/pidgin/main: 028f6001b4cd: cross-win32: finch: unicode input, p...

Tomasz Wasilczyk twasilczyk at pidgin.im
Tue Apr 22 18:56:05 EDT 2014


Changeset: 028f6001b4cd5922462251b63d08fc70f649ba8d
Author:	 Tomasz Wasilczyk <twasilczyk at pidgin.im>
Date:	 2014-04-23 00:55 +0200
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/028f6001b4cd

Description:

cross-win32: finch: unicode input, properly escape special keys

diffstat:

 finch/libgnt/gntkeys.c |   9 +++++++-
 finch/libgnt/gntkeys.h |  54 +++++++++++++++++++++++-----------------------
 finch/libgnt/gntmain.c |  57 ++++++++++++++++++++++++++++++++++++++-----------
 3 files changed, 79 insertions(+), 41 deletions(-)

diffs (220 lines):

diff --git a/finch/libgnt/gntkeys.c b/finch/libgnt/gntkeys.c
--- a/finch/libgnt/gntkeys.c
+++ b/finch/libgnt/gntkeys.c
@@ -51,6 +51,12 @@ void gnt_init_keys()
 			term = "";  /* Just in case */
 	}
 
+#ifdef _WIN32
+	gnt_key_cup = GNT_KEY_CTRL_UP;
+	gnt_key_cdown = GNT_KEY_CTRL_DOWN;
+	gnt_key_cright = GNT_KEY_CTRL_RIGHT;
+	gnt_key_cleft = GNT_KEY_CTRL_LEFT;
+#else
 	if (strstr(term, "xterm") == term || strcmp(term, "rxvt") == 0) {
 		gnt_key_cup    = "\033" "[1;5A";
 		gnt_key_cdown  = "\033" "[1;5B";
@@ -62,6 +68,7 @@ void gnt_init_keys()
 		gnt_key_cright = "\033" "Oc";
 		gnt_key_cleft  = "\033" "Od";
 	}
+#endif
 
 	specials = g_hash_table_new(g_str_hash, g_str_equal);
 
@@ -141,7 +148,7 @@ void gnt_init_keys()
 		}
 	}
 	c = 0;
