void catFN(wchar_t *text, int& pos, const csWString& filename, const UINT cmd) { const int len = filename.length(); const int tag = filename.lastIndexOf(L'\\'); const int tagPos = tag < 0 ? 0 : tag+1; if( cmd != Cmd_List && tagPos > 0 ) { csStringNCpy(&text[pos], filename.c_str(), tagPos); pos += tagPos; } // QUESTION: What to do in case of missing '\\'? if( cmd == Cmd_ListWithPathTabular ) { text[pos++] = L'\t'; } csStringNCpy(&text[pos], &filename[tagPos], len-tagPos); pos += len - tagPos; if( csIsDirectory(filename.c_str()) ) { text[pos++] = L'\\'; } text[pos++] = L'\r'; text[pos++] = L'\n'; }
int lenFN(const csWString& filename, const UINT cmd) { int size = 0; const int len = filename.length(); const int tag = filename.lastIndexOf(L'\\'); const int tagPos = tag < 0 || cmd != Cmd_List ? 0 : tag+1; size += len - tagPos; if( cmd == Cmd_ListWithPathTabular ) { size++; // separating '\t' } if( csIsDirectory(filename.c_str()) ) { size++; // trailing '\\' } size += 2; // "\r\n" return size; }
bool executeCommand(const UINT cmd, const csWStringList& files) { const csWString parallel = regReadParallel(); const DWORD parallelCount = regReadParallelCount(); const bool hasParallel = !parallel.empty() && parallelCount > 1; const DWORD flags = regReadFlags(); const bool isBatch = testFlags(flags, CMD_FLAG_BATCH); const bool isParallel = testFlags(flags, CMD_FLAG_PARALLEL) && hasParallel; const bool isUnc = testFlags(flags, CMD_FLAG_UNC) && cmd != Cmd_List; const bool isUnix = testFlags(flags, CMD_FLAG_UNIX); const csWString scriptPath = regReadScriptsPath(); const csWStringList scripts = regReadScripts(); if( cmd == Cmd_List || cmd == Cmd_ListWithPath || cmd == Cmd_ListWithPathTabular ) { int size = 0; for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) { wchar_t *uncName = 0; if( isUnc && (uncName = resolveUNC(it->c_str())) != 0 ) { size += lenFN(csWString(uncName), cmd); delete[] uncName; } else { size += lenFN(*it, cmd); } } wchar_t *text = new wchar_t[size+1]; if( text == 0 ) { return false; } int pos = 0; for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) { wchar_t *uncName = 0; if( isUnc && (uncName = resolveUNC(it->c_str())) != 0 ) { catFN(text, pos, csWString(uncName), cmd); delete[] uncName; } else { catFN(text, pos, *it, cmd); } } text[size] = L'\0'; if( files.size() == 1 ) { // Overwrite trailing <CR><LF> text[size-1] = text[size-2] = L'\0'; } if( isUnix ) { replace(text, size, L'\\', L'/'); } setClipboardText(text); delete[] text; return true; } else if( cmd == Cmd_CreateSymbolicLink ) { csWString symLink; IFileSaveDialog *saveDialog = NULL; HRESULT hr = CoCreateInstance(CLSID_FileSaveDialog, NULL, CLSCTX_INPROC_SERVER, IID_IFileSaveDialog, (LPVOID*)&saveDialog); if( hr == S_OK ) { saveDialog->SetTitle(L"Create symbolic link"); const int index = files.front().lastIndexOf(L'\\'); if( index >= 0 ) { const csWString path = files.front().mid(0, index); const csWString name = files.front().mid(index+1); PIDLIST_ABSOLUTE pidl = NULL; SHParseDisplayName(path.c_str(), NULL, &pidl, 0, NULL); if( pidl != NULL ) { IShellItem *item = NULL; SHCreateItemFromIDList(pidl, IID_IShellItem, (LPVOID*)&item); if( item != NULL ) { saveDialog->SetFolder(item); item->Release(); } CoTaskMemFree(pidl); } saveDialog->SetFileName(name.c_str()); } const COMDLG_FILTERSPEC filterSpec = { L"All files", L"*.*" }; saveDialog->SetFileTypes(1, &filterSpec); const FILEOPENDIALOGOPTIONS opts = FOS_OVERWRITEPROMPT | FOS_FORCEFILESYSTEM | FOS_PATHMUSTEXIST | FOS_CREATEPROMPT | FOS_NOREADONLYRETURN | FOS_NODEREFERENCELINKS | FOS_DONTADDTORECENT; saveDialog->SetOptions(opts); if( saveDialog->Show(NULL) == S_OK ) { IShellItem *item = NULL; if( saveDialog->GetResult(&item) == S_OK ) { wchar_t *filename = NULL; if( item->GetDisplayName(SIGDN_FILESYSPATH, &filename) == S_OK ) { symLink = filename; CoTaskMemFree(filename); } item->Release(); } } saveDialog->Release(); } if( !symLink.empty() ) { if( csFileExists(symLink.c_str()) ) { MessageBoxW(NULL, L"Symbolic link target already exists!", L"Error", MB_OK | MB_ICONERROR); return false; } const DWORD linkFlags = csIsDirectory(files.front().c_str()) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0; if( CreateSymbolicLinkW(symLink.c_str(), files.front().c_str(), linkFlags) == 0 ) { const DWORD lastError = GetLastError(); csWString msg(L"ERROR(0x"); msg += csWString::number(lastError, 16); msg += L"): "; msg += formatError(lastError); MessageBoxW(NULL, msg.c_str(), L"Error", MB_OK | MB_ICONERROR); return false; } } return true; } else if( cmd == Cmd_CheckBatchProcessing ) { regWriteFlags(flags ^ CMD_FLAG_BATCH); return true; } else if( cmd == Cmd_CheckParallelExecution ) { regWriteFlags(flags ^ CMD_FLAG_PARALLEL); return true; } else if( cmd == Cmd_CheckResolveUncPaths ) { regWriteFlags(flags ^ CMD_FLAG_UNC); return true; } else if( cmd == Cmd_CheckUnixPathSeparators ) { regWriteFlags(flags ^ CMD_FLAG_UNIX); return true; } else if( Cmd_ExecuteScripts <= cmd && cmd < Cmd_ExecuteScripts+scripts.size() ) { csWString script(scriptPath + L"\\"); UINT i = 0; for(csWStringList::const_iterator it = scripts.begin(); it != scripts.end(); it++) { if( i == cmd-Cmd_ExecuteScripts ) { script += *it; break; } i++; } if( isParallel ) { csWStringList args(files); args.push_front(script); args.push_front(csWString::number(parallelCount)); ShellExecuteW(NULL, L"open", parallel.c_str(), joinFileNames(args).c_str(), NULL, SW_SHOWNORMAL); } else { // DO NOT use parallelizer if( isBatch ) { const csWString args = joinFileNames(files); ShellExecuteW(NULL, L"open", script.c_str(), args.c_str(), NULL, SW_SHOWNORMAL); } else { // NO batch processing for(csWStringList::const_iterator it = files.begin(); it != files.end(); it++) { ShellExecuteW(NULL, L"open", script.c_str(), quoteFileName(*it).c_str(), NULL, SW_SHOWNORMAL); } } } return true; } return false; }