Mercurial > hg > xemacs-beta
comparison src/ntproc.c @ 771:943eaba38521
[xemacs-hg @ 2002-03-13 08:51:24 by ben]
The big ben-mule-21-5 check-in!
Various files were added and deleted. See CHANGES-ben-mule.
There are still some test suite failures. No crashes, though.
Many of the failures have to do with problems in the test suite itself
rather than in the actual code. I'll be addressing these in the next
day or so -- none of the test suite failures are at all critical.
Meanwhile I'll be trying to address the biggest issues -- i.e. build
or run failures, which will almost certainly happen on various platforms.
All comments should be sent to ben@xemacs.org -- use a Cc: if necessary
when sending to mailing lists. There will be pre- and post- tags,
something like
pre-ben-mule-21-5-merge-in, and
post-ben-mule-21-5-merge-in.
author | ben |
---|---|
date | Wed, 13 Mar 2002 08:54:06 +0000 |
parents | b39c14581166 |
children | a5954632b187 |
comparison
equal
deleted
inserted
replaced
770:336a418893b5 | 771:943eaba38521 |
---|---|
1 /* Old process support under MS Windows, soon to die. | 1 /* Old process support under MS Windows, soon to die. |
2 Copyright (C) 1992, 1995 Free Software Foundation, Inc. | 2 Copyright (C) 1992, 1995 Free Software Foundation, Inc. |
3 Copyright (C) 2001 Ben Wing. | |
3 | 4 |
4 This file is part of XEmacs. | 5 This file is part of XEmacs. |
5 | 6 |
6 XEmacs is free software; you can redistribute it and/or modify it | 7 XEmacs is free software; you can redistribute it and/or modify it |
7 under the terms of the GNU General Public License as published by the | 8 under the terms of the GNU General Public License as published by the |
20 | 21 |
21 Drew Bliss Oct 14, 1993 | 22 Drew Bliss Oct 14, 1993 |
22 Adapted from alarm.c by Tim Fleehart */ | 23 Adapted from alarm.c by Tim Fleehart */ |
23 | 24 |
24 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ | 25 /* Adapted for XEmacs by David Hobley <david@spook-le0.cia.com.au> */ |
25 /* Synced with FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> */ | 26 /* Synced with FSF Emacs 19.34.6 by Marc Paquette <marcpa@cam.org> |
27 (Note: Sync messages from Marc Paquette may indicate | |
28 incomplete synching, so beware.) | |
29 */ | |
30 | |
31 /* !!#### This piece of crap is not getting Mule-ized. It will go away | |
32 as soon as my process-stderr patches go in and there are a few stream | |
33 device fixes, so my new call-process-written-using-start-process can | |
34 always work. */ | |
26 | 35 |
27 /* #### This ENTIRE file is only around because of callproc.c, which | 36 /* #### This ENTIRE file is only around because of callproc.c, which |
28 in turn is only used in batch mode. | 37 in turn is only used in batch mode. |
29 | 38 |
30 We only need two things to get rid of both this and callproc.c: | 39 We only need two things to get rid of both this and callproc.c: |
31 | 40 |
32 -- my `stderr-proc' ws, which adds support for a separate stderr | 41 -- my `stderr-proc' ws, which adds support for a separate stderr |
33 in asynch. subprocesses. (it's a feature in `old-call-process-internal'.) | 42 in asynch. subprocesses. (it's a feature in `old-call-process-internal'.) |
34 -- a noninteractive event loop that supports processes. | 43 -- a noninteractive event loop that supports processes. |
35 */ | 44 */ |
36 | |
37 #include <config.h> | 45 #include <config.h> |
38 #undef signal | 46 #include "lisp.h" |
39 #undef wait | 47 |
40 #undef spawnve | 48 #include "buffer.h" |
41 #undef select | 49 #include "console-msw.h" |
42 #undef kill | 50 #include "process.h" |
43 | 51 |
44 #include <windows.h> | |
45 #ifdef HAVE_A_OUT_H | 52 #ifdef HAVE_A_OUT_H |
46 #include <a.out.h> | 53 #include <a.out.h> |
47 #endif | 54 #endif |
48 #include "lisp.h" | 55 #include "sysfile.h" |
49 #include "sysproc.h" | 56 #include "sysproc.h" |
50 #include "nt.h" | 57 #include "syssignal.h" |
51 #include "ntheap.h" /* From 19.34.6 */ | |
52 #include "systime.h" | 58 #include "systime.h" |
53 #include "syssignal.h" | |
54 #include "sysfile.h" | |
55 #include "syswait.h" | 59 #include "syswait.h" |
56 #include "buffer.h" | 60 |
57 #include "process.h" | |
58 | |
59 #include "console-msw.h" | |
60 | |
61 /*#include "w32term.h"*/ /* From 19.34.6: sync in ? --marcpa */ | |
62 | 61 |
63 /* #### I'm not going to play with shit. */ | 62 /* #### I'm not going to play with shit. */ |
64 #pragma warning (disable:4013 4024 4090) | 63 // #pragma warning (disable:4013 4024 4090) |
65 | 64 |
66 /* Control whether spawnve quotes arguments as necessary to ensure | 65 /* Control whether spawnve quotes arguments as necessary to ensure |
67 correct parsing by child process. Because not all uses of spawnve | 66 correct parsing by child process. Because not all uses of spawnve |
68 are careful about constructing argv arrays, we make this behavior | 67 are careful about constructing argv arrays, we make this behavior |
69 conditional (off by default). */ | 68 conditional (off by default). */ |
83 avoids the inefficiency of frequently reading small amounts of data. | 82 avoids the inefficiency of frequently reading small amounts of data. |
84 This is primarily necessary for handling DOS processes on Windows 95, | 83 This is primarily necessary for handling DOS processes on Windows 95, |
85 but is useful for Win32 processes on both Win95 and NT as well. */ | 84 but is useful for Win32 processes on both Win95 and NT as well. */ |
86 Lisp_Object Vwin32_pipe_read_delay; | 85 Lisp_Object Vwin32_pipe_read_delay; |
87 | 86 |
88 /* Control whether xemacs_stat() attempts to generate fake but hopefully | |
89 "accurate" inode values, by hashing the absolute truenames of files. | |
90 This should detect aliasing between long and short names, but still | |
91 allows the possibility of hash collisions. */ | |
92 Lisp_Object Vwin32_generate_fake_inodes; | |
93 | |
94 Lisp_Object Qhigh, Qlow; | |
95 | |
96 extern Lisp_Object Vlisp_EXEC_SUFFIXES; | 87 extern Lisp_Object Vlisp_EXEC_SUFFIXES; |
88 | |
89 /* child_process.status values */ | |
90 enum { | |
91 STATUS_READ_ERROR = -1, | |
92 STATUS_READ_READY, | |
93 STATUS_READ_IN_PROGRESS, | |
94 STATUS_READ_FAILED, | |
95 STATUS_READ_SUCCEEDED, | |
96 STATUS_READ_ACKNOWLEDGED | |
97 }; | |
98 | |
99 /* This structure is used for both pipes and sockets; for | |
100 a socket, the process handle in pi is NULL. */ | |
101 typedef struct _child_process | |
102 { | |
103 int fd; | |
104 int pid; | |
105 HANDLE char_avail; | |
106 HANDLE char_consumed; | |
107 HANDLE thrd; | |
108 HWND hwnd; | |
109 PROCESS_INFORMATION procinfo; | |
110 volatile int status; | |
111 char chr; | |
112 } child_process; | |
113 | |
114 #define MAX_CHILDREN MAXDESC/2 | |
115 #define CHILD_ACTIVE(cp) ((cp)->char_avail != NULL) | |
116 | |
117 extern child_process * new_child (void); | |
118 extern void delete_child (child_process *cp); | |
119 | |
120 /* parallel array of private info on file handles */ | |
121 typedef struct | |
122 { | |
123 unsigned flags; | |
124 HANDLE hnd; | |
125 child_process * cp; | |
126 } filedesc; | |
127 | |
128 extern filedesc fd_info []; | |
129 | |
130 /* fd_info flag definitions */ | |
131 #define FILE_READ 0x0001 | |
132 #define FILE_WRITE 0x0002 | |
133 #define FILE_BINARY 0x0010 | |
134 #define FILE_LAST_CR 0x0020 | |
135 #define FILE_AT_EOF 0x0040 | |
136 #define FILE_SEND_SIGCHLD 0x0080 | |
137 #define FILE_PIPE 0x0100 | |
138 #define FILE_SOCKET 0x0200 | |
139 | |
140 /* #### This is an evil dirty hack. We must get rid of it. | |
141 Word "munging" is not in XEmacs lexicon. - kkm */ | |
142 | |
143 /* parallel array of private info on file handles */ | |
144 filedesc fd_info [ MAXDESC ]; | |
145 | |
146 #ifdef DEBUG_XEMACS | |
147 #define DebPrint(stuff) _DebPrint stuff | |
148 #else | |
149 #define DebPrint(stuff) | |
150 #endif | |
151 | |
152 /* ------------------------------------------------------------------------- */ | |
97 | 153 |
98 #ifndef DEBUG_XEMACS | 154 #ifndef DEBUG_XEMACS |
99 __inline | 155 __inline |
100 #endif | 156 #endif |
101 void _DebPrint (const char *fmt, ...) | 157 void _DebPrint (const char *fmt, ...) |
110 OutputDebugString (buf); | 166 OutputDebugString (buf); |
111 #endif | 167 #endif |
112 } | 168 } |
113 | 169 |
114 /* sys_signal moved to nt.c. It's now called mswindows_signal... */ | 170 /* sys_signal moved to nt.c. It's now called mswindows_signal... */ |
115 | |
116 /* Defined in <process.h> which conflicts with the local copy */ | |
117 #define _P_NOWAIT 1 | |
118 | 171 |
119 /* Child process management list. */ | 172 /* Child process management list. */ |
120 int child_proc_count = 0; | 173 int child_proc_count = 0; |
121 child_process child_procs[ MAX_CHILDREN ]; | 174 child_process child_procs[ MAX_CHILDREN ]; |
122 child_process *dead_child = NULL; | 175 child_process *dead_child = NULL; |
388 } | 441 } |
389 | 442 |
390 return 0; | 443 return 0; |
391 } | 444 } |
392 | 445 |
446 /* This must die. */ | |
447 static void | |
448 unixtodos_filename (char *p) | |
449 { | |
450 while (*p) | |
451 { | |
452 if (*p == '/') | |
453 *p = '\\'; | |
454 p++; | |
455 } | |
456 } | |
457 | |
393 /* To avoid Emacs changing directory, we just record here the directory | 458 /* To avoid Emacs changing directory, we just record here the directory |
394 the new process should start in. This is set just before calling | 459 the new process should start in. This is set just before calling |
395 sys_spawnve, and is not generally valid at any other time. */ | 460 sys_spawnve, and is not generally valid at any other time. */ |
396 static const char * process_dir; | 461 static const char * process_dir; |
397 | 462 |
400 int * pPid, child_process *cp) | 465 int * pPid, child_process *cp) |
401 { | 466 { |
402 STARTUPINFO start; | 467 STARTUPINFO start; |
403 SECURITY_ATTRIBUTES sec_attrs; | 468 SECURITY_ATTRIBUTES sec_attrs; |
404 SECURITY_DESCRIPTOR sec_desc; | 469 SECURITY_DESCRIPTOR sec_desc; |
405 char dir[ MAXPATHLEN ]; | 470 char dir[ PATH_MAX ]; |
406 | 471 |
407 if (cp == NULL) abort (); | 472 if (cp == NULL) abort (); |
408 | 473 |
409 xzero (start); | 474 xzero (start); |
410 start.cb = sizeof (start); | 475 start.cb = sizeof (start); |
475 optr = envp2; | 540 optr = envp2; |
476 while (*optr) | 541 while (*optr) |
477 *nptr++ = *optr++; | 542 *nptr++ = *optr++; |
478 num += optr - envp2; | 543 num += optr - envp2; |
479 | 544 |
480 qsort (new_envp, num, sizeof (char*), compare_env); | 545 qsort (new_envp, num, sizeof (char*), mswindows_compare_env); |
481 | 546 |
482 *nptr = NULL; | 547 *nptr = NULL; |
483 } | 548 } |
484 | 549 |
485 /* When a new child process is created we need to register it in our list, | 550 /* When a new child process is created we need to register it in our list, |
486 so intercept spawn requests. */ | 551 so intercept spawn requests. */ |
487 int | 552 int |
488 sys_spawnve (int mode, const char *cmdname, | 553 spawnve_will_die_soon (int mode, const Intbyte *cmdname, |
489 const char * const *argv, const char *const *envp) | 554 const Intbyte * const *argv, const Intbyte *const *envp) |
490 { | 555 { |
491 Lisp_Object program, full; | 556 Lisp_Object program, full; |
492 char *cmdline, *env, *parg, **targ; | 557 char *cmdline, *env, *parg, **targ; |
493 int arglen, numenv; | 558 int arglen, numenv; |
494 int pid; | 559 int pid; |
548 /* On Windows 95, if cmdname is a DOS app, we invoke a helper | 613 /* On Windows 95, if cmdname is a DOS app, we invoke a helper |
549 application to start it by specifying the helper app as cmdname, | 614 application to start it by specifying the helper app as cmdname, |
550 while leaving the real app name as argv[0]. */ | 615 while leaving the real app name as argv[0]. */ |
551 if (is_dos_app) | 616 if (is_dos_app) |
552 { | 617 { |
553 cmdname = (char*) alloca (MAXPATHLEN); | 618 cmdname = (char*) alloca (PATH_MAX); |
554 if (egetenv ("CMDPROXY")) | 619 if (egetenv ("CMDPROXY")) |
555 strcpy ((char*)cmdname, egetenv ("CMDPROXY")); | 620 strcpy ((char*)cmdname, egetenv ("CMDPROXY")); |
556 else | 621 else |
557 { | 622 { |
558 strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory)); | 623 strcpy ((char*)cmdname, XSTRING_DATA (Vinvocation_directory)); |
791 { | 856 { |
792 char window_class[32]; | 857 char window_class[32]; |
793 | 858 |
794 GetClassName (hwnd, window_class, sizeof (window_class)); | 859 GetClassName (hwnd, window_class, sizeof (window_class)); |
795 if (strcmp (window_class, | 860 if (strcmp (window_class, |
796 mswindows_windows9x_p() | 861 mswindows_windows9x_p |
797 ? "tty" | 862 ? "tty" |
798 : "ConsoleWindowClass") == 0) | 863 : "ConsoleWindowClass") == 0) |
799 { | 864 { |
800 cp->hwnd = hwnd; | 865 cp->hwnd = hwnd; |
801 return FALSE; | 866 return FALSE; |
804 /* keep looking */ | 869 /* keep looking */ |
805 return TRUE; | 870 return TRUE; |
806 } | 871 } |
807 | 872 |
808 int | 873 int |
809 sys_kill (int pid, int sig) | 874 kill_will_disappear_soon (int pid, int sig) |
810 { | 875 { |
811 child_process *cp; | 876 child_process *cp; |
812 HANDLE proc_hand; | 877 HANDLE proc_hand; |
813 int need_to_free = 0; | 878 int need_to_free = 0; |
814 int rc = 0; | 879 int rc = 0; |
884 else | 949 else |
885 { | 950 { |
886 if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd) | 951 if (NILP (Vwin32_start_process_share_console) && cp && cp->hwnd) |
887 { | 952 { |
888 #if 1 | 953 #if 1 |
889 if (mswindows_windows9x_p()) | 954 if (mswindows_windows9x_p) |
890 { | 955 { |
891 /* | 956 /* |
892 Another possibility is to try terminating the VDM out-right by | 957 Another possibility is to try terminating the VDM out-right by |
893 calling the Shell VxD (id 0x17) V86 interface, function #4 | 958 calling the Shell VxD (id 0x17) V86 interface, function #4 |
894 "SHELL_Destroy_VM", ie. | 959 "SHELL_Destroy_VM", ie. |
943 CloseHandle (proc_hand); | 1008 CloseHandle (proc_hand); |
944 | 1009 |
945 return rc; | 1010 return rc; |
946 } | 1011 } |
947 | 1012 |
1013 /* From callproc.c */ | |
1014 extern Lisp_Object Vbinary_process_input; | |
1015 extern Lisp_Object Vbinary_process_output; | |
1016 | |
1017 /* Unix pipe() has only one arg */ | |
1018 /* Will die as soon as callproc.c dies */ | |
1019 int | |
1020 pipe_will_die_soon (int *phandles) | |
1021 { | |
1022 int rc; | |
1023 unsigned flags; | |
1024 | |
1025 /* make pipe handles non-inheritable; when we spawn a child, we | |
1026 replace the relevant handle with an inheritable one. Also put | |
1027 pipes into binary mode; we will do text mode translation ourselves | |
1028 if required. */ | |
1029 rc = _pipe (phandles, 0, _O_NOINHERIT | _O_BINARY); | |
1030 | |
1031 if (rc == 0) | |
1032 { | |
1033 flags = FILE_PIPE | FILE_READ; | |
1034 if (!NILP (Vbinary_process_output)) | |
1035 flags |= FILE_BINARY; | |
1036 fd_info[phandles[0]].flags = flags; | |
1037 | |
1038 flags = FILE_PIPE | FILE_WRITE; | |
1039 if (!NILP (Vbinary_process_input)) | |
1040 flags |= FILE_BINARY; | |
1041 fd_info[phandles[1]].flags = flags; | |
1042 } | |
1043 | |
1044 return rc; | |
1045 } | |
1046 | |
948 /* The following two routines are used to manipulate stdin, stdout, and | 1047 /* The following two routines are used to manipulate stdin, stdout, and |
949 stderr of our child processes. | 1048 stderr of our child processes. |
950 | 1049 |
951 Assuming that in, out, and err are *not* inheritable, we make them | 1050 Assuming that in, out, and err are *not* inheritable, we make them |
952 stdin, stdout, and stderr of the child as follows: | 1051 stdin, stdout, and stderr of the child as follows: |
1036 void | 1135 void |
1037 set_process_dir (const char * dir) | 1136 set_process_dir (const char * dir) |
1038 { | 1137 { |
1039 process_dir = dir; | 1138 process_dir = dir; |
1040 } | 1139 } |
1041 | |
1042 /* Some miscellaneous functions that are Windows specific, but not GUI | |
1043 specific (ie. are applicable in terminal or batch mode as well). */ | |
1044 | |
1045 DEFUN ("win32-short-file-name", Fwin32_short_file_name, 1, 1, "", /* | |
1046 Return the short file name version (8.3) of the full path of FILENAME. | |
1047 If FILENAME does not exist, return nil. | |
1048 All path elements in FILENAME are converted to their short names. | |
1049 */ | |
1050 (filename)) | |
1051 { | |
1052 char shortname[PATH_MAX]; | |
1053 | |
1054 CHECK_STRING (filename); | |
1055 | |
1056 /* first expand it. */ | |
1057 filename = Fexpand_file_name (filename, Qnil); | |
1058 | |
1059 /* luckily, this returns the short version of each element in the path. */ | |
1060 if (GetShortPathName (XSTRING_DATA (filename), shortname, PATH_MAX) == 0) | |
1061 return Qnil; | |
1062 | |
1063 CORRECT_DIR_SEPS (shortname); | |
1064 | |
1065 return build_string (shortname); | |
1066 } | |
1067 | |
1068 | |
1069 DEFUN ("win32-long-file-name", Fwin32_long_file_name, 1, 1, "", /* | |
1070 Return the long file name version of the full path of FILENAME. | |
1071 If FILENAME does not exist, return nil. | |
1072 All path elements in FILENAME are converted to their long names. | |
1073 */ | |
1074 (filename)) | |
1075 { | |
1076 char longname[ PATH_MAX ]; | |
1077 | |
1078 CHECK_STRING (filename); | |
1079 | |
1080 /* first expand it. */ | |
1081 filename = Fexpand_file_name (filename, Qnil); | |
1082 | |
1083 if (!win32_get_long_filename (XSTRING_DATA (filename), longname, PATH_MAX)) | |
1084 return Qnil; | |
1085 | |
1086 CORRECT_DIR_SEPS (longname); | |
1087 | |
1088 return build_string (longname); | |
1089 } | |
1090 | |
1091 DEFUN ("win32-set-process-priority", Fwin32_set_process_priority, 2, 2, "", /* | |
1092 Set the priority of PROCESS to PRIORITY. | |
1093 If PROCESS is nil, the priority of Emacs is changed, otherwise the | |
1094 priority of the process whose pid is PROCESS is changed. | |
1095 PRIORITY should be one of the symbols high, normal, or low; | |
1096 any other symbol will be interpreted as normal. | |
1097 | |
1098 If successful, the return value is t, otherwise nil. | |
1099 */ | |
1100 (process, priority)) | |
1101 { | |
1102 HANDLE proc_handle = GetCurrentProcess (); | |
1103 DWORD priority_class = NORMAL_PRIORITY_CLASS; | |
1104 Lisp_Object result = Qnil; | |
1105 | |
1106 CHECK_SYMBOL (priority); | |
1107 | |
1108 if (!NILP (process)) | |
1109 { | |
1110 DWORD pid; | |
1111 child_process *cp; | |
1112 | |
1113 CHECK_INT (process); | |
1114 | |
1115 /* Allow pid to be an internally generated one, or one obtained | |
1116 externally. This is necessary because real pids on Win95 are | |
1117 negative. */ | |
1118 | |
1119 pid = XINT (process); | |
1120 cp = find_child_pid (pid); | |
1121 if (cp != NULL) | |
1122 pid = cp->procinfo.dwProcessId; | |
1123 | |
1124 proc_handle = OpenProcess (PROCESS_SET_INFORMATION, FALSE, pid); | |
1125 } | |
1126 | |
1127 if (EQ (priority, Qhigh)) | |
1128 priority_class = HIGH_PRIORITY_CLASS; | |
1129 else if (EQ (priority, Qlow)) | |
1130 priority_class = IDLE_PRIORITY_CLASS; | |
1131 | |
1132 if (proc_handle != NULL) | |
1133 { | |
1134 if (SetPriorityClass (proc_handle, priority_class)) | |
1135 result = Qt; | |
1136 if (!NILP (process)) | |
1137 CloseHandle (proc_handle); | |
1138 } | |
1139 | |
1140 return result; | |
1141 } | |
1142 | |
1143 | |
1144 DEFUN ("win32-get-locale-info", Fwin32_get_locale_info, 1, 2, "", /* | |
1145 "Return information about the Windows locale LCID. | |
1146 By default, return a three letter locale code which encodes the default | |
1147 language as the first two characters, and the country or regional variant | |
1148 as the third letter. For example, ENU refers to `English (United States)', | |
1149 while ENC means `English (Canadian)'. | |
1150 | |
1151 If the optional argument LONGFORM is non-nil, the long form of the locale | |
1152 name is returned, e.g. `English (United States)' instead. | |
1153 | |
1154 If LCID (a 16-bit number) is not a valid locale, the result is nil. | |
1155 */ | |
1156 (lcid, longform)) | |
1157 { | |
1158 int got_abbrev; | |
1159 int got_full; | |
1160 char abbrev_name[32] = { 0 }; | |
1161 char full_name[256] = { 0 }; | |
1162 | |
1163 CHECK_INT (lcid); | |
1164 | |
1165 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED)) | |
1166 return Qnil; | |
1167 | |
1168 if (NILP (longform)) | |
1169 { | |
1170 got_abbrev = GetLocaleInfo (XINT (lcid), | |
1171 LOCALE_SABBREVLANGNAME | LOCALE_USE_CP_ACP, | |
1172 abbrev_name, sizeof (abbrev_name)); | |
1173 if (got_abbrev) | |
1174 return build_string (abbrev_name); | |
1175 } | |
1176 else | |
1177 { | |
1178 got_full = GetLocaleInfo (XINT (lcid), | |
1179 LOCALE_SLANGUAGE | LOCALE_USE_CP_ACP, | |
1180 full_name, sizeof (full_name)); | |
1181 if (got_full) | |
1182 return build_string (full_name); | |
1183 } | |
1184 | |
1185 return Qnil; | |
1186 } | |
1187 | |
1188 | |
1189 DEFUN ("win32-get-current-locale-id", Fwin32_get_current_locale_id, 0, 0, "", /* | |
1190 "Return Windows locale id for current locale setting. | |
1191 This is a numerical value; use `win32-get-locale-info' to convert to a | |
1192 human-readable form. | |
1193 */ | |
1194 ()) | |
1195 { | |
1196 return make_int (GetThreadLocale ()); | |
1197 } | |
1198 | |
1199 | |
1200 DEFUN ("win32-get-default-locale-id", Fwin32_get_default_locale_id, 0, 1, "", /* | |
1201 "Return Windows locale id for default locale setting. | |
1202 By default, the system default locale setting is returned; if the optional | |
1203 parameter USERP is non-nil, the user default locale setting is returned. | |
1204 This is a numerical value; use `win32-get-locale-info' to convert to a | |
1205 human-readable form. | |
1206 */ | |
1207 (userp)) | |
1208 { | |
1209 if (NILP (userp)) | |
1210 return make_int (GetSystemDefaultLCID ()); | |
1211 return make_int (GetUserDefaultLCID ()); | |
1212 } | |
1213 | |
1214 DWORD int_from_hex (char * s) | |
1215 { | |
1216 DWORD val = 0; | |
1217 static char hex[] = "0123456789abcdefABCDEF"; | |
1218 char * p; | |
1219 | |
1220 while (*s && (p = strchr(hex, *s)) != NULL) | |
1221 { | |
1222 unsigned digit = p - hex; | |
1223 if (digit > 15) | |
1224 digit -= 6; | |
1225 val = val * 16 + digit; | |
1226 s++; | |
1227 } | |
1228 return val; | |
1229 } | |
1230 | |
1231 /* We need to build a global list, since the EnumSystemLocale callback | |
1232 function isn't given a context pointer. */ | |
1233 Lisp_Object Vwin32_valid_locale_ids; | |
1234 | |
1235 BOOL CALLBACK enum_locale_fn (LPTSTR localeNum) | |
1236 { | |
1237 DWORD id = int_from_hex (localeNum); | |
1238 Vwin32_valid_locale_ids = Fcons (make_int (id), Vwin32_valid_locale_ids); | |
1239 return TRUE; | |
1240 } | |
1241 | |
1242 DEFUN ("win32-get-valid-locale-ids", Fwin32_get_valid_locale_ids, 0, 0, "", /* | |
1243 Return list of all valid Windows locale ids. | |
1244 Each id is a numerical value; use `win32-get-locale-info' to convert to a | |
1245 human-readable form. | |
1246 */ | |
1247 ()) | |
1248 { | |
1249 Vwin32_valid_locale_ids = Qnil; | |
1250 | |
1251 EnumSystemLocales (enum_locale_fn, LCID_SUPPORTED); | |
1252 | |
1253 Vwin32_valid_locale_ids = Fnreverse (Vwin32_valid_locale_ids); | |
1254 return Vwin32_valid_locale_ids; | |
1255 } | |
1256 | |
1257 | |
1258 DEFUN ("win32-set-current-locale", Fwin32_set_current_locale, 1, 1, "", /* | |
1259 Make Windows locale LCID be the current locale setting for Emacs. | |
1260 If successful, the new locale id is returned, otherwise nil. | |
1261 */ | |
1262 (lcid)) | |
1263 { | |
1264 CHECK_INT (lcid); | |
1265 | |
1266 if (!IsValidLocale (XINT (lcid), LCID_SUPPORTED)) | |
1267 return Qnil; | |
1268 | |
1269 /* #### not supported under win98, but will go away */ | |
1270 if (!SetThreadLocale (XINT (lcid))) | |
1271 return Qnil; | |
1272 | |
1273 /* Sync with FSF Emacs 19.34.6 note: dwWinThreadId declared in | |
1274 w32term.h and defined in w32fns.c, both of which are not in current | |
1275 XEmacs. #### Check what we lose by ifdef'ing out these. --marcpa */ | |
1276 #if 0 | |
1277 /* Need to set input thread locale if present. */ | |
1278 if (dwWinThreadId) | |
1279 /* Reply is not needed. */ | |
1280 PostThreadMessage (dwWinThreadId, WM_EMACS_SETLOCALE, XINT (lcid), 0); | |
1281 #endif | |
1282 | |
1283 return make_int (GetThreadLocale ()); | |
1284 } | |
1285 | 1140 |
1286 | 1141 |
1287 void | 1142 void |
1288 syms_of_ntproc (void) | 1143 syms_of_ntproc (void) |
1289 { | 1144 { |
1290 DEFSUBR (Fwin32_short_file_name); | 1145 } |
1291 DEFSUBR (Fwin32_long_file_name); | |
1292 DEFSUBR (Fwin32_set_process_priority); | |
1293 DEFSUBR (Fwin32_get_locale_info); | |
1294 DEFSUBR (Fwin32_get_current_locale_id); | |
1295 DEFSUBR (Fwin32_get_default_locale_id); | |
1296 DEFSUBR (Fwin32_get_valid_locale_ids); | |
1297 DEFSUBR (Fwin32_set_current_locale); | |
1298 } | |
1299 | |
1300 | 1146 |
1301 void | 1147 void |
1302 vars_of_ntproc (void) | 1148 vars_of_ntproc (void) |
1303 { | 1149 { |
1304 DEFSYMBOL (Qhigh); | |
1305 DEFSYMBOL (Qlow); | |
1306 | |
1307 DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /* | 1150 DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /* |
1308 Non-nil enables quoting of process arguments to ensure correct parsing. | 1151 Non-nil enables quoting of process arguments to ensure correct parsing. |
1309 Because Windows does not directly pass argv arrays to child processes, | 1152 Because Windows does not directly pass argv arrays to child processes, |
1310 programs have to reconstruct the argv array by parsing the command | 1153 programs have to reconstruct the argv array by parsing the command |
1311 line string. For an argument to contain a space, it must be enclosed | 1154 line string. For an argument to contain a space, it must be enclosed |
1344 reading the subprocess output. If negative, the magnitude is the number | 1187 reading the subprocess output. If negative, the magnitude is the number |
1345 of time slices to wait (effectively boosting the priority of the child | 1188 of time slices to wait (effectively boosting the priority of the child |
1346 process temporarily). A value of zero disables waiting entirely. | 1189 process temporarily). A value of zero disables waiting entirely. |
1347 */ ); | 1190 */ ); |
1348 Vwin32_pipe_read_delay = make_int (50); | 1191 Vwin32_pipe_read_delay = make_int (50); |
1349 | |
1350 #if 0 | |
1351 DEFVAR_LISP ("win32-generate-fake-inodes", &Vwin32_generate_fake_inodes /* | |
1352 "Non-nil means attempt to fake realistic inode values. | |
1353 This works by hashing the truename of files, and should detect | |
1354 aliasing between long and short (8.3 DOS) names, but can have | |
1355 false positives because of hash collisions. Note that determining | |
1356 the truename of a file can be slow. | |
1357 */ ); | |
1358 Vwin32_generate_fake_inodes = Qnil; | |
1359 #endif | |
1360 } | 1192 } |
1361 | 1193 |
1362 /* end of ntproc.c */ | 1194 /* end of ntproc.c */ |