21.4.14 "Reasonable Discussion".
[chise/xemacs-chise.git.1] / src / event-msw.c
index a09c81f..bf87090 100644 (file)
@@ -49,31 +49,31 @@ Boston, MA 02111-1307, USA.  */
 # include "dragdrop.h"
 #endif
 
+#include "buffer.h"
 #include "device.h"
 #include "events.h"
-#include "frame.h"
-#include "buffer.h"
 #include "faces.h"
+#include "frame.h"
 #include "lstream.h"
+#include "objects-msw.h"
 #include "process.h"
 #include "redisplay.h"
 #include "select.h"
+#include "sysdep.h"
 #include "window.h"
+
+#include "sysfile.h"
 #include "sysproc.h"
-#include "syswait.h"
 #include "systime.h"
-#include "sysdep.h"
-#include "objects-msw.h"
+#include "syswait.h"
 
 #include "events-mod.h"
+
 #ifdef HAVE_MSG_SELECT
-#include "sysfile.h"
 #include "console-tty.h"
 #elif defined(CYGWIN)
 typedef unsigned int SOCKET;
 #endif
-#include <io.h>
-#include <errno.h>
 
 #if !(defined(CYGWIN) || defined(MINGW))
 # include <shlobj.h>   /* For IShellLink */
@@ -87,12 +87,13 @@ 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
 
-static Lisp_Object mswindows_find_frame (HWND hwnd);
+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,
                                                  int extendedp);
@@ -146,13 +147,16 @@ int mswindows_quit_chars_count = 0;
 /* These are Lisp integers; see DEFVARS in this file for description. */
 int mswindows_dynamic_frame_resize;
 int mswindows_alt_by_itself_activates_menu;
-int mswindows_num_mouse_buttons;
-int mswindows_mouse_button_max_skew_x;
-int mswindows_mouse_button_max_skew_y;
-int mswindows_mouse_button_tolerance;
+Fixnum mswindows_num_mouse_buttons;
+Fixnum mswindows_mouse_button_max_skew_x;
+Fixnum mswindows_mouse_button_max_skew_y;
+Fixnum mswindows_mouse_button_tolerance;
 
 #ifdef DEBUG_XEMACS
-int debug_mswindows_events;
+Fixnum debug_mswindows_events;
+
+static void debug_output_mswin_message (HWND hwnd, UINT message_,
+                                       WPARAM wParam, LPARAM lParam);
 #endif
 
 /* This is the event signaled by the event pump.
@@ -182,7 +186,7 @@ static DWORD mswindows_last_mouse_button_state;
    exists. For example, "start notepad" command is issued from the
    shell, then the shell is closed by C-c C-d. Although the shell
    process exits, its output pipe will not get closed until the
-   notepad process exits also, because it inherits the pipe form the
+   notepad process exits also, because it inherits the pipe from the
    shell. In this case, we abandon the thread, and let it live until
    all such processes exit. While struct ntpipe_slurp_stream is
    deallocated in this case, ntpipe_slurp_stream_shared_data are not. */
@@ -228,6 +232,7 @@ slurper_free_shared_data_maybe (struct ntpipe_slurp_stream_shared_data* s)
       CloseHandle (s->hev_thread);
       CloseHandle (s->hev_caller);
       CloseHandle (s->hev_unsleep);
+      CloseHandle (s->hpipe);
       s->inuse_p = 0;
     }
 }
@@ -366,8 +371,9 @@ get_ntpipe_input_stream_waitable (Lstream *stream)
   return s->thread_data->hev_caller;
 }
 
-static ssize_t
-ntpipe_slurp_reader (Lstream *stream, unsigned char *data, size_t size)
+static Lstream_data_count
+ntpipe_slurp_reader (Lstream *stream, unsigned char *data,
+                    Lstream_data_count size)
 {
   /* This function must be called from the main thread only */
   struct ntpipe_slurp_stream_shared_data* s =
@@ -580,8 +586,9 @@ get_ntpipe_output_stream_param (Lstream *stream)
 }
 #endif
 
-static ssize_t
-ntpipe_shove_writer (Lstream *stream, const unsigned char *data, size_t size)
+static Lstream_data_count
+ntpipe_shove_writer (Lstream *stream, const unsigned char *data,
+                    Lstream_data_count size)
 {
   struct ntpipe_shove_stream* s = NTPIPE_SHOVE_STREAM_DATA(stream);
 
@@ -663,7 +670,7 @@ struct winsock_stream
   LPARAM user_data;            /* Any user data stored in the stream object */
   SOCKET s;                    /* Socket handle (which is a Win32 handle)   */
   OVERLAPPED ov;               /* Overlapped I/O structure                  */
-  void* buffer;                        /* Buffer. Allocated for input stream only   */
+  void* buffer;                        /* Buffer.                                   */
   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                            */
@@ -697,8 +704,8 @@ winsock_initiate_read (struct winsock_stream *str)
     str->eof_p = 1;
 }
 
-static ssize_t
-winsock_reader (Lstream *stream, unsigned char *data, size_t size)
+static Lstream_data_count
+winsock_reader (Lstream *stream, unsigned char *data, Lstream_data_count size)
 {
   struct winsock_stream *str = WINSOCK_STREAM_DATA (stream);
 
@@ -732,7 +739,7 @@ winsock_reader (Lstream *stream, unsigned char *data, size_t size)
     return -1;
 
   /* Return as much of buffer as we have */
-  size = min (size, (size_t) (str->bufsize - str->bufpos));
+  size = min (size, (Lstream_data_count) (str->bufsize - str->bufpos));
   memcpy (data, (void*)((BYTE*)str->buffer + str->bufpos), size);
   str->bufpos += size;
 
@@ -743,8 +750,9 @@ winsock_reader (Lstream *stream, unsigned char *data, size_t size)
   return size;
 }
 
