Fix 'expand-file-name' during startup on MS-Windows
* src/w32.c (w32_init_file_name_codepage): New function, resets file_name_codepage and w32_ansi_code_page to undo the values recorded during dumping. (codepage_for_filenames): Fix an embarrassing typo. Ignore the cached value of file-name encoding if it is nil, i.e. not initialized yet. Actually cache the last used file-name encoding to avoid calling APIs when not necessary. * src/w32.h (w32_init_file_name_codepage): Add prototype. * src/w32term.c (syms_of_w32term): Set the value of w32_unicode_filenames according to the OS version. This avoids resetting it during startup, which then causes temacs to run with the incorrect value. * src/emacs.c (main): Call w32_init_file_name_codepage early during the startup. * src/fileio.c (Fexpand_file_name) [WINDOWSNT]: Update 'newdir' after converting $HOME to a UTF-8 string, so that 'newdirlim' is consistent with it. (Bug#25038) * lisp/international/mule-cmds.el (set-locale-environment): Set 'default-file-name-coding-system' to the ANSI codepage even in non-interactive sessions. * lisp/files.el (directory-abbrev-alist, abbreviated-home-dir): Doc fix. (abbreviate-file-name): Decode 'abbreviated-home-dir' if it is a unibyte string. * doc/lispref/files.texi (Directory Names): Index 'directory-abbrev-alist'.
This commit is contained in:
parent
46065291fa
commit
5878abf87b
8 changed files with 64 additions and 23 deletions
|
@ -2151,6 +2151,7 @@ function:
|
||||||
|
|
||||||
@cindex file name abbreviations
|
@cindex file name abbreviations
|
||||||
@cindex abbreviated file names
|
@cindex abbreviated file names
|
||||||
|
@vindex directory-abbrev-alist
|
||||||
@defun abbreviate-file-name filename
|
@defun abbreviate-file-name filename
|
||||||
@anchor{abbreviate-file-name}
|
@anchor{abbreviate-file-name}
|
||||||
This function returns an abbreviated form of @var{filename}. It
|
This function returns an abbreviated form of @var{filename}. It
|
||||||
|
|
|
@ -51,20 +51,21 @@ when it has unsaved changes."
|
||||||
nil
|
nil
|
||||||
"Alist of abbreviations for file directories.
|
"Alist of abbreviations for file directories.
|
||||||
A list of elements of the form (FROM . TO), each meaning to replace
|
A list of elements of the form (FROM . TO), each meaning to replace
|
||||||
FROM with TO when it appears in a directory name. This replacement is
|
a match for FROM with TO when a directory name matches FROM. This
|
||||||
done when setting up the default directory of a newly visited file.
|
replacement is done when setting up the default directory of a
|
||||||
|
newly visited file buffer.
|
||||||
|
|
||||||
FROM is matched against directory names anchored at the first
|
FROM is a regexp that is matched against directory names anchored at
|
||||||
character, so it should start with a \"\\\\\\=`\", or, if directory
|
the first character, so it should start with a \"\\\\\\=`\", or, if
|
||||||
names cannot have embedded newlines, with a \"^\".
|
directory names cannot have embedded newlines, with a \"^\".
|
||||||
|
|
||||||
FROM and TO should be equivalent names, which refer to the
|
FROM and TO should be equivalent names, which refer to the
|
||||||
same directory. Do not use `~' in the TO strings;
|
same directory. TO should be an absolute directory name.
|
||||||
they should be ordinary absolute directory names.
|
Do not use `~' in the TO strings.
|
||||||
|
|
||||||
Use this feature when you have directories which you normally refer to
|
Use this feature when you have directories which you normally refer to
|
||||||
via absolute symbolic links. Make TO the name of the link, and FROM
|
via absolute symbolic links. Make TO the name of the link, and FROM
|
||||||
the name it is linked to."
|
a regexp matching the name it is linked to."
|
||||||
:type '(repeat (cons :format "%v"
|
:type '(repeat (cons :format "%v"
|
||||||
:value ("\\`" . "")
|
:value ("\\`" . "")
|
||||||
(regexp :tag "From")
|
(regexp :tag "From")
|
||||||
|
@ -1736,7 +1737,8 @@ Choose the buffer's name using `generate-new-buffer-name'."
|
||||||
(make-obsolete-variable 'automount-dir-prefix 'directory-abbrev-alist "24.3")
|
(make-obsolete-variable 'automount-dir-prefix 'directory-abbrev-alist "24.3")
|
||||||
|
|
||||||
(defvar abbreviated-home-dir nil
|
(defvar abbreviated-home-dir nil
|
||||||
"The user's homedir abbreviated according to `directory-abbrev-alist'.")
|
"Regexp matching the user's homedir at the beginning of file name.
|
||||||
|
The value includes abbreviation according to `directory-abbrev-alist'.")
|
||||||
|
|
||||||
(defun abbreviate-file-name (filename)
|
(defun abbreviate-file-name (filename)
|
||||||
"Return a version of FILENAME shortened using `directory-abbrev-alist'.
|
"Return a version of FILENAME shortened using `directory-abbrev-alist'.
|
||||||
|
@ -1770,8 +1772,23 @@ home directory is a root directory) and removes automounter prefixes
|
||||||
(or abbreviated-home-dir
|
(or abbreviated-home-dir
|
||||||
(setq abbreviated-home-dir
|
(setq abbreviated-home-dir
|
||||||
(let ((abbreviated-home-dir "$foo"))
|
(let ((abbreviated-home-dir "$foo"))
|
||||||
(concat "\\`" (abbreviate-file-name (expand-file-name "~"))
|
(setq abbreviated-home-dir
|
||||||
"\\(/\\|\\'\\)"))))
|
(concat "\\`"
|
||||||
|
(abbreviate-file-name (expand-file-name "~"))
|
||||||
|
"\\(/\\|\\'\\)"))
|
||||||
|
;; Depending on whether default-directory does or
|
||||||
|
;; doesn't include non-ASCII characters, the value
|
||||||
|
;; of abbreviated-home-dir could be multibyte or
|
||||||
|
;; unibyte. In the latter case, we need to decode
|
||||||
|
;; it. Note that this function is called for the
|
||||||
|
;; first time (from startup.el) when
|
||||||
|
;; locale-coding-system is already set up.
|
||||||
|
(if (multibyte-string-p abbreviated-home-dir)
|
||||||
|
abbreviated-home-dir
|
||||||
|
(decode-coding-string abbreviated-home-dir
|
||||||
|
(if (eq system-type 'windows-nt)
|
||||||
|
'utf-8
|
||||||
|
locale-coding-system))))))
|
||||||
|
|
||||||
;; If FILENAME starts with the abbreviated homedir,
|
;; If FILENAME starts with the abbreviated homedir,
|
||||||
;; make it start with `~' instead.
|
;; make it start with `~' instead.
|
||||||
|
|
|
@ -2704,10 +2704,12 @@ See also `locale-charset-language-names', `locale-language-names',
|
||||||
;; terminal-coding-system with the ANSI or console codepage.
|
;; terminal-coding-system with the ANSI or console codepage.
|
||||||
(when (and (eq system-type 'windows-nt)
|
(when (and (eq system-type 'windows-nt)
|
||||||
(boundp 'w32-ansi-code-page))
|
(boundp 'w32-ansi-code-page))
|
||||||
(let* ((code-page-coding
|
(let* ((ansi-code-page-coding
|
||||||
(intern (format "cp%d" (if noninteractive
|
(intern (format "cp%d" w32-ansi-code-page)))
|
||||||
(w32-get-console-codepage)
|
(code-page-coding
|
||||||
w32-ansi-code-page))))
|
(if noninteractive
|
||||||
|
(intern (format "cp%d" (w32-get-console-codepage)))
|
||||||
|
ansi-code-page-coding))
|
||||||
(output-coding
|
(output-coding
|
||||||
(if noninteractive
|
(if noninteractive
|
||||||
(intern (format "cp%d" (w32-get-console-output-codepage)))
|
(intern (format "cp%d" (w32-get-console-output-codepage)))
|
||||||
|
@ -2717,7 +2719,7 @@ See also `locale-charset-language-names', `locale-language-names',
|
||||||
(unless frame (setq locale-coding-system code-page-coding))
|
(unless frame (setq locale-coding-system code-page-coding))
|
||||||
(set-keyboard-coding-system code-page-coding frame)
|
(set-keyboard-coding-system code-page-coding frame)
|
||||||
(set-terminal-coding-system output-coding frame)
|
(set-terminal-coding-system output-coding frame)
|
||||||
(setq default-file-name-coding-system code-page-coding))))
|
(setq default-file-name-coding-system ansi-code-page-coding))))
|
||||||
|
|
||||||
(when (eq system-type 'darwin)
|
(when (eq system-type 'darwin)
|
||||||
;; On Darwin, file names are always encoded in utf-8, no matter
|
;; On Darwin, file names are always encoded in utf-8, no matter
|
||||||
|
|
|
@ -716,6 +716,9 @@ main (int argc, char **argv)
|
||||||
to have non-stub implementations of APIs we need to convert file
|
to have non-stub implementations of APIs we need to convert file
|
||||||
names between UTF-8 and the system's ANSI codepage. */
|
names between UTF-8 and the system's ANSI codepage. */
|
||||||
maybe_load_unicows_dll ();
|
maybe_load_unicows_dll ();
|
||||||
|
/* Initialize the codepage for file names, needed to decode
|
||||||
|
non-ASCII file names during startup. */
|
||||||
|
w32_init_file_name_codepage ();
|
||||||
#endif
|
#endif
|
||||||
/* This has to be done before module_init is called below, so that
|
/* This has to be done before module_init is called below, so that
|
||||||
the latter could use the thread ID of the main thread. */
|
the latter could use the thread ID of the main thread. */
|
||||||
|
|
|
@ -1063,8 +1063,6 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|
||||||
if (!(newdir = egetenv ("HOME")))
|
if (!(newdir = egetenv ("HOME")))
|
||||||
newdir = newdirlim = "";
|
newdir = newdirlim = "";
|
||||||
nm++;
|
nm++;
|
||||||
/* `egetenv' may return a unibyte string, which will bite us since
|
|
||||||
we expect the directory to be multibyte. */
|
|
||||||
#ifdef WINDOWSNT
|
#ifdef WINDOWSNT
|
||||||
if (newdir[0])
|
if (newdir[0])
|
||||||
{
|
{
|
||||||
|
@ -1072,11 +1070,14 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|
||||||
|
|
||||||
filename_from_ansi (newdir, newdir_utf8);
|
filename_from_ansi (newdir, newdir_utf8);
|
||||||
tem = make_unibyte_string (newdir_utf8, strlen (newdir_utf8));
|
tem = make_unibyte_string (newdir_utf8, strlen (newdir_utf8));
|
||||||
|
newdir = SSDATA (tem);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
tem = build_string (newdir);
|
tem = build_string (newdir);
|
||||||
newdirlim = newdir + SBYTES (tem);
|
newdirlim = newdir + SBYTES (tem);
|
||||||
|
/* `egetenv' may return a unibyte string, which will bite us
|
||||||
|
if we expect the directory to be multibyte. */
|
||||||
if (multibyte && !STRING_MULTIBYTE (tem))
|
if (multibyte && !STRING_MULTIBYTE (tem))
|
||||||
{
|
{
|
||||||
hdir = DECODE_FILE (tem);
|
hdir = DECODE_FILE (tem);
|
||||||
|
@ -1105,8 +1106,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|
||||||
|
|
||||||
newdir = pw->pw_dir;
|
newdir = pw->pw_dir;
|
||||||
/* `getpwnam' may return a unibyte string, which will
|
/* `getpwnam' may return a unibyte string, which will
|
||||||
bite us since we expect the directory to be
|
bite us when we expect the directory to be multibyte. */
|
||||||
multibyte. */
|
|
||||||
tem = make_unibyte_string (newdir, strlen (newdir));
|
tem = make_unibyte_string (newdir, strlen (newdir));
|
||||||
newdirlim = newdir + SBYTES (tem);
|
newdirlim = newdir + SBYTES (tem);
|
||||||
if (multibyte && !STRING_MULTIBYTE (tem))
|
if (multibyte && !STRING_MULTIBYTE (tem))
|
||||||
|
|
18
src/w32.c
18
src/w32.c
|
@ -1493,6 +1493,16 @@ w32_valid_pointer_p (void *p, int size)
|
||||||
/* Current codepage for encoding file names. */
|
/* Current codepage for encoding file names. */
|
||||||
static int file_name_codepage;
|
static int file_name_codepage;
|
||||||
|
|
||||||
|
/* Initialize the codepage used for decoding file names. This is
|
||||||
|
needed to undo the value recorded during dumping, which might not
|
||||||
|
be correct when we run the dumped Emacs. */
|
||||||
|
void
|
||||||
|
w32_init_file_name_codepage (void)
|
||||||
|
{
|
||||||
|
file_name_codepage = CP_ACP;
|
||||||
|
w32_ansi_code_page = CP_ACP;
|
||||||
|
}
|
||||||
|
|
||||||
/* Produce a Windows ANSI codepage suitable for encoding file names.
|
/* Produce a Windows ANSI codepage suitable for encoding file names.
|
||||||
Return the information about that codepage in CP_INFO. */
|
Return the information about that codepage in CP_INFO. */
|
||||||
int
|
int
|
||||||
|
@ -1509,12 +1519,13 @@ codepage_for_filenames (CPINFO *cp_info)
|
||||||
if (NILP (current_encoding))
|
if (NILP (current_encoding))
|
||||||
current_encoding = Vdefault_file_name_coding_system;
|
current_encoding = Vdefault_file_name_coding_system;
|
||||||
|
|
||||||
if (!EQ (last_file_name_encoding, current_encoding))
|
if (!EQ (last_file_name_encoding, current_encoding)
|
||||||
|
|| NILP (last_file_name_encoding))
|
||||||
{
|
{
|
||||||
/* Default to the current ANSI codepage. */
|
/* Default to the current ANSI codepage. */
|
||||||
file_name_codepage = w32_ansi_code_page;
|
file_name_codepage = w32_ansi_code_page;
|
||||||
|
|
||||||
if (NILP (current_encoding))
|
if (!NILP (current_encoding))
|
||||||
{
|
{
|
||||||
char *cpname = SSDATA (SYMBOL_NAME (current_encoding));
|
char *cpname = SSDATA (SYMBOL_NAME (current_encoding));
|
||||||
char *cp = NULL, *end;
|
char *cp = NULL, *end;
|
||||||
|
@ -1543,6 +1554,9 @@ codepage_for_filenames (CPINFO *cp_info)
|
||||||
if (!GetCPInfo (file_name_codepage, &cp))
|
if (!GetCPInfo (file_name_codepage, &cp))
|
||||||
emacs_abort ();
|
emacs_abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Cache the new value. */
|
||||||
|
last_file_name_encoding = current_encoding;
|
||||||
}
|
}
|
||||||
if (cp_info)
|
if (cp_info)
|
||||||
*cp_info = cp;
|
*cp_info = cp;
|
||||||
|
|
|
@ -195,6 +195,7 @@ extern int filename_from_ansi (const char *, char *);
|
||||||
extern int filename_to_ansi (const char *, char *);
|
extern int filename_to_ansi (const char *, char *);
|
||||||
extern int filename_from_utf16 (const wchar_t *, char *);
|
extern int filename_from_utf16 (const wchar_t *, char *);
|
||||||
extern int filename_to_utf16 (const char *, wchar_t *);
|
extern int filename_to_utf16 (const char *, wchar_t *);
|
||||||
|
extern void w32_init_file_name_codepage (void);
|
||||||
extern int codepage_for_filenames (CPINFO *);
|
extern int codepage_for_filenames (CPINFO *);
|
||||||
extern Lisp_Object ansi_encode_filename (Lisp_Object);
|
extern Lisp_Object ansi_encode_filename (Lisp_Object);
|
||||||
extern int w32_copy_file (const char *, const char *, int, int, int);
|
extern int w32_copy_file (const char *, const char *, int, int, int);
|
||||||
|
|
|
@ -7157,7 +7157,10 @@ specified by `file-name-coding-system'.
|
||||||
This variable is set to non-nil by default when Emacs runs on Windows
|
This variable is set to non-nil by default when Emacs runs on Windows
|
||||||
systems of the NT family, including W2K, XP, Vista, Windows 7 and
|
systems of the NT family, including W2K, XP, Vista, Windows 7 and
|
||||||
Windows 8. It is set to nil on Windows 9X. */);
|
Windows 8. It is set to nil on Windows 9X. */);
|
||||||
w32_unicode_filenames = 0;
|
if (os_subtype == OS_9X)
|
||||||
|
w32_unicode_filenames = 0;
|
||||||
|
else
|
||||||
|
w32_unicode_filenames = 1;
|
||||||
|
|
||||||
|
|
||||||
/* FIXME: The following variable will be (hopefully) removed
|
/* FIXME: The following variable will be (hopefully) removed
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue