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_linguistic.hxx" 26 27 #include <cppuhelper/factory.hxx> 28 #include <i18npool/mslangid.hxx> 29 #include <osl/file.hxx> 30 #include <tools/fsys.hxx> 31 #include <tools/stream.hxx> 32 #include <tools/urlobj.hxx> 33 #include <i18npool/mslangid.hxx> 34 #include <unotools/pathoptions.hxx> 35 #include <unotools/useroptions.hxx> 36 #include <cppuhelper/factory.hxx> // helper for factories 37 #include <unotools/localfilehelper.hxx> 38 #include <comphelper/processfactory.hxx> 39 #include <unotools/ucbstreamhelper.hxx> 40 #include <com/sun/star/frame/XStorable.hpp> 41 #include <com/sun/star/lang/Locale.hpp> 42 #include <com/sun/star/uno/Reference.h> 43 #include <com/sun/star/linguistic2/DictionaryEventFlags.hpp> 44 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp> 45 #include <com/sun/star/registry/XRegistryKey.hpp> 46 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 47 48 #include "defs.hxx" 49 #include "dlistimp.hxx" 50 #include "dicimp.hxx" 51 #include "lngopt.hxx" 52 53 #include "defs.hxx" 54 #include "dlistimp.hxx" 55 #include "dicimp.hxx" 56 #include "lngopt.hxx" 57 58 //using namespace utl; 59 using namespace osl; 60 using namespace rtl; 61 using namespace com::sun::star; 62 using namespace com::sun::star::lang; 63 using namespace com::sun::star::uno; 64 using namespace com::sun::star::linguistic2; 65 using namespace linguistic; 66 67 /////////////////////////////////////////////////////////////////////////// 68 69 static sal_Bool IsVers2OrNewer( const String& rFileURL, sal_uInt16& nLng, sal_Bool& bNeg ); 70 71 static void AddInternal( const uno::Reference< XDictionary > &rDic, 72 const rtl::OUString& rNew ); 73 static void AddUserData( const uno::Reference< XDictionary > &rDic ); 74 75 /////////////////////////////////////////////////////////////////////////// 76 77 class DicEvtListenerHelper : 78 public cppu::WeakImplHelper1 79 < 80 XDictionaryEventListener 81 > 82 { 83 cppu::OInterfaceContainerHelper aDicListEvtListeners; 84 uno::Sequence< DictionaryEvent > aCollectDicEvt; 85 uno::Reference< XDictionaryList > xMyDicList; 86 87 sal_Int16 nCondensedEvt; 88 sal_Int16 nNumCollectEvtListeners, 89 nNumVerboseListeners; 90 91 public: 92 DicEvtListenerHelper( const uno::Reference< XDictionaryList > &rxDicList ); 93 virtual ~DicEvtListenerHelper(); 94 95 // XEventListener 96 virtual void SAL_CALL 97 disposing( const EventObject& rSource ) 98 throw(RuntimeException); 99 100 // XDictionaryEventListener 101 virtual void SAL_CALL 102 processDictionaryEvent( const DictionaryEvent& rDicEvent ) 103 throw(RuntimeException); 104 105 // non-UNO functions 106 void DisposeAndClear( const EventObject &rEvtObj ); 107 108 sal_Bool AddDicListEvtListener( 109 const uno::Reference< XDictionaryListEventListener >& rxListener, 110 sal_Bool bReceiveVerbose ); 111 sal_Bool RemoveDicListEvtListener( 112 const uno::Reference< XDictionaryListEventListener >& rxListener ); 113 sal_Int16 BeginCollectEvents(); 114 sal_Int16 EndCollectEvents(); 115 sal_Int16 FlushEvents(); 116 void ClearEvents() { nCondensedEvt = 0; } 117 }; 118 119 120 DicEvtListenerHelper::DicEvtListenerHelper( 121 const uno::Reference< XDictionaryList > &rxDicList ) : 122 aDicListEvtListeners ( GetLinguMutex() ), 123 xMyDicList ( rxDicList ) 124 { 125 nCondensedEvt = 0; 126 nNumCollectEvtListeners = nNumVerboseListeners = 0; 127 } 128 129 130 DicEvtListenerHelper::~DicEvtListenerHelper() 131 { 132 DBG_ASSERT(aDicListEvtListeners.getLength() == 0, 133 "lng : event listeners are still existing"); 134 } 135 136 137 void DicEvtListenerHelper::DisposeAndClear( const EventObject &rEvtObj ) 138 { 139 aDicListEvtListeners.disposeAndClear( rEvtObj ); 140 } 141 142 143 void SAL_CALL DicEvtListenerHelper::disposing( const EventObject& rSource ) 144 throw(RuntimeException) 145 { 146 osl::MutexGuard aGuard( GetLinguMutex() ); 147 148 uno::Reference< XInterface > xSrc( rSource.Source ); 149 150 // remove event object from EventListener list 151 if (xSrc.is()) 152 aDicListEvtListeners.removeInterface( xSrc ); 153 154 // if object is a dictionary then remove it from the dictionary list 155 // Note: this will probably happen only if someone makes a XDictionary 156 // implementation of his own that is also a XComponent. 157 uno::Reference< XDictionary > xDic( xSrc, UNO_QUERY ); 158 if (xDic.is()) 159 { 160 xMyDicList->removeDictionary( xDic ); 161 } 162 } 163 164 165 void SAL_CALL DicEvtListenerHelper::processDictionaryEvent( 166 const DictionaryEvent& rDicEvent ) 167 throw(RuntimeException) 168 { 169 osl::MutexGuard aGuard( GetLinguMutex() ); 170 171 uno::Reference< XDictionary > xDic( rDicEvent.Source, UNO_QUERY ); 172 DBG_ASSERT(xDic.is(), "lng : missing event source"); 173 174 // assert that there is a corresponding dictionary entry if one was 175 // added or deleted 176 uno::Reference< XDictionaryEntry > xDicEntry( rDicEvent.xDictionaryEntry, UNO_QUERY ); 177 DBG_ASSERT( !(rDicEvent.nEvent & 178 (DictionaryEventFlags::ADD_ENTRY | DictionaryEventFlags::DEL_ENTRY)) 179 || xDicEntry.is(), 180 "lng : missing dictionary entry" ); 181 182 /*sal_Bool bActiveDicsModified = sal_False;*/ 183 // 184 // evaluate DictionaryEvents and update data for next DictionaryListEvent 185 // 186 DictionaryType eDicType = xDic->getDictionaryType(); 187 DBG_ASSERT(eDicType != DictionaryType_MIXED, 188 "lng : unexpected dictionary type"); 189 if ((rDicEvent.nEvent & DictionaryEventFlags::ADD_ENTRY) && xDic->isActive()) 190 nCondensedEvt |= xDicEntry->isNegative() ? 191 DictionaryListEventFlags::ADD_NEG_ENTRY : 192 DictionaryListEventFlags::ADD_POS_ENTRY; 193 if ((rDicEvent.nEvent & DictionaryEventFlags::DEL_ENTRY) && xDic->isActive()) 194 nCondensedEvt |= xDicEntry->isNegative() ? 195 DictionaryListEventFlags::DEL_NEG_ENTRY : 196 DictionaryListEventFlags::DEL_POS_ENTRY; 197 if ((rDicEvent.nEvent & DictionaryEventFlags::ENTRIES_CLEARED) && xDic->isActive()) 198 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? 199 DictionaryListEventFlags::DEL_NEG_ENTRY : 200 DictionaryListEventFlags::DEL_POS_ENTRY; 201 if ((rDicEvent.nEvent & DictionaryEventFlags::CHG_LANGUAGE) && xDic->isActive()) 202 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? 203 DictionaryListEventFlags::DEACTIVATE_NEG_DIC 204 | DictionaryListEventFlags::ACTIVATE_NEG_DIC : 205 DictionaryListEventFlags::DEACTIVATE_POS_DIC 206 | DictionaryListEventFlags::ACTIVATE_POS_DIC; 207 if ((rDicEvent.nEvent & DictionaryEventFlags::ACTIVATE_DIC)) 208 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? 209 DictionaryListEventFlags::ACTIVATE_NEG_DIC : 210 DictionaryListEventFlags::ACTIVATE_POS_DIC; 211 if ((rDicEvent.nEvent & DictionaryEventFlags::DEACTIVATE_DIC)) 212 nCondensedEvt |= eDicType == DictionaryType_NEGATIVE ? 213 DictionaryListEventFlags::DEACTIVATE_NEG_DIC : 214 DictionaryListEventFlags::DEACTIVATE_POS_DIC; 215 216 // update list of collected events if needs to be 217 if (nNumVerboseListeners > 0) 218 { 219 sal_Int32 nColEvts = aCollectDicEvt.getLength(); 220 aCollectDicEvt.realloc( nColEvts + 1 ); 221 aCollectDicEvt.getArray()[ nColEvts ] = rDicEvent; 222 } 223 224 if (nNumCollectEvtListeners == 0 && nCondensedEvt != 0) 225 FlushEvents(); 226 } 227 228 229 sal_Bool DicEvtListenerHelper::AddDicListEvtListener( 230 const uno::Reference< XDictionaryListEventListener >& xListener, 231 sal_Bool /*bReceiveVerbose*/ ) 232 { 233 DBG_ASSERT( xListener.is(), "empty reference" ); 234 sal_Int32 nCount = aDicListEvtListeners.getLength(); 235 return aDicListEvtListeners.addInterface( xListener ) != nCount; 236 } 237 238 239 sal_Bool DicEvtListenerHelper::RemoveDicListEvtListener( 240 const uno::Reference< XDictionaryListEventListener >& xListener ) 241 { 242 DBG_ASSERT( xListener.is(), "empty reference" ); 243 sal_Int32 nCount = aDicListEvtListeners.getLength(); 244 return aDicListEvtListeners.removeInterface( xListener ) != nCount; 245 } 246 247 248 sal_Int16 DicEvtListenerHelper::BeginCollectEvents() 249 { 250 return ++nNumCollectEvtListeners; 251 } 252 253 254 sal_Int16 DicEvtListenerHelper::EndCollectEvents() 255 { 256 DBG_ASSERT(nNumCollectEvtListeners > 0, "lng: mismatched function call"); 257 if (nNumCollectEvtListeners > 0) 258 { 259 FlushEvents(); 260 nNumCollectEvtListeners--; 261 } 262 263 return nNumCollectEvtListeners; 264 } 265 266 267 sal_Int16 DicEvtListenerHelper::FlushEvents() 268 { 269 if (0 != nCondensedEvt) 270 { 271 // build DictionaryListEvent to pass on to listeners 272 uno::Sequence< DictionaryEvent > aDicEvents; 273 if (nNumVerboseListeners > 0) 274 aDicEvents = aCollectDicEvt; 275 DictionaryListEvent aEvent( xMyDicList, nCondensedEvt, aDicEvents ); 276 277 // pass on event 278 cppu::OInterfaceIteratorHelper aIt( aDicListEvtListeners ); 279 while (aIt.hasMoreElements()) 280 { 281 uno::Reference< XDictionaryListEventListener > xRef( aIt.next(), UNO_QUERY ); 282 if (xRef.is()) 283 xRef->processDictionaryListEvent( aEvent ); 284 } 285 286 // clear "list" of events 287 nCondensedEvt = 0; 288 aCollectDicEvt.realloc( 0 ); 289 } 290 291 return nNumCollectEvtListeners; 292 } 293 294 295 /////////////////////////////////////////////////////////////////////////// 296 297 298 void DicList::MyAppExitListener::AtExit() 299 { 300 rMyDicList.SaveDics(); 301 } 302 303 304 DicList::DicList() : 305 aEvtListeners ( GetLinguMutex() ) 306 { 307 pDicEvtLstnrHelper = new DicEvtListenerHelper( this ); 308 xDicEvtLstnrHelper = pDicEvtLstnrHelper; 309 bDisposing = sal_False; 310 bInCreation = sal_False; 311 312 pExitListener = new MyAppExitListener( *this ); 313 xExitListener = pExitListener; 314 pExitListener->Activate(); 315 } 316 317 DicList::~DicList() 318 { 319 pExitListener->Deactivate(); 320 } 321 322 323 void DicList::SearchForDictionaries( 324 DictionaryVec_t&rDicList, 325 const String &rDicDirURL, 326 sal_Bool bIsWriteablePath ) 327 { 328 osl::MutexGuard aGuard( GetLinguMutex() ); 329 330 const uno::Sequence< rtl::OUString > aDirCnt( utl::LocalFileHelper:: 331 GetFolderContents( rDicDirURL, sal_False ) ); 332 const rtl::OUString *pDirCnt = aDirCnt.getConstArray(); 333 sal_Int32 nEntries = aDirCnt.getLength(); 334 335 String aDCN( String::CreateFromAscii( "dcn" ) ); 336 String aDCP( String::CreateFromAscii( "dcp" ) ); 337 for (sal_Int32 i = 0; i < nEntries; ++i) 338 { 339 String aURL( pDirCnt[i] ); 340 sal_uInt16 nLang = LANGUAGE_NONE; 341 sal_Bool bNeg = sal_False; 342 343 if(!::IsVers2OrNewer( aURL, nLang, bNeg )) 344 { 345 // Wenn kein 346 xub_StrLen nPos = aURL.Search('.'); 347 String aExt(aURL.Copy(nPos + 1)); 348 aExt.ToLowerAscii(); 349 350 if(aExt == aDCN) // negativ 351 bNeg = sal_True; 352 else if(aExt == aDCP) // positiv 353 bNeg = sal_False; 354 else 355 continue; // andere Files 356 } 357 358 // Aufnehmen in die Liste der Dictionaries 359 // Wenn existent nicht aufnehmen 360 // 361 sal_Int16 nSystemLanguage = MsLangId::getSystemLanguage(); 362 String aTmp1 = ToLower( aURL, nSystemLanguage ); 363 xub_StrLen nPos = aTmp1.SearchBackward( '/' ); 364 if (STRING_NOTFOUND != nPos) 365 aTmp1 = aTmp1.Copy( nPos + 1 ); 366 String aTmp2; 367 size_t j; 368 size_t nCount = rDicList.size(); 369 for(j = 0; j < nCount; j++) 370 { 371 aTmp2 = rDicList[j]->getName().getStr(); 372 aTmp2 = ToLower( aTmp2, nSystemLanguage ); 373 if(aTmp1 == aTmp2) 374 break; 375 } 376 if(j >= nCount) // dictionary not yet in DicList 377 { 378 // get decoded dictionary file name 379 INetURLObject aURLObj( aURL ); 380 String aDicName = aURLObj.getName( INetURLObject::LAST_SEGMENT, 381 true, INetURLObject::DECODE_WITH_CHARSET, 382 RTL_TEXTENCODING_UTF8 ); 383 384 DictionaryType eType = bNeg ? DictionaryType_NEGATIVE : DictionaryType_POSITIVE; 385 uno::Reference< XDictionary > xDic = 386 new DictionaryNeo( aDicName, nLang, eType, aURL, bIsWriteablePath ); 387 388 addDictionary( xDic ); 389 nCount++; 390 } 391 } 392 } 393 394 395 sal_Int32 DicList::GetDicPos(const uno::Reference< XDictionary > &xDic) 396 { 397 osl::MutexGuard aGuard( GetLinguMutex() ); 398 399 sal_Int32 nPos = -1; 400 DictionaryVec_t& rDicList = GetOrCreateDicList(); 401 size_t n = rDicList.size(); 402 for (size_t i = 0; i < n; i++) 403 { 404 if ( rDicList[i] == xDic ) 405 return i; 406 } 407 return nPos; 408 } 409 410 411 uno::Reference< XInterface > SAL_CALL 412 DicList_CreateInstance( const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ ) 413 throw(Exception) 414 { 415 uno::Reference< XInterface > xService = (cppu::OWeakObject *) new DicList; 416 return xService; 417 } 418 419 sal_Int16 SAL_CALL DicList::getCount() throw(RuntimeException) 420 { 421 osl::MutexGuard aGuard( GetLinguMutex() ); 422 return static_cast< sal_Int16 >(GetOrCreateDicList().size()); 423 } 424 425 uno::Sequence< uno::Reference< XDictionary > > SAL_CALL 426 DicList::getDictionaries() 427 throw(RuntimeException) 428 { 429 osl::MutexGuard aGuard( GetLinguMutex() ); 430 431 DictionaryVec_t& rDicList = GetOrCreateDicList(); 432 433 uno::Sequence< uno::Reference< XDictionary > > aDics( rDicList.size() ); 434 uno::Reference< XDictionary > *pDic = aDics.getArray(); 435 436 sal_Int32 n = (sal_uInt16) aDics.getLength(); 437 for (sal_Int32 i = 0; i < n; i++) 438 pDic[i] = rDicList[i]; 439 440 return aDics; 441 } 442 443 uno::Reference< XDictionary > SAL_CALL 444 DicList::getDictionaryByName( const rtl::OUString& aDictionaryName ) 445 throw(RuntimeException) 446 { 447 osl::MutexGuard aGuard( GetLinguMutex() ); 448 449 uno::Reference< XDictionary > xDic; 450 DictionaryVec_t& rDicList = GetOrCreateDicList(); 451 size_t nCount = rDicList.size(); 452 for (size_t i = 0; i < nCount; i++) 453 { 454 const uno::Reference< XDictionary > &rDic = rDicList[i]; 455 if (rDic.is() && rDic->getName() == aDictionaryName) 456 { 457 xDic = rDic; 458 break; 459 } 460 } 461 462 return xDic; 463 } 464 465 sal_Bool SAL_CALL DicList::addDictionary( 466 const uno::Reference< XDictionary >& xDictionary ) 467 throw(RuntimeException) 468 { 469 osl::MutexGuard aGuard( GetLinguMutex() ); 470 471 if (bDisposing) 472 return sal_False; 473 474 sal_Bool bRes = sal_False; 475 if (xDictionary.is()) 476 { 477 DictionaryVec_t& rDicList = GetOrCreateDicList(); 478 rDicList.push_back( xDictionary ); 479 bRes = sal_True; 480 481 // add listener helper to the dictionaries listener lists 482 xDictionary->addDictionaryEventListener( xDicEvtLstnrHelper ); 483 } 484 return bRes; 485 } 486 487 sal_Bool SAL_CALL 488 DicList::removeDictionary( const uno::Reference< XDictionary >& xDictionary ) 489 throw(RuntimeException) 490 { 491 osl::MutexGuard aGuard( GetLinguMutex() ); 492 493 if (bDisposing) 494 return sal_False; 495 496 sal_Bool bRes = sal_False; 497 sal_Int32 nPos = GetDicPos( xDictionary ); 498 if (nPos >= 0) 499 { 500 // remove dictionary list from the dictionaries listener lists 501 DictionaryVec_t& rDicList = GetOrCreateDicList(); 502 uno::Reference< XDictionary > xDic( rDicList[ nPos ] ); 503 DBG_ASSERT(xDic.is(), "lng : empty reference"); 504 if (xDic.is()) 505 { 506 // deactivate dictionary if not already done 507 xDic->setActive( sal_False ); 508 509 xDic->removeDictionaryEventListener( xDicEvtLstnrHelper ); 510 } 511 512 // remove element at nPos 513 rDicList.erase( rDicList.begin() + nPos ); 514 bRes = sal_True; 515 } 516 return bRes; 517 } 518 519 sal_Bool SAL_CALL DicList::addDictionaryListEventListener( 520 const uno::Reference< XDictionaryListEventListener >& xListener, 521 sal_Bool bReceiveVerbose ) 522 throw(RuntimeException) 523 { 524 osl::MutexGuard aGuard( GetLinguMutex() ); 525 526 if (bDisposing) 527 return sal_False; 528 529 DBG_ASSERT(!bReceiveVerbose, "lng : not yet supported"); 530 531 sal_Bool bRes = sal_False; 532 if (xListener.is()) //! don't add empty references 533 { 534 bRes = pDicEvtLstnrHelper-> 535 AddDicListEvtListener( xListener, bReceiveVerbose ); 536 } 537 return bRes; 538 } 539 540 sal_Bool SAL_CALL DicList::removeDictionaryListEventListener( 541 const uno::Reference< XDictionaryListEventListener >& xListener ) 542 throw(RuntimeException) 543 { 544 osl::MutexGuard aGuard( GetLinguMutex() ); 545 546 if (bDisposing) 547 return sal_False; 548 549 sal_Bool bRes = sal_False; 550 if(xListener.is()) 551 { 552 bRes = pDicEvtLstnrHelper->RemoveDicListEvtListener( xListener ); 553 } 554 return bRes; 555 } 556 557 sal_Int16 SAL_CALL DicList::beginCollectEvents() throw(RuntimeException) 558 { 559 osl::MutexGuard aGuard( GetLinguMutex() ); 560 return pDicEvtLstnrHelper->BeginCollectEvents(); 561 } 562 563 sal_Int16 SAL_CALL DicList::endCollectEvents() throw(RuntimeException) 564 { 565 osl::MutexGuard aGuard( GetLinguMutex() ); 566 return pDicEvtLstnrHelper->EndCollectEvents(); 567 } 568 569 sal_Int16 SAL_CALL DicList::flushEvents() throw(RuntimeException) 570 { 571 osl::MutexGuard aGuard( GetLinguMutex() ); 572 return pDicEvtLstnrHelper->FlushEvents(); 573 } 574 575 uno::Reference< XDictionary > SAL_CALL 576 DicList::createDictionary( const rtl::OUString& rName, const Locale& rLocale, 577 DictionaryType eDicType, const rtl::OUString& rURL ) 578 throw(RuntimeException) 579 { 580 osl::MutexGuard aGuard( GetLinguMutex() ); 581 582 sal_Int16 nLanguage = LocaleToLanguage( rLocale ); 583 bool bIsWriteablePath = rURL.match( GetDictionaryWriteablePath(), 0 ); 584 return new DictionaryNeo( rName, nLanguage, eDicType, rURL, bIsWriteablePath ); 585 } 586 587 588 uno::Reference< XDictionaryEntry > SAL_CALL 589 DicList::queryDictionaryEntry( const rtl::OUString& rWord, const Locale& rLocale, 590 sal_Bool bSearchPosDics, sal_Bool bSearchSpellEntry ) 591 throw(RuntimeException) 592 { 593 osl::MutexGuard aGuard( GetLinguMutex() ); 594 return SearchDicList( this, rWord, LocaleToLanguage( rLocale ), 595 bSearchPosDics, bSearchSpellEntry ); 596 } 597 598 599 void SAL_CALL 600 DicList::dispose() 601 throw(RuntimeException) 602 { 603 osl::MutexGuard aGuard( GetLinguMutex() ); 604 605 if (!bDisposing) 606 { 607 bDisposing = sal_True; 608 EventObject aEvtObj( (XDictionaryList *) this ); 609 610 aEvtListeners.disposeAndClear( aEvtObj ); 611 if (pDicEvtLstnrHelper) 612 pDicEvtLstnrHelper->DisposeAndClear( aEvtObj ); 613 614 //! avoid creation of dictionaries if not already done 615 if (aDicList.size() > 0) 616 { 617 DictionaryVec_t& rDicList = GetOrCreateDicList(); 618 size_t nCount = rDicList.size(); 619 for (size_t i = 0; i < nCount; i++) 620 { 621 uno::Reference< XDictionary > xDic( rDicList[i], UNO_QUERY ); 622 623 // save (modified) dictionaries 624 uno::Reference< frame::XStorable > xStor( xDic , UNO_QUERY ); 625 if (xStor.is()) 626 { 627 try 628 { 629 if (!xStor->isReadonly() && xStor->hasLocation()) 630 xStor->store(); 631 } 632 catch(Exception &) 633 { 634 } 635 } 636 637 // release references to (members of) this object hold by 638 // dictionaries 639 if (xDic.is()) 640 xDic->removeDictionaryEventListener( xDicEvtLstnrHelper ); 641 } 642 } 643 } 644 } 645 646 void SAL_CALL 647 DicList::addEventListener( const uno::Reference< XEventListener >& rxListener ) 648 throw(RuntimeException) 649 { 650 osl::MutexGuard aGuard( GetLinguMutex() ); 651 652 if (!bDisposing && rxListener.is()) 653 aEvtListeners.addInterface( rxListener ); 654 } 655 656 void SAL_CALL 657 DicList::removeEventListener( const uno::Reference< XEventListener >& rxListener ) 658 throw(RuntimeException) 659 { 660 osl::MutexGuard aGuard( GetLinguMutex() ); 661 662 if (!bDisposing && rxListener.is()) 663 aEvtListeners.removeInterface( rxListener ); 664 } 665 666 void DicList::_CreateDicList() 667 { 668 bInCreation = sal_True; 669 670 // look for dictionaries 671 const rtl::OUString aWriteablePath( GetDictionaryWriteablePath() ); 672 uno::Sequence< rtl::OUString > aPaths( GetDictionaryPaths() ); 673 const rtl::OUString *pPaths = aPaths.getConstArray(); 674 for (sal_Int32 i = 0; i < aPaths.getLength(); ++i) 675 { 676 const sal_Bool bIsWriteablePath = (pPaths[i] == aWriteablePath); 677 SearchForDictionaries( aDicList, pPaths[i], bIsWriteablePath ); 678 } 679 680 // create IgnoreAllList dictionary with empty URL (non persistent) 681 // and add it to list 682 rtl::OUString aDicName( A2OU( "IgnoreAllList" ) ); 683 uno::Reference< XDictionary > xIgnAll( 684 createDictionary( aDicName, CreateLocale( LANGUAGE_NONE ), 685 DictionaryType_POSITIVE, rtl::OUString() ) ); 686 if (xIgnAll.is()) 687 { 688 AddUserData( xIgnAll ); 689 xIgnAll->setActive( sal_True ); 690 addDictionary( xIgnAll ); 691 } 692 693 694 // evaluate list of dictionaries to be activated from configuration 695 // 696 //! to suppress overwriting the list of active dictionaries in the 697 //! configuration with incorrect arguments during the following 698 //! activation of the dictionaries 699 pDicEvtLstnrHelper->BeginCollectEvents(); 700 // 701 const uno::Sequence< rtl::OUString > aActiveDics( aOpt.GetActiveDics() ); 702 const rtl::OUString *pActiveDic = aActiveDics.getConstArray(); 703 sal_Int32 nLen = aActiveDics.getLength(); 704 for (sal_Int32 i = 0; i < nLen; ++i) 705 { 706 if (pActiveDic[i].getLength()) 707 { 708 uno::Reference< XDictionary > xDic( getDictionaryByName( pActiveDic[i] ) ); 709 if (xDic.is()) 710 xDic->setActive( sal_True ); 711 } 712 } 713 714 // suppress collected events during creation of the dictionary list. 715 // there should be no events during creation. 716 pDicEvtLstnrHelper->ClearEvents(); 717 718 pDicEvtLstnrHelper->EndCollectEvents(); 719 720 bInCreation = sal_False; 721 } 722 723 724 void DicList::SaveDics() 725 { 726 // save dics only if they have already been used/created. 727 //! don't create them just for the purpose of saving them ! 728 if (aDicList.size() > 0) 729 { 730 // save (modified) dictionaries 731 DictionaryVec_t& rDicList = GetOrCreateDicList(); 732 size_t nCount = rDicList.size();; 733 for (size_t i = 0; i < nCount; i++) 734 { 735 // save (modified) dictionaries 736 uno::Reference< frame::XStorable > xStor( rDicList[i], UNO_QUERY ); 737 if (xStor.is()) 738 { 739 try 740 { 741 if (!xStor->isReadonly() && xStor->hasLocation()) 742 xStor->store(); 743 } 744 catch(Exception &) 745 { 746 } 747 } 748 } 749 } 750 } 751 752 753 /////////////////////////////////////////////////////////////////////////// 754 // Service specific part 755 // 756 757 rtl::OUString SAL_CALL DicList::getImplementationName( ) throw(RuntimeException) 758 { 759 osl::MutexGuard aGuard( GetLinguMutex() ); 760 return getImplementationName_Static(); 761 } 762 763 764 sal_Bool SAL_CALL DicList::supportsService( const rtl::OUString& ServiceName ) 765 throw(RuntimeException) 766 { 767 osl::MutexGuard aGuard( GetLinguMutex() ); 768 769 uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames(); 770 const rtl::OUString * pArray = aSNL.getConstArray(); 771 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 772 if( pArray[i] == ServiceName ) 773 return sal_True; 774 return sal_False; 775 } 776 777 778 uno::Sequence< rtl::OUString > SAL_CALL DicList::getSupportedServiceNames( ) 779 throw(RuntimeException) 780 { 781 osl::MutexGuard aGuard( GetLinguMutex() ); 782 return getSupportedServiceNames_Static(); 783 } 784 785 786 uno::Sequence< rtl::OUString > DicList::getSupportedServiceNames_Static() throw() 787 { 788 osl::MutexGuard aGuard( GetLinguMutex() ); 789 790 uno::Sequence< rtl::OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich 791 aSNS.getArray()[0] = A2OU( SN_DICTIONARY_LIST ); 792 return aSNS; 793 } 794 795 void * SAL_CALL DicList_getFactory( const sal_Char * pImplName, 796 XMultiServiceFactory * pServiceManager, void * ) 797 { 798 void * pRet = 0; 799 if ( !DicList::getImplementationName_Static().compareToAscii( pImplName ) ) 800 { 801 uno::Reference< XSingleServiceFactory > xFactory = 802 cppu::createOneInstanceFactory( 803 pServiceManager, 804 DicList::getImplementationName_Static(), 805 DicList_CreateInstance, 806 DicList::getSupportedServiceNames_Static()); 807 // acquire, because we return an interface pointer instead of a reference 808 xFactory->acquire(); 809 pRet = xFactory.get(); 810 } 811 return pRet; 812 } 813 814 /////////////////////////////////////////////////////////////////////////// 815 816 xub_StrLen lcl_GetToken( String &rToken, 817 const String &rText, xub_StrLen nPos, const String &rDelim ) 818 { 819 xub_StrLen nRes = STRING_LEN; 820 821 if (rText.Len() == 0 || nPos >= rText.Len()) 822 rToken = String(); 823 else if (rDelim.Len() == 0) 824 { 825 rToken = rText; 826 if (rToken.Len()) 827 nRes = rText.Len(); 828 } 829 else 830 { 831 xub_StrLen i; 832 for (i = nPos; i < rText.Len(); ++i) 833 { 834 if (STRING_NOTFOUND != rDelim.Search( rText.GetChar(i) )) 835 break; 836 } 837 838 if (i >= rText.Len()) // delimeter not found 839 rToken = rText.Copy( nPos ); 840 else 841 rToken = rText.Copy( nPos, sal::static_int_cast< xub_StrLen >((sal_Int32) i - nPos) ); 842 nRes = i + 1; // continue after found delimeter 843 } 844 845 return nRes; 846 } 847 848 849 static void AddInternal( 850 const uno::Reference<XDictionary> &rDic, 851 const rtl::OUString& rNew ) 852 { 853 if (rDic.is()) 854 { 855 //! TL TODO: word iterator should be used to break up the text 856 static const char *pDefWordDelim = 857 "!\"#$%&'()*+,-./:;<=>?[]\\_^`{|}~\t \n"; 858 ByteString aDummy( pDefWordDelim ); 859 String aDelim( aDummy, osl_getThreadTextEncoding() ); 860 aDelim.EraseAllChars( '.' ); 861 862 String aToken; 863 xub_StrLen nPos = 0; 864 while (STRING_LEN != 865 (nPos = lcl_GetToken( aToken, rNew, nPos, aDelim ))) 866 { 867 if( aToken.Len() && !IsNumeric( aToken ) ) 868 { 869 rDic->add( aToken, sal_False, rtl::OUString() ); 870 } 871 } 872 } 873 } 874 875 static void AddUserData( const uno::Reference< XDictionary > &rDic ) 876 { 877 if (rDic.is()) 878 { 879 SvtUserOptions aUserOpt; 880 AddInternal( rDic, aUserOpt.GetFullName() ); 881 AddInternal( rDic, aUserOpt.GetCompany() ); 882 AddInternal( rDic, aUserOpt.GetStreet() ); 883 AddInternal( rDic, aUserOpt.GetCity() ); 884 AddInternal( rDic, aUserOpt.GetTitle() ); 885 AddInternal( rDic, aUserOpt.GetPosition() ); 886 AddInternal( rDic, aUserOpt.GetEmail() ); 887 } 888 } 889 890 /////////////////////////////////////////////////////////////////////////// 891 892 #if defined _MSC_VER 893 #pragma optimize("g",off) 894 #endif 895 896 static sal_Bool IsVers2OrNewer( const String& rFileURL, sal_uInt16& nLng, sal_Bool& bNeg ) 897 { 898 if (rFileURL.Len() == 0) 899 return sal_False; 900 String aDIC( GetDicExtension() ); 901 String aExt; 902 xub_StrLen nPos = rFileURL.SearchBackward( '.' ); 903 if (STRING_NOTFOUND != nPos) 904 aExt = rFileURL.Copy( nPos + 1 ); 905 aExt.ToLowerAscii(); 906 907 if(aExt != aDIC) 908 return sal_False; 909 910 // get stream to be used 911 uno::Reference< lang::XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() ); 912 913 // get XInputStream stream 914 uno::Reference< io::XInputStream > xStream; 915 try 916 { 917 uno::Reference< ucb::XSimpleFileAccess > xAccess( xServiceFactory->createInstance( 918 A2OU( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY_THROW ); 919 xStream = xAccess->openFileRead( rFileURL ); 920 } 921 catch (uno::Exception & e) 922 { 923 DBG_ASSERT( 0, "failed to get input stream" ); 924 (void) e; 925 } 926 DBG_ASSERT( xStream.is(), "failed to get stream for read" ); 927 if (!xStream.is()) 928 return sal_False; 929 930 SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) ); 931 932 int nDicVersion = ReadDicVersion(pStream, nLng, bNeg); 933 if (2 == nDicVersion || nDicVersion >= 5) 934 return sal_True; 935 936 return sal_False; 937 } 938 939 /////////////////////////////////////////////////////////////////////////// 940 941