From f588f1c8b6a890bf04207be34669120ebc9d3e49 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Tue, 16 Mar 2010 14:13:32 +0100 Subject: [PATCH] Add simple line wrapping --- commands/help.c | 2 +- include/grub/normal.h | 8 ++- normal/charset.c | 144 ++++++++++++++++++++++++++++-------------- normal/main.c | 2 +- normal/menu_text.c | 35 +++------- 5 files changed, 113 insertions(+), 78 deletions(-) diff --git a/commands/help.c b/commands/help.c index d56ad49a1..b9e1a9145 100644 --- a/commands/help.c +++ b/commands/help.c @@ -77,7 +77,7 @@ grub_cmd_help (grub_extcmd_t ext __attribute__ ((unused)), int argc, } grub_print_ucs4 (unicode_command_help, - unicode_last_screen_position, term); + unicode_last_screen_position, 0, 0, term); if (!(cnt % 2)) grub_print_spaces (term, grub_term_width (term) / 2 - stringwidth); diff --git a/include/grub/normal.h b/include/grub/normal.h index b53c6c121..6ec14d31a 100644 --- a/include/grub/normal.h +++ b/include/grub/normal.h @@ -77,9 +77,11 @@ void grub_parse_color_name_pair (grub_uint8_t *ret, const char *name); /* Defined in `menu_text.c'. */ void grub_wait_after_message (void); -void grub_print_ucs4 (const grub_uint32_t * str, - const grub_uint32_t * last_position, - struct grub_term_output *term); +void +grub_print_ucs4 (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); diff --git a/normal/charset.c b/normal/charset.c index 490a70383..383f2c458 100644 --- a/normal/charset.c +++ b/normal/charset.c @@ -544,11 +544,11 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, } static grub_ssize_t -line_wrap (struct grub_unicode_glyph *visual_out, - struct grub_unicode_glyph *visual, - grub_size_t visual_len, unsigned *levels, - grub_ssize_t (*getcharwidth) (const struct grub_unicode_glyph *visual), - grub_size_t maxwidth, grub_size_t startwidth) +bidi_line_wrap (struct grub_unicode_glyph *visual_out, + struct grub_unicode_glyph *visual, + grub_size_t visual_len, unsigned *levels, + grub_ssize_t (*getcharwidth) (const struct grub_unicode_glyph *visual), + grub_size_t maxwidth, grub_size_t startwidth) { struct grub_unicode_glyph *outptr = visual_out; unsigned line_start = 0; @@ -582,38 +582,35 @@ line_wrap (struct grub_unicode_glyph *visual_out, if (((grub_ssize_t) maxwidth > 0 && line_width > (grub_ssize_t) maxwidth) || k == visual_len) { - if (levels) + unsigned min_odd_level = 0xffffffff; + unsigned max_level = 0; + unsigned j; + + unsigned i; + for (i = line_start; i < k; i++) { - unsigned min_odd_level = 0xffffffff; - unsigned max_level = 0; - unsigned j; - - unsigned i; - for (i = line_start; i < k; i++) - { - if (levels[i] > max_level) - max_level = levels[i]; - if (levels[i] < min_odd_level && (levels[i] & 1)) - min_odd_level = levels[i]; - } - - /* FIXME: can be optimized. */ - for (j = max_level; j >= min_odd_level; j--) - { - unsigned in = 0; - for (i = line_start; i < k; i++) - { - if (i != line_start && levels[i] >= j && levels[i-1] < j) - in = i; - if (levels[i] >= j && (i + 1 == k || levels[i+1] < j)) - revert (in, i); - } - } - - for (i = line_start; i < k; i++) - if (is_mirrored (visual[i].base) && levels[i]) - visual[i].attributes |= GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR; + if (levels[i] > max_level) + max_level = levels[i]; + if (levels[i] < min_odd_level && (levels[i] & 1)) + min_odd_level = levels[i]; } + + /* FIXME: can be optimized. */ + for (j = max_level; j >= min_odd_level; j--) + { + unsigned in = 0; + for (i = line_start; i < k; i++) + { + if (i != line_start && levels[i] >= j && levels[i-1] < j) + in = i; + if (levels[i] >= j && (i + 1 == k || levels[i+1] < j)) + revert (in, i); + } + } + + for (i = line_start; i < k; i++) + if (is_mirrored (visual[i].base) && levels[i]) + visual[i].attributes |= GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR; outptr += k - line_start; if (k != visual_len) @@ -927,8 +924,8 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, { grub_ssize_t ret; - ret = line_wrap (visual_out, visual, visual_len, levels, - getcharwidth, maxwidth, startwidth); + ret = bidi_line_wrap (visual_out, visual, visual_len, levels, + getcharwidth, maxwidth, startwidth); grub_free (levels); grub_free (visual); return ret; @@ -1056,7 +1053,11 @@ grub_putcode (grub_uint32_t code, struct grub_term_output *term) .combining = 0 }; - if (grub_unicode_get_comb_type (code) != GRUB_UNICODE_COMB_NONE) + if (grub_unicode_get_comb_type (code) != GRUB_UNICODE_COMB_NONE + && ((term->flags & GRUB_TERM_CODE_TYPE_MASK) + != GRUB_TERM_CODE_TYPE_UTF8_LOGICAL + && (term->flags & GRUB_TERM_CODE_TYPE_MASK) + != GRUB_TERM_CODE_TYPE_UTF8_VISUAL)) return; if (code == '\t' && term->getxy) @@ -1095,12 +1096,33 @@ grub_putcode (grub_uint32_t code, struct grub_term_output *term) grub_putcode ('\r', term); } - void grub_print_ucs4 (const grub_uint32_t * str, const grub_uint32_t * last_position, + int margin_left, int margin_right, struct grub_term_output *term) { + grub_size_t line_len; + grub_ssize_t startwidth; + + { + struct grub_unicode_glyph space_glyph = { + .base = ' ', + .variant = 0, + .attributes = 0, + .ncomb = 0, + .combining = 0 + }; + line_len = grub_term_width (term) + - grub_term_getcharwidth (term, &space_glyph) + * (margin_left + margin_right) - 1; + } + + if (((term->getxy () >> 8) & 0xff) < margin_left) + grub_print_spaces (term, margin_left - ((term->getxy () >> 8) & 0xff)); + + startwidth = ((term->getxy () >> 8) & 0xff) - margin_left; + if ((term->flags & GRUB_TERM_CODE_TYPE_MASK) == GRUB_TERM_CODE_TYPE_UCS4_VISUAL || (term->flags & GRUB_TERM_CODE_TYPE_MASK) @@ -1109,12 +1131,9 @@ grub_print_ucs4 (const grub_uint32_t * str, grub_ssize_t visual_len; struct grub_unicode_glyph *visual; struct grub_unicode_glyph *visual_ptr; - visual_len = grub_bidi_logical_to_visual (str, - last_position - str, - &visual, - term->getcharwidth, - grub_term_width (term), - (term->getxy () >> 8) & 0xff); + visual_len = grub_bidi_logical_to_visual (str, last_position - str, + &visual, term->getcharwidth, + line_len, startwidth); if (visual_len < 0) { grub_print_error (); @@ -1128,6 +1147,8 @@ grub_print_ucs4 (const grub_uint32_t * str, .ncomb = 0, .combining = 0 }; + if (visual_ptr->base == '\n') + grub_print_spaces (term, margin_right); if ((term->flags & GRUB_TERM_CODE_TYPE_MASK) == GRUB_TERM_CODE_TYPE_UTF8_VISUAL) { @@ -1155,6 +1176,7 @@ grub_print_ucs4 (const grub_uint32_t * str, { c.base = '\r'; term->putchar (&c); + grub_print_spaces (term, margin_left); } grub_free (visual_ptr->combining); } @@ -1164,8 +1186,36 @@ grub_print_ucs4 (const grub_uint32_t * str, { const grub_uint32_t *ptr; + grub_ssize_t line_width = startwidth; + grub_ssize_t maxwidth = line_len; + for (ptr = str; ptr < last_position; ptr++) - grub_putcode (*ptr, term); + { + struct grub_unicode_glyph c = { + .variant = 0, + .attributes = 0, + .ncomb = 0, + .combining = 0 + }; + grub_ssize_t last_width = 0; + if (grub_unicode_get_comb_type (*ptr) == GRUB_UNICODE_COMB_NONE) + { + c.base = *ptr; + line_width += last_width = term->getcharwidth (&c); + } + + if (line_width > maxwidth || *ptr == '\n') + { + grub_print_spaces (term, margin_right); + grub_putcode ('\n', term); + grub_putcode ('\r', term); + line_width = last_width; + grub_print_spaces (term, margin_left); + } + + if (*ptr != '\n') + grub_putcode (*ptr, term); + } } } @@ -1179,7 +1229,7 @@ grub_xputs_normal (const char *str) grub_uint32_t *unicode_str, *unicode_last_position; grub_utf8_to_ucs4_alloc (str, &unicode_str, &unicode_last_position); - grub_print_ucs4 (unicode_str, unicode_last_position, term); + grub_print_ucs4 (unicode_str, unicode_last_position, 0, 0, term); grub_free (unicode_str); } } diff --git a/normal/main.c b/normal/main.c index 334be00e9..ab28609cd 100644 --- a/normal/main.c +++ b/normal/main.c @@ -429,7 +429,7 @@ grub_normal_init_page (struct grub_term_output *term) posx = (grub_term_width (term) - posx) / 2; grub_term_gotoxy (term, posx, 1); - grub_print_ucs4 (unicode_msg, last_position, term); + grub_print_ucs4 (unicode_msg, last_position, 0, 0, term); grub_printf("\n\n"); grub_free (unicode_msg); } diff --git a/normal/menu_text.c b/normal/menu_text.c index 5b75f29fd..61ddd2490 100644 --- a/normal/menu_text.c +++ b/normal/menu_text.c @@ -38,14 +38,6 @@ struct menu_viewer_data struct grub_term_output *term; }; -static void -print_spaces (int number_spaces, struct grub_term_output *term) -{ - int i; - for (i = 0; i < number_spaces; i++) - grub_putcode (' ', term); -} - grub_ssize_t grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position, struct grub_term_output *term) @@ -65,26 +57,11 @@ void grub_print_message_indented (const char *msg, int margin_left, int margin_right, struct grub_term_output *term) { - int line_len; - grub_uint32_t *unicode_msg; grub_uint32_t *last_position; int msg_len; - { - struct grub_unicode_glyph pseudo_glyph = { - .base = ' ', - .variant = 0, - .attributes = 0, - .ncomb = 0, - .combining = 0 - }; - line_len = grub_term_width (term) - - grub_term_getcharwidth (term, &pseudo_glyph) - * (margin_left + margin_right); - } - msg_len = grub_utf8_to_ucs4_alloc (msg, &unicode_msg, &last_position); if (msg_len < 0) @@ -92,6 +69,11 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right, return; } + grub_print_ucs4 (unicode_msg, last_position, margin_left, margin_right, term); + +#if 0 + int line_len; + grub_uint32_t *current_position = unicode_msg; grub_uint32_t *next_new_line = unicode_msg; @@ -126,6 +108,7 @@ grub_print_message_indented (const char *msg, int margin_left, int margin_right, current_position = next_new_line; first_loop = 0; } +#endif grub_free (unicode_msg); } @@ -280,7 +263,7 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, } grub_print_ucs4 (unicode_title, - unicode_title + last_printed, term); + unicode_title + last_printed, 0, 0, term); if (last_printed != len) { @@ -397,7 +380,7 @@ menu_text_print_timeout (int timeout, void *dataptr) grub_print_message_indented (msg_translated, 3, 0, data->term); posx = grub_term_getxy (data->term) >> 8; - print_spaces (grub_term_width (data->term) - posx - 1, data->term); + grub_print_spaces (data->term, grub_term_width (data->term) - posx - 1); grub_term_gotoxy (data->term, grub_term_cursor_x (data->term), @@ -455,7 +438,7 @@ menu_text_clear_timeout (void *dataptr) struct menu_viewer_data *data = dataptr; grub_term_gotoxy (data->term, 0, grub_term_height (data->term) - 3); - print_spaces (grub_term_width (data->term) - 1, data->term); + grub_print_spaces (data->term, grub_term_width (data->term) - 1); grub_term_gotoxy (data->term, grub_term_cursor_x (data->term), GRUB_TERM_FIRST_ENTRY_Y + data->offset); grub_term_refresh (data->term);