XEmacs 21.4.2 "Developer-Friendly Unix APIs".
[chise/xemacs-chise.git.1] / src / event-msw.c
index 1350d26..49be245 100644 (file)
@@ -65,7 +65,6 @@ Boston, MA 02111-1307, USA.  */
 #include "sysdep.h"
 #include "objects-msw.h"
 
-#include "events-mod.h"
 #ifdef HAVE_MSG_SELECT
 #include "sysfile.h"
 #include "console-tty.h"
@@ -87,7 +86,8 @@ typedef unsigned int SOCKET;
 
 /* Fake key modifier which is attached to a quit char event.
    Removed upon dequeueing an event */
-#define FAKE_MOD_QUIT  0x80
+#define FAKE_MOD_QUIT (1 << 20)
+#define FAKE_MOD_QUIT_CRITICAL (1 << 21)
 
 /* Timer ID used for button2 emulation */
 #define BUTTON_2_TIMER_ID 1
@@ -1048,7 +1048,8 @@ mswindows_dequeue_dispatch_event (void)
   if (sevt->event_type == key_press_event
       && (sevt->event.key.modifiers & FAKE_MOD_QUIT))
     {
-      sevt->event.key.modifiers &= ~FAKE_MOD_QUIT;
+      sevt->event.key.modifiers &=
+       ~(FAKE_MOD_QUIT | FAKE_MOD_QUIT_CRITICAL);
       --mswindows_quit_chars_count;
     }
 
@@ -1340,6 +1341,10 @@ mswindows_drain_windows_queue (void)
  * fetching WM_TIMER messages. Instead of trying to fetch a WM_TIMER
  * which will never come when there are no pending timers, which leads
  * to deadlock, we simply signal an error.
+ *
+ * It might be possible to combine this with mswindows_drain_windows_queue
+ * which fetches events when not in a modal loop.  It's not clear
+ * whether the result would be more complex than is justified.
  */
 static void
 mswindows_need_event_in_modal_loop (int badly_p)
@@ -1363,8 +1368,8 @@ mswindows_need_event_in_modal_loop (int badly_p)
        error ("Deadlock due to an attempt to call next-event in a wrong context");
 
       /* Fetch and dispatch any pending timers */
-      GetMessage (&msg, NULL, WM_TIMER, WM_TIMER);
-      DispatchMessage (&msg);
+      if (GetMessage (&msg, NULL, WM_TIMER, WM_TIMER) > 0)
+       DispatchMessage (&msg);
     }
 }
 
