diff options
author | Jeremie Koenig <jk@jk.fr.eu.org> | 2010-08-01 13:52:04 +0200 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2010-08-01 14:02:43 +0200 |
commit | 45e3044ed47fcaab15579da516df8922b3b48954 (patch) | |
tree | 7e0c4ca4d49afba73218f8fd51c40cce52eae996 | |
parent | ee096c09818baf60ef2f8bafc421171ceadd8e18 (diff) |
Add wide character support to the Hurd console
* hurd/console.h (CONS_WCHAR_MASK, CONS_WCHAR_CONTINUED): New macros.
* console/console.c: Include <locale.h>
(main): Call setlocale.
* console/display.c (display_output_one): Call wcwidth() to know the
width of the character to be displayed. Iterate over this with to insert
characters with the additional CONS_WCHAR_CONTINUED flag. Update
screen_shift_right and display_record_filechange calls accordingly.
* console-client/vga-dynafont.c (WCHAR_BOLD, WCHAR_ITALIC, WCHAR_MASK):
Change macro values.
(dynafont_new): Use glyph->bbox.{width,height} instead of
df->font->bbox.{width,height}.
(dynafont_change_font): Likewise.
(dynafont_lookup_internal): Likewise.
Mask out CONS_WCHAR_CONTINUED before calling bdf_find_glyph, but test it
for the second position of a double-width glyph.
(dynafont_activate): Enable 9-bit width only when font width is not
dividable by 8.
-rw-r--r-- | console-client/vga-dynafont.c | 54 | ||||
-rw-r--r-- | console/console.c | 3 | ||||
-rw-r--r-- | console/display.c | 29 | ||||
-rw-r--r-- | hurd/console.h | 8 |
4 files changed, 60 insertions, 34 deletions
diff --git a/console-client/vga-dynafont.c b/console-client/vga-dynafont.c index 0cce5176..3888af79 100644 --- a/console-client/vga-dynafont.c +++ b/console-client/vga-dynafont.c @@ -60,9 +60,9 @@ struct mapped_character /* Remember the character this glyph belongs to, so the glyph can be reloaded when the font is changed. This is actually a wchar_t with some text attributes mixed into the high bits. */ -#define WCHAR_BOLD ((wchar_t) 0x40000000) -#define WCHAR_ITALIC ((wchar_t) 0x20000000) -#define WCHAR_MASK ((wchar_t) 0x001fffff) +#define WCHAR_BOLD ((wchar_t) 0x20000000) +#define WCHAR_ITALIC ((wchar_t) 0x10000000) +#define WCHAR_MASK CONS_WCHAR_MASK wchar_t character; /* Used by libihash for fast removal of elements. */ @@ -541,14 +541,13 @@ dynafont_new (bdf_font_t font, bdf_font_t font_italic, bdf_font_t font_bold, glyph = bdf_find_glyph (df->font, -1, UNICODE_REPLACEMENT_CHARACTER); if (glyph) { - /* XXX Take glyph size into account. */ - for (int i = 0; i < ((df->font->bbox.height > 32) - ? 32 : df->font->bbox.height); i++) + for (int i = 0; i < ((glyph->bbox.height > 32) + ? 32 : glyph->bbox.height); i++) df->vga_font[FONT_INDEX_UNKNOWN][i] - = glyph->bitmap[i * ((df->font->bbox.width + 7) / 8)]; - if (df->font->bbox.height < 32) + = glyph->bitmap[i * ((glyph->bbox.width + 7) / 8)]; + if (glyph->bbox.height < 32) memset (((char *) df->vga_font[FONT_INDEX_UNKNOWN]) - + df->font->bbox.height, 0, 32 - df->font->bbox.height); + + glyph->bbox.height, 0, 32 - glyph->bbox.height); /* Update the hash table. */ hurd_ihash_add (&df->charmap, UNICODE_REPLACEMENT_CHARACTER, chr); @@ -780,9 +779,9 @@ dynafont_lookup_internal (dynafont_t df, bdf_font_t font, || (!lgc && !df->vga_font_free_indices)) return 0; - glyph = bdf_find_glyph (font, (int) wide_chr, 0); + glyph = bdf_find_glyph (font, (int) (wide_chr & ~CONS_WCHAR_CONTINUED), 0); if (!glyph) - glyph = bdf_find_glyph (font, -1, (int) wide_chr); + glyph = bdf_find_glyph (font, -1, (int) (wide_chr & ~CONS_WCHAR_CONTINUED)); if (!glyph) return 0; @@ -847,14 +846,17 @@ dynafont_lookup_internal (dynafont_t df, bdf_font_t font, chr->refs = 1; chr->character = (wide_chr | attr); - /* XXX Should look at glyph bbox. */ - for (int i = 0; i < ((font->bbox.height > 32) - ? 32 : font->bbox.height); i++) - df->vga_font[pos][i] - = glyph->bitmap[i * ((font->bbox.width + 7) / 8)]; - if (font->bbox.height < 32) - memset (((char *) df->vga_font[pos]) - + font->bbox.height, 0, 32 - font->bbox.height); + /* Copy the glyph bitmap, taking into account double-width charcters. */ + { + int height = (glyph->bbox.height > 32) ? 32 : glyph->bbox.height; + int bwidth = (glyph->bbox.width + 7) / 8; + int ofs = (bwidth >= 2) && (wide_chr & CONS_WCHAR_CONTINUED); + + for (int i = 0; i < height; i++) + df->vga_font[pos][i] = glyph->bitmap[i * bwidth + ofs]; + if (height < 32) + memset (&df->vga_font[pos][height], 0, 32 - height); + } if (active_dynafont == df) vga_write_font_buffer (0, pos, df->vga_font[pos], @@ -958,7 +960,7 @@ dynafont_activate (dynafont_t df) display problems for the user if we don't also program the video mode timings. The standard font height for 80x25 is 16. */ vga_set_font_height (height); - vga_set_font_width (df->font->bbox.width <= 8 ? 8 : 9); + vga_set_font_width (df->font->bbox.width % 8 ? 9 : 8); active_dynafont = df; dynafont_set_cursor (df, df->cursor_standout); @@ -1027,13 +1029,13 @@ dynafont_change_font (dynafont_t df, bdf_font_t font) else { /* XXX Take font size and glyph size into account. */ - for (int j = 0; j < ((df->font->bbox.height > 32) - ? 32 : df->font->bbox.height); j++) + for (int j = 0; j < ((glyph->bbox.height > 32) + ? 32 : glyph->bbox.height); j++) df->vga_font[i][j] - = glyph->bitmap[j * ((df->font->bbox.width + 7) / 8)]; - if (df->font->bbox.height < 32) - memset (((char *) df->vga_font[i]) + df->font->bbox.height, - 0, 32 - df->font->bbox.height); + = glyph->bitmap[j * ((glyph->bbox.width + 7) / 8)]; + if (glyph->bbox.height < 32) + memset (((char *) df->vga_font[i]) + glyph->bbox.height, + 0, 32 - glyph->bbox.height); } } } diff --git a/console/console.c b/console/console.c index 6225d71d..eb2f1f44 100644 --- a/console/console.c +++ b/console/console.c @@ -23,6 +23,7 @@ #include <stdlib.h> #include <stddef.h> #include <unistd.h> +#include <locale.h> #include <argp.h> #include <argz.h> @@ -2018,6 +2019,8 @@ main (int argc, char **argv) /* Parse our command line arguments. */ argp_parse (&netfs_std_runtime_argp, argc, argv, 0, 0, cons); + setlocale (LC_CTYPE, "C.UTF-8"); + task_get_bootstrap_port (mach_task_self (), &bootstrap); netfs_init (); diff --git a/console/display.c b/console/display.c index 090aaf80..f6a24a8a 100644 --- a/console/display.c +++ b/console/display.c @@ -1593,23 +1593,38 @@ display_output_one (display_t display, wchar_t chr) int line = (user->screen.cur_line + user->cursor.row) % user->screen.lines; int idx = line * user->screen.width + user->cursor.col; + int width, i; + + width = wcwidth (chr); + if (width < 0) + width = 1; if (display->insert_mode - && user->cursor.col != user->screen.width - 1) + && user->cursor.col < user->screen.width - width) { /* If in insert mode, do the same as <ich1>. */ screen_shift_right (display, user->cursor.col, user->cursor.row, user->screen.width - 1, user->cursor.row, - 1, L' ', display->attr.current); + width, L' ', display->attr.current); + } + + if (display->attr.altchar) + chr = altchar_to_ucs4 (chr); + + for (i = 0; i < width; i++) + { + if (user->cursor.col >= user->screen.width) + break; + user->_matrix[idx+i].chr = chr; + user->_matrix[idx+i].attr = display->attr.current; + user->cursor.col++; + chr |= CONS_WCHAR_CONTINUED; } - user->_matrix[idx].chr = display->attr.altchar - ? altchar_to_ucs4 (chr) : chr; - user->_matrix[idx].attr = display->attr.current; + if (i > 0) + display_record_filechange (display, idx, idx + i - 1); - display_record_filechange (display, idx, idx); - user->cursor.col++; if (user->cursor.col == user->screen.width) { user->cursor.col = 0; diff --git a/hurd/console.h b/hurd/console.h index 065ed7d2..16bc068d 100644 --- a/hurd/console.h +++ b/hurd/console.h @@ -50,7 +50,13 @@ typedef struct uint32_t italic : 1; uint32_t bold : 1; } conchar_attr_t; - + +/* We support double-width characters by using an extra bit to identify the + continuation in the character matrix. The constants below document our + usage of wchar_t. */ +#define CONS_WCHAR_MASK ((wchar_t) 0x401fffff) +#define CONS_WCHAR_CONTINUED ((wchar_t) 0x40000000) + typedef struct { wchar_t chr; |