int desclen = grub_strlen (cmd->summary);
for (cur = grub_term_outputs; cur; cur = cur->next)
{
- if (!(cur->flags & GRUB_TERM_ACTIVE))
+ if (!grub_term_is_active (cur))
continue;
int width = grub_term_width(cur);
char description[width / 2];
/* 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
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;
+ 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_register_viewer_init (void (*callback) (int entry,
+ grub_menu_t menu,
+ int nested));
#endif /* GRUB_MENU_VIEWER_HEADER */
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_abort) (void) __attribute__ ((noreturn));
-grub_ssize_t EXPORT_FUNC(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 **srcend);
+grub_size_t EXPORT_FUNC(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 **srcend);
grub_uint64_t EXPORT_FUNC(grub_divmod64) (grub_uint64_t n,
grub_uint32_t d, grub_uint32_t *r);
/* Defined in `main.c'. */
void grub_enter_normal_mode (const char *config);
void grub_normal_execute (const char *config, int nested, int batch);
+void grub_menu_init_page (int nested, int edit,
+ struct grub_term_output *term);
void grub_normal_init_page (struct grub_term_output *term);
-void grub_menu_init_page (int nested, int edit);
grub_err_t grub_normal_add_menu_entry (int argc, const char **args,
const char *sourcecode);
char *grub_file_getline (grub_file_t file);
void grub_cmdline_run (int nested);
/* Defined in `cmdline.c'. */
-char *grub_cmdline_get (const char *prompt, unsigned max_len);
+char *grub_cmdline_get (const char *prompt);
grub_err_t grub_set_history (int newsize);
/* Defined in `completion.c'. */
/* Defined in `menu_text.c'. */
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,
- 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,
- 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,
- 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'. */
void read_handler_list (void);
/* The X position of the left border. */
#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. */
#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. */
#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
{
/* The next terminal. */
grub_uint16_t *grub_term_save_pos (void);
void grub_term_restore_pos (grub_uint16_t *pos);
-static inline int grub_term_width (struct grub_term_output *term)
+static inline unsigned grub_term_width (struct grub_term_output *term)
{
return ((term->getwh()&0xFF00)>>8);
}
-static inline int grub_term_height (struct grub_term_output *term)
+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
+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 int
+grub_term_is_active (struct grub_term_output *term)
+{
+ return !!(term->flags & GRUB_TERM_ACTIVE);
+}
+
+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)
+{
+ term->getcolor (normal_color, highlight_color);
+}
+
+extern void (*EXPORT_VAR (grub_newline_hook)) (void);
+
/* For convenience. */
#define GRUB_TERM_ASCII_CHAR(c) ((c) & 0xff)
/* 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.
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
last byte used in SRC. */
-grub_ssize_t
+grub_size_t
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 **srcend)
if ((c & 0xc0) != 0x80)
{
/* invalid */
- return -1;
+ code = '?';
+ count = 0;
}
else
{
code = c & 0x01;
}
else
- return -1;
+ {
+ /* invalid */
+ code = '?';
+ count = 0;
+ }
}
if (count == 0)
struct grub_term_output *grub_term_outputs;
+void (*grub_newline_hook) (void) = NULL;
+
/* Put a Unicode character. */
void
grub_putcode (grub_uint32_t code, struct grub_term_output *term)
{
int height;
- height = term->getwh () & 255;
+ height = grub_term_height (term);
if (code == '\t' && term->getxy)
{
return;
}
+ if (code == '\n')
+ (term->putchar) ('\r');
(term->putchar) (code);
}
{
struct grub_term_output *term = (struct grub_term_output *) item;
- if (term->flags & GRUB_TERM_ACTIVE)
+ if (grub_term_is_active (term))
grub_putcode (code, term);
return 0;
buf[size++] = c;
ret = grub_utf8_to_ucs4 (&code, 1, buf, size, 0);
- if (ret < 0)
- code = '?';
-
if (ret != 0)
{
size = 0;
grub_list_iterate (GRUB_AS_LIST (grub_term_outputs), do_putcode);
}
+ if (ret == '\n' && grub_newline_hook)
+ grub_newline_hook ();
}
int
{
struct grub_term_output *term = (struct grub_term_output *) item;
- if (!(term->flags & GRUB_TERM_ACTIVE))
+ if (! grub_term_is_active (term))
return 0;
if ((term->flags & GRUB_TERM_DUMB) || (grub_env_get ("debug")))
{
struct grub_term_output *term = (struct grub_term_output *) item;
- if (!(term->flags & GRUB_TERM_ACTIVE))
+ if (! grub_term_is_active (term))
return 0;
- if (term->setcolorstate)
- (term->setcolorstate) (state);
+ grub_term_setcolorstate (term, state);
return 0;
}
{
struct grub_term_output *term = (struct grub_term_output *) item;
- if (!(term->flags & GRUB_TERM_ACTIVE))
+ if (!grub_term_is_active (term))
return 0;
- if (term->refresh)
- (term->refresh) ();
+ grub_term_refresh (term);
return 0;
}
last byte used in SRC. */
#include <grub/charset.h>
+#include <grub/mm.h>
+#include <grub/misc.h>
grub_ssize_t
grub_utf8_to_utf16 (grub_uint16_t *dest, grub_size_t destsize,
}
*dest = 0;
- return ret;
+ 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;
}
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_auth_check_authentication (const char *userlist)
{
return GRUB_ERR_NONE;
}
- if (!grub_cmdline_get (N_("Enter username:"), login, sizeof (login) - 1,
- 0, 0, 0))
+ grub_puts_ (N_("Enter username: "));
+
+ if (!grub_username_get (login, sizeof (login) - 1))
goto access_denied;
- grub_printf ("Enter password: ");
+ grub_puts_ (N_("Enter password: "));
if (!grub_password_get (entered, GRUB_AUTH_MAX_PASSLEN))
goto access_denied;
#include <grub/file.h>
#include <grub/env.h>
#include <grub/i18n.h>
+#include <grub/charset.h>
static grub_uint32_t *kill_buf;
otherwise return command line. */
/* FIXME: The dumb interface is not supported yet. */
char *
-grub_cmdline_get (const char *prompt, unsigned max_len)
+grub_cmdline_get (const char *prompt)
{
grub_size_t lpos, llen;
grub_size_t plen;
- grub_uint32_t buf[max_len];
+ grub_uint32_t *buf;
+ grub_size_t max_len = 256;
int key;
int histpos = 0;
auto void cl_insert (const grub_uint32_t *str);
auto void cl_set_pos_all (void);
const char *prompt_translated = _(prompt);
struct cmdline_term *cl_terms;
+ char *ret;
unsigned nterms;
void cl_set_pos (struct cmdline_term *cl_term)
{
cl_term->xpos = (plen + lpos) % (cl_term->width - 1);
cl_term->ypos = cl_term->ystart + (plen + lpos) / (cl_term->width - 1);
- cl_term->term->gotoxy (cl_term->xpos, cl_term->ypos);
+ grub_term_gotoxy (cl_term->term, cl_term->xpos, cl_term->ypos);
}
void cl_set_pos_all ()
{
grub_uint32_t *p;
- for (p = buf + pos; *p; p++)
+ for (p = buf + pos; p < buf + llen; p++)
{
if (cl_term->xpos++ > cl_term->width - 2)
{
{
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)
{
- grub_memmove (buf + lpos + len, buf + lpos, llen - lpos + 1);
- grub_memmove (buf + lpos, str, len);
+ grub_memmove (buf + lpos + len, buf + lpos,
+ (llen - lpos + 1) * sizeof (grub_uint32_t));
+ grub_memmove (buf + lpos, str, len * sizeof (grub_uint32_t));
llen += len;
lpos += len;
- cl_print_all (lpos - len, echo_char);
+ cl_print_all (lpos - len, 0);
cl_set_pos_all ();
}
grub_memmove (buf + lpos, buf + lpos + len, llen - lpos + 1);
llen -= len;
- cl_print_all (lpos, echo_char);
+ cl_print_all (lpos, 0);
cl_set_pos_all ();
}
void init_clterm (struct cmdline_term *cl_term_cur)
{
cl_term_cur->xpos = plen;
- cl_term_cur->ypos = (cl_term_cur->term->getxy () & 0xFF);
+ cl_term_cur->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);
init_clterm (&cl_terms[i]);
}
+ buf = grub_malloc (max_len * sizeof (grub_uint32_t));
+ if (!buf)
+ return 0;
+
plen = grub_strlen (prompt_translated);
lpos = llen = 0;
buf[0] = '\0';
struct grub_term_output *cur;
nterms = 0;
for (cur = grub_term_outputs; cur; cur = cur->next)
- if (cur->flags & GRUB_TERM_ACTIVE)
+ if (grub_term_is_active (cur))
nterms++;
cl_terms = grub_malloc (sizeof (cl_terms[0]) * nterms);
if (!cl_terms)
- return grub_errno;
+ return 0;
cl_term_cur = cl_terms;
for (cur = grub_term_outputs; cur; cur = cur->next)
- if (cur->flags & GRUB_TERM_ACTIVE)
+ if (grub_term_is_active (cur))
{
cl_term_cur->term = cur;
init_clterm (cl_term_cur);
}
}
- if (history && hist_used == 0)
+ if (hist_used == 0)
grub_history_add (buf);
while ((key = GRUB_TERM_ASCII_CHAR (grub_getkey ())) != '\n' && key != '\r')
{
grub_uint32_t *insert;
int restore;
+ char *bufu8, *insertu8;
+ grub_size_t insertlen;
+ grub_size_t t;
- /* Backup the next character and make it 0 so it will
- be easy to use string functions. */
- char backup = buf[lpos];
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);
+ insertlen = grub_strlen (bufu8);
+ 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);
+ insert[t] = 0;
- insert = grub_normal_do_completion (buf, &restore,
- print_completion);
- /* Restore the original string. */
- buf[lpos] = backup;
+ grub_free (insertu8);
if (restore)
{
grub_free (kill_buf);
kill_buf = strdup_ucs4 (buf + lpos);
- grub_errno = GRUB_ERR_NONE;
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
cl_delete (llen - lpos);
}
grub_free (kill_buf);
kill_buf = grub_malloc (n + 1);
- grub_errno = GRUB_ERR_NONE;
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
if (kill_buf)
{
grub_memcpy (kill_buf, buf, n);
while (buf[lpos] == ' ')
lpos++;
- if (history)
+ histpos = 0;
+ if (strlen_ucs4 (buf) > 0)
{
- histpos = 0;
- if (strlen_ucs4 (buf) > 0)
- {
- grub_uint32_t empty[] = { 0 };
- grub_history_replace (histpos, buf);
- grub_history_add (empty);
- }
+ grub_uint32_t empty[] = { 0 };
+ grub_history_replace (histpos, buf);
+ grub_history_add (empty);
}
- return grub_ucs4_to_utf8_alloc (buf + lpos, llen - lpos + 1);
+ ret = grub_ucs4_to_utf8_alloc (buf + lpos, llen - lpos + 1);
+ grub_free (buf);
+ return ret;
}
for (term = grub_term_outputs; term; term = term->next)
{
- if (! (term->flags & GRUB_TERM_ACTIVE))
+ if (! grub_term_is_active (term))
continue;
/* Reloads terminal `normal' and `highlight' colors. */
- if (term->setcolor)
- term->setcolor (color_normal, color_highlight);
+ grub_term_setcolor (term, color_normal, color_highlight);
/* Propagates `normal' color to terminal current color. */
- if (term->setcolorstate)
- term->setcolorstate (GRUB_TERM_COLOR_NORMAL);
+ grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
}
}
#include <grub/menu_viewer.h>
#include <grub/auth.h>
#include <grub/i18n.h>
+#include <grub/charset.h>
#define GRUB_DEFAULT_HISTORY_SIZE 50
return;
}
- posx = grub_getstringwidth (unicode_msg, last_position);
+ posx = grub_getstringwidth (unicode_msg, last_position, term);
posx = (grub_term_width (term) - posx) / 2;
- term->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_free (unicode_msg);
}
{
if (menu && menu->size)
{
- grub_menu_viewer_show_menu (menu, nested);
+ grub_show_menu (menu, nested);
if (nested)
free_menu (menu);
}
grub_enter_normal_mode (const char *config)
{
grub_normal_execute (config, 0, 0);
+ grub_cmdline_run (1);
}
/* Enter normal mode from rescue mode. */
static grub_err_t
-grub_cmd_normal (struct grub_command *cmd,
+grub_cmd_normal (struct grub_command *cmd __attribute__ ((unused)),
int argc, char *argv[])
{
- grub_unregister_command (cmd);
-
if (argc == 0)
{
/* Guess the config filename. It is necessary to make CONFIG static,
so that it won't get broken by longjmp. */
- static char *config;
+ char *config;
const char *prefix;
prefix = grub_env_get ("prefix");
if (! (term->flags & GRUB_TERM_ACTIVE))
continue;
grub_normal_init_page (term);
- if (term->setcursor)
- term->setcursor (1);
+ grub_term_setcursor (term, 1);
- grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN);
+ grub_print_message_indented (msg_formatted, 3, STANDARD_MARGIN, term);
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)
while (1)
{
- cmdline[0] = 0;
- if (grub_cmdline_get (prompt, cmdline, sizeof (cmdline), 0, 1, 1))
+ *line = grub_cmdline_get (prompt);
+ if (*line)
break;
if ((reader_nested) || (cont))
{
+ grub_free (*line);
*line = 0;
return grub_errno;
}
}
- *line = grub_strdup (cmdline);
return 0;
}
grub_normal_read_line (&line, 0);
if (! line)
- continue;
+ break;
grub_parser_get_current ()->parse_line (line, grub_normal_read_line);
grub_free (line);
if (mod)
grub_dl_ref (mod);
- grub_menu_viewer_register (&grub_normal_text_menu_viewer);
-
grub_set_history (GRUB_DEFAULT_HISTORY_SIZE);
+ grub_menu_register_viewer_init (grub_menu_text_register_instances);
+ if (grub_errno)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ }
+
grub_register_variable_hook ("pager", 0, grub_env_write_pager);
/* Register a command "normal" for the rescue mode. */
- grub_register_command_prio ("normal", grub_cmd_normal,
- 0, "Enter normal mode", 0);
+ grub_register_command ("normal", grub_cmd_normal,
+ 0, "Enter normal mode");
/* Reload terminal colors when these variables are written to. */
grub_register_variable_hook ("color_normal", NULL, grub_env_write_color_normal);
#include <grub/command.h>
#include <grub/parser.h>
#include <grub/auth.h>
+#include <grub/i18n.h>
+
+/* Time to delay after displaying an error message about a default/fallback
+ entry failing to boot. */
+#define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
+
+struct menu_run_callback
+{
+ struct menu_run_callback *next;
+ void (*hook) (int entry, grub_menu_t menu, int nested);
+};
+
+struct menu_run_callback *callbacks = 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. */
grub_menu_entry_t
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 menu_run_callback *cb;
+ for (cb = callbacks; cb; cb = cb->next)
+ cb->hook (entry, menu, nested);
+}
+
+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;
+}
+
+grub_err_t
+grub_menu_register_viewer_init (void (*callback) (int entry, grub_menu_t menu,
+ int nested))
+{
+ struct menu_run_callback *cb;
+ cb = grub_malloc (sizeof (*cb));
+ if (!cb)
+ return grub_errno;
+ cb->hook = callback;
+ cb->next = callbacks;
+ callbacks = cb;
+ return GRUB_ERR_NONE;
+}
+
+/* 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 (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 '^':
+ current_entry--;
+ menu_set_chosen_entry (current_entry);
+ break;
+
+ case GRUB_TERM_DOWN:
+ case 'v':
+ 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 = 0;
+ else
+ current_entry += GRUB_MENU_PAGE_SIZE;
+ 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':
+ grub_cmdline_run (1);
+ goto refresh;
+
+ case 'e':
+ {
+ 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 ();
+
+ err2 = grub_auth_check_authentication (NULL);
+ if (err2)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+
+ break;
+ }
+
+ return err1;
+}
int max_len;
};
+struct per_term_screen
+{
+ struct grub_term_output *term;
+ /* The X coordinate. */
+ int x;
+ /* The Y coordinate. */
+ int y;
+};
+
struct screen
{
/* The array of lines. */
int real_column;
/* The current line. */
int line;
- /* The X coordinate. */
- int x;
- /* The Y coordinate. */
- int y;
/* The kill buffer. */
char *killed_text;
/* The flag of a completion window. */
int completion_shown;
+
+ struct per_term_screen *terms;
+ unsigned nterms;
};
/* Used for storing completion items temporarily. */
static struct line completion_buffer;
+static int completion_type;
/* Initialize a line. */
static int
/* Return the number of lines occupied by this line on the screen. */
static int
-get_logical_num_lines (struct line *linep)
+get_logical_num_lines (struct line *linep, struct per_term_screen *term_screen)
{
- return (linep->len / GRUB_TERM_ENTRY_WIDTH) + 1;
+ return (linep->len / grub_term_entry_width (term_screen->term)) + 1;
}
/* Print a line. */
static void
-print_line (struct line *linep, int offset, int start, int y)
+print_line (struct line *linep, int offset, int start, int y,
+ struct per_term_screen *term_screen)
{
- int i;
- char *p;
-
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1,
- y + GRUB_TERM_FIRST_ENTRY_Y);
-
- for (p = linep->buf + offset + start, i = start;
- i < GRUB_TERM_ENTRY_WIDTH && offset + i < linep->len;
- p++, i++)
- grub_putchar (*p);
-
- for (; i < GRUB_TERM_ENTRY_WIDTH; i++)
- grub_putchar (' ');
+ grub_term_gotoxy (term_screen->term,
+ GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + start + 1,
+ y + GRUB_TERM_FIRST_ENTRY_Y);
- if (linep->len >= offset + GRUB_TERM_ENTRY_WIDTH)
- grub_putchar ('\\');
+ if (linep->len >= offset + grub_term_entry_width (term_screen->term))
+ {
+ char *p, c;
+ p = linep->buf + offset + start
+ + grub_term_entry_width (term_screen->term);
+ c = *p;
+ *p = 0;
+ grub_puts_terminal (linep->buf + offset + start, term_screen->term);
+ *p = c;
+ grub_putcode ('\\', term_screen->term);
+ }
else
- grub_putchar (' ');
+ {
+ int i;
+ for (i = 0;
+ i <= grub_term_entry_width (term_screen->term) - linep->len + offset;
+ i++)
+ grub_putcode (' ', term_screen->term);
+ }
}
/* Print an empty line. */
static void
-print_empty_line (int y)
+print_empty_line (int y, struct per_term_screen *term_screen)
{
int i;
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1,
- y + GRUB_TERM_FIRST_ENTRY_Y);
+ grub_term_gotoxy (term_screen->term,
+ GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1,
+ y + GRUB_TERM_FIRST_ENTRY_Y);
- for (i = 0; i < GRUB_TERM_ENTRY_WIDTH + 1; i++)
- grub_putchar (' ');
+ for (i = 0; i < grub_term_entry_width (term_screen->term) + 1; i++)
+ grub_putcode (' ', term_screen->term);
}
/* Print an up arrow. */
static void
-print_up (int flag)
+print_up (int flag, struct per_term_screen *term_screen)
{
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
- GRUB_TERM_FIRST_ENTRY_Y);
+ grub_term_gotoxy (term_screen->term, GRUB_TERM_LEFT_BORDER_X
+ + grub_term_entry_width (term_screen->term),
+ GRUB_TERM_FIRST_ENTRY_Y);
if (flag)
- grub_putcode (GRUB_TERM_DISP_UP);
+ grub_putcode (GRUB_TERM_DISP_UP, term_screen->term);
else
- grub_putchar (' ');
+ grub_putcode (' ', term_screen->term);
}
/* Print a down arrow. */
static void
-print_down (int flag)
+print_down (int flag, struct per_term_screen *term_screen)
{
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
- GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
+ 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));
if (flag)
- grub_putcode (GRUB_TERM_DISP_DOWN);
+ grub_putcode (GRUB_TERM_DISP_DOWN, term_screen->term);
else
- grub_putchar (' ');
+ grub_putcode (' ', term_screen->term);
}
/* Draw the lines of the screen SCREEN. */
static void
-update_screen (struct screen *screen, int region_start, int region_column,
+update_screen (struct screen *screen, struct per_term_screen *term_screen,
+ int region_start, int region_column,
int up, int down, enum update_mode mode)
{
int up_flag = 0;
struct line *linep;
/* Check if scrolling is necessary. */
- if (screen->y < 0 || screen->y >= GRUB_TERM_NUM_ENTRIES)
+ if (term_screen->y < 0 || term_screen->y
+ >= grub_term_num_entries (term_screen->term))
{
- if (screen->y < 0)
- screen->y = 0;
+ if (term_screen->y < 0)
+ term_screen->y = 0;
else
- screen->y = GRUB_TERM_NUM_ENTRIES - 1;
+ term_screen->y = grub_term_num_entries (term_screen->term) - 1;
region_start = 0;
region_column = 0;
{
/* Draw lines. This code is tricky, because this must calculate logical
positions. */
- y = screen->y - screen->column / GRUB_TERM_ENTRY_WIDTH;
+ y = term_screen->y - screen->column
+ / grub_term_entry_width (term_screen->term);
i = screen->line;
linep = screen->lines + i;
while (y > 0)
{
i--;
linep--;
- y -= get_logical_num_lines (linep);
+ y -= get_logical_num_lines (linep, term_screen);
}
if (y < 0 || i > 0)
int column;
for (column = 0;
- column <= linep->len && y < GRUB_TERM_NUM_ENTRIES;
- column += GRUB_TERM_ENTRY_WIDTH, y++)
+ column <= linep->len
+ && y < grub_term_num_entries (term_screen->term);
+ column += grub_term_entry_width (term_screen->term), y++)
{
if (y < 0)
continue;
if (i == region_start)
{
if (region_column >= column
- && region_column < column + GRUB_TERM_ENTRY_WIDTH)
- print_line (linep, column, region_column - column, y);
+ && region_column
+ < (column
+ + grub_term_entry_width (term_screen->term)))
+ print_line (linep, column, region_column - column, y,
+ term_screen);
else if (region_column < column)
- print_line (linep, column, 0, y);
+ print_line (linep, column, 0, y, term_screen);
}
else if (i > region_start && mode == ALL_LINES)
- print_line (linep, column, 0, y);
+ print_line (linep, column, 0, y, term_screen);
}
- if (y == GRUB_TERM_NUM_ENTRIES)
+ if (y == grub_term_num_entries (term_screen->term))
{
if (column <= linep->len || i + 1 < screen->num_lines)
down_flag = 1;
i++;
if (mode == ALL_LINES && i == screen->num_lines)
- for (; y < GRUB_TERM_NUM_ENTRIES; y++)
- print_empty_line (y);
+ for (; y < grub_term_num_entries (term_screen->term); y++)
+ print_empty_line (y, term_screen);
}
- while (y < GRUB_TERM_NUM_ENTRIES);
+ while (y < grub_term_num_entries (term_screen->term));
/* Draw up and down arrows. */
if (up)
- print_up (up_flag);
+ print_up (up_flag, term_screen);
if (down)
- print_down (down_flag);
+ print_down (down_flag, term_screen);
}
/* Place the cursor. */
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1 + screen->x,
- GRUB_TERM_FIRST_ENTRY_Y + screen->y);
+ grub_term_gotoxy (term_screen->term,
+ GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_MARGIN + 1
+ + term_screen->x,
+ GRUB_TERM_FIRST_ENTRY_Y + term_screen->y);
- grub_refresh ();
+ grub_term_refresh (term_screen->term);
+}
+
+static void
+update_screen_all (struct screen *screen,
+ int region_start, int region_column,
+ int up, int down, enum update_mode mode)
+{
+ unsigned i;
+ for (i = 0; i < screen->nterms; i++)
+ update_screen (screen, &screen->terms[i], region_start, region_column,
+ up, down, mode);
}
-/* Insert the string S into the screen SCREEN. This updates the cursor
- position and redraw the screen. Return zero if fails. */
static int
insert_string (struct screen *screen, char *s, int update)
{
int region_start = screen->num_lines;
int region_column = 0;
- int down = 0;
- enum update_mode mode = NO_LINE;
+ int down[screen->nterms];
+ enum update_mode mode[screen->nterms];
+ unsigned i;
+
+ for (i = 0; i < screen->nterms; i++)
+ {
+ down[i] = 0;
+ mode[i] = NO_LINE;
+ }
while (*s)
{
region_column = screen->column;
}
- mode = ALL_LINES;
- down = 1; /* XXX not optimal. */
+ for (i = 0; i < screen->nterms; i++)
+ {
+ mode[i] = ALL_LINES;
+ down[i] = 1; /* XXX not optimal. */
+ }
/* Move the cursor. */
screen->column = screen->real_column = 0;
screen->line++;
- screen->x = 0;
- screen->y++;
-
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].x = 0;
+ screen->terms[i].y++;
+ }
s++;
}
else
char *p;
struct line *current_linep;
int size;
- int orig_num, new_num;
+ int orig_num[screen->nterms], new_num[screen->nterms];
/* Find a string delimited by LF. */
p = grub_strchr (s, '\n');
grub_memmove (current_linep->buf + screen->column,
s,
size);
- orig_num = get_logical_num_lines (current_linep);
+ for (i = 0; i < screen->nterms; i++)
+ orig_num[i] = get_logical_num_lines (current_linep,
+ &screen->terms[i]);
current_linep->len += size;
- new_num = get_logical_num_lines (current_linep);
+ for (i = 0; i < screen->nterms; i++)
+ new_num[i] = get_logical_num_lines (current_linep,
+ &screen->terms[i]);
/* Update the dirty region. */
if (region_start > screen->line)
region_column = screen->column;
}
- if (orig_num != new_num)
- {
- mode = ALL_LINES;
- down = 1; /* XXX not optimal. */
- }
- else if (mode != ALL_LINES)
- mode = SINGLE_LINE;
+ for (i = 0; i < screen->nterms; i++)
+ if (orig_num[i] != new_num[i])
+ {
+ mode[i] = ALL_LINES;
+ down[i] = 1; /* XXX not optimal. */
+ }
+ else if (mode[i] != ALL_LINES)
+ mode[i] = SINGLE_LINE;
/* Move the cursor. */
screen->column += size;
screen->real_column = screen->column;
- screen->x += size;
- screen->y += screen->x / GRUB_TERM_ENTRY_WIDTH;
- screen->x %= GRUB_TERM_ENTRY_WIDTH;
-
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].x += size;
+ screen->terms[i].y += screen->terms[i].x
+ / grub_term_entry_width (screen->terms[i].term);
+ screen->terms[i].x
+ %= grub_term_entry_width (screen->terms[i].term);
+ }
s = p;
}
}
if (update)
- update_screen (screen, region_start, region_column, 0, down, mode);
+ for (i = 0; i < screen->nterms; i++)
+ update_screen (screen, &screen->terms[i],
+ region_start, region_column, 0, down[i], mode[i]);
return 1;
}
grub_free (screen->killed_text);
grub_free (screen->lines);
+ grub_free (screen->terms);
grub_free (screen);
}
make_screen (grub_menu_entry_t entry)
{
struct screen *screen;
+ unsigned i;
/* Initialize the screen. */
screen = grub_zalloc (sizeof (*screen));
screen->column = 0;
screen->real_column = 0;
screen->line = 0;
- screen->x = 0;
- screen->y = 0;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].x = 0;
+ screen->terms[i].y = 0;
+ }
return screen;
forward_char (struct screen *screen, int update)
{
struct line *linep;
+ unsigned i;
linep = screen->lines + screen->line;
if (screen->column < linep->len)
{
screen->column++;
- screen->x++;
- if (screen->x == GRUB_TERM_ENTRY_WIDTH)
+ for (i = 0; i < screen->nterms; i++)
{
- screen->x = 0;
- screen->y++;
+ screen->terms[i].x++;
+ if (screen->terms[i].x
+ == grub_term_entry_width (screen->terms[i].term))
+ {
+ screen->terms[i].x = 0;
+ screen->terms[i].y++;
+ }
}
}
else if (screen->num_lines > screen->line + 1)
{
screen->column = 0;
screen->line++;
- screen->x = 0;
- screen->y++;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].x = 0;
+ screen->terms[i].y++;
+ }
}
screen->real_column = screen->column;
if (update)
- update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+ update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
return 1;
}
static int
backward_char (struct screen *screen, int update)
{
+ unsigned i;
+
if (screen->column > 0)
{
screen->column--;
- screen->x--;
- if (screen->x == -1)
+ for (i = 0; i < screen->nterms; i++)
{
- screen->x = GRUB_TERM_ENTRY_WIDTH - 1;
- screen->y--;
+ screen->terms[i].x--;
+ if (screen->terms[i].x == -1)
+ {
+ screen->terms[i].x
+ = grub_term_entry_width (screen->terms[i].term) - 1;
+ screen->terms[i].y--;
+ }
}
}
else if (screen->line > 0)
screen->line--;
linep = screen->lines + screen->line;
screen->column = linep->len;
- screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
- screen->y--;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].x = screen->column
+ % grub_term_entry_width (screen->terms[i].term);
+ screen->terms[i].y--;
+ }
}
screen->real_column = screen->column;
if (update)
- update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+ update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
return 1;
}
static int
previous_line (struct screen *screen, int update)
{
+ unsigned i;
+
if (screen->line > 0)
{
struct line *linep;
- int dy;
+ int col;
/* How many physical lines from the current position
to the first physical line? */
- dy = screen->column / GRUB_TERM_ENTRY_WIDTH;
+ col = screen->column;
screen->line--;
else
screen->column = screen->real_column;
- /* How many physical lines from the current position
- to the last physical line? */
- dy += (linep->len / GRUB_TERM_ENTRY_WIDTH
- - screen->column / GRUB_TERM_ENTRY_WIDTH);
-
- screen->y -= dy + 1;
- screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ int dy;
+ dy = col / grub_term_entry_width (screen->terms[i].term);
+
+ /* How many physical lines from the current position
+ to the last physical line? */
+ dy += (linep->len / grub_term_entry_width (screen->terms[i].term)
+ - screen->column
+ / grub_term_entry_width (screen->terms[i].term));
+
+ screen->terms[i].y -= dy + 1;
+ screen->terms[i].x
+ = screen->column % grub_term_entry_width (screen->terms[i].term);
+ }
}
else
{
- screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].y
+ -= screen->column / grub_term_entry_width (screen->terms[i].term);
+ screen->terms[i].x = 0;
+ }
screen->column = 0;
- screen->x = 0;
}
if (update)
- update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+ update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
return 1;
}
static int
next_line (struct screen *screen, int update)
{
+ unsigned i;
+
if (screen->line < screen->num_lines - 1)
{
struct line *linep;
- int dy;
+ int l1, c1;
/* How many physical lines from the current position
to the last physical line? */
linep = screen->lines + screen->line;
- dy = (linep->len / GRUB_TERM_ENTRY_WIDTH
- - screen->column / GRUB_TERM_ENTRY_WIDTH);
+ l1 = linep->len;
+ c1 = screen->column;
screen->line++;
else
screen->column = screen->real_column;
- /* How many physical lines from the current position
- to the first physical line? */
- dy += screen->column / GRUB_TERM_ENTRY_WIDTH;
-
- screen->y += dy + 1;
- screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ int dy;
+ dy = l1 / grub_term_entry_width (screen->terms[i].term)
+ - c1 / grub_term_entry_width (screen->terms[i].term);
+ /* How many physical lines from the current position
+ to the first physical line? */
+ dy += screen->column / grub_term_entry_width (screen->terms[i].term);
+ screen->terms[i].y += dy + 1;
+ screen->terms[i].x = screen->column
+ % grub_term_entry_width (screen->terms[i].term);
+ }
}
else
{
struct line *linep;
-
+ int l, s;
+
linep = screen->lines + screen->line;
- screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
- - screen->column / GRUB_TERM_ENTRY_WIDTH);
+ l = linep->len;
+ s = screen->column;
screen->column = linep->len;
- screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].y
+ += (l / grub_term_entry_width (screen->terms[i].term)
+ - s / grub_term_entry_width (screen->terms[i].term));
+ screen->terms[i].x
+ = screen->column % grub_term_entry_width (screen->terms[i].term);
+ }
}
if (update)
- update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+ update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
return 1;
}
static int
beginning_of_line (struct screen *screen, int update)
{
- screen->y -= screen->column / GRUB_TERM_ENTRY_WIDTH;
+ unsigned i;
+ int col;
+
+ col = screen->column;
screen->column = screen->real_column = 0;
- screen->x = 0;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].x = 0;
+ screen->terms[i].y -= col / grub_term_entry_width (screen->terms[i].term);
+ }
if (update)
- update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+ update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
return 1;
}
end_of_line (struct screen *screen, int update)
{
struct line *linep;
+ unsigned i;
+ int col;
linep = screen->lines + screen->line;
- screen->y += (linep->len / GRUB_TERM_ENTRY_WIDTH
- - screen->column / GRUB_TERM_ENTRY_WIDTH);
+ col = screen->column;
screen->column = screen->real_column = linep->len;
- screen->x = screen->column % GRUB_TERM_ENTRY_WIDTH;
+ for (i = 0; i < screen->nterms; i++)
+ {
+ screen->terms[i].y
+ += (linep->len / grub_term_entry_width (screen->terms->term)
+ - col / grub_term_entry_width (screen->terms->term));
+ screen->terms[i].x
+ = screen->column % grub_term_entry_width (screen->terms->term);
+ }
if (update)
- update_screen (screen, screen->num_lines, 0, 0, 0, NO_LINE);
+ update_screen_all (screen, screen->num_lines, 0, 0, 0, NO_LINE);
return 1;
}
delete_char (struct screen *screen, int update)
{
struct line *linep;
- enum update_mode mode = NO_LINE;
int start = screen->num_lines;
int column = 0;
- int down = 0;
linep = screen->lines + screen->line;
if (linep->len > screen->column)
{
- int orig_num, new_num;
+ int orig_num[screen->nterms], new_num;
+ unsigned i;
- orig_num = get_logical_num_lines (linep);
+ for (i = 0; i < screen->nterms; i++)
+ orig_num[i] = get_logical_num_lines (linep, &screen->terms[i]);
grub_memmove (linep->buf + screen->column,
linep->buf + screen->column + 1,
linep->len - screen->column - 1);
linep->len--;
- new_num = get_logical_num_lines (linep);
-
- if (orig_num != new_num)
- mode = ALL_LINES;
- else
- mode = SINGLE_LINE;
-
start = screen->line;
column = screen->column;
+
+ screen->real_column = screen->column;
+
+ if (update)
+ {
+ for (i = 0; i < screen->nterms; i++)
+ {
+ new_num = get_logical_num_lines (linep, &screen->terms[i]);
+ if (orig_num[i] != new_num)
+ update_screen (screen, &screen->terms[i],
+ start, column, 0, 0, ALL_LINES);
+ else
+ update_screen (screen, &screen->terms[i],
+ start, column, 0, 0, SINGLE_LINE);
+ }
+ }
}
else if (screen->num_lines > screen->line + 1)
{
* sizeof (struct line));
screen->num_lines--;
- mode = ALL_LINES;
start = screen->line;
column = screen->column;
- down = 1;
- }
-
- screen->real_column = screen->column;
- if (update)
- update_screen (screen, start, column, 0, down, mode);
+ screen->real_column = screen->column;
+ if (update)
+ update_screen_all (screen, start, column, 0, 1, ALL_LINES);
+ }
return 1;
}
if (size > 0)
{
- enum update_mode mode = SINGLE_LINE;
- int down = 0;
- int orig_num, new_num;
+ int orig_num[screen->nterms], new_num;
+ unsigned i;
p = grub_realloc (p, offset + size + 1);
if (! p)
screen->killed_text = p;
- orig_num = get_logical_num_lines (linep);
+ for (i = 0; i < screen->nterms; i++)
+ orig_num[i] = get_logical_num_lines (linep, &screen->terms[i]);
linep->len = screen->column;
- new_num = get_logical_num_lines (linep);
- if (orig_num != new_num)
+ if (update)
{
- mode = ALL_LINES;
- down = 1;
+ new_num = get_logical_num_lines (linep, &screen->terms[i]);
+ for (i = 0; i < screen->nterms; i++)
+ {
+ if (orig_num[i] != new_num)
+ update_screen (screen, &screen->terms[i],
+ screen->line, screen->column, 0, 1, ALL_LINES);
+ else
+ update_screen (screen, &screen->terms[i],
+ screen->line, screen->column, 0, 0, SINGLE_LINE);
+ }
}
-
- if (update)
- update_screen (screen, screen->line, screen->column, 0, down, mode);
}
else if (screen->line + 1 < screen->num_lines)
{
static int
open_line (struct screen *screen, int update)
{
- int saved_y = screen->y;
+ int saved_y[screen->nterms];
+ unsigned i;
+
+ for (i = 0; i < screen->nterms; i++)
+ saved_y[i] = screen->terms[i].y;
if (! insert_string (screen, "\n", 0))
return 0;
if (! backward_char (screen, 0))
return 0;
- screen->y = saved_y;
+ for (i = 0; i < screen->nterms; i++)
+ screen->terms[i].y = saved_y[i];
if (update)
- update_screen (screen, screen->line, screen->column, 0, 1, ALL_LINES);
+ update_screen_all (screen, screen->line, screen->column, 0, 1, ALL_LINES);
return 1;
}
/* A completion hook to print items. */
static void
-store_completion (const char *item, grub_completion_type_t type, int count)
+store_completion (const char *item, grub_completion_type_t type,
+ int count __attribute__ ((unused)))
{
char *p;
- if (count == 0)
- {
- /* If this is the first time, print a label. */
- const char *what;
-
- switch (type)
- {
- case GRUB_COMPLETION_TYPE_COMMAND:
- what = "commands";
- break;
- case GRUB_COMPLETION_TYPE_DEVICE:
- what = "devices";
- break;
- case GRUB_COMPLETION_TYPE_FILE:
- what = "files";
- break;
- case GRUB_COMPLETION_TYPE_PARTITION:
- what = "partitions";
- break;
- case GRUB_COMPLETION_TYPE_ARGUMENT:
- what = "arguments";
- break;
- default:
- what = "things";
- break;
- }
-
- grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
- grub_printf (" ");
- grub_printf_ (N_("Possible %s are:"), what);
- grub_printf ("\n ");
- }
+ completion_type = type;
/* Make sure that the completion buffer has enough room. */
if (completion_buffer.max_len < (completion_buffer.len
static int
complete (struct screen *screen, int continuous, int update)
{
- grub_uint16_t pos;
char saved_char;
struct line *linep;
int restore;
char *insert;
static int count = -1;
+ unsigned i;
+ grub_uint32_t *ucs4;
+ grub_size_t buflen;
+ grub_ssize_t ucs4len;
if (continuous)
count++;
else
count = 0;
- pos = grub_getxy ();
- grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
-
completion_buffer.buf = 0;
completion_buffer.len = 0;
completion_buffer.max_len = 0;
linep->buf[screen->column] = saved_char;
- if (restore)
- {
- char *p = completion_buffer.buf;
-
- screen->completion_shown = 1;
-
- if (p)
- {
- int num_sections = ((completion_buffer.len + GRUB_TERM_WIDTH - 8 - 1)
- / (GRUB_TERM_WIDTH - 8));
- char *endp;
-
- p += (count % num_sections) * (GRUB_TERM_WIDTH - 8);
- endp = p + (GRUB_TERM_WIDTH - 8);
-
- if (p != completion_buffer.buf)
- grub_putcode (GRUB_TERM_DISP_LEFT);
- else
- grub_putchar (' ');
+ buflen = grub_strlen (completion_buffer.buf);
+ ucs4 = grub_malloc (sizeof (grub_uint32_t) * (buflen + 1));
- while (*p && p < endp)
- grub_putchar (*p++);
-
- if (*p)
- grub_putcode (GRUB_TERM_DISP_RIGHT);
- }
+ if (!ucs4)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ return 1;
}
- grub_gotoxy (pos >> 8, pos & 0xFF);
+ ucs4len = grub_utf8_to_ucs4 (ucs4, buflen,
+ (grub_uint8_t *) completion_buffer.buf,
+ buflen, 0);
+ ucs4[ucs4len] = 0;
+
+ if (restore)
+ for (i = 0; i < screen->nterms; i++)
+ {
+ int num_sections = ((completion_buffer.len
+ + grub_term_width (screen->terms[i].term) - 8 - 1)
+ / (grub_term_width (screen->terms[i].term) - 8));
+ grub_uint32_t *endp;
+ grub_uint16_t pos;
+ grub_uint32_t *p = ucs4;
+
+ pos = grub_term_getxy (screen->terms[i].term);
+ grub_term_gotoxy (screen->terms[i].term, 0,
+ grub_term_height (screen->terms[i].term) - 3);
+
+ screen->completion_shown = 1;
+
+ grub_term_gotoxy (screen->terms[i].term, 0,
+ grub_term_height (screen->terms[i].term) - 3);
+ grub_puts_terminal (" ", screen->terms[i].term);
+ switch (completion_type)
+ {
+ case GRUB_COMPLETION_TYPE_COMMAND:
+ grub_puts_terminal (_("Possible commands are:"),
+ screen->terms[i].term);
+ break;
+ case GRUB_COMPLETION_TYPE_DEVICE:
+ grub_puts_terminal (_("Possible devices are:"),
+ screen->terms[i].term);
+ break;
+ case GRUB_COMPLETION_TYPE_FILE:
+ grub_puts_terminal (_("Possible files are:"),
+ screen->terms[i].term);
+ break;
+ case GRUB_COMPLETION_TYPE_PARTITION:
+ grub_puts_terminal (_("Possible partitions are:"),
+ screen->terms[i].term);
+ break;
+ case GRUB_COMPLETION_TYPE_ARGUMENT:
+ grub_puts_terminal (_("Possible arguments are:"),
+ screen->terms[i].term);
+ break;
+ default:
+ grub_puts_terminal (_("Possible things are:"),
+ screen->terms[i].term);
+ break;
+ }
+
+ grub_puts_terminal ("\n ", screen->terms[i].term);
+
+ p += (count % num_sections)
+ * (grub_term_width (screen->terms[i].term) - 8);
+ endp = p + (grub_term_width (screen->terms[i].term) - 8);
+
+ if (p != ucs4)
+ grub_putcode (GRUB_TERM_DISP_LEFT, screen->terms[i].term);
+ else
+ grub_putcode (' ', screen->terms[i].term);
+
+ while (*p && p < endp)
+ grub_putcode (*p++, screen->terms[i].term);
+
+ if (*p)
+ grub_putcode (GRUB_TERM_DISP_RIGHT, screen->terms[i].term);
+ grub_term_gotoxy (screen->terms[i].term, pos >> 8, pos & 0xFF);
+ }
if (insert)
{
/* Clear displayed completions. */
static void
-clear_completions (void)
+clear_completions (struct per_term_screen *term_screen)
{
grub_uint16_t pos;
- int i, j;
+ unsigned i, j;
- pos = grub_getxy ();
- grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
+ pos = grub_term_getxy (term_screen->term);
+ grub_term_gotoxy (term_screen->term, 0,
+ grub_term_height (term_screen->term) - 3);
for (i = 0; i < 2; i++)
{
- for (j = 0; j < GRUB_TERM_WIDTH - 1; j++)
- grub_putchar (' ');
- grub_putchar ('\n');
+ for (j = 0; j < grub_term_width (term_screen->term) - 1; j++)
+ grub_putcode (' ', term_screen->term);
+ grub_putcode ('\n', term_screen->term);
}
- grub_gotoxy (pos >> 8, pos & 0xFF);
- grub_refresh ();
+ grub_term_gotoxy (term_screen->term, pos >> 8, pos & 0xFF);
+ grub_term_refresh (term_screen->term);
+}
+
+static void
+clear_completions_all (struct screen *screen)
+{
+ unsigned i;
+
+ for (i = 0; i < screen->nterms; i++)
+ clear_completions (&screen->terms[i]);
}
/* Execute the command list in the screen SCREEN. */
struct screen *screen;
int prev_c;
grub_err_t err = GRUB_ERR_NONE;
+ unsigned i;
err = grub_auth_check_authentication (NULL);
refresh:
/* Draw the screen. */
- grub_menu_init_page (0, 1);
- update_screen (screen, 0, 0, 1, 1, ALL_LINES);
- grub_setcursor (1);
+ for (i = 0; i < screen->nterms; i++)
+ grub_menu_init_page (0, 1, 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);
prev_c = '\0';
while (1)
if (screen->completion_shown)
{
- clear_completions ();
+ clear_completions_all (screen);
screen->completion_shown = 0;
}
#include <grub/env.h>
#include <grub/menu_viewer.h>
#include <grub/i18n.h>
-
-/* Time to delay after displaying an error message about a default/fallback
- entry failing to boot. */
-#define DEFAULT_ENTRY_ERROR_DELAY_MS 2500
+#include <grub/charset.h>
static grub_uint8_t grub_color_menu_normal;
static grub_uint8_t grub_color_menu_highlight;
-/* Wait until the user pushes any key so that the user
- can see what happened. */
-void
-grub_wait_after_message (void)
+struct menu_viewer_data
{
- grub_putchar ('\n');
- grub_printf_ (N_("Press any key to continue..."));
- (void) grub_getkey ();
- grub_putchar ('\n');
-}
+ int first, offset;
+ grub_menu_t menu;
+ struct grub_term_output *term;
+};
static void
-print_spaces (int number_spaces)
+print_spaces (int number_spaces, struct grub_term_output *term)
{
int i;
for (i = 0; i < number_spaces; i++)
- grub_putchar (' ');
+ grub_putcode (' ', term);
}
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)
{
while (str < last_position)
{
- grub_putcode (*str);
+ grub_putcode (*str, term);
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_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;
while (str < last_position)
{
- width += grub_getcharwidth (*str);
+ width += grub_term_getcharwidth (term, *str);
str++;
}
return width;
}
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;
- line_len = GRUB_TERM_WIDTH - grub_getcharwidth ('m') *
- (margin_left + margin_right);
grub_uint32_t *unicode_msg;
grub_uint32_t *last_position;
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);
if (msg_len < 0)
while (current_position < last_position)
{
if (! first_loop)
- grub_putchar ('\n');
+ grub_putcode ('\n', term);
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 != ' ' && next_new_line > current_position &&
next_new_line != last_position))
{
(grub_uint32_t *) last_position : next_new_line + line_len;
}
- print_spaces (margin_left);
- grub_print_ucs4 (current_position, next_new_line);
+ print_spaces (margin_left, term);
+ grub_print_ucs4 (current_position, next_new_line, term);
next_new_line++;
current_position = next_new_line;
static void
-draw_border (void)
+draw_border (struct grub_term_output *term)
{
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_putcode (GRUB_TERM_DISP_UL);
- for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
- grub_putcode (GRUB_TERM_DISP_HLINE);
- grub_putcode (GRUB_TERM_DISP_UR);
+ grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y);
+ grub_putcode (GRUB_TERM_DISP_UL, term);
+ for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++)
+ grub_putcode (GRUB_TERM_DISP_HLINE, term);
+ 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_putcode (GRUB_TERM_DISP_VLINE);
- grub_gotoxy (GRUB_TERM_MARGIN + GRUB_TERM_BORDER_WIDTH - 1,
- GRUB_TERM_TOP_BORDER_Y + i + 1);
- grub_putcode (GRUB_TERM_DISP_VLINE);
+ grub_term_gotoxy (term, GRUB_TERM_MARGIN, GRUB_TERM_TOP_BORDER_Y + i + 1);
+ grub_putcode (GRUB_TERM_DISP_VLINE, term);
+ grub_term_gotoxy (term, GRUB_TERM_MARGIN + grub_term_border_width (term)
+ - 1,
+ GRUB_TERM_TOP_BORDER_Y + i + 1);
+ grub_putcode (GRUB_TERM_DISP_VLINE, term);
}
- grub_gotoxy (GRUB_TERM_MARGIN,
- GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES + 1);
- grub_putcode (GRUB_TERM_DISP_LL);
- for (i = 0; i < (unsigned) GRUB_TERM_BORDER_WIDTH - 2; i++)
- grub_putcode (GRUB_TERM_DISP_HLINE);
- grub_putcode (GRUB_TERM_DISP_LR);
+ grub_term_gotoxy (term, GRUB_TERM_MARGIN,
+ GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term) + 1);
+ grub_putcode (GRUB_TERM_DISP_LL, term);
+ for (i = 0; i < (unsigned) grub_term_border_width (term) - 2; i++)
+ grub_putcode (GRUB_TERM_DISP_HLINE, term);
+ 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_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES
- + GRUB_TERM_MARGIN + 1));
+ grub_term_gotoxy (term, GRUB_TERM_MARGIN,
+ (GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term)
+ + GRUB_TERM_MARGIN + 1));
}
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)
{
- grub_putchar ('\n');
+ grub_putcode ('\n', term);
grub_print_message_indented (_("Minimum Emacs-like screen editing is \
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
{
grub_sprintf (msg_translated, msg, (grub_uint32_t) GRUB_TERM_DISP_UP,
(grub_uint32_t) GRUB_TERM_DISP_DOWN);
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_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);
+\'e\' to edit the commands before booting or \'c\' for a command-line.\n"),
+ STANDARD_MARGIN, STANDARD_MARGIN, term);
if (nested)
{
}
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;
const char *title;
return;
}
- grub_getcolor (&old_color_normal, &old_color_highlight);
- grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
- grub_setcolorstate (highlight
- ? GRUB_TERM_COLOR_HIGHLIGHT
- : GRUB_TERM_COLOR_NORMAL);
+ grub_term_getcolor (term, &old_color_normal, &old_color_highlight);
+ grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight);
+ grub_term_setcolorstate (term, highlight
+ ? GRUB_TERM_COLOR_HIGHLIGHT
+ : 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;
- 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++)
{
if (i < len
- && x <= (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH
- - GRUB_TERM_MARGIN - 1))
+ && x <= (int) (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term)
+ - GRUB_TERM_MARGIN - 1))
{
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
- - GRUB_TERM_MARGIN - 1))
- grub_putcode (GRUB_TERM_DISP_RIGHT);
+ if (x + width > (int) (GRUB_TERM_LEFT_BORDER_X
+ + grub_term_border_width (term)
+ - GRUB_TERM_MARGIN - 1))
+ grub_putcode (GRUB_TERM_DISP_RIGHT, term);
else
- grub_putcode (unicode_title[i]);
+ grub_putcode (unicode_title[i], term);
x += width;
}
else
{
- grub_putchar (' ');
+ grub_putcode (' ', term);
x++;
}
}
- grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
- grub_putchar (' ');
+ grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
+ 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_setcolorstate (GRUB_TERM_COLOR_NORMAL);
+ grub_term_setcolor (term, old_color_normal, old_color_highlight);
+ grub_term_setcolorstate (term, GRUB_TERM_COLOR_NORMAL);
grub_free (unicode_title);
}
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;
int i;
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
- GRUB_TERM_FIRST_ENTRY_Y);
+ grub_term_gotoxy (term,
+ GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term),
+ GRUB_TERM_FIRST_ENTRY_Y);
if (first)
- grub_putcode (GRUB_TERM_DISP_UP);
+ grub_putcode (GRUB_TERM_DISP_UP, term);
else
- grub_putchar (' ');
+ grub_putcode (' ', term);
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)
e = e->next;
}
- grub_gotoxy (GRUB_TERM_LEFT_BORDER_X + GRUB_TERM_BORDER_WIDTH,
- GRUB_TERM_TOP_BORDER_Y + GRUB_TERM_NUM_ENTRIES);
+ grub_term_gotoxy (term, GRUB_TERM_LEFT_BORDER_X
+ + grub_term_border_width (term),
+ GRUB_TERM_TOP_BORDER_Y + grub_term_num_entries (term));
if (e)
- grub_putcode (GRUB_TERM_DISP_DOWN);
+ grub_putcode (GRUB_TERM_DISP_DOWN, term);
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
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,
+ struct grub_term_output *term)
{
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. */
grub_color_menu_normal = old_color_normal;
grub_color_menu_highlight = old_color_highlight;
/* 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_highlight, grub_env_get ("menu_color_highlight"));
-
- grub_normal_init_page ();
- grub_setcolor (grub_color_menu_normal, grub_color_menu_highlight);
- draw_border ();
- grub_setcolor (old_color_normal, old_color_highlight);
- print_message (nested, edit);
-}
-
-/* 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;
+ grub_parse_color_name_pair (&grub_color_menu_normal,
+ 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 (term);
+ grub_term_setcolor (term, grub_color_menu_normal, grub_color_menu_highlight);
+ draw_border (term);
+ grub_term_setcolor (term, old_color_normal, old_color_highlight);
+ print_message (nested, edit, term);
}
static void
-print_timeout (int timeout, int offset)
+menu_text_print_timeout (int timeout, void *dataptr)
{
const char *msg =
_("The highlighted entry will be booted automatically in %ds.");
+ struct menu_viewer_data *data = dataptr;
+ char *msg_translated;
+ int posx;
- grub_gotoxy (0, GRUB_TERM_HEIGHT - 3);
+ grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3);
- char *msg_translated =
- grub_malloc (sizeof (char) * grub_strlen (msg) + 5);
+ msg_translated = grub_malloc (sizeof (char) * grub_strlen (msg) + 5);
+ if (!msg_translated)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ return;
+ }
grub_sprintf (msg_translated, msg, timeout);
- grub_print_message_indented (msg_translated, 3, 0);
+ grub_print_message_indented (msg_translated, 3, 0, data->term);
- int posx;
- posx = grub_getxy() >> 8;
- print_spaces (GRUB_TERM_WIDTH - posx - 1);
+ posx = grub_term_getxy (data->term) >> 8;
+ print_spaces (grub_term_width (data->term) - posx - 1, data->term);
- grub_gotoxy (GRUB_TERM_CURSOR_X, GRUB_TERM_FIRST_ENTRY_Y + offset);
- grub_refresh ();
+ grub_term_gotoxy (data->term,
+ grub_term_cursor_x (data->term),
+ GRUB_TERM_FIRST_ENTRY_Y + data->offset);
+ grub_term_refresh (data->term);
}
-/* 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)
+static void
+menu_text_set_chosen_entry (int entry, void *dataptr)
{
- 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)
+ struct menu_viewer_data *data = dataptr;
+ int oldoffset = data->offset;
+ int complete_redraw = 0;
+ data->offset = entry - data->first;
+ if (data->offset > grub_term_num_entries (data->term) - 1)
{
- *auto_boot = 1;
- return default_entry;
+ data->first = data->offset - (grub_term_num_entries (data->term) - 1);
+ data->offset = grub_term_num_entries (data->term) - 1;
+ complete_redraw = 1;
}
-
- offset = default_entry;
- if (offset > GRUB_TERM_NUM_ENTRIES - 1)
+ if (data->offset < 0)
{
- first = offset - (GRUB_TERM_NUM_ENTRIES - 1);
- offset = GRUB_TERM_NUM_ENTRIES - 1;
+ data->offset = 0;
+ data->first = entry;
+ complete_redraw = 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)
+ if (complete_redraw)
+ print_entries (data->menu, data->first, data->offset, data->term);
+ else
{
- 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);
- 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 ();
- }
+ 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);
}
-
- /* Never reach here. */
- return -1;
+ grub_term_refresh (data->term);
}
-/* Callback invoked immediately before a menu entry is executed. */
static void
-notify_booting (grub_menu_entry_t entry,
- void *userdata __attribute__((unused)))
+menu_text_fini (void *dataptr)
{
- grub_printf (" ");
- grub_printf_ (N_("Booting \'%s\'"), entry->title);
- grub_printf ("\n\n");
-}
+ struct menu_viewer_data *data = dataptr;
-/* 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);
+ grub_term_setcursor (data->term, 1);
}
-/* 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)))
+menu_text_clear_timeout (void *dataptr)
{
- 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 ();
+ 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);
}
-/* Callbacks used by the text menu to provide user feedback when menu entries
- are executed. */
-static struct grub_menu_execute_callback execution_callback =
+void
+grub_menu_text_register_instances (int entry, grub_menu_t menu, int nested)
{
- .notify_booting = notify_booting,
- .notify_fallback = notify_fallback,
- .notify_failure = notify_execution_failure
-};
+ struct menu_viewer_data *data;
+ struct grub_menu_viewer *instance;
+ struct grub_term_output *term;
-static grub_err_t
-show_text_menu (grub_menu_t menu, int nested)
-{
- while (1)
+ for (term = grub_term_outputs; term; term = term->next)
{
- 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 ();
- grub_setcursor (1);
+ if (!grub_term_is_active (term))
+ continue;
+ instance = grub_zalloc (sizeof (*instance));
+ if (!instance)
+ {
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ data = grub_zalloc (sizeof (*data));
+ if (!data)
+ {
+ grub_free (instance);
+ grub_print_error ();
+ grub_errno = GRUB_ERR_NONE;
+ continue;
+ }
+ 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;
+ }
- 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 ();
- }
- }
+ 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);
}
-
- return GRUB_ERR_NONE;
}
-
-struct grub_menu_viewer grub_normal_text_menu_viewer =
-{
- .name = "text",
- .show_menu = show_text_menu
-};
#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;
-}
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <grub/term.h>
+#include <grub/misc.h>
+#include <grub/mm.h>
+
/* The amount of lines counted by the pager. */
-static int grub_more_lines;
+static unsigned grub_more_lines;
/* If the more pager is active. */
static int grub_more;
static void
process_newline (void)
{
- if (code == '\n')
+ struct grub_term_output *cur;
+ unsigned height = -1;
+
+ for (cur = grub_term_outputs; cur; cur = cur->next)
+ if (grub_term_is_active(cur) && grub_term_height (cur) < height)
+ height = grub_term_height (cur);
+ grub_more_lines++;
+
+ if (grub_more && grub_more_lines == height - 1)
{
- grub_putcode ('\r');
-
- grub_more_lines++;
-
- if (grub_more && grub_more_lines == height - 1)
- {
- char key;
- int pos = term->getxy ();
-
- /* Show --MORE-- on the lower left side of the screen. */
- term->gotoxy (1, height - 1);
- grub_setcolorstate (GRUB_TERM_COLOR_HIGHLIGHT);
- grub_printf ("--MORE--");
- grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
-
- key = grub_getkey ();
-
- /* Remove the message. */
- term->gotoxy (1, height - 1);
- grub_printf (" ");
- term->gotoxy (pos >> 8, pos & 0xFF);
-
- /* Scroll one lines or an entire page, depending on the key. */
- if (key == '\r' || key =='\n')
- grub_more_lines--;
- else
- grub_more_lines = 0;
- }
+ 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--;
+ else
+ grub_more_lines = 0;
}
}
grub_more--;
grub_more_lines = 0;
+ grub_newline_hook = process_newline;
}
void
{
grub_uint32_t code;
grub_ssize_t ret;
- const char *ptr = str;
- unsigned i;
+ 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,
- grub_strlen (ptr), &ptr);
- if (ret < 0)
- {
- grub_putcode ('?', term);
- ptr++;
- continue;
- }
- else
- grub_putcode (code, term);
+ ret = grub_utf8_to_ucs4 (&code, 1, ptr, end - ptr, &ptr);
+ grub_putcode (code, term);
}
}
grub_uint16_t *ret, *ptr;
for (cur = grub_term_outputs; cur; cur = cur->next)
- if (cur->flags & GRUB_TERM_ACTIVE)
+ if (grub_term_is_active (cur))
cnt++;
ret = grub_malloc (cnt * sizeof (ret[0]));
if (!ret)
return NULL;
+ ptr = ret;
for (cur = grub_term_outputs; cur; cur = cur->next)
- if (cur->flags & GRUB_TERM_ACTIVE)
- *ptr++ = cur->getxy ();
+ if (grub_term_is_active (cur))
+ *ptr++ = grub_term_getxy (cur);
return ret;
}
grub_term_restore_pos (grub_uint16_t *pos)
{
struct grub_term_output *cur;
+ grub_uint16_t *ptr = pos;
if (!pos)
return;
for (cur = grub_term_outputs; cur; cur = cur->next)
- if (cur->flags & GRUB_TERM_ACTIVE)
- cur->gotoxy ((*ptr & 0xff00) >> 8, *ptr & 0xff);
+ if (grub_term_is_active (cur))
+ {
+ grub_term_gotoxy (cur, (*ptr & 0xff00) >> 8, *ptr & 0xff);
+ ptr++;
+ }
}
.setcolor = grub_console_setcolor,
.getcolor = grub_console_getcolor,
.setcursor = grub_console_setcursor,
- .flags = 0,
+ .flags = GRUB_TERM_ACTIVE,
};
void
.setcolor = grub_console_setcolor,
.getcolor = grub_console_getcolor,
.setcursor = grub_console_setcursor,
- .flags = 0,
+ .flags = GRUB_TERM_ACTIVE,
};
void
.setcolor = grub_console_setcolor,
.getcolor = grub_console_getcolor,
.setcursor = grub_vga_text_setcursor,
+#if defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
+ .flags = GRUB_TERM_ACTIVE,
+#endif
};
GRUB_MOD_INIT(vga_text)
{
+#if defined (GRUB_MACHINE_COREBOOT) || defined (GRUB_MACHINE_QEMU)
+ grub_vga_text_init_fini ();
+#endif
+
grub_term_register_output ("vga_text", &grub_vga_text_term);
}
.getcolor = grub_ofconsole_getcolor,
.setcursor = grub_ofconsole_setcursor,
.refresh = grub_ofconsole_refresh,
- .flags = 0,
+ .flags = GRUB_TERM_ACTIVE,
};
void
.getcolor = grub_ncurses_getcolor,
.setcursor = grub_ncurses_setcursor,
.refresh = grub_ncurses_refresh,
- .flags = 0,
+ .flags = GRUB_TERM_ACTIVE
};
void