Merge multiterm branch

This commit is contained in:
Robert Millan 2010-01-09 22:49:18 +00:00
commit cdb3f378d6
51 changed files with 3046 additions and 1656 deletions

109
ChangeLog
View file

@ -1,3 +1,112 @@
2010-01-07 Vladimir Serbinenko <phcoder@gmail.com>
2010-01-09 Robert Millan <rmh.grub@aybabtu.com>
Support for multiple terminals.
* Makefile.in (pkglib_DATA): terminal.lst.
(terminal.lst): New target.
* commands/handler.c (grub_cmd_handler): Don't handle terminals.
(GRUB_MOD_INIT(handler)): Likewise.
(GRUB_MOD_FINI(handler)): Likewise.
* commands/help.c (grub_cmd_help): Handle multiple terminals.
* commands/keystatus.c (grub_cmd_keystatus): Likewise.
* commands/sleep.c (do_print): Use grub_term_restore_pos.
(grub_cmd_sleep): Use grub_term_save_pos.
* commands/terminal.c: New file.
* conf/any-emu.rmk (grub_emu_SOURCES): Add normal/term.c
commands/terminal.c and lib/charset.c.
* conf/common.rmk (normal_mod_SOURCES): Add normal/term.c.
(pkglib_MODULES): Add terminal.mod.
(terminal_mod_SOURCES): New variable.
(terminal_mod_CFLAGS): Likewise.
(terminal_mod_LDFLAGS): Likewise.
* genhandlerlist.sh: Don't handle terminals.
* genmk.rb: Generate terminal-*.lst.
* genterminallist.sh: New file.
* include/grub/charset.h (grub_ucs4_to_utf8_alloc): New proto.
(grub_is_valid_utf8): Likewise.
(grub_utf8_to_ucs4_alloc): Likewise.
* include/grub/menu_viewer.h (grub_menu_viewer): Rewritten.
(grub_menu_register_viewer): Changed argument.
(grub_menu_try_text): New proto.
(grub_gfxmenu_try_hook): New declaration.
* include/grub/normal.h (grub_normal_exit_level): New declaration.
(grub_menu_init_page): Additional argument term.
(grub_normal_init_page): Likewise.
(grub_cmdline_get): Arguments simplified.
(grub_utf8_to_ucs4_alloc): Removed.
(grub_print_ucs4): Additional argument term.
(grub_getstringwidth): Likewise.
(grub_print_message_indented): Likewise.
(grub_menu_text_register_instances): New proto.
(grub_show_menu): Likewise.
(read_terminal_list): Likewise.
(grub_set_more): Likewise.
* include/grub/parser.h: Include handler.h.
* include/grub/reader.h: Rewritten.
* include/grub/term.h (GRUB_TERM_NEED_INIT): Removed.
(GRUB_TERM_WIDTH): Changed to function.
(GRUB_TERM_HEIGHT): Likewise.
(GRUB_TERM_BORDER_WIDTH): Likewise.
(GRUB_TERM_BORDER_HEIGHT): Likewise.
(GRUB_TERM_NUM_ENTRIES): Likewise.
(GRUB_TERM_ENTRY_WIDTH): Likewise.
(GRUB_TERM_CURSOR_X): Likewise.
(grub_term_input_class): Likewise.
(grub_term_output_class): Likewise.
(grub_term_outputs_disabled): New declaration.
(grub_term_inputs_disabled): Likewise.
(grub_term_outputs): Likewise.
(grub_term_inputs): Likewise.
(grub_term_register_input): Rewritten.
(grub_term_register_output): Likewise.
(grub_term_unregister_input): Likewise.
(grub_term_unregister_output): Likewise.
(FOR_ACTIVE_TERM_INPUTS): New macro.
(FOR_DISABLED_TERM_INPUTS): Likewise.
(FOR_ACTIVE_TERM_OUTPUTS): Likewise.
(FOR_DISABLED_TERM_OUTPUTS): Likewise.
* include/grub/terminfo.h: Add oterm argument to all protypes.
* kern/main.c (grub_main): Don't call grub_register_rescue_reader.
Use grub_rescue_run.
* kern/misc.c (grub_utf8_to_ucs4): Put '?' for invalid characters.
All users updated.
* kern/reader.c: Removed. All users updated.
* kern/rescue_reader.c (grub_rescue_init): Removed.
(grub_rescue_reader): Likewise.
(grub_register_rescue_reader): Likewise.
(grub_rescue_run): New function based on kern/reader.c.
* kern/term.c: Adapted for multiterm.
* lib/charset.c (grub_ucs4_to_utf8_alloc): New function.
(grub_is_valid_utf8): Likewise.
(grub_utf8_to_ucs4_alloc): Moved from normal/menu_text.c.
* loader/i386/efi/linux.c (grub_cmd_linux): Retrieve parameters of
right terminal.
* loader/i386/linux.c (grub_linux_boot): Likewise.
* normal/auth.c (grub_username_get): New function.
(grub_auth_check_authentication): Use grub_username_get.
* normal/cmdline.c: Changed to UCS4. Adapted for multiterm.
* normal/color.c: Adapt for multiterm.
* normal/main.c (read_config_file): Don't use grub_reader_loop.
(grub_normal_init_page): Additional argument term.
(read_lists): Call read_terminal_lists.
(grub_enter_normal_mode): Call grub_cmdline_run.
Handle grub_normal_exit_level.
(grub_cmd_normal): Make reentrant.
(grub_cmd_normal_exit): New function.
(grub_normal_reader_init): Additional argument nested. Handle multiterm.
* normal/menu.c: Adapt for multiterm.
* normal/menu_entry.c: Likewise.
* normal/menu_text.c: Likewise.
* normal/menu_viewer.c: Removed. All users updated.
* normal/term.c: New file.
* util/console.c: Change order of includes to workaround a bug in
ncurses headers.
* term/terminfo.c: New argument oterm on all exported functions.
All users updated.
* util/grub-editenv.c (grub_term_input_class): Removed.
(grub_term_output_class): Likewise.
2010-01-09 Robert Millan <rmh.grub@aybabtu.com> 2010-01-09 Robert Millan <rmh.grub@aybabtu.com>
Make loader output a bit more user-friendly. Make loader output a bit more user-friendly.

View file

@ -174,7 +174,7 @@ endif
### General targets. ### General targets.
CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) po/*.mo CLEANFILES += $(pkglib_DATA) $(pkgdata_DATA) po/*.mo
pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst pkglib_DATA += moddep.lst command.lst fs.lst partmap.lst parttool.lst handler.lst video.lst crypto.lst terminal.lst
moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk moddep.lst: $(DEFSYMFILES) $(UNDSYMFILES) genmoddep.awk
cat $(DEFSYMFILES) /dev/null \ cat $(DEFSYMFILES) /dev/null \
| $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \ | $(AWK) -f $(srcdir)/genmoddep.awk $(UNDSYMFILES) > $@ \
@ -192,6 +192,9 @@ partmap.lst: $(PARTMAPFILES)
handler.lst: $(HANDLERFILES) handler.lst: $(HANDLERFILES)
cat $^ /dev/null | sort > $@ cat $^ /dev/null | sort > $@
terminal.lst: $(TERMINALFILES)
cat $^ /dev/null | sort > $@
parttool.lst: $(PARTTOOLFILES) parttool.lst: $(PARTTOOLFILES)
cat $^ /dev/null | sort | uniq > $@ cat $^ /dev/null | sort | uniq > $@

View file

@ -26,10 +26,9 @@
#include <grub/i18n.h> #include <grub/i18n.h>
static grub_err_t static grub_err_t
grub_cmd_handler (struct grub_command *cmd, grub_cmd_handler (struct grub_command *cmd __attribute__ ((unused)),
int argc, char **args) int argc, char **args)
{ {
char *class_name;
void *curr_item = 0; void *curr_item = 0;
grub_handler_class_t head; grub_handler_class_t head;
@ -44,23 +43,19 @@ grub_cmd_handler (struct grub_command *cmd,
return 0; return 0;
} }
class_name = (grub_strcmp (cmd->name, "handler")) ? (char *) cmd->name : 0;
head = grub_handler_class_list; head = grub_handler_class_list;
if ((argc == 0) && (class_name == 0)) if (argc == 0)
{ {
grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_item); grub_list_iterate (GRUB_AS_LIST (head), (grub_list_hook_t) list_item);
} }
else else
{ {
char *class_name;
grub_handler_class_t class; grub_handler_class_t class;
if (class_name == 0) class_name = args[0];
{ argc--;
class_name = args[0]; args++;
argc--;
args++;
}
class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name); class = grub_named_list_find (GRUB_AS_NAMED_LIST (head), class_name);
if (! class) if (! class)
@ -90,7 +85,7 @@ grub_cmd_handler (struct grub_command *cmd,
return 0; return 0;
} }
static grub_command_t cmd_handler, cmd_terminal_input, cmd_terminal_output; static grub_command_t cmd_handler;
GRUB_MOD_INIT(handler) GRUB_MOD_INIT(handler)
{ {
@ -98,19 +93,9 @@ GRUB_MOD_INIT(handler)
grub_register_command ("handler", grub_cmd_handler, grub_register_command ("handler", grub_cmd_handler,
N_("[class [handler]]"), N_("[class [handler]]"),
N_("List or select a handler.")); N_("List or select a handler."));
cmd_terminal_input =
grub_register_command ("terminal_input", grub_cmd_handler,
N_("[handler]"),
N_("List or select an input terminal."));
cmd_terminal_output =
grub_register_command ("terminal_output", grub_cmd_handler,
N_("[handler]"),
N_("List or select an output terminal."));
} }
GRUB_MOD_FINI(handler) GRUB_MOD_FINI(handler)
{ {
grub_unregister_command (cmd_handler); grub_unregister_command (cmd_handler);
grub_unregister_command (cmd_terminal_input);
grub_unregister_command (cmd_terminal_output);
} }

View file

@ -24,6 +24,7 @@
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/normal.h> #include <grub/normal.h>
#include <grub/charset.h>
static grub_err_t static grub_err_t
grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
@ -40,12 +41,11 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) && if ((cmd->prio & GRUB_PRIO_LIST_FLAG_ACTIVE) &&
(cmd->flags & GRUB_COMMAND_FLAG_CMDLINE)) (cmd->flags & GRUB_COMMAND_FLAG_CMDLINE))
{ {
struct grub_term_output *term;
const char *summary_translated = _(cmd->summary);
char *command_help; char *command_help;
int stringwidth;
grub_uint32_t *unicode_command_help; grub_uint32_t *unicode_command_help;
grub_uint32_t *unicode_last_position; grub_uint32_t *unicode_last_position;
grub_uint32_t *unicode_last_screen_position;
const char *summary_translated = _(cmd->summary);
command_help = grub_malloc (grub_strlen (cmd->name) + command_help = grub_malloc (grub_strlen (cmd->name) +
sizeof (" ") - 1 + sizeof (" ") - 1 +
@ -55,28 +55,34 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
grub_utf8_to_ucs4_alloc (command_help, &unicode_command_help, grub_utf8_to_ucs4_alloc (command_help, &unicode_command_help,
&unicode_last_position); &unicode_last_position);
unicode_last_screen_position = unicode_command_help;
stringwidth = 0; FOR_ACTIVE_TERM_OUTPUTS(term)
{
unsigned stringwidth;
grub_uint32_t *unicode_last_screen_position;
while (unicode_last_screen_position < unicode_last_position && unicode_last_screen_position = unicode_command_help;
stringwidth < ((GRUB_TERM_WIDTH / 2) - 2))
{
stringwidth += grub_getcharwidth (*unicode_last_screen_position);
unicode_last_screen_position++;
}
grub_print_ucs4 (unicode_command_help, unicode_last_screen_position); stringwidth = 0;
if ((cnt++) % 2) while (unicode_last_screen_position < unicode_last_position &&
{ stringwidth < ((grub_term_width (term) / 2) - 2))
grub_putchar ('\n'); {
} stringwidth
else += grub_term_getcharwidth (term,
{ *unicode_last_screen_position);
grub_print_spaces (GRUB_TERM_WIDTH / 2 - stringwidth); unicode_last_screen_position++;
} }
grub_print_ucs4 (unicode_command_help,
unicode_last_screen_position, term);
if (!(cnt % 2))
grub_print_spaces (term, grub_term_width (term) / 2
- stringwidth);
}
if (cnt % 2)
grub_printf ("\n");
cnt++;
grub_free (command_help); grub_free (command_help);
grub_free (unicode_command_help); grub_free (unicode_command_help);
@ -104,7 +110,11 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc,
} }
if (argc == 0) if (argc == 0)
grub_command_iterate (print_command_info); {
grub_command_iterate (print_command_info);
if (!(cnt % 2))
grub_printf ("\n");
}
else else
{ {
int i; int i;

View file

@ -49,13 +49,24 @@ grub_cmd_keystatus (grub_extcmd_t cmd,
if (state[2].set) if (state[2].set)
expect_mods |= GRUB_TERM_STATUS_ALT; expect_mods |= GRUB_TERM_STATUS_ALT;
grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods);
/* Without arguments, just check whether getkeystatus is supported at /* Without arguments, just check whether getkeystatus is supported at
all. */ all. */
if (!grub_cur_term_input->getkeystatus) if (expect_mods == 0)
return grub_error (GRUB_ERR_TEST_FAILURE, "false"); {
grub_dprintf ("keystatus", "expect_mods: %d\n", expect_mods); grub_term_input_t term;
if (!expect_mods) int nterms = 0;
return 0;
FOR_ACTIVE_TERM_INPUTS (term)
if (!term->getkeystatus)
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
else
nterms++;
if (!nterms)
return grub_error (GRUB_ERR_TEST_FAILURE, "false");
return 0;
}
mods = grub_getkeystatus (); mods = grub_getkeystatus ();
grub_dprintf ("keystatus", "mods: %d\n", mods); grub_dprintf ("keystatus", "mods: %d\n", mods);

View file

