merged tag ooo/DEV300_m83
[LibreOffice.git] / lingucomponent / source / thesaurus / libnth / nthesimp.cxx
blobbd6afffdbd6aa90aceb8768a4e82c3da05b754e4
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_lingucomponent.hxx"
31 // include <stdio.h>
32 #include <com/sun/star/uno/Reference.h>
34 #include <cppuhelper/factory.hxx> // helper for factories
35 #include <com/sun/star/registry/XRegistryKey.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <i18npool/mslangid.hxx>
38 #include <tools/debug.hxx>
39 #include <unotools/processfactory.hxx>
40 #include <osl/mutex.hxx>
41 #include <unotools/pathoptions.hxx>
42 #include <unotools/lingucfg.hxx>
44 #include <rtl/string.hxx>
45 #include <rtl/ustrbuf.hxx>
46 #include "nthesimp.hxx"
47 #include <linguistic/misc.hxx>
48 #include <linguistic/lngprops.hxx>
49 #include "nthesdta.hxx"
50 #include <dictmgr.hxx>
52 #include <list>
53 #include <set>
54 #include <string.h>
56 // values asigned to capitalization types
57 #define CAPTYPE_UNKNOWN 0
58 #define CAPTYPE_NOCAP 1
59 #define CAPTYPE_INITCAP 2
60 #define CAPTYPE_ALLCAP 3
61 #define CAPTYPE_MIXED 4
63 // XML-header to query SPELLML support
64 #define SPELLML_SUPPORT "<?xml?>"
66 using namespace utl;
67 using namespace osl;
68 using namespace rtl;
69 using namespace com::sun::star;
70 using namespace com::sun::star::beans;
71 using namespace com::sun::star::lang;
72 using namespace com::sun::star::uno;
73 using namespace com::sun::star::linguistic2;
74 using namespace linguistic;
78 ///////////////////////////////////////////////////////////////////////////
80 static uno::Reference< XLinguServiceManager > GetLngSvcMgr_Impl()
82 uno::Reference< XLinguServiceManager > xRes;
83 uno::Reference< XMultiServiceFactory > xMgr = getProcessServiceFactory();
84 if (xMgr.is())
86 xRes = uno::Reference< XLinguServiceManager > ( xMgr->createInstance(
87 OUString( RTL_CONSTASCII_USTRINGPARAM(
88 "com.sun.star.linguistic2.LinguServiceManager" ) ) ), UNO_QUERY ) ;
90 return xRes;
93 Thesaurus::Thesaurus() :
94 aEvtListeners ( GetLinguMutex() )
96 bDisposing = FALSE;
97 pPropHelper = NULL;
98 aThes = NULL;
99 aCharSetInfo = NULL;
100 aTEncs = NULL;
101 aTLocs = NULL;
102 aTNames = NULL;
103 numthes = 0;
107 Thesaurus::~Thesaurus()
110 if (aThes) {
111 for (int i = 0; i < numthes; i++) {
112 if (aThes[i]) delete aThes[i];
113 aThes[i] = NULL;
115 delete[] aThes;
117 aThes = NULL;
118 if (aCharSetInfo) {
119 for (int i = 0; i < numthes; i++) {
120 if (aCharSetInfo[i]) delete aCharSetInfo[i];
121 aCharSetInfo[i] = NULL;
123 delete[] aCharSetInfo;
125 aCharSetInfo = NULL;
126 numthes = 0;
127 if (aTEncs) delete[] aTEncs;
128 aTEncs = NULL;
129 if (aTLocs) delete[] aTLocs;
130 aTLocs = NULL;
131 if (aTNames) delete[] aTNames;
132 aTNames = NULL;
134 if (pPropHelper)
135 pPropHelper->RemoveAsPropListener();
139 PropertyHelper_Thes & Thesaurus::GetPropHelper_Impl()
141 if (!pPropHelper)
143 Reference< XPropertySet > xPropSet( GetLinguProperties(), UNO_QUERY );
145 pPropHelper = new PropertyHelper_Thes( (XThesaurus *) this, xPropSet );
146 xPropHelper = pPropHelper;
147 pPropHelper->AddAsPropListener(); //! after a reference is established
149 return *pPropHelper;
153 Sequence< Locale > SAL_CALL Thesaurus::getLocales()
154 throw(RuntimeException)
156 MutexGuard aGuard( GetLinguMutex() );
158 // this routine should return the locales supported by the installed
159 // dictionaries.
161 if (!numthes)
163 SvtLinguConfig aLinguCfg;
165 // get list of dictionaries-to-use
166 std::list< SvtLinguConfigDictionaryEntry > aDics;
167 uno::Sequence< rtl::OUString > aFormatList;
168 aLinguCfg.GetSupportedDictionaryFormatsFor( A2OU("Thesauri"),
169 A2OU("org.openoffice.lingu.new.Thesaurus"), aFormatList );
170 sal_Int32 nLen = aFormatList.getLength();
171 for (sal_Int32 i = 0; i < nLen; ++i)
173 std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
174 aLinguCfg.GetActiveDictionariesByFormat( aFormatList[i] ) );
175 aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
178 //!! for compatibility with old dictionaries (the ones not using extensions
179 //!! or new configuration entries, but still using the dictionary.lst file)
180 //!! Get the list of old style spell checking dictionaries to use...
181 std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
182 GetOldStyleDics( "THES" ) );
184 // to prefer dictionaries with configuration entries we will only
185 // use those old style dictionaries that add a language that
186 // is not yet supported by the list od new style dictionaries
187 MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics );
189 numthes = aDics.size();
190 if (numthes)
192 // get supported locales from the dictionaries-to-use...
193 sal_Int32 k = 0;
194 std::set< rtl::OUString, lt_rtl_OUString > aLocaleNamesSet;
195 std::list< SvtLinguConfigDictionaryEntry >::const_iterator aDictIt;
196 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
198 uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
199 sal_Int32 nLen2 = aLocaleNames.getLength();
200 for (k = 0; k < nLen2; ++k)
202 aLocaleNamesSet.insert( aLocaleNames[k] );
205 // ... and add them to the resulting sequence
206 aSuppLocales.realloc( aLocaleNamesSet.size() );
207 std::set< rtl::OUString, lt_rtl_OUString >::const_iterator aItB;
208 k = 0;
209 for (aItB = aLocaleNamesSet.begin(); aItB != aLocaleNamesSet.end(); ++aItB)
211 Locale aTmp( MsLangId::convertLanguageToLocale(
212 MsLangId::convertIsoStringToLanguage( *aItB )));
213 aSuppLocales[k++] = aTmp;
216 //! For each dictionary and each locale we need a seperate entry.
217 //! If this results in more than one dictionary per locale than (for now)
218 //! it is undefined which dictionary gets used.
219 //! In the future the implementation should support using several dictionaries
220 //! for one locale.
221 numthes = 0;
222 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
223 numthes = numthes + aDictIt->aLocaleNames.getLength();
225 // add dictionary information
226 aThes = new MyThes* [numthes];
227 aTEncs = new rtl_TextEncoding [numthes];
228 aTLocs = new Locale [numthes];
229 aTNames = new OUString [numthes];
230 aCharSetInfo = new CharClass* [numthes];
232 k = 0;
233 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
235 if (aDictIt->aLocaleNames.getLength() > 0 &&
236 aDictIt->aLocations.getLength() > 0)
238 uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
239 sal_Int32 nLocales = aLocaleNames.getLength();
241 // currently only one language per dictionary is supported in the actual implementation...
242 // Thus here we work-around this by adding the same dictionary several times.
243 // Once for each of it's supported locales.
244 for (sal_Int32 i = 0; i < nLocales; ++i)
246 aThes[k] = NULL;
247 aTEncs[k] = 0;
248 aTLocs[k] = MsLangId::convertLanguageToLocale(
249 MsLangId::convertIsoStringToLanguage( aDictIt->aLocaleNames[i] ));
250 aCharSetInfo[k] = new CharClass( aTLocs[k] );
251 // also both files have to be in the same directory and the
252 // file names must only differ in the extension (.aff/.dic).
253 // Thus we use the first location only and strip the extension part.
254 rtl::OUString aLocation = aDictIt->aLocations[0];
255 sal_Int32 nPos = aLocation.lastIndexOf( '.' );
256 aLocation = aLocation.copy( 0, nPos );
257 aTNames[k] = aLocation;
259 ++k;
263 DBG_ASSERT( k == numthes, "index mismatch?" );
265 else
267 /* no dictionary found so register no dictionaries */
268 numthes = 0;
269 aThes = NULL;
270 aTEncs = NULL;
271 aTLocs = NULL;
272 aTNames = NULL;
273 aCharSetInfo = NULL;
274 aSuppLocales.realloc(0);
278 return aSuppLocales;
283 sal_Bool SAL_CALL Thesaurus::hasLocale(const Locale& rLocale)
284 throw(RuntimeException)
286 MutexGuard aGuard( GetLinguMutex() );
288 BOOL bRes = FALSE;
289 if (!aSuppLocales.getLength())
290 getLocales();
291 INT32 nLen = aSuppLocales.getLength();
292 for (INT32 i = 0; i < nLen; ++i)
294 const Locale *pLocale = aSuppLocales.getConstArray();
295 if (rLocale == pLocale[i])
297 bRes = TRUE;
298 break;
301 return bRes;
305 Sequence < Reference < ::com::sun::star::linguistic2::XMeaning > > SAL_CALL
306 Thesaurus::queryMeanings( const OUString& qTerm, const Locale& rLocale,
307 const PropertyValues& rProperties)
308 throw(IllegalArgumentException, RuntimeException)
310 MutexGuard aGuard( GetLinguMutex() );
312 uno::Sequence< Reference< XMeaning > > aMeanings( 1 );
313 uno::Sequence< Reference< XMeaning > > noMeanings( 0 );
314 uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
315 uno::Reference< XSpellChecker1 > xSpell;
317 OUString rTerm(qTerm);
318 OUString pTerm(qTerm);
319 sal_uInt16 ct = CAPTYPE_UNKNOWN;
320 sal_Int32 stem = 0;
321 sal_Int32 stem2 = 0;
323 INT16 nLanguage = LocaleToLanguage( rLocale );
325 if (nLanguage == LANGUAGE_NONE || !rTerm.getLength())
326 return noMeanings;
328 if (!hasLocale( rLocale ))
329 #ifdef LINGU_EXCEPTIONS
330 throw( IllegalArgumentException() );
331 #else
332 return noMeanings;
333 #endif
335 if (prevTerm == qTerm && prevLocale == nLanguage) return prevMeanings;
337 mentry * pmean = NULL;
338 sal_Int32 nmean = 0;
340 PropertyHelper_Thes &rHelper = GetPropHelper();
341 rHelper.SetTmpPropVals( rProperties );
343 MyThes * pTH = NULL;
344 rtl_TextEncoding aEnc = 0;
345 CharClass * pCC = NULL;
347 // find the first thesaurus that matches the locale
348 for (int i =0; i < numthes; i++) {
349 if (rLocale == aTLocs[i])
351 // open up and intialize this thesaurus if need be
352 if (!aThes[i])
354 OUString datpath = aTNames[i] + A2OU(".dat");
355 OUString idxpath = aTNames[i] + A2OU(".idx");
356 OUString ndat;
357 OUString nidx;
358 osl::FileBase::getSystemPathFromFileURL(datpath,ndat);
359 osl::FileBase::getSystemPathFromFileURL(idxpath,nidx);
360 OString aTmpidx(OU2ENC(nidx,osl_getThreadTextEncoding()));
361 OString aTmpdat(OU2ENC(ndat,osl_getThreadTextEncoding()));
363 #if defined(WNT)
364 // workaround for Windows specifc problem that the
365 // path length in calls to 'fopen' is limted to somewhat
366 // about 120+ characters which will usually be exceed when
367 // using dictionaries as extensions.
368 aTmpidx = Win_GetShortPathName( nidx );
369 aTmpdat = Win_GetShortPathName( ndat );
370 #endif
372 aThes[i] = new MyThes(aTmpidx.getStr(),aTmpdat.getStr());
373 if (aThes[i]) {
374 const char * enc_string = aThes[i]->get_th_encoding();
375 if (!enc_string) {
376 aTEncs[i] = rtl_getTextEncodingFromUnixCharset("ISO8859-1");
377 } else {
378 aTEncs[i] = rtl_getTextEncodingFromUnixCharset(enc_string);
379 if (aTEncs[i] == RTL_TEXTENCODING_DONTKNOW) {
380 if (strcmp("ISCII-DEVANAGARI", enc_string) == 0) {
381 aTEncs[i] = RTL_TEXTENCODING_ISCII_DEVANAGARI;
382 } else if (strcmp("UTF-8", enc_string) == 0) {
383 aTEncs[i] = RTL_TEXTENCODING_UTF8;
389 pTH = aThes[i];
390 aEnc = aTEncs[i];
391 pCC = aCharSetInfo[i];
393 if (pTH)
394 break;
398 while (pTH) {
399 // convert word to all lower case for searching
400 if (!stem) ct = capitalType(rTerm, pCC);
401 OUString nTerm(makeLowerCase(rTerm, pCC));
402 OString aTmp( OU2ENC(nTerm, aEnc) );
403 nmean = pTH->Lookup(aTmp.getStr(),aTmp.getLength(),&pmean);
405 if (nmean) aMeanings.realloc( nmean );
407 mentry * pe = pmean;
408 OUString codeTerm = qTerm;
409 Reference< XSpellAlternatives > xTmpRes2;
411 if (stem) {
412 xTmpRes2 = xSpell->spell( A2OU("<?xml?><query type='analyze'><word>") +
413 pTerm + A2OU("</word></query>"), nLanguage, rProperties );
414 if (xTmpRes2.is()) {
415 Sequence<OUString>seq = xTmpRes2->getAlternatives();
416 if (seq.getLength() > 0) {
417 codeTerm = seq[0];
418 stem2 = 1;
420 #if 0
421 OString o = OUStringToOString(codeTerm, rtl_getTextEncodingFromUnixCharset("UTF-8"));
422 fprintf(stderr, "CODETERM: %s\n", o.pData->buffer);
423 #endif
427 for (int j = 0; j < nmean; j++) {
428 int count = pe->count;
429 if (count) {
430 Sequence< OUString > aStr( count );
431 OUString *pStr = aStr.getArray();
433 for (int i=0; i < count; i++) {
434 OUString sTerm(pe->psyns[i],strlen(pe->psyns[i]),aEnc );
435 sal_Int32 catpos = sTerm.indexOf('(');
436 sal_Int32 catpos2 = 0;
437 OUString catst;
438 OUString catst2;
439 if (catpos > 2) {
440 // remove category name for affixation and casing
441 catst = A2OU(" ") + sTerm.copy(catpos);
442 sTerm = sTerm.copy(0, catpos);
443 sTerm = sTerm.trim();
445 // generate synonyms with affixes
446 if (stem && stem2) {
447 Reference< XSpellAlternatives > xTmpRes;
448 xTmpRes = xSpell->spell( A2OU("<?xml?><query type='generate'><word>") +
449 sTerm + A2OU("</word>") + codeTerm + A2OU("</query>"), nLanguage, rProperties );
450 if (xTmpRes.is()) {
451 Sequence<OUString>seq = xTmpRes->getAlternatives();
452 for (int k = 0; k < seq.getLength(); k++) {
453 OString o = OUStringToOString(seq[k], rtl_getTextEncodingFromUnixCharset("UTF-8"));
455 if (seq.getLength() > 0) sTerm = seq[0];
458 if (catpos2) sTerm = catst2 + sTerm;
460 sal_uInt16 ct1 = capitalType(sTerm, pCC);
461 if (CAPTYPE_MIXED == ct1)
462 ct = ct1;
463 OUString cTerm;
464 switch (ct) {
465 case CAPTYPE_ALLCAP:
467 cTerm = makeUpperCase(sTerm, pCC);
468 break;
470 case CAPTYPE_INITCAP:
472 cTerm = makeInitCap(sTerm, pCC);
473 break;
475 default:
477 cTerm = sTerm;
478 break;
481 OUString aAlt( cTerm + catst);
482 pStr[i] = aAlt;
484 #if 0
485 Meaning * pMn = new Meaning(rTerm,nLanguage,rHelper);
486 #endif
487 Meaning * pMn = new Meaning(rTerm,nLanguage);
488 OUString dTerm(pe->defn,strlen(pe->defn),aEnc );
489 pMn->SetMeaning(dTerm);
490 pMn->SetSynonyms(aStr);
491 Reference<XMeaning>* pMeaning = aMeanings.getArray();
492 pMeaning[j] = pMn;
494 pe++;
496 pTH->CleanUpAfterLookup(&pmean,nmean);
498 if (nmean) {
499 prevTerm = qTerm;
500 prevMeanings = aMeanings;
501 prevLocale = nLanguage;
502 return aMeanings;
505 if (stem || !xLngSvcMgr.is()) return noMeanings;
506 stem = 1;
508 xSpell = uno::Reference< XSpellChecker1 >( xLngSvcMgr->getSpellChecker(), UNO_QUERY );
509 if (!xSpell.is() || !xSpell->isValid( A2OU(SPELLML_SUPPORT), nLanguage, rProperties )) {
510 return noMeanings;
512 Reference< XSpellAlternatives > xTmpRes;
513 xTmpRes = xSpell->spell( A2OU("<?xml?><query type='stem'><word>") +
514 rTerm + A2OU("</word></query>"), nLanguage, rProperties );
515 if (xTmpRes.is()) {
516 Sequence<OUString>seq = xTmpRes->getAlternatives();
517 #if 0
518 for (int i = 0; i < seq.getLength(); i++) {
519 OString o = OUStringToOString(seq[i], rtl_getTextEncodingFromUnixCharset("UTF-8"));
520 fprintf(stderr, "%d: %s\n", i + 1, o.pData->buffer);
522 #endif
523 if (seq.getLength() > 0) {
524 rTerm = seq[0]; // XXX Use only the first stem
525 continue;
529 // stem the last word of the synonym (for categories after affixation)
530 rTerm = rTerm.trim();
531 sal_Int32 pos = rTerm.lastIndexOf(' ');
532 if (!pos) return noMeanings;
533 xTmpRes = xSpell->spell( A2OU("<?xml?><query type='stem'><word>") +
534 rTerm.copy(pos + 1) + A2OU("</word></query>"), nLanguage, rProperties );
535 if (xTmpRes.is()) {
536 Sequence<OUString>seq = xTmpRes->getAlternatives();
537 if (seq.getLength() > 0) {
538 pTerm = rTerm.copy(pos + 1);
539 rTerm = rTerm.copy(0, pos + 1) + seq[0];
540 #if 0
541 for (int i = 0; i < seq.getLength(); i++) {
542 OString o = OUStringToOString(seq[i], rtl_getTextEncodingFromUnixCharset("UTF-8"));
543 fprintf(stderr, "%d: %s\n", i + 1, o.pData->buffer);
545 #endif
546 continue;
549 break;
551 return noMeanings;
556 Reference< XInterface > SAL_CALL Thesaurus_CreateInstance(
557 const Reference< XMultiServiceFactory > & /*rSMgr*/ )
558 throw(Exception)
560 Reference< XInterface > xService = (cppu::OWeakObject*) new Thesaurus;
561 return xService;
565 OUString SAL_CALL
566 Thesaurus::getServiceDisplayName( const Locale& /*rLocale*/ )
567 throw(RuntimeException)
569 MutexGuard aGuard( GetLinguMutex() );
570 return A2OU( "OpenOffice.org New Thesaurus" );
574 void SAL_CALL
575 Thesaurus::initialize( const Sequence< Any >& rArguments )
576 throw(Exception, RuntimeException)
578 MutexGuard aGuard( GetLinguMutex() );
580 if (!pPropHelper)
582 INT32 nLen = rArguments.getLength();
583 if (1 == nLen)
585 Reference< XPropertySet > xPropSet;
586 rArguments.getConstArray()[0] >>= xPropSet;
588 //! Pointer allows for access of the non-UNO functions.
589 //! And the reference to the UNO-functions while increasing
590 //! the ref-count and will implicitly free the memory
591 //! when the object is not longer used.
592 pPropHelper = new PropertyHelper_Thes( (XThesaurus *) this, xPropSet );
593 xPropHelper = pPropHelper;
594 pPropHelper->AddAsPropListener(); //! after a reference is established
596 else
597 DBG_ERROR( "wrong number of arguments in sequence" );
603 sal_uInt16 SAL_CALL Thesaurus::capitalType(const OUString& aTerm, CharClass * pCC)
605 sal_Int32 tlen = aTerm.getLength();
606 if ((pCC) && (tlen)) {
607 String aStr(aTerm);
608 sal_Int32 nc = 0;
609 for (USHORT tindex = 0; tindex < tlen; tindex++) {
610 if (pCC->getCharacterType(aStr,tindex) &
611 ::com::sun::star::i18n::KCharacterType::UPPER) nc++;
614 if (nc == 0) return (sal_uInt16) CAPTYPE_NOCAP;
616 if (nc == tlen) return (sal_uInt16) CAPTYPE_ALLCAP;
618 if ((nc == 1) && (pCC->getCharacterType(aStr,0) &
619 ::com::sun::star::i18n::KCharacterType::UPPER))
620 return (sal_uInt16) CAPTYPE_INITCAP;
622 return (sal_uInt16) CAPTYPE_MIXED;
624 return (sal_uInt16) CAPTYPE_UNKNOWN;
629 OUString SAL_CALL Thesaurus::makeLowerCase(const OUString& aTerm, CharClass * pCC)
631 if (pCC)
632 return pCC->toLower_rtl(aTerm, 0, aTerm.getLength());
633 return aTerm;
637 OUString SAL_CALL Thesaurus::makeUpperCase(const OUString& aTerm, CharClass * pCC)
639 if (pCC)
640 return pCC->toUpper_rtl(aTerm, 0, aTerm.getLength());
641 return aTerm;
645 OUString SAL_CALL Thesaurus::makeInitCap(const OUString& aTerm, CharClass * pCC)
647 sal_Int32 tlen = aTerm.getLength();
648 if ((pCC) && (tlen)) {
649 OUString bTemp = aTerm.copy(0,1);
650 if (tlen > 1)
651 return ( pCC->toUpper_rtl(bTemp, 0, 1)
652 + pCC->toLower_rtl(aTerm,1,(tlen-1)) );
654 return pCC->toUpper_rtl(bTemp, 0, 1);
656 return aTerm;
661 void SAL_CALL
662 Thesaurus::dispose()
663 throw(RuntimeException)
665 MutexGuard aGuard( GetLinguMutex() );
667 if (!bDisposing)
669 bDisposing = TRUE;
670 EventObject aEvtObj( (XThesaurus *) this );
671 aEvtListeners.disposeAndClear( aEvtObj );
676 void SAL_CALL
677 Thesaurus::addEventListener( const Reference< XEventListener >& rxListener )
678 throw(RuntimeException)
680 MutexGuard aGuard( GetLinguMutex() );
682 if (!bDisposing && rxListener.is())
683 aEvtListeners.addInterface( rxListener );
687 void SAL_CALL
688 Thesaurus::removeEventListener( const Reference< XEventListener >& rxListener )
689 throw(RuntimeException)
691 MutexGuard aGuard( GetLinguMutex() );
693 if (!bDisposing && rxListener.is())
694 aEvtListeners.removeInterface( rxListener );
698 ///////////////////////////////////////////////////////////////////////////
699 // Service specific part
702 OUString SAL_CALL Thesaurus::getImplementationName()
703 throw(RuntimeException)
705 MutexGuard aGuard( GetLinguMutex() );
706 return getImplementationName_Static();
710 sal_Bool SAL_CALL Thesaurus::supportsService( const OUString& ServiceName )
711 throw(RuntimeException)
713 MutexGuard aGuard( GetLinguMutex() );
715 Sequence< OUString > aSNL = getSupportedServiceNames();
716 const OUString * pArray = aSNL.getConstArray();
717 for( INT32 i = 0; i < aSNL.getLength(); i++ )
718 if( pArray[i] == ServiceName )
719 return TRUE;
720 return FALSE;
724 Sequence< OUString > SAL_CALL Thesaurus::getSupportedServiceNames()
725 throw(RuntimeException)
727 MutexGuard aGuard( GetLinguMutex() );
728 return getSupportedServiceNames_Static();
732 Sequence< OUString > Thesaurus::getSupportedServiceNames_Static()
733 throw()
735 MutexGuard aGuard( GetLinguMutex() );
737 Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich
738 aSNS.getArray()[0] = A2OU( SN_THESAURUS );
739 return aSNS;
743 sal_Bool SAL_CALL Thesaurus_writeInfo(
744 void * /*pServiceManager*/, registry::XRegistryKey * pRegistryKey )
748 String aImpl( '/' );
749 aImpl += Thesaurus::getImplementationName_Static().getStr();
750 aImpl.AppendAscii( "/UNO/SERVICES" );
751 Reference< registry::XRegistryKey > xNewKey =
752 pRegistryKey->createKey( aImpl );
753 Sequence< OUString > aServices =
754 Thesaurus::getSupportedServiceNames_Static();
755 for( INT32 i = 0; i < aServices.getLength(); i++ )
756 xNewKey->createKey( aServices.getConstArray()[i] );
758 return sal_True;
760 catch(Exception &)
762 return sal_False;
767 void * SAL_CALL Thesaurus_getFactory( const sal_Char * pImplName,
768 XMultiServiceFactory * pServiceManager, void * )
770 void * pRet = 0;
771 if ( !Thesaurus::getImplementationName_Static().compareToAscii( pImplName ) )
774 Reference< XSingleServiceFactory > xFactory =
775 cppu::createOneInstanceFactory(
776 pServiceManager,
777 Thesaurus::getImplementationName_Static(),
778 Thesaurus_CreateInstance,
779 Thesaurus::getSupportedServiceNames_Static());
780 // acquire, because we return an interface pointer instead of a reference
781 xFactory->acquire();
782 pRet = xFactory.get();
784 return pRet;
788 ///////////////////////////////////////////////////////////////////////////
791 #undef CAPTYPE_UNKNOWN
792 #undef CAPTYPE_NOCAP
793 #undef CAPTYPE_INITCAP
794 #undef CAPTYPE_ALLCAP
795 #undef CAPTYPE_MIXED