コード例 #1
0
ファイル: panel.cpp プロジェクト: johnd0e/farmanager
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;
}
コード例 #2
0
ファイル: Directory.cpp プロジェクト: chatgen/pandion
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;
	}
}
コード例 #3
0
ファイル: pathmix.cpp プロジェクト: alexlav/conemu
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);
}
コード例 #4
0
ファイル: pathmix.cpp プロジェクト: alexlav/conemu
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);
}
コード例 #5
0
ファイル: pathmix.cpp プロジェクト: alexlav/conemu
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;
}
コード例 #6
0
ファイル: usermenu.cpp プロジェクト: alexlav/conemu
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);
}
コード例 #7
0
ファイル: flshow.cpp プロジェクト: landswellsong/FAR
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();
}
コード例 #8
0
ファイル: flink.cpp プロジェクト: johnd0e/farmanager
// Кусок для создания 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;
}
コード例 #9
0
ファイル: cmdline.cpp プロジェクト: johnd0e/farmanager
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
				{