/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
void SvxLanguageBox::set_active_id(const LanguageType eLangType)
{ // If the core uses a LangID of an imported MS document and wants to select // a language that is replaced, we need to select the replacement instead.
LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage( eLangType);
// Make sure that e.g. generic 'Spanish {es}' goes before 'Spanish (Argentina)'. // We can't depend on MsLangId::getPrimaryLanguage/getSubLanguage, because e.g. // for generic Bosnian {bs}, the MS-LCID is 0x781A, and getSubLanguage is not 0. // So we have to do the expensive LanguageTag construction in EntryData.
if (isLangOnly1)
{ // e1.tag is a generic language-only tag, e2.tag is not returntrue;
} elseif (isLangOnly2)
{ // e2.tag is a generic language-only tag, e1.tag is not returnfalse;
}
// Do a normal string comparison for other cases return NaturalStringSorterCompare()(e1.entry.sString, e2.entry.sString);
}
}; using SortedLangEntries = o3tl::sorted_vector<EntryData, GenericFirst>;
// It is impossible to sort using only GenericFirst comparison: it would fail the strict weak // ordering requirement, where the following simplified example would fail the last assertion: // // weld::ComboBoxEntry nn{ u"노르웨이어(니노르스크) {nn}"_ustr, "30740", "" } // weld::ComboBoxEntry nn_NO{ u"노르웨이어 뉘노르스크>"_ustr, "2068", "" }; // weld::ComboBoxEntry nb_NO{ u"노르웨이어 부크몰"_ustr, "1044", "" }; // // assert(GenericFirst(nn, nn_NO)); // assert(GenericFirst(nn_NO, nb_NO)); // assert(GenericFirst(nn, nb_NO)); // // So only sort this way inside language groups, where the data set itself guarantees the // comparison's strict weak ordering.
for (constauto& entry : rEntries)
{
LanguageType languageType(entry.sId.toInt32()); // Remove LANGUAGE_USER_SYSTEM_CONFIG special entry and friends from the list if (languageType >= LanguageType(0xFFE0)) continue;
LanguageTag tag(languageType);
langToEntriesMap[tag.getLanguage()].insert({ tag, entry }); // also makes unique
}
// 2. Sort using generic language's translated name, plus ISO language tag appended just in case
std::map<OUString, const SortedLangEntries&, NaturalStringSorterCompare> finalSort; const LanguageTag& uiLang = Application::GetSettings().GetUILanguageTag(); for (constauto& [lang, lang_entries] : langToEntriesMap)
{
OUString translatedLangName = LanguageTagIcu::getDisplayName(LanguageTag(lang), uiLang);
finalSort.emplace(translatedLangName + "_" + lang, lang_entries);
}
rEntries.clear(); for ([[maybe_unused]] constauto& [lang, lang_entries] : finalSort) for (auto& entryData : lang_entries)
rEntries.push_back(entryData.entry);
}
std::vector<weld::ComboBoxEntry> aEntries; for ( sal_uInt32 i = 0; i < nCount; i++ )
{
LanguageType nLangType; if ( nLangList & SvxLanguageListFlags::ONLY_KNOWN )
nLangType = aKnown[i]; else
nLangType = SvtLanguageTable::GetLanguageTypeAtIndex( i ); if ( lcl_isPrerequisite( nLangType, true ) &&
(lcl_isScriptTypeRequested( nLangType, nLangList) ||
(bool(nLangList & SvxLanguageListFlags::FBD_CHARS) &&
MsLangId::hasForbiddenCharacters(nLangType)) ||
(bool(nLangList & SvxLanguageListFlags::SPELL_USED) &&
lcl_SeqHasLang(aSpellUsedLang, static_cast<sal_uInt16>(nLangType)))
) )
{
aEntries.push_back(BuildEntry(nLangType)); if (aEntries.back().sString.isEmpty())
aEntries.pop_back();
}
}
if (bAddAvailable)
{ // Spell checkers, hyphenators and thesauri may add language tags // unknown so far.
AddLanguages(aAvailLang, nLangList, aEntries, true);
}
weld::ComboBoxEntry SvxLanguageBox::BuildEntry(const LanguageType nLangType, sal_Int16 nType)
{
LanguageType nLang = MsLangId::getReplacementForObsoleteLanguage(nLangType); // For obsolete and to be replaced languages check whether an entry of the // replacement already exists and if so don't add an entry with identical // string as would be returned by SvtLanguageTable::GetString(). if (nLang != nLangType)
{ int nAt = find_id( nLang ); if (nAt != -1) return weld::ComboBoxEntry(u""_ustr);
}
if (m_bWithCheckmark)
{ if (!m_xSpellUsedLang)
{
Reference<XSpellChecker1> xSpell = LinguMgr::GetSpellChecker(); if (xSpell.is())
m_xSpellUsedLang.reset(new Sequence<sal_Int16>(xSpell->getLanguages()));
}
IMPL_LINK(SvxLanguageBox, ChangeHdl, weld::ComboBox&, rControl, void)
{ if (rControl.has_entry())
{
EditedAndValid eOldState = m_eEditedAndValid;
OUString aStr(rControl.get_active_text()); if (aStr.isEmpty())
m_eEditedAndValid = EditedAndValid::Invalid; else
{ constint nPos = rControl.find_text(aStr); if (nPos != -1)
{ int nStartSelectPos, nEndSelectPos;
rControl.get_entry_selection_bounds(nStartSelectPos, nEndSelectPos);
// Select the corresponding listbox entry if not current. This // invalidates the Edit Selection thus has to happen between // obtaining the Selection and setting the new Selection. int nSelPos = m_xControl->get_active(); bool bSetEditSelection; if (nSelPos == nPos)
bSetEditSelection = false; else
{
m_xControl->set_active(nPos);
bSetEditSelection = true;
}
// If typing into the Edit control led us here, advance start of a // full selection by one so the next character will already // continue the string instead of having to type the same character // again to start a new string. The selection is in reverse // when obtained from the Edit control. if (nEndSelectPos == 0)
{
OUString aText(m_xControl->get_active_text()); if (nStartSelectPos == aText.getLength())
{
++nEndSelectPos;
bSetEditSelection = true;
}
}
if (bSetEditSelection)
rControl.select_entry_region(nStartSelectPos, nEndSelectPos);
for (size_t i = 0; i < 3; ++i)
{
SvxLanguageBox* pBox = ppBoxes[i]; if (!pBox) continue;
constint nPos = pBox->find_id( nLang); if (nPos != -1)
{ // Already present but with a different string or in another list.
pBox->m_xControl->set_active(nPos); return pBox;
}
}
if (SvtLanguageTable::HasLanguageType( nLang))
{ // In SvtLanguageTable but not in SvxLanguageBox. On purpose? This // may be an entry with different settings.
SAL_WARN( "svx.dialog", "SvxLanguageBox::SaveEditedAsEntry: already in SvtLanguageTable: " <<
SvtLanguageTable::GetLanguageString( nLang) << ", " << nLang);
} else
{ // Add to SvtLanguageTable first. This at an on-the-fly LanguageTag // also sets the ScriptType needed below.
SvtLanguageTable::AddLanguageTag( aLanguageTag );
}
// Add to the proper list.
SvxLanguageBox* pBox = nullptr; switch (MsLangId::getScriptType(nLang))
{ default: case css::i18n::ScriptType::LATIN:
pBox = ppBoxes[0]; break; case css::i18n::ScriptType::ASIAN:
pBox = ppBoxes[1]; break; case css::i18n::ScriptType::COMPLEX:
pBox = ppBoxes[2]; break;
} if (!pBox)
pBox = this;
pBox->InsertLanguage(nLang);
// Select it. constint nPos = pBox->find_id(nLang); if (nPos != -1)
pBox->m_xControl->set_active(nPos);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.