diff --git a/headers/private/kernel/boot/platform.h b/headers/private/kernel/boot/platform.h index 013394266a..3071c50316 100644 --- a/headers/private/kernel/boot/platform.h +++ b/headers/private/kernel/boot/platform.h @@ -68,6 +68,8 @@ class MenuItem; extern void platform_add_menus(Menu *menu); extern void platform_update_menu_item(Menu *menu, MenuItem *item); extern void platform_run_menu(Menu *menu); +extern size_t platform_get_user_input_text(Menu *menu, const char *prompt, + char *buffer, size_t bufferSize); #endif diff --git a/headers/private/kernel/boot/platform/generic/text_console.h b/headers/private/kernel/boot/platform/generic/text_console.h index 23dc554b24..82d8720a68 100644 --- a/headers/private/kernel/boot/platform/generic/text_console.h +++ b/headers/private/kernel/boot/platform/generic/text_console.h @@ -36,6 +36,7 @@ enum { // ASCII TEXT_CONSOLE_NO_KEY = '\0', TEXT_CONSOLE_KEY_RETURN = '\r', + TEXT_CONSOLE_KEY_BACKSPACE = '\b', TEXT_CONSOLE_KEY_ESCAPE = 0x1b, TEXT_CONSOLE_KEY_SPACE = ' ', @@ -64,6 +65,8 @@ extern void console_clear_screen(void); extern int32 console_width(void); extern int32 console_height(void); extern void console_set_cursor(int32 x, int32 y); +extern void console_show_cursor(void); +extern void console_hide_cursor(void); extern void console_set_color(int32 foreground, int32 background); extern int console_wait_for_key(void); diff --git a/headers/private/kernel/boot/platform/generic/text_menu.h b/headers/private/kernel/boot/platform/generic/text_menu.h index 2dc2e47875..437a2a41fd 100644 --- a/headers/private/kernel/boot/platform/generic/text_menu.h +++ b/headers/private/kernel/boot/platform/generic/text_menu.h @@ -1,15 +1,18 @@ -/* - * Copyright 2005, Ingo Weinhold . - * All rights reserved. Distributed under the terms of the MIT License. - */ - -#ifndef GENERIC_TEXT_MENU_H -#define GENERIC_TEXT_MENU_H - -class Menu; -class MenuItem; - -void platform_generic_update_text_menu_item(Menu *menu, MenuItem *item); -void platform_generic_run_text_menu(Menu *menu); - -#endif /* GENERIC_TEXT_MENU_H */ +/* + * Copyright 2011, Rene Gollent . + * Copyright 2005, Ingo Weinhold . + * All rights reserved. Distributed under the terms of the MIT License. + */ + +#ifndef GENERIC_TEXT_MENU_H +#define GENERIC_TEXT_MENU_H + +class Menu; +class MenuItem; + +void platform_generic_update_text_menu_item(Menu* menu, MenuItem* item); +void platform_generic_run_text_menu(Menu* menu); +size_t platform_generic_get_user_input_text(Menu* menu, const char* prompt, + char* buffer, size_t bufferSize); + +#endif /* GENERIC_TEXT_MENU_H */ diff --git a/src/system/boot/loader/menu.cpp b/src/system/boot/loader/menu.cpp index e878f0ed69..b150e890ab 100644 --- a/src/system/boot/loader/menu.cpp +++ b/src/system/boot/loader/menu.cpp @@ -1,5 +1,6 @@ /* * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2011, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -39,6 +40,9 @@ #endif +static char sSafeModeOptionsBuffer[2048]; + + MenuItem::MenuItem(const char *label, Menu *subMenu) : fLabel(strdup(label)), @@ -516,6 +520,26 @@ debug_menu_display_syslog(Menu* menu, MenuItem* item) } +static bool +debug_menu_add_advanced_option(Menu* menu, MenuItem* item) +{ + char buffer[128]; + const char* prompt = "Option: "; + + size_t size = platform_get_user_input_text(menu, prompt, buffer, + sizeof(buffer) - 1); + + if (size > 0) { + buffer[size] = '\n'; + uint32 pos = strlen(sSafeModeOptionsBuffer); + if (pos + size < sizeof(sSafeModeOptionsBuffer)) + strlcat(sSafeModeOptionsBuffer, buffer, + sizeof(sSafeModeOptionsBuffer)); + } + + return true; +} + static status_t save_syslog_to_volume(Directory* directory) { @@ -829,6 +853,14 @@ add_debug_menu() "disk. Currently only FAT32 volumes are supported."); } + menu->AddSeparatorItem(); + menu->AddItem(item = new(nothrow) MenuItem( + "Add advanced debug option")); + item->SetType(MENU_ITEM_NO_CHOICE); + item->SetTarget(&debug_menu_add_advanced_option); + item->SetHelpText( + "Allows advanced debugging options to be entered directly."); + menu->AddSeparatorItem(); menu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); @@ -837,9 +869,10 @@ add_debug_menu() static void -apply_safe_mode_options(Menu* menu, char *buffer, size_t bufferSize) +apply_safe_mode_options(Menu* menu) { - int32 pos = strlen(buffer); + int32 pos = strlen(sSafeModeOptionsBuffer); + size_t bufferSize = sizeof(sSafeModeOptionsBuffer); MenuItemIterator iterator = menu->ItemIterator(); while (MenuItem* item = iterator.Next()) { @@ -847,8 +880,8 @@ apply_safe_mode_options(Menu* menu, char *buffer, size_t bufferSize) || item->Data() == NULL || (uint32)pos >= bufferSize) continue; - size_t totalBytes = snprintf(buffer + pos, bufferSize - pos, - "%s true\n", (const char*)item->Data()); + size_t totalBytes = snprintf(sSafeModeOptionsBuffer + pos, + bufferSize - pos, "%s true\n", (const char*)item->Data()); pos += std::min(totalBytes, bufferSize - pos - 1); } } @@ -872,6 +905,8 @@ user_menu(Directory** _bootVolume) TRACE(("user_menu: enter\n")); + memset(sSafeModeOptionsBuffer, 0, sizeof(sSafeModeOptionsBuffer)); + // Add boot volume menu->AddItem(item = new(std::nothrow) MenuItem("Select boot volume", add_boot_volume_menu(*_bootVolume))); @@ -906,13 +941,9 @@ user_menu(Directory** _bootVolume) if (item->Data() != NULL) *_bootVolume = (Directory*)item->Data(); - char buffer[2048]; - - memset(buffer, 0, sizeof(buffer)); - - apply_safe_mode_options(safeModeMenu, buffer, sizeof(buffer)); - apply_safe_mode_options(debugMenu, buffer, sizeof(buffer)); - add_safe_mode_settings(buffer); + apply_safe_mode_options(safeModeMenu); + apply_safe_mode_options(debugMenu); + add_safe_mode_settings(sSafeModeOptionsBuffer); delete menu; diff --git a/src/system/boot/platform/bios_ia32/console.cpp b/src/system/boot/platform/bios_ia32/console.cpp index 25a136fea8..8a41d373c3 100644 --- a/src/system/boot/platform/bios_ia32/console.cpp +++ b/src/system/boot/platform/bios_ia32/console.cpp @@ -1,11 +1,13 @@ /* * 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 #include @@ -116,7 +118,7 @@ console_height(void) } -void +void console_set_cursor(int32 x, int32 y) { if (y >= (int32)sScreenHeight) @@ -129,10 +131,25 @@ console_set_cursor(int32 x, int32 y) x = 0; sScreenOffset = x + y * sScreenWidth; + video_move_text_cursor(x, y); } -void +void +console_show_cursor(void) +{ + video_show_text_cursor(); +} + + +void +console_hide_cursor(void) +{ + video_hide_text_cursor(); +} + + +void console_set_color(int32 foreground, int32 background) { sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8; @@ -150,6 +167,10 @@ console_wait_for_key(void) 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: diff --git a/src/system/boot/platform/bios_ia32/menu.cpp b/src/system/boot/platform/bios_ia32/menu.cpp index 396dd65b2d..9fe9e1df59 100644 --- a/src/system/boot/platform/bios_ia32/menu.cpp +++ b/src/system/boot/platform/bios_ia32/menu.cpp @@ -1,5 +1,6 @@ /* * Copyright 2004-2010, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2011, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -111,3 +112,11 @@ platform_run_menu(Menu* menu) platform_generic_run_text_menu(menu); } + +size_t +platform_get_user_input_text(Menu* menu, const char* prompt, char *buffer, + size_t bufferSize) +{ + return platform_generic_get_user_input_text(menu, prompt, buffer, + bufferSize); +} diff --git a/src/system/boot/platform/bios_ia32/video.cpp b/src/system/boot/platform/bios_ia32/video.cpp index a05c85664a..8ca0c26144 100644 --- a/src/system/boot/platform/bios_ia32/video.cpp +++ b/src/system/boot/platform/bios_ia32/video.cpp @@ -2,6 +2,7 @@ * Copyright 2004-2009, Axel Dörfler, axeld@pinc-software.de. * Copyright 2008, Stephan Aßmus * Copyright 2008, Philippe Saint-Pierre + * Copyright 2011, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -696,7 +697,35 @@ set_text_mode(void) regs.eax = 0x0003; call_bios(0x10, ®s); - // turns off text cursor + video_hide_text_cursor(); +} + + +void +video_move_text_cursor(int x, int y) +{ + bios_regs regs; + regs.eax = 0x0200; + regs.ebx = 0; + regs.edx = (y << 8) | x; + call_bios(0x10, ®s); +} + + +void +video_show_text_cursor(void) +{ + bios_regs regs; + regs.eax = 0x0100; + regs.ecx = 0x0607; + call_bios(0x10, ®s); +} + + +void +video_hide_text_cursor(void) +{ + bios_regs regs; regs.eax = 0x0100; regs.ecx = 0x2000; call_bios(0x10, ®s); diff --git a/src/system/boot/platform/bios_ia32/video.h b/src/system/boot/platform/bios_ia32/video.h index 37cd88782c..7482abcd58 100644 --- a/src/system/boot/platform/bios_ia32/video.h +++ b/src/system/boot/platform/bios_ia32/video.h @@ -1,7 +1,9 @@ /* -** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. -** Distributed under the terms of the Haiku License. -*/ + * Copyright 2004, 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 Haiku License. + */ #ifndef VIDEO_H #define VIDEO_H @@ -15,4 +17,8 @@ class MenuItem; bool video_mode_hook(Menu *menu, MenuItem *item); Menu *video_mode_menu(); +void video_move_text_cursor(int x, int y); +void video_show_text_cursor(void); +void video_hide_text_cursor(void); + #endif /* VIDEO_H */ diff --git a/src/system/boot/platform/generic/text_menu.cpp b/src/system/boot/platform/generic/text_menu.cpp index 77cf82be83..5181792ad0 100644 --- a/src/system/boot/platform/generic/text_menu.cpp +++ b/src/system/boot/platform/generic/text_menu.cpp @@ -1,5 +1,6 @@ /* * Copyright 2004-2010, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2011, Rene Gollent, rene@gollent.com. * Distributed under the terms of the MIT License. */ @@ -57,13 +58,15 @@ print_spacing(int32 count) static void -print_centered(int32 line, const char *text) +print_centered(int32 line, const char *text, bool resetPosition = true) { console_set_cursor(console_width() / 2 - strlen(text) / 2, line); printf("%s", text); - console_set_cursor(0, 0); - // this avoids unwanted line feeds + if (resetPosition) { + console_set_cursor(0, 0); + // this avoids unwanted line feeds + } } @@ -508,3 +511,75 @@ platform_generic_run_text_menu(Menu *menu) // platform_switch_to_logo(); } + +size_t +platform_generic_get_user_input_text(Menu* menu, const char* prompt, + char* buffer, size_t bufferSize) +{ + size_t pos = 0; + + memset(buffer, 0, bufferSize); + + int32 promptLength = strlen(prompt); + int32 line = console_height() / 2; + int32 x = kOffsetX + 1; + console_set_cursor(0, line); + console_set_color(kSelectedItemColor, kSelectedItemBackgroundColor); + print_spacing(console_width()); + console_set_color(kTextColor, kBackgroundColor); + console_set_cursor(0, line); + print_spacing(x); + printf(prompt); + x += promptLength; + console_set_color(kSelectedItemColor, kSelectedItemBackgroundColor); + console_show_cursor(); + console_set_cursor(x, line); + + int key = 0; + size_t dataLength = 0; + while (true) { + key = console_wait_for_key(); + if (key == TEXT_CONSOLE_KEY_RETURN || key == TEXT_CONSOLE_KEY_ESCAPE) + break; + else if (key >= TEXT_CONSOLE_CURSOR_KEYS_START + && key < TEXT_CONSOLE_CURSOR_KEYS_END) + { + switch (key) { + case TEXT_CONSOLE_KEY_LEFT: + if (pos != 0) + pos--; + break; + case TEXT_CONSOLE_KEY_RIGHT: + if (pos < dataLength) + pos++; + break; + default: + break; + } + } else if (key == TEXT_CONSOLE_KEY_BACKSPACE) { + if (pos != 0) { + pos--; + dataLength--; + buffer[pos] = '\0'; + console_set_cursor(x + pos, line); + printf(" "); + } + // only accept printable ascii characters + } else if (key > 32 || key == TEXT_CONSOLE_KEY_SPACE) { + // don't allow the input to exceed either the buffer size + // or screen width + // TODO: support scrolling the line to allow larger inputs + if (x < (console_width() - 1) && pos < (bufferSize - 1)) { + buffer[pos++] = key; + printf("%c", key); + dataLength++; + } + } + console_set_cursor(x + pos, line); + } + + console_hide_cursor(); + draw_menu(menu); + + return key == TEXT_CONSOLE_KEY_RETURN ? pos : 0; +}