Add a console implementation.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23351 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
François Revol
2008-01-10 20:54:55 +00:00
parent 3831b73445
commit c2b8af8b2b
2 changed files with 319 additions and 0 deletions
@@ -0,0 +1,295 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*
* Author:
* François Revol, [email protected].
*/
#include <SupportDefs.h>
#include <string.h>
#include "toscalls.h"
#include <util/kernel_cpp.h>
#include "Handle.h"
#include "console.h"
// TOS emulates a VT52
class ConsoleHandle : public Handle {
public:
ConsoleHandle();
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
size_t bufferSize);
virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
size_t bufferSize);
int16 f
};
class InputConsoleHandle : public ConsoleHandle {
public:
InputConsoleHandle();
virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
size_t bufferSize);
void PutChar(char c);
void PutChars(const char *buffer, int count);
char GetChar();
private:
enum { BUFFER_SIZE = 32 };
char fBuffer[BUFFER_SIZE];
int fStart;
int fCount;
};
static InputConsoleHandle sInput;
static ConsoleHandle sOutput;
FILE *stdin, *stdout, *stderr;
ConsoleHandle::ConsoleHandle()
: Handle()
{
}
ssize_t
ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer,
size_t bufferSize)
{
// don't seek in character devices
// not implemented (and not yet? needed)
return B_ERROR;
}
ssize_t
ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer,
size_t bufferSize)
{
const char *string = (const char *)buffer;
// be nice to our audience and replace single "\n" with "\r\n"
for (i = 0; i < bufferSize; i++) {
if (string[i] == '\n')
Bconout(fHandle, '\r');
Bconout(fHandle, string[i]);
}
return bufferSize;
}
// #pragma mark -
InputConsoleHandle::InputConsoleHandle()
: ConsoleHandle()
, fStart(0)
, fCount(0)
{
}
ssize_t
InputConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *_buffer,
size_t bufferSize)
{
char *buffer = (char*)_buffer;
// copy buffered bytes first
int bytesTotal = 0;
while (bufferSize > 0 && fCount > 0) {
*buffer++ = GetChar();
bytesTotal++;
bufferSize--;
}
// read from console
if (bufferSize > 0) {
ssize_t bytesRead = ConsoleHandle::ReadAt(NULL, 0, buffer, bufferSize);
if (bytesRead < 0)
return bytesRead;
bytesTotal += bytesRead;
}
return bytesTotal;
}
void
InputConsoleHandle::PutChar(char c)
{
if (fCount >= BUFFER_SIZE)
return;
int pos = (fStart + fCount) % BUFFER_SIZE;
fBuffer[pos] = c;
fCount++;
}
void
InputConsoleHandle::PutChars(const char *buffer, int count)
{
for (int i = 0; i < count; i++)
PutChar(buffer[i]);
}
char
InputConsoleHandle::GetChar()
{
if (fCount == 0)
return 0;
fCount--;
char c = fBuffer[fStart];
fStart = (fStart + 1) % BUFFER_SIZE;
return c;
}
// #pragma mark -
status_t
console_init(void)
{
sInput.SetHandle(DEV_CONSOLE);
sOutput.SetHandle(DEV_CONSOLE);
// now that we're initialized, enable stdio functionality
stdin = (FILE *)&sInput;
stdout = stderr = (FILE *)&sOutput;
return B_OK;
}
// #pragma mark -
void
console_clear_screen(void)
{
stdin->WriteAt(NULL, 0LL, "\033E", 2);
}
int32
console_width(void)
{
int columnCount = 80; //XXX: check video mode
return columnCount;
}
int32
console_height(void)
{
int lineCount = 25; //XXX: check video mode
return lineCount;
}
void
console_set_cursor(int32 x, int32 y)
{
char buff[] = "\033Y ";
buff[3] += (char)x;
buff[2] += (char)y;
stdin->WriteAt(NULL, 0LL, buff, 4);
}
static int
translate_color(int32 color)
{
/*
r g b
0: 0 0 0 // black
1: 0 0 aa // dark blue
2: 0 aa 0 // dark green
3: 0 aa aa // cyan
4: aa 0 0 // dark red
5: aa 0 aa // purple
6: aa 55 0 // brown
7: aa aa aa // light gray
8: 55 55 55 // dark gray
9: 55 55 ff // light blue
a: 55 ff 55 // light green
b: 55 ff ff // light cyan
c: ff 55 55 // light red
d: ff 55 ff // magenta
e: ff ff 55 // yellow
f: ff ff ff // white
*/
if (color >= 0 && color < 16)
return color;
return 0;
}
void
console_set_color(int32 foreground, int32 background)
{
// Note: Toggling the cursor doesn't seem to help. We still get cursor
// artifacts.
of_interpret("toggle-cursor"
" to foreground-color"
" to background-color"
" toggle-cursor",
2, 0, translate_color(foreground), translate_color(background));
}
int
console_wait_for_key(void)
{
// wait for a key
char buffer[3];
ssize_t bytesRead;
do {
bytesRead = sInput.ReadAt(NULL, 0, buffer, 3);
if (bytesRead < 0)
return 0;
} while (bytesRead == 0);
// translate the ESC sequences for cursor keys
if (bytesRead == 3 && buffer[0] == 27 && buffer [1] == 91) {
switch (buffer[2]) {
case 65:
return TEXT_CONSOLE_KEY_UP;
case 66:
return TEXT_CONSOLE_KEY_DOWN;
case 67:
return TEXT_CONSOLE_KEY_RIGHT;
case 68:
return TEXT_CONSOLE_KEY_LEFT;
// TODO: Translate the codes for the following keys. Unfortunately my OF just
// returns a '\0' character. :-/
// TEXT_CONSOLE_KEY_PAGE_UP,
// TEXT_CONSOLE_KEY_PAGE_DOWN,
// TEXT_CONSOLE_KEY_HOME,
// TEXT_CONSOLE_KEY_END,
default:
break;
}
}
// put back unread chars
if (bytesRead > 1)
sInput.PutChars(buffer + 1, bytesRead - 1);
return buffer[0];
}
@@ -0,0 +1,24 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*
* Author:
* François Revol, [email protected].
*/
#ifndef CONSOLE_H
#define CONSOLE_H
#include <boot/platform/generic/text_console.h>
#ifdef __cplusplus
extern "C" {
#endif
extern status_t console_init(void);
#ifdef __cplusplus
}
#endif
#endif /* CONSOLE_H */