DialogItemEx *DialogBuilder::AddListControl(FARDIALOGITEMTYPES Type, IntOption& Value, string *Text, int Width, int Height, const std::vector<FarDialogBuilderListItem2> &Items, FARDIALOGITEMFLAGS Flags) { const auto Item = AddDialogItem(Type, Text ? Text->c_str() : L""); SetNextY(Item); Item->X2 = Item->X1 + Width; Item->Y2 = Item->Y1 + Height; Item->Flags |= DIF_DROPDOWNLIST|Flags; m_NextY += Height; const auto ListItems = new FarListItem[Items.size()]; std::transform(ALL_CONST_RANGE(Items), ListItems, [&Value](const auto& i) { FarListItem NewItem = {}; NewItem.Text = i.Text.c_str(); NewItem.Flags = i.Flags | ((Value == i.ItemValue)? LIF_SELECTED : 0); NewItem.UserData = i.ItemValue; return NewItem; }); const auto List = new FarList; List->StructSize = sizeof(FarList); List->Items = ListItems; List->ItemsNumber = Items.size(); Item->ListItems = List; SetLastItemBinding(new FarListControlBinding<IntOption>(Value, Text, List)); return Item; }
static wchar_t* AddString(const string& String) { auto result = new wchar_t[String.size() + 1]; std::copy(ALL_CONST_RANGE(String), result); result[String.size()] = 0; return result; }
size_t find_icase(string_view const Str, string_view const What, size_t Pos) { if (Pos >= Str.size()) return Str.npos; const auto It = std::search(Str.cbegin() + Pos, Str.cend(), ALL_CONST_RANGE(What), equal_icase_t{}); return It == Str.cend()? Str.npos : It - Str.cbegin(); }
void ScreenBuf::DebugDump() const { #ifdef _DEBUG string s(Buf.width() + 1, L' '); s.back() = L'\n'; for (size_t row_num = 0; row_num != Buf.height(); ++row_num) { const auto&& row = Buf[row_num]; std::transform(ALL_CONST_RANGE(row), s.begin(), [](CONST_REFERENCE(row) i) { return i.Char; }); OutputDebugString(s.data()); }
bool NamesList::SetCurName(const string& Name) { bool Result = false; const auto ItemIterator = std::find(ALL_CONST_RANGE(Names), Name); if (ItemIterator != Names.cend()) { CurPos = ItemIterator; Result = true; } return Result; }
/* Заполнение виртуального буфера значением из консоли. */ 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; }
// try to replace volume GUID (if present) with drive letter // used by ConvertNameToReal() only static string TryConvertVolumeGuidToDrivePath(string_view const Path, const string_view AbsPath = {}) { string Result(Path); size_t DirectoryOffset; if (ParsePath(Path, &DirectoryOffset) == root_type::volume) { if (imports.GetVolumePathNamesForVolumeNameW) { string VolumePathNames; if (os::fs::GetVolumePathNamesForVolumeName(ExtractPathRoot(Path), VolumePathNames)) { for(const auto& i: enum_substrings(VolumePathNames.c_str())) { if (!AbsPath.empty() && starts_with_icase(AbsPath, i)) return string(i); if (IsRootPath(i)) { Result.replace(0, DirectoryOffset, i.data(), i.size()); break; } } } if (!AbsPath.empty()) Result.clear(); } else if (!AbsPath.empty()) Result.clear(); else { string strVolumeGuid; const os::fs::enum_drives Enumerator(os::fs::get_logical_drives()); const auto ItemIterator = std::find_if(ALL_CONST_RANGE(Enumerator), [&](const auto& i) { return os::fs::GetVolumeNameForVolumeMountPoint(os::fs::get_root_directory(i), strVolumeGuid) && starts_with(Path, string_view(strVolumeGuid).substr(0, DirectoryOffset)); }); if (ItemIterator != Enumerator.cend()) { Result.replace(0, DirectoryOffset, os::fs::get_drive(*ItemIterator)); } } } else if (!AbsPath.empty()) Result.clear(); return Result; }
int DialogBuilder::AddTextWrap(const wchar_t *text, bool center, int width) { string str(text); FarFormatText(str, width <= 0 ? ScrX-1-10 : width, str, L"\n", 0); int LineCount = 1 + std::count(ALL_CONST_RANGE(str), L'\n'); std::replace(ALL_RANGE(str), L'\n', L'\0'); const wchar_t *ps = str.data(); for (int i = 0; i < LineCount; ++i, ps += wcslen(ps) + 1) { const auto Text = AddText(ps); Text->Flags = (center ? DIF_CENTERTEXT : 0); } return LineCount; }
DizList::desc_map::iterator DizList::AddRecord(const string& DizText) { string::const_iterator NameBegin, NameEnd, DescBegin; if (DizText.front() == L'"') { NameBegin = DizText.cbegin() + 1; NameEnd = std::find(NameBegin, DizText.cend(), L'"'); DescBegin = NameEnd == DizText.cend()? NameEnd : NameEnd + 1; } else { NameBegin = DizText.cbegin(); NameEnd = std::find_if(ALL_CONST_RANGE(DizText), IsSpace); DescBegin = NameEnd; } return AddRecord(string(NameBegin, NameEnd), string(DescBegin, DizText.end())); }
bool filemasks::Set(const string& masks, DWORD Flags) { bool Result = false; if (!masks.empty()) { Free(); string expmasks(masks); std::list<string> UsedGroups; size_t LBPos, RBPos; while((LBPos = expmasks.find(L'<')) != string::npos && (RBPos = expmasks.find(L'>', LBPos)) != string::npos) { string MaskGroupNameWB = expmasks.substr(LBPos, RBPos-LBPos+1); string MaskGroupName = expmasks.substr(LBPos+1, RBPos-LBPos-1); string MaskGroupValue; if (std::find(ALL_CONST_RANGE(UsedGroups), MaskGroupName) == UsedGroups.cend()) { Global->Db->GeneralCfg()->GetValue(L"Masks", MaskGroupName, MaskGroupValue, L""); ReplaceStrings(expmasks, MaskGroupNameWB, MaskGroupValue); UsedGroups.emplace_back(MaskGroupName); } else { ReplaceStrings(expmasks, MaskGroupNameWB, L""); } } if (!expmasks.empty()) { const wchar_t* ptr = expmasks.data(); string SimpleMasksInclude, SimpleMasksExclude; auto DestContainer = &Include; auto DestString = &SimpleMasksInclude; Result = true; while(*ptr) { ptr = SkipSeparators(ptr); auto nextpos = SkipRE(ptr); if (nextpos != ptr) { filemasks::masks m; Result = m.Set(string(ptr, nextpos-ptr)); if (Result) { DestContainer->emplace_back(std::move(m)); ptr = nextpos; } else { break; } ptr = nextpos; } ptr = SkipSeparators(ptr); nextpos = SkipMasks(ptr); if (nextpos != ptr) { *DestString += string(ptr, nextpos-ptr); ptr = nextpos; } if (*ptr == ExcludeMaskSeparator) { if (DestContainer != &Exclude) { DestContainer = &Exclude; DestString = &SimpleMasksExclude; } else { break; } ++ptr; } } if (Result && !SimpleMasksInclude.empty()) { filemasks::masks m; Result = m.Set(SimpleMasksInclude); if (Result) Include.emplace_back(std::move(m)); } if (Result && !SimpleMasksExclude.empty()) { filemasks::masks m; Result = m.Set(SimpleMasksExclude); if (Result) Exclude.emplace_back(std::move(m)); } if (Result && Include.empty() && !Exclude.empty()) { Include.emplace_back(VALUE_TYPE(Include)()); Result = Include.back().Set(L"*"); } Result = !empty(); } if (!Result) { if (!(Flags & FMF_SILENT)) { ErrorMessage(); } Free(); } } return Result; }
bool filemasks::empty() const { return std::all_of(ALL_CONST_RANGE(Include), std::mem_fn(&masks::empty)) && std::all_of(ALL_CONST_RANGE(Exclude), std::mem_fn(&masks::empty)); }
bool contains_icase(const string_view Str, const string_view Token) { return std::search(ALL_CONST_RANGE(Str), ALL_CONST_RANGE(Token), equal_icase_t{}) != Str.cend(); }
bool GetFileFormat( api::fs::file& file, uintptr_t& nCodePage, bool* pSignatureFound, bool bUseHeuristics, bool* pPureAscii) { DWORD dwTemp = 0; bool bSignatureFound = false; bool bDetect = false; bool bPureAscii = false; size_t Readed = 0; if (file.Read(&dwTemp, sizeof(dwTemp), Readed) && Readed > 1 ) // minimum signature size is 2 bytes { if (LOWORD(dwTemp) == SIGN_UNICODE) { nCodePage = CP_UNICODE; file.SetPointer(2, nullptr, FILE_BEGIN); bSignatureFound = true; } else if (LOWORD(dwTemp) == SIGN_REVERSEBOM) { nCodePage = CP_REVERSEBOM; file.SetPointer(2, nullptr, FILE_BEGIN); bSignatureFound = true; } else if ((dwTemp & 0x00FFFFFF) == SIGN_UTF8) { nCodePage = CP_UTF8; file.SetPointer(3, nullptr, FILE_BEGIN); bSignatureFound = true; } else { file.SetPointer(0, nullptr, FILE_BEGIN); } } if (bSignatureFound) { bDetect = true; } else if (bUseHeuristics) { file.SetPointer(0, nullptr, FILE_BEGIN); size_t Size = 0x8000; // BUGBUG. TODO: configurable char_ptr Buffer(Size); size_t ReadSize = 0; bool ReadResult = file.Read(Buffer.get(), Size, ReadSize); file.SetPointer(0, nullptr, FILE_BEGIN); bPureAscii = ReadResult && !ReadSize; // empty file == pure ascii if (ReadResult && ReadSize) { // BUGBUG MSDN documents IS_TEXT_UNICODE_BUFFER_TOO_SMALL but there is no such thing if (ReadSize > 1) { int test = IS_TEXT_UNICODE_UNICODE_MASK | IS_TEXT_UNICODE_REVERSE_MASK | IS_TEXT_UNICODE_NOT_UNICODE_MASK | IS_TEXT_UNICODE_NOT_ASCII_MASK; IsTextUnicode(Buffer.get(), static_cast<int>(ReadSize), &test); // return value is ignored, it's ok. if (!(test & IS_TEXT_UNICODE_NOT_UNICODE_MASK) && (test & IS_TEXT_UNICODE_NOT_ASCII_MASK)) { if (test & IS_TEXT_UNICODE_UNICODE_MASK) { nCodePage = CP_UNICODE; bDetect = true; } else if (test & IS_TEXT_UNICODE_REVERSE_MASK) { nCodePage = CP_REVERSEBOM; bDetect = true; } } if (!bDetect && IsTextUTF8(Buffer.get(), ReadSize, bPureAscii)) { nCodePage = CP_UTF8; bDetect = true; } } if (!bDetect && !bPureAscii) { int cp = GetCpUsingUniversalDetector(Buffer.get(), ReadSize); if ( cp >= 0 ) { if (Global->Opt->strNoAutoDetectCP.Get() == L"-1") { if ( Global->Opt->CPMenuMode ) { if ( static_cast<UINT>(cp) != GetACP() && static_cast<UINT>(cp) != GetOEMCP() ) { long long selectType = Codepages().GetFavorite(cp); if (0 == (selectType & CPST_FAVORITE)) cp = -1; } } } else { std::vector<string> BannedCpList; split(BannedCpList, Global->Opt->strNoAutoDetectCP, STLF_UNIQUE); if (std::find(ALL_CONST_RANGE(BannedCpList), std::to_wstring(cp)) != BannedCpList.cend()) { cp = -1; } } } if (cp != -1) { nCodePage = cp; bDetect = true; } } } } if (pSignatureFound) *pSignatureFound = bSignatureFound; if (pPureAscii) *pPureAscii = bPureAscii; return bDetect; }
int Panel::SetPluginCommand(int Command,int Param1,void* Param2) { _ALGO(CleverSysLog clv(L"Panel::SetPluginCommand")); _ALGO(SysLog(L"(Command=%s, Param1=[%d/0x%08X], Param2=[%d/0x%08X])",_FCTL_ToName(Command),(int)Param1,Param1,(int)Param2,Param2)); int Result=FALSE; ProcessingPluginCommand++; switch (Command) { case FCTL_SETVIEWMODE: Result = Parent()->ChangePanelViewMode(shared_from_this(), Param1, Parent()->IsTopWindow()); break; case FCTL_SETSORTMODE: { int Mode=Param1; if ((Mode>SM_DEFAULT) && (Mode < SM_COUNT)) { SetSortMode(panel_sort(Mode - 1)); // Уменьшим на 1 из-за SM_DEFAULT Result=TRUE; } break; } case FCTL_SETSORTORDER: { ChangeSortOrder(Param1 != 0); Result=TRUE; break; } case FCTL_SETDIRECTORIESFIRST: { ChangeDirectoriesFirst(Param1 != 0); Result=TRUE; break; } case FCTL_CLOSEPANEL: if (m_PanelMode == panel_mode::PLUGIN_PANEL) { string folder=NullToEmpty((const wchar_t *)Param2); SetCurDir(folder,true); if (folder.empty()) Update(UPDATE_KEEP_SELECTION); Redraw(); } Result=TRUE; break; case FCTL_GETPANELINFO: { PanelInfo *Info=(PanelInfo *)Param2; if(!CheckStructSize(Info)) break; *Info = {}; Info->StructSize = sizeof(PanelInfo); UpdateIfRequired(); Info->OwnerGuid=FarGuid; Info->PluginHandle=nullptr; switch (GetType()) { case panel_type::FILE_PANEL: Info->PanelType=PTYPE_FILEPANEL; break; case panel_type::TREE_PANEL: Info->PanelType=PTYPE_TREEPANEL; break; case panel_type::QVIEW_PANEL: Info->PanelType=PTYPE_QVIEWPANEL; break; case panel_type::INFO_PANEL: Info->PanelType=PTYPE_INFOPANEL; break; } int X1,Y1,X2,Y2; GetPosition(X1,Y1,X2,Y2); Info->PanelRect.left=X1; Info->PanelRect.top=Y1; Info->PanelRect.right=X2; Info->PanelRect.bottom=Y2; Info->ViewMode=GetViewMode(); Info->SortMode = static_cast<OPENPANELINFO_SORTMODES>((GetSortMode() < panel_sort::COUNT? SM_UNSORTED - static_cast<int>(panel_sort::UNSORTED) : 0) + static_cast<int>(GetSortMode())); Info->Flags |= Global->Opt->ShowHidden? PFLAGS_SHOWHIDDEN : 0; Info->Flags |= Global->Opt->Highlight? PFLAGS_HIGHLIGHT : 0; Info->Flags |= GetSortOrder()? PFLAGS_REVERSESORTORDER : 0; Info->Flags |= GetSortGroups()? PFLAGS_USESORTGROUPS : 0; Info->Flags |= GetSelectedFirstMode()? PFLAGS_SELECTEDFIRST : 0; Info->Flags |= GetDirectoriesFirst()? PFLAGS_DIRECTORIESFIRST : 0; Info->Flags |= (GetMode() == panel_mode::PLUGIN_PANEL)? PFLAGS_PLUGIN : 0; Info->Flags |= IsVisible()? PFLAGS_VISIBLE : 0; Info->Flags |= IsFocused()? PFLAGS_FOCUS : 0; Info->Flags |= Parent()->IsLeft(this)? PFLAGS_PANELLEFT : 0; if (GetType() == panel_type::FILE_PANEL) { FileList *DestFilePanel=(FileList *)this; if (Info->Flags&PFLAGS_PLUGIN) { Info->OwnerGuid = DestFilePanel->GetPluginHandle()->plugin()->Id(); Info->PluginHandle = DestFilePanel->GetPluginHandle()->panel(); static int Reenter=0; if (!Reenter) { Reenter++; OpenPanelInfo PInfo; DestFilePanel->GetOpenPanelInfo(&PInfo); if (PInfo.Flags & OPIF_REALNAMES) Info->Flags |= PFLAGS_REALNAMES; if (PInfo.Flags & OPIF_DISABLEHIGHLIGHTING) Info->Flags &= ~PFLAGS_HIGHLIGHT; if (PInfo.Flags & OPIF_USECRC32) Info->Flags |= PFLAGS_USECRC32; if (PInfo.Flags & OPIF_SHORTCUT) Info->Flags |= PFLAGS_SHORTCUT; Reenter--; } } DestFilePanel->PluginGetPanelInfo(*Info); } if (!(Info->Flags&PFLAGS_PLUGIN)) // $ 12.12.2001 DJ - на неплагиновой панели - всегда реальные имена Info->Flags |= PFLAGS_REALNAMES; Result=TRUE; break; } case FCTL_GETPANELPREFIX: { string strTemp; if (GetType() == panel_type::FILE_PANEL && GetMode() == panel_mode::PLUGIN_PANEL) { PluginInfo PInfo = {sizeof(PInfo)}; FileList *DestPanel = ((FileList*)this); if (DestPanel->GetPluginInfo(&PInfo)) strTemp = NullToEmpty(PInfo.CommandPrefix); } if (Param1&&Param2) xwcsncpy((wchar_t*)Param2, strTemp.c_str(), Param1); Result=(int)strTemp.size()+1; break; } case FCTL_GETPANELHOSTFILE: case FCTL_GETPANELFORMAT: { string strTemp; if (GetType() == panel_type::FILE_PANEL) { FileList *DestFilePanel=(FileList *)this; static int Reenter=0; if (!Reenter && GetMode() == panel_mode::PLUGIN_PANEL) { Reenter++; OpenPanelInfo PInfo; DestFilePanel->GetOpenPanelInfo(&PInfo); switch (Command) { case FCTL_GETPANELHOSTFILE: strTemp=NullToEmpty(PInfo.HostFile); break; case FCTL_GETPANELFORMAT: strTemp=NullToEmpty(PInfo.Format); break; } Reenter--; } } if (Param1&&Param2) xwcsncpy((wchar_t*)Param2, strTemp.c_str(), Param1); Result=(int)strTemp.size()+1; break; } case FCTL_GETPANELDIRECTORY: { static int Reenter=0; if(!Reenter) { Reenter++; ShortcutInfo Info; GetShortcutInfo(Info); Result = static_cast<int>(aligned_sizeof<FarPanelDirectory>()); const auto folderOffset = Result; Result+=static_cast<int>(sizeof(wchar_t)*(Info.ShortcutFolder.size()+1)); const auto pluginFileOffset = Result; Result+=static_cast<int>(sizeof(wchar_t)*(Info.PluginFile.size()+1)); const auto pluginDataOffset = Result; Result+=static_cast<int>(sizeof(wchar_t)*(Info.PluginData.size()+1)); const auto dirInfo = static_cast<FarPanelDirectory*>(Param2); if(Param1>=Result && CheckStructSize(dirInfo)) { dirInfo->StructSize=sizeof(FarPanelDirectory); dirInfo->PluginId=Info.PluginGuid; dirInfo->Name = static_cast<wchar_t*>(static_cast<void*>(static_cast<char*>(Param2) + folderOffset)); dirInfo->Param = static_cast<wchar_t*>(static_cast<void*>(static_cast<char*>(Param2) + pluginDataOffset)); dirInfo->File = static_cast<wchar_t*>(static_cast<void*>(static_cast<char*>(Param2) + pluginFileOffset)); *std::copy(ALL_CONST_RANGE(Info.ShortcutFolder), const_cast<wchar_t*>(dirInfo->Name)) = L'\0'; *std::copy(ALL_CONST_RANGE(Info.PluginData), const_cast<wchar_t*>(dirInfo->Param)) = L'\0'; *std::copy(ALL_CONST_RANGE(Info.PluginFile), const_cast<wchar_t*>(dirInfo->File)) = L'\0'; } Reenter--; } break; } case FCTL_GETCOLUMNTYPES: case FCTL_GETCOLUMNWIDTHS: if (GetType() == panel_type::FILE_PANEL) { string strColumnTypes,strColumnWidths; ((FileList *)this)->PluginGetColumnTypesAndWidths(strColumnTypes,strColumnWidths); if (Command==FCTL_GETCOLUMNTYPES) { if (Param1&&Param2) xwcsncpy((wchar_t*)Param2,strColumnTypes.c_str(),Param1); Result=(int)strColumnTypes.size()+1; } else { if (Param1&&Param2) xwcsncpy((wchar_t*)Param2,strColumnWidths.c_str(),Param1); Result=(int)strColumnWidths.size()+1; } } break; case FCTL_GETPANELITEM: { if (GetType() == panel_type::FILE_PANEL && CheckNullOrStructSize(static_cast<FarGetPluginPanelItem*>(Param2))) Result = static_cast<int>(static_cast<FileList*>(this)->PluginGetPanelItem(Param1, static_cast<FarGetPluginPanelItem*>(Param2))); break; } case FCTL_GETSELECTEDPANELITEM: { if (GetType() == panel_type::FILE_PANEL && CheckNullOrStructSize(static_cast<FarGetPluginPanelItem*>(Param2))) Result = static_cast<int>(static_cast<FileList*>(this)->PluginGetSelectedPanelItem(Param1, static_cast<FarGetPluginPanelItem*>(Param2))); break; } case FCTL_GETCURRENTPANELITEM: { if (GetType() == panel_type::FILE_PANEL && CheckNullOrStructSize(static_cast<FarGetPluginPanelItem*>(Param2))) { PanelInfo Info; const auto DestPanel = static_cast<FileList*>(this); DestPanel->PluginGetPanelInfo(Info); Result = static_cast<int>(DestPanel->PluginGetPanelItem(static_cast<int>(Info.CurrentItem), static_cast<FarGetPluginPanelItem*>(Param2))); } break; } case FCTL_BEGINSELECTION: { if (GetType() == panel_type::FILE_PANEL) { ((FileList *)this)->PluginBeginSelection(); Result=TRUE; } break; } case FCTL_SETSELECTION: { if (GetType() == panel_type::FILE_PANEL) { ((FileList *)this)->PluginSetSelection(Param1, Param2 != nullptr); Result=TRUE; } break; } case FCTL_CLEARSELECTION: { if (GetType() == panel_type::FILE_PANEL) { static_cast<FileList*>(this)->PluginClearSelection(Param1); Result=TRUE; } break; } case FCTL_ENDSELECTION: { if (GetType() == panel_type::FILE_PANEL) { ((FileList *)this)->PluginEndSelection(); Result=TRUE; } break; } case FCTL_UPDATEPANEL: Update(Param1?UPDATE_KEEP_SELECTION:0); if (GetType() == panel_type::QVIEW_PANEL) UpdateViewPanel(); Result=TRUE; break; case FCTL_REDRAWPANEL: { PanelRedrawInfo *Info=(PanelRedrawInfo *)Param2; if (CheckStructSize(Info)) { m_CurFile=static_cast<int>(Info->CurrentItem); m_CurTopFile=static_cast<int>(Info->TopPanelItem); } // $ 12.05.2001 DJ перерисовываемся только в том случае, если мы - текущее окно if (Parent()->IsTopWindow()) Redraw(); Result=TRUE; break; } case FCTL_SETPANELDIRECTORY: { const auto dirInfo = static_cast<const FarPanelDirectory*>(Param2); if (CheckStructSize(dirInfo)) { Result = ExecShortcutFolder(NullToEmpty(dirInfo->Name), dirInfo->PluginId, NullToEmpty(dirInfo->File), NullToEmpty(dirInfo->Param), false, false, true); // restore current directory to active panel path if (!IsFocused()) { Parent()->ActivePanel()->SetCurPath(); } } break; } case FCTL_SETACTIVEPANEL: { if (IsVisible()) { Parent()->SetActivePanel(this); Result=TRUE; } break; } } ProcessingPluginCommand--; return Result; }
static bool FillREPARSE_DATA_BUFFER(REPARSE_DATA_BUFFER* rdb, const string& PrintName, const string& SubstituteName) { switch (rdb->ReparseTag) { // IO_REPARSE_TAG_MOUNT_POINT and IO_REPARSE_TAG_SYMLINK buffers are filled differently: // different order of print and substitute names and additional zero bytes in IO_REPARSE_TAG_MOUNT_POINT. // No particular reason to do that, but Windows for some reason does and we just mimic its approach to make // reparse points created by Far indistinguishable from created by, say, mklink. case IO_REPARSE_TAG_MOUNT_POINT: { const size_t SubstituteNameOffset = 0; const size_t SubstituteNameLength = SubstituteName.size() * sizeof(wchar_t); const size_t PrintNameOffset = SubstituteNameLength + 1 * sizeof(wchar_t); const size_t PrintNameLength = PrintName.size() * sizeof(wchar_t); const size_t ReparseDataLength = offsetof(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) - REPARSE_DATA_BUFFER_HEADER_SIZE + PrintNameOffset + PrintNameLength + 1 * sizeof(wchar_t); if (ReparseDataLength + REPARSE_DATA_BUFFER_HEADER_SIZE > MAXIMUM_REPARSE_DATA_BUFFER_SIZE) return false; rdb->ReparseDataLength = static_cast<USHORT>(ReparseDataLength); rdb->Reserved = 0; auto& Buffer = rdb->MountPointReparseBuffer; Buffer.SubstituteNameOffset = static_cast<USHORT>(SubstituteNameOffset); Buffer.SubstituteNameLength = static_cast<USHORT>(SubstituteNameLength); Buffer.PrintNameOffset = static_cast<USHORT>(PrintNameOffset); Buffer.PrintNameLength = static_cast<USHORT>(PrintNameLength); *std::copy(ALL_CONST_RANGE(SubstituteName), Buffer.PathBuffer + SubstituteNameOffset / sizeof(wchar_t)) = 0; *std::copy(ALL_CONST_RANGE(PrintName), Buffer.PathBuffer + PrintNameOffset / sizeof(wchar_t)) = 0; return true; } case IO_REPARSE_TAG_SYMLINK: { const size_t PrintNameOffset = 0; const size_t PrintNameLength = PrintName.size() * sizeof(wchar_t); const size_t SubstituteNameOffset = PrintNameLength; const size_t SubstituteNameLength = SubstituteName.size() * sizeof(wchar_t); const size_t ReparseDataLength = offsetof(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) - REPARSE_DATA_BUFFER_HEADER_SIZE + SubstituteNameOffset + SubstituteNameLength; if (ReparseDataLength + REPARSE_DATA_BUFFER_HEADER_SIZE > MAXIMUM_REPARSE_DATA_BUFFER_SIZE) return false; rdb->ReparseDataLength = static_cast<USHORT>(ReparseDataLength); rdb->Reserved = 0; auto& Buffer = rdb->SymbolicLinkReparseBuffer; Buffer.SubstituteNameOffset = static_cast<USHORT>(SubstituteNameOffset); Buffer.SubstituteNameLength = static_cast<USHORT>(SubstituteNameLength); Buffer.PrintNameOffset = static_cast<USHORT>(PrintNameOffset); Buffer.PrintNameLength = static_cast<USHORT>(PrintNameLength); std::copy(ALL_CONST_RANGE(SubstituteName), Buffer.PathBuffer + SubstituteNameOffset / sizeof(wchar_t)); std::copy(ALL_CONST_RANGE(PrintName), Buffer.PathBuffer + PrintNameOffset / sizeof(wchar_t)); return true; } default: return false; } }
/* $ 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); });
bool equal_icase(const string_view Str1, const string_view Str2) { return std::equal(ALL_CONST_RANGE(Str1), ALL_CONST_RANGE(Str2), equal_icase_t{}); }
void EnumFiles(VMenu2& Menu, const string& Str) { if(!Str.empty()) { string strStr(Str); size_t Pos = 0; if(std::count(ALL_CONST_RANGE(strStr), L'"') & 1) // odd quotes count { Pos = strStr.rfind(L'"'); } else { for(Pos=strStr.size()-1; Pos!=static_cast<size_t>(-1); Pos--) { if(strStr[Pos]==L'"') { Pos--; while(strStr[Pos]!=L'"' && Pos!=static_cast<size_t>(-1)) { Pos--; } } else if(strStr[Pos]==L' ') { Pos++; break; } } } if(Pos==static_cast<size_t>(-1)) { Pos=0; } bool StartQuote=false; if(Pos < strStr.size() && strStr[Pos]==L'"') { Pos++; StartQuote=true; } string strStart(strStr.data(),Pos); Unquote(strStr.erase(0, Pos)); if(!strStr.empty()) { string strExp = os::env::expand_strings(strStr); os::fs::enum_file Find(strExp+L"*"); bool Separator=false; std::for_each(CONST_RANGE(Find, i) { const wchar_t* FileName=PointToName(strStr); bool NameMatch=!StrCmpNI(FileName, i.strFileName.data(), StrLength(FileName)), AltNameMatch = NameMatch? false : !StrCmpNI(FileName, i.strAlternateFileName.data(), StrLength(FileName)); if(NameMatch || AltNameMatch) { strStr.resize(FileName-strStr.data()); string strAdd (strStr + (NameMatch ? i.strFileName : i.strAlternateFileName)); if (!StartQuote) QuoteSpace(strAdd); string strTmp(strStart+strAdd); if(StartQuote) strTmp += L'"'; if(!Separator) { if(Menu.GetItemCount()) { MenuItemEx Item; Item.strName = MSG(MCompletionFilesTitle); Item.Flags=LIF_SEPARATOR; Menu.AddItem(Item); } else { Menu.SetTitle(MSG(MCompletionFilesTitle)); } Separator=true; } Menu.AddItem(strTmp); } });
/* "Сбросить" виртуальный буфер на консоль */ 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()); }
int OperationFailed(const string& Object, LNGID Title, const string& Description, bool AllowSkip) { std::vector<string> Msg; IFileIsInUse *pfiu = nullptr; LNGID Reason = MObjectLockedReasonOpened; bool SwitchBtn = false, CloseBtn = false; DWORD Error = Global->CaughtError(); if(Error == ERROR_ACCESS_DENIED || Error == ERROR_SHARING_VIOLATION || Error == ERROR_LOCK_VIOLATION || Error == ERROR_DRIVE_LOCKED) { string FullName; ConvertNameToFull(Object, FullName); pfiu = CreateIFileIsInUse(FullName); if (pfiu) { FILE_USAGE_TYPE UsageType = FUT_GENERIC; pfiu->GetUsage(&UsageType); switch(UsageType) { case FUT_PLAYING: Reason = MObjectLockedReasonPlayed; break; case FUT_EDITING: Reason = MObjectLockedReasonEdited; break; case FUT_GENERIC: Reason = MObjectLockedReasonOpened; break; } DWORD Capabilities = 0; pfiu->GetCapabilities(&Capabilities); if(Capabilities&OF_CAP_CANSWITCHTO) { SwitchBtn = true; } if(Capabilities&OF_CAP_CANCLOSE) { CloseBtn = true; } LPWSTR AppName = nullptr; if(SUCCEEDED(pfiu->GetAppName(&AppName))) { Msg.emplace_back(AppName); } } else { DWORD dwSession; WCHAR szSessionKey[CCH_RM_SESSION_KEY+1] = {}; if (Imports().RmStartSession(&dwSession, 0, szSessionKey) == ERROR_SUCCESS) { PCWSTR pszFile = FullName.data(); if (Imports().RmRegisterResources(dwSession, 1, &pszFile, 0, nullptr, 0, nullptr) == ERROR_SUCCESS) { DWORD dwReason; DWORD RmGetListResult; UINT nProcInfoNeeded; UINT nProcInfo = 1; std::vector<RM_PROCESS_INFO> rgpi(nProcInfo); while((RmGetListResult=Imports().RmGetList(dwSession, &nProcInfoNeeded, &nProcInfo, rgpi.data(), &dwReason)) == ERROR_MORE_DATA) { nProcInfo = nProcInfoNeeded; rgpi.resize(nProcInfo); } if(RmGetListResult ==ERROR_SUCCESS) { for (size_t i = 0; i < nProcInfo; i++) { string tmp = rgpi[i].strAppName; if (*rgpi[i].strServiceShortName) { tmp.append(L" [").append(rgpi[i].strServiceShortName).append(L"]"); } tmp += L" (PID: " + std::to_wstring(rgpi[i].Process.dwProcessId); HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, rgpi[i].Process.dwProcessId); if (hProcess) { FILETIME ftCreate, ftExit, ftKernel, ftUser; if (GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser) && rgpi[i].Process.ProcessStartTime == ftCreate) { string Name; if (os::GetModuleFileNameEx(hProcess, nullptr, Name)) { tmp += L", " + Name; } } CloseHandle(hProcess); } tmp += L")"; Msg.emplace_back(tmp); } } } Imports().RmEndSession(dwSession); } } } auto Msgs = make_vector(Description, QuoteLeadingSpace(string(Object))); if(!Msg.empty()) { Msgs.emplace_back(LangString(MObjectLockedReason) << MSG(Reason)); Msgs.insert(Msgs.end(), ALL_CONST_RANGE(Msg)); } std::vector<string> Buttons; Buttons.reserve(4); if(SwitchBtn) { Buttons.emplace_back(MSG(MObjectLockedSwitchTo)); } Buttons.emplace_back(MSG(CloseBtn? MObjectLockedClose : MDeleteRetry)); if(AllowSkip) { Buttons.emplace_back(MSG(MDeleteSkip)); Buttons.emplace_back(MSG(MDeleteFileSkipAll)); } Buttons.emplace_back(MSG(MDeleteCancel)); int Result = -1; for(;;) { Result = Message(MSG_WARNING|MSG_ERRORTYPE, MSG(Title), Msgs, Buttons); if(SwitchBtn) { if(Result == 0) { HWND Wnd = nullptr; if (pfiu && SUCCEEDED(pfiu->GetSwitchToHWND(&Wnd))) { SetForegroundWindow(Wnd); if (IsIconic(Wnd)) ShowWindow(Wnd, SW_RESTORE); } continue; } else if(Result > 0) { --Result; } } if(CloseBtn && Result == 0) { // close & retry if (pfiu) { pfiu->CloseFile(); } } break; } if (pfiu) { pfiu->Release(); } return Result; }
bool GetFileFormat(api::File& file, uintptr_t& nCodePage, bool* pSignatureFound, bool bUseHeuristics) { DWORD dwTemp=0; bool bSignatureFound = false; bool bDetect=false; DWORD Readed = 0; if (file.Read(&dwTemp, sizeof(dwTemp), Readed) && Readed > 1 ) // minimum signature size is 2 bytes { if (LOWORD(dwTemp) == SIGN_UNICODE) { nCodePage = CP_UNICODE; file.SetPointer(2, nullptr, FILE_BEGIN); bSignatureFound = true; } else if (LOWORD(dwTemp) == SIGN_REVERSEBOM) { nCodePage = CP_REVERSEBOM; file.SetPointer(2, nullptr, FILE_BEGIN); bSignatureFound = true; } else if ((dwTemp & 0x00FFFFFF) == SIGN_UTF8) { nCodePage = CP_UTF8; file.SetPointer(3, nullptr, FILE_BEGIN); bSignatureFound = true; } else { file.SetPointer(0, nullptr, FILE_BEGIN); } } if (bSignatureFound) { bDetect = true; } else if (bUseHeuristics) { file.SetPointer(0, nullptr, FILE_BEGIN); DWORD Size=0x8000; // BUGBUG. TODO: configurable char_ptr Buffer(Size); DWORD ReadSize = 0; bool ReadResult = file.Read(Buffer.get(), Size, ReadSize); file.SetPointer(0, nullptr, FILE_BEGIN); if (ReadResult && ReadSize) { int test= IS_TEXT_UNICODE_STATISTICS| IS_TEXT_UNICODE_REVERSE_STATISTICS| IS_TEXT_UNICODE_CONTROLS| IS_TEXT_UNICODE_REVERSE_CONTROLS| IS_TEXT_UNICODE_ILLEGAL_CHARS| IS_TEXT_UNICODE_ODD_LENGTH| IS_TEXT_UNICODE_NULL_BYTES; if (IsTextUnicode(Buffer.get(), ReadSize, &test)) { if (!(test&IS_TEXT_UNICODE_ODD_LENGTH) && !(test&IS_TEXT_UNICODE_ILLEGAL_CHARS)) { if ((test&IS_TEXT_UNICODE_NULL_BYTES) || (test&IS_TEXT_UNICODE_CONTROLS) || (test&IS_TEXT_UNICODE_REVERSE_CONTROLS)) { if ((test&IS_TEXT_UNICODE_CONTROLS) || (test&IS_TEXT_UNICODE_STATISTICS)) { nCodePage=CP_UNICODE; bDetect=true; } else if ((test&IS_TEXT_UNICODE_REVERSE_CONTROLS) || (test&IS_TEXT_UNICODE_REVERSE_STATISTICS)) { nCodePage=CP_REVERSEBOM; bDetect=true; } } } } else if (IsTextUTF8(Buffer.get(), ReadSize)) { nCodePage=CP_UTF8; bDetect=true; } else { int cp = GetCpUsingUniversalDetector(Buffer.get(), ReadSize); if ( cp >= 0 ) { if (Global->Opt->strNoAutoDetectCP.Get() == L"-1") { if ( Global->Opt->CPMenuMode ) { if ( static_cast<UINT>(cp) != GetACP() && static_cast<UINT>(cp) != GetOEMCP() ) { long long selectType = Global->CodePages->GetFavorite(cp); if (0 == (selectType & CPST_FAVORITE)) cp = -1; } } } else { const auto BannedCpList = StringToList(Global->Opt->strNoAutoDetectCP, STLF_UNIQUE); if (std::find(ALL_CONST_RANGE(BannedCpList), std::to_wstring(cp)) != BannedCpList.cend()) { cp = -1; } } } if (cp != -1) { nCodePage = cp; bDetect = true; } } } } if (pSignatureFound) { *pSignatureFound = bSignatureFound; } return bDetect; }