diff --git a/grub2-gfxmenu-support-scrolling-menu-entry-s-text.patch b/grub2-gfxmenu-support-scrolling-menu-entry-s-text.patch new file mode 100644 index 0000000..471debc --- /dev/null +++ b/grub2-gfxmenu-support-scrolling-menu-entry-s-text.patch @@ -0,0 +1,267 @@ +From b4c5f80fbfaf912553eca1b12da6fc49de4ae37f Mon Sep 17 00:00:00 2001 +From: Michael Chang +Date: Mon, 7 Jan 2019 17:55:05 +0800 +Subject: [PATCH] gfxmenu: support scrolling menu entry's text + +If menu entry's title text is longer than its display width, the +overlong text simply get truncated. The only possible way to view the +full text is through the menu editing mode, but is a hassle switching +over the mode back and forth. Also menu editing mode could be password +protected which makes it not generally available to everyone. + +This patch implemented scrolling text support to the title of grub's +gfxmenu to make it convenient for viewing the truncated text by pressing +the ctrl+l and ctrl+r to scroll the highlighted text left and right. The +scrolled result will remain in place to help memorizing it after +changing highlight to other entry. +--- + grub-core/gfxmenu/gfxmenu.c | 3 +++ + grub-core/gfxmenu/gui_label.c | 2 ++ + grub-core/gfxmenu/gui_list.c | 38 ++++++++++++++++++++++++++++++++++ + grub-core/gfxmenu/view.c | 48 +++++++++++++++++++++++++++++++++++++++++++ + grub-core/normal/menu.c | 16 +++++++++++++++ + include/grub/gfxmenu_view.h | 4 ++++ + include/grub/menu_viewer.h | 1 + + 7 files changed, 112 insertions(+) + +diff --git a/grub-core/gfxmenu/gfxmenu.c b/grub-core/gfxmenu/gfxmenu.c +index 8a17dda2c..e834895fb 100644 +--- a/grub-core/gfxmenu/gfxmenu.c ++++ b/grub-core/gfxmenu/gfxmenu.c +@@ -108,6 +108,8 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) + view->menu = menu; + view->nested = nested; + view->first_timeout = -1; ++ if (menu->size) ++ view->menu_title_offset = grub_zalloc (sizeof (*view->menu_title_offset) * menu->size); + + grub_video_set_viewport (0, 0, mode_info.width, mode_info.height); + if (view->double_repaint) +@@ -123,6 +125,7 @@ grub_gfxmenu_try (int entry, grub_menu_t menu, int nested) + instance->fini = grub_gfxmenu_viewer_fini; + instance->print_timeout = grub_gfxmenu_print_timeout; + instance->clear_timeout = grub_gfxmenu_clear_timeout; ++ instance->scroll_chosen_entry = grub_gfxmenu_scroll_chosen_entry; + + grub_menu_register_viewer (instance); + +diff --git a/grub-core/gfxmenu/gui_label.c b/grub-core/gfxmenu/gui_label.c +index a4c817891..8b1358dd4 100644 +--- a/grub-core/gfxmenu/gui_label.c ++++ b/grub-core/gfxmenu/gui_label.c +@@ -192,6 +192,8 @@ label_set_property (void *vself, const char *name, const char *value) + "or `c' for a command-line."); + else if (grub_strcmp (value, "@KEYMAP_SHORT@") == 0) + value = _("enter: boot, `e': options, `c': cmd-line"); ++ else if (grub_strcmp (value, "@SUSE_KEYMAP_SCROLL_ENTRY@") == 0) ++ value = _("ctrl+l: scroll entry left, ctrl+r: scroll entry right"); + /* FIXME: Add more templates here if needed. */ + self->template = grub_strdup (value); + self->text = grub_xasprintf (value, self->value); +diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c +index 01477cdf2..90487aef4 100644 +--- a/grub-core/gfxmenu/gui_list.c ++++ b/grub-core/gfxmenu/gui_list.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + enum scrollbar_slice_mode { + SCROLLBAR_SLICE_WEST, +@@ -314,6 +315,33 @@ draw_scrollbar (list_impl_t self, + thumb->draw (thumb, thumbx, thumby); + } + ++static const char * ++grub_utf8_offset_code (const char *src, grub_size_t srcsize, int num) ++{ ++ int count = 0; ++ grub_uint32_t code = 0; ++ ++ while (srcsize && num) ++ { ++ if (srcsize != (grub_size_t)-1) ++ srcsize--; ++ if (!grub_utf8_process ((grub_uint8_t)*src++, &code, &count)) ++ return 0; ++ if (count != 0) ++ continue; ++ if (code == 0) ++ return 0; ++ if (code > GRUB_UNICODE_LAST_VALID) ++ return 0; ++ --num; ++ } ++ ++ if (!num) ++ return src; ++ ++ return 0; ++} ++ + /* Draw the list of items. */ + static void + draw_menu (list_impl_t self, int num_shown_items) +@@ -433,6 +461,16 @@ draw_menu (list_impl_t self, int num_shown_items) + const char *item_title = + grub_menu_get_entry (self->view->menu, menu_index)->title; + ++ { ++ int off = self->view->menu_title_offset[menu_index]; ++ const char *scrolled_title; ++ ++ scrolled_title = grub_utf8_offset_code (item_title, grub_strlen (item_title), off); ++ ++ if (scrolled_title) ++ item_title = scrolled_title; ++ } ++ + sviewport.y = item_top + top_pad; + sviewport.width = viewport_width; + grub_gui_set_viewport (&sviewport, &svpsave); +diff --git a/grub-core/gfxmenu/view.c b/grub-core/gfxmenu/view.c +index ad5e82b81..7aed7faa1 100644 +--- a/grub-core/gfxmenu/view.c ++++ b/grub-core/gfxmenu/view.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + + static void + init_terminal (grub_gfxmenu_view_t view); +@@ -142,6 +143,7 @@ grub_gfxmenu_view_destroy (grub_gfxmenu_view_t view) + grub_free (view->title_text); + grub_free (view->progress_message_text); + grub_free (view->theme_path); ++ grub_free (view->menu_title_offset); + if (view->canvas) + view->canvas->component.ops->destroy (view->canvas); + grub_free (view); +@@ -410,6 +412,52 @@ grub_gfxmenu_set_chosen_entry (int entry, void *data) + grub_gfxmenu_redraw_menu (view); + } + ++static int ++grub_utf8_get_num_code (const char *src, grub_size_t srcsize) ++{ ++ int count = 0; ++ grub_uint32_t code = 0; ++ int num = 0; ++ ++ while (srcsize) ++ { ++ if (srcsize != (grub_size_t)-1) ++ srcsize--; ++ if (!grub_utf8_process ((grub_uint8_t)*src++, &code, &count)) ++ return 0; ++ if (count != 0) ++ continue; ++ if (code == 0) ++ return num; ++ if (code > GRUB_UNICODE_LAST_VALID) ++ return 0; ++ ++num; ++ } ++ ++ return num; ++} ++ ++void ++grub_gfxmenu_scroll_chosen_entry (void *data, int diren) ++{ ++ grub_gfxmenu_view_t view = data; ++ const char *item_title; ++ int off; ++ ++ if (!view->menu->size) ++ return; ++ ++ item_title =grub_menu_get_entry (view->menu, view->selected)->title; ++ off = view->menu_title_offset[view->selected] + diren; ++ ++ if (off < 0 ++ || off > grub_utf8_get_num_code (item_title, grub_strlen(item_title))) ++ return; ++ ++ view->menu_title_offset[view->selected] = off; ++ grub_gfxmenu_redraw_menu (view); ++} ++ + static void + grub_gfxmenu_draw_terminal_box (void) + { +diff --git a/grub-core/normal/menu.c b/grub-core/normal/menu.c +index e7a83c2d6..0af20d052 100644 +--- a/grub-core/normal/menu.c ++++ b/grub-core/normal/menu.c +@@ -376,6 +376,15 @@ menu_set_chosen_entry (int entry) + cur->set_chosen_entry (entry, cur->data); + } + ++static void ++menu_scroll_chosen_entry (int diren) ++{ ++ struct grub_menu_viewer *cur; ++ for (cur = viewers; cur; cur = cur->next) ++ if (cur->scroll_chosen_entry) ++ cur->scroll_chosen_entry (cur->data, diren); ++} ++ + static void + menu_print_timeout (int timeout) + { +@@ -755,6 +764,13 @@ run_menu (grub_menu_t menu, int nested, int *auto_boot) + menu_set_chosen_entry (current_entry); + break; + ++ case GRUB_TERM_CTRL | 'l': ++ menu_scroll_chosen_entry (1); ++ break; ++ case GRUB_TERM_CTRL | 'r': ++ menu_scroll_chosen_entry (-1); ++ break; ++ + case '\n': + case '\r': + case GRUB_TERM_KEY_RIGHT: +diff --git a/include/grub/gfxmenu_view.h b/include/grub/gfxmenu_view.h +index 4203c8fb9..56c0d17ae 100644 +--- a/include/grub/gfxmenu_view.h ++++ b/include/grub/gfxmenu_view.h +@@ -61,6 +61,8 @@ void + grub_gfxmenu_print_timeout (int timeout, void *data); + void + grub_gfxmenu_set_chosen_entry (int entry, void *data); ++void ++grub_gfxmenu_scroll_chosen_entry (void *data, int diren); + + grub_err_t grub_font_draw_string (const char *str, + grub_font_t font, +@@ -119,6 +121,8 @@ struct grub_gfxmenu_view + int nested; + + int first_timeout; ++ ++ int *menu_title_offset; + }; + + #endif /* ! GRUB_GFXMENU_VIEW_HEADER */ +diff --git a/include/grub/menu_viewer.h b/include/grub/menu_viewer.h +index c6513c4e8..5f2a39dc9 100644 +--- a/include/grub/menu_viewer.h ++++ b/include/grub/menu_viewer.h +@@ -33,6 +33,7 @@ struct grub_menu_viewer + void (*set_chosen_entry) (int entry, void *data); + void (*print_timeout) (int timeout, void *data); + void (*clear_timeout) (void *data); ++ void (*scroll_chosen_entry) (void *data, int diren); + void (*fini) (void *fini); + }; + +-- +2.16.4 + diff --git a/grub2.changes b/grub2.changes index 3ffa65e..5327853 100644 --- a/grub2.changes +++ b/grub2.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Fri Jan 25 07:08:32 UTC 2019 - mchang@suse.com + +- Support long menu entry by scrolling its text left and right through + the key stroke ctrl+l and ctrl+r (FATE#325760) + * grub2-gfxmenu-support-scrolling-menu-entry-s-text.patch + ------------------------------------------------------------------- Thu Jan 24 09:26:09 UTC 2019 - mchang@suse.com diff --git a/grub2.spec b/grub2.spec index d31a276..8f6354c 100644 --- a/grub2.spec +++ b/grub2.spec @@ -315,6 +315,8 @@ Patch500: grub2-freetype-pkgconfig.patch Patch501: grub2-btrfs-help-on-snapper-rollback.patch # Improved hiDPI device support (FATE#326680) Patch510: grub2-video-limit-the-resolution-for-fixed-bimap-font.patch +# Support long menuentries (FATE#325760) +Patch511: grub2-gfxmenu-support-scrolling-menu-entry-s-text.patch Requires: gettext-runtime %if 0%{?suse_version} >= 1140 @@ -614,6 +616,7 @@ swap partition while in resuming %patch500 -p1 %patch501 -p1 %patch510 -p1 +%patch511 -p1 %build # collect evidence to debug spurious build failure on SLE15