diff --git a/modules/juce_core/native/juce_linux_Files.cpp b/modules/juce_core/native/juce_linux_Files.cpp index 37cb07cbbd..02b3b36a68 100644 --- a/modules/juce_core/native/juce_linux_Files.cpp +++ b/modules/juce_core/native/juce_linux_Files.cpp @@ -129,7 +129,8 @@ File File::getLinkedTarget() const } //============================================================================== -const char* juce_Argv0 = nullptr; // referenced from juce_Application.cpp +extern const char** juce_argv; // declared in juce_Application.cpp +extern int juce_argc; File File::getSpecialLocation (const SpecialLocationType type) { @@ -180,8 +181,8 @@ File File::getSpecialLocation (const SpecialLocationType type) } case invokedExecutableFile: - if (juce_Argv0 != nullptr) - return File (CharPointer_UTF8 (juce_Argv0)); + if (juce_argv != nullptr && juce_argc > 0) + return File (CharPointer_UTF8 (juce_argv[0])); // deliberate fall-through... case currentExecutableFile: diff --git a/modules/juce_core/native/juce_mac_Files.mm b/modules/juce_core/native/juce_mac_Files.mm index 2fbb603071..6ceb94c859 100644 --- a/modules/juce_core/native/juce_mac_Files.mm +++ b/modules/juce_core/native/juce_mac_Files.mm @@ -163,7 +163,8 @@ bool File::isHidden() const } //============================================================================== -const char* juce_Argv0 = nullptr; // referenced from juce_Application.cpp +extern const char** juce_argv; // declared in juce_Application.cpp +extern int juce_argc; File File::getSpecialLocation (const SpecialLocationType type) { @@ -204,8 +205,8 @@ File File::getSpecialLocation (const SpecialLocationType type) case globalApplicationsDirectory: resultPath = "/Applications"; break; case invokedExecutableFile: - if (juce_Argv0 != 0) - return File (CharPointer_UTF8 (juce_Argv0)); + if (juce_argv != nullptr && juce_argc > 0) + return File (CharPointer_UTF8 (juce_argv[0])); // deliberate fall-through... case currentExecutableFile: diff --git a/modules/juce_core/native/juce_win32_Threads.cpp b/modules/juce_core/native/juce_win32_Threads.cpp index 9f2b2420e8..4b0cfd95b0 100644 --- a/modules/juce_core/native/juce_win32_Threads.cpp +++ b/modules/juce_core/native/juce_win32_Threads.cpp @@ -282,13 +282,6 @@ bool JUCE_CALLTYPE Process::isRunningUnderDebugger() return juce_isRunningUnderDebugger(); } -String JUCE_CALLTYPE Process::getCurrentCommandLineParams() -{ - return CharacterFunctions::findEndOfToken (CharPointer_UTF16 (GetCommandLineW()), - CharPointer_UTF16 (L" "), - CharPointer_UTF16 (L"\"")).findEndOfWhitespace(); -} - static void* currentModuleHandle = nullptr; void* Process::getCurrentModuleInstanceHandle() noexcept diff --git a/modules/juce_core/threads/juce_Process.h b/modules/juce_core/threads/juce_Process.h index 522d2a667c..2caf56d5f0 100644 --- a/modules/juce_core/threads/juce_Process.h +++ b/modules/juce_core/threads/juce_Process.h @@ -128,11 +128,6 @@ public: @see getCurrentModuleInstanceHandle() */ static void JUCE_CALLTYPE setCurrentModuleInstanceHandle (void* newHandle) noexcept; - - /** WINDOWS ONLY - Gets the command-line params as a string. - This is needed to avoid unicode problems with the argc type params. - */ - static String JUCE_CALLTYPE getCurrentCommandLineParams(); #endif private: diff --git a/modules/juce_events/messages/juce_ApplicationBase.h b/modules/juce_events/messages/juce_ApplicationBase.h index aa8fe11040..f3139fd1e0 100644 --- a/modules/juce_events/messages/juce_ApplicationBase.h +++ b/modules/juce_events/messages/juce_ApplicationBase.h @@ -85,8 +85,10 @@ public: If during the initialise() method, the application decides not to start-up after all, it can just call the quit() method and the event loop won't be run. - @param commandLineParameters the line passed in does not include the - name of the executable, just the parameter list. + @param commandLineParameters the line passed in does not include the name of + the executable, just the parameter list. To get the + parameters as an array, you can call + JUCEApplication::getCommandLineParameters() @see shutdown, quit */ virtual void initialise (const String& commandLineParameters) = 0; diff --git a/modules/juce_gui_basics/application/juce_Application.cpp b/modules/juce_gui_basics/application/juce_Application.cpp index e0f89619e3..b9dc78d980 100644 --- a/modules/juce_gui_basics/application/juce_Application.cpp +++ b/modules/juce_gui_basics/application/juce_Application.cpp @@ -136,10 +136,8 @@ bool JUCEApplication::perform (const InvocationInfo& info) } //============================================================================== -bool JUCEApplication::initialiseApp (const String& commandLine) +bool JUCEApplication::initialiseApp() { - commandLineParameters = commandLine.trim(); - #if ! (JUCE_IOS || JUCE_ANDROID) jassert (appLock == nullptr); // initialiseApp must only be called once! @@ -150,7 +148,7 @@ bool JUCEApplication::initialiseApp (const String& commandLine) if (! appLock->enter(0)) { appLock = nullptr; - MessageManager::broadcastMessage (getApplicationName() + "/" + commandLineParameters); + MessageManager::broadcastMessage (getApplicationName() + "/" + getCommandLineParameters()); DBG ("Another instance is running - quitting..."); return false; @@ -159,7 +157,7 @@ bool JUCEApplication::initialiseApp (const String& commandLine) #endif // let the app do its setting-up.. - initialise (commandLineParameters); + initialise (getCommandLineParameters()); #if JUCE_MAC juce_initialiseMacMainMenu(); // needs to be called after the app object has created, to get its name @@ -190,73 +188,85 @@ int JUCEApplication::shutdownApp() } //============================================================================== -#if ! JUCE_ANDROID -int JUCEApplication::main (const String& commandLine) +#if JUCE_ANDROID + +StringArray JUCEApplication::getCommandLineParameterArray() { return StringArray(); } +String JUCEApplication::getCommandLineParameters() { return String::empty; } + +#else + +int JUCEApplication::main() { ScopedJuceInitialiser_GUI libraryInitialiser; jassert (createInstance != nullptr); - int returnCode = 0; - - { - const ScopedPointer app (dynamic_cast (createInstance())); - jassert (app != nullptr); + const ScopedPointer app (dynamic_cast (createInstance())); + jassert (app != nullptr); - if (! app->initialiseApp (commandLine)) - return 0; + if (! app->initialiseApp()) + return 0; - JUCE_TRY - { - // loop until a quit message is received.. - MessageManager::getInstance()->runDispatchLoop(); - } - JUCE_CATCH_EXCEPTION - - returnCode = app->shutdownApp(); + JUCE_TRY + { + // loop until a quit message is received.. + MessageManager::getInstance()->runDispatchLoop(); } + JUCE_CATCH_EXCEPTION - return returnCode; + return app->shutdownApp(); } +#if ! JUCE_WINDOWS #if JUCE_IOS extern int juce_iOSMain (int argc, const char* argv[]); #endif -#if ! JUCE_WINDOWS - extern const char* juce_Argv0; -#endif - #if JUCE_MAC extern void initialiseNSApplication(); #endif +const char* const* juce_argv = nullptr; +int juce_argc = 0; + +StringArray JUCEApplication::getCommandLineParameterArray() +{ + return StringArray (juce_argv + 1, juce_argc - 1); +} + +String JUCEApplication::getCommandLineParameters() +{ + String argString; + + for (int i = 1; i < juce_argc; ++i) + { + String arg (juce_argv[i]); + + if (arg.containsChar (' ') && ! arg.isQuotedString()) + arg = arg.quoted ('"'); + + argString << arg << ' '; + } + + return argString.trim(); +} + int JUCEApplication::main (int argc, const char* argv[]) { JUCE_AUTORELEASEPOOL + juce_argc = argc; + juce_argv = argv; + #if JUCE_MAC initialiseNSApplication(); #endif - #if ! JUCE_WINDOWS - jassert (createInstance != nullptr); - juce_Argv0 = argv[0]; - #endif - #if JUCE_IOS return juce_iOSMain (argc, argv); #else - String cmd; - for (int i = 1; i < argc; ++i) - { - String arg (argv[i]); - if (arg.containsChar (' ') && ! arg.isQuotedString()) - arg = arg.quoted ('"'); - - cmd << arg << ' '; - } - - return JUCEApplication::main (cmd); + return JUCEApplication::main(); #endif } #endif + +#endif diff --git a/modules/juce_gui_basics/application/juce_Application.h b/modules/juce_gui_basics/application/juce_Application.h index 26165848ed..1fd621e31e 100644 --- a/modules/juce_gui_basics/application/juce_Application.h +++ b/modules/juce_gui_basics/application/juce_Application.h @@ -204,8 +204,15 @@ public: */ int getApplicationReturnValue() const noexcept { return appReturnValue; } - /** Returns the application's command line parameters. */ - const String& getCommandLineParameters() const noexcept { return commandLineParameters; } + /** Returns the application's command line parameters as a set of strings. + @see getCommandLineParameters + */ + static StringArray JUCE_CALLTYPE getCommandLineParameterArray(); + + /** Returns the application's command line parameters as a single string. + @see getCommandLineParameterArray + */ + static String JUCE_CALLTYPE getCommandLineParameters(); /** Returns true if this executable is running as an app (as opposed to being a plugin or other kind of shared library. */ @@ -224,16 +231,15 @@ public: //============================================================================== #ifndef DOXYGEN // The following methods are internal calls - not for public use. - static int main (const String& commandLine); + static int main(); static int main (int argc, const char* argv[]); static void sendUnhandledException (const std::exception*, const char* sourceFile, int lineNumber); - bool initialiseApp (const String& commandLine); + bool initialiseApp(); int shutdownApp(); #endif private: //============================================================================== - String commandLineParameters; ScopedPointer appLock; ScopedPointer broadcastCallback; int appReturnValue; diff --git a/modules/juce_gui_basics/application/juce_Initialisation.h b/modules/juce_gui_basics/application/juce_Initialisation.h index ff03508de8..6819f76ea5 100644 --- a/modules/juce_gui_basics/application/juce_Initialisation.h +++ b/modules/juce_gui_basics/application/juce_Initialisation.h @@ -89,8 +89,16 @@ public: #define START_JUCE_APPLICATION(AppClass) \ juce::JUCEApplication* juce_CreateApplication() { return new AppClass(); } -#elif defined (JUCE_GCC) || defined (__MWERKS__) - +#elif JUCE_WINDOWS + #define START_JUCE_APPLICATION(AppClass) \ + static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \ + int __stdcall WinMain (void*, void*, const char*, int) \ + { \ + juce::JUCEApplication::createInstance = &juce_CreateApplication; \ + return juce::JUCEApplication::main(); \ + } + +#else #define START_JUCE_APPLICATION(AppClass) \ static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \ int main (int argc, char* argv[]) \ @@ -99,36 +107,6 @@ public: return juce::JUCEApplication::main (argc, (const char**) argv); \ } -#elif JUCE_WINDOWS - - #ifdef _CONSOLE - #define START_JUCE_APPLICATION(AppClass) \ - static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \ - int main (int, char* argv[]) \ - { \ - juce::JUCEApplication::createInstance = &juce_CreateApplication; \ - return juce::JUCEApplication::main (juce::Process::getCurrentCommandLineParams()); \ - } - #elif ! defined (_AFXDLL) - #ifdef _WINDOWS_ - #define START_JUCE_APPLICATION(AppClass) \ - static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \ - int WINAPI WinMain (HINSTANCE, HINSTANCE, LPSTR, int) \ - { \ - juce::JUCEApplication::createInstance = &juce_CreateApplication; \ - return juce::JUCEApplication::main (juce::Process::getCurrentCommandLineParams()); \ - } - #else - #define START_JUCE_APPLICATION(AppClass) \ - static juce::JUCEApplicationBase* juce_CreateApplication() { return new AppClass(); } \ - int __stdcall WinMain (void*, void*, const char*, int) \ - { \ - juce::JUCEApplication::createInstance = &juce_CreateApplication; \ - return juce::JUCEApplication::main (juce::Process::getCurrentCommandLineParams()); \ - } - #endif - #endif - #endif diff --git a/modules/juce_gui_basics/native/juce_android_Windowing.cpp b/modules/juce_gui_basics/native/juce_android_Windowing.cpp index c5b2cefa89..cade2d36e5 100644 --- a/modules/juce_gui_basics/native/juce_android_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_android_Windowing.cpp @@ -43,7 +43,7 @@ JUCE_JNI_CALLBACK (JUCE_ANDROID_ACTIVITY_CLASSNAME, launchApp, void, (JNIEnv* en initialiseJuce_GUI(); JUCEApplication* app = dynamic_cast (JUCEApplicationBase::createInstance()); - if (! app->initialiseApp (String::empty)) + if (! app->initialiseApp()) exit (0); jassert (MessageManager::getInstance()->isThisTheMessageThread()); diff --git a/modules/juce_gui_basics/native/juce_ios_Windowing.mm b/modules/juce_gui_basics/native/juce_ios_Windowing.mm index 867fbeb622..c1e839d4ce 100644 --- a/modules/juce_gui_basics/native/juce_ios_Windowing.mm +++ b/modules/juce_gui_basics/native/juce_ios_Windowing.mm @@ -41,7 +41,7 @@ initialiseJuce_GUI(); JUCEApplication* app = dynamic_cast (JUCEApplicationBase::createInstance()); - if (! app->initialiseApp (String::empty)) + if (! app->initialiseApp()) exit (0); } diff --git a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp index f696562ad4..cdc28d1d76 100644 --- a/modules/juce_gui_basics/native/juce_win32_Windowing.cpp +++ b/modules/juce_gui_basics/native/juce_win32_Windowing.cpp @@ -3059,6 +3059,30 @@ String SystemClipboard::getTextFromClipboard() return result; } +//============================================================================== +String JUCE_CALLTYPE JUCEApplication::getCommandLineParameters() +{ + return CharacterFunctions::findEndOfToken (CharPointer_UTF16 (GetCommandLineW()), + CharPointer_UTF16 (L" "), + CharPointer_UTF16 (L"\"")).findEndOfWhitespace(); +} + +StringArray JUCE_CALLTYPE JUCEApplication::getCommandLineParameterArray() +{ + StringArray s; + + int argc = 0; + LPWSTR* const argv = CommandLineToArgvW (GetCommandLineW(), &argc); + + if (argv != nullptr) + { + s = StringArray (argv + 1, argc - 1); + LocalFree (argv); + } + + return s; +} + //============================================================================== void Desktop::setKioskComponent (Component* kioskModeComponent, bool enableOrDisable, bool /*allowMenusAndBars*/) {