NOTE: This patch has been committed.
src/ChangeLog addition:
2005-01-27 Ben Wing <ben(a)xemacs.org>
* nt.c:
* fileio.c:
Fix sync comments.
* config.h.in:
* dired-msw.c (mswindows_get_files):
* emacs.c (main_1):
* event-msw.c (mswindows_wnd_proc):
* fileio.c:
* fileio.c (find_end_of_directory_component):
* fileio.c (Ffile_name_directory):
* fileio.c (Ffile_name_as_directory):
* fileio.c (if):
* fileio.c (Ffile_truename):
* fileio.c (Ffile_readable_p):
* fileio.c (Ffile_symlink_p):
* fileio.c (Ffile_accessible_directory_p):
* fileio.c (vars_of_fileio):
* glyphs.c:
* glyphs.c (pixmap_to_lisp_data):
* lisp.h:
* nt.c:
* nt.c (get_long_basename):
* nt.c (get_cached_volume_information):
* nt.c (mswindows_readdir):
* nt.c (open_unc_volume):
* nt.c (mswindows_access):
* nt.c (mswindows_link):
* nt.c (mswindows_rename):
* nt.c (mswindows_unlink):
* nt.c (mswindows_stat):
* nt.c (mswindows_utime):
* nt.c (open_input_file):
* nt.c (open_output_file):
* nt.c (Fmswindows_short_file_name):
* nt.c (init_nt):
* process-nt.c (nt_create_process):
* realpath.c:
* realpath.c (readlink_or_correct_case):
* realpath.c (qxe_realpath):
* sound.c (Fplay_sound_file):
* symsinit.h:
* sysdep.c:
* sysdep.c (qxe_lstat):
* sysdep.c (qxe_stat):
* sysfile.h:
* syswindows.h:
* syswindows.h (LOCAL_FILE_FORMAT_TO_TSTR):
* syswindows.h (LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR):
* win32.c:
* win32.c (Fmswindows_shell_execute):
* win32.c (struct read_link_hash):
* win32.c (mswindows_read_link_1):
* win32.c (mswindows_read_link):
* win32.c (vars_of_win32):
* win32.c (init_win32):
Add support for treating shortcuts under Windows as symbolic links.
Enabled with mswindows-shortcuts-are-links (t by default). Rewrite
lots of places to use PATHNAME_CONVERT_OUT, which is moved to
sysfile.h. Add PATHNAME_RESOLVE_LINKS, which only does things
under Windows.
Add profiling section for expand_file_name calls.
* nt.c (mswindows_rename):
* nt.c (mswindows_unlink):
* sysdep.c (sys_subshell):
Unicode-ize.
* realpath.c (readlink_or_correct_case):
Renamed from readlink_and_correct_case. Fix some problems with
Windows implementation due to incorrect understanding of workings
of the function.
* sound.c (Fplay_sound_file):
* ntplay.c (nt_play_sound_file):
* sound.c:
* sound.h:
Rename play_sound_file to nt_play_sound_file and pass
internally-formatted data to it to avoid converting out and back
again.
* text.h:
is_c -> is_ascii.
symlink source patch:
Diff command: bash -ci "cvs-diff --show-c-function -no-changelog "
Files affected: src/win32.c src/text.h src/syswindows.h src/sysfile.h src/sysdep.c src/symsinit.h src/sound.h src/sound.c src/realpath.c src/process-nt.c src/ntplay.c src/nt.c src/lisp.h src/glyphs.c src/fileio.c src/event-msw.c src/emacs.c src/dired-msw.c
cvs server: Diffing .
Index: src/dired-msw.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/dired-msw.c,v
retrieving revision 1.18
diff -u -p -r1.18 dired-msw.c
--- src/dired-msw.c 2004/12/06 03:52:03 1.18
+++ src/dired-msw.c 2005/01/28 02:31:48
@@ -192,7 +192,7 @@ mswindows_get_files (Lisp_Object dirfile
int findex;
DECLARE_EISTRING (win32pattern);
HANDLE fh;
- int errm;
+ int errm;
while (1)
{
@@ -206,8 +206,13 @@ mswindows_get_files (Lisp_Object dirfile
/* Now *bufp is the compiled form of PATTERN; don't call anything
which might compile a new regexp until we're done with the loop! */
+ {
+ Ibyte *dir2;
+ LISP_PATHNAME_RESOLVE_LINKS (dirfile, dir2);
+ eicpy_rawz (win32pattern, dir2);
+ }
+
/* for Win32, we need to insure that the pathname ends with "\*". */
- eicpy_lstr (win32pattern, dirfile);
if (!nowild)
{
Charcount len = eicharlen (win32pattern) - 1;
Index: src/emacs.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/emacs.c,v
retrieving revision 1.152
diff -u -p -r1.152 emacs.c
--- src/emacs.c 2005/01/26 10:27:57 1.152
+++ src/emacs.c 2005/01/28 02:31:49
@@ -2085,6 +2085,7 @@ main_1 (int argc, Wexttext **argv, Wextt
#if defined (HAVE_MMAP) && defined (REL_ALLOC) && !defined (DOUG_LEA_MALLOC)
vars_of_ralloc ();
#endif /* HAVE_MMAP && REL_ALLOC */
+ vars_of_realpath ();
vars_of_redisplay ();
vars_of_regex ();
#ifdef HAVE_SCROLLBARS
Index: src/event-msw.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/event-msw.c,v
retrieving revision 1.102
diff -u -p -r1.102 event-msw.c
--- src/event-msw.c 2005/01/24 23:33:52 1.102
+++ src/event-msw.c 2005/01/28 02:31:51
@@ -3712,6 +3712,7 @@ mswindows_wnd_proc (HWND hwnd, UINT mess
Extbyte *fname_ext;
Bytecount fnamelen;
Charcount len = qxeDragQueryFile ((HDROP) wParam, i, NULL, 0);
+ int freeme = 0;
/* The URLs that we make here aren't correct according to section
* 3.10 of rfc1738 because they're missing the //<host>/ part and
* because they may contain reserved characters. But that's OK -
@@ -3723,156 +3724,20 @@ mswindows_wnd_proc (HWND hwnd, UINT mess
ALLOCA, (fname, fnamelen),
Qmswindows_tstr);
+
/* May be a shell link aka "shortcut" - replace fname if so */
-#if !defined (NO_CYGWIN_COM_SUPPORT)
if (!qxestrcasecmp_ascii (fname + fnamelen - 4, ".LNK"))
{
- /* ####
-
- Note the following in the docs:
-
- Note: The IShellLink interface has an ANSI version
- (IShellLinkA) and a Unicode version (IShellLinkW). The
- version that will be used depends on whether you compile
- for ANSI or Unicode. However, Microsoft® Windows 95 and
- Microsoft® Windows 98 only support IShellLinkA.
-
- We haven't yet implemented COM support in the
- Unicode-splitting library. I don't quite understand how
- COM works yet, but it looks like what's happening is
- that the ShellLink class implements both the IShellLinkA
- and IShellLinkW interfaces. To make this work at
- run-time, we have to do something like this:
-
- -- define a new interface qxeIShellLink that uses
- Extbyte * instead of LPSTR or LPWSTR. (not totally
- necessary since Extbyte * == LPSTR).
-
- -- define a new class qxeShellLink that implements
- qxeIShellLink. the methods on this class need to create
- a shadow ShellLink object to do all the real work, and
- call the corresponding function from either the
- IShellLinkA or IShellLinkW interfaces on this object,
- depending on whether XEUNICODE_P is defined.
-
- -- with appropriate preprocessor magic, of course, we
- could make things appear transparent; but we've decided
- not to do preprocessor magic for the moment.
- */
-
- /* #### Not Unicode-split for the moment; we have to do it
- ourselves. */
- if (XEUNICODE_P)
- {
- IShellLinkW *psl;
-
- if (CoCreateInstance (
- XECOMID (CLSID_ShellLink),
- NULL,
- CLSCTX_INPROC_SERVER,
- XECOMID (IID_IShellLinkW),
- &VOIDP_CAST (psl)) == S_OK)
- {
- IPersistFile *ppf;
-
- if (XECOMCALL2 (psl, QueryInterface,
- XECOMID (IID_IPersistFile),
- &VOIDP_CAST (ppf)) == S_OK)
- {
- Extbyte *fname_unicode;
- WIN32_FIND_DATAW wfd;
- LPWSTR resolved =
- alloca_array (WCHAR, PATH_MAX_EXTERNAL + 1);
-
- TO_EXTERNAL_FORMAT (DATA, (fname, fnamelen),
- C_STRING_ALLOCA,
- fname_unicode,
- Qmswindows_unicode);
-
- if (XECOMCALL2 (ppf, Load,
- (LPWSTR) fname_unicode,
- STGM_READ) == S_OK &&
- /* #### YUCK! Docs read
-
- cchMaxPath
-
- Maximum number of bytes to copy to the buffer pointed to by the
- pszFile parameter.
-
- But "cch" means "count of characters", not bytes. I'll assume the doc
- writers messed up and the programmer was correct. Also, this approach
- is safe even if it's actually the other way around. */
-#if defined (CYGWIN_HEADERS) && W32API_INSTALLED_VER < W32API_VER(2,2)
- /* Another Cygwin prototype error,
- fixed in v2.2 of w32api */
- XECOMCALL4 (psl, GetPath, (LPSTR) resolved,
- PATH_MAX_EXTERNAL, &wfd, 0)
-#else
- XECOMCALL4 (psl, GetPath, resolved,
- PATH_MAX_EXTERNAL, &wfd, 0)
-#endif
- == S_OK)
- TO_INTERNAL_FORMAT (C_STRING, resolved,
- ALLOCA, (fname, fnamelen),
- Qmswindows_tstr);
-
- XECOMCALL0 (ppf, Release);
- }
-
- XECOMCALL0 (psl, Release);
- }
- }
- else
- {
- IShellLinkA *psl;
-
- if (CoCreateInstance (
- XECOMID (CLSID_ShellLink),
- NULL,
- CLSCTX_INPROC_SERVER,
- XECOMID (IID_IShellLinkA),
- &VOIDP_CAST (psl)) == S_OK)
- {
- IPersistFile *ppf;
-
- if (XECOMCALL2 (psl, QueryInterface,
- XECOMID (IID_IPersistFile),
- &VOIDP_CAST (ppf)) == S_OK)
- {
- Extbyte *fname_unicode;
- WIN32_FIND_DATAA wfd;
- LPSTR resolved =
- alloca_array (CHAR, PATH_MAX_EXTERNAL + 1);
-
- /* Always Unicode. Not obvious from the
- IPersistFile documentation, but look under
- "Shell Link" for example code. */
- TO_EXTERNAL_FORMAT (DATA, (fname, fnamelen),
- C_STRING_ALLOCA,
- fname_unicode,
- Qmswindows_unicode);
-
- if (XECOMCALL2 (ppf, Load,
- (LPWSTR) fname_unicode,
- STGM_READ) == S_OK
- && XECOMCALL4 (psl, GetPath, resolved,
- PATH_MAX_EXTERNAL, &wfd, 0) == S_OK)
- TO_INTERNAL_FORMAT (C_STRING, resolved,
- ALLOCA, (fname, fnamelen),
- Qmswindows_tstr);
-
- XECOMCALL0 (ppf, Release);
- }
-
- XECOMCALL0 (psl, Release);
- }
- }
+ fname = mswindows_read_link (fname);
+ freeme = 1;
}
-#endif /* !defined (NO_CYGWIN_COM_SUPPORT) */
+
{
- fname = urlify_filename (fname);
- l_item = build_intstring (fname);
- xfree (fname, Ibyte *);
+ Ibyte *fname2 = urlify_filename (fname);
+ l_item = build_intstring (fname2);
+ xfree (fname2, Ibyte *);
+ if (freeme)
+ xfree (fname, Ibyte *);
l_dndlist = Fcons (l_item, l_dndlist);
}
}
Index: src/fileio.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/fileio.c,v
retrieving revision 1.103
diff -u -p -r1.103 fileio.c
--- src/fileio.c 2005/01/24 23:33:55 1.103
+++ src/fileio.c 2005/01/28 02:31:53
@@ -23,6 +23,7 @@ Boston, MA 02111-1307, USA. */
/* More syncing: FSF Emacs 19.34.6 by Marc Paquette <marcpa(a)cam.org>
(Note: Sync messages from Marc Paquette may indicate
incomplete synching, so beware.) */
+/* Some functions synched with FSF 21.0.103. */
/* Mule-ized completely except for the #if 0-code including decrypt-string
and encrypt-string. --ben 7-2-00 */
/* #if 0-code Mule-ized, 2-22-03. --ben */
@@ -38,6 +39,7 @@ Boston, MA 02111-1307, USA. */
#include "frame.h"
#include "insdel.h"
#include "lstream.h"
+#include "profile.h"
#include "process.h"
#include "redisplay.h"
#include "sysdep.h"
@@ -129,6 +131,8 @@ Lisp_Object Qcar_less_than_car;
Lisp_Object Qcompute_buffer_file_truename;
+Lisp_Object QSin_expand_file_name;
+
EXFUN (Frunning_temacs_p, 0);
/* DATA can be anything acceptable to signal_error ().
@@ -325,6 +329,25 @@ call3_check_string (Lisp_Object fn, Lisp
}
+
+Ibyte *
+find_end_of_directory_component (const Ibyte *path, Bytecount len)
+{
+ const Ibyte *p = path + len;
+
+ while (p != path && !IS_DIRECTORY_SEP (p[-1])
+#ifdef WIN32_FILENAMES
+ /* only recognise drive specifier at the beginning */
+ && !(p[-1] == ':'
+ /* handle the "/:d:foo" and "/:foo" cases correctly */
+ && ((p == path + 2 && !IS_DIRECTORY_SEP (*path))
+ || (p == path + 4 && IS_DIRECTORY_SEP (*path))))
+#endif
+ ) p--;
+
+ return (Ibyte *) p;
+}
+
DEFUN ("file-name-directory", Ffile_name_directory, 1, 1, 0, /*
Return the directory component in file name FILENAME.
Return nil if FILENAME does not include a directory.
@@ -352,17 +375,7 @@ Given a Unix syntax file name, returns a
#endif
beg = XSTRING_DATA (filename);
/* XEmacs: no need to alloca-copy here */
- p = beg + XSTRING_LENGTH (filename);
-
- while (p != beg && !IS_DIRECTORY_SEP (p[-1])
-#ifdef WIN32_FILENAMES
- /* only recognise drive specifier at the beginning */
- && !(p[-1] == ':'
- /* handle the "/:d:foo" and "/:foo" cases correctly */
- && ((p == beg + 2 && !IS_DIRECTORY_SEP (*beg))
- || (p == beg + 4 && IS_DIRECTORY_SEP (*beg))))
-#endif
- ) p--;
+ p = find_end_of_directory_component (beg, XSTRING_LENGTH (filename));
if (p == beg)
return Qnil;
@@ -522,7 +535,11 @@ except for (file-name-as-directory \"\")
return call2_check_string (handler, Qfile_name_as_directory, filename);
buf = alloca_ibytes (XSTRING_LENGTH (filename) + 10);
- return build_intstring (file_name_as_directory (buf, XSTRING_DATA (filename)));
+ file_name_as_directory (buf, XSTRING_DATA (filename));
+ if (qxestrcmp (buf, XSTRING_DATA (filename)))
+ return build_intstring (buf);
+ else
+ return filename;
}
/*
@@ -735,7 +752,10 @@ See also the function `substitute-in-fil
int length;
Lisp_Object handler = Qnil;
struct gcpro gcpro1, gcpro2, gcpro3;
+ PROFILE_DECLARE ();
+ PROFILE_RECORD_ENTERING_SECTION (QSin_expand_file_name);
+
/* both of these get set below */
GCPRO3 (name, default_directory, handler);
@@ -745,8 +765,10 @@ See also the function `substitute-in-fil
call the corresponding file handler. */
handler = Ffind_file_name_handler (name, Qexpand_file_name);
if (!NILP (handler))
- RETURN_UNGCPRO (call3_check_string (handler, Qexpand_file_name,
- name, default_directory));
+ RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name,
+ call3_check_string
+ (handler, Qexpand_file_name,
+ name, default_directory));
/* Use the buffer's default-directory if DEFAULT_DIRECTORY is omitted. */
if (NILP (default_directory))
@@ -762,8 +784,9 @@ See also the function `substitute-in-fil
{
handler = Ffind_file_name_handler (default_directory, Qexpand_file_name);
if (!NILP (handler))
- RETURN_UNGCPRO (call3 (handler, Qexpand_file_name,
- name, default_directory));
+ RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name,
+ call3 (handler, Qexpand_file_name,
+ name, default_directory));
}
o = XSTRING_DATA (default_directory);
@@ -927,13 +950,14 @@ See also the function `substitute-in-fil
}
}
xfree (newnm, Ibyte *);
- RETURN_UNGCPRO (name);
+ RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, name);
}
#endif /* WIN32_FILENAMES */
#ifndef WIN32_NATIVE
if (nm == XSTRING_DATA (name))
- RETURN_UNGCPRO (name);
- RETURN_UNGCPRO (build_intstring (nm));
+ RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, name);
+ RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name,
+ build_intstring (nm));
#endif /* not WIN32_NATIVE */
}
}
@@ -1301,10 +1325,11 @@ See also the function `substitute-in-fil
Lisp_Object result = build_intstring (newtarget);
xfree (newtarget, Ibyte *);
- RETURN_UNGCPRO (result);
+ RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name, result);
}
#else /* not WIN32_FILENAMES */
- RETURN_UNGCPRO (make_string (target, o - target));
+ RETURN_UNGCPRO_EXIT_PROFILING (QSin_expand_file_name,
+ make_string (target, o - target));
#endif /* not WIN32_FILENAMES */
}
@@ -1360,7 +1385,7 @@ No component of the resulting pathname w
p = path;
/* Try doing it all at once. */
- if (!qxe_realpath (path, resolved_path))
+ if (!qxe_realpath (path, resolved_path, 0))
{
/* Didn't resolve it -- have to do it one component at a time. */
/* "realpath" is a typically useless, stupid un*x piece of crap.
@@ -1379,7 +1404,11 @@ No component of the resulting pathname w
resolved_name are undefined."
Since we depend on undocumented semantics of various system
- realpath()s, we just use our own version in realpath.c. */
+ realpath()s, we just use our own version in realpath.c.
+
+ Note also that our own version differs in its semantics from any
+ standard version, since it accepts and returns internal-format
+ text, not external-format. */
for (;;)
{
Ibyte *pos;
@@ -1402,7 +1431,7 @@ No component of the resulting pathname w
if (p != pos)
p = 0;
- if (qxe_realpath (path, resolved_path))
+ if (qxe_realpath (path, resolved_path, 0))
{
if (p)
*p = DIRECTORY_SEP;
@@ -2338,7 +2367,7 @@ See also `file-exists-p' and `file-attri
if (!NILP (handler))
RETURN_UNGCPRO (call2 (handler, Qfile_readable_p, abspath));
-#if defined(WIN32_FILENAMES)
+#if defined (WIN32_FILENAMES)
/* Under MS-DOS and Windows, open does not work for directories. */
UNGCPRO;
if (qxe_access (XSTRING_DATA (abspath), 0) == 0)
@@ -2443,9 +2472,42 @@ Otherwise returns nil.
val = make_string (buf, valsize);
xfree (buf, Ibyte *);
return val;
-#else /* not HAVE_READLINK */
+#elif defined (WIN32_NATIVE)
+ if (mswindows_shortcuts_are_symlinks)
+ {
+ /* We want to resolve the directory component and leave the rest
+ alone. */
+ Ibyte *path = XSTRING_DATA (filename);
+ Ibyte *dirend =
+ find_end_of_directory_component (path, XSTRING_LENGTH (filename));
+ Ibyte *fname;
+ DECLARE_EISTRING (dir);
+
+ if (dirend != path)
+ {
+ Ibyte *resdir;
+ DECLARE_EISTRING (resname);
+
+ eicpy_raw (dir, path, dirend - path);
+ PATHNAME_RESOLVE_LINKS (eidata (dir), resdir);
+ eicpy_rawz (resname, resdir);
+ eicat_rawz (resname, dirend);
+ path = eidata (resname);
+ }
+
+ fname = mswindows_read_link (path);
+ if (!fname)
+ return Qnil;
+ {
+ Lisp_Object val = build_intstring (fname);
+ xfree (fname, Ibyte *);
+ return val;
+ }
+ }
+ return Qnil;
+#else
return Qnil;
-#endif /* not HAVE_READLINK */
+#endif
}
DEFUN ("file-directory-p", Ffile_directory_p, 1, 1, 0, /*
@@ -2499,7 +2561,7 @@ searchable directory.
return call2 (handler, Qfile_accessible_directory_p,
filename);
-#if !defined(WIN32_NATIVE)
+#if !defined (WIN32_NATIVE)
if (NILP (Ffile_directory_p (filename)))
return (Qnil);
else
@@ -4300,6 +4362,10 @@ syms_of_fileio (void)
void
vars_of_fileio (void)
{
+ QSin_expand_file_name =
+ build_msg_string ("(in expand-file-name)");
+ staticpro (&QSin_expand_file_name);
+
DEFVAR_LISP ("auto-save-file-format", &Vauto_save_file_format /*
*Format in which to write auto-save files.
Should be a list of symbols naming formats that are defined in `format-alist'.
Index: src/glyphs.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/glyphs.c,v
retrieving revision 1.49
diff -u -p -r1.49 glyphs.c
--- src/glyphs.c 2005/01/24 23:33:58 1.49
+++ src/glyphs.c 2005/01/28 02:31:54
@@ -1,7 +1,7 @@
/* Generic glyph/image implementation + display tables
Copyright (C) 1994, 1995 Board of Trustees, University of Illinois.
Copyright (C) 1995 Tinker Systems
- Copyright (C) 1995, 1996, 2000, 2001, 2002 Ben Wing
+ Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004 Ben Wing
Copyright (C) 1995 Sun Microsystems
Copyright (C) 1998, 1999, 2000 Andy Piper
@@ -2917,11 +2917,13 @@ pixmap_to_lisp_data (Lisp_Object name, i
Lisp_Object
pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid)
{
- char **data;
+ Ascbyte **data;
int result;
- char *fname = 0;
+ Extbyte *fname = 0;
+ Ibyte *resolved;
- LISP_STRING_TO_EXTERNAL (name, fname, Qfile_name);
+ LISP_PATHNAME_RESOLVE_LINKS (name, resolved);
+ C_STRING_TO_EXTERNAL (resolved, fname, Qfile_name);
result = XpmReadFileToData (fname, &data);
if (result == XpmSuccess)
Index: src/lisp.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/lisp.h,v
retrieving revision 1.119
diff -u -p -r1.119 lisp.h
--- src/lisp.h 2005/01/26 10:25:05 1.119
+++ src/lisp.h 2005/01/28 02:31:56
@@ -4305,6 +4305,8 @@ DECLARE_DOESNT_RETURN (report_file_error
Lisp_Object lisp_strerror (int);
Lisp_Object expand_and_dir_to_file (Lisp_Object, Lisp_Object);
int internal_delete_file (Lisp_Object);
+Ibyte *find_end_of_directory_component (const Ibyte *path,
+ Bytecount len);
/* Defined in filelock.c */
EXFUN (Funlock_buffer, 0);
Index: src/nt.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/nt.c,v
retrieving revision 1.45
diff -u -p -r1.45 nt.c
--- src/nt.c 2004/12/06 03:52:14 1.45
+++ src/nt.c 2005/01/28 02:31:57
@@ -30,7 +30,7 @@ Software Foundation, Inc., 59 Temple Pla
incomplete synching, so beware.)
Synched (completely!) with Emacs 20.6 by Ben Wing, 6-23-00.
Largely rewritten by Ben Wing for XEmacs Mule support.
- Synched (completely!) with Emacs 21.1.103 by Ben Wing, 6-13-01.
+ Synched (completely!) with Emacs 21.0.103 by Ben Wing, 6-13-01.
*/
/* This file Mule-ized by Ben Wing, 6-23-00. */
@@ -295,7 +295,7 @@ get_long_basename (Ibyte *name)
if (qxestrpbrk (name, "*?|<>\""))
return 0;
- C_STRING_TO_TSTR (name, nameext);
+ PATHNAME_CONVERT_OUT (name, nameext);
dir_handle = qxeFindFirstFile (nameext, &find_data);
if (dir_handle != INVALID_HANDLE_VALUE)
{
@@ -663,7 +663,7 @@ get_cached_volume_information (Ibyte *ro
Ibyte drive[3] = { root_dir[0], ':' };
Extbyte *driveext;
- C_STRING_TO_TSTR (drive, driveext);
+ PATHNAME_CONVERT_OUT (drive, driveext);
if (qxeWNetGetConnection (driveext, remote_name,
sizeof (remote_name) / XETCHAR_SIZE)
== NO_ERROR)
@@ -682,7 +682,7 @@ get_cached_volume_information (Ibyte *ro
Extbyte type[256 * MAX_XETCHAR_SIZE];
Extbyte *rootdirext;
- C_STRING_TO_TSTR (root_dir, rootdirext);
+ PATHNAME_CONVERT_OUT (root_dir, rootdirext);
/* Info is not cached, or is stale. */
if (!qxeGetVolumeInformation (rootdirext,
@@ -869,16 +869,16 @@ mswindows_readdir (DIR *UNUSED (dirp))
{
DECLARE_EISTRING (filename);
Ichar lastch;
+ Extbyte *fileext;
eicpy_rawz (filename, dir_pathname);
lastch = eigetch_char (filename, eicharlen (filename) - 1);
if (!IS_DIRECTORY_SEP (lastch))
eicat_ch (filename, '\\');
eicat_ch (filename, '*');
- eito_external (filename, Qmswindows_tstr);
+ PATHNAME_CONVERT_OUT (eidata (filename), fileext);
- dir_find_handle = qxeFindFirstFile (eiextdata (filename),
- &dir_find_data);
+ dir_find_handle = qxeFindFirstFile (fileext, &dir_find_data);
if (dir_find_handle == INVALID_HANDLE_VALUE)
return NULL;
@@ -902,6 +902,33 @@ mswindows_readdir (DIR *UNUSED (dirp))
DECLARE_EISTRING (found);
Bytecount namlen;
+ if (mswindows_shortcuts_are_symlinks)
+ {
+ int len = qxestrlen (val);
+ if (len > 4 && !qxestrcasecmp_ascii (val + len - 4, ".LNK"))
+ {
+ /* If we've found a valid link, then chop off the .LNK ending */
+ DECLARE_EISTRING (linkname);
+ Ichar lastch;
+ Ibyte *resolved;
+
+ /* First check if link is valid */
+ PATHNAME_RESOLVE_LINKS (dir_pathname, resolved);
+ eicpy_rawz (linkname, resolved);
+ lastch = eigetch_char (linkname, eicharlen (linkname) - 1);
+ if (!IS_DIRECTORY_SEP (lastch))
+ eicat_ch (linkname, '\\');
+ eicat_rawz (linkname, val);
+ resolved = mswindows_read_link (eidata (linkname));
+ if (resolved)
+ {
+ xfree (resolved, Ibyte *);
+ len -= 4;
+ val[len] = '\0';
+ }
+ }
+ }
+
eicpy_rawz (found, val);
if (need_to_free)
xfree (val, Ibyte *);
@@ -930,7 +957,7 @@ open_unc_volume (const Ibyte *path)
nr.dwDisplayType = RESOURCEDISPLAYTYPE_SERVER;
nr.dwUsage = RESOURCEUSAGE_CONTAINER;
nr.lpLocalName = NULL;
- C_STRING_TO_TSTR (path, nr.lpRemoteName);
+ PATHNAME_CONVERT_OUT (path, nr.lpRemoteName);
nr.lpComment = NULL;
nr.lpProvider = NULL;
@@ -1023,7 +1050,7 @@ mswindows_access (const Ibyte *path, int
{
Extbyte *pathext;
- C_STRING_TO_TSTR (path, pathext);
+ PATHNAME_CONVERT_OUT (path, pathext);
if ((attributes = qxeGetFileAttributes (pathext)) == -1)
{
/* Should try mapping GetLastError to errno; for now just indicate
@@ -1066,7 +1093,7 @@ mswindows_link (const Ibyte *old, const
return -1;
}
- C_STRING_TO_TSTR (old, oldext);
+ PATHNAME_CONVERT_OUT (old, oldext);
fileh = qxeCreateFile (oldext, 0, 0, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (fileh != INVALID_HANDLE_VALUE)
@@ -1175,8 +1202,8 @@ mswindows_rename (const Ibyte *oldname,
seems to make the second rename work properly. */
qxesprintf (p, "_.%s.%u", o, i);
i++;
- C_STRING_TO_EXTERNAL (oldname, oldext, Qfile_name);
- C_STRING_TO_EXTERNAL (temp, tempext, Qfile_name);
+ PATHNAME_CONVERT_OUT (oldname, oldext);
+ PATHNAME_CONVERT_OUT (temp, tempext);
result = rename (oldext, tempext);
}
/* This loop must surely terminate! */
@@ -1198,15 +1225,28 @@ mswindows_rename (const Ibyte *oldname,
{
Extbyte *newext, *tempext;
- C_STRING_TO_EXTERNAL (newname, newext, Qfile_name);
- C_STRING_TO_EXTERNAL (temp, tempext, Qfile_name);
- result = rename (tempext, newext);
-
- if (result < 0
- && (errno == EEXIST || errno == EACCES)
- && _chmod (newext, 0666) == 0
- && _unlink (newext) == 0)
- result = rename (tempext, newext);
+ PATHNAME_CONVERT_OUT (newname, newext);
+ PATHNAME_CONVERT_OUT (temp, tempext);
+ if (XEUNICODE_P)
+ {
+ result = _wrename ((const wchar_t *) tempext,
+ (const wchar_t *) newext);
+ if (result < 0
+ && (errno == EEXIST || errno == EACCES)
+ && _wchmod ((const wchar_t *) newext, 0666) == 0
+ && _wunlink ((const wchar_t *) newext) == 0)
+ result = _wrename ((const wchar_t *) tempext,
+ (const wchar_t *) newext);
+ }
+ else
+ {
+ result = rename (tempext, newext);
+ if (result < 0
+ && (errno == EEXIST || errno == EACCES)
+ && _chmod (newext, 0666) == 0
+ && _unlink (newext) == 0)
+ result = rename (tempext, newext);
+ }
}
return result;
@@ -1217,10 +1257,18 @@ mswindows_unlink (const Ibyte *path)
{
Extbyte *pathout;
- C_STRING_TO_EXTERNAL (path, pathout, Qfile_name);
+ PATHNAME_CONVERT_OUT (path, pathout);
/* On Unix, unlink works without write permission. */
- _chmod (pathout, 0666);
- return _unlink (pathout);
+ if (XEUNICODE_P)
+ {
+ _wchmod ((const wchar_t *) pathout, 0666);
+ return _wunlink ((const wchar_t *) pathout);
+ }
+ else
+ {
+ _chmod (pathout, 0666);
+ return _unlink (pathout);
+ }
}
static FILETIME utc_base_ft;
@@ -1510,6 +1558,8 @@ mswindows_stat (const Ibyte *path, struc
{
if (!IS_DIRECTORY_SEP (name[len-1]))
qxestrcat (name, (Ibyte *) "\\");
+ /* File has already been resolved and we don't want to do it again
+ in case of lstat() */
C_STRING_TO_TSTR (name, nameext);
if (qxeGetDriveType (nameext) < 2)
{
@@ -1574,13 +1624,15 @@ mswindows_stat (const Ibyte *path, struc
else
{
if (!NILP (Vmswindows_get_true_file_attributes))
+ /* File has already been resolved and we don't want to do it again
+ in case of lstat() */
C_STRING_TO_TSTR (name, nameext);
if (!NILP (Vmswindows_get_true_file_attributes)
/* No access rights required to get info. */
&& (fh = qxeCreateFile (nameext, 0, 0, NULL, OPEN_EXISTING, 0, NULL))
!= INVALID_HANDLE_VALUE)
{
- /* This is more accurate in terms of gettting the correct number
+ /* This is more accurate in terms of getting the correct number
of links, but is quite slow (it is noticable when Emacs is
making a list of file name completions). */
BY_HANDLE_FILE_INFORMATION info;
@@ -1623,6 +1675,22 @@ mswindows_stat (const Ibyte *path, struc
buf->st_nlink = 1;
fake_inode = 0;
}
+
+ if (mswindows_shortcuts_are_symlinks &&
+ buf->st_mode == _S_IFREG)
+ {
+ len = qxestrlen (name);
+ if (len > 4 && !qxestrcasecmp_ascii (name + len - 4, ".LNK"))
+ {
+ /* check if link is valid */
+ Ibyte *resolved = mswindows_read_link (name);
+ if (resolved)
+ {
+ xfree (resolved, Ibyte *);
+ buf->st_mode = S_IFLNK;
+ }
+ }
+ }
}
SetErrorMode (errm);
@@ -1698,7 +1766,7 @@ mswindows_utime (Lisp_Object path, struc
times = &deftime;
}
- LISP_STRING_TO_TSTR (path, filename);
+ LISP_PATHNAME_CONVERT_OUT (path, filename);
/* APA: SetFileTime fails to set mtime correctly (always 1-Jan-1970) */
#if 0
/* Need write access to set times. */
@@ -1768,7 +1836,7 @@ open_input_file (file_data *p_file, cons
DWORD size, upper_size;
Extbyte *fileext;
- C_STRING_TO_TSTR (filename, fileext);
+ PATHNAME_CONVERT_OUT (filename, fileext);
file = qxeCreateFile (fileext, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
@@ -1804,7 +1872,7 @@ open_output_file (file_data *p_file, con
void *file_base;
Extbyte *fileext;
- C_STRING_TO_TSTR (filename, fileext);
+ PATHNAME_CONVERT_OUT (filename, fileext);
file = qxeCreateFile (fileext, GENERIC_READ | GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
@@ -2007,7 +2075,7 @@ All path elements in FILENAME are conver
/* first expand it. */
filename = Fexpand_file_name (filename, Qnil);
- LISP_STRING_TO_TSTR (filename, fileext);
+ LISP_PATHNAME_CONVERT_OUT (filename, fileext);
/* luckily, this returns the short version of each element in the path. */
if (qxeGetShortPathName (fileext, shortname,
sizeof (shortname) / XETCHAR_SIZE) == 0)
@@ -2121,7 +2189,7 @@ init_nt (void)
{
Extbyte *driveext;
- C_STRING_TO_TSTR (drive, driveext);
+ PATHNAME_CONVERT_OUT (drive, driveext);
/* Record if this drive letter refers to a fixed drive. */
fixed_drives[DRIVE_INDEX (*drive)] =
Index: src/ntplay.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/ntplay.c,v
retrieving revision 1.12
diff -u -p -r1.12 ntplay.c
--- src/ntplay.c 2004/11/04 23:06:45 1.12
+++ src/ntplay.c 2005/01/28 02:31:57
@@ -35,14 +35,12 @@ static int play_sound_data_1 (Binbyte *d
int volume, int convert);
void
-play_sound_file (Extbyte *sound_file, int UNUSED (volume))
+nt_play_sound_file (Lisp_Object path, int UNUSED (volume))
{
DWORD flags = SND_ASYNC | SND_NODEFAULT | SND_FILENAME;
- Lisp_Object fname =
- Ffile_name_nondirectory (build_tstr_string (sound_file));
+ Lisp_Object fname = Ffile_name_nondirectory (path);
Extbyte *fnameext;
- CHECK_STRING (fname);
LISP_STRING_TO_TSTR (fname, fnameext);
if (qxeSearchPath (NULL, fnameext, NULL, 0, NULL, NULL) == 0)
@@ -50,9 +48,9 @@ play_sound_file (Extbyte *sound_file, in
/* file isn't in the path so read it as data */
int size;
Binbyte *data;
- int ofd = qxe_open (XSTRING_DATA (fname), O_RDONLY | OPEN_BINARY, 0);
+ int ofd = qxe_open (XSTRING_DATA (path), O_RDONLY | OPEN_BINARY, 0);
- if (ofd <0)
+ if (ofd < 0)
return;
size = lseek (ofd, 0, SEEK_END);
Index: src/process-nt.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/process-nt.c,v
retrieving revision 1.37
diff -u -p -r1.37 process-nt.c
--- src/process-nt.c 2005/01/24 23:34:05 1.37
+++ src/process-nt.c 2005/01/28 02:31:57
@@ -764,13 +764,15 @@ nt_create_process (Lisp_Process *p,
if (mswindows_is_executable (XSTRING_DATA (program)))
{
Extbyte *progext;
- LISP_STRING_TO_TSTR (program, progext);
+ LISP_PATHNAME_CONVERT_OUT (program, progext);
image_type = qxeSHGetFileInfo (progext, 0, NULL, 0, SHGFI_EXETYPE);
}
else
{
DECLARE_EISTRING (progext);
- eicpy_lstr (progext, program);
+ Ibyte *prog2;
+ LISP_PATHNAME_RESOLVE_LINKS (program, prog2);
+ eicpy_rawz (progext, prog2);
eicat_ascii (progext, ".exe");
eito_external (progext, Qmswindows_tstr);
image_type = qxeSHGetFileInfo (eiextdata (progext), 0, NULL, 0,
@@ -858,6 +860,7 @@ nt_create_process (Lisp_Process *p,
("Bogus return value from `mswindows-construct-process-command-line'",
args_or_ret);
+ /* #### What about path names, which may be links? */
LISP_STRING_TO_TSTR (args_or_ret, command_line);
UNGCPRO; /* args_or_ret */
@@ -994,7 +997,7 @@ nt_create_process (Lisp_Process *p,
{
Extbyte *curdirext;
- LISP_STRING_TO_TSTR (cur_dir, curdirext);
+ LISP_PATHNAME_CONVERT_OUT (cur_dir, curdirext);
err = (qxeCreateProcess (NULL, command_line, NULL, NULL, TRUE,
(XEUNICODE_P ?
Index: src/realpath.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/realpath.c,v
retrieving revision 1.20
diff -u -p -r1.20 realpath.c
--- src/realpath.c 2004/12/06 03:52:17 1.20
+++ src/realpath.c 2005/01/28 02:31:58
@@ -1,7 +1,7 @@
/*
* realpath.c -- canonicalize pathname by removing symlinks
* Copyright (C) 1993 Rick Sladkey <jrs(a)world.std.com>
- * Copyright (C) 2001, 2002 Ben Wing.
+ * Copyright (C) 2001, 2002, 2004 Ben Wing.
*
This file is part of XEmacs.
@@ -31,6 +31,8 @@ Boston, MA 02111-1307, USA. */
#include <config.h>
#include "lisp.h"
+#include "profile.h"
+
#include "sysfile.h"
#include "sysdir.h"
@@ -43,6 +45,8 @@ Boston, MA 02111-1307, USA. */
#endif
#endif
+Lisp_Object QSin_qxe_realpath;
+
/* Length of start of absolute filename. */
static int
abs_start (const Ibyte *name)
@@ -59,25 +63,31 @@ abs_start (const Ibyte *name)
return IS_DIRECTORY_SEP (*name) ? 1 : 0;
#endif
}
+
+/* Find real name of a file by resolving symbolic links and/or shortcuts
+ under Windows (.LNK links), if such support is enabled.
-/* Find real name of a file by resolving symbolic links and (under Windows)
- looking up the correct case of the file as it appears on the file
- system.
+ If no link found, and LINKS_ONLY is false, look up the correct case in
+ the file system of the last component.
Under Windows, UNC servers and shares are lower-cased. Directories must
be given without trailing '/'. One day, this could read Win2K's reparse
- points. */
+ points.
+ Returns length of characters copied info BUF.
+ DOES NOT ZERO TERMINATE!!!!!
+*/
+
static int
-readlink_and_correct_case (const Ibyte *name, Ibyte *buf,
- int size)
+readlink_or_correct_case (const Ibyte *name, Ibyte *buf, Bytecount size,
+ Boolint links_only)
{
#ifndef WIN32_ANY
- return qxe_readlink (name, buf, size);
+ return qxe_readlink (name, buf, (size_t) size);
#else
# ifdef CYGWIN
Ibyte *tmp;
- int n = qxe_readlink (name, buf, size);
+ int n = qxe_readlink (name, buf, (size_t) size);
if (n >= 0 || errno != EINVAL)
return n;
@@ -87,8 +97,33 @@ readlink_and_correct_case (const Ibyte *
alloca_ibytes (cygwin_posix_to_win32_path_list_buf_size ((char *) name));
cygwin_posix_to_win32_path_list ((char *) name, (char *) tmp);
name = tmp;
+# else
+ if (mswindows_shortcuts_are_symlinks)
+ {
+ Ibyte *tmp = mswindows_read_link (name);
+
+ if (tmp != NULL)
+ {
+ /* Fucking fixed buffers. */
+ Bytecount len = qxestrlen (tmp);
+ if (len > size)
+ {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ memcpy (buf, tmp, len);
+ xfree (tmp, Ibyte *);
+ return len;
+ }
+ }
# endif
+ if (links_only)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
{
int len = 0;
int err = 0;
@@ -144,16 +179,16 @@ readlink_and_correct_case (const Ibyte *
FindClose (dir_handle);
}
- if ((len = eilen (result)) < size)
+ if ((len = eilen (result)) <= size)
{
DECLARE_EISTRING (eilastname);
eicpy_rawz (eilastname, lastname);
if (eicmp_ei (eilastname, result) == 0)
- /* Signal that the name is already OK. */
- err = EINVAL;
+ /* Signal that the name is already OK. */
+ err = EINVAL;
else
- memcpy (buf, eidata (result), len + 1);
+ memcpy (buf, eidata (result), len);
}
else
err = ENAMETOOLONG;
@@ -165,14 +200,18 @@ readlink_and_correct_case (const Ibyte *
}
/* Mule Note: This function works with and returns
- internally-formatted strings. */
+ internally-formatted strings.
+
+ if LINKS_ONLY is true, don't do case canonicalization under
+ Windows. */
Ibyte *
-qxe_realpath (const Ibyte *path, Ibyte *resolved_path)
+qxe_realpath (const Ibyte *path, Ibyte *resolved_path, Boolint links_only)
{
Ibyte copy_path[PATH_MAX_INTERNAL];
Ibyte *new_path = resolved_path;
Ibyte *max_path;
+ Ibyte *retval = NULL;
#if defined (HAVE_READLINK) || defined (WIN32_ANY)
int readlinks = 0;
Ibyte link_path[PATH_MAX_INTERNAL];
@@ -180,6 +219,10 @@ qxe_realpath (const Ibyte *path, Ibyte *
int abslen = abs_start (path);
#endif
+ PROFILE_DECLARE ();
+
+ PROFILE_RECORD_ENTERING_SECTION (QSin_qxe_realpath);
+
restart:
/* Make a copy of the source path since we may need to modify it. */
@@ -288,7 +331,7 @@ qxe_realpath (const Ibyte *path, Ibyte *
if (path > max_path)
{
errno = ENAMETOOLONG;
- return NULL;
+ goto done;
}
*new_path++ = *path++;
}
@@ -297,7 +340,8 @@ qxe_realpath (const Ibyte *path, Ibyte *
/* See if latest pathname component is a symlink or needs case
correction. */
*new_path = '\0';
- n = readlink_and_correct_case (resolved_path, link_path, PATH_MAX_INTERNAL - 1);
+ n = readlink_or_correct_case (resolved_path, link_path,
+ PATH_MAX_INTERNAL - 1, links_only);
if (n < 0)
{
@@ -308,7 +352,7 @@ qxe_realpath (const Ibyte *path, Ibyte *
#else
if (errno != EINVAL)
#endif
- return NULL;
+ goto done;
}
else
{
@@ -316,7 +360,7 @@ qxe_realpath (const Ibyte *path, Ibyte *
if (readlinks++ > MAX_READLINKS)
{
errno = ELOOP;
- return NULL;
+ goto done;
}
/* Note: readlink doesn't add the null byte. */
@@ -340,7 +384,7 @@ qxe_realpath (const Ibyte *path, Ibyte *
if (qxestrlen (path) + n >= PATH_MAX_INTERNAL)
{
errno = ENAMETOOLONG;
- return NULL;
+ goto done;
}
/* Insert symlink contents into path. */
@@ -360,5 +404,16 @@ qxe_realpath (const Ibyte *path, Ibyte *
/* Make sure it's null terminated. */
*new_path = '\0';
- return resolved_path;
+ retval = resolved_path;
+done:
+ PROFILE_RECORD_EXITING_SECTION (QSin_qxe_realpath);
+ return retval;
+}
+
+void
+vars_of_realpath (void)
+{
+ QSin_qxe_realpath =
+ build_msg_string ("(in qxe_realpath)");
+ staticpro (&QSin_qxe_realpath);
}
Index: src/sound.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/sound.c,v
retrieving revision 1.22
diff -u -p -r1.22 sound.c
--- src/sound.c 2004/11/04 23:06:53 1.22
+++ src/sound.c 2005/01/28 02:31:58
@@ -1,7 +1,7 @@
/* Sound functions.
Copyright (C) 1992, 1993, 1994 Lucid Inc.
Copyright (C) 1994, 1995 Free Software Foundation, Inc.
- Copyright (C) 2002 Ben Wing.
+ Copyright (C) 2002, 2004 Ben Wing.
This file is part of XEmacs.
@@ -161,20 +161,17 @@ Windows the sound file must be in WAV fo
#ifdef HAVE_NATIVE_SOUND
if (NILP (Vnative_sound_only_on_console) || DEVICE_ON_CONSOLE_P (d))
{
- Extbyte *fileext;
-
-#ifdef WIN32_NATIVE
- /* #### more garbage. we should be passing the internal file name
- to play_sound_file. */
- LISP_STRING_TO_EXTERNAL (file, fileext, Qmswindows_tstr);
+#ifdef WIN32_ANY
+ nt_play_sound_file (file, vol);
#else
- LISP_STRING_TO_EXTERNAL (file, fileext, Qfile_name);
-#endif
+ Extbyte *fileext;
+ LISP_PATHNAME_CONVERT_OUT (file, fileext);
/* The sound code doesn't like getting SIGIO interrupts.
Unix sucks! */
stop_interrupts ();
play_sound_file (fileext, vol);
start_interrupts ();
+#endif /* WIN32_NATIVE */
QUIT;
}
#endif /* HAVE_NATIVE_SOUND */
Index: src/sound.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/sound.h,v
retrieving revision 1.9
diff -u -p -r1.9 sound.h
--- src/sound.h 2004/11/04 23:06:53 1.9
+++ src/sound.h 2005/01/28 02:31:58
@@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */
/* Defined in *play.c */
void play_sound_file (Extbyte *name, int volume);
+void nt_play_sound_file (Lisp_Object name, int volume);
int play_sound_data (Binbyte *data, int length, int volume);
# define sound_perror(string) \
Index: src/symsinit.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/symsinit.h,v
retrieving revision 1.50
diff -u -p -r1.50 symsinit.h
--- src/symsinit.h 2004/11/04 23:06:54 1.50
+++ src/symsinit.h 2005/01/28 02:31:58
@@ -406,6 +406,7 @@ void vars_of_process_nt (void);
void vars_of_process_unix (void);
void vars_of_profile (void);
void vars_of_ralloc (void);
+void vars_of_realpath (void);
void vars_of_redisplay (void);
void vars_of_regex (void);
void vars_of_scrollbar_x (void);
Index: src/sysdep.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/sysdep.c,v
retrieving revision 1.79
diff -u -p -r1.79 sysdep.c
--- src/sysdep.c 2005/01/24 23:34:11 1.79
+++ src/sysdep.c 2005/01/28 02:31:59
@@ -628,7 +628,7 @@ sys_subshell (void)
if (sh == 0)
sh = (Ibyte *) "sh";
- C_STRING_TO_EXTERNAL (sh, shext, Qfile_name);
+ PATHNAME_CONVERT_OUT (sh, shext);
UNGCPRO;
@@ -638,7 +638,10 @@ sys_subshell (void)
qxe_chdir (str);
/* Waits for process completion */
- if (_spawnlp (_P_WAIT, shext, shext, NULL) != 0)
+ if (XEUNICODE_P ?
+ _wspawnlp (_P_WAIT, (const wchar_t *) shext,
+ (const wchar_t *) shext, NULL) != 0 :
+ _spawnlp (_P_WAIT, shext, shext, NULL) != 0)
report_process_error ("Can't spawn subshell", Qunbound);
else
return; /* we're done, no need to wait for termination */
@@ -2537,18 +2540,6 @@ strerror (int errnum)
/* Encapsulations of system calls */
/************************************************************************/
-/* The documentation in VC++ claims that the pathname library functions
- accept strings in the current locale-specific encoding, but that's
- false, because they just call the native Win32 routines directly, which
- always use the system-default encoding (which is what Qmswindows_tstr
- will give us when not XEUNICODE_P). */
-#ifdef WIN32_NATIVE
-#define PATHNAME_CONVERT_OUT(path, pathout) C_STRING_TO_TSTR (path, pathout)
-#else
-#define PATHNAME_CONVERT_OUT(path, pathout) \
- C_STRING_TO_EXTERNAL (path, pathout, Qfile_name)
-#endif
-
/***************** low-level calls ****************/
/*
@@ -3180,6 +3171,51 @@ qxe_lstat (const Ibyte *path, struct sta
In that case, use ordinary stat instead. */
#ifndef S_IFLNK
return qxe_stat (path, buf);
+#elif defined (WIN32_NATIVE)
+ if (mswindows_shortcuts_are_symlinks)
+ {
+ /* We want to resolve the directory component and leave the rest
+ alone. */
+ Ibyte *dirend = find_end_of_directory_component (path, qxestrlen (path));
+ Bytecount len;
+
+ if (dirend != path)
+ {
+ Ibyte *resdir;
+ Ichar lastch;
+ DECLARE_EISTRING (resname);
+ DECLARE_EISTRING (dir);
+
+ eicpy_raw (dir, path, dirend - path);
+ PATHNAME_RESOLVE_LINKS (eidata (dir), resdir);
+ eicpy_rawz (resname, resdir);
+ lastch = eigetch_char (resname, eicharlen (resname) - 1);
+ if (!IS_DIRECTORY_SEP (lastch))
+ eicat_ch (resname, '\\');
+ eicat_rawz (resname, dirend);
+ path = eidata (resname);
+ }
+
+ /* However, if what we are trying to stat is a link, we need to add
+ the .LNK so that the actual file is statted. */
+ len = qxestrlen (path);
+ if (len > 4 && qxestrcasecmp_ascii (path + len - 4, ".LNK"))
+ {
+ DECLARE_EISTRING (name2);
+ Ibyte *resolved;
+
+ eicpy_rawz (name2, path);
+ eicat_ascii (name2, ".LNK");
+ resolved = mswindows_read_link (eidata (name2));
+ if (resolved)
+ {
+ xfree (resolved, Ibyte *);
+ return mswindows_stat (eidata (name2), buf);
+ }
+ }
+ }
+
+ return mswindows_stat (path, buf);
#else
Extbyte *pathout;
PATHNAME_CONVERT_OUT (path, pathout);
@@ -3227,7 +3263,9 @@ int
qxe_stat (const Ibyte *path, struct stat *buf)
{
#ifdef WIN32_NATIVE
- return mswindows_stat (path, buf);
+ Ibyte *resolved;
+ PATHNAME_RESOLVE_LINKS (path, resolved);
+ return mswindows_stat (resolved, buf);
#else /* not WIN32_NATIVE */
Extbyte *pathout;
PATHNAME_CONVERT_OUT (path, pathout);
Index: src/sysfile.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/sysfile.h,v
retrieving revision 1.19
diff -u -p -r1.19 sysfile.h
--- src/sysfile.h 2004/12/06 03:52:21 1.19
+++ src/sysfile.h 2005/01/28 02:32:00
@@ -238,6 +238,13 @@ Boston, MA 02111-1307, USA. */
#undef S_ISSOCK
#endif /* STAT_MACROS_BROKEN. */
+#ifdef WIN32_NATIVE
+/* This is the standard value for S_IFLNK. All of the S_... flags that
+ exist in the MSVCRT have standard values, so their bit tests will
+ magically work. */
+#define S_IFLNK 0120000
+#endif
+
#if !defined(S_ISBLK) && defined(S_IFBLK)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#endif
@@ -376,7 +383,8 @@ int qxe_lstat (const Ibyte *path, struct
int qxe_readlink (const Ibyte *path, Ibyte *buf, size_t bufsiz);
int qxe_fstat (int fd, struct stat *buf);
int qxe_stat (const Ibyte *path, struct stat *buf);
-Ibyte *qxe_realpath (const Ibyte *path, Ibyte resolved_path []);
+Ibyte *qxe_realpath (const Ibyte *path, Ibyte resolved_path [],
+ Boolint links_only);
/* encapsulations: file-manipulation calls */
@@ -399,6 +407,10 @@ int qxe_unlink (const Ibyte *path);
on systems like SCO 3.2v5 */
void filemodestring (struct stat *, char *);
+#ifdef WIN32_ANY
+extern int mswindows_shortcuts_are_symlinks;
+#endif
+
#endif /* emacs */
@@ -506,6 +518,50 @@ DECLARE_INLINE_HEADER (int IS_ANY_SEP (I
#define IS_ANY_SEP(c) IS_DIRECTORY_SEP (c)
#endif /* WIN32_ANY */
+
+#if defined (WIN32_NATIVE)
+#define PATHNAME_RESOLVE_LINKS(path, pathout) \
+do \
+{ \
+ if (mswindows_shortcuts_are_symlinks) \
+ { \
+ Ibyte *_prl_path_ = (Ibyte *) (path); \
+ Ibyte _prl_path2_[PATH_MAX_INTERNAL]; \
+ \
+ if (!qxe_realpath (_prl_path_, _prl_path2_, 1)) \
+ (pathout) = _prl_path_; \
+ else \
+ IBYTE_STRING_TO_ALLOCA (_prl_path2_, pathout); \
+ } \
+ else (pathout) = (Ibyte *) (path); \
+} while (0)
+#else
+#define PATHNAME_RESOLVE_LINKS(path, pathout) ((pathout) = (Ibyte *) (path))
+#endif
+
+#define LISP_PATHNAME_RESOLVE_LINKS(path, pathout) \
+ PATHNAME_RESOLVE_LINKS (XSTRING_DATA (path), pathout)
+
+/* The documentation in VC++ claims that the pathname library functions
+ accept strings in the current locale-specific encoding, but that's
+ false, because they just call the native Win32 routines directly, which
+ always use the system-default encoding (which is what Qmswindows_tstr
+ will give us when not XEUNICODE_P). */
+#ifdef WIN32_NATIVE
+# define PATHNAME_CONVERT_OUT(path, pathout) \
+do \
+{ \
+ const Ibyte *_pco_path_; \
+ PATHNAME_RESOLVE_LINKS (path, _pco_path_); \
+ C_STRING_TO_TSTR (_pco_path_, pathout); \
+} while (0)
+#else
+# define PATHNAME_CONVERT_OUT(path, pathout) \
+ C_STRING_TO_EXTERNAL (path, pathout, Qfile_name)
+#endif
+
+#define LISP_PATHNAME_CONVERT_OUT(path, pathout) \
+ PATHNAME_CONVERT_OUT (XSTRING_DATA (path), pathout)
#endif /* emacs */
Index: src/syswindows.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/syswindows.h,v
retrieving revision 1.25
diff -u -p -r1.25 syswindows.h
--- src/syswindows.h 2005/01/24 23:34:11 1.25
+++ src/syswindows.h 2005/01/28 02:32:00
@@ -939,10 +939,10 @@ END_C_DECLS
#define LOCAL_FILE_FORMAT_TO_TSTR(path, out) \
do { \
- Ibyte *lttff; \
+ Ibyte *lttff; \
\
LOCAL_TO_WIN32_FILE_FORMAT (XSTRING_DATA (path), lttff); \
- C_STRING_TO_TSTR (lttff, out); \
+ PATHNAME_CONVERT_OUT (lttff, out); \
} while (0)
Lisp_Object tstr_to_local_file_format (Extbyte *pathout);
@@ -1006,40 +1006,40 @@ do { \
#ifdef CYGWIN
-#define LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR(lispstr, pathout) \
-do \
-{ \
- Ibyte *lffmutt_fname1; \
- Ibyte *lffmutt_pathint = XSTRING_DATA (lispstr); \
- \
- if ((lffmutt_fname1 = qxestrchr (lffmutt_pathint, ':')) != NULL \
- && *++lffmutt_fname1 == '/' && *++lffmutt_fname1 == '/') \
- { \
- /* If URL style file, the innards may have Cygwin mount points and \
- the like. so separate out the innards, process them, and put back \
- together. */ \
- if (qxestrncasecmp_ascii (lffmutt_pathint, "file://", 7) == 0) \
- { \
- Ibyte *lffmutt_path1, *lffmutt_path2; \
- LOCAL_TO_WIN32_FILE_FORMAT (lffmutt_pathint + 7, lffmutt_path1); \
- if (lffmutt_path1 == lffmutt_pathint + 7) /* Optimization */ \
- lffmutt_path2 = lffmutt_pathint; \
- else \
- { \
+#define LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR(lispstr, pathout) \
+do \
+{ \
+ Ibyte *lffmutt_fname1; \
+ Ibyte *lffmutt_pathint = XSTRING_DATA (lispstr); \
+ \
+ if ((lffmutt_fname1 = qxestrchr (lffmutt_pathint, ':')) != NULL \
+ && *++lffmutt_fname1 == '/' && *++lffmutt_fname1 == '/') \
+ { \
+ /* If URL style file, the innards may have Cygwin mount points and \
+ the like. so separate out the innards, process them, and put back \
+ together. */ \
+ if (qxestrncasecmp_ascii (lffmutt_pathint, "file://", 7) == 0) \
+ { \
+ Ibyte *lffmutt_path1, *lffmutt_path2; \
+ LOCAL_TO_WIN32_FILE_FORMAT (lffmutt_pathint + 7, lffmutt_path1); \
+ if (lffmutt_path1 == lffmutt_pathint + 7) /* Optimization */ \
+ lffmutt_path2 = lffmutt_pathint; \
+ else \
+ { \
lffmutt_path2 = alloca_ibytes (7 + qxestrlen (lffmutt_path1) \
- + 1); \
- qxestrncpy (lffmutt_path2, lffmutt_pathint, 7); \
- qxestrcpy (lffmutt_path2 + 7, lffmutt_path1); \
- } \
- C_STRING_TO_TSTR (lffmutt_path2, pathout); \
- } \
- else \
- /* A straight URL, just convert */ \
- LISP_STRING_TO_TSTR (lispstr, pathout); \
- } \
- else \
- /* Not URL-style, must be a straight filename. */ \
- LOCAL_FILE_FORMAT_TO_TSTR (lispstr, pathout); \
+ + 1); \
+ qxestrncpy (lffmutt_path2, lffmutt_pathint, 7); \
+ qxestrcpy (lffmutt_path2 + 7, lffmutt_path1); \
+ } \
+ C_STRING_TO_TSTR (lffmutt_path2, pathout); \
+ } \
+ else \
+ /* A straight URL, just convert */ \
+ LISP_STRING_TO_TSTR (lispstr, pathout); \
+ } \
+ else \
+ /* Not URL-style, must be a straight filename. */ \
+ LOCAL_FILE_FORMAT_TO_TSTR (lispstr, pathout); \
} while (0)
#else /* not CYGWIN */
@@ -1176,6 +1176,7 @@ DECLARE_DOESNT_RETURN (mswindows_report_
Lisp_Object data,
int errnum));
Lisp_Object mswindows_lisp_error (int errnum);
+Ibyte *mswindows_read_link (const Ibyte *fname);
/* in intl-win32.c */
extern Lisp_Object Qmswindows_tstr, Qmswindows_unicode;
Index: src/text.h
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/text.h,v
retrieving revision 1.27
diff -u -p -r1.27 text.h
--- src/text.h 2005/01/24 23:34:12 1.27
+++ src/text.h 2005/01/28 02:32:02
@@ -2391,7 +2391,7 @@ do { \
int eicmp_1 (Eistring *ei, Bytecount off, Charcount charoff,
Bytecount len, Charcount charlen, const Ibyte *data,
- const Eistring *ei2, int is_c, int fold_case);
+ const Eistring *ei2, int is_ascii, int fold_case);
#define eicmp_ei(eistr, eistr2) \
eicmp_1 (eistr, 0, -1, -1, -1, 0, eistr2, 0, 0)
Index: src/win32.c
===================================================================
RCS file: /pack/xemacscvs/XEmacs/xemacs/src/win32.c,v
retrieving revision 1.24
diff -u -p -r1.24 win32.c
--- src/win32.c 2005/01/24 23:34:13 1.24
+++ src/win32.c 2005/01/28 02:32:02
@@ -23,6 +23,8 @@ Software Foundation, Inc., 59 Temple Pla
#include "buffer.h"
#include "console-msw.h"
+#include "hash.h"
+#include "profile.h"
#include "sysfile.h"
#include "sysproc.h"
@@ -46,7 +48,10 @@ Info on Windows issues:
nil means no, t means yes. */
Lisp_Object Vmswindows_downcase_file_names;
+struct hash_table *mswindows_read_link_hash;
+
int mswindows_windows9x_p;
+Boolint mswindows_shortcuts_are_symlinks;
pfSwitchToThread_t xSwitchToThread;
@@ -341,6 +346,7 @@ otherwise it is an integer representing
if (STRINGP (operation))
LISP_STRING_TO_TSTR (operation, opext);
+ /* #### What about path names, which may be links? */
if (STRINGP (parameters))
LISP_STRING_TO_TSTR (parameters, parmext);
if (STRINGP (current_dir))
@@ -403,6 +409,228 @@ No expansion is performed, all conversio
}
#endif
+struct read_link_hash
+{
+ Ibyte *resolved;
+ DWORD ticks;
+};
+
+static Ibyte *
+mswindows_read_link_1 (const Ibyte *fname)
+{
+#ifdef NO_CYGWIN_COM_SUPPORT
+ return NULL;
+#else
+ Ibyte *retval = NULL;
+ Extbyte *fnameext;
+ HANDLE fh;
+ struct read_link_hash *rlh;
+ DWORD ticks;
+
+ /* The call below to resolve a link is rather time-consuming.
+ I tried implementing a simple cache based on creation and write time
+ of the file, but that didn't help enough -- maybe 30% faster but still
+ a lot of time spent here. So just do something cheesy and don't
+ check again if we've recently (< a second) done so. */
+
+ if (!mswindows_read_link_hash)
+ mswindows_read_link_hash = make_string_hash_table (1000);
+ C_STRING_TO_TSTR (fname, fnameext);
+
+ /* See if we can find a cached value. */
+
+ /* The intermediate cast fools gcc into not outputting strict-aliasing
+ complaints */
+ ticks = GetTickCount ();
+ if (!gethash (fname, mswindows_read_link_hash,
+ (const void **) (void *) &rlh))
+ {
+ rlh = xnew_and_zero (struct read_link_hash);
+ puthash (qxestrdup (fname), rlh, mswindows_read_link_hash);
+ }
+ else if (ticks - rlh->ticks < 1000)
+ {
+ return rlh->resolved ? qxestrdup (rlh->resolved) : NULL;
+ }
+
+ rlh->ticks = ticks;
+
+ /* Retrieve creation/write time of link file. */
+
+ /* No access rights required to get info. */
+ if ((fh = qxeCreateFile (fnameext, 0, 0, NULL, OPEN_EXISTING, 0, NULL))
+ == INVALID_HANDLE_VALUE)
+ {
+ CloseHandle (fh);
+ return NULL;
+ }
+
+ CloseHandle (fh);
+
+ /* ####
+
+ Note the following in the docs:
+
+ Note: The IShellLink interface has an ANSI version
+ (IShellLinkA) and a Unicode version (IShellLinkW). The
+ version that will be used depends on whether you compile
+ for ANSI or Unicode. However, Microsoft® Windows 95 and
+ Microsoft® Windows 98 only support IShellLinkA.
+
+ We haven't yet implemented COM support in the
+ Unicode-splitting library. I don't quite understand how
+ COM works yet, but it looks like what's happening is
+ that the ShellLink class implements both the IShellLinkA
+ and IShellLinkW interfaces. To make this work at
+ run-time, we have to do something like this:
+
+ -- define a new interface qxeIShellLink that uses
+ Extbyte * instead of LPSTR or LPWSTR. (not totally
+ necessary since Extbyte * == LPSTR).
+
+ -- define a new class qxeShellLink that implements
+ qxeIShellLink. the methods on this class need to create
+ a shadow ShellLink object to do all the real work, and
+ call the corresponding function from either the
+ IShellLinkA or IShellLinkW interfaces on this object,
+ depending on whether XEUNICODE_P is defined.
+
+ -- with appropriate preprocessor magic, of course, we
+ could make things appear transparent; but we've decided
+ not to do preprocessor magic for the moment.
+ */
+
+ /* #### Not Unicode-split for the moment; we have to do it
+ ourselves. */
+ if (XEUNICODE_P)
+ {
+ IShellLinkW *psl;
+
+ if (CoCreateInstance (
+ XECOMID (CLSID_ShellLink),
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ XECOMID (IID_IShellLinkW),
+ &VOIDP_CAST (psl)) == S_OK)
+ {
+ IPersistFile *ppf;
+
+ if (XECOMCALL2 (psl, QueryInterface,
+ XECOMID (IID_IPersistFile),
+ &VOIDP_CAST (ppf)) == S_OK)
+ {
+ Extbyte *fname_unicode;
+ WIN32_FIND_DATAW wfd;
+ LPWSTR resolved = alloca_array (WCHAR, PATH_MAX_EXTERNAL + 1);
+
+ /* Always Unicode. Not obvious from the
+ IPersistFile documentation, but look under
+ "Shell Link" for example code. */
+ fname_unicode = fnameext;
+
+ if (XECOMCALL2 (ppf, Load,
+ (LPWSTR) fname_unicode,
+ STGM_READ) == S_OK &&
+ /* #### YUCK! Docs read
+
+ cchMaxPath
+
+ Maximum number of bytes to copy to the buffer pointed
+ to by the pszFile parameter.
+
+ But "cch" means "count of characters", not bytes.
+ I'll assume the doc writers messed up and the
+ programmer was correct. Also, this approach is safe
+ even if it's actually the other way around. */
+#if defined (CYGWIN_HEADERS) && W32API_INSTALLED_VER < W32API_VER(2,2)
+ /* Another Cygwin prototype error,
+ fixed in v2.2 of w32api */
+ XECOMCALL4 (psl, GetPath, (LPSTR) resolved,
+ PATH_MAX_EXTERNAL, &wfd, 0)
+#else
+ XECOMCALL4 (psl, GetPath, resolved,
+ PATH_MAX_EXTERNAL, &wfd, 0)
+#endif
+ == S_OK)
+ TSTR_TO_C_STRING_MALLOC (resolved, retval);
+
+ XECOMCALL0 (ppf, Release);
+ }
+
+ XECOMCALL0 (psl, Release);
+ }
+ }
+ else
+ {
+ IShellLinkA *psl;
+
+ if (CoCreateInstance (
+ XECOMID (CLSID_ShellLink),
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ XECOMID (IID_IShellLinkA),
+ &VOIDP_CAST (psl)) == S_OK)
+ {
+ IPersistFile *ppf;
+
+ if (XECOMCALL2 (psl, QueryInterface,
+ XECOMID (IID_IPersistFile),
+ &VOIDP_CAST (ppf)) == S_OK)
+ {
+ Extbyte *fname_unicode;
+ WIN32_FIND_DATAA wfd;
+ LPSTR resolved = alloca_array (CHAR, PATH_MAX_EXTERNAL + 1);
+
+ /* Always Unicode. Not obvious from the
+ IPersistFile documentation, but look under
+ "Shell Link" for example code. */
+ C_STRING_TO_EXTERNAL (fname, fname_unicode,
+ Qmswindows_unicode);
+
+ if (XECOMCALL2 (ppf, Load,
+ (LPWSTR) fname_unicode,
+ STGM_READ) == S_OK
+ && XECOMCALL4 (psl, GetPath, resolved,
+ PATH_MAX_EXTERNAL, &wfd, 0) == S_OK)
+ TSTR_TO_C_STRING_MALLOC (resolved, retval);
+
+ XECOMCALL0 (ppf, Release);
+ }
+
+ XECOMCALL0 (psl, Release);
+ }
+ }
+
+ /* Cache newly found value */
+ if (rlh->resolved)
+ xfree (rlh->resolved, Ibyte *);
+ rlh->resolved = retval ? qxestrdup (retval) : NULL;
+
+ return retval;
+#endif /* NO_CYGWIN_COM_SUPPORT */
+}
+
+/* Resolve a file that may be a shortcut. Accepts either a file ending
+ with .LNK or without the ending. If a shortcut is found, returns
+ a value that you must xfree(); otherwise NULL. */
+
+Ibyte *
+mswindows_read_link (const Ibyte *fname)
+{
+ int len = qxestrlen (fname);
+ if (len > 4 && !qxestrcasecmp_ascii (fname + len - 4, ".LNK"))
+ return mswindows_read_link_1 (fname);
+ else
+ {
+ DECLARE_EISTRING (name2);
+
+ eicpy_rawz (name2, fname);
+ eicat_ascii (name2, ".LNK");
+ return mswindows_read_link_1 (eidata (name2));
+ }
+}
+
+
#if defined (WIN32_NATIVE) || defined (CYGWIN_BROKEN_SIGNALS)
/* setitimer() does not exist on native MS Windows, and appears broken
@@ -414,7 +642,6 @@ No expansion is performed, all conversio
mechanism for SIGCHLD. Yuck.)
*/
-
/*--------------------------------------------------------------------*/
/* Signal support */
/*--------------------------------------------------------------------*/
@@ -664,11 +891,20 @@ syms_of_win32 (void)
void
vars_of_win32 (void)
{
- DEFVAR_LISP ("mswindows-downcase-file-names", &Vmswindows_downcase_file_names /*
+ DEFVAR_LISP ("mswindows-downcase-file-names",
+ &Vmswindows_downcase_file_names /*
Non-nil means convert all-upper case file names to lower case.
This applies when performing completions and file name expansion.
*/ );
Vmswindows_downcase_file_names = Qnil;
+
+ DEFVAR_BOOL ("mswindows-shortcuts-are-symlinks",
+ &mswindows_shortcuts_are_symlinks /*
+Non-nil means shortcuts (.LNK files) are treated as symbolic links.
+This works also for symlinks created under Cygwin, because they use .LNK
+files to implement symbolic links.
+*/ );
+ mswindows_shortcuts_are_symlinks = 1;
}
void
cvs server: Diffing src/m
cvs server: Diffing src/s
cvs server: Diffing tests
cvs server: Diffing tests/DLL
cvs server: Diffing tests/Dnd
cvs server: Diffing tests/automated
cvs server: Diffing tests/gtk
cvs server: Diffing tests/mule
cvs server: Diffing tests/tooltalk