/* $ 30.07.2001 IS 1. Проверяем правильность параметров. 2. Теперь обработка каталогов не зависит от маски файлов 3. Маска может быть стандартного фаровского вида (со скобками, перечислением и пр.). Может быть несколько масок файлов, разделенных запятыми или точкой с запятой, можно указывать маски исключения, можно заключать маски в кавычки. Короче, все как и должно быть :-) */ void WINAPI FarRecursiveSearch(const wchar_t *InitDir,const wchar_t *Mask,FRSUSERFUNC Func,DWORD Flags,void *Param) { if (Func && InitDir && *InitDir && Mask && *Mask) { CFileMask FMask; if (!FMask.Set(Mask, FMF_SILENT)) return; Flags=Flags&0x000000FF; // только младший байт! ScanTree ScTree(Flags & FRS_RETUPDIR,Flags & FRS_RECUR, Flags & FRS_SCANSYMLINK); FAR_FIND_DATA_EX FindData; string strFullName; ScTree.SetFindPath(InitDir,L"*"); while (ScTree.GetNextName(&FindData,strFullName)) { if (FMask.Compare(FindData.strFileName)) { FAR_FIND_DATA fdata; apiFindDataExToData(&FindData, &fdata); if (!Func(&fdata,strFullName,Param)) { apiFreeFindData(&fdata); break; } apiFreeFindData(&fdata); } } } }
int GetDescriptionWidth(const wchar_t *Name=nullptr,const wchar_t *ShortName=nullptr) { int Width=0; RenumKeyRecord(FTS.Associations,FTS.TypeFmt,FTS.Type0); for (int NumLine=0;; NumLine++) { string strRegKey; strRegKey.Format(FTS.TypeFmt, NumLine); string strMask; if (!GetRegKey(strRegKey,FTS.Mask, strMask, L"")) break; CFileMask FMask; if (!FMask.Set(strMask, FMF_SILENT)) continue; string strDescription; GetRegKey(strRegKey,FTS.Desc,strDescription,L""); int CurWidth; if (!Name) CurWidth = HiStrlen(strDescription); else { if (!FMask.Compare(Name)) continue; string strExpandedDesc = strDescription; SubstFileName(strExpandedDesc,Name,ShortName,nullptr,nullptr,nullptr,nullptr,TRUE); CurWidth = HiStrlen(strExpandedDesc); } if (CurWidth>Width) Width=CurWidth; } if (Width>ScrX/2) Width=ScrX/2; return(Width); }
/* $ 06.07.2001 + Используем CFileMask вместо GetCommaWord, этим самым добиваемся того, что можно использовать маски исключения - Убрал непонятный мне запрет на использование маски файлов типа "*.*" (был когда-то, вроде, такой баг-репорт) */ bool ProcessLocalFileTypes(const wchar_t *Name, const wchar_t *ShortName, int Mode, bool AlwaysWaitFinish) { RenumKeyRecord(FTS.Associations,FTS.TypeFmt,FTS.Type0); MenuItemEx TypesMenuItem; VMenu TypesMenu(MSG(MSelectAssocTitle),nullptr,0,ScrY-4); TypesMenu.SetHelp(FTS.Help); TypesMenu.SetFlags(VMENU_WRAPMODE); TypesMenu.SetPosition(-1,-1,0,0); int DizWidth=GetDescriptionWidth(Name, ShortName); int ActualCmdCount=0; // отображаемых ассоциаций в меню CFileMask FMask; // для работы с масками файлов string strCommand, strDescription; int CommandCount=0; for (int I=0;; I++) { strCommand.Clear(); string strRegKey, strMask; strRegKey.Format(FTS.TypeFmt,I); if (!GetRegKey(strRegKey,FTS.Mask,strMask,L"")) break; if (FMask.Set(strMask,FMF_SILENT)) { if (FMask.Compare(Name)) { LPCWSTR Type=nullptr; switch (Mode) { case FILETYPE_EXEC: Type=FTS.Execute; break; case FILETYPE_VIEW: Type=FTS.View; break; case FILETYPE_EDIT: Type=FTS.Edit; break; case FILETYPE_ALTEXEC: Type=FTS.AltExec; break; case FILETYPE_ALTVIEW: Type=FTS.AltView; break; case FILETYPE_ALTEDIT: Type=FTS.AltEdit; break; } DWORD State=GetRegKey(strRegKey,FTS.State,0xffffffff); if (State&(1<<Mode)) { string strNewCommand; GetRegKey(strRegKey,Type,strNewCommand,L""); if (!strNewCommand.IsEmpty()) { strCommand = strNewCommand; GetRegKey(strRegKey,FTS.Desc,strDescription,L""); CommandCount++; } } } if (strCommand.IsEmpty()) continue; } TypesMenuItem.Clear(); string strCommandText = strCommand; SubstFileName(strCommandText,Name,ShortName,nullptr,nullptr,nullptr,nullptr,TRUE); // все "подставлено", теперь проверим условия "if exist" if (!ExtractIfExistCommand(strCommandText)) continue; ActualCmdCount++; string strMenuText; if (DizWidth) { string strTitle; if (!strDescription.IsEmpty()) { strTitle = strDescription; SubstFileName(strTitle, Name,ShortName,nullptr,nullptr,nullptr,nullptr,TRUE); } size_t Pos=0; bool Ampersand=strTitle.Pos(Pos,L'&'); if (DizWidth+Ampersand>ScrX/2 && Ampersand && static_cast<int>(Pos)>DizWidth) Ampersand=false; strMenuText.Format(L"%-*.*s %c ",DizWidth+Ampersand,DizWidth+Ampersand,strTitle.CPtr(),BoxSymbols[BS_V1]); } TruncStr(strCommandText,ScrX-DizWidth-14); strMenuText += strCommandText; TypesMenuItem.strName = strMenuText; TypesMenuItem.SetSelect(!I); TypesMenu.SetUserData(strCommand.CPtr(),0,TypesMenu.AddItem(&TypesMenuItem)); } if (!CommandCount) return false; if (!ActualCmdCount) return true; int ExitCode=0; if (ActualCmdCount>1) { TypesMenu.Process(); ExitCode=TypesMenu.Modal::GetExitCode(); if (ExitCode<0) return true; } int Size=TypesMenu.GetUserDataSize(ExitCode); LPWSTR Command=strCommand.GetBuffer(Size/sizeof(wchar_t)); TypesMenu.GetUserData(Command,Size,ExitCode); strCommand.ReleaseBuffer(Size); string strListName, strAnotherListName; string strShortListName, strAnotherShortListName; int PreserveLFN=SubstFileName(strCommand,Name,ShortName,&strListName,&strAnotherListName, &strShortListName, &strAnotherShortListName); bool ListFileUsed=!strListName.IsEmpty()||!strAnotherListName.IsEmpty()||!strShortListName.IsEmpty()||!strAnotherShortListName.IsEmpty(); // Снова все "подставлено", теперь проверим условия "if exist" if (ExtractIfExistCommand(strCommand)) { PreserveLongName PreserveName(ShortName,PreserveLFN); RemoveExternalSpaces(strCommand); if (!strCommand.IsEmpty()) { bool isSilent=(strCommand.At(0)==L'@'); if (isSilent) { strCommand.LShift(1); } ProcessOSAliases(strCommand); if (!isSilent) { CtrlObject->CmdLine->ExecString(strCommand,AlwaysWaitFinish, false, false, ListFileUsed); if (!(Opt.ExcludeCmdHistory&EXCLUDECMDHISTORY_NOTFARASS) && !AlwaysWaitFinish) //AN CtrlObject->CmdHistory->AddToHistory(strCommand); } else { #if 1 SaveScreen SaveScr; CtrlObject->Cp()->LeftPanel->CloseFile(); CtrlObject->Cp()->RightPanel->CloseFile(); Execute(strCommand,AlwaysWaitFinish, 0, 0, 0, ListFileUsed, true); #else // здесь была бага с прорисовкой (и... вывод данных // на команду "@type !@!" пропадал с экрана) // сделаем по аналогии с CommandLine::CmdExecute() { RedrawDesktop RdrwDesktop(TRUE); Execute(strCommand,AlwaysWaitFinish, 0, 0, 0, ListFileUsed); ScrollScreen(1); // обязательно, иначе деструктор RedrawDesktop // проредравив экран забьет последнюю строку вывода. } CtrlObject->Cp()->LeftPanel->UpdateIfChanged(UIC_UPDATE_FORCE); CtrlObject->Cp()->RightPanel->UpdateIfChanged(UIC_UPDATE_FORCE); CtrlObject->Cp()->Redraw(); #endif } if (FrameManager->GetCurrentFrame()->GetType()==MODALTYPE_VIEWER) { TypesMenu.ResetCursor(); } } } if (!strListName.IsEmpty()) apiDeleteFile(strListName); if (!strAnotherListName.IsEmpty()) apiDeleteFile(strAnotherListName); if (!strShortListName.IsEmpty()) apiDeleteFile(strShortListName); if (!strAnotherShortListName.IsEmpty()) apiDeleteFile(strAnotherShortListName); return true; }