diff -Naur grub-2.01/docs/grub.texi grub-new/docs/grub.texi --- grub-2.01/docs/grub.texi 2013-06-25 15:21:25.000000000 +0400 +++ grub-new/docs/grub.texi 2013-06-25 19:50:51.000000000 +0400 @@ -1904,6 +1904,11 @@ @item desktop-image @tab Specifies the image to use as the background. It will be scaled to fit the screen size. @item desktop-color @tab Specifies the color for the background if *desktop-image* is not specified. @item terminal-box @tab Specifies the file name pattern for the styled box slices used for the command line terminal window. For example, ``terminal-box: terminal_*.png'' will use the images ``terminal_c.png`` as the center area, ``terminal_n.png`` as the north (top) edge, ``terminal_nw.png`` as the northwest (upper left) corner, and so on. If the image for any slice is not found, it will simply be left empty. address@hidden terminal-border @tab Specifies the border width of the terminal window. address@hidden terminal-left @tab Specifies the left coordinate of the terminal window. address@hidden terminal-top @tab Specifies the top coordinate of the terminal window. address@hidden terminal-width @tab Specifies the width of the terminal window. address@hidden terminal-height @tab Specifies the height of the terminal window. @end multitable diff -Naur grub-2.01/grub-core/gfxmenu/theme_loader.c grub-new/grub-core/gfxmenu/theme_loader.c --- grub-2.01/grub-core/gfxmenu/theme_loader.c 2013-06-25 15:21:25.000000000 +0400 +++ grub-new/grub-core/gfxmenu/theme_loader.c 2013-06-25 19:50:51.000000000 +0400 @@ -32,6 +32,9 @@ #include #include +static grub_err_t +parse_proportional_spec (char *value, signed *abs, grub_fixed_signed_t *prop); + /* Construct a new box widget using ABSPATTERN to find the pixmap files for it, storing the new box instance at *BOXPTR. PATTERN should be of the form: "(hd0,0)/somewhere/style*.png". @@ -179,6 +182,56 @@ if (err != GRUB_ERR_NONE) return err; } + else if (! grub_strcmp ("terminal-border", name)) + { + view->terminal_border = grub_strtoul (value, 0, 10); + if (grub_errno) + return grub_errno; + } + else if (! grub_strcmp ("terminal-left", name)) + { + grub_err_t err; + grub_fixed_signed_t frac; + signed pixels; + err = parse_proportional_spec (value, &pixels, &frac); + if (err != GRUB_ERR_NONE) + return err; + view->x = pixels; + view->xfrac = frac; + } + else if (! grub_strcmp ("terminal-top", name)) + { + grub_err_t err; + grub_fixed_signed_t frac; + signed pixels; + err = parse_proportional_spec (value, &pixels, &frac); + if (err != GRUB_ERR_NONE) + return err; + view->y = pixels; + view->yfrac = frac; + } + else if (! grub_strcmp ("terminal-width", name)) + { + grub_err_t err; + grub_fixed_signed_t frac; + signed pixels; + err = parse_proportional_spec (value, &pixels, &frac); + if (err != GRUB_ERR_NONE) + return err; + view->w = pixels; + view->wfrac = frac; + } + else if (! grub_strcmp ("terminal-height", name)) + { + grub_err_t err; + grub_fixed_signed_t frac; + signed pixels; + err = parse_proportional_spec (value, &pixels, &frac); + if (err != GRUB_ERR_NONE) + return err; + view->h = pixels; + view->hfrac = frac; + } else if (! grub_strcmp ("title-text", name)) { grub_free (view->title_text); diff -Naur grub-2.01/grub-core/gfxmenu/view.c grub-new/grub-core/gfxmenu/view.c --- grub-2.01/grub-core/gfxmenu/view.c 2013-04-26 23:39:50.000000000 +0400 +++ grub-new/grub-core/gfxmenu/view.c 2013-06-27 16:33:22.759010088 +0400 @@ -40,7 +40,6 @@ static void init_terminal (grub_gfxmenu_view_t view); -static grub_video_rect_t term_rect; static grub_gfxmenu_view_t term_view; /* Create a new view object, loading the theme specified by THEME_PATH and @@ -71,6 +70,19 @@ view->screen.width = width; view->screen.height = height; + view->terminal_border = 3; + + /* view->terminal_rect will be defined during execution of init_terminal */ + + view->x = 0; + view->xfrac = 0; + view->y = 0; + view->yfrac = 0; + view->w = 0; + view->wfrac = 0; + view->h = 0; + view->hfrac = 0; + default_font = grub_font_get ("Unknown Regular 16"); default_fg_color = grub_video_rgba_color_rgb (0, 0, 0); default_bg_color = grub_video_rgba_color_rgb (255, 255, 255); @@ -302,7 +314,7 @@ grub_gfxmenu_view_redraw (grub_gfxmenu_view_t view, const grub_video_rect_t *region) { - if (grub_video_have_common_points (&term_rect, region)) + if (grub_video_have_common_points (&view->terminal_rect, region)) grub_gfxterm_schedule_repaint (); grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY); @@ -386,25 +398,34 @@ term_box = term_view->terminal_box; if (!term_box) return; - - term_box->set_content_size (term_box, term_rect.width, - term_rect.height); + + term_box->set_content_size (term_box, term_view->terminal_rect.width, + term_view->terminal_rect.height); term_box->draw (term_box, - term_rect.x - term_box->get_left_pad (term_box), - term_rect.y - term_box->get_top_pad (term_box)); + term_view->terminal_rect.x - term_box->get_left_pad (term_box), + term_view->terminal_rect.y - term_box->get_top_pad (term_box)); } static void -init_terminal (grub_gfxmenu_view_t view) +get_min_terminal (grub_font_t terminal_font, int border_width, + unsigned int *min_terminal_width, unsigned int *min_terminal_height) { - const int border_width = 3; + struct grub_font_glyph *glyph; + glyph = grub_font_get_glyph (terminal_font, 'M'); + *min_terminal_width = (glyph? glyph->device_width : 8) * 80 + 2 * border_width; + *min_terminal_height = grub_font_get_max_char_height (terminal_font) * 24 + + 2 * border_width; +} +static void +init_terminal (grub_gfxmenu_view_t view) +{ + int border_width = view->terminal_border; + grub_video_rect_t screen_rect = view->screen; grub_font_t terminal_font; - - unsigned int line_width; - - struct grub_font_glyph *glyph; + unsigned int min_terminal_width; + unsigned int min_terminal_height; terminal_font = grub_font_get (view->terminal_font_name); if (!terminal_font) @@ -413,36 +434,78 @@ return; } - glyph = grub_font_get_glyph (terminal_font, 'M'); - - line_width = ((glyph ? glyph->device_width : 8) * 80 + 2 * border_width); - - if (view->screen.width <= line_width) - /* The screen is too small. Use all space, except a small border - to show the user, it is a window and not full screen: */ - term_rect.width = view->screen.width - 6 * border_width; - else - { - /* The screen is big enough. Try 70% of the screen width: */ - term_rect.width = view->screen.width * 7 / 10; - /* Make sure, that we use at least the line_width: */ - if ( term_rect.width < line_width ) - term_rect.width = line_width; - } - - term_rect.height = view->screen.height * 7 / 10; - - term_rect.x = view->screen.x + (view->screen.width - term_rect.width) / 2; - term_rect.y = view->screen.y + (view->screen.height - term_rect.height) / 2; + get_min_terminal (terminal_font, border_width, &min_terminal_width, &min_terminal_height); + /* Check that border_width isn't too big */ + if ((border_width > 3) && ((min_terminal_width >= screen_rect.width) + || (min_terminal_height >= screen_rect.height))) + { + border_width = 3; + get_min_terminal (terminal_font, border_width, &min_terminal_width, &min_terminal_height); + } + + signed x, y, w, h; + x = grub_fixed_sfs_multiply (screen_rect.width, view->xfrac) + view->x; + y = grub_fixed_sfs_multiply (screen_rect.height, view->yfrac) + view->y; + w = grub_fixed_sfs_multiply (screen_rect.width, view->wfrac) + view->w; + h = grub_fixed_sfs_multiply (screen_rect.height, view->hfrac) + view->h; + + /* Sanity checks. */ + if (w <= 0) + w = (signed) screen_rect.width * 7 / 10; + if (h <= 0) + h = (signed) screen_rect.height * 7 / 10; + + if (w > (signed) screen_rect.width) + w = (signed) screen_rect.width; + if (h > (signed) screen_rect.height) + h = (signed) screen_rect.height; + + if ((screen_rect.width <= min_terminal_width) + || (screen_rect.height <= min_terminal_height)) + { + /* The terminal window is too small. Use all space, except a small border + to show the user, that it is a window. Then center the window. */ + w = (signed) screen_rect.width - 6 * border_width; + h = (signed) screen_rect.height - 6 * border_width; + x = ((signed) screen_rect.width - w) / 2; + y = ((signed) screen_rect.height - h) / 2; + } + else if ((w < (signed) min_terminal_width) + || (h < (signed) min_terminal_height)) + { + /* The terminal window is big enough. The desired width is satisfying. + Make sure, that screen dimensions aren't less than minimal values. + Then center the window. */ + w = (signed) min_terminal_width; + h = (signed) min_terminal_height; + x = ((signed) screen_rect.width - w) / 2; + y = ((signed) screen_rect.height - h) / 2; + } + + /* At this point w and h are satisfying. */ + if (x + w > (signed) screen_rect.width) + x = (signed) screen_rect.width - w; + if (y + h > (signed) screen_rect.height) + y = (signed) screen_rect.height - h; + + if (x < (signed) screen_rect.x) + x = (signed) screen_rect.x; + if (y < (signed) screen_rect.y) + y = (signed) screen_rect.y; + + view->terminal_rect.x = x; + view->terminal_rect.width = w; + view->terminal_rect.y = y; + view->terminal_rect.height = h; + view->terminal_border = border_width; term_view = view; /* Note: currently there is no API for changing the gfxterm font on the fly, so whatever font the initially loaded theme specifies will be permanent. */ - grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, term_rect.x, - term_rect.y, - term_rect.width, term_rect.height, + grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY, + x, y, w, h, view->double_repaint, terminal_font, border_width); grub_gfxterm_decorator_hook = grub_gfxmenu_draw_terminal_box; diff -Naur grub-2.01/include/grub/gfxmenu_view.h grub-new/include/grub/gfxmenu_view.h --- grub-2.01/include/grub/gfxmenu_view.h 2013-02-25 16:54:27.000000000 +0400 +++ grub-new/include/grub/gfxmenu_view.h 2013-06-25 19:50:51.000000000 +0400 @@ -83,7 +83,18 @@ struct grub_gfxmenu_view { grub_video_rect_t screen; + grub_video_rect_t terminal_rect; + signed x; + grub_fixed_signed_t xfrac; + signed y; + grub_fixed_signed_t yfrac; + signed w; + grub_fixed_signed_t wfrac; + signed h; + grub_fixed_signed_t hfrac; + + int terminal_border; grub_font_t title_font; grub_font_t message_font; char *terminal_font_name;