aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2016-11-28 17:43:25 +0200
committerEli Zaretskii2016-11-28 17:43:25 +0200
commit5878abf87b6b3ead1367cbae5cc6b0743349f611 (patch)
tree83fef8ba83ca1733c6a95e3201db9be45558ba07
parent46065291fa0807a10180b958285f5d375cf05914 (diff)
downloademacs-5878abf87b6b3ead1367cbae5cc6b0743349f611.tar.gz
emacs-5878abf87b6b3ead1367cbae5cc6b0743349f611.zip
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'.
-rw-r--r--doc/lispref/files.texi1
-rw-r--r--lisp/files.el39
-rw-r--r--lisp/international/mule-cmds.el12
-rw-r--r--src/emacs.c3
-rw-r--r--src/fileio.c8
-rw-r--r--src/w32.c18
-rw-r--r--src/w32.h1
-rw-r--r--src/w32term.c5
8 files changed, 64 insertions, 23 deletions
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 544992d4ba5..85c80d76f73 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -2151,6 +2151,7 @@ function:
2151 2151
2152@cindex file name abbreviations 2152@cindex file name abbreviations
2153@cindex abbreviated file names 2153@cindex abbreviated file names
2154@vindex directory-abbrev-alist
2154@defun abbreviate-file-name filename 2155@defun abbreviate-file-name filename
2155@anchor{abbreviate-file-name} 2156@anchor{abbreviate-file-name}
2156This function returns an abbreviated form of @var{filename}. It 2157This function returns an abbreviated form of @var{filename}. It
diff --git a/lisp/files.el b/lisp/files.el
index fa630731b8d..45646b186af 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -51,20 +51,21 @@ when it has unsaved changes."
51 nil 51 nil
52 "Alist of abbreviations for file directories. 52 "Alist of abbreviations for file directories.
53A list of elements of the form (FROM . TO), each meaning to replace 53A list of elements of the form (FROM . TO), each meaning to replace
54FROM with TO when it appears in a directory name. This replacement is 54a match for FROM with TO when a directory name matches FROM. This
55done when setting up the default directory of a newly visited file. 55replacement is done when setting up the default directory of a
56newly visited file buffer.
56 57
57FROM is matched against directory names anchored at the first 58FROM is a regexp that is matched against directory names anchored at
58character, so it should start with a \"\\\\\\=`\", or, if directory 59the first character, so it should start with a \"\\\\\\=`\", or, if
59names cannot have embedded newlines, with a \"^\". 60directory names cannot have embedded newlines, with a \"^\".
60 61
61FROM and TO should be equivalent names, which refer to the 62FROM and TO should be equivalent names, which refer to the
62same directory. Do not use `~' in the TO strings; 63same directory. TO should be an absolute directory name.
63they should be ordinary absolute directory names. 64Do not use `~' in the TO strings.
64 65
65Use this feature when you have directories which you normally refer to 66Use this feature when you have directories which you normally refer to
66via absolute symbolic links. Make TO the name of the link, and FROM 67via absolute symbolic links. Make TO the name of the link, and FROM
67the name it is linked to." 68a regexp matching the name it is linked to."
68 :type '(repeat (cons :format "%v" 69 :type '(repeat (cons :format "%v"
69 :value ("\\`" . "") 70 :value ("\\`" . "")
70 (regexp :tag "From") 71 (regexp :tag "From")
@@ -1736,7 +1737,8 @@ Choose the buffer's name using `generate-new-buffer-name'."
1736(make-obsolete-variable 'automount-dir-prefix 'directory-abbrev-alist "24.3") 1737(make-obsolete-variable 'automount-dir-prefix 'directory-abbrev-alist "24.3")
1737 1738
1738(defvar abbreviated-home-dir nil 1739(defvar abbreviated-home-dir nil
1739 "The user's homedir abbreviated according to `directory-abbrev-alist'.") 1740 "Regexp matching the user's homedir at the beginning of file name.
1741The value includes abbreviation according to `directory-abbrev-alist'.")
1740 1742
1741(defun abbreviate-file-name (filename) 1743(defun abbreviate-file-name (filename)
1742 "Return a version of FILENAME shortened using `directory-abbrev-alist'. 1744 "Return a version of FILENAME shortened using `directory-abbrev-alist'.
@@ -1770,8 +1772,23 @@ home directory is a root directory) and removes automounter prefixes
1770 (or abbreviated-home-dir 1772 (or abbreviated-home-dir
1771 (setq abbreviated-home-dir 1773 (setq abbreviated-home-dir
1772 (let ((abbreviated-home-dir "$foo")) 1774 (let ((abbreviated-home-dir "$foo"))
1773 (concat "\\`" (abbreviate-file-name (expand-file-name "~")) 1775 (setq abbreviated-home-dir
1774 "\\(/\\|\\'\\)")))) 1776 (concat "\\`"
1777 (abbreviate-file-name (expand-file-name "~"))
1778 "\\(/\\|\\'\\)"))
1779 ;; Depending on whether default-directory does or
1780 ;; doesn't include non-ASCII characters, the value
1781 ;; of abbreviated-home-dir could be multibyte or
1782 ;; unibyte. In the latter case, we need to decode
1783 ;; it. Note that this function is called for the
1784 ;; first time (from startup.el) when
1785 ;; locale-coding-system is already set up.
1786 (if (multibyte-string-p abbreviated-home-dir)
1787 abbreviated-home-dir
1788 (decode-coding-string abbreviated-home-dir
1789 (if (eq system-type 'windows-nt)
1790 'utf-8
1791 locale-coding-system))))))
1775 1792
1776 ;; If FILENAME starts with the abbreviated homedir, 1793 ;; If FILENAME starts with the abbreviated homedir,
1777 ;; make it start with `~' instead. 1794 ;; make it start with `~' instead.
diff --git a/lisp/international/mule-cmds.el b/lisp/international/mule-cmds.el
index 5008fd5f27b..1ec7456c9e1 100644
--- a/lisp/international/mule-cmds.el
+++ b/lisp/international/mule-cmds.el
@@ -2704,10 +2704,12 @@ See also `locale-charset-language-names', `locale-language-names',
2704 ;; terminal-coding-system with the ANSI or console codepage. 2704 ;; terminal-coding-system with the ANSI or console codepage.
2705 (when (and (eq system-type 'windows-nt) 2705 (when (and (eq system-type 'windows-nt)
2706 (boundp 'w32-ansi-code-page)) 2706 (boundp 'w32-ansi-code-page))
2707 (let* ((code-page-coding 2707 (let* ((ansi-code-page-coding
2708 (intern (format "cp%d" (if noninteractive 2708 (intern (format "cp%d" w32-ansi-code-page)))
2709 (w32-get-console-codepage) 2709 (code-page-coding
2710 w32-ansi-code-page)))) 2710 (if noninteractive
2711 (intern (format "cp%d" (w32-get-console-codepage)))
2712 ansi-code-page-coding))
2711 (output-coding 2713 (output-coding
2712 (if noninteractive 2714 (if noninteractive
2713 (intern (format "cp%d" (w32-get-console-output-codepage))) 2715 (intern (format "cp%d" (w32-get-console-output-codepage)))
@@ -2717,7 +2719,7 @@ See also `locale-charset-language-names', `locale-language-names',
2717 (unless frame (setq locale-coding-system code-page-coding)) 2719 (unless frame (setq locale-coding-system code-page-coding))
2718 (set-keyboard-coding-system code-page-coding frame) 2720 (set-keyboard-coding-system code-page-coding frame)
2719 (set-terminal-coding-system output-coding frame) 2721 (set-terminal-coding-system output-coding frame)
2720 (setq default-file-name-coding-system code-page-coding)))) 2722 (setq default-file-name-coding-system ansi-code-page-coding))))
2721 2723
2722 (when (eq system-type 'darwin) 2724 (when (eq system-type 'darwin)
2723 ;; On Darwin, file names are always encoded in utf-8, no matter 2725 ;; On Darwin, file names are always encoded in utf-8, no matter
diff --git a/src/emacs.c b/src/emacs.c
index ce30ae741b2..16cf6cc0e4d 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -716,6 +716,9 @@ main (int argc, char **argv)
716 to have non-stub implementations of APIs we need to convert file 716 to have non-stub implementations of APIs we need to convert file
717 names between UTF-8 and the system's ANSI codepage. */ 717 names between UTF-8 and the system's ANSI codepage. */
718 maybe_load_unicows_dll (); 718 maybe_load_unicows_dll ();
719 /* Initialize the codepage for file names, needed to decode
720 non-ASCII file names during startup. */
721 w32_init_file_name_codepage ();
719#endif 722#endif
720 /* This has to be done before module_init is called below, so that 723 /* This has to be done before module_init is called below, so that
721 the latter could use the thread ID of the main thread. */ 724 the latter could use the thread ID of the main thread. */
diff --git a/src/fileio.c b/src/fileio.c
index c3b2be7c5f7..d94805f316b 100644
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -1063,8 +1063,6 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1063 if (!(newdir = egetenv ("HOME"))) 1063 if (!(newdir = egetenv ("HOME")))
1064 newdir = newdirlim = ""; 1064 newdir = newdirlim = "";
1065 nm++; 1065 nm++;
1066 /* `egetenv' may return a unibyte string, which will bite us since
1067 we expect the directory to be multibyte. */
1068#ifdef WINDOWSNT 1066#ifdef WINDOWSNT
1069 if (newdir[0]) 1067 if (newdir[0])
1070 { 1068 {
@@ -1072,11 +1070,14 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1072 1070
1073 filename_from_ansi (newdir, newdir_utf8); 1071 filename_from_ansi (newdir, newdir_utf8);
1074 tem = make_unibyte_string (newdir_utf8, strlen (newdir_utf8)); 1072 tem = make_unibyte_string (newdir_utf8, strlen (newdir_utf8));
1073 newdir = SSDATA (tem);
1075 } 1074 }
1076 else 1075 else
1077#endif 1076#endif
1078 tem = build_string (newdir); 1077 tem = build_string (newdir);
1079 newdirlim = newdir + SBYTES (tem); 1078 newdirlim = newdir + SBYTES (tem);
1079 /* `egetenv' may return a unibyte string, which will bite us
1080 if we expect the directory to be multibyte. */
1080 if (multibyte && !STRING_MULTIBYTE (tem)) 1081 if (multibyte && !STRING_MULTIBYTE (tem))
1081 { 1082 {
1082 hdir = DECODE_FILE (tem); 1083 hdir = DECODE_FILE (tem);
@@ -1105,8 +1106,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
1105 1106
1106 newdir = pw->pw_dir; 1107 newdir = pw->pw_dir;
1107 /* `getpwnam' may return a unibyte string, which will 1108 /* `getpwnam' may return a unibyte string, which will
1108 bite us since we expect the directory to be 1109 bite us when we expect the directory to be multibyte. */
1109 multibyte. */
1110 tem = make_unibyte_string (newdir, strlen (newdir)); 1110 tem = make_unibyte_string (newdir, strlen (newdir));
1111 newdirlim = newdir + SBYTES (tem); 1111 newdirlim = newdir + SBYTES (tem);
1112 if (multibyte && !STRING_MULTIBYTE (tem)) 1112 if (multibyte && !STRING_MULTIBYTE (tem))
diff --git a/src/w32.c b/src/w32.c
index 793bc0f28d0..7c57693cf3d 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -1493,6 +1493,16 @@ w32_valid_pointer_p (void *p, int size)
1493/* Current codepage for encoding file names. */ 1493/* Current codepage for encoding file names. */
1494static int file_name_codepage; 1494static int file_name_codepage;
1495 1495
1496/* Initialize the codepage used for decoding file names. This is
1497 needed to undo the value recorded during dumping, which might not
1498 be correct when we run the dumped Emacs. */
1499void
1500w32_init_file_name_codepage (void)
1501{
1502 file_name_codepage = CP_ACP;
1503 w32_ansi_code_page = CP_ACP;
1504}
1505
1496/* Produce a Windows ANSI codepage suitable for encoding file names. 1506/* Produce a Windows ANSI codepage suitable for encoding file names.
1497 Return the information about that codepage in CP_INFO. */ 1507 Return the information about that codepage in CP_INFO. */
1498int 1508int
@@ -1509,12 +1519,13 @@ codepage_for_filenames (CPINFO *cp_info)
1509 if (NILP (current_encoding)) 1519 if (NILP (current_encoding))
1510 current_encoding = Vdefault_file_name_coding_system; 1520 current_encoding = Vdefault_file_name_coding_system;
1511 1521
1512 if (!EQ (last_file_name_encoding, current_encoding)) 1522 if (!EQ (last_file_name_encoding, current_encoding)
1523 || NILP (last_file_name_encoding))
1513 { 1524 {
1514 /* Default to the current ANSI codepage. */ 1525 /* Default to the current ANSI codepage. */
1515 file_name_codepage = w32_ansi_code_page; 1526 file_name_codepage = w32_ansi_code_page;
1516 1527
1517 if (NILP (current_encoding)) 1528 if (!NILP (current_encoding))
1518 { 1529 {
1519 char *cpname = SSDATA (SYMBOL_NAME (current_encoding)); 1530 char *cpname = SSDATA (SYMBOL_NAME (current_encoding));
1520 char *cp = NULL, *end; 1531 char *cp = NULL, *end;
@@ -1543,6 +1554,9 @@ codepage_for_filenames (CPINFO *cp_info)
1543 if (!GetCPInfo (file_name_codepage, &cp)) 1554 if (!GetCPInfo (file_name_codepage, &cp))
1544 emacs_abort (); 1555 emacs_abort ();
1545 } 1556 }
1557
1558 /* Cache the new value. */
1559 last_file_name_encoding = current_encoding;
1546 } 1560 }
1547 if (cp_info) 1561 if (cp_info)
1548 *cp_info = cp; 1562 *cp_info = cp;
diff --git a/src/w32.h b/src/w32.h
index 42a1c423ce7..08b88f5f5a0 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -195,6 +195,7 @@ extern int filename_from_ansi (const char *, char *);
195extern int filename_to_ansi (const char *, char *); 195extern int filename_to_ansi (const char *, char *);
196extern int filename_from_utf16 (const wchar_t *, char *); 196extern int filename_from_utf16 (const wchar_t *, char *);
197extern int filename_to_utf16 (const char *, wchar_t *); 197extern int filename_to_utf16 (const char *, wchar_t *);
198extern void w32_init_file_name_codepage (void);
198extern int codepage_for_filenames (CPINFO *); 199extern int codepage_for_filenames (CPINFO *);
199extern Lisp_Object ansi_encode_filename (Lisp_Object); 200extern Lisp_Object ansi_encode_filename (Lisp_Object);
200extern int w32_copy_file (const char *, const char *, int, int, int); 201extern int w32_copy_file (const char *, const char *, int, int, int);
diff --git a/src/w32term.c b/src/w32term.c
index 51743f8f94d..7b74ae03ad0 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -7157,7 +7157,10 @@ specified by `file-name-coding-system'.
7157This variable is set to non-nil by default when Emacs runs on Windows 7157This variable is set to non-nil by default when Emacs runs on Windows
7158systems of the NT family, including W2K, XP, Vista, Windows 7 and 7158systems of the NT family, including W2K, XP, Vista, Windows 7 and
7159Windows 8. It is set to nil on Windows 9X. */); 7159Windows 8. It is set to nil on Windows 9X. */);
7160 w32_unicode_filenames = 0; 7160 if (os_subtype == OS_9X)
7161 w32_unicode_filenames = 0;
7162 else
7163 w32_unicode_filenames = 1;
7161 7164
7162 7165
7163 /* FIXME: The following variable will be (hopefully) removed 7166 /* FIXME: The following variable will be (hopefully) removed