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