@ -33,12 +33,12 @@ static const struct grub_arg_option options[] =
{0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0}
}; };
static grub_uint8_t x, y; static grub_uint16_t *pos;
static void static void
do_print (int n) do_print (int n)
{ {
grub_gotoxy (x, y); grub_term_restore_pos (pos);
/* NOTE: Do not remove the trailing space characters. /* NOTE: Do not remove the trailing space characters.
They are required to clear the line. */ They are required to clear the line. */
grub_printf ("%d ", n); grub_printf ("%d ", n);
@ -64,7 +64,6 @@ static grub_err_t
grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args) grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args)
{ {
struct grub_arg_list *state = cmd->state; struct grub_arg_list *state = cmd->state;
grub_uint16_t xy;
int n; int n;
if (argc != 1) if (argc != 1)
@ -78,9 +77,7 @@ grub_cmd_sleep (grub_extcmd_t cmd, int argc, char **args)
return 0; return 0;
} }
xy = grub_getxy (); pos = grub_term_save_pos ();
x = xy >> 8;
y = xy & 0xff;
for (; n; n--) for (; n; n--)
{ {

364
commands/terminal.c Normal file
View file

@ -0,0 +1,364 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/>.
*/
#include <grub/mm.h>
#include <grub/dl.h>
#include <grub/command.h>
#include <grub/term.h>
#include <grub/i18n.h>
#include <grub/misc.h>
struct grub_term_autoload *grub_term_input_autoload = NULL;
struct grub_term_autoload *grub_term_output_autoload = NULL;
static grub_err_t
grub_cmd_terminal_input (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
int i;
grub_term_input_t term;
struct grub_term_autoload *aut;
if (argc == 0)
{
grub_puts_ (N_ ("Active input terminals:"));
FOR_ACTIVE_TERM_INPUTS(term)
grub_printf ("%s ", term->name);
grub_printf ("\n");
grub_puts_ (N_ ("Available input terminals:"));
FOR_DISABLED_TERM_INPUTS(term)
grub_printf ("%s ", term->name);
/* This is quadratic but we don't expect mode than 30 terminal
modules ever. */
for (aut = grub_term_input_autoload; aut; aut = aut->next)
{
FOR_DISABLED_TERM_INPUTS(term)
if (grub_strcmp (term->name, aut->name) == 0)
break;
if (!term)
FOR_ACTIVE_TERM_INPUTS(term)
if (grub_strcmp (term->name, aut->name) == 0)
break;
if (!term)
grub_printf ("%s ", aut->name);
}
grub_printf ("\n");
return GRUB_ERR_NONE;
}
i = 0;
if (grub_strcmp (args[0], "--append") == 0
|| grub_strcmp (args[0], "--remove") == 0)
i++;
if (i == argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
for (; i < argc; i++)
{
int again = 0;
while (1)
{
FOR_DISABLED_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term == 0)
FOR_ACTIVE_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
break;
if (again)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
args[i]);
for (aut = grub_term_input_autoload; aut; aut = aut->next)
if (grub_strcmp (args[i], aut->name) == 0)
{
grub_dl_t mod;
mod = grub_dl_load (aut->modname);
if (mod)
grub_dl_ref (mod);
grub_errno = GRUB_ERR_NONE;
break;
}
if (!aut)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
args[i]);
again = 1;
}
}
if (grub_strcmp (args[0], "--append") == 0)
{
for (i = 1; i < argc; i++)
{
FOR_DISABLED_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)),
GRUB_AS_LIST (term));
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
if (grub_strcmp (args[0], "--remove") == 0)
{
for (i = 1; i < argc; i++)
{
FOR_ACTIVE_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
if (!term->next && term == grub_term_inputs)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)),
GRUB_AS_LIST (term));
if (term->fini)
term->fini ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
for (i = 0; i < argc; i++)
{
FOR_DISABLED_TERM_INPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs_disabled)),
GRUB_AS_LIST (term));
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs),
GRUB_AS_LIST (term));
}
}
FOR_ACTIVE_TERM_INPUTS(term)
{
for (i = 0; i < argc; i++)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (i == argc)
{
if (!term->next && term == grub_term_inputs)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_inputs)),
GRUB_AS_LIST (term));
if (term->fini)
term->fini ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
static grub_err_t
grub_cmd_terminal_output (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
int i;
grub_term_output_t term;
struct grub_term_autoload *aut;
if (argc == 0)
{
grub_puts_ (N_ ("Active output terminals:"));
FOR_ACTIVE_TERM_OUTPUTS(term)
grub_printf ("%s ", term->name);
grub_printf ("\n");
grub_puts_ (N_ ("Available output terminals:"));
FOR_DISABLED_TERM_OUTPUTS(term)
grub_printf ("%s ", term->name);
/* This is quadratic but we don't expect mode than 30 terminal
modules ever. */
for (aut = grub_term_output_autoload; aut; aut = aut->next)
{
FOR_DISABLED_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, aut->name) == 0)
break;
if (!term)
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, aut->name) == 0)
break;
if (!term)
grub_printf ("%s ", aut->name);
}
grub_printf ("\n");
return GRUB_ERR_NONE;
}
i = 0;
if (grub_strcmp (args[0], "--append") == 0
|| grub_strcmp (args[0], "--remove") == 0)
i++;
if (i == argc)
return grub_error (GRUB_ERR_BAD_ARGUMENT, N_ ("no terminal specified"));
for (; i < argc; i++)
{
int again = 0;
while (1)
{
FOR_DISABLED_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term == 0)
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
break;
if (again)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
args[i]);
for (aut = grub_term_output_autoload; aut; aut = aut->next)
if (grub_strcmp (args[i], aut->name) == 0)
{
grub_dl_t mod;
mod = grub_dl_load (aut->modname);
if (mod)
grub_dl_ref (mod);
grub_errno = GRUB_ERR_NONE;
break;
}
if (!aut)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "unknown terminal '%s'\n",
args[i]);
again = 1;
}
}
if (grub_strcmp (args[0], "--append") == 0)
{
for (i = 1; i < argc; i++)
{
FOR_DISABLED_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
GRUB_AS_LIST (term));
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
if (grub_strcmp (args[0], "--remove") == 0)
{
for (i = 1; i < argc; i++)
{
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
if (!term->next && term == grub_term_outputs)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)),
GRUB_AS_LIST (term));
if (term->fini)
term->fini ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
for (i = 0; i < argc; i++)
{
FOR_DISABLED_TERM_OUTPUTS(term)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (term)
{
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
GRUB_AS_LIST (term));
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
GRUB_AS_LIST (term));
}
}
FOR_ACTIVE_TERM_OUTPUTS(term)
{
for (i = 0; i < argc; i++)
if (grub_strcmp (args[i], term->name) == 0)
break;
if (i == argc)
{
if (!term->next && term == grub_term_outputs)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"can't remove the last terminal");
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs)),
GRUB_AS_LIST (term));
if (term->fini)
term->fini ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
GRUB_AS_LIST (term));
}
}
return GRUB_ERR_NONE;
}
static grub_command_t cmd_terminal_input, cmd_terminal_output;
GRUB_MOD_INIT(terminal)
{
cmd_terminal_input =
grub_register_command ("terminal_input", grub_cmd_terminal_input,
"[--append|--remove] "
"[TERMINAL1] [TERMINAL2] ...",
"List or select an input terminal.");
cmd_terminal_output =
grub_register_command ("terminal_output", grub_cmd_terminal_output,
"[--append|--remove] "
"[TERMINAL1] [TERMINAL2] ...",
"List or select an output terminal.");
}
GRUB_MOD_FINI(terminal)
{
grub_unregister_command (cmd_terminal_input);
grub_unregister_command (cmd_terminal_output);
}

View file

@ -28,8 +28,9 @@ grub_emu_SOURCES = commands/minicmd.c commands/cat.c commands/cmp.c \
lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c \ lib/arg.c normal/cmdline.c normal/datetime.c normal/misc.c \
normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c \ normal/handler.c normal/auth.c lib/crypto.c normal/autofs.c \
normal/completion.c normal/main.c normal/color.c \ normal/completion.c normal/main.c normal/color.c \
normal/menu.c normal/menu_entry.c normal/menu_viewer.c \ normal/menu.c normal/menu_entry.c \
normal/menu_text.c normal/crypto.c \ normal/menu_text.c normal/crypto.c normal/term.c \
commands/terminal.c lib/charset.c \
script/main.c script/execute.c script/function.c \ script/main.c script/execute.c script/function.c \
script/lexer.c script/script.c grub_script.tab.c \ script/lexer.c script/script.c grub_script.tab.c \
partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \ partmap/amiga.c partmap/apple.c partmap/msdos.c partmap/sun.c \

View file

@ -549,8 +549,8 @@ keystatus_mod_LDFLAGS = $(COMMON_LDFLAGS)
normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \ normal_mod_SOURCES = normal/main.c normal/cmdline.c normal/dyncmd.c \
normal/auth.c normal/autofs.c normal/handler.c \ normal/auth.c normal/autofs.c normal/handler.c \
normal/color.c normal/completion.c normal/datetime.c normal/menu.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/menu_entry.c normal/menu_text.c \
normal/misc.c normal/crypto.c normal/misc.c normal/crypto.c normal/term.c
normal_mod_CFLAGS = $(COMMON_CFLAGS) normal_mod_CFLAGS = $(COMMON_CFLAGS)
normal_mod_LDFLAGS = $(COMMON_LDFLAGS) normal_mod_LDFLAGS = $(COMMON_LDFLAGS)
@ -651,6 +651,11 @@ charset_mod_SOURCES = lib/charset.c
charset_mod_CFLAGS = $(COMMON_CFLAGS) charset_mod_CFLAGS = $(COMMON_CFLAGS)
charset_mod_LDFLAGS = $(COMMON_LDFLAGS) charset_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += terminal.mod
terminal_mod_SOURCES = commands/terminal.c
terminal_mod_CFLAGS = $(COMMON_CFLAGS)
terminal_mod_LDFLAGS = $(COMMON_LDFLAGS)
pkglib_MODULES += crypto.mod pkglib_MODULES += crypto.mod
crypto_mod_SOURCES = lib/crypto.c crypto_mod_SOURCES = lib/crypto.c
crypto_mod_CFLAGS = $(COMMON_CFLAGS) crypto_mod_CFLAGS = $(COMMON_CFLAGS)

View file

@ -21,7 +21,7 @@ kernel_img_SOURCES = kern/i386/coreboot/startup.S \
kern/i386/halt.c \ kern/i386/halt.c \
kern/main.c kern/device.c \ kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
kern/misc.c kern/mm.c kern/reader.c kern/term.c \ kern/misc.c kern/mm.c kern/term.c \
kern/rescue_parser.c kern/rescue_reader.c \ kern/rescue_parser.c kern/rescue_reader.c \
kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \
@ -65,7 +65,7 @@ kernel_img_SOURCES = kern/i386/qemu/startup.S \
kern/i386/halt.c \ kern/i386/halt.c \
kern/main.c kern/device.c \ kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
kern/misc.c kern/mm.c kern/reader.c kern/term.c \ kern/misc.c kern/mm.c kern/term.c \
kern/rescue_parser.c kern/rescue_reader.c \ kern/rescue_parser.c kern/rescue_reader.c \
kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \

View file

@ -39,7 +39,7 @@ pkglib_MODULES = kernel.img chain.mod appleldr.mod \
kernel_img_EXPORTS = no kernel_img_EXPORTS = no
kernel_img_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \ kernel_img_SOURCES = kern/i386/efi/startup.S kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
kern/misc.c kern/mm.c kern/reader.c kern/term.c \ kern/misc.c kern/mm.c kern/term.c \
kern/rescue_parser.c kern/rescue_reader.c \ kern/rescue_parser.c kern/rescue_reader.c \
kern/$(target_cpu)/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/$(target_cpu)/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \

View file

@ -19,7 +19,7 @@ kernel_img_SOURCES = kern/i386/ieee1275/startup.S \
kern/ieee1275/cmain.c kern/ieee1275/openfw.c \ kern/ieee1275/cmain.c kern/ieee1275/openfw.c \
kern/main.c kern/device.c \ kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
kern/misc.c kern/mm.c kern/reader.c kern/term.c \ kern/misc.c kern/mm.c kern/term.c \
kern/rescue_parser.c kern/rescue_reader.c \ kern/rescue_parser.c kern/rescue_reader.c \
kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \ kern/$(target_cpu)/dl.c kern/parser.c kern/partition.c \
kern/env.c \ kern/env.c \

View file

@ -48,7 +48,7 @@ kernel_img_SOURCES = kern/i386/pc/startup.S \
kern/i386/misc.S \ kern/i386/misc.S \
kern/main.c kern/device.c \ kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
kern/misc.c kern/mm.c kern/reader.c kern/term.c \ kern/misc.c kern/mm.c kern/term.c \
kern/rescue_parser.c kern/rescue_reader.c \ kern/rescue_parser.c kern/rescue_reader.c \
kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/time.c kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
kern/$(target_cpu)/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \ kern/$(target_cpu)/dl.c kern/i386/pc/init.c kern/i386/pc/mmap.c \

View file

@ -31,7 +31,7 @@ pkglib_PROGRAMS = kernel.img
kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \ kernel_img_SOURCES = kern/powerpc/ieee1275/startup.S kern/ieee1275/cmain.c \
kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ kern/ieee1275/ieee1275.c kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \
kern/misc.c kern/mm.c kern/reader.c kern/term.c \ kern/misc.c kern/mm.c kern/term.c \
kern/rescue_parser.c kern/rescue_reader.c \ kern/rescue_parser.c kern/rescue_reader.c \
kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
kern/ieee1275/init.c \ kern/ieee1275/init.c \

View file

@ -35,7 +35,7 @@ kernel_img_HEADERS = boot.h cache.h device.h disk.h dl.h elf.h elfload.h \
kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \ kernel_img_SOURCES = kern/sparc64/ieee1275/crt0.S kern/ieee1275/cmain.c \
kern/ieee1275/ieee1275.c kern/main.c kern/device.c \ kern/ieee1275/ieee1275.c kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \ kern/disk.c kern/dl.c kern/err.c kern/file.c kern/fs.c \
kern/misc.c kern/mm.c kern/reader.c kern/term.c \ kern/misc.c kern/mm.c kern/term.c \
kern/rescue_parser.c kern/rescue_reader.c \ kern/rescue_parser.c kern/rescue_reader.c \
kern/list.c kern/handler.c kern/command.c kern/corecmd.c \ kern/list.c kern/handler.c kern/command.c kern/corecmd.c \
kern/sparc64/ieee1275/ieee1275.c \ kern/sparc64/ieee1275/ieee1275.c \

View file

@ -39,7 +39,7 @@ kernel_img_EXPORTS = no
kernel_img_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \ kernel_img_SOURCES = kern/x86_64/efi/startup.S kern/x86_64/efi/callwrap.S \
kern/main.c kern/device.c \ kern/main.c kern/device.c \
kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \ kern/disk.c kern/dl.c kern/file.c kern/fs.c kern/err.c \
kern/misc.c kern/mm.c kern/reader.c kern/term.c \ kern/misc.c kern/mm.c kern/term.c \
kern/rescue_parser.c kern/rescue_reader.c \ kern/rescue_parser.c kern/rescue_reader.c \
kern/$(target_cpu)/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \ kern/$(target_cpu)/dl.c kern/i386/efi/init.c kern/parser.c kern/partition.c \
kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \ kern/env.c symlist.c kern/efi/efi.c kern/efi/init.c kern/efi/mm.c \

View file

@ -16,8 +16,4 @@
module=$1 module=$1
grep -v "^#" | sed -n \ grep -v "^#" | sed -n \
-e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}" \ -e "/grub_parser_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/parser.\1: $module/;p;}"
-e "/grub_reader_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/reader.\1: $module/;p;}" \
-e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/terminal_input.\1: $module/;p;}" \
-e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/terminal_output.\1: $module/;p;}" \
-e "/grub_menu_viewer_register *( *\"/{s/.*( *\"\([^\"]*\)\".*/menu_viewer.\1: $module/;p;}"

View file

@ -192,6 +192,7 @@ endif
fs = 'fs-' + obj.suffix('lst') fs = 'fs-' + obj.suffix('lst')
partmap = 'partmap-' + obj.suffix('lst') partmap = 'partmap-' + obj.suffix('lst')
handler = 'handler-' + obj.suffix('lst') handler = 'handler-' + obj.suffix('lst')
terminal = 'terminal-' + obj.suffix('lst')
parttool = 'parttool-' + obj.suffix('lst') parttool = 'parttool-' + obj.suffix('lst')
video = 'video-' + obj.suffix('lst') video = 'video-' + obj.suffix('lst')
dep = deps[i] dep = deps[i]
@ -213,6 +214,7 @@ FSFILES += #{fs}
PARTTOOLFILES += #{parttool} PARTTOOLFILES += #{parttool}
PARTMAPFILES += #{partmap} PARTMAPFILES += #{partmap}
HANDLERFILES += #{handler} HANDLERFILES += #{handler}
TERMINALFILES += #{terminal}
VIDEOFILES += #{video} VIDEOFILES += #{video}
#{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh #{command}: #{src} $(#{src}_DEPENDENCIES) gencmdlist.sh
@ -240,6 +242,11 @@ VIDEOFILES += #{video}
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
| sh $(srcdir)/genhandlerlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1) | sh $(srcdir)/genhandlerlist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
#{terminal}: #{src} $(#{src}_DEPENDENCIES) genterminallist.sh
set -e; \
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \
| sh $(srcdir)/genterminallist.sh #{symbolic_name} > $@ || (rm -f $@; exit 1)
#{video}: #{src} $(#{src}_DEPENDENCIES) genvideolist.sh #{video}: #{src} $(#{src}_DEPENDENCIES) genvideolist.sh
set -e; \ set -e; \
$(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \ $(TARGET_CC) -I#{dir} -I$(srcdir)/#{dir} $(TARGET_CPPFLAGS) #{extra_flags} $(TARGET_#{flag}) $(#{prefix}_#{flag}) -E $< \

20
genterminallist.sh Normal file
View file

@ -0,0 +1,20 @@
#! /bin/sh
#
# Copyright (C) 2009,2010 Free Software Foundation, Inc.
#
# This script is free software; the author
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
# Read source code from stdin and detect command names.
module=$1
grep -v "^#" | sed -n \
-e "/grub_term_register_input *( *\"/{s/.*( *\"\([^\"]*\)\".*/i\1: $module/;p;}" \
-e "/grub_term_register_output *( *\"/{s/.*( *\"\([^\"]*\)\".*/o\1: $module/;p;}" \

View file

@ -109,4 +109,13 @@ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src,
return dest; return dest;
} }
/* Convert UCS-4 to UTF-8. */
char *grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size);
int
grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize);
int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position);
#endif #endif

View file

@ -24,20 +24,25 @@
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/menu.h> #include <grub/menu.h>
#include <grub/term.h>
struct grub_menu_viewer struct grub_menu_viewer
{ {
/* The menu viewer name. */
const char *name;
grub_err_t (*show_menu) (grub_menu_t menu, int nested);
struct grub_menu_viewer *next; struct grub_menu_viewer *next;
void *data;
void (*set_chosen_entry) (int entry, void *data);
void (*print_timeout) (int timeout, void *data);
void (*clear_timeout) (void *data);
void (*fini) (void *fini);
}; };
typedef struct grub_menu_viewer *grub_menu_viewer_t;
void grub_menu_viewer_register (grub_menu_viewer_t viewer); void grub_menu_register_viewer (struct grub_menu_viewer *viewer);
grub_err_t grub_menu_viewer_show_menu (grub_menu_t menu, int nested); grub_err_t
grub_menu_try_text (struct grub_term_output *term,
int entry, grub_menu_t menu, int nested);
extern grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu,
int nested);
#endif /* GRUB_MENU_VIEWER_HEADER */ #endif /* GRUB_MENU_VIEWER_HEADER */

View file

