summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2013-11-02 15:03:32 +0200
committerEli Zaretskii <eliz@gnu.org>2013-11-02 15:03:32 +0200
commit1fd201bb1d720d0c5ab727a3972363778eef834f (patch)
tree508abf22dbb91d24309869bc42a93e814f9fbcd6 /src
parent5c4a19a90f803ed46629c2bdc1ac3d3563caa738 (diff)
downloademacs-1fd201bb1d720d0c5ab727a3972363778eef834f.tar.gz
Adapted dostounix_filename. w32-short/long-filename work with wide APIs.
Diffstat (limited to 'src')
-rw-r--r--src/emacs.c19
-rw-r--r--src/fileio.c20
-rw-r--r--src/filelock.c2
-rw-r--r--src/msdos.c6
-rw-r--r--src/msdos.h2
-rw-r--r--src/termcap.c2
-rw-r--r--src/unexw32.c10
-rw-r--r--src/w32.c202
-rw-r--r--src/w32.h7
-rw-r--r--src/w32fns.c4
-rw-r--r--src/w32proc.c14
11 files changed, 131 insertions, 157 deletions
diff --git a/src/emacs.c b/src/emacs.c
index 06b8d290cae..a58829e8918 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -2153,9 +2153,15 @@ decode_env_path (const char *evarname, const char *defalt)
Lisp_Object lpath, element, tem;
#ifdef WINDOWSNT
bool defaulted = 0;
- const char *emacs_dir = egetenv ("emacs_dir");
static const char *emacs_dir_env = "%emacs_dir%/";
const size_t emacs_dir_len = strlen (emacs_dir_env);
+ const char *edir = egetenv ("emacs_dir");
+ char emacs_dir[MAX_UTF8_PATH];
+
+ /* egetenv looks in process-environment, which holds the variables
+ in their original system-locale encoding. We need emacs_dir to
+ be in UTF-8. */
+ filename_from_ansi (edir, emacs_dir);
#endif
/* It's okay to use getenv here, because this function is only used
@@ -2176,9 +2182,16 @@ decode_env_path (const char *evarname, const char *defalt)
/* Ensure values from the environment use the proper directory separator. */
if (path)
{
- char *path_copy = alloca (strlen (path) + 1);
+ char *path_copy;
+
+#ifdef WINDOWSNT
+ path_copy = alloca (MAX_UTF8_PATH);
+ filename_from_ansi (path, path_copy);
+#else /* MSDOS */
+ path_copy = alloca (strlen (path) + 1);
strcpy (path_copy, path);
- dostounix_filename (path_copy, 0);
+#endif
+ dostounix_filename (path_copy);
path = path_copy;
}
#endif
diff --git a/src/fileio.c b/src/fileio.c
index dc6d80932c4..eeaa736290c 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -459,7 +459,8 @@ Given a Unix syntax file name, returns a string ending in slash. */)
strcat (res, "/");
beg = res;
p = beg + strlen (beg);
- dostounix_filename (beg, 0);
+ dostounix_filename (beg);
+ /* FIXME: Figure out the multibyte vs unibyte stuff here. */
tem_fn = make_specified_string (beg, -1, p - beg,
STRING_MULTIBYTE (filename));
}
@@ -470,7 +471,7 @@ Given a Unix syntax file name, returns a string ending in slash. */)
else if (STRING_MULTIBYTE (filename))
{
tem_fn = make_specified_string (beg, -1, p - beg, 1);
- dostounix_filename (SSDATA (tem_fn), 1);
+ dostounix_filename (SSDATA (tem_fn));
#ifdef WINDOWSNT
if (!NILP (Vw32_downcase_file_names))
tem_fn = Fdowncase (tem_fn);
@@ -478,7 +479,7 @@ Given a Unix syntax file name, returns a string ending in slash. */)
}
else
{
- dostounix_filename (beg, 0);
+ dostounix_filename (beg);
tem_fn = make_specified_string (beg, -1, p - beg, 0);
}
return tem_fn;
@@ -582,7 +583,7 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
dst[srclen++] = DIRECTORY_SEP;
dst[srclen] = 0;
#ifdef DOS_NT
- dostounix_filename (dst, multibyte);
+ dostounix_filename (dst);
#endif
return srclen;
}
@@ -651,7 +652,7 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
memcpy (dst, src, srclen);
dst[srclen] = 0;
#ifdef DOS_NT
- dostounix_filename (dst, multibyte);
+ dostounix_filename (dst);
#endif
return srclen;
}
@@ -1082,7 +1083,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
#ifdef DOS_NT
/* Make sure directories are all separated with /, but
avoid allocation of a new string when not required. */
- dostounix_filename (nm, multibyte);
+ /* FIXME: Figure out multibyte and downcase here. */
+ dostounix_filename (nm);
#ifdef WINDOWSNT
if (IS_DIRECTORY_SEP (nm[1]))
{
@@ -1465,7 +1467,8 @@ filesystem tree, not (expand-file-name ".." dirname). */)
target[1] = ':';
}
result = make_specified_string (target, -1, o - target, multibyte);
- dostounix_filename (SSDATA (result), multibyte);
+ /* FIXME: Figure out the multibyte and downcase here. */
+ dostounix_filename (SSDATA (result));
#ifdef WINDOWSNT
if (!NILP (Vw32_downcase_file_names))
result = Fdowncase (result);
@@ -1749,7 +1752,8 @@ those `/' is discarded. */)
nm = xlispstrdupa (filename);
#ifdef DOS_NT
- dostounix_filename (nm, multibyte);
+ /* FIXME: Figure out multibyte and downcase. */
+ dostounix_filename (nm);
substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
#endif
endp = nm + SBYTES (filename);
diff --git a/src/filelock.c b/src/filelock.c
index 2f53047f526..82ffd5d172b 100644
--- a/src/filelock.c
+++ b/src/filelock.c
@@ -689,7 +689,7 @@ lock_file (Lisp_Object fn)
/* Ensure we have only '/' separators, to avoid problems with
looking (inside fill_in_lock_file_name) for backslashes in file
names encoded by some DBCS codepage. */
- dostounix_filename (SSDATA (fn), 1);
+ dostounix_filename (SSDATA (fn));
#endif
encoded_fn = ENCODE_FILE (fn);
diff --git a/src/msdos.c b/src/msdos.c
index 2ba7a16a443..cb4f8c3df89 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -3295,7 +3295,7 @@ void msdos_downcase_filename (unsigned char *);
/* Destructively turn backslashes into slashes. */
void
-dostounix_filename (char *p, int ignore)
+dostounix_filename (char *p)
{
msdos_downcase_filename (p);
@@ -3559,7 +3559,7 @@ init_environment (int argc, char **argv, int skip_args)
if (!s) s = "c:/command.com";
t = alloca (strlen (s) + 1);
strcpy (t, s);
- dostounix_filename (t, 0);
+ dostounix_filename (t);
setenv ("SHELL", t, 0);
/* PATH is also downcased and backslashes mirrored. */
@@ -3569,7 +3569,7 @@ init_environment (int argc, char **argv, int skip_args)
/* Current directory is always considered part of MsDos's path but it is
not normally mentioned. Now it is. */
strcat (strcpy (t, ".;"), s);
- dostounix_filename (t, 0); /* Not a single file name, but this should work. */
+ dostounix_filename (t); /* Not a single file name, but this should work. */
setenv ("PATH", t, 1);
/* In some sense all dos users have root privileges, so... */
diff --git a/src/msdos.h b/src/msdos.h
index 27090324b44..11d7eb5c3e1 100644
--- a/src/msdos.h
+++ b/src/msdos.h
@@ -29,7 +29,7 @@ void dos_set_window_size (int *, int *);
int getdefdir (int, char*);
void unixtodos_filename (char *);
-void dostounix_filename (char *, int);
+void dostounix_filename (char *);
char *rootrelativepath (char *);
void init_environment (int, char **, int);
void internal_terminal_init (void);
diff --git a/src/termcap.c b/src/termcap.c
index aa225d9b3b1..f0819266318 100644
--- a/src/termcap.c
+++ b/src/termcap.c
@@ -393,7 +393,7 @@ tgetent (char *bp, const char *name)
if (termcap_name && (*termcap_name == '\\'
|| *termcap_name == '/'
|| termcap_name[1] == ':'))
- dostounix_filename (termcap_name, 0);
+ dostounix_filename (termcap_name);
#endif
filep = termcap_name && valid_filename_p (termcap_name);
diff --git a/src/unexw32.c b/src/unexw32.c
index a01ac799592..5320ec1e371 100644
--- a/src/unexw32.c
+++ b/src/unexw32.c
@@ -728,9 +728,15 @@ unexec (const char *new_name, const char *old_name)
char *q;
/* Ignore old_name, and get our actual location from the OS. */
- if (!GetModuleFileName (NULL, in_filename, MAX_PATH))
+ if (!GetModuleFileNameA (NULL, in_filename, MAX_PATH))
abort ();
- dostounix_filename (in_filename, 0);
+
+ /* Can't use dostounix_filename here, since that needs its file name
+ argument encoded in UTF-8. */
+ for (p = in_filename; *p; p = CharNextA (p))
+ if (*p == '\\')
+ *p = '/';
+
strcpy (out_filename, in_filename);
/* Change the base of the output filename to match the requested name. */
diff --git a/src/w32.c b/src/w32.c
index 09d78141e14..396a8cdd08b 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1336,7 +1336,7 @@ filename_to_ansi (const char *fn_in, char *fn_out)
return -1;
}
-static int
+int
filename_from_ansi (const char *fn_in, char *fn_out)
{
wchar_t fn_utf16[MAXPATHLEN];
@@ -1799,31 +1799,20 @@ max_filename_mbslen (void)
return cp_info.MaxCharSize;
}
-/* Normalize filename by converting all path separators to
- the specified separator. Also conditionally convert upper
- case path name components to lower case. */
+/* Normalize filename by converting in-place all of its path
+ separators to the separator specified by PATH_SEP. */
static void
-normalize_filename (register char *fp, char path_sep, int multibyte)
+normalize_filename (register char *fp, char path_sep)
{
- char sep;
- char *elem, *p2;
- int dbcs_p = max_filename_mbslen () > 1;
-
- /* Multibyte file names are in the Emacs internal representation, so
- we can traverse them by bytes with no problems. */
- if (multibyte)
- dbcs_p = 0;
+ char *p2;
/* Always lower-case drive letters a-z, even if the filesystem
preserves case in filenames.
This is so filenames can be compared by string comparison
functions that are case-sensitive. Even case-preserving filesystems
do not distinguish case in drive letters. */
- if (dbcs_p)
- p2 = CharNextExA (file_name_codepage, fp, 0);
- else
- p2 = fp + 1;
+ p2 = fp + 1;
if (*p2 == ':' && *fp >= 'A' && *fp <= 'Z')
{
@@ -1831,68 +1820,26 @@ normalize_filename (register char *fp, char path_sep, int multibyte)
fp += 2;
}
- if (multibyte || NILP (Vw32_downcase_file_names))
+ while (*fp)
{
- while (*fp)
- {
- if (*fp == '/' || *fp == '\\')
- *fp = path_sep;
- if (!dbcs_p)
- fp++;
- else
- fp = CharNextExA (file_name_codepage, fp, 0);
- }
- return;
+ if (*fp == '/' || *fp == '\\')
+ *fp = path_sep;
+ fp++;
}
-
- sep = path_sep; /* convert to this path separator */
- elem = fp; /* start of current path element */
-
- do {
- if (*fp >= 'a' && *fp <= 'z')
- elem = 0; /* don't convert this element */
-
- if (*fp == 0 || *fp == ':')
- {
- sep = *fp; /* restore current separator (or 0) */
- *fp = '/'; /* after conversion of this element */
- }
-
- if (*fp == '/' || *fp == '\\')
- {
- if (elem && elem != fp)
- {
- *fp = 0; /* temporary end of string */
- _mbslwr (elem); /* while we convert to lower case */
- }
- *fp = sep; /* convert (or restore) path separator */
- elem = fp + 1; /* next element starts after separator */
- sep = path_sep;
- }
- if (*fp)
- {
- if (!dbcs_p)
- fp++;
- else
- fp = CharNextExA (file_name_codepage, fp, 0);
- }
- } while (*fp);
}
-/* Destructively turn backslashes into slashes. MULTIBYTE non-zero
- means the file name is a multibyte string in Emacs's internal
- representation. */
+/* Destructively turn backslashes into slashes. */
void
-dostounix_filename (register char *p, int multibyte)
+dostounix_filename (register char *p)
{
- normalize_filename (p, '/', multibyte);
+ normalize_filename (p, '/');
}
/* Destructively turn slashes into backslashes. */
void
unixtodos_filename (register char *p)
{
- normalize_filename (p, '\\', 0);
+ normalize_filename (p, '\\');
}
/* Remove all CR's that are followed by a LF.
@@ -1943,17 +1890,13 @@ parse_root (char * name, char ** pPath)
else if (IS_DIRECTORY_SEP (name[0]) && IS_DIRECTORY_SEP (name[1]))
{
int slashes = 2;
- int dbcs_p = max_filename_mbslen () > 1;
name += 2;
do
{
if (IS_DIRECTORY_SEP (*name) && --slashes == 0)
break;
- if (dbcs_p)
- name = CharNextExA (file_name_codepage, name, 0);
- else
- name++;
+ name++;
}
while ( *name );
if (IS_DIRECTORY_SEP (name[0]))
@@ -1970,23 +1913,44 @@ parse_root (char * name, char ** pPath)
static int
get_long_basename (char * name, char * buf, int size)
{
- WIN32_FIND_DATA find_data;
HANDLE dir_handle;
+ char fname_utf8[MAX_UTF8_PATH];
int len = 0;
+ int cstatus;
- /* must be valid filename, no wild cards or other invalid characters */
- if (_mbspbrk (name, "*?|<>\""))
+ /* Must be valid filename, no wild cards or other invalid characters. */
+ if (strpbrk (name, "*?|<>\""))
return 0;
- dir_handle = FindFirstFile (name, &find_data);
- if (dir_handle != INVALID_HANDLE_VALUE)
+ if (w32_unicode_filenames)
{
- if ((len = strlen (find_data.cFileName)) < size)
- memcpy (buf, find_data.cFileName, len + 1);
- else
- len = 0;
- FindClose (dir_handle);
+ wchar_t fname_utf16[MAX_PATH];
+ WIN32_FIND_DATAW find_data_wide;
+
+ filename_to_utf16 (name, fname_utf16);
+ dir_handle = FindFirstFileW (fname_utf16, &find_data_wide);
+ if (dir_handle != INVALID_HANDLE_VALUE)
+ cstatus = filename_from_utf16 (find_data_wide.cFileName, fname_utf8);
+ }
+ else
+ {
+ char fname_ansi[MAX_PATH];
+ WIN32_FIND_DATAA find_data_ansi;
+
+ filename_to_ansi (name, fname_ansi);
+ dir_handle = FindFirstFileA (fname_ansi, &find_data_ansi);
+ if (dir_handle != INVALID_HANDLE_VALUE)
+ cstatus = filename_from_ansi (find_data_ansi.cFileName, fname_utf8);
}
+
+ if (cstatus == 0 && (len = strlen (fname_utf8)) < size)
+ memcpy (buf, fname_utf8, len + 1);
+ else
+ len = 0;
+
+ if (dir_handle != INVALID_HANDLE_VALUE)
+ FindClose (dir_handle);
+
return len;
}
@@ -1997,11 +1961,11 @@ w32_get_long_filename (char * name, char * buf, int size)
char * o = buf;
char * p;
char * q;
- char full[ MAX_PATH ];
+ char full[ MAX_UTF8_PATH ];
int len;
len = strlen (name);
- if (len >= MAX_PATH)
+ if (len >= MAX_UTF8_PATH)
return FALSE;
/* Use local copy for destructive modification. */
@@ -2018,7 +1982,7 @@ w32_get_long_filename (char * name, char * buf, int size)
while (p != NULL && *p)
{
q = p;
- p = _mbschr (q, '\\');
+ p = strchr (q, '\\');
if (p) *p = '\0';
len = get_long_basename (full, o, size);
if (len > 0)
@@ -2042,6 +2006,29 @@ w32_get_long_filename (char * name, char * buf, int size)
return TRUE;
}
+unsigned int
+w32_get_short_filename (char * name, char * buf, int size)
+{
+ if (w32_unicode_filenames)
+ {
+ wchar_t name_utf16[MAX_PATH], short_name[MAX_PATH];
+ unsigned int retval;
+
+ filename_to_utf16 (name, name_utf16);
+ retval = GetShortPathNameW (name_utf16, short_name, size);
+ if (retval && retval < size)
+ filename_from_utf16 (short_name, buf);
+ return retval;
+ }
+ else
+ {
+ char name_ansi[MAX_PATH];
+
+ filename_to_ansi (name, name_ansi);
+ return GetShortPathNameA (name_ansi, buf, size);
+ }
+}
+
static int
is_unc_volume (const char *filename)
{
@@ -2506,7 +2493,7 @@ emacs_root_dir (void)
emacs_abort ();
strcpy (root_dir, p);
root_dir[parse_root (root_dir, NULL)] = '\0';
- dostounix_filename (root_dir, 0);
+ dostounix_filename (root_dir);
return root_dir;
}
@@ -3937,49 +3924,6 @@ convert_from_time_t (time_t time, FILETIME * pft)
pft->dwLowDateTime = tmp.LowPart;
}
-#if 0
-/* No reason to keep this; faking inode values either by hashing or even
- using the file index from GetInformationByHandle, is not perfect and
- so by default Emacs doesn't use the inode values on Windows.
- Instead, we now determine file-truename correctly (except for
- possible drive aliasing etc). */
-
-/* Modified version of "PJW" algorithm (see the "Dragon" compiler book). */
-static unsigned
-hashval (const unsigned char * str)
-{
- unsigned h = 0;
- while (*str)
- {
- h = (h << 4) + *str++;
- h ^= (h >> 28);
- }
- return h;
-}
-
-/* Return the hash value of the canonical pathname, excluding the
- drive/UNC header, to get a hopefully unique inode number. */
-static DWORD
-generate_inode_val (const char * name)
-{
- char fullname[ MAX_PATH ];
- char * p;
- unsigned hash;
-
- /* Get the truly canonical filename, if it exists. (Note: this
- doesn't resolve aliasing due to subst commands, or recognize hard
- links. */
- if (!w32_get_long_filename ((char *)name, fullname, MAX_PATH))
- emacs_abort ();
-
- parse_root (fullname, &p);
- /* Normal W32 filesystems are still case insensitive. */
- _strlwr (p);
- return hashval (p);
-}
-
-#endif
-
static PSECURITY_DESCRIPTOR
get_file_security_desc_by_handle (HANDLE h)
{
diff --git a/src/w32.h b/src/w32.h
index c836937bd66..80756e8e4ff 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -152,6 +152,9 @@ extern int w32_valid_pointer_p (void *, int);
/* Get long (aka "true") form of file name, if it exists. */
extern BOOL w32_get_long_filename (char * name, char * buf, int size);
+/* Get the short (a.k.a. "8+3") form of a file name. */
+extern unsigned int w32_get_short_filename (char *, char *, int);
+
/* Prepare our standard handles for proper inheritance by child processes. */
extern void prepare_standard_handles (int in, int out,
int err, HANDLE handles[4]);
@@ -181,8 +184,10 @@ extern void init_environment (char **);
extern void check_windows_init_file (void);
extern void syms_of_ntproc (void);
extern void syms_of_ntterm (void);
-extern void dostounix_filename (register char *, int);
+extern void dostounix_filename (register char *);
extern void unixtodos_filename (register char *);
+extern int filename_from_ansi (const char *, char *);
+
extern BOOL init_winsock (int load_now);
extern void srandom (int);
extern int random (void);
diff --git a/src/w32fns.c b/src/w32fns.c
index c98c84c8542..3e60d68023b 100644
--- a/src/w32fns.c
+++ b/src/w32fns.c
@@ -6466,8 +6466,8 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
#ifdef NTGUI_UNICODE
filename = from_unicode_buffer (filename_buf);
#else /* !NTGUI_UNICODE */
- dostounix_filename (filename_buf, 0);
- filename = DECODE_FILE (build_string (filename_buf));
+ filename = DECODE_FILE (build_unibyte_string (filename_buf));
+ dostounix_filename (SSDATA (filename));
#endif /* NTGUI_UNICODE */
#ifdef CYGWIN
diff --git a/src/w32proc.c b/src/w32proc.c
index ea16f26a0ee..89748267bc6 100644
--- a/src/w32proc.c
+++ b/src/w32proc.c
@@ -2647,10 +2647,11 @@ All path elements in FILENAME are converted to their short names. */)
filename = Fexpand_file_name (filename, Qnil);
/* luckily, this returns the short version of each element in the path. */
- if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0)
+ if (w32_get_short_filename (SDATA (ENCODE_FILE (filename)),
+ shortname, MAX_PATH) == 0)
return Qnil;
- dostounix_filename (shortname, 0);
+ dostounix_filename (shortname);
/* No need to DECODE_FILE, because 8.3 names are pure ASCII. */
return build_string (shortname);
@@ -2664,7 +2665,7 @@ If FILENAME does not exist, return nil.
All path elements in FILENAME are converted to their long names. */)
(Lisp_Object filename)
{
- char longname[ MAX_PATH ];
+ char longname[ MAX_UTF8_PATH ];
int drive_only = 0;
CHECK_STRING (filename);
@@ -2676,10 +2677,11 @@ All path elements in FILENAME are converted to their long names. */)
/* first expand it. */
filename = Fexpand_file_name (filename, Qnil);
- if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH))
+ if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname,
+ MAX_UTF8_PATH))
return Qnil;
- dostounix_filename (longname, 0);
+ dostounix_filename (longname);
/* If we were passed only a drive, make sure that a slash is not appended
for consistency with directories. Allow for drive mapping via SUBST
@@ -2687,7 +2689,7 @@ All path elements in FILENAME are converted to their long names. */)
if (drive_only && longname[1] == ':' && longname[2] == '/' && !longname[3])
longname[2] = '\0';
- return DECODE_FILE (build_string (longname));
+ return DECODE_FILE (build_unibyte_string (longname));
}
DEFUN ("w32-set-process-priority", Fw32_set_process_priority,