summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremie Koenig <jk@jk.fr.eu.org>2010-08-01 13:52:04 +0200
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2010-08-01 14:02:43 +0200
commit45e3044ed47fcaab15579da516df8922b3b48954 (patch)
tree7e0c4ca4d49afba73218f8fd51c40cce52eae996
parentee096c09818baf60ef2f8bafc421171ceadd8e18 (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.c54
-rw-r--r--console/console.c3
-rw-r--r--console/display.c29
-rw-r--r--hurd/console.h8
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;