@ -199,11 +199,11 @@ int EXPORT_FUNC(grub_sprintf) (char *str, const char *fmt, ...) __attribute__ ((
int EXPORT_FUNC(grub_vsprintf) (char *str, const char *fmt, va_list args); int EXPORT_FUNC(grub_vsprintf) (char *str, const char *fmt, va_list args);
void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_exit) (void) __attribute__ ((noreturn));
void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn)); void EXPORT_FUNC(grub_abort) (void) __attribute__ ((noreturn));
grub_ssize_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest, grub_size_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest,
grub_size_t destsize, grub_size_t destsize,
const grub_uint8_t *src, const grub_uint8_t *src,
grub_size_t srcsize, grub_size_t srcsize,
const grub_uint8_t **srcend); const grub_uint8_t **srcend);
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n, grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
grub_uint32_t d, grub_uint32_t *r); grub_uint32_t d, grub_uint32_t *r);

View file

@ -20,6 +20,7 @@
#ifndef GRUB_NORMAL_HEADER #ifndef GRUB_NORMAL_HEADER
#define GRUB_NORMAL_HEADER 1 #define GRUB_NORMAL_HEADER 1
#include <grub/term.h>
#include <grub/symbol.h> #include <grub/symbol.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/env.h> #include <grub/env.h>
@ -45,21 +46,21 @@ enum grub_completion_type
typedef enum grub_completion_type grub_completion_type_t; typedef enum grub_completion_type grub_completion_type_t;
extern struct grub_menu_viewer grub_normal_text_menu_viewer; extern struct grub_menu_viewer grub_normal_text_menu_viewer;
extern int grub_normal_exit_level;
/* Defined in `main.c'. */ /* Defined in `main.c'. */
void grub_enter_normal_mode (const char *config); void grub_enter_normal_mode (const char *config);
void grub_normal_execute (const char *config, int nested, int batch); void grub_normal_execute (const char *config, int nested, int batch);
void grub_normal_init_page (void); void grub_menu_init_page (int nested, int edit,
void grub_menu_init_page (int nested, int edit); struct grub_term_output *term);
void grub_normal_init_page (struct grub_term_output *term);
grub_err_t grub_normal_add_menu_entry (int argc, const char **args, grub_err_t grub_normal_add_menu_entry (int argc, const char **args,
const char *sourcecode); const char *sourcecode);
char *grub_file_getline (grub_file_t file); char *grub_file_getline (grub_file_t file);
void grub_cmdline_run (int nested); void grub_cmdline_run (int nested);
/* Defined in `cmdline.c'. */ /* Defined in `cmdline.c'. */
int grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len, char *grub_cmdline_get (const char *prompt);
int echo_char, int readline, int history);
grub_err_t grub_set_history (int newsize); grub_err_t grub_set_history (int newsize);
/* Defined in `completion.c'. */ /* Defined in `completion.c'. */
@ -76,14 +77,19 @@ void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name);
/* Defined in `menu_text.c'. */ /* Defined in `menu_text.c'. */
void grub_wait_after_message (void); void grub_wait_after_message (void);
int grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position);
void grub_print_ucs4 (const grub_uint32_t * str, void grub_print_ucs4 (const grub_uint32_t * str,
const grub_uint32_t * last_position); const grub_uint32_t * last_position,
struct grub_term_output *term);
grub_ssize_t grub_getstringwidth (grub_uint32_t * str, grub_ssize_t grub_getstringwidth (grub_uint32_t * str,
const grub_uint32_t * last_position); const grub_uint32_t * last_position,
struct grub_term_output *term);
void grub_print_message_indented (const char *msg, int margin_left, void grub_print_message_indented (const char *msg, int margin_left,
int margin_right); int margin_right,
struct grub_term_output *term);
void
grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested);
grub_err_t
grub_show_menu (grub_menu_t menu, int nested);
/* Defined in `handler.c'. */ /* Defined in `handler.c'. */
void read_handler_list (void); void read_handler_list (void);
@ -97,6 +103,9 @@ void read_fs_list (void);
void read_crypto_list (void); void read_crypto_list (void);
void read_terminal_list (void);
void grub_set_more (int onoff);
#ifdef GRUB_UTIL #ifdef GRUB_UTIL
void grub_normal_init (void); void grub_normal_init (void);

View file

@ -22,6 +22,7 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/handler.h>
#include <grub/reader.h> #include <grub/reader.h>
/* All the states for the command line. */ /* All the states for the command line. */

View file

@ -20,60 +20,10 @@
#ifndef GRUB_READER_HEADER #ifndef GRUB_READER_HEADER
#define GRUB_READER_HEADER 1 #define GRUB_READER_HEADER 1
#include <grub/types.h>
#include <grub/err.h> #include <grub/err.h>
#include <grub/handler.h>
typedef grub_err_t (*grub_reader_getline_t) (char **, int); typedef grub_err_t (*grub_reader_getline_t) (char **, int);
struct grub_reader void grub_rescue_run (void);
{
/* 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);
#endif /* ! GRUB_READER_HEADER */ #endif /* ! GRUB_READER_HEADER */

View file

@ -1,6 +1,6 @@
/* /*
* GRUB -- GRand Unified Bootloader * GRUB -- GRand Unified Bootloader
* Copyright (C) 2002,2003,2005,2007,2008,2009 Free Software Foundation, Inc. * Copyright (C) 2002,2003,2005,2007,2008,2009,2010 Free Software Foundation, Inc.
* *
* GRUB is free software: you can redistribute it and/or modify * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -68,8 +68,6 @@ grub_term_color_state;
#define GRUB_TERM_NO_EDIT (1 << 1) #define GRUB_TERM_NO_EDIT (1 << 1)
/* Set when the terminal cannot do fancy things. */ /* Set when the terminal cannot do fancy things. */
#define GRUB_TERM_DUMB (1 << 2) #define GRUB_TERM_DUMB (1 << 2)
/* Set when the terminal needs to be initialized. */
#define GRUB_TERM_NEED_INIT (1 << 16)
/* Bitmasks for modifier keys returned by grub_getkeystatus. */ /* Bitmasks for modifier keys returned by grub_getkeystatus. */
@ -93,10 +91,6 @@ grub_term_color_state;
/* Menu-related geometrical constants. */ /* 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. */ /* The number of lines of "GRUB version..." at the top. */
#define GRUB_TERM_INFO_HEIGHT 1 #define GRUB_TERM_INFO_HEIGHT 1
@ -113,37 +107,12 @@ grub_term_color_state;
/* The X position of the left border. */ /* The X position of the left border. */
#define GRUB_TERM_LEFT_BORDER_X GRUB_TERM_MARGIN #define GRUB_TERM_LEFT_BORDER_X GRUB_TERM_MARGIN
/* The width of the border. */
#define GRUB_TERM_BORDER_WIDTH (GRUB_TERM_WIDTH \
- GRUB_TERM_MARGIN * 3 \
- GRUB_TERM_SCROLL_WIDTH)
/* The number of lines of messages at the bottom. */ /* The number of lines of messages at the bottom. */
#define GRUB_TERM_MESSAGE_HEIGHT 8 #define GRUB_TERM_MESSAGE_HEIGHT 8
/* The height of the border. */
#define GRUB_TERM_BORDER_HEIGHT (GRUB_TERM_HEIGHT \
- GRUB_TERM_TOP_BORDER_Y \
- GRUB_TERM_MESSAGE_HEIGHT)
/* The number of entries shown at a time. */
#define GRUB_TERM_NUM_ENTRIES (GRUB_TERM_BORDER_HEIGHT - 2)
/* The Y position of the first entry. */ /* The Y position of the first entry. */
#define GRUB_TERM_FIRST_ENTRY_Y (GRUB_TERM_TOP_BORDER_Y + 1) #define GRUB_TERM_FIRST_ENTRY_Y (GRUB_TERM_TOP_BORDER_Y + 1)
/* The max column number of an entry. The last "-1" is for a
continuation marker. */
#define GRUB_TERM_ENTRY_WIDTH (GRUB_TERM_BORDER_WIDTH - 2 \
- GRUB_TERM_MARGIN * 2 - 1)
/* The standard X position of the cursor. */
#define GRUB_TERM_CURSOR_X (GRUB_TERM_LEFT_BORDER_X \
+ GRUB_TERM_BORDER_WIDTH \
- GRUB_TERM_MARGIN \
- 1)
struct grub_term_input struct grub_term_input
{ {
/* The next terminal. */ /* The next terminal. */
@ -224,86 +193,222 @@ struct grub_term_output
}; };
typedef struct grub_term_output *grub_term_output_t; typedef struct grub_term_output *grub_term_output_t;
extern struct grub_handler_class EXPORT_VAR(grub_term_input_class); extern struct grub_term_output *EXPORT_VAR(grub_term_outputs_disabled);
extern struct grub_handler_class EXPORT_VAR(grub_term_output_class); extern struct grub_term_input *EXPORT_VAR(grub_term_inputs_disabled);
extern struct grub_term_output *EXPORT_VAR(grub_term_outputs);
extern struct grub_term_input *EXPORT_VAR(grub_term_inputs);
static inline void static inline void
grub_term_register_input (const char *name __attribute__ ((unused)), grub_term_register_input (const char *name __attribute__ ((unused)),
grub_term_input_t term) grub_term_input_t term)
{ {
grub_handler_register (&grub_term_input_class, GRUB_AS_HANDLER (term)); if (grub_term_inputs)
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
else
{
/* If this is the first terminal, enable automatically. */
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
}
} }
static inline void static inline void
grub_term_register_output (const char *name __attribute__ ((unused)), grub_term_register_output (const char *name __attribute__ ((unused)),
grub_term_output_t term) grub_term_output_t term)
{ {
grub_handler_register (&grub_term_output_class, GRUB_AS_HANDLER (term)); if (grub_term_outputs)
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs_disabled),
GRUB_AS_LIST (term));
else
{
/* If this is the first terminal, enable automatically. */
if (term->init)
term->init ();
grub_list_push (GRUB_AS_LIST_P (&grub_term_outputs),
GRUB_AS_LIST (term));
}
} }
static inline void static inline void
grub_term_unregister_input (grub_term_input_t term) grub_term_unregister_input (grub_term_input_t term)
{ {
grub_handler_unregister (&grub_term_input_class, GRUB_AS_HANDLER (term)); grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs), GRUB_AS_LIST (term));
grub_list_remove (GRUB_AS_LIST_P (&grub_term_inputs_disabled),
GRUB_AS_LIST (term));
} }
static inline void static inline void
grub_term_unregister_output (grub_term_output_t term) 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));
grub_list_remove (GRUB_AS_LIST_P (&(grub_term_outputs_disabled)),
GRUB_AS_LIST (term));
} }
static inline grub_err_t #define FOR_ACTIVE_TERM_INPUTS(var) for (var = grub_term_inputs; var; var = var->next)
grub_term_set_current_input (grub_term_input_t term) #define FOR_DISABLED_TERM_INPUTS(var) for (var = grub_term_inputs_disabled; var; var = var->next)
{ #define FOR_ACTIVE_TERM_OUTPUTS(var) for (var = grub_term_outputs; var; var = var->next)
return grub_handler_set_current (&grub_term_input_class, #define FOR_DISABLED_TERM_OUTPUTS(var) for (var = grub_term_outputs_disabled; var; var = var->next)
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_putchar) (int c);
void EXPORT_FUNC(grub_putcode) (grub_uint32_t code); void EXPORT_FUNC(grub_putcode) (grub_uint32_t code,
grub_ssize_t EXPORT_FUNC(grub_getcharwidth) (grub_uint32_t code); struct grub_term_output *term);
int EXPORT_FUNC(grub_getkey) (void); int EXPORT_FUNC(grub_getkey) (void);
int EXPORT_FUNC(grub_checkkey) (void); int EXPORT_FUNC(grub_checkkey) (void);
int EXPORT_FUNC(grub_getkeystatus) (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_cls) (void);
void EXPORT_FUNC(grub_setcolorstate) (grub_term_color_state state); 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_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 unsigned grub_term_width (struct grub_term_output *term)
{
return ((term->getwh()&0xFF00)>>8);
}
static inline unsigned grub_term_height (struct grub_term_output *term)
{
return (term->getwh()&0xFF);
}
/* The width of the border. */
static inline unsigned
grub_term_border_width (struct grub_term_output *term)
{
return grub_term_width (term) - GRUB_TERM_MARGIN * 3 - GRUB_TERM_SCROLL_WIDTH;
}
/* The max column number of an entry. The last "-1" is for a
continuation marker. */
static inline int
grub_term_entry_width (struct grub_term_output *term)
{
return grub_term_border_width (term) - 2 - GRUB_TERM_MARGIN * 2 - 1;
}
/* The height of the border. */
static inline unsigned
grub_term_border_height (struct grub_term_output *term)
{
return grub_term_height (term) - GRUB_TERM_TOP_BORDER_Y
- GRUB_TERM_MESSAGE_HEIGHT;
}
/* The number of entries shown at a time. */
static inline int
grub_term_num_entries (struct grub_term_output *term)
{
return grub_term_border_height (term) - 2;
}
static inline int
grub_term_cursor_x (struct grub_term_output *term)
{
return (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term)
- GRUB_TERM_MARGIN - 1);
}
static inline grub_uint16_t
grub_term_getxy (struct grub_term_output *term)
{
return term->getxy ();
}
static inline void static inline void
grub_print_spaces (int number_spaces) grub_term_refresh (struct grub_term_output *term)
{
if (term->refresh)
term->refresh ();
}
static inline void
grub_term_gotoxy (struct grub_term_output *term, grub_uint8_t x, grub_uint8_t y)
{
term->gotoxy (x, y);
}
static inline void
grub_term_setcolorstate (struct grub_term_output *term,
grub_term_color_state state)
{
if (term->setcolorstate)
term->setcolorstate (state);
}
/* Set the normal color and the highlight color. The format of each
color is VGA's. */
static inline void
grub_term_setcolor (struct grub_term_output *term,
grub_uint8_t normal_color, grub_uint8_t highlight_color)
{
if (term->setcolor)
term->setcolor (normal_color, highlight_color);
}
/* Turn on/off the cursor. */
static inline void
grub_term_setcursor (struct grub_term_output *term, int on)
{
if (term->setcursor)
term->setcursor (on);
}
static inline void
grub_term_cls (struct grub_term_output *term)
{
if (term->cls)
(term->cls) ();
else
{
grub_putcode ('\n', term);
grub_term_refresh (term);
}
}
static inline grub_ssize_t
grub_term_getcharwidth (struct grub_term_output *term, grub_uint32_t c)
{
if (term->getcharwidth)
return term->getcharwidth (c);
else
return 1;
}
static inline void
grub_term_getcolor (struct grub_term_output *term,
grub_uint8_t *normal_color, grub_uint8_t *highlight_color)
{
if (term->getcolor)
term->getcolor (normal_color, highlight_color);
else
{
*normal_color = 0x07;
*highlight_color = 0x07;
}
}
extern void (*EXPORT_VAR (grub_newline_hook)) (void);
struct grub_term_autoload
{
struct grub_term_autoload *next;
char *name;
char *modname;
};
extern struct grub_term_autoload *grub_term_input_autoload;
extern struct grub_term_autoload *grub_term_output_autoload;
static inline void
grub_print_spaces (struct grub_term_output *term, int number_spaces)
{ {
while (--number_spaces >= 0) while (--number_spaces >= 0)
grub_putchar (' '); grub_putcode (' ', term);
} }

View file

@ -21,15 +21,17 @@
#include <grub/err.h> #include <grub/err.h>
#include <grub/types.h> #include <grub/types.h>
#include <grub/term.h>
char *grub_terminfo_get_current (void); char *grub_terminfo_get_current (void);
grub_err_t grub_terminfo_set_current (const char *); grub_err_t grub_terminfo_set_current (const char *);
void grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y); void grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y,
void grub_terminfo_cls (void); grub_term_output_t oterm);
void grub_terminfo_reverse_video_on (void); void grub_terminfo_cls (grub_term_output_t oterm);
void grub_terminfo_reverse_video_off (void); void grub_terminfo_reverse_video_on (grub_term_output_t oterm);
void grub_terminfo_cursor_on (void); void grub_terminfo_reverse_video_off (grub_term_output_t oterm);
void grub_terminfo_cursor_off (void); void grub_terminfo_cursor_on (grub_term_output_t oterm);
void grub_terminfo_cursor_off (grub_term_output_t oterm);
#endif /* ! GRUB_TERMINFO_HEADER */ #endif /* ! GRUB_TERMINFO_HEADER */

View file

@ -169,9 +169,8 @@ grub_main (void)
grub_register_core_commands (); grub_register_core_commands ();
grub_register_rescue_parser (); grub_register_rescue_parser ();
grub_register_rescue_reader ();
grub_load_config (); grub_load_config ();
grub_load_normal_mode (); grub_load_normal_mode ();
grub_reader_loop (0); grub_rescue_run ();
} }

View file

