Refactor InitPlatform.

This commit performs three related cleanups:
  * The slvs library no longer uses explicit platform initialization
    (which drags in the side effects of InitPlatform that are not
    desirable in a library). Instead, it just ensures that it has
    the temporary heap, which is what it was callingInitPlatform for.
  * InitPlatform is simplified and moved to platform.cpp, next to
    other path related functions.
  * InitPlatform is renamed to InitCli and is called from InitGui
    implementations. GUI toolkits sometimes have options they use
    internally (that's the case for for GTK and Cocoa at least),
    and we shouldn't try to parse those as a file to open.
pull/598/head^2
whitequark 2020-05-10 07:21:16 +00:00
parent 9c1804b1b5
commit 1442ee5ec3
16 changed files with 78 additions and 63 deletions

View File

@ -41,7 +41,7 @@ static bool RunBenchmark(std::function<void()> setupFn,
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
std::vector<std::string> args = InitPlatform(argc, argv); std::vector<std::string> args = Platform::InitCli(argc, argv);
std::string mode; std::string mode;
Platform::Path filename; Platform::Path filename;

View File

@ -11,8 +11,6 @@
Sketch SolveSpace::SK = {}; Sketch SolveSpace::SK = {};
static System SYS; static System SYS;
static int IsInit = 0;
void SolveSpace::Platform::FatalError(const std::string &message) { void SolveSpace::Platform::FatalError(const std::string &message) {
fprintf(stderr, "%s", message.c_str()); fprintf(stderr, "%s", message.c_str());
abort(); abort();
@ -69,10 +67,8 @@ void Slvs_MakeQuaternion(double ux, double uy, double uz,
void Slvs_Solve(Slvs_System *ssys, Slvs_hGroup shg) void Slvs_Solve(Slvs_System *ssys, Slvs_hGroup shg)
{ {
if(!IsInit) { // Create the temporary heap, if this is the first time we're solving.
InitPlatform(0, NULL); FreeAllTemporary();
IsInit = 1;
}
int i; int i;
for(i = 0; i < ssys->params; i++) { for(i = 0; i < ssys->params; i++) {

View File

@ -351,7 +351,7 @@ static bool RunCommand(const std::vector<std::string> args) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
std::vector<std::string> args = InitPlatform(argc, argv); std::vector<std::string> args = Platform::InitCli(argc, argv);
if(args.size() == 1) { if(args.size() == 1) {
ShowUsage(args[0]); ShowUsage(args[0]);

View File

@ -11,9 +11,8 @@
using namespace SolveSpace; using namespace SolveSpace;
int main(int argc, char** argv) { int main(int argc, char** argv) {
std::vector<std::string> args = InitPlatform(argc, argv); std::vector<std::string> args = Platform::InitGui(argc, argv);
Platform::InitGui(argc, argv);
Platform::Open3DConnexion(); Platform::Open3DConnexion();
SS.Init(); SS.Init();

View File

@ -377,7 +377,7 @@ FileDialogRef CreateSaveFileDialog(WindowRef parentWindow);
std::vector<Platform::Path> GetFontFiles(); std::vector<Platform::Path> GetFontFiles();
void OpenInBrowser(const std::string &url); void OpenInBrowser(const std::string &url);
void InitGui(int argc, char **argv); std::vector<std::string> InitGui(int argc, char **argv);
void RunGui(); void RunGui();
void ExitGui(); void ExitGui();
void ClearGui(); void ClearGui();

View File

@ -1432,7 +1432,7 @@ void OpenInBrowser(const std::string &url) {
Gtk::Main *gtkMain; Gtk::Main *gtkMain;
void InitGui(int argc, char **argv) { std::vector<std::string> InitGui(int argc, char **argv) {
// It would in principle be possible to judiciously use Glib::filename_{from,to}_utf8, // It would in principle be possible to judiciously use Glib::filename_{from,to}_utf8,
// but it's not really worth the effort. // but it's not really worth the effort.
// The setlocale() call is necessary for Glib::get_charset() to detect the system // The setlocale() call is necessary for Glib::get_charset() to detect the system
@ -1445,8 +1445,12 @@ void InitGui(int argc, char **argv) {
} }
setlocale(LC_ALL, "C"); setlocale(LC_ALL, "C");
// Let GTK parse arguments and update argc/argv. (They're passed by reference.)
gtkMain = new Gtk::Main(argc, argv, /*set_locale=*/false); gtkMain = new Gtk::Main(argc, argv, /*set_locale=*/false);
// Now that GTK arguments are removed, grab arguments for ourselves.
std::vector<std::string> args = InitCli(argc, argv);
// Add our application-specific styles, to override GTK defaults. // Add our application-specific styles, to override GTK defaults.
Glib::RefPtr<Gtk::CssProvider> style_provider = Gtk::CssProvider::create(); Glib::RefPtr<Gtk::CssProvider> style_provider = Gtk::CssProvider::create();
style_provider->load_from_data(R"( style_provider->load_from_data(R"(
@ -1468,6 +1472,8 @@ void InitGui(int argc, char **argv) {
if(!*langNames) { if(!*langNames) {
SetLocale("en_US"); SetLocale("en_US");
} }
return args;
} }
void RunGui() { void RunGui() {

View File

@ -1441,7 +1441,9 @@ namespace Platform {
static SSApplicationDelegate *ssDelegate; static SSApplicationDelegate *ssDelegate;
void InitGui(int argc, char **argv) { std::vector<std::string> InitGui(int argc, char **argv) {
std::vector<std::string> args = InitCli(argc, argv);
ssDelegate = [[SSApplicationDelegate alloc] init]; ssDelegate = [[SSApplicationDelegate alloc] init];
NSApplication.sharedApplication.delegate = ssDelegate; NSApplication.sharedApplication.delegate = ssDelegate;
@ -1454,6 +1456,8 @@ void InitGui(int argc, char **argv) {
if(languages.count == 0) { if(languages.count == 0) {
SolveSpace::SetLocale("en_US"); SolveSpace::SetLocale("en_US");
} }
return args;
} }
void RunGui() { void RunGui() {

View File

@ -148,7 +148,9 @@ std::vector<Platform::Path> GetFontFiles() {
void OpenInBrowser(const std::string &url) {} void OpenInBrowser(const std::string &url) {}
void InitGui(int argc, char **argv) {} std::vector<std::string> InitGui(int argc, char **argv) {
return {};
}
void RunGui() {} void RunGui() {}

View File

@ -1656,7 +1656,9 @@ void OpenInBrowser(const std::string &url) {
ShellExecuteW(NULL, L"open", Widen(url).c_str(), NULL, NULL, SW_SHOWNORMAL); ShellExecuteW(NULL, L"open", Widen(url).c_str(), NULL, NULL, SW_SHOWNORMAL);
} }
void InitGui(int argc, char **argv) { std::vector<std::string> InitGui(int argc, char **argv) {
std::vector<std::string> args = InitCli(argc, argv);
INITCOMMONCONTROLSEX icc; INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(icc); icc.dwSize = sizeof(icc);
icc.dwICC = ICC_STANDARD_CLASSES|ICC_BAR_CLASSES; icc.dwICC = ICC_STANDARD_CLASSES|ICC_BAR_CLASSES;
@ -1665,6 +1667,8 @@ void InitGui(int argc, char **argv) {
if(!SetLocale((uint16_t)GetUserDefaultLCID())) { if(!SetLocale((uint16_t)GetUserDefaultLCID())) {
SetLocale("en_US"); SetLocale("en_US");
} }
return args;
} }
void RunGui() { void RunGui() {

View File

@ -14,6 +14,7 @@
#if defined(WIN32) #if defined(WIN32)
// Conversely, include Microsoft headers after solvespace.h to avoid clashes. // Conversely, include Microsoft headers after solvespace.h to avoid clashes.
# include <windows.h> # include <windows.h>
# include <shellapi.h>
#else #else
# include <unistd.h> # include <unistd.h>
# include <sys/stat.h> # include <sys/stat.h>
@ -452,7 +453,7 @@ bool WriteFile(const Platform::Path &filename, const std::string &data) {
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Loading resources, on Windows // Loading resources, on Windows.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#if defined(WIN32) #if defined(WIN32)
@ -470,7 +471,7 @@ const void *LoadResource(const std::string &name, size_t *size) {
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Loading resources, on *nix // Loading resources, on *nix.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#if defined(__APPLE__) #if defined(__APPLE__)
@ -588,8 +589,49 @@ const void *LoadResource(const std::string &name, size_t *size) {
#endif #endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Command-line argument handling // Startup and command-line argument handling, on Windows.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#if defined(WIN32)
std::vector<std::string> InitCli(int argc, char **argv) {
#if defined(_MSC_VER)
// We display our own message on abort; just call ReportFault.
_set_abort_behavior(_CALL_REPORTFAULT, _WRITE_ABORT_MSG|_CALL_REPORTFAULT);
int crtReportTypes[] = {_CRT_WARN, _CRT_ERROR, _CRT_ASSERT};
for(int crtReportType : crtReportTypes) {
_CrtSetReportMode(crtReportType, _CRTDBG_MODE_FILE|_CRTDBG_MODE_DEBUG);
_CrtSetReportFile(crtReportType, _CRTDBG_FILE_STDERR);
}
#endif
// Create the heap that we use to store Exprs and other temp stuff.
FreeAllTemporary();
// Extract the command-line arguments; the ones from main() are ignored,
// since they are in the OEM encoding.
int argcW;
LPWSTR *argvW = CommandLineToArgvW(GetCommandLineW(), &argcW);
std::vector<std::string> args;
for(int i = 0; i < argcW; i++)
args.push_back(Platform::Narrow(argvW[i]));
LocalFree(argvW);
return args;
}
#endif
//-----------------------------------------------------------------------------
// Startup and command-line argument handling, on *nix.
//-----------------------------------------------------------------------------
#if !defined(WIN32)
std::vector<std::string> InitCli(int argc, char **argv) {
return {&argv[0], &argv[argc]};
}
#endif
} }
} }

View File

@ -64,6 +64,9 @@ void RemoveFile(const Platform::Path &filename);
// Resource loading function. // Resource loading function.
const void *LoadResource(const std::string &name, size_t *size); const void *LoadResource(const std::string &name, size_t *size);
// Startup and command-line argument handling.
std::vector<std::string> InitCli(int argc, char **argv);
} }
#endif #endif

View File

@ -4,11 +4,7 @@
// Copyright 2008-2013 Jonathan Westhues. // Copyright 2008-2013 Jonathan Westhues.
// Copyright 2013 Daniel Richard G. <skunk@iSKUNK.ORG> // Copyright 2013 Daniel Richard G. <skunk@iSKUNK.ORG>
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "config.h"
#include "solvespace.h" #include "solvespace.h"
#if defined(HAVE_BACKTRACE)
# include BACKTRACE_HEADER
#endif
namespace SolveSpace { namespace SolveSpace {
@ -61,13 +57,4 @@ void FreeAllTemporary() {
Head = NULL; Head = NULL;
} }
std::vector<std::string> InitPlatform(int argc, char **argv) {
std::vector<std::string> args;
args.reserve(argc);
for(int i = 0; i < argc; i++) {
args.emplace_back(argv[i]);
}
return args;
}
}; };

View File

@ -7,10 +7,8 @@
// Include after solvespace.h to avoid identifier clashes. // Include after solvespace.h to avoid identifier clashes.
#include <windows.h> #include <windows.h>
#include <shellapi.h>
namespace SolveSpace { namespace SolveSpace {
static HANDLE TempHeap;
void dbp(const char *str, ...) void dbp(const char *str, ...)
{ {
@ -38,6 +36,8 @@ void dbp(const char *str, ...)
// to be sloppy with our memory management, and just free everything at once // to be sloppy with our memory management, and just free everything at once
// at the end. // at the end.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static HANDLE TempHeap;
void *AllocTemporary(size_t n) void *AllocTemporary(size_t n)
{ {
void *v = HeapAlloc(TempHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, n); void *v = HeapAlloc(TempHeap, HEAP_NO_SERIALIZE | HEAP_ZERO_MEMORY, n);
@ -50,30 +50,4 @@ void FreeAllTemporary()
TempHeap = HeapCreate(HEAP_NO_SERIALIZE, 1024*1024*20, 0); TempHeap = HeapCreate(HEAP_NO_SERIALIZE, 1024*1024*20, 0);
} }
std::vector<std::string> InitPlatform(int argc, char **argv) {
#if !defined(LIBRARY) && defined(_MSC_VER)
// We display our own message on abort; just call ReportFault.
_set_abort_behavior(_CALL_REPORTFAULT, _WRITE_ABORT_MSG|_CALL_REPORTFAULT);
int crtReportTypes[] = {_CRT_WARN, _CRT_ERROR, _CRT_ASSERT};
for(int crtReportType : crtReportTypes) {
_CrtSetReportMode(crtReportType, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(crtReportType, _CRTDBG_FILE_STDERR);
}
#endif
// Create the heap that we use to store Exprs and other temp stuff.
FreeAllTemporary();
// Extract the command-line arguments; the ones from main() are ignored,
// since they are in the OEM encoding.
int argcW;
LPWSTR *argvW = CommandLineToArgvW(GetCommandLineW(), &argcW);
std::vector<std::string> args;
for(int i = 0; i < argcW; i++) {
args.push_back(Platform::Narrow(argvW[i]));
}
LocalFree(argvW);
return args;
}
} }

View File

@ -146,8 +146,6 @@ void dbp(const char *str, ...);
dbp("tri: (%.3f %.3f %.3f) (%.3f %.3f %.3f) (%.3f %.3f %.3f)", \ dbp("tri: (%.3f %.3f %.3f) (%.3f %.3f %.3f) (%.3f %.3f %.3f)", \
CO((tri).a), CO((tri).b), CO((tri).c)) CO((tri).a), CO((tri).b), CO((tri).c))
std::vector<std::string> InitPlatform(int argc, char **argv);
void *AllocTemporary(size_t n); void *AllocTemporary(size_t n);
void FreeAllTemporary(); void FreeAllTemporary();

View File

@ -6,7 +6,7 @@
#include "solvespace.h" #include "solvespace.h"
int main(int argc, char **argv) { int main(int argc, char **argv) {
std::vector<std::string> args = InitPlatform(argc, argv); std::vector<std::string> args = Platform::InitCli(argc, argv);
if(args.size() == 3 && args[1] == "expr") { if(args.size() == 3 && args[1] == "expr") {
std::string expr = args[2], err; std::string expr = args[2], err;

View File

@ -335,7 +335,7 @@ int Test::Case::Register(Test::Case testCase) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
std::vector<std::string> args = InitPlatform(argc, argv); std::vector<std::string> args = Platform::InitCli(argc, argv);
std::regex filter(".*"); std::regex filter(".*");
if(args.size() == 1) { if(args.size() == 1) {