/* console.c -- Ncurses console for GRUB. */ /* * GRUB -- GRand Unified Bootloader * Copyright (C) 2003,2005,2007,2008 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 * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GRUB 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 GRUB. If not, see . */ #include /* For compatibility. */ #ifndef A_NORMAL # define A_NORMAL 0 #endif /* ! A_NORMAL */ #ifndef A_STANDOUT # define A_STANDOUT 0 #endif /* ! A_STANDOUT */ #include #include #include #if defined(HAVE_NCURSES_CURSES_H) # include #elif defined(HAVE_NCURSES_H) # include #elif defined(HAVE_CURSES_H) # include #endif static int grub_console_attr = A_NORMAL; 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; static void grub_ncurses_putchar (struct grub_term_output *term __attribute__ ((unused)), const struct grub_unicode_glyph *c) { addch (c->base | grub_console_attr); } 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 = term->normal_color; grub_console_attr = A_NORMAL; break; case GRUB_TERM_COLOR_HIGHLIGHT: grub_console_cur_color = 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); } } static int saved_char = ERR; static int grub_ncurses_checkkey (struct grub_term_input *term __attribute__ ((unused))) { int c; /* Check for SAVED_CHAR. This should not be true, because this means checkkey is called twice continuously. */ if (saved_char != ERR) return saved_char; wtimeout (stdscr, 100); c = getch (); /* If C is not ERR, then put it back in the input queue. */ if (c != ERR) { saved_char = c; return c; } return -1; } static int grub_ncurses_getkey (struct grub_term_input *term __attribute__ ((unused))) { int c; /* If checkkey has already got a character, then return it. */ if (saved_char != ERR) { c = saved_char; saved_char = ERR; } else { wtimeout (stdscr, -1); c = getch (); } switch (c) { case KEY_LEFT: c = GRUB_TERM_LEFT; break; case KEY_RIGHT: c = GRUB_TERM_RIGHT; break; case KEY_UP: c = GRUB_TERM_UP; break; case KEY_DOWN: c = GRUB_TERM_DOWN; break; case KEY_IC: c = 24; break; case KEY_DC: c = GRUB_TERM_DC; break; case KEY_BACKSPACE: /* XXX: For some reason ncurses on xterm does not return KEY_BACKSPACE. */ case 127: c = GRUB_TERM_BACKSPACE; break; case KEY_HOME: c = GRUB_TERM_HOME; break; case KEY_END: c = GRUB_TERM_END; break; case KEY_NPAGE: c = GRUB_TERM_NPAGE; break; case KEY_PPAGE: c = GRUB_TERM_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 (); } static grub_err_t grub_ncurses_init (struct grub_term_output *term __attribute__ ((unused))) { initscr (); raw (); noecho (); scrollok (stdscr, TRUE); nonl (); intrflush (stdscr, FALSE); keypad (stdscr, TRUE); if (has_colors ()) { 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; } } return 0; } static grub_err_t grub_ncurses_fini (struct grub_term_output *term __attribute__ ((unused))) { endwin (); return 0; } static struct grub_term_input grub_ncurses_term_input = { .name = "console", .checkkey = grub_ncurses_checkkey, .getkey = grub_ncurses_getkey, }; static struct grub_term_output grub_ncurses_term_output = { .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 }; void grub_console_init (void) { grub_term_register_output ("console", &grub_ncurses_term_output); grub_term_register_input ("console", &grub_ncurses_term_input); } void grub_console_fini (void) { grub_ncurses_fini (&grub_ncurses_term_output); }