1*3b8558fdSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*3b8558fdSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*3b8558fdSAndrew Rist * or more contributor license agreements. See the NOTICE file
5*3b8558fdSAndrew Rist * distributed with this work for additional information
6*3b8558fdSAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*3b8558fdSAndrew Rist * to you under the Apache License, Version 2.0 (the
8*3b8558fdSAndrew Rist * "License"); you may not use this file except in compliance
9*3b8558fdSAndrew Rist * with the License. You may obtain a copy of the License at
10*3b8558fdSAndrew Rist *
11*3b8558fdSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12*3b8558fdSAndrew Rist *
13*3b8558fdSAndrew Rist * Unless required by applicable law or agreed to in writing,
14*3b8558fdSAndrew Rist * software distributed under the License is distributed on an
15*3b8558fdSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*3b8558fdSAndrew Rist * KIND, either express or implied. See the License for the
17*3b8558fdSAndrew Rist * specific language governing permissions and limitations
18*3b8558fdSAndrew Rist * under the License.
19*3b8558fdSAndrew Rist *
20*3b8558fdSAndrew Rist *************************************************************/
21*3b8558fdSAndrew Rist
22*3b8558fdSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_linguistic.hxx"
26cdf0e10cSrcweir #include <com/sun/star/uno/Reference.h>
27cdf0e10cSrcweir
28cdf0e10cSrcweir #include <com/sun/star/linguistic2/SpellFailure.hpp>
29cdf0e10cSrcweir #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
30cdf0e10cSrcweir #include <tools/debug.hxx>
31cdf0e10cSrcweir #include <unotools/processfactory.hxx>
32cdf0e10cSrcweir #include <osl/mutex.hxx>
33cdf0e10cSrcweir
34cdf0e10cSrcweir #include <vector>
35cdf0e10cSrcweir
36cdf0e10cSrcweir #include "linguistic/spelldta.hxx"
37cdf0e10cSrcweir #include "lngsvcmgr.hxx"
38cdf0e10cSrcweir
39cdf0e10cSrcweir
40cdf0e10cSrcweir using namespace utl;
41cdf0e10cSrcweir using namespace osl;
42cdf0e10cSrcweir using namespace rtl;
43cdf0e10cSrcweir using namespace com::sun::star;
44cdf0e10cSrcweir using namespace com::sun::star::beans;
45cdf0e10cSrcweir using namespace com::sun::star::lang;
46cdf0e10cSrcweir using namespace com::sun::star::uno;
47cdf0e10cSrcweir using namespace com::sun::star::linguistic2;
48cdf0e10cSrcweir
49cdf0e10cSrcweir namespace linguistic
50cdf0e10cSrcweir {
51cdf0e10cSrcweir
52cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
53cdf0e10cSrcweir
54cdf0e10cSrcweir
55cdf0e10cSrcweir #define MAX_PROPOSALS 40
56cdf0e10cSrcweir
MergeProposals(Reference<XSpellAlternatives> & rxAlt1,Reference<XSpellAlternatives> & rxAlt2)57cdf0e10cSrcweir Reference< XSpellAlternatives > MergeProposals(
58cdf0e10cSrcweir Reference< XSpellAlternatives > &rxAlt1,
59cdf0e10cSrcweir Reference< XSpellAlternatives > &rxAlt2)
60cdf0e10cSrcweir {
61cdf0e10cSrcweir Reference< XSpellAlternatives > xMerged;
62cdf0e10cSrcweir
63cdf0e10cSrcweir if (!rxAlt1.is())
64cdf0e10cSrcweir xMerged = rxAlt2;
65cdf0e10cSrcweir else if (!rxAlt2.is())
66cdf0e10cSrcweir xMerged = rxAlt1;
67cdf0e10cSrcweir else
68cdf0e10cSrcweir {
69cdf0e10cSrcweir sal_Int32 nAltCount1 = rxAlt1->getAlternativesCount();
70cdf0e10cSrcweir Sequence< OUString > aAlt1( rxAlt1->getAlternatives() );
71cdf0e10cSrcweir const OUString *pAlt1 = aAlt1.getConstArray();
72cdf0e10cSrcweir
73cdf0e10cSrcweir sal_Int32 nAltCount2 = rxAlt2->getAlternativesCount();
74cdf0e10cSrcweir Sequence< OUString > aAlt2( rxAlt2->getAlternatives() );
75cdf0e10cSrcweir const OUString *pAlt2 = aAlt2.getConstArray();
76cdf0e10cSrcweir
77cdf0e10cSrcweir sal_Int32 nCountNew = Min( nAltCount1 + nAltCount2, (sal_Int32) MAX_PROPOSALS );
78cdf0e10cSrcweir Sequence< OUString > aAltNew( nCountNew );
79cdf0e10cSrcweir OUString *pAltNew = aAltNew.getArray();
80cdf0e10cSrcweir
81cdf0e10cSrcweir sal_Int32 nIndex = 0;
82cdf0e10cSrcweir sal_Int32 i = 0;
83cdf0e10cSrcweir for (int j = 0; j < 2; j++)
84cdf0e10cSrcweir {
85cdf0e10cSrcweir sal_Int32 nCount = j == 0 ? nAltCount1 : nAltCount2;
86cdf0e10cSrcweir const OUString *pAlt = j == 0 ? pAlt1 : pAlt2;
87cdf0e10cSrcweir for (i = 0; i < nCount && nIndex < MAX_PROPOSALS; i++)
88cdf0e10cSrcweir {
89cdf0e10cSrcweir if (pAlt[i].getLength())
90cdf0e10cSrcweir pAltNew[ nIndex++ ] = pAlt[ i ];
91cdf0e10cSrcweir }
92cdf0e10cSrcweir }
93cdf0e10cSrcweir DBG_ASSERT(nIndex == nCountNew, "lng : wrong number of proposals");
94cdf0e10cSrcweir
95cdf0e10cSrcweir SpellAlternatives *pSpellAlt = new SpellAlternatives;
96cdf0e10cSrcweir pSpellAlt->SetWordLanguage( rxAlt1->getWord(),
97cdf0e10cSrcweir LocaleToLanguage( rxAlt1->getLocale() ) );
98cdf0e10cSrcweir pSpellAlt->SetFailureType( rxAlt1->getFailureType() );
99cdf0e10cSrcweir pSpellAlt->SetAlternatives( aAltNew );
100cdf0e10cSrcweir xMerged = pSpellAlt;
101cdf0e10cSrcweir }
102cdf0e10cSrcweir
103cdf0e10cSrcweir return xMerged;
104cdf0e10cSrcweir }
105cdf0e10cSrcweir
106cdf0e10cSrcweir
SeqHasEntry(const Sequence<OUString> & rSeq,const OUString & rTxt)107cdf0e10cSrcweir sal_Bool SeqHasEntry(
108cdf0e10cSrcweir const Sequence< OUString > &rSeq,
109cdf0e10cSrcweir const OUString &rTxt)
110cdf0e10cSrcweir {
111cdf0e10cSrcweir sal_Bool bRes = sal_False;
112cdf0e10cSrcweir sal_Int32 nLen = rSeq.getLength();
113cdf0e10cSrcweir const OUString *pEntry = rSeq.getConstArray();
114cdf0e10cSrcweir for (sal_Int32 i = 0; i < nLen && !bRes; ++i)
115cdf0e10cSrcweir {
116cdf0e10cSrcweir if (rTxt == pEntry[i])
117cdf0e10cSrcweir bRes = sal_True;
118cdf0e10cSrcweir }
119cdf0e10cSrcweir return bRes;
120cdf0e10cSrcweir }
121cdf0e10cSrcweir
122cdf0e10cSrcweir
SearchSimilarText(const OUString & rText,sal_Int16 nLanguage,Reference<XDictionaryList> & xDicList,std::vector<OUString> & rDicListProps)123cdf0e10cSrcweir void SearchSimilarText( const OUString &rText, sal_Int16 nLanguage,
124cdf0e10cSrcweir Reference< XDictionaryList > &xDicList,
125cdf0e10cSrcweir std::vector< OUString > & rDicListProps )
126cdf0e10cSrcweir {
127cdf0e10cSrcweir if (!xDicList.is())
128cdf0e10cSrcweir return;
129cdf0e10cSrcweir
130cdf0e10cSrcweir const uno::Sequence< Reference< XDictionary > >
131cdf0e10cSrcweir aDics( xDicList->getDictionaries() );
132cdf0e10cSrcweir const Reference< XDictionary >
133cdf0e10cSrcweir *pDic = aDics.getConstArray();
134cdf0e10cSrcweir sal_Int32 nDics = xDicList->getCount();
135cdf0e10cSrcweir
136cdf0e10cSrcweir for (sal_Int32 i = 0; i < nDics; i++)
137cdf0e10cSrcweir {
138cdf0e10cSrcweir Reference< XDictionary > xDic( pDic[i], UNO_QUERY );
139cdf0e10cSrcweir
140cdf0e10cSrcweir sal_Int16 nLang = LocaleToLanguage( xDic->getLocale() );
141cdf0e10cSrcweir
142cdf0e10cSrcweir if ( xDic.is() && xDic->isActive()
143cdf0e10cSrcweir && (nLang == nLanguage || nLang == LANGUAGE_NONE) )
144cdf0e10cSrcweir {
145cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
146cdf0e10cSrcweir DictionaryType eType = xDic->getDictionaryType();
147cdf0e10cSrcweir (void) eType;
148cdf0e10cSrcweir DBG_ASSERT( eType != DictionaryType_MIXED, "unexpected dictionary type" );
149cdf0e10cSrcweir #endif
150cdf0e10cSrcweir const Sequence< Reference< XDictionaryEntry > > aEntries = xDic->getEntries();
151cdf0e10cSrcweir const Reference< XDictionaryEntry > *pEntries = aEntries.getConstArray();
152cdf0e10cSrcweir sal_Int32 nLen = aEntries.getLength();
153cdf0e10cSrcweir for (sal_Int32 k = 0; k < nLen; ++k)
154cdf0e10cSrcweir {
155cdf0e10cSrcweir String aEntryTxt;
156cdf0e10cSrcweir if (pEntries[k].is())
157cdf0e10cSrcweir {
158cdf0e10cSrcweir aEntryTxt = pEntries[k]->getDictionaryWord();
159cdf0e10cSrcweir // remove characters used to determine hyphenation positions
160cdf0e10cSrcweir aEntryTxt.EraseAllChars( '=' );
161cdf0e10cSrcweir }
162cdf0e10cSrcweir if (aEntryTxt.Len() > 0 && LevDistance( rText, aEntryTxt ) <= 2)
163cdf0e10cSrcweir rDicListProps.push_back( aEntryTxt );
164cdf0e10cSrcweir }
165cdf0e10cSrcweir }
166cdf0e10cSrcweir }
167cdf0e10cSrcweir }
168cdf0e10cSrcweir
169cdf0e10cSrcweir
SeqRemoveNegEntries(Sequence<OUString> & rSeq,Reference<XDictionaryList> & rxDicList,sal_Int16 nLanguage)170cdf0e10cSrcweir void SeqRemoveNegEntries( Sequence< OUString > &rSeq,
171cdf0e10cSrcweir Reference< XDictionaryList > &rxDicList,
172cdf0e10cSrcweir sal_Int16 nLanguage )
173cdf0e10cSrcweir {
174cdf0e10cSrcweir static const OUString aEmpty;
175cdf0e10cSrcweir sal_Bool bSthRemoved = sal_False;
176cdf0e10cSrcweir sal_Int32 nLen = rSeq.getLength();
177cdf0e10cSrcweir OUString *pEntries = rSeq.getArray();
178cdf0e10cSrcweir for (sal_Int32 i = 0; i < nLen; ++i)
179cdf0e10cSrcweir {
180cdf0e10cSrcweir Reference< XDictionaryEntry > xNegEntry( SearchDicList( rxDicList,
181cdf0e10cSrcweir pEntries[i], nLanguage, sal_False, sal_True ) );
182cdf0e10cSrcweir if (xNegEntry.is())
183cdf0e10cSrcweir {
184cdf0e10cSrcweir pEntries[i] = aEmpty;
185cdf0e10cSrcweir bSthRemoved = sal_True;
186cdf0e10cSrcweir }
187cdf0e10cSrcweir }
188cdf0e10cSrcweir if (bSthRemoved)
189cdf0e10cSrcweir {
190cdf0e10cSrcweir Sequence< OUString > aNew;
191cdf0e10cSrcweir // merge sequence without duplicates and empty strings in new empty sequence
192cdf0e10cSrcweir aNew = MergeProposalSeqs( aNew, rSeq, sal_False );
193cdf0e10cSrcweir rSeq = aNew;
194cdf0e10cSrcweir }
195cdf0e10cSrcweir }
196cdf0e10cSrcweir
197cdf0e10cSrcweir
MergeProposalSeqs(Sequence<OUString> & rAlt1,Sequence<OUString> & rAlt2,sal_Bool bAllowDuplicates)198cdf0e10cSrcweir Sequence< OUString > MergeProposalSeqs(
199cdf0e10cSrcweir Sequence< OUString > &rAlt1,
200cdf0e10cSrcweir Sequence< OUString > &rAlt2,
201cdf0e10cSrcweir sal_Bool bAllowDuplicates )
202cdf0e10cSrcweir {
203cdf0e10cSrcweir Sequence< OUString > aMerged;
204cdf0e10cSrcweir
205cdf0e10cSrcweir if (0 == rAlt1.getLength() && bAllowDuplicates)
206cdf0e10cSrcweir aMerged = rAlt2;
207cdf0e10cSrcweir else if (0 == rAlt2.getLength() && bAllowDuplicates)
208cdf0e10cSrcweir aMerged = rAlt1;
209cdf0e10cSrcweir else
210cdf0e10cSrcweir {
211cdf0e10cSrcweir sal_Int32 nAltCount1 = rAlt1.getLength();
212cdf0e10cSrcweir const OUString *pAlt1 = rAlt1.getConstArray();
213cdf0e10cSrcweir sal_Int32 nAltCount2 = rAlt2.getLength();
214cdf0e10cSrcweir const OUString *pAlt2 = rAlt2.getConstArray();
215cdf0e10cSrcweir
216cdf0e10cSrcweir sal_Int32 nCountNew = Min( nAltCount1 + nAltCount2, (sal_Int32) MAX_PROPOSALS );
217cdf0e10cSrcweir aMerged.realloc( nCountNew );
218cdf0e10cSrcweir OUString *pMerged = aMerged.getArray();
219cdf0e10cSrcweir
220cdf0e10cSrcweir sal_Int32 nIndex = 0;
221cdf0e10cSrcweir sal_Int32 i = 0;
222cdf0e10cSrcweir for (int j = 0; j < 2; j++)
223cdf0e10cSrcweir {
224cdf0e10cSrcweir sal_Int32 nCount = j == 0 ? nAltCount1 : nAltCount2;
225cdf0e10cSrcweir const OUString *pAlt = j == 0 ? pAlt1 : pAlt2;
226cdf0e10cSrcweir for (i = 0; i < nCount && nIndex < MAX_PROPOSALS; i++)
227cdf0e10cSrcweir {
228cdf0e10cSrcweir if (pAlt[i].getLength() &&
229cdf0e10cSrcweir (bAllowDuplicates || !SeqHasEntry(aMerged, pAlt[i] )))
230cdf0e10cSrcweir pMerged[ nIndex++ ] = pAlt[ i ];
231cdf0e10cSrcweir }
232cdf0e10cSrcweir }
233cdf0e10cSrcweir //DBG_ASSERT(nIndex == nCountNew, "wrong number of proposals");
234cdf0e10cSrcweir aMerged.realloc( nIndex );
235cdf0e10cSrcweir }
236cdf0e10cSrcweir
237cdf0e10cSrcweir return aMerged;
238cdf0e10cSrcweir }
239cdf0e10cSrcweir
240cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
241cdf0e10cSrcweir
242cdf0e10cSrcweir
SpellAlternatives()243cdf0e10cSrcweir SpellAlternatives::SpellAlternatives()
244cdf0e10cSrcweir {
245cdf0e10cSrcweir nLanguage = LANGUAGE_NONE;
246cdf0e10cSrcweir nType = SpellFailure::IS_NEGATIVE_WORD;
247cdf0e10cSrcweir }
248cdf0e10cSrcweir
249cdf0e10cSrcweir
SpellAlternatives(const OUString & rWord,sal_Int16 nLang,sal_Int16 nFailureType,const OUString & rRplcWord)250cdf0e10cSrcweir SpellAlternatives::SpellAlternatives(
251cdf0e10cSrcweir const OUString &rWord, sal_Int16 nLang,
252cdf0e10cSrcweir sal_Int16 nFailureType, const OUString &rRplcWord ) :
253cdf0e10cSrcweir aAlt ( Sequence< OUString >(1) ),
254cdf0e10cSrcweir aWord (rWord),
255cdf0e10cSrcweir nType (nFailureType),
256cdf0e10cSrcweir nLanguage (nLang)
257cdf0e10cSrcweir {
258cdf0e10cSrcweir if (rRplcWord.getLength())
259cdf0e10cSrcweir aAlt.getArray()[ 0 ] = rRplcWord;
260cdf0e10cSrcweir else
261cdf0e10cSrcweir aAlt.realloc( 0 );
262cdf0e10cSrcweir }
263cdf0e10cSrcweir
264cdf0e10cSrcweir
SpellAlternatives(const OUString & rWord,sal_Int16 nLang,sal_Int16 nFailureType,const Sequence<OUString> & rAlternatives)265cdf0e10cSrcweir SpellAlternatives::SpellAlternatives(
266cdf0e10cSrcweir const OUString &rWord, sal_Int16 nLang, sal_Int16 nFailureType,
267cdf0e10cSrcweir const Sequence< OUString > &rAlternatives ) :
268cdf0e10cSrcweir aAlt (rAlternatives),
269cdf0e10cSrcweir aWord (rWord),
270cdf0e10cSrcweir nType (nFailureType),
271cdf0e10cSrcweir nLanguage (nLang)
272cdf0e10cSrcweir {
273cdf0e10cSrcweir }
274cdf0e10cSrcweir
275cdf0e10cSrcweir
~SpellAlternatives()276cdf0e10cSrcweir SpellAlternatives::~SpellAlternatives()
277cdf0e10cSrcweir {
278cdf0e10cSrcweir }
279cdf0e10cSrcweir
280cdf0e10cSrcweir
getWord()281cdf0e10cSrcweir OUString SAL_CALL SpellAlternatives::getWord()
282cdf0e10cSrcweir throw(RuntimeException)
283cdf0e10cSrcweir {
284cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
285cdf0e10cSrcweir return aWord;
286cdf0e10cSrcweir }
287cdf0e10cSrcweir
288cdf0e10cSrcweir
getLocale()289cdf0e10cSrcweir Locale SAL_CALL SpellAlternatives::getLocale()
290cdf0e10cSrcweir throw(RuntimeException)
291cdf0e10cSrcweir {
292cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
293cdf0e10cSrcweir return CreateLocale( nLanguage );
294cdf0e10cSrcweir }
295cdf0e10cSrcweir
296cdf0e10cSrcweir
getFailureType()297cdf0e10cSrcweir sal_Int16 SAL_CALL SpellAlternatives::getFailureType()
298cdf0e10cSrcweir throw(RuntimeException)
299cdf0e10cSrcweir {
300cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
301cdf0e10cSrcweir return nType;
302cdf0e10cSrcweir }
303cdf0e10cSrcweir
304cdf0e10cSrcweir
getAlternativesCount()305cdf0e10cSrcweir sal_Int16 SAL_CALL SpellAlternatives::getAlternativesCount()
306cdf0e10cSrcweir throw(RuntimeException)
307cdf0e10cSrcweir {
308cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
309cdf0e10cSrcweir return (sal_Int16) aAlt.getLength();
310cdf0e10cSrcweir }
311cdf0e10cSrcweir
312cdf0e10cSrcweir
getAlternatives()313cdf0e10cSrcweir Sequence< OUString > SAL_CALL SpellAlternatives::getAlternatives()
314cdf0e10cSrcweir throw(RuntimeException)
315cdf0e10cSrcweir {
316cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
317cdf0e10cSrcweir return aAlt;
318cdf0e10cSrcweir }
319cdf0e10cSrcweir
320cdf0e10cSrcweir
setAlternatives(const uno::Sequence<OUString> & rAlternatives)321cdf0e10cSrcweir void SAL_CALL SpellAlternatives::setAlternatives( const uno::Sequence< OUString >& rAlternatives )
322cdf0e10cSrcweir throw (uno::RuntimeException)
323cdf0e10cSrcweir {
324cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
325cdf0e10cSrcweir aAlt = rAlternatives;
326cdf0e10cSrcweir }
327cdf0e10cSrcweir
328cdf0e10cSrcweir
setFailureType(sal_Int16 nFailureType)329cdf0e10cSrcweir void SAL_CALL SpellAlternatives::setFailureType( sal_Int16 nFailureType )
330cdf0e10cSrcweir throw (uno::RuntimeException)
331cdf0e10cSrcweir {
332cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
333cdf0e10cSrcweir nType = nFailureType;
334cdf0e10cSrcweir }
335cdf0e10cSrcweir
336cdf0e10cSrcweir
SetWordLanguage(const OUString & rWord,sal_Int16 nLang)337cdf0e10cSrcweir void SpellAlternatives::SetWordLanguage(const OUString &rWord, sal_Int16 nLang)
338cdf0e10cSrcweir {
339cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
340cdf0e10cSrcweir aWord = rWord;
341cdf0e10cSrcweir nLanguage = nLang;
342cdf0e10cSrcweir }
343cdf0e10cSrcweir
344cdf0e10cSrcweir
SetFailureType(sal_Int16 nTypeP)345cdf0e10cSrcweir void SpellAlternatives::SetFailureType(sal_Int16 nTypeP)
346cdf0e10cSrcweir {
347cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
348cdf0e10cSrcweir nType = nTypeP;
349cdf0e10cSrcweir }
350cdf0e10cSrcweir
351cdf0e10cSrcweir
SetAlternatives(const Sequence<OUString> & rAlt)352cdf0e10cSrcweir void SpellAlternatives::SetAlternatives( const Sequence< OUString > &rAlt )
353cdf0e10cSrcweir {
354cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() );
355cdf0e10cSrcweir aAlt = rAlt;
356cdf0e10cSrcweir }
357cdf0e10cSrcweir
358cdf0e10cSrcweir
359cdf0e10cSrcweir ///////////////////////////////////////////////////////////////////////////
360cdf0e10cSrcweir
361cdf0e10cSrcweir } // namespace linguistic
362cdf0e10cSrcweir
363