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_linguistic.hxx" 30*cdf0e10cSrcweir 31*cdf0e10cSrcweir #include <cppuhelper/factory.hxx> 32*cdf0e10cSrcweir #include <i18npool/lang.h> 33*cdf0e10cSrcweir #include <osl/mutex.hxx> 34*cdf0e10cSrcweir #include <tools/debug.hxx> 35*cdf0e10cSrcweir #include <tools/fsys.hxx> 36*cdf0e10cSrcweir #include <tools/stream.hxx> 37*cdf0e10cSrcweir #include <tools/stream.hxx> 38*cdf0e10cSrcweir #include <tools/string.hxx> 39*cdf0e10cSrcweir #include <tools/urlobj.hxx> 40*cdf0e10cSrcweir #include <ucbhelper/content.hxx> 41*cdf0e10cSrcweir #include <unotools/processfactory.hxx> 42*cdf0e10cSrcweir #include <unotools/streamwrap.hxx> 43*cdf0e10cSrcweir #include <unotools/ucbstreamhelper.hxx> 44*cdf0e10cSrcweir 45*cdf0e10cSrcweir #include <com/sun/star/linguistic2/XConversionDictionary.hpp> 46*cdf0e10cSrcweir #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp> 47*cdf0e10cSrcweir #include <com/sun/star/linguistic2/XConversionPropertyType.hpp> 48*cdf0e10cSrcweir #include <com/sun/star/linguistic2/ConversionPropertyType.hpp> 49*cdf0e10cSrcweir #include <com/sun/star/util/XFlushable.hpp> 50*cdf0e10cSrcweir #include <com/sun/star/lang/Locale.hpp> 51*cdf0e10cSrcweir #include <com/sun/star/lang/EventObject.hpp> 52*cdf0e10cSrcweir #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 53*cdf0e10cSrcweir #include <com/sun/star/uno/Reference.h> 54*cdf0e10cSrcweir #include <com/sun/star/registry/XRegistryKey.hpp> 55*cdf0e10cSrcweir #include <com/sun/star/util/XFlushListener.hpp> 56*cdf0e10cSrcweir #include <com/sun/star/io/XActiveDataSource.hpp> 57*cdf0e10cSrcweir #include <com/sun/star/io/XActiveDataSource.hpp> 58*cdf0e10cSrcweir #include <com/sun/star/io/XInputStream.hpp> 59*cdf0e10cSrcweir #include <com/sun/star/io/XOutputStream.hpp> 60*cdf0e10cSrcweir #include <com/sun/star/xml/sax/XDocumentHandler.hpp> 61*cdf0e10cSrcweir #include <com/sun/star/document/XFilter.hpp> 62*cdf0e10cSrcweir #include <com/sun/star/beans/PropertyValue.hpp> 63*cdf0e10cSrcweir #include <com/sun/star/xml/sax/InputSource.hpp> 64*cdf0e10cSrcweir #include <com/sun/star/xml/sax/XParser.hpp> 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir 67*cdf0e10cSrcweir #include "convdic.hxx" 68*cdf0e10cSrcweir #include "convdicxml.hxx" 69*cdf0e10cSrcweir #include "linguistic/misc.hxx" 70*cdf0e10cSrcweir #include "defs.hxx" 71*cdf0e10cSrcweir 72*cdf0e10cSrcweir using namespace std; 73*cdf0e10cSrcweir using namespace utl; 74*cdf0e10cSrcweir using namespace osl; 75*cdf0e10cSrcweir using namespace rtl; 76*cdf0e10cSrcweir using namespace com::sun::star; 77*cdf0e10cSrcweir using namespace com::sun::star::lang; 78*cdf0e10cSrcweir using namespace com::sun::star::uno; 79*cdf0e10cSrcweir using namespace com::sun::star::linguistic2; 80*cdf0e10cSrcweir using namespace linguistic; 81*cdf0e10cSrcweir 82*cdf0e10cSrcweir #define SN_CONV_DICTIONARY "com.sun.star.linguistic2.ConversionDictionary" 83*cdf0e10cSrcweir #define SN_HCD_CONV_DICTIONARY "com.sun.star.linguistic2.HangulHanjaConversionDictionary" 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir 86*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 87*cdf0e10cSrcweir void ReadThroughDic( const String &rMainURL, ConvDicXMLImport &rImport ) 88*cdf0e10cSrcweir { 89*cdf0e10cSrcweir if (rMainURL.Len() == 0) 90*cdf0e10cSrcweir return; 91*cdf0e10cSrcweir DBG_ASSERT(!INetURLObject( rMainURL ).HasError(), "invalid URL"); 92*cdf0e10cSrcweir 93*cdf0e10cSrcweir uno::Reference< lang::XMultiServiceFactory > xServiceFactory( utl::getProcessServiceFactory() ); 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir // get xInputStream stream 96*cdf0e10cSrcweir uno::Reference< io::XInputStream > xIn; 97*cdf0e10cSrcweir try 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir uno::Reference< ucb::XSimpleFileAccess > xAccess( xServiceFactory->createInstance( 100*cdf0e10cSrcweir A2OU( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY_THROW ); 101*cdf0e10cSrcweir xIn = xAccess->openFileRead( rMainURL ); 102*cdf0e10cSrcweir } 103*cdf0e10cSrcweir catch (uno::Exception & e) 104*cdf0e10cSrcweir { 105*cdf0e10cSrcweir DBG_ASSERT( 0, "failed to get input stream" ); 106*cdf0e10cSrcweir (void) e; 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir if (!xIn.is()) 109*cdf0e10cSrcweir return; 110*cdf0e10cSrcweir 111*cdf0e10cSrcweir SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xIn ) ); 112*cdf0e10cSrcweir 113*cdf0e10cSrcweir sal_uLong nError = sal::static_int_cast< sal_uLong >(-1); 114*cdf0e10cSrcweir 115*cdf0e10cSrcweir // prepare ParserInputSource 116*cdf0e10cSrcweir xml::sax::InputSource aParserInput; 117*cdf0e10cSrcweir aParserInput.aInputStream = xIn; 118*cdf0e10cSrcweir 119*cdf0e10cSrcweir // get parser 120*cdf0e10cSrcweir uno::Reference< xml::sax::XParser > xParser; 121*cdf0e10cSrcweir try 122*cdf0e10cSrcweir { 123*cdf0e10cSrcweir xParser = uno::Reference< xml::sax::XParser >( xServiceFactory->createInstance( 124*cdf0e10cSrcweir A2OU( "com.sun.star.xml.sax.Parser" ) ), UNO_QUERY ); 125*cdf0e10cSrcweir } 126*cdf0e10cSrcweir catch (uno::Exception &) 127*cdf0e10cSrcweir { 128*cdf0e10cSrcweir } 129*cdf0e10cSrcweir DBG_ASSERT( xParser.is(), "Can't create parser" ); 130*cdf0e10cSrcweir if (!xParser.is()) 131*cdf0e10cSrcweir return; 132*cdf0e10cSrcweir 133*cdf0e10cSrcweir // get filter 134*cdf0e10cSrcweir //ConvDicXMLImport *pImport = new ConvDicXMLImport( this, rMainURL ); 135*cdf0e10cSrcweir //!! keep a reference until everything is done to 136*cdf0e10cSrcweir //!! ensure the proper lifetime of the object 137*cdf0e10cSrcweir uno::Reference < xml::sax::XDocumentHandler > xFilter( 138*cdf0e10cSrcweir (xml::sax::XExtendedDocumentHandler *) &rImport, UNO_QUERY ); 139*cdf0e10cSrcweir 140*cdf0e10cSrcweir // connect parser and filter 141*cdf0e10cSrcweir xParser->setDocumentHandler( xFilter ); 142*cdf0e10cSrcweir 143*cdf0e10cSrcweir // finally, parser the stream 144*cdf0e10cSrcweir try 145*cdf0e10cSrcweir { 146*cdf0e10cSrcweir xParser->parseStream( aParserInput ); // implicitly calls ConvDicXMLImport::CreateContext 147*cdf0e10cSrcweir if (rImport.GetSuccess()) 148*cdf0e10cSrcweir nError = 0; 149*cdf0e10cSrcweir } 150*cdf0e10cSrcweir catch( xml::sax::SAXParseException& ) 151*cdf0e10cSrcweir { 152*cdf0e10cSrcweir // if( bEncrypted ) 153*cdf0e10cSrcweir // nError = ERRCODE_SFX_WRONGPASSWORD; 154*cdf0e10cSrcweir } 155*cdf0e10cSrcweir catch( xml::sax::SAXException& ) 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir // if( bEncrypted ) 158*cdf0e10cSrcweir // nError = ERRCODE_SFX_WRONGPASSWORD; 159*cdf0e10cSrcweir } 160*cdf0e10cSrcweir catch( io::IOException& ) 161*cdf0e10cSrcweir { 162*cdf0e10cSrcweir } 163*cdf0e10cSrcweir } 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir sal_Bool IsConvDic( const String &rFileURL, sal_Int16 &nLang, sal_Int16 &nConvType ) 166*cdf0e10cSrcweir { 167*cdf0e10cSrcweir sal_Bool bRes = sal_False; 168*cdf0e10cSrcweir 169*cdf0e10cSrcweir if (rFileURL.Len() == 0) 170*cdf0e10cSrcweir return bRes; 171*cdf0e10cSrcweir 172*cdf0e10cSrcweir // check if file extension matches CONV_DIC_EXT 173*cdf0e10cSrcweir String aExt; 174*cdf0e10cSrcweir xub_StrLen nPos = rFileURL.SearchBackward( '.' ); 175*cdf0e10cSrcweir if (STRING_NOTFOUND != nPos) 176*cdf0e10cSrcweir aExt = rFileURL.Copy( nPos + 1 ); 177*cdf0e10cSrcweir aExt.ToLowerAscii(); 178*cdf0e10cSrcweir if (!aExt.EqualsAscii( CONV_DIC_EXT )) 179*cdf0e10cSrcweir return bRes; 180*cdf0e10cSrcweir 181*cdf0e10cSrcweir // first argument being 0 should stop the file from being parsed 182*cdf0e10cSrcweir // up to the end (reading all entries) when the required 183*cdf0e10cSrcweir // data (language, conversion type) is found. 184*cdf0e10cSrcweir ConvDicXMLImport *pImport = new ConvDicXMLImport( 0, rFileURL ); 185*cdf0e10cSrcweir 186*cdf0e10cSrcweir //!! keep a first reference to ensure the lifetime of the object !! 187*cdf0e10cSrcweir uno::Reference< XInterface > xRef( (document::XFilter *) pImport, UNO_QUERY ); 188*cdf0e10cSrcweir 189*cdf0e10cSrcweir ReadThroughDic( rFileURL, *pImport ); // will implicitly add the entries 190*cdf0e10cSrcweir bRes = pImport->GetLanguage() != LANGUAGE_NONE && 191*cdf0e10cSrcweir pImport->GetConversionType() != -1; 192*cdf0e10cSrcweir DBG_ASSERT( bRes, "conversion dictionary corrupted?" ); 193*cdf0e10cSrcweir 194*cdf0e10cSrcweir if (bRes) 195*cdf0e10cSrcweir { 196*cdf0e10cSrcweir nLang = pImport->GetLanguage(); 197*cdf0e10cSrcweir nConvType = pImport->GetConversionType(); 198*cdf0e10cSrcweir } 199*cdf0e10cSrcweir 200*cdf0e10cSrcweir return bRes; 201*cdf0e10cSrcweir } 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir 204*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir ConvDic::ConvDic( 207*cdf0e10cSrcweir const String &rName, 208*cdf0e10cSrcweir sal_Int16 nLang, 209*cdf0e10cSrcweir sal_Int16 nConvType, 210*cdf0e10cSrcweir sal_Bool bBiDirectional, 211*cdf0e10cSrcweir const String &rMainURL) : 212*cdf0e10cSrcweir aFlushListeners( GetLinguMutex() ) 213*cdf0e10cSrcweir { 214*cdf0e10cSrcweir aName = rName; 215*cdf0e10cSrcweir nLanguage = nLang; 216*cdf0e10cSrcweir nConversionType = nConvType; 217*cdf0e10cSrcweir aMainURL = rMainURL; 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir if (bBiDirectional) 220*cdf0e10cSrcweir pFromRight = std::auto_ptr< ConvMap >( new ConvMap ); 221*cdf0e10cSrcweir if (nLang == LANGUAGE_CHINESE_SIMPLIFIED || nLang == LANGUAGE_CHINESE_TRADITIONAL) 222*cdf0e10cSrcweir pConvPropType = std::auto_ptr< PropTypeMap >( new PropTypeMap ); 223*cdf0e10cSrcweir 224*cdf0e10cSrcweir nMaxLeftCharCount = nMaxRightCharCount = 0; 225*cdf0e10cSrcweir bMaxCharCountIsValid = sal_True; 226*cdf0e10cSrcweir 227*cdf0e10cSrcweir bNeedEntries = sal_True; 228*cdf0e10cSrcweir bIsModified = bIsActive = sal_False; 229*cdf0e10cSrcweir bIsReadonly = sal_False; 230*cdf0e10cSrcweir 231*cdf0e10cSrcweir if( rMainURL.Len() > 0 ) 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir sal_Bool bExists = sal_False; 234*cdf0e10cSrcweir bIsReadonly = IsReadOnly( rMainURL, &bExists ); 235*cdf0e10cSrcweir 236*cdf0e10cSrcweir if( !bExists ) // new empty dictionary 237*cdf0e10cSrcweir { 238*cdf0e10cSrcweir bNeedEntries = sal_False; 239*cdf0e10cSrcweir //! create physical representation of an **empty** dictionary 240*cdf0e10cSrcweir //! that could be found by the dictionary-list implementation 241*cdf0e10cSrcweir // (Note: empty dictionaries are not just empty files!) 242*cdf0e10cSrcweir Save(); 243*cdf0e10cSrcweir bIsReadonly = IsReadOnly( rMainURL ); // will be sal_False if Save was succesfull 244*cdf0e10cSrcweir } 245*cdf0e10cSrcweir } 246*cdf0e10cSrcweir else 247*cdf0e10cSrcweir { 248*cdf0e10cSrcweir bNeedEntries = sal_False; 249*cdf0e10cSrcweir } 250*cdf0e10cSrcweir } 251*cdf0e10cSrcweir 252*cdf0e10cSrcweir 253*cdf0e10cSrcweir ConvDic::~ConvDic() 254*cdf0e10cSrcweir { 255*cdf0e10cSrcweir } 256*cdf0e10cSrcweir 257*cdf0e10cSrcweir 258*cdf0e10cSrcweir void ConvDic::Load() 259*cdf0e10cSrcweir { 260*cdf0e10cSrcweir DBG_ASSERT( !bIsModified, "dictionary is modified. Really do 'Load'?" ); 261*cdf0e10cSrcweir 262*cdf0e10cSrcweir //!! prevent function from being called recursively via HasEntry, AddEntry 263*cdf0e10cSrcweir bNeedEntries = sal_False; 264*cdf0e10cSrcweir ConvDicXMLImport *pImport = new ConvDicXMLImport( this, aMainURL ); 265*cdf0e10cSrcweir //!! keep a first reference to ensure the lifetime of the object !! 266*cdf0e10cSrcweir uno::Reference< XInterface > xRef( (document::XFilter *) pImport, UNO_QUERY ); 267*cdf0e10cSrcweir ReadThroughDic( aMainURL, *pImport ); // will implicitly add the entries 268*cdf0e10cSrcweir bIsModified = sal_False; 269*cdf0e10cSrcweir } 270*cdf0e10cSrcweir 271*cdf0e10cSrcweir 272*cdf0e10cSrcweir void ConvDic::Save() 273*cdf0e10cSrcweir { 274*cdf0e10cSrcweir DBG_ASSERT( !bNeedEntries, "saving while entries missing" ); 275*cdf0e10cSrcweir if (aMainURL.Len() == 0 || bNeedEntries) 276*cdf0e10cSrcweir return; 277*cdf0e10cSrcweir DBG_ASSERT(!INetURLObject( aMainURL ).HasError(), "invalid URL"); 278*cdf0e10cSrcweir 279*cdf0e10cSrcweir uno::Reference< lang::XMultiServiceFactory > xServiceFactory( utl::getProcessServiceFactory() ); 280*cdf0e10cSrcweir 281*cdf0e10cSrcweir // get XOutputStream stream 282*cdf0e10cSrcweir uno::Reference< io::XStream > xStream; 283*cdf0e10cSrcweir try 284*cdf0e10cSrcweir { 285*cdf0e10cSrcweir uno::Reference< ucb::XSimpleFileAccess > xAccess( xServiceFactory->createInstance( 286*cdf0e10cSrcweir A2OU( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY_THROW ); 287*cdf0e10cSrcweir xStream = xAccess->openFileReadWrite( aMainURL ); 288*cdf0e10cSrcweir } 289*cdf0e10cSrcweir catch (uno::Exception & e) 290*cdf0e10cSrcweir { 291*cdf0e10cSrcweir DBG_ASSERT( 0, "failed to get input stream" ); 292*cdf0e10cSrcweir (void) e; 293*cdf0e10cSrcweir } 294*cdf0e10cSrcweir if (!xStream.is()) 295*cdf0e10cSrcweir return; 296*cdf0e10cSrcweir 297*cdf0e10cSrcweir SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) ); 298*cdf0e10cSrcweir 299*cdf0e10cSrcweir // get XML writer 300*cdf0e10cSrcweir uno::Reference< io::XActiveDataSource > xSaxWriter; 301*cdf0e10cSrcweir if (xServiceFactory.is()) 302*cdf0e10cSrcweir { 303*cdf0e10cSrcweir try 304*cdf0e10cSrcweir { 305*cdf0e10cSrcweir xSaxWriter = uno::Reference< io::XActiveDataSource >( 306*cdf0e10cSrcweir xServiceFactory->createInstance( 307*cdf0e10cSrcweir OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) ), UNO_QUERY ); 308*cdf0e10cSrcweir } 309*cdf0e10cSrcweir catch (uno::Exception &) 310*cdf0e10cSrcweir { 311*cdf0e10cSrcweir } 312*cdf0e10cSrcweir } 313*cdf0e10cSrcweir DBG_ASSERT( xSaxWriter.is(), "can't instantiate XML writer" ); 314*cdf0e10cSrcweir 315*cdf0e10cSrcweir if (xSaxWriter.is() && xStream.is()) 316*cdf0e10cSrcweir { 317*cdf0e10cSrcweir // connect XML writer to output stream 318*cdf0e10cSrcweir xSaxWriter->setOutputStream( xStream->getOutputStream() ); 319*cdf0e10cSrcweir 320*cdf0e10cSrcweir // prepare arguments (prepend doc handler to given arguments) 321*cdf0e10cSrcweir uno::Reference< xml::sax::XDocumentHandler > xDocHandler( xSaxWriter, UNO_QUERY ); 322*cdf0e10cSrcweir ConvDicXMLExport *pExport = new ConvDicXMLExport( *this, aMainURL, xDocHandler ); 323*cdf0e10cSrcweir //!! keep a first(!) reference until everything is done to 324*cdf0e10cSrcweir //!! ensure the proper lifetime of the object 325*cdf0e10cSrcweir uno::Reference< document::XFilter > aRef( (document::XFilter *) pExport ); 326*cdf0e10cSrcweir sal_Bool bRet = pExport->Export(); // write entries to file 327*cdf0e10cSrcweir DBG_ASSERT( !pStream->GetError(), "I/O error while writing to stream" ); 328*cdf0e10cSrcweir if (bRet) 329*cdf0e10cSrcweir bIsModified = sal_False; 330*cdf0e10cSrcweir } 331*cdf0e10cSrcweir DBG_ASSERT( !bIsModified, "dictionary still modified after save. Save failed?" ); 332*cdf0e10cSrcweir } 333*cdf0e10cSrcweir 334*cdf0e10cSrcweir 335*cdf0e10cSrcweir ConvMap::iterator ConvDic::GetEntry( ConvMap &rMap, const rtl::OUString &rFirstText, const rtl::OUString &rSecondText ) 336*cdf0e10cSrcweir { 337*cdf0e10cSrcweir pair< ConvMap::iterator, ConvMap::iterator > aRange = 338*cdf0e10cSrcweir rMap.equal_range( rFirstText ); 339*cdf0e10cSrcweir ConvMap::iterator aPos = rMap.end(); 340*cdf0e10cSrcweir for (ConvMap::iterator aIt = aRange.first; 341*cdf0e10cSrcweir aIt != aRange.second && aPos == rMap.end(); 342*cdf0e10cSrcweir ++aIt) 343*cdf0e10cSrcweir { 344*cdf0e10cSrcweir if ((*aIt).second == rSecondText) 345*cdf0e10cSrcweir aPos = aIt; 346*cdf0e10cSrcweir } 347*cdf0e10cSrcweir return aPos; 348*cdf0e10cSrcweir } 349*cdf0e10cSrcweir 350*cdf0e10cSrcweir 351*cdf0e10cSrcweir sal_Bool ConvDic::HasEntry( const OUString &rLeftText, const OUString &rRightText ) 352*cdf0e10cSrcweir { 353*cdf0e10cSrcweir if (bNeedEntries) 354*cdf0e10cSrcweir Load(); 355*cdf0e10cSrcweir ConvMap::iterator aIt = GetEntry( aFromLeft, rLeftText, rRightText ); 356*cdf0e10cSrcweir return aIt != aFromLeft.end(); 357*cdf0e10cSrcweir } 358*cdf0e10cSrcweir 359*cdf0e10cSrcweir 360*cdf0e10cSrcweir void ConvDic::AddEntry( const OUString &rLeftText, const OUString &rRightText ) 361*cdf0e10cSrcweir { 362*cdf0e10cSrcweir if (bNeedEntries) 363*cdf0e10cSrcweir Load(); 364*cdf0e10cSrcweir 365*cdf0e10cSrcweir DBG_ASSERT(!HasEntry( rLeftText, rRightText), "entry already exists" ); 366*cdf0e10cSrcweir aFromLeft .insert( ConvMap::value_type( rLeftText, rRightText ) ); 367*cdf0e10cSrcweir if (pFromRight.get()) 368*cdf0e10cSrcweir pFromRight->insert( ConvMap::value_type( rRightText, rLeftText ) ); 369*cdf0e10cSrcweir 370*cdf0e10cSrcweir if (bMaxCharCountIsValid) 371*cdf0e10cSrcweir { 372*cdf0e10cSrcweir if (rLeftText.getLength() > nMaxLeftCharCount) 373*cdf0e10cSrcweir nMaxLeftCharCount = (sal_Int16) rLeftText.getLength(); 374*cdf0e10cSrcweir if (pFromRight.get() && rRightText.getLength() > nMaxRightCharCount) 375*cdf0e10cSrcweir nMaxRightCharCount = (sal_Int16) rRightText.getLength(); 376*cdf0e10cSrcweir } 377*cdf0e10cSrcweir 378*cdf0e10cSrcweir bIsModified = sal_True; 379*cdf0e10cSrcweir } 380*cdf0e10cSrcweir 381*cdf0e10cSrcweir 382*cdf0e10cSrcweir void ConvDic::RemoveEntry( const OUString &rLeftText, const OUString &rRightText ) 383*cdf0e10cSrcweir { 384*cdf0e10cSrcweir if (bNeedEntries) 385*cdf0e10cSrcweir Load(); 386*cdf0e10cSrcweir 387*cdf0e10cSrcweir ConvMap::iterator aLeftIt = GetEntry( aFromLeft, rLeftText, rRightText ); 388*cdf0e10cSrcweir DBG_ASSERT( aLeftIt != aFromLeft.end(), "left map entry missing" ); 389*cdf0e10cSrcweir aFromLeft .erase( aLeftIt ); 390*cdf0e10cSrcweir 391*cdf0e10cSrcweir if (pFromRight.get()) 392*cdf0e10cSrcweir { 393*cdf0e10cSrcweir ConvMap::iterator aRightIt = GetEntry( *pFromRight, rRightText, rLeftText ); 394*cdf0e10cSrcweir DBG_ASSERT( aRightIt != pFromRight->end(), "right map entry missing" ); 395*cdf0e10cSrcweir pFromRight->erase( aRightIt ); 396*cdf0e10cSrcweir } 397*cdf0e10cSrcweir 398*cdf0e10cSrcweir bIsModified = sal_True; 399*cdf0e10cSrcweir bMaxCharCountIsValid = sal_False; 400*cdf0e10cSrcweir } 401*cdf0e10cSrcweir 402*cdf0e10cSrcweir 403*cdf0e10cSrcweir OUString SAL_CALL ConvDic::getName( ) 404*cdf0e10cSrcweir throw (RuntimeException) 405*cdf0e10cSrcweir { 406*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 407*cdf0e10cSrcweir return aName; 408*cdf0e10cSrcweir } 409*cdf0e10cSrcweir 410*cdf0e10cSrcweir 411*cdf0e10cSrcweir Locale SAL_CALL ConvDic::getLocale( ) 412*cdf0e10cSrcweir throw (RuntimeException) 413*cdf0e10cSrcweir { 414*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 415*cdf0e10cSrcweir return CreateLocale( nLanguage ); 416*cdf0e10cSrcweir } 417*cdf0e10cSrcweir 418*cdf0e10cSrcweir 419*cdf0e10cSrcweir sal_Int16 SAL_CALL ConvDic::getConversionType( ) 420*cdf0e10cSrcweir throw (RuntimeException) 421*cdf0e10cSrcweir { 422*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 423*cdf0e10cSrcweir return nConversionType; 424*cdf0e10cSrcweir } 425*cdf0e10cSrcweir 426*cdf0e10cSrcweir 427*cdf0e10cSrcweir void SAL_CALL ConvDic::setActive( sal_Bool bActivate ) 428*cdf0e10cSrcweir throw (RuntimeException) 429*cdf0e10cSrcweir { 430*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 431*cdf0e10cSrcweir bIsActive = bActivate; 432*cdf0e10cSrcweir } 433*cdf0e10cSrcweir 434*cdf0e10cSrcweir 435*cdf0e10cSrcweir sal_Bool SAL_CALL ConvDic::isActive( ) 436*cdf0e10cSrcweir throw (RuntimeException) 437*cdf0e10cSrcweir { 438*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 439*cdf0e10cSrcweir return bIsActive; 440*cdf0e10cSrcweir } 441*cdf0e10cSrcweir 442*cdf0e10cSrcweir 443*cdf0e10cSrcweir void SAL_CALL ConvDic::clear( ) 444*cdf0e10cSrcweir throw (RuntimeException) 445*cdf0e10cSrcweir { 446*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 447*cdf0e10cSrcweir aFromLeft .clear(); 448*cdf0e10cSrcweir if (pFromRight.get()) 449*cdf0e10cSrcweir pFromRight->clear(); 450*cdf0e10cSrcweir bNeedEntries = sal_False; 451*cdf0e10cSrcweir bIsModified = sal_True; 452*cdf0e10cSrcweir nMaxLeftCharCount = 0; 453*cdf0e10cSrcweir nMaxRightCharCount = 0; 454*cdf0e10cSrcweir bMaxCharCountIsValid = sal_True; 455*cdf0e10cSrcweir } 456*cdf0e10cSrcweir 457*cdf0e10cSrcweir 458*cdf0e10cSrcweir uno::Sequence< OUString > SAL_CALL ConvDic::getConversions( 459*cdf0e10cSrcweir const OUString& aText, 460*cdf0e10cSrcweir sal_Int32 nStartPos, 461*cdf0e10cSrcweir sal_Int32 nLength, 462*cdf0e10cSrcweir ConversionDirection eDirection, 463*cdf0e10cSrcweir sal_Int32 /*nTextConversionOptions*/ ) 464*cdf0e10cSrcweir throw (IllegalArgumentException, RuntimeException) 465*cdf0e10cSrcweir { 466*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 467*cdf0e10cSrcweir 468*cdf0e10cSrcweir if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT) 469*cdf0e10cSrcweir return uno::Sequence< OUString >(); 470*cdf0e10cSrcweir 471*cdf0e10cSrcweir if (bNeedEntries) 472*cdf0e10cSrcweir Load(); 473*cdf0e10cSrcweir 474*cdf0e10cSrcweir OUString aLookUpText( aText.copy(nStartPos, nLength) ); 475*cdf0e10cSrcweir ConvMap &rConvMap = eDirection == ConversionDirection_FROM_LEFT ? 476*cdf0e10cSrcweir aFromLeft : *pFromRight; 477*cdf0e10cSrcweir pair< ConvMap::iterator, ConvMap::iterator > aRange = 478*cdf0e10cSrcweir rConvMap.equal_range( aLookUpText ); 479*cdf0e10cSrcweir 480*cdf0e10cSrcweir sal_Int32 nCount = 0; 481*cdf0e10cSrcweir ConvMap::iterator aIt; 482*cdf0e10cSrcweir for (aIt = aRange.first; aIt != aRange.second; ++aIt) 483*cdf0e10cSrcweir ++nCount; 484*cdf0e10cSrcweir 485*cdf0e10cSrcweir uno::Sequence< OUString > aRes( nCount ); 486*cdf0e10cSrcweir OUString *pRes = aRes.getArray(); 487*cdf0e10cSrcweir sal_Int32 i = 0; 488*cdf0e10cSrcweir for (aIt = aRange.first; aIt != aRange.second; ++aIt) 489*cdf0e10cSrcweir pRes[i++] = (*aIt).second; 490*cdf0e10cSrcweir 491*cdf0e10cSrcweir return aRes; 492*cdf0e10cSrcweir } 493*cdf0e10cSrcweir 494*cdf0e10cSrcweir 495*cdf0e10cSrcweir static sal_Bool lcl_SeqHasEntry( 496*cdf0e10cSrcweir const OUString *pSeqStart, // first element to check 497*cdf0e10cSrcweir sal_Int32 nToCheck, // number of elements to check 498*cdf0e10cSrcweir const OUString &rText) 499*cdf0e10cSrcweir { 500*cdf0e10cSrcweir sal_Bool bRes = sal_False; 501*cdf0e10cSrcweir if (pSeqStart && nToCheck > 0) 502*cdf0e10cSrcweir { 503*cdf0e10cSrcweir const OUString *pDone = pSeqStart + nToCheck; // one behind last to check 504*cdf0e10cSrcweir while (!bRes && pSeqStart != pDone) 505*cdf0e10cSrcweir { 506*cdf0e10cSrcweir if (*pSeqStart++ == rText) 507*cdf0e10cSrcweir bRes = sal_True; 508*cdf0e10cSrcweir } 509*cdf0e10cSrcweir } 510*cdf0e10cSrcweir return bRes; 511*cdf0e10cSrcweir } 512*cdf0e10cSrcweir 513*cdf0e10cSrcweir uno::Sequence< OUString > SAL_CALL ConvDic::getConversionEntries( 514*cdf0e10cSrcweir ConversionDirection eDirection ) 515*cdf0e10cSrcweir throw (RuntimeException) 516*cdf0e10cSrcweir { 517*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 518*cdf0e10cSrcweir 519*cdf0e10cSrcweir if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT) 520*cdf0e10cSrcweir return uno::Sequence< OUString >(); 521*cdf0e10cSrcweir 522*cdf0e10cSrcweir if (bNeedEntries) 523*cdf0e10cSrcweir Load(); 524*cdf0e10cSrcweir 525*cdf0e10cSrcweir ConvMap &rConvMap = eDirection == ConversionDirection_FROM_LEFT ? 526*cdf0e10cSrcweir aFromLeft : *pFromRight; 527*cdf0e10cSrcweir uno::Sequence< OUString > aRes( rConvMap.size() ); 528*cdf0e10cSrcweir OUString *pRes = aRes.getArray(); 529*cdf0e10cSrcweir ConvMap::iterator aIt = rConvMap.begin(); 530*cdf0e10cSrcweir sal_Int32 nIdx = 0; 531*cdf0e10cSrcweir while (aIt != rConvMap.end()) 532*cdf0e10cSrcweir { 533*cdf0e10cSrcweir OUString aCurEntry( (*aIt).first ); 534*cdf0e10cSrcweir // skip duplicate entries ( duplicate = duplicate entries 535*cdf0e10cSrcweir // respective to the evaluated side (FROM_LEFT or FROM_RIGHT). 536*cdf0e10cSrcweir // Thus if FROM_LEFT is evaluated for pairs (A,B) and (A,C) 537*cdf0e10cSrcweir // only one entry for A will be returned in the result) 538*cdf0e10cSrcweir if (nIdx == 0 || !lcl_SeqHasEntry( pRes, nIdx, aCurEntry )) 539*cdf0e10cSrcweir pRes[ nIdx++ ] = aCurEntry; 540*cdf0e10cSrcweir ++aIt; 541*cdf0e10cSrcweir } 542*cdf0e10cSrcweir aRes.realloc( nIdx ); 543*cdf0e10cSrcweir 544*cdf0e10cSrcweir return aRes; 545*cdf0e10cSrcweir } 546*cdf0e10cSrcweir 547*cdf0e10cSrcweir 548*cdf0e10cSrcweir void SAL_CALL ConvDic::addEntry( 549*cdf0e10cSrcweir const OUString& aLeftText, 550*cdf0e10cSrcweir const OUString& aRightText ) 551*cdf0e10cSrcweir throw (IllegalArgumentException, container::ElementExistException, RuntimeException) 552*cdf0e10cSrcweir { 553*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 554*cdf0e10cSrcweir if (bNeedEntries) 555*cdf0e10cSrcweir Load(); 556*cdf0e10cSrcweir if (HasEntry( aLeftText, aRightText )) 557*cdf0e10cSrcweir throw container::ElementExistException(); 558*cdf0e10cSrcweir AddEntry( aLeftText, aRightText ); 559*cdf0e10cSrcweir } 560*cdf0e10cSrcweir 561*cdf0e10cSrcweir 562*cdf0e10cSrcweir void SAL_CALL ConvDic::removeEntry( 563*cdf0e10cSrcweir const OUString& aLeftText, 564*cdf0e10cSrcweir const OUString& aRightText ) 565*cdf0e10cSrcweir throw (container::NoSuchElementException, RuntimeException) 566*cdf0e10cSrcweir { 567*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 568*cdf0e10cSrcweir if (bNeedEntries) 569*cdf0e10cSrcweir Load(); 570*cdf0e10cSrcweir if (!HasEntry( aLeftText, aRightText )) 571*cdf0e10cSrcweir throw container::NoSuchElementException(); 572*cdf0e10cSrcweir RemoveEntry( aLeftText, aRightText ); 573*cdf0e10cSrcweir } 574*cdf0e10cSrcweir 575*cdf0e10cSrcweir 576*cdf0e10cSrcweir sal_Int16 SAL_CALL ConvDic::getMaxCharCount( ConversionDirection eDirection ) 577*cdf0e10cSrcweir throw (RuntimeException) 578*cdf0e10cSrcweir { 579*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 580*cdf0e10cSrcweir 581*cdf0e10cSrcweir if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT) 582*cdf0e10cSrcweir { 583*cdf0e10cSrcweir DBG_ASSERT( nMaxRightCharCount == 0, "max right char count should be 0" ); 584*cdf0e10cSrcweir return 0; 585*cdf0e10cSrcweir } 586*cdf0e10cSrcweir 587*cdf0e10cSrcweir if (bNeedEntries) 588*cdf0e10cSrcweir Load(); 589*cdf0e10cSrcweir 590*cdf0e10cSrcweir if (!bMaxCharCountIsValid) 591*cdf0e10cSrcweir { 592*cdf0e10cSrcweir nMaxLeftCharCount = 0; 593*cdf0e10cSrcweir ConvMap::iterator aIt = aFromLeft.begin(); 594*cdf0e10cSrcweir while (aIt != aFromLeft.end()) 595*cdf0e10cSrcweir { 596*cdf0e10cSrcweir sal_Int16 nTmp = (sal_Int16) (*aIt).first.getLength(); 597*cdf0e10cSrcweir if (nTmp > nMaxLeftCharCount) 598*cdf0e10cSrcweir nMaxLeftCharCount = nTmp; 599*cdf0e10cSrcweir ++aIt; 600*cdf0e10cSrcweir } 601*cdf0e10cSrcweir 602*cdf0e10cSrcweir nMaxRightCharCount = 0; 603*cdf0e10cSrcweir if (pFromRight.get()) 604*cdf0e10cSrcweir { 605*cdf0e10cSrcweir aIt = pFromRight->begin(); 606*cdf0e10cSrcweir while (aIt != pFromRight->end()) 607*cdf0e10cSrcweir { 608*cdf0e10cSrcweir sal_Int16 nTmp = (sal_Int16) (*aIt).first.getLength(); 609*cdf0e10cSrcweir if (nTmp > nMaxRightCharCount) 610*cdf0e10cSrcweir nMaxRightCharCount = nTmp; 611*cdf0e10cSrcweir ++aIt; 612*cdf0e10cSrcweir } 613*cdf0e10cSrcweir } 614*cdf0e10cSrcweir 615*cdf0e10cSrcweir bMaxCharCountIsValid = sal_True; 616*cdf0e10cSrcweir } 617*cdf0e10cSrcweir sal_Int16 nRes = eDirection == ConversionDirection_FROM_LEFT ? 618*cdf0e10cSrcweir nMaxLeftCharCount : nMaxRightCharCount; 619*cdf0e10cSrcweir DBG_ASSERT( nRes >= 0, "invalid MaxCharCount" ); 620*cdf0e10cSrcweir return nRes; 621*cdf0e10cSrcweir } 622*cdf0e10cSrcweir 623*cdf0e10cSrcweir 624*cdf0e10cSrcweir void SAL_CALL ConvDic::setPropertyType( 625*cdf0e10cSrcweir const OUString& rLeftText, 626*cdf0e10cSrcweir const OUString& rRightText, 627*cdf0e10cSrcweir sal_Int16 nPropertyType ) 628*cdf0e10cSrcweir throw (container::NoSuchElementException, IllegalArgumentException, RuntimeException) 629*cdf0e10cSrcweir { 630*cdf0e10cSrcweir sal_Bool bHasElement = HasEntry( rLeftText, rRightText); 631*cdf0e10cSrcweir if (!bHasElement) 632*cdf0e10cSrcweir throw container::NoSuchElementException(); 633*cdf0e10cSrcweir 634*cdf0e10cSrcweir // currently we assume that entries with the same left text have the 635*cdf0e10cSrcweir // same PropertyType even if the right text is different... 636*cdf0e10cSrcweir if (pConvPropType.get()) 637*cdf0e10cSrcweir pConvPropType->insert( PropTypeMap::value_type( rLeftText, nPropertyType ) ); 638*cdf0e10cSrcweir bIsModified = sal_True; 639*cdf0e10cSrcweir } 640*cdf0e10cSrcweir 641*cdf0e10cSrcweir 642*cdf0e10cSrcweir sal_Int16 SAL_CALL ConvDic::getPropertyType( 643*cdf0e10cSrcweir const OUString& rLeftText, 644*cdf0e10cSrcweir const OUString& rRightText ) 645*cdf0e10cSrcweir throw (container::NoSuchElementException, RuntimeException) 646*cdf0e10cSrcweir { 647*cdf0e10cSrcweir sal_Bool bHasElement = HasEntry( rLeftText, rRightText); 648*cdf0e10cSrcweir if (!bHasElement) 649*cdf0e10cSrcweir throw container::NoSuchElementException(); 650*cdf0e10cSrcweir 651*cdf0e10cSrcweir sal_Int16 nRes = ConversionPropertyType::NOT_DEFINED; 652*cdf0e10cSrcweir if (pConvPropType.get()) 653*cdf0e10cSrcweir { 654*cdf0e10cSrcweir // still assuming that entries with same left text have same PropertyType 655*cdf0e10cSrcweir // even if they have different right text... 656*cdf0e10cSrcweir PropTypeMap::iterator aIt = pConvPropType->find( rLeftText ); 657*cdf0e10cSrcweir if (aIt != pConvPropType->end()) 658*cdf0e10cSrcweir nRes = (*aIt).second; 659*cdf0e10cSrcweir } 660*cdf0e10cSrcweir return nRes; 661*cdf0e10cSrcweir } 662*cdf0e10cSrcweir 663*cdf0e10cSrcweir 664*cdf0e10cSrcweir void SAL_CALL ConvDic::flush( ) 665*cdf0e10cSrcweir throw (RuntimeException) 666*cdf0e10cSrcweir { 667*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 668*cdf0e10cSrcweir 669*cdf0e10cSrcweir if (!bIsModified) 670*cdf0e10cSrcweir return; 671*cdf0e10cSrcweir 672*cdf0e10cSrcweir Save(); 673*cdf0e10cSrcweir 674*cdf0e10cSrcweir // notify listeners 675*cdf0e10cSrcweir EventObject aEvtObj; 676*cdf0e10cSrcweir aEvtObj.Source = uno::Reference< XFlushable >( this ); 677*cdf0e10cSrcweir cppu::OInterfaceIteratorHelper aIt( aFlushListeners ); 678*cdf0e10cSrcweir while (aIt.hasMoreElements()) 679*cdf0e10cSrcweir { 680*cdf0e10cSrcweir uno::Reference< util::XFlushListener > xRef( aIt.next(), UNO_QUERY ); 681*cdf0e10cSrcweir if (xRef.is()) 682*cdf0e10cSrcweir xRef->flushed( aEvtObj ); 683*cdf0e10cSrcweir } 684*cdf0e10cSrcweir } 685*cdf0e10cSrcweir 686*cdf0e10cSrcweir 687*cdf0e10cSrcweir void SAL_CALL ConvDic::addFlushListener( 688*cdf0e10cSrcweir const uno::Reference< util::XFlushListener >& rxListener ) 689*cdf0e10cSrcweir throw (RuntimeException) 690*cdf0e10cSrcweir { 691*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 692*cdf0e10cSrcweir if (rxListener.is()) 693*cdf0e10cSrcweir aFlushListeners.addInterface( rxListener ); 694*cdf0e10cSrcweir } 695*cdf0e10cSrcweir 696*cdf0e10cSrcweir 697*cdf0e10cSrcweir void SAL_CALL ConvDic::removeFlushListener( 698*cdf0e10cSrcweir const uno::Reference< util::XFlushListener >& rxListener ) 699*cdf0e10cSrcweir throw (RuntimeException) 700*cdf0e10cSrcweir { 701*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 702*cdf0e10cSrcweir if (rxListener.is()) 703*cdf0e10cSrcweir aFlushListeners.removeInterface( rxListener ); 704*cdf0e10cSrcweir } 705*cdf0e10cSrcweir 706*cdf0e10cSrcweir 707*cdf0e10cSrcweir OUString SAL_CALL ConvDic::getImplementationName( ) 708*cdf0e10cSrcweir throw (RuntimeException) 709*cdf0e10cSrcweir { 710*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 711*cdf0e10cSrcweir return getImplementationName_Static(); 712*cdf0e10cSrcweir } 713*cdf0e10cSrcweir 714*cdf0e10cSrcweir 715*cdf0e10cSrcweir sal_Bool SAL_CALL ConvDic::supportsService( const OUString& rServiceName ) 716*cdf0e10cSrcweir throw (RuntimeException) 717*cdf0e10cSrcweir { 718*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 719*cdf0e10cSrcweir sal_Bool bRes = sal_False; 720*cdf0e10cSrcweir if (rServiceName.equalsAscii( SN_CONV_DICTIONARY )) 721*cdf0e10cSrcweir bRes = sal_True; 722*cdf0e10cSrcweir return bRes; 723*cdf0e10cSrcweir } 724*cdf0e10cSrcweir 725*cdf0e10cSrcweir 726*cdf0e10cSrcweir uno::Sequence< OUString > SAL_CALL ConvDic::getSupportedServiceNames( ) 727*cdf0e10cSrcweir throw (RuntimeException) 728*cdf0e10cSrcweir { 729*cdf0e10cSrcweir MutexGuard aGuard( GetLinguMutex() ); 730*cdf0e10cSrcweir return getSupportedServiceNames_Static(); 731*cdf0e10cSrcweir } 732*cdf0e10cSrcweir 733*cdf0e10cSrcweir 734*cdf0e10cSrcweir uno::Sequence< OUString > ConvDic::getSupportedServiceNames_Static() 735*cdf0e10cSrcweir throw() 736*cdf0e10cSrcweir { 737*cdf0e10cSrcweir uno::Sequence< OUString > aSNS( 1 ); 738*cdf0e10cSrcweir aSNS.getArray()[0] = A2OU( SN_CONV_DICTIONARY ); 739*cdf0e10cSrcweir return aSNS; 740*cdf0e10cSrcweir } 741*cdf0e10cSrcweir 742*cdf0e10cSrcweir /////////////////////////////////////////////////////////////////////////// 743*cdf0e10cSrcweir 744*cdf0e10cSrcweir 745