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