-static ssize_t
-winsock_writer (Lstream *stream, const unsigned char *data, size_t size)
+static Lstream_data_count
+winsock_writer (Lstream *stream, const unsigned char *data,
+               Lstream_data_count size)
 {
   struct winsock_stream *str = WINSOCK_STREAM_DATA (stream);
 
@@ -772,18 +780,24 @@ winsock_writer (Lstream *stream, const unsigned char *data, size_t size)
   if (size == 0)
     return 0;
 
-  {
-    ResetEvent (str->ov.hEvent);
-
-    /* Docs indicate that 4th parameter to WriteFile can be NULL since this is
-     * an overlapped operation. This fails on Win95 with winsock 1.x so we
-     * supply a spare address which is ignored by Win95 anyway. Sheesh. */
-    if (WriteFile ((HANDLE)str->s, data, size, (LPDWORD)&str->buffer, &str->ov)
-       || GetLastError() == ERROR_IO_PENDING)
-      str->pending_p = 1;
-    else
-      str->error_p = 1;
-  }
+  ResetEvent (str->ov.hEvent);
+
+  /* According to WriteFile docs, we must hold onto the data we pass to it
+     and not make any changes until it finishes -- which may not be until
+     the next time we get here, since we use asynchronous I/O.  We have
+     in fact seen data loss as a result of not doing this. */
+  str->buffer = xrealloc (str->buffer, size);
+  memcpy (str->buffer, data, size);
+
+  /* According to MSDN WriteFile docs, the fourth parameter cannot be NULL
+     on Win95 even when doing an overlapped operation, as we are, where
+     the return value through that parameter is not meaningful. */
+  if (WriteFile ((HANDLE)str->s, str->buffer, size, &str->bufsize,
+                &str->ov)
+      || GetLastError() == ERROR_IO_PENDING)
+    str->pending_p = 1;
+  else
+    str->error_p = 1;
 
   return str->error_p ? -1 : size;
 }
@@ -798,12 +812,15 @@ winsock_closer (Lstream *lstr)
   else
     shutdown (str->s, 1);
 
-  CloseHandle ((HANDLE)str->s);
+  closesocket (str->s);
   if (str->pending_p)
     WaitForSingleObject (str->ov.hEvent, INFINITE);
 
-  if (lstr->flags & LSTREAM_FL_READ)
-    xfree (str->buffer);
+  if (str->buffer)
+    {
+      xfree (str->buffer);
+      str->buffer = 0;
+    }
 
   CloseHandle (str->ov.hEvent);
   return 0;
@@ -823,14 +840,10 @@ make_winsock_stream_1 (SOCKET s, LPARAM param, const char *mode)
   Lstream *lstr = Lstream_new (lstream_winsock, mode);
   struct winsock_stream *str = WINSOCK_STREAM_DATA (lstr);
 
+  xzero (*str);
   str->s = s;
-  str->blocking_p = 0;
-  str->error_p = 0;
-  str->eof_p = 0;
-  str->pending_p = 0;
   str->user_data = param;
 
-  xzero (str->ov);
   str->ov.hEvent = CreateEvent (NULL, TRUE, FALSE, NULL);
 
   if (lstr->flags & LSTREAM_FL_READ)
@@ -968,6 +981,9 @@ mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where,
   int downp = (msg == WM_LBUTTONDOWN || msg == WM_MBUTTONDOWN ||
               msg == WM_RBUTTONDOWN);
 
+  /* Wheel rotation amount: positive is away from user, negative towards user */
+  int delta = (short) HIWORD (mods);
+  
   /* We always use last message time, because mouse button
      events may get delayed, and XEmacs double click
      recognition will fail */
@@ -980,7 +996,9 @@ mswindows_enqueue_mouse_button_event (HWND hwnd, UINT msg, POINTS where,
   event->timestamp = when;
   event->event.button.button =
     (msg==WM_LBUTTONDOWN || msg==WM_LBUTTONUP) ? 1 :
-    ((msg==WM_RBUTTONDOWN || msg==WM_RBUTTONUP) ? 3 : 2);
+    (msg==WM_MBUTTONDOWN || msg==WM_MBUTTONUP) ? 2 :
+    (msg==WM_RBUTTONDOWN || msg==WM_RBUTTONUP) ? 3 :
+    (msg==WM_MOUSEWHEEL && delta>0) ? 4 : 5;
   event->event.button.x = where.x;
   event->event.button.y = where.y;
   event->event.button.modifiers = mswindows_modifier_state (NULL, mods, 0);
@@ -1041,13 +1059,11 @@ mswindows_dequeue_dispatch_event (void)
                         &mswindows_s_dispatch_event_queue_tail :
                         &mswindows_u_dispatch_event_queue_tail);
 
-  sevt = XEVENT(event);
+  sevt = XEVENT (event);
   if (sevt->event_type == key_press_event
       && (sevt->event.key.modifiers & FAKE_MOD_QUIT))
