/* 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.
#undef kill
#include <windows.h>
+#ifdef __GNUC__
+/* This definition is missing from mingw32 headers. */
+extern BOOL WINAPI IsValidLocale(LCID, DWORD);
+#endif
#include "lisp.h"
#include "w32.h"
Lisp_Object Qhigh, Qlow;
-#ifndef SYS_SIGLIST_DECLARED
-extern char *sys_siglist[];
-#endif
-
#ifdef EMACSDEBUG
void _DebPrint (const char *fmt, ...)
{
{
STARTUPINFO start;
SECURITY_ATTRIBUTES sec_attrs;
+#if 0
SECURITY_DESCRIPTOR sec_desc;
+#endif
DWORD flags;
char dir[ MAXPATHLEN ];
start.hStdError = GetStdHandle (STD_ERROR_HANDLE);
#endif /* HAVE_NTGUI */
+#if 0
/* Explicitly specify no security */
if (!InitializeSecurityDescriptor (&sec_desc, SECURITY_DESCRIPTOR_REVISION))
goto EH_Fail;
if (!SetSecurityDescriptorDacl (&sec_desc, TRUE, NULL, FALSE))
goto EH_Fail;
+#endif
sec_attrs.nLength = sizeof (sec_attrs);
- sec_attrs.lpSecurityDescriptor = &sec_desc;
+ sec_attrs.lpSecurityDescriptor = NULL /* &sec_desc */;
sec_attrs.bInheritHandle = FALSE;
strcpy (dir, process_dir);
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";
{
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;
}
int
-compare_env (const char **strp1, const char **strp2)
+compare_env (const void *strp1, const void *strp2)
{
- const char *str1 = *strp1, *str2 = *strp2;
+ const char *str1 = *(const char **)strp1, *str2 = *(const char **)strp2;
while (*str1 && *str2 && *str1 != '=' && *str2 != '=')
{
- if (tolower (*str1) > tolower (*str2))
+ /* Sort order in command.com/cmd.exe is based on uppercasing
+ names, so do the same here. */
+ if (toupper (*str1) > toupper (*str2))
return 1;
- else if (tolower (*str1) < tolower (*str2))
+ else if (toupper (*str1) < toupper (*str2))
return -1;
str1++, str2++;
}
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)
{
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];
/* Substitute for certain kill () operations */
static BOOL CALLBACK
-find_child_console (HWND hwnd, child_process * cp)
+find_child_console (HWND hwnd, LPARAM arg)
{
+ child_process * cp = (child_process *) arg;
DWORD thread_id;
DWORD process_id;
}
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))
{
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)