@ -892,10 +892,10 @@ grub_sprintf (char *str, const char *fmt, ...)
/* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE /* Convert a (possibly null-terminated) UTF-8 string of at most SRCSIZE
bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string. bytes (if SRCSIZE is -1, it is ignored) in length to a UCS-4 string.
Return the number of characters converted. DEST must be able to hold Return the number of characters converted. DEST must be able to hold
at least DESTSIZE characters. If an invalid sequence is found, return -1. at least DESTSIZE characters.
If SRCEND is not NULL, then *SRCEND is set to the next byte after the If SRCEND is not NULL, then *SRCEND is set to the next byte after the
last byte used in SRC. */ last byte used in SRC. */
grub_ssize_t grub_size_t
grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize, grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
const grub_uint8_t *src, grub_size_t srcsize, const grub_uint8_t *src, grub_size_t srcsize,
const grub_uint8_t **srcend) const grub_uint8_t **srcend)
@ -917,7 +917,8 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
if ((c & 0xc0) != 0x80) if ((c & 0xc0) != 0x80)
{ {
/* invalid */ /* invalid */
return -1; code = '?';
count = 0;
} }
else else
{ {
@ -959,7 +960,11 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
code = c & 0x01; code = c & 0x01;
} }
else else
return -1; {
/* invalid */
code = '?';
count = 0;
}
} }
if (count == 0) if (count == 0)
@ -978,15 +983,14 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
void void
grub_abort (void) grub_abort (void)
{ {
if (grub_term_get_current_output ()) grub_printf ("\nAborted.");
#ifndef GRUB_UTIL
if (grub_term_inputs)
#endif
{ {
grub_printf ("\nAborted."); grub_printf (" Press any key to exit.");
grub_getkey ();
if (grub_term_get_current_input ())
{
grub_printf (" Press any key to exit.");
grub_getkey ();
}
} }
grub_exit (); grub_exit ();

View file

@ -1,49 +0,0 @@
/* reader.c - reader support */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/>.
*/
#include <grub/types.h>
#include <grub/mm.h>
#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);
}
}

View file

@ -19,20 +19,15 @@
#include <grub/types.h> #include <grub/types.h>
#include <grub/reader.h> #include <grub/reader.h>
#include <grub/parser.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/term.h> #include <grub/term.h>
#include <grub/mm.h>
#define GRUB_RESCUE_BUF_SIZE 256 #define GRUB_RESCUE_BUF_SIZE 256
static char linebuf[GRUB_RESCUE_BUF_SIZE]; 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. */ /* Prompt to input a command and read the line. */
static grub_err_t static grub_err_t
grub_rescue_read_line (char **line, int cont) grub_rescue_read_line (char **line, int cont)
@ -74,15 +69,24 @@ grub_rescue_read_line (char **line, int cont)
return 0; return 0;
} }
static struct grub_reader grub_rescue_reader =
{
.name = "rescue",
.init = grub_rescue_init,
.read_line = grub_rescue_read_line
};
void 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);
}
} }

View file

@ -21,79 +21,33 @@
#include <grub/mm.h> #include <grub/mm.h>
#include <grub/misc.h> #include <grub/misc.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/time.h>
/* The amount of lines counted by the pager. */ struct grub_term_output *grub_term_outputs_disabled;
static int grub_more_lines; struct grub_term_input *grub_term_inputs_disabled;
struct grub_term_output *grub_term_outputs;
struct grub_term_input *grub_term_inputs;
/* If the more pager is active. */ void (*grub_newline_hook) (void) = NULL;
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 ()
/* Put a Unicode character. */ /* Put a Unicode character. */
void void
grub_putcode (grub_uint32_t code) grub_putcode (grub_uint32_t code, struct grub_term_output *term)
{ {
int height = grub_getwh () & 255; if (code == '\t' && term->getxy)
if (code == '\t' && grub_cur_term_output->getxy)
{ {
int n; int n;
n = 8 - ((grub_getxy () >> 8) & 7); n = 8 - ((term->getxy () >> 8) & 7);
while (n--) while (n--)
grub_putcode (' '); grub_putcode (' ', term);
return; return;
} }
(grub_cur_term_output->putchar) (code); (term->putchar) (code);
if (code == '\n') if (code == '\n')
{ (term->putchar) ('\r');
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;
}
}
} }
/* Put a character. C is one byte of a UTF-8 stream. /* Put a character. C is one byte of a UTF-8 stream.
@ -104,136 +58,101 @@ grub_putchar (int c)
static grub_size_t size = 0; static grub_size_t size = 0;
static grub_uint8_t buf[6]; static grub_uint8_t buf[6];
grub_uint32_t code; grub_uint32_t code;
grub_ssize_t ret; grub_size_t ret;
buf[size++] = c; buf[size++] = c;
ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0); ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0);
if (ret > 0) if (ret != 0)
{ {
struct grub_term_output *term;
size = 0; size = 0;
grub_putcode (code); FOR_ACTIVE_TERM_OUTPUTS(term)
grub_putcode (code, term);
if (code == '\n' && grub_newline_hook)
grub_newline_hook ();
} }
else if (ret < 0)
{
size = 0;
grub_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 int
grub_getkey (void) grub_getkey (void)
{ {
return (grub_cur_term_input->getkey) (); grub_term_input_t term;
while (1)
{
FOR_ACTIVE_TERM_INPUTS(term)
{
int key = term->checkkey ();
if (key != -1)
return term->getkey ();
}
grub_cpu_idle ();
}
} }
int int
grub_checkkey (void) grub_checkkey (void)
{ {
return (grub_cur_term_input->checkkey) (); grub_term_input_t term;
FOR_ACTIVE_TERM_INPUTS(term)
{
int key = term->checkkey ();
if (key != -1)
return key;
}
return -1;
} }
int int
grub_getkeystatus (void) grub_getkeystatus (void)
{ {
if (grub_cur_term_input->getkeystatus) int status = 0;
return (grub_cur_term_input->getkeystatus) (); grub_term_input_t term;
else
return 0;
}
grub_uint16_t FOR_ACTIVE_TERM_INPUTS(term)
grub_getxy (void) {
{ if (term->getkeystatus)
return (grub_cur_term_output->getxy) (); status |= term->getkeystatus ();
} }
grub_uint16_t return status;
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 void
grub_cls (void) grub_cls (void)
{ {
if ((grub_cur_term_output->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug"))) struct grub_term_output *term;
{
grub_putchar ('\n'); FOR_ACTIVE_TERM_OUTPUTS(term)
grub_refresh (); {
} if ((term->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug")))
else {
(grub_cur_term_output->cls) (); grub_putcode ('\n', term);
grub_term_refresh (term);
}
else
(term->cls) ();
}
} }
void void
grub_setcolorstate (grub_term_color_state state) grub_setcolorstate (grub_term_color_state state)
{ {
if (grub_cur_term_output->setcolorstate) struct grub_term_output *term;
(grub_cur_term_output->setcolorstate) (state);
} FOR_ACTIVE_TERM_OUTPUTS(term)
grub_term_setcolorstate (term, state);
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);
}
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);
}
int
grub_setcursor (int on)
{
int ret = cursor_state;
if (grub_cur_term_output->setcursor)
{
(grub_cur_term_output->setcursor) (on);
cursor_state = on;
}
return ret;
}
int
grub_getcursor (void)
{
return cursor_state;
} }
void void
grub_refresh (void) grub_refresh (void)
{ {
if (grub_cur_term_output->refresh) struct grub_term_output *term;
(grub_cur_term_output->refresh) ();
}
void FOR_ACTIVE_TERM_OUTPUTS(term)
grub_set_more (int onoff) grub_term_refresh (term);
{
if (onoff == 1)
grub_more++;
else
grub_more--;
grub_more_lines = 0;
} }

View file

@ -24,6 +24,8 @@
last byte used in SRC. */ last byte used in SRC. */
#include <grub/charset.h> #include <grub/charset.h>
#include <grub/mm.h>
#include <grub/misc.h>
grub_ssize_t grub_ssize_t
grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize, grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
@ -114,3 +116,154 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
*srcend = src; *srcend = src;
return p - dest; 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 (char *) ret;
}
int
grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize)
{
grub_uint32_t code = 0;
int count = 0;
while (srcsize)
{
grub_uint32_t c = *src++;
if (srcsize != (grub_size_t)-1)
srcsize--;
if (count)
{
if ((c & 0xc0) != 0x80)
{
/* invalid */
return 0;
}
else
{
code <<= 6;
code |= (c & 0x3f);
count--;
}
}
else
{
if (c == 0)
break;
if ((c & 0x80) == 0x00)
code = c;
else if ((c & 0xe0) == 0xc0)
{
count = 1;
code = c & 0x1f;
}
else if ((c & 0xf0) == 0xe0)
{
count = 2;
code = c & 0x0f;
}
else if ((c & 0xf8) == 0xf0)
{
count = 3;
code = c & 0x07;
}
else if ((c & 0xfc) == 0xf8)
{
count = 4;
code = c & 0x03;
}
else if ((c & 0xfe) == 0xfc)
{
count = 5;
code = c & 0x01;
}
else
return 0;
}
}
return 1;
}
int
grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position)
{
grub_size_t msg_len = grub_strlen (msg);
*unicode_msg = grub_malloc (grub_strlen (msg) * sizeof (grub_uint32_t));
if (!*unicode_msg)
{
grub_printf ("utf8_to_ucs4 ERROR1: %s", msg);
return -1;
}
msg_len = grub_utf8_to_ucs4 (*unicode_msg, msg_len,
(grub_uint8_t *) msg, -1, 0);
*last_position = *unicode_msg + msg_len;
return msg_len;
}

View file

@ -694,13 +694,32 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
params->ext_mem = ((32 * 0x100000) >> 10); params->ext_mem = ((32 * 0x100000) >> 10);
params->alt_mem = ((32 * 0x100000) >> 10); params->alt_mem = ((32 * 0x100000) >> 10);
params->video_cursor_x = grub_getxy () >> 8; {
params->video_cursor_y = grub_getxy () & 0xff; grub_term_output_t term;
int found = 0;
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, "vga_text") == 0
|| grub_strcmp (term->name, "console") == 0)
{
grub_uint16_t pos = grub_term_getxy (term);
params->video_cursor_x = pos >> 8;
params->video_cursor_y = pos & 0xff;
params->video_width = grub_term_width (term);
params->video_height = grub_term_height (term);
found = 1;
break;
}
if (!found)
{
params->video_cursor_x = 0;
params->video_cursor_y = 0;
params->video_width = 80;
params->video_height = 25;
}
}
params->video_page = 0; /* ??? */ params->video_page = 0; /* ??? */
params->video_mode = grub_efi_system_table->con_out->mode->mode; params->video_mode = grub_efi_system_table->con_out->mode->mode;
params->video_width = (grub_getwh () >> 8);
params->video_ega_bx = 0; params->video_ega_bx = 0;
params->video_height = (grub_getwh () & 0xff);
params->have_vga = 0; params->have_vga = 0;
params->font_size = 16; /* XXX */ params->font_size = 16; /* XXX */

View file

@ -33,6 +33,7 @@
#include <grub/video_fb.h> #include <grub/video_fb.h>
#include <grub/command.h> #include <grub/command.h>
#include <grub/i386/pc/vbe.h> #include <grub/i386/pc/vbe.h>
#include <grub/i386/pc/console.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#define GRUB_LINUX_CL_OFFSET 0x1000 #define GRUB_LINUX_CL_OFFSET 0x1000
@ -548,8 +549,23 @@ grub_linux_boot (void)
/* Initialize these last, because terminal position could be affected by printfs above. */ /* Initialize these last, because terminal position could be affected by printfs above. */
if (params->have_vga == GRUB_VIDEO_TYPE_TEXT) if (params->have_vga == GRUB_VIDEO_TYPE_TEXT)
{ {
params->video_cursor_x = grub_getxy () >> 8; grub_term_output_t term;
params->video_cursor_y = grub_getxy () & 0xff; int found = 0;
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, "vga_text") == 0
|| grub_strcmp (term->name, "console") == 0)
{
grub_uint16_t pos = grub_term_getxy (term);
params->video_cursor_x = pos >> 8;
params->video_cursor_y = pos & 0xff;
found = 1;
break;
}
if (!found)
{
params->video_cursor_x = 0;
params->video_cursor_y = 0;
}
} }
#ifdef __x86_64__ #ifdef __x86_64__

View file

@ -154,6 +154,49 @@ is_authenticated (const char *userlist)
return grub_list_iterate (GRUB_AS_LIST (users), hook); return grub_list_iterate (GRUB_AS_LIST (users), hook);
} }
static int
grub_username_get (char buf[], unsigned buf_size)
{
unsigned cur_len = 0;
int key;
while (1)
{
key = GRUB_TERM_ASCII_CHAR (grub_getkey ());
if (key == '\n' || key == '\r')
break;
if (key == '\e')
{
cur_len = 0;
break;
}
if (key == '\b')
{
cur_len--;
grub_printf ("\b");
continue;
}
if (!grub_isprint (key))
continue;
if (cur_len + 2 < buf_size)
{
buf[cur_len++] = key;
grub_putchar (key);
}
}
grub_memset (buf + cur_len, 0, buf_size - cur_len);
grub_putchar ('\n');
grub_refresh ();
return (key != '\e');
}
grub_err_t grub_err_t
grub_auth_check_authentication (const char *userlist) grub_auth_check_authentication (const char *userlist)
{ {
@ -187,11 +230,12 @@ grub_auth_check_authentication (const char *userlist)
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
if (!grub_cmdline_get (N_("Enter username:"), login, sizeof (login) - 1, grub_puts_ (N_("Enter username: "));
0, 0, 0))
if (!grub_username_get (login, sizeof (login) - 1))
goto access_denied; goto access_denied;
grub_printf ("Enter password: "); grub_puts_ (N_("Enter password: "));
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN)) if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
goto access_denied; goto access_denied;

View file

