Windows/MSVC: Fix wide char commandline handling (#840)
Windows programs (subsystem:windows, not Windows console programs) compiled with Visual Studio need a WinMain entry point. The commandline arguments handled by this function are now properly converted to UTF-8 before the standard main() entry point is called. This applies only to Visual Studio! Note that some build systems like MinGW and/or MSYS2 may still have issues with some Unicode (non-ASCII) commandline arguments.
This commit is contained in:
parent
a72eff7588
commit
7e8994c4a2
@ -578,9 +578,9 @@ list (APPEND SHARED_FILES ${HEADER_FILES} ${DRIVER_HEADER_FILES})
|
|||||||
|
|
||||||
set (STATIC_FILES ${SHARED_FILES})
|
set (STATIC_FILES ${SHARED_FILES})
|
||||||
|
|
||||||
if (WIN32)
|
if (MSVC)
|
||||||
list (APPEND STATIC_FILES fl_call_main.c)
|
list (APPEND STATIC_FILES fl_call_main.c)
|
||||||
endif (WIN32)
|
endif (MSVC)
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
|
@ -244,7 +244,8 @@ IMGCPPFILES = \
|
|||||||
Fl_SVG_Image.cxx \
|
Fl_SVG_Image.cxx \
|
||||||
drivers/SVG/Fl_SVG_File_Surface.cxx
|
drivers/SVG/Fl_SVG_File_Surface.cxx
|
||||||
|
|
||||||
CFILES = fl_call_main.c flstring.c numericsort.c vsnprintf.c
|
CFILES = flstring.c numericsort.c vsnprintf.c
|
||||||
|
CFILES_WIN = fl_call_main.c
|
||||||
|
|
||||||
UTF8CFILES = \
|
UTF8CFILES = \
|
||||||
xutf8/case.c \
|
xutf8/case.c \
|
||||||
@ -431,7 +432,7 @@ EXTRA_OBJECTS_WAYLANDX11 = $(EXTRA_OBJECTS_WAYLAND)
|
|||||||
EXTRA_CXXFLAGS_WAYLAND = -I.
|
EXTRA_CXXFLAGS_WAYLAND = -I.
|
||||||
EXTRA_CXXFLAGS_WAYLANDX11 = $(EXTRA_CXXFLAGS_WAYLAND)
|
EXTRA_CXXFLAGS_WAYLANDX11 = $(EXTRA_CXXFLAGS_WAYLAND)
|
||||||
|
|
||||||
CFILES_WIN = $(GDICFILES)
|
CFILES_WIN += $(GDICFILES)
|
||||||
|
|
||||||
CFILES += $(CFILES_$(BUILD))
|
CFILES += $(CFILES_$(BUILD))
|
||||||
CXXFLAGS += $(EXTRA_CXXFLAGS_$(BUILD))
|
CXXFLAGS += $(EXTRA_CXXFLAGS_$(BUILD))
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 1998-2018 by Bill Spitzak and others.
|
* Copyright 1998-2023 by Bill Spitzak and others.
|
||||||
*
|
*
|
||||||
* fl_call_main() calls main() for you Windows people. Needs to be done in C
|
* fl_call_main() calls main() for you Windows people. Needs to be done in C
|
||||||
* because Borland C++ won't let you call main() from C++.
|
* because Borland C++ won't let you call main() from C++.
|
||||||
@ -35,44 +35,34 @@
|
|||||||
* Microsoft(r) Windows(r) that allows for it.
|
* Microsoft(r) Windows(r) that allows for it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(FL_DLL) && !defined (__GNUC__)
|
/*
|
||||||
|
* This file is compiled only on Windows platforms (since FLTK 1.4.0).
|
||||||
|
* Therefore we don't need to test the _WIN32 macro anymore.
|
||||||
|
* The _MSC_VER macro is tested to compile it only for Visual Studio
|
||||||
|
* platforms because GNU platforms (MinGW, MSYS) don't need it.
|
||||||
|
*/
|
||||||
|
#if defined(_MSC_VER) && !defined(FL_DLL)
|
||||||
|
|
||||||
# include <windows.h>
|
#include <FL/fl_utf8.h>
|
||||||
# include <stdio.h>
|
#include <FL/fl_string_functions.h>
|
||||||
# include <stdlib.h>
|
|
||||||
# include <FL/fl_utf8.h>
|
#include <windows.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <shellapi.h>
|
||||||
|
|
||||||
extern int main(int, char *[]);
|
extern int main(int, char *[]);
|
||||||
|
|
||||||
# ifdef BORLAND5
|
|
||||||
# define __argc _argc
|
|
||||||
# define __argv _argv
|
|
||||||
# endif /* BORLAND5 */
|
|
||||||
|
|
||||||
/* static int mbcs2utf(const char *s, int l, char *dst, unsigned dstlen) */
|
|
||||||
static int mbcs2utf(const char *s, int l, char *dst)
|
|
||||||
{
|
|
||||||
static wchar_t *mbwbuf;
|
|
||||||
unsigned dstlen = 0;
|
|
||||||
if (!s) return 0;
|
|
||||||
dstlen = (l * 6) + 6;
|
|
||||||
mbwbuf = (wchar_t*)malloc(dstlen * sizeof(wchar_t));
|
|
||||||
l = (int) mbstowcs(mbwbuf, s, l);
|
|
||||||
/* l = fl_unicode2utf(mbwbuf, l, dst); */
|
|
||||||
l = fl_utf8fromwc(dst, dstlen, mbwbuf, l);
|
|
||||||
dst[l] = 0;
|
|
||||||
free(mbwbuf);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
||||||
LPSTR lpCmdLine, int nCmdShow) {
|
LPSTR lpCmdLine, int nCmdShow) {
|
||||||
int rc, i;
|
int rc;
|
||||||
char **ar;
|
int i;
|
||||||
|
int argc;
|
||||||
|
char** argv;
|
||||||
|
char strbuf[2048];
|
||||||
|
|
||||||
# ifdef _DEBUG
|
|
||||||
/*
|
/*
|
||||||
* If we are using compiling in debug mode, open a console window so
|
* If we are compiling in debug mode, open a console window so
|
||||||
* we can see any printf's, etc...
|
* we can see any printf's, etc...
|
||||||
*
|
*
|
||||||
* While we can detect if the program was run from the command-line -
|
* While we can detect if the program was run from the command-line -
|
||||||
@ -81,48 +71,52 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
|
|||||||
* applications in the background anyways...
|
* applications in the background anyways...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
AllocConsole();
|
AllocConsole();
|
||||||
freopen("conin$", "r", stdin);
|
freopen("conin$", "r", stdin);
|
||||||
freopen("conout$", "w", stdout);
|
freopen("conout$", "w", stdout);
|
||||||
freopen("conout$", "w", stderr);
|
freopen("conout$", "w", stderr);
|
||||||
# endif /* _DEBUG */
|
#endif /* _DEBUG */
|
||||||
|
|
||||||
ar = (char**) malloc(sizeof(char*) * (__argc + 1));
|
/* Convert the command line arguments to UTF-8 */
|
||||||
i = 0;
|
LPWSTR *wideArgv = CommandLineToArgvW(GetCommandLineW(), &argc);
|
||||||
while (i < __argc) {
|
argv = malloc(argc * sizeof(void *));
|
||||||
int l;
|
for (i = 0; i < argc; i++) {
|
||||||
unsigned dstlen;
|
int ret = WideCharToMultiByte(CP_UTF8, /* CodePage */
|
||||||
if (__wargv ) {
|
0, /* dwFlags */
|
||||||
for (l = 0; __wargv[i] && __wargv[i][l]; l++) {}; /* is this just wstrlen??? */
|
wideArgv[i], /* lpWideCharStr */
|
||||||
dstlen = (l * 5) + 1;
|
-1, /* cchWideChar */
|
||||||
ar[i] = (char*) malloc(dstlen);
|
strbuf, /* lpMultiByteStr */
|
||||||
/* ar[i][fl_unicode2utf(__wargv[i], l, ar[i])] = 0; */
|
sizeof(strbuf), /* cbMultiByte */
|
||||||
dstlen = fl_utf8fromwc(ar[i], dstlen, __wargv[i], l);
|
NULL, /* lpDefaultChar */
|
||||||
ar[i][dstlen] = 0;
|
NULL); /* lpUsedDefaultChar */
|
||||||
} else {
|
argv[i] = fl_strdup(strbuf);
|
||||||
for (l = 0; __argv[i] && __argv[i][l]; l++) {};
|
|
||||||
dstlen = (l * 5) + 1;
|
|
||||||
ar[i] = (char*) malloc(dstlen);
|
|
||||||
/* ar[i][mbcs2utf(__argv[i], l, ar[i], dstlen)] = 0; */
|
|
||||||
ar[i][mbcs2utf(__argv[i], l, ar[i])] = 0;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
ar[__argc] = 0;
|
|
||||||
/* Run the standard main entry point function... */
|
|
||||||
rc = main(__argc, ar);
|
|
||||||
|
|
||||||
# ifdef _DEBUG
|
/* Free the wide character string array */
|
||||||
|
LocalFree(wideArgv);
|
||||||
|
|
||||||
|
/* Call the program's entry point main() */
|
||||||
|
rc = main(argc, argv);
|
||||||
|
|
||||||
|
/* Cleanup allocated memory for argv */
|
||||||
|
for (int i = 0; i < argc; ++i) {
|
||||||
|
free((void *)argv[i]);
|
||||||
|
}
|
||||||
|
free((void *)argv);
|
||||||
|
|
||||||
|
/* Close the console in debug mode */
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
fclose(stdin);
|
fclose(stdin);
|
||||||
fclose(stdout);
|
fclose(stdout);
|
||||||
fclose(stderr);
|
fclose(stderr);
|
||||||
# endif /* _DEBUG */
|
#endif /* _DEBUG */
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* STR# 2973: solves "empty translation unit" error (Sun, HP-UX..) */
|
/* STR# 2973: solves "empty translation unit" error */
|
||||||
typedef int dummy;
|
typedef int dummy;
|
||||||
#endif /* _WIN32 && !FL_DLL && !__GNUC__ */
|
#endif /* defined(_MSC_VER) && !defined(FL_DLL) */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user