@@ -1380,12 +1385,6 @@ mswindows_need_event (int badly_p)
 {
   int active;
 
-  if (mswindows_in_modal_loop)
-    {
-      mswindows_need_event_in_modal_loop (badly_p);
-      return;
-    }
-
   while (NILP (mswindows_u_dispatch_event_queue)
         && NILP (mswindows_s_dispatch_event_queue))
     {
@@ -1402,6 +1401,10 @@ mswindows_need_event (int badly_p)
          EMACS_SET_SECS_USECS (sometime, 0, 0);
          EMACS_TIME_TO_SELECT_TIME (sometime, select_time_to_block);
          pointer_to_this = &select_time_to_block;
+         if (mswindows_in_modal_loop)
+           /* In modal loop with badly_p false, don't care about
+              Windows events. */
+           FD_CLR (windows_fd, &temp_mask);
        }
 
       active = select (MAXDESC, &temp_mask, 0, 0, pointer_to_this);
@@ -1415,7 +1418,10 @@ mswindows_need_event (int badly_p)
        {
          if (FD_ISSET (windows_fd, &temp_mask))
            {
-             mswindows_drain_windows_queue ();
+             if (mswindows_in_modal_loop)
+               mswindows_need_event_in_modal_loop (badly_p);
+             else
+               mswindows_drain_windows_queue ();
            }
          else
            {
@@ -1480,10 +1486,24 @@ mswindows_need_event (int badly_p)
        }
 #else
       /* Now try getting a message or process event */
+      DWORD what_events;
+      if (mswindows_in_modal_loop)
+       /* In a modal loop, only look for timer events, and only if
+          we really need one. */
+       {
+         if (badly_p)
+           what_events = QS_TIMER;
+         else
+           what_events = 0;
+       }
+      else
+       /* Look for any event */
+       what_events = QS_ALLINPUT;
+
       active = MsgWaitForMultipleObjects (mswindows_waitable_count,
                                          mswindows_waitable_handles,
                                          FALSE, badly_p ? INFINITE : 0,
-                                         QS_ALLINPUT);
+                                         what_events);
 
       /* This will assert if handle being waited for becomes abandoned.
         Not the case currently tho */
@@ -1499,7 +1519,10 @@ mswindows_need_event (int badly_p)
       else if (active == WAIT_OBJECT_0 + mswindows_waitable_count)
        {
          /* Got your message, thanks */
-         mswindows_drain_windows_queue ();
+         if (mswindows_in_modal_loop)
+           mswindows_need_event_in_modal_loop (badly_p);
+         else
+           mswindows_drain_windows_queue ();
        }
       else
        {
@@ -1516,7 +1539,12 @@ mswindows_need_event (int badly_p)
            {
              /* None. This means that the process handle itself has signaled.
                 Remove the handle from the wait vector, and make status_notify
-                note the exited process */
+                note the exited process.  First find the process object if
+                possible. */
+             LIST_LOOP_3 (vaffanculo, Vprocess_list, vproctail)
+               if (get_nt_process_handle (XPROCESS (vaffanculo)) ==
+                   mswindows_waitable_handles [ix])
+                 break;
              mswindows_waitable_handles [ix] =
                mswindows_waitable_handles [--mswindows_waitable_count];
              kick_status_notify ();
@@ -1525,10 +1553,12 @@ mswindows_need_event (int badly_p)
                 process, and (2) status notifications will happen in
                 accept-process-output, sleep-for, and sit-for. */
              /* #### horrible kludge till my real process fixes go in.
+                #### Replaced with a slightly less horrible kluge that
+                     at least finds the right process instead of axing the
+                     first one on the list.
               */
-             if (!NILP (Vprocess_list))
+             if (!NILP (vproctail))
                {
-                 Lisp_Object vaffanculo = XCAR (Vprocess_list);
                  mswindows_enqueue_process_event (XPROCESS (vaffanculo));
                }
              else /* trash me soon. */
@@ -2118,7 +2148,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
        BYTE keymap_orig[256];
        BYTE keymap_sticky[256];
        int has_AltGr = mswindows_current_layout_has_AltGr ();
-       int mods = 0;
+       int mods = 0, mods_with_shift = 0;
        int extendedp = lParam & 0x1000000;
        Lisp_Object keysym;
        int sticky_changed;
@@ -2153,6 +2183,7 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
          memcpy (keymap_sticky, keymap_orig, 256);
 
        mods = mswindows_modifier_state (keymap_sticky, (DWORD) -1, has_AltGr);
+       mods_with_shift = mods;
 
        /* Handle non-printables */
        if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods,
@@ -2221,22 +2252,27 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
                   || PeekMessage (&tranmsg, hwnd, WM_SYSCHAR, WM_SYSCHAR,
                                   PM_REMOVE))
              {
-               int mods1 = mods;
+               int mods_with_quit = mods;
                WPARAM ch = tranmsg.wParam;
 
                /* If a quit char with no modifiers other than control and
                   shift, then mark it with a fake modifier, which is removed
                   upon dequeueing the event */
-               /* #### This might also not withstand localization, if
-                  quit character is not a latin-1 symbol */
+               /* !!#### Fix this in my mule ws -- replace current_buffer
+                  with 0 */
                if (((quit_ch < ' ' && (mods & XEMACS_MOD_CONTROL)
-                     && quit_ch + 'a' - 1 == ch)
+                     && DOWNCASE (current_buffer, quit_ch + 'a' - 1) ==
+                     DOWNCASE (current_buffer, ch))
                     || (quit_ch >= ' ' && !(mods & XEMACS_MOD_CONTROL)
-                        && quit_ch == ch))
-                   && ((mods  & ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT))
+                        && DOWNCASE (current_buffer, quit_ch) ==
+                        DOWNCASE (current_buffer, ch)))
+                   && ((mods_with_shift &
+                        ~(XEMACS_MOD_CONTROL | XEMACS_MOD_SHIFT))
                        == 0))
                  {
-                   mods1 |= FAKE_MOD_QUIT;
+                   mods_with_quit |= FAKE_MOD_QUIT;
+                   if (mods_with_shift & XEMACS_MOD_SHIFT)
+                     mods_with_quit |= FAKE_MOD_QUIT_CRITICAL;
                    ++mswindows_quit_chars_count;
                  }
                else if (potential_accelerator && !got_accelerator &&
@@ -2245,7 +2281,8 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
                    got_accelerator = 1;
                    break;
                  }
-               mswindows_enqueue_keypress_event (hwnd, make_char (ch), mods1);
+               mswindows_enqueue_keypress_event (hwnd, make_char (ch),
+                                                 mods_with_quit);
              } /* while */
 
            /* This generates WM_SYSCHAR messages, which are interpreted
@@ -3435,8 +3472,8 @@ emacs_mswindows_quit_p (void)
   if (mswindows_in_modal_loop)
     return;
 
-  /* Drain windows queue. This sets up number of quit characters in
-     the queue */
+  /* Drain windows queue.  This sets up number of quit characters in
+     the queue. */
   mswindows_drain_windows_queue ();
 
   if (mswindows_quit_chars_count > 0)
@@ -3454,10 +3491,11 @@ emacs_mswindows_quit_p (void)
          emacs_event = mswindows_cancel_dispatch_event (&match_against);
          assert (!NILP (emacs_event));
 
-         if (XEVENT(emacs_event)->event.key.modifiers & XEMACS_MOD_SHIFT)
+         if (XEVENT (emacs_event)->event.key.modifiers &
+             FAKE_MOD_QUIT_CRITICAL)
            critical_p = 1;
 
-         Fdeallocate_event(emacs_event);
+         Fdeallocate_event (emacs_event);
        }
 
       Vquit_flag = critical_p ? Qcritical : Qt;
@@ -3730,7 +3768,7 @@ lstream_type_create_mswindows_selectable (void)
 {
   init_slurp_stream ();
   init_shove_stream ();
-#if defined (HAVE_SOCKETS) && !defined(HAVE_MSG_SELECT)
+#if defined (HAVE_SOCKETS) && !defined (HAVE_MSG_SELECT)
   init_winsock_stream ();
 #endif
 }