@ -27,11 +27,12 @@
#include <grub/file.h> #include <grub/file.h>
#include <grub/env.h> #include <grub/env.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/charset.h>
static char *kill_buf; static grub_uint32_t *kill_buf;
static int hist_size; static int hist_size;
static char **hist_lines = 0; static grub_uint32_t **hist_lines = 0;
static int hist_pos = 0; static int hist_pos = 0;
static int hist_end = 0; static int hist_end = 0;
static int hist_used = 0; static int hist_used = 0;
@ -39,8 +40,8 @@ static int hist_used = 0;
grub_err_t grub_err_t
grub_set_history (int newsize) 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); hist_lines = grub_malloc (sizeof (grub_uint32_t *) * newsize);
/* Copy the old lines into the new buffer. */ /* Copy the old lines into the new buffer. */
if (old_hist_lines) if (old_hist_lines)
@ -67,16 +68,16 @@ grub_set_history (int newsize)
if (hist_pos < hist_end) if (hist_pos < hist_end)
grub_memmove (hist_lines, old_hist_lines + hist_pos, grub_memmove (hist_lines, old_hist_lines + hist_pos,
(hist_end - hist_pos) * sizeof (char *)); (hist_end - hist_pos) * sizeof (grub_uint32_t *));
else if (hist_used) else if (hist_used)
{ {
/* Copy the older part. */ /* Copy the older part. */
grub_memmove (hist_lines, old_hist_lines + hist_pos, grub_memmove (hist_lines, old_hist_lines + hist_pos,
(hist_size - hist_pos) * sizeof (char *)); (hist_size - hist_pos) * sizeof (grub_uint32_t *));
/* Copy the newer part. */ /* Copy the newer part. */
grub_memmove (hist_lines + hist_size - hist_pos, old_hist_lines, grub_memmove (hist_lines + hist_size - hist_pos, old_hist_lines,
hist_end * sizeof (char *)); hist_end * sizeof (grub_uint32_t *));
} }
} }
@ -90,17 +91,43 @@ grub_set_history (int newsize)
/* Get the entry POS from the history where `0' is the newest /* Get the entry POS from the history where `0' is the newest
entry. */ entry. */
static char * static grub_uint32_t *
grub_history_get (int pos) grub_history_get (int pos)
{ {
pos = (hist_pos + pos) % hist_size; pos = (hist_pos + pos) % hist_size;
return hist_lines[pos]; 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;
}
/* Replace the history entry on position POS with the string S. */
static void
grub_history_set (int pos, grub_uint32_t *s, grub_size_t len)
{
grub_free (hist_lines[pos]);
hist_lines[pos] = grub_malloc ((len + 1) * sizeof (grub_uint32_t));
if (!hist_lines[pos])
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
return ;
}
grub_memcpy (hist_lines[pos], s, len * sizeof (grub_uint32_t));
hist_lines[pos][len] = 0;
}
/* Insert a new history line S on the top of the history. */ /* Insert a new history line S on the top of the history. */
static void static void
grub_history_add (char *s) grub_history_add (grub_uint32_t *s, grub_size_t len)
{ {
/* Remove the oldest entry in the history to make room for a new /* Remove the oldest entry in the history to make room for a new
entry. */ entry. */
@ -121,16 +148,15 @@ grub_history_add (char *s)
hist_pos = hist_size + hist_pos; hist_pos = hist_size + hist_pos;
/* Insert into history. */ /* Insert into history. */
hist_lines[hist_pos] = grub_strdup (s); hist_lines[hist_pos] = NULL;
grub_history_set (hist_pos, s, len);
} }
/* Replace the history entry on position POS with the string S. */ /* Replace the history entry on position POS with the string S. */
static void static void
grub_history_replace (int pos, char *s) grub_history_replace (int pos, grub_uint32_t *s, grub_size_t len)
{ {
pos = (hist_pos + pos) % hist_size; grub_history_set ((hist_pos + pos) % hist_size, s, len);
grub_free (hist_lines[pos]);
hist_lines[pos] = grub_strdup (s);
} }
/* A completion hook to print items. */ /* A completion hook to print items. */
@ -176,75 +202,113 @@ print_completion (const char *item, grub_completion_type_t type, int count)
grub_printf (" %s", item); grub_printf (" %s", item);
} }
/* Get a command-line. If ECHO_CHAR is not zero, echo it instead of input struct cmdline_term
characters. If READLINE is non-zero, readline-like key bindings are {
available. If ESC is pushed, return zero, otherwise return non-zero. */ unsigned xpos, ypos, ystart, width, height;
/* FIXME: The dumb interface is not supported yet. */ struct grub_term_output *term;
int };
grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
int echo_char, int readline, int history) /* 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 xpos, ypos, ystart;
grub_size_t lpos, llen; grub_size_t lpos, llen;
grub_size_t plen; grub_size_t plen;
char buf[max_len]; grub_uint32_t *buf;
grub_size_t max_len = 256;
int key; int key;
int histpos = 0; 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_delete (unsigned len);
auto void cl_print (int pos, int c); auto inline void __attribute__ ((always_inline)) cl_print (struct cmdline_term *cl_term, int pos,
auto void cl_set_pos (void); 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);
auto void init_clterm (struct cmdline_term *cl_term_cur);
auto void init_clterm_all (void);
const char *prompt_translated = _(prompt); const char *prompt_translated = _(prompt);
struct cmdline_term *cl_terms;
char *ret;
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);
grub_term_gotoxy (cl_term->term, 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]);
}
inline void __attribute__ ((always_inline)) cl_print (struct cmdline_term *cl_term, int pos, grub_uint32_t c)
{ {
xpos = (plen + lpos) % 79; grub_uint32_t *p;
ypos = ystart + (plen + lpos) / 79;
grub_gotoxy (xpos, ypos);
grub_refresh (); for (p = buf + pos; p < buf + llen; p++)
}
void cl_print (int pos, int c)
{
char *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; cl_term->xpos = 1;
if (ypos == (unsigned) (grub_getxy () & 0xFF)) if (cl_term->ypos == (unsigned) (cl_term->height))
ystart--; cl_term->ystart--;
else else
ypos++; cl_term->ypos++;
} }
if (c) if (c)
grub_putchar (c); grub_putcode (c, cl_term->term);
else 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)
{
grub_uint32_t *nbuf;
max_len *= 2;
nbuf = grub_realloc (buf, sizeof (grub_uint32_t) * max_len);
if (nbuf)
buf = nbuf;
else
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
max_len /= 2;
}
}
if (len + llen < max_len) if (len + llen < max_len)
{ {
grub_memmove (buf + lpos + len, buf + lpos, llen - lpos + 1); grub_memmove (buf + lpos + len, buf + lpos,
grub_memmove (buf + lpos, str, len); (llen - lpos + 1) * sizeof (grub_uint32_t));
grub_memmove (buf + lpos, str, len * sizeof (grub_uint32_t));
llen += len; llen += len;
lpos += len; lpos += len;
cl_print (lpos - len, echo_char); cl_print_all (lpos - len, 0);
cl_set_pos (); cl_set_pos_all ();
} }
grub_refresh ();
} }
void cl_delete (unsigned len) void cl_delete (unsigned len)
@ -254,182 +318,254 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
grub_size_t saved_lpos = lpos; grub_size_t saved_lpos = lpos;
lpos = llen - len; lpos = llen - len;
cl_set_pos (); cl_set_pos_all ();
cl_print (lpos, ' '); cl_print_all (lpos, ' ');
lpos = saved_lpos; lpos = saved_lpos;
cl_set_pos (); cl_set_pos_all ();
grub_memmove (buf + lpos, buf + lpos + len, llen - lpos + 1); grub_memmove (buf + lpos, buf + lpos + len,
sizeof (grub_uint32_t) * (llen - lpos + 1));
llen -= len; llen -= len;
cl_print (lpos, echo_char); cl_print_all (lpos, 0);
cl_set_pos (); cl_set_pos_all ();
} }
grub_refresh ();
} }
void init_clterm (struct cmdline_term *cl_term_cur)
{
cl_term_cur->xpos = plen;
cl_term_cur->ypos = (grub_term_getxy (cl_term_cur->term) & 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]);
}
buf = grub_malloc (max_len * sizeof (grub_uint32_t));
if (!buf)
return 0;
plen = grub_strlen (prompt_translated) + sizeof (" ") - 1; plen = grub_strlen (prompt_translated) + sizeof (" ") - 1;
lpos = llen = 0; lpos = llen = 0;
buf[0] = '\0'; buf[0] = '\0';
if ((grub_getxy () >> 8) != 0) {
grub_putchar ('\n'); grub_term_output_t term;
FOR_ACTIVE_TERM_OUTPUTS(term)
if ((grub_term_getxy (term) >> 8) != 0)
grub_putcode ('\n', term);
}
grub_printf ("%s ", prompt_translated); 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_ACTIVE_TERM_OUTPUTS(cur)
nterms++;
cl_insert (cmdline); cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms);
if (!cl_terms)
return 0;
cl_term_cur = cl_terms;
FOR_ACTIVE_TERM_OUTPUTS(cur)
{
cl_term_cur->term = cur;
init_clterm (cl_term_cur);
cl_term_cur++;
}
}
if (history && hist_used == 0) if (hist_used == 0)
grub_history_add (buf); grub_history_add (buf, llen);
while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r') 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) 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 */
{
int restore;
char *insertu8;
char *bufu8;
buf[lpos] = '\0';
bufu8 = grub_ucs4_to_utf8_alloc (buf, lpos);
if (!bufu8)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
break;
}
insertu8 = grub_normal_do_completion (bufu8, &restore,
print_completion);
grub_free (bufu8);
if (restore)
{
/* Restore the prompt. */
grub_printf ("\n%s ", prompt_translated);
init_clterm_all ();
cl_print_all (0, 0);
}
if (insertu8)
{
grub_size_t insertlen;
grub_ssize_t t;
grub_uint32_t *insert;
insertlen = grub_strlen (insertu8);
insert = grub_malloc ((insertlen + 1) * sizeof (grub_uint32_t));
if (!insert)
{
grub_free (insertu8);
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
break;
}
t = grub_utf8_to_ucs4 (insert, insertlen,
(grub_uint8_t *) insertu8,
insertlen, 0);
if (t > 0)
{
insert[t] = 0;
cl_insert (insert);
}
grub_free (insertu8);
grub_free (insert);
}
}
break;
case 11: /* Ctrl-k */
if (lpos < llen)
{
if (kill_buf)
grub_free (kill_buf);
kill_buf = grub_malloc ((llen - lpos + 1)
* sizeof (grub_uint32_t));
if (grub_errno)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
else
{
grub_memcpy (kill_buf, buf + lpos,
(llen - lpos + 1) * sizeof (grub_uint32_t));
kill_buf[llen - lpos] = 0;
}
cl_delete (llen - lpos);
}
break;
case 14: /* Ctrl-n */
{
grub_uint32_t *hist;
lpos = 0;
if (histpos > 0)
{
grub_history_replace (histpos, buf, llen);
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, llen);
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);
if (grub_errno)
{
grub_print_error ();
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': case '\e':
return 0; return 0;
@ -437,7 +573,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
if (lpos > 0) if (lpos > 0)
{ {
lpos--; lpos--;
cl_set_pos (); cl_set_pos_all ();
} }
else else
break; break;
@ -451,7 +587,7 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
default: default:
if (grub_isprint (key)) if (grub_isprint (key))
{ {
char str[2]; grub_uint32_t str[2];
str[0] = key; str[0] = key;
str[1] = '\0'; str[1] = '\0';
@ -459,28 +595,26 @@ grub_cmdline_get (const char *prompt, char cmdline[], unsigned max_len,
} }
break; break;
} }
grub_refresh ();
} }
grub_putchar ('\n'); grub_putchar ('\n');
grub_refresh (); grub_refresh ();
/* If ECHO_CHAR is NUL, remove leading spaces. */ /* Remove leading spaces. */
lpos = 0; lpos = 0;
if (! echo_char) while (buf[lpos] == ' ')
while (buf[lpos] == ' ') lpos++;
lpos++;
if (history) histpos = 0;
if (strlen_ucs4 (buf) > 0)
{ {
histpos = 0; grub_uint32_t empty[] = { 0 };
if (grub_strlen (buf) > 0) grub_history_replace (histpos, buf, llen);
{ grub_history_add (empty, 0);
grub_history_replace (histpos, buf);
grub_history_add ("");
}
} }
grub_memcpy (cmdline, buf + lpos, llen - lpos + 1); ret = grub_ucs4_to_utf8_alloc (buf + lpos, llen - lpos + 1);
grub_free (buf);
return 1; return ret;
} }

View file

@ -103,23 +103,31 @@ free_and_return:
grub_free (fg_name); grub_free (fg_name);
} }
static grub_uint8_t color_normal, color_highlight;
static void
set_colors (void)
{
struct grub_term_output *term;
FOR_ACTIVE_TERM_OUTPUTS(term)
{
/* Reloads terminal `normal' and `highlight' colors. */
grub_term_setcolor (term, color_normal, color_highlight);
/* Propagates `normal' color to terminal current color. */
grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
}
}
/* Replace default `normal' colors with the ones specified by user (if any). */ /* Replace default `normal' colors with the ones specified by user (if any). */
char * char *
grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)), grub_env_write_color_normal (struct grub_env_var *var __attribute__ ((unused)),
const char *val) 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); grub_parse_color_name_pair (&color_normal, val);
/* Reloads terminal `normal' and `highlight' colors. */ set_colors ();
grub_setcolor (color_normal, color_highlight);
/* Propagates `normal' color to terminal current color. */
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
return grub_strdup (val); return grub_strdup (val);
} }
@ -129,21 +137,9 @@ char *
grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)), grub_env_write_color_highlight (struct grub_env_var *var __attribute__ ((unused)),
const char *val) 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); grub_parse_color_name_pair (&color_highlight, val);
/* Reloads terminal `normal' and `highlight' colors. */ set_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);
return grub_strdup (val); return grub_strdup (val);
} }

View file

