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