]> git.ipfire.org Git - thirdparty/grub.git/commitdiff
Work on multi-out terminal
authorVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 23 Dec 2009 23:37:11 +0000 (00:37 +0100)
committerVladimir 'phcoder' Serbinenko <phcoder@gmail.com>
Wed, 23 Dec 2009 23:37:11 +0000 (00:37 +0100)
21 files changed:
commands/help.c
commands/sleep.c
conf/any-emu.rmk
conf/common.rmk
include/grub/charset.h
include/grub/normal.h
include/grub/parser.h
include/grub/reader.h
include/grub/term.h
kern/main.c
kern/misc.c
kern/reader.c
kern/rescue_reader.c
kern/term.c
lib/charset.c
loader/i386/linux.c
normal/cmdline.c
normal/color.c
normal/main.c
normal/term.c [new file with mode: 0644]
term/i386/pc/console.c

index c18ec6b83ca1d68997ac278f23db49a62c9c7c7d..4d16945af5e6f0a0a66544fffac02b877149d0e3 100644 (file)
@@ -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;
     }
index 9207b60a78ca609a9a6f4ef7870f197518a17295..aea7f2690166c388e173a396c4239ea06137f557 100644 (file)
@@ -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--)
     {
index fb97de0a0203501073c436f05643e84328539af9..2c383f3870152a79cad5c7079cb1878a3f02caf4 100644 (file)
@@ -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   \
index 1ed30a404c912998115b1a4f99dd482bc00349a3..02d57f0a34f5142996e92518eee873aded28f297 100644 (file)
@@ -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)
 
index f85862f8b6340e51c2ab7844890aea1e2110e091..daaa5c99fabedd7009f44573fbf4b2444eb1096d 100644 (file)
@@ -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
index e55553de54fc7c2941917ab0a146ce1bd67eb013..d629338e60f9a6c13d7356050a366c7e9d904521 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef GRUB_NORMAL_HEADER
 #define GRUB_NORMAL_HEADER     1
 
+#include <grub/term.h>
 #include <grub/symbol.h>
 #include <grub/err.h>
 #include <grub/env.h>
@@ -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);
index 41f768bbac54e0686c1188bcfeb7a298958ece68..17f0c430376820e10ebe36c04048573c34b2ed38 100644 (file)
@@ -22,6 +22,7 @@
 
 #include <grub/types.h>
 #include <grub/err.h>
+#include <grub/handler.h>
 #include <grub/reader.h>
 
 /* All the states for the command line.  */
index c7e67bf5e4f0850a870c94b761b04b52a0f02d2e..fd72a32526fd3d54c3134a2bf2474df6d9c6f3c7 100644 (file)
 #ifndef GRUB_READER_HEADER
 #define GRUB_READER_HEADER     1
 
-#include <grub/types.h>
 #include <grub/err.h>
-#include <grub/handler.h>
 
 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 */
index 316d75390467388ad0261ebe7b4491f9c2065696..39a10ed71c76d8d7ecde011aeb5c04426fdf2079 100644 (file)
@@ -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)
index 9215d55e767f18238252c48126428303a7cf9ecd..040f89e6de38213897a2a1db7b1d974a44716344 100644 (file)
@@ -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 ();
 }
index f6d189e948c139678f4c8bda6d60b3736f0378f6..7dd9bd18a6c624c8ae4140961c2ab800e1441b32 100644 (file)
@@ -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 ();
index 271a90f5a5bccd43b000b9739304fb5819fe3377..74698d34b466f8ee4fb0899bbb434deca3184a3a 100644 (file)
 #include <grub/reader.h>
 #include <grub/parser.h>
 
-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);
-    }
-}
index 2a06f3fc248920517e830689f41da8ef7879dfef..732124b1afc21fe013f3e4c420f5c104a28d584d 100644 (file)
 
 #include <grub/types.h>
 #include <grub/reader.h>
+#include <grub/parser.h>
 #include <grub/misc.h>
 #include <grub/term.h>
+#include <grub/mm.h>
 
 #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);
+    }
 }
