summaryrefslogtreecommitdiff
path: root/src/w32proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/w32proc.c')
-rw-r--r--src/w32proc.c225
1 files changed, 216 insertions, 9 deletions
diff --git a/src/w32proc.c b/src/w32proc.c
index 96f11657892..38452917add 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -32,6 +32,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <signal.h>
#include <sys/file.h>
#include <mbstring.h>
+#include <locale.h>
/* must include CRT headers *before* config.h */
#include <config.h>
@@ -1604,6 +1605,15 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
program = ENCODE_FILE (full);
cmdname = SDATA (program);
}
+ else
+ {
+ char *p = alloca (strlen (cmdname) + 1);
+
+ /* Don't change the command name we were passed by our caller
+ (unixtodos_filename below will destructively mirror forward
+ slashes). */
+ cmdname = strcpy (p, cmdname);
+ }
/* make sure argv[0] and cmdname are both in DOS format */
unixtodos_filename (cmdname);
@@ -1646,7 +1656,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
strcpy (cmdname, egetenv ("CMDPROXY"));
else
{
- strcpy (cmdname, SDATA (Vinvocation_directory));
+ lispstpcpy (cmdname, Vinvocation_directory);
strcat (cmdname, "cmdproxy.exe");
}
@@ -1772,12 +1782,12 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
if (need_quotes)
{
int escape_char_run = 0;
- char * first;
- char * last;
+ /* char * first; */
+ /* char * last; */
p = *targ;
- first = p;
- last = p + strlen (p) - 1;
+ /* first = p; */
+ /* last = p + strlen (p) - 1; */
*parg++ = '"';
#if 0
/* This version does not escape quotes if they occur at the
@@ -2249,10 +2259,9 @@ static BOOL CALLBACK
find_child_console (HWND hwnd, LPARAM arg)
{
child_process * cp = (child_process *) arg;
- DWORD thread_id;
DWORD process_id;
- thread_id = GetWindowThreadProcessId (hwnd, &process_id);
+ GetWindowThreadProcessId (hwnd, &process_id);
if (process_id == cp->procinfo.dwProcessId)
{
char window_class[32];
@@ -2909,7 +2918,7 @@ int_from_hex (char * s)
function isn't given a context pointer. */
Lisp_Object Vw32_valid_locale_ids;
-static BOOL CALLBACK
+static BOOL CALLBACK ALIGN_STACK
enum_locale_fn (LPTSTR localeNum)
{
DWORD id = int_from_hex (localeNum);
@@ -2973,7 +2982,7 @@ If successful, the new locale id is returned, otherwise nil. */)
function isn't given a context pointer. */
Lisp_Object Vw32_valid_codepages;
-static BOOL CALLBACK
+static BOOL CALLBACK ALIGN_STACK
enum_codepage_fn (LPTSTR codepageNum)
{
DWORD id = atoi (codepageNum);
@@ -3145,6 +3154,190 @@ If successful, the new layout id is returned, otherwise nil. */)
return Fw32_get_keyboard_layout ();
}
+/* Two variables to interface between get_lcid and the EnumLocales
+ callback function below. */
+#ifndef LOCALE_NAME_MAX_LENGTH
+# define LOCALE_NAME_MAX_LENGTH 85
+#endif
+static LCID found_lcid;
+static char lname[3 * LOCALE_NAME_MAX_LENGTH + 1 + 1];
+
+/* Callback function for EnumLocales. */
+static BOOL CALLBACK
+get_lcid_callback (LPTSTR locale_num_str)
+{
+ char *endp;
+ char locval[2 * LOCALE_NAME_MAX_LENGTH + 1 + 1];
+ LCID try_lcid = strtoul (locale_num_str, &endp, 16);
+
+ if (GetLocaleInfo (try_lcid, LOCALE_SABBREVLANGNAME,
+ locval, LOCALE_NAME_MAX_LENGTH))
+ {
+ /* This is for when they only specify the language, as in "ENU". */
+ if (stricmp (locval, lname) == 0)
+ {
+ found_lcid = try_lcid;
+ return FALSE;
+ }
+ strcat (locval, "_");
+ if (GetLocaleInfo (try_lcid, LOCALE_SABBREVCTRYNAME,
+ locval + strlen (locval), LOCALE_NAME_MAX_LENGTH))
+ {
+ size_t locval_len = strlen (locval);
+
+ if (strnicmp (locval, lname, locval_len) == 0
+ && (lname[locval_len] == '.'
+ || lname[locval_len] == '\0'))
+ {
+ found_lcid = try_lcid;
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+/* Return the Locale ID (LCID) number given the locale's name, a
+ string, in LOCALE_NAME. This works by enumerating all the locales
+ supported by the system, until we find one whose name matches
+ LOCALE_NAME. */
+static LCID
+get_lcid (const char *locale_name)
+{
+ /* A simple cache. */
+ static LCID last_lcid;
+ static char last_locale[1000];
+
+ /* The code below is not thread-safe, as it uses static variables.
+ But this function is called only from the Lisp thread. */
+ if (last_lcid > 0 && strcmp (locale_name, last_locale) == 0)
+ return last_lcid;
+
+ strncpy (lname, locale_name, sizeof (lname) - 1);
+ lname[sizeof (lname) - 1] = '\0';
+ found_lcid = 0;
+ EnumSystemLocales (get_lcid_callback, LCID_SUPPORTED);
+ if (found_lcid > 0)
+ {
+ last_lcid = found_lcid;
+ strcpy (last_locale, locale_name);
+ }
+ return found_lcid;
+}
+
+#ifndef _NSLCMPERROR
+# define _NSLCMPERROR INT_MAX
+#endif
+#ifndef LINGUISTIC_IGNORECASE
+# define LINGUISTIC_IGNORECASE 0x00000010
+#endif
+
+int
+w32_compare_strings (const char *s1, const char *s2, char *locname,
+ int ignore_case)
+{
+ LCID lcid = GetThreadLocale ();
+ wchar_t *string1_w, *string2_w;
+ int val, needed;
+ extern BOOL g_b_init_compare_string_w;
+ static int (WINAPI *pCompareStringW)(LCID, DWORD, LPCWSTR, int, LPCWSTR, int);
+ DWORD flags = 0;
+
+ USE_SAFE_ALLOCA;
+
+ /* The LCID machinery doesn't seem to support the "C" locale, so we
+ need to do that by hand. */
+ if (locname
+ && ((locname[0] == 'C' && (locname[1] == '\0' || locname[1] == '.'))
+ || strcmp (locname, "POSIX") == 0))
+ return (ignore_case ? stricmp (s1, s2) : strcmp (s1, s2));
+
+ if (!g_b_init_compare_string_w)
+ {
+ if (os_subtype == OS_9X)
+ {
+ pCompareStringW = GetProcAddress (LoadLibrary ("Unicows.dll"),
+ "CompareStringW");
+ if (!pCompareStringW)
+ {
+ errno = EINVAL;
+ /* This return value is compatible with wcscoll and
+ other MS CRT functions. */
+ return _NSLCMPERROR;
+ }
+ }
+ else
+ pCompareStringW = CompareStringW;
+
+ g_b_init_compare_string_w = 1;
+ }
+
+ needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, s1, -1, NULL, 0);
+ if (needed > 0)
+ {
+ SAFE_NALLOCA (string1_w, 1, needed + 1);
+ pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, s1, -1,
+ string1_w, needed);
+ }
+ else
+ {
+ errno = EINVAL;
+ return _NSLCMPERROR;
+ }
+
+ needed = pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, s2, -1, NULL, 0);
+ if (needed > 0)
+ {
+ SAFE_NALLOCA (string2_w, 1, needed + 1);
+ pMultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, s2, -1,
+ string2_w, needed);
+ }
+ else
+ {
+ SAFE_FREE ();
+ errno = EINVAL;
+ return _NSLCMPERROR;
+ }
+
+ if (locname)
+ {
+ /* Convert locale name string to LCID. We don't want to use
+ LocaleNameToLCID because (a) it is only available since
+ Vista, and (b) it doesn't accept locale names returned by
+ 'setlocale' and 'GetLocaleInfo'. */
+ LCID new_lcid = get_lcid (locname);
+
+ if (new_lcid > 0)
+ lcid = new_lcid;
+ else
+ error ("Invalid locale %s: Invalid argument", locname);
+ }
+
+ if (ignore_case)
+ {
+ /* NORM_IGNORECASE ignores any tertiary distinction, not just
+ case variants. LINGUISTIC_IGNORECASE is more selective, and
+ is sensitive to the locale's language, but it is not
+ available before Vista. */
+ if (w32_major_version >= 6)
+ flags |= LINGUISTIC_IGNORECASE;
+ else
+ flags |= NORM_IGNORECASE;
+ }
+ /* This approximates what glibc collation functions do when the
+ locale's codeset is UTF-8. */
+ if (!NILP (Vw32_collate_ignore_punctuation))
+ flags |= NORM_IGNORESYMBOLS;
+ val = pCompareStringW (lcid, flags, string1_w, -1, string2_w, -1);
+ SAFE_FREE ();
+ if (!val)
+ {
+ errno = EINVAL;
+ return _NSLCMPERROR;
+ }
+ return val - 2;
+}
+
void
syms_of_ntproc (void)
@@ -3255,6 +3448,20 @@ Any other non-nil value means do this even on remote and removable drives
where the performance impact may be noticeable even on modern hardware. */);
Vw32_get_true_file_attributes = Qlocal;
+ DEFVAR_LISP ("w32-collate-ignore-punctuation",
+ Vw32_collate_ignore_punctuation,
+ doc: /* Non-nil causes string collation functions ignore punctuation on MS-Windows.
+On Posix platforms, `string-collate-lessp' and `string-collate-equalp'
+ignore punctuation characters when they compare strings, if the
+locale's codeset is UTF-8, as in \"en_US.UTF-8\". Binding this option
+to a non-nil value will achieve a similar effect on MS-Windows, where
+locales with UTF-8 codeset are not supported.
+
+Note that setting this to non-nil will also ignore blanks and symbols
+in the strings. So do NOT use this option when comparing file names
+for equality, only when you need to sort them. */);
+ Vw32_collate_ignore_punctuation = Qnil;
+
staticpro (&Vw32_valid_locale_ids);
staticpro (&Vw32_valid_codepages);
}