std::tuple<os::fs::file, string, uintptr_t> OpenLangFile(string_view const Path, string_view const Mask, string_view const Language) { FN_RETURN_TYPE(OpenLangFile) CurrentFileData, EnglishFileData; for (const auto& FindData: os::fs::enum_files(path::join(Path, Mask))) { const auto CurrentFileName = path::join(Path, FindData.FileName); auto& CurrentFile = std::get<0>(CurrentFileData); auto& CurrentLngName = std::get<1>(CurrentFileData); auto& CurrentCodepage = std::get<2>(CurrentFileData); CurrentFile = os::fs::file(CurrentFileName, FILE_READ_DATA, FILE_SHARE_READ, nullptr, OPEN_EXISTING); if (CurrentFile) { CurrentCodepage = GetFileCodepage(CurrentFile, encoding::codepage::oem(), nullptr, false); if (GetLangParam(CurrentFile, L"Language"sv, CurrentLngName, nullptr, CurrentCodepage) && equal_icase(CurrentLngName, Language)) { return CurrentFileData; } if (equal_icase(CurrentLngName, L"English"sv)) { EnglishFileData = std::move(CurrentFileData); } } } if (std::get<0>(EnglishFileData)) return EnglishFileData; return CurrentFileData; }
static void LoadCustomStrings(const string& FileName, std::unordered_map<string, string>& Strings) { 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); string SavedLabel; for (const auto& i : enum_file_lines(CustomFile, CustomFileCodepage)) { string_view Label, Text; switch (parse_lng_line(trim(i.Str), true, Label, Text)) { case lng_line_type::label: SavedLabel = Label; break; case lng_line_type::text: Strings.emplace(std::move(SavedLabel), ConvertString(Text)); SavedLabel.clear(); break; case lng_line_type::both: Strings.emplace(Label, ConvertString(Text)); break; default: break; } } }
uintptr_t GetFileCodepage(const os::fs::file& File, uintptr_t DefaultCodepage, bool* SignatureFound, bool UseHeuristics) { bool SignatureFoundValue = false; uintptr_t Codepage; bool NotUTF8 = false; bool NotUTF16 = false; if (!GetFileCodepage(File, DefaultCodepage, Codepage, SignatureFoundValue, NotUTF8, NotUTF16, UseHeuristics)) { Codepage = (NotUTF8 && DefaultCodepage == CP_UTF8) || (NotUTF16 && IsUnicodeCodePage(DefaultCodepage))? encoding::codepage::ansi() : DefaultCodepage; } if (SignatureFound) *SignatureFound = SignatureFoundValue; return Codepage; }
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); }
static bool SelectLanguage(bool HelpLanguage, string& Dest) { lng Title; string_view Mask; if (HelpLanguage) { Title = lng::MHelpLangTitle; Mask=Global->HelpFileMask; } else { Title = lng::MLangTitle; Mask=LangFileMask; } const auto LangMenu = VMenu2::create(msg(Title), {}, ScrY - 4); LangMenu->SetMenuFlags(VMENU_WRAPMODE); LangMenu->SetPosition(ScrX/2-8+5*HelpLanguage,ScrY/2-4+2*HelpLanguage,0,0); for (const auto& FindData: os::fs::enum_files(path::join(Global->g_strFarPath, Mask))) { const os::fs::file LangFile(path::join(Global->g_strFarPath, FindData.FileName), FILE_READ_DATA, FILE_SHARE_READ, nullptr, OPEN_EXISTING); if (!LangFile) continue; const auto Codepage = GetFileCodepage(LangFile, encoding::codepage::oem(), nullptr, false); string strLangName, strLangDescr; if (GetLangParam(LangFile, L"Language"sv, strLangName, &strLangDescr, Codepage)) { string strEntryName; if (!HelpLanguage || ( !GetLangParam(LangFile, L"PluginContents"sv, strEntryName, nullptr, Codepage) && !GetLangParam(LangFile, L"DocumentContents"sv, strEntryName, nullptr, Codepage))) { MenuItemEx LangMenuItem(!strLangDescr.empty()? strLangDescr : strLangName); /* $ 01.08.2001 SVS Не допускаем дубликатов! Если в каталог с ФАРом положить еще один HLF с одноименным языком, то... фигня получается при выборе языка. */ if (LangMenu->FindItem(0,LangMenuItem.Name,LIFIND_EXACTMATCH) == -1) { LangMenuItem.SetSelect(equal_icase(Dest, strLangName)); LangMenuItem.ComplexUserData = strLangName; LangMenu->AddItem(LangMenuItem); } } } } LangMenu->AssignHighlights(FALSE); LangMenu->Run(); if (LangMenu->GetExitCode()<0) return false; Dest = *LangMenu->GetComplexUserDataPtr<string>(); return true; }