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