string Panel::GetTitle() const { if (m_PanelMode == panel_mode::NORMAL_PANEL) return m_ShowShortNames? ConvertNameToShort(m_CurDir) : m_CurDir; OpenPanelInfo Info; GetOpenPanelInfo(&Info); return string(trim(string_view(NullToEmpty(Info.PanelTitle)))); }
/* Используется для запуска внешнего редактора и вьювера */ void ProcessExternal(const wchar_t *Command, const wchar_t *Name, const wchar_t *ShortName, bool AlwaysWaitFinish) { string strListName, strAnotherListName; string strShortListName, strAnotherShortListName; string strFullName, strFullShortName; string strExecStr = Command; string strFullExecStr = Command; { int PreserveLFN=SubstFileName(strExecStr,Name,ShortName,&strListName,&strAnotherListName, &strShortListName, &strAnotherShortListName); bool ListFileUsed=!strListName.IsEmpty()||!strAnotherListName.IsEmpty()||!strShortListName.IsEmpty()||!strAnotherShortListName.IsEmpty(); // Снова все "подставлено", теперь проверим условия "if exist" if (!ExtractIfExistCommand(strExecStr)) return; PreserveLongName PreserveName(ShortName,PreserveLFN); ConvertNameToFull(Name,strFullName); ConvertNameToShort(strFullName,strFullShortName); //BUGBUGBUGBUGBUGBUG !!! Same ListNames!!! SubstFileName(strFullExecStr,strFullName,strFullShortName,&strListName,&strAnotherListName, &strShortListName, &strAnotherShortListName); // Снова все "подставлено", теперь проверим условия "if exist" if (!ExtractIfExistCommand(strFullExecStr)) return; CtrlObject->ViewHistory->AddToHistory(strFullExecStr,(AlwaysWaitFinish&1)+2); if (strExecStr.At(0) != L'@') CtrlObject->CmdLine->ExecString(strExecStr,AlwaysWaitFinish, 0, 0, ListFileUsed, true); else { SaveScreen SaveScr; CtrlObject->Cp()->LeftPanel->CloseFile(); CtrlObject->Cp()->RightPanel->CloseFile(); Execute(strExecStr.CPtr()+1,AlwaysWaitFinish, 0, 0, 0, ListFileUsed); } } if (!strListName.IsEmpty()) apiDeleteFile(strListName); if (!strAnotherListName.IsEmpty()) apiDeleteFile(strAnotherListName); if (!strShortListName.IsEmpty()) apiDeleteFile(strShortListName); if (!strAnotherShortListName.IsEmpty()) apiDeleteFile(strAnotherShortListName); }
string Panel::CreateFullPathName(string_view const Name, bool const Directory, bool const UNC, bool const ShortNameAsIs) const { auto FullName = FindSlash(Name) == string::npos? ConvertNameToFull(Name) : string(Name); if (m_ShowShortNames && ShortNameAsIs) FullName = ConvertNameToShort(FullName); /* $ 29.01.2001 VVM + По CTRL+ALT+F в командную строку сбрасывается UNC-имя текущего файла. */ if (UNC) FullName = ConvertNameToUNC(FullName); // $ 20.10.2000 SVS Сделаем фичу Ctrl-F опциональной! if (Global->Opt->PanelCtrlFRule) { /* $ 13.10.2000 tran по Ctrl-f имя должно отвечать условиям на панели */ if (m_ViewSettings.Flags&PVS_FOLDERUPPERCASE) { if (Directory) { inplace::upper(FullName); } else { inplace::upper(FullName, 0, FindLastSlash(FullName)); } } if ((m_ViewSettings.Flags&PVS_FILEUPPERTOLOWERCASE) && !Directory) { const auto pos = FindLastSlash(FullName); if (pos != string::npos && !IsCaseMixed(string_view(FullName).substr(pos))) { inplace::lower(FullName, pos); } } if ((m_ViewSettings.Flags&PVS_FILELOWERCASE) && !Directory) { const auto pos = FindLastSlash(FullName); if (pos != string::npos) { inplace::lower(FullName, pos); } } } return FullName; }
int _MakePath1(DWORD Key, string &strPathName, const wchar_t *Param2,int ShortNameAsIs) { int RetCode=FALSE; int NeedRealName=FALSE; strPathName.clear(); switch (Key) { case KEY_CTRLALTBRACKET: // Вставить сетевое (UNC) путь из левой панели case KEY_RCTRLRALTBRACKET: case KEY_CTRLRALTBRACKET: case KEY_RCTRLALTBRACKET: case KEY_CTRLALTBACKBRACKET: // Вставить сетевое (UNC) путь из правой панели case KEY_RCTRLRALTBACKBRACKET: case KEY_CTRLRALTBACKBRACKET: case KEY_RCTRLALTBACKBRACKET: case KEY_ALTSHIFTBRACKET: // Вставить сетевое (UNC) путь из активной панели case KEY_RALTSHIFTBRACKET: case KEY_ALTSHIFTBACKBRACKET: // Вставить сетевое (UNC) путь из пассивной панели case KEY_RALTSHIFTBACKBRACKET: NeedRealName=TRUE; case KEY_CTRLBRACKET: // Вставить путь из левой панели case KEY_RCTRLBRACKET: case KEY_CTRLBACKBRACKET: // Вставить путь из правой панели case KEY_RCTRLBACKBRACKET: case KEY_CTRLSHIFTBRACKET: // Вставить путь из активной панели case KEY_RCTRLSHIFTBRACKET: case KEY_CTRLSHIFTBACKBRACKET: // Вставить путь из пассивной панели case KEY_RCTRLSHIFTBACKBRACKET: case KEY_CTRLSHIFTNUMENTER: // Текущий файл с пасс.панели case KEY_RCTRLSHIFTNUMENTER: case KEY_SHIFTNUMENTER: // Текущий файл с актив.панели case KEY_CTRLSHIFTENTER: // Текущий файл с пасс.панели case KEY_RCTRLSHIFTENTER: case KEY_SHIFTENTER: // Текущий файл с актив.панели { Panel *SrcPanel=nullptr; FilePanels *Cp=Global->CtrlObject->Cp(); switch (Key) { case KEY_CTRLALTBRACKET: case KEY_RCTRLRALTBRACKET: case KEY_CTRLRALTBRACKET: case KEY_RCTRLALTBRACKET: case KEY_CTRLBRACKET: case KEY_RCTRLBRACKET: SrcPanel=Cp->LeftPanel; break; case KEY_CTRLALTBACKBRACKET: case KEY_RCTRLRALTBACKBRACKET: case KEY_CTRLRALTBACKBRACKET: case KEY_RCTRLALTBACKBRACKET: case KEY_CTRLBACKBRACKET: case KEY_RCTRLBACKBRACKET: SrcPanel=Cp->RightPanel; break; case KEY_SHIFTNUMENTER: case KEY_SHIFTENTER: case KEY_ALTSHIFTBRACKET: case KEY_RALTSHIFTBRACKET: case KEY_CTRLSHIFTBRACKET: case KEY_RCTRLSHIFTBRACKET: SrcPanel=Cp->ActivePanel(); break; case KEY_CTRLSHIFTNUMENTER: case KEY_RCTRLSHIFTNUMENTER: case KEY_CTRLSHIFTENTER: case KEY_RCTRLSHIFTENTER: case KEY_ALTSHIFTBACKBRACKET: case KEY_RALTSHIFTBACKBRACKET: case KEY_CTRLSHIFTBACKBRACKET: case KEY_RCTRLSHIFTBACKBRACKET: SrcPanel=Cp->PassivePanel(); break; } if (SrcPanel) { if (Key == KEY_SHIFTENTER || Key == KEY_CTRLSHIFTENTER || Key == KEY_RCTRLSHIFTENTER || Key == KEY_SHIFTNUMENTER || Key == KEY_CTRLSHIFTNUMENTER || Key == KEY_RCTRLSHIFTNUMENTER) { string strShortFileName; SrcPanel->GetCurName(strPathName,strShortFileName); if (SrcPanel->GetShowShortNamesMode()) // учтем короткость имен :-) strPathName = strShortFileName; } else { if (!(SrcPanel->GetType()==FILE_PANEL || SrcPanel->GetType()==TREE_PANEL)) return FALSE; strPathName = SrcPanel->GetCurDir(); if (SrcPanel->GetMode()!=PLUGIN_PANEL) { if (NeedRealName) SrcPanel->CreateFullPathName(strPathName, strPathName, FILE_ATTRIBUTE_DIRECTORY, strPathName, TRUE, ShortNameAsIs); if (SrcPanel->GetShowShortNamesMode() && ShortNameAsIs) ConvertNameToShort(strPathName,strPathName); } else { FileList *SrcFilePanel=(FileList *)SrcPanel; OpenPanelInfo Info; Global->CtrlObject->Plugins->GetOpenPanelInfo(SrcFilePanel->GetPluginHandle(),&Info); FileList::AddPluginPrefix(SrcFilePanel,strPathName); if (Info.HostFile && *Info.HostFile) { strPathName += Info.HostFile; strPathName += L"/"; } strPathName += NullToEmpty(Info.CurDir); } AddEndSlash(strPathName); } if (Global->Opt->QuotedName"EDNAME_INSERT) QuoteSpace(strPathName); if (Param2) strPathName += Param2; RetCode=TRUE; } } break; } return RetCode; }
static const wchar_t *_SubstFileName(const wchar_t *CurStr,TSubstData *PSubstData,string &strOut) { // рассмотрим переключатели активности/пассивности панели. if (!StrCmpN(CurStr,L"!#",2)) { CurStr+=2; PSubstData->PassivePanel=TRUE; return CurStr; } if (!StrCmpN(CurStr,L"!^",2)) { CurStr+=2; PSubstData->PassivePanel=FALSE; return CurStr; } // !! символ '!' if (!StrCmpN(CurStr,L"!!",2) && CurStr[2] != L'?') { strOut += L"!"; CurStr+=2; return CurStr; } // !.! Длинное имя файла с расширением if (!StrCmpN(CurStr,L"!.!",3) && CurStr[3] != L'?') { if (PSubstData->PassivePanel) strOut += PSubstData->strAnotherName; else strOut += PSubstData->Name; CurStr+=3; return CurStr; } // !~ Короткое имя файла без расширения if (!StrCmpN(CurStr,L"!~",2)) { strOut += PSubstData->PassivePanel ? PSubstData->strAnotherShortNameOnly : PSubstData->strShortNameOnly; CurStr+=2; return CurStr; } // !` Длинное расширение файла без имени if (!StrCmpN(CurStr,L"!`",2)) { const wchar_t *Ext; if (CurStr[2] == L'~') { Ext=wcsrchr((PSubstData->PassivePanel ? PSubstData->strAnotherShortName.CPtr():PSubstData->ShortName),L'.'); CurStr+=3; } else { Ext=wcsrchr((PSubstData->PassivePanel ? PSubstData->strAnotherName.CPtr():PSubstData->Name),L'.'); CurStr+=2; } if (Ext && *Ext) strOut += ++Ext; return CurStr; } // !& !&~ список файлов разделенных пробелом. if ((!StrCmpN(CurStr,L"!&~",3) && CurStr[3] != L'?') || (!StrCmpN(CurStr,L"!&",2) && CurStr[2] != L'?')) { string strFileNameL, strShortNameL; Panel *WPanel=PSubstData->PassivePanel?PSubstData->AnotherPanel:PSubstData->ActivePanel; DWORD FileAttrL; int ShortN0=FALSE; int CntSkip=2; if (CurStr[2] == L'~') { ShortN0=TRUE; CntSkip++; } WPanel->GetSelName(nullptr,FileAttrL); int First = TRUE; while (WPanel->GetSelName(&strFileNameL,FileAttrL,&strShortNameL)) { if (ShortN0) strFileNameL = strShortNameL; else // в список все же должно попасть имя в кавычках. QuoteSpaceOnly(strFileNameL); // Вот здесь фиг его знает - нужно/ненужно... // если будет нужно - раскомментируем :-) // if(FileAttrL & FILE_ATTRIBUTE_DIRECTORY) // AddEndSlash(FileNameL); // А нужен ли нам пробел в самом начале? if (First) First = FALSE; else strOut += L" "; strOut += strFileNameL; } CurStr+=CntSkip; return CurStr; } // !@ Имя файла, содержащего имена помеченных файлов // !$! Имя файла, содержащего короткие имена помеченных файлов // Ниже идет совмещение кода для разбора как !@! так и !$! //Вообще-то (по исторической справедливости как бы) - в !$! нужно выбрасывать модификаторы Q и A // Но нафиг нада:) if (!StrCmpN(CurStr,L"!@",2) || !StrCmpN(CurStr,L"!$",2)) { string *pListName; string *pAnotherListName; bool ShortN0 = FALSE; if (CurStr[1] == L'$') ShortN0 = TRUE; if (ShortN0) { pListName = PSubstData->pShortListName; pAnotherListName = PSubstData->pAnotherShortListName; } else { pListName = PSubstData->pListName; pAnotherListName = PSubstData->pAnotherListName; } wchar_t Modifers[32]=L""; const wchar_t *Ptr; if ((Ptr=wcschr(CurStr+2,L'!')) ) { if (Ptr[1] != L'?') { xwcsncpy(Modifers,CurStr+2,Min(ARRAYSIZE(Modifers),static_cast<size_t>(Ptr-(CurStr+2)+1))); if (pListName) { if (PSubstData->PassivePanel && (!pAnotherListName->IsEmpty() || PSubstData->AnotherPanel->MakeListFile(*pAnotherListName,ShortN0,Modifers))) { if (ShortN0) ConvertNameToShort(*pAnotherListName, *pAnotherListName); strOut += *pAnotherListName; } if (!PSubstData->PassivePanel && (!pListName->IsEmpty() || PSubstData->ActivePanel->MakeListFile(*pListName,ShortN0,Modifers))) { if (ShortN0) ConvertNameToShort(*pListName,*pListName); strOut += *pListName; } } else { strOut += CurStr; strOut += Modifers; strOut += L"!"; } CurStr+=Ptr-CurStr+1; return CurStr; } } } // !-! Короткое имя файла с расширением if (!StrCmpN(CurStr,L"!-!",3) && CurStr[3] != L'?') { if (PSubstData->PassivePanel) strOut += PSubstData->strAnotherShortName; else strOut += PSubstData->ShortName; CurStr+=3; return CurStr; } // !+! Аналогично !-!, но если длинное имя файла утеряно // после выполнения команды, FAR восстановит его if (!StrCmpN(CurStr,L"!+!",3) && CurStr[3] != L'?') { if (PSubstData->PassivePanel) strOut += PSubstData->strAnotherShortName; else strOut += PSubstData->ShortName; CurStr+=3; PSubstData->PreserveLFN=TRUE; return CurStr; } // !: Текущий диск if (!StrCmpN(CurStr,L"!:",2)) { string strCurDir; string strRootDir; if (*PSubstData->Name && PSubstData->Name[1]==L':') strCurDir = PSubstData->Name; else if (PSubstData->PassivePanel) PSubstData->AnotherPanel->GetCurDir(strCurDir); else strCurDir = PSubstData->strCmdDir; GetPathRoot(strCurDir,strRootDir); DeleteEndSlash(strRootDir); strOut += strRootDir; CurStr+=2; return CurStr; } // !\ Текущий путь // !/ Короткое имя текущего пути // Ниже идет совмещение кода для разбора как !\ так и !/ if (!StrCmpN(CurStr,L"!\\",2) || !StrCmpN(CurStr,L"!=\\",3) || !StrCmpN(CurStr,L"!/",2) || !StrCmpN(CurStr,L"!=/",3)) { string strCurDir; bool ShortN0 = FALSE; int RealPath= CurStr[1]==L'='?1:0; if (CurStr[1] == L'/' || (RealPath && CurStr[2] == L'/')) { ShortN0 = TRUE; } if (PSubstData->PassivePanel) PSubstData->AnotherPanel->GetCurDir(strCurDir); else strCurDir = PSubstData->strCmdDir; if (RealPath) { _MakePath1(PSubstData->PassivePanel?KEY_ALTSHIFTBACKBRACKET:KEY_ALTSHIFTBRACKET,strCurDir,L"",ShortN0); Unquote(strCurDir); } if (ShortN0) ConvertNameToShort(strCurDir,strCurDir); AddEndSlash(strCurDir); CurStr+=2+RealPath; if (*CurStr==L'!') { if (wcspbrk(PSubstData->PassivePanel?PSubstData->strAnotherName.CPtr():PSubstData->Name,L"\\:")) strCurDir.Clear(); } strOut += strCurDir; return CurStr; } // !?<title>?<init>! if (!StrCmpN(CurStr,L"!?",2) && wcschr(CurStr+2,L'!')) { int j; int i = IsReplaceVariable(CurStr); if (i == -1) // if bad format string { // skip 1 char j = 1; } else { j = i + 1; } strOut.Append(CurStr, j); CurStr += j; return CurStr; } // ! Длинное имя файла без расширения if (*CurStr==L'!') { strOut += PointToName(PSubstData->PassivePanel ? PSubstData->strAnotherNameOnly : PSubstData->strNameOnly); CurStr++; } return CurStr; }
bool Panel::MakeListFile(string &strListFileName,bool ShortNames,const wchar_t *Modifers) { bool Ret=false; if (FarMkTempEx(strListFileName)) { File ListFile; if (ListFile.Open(strListFileName,GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,nullptr,CREATE_ALWAYS)) { UINT CodePage=CP_OEMCP; LPCVOID Eol="\r\n"; DWORD EolSize=2; if (Modifers && *Modifers) { if (wcschr(Modifers,L'A')) // ANSI { CodePage=CP_ACP; } else { DWORD Signature=0; int SignatureSize=0; if (wcschr(Modifers,L'W')) // UTF16LE { CodePage=CP_UNICODE; Signature=SIGN_UNICODE; SignatureSize=2; Eol=DOS_EOL_fmt; EolSize=2*sizeof(WCHAR); } else { if (wcschr(Modifers,L'U')) // UTF8 { CodePage=CP_UTF8; Signature=SIGN_UTF8; SignatureSize=3; } } if (Signature && SignatureSize) { DWORD NumberOfBytesWritten; ListFile.Write(&Signature,SignatureSize, NumberOfBytesWritten); } } } string strFileName,strShortName; DWORD FileAttr; GetSelName(nullptr,FileAttr); while (GetSelName(&strFileName,FileAttr,&strShortName)) { if (ShortNames) strFileName = strShortName; if (Modifers && *Modifers) { if (wcschr(Modifers,L'F') && PointToName(strFileName) == strFileName.CPtr()) // 'F' - использовать полный путь; //BUGBUG ? { string strTempFileName=strCurDir; if (ShortNames) ConvertNameToShort(strTempFileName,strTempFileName); AddEndSlash(strTempFileName); strTempFileName+=strFileName; //BUGBUG ? strFileName=strTempFileName; } if (wcschr(Modifers,L'Q')) // 'Q' - заключать имена с пробелами в кавычки; QuoteSpaceOnly(strFileName); if (wcschr(Modifers,L'S')) // 'S' - использовать '/' вместо '\' в путях файлов; { size_t Len=strFileName.GetLength(); wchar_t *FileName=strFileName.GetBuffer(); for (size_t i=0; i<Len; i++) { if (FileName[i]==L'\\') { FileName[i]=L'/'; } } strFileName.ReleaseBuffer(); } } LPCVOID Ptr=nullptr; LPSTR Buffer=nullptr; DWORD NumberOfBytesToWrite=0,NumberOfBytesWritten=0; if (CodePage==CP_UNICODE) { Ptr=strFileName.CPtr(); NumberOfBytesToWrite=static_cast<DWORD>(strFileName.GetLength()*sizeof(WCHAR)); } else { int Size=WideCharToMultiByte(CodePage,0,strFileName,static_cast<int>(strFileName.GetLength()),nullptr,0,nullptr,nullptr); if (Size) { Buffer=static_cast<LPSTR>(xf_malloc(Size)); if (Buffer) { NumberOfBytesToWrite=WideCharToMultiByte(CodePage,0,strFileName,static_cast<int>(strFileName.GetLength()),Buffer,Size,nullptr,nullptr); Ptr=Buffer; } } } BOOL Written=ListFile.Write(Ptr,NumberOfBytesToWrite,NumberOfBytesWritten); if (Buffer) xf_free(Buffer); if (Written && NumberOfBytesWritten==NumberOfBytesToWrite) { if (ListFile.Write(Eol,EolSize,NumberOfBytesWritten) && NumberOfBytesWritten==EolSize) { Ret=true; } } else { Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MError),MSG(MCannotCreateListFile),MSG(MCannotCreateListWrite),MSG(MOk)); apiDeleteFile(strListFileName); break; } } ListFile.Close(); } else { Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MError),MSG(MCannotCreateListFile),MSG(MCannotCreateListTemp),MSG(MOk)); } } else { Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MError),MSG(MCannotCreateListFile),MSG(MCannotCreateListTemp),MSG(MOk)); } return Ret; }
int ArcCommand::ReplaceVar(char *Command,int &Length) { char Chr=Command[2]&(~0x20); if (Command[0]!='%' || Command[1]!='%' || Chr < 'A' || Chr > 'Z') return FALSE; char SaveStr[MAX_COMMAND_LENGTH],LocalAllFilesMask[NM]; int QuoteName=0,UseSlash=FALSE,FolderMask=FALSE,FolderName=FALSE; int NameOnly=FALSE,PathOnly=FALSE,AnsiCode=FALSE; int MaxNamesLength=127; int VarLength=3; lstrcpy(LocalAllFilesMask,AllFilesMask); while (1) { int BreakScan=FALSE; Chr=Command[VarLength]; if (Command[2]=='F' && Chr >= '0' && Chr <= '9') { MaxNamesLength=FSF.atoi(&Command[VarLength]); while (Chr >= '0' && Chr <= '9') Chr=Command[++VarLength]; continue; } if (Command[2]=='E' && Chr >= '0' && Chr <= '9') { MaxAllowedExitCode=FSF.atoi(&Command[VarLength]); while (Chr >= '0' && Chr <= '9') Chr=Command[++VarLength]; continue; } switch(Command[VarLength]) { case 'A': AnsiCode=TRUE; break; case 'Q': QuoteName=1; break; case 'q': QuoteName=2; break; case 'S': UseSlash=TRUE; break; case 'M': FolderMask=TRUE; break; case 'N': FolderName=TRUE; break; case 'W': NameOnly=TRUE; break; case 'P': PathOnly=TRUE; break; case '*': lstrcpy(LocalAllFilesMask,"*"); break; default: BreakScan=TRUE; break; } if (BreakScan) break; VarLength++; } if ((MaxNamesLength-=Length)<=0) MaxNamesLength=1; if (MaxNamesLength>MAX_COMMAND_LENGTH-512) MaxNamesLength=MAX_COMMAND_LENGTH-512; if (FolderMask==FALSE && FolderName==FALSE) FolderName=TRUE; lstrcpy(SaveStr,Command+VarLength); switch(Command[2]) { case 'A': lstrcpy(Command,ArcName); if (AnsiCode) OemToChar(Command,Command); if (PathOnly) { char *NamePtr=(char *)FSF.PointToName(Command); if (NamePtr!=Command) *(NamePtr-1)=0; else lstrcpy(Command," "); } FSF.QuoteSpaceOnly(Command); break; case 'a': { int Dot=strchr(FSF.PointToName(ArcName),'.')!=NULL; ConvertNameToShort(ArcName,Command); char *Slash=strrchr(ArcName,'\\'); if (GetFileAttributes(ArcName)==0xFFFFFFFF && Slash!=NULL && Slash!=ArcName) { char Path[NM]; lstrcpy(Path,ArcName); Path[Slash-ArcName]=0; ConvertNameToShort(Path,Command); lstrcat(Command,Slash); } if (Dot && strchr(FSF.PointToName(Command),'.')==NULL) lstrcat(Command,"."); if (AnsiCode) OemToChar(Command,Command); if (PathOnly) { char *NamePtr=(char *)FSF.PointToName(Command); if (NamePtr!=Command) *(NamePtr-1)=0; else lstrcpy(Command," "); } } FSF.QuoteSpaceOnly(Command); break; case 'D': *Command=0; break; case 'E': *Command=0; break; case 'l': case 'L': if (!MakeListFile(ListFileName,Command[2]=='l',QuoteName,UseSlash, FolderName,NameOnly,PathOnly,FolderMask, LocalAllFilesMask,AnsiCode)) return -1; char QListName[NM+2]; FSF.QuoteSpaceOnly(lstrcpy(QListName,ListFileName)); lstrcpy(Command,QListName); break; case 'P': lstrcpy(Command,Password); break; case 'C': if(*CommentFileName) //второй раз сюда не лезем break; { *Command=0; HANDLE CommentFile; //char CommentFileName[MAX_PATH]; char Buf[512]; SECURITY_ATTRIBUTES sa; sa.nLength=sizeof(sa); sa.lpSecurityDescriptor=NULL; sa.bInheritHandle=TRUE; if(FSF.MkTemp(CommentFileName, "FAR") && (CommentFile=CreateFile(CommentFileName, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, /*FILE_ATTRIBUTE_TEMPORARY|*//*FILE_FLAG_DELETE_ON_CLOSE*/0, NULL)) != INVALID_HANDLE_VALUE) { DWORD Count; if(Info.InputBox(GetMsg(MComment), GetMsg(MInputComment), NULL, "", Buf, sizeof(Buf), NULL, 0)) //??тут можно и заполнить строку комментарием, но надо знать, файловый //?? он или архивный. да и имя файла в архиве тоже надо знать... { WriteFile(CommentFile, Buf, lstrlen(Buf), &Count, NULL); lstrcpy(Command, CommentFileName); CloseHandle(CommentFile); } FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE)); } } break; case 'R': lstrcpy(Command,RealArcDir); if (UseSlash) { for (int I=0;Command[I];I++) if (Command[I]=='\\') // Command[I]='//'; /* $ 28.11.2000 AS */ Command[I]='/'; /* AS $*/ } FSF.QuoteSpaceOnly(Command); break; case 'W': lstrcpy(Command,TempPath); break; case 'f': case 'F': if (PanelItem!=NULL) { char CurArcDir[NM]; lstrcpy(CurArcDir,ArcDir); int Length=lstrlen(CurArcDir); if (Length>0 && CurArcDir[Length-1]!='\\') lstrcat(CurArcDir,"\\"); char Names[MAX_COMMAND_LENGTH]; *Names=0; if (NameNumber==-1) NameNumber=0; while (NameNumber<ItemsNumber || Command[2]=='f') { char Name[NM*2]; int IncreaseNumber=0,FileAttr; if (*NextFileName) { FSF.sprintf(Name,"%s%s%s",PrefixFileName,CurArcDir,NextFileName); *NextFileName=0; FileAttr=0; } else { int N; if (Command[2]=='f' && PrevFileNameNumber!=-1) N=PrevFileNameNumber; else { N=NameNumber; IncreaseNumber=1; } if (N>=ItemsNumber) break; *PrefixFileName=0; char *cFileName=PanelItem[N].FindData.cFileName; if(PanelItem[N].UserData && (PanelItem[N].Flags & PPIF_USERDATA)) { struct ArcItemUserData *aud=(struct ArcItemUserData*)PanelItem[N].UserData; if(aud->SizeStruct == sizeof(struct ArcItemUserData)) { if(aud->Prefix) lstrcpyn(PrefixFileName,aud->Prefix,sizeof(PrefixFileName)); if(aud->LinkName) cFileName=aud->LinkName; } } // CHECK for BUGS!! if(*cFileName == '\\' || *cFileName == '/') FSF.sprintf(Name,"%s%s",PrefixFileName,cFileName+1); else FSF.sprintf(Name,"%s%s%s",PrefixFileName,CurArcDir,cFileName); NormalizePath(Name,Name); FileAttr=PanelItem[N].FindData.dwFileAttributes; PrevFileNameNumber=N; } if (AnsiCode) OemToChar(Name,Name); if (NameOnly) { char NewName[NM]; lstrcpy(NewName,FSF.PointToName(Name)); lstrcpy(Name,NewName); } if (PathOnly) { char *NamePtr=(char *)FSF.PointToName(Name); if (NamePtr!=Name) *(NamePtr-1)=0; else lstrcpy(Name," "); } if (*Names==0 || (lstrlen(Names)+lstrlen(Name)<MaxNamesLength && Command[2]!='f')) { NameNumber+=IncreaseNumber; if (FileAttr & FILE_ATTRIBUTE_DIRECTORY) { char FolderMaskName[NM]; //lstrcpy(LocalAllFilesMask,PrefixFileName); FSF.sprintf(FolderMaskName,"%s\\%s",Name,LocalAllFilesMask); if (PathOnly) { lstrcpy(FolderMaskName,Name); char *NamePtr=(char *)FSF.PointToName(FolderMaskName); if (NamePtr!=FolderMaskName) *(NamePtr-1)=0; else lstrcpy(FolderMaskName," "); } if (FolderMask) { if (FolderName) lstrcpy(NextFileName,FolderMaskName); else lstrcpy(Name,FolderMaskName); } } if (QuoteName==1) FSF.QuoteSpaceOnly(Name); else if (QuoteName==2) QuoteText(Name); if (UseSlash) for (int I=0;Name[I];I++) if (Name[I]=='\\') // Name[I]='//'; /* $ 28.11.2000 AS */ Name[I]='/'; /* AS $*/ if (*Names) lstrcat(Names," "); lstrcat(Names,Name); } else break; } lstrcpy(Command,Names); } else *Command=0; break; default: return FALSE; } Length=lstrlen(Command); lstrcat(Command,SaveStr); return TRUE; }
bool Panel::MakeListFile(string& ListFileName, bool ShortNames, string_view const Modifers) { uintptr_t CodePage = CP_OEMCP; if (!Modifers.empty()) { if (contains(Modifers, L'A')) // ANSI { CodePage = CP_ACP; } else if (contains(Modifers, L'U')) // UTF8 { CodePage = CP_UTF8; } else if (contains(Modifers, L'W')) // UTF16LE { CodePage = CP_UNICODE; } } const auto& transform = [&](string& strFileName) { if (!Modifers.empty()) { if (contains(Modifers, L'F') && PointToName(strFileName).size() == strFileName.size()) // 'F' - использовать полный путь; //BUGBUG ? { strFileName = path::join(ShortNames ? ConvertNameToShort(m_CurDir) : m_CurDir, strFileName); //BUGBUG ? } if (contains(Modifers, L'Q')) // 'Q' - заключать имена с пробелами в кавычки; QuoteSpaceOnly(strFileName); if (contains(Modifers, L'S')) // 'S' - использовать '/' вместо '\' в путях файлов; { ReplaceBackslashToSlash(strFileName); } } }; try { ListFileName = MakeTemp(); if (const auto ListFile = os::fs::file(ListFileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, CREATE_ALWAYS)) { os::fs::filebuf StreamBuffer(ListFile, std::ios::out); std::ostream Stream(&StreamBuffer); Stream.exceptions(Stream.badbit | Stream.failbit); encoding::writer Writer(Stream, CodePage); for (const auto& i: enum_selected()) { auto Name = ShortNames? i.AlternateFileName() : i.FileName; transform(Name); Writer.write(Name); Writer.write(L"\r\n"sv); } Stream.flush(); } else { throw MAKE_FAR_EXCEPTION(msg(lng::MCannotCreateListTemp)); } return true; } catch (const far_exception& e) { os::fs::delete_file(ListFileName); Message(MSG_WARNING, e.get_error_state(), msg(lng::MError), { msg(lng::MCannotCreateListFile), e.get_message() }, { lng::MOk }); return false; } }
static string_view ProcessMetasymbol(string_view const CurStr, subst_data& SubstData, string& Out) { const auto append_with_escape = [EscapeAmpersands = SubstData.EscapeAmpersands](string& Destination, string_view const Str) { if (EscapeAmpersands && contains(Str, L"&"sv)) { string Escaped(Str); replace(Escaped, L"&"sv, L"&&"sv); append(Destination, Escaped); } else { append(Destination, Str); } }; if (const auto Tail = tokens::skip(CurStr, tokens::passive_panel)) { SubstData.PassivePanel = true; return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::active_panel)) { SubstData.PassivePanel = false; return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::exclamation)) { if (!starts_with(Tail, L'?')) { Out.push_back(L'!'); return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::name_extension)) { if (!starts_with(Tail, L'?')) { append_with_escape(Out, SubstData.Default().Normal.Name); return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::short_name)) { append_with_escape(Out, SubstData.Default().Short.NameOnly); return Tail; } const auto GetExtension = [](string_view const Name) { const auto Extension = PointToExt(Name); return Extension.empty()? Extension : Extension.substr(1); }; if (const auto Tail = tokens::skip(CurStr, tokens::short_extension)) { append_with_escape(Out, GetExtension(SubstData.Default().Short.Name)); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::extension)) { append_with_escape(Out, GetExtension(SubstData.Default().Normal.Name)); return Tail; } const auto CollectNames = [&SubstData, &append_with_escape](string& Str, auto const Selector) { append_with_escape(Str, join(select(SubstData.Default().Panel->enum_selected(), Selector), L" "sv)); }; if (const auto Tail = tokens::skip(CurStr, tokens::short_list)) { if (!starts_with(Tail, L'?')) { CollectNames(Out, &os::fs::find_data::AlternateFileName); return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::list)) { if (!starts_with(Tail, L'?')) { CollectNames(Out, [](const os::fs::find_data& Data) { return quote_space(Data.FileName); }); return Tail; } } const auto GetListName = [&Out, &append_with_escape](string_view const Tail, subst_data& Data, bool Short) { const auto ExclPos = Tail.find(L'!'); if (ExclPos == Tail.npos || starts_with(Tail.substr(ExclPos + 1), L'?')) return size_t{}; const auto Modifiers = Tail.substr(0, ExclPos); if (Data.ListNames) { string Str; if (Data.Default().Panel->MakeListFile(Str, Short, Modifiers)) { if (Short) Str = ConvertNameToShort(Str); append_with_escape(Out, Str); Data.ListNames->add(std::move(Str)); } } else { append(Out, L'!', Short? L'$' : L'@', Modifiers, L'!'); } return Modifiers.size() + 1; }; if (const auto Tail = tokens::skip(CurStr, tokens::list_file)) { if (const auto Offset = GetListName(Tail, SubstData, false)) return string_view(Tail).substr(Offset); } if (const auto Tail = tokens::skip(CurStr, tokens::short_list_file)) { if (const auto Offset = GetListName(Tail, SubstData, true)) return string_view(Tail).substr(Offset); } if (const auto Tail = tokens::skip(CurStr, tokens::short_name_extension)) { if (!starts_with(Tail, L'?')) { append_with_escape(Out, SubstData.Default().Short.Name); return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::short_name_extension_safe)) { if (!starts_with(Tail, L'?')) { append_with_escape(Out, SubstData.Default().Short.Name); SubstData.PreserveLFN = true; return Tail; } } if (const auto Tail = tokens::skip(CurStr, tokens::current_drive)) { const auto CurDir = IsAbsolutePath(SubstData.This.Normal.Name)? SubstData.This.Normal.Name : SubstData.PassivePanel? SubstData.Another.Panel->GetCurDir() : SubstData.CmdDir; auto RootDir = GetPathRoot(CurDir); DeleteEndSlash(RootDir); append_with_escape(Out, RootDir); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::description)) { Out += SubstData.Default().GetDescription(); return Tail; } const auto GetPath = [](string_view const Tail, const subst_data& Data, bool Short, bool Real) { // TODO: paths on plugin panels are ambiguous auto CurDir = Data.PassivePanel? Data.Another.Panel->GetCurDir() : Data.CmdDir; if (Real) CurDir = ConvertNameToReal(CurDir); if (Short) CurDir = ConvertNameToShort(CurDir); AddEndSlash(CurDir); return CurDir; }; if (const auto Tail = tokens::skip(CurStr, tokens::path)) { Out += GetPath(Tail, SubstData, false, false); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::short_path)) { Out += GetPath(Tail, SubstData, true, false); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::real_path)) { Out += GetPath(Tail, SubstData, false, true); return Tail; } if (const auto Tail = tokens::skip(CurStr, tokens::real_short_path)) { Out += GetPath(Tail, SubstData, true, true); return Tail; } // !?<title>?<init>! if (const auto Tail = tokens::skip(CurStr, tokens::input)) { auto SkipSize = SkipInputToken(CurStr); // if bad format string skip 1 char if (!SkipSize) SkipSize = 1; Out.append(CurStr.data(), SkipSize); return CurStr.substr(SkipSize); } if (const auto Tail = tokens::skip(CurStr, tokens::name)) { append(Out, PointToName(SubstData.Default().Normal.NameOnly)); return Tail; } return CurStr; }