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