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