From 74d39b1cec6dd0995ce41f3d860539f24cb34a9e Mon Sep 17 00:00:00 2001 From: Silent Date: Mon, 2 Jul 2018 17:24:39 +0200 Subject: [PATCH] Greatly simplify commandline parsing --- PowerEditor/src/winmain.cpp | 123 ++++-------------------------------- 1 file changed, 13 insertions(+), 110 deletions(-) diff --git a/PowerEditor/src/winmain.cpp b/PowerEditor/src/winmain.cpp index 6c44ea6bb..044d6c569 100644 --- a/PowerEditor/src/winmain.cpp +++ b/PowerEditor/src/winmain.cpp @@ -76,122 +76,27 @@ void allowWmCopydataMessages(Notepad_plus_Window& notepad_plus_plus, const NppPa } } - -bool checkSingleFile(const TCHAR *commandLine) -{ - if (!commandLine || commandLine[0] == TEXT('\0')) - return false; - - TCHAR fullpath[MAX_PATH] = {0}; - const DWORD fullpathResult = ::GetFullPathName(commandLine, MAX_PATH, fullpath, NULL); - - if (fullpathResult == 0) - return false; - - if (fullpathResult > MAX_PATH) - return false; - - if (::PathFileExists(fullpath)) - return true; - - return false; -} - //commandLine should contain path to n++ executable running -void parseCommandLine(const TCHAR* commandLine, ParamVector& paramVector) +ParamVector parseCommandLine(const TCHAR* commandLine) { - if (!commandLine) - return; - - TCHAR* cmdLine = new TCHAR[lstrlen(commandLine) + 1]; - lstrcpy(cmdLine, commandLine); - - TCHAR* cmdLinePtr = cmdLine; - - //remove the first element, since thats the path the the executable (GetCommandLine does that) - TCHAR stopChar = TEXT(' '); - if (cmdLinePtr[0] == TEXT('\"')) + ParamVector result; + int numArgs = 0; + LPWSTR* tokenizedCmdLine = CommandLineToArgvW( commandLine, &numArgs ); + if ( tokenizedCmdLine != nullptr ) { - stopChar = TEXT('\"'); - ++cmdLinePtr; + result.assign( tokenizedCmdLine+1, tokenizedCmdLine+numArgs ); // If numArgs == 1, it will do nothing + LocalFree( tokenizedCmdLine ); } - //while this is not really DBCS compliant, space and quote are in the lower 127 ASCII range - while(cmdLinePtr[0] && cmdLinePtr[0] != stopChar) - { - ++cmdLinePtr; - } - - // For unknown reason, the following command : - // c:\NppDir>notepad++ - // (without quote) will give string "notepad++\0notepad++\0" - // To avoid the unexpected behaviour we check the end of string before increasing the pointer - if (cmdLinePtr[0] != '\0') - ++cmdLinePtr; //advance past stopChar - - //kill remaining spaces - while(cmdLinePtr[0] == TEXT(' ')) - ++cmdLinePtr; - - bool isFile = checkSingleFile(cmdLinePtr); //if the commandline specifies only a file, open it as such - if (isFile) - { - paramVector.push_back(cmdLinePtr); - delete[] cmdLine; - return; - } - bool isInFile = false; - bool isInWhiteSpace = true; - size_t commandLength = lstrlen(cmdLinePtr); - std::vector args; - for (size_t i = 0; i < commandLength; ++i) - { - switch(cmdLinePtr[i]) - { - case '\"': //quoted filename, ignore any following whitespace - { - 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 = !isInFile; - isInWhiteSpace = false; - //because we dont want to leave in any quotes in the filename, remove them now (with zero terminator) - cmdLinePtr[i] = 0; - } - break; - - case '\t': //also treat tab as whitespace - case ' ': - { - isInWhiteSpace = true; - if (!isInFile) - 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 && isInWhiteSpace) - { - args.push_back(cmdLinePtr+i); //add next param - isInWhiteSpace = false; - } - } - } - } - paramVector.assign(args.begin(), args.end()); - delete [] cmdLine; + return result; } -bool isInList(const TCHAR *token2Find, ParamVector & params) +bool isInList(const TCHAR *token2Find, ParamVector& params, bool eraseArg = true) { - size_t nbItems = params.size(); - - for (size_t i = 0; i < nbItems; ++i) + for (auto it = params.begin(); it != params.end(); ++it) { - if (!lstrcmp(token2Find, params.at(i).c_str())) + if (lstrcmp(token2Find, it->c_str()) == 0) { - params.erase(params.begin() + i); + if (eraseArg) params.erase(it); return true; } } @@ -352,9 +257,7 @@ void doException(Notepad_plus_Window & notepad_plus_plus) int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int) { - LPTSTR cmdLine = ::GetCommandLine(); - ParamVector params; - parseCommandLine(cmdLine, params); + ParamVector params = parseCommandLine(::GetCommandLine()); MiniDumper mdump; //for debugging purposes.