diff options
| author | Eli Zaretskii | 2016-11-28 17:43:25 +0200 |
|---|---|---|
| committer | Eli Zaretskii | 2016-11-28 17:43:25 +0200 |
| commit | 5878abf87b6b3ead1367cbae5cc6b0743349f611 (patch) | |
| tree | 83fef8ba83ca1733c6a95e3201db9be45558ba07 | |
| parent | 46065291fa0807a10180b958285f5d375cf05914 (diff) | |
| download | emacs-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.texi | 1 | ||||
| -rw-r--r-- | lisp/files.el | 39 | ||||
| -rw-r--r-- | lisp/international/mule-cmds.el | 12 | ||||
| -rw-r--r-- | src/emacs.c | 3 | ||||
| -rw-r--r-- | src/fileio.c | 8 | ||||
| -rw-r--r-- | src/w32.c | 18 | ||||
| -rw-r--r-- | src/w32.h | 1 | ||||
| -rw-r--r-- | src/w32term.c | 5 |
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} |
| 2156 | This function returns an abbreviated form of @var{filename}. It | 2157 | This 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. |
| 53 | A list of elements of the form (FROM . TO), each meaning to replace | 53 | A list of elements of the form (FROM . TO), each meaning to replace |
| 54 | FROM with TO when it appears in a directory name. This replacement is | 54 | a match for FROM with TO when a directory name matches FROM. This |
| 55 | done when setting up the default directory of a newly visited file. | 55 | replacement is done when setting up the default directory of a |
| 56 | newly visited file buffer. | ||
| 56 | 57 | ||
| 57 | FROM is matched against directory names anchored at the first | 58 | FROM is a regexp that is matched against directory names anchored at |
| 58 | character, so it should start with a \"\\\\\\=`\", or, if directory | 59 | the first character, so it should start with a \"\\\\\\=`\", or, if |
| 59 | names cannot have embedded newlines, with a \"^\". | 60 | directory names cannot have embedded newlines, with a \"^\". |
| 60 | 61 | ||
| 61 | FROM and TO should be equivalent names, which refer to the | 62 | FROM and TO should be equivalent names, which refer to the |
| 62 | same directory. Do not use `~' in the TO strings; | 63 | same directory. TO should be an absolute directory name. |
| 63 | they should be ordinary absolute directory names. | 64 | Do not use `~' in the TO strings. |
| 64 | 65 | ||
| 65 | Use this feature when you have directories which you normally refer to | 66 | Use this feature when you have directories which you normally refer to |
| 66 | via absolute symbolic links. Make TO the name of the link, and FROM | 67 | via absolute symbolic links. Make TO the name of the link, and FROM |
| 67 | the name it is linked to." | 68 | a 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. |
| 1741 | The 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)) |
| @@ -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. */ |
| 1494 | static int file_name_codepage; | 1494 | static 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. */ | ||
| 1499 | void | ||
| 1500 | w32_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. */ |
| 1498 | int | 1508 | int |
| @@ -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; |
| @@ -195,6 +195,7 @@ extern int filename_from_ansi (const char *, char *); | |||
| 195 | extern int filename_to_ansi (const char *, char *); | 195 | extern int filename_to_ansi (const char *, char *); |
| 196 | extern int filename_from_utf16 (const wchar_t *, char *); | 196 | extern int filename_from_utf16 (const wchar_t *, char *); |
| 197 | extern int filename_to_utf16 (const char *, wchar_t *); | 197 | extern int filename_to_utf16 (const char *, wchar_t *); |
| 198 | extern void w32_init_file_name_codepage (void); | ||
| 198 | extern int codepage_for_filenames (CPINFO *); | 199 | extern int codepage_for_filenames (CPINFO *); |
| 199 | extern Lisp_Object ansi_encode_filename (Lisp_Object); | 200 | extern Lisp_Object ansi_encode_filename (Lisp_Object); |
| 200 | extern int w32_copy_file (const char *, const char *, int, int, int); | 201 | extern 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'. | |||
| 7157 | This variable is set to non-nil by default when Emacs runs on Windows | 7157 | This variable is set to non-nil by default when Emacs runs on Windows |
| 7158 | systems of the NT family, including W2K, XP, Vista, Windows 7 and | 7158 | systems of the NT family, including W2K, XP, Vista, Windows 7 and |
| 7159 | Windows 8. It is set to nil on Windows 9X. */); | 7159 | Windows 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 |