LibreOffice Module lingucomponent (master) 1
hyphenimp.cxx
Go to the documentation of this file.
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 <com/sun/star/uno/Reference.h>
21
25#include <cppuhelper/weak.hxx>
26#include <com/sun/star/linguistic2/XLinguProperties.hpp>
28#include <tools/debug.hxx>
29#include <osl/mutex.hxx>
30#include <osl/thread.h>
31
32#include <hyphen.h>
33#include "hyphenimp.hxx"
34
36#include <rtl/ustring.hxx>
37#include <rtl/ustrbuf.hxx>
38#include <rtl/textenc.h>
39#include <sal/log.hxx>
40
41#include <linguistic/misc.hxx>
42#include <svtools/strings.hrc>
44#include <unotools/lingucfg.hxx>
45#include <unotools/resmgr.hxx>
46#include <osl/file.hxx>
47
48#include <stdio.h>
49#include <string.h>
50
51#include <cassert>
52#include <numeric>
53#include <vector>
54#include <set>
55#include <memory>
56
57using namespace utl;
58using namespace osl;
59using namespace com::sun::star;
60using namespace com::sun::star::beans;
61using namespace com::sun::star::lang;
62using namespace com::sun::star::uno;
63using namespace com::sun::star::linguistic2;
64using namespace linguistic;
65
67 aEvtListeners ( GetLinguMutex() )
68{
69 bDisposing = false;
70}
71
73{
74 for (auto & rInfo : mvDicts)
75 {
76 if (rInfo.aPtr)
77 hnj_hyphen_free(rInfo.aPtr);
78 }
79
80 if (pPropHelper)
81 {
82 pPropHelper->RemoveAsPropListener();
83 }
84}
85
86PropertyHelper_Hyphenation& Hyphenator::GetPropHelper_Impl()
87{
88 if (!pPropHelper)
89 {
91
92 pPropHelper.reset( new PropertyHelper_Hyphenation (static_cast<XHyphenator *>(this), xPropSet ) );
93 pPropHelper->AddAsPropListener();
94 }
95 return *pPropHelper;
96}
97
99{
100 MutexGuard aGuard( GetLinguMutex() );
101
102 // this routine should return the locales supported by the installed
103 // dictionaries.
104 if (mvDicts.empty())
105 {
106 SvtLinguConfig aLinguCfg;
107
108 // get list of dictionaries-to-use
109 // (or better speaking: the list of dictionaries using the
110 // new configuration entries).
111 std::vector< SvtLinguConfigDictionaryEntry > aDics;
112 uno::Sequence< OUString > aFormatList;
113 aLinguCfg.GetSupportedDictionaryFormatsFor( "Hyphenators",
114 "org.openoffice.lingu.LibHnjHyphenator", aFormatList );
115 for (const auto& rFormat : std::as_const(aFormatList))
116 {
117 std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
118 aLinguCfg.GetActiveDictionariesByFormat( rFormat ) );
119 aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
120 }
121
125 std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
126 GetOldStyleDics( "HYPH" ) );
127
128 // to prefer dictionaries with configuration entries we will only
129 // use those old style dictionaries that add a language that
130 // is not yet supported by the list of new style dictionaries
131 MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics );
132
133 if (!aDics.empty())
134 {
135 // get supported locales from the dictionaries-to-use...
136 std::set<OUString> aLocaleNamesSet;
137 for (auto const& dict : aDics)
138 {
139 for (const auto& rLocaleName : dict.aLocaleNames)
140 {
141 aLocaleNamesSet.insert( rLocaleName );
142 }
143 }
144 // ... and add them to the resulting sequence
145 std::vector<Locale> aLocalesVec;
146 aLocalesVec.reserve(aLocaleNamesSet.size());
147
148 std::transform(aLocaleNamesSet.begin(), aLocaleNamesSet.end(), std::back_inserter(aLocalesVec),
149 [](const OUString& localeName) { return LanguageTag::convertToLocale(localeName); });
150
152
158 sal_Int32 numdict = std::accumulate(aDics.begin(), aDics.end(), 0,
159 [](const sal_Int32 nSum, const SvtLinguConfigDictionaryEntry& dict) {
160 return nSum + dict.aLocaleNames.getLength(); });
161
162 // add dictionary information
163 mvDicts.resize(numdict);
164
165 sal_Int32 k = 0;
166 for (auto const& dict : aDics)
167 {
168 if (dict.aLocaleNames.hasElements() &&
169 dict.aLocations.hasElements())
170 {
171 // currently only one language per dictionary is supported in the actual implementation...
172 // Thus here we work-around this by adding the same dictionary several times.
173 // Once for each of its supported locales.
174 for (const auto& rLocaleName : dict.aLocaleNames)
175 {
176 LanguageTag aLanguageTag(rLocaleName);
177 mvDicts[k].aPtr = nullptr;
178 mvDicts[k].eEnc = RTL_TEXTENCODING_DONTKNOW;
179 mvDicts[k].aLoc = aLanguageTag.getLocale();
180 mvDicts[k].apCC.reset( new CharClass( std::move(aLanguageTag) ) );
181 // also both files have to be in the same directory and the
182 // file names must only differ in the extension (.aff/.dic).
183 // Thus we use the first location only and strip the extension part.
184 OUString aLocation = dict.aLocations[0];
185 sal_Int32 nPos = aLocation.lastIndexOf( '.' );
186 aLocation = aLocation.copy( 0, nPos );
187 mvDicts[k].aName = aLocation;
188
189 ++k;
190 }
191 }
192 }
193 DBG_ASSERT( k == numdict, "index mismatch?" );
194 }
195 else
196 {
197 // no dictionary found so register no dictionaries
198 mvDicts.clear();
199 aSuppLocales.realloc(0);
200 }
201 }
202
203 return aSuppLocales;
204}
205
206sal_Bool SAL_CALL Hyphenator::hasLocale(const Locale& rLocale)
207{
208 MutexGuard aGuard( GetLinguMutex() );
209
210 if (!aSuppLocales.hasElements())
211 getLocales();
212
213 return comphelper::findValue(aSuppLocales, rLocale) != -1;
214}
215
216namespace {
217bool LoadDictionary(HDInfo& rDict)
218{
219 OUString DictFN = rDict.aName + ".dic";
220 OUString dictpath;
221
222 osl::FileBase::getSystemPathFromFileURL(DictFN, dictpath);
223
224#if defined(_WIN32)
225 // hnj_hyphen_load expects UTF-8 encoded paths with \\?\ long path prefix.
226 OString sTmp = Win_AddLongPathPrefix(OUStringToOString(dictpath, RTL_TEXTENCODING_UTF8));
227#else
228 OString sTmp(OU2ENC(dictpath, osl_getThreadTextEncoding()));
229#endif
230 HyphenDict *dict = nullptr;
231 if ((dict = hnj_hyphen_load(sTmp.getStr())) == nullptr)
232 {
233 SAL_WARN(
234 "lingucomponent",
235 "Couldn't find file " << dictpath);
236 return false;
237 }
238 rDict.aPtr = dict;
239 rDict.eEnc = getTextEncodingFromCharset(dict->cset);
240 return true;
241}
242}
243
245 const css::lang::Locale& aLocale,
246 sal_Int16 nMaxLeading,
247 const css::uno::Sequence< css::beans::PropertyValue >& aProperties )
248{
249 PropertyHelper_Hyphenation& rHelper = GetPropHelper();
250 rHelper.SetTmpPropVals(aProperties);
251 sal_Int16 minTrail = rHelper.GetMinTrailing();
252 sal_Int16 minLead = rHelper.GetMinLeading();
253 sal_Int16 minLen = rHelper.GetMinWordLength();
254 bool bNoHyphenateCaps = rHelper.IsNoHyphenateCaps();
255
256 rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
257
259
260 int k = -1;
261 for (size_t j = 0; j < mvDicts.size(); ++j)
262 {
263 if (aLocale == mvDicts[j].aLoc)
264 k = j;
265 }
266
267 // if we have a hyphenation dictionary matching this locale
268 if (k != -1)
269 {
270 int nHyphenationPos = -1;
271 int nHyphenationPosAlt = -1;
272 int nHyphenationPosAltHyph = -1;
273
274 // if this dictionary has not been loaded yet do that
275 if (!mvDicts[k].aPtr)
276 {
277 if (!LoadDictionary(mvDicts[k]))
278 return nullptr;
279 }
280
281 // otherwise hyphenate the word with that dictionary
282 HyphenDict *dict = mvDicts[k].aPtr;
283 eEnc = mvDicts[k].eEnc;
284 CharClass * pCC = mvDicts[k].apCC.get();
285
286 // Don't hyphenate uppercase words if requested
287 if (bNoHyphenateCaps && aWord == makeUpperCase(aWord, pCC))
288 {
289 return nullptr;
290 }
291
292 // we don't want to work with a default text encoding since following incorrect
293 // results may occur only for specific text and thus may be hard to notice.
294 // Thus better always make a clean exit here if the text encoding is in question.
295 // Hopefully something not working at all will raise proper attention quickly. ;-)
296 DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
297 if (eEnc == RTL_TEXTENCODING_DONTKNOW)
298 return nullptr;
299
300 CapType ct = capitalType(aWord, pCC);
301
302 // first convert any smart quotes or apostrophes to normal ones
303 OUStringBuffer rBuf(aWord);
304 sal_Int32 nc = rBuf.getLength();
306 for (sal_Int32 ix=0; ix < nc; ix++)
307 {
308 ch = rBuf[ix];
309 if ((ch == 0x201C) || (ch == 0x201D))
310 rBuf[ix] = u'"';
311 if ((ch == 0x2018) || (ch == 0x2019))
312 rBuf[ix] = u'\'';
313 }
314 OUString nWord(rBuf.makeStringAndClear());
315
316 // now convert word to all lowercase for pattern recognition
317 OUString nTerm(makeLowerCase(nWord, pCC));
318
319 // now convert word to needed encoding
320 OString encWord(OU2ENC(nTerm,eEnc));
321
322 int wordlen = encWord.getLength();
323 std::unique_ptr<char[]> lcword(new char[wordlen + 1]);
324 std::unique_ptr<char[]> hyphens(new char[wordlen + 5]);
325
326 char ** rep = nullptr; // replacements of discretionary hyphenation
327 int * pos = nullptr; // array of [hyphenation point] minus [deletion position]
328 int * cut = nullptr; // length of deletions in original word
329
330 // copy converted word into simple char buffer
331 strcpy(lcword.get(),encWord.getStr());
332
333 // now strip off any ending periods
334 int n = wordlen-1;
335 while((n >=0) && (lcword[n] == '.'))
336 n--;
337 n++;
338 if (n > 0)
339 {
340 const bool bFailed = 0 != hnj_hyphen_hyphenate3( dict, lcword.get(), n, hyphens.get(), nullptr,
341 &rep, &pos, &cut, minLead, minTrail,
342 std::max<sal_Int16>(dict->clhmin, std::max<sal_Int16>(dict->clhmin, 2) + std::max(0, minLead - std::max<sal_Int16>(dict->lhmin, 2))),
343 std::max<sal_Int16>(dict->crhmin, std::max<sal_Int16>(dict->crhmin, 2) + std::max(0, minTrail - std::max<sal_Int16>(dict->rhmin, 2))) );
344 if (bFailed)
345 {
346 // whoops something did not work
347 if (rep)
348 {
349 for(int j = 0; j < n; j++)
350 {
351 if (rep[j]) free(rep[j]);
352 }
353 free(rep);
354 }
355 if (pos) free(pos);
356 if (cut) free(cut);
357 return nullptr;
358 }
359 }
360
361 // now backfill hyphens[] for any removed trailing periods
362 for (int c = n; c < wordlen; c++) hyphens[c] = '0';
363 hyphens[wordlen] = '\0';
364
365 sal_Int32 Leading = GetPosInWordToCheck( aWord, nMaxLeading );
366
367 for (sal_Int32 i = 0; i < n; i++)
368 {
369 int leftrep = 0;
370 bool hit = (n >= minLen);
371 if (!rep || !rep[i])
372 {
373 hit = hit && (hyphens[i]&1) && (i < Leading);
374 hit = hit && (i >= (minLead-1) );
375 hit = hit && ((n - i - 1) >= minTrail);
376 }
377 else
378 {
379 // calculate change character length before hyphenation point signed with '='
380 for (char * c = rep[i]; *c && (*c != '='); c++)
381 {
382 if (eEnc == RTL_TEXTENCODING_UTF8)
383 {
384 if (static_cast<unsigned char>(*c) >> 6 != 2)
385 leftrep++;
386 }
387 else
388 leftrep++;
389 }
390 hit = hit && (hyphens[i]&1) && ((i + leftrep - pos[i]) < Leading);
391 hit = hit && ((i + leftrep - pos[i]) >= (minLead-1) );
392 hit = hit && ((n - i - 1 + sal::static_int_cast< sal_sSize >(strlen(rep[i])) - leftrep - 1) >= minTrail);
393 }
394 if (hit)
395 {
396 nHyphenationPos = i;
397 if (rep && rep[i])
398 {
399 nHyphenationPosAlt = i - pos[i];
400 nHyphenationPosAltHyph = i + leftrep - pos[i];
401 }
402 }
403 }
404
405 if (nHyphenationPos == -1)
406 {
407 xRes = nullptr;
408 }
409 else
410 {
411 if (rep && rep[nHyphenationPos])
412 {
413 // remove equal sign
414 char * s = rep[nHyphenationPos];
415 int eq = 0;
416 for (; *s; s++)
417 {
418 if (*s == '=') eq = 1;
419 if (eq) *s = *(s + 1);
420 }
421 OUString repHyphlow(rep[nHyphenationPos], strlen(rep[nHyphenationPos]), eEnc);
422 OUString repHyph;
423 switch (ct)
424 {
425 case CapType::ALLCAP:
426 {
427 repHyph = makeUpperCase(repHyphlow, pCC);
428 break;
429 }
430 case CapType::INITCAP:
431 {
432 if (nHyphenationPosAlt == -1)
433 repHyph = makeInitCap(repHyphlow, pCC);
434 else
435 repHyph = repHyphlow;
436 break;
437 }
438 default:
439 {
440 repHyph = repHyphlow;
441 break;
442 }
443 }
444
445 // handle shortening
446 sal_Int16 nPos = static_cast<sal_Int16>((nHyphenationPosAltHyph < nHyphenationPos) ?
447 nHyphenationPosAltHyph : nHyphenationPos);
448 // discretionary hyphenation
449 xRes = HyphenatedWord::CreateHyphenatedWord( aWord, LinguLocaleToLanguage( aLocale ), nPos,
450 aWord.replaceAt(nHyphenationPosAlt + 1, cut[nHyphenationPos], repHyph),
451 static_cast<sal_Int16>(nHyphenationPosAltHyph));
452 }
453 else
454 {
455 xRes = HyphenatedWord::CreateHyphenatedWord( aWord, LinguLocaleToLanguage( aLocale ),
456 static_cast<sal_Int16>(nHyphenationPos), aWord, static_cast<sal_Int16>(nHyphenationPos));
457 }
458 }
459
460 if (rep)
461 {
462 for(int j = 0; j < n; j++)
463 {
464 if (rep[j]) free(rep[j]);
465 }
466 free(rep);
467 }
468 if (pos) free(pos);
469 if (cut) free(cut);
470 return xRes;
471 }
472 return nullptr;
473}
474
476 const OUString& aWord,
477 const css::lang::Locale& aLocale,
478 sal_Int16 nIndex,
479 const css::uno::Sequence< css::beans::PropertyValue >& aProperties )
480{
481 // Firstly we allow only one plus character before the hyphen to avoid to miss the right break point:
482 for (int extrachar = 1; extrachar <= 2; extrachar++)
483 {
484 Reference< XHyphenatedWord > xRes = hyphenate(aWord, aLocale, nIndex + 1 + extrachar, aProperties);
485 if (xRes.is() && xRes->isAlternativeSpelling() && xRes->getHyphenationPos() == nIndex)
486 return xRes;
487 }
488 return nullptr;
489}
490
492 const css::lang::Locale& aLocale,
493 const css::uno::Sequence< css::beans::PropertyValue >& aProperties )
494{
495 PropertyHelper_Hyphenation& rHelper = GetPropHelper();
496 rHelper.SetTmpPropVals(aProperties);
497 sal_Int16 minTrail = rHelper.GetMinTrailing();
498 sal_Int16 minLead = rHelper.GetMinLeading();
499 sal_Int16 minLen = rHelper.GetMinWordLength();
500
501 // Resolves: fdo#41083 honour MinWordLength in "createPossibleHyphens" as
502 // well as "hyphenate"
503 if (aWord.getLength() < minLen)
504 {
505 return PossibleHyphens::CreatePossibleHyphens( aWord, LinguLocaleToLanguage( aLocale ),
506 aWord, Sequence< sal_Int16 >() );
507 }
508
509 int k = -1;
510 for (size_t j = 0; j < mvDicts.size(); ++j)
511 {
512 if (aLocale == mvDicts[j].aLoc)
513 k = j;
514 }
515
516 // if we have a hyphenation dictionary matching this locale
517 if (k != -1)
518 {
519 HyphenDict *dict = nullptr;
520 // if this dictionary has not been loaded yet do that
521 if (!mvDicts[k].aPtr)
522 {
523 if (!LoadDictionary(mvDicts[k]))
524 return nullptr;
525 }
526
527 // otherwise hyphenate the word with that dictionary
528 dict = mvDicts[k].aPtr;
529 rtl_TextEncoding eEnc = mvDicts[k].eEnc;
530 CharClass* pCC = mvDicts[k].apCC.get();
531
532 // we don't want to work with a default text encoding since following incorrect
533 // results may occur only for specific text and thus may be hard to notice.
534 // Thus better always make a clean exit here if the text encoding is in question.
535 // Hopefully something not working at all will raise proper attention quickly. ;-)
536 DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
537 if (eEnc == RTL_TEXTENCODING_DONTKNOW)
538 return nullptr;
539
540 // first handle smart quotes both single and double
541 OUStringBuffer rBuf(aWord);
542 sal_Int32 nc = rBuf.getLength();
544 for (sal_Int32 ix=0; ix < nc; ix++)
545 {
546 ch = rBuf[ix];
547 if ((ch == 0x201C) || (ch == 0x201D))
548 rBuf[ix] = u'"';
549 if ((ch == 0x2018) || (ch == 0x2019))
550 rBuf[ix] = u'\'';
551 }
552 OUString nWord(rBuf.makeStringAndClear());
553
554 // now convert word to all lowercase for pattern recognition
555 OUString nTerm(makeLowerCase(nWord, pCC));
556
557 // now convert word to needed encoding
558 OString encWord(OU2ENC(nTerm,eEnc));
559
560 sal_Int32 wordlen = encWord.getLength();
561 std::unique_ptr<char[]> lcword(new char[wordlen+1]);
562 std::unique_ptr<char[]> hyphens(new char[wordlen+5]);
563 char ** rep = nullptr; // replacements of discretionary hyphenation
564 int * pos = nullptr; // array of [hyphenation point] minus [deletion position]
565 int * cut = nullptr; // length of deletions in original word
566
567 // copy converted word into simple char buffer
568 strcpy(lcword.get(),encWord.getStr());
569
570 // first remove any trailing periods
571 sal_Int32 n = wordlen-1;
572 while((n >=0) && (lcword[n] == '.'))
573 n--;
574 n++;
575 if (n > 0)
576 {
577 const bool bFailed = 0 != hnj_hyphen_hyphenate3(dict, lcword.get(), n, hyphens.get(), nullptr,
578 &rep, &pos, &cut, minLead, minTrail,
579 std::max<sal_Int16>(dict->clhmin, std::max<sal_Int16>(dict->clhmin, 2) + std::max(0, minLead - std::max<sal_Int16>(dict->lhmin, 2))),
580 std::max<sal_Int16>(dict->crhmin, std::max<sal_Int16>(dict->crhmin, 2) + std::max(0, minTrail - std::max<sal_Int16>(dict->rhmin, 2))) );
581 if (bFailed)
582 {
583 if (rep)
584 {
585 for(int j = 0; j < n; j++)
586 {
587 if (rep[j]) free(rep[j]);
588 }
589 free(rep);
590 }
591 if (pos) free(pos);
592 if (cut) free(cut);
593
594 return nullptr;
595 }
596 }
597 // now backfill hyphens[] for any removed periods
598 for (sal_Int32 c = n; c < wordlen; c++)
599 hyphens[c] = '0';
600 hyphens[wordlen] = '\0';
601
602 sal_Int32 nHyphCount = 0;
603
604 for ( sal_Int32 i = 0; i < encWord.getLength(); i++)
605 {
606 if (hyphens[i]&1)
607 nHyphCount++;
608 }
609
610 Sequence< sal_Int16 > aHyphPos(nHyphCount);
611 sal_Int16 *pPos = aHyphPos.getArray();
612 OUStringBuffer hyphenatedWordBuffer;
613 nHyphCount = 0;
614
615 for (sal_Int32 i = 0; i < nWord.getLength(); i++)
616 {
617 hyphenatedWordBuffer.append(aWord[i]);
618 // hyphenation position
619 if (hyphens[i]&1)
620 {
621 // linguistic::PossibleHyphens is stuck with
622 // css::uno::Sequence<sal_Int16> because of
623 // css.linguistic2.XPossibleHyphens.getHyphenationPositions, so
624 // any further positions need to be ignored:
625 assert(i >= SAL_MIN_INT16);
626 if (i > SAL_MAX_INT16)
627 {
628 SAL_WARN(
629 "lingucomponent",
630 "hyphen pos " << i << " > SAL_MAX_INT16 in \"" << aWord
631 << "\"");
632 continue;
633 }
634 pPos[nHyphCount] = i;
635 hyphenatedWordBuffer.append('=');
636 nHyphCount++;
637 }
638 }
639
640 OUString hyphenatedWord = hyphenatedWordBuffer.makeStringAndClear();
641
642 Reference< XPossibleHyphens > xRes = PossibleHyphens::CreatePossibleHyphens(
643 aWord, LinguLocaleToLanguage( aLocale ), hyphenatedWord, aHyphPos);
644
645 if (rep)
646 {
647 for(int j = 0; j < n; j++)
648 {
649 if (rep[j]) free(rep[j]);
650 }
651 free(rep);
652 }
653 if (pos) free(pos);
654 if (cut) free(cut);
655
656 return xRes;
657 }
658
659 return nullptr;
660}
661
662OUString Hyphenator::makeLowerCase(const OUString& aTerm, CharClass const * pCC)
663{
664 if (pCC)
665 return pCC->lowercase(aTerm);
666 return aTerm;
667}
668
669OUString Hyphenator::makeUpperCase(const OUString& aTerm, CharClass const * pCC)
670{
671 if (pCC)
672 return pCC->uppercase(aTerm);
673 return aTerm;
674}
675
676OUString Hyphenator::makeInitCap(const OUString& aTerm, CharClass const * pCC)
677{
678 sal_Int32 tlen = aTerm.getLength();
679 if (pCC && tlen)
680 {
681 OUString bTemp = aTerm.copy(0,1);
682 if (tlen > 1)
683 return ( pCC->uppercase(bTemp, 0, 1) + pCC->lowercase(aTerm,1,(tlen-1)) );
684
685 return pCC->uppercase(bTemp, 0, 1);
686 }
687 return aTerm;
688}
689
692{
693 MutexGuard aGuard( GetLinguMutex() );
694
695 bool bRes = false;
696 if (!bDisposing && rxLstnr.is())
697 {
698 bRes = GetPropHelper().addLinguServiceEventListener( rxLstnr );
699 }
700 return bRes;
701}
702
705{
706 MutexGuard aGuard( GetLinguMutex() );
707
708 bool bRes = false;
709 if (!bDisposing && rxLstnr.is())
710 {
711 bRes = GetPropHelper().removeLinguServiceEventListener( rxLstnr );
712 }
713 return bRes;
714}
715
716OUString SAL_CALL Hyphenator::getServiceDisplayName(const Locale& rLocale)
717{
718 std::locale loc(Translate::Create("svt", LanguageTag(rLocale)));
719 return Translate::get(STR_DESCRIPTION_LIBHYPHEN, loc);
720}
721
722void SAL_CALL Hyphenator::initialize( const Sequence< Any >& rArguments )
723{
724 MutexGuard aGuard( GetLinguMutex() );
725
726 if (pPropHelper)
727 return;
728
729 sal_Int32 nLen = rArguments.getLength();
730 if (2 == nLen)
731 {
733 rArguments.getConstArray()[0] >>= xPropSet;
734 // rArguments.getConstArray()[1] >>= xDicList;
735
740 pPropHelper.reset( new PropertyHelper_Hyphenation( static_cast<XHyphenator *>(this), xPropSet ) );
741 pPropHelper->AddAsPropListener();
742 }
743 else {
744 OSL_FAIL( "wrong number of arguments in sequence" );
745 }
746}
747
748void SAL_CALL Hyphenator::dispose()
749{
750 MutexGuard aGuard( GetLinguMutex() );
751
752 if (!bDisposing)
753 {
754 bDisposing = true;
755 EventObject aEvtObj( static_cast<XHyphenator *>(this) );
757 if (pPropHelper)
758 {
759 pPropHelper->RemoveAsPropListener();
760 pPropHelper.reset();
761 }
762 }
763}
764
766{
767 MutexGuard aGuard( GetLinguMutex() );
768
769 if (!bDisposing && rxListener.is())
770 aEvtListeners.addInterface( rxListener );
771}
772
774{
775 MutexGuard aGuard( GetLinguMutex() );
776
777 if (!bDisposing && rxListener.is())
778 aEvtListeners.removeInterface( rxListener );
779}
780
781// Service specific part
783{
784 return "org.openoffice.lingu.LibHnjHyphenator";
785}
786
787sal_Bool SAL_CALL Hyphenator::supportsService( const OUString& ServiceName )
788{
790}
791
793{
794 return { SN_HYPHENATOR };
795}
796
797extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
799 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
800{
801 return cppu::acquire(new Hyphenator());
802}
803
804
805/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
OUString lowercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
static OUString makeLowerCase(const OUString &, CharClass const *)
Definition: hyphenimp.cxx:662
std::vector< HDInfo > mvDicts
Definition: hyphenimp.hxx:69
virtual sal_Bool SAL_CALL removeLinguServiceEventListener(const Reference< XLinguServiceEventListener > &rxLstnr) override
Definition: hyphenimp.cxx:703
virtual void SAL_CALL addEventListener(const Reference< XEventListener > &rxListener) override
Definition: hyphenimp.cxx:765
linguistic::PropertyHelper_Hyphenation & GetPropHelper()
Definition: hyphenimp.hxx:79
virtual Sequence< Locale > SAL_CALL getLocales() override
Definition: hyphenimp.cxx:98
virtual css::uno::Reference< css::linguistic2::XPossibleHyphens > SAL_CALL createPossibleHyphens(const OUString &aWord, const css::lang::Locale &aLocale, const css::uno::Sequence< css::beans::PropertyValue > &aProperties) override
Definition: hyphenimp.cxx:491
std::unique_ptr< linguistic::PropertyHelper_Hyphenation > pPropHelper
Definition: hyphenimp.hxx:72
virtual sal_Bool SAL_CALL addLinguServiceEventListener(const Reference< XLinguServiceEventListener > &rxLstnr) override
Definition: hyphenimp.cxx:690
virtual css::uno::Reference< css::linguistic2::XHyphenatedWord > SAL_CALL hyphenate(const OUString &aWord, const css::lang::Locale &aLocale, sal_Int16 nMaxLeading, const css::uno::Sequence< css::beans::PropertyValue > &aProperties) override
Definition: hyphenimp.cxx:244
virtual sal_Bool SAL_CALL hasLocale(const Locale &rLocale) override
Definition: hyphenimp.cxx:206
::comphelper::OInterfaceContainerHelper3< XEventListener > aEvtListeners
Definition: hyphenimp.hxx:71
static OUString makeUpperCase(const OUString &, CharClass const *)
Definition: hyphenimp.cxx:669
virtual void SAL_CALL dispose() override
Definition: hyphenimp.cxx:748
virtual OUString SAL_CALL getImplementationName() override
Definition: hyphenimp.cxx:782
Sequence< Locale > aSuppLocales
Definition: hyphenimp.hxx:68
static OUString makeInitCap(const OUString &, CharClass const *)
Definition: hyphenimp.cxx:676
virtual void SAL_CALL removeEventListener(const Reference< XEventListener > &rxListener) override
Definition: hyphenimp.cxx:773
virtual void SAL_CALL initialize(const Sequence< Any > &rArguments) override
Definition: hyphenimp.cxx:722
virtual OUString SAL_CALL getServiceDisplayName(const Locale &rLocale) override
Definition: hyphenimp.cxx:716
virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override
Definition: hyphenimp.cxx:792
bool bDisposing
Definition: hyphenimp.hxx:73
virtual ~Hyphenator() override
Definition: hyphenimp.cxx:72
linguistic::PropertyHelper_Hyphenation & GetPropHelper_Impl()
Definition: hyphenimp.cxx:86
virtual css::uno::Reference< css::linguistic2::XHyphenatedWord > SAL_CALL queryAlternativeSpelling(const OUString &aWord, const css::lang::Locale &aLocale, sal_Int16 nIndex, const css::uno::Sequence< css::beans::PropertyValue > &aProperties) override
Definition: hyphenimp.cxx:475
virtual sal_Bool SAL_CALL supportsService(const OUString &rServiceName) override
Definition: hyphenimp.cxx:787
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
std::vector< SvtLinguConfigDictionaryEntry > GetActiveDictionariesByFormat(std::u16string_view rFormatName) const
bool GetSupportedDictionaryFormatsFor(const OUString &rSetName, const OUString &rSetEntry, css::uno::Sequence< OUString > &rFormatList) const
sal_Int32 addInterface(const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(const css::uno::Reference< ListenerT > &rxIFace)
#define DBG_ASSERT(sCon, aError)
float u
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * lingucomponent_Hyphenator_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: hyphenimp.cxx:798
sal_Int32 nIndex
sal_Int64 n
std::vector< SvtLinguConfigDictionaryEntry > GetOldStyleDics(const char *pDicType)
Definition: lingutil.cxx:146
void MergeNewStyleDicsAndOldStyleDics(std::vector< SvtLinguConfigDictionaryEntry > &rNewStyleDics, const std::vector< SvtLinguConfigDictionaryEntry > &rOldStyleDics)
Definition: lingutil.cxx:252
rtl_TextEncoding getTextEncodingFromCharset(const char *pCharset)
Definition: lingutil.cxx:295
#define OU2ENC(rtlOUString, rtlEncoding)
Definition: lingutil.hxx:27
sal_uInt16 nPos
#define SAL_WARN(area, stream)
constexpr OUStringLiteral SN_HYPHENATOR
std::locale Create(std::string_view aPrefixName, const LanguageTag &rLocale)
OUString get(TranslateId sContextAndId, const std::locale &loc)
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
CapType
uno::Reference< XLinguProperties > GetLinguProperties()
CapType capitalType(const OUString &aTerm, CharClass const *pCC)
sal_Int32 GetPosInWordToCheck(std::u16string_view rTxt, sal_Int32 nPos)
osl::Mutex & GetLinguMutex()
LanguageType LinguLocaleToLanguage(const css::lang::Locale &rLocale)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
rtl_TextEncoding eEnc
Definition: hyphenimp.hxx:53
HyphenDict * aPtr
Definition: hyphenimp.hxx:50
OUString aName
Definition: hyphenimp.hxx:51
css::uno::Sequence< OUString > aLocaleNames
css::uno::Sequence< OUString > aLocations
unsigned char sal_Bool
#define SAL_MIN_INT16
#define SAL_MAX_INT16
sal_uInt16 sal_Unicode
size_t pos