filenames on MS Windows: follow-up
Allin Cottrell <[email protected]>
| Newsgroups | gmane.comp.graphics.gnuplot.devel |
|---|---|
| Message-ID | <[email protected]> |
I'm attaching a patch against gnuplot git master which does what I mentioned in https://sourceforge.net/p/gnuplot/mailman/message/37141539/ That is, it allows wgnuplot.exe to accept via the Windows command-line unicode filenames that cannot be represented in the user's "system codepage", and to successfully to open such files. This iteration of my patch uses native win32 APIs to perform the necessary recoding of filenames, as opposed to the previous iteration which used GLib. I gave evidence in https://sourceforge.net/p/gnuplot/mailman/message/37143153/ that the patch is not disruptive of gnuplot's ability to open files named via the "load" command, in which case the encoding specified in the gnuplot script must be respected. The patch is activated only when compiling the program for Windows, and then only when the symbol WIDE_ARGS is defined. -- Allin Cottrell Department of Economics Wake Forest University _______________________________________________ gnuplot-beta mailing list [email protected] Membership management via: https://lists.sourceforge.net/lists/listinfo/gnuplot-beta
wide_args.diff
(text/plain, 3.8 KB)
diff --git a/src/misc.c b/src/misc.c
index b1fd32c5d..998f93be4 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -49,6 +49,9 @@
# if defined(__WATCOMC__) || defined(_MSC_VER)
# include <io.h> /* for setmode() */
# endif
+# ifdef WIDE_ARGS
+# include <windows.h>
+# endif
#endif
static void prepare_call(int calltype);
@@ -514,6 +517,49 @@ load_file_error()
while (lf_pop());
}
+#ifdef WIDE_ARGS
+
+wchar_t *win32_utf8_to_utf16 (const char *s)
+{
+ wchar_t *ret = NULL;
+ int len;
+
+ len = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0);
+ if (len > 0) {
+ ret = malloc(len * sizeof *ret);
+ MultiByteToWideChar(CP_UTF8, 0, s, -1, ret, len);
+ }
+
+ return ret;
+}
+
+#endif
+
+static FILE *
+alt_fopen(const char *filename, const char *mode)
+{
+ FILE *fp = fopen(filename, mode);
+
+#ifdef WIDE_ARGS
+ if (fp == NULL) {
+ wchar_t *wfname;
+
+ wfname = win32_utf8_to_utf16(filename);
+ if (wfname != NULL) {
+ size_t len = strlen(mode) + 1;
+ wchar_t *wmode = calloc(len, sizeof *wmode);
+
+ mbstowcs(wmode, mode, len);
+ fp = _wfopen(wfname, wmode);
+ free(wmode);
+ free(wfname);
+ }
+ }
+#endif
+
+ return fp;
+}
+
FILE *
loadpath_fopen(const char *filename, const char *mode)
{
@@ -535,7 +581,7 @@ loadpath_fopen(const char *filename, const char *mode)
return (FILE *) 0;
} else
#endif /* PIPES */
- if ((fp = fopen(filename, mode)) == (FILE *) NULL) {
+ if ((fp = alt_fopen(filename, mode)) == (FILE *) NULL) {
/* try 'loadpath' variable */
char *fullname = NULL, *path;
@@ -544,7 +590,7 @@ loadpath_fopen(const char *filename, const char *mode)
fullname = gp_realloc(fullname, strlen(path) + 1 + strlen(filename) + 1, "loadpath_fopen");
strcpy(fullname, path);
PATH_CONCAT(fullname, filename);
- if ((fp = fopen(fullname, mode)) != NULL) {
+ if ((fp = alt_fopen(fullname, mode)) != NULL) {
/* free(fullname); */
loadpath_fontname = fullname;
fullname = NULL;
diff --git a/src/win/winmain.c b/src/win/winmain.c
index 0fd3de027..0efcd36ce 100644
--- a/src/win/winmain.c
+++ b/src/win/winmain.c
@@ -424,6 +424,56 @@ ReadMainIni(LPTSTR file, LPTSTR section)
}
}
+#ifdef WIDE_ARGS
+
+static char *win32_utf16_to_utf8 (wchar_t *w)
+{
+ char *ret = NULL;
+ int len;
+
+ len = WideCharToMultiByte(CP_UTF8, 0, w, -1, NULL, 0, NULL, NULL);
+ if (len > 0) {
+ ret = malloc(len);
+ WideCharToMultiByte(CP_UTF8, 0, w, -1, ret, len, NULL, NULL);
+ }
+
+ return ret;
+}
+
+static int alt_winargs (int *pargc, char ***pargv)
+{
+ int argc_w = 0;
+ LPWSTR *argv_w;
+ int err = 0;
+
+ /* get args as UTF-16 */
+ argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
+
+ if (argv_w == NULL) {
+ err = 1;
+ } else {
+ /* convert args to UTF-8, so they can be passed
+ and read as char * by gnu_main()
+ */
+ char **argv_u8 = calloc(argc_w, sizeof *argv_u8);
+ int i;
+
+ for (i=0; i<argc_w && !err; i++) {
+ argv_u8[i] = win32_utf16_to_utf8(argv_w[i]);
+ if (argv_u8[i] == NULL) {
+ err = 1;
+ }
+ }
+ *pargc = argc_w;
+ *pargv = argv_u8;
+ /* we're done with this */
+ LocalFree(argv_w);
+ }
+
+ return err;
+}
+
+#endif
#ifndef WGP_CONSOLE
int WINAPI
@@ -441,10 +491,14 @@ main(int argc, char **argv)
#endif
#ifndef WGP_CONSOLE
-# if defined( __MINGW32__) && !defined(_W64)
+# if defined(__MINGW32__) && !defined(_W64)
# define argc _argc
# define argv _argv
-# else /* MSVC, WATCOM, MINGW-W64 */
+# elif defined(WIDE_ARGS)
+ int argc = 0;
+ char **argv = NULL;
+ alt_winargs(&argc, &argv);
+# else /* MSVC, WATCOM */
# define argc __argc
# define argv __argv
# endif