index 94d5a9e1d5edd2f8b951b9247e3ccd9fb596330b..35660273e4ec19314631e627694fc09f9f04d5f0 100644 (file)
 #include <grub/misc.h>
 #include <grub/env.h>
 
-/* 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,28 +63,30 @@ 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)
+  if (ret < 0)
+    code = '?';
+
+  if (ret != 0)
     {
       size = 0;
-      grub_putcode ('?');
+      grub_list_iterate (GRUB_AS_LIST (grub_term_outputs), do_putcode);
     }
 }
 
-/* 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);
-}
-
 int
 grub_getkey (void)
 {
@@ -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;
 
-void
-grub_setcolorstate (grub_term_color_state state)
-{
-  if (grub_cur_term_output->setcolorstate)
-    (grub_cur_term_output->setcolorstate) (state);
-}
+    if (!(term->flags & GRUB_TERM_ACTIVE))
+      return 0;
 
-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_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_getcolor (grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
+grub_setcolorstate (grub_term_color_state state)
 {
-  if (grub_cur_term_output->getcolor)
-    (grub_cur_term_output->getcolor) (normal_color, highlight_color);
-}
+  auto int hook (grub_list_t item);
+  int hook (grub_list_t item)
+  {
+    struct grub_term_output *term = (struct grub_term_output *) item;
 
-int
-grub_setcursor (int on)
-{
-  int ret = cursor_state;
+    if (!(term->flags & GRUB_TERM_ACTIVE))
+      return 0;
 
-  if (grub_cur_term_output->setcursor)
-    {
-      (grub_cur_term_output->setcursor) (on);
-      cursor_state = on;
-    }
+    if (term->setcolorstate)
+      (term->setcolorstate) (state);
 
-  return ret;
-}
+    return 0;
+  }
 
-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;
+
+    if (term->refresh)
+      (term->refresh) ();
+
+    return 0;
+  }
 
-  grub_more_lines = 0;
+  grub_list_iterate (GRUB_AS_LIST (grub_term_outputs), hook);
 }
index 8bc5b9149f0f094a316963c816c484958e955719..0f2c2c8eea8a5fa3fd44946a30617ee795cadb4f 100644 (file)
@@ -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;
+}
index 82bfd6b9549a4b3b0a79a0d0038f7a807190f038..140ed19574fae66bc9a67cdfbb2759708952e95c 100644 (file)
@@ -33,6 +33,7 @@
 #include <grub/video_fb.h>
 #include <grub/command.h>
 #include <grub/i386/pc/vbe.h>
+#include <grub/i386/pc/console.h>
 
 #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__
index 6d74e6e6930d140e1ba16fa68fa2e51d5e5e9e63..c104709c568534e98a294da767d0c9de59e1c9ce 100644 (file)
 #include <grub/env.h>
 #include <grub/i18n.h>
 
-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.  */
+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.  */
-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)
 {
-  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);
-
-  void cl_set_pos (void)
+  struct cmdline_term *cl_terms;
+  unsigned nterms;
+
+  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);
-
-  cl_insert (cmdline);
+  {
+    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_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)
        {
-         switch (key)
+       case 1: /* Ctrl-a */
+         lpos = 0;
+         cl_set_pos_all ();
+         break;
+
+       case 2: /* Ctrl-b */
+         if (lpos > 0)
            {
-           case 1:     /* Ctrl-a */
-             lpos = 0;
-             cl_set_pos ();
-             break;
+             lpos--;
+             cl_set_pos_all ();
+           }
+         break;
 
-           case 2:     /* Ctrl-b */
-             if (lpos > 0)
-               {
-                 lpos--;
-                 cl_set_pos ();
-               }
-             break;
+       case 5: /* Ctrl-e */
+         lpos = llen;
+         cl_set_pos_all ();
+         break;
 
-           case 5:     /* Ctrl-e */
-             lpos = llen;
-             cl_set_pos ();
-             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';
 
-           case 6:     /* Ctrl-f */
-             if (lpos < llen)
-               {
-                 lpos++;
-                 cl_set_pos ();
-               }
-             break;
 
-           case 9:     /* Ctrl-i or TAB */
+           insert = grub_normal_do_completion (buf, &restore,
+                                               print_completion);
+           /* Restore the original string.  */
+           buf[lpos] = backup;
+
+           if (restore)
              {
-               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);
-                 }
+               /* Restore the prompt.  */
+               grub_printf ("\n%s", prompt_translated);
+               init_clterm_all ();
+               cl_print_all (0, 0);
              }
-             break;
 
-           case 11:    /* Ctrl-k */
-             if (lpos < llen)
-               {
-                 if (kill_buf)
-                   grub_free (kill_buf);
+           if (insert)
+             {
+               cl_insert (insert);
+               grub_free (insert);
+             }
+         }
+         break;
 
-                 kill_buf = grub_strdup (buf + lpos);
-                 grub_errno = GRUB_ERR_NONE;
+       case 11:        /* Ctrl-k */
+         if (lpos < llen)
+           {
+             if (kill_buf)
+               grub_free (kill_buf);
 
-                 cl_delete (llen - lpos);
-               }
-             break;
+             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;
 
-           case 14:    /* Ctrl-n */
+           if (histpos > 0)
              {
-               char *hist;
+               grub_history_replace (histpos, buf);
+               histpos--;
+             }
 
-               lpos = 0;
+           cl_delete (llen);
+           hist = grub_history_get (histpos);
+           cl_insert (hist);
 
-               if (histpos > 0)
-                 {
-                   grub_history_replace (histpos, buf);
-                   histpos--;
-                 }
+           break;
+         }
+       case 16:        /* Ctrl-p */
+         {
+           grub_uint32_t *hist;
 
-               cl_delete (llen);
-               hist = grub_history_get (histpos);
-               cl_insert (hist);
+           lpos = 0;
 
-               break;
-             }
-           case 16:    /* Ctrl-p */
+           if (histpos < hist_used - 1)
              {
-               char *hist;
+               grub_history_replace (histpos, buf);
+               histpos++;
+             }
 
-               lpos = 0;
+           cl_delete (llen);
+           hist = grub_history_get (histpos);
 
-               if (histpos < hist_used - 1)
-                 {
-                   grub_history_replace (histpos, buf);
-                   histpos++;
-                 }
+           cl_insert (hist);
+         }
+         break;
 
-               cl_delete (llen);
-               hist = grub_history_get (histpos);
+       case 21:        /* Ctrl-u */
+         if (lpos > 0)
+           {
+             grub_size_t n = lpos;
 
-               cl_insert (hist);
-             }
-             break;
+             if (kill_buf)
+               grub_free (kill_buf);
 
-           case 21:    /* Ctrl-u */
-             if (lpos > 0)
+             kill_buf = grub_malloc (n + 1);
+             grub_errno = GRUB_ERR_NONE;
+             if (kill_buf)
                {
-                 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);
+                 grub_memcpy (kill_buf, buf, n);
+                 kill_buf[n] = '\0';
                }
-             break;
 
-           case 25:    /* Ctrl-y */
-             if (kill_buf)
-               cl_insert (kill_buf);
-             break;
+             lpos = 0;
+             cl_set_pos_all ();
+             cl_delete (n);
            }
-       }
+         break;
+
+       case 25:        /* Ctrl-y */
+         if (kill_buf)
+           cl_insert (kill_buf);
+         break;
 
-      switch (key)
-       {
        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);
 }
index 0b9868d3bbd1d748d951ce9a5e99ceac79d8970d..63bd889a5b99ec2bca5285d4edc691ebca06ae50 100644 (file)
@@ -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);
 }
index e8dfb182bcdb7a3645e910369306ba281942d333..42098e682c9648ed320e164da79c42ce647840d0 100644 (file)
@@ -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 (file)
index 0000000..73eab54
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+/* 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);
+}
index 66475d456ec0ef453d62b75d50584fbdeb81f4c2..b54e2f6f184fcb7d136428206e439807f6dd36be 100644 (file)
@@ -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);
 }