* Copyright 2004-2005, Axel DΓΆrfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "console.h"
#include "keyboard.h"
#include "video.h"
#include <SupportDefs.h>
#include <util/kernel_cpp.h>
#include <boot/stage2.h>
#include <string.h>
class Console : public ConsoleNode {
public:
Console();
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);
virtual void ClearScreen();
virtual int32 Width();
virtual int32 Height();
virtual void SetCursor(int32 x, int32 y);
virtual void SetCursorVisible(bool visible);
virtual void SetColors(int32 foreground, int32 background);
};
static uint16 *sScreenBase = (uint16 *)0xb8000;
static uint32 sScreenWidth = 80;
static uint32 sScreenHeight = 25;
static uint32 sScreenOffset = 0;
static uint16 sColor = 0x0f00;
extern ConsoleNode* gConsoleNode;
static Console sConsole;
FILE *stdin, *stdout, *stderr;
static void
scroll_up()
{
memcpy(sScreenBase, sScreenBase + sScreenWidth,
sScreenWidth * sScreenHeight * 2 - sScreenWidth * 2);
sScreenOffset = (sScreenHeight - 1) * sScreenWidth;
for (uint32 i = 0; i < sScreenWidth; i++)
sScreenBase[sScreenOffset + i] = sColor | ' ';
}
Console::Console()
: ConsoleNode()
{
}
ssize_t
Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
{
return B_ERROR;
}
ssize_t
Console::WriteAt(void *cookie, off_t , const void *buffer, size_t bufferSize)
{
const char *string = (const char *)buffer;
if (gKernelArgs.frame_buffer.enabled)
return bufferSize;
for (uint32 i = 0; i < bufferSize; i++) {
if (string[0] == '\n')
sScreenOffset += sScreenWidth - (sScreenOffset % sScreenWidth);
else
sScreenBase[sScreenOffset++] = sColor | string[0];
if (sScreenOffset >= sScreenWidth * sScreenHeight)
scroll_up();
string++;
}
return bufferSize;
}
void
Console::ClearScreen()
{
if (gKernelArgs.frame_buffer.enabled)
return;
for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++)
sScreenBase[i] = sColor;
sScreenOffset = 0;
}
int32
Console::Width()
{
return sScreenWidth;
}
int32
Console::Height()
{
return sScreenHeight;
}
void
Console::SetCursor(int32 x, int32 y)
{
if (y >= (int32)sScreenHeight)
y = sScreenHeight - 1;
else if (y < 0)
y = 0;
if (x >= (int32)sScreenWidth)
x = sScreenWidth - 1;
else if (x < 0)
x = 0;
sScreenOffset = x + y * sScreenWidth;
video_move_text_cursor(x, y);
}
void
Console::SetCursorVisible(bool visible)
{
if (visible)
video_show_text_cursor();
else
video_hide_text_cursor();
}
void
Console::SetColors(int32 foreground, int32 background)
{
sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8;
}
int
console_wait_for_key(void)
{
union key key = wait_for_key();
if (key.code.ascii == 0) {
switch (key.code.bios) {
case BIOS_KEY_UP:
return TEXT_CONSOLE_KEY_UP;
case BIOS_KEY_DOWN:
return TEXT_CONSOLE_KEY_DOWN;
case BIOS_KEY_LEFT:
return TEXT_CONSOLE_KEY_LEFT;
case BIOS_KEY_RIGHT:
return TEXT_CONSOLE_KEY_RIGHT;
case BIOS_KEY_PAGE_UP:
return TEXT_CONSOLE_KEY_PAGE_UP;
case BIOS_KEY_PAGE_DOWN:
return TEXT_CONSOLE_KEY_PAGE_DOWN;
case BIOS_KEY_HOME:
return TEXT_CONSOLE_KEY_HOME;
case BIOS_KEY_END:
return TEXT_CONSOLE_KEY_END;
default:
return 0;
}
} else
return key.code.ascii;
}
status_t
console_init(void)
{
gConsoleNode = &sConsole;
console_clear_screen();
stdin = (FILE *)&sConsole;
stdout = stderr = (FILE *)&sConsole;
return B_OK;
}