1/*
2 * Copyright 2007-2010, 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 "nextrom.h"
12#include <util/kernel_cpp.h>
13
14#include "console.h"
15#include "keyboard.h"
16
17
18static bool sForceBW = false;	// force black & white for Milan
19
20// bootrom has more console info but we don't know the structure
21// so we just use getc & putc for now.
22
23class Console : public ConsoleNode {
24	public:
25		Console();
26
27		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
28			size_t bufferSize);
29		virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
30			size_t bufferSize);
31
32		virtual void	ClearScreen();
33		virtual int32	Width();
34		virtual int32	Height();
35		virtual void	SetCursor(int32 x, int32 y);
36		virtual void	SetCursorVisible(bool visible);
37		virtual void	SetColors(int32 foreground, int32 background);
38};
39
40
41extern ConsoleNode* gConsoleNode;
42static Console sConsole;
43FILE *stdin, *stdout, *stderr;
44
45
46Console::Console()
47	: ConsoleNode()
48{
49}
50
51
52ssize_t
53Console::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
54	size_t bufferSize)
55{
56	char *buffer = (char*)_buffer;
57	int c;
58	ssize_t bytesTotal = 0;
59
60	while (bytesTotal < bufferSize && (c = mg->mg_try_getc())) {
61		*buffer++ = (char)c;
62		bytesTotal++;
63	}
64
65	return bytesTotal;
66}
67
68
69ssize_t
70Console::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
71	size_t bufferSize)
72{
73	const char *string = (const char *)buffer;
74	size_t i;
75
76	for (i = 0; i < bufferSize; i++) {
77		if (string[i] == '\0')
78			break;
79		mg->mg_putc(string[i]);
80	}
81
82	return bufferSize;
83}
84
85
86void
87Console::ClearScreen()
88{
89	sConsole.WriteAt(NULL, 0LL, "\033E", 2);
90}
91
92
93int32
94Console::Width()
95{
96	int columnCount = 80; //XXX: check video mode
97	return columnCount;
98}
99
100
101int32
102Console::Height()
103{
104	int lineCount = 25; //XXX: check video mode
105	return lineCount;
106}
107
108
109void
110Console::SetCursor(int32 x, int32 y)
111{
112	char buff[] = "\033Y  ";
113	x = MIN(79,MAX(0,x));
114	y = MIN(24,MAX(0,y));
115	buff[3] += (char)x;
116	buff[2] += (char)y;
117	sConsole.WriteAt(NULL, 0LL, buff, 4);
118}
119
120
121static int
122translate_color(int32 color)
123{
124	/*
125			r	g	b
126		0:	0	0	0		// black
127		1:	0	0	aa		// dark blue
128		2:	0	aa	0		// dark green
129		3:	0	aa	aa		// cyan
130		4:	aa	0	0		// dark red
131		5:	aa	0	aa		// purple
132		6:	aa	55	0		// brown
133		7:	aa	aa	aa		// light gray
134		8:	55	55	55		// dark gray
135		9:	55	55	ff		// light blue
136		a:	55	ff	55		// light green
137		b:	55	ff	ff		// light cyan
138		c:	ff	55	55		// light red
139		d:	ff	55	ff		// magenta
140		e:	ff	ff	55		// yellow
141		f:	ff	ff	ff		// white
142	*/
143	// cf. http://www.fortunecity.com/skyscraper/apple/308/html/chap4.htm
144	static const char cmap[] = {
145		15, 4, 2, 6, 1, 5, 3, 7,
146		8, 12, 10, 14, 9, 13, 11, 0 };
147
148	if (color < 0 || color >= 16)
149		return 0;
150	return cmap[color];
151	//return color;
152}
153
154
155void
156Console::SetColors(int32 foreground, int32 background)
157{
158	char buff[] = "\033b \033c ";
159	if (sForceBW) {
160		if (background == 0) {
161			foreground = 15;
162		} else {
163			background = 15;
164			foreground = 0;
165		}
166	}
167	buff[2] += (char)translate_color(foreground);
168	buff[5] += (char)translate_color(background);
169	sConsole.WriteAt(NULL, 0LL, buff, 6);
170}
171
172
173void
174Console::SetCursorVisible(bool)
175{
176	// TODO?
177}
178
179
180//	#pragma mark -
181
182
183static void
184dump_colors()
185{
186	int bg, fg;
187	dprintf("colors:\n");
188	for (bg = 0; bg < 16; bg++) {
189		for (fg = 0; fg < 16; fg++) {
190			console_set_color(fg, bg);
191			dprintf("#");
192		}
193		console_set_color(0, 15);
194		dprintf("\n");
195	}
196}
197
198
199status_t
200console_init(void)
201{
202	gConsoleNode = &sConsole;
203
204	// now that we're initialized, enable stdio functionality
205	stdin = (FILE *)&sConsole;
206	stdout = stderr = (FILE *)&sConsole;
207
208	//dump_colors();
209
210	return B_OK;
211}
212
213
214// #pragma mark -
215
216
217int
218console_wait_for_key(void)
219{
220#if 0
221	// XXX: do this way and remove keyboard.cpp ?
222	// wait for a key
223	char buffer[3];
224	ssize_t bytesRead;
225	do {
226		bytesRead = sConsole.ReadAt(NULL, 0, buffer, 3);
227		if (bytesRead < 0)
228			return 0;
229	} while (bytesRead == 0);
230#endif
231	union key key = wait_for_key();
232
233	if (key.code.ascii == 0) {
234		switch (key.code.bios) {
235			case BIOS_KEY_UP:
236				return TEXT_CONSOLE_KEY_UP;
237			case BIOS_KEY_DOWN:
238				return TEXT_CONSOLE_KEY_DOWN;
239			case BIOS_KEY_PAGE_UP:
240				return TEXT_CONSOLE_KEY_PAGE_UP;
241			case BIOS_KEY_PAGE_DOWN:
242				return TEXT_CONSOLE_KEY_PAGE_DOWN;
243			case BIOS_KEY_HOME:
244				return TEXT_CONSOLE_KEY_HOME;
245			case BIOS_KEY_END:
246				return TEXT_CONSOLE_KEY_END;
247			default:
248				return 0;
249		}
250	} else
251		return key.code.ascii;
252}
253