changeset 91099:8bbec66c0718

Include imm.h. (get_composition_string_fn, get_ime_context_fn): New optional system functions. (globals_of_w32fns): Load them from imm32.dll. (ignore_ime_char): New flag. (w32_wnd_proc): Handle WM_UNICHAR, WM_IME_CHAR and WM_IME_ENDCOMPOSITION.
author Jason Rumney <jasonr@gnu.org>
date Sat, 17 Nov 2007 03:01:50 +0000
parents bbf4813494da
children a6d077e6a893
files src/w32fns.c
diffstat 1 files changed, 75 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32fns.c	Sat Nov 17 03:00:47 2007 +0000
+++ b/src/w32fns.c	Sat Nov 17 03:01:50 2007 +0000
@@ -58,6 +58,7 @@
 #include <objbase.h>
 
 #include <dlgs.h>
+#include <imm.h>
 #define FILE_NAME_TEXT_FIELD edt1
 
 #ifdef USE_FONT_BACKEND
@@ -269,11 +270,20 @@
 
 typedef BOOL (WINAPI * TrackMouseEvent_Proc)
   (IN OUT LPTRACKMOUSEEVENT lpEventTrack);
+typedef LONG (WINAPI * ImmGetCompositionString_Proc)
+  (IN HIMC context, IN DWORD index, OUT LPVOID buffer, IN DWORD bufLen);
+typedef HIMC (WINAPI * ImmGetContext_Proc) (IN HWND window);
 
 TrackMouseEvent_Proc track_mouse_event_fn = NULL;
 ClipboardSequence_Proc clipboard_sequence_fn = NULL;
+ImmGetCompositionString_Proc get_composition_string_fn = NULL;
+ImmGetContext_Proc get_ime_context_fn = NULL;
+
 extern AppendMenuW_Proc unicode_append_menu;
 
+/* Flag to selectively ignore WM_IME_CHAR messages.  */
+static int ignore_ime_char = 0;
+
 /* W95 mousewheel handler */
 unsigned int msh_mousewheel = 0;
 
@@ -3162,7 +3172,6 @@
       if (windows_translate)
 	{
 	  MSG windows_msg = { hwnd, msg, wParam, lParam, 0, {0,0} };
-
 	  windows_msg.time = GetMessageTime ();
 	  TranslateMessage (&windows_msg);
 	  goto dflt;
@@ -3176,6 +3185,64 @@
 			      w32_get_key_modifiers (wParam, lParam));
       break;
 
+    case WM_UNICHAR:
+      /* WM_UNICHAR looks promising from the docs, but the exact
+         circumstances in which TranslateMessage sends it is one of those
+         Microsoft secret API things that EU and US courts are supposed
+         to have put a stop to already. Spy++ shows it being sent to Notepad
+         and other MS apps, but never to Emacs.
+
+         Some third party IMEs send it in accordance with the official
+         documentation though, so handle it here.
+
+         UNICODE_NOCHAR is used to test for support for this message.
+         TRUE indicates that the message is supported.  */
+      if (wParam == UNICODE_NOCHAR)
+        return TRUE;
+
+      {
+        W32Msg wmsg;
+        wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
+        signal_user_input ();
+        my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+      }
+      break;
+
+    case WM_IME_CHAR:
+      /* If we can't get the IME result as unicode, use default processing,
+         which will at least allow characters decodable in the system locale
+         get through.  */
+      if (!get_composition_string_fn)
+        goto dflt;
+
+      else if (!ignore_ime_char)
+        {
+          wchar_t * buffer;
+          int size, i;
+          W32Msg wmsg;
+          HIMC context = get_ime_context_fn (hwnd);
+          wmsg.dwModifiers = w32_get_key_modifiers (wParam, lParam);
+          /* Get buffer size.  */
+          size = get_composition_string_fn (context, GCS_RESULTSTR, buffer, 0);
+          buffer = alloca(size);
+          size = get_composition_string_fn (context, GCS_RESULTSTR,
+                                            buffer, size);
+          signal_user_input ();
+          for (i = 0; i < size / sizeof (wchar_t); i++)
+            {
+              my_post_msg (&wmsg, hwnd, WM_UNICHAR, (WPARAM) buffer[i],
+                           lParam);
+            }
+          /* We output the whole string above, so ignore following ones
+             until we are notified of the end of composition.  */
+          ignore_ime_char = 1;
+        }
+      break;
+
+    case WM_IME_ENDCOMPOSITION:
+      ignore_ime_char = 0;
+      goto dflt;
+
       /* Simulate middle mouse button events when left and right buttons
 	 are used together, but only if user has two button mouse. */
     case WM_LBUTTONDOWN:
@@ -9227,7 +9294,13 @@
   /* ditto for GetClipboardSequenceNumber.  */
   clipboard_sequence_fn = (ClipboardSequence_Proc)
     GetProcAddress (user32_lib, "GetClipboardSequenceNumber");
-
+  {
+    HMODULE imm32_lib = GetModuleHandle ("imm32.dll");
+    get_composition_string_fn = (ImmGetCompositionString_Proc)
+      GetProcAddress (imm32_lib, "ImmGetCompositionStringW");
+    get_ime_context_fn = (ImmGetContext_Proc)
+      GetProcAddress (imm32_lib, "ImmGetContext");
+  }
   DEFVAR_INT ("w32-ansi-code-page",
 	      &w32_ansi_code_page,
 	      doc: /* The ANSI code page used by the system.  */);