diff src/syswindows.h @ 4834:b3ea9c582280

Use new cygwin_conv_path API with Cygwin 1.7 for converting names between Win32 and POSIX, UTF-8-aware, with attendant changes elsewhere
author Ben Wing <ben@xemacs.org>
date Tue, 12 Jan 2010 01:38:04 -0600
parents 11daf37dae4d
children 95c4ced5c07c
line wrap: on
line diff
--- a/src/syswindows.h	Sun Jan 10 01:06:15 2010 -0600
+++ b/src/syswindows.h	Tue Jan 12 01:38:04 2010 -0600
@@ -1,5 +1,5 @@
 /* Copyright (C) 2000 Free Software Foundation, Inc.
-   Copyright (C) 2000, 2001, 2002, 2004 Ben Wing.
+   Copyright (C) 2000, 2001, 2002, 2004, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -137,6 +137,7 @@
 
 #include <cygwin/stat.h> /* for struct stat */
 #include <w32api.h> /* for version info */
+#include <sys/cygwin.h> /* path conversion functions */
 
 /* Test for a specific version of w32api */
 #define W32API_VER(major,minor) (((major) << 16) + (minor))
@@ -931,28 +932,68 @@
 
 #ifdef CYGWIN
 
-BEGIN_C_DECLS
+/* We should just remove the Windows 9x support */
 
-void cygwin_win32_to_posix_path_list (const char *, char *);
-int cygwin_win32_to_posix_path_list_buf_size (const char *);
-void cygwin_posix_to_win32_path_list (const char *, char *);
-int cygwin_posix_to_win32_path_list_buf_size (const char *);
-extern int cygwin_conv_to_full_win32_path (const char *, char *);
-
-END_C_DECLS
+#define CCP_POSIX_TO_WIN_T \
+  (XEUNICODE_P ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A)
+#define CCP_WIN_T_TO_POSIX \
+  (XEUNICODE_P ? CCP_WIN_W_TO_POSIX : CCP_WIN_A_TO_POSIX)
 
 #endif
 
