fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / lingucomponent / source / hyphenator / hyphen / hyphenimp.cxx
blob435e9fbfad063fd02f60bdb6abf8966dd35686f6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #if defined(WNT)
21 #include <prewin.h>
22 #include <postwin.h>
23 #endif
25 #include <com/sun/star/uno/Reference.h>
26 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
28 #include <cppuhelper/factory.hxx>
29 #include <cppuhelper/supportsservice.hxx>
30 #include <com/sun/star/registry/XRegistryKey.hpp>
31 #include <i18nlangtag/languagetag.hxx>
32 #include <tools/debug.hxx>
33 #include <osl/mutex.hxx>
35 #include <hyphen.h>
36 #include <hyphenimp.hxx>
38 #include <linguistic/hyphdta.hxx>
39 #include <rtl/ustring.hxx>
40 #include <rtl/ustrbuf.hxx>
41 #include <rtl/textenc.h>
43 #include <linguistic/lngprops.hxx>
44 #include <linguistic/misc.hxx>
45 #include <unotools/pathoptions.hxx>
46 #include <unotools/useroptions.hxx>
47 #include <unotools/lingucfg.hxx>
48 #include <osl/file.hxx>
50 #include <stdio.h>
51 #include <string.h>
53 #include <list>
54 #include <set>
55 #include <boost/scoped_array.hpp>
57 using namespace utl;
58 using namespace osl;
59 using namespace com::sun::star;
60 using namespace com::sun::star::beans;
61 using namespace com::sun::star::lang;
62 using namespace com::sun::star::uno;
63 using namespace com::sun::star::linguistic2;
64 using namespace linguistic;
66 // min, max
67 #define Max(a,b) (a > b ? a : b)
69 Hyphenator::Hyphenator() :
70 aEvtListeners ( GetLinguMutex() )
72 bDisposing = false;
73 pPropHelper = NULL;
74 aDicts = NULL;
75 numdict = 0;
78 Hyphenator::~Hyphenator()
80 if (numdict && aDicts)
82 for (int i=0; i < numdict; ++i)
84 delete aDicts[i].apCC;
85 if (aDicts[i].aPtr)
86 hnj_hyphen_free(aDicts[i].aPtr);
89 delete[] aDicts;
91 if (pPropHelper)
93 pPropHelper->RemoveAsPropListener();
94 delete pPropHelper;
98 PropertyHelper_Hyphenation& Hyphenator::GetPropHelper_Impl()
100 if (!pPropHelper)
102 Reference< XLinguProperties > xPropSet( GetLinguProperties(), UNO_QUERY );
104 pPropHelper = new PropertyHelper_Hyphenation ((XHyphenator *) this, xPropSet );
105 pPropHelper->AddAsPropListener(); //! after a reference is established
107 return *pPropHelper;
110 Sequence< Locale > SAL_CALL Hyphenator::getLocales()
111 throw(RuntimeException, std::exception)
113 MutexGuard aGuard( GetLinguMutex() );
115 // this routine should return the locales supported by the installed
116 // dictionaries.
117 if (!numdict)
119 SvtLinguConfig aLinguCfg;
121 // get list of dictionaries-to-use
122 // (or better speaking: the list of dictionaries using the
123 // new configuration entries).
124 std::list< SvtLinguConfigDictionaryEntry > aDics;
125 uno::Sequence< OUString > aFormatList;
126 aLinguCfg.GetSupportedDictionaryFormatsFor( "Hyphenators",
127 "org.openoffice.lingu.LibHnjHyphenator", aFormatList );
128 sal_Int32 nLen = aFormatList.getLength();
129 for (sal_Int32 i = 0; i < nLen; ++i)
131 std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
132 aLinguCfg.GetActiveDictionariesByFormat( aFormatList[i] ) );
133 aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
136 //!! for compatibility with old dictionaries (the ones not using extensions
137 //!! or new configuration entries, but still using the dictionary.lst file)
138 //!! Get the list of old style spell checking dictionaries to use...
139 std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
140 GetOldStyleDics( "HYPH" ) );
142 // to prefer dictionaries with configuration entries we will only
143 // use those old style dictionaries that add a language that
144 // is not yet supported by the list od new style dictionaries
145 MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics );
147 numdict = aDics.size();
148 if (numdict)
150 // get supported locales from the dictionaries-to-use...
151 sal_Int32 k = 0;
152 std::set< OUString, lt_rtl_OUString > aLocaleNamesSet;
153 std::list< SvtLinguConfigDictionaryEntry >::const_iterator aDictIt;
154 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
156 uno::Sequence< OUString > aLocaleNames( aDictIt->aLocaleNames );
157 sal_Int32 nLen2 = aLocaleNames.getLength();
158 for (k = 0; k < nLen2; ++k)
160 aLocaleNamesSet.insert( aLocaleNames[k] );
163 // ... and add them to the resulting sequence
164 aSuppLocales.realloc( aLocaleNamesSet.size() );
165 std::set< OUString, lt_rtl_OUString >::const_iterator aItB;
166 k = 0;
167 for (aItB = aLocaleNamesSet.begin(); aItB != aLocaleNamesSet.end(); ++aItB)
169 Locale aTmp( LanguageTag::convertToLocale( *aItB ));
170 aSuppLocales[k++] = aTmp;
173 //! For each dictionary and each locale we need a separate entry.
174 //! If this results in more than one dictionary per locale than (for now)
175 //! it is undefined which dictionary gets used.
176 //! In the future the implementation should support using several dictionaries
177 //! for one locale.
178 numdict = 0;
179 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
180 numdict = numdict + aDictIt->aLocaleNames.getLength();
182 // add dictionary information
183 aDicts = new HDInfo[numdict];
185 k = 0;
186 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
188 if (aDictIt->aLocaleNames.getLength() > 0 &&
189 aDictIt->aLocations.getLength() > 0)
191 uno::Sequence< OUString > aLocaleNames( aDictIt->aLocaleNames );
192 sal_Int32 nLocales = aLocaleNames.getLength();
194 // currently only one language per dictionary is supported in the actual implementation...
195 // Thus here we work-around this by adding the same dictionary several times.
196 // Once for each of it's supported locales.
197 for (sal_Int32 i = 0; i < nLocales; ++i)
199 LanguageTag aLanguageTag( aDictIt->aLocaleNames[i] );
200 aDicts[k].aPtr = NULL;
201 aDicts[k].eEnc = RTL_TEXTENCODING_DONTKNOW;
202 aDicts[k].aLoc = aLanguageTag.getLocale();
203 aDicts[k].apCC = new CharClass( aLanguageTag );
204 // also both files have to be in the same directory and the
205 // file names must only differ in the extension (.aff/.dic).
206 // Thus we use the first location only and strip the extension part.
207 OUString aLocation = aDictIt->aLocations[0];
208 sal_Int32 nPos = aLocation.lastIndexOf( '.' );
209 aLocation = aLocation.copy( 0, nPos );
210 aDicts[k].aName = aLocation;
212 ++k;
216 DBG_ASSERT( k == numdict, "index mismatch?" );
218 else
220 // no dictionary found so register no dictionaries
221 numdict = 0;
222 aDicts = NULL;
223 aSuppLocales.realloc(0);
227 return aSuppLocales;
230 sal_Bool SAL_CALL Hyphenator::hasLocale(const Locale& rLocale)
231 throw(RuntimeException, std::exception)
233 MutexGuard aGuard( GetLinguMutex() );
235 bool bRes = false;
236 if (!aSuppLocales.getLength())
237 getLocales();
239 const Locale *pLocale = aSuppLocales.getConstArray();
240 sal_Int32 nLen = aSuppLocales.getLength();
241 for (sal_Int32 i = 0; i < nLen; ++i)
243 if (rLocale == pLocale[i])
245 bRes = true;
246 break;
249 return bRes;
252 Reference< XHyphenatedWord > SAL_CALL Hyphenator::hyphenate( const OUString& aWord,
253 const ::com::sun::star::lang::Locale& aLocale,
254 sal_Int16 nMaxLeading,
255 const ::com::sun::star::beans::PropertyValues& aProperties )
256 throw (com::sun::star::uno::RuntimeException, com::sun::star::lang::IllegalArgumentException, std::exception)
258 int k = 0;
260 PropertyHelper_Hyphenation& rHelper = GetPropHelper();
261 rHelper.SetTmpPropVals(aProperties);
262 sal_Int16 minTrail = rHelper.GetMinTrailing();
263 sal_Int16 minLead = rHelper.GetMinLeading();
264 sal_Int16 minLen = rHelper.GetMinWordLength();
266 HyphenDict *dict = NULL;
267 rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
269 Reference< XHyphenatedWord > xRes;
271 k = -1;
272 for (int j = 0; j < numdict; j++)
274 if (aLocale == aDicts[j].aLoc)
275 k = j;
278 // if we have a hyphenation dictionary matching this locale
279 if (k != -1)
281 int nHyphenationPos = -1;
282 int nHyphenationPosAlt = -1;
283 int nHyphenationPosAltHyph = -1;
285 // if this dictinary has not been loaded yet do that
286 if (!aDicts[k].aPtr)
288 OUString DictFN = aDicts[k].aName + ".dic";
289 OUString dictpath;
291 osl::FileBase::getSystemPathFromFileURL( DictFN, dictpath );
293 #if defined(WNT)
294 // Hyphen waits UTF-8 encoded paths with \\?\ long path prefix.
295 OString sTmp = Win_AddLongPathPrefix(OUStringToOString(dictpath, RTL_TEXTENCODING_UTF8));
296 #else
297 OString sTmp( OU2ENC( dictpath, osl_getThreadTextEncoding() ) );
298 #endif
300 if ( ( dict = hnj_hyphen_load ( sTmp.getStr()) ) == NULL )
302 fprintf(stderr, "Couldn't find file %s\n", OU2ENC(dictpath, osl_getThreadTextEncoding()) );
303 return NULL;
305 aDicts[k].aPtr = dict;
306 aDicts[k].eEnc = getTextEncodingFromCharset(dict->cset);
309 // other wise hyphenate the word with that dictionary
310 dict = aDicts[k].aPtr;
311 eEnc = aDicts[k].eEnc;
312 CharClass * pCC = aDicts[k].apCC;
314 // we don't want to work with a default text encoding since following incorrect
315 // results may occur only for specific text and thus may be hard to notice.
316 // Thus better always make a clean exit here if the text encoding is in question.
317 // Hopefully something not working at all will raise proper attention quickly. ;-)
318 DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
319 if (eEnc == RTL_TEXTENCODING_DONTKNOW)
320 return NULL;
322 CapType ct = capitalType(aWord, pCC);
324 // first convert any smart quotes or apostrophes to normal ones
325 OUStringBuffer rBuf(aWord);
326 sal_Int32 nc = rBuf.getLength();
327 sal_Unicode ch;
328 for (sal_Int32 ix=0; ix < nc; ix++)
330 ch = rBuf[ix];
331 if ((ch == 0x201C) || (ch == 0x201D))
332 rBuf[ix] = (sal_Unicode)0x0022;
333 if ((ch == 0x2018) || (ch == 0x2019))
334 rBuf[ix] = (sal_Unicode)0x0027;
336 OUString nWord(rBuf.makeStringAndClear());
338 // now convert word to all lowercase for pattern recognition
339 OUString nTerm(makeLowerCase(nWord, pCC));
341 // now convert word to needed encoding
342 OString encWord(OU2ENC(nTerm,eEnc));
344 int wordlen = encWord.getLength();
345 boost::scoped_array<char> lcword(new char[wordlen + 1]);
346 boost::scoped_array<char> hyphens(new char[wordlen + 5]);
348 char ** rep = NULL; // replacements of discretionary hyphenation
349 int * pos = NULL; // array of [hyphenation point] minus [deletion position]
350 int * cut = NULL; // length of deletions in original word
352 // copy converted word into simple char buffer
353 strcpy(lcword.get(),encWord.getStr());
355 // now strip off any ending periods
356 int n = wordlen-1;
357 while((n >=0) && (lcword[n] == '.'))
358 n--;
359 n++;
360 if (n > 0)
362 const bool bFailed = 0 != hnj_hyphen_hyphenate3( dict, lcword.get(), n, hyphens.get(), NULL,
363 &rep, &pos, &cut, minLead, minTrail,
364 Max(dict->clhmin, Max(dict->clhmin, 2) + Max(0, minLead - Max(dict->lhmin, 2))),
365 Max(dict->crhmin, Max(dict->crhmin, 2) + Max(0, minTrail - Max(dict->rhmin, 2))) );
366 if (bFailed)
368 // whoops something did not work
369 if (rep)
371 for(int j = 0; j < n; j++)
373 if (rep[j]) free(rep[j]);
375 free(rep);
377 if (pos) free(pos);
378 if (cut) free(cut);
379 return NULL;
383 // now backfill hyphens[] for any removed trailing periods
384 for (int c = n; c < wordlen; c++) hyphens[c] = '0';
385 hyphens[wordlen] = '\0';
387 sal_Int32 Leading = GetPosInWordToCheck( aWord, nMaxLeading );
389 for (sal_Int32 i = 0; i < n; i++)
391 int leftrep = 0;
392 bool hit = (n >= minLen);
393 if (!rep || !rep[i] || (i >= n))
395 hit = hit && (hyphens[i]&1) && (i < Leading);
396 hit = hit && (i >= (minLead-1) );
397 hit = hit && ((n - i - 1) >= minTrail);
399 else
401 // calculate change character length before hyphenation point signed with '='
402 for (char * c = rep[i]; *c && (*c != '='); c++)
404 if (eEnc == RTL_TEXTENCODING_UTF8)
406 if (((unsigned char) *c) >> 6 != 2)
407 leftrep++;
409 else
410 leftrep++;
412 hit = hit && (hyphens[i]&1) && ((i + leftrep - pos[i]) < Leading);
413 hit = hit && ((i + leftrep - pos[i]) >= (minLead-1) );
414 hit = hit && ((n - i - 1 + sal::static_int_cast< sal_sSize >(strlen(rep[i])) - leftrep - 1) >= minTrail);
416 if (hit)
418 nHyphenationPos = i;
419 if (rep && (i < n) && rep[i])
421 nHyphenationPosAlt = i - pos[i];
422 nHyphenationPosAltHyph = i + leftrep - pos[i];
427 if (nHyphenationPos == -1)
429 xRes = NULL;
431 else
433 if (rep && rep[nHyphenationPos])
435 // remove equal sign
436 char * s = rep[nHyphenationPos];
437 int eq = 0;
438 for (; *s; s++)
440 if (*s == '=') eq = 1;
441 if (eq) *s = *(s + 1);
443 OUString repHyphlow(rep[nHyphenationPos], strlen(rep[nHyphenationPos]), eEnc);
444 OUString repHyph;
445 switch (ct)
447 case CapType::ALLCAP:
449 repHyph = makeUpperCase(repHyphlow, pCC);
450 break;
452 case CapType::INITCAP:
454 if (nHyphenationPosAlt == -1)
455 repHyph = makeInitCap(repHyphlow, pCC);
456 else
457 repHyph = repHyphlow;
458 break;
460 default:
462 repHyph = repHyphlow;
463 break;
467 // handle shortening
468 sal_Int16 nPos = (sal_Int16) ((nHyphenationPosAltHyph < nHyphenationPos) ?
469 nHyphenationPosAltHyph : nHyphenationPos);
470 // dicretionary hyphenation
471 xRes = HyphenatedWord::CreateHyphenatedWord( aWord, LinguLocaleToLanguage( aLocale ), nPos,
472 aWord.replaceAt(nHyphenationPosAlt + 1, cut[nHyphenationPos], repHyph),
473 (sal_Int16) nHyphenationPosAltHyph);
475 else
477 xRes = HyphenatedWord::CreateHyphenatedWord( aWord, LinguLocaleToLanguage( aLocale ),
478 (sal_Int16)nHyphenationPos, aWord, (sal_Int16) nHyphenationPos);
482 if (rep)
484 for(int j = 0; j < n; j++)
486 if (rep[j]) free(rep[j]);
488 free(rep);
490 if (pos) free(pos);
491 if (cut) free(cut);
492 return xRes;
494 return NULL;
497 Reference < XHyphenatedWord > SAL_CALL Hyphenator::queryAlternativeSpelling(
498 const OUString& aWord,
499 const ::com::sun::star::lang::Locale& aLocale,
500 sal_Int16 nIndex,
501 const ::com::sun::star::beans::PropertyValues& aProperties )
502 throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
504 // Firstly we allow only one plus character before the hyphen to avoid to miss the right break point:
505 for (int extrachar = 1; extrachar <= 2; extrachar++)
507 Reference< XHyphenatedWord > xRes = hyphenate(aWord, aLocale, nIndex + 1 + extrachar, aProperties);
508 if (xRes.is() && xRes->isAlternativeSpelling() && xRes->getHyphenationPos() == nIndex)
509 return xRes;
511 return NULL;
514 #if defined(WNT)
515 static OString Win_GetShortPathName( const OUString &rLongPathName )
517 OString aRes;
519 sal_Unicode aShortBuffer[1024] = {0};
520 sal_Int32 nShortBufSize = SAL_N_ELEMENTS( aShortBuffer );
522 // use the version of 'GetShortPathName' that can deal with Unicode...
523 sal_Int32 nShortLen = GetShortPathNameW(
524 reinterpret_cast<LPCWSTR>( rLongPathName.getStr() ),
525 reinterpret_cast<LPWSTR>( aShortBuffer ),
526 nShortBufSize );
528 if (nShortLen < nShortBufSize) // conversion successful?
529 aRes = OString( OU2ENC( OUString( aShortBuffer, nShortLen ), osl_getThreadTextEncoding()) );
530 else
531 OSL_FAIL( "Win_GetShortPathName: buffer to short" );
533 return aRes;
535 #endif //defined(WNT)
537 Reference< XPossibleHyphens > SAL_CALL Hyphenator::createPossibleHyphens( const OUString& aWord,
538 const ::com::sun::star::lang::Locale& aLocale,
539 const ::com::sun::star::beans::PropertyValues& aProperties )
540 throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
542 PropertyHelper_Hyphenation& rHelper = GetPropHelper();
543 rHelper.SetTmpPropVals(aProperties);
544 sal_Int16 minTrail = rHelper.GetMinTrailing();
545 sal_Int16 minLead = rHelper.GetMinLeading();
546 sal_Int16 minLen = rHelper.GetMinWordLength();
548 // Resolves: fdo#41083 honour MinWordLength in "createPossibleHyphens" as
549 // well as "hyphenate"
550 if (aWord.getLength() < minLen)
552 return PossibleHyphens::CreatePossibleHyphens( aWord, LinguLocaleToLanguage( aLocale ),
553 aWord, Sequence< sal_Int16 >() );
556 int k = -1;
557 for (int j = 0; j < numdict; j++)
559 if (aLocale == aDicts[j].aLoc) k = j;
562 // if we have a hyphenation dictionary matching this locale
563 if (k != -1)
565 HyphenDict *dict = NULL;
566 // if this dictioanry has not been loaded yet do that
567 if (!aDicts[k].aPtr)
569 OUString DictFN = aDicts[k].aName + ".dic";
570 OUString dictpath;
572 osl::FileBase::getSystemPathFromFileURL( DictFN, dictpath );
573 OString sTmp( OU2ENC( dictpath, osl_getThreadTextEncoding() ) );
575 #if defined(WNT)
576 // workaround for Windows specific problem that the
577 // path length in calls to 'fopen' is limted to somewhat
578 // about 120+ characters which will usually be exceed when
579 // using dictionaries as extensions.
580 sTmp = Win_GetShortPathName( dictpath );
581 #endif
583 if ( ( dict = hnj_hyphen_load ( sTmp.getStr()) ) == NULL )
585 fprintf(stderr, "Couldn't find file %s and %s\n", sTmp.getStr(), OU2ENC(dictpath, osl_getThreadTextEncoding()) );
586 return NULL;
588 aDicts[k].aPtr = dict;
589 aDicts[k].eEnc = getTextEncodingFromCharset(dict->cset);
592 // other wise hyphenate the word with that dictionary
593 dict = aDicts[k].aPtr;
594 rtl_TextEncoding eEnc = aDicts[k].eEnc;
595 CharClass* pCC = aDicts[k].apCC;
597 // we don't want to work with a default text encoding since following incorrect
598 // results may occur only for specific text and thus may be hard to notice.
599 // Thus better always make a clean exit here if the text encoding is in question.
600 // Hopefully something not working at all will raise proper attention quickly. ;-)
601 DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
602 if (eEnc == RTL_TEXTENCODING_DONTKNOW)
603 return NULL;
605 // first handle smart quotes both single and double
606 OUStringBuffer rBuf(aWord);
607 sal_Int32 nc = rBuf.getLength();
608 sal_Unicode ch;
609 for (sal_Int32 ix=0; ix < nc; ix++)
611 ch = rBuf[ix];
612 if ((ch == 0x201C) || (ch == 0x201D))
613 rBuf[ix] = (sal_Unicode)0x0022;
614 if ((ch == 0x2018) || (ch == 0x2019))
615 rBuf[ix] = (sal_Unicode)0x0027;
617 OUString nWord(rBuf.makeStringAndClear());
619 // now convert word to all lowercase for pattern recognition
620 OUString nTerm(makeLowerCase(nWord, pCC));
622 // now convert word to needed encoding
623 OString encWord(OU2ENC(nTerm,eEnc));
625 int wordlen = encWord.getLength();
626 boost::scoped_array<char> lcword(new char[wordlen+1]);
627 boost::scoped_array<char> hyphens(new char[wordlen+5]);
628 char ** rep = NULL; // replacements of discretionary hyphenation
629 int * pos = NULL; // array of [hyphenation point] minus [deletion position]
630 int * cut = NULL; // length of deletions in original word
632 // copy converted word into simple char buffer
633 strcpy(lcword.get(),encWord.getStr());
635 // first remove any trailing periods
636 int n = wordlen-1;
637 while((n >=0) && (lcword[n] == '.'))
638 n--;
639 n++;
640 if (n > 0)
642 const bool bFailed = 0 != hnj_hyphen_hyphenate3(dict, lcword.get(), n, hyphens.get(), NULL,
643 &rep, &pos, &cut, minLead, minTrail,
644 Max(dict->clhmin, Max(dict->clhmin, 2) + Max(0, minLead - Max(dict->lhmin, 2))),
645 Max(dict->crhmin, Max(dict->crhmin, 2) + Max(0, minTrail - Max(dict->rhmin, 2))) );
646 if (bFailed)
648 if (rep)
650 for(int j = 0; j < n; j++)
652 if (rep[j]) free(rep[j]);
654 free(rep);
656 if (pos) free(pos);
657 if (cut) free(cut);
659 return NULL;
662 // now backfill hyphens[] for any removed periods
663 for (int c = n; c < wordlen; c++)
664 hyphens[c] = '0';
665 hyphens[wordlen] = '\0';
667 sal_Int16 nHyphCount = 0;
668 sal_Int16 i;
670 for ( i = 0; i < encWord.getLength(); i++)
672 if (hyphens[i]&1)
673 nHyphCount++;
676 Sequence< sal_Int16 > aHyphPos(nHyphCount);
677 sal_Int16 *pPos = aHyphPos.getArray();
678 OUStringBuffer hyphenatedWordBuffer;
679 nHyphCount = 0;
681 for (i = 0; i < nWord.getLength(); i++)
683 hyphenatedWordBuffer.append(aWord[i]);
684 // hyphenation position
685 if (hyphens[i]&1)
687 pPos[nHyphCount] = i;
688 hyphenatedWordBuffer.append('=');
689 nHyphCount++;
693 OUString hyphenatedWord = hyphenatedWordBuffer.makeStringAndClear();
695 Reference< XPossibleHyphens > xRes = PossibleHyphens::CreatePossibleHyphens(
696 aWord, LinguLocaleToLanguage( aLocale ), hyphenatedWord, aHyphPos);
698 if (rep)
700 for(int j = 0; j < n; j++)
702 if (rep[j]) free(rep[j]);
704 free(rep);
706 if (pos) free(pos);
707 if (cut) free(cut);
709 return xRes;
712 return NULL;
715 OUString SAL_CALL Hyphenator::makeLowerCase(const OUString& aTerm, CharClass * pCC)
717 if (pCC)
718 return pCC->lowercase(aTerm);
719 return aTerm;
722 OUString SAL_CALL Hyphenator::makeUpperCase(const OUString& aTerm, CharClass * pCC)
724 if (pCC)
725 return pCC->uppercase(aTerm);
726 return aTerm;
729 OUString SAL_CALL Hyphenator::makeInitCap(const OUString& aTerm, CharClass * pCC)
731 sal_Int32 tlen = aTerm.getLength();
732 if ((pCC) && (tlen))
734 OUString bTemp = aTerm.copy(0,1);
735 if (tlen > 1)
736 return ( pCC->uppercase(bTemp, 0, 1) + pCC->lowercase(aTerm,1,(tlen-1)) );
738 return pCC->uppercase(bTemp, 0, 1);
740 return aTerm;
743 Reference< XInterface > SAL_CALL Hyphenator_CreateInstance(
744 const Reference< XMultiServiceFactory > & /*rSMgr*/ )
745 throw(Exception)
747 Reference< XInterface > xService = (cppu::OWeakObject*) new Hyphenator;
748 return xService;
751 sal_Bool SAL_CALL Hyphenator::addLinguServiceEventListener(
752 const Reference< XLinguServiceEventListener >& rxLstnr )
753 throw(RuntimeException, std::exception)
755 MutexGuard aGuard( GetLinguMutex() );
757 bool bRes = false;
758 if (!bDisposing && rxLstnr.is())
760 bRes = GetPropHelper().addLinguServiceEventListener( rxLstnr );
762 return bRes;
765 sal_Bool SAL_CALL Hyphenator::removeLinguServiceEventListener(
766 const Reference< XLinguServiceEventListener >& rxLstnr )
767 throw(RuntimeException, std::exception)
769 MutexGuard aGuard( GetLinguMutex() );
771 bool bRes = false;
772 if (!bDisposing && rxLstnr.is())
774 bRes = GetPropHelper().removeLinguServiceEventListener( rxLstnr );
776 return bRes;
779 OUString SAL_CALL Hyphenator::getServiceDisplayName( const Locale& /*rLocale*/ )
780 throw(RuntimeException, std::exception)
782 MutexGuard aGuard( GetLinguMutex() );
783 return OUString( "Libhyphen Hyphenator" );
786 void SAL_CALL Hyphenator::initialize( const Sequence< Any >& rArguments )
787 throw(Exception, RuntimeException, std::exception)
789 MutexGuard aGuard( GetLinguMutex() );
791 if (!pPropHelper)
793 sal_Int32 nLen = rArguments.getLength();
794 if (2 == nLen)
796 Reference< XLinguProperties > xPropSet;
797 rArguments.getConstArray()[0] >>= xPropSet;
798 // rArguments.getConstArray()[1] >>= xDicList;
800 //! Pointer allows for access of the non-UNO functions.
801 //! And the reference to the UNO-functions while increasing
802 //! the ref-count and will implicitly free the memory
803 //! when the object is not longer used.
804 pPropHelper = new PropertyHelper_Hyphenation( (XHyphenator *) this, xPropSet );
805 pPropHelper->AddAsPropListener(); //! after a reference is established
807 else {
808 OSL_FAIL( "wrong number of arguments in sequence" );
813 void SAL_CALL Hyphenator::dispose()
814 throw(RuntimeException, std::exception)
816 MutexGuard aGuard( GetLinguMutex() );
818 if (!bDisposing)
820 bDisposing = true;
821 EventObject aEvtObj( (XHyphenator *) this );
822 aEvtListeners.disposeAndClear( aEvtObj );
823 if (pPropHelper)
825 pPropHelper->RemoveAsPropListener();
826 delete pPropHelper;
827 pPropHelper = NULL;
832 void SAL_CALL Hyphenator::addEventListener( const Reference< XEventListener >& rxListener )
833 throw(RuntimeException, std::exception)
835 MutexGuard aGuard( GetLinguMutex() );
837 if (!bDisposing && rxListener.is())
838 aEvtListeners.addInterface( rxListener );
841 void SAL_CALL Hyphenator::removeEventListener( const Reference< XEventListener >& rxListener )
842 throw(RuntimeException, std::exception)
844 MutexGuard aGuard( GetLinguMutex() );
846 if (!bDisposing && rxListener.is())
847 aEvtListeners.removeInterface( rxListener );
850 // Service specific part
851 OUString SAL_CALL Hyphenator::getImplementationName()
852 throw(RuntimeException, std::exception)
854 MutexGuard aGuard( GetLinguMutex() );
856 return getImplementationName_Static();
859 sal_Bool SAL_CALL Hyphenator::supportsService( const OUString& ServiceName )
860 throw(RuntimeException, std::exception)
862 return cppu::supportsService(this, ServiceName);
865 Sequence< OUString > SAL_CALL Hyphenator::getSupportedServiceNames()
866 throw(RuntimeException, std::exception)
868 MutexGuard aGuard( GetLinguMutex() );
870 return getSupportedServiceNames_Static();
873 Sequence< OUString > Hyphenator::getSupportedServiceNames_Static()
874 throw()
876 MutexGuard aGuard( GetLinguMutex() );
878 Sequence< OUString > aSNS( 1 ); // more than 1 service is possible, too
879 aSNS.getArray()[0] = SN_HYPHENATOR;
880 return aSNS;
883 void * SAL_CALL Hyphenator_getFactory( const sal_Char * pImplName,
884 XMultiServiceFactory * pServiceManager, void * )
886 void * pRet = 0;
887 if ( Hyphenator::getImplementationName_Static().equalsAscii( pImplName ) )
889 Reference< XSingleServiceFactory > xFactory =
890 cppu::createOneInstanceFactory(
891 pServiceManager,
892 Hyphenator::getImplementationName_Static(),
893 Hyphenator_CreateInstance,
894 Hyphenator::getSupportedServiceNames_Static());
895 // acquire, because we return an interface pointer instead of a reference
896 xFactory->acquire();
897 pRet = xFactory.get();
899 return pRet;
902 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */