| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_linguistic.hxx" |
| |
| |
| #include <cppuhelper/factory.hxx> // helper for factories |
| #include <com/sun/star/registry/XRegistryKey.hpp> |
| #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp> |
| #include <com/sun/star/linguistic2/XHyphenatedWord.hpp> |
| #include <rtl/ustrbuf.hxx> |
| #include <i18npool/lang.h> |
| #include <unotools/localedatawrapper.hxx> |
| #include <tools/debug.hxx> |
| #include <svl/lngmisc.hxx> |
| #include <unotools/processfactory.hxx> |
| #include <osl/mutex.hxx> |
| |
| #include "hyphdsp.hxx" |
| #include "linguistic/hyphdta.hxx" |
| #include "linguistic/lngprops.hxx" |
| #include "lngsvcmgr.hxx" |
| |
| |
| using namespace utl; |
| using namespace osl; |
| using namespace rtl; |
| using namespace com::sun::star; |
| using namespace com::sun::star::beans; |
| using namespace com::sun::star::lang; |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::linguistic2; |
| using namespace linguistic; |
| |
| /////////////////////////////////////////////////////////////////////////// |
| |
| HyphenatorDispatcher::HyphenatorDispatcher( LngSvcMgr &rLngSvcMgr ) : |
| rMgr (rLngSvcMgr) |
| { |
| } |
| |
| |
| HyphenatorDispatcher::~HyphenatorDispatcher() |
| { |
| ClearSvcList(); |
| } |
| |
| |
| void HyphenatorDispatcher::ClearSvcList() |
| { |
| // release memory for each table entry |
| HyphSvcByLangMap_t aTmp; |
| aSvcMap.swap( aTmp ); |
| } |
| |
| |
| Reference<XHyphenatedWord> HyphenatorDispatcher::buildHyphWord( |
| const OUString rOrigWord, |
| const Reference<XDictionaryEntry> &xEntry, |
| sal_Int16 nLang, sal_Int16 nMaxLeading ) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Reference< XHyphenatedWord > xRes; |
| |
| if (xEntry.is()) |
| { |
| OUString aText( xEntry->getDictionaryWord() ); |
| sal_Int32 nTextLen = aText.getLength(); |
| |
| // trailing '=' means "hyphenation should not be possible" |
| if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=') |
| { |
| sal_Int16 nHyphenationPos = -1; |
| |
| OUStringBuffer aTmp( nTextLen ); |
| sal_Bool bSkip = sal_False; |
| sal_Int32 nHyphIdx = -1; |
| sal_Int32 nLeading = 0; |
| for (sal_Int32 i = 0; i < nTextLen; i++) |
| { |
| sal_Unicode cTmp = aText[i]; |
| if (cTmp != '=') |
| { |
| aTmp.append( cTmp ); |
| nLeading++; |
| bSkip = sal_False; |
| nHyphIdx++; |
| } |
| else |
| { |
| if (!bSkip && nHyphIdx >= 0) |
| { |
| if (nLeading <= nMaxLeading) |
| nHyphenationPos = (sal_Int16) nHyphIdx; |
| } |
| bSkip = sal_True; //! multiple '=' should count as one only |
| } |
| } |
| |
| if (nHyphenationPos > 0) |
| { |
| aText = aTmp.makeStringAndClear(); |
| |
| #if OSL_DEBUG_LEVEL > 1 |
| { |
| if (aText != rOrigWord) |
| { |
| // both words should only differ by a having a trailing '.' |
| // character or not... |
| OUString aShorter, aLonger; |
| if (aText.getLength() <= rOrigWord.getLength()) |
| { |
| aShorter = aText; |
| aLonger = rOrigWord; |
| } |
| else |
| { |
| aShorter = rOrigWord; |
| aLonger = aText; |
| } |
| xub_StrLen nS = sal::static_int_cast< xub_StrLen >( aShorter.getLength() ); |
| xub_StrLen nL = sal::static_int_cast< xub_StrLen >( aLonger.getLength() ); |
| if (nS > 0 && nL > 0) |
| { |
| DBG_ASSERT( (nS + 1 == nL) && aLonger[nL-1] == (sal_Unicode) '.', |
| "HyphenatorDispatcher::buildHyphWord: unexpected difference between words!" ); |
| } |
| } |
| } |
| #endif |
| //! take care of #i22591# |
| aText = rOrigWord; |
| |
| DBG_ASSERT( aText == rOrigWord, "failed to " ); |
| xRes = new HyphenatedWord( aText, nLang, nHyphenationPos, |
| aText, nHyphenationPos ); |
| } |
| } |
| } |
| |
| return xRes; |
| } |
| |
| |
| Reference< XPossibleHyphens > HyphenatorDispatcher::buildPossHyphens( |
| const Reference< XDictionaryEntry > &xEntry, sal_Int16 nLanguage ) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Reference<XPossibleHyphens> xRes; |
| |
| if (xEntry.is()) |
| { |
| // text with hyphenation info |
| OUString aText( xEntry->getDictionaryWord() ); |
| sal_Int32 nTextLen = aText.getLength(); |
| |
| // trailing '=' means "hyphenation should not be possible" |
| if (nTextLen > 0 && aText[ nTextLen - 1 ] != '=') |
| { |
| // sequence to hold hyphenation positions |
| Sequence< sal_Int16 > aHyphPos( nTextLen ); |
| sal_Int16 *pPos = aHyphPos.getArray(); |
| sal_Int32 nHyphCount = 0; |
| |
| OUStringBuffer aTmp( nTextLen ); |
| sal_Bool bSkip = sal_False; |
| sal_Int32 nHyphIdx = -1; |
| for (sal_Int32 i = 0; i < nTextLen; i++) |
| { |
| sal_Unicode cTmp = aText[i]; |
| if (cTmp != '=') |
| { |
| aTmp.append( cTmp ); |
| bSkip = sal_False; |
| nHyphIdx++; |
| } |
| else |
| { |
| if (!bSkip && nHyphIdx >= 0) |
| pPos[ nHyphCount++ ] = (sal_Int16) nHyphIdx; |
| bSkip = sal_True; //! multiple '=' should count as one only |
| } |
| } |
| |
| // ignore (multiple) trailing '=' |
| if (bSkip && nHyphIdx >= 0) |
| { |
| nHyphCount--; |
| } |
| DBG_ASSERT( nHyphCount >= 0, "lng : invalid hyphenation count"); |
| |
| if (nHyphCount > 0) |
| { |
| aHyphPos.realloc( nHyphCount ); |
| xRes = new PossibleHyphens( aTmp.makeStringAndClear(), nLanguage, |
| aText, aHyphPos ); |
| } |
| } |
| } |
| |
| return xRes; |
| } |
| |
| |
| Sequence< Locale > SAL_CALL HyphenatorDispatcher::getLocales() |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Sequence< Locale > aLocales( static_cast< sal_Int32 >(aSvcMap.size()) ); |
| Locale *pLocales = aLocales.getArray(); |
| HyphSvcByLangMap_t::const_iterator aIt; |
| for (aIt = aSvcMap.begin(); aIt != aSvcMap.end(); ++aIt) |
| { |
| *pLocales++ = CreateLocale( aIt->first ); |
| } |
| return aLocales; |
| } |
| |
| |
| sal_Bool SAL_CALL HyphenatorDispatcher::hasLocale(const Locale& rLocale) |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| HyphSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LocaleToLanguage( rLocale ) ) ); |
| return aIt != aSvcMap.end(); |
| } |
| |
| |
| Reference< XHyphenatedWord > SAL_CALL |
| HyphenatorDispatcher::hyphenate( |
| const OUString& rWord, const Locale& rLocale, sal_Int16 nMaxLeading, |
| const PropertyValues& rProperties ) |
| throw(IllegalArgumentException, RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Reference< XHyphenatedWord > xRes; |
| |
| sal_Int32 nWordLen = rWord.getLength(); |
| sal_Int16 nLanguage = LocaleToLanguage( rLocale ); |
| if (nLanguage == LANGUAGE_NONE || !nWordLen || |
| nMaxLeading == 0 || nMaxLeading == nWordLen) |
| return xRes; |
| |
| // search for entry with that language |
| HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) ); |
| LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL; |
| |
| sal_Bool bWordModified = sal_False; |
| if (!pEntry || (nMaxLeading < 0 || nMaxLeading > nWordLen)) |
| { |
| #ifdef LINGU_EXCEPTIONS |
| throw IllegalArgumentException(); |
| #else |
| return NULL; |
| #endif |
| } |
| else |
| { |
| OUString aChkWord( rWord ); |
| |
| // replace typographical apostroph by ascii apostroph |
| String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() ); |
| DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" ); |
| if (aSingleQuote.Len()) |
| aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' ); |
| |
| bWordModified |= RemoveHyphens( aChkWord ); |
| if (IsIgnoreControlChars( rProperties, GetPropSet() )) |
| bWordModified |= RemoveControlChars( aChkWord ); |
| sal_Int16 nChkMaxLeading = (sal_Int16) GetPosInWordToCheck( rWord, nMaxLeading ); |
| |
| // check for results from (positive) dictionaries which have precedence! |
| Reference< XDictionaryEntry > xEntry; |
| |
| if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() )) |
| { |
| xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale, |
| sal_True, sal_False ); |
| } |
| |
| if (xEntry.is()) |
| { |
| //! because queryDictionaryEntry (in the end DictionaryNeo::getEntry) |
| //! does not distinguish betwee "XYZ" and "XYZ." in order to avoid |
| //! to require them as different entry we have to supply the |
| //! original word here as well so it can be used in th result |
| //! otherwise a strange effect may occur (see #i22591#) |
| xRes = buildHyphWord( rWord, xEntry, nLanguage, nChkMaxLeading ); |
| } |
| else |
| { |
| sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0; |
| DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen, |
| "lng : index out of range"); |
| |
| sal_Int32 i = 0; |
| Reference< XHyphenator > xHyph; |
| if (pEntry->aSvcRefs.getLength() > 0) |
| xHyph = pEntry->aSvcRefs[0]; |
| |
| // try already instantiated service |
| if (i <= pEntry->nLastTriedSvcIndex) |
| { |
| if (xHyph.is() && xHyph->hasLocale( rLocale )) |
| xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading, |
| rProperties ); |
| ++i; |
| } |
| else if (pEntry->nLastTriedSvcIndex < nLen - 1) |
| // instantiate services and try it |
| { |
| // const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray(); |
| Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray(); |
| |
| Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() ); |
| if (xMgr.is()) |
| { |
| // build service initialization argument |
| Sequence< Any > aArgs(2); |
| aArgs.getArray()[0] <<= GetPropSet(); |
| //! The dispatcher searches the dictionary-list |
| //! thus the service needs not to now about it |
| //aArgs.getArray()[1] <<= GetDicList(); |
| |
| // create specific service via it's implementation name |
| try |
| { |
| xHyph = Reference< XHyphenator >( |
| xMgr->createInstanceWithArguments( |
| pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY ); |
| } |
| catch (uno::Exception &) |
| { |
| DBG_ASSERT( 0, "createInstanceWithArguments failed" ); |
| } |
| pRef [i] = xHyph; |
| |
| Reference< XLinguServiceEventBroadcaster > |
| xBroadcaster( xHyph, UNO_QUERY ); |
| if (xBroadcaster.is()) |
| rMgr.AddLngSvcEvtBroadcaster( xBroadcaster ); |
| |
| if (xHyph.is() && xHyph->hasLocale( rLocale )) |
| xRes = xHyph->hyphenate( aChkWord, rLocale, nChkMaxLeading, |
| rProperties ); |
| |
| pEntry->nLastTriedSvcIndex = (sal_Int16) i; |
| ++i; |
| |
| // if language is not supported by the services |
| // remove it from the list. |
| if (xHyph.is() && !xHyph->hasLocale( rLocale )) |
| aSvcMap.erase( nLanguage ); |
| } |
| } |
| } // if (xEntry.is()) |
| } |
| |
| if (bWordModified && xRes.is()) |
| xRes = RebuildHyphensAndControlChars( rWord, xRes ); |
| |
| if (xRes.is() && xRes->getWord() != rWord) |
| { |
| xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(), |
| xRes->getHyphenatedWord(), |
| xRes->getHyphenPos() ); |
| } |
| |
| return xRes; |
| } |
| |
| |
| Reference< XHyphenatedWord > SAL_CALL |
| HyphenatorDispatcher::queryAlternativeSpelling( |
| const OUString& rWord, const Locale& rLocale, sal_Int16 nIndex, |
| const PropertyValues& rProperties ) |
| throw(IllegalArgumentException, RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Reference< XHyphenatedWord > xRes; |
| |
| sal_Int32 nWordLen = rWord.getLength(); |
| sal_Int16 nLanguage = LocaleToLanguage( rLocale ); |
| if (nLanguage == LANGUAGE_NONE || !nWordLen) |
| return xRes; |
| |
| // search for entry with that language |
| HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) ); |
| LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL; |
| |
| sal_Bool bWordModified = sal_False; |
| if (!pEntry || !(0 <= nIndex && nIndex <= nWordLen - 2)) |
| { |
| #ifdef LINGU_EXCEPTIONS |
| throw IllegalArgumentException(); |
| #else |
| return NULL; |
| #endif |
| } |
| else |
| { |
| OUString aChkWord( rWord ); |
| |
| // replace typographical apostroph by ascii apostroph |
| String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() ); |
| DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" ); |
| if (aSingleQuote.Len()) |
| aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' ); |
| |
| bWordModified |= RemoveHyphens( aChkWord ); |
| if (IsIgnoreControlChars( rProperties, GetPropSet() )) |
| bWordModified |= RemoveControlChars( aChkWord ); |
| sal_Int16 nChkIndex = (sal_Int16) GetPosInWordToCheck( rWord, nIndex ); |
| |
| // check for results from (positive) dictionaries which have precedence! |
| Reference< XDictionaryEntry > xEntry; |
| |
| if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() )) |
| { |
| xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale, |
| sal_True, sal_False ); |
| } |
| |
| if (xEntry.is()) |
| { |
| //! alternative spellings not yet supported by dictionaries |
| } |
| else |
| { |
| sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0; |
| DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen, |
| "lng : index out of range"); |
| |
| sal_Int32 i = 0; |
| Reference< XHyphenator > xHyph; |
| if (pEntry->aSvcRefs.getLength() > 0) |
| xHyph = pEntry->aSvcRefs[0]; |
| |
| // try already instantiated service |
| if (i <= pEntry->nLastTriedSvcIndex) |
| { |
| if (xHyph.is() && xHyph->hasLocale( rLocale )) |
| xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale, |
| nChkIndex, rProperties ); |
| ++i; |
| } |
| else if (pEntry->nLastTriedSvcIndex < nLen - 1) |
| // instantiate services and try it |
| { |
| // const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray(); |
| Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray(); |
| |
| Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() ); |
| if (xMgr.is()) |
| { |
| // build service initialization argument |
| Sequence< Any > aArgs(2); |
| aArgs.getArray()[0] <<= GetPropSet(); |
| //! The dispatcher searches the dictionary-list |
| //! thus the service needs not to now about it |
| //aArgs.getArray()[1] <<= GetDicList(); |
| |
| // create specific service via it's implementation name |
| try |
| { |
| xHyph = Reference< XHyphenator >( |
| xMgr->createInstanceWithArguments( |
| pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY ); |
| } |
| catch (uno::Exception &) |
| { |
| DBG_ASSERT( 0, "createInstanceWithArguments failed" ); |
| } |
| pRef [i] = xHyph; |
| |
| Reference< XLinguServiceEventBroadcaster > |
| xBroadcaster( xHyph, UNO_QUERY ); |
| if (xBroadcaster.is()) |
| rMgr.AddLngSvcEvtBroadcaster( xBroadcaster ); |
| |
| if (xHyph.is() && xHyph->hasLocale( rLocale )) |
| xRes = xHyph->queryAlternativeSpelling( aChkWord, rLocale, |
| nChkIndex, rProperties ); |
| |
| pEntry->nLastTriedSvcIndex = (sal_Int16) i; |
| ++i; |
| |
| // if language is not supported by the services |
| // remove it from the list. |
| if (xHyph.is() && !xHyph->hasLocale( rLocale )) |
| aSvcMap.erase( nLanguage ); |
| } |
| } |
| } // if (xEntry.is()) |
| } |
| |
| if (bWordModified && xRes.is()) |
| xRes = RebuildHyphensAndControlChars( rWord, xRes ); |
| |
| if (xRes.is() && xRes->getWord() != rWord) |
| { |
| xRes = new HyphenatedWord( rWord, nLanguage, xRes->getHyphenationPos(), |
| xRes->getHyphenatedWord(), |
| xRes->getHyphenPos() ); |
| } |
| |
| return xRes; |
| } |
| |
| |
| Reference< XPossibleHyphens > SAL_CALL |
| HyphenatorDispatcher::createPossibleHyphens( |
| const OUString& rWord, const Locale& rLocale, |
| const PropertyValues& rProperties ) |
| throw(IllegalArgumentException, RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Reference< XPossibleHyphens > xRes; |
| |
| sal_Int16 nLanguage = LocaleToLanguage( rLocale ); |
| if (nLanguage == LANGUAGE_NONE || !rWord.getLength()) |
| return xRes; |
| |
| // search for entry with that language |
| HyphSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) ); |
| LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL; |
| |
| if (!pEntry) |
| { |
| #ifdef LINGU_EXCEPTIONS |
| throw IllegalArgumentException(); |
| #endif |
| } |
| else |
| { |
| OUString aChkWord( rWord ); |
| |
| // replace typographical apostroph by ascii apostroph |
| String aSingleQuote( GetLocaleDataWrapper( nLanguage ).getQuotationMarkEnd() ); |
| DBG_ASSERT( 1 == aSingleQuote.Len(), "unexpectend length of quotation mark" ); |
| if (aSingleQuote.Len()) |
| aChkWord = aChkWord.replace( aSingleQuote.GetChar(0), '\'' ); |
| |
| RemoveHyphens( aChkWord ); |
| if (IsIgnoreControlChars( rProperties, GetPropSet() )) |
| RemoveControlChars( aChkWord ); |
| |
| // check for results from (positive) dictionaries which have precedence! |
| Reference< XDictionaryEntry > xEntry; |
| |
| if (GetDicList().is() && IsUseDicList( rProperties, GetPropSet() )) |
| { |
| xEntry = GetDicList()->queryDictionaryEntry( aChkWord, rLocale, |
| sal_True, sal_False ); |
| } |
| |
| if (xEntry.is()) |
| { |
| xRes = buildPossHyphens( xEntry, nLanguage ); |
| } |
| else |
| { |
| sal_Int32 nLen = pEntry->aSvcImplNames.getLength() > 0 ? 1 : 0; |
| DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen, |
| "lng : index out of range"); |
| |
| sal_Int32 i = 0; |
| Reference< XHyphenator > xHyph; |
| if (pEntry->aSvcRefs.getLength() > 0) |
| xHyph = pEntry->aSvcRefs[0]; |
| |
| // try already instantiated service |
| if (i <= pEntry->nLastTriedSvcIndex) |
| { |
| if (xHyph.is() && xHyph->hasLocale( rLocale )) |
| xRes = xHyph->createPossibleHyphens( aChkWord, rLocale, |
| rProperties ); |
| ++i; |
| } |
| else if (pEntry->nLastTriedSvcIndex < nLen - 1) |
| // instantiate services and try it |
| { |
| // const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray(); |
| Reference< XHyphenator > *pRef = pEntry->aSvcRefs.getArray(); |
| |
| Reference< XMultiServiceFactory > xMgr( getProcessServiceFactory() ); |
| if (xMgr.is()) |
| { |
| // build service initialization argument |
| Sequence< Any > aArgs(2); |
| aArgs.getArray()[0] <<= GetPropSet(); |
| //! The dispatcher searches the dictionary-list |
| //! thus the service needs not to now about it |
| //aArgs.getArray()[1] <<= GetDicList(); |
| |
| // create specific service via it's implementation name |
| try |
| { |
| xHyph = Reference< XHyphenator >( |
| xMgr->createInstanceWithArguments( |
| pEntry->aSvcImplNames[0], aArgs ), UNO_QUERY ); |
| } |
| catch (uno::Exception &) |
| { |
| DBG_ASSERT( 0, "createWithArguments failed" ); |
| } |
| pRef [i] = xHyph; |
| |
| Reference< XLinguServiceEventBroadcaster > |
| xBroadcaster( xHyph, UNO_QUERY ); |
| if (xBroadcaster.is()) |
| rMgr.AddLngSvcEvtBroadcaster( xBroadcaster ); |
| |
| if (xHyph.is() && xHyph->hasLocale( rLocale )) |
| xRes = xHyph->createPossibleHyphens( aChkWord, rLocale, |
| rProperties ); |
| |
| pEntry->nLastTriedSvcIndex = (sal_Int16) i; |
| ++i; |
| |
| // if language is not supported by the services |
| // remove it from the list. |
| if (xHyph.is() && !xHyph->hasLocale( rLocale )) |
| aSvcMap.erase( nLanguage ); |
| } |
| } |
| } // if (xEntry.is()) |
| } |
| |
| if (xRes.is() && xRes->getWord() != rWord) |
| { |
| xRes = new PossibleHyphens( rWord, nLanguage, |
| xRes->getPossibleHyphens(), |
| xRes->getHyphenationPositions() ); |
| } |
| |
| return xRes; |
| } |
| |
| |
| void HyphenatorDispatcher::SetServiceList( const Locale &rLocale, |
| const Sequence< OUString > &rSvcImplNames ) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| sal_Int16 nLanguage = LocaleToLanguage( rLocale ); |
| |
| sal_Int32 nLen = rSvcImplNames.getLength(); |
| if (0 == nLen) |
| // remove entry |
| aSvcMap.erase( nLanguage ); |
| else |
| { |
| // modify/add entry |
| LangSvcEntries_Hyph *pEntry = aSvcMap[ nLanguage ].get(); |
| // only one hypenator can be in use for a language... |
| //const OUString &rSvcImplName = rSvcImplNames.getConstArray()[0]; |
| if (pEntry) |
| { |
| pEntry->Clear(); |
| pEntry->aSvcImplNames = rSvcImplNames; |
| pEntry->aSvcImplNames.realloc(1); |
| pEntry->aSvcRefs = Sequence< Reference < XHyphenator > > ( 1 ); |
| } |
| else |
| { |
| boost::shared_ptr< LangSvcEntries_Hyph > pTmpEntry( new LangSvcEntries_Hyph( rSvcImplNames[0] ) ); |
| pTmpEntry->aSvcRefs = Sequence< Reference < XHyphenator > >( 1 ); |
| aSvcMap[ nLanguage ] = pTmpEntry; |
| } |
| } |
| } |
| |
| |
| Sequence< OUString > |
| HyphenatorDispatcher::GetServiceList( const Locale &rLocale ) const |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Sequence< OUString > aRes; |
| |
| // search for entry with that language and use data from that |
| sal_Int16 nLanguage = LocaleToLanguage( rLocale ); |
| HyphenatorDispatcher *pThis = (HyphenatorDispatcher *) this; |
| const HyphSvcByLangMap_t::iterator aIt( pThis->aSvcMap.find( nLanguage ) ); |
| const LangSvcEntries_Hyph *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL; |
| if (pEntry) |
| { |
| aRes = pEntry->aSvcImplNames; |
| if (aRes.getLength() > 0) |
| aRes.realloc(1); |
| } |
| |
| return aRes; |
| } |
| |
| |
| LinguDispatcher::DspType HyphenatorDispatcher::GetDspType() const |
| { |
| return DSP_HYPH; |
| } |
| |
| |
| /////////////////////////////////////////////////////////////////////////// |
| |