-	for (a = 0; alts[a]; a++) {
+	for (a = 0; alts[a]; a++) { /* XXX: is that loop necessary? */
 		/* Upper-case alphabets */
 		for (ch = 0; ch < 26; ch++) {
 			char str[2] = {'A' + ch, 0}, code[] = {'\033', 'A' + ch, 0};
diff --git a/finch/libgnt/gntkeys.h b/finch/libgnt/gntkeys.h
--- a/finch/libgnt/gntkeys.h
+++ b/finch/libgnt/gntkeys.h
@@ -49,40 +49,40 @@ extern char *gnt_key_cright;
 
 #define GNT_KEY_POPUP "" /* not supported? */
 
-#define GNT_KEY_UP "\xe0\x48"
-#define GNT_KEY_DOWN "\xe0\x50"
-#define GNT_KEY_LEFT "\xe0\x4B"
-#define GNT_KEY_RIGHT "\xe0\x4D"
+#define GNT_KEY_UP "\033\xe0\x48"
+#define GNT_KEY_DOWN "\033\xe0\x50"
+#define GNT_KEY_LEFT "\033\xe0\x4B"
+#define GNT_KEY_RIGHT "\033\xe0\x4D"
 
-#define GNT_KEY_CTRL_UP "\xe0\x8d"
-#define GNT_KEY_CTRL_DOWN "\xe0\x91"
-#define GNT_KEY_CTRL_LEFT "\xe0\x73"
-#define GNT_KEY_CTRL_RIGHT "\xe0\x74"
+#define GNT_KEY_CTRL_UP "\033\xe0\x8d"
+#define GNT_KEY_CTRL_DOWN "\033\xe0\x91"
+#define GNT_KEY_CTRL_LEFT "\033\xe0\x73"
+#define GNT_KEY_CTRL_RIGHT "\033\xe0\x74"
 
-#define GNT_KEY_PGUP "\xe0\x49"
-#define GNT_KEY_PGDOWN "\xe0\x51"
-#define GNT_KEY_HOME "\xe0\x47"
-#define GNT_KEY_END "\xe0\x4f"
+#define GNT_KEY_PGUP "\033\xe0\x49"
+#define GNT_KEY_PGDOWN "\033\xe0\x51"
+#define GNT_KEY_HOME "\033\xe0\x47"
+#define GNT_KEY_END "\033\xe0\x4f"
 
 #define GNT_KEY_ENTER "\x0d"
 
 #define GNT_KEY_BACKSPACE "\x08"
-#define GNT_KEY_DEL "\xe0\x53"
-#define GNT_KEY_INS "\xe0\x52"
-#define GNT_KEY_BACK_TAB "\xe1\x94"
+#define GNT_KEY_DEL "\033\xe0\x53"
+#define GNT_KEY_INS "\033\xe0\x52"
+#define GNT_KEY_BACK_TAB "\033\xe1\x94"
 
-#define GNT_KEY_F1 "\xe1\x3b"
-#define GNT_KEY_F2 "\xe1\x3c"
-#define GNT_KEY_F3 "\xe1\x3d"
-#define GNT_KEY_F4 "\xe1\x3e"
-#define GNT_KEY_F5 "\xe1\x3f"
-#define GNT_KEY_F6 "\xe1\x40"
-#define GNT_KEY_F7 "\xe1\x41"
-#define GNT_KEY_F8 "\xe1\x42"
-#define GNT_KEY_F9 "\xe1\x43"
-#define GNT_KEY_F10 "\xe1\x44"
-#define GNT_KEY_F11 "\xe0\x85"
-#define GNT_KEY_F12 "\xe0\x86"
+#define GNT_KEY_F1 "\033\xe1\x3b"
+#define GNT_KEY_F2 "\033\xe1\x3c"
+#define GNT_KEY_F3 "\033\xe1\x3d"
+#define GNT_KEY_F4 "\033\xe1\x3e"
+#define GNT_KEY_F5 "\033\xe1\x3f"
+#define GNT_KEY_F6 "\033\xe1\x40"
+#define GNT_KEY_F7 "\033\xe1\x41"
+#define GNT_KEY_F8 "\033\xe1\x42"
+#define GNT_KEY_F9 "\033\xe1\x43"
+#define GNT_KEY_F10 "\033\xe1\x44"
+#define GNT_KEY_F11 "\033\xe0\x85"
+#define GNT_KEY_F12 "\033\xe0\x86"
 
 #else
 
diff --git a/finch/libgnt/gntmain.c b/finch/libgnt/gntmain.c
--- a/finch/libgnt/gntmain.c
+++ b/finch/libgnt/gntmain.c
@@ -66,6 +66,7 @@
 #ifdef _WIN32
 #undef _getch
 #undef getch
+#include <windows.h>
 #include <conio.h>
 #endif
 
@@ -247,22 +248,34 @@ static gboolean
 io_invoke(GIOChannel *source, GIOCondition cond, gpointer null)
 {
 #ifdef _WIN32
+	/* We need:
+	 * - 1 for escape prefix
+	 * - 6 for gunichar-to-gchar conversion (see g_unichar_to_utf8)
+	 * - 1 for the terminating NUL
+	 * or:
+	 * - 1 for escape prefix
+	 * - 1 for special key prefix
+	 * - 1 for the key
+	 * - 1 for the terminating NUL
+	 */
 	gchar keys[8];
 	gchar *k = keys;
 	int ch;
 	gboolean is_special = FALSE;
+	gboolean is_escape = FALSE;
 
 	if (wm->mode == GNT_KP_MODE_WAIT_ON_CHILD)
 		return FALSE;
 
 	if (HOLDING_ESCAPE) {
+		is_escape = TRUE;
 		*k = '\033';
 		k++;
 		g_source_remove(escape_stuff.timer);
 		escape_stuff.timer = 0;
 	}
 
-	ch = _getch(); /* we could use _getch_nolock */
+	ch = _getwch(); /* we could use _getwch_nolock */
 
 	/* a small hack - we don't want to put NUL anywhere */
 	if (ch == 0x00)
@@ -270,14 +283,16 @@ io_invoke(GIOChannel *source, GIOConditi
 
 	if (ch == 0xE0 || ch == 0xE1) {
 		is_special = TRUE;
+		if (!is_escape) {
+			*k = '\033';
+			k++;
+		}
 		*k = ch;
 		k++;
-		ch = _getch();
+		ch = _getwch();
 	}
-	k[0] = ch;
-	k[1] = '\0';
 
-	if (ch == 0x1B && !is_special) { /* ESC */
+	if (ch == 0x1B && !is_special) { /* ESC key */
 		escape_stuff.timer = g_timeout_add(250, escape_timeout, NULL);
 		return TRUE;
 	}
@@ -285,16 +300,26 @@ io_invoke(GIOChannel *source, GIOConditi
 	if (wm)
 		gnt_wm_set_event_stack(wm, TRUE);
 
-	if (!is_special) {
-		gchar *converted;
-		gsize converted_len = 0;
+	if (is_special) {
+		if (ch > 0xFF) {
+			gnt_warning("a special key out of gchar range (%d)", ch);
+			return TRUE;
+		}
+		*k = ch;
+		k++;
+	} else {
+		gint result_len;
 
-		converted = g_locale_to_utf8(k, 1, NULL, &converted_len, NULL);
-		if (converted_len > 0 && converted_len <= 4) {
-			memcpy(k, converted, converted_len);
-			k[converted_len] = '\0';
-		}
+		result_len = g_unichar_to_utf8(ch, k);
+		k += result_len;
 	}
+	*k = '\0';
+
+#if 0
+	gnt_warning("a key: [%s] %#x %#x %#x %#x %#x %#x", keys,
+		(guchar)keys[0], (guchar)keys[1], (guchar)keys[2],
+		(guchar)keys[3], (guchar)keys[4], (guchar)keys[5]);
+#endif
 
 	/* TODO: we could call detect_mouse_action here, but no
 	 * events are triggered (yet?) for mouse on win32.
@@ -554,6 +579,12 @@ void gnt_init()
 	if (channel)
 		return;
 
+#ifdef _WIN32
+	/* UTF-8 for input */
+	/* TODO: check it with NO_WIDECHAR. */
+	SetConsoleCP(65001);
+#endif
+
 	locale = setlocale(LC_ALL, "");
 
 	setup_io();



More information about the Commits mailing list