1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 29*cdf0e10cSrcweir #include "precompiled_lingucomponent.hxx" 30*cdf0e10cSrcweir #include <com/sun/star/uno/Reference.h> 31*cdf0e10cSrcweir #include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp> 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir #include <com/sun/star/linguistic2/SpellFailure.hpp> 34*cdf0e10cSrcweir #include <cppuhelper/factory.hxx> // helper for factories 35*cdf0e10cSrcweir #include <com/sun/star/registry/XRegistryKey.hpp> 36*cdf0e10cSrcweir #include <tools/debug.hxx> 37*cdf0e10cSrcweir #include <unotools/processfactory.hxx> 38*cdf0e10cSrcweir #include <osl/mutex.hxx> 39*cdf0e10cSrcweir 40*cdf0e10cSrcweir //#include <hunspell.hxx> 41*cdf0e10cSrcweir #include <dictmgr.hxx> 42*cdf0e10cSrcweir #include <macspellimp.hxx> 43*cdf0e10cSrcweir 44*cdf0e10cSrcweir //#include <linguistic/lngprops.hxx> 45*cdf0e10cSrcweir #include <linguistic/spelldta.hxx> 46*cdf0e10cSrcweir #include <unotools/pathoptions.hxx> 47*cdf0e10cSrcweir #include <unotools/useroptions.hxx> 48*cdf0e10cSrcweir #include <osl/file.hxx> 49*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx> 50*cdf0e10cSrcweir 51*cdf0e10cSrcweir 52*cdf0e10cSrcweir using namespace utl; 53*cdf0e10cSrcweir using namespace osl; 54*cdf0e10cSrcweir using namespace rtl; 55*cdf0e10cSrcweir using namespace com::sun::star; 56*cdf0e10cSrcweir using namespace com::sun::star::beans; 57*cdf0e10cSrcweir using namespace com::sun::star::lang; 58*cdf0e10cSrcweir using namespace com::sun::star::uno; 59*cdf0e10cSrcweir using namespace com::sun::star::linguistic2; 60*cdf0e10cSrcweir using namespace linguistic; 61*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 62*cdf0e10cSrcweir // dbg_dump for development 63*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 64*cdf0e10cSrcweir #include <rtl/strbuf.hxx> 65*cdf0e10cSrcweir #include <rtl/ustring.hxx> 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir const sal_Char *dbg_dump(const rtl::OString &rStr) 68*cdf0e10cSrcweir { 69*cdf0e10cSrcweir static rtl::OStringBuffer aStr; 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir aStr = rtl::OStringBuffer(rStr); 72*cdf0e10cSrcweir aStr.append(static_cast<char>(0)); 73*cdf0e10cSrcweir return aStr.getStr(); 74*cdf0e10cSrcweir } 75*cdf0e10cSrcweir 76*cdf0e10cSrcweir const sal_Char *dbg_dump(const rtl::OUString &rStr) 77*cdf0e10cSrcweir { 78*cdf0e10cSrcweir return dbg_dump(rtl::OUStringToOString(rStr, RTL_TEXTENCODING_UTF8)); 79*cdf0e10cSrcweir } 80*cdf0e10cSrcweir 81*cdf0e10cSrcweir const sal_Char *dbg_dump(rtl_String *pStr) 82*cdf0e10cSrcweir { 83*cdf0e10cSrcweir return dbg_dump(rtl::OString(pStr)); 84*cdf0e10cSrcweir } 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir const sal_Char *dbg_dump(rtl_uString *pStr) 87*cdf0e10cSrcweir { 88*cdf0e10cSrcweir return dbg_dump(rtl::OUString(pStr)); 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir #endif 92*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 93*cdf0e10cSrcweir 94*cdf0e10cSrcweir MacSpellChecker::MacSpellChecker() : 95*cdf0e10cSrcweir aEvtListeners ( GetLinguMutex() ) 96*cdf0e10cSrcweir { 97*cdf0e10cSrcweir // aDicts = NULL; 98*cdf0e10cSrcweir aDEncs = NULL; 99*cdf0e10cSrcweir aDLocs = NULL; 100*cdf0e10cSrcweir aDNames = NULL; 101*cdf0e10cSrcweir bDisposing = sal_False; 102*cdf0e10cSrcweir pPropHelper = NULL; 103*cdf0e10cSrcweir numdict = 0; 104*cdf0e10cSrcweir NSApplicationLoad(); 105*cdf0e10cSrcweir NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 106*cdf0e10cSrcweir macSpell = [NSSpellChecker sharedSpellChecker]; 107*cdf0e10cSrcweir macTag = [NSSpellChecker uniqueSpellDocumentTag]; 108*cdf0e10cSrcweir [pool release]; 109*cdf0e10cSrcweir } 110*cdf0e10cSrcweir 111*cdf0e10cSrcweir 112*cdf0e10cSrcweir MacSpellChecker::~MacSpellChecker() 113*cdf0e10cSrcweir { 114*cdf0e10cSrcweir // if (aDicts) { 115*cdf0e10cSrcweir // for (int i = 0; i < numdict; i++) { 116*cdf0e10cSrcweir // if (aDicts[i]) delete aDicts[i]; 117*cdf0e10cSrcweir // aDicts[i] = NULL; 118*cdf0e10cSrcweir // } 119*cdf0e10cSrcweir // delete[] aDicts; 120*cdf0e10cSrcweir // } 121*cdf0e10cSrcweir // aDicts = NULL; 122*cdf0e10cSrcweir numdict = 0; 123*cdf0e10cSrcweir if (aDEncs) delete[] aDEncs; 124*cdf0e10cSrcweir aDEncs = NULL; 125*cdf0e10cSrcweir if (aDLocs) delete[] aDLocs; 126*cdf0e10cSrcweir aDLocs = NULL; 127*cdf0e10cSrcweir if (aDNames) delete[] aDNames; 128*cdf0e10cSrcweir aDNames = NULL; 129*cdf0e10cSrcweir if (pPropHelper) 130*cdf0e10cSrcweir pPropHelper->RemoveAsPropListener(); 131*cdf0e10cSrcweir } 132*cdf0e10cSrcweir 133*cdf0e10cSrcweir 134*cdf0e10cSrcweir PropertyHelper_Spell & MacSpellChecker::GetPropHelper_Impl() 135*cdf0e10cSrcweir { 136*cdf0e10cSrcweir if (!pPropHelper) 137*cdf0e10cSrcweir { 138*cdf0e10cSrcweir Reference< XPropertySet > xPropSet( GetLinguProperties(), UNO_QUERY ); 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir pPropHelper = new PropertyHelper_Spell( (XSpellChecker *) this, xPropSet ); 141*cdf0e10cSrcweir xPropHelper = pPropHelper; 142*cdf0e10cSrcweir pPropHelper->AddAsPropListener(); //! after a reference is established 143*cdf0e10cSrcweir } 144*cdf0e10cSrcweir return *pPropHelper; 145*cdf0e10cSrcweir } 146*cdf0e10cSrcweir 147*cdf0e10cSrcweir 148*cdf0e10cSrcweir Sequence< Locale > SAL_CALL MacSpellChecker::getLocales() 149*cdf0e10cSrcweir throw(RuntimeException) 150*cdf0e10cSrcweir { 151*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 152*cdf0e10cSrcweir 153*cdf0e10cSrcweir // this routine should return the locales supported by the installed 154*cdf0e10cSrcweir // dictionaries. So here we need to parse both the user edited 155*cdf0e10cSrcweir // dictionary list and the shared dictionary list 156*cdf0e10cSrcweir // to see what dictionaries the admin/user has installed 157*cdf0e10cSrcweir 158*cdf0e10cSrcweir int numusr; // number of user dictionary entries 159*cdf0e10cSrcweir int numshr; // number of shared dictionary entries 160*cdf0e10cSrcweir dictentry * spdict; // shared dict entry pointer 161*cdf0e10cSrcweir dictentry * updict; // user dict entry pointer 162*cdf0e10cSrcweir SvtPathOptions aPathOpt; 163*cdf0e10cSrcweir rtl_TextEncoding aEnc = RTL_TEXTENCODING_UTF8; 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir std::vector<objc_object *> postspdict; 166*cdf0e10cSrcweir //std::vector<dictentry *> postspdict; 167*cdf0e10cSrcweir std::vector<dictentry *> postupdict; 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir 170*cdf0e10cSrcweir if (!numdict) { 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir // invoke a dictionary manager to get the user dictionary list 173*cdf0e10cSrcweir // TODO How on Mac OS X? 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir // invoke a second dictionary manager to get the shared dictionary list 176*cdf0e10cSrcweir NSArray *aLocales = [NSLocale availableLocaleIdentifiers]; 177*cdf0e10cSrcweir 178*cdf0e10cSrcweir //Test for existence of the dictionaries 179*cdf0e10cSrcweir for (unsigned int i = 0; i < [aLocales count]; i++) 180*cdf0e10cSrcweir { 181*cdf0e10cSrcweir if( [macSpell setLanguage:[aLocales objectAtIndex:i] ] ) 182*cdf0e10cSrcweir { 183*cdf0e10cSrcweir postspdict.push_back( [ aLocales objectAtIndex:i ] ); 184*cdf0e10cSrcweir } 185*cdf0e10cSrcweir } 186*cdf0e10cSrcweir 187*cdf0e10cSrcweir numusr = postupdict.size(); 188*cdf0e10cSrcweir numshr = postspdict.size(); 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir // we really should merge these and remove duplicates but since 191*cdf0e10cSrcweir // users can name their dictionaries anything they want it would 192*cdf0e10cSrcweir // be impossible to know if a real duplication exists unless we 193*cdf0e10cSrcweir // add some unique key to each myspell dictionary 194*cdf0e10cSrcweir numdict = numshr + numusr; 195*cdf0e10cSrcweir 196*cdf0e10cSrcweir if (numdict) { 197*cdf0e10cSrcweir aDLocs = new Locale [numdict]; 198*cdf0e10cSrcweir aDEncs = new rtl_TextEncoding [numdict]; 199*cdf0e10cSrcweir aDNames = new OUString [numdict]; 200*cdf0e10cSrcweir aSuppLocales.realloc(numdict); 201*cdf0e10cSrcweir Locale * pLocale = aSuppLocales.getArray(); 202*cdf0e10cSrcweir int numlocs = 0; 203*cdf0e10cSrcweir int newloc; 204*cdf0e10cSrcweir int i,j; 205*cdf0e10cSrcweir int k = 0; 206*cdf0e10cSrcweir 207*cdf0e10cSrcweir //first add the user dictionaries 208*cdf0e10cSrcweir //TODO for MAC? 209*cdf0e10cSrcweir 210*cdf0e10cSrcweir // now add the shared dictionaries 211*cdf0e10cSrcweir for (i = 0; i < numshr; i++) { 212*cdf0e10cSrcweir NSDictionary *aLocDict = [ NSLocale componentsFromLocaleIdentifier:postspdict[i] ]; 213*cdf0e10cSrcweir NSString* aLang = [ aLocDict objectForKey:NSLocaleLanguageCode ]; 214*cdf0e10cSrcweir NSString* aCountry = [ aLocDict objectForKey:NSLocaleCountryCode ]; 215*cdf0e10cSrcweir OUString lang([aLang cStringUsingEncoding: NSUTF8StringEncoding], [aLang length], aEnc); 216*cdf0e10cSrcweir OUString country([ aCountry cStringUsingEncoding: NSUTF8StringEncoding], [aCountry length], aEnc); 217*cdf0e10cSrcweir Locale nLoc( lang, country, OUString() ); 218*cdf0e10cSrcweir newloc = 1; 219*cdf0e10cSrcweir //eliminate duplicates (is this needed for MacOS?) 220*cdf0e10cSrcweir for (j = 0; j < numlocs; j++) { 221*cdf0e10cSrcweir if (nLoc == pLocale[j]) newloc = 0; 222*cdf0e10cSrcweir } 223*cdf0e10cSrcweir if (newloc) { 224*cdf0e10cSrcweir pLocale[numlocs] = nLoc; 225*cdf0e10cSrcweir numlocs++; 226*cdf0e10cSrcweir } 227*cdf0e10cSrcweir aDLocs[k] = nLoc; 228*cdf0e10cSrcweir //pointer to Hunspell dictionary - not needed for MAC 229*cdf0e10cSrcweir //aDicts[k] = NULL; 230*cdf0e10cSrcweir aDEncs[k] = 0; 231*cdf0e10cSrcweir // Dictionary file names not valid for Mac Spell 232*cdf0e10cSrcweir //aDNames[k] = aPathOpt.GetLinguisticPath() + A2OU("/ooo/") + A2OU(postspdict[i]->filename); 233*cdf0e10cSrcweir k++; 234*cdf0e10cSrcweir } 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir aSuppLocales.realloc(numlocs); 237*cdf0e10cSrcweir 238*cdf0e10cSrcweir } else { 239*cdf0e10cSrcweir /* no dictionary.lst found so register no dictionaries */ 240*cdf0e10cSrcweir numdict = 0; 241*cdf0e10cSrcweir //aDicts = NULL; 242*cdf0e10cSrcweir aDEncs = NULL; 243*cdf0e10cSrcweir aDLocs = NULL; 244*cdf0e10cSrcweir aDNames = NULL; 245*cdf0e10cSrcweir aSuppLocales.realloc(0); 246*cdf0e10cSrcweir } 247*cdf0e10cSrcweir 248*cdf0e10cSrcweir /* de-allocation of memory is handled inside the DictMgr */ 249*cdf0e10cSrcweir updict = NULL; 250*cdf0e10cSrcweir spdict = NULL; 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir } 253*cdf0e10cSrcweir 254*cdf0e10cSrcweir return aSuppLocales; 255*cdf0e10cSrcweir } 256*cdf0e10cSrcweir 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir 259*cdf0e10cSrcweir sal_Bool SAL_CALL MacSpellChecker::hasLocale(const Locale& rLocale) 260*cdf0e10cSrcweir throw(RuntimeException) 261*cdf0e10cSrcweir { 262*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 263*cdf0e10cSrcweir 264*cdf0e10cSrcweir sal_Bool bRes = sal_False; 265*cdf0e10cSrcweir if (!aSuppLocales.getLength()) 266*cdf0e10cSrcweir getLocales(); 267*cdf0e10cSrcweir 268*cdf0e10cSrcweir sal_Int32 nLen = aSuppLocales.getLength(); 269*cdf0e10cSrcweir for (sal_Int32 i = 0; i < nLen; ++i) 270*cdf0e10cSrcweir { 271*cdf0e10cSrcweir const Locale *pLocale = aSuppLocales.getConstArray(); 272*cdf0e10cSrcweir if (rLocale == pLocale[i]) 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir bRes = sal_True; 275*cdf0e10cSrcweir break; 276*cdf0e10cSrcweir } 277*cdf0e10cSrcweir } 278*cdf0e10cSrcweir return bRes; 279*cdf0e10cSrcweir } 280*cdf0e10cSrcweir 281*cdf0e10cSrcweir 282*cdf0e10cSrcweir sal_Int16 MacSpellChecker::GetSpellFailure( const OUString &rWord, const Locale &rLocale ) 283*cdf0e10cSrcweir { 284*cdf0e10cSrcweir rtl_TextEncoding aEnc; 285*cdf0e10cSrcweir 286*cdf0e10cSrcweir // initialize a myspell object for each dictionary once 287*cdf0e10cSrcweir // (note: mutex is held higher up in isValid) 288*cdf0e10cSrcweir 289*cdf0e10cSrcweir 290*cdf0e10cSrcweir sal_Int16 nRes = -1; 291*cdf0e10cSrcweir 292*cdf0e10cSrcweir // first handle smart quotes both single and double 293*cdf0e10cSrcweir OUStringBuffer rBuf(rWord); 294*cdf0e10cSrcweir sal_Int32 n = rBuf.getLength(); 295*cdf0e10cSrcweir sal_Unicode c; 296*cdf0e10cSrcweir for (sal_Int32 ix=0; ix < n; ix++) { 297*cdf0e10cSrcweir c = rBuf.charAt(ix); 298*cdf0e10cSrcweir if ((c == 0x201C) || (c == 0x201D)) rBuf.setCharAt(ix,(sal_Unicode)0x0022); 299*cdf0e10cSrcweir if ((c == 0x2018) || (c == 0x2019)) rBuf.setCharAt(ix,(sal_Unicode)0x0027); 300*cdf0e10cSrcweir } 301*cdf0e10cSrcweir OUString nWord(rBuf.makeStringAndClear()); 302*cdf0e10cSrcweir 303*cdf0e10cSrcweir if (n) 304*cdf0e10cSrcweir { 305*cdf0e10cSrcweir aEnc = 0; 306*cdf0e10cSrcweir NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 307*cdf0e10cSrcweir NSString* aNSStr = [[NSString alloc] initWithCharacters: nWord.getStr() length: nWord.getLength()]; 308*cdf0e10cSrcweir NSString* aLang = [[NSString alloc] initWithCharacters: rLocale.Language.getStr() length: rLocale.Language.getLength()]; 309*cdf0e10cSrcweir if(rLocale.Country.getLength()>0) 310*cdf0e10cSrcweir { 311*cdf0e10cSrcweir NSString* aCountry = [[NSString alloc] initWithCharacters: rLocale.Country.getStr() length: rLocale.Country.getLength()]; 312*cdf0e10cSrcweir NSString* aTag = @"_"; 313*cdf0e10cSrcweir NSString* aTaggedCountry = [aTag stringByAppendingString:aCountry]; 314*cdf0e10cSrcweir [aLang autorelease]; 315*cdf0e10cSrcweir aLang = [aLang stringByAppendingString:aTaggedCountry]; 316*cdf0e10cSrcweir } 317*cdf0e10cSrcweir 318*cdf0e10cSrcweir int aCount; 319*cdf0e10cSrcweir NSRange range = [macSpell checkSpellingOfString:aNSStr startingAt:0 language:aLang wrap:sal_False inSpellDocumentWithTag:macTag wordCount:&aCount]; 320*cdf0e10cSrcweir int rVal = 0; 321*cdf0e10cSrcweir if(range.length>0) 322*cdf0e10cSrcweir { 323*cdf0e10cSrcweir rVal = -1; 324*cdf0e10cSrcweir } 325*cdf0e10cSrcweir else 326*cdf0e10cSrcweir { 327*cdf0e10cSrcweir rVal = 1; 328*cdf0e10cSrcweir } 329*cdf0e10cSrcweir [pool release]; 330*cdf0e10cSrcweir if (rVal != 1) 331*cdf0e10cSrcweir { 332*cdf0e10cSrcweir nRes = SpellFailure::SPELLING_ERROR; 333*cdf0e10cSrcweir } else { 334*cdf0e10cSrcweir return -1; 335*cdf0e10cSrcweir } 336*cdf0e10cSrcweir } 337*cdf0e10cSrcweir return nRes; 338*cdf0e10cSrcweir } 339*cdf0e10cSrcweir 340*cdf0e10cSrcweir 341*cdf0e10cSrcweir 342*cdf0e10cSrcweir sal_Bool SAL_CALL 343*cdf0e10cSrcweir MacSpellChecker::isValid( const OUString& rWord, const Locale& rLocale, 344*cdf0e10cSrcweir const PropertyValues& rProperties ) 345*cdf0e10cSrcweir throw(IllegalArgumentException, RuntimeException) 346*cdf0e10cSrcweir { 347*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 348*cdf0e10cSrcweir 349*cdf0e10cSrcweir if (rLocale == Locale() || !rWord.getLength()) 350*cdf0e10cSrcweir return sal_True; 351*cdf0e10cSrcweir 352*cdf0e10cSrcweir if (!hasLocale( rLocale )) 353*cdf0e10cSrcweir #ifdef LINGU_EXCEPTIONS 354*cdf0e10cSrcweir throw( IllegalArgumentException() ); 355*cdf0e10cSrcweir #else 356*cdf0e10cSrcweir return sal_True; 357*cdf0e10cSrcweir #endif 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir // Get property values to be used. 360*cdf0e10cSrcweir // These are be the default values set in the SN_LINGU_PROPERTIES 361*cdf0e10cSrcweir // PropertySet which are overridden by the supplied ones from the 362*cdf0e10cSrcweir // last argument. 363*cdf0e10cSrcweir // You'll probably like to use a simplier solution than the provided 364*cdf0e10cSrcweir // one using the PropertyHelper_Spell. 365*cdf0e10cSrcweir 366*cdf0e10cSrcweir PropertyHelper_Spell &rHelper = GetPropHelper(); 367*cdf0e10cSrcweir rHelper.SetTmpPropVals( rProperties ); 368*cdf0e10cSrcweir 369*cdf0e10cSrcweir sal_Int16 nFailure = GetSpellFailure( rWord, rLocale ); 370*cdf0e10cSrcweir if (nFailure != -1) 371*cdf0e10cSrcweir { 372*cdf0e10cSrcweir sal_Int16 nLang = LocaleToLanguage( rLocale ); 373*cdf0e10cSrcweir // postprocess result for errors that should be ignored 374*cdf0e10cSrcweir if ( (!rHelper.IsSpellUpperCase() && IsUpper( rWord, nLang )) 375*cdf0e10cSrcweir || (!rHelper.IsSpellWithDigits() && HasDigits( rWord )) 376*cdf0e10cSrcweir || (!rHelper.IsSpellCapitalization() 377*cdf0e10cSrcweir && nFailure == SpellFailure::CAPTION_ERROR) 378*cdf0e10cSrcweir ) 379*cdf0e10cSrcweir nFailure = -1; 380*cdf0e10cSrcweir } 381*cdf0e10cSrcweir 382*cdf0e10cSrcweir return (nFailure == -1); 383*cdf0e10cSrcweir } 384*cdf0e10cSrcweir 385*cdf0e10cSrcweir 386*cdf0e10cSrcweir Reference< XSpellAlternatives > 387*cdf0e10cSrcweir MacSpellChecker::GetProposals( const OUString &rWord, const Locale &rLocale ) 388*cdf0e10cSrcweir { 389*cdf0e10cSrcweir // Retrieves the return values for the 'spell' function call in case 390*cdf0e10cSrcweir // of a misspelled word. 391*cdf0e10cSrcweir // Especially it may give a list of suggested (correct) words: 392*cdf0e10cSrcweir 393*cdf0e10cSrcweir Reference< XSpellAlternatives > xRes; 394*cdf0e10cSrcweir // note: mutex is held by higher up by spell which covers both 395*cdf0e10cSrcweir 396*cdf0e10cSrcweir sal_Int16 nLang = LocaleToLanguage( rLocale ); 397*cdf0e10cSrcweir int count; 398*cdf0e10cSrcweir Sequence< OUString > aStr( 0 ); 399*cdf0e10cSrcweir 400*cdf0e10cSrcweir // first handle smart quotes (single and double) 401*cdf0e10cSrcweir OUStringBuffer rBuf(rWord); 402*cdf0e10cSrcweir sal_Int32 n = rBuf.getLength(); 403*cdf0e10cSrcweir sal_Unicode c; 404*cdf0e10cSrcweir for (sal_Int32 ix=0; ix < n; ix++) { 405*cdf0e10cSrcweir c = rBuf.charAt(ix); 406*cdf0e10cSrcweir if ((c == 0x201C) || (c == 0x201D)) rBuf.setCharAt(ix,(sal_Unicode)0x0022); 407*cdf0e10cSrcweir if ((c == 0x2018) || (c == 0x2019)) rBuf.setCharAt(ix,(sal_Unicode)0x0027); 408*cdf0e10cSrcweir } 409*cdf0e10cSrcweir OUString nWord(rBuf.makeStringAndClear()); 410*cdf0e10cSrcweir 411*cdf0e10cSrcweir if (n) 412*cdf0e10cSrcweir { 413*cdf0e10cSrcweir NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 414*cdf0e10cSrcweir NSString* aNSStr = [[NSString alloc] initWithCharacters: nWord.getStr() length: nWord.getLength()]; 415*cdf0e10cSrcweir NSString* aLang = [[NSString alloc] initWithCharacters: rLocale.Language.getStr() length: rLocale.Language.getLength() ]; 416*cdf0e10cSrcweir if(rLocale.Country.getLength()>0) 417*cdf0e10cSrcweir { 418*cdf0e10cSrcweir NSString* aCountry = [[NSString alloc] initWithCharacters: rLocale.Country.getStr() length: rLocale.Country.getLength() ]; 419*cdf0e10cSrcweir NSString* aTag = @"_"; 420*cdf0e10cSrcweir NSString* aTaggedCountry = [aTag stringByAppendingString:aCountry]; 421*cdf0e10cSrcweir [aLang autorelease]; 422*cdf0e10cSrcweir aLang = [aLang stringByAppendingString:aTaggedCountry]; 423*cdf0e10cSrcweir } 424*cdf0e10cSrcweir [macSpell setLanguage:aLang]; 425*cdf0e10cSrcweir NSArray *guesses = [macSpell guessesForWord:aNSStr]; 426*cdf0e10cSrcweir count = [guesses count]; 427*cdf0e10cSrcweir if (count) 428*cdf0e10cSrcweir { 429*cdf0e10cSrcweir aStr.realloc( count ); 430*cdf0e10cSrcweir OUString *pStr = aStr.getArray(); 431*cdf0e10cSrcweir for (int ii=0; ii < count; ii++) 432*cdf0e10cSrcweir { 433*cdf0e10cSrcweir // if needed add: if (suglst[ii] == NULL) continue; 434*cdf0e10cSrcweir NSString* guess = [guesses objectAtIndex:ii]; 435*cdf0e10cSrcweir OUString cvtwrd((const sal_Unicode*)[guess cStringUsingEncoding:NSUnicodeStringEncoding], (sal_Int32)[guess length]); 436*cdf0e10cSrcweir pStr[ii] = cvtwrd; 437*cdf0e10cSrcweir } 438*cdf0e10cSrcweir } 439*cdf0e10cSrcweir [pool release]; 440*cdf0e10cSrcweir } 441*cdf0e10cSrcweir 442*cdf0e10cSrcweir // now return an empty alternative for no suggestions or the list of alternatives if some found 443*cdf0e10cSrcweir SpellAlternatives *pAlt = new SpellAlternatives; 444*cdf0e10cSrcweir String aTmp(rWord); 445*cdf0e10cSrcweir pAlt->SetWordLanguage( aTmp, nLang ); 446*cdf0e10cSrcweir pAlt->SetFailureType( SpellFailure::SPELLING_ERROR ); 447*cdf0e10cSrcweir pAlt->SetAlternatives( aStr ); 448*cdf0e10cSrcweir xRes = pAlt; 449*cdf0e10cSrcweir return xRes; 450*cdf0e10cSrcweir 451*cdf0e10cSrcweir } 452*cdf0e10cSrcweir 453*cdf0e10cSrcweir 454*cdf0e10cSrcweir 455*cdf0e10cSrcweir 456*cdf0e10cSrcweir Reference< XSpellAlternatives > SAL_CALL 457*cdf0e10cSrcweir MacSpellChecker::spell( const OUString& rWord, const Locale& rLocale, 458*cdf0e10cSrcweir const PropertyValues& rProperties ) 459*cdf0e10cSrcweir throw(IllegalArgumentException, RuntimeException) 460*cdf0e10cSrcweir { 461*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 462*cdf0e10cSrcweir 463*cdf0e10cSrcweir if (rLocale == Locale() || !rWord.getLength()) 464*cdf0e10cSrcweir return NULL; 465*cdf0e10cSrcweir 466*cdf0e10cSrcweir if (!hasLocale( rLocale )) 467*cdf0e10cSrcweir #ifdef LINGU_EXCEPTIONS 468*cdf0e10cSrcweir throw( IllegalArgumentException() ); 469*cdf0e10cSrcweir #else 470*cdf0e10cSrcweir return NULL; 471*cdf0e10cSrcweir #endif 472*cdf0e10cSrcweir 473*cdf0e10cSrcweir Reference< XSpellAlternatives > xAlt; 474*cdf0e10cSrcweir if (!isValid( rWord, rLocale, rProperties )) 475*cdf0e10cSrcweir { 476*cdf0e10cSrcweir xAlt = GetProposals( rWord, rLocale ); 477*cdf0e10cSrcweir } 478*cdf0e10cSrcweir return xAlt; 479*cdf0e10cSrcweir } 480*cdf0e10cSrcweir 481*cdf0e10cSrcweir 482*cdf0e10cSrcweir Reference< XInterface > SAL_CALL MacSpellChecker_CreateInstance( 483*cdf0e10cSrcweir const Reference< XMultiServiceFactory > & /*rSMgr*/ ) 484*cdf0e10cSrcweir throw(Exception) 485*cdf0e10cSrcweir { 486*cdf0e10cSrcweir 487*cdf0e10cSrcweir Reference< XInterface > xService = (cppu::OWeakObject*) new MacSpellChecker; 488*cdf0e10cSrcweir return xService; 489*cdf0e10cSrcweir } 490*cdf0e10cSrcweir 491*cdf0e10cSrcweir 492*cdf0e10cSrcweir sal_Bool SAL_CALL 493*cdf0e10cSrcweir MacSpellChecker::addLinguServiceEventListener( 494*cdf0e10cSrcweir const Reference< XLinguServiceEventListener >& rxLstnr ) 495*cdf0e10cSrcweir throw(RuntimeException) 496*cdf0e10cSrcweir { 497*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 498*cdf0e10cSrcweir 499*cdf0e10cSrcweir sal_Bool bRes = sal_False; 500*cdf0e10cSrcweir if (!bDisposing && rxLstnr.is()) 501*cdf0e10cSrcweir { 502*cdf0e10cSrcweir bRes = GetPropHelper().addLinguServiceEventListener( rxLstnr ); 503*cdf0e10cSrcweir } 504*cdf0e10cSrcweir return bRes; 505*cdf0e10cSrcweir } 506*cdf0e10cSrcweir 507*cdf0e10cSrcweir 508*cdf0e10cSrcweir sal_Bool SAL_CALL 509*cdf0e10cSrcweir MacSpellChecker::removeLinguServiceEventListener( 510*cdf0e10cSrcweir const Reference< XLinguServiceEventListener >& rxLstnr ) 511*cdf0e10cSrcweir throw(RuntimeException) 512*cdf0e10cSrcweir { 513*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 514*cdf0e10cSrcweir 515*cdf0e10cSrcweir sal_Bool bRes = sal_False; 516*cdf0e10cSrcweir if (!bDisposing && rxLstnr.is()) 517*cdf0e10cSrcweir { 518*cdf0e10cSrcweir DBG_ASSERT( xPropHelper.is(), "xPropHelper non existent" ); 519*cdf0e10cSrcweir bRes = GetPropHelper().removeLinguServiceEventListener( rxLstnr ); 520*cdf0e10cSrcweir } 521*cdf0e10cSrcweir return bRes; 522*cdf0e10cSrcweir } 523*cdf0e10cSrcweir 524*cdf0e10cSrcweir 525*cdf0e10cSrcweir OUString SAL_CALL 526*cdf0e10cSrcweir MacSpellChecker::getServiceDisplayName( const Locale& /*rLocale*/ ) 527*cdf0e10cSrcweir throw(RuntimeException) 528*cdf0e10cSrcweir { 529*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 530*cdf0e10cSrcweir return A2OU( "Mac OS X Spell Checker" ); 531*cdf0e10cSrcweir } 532*cdf0e10cSrcweir 533*cdf0e10cSrcweir 534*cdf0e10cSrcweir void SAL_CALL 535*cdf0e10cSrcweir MacSpellChecker::initialize( const Sequence< Any >& rArguments ) 536*cdf0e10cSrcweir throw(Exception, RuntimeException) 537*cdf0e10cSrcweir { 538*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 539*cdf0e10cSrcweir 540*cdf0e10cSrcweir if (!pPropHelper) 541*cdf0e10cSrcweir { 542*cdf0e10cSrcweir sal_Int32 nLen = rArguments.getLength(); 543*cdf0e10cSrcweir if (2 == nLen) 544*cdf0e10cSrcweir { 545*cdf0e10cSrcweir Reference< XPropertySet > xPropSet; 546*cdf0e10cSrcweir rArguments.getConstArray()[0] >>= xPropSet; 547*cdf0e10cSrcweir //rArguments.getConstArray()[1] >>= xDicList; 548*cdf0e10cSrcweir 549*cdf0e10cSrcweir //! Pointer allows for access of the non-UNO functions. 550*cdf0e10cSrcweir //! And the reference to the UNO-functions while increasing 551*cdf0e10cSrcweir //! the ref-count and will implicitly free the memory 552*cdf0e10cSrcweir //! when the object is not longer used. 553*cdf0e10cSrcweir pPropHelper = new PropertyHelper_Spell( (XSpellChecker *) this, xPropSet ); 554*cdf0e10cSrcweir xPropHelper = pPropHelper; 555*cdf0e10cSrcweir pPropHelper->AddAsPropListener(); //! after a reference is established 556*cdf0e10cSrcweir } 557*cdf0e10cSrcweir else 558*cdf0e10cSrcweir DBG_ERROR( "wrong number of arguments in sequence" ); 559*cdf0e10cSrcweir 560*cdf0e10cSrcweir } 561*cdf0e10cSrcweir } 562*cdf0e10cSrcweir 563*cdf0e10cSrcweir 564*cdf0e10cSrcweir void SAL_CALL 565*cdf0e10cSrcweir MacSpellChecker::dispose() 566*cdf0e10cSrcweir throw(RuntimeException) 567*cdf0e10cSrcweir { 568*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 569*cdf0e10cSrcweir 570*cdf0e10cSrcweir if (!bDisposing) 571*cdf0e10cSrcweir { 572*cdf0e10cSrcweir bDisposing = sal_True; 573*cdf0e10cSrcweir EventObject aEvtObj( (XSpellChecker *) this ); 574*cdf0e10cSrcweir aEvtListeners.disposeAndClear( aEvtObj ); 575*cdf0e10cSrcweir } 576*cdf0e10cSrcweir } 577*cdf0e10cSrcweir 578*cdf0e10cSrcweir 579*cdf0e10cSrcweir void SAL_CALL 580*cdf0e10cSrcweir MacSpellChecker::addEventListener( const Reference< XEventListener >& rxListener ) 581*cdf0e10cSrcweir throw(RuntimeException) 582*cdf0e10cSrcweir { 583*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 584*cdf0e10cSrcweir 585*cdf0e10cSrcweir if (!bDisposing && rxListener.is()) 586*cdf0e10cSrcweir aEvtListeners.addInterface( rxListener ); 587*cdf0e10cSrcweir } 588*cdf0e10cSrcweir 589*cdf0e10cSrcweir 590*cdf0e10cSrcweir void SAL_CALL 591*cdf0e10cSrcweir MacSpellChecker::removeEventListener( const Reference< XEventListener >& rxListener ) 592*cdf0e10cSrcweir throw(RuntimeException) 593*cdf0e10cSrcweir { 594*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 595*cdf0e10cSrcweir 596*cdf0e10cSrcweir if (!bDisposing && rxListener.is()) 597*cdf0e10cSrcweir aEvtListeners.removeInterface( rxListener ); 598*cdf0e10cSrcweir } 599*cdf0e10cSrcweir 600*cdf0e10cSrcweir 601*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 602*cdf0e10cSrcweir // Service specific part 603*cdf0e10cSrcweir // 604*cdf0e10cSrcweir 605*cdf0e10cSrcweir OUString SAL_CALL MacSpellChecker::getImplementationName() 606*cdf0e10cSrcweir throw(RuntimeException) 607*cdf0e10cSrcweir { 608*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 609*cdf0e10cSrcweir 610*cdf0e10cSrcweir return getImplementationName_Static(); 611*cdf0e10cSrcweir } 612*cdf0e10cSrcweir 613*cdf0e10cSrcweir 614*cdf0e10cSrcweir sal_Bool SAL_CALL MacSpellChecker::supportsService( const OUString& ServiceName ) 615*cdf0e10cSrcweir throw(RuntimeException) 616*cdf0e10cSrcweir { 617*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 618*cdf0e10cSrcweir 619*cdf0e10cSrcweir Sequence< OUString > aSNL = getSupportedServiceNames(); 620*cdf0e10cSrcweir const OUString * pArray = aSNL.getConstArray(); 621*cdf0e10cSrcweir for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) 622*cdf0e10cSrcweir if( pArray[i] == ServiceName ) 623*cdf0e10cSrcweir return sal_True; 624*cdf0e10cSrcweir return sal_False; 625*cdf0e10cSrcweir } 626*cdf0e10cSrcweir 627*cdf0e10cSrcweir 628*cdf0e10cSrcweir Sequence< OUString > SAL_CALL MacSpellChecker::getSupportedServiceNames() 629*cdf0e10cSrcweir throw(RuntimeException) 630*cdf0e10cSrcweir { 631*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 632*cdf0e10cSrcweir 633*cdf0e10cSrcweir return getSupportedServiceNames_Static(); 634*cdf0e10cSrcweir } 635*cdf0e10cSrcweir 636*cdf0e10cSrcweir 637*cdf0e10cSrcweir Sequence< OUString > MacSpellChecker::getSupportedServiceNames_Static() 638*cdf0e10cSrcweir throw() 639*cdf0e10cSrcweir { 640*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 641*cdf0e10cSrcweir 642*cdf0e10cSrcweir Sequence< OUString > aSNS( 1 ); // auch mehr als 1 Service moeglich 643*cdf0e10cSrcweir aSNS.getArray()[0] = A2OU( SN_SPELLCHECKER ); 644*cdf0e10cSrcweir return aSNS; 645*cdf0e10cSrcweir } 646*cdf0e10cSrcweir 647*cdf0e10cSrcweir void * SAL_CALL MacSpellChecker_getFactory( const sal_Char * pImplName, 648*cdf0e10cSrcweir XMultiServiceFactory * pServiceManager, void * ) 649*cdf0e10cSrcweir { 650*cdf0e10cSrcweir void * pRet = 0; 651*cdf0e10cSrcweir if ( !MacSpellChecker::getImplementationName_Static().compareToAscii( pImplName ) ) 652*cdf0e10cSrcweir { 653*cdf0e10cSrcweir Reference< XSingleServiceFactory > xFactory = 654*cdf0e10cSrcweir cppu::createOneInstanceFactory( 655*cdf0e10cSrcweir pServiceManager, 656*cdf0e10cSrcweir MacSpellChecker::getImplementationName_Static(), 657*cdf0e10cSrcweir MacSpellChecker_CreateInstance, 658*cdf0e10cSrcweir MacSpellChecker::getSupportedServiceNames_Static()); 659*cdf0e10cSrcweir // acquire, because we return an interface pointer instead of a reference 660*cdf0e10cSrcweir xFactory->acquire(); 661*cdf0e10cSrcweir pRet = xFactory.get(); 662*cdf0e10cSrcweir } 663*cdf0e10cSrcweir return pRet; 664*cdf0e10cSrcweir } 665*cdf0e10cSrcweir 666*cdf0e10cSrcweir 667*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 668