-    {
-      sevt->event.key.modifiers &= ~FAKE_MOD_QUIT;
-      --mswindows_quit_chars_count;
-    }
+    sevt->event.key.modifiers &=
+      ~(FAKE_MOD_QUIT | FAKE_MOD_QUIT_CRITICAL);
 
   return event;
 }
@@ -1138,6 +1154,21 @@ remove_waitable_handle (HANDLE h)
 }
 #endif /* HAVE_MSG_SELECT */
 
+/*
+ * Given a lisp process pointer remove the corresponding process handle
+ * from mswindows_waitable_handles if it is in it.  Normally the handle is
+ * removed when the process terminates, but if the lisp process structure
+ * is deleted before the process terminates we must delete the process
+ * handle since it will be invalid and will cause the wait to fail
+ */
+void
+mswindows_unwait_process (Lisp_Process *p)
+{
+#ifndef HAVE_MSG_SELECT
+  remove_waitable_handle (get_nt_process_handle (p));
+#endif /* HAVE_MSG_SELECT */
+}
+
 \f
 /************************************************************************/
 /*                             Event pump                               */
@@ -1337,6 +1368,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)
@@ -1360,8 +1395,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);
     }
 }
 
@@ -1377,12 +1412,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))
     {
@@ -1399,6 +1428,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);
@@ -1412,7 +1445,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
            {
@@ -1477,10 +1513,39 @@ mswindows_need_event (int badly_p)
        }
 #else
       /* Now try getting a message or process event */
-      active = MsgWaitForMultipleObjects (mswindows_waitable_count,
-                                         mswindows_waitable_handles,
-                                         FALSE, badly_p ? INFINITE : 0,
-                                         QS_ALLINPUT);
+      DWORD what_events;
+      MSG msg;
+
+      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;
+
+      /* This fixes a long outstanding bug, where XEmacs would occasionally
+       * not redraw its window (or process other events) until "something
+       * happened" - usually the mouse moving over a frame.
+       *
+       * The problem is that MsgWaitForMultipleObjects only checks to see
+       * if NEW messages have been placed into the thread queue. So we
+       * specifically check to see if the queue is empty (using PeekMessage
+       * with the PM_NOREMOVE flag) before we wait.
+       */
+      if (what_events == QS_ALLINPUT && badly_p &&
+         PeekMessage (&msg, 0, 0, 0, PM_NOREMOVE))
+       active = WAIT_OBJECT_0 + mswindows_waitable_count;
+      else
+       active = MsgWaitForMultipleObjects (mswindows_waitable_count,
+                                           mswindows_waitable_handles,
+                                           FALSE, badly_p ? INFINITE : 0,
+                                           what_events);
 
       /* This will assert if handle being waited for becomes abandoned.
         Not the case currently tho */
