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 <tools/fsys.hxx>
28 #include <tools/stream.hxx>
29 #include <tools/urlobj.hxx>
30 #include <unotools/pathoptions.hxx>
31 #include <unotools/useroptions.hxx>
32 #include <unotools/lingucfg.hxx>
33 #include <rtl/instance.hxx>
34 #include <cppuhelper/factory.hxx>	// helper for factories
35 #include <unotools/localfilehelper.hxx>
36 #include <com/sun/star/linguistic2/XConversionDictionaryList.hpp>
37 #include <com/sun/star/linguistic2/XConversionDictionary.hpp>
38 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
39 #include <com/sun/star/util/XFlushable.hpp>
40 #include <com/sun/star/lang/Locale.hpp>
41 #ifndef _COM_SUN_STAR_UNO_REFERENCE_HPP_
42 #include <com/sun/star/uno/Reference.h>
43 #endif
44 #include <com/sun/star/registry/XRegistryKey.hpp>
45 #include <com/sun/star/container/XNameContainer.hpp>
46 
47 #include <ucbhelper/content.hxx>
48 
49 #include "convdiclist.hxx"
50 #include "convdic.hxx"
51 #include "hhconvdic.hxx"
52 #include "linguistic/misc.hxx"
53 #include "defs.hxx"
54 
55 //using namespace utl;
56 using namespace osl;
57 using namespace rtl;
58 using namespace com::sun::star;
59 using namespace com::sun::star::lang;
60 using namespace com::sun::star::uno;
61 using namespace com::sun::star::container;
62 using namespace com::sun::star::linguistic2;
63 using namespace linguistic;
64 
65 #define SN_CONV_DICTIONARY_LIST  "com.sun.star.linguistic2.ConversionDictionaryList"
66 
67 
68 ///////////////////////////////////////////////////////////////////////////
69 
operator ==(const Locale & r1,const Locale & r2)70 bool operator == ( const Locale &r1, const Locale &r2 )
71 {
72     return  r1.Language == r2.Language &&
73             r1.Country  == r2.Country  &&
74             r1.Variant  == r2.Variant;
75 }
76 
77 ///////////////////////////////////////////////////////////////////////////
78 
GetConvDicMainURL(const String & rDicName,const String & rDirectoryURL)79 String GetConvDicMainURL( const String &rDicName, const String &rDirectoryURL )
80 {
81     // build URL to use for new (persistent) dictionaries
82 
83     String aFullDicName( rDicName );
84     aFullDicName.AppendAscii( CONV_DIC_DOT_EXT );
85 
86     INetURLObject aURLObj;
87     aURLObj.SetSmartProtocol( INET_PROT_FILE );
88     aURLObj.SetSmartURL( rDirectoryURL );
89     aURLObj.Append( aFullDicName, INetURLObject::ENCODE_ALL );
90     DBG_ASSERT(!aURLObj.HasError(), "invalid URL");
91     if (aURLObj.HasError())
92         return String();
93     else
94         return aURLObj.GetMainURL( INetURLObject::DECODE_TO_IURI );
95 }
96 
97 ///////////////////////////////////////////////////////////////////////////
98 
99 class ConvDicNameContainer :
100     public cppu::WeakImplHelper1
101     <
102         ::com::sun::star::container::XNameContainer
103     >
104 {
105     uno::Sequence< uno::Reference< XConversionDictionary > >   aConvDics;
106     ConvDicList     &rConvDicList;
107 
108     // disallow copy-constructor and assignment-operator for now
109     ConvDicNameContainer(const ConvDicNameContainer &);
110     ConvDicNameContainer & operator = (const ConvDicNameContainer &);
111 
112     sal_Int32 GetIndexByName_Impl( const OUString& rName );
113 
114 public:
115     ConvDicNameContainer( ConvDicList &rMyConvDicList );
116     virtual ~ConvDicNameContainer();
117 
118     // XElementAccess
119     virtual ::com::sun::star::uno::Type SAL_CALL getElementType(  ) throw (::com::sun::star::uno::RuntimeException);
120     virtual sal_Bool SAL_CALL hasElements(  ) throw (::com::sun::star::uno::RuntimeException);
121 
122     // XNameAccess
123     virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
124     virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames(  ) throw (::com::sun::star::uno::RuntimeException);
125     virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException);
126 
127     // XNameReplace
128     virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
129 
130     // XNameContainer
131     virtual void SAL_CALL insertByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::container::ElementExistException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
132     virtual void SAL_CALL removeByName( const ::rtl::OUString& Name ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
133 
134 
135     // looks for conversion dictionaries with the specified extension
136     // in the directory and adds them to the container
137     void AddConvDics( const String &rSearchDirPathURL, const String &rExtension );
138 
139     // calls Flush for the dictionaries that support XFlushable
140     void    FlushDics() const;
141 
GetCount() const142     sal_Int32   GetCount() const    { return aConvDics.getLength(); }
143     uno::Reference< XConversionDictionary > GetByName( const OUString& rName );
144 
GetByIndex(sal_Int32 nIdx)145     const uno::Reference< XConversionDictionary >    GetByIndex( sal_Int32 nIdx )
146     {
147         return aConvDics.getConstArray()[nIdx];
148     }
149 };
150 
151 
ConvDicNameContainer(ConvDicList & rMyConvDicList)152 ConvDicNameContainer::ConvDicNameContainer( ConvDicList &rMyConvDicList ) :
153     rConvDicList( rMyConvDicList )
154 {
155 }
156 
157 
~ConvDicNameContainer()158 ConvDicNameContainer::~ConvDicNameContainer()
159 {
160 }
161 
162 
FlushDics() const163 void ConvDicNameContainer::FlushDics() const
164 {
165     sal_Int32 nLen = aConvDics.getLength();
166     const uno::Reference< XConversionDictionary > *pDic = aConvDics.getConstArray();
167     for (sal_Int32 i = 0;  i < nLen;  ++i)
168     {
169         uno::Reference< util::XFlushable > xFlush( pDic[i] , UNO_QUERY );
170         if (xFlush.is())
171         {
172             try
173             {
174                 xFlush->flush();
175             }
176             catch(Exception &)
177             {
178                 DBG_ERROR( "flushing of conversion dictionary failed" );
179             }
180         }
181     }
182 }
183 
184 
GetIndexByName_Impl(const OUString & rName)185 sal_Int32 ConvDicNameContainer::GetIndexByName_Impl(
186         const OUString& rName )
187 {
188     sal_Int32 nRes = -1;
189     sal_Int32 nLen = aConvDics.getLength();
190     const uno::Reference< XConversionDictionary > *pDic = aConvDics.getConstArray();
191     for (sal_Int32 i = 0;  i < nLen && nRes == -1;  ++i)
192     {
193         if (rName == pDic[i]->getName())
194             nRes = i;
195     }
196     return nRes;
197 }
198 
199 
GetByName(const OUString & rName)200 uno::Reference< XConversionDictionary > ConvDicNameContainer::GetByName(
201         const OUString& rName )
202 {
203     uno::Reference< XConversionDictionary > xRes;
204     sal_Int32 nIdx = GetIndexByName_Impl( rName );
205     if ( nIdx != -1)
206         xRes = aConvDics.getArray()[nIdx];
207     return xRes;
208 }
209 
210 
getElementType()211 uno::Type SAL_CALL ConvDicNameContainer::getElementType(  )
212     throw (RuntimeException)
213 {
214     MutexGuard  aGuard( GetLinguMutex() );
215     return uno::Type( ::getCppuType( (uno::Reference< XConversionDictionary > *) 0) );
216 }
217 
218 
hasElements()219 sal_Bool SAL_CALL ConvDicNameContainer::hasElements(  )
220     throw (RuntimeException)
221 {
222     MutexGuard  aGuard( GetLinguMutex() );
223     return aConvDics.getLength() > 0;
224 }
225 
226 
getByName(const OUString & rName)227 uno::Any SAL_CALL ConvDicNameContainer::getByName( const OUString& rName )
228     throw (NoSuchElementException, WrappedTargetException, RuntimeException)
229 {
230     MutexGuard  aGuard( GetLinguMutex() );
231     uno::Reference< XConversionDictionary > xRes( GetByName( rName ) );
232     if (!xRes.is())
233         throw NoSuchElementException();
234     return makeAny( xRes );
235 }
236 
237 
getElementNames()238 uno::Sequence< OUString > SAL_CALL ConvDicNameContainer::getElementNames(  )
239     throw (RuntimeException)
240 {
241     MutexGuard  aGuard( GetLinguMutex() );
242 
243     sal_Int32 nLen = aConvDics.getLength();
244     uno::Sequence< OUString > aRes( nLen );
245     OUString *pName = aRes.getArray();
246     const uno::Reference< XConversionDictionary > *pDic = aConvDics.getConstArray();
247     for (sal_Int32 i = 0;  i < nLen;  ++i)
248         pName[i] = pDic[i]->getName();
249     return aRes;
250 }
251 
252 
hasByName(const OUString & rName)253 sal_Bool SAL_CALL ConvDicNameContainer::hasByName( const OUString& rName )
254     throw (RuntimeException)
255 {
256     MutexGuard  aGuard( GetLinguMutex() );
257     return GetByName( rName ).is();
258 }
259 
260 
replaceByName(const OUString & rName,const uno::Any & rElement)261 void SAL_CALL ConvDicNameContainer::replaceByName(
262         const OUString& rName,
263         const uno::Any& rElement )
264     throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException)
265 {
266     MutexGuard  aGuard( GetLinguMutex() );
267 
268     sal_Int32 nRplcIdx = GetIndexByName_Impl( rName );
269     if (nRplcIdx == -1)
270         throw NoSuchElementException();
271     uno::Reference< XConversionDictionary > xNew;
272     rElement >>= xNew;
273     if (!xNew.is() || xNew->getName() != rName)
274         throw IllegalArgumentException();
275     aConvDics.getArray()[ nRplcIdx ] = xNew;
276 }
277 
278 
insertByName(const OUString & rName,const Any & rElement)279 void SAL_CALL ConvDicNameContainer::insertByName(
280         const OUString& rName,
281         const Any& rElement )
282     throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException)
283 {
284     MutexGuard  aGuard( GetLinguMutex() );
285 
286     if (GetByName( rName ).is())
287         throw ElementExistException();
288     uno::Reference< XConversionDictionary > xNew;
289     rElement >>= xNew;
290     if (!xNew.is() || xNew->getName() != rName)
291         throw IllegalArgumentException();
292 
293     sal_Int32 nLen = aConvDics.getLength();
294     aConvDics.realloc( nLen + 1 );
295     aConvDics.getArray()[ nLen ] = xNew;
296 }
297 
298 
removeByName(const OUString & rName)299 void SAL_CALL ConvDicNameContainer::removeByName( const OUString& rName )
300     throw (NoSuchElementException, WrappedTargetException, RuntimeException)
301 {
302     MutexGuard  aGuard( GetLinguMutex() );
303 
304     sal_Int32 nRplcIdx = GetIndexByName_Impl( rName );
305     if (nRplcIdx == -1)
306         throw NoSuchElementException();
307 
308 	// physically remove dictionary
309     uno::Reference< XConversionDictionary > xDel = aConvDics.getArray()[nRplcIdx];
310 	String aName( xDel->getName() );
311     String aDicMainURL( GetConvDicMainURL( aName, GetDictionaryWriteablePath() ) );
312 	INetURLObject aObj( aDicMainURL );
313 	DBG_ASSERT( aObj.GetProtocol() == INET_PROT_FILE, "+HangulHanjaOptionsDialog::OkHdl(): non-file URLs cannot be deleted" );
314 	if( aObj.GetProtocol() == INET_PROT_FILE )
315 	{
316 		try
317 		{
318 			::ucbhelper::Content	aCnt( aObj.GetMainURL( INetURLObject::NO_DECODE ),
319 									uno::Reference< ::com::sun::star::ucb::XCommandEnvironment > () );
320 			aCnt.executeCommand( OUString::createFromAscii( "delete" ), makeAny( sal_Bool( sal_True ) ) );
321 		}
322 		catch( ::com::sun::star::ucb::CommandAbortedException& )
323 		{
324 			DBG_ERRORFILE( "HangulHanjaOptionsDialog::OkHdl(): CommandAbortedException" );
325 		}
326 		catch( ... )
327 		{
328 			DBG_ERRORFILE( "HangulHanjaOptionsDialog::OkHdl(): Any other exception" );
329 		}
330 	}
331 
332     sal_Int32 nLen = aConvDics.getLength();
333     uno::Reference< XConversionDictionary > *pDic = aConvDics.getArray();
334     for (sal_Int32 i = nRplcIdx;  i < nLen - 1;  ++i)
335         pDic[i] = pDic[i + 1];
336     aConvDics.realloc( nLen - 1 );
337 }
338 
339 
AddConvDics(const String & rSearchDirPathURL,const String & rExtension)340 void ConvDicNameContainer::AddConvDics(
341         const String &rSearchDirPathURL,
342         const String &rExtension )
343 {
344     const Sequence< OUString > aDirCnt(
345                 utl::LocalFileHelper::GetFolderContents( rSearchDirPathURL, sal_False ) );
346     const OUString *pDirCnt = aDirCnt.getConstArray();
347     sal_Int32 nEntries = aDirCnt.getLength();
348 
349     for (sal_Int32 i = 0;  i < nEntries;  ++i)
350     {
351         String  aURL( pDirCnt[i] );
352 
353         xub_StrLen nPos  = aURL.SearchBackward('.');
354         String  aExt(aURL.Copy(nPos + 1));
355         aExt.ToLowerAscii();
356         String  aSearchExt( rExtension );
357         aSearchExt.ToLowerAscii();
358         if(aExt != aSearchExt)
359             continue;          // skip other files
360 
361         sal_Int16 nLang;
362         sal_Int16 nConvType;
363         if (IsConvDic( aURL, nLang, nConvType ))
364         {
365             // get decoded dictionary file name
366             INetURLObject aURLObj( aURL );
367             String aDicName = aURLObj.getBase( INetURLObject::LAST_SEGMENT,
368                         true, INetURLObject::DECODE_WITH_CHARSET,
369                         RTL_TEXTENCODING_UTF8 );
370 
371             uno::Reference < XConversionDictionary > xDic;
372             if (nLang == LANGUAGE_KOREAN &&
373                 nConvType == ConversionDictionaryType::HANGUL_HANJA)
374             {
375                 xDic = new HHConvDic( aDicName, aURL );
376             }
377             else if ((nLang == LANGUAGE_CHINESE_SIMPLIFIED || nLang == LANGUAGE_CHINESE_TRADITIONAL) &&
378                       nConvType == ConversionDictionaryType::SCHINESE_TCHINESE)
379             {
380                 xDic = new ConvDic( aDicName, nLang, nConvType, sal_False, aURL );
381             }
382 
383             if (xDic.is())
384             {
385                 uno::Any aAny;
386                 aAny <<= xDic;
387                 insertByName( xDic->getName(), aAny );
388             }
389         }
390     }
391 }
392 
393 ///////////////////////////////////////////////////////////////////////////
394 
395 namespace
396 {
397     struct StaticConvDicList : public rtl::StaticWithInit<
398         uno::Reference<XInterface>, StaticConvDicList> {
operator ()__anonf99d38640111::StaticConvDicList399         uno::Reference<XInterface> operator () () {
400             return (cppu::OWeakObject *) new ConvDicList;
401         }
402     };
403 }
404 
405 
AtExit()406 void ConvDicList::MyAppExitListener::AtExit()
407 {
408     rMyDicList.FlushDics();
409     StaticConvDicList::get().clear();
410 }
411 
ConvDicList()412 ConvDicList::ConvDicList() :
413     aEvtListeners( GetLinguMutex() )
414 {
415     pNameContainer = 0;
416     bDisposing = sal_False;
417 
418     pExitListener = new MyAppExitListener( *this );
419     xExitListener = pExitListener;
420     pExitListener->Activate();
421 }
422 
423 
~ConvDicList()424 ConvDicList::~ConvDicList()
425 {
426     // NameContainer will deleted when the reference xNameContainer
427     // is destroyed.
428     // delete pNameContainer;
429 
430 	if (!bDisposing && pNameContainer)
431 		pNameContainer->FlushDics();
432 
433     pExitListener->Deactivate();
434 }
435 
436 
FlushDics()437 void ConvDicList::FlushDics()
438 {
439     // check only pointer to avoid creating the container when
440     // the dictionaries were not accessed yet
441     if (pNameContainer)
442         pNameContainer->FlushDics();
443 }
444 
445 
GetNameContainer()446 ConvDicNameContainer & ConvDicList::GetNameContainer()
447 {
448     if (!pNameContainer)
449     {
450         pNameContainer = new ConvDicNameContainer( *this );
451         pNameContainer->AddConvDics( GetDictionaryWriteablePath(),
452                                      A2OU( CONV_DIC_EXT ) );
453         xNameContainer = pNameContainer;
454 
455         // access list of text conversion dictionaries to activate
456         SvtLinguOptions aOpt;
457         SvtLinguConfig().GetOptions( aOpt );
458         sal_Int32 nLen = aOpt.aActiveConvDics.getLength();
459         const OUString *pActiveConvDics = aOpt.aActiveConvDics.getConstArray();
460         for (sal_Int32 i = 0;  i < nLen;  ++i)
461         {
462             uno::Reference< XConversionDictionary > xDic =
463                     pNameContainer->GetByName( pActiveConvDics[i] );
464             if (xDic.is())
465                 xDic->setActive( sal_True );
466         }
467 
468 		// since there is no UI to active/deactivate the dictionaries
469 		// for chinese text conversion they should be activated by default
470 		uno::Reference< XConversionDictionary > xS2TDic(
471                     pNameContainer->GetByName( A2OU("ChineseS2T") ), UNO_QUERY );
472 		uno::Reference< XConversionDictionary > xT2SDic(
473                     pNameContainer->GetByName( A2OU("ChineseT2S") ), UNO_QUERY );
474             if (xS2TDic.is())
475                 xS2TDic->setActive( sal_True );
476             if (xT2SDic.is())
477                 xT2SDic->setActive( sal_True );
478 
479     }
480     return *pNameContainer;
481 }
482 
483 
getDictionaryContainer()484 uno::Reference< container::XNameContainer > SAL_CALL ConvDicList::getDictionaryContainer(  ) throw (RuntimeException)
485 {
486     MutexGuard  aGuard( GetLinguMutex() );
487     GetNameContainer();
488     DBG_ASSERT( xNameContainer.is(), "missing name container" );
489     return xNameContainer;
490 }
491 
492 
addNewDictionary(const OUString & rName,const Locale & rLocale,sal_Int16 nConvDicType)493 uno::Reference< XConversionDictionary > SAL_CALL ConvDicList::addNewDictionary(
494         const OUString& rName,
495         const Locale& rLocale,
496         sal_Int16 nConvDicType )
497     throw (NoSupportException, ElementExistException, RuntimeException)
498 {
499     MutexGuard  aGuard( GetLinguMutex() );
500 
501     sal_Int16 nLang = LocaleToLanguage( rLocale );
502 
503     if (GetNameContainer().hasByName( rName ))
504         throw ElementExistException();
505 
506     uno::Reference< XConversionDictionary > xRes;
507     String aDicMainURL( GetConvDicMainURL( rName, GetDictionaryWriteablePath() ) );
508     if (nLang == LANGUAGE_KOREAN &&
509         nConvDicType == ConversionDictionaryType::HANGUL_HANJA)
510     {
511         xRes = new HHConvDic( rName, aDicMainURL );
512     }
513     else if ((nLang == LANGUAGE_CHINESE_SIMPLIFIED || nLang == LANGUAGE_CHINESE_TRADITIONAL) &&
514               nConvDicType == ConversionDictionaryType::SCHINESE_TCHINESE)
515     {
516         xRes = new ConvDic( rName, nLang, nConvDicType, sal_False, aDicMainURL );
517     }
518 
519     if (!xRes.is())
520         throw NoSupportException();
521     else
522     {
523         xRes->setActive( sal_True );
524         uno::Any aAny;
525         aAny <<= xRes;
526         GetNameContainer().insertByName( rName, aAny );
527     }
528     return xRes;
529 }
530 
531 
queryConversions(const OUString & rText,sal_Int32 nStartPos,sal_Int32 nLength,const Locale & rLocale,sal_Int16 nConversionDictionaryType,ConversionDirection eDirection,sal_Int32 nTextConversionOptions)532 uno::Sequence< OUString > SAL_CALL ConvDicList::queryConversions(
533         const OUString& rText,
534         sal_Int32 nStartPos,
535         sal_Int32 nLength,
536         const Locale& rLocale,
537         sal_Int16 nConversionDictionaryType,
538         ConversionDirection eDirection,
539         sal_Int32 nTextConversionOptions )
540     throw (IllegalArgumentException, NoSupportException, RuntimeException)
541 {
542     MutexGuard  aGuard( GetLinguMutex() );
543 
544     /*sal_Int16 nLang = LocaleToLanguage( rLocale );*/
545 
546     sal_Int32 nCount = 0;
547     uno::Sequence< OUString > aRes( 20 );
548     OUString *pRes = aRes.getArray();
549 
550 	sal_Bool bSupported = sal_False;
551     sal_Int32 nLen = GetNameContainer().GetCount();
552     for (sal_Int32 i = 0;  i < nLen;  ++i)
553     {
554         const uno::Reference< XConversionDictionary > xDic( GetNameContainer().GetByIndex(i) );
555 		sal_Bool bMatch =   xDic.is()  &&
556 							xDic->getLocale() == rLocale  &&
557 							xDic->getConversionType() == nConversionDictionaryType;
558 		bSupported |= bMatch;
559         if (bMatch  &&  xDic->isActive())
560         {
561             Sequence< OUString > aNewConv( xDic->getConversions(
562                                 rText, nStartPos, nLength,
563                                 eDirection, nTextConversionOptions ) );
564             sal_Int32 nNewLen = aNewConv.getLength();
565             if (nNewLen > 0)
566             {
567                 if (nCount + nNewLen > aRes.getLength())
568                 {
569                     aRes.realloc( nCount + nNewLen + 20 );
570                     pRes = aRes.getArray();
571                 }
572                 const OUString *pNewConv = aNewConv.getConstArray();
573                 for (sal_Int32 k = 0;  k < nNewLen;  ++k)
574                     pRes[nCount++] = pNewConv[k];
575             }
576         }
577     }
578 
579 	if (!bSupported)
580         throw NoSupportException();
581 
582     aRes.realloc( nCount );
583     return aRes;
584 }
585 
586 
queryMaxCharCount(const Locale & rLocale,sal_Int16 nConversionDictionaryType,ConversionDirection eDirection)587 sal_Int16 SAL_CALL ConvDicList::queryMaxCharCount(
588         const Locale& rLocale,
589         sal_Int16 nConversionDictionaryType,
590         ConversionDirection eDirection )
591     throw (RuntimeException)
592 {
593     MutexGuard  aGuard( GetLinguMutex() );
594 
595     sal_Int16 nRes = 0;
596     GetNameContainer();
597     sal_Int32 nLen = GetNameContainer().GetCount();
598     for (sal_Int32 i = 0;  i < nLen;  ++i)
599     {
600         const uno::Reference< XConversionDictionary > xDic( GetNameContainer().GetByIndex(i) );
601         if (xDic.is()  &&
602             xDic->getLocale() == rLocale  &&
603             xDic->getConversionType() == nConversionDictionaryType)
604         {
605             sal_Int16 nC = xDic->getMaxCharCount( eDirection );
606             if (nC > nRes)
607                 nRes = nC;
608         }
609     }
610     return nRes;
611 }
612 
613 
dispose()614 void SAL_CALL ConvDicList::dispose(  )
615     throw (RuntimeException)
616 {
617     MutexGuard  aGuard( GetLinguMutex() );
618     if (!bDisposing)
619     {
620         bDisposing = sal_True;
621         EventObject aEvtObj( (XConversionDictionaryList *) this );
622         aEvtListeners.disposeAndClear( aEvtObj );
623 
624         FlushDics();
625     }
626 }
627 
628 
addEventListener(const uno::Reference<XEventListener> & rxListener)629 void SAL_CALL ConvDicList::addEventListener(
630         const uno::Reference< XEventListener >& rxListener )
631     throw (RuntimeException)
632 {
633     MutexGuard  aGuard( GetLinguMutex() );
634     if (!bDisposing && rxListener.is())
635         aEvtListeners.addInterface( rxListener );
636 }
637 
638 
removeEventListener(const uno::Reference<XEventListener> & rxListener)639 void SAL_CALL ConvDicList::removeEventListener(
640         const uno::Reference< XEventListener >& rxListener )
641     throw (RuntimeException)
642 {
643     MutexGuard  aGuard( GetLinguMutex() );
644     if (!bDisposing && rxListener.is())
645         aEvtListeners.removeInterface( rxListener );
646 }
647 
648 
getImplementationName()649 OUString SAL_CALL ConvDicList::getImplementationName(  )
650     throw (RuntimeException)
651 {
652     MutexGuard  aGuard( GetLinguMutex() );
653     return getImplementationName_Static();
654 }
655 
656 
supportsService(const OUString & rServiceName)657 sal_Bool SAL_CALL ConvDicList::supportsService( const OUString& rServiceName )
658     throw (RuntimeException)
659 {
660     MutexGuard  aGuard( GetLinguMutex() );
661     return rServiceName.equalsAscii( SN_CONV_DICTIONARY_LIST );
662 }
663 
664 
getSupportedServiceNames()665 uno::Sequence< OUString > SAL_CALL ConvDicList::getSupportedServiceNames(  )
666     throw (RuntimeException)
667 {
668     MutexGuard  aGuard( GetLinguMutex() );
669     return getSupportedServiceNames_Static();
670 }
671 
672 
getSupportedServiceNames_Static()673 uno::Sequence< OUString > ConvDicList::getSupportedServiceNames_Static()
674     throw()
675 {
676     uno::Sequence< OUString > aSNS( 1 );
677     aSNS.getArray()[0] = A2OU( SN_CONV_DICTIONARY_LIST );
678     return aSNS;
679 }
680 
681 
682 ///////////////////////////////////////////////////////////////////////////
683 
ConvDicList_CreateInstance(const uno::Reference<XMultiServiceFactory> &)684 uno::Reference< uno::XInterface > SAL_CALL ConvDicList_CreateInstance(
685         const uno::Reference< XMultiServiceFactory > & /*rSMgr*/ )
686     throw(Exception)
687 {
688     return StaticConvDicList::get();
689 }
690 
ConvDicList_getFactory(const sal_Char * pImplName,XMultiServiceFactory * pServiceManager,void *)691 void * SAL_CALL ConvDicList_getFactory(
692         const sal_Char * pImplName,
693         XMultiServiceFactory * pServiceManager, void *  )
694 {
695     void * pRet = 0;
696     if ( !ConvDicList::getImplementationName_Static().compareToAscii( pImplName ) )
697     {
698         uno::Reference< XSingleServiceFactory > xFactory =
699             cppu::createOneInstanceFactory(
700                 pServiceManager,
701                 ConvDicList::getImplementationName_Static(),
702                 ConvDicList_CreateInstance,
703                 ConvDicList::getSupportedServiceNames_Static());
704         // acquire, because we return an interface pointer instead of a reference
705         xFactory->acquire();
706         pRet = xFactory.get();
707     }
708     return pRet;
709 }
710 
711 ///////////////////////////////////////////////////////////////////////////
712 
713