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