22#include <com/sun/star/uno/Reference.h>
23#include <com/sun/star/linguistic2/XLinguServiceEventBroadcaster.hpp>
24#include <com/sun/star/linguistic2/SpellFailure.hpp>
25#include <com/sun/star/uno/XComponentContext.hpp>
32#include <osl/mutex.hxx>
60 std::vector< OUString > aVec;
62 bool HasEntry( std::u16string_view rText )
const;
66 ProposalList(
const ProposalList&) =
delete;
67 ProposalList& operator=(
const ProposalList&) =
delete;
70 void Prepend(
const OUString &rText );
71 void Append(
const OUString &rNew );
72 void Append(
const std::vector< OUString > &rNew );
74 std::vector< OUString > GetVector()
const;
79bool ProposalList::HasEntry( std::u16string_view rText )
const
82 size_t nCnt = aVec.size();
83 for (
size_t i = 0; !bFound &&
i < nCnt; ++
i)
91void ProposalList::Prepend(
const OUString &rText )
93 if (!HasEntry( rText ))
94 aVec.insert( aVec.begin(), rText );
97void ProposalList::Append(
const OUString &rText )
99 if (!HasEntry( rText ))
100 aVec.push_back( rText );
103void ProposalList::Append(
const std::vector< OUString > &rNew )
105 size_t nLen = rNew.size();
106 for (
size_t i = 0;
i < nLen; ++
i)
108 const OUString &rText = rNew[
i];
109 if (!HasEntry( rText ))
116 for (
const OUString& rText : rNew)
118 if (!HasEntry( rText ))
123size_t ProposalList::Count()
const
128 size_t nLen = aVec.size();
129 for (
size_t i = 0;
i < nLen; ++
i)
131 if (!aVec[i].isEmpty())
137std::vector< OUString > ProposalList::GetVector()
const
141 std::vector< OUString > aRes( nCount );
142 sal_Int32 nLen = aVec.size();
143 for (sal_Int32 i = 0;
i < nLen; ++
i)
145 const OUString &rText = aVec[
i];
146 DBG_ASSERT( nIdx < nCount,
"index out of range" );
147 if (nIdx < nCount && !rText.isEmpty())
148 aRes[ nIdx++ ] = rText;
161 return rRef.is() && rRef->hasLocale( aTmpLocale ); });
179 std::vector<Locale> aLocales;
183 [](SpellSvcByLangMap_t::const_reference elem) { return LanguageTag::convertToLocale(elem.first); });
199 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
208 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
218 const OUString &rWord,
228 xRes = xIgnoreAll->getEntry( rWord );
233 rWord, nLanguage,
false,
true ) );
239 rWord, nLanguage,
true,
true ) );
250 const OUString& rWord,
262 SpellSvcByLangMap_t::iterator aIt(
m_aSvcMap.find( nLanguage ) );
267 OUString aChkWord( rWord );
272 DBG_ASSERT( 1 == aSingleQuote.getLength(),
"unexpected length of quotation mark" );
273 if (!aSingleQuote.isEmpty())
274 aChkWord = aChkWord.replace( aSingleQuote[0],
'\'' );
280 sal_Int32 nLen = pEntry->
aSvcRefs.getLength();
282 "lng : sequence length mismatch");
284 "lng : index out of range");
288 bool bTmpResValid =
false;
294 while (i <= pEntry->nLastTriedSvcIndex
295 && (!bTmpResValid || !bTmpRes))
303 bTmpRes = pRef[
i]->isValid( aChkWord, aLocale, rProperties );
308 if (bTmpRes && !rProperties.hasElements())
313 bTmpResValid =
false;
323 if ((!bTmpResValid || !bTmpRes)
326 const OUString *pImplNames = pEntry->
aSvcImplNames.getConstArray();
336 while (
i < nLen && (!bTmpResValid || !bTmpRes))
342 xSpell.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
343 pImplNames[
i], aArgs, xContext ),
346 catch (uno::Exception &)
348 SAL_WARN(
"linguistic",
"createInstanceWithArguments failed" );
353 xBroadcaster( xSpell, UNO_QUERY );
354 if (xBroadcaster.is())
358 if (xSpell.is() && xSpell->hasLocale( aLocale ))
363 bTmpRes = xSpell->isValid( aChkWord, aLocale, rProperties );
367 if (bTmpRes && !rProperties.hasElements())
372 bTmpResValid =
false;
394 bRes = !xTmp->isNegative();
398 if (ct == CapType::INITCAP || ct == CapType::ALLCAP) {
401 bRes = !xTmp2->isNegative();
413 const OUString& rWord,
425 SpellSvcByLangMap_t::iterator aIt(
m_aSvcMap.find( nLanguage ) );
430 OUString aChkWord( rWord );
435 DBG_ASSERT( 1 == aSingleQuote.getLength(),
"unexpected length of quotation mark" );
436 if (!aSingleQuote.isEmpty())
437 aChkWord = aChkWord.replace( aSingleQuote[0],
'\'' );
443 sal_Int32 nLen = pEntry->
aSvcRefs.getLength();
445 "lng : sequence length mismatch");
447 "lng : index out of range");
451 bool bTmpResValid =
false;
456 sal_Int32 nNumSuggestions = -1;
457 while (i <= pEntry->nLastTriedSvcIndex
458 && (!bTmpResValid || xTmpRes.is()) )
468 xTmpRes = pRef[
i]->spell( aChkWord, aLocale, rProperties );
473 if (!xTmpRes.is() && !rProperties.hasElements())
478 bTmpResValid =
false;
483 if (!xRes.is() && bTmpResValid)
488 nNumSuggestions = xRes->getAlternatives().getLength();
490 sal_Int32 nTmpNumSuggestions = 0;
491 if (xTmpRes.is() && bTmpResValid)
492 nTmpNumSuggestions = xTmpRes->getAlternatives().getLength();
493 if (xRes.is() && nNumSuggestions == 0 && nTmpNumSuggestions > 0)
496 nNumSuggestions = nTmpNumSuggestions;
504 if ((!bTmpResValid || xTmpRes.is())
507 const OUString *pImplNames = pEntry->
aSvcImplNames.getConstArray();
517 sal_Int32 nNumSuggestions = -1;
518 while (
i < nLen && (!bTmpResValid || xTmpRes.is()))
524 xSpell.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
525 pImplNames[
i], aArgs, xContext ),
528 catch (uno::Exception &)
530 SAL_WARN(
"linguistic",
"createInstanceWithArguments failed" );
535 xBroadcaster( xSpell, UNO_QUERY );
536 if (xBroadcaster.is())
540 if (xSpell.is() && xSpell->hasLocale( aLocale ))
547 xTmpRes = xSpell->spell( aChkWord, aLocale, rProperties );
552 if (!xTmpRes.is() && !rProperties.hasElements())
557 bTmpResValid =
false;
562 if (!xRes.is() && bTmpResValid)
567 nNumSuggestions = xRes->getAlternatives().getLength();
569 sal_Int32 nTmpNumSuggestions = 0;
570 if (xTmpRes.is() && bTmpResValid)
571 nTmpNumSuggestions = xTmpRes->getAlternatives().getLength();
572 if (xRes.is() && nNumSuggestions == 0 && nTmpNumSuggestions > 0)
575 nNumSuggestions = nTmpNumSuggestions;
593 if (bTmpResValid && !xTmpRes.is())
598 ProposalList aProposalList;
599 sal_Int16 eFailureType = -1;
602 aProposalList.Append( xRes->getAlternatives() );
603 eFailureType = xRes->getFailureType();
615 if (xTmp->isNegative())
617 eFailureType = SpellFailure::IS_NEGATIVE_WORD;
620 OUString aAddRplcTxt( xTmp->getReplacementText() );
623 if (!aAddRplcTxt.isEmpty() &&
624 !
SearchDicList( xDList, aAddRplcTxt, nLanguage,
false,
true ).is())
626 aProposalList.Prepend( aAddRplcTxt );
639 if (ct == CapType::INITCAP || ct == CapType::ALLCAP)
644 if (xTmp2->isNegative())
646 eFailureType = SpellFailure::IS_NEGATIVE_WORD;
649 OUString aAddRplcTxt( xTmp2->getReplacementText() );
652 if (!aAddRplcTxt.isEmpty() &&
653 !
SearchDicList( xDList, aAddRplcTxt, nLanguage,
false,
true ).is())
657 case CapType::INITCAP:
658 aProposalList.Prepend(
m_oCharClass->titlecase(aAddRplcTxt) );
660 case CapType::ALLCAP:
661 aProposalList.Prepend(
m_oCharClass->uppercase(aAddRplcTxt) );
679 if (eFailureType != -1)
683 std::vector< OUString > aDicListProps;
685 aProposalList.Append( aDicListProps );
686 std::vector< OUString > aProposals = aProposalList.GetVector();
693 uno::Reference< linguistic2::XSetSpellAlternatives > xSetAlt( xRes, uno::UNO_QUERY );
697 xSetAlt->setFailureType( eFailureType );
703 SAL_WARN(
"linguistic",
"XSetSpellAlternatives not implemented!" );
705 else if (!aProposals.empty())
729 sal_Int16 nLanguage )
737 const OUString& rWord,
739 const uno::Sequence< beans::PropertyValue >& rProperties )
747 const OUString& rWord,
749 const uno::Sequence< beans::PropertyValue >& rProperties )
766 sal_Int32 nLen = rSvcImplNames.getLength();
782 auto pTmpEntry = std::make_shared<LangSvcEntries_Spell>( rSvcImplNames );
799 const SpellSvcByLangMap_t::const_iterator aIt(
m_aSvcMap.find( nLanguage ) );
825 return pCC->lowercase(aTerm);
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
bool AddLngSvcEvtBroadcaster(const css::uno::Reference< css::linguistic2::XLinguServiceEventBroadcaster > &rxBroadcaster)
virtual css::uno::Reference< css::linguistic2::XSpellAlternatives > SAL_CALL spell(const OUString &aWord, const css::lang::Locale &aLocale, const css::uno::Sequence< ::css::beans::PropertyValue > &aProperties) override
virtual void SetServiceList(const css::lang::Locale &rLocale, const css::uno::Sequence< OUString > &rSvcImplNames) override
virtual sal_Bool SAL_CALL hasLocale(const css::lang::Locale &aLocale) override
linguistic::SpellCache & GetCache() const
void setCharClass(const LanguageTag &rLanguageTag)
const css::uno::Reference< css::linguistic2::XLinguProperties > & GetPropSet()
const css::uno::Reference< css::linguistic2::XSearchableDictionaryList > & GetDicList()
SpellSvcByLangMap_t m_aSvcMap
virtual css::uno::Sequence< css::lang::Locale > SAL_CALL getLocales() override
std::unique_ptr< linguistic::SpellCache > m_pCache
virtual css::uno::Sequence< ::sal_Int16 > SAL_CALL getLanguages() override
std::optional< CharClass > m_oCharClass
virtual sal_Bool SAL_CALL hasLanguage(::sal_Int16 nLanguage) override
virtual sal_Bool SAL_CALL isValid(const OUString &aWord, const css::lang::Locale &aLocale, const css::uno::Sequence< ::css::beans::PropertyValue > &aProperties) override
css::uno::Reference< css::linguistic2::XSpellAlternatives > spell_Impl(const OUString &aWord, LanguageType nLanguage, const css::beans::PropertyValues &aProperties)
virtual ~SpellCheckerDispatcher() override
static OUString makeLowerCase(const OUString &, const std::optional< CharClass > &)
bool isValid_Impl(const OUString &aWord, LanguageType nLanguage, const css::beans::PropertyValues &aProperties)
SpellCheckerDispatcher(const SpellCheckerDispatcher &)=delete
virtual css::uno::Sequence< OUString > GetServiceList(const css::lang::Locale &rLocale) const override
void AddWord(const OUString &rWord, LanguageType nLang)
bool CheckWord(const OUString &rWord, LanguageType nLang)
#define DBG_ASSERT(sCon, aError)
#define SAL_WARN(area, stream)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Reference< XComponentContext > getProcessComponentContext()
std::map< sal_Int32, std::shared_ptr< SetItemPropertyStorage > > PropertyValues
void SearchSimilarText(const OUString &rText, LanguageType nLanguage, Reference< XSearchableDictionaryList > const &xDicList, std::vector< OUString > &rDicListProps)
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()
bool RemoveHyphens(OUString &rTxt)
bool RemoveControlChars(OUString &rTxt)
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)
osl::Mutex & GetLinguMutex()
! multi-thread safe mutex for all platforms !!
void SeqRemoveNegEntries(std::vector< OUString > &rSeq, Reference< XSearchableDictionaryList > const &rxDicList, LanguageType nLanguage)
bool IsIgnoreControlChars(const PropertyValues &rProperties, const uno::Reference< XPropertySet > &rxProp)
const LocaleDataWrapper & GetLocaleDataWrapper(LanguageType nLang)
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)
static Reference< XDictionaryEntry > lcl_GetRulingDictionaryEntry(const OUString &rWord, LanguageType nLanguage)
static bool SvcListHasLanguage(const LangSvcEntries_Spell &rEntry, LanguageType nLanguage)
css::uno::Sequence< css::uno::Reference< css::linguistic2::XSpellChecker > > aSvcRefs
css::uno::Sequence< OUString > aSvcImplNames
sal_Int16 nLastTriedSvcIndex