This commit was manufactured by cvs2svn to create branch 'XEmacs-21_4'.
[chise/xemacs-chise.git.1] / src / event-msw.c
index 3911ef6..e18c1e6 100644 (file)
@@ -90,13 +90,6 @@ typedef NMHDR *LPNMHDR;
 /* Timer ID used for button2 emulation */
 #define BUTTON_2_TIMER_ID 1
 
-extern Lisp_Object
-mswindows_get_toolbar_button_text (struct frame* f, int command_id);
-extern Lisp_Object
-mswindows_handle_toolbar_wm_command (struct frame* f, HWND ctrl, WORD id);
-extern Lisp_Object
-mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, WORD id);
-
 static Lisp_Object mswindows_find_frame (HWND hwnd);
 static Lisp_Object mswindows_find_console (HWND hwnd);
 static Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods,
@@ -135,6 +128,7 @@ static HANDLE mswindows_waitable_handles[MAX_WAITABLE];
 /* Number of wait handles */
 static int mswindows_waitable_count=0;
 #endif /* HAVE_MSG_SELECT */
+
 /* Brush for painting widgets */
 static HBRUSH widget_brush = 0;
 static LONG    last_widget_brushed = 0;
@@ -639,8 +633,8 @@ struct winsock_stream
   SOCKET s;                    /* Socket handle (which is a Win32 handle)   */
   OVERLAPPED ov;               /* Overlapped I/O structure                  */
   void* buffer;                        /* Buffer. Allocated for input stream only   */
-  unsigned int bufsize;                /* Number of bytes last read                 */
-  unsigned int bufpos;         /* Position in buffer for next fetch         */
+  unsigned long bufsize;       /* Number of bytes last read                 */
+  unsigned long bufpos;                /* Position in buffer for next fetch         */
   unsigned int error_p :1;     /* I/O Error seen                            */
   unsigned int eof_p :1;       /* EOF Error seen                            */
   unsigned int pending_p :1;   /* There is a pending I/O operation          */
@@ -719,7 +713,7 @@ winsock_reader (Lstream *stream, unsigned char *data, size_t size)
 }
 
 static ssize_t
-winsock_writer (Lstream *stream, CONST unsigned char *data, size_t size)
+winsock_writer (Lstream *stream, const unsigned char *data, size_t size)
 {
   struct winsock_stream *str = WINSOCK_STREAM_DATA (stream);
 
@@ -792,7 +786,7 @@ winsock_was_blocked_p (Lstream *stream)
 }
 
 static Lisp_Object
-make_winsock_stream_1 (SOCKET s, LPARAM param, CONST char *mode)
+make_winsock_stream_1 (SOCKET s, LPARAM param, const char *mode)
 {
   Lisp_Object obj;
   Lstream *lstr = Lstream_new (lstream_winsock, mode);
@@ -860,7 +854,7 @@ init_winsock_stream (void)
 /************************************************************************/
 
 static int
-mswindows_user_event_p (struct Lisp_Event* sevt)
+mswindows_user_event_p (Lisp_Event* sevt)
 {
   return (sevt->event_type == key_press_event
          || sevt->event_type == button_press_event
@@ -896,10 +890,11 @@ mswindows_enqueue_misc_user_event (Lisp_Object channel, Lisp_Object function,
                                   Lisp_Object object)
 {
   Lisp_Object event = Fmake_event (Qnil, Qnil);
-  struct Lisp_Event* e = XEVENT (event);
+  Lisp_Event* e = XEVENT (event);
 
   e->event_type = misc_user_event;
   e->channel = channel;
+  e->timestamp = GetTickCount ();
   e->event.misc.function = function;
   e->event.misc.object = object;
 
@@ -907,24 +902,24 @@ mswindows_enqueue_misc_user_event (Lisp_Object channel, Lisp_Object function,
 }
 
 void
-mswindows_enqueue_magic_event (HWND hwnd, UINT message)
+mswindows_enqueue_magic_event (HWND hwnd, UINT msg)
 {
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-  struct Lisp_Event* event = XEVENT (emacs_event);
+  Lisp_Event* event = XEVENT (emacs_event);
 
   event->channel = hwnd ? mswindows_find_frame (hwnd) : Qnil;
   event->timestamp = GetMessageTime();
   event->event_type = magic_event;
-  EVENT_MSWINDOWS_MAGIC_TYPE (event) = message;
+  EVENT_MSWINDOWS_MAGIC_TYPE (event) = msg;
 
   mswindows_enqueue_dispatch_event (emacs_event);
 }
 
 static void
-mswindows_enqueue_process_event (struct Lisp_Process* p)
+mswindows_enqueue_process_event (Lisp_Process* p)
 {
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-  struct Lisp_Event* event = XEVENT (emacs_event);
+  Lisp_Event* event = XEVENT (emacs_event);
   Lisp_Object process;
   XSETPROCESS (process, p);
 
@@ -936,7 +931,7 @@ mswindows_enqueue_process_event (struct Lisp_Process* p)
 }
 
 static void
-mswindows_enqueue_mouse_button_event (HWND hwnd, UINT message, POINTS where, DWORD when)
+mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where, DWORD when)
 {
 
   /* We always use last message time, because mouse button
@@ -944,19 +939,19 @@ mswindows_enqueue_mouse_button_event (HWND hwnd, UINT message, POINTS where, DWO
      recognition will fail */
 
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-  struct Lisp_Event* event = XEVENT(emacs_event);
+  Lisp_Event* event = XEVENT(emacs_event);
 
   event->channel = mswindows_find_frame(hwnd);
   event->timestamp = when;
   event->event.button.button =
-    (message==WM_LBUTTONDOWN || message==WM_LBUTTONUP) ? 1 :
-    ((message==WM_RBUTTONDOWN || message==WM_RBUTTONUP) ? 3 : 2);
+    (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONUP) ? 1 :
+    ((msg==WM_RBUTTONDOWN || msg==WM_RBUTTONUP) ? 3 : 2);
   event->event.button.x = where.x;
   event->event.button.y = where.y;
   event->event.button.modifiers = mswindows_modifier_state (NULL, 0);
 
-  if (message==WM_LBUTTONDOWN || message==WM_MBUTTONDOWN ||
-      message==WM_RBUTTONDOWN)
+  if (msg==WM_LBUTTONDOWN || msg==WM_MBUTTONDOWN ||
+      msg==WM_RBUTTONDOWN)
     {
       event->event_type = button_press_event;
       SetCapture (hwnd);
@@ -981,7 +976,7 @@ static void
 mswindows_enqueue_keypress_event (HWND hwnd, Lisp_Object keysym, int mods)
 {
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-  struct Lisp_Event* event = XEVENT(emacs_event);
+  Lisp_Event* event = XEVENT(emacs_event);
 
   event->channel = mswindows_find_console(hwnd);
   event->timestamp = GetMessageTime();
@@ -999,7 +994,7 @@ static Lisp_Object
 mswindows_dequeue_dispatch_event ()
 {
   Lisp_Object event;
-  struct Lisp_Event* sevt;
+  Lisp_Event* sevt;
 
   assert (!NILP(mswindows_u_dispatch_event_queue) ||
          !NILP(mswindows_s_dispatch_event_queue));
@@ -1033,7 +1028,7 @@ mswindows_dequeue_dispatch_event ()
  */
 
 Lisp_Object
-mswindows_cancel_dispatch_event (struct Lisp_Event *match)
+mswindows_cancel_dispatch_event (Lisp_Event *match)
 {
   Lisp_Object event;
   Lisp_Object previous_event = Qnil;
@@ -1048,7 +1043,7 @@ mswindows_cancel_dispatch_event (struct Lisp_Event *match)
 
   EVENT_CHAIN_LOOP (event, *head)
     {
-      struct Lisp_Event *e = XEVENT (event);
+      Lisp_Event *e = XEVENT (event);
       if ((e->event_type == match->event_type) &&
          ((e->event_type == timeout_event) ?
           (e->event.timeout.interval_id == match->event.timeout.interval_id) :
@@ -1231,20 +1226,41 @@ mswindows_pump_outstanding_events (void)
   return result;
 }
 
+/*
+ * KEYBOARD_ONLY_P is set to non-zero when we are called from
+ * QUITP, and are interesting in keyboard messages only.
+ */
 static void
 mswindows_drain_windows_queue ()
 {
   MSG msg;
+
+  /* should call mswindows_need_event_in_modal_loop() if in modal loop */
+  assert (!mswindows_in_modal_loop);
+
   while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
     {
-      /* we have to translate messages that are not sent to the main
-         window. this is so that key presses work ok in things like
-         edit fields. however, we *musn't* translate message for the
+      /* We have to translate messages that are not sent to the main
+         window. This is so that key presses work ok in things like
+         edit fields. However, we *musn't* translate message for the
          main window as this is handled in the wnd proc. */
-      if ( GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD )
+      if (GetWindowLong (msg.hwnd, GWL_STYLE) & WS_CHILD)
        {
          TranslateMessage (&msg);
        }
+      else if (msg.message == WM_PAINT)
+       {
+         /* hdc will be NULL unless this is a subwindow - in which case we
+            shouldn't have received a paint message for it here. */
+         assert (msg.wParam == 0);
+
+         /* Queue a magic event for handling when safe */
+         mswindows_enqueue_magic_event (msg.hwnd, WM_PAINT);
+
+         /* Don't dispatch. WM_PAINT is always the last message in the
+            queue so it's OK to just return. */
+         return;
+       }
       DispatchMessage (&msg);
       mswindows_unmodalize_signal_maybe ();
     }
@@ -1308,10 +1324,6 @@ mswindows_need_event (int badly_p)
       return;
     }
 
-  /* Have to drain Windows message queue first, otherwise, we may miss
-     quit char when called from quit_p */
-  mswindows_drain_windows_queue ();
-
   while (NILP (mswindows_u_dispatch_event_queue)
         && NILP (mswindows_s_dispatch_event_queue))
     {
@@ -1354,7 +1366,7 @@ mswindows_need_event (int badly_p)
                {
                  struct console *c = tty_find_console_from_fd (i);
                  Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-                 struct Lisp_Event* event = XEVENT (emacs_event);
+                 Lisp_Event* event = XEVENT (emacs_event);
 
                  assert (c);
                  if (read_event_from_tty_or_stream_desc (event, c, i))
@@ -1372,7 +1384,7 @@ mswindows_need_event (int badly_p)
                {
                  if (FD_ISSET (i, &process_only_mask))
                    {
-                     struct Lisp_Process *p =
+                     Lisp_Process *p =
                        get_process_from_usid (FD_TO_USID(i));
 
                      mswindows_enqueue_process_event (p);
@@ -1428,7 +1440,7 @@ mswindows_need_event (int badly_p)
       {
        int ix = active - WAIT_OBJECT_0;
        /* First, try to find which process' output has signaled */
-       struct Lisp_Process *p =
+       Lisp_Process *p =
          get_process_from_usid (HANDLE_TO_USID (mswindows_waitable_handles[ix]));
        if (p != NULL)
          {
@@ -1463,7 +1475,7 @@ static void CALLBACK
 mswindows_wm_timer_callback (HWND hwnd, UINT umsg, UINT id_timer, DWORD dwtime)
 {
   Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
-  struct Lisp_Event *event = XEVENT (emacs_event);
+  Lisp_Event *event = XEVENT (emacs_event);
 
   if (KillTimer (NULL, id_timer))
     --mswindows_pending_timers_count;
@@ -1504,7 +1516,7 @@ mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv,
          { mswindows_dde_service, mswindows_dde_topic_system }, { 0, 0 } };
 
        if (!(hszItem  || DdeCmpStringHandles (hszItem, mswindows_dde_service)) &&
-           !(hszTopic || DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)));
+           !(hszTopic || DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system)))
          return (DdeCreateDataHandle (mswindows_dde_mlid, (LPBYTE)pairs,
                                       sizeof (pairs), 0L, 0, uFmt, 0));
       }
@@ -1514,14 +1526,14 @@ mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv,
       if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system))
        {
          DWORD len = DdeGetData (hdata, NULL, 0, 0);
-         char *cmd = alloca (len+1);
+         LPBYTE cmd = (LPBYTE) alloca (len+1);
          char *end;
          char *filename;
          struct gcpro gcpro1, gcpro2;
           Lisp_Object l_dndlist = Qnil;
          Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
          Lisp_Object frmcons, devcons, concons;
-         struct Lisp_Event *event = XEVENT (emacs_event);
+         Lisp_Event *event = XEVENT (emacs_event);
 
          DdeGetData (hdata, cmd, len, 0);
          cmd[len] = '\0';
@@ -1599,6 +1611,54 @@ mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv,
 #endif
 
 /*
+ * Helper to do repainting - repaints can happen both from the windows
+ * procedure and from magic events
+ */
+void
+mswindows_handle_paint (struct frame *frame)
+  {
+    HWND hwnd = FRAME_MSWINDOWS_HANDLE (frame);
+
+    /* According to the docs we need to check GetUpdateRect() before
+       actually doing a WM_PAINT */
+    if (GetUpdateRect (hwnd, NULL, FALSE))
+      {
+       PAINTSTRUCT paintStruct;
+       int x, y, width, height;
+
+       BeginPaint (hwnd, &paintStruct);
+       x = paintStruct.rcPaint.left;
+       y = paintStruct.rcPaint.top;
+       width = paintStruct.rcPaint.right - paintStruct.rcPaint.left;
+       height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top;
+       /* Normally we want to ignore expose events when child
+          windows are unmapped, however once we are in the guts of
+          WM_PAINT we need to make sure that we don't register
+          unmaps then because they will not actually occur. */
+       if (!check_for_ignored_expose (frame, x, y, width, height))
+         {
+           hold_ignored_expose_registration = 1;
+           mswindows_redraw_exposed_area (frame, x, y, width, height);
+           hold_ignored_expose_registration = 0;
+         }
+       EndPaint (hwnd, &paintStruct);
+      }
+  }
+
+/*
+ * Returns 1 if a key is a real modifier or special key, which 
+ * is better handled by DefWindowProc
+ */
+static int
+key_needs_default_processing_p (UINT vkey)
+{
+  if (mswindows_meta_activates_menu && vkey == VK_MENU)
+    return 1;
+
+  return 0;
+}
+
+/*
  * The windows procedure for the window class XEMACS_CLASS
  */
 LRESULT WINAPI
@@ -1609,7 +1669,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   Lisp_Object emacs_event = Qnil;
   Lisp_Object fobj = Qnil;
 
-  struct Lisp_Event *event;
+  Lisp_Event *event;
   struct frame *frame;
   struct mswindows_frame* msframe;
 
@@ -1653,7 +1713,10 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          SetKeyboardState (keymap);
        }
     };
-    goto defproc;
+    if (key_needs_default_processing_p (wParam))
+      goto defproc;
+    else
+      break;
 
   case WM_KEYDOWN:
   case WM_SYSKEYDOWN:
@@ -1709,7 +1772,8 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          /* Clear control and alt modifiers unless AltGr is pressed */
          keymap [VK_RCONTROL] = 0;
          keymap [VK_LMENU] = 0;
-         if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80) || !(keymap [VK_RMENU] & 0x80))
+         if (!has_AltGr || !(keymap [VK_LCONTROL] & 0x80)
+             || !(keymap [VK_RMENU] & 0x80))
            {
              keymap [VK_LCONTROL] = 0;
              keymap [VK_CONTROL] = 0;
@@ -1745,10 +1809,10 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          SetKeyboardState (keymap_orig);
        } /* else */
     }
-    /* F10 causes menu activation by default. We do not want this */
-    if (wParam != VK_F10 && (mswindows_meta_activates_menu || wParam != VK_MENU))
+    if (key_needs_default_processing_p (wParam))
       goto defproc;
-    break;
+    else
+      break;
 
   case WM_MBUTTONDOWN:
   case WM_MBUTTONUP:
@@ -1964,8 +2028,9 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
            {
              /* I think this is safe since the text will only go away
                  when the toolbar does...*/
-             GET_C_STRING_EXT_DATA_ALLOCA (btext, FORMAT_OS,
-                                           tttext->lpszText);
+             TO_EXTERNAL_FORMAT (LISP_STRING, btext,
+                                 C_STRING_ALLOCA, tttext->lpszText,
+                                 Qnative);
            }
 #endif
        }
@@ -1980,11 +2045,11 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       else if (nmhdr->code == TCN_SELCHANGE)
        {
          TC_ITEM item;
-         int index = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
+         int idx = SendMessage (nmhdr->hwndFrom, TCM_GETCURSEL, 0, 0);
          frame = XFRAME (mswindows_find_frame (hwnd));
 
          item.mask = TCIF_PARAM;
-         SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)index,
+         SendMessage (nmhdr->hwndFrom, TCM_GETITEM, (WPARAM)idx,
                       (LPARAM)&item);
 
          mswindows_handle_gui_wm_command (frame, 0, item.lParam);
@@ -1993,37 +2058,14 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     break;
 
   case WM_PAINT:
-    {
-      /* According to the docs we need to check GetUpdateRect() before
-         actually doing a WM_PAINT */
-      if (GetUpdateRect (hwnd, NULL, FALSE))
-       {
-         PAINTSTRUCT paintStruct;
-         int x, y, width, height;
-
-         frame = XFRAME (mswindows_find_frame (hwnd));
-
-         BeginPaint (hwnd, &paintStruct);
-         x = paintStruct.rcPaint.left;
-         y = paintStruct.rcPaint.top;
-         width = paintStruct.rcPaint.right - paintStruct.rcPaint.left;
-         height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top;
-         /* Normally we want to ignore expose events when child
-            windows are unmapped, however once we are in the guts of
-            WM_PAINT we need to make sure that we don't register
-            unmaps then because they will not actually occur. */
-         if (!check_for_ignored_expose (frame, x, y, width, height))
-           {
-             hold_ignored_expose_registration = 1;
-             mswindows_redraw_exposed_area (frame, x, y, width, height);
-             hold_ignored_expose_registration = 0;
-           }
-
-         EndPaint (hwnd, &paintStruct);
-       }
-      else
-       goto defproc;
-    }
+    /* hdc will be NULL unless this is a subwindow - in which case we
+       shouldn't have received a paint message for it here. */
+    assert (wParam == 0);
+
+    /* Can't queue a magic event because windows goes modal and sends paint 
+       messages directly to the windows procedure when doing solid drags
+       and the message queue doesn't get processed. */
+    mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd)));
     break;
 
   case WM_SIZE:
@@ -2264,9 +2306,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
          VOID_TO_LISP (image_instance, ii);
          if (IMAGE_INSTANCEP (image_instance)
              &&
-             IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET)
-             &&
-             !NILP (XIMAGE_INSTANCE_WIDGET_FACE (image_instance)))
+             IMAGE_INSTANCE_TYPE_P (image_instance, IMAGE_WIDGET))
            {
              /* set colors for the buttons */
              HDC hdc = (HDC)wParam;
@@ -2320,7 +2360,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 
       GCPRO3 (emacs_event, l_dndlist, l_item);
 
-      if (!DragQueryPoint ((HANDLE) wParam, &point))
+      if (!DragQueryPoint ((HDROP) wParam, &point))
        point.x = point.y = -1;         /* outside client area */
 
       event->event_type = misc_user_event;
@@ -2332,10 +2372,10 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       event->event.misc.y = point.y;
       event->event.misc.function = Qdragdrop_drop_dispatch;
 
-      filecount = DragQueryFile ((HANDLE) wParam, 0xffffffff, NULL, 0);
+      filecount = DragQueryFile ((HDROP) wParam, 0xffffffff, NULL, 0);
       for (i=0; i<filecount; i++)
        {
-         len = DragQueryFile ((HANDLE) wParam, i, NULL, 0);
+         len = DragQueryFile ((HDROP) wParam, i, NULL, 0);
          /* The URLs that we make here aren't correct according to section
           * 3.10 of rfc1738 because they're missing the //<host>/ part and
           * because they may contain reserved characters. But that's OK. */
@@ -2349,14 +2389,14 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 #else
          filename = (char *)xmalloc (len+6);
          strcpy (filename, "file:");
-         DragQueryFile ((HANDLE) wParam, i, filename+5, len+1);
+         DragQueryFile ((HDROP) wParam, i, filename+5, len+1);
          dostounix_filename (filename+5);
 #endif
          l_item = make_string (filename, strlen (filename));
          l_dndlist = Fcons (l_item, l_dndlist);
          xfree (filename);
        }
-      DragFinish ((HANDLE) wParam);
+      DragFinish ((HDROP) wParam);
 
       event->event.misc.object = Fcons (Qdragdrop_URL, l_dndlist);
       mswindows_enqueue_dispatch_event (emacs_event);
@@ -2617,7 +2657,7 @@ emacs_mswindows_add_timeout (EMACS_TIME thyme)
 static void
 emacs_mswindows_remove_timeout (int id)
 {
-  struct Lisp_Event match_against;
+  Lisp_Event match_against;
   Lisp_Object emacs_event;
 
   if (KillTimer (NULL, id))
@@ -2653,7 +2693,7 @@ emacs_mswindows_event_pending_p (int user_p)
  * Return the next event
  */
 static void
-emacs_mswindows_next_event (struct Lisp_Event *emacs_event)
+emacs_mswindows_next_event (Lisp_Event *emacs_event)
 {
   Lisp_Object event, event2;
 
@@ -2669,13 +2709,17 @@ emacs_mswindows_next_event (struct Lisp_Event *emacs_event)
  * Handle a magic event off the dispatch queue.
  */
 static void
-emacs_mswindows_handle_magic_event (struct Lisp_Event *emacs_event)
+emacs_mswindows_handle_magic_event (Lisp_Event *emacs_event)
 {
   switch (EVENT_MSWINDOWS_MAGIC_TYPE(emacs_event))
     {
     case XM_BUMPQUEUE:
       break;
 
+    case WM_PAINT:
+      mswindows_handle_paint (XFRAME (EVENT_CHANNEL (emacs_event)));
+      break;
+
     case WM_SETFOCUS:
     case WM_KILLFOCUS:
       {
@@ -2723,7 +2767,7 @@ emacs_mswindows_handle_magic_event (struct Lisp_Event *emacs_event)
 
 #ifndef HAVE_MSG_SELECT
 static HANDLE
-get_process_input_waitable (struct Lisp_Process *process)
+get_process_input_waitable (Lisp_Process *process)
 {
   Lisp_Object instr, outstr, p;
   XSETPROCESS (p, process);
@@ -2739,7 +2783,7 @@ get_process_input_waitable (struct Lisp_Process *process)
 }
 
 static void
-emacs_mswindows_select_process (struct Lisp_Process *process)
+emacs_mswindows_select_process (Lisp_Process *process)
 {
   HANDLE hev = get_process_input_waitable (process);
 
@@ -2764,7 +2808,7 @@ emacs_mswindows_select_process (struct Lisp_Process *process)
 }
 
 static void
-emacs_mswindows_unselect_process (struct Lisp_Process *process)
+emacs_mswindows_unselect_process (Lisp_Process *process)
 {
   /* Process handle is removed in the event loop as soon
      as it is signaled, so don't bother here about it */
@@ -2798,38 +2842,37 @@ emacs_mswindows_unselect_console (struct console *con)
 static void
 emacs_mswindows_quit_p (void)
 {
-  MSG msg;
-
   /* Quit cannot happen in modal loop: all program
      input is dedicated to Windows. */
   if (mswindows_in_modal_loop)
     return;
 
-  /* Drain windows queue. This sets up number of quit characters in the queue
-   * (and also processes wm focus change, move, resize, etc messages).
-   * We don't want to process WM_PAINT messages because this function can be
-   * called from almost anywhere and the windows' states may be changing. */
-  while (PeekMessage (&msg, NULL, 0, WM_PAINT-1, PM_REMOVE) ||
-        PeekMessage (&msg, NULL, WM_PAINT+1, WM_USER-1, PM_REMOVE))
-      DispatchMessage (&msg);
+  /* Drain windows queue. This sets up number of quit characters in
+     the queue */
+  mswindows_drain_windows_queue ();
 
   if (mswindows_quit_chars_count > 0)
     {
       /* Yes there's a hidden one... Throw it away */
-      struct Lisp_Event match_against;
+      Lisp_Event match_against;
       Lisp_Object emacs_event;
+      int critical_p = 0;
 
       match_against.event_type = key_press_event;
       match_against.event.key.modifiers = FAKE_MOD_QUIT;
 
-      emacs_event = mswindows_cancel_dispatch_event (&match_against);
-      assert (!NILP (emacs_event));
+      while (mswindows_quit_chars_count-- > 0)
+       {
+         emacs_event = mswindows_cancel_dispatch_event (&match_against);
+         assert (!NILP (emacs_event));
+         
+         if (XEVENT(emacs_event)->event.key.modifiers & MOD_SHIFT)
+           critical_p = 1;
 
-      Vquit_flag = (XEVENT(emacs_event)->event.key.modifiers & MOD_SHIFT
-                   ? Qcritical : Qt);
+         Fdeallocate_event(emacs_event);
+       }
 
-      Fdeallocate_event(emacs_event);
-      --mswindows_quit_chars_count;
+      Vquit_flag = critical_p ? Qcritical : Qt;
     }
 }
 
@@ -2941,7 +2984,7 @@ emacs_mswindows_delete_stream_pair (Lisp_Object instream,
    If we've still got pointers to it in this file, we're gonna lose hard.
  */
 void
-debug_process_finalization (struct Lisp_Process *p)
+debug_process_finalization (Lisp_Process *p)
 {
 #if 0 /* #### */
   Lisp_Object instr, outstr;
@@ -2978,9 +3021,9 @@ reinit_vars_of_event_mswindows (void)
   mswindows_event_stream->unselect_console_cb  = emacs_mswindows_unselect_console;
 #ifdef HAVE_MSG_SELECT
   mswindows_event_stream->select_process_cb    =
-    (void (*)(struct Lisp_Process*))event_stream_unixoid_select_process;
+    (void (*)(Lisp_Process*))event_stream_unixoid_select_process;
   mswindows_event_stream->unselect_process_cb  =
-    (void (*)(struct Lisp_Process*))event_stream_unixoid_unselect_process;
+    (void (*)(Lisp_Process*))event_stream_unixoid_unselect_process;
   mswindows_event_stream->create_stream_pair_cb = event_stream_unixoid_create_stream_pair;
   mswindows_event_stream->delete_stream_pair_cb = event_stream_unixoid_delete_stream_pair;
 #else
@@ -3004,7 +3047,7 @@ vars_of_event_mswindows (void)
   mswindows_s_dispatch_event_queue = Qnil;
   staticpro (&mswindows_s_dispatch_event_queue);
   mswindows_s_dispatch_event_queue_tail = Qnil;
-  pdump_wire (&mswindows_u_dispatch_event_queue_tail);
+  pdump_wire (&mswindows_s_dispatch_event_queue_tail);
 
   mswindows_error_caught_in_modal_loop = Qnil;
   staticpro (&mswindows_error_caught_in_modal_loop);