svx/source/dialog/langbox.cxx |   44 +++++++++++++++++++++++++++++++++---------
 1 file changed, 35 insertions(+), 9 deletions(-)

New commits:
commit 9b03f778adfb87a10d781860930ed4d09410af9c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Jun 6 14:12:38 2023 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Tue Jun 6 17:52:32 2023 +0200

    Language list: sort generic language before country variants
    
    In Edit Modules dialog, the language list may include entries added
    by LanguageTool, and among them are generic language-only entries
    like "Spanish {es}", stanfing for simple language tags like "es".
    These languages should go before country variants like "Spanish
    (Argentina)", but since "{" is sorted after "(", the order is the
    opposite.
    
    This change fixes this. Since other lists do not include generic
    language-only languages (filtered out by lcl_isPrerequisite and its
    requireSublang argument), this does not apply to them, but the code
    will execute nevertheless; hope that this UI-only performance hit
    will not be noticeable.
    
    Change-Id: I97adc1ae8feb4c8a94b567b33363d63d899cabaa
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152676
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/svx/source/dialog/langbox.cxx b/svx/source/dialog/langbox.cxx
index fae7cf66e8d8..e552f68cc749 100644
--- a/svx/source/dialog/langbox.cxx
+++ b/svx/source/dialog/langbox.cxx
@@ -190,16 +190,42 @@ void SvxLanguageBox::AddLanguages(const std::vector< 
LanguageType >& rLanguageTy
 
 static void SortLanguages(std::vector<weld::ComboBoxEntry>& rEntries)
 {
-    std::sort(rEntries.begin(), rEntries.end(),
-              [](const weld::ComboBoxEntry e1, const weld::ComboBoxEntry e2)
-              {
-                  static const auto aSorter = 
comphelper::string::NaturalStringSorter(
-                      ::comphelper::getProcessComponentContext(),
-                      
Application::GetSettings().GetUILanguageTag().getLocale());
-                  return aSorter.compare(e1.sString, e2.sString) < 0;
-              });
+    auto langLess = [](const weld::ComboBoxEntry& e1, const 
weld::ComboBoxEntry& e2)
+    {
+        if (e1.sId == e2.sId)
+            return false; // shortcut
+        // 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.
+        LanguageTag lt1(LanguageType(e1.sId.toInt32())), 
lt2(LanguageType(e2.sId.toInt32()));
+        if (lt1.getLanguage() == lt2.getLanguage())
+        {
+            const bool isLangOnly1 = lt1.isIsoLocale() && 
lt1.getCountry().isEmpty();
+            const bool isLangOnly2 = lt2.isIsoLocale() && 
lt2.getCountry().isEmpty();
+
+            if (isLangOnly1)
+            {
+                // lt1 is a generic language-only tag
+                if (!isLangOnly2)
+                    return true; // lt2 is not
+            }
+            else if (isLangOnly2)
+            {
+                // lt2 is a generic language-only tag, lt1 is not
+                return false;
+            }
+        }
+        // Do a normal string comparison for other cases
+        static const auto aSorter = comphelper::string::NaturalStringSorter(
+            comphelper::getProcessComponentContext(),
+            Application::GetSettings().GetUILanguageTag().getLocale());
+        return aSorter.compare(e1.sString, e2.sString) < 0;
+    };
+
+    std::sort(rEntries.begin(), rEntries.end(), langLess);
     rEntries.erase(std::unique(rEntries.begin(), rEntries.end(),
-                               [](const weld::ComboBoxEntry e1, const 
weld::ComboBoxEntry e2)
+                               [](const weld::ComboBoxEntry& e1, const 
weld::ComboBoxEntry& e2)
                                { return e1.sId == e2.sId; }),
                    rEntries.end());
 }

Reply via email to