From c726080def2d11ff322cfa3155ebdb89b94a14de Mon Sep 17 00:00:00 2001 From: Pavol Babincak Date: Wed, 8 Feb 2006 01:42:39 +0100 Subject: [PATCH] Double-width glyph support in terminal draw Added unicode_to_cell detect double-width glyphs. Modified terminal draw to correctly accept double-width glyphs. --- src/intl/charsets.c | 32 ++++++++++++++++++++++++++++++++ src/intl/charsets.h | 1 + src/terminal/draw.c | 40 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/intl/charsets.c b/src/intl/charsets.c index 9a2243990..da3b27b51 100644 --- a/src/intl/charsets.c +++ b/src/intl/charsets.c @@ -252,6 +252,38 @@ strlen_utf8(unsigned char **str) return x; } + +/* + * Find out number of standard terminal collumns needed for displaying symbol + * (glyph) which represents Unicode character c. + * TODO: Use wcwidth when it is available. + * + * @return 2 for double-width glyph, 1 for others. + * TODO: May be extended to return 0 for zero-width glyphs + * (like composing, maybe unprintable too). + */ +inline int +unicode_to_cell(unicode_val_T c) +{ + if (c >= 0x1100 + && (c <= 0x115f /* Hangul Jamo */ + || c == 0x2329 + || c == 0x232a + || (c >= 0x2e80 && c <= 0xa4cf + && c != 0x303f) /* CJK ... Yi */ + || (c >= 0xac00 && c <= 0xd7a3) /* Hangul Syllables */ + || (c >= 0xf900 && c <= 0xfaff) /* CJK Compatibility + Ideographs */ + || (c >= 0xfe30 && c <= 0xfe6f) /* CJK Compatibility Forms */ + || (c >= 0xff00 && c <= 0xff60) /* Fullwidth Forms */ + || (c >= 0xffe0 && c <= 0xffe6) + || (c >= 0x20000 && c <= 0x2fffd) + || (c >= 0x30000 && c <= 0x3fffd))) + return 2; + + return 1; +} + inline unicode_val_T utf_8_to_unicode(unsigned char **string, unsigned char *end) { diff --git a/src/intl/charsets.h b/src/intl/charsets.h index f237e8f90..fbccb3bb5 100644 --- a/src/intl/charsets.h +++ b/src/intl/charsets.h @@ -56,6 +56,7 @@ void free_conv_table(void); #ifdef CONFIG_UTF_8 inline unsigned char *encode_utf_8(unicode_val_T); inline int utf8charlen(const unsigned char *); +inline int unicode_to_cell(unicode_val_T); inline int strlen_utf8(unsigned char **); inline unicode_val_T utf_8_to_unicode(unsigned char **, unsigned char *); #endif /* CONFIG_UTF_8 */ diff --git a/src/terminal/draw.c b/src/terminal/draw.c index 5f94ab186..34c83d337 100644 --- a/src/terminal/draw.c +++ b/src/terminal/draw.c @@ -114,6 +114,26 @@ draw_char_data(struct terminal *term, int x, int y, unsigned char data) if (!screen_char) return; screen_char->data = data; + +#ifdef CONFIG_UTF_8 + if (unicode_to_cell(data) == 2) { + +#ifdef CONFIG_DEBUG + /* Detect attempt to draw double-width char on the last + * collumn of terminal. */ + if (x+1 > term->width) + INTERNAL("Attempt to draw double-width glyph on " + "last collumn!!"); +#endif /* CONFIG_DEBUG */ + + screen_char = get_char(term, x+1, y); + + if (!screen_char) return; + + screen_char->data = UCS_NO_CHAR; + } +#endif /* CONFIG_UTF_8 */ + set_screen_dirty(term->screen, y, y); } @@ -315,7 +335,25 @@ draw_text_utf8(struct terminal *term, int x, int y, get_opt_int_tree(term->spec, "colors")); } - for (pos = start + 1; x < term->width; x++, pos++) { + pos = start + 1; + + if (unicode_to_cell(data) == 2) { + +#ifdef CONFIG_DEBUG + /* Detect attempt to draw double-width char on the last + * collumn of terminal. */ + if (x+1 > term->width) + INTERNAL("Attempt to draw double-width character on " + "last collumn!!"); +#endif /* CONFIG_DEBUG */ + + pos->data = UCS_NO_CHAR; + if (color) copy_screen_chars(pos, start, 1); + x++; + pos++; + } + + for (; x < term->width; x++, pos++) { data = utf_8_to_unicode(&text, end); if (data == UCS_NO_CHAR) break; if (color) copy_screen_chars(pos, start, 1);