src/w32*.c: Convert function definitions to standard C.
[bpt/emacs.git] / src / w32inevt.c
index 17cfd38..aa9fe09 100644 (file)
@@ -1,13 +1,13 @@
 /* Input event support for Emacs on the Microsoft W32 API.
-   Copyright (C) 1992, 1993, 1995, 2001, 2002, 2003, 2004,
-                 2005, 2006, 2007  Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1995, 2001, 2002, 2003, 2004, 2005, 2006,
+                 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
-GNU Emacs is free software; you can redistribute it and/or modify
+GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3, or (at your option)
-any later version.
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -15,10 +15,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU Emacs; see the file COPYING.  If not, write to
-the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA.
+along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
+/*
    Drew Bliss                   01-Oct-93
      Adapted from ntkbd.c by Tim Fleehart
 */
@@ -31,6 +30,7 @@ Boston, MA 02110-1301, USA.
 #include <stdlib.h>
 #include <stdio.h>
 #include <windows.h>
+#include <setjmp.h>
 
 #ifndef MOUSE_MOVED
 #define MOUSE_MOVED   1
@@ -39,6 +39,7 @@ Boston, MA 02110-1301, USA.
 #include "lisp.h"
 #include "keyboard.h"
 #include "frame.h"
+#include "dispextern.h"
 #include "blockinput.h"
 #include "termhooks.h"
 #include "w32heap.h"
@@ -54,9 +55,6 @@ static DWORD movement_time;
 /* from keyboard.c */
 extern void reinvoke_input_signal (void);
 
-/* from dispnew.c */
-extern int change_frame_size (FRAME_PTR, int, int, int, int);
-
 /* from w32console.c */
 extern int w32_use_full_screen_buffer;
 
@@ -83,6 +81,9 @@ extern unsigned int w32_key_to_modifier (int key);
 static INPUT_RECORD event_queue[EVENT_QUEUE_SIZE];
 static INPUT_RECORD *queue_ptr = event_queue, *queue_end = event_queue;
 
+/* Temporarily store lead byte of DBCS input sequences.  */
+static char dbcs_lead = 0;
+
 static int
 fill_queue (BOOL block)
 {
@@ -155,7 +156,7 @@ w32_kbd_mods_to_emacs (DWORD mods, WORD key)
   if (mods & SCROLLLOCK_ON)
     retval |= w32_key_to_modifier (VK_SCROLL);
 
-  /* Just in case someone wanted the original behaviour, make it
+  /* Just in case someone wanted the original behavior, make it
      optional by setting w32-capslock-is-shiftlock to t.  */
   if (NILP (Vw32_capslock_is_shiftlock)
       /* Keys that should _not_ be affected by CapsLock.  */
@@ -255,13 +256,15 @@ w32_kbd_patch_key (KEY_EVENT_RECORD *event)
                          keystate, buf, 128, 0);
       if (isdead > 0)
        {
-          char cp[20];
-          int cpId;
+         char cp[20];
+         int cpId;
 
-          GetLocaleInfo (GetThreadLocale (),
+         event->uChar.UnicodeChar = buf[isdead - 1];
+
+         GetLocaleInfo (GetThreadLocale (),
                         LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
-          cpId = atoi (cp);
-          isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
+         cpId = atoi (cp);
+         isdead = WideCharToMultiByte (cpId, 0, buf, isdead,
                                        ansi_code, 4, NULL, NULL);
        }
       else
@@ -427,8 +430,6 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
 
   if (lispy_function_keys[event->wVirtualKeyCode] == 0)
     {
-      emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
-
       if (!NILP (Vw32_recognize_altgr)
          && (event->dwControlKeyState & LEFT_CTRL_PRESSED)
          && (event->dwControlKeyState & RIGHT_ALT_PRESSED))
@@ -463,9 +464,65 @@ key_event (KEY_EVENT_RECORD *event, struct input_event *emacs_ev, int *isdead)
          else if (event->uChar.AsciiChar == 0)
            w32_kbd_patch_key (event);
        }
+
       if (event->uChar.AsciiChar == 0)
-       return 0;
-      emacs_ev->code = event->uChar.AsciiChar;
+       {
+         emacs_ev->kind = NO_EVENT;
+         return 0;
+       }
+      else if (event->uChar.AsciiChar > 0)
+       {
+         emacs_ev->kind = ASCII_KEYSTROKE_EVENT;
+         emacs_ev->code = event->uChar.AsciiChar;
+       }
+      else if (event->uChar.UnicodeChar > 0)
+       {
+         emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+         emacs_ev->code = event->uChar.UnicodeChar;
+       }
+      else
+       {
+         /* Fallback for non-Unicode versions of Windows.  */
+         wchar_t code;
+         char dbcs[2];
+          char cp[20];
+          int cpId;
+
+         /* Get the codepage to interpret this key with.  */
+          GetLocaleInfo (GetThreadLocale (),
+                        LOCALE_IDEFAULTANSICODEPAGE, cp, 20);
+          cpId = atoi (cp);
+
+         dbcs[0] = dbcs_lead;
+         dbcs[1] = event->uChar.AsciiChar;
+         if (dbcs_lead)
+           {
+             dbcs_lead = 0;
+             if (!MultiByteToWideChar (cpId, 0, dbcs, 2, &code, 1))
+               {
+                 /* Garbage  */
+                 DebPrint (("Invalid DBCS sequence: %d %d\n",
+                            dbcs[0], dbcs[1]));
+                 emacs_ev->kind = NO_EVENT;
+               }
+           }
+         else if (IsDBCSLeadByteEx (cpId, dbcs[1]))
+           {
+             dbcs_lead = dbcs[1];
+             emacs_ev->kind = NO_EVENT;
+           }
+         else
+           {
+             if (!MultiByteToWideChar (cpId, 0, &dbcs[1], 1, &code, 1))
+               {
+                 /* Garbage  */
+                 DebPrint (("Invalid character: %d\n", dbcs[1]));
+                 emacs_ev->kind = NO_EVENT;
+               }
+           }
+         emacs_ev->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT;
+         emacs_ev->code = code;
+       }
     }
   else
     {
@@ -622,12 +679,12 @@ resize_event (WINDOW_BUFFER_SIZE_RECORD *event)
 {
   FRAME_PTR f = get_frame ();
 
-  change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1);
+  change_frame_size (f, event->dwSize.Y, event->dwSize.X, 0, 1, 0);
   SET_FRAME_GARBAGED (f);
 }
 
 static void
-maybe_generate_resize_event ()
+maybe_generate_resize_event (void)
 {
   CONSOLE_SCREEN_BUFFER_INFO info;
   FRAME_PTR f = get_frame ();
@@ -639,7 +696,7 @@ maybe_generate_resize_event ()
   change_frame_size (f,
                     1 + info.srWindow.Bottom - info.srWindow.Top,
                     1 + info.srWindow.Right - info.srWindow.Left,
-                    0, 0);
+                    0, 0, 0);
 }
 
 int