[PATCH v3] Fixes CJK wide character display

Peng Wu peng.e.wu at gmail.com
Wed Jul 31 22:49:03 PDT 2013


By jumping two columns when wide character prints,
and draw wide cursor under wide character.
---
 clients/Makefile.am |  2 +-
 clients/terminal.c  | 26 ++++++++++++++++++++++++--
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/clients/Makefile.am b/clients/Makefile.am
index 09963cc..e7c0ece 100644
--- a/clients/Makefile.am
+++ b/clients/Makefile.am
@@ -113,7 +113,7 @@ weston_screenshooter_SOURCES =			\
 weston_screenshooter_LDADD = libtoytoolkit.la
 
 weston_terminal_SOURCES = terminal.c
-weston_terminal_LDADD = libtoytoolkit.la -lutil
+weston_terminal_LDADD = libtoytoolkit.la -lutil $(PANGO_LIBS)
 
 weston_image_SOURCES = image.c
 weston_image_LDADD = libtoytoolkit.la
diff --git a/clients/terminal.c b/clients/terminal.c
index 0d4f726..dc56745 100644
--- a/clients/terminal.c
+++ b/clients/terminal.c
@@ -33,6 +33,10 @@
 #include <ctype.h>
 #include <cairo.h>
 #include <sys/epoll.h>
+#include <glib.h>
+#define __USE_XOPEN
+#include <wchar.h>
+#include <locale.h>
 
 #include <wayland-client.h>
 
@@ -93,6 +97,11 @@ union utf8_char {
 	uint32_t ch;
 };
 
+static bool is_wide(union utf8_char utf8){
+	gunichar unichar = g_utf8_get_char((const char*) utf8.byte);
+	return wcwidth(unichar) > 1;
+}
+
 enum utf8_state {
 	utf8state_start,
 	utf8state_accept,
@@ -942,6 +951,7 @@ redraw_handler(struct widget *widget, void *data)
 	struct glyph_run run;
 	cairo_font_extents_t extents;
 	double average_width;
+	double unichar_width;
 
 	surface = window_get_surface(terminal->window);
 	widget_get_allocation(terminal->widget, &allocation);
@@ -967,6 +977,7 @@ redraw_handler(struct widget *widget, void *data)
 			allocation.y + top_margin);
 	/* paint the background */
 	for (row = 0; row < terminal->height; row++) {
+		p_row = terminal_get_row(terminal, row);
 		for (col = 0; col < terminal->width; col++) {
 			/* get the attributes for this character cell */
 			terminal_decode_attr(terminal, row, col, &attr);
@@ -974,12 +985,17 @@ redraw_handler(struct widget *widget, void *data)
 			if (attr.attr.bg == terminal->color_scheme->border)
 				continue;
 
+			if(is_wide(p_row[col]))
+				unichar_width = 2 * average_width;
+			else
+				unichar_width = average_width;
+
 			terminal_set_color(terminal, cr, attr.attr.bg);
 			cairo_move_to(cr, col * average_width,
 				      row * extents.height);
-			cairo_rel_line_to(cr, average_width, 0);
+			cairo_rel_line_to(cr, unichar_width, 0);
 			cairo_rel_line_to(cr, 0, extents.height);
-			cairo_rel_line_to(cr, -average_width, 0);
+			cairo_rel_line_to(cr, -unichar_width, 0);
 			cairo_close_path(cr);
 			cairo_fill(cr);
 		}
@@ -1871,6 +1887,10 @@ handle_char(struct terminal *terminal, union utf8_char utf8)
 	row[terminal->column] = utf8;
 	attr_row[terminal->column++] = terminal->curr_attr;
 
+	/* cursor jump for wide character. */
+	if (is_wide(utf8))
+		row[terminal->column++].ch = 0;
+
 	if (utf8.ch != terminal->last_char.ch)
 		terminal->last_char = utf8;
 }
@@ -2711,6 +2731,8 @@ int main(int argc, char *argv[])
 	struct terminal *terminal;
 	int config_fd;
 
+	setlocale(LC_ALL, "");
+
 	option_shell = getenv("SHELL");
 	if (!option_shell)
 		option_shell = "/bin/bash";
-- 
1.8.3.1



More information about the wayland-devel mailing list