Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <cppuhelper/factory.hxx> // helper for factories
21 : #include <com/sun/star/registry/XRegistryKey.hpp>
22 : #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
23 : #include <com/sun/star/linguistic2/XHyphenatedWord.hpp>
24 : #include <rtl/ustrbuf.hxx>
25 : #include <i18npool/lang.h>
26 : #include <unotools/localedatawrapper.hxx>
27 : #include <tools/debug.hxx>
28 : #include <svl/lngmisc.hxx>
29 : #include <comphelper/processfactory.hxx>
30 : #include <osl/mutex.hxx>
31 :
32 : #include "hyphdsp.hxx"
33 : #include "linguistic/hyphdta.hxx"
34 : #include "linguistic/lngprops.hxx"
35 : #include "lngsvcmgr.hxx"
36 :
37 : using namespace osl;
38 : using namespace com::sun::star;
39 : using namespace com::sun::star::beans;
40 : using namespace com::sun::star::lang;
41 : using namespace com::sun::star::uno;
42 : using namespace com::sun::star::linguistic2;
43 : using namespace linguistic;
44 :
45 : using ::rtl::OUString;
46 : using ::rtl::OUStringBuffer;
47 :
48 :
49 7 : HyphenatorDispatcher::HyphenatorDispatcher( LngSvcMgr &rLngSvcMgr ) :
50 7 : rMgr (rLngSvcMgr)
51 : {
52 7 : }
53 :
54 :
55 6 : HyphenatorDispatcher::~HyphenatorDispatcher()
56 : {
57 2 : ClearSvcList();
58 4 : }
59 :
60 :
61 2 : void HyphenatorDispatcher::ClearSvcList()
62 : {
63 : // release memory for each table entry
64 2 : HyphSvcByLangMap_t aTmp;
65 2 : aSvcMap.swap( aTmp );
66 2 : }
67 :
68 :
69 0 : Reference<XHyphenatedWord> HyphenatorDispatcher::buildHyphWord(
70 : const OUString rOrigWord,
71 : const Reference<XDictionaryEntry> &xEntry,
72 : sal_Int16 nLang, sal_Int16 nMaxLeading )
73 : {
74 0 : MutexGuard aGuard( GetLinguMutex() );
75 :
76 0 : Reference< XHyphenatedWord > xRes;
77 :
78 0 : if (xEntry.is())
79 : {
80 0 : OUString aText( xEntry->getDictionaryWord() );
81 0 : sal_Int32 nTextLen = aText.getLength();
82 :
83 : // trailing '=' means "hyphenation should not be possible"
84 0 : if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=')
85 : {
86 0 : sal_Int16 nHyphenationPos = -1;
87 :
88 0 : OUStringBuffer aTmp( nTextLen );
89 0 : sal_Bool bSkip = sal_False;
90 0 : sal_Int32 nHyphIdx = -1;
91 0 : sal_Int32 nLeading = 0;
92 0 : for (sal_Int32 i = 0; i < nTextLen; i++)
93 : {
94 0 : sal_Unicode cTmp = aText[i];
95 0 : if (cTmp != '=')
96 : {
97 0 : aTmp.append( cTmp );
98 0 : nLeading++;
99 0 : bSkip = sal_False;
100 0 : nHyphIdx++;
101 : }
102 : else
103 : {
104 0 : if (!bSkip && nHyphIdx >= 0)
105 : {
106 0 : if (nLeading <= nMaxLeading)
107 0 : nHyphenationPos = (sal_Int16) nHyphIdx;
108 : }
109 0 : bSkip = sal_True; //! multiple '=' should count as one only
110 : }
111 : }
112 :
113 0 : if (nHyphenationPos > 0)
114 : {
115 0 : aText = aTmp.makeStringAndClear();
116 :
117 : #if OSL_DEBUG_LEVEL > 1
118 : {
119 : if (aText != rOrigWord)
120 : {
121 : // both words should only differ by a having a trailing '.'
122 : // character or not...
123 : OUString aShorter, aLonger;
124 : if (aText.getLength() <= rOrigWord.getLength())
125 : {
126 : aShorter = aText;
127 : aLonger = rOrigWord;
128 : }
129 : else
130 : {
131 : aShorter = rOrigWord;
132 : aLonger = aText;
133 : }
134 : xub_StrLen nS = sal::static_int_cast< xub_StrLen >( aShorter.getLength() );
135 : xub_StrLen nL = sal::static_int_cast< xub_StrLen >( aLonger.getLength() );
136 : if (nS > 0 && nL > 0)
137 : {
138 : DBG_ASSERT( (nS + 1 == nL) && aLonger[nL-1] == (sal_Unicode) '.',
139 : "HyphenatorDispatcher::buildHyphWord: unexpected difference between words!" );
140 : }
141 : }
142 : }
143 : #endif
144 : //! take care of #i22591#
145 0 : aText = rOrigWord;
146 :
147 : DBG_ASSERT( aText == rOrigWord, "failed to " );
148 : xRes = new HyphenatedWord( aText, nLang, nHyphenationPos,
149 0 : aText, nHyphenationPos );
150 0 : }
151 0 : }
152 : }
153 :
154 0 : return xRes;
155 : }
156 :
157 :
158 0 : Reference< XPossibleHyphens > HyphenatorDispatcher::buildPossHyphens(
159 : const Reference< XDictionaryEntry > &xEntry, sal_Int16 nLanguage )
160 : {
161 0 : MutexGuard aGuard( GetLinguMutex() );
162 :
163 0 : Reference<XPossibleHyphens> xRes;
164 :
165 0 : if (xEntry.is())
166 : {
167 : // text with hyphenation info
168 0 : OUString aText( xEntry->getDictionaryWord() );
169 0 : sal_Int32 nTextLen = aText.getLength();
170 :
171 : // trailing '=' means "hyphenation should not be possible"
172 0 : if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=')
173 : {
174 : // sequence to hold hyphenation positions
175 0 : Sequence< sal_Int16 > aHyphPos( nTextLen );
176 0 : sal_Int16 *pPos = aHyphPos.getArray();
177 0 : sal_Int32 nHyphCount = 0;
178 :
179 0 : OUStringBuffer aTmp( nTextLen );
180 0 : sal_Bool bSkip = sal_False;
181 0 : sal_Int32 nHyphIdx = -1;
182 0 : for (sal_Int32 i = 0; i < nTextLen; i++)
183 : {
184 0 : sal_Unicode cTmp = aText[i];
185 0 : if (cTmp != '=')
186 : {
187 0 : aTmp.append( cTmp );
188 0 : bSkip = sal_False;
189 0 : nHyphIdx++;
190 : }
191 : else
192 : {
193 0 : if (!bSkip && nHyphIdx >= 0)
194 0 : pPos[ nHyphCount++ ] = (sal_Int16) nHyphIdx;
195 0 : bSkip = sal_True; //! multiple '=' should count as one only
196 : }
197 : }
198 :
199 : // ignore (multiple) trailing '='
200 0 : if (bSkip && nHyphIdx >= 0)
201 : {
202 0 : nHyphCount--;
203 : }
204 : DBG_ASSERT( nHyphCount >= 0, "lng : invalid hyphenation count");
205 :
206 0 : if (nHyphCount > 0)
207 : {
208 0 : aHyphPos.realloc( nHyphCount );
209 : xRes = new PossibleHyphens( aTmp.makeStringAndClear(), nLanguage,
210 0 : aText, aHyphPos );
211 0 : }
212 0 : }
213 : }
214 :
215 0 : return xRes;
216 : }
217 :
218 :
219 0 : Sequence< Locale > SAL_CALL HyphenatorDispatcher::getLocales()
220 : throw(RuntimeException)
221 : {
222 0 : MutexGuard aGuard( GetLinguMutex() );
223 :
224 0 : Sequence< Locale > aLocales( static_cast< sal_Int32 >(aSvcMap.size()) );
225 0 : Locale *pLocales = aLocales.getArray();
226 0 : HyphSvcByLangMap_t::const_iterator aIt;
227 0 : for (aIt = aSvcMap.begin(); aIt != aSvcMap.end(); ++aIt)
228 : {
229 0 : *pLocales++ = LanguageTag( aIt->first ).getLocale();
230 : }
231 0 : return aLocales;
232 : }
233 :
234 :
235 0 : sal_Bool SAL_CALL HyphenatorDispatcher::hasLocale(const Locale& rLocale)
236 : throw(RuntimeException)
237 : {
238 0 : MutexGuard aGuard( GetLinguMutex() );
239 0 : HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LanguageTag( rLocale ).getLanguageType() ) );
240 0 : return aIt != aSvcMap.end();
241 : }
242 :
243 :
244 : Reference< XHyphenatedWord > SAL_CALL
245 1804 : HyphenatorDispatcher::hyphenate(
246 : const OUString& rWord, const Locale& rLocale, sal_Int16 nMaxLeading,
247 : const PropertyValues& rProperties )
248 : throw(IllegalArgumentException, RuntimeException)
249 : {
250 1804 : MutexGuard aGuard( GetLinguMutex() );
251 :
252 1804 : Reference< XHyphenatedWord > xRes;
253 :
254 1804 : sal_Int32 nWordLen = rWord.getLength();
255 1804 : sal_Int16 nLanguage = LanguageTag( rLocale ).getLanguageType();
256 1804 : if (nLanguage == LANGUAGE_NONE || !nWordLen ||
257 : nMaxLeading == 0 || nMaxLeading == nWordLen)
258 0 : return xRes;
259 :
260 : // search for entry with that language
261 1804 : HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
262 1804 : LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
263 :
264 1804 : bool bWordModified = false;
265 1804 : if (!pEntry || (nMaxLeading < 0 || nMaxLeading > nWordLen))
266 : {
267 1804 : return NULL;
268 : }
269 : else
270 : {
271 0 : OUString aChkWord( rWord );
272 :
273 : // replace typographical apostroph by ascii apostroph
274 0 : String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
275 : DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
276 0 : if (aSingleQuote.Len())
277 0 : aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
278 :
279 0 : bWordModified |= RemoveHyphens( aChkWord );
280 0 : if (IsIgnoreControlChars( rProperties, GetPropSet() ))
281 0 : bWordModified |= RemoveControlChars( aChkWord );
282 0 : sal_Int16 nChkMaxLeading = (sal_Int16) GetPosInWordToCheck( rWord, nMaxLeading );
283 :
284 : // check for results from (positive) dictionaries which have precedence!
285 0 : Reference< XDictionaryEntry > xEntry;
286 :
287 0 : if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
288 : {
289 0 : xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
290 0 : sal_True, sal_False );
291 : }
292 :
293 0 : if (xEntry.is())
294 : {
295 : //! because queryDictionaryEntry (in the end DictionaryNeo::getEntry)
296 : //! does not distinguish betwee "XYZ" and "XYZ." in order to avoid
297 : //! to require them as different entry we have to supply the
298 : //! original word here as well so it can be used in th result
299 : //! otherwise a strange effect may occur (see #i22591#)
300 0 : xRes = buildHyphWord( rWord, xEntry, nLanguage, nChkMaxLeading );
301 : }
302 : else
303 : {
304 0 : sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
305 : DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
306 : "lng : index out of range");
307 :
308 0 : sal_Int32 i = 0;
309 0 : Reference< XHyphenator > xHyph;
310 0 : if (pEntry->aSvcRefs.getLength() > 0)
311 0 : xHyph = pEntry->aSvcRefs[0];
312 :
313 : // try already instantiated service
314 0 : if (i <= pEntry->nLastTriedSvcIndex)
315 : {
316 0 : if (xHyph.is() && xHyph->hasLocale( rLocale ))
317 0 : xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
318 0 : rProperties );
319 0 : ++i;
320 : }
321 0 : else if (pEntry->nLastTriedSvcIndex < nLen - 1)
322 : // instantiate services and try it
323 : {
324 0 : Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
325 :
326 : Reference< XMultiServiceFactory > xMgr(
327 0 : comphelper::getProcessServiceFactory() );
328 0 : if (xMgr.is())
329 : {
330 : // build service initialization argument
331 0 : Sequence< Any > aArgs(2);
332 0 : aArgs.getArray()[0] <<= GetPropSet();
333 :
334 : // create specific service via it's implementation name
335 : try
336 : {
337 : xHyph = Reference< XHyphenator >(
338 0 : xMgr->createInstanceWithArguments(
339 0 : pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
340 : }
341 0 : catch (uno::Exception &)
342 : {
343 : DBG_ASSERT( 0, "createInstanceWithArguments failed" );
344 : }
345 0 : pRef [i] = xHyph;
346 :
347 : Reference< XLinguServiceEventBroadcaster >
348 0 : xBroadcaster( xHyph, UNO_QUERY );
349 0 : if (xBroadcaster.is())
350 0 : rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
351 :
352 0 : if (xHyph.is() && xHyph->hasLocale( rLocale ))
353 0 : xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading,
354 0 : rProperties );
355 :
356 0 : pEntry->nLastTriedSvcIndex = (sal_Int16) i;
357 0 : ++i;
358 :
359 : // if language is not supported by the services
360 : // remove it from the list.
361 0 : if (xHyph.is() && !xHyph->hasLocale( rLocale ))
362 0 : aSvcMap.erase( nLanguage );
363 0 : }
364 0 : }
365 0 : } // if (xEntry.is())
366 : }
367 :
368 0 : if (bWordModified && xRes.is())
369 0 : xRes = RebuildHyphensAndControlChars( rWord, xRes );
370 :
371 0 : if (xRes.is() && xRes->getWord() != rWord)
372 : {
373 0 : xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
374 0 : xRes->getHyphenatedWord(),
375 0 : xRes->getHyphenPos() );
376 : }
377 :
378 0 : return xRes;
379 : }
380 :
381 :
382 : Reference< XHyphenatedWord > SAL_CALL
383 0 : HyphenatorDispatcher::queryAlternativeSpelling(
384 : const OUString& rWord, const Locale& rLocale, sal_Int16 nIndex,
385 : const PropertyValues& rProperties )
386 : throw(IllegalArgumentException, RuntimeException)
387 : {
388 0 : MutexGuard aGuard( GetLinguMutex() );
389 :
390 0 : Reference< XHyphenatedWord > xRes;
391 :
392 0 : sal_Int32 nWordLen = rWord.getLength();
393 0 : sal_Int16 nLanguage = LanguageTag( rLocale ).getLanguageType();
394 0 : if (nLanguage == LANGUAGE_NONE || !nWordLen)
395 0 : return xRes;
396 :
397 : // search for entry with that language
398 0 : HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
399 0 : LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
400 :
401 0 : bool bWordModified = false;
402 0 : if (!pEntry || !(0 <= nIndex && nIndex <= nWordLen - 2))
403 : {
404 0 : return NULL;
405 : }
406 : else
407 : {
408 0 : OUString aChkWord( rWord );
409 :
410 : // replace typographical apostroph by ascii apostroph
411 0 : String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
412 : DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
413 0 : if (aSingleQuote.Len())
414 0 : aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
415 :
416 0 : bWordModified |= RemoveHyphens( aChkWord );
417 0 : if (IsIgnoreControlChars( rProperties, GetPropSet() ))
418 0 : bWordModified |= RemoveControlChars( aChkWord );
419 0 : sal_Int16 nChkIndex = (sal_Int16) GetPosInWordToCheck( rWord, nIndex );
420 :
421 : // check for results from (positive) dictionaries which have precedence!
422 0 : Reference< XDictionaryEntry > xEntry;
423 :
424 0 : if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
425 : {
426 0 : xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
427 0 : sal_True, sal_False );
428 : }
429 :
430 0 : if (xEntry.is())
431 : {
432 : //! alternative spellings not yet supported by dictionaries
433 : }
434 : else
435 : {
436 0 : sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
437 : DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
438 : "lng : index out of range");
439 :
440 0 : sal_Int32 i = 0;
441 0 : Reference< XHyphenator > xHyph;
442 0 : if (pEntry->aSvcRefs.getLength() > 0)
443 0 : xHyph = pEntry->aSvcRefs[0];
444 :
445 : // try already instantiated service
446 0 : if (i <= pEntry->nLastTriedSvcIndex)
447 : {
448 0 : if (xHyph.is() && xHyph->hasLocale( rLocale ))
449 0 : xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
450 0 : nChkIndex, rProperties );
451 0 : ++i;
452 : }
453 0 : else if (pEntry->nLastTriedSvcIndex < nLen - 1)
454 : // instantiate services and try it
455 : {
456 0 : Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
457 :
458 : Reference< XMultiServiceFactory > xMgr(
459 0 : comphelper::getProcessServiceFactory() );
460 0 : if (xMgr.is())
461 : {
462 : // build service initialization argument
463 0 : Sequence< Any > aArgs(2);
464 0 : aArgs.getArray()[0] <<= GetPropSet();
465 :
466 : // create specific service via it's implementation name
467 : try
468 : {
469 : xHyph = Reference< XHyphenator >(
470 0 : xMgr->createInstanceWithArguments(
471 0 : pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
472 : }
473 0 : catch (uno::Exception &)
474 : {
475 : DBG_ASSERT( 0, "createInstanceWithArguments failed" );
476 : }
477 0 : pRef [i] = xHyph;
478 :
479 : Reference< XLinguServiceEventBroadcaster >
480 0 : xBroadcaster( xHyph, UNO_QUERY );
481 0 : if (xBroadcaster.is())
482 0 : rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
483 :
484 0 : if (xHyph.is() && xHyph->hasLocale( rLocale ))
485 0 : xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale,
486 0 : nChkIndex, rProperties );
487 :
488 0 : pEntry->nLastTriedSvcIndex = (sal_Int16) i;
489 0 : ++i;
490 :
491 : // if language is not supported by the services
492 : // remove it from the list.
493 0 : if (xHyph.is() && !xHyph->hasLocale( rLocale ))
494 0 : aSvcMap.erase( nLanguage );
495 0 : }
496 0 : }
497 0 : } // if (xEntry.is())
498 : }
499 :
500 0 : if (bWordModified && xRes.is())
501 0 : xRes = RebuildHyphensAndControlChars( rWord, xRes );
502 :
503 0 : if (xRes.is() && xRes->getWord() != rWord)
504 : {
505 0 : xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(),
506 0 : xRes->getHyphenatedWord(),
507 0 : xRes->getHyphenPos() );
508 : }
509 :
510 0 : return xRes;
511 : }
512 :
513 :
514 : Reference< XPossibleHyphens > SAL_CALL
515 0 : HyphenatorDispatcher::createPossibleHyphens(
516 : const OUString& rWord, const Locale& rLocale,
517 : const PropertyValues& rProperties )
518 : throw(IllegalArgumentException, RuntimeException)
519 : {
520 0 : MutexGuard aGuard( GetLinguMutex() );
521 :
522 0 : Reference< XPossibleHyphens > xRes;
523 :
524 0 : sal_Int16 nLanguage = LanguageTag( rLocale ).getLanguageType();
525 0 : if (nLanguage == LANGUAGE_NONE || rWord.isEmpty())
526 : return xRes;
527 :
528 : // search for entry with that language
529 0 : HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
530 0 : LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
531 :
532 0 : if (pEntry)
533 : {
534 0 : OUString aChkWord( rWord );
535 :
536 : // replace typographical apostroph by ascii apostroph
537 0 : String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() );
538 : DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" );
539 0 : if (aSingleQuote.Len())
540 0 : aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' );
541 :
542 0 : RemoveHyphens( aChkWord );
543 0 : if (IsIgnoreControlChars( rProperties, GetPropSet() ))
544 0 : RemoveControlChars( aChkWord );
545 :
546 : // check for results from (positive) dictionaries which have precedence!
547 0 : Reference< XDictionaryEntry > xEntry;
548 :
549 0 : if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() ))
550 : {
551 0 : xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale,
552 0 : sal_True, sal_False );
553 : }
554 :
555 0 : if (xEntry.is())
556 : {
557 0 : xRes = buildPossHyphens( xEntry, nLanguage );
558 : }
559 : else
560 : {
561 0 : sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0;
562 : DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
563 : "lng : index out of range");
564 :
565 0 : sal_Int32 i = 0;
566 0 : Reference< XHyphenator > xHyph;
567 0 : if (pEntry->aSvcRefs.getLength() > 0)
568 0 : xHyph = pEntry->aSvcRefs[0];
569 :
570 : // try already instantiated service
571 0 : if (i <= pEntry->nLastTriedSvcIndex)
572 : {
573 0 : if (xHyph.is() && xHyph->hasLocale( rLocale ))
574 0 : xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
575 0 : rProperties );
576 0 : ++i;
577 : }
578 0 : else if (pEntry->nLastTriedSvcIndex < nLen - 1)
579 : // instantiate services and try it
580 : {
581 0 : Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray();
582 :
583 : Reference< XMultiServiceFactory > xMgr(
584 0 : comphelper::getProcessServiceFactory() );
585 0 : if (xMgr.is())
586 : {
587 : // build service initialization argument
588 0 : Sequence< Any > aArgs(2);
589 0 : aArgs.getArray()[0] <<= GetPropSet();
590 :
591 : // create specific service via it's implementation name
592 : try
593 : {
594 : xHyph = Reference< XHyphenator >(
595 0 : xMgr->createInstanceWithArguments(
596 0 : pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY );
597 : }
598 0 : catch (uno::Exception &)
599 : {
600 : DBG_ASSERT( 0, "createWithArguments failed" );
601 : }
602 0 : pRef [i] = xHyph;
603 :
604 : Reference< XLinguServiceEventBroadcaster >
605 0 : xBroadcaster( xHyph, UNO_QUERY );
606 0 : if (xBroadcaster.is())
607 0 : rMgr.AddLngSvcEvtBroadcaster( xBroadcaster );
608 :
609 0 : if (xHyph.is() && xHyph->hasLocale( rLocale ))
610 0 : xRes = xHyph->createPossibleHyphens( aChkWord, rLocale,
611 0 : rProperties );
612 :
613 0 : pEntry->nLastTriedSvcIndex = (sal_Int16) i;
614 0 : ++i;
615 :
616 : // if language is not supported by the services
617 : // remove it from the list.
618 0 : if (xHyph.is() && !xHyph->hasLocale( rLocale ))
619 0 : aSvcMap.erase( nLanguage );
620 0 : }
621 0 : }
622 0 : } // if (xEntry.is())
623 : }
624 :
625 0 : if (xRes.is() && xRes->getWord() != rWord)
626 : {
627 : xRes = new PossibleHyphens( rWord, nLanguage,
628 0 : xRes->getPossibleHyphens(),
629 0 : xRes->getHyphenationPositions() );
630 : }
631 :
632 0 : return xRes;
633 : }
634 :
635 :
636 0 : void HyphenatorDispatcher::SetServiceList( const Locale &rLocale,
637 : const Sequence< OUString > &rSvcImplNames )
638 : {
639 0 : MutexGuard aGuard( GetLinguMutex() );
640 :
641 0 : sal_Int16 nLanguage = LanguageTag( rLocale ).getLanguageType();
642 :
643 0 : sal_Int32 nLen = rSvcImplNames.getLength();
644 0 : if (0 == nLen)
645 : // remove entry
646 0 : aSvcMap.erase( nLanguage );
647 : else
648 : {
649 : // modify/add entry
650 0 : LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get();
651 0 : if (pEntry)
652 : {
653 0 : pEntry->Clear();
654 0 : pEntry->aSvcImplNames = rSvcImplNames;
655 0 : pEntry->aSvcImplNames.realloc(1);
656 0 : pEntry->aSvcRefs = Sequence< Reference < XHyphenator > > ( 1 );
657 : }
658 : else
659 : {
660 0 : boost::shared_ptr< LangSvcEntries_Hyph > pTmpEntry( new LangSvcEntries_Hyph( rSvcImplNames[0] ) );
661 0 : pTmpEntry->aSvcRefs = Sequence< Reference < XHyphenator > >( 1 );
662 0 : aSvcMap[ nLanguage ] = pTmpEntry;
663 : }
664 0 : }
665 0 : }
666 :
667 :
668 : Sequence< OUString >
669 0 : HyphenatorDispatcher::GetServiceList( const Locale &rLocale ) const
670 : {
671 0 : MutexGuard aGuard( GetLinguMutex() );
672 :
673 0 : Sequence< OUString > aRes;
674 :
675 : // search for entry with that language and use data from that
676 0 : sal_Int16 nLanguage = LanguageTag( rLocale ).getLanguageType();
677 0 : HyphenatorDispatcher *pThis = (HyphenatorDispatcher *) this;
678 0 : const HyphSvcByLangMap_t::iterator aIt( pThis->aSvcMap.find( nLanguage ) );
679 0 : const LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
680 0 : if (pEntry)
681 : {
682 0 : aRes = pEntry->aSvcImplNames;
683 0 : if (aRes.getLength() > 0)
684 0 : aRes.realloc(1);
685 : }
686 :
687 0 : return aRes;
688 : }
689 :
690 :
691 0 : LinguDispatcher::DspType HyphenatorDispatcher::GetDspType() const
692 : {
693 0 : return DSP_HYPH;
694 : }
695 :
696 :
697 :
698 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|