@ -30,9 +30,13 @@
#include <grub/menu_viewer.h> #include <grub/menu_viewer.h>
#include <grub/auth.h> #include <grub/auth.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/charset.h>
#define GRUB_DEFAULT_HISTORY_SIZE 50 #define GRUB_DEFAULT_HISTORY_SIZE 50
static int nested_level = 0;
int grub_normal_exit_level = 0;
/* Read a line from the file FILE. */ /* Read a line from the file FILE. */
char * char *
grub_file_getline (grub_file_t file) grub_file_getline (grub_file_t file)
@ -372,7 +376,21 @@ read_config_file (const char *config)
if (! file) if (! file)
return 0; 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); grub_file_close (file);
if (old_parser) if (old_parser)
@ -383,7 +401,7 @@ read_config_file (const char *config)
/* Initialize the screen. */ /* Initialize the screen. */
void void
grub_normal_init_page (void) grub_normal_init_page (struct grub_term_output *term)
{ {
int msg_len; int msg_len;
int posx; int posx;
@ -391,14 +409,13 @@ grub_normal_init_page (void)
char *msg_formatted = grub_malloc (grub_strlen(msg) + char *msg_formatted = grub_malloc (grub_strlen(msg) +
grub_strlen(PACKAGE_VERSION)); grub_strlen(PACKAGE_VERSION));
grub_cls ();
grub_sprintf (msg_formatted, msg, PACKAGE_VERSION);
grub_uint32_t *unicode_msg; grub_uint32_t *unicode_msg;
grub_uint32_t *last_position; grub_uint32_t *last_position;
grub_term_cls (term);
grub_sprintf (msg_formatted, msg, PACKAGE_VERSION);
msg_len = grub_utf8_to_ucs4_alloc (msg_formatted, msg_len = grub_utf8_to_ucs4_alloc (msg_formatted,
&unicode_msg, &last_position); &unicode_msg, &last_position);
@ -407,17 +424,15 @@ grub_normal_init_page (void)
return; return;
} }
posx = grub_getstringwidth (unicode_msg, last_position); posx = grub_getstringwidth (unicode_msg, last_position, term);
posx = (GRUB_TERM_WIDTH - posx) / 2; posx = (grub_term_width (term) - posx) / 2;
grub_gotoxy (posx, 1); grub_term_gotoxy (term, posx, 1);
grub_print_ucs4 (unicode_msg, last_position); grub_print_ucs4 (unicode_msg, last_position, term);
grub_printf("\n\n"); grub_printf("\n\n");
grub_free (unicode_msg); grub_free (unicode_msg);
} }
static int reader_nested;
static char * static char *
read_lists (struct grub_env_var *var __attribute__ ((unused)), read_lists (struct grub_env_var *var __attribute__ ((unused)),
const char *val) const char *val)
@ -425,6 +440,7 @@ read_lists (struct grub_env_var *var __attribute__ ((unused)),
read_command_list (); read_command_list ();
read_fs_list (); read_fs_list ();
read_crypto_list (); read_crypto_list ();
read_terminal_list ();
return val ? grub_strdup (val) : NULL; return val ? grub_strdup (val) : NULL;
} }
@ -440,8 +456,6 @@ grub_normal_execute (const char *config, int nested, int batch)
grub_register_variable_hook ("prefix", NULL, read_lists); grub_register_variable_hook ("prefix", NULL, read_lists);
grub_command_execute ("parser.grub", 0, 0); grub_command_execute ("parser.grub", 0, 0);
reader_nested = nested;
if (config) if (config)
{ {
menu = read_config_file (config); menu = read_config_file (config);
@ -454,7 +468,7 @@ grub_normal_execute (const char *config, int nested, int batch)
{ {
if (menu && menu->size) if (menu && menu->size)
{ {
grub_menu_viewer_show_menu (menu, nested); grub_show_menu (menu, nested);
if (nested) if (nested)
free_menu (menu); free_menu (menu);
} }
@ -465,21 +479,24 @@ grub_normal_execute (const char *config, int nested, int batch)
void void
grub_enter_normal_mode (const char *config) grub_enter_normal_mode (const char *config)
{ {
nested_level++;
grub_normal_execute (config, 0, 0); grub_normal_execute (config, 0, 0);
grub_cmdline_run (0);
nested_level--;
if (grub_normal_exit_level)
grub_normal_exit_level--;
} }
/* Enter normal mode from rescue mode. */ /* Enter normal mode from rescue mode. */
static grub_err_t static grub_err_t
grub_cmd_normal (struct grub_command *cmd, grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[]) int argc, char *argv[])
{ {
grub_unregister_command (cmd);
if (argc == 0) if (argc == 0)
{ {
/* Guess the config filename. It is necessary to make CONFIG static, /* Guess the config filename. It is necessary to make CONFIG static,
so that it won't get broken by longjmp. */ so that it won't get broken by longjmp. */
static char *config; char *config;
const char *prefix; const char *prefix;
prefix = grub_env_get ("prefix"); prefix = grub_env_get ("prefix");
@ -503,10 +520,82 @@ quit:
return 0; return 0;
} }
/* Exit from normal mode to rescue mode. */
static grub_err_t
grub_cmd_normal_exit (struct grub_command *cmd __attribute__ ((unused)),
int argc __attribute__ ((unused)),
char *argv[] __attribute__ ((unused)))
{
if (nested_level <= grub_normal_exit_level)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "not in normal environment");
grub_normal_exit_level++;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_normal_reader_init (int nested)
{
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, nested ? msg_esc : "");
FOR_ACTIVE_TERM_OUTPUTS(term)
{
grub_normal_init_page (term);
grub_term_setcursor (term, 1);
grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
grub_puts ("\n");
}
grub_free (msg_formatted);
return 0;
}
static grub_err_t
grub_normal_read_line_real (char **line, int cont, int nested)
{
grub_parser_t parser = grub_parser_get_current ();
char prompt[sizeof(">") + grub_strlen (parser->name)];
if (cont)
grub_sprintf (prompt, ">");
else
grub_sprintf (prompt, "%s>", parser->name);
while (1)
{
*line = grub_cmdline_get (prompt);
if (*line)
break;
if (cont || nested)
{
grub_free (*line);
*line = 0;
return grub_errno;
}
}
return 0;
}
static grub_err_t
grub_normal_read_line (char **line, int cont)
{
return grub_normal_read_line_real (line, cont, 0);
}
void void
grub_cmdline_run (int nested) grub_cmdline_run (int nested)
{ {
grub_reader_t reader;
grub_err_t err = GRUB_ERR_NONE; grub_err_t err = GRUB_ERR_NONE;
err = grub_auth_check_authentication (NULL); err = grub_auth_check_authentication (NULL);
@ -518,72 +607,28 @@ grub_cmdline_run (int nested)
return; return;
} }
reader = grub_reader_get_current (); grub_normal_reader_init (nested);
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);
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");
grub_free (msg_formatted);
return 0;
}
static char cmdline[GRUB_MAX_CMDLINE];
static grub_err_t
grub_normal_read_line (char **line, int cont)
{
grub_parser_t parser = grub_parser_get_current ();
char prompt[sizeof(">") + grub_strlen (parser->name)];
grub_sprintf (prompt, "%s>", parser->name);
while (1) while (1)
{ {
cmdline[0] = 0; char *line;
if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1, 1))
if (grub_normal_exit_level)
break; break;
if ((reader_nested) || (cont)) /* Print an error, if any. */
{ grub_print_error ();
*line = 0; grub_errno = GRUB_ERR_NONE;
return grub_errno;
} grub_normal_read_line_real (&line, 0, nested);
if (! line)
break;
grub_parser_get_current ()->parse_line (line, grub_normal_read_line);
grub_free (line);
} }
*line = grub_strdup (cmdline);
return 0;
} }
static struct grub_reader grub_normal_reader =
{
.name = "normal",
.init = grub_normal_reader_init,
.read_line = grub_normal_read_line
};
static char * static char *
grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)), grub_env_write_pager (struct grub_env_var *var __attribute__ ((unused)),
const char *val) const char *val)
@ -598,17 +643,15 @@ GRUB_MOD_INIT(normal)
if (mod) if (mod)
grub_dl_ref (mod); grub_dl_ref (mod);
grub_menu_viewer_register (&grub_normal_text_menu_viewer);
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE); 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); grub_register_variable_hook ("pager", 0, grub_env_write_pager);
/* Register a command "normal" for the rescue mode. */ /* Register a command "normal" for the rescue mode. */
grub_register_command_prio ("normal", grub_cmd_normal, grub_register_command ("normal", grub_cmd_normal,
0, "Enter normal mode.", 0); 0, "Enter normal mode.");
grub_register_command ("normal_exit", grub_cmd_normal_exit,
0, "Exit from normal mode.");
/* Reload terminal colors when these variables are written to. */ /* Reload terminal colors when these variables are written to. */
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal); grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
@ -622,7 +665,6 @@ GRUB_MOD_INIT(normal)
GRUB_MOD_FINI(normal) GRUB_MOD_FINI(normal)
{ {
grub_set_history (0); grub_set_history (0);
grub_reader_unregister (&grub_normal_reader);
grub_register_variable_hook ("pager", 0, 0); grub_register_variable_hook ("pager", 0, 0);
grub_fs_autoload_hook = 0; grub_fs_autoload_hook = 0;
free_handler_list (); free_handler_list ();

View file

@ -27,6 +27,26 @@
#include <grub/command.h> #include <grub/command.h>
#include <grub/parser.h> #include <grub/parser.h>
#include <grub/auth.h> #include <grub/auth.h>
#include <grub/i18n.h>
#include <grub/term.h>
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
#define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
grub_err_t (*grub_gfxmenu_try_hook) (int entry, grub_menu_t menu,
int nested) = NULL;
/* Wait until the user pushes any key so that the user
can see what happened. */
void
grub_wait_after_message (void)
{
grub_putchar ('\n');
grub_printf_ (N_("Press any key to continue..."));
(void) grub_getkey ();
grub_putchar ('\n');
}
/* Get a menu entry by its index in the entry list. */ /* Get a menu entry by its index in the entry list. */
grub_menu_entry_t grub_menu_entry_t
@ -178,3 +198,378 @@ grub_menu_execute_with_fallback (grub_menu_t menu,
callback->notify_failure (callback_data); callback->notify_failure (callback_data);
} }
static struct grub_menu_viewer *viewers;
static void
menu_set_chosen_entry (int entry)
{
struct grub_menu_viewer *cur;
for (cur = viewers; cur; cur = cur->next)
cur->set_chosen_entry (entry, cur->data);
}
static void
menu_print_timeout (int timeout)
{
struct grub_menu_viewer *cur;
for (cur = viewers; cur; cur = cur->next)
cur->print_timeout (timeout, cur->data);
}
static void
menu_fini (void)
{
struct grub_menu_viewer *cur, *next;
for (cur = viewers; cur; cur = next)
{
next = cur->next;
cur->fini (cur->data);
grub_free (cur);
}
viewers = NULL;
}
static void
menu_init (int entry, grub_menu_t menu, int nested)
{
struct grub_term_output *term;
FOR_ACTIVE_TERM_OUTPUTS(term)
{
grub_err_t err;
if (grub_gfxmenu_try_hook && grub_strcmp (term->name, "gfxterm") == 0)
{
err = grub_gfxmenu_try_hook (entry, menu, nested);
if(!err)
continue;
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
err = grub_menu_try_text (term, entry, menu, nested);
if(!err)
continue;
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
}
static void
clear_timeout (void)
{
struct grub_menu_viewer *cur;
for (cur = viewers; cur; cur = cur->next)
cur->clear_timeout (cur->data);
}
void
grub_menu_register_viewer (struct grub_menu_viewer *viewer)
{
viewer->next = viewers;
viewers = viewer;
}
/* Get the entry number from the variable NAME. */
static int
get_entry_number (const char *name)
{
char *val;
int entry;
val = grub_env_get (name);
if (! val)
return -1;
grub_error_push ();
entry = (int) grub_strtoul (val, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_errno = GRUB_ERR_NONE;
entry = -1;
}
grub_error_pop ();
return entry;
}
#define GRUB_MENU_PAGE_SIZE 10
/* Show the menu and handle menu entry selection. Returns the menu entry
index that should be executed or -1 if no entry should be executed (e.g.,
Esc pressed to exit a sub-menu or switching menu viewers).
If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
entry to be executed is a result of an automatic default selection because
of the timeout. */
static int
run_menu (grub_menu_t menu, int nested, int *auto_boot)
{
grub_uint64_t saved_time;
int default_entry, current_entry;
int timeout;
default_entry = get_entry_number ("default");
/* If DEFAULT_ENTRY is not within the menu entries, fall back to
the first entry. */
if (default_entry < 0 || default_entry >= menu->size)
default_entry = 0;
/* If timeout is 0, drawing is pointless (and ugly). */
if (grub_menu_get_timeout () == 0)
{
*auto_boot = 1;
return default_entry;
}
current_entry = default_entry;
/* Initialize the time. */
saved_time = grub_get_time_ms ();
refresh:
menu_init (current_entry, menu, nested);
timeout = grub_menu_get_timeout ();
if (timeout > 0)
menu_print_timeout (timeout);
while (1)
{
int c;
timeout = grub_menu_get_timeout ();
if (grub_normal_exit_level)
return -1;
if (timeout > 0)
{
grub_uint64_t current_time;
current_time = grub_get_time_ms ();
if (current_time - saved_time >= 1000)
{
timeout--;
grub_menu_set_timeout (timeout);
saved_time = current_time;
menu_print_timeout (timeout);
}
}
if (timeout == 0)
{
grub_env_unset ("timeout");
*auto_boot = 1;
menu_fini ();
return default_entry;
}
if (grub_checkkey () >= 0 || timeout < 0)
{
c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
if (timeout >= 0)
{
grub_env_unset ("timeout");
grub_env_unset ("fallback");
clear_timeout ();
}
switch (c)
{
case GRUB_TERM_HOME:
current_entry = 0;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_END:
current_entry = menu->size - 1;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_UP:
case '^':
if (current_entry > 0)
current_entry--;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_DOWN:
case 'v':
if (current_entry < menu->size - 1)
current_entry++;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_PPAGE:
if (current_entry < GRUB_MENU_PAGE_SIZE)
current_entry = 0;
else
current_entry -= GRUB_MENU_PAGE_SIZE;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_NPAGE:
if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size)
current_entry += GRUB_MENU_PAGE_SIZE;
else
current_entry = menu->size - 1;
menu_set_chosen_entry (current_entry);
break;
case '\n':
case '\r':
case 6:
menu_fini ();
*auto_boot = 0;
return current_entry;
case '\e':
if (nested)
{
menu_fini ();
return -1;
}
break;
case 'c':
menu_fini ();
grub_cmdline_run (1);
goto refresh;
case 'e':
menu_fini ();
{
grub_menu_entry_t e = grub_menu_get_entry (menu, current_entry);
if (e)
grub_menu_entry_run (e);
}
goto refresh;
default:
break;
}
}
}
/* Never reach here. */
return -1;
}
/* Callback invoked immediately before a menu entry is executed. */
static void
notify_booting (grub_menu_entry_t entry,
void *userdata __attribute__((unused)))
{
grub_printf (" ");
grub_printf_ (N_("Booting \'%s\'"), entry->title);
grub_printf ("\n\n");
}
/* Callback invoked when a default menu entry executed because of a timeout
has failed and an attempt will be made to execute the next fallback
entry, ENTRY. */
static void
notify_fallback (grub_menu_entry_t entry,
void *userdata __attribute__((unused)))
{
grub_printf ("\n ");
grub_printf_ (N_("Falling back to \'%s\'"), entry->title);
grub_printf ("\n\n");
grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS);
}
/* Callback invoked when a menu entry has failed and there is no remaining
fallback entry to attempt. */
static void
notify_execution_failure (void *userdata __attribute__((unused)))
{
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
}
grub_printf ("\n ");
grub_printf_ (N_("Failed to boot default entries.\n"));
grub_wait_after_message ();
}
/* Callbacks used by the text menu to provide user feedback when menu entries
are executed. */
static struct grub_menu_execute_callback execution_callback =
{
.notify_booting = notify_booting,
.notify_fallback = notify_fallback,
.notify_failure = notify_execution_failure
};
static grub_err_t
show_menu (grub_menu_t menu, int nested)
{
while (1)
{
int boot_entry;
grub_menu_entry_t e;
int auto_boot;
boot_entry = run_menu (menu, nested, &auto_boot);
if (boot_entry < 0)
break;
e = grub_menu_get_entry (menu, boot_entry);
if (! e)
continue; /* Menu is empty. */
grub_cls ();
if (auto_boot)
{
grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
}
else
{
grub_errno = GRUB_ERR_NONE;
grub_menu_execute_entry (e);
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_wait_after_message ();
}
}
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_show_menu (grub_menu_t menu, int nested)
{
grub_err_t err1, err2;
while (1)
{
err1 = show_menu (menu, nested);
grub_print_error ();
if (grub_normal_exit_level)
break;
err2 = grub_auth_check_authentication (NULL);
if (err2)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
continue;
}
break;
}
return err1;
}

File diff suppressed because it is too large Load diff

View file

