20#include <com/sun/star/uno/Reference.h>
26#include <com/sun/star/linguistic2/XLinguProperties.hpp>
29#include <osl/mutex.hxx>
30#include <osl/thread.h>
36#include <rtl/ustring.hxx>
37#include <rtl/ustrbuf.hxx>
38#include <rtl/textenc.h>
42#include <svtools/strings.hrc>
46#include <osl/file.hxx>
77 hnj_hyphen_free(rInfo.aPtr);
92 pPropHelper.reset(
new PropertyHelper_Hyphenation (
static_cast<XHyphenator *
>(
this), xPropSet ) );
111 std::vector< SvtLinguConfigDictionaryEntry > aDics;
112 uno::Sequence< OUString > aFormatList;
114 "org.openoffice.lingu.LibHnjHyphenator", aFormatList );
115 for (
const auto& rFormat : std::as_const(aFormatList))
117 std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
119 aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
125 std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
136 std::set<OUString> aLocaleNamesSet;
137 for (
auto const& dict : aDics)
139 for (
const auto& rLocaleName : dict.aLocaleNames)
141 aLocaleNamesSet.insert( rLocaleName );
145 std::vector<Locale> aLocalesVec;
146 aLocalesVec.reserve(aLocaleNamesSet.size());
148 std::transform(aLocaleNamesSet.begin(), aLocaleNamesSet.end(), std::back_inserter(aLocalesVec),
149 [](
const OUString& localeName) { return LanguageTag::convertToLocale(localeName); });
158 sal_Int32 numdict = std::accumulate(aDics.begin(), aDics.end(), 0,
160 return nSum + dict.aLocaleNames.getLength(); });
166 for (
auto const& dict : aDics)
178 mvDicts[k].eEnc = RTL_TEXTENCODING_DONTKNOW;
185 sal_Int32
nPos = aLocation.lastIndexOf(
'.' );
186 aLocation = aLocation.copy( 0,
nPos );
193 DBG_ASSERT( k == numdict,
"index mismatch?" );
217bool LoadDictionary(
HDInfo& rDict)
219 OUString DictFN = rDict.
aName +
".dic";
222 osl::FileBase::getSystemPathFromFileURL(DictFN, dictpath);
226 OString sTmp = Win_AddLongPathPrefix(
OUStringToOString(dictpath, RTL_TEXTENCODING_UTF8));
228 OString sTmp(
OU2ENC(dictpath, osl_getThreadTextEncoding()));
230 HyphenDict *dict =
nullptr;
231 if ((dict = hnj_hyphen_load(sTmp.getStr())) ==
nullptr)
235 "Couldn't find file " << dictpath);
245 const css::lang::Locale& aLocale,
246 sal_Int16 nMaxLeading,
247 const css::uno::Sequence< css::beans::PropertyValue >& aProperties )
251 sal_Int16 minTrail = rHelper.GetMinTrailing();
252 sal_Int16 minLead = rHelper.GetMinLeading();
253 sal_Int16 minLen = rHelper.GetMinWordLength();
254 bool bNoHyphenateCaps = rHelper.IsNoHyphenateCaps();
256 rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
261 for (
size_t j = 0; j <
mvDicts.size(); ++j)
263 if (aLocale ==
mvDicts[j].aLoc)
270 int nHyphenationPos = -1;
271 int nHyphenationPosAlt = -1;
272 int nHyphenationPosAltHyph = -1;
277 if (!LoadDictionary(
mvDicts[k]))
282 HyphenDict *dict =
mvDicts[k].aPtr;
296 DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW,
"failed to get text encoding! (maybe incorrect encoding string in file)" );
297 if (eEnc == RTL_TEXTENCODING_DONTKNOW)
303 OUStringBuffer rBuf(aWord);
304 sal_Int32 nc = rBuf.getLength();
306 for (sal_Int32 ix=0; ix < nc; ix++)
309 if ((
ch == 0x201C) || (
ch == 0x201D))
311 if ((
ch == 0x2018) || (
ch == 0x2019))
314 OUString nWord(rBuf.makeStringAndClear());
320 OString encWord(
OU2ENC(nTerm,eEnc));
322 int wordlen = encWord.getLength();
323 std::unique_ptr<char[]> lcword(
new char[wordlen + 1]);
324 std::unique_ptr<char[]> hyphens(
new char[wordlen + 5]);
326 char ** rep =
nullptr;
331 strcpy(lcword.get(),encWord.getStr());
335 while((
n >=0) && (lcword[
n] ==
'.'))
340 const bool bFailed = 0 != hnj_hyphen_hyphenate3( dict, lcword.get(),
n, hyphens.get(),
nullptr,
341 &rep, &
pos, &cut, minLead, minTrail,
342 std::max<sal_Int16>(dict->clhmin, std::max<sal_Int16>(dict->clhmin, 2) + std::max(0, minLead - std::max<sal_Int16>(dict->lhmin, 2))),
343 std::max<sal_Int16>(dict->crhmin, std::max<sal_Int16>(dict->crhmin, 2) + std::max(0, minTrail - std::max<sal_Int16>(dict->rhmin, 2))) );
349 for(
int j = 0; j <
n; j++)
351 if (rep[j]) free(rep[j]);
362 for (
int c =
n; c < wordlen; c++) hyphens[c] =
'0';
363 hyphens[wordlen] =
'\0';
367 for (sal_Int32
i = 0;
i <
n;
i++)
370 bool hit = (
n >= minLen);
373 hit = hit && (hyphens[
i]&1) && (
i <
Leading);
374 hit = hit && (
i >= (minLead-1) );
375 hit = hit && ((
n -
i - 1) >= minTrail);
380 for (
char * c = rep[
i]; *c && (*c !=
'='); c++)
382 if (eEnc == RTL_TEXTENCODING_UTF8)
384 if (
static_cast<unsigned char>(*c) >> 6 != 2)
390 hit = hit && (hyphens[
i]&1) && ((
i + leftrep -
pos[
i]) <
Leading);
391 hit = hit && ((
i + leftrep -
pos[
i]) >= (minLead-1) );
392 hit = hit && ((
n -
i - 1 + sal::static_int_cast< sal_sSize >(strlen(rep[
i])) - leftrep - 1) >= minTrail);
399 nHyphenationPosAlt =
i -
pos[
i];
400 nHyphenationPosAltHyph =
i + leftrep -
pos[
i];
405 if (nHyphenationPos == -1)
411 if (rep && rep[nHyphenationPos])
414 char * s = rep[nHyphenationPos];
418 if (*s ==
'=') eq = 1;
419 if (eq) *s = *(s + 1);
421 OUString repHyphlow(rep[nHyphenationPos], strlen(rep[nHyphenationPos]), eEnc);
425 case CapType::ALLCAP:
430 case CapType::INITCAP:
432 if (nHyphenationPosAlt == -1)
435 repHyph = repHyphlow;
440 repHyph = repHyphlow;
446 sal_Int16
nPos =
static_cast<sal_Int16
>((nHyphenationPosAltHyph < nHyphenationPos) ?
447 nHyphenationPosAltHyph : nHyphenationPos);
450 aWord.replaceAt(nHyphenationPosAlt + 1, cut[nHyphenationPos], repHyph),
451 static_cast<sal_Int16
>(nHyphenationPosAltHyph));
456 static_cast<sal_Int16
>(nHyphenationPos), aWord,
static_cast<sal_Int16
>(nHyphenationPos));
462 for(
int j = 0; j <
n; j++)
464 if (rep[j]) free(rep[j]);
476 const OUString& aWord,
477 const css::lang::Locale& aLocale,
479 const css::uno::Sequence< css::beans::PropertyValue >& aProperties )
482 for (
int extrachar = 1; extrachar <= 2; extrachar++)
485 if (xRes.is() && xRes->isAlternativeSpelling() && xRes->getHyphenationPos() ==
nIndex)
492 const css::lang::Locale& aLocale,
493 const css::uno::Sequence< css::beans::PropertyValue >& aProperties )
497 sal_Int16 minTrail = rHelper.GetMinTrailing();
498 sal_Int16 minLead = rHelper.GetMinLeading();
499 sal_Int16 minLen = rHelper.GetMinWordLength();
503 if (aWord.getLength() < minLen)
510 for (
size_t j = 0; j <
mvDicts.size(); ++j)
512 if (aLocale ==
mvDicts[j].aLoc)
519 HyphenDict *dict =
nullptr;
523 if (!LoadDictionary(
mvDicts[k]))
529 rtl_TextEncoding eEnc =
mvDicts[k].eEnc;
536 DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW,
"failed to get text encoding! (maybe incorrect encoding string in file)" );
537 if (eEnc == RTL_TEXTENCODING_DONTKNOW)
541 OUStringBuffer rBuf(aWord);
542 sal_Int32 nc = rBuf.getLength();
544 for (sal_Int32 ix=0; ix < nc; ix++)
547 if ((
ch == 0x201C) || (
ch == 0x201D))
549 if ((
ch == 0x2018) || (
ch == 0x2019))
552 OUString nWord(rBuf.makeStringAndClear());
558 OString encWord(
OU2ENC(nTerm,eEnc));
560 sal_Int32 wordlen = encWord.getLength();
561 std::unique_ptr<char[]> lcword(
new char[wordlen+1]);
562 std::unique_ptr<char[]> hyphens(
new char[wordlen+5]);
563 char ** rep =
nullptr;
568 strcpy(lcword.get(),encWord.getStr());
571 sal_Int32
n = wordlen-1;
572 while((
n >=0) && (lcword[
n] ==
'.'))
577 const bool bFailed = 0 != hnj_hyphen_hyphenate3(dict, lcword.get(),
n, hyphens.get(),
nullptr,
578 &rep, &
pos, &cut, minLead, minTrail,
579 std::max<sal_Int16>(dict->clhmin, std::max<sal_Int16>(dict->clhmin, 2) + std::max(0, minLead - std::max<sal_Int16>(dict->lhmin, 2))),
580 std::max<sal_Int16>(dict->crhmin, std::max<sal_Int16>(dict->crhmin, 2) + std::max(0, minTrail - std::max<sal_Int16>(dict->rhmin, 2))) );
585 for(
int j = 0; j <
n; j++)
587 if (rep[j]) free(rep[j]);
598 for (sal_Int32 c =
n; c < wordlen; c++)
600 hyphens[wordlen] =
'\0';
602 sal_Int32 nHyphCount = 0;
604 for ( sal_Int32
i = 0;
i < encWord.getLength();
i++)
611 sal_Int16 *pPos = aHyphPos.getArray();
612 OUStringBuffer hyphenatedWordBuffer;
615 for (sal_Int32
i = 0;
i < nWord.getLength();
i++)
617 hyphenatedWordBuffer.append(aWord[
i]);
630 "hyphen pos " <<
i <<
" > SAL_MAX_INT16 in \"" << aWord
634 pPos[nHyphCount] =
i;
635 hyphenatedWordBuffer.append(
'=');
640 OUString hyphenatedWord = hyphenatedWordBuffer.makeStringAndClear();
647 for(
int j = 0; j <
n; j++)
649 if (rep[j]) free(rep[j]);
678 sal_Int32 tlen = aTerm.getLength();
681 OUString bTemp = aTerm.copy(0,1);
698 bRes =
GetPropHelper().addLinguServiceEventListener( rxLstnr );
711 bRes =
GetPropHelper().removeLinguServiceEventListener( rxLstnr );
729 sal_Int32 nLen = rArguments.getLength();
733 rArguments.getConstArray()[0] >>= xPropSet;
740 pPropHelper.reset(
new PropertyHelper_Hyphenation(
static_cast<XHyphenator *
>(
this), xPropSet ) );
744 OSL_FAIL(
"wrong number of arguments in sequence" );
755 EventObject aEvtObj(
static_cast<XHyphenator *
>(
this) );
784 return "org.openoffice.lingu.LibHnjHyphenator";
797extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
799 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any>
const&)
PropertiesInfo aProperties
OUString uppercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
OUString lowercase(const OUString &rStr, sal_Int32 nPos, sal_Int32 nCount) const
static OUString makeLowerCase(const OUString &, CharClass const *)
std::vector< HDInfo > mvDicts
virtual sal_Bool SAL_CALL removeLinguServiceEventListener(const Reference< XLinguServiceEventListener > &rxLstnr) override
virtual void SAL_CALL addEventListener(const Reference< XEventListener > &rxListener) override
linguistic::PropertyHelper_Hyphenation & GetPropHelper()
virtual Sequence< Locale > SAL_CALL getLocales() override
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
std::unique_ptr< linguistic::PropertyHelper_Hyphenation > pPropHelper
virtual sal_Bool SAL_CALL addLinguServiceEventListener(const Reference< XLinguServiceEventListener > &rxLstnr) override
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
virtual sal_Bool SAL_CALL hasLocale(const Locale &rLocale) override
::comphelper::OInterfaceContainerHelper3< XEventListener > aEvtListeners
static OUString makeUpperCase(const OUString &, CharClass const *)
virtual void SAL_CALL dispose() override
virtual OUString SAL_CALL getImplementationName() override
Sequence< Locale > aSuppLocales
static OUString makeInitCap(const OUString &, CharClass const *)
virtual void SAL_CALL removeEventListener(const Reference< XEventListener > &rxListener) override
virtual void SAL_CALL initialize(const Sequence< Any > &rArguments) override
virtual OUString SAL_CALL getServiceDisplayName(const Locale &rLocale) override
virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual ~Hyphenator() override
linguistic::PropertyHelper_Hyphenation & GetPropHelper_Impl()
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
virtual sal_Bool SAL_CALL supportsService(const OUString &rServiceName) override
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
std::vector< SvtLinguConfigDictionaryEntry > GetActiveDictionariesByFormat(std::u16string_view rFormatName) const
bool GetSupportedDictionaryFormatsFor(const OUString &rSetName, const OUString &rSetEntry, css::uno::Sequence< OUString > &rFormatList) const
sal_Int32 addInterface(const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(const css::uno::Reference< ListenerT > &rxIFace)
#define DBG_ASSERT(sCon, aError)
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * lingucomponent_Hyphenator_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
std::vector< SvtLinguConfigDictionaryEntry > GetOldStyleDics(const char *pDicType)
void MergeNewStyleDicsAndOldStyleDics(std::vector< SvtLinguConfigDictionaryEntry > &rNewStyleDics, const std::vector< SvtLinguConfigDictionaryEntry > &rOldStyleDics)
rtl_TextEncoding getTextEncodingFromCharset(const char *pCharset)
#define OU2ENC(rtlOUString, rtlEncoding)
#define SAL_WARN(area, stream)
constexpr OUStringLiteral SN_HYPHENATOR
std::locale Create(std::string_view aPrefixName, const LanguageTag &rLocale)
OUString get(TranslateId sContextAndId, const std::locale &loc)
sal_Int32 findValue(const css::uno::Sequence< T1 > &_rList, const T2 &_rValue)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
uno::Reference< XLinguProperties > GetLinguProperties()
CapType capitalType(const OUString &aTerm, CharClass const *pCC)
sal_Int32 GetPosInWordToCheck(std::u16string_view rTxt, sal_Int32 nPos)
osl::Mutex & GetLinguMutex()
LanguageType LinguLocaleToLanguage(const css::lang::Locale &rLocale)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
css::uno::Sequence< OUString > aLocaleNames
css::uno::Sequence< OUString > aLocations