PageRenderTime 58ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/lingucomponent/source/thesaurus/libnth/nthesimp.cxx

https://bitbucket.org/markjenkins/libreoffice_ubuntu-debian-fixes
C++ | 761 lines | 580 code | 112 blank | 69 comment | 105 complexity | e981434e9a98104556c87c502a0f83a2 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause-No-Nuclear-License-2014
  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
  2. /*
  3. * This file is part of the LibreOffice project.
  4. *
  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/.
  8. *
  9. * This file incorporates work covered by the following license notice:
  10. *
  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 .
  18. */
  19. #include <com/sun/star/uno/Reference.h>
  20. #include <cppuhelper/factory.hxx> // helper for factories
  21. #include <com/sun/star/registry/XRegistryKey.hpp>
  22. #include <com/sun/star/beans/XPropertySet.hpp>
  23. #include <com/sun/star/linguistic2/LinguServiceManager.hpp>
  24. #include <i18npool/languagetag.hxx>
  25. #include <tools/debug.hxx>
  26. #include <comphelper/processfactory.hxx>
  27. #include <osl/mutex.hxx>
  28. #include <unotools/pathoptions.hxx>
  29. #include <unotools/lingucfg.hxx>
  30. #include <rtl/string.hxx>
  31. #include <rtl/ustrbuf.hxx>
  32. #include <rtl/textenc.h>
  33. #include "nthesimp.hxx"
  34. #include <linguistic/misc.hxx>
  35. #include <linguistic/lngprops.hxx>
  36. #include "nthesdta.hxx"
  37. #include <list>
  38. #include <set>
  39. #include <string.h>
  40. // values asigned to capitalization types
  41. #define CAPTYPE_UNKNOWN 0
  42. #define CAPTYPE_NOCAP 1
  43. #define CAPTYPE_INITCAP 2
  44. #define CAPTYPE_ALLCAP 3
  45. #define CAPTYPE_MIXED 4
  46. // XML-header to query SPELLML support
  47. #define SPELLML_SUPPORT "<?xml?>"
  48. using namespace osl;
  49. using namespace com::sun::star;
  50. using namespace com::sun::star::beans;
  51. using namespace com::sun::star::lang;
  52. using namespace com::sun::star::uno;
  53. using namespace com::sun::star::linguistic2;
  54. using namespace linguistic;
  55. using ::rtl::OUString;
  56. using ::rtl::OString;
  57. using ::rtl::OUStringToOString;
  58. ///////////////////////////////////////////////////////////////////////////
  59. static uno::Reference< XLinguServiceManager2 > GetLngSvcMgr_Impl()
  60. {
  61. uno::Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
  62. uno::Reference< XLinguServiceManager2 > xRes = LinguServiceManager::create( xContext ) ;
  63. return xRes;
  64. }
  65. Thesaurus::Thesaurus() :
  66. aEvtListeners ( GetLinguMutex() )
  67. {
  68. bDisposing = false;
  69. pPropHelper = NULL;
  70. aThes = NULL;
  71. aCharSetInfo = NULL;
  72. aTEncs = NULL;
  73. aTLocs = NULL;
  74. aTNames = NULL;
  75. numthes = 0;
  76. }
  77. Thesaurus::~Thesaurus()
  78. {
  79. if (aThes)
  80. {
  81. for (int i = 0; i < numthes; i++)
  82. {
  83. if (aThes[i]) delete aThes[i];
  84. aThes[i] = NULL;
  85. }
  86. delete[] aThes;
  87. }
  88. aThes = NULL;
  89. if (aCharSetInfo)
  90. {
  91. for (int i = 0; i < numthes; i++)
  92. {
  93. if (aCharSetInfo[i]) delete aCharSetInfo[i];
  94. aCharSetInfo[i] = NULL;
  95. }
  96. delete[] aCharSetInfo;
  97. }
  98. aCharSetInfo = NULL;
  99. numthes = 0;
  100. if (aTEncs) delete[] aTEncs;
  101. aTEncs = NULL;
  102. if (aTLocs) delete[] aTLocs;
  103. aTLocs = NULL;
  104. if (aTNames) delete[] aTNames;
  105. aTNames = NULL;
  106. if (pPropHelper)
  107. {
  108. pPropHelper->RemoveAsPropListener();
  109. delete pPropHelper;
  110. }
  111. }
  112. PropertyHelper_Thesaurus& Thesaurus::GetPropHelper_Impl()
  113. {
  114. if (!pPropHelper)
  115. {
  116. Reference< XPropertySet > xPropSet( GetLinguProperties(), UNO_QUERY );
  117. pPropHelper = new PropertyHelper_Thesaurus( (XThesaurus *) this, xPropSet );
  118. pPropHelper->AddAsPropListener(); //! after a reference is established
  119. }
  120. return *pPropHelper;
  121. }
  122. Sequence< Locale > SAL_CALL Thesaurus::getLocales()
  123. throw(RuntimeException)
  124. {
  125. MutexGuard aGuard( GetLinguMutex() );
  126. // this routine should return the locales supported by the installed
  127. // dictionaries.
  128. if (!numthes)
  129. {
  130. SvtLinguConfig aLinguCfg;
  131. // get list of dictionaries-to-use
  132. std::list< SvtLinguConfigDictionaryEntry > aDics;
  133. uno::Sequence< rtl::OUString > aFormatList;
  134. aLinguCfg.GetSupportedDictionaryFormatsFor( A2OU("Thesauri"),
  135. A2OU("org.openoffice.lingu.new.Thesaurus"), aFormatList );
  136. sal_Int32 nLen = aFormatList.getLength();
  137. for (sal_Int32 i = 0; i < nLen; ++i)
  138. {
  139. std::vector< SvtLinguConfigDictionaryEntry > aTmpDic(
  140. aLinguCfg.GetActiveDictionariesByFormat( aFormatList[i] ) );
  141. aDics.insert( aDics.end(), aTmpDic.begin(), aTmpDic.end() );
  142. }
  143. //!! for compatibility with old dictionaries (the ones not using extensions
  144. //!! or new configuration entries, but still using the dictionary.lst file)
  145. //!! Get the list of old style spell checking dictionaries to use...
  146. std::vector< SvtLinguConfigDictionaryEntry > aOldStyleDics(
  147. GetOldStyleDics( "THES" ) );
  148. // to prefer dictionaries with configuration entries we will only
  149. // use those old style dictionaries that add a language that
  150. // is not yet supported by the list od new style dictionaries
  151. MergeNewStyleDicsAndOldStyleDics( aDics, aOldStyleDics );
  152. numthes = aDics.size();
  153. if (numthes)
  154. {
  155. // get supported locales from the dictionaries-to-use...
  156. sal_Int32 k = 0;
  157. std::set< rtl::OUString, lt_rtl_OUString > aLocaleNamesSet;
  158. std::list< SvtLinguConfigDictionaryEntry >::const_iterator aDictIt;
  159. for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
  160. {
  161. uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
  162. sal_Int32 nLen2 = aLocaleNames.getLength();
  163. for (k = 0; k < nLen2; ++k)
  164. {
  165. aLocaleNamesSet.insert( aLocaleNames[k] );
  166. }
  167. }
  168. // ... and add them to the resulting sequence
  169. aSuppLocales.realloc( aLocaleNamesSet.size() );
  170. std::set< rtl::OUString, lt_rtl_OUString >::const_iterator aItB;
  171. k = 0;
  172. for (aItB = aLocaleNamesSet.begin(); aItB != aLocaleNamesSet.end(); ++aItB)
  173. {
  174. Locale aTmp( LanguageTag( *aItB ).getLocale());
  175. aSuppLocales[k++] = aTmp;
  176. }
  177. //! For each dictionary and each locale we need a seperate entry.
  178. //! If this results in more than one dictionary per locale than (for now)
  179. //! it is undefined which dictionary gets used.
  180. //! In the future the implementation should support using several dictionaries
  181. //! for one locale.
  182. numthes = 0;
  183. for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
  184. numthes = numthes + aDictIt->aLocaleNames.getLength();
  185. // add dictionary information
  186. aThes = new MyThes* [numthes];
  187. aTEncs = new rtl_TextEncoding [numthes];
  188. aTLocs = new Locale [numthes];
  189. aTNames = new OUString [numthes];
  190. aCharSetInfo = new CharClass* [numthes];
  191. k = 0;
  192. for (aDictIt = aDics.begin(); aDictIt != aDics.end(); ++aDictIt)
  193. {
  194. if (aDictIt->aLocaleNames.getLength() > 0 &&
  195. aDictIt->aLocations.getLength() > 0)
  196. {
  197. uno::Sequence< rtl::OUString > aLocaleNames( aDictIt->aLocaleNames );
  198. sal_Int32 nLocales = aLocaleNames.getLength();
  199. // currently only one language per dictionary is supported in the actual implementation...
  200. // Thus here we work-around this by adding the same dictionary several times.
  201. // Once for each of it's supported locales.
  202. for (sal_Int32 i = 0; i < nLocales; ++i)
  203. {
  204. LanguageTag aLanguageTag( aDictIt->aLocaleNames[i] );
  205. aThes[k] = NULL;
  206. aTEncs[k] = RTL_TEXTENCODING_DONTKNOW;
  207. aTLocs[k] = aLanguageTag.getLocale();
  208. aCharSetInfo[k] = new CharClass( aLanguageTag );
  209. // also both files have to be in the same directory and the
  210. // file names must only differ in the extension (.aff/.dic).
  211. // Thus we use the first location only and strip the extension part.
  212. rtl::OUString aLocation = aDictIt->aLocations[0];
  213. sal_Int32 nPos = aLocation.lastIndexOf( '.' );
  214. aLocation = aLocation.copy( 0, nPos );
  215. aTNames[k] = aLocation;
  216. ++k;
  217. }
  218. }
  219. }
  220. DBG_ASSERT( k == numthes, "index mismatch?" );
  221. }
  222. else
  223. {
  224. /* no dictionary found so register no dictionaries */
  225. numthes = 0;
  226. aThes = NULL;
  227. aTEncs = NULL;
  228. aTLocs = NULL;
  229. aTNames = NULL;
  230. aCharSetInfo = NULL;
  231. aSuppLocales.realloc(0);
  232. }
  233. }
  234. return aSuppLocales;
  235. }
  236. sal_Bool SAL_CALL Thesaurus::hasLocale(const Locale& rLocale)
  237. throw(RuntimeException)
  238. {
  239. MutexGuard aGuard( GetLinguMutex() );
  240. sal_Bool bRes = sal_False;
  241. if (!aSuppLocales.getLength())
  242. getLocales();
  243. sal_Int32 nLen = aSuppLocales.getLength();
  244. for (sal_Int32 i = 0; i < nLen; ++i)
  245. {
  246. const Locale *pLocale = aSuppLocales.getConstArray();
  247. if (rLocale == pLocale[i])
  248. {
  249. bRes = sal_True;
  250. break;
  251. }
  252. }
  253. return bRes;
  254. }
  255. Sequence < Reference < ::com::sun::star::linguistic2::XMeaning > > SAL_CALL Thesaurus::queryMeanings(
  256. const OUString& qTerm, const Locale& rLocale,
  257. const PropertyValues& rProperties)
  258. throw(IllegalArgumentException, RuntimeException)
  259. {
  260. MutexGuard aGuard( GetLinguMutex() );
  261. uno::Sequence< Reference< XMeaning > > aMeanings( 1 );
  262. uno::Sequence< Reference< XMeaning > > noMeanings( 0 );
  263. uno::Reference< XLinguServiceManager2 > xLngSvcMgr( GetLngSvcMgr_Impl() );
  264. uno::Reference< XSpellChecker1 > xSpell;
  265. OUString rTerm(qTerm);
  266. OUString pTerm(qTerm);
  267. sal_uInt16 ct = CAPTYPE_UNKNOWN;
  268. sal_Int32 stem = 0;
  269. sal_Int32 stem2 = 0;
  270. sal_Int16 nLanguage = LanguageTag( rLocale ).getLanguageType();
  271. if (nLanguage == LANGUAGE_NONE || rTerm.isEmpty())
  272. return noMeanings;
  273. if (!hasLocale( rLocale ))
  274. #ifdef LINGU_EXCEPTIONS
  275. throw( IllegalArgumentException() );
  276. #else
  277. return noMeanings;
  278. #endif
  279. if (prevTerm == qTerm && prevLocale == nLanguage)
  280. return prevMeanings;
  281. mentry * pmean = NULL;
  282. sal_Int32 nmean = 0;
  283. PropertyHelper_Thesaurus &rHelper = GetPropHelper();
  284. rHelper.SetTmpPropVals( rProperties );
  285. MyThes * pTH = NULL;
  286. rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW;
  287. CharClass * pCC = NULL;
  288. // find the first thesaurus that matches the locale
  289. for (int i =0; i < numthes; i++)
  290. {
  291. if (rLocale == aTLocs[i])
  292. {
  293. // open up and intialize this thesaurus if need be
  294. if (!aThes[i])
  295. {
  296. OUString datpath = aTNames[i] + A2OU(".dat");
  297. OUString idxpath = aTNames[i] + A2OU(".idx");
  298. OUString ndat;
  299. OUString nidx;
  300. osl::FileBase::getSystemPathFromFileURL(datpath,ndat);
  301. osl::FileBase::getSystemPathFromFileURL(idxpath,nidx);
  302. OString aTmpidx(OU2ENC(nidx,osl_getThreadTextEncoding()));
  303. OString aTmpdat(OU2ENC(ndat,osl_getThreadTextEncoding()));
  304. #if defined(WNT)
  305. // workaround for Windows specifc problem that the
  306. // path length in calls to 'fopen' is limted to somewhat
  307. // about 120+ characters which will usually be exceed when
  308. // using dictionaries as extensions.
  309. aTmpidx = Win_GetShortPathName( nidx );
  310. aTmpdat = Win_GetShortPathName( ndat );
  311. #endif
  312. aThes[i] = new MyThes(aTmpidx.getStr(),aTmpdat.getStr());
  313. if (aThes[i])
  314. aTEncs[i] = getTextEncodingFromCharset(aThes[i]->get_th_encoding());
  315. }
  316. pTH = aThes[i];
  317. eEnc = aTEncs[i];
  318. pCC = aCharSetInfo[i];
  319. if (pTH)
  320. break;
  321. }
  322. }
  323. // we don't want to work with a default text encoding since following incorrect
  324. // results may occur only for specific text and thus may be hard to notice.
  325. // Thus better always make a clean exit here if the text encoding is in question.
  326. // Hopefully something not working at all will raise proper attention quickly. ;-)
  327. DBG_ASSERT( eEnc != RTL_TEXTENCODING_DONTKNOW, "failed to get text encoding! (maybe incorrect encoding string in file)" );
  328. if (eEnc == RTL_TEXTENCODING_DONTKNOW)
  329. return noMeanings;
  330. while (pTH)
  331. {
  332. // convert word to all lower case for searching
  333. if (!stem)
  334. ct = capitalType(rTerm, pCC);
  335. OUString nTerm(makeLowerCase(rTerm, pCC));
  336. OString aTmp( OU2ENC(nTerm, eEnc) );
  337. nmean = pTH->Lookup(aTmp.getStr(),aTmp.getLength(),&pmean);
  338. if (nmean)
  339. aMeanings.realloc( nmean );
  340. mentry * pe = pmean;
  341. OUString codeTerm = qTerm;
  342. Reference< XSpellAlternatives > xTmpRes2;
  343. if (stem)
  344. {
  345. xTmpRes2 = xSpell->spell( A2OU("<?xml?><query type='analyze'><word>") +
  346. pTerm + A2OU("</word></query>"), nLanguage, rProperties );
  347. if (xTmpRes2.is())
  348. {
  349. Sequence<OUString>seq = xTmpRes2->getAlternatives();
  350. if (seq.getLength() > 0)
  351. {
  352. codeTerm = seq[0];
  353. stem2 = 1;
  354. }
  355. }
  356. }
  357. for (int j = 0; j < nmean; j++)
  358. {
  359. int count = pe->count;
  360. if (count)
  361. {
  362. Sequence< OUString > aStr( count );
  363. OUString *pStr = aStr.getArray();
  364. for (int i=0; i < count; i++)
  365. {
  366. OUString sTerm(pe->psyns[i],strlen(pe->psyns[i]),eEnc );
  367. sal_Int32 catpos = sTerm.indexOf('(');
  368. sal_Int32 catpos2 = 0;
  369. OUString catst;
  370. OUString catst2;
  371. if (catpos > 2)
  372. {
  373. // remove category name for affixation and casing
  374. catst = A2OU(" ") + sTerm.copy(catpos);
  375. sTerm = sTerm.copy(0, catpos);
  376. sTerm = sTerm.trim();
  377. }
  378. // generate synonyms with affixes
  379. if (stem && stem2)
  380. {
  381. Reference< XSpellAlternatives > xTmpRes;
  382. xTmpRes = xSpell->spell( A2OU("<?xml?><query type='generate'><word>") +
  383. sTerm + A2OU("</word>") + codeTerm + A2OU("</query>"), nLanguage, rProperties );
  384. if (xTmpRes.is())
  385. {
  386. Sequence<OUString>seq = xTmpRes->getAlternatives();
  387. if (seq.getLength() > 0)
  388. sTerm = seq[0];
  389. }
  390. }
  391. if (catpos2)
  392. sTerm = catst2 + sTerm;
  393. sal_uInt16 ct1 = capitalType(sTerm, pCC);
  394. if (CAPTYPE_MIXED == ct1)
  395. ct = ct1;
  396. OUString cTerm;
  397. switch (ct)
  398. {
  399. case CAPTYPE_ALLCAP:
  400. cTerm = makeUpperCase(sTerm, pCC);
  401. break;
  402. case CAPTYPE_INITCAP:
  403. cTerm = makeInitCap(sTerm, pCC);
  404. break;
  405. default:
  406. cTerm = sTerm;
  407. break;
  408. }
  409. OUString aAlt( cTerm + catst);
  410. pStr[i] = aAlt;
  411. }
  412. Meaning * pMn = new Meaning(rTerm,nLanguage);
  413. OUString dTerm(pe->defn,strlen(pe->defn),eEnc );
  414. pMn->SetMeaning(dTerm);
  415. pMn->SetSynonyms(aStr);
  416. Reference<XMeaning>* pMeaning = aMeanings.getArray();
  417. pMeaning[j] = pMn;
  418. }
  419. pe++;
  420. }
  421. pTH->CleanUpAfterLookup(&pmean,nmean);
  422. if (nmean)
  423. {
  424. prevTerm = qTerm;
  425. prevMeanings = aMeanings;
  426. prevLocale = nLanguage;
  427. return aMeanings;
  428. }
  429. if (stem || !xLngSvcMgr.is())
  430. return noMeanings;
  431. stem = 1;
  432. xSpell = uno::Reference< XSpellChecker1 >( xLngSvcMgr->getSpellChecker(), UNO_QUERY );
  433. if (!xSpell.is() || !xSpell->isValid( A2OU(SPELLML_SUPPORT), nLanguage, rProperties ))
  434. return noMeanings;
  435. Reference< XSpellAlternatives > xTmpRes;
  436. xTmpRes = xSpell->spell( A2OU("<?xml?><query type='stem'><word>") +
  437. rTerm + A2OU("</word></query>"), nLanguage, rProperties );
  438. if (xTmpRes.is())
  439. {
  440. Sequence<OUString>seq = xTmpRes->getAlternatives();
  441. if (seq.getLength() > 0)
  442. {
  443. rTerm = seq[0]; // XXX Use only the first stem
  444. continue;
  445. }
  446. }
  447. // stem the last word of the synonym (for categories after affixation)
  448. rTerm = rTerm.trim();
  449. sal_Int32 pos = rTerm.lastIndexOf(' ');
  450. if (!pos)
  451. return noMeanings;
  452. xTmpRes = xSpell->spell( A2OU("<?xml?><query type='stem'><word>") +
  453. rTerm.copy(pos + 1) + A2OU("</word></query>"), nLanguage, rProperties );
  454. if (xTmpRes.is())
  455. {
  456. Sequence<OUString>seq = xTmpRes->getAlternatives();
  457. if (seq.getLength() > 0)
  458. {
  459. pTerm = rTerm.copy(pos + 1);
  460. rTerm = rTerm.copy(0, pos + 1) + seq[0];
  461. #if 0
  462. for (int i = 0; i < seq.getLength(); i++)
  463. {
  464. OString o = OUStringToOString(seq[i], RTL_TEXTENCODING_UTF8);
  465. fprintf(stderr, "%d: %s\n", i + 1, o.pData->buffer);
  466. }
  467. #endif
  468. continue;
  469. }
  470. }
  471. break;
  472. }
  473. return noMeanings;
  474. }
  475. Reference< XInterface > SAL_CALL Thesaurus_CreateInstance(
  476. const Reference< XMultiServiceFactory > & /*rSMgr*/ )
  477. throw(Exception)
  478. {
  479. Reference< XInterface > xService = (cppu::OWeakObject*) new Thesaurus;
  480. return xService;
  481. }
  482. OUString SAL_CALL Thesaurus::getServiceDisplayName( const Locale& /*rLocale*/ )
  483. throw(RuntimeException)
  484. {
  485. MutexGuard aGuard( GetLinguMutex() );
  486. return A2OU( "OpenOffice.org New Thesaurus" );
  487. }
  488. void SAL_CALL Thesaurus::initialize( const Sequence< Any >& rArguments )
  489. throw(Exception, RuntimeException)
  490. {
  491. MutexGuard aGuard( GetLinguMutex() );
  492. if (!pPropHelper)
  493. {
  494. sal_Int32 nLen = rArguments.getLength();
  495. if (1 == nLen)
  496. {
  497. Reference< XPropertySet > xPropSet;
  498. rArguments.getConstArray()[0] >>= xPropSet;
  499. //! Pointer allows for access of the non-UNO functions.
  500. //! And the reference to the UNO-functions while increasing
  501. //! the ref-count and will implicitly free the memory
  502. //! when the object is not longer used.
  503. pPropHelper = new PropertyHelper_Thesaurus( (XThesaurus *) this, xPropSet );
  504. pPropHelper->AddAsPropListener(); //! after a reference is established
  505. }
  506. else
  507. OSL_FAIL( "wrong number of arguments in sequence" );
  508. }
  509. }
  510. sal_uInt16 SAL_CALL Thesaurus::capitalType(const OUString& aTerm, CharClass * pCC)
  511. {
  512. sal_Int32 tlen = aTerm.getLength();
  513. if ((pCC) && (tlen))
  514. {
  515. String aStr(aTerm);
  516. sal_Int32 nc = 0;
  517. for (sal_uInt16 tindex = 0; tindex < tlen; tindex++)
  518. {
  519. if (pCC->getCharacterType(aStr,tindex) &
  520. ::com::sun::star::i18n::KCharacterType::UPPER) nc++;
  521. }
  522. if (nc == 0)
  523. return (sal_uInt16) CAPTYPE_NOCAP;
  524. if (nc == tlen)
  525. return (sal_uInt16) CAPTYPE_ALLCAP;
  526. if ((nc == 1) && (pCC->getCharacterType(aStr,0) &
  527. ::com::sun::star::i18n::KCharacterType::UPPER))
  528. return (sal_uInt16) CAPTYPE_INITCAP;
  529. return (sal_uInt16) CAPTYPE_MIXED;
  530. }
  531. return (sal_uInt16) CAPTYPE_UNKNOWN;
  532. }
  533. OUString SAL_CALL Thesaurus::makeLowerCase(const OUString& aTerm, CharClass * pCC)
  534. {
  535. if (pCC)
  536. return pCC->lowercase(aTerm);
  537. return aTerm;
  538. }
  539. OUString SAL_CALL Thesaurus::makeUpperCase(const OUString& aTerm, CharClass * pCC)
  540. {
  541. if (pCC)
  542. return pCC->uppercase(aTerm);
  543. return aTerm;
  544. }
  545. OUString SAL_CALL Thesaurus::makeInitCap(const OUString& aTerm, CharClass * pCC)
  546. {
  547. sal_Int32 tlen = aTerm.getLength();
  548. if ((pCC) && (tlen))
  549. {
  550. OUString bTemp = aTerm.copy(0,1);
  551. if (tlen > 1)
  552. {
  553. return ( pCC->uppercase(bTemp, 0, 1)
  554. + pCC->lowercase(aTerm,1,(tlen-1)) );
  555. }
  556. return pCC->uppercase(bTemp, 0, 1);
  557. }
  558. return aTerm;
  559. }
  560. void SAL_CALL Thesaurus::dispose()
  561. throw(RuntimeException)
  562. {
  563. MutexGuard aGuard( GetLinguMutex() );
  564. if (!bDisposing)
  565. {
  566. bDisposing = true;
  567. EventObject aEvtObj( (XThesaurus *) this );
  568. aEvtListeners.disposeAndClear( aEvtObj );
  569. if (pPropHelper)
  570. {
  571. pPropHelper->RemoveAsPropListener();
  572. delete pPropHelper;
  573. pPropHelper = NULL;
  574. }
  575. }
  576. }
  577. void SAL_CALL Thesaurus::addEventListener( const Reference< XEventListener >& rxListener )
  578. throw(RuntimeException)
  579. {
  580. MutexGuard aGuard( GetLinguMutex() );
  581. if (!bDisposing && rxListener.is())
  582. aEvtListeners.addInterface( rxListener );
  583. }
  584. void SAL_CALL Thesaurus::removeEventListener( const Reference< XEventListener >& rxListener )
  585. throw(RuntimeException)
  586. {
  587. MutexGuard aGuard( GetLinguMutex() );
  588. if (!bDisposing && rxListener.is())
  589. aEvtListeners.removeInterface( rxListener );
  590. }
  591. ///////////////////////////////////////////////////////////////////////////
  592. // Service specific part
  593. //
  594. OUString SAL_CALL Thesaurus::getImplementationName()
  595. throw(RuntimeException)
  596. {
  597. MutexGuard aGuard( GetLinguMutex() );
  598. return getImplementationName_Static();
  599. }
  600. sal_Bool SAL_CALL Thesaurus::supportsService( const OUString& ServiceName )
  601. throw(RuntimeException)
  602. {
  603. MutexGuard aGuard( GetLinguMutex() );
  604. Sequence< OUString > aSNL = getSupportedServiceNames();
  605. const OUString * pArray = aSNL.getConstArray();
  606. for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
  607. if( pArray[i] == ServiceName )
  608. return sal_True;
  609. return sal_False;
  610. }
  611. Sequence< OUString > SAL_CALL Thesaurus::getSupportedServiceNames()
  612. throw(RuntimeException)
  613. {
  614. MutexGuard aGuard( GetLinguMutex() );
  615. return getSupportedServiceNames_Static();
  616. }
  617. Sequence< OUString > Thesaurus::getSupportedServiceNames_Static()
  618. throw()
  619. {
  620. MutexGuard aGuard( GetLinguMutex() );
  621. Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich
  622. aSNS.getArray()[0] = A2OU( SN_THESAURUS );
  623. return aSNS;
  624. }
  625. void * SAL_CALL Thesaurus_getFactory( const sal_Char * pImplName,
  626. XMultiServiceFactory * pServiceManager, void * )
  627. {
  628. void * pRet = 0;
  629. if ( !Thesaurus::getImplementationName_Static().compareToAscii( pImplName ) )
  630. {
  631. Reference< XSingleServiceFactory > xFactory =
  632. cppu::createOneInstanceFactory(
  633. pServiceManager,
  634. Thesaurus::getImplementationName_Static(),
  635. Thesaurus_CreateInstance,
  636. Thesaurus::getSupportedServiceNames_Static());
  637. // acquire, because we return an interface pointer instead of a reference
  638. xFactory->acquire();
  639. pRet = xFactory.get();
  640. }
  641. return pRet;
  642. }
  643. ///////////////////////////////////////////////////////////////////////////
  644. #undef CAPTYPE_UNKNOWN
  645. #undef CAPTYPE_NOCAP
  646. #undef CAPTYPE_INITCAP
  647. #undef CAPTYPE_ALLCAP
  648. #undef CAPTYPE_MIXED
  649. /* vim:set shiftwidth=4 softtabstop=4 expandtab: */