merge the formfield patch from ooo-build
[ooovba.git] / lingucomponent / source / hyphenator / altlinuxhyph / hyphen / hyphenimp.cxx
blob15bb0a5631ce6a9c0b60f3c0195d0433e911fe73
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: hyphenimp.cxx,v $
10 * $Revision: 1.29 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_lingucomponent.hxx"
35 #include <com/sun/star/uno/Reference.h>
36 #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
38 //#include <com/sun/star/linguistic2/SpellFailure.hpp>
39 #include <cppuhelper/factory.hxx> // helper for factories
40 #include <com/sun/star/registry/XRegistryKey.hpp>
41 #include <i18npool/mslangid.hxx>
42 #include <svtools/pathoptions.hxx>
43 #include <svtools/useroptions.hxx>
44 #include <tools/debug.hxx>
45 #include <unotools/processfactory.hxx>
46 #include <osl/mutex.hxx>
48 #include <hyphen.h>
50 #ifndef _HYPHENIMP_HXX
51 #include <hyphenimp.hxx>
52 #endif
54 #include <linguistic/hyphdta.hxx>
55 #include <rtl/ustring.hxx>
57 #include <rtl/ustrbuf.hxx>
59 #include <linguistic/lngprops.hxx>
60 #include <svtools/pathoptions.hxx>
61 #include <svtools/useroptions.hxx>
62 #include <svtools/lingucfg.hxx>
63 #include <osl/file.hxx>
65 #include "dictmgr.hxx"
67 #include <stdio.h>
69 #include <list>
70 #include <set>
72 using namespace utl;
73 using namespace osl;
74 using namespace rtl;
75 using namespace com::sun::star;
76 using namespace com::sun::star::beans;
77 using namespace com::sun::star::lang;
78 using namespace com::sun::star::uno;
79 using namespace com::sun::star::linguistic2;
80 using namespace linguistic;
82 // values asigned to capitalization types
83 #define CAPTYPE_UNKNOWN 0
84 #define CAPTYPE_NOCAP 1
85 #define CAPTYPE_INITCAP 2
86 #define CAPTYPE_ALLCAP 3
87 #define CAPTYPE_MIXED 4
89 // min, max
91 //#define Min(a,b) (a < b ? a : b)
92 #define Max(a,b) (a > b ? a : b)
94 ///////////////////////////////////////////////////////////////////////////
97 Hyphenator::Hyphenator() :
98 aEvtListeners ( GetLinguMutex() )
100 bDisposing = FALSE;
101 pPropHelper = NULL;
102 aDicts = NULL;
103 numdict = 0;
108 Hyphenator::~Hyphenator()
110 if (pPropHelper)
111 pPropHelper->RemoveAsPropListener();
113 if ((numdict) && (aDicts)) {
114 for (int i=0; i < numdict; i++) {
115 if (aDicts[i].apCC) delete aDicts[i].apCC;
116 aDicts[i].apCC = NULL;
119 if (aDicts) delete[] aDicts;
120 aDicts = NULL;
121 numdict = 0;
125 PropertyHelper_Hyphen & Hyphenator::GetPropHelper_Impl()
128 if (!pPropHelper)
130 Reference< XPropertySet > xPropSet( GetLinguProperties(), UNO_QUERY );
132 pPropHelper = new PropertyHelper_Hyphen ((XHyphenator *) this, xPropSet );
133 xPropHelper = pPropHelper;
134 pPropHelper->AddAsPropListener(); //! after a reference is established
136 return *pPropHelper;
141 Sequence< Locale > SAL_CALL Hyphenator::getLocales()
142 throw(RuntimeException)
144 MutexGuard aGuard( GetLinguMutex() );
146 // this routine should return the locales supported by the installed
147 // dictionaries.
149 if (!numdict)
151 SvtLinguConfig aLinguCfg;
153 // get list of dictionaries-to-use
154 // (or better speaking: the list of dictionaries using the
155 // new configuration entries).
156 std::list< SvtLinguConfigDictionaryEntry > aDics;
157 uno::Sequence< rtl::OUString > aFormatList;
158 aLinguCfg.GetSupportedDictionaryFormatsFor( A2OU("Hyphenators"),
159 A2OU("org.openoffice.lingu.LibHnjHyphenator"), aFormatList );
160 sal_Int32 nLen = aFormatList.getLength();
161 for (sal_Int32 i = 0; i < nLen; ++i)
163 std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
164 aLinguCfg.GetActiveDictionariesByFormat( aFormatList[i] ) );
165 aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
168 //!! for compatibility with old dictionaries (the ones not using extensions
169 //!! or new configuration entries, but still using the dictionary.lst file)
170 //!! Get the list of old style spell checking dictionaries to use...
171 std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
172 GetOldStyleDics( "HYPH" ) );
174 // to prefer dictionaries with configuration entries we will only
175 // use those old style dictionaries that add a language that
176 // is not yet supported by the list od new style dictionaries
177 MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics );
179 numdict = aDics.size();
180 if (numdict)
182 // get supported locales from the dictionaries-to-use...
183 sal_Int32 k = 0;
184 std::set< rtl::OUString, lt_rtl_OUString > aLocaleNamesSet;
185 std::list< SvtLinguConfigDictionaryEntry >::const_iterator aDictIt;
186 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
188 uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
189 sal_Int32 nLen2 = aLocaleNames.getLength();
190 for (k = 0; k < nLen2; ++k)
192 aLocaleNamesSet.insert( aLocaleNames[k] );
195 // ... and add them to the resulting sequence
196 aSuppLocales.realloc( aLocaleNamesSet.size() );
197 std::set< rtl::OUString, lt_rtl_OUString >::const_iterator aItB;
198 k = 0;
199 for (aItB = aLocaleNamesSet.begin(); aItB != aLocaleNamesSet.end(); ++aItB)
201 Locale aTmp( MsLangId::convertLanguageToLocale(
202 MsLangId::convertIsoStringToLanguage( *aItB )));
203 aSuppLocales[k++] = aTmp;
206 //! For each dictionary and each locale we need a seperate entry.
207 //! If this results in more than one dictionary per locale than (for now)
208 //! it is undefined which dictionary gets used.
209 //! In the future the implementation should support using several dictionaries
210 //! for one locale.
211 numdict = 0;
212 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
213 numdict = numdict + aDictIt->aLocaleNames.getLength();
215 // add dictionary information
216 aDicts = new HDInfo[numdict];
218 aTEncs = new rtl_TextEncoding [numdict];
219 aTLocs = new Locale [numdict];
220 aTNames = new OUString [numdict];
221 aCharSetInfo = new CharClass* [numdict];
223 k = 0;
224 for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
226 if (aDictIt->aLocaleNames.getLength() > 0 &&
227 aDictIt->aLocations.getLength() > 0)
229 uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
230 sal_Int32 nLocales = aLocaleNames.getLength();
232 // currently only one language per dictionary is supported in the actual implementation...
233 // Thus here we work-around this by adding the same dictionary several times.
234 // Once for each of it's supported locales.
235 for (sal_Int32 i = 0; i < nLocales; ++i)
237 aDicts[k].aPtr = NULL;
238 aDicts[k].aEnc = 0;
239 aDicts[k].aLoc = MsLangId::convertLanguageToLocale(
240 MsLangId::convertIsoStringToLanguage( aDictIt->aLocaleNames[i] ));
241 aDicts[k].apCC = new CharClass( aDicts[k].aLoc );
242 // also both files have to be in the same directory and the
243 // file names must only differ in the extension (.aff/.dic).
244 // Thus we use the first location only and strip the extension part.
245 rtl::OUString aLocation = aDictIt->aLocations[0];
246 sal_Int32 nPos = aLocation.lastIndexOf( '.' );
247 aLocation = aLocation.copy( 0, nPos );
248 aDicts[k].aName = aLocation;
250 ++k;
254 DBG_ASSERT( k == numdict, "index mismatch?" );
256 else
258 /* no dictionary found so register no dictionaries */
259 numdict = 0;
260 aDicts = NULL;
261 aSuppLocales.realloc(0);
265 return aSuppLocales;
270 sal_Bool SAL_CALL Hyphenator::hasLocale(const Locale& rLocale)
271 throw(RuntimeException)
273 MutexGuard aGuard( GetLinguMutex() );
275 BOOL bRes = FALSE;
276 if (!aSuppLocales.getLength())
277 getLocales();
279 const Locale *pLocale = aSuppLocales.getConstArray();
280 INT32 nLen = aSuppLocales.getLength();
281 for (INT32 i = 0; i < nLen; ++i)
283 if (rLocale == pLocale[i])
285 bRes = TRUE;
286 break;
289 return bRes;
293 Reference< XHyphenatedWord > SAL_CALL
294 Hyphenator::hyphenate( const ::rtl::OUString& aWord,
295 const ::com::sun::star::lang::Locale& aLocale,
296 sal_Int16 nMaxLeading,
297 const ::com::sun::star::beans::PropertyValues& aProperties )
298 throw (com::sun::star::uno::RuntimeException,
299 com::sun::star::lang::IllegalArgumentException)
301 int nHyphenationPos = -1;
302 int nHyphenationPosAlt = -1;
303 int nHyphenationPosAltHyph = -1;
304 int wordlen;
305 char *hyphens;
306 char *lcword;
307 int k = 0;
309 PropertyHelper_Hyphen & rHelper = GetPropHelper();
310 rHelper.SetTmpPropVals(aProperties);
311 sal_Int16 minTrail = rHelper.GetMinTrailing();
312 sal_Int16 minLead = rHelper.GetMinLeading();
313 sal_Int16 minLen = rHelper.GetMinWordLength();
315 HyphenDict *dict = NULL;
316 rtl_TextEncoding aEnc = 0;
317 CharClass * pCC = NULL;
319 Reference< XHyphenatedWord > xRes;
321 k = -1;
322 for (int j = 0; j < numdict; j++)
323 if (aLocale == aDicts[j].aLoc) k = j;
326 // if we have a hyphenation dictionary matching this locale
327 if (k != -1) {
329 // if this dictinary has not been loaded yet do that
330 if (!aDicts[k].aPtr) {
332 OUString DictFN = aDicts[k].aName + A2OU(".dic");
333 OUString dictpath;
335 osl::FileBase::getSystemPathFromFileURL( DictFN, dictpath );
336 OString sTmp( OU2ENC( dictpath, osl_getThreadTextEncoding() ) );
338 #if defined(WNT)
339 // workaround for Windows specifc problem that the
340 // path length in calls to 'fopen' is limted to somewhat
341 // about 120+ characters which will usually be exceed when
342 // using dictionaries as extensions.
343 sTmp = Win_GetShortPathName( dictpath );
344 #endif
346 if ( ( dict = hnj_hyphen_load ( sTmp.getStr()) ) == NULL )
348 fprintf(stderr, "Couldn't find file %s\n", OU2ENC(dictpath, osl_getThreadTextEncoding()) );
349 return NULL;
351 aDicts[k].aPtr = dict;
352 aDicts[k].aEnc = rtl_getTextEncodingFromUnixCharset(dict->cset);
353 if (aDicts[k].aEnc == RTL_TEXTENCODING_DONTKNOW) {
354 if (strcmp("ISCII-DEVANAGARI", dict->cset) == 0) {
355 aDicts[k].aEnc = RTL_TEXTENCODING_ISCII_DEVANAGARI;
356 } else if (strcmp("UTF-8", dict->cset) == 0) {
357 aDicts[k].aEnc = RTL_TEXTENCODING_UTF8;
362 // other wise hyphenate the word with that dictionary
363 dict = aDicts[k].aPtr;
364 aEnc = aDicts[k].aEnc;
365 pCC = aDicts[k].apCC;
367 sal_uInt16 ct = CAPTYPE_UNKNOWN;
368 ct = capitalType(aWord, pCC);
370 // first convert any smart quotes or apostrophes to normal ones
371 OUStringBuffer rBuf(aWord);
372 sal_Int32 nc = rBuf.getLength();
373 sal_Unicode ch;
374 for (sal_Int32 ix=0; ix < nc; ix++) {
375 ch = rBuf.charAt(ix);
376 if ((ch == 0x201C) || (ch == 0x201D)) rBuf.setCharAt(ix,(sal_Unicode)0x0022);
377 if ((ch == 0x2018) || (ch == 0x2019)) rBuf.setCharAt(ix,(sal_Unicode)0x0027);
379 OUString nWord(rBuf.makeStringAndClear());
381 // now convert word to all lowercase for pattern recognition
382 OUString nTerm(makeLowerCase(nWord, pCC));
384 // now convert word to needed encoding
385 OString encWord(OU2ENC(nTerm,aEnc));
387 wordlen = encWord.getLength();
388 lcword = new char[wordlen + 1];
389 hyphens = new char[wordlen + 5];
391 char ** rep = NULL; // replacements of discretionary hyphenation
392 int * pos = NULL; // array of [hyphenation point] minus [deletion position]
393 int * cut = NULL; // length of deletions in original word
395 // copy converted word into simple char buffer
396 strcpy(lcword,encWord.getStr());
398 // now strip off any ending periods
399 int n = wordlen-1;
400 while((n >=0) && (lcword[n] == '.')) n--;
401 n++;
402 if (n > 0) {
403 if (hnj_hyphen_hyphenate3(dict, lcword, n, hyphens, NULL, &rep, &pos, &cut,
404 minLead, minTrail, Max(dict->clhmin, Max(dict->clhmin, 2) + Max(0, minLead - Max(dict->lhmin, 2))),
405 Max(dict->crhmin, Max(dict->crhmin, 2) + Max(0, minTrail - Max(dict->rhmin, 2)))))
407 //whoops something did not work
408 delete[] hyphens;
409 delete[] lcword;
410 if (rep) {
411 for(int j = 0; j < n; j++) {
412 if (rep[j]) free(rep[j]);
414 free(rep);
416 if (pos) free(pos);
417 if (cut) free(cut);
418 return NULL;
422 // now backfill hyphens[] for any removed trailing periods
423 for (int c = n; c < wordlen; c++) hyphens[c] = '0';
424 hyphens[wordlen] = '\0';
426 INT32 Leading = GetPosInWordToCheck( aWord, nMaxLeading );
428 for (INT32 i = 0; i < n; i++)
430 int leftrep = 0;
431 BOOL hit = (n >= minLen);
432 if (!rep || !rep[i] || (i >= n)) {
433 hit = hit && (hyphens[i]&1) && (i < Leading);
434 hit = hit && (i >= (minLead-1) );
435 hit = hit && ((n - i - 1) >= minTrail);
436 } else {
437 // calculate change character length before hyphenation point signed with '='
438 for (char * c = rep[i]; *c && (*c != '='); c++) {
439 if (aEnc == RTL_TEXTENCODING_UTF8) {
440 if (((unsigned char) *c) >> 6 != 2) leftrep++;
441 } else leftrep++;
443 hit = hit && (hyphens[i]&1) && ((i + leftrep - pos[i]) < Leading);
444 hit = hit && ((i + leftrep - pos[i]) >= (minLead-1) );
445 hit = hit && ((n - i - 1 + sal::static_int_cast< sal_sSize >(strlen(rep[i])) - leftrep - 1) >= minTrail);
447 if (hit) {
448 nHyphenationPos = i;
449 if (rep && (i < n) && rep[i]) {
450 nHyphenationPosAlt = i - pos[i];
451 nHyphenationPosAltHyph = i + leftrep - pos[i];
456 if (nHyphenationPos == -1) {
457 xRes = NULL;
458 } else {
459 if (rep && rep[nHyphenationPos]) {
460 // remove equal sign
461 char * s = rep[nHyphenationPos];
462 int eq = 0;
463 for (; *s; s++) {
464 if (*s == '=') eq = 1;
465 if (eq) *s = *(s + 1);
467 OUString repHyphlow(rep[nHyphenationPos], strlen(rep[nHyphenationPos]), aEnc);
468 OUString repHyph;
469 switch (ct) {
470 case CAPTYPE_ALLCAP:
472 repHyph = makeUpperCase(repHyphlow, pCC);
473 break;
475 case CAPTYPE_INITCAP:
477 if (nHyphenationPosAlt == 0) {
478 repHyph = makeInitCap(repHyphlow, pCC);
479 } else {
480 repHyph = repHyphlow;
482 break;
484 default:
486 repHyph = repHyphlow;
487 break;
491 // handle shortening
492 INT16 nPos = (INT16) ((nHyphenationPosAltHyph < nHyphenationPos) ?
493 nHyphenationPosAltHyph : nHyphenationPos);
494 // dicretionary hyphenation
495 xRes = new HyphenatedWord( aWord, LocaleToLanguage( aLocale ), nPos,
496 aWord.replaceAt(nHyphenationPosAlt + 1, cut[nHyphenationPos], repHyph),
497 (INT16) nHyphenationPosAltHyph);
498 } else {
499 xRes = new HyphenatedWord( aWord, LocaleToLanguage( aLocale ),
500 (INT16)nHyphenationPos, aWord, (INT16) nHyphenationPos);
504 delete[] lcword;
505 delete[] hyphens;
506 if (rep) {
507 for(int j = 0; j < n; j++) {
508 if (rep[j]) free(rep[j]);
510 free(rep);
512 if (pos) free(pos);
513 if (cut) free(cut);
514 return xRes;
516 return NULL;
520 Reference < XHyphenatedWord > SAL_CALL
521 Hyphenator::queryAlternativeSpelling( const ::rtl::OUString& /*aWord*/,
522 const ::com::sun::star::lang::Locale& /*aLocale*/,
523 sal_Int16 /*nIndex*/,
524 const ::com::sun::star::beans::PropertyValues& /*aProperties*/ )
525 throw(::com::sun::star::lang::IllegalArgumentException,
526 ::com::sun::star::uno::RuntimeException)
528 /* alternative spelling isn't supported by tex dictionaries */
529 /* XXX: OOo's extended libhjn algorithm can support alternative spellings with extended TeX dic. */
530 /* TASK: implement queryAlternativeSpelling() */
531 return NULL;
534 Reference< XPossibleHyphens > SAL_CALL
535 Hyphenator::createPossibleHyphens( const ::rtl::OUString& aWord,
536 const ::com::sun::star::lang::Locale& aLocale,
537 const ::com::sun::star::beans::PropertyValues& /*aProperties*/ )
538 throw(::com::sun::star::lang::IllegalArgumentException,
539 ::com::sun::star::uno::RuntimeException)
542 int wordlen;
543 char *hyphens;
544 char *lcword;
545 int k;
548 HyphenDict *dict = NULL;
549 rtl_TextEncoding aEnc = 0;
550 CharClass* pCC = NULL;
552 Reference< XPossibleHyphens > xRes;
554 k = -1;
555 for (int j = 0; j < numdict; j++)
556 if (aLocale == aDicts[j].aLoc) k = j;
559 // if we have a hyphenation dictionary matching this locale
560 if (k != -1) {
562 // if this dictioanry has not been loaded yet do that
563 if (!aDicts[k].aPtr) {
565 OUString DictFN = aDicts[k].aName + A2OU(".dic");
566 OUString dictpath;
568 osl::FileBase::getSystemPathFromFileURL( DictFN, dictpath );
569 OString sTmp( OU2ENC( dictpath, osl_getThreadTextEncoding() ) );
571 #if defined(WNT)
572 // workaround for Windows specifc problem that the
573 // path length in calls to 'fopen' is limted to somewhat
574 // about 120+ characters which will usually be exceed when
575 // using dictionaries as extensions.
576 sTmp = Win_GetShortPathName( dictpath );
577 #endif
579 if ( ( dict = hnj_hyphen_load ( sTmp.getStr()) ) == NULL )
581 fprintf(stderr, "Couldn't find file %s and %s\n", sTmp.getStr(), OU2ENC(dictpath, osl_getThreadTextEncoding()) );
582 return NULL;
584 aDicts[k].aPtr = dict;
585 aDicts[k].aEnc = rtl_getTextEncodingFromUnixCharset(dict->cset);
586 if (aDicts[k].aEnc == RTL_TEXTENCODING_DONTKNOW) {
587 if (strcmp("ISCII-DEVANAGARI", dict->cset) == 0) {
588 aDicts[k].aEnc = RTL_TEXTENCODING_ISCII_DEVANAGARI;
589 } else if (strcmp("UTF-8", dict->cset) == 0) {
590 aDicts[k].aEnc = RTL_TEXTENCODING_UTF8;
595 // other wise hyphenate the word with that dictionary
596 dict = aDicts[k].aPtr;
597 aEnc = aDicts[k].aEnc;
598 pCC = aDicts[k].apCC;
600 // first handle smart quotes both single and double
601 OUStringBuffer rBuf(aWord);
602 sal_Int32 nc = rBuf.getLength();
603 sal_Unicode ch;
604 for (sal_Int32 ix=0; ix < nc; ix++) {
605 ch = rBuf.charAt(ix);
606 if ((ch == 0x201C) || (ch == 0x201D)) rBuf.setCharAt(ix,(sal_Unicode)0x0022);
607 if ((ch == 0x2018) || (ch == 0x2019)) rBuf.setCharAt(ix,(sal_Unicode)0x0027);
609 OUString nWord(rBuf.makeStringAndClear());
611 // now convert word to all lowercase for pattern recognition
612 OUString nTerm(makeLowerCase(nWord, pCC));
614 // now convert word to needed encoding
615 OString encWord(OU2ENC(nTerm,aEnc));
617 wordlen = encWord.getLength();
618 lcword = new char[wordlen+1];
619 hyphens = new char[wordlen+5];
621 // copy converted word into simple char buffer
622 strcpy(lcword,encWord.getStr());
624 // first remove any trailing periods
625 int n = wordlen-1;
626 while((n >=0) && (lcword[n] == '.')) n--;
627 n++;
628 // fprintf(stderr,"hyphenate... %s\n",lcword); fflush(stderr);
629 if (n > 0) {
630 if (hnj_hyphen_hyphenate(dict, lcword, n, hyphens))
632 delete[] hyphens;
633 delete[] lcword;
634 return NULL;
637 // now backfill hyphens[] for any removed periods
638 for (int c = n; c < wordlen; c++) hyphens[c] = '0';
639 hyphens[wordlen] = '\0';
640 // fprintf(stderr,"... %s\n",hyphens); fflush(stderr);
642 INT16 nHyphCount = 0;
643 INT16 i;
645 for ( i = 0; i < encWord.getLength(); i++)
646 if (hyphens[i]&1)
647 nHyphCount++;
649 Sequence< INT16 > aHyphPos(nHyphCount);
650 INT16 *pPos = aHyphPos.getArray();
651 OUStringBuffer hyphenatedWordBuffer;
652 OUString hyphenatedWord;
653 nHyphCount = 0;
655 for (i = 0; i < encWord.getLength(); i++)
657 hyphenatedWordBuffer.append(aWord[i]);
658 if (hyphens[i]&1)
660 pPos[nHyphCount] = i;
661 hyphenatedWordBuffer.append(sal_Unicode('='));
662 nHyphCount++;
666 hyphenatedWord = hyphenatedWordBuffer.makeStringAndClear();
667 //fprintf(stderr,"result is %s\n",OU2A(hyphenatedWord));
668 //fflush(stderr);
670 xRes = new PossibleHyphens( aWord, LocaleToLanguage( aLocale ),
671 hyphenatedWord, aHyphPos );
673 delete[] hyphens;
674 delete[] lcword;
675 return xRes;
678 return NULL;
682 sal_uInt16 SAL_CALL Hyphenator::capitalType(const OUString& aTerm, CharClass * pCC)
684 sal_Int32 tlen = aTerm.getLength();
685 if ((pCC) && (tlen)) {
686 String aStr(aTerm);
687 sal_Int32 nc = 0;
688 for (xub_StrLen tindex = 0; tindex < tlen; tindex++) {
689 if (pCC->getCharacterType(aStr,tindex) &
690 ::com::sun::star::i18n::KCharacterType::UPPER) nc++;
693 if (nc == 0) return (sal_uInt16) CAPTYPE_NOCAP;
695 if (nc == tlen) return (sal_uInt16) CAPTYPE_ALLCAP;
697 if ((nc == 1) && (pCC->getCharacterType(aStr,0) &
698 ::com::sun::star::i18n::KCharacterType::UPPER))
699 return (sal_uInt16) CAPTYPE_INITCAP;
701 return (sal_uInt16) CAPTYPE_MIXED;
703 return (sal_uInt16) CAPTYPE_UNKNOWN;
706 OUString SAL_CALL Hyphenator::makeLowerCase(const OUString& aTerm, CharClass * pCC)
708 if (pCC)
709 return pCC->toLower_rtl(aTerm, 0, aTerm.getLength());
710 return aTerm;
713 OUString SAL_CALL Hyphenator::makeUpperCase(const OUString& aTerm, CharClass * pCC)
715 if (pCC)
716 return pCC->toUpper_rtl(aTerm, 0, aTerm.getLength());
717 return aTerm;
721 OUString SAL_CALL Hyphenator::makeInitCap(const OUString& aTerm, CharClass * pCC)
723 sal_Int32 tlen = aTerm.getLength();
724 if ((pCC) && (tlen)) {
725 OUString bTemp = aTerm.copy(0,1);
726 if (tlen > 1)
727 return ( pCC->toUpper_rtl(bTemp, 0, 1)
728 + pCC->toLower_rtl(aTerm,1,(tlen-1)) );
730 return pCC->toUpper_rtl(bTemp, 0, 1);
732 return aTerm;
738 Reference< XInterface > SAL_CALL Hyphenator_CreateInstance(
739 const Reference< XMultiServiceFactory > & /*rSMgr*/ )
740 throw(Exception)
743 Reference< XInterface > xService = (cppu::OWeakObject*) new Hyphenator;
744 return xService;
748 sal_Bool SAL_CALL
749 Hyphenator::addLinguServiceEventListener(
750 const Reference< XLinguServiceEventListener >& rxLstnr )
751 throw(RuntimeException)
753 MutexGuard aGuard( GetLinguMutex() );
755 BOOL bRes = FALSE;
756 if (!bDisposing && rxLstnr.is())
758 bRes = GetPropHelper().addLinguServiceEventListener( rxLstnr );
760 return bRes;
764 sal_Bool SAL_CALL
765 Hyphenator::removeLinguServiceEventListener(
766 const Reference< XLinguServiceEventListener >& rxLstnr )
767 throw(RuntimeException)
769 MutexGuard aGuard( GetLinguMutex() );
771 BOOL bRes = FALSE;
772 if (!bDisposing && rxLstnr.is())
774 DBG_ASSERT( xPropHelper.is(), "xPropHelper non existent" );
775 bRes = GetPropHelper().removeLinguServiceEventListener( rxLstnr );
777 return bRes;
781 OUString SAL_CALL
782 Hyphenator::getServiceDisplayName( const Locale& /*rLocale*/ )
783 throw(RuntimeException)
785 MutexGuard aGuard( GetLinguMutex() );
786 return A2OU( "Libhyphen Hyphenator" );
790 void SAL_CALL
791 Hyphenator::initialize( const Sequence< Any >& rArguments )
792 throw(Exception, RuntimeException)
794 MutexGuard aGuard( GetLinguMutex() );
796 if (!pPropHelper)
798 INT32 nLen = rArguments.getLength();
799 if (2 == nLen)
801 Reference< XPropertySet > xPropSet;
802 rArguments.getConstArray()[0] >>= xPropSet;
803 //rArguments.getConstArray()[1] >>= xDicList;
805 //! Pointer allows for access of the non-UNO functions.
806 //! And the reference to the UNO-functions while increasing
807 //! the ref-count and will implicitly free the memory
808 //! when the object is not longer used.
809 pPropHelper = new PropertyHelper_Hyphen( (XHyphenator *) this, xPropSet );
810 xPropHelper = pPropHelper;
811 pPropHelper->AddAsPropListener(); //! after a reference is established
813 else {
814 DBG_ERROR( "wrong number of arguments in sequence" );
821 void SAL_CALL
822 Hyphenator::dispose()
823 throw(RuntimeException)
825 MutexGuard aGuard( GetLinguMutex() );
827 if (!bDisposing)
829 bDisposing = TRUE;
830 EventObject aEvtObj( (XHyphenator *) this );
831 aEvtListeners.disposeAndClear( aEvtObj );
836 void SAL_CALL
837 Hyphenator::addEventListener( const Reference< XEventListener >& rxListener )
838 throw(RuntimeException)
840 MutexGuard aGuard( GetLinguMutex() );
842 if (!bDisposing && rxListener.is())
843 aEvtListeners.addInterface( rxListener );
847 void SAL_CALL
848 Hyphenator::removeEventListener( const Reference< XEventListener >& rxListener )
849 throw(RuntimeException)
851 MutexGuard aGuard( GetLinguMutex() );
853 if (!bDisposing && rxListener.is())
854 aEvtListeners.removeInterface( rxListener );
858 ///////////////////////////////////////////////////////////////////////////
859 // Service specific part
862 OUString SAL_CALL Hyphenator::getImplementationName()
863 throw(RuntimeException)
865 MutexGuard aGuard( GetLinguMutex() );
867 return getImplementationName_Static();
871 sal_Bool SAL_CALL Hyphenator::supportsService( const OUString& ServiceName )
872 throw(RuntimeException)
874 MutexGuard aGuard( GetLinguMutex() );
876 Sequence< OUString > aSNL = getSupportedServiceNames();
877 const OUString * pArray = aSNL.getConstArray();
878 for( INT32 i = 0; i < aSNL.getLength(); i++ )
879 if( pArray[i] == ServiceName )
880 return TRUE;
881 return FALSE;
885 Sequence< OUString > SAL_CALL Hyphenator::getSupportedServiceNames()
886 throw(RuntimeException)
888 MutexGuard aGuard( GetLinguMutex() );
890 return getSupportedServiceNames_Static();
894 Sequence< OUString > Hyphenator::getSupportedServiceNames_Static()
895 throw()
897 MutexGuard aGuard( GetLinguMutex() );
899 Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich
900 aSNS.getArray()[0] = A2OU( SN_HYPHENATOR );
901 return aSNS;
905 sal_Bool SAL_CALL Hyphenator_writeInfo(
906 void * /*pServiceManager*/, registry::XRegistryKey * pRegistryKey )
911 String aImpl( '/' );
912 aImpl += Hyphenator::getImplementationName_Static().getStr();
913 aImpl.AppendAscii( "/UNO/SERVICES" );
914 Reference< registry::XRegistryKey > xNewKey =
915 pRegistryKey->createKey( aImpl );
916 Sequence< OUString > aServices =
917 Hyphenator::getSupportedServiceNames_Static();
918 for( INT32 i = 0; i < aServices.getLength(); i++ )
919 xNewKey->createKey( aServices.getConstArray()[i] );
921 return sal_True;
923 catch(Exception &)
925 return sal_False;
930 void * SAL_CALL Hyphenator_getFactory( const sal_Char * pImplName,
931 XMultiServiceFactory * pServiceManager, void * )
933 void * pRet = 0;
934 if ( !Hyphenator::getImplementationName_Static().compareToAscii( pImplName ) )
936 Reference< XSingleServiceFactory > xFactory =
937 cppu::createOneInstanceFactory(
938 pServiceManager,
939 Hyphenator::getImplementationName_Static(),
940 Hyphenator_CreateInstance,
941 Hyphenator::getSupportedServiceNames_Static());
942 // acquire, because we return an interface pointer instead of a reference
943 xFactory->acquire();
944 pRet = xFactory.get();
946 return pRet;
950 ///////////////////////////////////////////////////////////////////////////
952 #undef CAPTYPE_UNKNOWN
953 #undef CAPTYPE_NOCAP
954 #undef CAPTYPE_INITCAP
955 #undef CAPTYPE_ALLCAP
956 #undef CAPTYPE_MIXED