]> code.delx.au - gnu-emacs/blobdiff - src/w32proc.c
Rewritten to take advantage of shy-groups and
[gnu-emacs] / src / w32proc.c
index 81cdcbf93bff2a79bc86f5690870a78b8a518ad4..21bdebbbeccfa6dc1c9f132b5f46edd0ff30ba8c 100644 (file)
@@ -1,5 +1,5 @@
 /* Process support for GNU Emacs on the Microsoft W32 API.
-   Copyright (C) 1992, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1992, 1995, 1999 Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -91,10 +91,6 @@ Lisp_Object Vw32_get_true_file_attributes;
 
 Lisp_Object Qhigh, Qlow;
 
-#ifndef SYS_SIGLIST_DECLARED
-extern char *sys_siglist[];
-#endif
-
 #ifdef EMACSDEBUG
 void _DebPrint (const char *fmt, ...)
 {
@@ -546,13 +542,11 @@ get_result:
       else if (WIFSIGNALED (retval))
        {
          int code = WTERMSIG (retval);
-         char *signame = 0;
-         
-         if (code < NSIG)
-           {
-             /* Suppress warning if the table has const char *.  */
-             signame = (char *) sys_siglist[code];
-           }
+         char *signame;
+
+         synchronize_system_messages_locale ();
+         signame = strsignal (code);
+
          if (signame == 0)
            signame = "unknown";
 
@@ -639,7 +633,10 @@ w32_executable_type (char * filename, int * is_dos_app, int * is_cygnus_app)
            {
              char * dllname = RVA_TO_PTR (imports->Name, section, executable);
 
-             if (strcmp (dllname, "cygwin.dll") == 0)
+             /* The exact name of the cygwin dll has changed with
+                various releases, but hopefully this will be reasonably
+                future proof.  */
+             if (strncmp (dllname, "cygwin", 6) == 0)
                {
                  *is_cygnus_app = TRUE;
                  break;
@@ -1172,9 +1169,15 @@ count_children:
       return 0;
     }
   
-  /* Wait for input or child death to be signalled.  */
   start_time = GetTickCount ();
-  active = WaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms);
+
+  /* Wait for input or child death to be signalled.  If user input is
+     allowed, then also accept window messages.  */
+  if (FD_ISSET (0, &orfds))
+    active = MsgWaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms,
+                                       QS_ALLINPUT);
+  else
+    active = WaitForMultipleObjects (nh + nc, wait_hnd, FALSE, timeout_ms);
 
   if (active == WAIT_FAILED)
     {
@@ -1210,7 +1213,26 @@ count_children:
      processed - otherwise higher numbered channels could be starved. */
   do
     {
-      if (active >= nh)
+      if (active == nh + nc)
+       {
+         /* There are messages in the lisp thread's queue; we must
+             drain the queue now to ensure they are processed promptly,
+             because if we don't do so, we will not be woken again until
+             further messages arrive.
+
+            NB. If ever we allow window message procedures to callback
+            into lisp, we will need to ensure messages are dispatched
+            at a safe time for lisp code to be run (*), and we may also
+            want to provide some hooks in the dispatch loop to cater
+            for modeless dialogs created by lisp (ie. to register
+            window handles to pass to IsDialogMessage).
+
+            (*) Note that MsgWaitForMultipleObjects above is an
+            internal dispatch point for messages that are sent to
+            windows created by this thread.  */
+         drain_message_queue ();
+       }
+      else if (active >= nh)
        {
          cp = cps[active - nh];
 
@@ -1356,25 +1378,58 @@ sys_kill (int pid, int sig)
            }
 
          foreground_window = GetForegroundWindow ();
-         if (foreground_window && SetForegroundWindow (cp->hwnd))
+         if (foreground_window)
            {
-             /* Generate keystrokes as if user had typed Ctrl-Break or
-                 Ctrl-C.  */
-             keybd_event (VK_CONTROL, control_scan_code, 0, 0);
-             keybd_event (vk_break_code, break_scan_code,
-                          (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY), 0);
-             keybd_event (vk_break_code, break_scan_code,
-                          (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY)
-                          | KEYEVENTF_KEYUP, 0);
-             keybd_event (VK_CONTROL, control_scan_code, KEYEVENTF_KEYUP, 0);
-
-             /* Sleep for a bit to give time for Emacs frame to respond
-                to focus change events (if Emacs was active app).  */
-             Sleep (10);
-
-             SetForegroundWindow (foreground_window);
-           }
-       }
+              /* NT 5.0, and apparently also Windows 98, will not allow
+                a Window to be set to foreground directly without the
+                user's involvement. The workaround is to attach
+                ourselves to the thread that owns the foreground
+                window, since that is the only thread that can set the
+                foreground window.  */
+              DWORD foreground_thread, child_thread;
+              foreground_thread =
+               GetWindowThreadProcessId (foreground_window, NULL);
+             if (foreground_thread == GetCurrentThreadId ()
+                  || !AttachThreadInput (GetCurrentThreadId (),
+                                         foreground_thread, TRUE))
+                foreground_thread = 0;
+
+              child_thread = GetWindowThreadProcessId (cp->hwnd, NULL);
+             if (child_thread == GetCurrentThreadId ()
+                  || !AttachThreadInput (GetCurrentThreadId (),
+                                         child_thread, TRUE))
+                child_thread = 0;
+
+              /* Set the foreground window to the child.  */
+              if (SetForegroundWindow (cp->hwnd))
+                {
+                  /* Generate keystrokes as if user had typed Ctrl-Break or
+                     Ctrl-C.  */
+                  keybd_event (VK_CONTROL, control_scan_code, 0, 0);
+                  keybd_event (vk_break_code, break_scan_code,
+                   (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY), 0);
+                  keybd_event (vk_break_code, break_scan_code,
+                    (vk_break_code == 'C' ? 0 : KEYEVENTF_EXTENDEDKEY)
+                    | KEYEVENTF_KEYUP, 0);
+                  keybd_event (VK_CONTROL, control_scan_code,
+                               KEYEVENTF_KEYUP, 0);
+
+                  /* Sleep for a bit to give time for Emacs frame to respond
+                     to focus change events (if Emacs was active app).  */
+                  Sleep (100);
+
+                  SetForegroundWindow (foreground_window);
+                }
+              /* Detach from the foreground and child threads now that
+                 the foreground switching is over.  */
+              if (foreground_thread)
+                AttachThreadInput (GetCurrentThreadId (),
+                                   foreground_thread, FALSE);
+              if (child_thread)
+                AttachThreadInput (GetCurrentThreadId (),
+                                   child_thread, FALSE);
+            }
+        }
       /* Ctrl-Break is NT equivalent of SIGINT.  */
       else if (!GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, pid))
         {
@@ -2007,11 +2062,11 @@ If successful, the new layout id is returned, otherwise nil.")
   DWORD kl;
 
   CHECK_CONS (layout, 0);
-  CHECK_NUMBER (XCONS (layout)->car, 0);
-  CHECK_NUMBER (XCONS (layout)->cdr, 0);
+  CHECK_NUMBER (XCAR (layout), 0);
+  CHECK_NUMBER (XCDR (layout), 0);
 
-  kl = (XINT (XCONS (layout)->car) & 0xffff)
-    | (XINT (XCONS (layout)->cdr) << 16);
+  kl = (XINT (XCAR (layout)) & 0xffff)
+    | (XINT (XCDR (layout)) << 16);
 
   /* Synchronize layout with input thread.  */
   if (dwWindowsThreadId)