26#include <com/sun/star/beans/XPropertySet.hpp>
27#include <com/sun/star/beans/XFastPropertySet.hpp>
28#include <com/sun/star/beans/PropertyValues.hpp>
29#include <com/sun/star/frame/Desktop.hpp>
30#include <com/sun/star/frame/XStorable.hpp>
31#include <com/sun/star/linguistic2/DictionaryType.hpp>
32#include <com/sun/star/linguistic2/DictionaryList.hpp>
33#include <com/sun/star/linguistic2/LinguProperties.hpp>
34#include <com/sun/star/ucb/XCommandEnvironment.hpp>
35#include <com/sun/star/uno/Sequence.hxx>
36#include <com/sun/star/uno/Reference.h>
42#include <svtools/strings.hrc>
62 static osl::Mutex SINGLETON;
68 static std::optional<LocaleDataWrapper> oLclDtaWrp;
69 if (!oLclDtaWrp || oLclDtaWrp->getLoadedLanguageTag().getLanguageType() != nLang)
76 if ( rLocale.Language.isEmpty() )
84 return css::lang::Locale();
90 return nLanguage.
anyOf(
102 if (rBcp47.size() != 3)
104 return rBcp47 ==
u"zxx" || rBcp47 ==
u"und" || rBcp47 ==
u"mul";
107static sal_Int32
Minimum( sal_Int32
n1, sal_Int32
n2, sal_Int32 n3 )
109 return std::min(std::min(
n1,
n2),
n3);
121 IntArray2D(
int nDim1,
int nDim2 );
123 sal_Int32 &
Value(
int i,
int k );
128IntArray2D::IntArray2D(
int nDim1,
int nDim2 )
135sal_Int32 & IntArray2D::Value(
int i,
int k )
137 assert( (0 <= i && i <
n1) &&
"first index out of range" );
138 assert( (0 <= k && k <
n2) &&
"second index out of range" );
139 assert( (i *
n2 + k <
n1 *
n2) &&
"index out of range" );
143sal_Int32
LevDistance( std::u16string_view rTxt1, std::u16string_view rTxt2 )
145 sal_Int32 nLen1 = rTxt1.size();
146 sal_Int32 nLen2 = rTxt2.size();
153 IntArray2D
aData( nLen1 + 1, nLen2 + 1 );
156 for (
i = 0;
i <= nLen1; ++
i)
158 for (k = 0; k <= nLen2; ++k)
159 aData.Value(0, k) = k;
160 for (
i = 1;
i <= nLen1; ++
i)
162 for (k = 1; k <= nLen2; ++k)
166 sal_Int32 nCost = c1i == c2k ? 0 : 1;
169 aData.Value(
i-1, k-1) + nCost );
173 int nT =
aData.Value(
i-2, k-2) + 1;
174 if (rTxt1[
i - 2] != c1i)
176 if (rTxt2[k - 2] != c2k)
185 sal_Int32 nDist =
aData.Value(nLen1, nLen2);
190 const uno::Reference< XPropertySet > &rxProp )
194 const PropertyValue *pVal = std::find_if(rProperties.begin(), rProperties.end(),
195 [](
const PropertyValue& rVal) { return UPH_IS_USE_DICTIONARY_LIST == rVal.Handle; });
197 if (pVal != rProperties.end())
199 pVal->Value >>= bRes;
203 uno::Reference< XFastPropertySet > xFast( rxProp, UNO_QUERY );
212 const uno::Reference< XPropertySet > &rxProp )
216 const PropertyValue *pVal = std::find_if(rProperties.begin(), rProperties.end(),
217 [](
const PropertyValue& rVal) { return UPH_IS_IGNORE_CONTROL_CHARACTERS == rVal.Handle; });
219 if (pVal != rProperties.end())
221 pVal->Value >>= bRes;
225 uno::Reference< XFastPropertySet > xFast( rxProp, UNO_QUERY );
240 sal_Int32 nIdx = xEntry->getDictionaryWord().indexOf(
'=' );
242 nIdx = xEntry->getDictionaryWord().indexOf(
'[' );
243 bRes = nIdx != -1 && nIdx != 0;
249 const uno::Reference< XSearchableDictionaryList > &xDicList,
251 bool bSearchPosDics,
bool bSearchSpellEntry )
255 uno::Reference< XDictionaryEntry > xEntry;
260 const uno::Sequence< uno::Reference< XDictionary > >
261 aDics( xDicList->getDictionaries() );
262 const uno::Reference< XDictionary >
263 *pDic = aDics.getConstArray();
264 sal_Int32 nDics = xDicList->getCount();
267 for (
i = 0;
i < nDics;
i++)
269 uno::Reference< XDictionary > axDic = pDic[
i];
271 DictionaryType
eType = axDic->getDictionaryType();
274 if ( axDic.is() && axDic->isActive()
278 SAL_WARN_IF(
eType == DictionaryType_MIXED,
"linguistic",
"unexpected dictionary type");
280 if ( (!bSearchPosDics &&
eType == DictionaryType_NEGATIVE)
281 || ( bSearchPosDics &&
eType == DictionaryType_POSITIVE))
283 xEntry = axDic->getEntry( rWord );
302 for (
const uno::Reference<XDictionary>& rDic : aDics)
306 uno::Reference< frame::XStorable > xStor( rDic, UNO_QUERY );
309 if (!xStor->isReadonly() && xStor->hasLocation())
313 catch(uno::Exception &)
323 uno::Reference< XDictionary >
const &rxDic,
324 const OUString &rWord,
bool bIsNeg,
325 const OUString &rRplcTxt,
331 OUString aTmp( rWord );
334 sal_Int32 nLen = rWord.getLength();
335 if (nLen > 0 &&
'.' == rWord[ nLen - 1])
339 aTmp = aTmp.copy( 0, nLen - 1 );
342 bool bAddOk = rxDic->add( aTmp, bIsNeg, rRplcTxt );
351 uno::Reference< frame::XStorable > xStor( rxDic, UNO_QUERY );
352 if (xStor.is() && xStor->isReadonly())
362std::vector< LanguageType >
365 std::vector< LanguageType > aLangs;
366 aLangs.reserve(rLocaleSeq.getLength());
368 std::transform(rLocaleSeq.begin(), rLocaleSeq.end(), std::back_inserter(aLangs),
369 [](
const Locale& rLocale) { return LinguLocaleToLanguage(rLocale); });
374uno::Sequence< sal_Int16 >
377 std::vector<sal_Int16> aLangs;
378 aLangs.reserve(rLocaleSeq.getLength());
380 std::transform(rLocaleSeq.begin(), rLocaleSeq.end(), std::back_inserter(aLangs),
381 [](
const Locale& rLocale) { return static_cast<sal_uInt16>(LinguLocaleToLanguage(rLocale)); });
388 bool bExists =
false;
394 uno::Reference< css::ucb::XCommandEnvironment > xCmdEnv;
415static bool GetAltSpelling( sal_Int16 &rnChgPos, sal_Int16 &rnChgLen, OUString &rRplc,
416 uno::Reference< XHyphenatedWord >
const &rxHyphWord )
418 bool bRes = rxHyphWord->isAlternativeSpelling();
421 OUString aWord( rxHyphWord->getWord() ),
422 aHyphenatedWord( rxHyphWord->getHyphenatedWord() );
423 sal_Int16 nHyphenationPos = rxHyphWord->getHyphenationPos();
426 *pAltWord = aHyphenatedWord.getStr();
438 for (sal_Int16
i = 0 ; pWord[ nPosL ] == pAltWord[ nAltPosL ]; nPosL++, nAltPosL++,
i++)
444 if (
i >= nHyphenationPos + 1)
449 sal_Int32 nPosR = aWord.getLength() - 1,
450 nAltPosR = aHyphenatedWord.getLength() - 1;
451 for ( ; nPosR >= nPosL && nAltPosR >= nAltPosL
452 && pWord[ nPosR ] == pAltWord[ nAltPosR ];
456 rnChgPos = sal::static_int_cast< sal_Int16 >(nPosL);
457 rnChgLen = sal::static_int_cast< sal_Int16 >(nAltPosR - nPosL);
458 assert( rnChgLen >= 0 &&
"nChgLen < 0");
460 sal_Int32 nTxtStart = nPosL;
461 sal_Int32 nTxtLen = nAltPosR - nPosL + 1;
462 rRplc = aHyphenatedWord.copy( nTxtStart, nTxtLen );
469 sal_Int32 nLen = rOrigWord.size();
471 while (
nPos >= 0 &&
i++ < nLen)
478 return sal::static_int_cast< sal_Int16 >((0 <=
i &&
i < nLen) ?
i : -1);
484 sal_Int32 nLen = rTxt.size();
488 for (sal_Int32
i = 0;
i <
nPos; ++
i)
500 const OUString &rOrigWord,
501 uno::Reference< XHyphenatedWord >
const &rxHyphWord )
503 uno::Reference< XHyphenatedWord > xRes;
504 if (!rOrigWord.isEmpty() && rxHyphWord.is())
506 sal_Int16 nChgPos = 0,
509 bool bAltSpelling =
GetAltSpelling( nChgPos, nChgLen, aRplc, rxHyphWord );
511 OUString aOrigHyphenatedWord;
512 sal_Int16 nOrigHyphenPos = -1;
513 sal_Int16 nOrigHyphenationPos = -1;
516 aOrigHyphenatedWord = rOrigWord;
517 nOrigHyphenPos =
GetOrigWordPos( rOrigWord, rxHyphWord->getHyphenPos() );
518 nOrigHyphenationPos =
GetOrigWordPos( rOrigWord, rxHyphWord->getHyphenationPos() );
528 sal_Int16 nHyphenationPos = rxHyphWord->getHyphenationPos();
529 if (nChgPos > nHyphenationPos)
532 std::u16string_view aLeft = rOrigWord.subView( 0,
nPos );
533 std::u16string_view aRight = rOrigWord.subView(
nPos );
535 aOrigHyphenatedWord = aLeft + aRplc + aRight;
537 nOrigHyphenPos = sal::static_int_cast< sal_Int16 >(aLeft.size() +
538 rxHyphWord->getHyphenPos() - nChgPos);
539 nOrigHyphenationPos =
GetOrigWordPos( rOrigWord, nHyphenationPos );
542 if (nOrigHyphenPos == -1 || nOrigHyphenationPos == -1)
544 SAL_WARN(
"linguistic",
"failed to get nOrigHyphenPos or nOrigHyphenationPos" );
550 rOrigWord, nLang, nOrigHyphenationPos,
551 aOrigHyphenatedWord, nOrigHyphenPos );
566 sal_Int32 tlen = aTerm.getLength();
571 for (sal_Int32 tindex = 0; tindex < tlen; ++tindex)
574 css::i18n::KCharacterType::UPPER) nc++;
582 css::i18n::KCharacterType::UPPER))
629 const sal_Int32 nLen = rText.getLength();
634 const sal_uInt32 nCodePoint = rText.iterateCodePoints( &
i );
637 if (nDigitZero > nCodePoint)
639 if ( nCodePoint <= nDigitZero + 9)
651 sal_Int32 nLen = rText.size();
653 for(sal_Int32
i = 0;
i < nLen; ++
i)
656 if (
'0' > cChar || cChar >
'9' )
674 uno::Reference< XSearchableDictionaryList > xRef;
677 xRef = DictionaryList::create(xContext);
679 catch (
const uno::Exception &)
681 SAL_WARN(
"linguistic",
"createInstance failed" );
689 uno::Reference< XDictionary > xRes;
694 xRes = xDL->getDictionaryByName(
Translate::get(STR_DESCRIPTION_IGNOREALLLIST, loc) );
707 xDesktop = frame::Desktop::create(xContext);
709 catch (
const uno::Exception &)
711 SAL_WARN(
"linguistic",
"createInstance failed" );
722 xDesktop->addTerminateListener(
this );
728 xDesktop->removeTerminateListener(
this );
sal_Int32 getCharacterType(const OUString &rStr, sal_Int32 nPos) const
bool isUpper(const OUString &rStr, sal_Int32 nPos) const
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
static LanguageType convertToLanguageType(const css::lang::Locale &rLocale, bool bResolveSystem=true)
virtual void SAL_CALL disposing(const css::lang::EventObject &Source) override
css::uno::Reference< css::frame::XDesktop2 > xDesktop
virtual void SAL_CALL queryTermination(const css::lang::EventObject &aEvent) override
virtual ~AppExitListener() override
virtual void SAL_CALL notifyTermination(const css::lang::EventObject &aEvent) override
css::uno::Any getPropertyValue(const OUString &rPropertyName)
#define LANGUAGE_UNDETERMINED
#define LANGUAGE_MULTIPLE
#define UPH_IS_USE_DICTIONARY_LIST
#define UPH_IS_IGNORE_CONTROL_CHARACTERS
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
std::unique_ptr< sal_Int32[]> pData
constexpr OUStringLiteral aData
std::locale Create(std::string_view aPrefixName, const LanguageTag &rLocale)
OUString get(TranslateId sContextAndId, const std::locale &loc)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getProcessComponentContext()
std::map< sal_Int32, std::shared_ptr< SetItemPropertyStorage > > PropertyValues
bool IsHyphen(sal_Unicode cChar)
bool SaveDictionaries(const uno::Reference< XSearchableDictionaryList > &xDicList)
std::vector< LanguageType > LocaleSeqToLangVec(uno::Sequence< Locale > const &rLocaleSeq)
bool IsReadOnly(const OUString &rURL, bool *pbExist)
static bool GetAltSpelling(sal_Int16 &rnChgPos, sal_Int16 &rnChgLen, OUString &rRplc, uno::Reference< XHyphenatedWord > const &rxHyphWord)
const sal_uInt32 the_aDigitZeroes[]
uno::Sequence< sal_Int16 > LocaleSeqToLangSeq(uno::Sequence< Locale > const &rLocaleSeq)
bool LinguIsUnspecified(LanguageType nLanguage)
Checks if a LanguageType is one of the values that denote absence of language or undetermined languag...
uno::Reference< XSearchableDictionaryList > GetDictionaryList()
static sal_Int16 GetOrigWordPos(std::u16string_view rOrigWord, sal_Int16 nPos)
uno::Reference< XHyphenatedWord > RebuildHyphensAndControlChars(const OUString &rOrigWord, uno::Reference< XHyphenatedWord > const &rxHyphWord)
uno::Reference< XLinguProperties > GetLinguProperties()
static sal_Int32 Minimum(sal_Int32 n1, sal_Int32 n2, sal_Int32 n3)
CapType capitalType(const OUString &aTerm, CharClass const *pCC)
uno::Reference< XDictionaryEntry > SearchDicList(const uno::Reference< XSearchableDictionaryList > &xDicList, const OUString &rWord, LanguageType nLanguage, bool bSearchPosDics, bool bSearchSpellEntry)
sal_Int32 GetPosInWordToCheck(std::u16string_view rTxt, sal_Int32 nPos)
bool IsControlChar(sal_Unicode cChar)
osl::Mutex & GetLinguMutex()
! multi-thread safe mutex for all platforms !!
bool IsUpper(const OUString &rText, sal_Int32 nPos, sal_Int32 nLen, LanguageType nLanguage)
bool IsIgnoreControlChars(const PropertyValues &rProperties, const uno::Reference< XPropertySet > &rxProp)
sal_Int32 LevDistance(std::u16string_view rTxt1, std::u16string_view rTxt2)
bool IsNumeric(std::u16string_view rText)
css::lang::Locale LinguLanguageToLocale(LanguageType nLanguage)
Convert LanguageType to Locale for legacy handling.
static bool lcl_HasHyphInfo(const uno::Reference< XDictionaryEntry > &xEntry)
bool HasDigits(const OUString &rText)
const LocaleDataWrapper & GetLocaleDataWrapper(LanguageType nLang)
DictionaryError AddEntryToDic(uno::Reference< XDictionary > const &rxDic, const OUString &rWord, bool bIsNeg, const OUString &rRplcTxt, bool bStripDot)
uno::Reference< XDictionary > GetIgnoreAllList()
LanguageType LinguLocaleToLanguage(const css::lang::Locale &rLocale)
Convert Locale to LanguageType for legacy handling.
bool IsUseDicList(const PropertyValues &rProperties, const uno::Reference< XPropertySet > &rxProp)
bool anyOf(strong_int v) const