merge mainline into backtrace

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2011-11-14 10:50:24 +01:00
commit 245f4582f9
871 changed files with 102908 additions and 16407 deletions

View file

@ -34,7 +34,7 @@ struct grub_auth_user
int authenticated;
};
struct grub_auth_user *users = NULL;
static struct grub_auth_user *users = NULL;
grub_err_t
grub_auth_register_authentication (const char *user,
@ -161,7 +161,7 @@ grub_username_get (char buf[], unsigned buf_size)
while (1)
{
key = GRUB_TERM_ASCII_CHAR (grub_getkey ());
key = grub_getkey ();
if (key == '\n' || key == '\r')
break;
@ -201,7 +201,6 @@ grub_auth_check_authentication (const char *userlist)
{
char login[1024];
struct grub_auth_user *cur = NULL;
grub_err_t err;
static unsigned long punishment_delay = 1;
char entered[GRUB_AUTH_MAX_PASSLEN];
struct grub_auth_user *user;
@ -233,7 +232,7 @@ grub_auth_check_authentication (const char *userlist)
if (!cur || ! cur->callback)
goto access_denied;
err = cur->callback (login, entered, cur->arg);
cur->callback (login, entered, cur->arg);
if (is_authenticated (userlist))
{
punishment_delay = 1;
@ -248,3 +247,27 @@ grub_auth_check_authentication (const char *userlist)
return GRUB_ACCESS_DENIED;
}
static grub_err_t
grub_cmd_authenticate (struct grub_command *cmd __attribute__ ((unused)),
int argc, char **args)
{
return grub_auth_check_authentication ((argc >= 1) ? args[0] : "");
}
static grub_command_t cmd;
void
grub_normal_auth_init (void)
{
cmd = grub_register_command ("authenticate",
grub_cmd_authenticate,
N_("[USERLIST]"), N_("Authenticate users"));
}
void
grub_normal_auth_fini (void)
{
grub_unregister_command (cmd);
}

View file

@ -113,16 +113,6 @@ grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
count = 3;
code = c & GRUB_UINT8_3_TRAILINGBITS;
}
else if ((c & GRUB_UINT8_6_LEADINGBITS) == GRUB_UINT8_5_LEADINGBITS)
{
count = 4;
code = c & GRUB_UINT8_2_TRAILINGBITS;
}
else if ((c & GRUB_UINT8_7_LEADINGBITS) == GRUB_UINT8_6_LEADINGBITS)
{
count = 5;
code = c & GRUB_UINT8_1_TRAILINGBIT;
}
else
return -1;
}
@ -177,7 +167,7 @@ grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size,
/* No surrogates in UCS-4... */
*dest++ = '?';
}
else
else if (code < 0x10000)
{
if (dest + 2 >= destend)
break;
@ -185,6 +175,15 @@ grub_ucs4_to_utf8 (grub_uint32_t *src, grub_size_t size,
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
else
{
if (dest + 3 >= destend)
break;
*dest++ = (code >> 18) | 0xF0;
*dest++ = ((code >> 12) & 0x3F) | 0x80;
*dest++ = ((code >> 6) & 0x3F) | 0x80;
*dest++ = (code & 0x3F) | 0x80;
}
}
*dest = 0;
}
@ -212,8 +211,10 @@ grub_ucs4_to_utf8_alloc (grub_uint32_t *src, grub_size_t size)
|| (code >= 0xD800 && code <= 0xDBFF))
/* No surrogates in UCS-4... */
cnt++;
else
else if (code < 0x10000)
cnt += 3;
else
cnt += 4;
}
cnt++;
@ -273,16 +274,6 @@ grub_is_valid_utf8 (const grub_uint8_t *src, grub_size_t srcsize)
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;
}
@ -375,16 +366,6 @@ grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_size_t destsize,
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
{
/* invalid */

View file

@ -240,7 +240,7 @@ grub_cmdline_get (const char *prompt)
grub_term_gotoxy (cl_term->term, cl_term->xpos, cl_term->ypos);
}
void cl_set_pos_all ()
void cl_set_pos_all (void)
{
unsigned i;
for (i = 0; i < nterms; i++)
@ -388,16 +388,18 @@ grub_cmdline_get (const char *prompt)
grub_refresh ();
while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r')
while ((key = grub_getkey ()) != '\n' && key != '\r')
{
switch (key)
{
case 1: /* Ctrl-a */
case GRUB_TERM_CTRL | 'a':
case GRUB_TERM_KEY_HOME:
lpos = 0;
cl_set_pos_all ();
break;
case 2: /* Ctrl-b */
case GRUB_TERM_CTRL | 'b':
case GRUB_TERM_KEY_LEFT:
if (lpos > 0)
{
lpos--;
@ -405,12 +407,14 @@ grub_cmdline_get (const char *prompt)
}
break;
case 5: /* Ctrl-e */
case GRUB_TERM_CTRL | 'e':
case GRUB_TERM_KEY_END:
lpos = llen;
cl_set_pos_all ();
break;
case 6: /* Ctrl-f */
case GRUB_TERM_CTRL | 'f':
case GRUB_TERM_KEY_RIGHT:
if (lpos < llen)
{
lpos++;
@ -418,7 +422,8 @@ grub_cmdline_get (const char *prompt)
}
break;
case 9: /* Ctrl-i or TAB */
case GRUB_TERM_CTRL | 'i':
case '\t':
{
int restore;
char *insertu8;
@ -492,11 +497,10 @@ grub_cmdline_get (const char *prompt)
}
break;
case 11: /* Ctrl-k */
case GRUB_TERM_CTRL | 'k':
if (lpos < llen)
{
if (kill_buf)
grub_free (kill_buf);
grub_free (kill_buf);
kill_buf = grub_malloc ((llen - lpos + 1)
* sizeof (grub_uint32_t));
@ -516,7 +520,8 @@ grub_cmdline_get (const char *prompt)
}
break;
case 14: /* Ctrl-n */
case GRUB_TERM_CTRL | 'n':
case GRUB_TERM_KEY_DOWN:
{
grub_uint32_t *hist;
@ -534,7 +539,9 @@ grub_cmdline_get (const char *prompt)
break;
}
case 16: /* Ctrl-p */
case GRUB_TERM_KEY_UP:
case GRUB_TERM_CTRL | 'p':
{
grub_uint32_t *hist;
@ -553,13 +560,12 @@ grub_cmdline_get (const char *prompt)
}
break;
case 21: /* Ctrl-u */
case GRUB_TERM_CTRL | 'u':
if (lpos > 0)
{
grub_size_t n = lpos;
if (kill_buf)
grub_free (kill_buf);
grub_free (kill_buf);
kill_buf = grub_malloc (n + 1);
if (grub_errno)
@ -579,7 +585,7 @@ grub_cmdline_get (const char *prompt)
}
break;
case 25: /* Ctrl-y */
case GRUB_TERM_CTRL | 'y':
if (kill_buf)
cl_insert (kill_buf);
break;
@ -598,7 +604,8 @@ grub_cmdline_get (const char *prompt)
break;
/* fall through */
case 4: /* Ctrl-d */
case GRUB_TERM_CTRL | 'd':
case GRUB_TERM_KEY_DC:
if (lpos < llen)
cl_delete (1);
break;

View file

@ -100,15 +100,16 @@ static int
iterate_partition (grub_disk_t disk, const grub_partition_t p)
{
const char *disk_name = disk->name;
char *partition_name = grub_partition_get_name (p);
char *name;
int ret;
char *part_name;
if (! partition_name)
part_name = grub_partition_get_name (p);
if (! part_name)
return 1;
name = grub_xasprintf ("%s,%s", disk_name, partition_name);
grub_free (partition_name);
name = grub_xasprintf ("%s,%s", disk_name, part_name);
grub_free (part_name);
if (! name)
return 1;

View file

@ -31,8 +31,8 @@ struct menu_pointer
struct menu_pointer *prev;
};
struct menu_pointer initial_menu;
struct menu_pointer *current_menu = &initial_menu;
static struct menu_pointer initial_menu;
static struct menu_pointer *current_menu = &initial_menu;
void
grub_env_unset_menu (void)
@ -52,8 +52,8 @@ grub_env_set_menu (grub_menu_t nmenu)
current_menu->menu = nmenu;
}
grub_err_t
grub_env_context_open (int export)
static grub_err_t
grub_env_new_context (int export_all)
{
struct grub_env_context *context;
int i;
@ -78,23 +78,36 @@ grub_env_context_open (int export)
struct grub_env_var *var;
for (var = context->prev->vars[i]; var; var = var->next)
{
if (export && var->global)
{
if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
{
grub_env_context_close ();
return grub_errno;
}
grub_env_export (var->name);
grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
}
}
if (var->global || export_all)
{
if (grub_env_set (var->name, var->value) != GRUB_ERR_NONE)
{
grub_env_context_close ();
return grub_errno;
}
grub_env_export (var->name);
grub_register_variable_hook (var->name, var->read_hook, var->write_hook);
}
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_env_context_open (void)
{
return grub_env_new_context (0);
}
int grub_extractor_level = 0;
grub_err_t
grub_env_extractor_open (int source)
{
grub_extractor_level++;
return grub_env_new_context (source);
}
grub_err_t
grub_env_context_close (void)
{
@ -133,23 +146,34 @@ grub_env_context_close (void)
}
grub_err_t
grub_env_export (const char *name)
grub_env_extractor_close (int source)
{
struct grub_env_var *var;
grub_menu_t menu = NULL;
grub_menu_entry_t *last;
grub_err_t err;
var = grub_env_find (name);
if (! var)
if (source)
{
grub_err_t err;
err = grub_env_set (name, "");
if (err)
return err;
var = grub_env_find (name);
}
var->global = 1;
menu = grub_env_get_menu ();
grub_env_unset_menu ();
}
err = grub_env_context_close ();
return GRUB_ERR_NONE;
if (source)
{
grub_menu_t menu2;
menu2 = grub_env_get_menu ();
last = &menu2->entry_list;
while (*last)
last = &(*last)->next;
*last = menu->entry_list;
menu2->size += menu->size;
}
grub_extractor_level--;
return err;
}
static grub_command_t export_cmd;
@ -173,9 +197,6 @@ grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
void
grub_context_init (void)
{
grub_env_export ("root");
grub_env_export ("prefix");
export_cmd = grub_register_command ("export", grub_cmd_export,
N_("ENVVAR [ENVVAR] ..."),
N_("Export variables."));

View file

@ -31,7 +31,7 @@ struct load_spec
char *modname;
};
struct load_spec *crypto_specs = NULL;
static struct load_spec *crypto_specs = NULL;
static void
grub_crypto_autoload (const char *name)

View file

@ -18,16 +18,17 @@
*/
#include <grub/datetime.h>
#include <grub/i18n.h>
static char *grub_weekday_names[] =
static const char *grub_weekday_names[] =
{
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
N_("Sunday"),
N_("Monday"),
N_("Tuesday"),
N_("Wednesday"),
N_("Thursday"),
N_("Friday"),
N_("Saturday"),
};
int
@ -42,10 +43,10 @@ grub_get_weekday (struct grub_datetime *datetime)
return (datetime->day + y + y / 4 - y / 100 + y / 400 + (31 * m / 12)) % 7;
}
char *
const char *
grub_get_weekday_name (struct grub_datetime *datetime)
{
return grub_weekday_names[grub_get_weekday (datetime)];
return _ (grub_weekday_names[grub_get_weekday (datetime)]);
}
#define SECPERMIN 60

View file

@ -33,6 +33,8 @@
#include <grub/charset.h>
#include <grub/script_sh.h>
GRUB_MOD_LICENSE ("GPLv3+");
#define GRUB_DEFAULT_HISTORY_SIZE 50
static int nested_level = 0;
@ -123,8 +125,8 @@ grub_file_getline (grub_file_t file)
return cmdline;
}
static void
free_menu (grub_menu_t menu)
void
grub_normal_free_menu (grub_menu_t menu)
{
grub_menu_entry_t entry = menu->entry_list;
@ -272,7 +274,6 @@ grub_normal_execute (const char *config, int nested, int batch)
prefix = grub_env_get ("prefix");
read_lists (prefix);
grub_register_variable_hook ("prefix", NULL, read_lists_hook);
grub_command_execute ("parser.grub", 0, 0);
}
if (config)
@ -287,9 +288,9 @@ grub_normal_execute (const char *config, int nested, int batch)
{
if (menu && menu->size)
{
grub_show_menu (menu, nested);
grub_show_menu (menu, nested, 0);
if (nested)
free_menu (menu);
grub_normal_free_menu (menu);
}
}
}
@ -471,12 +472,18 @@ grub_mini_cmd_clear (struct grub_command *cmd __attribute__ ((unused)),
static grub_command_t cmd_clear;
static void (*grub_xputs_saved) (const char *str);
static const char *features[] = {
"feature_chainloader_bpb", "feature_ntldr"
};
GRUB_MOD_INIT(normal)
{
unsigned i;
/* Previously many modules depended on gzio. Be nice to user and load it. */
grub_dl_load ("gzio");
grub_normal_auth_init ();
grub_context_init ();
grub_script_init ();
grub_menu_init ();
@ -495,6 +502,7 @@ GRUB_MOD_INIT(normal)
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
grub_register_variable_hook ("pager", 0, grub_env_write_pager);
grub_env_export ("pager");
/* Register a command "normal" for the rescue mode. */
grub_register_command ("normal", grub_cmd_normal,
@ -513,6 +521,12 @@ GRUB_MOD_INIT(normal)
/* Set default color names. */
grub_env_set ("color_normal", "white/black");
grub_env_set ("color_highlight", "black/white");
for (i = 0; i < ARRAY_SIZE (features); i++)
{
grub_env_set (features[i], "y");
grub_env_export (features[i]);
}
}
GRUB_MOD_FINI(normal)
@ -520,6 +534,7 @@ GRUB_MOD_FINI(normal)
grub_context_fini ();
grub_script_fini ();
grub_menu_fini ();
grub_normal_auth_fini ();
grub_xputs = grub_xputs_saved;

View file

@ -30,6 +30,8 @@
#include <grub/i18n.h>
#include <grub/term.h>
#include <grub/script_sh.h>
#include <grub/gfxterm.h>
#include <grub/dl.h>
/* Time to delay after displaying an error message about a default/fallback
entry failing to boot. */
@ -77,7 +79,7 @@ grub_menu_get_entry (grub_menu_t menu, int no)
int
grub_menu_get_timeout (void)
{
char *val;
const char *val;
int timeout;
val = grub_env_get ("timeout");
@ -122,7 +124,7 @@ grub_menu_set_timeout (int timeout)
static int
get_and_remove_first_entry_number (const char *name)
{
char *val;
const char *val;
char *tail;
int entry;
@ -154,10 +156,15 @@ get_and_remove_first_entry_number (const char *name)
}
/* Run a menu entry. */
void
grub_menu_execute_entry(grub_menu_entry_t entry)
static void
grub_menu_execute_entry(grub_menu_entry_t entry, int auto_boot)
{
grub_err_t err = GRUB_ERR_NONE;
int errs_before;
grub_menu_t menu = NULL;
char *optr, *buf, *oldchosen = NULL, *olddefault = NULL;
const char *ptr, *chosen, *def;
grub_size_t sz = 0;
if (entry->restricted)
err = grub_auth_check_authentication (entry->users);
@ -169,21 +176,116 @@ grub_menu_execute_entry(grub_menu_entry_t entry)
return;
}
grub_env_set ("chosen", entry->title);
errs_before = grub_err_printed_errors;
chosen = grub_env_get ("chosen");
def = grub_env_get ("default");
if (entry->submenu)
{
grub_env_context_open ();
menu = grub_zalloc (sizeof (*menu));
if (! menu)
return;
grub_env_set_menu (menu);
if (auto_boot)
grub_env_set ("timeout", "0");
}
for (ptr = entry->title; *ptr; ptr++)
sz += (*ptr == '>') ? 2 : 1;
if (chosen)
{
oldchosen = grub_strdup (chosen);
if (!oldchosen)
grub_print_error ();
}
if (def)
{
olddefault = grub_strdup (def);
if (!olddefault)
grub_print_error ();
}
sz++;
if (chosen)
sz += grub_strlen (chosen);
sz++;
buf = grub_malloc (sz);
if (!buf)
grub_print_error ();
else
{
optr = buf;
if (chosen)
{
optr = grub_stpcpy (optr, chosen);
*optr++ = '>';
}
for (ptr = entry->title; *ptr; ptr++)
{
if (*ptr == '>')
*optr++ = '>';
*optr++ = *ptr;
}
*optr = 0;
grub_env_set ("chosen", buf);
grub_env_export ("chosen");
grub_free (buf);
}
for (ptr = def; ptr && *ptr; ptr++)
{
if (ptr[0] == '>' && ptr[1] == '>')
{
ptr++;
continue;
}
if (ptr[0] == '>')
break;
}
if (ptr && ptr[0] && ptr[1])
grub_env_set ("default", ptr + 1);
else
grub_env_unset ("default");
grub_script_execute_sourcecode (entry->sourcecode, entry->argc, entry->args);
if (errs_before != grub_err_printed_errors)
grub_wait_after_message ();
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */
grub_command_execute ("boot", 0, 0);
if (entry->submenu)
{
if (menu && menu->size)
{
grub_show_menu (menu, 1, auto_boot);
grub_normal_free_menu (menu);
}
grub_env_context_close ();
}
if (oldchosen)
grub_env_set ("chosen", oldchosen);
else
grub_env_unset ("chosen");
if (olddefault)
grub_env_set ("default", olddefault);
else
grub_env_unset ("default");
grub_env_unset ("timeout");
}
/* Execute ENTRY from the menu MENU, falling back to entries specified
in the environment variable "fallback" if it fails. CALLBACK is a
pointer to a struct of function pointers which are used to allow the
caller provide feedback to the user. */
void
static void
grub_menu_execute_with_fallback (grub_menu_t menu,
grub_menu_entry_t entry,
int autobooted,
grub_menu_execute_callback_t callback,
void *callback_data)
{
@ -191,7 +293,7 @@ grub_menu_execute_with_fallback (grub_menu_t menu,
callback->notify_booting (entry, callback_data);
grub_menu_execute_entry (entry);
grub_menu_execute_entry (entry, 1);
/* Deal with fallback entries. */
while ((fallback_entry = get_and_remove_first_entry_number ("fallback"))
@ -202,14 +304,15 @@ grub_menu_execute_with_fallback (grub_menu_t menu,
entry = grub_menu_get_entry (menu, fallback_entry);
callback->notify_fallback (entry, callback_data);
grub_menu_execute_entry (entry);
grub_menu_execute_entry (entry, 1);
/* If the function call to execute the entry returns at all, then this is
taken to indicate a boot failure. For menu entries that do something
other than actually boot an operating system, this could assume
incorrectly that something failed. */
}
callback->notify_failure (callback_data);
if (!autobooted)
callback->notify_failure (callback_data);
}
static struct grub_menu_viewer *viewers;
@ -247,18 +350,44 @@ static void
menu_init (int entry, grub_menu_t menu, int nested)
{
struct grub_term_output *term;
int gfxmenu = 0;
FOR_ACTIVE_TERM_OUTPUTS(term)
if (grub_strcmp (term->name, "gfxterm") == 0)
{
if (grub_env_get ("theme"))
{
if (!grub_gfxmenu_try_hook)
{
grub_dl_load ("gfxmenu");
grub_print_error ();
}
if (grub_gfxmenu_try_hook)
{
grub_err_t err;
err = grub_gfxmenu_try_hook (entry, menu, nested);
if(!err)
{
gfxmenu = 1;
break;
}
}
else
grub_error (GRUB_ERR_BAD_MODULE, "no gfxmenu found");
grub_print_error ();
grub_wait_after_message ();
}
grub_errno = GRUB_ERR_NONE;
grub_gfxterm_fullscreen ();
break;
}
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_errno = GRUB_ERR_NONE;
}
if (grub_strcmp (term->name, "gfxterm") == 0 && gfxmenu)
break;
err = grub_menu_try_text (term, entry, menu, nested);
if(!err)
@ -283,11 +412,35 @@ grub_menu_register_viewer (struct grub_menu_viewer *viewer)
viewers = viewer;
}
static int
menuentry_eq (const char *title, const char *spec)
{
const char *ptr1, *ptr2;
ptr1 = title;
ptr2 = spec;
while (1)
{
if (*ptr2 == '>' && ptr2[1] != '>' && *ptr1 == 0)
return 1;
if (*ptr2 == '>' && ptr2[1] != '>')
return 0;
if (*ptr2 == '>')
ptr2++;
if (*ptr1 != *ptr2)
return 0;
if (*ptr1 == 0)
return 1;
ptr1++;
ptr2++;
}
}
/* Get the entry number from the variable NAME. */
static int
get_entry_number (grub_menu_t menu, const char *name)
{
char *val;
const char *val;
int entry;
val = grub_env_get (name);
@ -308,7 +461,7 @@ get_entry_number (grub_menu_t menu, const char *name)
for (i = 0; e; i++)
{
if (grub_strcmp (e->title, val) == 0)
if (menuentry_eq (e->title, val))
{
entry = i;
break;
@ -407,7 +560,7 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
if (grub_checkkey () >= 0 || timeout < 0)
{
c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
c = grub_getkey ();
if (timeout >= 0)
{
@ -418,31 +571,36 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
switch (c)
{
case GRUB_TERM_HOME:
case GRUB_TERM_KEY_HOME:
case GRUB_TERM_CTRL | 'a':
current_entry = 0;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_END:
case GRUB_TERM_KEY_END:
case GRUB_TERM_CTRL | 'e':
current_entry = menu->size - 1;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_UP:
case GRUB_TERM_KEY_UP:
case GRUB_TERM_CTRL | 'p':
case '^':
if (current_entry > 0)
current_entry--;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_DOWN:
case GRUB_TERM_CTRL | 'n':
case GRUB_TERM_KEY_DOWN:
case 'v':
if (current_entry < menu->size - 1)
current_entry++;
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_PPAGE:
case GRUB_TERM_CTRL | 'g':
case GRUB_TERM_KEY_PPAGE:
if (current_entry < GRUB_MENU_PAGE_SIZE)
current_entry = 0;
else
@ -450,7 +608,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
menu_set_chosen_entry (current_entry);
break;
case GRUB_TERM_NPAGE:
case GRUB_TERM_CTRL | 'c':
case GRUB_TERM_KEY_NPAGE:
if (current_entry + GRUB_MENU_PAGE_SIZE < menu->size)
current_entry += GRUB_MENU_PAGE_SIZE;
else
@ -460,7 +619,8 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot)
case '\n':
case '\r':
case 6:
case GRUB_TERM_KEY_RIGHT:
case GRUB_TERM_CTRL | 'f':
menu_fini ();
*auto_boot = 0;
return current_entry;
@ -557,7 +717,7 @@ static struct grub_menu_execute_callback execution_callback =
};
static grub_err_t
show_menu (grub_menu_t menu, int nested)
show_menu (grub_menu_t menu, int nested, int autobooted)
{
while (1)
{
@ -576,33 +736,26 @@ show_menu (grub_menu_t menu, int nested)
grub_cls ();
if (auto_boot)
{
grub_menu_execute_with_fallback (menu, e, &execution_callback, 0);
}
grub_menu_execute_with_fallback (menu, e, autobooted,
&execution_callback, 0);
else
{
int chars_before = grub_normal_get_char_counter ();
grub_errno = GRUB_ERR_NONE;
grub_menu_execute_entry (e);
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
if (chars_before != grub_normal_get_char_counter ())
grub_wait_after_message ();
}
grub_menu_execute_entry (e, 0);
if (autobooted)
break;
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_show_menu (grub_menu_t menu, int nested)
grub_show_menu (grub_menu_t menu, int nested, int autoboot)
{
grub_err_t err1, err2;
while (1)
{
err1 = show_menu (menu, nested);
err1 = show_menu (menu, nested, autoboot);
autoboot = 0;
grub_print_error ();
if (grub_normal_exit_level)

View file

@ -52,6 +52,8 @@ struct per_term_screen
int x;
/* The Y coordinate. */
int y;
/* Number of entries. */
int num_entries;
};
struct screen
@ -71,6 +73,8 @@ struct screen
/* The flag of a completion window. */
int completion_shown;
int submenu;
struct per_term_screen *terms;
unsigned nterms;
};
@ -85,7 +89,7 @@ init_line (struct line *linep)
{
linep->len = 0;
linep->max_len = 80; /* XXX */
linep->buf = grub_malloc (linep->max_len);
linep->buf = grub_malloc (linep->max_len + 1);
if (! linep->buf)
return 0;
@ -170,7 +174,7 @@ static void
print_up (int flag, struct per_term_screen *term_screen)
{
grub_term_gotoxy (term_screen->term, GRUB_TERM_LEFT_BORDER_X
+ grub_term_entry_width (term_screen->term),
+ grub_term_border_width (term_screen->term),
GRUB_TERM_FIRST_ENTRY_Y);
if (flag)
@ -186,7 +190,7 @@ print_down (int flag, struct per_term_screen *term_screen)
grub_term_gotoxy (term_screen->term, GRUB_TERM_LEFT_BORDER_X
+ grub_term_border_width (term_screen->term),
GRUB_TERM_TOP_BORDER_Y
+ grub_term_num_entries (term_screen->term));
+ term_screen->num_entries);
if (flag)
grub_putcode (GRUB_UNICODE_DOWNARROW, term_screen->term);
@ -207,13 +211,12 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen,
struct line *linep;
/* Check if scrolling is necessary. */
if (term_screen->y < 0 || term_screen->y
>= grub_term_num_entries (term_screen->term))
if (term_screen->y < 0 || term_screen->y >= term_screen->num_entries)
{
if (term_screen->y < 0)
term_screen->y = 0;
else
term_screen->y = grub_term_num_entries (term_screen->term) - 1;
term_screen->y = term_screen->num_entries - 1;
region_start = 0;
region_column = 0;
@ -249,7 +252,7 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen,
for (column = 0;
column <= linep->len
&& y < grub_term_num_entries (term_screen->term);
&& y < term_screen->num_entries;
column += grub_term_entry_width (term_screen->term), y++)
{
if (y < 0)
@ -270,7 +273,7 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen,
print_line (linep, column, 0, y, term_screen);
}
if (y == grub_term_num_entries (term_screen->term))
if (y == term_screen->num_entries)
{
if (column <= linep->len || i + 1 < screen->num_lines)
down_flag = 1;
@ -280,11 +283,11 @@ update_screen (struct screen *screen, struct per_term_screen *term_screen,
i++;
if (mode == ALL_LINES && i == screen->num_lines)
for (; y < grub_term_num_entries (term_screen->term); y++)
for (; y < term_screen->num_entries; y++)
print_empty_line (y, term_screen);
}
while (y < grub_term_num_entries (term_screen->term));
while (y < term_screen->num_entries);
/* Draw up and down arrows. */
if (up)
@ -496,6 +499,8 @@ make_screen (grub_menu_entry_t entry)
if (! screen)
return 0;
screen->submenu = entry->submenu;
screen->num_lines = 1;
screen->lines = grub_malloc (sizeof (struct line));
if (! screen->lines)
@ -1159,54 +1164,76 @@ clear_completions_all (struct screen *screen)
static int
run (struct screen *screen)
{
int currline = 0;
char *nextline;
char *script;
int errs_before;
grub_menu_t menu = NULL;
char *dummy[1] = { NULL };
auto grub_err_t editor_getline (char **line, int cont);
grub_err_t editor_getline (char **line, int cont __attribute__ ((unused)))
{
struct line *linep = screen->lines + currline;
char *p;
auto char * editor_getsource (void);
char * editor_getsource (void)
{
int i;
int size = 0;
char *source;
if (currline > screen->num_lines)
{
*line = 0;
return 0;
}
for (i = 0; i < screen->num_lines; i++)
size += screen->lines[i].len + 1;
/* Trim down space characters. */
for (p = linep->buf + linep->len - 1;
p >= linep->buf && grub_isspace (*p);
p--)
;
*++p = '\0';
source = grub_malloc (size + 1);
if (! source)
return NULL;
linep->len = p - linep->buf;
for (p = linep->buf; grub_isspace (*p); p++)
;
*line = grub_strdup (p);
currline++;
return 0;
}
size = 0;
for (i = 0; i < screen->num_lines; i++)
{
grub_memcpy (source + size, screen->lines[i].buf, screen->lines[i].len);
size += screen->lines[i].len;
source[size++] = '\n';
}
source[size] = '\0';
return source;
}
grub_cls ();
grub_printf (" ");
grub_printf_ (N_("Booting a command list"));
grub_printf ("\n\n");
errs_before = grub_err_printed_errors;
if (screen->submenu)
{
grub_env_context_open ();
menu = grub_zalloc (sizeof (*menu));
if (! menu)
return 0;
grub_env_set_menu (menu);
}
/* Execute the script, line for line. */
while (currline < screen->num_lines)
{
editor_getline (&nextline, 0);
if (grub_normal_parse_line (nextline, editor_getline))
break;
}
script = editor_getsource ();
if (! script)
return 0;
grub_script_execute_sourcecode (script, 0, dummy);
grub_free (script);
if (errs_before != grub_err_printed_errors)
grub_wait_after_message ();
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */
grub_command_execute ("boot", 0, 0);
if (screen->submenu)
{
if (menu && menu->size)
{
grub_show_menu (menu, 1, 0);
grub_normal_free_menu (menu);
}
grub_env_context_close ();
}
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
@ -1264,7 +1291,8 @@ grub_menu_entry_run (grub_menu_entry_t entry)
}
/* Draw the screen. */
for (i = 0; i < screen->nterms; i++)
grub_menu_init_page (0, 1, screen->terms[i].term);
grub_menu_init_page (0, 1, &screen->terms[i].num_entries,
screen->terms[i].term);
update_screen_all (screen, 0, 0, 1, 1, ALL_LINES);
for (i = 0; i < screen->nterms; i++)
grub_term_setcursor (screen->terms[i].term, 1);
@ -1272,7 +1300,7 @@ grub_menu_entry_run (grub_menu_entry_t entry)
while (1)
{
int c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
int c = grub_getkey ();
if (screen->completion_shown)
{
@ -1288,70 +1316,79 @@ grub_menu_entry_run (grub_menu_entry_t entry)
switch (c)
{
case 16: /* C-p */
case GRUB_TERM_KEY_UP:
case GRUB_TERM_CTRL | 'p':
if (! previous_line (screen, 1))
goto fail;
break;
case 14: /* C-n */
case GRUB_TERM_CTRL | 'n':
case GRUB_TERM_KEY_DOWN:
if (! next_line (screen, 1))
goto fail;
break;
case 6: /* C-f */
case GRUB_TERM_CTRL | 'f':
case GRUB_TERM_KEY_RIGHT:
if (! forward_char (screen, 1))
goto fail;
break;
case 2: /* C-b */
case GRUB_TERM_CTRL | 'b':
case GRUB_TERM_KEY_LEFT:
if (! backward_char (screen, 1))
goto fail;
break;
case 1: /* C-a */
case GRUB_TERM_CTRL | 'a':
case GRUB_TERM_KEY_HOME:
if (! beginning_of_line (screen, 1))
goto fail;
break;
case 5: /* C-e */
case GRUB_TERM_CTRL | 'e':
case GRUB_TERM_KEY_END:
if (! end_of_line (screen, 1))
goto fail;
break;
case '\t': /* C-i */
case GRUB_TERM_CTRL | 'i':
case '\t':
if (! complete (screen, prev_c == c, 1))
goto fail;
break;
case 4: /* C-d */
case GRUB_TERM_CTRL | 'd':
case GRUB_TERM_KEY_DC:
if (! delete_char (screen, 1))
goto fail;
break;
case 8: /* C-h */
case GRUB_TERM_CTRL | 'h':
case '\b':
if (! backward_delete_char (screen, 1))
goto fail;
break;
case 11: /* C-k */
case GRUB_TERM_CTRL | 'k':
if (! kill_line (screen, prev_c == c, 1))
goto fail;
break;
case 21: /* C-u */
case GRUB_TERM_CTRL | 'u':
/* FIXME: What behavior is good for this key? */
break;
case 25: /* C-y */
case GRUB_TERM_CTRL | 'y':
if (! yank (screen, 1))
goto fail;
break;
case 12: /* C-l */
case GRUB_TERM_CTRL | 'l':
/* FIXME: centering. */
goto refresh;
case 15: /* C-o */
case GRUB_TERM_CTRL | 'o':
if (! open_line (screen, 1))
goto fail;
break;
@ -1366,23 +1403,19 @@ grub_menu_entry_run (grub_menu_entry_t entry)
destroy_screen (screen);
return;
case 3: /* C-c */
case GRUB_TERM_CTRL | 'c':
case GRUB_TERM_KEY_F2:
grub_cmdline_run (1);
goto refresh;
case 24: /* C-x */
{
int chars_before = grub_normal_get_char_counter ();
run (screen);
if (chars_before != grub_normal_get_char_counter ())
grub_wait_after_message ();
}
case GRUB_TERM_CTRL | 'x':
case GRUB_TERM_KEY_F10:
run (screen);
goto refresh;
case 18: /* C-r */
case 19: /* C-s */
case 20: /* C-t */
case GRUB_TERM_CTRL | 'r':
case GRUB_TERM_CTRL | 's':
case GRUB_TERM_CTRL | 't':
/* FIXME */
break;

View file

@ -34,10 +34,19 @@ static grub_uint8_t grub_color_menu_highlight;
struct menu_viewer_data
{
int first, offset;
/* The number of entries shown at a time. */
int num_entries;
grub_menu_t menu;
struct grub_term_output *term;
};
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);
}
grub_ssize_t
grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position,
struct grub_term_output *term)
@ -53,30 +62,45 @@ grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position,
return width;
}
void
grub_print_message_indented (const char *msg, int margin_left, int margin_right,
struct grub_term_output *term)
static int
grub_print_message_indented_real (const char *msg, int margin_left,
int margin_right,
struct grub_term_output *term, int dry_run)
{
grub_uint32_t *unicode_msg;
grub_uint32_t *last_position;
int msg_len;
int ret = 0;
msg_len = grub_utf8_to_ucs4_alloc (msg, &unicode_msg, &last_position);
if (msg_len < 0)
{
return;
return 0;
}
grub_print_ucs4 (unicode_msg, last_position, margin_left, margin_right, term);
if (dry_run)
ret = grub_ucs4_count_lines (unicode_msg, last_position, margin_left,
margin_right, term);
else
grub_print_ucs4 (unicode_msg, last_position, margin_left,
margin_right, term);
grub_free (unicode_msg);
return ret;
}
void
grub_print_message_indented (const char *msg, int margin_left, int margin_right,
struct grub_term_output *term)
{
grub_print_message_indented_real (msg, margin_left, margin_right, term, 0);
}
static void
draw_border (struct grub_term_output *term)
draw_border (struct grub_term_output *term, int num_entries)
{
unsigned i;
@ -88,7 +112,7 @@ draw_border (struct grub_term_output *term)
grub_putcode (GRUB_UNICODE_HLINE, term);
grub_putcode (GRUB_UNICODE_CORNER_UR, term);
for (i = 0; i < (unsigned) grub_term_num_entries (term); i++)
for (i = 0; i < (unsigned) num_entries; i++)
{
grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
grub_putcode (GRUB_UNICODE_VLINE, term);
@ -99,7 +123,7 @@ draw_border (struct grub_term_output *term)
}
grub_term_gotoxy (term, GRUB_TERM_MARGIN,
GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term) + 1);
GRUB_TERM_TOP_BORDER_Y + num_entries + 1);
grub_putcode (GRUB_UNICODE_CORNER_LL, term);
for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++)
grub_putcode (GRUB_UNICODE_HLINE, term);
@ -108,29 +132,27 @@ draw_border (struct grub_term_output *term)
grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_term_gotoxy (term, GRUB_TERM_MARGIN,
(GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term)
(GRUB_TERM_TOP_BORDER_Y + num_entries
+ GRUB_TERM_MARGIN + 1));
}
static void
print_message (int nested, int edit, struct grub_term_output *term)
static int
print_message (int nested, int edit, struct grub_term_output *term, int dry_run)
{
int ret = 0;
grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
if (edit)
{
grub_putcode ('\n', term);
#ifdef GRUB_MACHINE_EFI
grub_print_message_indented (_("Minimum Emacs-like screen editing is \
supported. TAB lists completions. Press F1 to boot, F2=Ctrl-a, F3=Ctrl-e, \
F4 for a command-line or ESC to discard edits and return to the GRUB menu."),
STANDARD_MARGIN, STANDARD_MARGIN, term);
#else
grub_print_message_indented (_("Minimum Emacs-like screen editing is \
supported. TAB lists completions. Press Ctrl-x to boot, Ctrl-c for a \
if(dry_run)
ret++;
else
grub_putcode ('\n', term);
ret += grub_print_message_indented_real (_("Minimum Emacs-like screen editing is \
supported. TAB lists completions. Press Ctrl-x or F10 to boot, Ctrl-c or F2 for a \
command-line or ESC to discard edits and return to the GRUB menu."),
STANDARD_MARGIN, STANDARD_MARGIN, term);
#endif
STANDARD_MARGIN, STANDARD_MARGIN,
term, dry_run);
}
else
{
@ -141,30 +163,34 @@ command-line or ESC to discard edits and return to the GRUB menu."),
msg_translated = grub_xasprintf (msg, GRUB_UNICODE_UPARROW,
GRUB_UNICODE_DOWNARROW);
if (!msg_translated)
return;
grub_putcode ('\n', term);
grub_print_message_indented (msg_translated, STANDARD_MARGIN,
STANDARD_MARGIN, term);
return 0;
if(dry_run)
ret++;
else
grub_putcode ('\n', term);
ret += grub_print_message_indented_real (msg_translated, STANDARD_MARGIN,
STANDARD_MARGIN, term, dry_run);
grub_free (msg_translated);
if (nested)
{
grub_print_message_indented
ret += grub_print_message_indented_real
(_("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);
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
}
else
{
grub_print_message_indented
ret += grub_print_message_indented_real
(_("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);
STANDARD_MARGIN, STANDARD_MARGIN, term, dry_run);
}
}
return ret;
}
static void
@ -263,52 +289,56 @@ print_entry (int y, int highlight, grub_menu_entry_t entry,
}
static void
print_entries (grub_menu_t menu, int first, int offset,
struct grub_term_output *term)
print_entries (grub_menu_t menu, const struct menu_viewer_data *data)
{
grub_menu_entry_t e;
int i;
grub_term_gotoxy (term,
GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term),
grub_term_gotoxy (data->term,
GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (data->term),
GRUB_TERM_FIRST_ENTRY_Y);
if (first)
grub_putcode (GRUB_UNICODE_UPARROW, term);
if (data->first)
grub_putcode (GRUB_UNICODE_UPARROW, data->term);
else
grub_putcode (' ', term);
grub_putcode (' ', data->term);
e = grub_menu_get_entry (menu, first);
e = grub_menu_get_entry (menu, data->first);
for (i = 0; i < grub_term_num_entries (term); i++)
for (i = 0; i < data->num_entries; i++)
{
print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, offset == i, e, term);
print_entry (GRUB_TERM_FIRST_ENTRY_Y + i, data->offset == i,
e, data->term);
if (e)
e = e->next;
}
grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X
+ grub_term_border_width (term),
GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term));
grub_term_gotoxy (data->term, GRUB_TERM_LEFT_BORDER_X
+ grub_term_border_width (data->term),
GRUB_TERM_TOP_BORDER_Y + data->num_entries);
if (e)
grub_putcode (GRUB_UNICODE_DOWNARROW, term);
grub_putcode (GRUB_UNICODE_DOWNARROW, data->term);
else
grub_putcode (' ', term);
grub_putcode (' ', data->term);
grub_term_gotoxy (term, grub_term_cursor_x (term),
GRUB_TERM_FIRST_ENTRY_Y + offset);
grub_term_gotoxy (data->term, grub_term_cursor_x (data->term),
GRUB_TERM_FIRST_ENTRY_Y + data->offset);
}
/* 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
a message for the menu entry editor. */
void
grub_menu_init_page (int nested, int edit,
grub_menu_init_page (int nested, int edit, int *num_entries,
struct grub_term_output *term)
{
grub_uint8_t old_color_normal, old_color_highlight;
/* 3 lines for timeout message and bottom margin. 2 lines for the border. */
*num_entries = grub_term_height (term) - GRUB_TERM_TOP_BORDER_Y
- (print_message (nested, edit, term, 1) + 3) - 2;
grub_term_getcolor (term, &old_color_normal, &old_color_highlight);
/* By default, use the same colors for the menu. */
@ -323,9 +353,9 @@ grub_menu_init_page (int nested, int edit,
grub_normal_init_page (term);
grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight);
draw_border (term);
draw_border (term, *num_entries);
grub_term_setcolor (term, old_color_normal, old_color_highlight);
print_message (nested, edit, term);
print_message (nested, edit, term, 0);
}
static void
@ -366,10 +396,10 @@ menu_text_set_chosen_entry (int entry, void *dataptr)
int complete_redraw = 0;
data->offset = entry - data->first;
if (data->offset > grub_term_num_entries (data->term) - 1)
if (data->offset > data->num_entries - 1)
{
data->first = entry - (grub_term_num_entries (data->term) - 1);
data->offset = grub_term_num_entries (data->term) - 1;
data->first = entry - (data->num_entries - 1);
data->offset = data->num_entries - 1;
complete_redraw = 1;
}
if (data->offset < 0)
@ -379,7 +409,7 @@ menu_text_set_chosen_entry (int entry, void *dataptr)
complete_redraw = 1;
}
if (complete_redraw)
print_entries (data->menu, data->first, data->offset, data->term);
print_entries (data->menu, data);
else
{
print_entry (GRUB_TERM_FIRST_ENTRY_Y + oldoffset, 0,
@ -443,15 +473,17 @@ grub_menu_try_text (struct grub_term_output *term,
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_menu_init_page (nested, 0, &data->num_entries, data->term);
if (data->offset > data->num_entries - 1)
{
data->first = data->offset - (data->num_entries - 1);
data->offset = data->num_entries - 1;
}
print_entries (menu, data);
grub_term_refresh (data->term);
grub_menu_register_viewer (instance);

View file

@ -112,14 +112,13 @@ grub_normal_print_device_info (const char *name)
grub_printf ("%s", _("Not a known filesystem"));
if (dev->disk->partition)
grub_printf (_(" - Partition start at %u"),
grub_partition_get_start (dev->disk->partition));
grub_printf (_(" - Partition start at %llu"),
(unsigned long long) grub_partition_get_start (dev->disk->partition));
if (grub_disk_get_size (dev->disk) == GRUB_DISK_SIZE_UNKNOWN)
grub_printf (_(" - Total size unknown"),
grub_disk_get_size (dev->disk));
grub_puts_ (" - Total size unknown");
else
grub_printf (_(" - Total size %u sectors"),
grub_disk_get_size (dev->disk));
grub_printf (_(" - Total size %llu sectors"),
(unsigned long long) grub_disk_get_size (dev->disk));
grub_device_close (dev);
}

View file

@ -24,6 +24,7 @@
#include <grub/env.h>
#include <grub/normal.h>
#include <grub/charset.h>
#include <grub/i18n.h>
struct term_state
{
@ -42,17 +43,9 @@ static struct term_state *term_states = NULL;
/* If the more pager is active. */
static int grub_more;
static int grub_normal_char_counter = 0;
static void
putcode_real (grub_uint32_t code, struct grub_term_output *term);
int
grub_normal_get_char_counter (void)
{
return grub_normal_char_counter;
}
void
grub_normal_reset_more (void)
{
@ -71,7 +64,9 @@ print_more (void)
pos = grub_term_save_pos ();
grub_utf8_to_ucs4_alloc ("--MORE--", &unicode_str,
/* TRANSLATORS: This has to fit on one line. It's ok to include few
words but don't write poems. */
grub_utf8_to_ucs4_alloc (_("--MORE--"), &unicode_str,
&unicode_last_position);
if (!unicode_str)
@ -99,16 +94,16 @@ print_more (void)
grub_term_restore_pos (pos);
grub_free (pos);
/* Scroll one lines or an entire page, depending on the key. */
/* Scroll one line or an entire page, depending on the key. */
if (key == '\r' || key =='\n')
grub_normal_reset_more ();
else
{
static struct term_state *state;
for (state = term_states; state; state = state->next)
state->num_lines -= 2;
state->num_lines--;
}
else
grub_normal_reset_more ();
}
void
@ -384,8 +379,8 @@ read_terminal_list (const char *prefix)
if (! cur->modname)
{
grub_errno = GRUB_ERR_NONE;
grub_free (cur);
grub_free (cur->name);
grub_free (cur);
continue;
}
cur->next = *target;
@ -409,8 +404,6 @@ putglyph (const struct grub_unicode_glyph *c, struct grub_term_output *term)
.estimated_width = 1
};
grub_normal_char_counter++;
if (c->base == '\t' && term->getxy)
{
int n;
@ -525,14 +518,16 @@ print_ucs4_terminal (const grub_uint32_t * str,
const grub_uint32_t * last_position,
int margin_left, int margin_right,
struct grub_term_output *term,
struct term_state *state)
struct term_state *state,
int dry_run)
{
const grub_uint32_t *ptr;
grub_ssize_t startwidth = get_startwidth (term, margin_left);
grub_ssize_t startwidth = dry_run ? 0 : get_startwidth (term, margin_left);
grub_ssize_t line_width = startwidth;
grub_ssize_t lastspacewidth = 0;
grub_ssize_t max_width = get_maxwidth (term, margin_left, margin_right);
const grub_uint32_t *line_start = str, *last_space = str - 1;
int lines = 0;
for (ptr = str; ptr < last_position; ptr++)
{
@ -562,7 +557,7 @@ print_ucs4_terminal (const grub_uint32_t * str,
if (line_width > max_width && last_space > line_start)
ptr = last_space;
else if (line_width > max_width
&& line_start == str && startwidth != 0)
&& line_start == str && line_width - lastspacewidth < max_width - 5)
{
ptr = str;
lastspacewidth = startwidth;
@ -570,50 +565,59 @@ print_ucs4_terminal (const grub_uint32_t * str,
else
lastspacewidth = line_width - last_width;
for (ptr2 = line_start; ptr2 < ptr; ptr2++)
{
/* Skip combining characters on non-UTF8 terminals. */
if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
!= GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
&& grub_unicode_get_comb_type (*ptr2)
!= GRUB_UNICODE_COMB_NONE)
continue;
putcode_real (*ptr2, term);
}
lines++;
grub_print_spaces (term, margin_right);
grub_putcode ('\n', term);
if (state && ++state->num_lines
>= (grub_ssize_t) grub_term_height (term) - 2)
if (!dry_run)
{
state->backlog_ucs4 = (ptr == last_space || *ptr == '\n')
? ptr + 1 : ptr;
state->backlog_len = last_position - state->backlog_ucs4;
return 1;
for (ptr2 = line_start; ptr2 < ptr; ptr2++)
{
/* Skip combining characters on non-UTF8 terminals. */
if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
!= GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
&& grub_unicode_get_comb_type (*ptr2)
!= GRUB_UNICODE_COMB_NONE)
continue;
putcode_real (*ptr2, term);
}
grub_print_spaces (term, margin_right);
grub_putcode ('\n', term);
if (state && ++state->num_lines
>= (grub_ssize_t) grub_term_height (term) - 2)
{
state->backlog_ucs4 = (ptr == last_space || *ptr == '\n')
? ptr + 1 : ptr;
state->backlog_len = last_position - state->backlog_ucs4;
return 1;
}
}
line_width -= lastspacewidth;
grub_print_spaces (term, margin_left);
if (!dry_run)
grub_print_spaces (term, margin_left);
if (ptr == last_space || *ptr == '\n')
ptr++;
line_start = ptr;
}
}
{
const grub_uint32_t *ptr2;
for (ptr2 = line_start; ptr2 < last_position; ptr2++)
{
/* Skip combining characters on non-UTF8 terminals. */
if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
!= GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
&& grub_unicode_get_comb_type (*ptr2)
!= GRUB_UNICODE_COMB_NONE)
continue;
putcode_real (*ptr2, term);
}
}
return 0;
if (line_start < last_position)
lines++;
if (!dry_run)
{
const grub_uint32_t *ptr2;
for (ptr2 = line_start; ptr2 < last_position; ptr2++)
{
/* Skip combining characters on non-UTF8 terminals. */
if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
!= GRUB_TERM_CODE_TYPE_UTF8_LOGICAL
&& grub_unicode_get_comb_type (*ptr2)
!= GRUB_UNICODE_COMB_NONE)
continue;
putcode_real (*ptr2, term);
}
}
return dry_run ? lines : 0;
}
static struct term_state *
@ -682,7 +686,7 @@ print_backlog (struct grub_term_output *term,
int ret;
ret = print_ucs4_terminal (state->backlog_ucs4,
state->backlog_ucs4 + state->backlog_len,
margin_left, margin_right, term, state);
margin_left, margin_right, term, state, 0);
if (!ret)
{
grub_free (state->free);
@ -716,15 +720,19 @@ static int
print_ucs4_real (const grub_uint32_t * str,
const grub_uint32_t * last_position,
int margin_left, int margin_right,
struct grub_term_output *term, int backlog)
struct grub_term_output *term, int backlog,
int dry_run)
{
struct term_state *state = NULL;
if (backlog)
state = find_term_state (term);
if (!dry_run)
{
if (backlog)
state = find_term_state (term);
if (((term->getxy (term) >> 8) & 0xff) < margin_left)
grub_print_spaces (term, margin_left - ((term->getxy (term) >> 8) & 0xff));
if (((term->getxy (term) >> 8) & 0xff) < margin_left)
grub_print_spaces (term, margin_left - ((term->getxy (term) >> 8) & 0xff));
}
if ((term->flags & GRUB_TERM_CODE_TYPE_MASK)
== GRUB_TERM_CODE_TYPE_VISUAL_GLYPHS
@ -753,16 +761,30 @@ print_ucs4_real (const grub_uint32_t * str,
grub_print_error ();
return 0;
}
ret = put_glyphs_terminal (visual, visual_len, margin_left, margin_right,
term, state);
if (!ret)
grub_free (visual);
if (dry_run)
{
struct grub_unicode_glyph *vptr;
ret = 0;
for (vptr = visual; vptr < visual + visual_len; vptr++)
if (vptr->base == '\n')
ret++;
if (visual_len && visual[visual_len - 1].base != '\n')
ret++;
grub_free (visual);
}
else
state->free = visual;
{
ret = put_glyphs_terminal (visual, visual_len, margin_left,
margin_right, term, state);
if (!ret)
grub_free (visual);
else
state->free = visual;
}
return ret;
}
return print_ucs4_terminal (str, last_position, margin_left, margin_right,
term, state);
term, state, dry_run);
}
void
@ -772,9 +794,18 @@ grub_print_ucs4 (const grub_uint32_t * str,
struct grub_term_output *term)
{
print_ucs4_real (str, last_position, margin_left, margin_right,
term, 0);
term, 0, 0);
}
int
grub_ucs4_count_lines (const grub_uint32_t * str,
const grub_uint32_t * last_position,
int margin_left, int margin_right,
struct grub_term_output *term)
{
return print_ucs4_real (str, last_position, margin_left, margin_right,
term, 0, 1);
}
void
grub_xputs_normal (const char *str)
@ -823,7 +854,7 @@ grub_xputs_normal (const char *str)
{
int cur;
cur = print_ucs4_real (unicode_str, unicode_last_position, 0, 0,
term, grub_more);
term, grub_more, 0);
if (cur)
backlog = 1;
}