| /************************************************************** |
| * |
| * 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_lingucomponent.hxx" |
| |
| #include <com/sun/star/uno/Reference.h> |
| #include <cppuhelper/factory.hxx> // helper for factories |
| #include <com/sun/star/registry/XRegistryKey.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <i18npool/mslangid.hxx> |
| #include <tools/debug.hxx> |
| #include <unotools/processfactory.hxx> |
| #include <osl/mutex.hxx> |
| #include <unotools/pathoptions.hxx> |
| #include <unotools/lingucfg.hxx> |
| |
| #include <rtl/string.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include <rtl/textenc.h> |
| |
| #include "nthesimp.hxx" |
| #include <linguistic/misc.hxx> |
| #include <linguistic/lngprops.hxx> |
| #include "nthesdta.hxx" |
| |
| #include <list> |
| #include <set> |
| #include <string.h> |
| |
| // values asigned to capitalization types |
| #define CAPTYPE_UNKNOWN 0 |
| #define CAPTYPE_NOCAP 1 |
| #define CAPTYPE_INITCAP 2 |
| #define CAPTYPE_ALLCAP 3 |
| #define CAPTYPE_MIXED 4 |
| |
| // XML-header to query SPELLML support |
| #define SPELLML_SUPPORT "<?xml?>" |
| |
| 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; |
| |
| |
| |
| /////////////////////////////////////////////////////////////////////////// |
| |
| static uno::Reference< XLinguServiceManager > GetLngSvcMgr_Impl() |
| { |
| uno::Reference< XLinguServiceManager > xRes; |
| uno::Reference< XMultiServiceFactory > xMgr = getProcessServiceFactory(); |
| if (xMgr.is()) |
| { |
| xRes = uno::Reference< XLinguServiceManager > ( xMgr->createInstance( |
| OUString( RTL_CONSTASCII_USTRINGPARAM( |
| "com.sun.star.linguistic2.LinguServiceManager" ) ) ), UNO_QUERY ) ; |
| } |
| return xRes; |
| } |
| |
| Thesaurus::Thesaurus() : |
| aEvtListeners ( GetLinguMutex() ) |
| { |
| bDisposing = sal_False; |
| pPropHelper = NULL; |
| aThes = NULL; |
| aCharSetInfo = NULL; |
| aTEncs = NULL; |
| aTLocs = NULL; |
| aTNames = NULL; |
| numthes = 0; |
| } |
| |
| |
| Thesaurus::~Thesaurus() |
| { |
| |
| if (aThes) |
| { |
| for (int i = 0; i < numthes; i++) |
| { |
| if (aThes[i]) delete aThes[i]; |
| aThes[i] = NULL; |
| } |
| delete[] aThes; |
| } |
| aThes = NULL; |
| if (aCharSetInfo) |
| { |
| for (int i = 0; i < numthes; i++) |
| { |
| if (aCharSetInfo[i]) delete aCharSetInfo[i]; |
| aCharSetInfo[i] = NULL; |
| } |
| delete[] aCharSetInfo; |
| } |
| aCharSetInfo = NULL; |
| numthes = 0; |
| if (aTEncs) delete[] aTEncs; |
| aTEncs = NULL; |
| if (aTLocs) delete[] aTLocs; |
| aTLocs = NULL; |
| if (aTNames) delete[] aTNames; |
| aTNames = NULL; |
| |
| if (pPropHelper) |
| pPropHelper->RemoveAsPropListener(); |
| } |
| |
| |
| PropertyHelper_Thes & Thesaurus::GetPropHelper_Impl() |
| { |
| if (!pPropHelper) |
| { |
| Reference< XPropertySet > xPropSet( GetLinguProperties(), UNO_QUERY ); |
| |
| pPropHelper = new PropertyHelper_Thes( (XThesaurus *) this, xPropSet ); |
| xPropHelper = pPropHelper; |
| pPropHelper->AddAsPropListener(); //! after a reference is established |
| } |
| return *pPropHelper; |
| } |
| |
| |
| Sequence< Locale > SAL_CALL Thesaurus::getLocales() |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| // this routine should return the locales supported by the installed |
| // dictionaries. |
| |
| if (!numthes) |
| { |
| SvtLinguConfig aLinguCfg; |
| |
| // get list of dictionaries-to-use |
| std::list< SvtLinguConfigDictionaryEntry > aDics; |
| uno::Sequence< rtl::OUString > aFormatList; |
| aLinguCfg.GetSupportedDictionaryFormatsFor( A2OU("Thesauri"), |
| A2OU("org.openoffice.lingu.new.Thesaurus"), aFormatList ); |
| sal_Int32 nLen = aFormatList.getLength(); |
| for (sal_Int32 i = 0; i < nLen; ++i) |
| { |
| std::vector< SvtLinguConfigDictionaryEntry > aTmpDic( |
| aLinguCfg.GetActiveDictionariesByFormat( aFormatList[i] ) ); |
| aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() ); |
| } |
| |
| //!! for compatibility with old dictionaries (the ones not using extensions |
| //!! or new configuration entries, but still using the dictionary.lst file) |
| //!! Get the list of old style spell checking dictionaries to use... |
| std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics( |
| GetOldStyleDics( "THES" ) ); |
| |
| // to prefer dictionaries with configuration entries we will only |
| // use those old style dictionaries that add a language that |
| // is not yet supported by the list od new style dictionaries |
| MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics ); |
| |
| numthes = aDics.size(); |
| if (numthes) |
| { |
| // get supported locales from the dictionaries-to-use... |
| sal_Int32 k = 0; |
| std::set< rtl::OUString, lt_rtl_OUString > aLocaleNamesSet; |
| std::list< SvtLinguConfigDictionaryEntry >::const_iterator aDictIt; |
| for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt) |
| { |
| uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames ); |
| sal_Int32 nLen2 = aLocaleNames.getLength(); |
| for (k = 0; k < nLen2; ++k) |
| { |
| aLocaleNamesSet.insert( aLocaleNames[k] ); |
| } |
| } |
| // ... and add them to the resulting sequence |
| aSuppLocales.realloc( aLocaleNamesSet.size() ); |
| std::set< rtl::OUString, lt_rtl_OUString >::const_iterator aItB; |
| k = 0; |
| for (aItB = aLocaleNamesSet.begin(); aItB != aLocaleNamesSet.end(); ++aItB) |
| { |
| Locale aTmp( MsLangId::convertLanguageToLocale( |
| MsLangId::convertIsoStringToLanguage( *aItB ))); |
| aSuppLocales[k++] = aTmp; |
| } |
| |
| //! For each dictionary and each locale we need a seperate entry. |
| //! If this results in more than one dictionary per locale than (for now) |
| //! it is undefined which dictionary gets used. |
| //! In the future the implementation should support using several dictionaries |
| //! for one locale. |
| numthes = 0; |
| for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt) |
| numthes = numthes + aDictIt->aLocaleNames.getLength(); |
| |
| // add dictionary information |
| aThes = new MyThes* [numthes]; |
| aTEncs = new rtl_TextEncoding [numthes]; |
| aTLocs = new Locale [numthes]; |
| aTNames = new OUString [numthes]; |
| aCharSetInfo = new CharClass* [numthes]; |
| |
| k = 0; |
| for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt) |
| { |
| if (aDictIt->aLocaleNames.getLength() > 0 && |
| aDictIt->aLocations.getLength() > 0) |
| { |
| uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames ); |
| sal_Int32 nLocales = aLocaleNames.getLength(); |
| |
| // currently only one language per dictionary is supported in the actual implementation... |
| // Thus here we work-around this by adding the same dictionary several times. |
| // Once for each of it's supported locales. |
| for (sal_Int32 i = 0; i < nLocales; ++i) |
| { |
| aThes[k] = NULL; |
| aTEncs[k] = RTL_TEXTENCODING_DONTKNOW; |
| aTLocs[k] = MsLangId::convertLanguageToLocale( |
| MsLangId::convertIsoStringToLanguage( aDictIt->aLocaleNames[i] )); |
| aCharSetInfo[k] = new CharClass( aTLocs[k] ); |
| // also both files have to be in the same directory and the |
| // file names must only differ in the extension (.aff/.dic). |
| // Thus we use the first location only and strip the extension part. |
| rtl::OUString aLocation = aDictIt->aLocations[0]; |
| sal_Int32 nPos = aLocation.lastIndexOf( '.' ); |
| aLocation = aLocation.copy( 0, nPos ); |
| aTNames[k] = aLocation; |
| |
| ++k; |
| } |
| } |
| } |
| DBG_ASSERT( k == numthes, "index mismatch?" ); |
| } |
| else |
| { |
| /* no dictionary found so register no dictionaries */ |
| numthes = 0; |
| aThes = NULL; |
| aTEncs = NULL; |
| aTLocs = NULL; |
| aTNames = NULL; |
| aCharSetInfo = NULL; |
| aSuppLocales.realloc(0); |
| } |
| } |
| |
| return aSuppLocales; |
| } |
| |
| |
| |
| sal_Bool SAL_CALL Thesaurus::hasLocale(const Locale& rLocale) |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| sal_Bool bRes = sal_False; |
| if (!aSuppLocales.getLength()) |
| getLocales(); |
| sal_Int32 nLen = aSuppLocales.getLength(); |
| for (sal_Int32 i = 0; i < nLen; ++i) |
| { |
| const Locale *pLocale = aSuppLocales.getConstArray(); |
| if (rLocale == pLocale[i]) |
| { |
| bRes = sal_True; |
| break; |
| } |
| } |
| return bRes; |
| } |
| |
| |
| Sequence < Reference < ::com::sun::star::linguistic2::XMeaning > > SAL_CALL Thesaurus::queryMeanings( |
| const OUString& qTerm, const Locale& rLocale, |
| const PropertyValues& rProperties) |
| throw(IllegalArgumentException, RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| uno::Sequence< Reference< XMeaning > > aMeanings( 1 ); |
| uno::Sequence< Reference< XMeaning > > noMeanings( 0 ); |
| uno::Reference< XLinguServiceManager > xLngSvcMgr( GetLngSvcMgr_Impl() ); |
| uno::Reference< XSpellChecker1 > xSpell; |
| |
| OUString rTerm(qTerm); |
| OUString pTerm(qTerm); |
| sal_uInt16 ct = CAPTYPE_UNKNOWN; |
| sal_Int32 stem = 0; |
| sal_Int32 stem2 = 0; |
| |
| sal_Int16 nLanguage = LocaleToLanguage( rLocale ); |
| |
| if (nLanguage == LANGUAGE_NONE || !rTerm.getLength()) |
| return noMeanings; |
| |
| if (!hasLocale( rLocale )) |
| #ifdef LINGU_EXCEPTIONS |
| throw( IllegalArgumentException() ); |
| #else |
| return noMeanings; |
| #endif |
| |
| if (prevTerm == qTerm && prevLocale == nLanguage) |
| return prevMeanings; |
| |
| mentry * pmean = NULL; |
| sal_Int32 nmean = 0; |
| |
| PropertyHelper_Thes &rHelper = GetPropHelper(); |
| rHelper.SetTmpPropVals( rProperties ); |
| |
| MyThes * pTH = NULL; |
| rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW; |
| CharClass * pCC = NULL; |
| |
| // find the first thesaurus that matches the locale |
| for (int i =0; i < numthes; i++) |
| { |
| if (rLocale == aTLocs[i]) |
| { |
| // open up and intialize this thesaurus if need be |
| if (!aThes[i]) |
| { |
| OUString datpath = aTNames[i] + A2OU(".dat"); |
| OUString idxpath = aTNames[i] + A2OU(".idx"); |
| OUString ndat; |
| OUString nidx; |
| osl::FileBase::getSystemPathFromFileURL(datpath,ndat); |
| osl::FileBase::getSystemPathFromFileURL(idxpath,nidx); |
| OString aTmpidx(OU2ENC(nidx,osl_getThreadTextEncoding())); |
| OString aTmpdat(OU2ENC(ndat,osl_getThreadTextEncoding())); |
| |
| #if defined(WNT) |
| // workaround for Windows specifc problem that the |
| // path length in calls to 'fopen' is limted to somewhat |
| // about 120+ characters which will usually be exceed when |
| // using dictionaries as extensions. |
| aTmpidx = Win_GetShortPathName( nidx ); |
| aTmpdat = Win_GetShortPathName( ndat ); |
| #endif |
| |
| aThes[i] = new MyThes(aTmpidx.getStr(),aTmpdat.getStr()); |
| if (aThes[i]) |
| aTEncs[i] = getTextEncodingFromCharset(aThes[i]->get_th_encoding()); |
| } |
| pTH = aThes[i]; |
| eEnc = aTEncs[i]; |
| pCC = aCharSetInfo[i]; |
| |
| if (pTH) |
| break; |
| } |
| } |
| |
| // we don't want to work with a default text encoding since following incorrect |
| // results may occur only for specific text and thus may be hard to notice. |
| // Thus better always make a clean exit here if the text encoding is in question. |
| // Hopefully something not working at all will raise proper attention quickly. ;-) |
| DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" ); |
| if (eEnc == RTL_TEXTENCODING_DONTKNOW) |
| return noMeanings; |
| |
| while (pTH) |
| { |
| // convert word to all lower case for searching |
| if (!stem) |
| ct = capitalType(rTerm, pCC); |
| OUString nTerm(makeLowerCase(rTerm, pCC)); |
| OString aTmp( OU2ENC(nTerm, eEnc) ); |
| nmean = pTH->Lookup(aTmp.getStr(),aTmp.getLength(),&pmean); |
| |
| if (nmean) |
| aMeanings.realloc( nmean ); |
| |
| mentry * pe = pmean; |
| OUString codeTerm = qTerm; |
| Reference< XSpellAlternatives > xTmpRes2; |
| |
| if (stem) |
| { |
| xTmpRes2 = xSpell->spell( A2OU("<?xml?><query type='analyze'><word>") + |
| pTerm + A2OU("</word></query>"), nLanguage, rProperties ); |
| if (xTmpRes2.is()) |
| { |
| Sequence<OUString>seq = xTmpRes2->getAlternatives(); |
| if (seq.getLength() > 0) |
| { |
| codeTerm = seq[0]; |
| stem2 = 1; |
| } |
| #if 0 |
| OString o = OUStringToOString(codeTerm, RTL_TEXTENCODING_UTF8); |
| fprintf(stderr, "CODETERM: %s\n", o.pData->buffer); |
| #endif |
| } |
| } |
| |
| for (int j = 0; j < nmean; j++) |
| { |
| int count = pe->count; |
| if (count) |
| { |
| Sequence< OUString > aStr( count ); |
| OUString *pStr = aStr.getArray(); |
| |
| for (int i=0; i < count; i++) |
| { |
| OUString sTerm(pe->psyns[i],strlen(pe->psyns[i]),eEnc ); |
| sal_Int32 catpos = sTerm.indexOf('('); |
| sal_Int32 catpos2 = 0; |
| OUString catst; |
| OUString catst2; |
| if (catpos > 2) |
| { |
| // remove category name for affixation and casing |
| catst = A2OU(" ") + sTerm.copy(catpos); |
| sTerm = sTerm.copy(0, catpos); |
| sTerm = sTerm.trim(); |
| } |
| // generate synonyms with affixes |
| if (stem && stem2) |
| { |
| Reference< XSpellAlternatives > xTmpRes; |
| xTmpRes = xSpell->spell( A2OU("<?xml?><query type='generate'><word>") + |
| sTerm + A2OU("</word>") + codeTerm + A2OU("</query>"), nLanguage, rProperties ); |
| if (xTmpRes.is()) |
| { |
| Sequence<OUString>seq = xTmpRes->getAlternatives(); |
| if (seq.getLength() > 0) |
| sTerm = seq[0]; |
| } |
| } |
| if (catpos2) |
| sTerm = catst2 + sTerm; |
| |
| sal_uInt16 ct1 = capitalType(sTerm, pCC); |
| if (CAPTYPE_MIXED == ct1) |
| ct = ct1; |
| OUString cTerm; |
| switch (ct) |
| { |
| case CAPTYPE_ALLCAP: |
| cTerm = makeUpperCase(sTerm, pCC); |
| break; |
| case CAPTYPE_INITCAP: |
| cTerm = makeInitCap(sTerm, pCC); |
| break; |
| default: |
| cTerm = sTerm; |
| break; |
| } |
| OUString aAlt( cTerm + catst); |
| pStr[i] = aAlt; |
| } |
| #if 0 |
| Meaning * pMn = new Meaning(rTerm,nLanguage,rHelper); |
| #endif |
| Meaning * pMn = new Meaning(rTerm,nLanguage); |
| OUString dTerm(pe->defn,strlen(pe->defn),eEnc ); |
| pMn->SetMeaning(dTerm); |
| pMn->SetSynonyms(aStr); |
| Reference<XMeaning>* pMeaning = aMeanings.getArray(); |
| pMeaning[j] = pMn; |
| } |
| pe++; |
| } |
| pTH->CleanUpAfterLookup(&pmean,nmean); |
| |
| if (nmean) |
| { |
| prevTerm = qTerm; |
| prevMeanings = aMeanings; |
| prevLocale = nLanguage; |
| return aMeanings; |
| } |
| |
| if (stem || !xLngSvcMgr.is()) |
| return noMeanings; |
| stem = 1; |
| |
| xSpell = uno::Reference< XSpellChecker1 >( xLngSvcMgr->getSpellChecker(), UNO_QUERY ); |
| if (!xSpell.is() || !xSpell->isValid( A2OU(SPELLML_SUPPORT), nLanguage, rProperties )) |
| return noMeanings; |
| Reference< XSpellAlternatives > xTmpRes; |
| xTmpRes = xSpell->spell( A2OU("<?xml?><query type='stem'><word>") + |
| rTerm + A2OU("</word></query>"), nLanguage, rProperties ); |
| if (xTmpRes.is()) |
| { |
| Sequence<OUString>seq = xTmpRes->getAlternatives(); |
| #if 0 |
| for (int i = 0; i < seq.getLength(); i++) |
| { |
| OString o = OUStringToOString(seq[i], RTL_TEXTENCODING_UTF8); |
| fprintf(stderr, "%d: %s\n", i + 1, o.pData->buffer); |
| } |
| #endif |
| if (seq.getLength() > 0) |
| { |
| rTerm = seq[0]; // XXX Use only the first stem |
| continue; |
| } |
| } |
| |
| // stem the last word of the synonym (for categories after affixation) |
| rTerm = rTerm.trim(); |
| sal_Int32 pos = rTerm.lastIndexOf(' '); |
| if (!pos) |
| return noMeanings; |
| xTmpRes = xSpell->spell( A2OU("<?xml?><query type='stem'><word>") + |
| rTerm.copy(pos + 1) + A2OU("</word></query>"), nLanguage, rProperties ); |
| if (xTmpRes.is()) |
| { |
| Sequence<OUString>seq = xTmpRes->getAlternatives(); |
| if (seq.getLength() > 0) |
| { |
| pTerm = rTerm.copy(pos + 1); |
| rTerm = rTerm.copy(0, pos + 1) + seq[0]; |
| #if 0 |
| for (int i = 0; i < seq.getLength(); i++) |
| { |
| OString o = OUStringToOString(seq[i], RTL_TEXTENCODING_UTF8); |
| fprintf(stderr, "%d: %s\n", i + 1, o.pData->buffer); |
| } |
| #endif |
| continue; |
| } |
| } |
| break; |
| } |
| return noMeanings; |
| } |
| |
| |
| Reference< XInterface > SAL_CALL Thesaurus_CreateInstance( |
| const Reference< XMultiServiceFactory > & /*rSMgr*/ ) |
| throw(Exception) |
| { |
| Reference< XInterface > xService = (cppu::OWeakObject*) new Thesaurus; |
| return xService; |
| } |
| |
| |
| OUString SAL_CALL Thesaurus::getServiceDisplayName( const Locale& /*rLocale*/ ) |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| return A2OU( "OpenOffice.org New Thesaurus" ); |
| } |
| |
| |
| void SAL_CALL Thesaurus::initialize( const Sequence< Any >& rArguments ) |
| throw(Exception, RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| if (!pPropHelper) |
| { |
| sal_Int32 nLen = rArguments.getLength(); |
| if (1 == nLen) |
| { |
| Reference< XPropertySet > xPropSet; |
| rArguments.getConstArray()[0] >>= xPropSet; |
| |
| //! Pointer allows for access of the non-UNO functions. |
| //! And the reference to the UNO-functions while increasing |
| //! the ref-count and will implicitly free the memory |
| //! when the object is not longer used. |
| pPropHelper = new PropertyHelper_Thes( (XThesaurus *) this, xPropSet ); |
| xPropHelper = pPropHelper; |
| pPropHelper->AddAsPropListener(); //! after a reference is established |
| } |
| else |
| DBG_ERROR( "wrong number of arguments in sequence" ); |
| } |
| } |
| |
| |
| |
| sal_uInt16 SAL_CALL Thesaurus::capitalType(const OUString& aTerm, CharClass * pCC) |
| { |
| sal_Int32 tlen = aTerm.getLength(); |
| if ((pCC) && (tlen)) |
| { |
| String aStr(aTerm); |
| sal_Int32 nc = 0; |
| for (sal_uInt16 tindex = 0; tindex < tlen; tindex++) |
| { |
| if (pCC->getCharacterType(aStr,tindex) & |
| ::com::sun::star::i18n::KCharacterType::UPPER) nc++; |
| } |
| |
| if (nc == 0) |
| return (sal_uInt16) CAPTYPE_NOCAP; |
| if (nc == tlen) |
| return (sal_uInt16) CAPTYPE_ALLCAP; |
| if ((nc == 1) && (pCC->getCharacterType(aStr,0) & |
| ::com::sun::star::i18n::KCharacterType::UPPER)) |
| return (sal_uInt16) CAPTYPE_INITCAP; |
| |
| return (sal_uInt16) CAPTYPE_MIXED; |
| } |
| return (sal_uInt16) CAPTYPE_UNKNOWN; |
| } |
| |
| |
| |
| OUString SAL_CALL Thesaurus::makeLowerCase(const OUString& aTerm, CharClass * pCC) |
| { |
| if (pCC) |
| return pCC->toLower_rtl(aTerm, 0, aTerm.getLength()); |
| return aTerm; |
| } |
| |
| |
| OUString SAL_CALL Thesaurus::makeUpperCase(const OUString& aTerm, CharClass * pCC) |
| { |
| if (pCC) |
| return pCC->toUpper_rtl(aTerm, 0, aTerm.getLength()); |
| return aTerm; |
| } |
| |
| |
| OUString SAL_CALL Thesaurus::makeInitCap(const OUString& aTerm, CharClass * pCC) |
| { |
| sal_Int32 tlen = aTerm.getLength(); |
| if ((pCC) && (tlen)) |
| { |
| OUString bTemp = aTerm.copy(0,1); |
| if (tlen > 1) |
| { |
| return ( pCC->toUpper_rtl(bTemp, 0, 1) |
| + pCC->toLower_rtl(aTerm,1,(tlen-1)) ); |
| } |
| |
| return pCC->toUpper_rtl(bTemp, 0, 1); |
| } |
| return aTerm; |
| } |
| |
| |
| |
| void SAL_CALL Thesaurus::dispose() |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| if (!bDisposing) |
| { |
| bDisposing = sal_True; |
| EventObject aEvtObj( (XThesaurus *) this ); |
| aEvtListeners.disposeAndClear( aEvtObj ); |
| } |
| } |
| |
| |
| void SAL_CALL Thesaurus::addEventListener( const Reference< XEventListener >& rxListener ) |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| if (!bDisposing && rxListener.is()) |
| aEvtListeners.addInterface( rxListener ); |
| } |
| |
| |
| void SAL_CALL Thesaurus::removeEventListener( const Reference< XEventListener >& rxListener ) |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| if (!bDisposing && rxListener.is()) |
| aEvtListeners.removeInterface( rxListener ); |
| } |
| |
| |
| /////////////////////////////////////////////////////////////////////////// |
| // Service specific part |
| // |
| |
| OUString SAL_CALL Thesaurus::getImplementationName() |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| return getImplementationName_Static(); |
| } |
| |
| |
| sal_Bool SAL_CALL Thesaurus::supportsService( const OUString& ServiceName ) |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Sequence< OUString > aSNL = getSupportedServiceNames(); |
| const OUString * pArray = aSNL.getConstArray(); |
| for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) |
| if( pArray[i] == ServiceName ) |
| return sal_True; |
| return sal_False; |
| } |
| |
| |
| Sequence< OUString > SAL_CALL Thesaurus::getSupportedServiceNames() |
| throw(RuntimeException) |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| return getSupportedServiceNames_Static(); |
| } |
| |
| |
| Sequence< OUString > Thesaurus::getSupportedServiceNames_Static() |
| throw() |
| { |
| MutexGuard aGuard( GetLinguMutex() ); |
| |
| Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich |
| aSNS.getArray()[0] = A2OU( SN_THESAURUS ); |
| return aSNS; |
| } |
| |
| void * SAL_CALL Thesaurus_getFactory( const sal_Char * pImplName, |
| XMultiServiceFactory * pServiceManager, void * ) |
| { |
| void * pRet = 0; |
| if ( !Thesaurus::getImplementationName_Static().compareToAscii( pImplName ) ) |
| { |
| |
| Reference< XSingleServiceFactory > xFactory = |
| cppu::createOneInstanceFactory( |
| pServiceManager, |
| Thesaurus::getImplementationName_Static(), |
| Thesaurus_CreateInstance, |
| Thesaurus::getSupportedServiceNames_Static()); |
| // acquire, because we return an interface pointer instead of a reference |
| xFactory->acquire(); |
| pRet = xFactory.get(); |
| } |
| return pRet; |
| } |
| |
| |
| /////////////////////////////////////////////////////////////////////////// |
| |
| |
| #undef CAPTYPE_UNKNOWN |
| #undef CAPTYPE_NOCAP |
| #undef CAPTYPE_INITCAP |
| #undef CAPTYPE_ALLCAP |
| #undef CAPTYPE_MIXED |