aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2013-10-26 13:37:43 +0300
committerEli Zaretskii2013-10-26 13:37:43 +0300
commitc3e9160b8c375760d6bc53602caeed211e91389d (patch)
tree94322287584b1c8a245a78caca63df5b16461a68 /src
parent03d58cca817e8a21414c84696387813687c75261 (diff)
downloademacs-c3e9160b8c375760d6bc53602caeed211e91389d.tar.gz
emacs-c3e9160b8c375760d6bc53602caeed211e91389d.zip
Finished conversion routines; w32-unicode-filenames exposed to Lisp.
Diffstat (limited to 'src')
-rw-r--r--src/coding.c43
-rw-r--r--src/coding.h18
-rw-r--r--src/w32.c181
-rw-r--r--src/w32.h2
-rw-r--r--src/w32term.c12
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. */
9478Lisp_Object
9479decode_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
9499Lisp_Object
9500encode_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
9477DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string, 9520DEFUN ("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);
717extern Lisp_Object code_convert_string_norecord (Lisp_Object, Lisp_Object, 705extern Lisp_Object code_convert_string_norecord (Lisp_Object, Lisp_Object,
718 bool); 706 bool);
707extern Lisp_Object encode_file_name (Lisp_Object);
708extern Lisp_Object decode_file_name (Lisp_Object);
719extern Lisp_Object raw_text_coding_system (Lisp_Object); 709extern Lisp_Object raw_text_coding_system (Lisp_Object);
720extern Lisp_Object coding_inherit_eol_type (Lisp_Object, Lisp_Object); 710extern Lisp_Object coding_inherit_eol_type (Lisp_Object, Lisp_Object);
721extern Lisp_Object complement_process_encoding_system (Lisp_Object); 711extern Lisp_Object complement_process_encoding_system (Lisp_Object);
diff --git a/src/w32.c b/src/w32.c
index 511cec15d5f..993d598ff54 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -300,8 +300,6 @@ static BOOL g_b_init_is_valid_security_descriptor;
300static BOOL g_b_init_set_file_security; 300static BOOL g_b_init_set_file_security;
301static BOOL g_b_init_get_adapters_info; 301static BOOL g_b_init_get_adapters_info;
302 302
303int 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. */
1191static 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. */
1195static int
1196codepage_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
1191static int 1250static int
1192filename_to_utf16 (const char *fn_in, wchar_t *fn_out) 1251filename_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)
1217static int 1277static int
1218filename_from_utf16 (const wchar_t *fn_in, char *fn_out) 1278filename_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
1223static int 1304static 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
1255static int 1339static int
1256filename_from_ansi (const char *fn_in, char *fn_out) 1340filename_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. */
1666static 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. */
1671static int 1775static int
1672max_filename_mbslen (void) 1776max_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
diff --git a/src/w32.h b/src/w32.h
index 32d0fdbe3cf..c836937bd66 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -200,8 +200,6 @@ extern void record_pending_deletion (char *);
200extern void sys_sleep (int); 200extern void sys_sleep (int);
201extern int sys_link (const char *, const char *); 201extern 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.
6567With MS Windows or Nextstep, the value is t. */); 6567With 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.
6573A value of nil means file names passed to the OS APIs and returned
6574from those APIs are encoded/decoded using the ANSI codepage
6575specified by `file-name-coding-system'.
6576
6577This variable is set to non-nil by default when Emacs runs on Windows
6578systems of the NT family, including W2K, XP, Vista, Windows 7 and
6579Windows 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}