@ -26,88 +26,66 @@
#include <grub/env.h> #include <grub/env.h>
#include <grub/menu_viewer.h> #include <grub/menu_viewer.h>
#include <grub/i18n.h> #include <grub/i18n.h>
#include <grub/charset.h>
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
#define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
static grub_uint8_t grub_color_menu_normal; static grub_uint8_t grub_color_menu_normal;
static grub_uint8_t grub_color_menu_highlight; static grub_uint8_t grub_color_menu_highlight;
/* Wait until the user pushes any key so that the user struct menu_viewer_data
can see what happened. */
void
grub_wait_after_message (void)
{ {
grub_putchar ('\n'); int first, offset;
grub_printf_ (N_("Press any key to continue...")); grub_menu_t menu;
(void) grub_getkey (); struct grub_term_output *term;
grub_putchar ('\n'); };
static void
print_spaces (int number_spaces, struct grub_term_output *term)
{
int i;
for (i = 0; i < number_spaces; i++)
grub_putcode (' ', term);
} }
void void
grub_print_ucs4 (const grub_uint32_t * str, grub_print_ucs4 (const grub_uint32_t * str,
const grub_uint32_t * last_position) const grub_uint32_t * last_position,
struct grub_term_output *term)
{ {
while (str < last_position) while (str < last_position)
{ {
grub_putcode (*str); grub_putcode (*str, term);
str++; str++;
} }
} }
int
grub_utf8_to_ucs4_alloc (const char *msg, grub_uint32_t **unicode_msg,
grub_uint32_t **last_position)
{
grub_ssize_t msg_len = grub_strlen (msg);
*unicode_msg = grub_malloc (grub_strlen (msg) * sizeof (grub_uint32_t));
if (!*unicode_msg)
{
grub_printf ("utf8_to_ucs4 ERROR1: %s", msg);
return -1;
}
msg_len = grub_utf8_to_ucs4 (*unicode_msg, msg_len,
(grub_uint8_t *) msg, -1, 0);
*last_position = *unicode_msg + msg_len;
if (msg_len < 0)
{
grub_printf ("utf8_to_ucs4 ERROR2: %s", msg);
grub_free (*unicode_msg);
}
return msg_len;
}
grub_ssize_t grub_ssize_t
grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position) grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position,
struct grub_term_output *term)
{ {
grub_ssize_t width = 0; grub_ssize_t width = 0;
while (str < last_position) while (str < last_position)
{ {
width += grub_getcharwidth (*str); width += grub_term_getcharwidth (term, *str);
str++; str++;
} }
return width; return width;
} }
void void
grub_print_message_indented (const char *msg, int margin_left, int margin_right) grub_print_message_indented (const char *msg, int margin_left, int margin_right,
struct grub_term_output *term)
{ {
int line_len; int line_len;
line_len = GRUB_TERM_WIDTH - grub_getcharwidth ('m') *
(margin_left + margin_right);
grub_uint32_t *unicode_msg; grub_uint32_t *unicode_msg;
grub_uint32_t *last_position; grub_uint32_t *last_position;
int msg_len; int msg_len;
line_len = grub_term_width (term) - grub_term_getcharwidth (term, 'm') *
(margin_left + margin_right);
msg_len = grub_utf8_to_ucs4_alloc (msg, &unicode_msg, &last_position); msg_len = grub_utf8_to_ucs4_alloc (msg, &unicode_msg, &last_position);
if (msg_len < 0) if (msg_len < 0)
@ -124,11 +102,12 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right)
while (current_position < last_position) while (current_position < last_position)
{ {
if (! first_loop) if (! first_loop)
grub_putchar ('\n'); grub_putcode ('\n', term);
next_new_line = (grub_uint32_t *) last_position; next_new_line = (grub_uint32_t *) last_position;
while (grub_getstringwidth (current_position, next_new_line) > line_len while (grub_getstringwidth (current_position, next_new_line,term)
> line_len
|| (next_new_line != last_position && *next_new_line != ' ' || (next_new_line != last_position && *next_new_line != ' '
&& next_new_line > current_position)) && next_new_line > current_position))
{ {
@ -141,8 +120,8 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right)
(grub_uint32_t *) last_position : next_new_line + line_len; (grub_uint32_t *) last_position : next_new_line + line_len;
} }
grub_print_spaces (margin_left); print_spaces (margin_left, term);
grub_print_ucs4 (current_position, next_new_line); grub_print_ucs4 (current_position, next_new_line, term);
next_new_line++; next_new_line++;
current_position = next_new_line; current_position = next_new_line;
@ -153,52 +132,54 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right)
static void static void
draw_border (void) draw_border (struct grub_term_output *term)
{ {
unsigned i; unsigned i;
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y); grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
grub_putcode (GRUB_TERM_DISP_UL); grub_putcode (GRUB_TERM_DISP_UL, term);
for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++) for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++)
grub_putcode (GRUB_TERM_DISP_HLINE); grub_putcode (GRUB_TERM_DISP_HLINE, term);
grub_putcode (GRUB_TERM_DISP_UR); grub_putcode (GRUB_TERM_DISP_UR, term);
for (i = 0; i < (unsigned) GRUB_TERM_NUM_ENTRIES; i++) for (i = 0; i < (unsigned) grub_term_num_entries (term); i++)
{ {
grub_gotoxy (GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1); grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
grub_putcode (GRUB_TERM_DISP_VLINE); grub_putcode (GRUB_TERM_DISP_VLINE, term);
grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1, grub_term_gotoxy (term, GRUB_TERM_MARGIN + grub_term_border_width (term)
GRUB_TERM_TOP_BORDER_Y + i + 1); - 1,
grub_putcode (GRUB_TERM_DISP_VLINE); GRUB_TERM_TOP_BORDER_Y + i + 1);
grub_putcode (GRUB_TERM_DISP_VLINE, term);
} }
grub_gotoxy (GRUB_TERM_MARGIN, grub_term_gotoxy (term, GRUB_TERM_MARGIN,
GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1); GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term) + 1);
grub_putcode (GRUB_TERM_DISP_LL); grub_putcode (GRUB_TERM_DISP_LL, term);
for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++) for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++)
grub_putcode (GRUB_TERM_DISP_HLINE); grub_putcode (GRUB_TERM_DISP_HLINE, term);
grub_putcode (GRUB_TERM_DISP_LR); grub_putcode (GRUB_TERM_DISP_LR, term);
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_gotoxy (GRUB_TERM_MARGIN, grub_term_gotoxy (term, GRUB_TERM_MARGIN,
(GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES (GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term)
+ GRUB_TERM_MARGIN + 1)); + GRUB_TERM_MARGIN + 1));
} }
static void static void
print_message (int nested, int edit) print_message (int nested, int edit, struct grub_term_output *term)
{ {
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
if (edit) if (edit)
{ {
grub_putchar ('\n'); grub_putcode ('\n', term);
grub_print_message_indented (_("Minimum Emacs-like screen editing is \ grub_print_message_indented (_("Minimum Emacs-like screen editing is \
supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \ supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \
command-line or ESC to return menu."), STANDARD_MARGIN, STANDARD_MARGIN); command-line or ESC to return menu."), STANDARD_MARGIN, STANDARD_MARGIN,
term);
} }
else else
{ {
@ -210,23 +191,33 @@ entry is highlighted.\n");
grub_sprintf (msg_translated, msg, (grub_uint32_t) GRUB_TERM_DISP_UP, grub_sprintf (msg_translated, msg, (grub_uint32_t) GRUB_TERM_DISP_UP,
(grub_uint32_t) GRUB_TERM_DISP_DOWN); (grub_uint32_t) GRUB_TERM_DISP_DOWN);
grub_putchar ('\n'); grub_putchar ('\n');
grub_print_message_indented (msg_translated, STANDARD_MARGIN, STANDARD_MARGIN); grub_print_message_indented (msg_translated, STANDARD_MARGIN,
STANDARD_MARGIN, term);
grub_free (msg_translated); grub_free (msg_translated);
grub_print_message_indented (_("Press enter to execute the selected \
entry, \'e\' to edit the commands before booting or \'c\' for a command-line.\n"), STANDARD_MARGIN, STANDARD_MARGIN);
if (nested) if (nested)
{ {
grub_printf ("\n "); grub_print_message_indented
grub_printf_ (N_("ESC to return previous menu.")); (_("Press enter to boot the selected OS, "
} "\'e\' to edit the commands before booting "
"or \'c\' for a command-line. ESC to return previous menu.\n"),
STANDARD_MARGIN, STANDARD_MARGIN, term);
}
else
{
grub_print_message_indented
(_("Press enter to boot the selected OS, "
"\'e\' to edit the commands before booting "
"or \'c\' for a command-line.\n"),
STANDARD_MARGIN, STANDARD_MARGIN, term);
}
} }
} }
static void static void
print_entry (int y, int highlight, grub_menu_entry_t entry) print_entry (int y, int highlight, grub_menu_entry_t entry,
struct grub_term_output *term)
{ {
int x; int x;
const char *title; const char *title;
@ -252,482 +243,245 @@ print_entry (int y, int highlight, grub_menu_entry_t entry)
return; return;
} }
grub_getcolor (&old_color_normal, &old_color_highlight); grub_term_getcolor (term, &old_color_normal, &old_color_highlight);
grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight); grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight);
grub_setcolorstate (highlight grub_term_setcolorstate (term, highlight
? GRUB_TERM_COLOR_HIGHLIGHT ? GRUB_TERM_COLOR_HIGHLIGHT
: GRUB_TERM_COLOR_NORMAL); : GRUB_TERM_COLOR_NORMAL);
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y); grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN, y);
for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0; for (x = GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1, i = 0;
x < GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH - GRUB_TERM_MARGIN; x < (int) (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term)
- GRUB_TERM_MARGIN);
i++) i++)
{ {
if (i < len if (i < len
&& x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH && x <= (int) (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term)
- GRUB_TERM_MARGIN - 1)) - GRUB_TERM_MARGIN - 1))
{ {
grub_ssize_t width; grub_ssize_t width;
width = grub_getcharwidth (unicode_title[i]); width = grub_term_getcharwidth (term, unicode_title[i]);
if (x + width > (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH if (x + width > (int) (GRUB_TERM_LEFT_BORDER_X
- GRUB_TERM_MARGIN - 1)) + grub_term_border_width (term)
grub_putcode (GRUB_TERM_DISP_RIGHT); - GRUB_TERM_MARGIN - 1))
grub_putcode (GRUB_TERM_DISP_RIGHT, term);
else else
grub_putcode (unicode_title[i]); grub_putcode (unicode_title[i], term);
x += width; x += width;
} }
else else
{ {
grub_putchar (' '); grub_putcode (' ', term);
x++; x++;
} }
} }
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_putchar (' '); grub_putcode (' ', term);
grub_gotoxy (GRUB_TERM_CURSOR_X, y); grub_term_gotoxy (term, grub_term_cursor_x (term), y);
grub_setcolor (old_color_normal, old_color_highlight); grub_term_setcolor (term, old_color_normal, old_color_highlight);
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL); grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_free (unicode_title); grub_free (unicode_title);
} }
static void static void
print_entries (grub_menu_t menu, int first, int offset) print_entries (grub_menu_t menu, int first, int offset,
struct grub_term_output *term)
{ {
grub_menu_entry_t e; grub_menu_entry_t e;
int i; int i;
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH, grub_term_gotoxy (term,
GRUB_TERM_FIRST_ENTRY_Y); GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term),
GRUB_TERM_FIRST_ENTRY_Y);
if (first) if (first)
grub_putcode (GRUB_TERM_DISP_UP); grub_putcode (GRUB_TERM_DISP_UP, term);
else else
grub_putchar (' '); grub_putcode (' ', term);
e = grub_menu_get_entry (menu, first); e = grub_menu_get_entry (menu, first);
for (i = 0; i < GRUB_TERM_NUM_ENTRIES; i++) for (i = 0; i < grub_term_num_entries (term); i++)
{ {
print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e); print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e, term);
if (e) if (e)
e = e->next; e = e->next;
} }
grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH, grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X
GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES); + grub_term_border_width (term),
GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term));
if (e) if (e)
grub_putcode (GRUB_TERM_DISP_DOWN); grub_putcode (GRUB_TERM_DISP_DOWN, term);
else else
grub_putchar (' '); grub_putcode (' ', term);
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset); grub_term_gotoxy (term, grub_term_cursor_x (term),
GRUB_TERM_FIRST_ENTRY_Y + offset);
} }
/* Initialize the screen. If NESTED is non-zero, assume that this menu /* Initialize the screen. If NESTED is non-zero, assume that this menu
is run from another menu or a command-line. If EDIT is non-zero, show is run from another menu or a command-line. If EDIT is non-zero, show
a message for the menu entry editor. */ a message for the menu entry editor. */
void void
grub_menu_init_page (int nested, int edit) grub_menu_init_page (int nested, int edit,
struct grub_term_output *term)
{ {
grub_uint8_t old_color_normal, old_color_highlight; grub_uint8_t old_color_normal, old_color_highlight;
grub_getcolor (&old_color_normal, &old_color_highlight); grub_term_getcolor (term, &old_color_normal, &old_color_highlight);
/* By default, use the same colors for the menu. */ /* By default, use the same colors for the menu. */
grub_color_menu_normal = old_color_normal; grub_color_menu_normal = old_color_normal;
grub_color_menu_highlight = old_color_highlight; grub_color_menu_highlight = old_color_highlight;
/* Then give user a chance to replace them. */ /* Then give user a chance to replace them. */
grub_parse_color_name_pair (&grub_color_menu_normal, grub_env_get ("menu_color_normal")); grub_parse_color_name_pair (&grub_color_menu_normal,
grub_parse_color_name_pair (&grub_color_menu_highlight, grub_env_get ("menu_color_highlight")); grub_env_get ("menu_color_normal"));
grub_parse_color_name_pair (&grub_color_menu_highlight,
grub_env_get ("menu_color_highlight"));
grub_normal_init_page (); grub_normal_init_page (term);
grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight); grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight);
draw_border (); draw_border (term);
grub_setcolor (old_color_normal, old_color_highlight); grub_term_setcolor (term, old_color_normal, old_color_highlight);
print_message (nested, edit); print_message (nested, edit, term);
}
/* Get the entry number from the variable NAME. */
static int
get_entry_number (const char *name)
{
char *val;
int entry;
val = grub_env_get (name);
if (! val)
return -1;
grub_error_push ();
entry = (int) grub_strtoul (val, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_errno = GRUB_ERR_NONE;
entry = -1;
}
grub_error_pop ();
return entry;
} }
static void static void
print_timeout (int timeout, int offset) menu_text_print_timeout (int timeout, void *dataptr)
{ {
const char *msg = const char *msg =
_("The highlighted entry will be executed automatically in %ds."); _("The highlighted entry will be executed automatically in %ds.");
struct menu_viewer_data *data = dataptr;
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3); char *msg_translated;
char *msg_translated =
grub_malloc (sizeof (char) * grub_strlen (msg) + 5);
grub_sprintf (msg_translated, msg, timeout);
grub_print_message_indented (msg_translated, 3, 0);
int posx; int posx;
posx = grub_getxy() >> 8;
grub_print_spaces (GRUB_TERM_WIDTH - posx - 1);
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset); grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3);
grub_refresh ();
}
/* Show the menu and handle menu entry selection. Returns the menu entry msg_translated = grub_malloc (sizeof (char) * grub_strlen (msg) + 5);
index that should be executed or -1 if no entry should be executed (e.g., if (!msg_translated)
Esc pressed to exit a sub-menu or switching menu viewers).
If the return value is not -1, then *AUTO_BOOT is nonzero iff the menu
entry to be executed is a result of an automatic default selection because
of the timeout. */
static int
run_menu (grub_menu_t menu, int nested, int *auto_boot)
{
int first, offset;
grub_uint64_t saved_time;
int default_entry;
int timeout;
first = 0;
default_entry = get_entry_number ("default");
/* If DEFAULT_ENTRY is not within the menu entries, fall back to
the first entry. */
if (default_entry < 0 || default_entry >= menu->size)
default_entry = 0;
/* If timeout is 0, drawing is pointless (and ugly). */
if (grub_menu_get_timeout () == 0)
{
*auto_boot = 1;
return default_entry;
}
offset = default_entry;
if (offset > GRUB_TERM_NUM_ENTRIES - 1)
{
first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
offset = GRUB_TERM_NUM_ENTRIES - 1;
}
/* Initialize the time. */
saved_time = grub_get_time_ms ();
refresh:
grub_setcursor (0);
grub_menu_init_page (nested, 0);
print_entries (menu, first, offset);
grub_refresh ();
timeout = grub_menu_get_timeout ();
if (timeout > 0)
print_timeout (timeout, offset);
while (1)
{
int c;
timeout = grub_menu_get_timeout ();
if (timeout > 0)
{
grub_uint64_t current_time;
current_time = grub_get_time_ms ();
if (current_time - saved_time >= 1000)
{
timeout--;
grub_menu_set_timeout (timeout);
saved_time = current_time;
print_timeout (timeout, offset);
}
}
if (timeout == 0)
{
grub_env_unset ("timeout");
*auto_boot = 1;
return default_entry;
}
if (grub_checkkey () >= 0 || timeout < 0)
{
c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
if (timeout >= 0)
{
grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
grub_print_spaces (GRUB_TERM_WIDTH - 1);
grub_env_unset ("timeout");
grub_env_unset ("fallback");
grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
}
switch (c)
{
case GRUB_TERM_HOME:
first = 0;
offset = 0;
print_entries (menu, first, offset);
break;
case GRUB_TERM_END:
offset = menu->size - 1;
if (offset > GRUB_TERM_NUM_ENTRIES - 1)
{
first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
offset = GRUB_TERM_NUM_ENTRIES - 1;
}
print_entries (menu, first, offset);
break;
case GRUB_TERM_UP:
case '^':
if (offset > 0)
{
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
grub_menu_get_entry (menu, first + offset));
offset--;
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
grub_menu_get_entry (menu, first + offset));
}
else if (first > 0)
{
first--;
print_entries (menu, first, offset);
}
break;
case GRUB_TERM_DOWN:
case 'v':
if (menu->size > first + offset + 1)
{
if (offset < GRUB_TERM_NUM_ENTRIES - 1)
{
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 0,
grub_menu_get_entry (menu, first + offset));
offset++;
print_entry (GRUB_TERM_FIRST_ENTRY_Y + offset, 1,
grub_menu_get_entry (menu, first + offset));
}
else
{
first++;
print_entries (menu, first, offset);
}
}
break;
case GRUB_TERM_PPAGE:
if (first == 0)
{
offset = 0;
}
else
{
first -= GRUB_TERM_NUM_ENTRIES;
if (first < 0)
{
offset += first;
first = 0;
}
}
print_entries (menu, first, offset);
break;
case GRUB_TERM_NPAGE:
if (offset == 0)
{
offset += GRUB_TERM_NUM_ENTRIES - 1;
if (first + offset >= menu->size)
{
offset = menu->size - first - 1;
}
}
else
{
first += GRUB_TERM_NUM_ENTRIES;
if (first + offset >= menu->size)
{
first -= GRUB_TERM_NUM_ENTRIES;
offset += GRUB_TERM_NUM_ENTRIES;
if (offset > menu->size - 1 ||
offset > GRUB_TERM_NUM_ENTRIES - 1)
{
offset = menu->size - first - 1;
}
if (offset > GRUB_TERM_NUM_ENTRIES)
{
first += offset - GRUB_TERM_NUM_ENTRIES + 1;
offset = GRUB_TERM_NUM_ENTRIES - 1;
}
}
}
print_entries (menu, first, offset);
break;
case '\n':
case '\r':
case 6:
grub_setcursor (1);
*auto_boot = 0;
return first + offset;
case '\e':
if (nested)
{
grub_setcursor (1);
return -1;
}
break;
case 'c':
grub_cmdline_run (1);
goto refresh;
case 'e':
{
grub_menu_entry_t e = grub_menu_get_entry (menu, first + offset);
if (e)
grub_menu_entry_run (e);
}
goto refresh;
default:
break;
}
grub_refresh ();
}
}
/* Never reach here. */
return -1;
}
/* Callback invoked immediately before a menu entry is executed. */
static void
notify_booting (grub_menu_entry_t entry,
void *userdata __attribute__((unused)))
{
grub_printf (" ");
grub_printf_ (N_("Booting \'%s\'"), entry->title);
grub_printf ("\n\n");
}
/* Callback invoked when a default menu entry executed because of a timeout
has failed and an attempt will be made to execute the next fallback
entry, ENTRY. */
static void
notify_fallback (grub_menu_entry_t entry,
void *userdata __attribute__((unused)))
{
grub_printf ("\n ");
grub_printf_ (N_("Falling back to \'%s\'"), entry->title);
grub_printf ("\n\n");
grub_millisleep (DEFAULT_ENTRY_ERROR_DELAY_MS);
}
/* Callback invoked when a menu entry has failed and there is no remaining
fallback entry to attempt. */
static void
notify_execution_failure (void *userdata __attribute__((unused)))
{
if (grub_errno != GRUB_ERR_NONE)
{ {
grub_print_error (); grub_print_error ();
grub_errno = GRUB_ERR_NONE; grub_errno = GRUB_ERR_NONE;
return;
} }
grub_printf ("\n ");
grub_printf_ (N_("Failed to boot default entries.\n")); grub_sprintf (msg_translated, msg, timeout);
grub_wait_after_message (); grub_print_message_indented (msg_translated, 3, 0, data->term);
posx = grub_term_getxy (data->term) >> 8;
print_spaces (grub_term_width (data->term) - posx - 1, data->term);
grub_term_gotoxy (data->term,
grub_term_cursor_x (data->term),
GRUB_TERM_FIRST_ENTRY_Y + data->offset);
grub_term_refresh (data->term);
} }
/* Callbacks used by the text menu to provide user feedback when menu entries static void
are executed. */ menu_text_set_chosen_entry (int entry, void *dataptr)
static struct grub_menu_execute_callback execution_callback =
{ {
.notify_booting = notify_booting, struct menu_viewer_data *data = dataptr;
.notify_fallback = notify_fallback, int oldoffset = data->offset;
.notify_failure = notify_execution_failure int complete_redraw = 0;
};
static grub_err_t data->offset = entry - data->first;
show_text_menu (grub_menu_t menu, int nested) if (data->offset > grub_term_num_entries (data->term) - 1)
{
while (1)
{ {
int boot_entry; data->first = entry - (grub_term_num_entries (data->term) - 1);
grub_menu_entry_t e; data->offset = grub_term_num_entries (data->term) - 1;
int auto_boot; complete_redraw = 1;
boot_entry = run_menu (menu, nested, &auto_boot);
if (boot_entry < 0)
break;
e = grub_menu_get_entry (menu, boot_entry);
if (! e)
continue; /* Menu is empty. */
grub_cls ();
grub_setcursor (1);
if (auto_boot)
{
grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
}
else
{
grub_errno = GRUB_ERR_NONE;
grub_menu_execute_entry (e);
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
grub_wait_after_message ();
}
}
} }
if (data->offset < 0)
{
data->offset = 0;
data->first = entry;
complete_redraw = 1;
}
if (complete_redraw)
print_entries (data->menu, data->first, data->offset, data->term);
else
{
print_entry (GRUB_TERM_FIRST_ENTRY_Y + oldoffset, 0,
grub_menu_get_entry (data->menu, data->first + oldoffset),
data->term);
print_entry (GRUB_TERM_FIRST_ENTRY_Y + data->offset, 1,
grub_menu_get_entry (data->menu, data->first + data->offset),
data->term);
}
grub_term_refresh (data->term);
}
static void
menu_text_fini (void *dataptr)
{
struct menu_viewer_data *data = dataptr;
grub_term_setcursor (data->term, 1);
grub_term_cls (data->term);
}
static void
menu_text_clear_timeout (void *dataptr)
{
struct menu_viewer_data *data = dataptr;
grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3);
print_spaces (grub_term_width (data->term) - 1, data->term);
grub_term_gotoxy (data->term, grub_term_cursor_x (data->term),
GRUB_TERM_FIRST_ENTRY_Y + data->offset);
grub_term_refresh (data->term);
}
grub_err_t
grub_menu_try_text (struct grub_term_output *term,
int entry, grub_menu_t menu, int nested)
{
struct menu_viewer_data *data;
struct grub_menu_viewer *instance;
instance = grub_zalloc (sizeof (*instance));
if (!instance)
return grub_errno;
data = grub_zalloc (sizeof (*data));
if (!data)
{
grub_free (instance);
return grub_errno;
}
data->term = term;
instance->data = data;
instance->set_chosen_entry = menu_text_set_chosen_entry;
instance->print_timeout = menu_text_print_timeout;
instance->clear_timeout = menu_text_clear_timeout;
instance->fini = menu_text_fini;
data->menu = menu;
data->offset = entry;
data->first = 0;
if (data->offset > grub_term_num_entries (data->term) - 1)
{
data->first = data->offset - (grub_term_num_entries (data->term) - 1);
data->offset = grub_term_num_entries (data->term) - 1;
}
grub_term_setcursor (data->term, 0);
grub_menu_init_page (nested, 0, data->term);
print_entries (menu, data->first, data->offset, data->term);
grub_term_refresh (data->term);
grub_menu_register_viewer (instance);
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }
struct grub_menu_viewer grub_normal_text_menu_viewer =
{
.name = "text",
.show_menu = show_text_menu
};

