changeset 79866:2ad653187371

(w32_read_socket) <WM_CHAR>: Decode characters outside the unicode range available in MULE by locale-coding-system. Improve dbcs lead byte detection. Set event timestamp and modifiers earlier.
author Jason Rumney <jasonr@gnu.org>
date Thu, 17 Jan 2008 11:37:44 +0000
parents fecd053cc641
children f870fe63579a
files src/w32term.c
diffstat 1 files changed, 70 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32term.c	Thu Jan 17 04:06:38 2008 +0000
+++ b/src/w32term.c	Thu Jan 17 11:37:44 2008 +0000
@@ -4290,6 +4290,10 @@
 		temp_index = 0;
 	      temp_buffer[temp_index++] = msg.msg.wParam;
 
+              inev.modifiers = msg.dwModifiers;
+              XSETFRAME (inev.frame_or_window, f);
+              inev.timestamp = msg.msg.time;
+
               if (msg.msg.wParam < 128 && !dbcs_lead)
                 {
                   inev.kind = ASCII_KEYSTROKE_EVENT;
@@ -4298,20 +4302,14 @@
               else if (msg.msg.wParam < 256)
                 {
                   wchar_t code;
-
+                  char dbcs[2];
                   inev.kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
-
-                  if (IsDBCSLeadByteEx(CP_ACP, (BYTE) msg.msg.wParam))
+                  dbcs[0] = 0;
+                  dbcs[1] = (char) msg.msg.wParam;
+
+                  if (dbcs_lead)
                     {
-                      dbcs_lead = (char) msg.msg.wParam;
-                      inev.kind = NO_EVENT;
-                      break;
-                    }
-                  else if (dbcs_lead)
-                    {
-                      char dbcs[2];
                       dbcs[0] = dbcs_lead;
-                      dbcs[1] = (char) msg.msg.wParam;
                       dbcs_lead = 0;
                       if (!MultiByteToWideChar(CP_ACP, 0, dbcs, 2, &code, 1))
                         {
@@ -4322,14 +4320,19 @@
                           break;
                         }
                     }
+                  else if (IsDBCSLeadByteEx(CP_ACP, (BYTE) msg.msg.wParam))
+                    {
+                      dbcs_lead = (char) msg.msg.wParam;
+                      inev.kind = NO_EVENT;
+                      break;
+                    }
                   else
                     {
-                      char single_byte = (char) msg.msg.wParam;
-                      if (!MultiByteToWideChar(CP_ACP, 0, &single_byte, 1,
+                      if (!MultiByteToWideChar(CP_ACP, 0, &dbcs[1], 1,
                                                &code, 1))
                         {
                           /* What to do with garbage? */
-                          DebPrint (("Invalid character: %d\n", single_byte));
+                          DebPrint (("Invalid character: %d\n", dbcs[1]));
                           inev.kind = NO_EVENT;
                           break;
                         }
@@ -4355,17 +4358,67 @@
                           charset_id = charset_mule_unicode_0100_24ff;
                           code -= 0x100;
                         }
-                      else if (code < 0xE000)
+                      else if (code < 0x3400)
                         {
                           charset_id = charset_mule_unicode_2500_33ff;
                           code -= 0x2500;
                         }
-                      else
+                      else if (code >= 0xE000)
                         {
                           charset_id = charset_mule_unicode_e000_ffff;
                           code -= 0xE000;
                         }
-
+                      else
+                        {
+                          /* Not in the unicode range that we can handle in
+                             Emacs-22, so decode the original character
+                             using the locale  */
+                          int nbytes, nchars, require, i, len;
+                          unsigned char *dest;
+                          struct coding_system coding;
+
+                          if (dbcs[0] == 0)
+                            {
+                              nbytes = 1;
+                              dbcs[0] = dbcs[1];
+                            }
+                          else
+                            nbytes = 2;
+
+                          setup_coding_system (Vlocale_coding_system, &coding);
+                          coding.src_multibyte = 0;
+                          coding.dst_multibyte = 1;
+                          coding.composing = COMPOSITION_DISABLED;
+                          require = decoding_buffer_size (&coding, nbytes);
+                          dest = (unsigned char *) alloca (require);
+                          coding.mode |= CODING_MODE_LAST_BLOCK;
+
+                          decode_coding (&coding, dbcs, dest, nbytes, require);
+                          nbytes = coding.produced;
+                          nchars = coding.produced_char;
+
+                          for (i = 0; i < nbytes; i += len)
+                            {
+                              if (nchars == nbytes)
+                                {
+                                  inev.code = dest[i];
+                                  len = 1;
+                                }
+                              else
+                                inev.code = STRING_CHAR_AND_LENGTH (dest + i,
+                                                                    nbytes - 1,
+                                                                    len);
+                              inev.kind = (SINGLE_BYTE_CHAR_P (inev.code)
+                                           ? ASCII_KEYSTROKE_EVENT
+                                           : MULTIBYTE_CHAR_KEYSTROKE_EVENT);
+                              kbd_buffer_store_event_hold (&inev, hold_quit);
+                              count++;
+                            }
+                          inev.kind = NO_EVENT; /* Already handled */
+                          break;
+                        }
+
+                      /* Unicode characters from above.  */
                       c1 = (code / 96) + 32;
                       c2 = (code % 96) + 32;
                       inev.code = MAKE_CHAR (charset_id, c1, c2);
@@ -4379,9 +4432,6 @@
                   inev.kind = NO_EVENT;
                   break;
                 }
-	      inev.modifiers = msg.dwModifiers;
-	      XSETFRAME (inev.frame_or_window, f);
-	      inev.timestamp = msg.msg.time;
 	    }
 	  break;