diff --git a/PowerEditor/src/Notepad_plus_Window.cpp b/PowerEditor/src/Notepad_plus_Window.cpp index 97b57c0a..bfba1b9f 100644 --- a/PowerEditor/src/Notepad_plus_Window.cpp +++ b/PowerEditor/src/Notepad_plus_Window.cpp @@ -177,7 +177,7 @@ void Notepad_plus_Window::init(HINSTANCE hInst, HWND parent, const TCHAR *cmdLin { ::ShowWindow(_hSelf, SW_HIDE); } - else if (not cmdLineParams->_isPreLaunch) + else if (!cmdLineParams->_isPreLaunch) { if (cmdLineParams->isPointValid()) ::ShowWindow(_hSelf, SW_SHOW); diff --git a/PowerEditor/src/Notepad_plus_Window.h b/PowerEditor/src/Notepad_plus_Window.h index 613a1c8c..c846d67d 100644 --- a/PowerEditor/src/Notepad_plus_Window.h +++ b/PowerEditor/src/Notepad_plus_Window.h @@ -31,7 +31,7 @@ const TCHAR COMMAND_ARG_HELP[] = TEXT("Usage :\r\ \r\ -notepad++ [--help] [-multiInst] [-noPlugin] [-lLanguage] [-LlangCode] [-nLineNumber] [-cColumnNumber] [-pPosition] [-xLeftPos] [-yTopPos] [-nosession] [-notabbar] [-ro] [-systemtray] [-loadingTime] [-alwaysOnTop] [-openSession] [-r] [-qnEasterEggName | -qtText | -qfCntentFileName] [-qSpeed1|2|3] [-quickPrint] [-openFoldersAsWorkspace] [filePath]\r\ +notepad++ [--help] [-multiInst] [-noPlugin] [-lLanguage] [-LlangCode] [-nLineNumber] [-cColumnNumber] [-pPosition] [-xLeftPos] [-yTopPos] [-nosession] [-notabbar] [-ro] [-systemtray] [-loadingTime] [-alwaysOnTop] [-openSession] [-r] [-qnEasterEggName | -qtText | -qfCntentFileName] [-qSpeed1|2|3] [-quickPrint] [-settingsDir=\"d:\\your settings dir\\\"] [-openFoldersAsWorkspace] [filePath]\r\ \r\ --help : This help message\r\ -multiInst : Launch another Notepad++ instance\r\ @@ -57,6 +57,7 @@ notepad++ [--help] [-multiInst] [-noPlugin] [-lLanguage] [-LlangCode] [-nLineNum -qf : Launch ghost typing to display a file content via the file path\r\ -qSpeed : Ghost typing speed. Value from 1 to 3 for slow, fast and fastest\r\ -quickPrint : Print the file given as argument then quit Notepad++\r\ +-settingsDir=\"d:\\your settings dir\\\": Override the default settings dir\r\ -openFoldersAsWorkspace: open filePath of folder(s) as workspace\r\ filePath : file or folder name to open (absolute or relative path name)\r\ "); diff --git a/PowerEditor/src/Parameters.cpp b/PowerEditor/src/Parameters.cpp index 8a5aeb81..7ea71b0e 100644 --- a/PowerEditor/src/Parameters.cpp +++ b/PowerEditor/src/Parameters.cpp @@ -1005,8 +1005,6 @@ bool NppParameters::load() { L_END = L_EXTERNAL; bool isAllLaoded = true; - for (int i = 0 ; i < NB_LANG ; _langList[i] = NULL, ++i) - {} _isx64 = sizeof(void *) == 8; @@ -1037,6 +1035,9 @@ bool NppParameters::load() _pluginRootDir = _nppPath; PathAppend(_pluginRootDir, TEXT("plugins")); + // + // the 3rd priority: general default configuration + // generic_string nppPluginRootParent; if (_isLocal) { @@ -1078,7 +1079,9 @@ bool NppParameters::load() generic_string cloudChoicePath{_userPath}; cloudChoicePath += TEXT("\\cloud\\choice"); - // cloudChoicePath doesn't exist, just quit + // + // the 2nd priority: cloud Choice Path + // if (::PathFileExists(cloudChoicePath.c_str())) { // Read cloud choice @@ -1086,7 +1089,7 @@ bool NppParameters::load() WcharMbcsConvertor& wmc = WcharMbcsConvertor::getInstance(); std::wstring cloudChoiceStrW = wmc.char2wchar(cloudChoiceStr.c_str(), SC_CP_UTF8); - if (not cloudChoiceStrW.empty() and ::PathFileExists(cloudChoiceStrW.c_str())) + if (!cloudChoiceStrW.empty() && ::PathFileExists(cloudChoiceStrW.c_str())) { _userPath = cloudChoiceStrW; _nppGUI._cloudPath = cloudChoiceStrW; @@ -1094,6 +1097,26 @@ bool NppParameters::load() } } + // + // the 1st priority: custom settings dir via command line argument + // + if (!_cmdSettingsDir.empty()) + { + if (!::PathIsDirectory(_cmdSettingsDir.c_str())) + { + // The following text is not translatable. + // _pNativeLangSpeaker is initialized AFTER _userPath being dterminated because nativeLang.xml is from from _userPath. + generic_string errMsg = TEXT("The given path\r"); + errMsg += _cmdSettingsDir; + errMsg += TEXT("\nvia command line \"-settingsDir=\" is not a valid directory.\rThis argument will be ignored."); + ::MessageBox(NULL, errMsg.c_str(), TEXT("Invalid directory"), MB_OK); + } + else + { + _userPath = _cmdSettingsDir; + _sessionPath = _userPath; // reset session path + } + } //-------------------------------------// // Transparent function for w2k and xp // diff --git a/PowerEditor/src/Parameters.h b/PowerEditor/src/Parameters.h index 6eab38ea..53c4a2d0 100644 --- a/PowerEditor/src/Parameters.h +++ b/PowerEditor/src/Parameters.h @@ -231,6 +231,7 @@ struct CmdLineParams LangType _langType = L_EXTERNAL; generic_string _localizationPath; + generic_string _easterEggName; unsigned char _quoteType = '\0'; int _ghostTypingSpeed = -1; // -1: initial value 1: slow 2: fast 3: speed of light @@ -1678,6 +1679,11 @@ public: void setUseNewStyleSaveDlg(bool v) { _nppGUI._useNewStyleSaveDlg = v; } + + void setCmdSettingsDir(const generic_string& settingsDir) { + _cmdSettingsDir = settingsDir; + }; + DPIManager _dpiManager; generic_string static getSpecialFolderLocation(int folderKind); @@ -1716,7 +1722,7 @@ private: NppGUI _nppGUI; ScintillaViewParams _svp; - Lang *_langList[NB_LANG]; + Lang *_langList[NB_LANG] = {}; int _nbLang = 0; // Recent File History @@ -1756,6 +1762,8 @@ private: bool _isLocal; bool _isx64 = false; // by default 32-bit + generic_string _cmdSettingsDir; + public: void setShortcutDirty() { _isAnyShortcutModified = true; }; void setAdminMode(bool isAdmin) { _isAdminMode = isAdmin; } diff --git a/PowerEditor/src/winmain.cpp b/PowerEditor/src/winmain.cpp index aeec60fb..5cbdfde7 100644 --- a/PowerEditor/src/winmain.cpp +++ b/PowerEditor/src/winmain.cpp @@ -77,21 +77,76 @@ void allowWmCopydataMessages(Notepad_plus_Window& notepad_plus_plus, const NppPa } } -//commandLine should contain path to n++ executable running -ParamVector parseCommandLine(const TCHAR* commandLine) +// parseCommandLine() takes command line arguments part string, cuts arguments by using white space as separater. +// Only white space in double quotes will be kept, such as file path argument or "-settingsDir=" argument (ex.: -settingsDir="c:\my settings\my folder\") +void parseCommandLine(const TCHAR* commandLine, ParamVector& paramVector) { - ParamVector result; - if ( commandLine[0] != '\0' ) + if (!commandLine) + return; + + TCHAR* cmdLine = new TCHAR[lstrlen(commandLine) + 1]; + lstrcpy(cmdLine, commandLine); + + TCHAR* cmdLinePtr = cmdLine; + + bool isInFile = false; + bool isStringInArg = false; + bool isInWhiteSpace = true; + + size_t commandLength = lstrlen(cmdLinePtr); + std::vector args; + for (size_t i = 0; i < commandLength; ++i) { - int numArgs; - LPWSTR* tokenizedCmdLine = CommandLineToArgvW( commandLine, &numArgs ); - if ( tokenizedCmdLine != nullptr ) + switch (cmdLinePtr[i]) { - result.assign( tokenizedCmdLine, tokenizedCmdLine+numArgs ); - LocalFree( tokenizedCmdLine ); + case '\"': //quoted filename, ignore any following whitespace + { + if (!isStringInArg && i > 0 && cmdLinePtr[i - 1] == '=') + { + isStringInArg = true; + } + else if (isStringInArg) + { + isStringInArg = false; + //cmdLinePtr[i] = 0; + } + else if (!isInFile) //" will always be treated as start or end of param, in case the user forgot to add an space + { + args.push_back(cmdLinePtr + i + 1); //add next param(since zero terminated original, no overflow of +1) + isInFile = true; + cmdLinePtr[i] = 0; + } + else if (isInFile) + { + isInFile = false; + //because we dont want to leave in any quotes in the filename, remove them now (with zero terminator) + cmdLinePtr[i] = 0; + } + isInWhiteSpace = false; + } + break; + + case '\t': //also treat tab as whitespace + case ' ': + { + isInWhiteSpace = true; + if (!isInFile && !isStringInArg) + cmdLinePtr[i] = 0; //zap spaces into zero terminators, unless its part of a filename + } + break; + + default: //default TCHAR, if beginning of word, add it + { + if (!isInFile && !isStringInArg && isInWhiteSpace) + { + args.push_back(cmdLinePtr + i); //add next param + isInWhiteSpace = false; + } + } } } - return result; + paramVector.assign(args.begin(), args.end()); + delete[] cmdLine; } // 1. Converts /p to -quickPrint if it exists as the first parameter @@ -265,6 +320,7 @@ const TCHAR FLAG_FUNCLSTEXPORT[] = TEXT("-export=functionList"); const TCHAR FLAG_PRINTANDQUIT[] = TEXT("-quickPrint"); const TCHAR FLAG_NOTEPAD_COMPATIBILITY[] = TEXT("-notepadStyleCmdline"); const TCHAR FLAG_OPEN_FOLDERS_AS_WORKSPACE[] = TEXT("-openFoldersAsWorkspace"); +const TCHAR FLAG_SETTINGS_DIR[] = TEXT("-settingsDir="); void doException(Notepad_plus_Window & notepad_plus_plus) { @@ -360,7 +416,8 @@ PWSTR stripIgnoredParams(ParamVector & params, PWSTR pCmdLine) int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int) { - ParamVector params = parseCommandLine(pCmdLine); + ParamVector params; + parseCommandLine(pCmdLine, params); PWSTR pCmdLineWithoutIgnores = stripIgnoredParams(params, pCmdLine); MiniDumper mdump; //for debugging purposes. @@ -394,6 +451,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int) cmdLineParams._isSessionFile = isInList(FLAG_OPENSESSIONFILE, params); cmdLineParams._isRecursive = isInList(FLAG_RECURSIVE, params); cmdLineParams._openFoldersAsWorkspace = isInList(FLAG_OPEN_FOLDERS_AS_WORKSPACE, params); + cmdLineParams._langType = getLangTypeFromParam(params); cmdLineParams._localizationPath = getLocalizationPathFromParam(params); cmdLineParams._easterEggName = getEasterEggNameFromParam(params, cmdLineParams._quoteType); @@ -406,11 +464,23 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int) cmdLineParams._point.x = getNumberFromParam('x', params, cmdLineParams._isPointXValid); cmdLineParams._point.y = getNumberFromParam('y', params, cmdLineParams._isPointYValid); + NppParameters& nppParameters = NppParameters::getInstance(); + + generic_string path; + if (getParamValFromString(FLAG_SETTINGS_DIR, params, path)) + { + // path could contain double quotes if path contains white space + if (path.c_str()[0] == '"' && path.c_str()[path.length() - 1] == '"') + { + path = path.substr(1, path.length() - 2); + } + nppParameters.setCmdSettingsDir(path); + } if (showHelp) ::MessageBox(NULL, COMMAND_ARG_HELP, TEXT("Notepad++ Command Argument Help"), MB_OK); - NppParameters& nppParameters = NppParameters::getInstance(); + if (cmdLineParams._localizationPath != TEXT("")) {