return code_convert_string (string, coding_system, Qt, encodep, 0, 1);
}
+/* Encode or decode a file name, to or from a unibyte string suitable
+ for passing to C library functions. */
+Lisp_Object
+decode_file_name (Lisp_Object fname)
+{
+#ifdef WINDOWSNT
+ /* The w32 build pretends to use UTF-8 for file-name encoding, and
+ converts the file names either to UTF-16LE or to the system ANSI
+ codepage internally, depending on the underlying OS; see w32.c. */
+ if (! NILP (Fcoding_system_p (Qutf_8)))
+ return code_convert_string_norecord (fname, Qutf_8, 0);
+ return fname;
+#else /* !WINDOWSNT */
+ if (! NILP (Vfile_name_coding_system))
+ return code_convert_string_norecord (fname, Vfile_name_coding_system, 0);
+ else if (! NILP (Vdefault_file_name_coding_system))
+ return code_convert_string_norecord (fname,
+ Vdefault_file_name_coding_system, 0);
+ else
+ return fname;
+#endif
+}
+
+Lisp_Object
+encode_file_name (Lisp_Object fname)
+{
+#ifdef WINDOWSNT
+ /* The w32 build pretends to use UTF-8 for file-name encoding, and
+ converts the file names either to UTF-16LE or to the system ANSI
+ codepage internally, depending on the underlying OS; see w32.c. */
+ if (! NILP (Fcoding_system_p (Qutf_8)))
+ return code_convert_string_norecord (fname, Qutf_8, 1);
+ return fname;
+#else /* !WINDOWSNT */
+ if (! NILP (Vfile_name_coding_system))
+ return code_convert_string_norecord (fname, Vfile_name_coding_system, 1);
+ else if (! NILP (Vdefault_file_name_coding_system))
+ return code_convert_string_norecord (fname,
+ Vdefault_file_name_coding_system, 1);
+ else
+ return fname;
+#endif
+}
DEFUN ("decode-coding-string", Fdecode_coding_string, Sdecode_coding_string,
2, 4, 0,
/* Encode the file name NAME using the specified coding system
for file names, if any. */
-#define ENCODE_FILE(name) \
- (! NILP (Vfile_name_coding_system) \
- ? code_convert_string_norecord (name, Vfile_name_coding_system, 1) \
- : (! NILP (Vdefault_file_name_coding_system) \
- ? code_convert_string_norecord (name, Vdefault_file_name_coding_system, 1) \
- : name))
-
+#define ENCODE_FILE(NAME) encode_file_name (NAME)
/* Decode the file name NAME using the specified coding system
for file names, if any. */
-#define DECODE_FILE(name) \
- (! NILP (Vfile_name_coding_system) \
- ? code_convert_string_norecord (name, Vfile_name_coding_system, 0) \
- : (! NILP (Vdefault_file_name_coding_system) \
- ? code_convert_string_norecord (name, Vdefault_file_name_coding_system, 0) \
- : name))
-
+#define DECODE_FILE(NAME) decode_file_name (NAME)
/* Encode the string STR using the specified coding system
for system functions, if any. */
Lisp_Object, bool, bool, bool);
extern Lisp_Object code_convert_string_norecord (Lisp_Object, Lisp_Object,
bool);
+extern Lisp_Object encode_file_name (Lisp_Object);
+extern Lisp_Object decode_file_name (Lisp_Object);
extern Lisp_Object raw_text_coding_system (Lisp_Object);
extern Lisp_Object coding_inherit_eol_type (Lisp_Object, Lisp_Object);
extern Lisp_Object complement_process_encoding_system (Lisp_Object);
static BOOL g_b_init_set_file_security;
static BOOL g_b_init_get_adapters_info;
-int w32_unicode_filenames;
-
/*
BEGIN: Wrapper functions around OpenProcessToken
and other functions in advapi32.dll that are only
\f
-/* Converting file names from UTF-8 to either UTF-16 or the system
- ANSI codepage. */
+/* Converting file names from UTF-8 to either UTF-16 or the ANSI
+ codepage defined by file-name-coding-system. */
+
+/* Current codepage for encoding file names. */
+static int file_name_codepage;
+
+/* Produce a Windows ANSI codepage suitable for encoding file names.
+ Return the information about that codepage in CP_INFO. */
+static int
+codepage_for_filenames (CPINFO *cp_info)
+{
+ /* A simple cache to avoid calling GetCPInfo every time we need to
+ encode/decode a file name. The file-name encoding is not
+ supposed to be changed too frequently, if ever. */
+ static Lisp_Object last_file_name_encoding;
+ static CPINFO cp;
+ Lisp_Object current_encoding;
+
+ current_encoding = Vfile_name_coding_system;
+ if (NILP (current_encoding))
+ current_encoding = Vdefault_file_name_coding_system;
+
+ if (!EQ (last_file_name_encoding, current_encoding))
+ {
+ /* Default to the current ANSI codepage. */
+ file_name_codepage = w32_ansi_code_page;
+
+ if (NILP (current_encoding))
+ {
+ char *cpname = SDATA (SYMBOL_NAME (current_encoding));
+ char *cp = NULL, *end;
+ int cpnum;
+
+ if (strncmp (cpname, "cp", 2) == 0)
+ cp = cpname + 2;
+ else if (strncmp (cpname, "windows-", 8) == 0)
+ cp = cpname + 8;
+
+ if (cp)
+ {
+ end = cp;
+ cpnum = strtol (cp, &end, 10);
+ if (cpnum && *end == '\0' && end - cp >= 2)
+ file_name_codepage = cpnum;
+ }
+ }
+
+ if (!file_name_codepage)
+ file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */
+
+ if (!GetCPInfo (file_name_codepage, &cp))
+ {
+ file_name_codepage = CP_ACP;
+ if (!GetCPInfo (file_name_codepage, &cp))
+ emacs_abort ();
+ }
+ }
+ if (cp_info)
+ *cp_info = cp;
+
+ return file_name_codepage;
+}
+
static int
filename_to_utf16 (const char *fn_in, wchar_t *fn_out)
{
- int result = MultiByteToWideChar (CP_UTF8, 0, fn_in, -1, fn_out, MAX_PATH);
+ int result = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, fn_in, -1,
+ fn_out, MAX_PATH);
if (!result)
{
static int
filename_from_utf16 (const wchar_t *fn_in, char *fn_out)
{
- return -1;
+ int result = WideCharToMultiByte (CP_UTF8, 0, fn_in, -1,
+ fn_out, MAX_UTF8_PATH, NULL, NULL);
+
+ if (!result)
+ {
+ DWORD err = GetLastError ();
+
+ switch (err)
+ {
+ case ERROR_INVALID_FLAGS:
+ case ERROR_INVALID_PARAMETER:
+ errno = EINVAL;
+ break;
+ case ERROR_INSUFFICIENT_BUFFER:
+ case ERROR_NO_UNICODE_TRANSLATION:
+ default:
+ errno = ENOENT;
+ break;
+ }
+ return -1;
+ }
+ return 0;
}
static int
if (filename_to_utf16 (fn_in, fn_utf16) == 0)
{
- int result = WideCharToMultiByte (CP_ACP, 0, fn_utf16, -1,
- fn_out, MAX_UTF8_PATH, NULL, NULL);
+ int result;
+ int codepage = codepage_for_filenames (NULL);
+ result = WideCharToMultiByte (codepage, 0, fn_utf16, -1,
+ fn_out, MAX_UTF8_PATH, NULL, NULL);
if (!result)
{
DWORD err = GetLastError ();
}
return 0;
}
+ return -1;
}
static int
filename_from_ansi (const char *fn_in, char *fn_out)
{
- return -1;
+ wchar_t fn_utf16[MAXPATHLEN];
+ int codepage = codepage_for_filenames (NULL);
+ int result = MultiByteToWideChar (codepage, MB_ERR_INVALID_CHARS, fn_in, -1,
+ fn_utf16, MAX_PATH);
+
+ if (!result)
+ {
+ DWORD err = GetLastError ();
+
+ switch (err)
+ {
+ case ERROR_INVALID_FLAGS:
+ case ERROR_INVALID_PARAMETER:
+ errno = EINVAL;
+ break;
+ case ERROR_INSUFFICIENT_BUFFER:
+ case ERROR_NO_UNICODE_TRANSLATION:
+ default:
+ errno = ENOENT;
+ break;
+ }
+ return -1;
+ }
+ return filename_from_utf16 (fn_utf16, fn_out);
}
\f
srand (seed);
}
-/* Current codepage for encoding file names. */
-static int file_name_codepage;
-
/* Return the maximum length in bytes of a multibyte character
sequence encoded in the current ANSI codepage. This is required to
correctly walk the encoded file names one character at a time. */
static int
max_filename_mbslen (void)
{
- /* A simple cache to avoid calling GetCPInfo every time we need to
- normalize a file name. The file-name encoding is not supposed to
- be changed too frequently, if ever. */
- static Lisp_Object last_file_name_encoding;
- static int last_max_mbslen;
- Lisp_Object current_encoding;
-
- current_encoding = Vfile_name_coding_system;
- if (NILP (current_encoding))
- current_encoding = Vdefault_file_name_coding_system;
-
- if (!EQ (last_file_name_encoding, current_encoding))
- {
- CPINFO cp_info;
-
- last_file_name_encoding = current_encoding;
- /* Default to the current ANSI codepage. */
- file_name_codepage = w32_ansi_code_page;
- if (!NILP (current_encoding))
- {
- char *cpname = SDATA (SYMBOL_NAME (current_encoding));
- char *cp = NULL, *end;
- int cpnum;
-
- if (strncmp (cpname, "cp", 2) == 0)
- cp = cpname + 2;
- else if (strncmp (cpname, "windows-", 8) == 0)
- cp = cpname + 8;
-
- if (cp)
- {
- end = cp;
- cpnum = strtol (cp, &end, 10);
- if (cpnum && *end == '\0' && end - cp >= 2)
- file_name_codepage = cpnum;
- }
- }
-
- if (!file_name_codepage)
- file_name_codepage = CP_ACP; /* CP_ACP = 0, but let's not assume that */
-
- if (!GetCPInfo (file_name_codepage, &cp_info))
- {
- file_name_codepage = CP_ACP;
- if (!GetCPInfo (file_name_codepage, &cp_info))
- emacs_abort ();
- }
- last_max_mbslen = cp_info.MaxCharSize;
- }
+ CPINFO cp_info;
- return last_max_mbslen;
+ codepage_for_filenames (&cp_info);
+ return cp_info.MaxCharSize;
}
/* Normalize filename by converting all path separators to