Replace libcurses with our own vt100 handling for the ease of testing

and decreasing prerequisites.
This commit is contained in:
Vladimir 'phcoder' Serbinenko 2013-04-27 00:02:23 +02:00
parent b24ca7cd89
commit db99fbe83f
9 changed files with 152 additions and 270 deletions

View file

@ -1,3 +1,8 @@
2013-04-26 Vladimir Serbinenko <phcoder@gmail.com>
Replace libcurses with our own vt100 handling for the ease of testing
and decreasing prerequisites.
2013-04-26 Vladimir Serbinenko <phcoder@gmail.com>
* grub-core/Makefile.core.def: Fix grub-emu and grub-emu-lite sources.

View file

@ -23,11 +23,11 @@ On GNU/Linux, you also need:
* libdevmapper 1.02.34 or later (recommended)
To build grub-emu, you need:
For optional grub-emu features, you need:
* ncurses
* libusb (recommended)
* SDL (recommended)
* libpciaccess (optional)
* libusb (optional)
To build GRUB's graphical terminal (gfxterm), you need:

View file

@ -842,22 +842,6 @@ AC_ARG_ENABLE([grub-emu-pci],
[build and install the `grub-emu' debugging utility with PCI support (potentially dangerous) (default=no)])])
if test "$platform" = emu; then
missing_ncurses=
[# Check for curses libraries.]
AC_CHECK_LIB([ncurses], [wgetch], [LIBCURSES="-lncurses"],
[AC_CHECK_LIB([curses], [wgetch], [LIBCURSES="-lcurses"],
[missing_ncurses=[true]])])
AC_SUBST([LIBCURSES])
[if [ x"$missing_ncurses" = x ]; then ]
[# Check for headers.]
AC_CHECK_HEADERS([ncurses/curses.h], [],
[AC_CHECK_HEADERS([ncurses.h], [],
[AC_CHECK_HEADERS([curses.h], [],
[missing_ncurses=[true]])])])
[fi]
if test x"$missing_ncurses" = xtrue ; then
AC_MSG_ERROR([grub-emu can't be compiled without ncurses])
fi
if test x"$enable_grub_emu_usb" != xyes ; then
grub_emu_usb_excuse="not enabled"

View file

@ -4586,26 +4586,35 @@ On normalized ZFS subvolumes filenames out of normalisation are inaccessible.
@chapter Output terminal
Firmware output console ``console'' on ARC and IEEE1275 are limited to ASCII.
BIOS firmware console and VGA text are limited to ASCII and some pseudographics.
None of above mentioned is appropriate for displaying international and any
unsupported character is replaced with question mark except pseudographics
which we attempt to approximate with ASCII. EFI console on the other hand
nominally supports UTF-16 but actual language coverage depends on firmware and
may be very limited. The encoding used on serial can be chosen with
@command{terminfo} as either ASCII, UTF-8 or ``visual UTF-8''. Last one is
against the specification but results in correct rendering of right-to-left
on some readers which don't have own bidi implementation. When using gfxterm
or gfxmenu GRUB itself is responsible for rendering the text. In this case
GRUB is limited by loaded fonts. If fonts contain all required characters
then bidirectional text, cursive variants and combining marks other than
enclosing, half (e.g. left half tilde or combining overline) and double ones.
Ligatures aren't supported though. This should cover European, Middle Eastern
(if you don't mind lack of lam-alif ligature in Arabic) and East Asian scripts.
Notable unsupported scripts are Brahmic family and derived as well as
Mongolian, Tifinagh, Korean Jamo (precomposed characters have no problem)
and tonal writing (2e5-2e9). GRUB also ignores deprecated (as specified
in Unicode) characters (e.g. tags). GRUB also doesn't handle so called
``annotation characters'' If you can complete either of
which we attempt to approximate with ASCII.
EFI console on the other hand nominally supports UTF-16 but actual language
coverage depends on firmware and may be very limited.
The encoding used on serial can be chosen with @command{terminfo} as
either ASCII, UTF-8 or ``visual UTF-8''. Last one is against the specification
but results in correct rendering of right-to-left on some readers which don't
have own bidi implementation.
On emu GRUB checks if charset is UTF-8 and uses it if so and uses ASCII
otherwise.
When using gfxterm or gfxmenu GRUB itself is responsible for rendering the
text. In this case GRUB is limited by loaded fonts. If fonts contain all
required characters then bidirectional text, cursive variants and combining
marks other than enclosing, half (e.g. left half tilde or combining overline)
and double ones. Ligatures aren't supported though. This should cover European,
Middle Eastern (if you don't mind lack of lam-alif ligature in Arabic) and
East Asian scripts. Notable unsupported scripts are Brahmic family and
derived as well as Mongolian, Tifinagh, Korean Jamo (precomposed characters
have no problem) and tonal writing (2e5-2e9). GRUB also ignores deprecated
(as specified in Unicode) characters (e.g. tags). GRUB also doesn't handle so
called ``annotation characters'' If you can complete either of
two lists or, better, propose a patch to improve rendering, please contact
developer team.
@ -4826,7 +4835,7 @@ and mips-qemu_mips can use only memory up to first hole.
@multitable @columnfractions .20 .20 .20 .20 .20
@item @tab MIPS qemu @tab emu
@item video @tab no @tab yes
@item console charset @tab CP437 @tab ASCII
@item console charset @tab CP437 @tab Unicode (*)
@item network @tab no @tab yes
@item ATA/AHCI @tab yes @tab no
@item AT keyboard @tab yes @tab no

View file

@ -57,7 +57,7 @@ GROUPS["videomodules"] = GRUB_PLATFORMS[:];
for i in GROUPS["videoinkernel"]: GROUPS["videomodules"].remove(i)
# Similar for terminfo
GROUPS["terminfoinkernel"] = ["mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"];
GROUPS["terminfoinkernel"] = [ "emu", "mips_loongson", "mips_arc", "mips_qemu_mips" ] + GROUPS["ieee1275"];
GROUPS["terminfomodule"] = GRUB_PLATFORMS[:];
for i in GROUPS["terminfoinkernel"]: GROUPS["terminfomodule"].remove(i)

View file

@ -216,6 +216,7 @@ if COND_emu
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/datetime.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/misc.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/emu/export.h
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/extcmd.h
if COND_GRUB_EMU_SDL
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/sdl.h
endif

View file

@ -250,7 +250,7 @@ program = {
ldadd = 'kernel.exec$(EXEEXT)';
ldadd = '$(MODULE_FILES)';
ldadd = 'gnulib/libgnu.a $(LIBCURSES) $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
ldadd = 'gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu;
};
@ -262,7 +262,7 @@ program = {
emu_nodist = symlist.c;
ldadd = 'kernel.exec$(EXEEXT)';
ldadd = 'gnulib/libgnu.a $(LIBCURSES) $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
ldadd = 'gnulib/libgnu.a $(LIBINTL) $(LIBUTIL) $(LIBSDL) $(LIBUSB) $(LIBPCIACCESS) $(LIBDEVMAPPER) $(LIBZFS) $(LIBNVPAIR) $(LIBGEOM)';
enable = emu;
};

View file

@ -1,7 +1,7 @@
/* console.c -- Ncurses console for GRUB. */
/* console.c -- console for GRUB. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2003,2005,2007,2008 Free Software Foundation, Inc.
* Copyright (C) 2013 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -20,274 +20,159 @@
#include <config.h>
#include <config-util.h>
/* For compatibility. */
#ifndef A_NORMAL
# define A_NORMAL 0
#endif /* ! A_NORMAL */
#ifndef A_STANDOUT
# define A_STANDOUT 0
#endif /* ! A_STANDOUT */
#include <grub/emu/console.h>
#include <grub/term.h>
#include <grub/types.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/time.h>
#include <grub/terminfo.h>
#include <grub/dl.h>
#if defined(HAVE_NCURSES_CURSES_H)
# include <ncurses/curses.h>
#elif defined(HAVE_NCURSES_H)
# include <ncurses.h>
#elif defined(HAVE_CURSES_H)
# include <curses.h>
#else
#error What the hell?
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <langinfo.h>
static int grub_console_attr = A_NORMAL;
#include <grub/emu/console.h>
grub_uint8_t grub_console_cur_color = 7;
static const grub_uint8_t grub_console_standard_color = 0x7;
#define NUM_COLORS 8
static grub_uint8_t color_map[NUM_COLORS] =
{
COLOR_BLACK,
COLOR_BLUE,
COLOR_GREEN,
COLOR_CYAN,
COLOR_RED,
COLOR_MAGENTA,
COLOR_YELLOW,
COLOR_WHITE
};
static int use_color;
extern struct grub_terminfo_output_state grub_console_terminfo_output;
static int original_fl;
static int saved_orig;
static struct termios orig_tty;
static struct termios new_tty;
static void
grub_ncurses_putchar (struct grub_term_output *term __attribute__ ((unused)),
const struct grub_unicode_glyph *c)
put (struct grub_term_output *term __attribute__ ((unused)), const int c)
{
addch (c->base | grub_console_attr);
}
char chr = c;
static void
grub_ncurses_setcolorstate (struct grub_term_output *term,
grub_term_color_state state)
{
switch (state)
{
case GRUB_TERM_COLOR_STANDARD:
grub_console_cur_color = grub_console_standard_color;
grub_console_attr = A_NORMAL;
break;
case GRUB_TERM_COLOR_NORMAL:
grub_console_cur_color = grub_term_normal_color;
grub_console_attr = A_NORMAL;
break;
case GRUB_TERM_COLOR_HIGHLIGHT:
grub_console_cur_color = grub_term_highlight_color;
grub_console_attr = A_STANDOUT;
break;
default:
break;
}
if (use_color)
{
grub_uint8_t fg, bg;
fg = (grub_console_cur_color & 7);
bg = (grub_console_cur_color >> 4) & 7;
grub_console_attr = (grub_console_cur_color & 8) ? A_BOLD : A_NORMAL;
color_set ((bg << 3) + fg, 0);
}
write (STDOUT_FILENO, &chr, 1);
}
static int
grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused)))
readkey (struct grub_term_input *term __attribute__ ((unused)))
{
int c;
grub_uint8_t c;
ssize_t actual;
wtimeout (stdscr, 100);
c = getch ();
switch (c)
{
case ERR:
return GRUB_TERM_NO_KEY;
case KEY_LEFT:
c = GRUB_TERM_KEY_LEFT;
break;
case KEY_RIGHT:
c = GRUB_TERM_KEY_RIGHT;
break;
case KEY_UP:
c = GRUB_TERM_KEY_UP;
break;
case KEY_DOWN:
c = GRUB_TERM_KEY_DOWN;
break;
case KEY_IC:
c = 24;
break;
case KEY_DC:
c = GRUB_TERM_KEY_DC;
break;
case KEY_BACKSPACE:
/* XXX: For some reason ncurses on xterm does not return
KEY_BACKSPACE. */
case 127:
c = '\b';
break;
case KEY_HOME:
c = GRUB_TERM_KEY_HOME;
break;
case KEY_END:
c = GRUB_TERM_KEY_END;
break;
case KEY_NPAGE:
c = GRUB_TERM_KEY_NPAGE;
break;
case KEY_PPAGE:
c = GRUB_TERM_KEY_PPAGE;
break;
}
return c;
}
static grub_uint16_t
grub_ncurses_getxy (struct grub_term_output *term __attribute__ ((unused)))
{
int x;
int y;
getyx (stdscr, y, x);
return (x << 8) | y;
}
static grub_uint16_t
grub_ncurses_getwh (struct grub_term_output *term __attribute__ ((unused)))
{
int x;
int y;
getmaxyx (stdscr, y, x);
return (x << 8) | y;
}
static void
grub_ncurses_gotoxy (struct grub_term_output *term __attribute__ ((unused)),
grub_uint8_t x, grub_uint8_t y)
{
move (y, x);
}
static void
grub_ncurses_cls (struct grub_term_output *term __attribute__ ((unused)))
{
clear ();
refresh ();
}
static void
grub_ncurses_setcursor (struct grub_term_output *term __attribute__ ((unused)),
int on)
{
curs_set (on ? 1 : 0);
}
static void
grub_ncurses_refresh (struct grub_term_output *term __attribute__ ((unused)))
{
refresh ();
actual = read (STDIN_FILENO, &c, 1);
if (actual > 0)
return c;
return -1;
}
static grub_err_t
grub_ncurses_init (struct grub_term_output *term __attribute__ ((unused)))
grub_console_init_input (struct grub_term_input *term)
{
initscr ();
raw ();
noecho ();
scrollok (stdscr, TRUE);
nonl ();
intrflush (stdscr, FALSE);
keypad (stdscr, TRUE);
if (has_colors ())
if (!saved_orig)
{
start_color ();
if ((COLORS >= NUM_COLORS) && (COLOR_PAIRS >= NUM_COLORS * NUM_COLORS))
{
int i, j, n;
n = 0;
for (i = 0; i < NUM_COLORS; i++)
for (j = 0; j < NUM_COLORS; j++)
init_pair(n++, color_map[j], color_map[i]);
use_color = 1;
}
original_fl = fcntl (STDIN_FILENO, F_GETFL);
fcntl (STDIN_FILENO, F_SETFL, original_fl | O_NONBLOCK);
}
return 0;
saved_orig = 1;
tcgetattr(STDIN_FILENO, &orig_tty);
new_tty = orig_tty;
new_tty.c_lflag &= ~(ICANON | ECHO);
new_tty.c_cc[VMIN] = 1;
tcsetattr(STDIN_FILENO, TCSANOW, &new_tty);
return grub_terminfo_input_init (term);
}
static grub_err_t
grub_ncurses_fini (struct grub_term_output *term __attribute__ ((unused)))
grub_console_fini_input (struct grub_term_input *term
__attribute__ ((unused)))
{
endwin ();
fcntl (STDIN_FILENO, F_SETFL, original_fl);
tcsetattr(STDIN_FILENO, TCSANOW, &orig_tty);
saved_orig = 0;
return GRUB_ERR_NONE;
}
static grub_err_t
grub_console_init_output (struct grub_term_output *term)
{
struct winsize size;
if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &size) >= 0)
{
grub_console_terminfo_output.width = size.ws_col;
grub_console_terminfo_output.height = size.ws_row;
}
else
{
grub_console_terminfo_output.width = 80;
grub_console_terminfo_output.height = 24;
}
grub_terminfo_output_init (term);
return 0;
}
static struct grub_term_input grub_ncurses_term_input =
struct grub_terminfo_input_state grub_console_terminfo_input =
{
.name = "console",
.getkey = grub_ncurses_getkey,
.readkey = readkey
};
static struct grub_term_output grub_ncurses_term_output =
struct grub_terminfo_output_state grub_console_terminfo_output =
{
.put = put,
.width = 80,
.height = 24
};
static struct grub_term_input grub_console_term_input =
{
.name = "console",
.init = grub_ncurses_init,
.fini = grub_ncurses_fini,
.putchar = grub_ncurses_putchar,
.getxy = grub_ncurses_getxy,
.getwh = grub_ncurses_getwh,
.gotoxy = grub_ncurses_gotoxy,
.cls = grub_ncurses_cls,
.setcolorstate = grub_ncurses_setcolorstate,
.setcursor = grub_ncurses_setcursor,
.refresh = grub_ncurses_refresh,
.flags = GRUB_TERM_CODE_TYPE_ASCII
.init = grub_console_init_input,
.fini = grub_console_fini_input,
.getkey = grub_terminfo_getkey,
.data = &grub_console_terminfo_input
};
static struct grub_term_output grub_console_term_output =
{
.name = "console",
.init = grub_console_init_output,
.putchar = grub_terminfo_putchar,
.getxy = grub_terminfo_getxy,
.getwh = grub_terminfo_getwh,
.gotoxy = grub_terminfo_gotoxy,
.cls = grub_terminfo_cls,
.setcolorstate = grub_terminfo_setcolorstate,
.setcursor = grub_terminfo_setcursor,
.data = &grub_console_terminfo_output,
};
void
grub_console_init (void)
{
grub_term_register_output ("console", &grub_ncurses_term_output);
grub_term_register_input ("console", &grub_ncurses_term_input);
const char *cs = nl_langinfo (CODESET);
if (cs && grub_strcasecmp (cs, "UTF-8"))
grub_console_term_output.flags = GRUB_TERM_CODE_TYPE_UTF8_LOGICAL;
else
grub_console_term_output.flags = GRUB_TERM_CODE_TYPE_ASCII;
grub_term_register_input ("console", &grub_console_term_input);
grub_term_register_output ("console", &grub_console_term_output);
grub_terminfo_init ();
grub_terminfo_output_register (&grub_console_term_output, "vt100-color");
}
void
grub_console_fini (void)
{
grub_ncurses_fini (&grub_ncurses_term_output);
if (saved_orig)
{
fcntl (STDIN_FILENO, F_SETFL, original_fl);
tcsetattr(STDIN_FILENO, TCSANOW, &orig_tty);
}
saved_orig = 0;
}

View file

@ -82,9 +82,7 @@ grub_err_t EXPORT_FUNC (grub_terminfo_output_register) (struct grub_term_output
const char *type);
grub_err_t EXPORT_FUNC (grub_terminfo_output_unregister) (struct grub_term_output *term);
#ifndef GRUB_MACHINE_EMU
void grub_terminfo_init (void);
void grub_terminfo_fini (void);
#endif
#endif /* ! GRUB_TERMINFO_HEADER */