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; }
STDMETHODIMP CDirectory::Create(BSTR path) { TCHAR cleanPath[MAX_PATH]; ::PathCanonicalize(cleanPath, path); ::PathRemoveBackslash(cleanPath); BOOL bAlreadyExists; Exists(cleanPath, &bAlreadyExists); if(!bAlreadyExists) { WCHAR parentPath[MAX_PATH]; ::StringCchCopy(parentPath, MAX_PATH, cleanPath); parentPath[FindLastSlash(cleanPath)] = 0; Exists(parentPath, &bAlreadyExists); if(!bAlreadyExists) { return Create(parentPath); } else { if(::CreateDirectory(cleanPath, NULL)) return S_OK; else return ::GetLastError(); } } else { return ERROR_ALREADY_EXISTS; } }
string ExtractFilePath(const string &Path) { size_t p; if (!FindLastSlash(p, Path)) p = 0; size_t PathRootLen = GetPathRootLength(Path); if (p <= PathRootLen && PathRootLen) return string(Path.CPtr(), PathRootLen).Append(L'\\'); return string(Path.CPtr(), p); }
string ExtractFileName(const string &Path) { size_t p; if (FindLastSlash(p, Path)) p++; else p = 0; size_t PathRootLen = GetPathRootLength(Path); if (p <= PathRootLen && PathRootLen) return string(); return string(Path.CPtr() + p, Path.GetLength() - p); }
bool CutToSlash(string &strStr, bool bInclude) { size_t pos; if (FindLastSlash(pos,strStr)) { if (pos==3 && HasPathPrefix(strStr)) return false; if (bInclude) strStr.SetLength(pos); else strStr.SetLength(pos+1); return true; } return false; }
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 FileList::ShowFileList(int Fast) { if (Locked()) { CorrectPosition(); return; } string strTitle; string strInfoCurDir; int Length; OpenPanelInfo Info; if (PanelMode==PLUGIN_PANEL) { if (ProcessPluginEvent(FE_REDRAW,nullptr)) return; CtrlObject->Plugins->GetOpenPanelInfo(hPlugin,&Info); strInfoCurDir=Info.CurDir; } bool CurFullScreen=IsFullScreen(); PrepareViewSettings(ViewMode,&Info); CorrectPosition(); if (CurFullScreen!=IsFullScreen()) { CtrlObject->Cp()->SetScreenPosition(); CtrlObject->Cp()->GetAnotherPanel(this)->Update(UPDATE_KEEP_SELECTION|UPDATE_SECONDARY); } SetScreen(X1+1,Y1+1,X2-1,Y2-1,L' ',ColorIndexToColor(COL_PANELTEXT)); Box(X1,Y1,X2,Y2,ColorIndexToColor(COL_PANELBOX),DOUBLE_BOX); if (Opt.ShowColumnTitles) { // SetScreen(X1+1,Y1+1,X2-1,Y1+1,' ',COL_PANELTEXT); SetColor(COL_PANELTEXT); //??? //GotoXY(X1+1,Y1+1); //FS<<fmt::Width(X2-X1-1)<<L""; } for (int I=0,ColumnPos=X1+1; I<ViewSettings.ColumnCount; I++) { if (ViewSettings.ColumnWidth[I]<0) continue; if (Opt.ShowColumnTitles) { LNGID IDMessage=MColumnUnknown; switch (ViewSettings.ColumnType[I] & 0xff) { case NAME_COLUMN: IDMessage=MColumnName; break; case EXTENSION_COLUMN: IDMessage=MColumnExtension; break; case SIZE_COLUMN: IDMessage=MColumnSize; break; case PACKED_COLUMN: IDMessage=MColumnAlocatedSize; break; case DATE_COLUMN: IDMessage=MColumnDate; break; case TIME_COLUMN: IDMessage=MColumnTime; break; case WDATE_COLUMN: IDMessage=MColumnWrited; break; case CDATE_COLUMN: IDMessage=MColumnCreated; break; case ADATE_COLUMN: IDMessage=MColumnAccessed; break; case CHDATE_COLUMN: IDMessage=MColumnChanged; break; case ATTR_COLUMN: IDMessage=MColumnAttr; break; case DIZ_COLUMN: IDMessage=MColumnDescription; break; case OWNER_COLUMN: IDMessage=MColumnOwner; break; case NUMLINK_COLUMN: IDMessage=MColumnMumLinks; break; case NUMSTREAMS_COLUMN: IDMessage=MColumnNumStreams; break; case STREAMSSIZE_COLUMN: IDMessage=MColumnStreamsSize; break; } strTitle=MSG(IDMessage); if (PanelMode==PLUGIN_PANEL && Info.PanelModesArray && ViewMode<static_cast<int>(Info.PanelModesNumber) && Info.PanelModesArray[ViewMode].ColumnTitles) { const wchar_t *NewTitle=Info.PanelModesArray[ViewMode].ColumnTitles[I]; if (NewTitle) strTitle=NewTitle; } string strTitleMsg; CenterStr(strTitle,strTitleMsg,ViewSettings.ColumnWidth[I]); SetColor(COL_PANELCOLUMNTITLE); GotoXY(ColumnPos,Y1+1); FS<<fmt::Precision(ViewSettings.ColumnWidth[I])<<strTitleMsg; } if (I>=ViewSettings.ColumnCount-1) break; if (ViewSettings.ColumnWidth[I+1]<0) continue; SetColor(COL_PANELBOX); ColumnPos+=ViewSettings.ColumnWidth[I]; GotoXY(ColumnPos,Y1); bool DoubleLine = Opt.DoubleGlobalColumnSeparator && (!((I+1)%ColumnsInGlobal)); BoxText(BoxSymbols[DoubleLine?BS_T_H2V2:BS_T_H2V1]); if (Opt.ShowColumnTitles) { GotoXY(ColumnPos,Y1+1); BoxText(BoxSymbols[DoubleLine?BS_V2:BS_V1]); } if (!Opt.ShowPanelStatus) { GotoXY(ColumnPos,Y2); BoxText(BoxSymbols[DoubleLine?BS_B_H2V2:BS_B_H2V1]); } ColumnPos++; } int NextX1=X1+1; if (Opt.ShowSortMode) { static int SortModes[]={UNSORTED,BY_NAME,BY_EXT,BY_MTIME,BY_CTIME, BY_ATIME,BY_CHTIME,BY_SIZE,BY_DIZ,BY_OWNER, BY_COMPRESSEDSIZE,BY_NUMLINKS, BY_NUMSTREAMS,BY_STREAMSSIZE, BY_FULLNAME,BY_CUSTOMDATA }; static LNGID SortStrings[]={MMenuUnsorted,MMenuSortByName, MMenuSortByExt,MMenuSortByWrite,MMenuSortByCreation, MMenuSortByAccess,MMenuSortByChange,MMenuSortBySize,MMenuSortByDiz,MMenuSortByOwner, MMenuSortByAllocatedSize,MMenuSortByNumLinks,MMenuSortByNumStreams,MMenuSortByStreamsSize, MMenuSortByFullName,MMenuSortByCustomData }; for (size_t I=0; I<ARRAYSIZE(SortModes); I++) { if (SortModes[I]==SortMode) { const wchar_t *SortStr=MSG(SortStrings[I]); const wchar_t *Ch=wcschr(SortStr,L'&'); if (Ch) { if (Opt.ShowColumnTitles) GotoXY(NextX1,Y1+1); else GotoXY(NextX1,Y1); SetColor(COL_PANELCOLUMNTITLE); OutCharacter[0]=SortOrder==1 ? Lower(Ch[1]):Upper(Ch[1]); Text(OutCharacter); NextX1++; if (Filter && Filter->IsEnabledOnPanel()) { OutCharacter[0]=L'*'; Text(OutCharacter); NextX1++; } } break; } } } /* <режимы сортировки> */ if (/*GetNumericSort() || GetCaseSensitiveSort() || GetSortGroups() || */GetSelectedFirstMode()) { if (Opt.ShowColumnTitles) GotoXY(NextX1,Y1+1); else GotoXY(NextX1,Y1); SetColor(COL_PANELCOLUMNTITLE); wchar_t *PtrOutCharacter=OutCharacter; *PtrOutCharacter=0; //if (GetSelectedFirstMode()) *PtrOutCharacter++=L'^'; /* if(GetNumericSort()) *PtrOutCharacter++=L'#'; if(GetSortGroups()) *PtrOutCharacter++=L'@'; */ /* if(GetCaseSensitiveSort()) { } */ *PtrOutCharacter=0; Text(OutCharacter); PtrOutCharacter[1]=0; } /* </режимы сортировки> */ if (!Fast && GetFocus()) { if (PanelMode==PLUGIN_PANEL) CtrlObject->CmdLine->SetCurDir(Info.CurDir); else CtrlObject->CmdLine->SetCurDir(strCurDir); CtrlObject->CmdLine->Show(); } int TitleX2=Opt.Clock && !Opt.ShowMenuBar ? Min(ScrX-4,X2):X2; int TruncSize=TitleX2-X1-3; if (!Opt.ShowColumnTitles && Opt.ShowSortMode && Filter && Filter->IsEnabledOnPanel()) TruncSize-=2; GetTitle(strTitle,TruncSize,2);//,(PanelMode==PLUGIN_PANEL?0:2)); Length=(int)strTitle.GetLength(); int ClockCorrection=FALSE; if ((Opt.Clock && !Opt.ShowMenuBar) && TitleX2==ScrX-4) { ClockCorrection=TRUE; TitleX2+=4; } int TitleX=X1+(TitleX2-X1+1-Length)/2; if (ClockCorrection) { int Overlap=TitleX+Length-TitleX2+5; if (Overlap > 0) TitleX-=Overlap; } if (TitleX <= X1) TitleX = X1+1; SetColor(Focus ? COL_PANELSELECTEDTITLE:COL_PANELTITLE); GotoXY(TitleX,Y1); Text(strTitle); if (!FileCount) { SetScreen(X1+1,Y2-1,X2-1,Y2-1,L' ',ColorIndexToColor(COL_PANELTEXT)); SetColor(COL_PANELTEXT); //??? //GotoXY(X1+1,Y2-1); //FS<<fmt::Width(X2-X1-1)<<L""; } if (PanelMode==PLUGIN_PANEL && FileCount>0 && (Info.Flags & OPIF_REALNAMES)) { if (!strInfoCurDir.IsEmpty()) { strCurDir = strInfoCurDir; } else { if (!TestParentFolderName(ListData[CurFile]->strName)) { strCurDir=ListData[CurFile]->strName; size_t pos; if (FindLastSlash(pos,strCurDir)) { if (pos) { if (strCurDir.At(pos-1)!=L':') strCurDir.SetLength(pos); else strCurDir.SetLength(pos+1); } } } else { strCurDir = strOriginalCurDir; } } if (GetFocus()) { CtrlObject->CmdLine->SetCurDir(strCurDir); CtrlObject->CmdLine->Show(); } } if ((Opt.ShowPanelTotals || Opt.ShowPanelFree) && (Opt.ShowPanelStatus || !SelFileCount)) { ShowTotalSize(Info); } ShowList(FALSE,0); ShowSelectedSize(); if (Opt.ShowPanelScrollbar) { SetColor(COL_PANELSCROLLBAR); ScrollBarEx(X2,Y1+1+Opt.ShowColumnTitles,Height,Round(CurTopFile,Columns),Round(FileCount,Columns)); } ShowScreensCount(); if (!ProcessingPluginCommand && LastCurFile!=CurFile) { LastCurFile=CurFile; UpdateViewPanel(); } if (PanelMode==PLUGIN_PANEL) CtrlObject->Cp()->RedrawKeyBar(); }
// Кусок для создания SymLink для каталогов. int MkSymLink(const string& Target, const string& LinkName, ReparsePointTypes LinkType, bool Silent, bool HoldTarget) { if (!Target.empty() && !LinkName.empty()) { string strFullTarget; // выделим имя auto strSelOnlyName = Target; DeleteEndSlash(strSelOnlyName); const auto SlashPos = FindLastSlash(strSelOnlyName); const auto symlink = LinkType==RP_SYMLINK || LinkType==RP_SYMLINKFILE || LinkType==RP_SYMLINKDIR; if (Target[1] == L':' && (!Target[2] || (IsSlash(Target[2]) && !Target[3]))) // C: или C:/ { // if(Flags&FCOPY_VOLMOUNT) { strFullTarget = Target; AddEndSlash(strFullTarget); } /* Вот здесь - ну очень умное поведение! Т.е. если в качестве SelName передали "C:", то в этом куске происходит коррекция типа линка - с symlink`а на volmount */ LinkType=RP_VOLMOUNT; } else strFullTarget = ConvertNameToFull(Target); auto strFullLink = ConvertNameToFull(LinkName); if (IsSlash(strFullLink.back())) { if (LinkType != RP_VOLMOUNT) { const auto SelName = SlashPos != string::npos? string_view(strSelOnlyName).substr(SlashPos + 1) : string_view(strSelOnlyName); append(strFullLink, SelName); } else { append(strFullLink, L"Disk_"sv, Target.front()); } } if (LinkType==RP_VOLMOUNT) { AddEndSlash(strFullTarget); AddEndSlash(strFullLink); } if (symlink) { // в этом случае создается путь, но не сам каталог string strPath=strFullLink; if (CutToSlash(strPath)) { if (!os::fs::exists(strPath)) CreatePath(strPath); } } else { bool CreateDir=true; if (LinkType==RP_EXACTCOPY) { // в этом случае создается или каталог, или пустой файл if (os::fs::is_file(strFullTarget)) CreateDir=false; } if (CreateDir) { if (os::fs::create_directory(strFullLink)) TreeList::AddTreeName(strFullLink); else CreatePath(strFullLink); } else { string strPath=strFullLink; if (CutToSlash(strPath)) { if (!os::fs::exists(strPath)) CreatePath(strPath); os::fs::file(strFullLink, 0, 0, nullptr, CREATE_NEW, os::fs::get_file_attributes(strFullTarget)); } } if (!os::fs::exists(strFullLink)) { if (!Silent) { const auto ErrorState = error_state::fetch(); Message(MSG_WARNING, ErrorState, msg(lng::MError), { msg(lng::MCopyCannotCreateLink), strFullLink }, { lng::MOk }); } return 0; } } if (LinkType!=RP_VOLMOUNT) { if (CreateReparsePoint(HoldTarget && symlink ? Target : strFullTarget, strFullLink, LinkType)) { return 1; } else { if (!Silent) { const auto ErrorState = error_state::fetch(); Message(MSG_WARNING, ErrorState, msg(lng::MError), { msg(lng::MCopyCannotCreateLink), strFullLink }, { lng::MOk }); } return 0; } } else { if (CreateVolumeMountPoint(strFullTarget,strFullLink)) { return 1; } else { if (!Silent) { const auto ErrorState = error_state::fetch(); Message(MSG_WARNING, ErrorState, msg(lng::MError), { format(msg(lng::MCopyMountVolFailed), Target), format(msg(lng::MCopyMountVolFailed2), strFullLink) }, { lng::MOk }); } return 0; } } } return 2; }
std::list<CommandLine::segment> CommandLine::GetPrompt() { FN_RETURN_TYPE(CommandLine::GetPrompt) Result; int NewPromptSize = DEFAULT_CMDLINE_WIDTH; const auto& PrefixColor = colors::PaletteColorToFarColor(COL_COMMANDLINEPREFIX); if (Global->Opt->CmdLine.UsePromptFormat) { const string_view Format = Global->Opt->CmdLine.strPromptFormat.Get(); auto Tail = Format.cbegin(); auto Color = PrefixColor; FOR_CONST_RANGE(Format, Iterator) { bool Stop; auto NewColor = PrefixColor; const auto NextIterator = colors::ExtractColorInNewFormat(Iterator, Format.cend(), NewColor, Stop); if (NextIterator == Iterator) { if (Stop) break; continue; } if (Iterator != Format.cbegin()) { Result.emplace_back(segment{ string(Tail, Iterator), Color }); } Iterator = NextIterator; Tail = Iterator; Color = NewColor; } Result.emplace_back(segment{ string(Tail, Format.cend()), Color }); for (auto Iterator = Result.begin(); Iterator != Result.end(); ++Iterator) { const auto strExpandedDestStr = os::env::expand(Iterator->Text); Iterator->Text.clear(); static const std::pair<wchar_t, wchar_t> ChrFmt[] = { {L'A', L'&'}, // $A - & (Ampersand) {L'B', L'|'}, // $B - | (pipe) {L'C', L'('}, // $C - ( (Left parenthesis) {L'F', L')'}, // $F - ) (Right parenthesis) {L'G', L'>'}, // $G - > (greater-than sign) {L'L', L'<'}, // $L - < (less-than sign) {L'Q', L'='}, // $Q - = (equal sign) {L'S', L' '}, // $S - (space) {L'$', L'$'}, // $$ - $ (dollar sign) }; FOR_CONST_RANGE(strExpandedDestStr, it) { auto& strDestStr = Iterator->Text; if (*it == L'$' && it + 1 != strExpandedDestStr.cend()) { const auto Chr = upper(*++it); const auto ItemIterator = std::find_if(CONST_RANGE(ChrFmt, Item) { return Item.first == Chr; }); if (ItemIterator != std::cend(ChrFmt)) { strDestStr += ItemIterator->second; } else { const auto& AddCollapsible = [&](string&& Str) { if (strDestStr.empty()) { strDestStr = std::move(Str); Iterator->Collapsible = true; } else { Iterator = Result.insert(std::next(Iterator), segment{ std::move(Str), Iterator->Colour, true }); } // No need to introduce a new segment if we're at the very end if (std::next(Iterator) != Result.end() && std::next(it) != strExpandedDestStr.cend()) { Iterator = Result.insert(std::next(Iterator), segment{ {}, Iterator->Colour, false }); } }; switch (Chr) { /* эти не реaлизованы $E - Escape code (ASCII code 27) $V - Windows version number $_ - Carriage return and linefeed */ case L'M': // $M - Отображение полного имени удаленного диска, связанного с именем текущего диска, или пустой строки, если текущий диск не является сетевым. { string strTemp; if (DriveLocalToRemoteName(DRIVE_UNKNOWN, m_CurDir[0], strTemp)) { AddCollapsible(std::move(strTemp)); } break; } case L'+': // $+ - Отображение нужного числа знаков плюс (+) в зависимости от текущей глубины стека каталогов PUSHD, по одному знаку на каждый сохраненный путь. { strDestStr.append(ppstack.size(), L'+'); break; } case L'H': // $H - Backspace (erases previous character) { if (!strDestStr.empty()) { strDestStr.pop_back(); } else { auto Prev = Iterator; while (Prev != Result.begin()) { --Prev; if (!Prev->Text.empty()) { Prev->Text.pop_back(); break; } } } break; } case L'@': // $@xx - Admin { if (it + 1 != strExpandedDestStr.cend()) { const auto lb = *++it; if (it + 1 != strExpandedDestStr.cend()) { const auto rb = *++it; if (os::security::is_admin()) { append(strDestStr, lb, msg(lng::MConfigCmdlinePromptFormatAdmin), rb); } } } break; } case L'D': // $D - Current date case L'T': // $T - Current time { strDestStr += MkStrFTime(Chr == L'D'? L"%D" : L"%T"); break; } case L'N': // $N - Current drive { const auto Type = ParsePath(m_CurDir); if(Type == root_type::drive_letter) strDestStr += upper(m_CurDir[0]); else if(Type == root_type::unc_drive_letter) strDestStr += upper(m_CurDir[4]); else strDestStr += L'?'; break; } case L'W': // $W - Текущий рабочий каталог (без указания пути) { const auto pos = FindLastSlash(m_CurDir); if (pos != string::npos) { AddCollapsible(m_CurDir.substr(pos + 1)); } break; } case L'P': // $P - Current drive and path { AddCollapsible(string{ m_CurDir }); break; } case L'#': //$#nn - max prompt width in % { if (it + 1 != strExpandedDestStr.end()) { size_t pos; if (from_string(string(it + 1, strExpandedDestStr.cend()), NewPromptSize, &pos)) it += pos; // else // bad format, NewPromptSize unchanged // TODO: diagnostics } } } if (it == strExpandedDestStr.cend()) { break; } } } else {