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