-#define LOCAL_FILE_FORMAT_TO_TSTR(path, out)			\
-do {								\
-  Ibyte *lttff;							\
-								\
-  LOCAL_TO_WIN32_FILE_FORMAT (XSTRING_DATA (path), lttff);	\
-  PATHNAME_CONVERT_OUT (lttff, out);				\
+#ifdef HAVE_CYGWIN_CONV_PATH
+#define LOCAL_FILE_FORMAT_TO_TSTR(path, out)				\
+do {									\
+  const Ibyte *lfftt = (path);						\
+  if (isalpha (lfftt[0]) && (IS_DEVICE_SEP (lfftt[1])))			\
+    PATHNAME_CONVERT_OUT_TSTR (lfftt, out);				\
+  else									\
+    {									\
+      int lfftt_size;							\
+      Extbyte *lfftt_utf8_path;						\
+      Extbyte *lfftt_tstr_path;						\
+									\
+      PATHNAME_CONVERT_OUT_UTF_8 (lfftt, lfftt_utf8_path);		\
+      lfftt_size = cygwin_conv_path (CCP_POSIX_TO_WIN_T | CCP_RELATIVE,	\
+				     lfftt_utf8_path, NULL, 0);		\
+      lfftt_tstr_path = alloca_extbytes (lfftt_size);			\
+      cygwin_conv_path (CCP_POSIX_TO_WIN_T | CCP_RELATIVE,		\
+			lfftt_utf8_path, lfftt_tstr_path, lfftt_size);	\
+      * (Extbyte **) &(out) = lfftt_tstr_path;				\
+    }									\
 } while (0)
+#define TSTR_TO_LOCAL_FILE_FORMAT(path, out)				\
+do {									\
+  const Extbyte *ttlff = (path);					\
+  int ttlff_size;							\
+  Extbyte *ttlff_utf8_path;						\
+									\
+  ttlff_size = cygwin_conv_path (CCP_WIN_T_TO_POSIX | CCP_RELATIVE,	\
+				 ttlff, NULL, 0);			\
+  ttlff_utf8_path = alloca_extbytes (ttlff_size);			\
+  cygwin_conv_path (CCP_WIN_T_TO_POSIX | CCP_RELATIVE,			\
+		    ttlff, ttlff_utf8_path, ttlff_size);		\
+  EXTERNAL_TO_C_STRING (ttlff_utf8_path, out, Qutf_8);			\
+} while (0)
+#else /* not HAVE_CYGWIN_CONV_PATH */
+#define LOCAL_FILE_FORMAT_TO_TSTR(path, out)		\
+do {							\
+  Ibyte *lfftt;						\
+							\
+  LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN (path, lfftt);	\
+  PATHNAME_CONVERT_OUT_TSTR (lfftt, out);		\
+} while (0)
+#define TSTR_TO_LOCAL_FILE_FORMAT(path, out)		\
+do {							\
+  Ibyte *ttlff;						\
+							\
+  TSTR_TO_C_STRING (path, ttlff);			\
+  INTERNAL_MSWIN_TO_LOCAL_FILE_FORMAT (ttlff, out);	\
+} while (0)
+#endif /* (not) HAVE_CYGWIN_CONV_PATH */
 
-Lisp_Object tstr_to_local_file_format (Extbyte *pathout);
-
+#define LISP_LOCAL_FILE_FORMAT_TO_TSTR(path, out) \
+  LOCAL_FILE_FORMAT_TO_TSTR (XSTRING_DATA (path), out)
 /* Convert from local file format, as used in XEmacs, to valid win32
    filenames as can be given to Windows API routines.  Under native XEmacs,
    this is a no-op, but under Cygwin, the local names look different --
@@ -962,36 +1003,50 @@
    check, look for letter plus colon at beginning of name) and do nothing
    in that case. */
 
-#ifdef CYGWIN
-#define LOCAL_TO_WIN32_FILE_FORMAT(path, pathout)			   \
-do {									   \
-  /* NOTE: It is a bit evil that here and below we are passing		   \
-     internal-format data to a function that (nominally) should work	   \
-     with external-format data.  But in point of fact, the Cygwin	   \
-     conversion functions are *NOT* localized, and will fail if they	   \
-     get 7-bit ISO2022-encoded data.  We know that our internal format	   \
-     is ASCII-compatible, and so these functions will work fine with	   \
-     this data. */							   \
-  Ibyte *ltwffp = (path);						   \
-  if (isalpha (ltwffp[0]) && (IS_DEVICE_SEP (ltwffp[1])))		   \
-    pathout = ltwffp;							   \
-  else									   \
-    {									   \
-      int ltwff2 =							   \
-        cygwin_posix_to_win32_path_list_buf_size ((char *) ltwffp);	   \
-      pathout = alloca_ibytes (ltwff2);				   \
-      cygwin_posix_to_win32_path_list ((char *) ltwffp, (char *) pathout); \
-    }									   \
+#ifdef HAVE_CYGWIN_CONV_PATH
+/* When Cygwin uses UTF-8, we can't just manipulate internal-format data
+   with its routines because it will mangle the high bytes, so we need to
+   convert to UTF-8 first, then to Win32 TSTR format (i.e. UTF-16, on
+   Windows NT), then back to internal format.  Routines that want external
+   format should avoid this by using LISP_LOCAL_FILE_FORMAT_TO_TSTR().
+   Same thing applies going the other direction. */
+#define LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN(path, pathout)	\
+do								\
+  {								\
+    Extbyte *lfftiwp;						\
+								\
+    LOCAL_FILE_FORMAT_TO_TSTR (path, lfftiwp);			\
+    TSTR_TO_C_STRING (lfftiwp, pathout);			\
+  }								\
+while (0)
+#define INTERNAL_MSWIN_TO_LOCAL_FILE_FORMAT(path, pathout)	\
+do {								\
+  Extbyte *iwtlffp;						\
+  C_STRING_TO_TSTR (path, iwtlffp);				\
+  TSTR_TO_LOCAL_FILE_FORMAT (iwtlffp, pathout);			\
 } while (0)
-#else
-#define LOCAL_TO_WIN32_FILE_FORMAT(path, pathout)	\
-do {							\
-  (pathout) = (path);					\
+#elif defined (CYGWIN)
+#define LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN(path, pathout)		\
+do {									\
+  /* NOTE: It is a bit evil that here and below we are passing		\
+     internal-format data to a function that (nominally) should work	\
+     with external-format data.  But in point of fact, the Cygwin	\
+     conversion functions are *NOT* localized, and will fail if they	\
+     get 7-bit ISO2022-encoded data.  We know that our internal format	\
+     is ASCII-compatible, and so these functions will work fine with	\
+     this data. */							\
+  Ibyte *lfftiwp = (path);						\
+  if (isalpha (lfftiwp[0]) && (IS_DEVICE_SEP (lfftiwp[1])))		\
+    pathout = lfftiwp;							\
+  else									\
+    {									\
+      int lfftiw2 =							\
+        cygwin_posix_to_win32_path_list_buf_size ((char *) lfftiwp);	\
+      pathout = alloca_ibytes (lfftiw2);				\
+      cygwin_posix_to_win32_path_list ((char *) lfftiwp, (char *) pathout); \
+    }									\
 } while (0)
-#endif
-
-#ifdef CYGWIN
-#define WIN32_TO_LOCAL_FILE_FORMAT(path, pathout)			\
+#define INTERNAL_MSWIN_TO_LOCAL_FILE_FORMAT(path, pathout)		\
 do {									\
   Ibyte *wtlff1 = (path);						\
   int wtlff2 =								\
@@ -1000,19 +1055,25 @@
   cygwin_win32_to_posix_path_list ((char *) wtlff1, (char *) wtlff3);	\
   (pathout) = wtlff3;							\
 } while (0)
-#else
-#define WIN32_TO_LOCAL_FILE_FORMAT(path, pathout)	\
-do {							\
-  (pathout) = (path);					\
+#else /* not defined (CYGWIN) */
+#define LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN(path, pathout)	\
+do {								\
+  (pathout) = (path);						\
 } while (0)
-#endif
+#define INTERNAL_MSWIN_TO_LOCAL_FILE_FORMAT(path, pathout)	\
+do {								\
+  (pathout) = (path);						\
+} while (0)
+#endif /* (not) defined (CYGWIN) */
+
+Lisp_Object tstr_to_local_file_format (Extbyte *pathout);
 
 /* Convert a local-format file name or URL in internal format into a Win32
    file name or URL in tstr format. */
 
 #ifdef CYGWIN
 
-#define LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR(lispstr, pathout)		\
+#define LISP_LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR(lispstr, pathout)	\
 do									\
 {									\
   Ibyte *lffmutt_fname1;						\
@@ -1027,7 +1088,8 @@
       if (qxestrncasecmp_ascii (lffmutt_pathint, "file://", 7) == 0)	\
 	{								\
 	  Ibyte *lffmutt_path1, *lffmutt_path2;				\
-	  LOCAL_TO_WIN32_FILE_FORMAT (lffmutt_pathint + 7, lffmutt_path1); \
+	  LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN (lffmutt_pathint + 7,	\
+                                               lffmutt_path1);		\
 	  if (lffmutt_path1 == lffmutt_pathint + 7) /* Optimization */	\
 	    lffmutt_path2 = lffmutt_pathint;				\
 	  else								\
@@ -1045,14 +1107,14 @@
     }									\
   else									\
     /* Not URL-style, must be a straight filename. */			\
-    LOCAL_FILE_FORMAT_TO_TSTR (lispstr, pathout);			\
+    LISP_LOCAL_FILE_FORMAT_TO_TSTR (lispstr, pathout);			\
 } while (0)
 
 #else /* not CYGWIN */
 
   /* URL's (and everything else) are already in the right format */
-#define LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR(lispstr, pathout) \
-   LOCAL_FILE_FORMAT_TO_TSTR (lispstr, pathout)
+#define LISP_LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR(lispstr, pathout) \
+   LISP_LOCAL_FILE_FORMAT_TO_TSTR (lispstr, pathout)
 
 #endif /* not CYGWIN */