xref: /aoo41x/main/editeng/source/misc/unolingu.cxx (revision cdf0e10c)
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_editeng.hxx"
30 
31 #include <map>
32 #include <set>
33 #include <vector>
34 #include <slist>
35 #include <memory>
36 #include <editeng/unolingu.hxx>
37 #include <tools/debug.hxx>
38 #include <tools/urlobj.hxx>
39 #include <rtl/logfile.hxx>
40 #include <unotools/pathoptions.hxx>
41 #include <com/sun/star/frame/XModel.hpp>
42 #include <com/sun/star/frame/XStorable.hpp>
43 #include <com/sun/star/lang/XEventListener.hpp>
44 #include <com/sun/star/linguistic2/XAvailableLocales.hpp>
45 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
46 #include <com/sun/star/ucb/XContentAccess.hpp>
47 #include <com/sun/star/ucb/XSortedDynamicResultSetFactory.hpp>
48 #include <com/sun/star/ucb/NumberedSortingInfo.hpp>
49 #include <com/sun/star/ucb/XContentAccess.hpp>
50 #include <com/sun/star/sdbc/XResultSet.hpp>
51 #include <com/sun/star/sdbc/XRow.hpp>
52 #include <com/sun/star/util/DateTime.hpp>
53 
54 #include <comphelper/processfactory.hxx>
55 #include <cppuhelper/implbase1.hxx>	// helper for implementations
56 #include <i18npool/mslangid.hxx>
57 #include <unotools/lingucfg.hxx>
58 #include <unotools/ucbhelper.hxx>
59 #include <unotools/localfilehelper.hxx>
60 #include <ucbhelper/commandenvironment.hxx>
61 #include <ucbhelper/content.hxx>
62 #include <comphelper/processfactory.hxx>
63 #include <vcl/msgbox.hxx>
64 #include <tools/shl.hxx>
65 #include <linguistic/misc.hxx>
66 #include <editeng/eerdll.hxx>
67 #include <editeng/editrids.hrc>
68 
69 using namespace ::rtl;
70 using namespace ::comphelper;
71 using namespace ::linguistic;
72 using namespace ::com::sun::star;
73 using namespace ::com::sun::star::util;
74 using namespace ::com::sun::star::uno;
75 using namespace ::com::sun::star::lang;
76 using namespace ::com::sun::star::beans;
77 using namespace ::com::sun::star::frame;
78 using namespace ::com::sun::star::linguistic2;
79 
80 #define CSS com::sun::star
81 
82 ///////////////////////////////////////////////////////////////////////////
83 
84 
85 static uno::Reference< XLinguServiceManager > GetLngSvcMgr_Impl()
86 {
87 	uno::Reference< XLinguServiceManager > xRes;
88 	uno::Reference< XMultiServiceFactory >  xMgr = getProcessServiceFactory();
89 	if (xMgr.is())
90 	{
91 		xRes = uno::Reference< XLinguServiceManager > ( xMgr->createInstance(
92 				OUString( RTL_CONSTASCII_USTRINGPARAM(
93 					"com.sun.star.linguistic2.LinguServiceManager" ) ) ), UNO_QUERY ) ;
94 	}
95 	return xRes;
96 }
97 
98 ///////////////////////////////////////////////////////////////////////////
99 
100 sal_Bool lcl_FindEntry( const OUString &rEntry, const Sequence< OUString > &rCfgSvcs )
101 {
102     sal_Int32 nRes = -1;
103     sal_Int32 nEntries = rCfgSvcs.getLength();
104     const OUString *pEntry = rCfgSvcs.getConstArray();
105     for (sal_Int32 i = 0;  i < nEntries && nRes == -1;  ++i)
106     {
107         if (rEntry == pEntry[i])
108             nRes = i;
109     }
110     return nRes != -1;
111 }
112 
113 
114 Sequence< OUString > lcl_RemoveMissingEntries(
115         const Sequence< OUString > &rCfgSvcs,
116         const Sequence< OUString > &rAvailSvcs )
117 {
118     Sequence< OUString > aRes( rCfgSvcs.getLength() );
119     OUString *pRes = aRes.getArray();
120     sal_Int32 nCnt = 0;
121 
122     sal_Int32 nEntries = rCfgSvcs.getLength();
123     const OUString *pEntry = rCfgSvcs.getConstArray();
124     for (sal_Int32 i = 0;  i < nEntries;  ++i)
125     {
126         if (pEntry[i].getLength() && lcl_FindEntry( pEntry[i], rAvailSvcs ))
127             pRes[ nCnt++ ] = pEntry[i];
128     }
129 
130     aRes.realloc( nCnt );
131     return aRes;
132 }
133 
134 
135 Sequence< OUString > lcl_GetLastFoundSvcs(
136         SvtLinguConfig &rCfg,
137         const OUString &rLastFoundList ,
138         const Locale &rAvailLocale )
139 {
140     Sequence< OUString > aRes;
141 
142     OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString(
143                                 SvxLocaleToLanguage( rAvailLocale ) ) );
144 
145     Sequence< OUString > aNodeNames( rCfg.GetNodeNames(rLastFoundList) );
146     sal_Bool bFound = lcl_FindEntry( aCfgLocaleStr, aNodeNames);
147 
148     if (bFound)
149     {
150         Sequence< OUString > aNames(1);
151         OUString &rNodeName = aNames.getArray()[0];
152         rNodeName = rLastFoundList;
153         rNodeName += OUString::valueOf( (sal_Unicode)'/' );
154         rNodeName += aCfgLocaleStr;
155         Sequence< Any > aValues( rCfg.GetProperties( aNames ) );
156 #if OSL_DEBUG_LEVEL > 1
157         const Any *pValue;
158         pValue = aValues.getConstArray();
159 #endif
160         if (aValues.getLength())
161         {
162             DBG_ASSERT( aValues.getLength() == 1, "unexpected length of sequence" );
163             Sequence< OUString > aSvcImplNames;
164             if (aValues.getConstArray()[0] >>= aSvcImplNames)
165                 aRes = aSvcImplNames;
166             else
167             {
168                 DBG_ERROR( "type mismatch" );
169             }
170         }
171     }
172 
173     return aRes;
174 }
175 
176 
177 Sequence< OUString > lcl_GetNewEntries(
178         const Sequence< OUString > &rLastFoundSvcs,
179         const Sequence< OUString > &rAvailSvcs )
180 {
181     sal_Int32 nLen = rAvailSvcs.getLength();
182     Sequence< OUString > aRes( nLen );
183     OUString *pRes = aRes.getArray();
184     sal_Int32 nCnt = 0;
185 
186     const OUString *pEntry = rAvailSvcs.getConstArray();
187     for (sal_Int32 i = 0;  i < nLen;  ++i)
188     {
189         if (pEntry[i].getLength() && !lcl_FindEntry( pEntry[i], rLastFoundSvcs ))
190             pRes[ nCnt++ ] = pEntry[i];
191     }
192 
193     aRes.realloc( nCnt );
194     return aRes;
195 }
196 
197 
198 Sequence< OUString > lcl_MergeSeq(
199         const Sequence< OUString > &rCfgSvcs,
200         const Sequence< OUString > &rNewSvcs )
201 {
202     Sequence< OUString > aRes( rCfgSvcs.getLength() + rNewSvcs.getLength() );
203     OUString *pRes = aRes.getArray();
204     sal_Int32 nCnt = 0;
205 
206     for (sal_Int32 k = 0;  k < 2;  ++k)
207     {
208 		// add previously configuerd service first and append
209 		// new found services at the end
210         const Sequence< OUString > &rSeq = k == 0 ? rCfgSvcs : rNewSvcs;
211 
212 		sal_Int32 nLen = rSeq.getLength();
213         const OUString *pEntry = rSeq.getConstArray();
214         for (sal_Int32 i = 0;  i < nLen;  ++i)
215         {
216             if (pEntry[i].getLength() && !lcl_FindEntry( pEntry[i], aRes ))
217                 pRes[ nCnt++ ] = pEntry[i];
218         }
219     }
220 
221     aRes.realloc( nCnt );
222     return aRes;
223 }
224 
225 ///////////////////////////////////////////////////////////////////////////
226 
227 // static member initialization
228 sal_Int16 SvxLinguConfigUpdate::nNeedUpdating = -1;
229 sal_Int32 SvxLinguConfigUpdate::nCurrentDataFilesChangedCheckValue = -1;
230 
231 void SvxLinguConfigUpdate::UpdateAll( sal_Bool bForceCheck )
232 {
233     RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::UpdateAll" );
234 
235     if (IsNeedUpdateAll( bForceCheck ))
236     {
237         typedef OUString OUstring_t;
238         typedef Sequence< OUString > Sequence_OUString_t;
239         typedef std::vector< OUstring_t > OUString_vector_t;
240         typedef std::set< OUstring_t > OUString_set_t;
241         std::vector< OUString_vector_t > aVector;
242         typedef std::map< OUstring_t, Sequence_OUString_t > list_entry_map_t;
243 
244         RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::UpdateAll - updating..." );
245 
246         DBG_ASSERT( nNeedUpdating == 1, "SvxLinguConfigUpdate::UpdateAll already updated!" );
247 
248         uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
249         DBG_ASSERT( xLngSvcMgr.is(), "service manager missing");
250         if (!xLngSvcMgr.is())
251             return;
252 
253         SvtLinguConfig aCfg;
254 
255 		const int nNumServices = 4;
256         const sal_Char * apServices[nNumServices]       =  { SN_SPELLCHECKER, SN_GRAMMARCHECKER, SN_HYPHENATOR, SN_THESAURUS };
257         const sal_Char * apCurLists[nNumServices]       =  { "ServiceManager/SpellCheckerList",       "ServiceManager/GrammarCheckerList",       "ServiceManager/HyphenatorList",       "ServiceManager/ThesaurusList" };
258         const sal_Char * apLastFoundLists[nNumServices] =  { "ServiceManager/LastFoundSpellCheckers", "ServiceManager/LastFoundGrammarCheckers", "ServiceManager/LastFoundHyphenators", "ServiceManager/LastFoundThesauri" };
259 
260         // usage of indices as above: 0 = spell checker, 1 = grammar checker, 2 = hyphenator, 3 = thesaurus
261         std::vector< list_entry_map_t > aLastFoundSvcs(nNumServices);
262         std::vector< list_entry_map_t > aCurSvcs(nNumServices);
263 
264         for (int k = 0;  k < nNumServices;  ++k)
265         {
266             OUString aService( A2OU( apServices[k] ) );
267             OUString aActiveList( A2OU( apCurLists[k] ) );
268             OUString aLastFoundList( A2OU( apLastFoundLists[k] ) );
269             sal_Int32 i;
270 
271             //
272             // remove configured but not available language/services entries
273             //
274             Sequence< OUString > aNodeNames( aCfg.GetNodeNames( aActiveList ) );   // list of configured locales
275             sal_Int32 nNodeNames = aNodeNames.getLength();
276             const OUString *pNodeName = aNodeNames.getConstArray();
277             for (i = 0;  i < nNodeNames;  ++i)
278             {
279                 Locale aLocale( SvxCreateLocale( MsLangId::convertIsoStringToLanguage(pNodeName[i]) ) );
280                 Sequence< OUString > aCfgSvcs(
281                         xLngSvcMgr->getConfiguredServices( aService, aLocale ));
282                 Sequence< OUString > aAvailSvcs(
283                         xLngSvcMgr->getAvailableServices( aService, aLocale ));
284 #if OSL_DEBUG_LEVEL > 1
285                 const OUString * pCfgSvcs   = aCfgSvcs.getConstArray();;
286                 const OUString * pAvailSvcs = aAvailSvcs.getConstArray();;
287                 (void) pCfgSvcs;
288                 (void) pAvailSvcs;
289 #endif
290                 aCfgSvcs = lcl_RemoveMissingEntries( aCfgSvcs, aAvailSvcs );
291 
292                 aCurSvcs[k][ pNodeName[i] ] = aCfgSvcs;
293             }
294 
295             //
296             // add new available language/servcice entries
297             //
298             uno::Reference< XAvailableLocales > xAvail( xLngSvcMgr, UNO_QUERY );
299             Sequence< Locale > aAvailLocales( xAvail->getAvailableLocales(aService) );
300             sal_Int32 nAvailLocales = aAvailLocales.getLength();
301             const Locale *pAvailLocale = aAvailLocales.getConstArray();
302             for (i = 0;  i < nAvailLocales;  ++i)
303             {
304                 Sequence< OUString > aAvailSvcs(
305                         xLngSvcMgr->getAvailableServices( aService, pAvailLocale[i] ));
306                 Sequence< OUString > aLastSvcs(
307                         lcl_GetLastFoundSvcs( aCfg, aLastFoundList , pAvailLocale[i] ));
308                 Sequence< OUString > aNewSvcs =
309                         lcl_GetNewEntries( aLastSvcs, aAvailSvcs );
310 #if OSL_DEBUG_LEVEL > 1
311                 const OUString * pAvailSvcs = aAvailSvcs.getConstArray();
312                 const OUString * pLastSvcs  = aLastSvcs.getConstArray();
313                 const OUString * pNewSvcs   = aNewSvcs.getConstArray();
314                 (void) pAvailSvcs;
315                 (void) pLastSvcs;
316                 (void) pNewSvcs;
317 #endif
318 
319                 OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString(
320                                             SvxLocaleToLanguage( pAvailLocale[i] ) ) );
321                 Sequence< OUString > aCfgSvcs( aCurSvcs[k][ aCfgLocaleStr ] );
322 
323                 // merge services list (previously configured to be listed first).
324 				aCfgSvcs = lcl_MergeSeq( aCfgSvcs, aNewSvcs );
325 
326 /*
327 				// there is at most one Hyphenator per language allowed
328 				// to be configured, thus we only use the first one found.
329 				if (k == 2 && aCfgSvcs.getLength() > 1)
330 					aCfgSvcs.realloc(1);
331 */
332                 aCurSvcs[k][ aCfgLocaleStr ] = aCfgSvcs;
333             }
334 
335             //
336             // set last found services to currently available ones
337             //
338             for (i = 0;  i < nAvailLocales;  ++i)
339             {
340                 Sequence< OUString > aSvcImplNames(
341                         xLngSvcMgr->getAvailableServices( aService, pAvailLocale[i] ) );
342 
343 #if OSL_DEBUG_LEVEL > 1
344                 sal_Int32 nSvcs = aSvcImplNames.getLength();
345                 const OUString *pSvcImplName = aSvcImplNames.getConstArray();
346                 for (sal_Int32 j = 0;  j < nSvcs;  ++j)
347                 {
348                     OUString aImplName( pSvcImplName[j] );
349                 }
350 #endif
351 
352                 OUString aCfgLocaleStr( MsLangId::convertLanguageToIsoString(
353                                             SvxLocaleToLanguage( pAvailLocale[i] ) ) );
354 				aLastFoundSvcs[k][ aCfgLocaleStr ] = aSvcImplNames;
355             }
356         }
357 
358         //
359         // write new data back to configuration
360         //
361         for (int k = 0;  k < nNumServices;  ++k)
362         {
363             for (int i = 0;  i < 2;  ++i)
364             {
365                 const sal_Char *pSubNodeName = (i == 0) ? apCurLists[k] : apLastFoundLists[k];
366                 OUString aSubNodeName( A2OU(pSubNodeName) );
367 
368 				list_entry_map_t &rCurMap = (i == 0) ? aCurSvcs[k] : aLastFoundSvcs[k];
369                 list_entry_map_t::const_iterator aIt( rCurMap.begin() );
370                 sal_Int32 nVals = static_cast< sal_Int32 >( rCurMap.size() );
371                 Sequence< PropertyValue > aNewValues( nVals );
372                 PropertyValue *pNewValue = aNewValues.getArray();
373                 while (aIt != rCurMap.end())
374                 {
375 					OUString aCfgEntryName( aSubNodeName );
376 	                aCfgEntryName += OUString::valueOf( (sal_Unicode) '/' );
377 					aCfgEntryName += (*aIt).first;
378 
379 #if OSL_DEBUG_LEVEL > 1
380                     Sequence< OUString > aSvcImplNames( (*aIt).second );
381                     sal_Int32 nSvcs = aSvcImplNames.getLength();
382                     const OUString *pSvcImplName = aSvcImplNames.getConstArray();
383                     for (sal_Int32 j = 0;  j < nSvcs;  ++j)
384                     {
385                         OUString aImplName( pSvcImplName[j] );
386                     }
387 #endif
388                     pNewValue->Name  = aCfgEntryName;
389                     pNewValue->Value <<= (*aIt).second;
390                     ++pNewValue;
391                     ++aIt;
392                 }
393                 DBG_ASSERT( pNewValue - aNewValues.getArray() == nVals,
394                         "possible mismatch of sequence size and property number" );
395 
396                 {
397                     RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::UpdateAll - ReplaceSetProperties" );
398                     // add new or replace existing entries.
399                     sal_Bool bRes = aCfg.ReplaceSetProperties( aSubNodeName, aNewValues );
400                     if (!bRes)
401                     {
402 #if OSL_DEBUG_LEVEL > 1
403                         DBG_ERROR( "failed to set new configuration values" );
404 #endif
405                     }
406                 }
407             }
408         }
409 		DBG_ASSERT( nCurrentDataFilesChangedCheckValue != -1, "SvxLinguConfigUpdate::UpdateAll DataFilesChangedCheckValue not yet calculated!" );
410 		Any aAny;
411 
412 		// for the time being (developer builds until OOo 3.0)
413 		// we should always check for everything available
414 		// otherwise we may miss a new installed extension dicitonary
415 		// just because e.g. the spellchecker is not asked what
416 		// languages it does support currently...
417 		// Since the check is on-demand occuring and executed once it should
418 		// not be too troublesome.
419 		// In OOo 3.0 we will not need the respective code anymore at all.
420 //		aAny <<= nCurrentDataFilesChangedCheckValue;
421 		aAny <<= (sal_Int32) -1;	// keep the value set to 'need to check'
422 
423 		aCfg.SetProperty( A2OU( "DataFilesChangedCheckValue" ), aAny );
424 
425 		//! Note 1: the new values are commited when the 'aCfg' object
426 		//!		gets destroyed.
427 		//! Note 2: the new settings in the configuration get applied
428 		//!		because the 'LngSvcMgr' (in linguistic/source/lngsvcmgr.hxx)
429 		//!		listens to the configuration for changes of the relevant
430 		//!		properties and then applies the new settings.
431 
432 		// nothing needs to be done anymore
433         nNeedUpdating = 0;
434     }
435 }
436 
437 
438 sal_Int32 SvxLinguConfigUpdate::CalcDataFilesChangedCheckValue()
439 {
440     RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::CalcDataFilesChangedCheckValue" );
441 
442     sal_Int32 nHashVal = 0;
443     // nothing to be checked anymore since those old directory paths are gone by now
444     return nHashVal;
445 }
446 
447 
448 sal_Bool SvxLinguConfigUpdate::IsNeedUpdateAll( sal_Bool bForceCheck )
449 {
450     RTL_LOGFILE_CONTEXT( aLog, "svx: SvxLinguConfigUpdate::IsNeedUpdateAll" );
451     if (nNeedUpdating == -1 || bForceCheck )    // need to check if updating is necessary
452     {
453         // calculate hash value for current data files
454         nCurrentDataFilesChangedCheckValue = CalcDataFilesChangedCheckValue();
455 
456         // compare hash value and check value to see if anything has changed
457         // and thus the configuration needs to be updated
458         SvtLinguOptions aLinguOpt;
459         SvtLinguConfig aCfg;
460         aCfg.GetOptions( aLinguOpt );
461         nNeedUpdating = (nCurrentDataFilesChangedCheckValue == aLinguOpt.nDataFilesChangedCheckValue) ? 0 : 1;
462     }
463     DBG_ASSERT( nNeedUpdating != -1,
464             "need for linguistic configuration update should have been already checked." );
465 
466     return nNeedUpdating == 1;
467 }
468 
469 ///////////////////////////////////////////////////////////////////////////
470 
471 
472 //! Dummy implementation in order to avoid loading of lingu DLL
473 //! when only the XSupportedLocales interface is used.
474 //! The dummy accesses the real implementation (and thus loading the DLL)
475 //! when "real" work needs to be done only.
476 class ThesDummy_Impl :
477     public cppu::WeakImplHelper1< XThesaurus >
478 {
479     uno::Reference< XThesaurus >     xThes;      // the real one...
480     Sequence< Locale >         *pLocaleSeq;
481 
482     void GetCfgLocales();
483 
484     void GetThes_Impl();
485 
486 public:
487     ThesDummy_Impl() : pLocaleSeq(0)  {}
488     ~ThesDummy_Impl();
489 
490     // XSupportedLocales
491     virtual ::com::sun::star::uno::Sequence<
492 			::com::sun::star::lang::Locale > SAL_CALL
493 		getLocales()
494 			throw(::com::sun::star::uno::RuntimeException);
495     virtual sal_Bool SAL_CALL
496         hasLocale( const ::com::sun::star::lang::Locale& rLocale )
497 			throw(::com::sun::star::uno::RuntimeException);
498 
499 	// XThesaurus
500     virtual ::com::sun::star::uno::Sequence<
501 			::com::sun::star::uno::Reference<
502 				::com::sun::star::linguistic2::XMeaning > > SAL_CALL
503         queryMeanings( const ::rtl::OUString& rTerm,
504                 const ::com::sun::star::lang::Locale& rLocale,
505                 const ::com::sun::star::beans::PropertyValues& rProperties )
506 			throw(::com::sun::star::lang::IllegalArgumentException,
507 				  ::com::sun::star::uno::RuntimeException);
508 };
509 
510 
511 ThesDummy_Impl::~ThesDummy_Impl()
512 {
513     delete pLocaleSeq;
514 }
515 
516 
517 void ThesDummy_Impl::GetCfgLocales()
518 {
519     if (!pLocaleSeq)
520     {
521         SvtLinguConfig aCfg;
522         String  aNode( A2OU( "ServiceManager/ThesaurusList" ) );
523         Sequence < OUString > aNodeNames( aCfg.GetNodeNames( aNode ) );
524         const OUString *pNodeNames = aNodeNames.getConstArray();
525         sal_Int32 nLen = aNodeNames.getLength();
526         pLocaleSeq = new Sequence< Locale >( nLen );
527         Locale *pLocale = pLocaleSeq->getArray();
528         for (sal_Int32 i = 0;  i < nLen;  ++i)
529         {
530             pLocale[i] = SvxCreateLocale(
531                             MsLangId::convertIsoStringToLanguage( pNodeNames[i] ) );
532         }
533     }
534 }
535 
536 
537 void ThesDummy_Impl::GetThes_Impl()
538 {
539     // update configuration before accessing the service
540     if (SvxLinguConfigUpdate::IsNeedUpdateAll())
541         SvxLinguConfigUpdate::UpdateAll();
542 
543     if (!xThes.is())
544     {
545         uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
546         if (xLngSvcMgr.is())
547             xThes = xLngSvcMgr->getThesaurus();
548 
549         if (xThes.is())
550         {
551             // no longer needed...
552             delete pLocaleSeq;    pLocaleSeq = 0;
553         }
554     }
555 }
556 
557 
558 uno::Sequence< lang::Locale > SAL_CALL
559         ThesDummy_Impl::getLocales()
560             throw(uno::RuntimeException)
561 {
562     if (!SvxLinguConfigUpdate::IsNeedUpdateAll())   // configuration already update and thus lingu DLL's already loaded ?
563         GetThes_Impl();
564     if (xThes.is())
565         return xThes->getLocales();
566     else if (!pLocaleSeq)       // if not already loaded save startup time by avoiding loading them now
567         GetCfgLocales();
568     return *pLocaleSeq;
569 }
570 
571 
572 sal_Bool SAL_CALL
573         ThesDummy_Impl::hasLocale( const lang::Locale& rLocale )
574             throw(uno::RuntimeException)
575 {
576     if (!SvxLinguConfigUpdate::IsNeedUpdateAll())   // configuration already update and thus lingu DLL's already loaded ?
577         GetThes_Impl();
578     if (xThes.is())
579         return xThes->hasLocale( rLocale );
580     else if (!pLocaleSeq)       // if not already loaded save startup time by avoiding loading them now
581         GetCfgLocales();
582         GetCfgLocales();
583     sal_Bool bFound = sal_False;
584     sal_Int32 nLen = pLocaleSeq->getLength();
585     const Locale *pLocale = pLocaleSeq->getConstArray();
586     const Locale *pEnd = pLocale + nLen;
587     for ( ;  pLocale < pEnd  &&  !bFound;  ++pLocale)
588     {
589         bFound = pLocale->Language == rLocale.Language  &&
590                  pLocale->Country  == rLocale.Country   &&
591                  pLocale->Variant  == rLocale.Variant;
592     }
593     return bFound;
594 }
595 
596 
597 uno::Sequence< uno::Reference< linguistic2::XMeaning > > SAL_CALL
598         ThesDummy_Impl::queryMeanings(
599                 const rtl::OUString& rTerm,
600                 const lang::Locale& rLocale,
601                 const beans::PropertyValues& rProperties )
602             throw(lang::IllegalArgumentException,
603                   uno::RuntimeException)
604 {
605     GetThes_Impl();
606     uno::Sequence< uno::Reference< linguistic2::XMeaning > > aRes;
607     DBG_ASSERT( xThes.is(), "Thesaurus missing" );
608     if (xThes.is())
609         aRes = xThes->queryMeanings( rTerm, rLocale, rProperties );
610     return aRes;
611 }
612 
613 
614 ///////////////////////////////////////////////////////////////////////////
615 
616 
617 //! Dummy implementation in order to avoid loading of lingu DLL.
618 //! The dummy accesses the real implementation (and thus loading the DLL)
619 //! when it needs to be done only.
620 class SpellDummy_Impl :
621     public cppu::WeakImplHelper1< XSpellChecker1 >
622 {
623     uno::Reference< XSpellChecker1 >     xSpell;      // the real one...
624 
625     void    GetSpell_Impl();
626 
627 public:
628 
629 	// XSupportedLanguages (for XSpellChecker1)
630     virtual ::com::sun::star::uno::Sequence< sal_Int16 > SAL_CALL
631 		getLanguages()
632 			throw(::com::sun::star::uno::RuntimeException);
633     virtual sal_Bool SAL_CALL
634 		hasLanguage( sal_Int16 nLanguage )
635 			throw(::com::sun::star::uno::RuntimeException);
636 
637 	// XSpellChecker1 (same as XSpellChecker but sal_Int16 for language)
638 	virtual sal_Bool SAL_CALL
639         isValid( const ::rtl::OUString& rWord, sal_Int16 nLanguage,
640                 const ::com::sun::star::beans::PropertyValues& rProperties )
641 			throw(::com::sun::star::lang::IllegalArgumentException,
642 				  ::com::sun::star::uno::RuntimeException);
643 	virtual ::com::sun::star::uno::Reference<
644 			::com::sun::star::linguistic2::XSpellAlternatives > SAL_CALL
645         spell( const ::rtl::OUString& rWord, sal_Int16 nLanguage,
646                 const ::com::sun::star::beans::PropertyValues& rProperties )
647 			throw(::com::sun::star::lang::IllegalArgumentException,
648 				  ::com::sun::star::uno::RuntimeException);
649 };
650 
651 
652 void SpellDummy_Impl::GetSpell_Impl()
653 {
654     // update configuration before accessing the service
655     if (SvxLinguConfigUpdate::IsNeedUpdateAll())
656         SvxLinguConfigUpdate::UpdateAll();
657 
658     if (!xSpell.is())
659     {
660         uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
661         if (xLngSvcMgr.is())
662             xSpell = uno::Reference< XSpellChecker1 >( xLngSvcMgr->getSpellChecker(), UNO_QUERY );
663     }
664 }
665 
666 
667 uno::Sequence< sal_Int16 > SAL_CALL
668     SpellDummy_Impl::getLanguages()
669         throw(uno::RuntimeException)
670 {
671     GetSpell_Impl();
672     if (xSpell.is())
673         return xSpell->getLanguages();
674     else
675         return uno::Sequence< sal_Int16 >();
676 }
677 
678 
679 sal_Bool SAL_CALL
680     SpellDummy_Impl::hasLanguage( sal_Int16 nLanguage )
681         throw(uno::RuntimeException)
682 {
683     GetSpell_Impl();
684     sal_Bool bRes = sal_False;
685     if (xSpell.is())
686         bRes = xSpell->hasLanguage( nLanguage );
687     return bRes;
688 }
689 
690 
691 sal_Bool SAL_CALL
692     SpellDummy_Impl::isValid( const rtl::OUString& rWord, sal_Int16 nLanguage,
693             const beans::PropertyValues& rProperties )
694         throw(lang::IllegalArgumentException,
695               uno::RuntimeException)
696 {
697     GetSpell_Impl();
698     sal_Bool bRes = sal_True;
699     if (xSpell.is())
700         bRes = xSpell->isValid( rWord, nLanguage, rProperties );
701     return bRes;
702 }
703 
704 
705 uno::Reference< linguistic2::XSpellAlternatives > SAL_CALL
706     SpellDummy_Impl::spell( const rtl::OUString& rWord, sal_Int16 nLanguage,
707             const beans::PropertyValues& rProperties )
708         throw(lang::IllegalArgumentException,
709               uno::RuntimeException)
710 {
711     GetSpell_Impl();
712     uno::Reference< linguistic2::XSpellAlternatives > xRes;
713     if (xSpell.is())
714         xRes = xSpell->spell( rWord, nLanguage, rProperties );
715     return xRes;
716 }
717 
718 
719 ///////////////////////////////////////////////////////////////////////////
720 
721 
722 //! Dummy implementation in order to avoid loading of lingu DLL.
723 //! The dummy accesses the real implementation (and thus loading the DLL)
724 //! when it needs to be done only.
725 class HyphDummy_Impl :
726     public cppu::WeakImplHelper1< XHyphenator >
727 {
728     uno::Reference< XHyphenator >     xHyph;      // the real one...
729 
730     void    GetHyph_Impl();
731 
732 public:
733 
734     // XSupportedLocales
735     virtual ::com::sun::star::uno::Sequence<
736 			::com::sun::star::lang::Locale > SAL_CALL
737 		getLocales()
738 			throw(::com::sun::star::uno::RuntimeException);
739     virtual sal_Bool SAL_CALL
740         hasLocale( const ::com::sun::star::lang::Locale& rLocale )
741 			throw(::com::sun::star::uno::RuntimeException);
742 
743     // XHyphenator
744     virtual ::com::sun::star::uno::Reference<
745 			::com::sun::star::linguistic2::XHyphenatedWord > SAL_CALL
746         hyphenate( const ::rtl::OUString& rWord,
747                 const ::com::sun::star::lang::Locale& rLocale,
748 				sal_Int16 nMaxLeading,
749                 const ::com::sun::star::beans::PropertyValues& rProperties )
750 			throw(::com::sun::star::lang::IllegalArgumentException,
751 				  ::com::sun::star::uno::RuntimeException);
752     virtual ::com::sun::star::uno::Reference<
753 			::com::sun::star::linguistic2::XHyphenatedWord > SAL_CALL
754         queryAlternativeSpelling( const ::rtl::OUString& rWord,
755                 const ::com::sun::star::lang::Locale& rLocale,
756 				sal_Int16 nIndex,
757                 const ::com::sun::star::beans::PropertyValues& rProperties )
758 			throw(::com::sun::star::lang::IllegalArgumentException,
759 				  ::com::sun::star::uno::RuntimeException);
760     virtual ::com::sun::star::uno::Reference<
761 			::com::sun::star::linguistic2::XPossibleHyphens > SAL_CALL
762 		createPossibleHyphens(
763                 const ::rtl::OUString& rWord,
764                 const ::com::sun::star::lang::Locale& rLocale,
765                 const ::com::sun::star::beans::PropertyValues& rProperties )
766 			throw(::com::sun::star::lang::IllegalArgumentException,
767 				  ::com::sun::star::uno::RuntimeException);
768 };
769 
770 
771 void HyphDummy_Impl::GetHyph_Impl()
772 {
773     // update configuration before accessing the service
774     if (SvxLinguConfigUpdate::IsNeedUpdateAll())
775         SvxLinguConfigUpdate::UpdateAll();
776 
777     if (!xHyph.is())
778     {
779         uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() );
780         if (xLngSvcMgr.is())
781             xHyph = xLngSvcMgr->getHyphenator();
782     }
783 }
784 
785 
786 uno::Sequence< lang::Locale > SAL_CALL
787     HyphDummy_Impl::getLocales()
788         throw(uno::RuntimeException)
789 {
790     GetHyph_Impl();
791     if (xHyph.is())
792         return xHyph->getLocales();
793     else
794         return uno::Sequence< lang::Locale >();
795 }
796 
797 
798 sal_Bool SAL_CALL
799     HyphDummy_Impl::hasLocale( const lang::Locale& rLocale )
800         throw(uno::RuntimeException)
801 {
802     GetHyph_Impl();
803     sal_Bool bRes = sal_False;
804     if (xHyph.is())
805         bRes = xHyph->hasLocale( rLocale );
806     return bRes;
807 }
808 
809 
810 uno::Reference< linguistic2::XHyphenatedWord > SAL_CALL
811     HyphDummy_Impl::hyphenate(
812             const rtl::OUString& rWord,
813             const lang::Locale& rLocale,
814             sal_Int16 nMaxLeading,
815             const beans::PropertyValues& rProperties )
816         throw(lang::IllegalArgumentException,
817               uno::RuntimeException)
818 {
819     GetHyph_Impl();
820     uno::Reference< linguistic2::XHyphenatedWord > xRes;
821     if (xHyph.is())
822         xRes = xHyph->hyphenate( rWord, rLocale, nMaxLeading, rProperties );
823     return xRes;
824 }
825 
826 
827 uno::Reference< linguistic2::XHyphenatedWord > SAL_CALL
828     HyphDummy_Impl::queryAlternativeSpelling(
829             const rtl::OUString& rWord,
830             const lang::Locale& rLocale,
831             sal_Int16 nIndex,
832             const PropertyValues& rProperties )
833         throw(lang::IllegalArgumentException,
834               uno::RuntimeException)
835 {
836     GetHyph_Impl();
837     uno::Reference< linguistic2::XHyphenatedWord > xRes;
838     if (xHyph.is())
839         xRes = xHyph->queryAlternativeSpelling( rWord, rLocale, nIndex, rProperties );
840     return xRes;
841 }
842 
843 
844 uno::Reference< linguistic2::XPossibleHyphens > SAL_CALL
845     HyphDummy_Impl::createPossibleHyphens(
846             const rtl::OUString& rWord,
847             const lang::Locale& rLocale,
848             const beans::PropertyValues& rProperties )
849         throw(lang::IllegalArgumentException,
850               uno::RuntimeException)
851 {
852     GetHyph_Impl();
853     uno::Reference< linguistic2::XPossibleHyphens > xRes;
854     if (xHyph.is())
855         xRes = xHyph->createPossibleHyphens( rWord, rLocale, rProperties );
856     return xRes;
857 }
858 
859 
860 ///////////////////////////////////////////////////////////////////////////
861 
862 
863 typedef cppu::WeakImplHelper1 < XEventListener > LinguMgrAppExitLstnrBaseClass;
864 
865 class LinguMgrAppExitLstnr : public LinguMgrAppExitLstnrBaseClass
866 {
867 	uno::Reference< XComponent > 		xDesktop;
868 
869 public:
870 	LinguMgrAppExitLstnr();
871 	virtual ~LinguMgrAppExitLstnr();
872 
873 	virtual	void	AtExit() = 0;
874 
875 
876 	// lang::XEventListener
877     virtual void 	SAL_CALL disposing(const EventObject& rSource)
878 			throw( RuntimeException );
879 };
880 
881 LinguMgrAppExitLstnr::LinguMgrAppExitLstnr()
882 {
883 	// add object to frame::Desktop EventListeners in order to properly call
884 	// the AtExit function at appliction exit.
885 
886 	uno::Reference< XMultiServiceFactory >  xMgr = getProcessServiceFactory();
887 	if ( xMgr.is() )
888 	{
889 		xDesktop = uno::Reference< XComponent > ( xMgr->createInstance(
890 				OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.frame.Desktop" ) ) ), UNO_QUERY ) ;
891 		if (xDesktop.is())
892 			xDesktop->addEventListener( this );
893 	}
894 }
895 
896 LinguMgrAppExitLstnr::~LinguMgrAppExitLstnr()
897 {
898 	if (xDesktop.is())
899 	{
900 		xDesktop->removeEventListener( this );
901 		xDesktop = NULL;	//! release reference to desktop
902 	}
903 	DBG_ASSERT(!xDesktop.is(), "reference to desktop should be realeased");
904 }
905 
906 void LinguMgrAppExitLstnr::disposing(const EventObject& rSource)
907 		throw( RuntimeException )
908 {
909 	if (xDesktop.is()  &&  rSource.Source == xDesktop)
910 	{
911 		xDesktop->removeEventListener( this );
912 		xDesktop = NULL;	//! release reference to desktop
913 
914 		AtExit();
915 	}
916 }
917 
918 ///////////////////////////////////////////////////////////////////////////
919 
920 class LinguMgrExitLstnr : public LinguMgrAppExitLstnr
921 {
922 public:
923 	virtual	void	AtExit();
924 };
925 
926 void LinguMgrExitLstnr::AtExit()
927 {
928 	// release references
929 	LinguMgr::xLngSvcMgr	= 0;
930 	LinguMgr::xSpell		= 0;
931 	LinguMgr::xHyph			= 0;
932 	LinguMgr::xThes			= 0;
933 	LinguMgr::xDicList		= 0;
934 	LinguMgr::xProp			= 0;
935 	LinguMgr::xIgnoreAll	= 0;
936 	LinguMgr::xChangeAll	= 0;
937 
938 	LinguMgr::bExiting		= sal_True;
939 
940 	//TL:TODO: MBA fragen wie ich ohne Absturz hier meinen Speicher
941 	//  wieder freibekomme...
942 	//delete LinguMgr::pExitLstnr;
943 	LinguMgr::pExitLstnr	= 0;
944 }
945 
946 ///////////////////////////////////////////////////////////////////////////
947 
948 
949 // static member initialization
950 LinguMgrExitLstnr * 			LinguMgr::pExitLstnr	= 0;
951 sal_Bool						LinguMgr::bExiting		= sal_False;
952 uno::Reference< XLinguServiceManager >	LinguMgr::xLngSvcMgr	= 0;
953 uno::Reference< XSpellChecker1 > 	LinguMgr::xSpell		= 0;
954 uno::Reference< XHyphenator > 		LinguMgr::xHyph			= 0;
955 uno::Reference< XThesaurus > 		LinguMgr::xThes			= 0;
956 uno::Reference< XDictionaryList > 	LinguMgr::xDicList		= 0;
957 uno::Reference< XPropertySet > 		LinguMgr::xProp			= 0;
958 uno::Reference< XDictionary >       LinguMgr::xIgnoreAll    = 0;
959 uno::Reference< XDictionary >       LinguMgr::xChangeAll    = 0;
960 
961 
962 uno::Reference< XLinguServiceManager > LinguMgr::GetLngSvcMgr()
963 {
964 	if (bExiting)
965 		return 0;
966 
967 	if (!pExitLstnr)
968 		pExitLstnr = new LinguMgrExitLstnr;
969 
970 	if (!xLngSvcMgr.is())
971 		xLngSvcMgr = GetLngSvcMgr_Impl();
972 
973 	return xLngSvcMgr;
974 }
975 
976 
977 uno::Reference< XSpellChecker1 > LinguMgr::GetSpellChecker()
978 {
979 	return xSpell.is() ? xSpell : GetSpell();
980 }
981 
982 uno::Reference< XHyphenator > LinguMgr::GetHyphenator()
983 {
984 	return xHyph.is() ? xHyph : GetHyph();
985 }
986 
987 uno::Reference< XThesaurus > LinguMgr::GetThesaurus()
988 {
989 	return xThes.is() ? xThes : GetThes();
990 }
991 
992 uno::Reference< XDictionaryList > LinguMgr::GetDictionaryList()
993 {
994 	return xDicList.is() ? xDicList : GetDicList();
995 }
996 
997 uno::Reference< XPropertySet > LinguMgr::GetLinguPropertySet()
998 {
999 	return xProp.is() ? xProp : GetProp();
1000 }
1001 
1002 uno::Reference< XDictionary > LinguMgr::GetStandardDic()
1003 {
1004 	//! don't hold reference to this
1005 	//! (it may be removed from dictionary list and needs to be
1006 	//! created empty if accessed again)
1007 	return GetStandard();
1008 }
1009 
1010 uno::Reference< XDictionary > LinguMgr::GetIgnoreAllList()
1011 {
1012 	return xIgnoreAll.is() ? xIgnoreAll : GetIgnoreAll();
1013 }
1014 
1015 uno::Reference< XDictionary > LinguMgr::GetChangeAllList()
1016 {
1017 	return xChangeAll.is() ? xChangeAll : GetChangeAll();
1018 }
1019 
1020 uno::Reference< XSpellChecker1 > LinguMgr::GetSpell()
1021 {
1022 	if (bExiting)
1023 		return 0;
1024 
1025 	if (!pExitLstnr)
1026 		pExitLstnr = new LinguMgrExitLstnr;
1027 
1028     //! use dummy implementation in order to avoid loading of lingu DLL
1029     xSpell = new SpellDummy_Impl;
1030 
1031 /*    if (!xLngSvcMgr.is())
1032 		xLngSvcMgr = GetLngSvcMgr_Impl();
1033 
1034 	if (xLngSvcMgr.is())
1035 	{
1036 		xSpell = uno::Reference< XSpellChecker1 > (
1037 						xLngSvcMgr->getSpellChecker(), UNO_QUERY );
1038 	}
1039 */
1040 	return xSpell;
1041 }
1042 
1043 uno::Reference< XHyphenator > LinguMgr::GetHyph()
1044 {
1045 	if (bExiting)
1046 		return 0;
1047 
1048 	if (!pExitLstnr)
1049 		pExitLstnr = new LinguMgrExitLstnr;
1050 
1051     //! use dummy implementation in order to avoid loading of lingu DLL
1052     xHyph = new HyphDummy_Impl;
1053 
1054 /*
1055 	if (!xLngSvcMgr.is())
1056 		xLngSvcMgr = GetLngSvcMgr_Impl();
1057 
1058 	if (xLngSvcMgr.is())
1059 	{
1060 		xHyph = xLngSvcMgr->getHyphenator();
1061 	}
1062 */
1063 	return xHyph;
1064 }
1065 
1066 uno::Reference< XThesaurus > LinguMgr::GetThes()
1067 {
1068 	if (bExiting)
1069 		return 0;
1070 
1071 	if (!pExitLstnr)
1072 		pExitLstnr = new LinguMgrExitLstnr;
1073 
1074     //! use dummy implementation in order to avoid loading of lingu DLL
1075     //! when only the XSupportedLocales interface is used.
1076     //! The dummy accesses the real implementation (and thus loading the DLL)
1077     //! when "real" work needs to be done only.
1078     xThes = new ThesDummy_Impl;
1079 /*
1080 	if (!xLngSvcMgr.is())
1081 		xLngSvcMgr = GetLngSvcMgr_Impl();
1082 
1083 	if (xLngSvcMgr.is())
1084 	{
1085 		xThes = xLngSvcMgr->getThesaurus();
1086 	}
1087 */
1088 	return xThes;
1089 }
1090 
1091 
1092 void LinguMgr::UpdateAll()
1093 {
1094 }
1095 
1096 
1097 uno::Reference< XDictionaryList > LinguMgr::GetDicList()
1098 {
1099 	if (bExiting)
1100 		return 0;
1101 
1102 	if (!pExitLstnr)
1103 		pExitLstnr = new LinguMgrExitLstnr;
1104 
1105 	uno::Reference< XMultiServiceFactory >  xMgr( getProcessServiceFactory() );
1106 	if (xMgr.is())
1107 	{
1108 		xDicList = uno::Reference< XDictionaryList > ( xMgr->createInstance(
1109                     A2OU("com.sun.star.linguistic2.DictionaryList") ), UNO_QUERY );
1110 	}
1111 	return xDicList;
1112 }
1113 
1114 uno::Reference< XPropertySet > LinguMgr::GetProp()
1115 {
1116 	if (bExiting)
1117 		return 0;
1118 
1119 	if (!pExitLstnr)
1120 		pExitLstnr = new LinguMgrExitLstnr;
1121 
1122 	uno::Reference< XMultiServiceFactory >  xMgr( getProcessServiceFactory() );
1123 	if (xMgr.is())
1124 	{
1125 		xProp = uno::Reference< XPropertySet > ( xMgr->createInstance(
1126                     A2OU("com.sun.star.linguistic2.LinguProperties") ), UNO_QUERY );
1127 	}
1128 	return xProp;
1129 }
1130 
1131 uno::Reference< XDictionary > LinguMgr::GetIgnoreAll()
1132 {
1133 	if (bExiting)
1134 		return 0;
1135 
1136 	if (!pExitLstnr)
1137 		pExitLstnr = new LinguMgrExitLstnr;
1138 
1139 	uno::Reference< XDictionaryList >  xTmpDicList( GetDictionaryList() );
1140 	if (xTmpDicList.is())
1141 	{
1142         xIgnoreAll = uno::Reference< XDictionary > ( xTmpDicList->getDictionaryByName(
1143                     A2OU("IgnoreAllList") ), UNO_QUERY );
1144 	}
1145 	return xIgnoreAll;
1146 }
1147 
1148 uno::Reference< XDictionary > LinguMgr::GetChangeAll()
1149 {
1150 	if (bExiting)
1151 		return 0;
1152 
1153 	if (!pExitLstnr)
1154 		pExitLstnr = new LinguMgrExitLstnr;
1155 
1156 	uno::Reference< XDictionaryList > _xDicList( GetDictionaryList() , UNO_QUERY );
1157 	if (_xDicList.is())
1158 	{
1159         xChangeAll = uno::Reference< XDictionary > (
1160 						_xDicList->createDictionary(
1161                             A2OU("ChangeAllList"),
1162 							SvxCreateLocale( LANGUAGE_NONE ),
1163 							DictionaryType_NEGATIVE, String() ), UNO_QUERY );
1164 	}
1165 	return xChangeAll;
1166 }
1167 
1168 uno::Reference< XDictionary > LinguMgr::GetStandard()
1169 {
1170 	// Tries to return a dictionary which may hold positive entries is
1171 	// persistent and not read-only.
1172 
1173 	if (bExiting)
1174 		return 0;
1175 
1176 	uno::Reference< XDictionaryList >  xTmpDicList( GetDictionaryList() );
1177 	if (!xTmpDicList.is())
1178 		return NULL;
1179 
1180 	const OUString aDicName( RTL_CONSTASCII_USTRINGPARAM( "standard.dic" ) );
1181     uno::Reference< XDictionary >   xDic( xTmpDicList->getDictionaryByName( aDicName ),
1182 									  UNO_QUERY );
1183     if (!xDic.is())
1184     {
1185         // try to create standard dictionary
1186         uno::Reference< XDictionary >    xTmp;
1187         try
1188         {
1189             xTmp =  xTmpDicList->createDictionary( aDicName,
1190                         SvxCreateLocale( LANGUAGE_NONE ),
1191                         DictionaryType_POSITIVE,
1192                         linguistic::GetWritableDictionaryURL( aDicName ) );
1193         }
1194         catch(com::sun::star::uno::Exception &)
1195         {
1196         }
1197 
1198         // add new dictionary to list
1199         if (xTmp.is())
1200         {
1201             xTmpDicList->addDictionary( xTmp );
1202             xTmp->setActive( sal_True );
1203         }
1204         xDic = uno::Reference< XDictionary > ( xTmp, UNO_QUERY );
1205     }
1206 #if OSL_DEBUG_LEVEL > 1
1207     uno::Reference< XStorable >      xStor( xDic, UNO_QUERY );
1208     DBG_ASSERT( xDic.is() && xDic->getDictionaryType() == DictionaryType_POSITIVE,
1209             "wrong dictionary type");
1210     DBG_ASSERT( xDic.is() && SvxLocaleToLanguage( xDic->getLocale() ) == LANGUAGE_NONE,
1211             "wrong dictionary language");
1212     DBG_ASSERT( !xStor.is() || (xStor->hasLocation() && !xStor->isReadonly()),
1213             "dictionary not editable" );
1214 #endif
1215 
1216 	return xDic;
1217 }
1218 
1219 ///////////////////////////////////////////////////////////////////////////
1220 
1221 uno::Reference< XSpellChecker1 >  SvxGetSpellChecker()
1222 {
1223 	return LinguMgr::GetSpellChecker();
1224 }
1225 
1226 uno::Reference< XHyphenator >  SvxGetHyphenator()
1227 {
1228 	return LinguMgr::GetHyphenator();
1229 }
1230 
1231 uno::Reference< XThesaurus >  SvxGetThesaurus()
1232 {
1233 	return LinguMgr::GetThesaurus();
1234 }
1235 
1236 uno::Reference< XDictionaryList >  SvxGetDictionaryList()
1237 {
1238 	return LinguMgr::GetDictionaryList();
1239 }
1240 
1241 uno::Reference< XPropertySet > 	SvxGetLinguPropertySet()
1242 {
1243 	return LinguMgr::GetLinguPropertySet();
1244 }
1245 
1246 //TL:TODO: remove argument or provide SvxGetIgnoreAllList with the same one
1247 uno::Reference< XDictionary >  SvxGetOrCreatePosDic(
1248 		uno::Reference< XDictionaryList >  /* xDicList */ )
1249 {
1250 	return LinguMgr::GetStandardDic();
1251 }
1252 
1253 uno::Reference< XDictionary >  SvxGetIgnoreAllList()
1254 {
1255 	return LinguMgr::GetIgnoreAllList();
1256 }
1257 
1258 uno::Reference< XDictionary >  SvxGetChangeAllList()
1259 {
1260 	return LinguMgr::GetChangeAllList();
1261 }
1262 
1263 ///////////////////////////////////////////////////////////////////////////
1264 
1265 
1266 #include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
1267 
1268 SvxAlternativeSpelling SvxGetAltSpelling(
1269 		const ::com::sun::star::uno::Reference<
1270 			::com::sun::star::linguistic2::XHyphenatedWord > & rHyphWord )
1271 {
1272 	SvxAlternativeSpelling aRes;
1273 	if (rHyphWord.is() && rHyphWord->isAlternativeSpelling())
1274 	{
1275 		OUString aWord( rHyphWord->getWord() ),
1276                  aAltWord( rHyphWord->getHyphenatedWord() );
1277 		sal_Int16	nHyphenationPos		= rHyphWord->getHyphenationPos(),
1278 				nHyphenPos			= rHyphWord->getHyphenPos();
1279         sal_Int16   nLen    = (sal_Int16)aWord.getLength();
1280         sal_Int16   nAltLen = (sal_Int16)aAltWord.getLength();
1281 		const sal_Unicode *pWord	= aWord.getStr(),
1282                           *pAltWord = aAltWord.getStr();
1283 
1284         // count number of chars from the left to the
1285         // hyphenation pos / hyphen pos that are equal
1286         sal_Int16 nL = 0;
1287         while (nL <= nHyphenationPos && nL <= nHyphenPos
1288                && pWord[ nL ] == pAltWord[ nL ])
1289             ++nL;
1290         // count number of chars from the right to the
1291         // hyphenation pos / hyphen pos that are equal
1292         sal_Int16 nR = 0;
1293         sal_Int32 nIdx    = nLen - 1;
1294         sal_Int32 nAltIdx = nAltLen - 1;
1295         while (nIdx > nHyphenationPos && nAltIdx > nHyphenPos
1296                && pWord[ nIdx-- ] == pAltWord[ nAltIdx-- ])
1297             ++nR;
1298 
1299         aRes.aReplacement       = OUString( aAltWord.copy( nL, nAltLen - nL - nR ) );
1300         aRes.nChangedPos        = (sal_Int16) nL;
1301         aRes.nChangedLength     = nLen - nL - nR;
1302 		aRes.bIsAltSpelling		= sal_True;
1303 		aRes.xHyphWord			= rHyphWord;
1304 	}
1305 	return aRes;
1306 }
1307 
1308 
1309 ///////////////////////////////////////////////////////////////////////////
1310 
1311 SvxDicListChgClamp::SvxDicListChgClamp( uno::Reference< XDictionaryList >  &rxDicList ) :
1312 	xDicList	( rxDicList )
1313 {
1314 	if (xDicList.is())
1315 	{
1316 		xDicList->beginCollectEvents();
1317 	}
1318 }
1319 
1320 SvxDicListChgClamp::~SvxDicListChgClamp()
1321 {
1322 	if (xDicList.is())
1323 	{
1324 		xDicList->endCollectEvents();
1325 	}
1326 }
1327 
1328 ///////////////////////////////////////////////////////////////////////////
1329 
1330 short SvxDicError( Window *pParent, sal_Int16 nError )
1331 {
1332 	short nRes = 0;
1333 	if (DIC_ERR_NONE != nError)
1334 	{
1335 		int nRid;
1336 		switch (nError)
1337 		{
1338 			case DIC_ERR_FULL	  : nRid = RID_SVXSTR_DIC_ERR_FULL;  break;
1339 			case DIC_ERR_READONLY : nRid = RID_SVXSTR_DIC_ERR_READONLY;  break;
1340 			default:
1341 				nRid = RID_SVXSTR_DIC_ERR_UNKNOWN;
1342 				DBG_ASSERT(0, "unexpected case");
1343 		}
1344 		nRes = InfoBox( pParent, EE_RESSTR( nRid ) ).Execute();
1345 	}
1346 	return nRes;
1347 }
1348 
1349 LanguageType SvxLocaleToLanguage( const Locale& rLocale )
1350 {
1351 	//	empty Locale -> LANGUAGE_NONE
1352 	if ( rLocale.Language.getLength() == 0 )
1353 		return LANGUAGE_NONE;
1354 
1355 	return MsLangId::convertLocaleToLanguage( rLocale );
1356 }
1357 
1358 Locale& SvxLanguageToLocale( Locale& rLocale, LanguageType eLang )
1359 {
1360 	if ( eLang != LANGUAGE_NONE	/* &&  eLang != LANGUAGE_SYSTEM */)
1361 		MsLangId::convertLanguageToLocale( eLang, rLocale );
1362     else
1363         rLocale = Locale();
1364 
1365 	return rLocale;
1366 }
1367 
1368 Locale SvxCreateLocale( LanguageType eLang )
1369 {
1370 	Locale aLocale;
1371 	if ( eLang != LANGUAGE_NONE /* &&  eLang != LANGUAGE_SYSTEM */)
1372 		MsLangId::convertLanguageToLocale( eLang, aLocale );
1373 
1374 	return aLocale;
1375 }
1376 
1377 
1378