changeset 20234:54db6b11351b draft

-Fix: [Win32] Handle Unicode characters from outside the BMP correctly.
author Michael Lutz <michi@icosahedron.de>
date Sun, 24 Mar 2013 01:00:46 +0100 (2013-03-24)
parents 98cec258f8e1
children 45ee665489d3
files src/string_func.h src/video/win32_v.cpp
diffstat 2 files changed, 52 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/src/string_func.h
+++ b/src/string_func.h
@@ -190,6 +190,38 @@
 	return c == 0x0020 /* SPACE */ || c == 0x3000; /* IDEOGRAPHIC SPACE */
 }
 
+/**
+ * Is the given character a lead surrogate code point?
+ * @param c The character to test.
+ * @return True if the character is a lead surrogate code point.
+ */
+static inline bool IsUTF16LeadSurrogate(uint c)
+{
+	return c >= 0xD800 && c <= 0xDBFF;
+}
+
+/**
+ * Is the given character a lead surrogate code point?
+ * @param c The character to test.
+ * @return True if the character is a lead surrogate code point.
+ */
+static inline bool IsUTF16TrailSurrogate(uint c)
+{
+	return c >= 0xDC00 && c <= 0xDFFF;
+}
+
+/**
+ * Convert an UTF-16 surrogate pair to the corresponding Unicode character.
+ * @param lead Lead surrogate code point.
+ * @param trail Trail surrogate code point.
+ * @return Decoded Unicode character.
+ */
+static inline WChar DecodeUTF16Surrogate(uint lead, uint trail)
+{
+	return 0x10000 + ((lead - 0xD800) << 10) | (trail - 0xDC00);
+}
+
+
 /* Needed for NetBSD version (so feature) testing */
 #if defined(__NetBSD__) || defined(__FreeBSD__)
 #include <sys/param.h>
--- a/src/video/win32_v.cpp
+++ b/src/video/win32_v.cpp
@@ -431,12 +431,31 @@
 }
 
 /** Forward key presses to the window system. */
-static LRESULT HandleCharMsg(uint keycode, uint charcode)
+static LRESULT HandleCharMsg(uint keycode, WChar charcode)
 {
 #if !defined(UNICODE)
 	wchar_t w;
 	int len = MultiByteToWideChar(_codepage, 0, (char*)&charcode, 1, &w, 1);
 	charcode = len == 1 ? w : 0;
+#else
+	static WChar prev_char = 0;
+
+	/* Did we get an lead surrogate? If yes, store and exit. */
+	if (IsUTF16LeadSurrogate(charcode)) {
+		if (prev_char != 0) DEBUG(driver, 1, "Got two UTF-16 lead surrogates, dropping the first one");
+		prev_char = charcode;
+		return 0;
+	}
+
+	/* Stored lead surrogate and incoming trail surrogate? Combine and forward to input handling. */
+	if (prev_char != 0) {
+		if (IsUTF16TrailSurrogate(charcode)) {
+			charcode = DecodeUTF16Surrogate(prev_char, charcode);
+		} else {
+			DEBUG(driver, 1, "Got an UTF-16 lead surrogate without a trail surrogate, dropping the lead surrogate");
+		}
+	}
+	prev_char = 0;
 #endif /* UNICODE */
 
 	HandleKeypress(keycode, charcode);