Esempio n. 1
0
/* Закрасить прямоугольник символом Ch и цветом Color
*/
void ScreenBuf::FillRect(int X1,int Y1,int X2,int Y2,WCHAR Ch,const FarColor& Color)
{
	SCOPED_ACTION(CriticalSectionLock)(CS);
	int Width=X2-X1+1;
	int Height=Y2-Y1+1;
	int I, J;
	FAR_CHAR_INFO CI,*PtrBuf;
	CI.Attributes=Color;
	SetVidChar(CI,Ch);

	for (I=0; I < Height; I++)
	{
		for (PtrBuf = Buf.data() + (Y1 + I)*BufX + X1, J = 0; J < Width; J++, ++PtrBuf)
			*PtrBuf=CI;
	}

	SBFlags.Clear(SBFLAGS_FLUSHED);
#ifdef DIRECT_SCREEN_OUT
	Flush();
#elif defined(DIRECT_RT)

	if (Global->DirectRT)
		Flush();

#endif
}
Esempio n. 2
0
/* Записать Text в виртуальный буфер
*/
void ScreenBuf::Write(int X,int Y,const FAR_CHAR_INFO *Text, size_t Size)
{
	SCOPED_ACTION(CriticalSectionLock)(CS);

	if (X<0)
	{
		Text-=X;
		Size = std::max(0, static_cast<int>(Size) + X);
		X=0;
	}

	if (X>=BufX || Y>=BufY || !Size || Y<0)
		return;

	if (X+Size >= static_cast<size_t>(BufX))
		Size=BufX-X; //??

	FAR_CHAR_INFO *PtrBuf=Buf.data()+Y*BufX+X;

	for (size_t i=0; i < Size; i++)
	{
		SetVidChar(PtrBuf[i],Text[i].Char);
		PtrBuf[i].Attributes=Text[i].Attributes;
	}

	SBFlags.Clear(SBFLAGS_FLUSHED);
#ifdef DIRECT_SCREEN_OUT
	Flush();
#elif defined(DIRECT_RT)

	if (Global->DirectRT)
		Flush();

#endif
}
Esempio n. 3
0
void ConsoleTitle::SetFarTitle(const string& Title)
{
	SCOPED_ACTION(CriticalSectionLock)(TitleCS);
	string strOldFarTitle;

	Global->Console->GetTitle(strOldFarTitle);

	if (!GetUserTitle().empty())
	{
		FarTitle() = GetUserTitle();
	}
	else
	{
		FarTitle() = Title;
		FarTitle() += GetFarTitleAddons();
	}

	TitleModified=true;

	if (strOldFarTitle != FarTitle() && !Global->ScrBuf->GetLockCount())
	{
		Global->Console->SetTitle(FarTitle());
		TitleModified=true;
	}
}
Esempio n. 4
0
void SQLiteDb::Initialize(initialiser Initialiser, string_view const DbName, bool Local, bool WAL)
{
	assign(m_Name, DbName);

	os::mutex m(os::make_name<os::mutex>(Local? Global->Opt->LocalProfilePath : Global->Opt->ProfilePath, m_Name));
	SCOPED_ACTION(std::lock_guard<os::mutex>)(m);

	const auto& OpenAndInitialise = [&](string_view const Name)
	{
		return Open(Name, Local, WAL) && Initialiser(db_initialiser(this));
	};

	if (!OpenAndInitialise(m_Name))
	{
		Close();
		++init_status;

		const auto in_memory = Global->Opt->ReadOnlyConfig ||
			!(os::fs::move_file(m_Path, m_Path + L".bad"sv, MOVEFILE_REPLACE_EXISTING) && OpenAndInitialise(m_Name));

		if (in_memory)
		{
			Close();
			++init_status;
			OpenAndInitialise(MemoryDbName);
		}
	}
}
Esempio n. 5
0
int SimpleModal::ReadInput(INPUT_RECORD *GetReadRec)
{
	if (GetReadRec)
		ClearStruct(*GetReadRec);

	if (m_WriteKey>=0)
	{
		m_ReadKey=m_WriteKey;
		m_WriteKey=-1;
	}
	else
	{
		m_ReadKey=GetInputRecord(&m_ReadRec);

		if (GetReadRec)
		{
			*GetReadRec=m_ReadRec;
		}
	}

	if (m_ReadKey == KEY_CONSOLE_BUFFER_RESIZE)
	{
		SCOPED_ACTION(LockScreen);
		Hide();
		Show();
	}

	if (Global->CloseFARMenu)
	{
		SetExitCode(-1);
	}

	return m_ReadKey;
}
Esempio n. 6
0
/* Читать блок из виртуального буфера.
*/
void ScreenBuf::Read(int X1,int Y1,int X2,int Y2,FAR_CHAR_INFO *Text, size_t Size)
{
	SCOPED_ACTION(CriticalSectionLock)(CS);
	size_t Width=X2-X1+1;
	size_t Height=Y2-Y1+1;

	for (size_t Idx = 0, I = 0; I < Height; I++, Idx+=Width)
		std::copy(Buf.data() + (Y1 + I)*BufX + X1, Buf.data() + (Y1 + I)*BufX + X1 + std::min(Width, Size), Text + Idx);
}
Esempio n. 7
0
/*
  Функция TestFolder возвращает одно состояний тестируемого каталога:

    TSTFLD_NOTEMPTY   (2) - не пусто
    TSTFLD_EMPTY      (1) - пусто
    TSTFLD_NOTFOUND   (0) - нет такого
    TSTFLD_NOTACCESS (-1) - нет доступа
    TSTFLD_ERROR     (-2) - ошибка (кривые параметры или не хватило памяти для выделения промежуточных буферов)
*/
int TestFolder(const string& Path)
{
	if (Path.empty())
		return TSTFLD_ERROR;

	string strFindPath = Path;
	// сообразим маску для поиска.
	AddEndSlash(strFindPath);
	strFindPath += L"*";

	// первая проверка - че-нить считать можем?
	api::fs::enum_file Find(strFindPath);
	if (Find.begin() != Find.end())
	{
		return TSTFLD_NOTEMPTY;
	}

	Global->CatchError();
	DWORD LastError = Global->CaughtError();
	if (LastError == ERROR_FILE_NOT_FOUND || LastError == ERROR_NO_MORE_FILES)
		return TSTFLD_EMPTY;

	if (LastError == ERROR_PATH_NOT_FOUND)
		return TSTFLD_NOTFOUND;

	// собственно... не факт, что диск не читаем, т.к. на чистом диске в корне нету даже "."
	// поэтому посмотрим на Root
	GetPathRoot(Path,strFindPath);

	if (strFindPath == Path)
	{
		// проверка атрибутов гарантировано скажет - это бага BugZ#743 или пустой корень диска.
		if (api::fs::exists(strFindPath))
		{
			if (LastError == ERROR_ACCESS_DENIED)
				return TSTFLD_NOTACCESS;

			return TSTFLD_EMPTY;
		}
	}

	strFindPath = Path;

	if (CheckShortcutFolder(strFindPath,FALSE,TRUE))
	{
		if (strFindPath != Path)
			return TSTFLD_NOTFOUND;
	}

	{
		SCOPED_ACTION(elevation::suppress);
		if (api::fs::is_file(strFindPath))
			return TSTFLD_ERROR;
	}
	return TSTFLD_NOTACCESS;
}
Esempio n. 8
0
bool SetOwnerInternal(const string& Object, const string& Owner)
{
	bool Result = false;

	PSID Sid = nullptr;
	SCOPE_EXIT { LocalFree(Sid); };

	if(!ConvertStringSidToSid(Owner.data(), &Sid))
	{
		SID_NAME_USE Use;
		DWORD cSid=0, ReferencedDomain=0;
		LookupAccountName(nullptr, Owner.data(), nullptr, &cSid, nullptr, &ReferencedDomain, &Use);
		if(cSid)
		{
			Sid = LocalAlloc(LMEM_FIXED, cSid);
			if(Sid)
			{
				std::vector<wchar_t> ReferencedDomainName(ReferencedDomain);
				if(LookupAccountName(nullptr, Owner.data(), Sid, &cSid, ReferencedDomainName.data(), &ReferencedDomain, &Use))
				{
					;
				}
			}
		}
	}
	if(Sid)
	{
		SCOPED_ACTION(Privilege)(SE_TAKE_OWNERSHIP_NAME);
		SCOPED_ACTION(Privilege)(SE_RESTORE_NAME);
		DWORD dwResult = SetNamedSecurityInfo(const_cast<LPWSTR>(Object.data()), SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, Sid, nullptr, nullptr, nullptr);
		if(dwResult == ERROR_SUCCESS)
		{
			Result = true;
		}
		else
		{
			SetLastError(dwResult);
		}
	}
	return Result;
}
Esempio n. 9
0
/* Заполнение виртуального буфера значением из консоли.
*/
void ScreenBuf::FillBuf()
{
	SCOPED_ACTION(CriticalSectionLock)(CS);
	COORD BufferSize={BufX, BufY}, BufferCoord={};
	SMALL_RECT ReadRegion={0, 0, static_cast<SHORT>(BufX-1), static_cast<SHORT>(BufY-1)};
	Global->Console->ReadOutput(Buf.data(), BufferSize, BufferCoord, ReadRegion);
	std::copy(ALL_CONST_RANGE(Buf), Shadow.begin());
	SBFlags.Set(SBFLAGS_USESHADOW);
	COORD CursorPosition;
	Global->Console->GetCursorPosition(CursorPosition);
	CurX=CursorPosition.X;
	CurY=CursorPosition.Y;
}
Esempio n. 10
0
// used in block selection
void ScreenBuf::ApplyColor(int X1,int Y1,int X2,int Y2,const FarColor& Color, bool PreserveExFlags)
{
	SCOPED_ACTION(CriticalSectionLock)(CS);
	if(X1<=ScrX && Y1<=ScrY && X2>=0 && Y2>=0)
	{
		X1=std::max(0,X1);
		X2=std::min(static_cast<int>(ScrX),X2);
		Y1=std::max(0,Y1);
		Y2=std::min(static_cast<int>(ScrY),Y2);

		int Width=X2-X1+1;
		int Height=Y2-Y1+1;
		int I, J;

		FAR_CHAR_INFO *PtrBuf;
		if(PreserveExFlags)
		{
			for (I=0; I < Height; I++)
			{
				PtrBuf = Buf.data() + (Y1 + I)*BufX + X1;
				for (J=0; J < Width; J++, ++PtrBuf)
				{
					FARCOLORFLAGS ExFlags = PtrBuf->Attributes.Flags&FCF_EXTENDEDFLAGS;
					PtrBuf->Attributes=Color;
					PtrBuf->Attributes.Flags = (PtrBuf->Attributes.Flags&~FCF_EXTENDEDFLAGS)|ExFlags;
				}
			}
		}
		else
		{
			for (I=0; I < Height; I++)
			{
				PtrBuf = Buf.data() + (Y1 + I)*BufX + X1;
				for (J=0; J < Width; J++, ++PtrBuf)
				{
					PtrBuf->Attributes=Color;
				}
			}
		}

#ifdef DIRECT_SCREEN_OUT
		Flush();
#elif defined(DIRECT_RT)

		if (Global->DirectRT)
			Flush();

#endif
	}
}
Esempio n. 11
0
ConsoleTitle::~ConsoleTitle()
{
	SCOPED_ACTION(CriticalSectionLock)(TitleCS);
	const string &strTitleAddons = GetFarTitleAddons();
	size_t OldLen = strOldTitle.size();
	size_t AddonsLen = strTitleAddons.size();

	if (AddonsLen <= OldLen)
	{
		if (!StrCmpI(strOldTitle.data()+OldLen-AddonsLen, strTitleAddons.data()))
			strOldTitle.resize(OldLen-AddonsLen);
	}

	SetFarTitle(strOldTitle);
}
Esempio n. 12
0
void Panel::DragMessage(int X,int Y,int Move)
{
	const auto SelCount = SrcDragPanel->GetSelCount();

	if (!SelCount)
		return;

	string strSelName;

	if (SelCount == 1)
	{
		os::fs::find_data Data;
		if (!SrcDragPanel->get_first_selected(Data))
			return;

		assign(strSelName, PointToName(Data.FileName));
		QuoteSpace(strSelName);
	}
	else
	{
		strSelName = format(msg(lng::MDragFiles), SelCount);
	}

	auto strDragMsg = format(msg(Move? lng::MDragMove : lng::MDragCopy), strSelName);

	auto Length = static_cast<int>(strDragMsg.size());
	int MsgX = X;

	if (Length + X > ScrX)
	{
		MsgX=ScrX-Length;

		if (MsgX<0)
		{
			MsgX=0;
			TruncStrFromEnd(strDragMsg,ScrX);
			Length=(int)strDragMsg.size();
		}
	}

	SCOPED_ACTION(ChangePriority)(THREAD_PRIORITY_NORMAL);
	// Important - the old one must be deleted before creating a new one, not after
	DragSaveScr.reset();
	DragSaveScr = std::make_unique<SaveScreen>(MsgX, Y, MsgX + Length - 1, Y);
	GotoXY(MsgX,Y);
	SetColor(COL_PANELDRAGTEXT);
	Text(strDragMsg);
}
Esempio n. 13
0
bool message_manager::dispatch()
{
	bool Result = false;
	message_queue::value_type EventData;
	while (m_Messages.try_pop(EventData))
	{
		SCOPED_ACTION(std::shared_lock<mutex_type>)(m_RWLock);
		const auto RelevantListeners = m_Handlers.equal_range(EventData.first);
		std::for_each(RelevantListeners.first, RelevantListeners.second, [&](const handlers_map::value_type& i)
		{
			std::invoke(*i.second, EventData.second);
		});
		Result = Result || RelevantListeners.first != RelevantListeners.second;
	}
	m_Window->Check();
	return Result;
}
Esempio n. 14
0
void ScreenBuf::AllocBuf(int X,int Y)
{
	SCOPED_ACTION(CriticalSectionLock)(CS);

	if (X==BufX && Y==BufY)
		return;

	size_t Cnt=X*Y;

	// don't call vector.resize() here:
	// - it's never shrink
	// - we don't care about old content
	resize_nomove(Buf, Cnt);
	resize_nomove(Shadow, Cnt);

	BufX=X;
	BufY=Y;
}
Esempio n. 15
0
/*
  Преобразует Src в полный РЕАЛЬНЫЙ путь с учетом reparse point.
  Note that Src can be partially non-existent.
*/
string ConvertNameToReal(string_view const Object)
{
	SCOPED_ACTION(elevation::suppress);

	// Получим сначала полный путь до объекта обычным способом
	const auto FullPath = ConvertNameToFull(Object);
	auto strDest = FullPath;

	string Path = FullPath;
	os::fs::file File;

	for (;;)
	{
		if (File.Open(Path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING))
			break;

		if (IsRootPath(Path))
			break;

		Path = ExtractFilePath(Path);
	}

	if (File)
	{
		string FinalFilePath;
		File.GetFinalPathName(FinalFilePath);
		File.Close();

		//assert(!FinalFilePath.empty());

		if (!FinalFilePath.empty())
		{
			// append non-existent path part (if present)
			DeleteEndSlash(Path);

			if (FullPath.size() > Path.size() + 1)
				path::append(FinalFilePath, string_view(FullPath).substr(Path.size() + 1));

			FinalFilePath = TryConvertVolumeGuidToDrivePath(FinalFilePath);
			strDest = FinalFilePath;
		}
	}
	return strDest;
}
Esempio n. 16
0
void FileSystemWatcher::Watch(bool got_focus, bool check_time)
{
	PropagateException();

	SCOPED_ACTION(elevation::suppress);

	if(!m_RegistrationThread)
		m_RegistrationThread = os::thread(&os::thread::join, &FileSystemWatcher::Register, this);

	if (got_focus)
	{
		if (!m_IsFatFilesystem.second)
		{
			const auto strRoot = GetPathRoot(m_Directory);
			if (!strRoot.empty())
			{
				string strFileSystem;
				if (os::fs::GetVolumeInformation(strRoot, nullptr, nullptr, nullptr, nullptr, &strFileSystem))
					m_IsFatFilesystem.first = starts_with(strFileSystem, L"FAT"sv);
			}

			m_IsFatFilesystem.second = true;
		}

		if (m_IsFatFilesystem.first)
		{
			// emulate FAT folder time change
			// otherwise changes missed (FAT folder time is NOT modified)
			// the price is directory reload on each GOT_FOCUS event
			check_time = false;
			m_PreviousLastWriteTime = m_CurrentLastWriteTime - 1s;
		}
	}

	if (check_time)
	{
		if (!os::fs::GetFileTimeSimple(m_Directory, nullptr, nullptr, &m_CurrentLastWriteTime, nullptr))
		{
			m_PreviousLastWriteTime = {};
			m_CurrentLastWriteTime = {};
		}
	}
}
Esempio n. 17
0
void Language::init(const string& Path, int CountNeed)
{
	SCOPED_ACTION(GuardLastError);

	uintptr_t nCodePage = CP_OEMCP;
	string strLangName = Global->Opt->strLanguage.Get();
	api::File LangFile;

	if (!OpenLangFile(LangFile, Path, LangFileMask, Global->Opt->strLanguage, m_FileName, nCodePage, false, &strLangName))
	{
		throw std::runtime_error("Cannot find language data");
	}

	GetFileString GetStr(LangFile, nCodePage);

	if (CountNeed != -1)
	{
		reserve(CountNeed);
	}

	string Buffer;
	while (GetStr.GetString(Buffer))
	{
		RemoveExternalSpaces(Buffer);

		if (Buffer.empty() || Buffer.front() != L'\"')
			continue;

		if (Buffer.size() > 1 && Buffer.back() == L'\"')
		{
			Buffer.pop_back();
		}

		add(ConvertString(Buffer.data() + 1, Buffer.size() - 1));
	}

	//   Проведем проверку на количество строк в LNG-файлах
	if (CountNeed != -1 && CountNeed != static_cast<int>(size()))
	{
		throw std::runtime_error("Language data is incorrect or damaged");
	}
}
Esempio n. 18
0
void FileSystemWatcher::Watch(bool got_focus, bool check_time)
{
	SCOPED_ACTION(elevation::suppress);

	if(!bOpen)
	{
		bOpen = true;
		Done.Reset();
		DoneDone.Reset();
		WatchRegistered.Reset();
		Thread WatchThread;
		WatchThread.Start(&FileSystemWatcher::WatchRegister, this);
	}

	if (got_focus)
	{
		bool isFAT = false;
		string strRoot, strFileSystem;
		GetPathRoot(Directory, strRoot);
		if (!strRoot.empty())
		{
			if (api::GetVolumeInformation(strRoot, nullptr, nullptr, nullptr, nullptr, &strFileSystem))
				isFAT = (strFileSystem.substr(0,3) == L"FAT");
		}
		if (isFAT)             // emulate FAT folder time change
		{                      // otherwise changes missed (FAT folder time is NOT modified)
			check_time = false; // the price is directory reload on each GOT_FOCUS event
			PreviousLastWriteTime.dwLowDateTime = CurrentLastWriteTime.dwLowDateTime - 1;
		}
	}

	if (check_time)
	{
		if (!api::GetFileTimeSimple(Directory,nullptr,nullptr,&CurrentLastWriteTime,nullptr))
		{
			PreviousLastWriteTime.dwLowDateTime = 0;
			PreviousLastWriteTime.dwHighDateTime = 0;
			CurrentLastWriteTime.dwLowDateTime = 0;
			CurrentLastWriteTime.dwHighDateTime = 0;
		}
	}
}
Esempio n. 19
0
/* Изменить значение цветовых атрибутов в соответствии с маской
   (применяется для "создания" тени)
*/
void ScreenBuf::ApplyShadow(int X1,int Y1,int X2,int Y2)
{
	SCOPED_ACTION(CriticalSectionLock)(CS);
	int Width=X2-X1+1;
	int Height=Y2-Y1+1;
	int I, J;
	for (I=0; I < Height; I++)
	{
		FAR_CHAR_INFO *PtrBuf = Buf.data() + (Y1 + I)*BufX + X1;

		for (J=0; J < Width; J++, ++PtrBuf)
		{
			PtrBuf->Attributes.BackgroundColor = 0;

			if(PtrBuf->Attributes.Flags&FCF_FG_4BIT)
			{
				PtrBuf->Attributes.ForegroundColor&=~0x8;
				if(!COLORVALUE(PtrBuf->Attributes.ForegroundColor))
				{
					PtrBuf->Attributes.ForegroundColor=0x8;
				}
			}
			else
			{
				PtrBuf->Attributes.ForegroundColor&=~0x808080;
				if(!COLORVALUE(PtrBuf->Attributes.ForegroundColor))
				{
					PtrBuf->Attributes.ForegroundColor = 0x808080;
				}
			}
		}
	}

#ifdef DIRECT_SCREEN_OUT
	Flush();
#elif defined(DIRECT_RT)

	if (Global->DirectRT)
		Flush();

#endif
}
Esempio n. 20
0
static bool SetREPARSE_DATA_BUFFER(const string& Object, REPARSE_DATA_BUFFER* rdb)
{
	if (!IsReparseTagValid(rdb->ReparseTag))
		return false;

	SCOPED_ACTION(os::security::privilege){ SE_CREATE_SYMBOLIC_LINK_NAME };

	const auto Attributes = os::fs::get_file_attributes(Object);
	if(Attributes&FILE_ATTRIBUTE_READONLY)
	{
		os::fs::set_file_attributes(Object, Attributes&~FILE_ATTRIBUTE_READONLY);
	}

	SCOPE_EXIT
	{
		if (Attributes&FILE_ATTRIBUTE_READONLY)
			os::fs::set_file_attributes(Object, Attributes);
	};

	const auto& SetBuffer = [&](bool ForceElevation)
	{
		const os::fs::file fObject(Object, GetDesiredAccessForReparsePointChange(), 0, nullptr, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, nullptr, ForceElevation);
		DWORD dwBytesReturned;
		return fObject && fObject.IoControl(FSCTL_SET_REPARSE_POINT, rdb, rdb->ReparseDataLength + REPARSE_DATA_BUFFER_HEADER_SIZE, nullptr, 0, &dwBytesReturned);
	};

	if (SetBuffer(false))
		return true;

	if (ElevationRequired(ELEVATION_MODIFY_REQUEST))
	{
		// Open() succeeded, but IoControl() failed. We can't handle this automatically :(
		return SetBuffer(true);
	}

	return false;
}
Esempio n. 21
0
// used in stream selection
void ScreenBuf::ApplyColor(int X1,int Y1,int X2,int Y2,const FarColor& Color,const FarColor& ExceptColor, bool ForceExFlags)
{
	SCOPED_ACTION(CriticalSectionLock)(CS);
	if(X1<=ScrX && Y1<=ScrY && X2>=0 && Y2>=0)
	{
		X1=std::max(0,X1);
		X2=std::min(static_cast<int>(ScrX),X2);
		Y1=std::max(0,Y1);
		Y2=std::min(static_cast<int>(ScrY),Y2);

		for (int I = 0; I < Y2-Y1+1; I++)
		{
			FAR_CHAR_INFO* PtrBuf = Buf.data() + (Y1 + I)*BufX + X1;
			for (int J = 0; J < X2-X1+1; J++, ++PtrBuf)
			{
				if (PtrBuf->Attributes.ForegroundColor != ExceptColor.ForegroundColor || PtrBuf->Attributes.BackgroundColor != ExceptColor.BackgroundColor)
				{
					PtrBuf->Attributes=Color;
				}
				else if (ForceExFlags)
				{
					PtrBuf->Attributes.Flags = (PtrBuf->Attributes.Flags&~FCF_EXTENDEDFLAGS)|(Color.Flags&FCF_EXTENDEDFLAGS);
				}
			}
		}

#ifdef DIRECT_SCREEN_OUT
		Flush();
#elif defined(DIRECT_RT)

		if (Global->DirectRT)
			Flush();

#endif
	}
}
Esempio n. 22
0
// Косметические преобразования строки пути.
// CheckFullPath используется в FCTL_SET[ANOTHER]PANELDIR
void PrepareDiskPath(string &strPath, bool CheckFullPath)
{
	// elevation not required during cosmetic operation
	SCOPED_ACTION(elevation::suppress);

	if (!strPath.empty())
	{
		if (strPath.size() > 1 && (strPath[1]==L':' || (IsSlash(strPath[0]) && IsSlash(strPath[1]))))
		{
			ReplaceSlashToBackslash(strPath);
			bool DoubleSlash = strPath[1]==L'\\';
			while(ReplaceStrings(strPath, L"\\\\"sv, L"\\"sv))
				;
			if(DoubleSlash)
			{
				strPath = L'\\' + strPath;
			}

			if (CheckFullPath)
			{
				strPath = ConvertNameToFull(strPath);

				size_t DirOffset = 0;
				const auto Type = ParsePath(strPath, &DirOffset);
				if (Type == root_type::unknown && HasPathPrefix(strPath))
				{
					DirOffset = 4;
				}

				size_t StartPos = DirOffset;

				if (StartPos < strPath.size())
				{
					string TmpStr;
					TmpStr.reserve(strPath.size());
					size_t LastPos = StartPos;
					const auto EndsWithSlash = IsSlash(strPath.back());

					for (size_t i = StartPos; i <= strPath.size(); ++i)
					{
						if ((i < strPath.size() && IsSlash(strPath[i])) || (i == strPath.size() && !EndsWithSlash))
						{
							TmpStr.assign(strPath, 0, i);
							os::fs::find_data fd;

							if (os::fs::get_find_data(TmpStr, fd))
							{
								strPath.replace(LastPos, i - LastPos, fd.FileName);
								i += fd.FileName.size() - (i - LastPos);
							}

							if (i != strPath.size())
							{
								LastPos = i + 1;
							}
						}
					}
				}
			}

			if (ParsePath(strPath) == root_type::drive_letter)
			{
				strPath[0] = upper(strPath[0]);
			}
		}
	}
}
Esempio n. 23
0
static int MainProcess(
    const string& EditName,
    const string& ViewName,
    const string& DestName1,
    const string& DestName2,
    int StartLine,
    int StartChar
)
{
		SCOPED_ACTION(ChangePriority)(THREAD_PRIORITY_NORMAL);
		FarColor InitAttributes={};
		console.GetTextAttributes(InitAttributes);
		SetRealColor(colors::PaletteColorToFarColor(COL_COMMANDLINEUSERSCREEN));

		string ename(EditName),vname(ViewName), apanel(DestName1),ppanel(DestName2);
		if (ConfigProvider().ShowProblems())
		{
			ename.clear();
			vname.clear();
			StartLine = StartChar = -1;
			apanel = Global->Opt->ProfilePath;
			ppanel = Global->Opt->LocalProfilePath;
		}

		if (!ename.empty() || !vname.empty())
		{
			Global->OnlyEditorViewerUsed = true;

			_tran(SysLog(L"create dummy panels"));
			Global->CtrlObject->CreateDummyFilePanels();
			Global->WindowManager->PluginCommit();

			Global->CtrlObject->Plugins->LoadPlugins();
			Global->CtrlObject->Macro.LoadMacros(true, true);

			if (!ename.empty())
			{
				const auto ShellEditor = FileEditor::create(ename, CP_DEFAULT, FFILEEDIT_CANNEWFILE | FFILEEDIT_ENABLEF6, StartLine, StartChar);
				_tran(SysLog(L"make shelleditor %p",ShellEditor));

				if (!ShellEditor->GetExitCode())  // ????????????
				{
					Global->WindowManager->ExitMainLoop(0);
				}
			}
			// TODO: Этот else убрать только после разборок с возможностью задавать несколько /e и /v в ком.строке
			else if (!vname.empty())
			{
				const auto ShellViewer = FileViewer::create(vname, true);

				if (!ShellViewer->GetExitCode())
				{
					Global->WindowManager->ExitMainLoop(0);
				}

				_tran(SysLog(L"make shellviewer, %p",ShellViewer));
			}

			Global->WindowManager->EnterMainLoop();
		}
		else
		{
			int DirCount=0;

			// воспользуемся тем, что ControlObject::Init() создает панели
			// юзая Global->Opt->*

			const auto& SetupPanel = [&](bool active)
			{
				++DirCount;
				string strPath = active? apanel : ppanel;
				if (os::fs::is_file(strPath))
				{
					CutToParent(strPath);
				}

				bool Root = false;
				const auto Type = ParsePath(strPath, nullptr, &Root);
				if(Root && (Type == root_type::drive_letter || Type == root_type::unc_drive_letter || Type == root_type::volume))
				{
					AddEndSlash(strPath);
				}

				auto& CurrentPanelOptions = (Global->Opt->LeftFocus == active)? Global->Opt->LeftPanel : Global->Opt->RightPanel;
				CurrentPanelOptions.m_Type = static_cast<int>(panel_type::FILE_PANEL);  // сменим моду панели
				CurrentPanelOptions.Visible = true;     // и включим ее
				CurrentPanelOptions.Folder = strPath;
			};

			if (!apanel.empty())
			{
				SetupPanel(true);

				if (!ppanel.empty())
				{
					SetupPanel(false);
				}
			}

			// теперь все готово - создаем панели!
			Global->CtrlObject->Init(DirCount);

			// а теперь "провалимся" в каталог или хост-файл (если получится ;-)
			if (!apanel.empty())  // активная панель
			{
				const auto ActivePanel = Global->CtrlObject->Cp()->ActivePanel();
				const auto AnotherPanel = Global->CtrlObject->Cp()->PassivePanel();

				if (!ppanel.empty())  // пассивная панель
				{
					FarChDir(AnotherPanel->GetCurDir());

					if (IsPluginPrefixPath(ppanel))
					{
						AnotherPanel->Parent()->SetActivePanel(AnotherPanel);

						execute_info Info;
						Info.Command = ppanel;

						Global->CtrlObject->CmdLine()->ExecString(Info);
						ActivePanel->Parent()->SetActivePanel(ActivePanel);
					}
					else
					{
						const auto strPath = PointToName(ppanel);

						if (!strPath.empty())
						{
							if (AnotherPanel->GoToFile(strPath))
								AnotherPanel->ProcessKey(Manager::Key(KEY_CTRLPGDN));
						}
					}
				}

				FarChDir(ActivePanel->GetCurDir());

				if (IsPluginPrefixPath(apanel))
				{
					execute_info Info;
					Info.Command = apanel;

					Global->CtrlObject->CmdLine()->ExecString(Info);
				}
				else
				{
					const auto strPath = PointToName(apanel);

					if (!strPath.empty())
					{
						if (ActivePanel->GoToFile(strPath))
							ActivePanel->ProcessKey(Manager::Key(KEY_CTRLPGDN));
					}
				}

				// !!! ВНИМАНИЕ !!!
				// Сначала редравим пассивную панель, а потом активную!
				AnotherPanel->Redraw();
				ActivePanel->Redraw();
			}

			Global->WindowManager->EnterMainLoop();
		}

		TreeList::FlushCache();

		// очистим за собой!
		SetScreen(0,0,ScrX,ScrY,L' ',colors::PaletteColorToFarColor(COL_COMMANDLINEUSERSCREEN));
		console.SetTextAttributes(InitAttributes);
		Global->ScrBuf->ResetLockCount();
		Global->ScrBuf->Flush();

		return 0;
}
Esempio n. 24
0
void language::load(const string& Path, const string& Language, int CountNeed)
{
	SCOPED_ACTION(GuardLastError);

	auto Data = m_Data->create();

	const auto LangFileData = OpenLangFile(Path, LangFileMask, Language);
	const auto& LangFile = std::get<0>(LangFileData);
	const auto LangFileCodePage = std::get<2>(LangFileData);

	if (!LangFile)
	{
		throw MAKE_EXCEPTION(exception, L"Cannot find language data"sv);
	}

	Data->m_FileName = LangFile.GetName();

	if (CountNeed != -1)
	{
		Data->reserve(CountNeed);
	}

	std::unordered_map<string, size_t> id_map;
	string label, text;
	for (const auto& i: enum_file_lines(LangFile, LangFileCodePage))
	{
		bool have_text;
		parse_lng_line(trim(i.Str), label, text, have_text);
		if (have_text)
		{
			auto idx = Data->size();
			Data->add(ConvertString(text));
			if (!label.empty())
			{
				id_map[label] = idx;
				label.clear();
			}
		}
	}

	//   Проведем проверку на количество строк в LNG-файлах
	if (CountNeed != -1 && CountNeed != static_cast<int>(Data->size()))
	{
		throw MAKE_EXCEPTION(exception, Data->m_FileName + L": language data is incorrect or damaged"sv);
	}

	// try to load Far<LNG>.lng.custom file(s)
	//
	if (!id_map.empty())
	{
		const auto& LoadStrings = [&](const string& FileName)
		{
			const os::fs::file CustomFile(FileName, FILE_READ_DATA, FILE_SHARE_READ, nullptr, OPEN_EXISTING);
			if (!CustomFile)
				return;

			const auto CustomFileCodepage = GetFileCodepage(CustomFile, encoding::codepage::oem(), nullptr, false);
			label.clear();
			for (const auto& i: enum_file_lines(CustomFile, CustomFileCodepage))
			{
				bool have_text;
				parse_lng_line(trim(i.Str), label, text, have_text);
				if (have_text && !label.empty())
				{
					const auto found = id_map.find(label);
					if (found != id_map.end())
					{
						Data->set_at(found->second, ConvertString(text));
					}
					label.clear();
				}
			}
		};

		const auto CustomLngInSameDir = Data->m_FileName + L".custom"sv;
		const auto CustomLngInProfileDir = concat(Global->Opt->ProfilePath, L'\\', ExtractFileName(CustomLngInSameDir));

		LoadStrings(CustomLngInSameDir);
		LoadStrings(CustomLngInProfileDir);
	}

	m_Data = std::move(Data);
}
Esempio n. 25
0
void PrintFiles(FileList* SrcPanel)
{
	_ALGO(CleverSysLog clv(L"Alt-F5 (PrintFiles)"));
	string strPrinterName;
	DWORD Needed = 0, Returned;
	DWORD FileAttr;
	string strSelName;
	size_t DirsCount=0;
	size_t SelCount=SrcPanel->GetSelCount();

	if (!SelCount)
	{
		_ALGO(SysLog(L"Error: !SelCount"));
		return;
	}

	// проверка каталогов
	_ALGO(SysLog(L"Check for FILE_ATTRIBUTE_DIRECTORY"));
	SrcPanel->GetSelName(nullptr,FileAttr);

	while (SrcPanel->GetSelName(&strSelName,FileAttr))
	{
		if (TestParentFolderName(strSelName) || (FileAttr & FILE_ATTRIBUTE_DIRECTORY))
			DirsCount++;
	}

	if (DirsCount==SelCount)
		return;

	EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, nullptr, PRINTER_INFO_LEVEL, nullptr, 0, &Needed, &Returned);

	if (!Needed)
		return;

	block_ptr<PRINTER_INFO> pi(Needed);

	if (!EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS,nullptr,PRINTER_INFO_LEVEL,(LPBYTE)pi.get(),Needed,&Needed,&Returned))
	{
		Global->CatchError();
		Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MPrintTitle),MSG(MCannotEnumeratePrinters),MSG(MOk));
		return;
	}

	{
		_ALGO(CleverSysLog clv2(L"Show Menu"));
		LangString strTitle;
		string strName;

		if (SelCount==1)
		{
			SrcPanel->GetSelName(nullptr,FileAttr);
			SrcPanel->GetSelName(&strName,FileAttr);
			strSelName = TruncStr(strName,50);
			strTitle = MPrintTo;
			strTitle << InsertQuote(strSelName);
		}
		else
		{
			_ALGO(SysLog(L"Correct: SelCount-=DirsCount"));
			SelCount-=DirsCount;
			strTitle = MPrintFilesTo;
			strTitle << SelCount;
		}

		VMenu2 PrinterList(strTitle,nullptr,0,ScrY-4);
		PrinterList.SetFlags(VMENU_WRAPMODE|VMENU_SHOWAMPERSAND);
		PrinterList.SetPosition(-1,-1,0,0);
		AddToPrintersMenu(&PrinterList,pi.get(),Returned);

		if (PrinterList.Run()<0)
		{
			_ALGO(SysLog(L"ESC"));
			return;
		}

		strPrinterName = NullToEmpty(static_cast<const wchar_t*>(PrinterList.GetUserData(nullptr, 0)));
	}

	HANDLE hPrinter;

	if (!OpenPrinter(UNSAFE_CSTR(strPrinterName), &hPrinter,nullptr))
	{
		Global->CatchError();
		Message(MSG_WARNING|MSG_ERRORTYPE,1,MSG(MPrintTitle),MSG(MCannotOpenPrinter),
		        strPrinterName.data(),MSG(MOk));
		_ALGO(SysLog(L"Error: Cannot Open Printer"));
		return;
	}

	{
		_ALGO(CleverSysLog clv3(L"Print selected Files"));
		SCOPED_ACTION(SaveScreen);

		auto PR_PrintMsg = [](){ Message(0, 0, MSG(MPrintTitle), MSG(MPreparingForPrinting)); };

		SCOPED_ACTION(TPreRedrawFuncGuard)(std::make_unique<PreRedrawItem>(PR_PrintMsg));
		SetCursorType(false, 0);
		PR_PrintMsg();
		auto hPlugin=SrcPanel->GetPluginHandle();
		int PluginMode=SrcPanel->GetMode()==PLUGIN_PANEL &&
		               !Global->CtrlObject->Plugins->UseFarCommand(hPlugin,PLUGIN_FARGETFILE);
		SrcPanel->GetSelName(nullptr,FileAttr);

		while (SrcPanel->GetSelName(&strSelName,FileAttr))
		{
			if (TestParentFolderName(strSelName) || (FileAttr & FILE_ATTRIBUTE_DIRECTORY))
				continue;

			int Success=FALSE;
			string FileName;
			string strTempDir, strTempName;

			if (PluginMode)
			{
				if (FarMkTempEx(strTempDir))
				{
					api::CreateDirectory(strTempDir,nullptr);
					auto ListItem = SrcPanel->GetLastSelectedItem();
					if (ListItem)
					{
						PluginPanelItem PanelItem;
						FileList::FileListToPluginItem(*ListItem, &PanelItem);

						if (Global->CtrlObject->Plugins->GetFile(hPlugin,&PanelItem,strTempDir,strTempName,OPM_SILENT))
							FileName = strTempName;
						else
							api::RemoveDirectory(strTempDir);

						FreePluginPanelItem(PanelItem);
					}
				}
			}
			else
				FileName = strSelName;

			api::File SrcFile;
			if(SrcFile.Open(FileName, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, nullptr, OPEN_EXISTING))
			{
				DOC_INFO_1 di1 = {UNSAFE_CSTR(FileName)};

				if (StartDocPrinter(hPrinter,1,(LPBYTE)&di1))
				{
					char Buffer[8192];
					DWORD Read,Written;
					Success=TRUE;

					while (SrcFile.Read(Buffer, sizeof(Buffer), Read) && Read > 0)
						if (!WritePrinter(hPrinter,Buffer,Read,&Written))
						{
							Global->CatchError();
							Success=FALSE;
							break;
						}

					EndDocPrinter(hPrinter);
				}
				SrcFile.Close();
			}

			if (!strTempName.empty())
			{
				DeleteFileWithFolder(strTempName);
			}

			if (Success)
				SrcPanel->ClearLastGetSelection();
			else
			{
				if (Message(MSG_WARNING|MSG_ERRORTYPE,2,MSG(MPrintTitle),MSG(MCannotPrint),
				            strSelName.data(),MSG(MSkip),MSG(MCancel)))
					break;
			}
		}

		ClosePrinter(hPrinter);
	}

	SrcPanel->Redraw();
}
Esempio n. 26
0
/* "Сбросить" виртуальный буфер на консоль
*/
void ScreenBuf::Flush(bool SuppressIndicators)
{
	SCOPED_ACTION(CriticalSectionLock)(CS);

	if (!LockCount)
	{
		if (!SuppressIndicators)
		{
			if(Global->CtrlObject &&
				(Global->CtrlObject->Macro.IsRecording() ||
				(Global->CtrlObject->Macro.IsExecuting() && Global->Opt->Macro.ShowPlayIndicator))
			)
			{
				MacroChar=Buf[0];
				MacroCharUsed=true;

				if(Global->CtrlObject->Macro.IsRecording())
				{
					Buf[0].Char=L'R';
					Buf[0].Attributes = Colors::ConsoleColorToFarColor(B_LIGHTRED|F_WHITE);
				}
				else
				{
					Buf[0].Char=L'P';
					Buf[0].Attributes = Colors::ConsoleColorToFarColor(B_GREEN|F_WHITE);
				}
			}

			if(Global->Elevation->Elevated())
			{
				ElevationChar=Buf[BufX*BufY-1];
				ElevationCharUsed=true;

				Buf[BufX*BufY-1].Char=L'A';
				Buf[BufX*BufY-1].Attributes = Colors::ConsoleColorToFarColor(B_LIGHTRED|F_WHITE);
			}
		}

		if (!SBFlags.Check(SBFLAGS_FLUSHEDCURTYPE) && !CurVisible)
		{
			CONSOLE_CURSOR_INFO cci={CurSize,CurVisible};
			Global->Console->SetCursorInfo(cci);
			SBFlags.Set(SBFLAGS_FLUSHEDCURTYPE);
		}

		if (!SBFlags.Check(SBFLAGS_FLUSHED))
		{
			SBFlags.Set(SBFLAGS_FLUSHED);

			if (Global->WaitInMainLoop && Global->Opt->Clock && !Global->ProcessShowClock)
			{
				ShowTime(FALSE);
			}

			std::list<SMALL_RECT>WriteList;
			bool Changes=false;

			if (SBFlags.Check(SBFLAGS_USESHADOW))
			{
				FAR_CHAR_INFO* PtrBuf = Buf.data(), *PtrShadow = Shadow.data();

				if (Global->Opt->ClearType)
				{
					//Для полного избавления от артефактов ClearType будем перерисовывать на всю ширину.
					//Чревато тормозами/миганием в зависимости от конфигурации системы.
					SMALL_RECT WriteRegion={0,0,static_cast<SHORT>(BufX-1),0};

					for (SHORT I=0; I<BufY; I++, PtrBuf+=BufX, PtrShadow+=BufX)
					{
						WriteRegion.Top=I;
						WriteRegion.Bottom=I-1;

						while (I<BufY && memcmp(PtrBuf,PtrShadow,BufX*sizeof(FAR_CHAR_INFO))!=0)
						{
							I++;
							PtrBuf+=BufX;
							PtrShadow+=BufX;
							WriteRegion.Bottom++;
						}

						if (WriteRegion.Bottom >= WriteRegion.Top)
						{
							WriteList.emplace_back(WriteRegion);
							Changes=true;
						}
					}
				}
				else
				{
					bool Started=false;
					SMALL_RECT WriteRegion={static_cast<SHORT>(BufX-1),static_cast<SHORT>(BufY-1),0,0};

					for (SHORT I=0; I<BufY; I++)
					{
						for (SHORT J=0; J<BufX; J++,++PtrBuf,++PtrShadow)
						{
							if (memcmp(PtrBuf,PtrShadow,sizeof(FAR_CHAR_INFO))!=0)
							{
								WriteRegion.Left=std::min(WriteRegion.Left,J);
								WriteRegion.Top=std::min(WriteRegion.Top,I);
								WriteRegion.Right=std::max(WriteRegion.Right,J);
								WriteRegion.Bottom=std::max(WriteRegion.Bottom,I);
								Changes=true;
								Started=true;
							}
							else if (Started && I>WriteRegion.Bottom && J>=WriteRegion.Left)
							{
								//BUGBUG: при включенном СlearType-сглаживании на экране остаётся "мусор" - тонкие вертикальные полосы
								// кстати, и при выключенном тоже (но реже).
								// баг, конечно, не наш, но что делать.
								// расширяем область прорисовки влево-вправо на 1 символ:
								WriteRegion.Left=std::max(static_cast<SHORT>(0),static_cast<SHORT>(WriteRegion.Left-1));
								WriteRegion.Right=std::min(static_cast<SHORT>(WriteRegion.Right+1),static_cast<SHORT>(BufX-1));
								bool Merge=false;
								if (!WriteList.empty())
								{
									SMALL_RECT& Last=WriteList.back();
									const int MAX_DELTA = 5;
									if (WriteRegion.Top-1==Last.Bottom && ((WriteRegion.Left>=Last.Left && WriteRegion.Left-Last.Left<MAX_DELTA) || (Last.Right>=WriteRegion.Right && Last.Right-WriteRegion.Right<MAX_DELTA)))
									{
										Last.Bottom=WriteRegion.Bottom;
										Last.Left=std::min(Last.Left,WriteRegion.Left);
										Last.Right=std::max(Last.Right,WriteRegion.Right);
										Merge=true;
									}
								}

								if (!Merge)
									WriteList.emplace_back(WriteRegion);

								WriteRegion.Left=BufX-1;
								WriteRegion.Top=BufY-1;
								WriteRegion.Right=0;
								WriteRegion.Bottom=0;
								Started=false;
							}
						}
					}

					if (Started)
					{
						WriteList.emplace_back(WriteRegion);
					}
				}
			}
			else
			{
				Changes=true;
				SMALL_RECT WriteRegion={0,0,static_cast<SHORT>(BufX-1),static_cast<SHORT>(BufY-1)};
				WriteList.emplace_back(WriteRegion);
			}

			if (Changes)
			{
				std::for_each(CONST_RANGE(WriteList, i)
				{
					COORD BufferSize={BufX, BufY}, BufferCoord={i.Left, i.Top};
					SMALL_RECT WriteRegion = i;
					Global->Console->WriteOutput(Buf.data(), BufferSize, BufferCoord, WriteRegion);
				});
				Global->Console->Commit();
				std::copy(ALL_CONST_RANGE(Buf), Shadow.begin());
			}
Esempio n. 27
0
void DizList::Read(const string& Path, const string* DizName)
{
	Reset();

	struct DizPreRedrawItem : public PreRedrawItem
	{
		DizPreRedrawItem() : PreRedrawItem(PR_ReadingMsg) {}
	};

	SCOPED_ACTION(TPreRedrawFuncGuard)(std::make_unique<DizPreRedrawItem>());
	const wchar_t *NamePtr=Global->Opt->Diz.strListNames.data();

	for (;;)
	{
		if (DizName)
		{
			strDizFileName = *DizName;
		}
		else
		{
			strDizFileName = Path;

			if (!PathCanHoldRegularFile(strDizFileName))
				break;

			string strArgName;
			NamePtr = GetCommaWord(NamePtr, strArgName);

			if (!NamePtr)
				break;

			AddEndSlash(strDizFileName);
			strDizFileName += strArgName;
		}

		os::fs::file DizFile;
		if (DizFile.Open(strDizFileName,GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING))
		{
			clock_t StartTime=clock();
			uintptr_t CodePage=CP_DEFAULT;
			bool bSigFound=false;

			if (!GetFileFormat(DizFile,CodePage,&bSigFound,false) || !bSigFound)
				CodePage = Global->Opt->Diz.AnsiByDefault ? CP_ACP : CP_OEMCP;

			GetFileString GetStr(DizFile, CodePage);

			auto LastAdded = DizData.end(); 
			string DizText;
			while (GetStr.GetString(DizText))
			{
				if (!(DizData.size() & 127) && clock() - StartTime > CLOCKS_PER_SEC)
				{
					SetCursorType(false, 0);
					PR_ReadingMsg();

					if (CheckForEsc())
						break;
				}

				RemoveTrailingSpaces(DizText);

				if (!DizText.empty())
				{
					if(!IsSpace(DizText.front()))
					{
						LastAdded = AddRecord(DizText);
					}
					else
					{
						if (LastAdded != DizData.end())
						{
							LastAdded->second.emplace_back(DizText);
						}
					}
				}
			}

			OrigCodePage=CodePage;
			Modified=false;
			DizFile.Close();
			return;
		}

		if (DizName)
			break;
	}

	Modified=false;
	strDizFileName.clear();
}
Esempio n. 28
0
void FileList::ReadFileNames(int KeepSelection, int UpdateEvenIfPanelInvisible, int DrawMessage)
{
	SCOPED_ACTION(TPreRedrawFuncGuard)(std::make_unique<FileListPreRedrawItem>());
	SCOPED_ACTION(TaskBar)(false);

	strOriginalCurDir = strCurDir;

	if (!IsVisible() && !UpdateEvenIfPanelInvisible)
	{
		UpdateRequired=TRUE;
		UpdateRequiredMode=KeepSelection;
		return;
	}

	UpdateRequired=FALSE;
	AccessTimeUpdateRequired=FALSE;
	DizRead=FALSE;
	api::FAR_FIND_DATA fdata;
	decltype(ListData) OldData;
	string strCurName, strNextCurName;
	StopFSWatcher();

	if (this!=Global->CtrlObject->Cp()->LeftPanel && this!=Global->CtrlObject->Cp()->RightPanel)
		return;

	string strSaveDir;
	api::GetCurrentDirectory(strSaveDir);
	{
		string strOldCurDir(strCurDir);

		if (!SetCurPath())
		{
			FlushInputBuffer(); // Очистим буффер ввода, т.к. мы уже можем быть в другом месте...

			if (strCurDir == strOldCurDir) //?? i??
			{
				GetPathRoot(strOldCurDir,strOldCurDir);

				if (!api::IsDiskInDrive(strOldCurDir))
					IfGoHome(strOldCurDir.front());

				/* При смене каталога путь не изменился */
			}

			return;
		}
	}
	SortGroupsRead=FALSE;

	if (GetFocus())
		Global->CtrlObject->CmdLine->SetCurDir(strCurDir);

	LastCurFile=-1;
	Panel *AnotherPanel=Global->CtrlObject->Cp()->GetAnotherPanel(this);
	AnotherPanel->QViewDelTempName();
	size_t PrevSelFileCount=SelFileCount;
	SelFileCount=0;
	SelFileSize=0;
	TotalFileCount=0;
	TotalFileSize=0;
	CacheSelIndex=-1;
	CacheSelClearIndex=-1;
	FreeDiskSize = -1;
	if (Global->Opt->ShowPanelFree)
	{
		api::GetDiskSize(strCurDir, nullptr, nullptr, &FreeDiskSize);
	}

	if (!ListData.empty())
	{
		strCurName = ListData[CurFile].strName;

		if (ListData[CurFile].Selected && !ReturnCurrentFile)
		{
			for (size_t i=CurFile+1; i < ListData.size(); i++)
			{
				if (!ListData[i].Selected)
				{
					strNextCurName = ListData[i].strName;
					break;
				}
			}
		}
	}

	if (KeepSelection || PrevSelFileCount>0)
	{
		OldData.swap(ListData);
	}
	else
		DeleteListData(ListData);

	DWORD FileSystemFlags = 0;
	string PathRoot;
	GetPathRoot(strCurDir, PathRoot);
	api::GetVolumeInformation(PathRoot, nullptr, nullptr, nullptr, &FileSystemFlags, nullptr);

	ListData.clear();

	bool ReadOwners = IsColumnDisplayed(OWNER_COLUMN);
	bool ReadNumLinks = IsColumnDisplayed(NUMLINK_COLUMN);
	bool ReadNumStreams = IsColumnDisplayed(NUMSTREAMS_COLUMN);
	bool ReadStreamsSize = IsColumnDisplayed(STREAMSSIZE_COLUMN);

	if (!(FileSystemFlags&FILE_SUPPORTS_HARD_LINKS) && IsWindows7OrGreater())
	{
		ReadNumLinks = false;
	}

	if(!(FileSystemFlags&FILE_NAMED_STREAMS))
	{
		ReadNumStreams = false;
		ReadStreamsSize = false;
	}

	string strComputerName;

	if (ReadOwners)
	{
		string strTemp;
		CurPath2ComputerName(strCurDir, strComputerName, strTemp);
	}

	SetLastError(ERROR_SUCCESS);
	// сформируем заголовок вне цикла
	string Title = MakeSeparator(X2-X1-1, 9, nullptr);
	BOOL IsShowTitle=FALSE;
	BOOL NeedHighlight=Global->Opt->Highlight && PanelMode != PLUGIN_PANEL;

	if (!Filter)
		Filter = std::make_unique<FileFilter>(this,FFT_PANEL);

	//Рефреш текущему времени для фильтра перед началом операции
	Filter->UpdateCurrentTime();
	Global->CtrlObject->HiFiles->UpdateCurrentTime();
	bool bCurDirRoot = false;
	ParsePath(strCurDir, nullptr, &bCurDirRoot);
	PATH_TYPE Type = ParsePath(strCurDir, nullptr, &bCurDirRoot);
	bool NetRoot = bCurDirRoot && (Type == PATH_REMOTE || Type == PATH_REMOTEUNC);

	string strFind(strCurDir);
	AddEndSlash(strFind);
	strFind+=L'*';
	api::FindFile Find(strFind, true);
	DWORD FindErrorCode = ERROR_SUCCESS;
	bool UseFilter=Filter->IsEnabledOnPanel();
	bool ReadCustomData=IsColumnDisplayed(CUSTOM_COLUMN0)!=0;

	DWORD StartTime = GetTickCount();

	std::all_of(CONST_RANGE(Find, fdata) -> bool
	{
		Global->CatchError();
		FindErrorCode = Global->CaughtError();

		if ((Global->Opt->ShowHidden || !(fdata.dwFileAttributes & (FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM))) && (!UseFilter || Filter->FileInFilter(fdata, nullptr, &fdata.strFileName)))
		{
			if (ListData.size() == ListData.capacity())
				ListData.reserve(ListData.size() + 4096);

			ListData.emplace_back(VALUE_TYPE(ListData)());
			auto& NewItem = ListData.back();

			NewItem.FileAttr = fdata.dwFileAttributes;
			NewItem.CreationTime = fdata.ftCreationTime;
			NewItem.AccessTime = fdata.ftLastAccessTime;
			NewItem.WriteTime = fdata.ftLastWriteTime;
			NewItem.ChangeTime = fdata.ftChangeTime;
			NewItem.FileSize = fdata.nFileSize;
			NewItem.AllocationSize = fdata.nAllocationSize;
			NewItem.strName = fdata.strFileName;
			NewItem.strShortName = fdata.strAlternateFileName;
			NewItem.Position = ListData.size() - 1;
			NewItem.NumberOfLinks=1;

			if (fdata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
			{
				NewItem.ReparseTag=fdata.dwReserved0; //MSDN
			}
			if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
			{
				TotalFileSize += NewItem.FileSize;

				if (ReadNumLinks)
					NewItem.NumberOfLinks = GetNumberOfLinks(fdata.strFileName, true);
			}
			else
			{
				NewItem.AllocationSize = 0;
			}

			NewItem.SortGroup=DEFAULT_SORT_GROUP;

			if (ReadOwners)
			{
				string strOwner;
				GetFileOwner(strComputerName, NewItem.strName,strOwner);
				NewItem.strOwner = strOwner;
			}

			NewItem.NumberOfStreams=NewItem.FileAttr&FILE_ATTRIBUTE_DIRECTORY?0:1;
			NewItem.StreamsSize=NewItem.FileSize;

			if (ReadNumStreams||ReadStreamsSize)
			{
				EnumStreams(TestParentFolderName(fdata.strFileName)? strCurDir : fdata.strFileName, NewItem.StreamsSize, NewItem.NumberOfStreams);
			}

			if (ReadCustomData)
				NewItem.strCustomData = Global->CtrlObject->Plugins->GetCustomData(NewItem.strName);

			if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
				TotalFileCount++;

			DWORD CurTime = GetTickCount();
			if (CurTime - StartTime > (DWORD)Global->Opt->RedrawTimeout)
			{
				StartTime = CurTime;
				if (IsVisible())
				{
					if (!IsShowTitle)
					{
						if (!DrawMessage)
						{
							Text(X1+1,Y1,ColorIndexToColor(COL_PANELBOX),Title);
							IsShowTitle=TRUE;
							SetColor(Focus ? COL_PANELSELECTEDTITLE:COL_PANELTITLE);
						}
					}

					LangString strReadMsg(MReadingFiles);
					strReadMsg << ListData.size();

					if (DrawMessage)
					{
						ReadFileNamesMsg(strReadMsg);
					}
					else
					{
						TruncStr(strReadMsg,static_cast<int>(Title.size())-2);
						int MsgLength=(int)strReadMsg.size();
						GotoXY(X1+1+(static_cast<int>(Title.size())-MsgLength-1)/2,Y1);
						Global->FS << L" "<<strReadMsg<<L" ";
					}
				}

				Global->CtrlObject->Macro.SuspendMacros(true);
				bool check = CheckForEsc();
				Global->CtrlObject->Macro.SuspendMacros(false);
				if (check)
				{
					// break loop
					return false;
				}
			}
		}
		return true;
	});
Esempio n. 29
0
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;
		});
Esempio n. 30
0
/* $ 06.07.2001
   + Используем filemasks вместо GetCommaWord, этим самым добиваемся того, что
     можно использовать маски исключения
   - Убрал непонятный мне запрет на использование маски файлов типа "*.*"
     (был когда-то, вроде, такой баг-репорт)
*/
bool ProcessLocalFileTypes(const string& Name, const string& ShortName, FILETYPE_MODE Mode, bool AlwaysWaitFinish)
{
	string strCommand, strDescription, strMask;
	{
		const auto TypesMenu = VMenu2::create(MSG(MSelectAssocTitle), nullptr, 0, ScrY - 4);
		TypesMenu->SetHelp(L"FileAssoc");
		TypesMenu->SetMenuFlags(VMENU_WRAPMODE);
		TypesMenu->SetId(SelectAssocMenuId);

		int ActualCmdCount=0; // отображаемых ассоциаций в меню
		filemasks FMask; // для работы с масками файлов

		int CommandCount=0;
		DWORD Index=0;
		unsigned __int64 id;
		string FileName = PointToName(Name);

		while (ConfigProvider().AssocConfig()->EnumMasksForType(Mode,Index++,&id,strMask))
		{
			strCommand.clear();

			if (FMask.Set(strMask,FMF_SILENT))
			{
				if (FMask.Compare(FileName))
				{
					ConfigProvider().AssocConfig()->GetCommand(id,Mode,strCommand);

					if (!strCommand.empty())
					{
						ConfigProvider().AssocConfig()->GetDescription(id,strDescription);
						CommandCount++;
					}
				}

				if (strCommand.empty())
					continue;
			}

			string strCommandText = strCommand;
			SubstFileName(nullptr,strCommandText,Name, ShortName,nullptr,nullptr,nullptr,nullptr,TRUE);

			// все "подставлено", теперь проверим условия "if exist"
			if (!ExtractIfExistCommand(strCommandText))
				continue;

			ActualCmdCount++;

			if (!strDescription.empty())
				SubstFileName(nullptr,strDescription, Name, ShortName, nullptr, nullptr, nullptr, nullptr, TRUE);
			else
				strDescription = strCommandText;

			MenuItemEx TypesMenuItem(strDescription);
			TypesMenuItem.SetSelect(Index==1);
			TypesMenuItem.UserData = strCommand;
			TypesMenu->AddItem(TypesMenuItem);
		}

		if (!CommandCount)
			return false;

		if (!ActualCmdCount)
			return true;

		int ExitCode=0;

		if (ActualCmdCount>1)
		{
			ExitCode=TypesMenu->Run();

			if (ExitCode<0)
				return true;
		}

		strCommand = *TypesMenu->GetUserDataPtr<string>(ExitCode);
	}

	string strListName, strAnotherListName, strShortListName, strAnotherShortListName;

	const string* ListNames[] =
	{
		&strListName,
		&strAnotherListName,
		&strShortListName,
		&strAnotherShortListName
	};

	int PreserveLFN=SubstFileName(nullptr,strCommand, Name, ShortName, &strListName, &strAnotherListName, &strShortListName, &strAnotherShortListName);
	const auto ListFileUsed = !std::all_of(ALL_CONST_RANGE(ListNames), std::mem_fn(&string::empty));

	// Снова все "подставлено", теперь проверим условия "if exist"
	if (ExtractIfExistCommand(strCommand))
	{
		SCOPED_ACTION(PreserveLongName)(ShortName, PreserveLFN);
		RemoveExternalSpaces(strCommand);

		if (!strCommand.empty())
		{
			Global->CtrlObject->CmdLine()->ExecString(strCommand,AlwaysWaitFinish, false, false, ListFileUsed, false,
				Mode == FILETYPE_VIEW || Mode == FILETYPE_ALTVIEW || Mode == FILETYPE_EDIT || Mode == FILETYPE_ALTEDIT);
			if (!(Global->Opt->ExcludeCmdHistory&EXCLUDECMDHISTORY_NOTFARASS) && !AlwaysWaitFinish) //AN
			{
				const auto curDir = Global->CtrlObject->CmdLine()->GetCurDir();
				Global->CtrlObject->CmdHistory->AddToHistory(strCommand, HR_DEFAULT, nullptr, nullptr, curDir.data());
			}
		}
	}

	std::for_each(CONST_RANGE(ListNames, i)
	{
		if (!i->empty())
			os::DeleteFile(*i);
	});