Support MS-Windows file names that use characters outside of ANSI codepage.
src/w32.c (get_file_security, set_file_security) (create_symbolic_link): Separate pointers and boolean flags for ANSI and Unicode APIs. Use the latter if w32_unicode_filenames is non-zero, else the former. (codepage_for_filenames, filename_to_utf16, ) (filename_from_utf16, filename_to_ansi, filename_from_ansi): New functions. (init_user_info): Allow $HOME and $SHELL to include non-ANSI characters. (normalize_filename): Lose the DBCS code, now works on UTF-8. Accept only one argument; all callers changed. (dostounix_filename): Remove the second argument, now works in UTF-8. All callers changed. (parse_root): Lose DBCS code. (get_long_basename, w32_get_short_filename, init_environment) (GetCachedVolumeInformation, sys_readdir, open_unc_volume) (read_unc_volume, logon_network_drive, faccessat, sys_chdir) (sys_chmod, sys_creat, sys_fopen, sys_link, sys_mkdir, sys_open) (sys_rename_replace, sys_rmdir, sys_unlink, stat_worker, utime) (is_symlink, readlink, chase_symlinks, w32_delayed_load): Work in Unicode mode if w32_unicode_filenames is non-zero, in ANSI mode otherwise. (ansi_encode_filename): New function. (get_emacs_configuration, get_emacs_configuration_options): Functions deleted. (add_volume_info, GetCachedVolumeInformation): Run the input file name through unixtodos_filename, to ensure it is stored and referenced in canonical form. (get_volume_info): Lose the DBCS code, now works in UTF-8. (logon_network_drive, sys_link, utime): Improve error handling. (sys_access): New function. (hashval, generate_inode_val): Unused functions deleted. (symlink, readlink, readlinkat): Lose DBCS code, now works in UTF-8. (check_windows_init_file): Convert error message from UTF-8 to ANSI codepage, for display in the message box. (globals_of_w32): Set w32_unicode_filenames according to the OS version. src/w32term.c (construct_drag_n_drop): Work in Unicode mode when w32_unicode_filenames is non-zero, ANSI mode otherwise. (syms_of_w32term): Declare w32-unicode-filenames. src/w32proc.c (new_child, delete_child): Remove code that handled unused pending_deletion and input_file members of the child struct. (create_child, sys_spawnve): Convert all file names to ANSI codepage. Use ANSI APIs explicitly; forcibly fail if any file name cannot be encoded in ANSI codepage. Don't use unixtodos_filename, mirror slashes by hand. (record_infile, record_pending_deletion): Functions deleted. (Fw32_short_file_name): Call w32_get_short_filename instead of GetShortPathName. src/w32notify.c (add_watch): Work in Unicode mode when w32_unicode_filenames is non-zero, ANSI mode otherwise. (Fw32notify_add_watch): Rewrite to avoid using GetFullPathName; instead, do the same with Lisp primitives. src/w32fns.c (file_dialog_callback, Fx_file_dialog) (Fsystem_move_file_to_trash, Fw32_shell_execute) (Ffile_system_info, Fdefault_printer_name): Work in Unicode mode when w32_unicode_filenames is non-zero, ANSI mode otherwise. (Fw32_shell_execute): Improve error reporting. (Fdefault_printer_name): Ifdef away for Cygwin. src/w32.h (struct _child_process): Remove input_file and pending_deletion members that are no longer used. (dostounix_filename, w32_get_short_filename, filename_from_ansi) (filename_to_ansi, filename_from_utf16, filename_to_utf16) (ansi_encode_filename): New and updated prototypes. src/unexw32.c (open_input_file, open_output_file, unexec): Use ANSI APIs explicitly. (unexec): Don't use dostounix_filename, it expects a file name in UTF-8. Instead, mirror backslashes by hand. Convert NEW_NAME to ANSI encoding. src/fileio.c (Ffile_name_directory, file_name_as_directory) (directory_file_name, Fexpand_file_name) (Fsubstitute_in_file_name) [WINDOWSNT]: Adapt to the change in arguments of dostounix_filename. (Fexpand_file_name) [WINDOWSNT]: Convert value of $HOME to UTF-8. use MAX_UTF8_PATH for size of file-name strings. (emacs_readlinkat): Build an explicitly unibyte string for file names. (syms_of_fileio) <file-name-coding-system> default-file-name-coding-system>: Mention MS-Windows peculiarities. src/emacs.c (init_cmdargs) [WINDOWSNT]: Convert argv[0] to UTF-8. (main) [WINDOWSNT]: Convert the argv[] elements that are files or directories to UTF-8. (decode_env_path) [WINDOWSNT]: Convert file names taken from the environment, and each element of the input PATH, to UTF-8. src/dired.c (file_attributes): Use build_unibyte_string explicitly to make Lisp strings from user and group names. src/coding.h (ENCODE_FILE, DECODE_FILE): Just call encode_file and decode_file. src/coding.c (decode_file_name, encode_file_name): New functions. src/termcap.c (tgetent): Adapt to the change in arguments of dostounix_filename. src/sysdep.c (sys_subshell) [WINDOWSNT]: Use MAX_UTF8_PATH for file names. src/msdos.c (dostounix_filename, init_environment): Adapt to the change in arguments of dostounix_filename. src/image.c (xpm_load, tiff_load, gif_load, imagemagick_load) [WINDOWSNT]: Encode file names passed to the image libraries in ANSI codepage. src/gnutls.c (Fgnutls_boot): Encode all file names passed to GnuTLS. [WINDOWSNT]: Convert file names to the current ANSI codepage. src/filelock.c (lock_file) [WINDOWSNT]: Adapt to the change in arguments of dostounix_filename. nt/inc/ms-w32.h (MAX_UTF8_PATH): New macro. (opendir, closedir, readdir, seekdir): Redirect to replacement functions. nt/inc/dirent.h: Make d_name[] be MAXNAMELEN*4 characters long. lisp/term/w32-win.el (w32-handle-dropped-file): lisp/startup.el (normal-top-level): lisp/net/browse-url.el (browse-url-file-url): lisp/dnd.el (dnd-get-local-file-name): On MS-Windows, encode and decode file names using 'utf-8' rather than file-name-coding-system. doc/emacs/mule.texi (File Name Coding): Document file-name encoding peculiarities on MS-Windows. doc/lispref/nonascii.texi (Encoding and I/O): Document file-name encoding peculiarities on MS-Windows. etc/NEWS: Mention support on MS-Windows of file names outside of the current locale. Fixes: debbugs:7100
This commit is contained in:
commit
01633a17e7
34 changed files with 2836 additions and 1351 deletions
|
@ -1,3 +1,8 @@
|
|||
2013-12-12 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* mule.texi (File Name Coding): Document file-name encoding
|
||||
peculiarities on MS-Windows.
|
||||
|
||||
2013-12-12 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
* emacs.texi: Sync direntry with info/dir version.
|
||||
|
|
|
@ -1130,6 +1130,21 @@ In the default language environment, non-@acronym{ASCII} characters in
|
|||
file names are not encoded specially; they appear in the file system
|
||||
using the internal Emacs representation.
|
||||
|
||||
@cindex file-name encoding, MS-Windows
|
||||
@vindex w32-unicode-filenames
|
||||
When Emacs runs on MS-Windows versions that are descendants of the
|
||||
NT family (Windows 2000, XP, Vista, Windows 7, and Windows 8), the
|
||||
value of @code{file-name-coding-system} is largely ignored, as Emacs
|
||||
by default uses APIs that allow to pass Unicode file names directly.
|
||||
By contrast, on Windows 9X, file names are encoded using
|
||||
@code{file-name-coding-system}, which should be set to the codepage
|
||||
(@pxref{Coding Systems, codepage}) pertinent for the current system
|
||||
locale. The value of the variable @code{w32-unicode-filenames}
|
||||
controls whether Emacs uses the Unicode APIs when it calls OS
|
||||
functions that accept file names. This variable is set by the startup
|
||||
code to @code{nil} on Windows 9X, and to @code{t} on newer versions of
|
||||
MS-Windows.
|
||||
|
||||
@strong{Warning:} if you change @code{file-name-coding-system} (or the
|
||||
language environment) in the middle of an Emacs session, problems can
|
||||
result if you have already visited files whose names were encoded using
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2013-12-12 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* nonascii.texi (Encoding and I/O): Document file-name encoding
|
||||
peculiarities on MS-Windows.
|
||||
|
||||
2013-12-12 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
* elisp.texi: Sync direntry with info/dir version.
|
||||
|
|
|
@ -1108,6 +1108,16 @@ visited file name, saving may use the wrong file name, or it may get
|
|||
an error. If such a problem happens, use @kbd{C-x C-w} to specify a
|
||||
new file name for that buffer.
|
||||
|
||||
@cindex file-name encoding, MS-Windows
|
||||
On Windows 2000 and later, Emacs by default uses Unicode APIs to
|
||||
pass file names to the OS, so the value of
|
||||
@code{file-name-coding-system} is largely ignored. Lisp applications
|
||||
that need to encode or decode file names on the Lisp level should use
|
||||
@code{utf-8} coding-system when @code{system-type} is
|
||||
@code{windows-nt}; the conversion of UTF-8 encoded file names to the
|
||||
encoding appropriate for communicating with the OS is performed
|
||||
internally by Emacs.
|
||||
|
||||
@node Lisp and Coding Systems
|
||||
@subsection Coding Systems in Lisp
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2013-12-12 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* NEWS: Mention support on MS-Windows of file names outside of the
|
||||
current locale.
|
||||
|
||||
2013-11-23 Xue Fuqiao <xfq.free@gmail.com>
|
||||
|
||||
* TODO: Minor update.
|
||||
|
|
8
etc/NEWS
8
etc/NEWS
|
@ -1000,6 +1000,14 @@ files are in share/emacs/VERSION/etc. (Emacs knows about all these
|
|||
directories and will find the files in there automatically; there's no
|
||||
need to set any variables due to this change.)
|
||||
|
||||
+++
|
||||
** Emacs on Windows 2000 and later can now access files and directories
|
||||
whose names cannot be encoded in the current system codepage.
|
||||
|
||||
The new variable `w32-unicode-filenames' controls this feature: if it
|
||||
is t, Emacs uses Unicode APIs to pass file names to system calls,
|
||||
which lifts the limitation of file names to the current locale.
|
||||
|
||||
+++
|
||||
** The "generate a backtrace on fatal error" feature now works on MS Windows.
|
||||
The backtrace is written to the 'emacs_backtrace.txt' file in the
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2013-12-12 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* term/w32-win.el (w32-handle-dropped-file):
|
||||
* startup.el (normal-top-level):
|
||||
* net/browse-url.el (browse-url-file-url):
|
||||
* dnd.el (dnd-get-local-file-name): On MS-Windows, encode and
|
||||
decode file names using 'utf-8' rather than
|
||||
file-name-coding-system.
|
||||
|
||||
2013-12-12 Fabián Ezequiel Gallina <fgallina@gnu.org>
|
||||
|
||||
* progmodes/python.el (python-indent-context)
|
||||
|
|
11
lisp/dnd.el
11
lisp/dnd.el
|
@ -152,10 +152,13 @@ Return nil if URI is not a local file."
|
|||
(let ((f (cond ((string-match "^file:///" uri) ; XDND format.
|
||||
(substring uri (1- (match-end 0))))
|
||||
((string-match "^file:" uri) ; Old KDE, Motif, Sun
|
||||
(substring uri (match-end 0))))))
|
||||
(and f (setq f (decode-coding-string (dnd-unescape-uri f)
|
||||
(or file-name-coding-system
|
||||
default-file-name-coding-system))))
|
||||
(substring uri (match-end 0)))))
|
||||
(coding (if (equal system-type 'windows-nt)
|
||||
;; W32 pretends that file names are UTF-8 encoded.
|
||||
'utf-8
|
||||
(or file-name-coding-system
|
||||
default-file-name-coding-system))))
|
||||
(and f (setq f (decode-coding-string (dnd-unescape-uri f) coding)))
|
||||
(when (and f must-exist (not (file-readable-p f)))
|
||||
(setq f nil))
|
||||
f))
|
||||
|
|
|
@ -723,9 +723,12 @@ interactively. Turn the filename into a URL with function
|
|||
(defun browse-url-file-url (file)
|
||||
"Return the URL corresponding to FILE.
|
||||
Use variable `browse-url-filename-alist' to map filenames to URLs."
|
||||
(let ((coding (and (default-value 'enable-multibyte-characters)
|
||||
(or file-name-coding-system
|
||||
default-file-name-coding-system))))
|
||||
(let ((coding (if (equal system-type 'windows-nt)
|
||||
;; W32 pretends that file names are UTF-8 encoded.
|
||||
'utf-8
|
||||
(and (default-value 'enable-multibyte-characters)
|
||||
(or file-name-coding-system
|
||||
default-file-name-coding-system)))))
|
||||
(if coding (setq file (encode-coding-string file coding))))
|
||||
(setq file (browse-url-url-encode-chars file "[*\"()',=;?% ]"))
|
||||
(dolist (map browse-url-filename-alist)
|
||||
|
|
|
@ -533,43 +533,45 @@ It is the default value of the variable `top-level'."
|
|||
;; for many other file-name variables and directory lists, so it
|
||||
;; is important to decode it ASAP.
|
||||
(when locale-coding-system
|
||||
(save-excursion
|
||||
(dolist (elt (buffer-list))
|
||||
(set-buffer elt)
|
||||
(if default-directory
|
||||
(setq default-directory
|
||||
(decode-coding-string default-directory
|
||||
locale-coding-system t)))))
|
||||
(let ((coding (if (eq system-type 'windows-nt)
|
||||
;; MS-Windows build converts all file names to
|
||||
;; UTF-8 during startup.
|
||||
'utf-8
|
||||
locale-coding-system)))
|
||||
(save-excursion
|
||||
(dolist (elt (buffer-list))
|
||||
(set-buffer elt)
|
||||
(if default-directory
|
||||
(setq default-directory
|
||||
(decode-coding-string default-directory coding t)))))
|
||||
|
||||
;; Decode all the important variables and directory lists, now
|
||||
;; that we know the locale's encoding. This is because the
|
||||
;; values of these variables are until here unibyte undecoded
|
||||
;; strings created by build_unibyte_string. data-directory in
|
||||
;; particular is used to construct many other standard directory
|
||||
;; names, so it must be decoded ASAP.
|
||||
;; Note that charset-map-path cannot be decoded here, since we
|
||||
;; could then be trapped in infinite recursion below, when we
|
||||
;; load subdirs.el, because encoding a directory name might need
|
||||
;; to load a charset map, which will want to encode
|
||||
;; charset-map-path, which will want to load the same charset
|
||||
;; map... So decoding of charset-map-path is delayed until
|
||||
;; further down below.
|
||||
(dolist (pathsym '(load-path exec-path))
|
||||
(let ((path (symbol-value pathsym)))
|
||||
(if (listp path)
|
||||
(set pathsym (mapcar (lambda (dir)
|
||||
(decode-coding-string
|
||||
dir
|
||||
locale-coding-system t))
|
||||
path)))))
|
||||
(dolist (filesym '(data-directory doc-directory exec-directory
|
||||
installation-directory
|
||||
invocation-directory invocation-name
|
||||
source-directory
|
||||
shared-game-score-directory))
|
||||
(let ((file (symbol-value filesym)))
|
||||
(if (stringp file)
|
||||
(set filesym (decode-coding-string file locale-coding-system t))))))
|
||||
;; Decode all the important variables and directory lists, now
|
||||
;; that we know the locale's encoding. This is because the
|
||||
;; values of these variables are until here unibyte undecoded
|
||||
;; strings created by build_unibyte_string. data-directory in
|
||||
;; particular is used to construct many other standard
|
||||
;; directory names, so it must be decoded ASAP. Note that
|
||||
;; charset-map-path cannot be decoded here, since we could
|
||||
;; then be trapped in infinite recursion below, when we load
|
||||
;; subdirs.el, because encoding a directory name might need to
|
||||
;; load a charset map, which will want to encode
|
||||
;; charset-map-path, which will want to load the same charset
|
||||
;; map... So decoding of charset-map-path is delayed until
|
||||
;; further down below.
|
||||
(dolist (pathsym '(load-path exec-path))
|
||||
(let ((path (symbol-value pathsym)))
|
||||
(if (listp path)
|
||||
(set pathsym (mapcar (lambda (dir)
|
||||
(decode-coding-string dir coding t))
|
||||
path)))))
|
||||
(dolist (filesym '(data-directory doc-directory exec-directory
|
||||
installation-directory
|
||||
invocation-directory invocation-name
|
||||
source-directory
|
||||
shared-game-score-directory))
|
||||
(let ((file (symbol-value filesym)))
|
||||
(if (stringp file)
|
||||
(set filesym (decode-coding-string file coding t)))))))
|
||||
|
||||
(let ((dir default-directory))
|
||||
(with-current-buffer "*Messages*"
|
||||
|
@ -599,12 +601,13 @@ It is the default value of the variable `top-level'."
|
|||
;; need for encoding them are already loaded, we are ready to
|
||||
;; decode charset-map-path.
|
||||
(if (listp charset-map-path)
|
||||
(setq charset-map-path
|
||||
(mapcar (lambda (dir)
|
||||
(decode-coding-string
|
||||
dir
|
||||
locale-coding-system t))
|
||||
charset-map-path)))
|
||||
(let ((coding (if (eq system-type 'windows-nt)
|
||||
'utf-8
|
||||
locale-coding-system)))
|
||||
(setq charset-map-path
|
||||
(mapcar (lambda (dir)
|
||||
(decode-coding-string dir coding t))
|
||||
charset-map-path))))
|
||||
(setq default-directory (abbreviate-file-name default-directory))
|
||||
(let ((old-face-font-rescale-alist face-font-rescale-alist))
|
||||
(unwind-protect
|
||||
|
|
|
@ -110,8 +110,13 @@
|
|||
(let ((f (if (eq system-type 'cygwin)
|
||||
(cygwin-convert-file-name-from-windows file-name t)
|
||||
(subst-char-in-string ?\\ ?/ file-name)))
|
||||
(coding (or file-name-coding-system
|
||||
default-file-name-coding-system)))
|
||||
(coding (if (eq system-type 'windows-nt)
|
||||
;; Native w32 build pretends that its file names
|
||||
;; are encoded in UTF-8, and converts to the
|
||||
;; appropriate encoding internally.
|
||||
'utf-8
|
||||
(or file-name-coding-system
|
||||
default-file-name-coding-system))))
|
||||
|
||||
(setq file-name
|
||||
(mapconcat 'url-hexify-string
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2013-12-12 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* inc/ms-w32.h (MAX_UTF8_PATH): New macro.
|
||||
(opendir, closedir, readdir, seekdir): Redirect to replacement
|
||||
functions.
|
||||
* inc/dirent.h: Make d_name[] be MAXNAMELEN*4 characters long.
|
||||
|
||||
2013-11-27 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
* README.W32:
|
||||
|
|
|
@ -40,7 +40,7 @@ struct dirent /* data from readdir() */
|
|||
__int64 d_time_write;
|
||||
_fsize_t d_size;
|
||||
#endif
|
||||
char d_name[MAXNAMLEN+1]; /* name of file */
|
||||
char d_name[MAXNAMLEN * 4 + 1]; /* name of file */
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
|
|
@ -152,6 +152,9 @@ extern char *getenv ();
|
|||
#define MAXPATHLEN _MAX_PATH
|
||||
#endif
|
||||
|
||||
/* This is used to hold UTF-8 encoded file names. */
|
||||
#define MAX_UTF8_PATH (MAXPATHLEN * 4)
|
||||
|
||||
#ifdef HAVE_NTGUI
|
||||
# ifndef HAVE_WINDOW_SYSTEM
|
||||
# define HAVE_WINDOW_SYSTEM 1
|
||||
|
@ -218,6 +221,14 @@ extern struct tm * sys_localtime (const time_t *);
|
|||
#define strerror sys_strerror
|
||||
#undef unlink
|
||||
#define unlink sys_unlink
|
||||
#undef opendir
|
||||
#define opendir sys_opendir
|
||||
#undef closedir
|
||||
#define closedir sys_closedir
|
||||
#undef readdir
|
||||
#define readdir sys_readdir
|
||||
#undef seekdir
|
||||
#define seekdir sys_seekdir
|
||||
/* This prototype is needed because some files include config.h
|
||||
_after_ the standard headers, so sys_unlink gets no prototype from
|
||||
stdio.h or io.h. */
|
||||
|
|
125
src/ChangeLog
125
src/ChangeLog
|
@ -1,3 +1,128 @@
|
|||
2013-12-12 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
Support file names on MS-Windows that use characters outside of
|
||||
the current system codepage. (Bug#7100)
|
||||
|
||||
* w32.c (get_file_security, set_file_security)
|
||||
(create_symbolic_link): Separate pointers and boolean flags for
|
||||
ANSI and Unicode APIs. Use the latter if w32_unicode_filenames is
|
||||
non-zero, else the former.
|
||||
(codepage_for_filenames, filename_to_utf16, )
|
||||
(filename_from_utf16, filename_to_ansi, filename_from_ansi): New
|
||||
functions.
|
||||
(init_user_info): Allow $HOME and $SHELL to include non-ANSI
|
||||
characters.
|
||||
(normalize_filename): Lose the DBCS code, now works on UTF-8.
|
||||
Accept only one argument; all callers changed.
|
||||
(dostounix_filename): Remove the second argument, now works in
|
||||
UTF-8. All callers changed.
|
||||
(parse_root): Lose DBCS code.
|
||||
(get_long_basename, w32_get_short_filename, init_environment)
|
||||
(GetCachedVolumeInformation, sys_readdir, open_unc_volume)
|
||||
(read_unc_volume, logon_network_drive, faccessat, sys_chdir)
|
||||
(sys_chmod, sys_creat, sys_fopen, sys_link, sys_mkdir, sys_open)
|
||||
(sys_rename_replace, sys_rmdir, sys_unlink, stat_worker, utime)
|
||||
(is_symlink, readlink, chase_symlinks, w32_delayed_load): Work in
|
||||
Unicode mode if w32_unicode_filenames is non-zero, in ANSI mode
|
||||
otherwise.
|
||||
(ansi_encode_filename): New function.
|
||||
(get_emacs_configuration, get_emacs_configuration_options):
|
||||
Functions deleted.
|
||||
(add_volume_info, GetCachedVolumeInformation): Run the input file
|
||||
name through unixtodos_filename, to ensure it is stored and
|
||||
referenced in canonical form.
|
||||
(get_volume_info): Lose the DBCS code, now works in UTF-8.
|
||||
(logon_network_drive, sys_link, utime): Improve error handling.
|
||||
(sys_access): New function.
|
||||
(hashval, generate_inode_val): Unused functions deleted.
|
||||
(symlink, readlink, readlinkat): Lose DBCS code, now works in UTF-8.
|
||||
(check_windows_init_file): Convert error message from UTF-8 to
|
||||
ANSI codepage, for display in the message box.
|
||||
(globals_of_w32): Set w32_unicode_filenames according to the OS
|
||||
version.
|
||||
|
||||
* w32term.c (construct_drag_n_drop): Work in Unicode mode when
|
||||
w32_unicode_filenames is non-zero, ANSI mode otherwise.
|
||||
(syms_of_w32term): Declare w32-unicode-filenames.
|
||||
|
||||
* w32proc.c (new_child, delete_child): Remove code that handled
|
||||
unused pending_deletion and input_file members of the child struct.
|
||||
(create_child, sys_spawnve): Convert all file names to ANSI
|
||||
codepage. Use ANSI APIs explicitly; forcibly fail if any file
|
||||
name cannot be encoded in ANSI codepage. Don't use
|
||||
unixtodos_filename, mirror slashes by hand.
|
||||
(record_infile, record_pending_deletion): Functions deleted.
|
||||
(Fw32_short_file_name): Call w32_get_short_filename instead of
|
||||
GetShortPathName.
|
||||
|
||||
* w32notify.c (add_watch): Work in Unicode mode when
|
||||
w32_unicode_filenames is non-zero, ANSI mode otherwise.
|
||||
(Fw32notify_add_watch): Rewrite to avoid using GetFullPathName;
|
||||
instead, do the same with Lisp primitives.
|
||||
|
||||
* w32fns.c (file_dialog_callback, Fx_file_dialog)
|
||||
(Fsystem_move_file_to_trash, Fw32_shell_execute)
|
||||
(Ffile_system_info, Fdefault_printer_name): Work in Unicode mode
|
||||
when w32_unicode_filenames is non-zero, ANSI mode otherwise.
|
||||
(Fw32_shell_execute): Improve error reporting.
|
||||
(Fdefault_printer_name): Ifdef away for Cygwin.
|
||||
|
||||
* w32.h (struct _child_process): Remove input_file and
|
||||
pending_deletion members that are no longer used.
|
||||
(dostounix_filename, w32_get_short_filename, filename_from_ansi)
|
||||
(filename_to_ansi, filename_from_utf16, filename_to_utf16)
|
||||
(ansi_encode_filename): New and updated prototypes.
|
||||
|
||||
* unexw32.c (open_input_file, open_output_file, unexec): Use ANSI
|
||||
APIs explicitly.
|
||||
(unexec): Don't use dostounix_filename, it expects a file name in
|
||||
UTF-8. Instead, mirror backslashes by hand. Convert NEW_NAME to
|
||||
ANSI encoding.
|
||||
|
||||
* fileio.c (Ffile_name_directory, file_name_as_directory)
|
||||
(directory_file_name, Fexpand_file_name)
|
||||
(Fsubstitute_in_file_name) [WINDOWSNT]: Adapt to the change in
|
||||
arguments of dostounix_filename.
|
||||
(Fexpand_file_name) [WINDOWSNT]: Convert value of $HOME to UTF-8.
|
||||
use MAX_UTF8_PATH for size of file-name strings.
|
||||
(emacs_readlinkat): Build an explicitly unibyte string for file
|
||||
names.
|
||||
(syms_of_fileio) <file-name-coding-system>
|
||||
default-file-name-coding-system>: Mention MS-Windows peculiarities.
|
||||
|
||||
* emacs.c (init_cmdargs) [WINDOWSNT]: Convert argv[0] to UTF-8.
|
||||
(main) [WINDOWSNT]: Convert the argv[] elements that are files or
|
||||
directories to UTF-8.
|
||||
(decode_env_path) [WINDOWSNT]: Convert file names taken from the
|
||||
environment, and each element of the input PATH, to UTF-8.
|
||||
|
||||
* dired.c (file_attributes): Use build_unibyte_string explicitly
|
||||
to make Lisp strings from user and group names.
|
||||
|
||||
* coding.h (ENCODE_FILE, DECODE_FILE): Just call encode_file and
|
||||
decode_file.
|
||||
|
||||
* coding.c (decode_file_name, encode_file_name): New functions.
|
||||
|
||||
* termcap.c (tgetent): Adapt to the change in arguments of
|
||||
dostounix_filename.
|
||||
|
||||
* sysdep.c (sys_subshell) [WINDOWSNT]: Use MAX_UTF8_PATH for file
|
||||
names.
|
||||
|
||||
* msdos.c (dostounix_filename, init_environment): Adapt to the
|
||||
change in arguments of dostounix_filename.
|
||||
|
||||
* image.c (xpm_load, tiff_load, gif_load, imagemagick_load)
|
||||
[WINDOWSNT]: Encode file names passed to the image libraries in
|
||||
ANSI codepage.
|
||||
|
||||
* gnutls.c (Fgnutls_boot): Encode all file names passed to GnuTLS.
|
||||
[WINDOWSNT]: Convert file names to the current ANSI codepage.
|
||||
|
||||
* filelock.c (lock_file) [WINDOWSNT]: Adapt to the change in
|
||||
arguments of dostounix_filename.
|
||||
|
||||
2013-12-12 Dmitry Antipov <dmantipov@yandex.ru>
|
||||
|
||||
* font.h (struct font_entity) [HAVE_NS]: New field to record
|
||||
|
|
49
src/coding.c
49
src/coding.c
|
@ -9490,6 +9490,55 @@ code_convert_string_norecord (Lisp_Object string, Lisp_Object coding_system,
|
|||
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)
|
||||
{
|
||||
/* This is especially important during bootstrap and dumping, when
|
||||
file-name encoding is not yet known, and therefore any non-ASCII
|
||||
file names are unibyte strings, and could only be thrashed if we
|
||||
try to encode them. */
|
||||
if (!STRING_MULTIBYTE (fname))
|
||||
return 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,
|
||||
|
|
24
src/coding.h
24
src/coding.h
|
@ -670,27 +670,13 @@ struct coding_system
|
|||
(code) = (s1 << 8) | s2; \
|
||||
} while (0)
|
||||
|
||||
/* Encode the file name NAME using the specified coding system for
|
||||
file names, if any. If NAME is a unibyte string, return NAME. */
|
||||
#define ENCODE_FILE(name) \
|
||||
(! STRING_MULTIBYTE (name) \
|
||||
? 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)))
|
||||
|
||||
/* Encode the file name NAME using the specified coding system
|
||||
for file names, if any. */
|
||||
#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. */
|
||||
|
@ -718,6 +704,8 @@ extern Lisp_Object code_convert_string (Lisp_Object, Lisp_Object,
|
|||
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);
|
||||
|
|
|
@ -958,11 +958,11 @@ file_attributes (int fd, char const *name, Lisp_Object id_format)
|
|||
unblock_input ();
|
||||
}
|
||||
if (uname)
|
||||
values[2] = DECODE_SYSTEM (build_string (uname));
|
||||
values[2] = DECODE_SYSTEM (build_unibyte_string (uname));
|
||||
else
|
||||
values[2] = make_fixnum_or_float (s.st_uid);
|
||||
if (gname)
|
||||
values[3] = DECODE_SYSTEM (build_string (gname));
|
||||
values[3] = DECODE_SYSTEM (build_unibyte_string (gname));
|
||||
else
|
||||
values[3] = make_fixnum_or_float (s.st_gid);
|
||||
|
||||
|
|
80
src/emacs.c
80
src/emacs.c
|
@ -36,6 +36,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#ifdef WINDOWSNT
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <mbstring.h>
|
||||
#include "w32.h"
|
||||
#include "w32heap.h"
|
||||
#endif
|
||||
|
@ -393,7 +394,20 @@ init_cmdargs (int argc, char **argv, int skip_args, char *original_pwd)
|
|||
initial_argv = argv;
|
||||
initial_argc = argc;
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
/* Must use argv[0] converted to UTF-8, as it begets many standard
|
||||
file and directory names. */
|
||||
{
|
||||
char argv0[MAX_UTF8_PATH];
|
||||
|
||||
if (filename_from_ansi (argv[0], argv0) == 0)
|
||||
raw_name = build_unibyte_string (argv0);
|
||||
else
|
||||
raw_name = build_unibyte_string (argv[0]);
|
||||
}
|
||||
#else
|
||||
raw_name = build_unibyte_string (argv[0]);
|
||||
#endif
|
||||
|
||||
/* Add /: to the front of the name
|
||||
if it would otherwise be treated as magic. */
|
||||
|
@ -795,6 +809,14 @@ main (int argc, char **argv)
|
|||
|
||||
if (argmatch (argv, argc, "-chdir", "--chdir", 4, &ch_to_dir, &skip_args))
|
||||
{
|
||||
#ifdef WINDOWSNT
|
||||
/* argv[] array is kept in its original ANSI codepage encoding,
|
||||
we need to convert to UTF-8, for chdir to work. */
|
||||
char newdir[MAX_UTF8_PATH];
|
||||
|
||||
filename_from_ansi (ch_to_dir, newdir);
|
||||
ch_to_dir = newdir;
|
||||
#endif
|
||||
original_pwd = get_current_dir_name ();
|
||||
if (chdir (ch_to_dir) != 0)
|
||||
{
|
||||
|
@ -1539,7 +1561,16 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
|
|||
char *file;
|
||||
/* Handle -l loadup, args passed by Makefile. */
|
||||
if (argmatch (argv, argc, "-l", "--load", 3, &file, &skip_args))
|
||||
Vtop_level = list2 (intern_c_string ("load"), build_string (file));
|
||||
{
|
||||
#ifdef WINDOWSNT
|
||||
char file_utf8[MAX_UTF8_PATH];
|
||||
|
||||
if (filename_from_ansi (file, file_utf8) == 0)
|
||||
file = file_utf8;
|
||||
#endif
|
||||
Vtop_level = list2 (intern_c_string ("load"),
|
||||
build_unibyte_string (file));
|
||||
}
|
||||
/* Unless next switch is -nl, load "loadup.el" first thing. */
|
||||
if (! no_loadup)
|
||||
Vtop_level = list2 (intern_c_string ("load"),
|
||||
|
@ -2185,9 +2216,15 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
|
|||
Lisp_Object empty_element = empty ? Qnil : build_string (".");
|
||||
#ifdef WINDOWSNT
|
||||
bool defaulted = 0;
|
||||
const char *emacs_dir = egetenv ("emacs_dir");
|
||||
static const char *emacs_dir_env = "%emacs_dir%/";
|
||||
const size_t emacs_dir_len = strlen (emacs_dir_env);
|
||||
const char *edir = egetenv ("emacs_dir");
|
||||
char emacs_dir[MAX_UTF8_PATH];
|
||||
|
||||
/* egetenv looks in process-environment, which holds the variables
|
||||
in their original system-locale encoding. We need emacs_dir to
|
||||
be in UTF-8. */
|
||||
filename_from_ansi (edir, emacs_dir);
|
||||
#endif
|
||||
|
||||
/* It's okay to use getenv here, because this function is only used
|
||||
|
@ -2208,9 +2245,44 @@ decode_env_path (const char *evarname, const char *defalt, bool empty)
|
|||
/* Ensure values from the environment use the proper directory separator. */
|
||||
if (path)
|
||||
{
|
||||
char *path_copy = alloca (strlen (path) + 1);
|
||||
char *path_copy;
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
char *path_utf8, *q, *d;
|
||||
int cnv_result;
|
||||
|
||||
/* Convert each element of PATH to UTF-8. */
|
||||
p = path_copy = alloca (strlen (path) + 1);
|
||||
strcpy (path_copy, path);
|
||||
dostounix_filename (path_copy, 0);
|
||||
d = path_utf8 = alloca (4 * strlen (path) + 1);
|
||||
*d = '\0';
|
||||
do {
|
||||
q = _mbschr (p, SEPCHAR);
|
||||
if (q)
|
||||
*q = '\0';
|
||||
cnv_result = filename_from_ansi (p, d);
|
||||
if (q)
|
||||
{
|
||||
*q++ = SEPCHAR;
|
||||
p = q;
|
||||
/* If conversion of this PATH elements fails, make sure
|
||||
destination pointer will stay put, thus effectively
|
||||
ignoring the offending element. */
|
||||
if (cnv_result == 0)
|
||||
{
|
||||
d += strlen (d);
|
||||
*d++ = SEPCHAR;
|
||||
}
|
||||
}
|
||||
else if (cnv_result != 0 && d > path_utf8)
|
||||
d[-1] = '\0'; /* remove last semi-colon and null-terminate PATH */
|
||||
} while (q);
|
||||
path_copy = path_utf8;
|
||||
#else /* MSDOS */
|
||||
path_copy = alloca (strlen (path) + 1);
|
||||
strcpy (path_copy, path);
|
||||
#endif
|
||||
dostounix_filename (path_copy);
|
||||
path = path_copy;
|
||||
}
|
||||
#endif
|
||||
|
|
55
src/fileio.c
55
src/fileio.c
|
@ -460,7 +460,8 @@ Given a Unix syntax file name, returns a string ending in slash. */)
|
|||
strcat (res, "/");
|
||||
beg = res;
|
||||
p = beg + strlen (beg);
|
||||
dostounix_filename (beg, 0);
|
||||
dostounix_filename (beg);
|
||||
/* FIXME: Figure out the multibyte vs unibyte stuff here. */
|
||||
tem_fn = make_specified_string (beg, -1, p - beg,
|
||||
STRING_MULTIBYTE (filename));
|
||||
}
|
||||
|
@ -471,7 +472,7 @@ Given a Unix syntax file name, returns a string ending in slash. */)
|
|||
else if (STRING_MULTIBYTE (filename))
|
||||
{
|
||||
tem_fn = make_specified_string (beg, -1, p - beg, 1);
|
||||
dostounix_filename (SSDATA (tem_fn), 1);
|
||||
dostounix_filename (SSDATA (tem_fn));
|
||||
#ifdef WINDOWSNT
|
||||
if (!NILP (Vw32_downcase_file_names))
|
||||
tem_fn = Fdowncase (tem_fn);
|
||||
|
@ -479,7 +480,7 @@ Given a Unix syntax file name, returns a string ending in slash. */)
|
|||
}
|
||||
else
|
||||
{
|
||||
dostounix_filename (beg, 0);
|
||||
dostounix_filename (beg);
|
||||
tem_fn = make_specified_string (beg, -1, p - beg, 0);
|
||||
}
|
||||
return tem_fn;
|
||||
|
@ -583,7 +584,7 @@ file_name_as_directory (char *dst, const char *src, ptrdiff_t srclen,
|
|||
dst[srclen++] = DIRECTORY_SEP;
|
||||
dst[srclen] = 0;
|
||||
#ifdef DOS_NT
|
||||
dostounix_filename (dst, multibyte);
|
||||
dostounix_filename (dst);
|
||||
#endif
|
||||
return srclen;
|
||||
}
|
||||
|
@ -652,7 +653,7 @@ directory_file_name (char *dst, char *src, ptrdiff_t srclen, bool multibyte)
|
|||
memcpy (dst, src, srclen);
|
||||
dst[srclen] = 0;
|
||||
#ifdef DOS_NT
|
||||
dostounix_filename (dst, multibyte);
|
||||
dostounix_filename (dst);
|
||||
#endif
|
||||
return srclen;
|
||||
}
|
||||
|
@ -1101,7 +1102,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|
|||
#ifdef DOS_NT
|
||||
/* Make sure directories are all separated with /, but
|
||||
avoid allocation of a new string when not required. */
|
||||
dostounix_filename (nm, multibyte);
|
||||
dostounix_filename (nm);
|
||||
#ifdef WINDOWSNT
|
||||
if (IS_DIRECTORY_SEP (nm[1]))
|
||||
{
|
||||
|
@ -1162,7 +1163,18 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|
|||
nm++;
|
||||
/* `egetenv' may return a unibyte string, which will bite us since
|
||||
we expect the directory to be multibyte. */
|
||||
tem = build_string (newdir);
|
||||
#ifdef WINDOWSNT
|
||||
if (newdir[0])
|
||||
{
|
||||
char newdir_utf8[MAX_UTF8_PATH];
|
||||
|
||||
filename_from_ansi (newdir, newdir_utf8);
|
||||
tem = build_string (newdir_utf8);
|
||||
}
|
||||
else
|
||||
#else
|
||||
tem = build_string (newdir);
|
||||
#endif
|
||||
if (multibyte && !STRING_MULTIBYTE (tem))
|
||||
{
|
||||
hdir = DECODE_FILE (tem);
|
||||
|
@ -1286,6 +1298,11 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|
|||
indirectly by prepending newdir to nm if necessary, and using
|
||||
cwd (or the wd of newdir's drive) as the new newdir. */
|
||||
char *adir;
|
||||
#ifdef WINDOWSNT
|
||||
const int adir_size = MAX_UTF8_PATH;
|
||||
#else
|
||||
const int adir_size = MAXPATHLEN + 1;
|
||||
#endif
|
||||
|
||||
if (IS_DRIVE (newdir[0]) && IS_DEVICE_SEP (newdir[1]))
|
||||
{
|
||||
|
@ -1301,14 +1318,14 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|
|||
strcat (tmp, nm);
|
||||
nm = tmp;
|
||||
}
|
||||
adir = alloca (MAXPATHLEN + 1);
|
||||
adir = alloca (adir_size);
|
||||
if (drive)
|
||||
{
|
||||
if (!getdefdir (c_toupper (drive) - 'A' + 1, adir))
|
||||
strcpy (adir, "/");
|
||||
}
|
||||
else
|
||||
getcwd (adir, MAXPATHLEN + 1);
|
||||
getcwd (adir, adir_size);
|
||||
if (multibyte)
|
||||
{
|
||||
Lisp_Object tem = build_string (adir);
|
||||
|
@ -1479,7 +1496,7 @@ filesystem tree, not (expand-file-name ".." dirname). */)
|
|||
target[1] = ':';
|
||||
}
|
||||
result = make_specified_string (target, -1, o - target, multibyte);
|
||||
dostounix_filename (SSDATA (result), multibyte);
|
||||
dostounix_filename (SSDATA (result));
|
||||
#ifdef WINDOWSNT
|
||||
if (!NILP (Vw32_downcase_file_names))
|
||||
result = Fdowncase (result);
|
||||
|
@ -1763,7 +1780,7 @@ those `/' is discarded. */)
|
|||
nm = xlispstrdupa (filename);
|
||||
|
||||
#ifdef DOS_NT
|
||||
dostounix_filename (nm, multibyte);
|
||||
dostounix_filename (nm);
|
||||
substituted = (memcmp (nm, SDATA (filename), SBYTES (filename)) != 0);
|
||||
#endif
|
||||
endp = nm + SBYTES (filename);
|
||||
|
@ -2661,9 +2678,9 @@ emacs_readlinkat (int fd, char const *filename)
|
|||
if (!buf)
|
||||
return Qnil;
|
||||
|
||||
val = build_string (buf);
|
||||
val = build_unibyte_string (buf);
|
||||
if (buf[0] == '/' && strchr (buf, ':'))
|
||||
val = concat2 (build_string ("/:"), val);
|
||||
val = concat2 (build_unibyte_string ("/:"), val);
|
||||
if (buf != readlink_buf)
|
||||
xfree (buf);
|
||||
val = DECODE_FILE (val);
|
||||
|
@ -5858,7 +5875,11 @@ syms_of_fileio (void)
|
|||
|
||||
DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system,
|
||||
doc: /* Coding system for encoding file names.
|
||||
If it is nil, `default-file-name-coding-system' (which see) is used. */);
|
||||
If it is nil, `default-file-name-coding-system' (which see) is used.
|
||||
|
||||
On MS-Windows, the value of this variable is largely ignored if
|
||||
\`w32-unicode-filenames' (which see) is non-nil. Emacs on Windows
|
||||
behaves as if file names were encoded in `utf-8'. */);
|
||||
Vfile_name_coding_system = Qnil;
|
||||
|
||||
DEFVAR_LISP ("default-file-name-coding-system",
|
||||
|
@ -5869,7 +5890,11 @@ This variable is used only when `file-name-coding-system' is nil.
|
|||
This variable is set/changed by the command `set-language-environment'.
|
||||
User should not set this variable manually,
|
||||
instead use `file-name-coding-system' to get a constant encoding
|
||||
of file names regardless of the current language environment. */);
|
||||
of file names regardless of the current language environment.
|
||||
|
||||
On MS-Windows, the value of this variable is largely ignored if
|
||||
\`w32-unicode-filenames' (which see) is non-nil. Emacs on Windows
|
||||
behaves as if file names were encoded in `utf-8'. */);
|
||||
Vdefault_file_name_coding_system = Qnil;
|
||||
|
||||
DEFSYM (Qformat_decode, "format-decode");
|
||||
|
|
|
@ -689,7 +689,7 @@ lock_file (Lisp_Object fn)
|
|||
/* Ensure we have only '/' separators, to avoid problems with
|
||||
looking (inside fill_in_lock_file_name) for backslashes in file
|
||||
names encoded by some DBCS codepage. */
|
||||
dostounix_filename (SSDATA (fn), 1);
|
||||
dostounix_filename (SSDATA (fn));
|
||||
#endif
|
||||
encoded_fn = ENCODE_FILE (fn);
|
||||
|
||||
|
|
18
src/gnutls.c
18
src/gnutls.c
|
@ -21,6 +21,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
|
||||
#include "lisp.h"
|
||||
#include "process.h"
|
||||
#include "coding.h"
|
||||
|
||||
#ifdef HAVE_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
|
@ -899,6 +900,13 @@ one trustfile (usually a CA bundle). */)
|
|||
{
|
||||
GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
|
||||
SSDATA (trustfile));
|
||||
trustfile = ENCODE_FILE (trustfile);
|
||||
#ifdef WINDOWSNT
|
||||
/* Since GnuTLS doesn't support UTF-8 or UTF-16 encoded
|
||||
file names on Windows, we need to re-encode the file
|
||||
name using the current ANSI codepage. */
|
||||
trustfile = ansi_encode_filename (trustfile);
|
||||
#endif
|
||||
ret = fn_gnutls_certificate_set_x509_trust_file
|
||||
(x509_cred,
|
||||
SSDATA (trustfile),
|
||||
|
@ -921,6 +929,10 @@ one trustfile (usually a CA bundle). */)
|
|||
{
|
||||
GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
|
||||
SSDATA (crlfile));
|
||||
crlfile = ENCODE_FILE (crlfile);
|
||||
#ifdef WINDOWSNT
|
||||
crlfile = ansi_encode_filename (crlfile);
|
||||
#endif
|
||||
ret = fn_gnutls_certificate_set_x509_crl_file
|
||||
(x509_cred, SSDATA (crlfile), file_format);
|
||||
|
||||
|
@ -944,6 +956,12 @@ one trustfile (usually a CA bundle). */)
|
|||
SSDATA (keyfile));
|
||||
GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
|
||||
SSDATA (certfile));
|
||||
keyfile = ENCODE_FILE (keyfile);
|
||||
certfile = ENCODE_FILE (certfile);
|
||||
#ifdef WINDOWSNT
|
||||
keyfile = ansi_encode_filename (keyfile);
|
||||
certfile = ansi_encode_filename (certfile);
|
||||
#endif
|
||||
ret = fn_gnutls_certificate_set_x509_key_file
|
||||
(x509_cred, SSDATA (certfile), SSDATA (keyfile), file_format);
|
||||
|
||||
|
|
15
src/image.c
15
src/image.c
|
@ -3590,6 +3590,12 @@ xpm_load (struct frame *f, struct image *img)
|
|||
}
|
||||
|
||||
#ifdef HAVE_NTGUI
|
||||
#ifdef WINDOWSNT
|
||||
/* FILE is encoded in UTF-8, but image libraries on Windows
|
||||
support neither UTF-8 nor UTF-16 encoded file names. So we
|
||||
need to re-encode it in ANSI. */
|
||||
file = ansi_encode_filename (file);
|
||||
#endif
|
||||
/* XpmReadFileToPixmap is not available in the Windows port of
|
||||
libxpm. But XpmReadFileToImage almost does what we want. */
|
||||
rc = fn_XpmReadFileToImage (&hdc, SDATA (file),
|
||||
|
@ -6968,6 +6974,9 @@ tiff_load (struct frame *f, struct image *img)
|
|||
image_error ("Cannot find image file `%s'", specified_file, Qnil);
|
||||
return 0;
|
||||
}
|
||||
#ifdef WINDOWSNT
|
||||
file = ansi_encode_filename (file);
|
||||
#endif
|
||||
|
||||
/* Try to open the image file. */
|
||||
tiff = fn_TIFFOpen (SSDATA (file), "r");
|
||||
|
@ -7353,6 +7362,9 @@ gif_load (struct frame *f, struct image *img)
|
|||
image_error ("Cannot find image file `%s'", specified_file, Qnil);
|
||||
return 0;
|
||||
}
|
||||
#ifdef WINDOWSNT
|
||||
file = ansi_encode_filename (file);
|
||||
#endif
|
||||
|
||||
/* Open the GIF file. */
|
||||
#if GIFLIB_MAJOR < 5
|
||||
|
@ -8479,6 +8491,9 @@ imagemagick_load (struct frame *f, struct image *img)
|
|||
image_error ("Cannot find image file `%s'", file_name, Qnil);
|
||||
return 0;
|
||||
}
|
||||
#ifdef WINDOWSNT
|
||||
file = ansi_encode_filename (file);
|
||||
#endif
|
||||
success_p = imagemagick_load_image (f, img, 0, 0, SSDATA (file));
|
||||
}
|
||||
/* Else its not a file, its a lisp object. Load the image from a
|
||||
|
|
|
@ -3295,7 +3295,7 @@ void msdos_downcase_filename (unsigned char *);
|
|||
/* Destructively turn backslashes into slashes. */
|
||||
|
||||
void
|
||||
dostounix_filename (char *p, int ignore)
|
||||
dostounix_filename (char *p)
|
||||
{
|
||||
msdos_downcase_filename (p);
|
||||
|
||||
|
@ -3559,7 +3559,7 @@ init_environment (int argc, char **argv, int skip_args)
|
|||
if (!s) s = "c:/command.com";
|
||||
t = alloca (strlen (s) + 1);
|
||||
strcpy (t, s);
|
||||
dostounix_filename (t, 0);
|
||||
dostounix_filename (t);
|
||||
setenv ("SHELL", t, 0);
|
||||
|
||||
/* PATH is also downcased and backslashes mirrored. */
|
||||
|
@ -3569,7 +3569,7 @@ init_environment (int argc, char **argv, int skip_args)
|
|||
/* Current directory is always considered part of MsDos's path but it is
|
||||
not normally mentioned. Now it is. */
|
||||
strcat (strcpy (t, ".;"), s);
|
||||
dostounix_filename (t, 0); /* Not a single file name, but this should work. */
|
||||
dostounix_filename (t); /* Not a single file name, but this should work. */
|
||||
setenv ("PATH", t, 1);
|
||||
|
||||
/* In some sense all dos users have root privileges, so... */
|
||||
|
|
|
@ -29,7 +29,7 @@ void dos_set_window_size (int *, int *);
|
|||
|
||||
int getdefdir (int, char*);
|
||||
void unixtodos_filename (char *);
|
||||
void dostounix_filename (char *, int);
|
||||
void dostounix_filename (char *);
|
||||
char *rootrelativepath (char *);
|
||||
void init_environment (int, char **, int);
|
||||
void internal_terminal_init (void);
|
||||
|
|
|
@ -464,7 +464,11 @@ sys_subshell (void)
|
|||
{
|
||||
#ifdef DOS_NT /* Demacs 1.1.2 91/10/20 Manabu Higashida */
|
||||
int st;
|
||||
#ifdef MSDOS
|
||||
char oldwd[MAXPATHLEN+1]; /* Fixed length is safe on MSDOS. */
|
||||
#else
|
||||
char oldwd[MAX_UTF8_PATH];
|
||||
#endif
|
||||
#endif
|
||||
pid_t pid;
|
||||
int status;
|
||||
|
|
|
@ -393,7 +393,7 @@ tgetent (char *bp, const char *name)
|
|||
if (termcap_name && (*termcap_name == '\\'
|
||||
|| *termcap_name == '/'
|
||||
|| termcap_name[1] == ':'))
|
||||
dostounix_filename (termcap_name, 0);
|
||||
dostounix_filename (termcap_name);
|
||||
#endif
|
||||
|
||||
filep = termcap_name && valid_filename_p (termcap_name);
|
||||
|
|
|
@ -120,6 +120,8 @@ _start (void)
|
|||
|
||||
/* File handling. */
|
||||
|
||||
/* Implementation note: this and the next functions work with ANSI
|
||||
codepage encoded file names! */
|
||||
int
|
||||
open_input_file (file_data *p_file, char *filename)
|
||||
{
|
||||
|
@ -128,8 +130,8 @@ open_input_file (file_data *p_file, char *filename)
|
|||
void *file_base;
|
||||
unsigned long size, upper_size;
|
||||
|
||||
file = CreateFile (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
file = CreateFileA (filename, GENERIC_READ, FILE_SHARE_READ, NULL,
|
||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
|
@ -166,9 +168,9 @@ open_output_file (file_data *p_file, char *filename, unsigned long size)
|
|||
creating it, all the emacs-XX.YY.ZZ.nn.exe end up being hard
|
||||
links to the same file, which defeats the purpose of these hard
|
||||
links: being able to run previous builds. */
|
||||
DeleteFile (filename);
|
||||
file = CreateFile (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
DeleteFileA (filename);
|
||||
file = CreateFileA (filename, GENERIC_READ | GENERIC_WRITE, 0, NULL,
|
||||
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (file == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
|
||||
|
@ -722,23 +724,30 @@ void
|
|||
unexec (const char *new_name, const char *old_name)
|
||||
{
|
||||
file_data in_file, out_file;
|
||||
char out_filename[MAX_PATH], in_filename[MAX_PATH];
|
||||
char out_filename[MAX_PATH], in_filename[MAX_PATH], new_name_a[MAX_PATH];
|
||||
unsigned long size;
|
||||
char *p;
|
||||
char *q;
|
||||
|
||||
/* Ignore old_name, and get our actual location from the OS. */
|
||||
if (!GetModuleFileName (NULL, in_filename, MAX_PATH))
|
||||
if (!GetModuleFileNameA (NULL, in_filename, MAX_PATH))
|
||||
abort ();
|
||||
dostounix_filename (in_filename, 0);
|
||||
|
||||
/* Can't use dostounix_filename here, since that needs its file name
|
||||
argument encoded in UTF-8. */
|
||||
for (p = in_filename; *p; p = CharNextA (p))
|
||||
if (*p == '\\')
|
||||
*p = '/';
|
||||
|
||||
strcpy (out_filename, in_filename);
|
||||
filename_to_ansi (new_name, new_name_a);
|
||||
|
||||
/* Change the base of the output filename to match the requested name. */
|
||||
if ((p = strrchr (out_filename, '/')) == NULL)
|
||||
abort ();
|
||||
/* The filenames have already been expanded, and will be in Unix
|
||||
format, so it is safe to expect an absolute name. */
|
||||
if ((q = strrchr (new_name, '/')) == NULL)
|
||||
if ((q = strrchr (new_name_a, '/')) == NULL)
|
||||
abort ();
|
||||
strcpy (p, q);
|
||||
|
||||
|
|
21
src/w32.h
21
src/w32.h
|
@ -103,12 +103,6 @@ typedef struct _child_process
|
|||
OVERLAPPED ovl_read;
|
||||
/* Used for async write operations on serial comm ports. */
|
||||
OVERLAPPED ovl_write;
|
||||
/* Input file, if any, for this subprocess. Should only be non-NULL
|
||||
for async subprocesses. */
|
||||
char *input_file;
|
||||
/* If non-zero, the subprocess input file is temporary and should be
|
||||
deleted when the subprocess exits. */
|
||||
int pending_deletion;
|
||||
} child_process;
|
||||
|
||||
#define MAXDESC FD_SETSIZE
|
||||
|
@ -152,6 +146,9 @@ extern int w32_valid_pointer_p (void *, int);
|
|||
/* Get long (aka "true") form of file name, if it exists. */
|
||||
extern BOOL w32_get_long_filename (char * name, char * buf, int size);
|
||||
|
||||
/* Get the short (a.k.a. "8+3") form of a file name. */
|
||||
extern unsigned int w32_get_short_filename (char *, char *, int);
|
||||
|
||||
/* Prepare our standard handles for proper inheritance by child processes. */
|
||||
extern void prepare_standard_handles (int in, int out,
|
||||
int err, HANDLE handles[4]);
|
||||
|
@ -181,8 +178,14 @@ extern void init_environment (char **);
|
|||
extern void check_windows_init_file (void);
|
||||
extern void syms_of_ntproc (void);
|
||||
extern void syms_of_ntterm (void);
|
||||
extern void dostounix_filename (register char *, int);
|
||||
extern void dostounix_filename (register char *);
|
||||
extern void unixtodos_filename (register char *);
|
||||
extern int filename_from_ansi (const char *, char *);
|
||||
extern int filename_to_ansi (const char *, char *);
|
||||
extern int filename_from_utf16 (const wchar_t *, char *);
|
||||
extern int filename_to_utf16 (const char *, wchar_t *);
|
||||
extern Lisp_Object ansi_encode_filename (Lisp_Object);
|
||||
|
||||
extern BOOL init_winsock (int load_now);
|
||||
extern void srandom (int);
|
||||
extern int random (void);
|
||||
|
@ -194,14 +197,10 @@ extern int pipe2 (int *, int);
|
|||
extern void set_process_dir (char *);
|
||||
extern int sys_spawnve (int, char *, char **, char **);
|
||||
extern void register_child (pid_t, int);
|
||||
extern void record_infile (pid_t, char *);
|
||||
extern void record_pending_deletion (char *);
|
||||
|
||||
extern void sys_sleep (int);
|
||||
extern int sys_link (const char *, const char *);
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_GNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
|
||||
|
|
671
src/w32fns.c
671
src/w32fns.c
|
@ -51,6 +51,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
|
||||
#ifdef WINDOWSNT
|
||||
#include "w32heap.h"
|
||||
#include <mbstring.h>
|
||||
#endif /* WINDOWSNT */
|
||||
|
||||
#if CYGWIN
|
||||
|
@ -6305,18 +6306,31 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
{
|
||||
if (msg == WM_NOTIFY)
|
||||
{
|
||||
OFNOTIFYW * notify_w = (OFNOTIFYW *)lParam;
|
||||
OFNOTIFYA * notify_a = (OFNOTIFYA *)lParam;
|
||||
int dropdown_changed;
|
||||
int dir_index;
|
||||
#ifdef NTGUI_UNICODE
|
||||
OFNOTIFYW * notify = (OFNOTIFYW *)lParam;
|
||||
const int use_unicode = 1;
|
||||
#else /* !NTGUI_UNICODE */
|
||||
OFNOTIFYA * notify = (OFNOTIFYA *)lParam;
|
||||
int use_unicode = w32_unicode_filenames;
|
||||
#endif /* NTGUI_UNICODE */
|
||||
|
||||
/* Detect when the Filter dropdown is changed. */
|
||||
if (notify->hdr.code == CDN_TYPECHANGE
|
||||
|| notify->hdr.code == CDN_INITDONE)
|
||||
if (use_unicode)
|
||||
dropdown_changed =
|
||||
notify_w->hdr.code == CDN_TYPECHANGE
|
||||
|| notify_w->hdr.code == CDN_INITDONE;
|
||||
else
|
||||
dropdown_changed =
|
||||
notify_a->hdr.code == CDN_TYPECHANGE
|
||||
|| notify_a->hdr.code == CDN_INITDONE;
|
||||
if (dropdown_changed)
|
||||
{
|
||||
HWND dialog = GetParent (hwnd);
|
||||
HWND edit_control = GetDlgItem (dialog, FILE_NAME_TEXT_FIELD);
|
||||
HWND list = GetDlgItem (dialog, FILE_NAME_LIST);
|
||||
int hdr_code;
|
||||
|
||||
/* At least on Windows 7, the above attempt to get the window handle
|
||||
to the File Name Text Field fails. The following code does the
|
||||
|
@ -6334,10 +6348,24 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
}
|
||||
|
||||
/* Directories is in index 2. */
|
||||
if (notify->lpOFN->nFilterIndex == 2)
|
||||
if (use_unicode)
|
||||
{
|
||||
CommDlg_OpenSave_SetControlText (dialog, FILE_NAME_TEXT_FIELD,
|
||||
GUISTR ("Current Directory"));
|
||||
dir_index = notify_w->lpOFN->nFilterIndex;
|
||||
hdr_code = notify_w->hdr.code;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir_index = notify_a->lpOFN->nFilterIndex;
|
||||
hdr_code = notify_a->hdr.code;
|
||||
}
|
||||
if (dir_index == 2)
|
||||
{
|
||||
if (use_unicode)
|
||||
SendMessageW (dialog, CDM_SETCONTROLTEXT, FILE_NAME_TEXT_FIELD,
|
||||
(LPARAM)L"Current Directory");
|
||||
else
|
||||
SendMessageA (dialog, CDM_SETCONTROLTEXT, FILE_NAME_TEXT_FIELD,
|
||||
(LPARAM)"Current Directory");
|
||||
EnableWindow (edit_control, FALSE);
|
||||
/* Note that at least on Windows 7, the above call to EnableWindow
|
||||
disables the window that would ordinarily have focus. If we
|
||||
|
@ -6345,16 +6373,21 @@ file_dialog_callback (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|||
no man's land and the user will be unable to tab through the
|
||||
dialog box (pressing tab will only result in a beep).
|
||||
Avoid that problem by setting focus to the list here. */
|
||||
if (notify->hdr.code == CDN_INITDONE)
|
||||
if (hdr_code == CDN_INITDONE)
|
||||
SetFocus (list);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Don't override default filename on init done. */
|
||||
if (notify->hdr.code == CDN_TYPECHANGE)
|
||||
CommDlg_OpenSave_SetControlText (dialog,
|
||||
FILE_NAME_TEXT_FIELD,
|
||||
GUISTR (""));
|
||||
if (hdr_code == CDN_TYPECHANGE)
|
||||
{
|
||||
if (use_unicode)
|
||||
SendMessageW (dialog, CDM_SETCONTROLTEXT,
|
||||
FILE_NAME_TEXT_FIELD, (LPARAM)L"");
|
||||
else
|
||||
SendMessageA (dialog, CDM_SETCONTROLTEXT,
|
||||
FILE_NAME_TEXT_FIELD, (LPARAM)"");
|
||||
}
|
||||
EnableWindow (edit_control, TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -6374,8 +6407,8 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
|
|||
(Lisp_Object prompt, Lisp_Object dir, Lisp_Object default_filename, Lisp_Object mustmatch, Lisp_Object only_dir_p)
|
||||
{
|
||||
/* Filter index: 1: All Files, 2: Directories only */
|
||||
static const guichar_t filter[] =
|
||||
GUISTR ("All Files (*.*)\0*.*\0Directories\0*|*\0");
|
||||
static const wchar_t filter_w[] = L"All Files (*.*)\0*.*\0Directories\0*|*\0";
|
||||
static const char filter_a[] = "All Files (*.*)\0*.*\0Directories\0*|*\0";
|
||||
|
||||
Lisp_Object filename = default_filename;
|
||||
struct frame *f = SELECTED_FRAME ();
|
||||
|
@ -6388,25 +6421,36 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
|
|||
enough struct for the new dialog to trick GetOpenFileName into
|
||||
giving us the new dialogs on newer versions of Windows. */
|
||||
struct {
|
||||
#ifdef NTGUI_UNICODE
|
||||
OPENFILENAMEW details;
|
||||
#else /* !NTGUI_UNICODE */
|
||||
OPENFILENAMEA details;
|
||||
#endif /* NTGUI_UNICODE */
|
||||
|
||||
#if _WIN32_WINNT < 0x500 /* < win2k */
|
||||
PVOID pvReserved;
|
||||
DWORD dwReserved;
|
||||
DWORD FlagsEx;
|
||||
#endif /* < win2k */
|
||||
} new_file_details;
|
||||
} new_file_details_w;
|
||||
|
||||
#ifdef NTGUI_UNICODE
|
||||
wchar_t filename_buf[32*1024 + 1]; // NT kernel maximum
|
||||
OPENFILENAMEW * file_details = &new_file_details.details;
|
||||
wchar_t filename_buf_w[32*1024 + 1]; // NT kernel maximum
|
||||
OPENFILENAMEW * file_details_w = &new_file_details_w.details;
|
||||
const int use_unicode = 1;
|
||||
#else /* not NTGUI_UNICODE */
|
||||
char filename_buf[MAX_PATH + 1];
|
||||
OPENFILENAMEA * file_details = &new_file_details.details;
|
||||
struct {
|
||||
OPENFILENAMEA details;
|
||||
#if _WIN32_WINNT < 0x500 /* < win2k */
|
||||
PVOID pvReserved;
|
||||
DWORD dwReserved;
|
||||
DWORD FlagsEx;
|
||||
#endif /* < win2k */
|
||||
} new_file_details_a;
|
||||
wchar_t filename_buf_w[MAX_PATH + 1], dir_w[MAX_PATH];
|
||||
char filename_buf_a[MAX_PATH + 1], dir_a[MAX_PATH];
|
||||
OPENFILENAMEW * file_details_w = &new_file_details_w.details;
|
||||
OPENFILENAMEA * file_details_a = &new_file_details_a.details;
|
||||
int use_unicode = w32_unicode_filenames;
|
||||
wchar_t *prompt_w;
|
||||
char *prompt_a;
|
||||
int len;
|
||||
char fname_ret[MAX_UTF8_PATH];
|
||||
#endif /* NTGUI_UNICODE */
|
||||
|
||||
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
|
||||
|
@ -6452,6 +6496,10 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
|
|||
to_unicode (prompt, &prompt);
|
||||
to_unicode (dir, &dir);
|
||||
to_unicode (filename, &filename);
|
||||
if (SBYTES (filename) + 1 > sizeof (filename_buf_w))
|
||||
report_file_error ("filename too long", default_filename);
|
||||
|
||||
memcpy (filename_buf_w, SDATA (filename), SBYTES (filename) + 1);
|
||||
#else /* !NTGUI_UNICODE */
|
||||
prompt = ENCODE_FILE (prompt);
|
||||
dir = ENCODE_FILE (dir);
|
||||
|
@ -6462,6 +6510,49 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
|
|||
unixtodos_filename (SDATA (dir));
|
||||
filename = Fcopy_sequence (filename);
|
||||
unixtodos_filename (SDATA (filename));
|
||||
if (SBYTES (filename) >= MAX_UTF8_PATH)
|
||||
report_file_error ("filename too long", default_filename);
|
||||
if (w32_unicode_filenames)
|
||||
{
|
||||
filename_to_utf16 (SSDATA (dir), dir_w);
|
||||
if (filename_to_utf16 (SSDATA (filename), filename_buf_w) != 0)
|
||||
{
|
||||
/* filename_to_utf16 sets errno to ENOENT when the file
|
||||
name is too long or cannot be converted to UTF-16. */
|
||||
if (errno == ENOENT && filename_buf_w[MAX_PATH - 1] != 0)
|
||||
report_file_error ("filename too long", default_filename);
|
||||
}
|
||||
len = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
SSDATA (prompt), -1, NULL, 0);
|
||||
if (len > 32768)
|
||||
len = 32768;
|
||||
prompt_w = alloca (len * sizeof (wchar_t));
|
||||
MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
SSDATA (prompt), -1, prompt_w, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
filename_to_ansi (SSDATA (dir), dir_a);
|
||||
if (filename_to_ansi (SSDATA (filename), filename_buf_a) != '\0')
|
||||
{
|
||||
/* filename_to_ansi sets errno to ENOENT when the file
|
||||
name is too long or cannot be converted to UTF-16. */
|
||||
if (errno == ENOENT && filename_buf_a[MAX_PATH - 1] != 0)
|
||||
report_file_error ("filename too long", default_filename);
|
||||
}
|
||||
len = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
SSDATA (prompt), -1, NULL, 0);
|
||||
if (len > 32768)
|
||||
len = 32768;
|
||||
prompt_w = alloca (len * sizeof (wchar_t));
|
||||
MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS,
|
||||
SSDATA (prompt), -1, prompt_w, len);
|
||||
len = WideCharToMultiByte (CP_ACP, 0, prompt_w, -1, NULL, 0, NULL, NULL);
|
||||
if (len > 32768)
|
||||
len = 32768;
|
||||
prompt_a = alloca (len);
|
||||
WideCharToMultiByte (CP_ACP, 0, prompt_w, -1, prompt_a, len, NULL, NULL);
|
||||
}
|
||||
#endif /* NTGUI_UNICODE */
|
||||
|
||||
/* Fill in the structure for the call to GetOpenFileName below.
|
||||
|
@ -6470,48 +6561,88 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
|
|||
builds, we tell the OS we're using an old version of the
|
||||
structure if the OS isn't new enough to support the newer
|
||||
version. */
|
||||
memset (&new_file_details, 0, sizeof (new_file_details));
|
||||
|
||||
if (w32_major_version > 4 && w32_major_version < 95)
|
||||
file_details->lStructSize = sizeof (new_file_details);
|
||||
else
|
||||
file_details->lStructSize = sizeof (*file_details);
|
||||
|
||||
/* Set up the inout parameter for the selected file name. */
|
||||
if (SBYTES (filename) + 1 > sizeof (filename_buf))
|
||||
report_file_error ("filename too long", default_filename);
|
||||
|
||||
memcpy (filename_buf, SDATA (filename), SBYTES (filename) + 1);
|
||||
file_details->lpstrFile = filename_buf;
|
||||
file_details->nMaxFile = sizeof (filename_buf) / sizeof (*filename_buf);
|
||||
|
||||
file_details->hwndOwner = FRAME_W32_WINDOW (f);
|
||||
/* Undocumented Bug in Common File Dialog:
|
||||
If a filter is not specified, shell links are not resolved. */
|
||||
file_details->lpstrFilter = filter;
|
||||
file_details->lpstrInitialDir = (guichar_t*) SDATA (dir);
|
||||
file_details->lpstrTitle = (guichar_t*) SDATA (prompt);
|
||||
file_details->nFilterIndex = NILP (only_dir_p) ? 1 : 2;
|
||||
file_details->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
|
||||
| OFN_EXPLORER | OFN_ENABLEHOOK);
|
||||
|
||||
if (!NILP (mustmatch))
|
||||
if (use_unicode)
|
||||
{
|
||||
/* Require that the path to the parent directory exists. */
|
||||
file_details->Flags |= OFN_PATHMUSTEXIST;
|
||||
/* If we are looking for a file, require that it exists. */
|
||||
if (NILP (only_dir_p))
|
||||
file_details->Flags |= OFN_FILEMUSTEXIST;
|
||||
memset (&new_file_details_w, 0, sizeof (new_file_details_w));
|
||||
if (w32_major_version > 4 && w32_major_version < 95)
|
||||
file_details_w->lStructSize = sizeof (new_file_details_w);
|
||||
else
|
||||
file_details_w->lStructSize = sizeof (*file_details_w);
|
||||
/* Set up the inout parameter for the selected file name. */
|
||||
file_details_w->lpstrFile = filename_buf_w;
|
||||
file_details_w->nMaxFile =
|
||||
sizeof (filename_buf_w) / sizeof (*filename_buf_w);
|
||||
file_details_w->hwndOwner = FRAME_W32_WINDOW (f);
|
||||
/* Undocumented Bug in Common File Dialog:
|
||||
If a filter is not specified, shell links are not resolved. */
|
||||
file_details_w->lpstrFilter = filter_w;
|
||||
#ifdef NTGUI_UNICODE
|
||||
file_details_w->lpstrInitialDir = (wchar_t*) SDATA (dir);
|
||||
file_details_w->lpstrTitle = (guichar_t*) SDATA (prompt);
|
||||
#else
|
||||
file_details_w->lpstrInitialDir = dir_w;
|
||||
file_details_w->lpstrTitle = prompt_w;
|
||||
#endif
|
||||
file_details_w->nFilterIndex = NILP (only_dir_p) ? 1 : 2;
|
||||
file_details_w->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
|
||||
| OFN_EXPLORER | OFN_ENABLEHOOK);
|
||||
if (!NILP (mustmatch))
|
||||
{
|
||||
/* Require that the path to the parent directory exists. */
|
||||
file_details_w->Flags |= OFN_PATHMUSTEXIST;
|
||||
/* If we are looking for a file, require that it exists. */
|
||||
if (NILP (only_dir_p))
|
||||
file_details_w->Flags |= OFN_FILEMUSTEXIST;
|
||||
}
|
||||
}
|
||||
#ifndef NTGUI_UNICODE
|
||||
else
|
||||
{
|
||||
memset (&new_file_details_a, 0, sizeof (new_file_details_a));
|
||||
if (w32_major_version > 4 && w32_major_version < 95)
|
||||
file_details_a->lStructSize = sizeof (new_file_details_a);
|
||||
else
|
||||
file_details_a->lStructSize = sizeof (*file_details_a);
|
||||
file_details_a->lpstrFile = filename_buf_a;
|
||||
file_details_a->nMaxFile =
|
||||
sizeof (filename_buf_a) / sizeof (*filename_buf_a);
|
||||
file_details_a->hwndOwner = FRAME_W32_WINDOW (f);
|
||||
file_details_a->lpstrFilter = filter_a;
|
||||
file_details_a->lpstrInitialDir = dir_a;
|
||||
file_details_a->lpstrTitle = prompt_a;
|
||||
file_details_a->nFilterIndex = NILP (only_dir_p) ? 1 : 2;
|
||||
file_details_a->Flags = (OFN_HIDEREADONLY | OFN_NOCHANGEDIR
|
||||
| OFN_EXPLORER | OFN_ENABLEHOOK);
|
||||
if (!NILP (mustmatch))
|
||||
{
|
||||
/* Require that the path to the parent directory exists. */
|
||||
file_details_a->Flags |= OFN_PATHMUSTEXIST;
|
||||
/* If we are looking for a file, require that it exists. */
|
||||
if (NILP (only_dir_p))
|
||||
file_details_a->Flags |= OFN_FILEMUSTEXIST;
|
||||
}
|
||||
}
|
||||
#endif /* !NTGUI_UNICODE */
|
||||
|
||||
{
|
||||
int count = SPECPDL_INDEX ();
|
||||
/* Prevent redisplay. */
|
||||
specbind (Qinhibit_redisplay, Qt);
|
||||
block_input ();
|
||||
file_details->lpfnHook = file_dialog_callback;
|
||||
if (use_unicode)
|
||||
{
|
||||
file_details_w->lpfnHook = file_dialog_callback;
|
||||
|
||||
file_opened = GUI_FN (GetOpenFileName) (file_details);
|
||||
file_opened = GetOpenFileNameW (file_details_w);
|
||||
}
|
||||
#ifndef NTGUI_UNICODE
|
||||
else
|
||||
{
|
||||
file_details_a->lpfnHook = file_dialog_callback;
|
||||
|
||||
file_opened = GetOpenFileNameA (file_details_a);
|
||||
}
|
||||
#endif /* !NTGUI_UNICODE */
|
||||
unblock_input ();
|
||||
unbind_to (count, Qnil);
|
||||
}
|
||||
|
@ -6520,10 +6651,14 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
|
|||
{
|
||||
/* Get an Emacs string from the value Windows gave us. */
|
||||
#ifdef NTGUI_UNICODE
|
||||
filename = from_unicode_buffer (filename_buf);
|
||||
filename = from_unicode_buffer (filename_buf_w);
|
||||
#else /* !NTGUI_UNICODE */
|
||||
dostounix_filename (filename_buf, 0);
|
||||
filename = DECODE_FILE (build_string (filename_buf));
|
||||
if (use_unicode)
|
||||
filename_from_utf16 (filename_buf_w, fname_ret);
|
||||
else
|
||||
filename_from_ansi (filename_buf_a, fname_ret);
|
||||
dostounix_filename (fname_ret);
|
||||
filename = DECODE_FILE (build_unibyte_string (fname_ret));
|
||||
#endif /* NTGUI_UNICODE */
|
||||
|
||||
#ifdef CYGWIN
|
||||
|
@ -6532,10 +6667,12 @@ Otherwise, if ONLY-DIR-P is non-nil, the user can only select directories. */)
|
|||
|
||||
/* Strip the dummy filename off the end of the string if we
|
||||
added it to select a directory. */
|
||||
if (file_details->nFilterIndex == 2)
|
||||
{
|
||||
filename = Ffile_name_directory (filename);
|
||||
}
|
||||
if (use_unicode && file_details_w->nFilterIndex == 2
|
||||
#ifndef NTGUI_UNICODE
|
||||
|| !use_unicode && file_details_a->nFilterIndex == 2
|
||||
#endif
|
||||
)
|
||||
filename = Ffile_name_directory (filename);
|
||||
}
|
||||
/* User canceled the dialog without making a selection. */
|
||||
else if (!CommDlgExtendedError ())
|
||||
|
@ -6582,38 +6719,80 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
|
|||
operation = intern ("delete-directory");
|
||||
filename = Fdirectory_file_name (filename);
|
||||
}
|
||||
|
||||
/* Must have fully qualified file names for moving files to Recycle
|
||||
Bin. */
|
||||
filename = Fexpand_file_name (filename, Qnil);
|
||||
|
||||
handler = Ffind_file_name_handler (filename, operation);
|
||||
if (!NILP (handler))
|
||||
return call2 (handler, operation, filename);
|
||||
else
|
||||
{
|
||||
const char * path;
|
||||
int result;
|
||||
|
||||
encoded_file = ENCODE_FILE (filename);
|
||||
encoded_file = ENCODE_FILE (filename);
|
||||
|
||||
{
|
||||
const char * path;
|
||||
SHFILEOPSTRUCT file_op;
|
||||
char tmp_path[MAX_PATH + 1];
|
||||
path = map_w32_filename (SDATA (encoded_file), NULL);
|
||||
|
||||
path = map_w32_filename (SDATA (encoded_file), NULL);
|
||||
/* The Unicode version of SHFileOperation is not supported on
|
||||
Windows 9X. */
|
||||
if (w32_unicode_filenames && os_subtype != OS_9X)
|
||||
{
|
||||
SHFILEOPSTRUCTW file_op_w;
|
||||
/* We need one more element beyond MAX_PATH because this is
|
||||
a list of file names, with the last element double-null
|
||||
terminated. */
|
||||
wchar_t tmp_path_w[MAX_PATH + 1];
|
||||
|
||||
/* On Windows, write permission is required to delete/move files. */
|
||||
_chmod (path, 0666);
|
||||
memset (tmp_path_w, 0, sizeof (tmp_path_w));
|
||||
filename_to_utf16 (path, tmp_path_w);
|
||||
|
||||
memset (tmp_path, 0, sizeof (tmp_path));
|
||||
strcpy (tmp_path, path);
|
||||
/* On Windows, write permission is required to delete/move files. */
|
||||
_wchmod (tmp_path_w, 0666);
|
||||
|
||||
memset (&file_op, 0, sizeof (file_op));
|
||||
file_op.hwnd = HWND_DESKTOP;
|
||||
file_op.wFunc = FO_DELETE;
|
||||
file_op.pFrom = tmp_path;
|
||||
file_op.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
|
||||
| FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
|
||||
file_op.fAnyOperationsAborted = FALSE;
|
||||
memset (&file_op_w, 0, sizeof (file_op_w));
|
||||
file_op_w.hwnd = HWND_DESKTOP;
|
||||
file_op_w.wFunc = FO_DELETE;
|
||||
file_op_w.pFrom = tmp_path_w;
|
||||
file_op_w.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
|
||||
| FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
|
||||
file_op_w.fAnyOperationsAborted = FALSE;
|
||||
|
||||
if (SHFileOperation (&file_op) != 0)
|
||||
report_file_error ("Removing old name", list1 (filename));
|
||||
}
|
||||
result = SHFileOperationW (&file_op_w);
|
||||
}
|
||||
else
|
||||
{
|
||||
SHFILEOPSTRUCTA file_op_a;
|
||||
char tmp_path_a[MAX_PATH + 1];
|
||||
|
||||
memset (tmp_path_a, 0, sizeof (tmp_path_a));
|
||||
filename_to_ansi (path, tmp_path_a);
|
||||
|
||||
/* If a file cannot be represented in ANSI codepage, don't
|
||||
let them inadvertently delete other files because some
|
||||
characters are interpreted as a wildcards. */
|
||||
if (_mbspbrk (tmp_path_a, "?*"))
|
||||
result = ERROR_FILE_NOT_FOUND;
|
||||
else
|
||||
{
|
||||
_chmod (tmp_path_a, 0666);
|
||||
|
||||
memset (&file_op_a, 0, sizeof (file_op_a));
|
||||
file_op_a.hwnd = HWND_DESKTOP;
|
||||
file_op_a.wFunc = FO_DELETE;
|
||||
file_op_a.pFrom = tmp_path_a;
|
||||
file_op_a.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_ALLOWUNDO
|
||||
| FOF_NOERRORUI | FOF_NO_CONNECTED_ELEMENTS;
|
||||
file_op_a.fAnyOperationsAborted = FALSE;
|
||||
|
||||
result = SHFileOperationA (&file_op_a);
|
||||
}
|
||||
}
|
||||
if (result != 0)
|
||||
report_file_error ("Removing old name", list1 (filename));
|
||||
}
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
|
@ -6688,38 +6867,159 @@ an integer representing a ShowWindow flag:
|
|||
6 - start minimized */)
|
||||
(Lisp_Object operation, Lisp_Object document, Lisp_Object parameters, Lisp_Object show_flag)
|
||||
{
|
||||
Lisp_Object current_dir;
|
||||
char *errstr;
|
||||
Lisp_Object current_dir = BVAR (current_buffer, directory);;
|
||||
wchar_t *doc_w = NULL, *params_w = NULL, *ops_w = NULL;
|
||||
intptr_t result;
|
||||
#ifndef CYGWIN
|
||||
int use_unicode = w32_unicode_filenames;
|
||||
char *doc_a = NULL, *params_a = NULL, *ops_a = NULL;
|
||||
#endif
|
||||
|
||||
CHECK_STRING (document);
|
||||
|
||||
/* Encode filename, current directory and parameters. */
|
||||
current_dir = BVAR (current_buffer, directory);
|
||||
|
||||
#ifdef CYGWIN
|
||||
current_dir = Fcygwin_convert_file_name_to_windows (current_dir, Qt);
|
||||
if (STRINGP (document))
|
||||
document = Fcygwin_convert_file_name_to_windows (document, Qt);
|
||||
#endif /* CYGWIN */
|
||||
|
||||
/* Encode filename, current directory and parameters. */
|
||||
current_dir = GUI_ENCODE_FILE (current_dir);
|
||||
if (STRINGP (document))
|
||||
document = GUI_ENCODE_FILE (document);
|
||||
{
|
||||
document = GUI_ENCODE_FILE (document);
|
||||
doc_w = GUI_SDATA (document);
|
||||
}
|
||||
if (STRINGP (parameters))
|
||||
parameters = GUI_ENCODE_SYSTEM (parameters);
|
||||
{
|
||||
parameters = GUI_ENCODE_SYSTEM (parameters);
|
||||
params_w = GUI_SDATA (parameters);
|
||||
}
|
||||
if (STRINGP (operation))
|
||||
{
|
||||
operation = GUI_ENCODE_SYSTEM (operation);
|
||||
ops_w = GUI_SDATA (operation);
|
||||
}
|
||||
result = (intptr_t) ShellExecuteW (NULL, ops_w, doc_w, params_w,
|
||||
GUI_SDATA (current_dir),
|
||||
(INTEGERP (show_flag)
|
||||
? XINT (show_flag) : SW_SHOWDEFAULT));
|
||||
#else /* !CYGWIN */
|
||||
if (use_unicode)
|
||||
{
|
||||
wchar_t document_w[MAX_PATH], current_dir_w[MAX_PATH];
|
||||
|
||||
if ((int) GUI_FN (ShellExecute) (NULL,
|
||||
(STRINGP (operation) ?
|
||||
GUI_SDATA (operation) : NULL),
|
||||
GUI_SDATA (document),
|
||||
(STRINGP (parameters) ?
|
||||
GUI_SDATA (parameters) : NULL),
|
||||
GUI_SDATA (current_dir),
|
||||
(INTEGERP (show_flag) ?
|
||||
XINT (show_flag) : SW_SHOWDEFAULT))
|
||||
> 32)
|
||||
/* Encode filename, current directory and parameters, and
|
||||
convert operation to UTF-16. */
|
||||
current_dir = ENCODE_FILE (current_dir);
|
||||
filename_to_utf16 (SSDATA (current_dir), current_dir_w);
|
||||
if (STRINGP (document))
|
||||
{
|
||||
document = ENCODE_FILE (document);
|
||||
filename_to_utf16 (SSDATA (document), document_w);
|
||||
doc_w = document_w;
|
||||
}
|
||||
if (STRINGP (parameters))
|
||||
{
|
||||
int len;
|
||||
|
||||
parameters = ENCODE_SYSTEM (parameters);
|
||||
len = MultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
|
||||
SSDATA (parameters), -1, NULL, 0);
|
||||
if (len > 32768)
|
||||
len = 32768;
|
||||
params_w = alloca (len * sizeof (wchar_t));
|
||||
MultiByteToWideChar (CP_ACP, MB_ERR_INVALID_CHARS,
|
||||
SSDATA (parameters), -1, params_w, len);
|
||||
}
|
||||
if (STRINGP (operation))
|
||||
{
|
||||
/* Assume OPERATION is pure ASCII. */
|
||||
const char *s = SSDATA (operation);
|
||||
wchar_t *d;
|
||||
int len = SBYTES (operation) + 1;
|
||||
|
||||
if (len > 32768)
|
||||
len = 32768;
|
||||
d = ops_w = alloca (len * sizeof (wchar_t));
|
||||
while (d < ops_w + len - 1)
|
||||
*d++ = *s++;
|
||||
*d = 0;
|
||||
}
|
||||
result = (intptr_t) ShellExecuteW (NULL, ops_w, doc_w, params_w,
|
||||
current_dir_w,
|
||||
(INTEGERP (show_flag)
|
||||
? XINT (show_flag) : SW_SHOWDEFAULT));
|
||||
}
|
||||
else
|
||||
{
|
||||
char document_a[MAX_PATH], current_dir_a[MAX_PATH];
|
||||
|
||||
current_dir = ENCODE_FILE (current_dir);
|
||||
filename_to_ansi (SSDATA (current_dir), current_dir_a);
|
||||
if (STRINGP (document))
|
||||
{
|
||||
ENCODE_FILE (document);
|
||||
filename_to_ansi (SSDATA (document), document_a);
|
||||
doc_a = document_a;
|
||||
}
|
||||
if (STRINGP (parameters))
|
||||
{
|
||||
int len;
|
||||
|
||||
parameters = ENCODE_SYSTEM (parameters);
|
||||
params_a = SSDATA (parameters);
|
||||
}
|
||||
if (STRINGP (operation))
|
||||
{
|
||||
/* Assume OPERATION is pure ASCII. */
|
||||
ops_a = SSDATA (operation);
|
||||
}
|
||||
result = (intptr_t) ShellExecuteA (NULL, ops_a, doc_a, params_a,
|
||||
current_dir_a,
|
||||
(INTEGERP (show_flag)
|
||||
? XINT (show_flag) : SW_SHOWDEFAULT));
|
||||
}
|
||||
#endif /* !CYGWIN */
|
||||
|
||||
if (result > 32)
|
||||
return Qt;
|
||||
errstr = w32_strerror (0);
|
||||
|
||||
switch (result)
|
||||
{
|
||||
case SE_ERR_ACCESSDENIED:
|
||||
errstr = w32_strerror (ERROR_ACCESS_DENIED);
|
||||
break;
|
||||
case SE_ERR_ASSOCINCOMPLETE:
|
||||
case SE_ERR_NOASSOC:
|
||||
errstr = w32_strerror (ERROR_NO_ASSOCIATION);
|
||||
break;
|
||||
case SE_ERR_DDEBUSY:
|
||||
case SE_ERR_DDEFAIL:
|
||||
errstr = w32_strerror (ERROR_DDE_FAIL);
|
||||
break;
|
||||
case SE_ERR_DDETIMEOUT:
|
||||
errstr = w32_strerror (ERROR_TIMEOUT);
|
||||
break;
|
||||
case SE_ERR_DLLNOTFOUND:
|
||||
errstr = w32_strerror (ERROR_DLL_NOT_FOUND);
|
||||
break;
|
||||
case SE_ERR_FNF:
|
||||
errstr = w32_strerror (ERROR_FILE_NOT_FOUND);
|
||||
break;
|
||||
case SE_ERR_OOM:
|
||||
errstr = w32_strerror (ERROR_NOT_ENOUGH_MEMORY);
|
||||
break;
|
||||
case SE_ERR_PNF:
|
||||
errstr = w32_strerror (ERROR_PATH_NOT_FOUND);
|
||||
break;
|
||||
case SE_ERR_SHARE:
|
||||
errstr = w32_strerror (ERROR_SHARING_VIOLATION);
|
||||
break;
|
||||
default:
|
||||
errstr = w32_strerror (0);
|
||||
break;
|
||||
}
|
||||
/* The error string might be encoded in the locale's encoding. */
|
||||
if (!NILP (Vlocale_coding_system))
|
||||
{
|
||||
|
@ -7132,14 +7432,23 @@ If the underlying system call fails, value is nil. */)
|
|||
added rather late on. */
|
||||
{
|
||||
HMODULE hKernel = GetModuleHandle ("kernel32");
|
||||
BOOL (*pfn_GetDiskFreeSpaceEx)
|
||||
BOOL (*pfn_GetDiskFreeSpaceExW)
|
||||
(wchar_t *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)
|
||||
= (void *) GetProcAddress (hKernel, "GetDiskFreeSpaceExW");
|
||||
BOOL (*pfn_GetDiskFreeSpaceExA)
|
||||
(char *, PULARGE_INTEGER, PULARGE_INTEGER, PULARGE_INTEGER)
|
||||
= (void *) GetProcAddress (hKernel, "GetDiskFreeSpaceEx");
|
||||
= (void *) GetProcAddress (hKernel, "GetDiskFreeSpaceExA");
|
||||
bool have_pfn_GetDiskFreeSpaceEx =
|
||||
(w32_unicode_filenames && pfn_GetDiskFreeSpaceExW
|
||||
|| !w32_unicode_filenames && pfn_GetDiskFreeSpaceExA);
|
||||
|
||||
/* On Windows, we may need to specify the root directory of the
|
||||
volume holding FILENAME. */
|
||||
char rootname[MAX_PATH];
|
||||
char rootname[MAX_UTF8_PATH];
|
||||
wchar_t rootname_w[MAX_PATH];
|
||||
char rootname_a[MAX_PATH];
|
||||
char *name = SDATA (encoded);
|
||||
BOOL result;
|
||||
|
||||
/* find the root name of the volume if given */
|
||||
if (isalpha (name[0]) && name[1] == ':')
|
||||
|
@ -7165,7 +7474,12 @@ If the underlying system call fails, value is nil. */)
|
|||
*str = 0;
|
||||
}
|
||||
|
||||
if (pfn_GetDiskFreeSpaceEx)
|
||||
if (w32_unicode_filenames)
|
||||
filename_to_utf16 (rootname, rootname_w);
|
||||
else
|
||||
filename_to_ansi (rootname, rootname_a);
|
||||
|
||||
if (have_pfn_GetDiskFreeSpaceEx)
|
||||
{
|
||||
/* Unsigned large integers cannot be cast to double, so
|
||||
use signed ones instead. */
|
||||
|
@ -7173,10 +7487,17 @@ If the underlying system call fails, value is nil. */)
|
|||
LARGE_INTEGER freebytes;
|
||||
LARGE_INTEGER totalbytes;
|
||||
|
||||
if (pfn_GetDiskFreeSpaceEx (rootname,
|
||||
(ULARGE_INTEGER *)&availbytes,
|
||||
(ULARGE_INTEGER *)&totalbytes,
|
||||
(ULARGE_INTEGER *)&freebytes))
|
||||
if (w32_unicode_filenames)
|
||||
result = pfn_GetDiskFreeSpaceExW (rootname_w,
|
||||
(ULARGE_INTEGER *)&availbytes,
|
||||
(ULARGE_INTEGER *)&totalbytes,
|
||||
(ULARGE_INTEGER *)&freebytes);
|
||||
else
|
||||
result = pfn_GetDiskFreeSpaceExA (rootname_a,
|
||||
(ULARGE_INTEGER *)&availbytes,
|
||||
(ULARGE_INTEGER *)&totalbytes,
|
||||
(ULARGE_INTEGER *)&freebytes);
|
||||
if (result)
|
||||
value = list3 (make_float ((double) totalbytes.QuadPart),
|
||||
make_float ((double) freebytes.QuadPart),
|
||||
make_float ((double) availbytes.QuadPart));
|
||||
|
@ -7188,11 +7509,19 @@ If the underlying system call fails, value is nil. */)
|
|||
DWORD free_clusters;
|
||||
DWORD total_clusters;
|
||||
|
||||
if (GetDiskFreeSpace (rootname,
|
||||
§ors_per_cluster,
|
||||
&bytes_per_sector,
|
||||
&free_clusters,
|
||||
&total_clusters))
|
||||
if (w32_unicode_filenames)
|
||||
result = GetDiskFreeSpaceW (rootname_w,
|
||||
§ors_per_cluster,
|
||||
&bytes_per_sector,
|
||||
&free_clusters,
|
||||
&total_clusters);
|
||||
else
|
||||
result = GetDiskFreeSpaceA (rootname_a,
|
||||
§ors_per_cluster,
|
||||
&bytes_per_sector,
|
||||
&free_clusters,
|
||||
&total_clusters);
|
||||
if (result)
|
||||
value = list3 (make_float ((double) total_clusters
|
||||
* sectors_per_cluster * bytes_per_sector),
|
||||
make_float ((double) free_clusters
|
||||
|
@ -7207,6 +7536,7 @@ If the underlying system call fails, value is nil. */)
|
|||
#endif /* WINDOWSNT */
|
||||
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
|
||||
0, 0, 0, doc: /* Return the name of Windows default printer device. */)
|
||||
(void)
|
||||
|
@ -7214,8 +7544,11 @@ DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
|
|||
static char pname_buf[256];
|
||||
int err;
|
||||
HANDLE hPrn;
|
||||
PRINTER_INFO_2 *ppi2 = NULL;
|
||||
PRINTER_INFO_2W *ppi2w = NULL;
|
||||
PRINTER_INFO_2A *ppi2a = NULL;
|
||||
DWORD dwNeeded = 0, dwReturned = 0;
|
||||
char server_name[MAX_UTF8_PATH], share_name[MAX_UTF8_PATH];
|
||||
char port_name[MAX_UTF8_PATH];
|
||||
|
||||
/* Retrieve the default string from Win.ini (the registry).
|
||||
* String will be in form "printername,drivername,portname".
|
||||
|
@ -7227,55 +7560,89 @@ DEFUN ("default-printer-name", Fdefault_printer_name, Sdefault_printer_name,
|
|||
/* We want to know more than the printer name */
|
||||
if (!OpenPrinter (pname_buf, &hPrn, NULL))
|
||||
return Qnil;
|
||||
GetPrinter (hPrn, 2, NULL, 0, &dwNeeded);
|
||||
/* GetPrinterW is not supported by unicows.dll. */
|
||||
if (w32_unicode_filenames && os_subtype != OS_9X)
|
||||
GetPrinterW (hPrn, 2, NULL, 0, &dwNeeded);
|
||||
else
|
||||
GetPrinterA (hPrn, 2, NULL, 0, &dwNeeded);
|
||||
if (dwNeeded == 0)
|
||||
{
|
||||
ClosePrinter (hPrn);
|
||||
return Qnil;
|
||||
}
|
||||
/* Allocate memory for the PRINTER_INFO_2 struct */
|
||||
ppi2 = xmalloc (dwNeeded);
|
||||
if (!ppi2)
|
||||
{
|
||||
ClosePrinter (hPrn);
|
||||
return Qnil;
|
||||
}
|
||||
/* Call GetPrinter again with big enough memory block. */
|
||||
err = GetPrinter (hPrn, 2, (LPBYTE)ppi2, dwNeeded, &dwReturned);
|
||||
ClosePrinter (hPrn);
|
||||
if (!err)
|
||||
if (w32_unicode_filenames && os_subtype != OS_9X)
|
||||
{
|
||||
xfree (ppi2);
|
||||
return Qnil;
|
||||
}
|
||||
/* Allocate memory for the PRINTER_INFO_2 struct. */
|
||||
ppi2w = xmalloc (dwNeeded);
|
||||
err = GetPrinterW (hPrn, 2, (LPBYTE)ppi2w, dwNeeded, &dwReturned);
|
||||
ClosePrinter (hPrn);
|
||||
if (!err)
|
||||
{
|
||||
xfree (ppi2w);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if (ppi2)
|
||||
{
|
||||
if (ppi2->Attributes & PRINTER_ATTRIBUTE_SHARED && ppi2->pServerName)
|
||||
{
|
||||
/* a remote printer */
|
||||
if (*ppi2->pServerName == '\\')
|
||||
snprintf (pname_buf, sizeof (pname_buf), "%s\\%s", ppi2->pServerName,
|
||||
ppi2->pShareName);
|
||||
else
|
||||
snprintf (pname_buf, sizeof (pname_buf), "\\\\%s\\%s", ppi2->pServerName,
|
||||
ppi2->pShareName);
|
||||
pname_buf[sizeof (pname_buf) - 1] = '\0';
|
||||
if ((ppi2w->Attributes & PRINTER_ATTRIBUTE_SHARED)
|
||||
&& ppi2w->pServerName)
|
||||
{
|
||||
filename_from_utf16 (ppi2w->pServerName, server_name);
|
||||
filename_from_utf16 (ppi2w->pShareName, share_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* a local printer */
|
||||
strncpy (pname_buf, ppi2->pPortName, sizeof (pname_buf));
|
||||
pname_buf[sizeof (pname_buf) - 1] = '\0';
|
||||
/* `pPortName' can include several ports, delimited by ','.
|
||||
* we only use the first one. */
|
||||
strtok (pname_buf, ",");
|
||||
{
|
||||
server_name[0] = '\0';
|
||||
filename_from_utf16 (ppi2w->pPortName, port_name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ppi2a = xmalloc (dwNeeded);
|
||||
err = GetPrinterA (hPrn, 2, (LPBYTE)ppi2a, dwNeeded, &dwReturned);
|
||||
ClosePrinter (hPrn);
|
||||
if (!err)
|
||||
{
|
||||
xfree (ppi2a);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
if ((ppi2a->Attributes & PRINTER_ATTRIBUTE_SHARED)
|
||||
&& ppi2a->pServerName)
|
||||
{
|
||||
filename_from_ansi (ppi2a->pServerName, server_name);
|
||||
filename_from_ansi (ppi2a->pShareName, share_name);
|
||||
}
|
||||
else
|
||||
{
|
||||
server_name[0] = '\0';
|
||||
filename_from_ansi (ppi2a->pPortName, port_name);
|
||||
}
|
||||
xfree (ppi2);
|
||||
}
|
||||
|
||||
return build_string (pname_buf);
|
||||
if (server_name[0])
|
||||
{
|
||||
/* a remote printer */
|
||||
if (server_name[0] == '\\')
|
||||
snprintf (pname_buf, sizeof (pname_buf), "%s\\%s", server_name,
|
||||
share_name);
|
||||
else
|
||||
snprintf (pname_buf, sizeof (pname_buf), "\\\\%s\\%s", server_name,
|
||||
share_name);
|
||||
pname_buf[sizeof (pname_buf) - 1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
/* a local printer */
|
||||
strncpy (pname_buf, port_name, sizeof (pname_buf));
|
||||
pname_buf[sizeof (pname_buf) - 1] = '\0';
|
||||
/* `pPortName' can include several ports, delimited by ','.
|
||||
* we only use the first one. */
|
||||
strtok (pname_buf, ",");
|
||||
}
|
||||
|
||||
return DECODE_FILE (build_unibyte_string (pname_buf));
|
||||
}
|
||||
#endif /* WINDOWSNT */
|
||||
|
||||
|
||||
/* Equivalent of strerror for W32 error codes. */
|
||||
|
@ -7946,9 +8313,9 @@ only be necessary if the default setting causes problems. */);
|
|||
|
||||
#ifdef WINDOWSNT
|
||||
defsubr (&Sfile_system_info);
|
||||
defsubr (&Sdefault_printer_name);
|
||||
#endif
|
||||
|
||||
defsubr (&Sdefault_printer_name);
|
||||
defsubr (&Sset_message_beep);
|
||||
|
||||
hourglass_hwnd = NULL;
|
||||
|
|
|
@ -105,7 +105,7 @@ struct notification {
|
|||
OVERLAPPED *io_info; /* the OVERLAPPED structure for async I/O */
|
||||
BOOL subtree; /* whether to watch subdirectories */
|
||||
DWORD filter; /* bit mask for events to watch */
|
||||
char *watchee; /* the file we are interested in */
|
||||
char *watchee; /* the file we are interested in, UTF-8 encoded */
|
||||
HANDLE dir; /* handle to the watched directory */
|
||||
HANDLE thr; /* handle to the thread that watches */
|
||||
volatile int terminate; /* if non-zero, request for the thread to terminate */
|
||||
|
@ -332,15 +332,43 @@ add_watch (const char *parent_dir, const char *file, BOOL subdirs, DWORD flags)
|
|||
if (!file)
|
||||
return NULL;
|
||||
|
||||
hdir = CreateFile (parent_dir,
|
||||
FILE_LIST_DIRECTORY,
|
||||
/* FILE_SHARE_DELETE doesn't preclude other
|
||||
processes from deleting files inside
|
||||
parent_dir. */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
if (w32_unicode_filenames)
|
||||
{
|
||||
wchar_t dir_w[MAX_PATH], file_w[MAX_PATH];
|
||||
|
||||
filename_to_utf16 (parent_dir, dir_w);
|
||||
if (*file)
|
||||
filename_to_utf16 (file, file_w);
|
||||
else
|
||||
file_w[0] = 0;
|
||||
|
||||
hdir = CreateFileW (dir_w,
|
||||
FILE_LIST_DIRECTORY,
|
||||
/* FILE_SHARE_DELETE doesn't preclude other
|
||||
processes from deleting files inside
|
||||
parent_dir. */
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
char dir_a[MAX_PATH], file_a[MAX_PATH];
|
||||
|
||||
filename_to_ansi (parent_dir, dir_a);
|
||||
if (*file)
|
||||
filename_to_ansi (file, file_a);
|
||||
else
|
||||
file_a[0] = '\0';
|
||||
|
||||
hdir = CreateFileA (dir_a,
|
||||
FILE_LIST_DIRECTORY,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
|
||||
NULL);
|
||||
}
|
||||
if (hdir == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
|
||||
|
@ -490,9 +518,7 @@ will never come in. Volumes shared from remote Windows machines do
|
|||
generate notifications correctly, though. */)
|
||||
(Lisp_Object file, Lisp_Object filter, Lisp_Object callback)
|
||||
{
|
||||
Lisp_Object encoded_file, watch_object, watch_descriptor;
|
||||
char parent_dir[MAX_PATH], *basename;
|
||||
size_t fn_len;
|
||||
Lisp_Object dirfn, basefn, watch_object, watch_descriptor;
|
||||
DWORD flags;
|
||||
BOOL subdirs = FALSE;
|
||||
struct notification *dirwatch = NULL;
|
||||
|
@ -510,49 +536,33 @@ generate notifications correctly, though. */)
|
|||
Qnil);
|
||||
}
|
||||
|
||||
/* We need a full absolute file name of FILE, and we need to remove
|
||||
any trailing slashes from it, so that GetFullPathName below gets
|
||||
the basename part correctly. */
|
||||
file = Fdirectory_file_name (Fexpand_file_name (file, Qnil));
|
||||
encoded_file = ENCODE_FILE (file);
|
||||
|
||||
fn_len = GetFullPathName (SDATA (encoded_file), MAX_PATH, parent_dir,
|
||||
&basename);
|
||||
if (!fn_len)
|
||||
{
|
||||
errstr = w32_strerror (0);
|
||||
errno = EINVAL;
|
||||
if (!NILP (Vlocale_coding_system))
|
||||
lisp_errstr
|
||||
= code_convert_string_norecord (build_unibyte_string (errstr),
|
||||
Vlocale_coding_system, 0);
|
||||
else
|
||||
lisp_errstr = build_string (errstr);
|
||||
report_file_error ("GetFullPathName failed",
|
||||
Fcons (lisp_errstr, Fcons (file, Qnil)));
|
||||
}
|
||||
/* filenotify.el always passes us a directory, either the parent
|
||||
directory of a file to be watched, or the directory to be
|
||||
watched. */
|
||||
if (file_directory_p (parent_dir))
|
||||
basename = "";
|
||||
else
|
||||
file = Fdirectory_file_name (Fexpand_file_name (file, Qnil));
|
||||
if (NILP (Ffile_directory_p (file)))
|
||||
{
|
||||
/* This should only happen if we are called directly, not via
|
||||
filenotify.el. If BASENAME is NULL, the argument was the
|
||||
root directory on its drive. */
|
||||
if (basename)
|
||||
basename[-1] = '\0';
|
||||
else
|
||||
filenotify.el. If BASEFN is empty, the argument was the root
|
||||
directory on its drive. */
|
||||
dirfn = ENCODE_FILE (Ffile_name_directory (file));
|
||||
basefn = ENCODE_FILE (Ffile_name_nondirectory (file));
|
||||
if (*SDATA (basefn) == '\0')
|
||||
subdirs = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dirfn = ENCODE_FILE (file);
|
||||
basefn = Qnil;
|
||||
}
|
||||
|
||||
if (!NILP (Fmember (Qsubtree, filter)))
|
||||
subdirs = TRUE;
|
||||
|
||||
flags = filter_list_to_flags (filter);
|
||||
|
||||
dirwatch = add_watch (parent_dir, basename, subdirs, flags);
|
||||
dirwatch = add_watch (SSDATA (dirfn), NILP (basefn) ? "" : SSDATA (basefn),
|
||||
subdirs, flags);
|
||||
if (!dirwatch)
|
||||
{
|
||||
DWORD err = GetLastError ();
|
||||
|
|
137
src/w32proc.c
137
src/w32proc.c
|
@ -30,6 +30,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include <fcntl.h>
|
||||
#include <signal.h>
|
||||
#include <sys/file.h>
|
||||
#include <mbstring.h>
|
||||
|
||||
/* must include CRT headers *before* config.h */
|
||||
#include <config.h>
|
||||
|
@ -861,8 +862,6 @@ new_child (void)
|
|||
cp->pid = -1;
|
||||
cp->procinfo.hProcess = NULL;
|
||||
cp->status = STATUS_READ_ERROR;
|
||||
cp->input_file = NULL;
|
||||
cp->pending_deletion = 0;
|
||||
|
||||
/* use manual reset event so that select() will function properly */
|
||||
cp->char_avail = CreateEvent (NULL, TRUE, FALSE, NULL);
|
||||
|
@ -911,21 +910,6 @@ delete_child (child_process *cp)
|
|||
if (!CHILD_ACTIVE (cp) && cp->procinfo.hProcess == NULL)
|
||||
return;
|
||||
|
||||
/* Delete the child's temporary input file, if any, that is pending
|
||||
deletion. */
|
||||
if (cp->input_file)
|
||||
{
|
||||
if (cp->pending_deletion)
|
||||
{
|
||||
if (unlink (cp->input_file))
|
||||
DebPrint (("delete_child.unlink (%s) failed, errno: %d\n",
|
||||
cp->input_file, errno));
|
||||
cp->pending_deletion = 0;
|
||||
}
|
||||
xfree (cp->input_file);
|
||||
cp->input_file = NULL;
|
||||
}
|
||||
|
||||
/* reap thread if necessary */
|
||||
if (cp->thrd)
|
||||
{
|
||||
|
@ -1073,9 +1057,10 @@ reader_thread (void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* To avoid Emacs changing directory, we just record here the directory
|
||||
the new process should start in. This is set just before calling
|
||||
sys_spawnve, and is not generally valid at any other time. */
|
||||
/* To avoid Emacs changing directory, we just record here the
|
||||
directory the new process should start in. This is set just before
|
||||
calling sys_spawnve, and is not generally valid at any other time.
|
||||
Note that this directory's name is UTF-8 encoded. */
|
||||
static char * process_dir;
|
||||
|
||||
static BOOL
|
||||
|
@ -1088,7 +1073,8 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
|
|||
SECURITY_DESCRIPTOR sec_desc;
|
||||
#endif
|
||||
DWORD flags;
|
||||
char dir[ MAXPATHLEN ];
|
||||
char dir[ MAX_PATH ];
|
||||
char *p;
|
||||
|
||||
if (cp == NULL) emacs_abort ();
|
||||
|
||||
|
@ -1118,16 +1104,22 @@ create_child (char *exe, char *cmdline, char *env, int is_gui_app,
|
|||
sec_attrs.lpSecurityDescriptor = NULL /* &sec_desc */;
|
||||
sec_attrs.bInheritHandle = FALSE;
|
||||
|
||||
strcpy (dir, process_dir);
|
||||
unixtodos_filename (dir);
|
||||
filename_to_ansi (process_dir, dir);
|
||||
/* Can't use unixtodos_filename here, since that needs its file name
|
||||
argument encoded in UTF-8. OTOH, process_dir, which _is_ in
|
||||
UTF-8, points, to the directory computed by our caller, and we
|
||||
don't want to modify that, either. */
|
||||
for (p = dir; *p; p = CharNextA (p))
|
||||
if (*p == '/')
|
||||
*p = '\\';
|
||||
|
||||
flags = (!NILP (Vw32_start_process_share_console)
|
||||
? CREATE_NEW_PROCESS_GROUP
|
||||
: CREATE_NEW_CONSOLE);
|
||||
if (NILP (Vw32_start_process_inherit_error_mode))
|
||||
flags |= CREATE_DEFAULT_ERROR_MODE;
|
||||
if (!CreateProcess (exe, cmdline, &sec_attrs, NULL, TRUE,
|
||||
flags, env, dir, &start, &cp->procinfo))
|
||||
if (!CreateProcessA (exe, cmdline, &sec_attrs, NULL, TRUE,
|
||||
flags, env, dir, &start, &cp->procinfo))
|
||||
goto EH_Fail;
|
||||
|
||||
cp->pid = (int) cp->procinfo.dwProcessId;
|
||||
|
@ -1182,45 +1174,6 @@ register_child (pid_t pid, int fd)
|
|||
fd_info[fd].cp = cp;
|
||||
}
|
||||
|
||||
/* Record INFILE as an input file for process PID. */
|
||||
void
|
||||
record_infile (pid_t pid, char *infile)
|
||||
{
|
||||
child_process *cp;
|
||||
|
||||
/* INFILE should never be NULL, since xstrdup would have signaled
|
||||
memory full condition in that case, see callproc.c where this
|
||||
function is called. */
|
||||
eassert (infile);
|
||||
|
||||
cp = find_child_pid ((DWORD)pid);
|
||||
if (cp == NULL)
|
||||
{
|
||||
DebPrint (("record_infile is unable to find pid %lu\n", pid));
|
||||
return;
|
||||
}
|
||||
|
||||
cp->input_file = infile;
|
||||
}
|
||||
|
||||
/* Mark the input file INFILE of the corresponding subprocess as
|
||||
temporary, to be deleted when the subprocess exits. */
|
||||
void
|
||||
record_pending_deletion (char *infile)
|
||||
{
|
||||
child_process *cp;
|
||||
|
||||
eassert (infile);
|
||||
|
||||
for (cp = child_procs + (child_proc_count-1); cp >= child_procs; cp--)
|
||||
if (CHILD_ACTIVE (cp)
|
||||
&& cp->input_file && xstrcasecmp (cp->input_file, infile) == 0)
|
||||
{
|
||||
cp->pending_deletion = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Called from waitpid when a process exits. */
|
||||
static void
|
||||
reap_subprocess (child_process *cp)
|
||||
|
@ -1427,6 +1380,8 @@ waitpid (pid_t pid, int *status, int options)
|
|||
# define IMAGE_OPTIONAL_HEADER32 IMAGE_OPTIONAL_HEADER
|
||||
#endif
|
||||
|
||||
/* Implementation note: This function works with file names encoded in
|
||||
the current ANSI codepage. */
|
||||
static void
|
||||
w32_executable_type (char * filename,
|
||||
int * is_dos_app,
|
||||
|
@ -1617,6 +1572,7 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
|
|||
char *sepchars = " \t*?";
|
||||
/* This is for native w32 apps; modified below for Cygwin apps. */
|
||||
char escape_char = '\\';
|
||||
char cmdname_a[MAX_PATH];
|
||||
|
||||
/* We don't care about the other modes */
|
||||
if (mode != _P_NOWAIT)
|
||||
|
@ -1625,12 +1581,15 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Handle executable names without an executable suffix. */
|
||||
program = build_string (cmdname);
|
||||
if (NILP (Ffile_executable_p (program)))
|
||||
/* Handle executable names without an executable suffix. The caller
|
||||
already searched exec-path and verified the file is executable,
|
||||
but start-process doesn't do that for file names that are already
|
||||
absolute. So we double-check this here, just in case. */
|
||||
if (faccessat (AT_FDCWD, cmdname, X_OK, AT_EACCESS) != 0)
|
||||
{
|
||||
struct gcpro gcpro1;
|
||||
|
||||
program = build_string (cmdname);
|
||||
full = Qnil;
|
||||
GCPRO1 (program);
|
||||
openp (Vexec_path, program, Vexec_suffixes, &full, make_number (X_OK));
|
||||
|
@ -1640,12 +1599,27 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
|
|||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
program = full;
|
||||
program = ENCODE_FILE (full);
|
||||
cmdname = SDATA (program);
|
||||
}
|
||||
|
||||
/* make sure argv[0] and cmdname are both in DOS format */
|
||||
cmdname = SDATA (program);
|
||||
unixtodos_filename (cmdname);
|
||||
/* argv[0] was encoded by caller using ENCODE_FILE, so it is in
|
||||
UTF-8. All the other arguments are encoded by ENCODE_SYSTEM or
|
||||
some such, and are in some ANSI codepage. We need to have
|
||||
argv[0] encoded in ANSI codepage. */
|
||||
filename_to_ansi (cmdname, cmdname_a);
|
||||
/* We explicitly require that the command's file name be encodable
|
||||
in the current ANSI codepage, because we will be invoking it via
|
||||
the ANSI APIs. */
|
||||
if (_mbspbrk (cmdname_a, "?"))
|
||||
{
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
/* From here on, CMDNAME is an ANSI-encoded string. */
|
||||
cmdname = cmdname_a;
|
||||
argv[0] = cmdname;
|
||||
|
||||
/* Determine whether program is a 16-bit DOS executable, or a 32-bit Windows
|
||||
|
@ -1663,7 +1637,9 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
|
|||
while leaving the real app name as argv[0]. */
|
||||
if (is_dos_app)
|
||||
{
|
||||
cmdname = alloca (MAXPATHLEN);
|
||||
char *p;
|
||||
|
||||
cmdname = alloca (MAX_PATH);
|
||||
if (egetenv ("CMDPROXY"))
|
||||
strcpy (cmdname, egetenv ("CMDPROXY"));
|
||||
else
|
||||
|
@ -1671,7 +1647,12 @@ sys_spawnve (int mode, char *cmdname, char **argv, char **envp)
|
|||
strcpy (cmdname, SDATA (Vinvocation_directory));
|
||||
strcat (cmdname, "cmdproxy.exe");
|
||||
}
|
||||
unixtodos_filename (cmdname);
|
||||
|
||||
/* Can't use unixtodos_filename here, since that needs its file
|
||||
name argument encoded in UTF-8. */
|
||||
for (p = cmdname; *p; p = CharNextA (p))
|
||||
if (*p == '/')
|
||||
*p = '\\';
|
||||
}
|
||||
|
||||
/* we have to do some conjuring here to put argv and envp into the
|
||||
|
@ -2673,10 +2654,11 @@ All path elements in FILENAME are converted to their short names. */)
|
|||
filename = Fexpand_file_name (filename, Qnil);
|
||||
|
||||
/* luckily, this returns the short version of each element in the path. */
|
||||
if (GetShortPathName (SDATA (ENCODE_FILE (filename)), shortname, MAX_PATH) == 0)
|
||||
if (w32_get_short_filename (SDATA (ENCODE_FILE (filename)),
|
||||
shortname, MAX_PATH) == 0)
|
||||
return Qnil;
|
||||
|
||||
dostounix_filename (shortname, 0);
|
||||
dostounix_filename (shortname);
|
||||
|
||||
/* No need to DECODE_FILE, because 8.3 names are pure ASCII. */
|
||||
return build_string (shortname);
|
||||
|
@ -2690,7 +2672,7 @@ If FILENAME does not exist, return nil.
|
|||
All path elements in FILENAME are converted to their long names. */)
|
||||
(Lisp_Object filename)
|
||||
{
|
||||
char longname[ MAX_PATH ];
|
||||
char longname[ MAX_UTF8_PATH ];
|
||||
int drive_only = 0;
|
||||
|
||||
CHECK_STRING (filename);
|
||||
|
@ -2702,10 +2684,11 @@ All path elements in FILENAME are converted to their long names. */)
|
|||
/* first expand it. */
|
||||
filename = Fexpand_file_name (filename, Qnil);
|
||||
|
||||
if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname, MAX_PATH))
|
||||
if (!w32_get_long_filename (SDATA (ENCODE_FILE (filename)), longname,
|
||||
MAX_UTF8_PATH))
|
||||
return Qnil;
|
||||
|
||||
dostounix_filename (longname, 0);
|
||||
dostounix_filename (longname);
|
||||
|
||||
/* If we were passed only a drive, make sure that a slash is not appended
|
||||
for consistency with directories. Allow for drive mapping via SUBST
|
||||
|
@ -2713,7 +2696,7 @@ All path elements in FILENAME are converted to their long names. */)
|
|||
if (drive_only && longname[1] == ':' && longname[2] == '/' && !longname[3])
|
||||
longname[2] = '\0';
|
||||
|
||||
return DECODE_FILE (build_string (longname));
|
||||
return DECODE_FILE (build_unibyte_string (longname));
|
||||
}
|
||||
|
||||
DEFUN ("w32-set-process-priority", Fw32_set_process_priority,
|
||||
|
|
|
@ -52,6 +52,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
|
|||
#include "keymap.h"
|
||||
|
||||
#ifdef WINDOWSNT
|
||||
#include "w32.h" /* for filename_from_utf16, filename_from_ansi */
|
||||
#include "w32heap.h"
|
||||
#endif
|
||||
|
||||
|
@ -3128,7 +3129,14 @@ construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
|
|||
HDROP hdrop;
|
||||
POINT p;
|
||||
WORD num_files;
|
||||
guichar_t *name;
|
||||
wchar_t name_w[MAX_PATH];
|
||||
#ifdef NTGUI_UNICODE
|
||||
const int use_unicode = 1;
|
||||
#else
|
||||
int use_unicode = w32_unicode_filenames;
|
||||
char name_a[MAX_PATH];
|
||||
char file[MAX_UTF8_PATH];
|
||||
#endif
|
||||
int i, len;
|
||||
|
||||
result->kind = DRAG_N_DROP_EVENT;
|
||||
|
@ -3153,17 +3161,30 @@ construct_drag_n_drop (struct input_event *result, W32Msg *msg, struct frame *f)
|
|||
|
||||
for (i = 0; i < num_files; i++)
|
||||
{
|
||||
len = GUI_FN (DragQueryFile) (hdrop, i, NULL, 0);
|
||||
if (len <= 0)
|
||||
continue;
|
||||
|
||||
name = alloca ((len + 1) * sizeof (*name));
|
||||
GUI_FN (DragQueryFile) (hdrop, i, name, len + 1);
|
||||
if (use_unicode)
|
||||
{
|
||||
eassert (DragQueryFileW (hdrop, i, NULL, 0) < MAX_PATH);
|
||||
/* If DragQueryFile returns zero, it failed to fetch a file
|
||||
name. */
|
||||
if (DragQueryFileW (hdrop, i, name_w, MAX_PATH) == 0)
|
||||
continue;
|
||||
#ifdef NTGUI_UNICODE
|
||||
files = Fcons (from_unicode_buffer (name), files);
|
||||
files = Fcons (from_unicode_buffer (name_w), files);
|
||||
#else
|
||||
files = Fcons (DECODE_FILE (build_string (name)), files);
|
||||
filename_from_utf16 (name_w, file);
|
||||
files = Fcons (DECODE_FILE (build_unibyte_string (file)), files);
|
||||
#endif /* NTGUI_UNICODE */
|
||||
}
|
||||
#ifndef NTGUI_UNICODE
|
||||
else
|
||||
{
|
||||
eassert (DragQueryFileA (hdrop, i, NULL, 0) < MAX_PATH);
|
||||
if (DragQueryFileA (hdrop, i, name_a, MAX_PATH) == 0)
|
||||
continue;
|
||||
filename_from_ansi (name_a, file);
|
||||
files = Fcons (DECODE_FILE (build_unibyte_string (file)), files);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
DragFinish (hdrop);
|
||||
|
@ -6640,6 +6661,18 @@ X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
|
|||
With MS Windows or Nextstep, the value is t. */);
|
||||
Vx_toolkit_scroll_bars = Qt;
|
||||
|
||||
DEFVAR_BOOL ("w32-unicode-filenames",
|
||||
w32_unicode_filenames,
|
||||
doc: /* Non-nil means use Unicode APIs when passing file names to the OS.
|
||||
A value of nil means file names passed to the OS APIs and returned
|
||||
from those APIs are encoded/decoded using the ANSI codepage
|
||||
specified by `file-name-coding-system'.
|
||||
|
||||
This variable is set to non-nil by default when Emacs runs on Windows
|
||||
systems of the NT family, including W2K, XP, Vista, Windows 7 and
|
||||
Windows 8. It is set to nil on Windows 9X. */);
|
||||
w32_unicode_filenames = 0;
|
||||
|
||||
/* Tell Emacs about this window system. */
|
||||
Fprovide (Qw32, Qnil);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue