/* -*- 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 .
*/
#pragma once
#include <com/sun/star/uno/Reference.hxx>
#include <i18nlangtag/lang.h>
#include <i18nutil/transliteration.hxx>
#include <unotools/syslocale.hxx>
#include <unotools/localedatawrapper.hxx>
#include <unotools/calendarwrapper.hxx>
#include <unotools/transliterationwrapper.hxx>
#include <unotools/nativenumberwrapper.hxx>
#include <unotools/charclass.hxx>
#include <optional>
/*
On demand instantiation and initialization of several i18n wrappers ,
helping the number formatter to not perform worse than it already does .
*/
/** @short
Switch between LANGUAGE_SYSTEM and LANGUAGE_ENGLISH_US and any other
LocaleDataWrapper .
SvNumberformatter uses it upon switching locales .
@ descr
Avoids reloading and analysing of locale data again and again .
@ ATTENTION
If the default ctor is used the init ( ) method MUST be called before
accessing any locale data . The passed parameters Locale and LanguageType
must match each other .
*/
class OnDemandLocaleDataWrapper
{
SvtSysLocale aSysLocale;
LanguageType eCurrentLanguage;
LanguageType eLastAnyLanguage;
const LocaleDataWrapper* mpEnglish{ nullptr };
const LocaleDataWrapper* mpAny{ nullptr };
int nCurrent; // 0 == system, 1 == english, 2 == any
bool bInitialized;
public :
OnDemandLocaleDataWrapper()
: eLastAnyLanguage(LANGUAGE_DONTKNOW)
, nCurrent(0 )
, bInitialized(false )
{
eCurrentLanguage = LANGUAGE_SYSTEM;
}
bool isInitialized() const { return bInitialized; }
void init(const LanguageTag& rLanguageTag)
{
changeLocale(rLanguageTag);
bInitialized = true ;
}
void changeLocale(const LanguageTag& rLanguageTag)
{
LanguageType eLang = rLanguageTag.getLanguageType(false );
if (eLang == LANGUAGE_SYSTEM)
nCurrent = 0 ;
else if (eLang == LANGUAGE_ENGLISH_US)
{
if (!mpEnglish)
mpEnglish = LocaleDataWrapper::get(rLanguageTag);
nCurrent = 1 ;
}
else
{
if (!mpAny)
{
mpAny = LocaleDataWrapper::get(rLanguageTag);
eLastAnyLanguage = eLang;
}
else if (eLastAnyLanguage != eLang)
{
mpAny = LocaleDataWrapper::get(rLanguageTag);
eLastAnyLanguage = eLang;
}
nCurrent = 2 ;
}
eCurrentLanguage = eLang;
}
LanguageType getCurrentLanguage() const { return eCurrentLanguage; }
const LocaleDataWrapper* get() const
{
switch (nCurrent)
{
case 0 :
return &aSysLocale.GetLocaleData();
case 1 :
return mpEnglish;
case 2 :
return mpAny;
default :
assert(false );
return nullptr;
}
}
const LocaleDataWrapper* operator ->() const { return get(); }
const LocaleDataWrapper& operator *() const { return *get(); }
};
/** Load a calendar only if it's needed. Keep calendar for "en-US" locale
separately , as there can be alternation between locale dependent and
locale independent formats .
SvNumberformatter uses it upon switching locales .
@ ATTENTION If the default ctor is used the init ( ) method MUST be called
before accessing the calendar .
*/
class OnDemandCalendarWrapper
{
css::uno::Reference<css::uno::XComponentContext> m_xContext;
css::lang::Locale aEnglishLocale;
css::lang::Locale aLocale;
mutable css::lang::Locale aLastAnyLocale;
mutable std::optional<CalendarWrapper> moEnglish;
mutable std::optional<CalendarWrapper> moAny;
public :
OnDemandCalendarWrapper()
{
LanguageTag aEnglishLanguageTag(LANGUAGE_ENGLISH_US);
aEnglishLocale = aEnglishLanguageTag.getLocale();
aLastAnyLocale = aEnglishLocale;
}
void init(const css::uno::Reference<css::uno::XComponentContext>& rxContext,
const css::lang::Locale& rLocale)
{
m_xContext = rxContext;
changeLocale(rLocale);
moEnglish.reset();
moAny.reset();
}
void changeLocale(const css::lang::Locale& rLocale) { aLocale = rLocale; }
CalendarWrapper* get() const
{
CalendarWrapper* pPtr;
if (aLocale == aEnglishLocale)
{
if (!moEnglish)
{
moEnglish.emplace(m_xContext);
moEnglish->loadDefaultCalendar(aEnglishLocale);
}
pPtr = &*moEnglish;
}
else
{
if (!moAny)
{
moAny.emplace(m_xContext);
moAny->loadDefaultCalendar(aLocale);
aLastAnyLocale = aLocale;
}
else if (aLocale != aLastAnyLocale)
{
moAny->loadDefaultCalendar(aLocale);
aLastAnyLocale = aLocale;
}
pPtr = &*moAny;
}
return pPtr;
}
};
/** Load a transliteration only if it's needed.
SvNumberformatter uses it upon switching locales .
@ ATTENTION If the default ctor is used the init ( ) method MUST be called
before accessing the transliteration .
*/
class OnDemandTransliterationWrapper
{
css::uno::Reference<css::uno::XComponentContext> m_xContext;
LanguageType eLanguage;
TransliterationFlags nType;
mutable std::optional<::utl::TransliterationWrapper> moTransliterate;
mutable bool bValid;
bool bInitialized;
public :
OnDemandTransliterationWrapper()
: eLanguage(LANGUAGE_SYSTEM)
, nType(TransliterationFlags::NONE)
, bValid(false )
, bInitialized(false )
{
}
bool isInitialized() const { return bInitialized; }
void init(const css::uno::Reference<css::uno::XComponentContext>& rxContext, LanguageType eLang)
{
m_xContext = rxContext;
nType = TransliterationFlags::IGNORE_CASE;
changeLocale(eLang);
moTransliterate.reset();
bInitialized = true ;
}
void changeLocale(LanguageType eLang)
{
bValid = false ;
eLanguage = eLang;
}
const ::utl::TransliterationWrapper* get() const
{
if (!bValid)
{
if (!moTransliterate)
moTransliterate.emplace(m_xContext, nType);
moTransliterate->loadModuleIfNeeded(eLanguage);
bValid = true ;
}
return &*moTransliterate;
}
const ::utl::TransliterationWrapper* operator ->() const { return get(); }
};
/** Load a native number service wrapper only if it's needed.
SvNumberformatter uses it .
*/
class OnDemandNativeNumberWrapper
{
css::uno::Reference<css::uno::XComponentContext> m_xContext;
mutable std::optional<NativeNumberWrapper> moNativeNumber;
public :
OnDemandNativeNumberWrapper(const css::uno::Reference<css::uno::XComponentContext>& rContext)
: m_xContext(rContext)
{
}
NativeNumberWrapper& get() const
{
if (!moNativeNumber)
moNativeNumber.emplace(m_xContext);
return *moNativeNumber;
}
};
/** @short
SvNumberformatter uses it upon switching locales .
@ descr
Avoids reloading and analysing of locale data again and again .
@ ATTENTION
If the default ctor is used the init ( ) method MUST be called before
accessing any locale data .
*/
class OnDemandCharClass
{
std::optional<CharClass> moCharClass1;
std::optional<CharClass> moCharClass2;
int nCurrent; // -1 == uninitialised, 0 == class1, 1 == class2
public :
OnDemandCharClass()
: nCurrent(-1 )
{
}
void changeLocale(const css::uno::Reference<css::uno::XComponentContext>& xContext,
const LanguageTag& rLanguageTag)
{
// check for existing match
if (moCharClass1 && moCharClass1->getLanguageTag() == rLanguageTag)
{
nCurrent = 0 ;
return ;
}
if (moCharClass2 && moCharClass2->getLanguageTag() == rLanguageTag)
{
nCurrent = 1 ;
return ;
}
// no match - update one the current entries
if (nCurrent == -1 || nCurrent == 1 )
{
moCharClass1.emplace(xContext, rLanguageTag);
nCurrent = 0 ;
}
else
{
moCharClass2.emplace(xContext, rLanguageTag);
nCurrent = 1 ;
}
}
const CharClass* get() const
{
switch (nCurrent)
{
case 0 :
return &*moCharClass1;
case 1 :
return &*moCharClass2;
default :
assert(false );
return nullptr;
}
}
const CharClass* operator ->() const { return get(); }
const CharClass& operator *() const { return *get(); }
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=94 H=100 G=96
¤ Dauer der Verarbeitung: 0.12 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland