Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <com/sun/star/uno/Reference.h>
31 : : #include <cppuhelper/factory.hxx> // helper for factories
32 : : #include <com/sun/star/registry/XRegistryKey.hpp>
33 : : #include <com/sun/star/beans/XPropertySet.hpp>
34 : : #include <i18npool/mslangid.hxx>
35 : : #include <tools/debug.hxx>
36 : : #include <comphelper/processfactory.hxx>
37 : : #include <osl/mutex.hxx>
38 : : #include <unotools/pathoptions.hxx>
39 : : #include <unotools/lingucfg.hxx>
40 : :
41 : : #include <rtl/string.hxx>
42 : : #include <rtl/ustrbuf.hxx>
43 : : #include <rtl/textenc.h>
44 : :
45 : : #include "nthesimp.hxx"
46 : : #include <linguistic/misc.hxx>
47 : : #include <linguistic/lngprops.hxx>
48 : : #include "nthesdta.hxx"
49 : : #include <dictmgr.hxx>
50 : :
51 : : #include <list>
52 : : #include <set>
53 : : #include <string.h>
54 : :
55 : : // values asigned to capitalization types
56 : : #define CAPTYPE_UNKNOWN 0
57 : : #define CAPTYPE_NOCAP 1
58 : : #define CAPTYPE_INITCAP 2
59 : : #define CAPTYPE_ALLCAP 3
60 : : #define CAPTYPE_MIXED 4
61 : :
62 : : // XML-header to query SPELLML support
63 : : #define SPELLML_SUPPORT "<?xml?>"
64 : :
65 : : using namespace osl;
66 : : using namespace com::sun::star;
67 : : using namespace com::sun::star::beans;
68 : : using namespace com::sun::star::lang;
69 : : using namespace com::sun::star::uno;
70 : : using namespace com::sun::star::linguistic2;
71 : : using namespace linguistic;
72 : :
73 : : using ::rtl::OUString;
74 : : using ::rtl::OString;
75 : : using ::rtl::OUStringToOString;
76 : :
77 : : ///////////////////////////////////////////////////////////////////////////
78 : :
79 : 0 : static uno::Reference< XLinguServiceManager > GetLngSvcMgr_Impl()
80 : : {
81 : 0 : uno::Reference< XLinguServiceManager > xRes;
82 : : uno::Reference< XMultiServiceFactory > xMgr(
83 [ # # ]: 0 : comphelper::getProcessServiceFactory() );
84 [ # # ]: 0 : if (xMgr.is())
85 : : {
86 [ # # ]: 0 : xRes = uno::Reference< XLinguServiceManager > ( xMgr->createInstance(
87 : : OUString( RTL_CONSTASCII_USTRINGPARAM(
88 [ # # ][ # # ]: 0 : "com.sun.star.linguistic2.LinguServiceManager" ) ) ), UNO_QUERY ) ;
[ # # ][ # # ]
89 : : }
90 : 0 : return xRes;
91 : : }
92 : :
93 : 46 : Thesaurus::Thesaurus() :
94 [ + - ][ + - ]: 46 : aEvtListeners ( GetLinguMutex() )
[ + - ][ + - ]
95 : : {
96 : 46 : bDisposing = sal_False;
97 : 46 : pPropHelper = NULL;
98 : 46 : aThes = NULL;
99 : 46 : aCharSetInfo = NULL;
100 : 46 : aTEncs = NULL;
101 : 46 : aTLocs = NULL;
102 : 46 : aTNames = NULL;
103 : 46 : numthes = 0;
104 : 46 : }
105 : :
106 : :
107 [ + - ][ + - ]: 46 : Thesaurus::~Thesaurus()
[ + - ]
108 : : {
109 [ + - ]: 46 : if (aThes)
110 : : {
111 [ + + ]: 2116 : for (int i = 0; i < numthes; i++)
112 : : {
113 [ - + ][ # # ]: 2070 : if (aThes[i]) delete aThes[i];
[ # # ]
114 : 2070 : aThes[i] = NULL;
115 : : }
116 [ + - ]: 46 : delete[] aThes;
117 : : }
118 : 46 : aThes = NULL;
119 [ + - ]: 46 : if (aCharSetInfo)
120 : : {
121 [ + + ]: 2116 : for (int i = 0; i < numthes; i++)
122 : : {
123 [ + - ][ + - ]: 2070 : if (aCharSetInfo[i]) delete aCharSetInfo[i];
[ + - ]
124 : 2070 : aCharSetInfo[i] = NULL;
125 : : }
126 [ + - ]: 46 : delete[] aCharSetInfo;
127 : : }
128 : 46 : aCharSetInfo = NULL;
129 : 46 : numthes = 0;
130 [ + - ][ + - ]: 46 : if (aTEncs) delete[] aTEncs;
131 : 46 : aTEncs = NULL;
132 [ + - ][ + - ]: 2116 : if (aTLocs) delete[] aTLocs;
[ + + ]
133 : 46 : aTLocs = NULL;
134 [ + - ][ + - ]: 2116 : if (aTNames) delete[] aTNames;
[ + + ]
135 : 46 : aTNames = NULL;
136 : :
137 [ - + ]: 46 : if (pPropHelper)
138 : : {
139 [ # # ]: 0 : pPropHelper->RemoveAsPropListener();
140 [ # # ][ # # ]: 0 : delete pPropHelper;
141 : : }
142 [ - + ]: 92 : }
143 : :
144 : :
145 : 0 : PropertyHelper_Thesaurus& Thesaurus::GetPropHelper_Impl()
146 : : {
147 [ # # ]: 0 : if (!pPropHelper)
148 : : {
149 [ # # ][ # # ]: 0 : Reference< XPropertySet > xPropSet( GetLinguProperties(), UNO_QUERY );
150 : :
151 [ # # ][ # # ]: 0 : pPropHelper = new PropertyHelper_Thesaurus( (XThesaurus *) this, xPropSet );
[ # # ]
152 [ # # ]: 0 : pPropHelper->AddAsPropListener(); //! after a reference is established
153 : : }
154 : 0 : return *pPropHelper;
155 : : }
156 : :
157 : :
158 : 96 : Sequence< Locale > SAL_CALL Thesaurus::getLocales()
159 : : throw(RuntimeException)
160 : : {
161 [ + - ][ + - ]: 96 : MutexGuard aGuard( GetLinguMutex() );
162 : :
163 : : // this routine should return the locales supported by the installed
164 : : // dictionaries.
165 : :
166 [ + + ]: 96 : if (!numthes)
167 : : {
168 [ + - ]: 46 : SvtLinguConfig aLinguCfg;
169 : :
170 : : // get list of dictionaries-to-use
171 [ + - ]: 46 : std::list< SvtLinguConfigDictionaryEntry > aDics;
172 [ + - ]: 46 : uno::Sequence< rtl::OUString > aFormatList;
173 : : aLinguCfg.GetSupportedDictionaryFormatsFor( A2OU("Thesauri"),
174 [ + - ][ + - ]: 46 : A2OU("org.openoffice.lingu.new.Thesaurus"), aFormatList );
[ + - ]
175 : 46 : sal_Int32 nLen = aFormatList.getLength();
176 [ + + ]: 92 : for (sal_Int32 i = 0; i < nLen; ++i)
177 : : {
178 : : std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
179 [ + - ][ + - ]: 46 : aLinguCfg.GetActiveDictionariesByFormat( aFormatList[i] ) );
180 [ + - ]: 46 : aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
181 : 46 : }
182 : :
183 : : //!! for compatibility with old dictionaries (the ones not using extensions
184 : : //!! or new configuration entries, but still using the dictionary.lst file)
185 : : //!! Get the list of old style spell checking dictionaries to use...
186 : : std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
187 [ + - ]: 46 : GetOldStyleDics( "THES" ) );
188 : :
189 : : // to prefer dictionaries with configuration entries we will only
190 : : // use those old style dictionaries that add a language that
191 : : // is not yet supported by the list od new style dictionaries
192 [ + - ]: 46 : MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics );
193 : :
194 : 46 : numthes = aDics.size();
195 [ + - ]: 46 : if (numthes)
196 : : {
197 : : // get supported locales from the dictionaries-to-use...
198 : 46 : sal_Int32 k = 0;
199 [ + - ]: 46 : std::set< rtl::OUString, lt_rtl_OUString > aLocaleNamesSet;
200 [ + - ]: 46 : std::list< SvtLinguConfigDictionaryEntry >::const_iterator aDictIt;
201 [ + - ][ + - ]: 276 : for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
[ + - ][ + - ]
[ + + ]
202 : : {
203 [ + - ][ + - ]: 230 : uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
204 : 230 : sal_Int32 nLen2 = aLocaleNames.getLength();
205 [ + + ]: 2300 : for (k = 0; k < nLen2; ++k)
206 : : {
207 [ + - ][ + - ]: 2070 : aLocaleNamesSet.insert( aLocaleNames[k] );
208 : : }
209 [ + - ]: 230 : }
210 : : // ... and add them to the resulting sequence
211 [ + - ]: 46 : aSuppLocales.realloc( aLocaleNamesSet.size() );
212 : 46 : std::set< rtl::OUString, lt_rtl_OUString >::const_iterator aItB;
213 : 46 : k = 0;
214 [ + + ]: 2116 : for (aItB = aLocaleNamesSet.begin(); aItB != aLocaleNamesSet.end(); ++aItB)
215 : : {
216 : : Locale aTmp( MsLangId::convertLanguageToLocale(
217 [ + - ][ + - ]: 2070 : MsLangId::convertIsoStringToLanguage( *aItB )));
218 [ + - ]: 2070 : aSuppLocales[k++] = aTmp;
219 : 2070 : }
220 : :
221 : : //! For each dictionary and each locale we need a seperate entry.
222 : : //! If this results in more than one dictionary per locale than (for now)
223 : : //! it is undefined which dictionary gets used.
224 : : //! In the future the implementation should support using several dictionaries
225 : : //! for one locale.
226 : 46 : numthes = 0;
227 [ + - ][ + - ]: 276 : for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
[ + - ][ + - ]
[ + + ]
228 [ + - ]: 230 : numthes = numthes + aDictIt->aLocaleNames.getLength();
229 : :
230 : : // add dictionary information
231 [ + - ]: 46 : aThes = new MyThes* [numthes];
232 [ + - ]: 46 : aTEncs = new rtl_TextEncoding [numthes];
233 [ + - ][ + + ]: 2116 : aTLocs = new Locale [numthes];
234 [ + - ][ + + ]: 2116 : aTNames = new OUString [numthes];
235 [ + - ]: 46 : aCharSetInfo = new CharClass* [numthes];
236 : :
237 : 46 : k = 0;
238 [ + - ][ + - ]: 276 : for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
[ + - ][ + - ]
[ + + ]
239 : : {
240 [ + - ]: 460 : if (aDictIt->aLocaleNames.getLength() > 0 &&
[ + - + - ]
[ + - ]
241 [ + - ]: 230 : aDictIt->aLocations.getLength() > 0)
242 : : {
243 [ + - ][ + - ]: 230 : uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
244 : 230 : sal_Int32 nLocales = aLocaleNames.getLength();
245 : :
246 : : // currently only one language per dictionary is supported in the actual implementation...
247 : : // Thus here we work-around this by adding the same dictionary several times.
248 : : // Once for each of it's supported locales.
249 [ + + ]: 2300 : for (sal_Int32 i = 0; i < nLocales; ++i)
250 : : {
251 : 2070 : aThes[k] = NULL;
252 : 2070 : aTEncs[k] = RTL_TEXTENCODING_DONTKNOW;
253 : : aTLocs[k] = MsLangId::convertLanguageToLocale(
254 [ + - ][ + - ]: 2070 : MsLangId::convertIsoStringToLanguage( aDictIt->aLocaleNames[i] ));
[ + - ]
255 [ + - ][ + - ]: 2070 : aCharSetInfo[k] = new CharClass( aTLocs[k] );
256 : : // also both files have to be in the same directory and the
257 : : // file names must only differ in the extension (.aff/.dic).
258 : : // Thus we use the first location only and strip the extension part.
259 [ + - ]: 2070 : rtl::OUString aLocation = aDictIt->aLocations[0];
260 : 2070 : sal_Int32 nPos = aLocation.lastIndexOf( '.' );
261 : 2070 : aLocation = aLocation.copy( 0, nPos );
262 : 2070 : aTNames[k] = aLocation;
263 : :
264 : 2070 : ++k;
265 [ + - ]: 2300 : }
266 : : }
267 : : }
268 : 46 : DBG_ASSERT( k == numthes, "index mismatch?" );
269 : : }
270 : : else
271 : : {
272 : : /* no dictionary found so register no dictionaries */
273 : 0 : numthes = 0;
274 : 0 : aThes = NULL;
275 : 0 : aTEncs = NULL;
276 : 0 : aTLocs = NULL;
277 : 0 : aTNames = NULL;
278 : 0 : aCharSetInfo = NULL;
279 [ # # ]: 0 : aSuppLocales.realloc(0);
280 [ + - ][ + - ]: 46 : }
281 : : }
282 : :
283 [ + - ][ + - ]: 96 : return aSuppLocales;
284 : : }
285 : :
286 : :
287 : :
288 : 0 : sal_Bool SAL_CALL Thesaurus::hasLocale(const Locale& rLocale)
289 : : throw(RuntimeException)
290 : : {
291 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
292 : :
293 : 0 : sal_Bool bRes = sal_False;
294 [ # # ]: 0 : if (!aSuppLocales.getLength())
295 [ # # ][ # # ]: 0 : getLocales();
296 : 0 : sal_Int32 nLen = aSuppLocales.getLength();
297 [ # # ]: 0 : for (sal_Int32 i = 0; i < nLen; ++i)
298 : : {
299 : 0 : const Locale *pLocale = aSuppLocales.getConstArray();
300 [ # # ]: 0 : if (rLocale == pLocale[i])
301 : : {
302 : 0 : bRes = sal_True;
303 : 0 : break;
304 : : }
305 : : }
306 [ # # ]: 0 : return bRes;
307 : : }
308 : :
309 : :
310 : 0 : Sequence < Reference < ::com::sun::star::linguistic2::XMeaning > > SAL_CALL Thesaurus::queryMeanings(
311 : : const OUString& qTerm, const Locale& rLocale,
312 : : const PropertyValues& rProperties)
313 : : throw(IllegalArgumentException, RuntimeException)
314 : : {
315 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
316 : :
317 [ # # ]: 0 : uno::Sequence< Reference< XMeaning > > aMeanings( 1 );
318 [ # # ]: 0 : uno::Sequence< Reference< XMeaning > > noMeanings( 0 );
319 [ # # ]: 0 : uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
320 : 0 : uno::Reference< XSpellChecker1 > xSpell;
321 : :
322 : 0 : OUString rTerm(qTerm);
323 : 0 : OUString pTerm(qTerm);
324 : 0 : sal_uInt16 ct = CAPTYPE_UNKNOWN;
325 : 0 : sal_Int32 stem = 0;
326 : 0 : sal_Int32 stem2 = 0;
327 : :
328 [ # # ]: 0 : sal_Int16 nLanguage = LocaleToLanguage( rLocale );
329 : :
330 [ # # ][ # # ]: 0 : if (nLanguage == LANGUAGE_NONE || rTerm.isEmpty())
[ # # ]
331 [ # # ]: 0 : return noMeanings;
332 : :
333 [ # # ][ # # ]: 0 : if (!hasLocale( rLocale ))
334 : : #ifdef LINGU_EXCEPTIONS
335 : : throw( IllegalArgumentException() );
336 : : #else
337 [ # # ]: 0 : return noMeanings;
338 : : #endif
339 : :
340 [ # # ][ # # ]: 0 : if (prevTerm == qTerm && prevLocale == nLanguage)
[ # # ]
341 [ # # ]: 0 : return prevMeanings;
342 : :
343 : 0 : mentry * pmean = NULL;
344 : 0 : sal_Int32 nmean = 0;
345 : :
346 [ # # ]: 0 : PropertyHelper_Thesaurus &rHelper = GetPropHelper();
347 [ # # ]: 0 : rHelper.SetTmpPropVals( rProperties );
348 : :
349 : 0 : MyThes * pTH = NULL;
350 : 0 : rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
351 : 0 : CharClass * pCC = NULL;
352 : :
353 : : // find the first thesaurus that matches the locale
354 [ # # ]: 0 : for (int i =0; i < numthes; i++)
355 : : {
356 [ # # ]: 0 : if (rLocale == aTLocs[i])
357 : : {
358 : : // open up and intialize this thesaurus if need be
359 [ # # ]: 0 : if (!aThes[i])
360 : : {
361 [ # # ]: 0 : OUString datpath = aTNames[i] + A2OU(".dat");
362 [ # # ]: 0 : OUString idxpath = aTNames[i] + A2OU(".idx");
363 : 0 : OUString ndat;
364 : 0 : OUString nidx;
365 [ # # ]: 0 : osl::FileBase::getSystemPathFromFileURL(datpath,ndat);
366 [ # # ]: 0 : osl::FileBase::getSystemPathFromFileURL(idxpath,nidx);
367 [ # # ][ # # ]: 0 : OString aTmpidx(OU2ENC(nidx,osl_getThreadTextEncoding()));
368 [ # # ][ # # ]: 0 : OString aTmpdat(OU2ENC(ndat,osl_getThreadTextEncoding()));
369 : :
370 : : #if defined(WNT)
371 : : // workaround for Windows specifc problem that the
372 : : // path length in calls to 'fopen' is limted to somewhat
373 : : // about 120+ characters which will usually be exceed when
374 : : // using dictionaries as extensions.
375 : : aTmpidx = Win_GetShortPathName( nidx );
376 : : aTmpdat = Win_GetShortPathName( ndat );
377 : : #endif
378 : :
379 [ # # ][ # # ]: 0 : aThes[i] = new MyThes(aTmpidx.getStr(),aTmpdat.getStr());
380 [ # # ]: 0 : if (aThes[i])
381 [ # # ][ # # ]: 0 : aTEncs[i] = getTextEncodingFromCharset(aThes[i]->get_th_encoding());
382 : : }
383 : 0 : pTH = aThes[i];
384 : 0 : eEnc = aTEncs[i];
385 : 0 : pCC = aCharSetInfo[i];
386 : :
387 [ # # ]: 0 : if (pTH)
388 : 0 : break;
389 : : }
390 : : }
391 : :
392 : : // we don't want to work with a default text encoding since following incorrect
393 : : // results may occur only for specific text and thus may be hard to notice.
394 : : // Thus better always make a clean exit here if the text encoding is in question.
395 : : // Hopefully something not working at all will raise proper attention quickly. ;-)
396 : : DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
397 [ # # ]: 0 : if (eEnc == RTL_TEXTENCODING_DONTKNOW)
398 [ # # ]: 0 : return noMeanings;
399 : :
400 [ # # ]: 0 : while (pTH)
401 : : {
402 : : // convert word to all lower case for searching
403 [ # # ]: 0 : if (!stem)
404 [ # # ]: 0 : ct = capitalType(rTerm, pCC);
405 [ # # ]: 0 : OUString nTerm(makeLowerCase(rTerm, pCC));
406 [ # # ]: 0 : OString aTmp( OU2ENC(nTerm, eEnc) );
407 [ # # ]: 0 : nmean = pTH->Lookup(aTmp.getStr(),aTmp.getLength(),&pmean);
408 : :
409 [ # # ]: 0 : if (nmean)
410 [ # # ]: 0 : aMeanings.realloc( nmean );
411 : :
412 : 0 : mentry * pe = pmean;
413 : 0 : OUString codeTerm = qTerm;
414 : 0 : Reference< XSpellAlternatives > xTmpRes2;
415 : :
416 [ # # ]: 0 : if (stem)
417 : : {
418 [ # # ]: 0 : xTmpRes2 = xSpell->spell( A2OU("<?xml?><query type='analyze'><word>") +
419 [ # # ][ # # ]: 0 : pTerm + A2OU("</word></query>"), nLanguage, rProperties );
[ # # ][ # # ]
420 [ # # ]: 0 : if (xTmpRes2.is())
421 : : {
422 [ # # ][ # # ]: 0 : Sequence<OUString>seq = xTmpRes2->getAlternatives();
423 [ # # ]: 0 : if (seq.getLength() > 0)
424 : : {
425 [ # # ]: 0 : codeTerm = seq[0];
426 : 0 : stem2 = 1;
427 [ # # ]: 0 : }
428 : : #if 0
429 : : OString o = OUStringToOString(codeTerm, RTL_TEXTENCODING_UTF8);
430 : : fprintf(stderr, "CODETERM: %s\n", o.pData->buffer);
431 : : #endif
432 : : }
433 : : }
434 : :
435 [ # # ]: 0 : for (int j = 0; j < nmean; j++)
436 : : {
437 : 0 : int count = pe->count;
438 [ # # ]: 0 : if (count)
439 : : {
440 [ # # ]: 0 : Sequence< OUString > aStr( count );
441 [ # # ]: 0 : OUString *pStr = aStr.getArray();
442 : :
443 [ # # ]: 0 : for (int i=0; i < count; i++)
444 : : {
445 [ # # ]: 0 : OUString sTerm(pe->psyns[i],strlen(pe->psyns[i]),eEnc );
446 : 0 : sal_Int32 catpos = sTerm.indexOf('(');
447 : 0 : sal_Int32 catpos2 = 0;
448 : 0 : OUString catst;
449 : 0 : OUString catst2;
450 [ # # ]: 0 : if (catpos > 2)
451 : : {
452 : : // remove category name for affixation and casing
453 [ # # ]: 0 : catst = A2OU(" ") + sTerm.copy(catpos);
454 : 0 : sTerm = sTerm.copy(0, catpos);
455 : 0 : sTerm = sTerm.trim();
456 : : }
457 : : // generate synonyms with affixes
458 [ # # ][ # # ]: 0 : if (stem && stem2)
459 : : {
460 : 0 : Reference< XSpellAlternatives > xTmpRes;
461 [ # # ]: 0 : xTmpRes = xSpell->spell( A2OU("<?xml?><query type='generate'><word>") +
462 [ # # ][ # # ]: 0 : sTerm + A2OU("</word>") + codeTerm + A2OU("</query>"), nLanguage, rProperties );
[ # # ][ # # ]
[ # # ]
463 [ # # ]: 0 : if (xTmpRes.is())
464 : : {
465 [ # # ][ # # ]: 0 : Sequence<OUString>seq = xTmpRes->getAlternatives();
466 [ # # ]: 0 : if (seq.getLength() > 0)
467 [ # # ][ # # ]: 0 : sTerm = seq[0];
468 : 0 : }
469 : : }
470 [ # # ]: 0 : if (catpos2)
471 : 0 : sTerm = catst2 + sTerm;
472 : :
473 [ # # ]: 0 : sal_uInt16 ct1 = capitalType(sTerm, pCC);
474 [ # # ]: 0 : if (CAPTYPE_MIXED == ct1)
475 : 0 : ct = ct1;
476 : 0 : OUString cTerm;
477 [ # # # ]: 0 : switch (ct)
478 : : {
479 : : case CAPTYPE_ALLCAP:
480 [ # # ]: 0 : cTerm = makeUpperCase(sTerm, pCC);
481 : 0 : break;
482 : : case CAPTYPE_INITCAP:
483 [ # # ]: 0 : cTerm = makeInitCap(sTerm, pCC);
484 : 0 : break;
485 : : default:
486 : 0 : cTerm = sTerm;
487 : 0 : break;
488 : : }
489 : 0 : OUString aAlt( cTerm + catst);
490 : 0 : pStr[i] = aAlt;
491 : 0 : }
492 : : #if 0
493 : : Meaning * pMn = new Meaning(rTerm,nLanguage,rHelper);
494 : : #endif
495 [ # # ]: 0 : Meaning * pMn = new Meaning(rTerm,nLanguage);
496 [ # # ]: 0 : OUString dTerm(pe->defn,strlen(pe->defn),eEnc );
497 [ # # ]: 0 : pMn->SetMeaning(dTerm);
498 [ # # ]: 0 : pMn->SetSynonyms(aStr);
499 [ # # ]: 0 : Reference<XMeaning>* pMeaning = aMeanings.getArray();
500 [ # # ][ # # ]: 0 : pMeaning[j] = pMn;
[ # # ]
501 : : }
502 : 0 : pe++;
503 : : }
504 [ # # ]: 0 : pTH->CleanUpAfterLookup(&pmean,nmean);
505 : :
506 [ # # ]: 0 : if (nmean)
507 : : {
508 : 0 : prevTerm = qTerm;
509 [ # # ]: 0 : prevMeanings = aMeanings;
510 : 0 : prevLocale = nLanguage;
511 [ # # ]: 0 : return aMeanings;
512 : : }
513 : :
514 [ # # ][ # # ]: 0 : if (stem || !xLngSvcMgr.is())
[ # # ]
515 [ # # ]: 0 : return noMeanings;
516 : 0 : stem = 1;
517 : :
518 [ # # ][ # # ]: 0 : xSpell = uno::Reference< XSpellChecker1 >( xLngSvcMgr->getSpellChecker(), UNO_QUERY );
[ # # ][ # # ]
519 [ # # ][ # # ]: 0 : if (!xSpell.is() || !xSpell->isValid( A2OU(SPELLML_SUPPORT), nLanguage, rProperties ))
[ # # ][ # # ]
[ # # ]
[ # # # # ]
[ # # ]
520 [ # # ]: 0 : return noMeanings;
521 : 0 : Reference< XSpellAlternatives > xTmpRes;
522 [ # # ]: 0 : xTmpRes = xSpell->spell( A2OU("<?xml?><query type='stem'><word>") +
523 [ # # ][ # # ]: 0 : rTerm + A2OU("</word></query>"), nLanguage, rProperties );
[ # # ][ # # ]
524 [ # # ]: 0 : if (xTmpRes.is())
525 : : {
526 [ # # ][ # # ]: 0 : Sequence<OUString>seq = xTmpRes->getAlternatives();
527 : : #if 0
528 : : for (int i = 0; i < seq.getLength(); i++)
529 : : {
530 : : OString o = OUStringToOString(seq[i], RTL_TEXTENCODING_UTF8);
531 : : fprintf(stderr, "%d: %s\n", i + 1, o.pData->buffer);
532 : : }
533 : : #endif
534 [ # # ]: 0 : if (seq.getLength() > 0)
535 : : {
536 [ # # ]: 0 : rTerm = seq[0]; // XXX Use only the first stem
537 : 0 : continue;
538 [ # # ][ # # ]: 0 : }
539 : : }
540 : :
541 : : // stem the last word of the synonym (for categories after affixation)
542 : 0 : rTerm = rTerm.trim();
543 : 0 : sal_Int32 pos = rTerm.lastIndexOf(' ');
544 [ # # ]: 0 : if (!pos)
545 [ # # ]: 0 : return noMeanings;
546 [ # # ]: 0 : xTmpRes = xSpell->spell( A2OU("<?xml?><query type='stem'><word>") +
547 [ # # ][ # # ]: 0 : rTerm.copy(pos + 1) + A2OU("</word></query>"), nLanguage, rProperties );
[ # # ][ # # ]
548 [ # # ]: 0 : if (xTmpRes.is())
549 : : {
550 [ # # ][ # # ]: 0 : Sequence<OUString>seq = xTmpRes->getAlternatives();
551 [ # # ]: 0 : if (seq.getLength() > 0)
552 : : {
553 : 0 : pTerm = rTerm.copy(pos + 1);
554 [ # # ]: 0 : rTerm = rTerm.copy(0, pos + 1) + seq[0];
555 : : #if 0
556 : : for (int i = 0; i < seq.getLength(); i++)
557 : : {
558 : : OString o = OUStringToOString(seq[i], RTL_TEXTENCODING_UTF8);
559 : : fprintf(stderr, "%d: %s\n", i + 1, o.pData->buffer);
560 : : }
561 : : #endif
562 : 0 : continue;
563 [ # # ][ # # ]: 0 : }
564 : : }
565 [ # # # ]: 0 : break;
566 [ # # # ]: 0 : }
[ # # # ]
[ # # # ]
[ # # # ]
567 [ # # ][ # # ]: 0 : return noMeanings;
[ # # ][ # # ]
568 : : }
569 : :
570 : :
571 : 46 : Reference< XInterface > SAL_CALL Thesaurus_CreateInstance(
572 : : const Reference< XMultiServiceFactory > & /*rSMgr*/ )
573 : : throw(Exception)
574 : : {
575 [ + - ][ + - ]: 46 : Reference< XInterface > xService = (cppu::OWeakObject*) new Thesaurus;
576 : 46 : return xService;
577 : : }
578 : :
579 : :
580 : 0 : OUString SAL_CALL Thesaurus::getServiceDisplayName( const Locale& /*rLocale*/ )
581 : : throw(RuntimeException)
582 : : {
583 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
584 [ # # ][ # # ]: 0 : return A2OU( "OpenOffice.org New Thesaurus" );
585 : : }
586 : :
587 : :
588 : 0 : void SAL_CALL Thesaurus::initialize( const Sequence< Any >& rArguments )
589 : : throw(Exception, RuntimeException)
590 : : {
591 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
592 : :
593 [ # # ]: 0 : if (!pPropHelper)
594 : : {
595 : 0 : sal_Int32 nLen = rArguments.getLength();
596 [ # # ]: 0 : if (1 == nLen)
597 : : {
598 : 0 : Reference< XPropertySet > xPropSet;
599 [ # # ]: 0 : rArguments.getConstArray()[0] >>= xPropSet;
600 : :
601 : : //! Pointer allows for access of the non-UNO functions.
602 : : //! And the reference to the UNO-functions while increasing
603 : : //! the ref-count and will implicitly free the memory
604 : : //! when the object is not longer used.
605 [ # # ][ # # ]: 0 : pPropHelper = new PropertyHelper_Thesaurus( (XThesaurus *) this, xPropSet );
[ # # ]
606 [ # # ]: 0 : pPropHelper->AddAsPropListener(); //! after a reference is established
607 : : }
608 : : else
609 : : OSL_FAIL( "wrong number of arguments in sequence" );
610 [ # # ]: 0 : }
611 : 0 : }
612 : :
613 : :
614 : :
615 : 0 : sal_uInt16 SAL_CALL Thesaurus::capitalType(const OUString& aTerm, CharClass * pCC)
616 : : {
617 : 0 : sal_Int32 tlen = aTerm.getLength();
618 [ # # ][ # # ]: 0 : if ((pCC) && (tlen))
619 : : {
620 [ # # ]: 0 : String aStr(aTerm);
621 : 0 : sal_Int32 nc = 0;
622 [ # # ]: 0 : for (sal_uInt16 tindex = 0; tindex < tlen; tindex++)
623 : : {
624 [ # # ][ # # ]: 0 : if (pCC->getCharacterType(aStr,tindex) &
625 : 0 : ::com::sun::star::i18n::KCharacterType::UPPER) nc++;
626 : : }
627 : :
628 [ # # ]: 0 : if (nc == 0)
629 : 0 : return (sal_uInt16) CAPTYPE_NOCAP;
630 [ # # ]: 0 : if (nc == tlen)
631 : 0 : return (sal_uInt16) CAPTYPE_ALLCAP;
632 [ # # ][ # # ]: 0 : if ((nc == 1) && (pCC->getCharacterType(aStr,0) &
[ # # ][ # # ]
633 : : ::com::sun::star::i18n::KCharacterType::UPPER))
634 : 0 : return (sal_uInt16) CAPTYPE_INITCAP;
635 : :
636 [ # # ]: 0 : return (sal_uInt16) CAPTYPE_MIXED;
637 : : }
638 : 0 : return (sal_uInt16) CAPTYPE_UNKNOWN;
639 : : }
640 : :
641 : :
642 : :
643 : 0 : OUString SAL_CALL Thesaurus::makeLowerCase(const OUString& aTerm, CharClass * pCC)
644 : : {
645 [ # # ]: 0 : if (pCC)
646 : 0 : return pCC->lowercase(aTerm);
647 : 0 : return aTerm;
648 : : }
649 : :
650 : :
651 : 0 : OUString SAL_CALL Thesaurus::makeUpperCase(const OUString& aTerm, CharClass * pCC)
652 : : {
653 [ # # ]: 0 : if (pCC)
654 : 0 : return pCC->uppercase(aTerm);
655 : 0 : return aTerm;
656 : : }
657 : :
658 : :
659 : 0 : OUString SAL_CALL Thesaurus::makeInitCap(const OUString& aTerm, CharClass * pCC)
660 : : {
661 : 0 : sal_Int32 tlen = aTerm.getLength();
662 [ # # ][ # # ]: 0 : if ((pCC) && (tlen))
663 : : {
664 : 0 : OUString bTemp = aTerm.copy(0,1);
665 [ # # ]: 0 : if (tlen > 1)
666 : : {
667 : : return ( pCC->uppercase(bTemp, 0, 1)
668 [ # # ][ # # ]: 0 : + pCC->lowercase(aTerm,1,(tlen-1)) );
669 : : }
670 : :
671 [ # # ]: 0 : return pCC->uppercase(bTemp, 0, 1);
672 : : }
673 : 0 : return aTerm;
674 : : }
675 : :
676 : :
677 : :
678 : 46 : void SAL_CALL Thesaurus::dispose()
679 : : throw(RuntimeException)
680 : : {
681 [ + - ][ + - ]: 46 : MutexGuard aGuard( GetLinguMutex() );
682 : :
683 [ + - ]: 46 : if (!bDisposing)
684 : : {
685 : 46 : bDisposing = sal_True;
686 [ + - ][ + - ]: 46 : EventObject aEvtObj( (XThesaurus *) this );
687 [ + - ]: 46 : aEvtListeners.disposeAndClear( aEvtObj );
688 [ - + ]: 46 : if (pPropHelper)
689 : : {
690 [ # # ]: 0 : pPropHelper->RemoveAsPropListener();
691 [ # # ][ # # ]: 0 : delete pPropHelper;
692 : 0 : pPropHelper = NULL;
693 [ + - ]: 46 : }
694 [ + - ]: 46 : }
695 : 46 : }
696 : :
697 : :
698 : 0 : void SAL_CALL Thesaurus::addEventListener( const Reference< XEventListener >& rxListener )
699 : : throw(RuntimeException)
700 : : {
701 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
702 : :
703 [ # # ][ # # ]: 0 : if (!bDisposing && rxListener.is())
[ # # ]
704 [ # # ][ # # ]: 0 : aEvtListeners.addInterface( rxListener );
705 : 0 : }
706 : :
707 : :
708 : 0 : void SAL_CALL Thesaurus::removeEventListener( const Reference< XEventListener >& rxListener )
709 : : throw(RuntimeException)
710 : : {
711 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
712 : :
713 [ # # ][ # # ]: 0 : if (!bDisposing && rxListener.is())
[ # # ]
714 [ # # ][ # # ]: 0 : aEvtListeners.removeInterface( rxListener );
715 : 0 : }
716 : :
717 : :
718 : : ///////////////////////////////////////////////////////////////////////////
719 : : // Service specific part
720 : : //
721 : :
722 : 48 : OUString SAL_CALL Thesaurus::getImplementationName()
723 : : throw(RuntimeException)
724 : : {
725 [ + - ][ + - ]: 48 : MutexGuard aGuard( GetLinguMutex() );
726 [ + - ]: 48 : return getImplementationName_Static();
727 : : }
728 : :
729 : :
730 : 0 : sal_Bool SAL_CALL Thesaurus::supportsService( const OUString& ServiceName )
731 : : throw(RuntimeException)
732 : : {
733 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
734 : :
735 [ # # ]: 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
736 : 0 : const OUString * pArray = aSNL.getConstArray();
737 [ # # ]: 0 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
738 [ # # ]: 0 : if( pArray[i] == ServiceName )
739 : 0 : return sal_True;
740 [ # # ][ # # ]: 0 : return sal_False;
741 : : }
742 : :
743 : :
744 : 0 : Sequence< OUString > SAL_CALL Thesaurus::getSupportedServiceNames()
745 : : throw(RuntimeException)
746 : : {
747 [ # # ][ # # ]: 0 : MutexGuard aGuard( GetLinguMutex() );
748 [ # # ]: 0 : return getSupportedServiceNames_Static();
749 : : }
750 : :
751 : :
752 : 46 : Sequence< OUString > Thesaurus::getSupportedServiceNames_Static()
753 : : throw()
754 : : {
755 [ + - ][ + - ]: 46 : MutexGuard aGuard( GetLinguMutex() );
756 : :
757 [ + - ]: 46 : Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich
758 [ + - ][ + - ]: 46 : aSNS.getArray()[0] = A2OU( SN_THESAURUS );
759 [ + - ]: 46 : return aSNS;
760 : : }
761 : :
762 : 46 : void * SAL_CALL Thesaurus_getFactory( const sal_Char * pImplName,
763 : : XMultiServiceFactory * pServiceManager, void * )
764 : : {
765 : 46 : void * pRet = 0;
766 [ + - ]: 46 : if ( !Thesaurus::getImplementationName_Static().compareToAscii( pImplName ) )
767 : : {
768 : :
769 : : Reference< XSingleServiceFactory > xFactory =
770 : : cppu::createOneInstanceFactory(
771 : : pServiceManager,
772 : : Thesaurus::getImplementationName_Static(),
773 : : Thesaurus_CreateInstance,
774 [ + - ][ + - ]: 46 : Thesaurus::getSupportedServiceNames_Static());
[ + - ]
775 : : // acquire, because we return an interface pointer instead of a reference
776 [ + - ]: 46 : xFactory->acquire();
777 [ + - ]: 46 : pRet = xFactory.get();
778 : : }
779 : 46 : return pRet;
780 : : }
781 : :
782 : :
783 : : ///////////////////////////////////////////////////////////////////////////
784 : :
785 : :
786 : : #undef CAPTYPE_UNKNOWN
787 : : #undef CAPTYPE_NOCAP
788 : : #undef CAPTYPE_INITCAP
789 : : #undef CAPTYPE_ALLCAP
790 : : #undef CAPTYPE_MIXED
791 : :
792 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|