Resolves: tdf#150370 Accept 'art-x-...' private-use input in language box

... for artificial constructed languages.

Change-Id: Ifd0f2ca63738eb9bbe78361cd3fdf507f3e397f5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/139135
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
diff --git a/i18nlangtag/source/languagetag/languagetag.cxx b/i18nlangtag/source/languagetag/languagetag.cxx
index 0b1ab1a..239215a 100644
--- a/i18nlangtag/source/languagetag/languagetag.cxx
+++ b/i18nlangtag/source/languagetag/languagetag.cxx
@@ -2868,28 +2868,35 @@ bool LanguageTag::isValidBcp47( const OUString& rString, OUString* o_pCanonicali
            bValid = true;
            if (ePrivateUse != PrivateUse::ALLOW)
            {
                const lt_string_t* pPrivate = lt_tag_get_privateuse( aVar.mpLangtag);
                if (pPrivate && lt_string_length( pPrivate) > 0)
                    bValid = false;
                else
                do
                {
                    const char* pLang = nullptr;
                    const lt_lang_t* pLangT = lt_tag_get_language( aVar.mpLangtag);
                    if (pLangT)
                    {
                        const char* pLang = lt_lang_get_tag( pLangT);
                        pLang = lt_lang_get_tag( pLangT);
                        if (pLang && strcmp( pLang, I18NLANGTAG_QLT_ASCII) == 0)
                        {
                            // Disallow 'qlt' privateuse code to prevent
                            // Disallow 'qlt' localuse code to prevent
                            // confusion with our internal usage.
                            bValid = false;
                            break;
                        }
                    }
                    if (ePrivateUse == PrivateUse::ALLOW_ART_X && pLang && strcmp( pLang, "art") == 0)
                    {
                        // Allow anything 'art' which includes 'art-x-...' and 'art-Latn-x-...'.
                        break;
                    }
                    const lt_string_t* pPrivate = lt_tag_get_privateuse( aVar.mpLangtag);
                    if (pPrivate && lt_string_length( pPrivate) > 0)
                        bValid = false;
                }
                while (false);
            }
            if (o_pCanonicalized)
                *o_pCanonicalized = OUString::createFromAscii( pTag);
            free( pTag);
            return bValid;
        }
    }
    else
diff --git a/include/i18nlangtag/languagetag.hxx b/include/i18nlangtag/languagetag.hxx
index 5b9a43c..79ffc28 100644
--- a/include/i18nlangtag/languagetag.hxx
+++ b/include/i18nlangtag/languagetag.hxx
@@ -518,8 +518,10 @@ public:
    /** Enums to be used with isValidBcp47(). */
    enum PrivateUse
    {
        ALLOW = 0,
        DISALLOW
        ALLOW = 0,      ///< Allow all private-use and local-use including (!) 'qlt' local-use.
        DISALLOW,       ///< Disallow all private-use and 'qlt' local-use, other 'qaa' to 'qtz' local-use are allowed.
        ALLOW_ART_X     ///< Disallow all private-use and 'qlt' local-use, but allow 'art-x-...' private-use
                        ///  for artificial constructed languages (and 'art-Latn-x-...' and other scripts).
    };

    /** If rString represents a valid BCP 47 language tag.
diff --git a/svx/source/dialog/langbox.cxx b/svx/source/dialog/langbox.cxx
index ead5f11..5db46c6 100644
--- a/svx/source/dialog/langbox.cxx
+++ b/svx/source/dialog/langbox.cxx
@@ -430,7 +430,7 @@ IMPL_LINK(SvxLanguageBox, ChangeHdl, weld::ComboBox&, rControl, void)
            else
            {
                OUString aCanonicalized;
                bool bValid = LanguageTag::isValidBcp47( aStr, &aCanonicalized, LanguageTag::PrivateUse::DISALLOW);
                bool bValid = LanguageTag::isValidBcp47( aStr, &aCanonicalized, LanguageTag::PrivateUse::ALLOW_ART_X);
                m_eEditedAndValid = (bValid ? EditedAndValid::Valid : EditedAndValid::Invalid);
                if (bValid && aCanonicalized != aStr)
                {