diff --git a/src/system/boot/platform/openfirmware/Jamfile b/src/system/boot/platform/openfirmware/Jamfile index 14261dc2a3..4cfba1d26e 100644 --- a/src/system/boot/platform/openfirmware/Jamfile +++ b/src/system/boot/platform/openfirmware/Jamfile @@ -3,21 +3,24 @@ SubDir HAIKU_TOP src system boot platform openfirmware ; SubDirC++Flags -fno-rtti ; KernelMergeObject boot_platform_openfirmware.o : - <$(SOURCE_GRIST)>start.c - <$(SOURCE_GRIST)>openfirmware.c - <$(SOURCE_GRIST)>debug.c - <$(SOURCE_GRIST)>mmu.cpp - <$(SOURCE_GRIST)>Handle.cpp - <$(SOURCE_GRIST)>devices.cpp - <$(SOURCE_GRIST)>console.cpp - <$(SOURCE_GRIST)>heap.cpp - <$(SOURCE_GRIST)>video.cpp - <$(SOURCE_GRIST)>menu.cpp + console.cpp + debug.c + devices.cpp + Handle.cpp + heap.cpp + menu.cpp + mmu.cpp + openfirmware.c + start.c + video.cpp + + # generic + text_menu.cpp : : boot_platform_openfirmware_$(TARGET_ARCH).a - ; +; -SEARCH on [ FGristFiles crt0.S ] - = [ FDirName $(HAIKU_TOP) src system boot arch $(TARGET_ARCH) ] ; +SEARCH on [ FGristFiles text_menu.cpp ] + = [ FDirName $(HAIKU_TOP) src system boot platform generic ] ; SubInclude HAIKU_TOP src system boot platform openfirmware arch ; diff --git a/src/system/boot/platform/openfirmware/console.cpp b/src/system/boot/platform/openfirmware/console.cpp index 8bd861dc01..2a2026b6f8 100644 --- a/src/system/boot/platform/openfirmware/console.cpp +++ b/src/system/boot/platform/openfirmware/console.cpp @@ -17,12 +17,36 @@ 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); + 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); }; -static ConsoleHandle sInput, sOutput; +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; +static bool sCursorVisible = true; ConsoleHandle::ConsoleHandle() @@ -32,7 +56,8 @@ ConsoleHandle::ConsoleHandle() ssize_t -ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer, size_t bufferSize) +ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer, + size_t bufferSize) { // don't seek in character devices return of_read(fHandle, buffer, bufferSize); @@ -40,7 +65,8 @@ ConsoleHandle::ReadAt(void */*cookie*/, off_t /*pos*/, void *buffer, size_t buff ssize_t -ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer, size_t bufferSize) +ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer, + size_t bufferSize) { const char *string = (const char *)buffer; @@ -81,6 +107,76 @@ ConsoleHandle::WriteAt(void */*cookie*/, off_t /*pos*/, const void *buffer, size // #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) { @@ -101,3 +197,130 @@ console_init(void) } +// #pragma mark - + + +void +console_clear_screen(void) +{ + of_interpret("erase-screen", 0, 0); +} + + +int32 +console_width(void) +{ + int columnCount; + if (of_interpret("#columns", 0, 1, &columnCount) == OF_FAILED) + return 0; + return columnCount; +} + + +int32 +console_height(void) +{ + int lineCount; + if (of_interpret("#lines", 0, 1, &lineCount) == OF_FAILED) + return 0; + return lineCount; +} + + +void +console_set_cursor(int32 x, int32 y) +{ + // Note: We toggle the cursor temporarily to prevent a cursor artifact at + // at the old location. + of_interpret("toggle-cursor" + " to line#" + " to column#" + " toggle-cursor", + 2, 0, y, x); + +} + + +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]; +} + diff --git a/src/system/boot/platform/openfirmware/console.h b/src/system/boot/platform/openfirmware/console.h index 42599f732b..487542c742 100644 --- a/src/system/boot/platform/openfirmware/console.h +++ b/src/system/boot/platform/openfirmware/console.h @@ -5,12 +5,7 @@ #ifndef CONSOLE_H #define CONSOLE_H - -#include -#include - -#include "Handle.h" - +#include #ifdef __cplusplus extern "C" { @@ -18,10 +13,6 @@ extern "C" { extern status_t console_init(void); -extern status_t set_cursor_pos(FILE *, int x, int y); -extern status_t set_foreground_color(FILE *, int c); -extern status_t set_background_color(FILE *, int c); - #ifdef __cplusplus } #endif diff --git a/src/system/boot/platform/openfirmware/menu.cpp b/src/system/boot/platform/openfirmware/menu.cpp index bee561a6d4..c0b06e7c2a 100644 --- a/src/system/boot/platform/openfirmware/menu.cpp +++ b/src/system/boot/platform/openfirmware/menu.cpp @@ -6,6 +6,7 @@ #include #include +#include void @@ -27,16 +28,13 @@ platform_add_menus(Menu *menu) void platform_update_menu_item(Menu *menu, MenuItem *item) { - if (menu->IsHidden()) - return; - - // ToDo: implement me! + platform_generic_update_text_menu_item(menu, item); } void platform_run_menu(Menu *menu) { - // ToDo: implement me! + platform_generic_run_text_menu(menu); }