xref: /haiku/src/system/boot/platform/atari_m68k/console.cpp (revision 239222b2369c39dc52df52b0a7cdd6cc0a91bc92)
1 /*
2  * Copyright 2007, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT license.
4  *
5  * Author:
6  *		François Revol, revol@free.fr.
7  */
8 
9 #include <SupportDefs.h>
10 #include <string.h>
11 #include "toscalls.h"
12 #include <util/kernel_cpp.h>
13 
14 #include "Handle.h"
15 #include "console.h"
16 #include "keyboard.h"
17 
18 
19 // TOS emulates a VT52
20 
21 class ConsoleHandle : public CharHandle {
22 	public:
23 		ConsoleHandle();
24 
25 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
26 			size_t bufferSize);
27 		virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
28 			size_t bufferSize);
29 };
30 
31 class InputConsoleHandle : public ConsoleHandle {
32 	public:
33 		InputConsoleHandle();
34 
35 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
36 			size_t bufferSize);
37 
38 		void PutChar(char c);
39 		void PutChars(const char *buffer, int count);
40 		char GetChar();
41 
42 	private:
43 		enum { BUFFER_SIZE = 32 };
44 
45 		char	fBuffer[BUFFER_SIZE];
46 		int		fStart;
47 		int		fCount;
48 };
49 
50 
51 static InputConsoleHandle sInput;
52 static ConsoleHandle sOutput;
53 FILE *stdin, *stdout, *stderr;
54 
55 
56 ConsoleHandle::ConsoleHandle()
57 	: CharHandle()
58 {
59 }
60 
61 
62 ssize_t
63 ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer,
64 	size_t bufferSize)
65 {
66 	// don't seek in character devices
67 	// not implemented (and not yet? needed)
68 	return B_ERROR;
69 }
70 
71 
72 ssize_t
73 ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
74 	size_t bufferSize)
75 {
76 	const char *string = (const char *)buffer;
77 	size_t i;
78 
79 	// be nice to our audience and replace single "\n" with "\r\n"
80 
81 	for (i = 0; i < bufferSize; i++) {
82 		if (string[i] == '\0')
83 			break;
84 		if (string[i] == '\n')
85 			Bconout(fHandle, '\r');
86 		Bconout(fHandle, string[i]);
87 	}
88 
89 	return bufferSize;
90 }
91 
92 
93 //	#pragma mark -
94 
95 
96 InputConsoleHandle::InputConsoleHandle()
97 	: ConsoleHandle()
98 	, fStart(0)
99 	, fCount(0)
100 {
101 }
102 
103 
104 ssize_t
105 InputConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
106 	size_t bufferSize)
107 {
108 	char *buffer = (char*)_buffer;
109 
110 	// copy buffered bytes first
111 	int bytesTotal = 0;
112 	while (bufferSize > 0 && fCount > 0) {
113 		*buffer++ = GetChar();
114 		bytesTotal++;
115 		bufferSize--;
116 	}
117 
118 	// read from console
119 	if (bufferSize > 0) {
120 		ssize_t bytesRead = ConsoleHandle::ReadAt(NULL, 0, buffer, bufferSize);
121 		if (bytesRead < 0)
122 			return bytesRead;
123 		bytesTotal += bytesRead;
124 	}
125 
126 	return bytesTotal;
127 }
128 
129 
130 void
131 InputConsoleHandle::PutChar(char c)
132 {
133 	if (fCount >= BUFFER_SIZE)
134 		return;
135 
136 	int pos = (fStart + fCount) % BUFFER_SIZE;
137 	fBuffer[pos] = c;
138 	fCount++;
139 }
140 
141 
142 void
143 InputConsoleHandle::PutChars(const char *buffer, int count)
144 {
145 	for (int i = 0; i < count; i++)
146 		PutChar(buffer[i]);
147 }
148 
149 
150 char
151 InputConsoleHandle::GetChar()
152 {
153 	if (fCount == 0)
154 		return 0;
155 
156 	fCount--;
157 	char c = fBuffer[fStart];
158 	fStart = (fStart + 1) % BUFFER_SIZE;
159 	return c;
160 }
161 
162 
163 //	#pragma mark -
164 
165 
166 status_t
167 console_init(void)
168 {
169 	sInput.SetHandle(DEV_CONSOLE);
170 	sOutput.SetHandle(DEV_CONSOLE);
171 
172 	// now that we're initialized, enable stdio functionality
173 	stdin = (FILE *)&sInput;
174 	stdout = stderr = (FILE *)&sOutput;
175 
176 	return B_OK;
177 }
178 
179 
180 // #pragma mark -
181 
182 
183 void
184 console_clear_screen(void)
185 {
186 	sInput.WriteAt(NULL, 0LL, "\033E", 2);
187 }
188 
189 
190 int32
191 console_width(void)
192 {
193 	int columnCount = 80; //XXX: check video mode
194 	return columnCount;
195 }
196 
197 
198 int32
199 console_height(void)
200 {
201 	int lineCount = 25; //XXX: check video mode
202 	return lineCount;
203 }
204 
205 
206 void
207 console_set_cursor(int32 x, int32 y)
208 {
209 	char buff[] = "\033Y  ";
210 	x = MIN(79,MAX(0,x));
211 	y = MIN(24,MAX(0,y));
212 	buff[3] += (char)x;
213 	buff[2] += (char)y;
214 	sInput.WriteAt(NULL, 0LL, buff, 4);
215 }
216 
217 
218 static int
219 translate_color(int32 color)
220 {
221 	/*
222 			r	g	b
223 		0:	0	0	0		// black
224 		1:	0	0	aa		// dark blue
225 		2:	0	aa	0		// dark green
226 		3:	0	aa	aa		// cyan
227 		4:	aa	0	0		// dark red
228 		5:	aa	0	aa		// purple
229 		6:	aa	55	0		// brown
230 		7:	aa	aa	aa		// light gray
231 		8:	55	55	55		// dark gray
232 		9:	55	55	ff		// light blue
233 		a:	55	ff	55		// light green
234 		b:	55	ff	ff		// light cyan
235 		c:	ff	55	55		// light red
236 		d:	ff	55	ff		// magenta
237 		e:	ff	ff	55		// yellow
238 		f:	ff	ff	ff		// white
239 	*/
240 	// cf. http://www.fortunecity.com/skyscraper/apple/308/html/chap4.htm
241 	static const char cmap[] = {
242 		15, 4, 2, 6, 1, 5, 3, 7,
243 		8, 12, 10, 14, 9, 13, 11, 0 };
244 
245 	if (color < 0 && color >= 16)
246 		return 0;
247 	return cmap[color];
248 	//return color;
249 }
250 
251 
252 void
253 console_set_color(int32 foreground, int32 background)
254 {
255 	char buff[] = "\033b \033c ";
256 	buff[2] += (char)translate_color(foreground);
257 	buff[5] += (char)translate_color(background);
258 	sInput.WriteAt(NULL, 0LL, buff, 6);
259 }
260 
261 
262 int
263 console_wait_for_key(void)
264 {
265 #if 0
266 	// XXX: do this way and remove keyboard.cpp ?
267 	// wait for a key
268 	char buffer[3];
269 	ssize_t bytesRead;
270 	do {
271 		bytesRead = sInput.ReadAt(NULL, 0, buffer, 3);
272 		if (bytesRead < 0)
273 			return 0;
274 	} while (bytesRead == 0);
275 #endif
276 	union key key = wait_for_key();
277 
278 	if (key.code.ascii == 0) {
279 		switch (key.code.bios) {
280 			case BIOS_KEY_UP:
281 				return TEXT_CONSOLE_KEY_UP;
282 			case BIOS_KEY_DOWN:
283 				return TEXT_CONSOLE_KEY_DOWN;
284 			case BIOS_KEY_PAGE_UP:
285 				return TEXT_CONSOLE_KEY_PAGE_UP;
286 			case BIOS_KEY_PAGE_DOWN:
287 				return TEXT_CONSOLE_KEY_PAGE_DOWN;
288 			case BIOS_KEY_HOME:
289 				return TEXT_CONSOLE_KEY_HOME;
290 			case BIOS_KEY_END:
291 				return TEXT_CONSOLE_KEY_END;
292 			default:
293 				return 0;
294 		}
295 	} else
296 		return key.code.ascii;
297 }
298 
299