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