+2011-04-10 Vladimir Serbinenko <phcoder@gmail.com>
+
+ Dynamically count the number of lines for the lower banner.
+
+ * grub-core/normal/menu_entry.c (per_term_screen): New member
+ num_entries.
+ (print_down): Use num_entries.
+ (update_screen): Likewise.
+ (grub_menu_entry_run): Set num_entries.
+ * grub-core/normal/menu_text.c (menu_viewer_data): New member
+ num_entries.
+ (grub_print_message_indented): Move real part to ...
+ (grub_print_message_indented_real): ... here. Additional argument
+ dry_run.
+ (draw_border): Additional argument num_entries.
+ (print_message): Additional argument dry_run.
+ (print_entries): Receive menu viewer data.
+ (grub_menu_init_page): New argment num_entries.
+ (menu_text_set_chosen_entry): Use num_entries.
+ (grub_menu_try_text): Likewise.
+ * grub-core/normal/term.c (print_ucs4_terminal): New argument dry_run.
+ All users updated.
+ (grub_ucs4_count_lines): New function.
+ * include/grub/term.h (grub_term_cursor_x): Moved from here ..
+ * grub-core/normal/menu_text.c (grub_term_cursor_x): ... to here.
+ * include/grub/term.h (GRUB_TERM_MESSAGE_HEIGHT): Removed.
+ (grub_term_border_height): Likewise.
+ (grub_term_num_entries): Likewise.
+
2011-04-10 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/boot/mips/yeeloong/fwstart.S: Fix address to error message.
int x;
/* The Y coordinate. */
int y;
+ /* Number of entries. */
+ int num_entries;
};
struct 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);
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;
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)
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;
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)
}
/* 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);
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)
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;
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);
}
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);
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);
- grub_print_message_indented (_("Minimum Emacs-like screen editing is \
+ 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);
+ STANDARD_MARGIN, STANDARD_MARGIN,
+ term, dry_run);
}
else
{
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
}
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. */
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
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)
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,
data->offset = entry;
data->first = 0;
- if (data->offset > grub_term_num_entries (data->term) - 1)
+
+ grub_term_setcursor (data->term, 0);
+ grub_menu_init_page (nested, 0, &data->num_entries, data->term);
+
+ if (data->offset > data->num_entries - 1)
{
- data->first = data->offset - (grub_term_num_entries (data->term) - 1);
- data->offset = grub_term_num_entries (data->term) - 1;
+ data->first = data->offset - (data->num_entries - 1);
+ data->offset = data->num_entries - 1;
}
- grub_term_setcursor (data->term, 0);
- grub_menu_init_page (nested, 0, data->term);
- print_entries (menu, data->first, data->offset, data->term);
+ print_entries (menu, data);
grub_term_refresh (data->term);
grub_menu_register_viewer (instance);
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++)
{
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 *
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);
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
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
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)
{
int cur;
cur = print_ucs4_real (unicode_str, unicode_last_position, 0, 0,
- term, grub_more);
+ term, grub_more, 0);
if (cur)
backlog = 1;
}
/* 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,
+void grub_menu_init_page (int nested, int edit, int *num_entries,
struct grub_term_output *term);
void grub_normal_init_page (struct grub_term_output *term);
char *grub_file_getline (grub_file_t file);
const grub_uint32_t * last_position,
int margin_left, int margin_right,
struct grub_term_output *term);
+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);
grub_ssize_t grub_getstringwidth (grub_uint32_t * str,
const grub_uint32_t * last_position,
struct grub_term_output *term);
/* The X position of the left border. */
#define GRUB_TERM_LEFT_BORDER_X GRUB_TERM_MARGIN
-/* The number of lines of messages at the bottom. */
-#define GRUB_TERM_MESSAGE_HEIGHT 8
-
/* The Y position of the first entry. */
#define GRUB_TERM_FIRST_ENTRY_Y (GRUB_TERM_TOP_BORDER_Y + 1)
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)
{