1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 #include <com/sun/star/uno/Reference.h>
22 #include <comphelper/sequence.hxx>
23 #include <cppuhelper/factory.hxx>
24 #include <cppuhelper/supportsservice.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>
28 #include <i18nlangtag/languagetag.hxx>
29 #include <tools/debug.hxx>
30 #include <osl/mutex.hxx>
31 #include <osl/thread.h>
34 #include "hyphenimp.hxx"
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>
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>
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
;
70 Hyphenator::Hyphenator() :
71 aEvtListeners ( GetLinguMutex() )
76 Hyphenator::~Hyphenator()
78 for (auto & rInfo
: mvDicts
)
81 hnj_hyphen_free(rInfo
.aPtr
);
86 pPropHelper
->RemoveAsPropListener();
90 PropertyHelper_Hyphenation
& Hyphenator::GetPropHelper_Impl()
94 Reference
< XLinguProperties
> xPropSet
= GetLinguProperties();
96 pPropHelper
.reset( new PropertyHelper_Hyphenation (static_cast<XHyphenator
*>(this), xPropSet
) );
97 pPropHelper
->AddAsPropListener(); //! after a reference is established
102 Sequence
< Locale
> SAL_CALL
Hyphenator::getLocales()
104 MutexGuard
aGuard( GetLinguMutex() );
106 // this routine should return the locales supported by the installed
110 SvtLinguConfig aLinguCfg
;
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
))
121 std::vector
< SvtLinguConfigDictionaryEntry
> aTmpDic(
122 aLinguCfg
.GetActiveDictionariesByFormat( rFormat
) );
123 aDics
.insert( aDics
.end(), aTmpDic
.begin(), aTmpDic
.end() );
126 //!! for compatibility with old dictionaries (the ones not using extensions
127 //!! or new configuration entries, but still using the dictionary.lst file)
128 //!! Get the list of old style spell checking dictionaries to use...
129 std::vector
< SvtLinguConfigDictionaryEntry
> aOldStyleDics(
130 GetOldStyleDics( "HYPH" ) );
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
);
139 // get supported locales from the dictionaries-to-use...
140 std::set
<OUString
> aLocaleNamesSet
;
141 for (auto const& dict
: aDics
)
143 for (const auto& rLocaleName
: dict
.aLocaleNames
)
145 aLocaleNamesSet
.insert( rLocaleName
);
148 // ... and add them to the resulting sequence
149 std::vector
<Locale
> aLocalesVec
;
150 aLocalesVec
.reserve(aLocaleNamesSet
.size());
152 std::transform(aLocaleNamesSet
.begin(), aLocaleNamesSet
.end(), std::back_inserter(aLocalesVec
),
153 [](const OUString
& localeName
) { return LanguageTag::convertToLocale(localeName
); });
155 aSuppLocales
= comphelper::containerToSequence(aLocalesVec
);
157 //! For each dictionary and each locale we need a separate entry.
158 //! If this results in more than one dictionary per locale than (for now)
159 //! it is undefined which dictionary gets used.
160 //! In the future the implementation should support using several dictionaries
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(); });
166 // add dictionary information
167 mvDicts
.resize(numdict
);
170 for (auto const& dict
: aDics
)
172 if (dict
.aLocaleNames
.hasElements() &&
173 dict
.aLocations
.hasElements())
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
)
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
;
197 DBG_ASSERT( k
== numdict
, "index mismatch?" );
201 // no dictionary found so register no dictionaries
203 aSuppLocales
.realloc(0);
210 sal_Bool SAL_CALL
Hyphenator::hasLocale(const Locale
& rLocale
)
212 MutexGuard
aGuard( GetLinguMutex() );
214 if (!aSuppLocales
.hasElements())
217 return comphelper::findValue(aSuppLocales
, rLocale
) != -1;
221 bool LoadDictionary(HDInfo
& rDict
)
223 OUString DictFN
= rDict
.aName
+ ".dic";
226 osl::FileBase::getSystemPathFromFileURL(DictFN
, dictpath
);
229 // hnj_hyphen_load expects UTF-8 encoded paths with \\?\ long path prefix.
230 OString sTmp
= Win_AddLongPathPrefix(OUStringToOString(dictpath
, RTL_TEXTENCODING_UTF8
));
232 OString
sTmp(OU2ENC(dictpath
, osl_getThreadTextEncoding()));
234 HyphenDict
*dict
= nullptr;
235 if ((dict
= hnj_hyphen_load(sTmp
.getStr())) == nullptr)
239 "Couldn't find file " << dictpath
);
243 rDict
.eEnc
= getTextEncodingFromCharset(dict
->cset
);
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
)
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();
260 HyphenDict
*dict
= nullptr;
261 rtl_TextEncoding eEnc
= RTL_TEXTENCODING_DONTKNOW
;
263 Reference
< XHyphenatedWord
> xRes
;
266 for (size_t j
= 0; j
< mvDicts
.size(); ++j
)
268 if (aLocale
== mvDicts
[j
].aLoc
)
272 // if we have a hyphenation dictionary matching this locale
275 int nHyphenationPos
= -1;
276 int nHyphenationPosAlt
= -1;
277 int nHyphenationPosAltHyph
= -1;
279 // if this dictionary has not been loaded yet do that
280 if (!mvDicts
[k
].aPtr
)
282 if (!LoadDictionary(mvDicts
[k
]))
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();
291 // Don't hyphenate uppercase words if requested
292 if (bNoHyphenateCaps
&& aWord
== makeUpperCase(aWord
, pCC
))
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
)
305 CapType ct
= capitalType(aWord
, pCC
);
307 // first convert any smart quotes or apostrophes to normal ones
308 OUStringBuffer
rBuf(aWord
);
309 sal_Int32 nc
= rBuf
.getLength();
311 for (sal_Int32 ix
=0; ix
< nc
; ix
++)
314 if ((ch
== 0x201C) || (ch
== 0x201D))
316 if ((ch
== 0x2018) || (ch
== 0x2019))
319 OUString
nWord(rBuf
.makeStringAndClear());
321 // now convert word to all lowercase for pattern recognition
322 OUString
nTerm(makeLowerCase(nWord
, pCC
));
324 // now convert word to needed encoding
325 OString
encWord(OU2ENC(nTerm
,eEnc
));
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]);
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
335 // copy converted word into simple char buffer
336 strcpy(lcword
.get(),encWord
.getStr());
338 // now strip off any ending periods
340 while((n
>=0) && (lcword
[n
] == '.'))
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))) );
351 // whoops something did not work
354 for(int j
= 0; j
< n
; j
++)
356 if (rep
[j
]) free(rep
[j
]);
366 // now backfill hyphens[] for any removed trailing periods
367 for (int c
= n
; c
< wordlen
; c
++) hyphens
[c
] = '0';
368 hyphens
[wordlen
] = '\0';
370 sal_Int32 Leading
= GetPosInWordToCheck( aWord
, nMaxLeading
);
372 for (sal_Int32 i
= 0; i
< n
; i
++)
375 bool hit
= (n
>= minLen
);
378 hit
= hit
&& (hyphens
[i
]&1) && (i
< Leading
);
379 hit
= hit
&& (i
>= (minLead
-1) );
380 hit
= hit
&& ((n
- i
- 1) >= minTrail
);
384 // calculate change character length before hyphenation point signed with '='
385 for (char * c
= rep
[i
]; *c
&& (*c
!= '='); c
++)
387 if (eEnc
== RTL_TEXTENCODING_UTF8
)
389 if (static_cast<unsigned char>(*c
) >> 6 != 2)
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
);
404 nHyphenationPosAlt
= i
- pos
[i
];
405 nHyphenationPosAltHyph
= i
+ leftrep
- pos
[i
];
410 if (nHyphenationPos
== -1)
416 if (rep
&& rep
[nHyphenationPos
])
419 char * s
= rep
[nHyphenationPos
];
423 if (*s
== '=') eq
= 1;
424 if (eq
) *s
= *(s
+ 1);
426 OUString
repHyphlow(rep
[nHyphenationPos
], strlen(rep
[nHyphenationPos
]), eEnc
);
430 case CapType::ALLCAP
:
432 repHyph
= makeUpperCase(repHyphlow
, pCC
);
435 case CapType::INITCAP
:
437 if (nHyphenationPosAlt
== -1)
438 repHyph
= makeInitCap(repHyphlow
, pCC
);
440 repHyph
= repHyphlow
;
445 repHyph
= repHyphlow
;
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
));
460 xRes
= HyphenatedWord::CreateHyphenatedWord( aWord
, LinguLocaleToLanguage( aLocale
),
461 static_cast<sal_Int16
>(nHyphenationPos
), aWord
, static_cast<sal_Int16
>(nHyphenationPos
));
467 for(int j
= 0; j
< n
; j
++)
469 if (rep
[j
]) free(rep
[j
]);
480 Reference
< XHyphenatedWord
> SAL_CALL
Hyphenator::queryAlternativeSpelling(
481 const OUString
& aWord
,
482 const css::lang::Locale
& aLocale
,
484 const css::uno::Sequence
< css::beans::PropertyValue
>& aProperties
)
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
++)
489 Reference
< XHyphenatedWord
> xRes
= hyphenate(aWord
, aLocale
, nIndex
+ 1 + extrachar
, aProperties
);
490 if (xRes
.is() && xRes
->isAlternativeSpelling() && xRes
->getHyphenationPos() == nIndex
)
496 Reference
< XPossibleHyphens
> SAL_CALL
Hyphenator::createPossibleHyphens( const OUString
& aWord
,
497 const css::lang::Locale
& aLocale
,
498 const css::uno::Sequence
< css::beans::PropertyValue
>& aProperties
)
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();
506 // Resolves: fdo#41083 honour MinWordLength in "createPossibleHyphens" as
507 // well as "hyphenate"
508 if (aWord
.getLength() < minLen
)
510 return PossibleHyphens::CreatePossibleHyphens( aWord
, LinguLocaleToLanguage( aLocale
),
511 aWord
, Sequence
< sal_Int16
>() );
515 for (size_t j
= 0; j
< mvDicts
.size(); ++j
)
517 if (aLocale
== mvDicts
[j
].aLoc
)
521 // if we have a hyphenation dictionary matching this locale
524 HyphenDict
*dict
= nullptr;
525 // if this dictionary has not been loaded yet do that
526 if (!mvDicts
[k
].aPtr
)
528 if (!LoadDictionary(mvDicts
[k
]))
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();
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
)
545 // first handle smart quotes both single and double
546 OUStringBuffer
rBuf(aWord
);
547 sal_Int32 nc
= rBuf
.getLength();
549 for (sal_Int32 ix
=0; ix
< nc
; ix
++)
552 if ((ch
== 0x201C) || (ch
== 0x201D))
554 if ((ch
== 0x2018) || (ch
== 0x2019))
557 OUString
nWord(rBuf
.makeStringAndClear());
559 // now convert word to all lowercase for pattern recognition
560 OUString
nTerm(makeLowerCase(nWord
, pCC
));
562 // now convert word to needed encoding
563 OString
encWord(OU2ENC(nTerm
,eEnc
));
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
572 // copy converted word into simple char buffer
573 strcpy(lcword
.get(),encWord
.getStr());
575 // first remove any trailing periods
576 sal_Int32 n
= wordlen
-1;
577 while((n
>=0) && (lcword
[n
] == '.'))
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))) );
590 for(int j
= 0; j
< n
; j
++)
592 if (rep
[j
]) free(rep
[j
]);
602 // now backfill hyphens[] for any removed periods
603 for (sal_Int32 c
= n
; c
< wordlen
; c
++)
605 hyphens
[wordlen
] = '\0';
607 sal_Int32 nHyphCount
= 0;
609 for ( sal_Int32 i
= 0; i
< encWord
.getLength(); i
++)
615 Sequence
< sal_Int16
> aHyphPos(nHyphCount
);
616 sal_Int16
*pPos
= aHyphPos
.getArray();
617 OUStringBuffer hyphenatedWordBuffer
;
620 for (sal_Int32 i
= 0; i
< nWord
.getLength(); i
++)
622 hyphenatedWordBuffer
.append(aWord
[i
]);
623 // hyphenation position
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
)
635 "hyphen pos " << i
<< " > SAL_MAX_INT16 in \"" << aWord
639 pPos
[nHyphCount
] = i
;
640 hyphenatedWordBuffer
.append('=');
645 OUString hyphenatedWord
= hyphenatedWordBuffer
.makeStringAndClear();
647 Reference
< XPossibleHyphens
> xRes
= PossibleHyphens::CreatePossibleHyphens(
648 aWord
, LinguLocaleToLanguage( aLocale
), hyphenatedWord
, aHyphPos
);
652 for(int j
= 0; j
< n
; j
++)
654 if (rep
[j
]) free(rep
[j
]);
667 OUString
Hyphenator::makeLowerCase(const OUString
& aTerm
, CharClass
const * pCC
)
670 return pCC
->lowercase(aTerm
);
674 OUString
Hyphenator::makeUpperCase(const OUString
& aTerm
, CharClass
const * pCC
)
677 return pCC
->uppercase(aTerm
);
681 OUString
Hyphenator::makeInitCap(const OUString
& aTerm
, CharClass
const * pCC
)
683 sal_Int32 tlen
= aTerm
.getLength();
686 OUString bTemp
= aTerm
.copy(0,1);
688 return ( pCC
->uppercase(bTemp
, 0, 1) + pCC
->lowercase(aTerm
,1,(tlen
-1)) );
690 return pCC
->uppercase(bTemp
, 0, 1);
695 /// @throws Exception
696 static Reference
< XInterface
> Hyphenator_CreateInstance(
697 const Reference
< XMultiServiceFactory
> & /*rSMgr*/ )
699 Reference
< XInterface
> xService
= static_cast<cppu::OWeakObject
*>(new Hyphenator
);
703 sal_Bool SAL_CALL
Hyphenator::addLinguServiceEventListener(
704 const Reference
< XLinguServiceEventListener
>& rxLstnr
)
706 MutexGuard
aGuard( GetLinguMutex() );
709 if (!bDisposing
&& rxLstnr
.is())
711 bRes
= GetPropHelper().addLinguServiceEventListener( rxLstnr
);
716 sal_Bool SAL_CALL
Hyphenator::removeLinguServiceEventListener(
717 const Reference
< XLinguServiceEventListener
>& rxLstnr
)
719 MutexGuard
aGuard( GetLinguMutex() );
722 if (!bDisposing
&& rxLstnr
.is())
724 bRes
= GetPropHelper().removeLinguServiceEventListener( rxLstnr
);
729 OUString SAL_CALL
Hyphenator::getServiceDisplayName(const Locale
& rLocale
)
731 std::locale
loc(Translate::Create("svt", LanguageTag(rLocale
)));
732 return Translate::get(STR_DESCRIPTION_LIBHYPHEN
, loc
);
735 void SAL_CALL
Hyphenator::initialize( const Sequence
< Any
>& rArguments
)
737 MutexGuard
aGuard( GetLinguMutex() );
741 sal_Int32 nLen
= rArguments
.getLength();
744 Reference
< XLinguProperties
> xPropSet
;
745 rArguments
.getConstArray()[0] >>= xPropSet
;
746 // rArguments.getConstArray()[1] >>= xDicList;
748 //! Pointer allows for access of the non-UNO functions.
749 //! And the reference to the UNO-functions while increasing
750 //! the ref-count and will implicitly free the memory
751 //! when the object is no longer used.
752 pPropHelper
.reset( new PropertyHelper_Hyphenation( static_cast<XHyphenator
*>(this), xPropSet
) );
753 pPropHelper
->AddAsPropListener(); //! after a reference is established
756 OSL_FAIL( "wrong number of arguments in sequence" );
761 void SAL_CALL
Hyphenator::dispose()
763 MutexGuard
aGuard( GetLinguMutex() );
768 EventObject
aEvtObj( static_cast<XHyphenator
*>(this) );
769 aEvtListeners
.disposeAndClear( aEvtObj
);
772 pPropHelper
->RemoveAsPropListener();
778 void SAL_CALL
Hyphenator::addEventListener( const Reference
< XEventListener
>& rxListener
)
780 MutexGuard
aGuard( GetLinguMutex() );
782 if (!bDisposing
&& rxListener
.is())
783 aEvtListeners
.addInterface( rxListener
);
786 void SAL_CALL
Hyphenator::removeEventListener( const Reference
< XEventListener
>& rxListener
)
788 MutexGuard
aGuard( GetLinguMutex() );
790 if (!bDisposing
&& rxListener
.is())
791 aEvtListeners
.removeInterface( rxListener
);
794 // Service specific part
795 OUString SAL_CALL
Hyphenator::getImplementationName()
797 return getImplementationName_Static();
800 sal_Bool SAL_CALL
Hyphenator::supportsService( const OUString
& ServiceName
)
802 return cppu::supportsService(this, ServiceName
);
805 Sequence
< OUString
> SAL_CALL
Hyphenator::getSupportedServiceNames()
807 return getSupportedServiceNames_Static();
810 Sequence
< OUString
> Hyphenator::getSupportedServiceNames_Static()
813 Sequence
< OUString
> aSNS
{ SN_HYPHENATOR
};
820 SAL_DLLPUBLIC_EXPORT
void * hyphen_component_getFactory(
821 const sal_Char
* pImplName
, void * pServiceManager
, void * /*pRegistryKey*/ )
823 void * pRet
= nullptr;
824 if ( Hyphenator::getImplementationName_Static().equalsAscii( pImplName
) )
826 Reference
< XSingleServiceFactory
> xFactory
=
827 cppu::createOneInstanceFactory(
828 static_cast< XMultiServiceFactory
* >( pServiceManager
),
829 Hyphenator::getImplementationName_Static(),
830 Hyphenator_CreateInstance
,
831 Hyphenator::getSupportedServiceNames_Static());
832 // acquire, because we return an interface pointer instead of a reference
834 pRet
= xFactory
.get();
840 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */