From f4c623e170d42b4f55172d52426251ef55c1ee66 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Thu, 24 Dec 2009 00:37:11 +0100 Subject: [PATCH] Work on multi-out terminal --- commands/help.c | 26 ++- commands/sleep.c | 9 +- conf/any-emu.rmk | 2 +- conf/common.rmk | 2 +- include/grub/charset.h | 3 + include/grub/normal.h | 7 +- include/grub/parser.h | 1 + include/grub/reader.h | 52 +---- include/grub/term.h | 52 ++--- kern/main.c | 3 +- kern/misc.c | 13 +- kern/reader.c | 25 --- kern/rescue_reader.c | 36 ++-- kern/term.c | 209 +++++++----------- lib/charset.c | 64 ++++++ loader/i386/linux.c | 5 +- normal/cmdline.c | 477 +++++++++++++++++++++++------------------ normal/color.c | 47 ++-- normal/main.c | 112 ++++++---- normal/term.c | 128 +++++++++++ term/i386/pc/console.c | 4 - 21 files changed, 707 insertions(+), 570 deletions(-) create mode 100644 normal/term.c diff --git a/commands/help.c b/commands/help.c index c18ec6b83..4d16945af 100644 --- a/commands/help.c +++ b/commands/help.c @@ -37,18 +37,28 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)) { - char description[GRUB_TERM_WIDTH / 2]; + struct grub_term_output *cur; int desclen = grub_strlen (cmd->summary); + for (cur = grub_term_outputs; cur; cur = cur->next) + { + if (!(cur->flags & GRUB_TERM_ACTIVE)) + continue; + int width = grub_term_width(cur); + char description[width / 2]; /* Make a string with a length of GRUB_TERM_WIDTH / 2 - 1 filled with the description followed by spaces. */ - grub_memset (description, ' ', GRUB_TERM_WIDTH / 2 - 1); - description[GRUB_TERM_WIDTH / 2 - 1] = '\0'; - grub_memcpy (description, cmd->summary, - (desclen < GRUB_TERM_WIDTH / 2 - 1 - ? desclen : GRUB_TERM_WIDTH / 2 - 1)); - - grub_printf ("%s%s", description, (cnt++) % 2 ? "\n" : " "); + grub_memset (description, ' ', width / 2 - 1); + description[width / 2 - 1] = '\0'; + grub_memcpy (description, cmd->summary, + (desclen < width / 2 - 1 + ? desclen : width / 2 - 1)); + grub_puts_terminal (description, cur); + } + if ((cnt++) % 2) + grub_printf ("\n"); + else + grub_printf (" "); } return 0; } diff --git a/commands/sleep.c b/commands/sleep.c index 9207b60a7..aea7f2690 100644 --- a/commands/sleep.c +++ b/commands/sleep.c @@ -32,12 +32,12 @@ static const struct grub_arg_option options[] = {0, 0, 0, 0, 0, 0} }; -static grub_uint8_t x, y; +static grub_uint16_t *pos; static void do_print (int n) { - grub_gotoxy (x, y); + grub_term_restore_pos (pos); /* NOTE: Do not remove the trailing space characters. They are required to clear the line. */ grub_printf ("%d ", n); @@ -63,7 +63,6 @@ static grub_err_t grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) { struct grub_arg_list *state = cmd->state; - grub_uint16_t xy; int n; if (argc != 1) @@ -77,9 +76,7 @@ grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) return 0; } - xy = grub_getxy (); - x = xy >> 8; - y = xy & 0xff; + pos = grub_term_save_pos (); for (; n; n--) { diff --git a/conf/any-emu.rmk b/conf/any-emu.rmk index fb97de0a0..2c383f387 100644 --- a/conf/any-emu.rmk +++ b/conf/any-emu.rmk @@ -27,7 +27,7 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \ normal/handler.c normal/auth.c normal/autofs.c \ normal/completion.c normal/main.c normal/color.c \ normal/menu.c normal/menu_entry.c normal/menu_viewer.c \ - normal/menu_text.c \ + normal/menu_text.c normal/term.c \ script/main.c script/execute.c script/function.c \ script/lexer.c script/script.c grub_script.tab.c \ partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \ diff --git a/conf/common.rmk b/conf/common.rmk index 1ed30a404..02d57f0a3 100644 --- a/conf/common.rmk +++ b/conf/common.rmk @@ -543,7 +543,7 @@ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ normal/auth.c normal/autofs.c normal/handler.c \ normal/color.c normal/completion.c normal/datetime.c normal/menu.c \ normal/menu_entry.c normal/menu_text.c normal/menu_viewer.c \ - normal/misc.c + normal/misc.c normal/term.c normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_LDFLAGS = $(COMMON_LDFLAGS) diff --git a/include/grub/charset.h b/include/grub/charset.h index f85862f8b..daaa5c99f 100644 --- a/include/grub/charset.h +++ b/include/grub/charset.h @@ -109,4 +109,7 @@ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, return dest; } +/* Convert UCS-4 to UTF-8. */ +char *grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size); + #endif diff --git a/include/grub/normal.h b/include/grub/normal.h index e55553de5..d629338e6 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -20,6 +20,7 @@ #ifndef GRUB_NORMAL_HEADER #define GRUB_NORMAL_HEADER 1 +#include #include #include #include @@ -50,7 +51,7 @@ extern struct grub_menu_viewer grub_normal_text_menu_viewer; /* Defined in `main.c'. */ void grub_enter_normal_mode (const char *config); void grub_normal_execute (const char *config, int nested, int batch); -void grub_normal_init_page (void); +void grub_normal_init_page (struct grub_term_output *term); void grub_menu_init_page (int nested, int edit); grub_err_t grub_normal_add_menu_entry (int argc, const char **args, const char *sourcecode); @@ -58,8 +59,7 @@ char *grub_file_getline (grub_file_t file); void grub_cmdline_run (int nested); /* Defined in `cmdline.c'. */ -int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, - int echo_char, int readline, int history); +char *grub_cmdline_get (const char *prompt, unsigned max_len); grub_err_t grub_set_history (int newsize); /* Defined in `completion.c'. */ @@ -95,6 +95,7 @@ void read_command_list (void); /* Defined in `autofs.c'. */ void read_fs_list (void); +void grub_set_more (int onoff); #ifdef GRUB_UTIL void grub_normal_init (void); diff --git a/include/grub/parser.h b/include/grub/parser.h index 41f768bba..17f0c4303 100644 --- a/include/grub/parser.h +++ b/include/grub/parser.h @@ -22,6 +22,7 @@ #include #include +#include #include /* All the states for the command line. */ diff --git a/include/grub/reader.h b/include/grub/reader.h index c7e67bf5e..fd72a3252 100644 --- a/include/grub/reader.h +++ b/include/grub/reader.h @@ -20,60 +20,10 @@ #ifndef GRUB_READER_HEADER #define GRUB_READER_HEADER 1 -#include #include -#include typedef grub_err_t (*grub_reader_getline_t) (char **, int); -struct grub_reader -{ - /* The next reader. */ - struct grub_parser *next; - - /* The reader name. */ - const char *name; - - /* Initialize the reader. */ - grub_err_t (*init) (void); - - /* Clean up the reader. */ - grub_err_t (*fini) (void); - - grub_reader_getline_t read_line; -}; -typedef struct grub_reader *grub_reader_t; - -extern struct grub_handler_class EXPORT_VAR(grub_reader_class); - -grub_err_t EXPORT_FUNC(grub_reader_loop) (grub_reader_getline_t getline); - -static inline void -grub_reader_register (const char *name __attribute__ ((unused)), - grub_reader_t reader) -{ - grub_handler_register (&grub_reader_class, GRUB_AS_HANDLER (reader)); -} - -static inline void -grub_reader_unregister (grub_reader_t reader) -{ - grub_handler_unregister (&grub_reader_class, GRUB_AS_HANDLER (reader)); -} - -static inline grub_reader_t -grub_reader_get_current (void) -{ - return (grub_reader_t) grub_reader_class.cur_handler; -} - -static inline grub_err_t -grub_reader_set_current (grub_reader_t reader) -{ - return grub_handler_set_current (&grub_reader_class, - GRUB_AS_HANDLER (reader)); -} - -void grub_register_rescue_reader (void); +void grub_rescue_run (void); #endif /* ! GRUB_READER_HEADER */ diff --git a/include/grub/term.h b/include/grub/term.h index 316d75390..39a10ed71 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -68,6 +68,8 @@ grub_term_color_state; #define GRUB_TERM_NO_EDIT (1 << 1) /* Set when the terminal cannot do fancy things. */ #define GRUB_TERM_DUMB (1 << 2) +/* Terminal is used as general output. */ +#define GRUB_TERM_ACTIVE (1 << 3) /* Set when the terminal needs to be initialized. */ #define GRUB_TERM_NEED_INIT (1 << 16) @@ -93,10 +95,6 @@ grub_term_color_state; /* Menu-related geometrical constants. */ -/* FIXME: Ugly way to get them form terminal. */ -#define GRUB_TERM_WIDTH ((grub_getwh()&0xFF00)>>8) -#define GRUB_TERM_HEIGHT (grub_getwh()&0xFF) - /* The number of lines of "GRUB version..." at the top. */ #define GRUB_TERM_INFO_HEIGHT 1 @@ -225,7 +223,7 @@ struct grub_term_output typedef struct grub_term_output *grub_term_output_t; extern struct grub_handler_class EXPORT_VAR(grub_term_input_class); -extern struct grub_handler_class EXPORT_VAR(grub_term_output_class); +extern struct grub_term_output *EXPORT_VAR(grub_term_outputs); static inline void grub_term_register_input (const char *name __attribute__ ((unused)), @@ -238,7 +236,7 @@ static inline void grub_term_register_output (const char *name __attribute__ ((unused)), grub_term_output_t term) { - grub_handler_register (&grub_term_output_class, GRUB_AS_HANDLER (term)); + grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term)); } static inline void @@ -250,7 +248,7 @@ grub_term_unregister_input (grub_term_input_t term) static inline void grub_term_unregister_output (grub_term_output_t term) { - grub_handler_unregister (&grub_term_output_class, GRUB_AS_HANDLER (term)); + grub_list_remove (GRUB_AS_LIST_P (&grub_term_outputs), GRUB_AS_LIST (term)); } static inline grub_err_t @@ -260,44 +258,34 @@ grub_term_set_current_input (grub_term_input_t term) GRUB_AS_HANDLER (term)); } -static inline grub_err_t -grub_term_set_current_output (grub_term_output_t term) -{ - return grub_handler_set_current (&grub_term_output_class, - GRUB_AS_HANDLER (term)); -} - static inline grub_term_input_t grub_term_get_current_input (void) { return (grub_term_input_t) grub_term_input_class.cur_handler; } -static inline grub_term_output_t -grub_term_get_current_output (void) -{ - return (grub_term_output_t) grub_term_output_class.cur_handler; -} - void EXPORT_FUNC(grub_putchar) (int c); -void EXPORT_FUNC(grub_putcode) (grub_uint32_t code); -grub_ssize_t EXPORT_FUNC(grub_getcharwidth) (grub_uint32_t code); +void EXPORT_FUNC(grub_putcode) (grub_uint32_t code, + struct grub_term_output *term); int EXPORT_FUNC(grub_getkey) (void); int EXPORT_FUNC(grub_checkkey) (void); int EXPORT_FUNC(grub_getkeystatus) (void); -grub_uint16_t EXPORT_FUNC(grub_getwh) (void); -grub_uint16_t EXPORT_FUNC(grub_getxy) (void); -void EXPORT_FUNC(grub_gotoxy) (grub_uint8_t x, grub_uint8_t y); void EXPORT_FUNC(grub_cls) (void); void EXPORT_FUNC(grub_setcolorstate) (grub_term_color_state state); -void EXPORT_FUNC(grub_setcolor) (grub_uint8_t normal_color, - grub_uint8_t highlight_color); -void EXPORT_FUNC(grub_getcolor) (grub_uint8_t *normal_color, - grub_uint8_t *highlight_color); -int EXPORT_FUNC(grub_setcursor) (int on); -int EXPORT_FUNC(grub_getcursor) (void); void EXPORT_FUNC(grub_refresh) (void); -void EXPORT_FUNC(grub_set_more) (int onoff); +void grub_puts_terminal (const char *str, struct grub_term_output *term); +grub_uint16_t *grub_term_save_pos (void); +void grub_term_restore_pos (grub_uint16_t *pos); + +static inline int grub_term_width (struct grub_term_output *term) +{ + return ((term->getwh()&0xFF00)>>8); +} + +static inline int grub_term_height (struct grub_term_output *term) +{ + return (term->getwh()&0xFF); +} /* For convenience. */ #define GRUB_TERM_ASCII_CHAR(c) ((c) & 0xff) diff --git a/kern/main.c b/kern/main.c index 9215d55e7..040f89e6d 100644 --- a/kern/main.c +++ b/kern/main.c @@ -169,9 +169,8 @@ grub_main (void) grub_register_core_commands (); grub_register_rescue_parser (); - grub_register_rescue_reader (); grub_load_config (); grub_load_normal_mode (); - grub_reader_loop (0); + grub_rescue_run (); } diff --git a/kern/misc.c b/kern/misc.c index f6d189e94..7dd9bd18a 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -968,15 +968,12 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, void grub_abort (void) { - if (grub_term_get_current_output ()) + grub_printf ("\nAborted."); + + if (grub_term_get_current_input ()) { - grub_printf ("\nAborted."); - - if (grub_term_get_current_input ()) - { - grub_printf (" Press any key to exit."); - grub_getkey (); - } + grub_printf (" Press any key to exit."); + grub_getkey (); } grub_exit (); diff --git a/kern/reader.c b/kern/reader.c index 271a90f5a..74698d34b 100644 --- a/kern/reader.c +++ b/kern/reader.c @@ -22,28 +22,3 @@ #include #include -struct grub_handler_class grub_reader_class = - { - .name = "reader" - }; - -grub_err_t -grub_reader_loop (grub_reader_getline_t getline) -{ - while (1) - { - char *line; - grub_reader_getline_t func; - - /* Print an error, if any. */ - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - - func = (getline) ? : grub_reader_get_current ()->read_line; - if ((func (&line, 0)) || (! line)) - return grub_errno; - - grub_parser_get_current ()->parse_line (line, func); - grub_free (line); - } -} diff --git a/kern/rescue_reader.c b/kern/rescue_reader.c index 2a06f3fc2..732124b1a 100644 --- a/kern/rescue_reader.c +++ b/kern/rescue_reader.c @@ -19,20 +19,15 @@ #include #include +#include #include #include +#include #define GRUB_RESCUE_BUF_SIZE 256 static char linebuf[GRUB_RESCUE_BUF_SIZE]; -static grub_err_t -grub_rescue_init (void) -{ - grub_printf ("Entering rescue mode...\n"); - return 0; -} - /* Prompt to input a command and read the line. */ static grub_err_t grub_rescue_read_line (char **line, int cont) @@ -74,15 +69,24 @@ grub_rescue_read_line (char **line, int cont) return 0; } -static struct grub_reader grub_rescue_reader = - { - .name = "rescue", - .init = grub_rescue_init, - .read_line = grub_rescue_read_line - }; - void -grub_register_rescue_reader (void) +grub_rescue_run (void) { - grub_reader_register ("rescue", &grub_rescue_reader); + grub_printf ("Entering rescue mode...\n"); + + while (1) + { + char *line; + + /* Print an error, if any. */ + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + + grub_rescue_read_line (&line, 0); + if (! line) + continue; + + grub_parser_get_current ()->parse_line (line, grub_rescue_read_line); + grub_free (line); + } } diff --git a/kern/term.c b/kern/term.c index 94d5a9e1d..35660273e 100644 --- a/kern/term.c +++ b/kern/term.c @@ -22,78 +22,35 @@ #include #include -/* The amount of lines counted by the pager. */ -static int grub_more_lines; - -/* If the more pager is active. */ -static int grub_more; - -/* The current cursor state. */ -static int cursor_state = 1; - struct grub_handler_class grub_term_input_class = { .name = "terminal_input" }; -struct grub_handler_class grub_term_output_class = - { - .name = "terminal_output" - }; - #define grub_cur_term_input grub_term_get_current_input () -#define grub_cur_term_output grub_term_get_current_output () + +struct grub_term_output *grub_term_outputs; /* Put a Unicode character. */ void -grub_putcode (grub_uint32_t code) +grub_putcode (grub_uint32_t code, struct grub_term_output *term) { - int height = grub_getwh () & 255; + int height; - if (code == '\t' && grub_cur_term_output->getxy) + height = term->getwh () & 255; + + if (code == '\t' && term->getxy) { int n; - n = 8 - ((grub_getxy () >> 8) & 7); + n = 8 - ((term->getxy () >> 8) & 7); while (n--) - grub_putcode (' '); + grub_putcode (' ', term); return; } - (grub_cur_term_output->putchar) (code); - - if (code == '\n') - { - grub_putcode ('\r'); - - grub_more_lines++; - - if (grub_more && grub_more_lines == height - 1) - { - char key; - int pos = grub_getxy (); - - /* Show --MORE-- on the lower left side of the screen. */ - grub_gotoxy (1, height - 1); - grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); - grub_printf ("--MORE--"); - grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); - - key = grub_getkey (); - - /* Remove the message. */ - grub_gotoxy (1, height - 1); - grub_printf (" "); - grub_gotoxy (pos >> 8, pos & 0xFF); - - /* Scroll one lines or an entire page, depending on the key. */ - if (key == '\r' || key =='\n') - grub_more_lines--; - else - grub_more_lines = 0; - } - } + (term->putchar) (code); } /* Put a character. C is one byte of a UTF-8 stream. @@ -106,26 +63,28 @@ grub_putchar (int c) grub_uint32_t code; grub_ssize_t ret; + auto int do_putcode (grub_list_t item); + int do_putcode (grub_list_t item) + { + struct grub_term_output *term = (struct grub_term_output *) item; + + if (term->flags & GRUB_TERM_ACTIVE) + grub_putcode (code, term); + + return 0; + } + buf[size++] = c; ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0); - if (ret > 0) - { - size = 0; - grub_putcode (code); - } - else if (ret < 0) - { - size = 0; - grub_putcode ('?'); - } -} + if (ret < 0) + code = '?'; -/* Return the number of columns occupied by the character code CODE. */ -grub_ssize_t -grub_getcharwidth (grub_uint32_t code) -{ - return (grub_cur_term_output->getcharwidth) (code); + if (ret != 0) + { + size = 0; + grub_list_iterate (GRUB_AS_LIST (grub_term_outputs), do_putcode); + } } int @@ -149,91 +108,67 @@ grub_getkeystatus (void) return 0; } -grub_uint16_t -grub_getxy (void) -{ - return (grub_cur_term_output->getxy) (); -} - -grub_uint16_t -grub_getwh (void) -{ - return (grub_cur_term_output->getwh) (); -} - -void -grub_gotoxy (grub_uint8_t x, grub_uint8_t y) -{ - (grub_cur_term_output->gotoxy) (x, y); -} - void grub_cls (void) { - if ((grub_cur_term_output->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug"))) - { - grub_putchar ('\n'); - grub_refresh (); - } - else - (grub_cur_term_output->cls) (); + auto int hook (grub_list_t item); + int hook (grub_list_t item) + { + struct grub_term_output *term = (struct grub_term_output *) item; + + if (!(term->flags & GRUB_TERM_ACTIVE)) + return 0; + + if ((term->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug"))) + { + grub_putcode ('\n', term); + grub_refresh (); + } + else + (term->cls) (); + + return 0; + } + + grub_list_iterate (GRUB_AS_LIST (grub_term_outputs), hook); } void grub_setcolorstate (grub_term_color_state state) { - if (grub_cur_term_output->setcolorstate) - (grub_cur_term_output->setcolorstate) (state); -} + auto int hook (grub_list_t item); + int hook (grub_list_t item) + { + struct grub_term_output *term = (struct grub_term_output *) item; -void -grub_setcolor (grub_uint8_t normal_color, grub_uint8_t highlight_color) -{ - if (grub_cur_term_output->setcolor) - (grub_cur_term_output->setcolor) (normal_color, highlight_color); -} + if (!(term->flags & GRUB_TERM_ACTIVE)) + return 0; -void -grub_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color) -{ - if (grub_cur_term_output->getcolor) - (grub_cur_term_output->getcolor) (normal_color, highlight_color); -} + if (term->setcolorstate) + (term->setcolorstate) (state); -int -grub_setcursor (int on) -{ - int ret = cursor_state; + return 0; + } - if (grub_cur_term_output->setcursor) - { - (grub_cur_term_output->setcursor) (on); - cursor_state = on; - } - - return ret; -} - -int -grub_getcursor (void) -{ - return cursor_state; + grub_list_iterate (GRUB_AS_LIST (grub_term_outputs), hook); } void grub_refresh (void) { - if (grub_cur_term_output->refresh) - (grub_cur_term_output->refresh) (); -} + auto int hook (grub_list_t item); + int hook (grub_list_t item) + { + struct grub_term_output *term = (struct grub_term_output *) item; -void -grub_set_more (int onoff) -{ - if (onoff == 1) - grub_more++; - else - grub_more--; + if (!(term->flags & GRUB_TERM_ACTIVE)) + return 0; - grub_more_lines = 0; + if (term->refresh) + (term->refresh) (); + + return 0; + } + + grub_list_iterate (GRUB_AS_LIST (grub_term_outputs), hook); } diff --git a/lib/charset.c b/lib/charset.c index 8bc5b9149..0f2c2c8ee 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -114,3 +114,67 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, *srcend = src; return p - dest; } + +/* Convert UCS-4 to UTF-8. */ +char * +grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size) +{ + grub_size_t remaining; + grub_uint32_t *ptr; + grub_size_t cnt = 0; + grub_uint8_t *ret, *dest; + + remaining = size; + ptr = src; + while (remaining--) + { + grub_uint32_t code = *ptr++; + + if (code <= 0x007F) + cnt++; + else if (code <= 0x07FF) + cnt += 2; + else if ((code >= 0xDC00 && code <= 0xDFFF) + || (code >= 0xD800 && code <= 0xDBFF)) + /* No surrogates in UCS-4... */ + cnt++; + else + cnt += 3; + } + cnt++; + + ret = grub_malloc (cnt); + if (!ret) + return 0; + + dest = ret; + remaining = size; + ptr = src; + while (remaining--) + { + grub_uint32_t code = *ptr++; + + if (code <= 0x007F) + *dest++ = code; + else if (code <= 0x07FF) + { + *dest++ = (code >> 6) | 0xC0; + *dest++ = (code & 0x3F) | 0x80; + } + else if ((code >= 0xDC00 && code <= 0xDFFF) + || (code >= 0xD800 && code <= 0xDBFF)) + { + /* No surrogates in UCS-4... */ + *dest++ = '?'; + } + else + { + *dest++ = (code >> 12) | 0xE0; + *dest++ = ((code >> 6) & 0x3F) | 0x80; + *dest++ = (code & 0x3F) | 0x80; + } + } + *dest = 0; + + return ret; +} diff --git a/loader/i386/linux.c b/loader/i386/linux.c index 82bfd6b95..140ed1957 100644 --- a/loader/i386/linux.c +++ b/loader/i386/linux.c @@ -33,6 +33,7 @@ #include #include #include +#include #define GRUB_LINUX_CL_OFFSET 0x1000 #define GRUB_LINUX_CL_END_OFFSET 0x2000 @@ -547,8 +548,8 @@ grub_linux_boot (void) /* Initialize these last, because terminal position could be affected by printfs above. */ if (params->have_vga == GRUB_VIDEO_TYPE_TEXT) { - params->video_cursor_x = grub_getxy () >> 8; - params->video_cursor_y = grub_getxy () & 0xff; + params->video_cursor_x = grub_console_getxy () >> 8; + params->video_cursor_y = grub_console_getxy () & 0xff; } #ifdef __x86_64__ diff --git a/normal/cmdline.c b/normal/cmdline.c index 6d74e6e69..c104709c5 100644 --- a/normal/cmdline.c +++ b/normal/cmdline.c @@ -28,10 +28,10 @@ #include #include -static char *kill_buf; +static grub_uint32_t *kill_buf; static int hist_size; -static char **hist_lines = 0; +static grub_uint32_t **hist_lines = 0; static int hist_pos = 0; static int hist_end = 0; static int hist_used = 0; @@ -39,7 +39,7 @@ static int hist_used = 0; grub_err_t grub_set_history (int newsize) { - char **old_hist_lines = hist_lines; + grub_uint32_t **old_hist_lines = hist_lines; hist_lines = grub_malloc (sizeof (char *) * newsize); /* Copy the old lines into the new buffer. */ @@ -90,17 +90,42 @@ grub_set_history (int newsize) /* Get the entry POS from the history where `0' is the newest entry. */ -static char * +static grub_uint32_t * grub_history_get (int pos) { pos = (hist_pos + pos) % hist_size; return hist_lines[pos]; } +static grub_size_t +strlen_ucs4 (const grub_uint32_t *s) +{ + const grub_uint32_t *p = s; + + while (*p) + p++; + + return p - s; +} + +static grub_uint32_t * +strdup_ucs4 (const grub_uint32_t *s) +{ + grub_size_t len; + char *p; + + len = strlen_ucs4 (s) + 1; + p = (char *) grub_malloc (len * sizeof (grub_uint32_t)); + if (! p) + return 0; + + return grub_memcpy (p, s, len * sizeof (grub_uint32_t)); +} + /* Insert a new history line S on the top of the history. */ static void -grub_history_add (char *s) +grub_history_add (grub_uint32_t *s) { /* Remove the oldest entry in the history to make room for a new entry. */ @@ -121,16 +146,16 @@ grub_history_add (char *s) hist_pos = hist_size + hist_pos; /* Insert into history. */ - hist_lines[hist_pos] = grub_strdup (s); + hist_lines[hist_pos] = strdup_ucs4 (s); } /* Replace the history entry on position POS with the string S. */ static void -grub_history_replace (int pos, char *s) +grub_history_replace (int pos, grub_uint32_t *s) { pos = (hist_pos + pos) % hist_size; grub_free (hist_lines[pos]); - hist_lines[pos] = grub_strdup (s); + hist_lines[pos] = strdup_ucs4 (s); } /* A completion hook to print items. */ @@ -176,62 +201,81 @@ print_completion (const char *item, grub_completion_type_t type, int count) grub_printf (" %s", item); } -/* Get a command-line. If ECHO_CHAR is not zero, echo it instead of input - characters. If READLINE is non-zero, readline-like key bindings are - available. If ESC is pushed, return zero, otherwise return non-zero. */ -/* FIXME: The dumb interface is not supported yet. */ -int -grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, - int echo_char, int readline, int history) +struct cmdline_term +{ + unsigned xpos, ypos, ystart, width, height; + struct grub_term_output *term; +}; + +/* Get a command-line. If ESC is pushed, return zero, + otherwise return command line. */ +/* FIXME: The dumb interface is not supported yet. */ +char * +grub_cmdline_get (const char *prompt, unsigned max_len) { - unsigned xpos, ypos, ystart; grub_size_t lpos, llen; grub_size_t plen; - char buf[max_len]; + grub_uint32_t buf[max_len]; int key; int histpos = 0; - auto void cl_insert (const char *str); + auto void cl_insert (const grub_uint32_t *str); auto void cl_delete (unsigned len); - auto void cl_print (int pos, int c); - auto void cl_set_pos (void); + auto void cl_print (struct cmdline_term *cl_term, int pos, grub_uint32_t c); + auto void cl_set_pos (struct cmdline_term *cl_term); + auto void cl_print_all (int pos, grub_uint32_t c); + auto void cl_set_pos_all (void); const char *prompt_translated = _(prompt); + struct cmdline_term *cl_terms; + unsigned nterms; - void cl_set_pos (void) + void cl_set_pos (struct cmdline_term *cl_term) + { + cl_term->xpos = (plen + lpos) % (cl_term->width - 1); + cl_term->ypos = cl_term->ystart + (plen + lpos) / (cl_term->width - 1); + cl_term->term->gotoxy (cl_term->xpos, cl_term->ypos); + } + + void cl_set_pos_all () + { + unsigned i; + for (i = 0; i < nterms; i++) + cl_set_pos (&cl_terms[i]); + } + + void cl_print (struct cmdline_term *cl_term, int pos, grub_uint32_t c) { - xpos = (plen + lpos) % 79; - ypos = ystart + (plen + lpos) / 79; - grub_gotoxy (xpos, ypos); - - grub_refresh (); - } - - void cl_print (int pos, int c) - { - char *p; + grub_uint32_t *p; for (p = buf + pos; *p; p++) { - if (xpos++ > 78) + if (cl_term->xpos++ > cl_term->width - 2) { - grub_putchar ('\n'); + grub_putcode ('\n', cl_term->term); - xpos = 1; - if (ypos == (unsigned) (grub_getxy () & 0xFF)) - ystart--; + cl_term->xpos = 1; + if (cl_term->ypos == (unsigned) (cl_term->height)) + cl_term->ystart--; else - ypos++; + cl_term->ypos++; } if (c) - grub_putchar (c); + grub_putcode (c, cl_term->term); else - grub_putchar (*p); + grub_putcode (*p, cl_term->term); } } - void cl_insert (const char *str) + void cl_print_all (int pos, grub_uint32_t c) + { + unsigned i; + for (i = 0; i < nterms; i++) + cl_print (&cl_terms[i], pos, c); + } + + void cl_insert (const grub_uint32_t *str) { - grub_size_t len = grub_strlen (str); + grub_size_t len = strlen_ucs4 (str); if (len + llen < max_len) { @@ -240,8 +284,8 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, llen += len; lpos += len; - cl_print (lpos - len, echo_char); - cl_set_pos (); + cl_print_all (lpos - len, echo_char); + cl_set_pos_all (); } grub_refresh (); @@ -254,182 +298,207 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, grub_size_t saved_lpos = lpos; lpos = llen - len; - cl_set_pos (); - cl_print (lpos, ' '); + cl_set_pos_all (); + cl_print_all (lpos, ' '); lpos = saved_lpos; - cl_set_pos (); + cl_set_pos_all (); grub_memmove (buf + lpos, buf + lpos + len, llen - lpos + 1); llen -= len; - cl_print (lpos, echo_char); - cl_set_pos (); + cl_print_all (lpos, echo_char); + cl_set_pos_all (); } grub_refresh (); } + void init_clterm (struct cmdline_term *cl_term_cur) + { + cl_term_cur->xpos = plen; + cl_term_cur->ypos = (cl_term_cur->term->getxy () & 0xFF); + cl_term_cur->ystart = cl_term_cur->ypos; + cl_term_cur->width = grub_term_width (cl_term_cur->term); + cl_term_cur->height = grub_term_height (cl_term_cur->term); + } + + void init_clterm_all (void) + { + unsigned i; + for (i = 0; i < nterms; i++) + init_clterm (&cl_terms[i]); + } + plen = grub_strlen (prompt_translated); lpos = llen = 0; buf[0] = '\0'; - if ((grub_getxy () >> 8) != 0) - grub_putchar ('\n'); + grub_putchar ('\n'); grub_printf ("%s", prompt_translated); - xpos = plen; - ystart = ypos = (grub_getxy () & 0xFF); + { + struct cmdline_term *cl_term_cur; + struct grub_term_output *cur; + nterms = 0; + for (cur = grub_term_outputs; cur; cur = cur->next) + if (cur->flags & GRUB_TERM_ACTIVE) + nterms++; - cl_insert (cmdline); + cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms); + if (!cl_terms) + return grub_errno; + cl_term_cur = cl_terms; + for (cur = grub_term_outputs; cur; cur = cur->next) + if (cur->flags & GRUB_TERM_ACTIVE) + { + cl_term_cur->term = cur; + init_clterm (cl_term_cur); + cl_term_cur++; + } + } if (history && hist_used == 0) grub_history_add (buf); while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r') { - if (readline) - { - switch (key) - { - case 1: /* Ctrl-a */ - lpos = 0; - cl_set_pos (); - break; - - case 2: /* Ctrl-b */ - if (lpos > 0) - { - lpos--; - cl_set_pos (); - } - break; - - case 5: /* Ctrl-e */ - lpos = llen; - cl_set_pos (); - break; - - case 6: /* Ctrl-f */ - if (lpos < llen) - { - lpos++; - cl_set_pos (); - } - break; - - case 9: /* Ctrl-i or TAB */ - { - char *insert; - int restore; - - /* Backup the next character and make it 0 so it will - be easy to use string functions. */ - char backup = buf[lpos]; - buf[lpos] = '\0'; - - - insert = grub_normal_do_completion (buf, &restore, - print_completion); - /* Restore the original string. */ - buf[lpos] = backup; - - if (restore) - { - /* Restore the prompt. */ - grub_printf ("\n%s %s", prompt_translated, buf); - xpos = plen; - ystart = ypos = (grub_getxy () & 0xFF); - } - - if (insert) - { - cl_insert (insert); - grub_free (insert); - } - } - break; - - case 11: /* Ctrl-k */ - if (lpos < llen) - { - if (kill_buf) - grub_free (kill_buf); - - kill_buf = grub_strdup (buf + lpos); - grub_errno = GRUB_ERR_NONE; - - cl_delete (llen - lpos); - } - break; - - case 14: /* Ctrl-n */ - { - char *hist; - - lpos = 0; - - if (histpos > 0) - { - grub_history_replace (histpos, buf); - histpos--; - } - - cl_delete (llen); - hist = grub_history_get (histpos); - cl_insert (hist); - - break; - } - case 16: /* Ctrl-p */ - { - char *hist; - - lpos = 0; - - if (histpos < hist_used - 1) - { - grub_history_replace (histpos, buf); - histpos++; - } - - cl_delete (llen); - hist = grub_history_get (histpos); - - cl_insert (hist); - } - break; - - case 21: /* Ctrl-u */ - if (lpos > 0) - { - grub_size_t n = lpos; - - if (kill_buf) - grub_free (kill_buf); - - kill_buf = grub_malloc (n + 1); - grub_errno = GRUB_ERR_NONE; - if (kill_buf) - { - grub_memcpy (kill_buf, buf, n); - kill_buf[n] = '\0'; - } - - lpos = 0; - cl_set_pos (); - cl_delete (n); - } - break; - - case 25: /* Ctrl-y */ - if (kill_buf) - cl_insert (kill_buf); - break; - } - } - switch (key) { + case 1: /* Ctrl-a */ + lpos = 0; + cl_set_pos_all (); + break; + + case 2: /* Ctrl-b */ + if (lpos > 0) + { + lpos--; + cl_set_pos_all (); + } + break; + + case 5: /* Ctrl-e */ + lpos = llen; + cl_set_pos_all (); + break; + + case 6: /* Ctrl-f */ + if (lpos < llen) + { + lpos++; + cl_set_pos_all (); + } + break; + + case 9: /* Ctrl-i or TAB */ + { + grub_uint32_t *insert; + int restore; + + /* Backup the next character and make it 0 so it will + be easy to use string functions. */ + char backup = buf[lpos]; + buf[lpos] = '\0'; + + + insert = grub_normal_do_completion (buf, &restore, + print_completion); + /* Restore the original string. */ + buf[lpos] = backup; + + if (restore) + { + /* Restore the prompt. */ + grub_printf ("\n%s", prompt_translated); + init_clterm_all (); + cl_print_all (0, 0); + } + + if (insert) + { + cl_insert (insert); + grub_free (insert); + } + } + break; + + case 11: /* Ctrl-k */ + if (lpos < llen) + { + if (kill_buf) + grub_free (kill_buf); + + kill_buf = strdup_ucs4 (buf + lpos); + grub_errno = GRUB_ERR_NONE; + + cl_delete (llen - lpos); + } + break; + + case 14: /* Ctrl-n */ + { + grub_uint32_t *hist; + + lpos = 0; + + if (histpos > 0) + { + grub_history_replace (histpos, buf); + histpos--; + } + + cl_delete (llen); + hist = grub_history_get (histpos); + cl_insert (hist); + + break; + } + case 16: /* Ctrl-p */ + { + grub_uint32_t *hist; + + lpos = 0; + + if (histpos < hist_used - 1) + { + grub_history_replace (histpos, buf); + histpos++; + } + + cl_delete (llen); + hist = grub_history_get (histpos); + + cl_insert (hist); + } + break; + + case 21: /* Ctrl-u */ + if (lpos > 0) + { + grub_size_t n = lpos; + + if (kill_buf) + grub_free (kill_buf); + + kill_buf = grub_malloc (n + 1); + grub_errno = GRUB_ERR_NONE; + if (kill_buf) + { + grub_memcpy (kill_buf, buf, n); + kill_buf[n] = '\0'; + } + + lpos = 0; + cl_set_pos_all (); + cl_delete (n); + } + break; + + case 25: /* Ctrl-y */ + if (kill_buf) + cl_insert (kill_buf); + break; + case '\e': return 0; @@ -437,7 +506,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, if (lpos > 0) { lpos--; - cl_set_pos (); + cl_set_pos_all (); } else break; @@ -451,7 +520,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, default: if (grub_isprint (key)) { - char str[2]; + grub_uint32_t str[2]; str[0] = key; str[1] = '\0'; @@ -464,23 +533,21 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, grub_putchar ('\n'); grub_refresh (); - /* If ECHO_CHAR is NUL, remove leading spaces. */ + /* Remove leading spaces. */ lpos = 0; - if (! echo_char) - while (buf[lpos] == ' ') - lpos++; + while (buf[lpos] == ' ') + lpos++; if (history) { histpos = 0; - if (grub_strlen (buf) > 0) + if (strlen_ucs4 (buf) > 0) { + grub_uint32_t empty[] = { 0 }; grub_history_replace (histpos, buf); - grub_history_add (""); + grub_history_add (empty); } } - grub_memcpy (cmdline, buf + lpos, llen - lpos + 1); - - return 1; + return grub_ucs4_to_utf8_alloc (buf + lpos, llen - lpos + 1); } diff --git a/normal/color.c b/normal/color.c index 0b9868d3b..63bd889a5 100644 --- a/normal/color.c +++ b/normal/color.c @@ -103,23 +103,36 @@ free_and_return: grub_free (fg_name); } +static grub_uint8_t color_normal, color_highlight; + +static void +set_colors (void) +{ + struct grub_term_output *term; + + for (term = grub_term_outputs; term; term = term->next) + { + if (! (term->flags & GRUB_TERM_ACTIVE)) + continue; + + /* Reloads terminal `normal' and `highlight' colors. */ + if (term->setcolor) + term->setcolor (color_normal, color_highlight); + + /* Propagates `normal' color to terminal current color. */ + if (term->setcolorstate) + term->setcolorstate (GRUB_TERM_COLOR_NORMAL); + } +} + /* Replace default `normal' colors with the ones specified by user (if any). */ char * grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)), const char *val) { - grub_uint8_t color_normal, color_highlight; - - /* Use old settings in case grub_parse_color_name_pair() has no effect. */ - grub_getcolor (&color_normal, &color_highlight); - grub_parse_color_name_pair (&color_normal, val); - /* Reloads terminal `normal' and `highlight' colors. */ - grub_setcolor (color_normal, color_highlight); - - /* Propagates `normal' color to terminal current color. */ - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); + set_colors (); return grub_strdup (val); } @@ -129,21 +142,9 @@ char * grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)), const char *val) { - grub_uint8_t color_normal, color_highlight; - - /* Use old settings in case grub_parse_color_name_pair() has no effect. */ - grub_getcolor (&color_normal, &color_highlight); - grub_parse_color_name_pair (&color_highlight, val); - /* Reloads terminal `normal' and `highlight' colors. */ - grub_setcolor (color_normal, color_highlight); - - /* Propagates `normal' color to terminal current color. - Note: Using GRUB_TERM_COLOR_NORMAL here rather than - GRUB_TERM_COLOR_HIGHLIGHT is intentional. We don't want to switch - to highlight state just because color was reloaded. */ - grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); + set_colors (); return grub_strdup (val); } diff --git a/normal/main.c b/normal/main.c index e8dfb182b..42098e682 100644 --- a/normal/main.c +++ b/normal/main.c @@ -372,7 +372,21 @@ read_config_file (const char *config) if (! file) return 0; - grub_reader_loop (getline); + while (1) + { + char *line; + + /* Print an error, if any. */ + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + + if ((getline (&line, 0)) || (! line)) + break; + + grub_parser_get_current ()->parse_line (line, getline); + grub_free (line); + } + grub_file_close (file); if (old_parser) @@ -383,7 +397,7 @@ read_config_file (const char *config) /* Initialize the screen. */ void -grub_normal_init_page (void) +grub_normal_init_page (struct grub_term_output *term) { int msg_len; int posx; @@ -391,13 +405,12 @@ grub_normal_init_page (void) char *msg_formatted = grub_malloc (grub_strlen(msg) + grub_strlen(PACKAGE_VERSION)); + grub_uint32_t *unicode_msg; + grub_uint32_t *last_position; grub_cls (); grub_sprintf (msg_formatted, msg, PACKAGE_VERSION); - - grub_uint32_t *unicode_msg; - grub_uint32_t *last_position; msg_len = grub_utf8_to_ucs4_alloc (msg_formatted, &unicode_msg, &last_position); @@ -408,8 +421,8 @@ grub_normal_init_page (void) } posx = grub_getstringwidth (unicode_msg, last_position); - posx = (GRUB_TERM_WIDTH - posx) / 2; - grub_gotoxy (posx, 1); + posx = (grub_term_width (term) - posx) / 2; + term->gotoxy (posx, 1); grub_print_ucs4 (unicode_msg, last_position); grub_printf("\n\n"); @@ -493,48 +506,30 @@ quit: return 0; } -void -grub_cmdline_run (int nested) -{ - grub_reader_t reader; - grub_err_t err = GRUB_ERR_NONE; - - err = grub_auth_check_authentication (NULL); - - if (err) - { - grub_print_error (); - grub_errno = GRUB_ERR_NONE; - return; - } - - reader = grub_reader_get_current (); - - reader_nested = nested; - if (reader->init) - reader->init (); - grub_reader_loop (0); -} - static grub_err_t grub_normal_reader_init (void) { - grub_normal_init_page (); - grub_setcursor (1); - + struct grub_term_output *term; const char *msg = _("Minimal BASH-like line editing is supported. For " "the first word, TAB lists possible command completions. Anywhere " "else TAB lists possible device or file completions. %s"); - const char *msg_esc = _("ESC at any time exits."); - char *msg_formatted = grub_malloc (sizeof (char) * (grub_strlen (msg) + grub_strlen(msg_esc) + 1)); grub_sprintf (msg_formatted, msg, reader_nested ? msg_esc : ""); - grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN); - grub_puts ("\n"); + for (term = grub_term_outputs; term; term = term->next) + { + if (! (term->flags & GRUB_TERM_ACTIVE)) + continue; + grub_normal_init_page (term); + if (term->setcursor) + term->setcursor (1); + + grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN); + grub_puts ("\n"); + } grub_free (msg_formatted); return 0; @@ -567,12 +562,40 @@ grub_normal_read_line (char **line, int cont) return 0; } -static struct grub_reader grub_normal_reader = - { - .name = "normal", - .init = grub_normal_reader_init, - .read_line = grub_normal_read_line - }; +void +grub_cmdline_run (int nested) +{ + grub_err_t err = GRUB_ERR_NONE; + + err = grub_auth_check_authentication (NULL); + + if (err) + { + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + return; + } + + reader_nested = nested; + + grub_normal_reader_init (); + + while (1) + { + char *line; + + /* Print an error, if any. */ + grub_print_error (); + grub_errno = GRUB_ERR_NONE; + + grub_normal_read_line (&line, 0); + if (! line) + continue; + + grub_parser_get_current ()->parse_line (line, grub_normal_read_line); + grub_free (line); + } +} static char * grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)), @@ -592,8 +615,6 @@ GRUB_MOD_INIT(normal) grub_set_history (GRUB_DEFAULT_HISTORY_SIZE); - grub_reader_register ("normal", &grub_normal_reader); - grub_reader_set_current (&grub_normal_reader); grub_register_variable_hook ("pager", 0, grub_env_write_pager); /* Register a command "normal" for the rescue mode. */ @@ -612,7 +633,6 @@ GRUB_MOD_INIT(normal) GRUB_MOD_FINI(normal) { grub_set_history (0); - grub_reader_unregister (&grub_normal_reader); grub_register_variable_hook ("pager", 0, 0); grub_fs_autoload_hook = 0; free_handler_list (); diff --git a/normal/term.c b/normal/term.c new file mode 100644 index 000000000..73eab548a --- /dev/null +++ b/normal/term.c @@ -0,0 +1,128 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2002,2003,2005,2007,2008,2009 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +/* The amount of lines counted by the pager. */ +static int grub_more_lines; + +/* If the more pager is active. */ +static int grub_more; + +static void +process_newline (void) +{ + if (code == '\n') + { + grub_putcode ('\r'); + + grub_more_lines++; + + if (grub_more && grub_more_lines == height - 1) + { + char key; + int pos = term->getxy (); + + /* Show --MORE-- on the lower left side of the screen. */ + term->gotoxy (1, height - 1); + grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT); + grub_printf ("--MORE--"); + grub_setcolorstate (GRUB_TERM_COLOR_STANDARD); + + key = grub_getkey (); + + /* Remove the message. */ + term->gotoxy (1, height - 1); + grub_printf (" "); + term->gotoxy (pos >> 8, pos & 0xFF); + + /* Scroll one lines or an entire page, depending on the key. */ + if (key == '\r' || key =='\n') + grub_more_lines--; + else + grub_more_lines = 0; + } + } +} + +void +grub_set_more (int onoff) +{ + if (onoff == 1) + grub_more++; + else + grub_more--; + + grub_more_lines = 0; +} + +void +grub_puts_terminal (const char *str, struct grub_term_output *term) +{ + grub_uint32_t code; + grub_ssize_t ret; + const char *ptr = str; + unsigned i; + + while (*ptr) + { + ret = grub_utf8_to_ucs4 (&code, 1, ptr, + grub_strlen (ptr), &ptr); + if (ret < 0) + { + grub_putcode ('?', term); + ptr++; + continue; + } + else + grub_putcode (code, term); + } +} + +grub_uint16_t * +grub_term_save_pos (void) +{ + struct grub_term_output *cur; + unsigned cnt = 0; + grub_uint16_t *ret, *ptr; + + for (cur = grub_term_outputs; cur; cur = cur->next) + if (cur->flags & GRUB_TERM_ACTIVE) + cnt++; + + ret = grub_malloc (cnt * sizeof (ret[0])); + if (!ret) + return NULL; + + for (cur = grub_term_outputs; cur; cur = cur->next) + if (cur->flags & GRUB_TERM_ACTIVE) + *ptr++ = cur->getxy (); + + return ret; +} + +void +grub_term_restore_pos (grub_uint16_t *pos) +{ + struct grub_term_output *cur; + + if (!pos) + return; + + for (cur = grub_term_outputs; cur; cur = cur->next) + if (cur->flags & GRUB_TERM_ACTIVE) + cur->gotoxy ((*ptr & 0xff00) >> 8, *ptr & 0xff); +} diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index 66475d456..b54e2f6f1 100644 --- a/term/i386/pc/console.c +++ b/term/i386/pc/console.c @@ -79,10 +79,6 @@ grub_console_init (void) void grub_console_fini (void) { - /* This is to make sure the console is restored to text mode before - we boot. */ - grub_term_set_current_output (&grub_console_term_output); - grub_term_unregister_input (&grub_console_term_input); grub_term_unregister_output (&grub_console_term_output); }