fltk/src/fl_call_main.c
2023-12-15 20:03:35 +01:00

159 lines
5.6 KiB
C

/*
* Copyright 1998-2023 by Bill Spitzak and others.
*
* 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++.
*
* This library is free software. Distribution and use rights are outlined in
* the file "COPYING" which should have been included with this file. If this
* file is missing or damaged, see the license at:
*
* https://www.fltk.org/COPYING.php
*
* Please see the following page on how to report bugs and issues:
*
* https://www.fltk.org/bugs.php
*/
/*
* This WinMain() function can be overridden by an application and
* is provided for compatibility with programs written for other
* operating systems that conform to the ANSI standard entry point
* "main()". This will allow you to build a Windows Application
* without any special settings.
*
* You cannot have this WinMain() function in a DLL because it would have
* to call \c main() outside the DLL. Thus, this nifty feature is only
* available if you link to the static library.
*
* However, it is possible to build this module separately so you can
* use it in progams that link to the shared library.
*
* Currently the debug version of this library will create a console window
* for your application so you can put printf() statements for debugging or
* informational purposes. Ultimately we want to update this to always use
* the parent's console, but at present we have not identified a function
* or API in Microsoft(r) Windows(r) that allows for it.
*/
/*
* Notes for FLTK developers:
*
* 1) Since FLTK 1.4.0 this file is compiled only on Windows, hence we don't
* need to test the _WIN32 macro.
* 2) This file must not call any FLTK library functions because this would
* not work with /both/ the DLL /and/ the static library (linkage stuff).
* 3) Converting the commandline arguments to UTF-8 is therefore implemented
* here *and* in the library but this seems to be an acceptable compromise.
* 4) (Unless someone finds a better solution, of course. Albrecht)
* 5) The condition "!defined(FL_DLL)" prevents building this in the shared
* library, i.e. "WinMain()" will not be defined in the shared lib (DLL).
* 6) The condition "!defined (__GNUC__)" prevents compilation of this
* module with MinGW, MSYS, and Cygwin which don't use WinMain().
* 7) It is unclear if there are other build systems on Windows that need a
* WinMain() entry point. Earlier comments and code seem to indicate that
* Borland C++ would require it.
*/
#if !defined(FL_DLL) && !defined (__GNUC__)
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <shellapi.h>
extern int main(int, char *[]);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow) {
int rc;
int i;
int argc = 0;
char** argv = NULL;
/*
* If we are compiling in debug mode, open a console window so
* we can see any printf's, etc...
*
* While we can detect if the program was run from the command-line -
* look at the CMDLINE environment variable, it will be "WIN" for
* programs started from the GUI - the shell seems to run all Windows
* applications in the background anyways...
*/
#ifdef _DEBUG
AllocConsole();
freopen("conin$", "r", stdin);
freopen("conout$", "w", stdout);
freopen("conout$", "w", stderr);
#endif /* _DEBUG */
/* Get the command line arguments as Windows Wide Character strings */
LPWSTR *wideArgv = CommandLineToArgvW(GetCommandLineW(), &argc);
/* Allocate an array of 'argc + 1' string pointers */
argv = (char **)malloc((argc + 1) * sizeof(char *));
/* Convert the command line arguments to UTF-8 */
for (i = 0; i < argc; i++) {
/* find the required size of the buffer */
int u8size = WideCharToMultiByte(CP_UTF8, /* CodePage */
0, /* dwFlags */
wideArgv[i], /* lpWideCharStr */
-1, /* cchWideChar */
NULL, /* lpMultiByteStr */
0, /* cbMultiByte */
NULL, /* lpDefaultChar */
NULL); /* lpUsedDefaultChar */
if (u8size > 0) {
char *strbuf = (char *)malloc(u8size);
int ret = WideCharToMultiByte(CP_UTF8, /* CodePage */
0, /* dwFlags */
wideArgv[i], /* lpWideCharStr */
-1, /* cchWideChar */
strbuf, /* lpMultiByteStr */
u8size, /* cbMultiByte */
NULL, /* lpDefaultChar */
NULL); /* lpUsedDefaultChar */
if (ret) {
argv[i] = strbuf;
} else {
argv[i] = _strdup("");
free(strbuf);
}
} else {
argv[i] = _strdup("");
}
}
argv[argc] = NULL; /* required by C standard at end of list */
/* 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(stdout);
fclose(stderr);
#endif /* _DEBUG */
return rc;
}
#else
/* STR# 2973: solves "empty translation unit" error */
typedef int dummy;
#endif /* !defined(FL_DLL) && !defined (__GNUC__) */