diff --git a/ChangeLog b/ChangeLog index 36a01642b..0e1ebcede 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,37 @@ +2005-08-20 Yoshinori K. Okuji + + * kern/term.c (grub_putchar): Use grub_utf8_to_ucs4 for the + conversion. + (grub_getcharwidth): New function. + + * kern/misc.c (grub_utf8_to_ucs4): New function. + + * include/grub/term.h (struct grub_term): Added a new member + "getcharwidth". + (grub_getcharwidth): New prototype. + + * include/grub/misc.h (grub_utf8_to_ucs4): New prototype. + + * term/i386/pc/console.c (map_char): New function. Segregated from + grub_console_putchar. + (grub_console_putchar): Use map_char. + (grub_console_getcharwidth): New function. + (grub_console_term): Specified grub_console_getcharwidth as + getcharwidth. + + * term/i386/pc/vga.c (grub_vga_getcharwidth): New function. + (grub_vga_term): Specified grub_vga_getcharwidth as getcharwidth. + + * term/i386/pc/vesafb.c (grub_virtual_screen_setup): Return + GRUB_ERRNO. + (grub_vesafb_init): Do not use RC. Instead, use GRUB_ERRNO. Rely + on grub_strtoul completely. + (write_char): Declare local variables in the beginning of the + function. + (grub_vesafb_getcharwidth): New function. + (grub_vesafb_term): Specified grub_vesafb_getcharwidth as + getcharwidth. + 2005-08-19 Yoshinori K. Okuji * DISTLIST: Replace commands/i386/pc/vbe_list_modes.c and diff --git a/include/grub/misc.h b/include/grub/misc.h index 1f605dd18..b549c3e2f 100644 --- a/include/grub/misc.h +++ b/include/grub/misc.h @@ -72,6 +72,9 @@ void EXPORT_FUNC(grub_stop) (void) __attribute__ ((noreturn)); grub_uint8_t *EXPORT_FUNC(grub_utf16_to_utf8) (grub_uint8_t *dest, grub_uint16_t *src, grub_size_t size); +grub_ssize_t EXPORT_FUNC(grub_utf8_to_ucs4) (grub_uint32_t *dest, + grub_uint8_t *src, + grub_size_t size); grub_err_t EXPORT_FUNC(grub_split_cmdline) (const char *str, grub_err_t (* getline) (char **), diff --git a/include/grub/term.h b/include/grub/term.h index 17ccc0053..a27ab4011 100644 --- a/include/grub/term.h +++ b/include/grub/term.h @@ -135,6 +135,10 @@ struct grub_term /* Put a character. C is encoded in Unicode. */ void (*putchar) (grub_uint32_t c); + + /* Get the number of columns occupied by a given character C. C is + encoded in Unicode. */ + grub_ssize_t (*getcharwidth) (grub_uint32_t c); /* Check if any input character is available. */ int (*checkkey) (void); @@ -184,6 +188,7 @@ grub_term_t EXPORT_FUNC(grub_term_get_current) (void); void EXPORT_FUNC(grub_putchar) (int c); void EXPORT_FUNC(grub_putcode) (grub_uint32_t code); +grub_ssize_t EXPORT_FUNC(grub_getcharwidth) (grub_uint32_t code); int EXPORT_FUNC(grub_getkey) (void); int EXPORT_FUNC(grub_checkkey) (void); grub_uint16_t EXPORT_FUNC(grub_getwh) (void); diff --git a/kern/misc.c b/kern/misc.c index 6611dac2b..255ebb250 100644 --- a/kern/misc.c +++ b/kern/misc.c @@ -742,7 +742,7 @@ grub_sprintf (char *str, const char *fmt, ...) return ret; } -/* Convert UTF-16 to UTF8. */ +/* Convert UTF-16 to UTF-8. */ grub_uint8_t * grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, grub_size_t size) @@ -804,8 +804,79 @@ grub_utf16_to_utf8 (grub_uint8_t *dest, grub_uint16_t *src, return dest; } +/* Convert an UTF-8 string to an UCS-4 string. Return the number of + characters converted. DEST must be able to hold at least SIZE + characters (when the input is unknown). If an invalid sequence is found, + return -1. */ +grub_ssize_t +grub_utf8_to_ucs4 (grub_uint32_t *dest, grub_uint8_t *src, grub_size_t size) +{ + grub_uint32_t *p = dest; + int count = 0; + grub_uint32_t code = 0; + + while (size--) + { + grub_uint32_t c = *src++; + + if (count) + { + if ((c & 0xc0) != 0x80) + { + /* invalid */ + return -1; + } + else + { + code <<= 6; + code |= (c & 0x3f); + count--; + } + } + else + { + if ((c & 0x80) == 0x00) + code = c; + else if ((c & 0xe0) == 0xc0) + { + count = 1; + code = c & 0x1f; + } + else if ((c & 0xf0) == 0xe0) + { + count = 2; + code = c & 0x0f; + } + else if ((c & 0xf8) == 0xf0) + { + count = 3; + code = c & 0x07; + } + else if ((c & 0xfc) == 0xf8) + { + count = 4; + code = c & 0x03; + } + else if ((c & 0xfe) == 0xfc) + { + count = 5; + code = c & 0x01; + } + else + /* invalid */ + return -1; + } + + if (count == 0) + *p++ = code; + } + + return p - dest; +} + grub_err_t -grub_split_cmdline (const char *cmdline, grub_err_t (* getline) (char **), int *argc, char ***argv) +grub_split_cmdline (const char *cmdline, grub_err_t (*getline) (char **), + int *argc, char ***argv) { /* XXX: Fixed size buffer, perhaps this buffer should be dynamically allocated. */ diff --git a/kern/term.c b/kern/term.c index c5ce2c33e..f5e397653 100644 --- a/kern/term.c +++ b/kern/term.c @@ -143,63 +143,31 @@ grub_putcode (grub_uint32_t code) void grub_putchar (int c) { - static grub_uint32_t code = 0; - static int count = 0; + static grub_size_t size = 0; + static grub_uint8_t buf[6]; + grub_uint32_t code; + grub_ssize_t ret; - if (count) + buf[size++] = c; + ret = grub_utf8_to_ucs4 (&code, buf, size); + + if (ret > 0) { - if ((c & 0xc0) != 0x80) - { - /* invalid */ - code = '@'; - count = 0; - } - else - { - code <<= 6; - code |= (c & 0x3f); - count--; - } + size = 0; + grub_putcode (code); } - else + else if (ret < 0) { - if ((c & 0x80) == 0x00) - code = c; - else if ((c & 0xe0) == 0xc0) - { - count = 1; - code = c & 0x1f; - } - else if ((c & 0xf0) == 0xe0) - { - count = 2; - code = c & 0x0f; - } - else if ((c & 0xf8) == 0xf0) - { - count = 3; - code = c & 0x07; - } - else if ((c & 0xfc) == 0xf8) - { - count = 4; - code = c & 0x03; - } - else if ((c & 0xfe) == 0xfc) - { - count = 5; - code = c & 0x01; - } - else - /* invalid */ - code = '?'; - } + size = 0; + grub_putcode ('?'); + } +} - if (count) - /* Not finished yet. */ - return; - - grub_putcode (code); +/* Return the number of columns occupied by the character code CODE. */ +grub_ssize_t +grub_getcharwidth (grub_uint32_t code) +{ + return (grub_cur_term->getcharwidth) (code); } int diff --git a/term/i386/pc/console.c b/term/i386/pc/console.c index c0f2f7144..deae1d7aa 100644 --- a/term/i386/pc/console.c +++ b/term/i386/pc/console.c @@ -26,8 +26,8 @@ static grub_uint8_t grub_console_standard_color = 0x7; static grub_uint8_t grub_console_normal_color = 0x7; static grub_uint8_t grub_console_highlight_color = 0x70; -static void -grub_console_putchar (grub_uint32_t c) +static grub_uint32_t +map_char (grub_uint32_t c) { if (c > 0x7f) { @@ -71,7 +71,20 @@ grub_console_putchar (grub_uint32_t c) } } - grub_console_real_putchar (c); + return c; +} + +static void +grub_console_putchar (grub_uint32_t c) +{ + grub_console_real_putchar (map_char (c)); +} + +static grub_ssize_t +grub_console_getcharwidth (grub_uint32_t c __attribute__ ((unused))) +{ + /* For now, every printable character has the width 1. */ + return 1; } static grub_uint16_t @@ -111,6 +124,7 @@ static struct grub_term grub_console_term = .init = 0, .fini = 0, .putchar = grub_console_putchar, + .getcharwidth = grub_console_getcharwidth, .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, .getwh = grub_console_getwh, diff --git a/term/i386/pc/vesafb.c b/term/i386/pc/vesafb.c index 9384ddfbb..b2f39d568 100644 --- a/term/i386/pc/vesafb.c +++ b/term/i386/pc/vesafb.c @@ -102,12 +102,10 @@ grub_virtual_screen_free (void) { /* If virtual screen has been allocated, free it. */ if (virtual_screen.text_buffer != 0) - { - grub_free (virtual_screen.text_buffer); - } + grub_free (virtual_screen.text_buffer); /* Reset virtual screen data. */ - grub_memset (&virtual_screen, 0, sizeof(virtual_screen)); + grub_memset (&virtual_screen, 0, sizeof (virtual_screen)); } static grub_err_t @@ -136,21 +134,16 @@ grub_virtual_screen_setup (grub_uint32_t width, /* Allocate memory for text buffer. */ virtual_screen.text_buffer = - (struct grub_colored_char *)grub_malloc (virtual_screen.columns - * virtual_screen.rows - * sizeof(struct grub_colored_char)); - if (virtual_screen.text_buffer == 0) - { - return GRUB_ERR_OUT_OF_MEMORY; - } + (struct grub_colored_char *) grub_malloc (virtual_screen.columns + * virtual_screen.rows + * sizeof (*virtual_screen.text_buffer)); - return GRUB_ERR_NONE; + return grub_errno; } static grub_err_t grub_vesafb_init (void) { - grub_uint32_t rc; grub_uint32_t use_mode = GRUB_VBE_DEFAULT_VIDEO_MODE; struct grub_vbe_info_block controller_info; char *modevar; @@ -159,66 +152,43 @@ grub_vesafb_init (void) vga_font = grub_vga_get_font (); /* Check if we have VESA BIOS installed. */ - rc = grub_vbe_probe (&controller_info); - if (rc != GRUB_ERR_NONE) - { - return rc; - } + if (grub_vbe_probe (&controller_info) != GRUB_ERR_NONE) + return grub_errno; /* Check existence of vbe_mode environment variable. */ modevar = grub_env_get ("vbe_mode"); if (modevar != 0) { - unsigned long value = 0; + unsigned long value; - if ((grub_strncmp (modevar, "0x", 2) == 0) || - (grub_strncmp (modevar, "0X", 2) == 0)) - { - /* Convert HEX mode number. */ - value = grub_strtoul (modevar + 2, 0, 16); - } - else - { - /* Convert DEC mode number. */ - value = grub_strtoul (modevar, 0, 10); - } - - if (value != 0) - { - use_mode = value; - } + value = grub_strtoul (modevar, 0, 0); + if (grub_errno == GRUB_ERR_NONE) + use_mode = value; } /* Store initial video mode. */ - rc = grub_vbe_get_video_mode (&old_mode); + if (grub_vbe_get_video_mode (&old_mode) != GRUB_ERR_NONE) + return grub_errno; /* Setup desired graphics mode. */ - rc = grub_vbe_set_video_mode (use_mode, &mode_info); - if (rc != GRUB_ERR_NONE) - { - return rc; - } + if (grub_vbe_set_video_mode (use_mode, &mode_info) != GRUB_ERR_NONE) + return grub_errno; /* Determine framebuffer and bytes per scan line. */ - framebuffer = (grub_uint8_t *)mode_info.phys_base_addr; + framebuffer = (grub_uint8_t *) mode_info.phys_base_addr; if (controller_info.version >= 0x300) - { - bytes_per_scan_line = mode_info.lin_bytes_per_scan_line; - } + bytes_per_scan_line = mode_info.lin_bytes_per_scan_line; else - { - bytes_per_scan_line = mode_info.bytes_per_scan_line; - } + bytes_per_scan_line = mode_info.bytes_per_scan_line; /* Create virtual screen. */ - rc = grub_virtual_screen_setup (mode_info.x_resolution, - mode_info.y_resolution); - if (rc != GRUB_ERR_NONE) + if (grub_virtual_screen_setup (mode_info.x_resolution, + mode_info.y_resolution) != GRUB_ERR_NONE) { grub_vbe_set_video_mode (old_mode, 0); - return rc; + return grub_errno; } /* Make sure frame buffer is black. */ @@ -319,6 +289,8 @@ write_char (void) struct grub_colored_char *p; unsigned char bitmap[32]; unsigned width; + unsigned y; + unsigned offset; p = (virtual_screen.text_buffer + virtual_screen.cursor_x @@ -332,9 +304,6 @@ write_char (void) width = 0; } - unsigned y; - unsigned offset; - for (y = 0, offset = 0; y < virtual_screen.char_height; y++, offset++) @@ -347,7 +316,7 @@ write_char (void) { unsigned char color; - if (bitmap[offset] & (1<<(8-i))) + if (bitmap[offset] & (1 << (8-i))) { color = p->fg_color; } @@ -392,7 +361,7 @@ scroll_up (void) /* Scroll text buffer with one line to up. */ grub_memmove (virtual_screen.text_buffer, virtual_screen.text_buffer + virtual_screen.columns, - sizeof (struct grub_colored_char) + sizeof (*virtual_screen.text_buffer) * virtual_screen.columns * (virtual_screen.rows - 1)); @@ -468,9 +437,9 @@ grub_vesafb_putchar (grub_uint32_t c) if (virtual_screen.cursor_x + width > virtual_screen.columns) grub_putchar ('\n'); - p = virtual_screen.text_buffer + - virtual_screen.cursor_x + - virtual_screen.cursor_y * virtual_screen.columns; + p = (virtual_screen.text_buffer + + virtual_screen.cursor_x + + virtual_screen.cursor_y * virtual_screen.columns); p->code = c; p->fg_color = virtual_screen.fg_color; p->bg_color = virtual_screen.bg_color; @@ -507,6 +476,17 @@ grub_vesafb_putchar (grub_uint32_t c) } } +static grub_ssize_t +grub_vesafb_getcharwidth (grub_uint32_t c) +{ + unsigned width; + + if (! grub_virtual_screen_get_glyph (c, 0, &width)) + return 0; + + return width; +} + static grub_uint16_t grub_virtual_screen_getwh (void) { @@ -612,6 +592,7 @@ static struct grub_term grub_vesafb_term = .init = grub_vesafb_init, .fini = grub_vesafb_fini, .putchar = grub_vesafb_putchar, + .getcharwidth = grub_vesafb_getcharwidth, .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, .getwh = grub_virtual_screen_getwh, diff --git a/term/i386/pc/vga.c b/term/i386/pc/vga.c index 058468dc1..a0b2b3c45 100644 --- a/term/i386/pc/vga.c +++ b/term/i386/pc/vga.c @@ -472,6 +472,17 @@ grub_vga_putchar (grub_uint32_t c) #endif } +static grub_ssize_t +grub_vga_getcharwidth (grub_uint32_t c) +{ + unsigned width; + + if (! get_vga_glyph (c, 0, &width)) + return 0; + + return width; +} + static grub_uint16_t grub_vga_getwh (void) { @@ -570,6 +581,7 @@ static struct grub_term grub_vga_term = .init = grub_vga_init, .fini = grub_vga_fini, .putchar = grub_vga_putchar, + .getcharwidth = grub_vga_getcharwidth, .checkkey = grub_console_checkkey, .getkey = grub_console_getkey, .getwh = grub_vga_getwh,