diff options
| author | Eli Zaretskii | 2013-10-26 13:37:43 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2013-10-26 13:37:43 +0300 |
| commit | c3e9160b8c375760d6bc53602caeed211e91389d (patch) | |
| tree | 94322287584b1c8a245a78caca63df5b16461a68 /src | |
| parent | 03d58cca817e8a21414c84696387813687c75261 (diff) | |
| download | emacs-c3e9160b8c375760d6bc53602caeed211e91389d.tar.gz emacs-c3e9160b8c375760d6bc53602caeed211e91389d.zip | |
Finished conversion routines; w32-unicode-filenames exposed to Lisp.
Diffstat (limited to 'src')
| -rw-r--r-- | src/coding.c | 43 | ||||
| -rw-r--r-- | src/coding.h | 18 | ||||
| -rw-r--r-- | src/w32.c | 181 | ||||
| -rw-r--r-- | src/w32.h | 2 | ||||
| -rw-r--r-- | src/w32term.c | 12 |
5 files changed, 178 insertions, 78 deletions
diff --git a/src/coding.c b/src/coding.c index ac828a48683..69b01553e7f 100644 --- a/src/coding.c +++ b/src/coding.c | |||
| @@ -9473,6 +9473,49 @@ code_convert_string_norecord (Lisp_Object string, Lisp_Object coding_system, | |||
| 9473 | return code_convert_string (string, coding_system, Qt, encodep, 0, 1); | 9473 | return code_convert_string (string, coding_system, Qt, encodep, 0, 1); |
| 9474 | } | 9474 | } |
| 9475 | 9475 | ||
| 9476 | /* Encode or decode a file name, to or from a unibyte string suitable | ||
| 9477 | for passing to C library functions. */ | ||
| 9478 | Lisp_Object | ||
| 9479 | decode_file_name (Lisp_Object fname) | ||
| 9480 | { | ||
| 9481 | #ifdef WINDOWSNT | ||
| 9482 | /* The w32 build pretends to use UTF-8 for file-name encoding, and | ||
| 9483 | converts the file names either to UTF-16LE or to the system ANSI | ||
| 9484 | codepage internally, depending on the underlying OS; see w32.c. */ | ||
| 9485 | if (! NILP (Fcoding_system_p (Qutf_8))) | ||
| 9486 | return code_convert_string_norecord (fname, Qutf_8, 0); | ||
| 9487 | return fname; | ||
| 9488 | #else /* !WINDOWSNT */ | ||
| 9489 | if (! NILP (Vfile_name_coding_system)) | ||
| 9490 | return code_convert_string_norecord (fname, Vfile_name_coding_system, 0); | ||
| 9491 | else if (! NILP (Vdefault_file_name_coding_system)) | ||
| 9492 | return code_convert_string_norecord (fname, | ||
| 9493 | Vdefault_file_name_coding_system, 0); | ||
| 9494 | else | ||
| 9495 | return fname; | ||
| 9496 | #endif | ||
| 9497 | } | ||
| 9498 | |||
| 9499 | Lisp_Object | ||
| 9500 | encode_file_name (Lisp_Object fname) | ||
| 9501 | { | ||
| 9502 | #ifdef WINDOWSNT | ||
| 9503 | /* The w32 build pretends to use UTF-8 for file-name encoding, and | ||
| 9504 | converts the file names either to UTF-16LE or to the system ANSI | ||
| 9505 | codepage internally, depending on the underlying OS; see w32.c. */ | ||
| 9506 | if (! NILP (Fcoding_system_p (Qutf_8))) | ||
| 9507 | return code_convert_string_norecord (fname, Qutf_8, 1); | ||
| 9508 | return fname; | ||
| 9509 | #else /* !WINDOWSNT */ | ||
| 9510 | if (! NILP (Vfile_name_coding_system)) | ||
| 9511 | return code_convert_string_norecord (fname, Vfile_name_coding_system, 1); | ||
| 9512 | else if (! NILP (Vdefault_file_name_coding_system)) | ||
| 9513 | return code_convert_string_norecord (fname, | ||
| 9514 | Vdefault_file_name_coding_system, 1); | ||
| 9515 | else | ||
| 9516 | return fname; | ||
| 9517 | #endif | ||
| 9518 | } | ||
| 9476 | 9519 | ||
| 9477 | DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string, | 9520 | DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string, |
| 9478 | 2, 4, 0, | 9521 | 2, 4, 0, |
diff --git a/src/coding.h b/src/coding.h index 0472bec99de..39f9d62462b 100644 --- a/src/coding.h +++ b/src/coding.h | |||
| @@ -672,23 +672,11 @@ struct coding_system | |||
| 672 | 672 | ||
| 673 | /* Encode the file name NAME using the specified coding system | 673 | /* Encode the file name NAME using the specified coding system |
| 674 | for file names, if any. */ | 674 | for file names, if any. */ |
| 675 | #define ENCODE_FILE(name) \ | 675 | #define ENCODE_FILE(NAME) encode_file_name (NAME) |
| 676 | (! NILP (Vfile_name_coding_system) \ | ||
| 677 | ? code_convert_string_norecord (name, Vfile_name_coding_system, 1) \ | ||
| 678 | : (! NILP (Vdefault_file_name_coding_system) \ | ||
| 679 | ? code_convert_string_norecord (name, Vdefault_file_name_coding_system, 1) \ | ||
| 680 | : name)) | ||
| 681 | |||
| 682 | 676 | ||
| 683 | /* Decode the file name NAME using the specified coding system | 677 | /* Decode the file name NAME using the specified coding system |
| 684 | for file names, if any. */ | 678 | for file names, if any. */ |
| 685 | #define DECODE_FILE(name) \ | 679 | #define DECODE_FILE(NAME) decode_file_name (NAME) |
| 686 | (! NILP (Vfile_name_coding_system) \ | ||
| 687 | ? code_convert_string_norecord (name, Vfile_name_coding_system, 0) \ | ||
| 688 | : (! NILP (Vdefault_file_name_coding_system) \ | ||
| 689 | ? code_convert_string_norecord (name, Vdefault_file_name_coding_system, 0) \ | ||
| 690 | : name)) | ||
| 691 | |||
| 692 | 680 | ||
| 693 | /* Encode the string STR using the specified coding system | 681 | /* Encode the string STR using the specified coding system |
| 694 | for system functions, if any. */ | 682 | for system functions, if any. */ |
| @@ -716,6 +704,8 @@ extern Lisp_Object code_convert_string (Lisp_Object, Lisp_Object, | |||
| 716 | Lisp_Object, bool, bool, bool); | 704 | Lisp_Object, bool, bool, bool); |
| 717 | extern Lisp_Object code_convert_string_norecord (Lisp_Object, Lisp_Object, | 705 | extern Lisp_Object code_convert_string_norecord (Lisp_Object, Lisp_Object, |
| 718 | bool); | 706 | bool); |
| 707 | extern Lisp_Object encode_file_name (Lisp_Object); | ||
| 708 | extern Lisp_Object decode_file_name (Lisp_Object); | ||
| 719 | extern Lisp_Object raw_text_coding_system (Lisp_Object); | 709 | extern Lisp_Object raw_text_coding_system (Lisp_Object); |
| 720 | extern Lisp_Object coding_inherit_eol_type (Lisp_Object, Lisp_Object); | 710 | extern Lisp_Object coding_inherit_eol_type (Lisp_Object, Lisp_Object); |
| 721 | extern Lisp_Object complement_process_encoding_system (Lisp_Object); | 711 | extern Lisp_Object complement_process_encoding_system (Lisp_Object); |
| @@ -300,8 +300,6 @@ static BOOL g_b_init_is_valid_security_descriptor; | |||
| 300 | static BOOL g_b_init_set_file_security; | 300 | static BOOL g_b_init_set_file_security; |
| 301 | static BOOL g_b_init_get_adapters_info; | 301 | static BOOL g_b_init_get_adapters_info; |
| 302 | 302 | ||
| 303 | int w32_unicode_filenames; | ||
| 304 | |||
| 305 | /* | 303 | /* |
| 306 | BEGIN: Wrapper functions around OpenProcessToken | 304 | BEGIN: Wrapper functions around OpenProcessToken |
| 307 | and other functions in advapi32.dll that are only | 305 | and other functions in advapi32.dll that are only |
| @@ -1186,12 +1184,74 @@ w32_valid_pointer_p (void *p, int size) | |||
| 1186 | 1184 | ||
| 1187 | 1185 | ||
| 1188 | 1186 | ||
| 1189 | /* Converting file names from UTF-8 to either UTF-16 or the system | 1187 | /* Converting file names from UTF-8 to either UTF-16 or the ANSI |
| 1190 | ANSI codepage. */ | 1188 | codepage defined by file-name-coding-system. */ |
| 1189 | |||
| 1190 | /* Current codepage for encoding file names. */ | ||
| 1191 | static int file_name_codepage; | ||
| 1192 | |||
| 1193 | /* Produce a Windows ANSI codepage suitable for encoding file names. | ||
| 1194 | Return the information about that codepage in CP_INFO. */ | ||
| 1195 | static int | ||
| 1196 | codepage_for_filenames (CPINFO *cp_info) | ||
| 1197 | { | ||
| 1198 | /* A simple cache to avoid calling GetCPInfo every time we need to | ||
| 1199 | encode/decode a file name. The file-name encoding is not | ||
| 1200 | supposed to be changed too frequently, if ever. */ | ||
| 1201 | static Lisp_Object last_file_name_encoding; | ||
| 1202 | static CPINFO cp; | ||
| 1203 | Lisp_Object current_encoding; | ||
| 1204 | |||
| 1205 | current_encoding = Vfile_name_coding_system; | ||
| 1206 | if (NILP (current_encoding)) | ||
| 1207 | current_encoding = Vdefault_file_name_coding_system; | ||
| 1208 | |||
| 1209 | if (!EQ (last_file_name_encoding, current_encoding)) | ||
| 1210 | { | ||
| 1211 | /* Default to the current ANSI codepage. */ | ||
| 1212 | file_name_codepage = w32_ansi_code_page; | ||
| 1213 | |||
| 1214 | if (NILP (current_encoding)) | ||
| 1215 | { | ||
| 1216 | char *cpname = SDATA (SYMBOL_NAME (current_encoding)); | ||
| 1217 | char *cp = NULL, *end; | ||
| 1218 | int cpnum; | ||
| 1219 | |||
| 1220 | if (strncmp (cpname, "cp", 2) == 0) | ||
| 1221 | cp = cpname + 2; | ||
| 1222 | else if (strncmp (cpname, "windows-", 8) == 0) | ||
| 1223 | cp = cpname + 8; | ||
| 1224 | |||
| 1225 | if (cp) | ||
| 1226 | { | ||
| 1227 | end = cp; | ||
| 1228 | cpnum = strtol (cp, &end, 10); | ||
| 1229 | if (cpnum && *end == '\0' && end - cp >= 2) | ||
| 1230 | file_name_codepage = cpnum; | ||
| 1231 | } | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | if (!file_name_codepage) | ||
| 1235 | file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */ | ||
| 1236 | |||
| 1237 | if (!GetCPInfo (file_name_codepage, &cp)) | ||
| 1238 | { | ||
| 1239 | file_name_codepage = CP_ACP; | ||
| 1240 | if (!GetCPInfo (file_name_codepage, &cp)) | ||
| 1241 | emacs_abort (); | ||
| 1242 | } | ||
| 1243 | } | ||
| 1244 | if (cp_info) | ||
| 1245 | *cp_info = cp; | ||
| 1246 | |||
| 1247 | return file_name_codepage; | ||
| 1248 | } | ||
| 1249 | |||
| 1191 | static int | 1250 | static int |
| 1192 | filename_to_utf16 (const char *fn_in, wchar_t *fn_out) | 1251 | filename_to_utf16 (const char *fn_in, wchar_t *fn_out) |
| 1193 | { | 1252 | { |
| 1194 | int result = MultiByteToWideChar (CP_UTF8, 0, fn_in, -1, fn_out, MAX_PATH); | 1253 | int result = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1, |
| 1254 | fn_out, MAX_PATH); | ||
| 1195 | 1255 | ||
| 1196 | if (!result) | 1256 | if (!result) |
| 1197 | { | 1257 | { |
| @@ -1217,7 +1277,28 @@ filename_to_utf16 (const char *fn_in, wchar_t *fn_out) | |||
| 1217 | static int | 1277 | static int |
| 1218 | filename_from_utf16 (const wchar_t *fn_in, char *fn_out) | 1278 | filename_from_utf16 (const wchar_t *fn_in, char *fn_out) |
| 1219 | { | 1279 | { |
| 1220 | return -1; | 1280 | int result = WideCharToMultiByte (CP_UTF8, 0, fn_in, -1, |
| 1281 | fn_out, MAX_UTF8_PATH, NULL, NULL); | ||
| 1282 | |||
| 1283 | if (!result) | ||
| 1284 | { | ||
| 1285 | DWORD err = GetLastError (); | ||
| 1286 | |||
| 1287 | switch (err) | ||
| 1288 | { | ||
| 1289 | case ERROR_INVALID_FLAGS: | ||
| 1290 | case ERROR_INVALID_PARAMETER: | ||
| 1291 | errno = EINVAL; | ||
| 1292 | break; | ||
| 1293 | case ERROR_INSUFFICIENT_BUFFER: | ||
| 1294 | case ERROR_NO_UNICODE_TRANSLATION: | ||
| 1295 | default: | ||
| 1296 | errno = ENOENT; | ||
| 1297 | break; | ||
| 1298 | } | ||
| 1299 | return -1; | ||
| 1300 | } | ||
| 1301 | return 0; | ||
| 1221 | } | 1302 | } |
| 1222 | 1303 | ||
| 1223 | static int | 1304 | static int |
| @@ -1227,9 +1308,11 @@ filename_to_ansi (const char *fn_in, char *fn_out) | |||
| 1227 | 1308 | ||
| 1228 | if (filename_to_utf16 (fn_in, fn_utf16) == 0) | 1309 | if (filename_to_utf16 (fn_in, fn_utf16) == 0) |
| 1229 | { | 1310 | { |
| 1230 | int result = WideCharToMultiByte (CP_ACP, 0, fn_utf16, -1, | 1311 | int result; |
| 1231 | fn_out, MAX_UTF8_PATH, NULL, NULL); | 1312 | int codepage = codepage_for_filenames (NULL); |
| 1232 | 1313 | ||
| 1314 | result = WideCharToMultiByte (codepage, 0, fn_utf16, -1, | ||
| 1315 | fn_out, MAX_UTF8_PATH, NULL, NULL); | ||
| 1233 | if (!result) | 1316 | if (!result) |
| 1234 | { | 1317 | { |
| 1235 | DWORD err = GetLastError (); | 1318 | DWORD err = GetLastError (); |
| @@ -1250,12 +1333,36 @@ filename_to_ansi (const char *fn_in, char *fn_out) | |||
| 1250 | } | 1333 | } |
| 1251 | return 0; | 1334 | return 0; |
| 1252 | } | 1335 | } |
| 1336 | return -1; | ||
| 1253 | } | 1337 | } |
| 1254 | 1338 | ||
| 1255 | static int | 1339 | static int |
| 1256 | filename_from_ansi (const char *fn_in, char *fn_out) | 1340 | filename_from_ansi (const char *fn_in, char *fn_out) |
| 1257 | { | 1341 | { |
| 1258 | return -1; | 1342 | wchar_t fn_utf16[MAXPATHLEN]; |
| 1343 | int codepage = codepage_for_filenames (NULL); | ||
| 1344 | int result = MultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1, | ||
| 1345 | fn_utf16, MAX_PATH); | ||
| 1346 | |||
| 1347 | if (!result) | ||
| 1348 | { | ||
| 1349 | DWORD err = GetLastError (); | ||
| 1350 | |||
| 1351 | switch (err) | ||
| 1352 | { | ||
| 1353 | case ERROR_INVALID_FLAGS: | ||
| 1354 | case ERROR_INVALID_PARAMETER: | ||
| 1355 | errno = EINVAL; | ||
| 1356 | break; | ||
| 1357 | case ERROR_INSUFFICIENT_BUFFER: | ||
| 1358 | case ERROR_NO_UNICODE_TRANSLATION: | ||
| 1359 | default: | ||
| 1360 | errno = ENOENT; | ||
| 1361 | break; | ||
| 1362 | } | ||
| 1363 | return -1; | ||
| 1364 | } | ||
| 1365 | return filename_from_utf16 (fn_utf16, fn_out); | ||
| 1259 | } | 1366 | } |
| 1260 | 1367 | ||
| 1261 | 1368 | ||
| @@ -1662,66 +1769,16 @@ srandom (int seed) | |||
| 1662 | srand (seed); | 1769 | srand (seed); |
| 1663 | } | 1770 | } |
| 1664 | 1771 | ||
| 1665 | /* Current codepage for encoding file names. */ | ||
| 1666 | static int file_name_codepage; | ||
| 1667 | |||
| 1668 | /* Return the maximum length in bytes of a multibyte character | 1772 | /* Return the maximum length in bytes of a multibyte character |
| 1669 | sequence encoded in the current ANSI codepage. This is required to | 1773 | sequence encoded in the current ANSI codepage. This is required to |
| 1670 | correctly walk the encoded file names one character at a time. */ | 1774 | correctly walk the encoded file names one character at a time. */ |
| 1671 | static int | 1775 | static int |
| 1672 | max_filename_mbslen (void) | 1776 | max_filename_mbslen (void) |
| 1673 | { | 1777 | { |
| 1674 | /* A simple cache to avoid calling GetCPInfo every time we need to | 1778 | CPINFO cp_info; |
| 1675 | normalize a file name. The file-name encoding is not supposed to | ||
| 1676 | be changed too frequently, if ever. */ | ||
| 1677 | static Lisp_Object last_file_name_encoding; | ||
| 1678 | static int last_max_mbslen; | ||
| 1679 | Lisp_Object current_encoding; | ||
| 1680 | |||
| 1681 | current_encoding = Vfile_name_coding_system; | ||
| 1682 | if (NILP (current_encoding)) | ||
| 1683 | current_encoding = Vdefault_file_name_coding_system; | ||
| 1684 | |||
| 1685 | if (!EQ (last_file_name_encoding, current_encoding)) | ||
| 1686 | { | ||
| 1687 | CPINFO cp_info; | ||
| 1688 | |||
| 1689 | last_file_name_encoding = current_encoding; | ||
| 1690 | /* Default to the current ANSI codepage. */ | ||
| 1691 | file_name_codepage = w32_ansi_code_page; | ||
| 1692 | if (!NILP (current_encoding)) | ||
| 1693 | { | ||
| 1694 | char *cpname = SDATA (SYMBOL_NAME (current_encoding)); | ||
| 1695 | char *cp = NULL, *end; | ||
| 1696 | int cpnum; | ||
| 1697 | |||
| 1698 | if (strncmp (cpname, "cp", 2) == 0) | ||
| 1699 | cp = cpname + 2; | ||
| 1700 | else if (strncmp (cpname, "windows-", 8) == 0) | ||
| 1701 | cp = cpname + 8; | ||
| 1702 | |||
| 1703 | if (cp) | ||
| 1704 | { | ||
| 1705 | end = cp; | ||
| 1706 | cpnum = strtol (cp, &end, 10); | ||
| 1707 | if (cpnum && *end == '\0' && end - cp >= 2) | ||
| 1708 | file_name_codepage = cpnum; | ||
| 1709 | } | ||
| 1710 | } | ||
| 1711 | |||
| 1712 | if (!file_name_codepage) | ||
| 1713 | file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */ | ||
| 1714 | |||
| 1715 | if (!GetCPInfo (file_name_codepage, &cp_info)) | ||
| 1716 | { | ||
| 1717 | file_name_codepage = CP_ACP; | ||
| 1718 | if (!GetCPInfo (file_name_codepage, &cp_info)) | ||
| 1719 | emacs_abort (); | ||
| 1720 | } | ||
| 1721 | last_max_mbslen = cp_info.MaxCharSize; | ||
| 1722 | } | ||
| 1723 | 1779 | ||
| 1724 | return last_max_mbslen; | 1780 | codepage_for_filenames (&cp_info); |
| 1781 | return cp_info.MaxCharSize; | ||
| 1725 | } | 1782 | } |
| 1726 | 1783 | ||
| 1727 | /* Normalize filename by converting all path separators to | 1784 | /* Normalize filename by converting all path separators to |
| @@ -200,8 +200,6 @@ extern void record_pending_deletion (char *); | |||
| 200 | extern void sys_sleep (int); | 200 | extern void sys_sleep (int); |
| 201 | extern int sys_link (const char *, const char *); | 201 | extern int sys_link (const char *, const char *); |
| 202 | 202 | ||
| 203 | |||
| 204 | |||
| 205 | #ifdef HAVE_GNUTLS | 203 | #ifdef HAVE_GNUTLS |
| 206 | #include <gnutls/gnutls.h> | 204 | #include <gnutls/gnutls.h> |
| 207 | 205 | ||
diff --git a/src/w32term.c b/src/w32term.c index 8bc46734b7d..6c94090f3b7 100644 --- a/src/w32term.c +++ b/src/w32term.c | |||
| @@ -6567,6 +6567,18 @@ X toolkit. Possible values are: gtk, motif, xaw, or xaw3d. | |||
| 6567 | With MS Windows or Nextstep, the value is t. */); | 6567 | With MS Windows or Nextstep, the value is t. */); |
| 6568 | Vx_toolkit_scroll_bars = Qt; | 6568 | Vx_toolkit_scroll_bars = Qt; |
| 6569 | 6569 | ||
| 6570 | DEFVAR_BOOL ("w32-unicode-filenames", | ||
| 6571 | w32_unicode_filenames, | ||
| 6572 | doc: /* Non-nil means use Unicode APIs when passing file names to the OS. | ||
| 6573 | A value of nil means file names passed to the OS APIs and returned | ||
| 6574 | from those APIs are encoded/decoded using the ANSI codepage | ||
| 6575 | specified by `file-name-coding-system'. | ||
| 6576 | |||
| 6577 | This variable is set to non-nil by default when Emacs runs on Windows | ||
| 6578 | systems of the NT family, including W2K, XP, Vista, Windows 7 and | ||
| 6579 | Windows 8. It is set to nil on Windows 9X. */); | ||
| 6580 | w32_unicode_filenames = 0; | ||
| 6581 | |||
| 6570 | /* Tell Emacs about this window system. */ | 6582 | /* Tell Emacs about this window system. */ |
| 6571 | Fprovide (Qw32, Qnil); | 6583 | Fprovide (Qw32, Qnil); |
| 6572 | } | 6584 | } |