diff -Naur grub-new2/grub-core/gfxmenu/font.c grub-new3/grub-core/gfxmenu/font.c --- grub-new2/grub-core/gfxmenu/font.c 2013-04-08 13:00:36.000000000 +0400 +++ grub-new3/grub-core/gfxmenu/font.c 2013-04-23 15:55:02.793444845 +0400 @@ -75,6 +75,95 @@ return GRUB_ERR_NONE; } +/* Printing function for grub_font_draw_multiline. */ +static grub_err_t +print_line (grub_font_t font, grub_video_color_t color, + int start_x, int baseline_y, + struct grub_unicode_glyph *pos, struct grub_unicode_glyph *end) +{ + struct grub_font_glyph *glyph; + while (pos != end) + { + grub_err_t err; + glyph = grub_font_construct_glyph (font, pos); + if (!glyph) + return grub_errno; + err = grub_font_draw_glyph (glyph, color, start_x, baseline_y); + start_x += glyph->device_width; + grub_free (glyph); + if (err) + return err; + pos ++; + } + return GRUB_ERR_NONE; +} + +/* Get character's printing width. */ +static grub_ssize_t +font_getcharwidth (const struct grub_unicode_glyph *c, void *font) +{ + return grub_font_get_constructed_device_width (font, c); +} + +/* Analog of grub_font_draw_line with multiline output. */ +grub_err_t +grub_font_draw_multiline (const char *str, grub_font_t font, + grub_video_color_t color, + int baseline_y, int font_height, + int max_width, int max_height, + int align) +{ + int x; + grub_uint32_t *logical; + grub_ssize_t logical_len, visual_len; + struct grub_unicode_glyph *visual, *ptr, *pos; + + logical_len = grub_utf8_to_ucs4_alloc (str, &logical, 0); + if (logical_len < 0) + return grub_errno; + + visual_len = grub_bidi_logical_to_visual (logical, logical_len, &visual, + font_getcharwidth, font, max_width, 0, 0, 0, 0); + grub_free (logical); + if (visual_len < 0) + return grub_errno; + + pos = visual; + for (ptr = visual, x = 0; ptr <= visual + visual_len; ptr++) + { + if (baseline_y > max_height) + break; + if (ptr->base == '\n' || ptr == visual + visual_len) + { + if (align == 1) + x = (max_width - x) / 2; + else if (align == 2) + x = max_width - x; + else + x = 0; + + grub_err_t err; + err = print_line(font, color, x, baseline_y, pos, ptr); + if (err != GRUB_ERR_NONE) + return err; + + baseline_y += font_height; + x = 0; + while ((ptr + 1 < visual + visual_len) + && ((ptr + 1)->base == ' ' + || (ptr + 1)->base == '\t')) + ptr ++; + pos = ptr + 1; + } + else + x += grub_font_get_constructed_device_width (font, ptr); + } + + grub_free (visual); + + return GRUB_ERR_NONE; +} + /* Get the width in pixels of the specified UTF-8 string, when rendered in in the specified font (but falling back on other fonts for glyphs that are missing). */ diff -Naur grub-new2/grub-core/gfxmenu/gui_label.c grub-new3/grub-core/gfxmenu/gui_label.c --- grub-new2/grub-core/gfxmenu/gui_label.c 2013-02-25 16:54:27.000000000 +0400 +++ grub-new3/grub-core/gfxmenu/gui_label.c 2013-04-19 04:01:17.925936541 +0400 @@ -46,6 +46,7 @@ grub_video_rect_t bounds; char *id; int visible; + int multiline; char *text; char *template; grub_font_t font; @@ -91,28 +92,46 @@ return; /* Calculate the starting x coordinate. */ - int left_x; - if (self->align == align_left) - left_x = 0; - else if (self->align == align_center) - left_x = (self->bounds.width - - grub_font_get_string_width (self->font, self->text)) / 2; - else if (self->align == align_right) - left_x = (self->bounds.width - - grub_font_get_string_width (self->font, self->text)); - else - return; /* Invalid alignment. */ + int left_x = 0; + if (!self->multiline) + { + if (self->align == align_left) + left_x = 0; + else if (self->align == align_center) + left_x = (self->bounds.width + - grub_font_get_string_width (self->font, self->text)) / 2; + else if (self->align == align_right) + left_x = (self->bounds.width + - grub_font_get_string_width (self->font, self->text)); + else + return; /* Invalid alignment. */ - if (left_x < 0 || left_x > (int) self->bounds.width) - left_x = 0; + if (left_x < 0 || left_x > (int) self->bounds.width) + left_x = 0; + } grub_video_rect_t vpsave; grub_gui_set_viewport (&self->bounds, &vpsave); - grub_font_draw_string (self->text, - self->font, - grub_video_map_rgba_color (self->color), - left_x, - grub_font_get_ascent (self->font)); + if (!self->multiline) + grub_font_draw_string (self->text, + self->font, + grub_video_map_rgba_color (self->color), + left_x, + grub_font_get_ascent (self->font)); + else + { + int font_height = grub_font_get_max_char_height (self->font); + int max_width = self->bounds.width; + int max_height = self->bounds.height; + grub_font_draw_multiline (self->text, + self->font, + grub_video_map_rgba_color (self->color), + grub_font_get_ascent (self->font), + font_height, + max_width, + max_height, + self->align); + } grub_gui_restore_viewport (&vpsave); } @@ -148,9 +167,15 @@ label_get_minimal_size (void *vself, unsigned *width, unsigned *height) { grub_gui_label_t self = vself; - *width = grub_font_get_string_width (self->font, self->text); - *height = (grub_font_get_ascent (self->font) - + grub_font_get_descent (self->font)); + if (self->multiline) + { + *width = grub_font_get_max_char_width (self->font); + *height = grub_font_get_max_char_height (self->font); + } else { + *width = grub_font_get_string_width (self->font, self->text); + *height = (grub_font_get_ascent (self->font) + + grub_font_get_descent (self->font)); + } } static void @@ -218,6 +243,10 @@ { self->visible = grub_strcmp (value, "false") != 0; } + else if (grub_strcmp (name, "multiline") == 0) + { + self->multiline = grub_strcmp (value, "false") != 0; + } else if (grub_strcmp (name, "id") == 0) { grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self); @@ -257,6 +286,7 @@ return 0; label->comp.ops = &label_ops; label->visible = 1; + label->multiline = 0; label->text = grub_strdup (""); label->font = grub_font_get ("Unknown Regular 16"); label->color.red = 0; diff -Naur grub-new2/include/grub/gfxmenu_view.h grub-new3/include/grub/gfxmenu_view.h --- grub-new2/include/grub/gfxmenu_view.h 2013-02-25 16:54:27.000000000 +0400 +++ grub-new3/include/grub/gfxmenu_view.h 2013-04-19 04:01:17.926936694 +0400 @@ -66,6 +66,12 @@ grub_font_t font, grub_video_color_t color, int left_x, int baseline_y); +grub_err_t grub_font_draw_multiline (const char *str, + grub_font_t font, + grub_video_color_t color, + int baseline_y, int font_height, + int max_width, int max_height, + int align); int grub_font_get_string_width (grub_font_t font, const char *str);