@@ -1496,7 +1561,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
        {
@@ -1513,7 +1581,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 ();
@@ -1522,10 +1595,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. */
@@ -1571,6 +1646,8 @@ mswindows_wm_timer_callback (HWND hwnd, UINT umsg, UINT id_timer, DWORD dwtime)
  * depends on dnd support.
  */
 #ifdef HAVE_DRAGNDROP
+extern int mswindows_dde_enable;
+
 HDDEDATA CALLBACK
 mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv,
                        HSZ hszTopic, HSZ hszItem, HDDEDATA hdata,
@@ -1597,6 +1674,9 @@ mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv,
       return (HDDEDATA)NULL;
 
     case XTYP_EXECUTE:
+      if (!mswindows_dde_enable)
+       return (HDDEDATA) DDE_FBUSY;
+
       if (!DdeCmpStringHandles (hszTopic, mswindows_dde_topic_system))
        {
          DWORD len = DdeGetData (hdata, NULL, 0, 0);
@@ -1604,7 +1684,7 @@ mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv,
          char *end;
          char *filename;
          struct gcpro gcpro1, gcpro2;
-          Lisp_Object l_dndlist = Qnil;
+         Lisp_Object l_dndlist = Qnil;
          Lisp_Object emacs_event = Fmake_event (Qnil, Qnil);
          Lisp_Object frmcons, devcons, concons;
          Lisp_Event *event = XEVENT (emacs_event);
@@ -1640,9 +1720,9 @@ mswindows_dde_callback (UINT uType, UINT uFmt, HCONV hconv,
            return DDE_FNOTPROCESSED;
 
 #ifdef CYGWIN
-         filename = alloca (cygwin32_win32_to_posix_path_list_buf_size (cmd) + 5);
+         filename = alloca (cygwin_win32_to_posix_path_list_buf_size (cmd) + 5);
          strcpy (filename, "file:");
-         cygwin32_win32_to_posix_path_list (cmd, filename+5);
+         cygwin_win32_to_posix_path_list (cmd, filename+5);
 #else
          dostounix_filename (cmd);
          filename = alloca (strlen (cmd)+6);
@@ -2025,10 +2105,14 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
   struct frame *frame;
   struct mswindows_frame* msframe;
 
-  /* Not perfect but avoids crashes. There is potential for wierd
-     behavior here. */
-  if (gc_in_progress)
-    goto defproc;
+  /* If you hit this, rewrite the offending API call to occur after GC,
+     using register_post_gc_action(). */
+  assert (!gc_in_progress);
+
+#ifdef DEBUG_XEMACS
+  if (debug_mswindows_events)
+    debug_output_mswin_message (hwnd, message_, wParam, lParam);
+#endif /* DEBUG_XEMACS */
 
   assert (!GetWindowLong (hwnd, GWL_USERDATA));
   switch (message_)
@@ -2064,13 +2148,8 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
        int should_set_keymap = 0;
 
 #ifdef DEBUG_XEMACS
-       if (debug_mswindows_events)
-         {
-           stderr_out ("%s wparam=%d lparam=%d\n",
-                       message_ == WM_KEYUP ? "WM_KEYUP" : "WM_SYSKEYUP",
-                       wParam, (int)lParam);
-           output_alt_keyboard_state ();
-         }
+       if (debug_mswindows_events > 2)
+         output_alt_keyboard_state ();
 #endif /* DEBUG_XEMACS */
 
        mswindows_handle_sticky_modifiers (wParam, lParam, 0, 1);
@@ -2115,19 +2194,14 @@ 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;
 
 #ifdef DEBUG_XEMACS
-       if (debug_mswindows_events)
-         {
-           stderr_out ("%s wparam=%d lparam=%d\n",
-                       message_ == WM_KEYDOWN ? "WM_KEYDOWN" : "WM_SYSKEYDOWN",
-                       wParam, (int)lParam);
-           output_alt_keyboard_state ();
-         }
+       if (debug_mswindows_events > 2)
+         output_alt_keyboard_state ();
 #endif /* DEBUG_XEMACS */
 
        GetKeyboardState (keymap_orig);
@@ -2150,6 +2224,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,
@@ -2218,23 +2293,38 @@ 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;
 
+#ifdef DEBUG_XEMACS
+               if (debug_mswindows_events)
+                 {
+                   stderr_out ("-> ");
+                   debug_output_mswin_message (tranmsg.hwnd, tranmsg.message,
+                                               tranmsg.wParam,
+                                               tranmsg.lParam);
+                 }
+#endif /* DEBUG_XEMACS */
+
                /* 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;
-                   ++mswindows_quit_chars_count;
+                   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 &&
                         mswindows_char_is_accelerator (frame, ch))
@@ -2242,7 +2332,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
@@ -2563,6 +2654,125 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
       mswindows_handle_paint (XFRAME (mswindows_find_frame (hwnd)));
       break;
 
+    case WM_ACTIVATE:
+      {
+        /*
+         * If we receive a WM_ACTIVATE message that indicates that our frame
+         * is being activated, make sure that the frame is marked visible
+         * if the window itself is visible. This seems to fix the problem
+         * where XEmacs appears to lock-up after switching desktops with
+         * some virtual window managers.
+         */
+        int state = (int)(short) LOWORD(wParam);
+#ifdef DEBUG_XEMACS
+        if (debug_mswindows_events)
+          stderr_out("state = %d\n", state);
+#endif /* DEBUG_XEMACS */
+        if (state == WA_ACTIVE || state == WA_CLICKACTIVE)
+          {
+#ifdef DEBUG_XEMACS
+            if (debug_mswindows_events)
+              stderr_out("  activating\n");
+#endif /* DEBUG_XEMACS */
+            
+            fobj = mswindows_find_frame (hwnd);
+            frame = XFRAME (fobj);
+            if (IsWindowVisible (hwnd))
+              {
+#ifdef DEBUG_XEMACS
+                if (debug_mswindows_events)
+                  stderr_out("  window is visible\n");
+#endif /* DEBUG_XEMACS */
+                if (!FRAME_VISIBLE_P (frame))
+                  {
+#ifdef DEBUG_XEMACS
+                    if (debug_mswindows_events)
+                      stderr_out("  frame is not visible\n");
+#endif /* DEBUG_XEMACS */
+                    /*
+                     * It seems that we have to enqueue the XM_MAPFRAME event
+                     * prior to setting the frame visible so that
+                     * suspend-or-iconify-emacs works properly.
+                     */
+                    mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME);
+                    FRAME_VISIBLE_P (frame) = 1;
+                    FRAME_ICONIFIED_P (frame) = 0;
+                  }
+#ifdef DEBUG_XEMACS
+                else
+                  {
+                    if (debug_mswindows_events)
+                      stderr_out("  frame is visible\n");
+                  }
+#endif /* DEBUG_XEMACS */
+              }
+#ifdef DEBUG_XEMACS
+            else
+              {     
+                if (debug_mswindows_events)
+                  stderr_out("  window is not visible\n");
+              }
+#endif /* DEBUG_XEMACS */
+          }
+       return DefWindowProc (hwnd, message_, wParam, lParam);
+      }
+      break;
+      
+    case WM_WINDOWPOSCHANGED:
+      /* This is sent before WM_SIZE; in fact, the processing of this
+        by DefWindowProc() sends WM_SIZE.  But WM_SIZE is not sent when
+        a window is hidden (make-frame-invisible), so we need to process
+        this and update the state flags. */
+      {
+       fobj = mswindows_find_frame (hwnd);
+       frame = XFRAME (fobj);
+       if (IsIconic (hwnd))
+         {
+           FRAME_VISIBLE_P (frame) = 0;
+           FRAME_ICONIFIED_P (frame) = 1;
+         }
+       else if (IsWindowVisible (hwnd))
+         {
+           /* APA: It's too early here to set the frame visible.
+            * Let's do this later, in WM_SIZE processing, after the
+            * magic XM_MAPFRAME event has been sent (just like 21.1
+            * did). */
+           /* FRAME_VISIBLE_P (frame) = 1; */
+           FRAME_ICONIFIED_P (frame) = 0;
+         }
+       else
+         {
+           FRAME_VISIBLE_P (frame) = 0;
+           FRAME_ICONIFIED_P (frame) = 0;
+         }         
+
+       return DefWindowProc (hwnd, message_, wParam, lParam);
+      }
+
+    case WM_SHOWWINDOW:
+      /*
+         The WM_SHOWWINDOW message is sent to a window when the window
+         is about to be hidden or shown.
+         APA: This message is also sent when switching to a virtual
+         desktop under the virtuawin virtual window manager.
+      
+      */
+      {
+       fobj = mswindows_find_frame (hwnd);
+       frame = XFRAME (fobj);
+        if (wParam == TRUE)
+          {
+            mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME);
+            FRAME_VISIBLE_P (frame) = 1;
+          }
+        else
+          {
+            mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME);
+            FRAME_VISIBLE_P (frame) = 0;
+          }
+      }
+      break;
+
     case WM_SIZE:
       /* We only care about this message if our size has really changed */
       if (wParam==SIZE_RESTORED || wParam==SIZE_MAXIMIZED || wParam==SIZE_MINIMIZED)
@@ -2581,7 +2791,6 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
          if (wParam==SIZE_MINIMIZED)
            {
              /* Iconified */
-             FRAME_VISIBLE_P (frame) = 0;
              mswindows_enqueue_magic_event (hwnd, XM_UNMAPFRAME);
            }
          else
@@ -2616,8 +2825,13 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
              else
                {
                  if (!msframe->sizing && !FRAME_VISIBLE_P (frame))
-                   mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME);
-                 FRAME_VISIBLE_P (frame) = 1;
+                    {
+                      mswindows_enqueue_magic_event (hwnd, XM_MAPFRAME);
+                      /* APA: Now that the magic XM_MAPFRAME event has
+                       * been sent we can mark the frame as visible (just
+                       * like 21.1 did). */
+                      FRAME_VISIBLE_P (frame) = 1;
+                    }
 
                  if (!msframe->sizing || mswindows_dynamic_frame_resize)
                    redisplay ();
@@ -2740,17 +2954,19 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
       {
        int keys = LOWORD (wParam); /* Modifier key flags */
        int delta = (short) HIWORD (wParam); /* Wheel rotation amount */
-       struct gcpro gcpro1, gcpro2;
 
-       if (mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd), keys,  delta))
-         {
-           GCPRO2 (emacs_event, fobj);
-           mswindows_pump_outstanding_events ();       /* Can GC */
-           UNGCPRO;
-         }
-       else
-         goto defproc;
-       break;
+        /* enqueue button4/5 events if mswindows_handle_mousewheel_event
+           doesn't handle the event, such as when the scrollbars are not
+           displayed */
+       if (!mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd),
+                                              keys, delta,
+                                              MAKEPOINTS (lParam)))
+          mswindows_enqueue_mouse_button_event (hwnd, message_,
+                                                MAKEPOINTS (lParam),
+                                                wParam,
+                                                GetMessageTime());
+        /* We are not in a modal loop so no pumping is necessary. */
+        break;
       }
 #endif
 
@@ -2794,8 +3010,6 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
          case CBN_SELCHANGE:
            if (!NILP (mswindows_handle_gui_wm_command (frame, cid, id)))
              return 0;
-         case BN_SETFOCUS:
-           
          }
        /* menubars always must come last since the hashtables do not
           always exist*/
@@ -2919,14 +3133,14 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
                    if (psl->lpVtbl->QueryInterface (psl, &IID_IPersistFile,
                                                     &ppf) == S_OK)
                      {
-                       WORD wsz[MAX_PATH];
+                       OLECHAR wsz[PATH_MAX];
                        WIN32_FIND_DATA wfd;
-                       LPSTR resolved = (char *) xmalloc (MAX_PATH+1);
+                       LPSTR resolved = (char *) xmalloc (PATH_MAX+1);
 
-                       MultiByteToWideChar (CP_ACP,0, fname, -1, wsz, MAX_PATH);
+                       MultiByteToWideChar (CP_ACP,0, fname, -1, wsz, PATH_MAX);
 
                        if ((ppf->lpVtbl->Load (ppf, wsz, STGM_READ) == S_OK) &&
-                           (psl->lpVtbl->GetPath (psl, resolved, MAX_PATH,
+                           (psl->lpVtbl->GetPath (psl, resolved, PATH_MAX,
                                                   &wfd, 0)==S_OK))
                          {
                            xfree (fname);
@@ -2943,9 +3157,9 @@ mswindows_wnd_proc (HWND hwnd, UINT message_, WPARAM wParam, LPARAM lParam)
 #endif
 
 #ifdef CYGWIN
-           filename = xmalloc (cygwin32_win32_to_posix_path_list_buf_size (fname) + 5);
+           filename = xmalloc (cygwin_win32_to_posix_path_list_buf_size (fname) + 5);
            strcpy (filename, "file:");
-           cygwin32_win32_to_posix_path_list (fname, filename+5);
+           cygwin_win32_to_posix_path_list (fname, filename+5);
 #else
            filename = (char *)xmalloc (len+6);
            strcat (strcpy (filename, "file:"), fname);
@@ -3196,7 +3410,7 @@ mswindows_find_console (HWND hwnd)
 /*
  * Find the frame that matches the supplied mswindows window handle
  */
-static Lisp_Object
+Lisp_Object
 mswindows_find_frame (HWND hwnd)
 {
   LONG l = GetWindowLong (hwnd, XWL_FRAMEOBJ);
@@ -3432,8 +3646,9 @@ emacs_mswindows_quit_p (void)
   if (mswindows_in_modal_loop)
     return;
 
-  /* Drain windows queue. This sets up number of quit characters in
-     the queue */
+  mswindows_quit_chars_count = 0;
+  /* Drain windows queue.  This sets up number of quit characters in
+     the queue. */
   mswindows_drain_windows_queue ();
 
   if (mswindows_quit_chars_count > 0)
@@ -3446,15 +3661,17 @@ emacs_mswindows_quit_p (void)
       match_against.event_type = key_press_event;
       match_against.event.key.modifiers = FAKE_MOD_QUIT;
 
-      while (mswindows_quit_chars_count-- > 0)
+      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 & 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);
+         mswindows_quit_chars_count--;
        }
 
       Vquit_flag = critical_p ? Qcritical : Qt;
@@ -3590,6 +3807,341 @@ debug_process_finalization (Lisp_Process *p)
 }
 #endif
 
+#ifdef DEBUG_XEMACS
+
+struct mswin_message_debug
+{
+  int mess;
+  char *string;
+};
+
+#define FROB(val) { val, #val, },
+
+struct mswin_message_debug debug_mswin_messages[] =
+{
+FROB (WM_NULL)
+FROB (WM_CREATE)
+FROB (WM_DESTROY)
+FROB (WM_MOVE)
+FROB (WM_SIZE)
+
+FROB (WM_ACTIVATE)
+
+FROB (WM_SETFOCUS)
+FROB (WM_KILLFOCUS)
+FROB (WM_ENABLE)
+FROB (WM_SETREDRAW)
+FROB (WM_SETTEXT)
+FROB (WM_GETTEXT)
+FROB (WM_GETTEXTLENGTH)
+FROB (WM_PAINT)
+FROB (WM_CLOSE)
+FROB (WM_QUERYENDSESSION)
+FROB (WM_QUIT)
+FROB (WM_QUERYOPEN)
+FROB (WM_ERASEBKGND)
+FROB (WM_SYSCOLORCHANGE)
+FROB (WM_ENDSESSION)
+FROB (WM_SHOWWINDOW)
+FROB (WM_WININICHANGE)
+#if(WINVER >= 0x0400)
+FROB (WM_SETTINGCHANGE)
+#endif /* WINVER >= 0x0400 */
+
+FROB (WM_DEVMODECHANGE)
+FROB (WM_ACTIVATEAPP)
+FROB (WM_FONTCHANGE)
+FROB (WM_TIMECHANGE)
+FROB (WM_CANCELMODE)
+FROB (WM_SETCURSOR)
+FROB (WM_MOUSEACTIVATE)
+FROB (WM_CHILDACTIVATE)
+FROB (WM_QUEUESYNC)
+
+FROB (WM_GETMINMAXINFO)
+
+FROB (WM_PAINTICON)
+FROB (WM_ICONERASEBKGND)
+FROB (WM_NEXTDLGCTL)
+FROB (WM_SPOOLERSTATUS)
+FROB (WM_DRAWITEM)
+FROB (WM_MEASUREITEM)
+FROB (WM_DELETEITEM)
+FROB (WM_VKEYTOITEM)
+FROB (WM_CHARTOITEM)
+FROB (WM_SETFONT)
+FROB (WM_GETFONT)
+FROB (WM_SETHOTKEY)
+FROB (WM_GETHOTKEY)
+FROB (WM_QUERYDRAGICON)
+FROB (WM_COMPAREITEM)
+#if(WINVER >= 0x0500)
+FROB (WM_GETOBJECT)
+#endif /* WINVER >= 0x0500 */
+FROB (WM_COMPACTING)
+FROB (WM_COMMNOTIFY)
+FROB (WM_WINDOWPOSCHANGING)
+FROB (WM_WINDOWPOSCHANGED)
+
+FROB (WM_POWER)
+
+FROB (WM_COPYDATA)
+FROB (WM_CANCELJOURNAL)
+
+#if(WINVER >= 0x0400)
+FROB (WM_NOTIFY)
+FROB (WM_INPUTLANGCHANGEREQUEST)
+FROB (WM_INPUTLANGCHANGE)
+FROB (WM_TCARD)
+FROB (WM_HELP)
+FROB (WM_USERCHANGED)
+FROB (WM_NOTIFYFORMAT)
+
+FROB (WM_CONTEXTMENU)
+FROB (WM_STYLECHANGING)
+FROB (WM_STYLECHANGED)
+FROB (WM_DISPLAYCHANGE)
+FROB (WM_GETICON)
+FROB (WM_SETICON)
+#endif /* WINVER >= 0x0400 */
+
+FROB (WM_NCCREATE)
+FROB (WM_NCDESTROY)
+FROB (WM_NCCALCSIZE)
+FROB (WM_NCHITTEST)
+FROB (WM_NCPAINT)
+FROB (WM_NCACTIVATE)
+FROB (WM_GETDLGCODE)
+#ifdef WM_SYNCPAINT /* not in VC 5 */
+FROB (WM_SYNCPAINT)
+#endif /* WM_SYNCPAINT */
+FROB (WM_NCMOUSEMOVE)
+FROB (WM_NCLBUTTONDOWN)
+FROB (WM_NCLBUTTONUP)
+FROB (WM_NCLBUTTONDBLCLK)
+FROB (WM_NCRBUTTONDOWN)
+FROB (WM_NCRBUTTONUP)
+FROB (WM_NCRBUTTONDBLCLK)
+FROB (WM_NCMBUTTONDOWN)
+FROB (WM_NCMBUTTONUP)
+FROB (WM_NCMBUTTONDBLCLK)
+
+/* FROB (WM_KEYFIRST) */
+FROB (WM_KEYDOWN)
+FROB (WM_KEYUP)
+FROB (WM_CHAR)
+FROB (WM_DEADCHAR)
+FROB (WM_SYSKEYDOWN)
+FROB (WM_SYSKEYUP)
+FROB (WM_SYSCHAR)
+FROB (WM_SYSDEADCHAR)
+FROB (WM_KEYLAST)
+
+#if(WINVER >= 0x0400) && defined (WM_IME_STARTCOMPOSITION)
+FROB (WM_IME_STARTCOMPOSITION)
+FROB (WM_IME_ENDCOMPOSITION)
+FROB (WM_IME_COMPOSITION)
+FROB (WM_IME_KEYLAST)
+#endif /* WINVER >= 0x0400 && defined (WM_IME_STARTCOMPOSITION) */
+
+FROB (WM_INITDIALOG)
+FROB (WM_COMMAND)
+FROB (WM_SYSCOMMAND)
+FROB (WM_TIMER)
+FROB (WM_HSCROLL)
+FROB (WM_VSCROLL)
+FROB (WM_INITMENU)
+FROB (WM_INITMENUPOPUP)
+FROB (WM_MENUSELECT)
+FROB (WM_MENUCHAR)
+FROB (WM_ENTERIDLE)
+#if(WINVER >= 0x0500)
+FROB (WM_MENURBUTTONUP)
+FROB (WM_MENUDRAG)
+FROB (WM_MENUGETOBJECT)
+FROB (WM_UNINITMENUPOPUP)
+FROB (WM_MENUCOMMAND)
+#endif /* WINVER >= 0x0500 */
+
+
+FROB (WM_CTLCOLORMSGBOX)
+FROB (WM_CTLCOLOREDIT)
+FROB (WM_CTLCOLORLISTBOX)
+FROB (WM_CTLCOLORBTN)
+FROB (WM_CTLCOLORDLG)
+FROB (WM_CTLCOLORSCROLLBAR)
+FROB (WM_CTLCOLORSTATIC)
+
+
+/* FROB (WM_MOUSEFIRST) */
+FROB (WM_MOUSEMOVE)
+FROB (WM_LBUTTONDOWN)
+FROB (WM_LBUTTONUP)
+FROB (WM_LBUTTONDBLCLK)
+FROB (WM_RBUTTONDOWN)
+FROB (WM_RBUTTONUP)
+FROB (WM_RBUTTONDBLCLK)
+FROB (WM_MBUTTONDOWN)
+FROB (WM_MBUTTONUP)
+FROB (WM_MBUTTONDBLCLK)
+
+#if (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
+FROB (WM_MOUSEWHEEL)
+FROB (WM_MOUSELAST)
+#else
+FROB (WM_MOUSELAST)
+#endif /* if (_WIN32_WINNT < 0x0400) */
+
+FROB (WM_PARENTNOTIFY)
+FROB (WM_ENTERMENULOOP)
+FROB (WM_EXITMENULOOP)
+
+#if(WINVER >= 0x0400)
+FROB (WM_NEXTMENU)
+
+FROB (WM_SIZING)
+FROB (WM_CAPTURECHANGED)
+FROB (WM_MOVING)
+FROB (WM_POWERBROADCAST)
+
+FROB (WM_DEVICECHANGE)
+
+#endif /* WINVER >= 0x0400 */
+
+FROB (WM_MDICREATE)
+FROB (WM_MDIDESTROY)
+FROB (WM_MDIACTIVATE)
+FROB (WM_MDIRESTORE)
+FROB (WM_MDINEXT)
+FROB (WM_MDIMAXIMIZE)
+FROB (WM_MDITILE)
+FROB (WM_MDICASCADE)
+FROB (WM_MDIICONARRANGE)
+FROB (WM_MDIGETACTIVE)
+
+
+FROB (WM_MDISETMENU)
+FROB (WM_ENTERSIZEMOVE)
+FROB (WM_EXITSIZEMOVE)
+FROB (WM_DROPFILES)
+FROB (WM_MDIREFRESHMENU)
+
+#ifdef WM_IME_SETCONTEXT /* not in Cygwin? */
+
+#if(WINVER >= 0x0400) && !defined(CYGWIN)
+FROB (WM_IME_SETCONTEXT)
+FROB (WM_IME_NOTIFY)
+FROB (WM_IME_CONTROL)
+FROB (WM_IME_COMPOSITIONFULL)
+FROB (WM_IME_SELECT)
+FROB (WM_IME_CHAR)
+#endif /* WINVER >= 0x0400 */
+#if(WINVER >= 0x0500)
+FROB (WM_IME_REQUEST)
+#endif /* WINVER >= 0x0500 */
+#if(WINVER >= 0x0400) && !defined(CYGWIN)
+FROB (WM_IME_KEYDOWN)
+FROB (WM_IME_KEYUP)
+#endif /* WINVER >= 0x0400 */
+
+#endif /* WM_IME_SETCONTEXT */
+
+#if(_WIN32_WINNT >= 0x0400)
+FROB (WM_MOUSEHOVER)
+FROB (WM_MOUSELEAVE)
+#endif /* _WIN32_WINNT >= 0x0400 */
+
+FROB (WM_CUT)
+FROB (WM_COPY)
+FROB (WM_PASTE)
+FROB (WM_CLEAR)
+FROB (WM_UNDO)
+FROB (WM_RENDERFORMAT)
+FROB (WM_RENDERALLFORMATS)
+FROB (WM_DESTROYCLIPBOARD)
+FROB (WM_DRAWCLIPBOARD)
+FROB (WM_PAINTCLIPBOARD)
+FROB (WM_VSCROLLCLIPBOARD)
+FROB (WM_SIZECLIPBOARD)
+FROB (WM_ASKCBFORMATNAME)
+FROB (WM_CHANGECBCHAIN)
+FROB (WM_HSCROLLCLIPBOARD)
+FROB (WM_QUERYNEWPALETTE)
+FROB (WM_PALETTEISCHANGING)
+FROB (WM_PALETTECHANGED)
+FROB (WM_HOTKEY)
+
+#if(WINVER >= 0x0400)
+FROB (WM_PRINT)
+FROB (WM_PRINTCLIENT)
+
+FROB (WM_HANDHELDFIRST)
+FROB (WM_HANDHELDLAST)
+
+FROB (WM_AFXFIRST)
+FROB (WM_AFXLAST)
+#endif /* WINVER >= 0x0400 */
+
+FROB (WM_PENWINFIRST)
+FROB (WM_PENWINLAST)
+};
+
+#undef FROB
+
+static void
+debug_output_mswin_message (HWND hwnd, UINT message_, WPARAM wParam,
+                           LPARAM lParam)
+{
+  Lisp_Object frame = mswindows_find_frame (hwnd);
+  int i;
+  char *str = 0;
+  /* struct mswin_message_debug *i_hate_cranking_out_code_like_this; */
+
+  for (i = 0; i < countof (debug_mswin_messages); i++)
+    {
+      if (debug_mswin_messages[i].mess == message_)
+       {
+         str = debug_mswin_messages[i].string;
+         break;
+       }
+    }
+
+  if (str)
+    stderr_out ("%s", str);
+  else
+    stderr_out ("%x", message_);
+
+  if (debug_mswindows_events > 1)
+    {
+      stderr_out (" wparam=%d lparam=%d hwnd=%x frame: ",
+                 wParam, (int) lParam, (unsigned int) hwnd);
+      debug_print (frame);
+      if (message_ == WM_WINDOWPOSCHANGED ||
+          message_ == WM_WINDOWPOSCHANGING)
+        {
+          WINDOWPOS *wp = (WINDOWPOS *) lParam;
+          stderr_out("  WINDOWPOS: x=%d, y=%d, h=%d, w=%d\n",
+                     wp->x, wp->y, wp->cx, wp->cy);
+        }
+      else if (message_ == WM_MOVE)
+        {
+          int x = (int)(short) LOWORD(lParam);   /* horizontal position */
+          int y = (int)(short) HIWORD(lParam);   /* vertical position */
+          stderr_out("  MOVE: x=%d, y=%d\n", x, y);
+        }
+      else if (message_ == WM_SIZE)
+        {
+          int w = (int)(short) LOWORD(lParam);   /* width */
+          int h = (int)(short) HIWORD(lParam);   /* height */
+          stderr_out("  SIZE: w=%d, h=%d\n", w, h);
+        }
+    }
+  else
+    stderr_out ("\n");
+}
+
+#endif /* DEBUG_XEMACS */
+
 /************************************************************************/
 /*                            initialization                            */
 /************************************************************************/
@@ -3636,12 +4188,12 @@ vars_of_event_mswindows (void)
   mswindows_u_dispatch_event_queue = Qnil;
   staticpro (&mswindows_u_dispatch_event_queue);
   mswindows_u_dispatch_event_queue_tail = Qnil;
-  pdump_wire (&mswindows_u_dispatch_event_queue_tail);
+  dump_add_root_object (&mswindows_u_dispatch_event_queue_tail);
 
   mswindows_s_dispatch_event_queue = Qnil;
   staticpro (&mswindows_s_dispatch_event_queue);
   mswindows_s_dispatch_event_queue_tail = Qnil;
-  pdump_wire (&mswindows_s_dispatch_event_queue_tail);
+  dump_add_root_object (&mswindows_s_dispatch_event_queue_tail);
 
   mswindows_error_caught_in_modal_loop = Qnil;
   staticpro (&mswindows_error_caught_in_modal_loop);
@@ -3649,13 +4201,12 @@ vars_of_event_mswindows (void)
 
 #ifdef DEBUG_XEMACS
   DEFVAR_INT ("debug-mswindows-events", &debug_mswindows_events /*
-If non-zero, display debug information about Windows events that XEmacs sees.
+If non-zero, display debug information about Windows messages that XEmacs sees.
 Information is displayed in a console window.  Currently defined values are:
 
-1 == non-verbose output
-2 == verbose output
-
-#### Unfortunately, not yet implemented.
+1 == non-verbose output (just the message name)
+2 == verbose output (all parameters)
+3 == even more verbose output (extra debugging info)
 */ );
   debug_mswindows_events = 0;
 #endif
@@ -3727,7 +4278,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
 }