xref: /haiku/src/system/boot/platform/atari_m68k/console.cpp (revision 020cbad9d40235a2c50a81a42d69912a5ff8fbc4)
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] == '\n')
83 			Bconout(fHandle, '\r');
84 		Bconout(fHandle, string[i]);
85 	}
86 
87 	return bufferSize;
88 }
89 
90 
91 //	#pragma mark -
92 
93 
94 InputConsoleHandle::InputConsoleHandle()
95 	: ConsoleHandle()
96 	, fStart(0)
97 	, fCount(0)
98 {
99 }
100 
101 
102 ssize_t
103 InputConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
104 	size_t bufferSize)
105 {
106 	char *buffer = (char*)_buffer;
107 
108 	// copy buffered bytes first
109 	int bytesTotal = 0;
110 	while (bufferSize > 0 && fCount > 0) {
111 		*buffer++ = GetChar();
112 		bytesTotal++;
113 		bufferSize--;
114 	}
115 
116 	// read from console
117 	if (bufferSize > 0) {
118 		ssize_t bytesRead = ConsoleHandle::ReadAt(NULL, 0, buffer, bufferSize);
119 		if (bytesRead < 0)
120 			return bytesRead;
121 		bytesTotal += bytesRead;
122 	}
123 
124 	return bytesTotal;
125 }
126 
127 
128 void
129 InputConsoleHandle::PutChar(char c)
130 {
131 	if (fCount >= BUFFER_SIZE)
132 		return;
133 
134 	int pos = (fStart + fCount) % BUFFER_SIZE;
135 	fBuffer[pos] = c;
136 	fCount++;
137 }
138 
139 
140 void
141 InputConsoleHandle::PutChars(const char *buffer, int count)
142 {
143 	for (int i = 0; i < count; i++)
144 		PutChar(buffer[i]);
145 }
146 
147 
148 char
149 InputConsoleHandle::GetChar()
150 {
151 	if (fCount == 0)
152 		return 0;
153 
154 	fCount--;
155 	char c = fBuffer[fStart];
156 	fStart = (fStart + 1) % BUFFER_SIZE;
157 	return c;
158 }
159 
160 
161 //	#pragma mark -
162 
163 
164 status_t
165 console_init(void)
166 {
167 	sInput.SetHandle(DEV_CONSOLE);
168 	sOutput.SetHandle(DEV_CONSOLE);
169 
170 	// now that we're initialized, enable stdio functionality
171 	stdin = (FILE *)&sInput;
172 	stdout = stderr = (FILE *)&sOutput;
173 
174 	return B_OK;
175 }
176 
177 
178 // #pragma mark -
179 
180 
181 void
182 console_clear_screen(void)
183 {
184 	sInput.WriteAt(NULL, 0LL, "\033E", 2);
185 }
186 
187 
188 int32
189 console_width(void)
190 {
191 	int columnCount = 80; //XXX: check video mode
192 	return columnCount;
193 }
194 
195 
196 int32
197 console_height(void)
198 {
199 	int lineCount = 25; //XXX: check video mode
200 	return lineCount;
201 }
202 
203 
204 void
205 console_set_cursor(int32 x, int32 y)
206 {
207 	char buff[] = "\033Y  ";
208 	x = MIN(79,MAX(0,x));
209 	y = MIN(24,MAX(0,y));
210 	buff[3] += (char)x;
211 	buff[2] += (char)y;
212 	sInput.WriteAt(NULL, 0LL, buff, 4);
213 }
214 
215 
216 static int
217 translate_color(int32 color)
218 {
219 	/*
220 			r	g	b
221 		0:	0	0	0		// black
222 		1:	0	0	aa		// dark blue
223 		2:	0	aa	0		// dark green
224 		3:	0	aa	aa		// cyan
225 		4:	aa	0	0		// dark red
226 		5:	aa	0	aa		// purple
227 		6:	aa	55	0		// brown
228 		7:	aa	aa	aa		// light gray
229 		8:	55	55	55		// dark gray
230 		9:	55	55	ff		// light blue
231 		a:	55	ff	55		// light green
232 		b:	55	ff	ff		// light cyan
233 		c:	ff	55	55		// light red
234 		d:	ff	55	ff		// magenta
235 		e:	ff	ff	55		// yellow
236 		f:	ff	ff	ff		// white
237 	*/
238 	if (color >= 0 && color < 16)
239 		return color;
240 	return 0;
241 }
242 
243 
244 void
245 console_set_color(int32 foreground, int32 background)
246 {
247 	char buff[] = "\033b \033c ";
248 	buff[2] = (char)translate_color(foreground);
249 	buff[5] = (char)translate_color(background);
250 	sInput.WriteAt(NULL, 0LL, buff, 6);
251 }
252 
253 
254 int
255 console_wait_for_key(void)
256 {
257 #if 0
258 	// XXX: do this way and remove keyboard.cpp ?
259 	// wait for a key
260 	char buffer[3];
261 	ssize_t bytesRead;
262 	do {
263 		bytesRead = sInput.ReadAt(NULL, 0, buffer, 3);
264 		if (bytesRead < 0)
265 			return 0;
266 	} while (bytesRead == 0);
267 #endif
268 	union key key = wait_for_key();
269 
270 	if (key.code.ascii == 0) {
271 		switch (key.code.bios) {
272 			case BIOS_KEY_UP:
273 				return TEXT_CONSOLE_KEY_UP;
274 			case BIOS_KEY_DOWN:
275 				return TEXT_CONSOLE_KEY_DOWN;
276 			case BIOS_KEY_PAGE_UP:
277 				return TEXT_CONSOLE_KEY_PAGE_UP;
278 			case BIOS_KEY_PAGE_DOWN:
279 				return TEXT_CONSOLE_KEY_PAGE_DOWN;
280 			case BIOS_KEY_HOME:
281 				return TEXT_CONSOLE_KEY_HOME;
282 			case BIOS_KEY_END:
283 				return TEXT_CONSOLE_KEY_END;
284 			default:
285 				return 0;
286 		}
287 	} else
288 		return key.code.ascii;
289 }
290 
291