View file

@ -1,81 +0,0 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 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/>.
*/
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/env.h>
#include <grub/menu_viewer.h>
#include <grub/menu.h>
#include <grub/auth.h>
/* The list of menu viewers. */
static grub_menu_viewer_t menu_viewer_list;
void
grub_menu_viewer_register (grub_menu_viewer_t viewer)
{
viewer->next = menu_viewer_list;
menu_viewer_list = viewer;
}
static grub_menu_viewer_t get_current_menu_viewer (void)
{
const char *selected_name = grub_env_get ("menuviewer");
/* If none selected, pick the last registered one. */
if (selected_name == 0)
return menu_viewer_list;
grub_menu_viewer_t cur;
for (cur = menu_viewer_list; cur; cur = cur->next)
{
if (grub_strcmp (cur->name, selected_name) == 0)
return cur;
}
/* Fall back to the first entry (or null). */
return menu_viewer_list;
}
grub_err_t
grub_menu_viewer_show_menu (grub_menu_t menu, int nested)
{
grub_menu_viewer_t cur = get_current_menu_viewer ();
grub_err_t err1, err2;
if (!cur)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "no menu viewer available");
while (1)
{
err1 = cur->show_menu (menu, nested);
grub_print_error ();
err2 = grub_auth_check_authentication (NULL);
if (err2)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
continue;
}
break;
}
return err1;
}

252
normal/term.c Normal file
View file

@ -0,0 +1,252 @@
/*
* 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/>.
*/
#include <grub/term.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/file.h>
#include <grub/dl.h>
#include <grub/env.h>
#include <grub/normal.h>
/* The amount of lines counted by the pager. */
static unsigned grub_more_lines;
/* If the more pager is active. */
static int grub_more;
static void
process_newline (void)
{
struct grub_term_output *cur;
unsigned height = -1;
FOR_ACTIVE_TERM_OUTPUTS(cur)
if (grub_term_height (cur) < height)
height = grub_term_height (cur);
grub_more_lines++;
if (grub_more && grub_more_lines >= height - 1)
{
char key;
grub_uint16_t *pos;
pos = grub_term_save_pos ();
grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
grub_printf ("--MORE--");
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
key = grub_getkey ();
/* Remove the message. */
grub_term_restore_pos (pos);
grub_printf (" ");
grub_term_restore_pos (pos);
/* Scroll one lines or an entire page, depending on the key. */
if (key == '\r' || key =='\n')
grub_more_lines = height - 2;
else
grub_more_lines = 0;
}
}
void
grub_set_more (int onoff)
{
if (onoff == 1)
grub_more++;
else
grub_more--;
grub_more_lines = 0;
grub_newline_hook = process_newline;
}
void
grub_puts_terminal (const char *str, struct grub_term_output *term)
{
grub_uint32_t code;
grub_ssize_t ret;
const grub_uint8_t *ptr = (const grub_uint8_t *) str;
const grub_uint8_t *end;
end = (const grub_uint8_t *) (str + grub_strlen (str));
while (*ptr)
{
ret = grub_utf8_to_ucs4 (&code, 1, ptr, end - ptr, &ptr);
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_ACTIVE_TERM_OUTPUTS(cur)
cnt++;
ret = grub_malloc (cnt * sizeof (ret[0]));
if (!ret)
return NULL;
ptr = ret;
FOR_ACTIVE_TERM_OUTPUTS(cur)
*ptr++ = grub_term_getxy (cur);
return ret;
}
void
grub_term_restore_pos (grub_uint16_t *pos)
{
struct grub_term_output *cur;
grub_uint16_t *ptr = pos;
if (!pos)
return;
FOR_ACTIVE_TERM_OUTPUTS(cur)
{
grub_term_gotoxy (cur, (*ptr & 0xff00) >> 8, *ptr & 0xff);
ptr++;
}
}
static void
grub_terminal_autoload_free (void)
{
struct grub_term_autoload *cur, *next;
unsigned i;
for (i = 0; i < 2; i++)
for (cur = i ? grub_term_input_autoload : grub_term_output_autoload;
cur; cur = next)
{
next = cur->next;
grub_free (cur->name);
grub_free (cur->modname);
grub_free (cur);
}
grub_term_input_autoload = NULL;
grub_term_output_autoload = NULL;
}
/* Read the file terminal.lst for auto-loading. */
void
read_terminal_list (void)
{
const char *prefix;
char *filename;
grub_file_t file;
char *buf = NULL;
prefix = grub_env_get ("prefix");
if (!prefix)
{
grub_errno = GRUB_ERR_NONE;
return;
}
filename = grub_malloc (grub_strlen (prefix) + sizeof ("/terminal.lst"));
if (!filename)
{
grub_errno = GRUB_ERR_NONE;
return;
}
grub_sprintf (filename, "%s/terminal.lst", prefix);
file = grub_file_open (filename);
if (!file)
{
grub_errno = GRUB_ERR_NONE;
return;
}
/* Override previous terminal.lst. */
grub_terminal_autoload_free ();
for (;; grub_free (buf))
{
char *p, *name;
struct grub_term_autoload *cur;
struct grub_term_autoload **target = NULL;
buf = grub_file_getline (file);
if (! buf)
break;
switch (buf[0])
{
case 'i':
target = &grub_term_input_autoload;
break;
case 'o':
target = &grub_term_output_autoload;
break;
}
if (!target)
continue;
name = buf + 1;
p = grub_strchr (name, ':');
if (! p)
continue;
*p = '\0';
while (*++p == ' ')
;
cur = grub_malloc (sizeof (*cur));
if (!cur)
{
grub_errno = GRUB_ERR_NONE;
continue;
}
cur->name = grub_strdup (name);
if (! name)
{
grub_errno = GRUB_ERR_NONE;
grub_free (cur);
continue;
}
cur->modname = grub_strdup (p);
if (! cur->modname)
{
grub_errno = GRUB_ERR_NONE;
grub_free (cur);
grub_free (cur->name);
continue;
}
cur->next = *target;
*target = cur;
}
grub_file_close (file);
grub_errno = GRUB_ERR_NONE;
}

View file

@ -351,8 +351,7 @@ static struct grub_term_output grub_console_term_output =
.setcolorstate = grub_console_setcolorstate, .setcolorstate = grub_console_setcolorstate,
.setcolor = grub_console_setcolor, .setcolor = grub_console_setcolor,
.getcolor = grub_console_getcolor, .getcolor = grub_console_getcolor,
.setcursor = grub_console_setcursor, .setcursor = grub_console_setcursor
.flags = 0,
}; };
void void

View file

@ -65,8 +65,7 @@ static struct grub_term_output grub_console_term_output =
.setcolorstate = grub_console_setcolorstate, .setcolorstate = grub_console_setcolorstate,
.setcolor = grub_console_setcolor, .setcolor = grub_console_setcolor,
.getcolor = grub_console_getcolor, .getcolor = grub_console_getcolor,
.setcursor = grub_console_setcursor, .setcursor = grub_console_setcursor
.flags = 0,
}; };
void void
@ -79,10 +78,6 @@ grub_console_init (void)
void void
grub_console_fini (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_input (&grub_console_term_input);
grub_term_unregister_output (&grub_console_term_output); grub_term_unregister_output (&grub_console_term_output);
} }

View file

@ -31,6 +31,7 @@
#define TEXT_WIDTH 80 #define TEXT_WIDTH 80
#define TEXT_HEIGHT 25 #define TEXT_HEIGHT 25
static struct grub_term_output grub_serial_term_output;
static unsigned int xpos, ypos; static unsigned int xpos, ypos;
static unsigned int keep_track = 1; static unsigned int keep_track = 1;
static unsigned int registered = 0; static unsigned int registered = 0;
@ -414,7 +415,7 @@ grub_serial_gotoxy (grub_uint8_t x, grub_uint8_t y)
else else
{ {
keep_track = 0; keep_track = 0;
grub_terminfo_gotoxy (x, y); grub_terminfo_gotoxy (x, y, &grub_serial_term_output);
keep_track = 1; keep_track = 1;
xpos = x; xpos = x;
@ -426,7 +427,7 @@ static void
grub_serial_cls (void) grub_serial_cls (void)
{ {
keep_track = 0; keep_track = 0;
grub_terminfo_cls (); grub_terminfo_cls (&grub_serial_term_output);
keep_track = 1; keep_track = 1;
xpos = ypos = 0; xpos = ypos = 0;
@ -440,10 +441,10 @@ grub_serial_setcolorstate (const grub_term_color_state state)
{ {
case GRUB_TERM_COLOR_STANDARD: case GRUB_TERM_COLOR_STANDARD:
case GRUB_TERM_COLOR_NORMAL: case GRUB_TERM_COLOR_NORMAL:
grub_terminfo_reverse_video_off (); grub_terminfo_reverse_video_off (&grub_serial_term_output);
break; break;
case GRUB_TERM_COLOR_HIGHLIGHT: case GRUB_TERM_COLOR_HIGHLIGHT:
grub_terminfo_reverse_video_on (); grub_terminfo_reverse_video_on (&grub_serial_term_output);
break; break;
default: default:
break; break;
@ -455,9 +456,9 @@ static void
grub_serial_setcursor (const int on) grub_serial_setcursor (const int on)
{ {
if (on) if (on)
grub_terminfo_cursor_on (); grub_terminfo_cursor_on (&grub_serial_term_output);
else else
grub_terminfo_cursor_off (); grub_terminfo_cursor_off (&grub_serial_term_output);
} }
static struct grub_term_input grub_serial_term_input = static struct grub_term_input grub_serial_term_input =

View file

@ -88,7 +88,7 @@ grub_ofconsole_putchar (grub_uint32_t c)
grub_curr_x++; grub_curr_x++;
if (grub_curr_x > grub_ofconsole_width) if (grub_curr_x > grub_ofconsole_width)
{ {
grub_putcode ('\n'); grub_ofconsole_putchar ('\n');
grub_curr_x++; grub_curr_x++;
} }
} }
@ -319,7 +319,7 @@ grub_ofconsole_cls (void)
* ANSI escape sequence. Using video console, Apple Open Firmware (version * ANSI escape sequence. Using video console, Apple Open Firmware (version
* 3.1.1) only recognizes the literal ^L. So use both. */ * 3.1.1) only recognizes the literal ^L. So use both. */
grub_ofconsole_writeesc (" \e[2J"); grub_ofconsole_writeesc (" \e[2J");
grub_gotoxy (0, 0); grub_ofconsole_gotoxy (0, 0);
} }
static void static void
@ -414,8 +414,7 @@ static struct grub_term_output grub_ofconsole_term_output =
.setcolor = grub_ofconsole_setcolor, .setcolor = grub_ofconsole_setcolor,
.getcolor = grub_ofconsole_getcolor, .getcolor = grub_ofconsole_getcolor,
.setcursor = grub_ofconsole_setcursor, .setcursor = grub_ofconsole_setcursor,
.refresh = grub_ofconsole_refresh, .refresh = grub_ofconsole_refresh
.flags = 0,
}; };
void void

View file

@ -108,52 +108,52 @@ grub_terminfo_set_current (const char *str)
/* Wrapper for grub_putchar to write strings. */ /* Wrapper for grub_putchar to write strings. */
static void static void
putstr (const char *str) putstr (const char *str, grub_term_output_t oterm)
{ {
while (*str) while (*str)
grub_putchar (*str++); grub_putcode (*str++, oterm);
} }
/* Move the cursor to the given position starting with "0". */ /* Move the cursor to the given position starting with "0". */
void void
grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y) grub_terminfo_gotoxy (grub_uint8_t x, grub_uint8_t y, grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.gotoxy, y, x)); putstr (grub_terminfo_tparm (term.gotoxy, y, x), oterm);
} }
/* Clear the screen. */ /* Clear the screen. */
void void
grub_terminfo_cls (void) grub_terminfo_cls (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.cls)); putstr (grub_terminfo_tparm (term.cls), oterm);
} }
/* Set reverse video mode on. */ /* Set reverse video mode on. */
void void
grub_terminfo_reverse_video_on (void) grub_terminfo_reverse_video_on (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.reverse_video_on)); putstr (grub_terminfo_tparm (term.reverse_video_on), oterm);
} }
/* Set reverse video mode off. */ /* Set reverse video mode off. */
void void
grub_terminfo_reverse_video_off (void) grub_terminfo_reverse_video_off (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.reverse_video_off)); putstr (grub_terminfo_tparm (term.reverse_video_off), oterm);
} }
/* Show cursor. */ /* Show cursor. */
void void
grub_terminfo_cursor_on (void) grub_terminfo_cursor_on (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.cursor_on)); putstr (grub_terminfo_tparm (term.cursor_on), oterm);
} }
/* Hide cursor. */ /* Hide cursor. */
void void
grub_terminfo_cursor_off (void) grub_terminfo_cursor_off (grub_term_output_t oterm)
{ {
putstr (grub_terminfo_tparm (term.cursor_off)); putstr (grub_terminfo_tparm (term.cursor_off), oterm);
} }
/* GRUB Command. */ /* GRUB Command. */

View file

@ -19,14 +19,6 @@
#include <config.h> #include <config.h>
#if defined(HAVE_NCURSES_CURSES_H)
# include <ncurses/curses.h>
#elif defined(HAVE_NCURSES_H)
# include <ncurses.h>
#elif defined(HAVE_CURSES_H)
# include <curses.h>
#endif
/* For compatibility. */ /* For compatibility. */
#ifndef A_NORMAL #ifndef A_NORMAL
# define A_NORMAL 0 # define A_NORMAL 0
@ -39,6 +31,14 @@
#include <grub/term.h> #include <grub/term.h>
#include <grub/types.h> #include <grub/types.h>
#if defined(HAVE_NCURSES_CURSES_H)
# include <ncurses/curses.h>
#elif defined(HAVE_NCURSES_H)
# include <ncurses.h>
#elif defined(HAVE_CURSES_H)
# include <curses.h>
#endif
static int grub_console_attr = A_NORMAL; static int grub_console_attr = A_NORMAL;
grub_uint8_t grub_console_cur_color = 7; grub_uint8_t grub_console_cur_color = 7;
@ -367,8 +367,7 @@ static struct grub_term_output grub_ncurses_term_output =
.setcolor = grub_ncurses_setcolor, .setcolor = grub_ncurses_setcolor,
.getcolor = grub_ncurses_getcolor, .getcolor = grub_ncurses_getcolor,
.setcursor = grub_ncurses_setcursor, .setcursor = grub_ncurses_setcursor,
.refresh = grub_ncurses_refresh, .refresh = grub_ncurses_refresh
.flags = 0,
}; };
void void
@ -376,8 +375,6 @@ grub_console_init (void)
{ {
grub_term_register_output ("console", &grub_ncurses_term_output); grub_term_register_output ("console", &grub_ncurses_term_output);
grub_term_register_input ("console", &grub_ncurses_term_input); grub_term_register_input ("console", &grub_ncurses_term_input);
grub_term_set_current_output (&grub_ncurses_term_output);
grub_term_set_current_input (&grub_ncurses_term_input);
} }
void void

View file

@ -46,9 +46,6 @@ grub_refresh (void)
fflush (stdout); fflush (stdout);
} }
struct grub_handler_class grub_term_input_class;
struct grub_handler_class grub_term_output_class;
int int
grub_getkey (void) grub_getkey (void)
{ {