From: Vincent Pelletier <subdino2004@yahoo.fr>
To: The development of GRUB 2 <grub-devel@gnu.org>
Subject: [PATCH] Re: [BUG] grub2 menu : freeze while initial drawing
Date: Sun, 19 Dec 2004 22:45:00 +0100 [thread overview]
Message-ID: <41C5F65C.4080809@yahoo.fr> (raw)
In-Reply-To: <200412191622.00337.okuji@enbug.org>
[-- Attachment #1.1: Type: text/plain, Size: 843 bytes --]
Yoshinori K. Okuji a écrit :
> If you can test this more, please do it.
Done :).
Menu tested to work with 2 entries. Vertical scrolling not tested (when
there are too many entries to fit on screen).
Please let me know if the coding style and Changelog are ok.
Vincent Pelletier
2004-12-19 Vincent Pelletier <subdino2004@yahoo.fr>
* normal/menu.c: corrected bug which caused menu to be displayed
outside of the screen
(#define TERM_TOP_BORDER_Y): changed TERM_HEIGHT to
TERM_INFO_HEIGHT
(draw_border): make the right border stick the right border,
replaced while loop by for loop, number of line in rectangle
consistent with number of line displayed in print_entries
added a margin below the rectangle
(print_entry): entry fits the rectangle horizontaly
(print_entries): vertical line displayed in case no arrow is
displayed
[-- Attachment #1.2: menu.c --]
[-- Type: text/x-csrc, Size: 11190 bytes --]
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2004 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <grub/normal.h>
#include <grub/term.h>
#include <grub/misc.h>
#include <grub/loader.h>
#include <grub/mm.h>
#include <grub/machine/time.h>
/* FIXME: These below are all runaround. */
#define DISP_LEFT 0x2190
#define DISP_UP 0x2191
#define DISP_RIGHT 0x2192
#define DISP_DOWN 0x2193
#define DISP_HLINE 0x2501
#define DISP_VLINE 0x2503
#define DISP_UL 0x250F
#define DISP_UR 0x2513
#define DISP_LL 0x2517
#define DISP_LR 0x251B
/* FIXME: These should be dynamically obtained from a terminal. */
#define TERM_WIDTH (80 - 1)
#define TERM_HEIGHT 25
/* The number of lines of "GRUB version..." at the top. */
#define TERM_INFO_HEIGHT 1
/* The number of columns/lines between messages/borders/etc. */
#define TERM_MARGIN 1
/* The number of columns of scroll information. */
#define TERM_SCROLL_WIDTH 1
/* The Y position of the top border. */
#define TERM_TOP_BORDER_Y (TERM_MARGIN + TERM_INFO_HEIGHT + TERM_MARGIN)
/* The X position of the left border. */
#define TERM_LEFT_BORDER_X TERM_MARGIN
/* The width of the border. */
#define TERM_BORDER_WIDTH (TERM_WIDTH \
- TERM_MARGIN * 3 \
- TERM_SCROLL_WIDTH)
/* The number of lines of messages at the bottom. */
#define TERM_MESSAGE_HEIGHT 8
/* The height of the border. */
#define TERM_BORDER_HEIGHT (TERM_HEIGHT \
- TERM_TOP_BORDER_Y \
- TERM_MESSAGE_HEIGHT)
/* The number of entries shown at a time. */
#define TERM_NUM_ENTRIES (TERM_BORDER_HEIGHT - 2)
/* The Y position of the first entry. */
#define TERM_FIRST_ENTRY_Y (TERM_TOP_BORDER_Y + 1)
/* The max column number of an entry. The last "-1" is for a
continuation marker. */
#define TERM_ENTRY_WIDTH (TERM_BORDER_WIDTH - 2 - TERM_MARGIN * 2 - 1)
/* The standard X position of the cursor. */
#define TERM_CURSOR_X (TERM_LEFT_BORDER_X \
+ TERM_BORDER_WIDTH \
- TERM_MARGIN \
- 1)
static void
draw_border (void)
{
unsigned i;
grub_setcolorstate (GRUB_TERM_COLOR_NORMAL);
grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y);
grub_putcode (DISP_UL);
for (i = 0; i < TERM_BORDER_WIDTH; i++)
grub_putcode (DISP_HLINE);
grub_putcode (DISP_UR);
for(i=0;i<(unsigned) TERM_NUM_ENTRIES;i++)
{
grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y + i + 1);
grub_putcode (DISP_VLINE);
grub_gotoxy (TERM_MARGIN + TERM_BORDER_WIDTH + 1, TERM_TOP_BORDER_Y + i + 1);
grub_putcode (DISP_VLINE);
}
grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y + TERM_NUM_ENTRIES + 1);
grub_putcode (DISP_LL);
for (i = 0; i < TERM_BORDER_WIDTH; i++)
grub_putcode (DISP_HLINE);
grub_putcode (DISP_LR);
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
grub_gotoxy (TERM_MARGIN, TERM_TOP_BORDER_Y + TERM_NUM_ENTRIES + TERM_MARGIN +1 );
}
static void
print_message (int nested, int edit)
{
if (edit)
{
grub_printf ("\n\
Minimum Emacs-like screen editing is supported. TAB lists\n\
available completions. Press C-x (\'x\' with Ctrl) to boot,\n\
C-c (\'c\' with Ctrl) for a command-line or ESC to return menu.");
}
else
{
grub_printf ("\n\
Use the %C and %C keys to select which entry is highlighted.\n",
(grub_uint32_t) DISP_UP, (grub_uint32_t) DISP_DOWN);
grub_printf ("\
Press enter to boot the selected OS, \'e\' to edit the\n\
commands before booting or \'c\' for a command-line.");
if (nested)
grub_printf ("\n\
ESC to return previous menu.");
}
}
static grub_menu_entry_t
get_entry (grub_menu_t menu, int no)
{
grub_menu_entry_t e;
for (e = menu->entry_list; e && no > 0; e = e->next, no--)
;
return e;
}
static void
print_entry (int y, int highlight, grub_menu_entry_t entry)
{
int x;
const char *title;
title = entry ? entry->title : "";
grub_setcolorstate (highlight
? GRUB_TERM_COLOR_HIGHLIGHT
: GRUB_TERM_COLOR_NORMAL);
grub_gotoxy (TERM_LEFT_BORDER_X + TERM_MARGIN, y);
grub_putchar (' ');
for (x = TERM_LEFT_BORDER_X + TERM_MARGIN + 1;
x < TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH + 1;
x++)
{
if (*title && x <= TERM_LEFT_BORDER_X + TERM_ENTRY_WIDTH + 1)
{
if (x == TERM_LEFT_BORDER_X + TERM_ENTRY_WIDTH + 1)
grub_putcode (DISP_RIGHT);
else
grub_putchar (*title++);
}
else
grub_putchar (' ');
}
grub_gotoxy (TERM_CURSOR_X, y);
grub_setcolorstate (GRUB_TERM_COLOR_STANDARD);
}
static void
print_entries (grub_menu_t menu, int first, int offset)
{
grub_menu_entry_t e;
int i;
grub_gotoxy (TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH + TERM_MARGIN,
TERM_FIRST_ENTRY_Y);
if (first)
grub_putcode (DISP_UP);
else
grub_putcode (DISP_VLINE);
e = get_entry (menu, first);
for (i = 0; i < TERM_NUM_ENTRIES; i++)
{
print_entry (TERM_FIRST_ENTRY_Y + i, offset == i, e);
if (e)
e = e->next;
}
grub_gotoxy (TERM_LEFT_BORDER_X + TERM_BORDER_WIDTH + TERM_MARGIN,
TERM_TOP_BORDER_Y + TERM_NUM_ENTRIES);
if (e)
grub_putcode (DISP_DOWN);
else
grub_putcode (DISP_VLINE);
grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset);
}
static void
init_page (int nested, int edit)
{
grub_normal_init_page ();
draw_border ();
print_message (nested, edit);
}
/* Edit a menu entry with an Emacs-like interface. */
static void
edit_menu_entry (grub_menu_entry_t entry)
{
/* Not yet implemented. */
}
static int
run_menu (grub_menu_t menu, int nested)
{
int first, offset;
unsigned long saved_time;
first = 0;
offset = menu->default_entry;
if (offset > TERM_NUM_ENTRIES - 1)
{
first = offset - (TERM_NUM_ENTRIES - 1);
offset = TERM_NUM_ENTRIES - 1;
}
/* Initialize the time. */
saved_time = grub_get_rtc ();
refresh:
grub_setcursor (0);
init_page (nested, 0);
print_entries (menu, first, offset);
grub_refresh ();
while (1)
{
int c;
if (menu->timeout > 0)
{
unsigned long current_time;
current_time = grub_get_rtc ();
if (current_time - saved_time >= GRUB_TICKS_PER_SECOND)
{
menu->timeout--;
saved_time = current_time;
}
grub_gotoxy (0, TERM_HEIGHT - 3);
/* NOTE: Do not remove the trailing space characters.
They are required to clear the line. */
grub_printf ("\
The highlighted entry will be booted automatically in %d seconds. ",
menu->timeout);
grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset);
grub_refresh ();
}
if (menu->timeout == 0)
return menu->default_entry;
if (grub_checkkey () >= 0 || menu->timeout < 0)
{
c = GRUB_TERM_ASCII_CHAR (grub_getkey ());
if (menu->timeout >= 0)
{
grub_gotoxy (0, TERM_HEIGHT - 3);
grub_printf ("\
");
menu->timeout = -1;
menu->fallback_entry = -1;
grub_gotoxy (TERM_CURSOR_X, TERM_FIRST_ENTRY_Y + offset);
}
switch (c)
{
case 16:
case '^':
if (offset > 0)
{
print_entry (TERM_FIRST_ENTRY_Y + offset, 0,
get_entry (menu, first + offset));
offset--;
print_entry (TERM_FIRST_ENTRY_Y + offset, 1,
get_entry (menu, first + offset));
}
else if (first > 0)
{
first--;
print_entries (menu, first, offset);
}
break;
case 14:
case 'v':
if (menu->size > first + offset + 1)
{
if (offset < TERM_NUM_ENTRIES - 1)
{
print_entry (TERM_FIRST_ENTRY_Y + offset, 0,
get_entry (menu, first + offset));
offset++;
print_entry (TERM_FIRST_ENTRY_Y + offset, 1,
get_entry (menu, first + offset));
}
else
{
first++;
print_entries (menu, first, offset);
}
}
break;
case '\n':
case '\r':
case 6:
grub_setcursor (1);
return first + offset;
case '\e':
if (nested)
{
grub_setcursor (1);
return -1;
}
break;
case 'c':
grub_setcursor (1);
grub_cmdline_run (1);
goto refresh;
case 'e':
edit_menu_entry (get_entry (menu, first + offset));
goto refresh;
default:
break;
}
grub_refresh ();
}
}
/* Never reach here. */
return -1;
}
/* Run a menu entry. */
static void
run_menu_entry (grub_menu_entry_t entry)
{
grub_command_list_t cl;
for (cl = entry->command_list; cl != 0; cl = cl->next)
{
grub_command_t c;
if (cl->command[0] == '\0')
/* Ignore an empty command line. */
continue;
c = grub_command_find (cl->command);
if (! c)
break;
if (! (c->flags & GRUB_COMMAND_FLAG_CMDLINE))
{
grub_error (GRUB_ERR_INVALID_COMMAND,
"invalid command `%s'",
cl->command);
break;
}
if (! (c->flags & GRUB_COMMAND_FLAG_NO_ECHO))
grub_printf ("%s\n", cl->command);
if (grub_command_execute (cl->command) != 0)
break;
}
if (grub_errno == GRUB_ERR_NONE && grub_loader_is_loaded ())
/* Implicit execution of boot, only if something is loaded. */
grub_command_execute ("boot");
}
void
grub_menu_run (grub_menu_t menu, int nested)
{
while (1)
{
int boot_entry;
grub_menu_entry_t e;
boot_entry = run_menu (menu, nested);
if (boot_entry < 0)
break;
grub_cls ();
grub_setcursor (1);
e = get_entry (menu, boot_entry);
grub_printf (" Booting \'%s\'\n\n", e->title);
run_menu_entry (e);
/* Deal with a fallback entry. */
/* FIXME: Multiple fallback entries like GRUB Legacy. */
if (menu->fallback_entry >= 0)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
e = get_entry (menu, menu->fallback_entry);
menu->fallback_entry = -1;
grub_printf ("\n Falling back to \'%s\'\n\n", e->title);
run_menu_entry (e);
}
if (grub_errno != GRUB_ERR_NONE)
{
grub_print_error ();
grub_errno = GRUB_ERR_NONE;
/* Wait until the user pushes any key so that the user
can see what happened. */
grub_printf ("\nPress any key to continue...");
(void) grub_getkey ();
}
}
}
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 256 bytes --]
next prev parent reply other threads:[~2004-12-19 21:58 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2004-12-14 10:27 [BUG] grub2 menu : freeze while initial drawing Vincent Pelletier
2004-12-19 15:22 ` Yoshinori K. Okuji
2004-12-19 21:45 ` Vincent Pelletier [this message]
2004-12-19 21:57 ` [PATCH] " Vincent Pelletier
2004-12-22 13:45 ` Yoshinori K. Okuji
2004-12-22 13:57 ` Vincent Pelletier
2004-12-22 16:03 ` Yoshinori K. Okuji
2005-01-08 15:25 ` [PATCH v2] " Vincent Pelletier
2005-01-20 14:36 ` Marco Gerards
2005-01-20 17:32 ` Yoshinori K. Okuji
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=41C5F65C.4080809@yahoo.fr \
--to=subdino2004@yahoo.fr \
--cc=grub-devel@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.