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