PageRenderTime 41ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/libreoffice-3.6.0.2/lingucomponent/source/thesaurus/libnth/nthesimp.cxx

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