int WINAPI FarMkLink(const wchar_t *Src,const wchar_t *Dest,DWORD Flags) { int Result=0; if (Src && *Src && Dest && *Dest) { int Op=Flags&0xFFFF; switch (Op) { case FLINK_HARDLINK: Result=MkHardLink(Src,Dest); break; case FLINK_JUNCTION: case FLINK_VOLMOUNT: case FLINK_SYMLINKFILE: case FLINK_SYMLINKDIR: ReparsePointTypes LinkType=RP_JUNCTION; switch (Op) { case FLINK_VOLMOUNT: LinkType=RP_VOLMOUNT; break; case FLINK_SYMLINK: LinkType=RP_SYMLINK; break; case FLINK_SYMLINKFILE: LinkType=RP_SYMLINKFILE; break; case FLINK_SYMLINKDIR: LinkType=RP_SYMLINKDIR; break; } Result=MkSymLink(Src,Dest,LinkType,(Flags&FLINK_SHOWERRMSG?0:FCOPY_NOSHOWMSGLINK)); } } if (Result && !(Flags&FLINK_DONOTUPDATEPANEL)) ShellUpdatePanels(nullptr,FALSE); return Result; }
void UserMenu::ProcessUserMenu(bool ChoiceMenuType) { // Путь к текущему каталогу с файлом LocalMenuFileName string strMenuFilePath; CtrlObject->CmdLine->GetCurDir(strMenuFilePath); // по умолчанию меню - это FarMenu.ini MenuMode = MM_LOCAL; MenuModified = MenuNeedRefresh = false; if (ChoiceMenuType) { int EditChoice=Message(0,3,MSG(MUserMenuTitle),MSG(MChooseMenuType),MSG(MChooseMenuMain),MSG(MChooseMenuLocal),MSG(MCancel)); if (EditChoice<0 || EditChoice==2) return; if (!EditChoice) { MenuMode = MM_GLOBAL; strMenuFilePath = Opt.GlobalUserMenuDir; } } // основной цикл обработки bool FirstRun=true; int ExitCode = 0; while ((ExitCode != EC_CLOSE_LEVEL) && (ExitCode != EC_CLOSE_MENU) && (ExitCode != EC_COMMAND_SELECTED)) { string strMenuFileFullPath = strMenuFilePath; AddEndSlash(strMenuFileFullPath); strMenuFileFullPath += LocalMenuFileName; Menu.Clear(); // Пытаемся открыть файл на локальном диске File MenuFile; bool FileOpened = PathCanHoldRegularFile(strMenuFilePath) ? MenuFile.Open(strMenuFileFullPath,GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING) : false; if (FileOpened) { GetFileString GetStr(MenuFile); MenuFileToList(&Menu, MenuFile, GetStr); MenuFile.Close(); } else if (MenuMode != MM_USER) { // Файл не открылся. Смотрим дальше. if (MenuMode == MM_GLOBAL) // был в %FARHOME%? { MenuMode = MM_USER; strMenuFilePath = Opt.ProfilePath; continue; } else if (!ChoiceMenuType) { if (!FirstRun) { // подымаемся выше... if(!IsRootPath(strMenuFilePath)) { size_t pos; if (FindLastSlash(pos,strMenuFilePath)) { strMenuFilePath.SetLength(pos--); continue; } } } FirstRun = false; MenuMode = MM_GLOBAL; strMenuFilePath = Opt.GlobalUserMenuDir; continue; } } int PrevMacroMode=CtrlObject->Macro.GetMode(); int _CurrentFrame=FrameManager->GetCurrentFrame()->GetType(); CtrlObject->Macro.SetMode(MACRO_USERMENU); // вызываем меню ExitCode=ProcessSingleMenu(&Menu, 0, &Menu, strMenuFileFullPath); if (_CurrentFrame == FrameManager->GetCurrentFrame()->GetType()) //??? CtrlObject->Macro.SetMode(PrevMacroMode); // ...запишем изменения обратно в файл SaveMenu(strMenuFileFullPath); // что было после вызова меню? switch (ExitCode) { // Показать меню родительского каталога case EC_PARENT_MENU: { if (MenuMode == MM_LOCAL) { if(!IsRootPath(strMenuFilePath)) { size_t pos; if (FindLastSlash(pos,strMenuFilePath)) { strMenuFilePath.SetLength(pos--); continue; } } MenuMode = MM_GLOBAL; strMenuFilePath = Opt.GlobalUserMenuDir; } else { MenuMode = MM_USER; strMenuFilePath = Opt.ProfilePath; } break; } // Показать главное меню case EC_MAIN_MENU: { // $ 14.07.2000 VVM: Shift+F2 переключает Главное меню/локальное в цикле switch (MenuMode) { case MM_LOCAL: MenuMode = MM_GLOBAL; strMenuFilePath = Opt.GlobalUserMenuDir; break; case MM_GLOBAL: MenuMode = MM_USER; strMenuFilePath = Opt.ProfilePath; break; default: // MM_USER CtrlObject->CmdLine->GetCurDir(strMenuFilePath); MenuMode=MM_LOCAL; } break; } } } if (FrameManager->IsPanelsActive() && (ExitCode == EC_COMMAND_SELECTED || MenuModified)) ShellUpdatePanels(CtrlObject->Cp()->ActivePanel,FALSE); }
void ShellDelete(Panel *SrcPanel,int Wipe) { ChangePriority ChPriority(Opt.DelThreadPriority); TPreRedrawFuncGuard preRedrawFuncGuard(PR_ShellDeleteMsg); FAR_FIND_DATA_EX FindData; string strDeleteFilesMsg; string strSelName; string strSelShortName; string strDizName; string strFullName; DWORD FileAttr; int SelCount,UpdateDiz; int DizPresent; int Ret; BOOL NeedUpdate=TRUE, NeedSetUpADir=FALSE; int Opt_DeleteToRecycleBin=Opt.DeleteToRecycleBin; /*& 31.05.2001 OT Запретить перерисовку текущего фрейма*/ Frame *FrameFromLaunched=FrameManager->GetCurrentFrame(); FrameFromLaunched->Lock(); DeleteAllFolders=!Opt.Confirm.DeleteFolder; UpdateDiz=(Opt.Diz.UpdateMode==DIZ_UPDATE_ALWAYS || (SrcPanel->IsDizDisplayed() && Opt.Diz.UpdateMode==DIZ_UPDATE_IF_DISPLAYED)); if (!(SelCount=SrcPanel->GetSelCount())) goto done; // Удаление в корзину только для FIXED-дисков { string strRoot; // char FSysNameSrc[NM]; SrcPanel->GetSelName(nullptr,FileAttr); SrcPanel->GetSelName(&strSelName,FileAttr); ConvertNameToFull(strSelName, strRoot); GetPathRoot(strRoot,strRoot); //_SVS(SysLog(L"Del: SelName='%s' Root='%s'",SelName,Root)); if (Opt.DeleteToRecycleBin && FAR_GetDriveType(strRoot) != DRIVE_FIXED) Opt.DeleteToRecycleBin=0; } if (SelCount==1) { SrcPanel->GetSelName(nullptr,FileAttr); SrcPanel->GetSelName(&strSelName,FileAttr); if (TestParentFolderName(strSelName) || strSelName.IsEmpty()) { NeedUpdate=FALSE; goto done; } strDeleteFilesMsg = strSelName; } else { // в зависимости от числа ставим нужное окончание const wchar_t *Ends; wchar_t StrItems[16]; _itow(SelCount,StrItems,10); Ends=MSG(MAskDeleteItemsA); int LenItems=StrLength(StrItems); if (LenItems > 0) { if ((LenItems >= 2 && StrItems[LenItems-2] == L'1') || StrItems[LenItems-1] >= L'5' || StrItems[LenItems-1] == L'0') Ends=MSG(MAskDeleteItemsS); else if (StrItems[LenItems-1] == L'1') Ends=MSG(MAskDeleteItems0); } strDeleteFilesMsg.Format(MSG(MAskDeleteItems),SelCount,Ends); } Ret=1; // Обработка "удаления" линков if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT) && SelCount==1) { string strJuncName; ConvertNameToFull(strSelName,strJuncName); if (GetReparsePointInfo(strJuncName, strJuncName)) // ? SelName ? { NormalizeSymlinkName(strJuncName); //SetMessageHelp(L"DeleteLink"); string strAskDeleteLink=MSG(MAskDeleteLink); DWORD dwAttr=apiGetFileAttributes(strJuncName); if (dwAttr!=INVALID_FILE_ATTRIBUTES) { strAskDeleteLink+=L" "; strAskDeleteLink+=dwAttr&FILE_ATTRIBUTE_DIRECTORY?MSG(MAskDeleteLinkFolder):MSG(MAskDeleteLinkFile); } Ret=Message(0,3,MSG(MDeleteLinkTitle), strDeleteFilesMsg, strAskDeleteLink, strJuncName, MSG(MDeleteLinkDelete),MSG(MDeleteLinkUnlink),MSG(MCancel)); if (Ret == 1) { ConvertNameToFull(strSelName, strJuncName); if (Opt.Confirm.Delete) { ; // ;-% } if ((NeedSetUpADir=CheckUpdateAnotherPanel(SrcPanel,strSelName)) != -1) //JuncName? { DeleteReparsePoint(strJuncName); ShellUpdatePanels(SrcPanel,NeedSetUpADir); } goto done; } if (Ret ) goto done; } } if (Ret && (Opt.Confirm.Delete || SelCount>1 || (FileAttr & FILE_ATTRIBUTE_DIRECTORY))) { const wchar_t *DelMsg; const wchar_t *TitleMsg=MSG(Wipe?MDeleteWipeTitle:MDeleteTitle); /* $ 05.01.2001 IS ! Косметика в сообщениях - разные сообщения в зависимости от того, какие и сколько элементов выделено. */ BOOL folder=(FileAttr & FILE_ATTRIBUTE_DIRECTORY); if (SelCount==1) { if (Wipe && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) DelMsg=MSG(folder?MAskWipeFolder:MAskWipeFile); else { if (Opt.DeleteToRecycleBin && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) DelMsg=MSG(folder?MAskDeleteRecycleFolder:MAskDeleteRecycleFile); else DelMsg=MSG(folder?MAskDeleteFolder:MAskDeleteFile); } } else { if (Wipe && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) { DelMsg=MSG(MAskWipe); TitleMsg=MSG(MDeleteWipeTitle); } else if (Opt.DeleteToRecycleBin && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) DelMsg=MSG(MAskDeleteRecycle); else DelMsg=MSG(MAskDelete); } SetMessageHelp(L"DeleteFile"); if (Message(0,2,TitleMsg,DelMsg,strDeleteFilesMsg,MSG(Wipe?MDeleteWipe:Opt.DeleteToRecycleBin?MDeleteRecycle:MDelete),MSG(MCancel))) { NeedUpdate=FALSE; goto done; } } if (Opt.Confirm.Delete && SelCount>1) { //SaveScreen SaveScr; SetCursorType(FALSE,0); SetMessageHelp(L"DeleteFile"); if (Message(MSG_WARNING,2,MSG(Wipe?MWipeFilesTitle:MDeleteFilesTitle),MSG(Wipe?MAskWipe:MAskDelete), strDeleteFilesMsg,MSG(MDeleteFileAll),MSG(MDeleteFileCancel))) { NeedUpdate=FALSE; goto done; } } if (UpdateDiz) SrcPanel->ReadDiz(); SrcPanel->GetDizName(strDizName); DizPresent=(!strDizName.IsEmpty() && apiGetFileAttributes(strDizName)!=INVALID_FILE_ATTRIBUTES); DeleteTitle = new ConsoleTitle(MSG(MDeletingTitle)); if ((NeedSetUpADir=CheckUpdateAnotherPanel(SrcPanel,strSelName)) == -1) goto done; if (SrcPanel->GetType()==TREE_PANEL) FarChDir(L"\\"); { TaskBar TB; wakeful W; bool Cancel=false; //SaveScreen SaveScr; SetCursorType(FALSE,0); ReadOnlyDeleteMode=-1; SkipMode=-1; SkipWipeMode=-1; SkipFoldersMode=-1; ULONG ItemsCount=0; ProcessedItems=0; if (Opt.DelOpt.DelShowTotal) { SrcPanel->GetSelName(nullptr,FileAttr); DWORD StartTime=GetTickCount(); bool FirstTime=true; while (SrcPanel->GetSelName(&strSelName,FileAttr,&strSelShortName) && !Cancel) { if (!(FileAttr&FILE_ATTRIBUTE_REPARSE_POINT)) { if (FileAttr&FILE_ATTRIBUTE_DIRECTORY) { DWORD CurTime=GetTickCount(); if (CurTime-StartTime>RedrawTimeout || FirstTime) { StartTime=CurTime; FirstTime=false; if (CheckForEscSilent() && ConfirmAbortOp()) { Cancel=true; break; } ShellDeleteMsg(strSelName,Wipe,-1); } ULONG CurrentFileCount,CurrentDirCount,ClusterSize; UINT64 FileSize,CompressedFileSize,RealSize; if (GetDirInfo(nullptr,strSelName,CurrentDirCount,CurrentFileCount,FileSize,CompressedFileSize,RealSize,ClusterSize,-1,nullptr,0)>0) { ItemsCount+=CurrentFileCount+CurrentDirCount+1; } else { Cancel=true; } } else { ItemsCount++; } } } } SrcPanel->GetSelName(nullptr,FileAttr); DWORD StartTime=GetTickCount(); bool FirstTime=true; while (SrcPanel->GetSelName(&strSelName,FileAttr,&strSelShortName) && !Cancel) { int Length=(int)strSelName.GetLength(); if (!Length || (strSelName.At(0)==L'\\' && Length<2) || (strSelName.At(1)==L':' && Length<4)) continue; DWORD CurTime=GetTickCount(); if (CurTime-StartTime>RedrawTimeout || FirstTime) { StartTime=CurTime; FirstTime=false; if (CheckForEscSilent() && ConfirmAbortOp()) { Cancel=true; break; } ShellDeleteMsg(strSelName,Wipe,Opt.DelOpt.DelShowTotal?(ItemsCount?(ProcessedItems*100/ItemsCount):0):-1); } if (FileAttr & FILE_ATTRIBUTE_DIRECTORY) { if (!DeleteAllFolders) { ConvertNameToFull(strSelName, strFullName); if (TestFolder(strFullName) == TSTFLD_NOTEMPTY) { int MsgCode=0; // для symlink`а не нужно подтверждение if (!(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) MsgCode=Message(MSG_WARNING,4,MSG(Wipe?MWipeFolderTitle:MDeleteFolderTitle), MSG(Wipe?MWipeFolderConfirm:MDeleteFolderConfirm),strFullName, MSG(Wipe?MDeleteFileWipe:MDeleteFileDelete),MSG(MDeleteFileAll), MSG(MDeleteFileSkip),MSG(MDeleteFileCancel)); if (MsgCode<0 || MsgCode==3) { NeedSetUpADir=FALSE; break; } if (MsgCode==1) DeleteAllFolders=1; if (MsgCode==2) continue; } } bool DirSymLink=(FileAttr&FILE_ATTRIBUTE_DIRECTORY && FileAttr&FILE_ATTRIBUTE_REPARSE_POINT); if (!DirSymLink && (!Opt.DeleteToRecycleBin || Wipe)) { string strFullName; ScanTree ScTree(TRUE,TRUE,FALSE); string strSelFullName; if (IsAbsolutePath(strSelName)) { strSelFullName=strSelName; } else { SrcPanel->GetCurDir(strSelFullName); AddEndSlash(strSelFullName); strSelFullName+=strSelName; } ScTree.SetFindPath(strSelFullName,L"*", 0); DWORD StartTime=GetTickCount(); while (ScTree.GetNextName(&FindData,strFullName)) { DWORD CurTime=GetTickCount(); if (CurTime-StartTime>RedrawTimeout) { StartTime=CurTime; if (CheckForEscSilent()) { int AbortOp = ConfirmAbortOp(); if (AbortOp) { Cancel=true; break; } } ShellDeleteMsg(strFullName,Wipe,Opt.DelOpt.DelShowTotal?(ItemsCount?(ProcessedItems*100/ItemsCount):0):-1); } if (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { if (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { if (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) apiSetFileAttributes(strFullName,FILE_ATTRIBUTE_NORMAL); int MsgCode=ERemoveDirectory(strFullName,Wipe); if (MsgCode==DELETE_CANCEL) { Cancel=true; break; } else if (MsgCode==DELETE_SKIP) { ScTree.SkipDir(); continue; } TreeList::DelTreeName(strFullName); if (UpdateDiz) SrcPanel->DeleteDiz(strFullName,strSelShortName); continue; } if (!DeleteAllFolders && !ScTree.IsDirSearchDone() && TestFolder(strFullName) == TSTFLD_NOTEMPTY) { int MsgCode=Message(MSG_WARNING,4,MSG(Wipe?MWipeFolderTitle:MDeleteFolderTitle), MSG(Wipe?MWipeFolderConfirm:MDeleteFolderConfirm),strFullName, MSG(Wipe?MDeleteFileWipe:MDeleteFileDelete),MSG(MDeleteFileAll), MSG(MDeleteFileSkip),MSG(MDeleteFileCancel)); if (MsgCode<0 || MsgCode==3) { Cancel=true; break; } if (MsgCode==1) DeleteAllFolders=1; if (MsgCode==2) { ScTree.SkipDir(); continue; } } if (ScTree.IsDirSearchDone()) { if (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) apiSetFileAttributes(strFullName,FILE_ATTRIBUTE_NORMAL); int MsgCode=ERemoveDirectory(strFullName,Wipe); if (MsgCode==DELETE_CANCEL) { Cancel=true;; break; } else if (MsgCode==DELETE_SKIP) { //ScTree.SkipDir(); continue; } TreeList::DelTreeName(strFullName); } } else { int AskCode=AskDeleteReadOnly(strFullName,FindData.dwFileAttributes,Wipe); if (AskCode==DELETE_CANCEL) { Cancel=true; break; } if (AskCode==DELETE_YES) if (ShellRemoveFile(strFullName,Wipe)==DELETE_CANCEL) { Cancel=true; break; } } } } if (!Cancel) { if (FileAttr & FILE_ATTRIBUTE_READONLY) apiSetFileAttributes(strSelName,FILE_ATTRIBUTE_NORMAL); int DeleteCode; // нефига здесь выделываться, а надо учесть, что удаление // симлинка в корзину чревато потерей оригинала. if (DirSymLink || !Opt.DeleteToRecycleBin || Wipe) { DeleteCode=ERemoveDirectory(strSelName,Wipe); if (DeleteCode==DELETE_CANCEL) break; else if (DeleteCode==DELETE_SUCCESS) { TreeList::DelTreeName(strSelName); if (UpdateDiz) SrcPanel->DeleteDiz(strSelName,strSelShortName); } } else { DeleteCode=RemoveToRecycleBin(strSelName); if (!DeleteCode) Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MError), MSG(MCannotDeleteFolder),strSelName,MSG(MOk)); else { TreeList::DelTreeName(strSelName); if (UpdateDiz) SrcPanel->DeleteDiz(strSelName,strSelShortName); } } } } else { int AskCode=AskDeleteReadOnly(strSelName,FileAttr,Wipe); if (AskCode==DELETE_CANCEL) break; if (AskCode==DELETE_YES) { int DeleteCode=ShellRemoveFile(strSelName,Wipe); if (DeleteCode==DELETE_SUCCESS && UpdateDiz) { SrcPanel->DeleteDiz(strSelName,strSelShortName); } if (DeleteCode==DELETE_CANCEL) break; } } } } if (UpdateDiz) if (DizPresent==(!strDizName.IsEmpty() && apiGetFileAttributes(strDizName)!=INVALID_FILE_ATTRIBUTES)) SrcPanel->FlushDiz(); delete DeleteTitle; done: Opt.DeleteToRecycleBin=Opt_DeleteToRecycleBin; // Разрешить перерисовку фрейма FrameFromLaunched->Unlock(); if (NeedUpdate) { ShellUpdatePanels(SrcPanel,NeedSetUpADir); } }
ShellDelete::ShellDelete(Panel *SrcPanel,bool Wipe): ReadOnlyDeleteMode(-1), m_SkipMode(-1), SkipWipeMode(-1), SkipFoldersMode(-1), ProcessedItems(0) { SCOPED_ACTION(ChangePriority)(Global->Opt->DelThreadPriority); SCOPED_ACTION(TPreRedrawFuncGuard)(std::make_unique<DelPreRedrawItem>()); os::FAR_FIND_DATA FindData; string strDeleteFilesMsg; string strSelName; string strSelShortName; string strDizName; DWORD FileAttr; size_t SelCount; int UpdateDiz; int DizPresent; int Ret; BOOL NeedUpdate=TRUE, NeedSetUpADir=FALSE; bool Opt_DeleteToRecycleBin=Global->Opt->DeleteToRecycleBin; /*& 31.05.2001 OT Запретить перерисовку текущего окна*/ auto WindowFromLaunched = Global->WindowManager->GetCurrentWindow(); WindowFromLaunched->Lock(); bool DeleteAllFolders=!Global->Opt->Confirm.DeleteFolder; UpdateDiz=(Global->Opt->Diz.UpdateMode==DIZ_UPDATE_ALWAYS || (SrcPanel->IsDizDisplayed() && Global->Opt->Diz.UpdateMode==DIZ_UPDATE_IF_DISPLAYED)); SCOPE_EXIT { Global->Opt->DeleteToRecycleBin=Opt_DeleteToRecycleBin; // Разрешить перерисовку окна WindowFromLaunched->Unlock(); if (NeedUpdate) { ShellUpdatePanels(SrcPanel,NeedSetUpADir); } }; if (!(SelCount=SrcPanel->GetSelCount())) return; // Удаление в корзину только для FIXED-дисков { string strRoot; SrcPanel->GetSelName(nullptr,FileAttr); SrcPanel->GetSelName(&strSelName,FileAttr); ConvertNameToFull(strSelName, strRoot); GetPathRoot(strRoot,strRoot); if (Global->Opt->DeleteToRecycleBin && FAR_GetDriveType(strRoot) != DRIVE_FIXED) Global->Opt->DeleteToRecycleBin=0; } if (SelCount==1) { SrcPanel->GetSelName(nullptr,FileAttr); SrcPanel->GetSelName(&strSelName,FileAttr); if (TestParentFolderName(strSelName) || strSelName.empty()) { NeedUpdate=FALSE; return; } strDeleteFilesMsg = strSelName; QuoteLeadingSpace(strDeleteFilesMsg); } else { // в зависимости от числа ставим нужное окончание const wchar_t *Ends; FormatString StrItems; StrItems << SelCount; Ends=MSG(MAskDeleteItemsA); size_t LenItems = StrItems.size(); if (LenItems > 0) { if ((LenItems >= 2 && StrItems[LenItems-2] == L'1') || StrItems[LenItems-1] >= L'5' || StrItems[LenItems-1] == L'0') Ends=MSG(MAskDeleteItemsS); else if (StrItems[LenItems-1] == L'1') Ends=MSG(MAskDeleteItems0); } strDeleteFilesMsg = LangString(MAskDeleteItems) << SelCount << Ends; } Ret=1; // Обработка "удаления" линков if ((FileAttr & FILE_ATTRIBUTE_REPARSE_POINT) && SelCount==1) { string strJuncName; ConvertNameToFull(strSelName,strJuncName); if (GetReparsePointInfo(strJuncName, strJuncName)) // ? SelName ? { NormalizeSymlinkName(strJuncName); string strAskDeleteLink=MSG(MAskDeleteLink); os::fs::file_status Status(strJuncName); if (os::fs::exists(Status)) { strAskDeleteLink+=L" "; strAskDeleteLink += MSG(is_directory(Status)? MAskDeleteLinkFolder : MAskDeleteLinkFile); } Ret=Message(0,2,MSG(MDeleteLinkTitle), strDeleteFilesMsg.data(), strAskDeleteLink.data(), strJuncName.data(), MSG(MDeleteLinkDelete), MSG(MCancel)); if (Ret) return; } } if (Ret && Global->Opt->Confirm.Delete) { LNGID mTitle = Wipe ? MDeleteWipeTitle : MDeleteTitle; LNGID mDText; string tText; LNGID mDBttn = Wipe ? MDeleteWipe : Global->Opt->DeleteToRecycleBin ? MDeleteRecycle : MDelete; bool bHilite = Global->Opt->DelOpt.HighlightSelected; int mshow = std::min(std::max((int)Global->Opt->DelOpt.ShowSelected, 1), ScrY/2); std::vector<string> items; items.push_back(strDeleteFilesMsg); if (SelCount == 1) { bool folder = (FileAttr & FILE_ATTRIBUTE_DIRECTORY) != 0; if (Wipe && !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) mDText = folder ? MAskWipeFolder : MAskWipeFile; else { if (Global->Opt->DeleteToRecycleBin) mDText = folder ? MAskDeleteRecycleFolder : MAskDeleteRecycleFile; else mDText = folder ? MAskDeleteFolder : MAskDeleteFile; } if (bHilite) { string name, sname; SrcPanel->GetCurName(name, sname); QuoteLeadingSpace(name); bHilite = strDeleteFilesMsg != name; } } else { if (Wipe) { mDText = MAskWipe; mTitle = MDeleteWipeTitle; } else mDText = Global->Opt->DeleteToRecycleBin ? MAskDeleteRecycle : MAskDelete; if (mshow > 1) { tText = MSG(mDText) + string(L" ") + strDeleteFilesMsg; items.clear(); DWORD attr; string name; SrcPanel->GetSelName(nullptr, attr); for (size_t i = 0; i < SelCount; ++i) { if (i == (size_t)mshow-1 && i+1 < SelCount) { items.push_back(L"..."); break; } SrcPanel->GetSelName(&name, attr); QuoteLeadingSpace(name); items.push_back(name); } } } intptr_t start_hilite = 0, end_hilite = 0; DialogBuilder Builder(mTitle, nullptr, [&](Dialog* Dlg, intptr_t Msg, intptr_t Param1, void* Param2) -> intptr_t { if (bHilite && Msg == DN_CTLCOLORDLGITEM && Param1 >= start_hilite && Param1 <= end_hilite) { auto Colors = static_cast<FarDialogItemColors*>(Param2); Colors->Colors[0] = Colors->Colors[1]; } return Dlg->DefProc(Msg, Param1, Param2); }); if (tText.empty()) tText = MSG(mDText); Builder.AddText(tText.data())->Flags = DIF_CENTERTEXT; if (bHilite || (mshow > 1 && SelCount > 1)) Builder.AddSeparator(); std::for_each(RANGE(items, i) { TruncStrFromCenter(i, ScrX+1-6*2); auto dx = Builder.AddText(i.data()); dx->Flags = (SelCount <= 1 || mshow <= 1 ? DIF_CENTERTEXT : 0) | DIF_SHOWAMPERSAND; size_t index = Builder.GetLastID(); end_hilite = index; if (!start_hilite) start_hilite = index; });