LCOV - code coverage report
Current view: top level - libreoffice/editeng/source/misc - svxacorr.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 36 1358 2.7 %
Date: 2012-12-27 Functions: 8 95 8.4 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
      20             : #include <com/sun/star/io/XStream.hpp>
      21             : #include <com/sun/star/lang/Locale.hpp>
      22             : #include <tools/urlobj.hxx>
      23             : #include <i18npool/mslangid.hxx>
      24             : #include <vcl/svapp.hxx>
      25             : #include <sot/storinfo.hxx>
      26             : #include <svl/fstathelper.hxx>
      27             : #include <svtools/helpopt.hxx>
      28             : #include <svl/urihelper.hxx>
      29             : #include <unotools/charclass.hxx>
      30             : #include <com/sun/star/i18n/UnicodeType.hpp>
      31             : #include <unotools/collatorwrapper.hxx>
      32             : #include <com/sun/star/i18n/CollatorOptions.hpp>
      33             : #include <com/sun/star/i18n/UnicodeScript.hpp>
      34             : #include <com/sun/star/i18n/XOrdinalSuffix.hpp>
      35             : #include <unotools/localedatawrapper.hxx>
      36             : #include <unotools/transliterationwrapper.hxx>
      37             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      38             : #include <com/sun/star/io/XActiveDataSource.hpp>
      39             : #include <comphelper/componentcontext.hxx>
      40             : #include <comphelper/processfactory.hxx>
      41             : #include <comphelper/storagehelper.hxx>
      42             : #include <comphelper/string.hxx>
      43             : #include <editeng/editids.hrc>
      44             : #include <sot/storage.hxx>
      45             : #include <editeng/udlnitem.hxx>
      46             : #include <editeng/wghtitem.hxx>
      47             : #include <editeng/escpitem.hxx>
      48             : #include <editeng/svxacorr.hxx>
      49             : #include <editeng/unolingu.hxx>
      50             : #include "vcl/window.hxx"
      51             : #include <helpid.hrc>
      52             : #include <com/sun/star/xml/sax/InputSource.hpp>
      53             : #include <com/sun/star/xml/sax/Parser.hpp>
      54             : #include <com/sun/star/xml/sax/Writer.hpp>
      55             : #include <unotools/streamwrap.hxx>
      56             : #include <SvXMLAutoCorrectImport.hxx>
      57             : #include <SvXMLAutoCorrectExport.hxx>
      58             : #include <ucbhelper/content.hxx>
      59             : #include <com/sun/star/ucb/XCommandEnvironment.hpp>
      60             : #include <com/sun/star/ucb/TransferInfo.hpp>
      61             : #include <com/sun/star/ucb/NameClash.hpp>
      62             : #include <xmloff/xmltoken.hxx>
      63             : #include <vcl/help.hxx>
      64             : #include <rtl/logfile.hxx>
      65             : 
      66             : #define CHAR_HARDBLANK      ((sal_Unicode)0x00A0)
      67             : 
      68             : using namespace ::com::sun::star::ucb;
      69             : using namespace ::com::sun::star::uno;
      70             : using namespace ::com::sun::star;
      71             : using namespace ::xmloff::token;
      72             : using namespace ::rtl;
      73             : using namespace ::utl;
      74             : 
      75             : static const int C_NONE             = 0x00;
      76             : static const int C_FULL_STOP        = 0x01;
      77             : static const int C_EXCLAMATION_MARK = 0x02;
      78             : static const int C_QUESTION_MARK    = 0x04;
      79             : 
      80             : static const sal_Char pImplWrdStt_ExcptLstStr[]    = "WordExceptList";
      81             : static const sal_Char pImplCplStt_ExcptLstStr[]    = "SentenceExceptList";
      82             : static const sal_Char pImplAutocorr_ListStr[]      = "DocumentList";
      83             : static const sal_Char pXMLImplWrdStt_ExcptLstStr[] = "WordExceptList.xml";
      84             : static const sal_Char pXMLImplCplStt_ExcptLstStr[] = "SentenceExceptList.xml";
      85             : static const sal_Char pXMLImplAutocorr_ListStr[]   = "DocumentList.xml";
      86             : 
      87             : static const sal_Char
      88             :     /* also at these beginnings - Brackets and all kinds of begin characters */
      89             :     sImplSttSkipChars[] = "\"\'([{\x83\x84\x89\x91\x92\x93\x94",
      90             :     /* also at these ends - Brackets and all kinds of begin characters */
      91             :     sImplEndSkipChars[] = "\"\')]}\x83\x84\x89\x91\x92\x93\x94";
      92             : 
      93             : // These characters are allowed in words: (for FnCptlSttSntnc)
      94             : static const sal_Char sImplWordChars[] = "-'";
      95             : 
      96             : void EncryptBlockName_Imp( String& rName );
      97             : 
      98           0 : TYPEINIT0(SvxAutoCorrect)
      99             : 
     100             : typedef SvxAutoCorrectLanguageLists* SvxAutoCorrectLanguageListsPtr;
     101             : 
     102           0 : static inline int IsWordDelim( const sal_Unicode c )
     103             : {
     104             :     return ' ' == c || '\t' == c || 0x0a == c ||
     105           0 :             0xA0 == c || 0x2011 == c || 0x1 == c;
     106             : }
     107             : 
     108           0 : static inline int IsLowerLetter( sal_Int32 nCharType )
     109             : {
     110           0 :     return CharClass::isLetterType( nCharType ) &&
     111           0 :             0 == ( ::com::sun::star::i18n::KCharacterType::UPPER & nCharType);
     112             : }
     113             : 
     114           0 : static inline int IsUpperLetter( sal_Int32 nCharType )
     115             : {
     116           0 :     return CharClass::isLetterType( nCharType ) &&
     117           0 :             0 == ( ::com::sun::star::i18n::KCharacterType::LOWER & nCharType);
     118             : }
     119             : 
     120           0 : bool lcl_IsUnsupportedUnicodeChar( CharClass& rCC, const String& rTxt,
     121             :                                    xub_StrLen nStt, xub_StrLen nEnd )
     122             : {
     123           0 :     for( ; nStt < nEnd; ++nStt )
     124             :     {
     125           0 :         short nScript = rCC.getScript( rTxt, nStt );
     126           0 :         switch( nScript )
     127             :         {
     128             :             case ::com::sun::star::i18n::UnicodeScript_kCJKRadicalsSupplement:
     129             :             case ::com::sun::star::i18n::UnicodeScript_kHangulJamo:
     130             :             case ::com::sun::star::i18n::UnicodeScript_kCJKSymbolPunctuation:
     131             :             case ::com::sun::star::i18n::UnicodeScript_kHiragana:
     132             :             case ::com::sun::star::i18n::UnicodeScript_kKatakana:
     133             :             case ::com::sun::star::i18n::UnicodeScript_kHangulCompatibilityJamo:
     134             :             case ::com::sun::star::i18n::UnicodeScript_kEnclosedCJKLetterMonth:
     135             :             case ::com::sun::star::i18n::UnicodeScript_kCJKCompatibility:
     136             :             case ::com::sun::star::i18n::UnicodeScript_k_CJKUnifiedIdeographsExtensionA:
     137             :             case ::com::sun::star::i18n::UnicodeScript_kCJKUnifiedIdeograph:
     138             :             case ::com::sun::star::i18n::UnicodeScript_kHangulSyllable:
     139             :             case ::com::sun::star::i18n::UnicodeScript_kCJKCompatibilityIdeograph:
     140             :             case ::com::sun::star::i18n::UnicodeScript_kHalfwidthFullwidthForm:
     141           0 :                 return true;
     142             :             default: ; //do nothing
     143             :         }
     144             :     }
     145           0 :     return false;
     146             : }
     147             : 
     148           0 : static sal_Bool lcl_IsSymbolChar( CharClass& rCC, const String& rTxt,
     149             :                                   xub_StrLen nStt, xub_StrLen nEnd )
     150             : {
     151           0 :     for( ; nStt < nEnd; ++nStt )
     152             :     {
     153           0 :         if( ::com::sun::star::i18n::UnicodeType::PRIVATE_USE ==
     154           0 :                 rCC.getType( rTxt, nStt ))
     155           0 :             return sal_True;
     156             :     }
     157           0 :     return sal_False;
     158             : }
     159             : 
     160           0 : static sal_Bool lcl_IsInAsciiArr( const sal_Char* pArr, const sal_Unicode c )
     161             : {
     162           0 :     sal_Bool bRet = sal_False;
     163           0 :     for( ; *pArr; ++pArr )
     164           0 :         if( *pArr == c )
     165             :         {
     166           0 :             bRet = sal_True;
     167           0 :             break;
     168             :         }
     169           0 :     return bRet;
     170             : }
     171             : 
     172           0 : SvxAutoCorrDoc::~SvxAutoCorrDoc()
     173             : {
     174           0 : }
     175             :     // Is called by the functions:
     176             :     //  - FnCptlSttWrd
     177             :     //  - FnCptlSttSntnc
     178             :     // after the exchange of characters. then the words can maybe be inserted
     179             :     // into the exception list.
     180           0 : void SvxAutoCorrDoc::SaveCpltSttWord( sal_uLong, xub_StrLen, const String&,
     181             :                                         sal_Unicode )
     182             : {
     183           0 : }
     184             : 
     185           0 : LanguageType SvxAutoCorrDoc::GetLanguage( xub_StrLen , sal_Bool ) const
     186             : {
     187           0 :     return LANGUAGE_SYSTEM;
     188             : }
     189             : 
     190          10 : static const LanguageTag& GetAppLang()
     191             : {
     192          10 :     return Application::GetSettings().GetLanguageTag();
     193             : }
     194           0 : static LocaleDataWrapper& GetLocaleDataWrapper( sal_uInt16 nLang )
     195             : {
     196           0 :     static LocaleDataWrapper aLclDtWrp( GetAppLang() );
     197           0 :     LanguageTag aLcl( nLang );
     198           0 :     const LanguageTag& rLcl = aLclDtWrp.getLoadedLanguageTag();
     199           0 :     if( aLcl != rLcl )
     200           0 :         aLclDtWrp.setLanguageTag( aLcl );
     201           0 :     return aLclDtWrp;
     202             : }
     203           0 : static TransliterationWrapper& GetIgnoreTranslWrapper()
     204             : {
     205             :     static int bIsInit = 0;
     206             :     static TransliterationWrapper aWrp( ::comphelper::getProcessComponentContext(),
     207             :                 ::com::sun::star::i18n::TransliterationModules_IGNORE_KANA |
     208           0 :                 ::com::sun::star::i18n::TransliterationModules_IGNORE_WIDTH );
     209           0 :     if( !bIsInit )
     210             :     {
     211           0 :         aWrp.loadModuleIfNeeded( GetAppLang().getLanguageType() );
     212           0 :         bIsInit = 1;
     213             :     }
     214           0 :     return aWrp;
     215             : }
     216           0 : static CollatorWrapper& GetCollatorWrapper()
     217             : {
     218             :     static int bIsInit = 0;
     219           0 :     static CollatorWrapper aCollWrp( ::comphelper::getProcessComponentContext() );
     220           0 :     if( !bIsInit )
     221             :     {
     222           0 :         aCollWrp.loadDefaultCollator( GetAppLang().getLocale(), 0 );
     223           0 :         bIsInit = 1;
     224             :     }
     225           0 :     return aCollWrp;
     226             : }
     227             : 
     228          20 : static void lcl_ClearTable(boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists>& rLangTable)
     229             : {
     230          20 :     rLangTable.clear();
     231          20 : }
     232             : 
     233           0 : sal_Bool SvxAutoCorrect::IsAutoCorrectChar( sal_Unicode cChar )
     234             : {
     235             :     return  cChar == '\0' || cChar == '\t' || cChar == 0x0a ||
     236             :             cChar == ' '  || cChar == '\'' || cChar == '\"' ||
     237             :             cChar == '*'  || cChar == '_'  || cChar == '%' ||
     238             :             cChar == '.'  || cChar == ','  || cChar == ';' ||
     239           0 :             cChar == ':'  || cChar == '?' || cChar == '!' || cChar == '/';
     240             : }
     241             : 
     242           0 : sal_Bool SvxAutoCorrect::NeedsHardspaceAutocorr( sal_Unicode cChar )
     243             : {
     244             :     return cChar == '%' || cChar == ';' || cChar == ':'  || cChar == '?' || cChar == '!' ||
     245           0 :         cChar == '/' /*case for the urls exception*/;
     246             : }
     247             : 
     248          10 : long SvxAutoCorrect::GetDefaultFlags()
     249             : {
     250             :     long nRet = Autocorrect
     251             :                     | CptlSttSntnc
     252             :                     | CptlSttWrd
     253             :                     | ChgOrdinalNumber
     254             :                     | ChgToEnEmDash
     255             :                     | AddNonBrkSpace
     256             :                     | ChgWeightUnderl
     257             :                     | SetINetAttr
     258             :                     | ChgQuotes
     259             :                     | SaveWordCplSttLst
     260             :                     | SaveWordWrdSttLst
     261          10 :                     | CorrectCapsLock;
     262          10 :     LanguageType eLang = GetAppLang().getLanguageType();
     263          10 :     switch( eLang )
     264             :     {
     265             :     case LANGUAGE_ENGLISH:
     266             :     case LANGUAGE_ENGLISH_US:
     267             :     case LANGUAGE_ENGLISH_UK:
     268             :     case LANGUAGE_ENGLISH_AUS:
     269             :     case LANGUAGE_ENGLISH_CAN:
     270             :     case LANGUAGE_ENGLISH_NZ:
     271             :     case LANGUAGE_ENGLISH_EIRE:
     272             :     case LANGUAGE_ENGLISH_SAFRICA:
     273             :     case LANGUAGE_ENGLISH_JAMAICA:
     274             :     case LANGUAGE_ENGLISH_CARRIBEAN:
     275          10 :         nRet &= ~(ChgQuotes|ChgSglQuotes);
     276          10 :         break;
     277             :     }
     278          10 :     return nRet;
     279             : }
     280             : 
     281             : 
     282          10 : SvxAutoCorrect::SvxAutoCorrect( const String& rShareAutocorrFile,
     283             :                                 const String& rUserAutocorrFile )
     284             :     : sShareAutoCorrFile( rShareAutocorrFile ),
     285             :     sUserAutoCorrFile( rUserAutocorrFile ),
     286          10 :     pLangTable( new boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists> ),
     287             :     pCharClass( 0 ), bRunNext( false ),
     288          20 :     cStartDQuote( 0 ), cEndDQuote( 0 ), cStartSQuote( 0 ), cEndSQuote( 0 )
     289             : {
     290          10 :     nFlags = SvxAutoCorrect::GetDefaultFlags();
     291             : 
     292          10 :     cEmDash = 0x2014;
     293          10 :     cEnDash = 0x2013;
     294          10 : }
     295             : 
     296          10 : SvxAutoCorrect::SvxAutoCorrect( const SvxAutoCorrect& rCpy )
     297             : :   sShareAutoCorrFile( rCpy.sShareAutoCorrFile ),
     298             :     sUserAutoCorrFile( rCpy.sUserAutoCorrFile ),
     299             : 
     300             :     aSwFlags( rCpy.aSwFlags ),
     301             : 
     302          10 :     pLangTable( new boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists> ),
     303             :     pCharClass( 0 ), bRunNext( false ),
     304             : 
     305             :     nFlags( rCpy.nFlags & ~(ChgWordLstLoad|CplSttLstLoad|WrdSttLstLoad)),
     306             :     cStartDQuote( rCpy.cStartDQuote ), cEndDQuote( rCpy.cEndDQuote ),
     307             :     cStartSQuote( rCpy.cStartSQuote ), cEndSQuote( rCpy.cEndSQuote ),
     308          20 :     cEmDash( rCpy.cEmDash ), cEnDash( rCpy.cEnDash )
     309             : {
     310          10 : }
     311             : 
     312             : 
     313          50 : SvxAutoCorrect::~SvxAutoCorrect()
     314             : {
     315          20 :     lcl_ClearTable(*pLangTable);
     316          20 :     delete pLangTable;
     317          20 :     delete pCharClass;
     318          30 : }
     319             : 
     320           0 : void SvxAutoCorrect::_GetCharClass( LanguageType eLang )
     321             : {
     322           0 :     delete pCharClass;
     323           0 :     pCharClass = new CharClass( LanguageTag( eLang ));
     324           0 :     eCharClassLang = eLang;
     325           0 : }
     326             : 
     327          20 : void SvxAutoCorrect::SetAutoCorrFlag( long nFlag, sal_Bool bOn )
     328             : {
     329          20 :     long nOld = nFlags;
     330             :     nFlags = bOn ? nFlags | nFlag
     331          20 :                  : nFlags & ~nFlag;
     332             : 
     333          20 :     if( !bOn )
     334             :     {
     335          10 :         if( (nOld & CptlSttSntnc) != (nFlags & CptlSttSntnc) )
     336           0 :             nFlags &= ~CplSttLstLoad;
     337          10 :         if( (nOld & CptlSttWrd) != (nFlags & CptlSttWrd) )
     338           0 :             nFlags &= ~WrdSttLstLoad;
     339          10 :         if( (nOld & Autocorrect) != (nFlags & Autocorrect) )
     340           0 :             nFlags &= ~ChgWordLstLoad;
     341             :     }
     342          20 : }
     343             : 
     344             : 
     345             :     // Two capital letters at the beginning of word?
     346           0 : sal_Bool SvxAutoCorrect::FnCptlSttWrd( SvxAutoCorrDoc& rDoc, const String& rTxt,
     347             :                                     xub_StrLen nSttPos, xub_StrLen nEndPos,
     348             :                                     LanguageType eLang )
     349             : {
     350           0 :     sal_Bool bRet = sal_False;
     351           0 :     CharClass& rCC = GetCharClass( eLang );
     352             : 
     353             :     // Delete all non alphanumeric. Test the characters at the beginning/end of
     354             :     // the word ( recognizes: "(min.", "/min.", and so on.)
     355           0 :     for( ; nSttPos < nEndPos; ++nSttPos )
     356           0 :         if( rCC.isLetterNumeric( rTxt, nSttPos ))
     357           0 :             break;
     358           0 :     for( ; nSttPos < nEndPos; --nEndPos )
     359           0 :         if( rCC.isLetterNumeric( rTxt, nEndPos - 1 ))
     360           0 :             break;
     361             : 
     362             :     // Two capital letters at the beginning of word?
     363           0 :     if( nSttPos+2 < nEndPos &&
     364           0 :         IsUpperLetter( rCC.getCharacterType( rTxt, nSttPos )) &&
     365           0 :         IsUpperLetter( rCC.getCharacterType( rTxt, ++nSttPos )) &&
     366             :         // Is the third character a lower case
     367           0 :         IsLowerLetter( rCC.getCharacterType( rTxt, nSttPos +1 )) &&
     368             :         // Do not replace special attributes
     369           0 :         0x1 != rTxt.GetChar( nSttPos ) && 0x2 != rTxt.GetChar( nSttPos ))
     370             :     {
     371             :         // test if the word is in an exception list
     372           0 :         String sWord( rTxt.Copy( nSttPos - 1, nEndPos - nSttPos + 1 ));
     373           0 :         if( !FindInWrdSttExceptList(eLang, sWord) )
     374             :         {
     375             :             // Check that word isn't correctly spelled before correcting:
     376             :             ::com::sun::star::uno::Reference<
     377             :                 ::com::sun::star::linguistic2::XSpellChecker1 > xSpeller =
     378           0 :                 SvxGetSpellChecker();
     379           0 :             if( xSpeller->hasLanguage(eLang) )
     380             :             {
     381           0 :                 Sequence< ::com::sun::star::beans::PropertyValue > aEmptySeq;
     382           0 :                 if (!xSpeller->spell(sWord, eLang, aEmptySeq).is())
     383             :                 {
     384           0 :                     return false;
     385           0 :                 }
     386             :             }
     387           0 :             sal_Unicode cSave = rTxt.GetChar( nSttPos );
     388           0 :             rtl::OUString sChar( cSave );
     389           0 :             sChar = rCC.lowercase( sChar );
     390           0 :             if( sChar[0] != cSave && rDoc.ReplaceRange( nSttPos, 1, sChar ))
     391             :             {
     392           0 :                 if( SaveWordWrdSttLst & nFlags )
     393           0 :                     rDoc.SaveCpltSttWord( CptlSttWrd, nSttPos, sWord, cSave );
     394           0 :                 bRet = sal_True;
     395           0 :             }
     396           0 :         }
     397             :     }
     398           0 :     return bRet;
     399             : }
     400             : 
     401             : 
     402           0 : sal_Bool SvxAutoCorrect::FnChgOrdinalNumber(
     403             :                                 SvxAutoCorrDoc& rDoc, const String& rTxt,
     404             :                                 xub_StrLen nSttPos, xub_StrLen nEndPos,
     405             :                                 LanguageType eLang )
     406             : {
     407             : // 1st, 2nd, 3rd, 4 - 0th
     408             : // 201th or 201st
     409             : // 12th or 12nd
     410           0 :     CharClass& rCC = GetCharClass( eLang );
     411           0 :     sal_Bool bChg = sal_False;
     412             : 
     413           0 :     for( ; nSttPos < nEndPos; ++nSttPos )
     414           0 :         if( !lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nSttPos ) ))
     415           0 :             break;
     416           0 :     for( ; nSttPos < nEndPos; --nEndPos )
     417           0 :         if( !lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nEndPos - 1 ) ))
     418           0 :             break;
     419             : 
     420             : 
     421             :     // Get the last number in the string to check
     422           0 :     xub_StrLen nNumEnd = nEndPos;
     423           0 :     bool foundEnd = false;
     424           0 :     bool validNumber = true;
     425           0 :     xub_StrLen i = nEndPos;
     426             : 
     427           0 :     while ( i > nSttPos )
     428             :     {
     429           0 :         i--;
     430           0 :         bool isDigit = rCC.isDigit( rTxt, i );
     431           0 :         if ( foundEnd )
     432           0 :             validNumber |= isDigit;
     433             : 
     434           0 :         if ( isDigit && !foundEnd )
     435             :         {
     436           0 :             foundEnd = true;
     437           0 :             nNumEnd = i;
     438             :         }
     439             :     }
     440             : 
     441           0 :     if ( foundEnd && validNumber ) {
     442           0 :         sal_Int32 nNum = rTxt.Copy( nSttPos, nNumEnd - nSttPos + 1 ).ToInt32( );
     443             : 
     444             :         // Check if the characters after that number correspond to the ordinal suffix
     445           0 :         rtl::OUString sServiceName("com.sun.star.i18n.OrdinalSuffix");
     446             :         uno::Reference< i18n::XOrdinalSuffix > xOrdSuffix(
     447           0 :                 comphelper::getProcessServiceFactory()->createInstance( sServiceName ),
     448           0 :                 uno::UNO_QUERY );
     449             : 
     450           0 :         if ( xOrdSuffix.is( ) )
     451             :         {
     452           0 :             uno::Sequence< rtl::OUString > aSuffixes = xOrdSuffix->getOrdinalSuffix( nNum, rCC.getLanguageTag().getLocale( ) );
     453           0 :             for ( sal_Int32 nSuff = 0; nSuff < aSuffixes.getLength(); nSuff++ )
     454             :             {
     455           0 :                 String sSuffix( aSuffixes[ nSuff ] );
     456           0 :                 String sEnd = rTxt.Copy( nNumEnd + 1, nEndPos - nNumEnd - 1 );
     457             : 
     458           0 :                 if ( sSuffix == sEnd )
     459             :                 {
     460             :                     // Check if the ordinal suffix has to be set as super script
     461           0 :                     if ( rCC.isLetter( sSuffix ) )
     462             :                     {
     463             :                         // Do the change
     464             :                         SvxEscapementItem aSvxEscapementItem( DFLT_ESC_AUTO_SUPER,
     465           0 :                                                             DFLT_ESC_PROP, SID_ATTR_CHAR_ESCAPEMENT );
     466             :                         rDoc.SetAttr( nNumEnd + 1 , nEndPos,
     467             :                                         SID_ATTR_CHAR_ESCAPEMENT,
     468           0 :                                         aSvxEscapementItem);
     469             :                     }
     470             :                 }
     471           0 :             }
     472           0 :         }
     473             : 
     474             :     }
     475           0 :     return bChg;
     476             : }
     477             : 
     478             : 
     479           0 : sal_Bool SvxAutoCorrect::FnChgToEnEmDash(
     480             :                                 SvxAutoCorrDoc& rDoc, const String& rTxt,
     481             :                                 xub_StrLen nSttPos, xub_StrLen nEndPos,
     482             :                                 LanguageType eLang )
     483             : {
     484           0 :     sal_Bool bRet = sal_False;
     485           0 :     CharClass& rCC = GetCharClass( eLang );
     486           0 :     if (eLang == LANGUAGE_SYSTEM)
     487           0 :         eLang = GetAppLang().getLanguageType();
     488           0 :     bool bAlwaysUseEmDash = (cEmDash && (eLang == LANGUAGE_RUSSIAN || eLang == LANGUAGE_UKRAINIAN));
     489             : 
     490             :     // replace " - " or " --" with "enDash"
     491           0 :     if( cEnDash && 1 < nSttPos && 1 <= nEndPos - nSttPos )
     492             :     {
     493           0 :         sal_Unicode cCh = rTxt.GetChar( nSttPos );
     494           0 :         if( '-' == cCh )
     495             :         {
     496           0 :             if( ' ' == rTxt.GetChar( nSttPos-1 ) &&
     497           0 :                 '-' == rTxt.GetChar( nSttPos+1 ))
     498             :             {
     499             :                 xub_StrLen n;
     500           0 :                 for( n = nSttPos+2; n < nEndPos && lcl_IsInAsciiArr(
     501           0 :                             sImplSttSkipChars,(cCh = rTxt.GetChar( n )));
     502             :                         ++n )
     503             :                     ;
     504             : 
     505             :                 // found: " --[<AnySttChars>][A-z0-9]
     506           0 :                 if( rCC.isLetterNumeric( rtl::OUString(cCh) ) )
     507             :                 {
     508           0 :                     for( n = nSttPos-1; n && lcl_IsInAsciiArr(
     509           0 :                             sImplEndSkipChars,(cCh = rTxt.GetChar( --n ))); )
     510             :                         ;
     511             : 
     512             :                     // found: "[A-z0-9][<AnyEndChars>] --[<AnySttChars>][A-z0-9]
     513           0 :                     if( rCC.isLetterNumeric( rtl::OUString(cCh) ))
     514             :                     {
     515           0 :                         rDoc.Delete( nSttPos, nSttPos + 2 );
     516           0 :                         rDoc.Insert( nSttPos, bAlwaysUseEmDash ? rtl::OUString(cEmDash) : rtl::OUString(cEnDash) );
     517           0 :                         bRet = sal_True;
     518             :                     }
     519             :                 }
     520             :             }
     521             :         }
     522           0 :         else if( 3 < nSttPos &&
     523           0 :                  ' ' == rTxt.GetChar( nSttPos-1 ) &&
     524           0 :                  '-' == rTxt.GetChar( nSttPos-2 ))
     525             :         {
     526           0 :             xub_StrLen n, nLen = 1, nTmpPos = nSttPos - 2;
     527           0 :             if( '-' == ( cCh = rTxt.GetChar( nTmpPos-1 )) )
     528             :             {
     529           0 :                 --nTmpPos;
     530           0 :                 ++nLen;
     531           0 :                 cCh = rTxt.GetChar( nTmpPos-1 );
     532             :             }
     533           0 :             if( ' ' == cCh )
     534             :             {
     535           0 :                 for( n = nSttPos; n < nEndPos && lcl_IsInAsciiArr(
     536           0 :                             sImplSttSkipChars,(cCh = rTxt.GetChar( n )));
     537             :                         ++n )
     538             :                     ;
     539             : 
     540             :                 // found: " - [<AnySttChars>][A-z0-9]
     541           0 :                 if( rCC.isLetterNumeric( rtl::OUString(cCh) ) )
     542             :                 {
     543           0 :                     cCh = ' ';
     544           0 :                     for( n = nTmpPos-1; n && lcl_IsInAsciiArr(
     545           0 :                             sImplEndSkipChars,(cCh = rTxt.GetChar( --n ))); )
     546             :                             ;
     547             :                     // found: "[A-z0-9][<AnyEndChars>] - [<AnySttChars>][A-z0-9]
     548           0 :                     if( rCC.isLetterNumeric( rtl::OUString(cCh) ))
     549             :                     {
     550           0 :                         rDoc.Delete( nTmpPos, nTmpPos + nLen );
     551           0 :                         rDoc.Insert( nTmpPos, bAlwaysUseEmDash ? rtl::OUString(cEmDash) : rtl::OUString(cEnDash) );
     552           0 :                         bRet = sal_True;
     553             :                     }
     554             :                 }
     555             :             }
     556             :         }
     557             :     }
     558             : 
     559             :     // Replace [A-z0-9]--[A-z0-9] double dash with "emDash" or "enDash".
     560             :     // Finnish and Hungarian use enDash instead of emDash.
     561           0 :     bool bEnDash = (eLang == LANGUAGE_HUNGARIAN || eLang == LANGUAGE_FINNISH);
     562           0 :     if( ((cEmDash && !bEnDash) || (cEnDash && bEnDash)) && 4 <= nEndPos - nSttPos )
     563             :     {
     564           0 :         String sTmp( rTxt.Copy( nSttPos, nEndPos - nSttPos ) );
     565           0 :         xub_StrLen nFndPos = sTmp.SearchAscii( "--" );
     566           0 :         if( STRING_NOTFOUND != nFndPos && nFndPos &&
     567           0 :             nFndPos + 2 < sTmp.Len() &&
     568           0 :             ( rCC.isLetterNumeric( sTmp, nFndPos - 1 ) ||
     569           0 :               lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nFndPos - 1 ) )) &&
     570           0 :             ( rCC.isLetterNumeric( sTmp, nFndPos + 2 ) ||
     571           0 :             lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nFndPos + 2 ) )))
     572             :         {
     573           0 :             nSttPos = nSttPos + nFndPos;
     574           0 :             rDoc.Delete( nSttPos, nSttPos + 2 );
     575           0 :             rDoc.Insert( nSttPos, (bEnDash ? rtl::OUString(cEnDash) : rtl::OUString(cEmDash)) );
     576           0 :             bRet = sal_True;
     577           0 :         }
     578             :     }
     579           0 :     return bRet;
     580             : }
     581             : 
     582             : #ifdef _MSC_VER
     583             : #pragma warning(push)
     584             : #pragma warning(disable: 4706) // assignment within conditional expression
     585             : #endif
     586             : 
     587           0 : sal_Bool SvxAutoCorrect::FnAddNonBrkSpace(
     588             :                                 SvxAutoCorrDoc& rDoc, const String& rTxt,
     589             :                                 xub_StrLen, xub_StrLen nEndPos,
     590             :                                 LanguageType eLang )
     591             : {
     592           0 :     bool bRet = false;
     593             : 
     594           0 :     CharClass& rCC = GetCharClass( eLang );
     595           0 :     const lang::Locale rLocale = rCC.getLanguageTag().getLocale( );
     596             : 
     597           0 :     if ( rLocale.Language == OUString( "fr" ) )
     598             :     {
     599           0 :         bool bFrCA = rLocale.Country == OUString( "CA" );
     600           0 :         OUString allChars = OUString( ":;?!%" );
     601           0 :         OUString chars( allChars );
     602           0 :         if ( bFrCA )
     603           0 :             chars = OUString( ":" );
     604             : 
     605           0 :         sal_Unicode cChar = rTxt.GetChar( nEndPos );
     606           0 :         bool bHasSpace = chars.indexOf( cChar ) != -1;
     607           0 :         bool bIsSpecial = allChars.indexOf( cChar ) != -1;
     608           0 :         if ( bIsSpecial )
     609             :         {
     610             :             // Get the last word delimiter position
     611           0 :             xub_StrLen nSttWdPos = nEndPos;
     612           0 :             bool bWasWordDelim = false;
     613           0 :             while( nSttWdPos && !(bWasWordDelim = IsWordDelim( rTxt.GetChar( --nSttWdPos ))))
     614             :                 ;
     615             : 
     616           0 :             if(INetURLObject::CompareProtocolScheme(rTxt.Copy(nSttWdPos + (bWasWordDelim ? 1 : 0), nEndPos - nSttWdPos + 1)) != INET_PROT_NOT_VALID) {
     617           0 :                 return sal_False;
     618             :             }
     619             : 
     620             : 
     621             :             // Check the presence of "://" in the word
     622           0 :             xub_StrLen nStrPos = rTxt.Search( rtl::OUString( "://" ), nSttWdPos + 1 );
     623           0 :             if ( STRING_NOTFOUND == nStrPos && nEndPos > 0 )
     624             :             {
     625             :                 // Check the previous char
     626           0 :                 sal_Unicode cPrevChar = rTxt.GetChar( nEndPos - 1 );
     627           0 :                 if ( ( chars.indexOf( cPrevChar ) == -1 ) && cPrevChar != '\t' )
     628             :                 {
     629             :                     // Remove any previous normal space
     630           0 :                     xub_StrLen nPos = nEndPos - 1;
     631           0 :                     while ( cPrevChar == ' ' || cPrevChar == CHAR_HARDBLANK )
     632             :                     {
     633           0 :                         if ( nPos == 0 ) break;
     634           0 :                         nPos--;
     635           0 :                         cPrevChar = rTxt.GetChar( nPos );
     636             :                     }
     637             : 
     638           0 :                     nPos++;
     639           0 :                     if ( nEndPos - nPos > 0 )
     640           0 :                         rDoc.Delete( nPos, nEndPos );
     641             : 
     642             :                     // Add the non-breaking space at the end pos
     643           0 :                     if ( bHasSpace )
     644           0 :                         rDoc.Insert( nPos, rtl::OUString(CHAR_HARDBLANK) );
     645           0 :                     bRunNext = true;
     646           0 :                     bRet = true;
     647             :                 }
     648           0 :                 else if ( chars.indexOf( cPrevChar ) != -1 )
     649           0 :                     bRunNext = true;
     650             :             }
     651             :         }
     652           0 :         else if ( cChar == '/' && nEndPos > 1 && rTxt.Len() > (nEndPos - 1) )
     653             :         {
     654             :             // Remove the hardspace right before to avoid formatting URLs
     655           0 :             sal_Unicode cPrevChar = rTxt.GetChar( nEndPos - 1 );
     656           0 :             sal_Unicode cMaybeSpaceChar = rTxt.GetChar( nEndPos - 2 );
     657           0 :             if ( cPrevChar == ':' && cMaybeSpaceChar == CHAR_HARDBLANK )
     658             :             {
     659           0 :                 rDoc.Delete( nEndPos - 2, nEndPos - 1 );
     660           0 :                 bRet = true;
     661             :             }
     662           0 :         }
     663             :     }
     664             : 
     665           0 :     return bRet;
     666             : }
     667             : 
     668             : #ifdef _MSC_VER
     669             : #pragma warning(pop)
     670             : #endif
     671             : 
     672           0 : sal_Bool SvxAutoCorrect::FnSetINetAttr( SvxAutoCorrDoc& rDoc, const String& rTxt,
     673             :                                     xub_StrLen nSttPos, xub_StrLen nEndPos,
     674             :                                     LanguageType eLang )
     675             : {
     676           0 :     sal_Int32 nStart(nSttPos);
     677           0 :     sal_Int32 nEnd(nEndPos);
     678             : 
     679             :     String sURL( URIHelper::FindFirstURLInText( rTxt, nStart, nEnd,
     680           0 :                                                 GetCharClass( eLang ) ));
     681           0 :     nSttPos = (xub_StrLen)nStart;
     682           0 :     nEndPos = (xub_StrLen)nEnd;
     683           0 :     sal_Bool bRet = 0 != sURL.Len();
     684           0 :     if( bRet )          // also Attribut setzen:
     685           0 :         rDoc.SetINetAttr( nSttPos, nEndPos, sURL );
     686           0 :     return bRet;
     687             : }
     688             : 
     689             : 
     690           0 : sal_Bool SvxAutoCorrect::FnChgWeightUnderl( SvxAutoCorrDoc& rDoc, const String& rTxt,
     691             :                                         xub_StrLen, xub_StrLen nEndPos,
     692             :                                         LanguageType eLang )
     693             : {
     694             :     // Condition:
     695             :     //  at the beginning:   _ or * after Space with the folloeing !Space
     696             :     //  at the end:         _ or * before Space (word delimiter?)
     697             : 
     698           0 :     sal_Unicode c, cInsChar = rTxt.GetChar( nEndPos );  // underline or bold
     699           0 :     if( ++nEndPos != rTxt.Len() &&
     700           0 :         !IsWordDelim( rTxt.GetChar( nEndPos ) ) )
     701           0 :         return sal_False;
     702             : 
     703           0 :     --nEndPos;
     704             : 
     705           0 :     sal_Bool bAlphaNum = sal_False;
     706           0 :     xub_StrLen nPos = nEndPos, nFndPos = STRING_NOTFOUND;
     707           0 :     CharClass& rCC = GetCharClass( eLang );
     708             : 
     709           0 :     while( nPos )
     710             :     {
     711           0 :         switch( c = rTxt.GetChar( --nPos ) )
     712             :         {
     713             :         case '_':
     714             :         case '*':
     715           0 :             if( c == cInsChar )
     716             :             {
     717           0 :                 if( bAlphaNum && nPos+1 < nEndPos && ( !nPos ||
     718           0 :                     IsWordDelim( rTxt.GetChar( nPos-1 ))) &&
     719           0 :                     !IsWordDelim( rTxt.GetChar( nPos+1 )))
     720           0 :                         nFndPos = nPos;
     721             :                 else
     722             :                     // Condition is not satisfied, so cancel
     723           0 :                     nFndPos = STRING_NOTFOUND;
     724           0 :                 nPos = 0;
     725             :             }
     726           0 :             break;
     727             :         default:
     728           0 :             if( !bAlphaNum )
     729           0 :                 bAlphaNum = rCC.isLetterNumeric( rTxt, nPos );
     730             :         }
     731             :     }
     732             : 
     733           0 :     if( STRING_NOTFOUND != nFndPos )
     734             :     {
     735             :         // Span the Attribute over the area and delete the Character found at
     736             :         // the end.
     737           0 :         if( '*' == cInsChar )           // Bold
     738             :         {
     739           0 :             SvxWeightItem aSvxWeightItem( WEIGHT_BOLD, SID_ATTR_CHAR_WEIGHT );
     740             :             rDoc.SetAttr( nFndPos + 1, nEndPos,
     741             :                             SID_ATTR_CHAR_WEIGHT,
     742           0 :                             aSvxWeightItem);
     743             :         }
     744             :         else                            // underline
     745             :         {
     746           0 :             SvxUnderlineItem aSvxUnderlineItem( UNDERLINE_SINGLE, SID_ATTR_CHAR_UNDERLINE );
     747             :             rDoc.SetAttr( nFndPos + 1, nEndPos,
     748             :                             SID_ATTR_CHAR_UNDERLINE,
     749           0 :                             aSvxUnderlineItem);
     750             :         }
     751           0 :         rDoc.Delete( nEndPos, nEndPos + 1 );
     752           0 :         rDoc.Delete( nFndPos, nFndPos + 1 );
     753             :     }
     754             : 
     755           0 :     return STRING_NOTFOUND != nFndPos;
     756             : }
     757             : 
     758             : 
     759           0 : sal_Bool SvxAutoCorrect::FnCptlSttSntnc( SvxAutoCorrDoc& rDoc,
     760             :                                     const String& rTxt, sal_Bool bNormalPos,
     761             :                                     xub_StrLen nSttPos, xub_StrLen nEndPos,
     762             :                                     LanguageType eLang )
     763             : {
     764             : 
     765           0 :     if( !rTxt.Len() || nEndPos <= nSttPos )
     766           0 :         return sal_False;
     767             : 
     768           0 :     CharClass& rCC = GetCharClass( eLang );
     769           0 :     String aText( rTxt );
     770           0 :     const sal_Unicode *pStart = aText.GetBuffer(),
     771           0 :                       *pStr = pStart + nEndPos,
     772           0 :                       *pWordStt = 0,
     773           0 :                       *pDelim = 0;
     774             : 
     775           0 :     sal_Bool bAtStart = sal_False;
     776           0 :     do {
     777           0 :         --pStr;
     778           0 :         if( rCC.isLetter(
     779           0 :                 aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) )
     780             :         {
     781           0 :             if( !pWordStt )
     782           0 :                 pDelim = pStr+1;
     783           0 :             pWordStt = pStr;
     784             :         }
     785           0 :         else if( pWordStt &&
     786             :                  !rCC.isDigit(
     787             :                      aText,
     788           0 :                      sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) )
     789             :         {
     790           0 :             if( lcl_IsInAsciiArr( sImplWordChars, *pStr ) &&
     791           0 :                 pWordStt - 1 == pStr &&
     792             :                 // Installation at beginning of paragraph. Replaced < by <= (#i38971#)
     793           0 :                 (long)(pStart + 1) <= (long)pStr &&
     794             :                 rCC.isLetter(
     795             :                     aText,
     796           0 :                     sal::static_int_cast< xub_StrLen >( pStr-1 - pStart ) ) )
     797           0 :                 pWordStt = --pStr;
     798             :             else
     799           0 :                 break;
     800             :         }
     801             :     } while( 0 == ( bAtStart = (pStart == pStr)) );
     802             : 
     803           0 :     if( !pWordStt ||
     804             :         rCC.isDigit(
     805           0 :             aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) ||
     806             :         IsUpperLetter(
     807             :             rCC.getCharacterType(
     808             :                 aText,
     809           0 :                 sal::static_int_cast< xub_StrLen >( pWordStt - pStart ) ) ) ||
     810           0 :         INetURLObject::CompareProtocolScheme(rTxt.Copy(pWordStt - pStart, pDelim - pWordStt + 1)) != INET_PROT_NOT_VALID ||
     811             :         0x1 == *pWordStt || 0x2 == *pWordStt )
     812           0 :         return sal_False;       // no character to be replaced, or already ok
     813             : 
     814           0 :     if( *pDelim && 2 >= pDelim - pWordStt &&
     815           0 :         lcl_IsInAsciiArr( ".-)>", *pDelim ) )
     816           0 :         return sal_False;
     817             : 
     818           0 :     if( !bAtStart ) // Still no beginning of a paragraph?
     819             :     {
     820           0 :         if ( IsWordDelim( *pStr ) )
     821             :         {
     822           0 :             while( 0 == ( bAtStart = (pStart == pStr--) ) && IsWordDelim( *pStr ))
     823             :                 ;
     824             :         }
     825             :         // Asian full stop, full width full stop, full width exclamation mark
     826             :         // and full width question marks are treated as word delimiters
     827           0 :         else if ( 0x3002 != *pStr && 0xFF0E != *pStr && 0xFF01 != *pStr &&
     828             :                   0xFF1F != *pStr )
     829           0 :             return sal_False; // no valid separator -> no replacement
     830             :     }
     831             : 
     832           0 :     if( bAtStart )  // at the beginning of a paragraph?
     833             :     {
     834             :         // Check out the previous paragraph, if it exists.
     835             :         // If so, then check to paragraph separator at the end.
     836           0 :         const String* pPrevPara = rDoc.GetPrevPara( bNormalPos );
     837           0 :         if( !pPrevPara )
     838             :         {
     839             :             // valid separator -> replace
     840           0 :             rtl::OUString sChar( *pWordStt );
     841           0 :             sChar = rCC.titlecase(sChar); //see fdo#56740
     842           0 :             return  !comphelper::string::equals(sChar, *pWordStt) &&
     843           0 :                     rDoc.ReplaceRange( xub_StrLen( pWordStt - pStart ), 1, sChar );
     844             :         }
     845             : 
     846           0 :         aText = *pPrevPara;
     847           0 :         bAtStart = sal_False;
     848           0 :         pStart = aText.GetBuffer();
     849           0 :         pStr = pStart + aText.Len();
     850             : 
     851           0 :         do {            // overwrite all blanks
     852           0 :             --pStr;
     853           0 :             if( !IsWordDelim( *pStr ))
     854           0 :                 break;
     855             :         } while( 0 == ( bAtStart = (pStart == pStr)) );
     856             : 
     857           0 :         if( bAtStart )
     858           0 :             return sal_False;  // no valid separator -> no replacement
     859             :     }
     860             : 
     861             :     // Found [ \t]+[A-Z0-9]+ until here. Test now on the paragraph separator.
     862             :     // all three can happen, but not more than once!
     863           0 :     const sal_Unicode* pExceptStt = 0;
     864           0 :     if( !bAtStart )
     865             :     {
     866           0 :         sal_Bool bWeiter = sal_True;
     867           0 :         int nFlag = C_NONE;
     868           0 :         do {
     869           0 :             switch( *pStr )
     870             :             {
     871             :             // Western and Asian full stop
     872             :             case '.':
     873             :             case 0x3002 :
     874             :             case 0xFF0E :
     875             :                 {
     876           0 :                     if( nFlag & C_FULL_STOP )
     877           0 :                         return sal_False;  // no valid separator -> no replacement
     878           0 :                     nFlag |= C_FULL_STOP;
     879           0 :                     pExceptStt = pStr;
     880             :                 }
     881           0 :                 break;
     882             :             case '!':
     883             :             case 0xFF01 :
     884             :                 {
     885           0 :                     if( nFlag & C_EXCLAMATION_MARK )
     886           0 :                         return sal_False;   // no valid separator -> no replacement
     887           0 :                     nFlag |= C_EXCLAMATION_MARK;
     888             :                 }
     889           0 :                 break;
     890             :             case '?':
     891             :             case 0xFF1F :
     892             :                 {
     893           0 :                     if( nFlag & C_QUESTION_MARK)
     894           0 :                         return sal_False;   // no valid separator -> no replacement
     895           0 :                     nFlag |= C_QUESTION_MARK;
     896             :                 }
     897           0 :                 break;
     898             :             default:
     899           0 :                 if( !nFlag )
     900           0 :                     return sal_False;       // no valid separator -> no replacement
     901             :                 else
     902           0 :                     bWeiter = sal_False;
     903           0 :                 break;
     904             :             }
     905             : 
     906           0 :             if( bWeiter && pStr-- == pStart )
     907             :             {
     908           0 :                 return sal_False;       // no valid separator -> no replacement
     909             :             }
     910             :         } while( bWeiter );
     911           0 :         if( C_FULL_STOP != nFlag )
     912           0 :             pExceptStt = 0;
     913             :     }
     914             : 
     915           0 :     if( 2 > ( pStr - pStart ) )
     916           0 :         return sal_False;
     917             : 
     918           0 :     if( !rCC.isLetterNumeric(
     919           0 :             aText, sal::static_int_cast< xub_StrLen >( pStr-- - pStart ) ) )
     920             :     {
     921           0 :         sal_Bool bValid = sal_False, bAlphaFnd = sal_False;
     922           0 :         const sal_Unicode* pTmpStr = pStr;
     923           0 :         while( !bValid )
     924             :         {
     925           0 :             if( rCC.isDigit(
     926             :                     aText,
     927           0 :                     sal::static_int_cast< xub_StrLen >( pTmpStr - pStart ) ) )
     928             :             {
     929           0 :                 bValid = sal_True;
     930           0 :                 pStr = pTmpStr - 1;
     931             :             }
     932           0 :             else if( rCC.isLetter(
     933             :                          aText,
     934             :                          sal::static_int_cast< xub_StrLen >(
     935           0 :                              pTmpStr - pStart ) ) )
     936             :             {
     937           0 :                 if( bAlphaFnd )
     938             :                 {
     939           0 :                     bValid = sal_True;
     940           0 :                     pStr = pTmpStr;
     941             :                 }
     942             :                 else
     943           0 :                     bAlphaFnd = sal_True;
     944             :             }
     945           0 :             else if( bAlphaFnd || IsWordDelim( *pTmpStr ) )
     946           0 :                 break;
     947             : 
     948           0 :             if( pTmpStr == pStart )
     949           0 :                 break;
     950             : 
     951           0 :             --pTmpStr;
     952             :         }
     953             : 
     954           0 :         if( !bValid )
     955           0 :             return sal_False;       // no valid separator -> no replacement
     956             :     }
     957             : 
     958           0 :     sal_Bool bNumericOnly = '0' <= *(pStr+1) && *(pStr+1) <= '9';
     959             : 
     960             :     // Search for the beginning of the word
     961           0 :     while( !IsWordDelim( *pStr ))
     962             :     {
     963           0 :         if( bNumericOnly &&
     964             :             rCC.isLetter(
     965           0 :                 aText, sal::static_int_cast< xub_StrLen >( pStr - pStart ) ) )
     966           0 :             bNumericOnly = sal_False;
     967             : 
     968           0 :         if( pStart == pStr )
     969           0 :             break;
     970             : 
     971           0 :         --pStr;
     972             :     }
     973             : 
     974           0 :     if( bNumericOnly )      // consists of only numbers, then not
     975           0 :         return sal_False;
     976             : 
     977           0 :     if( IsWordDelim( *pStr ))
     978           0 :         ++pStr;
     979             : 
     980           0 :     String sWord;
     981             : 
     982             :     // check on the basis of the exception list
     983           0 :     if( pExceptStt )
     984             :     {
     985           0 :         sWord = rtl::OUString(pStr, pExceptStt - pStr + 1);
     986           0 :         if( FindInCplSttExceptList(eLang, sWord) )
     987           0 :             return sal_False;
     988             : 
     989             :         // Delete all non alphanumeric. Test the characters at the
     990             :         // beginning/end of the word ( recognizes: "(min.", "/min.", and so on.)
     991           0 :         String sTmp( sWord );
     992           0 :         while( sTmp.Len() &&
     993           0 :                 !rCC.isLetterNumeric( sTmp, 0 ) )
     994           0 :             sTmp.Erase( 0, 1 );
     995             : 
     996             :         // Remove all non alphanumeric characters towards the end up until
     997             :         // the last one.
     998           0 :         xub_StrLen nLen = sTmp.Len();
     999           0 :         while( nLen && !rCC.isLetterNumeric( sTmp, nLen-1 ) )
    1000           0 :             --nLen;
    1001           0 :         if( nLen + 1 < sTmp.Len() )
    1002           0 :             sTmp.Erase( nLen + 1 );
    1003             : 
    1004           0 :         if( sTmp.Len() && sTmp.Len() != sWord.Len() &&
    1005           0 :             FindInCplSttExceptList(eLang, sTmp))
    1006           0 :             return sal_False;
    1007             : 
    1008           0 :         if(FindInCplSttExceptList(eLang, sWord, sal_True))
    1009           0 :             return sal_False;
    1010             :     }
    1011             : 
    1012             :     // Ok, then replace
    1013           0 :     sal_Unicode cSave = *pWordStt;
    1014           0 :     nSttPos = sal::static_int_cast< xub_StrLen >( pWordStt - rTxt.GetBuffer() );
    1015           0 :     rtl::OUString sChar( cSave );
    1016           0 :     sChar = rCC.titlecase(sChar); //see fdo#56740
    1017           0 :     sal_Bool bRet = sChar[0] != cSave && rDoc.ReplaceRange( nSttPos, 1, sChar );
    1018             : 
    1019             :     // Parahaps someone wants to have the word
    1020           0 :     if( bRet && SaveWordCplSttLst & nFlags )
    1021           0 :         rDoc.SaveCpltSttWord( CptlSttSntnc, nSttPos, sWord, cSave );
    1022             : 
    1023           0 :     return bRet;
    1024             : }
    1025             : 
    1026           0 : bool SvxAutoCorrect::FnCorrectCapsLock( SvxAutoCorrDoc& rDoc, const String& rTxt,
    1027             :                                         xub_StrLen nSttPos, xub_StrLen nEndPos,
    1028             :                                         LanguageType eLang )
    1029             : {
    1030           0 :     if (nEndPos - nSttPos < 2)
    1031             :         // string must be at least 2-character long.
    1032           0 :         return false;
    1033             : 
    1034           0 :     CharClass& rCC = GetCharClass( eLang );
    1035             : 
    1036             :     // Check the first 2 letters.
    1037           0 :     if ( !IsLowerLetter(rCC.getCharacterType(rTxt, nSttPos)) )
    1038           0 :         return false;
    1039             : 
    1040           0 :     if ( !IsUpperLetter(rCC.getCharacterType(rTxt, nSttPos+1)) )
    1041           0 :         return false;
    1042             : 
    1043           0 :     String aConverted;
    1044           0 :     aConverted.Append( rCC.uppercase(rtl::OUString(rTxt.GetChar(nSttPos))) );
    1045           0 :     aConverted.Append( rCC.lowercase(rtl::OUString(rTxt.GetChar(nSttPos+1))) );
    1046             : 
    1047           0 :     for (xub_StrLen i = nSttPos+2; i < nEndPos; ++i)
    1048             :     {
    1049           0 :         if ( IsLowerLetter(rCC.getCharacterType(rTxt, i)) )
    1050             :             // A lowercase letter disqualifies the whole text.
    1051           0 :             return false;
    1052             : 
    1053           0 :         if ( IsUpperLetter(rCC.getCharacterType(rTxt, i)) )
    1054             :             // Another uppercase letter.  Convert it.
    1055           0 :             aConverted.Append(rCC.lowercase(rtl::OUString(rTxt.GetChar(i))));
    1056             :         else
    1057             :             // This is not an alphabetic letter.  Leave it as-is.
    1058           0 :             aConverted.Append(rTxt.GetChar(i));
    1059             :     }
    1060             : 
    1061             :     // Replace the word.
    1062           0 :     rDoc.Delete(nSttPos, nEndPos);
    1063           0 :     rDoc.Insert(nSttPos, aConverted);
    1064             : 
    1065           0 :     return true;
    1066             : }
    1067             : 
    1068             : 
    1069           0 : sal_Unicode SvxAutoCorrect::GetQuote( sal_Unicode cInsChar, sal_Bool bSttQuote,
    1070             :                                         LanguageType eLang ) const
    1071             : {
    1072             :     sal_Unicode cRet = bSttQuote ? ( '\"' == cInsChar
    1073             :                                     ? GetStartDoubleQuote()
    1074             :                                     : GetStartSingleQuote() )
    1075             :                                    : ( '\"' == cInsChar
    1076             :                                     ? GetEndDoubleQuote()
    1077           0 :                                     : GetEndSingleQuote() );
    1078           0 :     if( !cRet )
    1079             :     {
    1080             :         // then through the Language find the right character
    1081           0 :         if( LANGUAGE_NONE == eLang )
    1082           0 :             cRet = cInsChar;
    1083             :         else
    1084             :         {
    1085           0 :             LocaleDataWrapper& rLcl = GetLocaleDataWrapper( eLang );
    1086             :             String sRet( bSttQuote
    1087             :                             ? ( '\"' == cInsChar
    1088             :                                 ? rLcl.getDoubleQuotationMarkStart()
    1089             :                                 : rLcl.getQuotationMarkStart() )
    1090             :                             : ( '\"' == cInsChar
    1091             :                                 ? rLcl.getDoubleQuotationMarkEnd()
    1092           0 :                                 : rLcl.getQuotationMarkEnd() ));
    1093           0 :             cRet = sRet.Len() ? sRet.GetChar( 0 ) : cInsChar;
    1094             :         }
    1095             :     }
    1096           0 :     return cRet;
    1097             : }
    1098             : 
    1099           0 : void SvxAutoCorrect::InsertQuote( SvxAutoCorrDoc& rDoc, xub_StrLen nInsPos,
    1100             :                                     sal_Unicode cInsChar, sal_Bool bSttQuote,
    1101             :                                     sal_Bool bIns )
    1102             : {
    1103           0 :     LanguageType eLang = rDoc.GetLanguage( nInsPos, sal_False );
    1104           0 :     sal_Unicode cRet = GetQuote( cInsChar, bSttQuote, eLang );
    1105             : 
    1106           0 :     rtl::OUString sChg( cInsChar );
    1107           0 :     if( bIns )
    1108           0 :         rDoc.Insert( nInsPos, sChg );
    1109             :     else
    1110           0 :         rDoc.Replace( nInsPos, sChg );
    1111             : 
    1112           0 :     sChg = rtl::OUString(cRet);
    1113             : 
    1114           0 :     if( '\"' == cInsChar )
    1115             :     {
    1116           0 :         if( LANGUAGE_SYSTEM == eLang )
    1117           0 :             eLang = GetAppLang().getLanguageType();
    1118           0 :         switch( eLang )
    1119             :         {
    1120             :         case LANGUAGE_FRENCH:
    1121             :         case LANGUAGE_FRENCH_BELGIAN:
    1122             :         case LANGUAGE_FRENCH_CANADIAN:
    1123             :         case LANGUAGE_FRENCH_SWISS:
    1124             :         case LANGUAGE_FRENCH_LUXEMBOURG:
    1125             :             {
    1126           0 :                 rtl::OUString s( static_cast< sal_Unicode >(0xA0) );
    1127             :                     // UNICODE code for no break space
    1128           0 :                 if( rDoc.Insert( bSttQuote ? nInsPos+1 : nInsPos, s ))
    1129             :                 {
    1130           0 :                     if( !bSttQuote )
    1131           0 :                         ++nInsPos;
    1132           0 :                 }
    1133             :             }
    1134           0 :             break;
    1135             :         }
    1136             :     }
    1137             : 
    1138           0 :     rDoc.Replace( nInsPos, sChg );
    1139           0 : }
    1140             : 
    1141           0 : String SvxAutoCorrect::GetQuote( SvxAutoCorrDoc& rDoc, xub_StrLen nInsPos,
    1142             :                                 sal_Unicode cInsChar, sal_Bool bSttQuote )
    1143             : {
    1144           0 :     LanguageType eLang = rDoc.GetLanguage( nInsPos, sal_False );
    1145           0 :     sal_Unicode cRet = GetQuote( cInsChar, bSttQuote, eLang );
    1146             : 
    1147           0 :     String sRet = rtl::OUString(cRet);
    1148             : 
    1149           0 :     if( '\"' == cInsChar )
    1150             :     {
    1151           0 :         if( LANGUAGE_SYSTEM == eLang )
    1152           0 :             eLang = GetAppLang().getLanguageType();
    1153           0 :         switch( eLang )
    1154             :         {
    1155             :         case LANGUAGE_FRENCH:
    1156             :         case LANGUAGE_FRENCH_BELGIAN:
    1157             :         case LANGUAGE_FRENCH_CANADIAN:
    1158             :         case LANGUAGE_FRENCH_SWISS:
    1159             :         case LANGUAGE_FRENCH_LUXEMBOURG:
    1160           0 :             if( bSttQuote )
    1161           0 :                 sRet += ' ';
    1162             :             else
    1163           0 :                 sRet.Insert( ' ', 0 );
    1164           0 :             break;
    1165             :         }
    1166             :     }
    1167           0 :     return sRet;
    1168             : }
    1169             : 
    1170           0 : sal_uLong SvxAutoCorrect::AutoCorrect( SvxAutoCorrDoc& rDoc, const String& rTxt,
    1171             :                                     xub_StrLen nInsPos, sal_Unicode cChar,
    1172             :                                     sal_Bool bInsert, Window* pFrameWin )
    1173             : {
    1174           0 :     sal_uLong nRet = 0;
    1175           0 :     bool bIsNextRun = bRunNext;
    1176           0 :     bRunNext = false;  // if it was set, then it has to be turned off
    1177             : 
    1178             :     do{                                 // only for middle check loop !!
    1179           0 :         if( cChar )
    1180             :         {
    1181             :             // Prevent double space
    1182           0 :             if( nInsPos && ' ' == cChar &&
    1183           0 :                 IsAutoCorrFlag( IgnoreDoubleSpace ) &&
    1184           0 :                 ' ' == rTxt.GetChar( nInsPos - 1 ) )
    1185             :             {
    1186           0 :                 nRet = IgnoreDoubleSpace;
    1187             :                 break;
    1188             :             }
    1189             : 
    1190           0 :             sal_Bool bSingle = '\'' == cChar;
    1191             :             sal_Bool bIsReplaceQuote =
    1192           0 :                         (IsAutoCorrFlag( ChgQuotes ) && ('\"' == cChar )) ||
    1193           0 :                         (IsAutoCorrFlag( ChgSglQuotes ) && bSingle );
    1194           0 :             if( bIsReplaceQuote )
    1195             :             {
    1196             :                 sal_Unicode cPrev;
    1197             :                 sal_Bool bSttQuote = !nInsPos ||
    1198           0 :                         IsWordDelim( ( cPrev = rTxt.GetChar( nInsPos-1 ))) ||
    1199           0 :                         lcl_IsInAsciiArr( "([{", cPrev ) ||
    1200             :                         ( cEmDash && cEmDash == cPrev ) ||
    1201           0 :                         ( cEnDash && cEnDash == cPrev );
    1202             : 
    1203           0 :                 InsertQuote( rDoc, nInsPos, cChar, bSttQuote, bInsert );
    1204           0 :                 nRet = bSingle ? ChgSglQuotes : ChgQuotes;
    1205             :                 break;
    1206             :             }
    1207             : 
    1208           0 :             if( bInsert )
    1209           0 :                 rDoc.Insert( nInsPos, rtl::OUString(cChar) );
    1210             :             else
    1211           0 :                 rDoc.Replace( nInsPos, rtl::OUString(cChar) );
    1212             : 
    1213             :             // Hardspaces autocorrection
    1214           0 :             if ( IsAutoCorrFlag( AddNonBrkSpace ) )
    1215             :             {
    1216           0 :                 if ( NeedsHardspaceAutocorr( cChar ) &&
    1217           0 :                     FnAddNonBrkSpace( rDoc, rTxt, 0, nInsPos, rDoc.GetLanguage( nInsPos, sal_False ) ) )
    1218             :                 {
    1219           0 :                     nRet = AddNonBrkSpace;
    1220             :                 }
    1221           0 :                 else if ( bIsNextRun && !IsAutoCorrectChar( cChar ) )
    1222             :                 {
    1223             :                     // Remove the NBSP if it wasn't an autocorrection
    1224           0 :                     if ( nInsPos != 0 && NeedsHardspaceAutocorr( rTxt.GetChar( nInsPos - 1 ) ) &&
    1225             :                             cChar != ' ' && cChar != '\t' && cChar != CHAR_HARDBLANK )
    1226             :                     {
    1227             :                         // Look for the last HARD_SPACE
    1228           0 :                         xub_StrLen nPos = nInsPos - 1;
    1229           0 :                         bool bContinue = true;
    1230           0 :                         while ( bContinue )
    1231             :                         {
    1232           0 :                             const sal_Unicode cTmpChar = rTxt.GetChar( nPos );
    1233           0 :                             if ( cTmpChar == CHAR_HARDBLANK )
    1234             :                             {
    1235           0 :                                 rDoc.Delete( nPos, nPos + 1 );
    1236           0 :                                 nRet = AddNonBrkSpace;
    1237           0 :                                 bContinue = false;
    1238             :                             }
    1239           0 :                             else if ( !NeedsHardspaceAutocorr( cTmpChar ) || nPos == 0 )
    1240           0 :                                 bContinue = false;
    1241           0 :                             nPos--;
    1242             :                         }
    1243             :                     }
    1244             :                 }
    1245             :             }
    1246             :         }
    1247             : 
    1248           0 :         if( !nInsPos )
    1249             :             break;
    1250             : 
    1251           0 :         xub_StrLen nPos = nInsPos - 1;
    1252             : 
    1253           0 :         if( IsWordDelim( rTxt.GetChar( nPos )))
    1254             :             break;
    1255             : 
    1256             :         // Set bold or underline automatically?
    1257           0 :         if( '*' == cChar || '_' == cChar )
    1258             :         {
    1259           0 :             if( IsAutoCorrFlag( ChgWeightUnderl ) &&
    1260           0 :                 FnChgWeightUnderl( rDoc, rTxt, 0, nPos+1 ) )
    1261           0 :                 nRet = ChgWeightUnderl;
    1262             :             break;
    1263             :         }
    1264             : 
    1265           0 :         while( nPos && !IsWordDelim( rTxt.GetChar( --nPos )))
    1266             :             ;
    1267             : 
    1268             :         // Found a Paragraph-start or a Blank, search for the word shortcut in
    1269             :         // auto.
    1270           0 :         xub_StrLen nCapLttrPos = nPos+1;        // on the 1st Character
    1271           0 :         if( !nPos && !IsWordDelim( rTxt.GetChar( 0 )))
    1272           0 :             --nCapLttrPos;          // Absatz Anfang und kein Blank !
    1273             : 
    1274           0 :         LanguageType eLang = rDoc.GetLanguage( nCapLttrPos, sal_False );
    1275           0 :         if( LANGUAGE_SYSTEM == eLang )
    1276           0 :             eLang = MsLangId::getSystemLanguage();
    1277           0 :         CharClass& rCC = GetCharClass( eLang );
    1278             : 
    1279             :         // no symbol characters
    1280           0 :         if( lcl_IsSymbolChar( rCC, rTxt, nCapLttrPos, nInsPos ))
    1281             :             break;
    1282             : 
    1283           0 :         if( IsAutoCorrFlag( Autocorrect ) )
    1284             :         {
    1285           0 :             const String* pPara = 0;
    1286           0 :             const String** ppPara = IsAutoCorrFlag(CptlSttSntnc) ? &pPara : 0;
    1287             : 
    1288             :             sal_Bool bChgWord = rDoc.ChgAutoCorrWord( nCapLttrPos, nInsPos,
    1289           0 :                                                     *this, ppPara );
    1290           0 :             if( !bChgWord )
    1291             :             {
    1292           0 :                 xub_StrLen nCapLttrPos1 = nCapLttrPos, nInsPos1 = nInsPos;
    1293           0 :                 while( nCapLttrPos1 < nInsPos &&
    1294           0 :                         lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nCapLttrPos1 ) )
    1295             :                         )
    1296           0 :                         ++nCapLttrPos1;
    1297           0 :                 while( nCapLttrPos1 < nInsPos1 && nInsPos1 &&
    1298           0 :                         lcl_IsInAsciiArr( sImplEndSkipChars, rTxt.GetChar( nInsPos1-1 ) )
    1299             :                         )
    1300           0 :                         --nInsPos1;
    1301             : 
    1302           0 :                 if( (nCapLttrPos1 != nCapLttrPos || nInsPos1 != nInsPos ) &&
    1303             :                     nCapLttrPos1 < nInsPos1 &&
    1304           0 :                     rDoc.ChgAutoCorrWord( nCapLttrPos1, nInsPos1, *this, ppPara ))
    1305             :                 {
    1306           0 :                     bChgWord = sal_True;
    1307           0 :                     nCapLttrPos = nCapLttrPos1;
    1308             :                 }
    1309             :             }
    1310             : 
    1311           0 :             if( bChgWord )
    1312             :             {
    1313           0 :                 nRet = Autocorrect;
    1314           0 :                 if( pPara )
    1315             :                 {
    1316           0 :                     xub_StrLen nEnd = nCapLttrPos;
    1317           0 :                     while( nEnd < pPara->Len() &&
    1318           0 :                             !IsWordDelim( pPara->GetChar( nEnd )))
    1319           0 :                         ++nEnd;
    1320             : 
    1321             :                     // Capital letter at beginning of paragraph?
    1322           0 :                     if( IsAutoCorrFlag( CptlSttSntnc ) &&
    1323             :                         FnCptlSttSntnc( rDoc, *pPara, sal_False,
    1324           0 :                                                 nCapLttrPos, nEnd, eLang ) )
    1325           0 :                         nRet |= CptlSttSntnc;
    1326             : 
    1327           0 :                     if( IsAutoCorrFlag( ChgToEnEmDash ) &&
    1328           0 :                         FnChgToEnEmDash( rDoc, rTxt, nCapLttrPos, nEnd, eLang ) )
    1329           0 :                         nRet |= ChgToEnEmDash;
    1330             :                 }
    1331             :                 break;
    1332             :             }
    1333             :         }
    1334             : 
    1335           0 :         if( ( IsAutoCorrFlag( nRet = ChgOrdinalNumber ) &&
    1336           0 :                 FnChgOrdinalNumber( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) ||
    1337           0 :             ( IsAutoCorrFlag( nRet = SetINetAttr ) &&
    1338             :                 ( ' ' == cChar || '\t' == cChar || 0x0a == cChar || !cChar ) &&
    1339           0 :                 FnSetINetAttr( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) ) )
    1340             :             ;
    1341             :         else
    1342             :         {
    1343           0 :             bool bLockKeyOn = pFrameWin && (pFrameWin->GetIndicatorState() & INDICATOR_CAPSLOCK);
    1344           0 :             bool bUnsupported = lcl_IsUnsupportedUnicodeChar( rCC, rTxt, nCapLttrPos, nInsPos );
    1345             : 
    1346           0 :             nRet = 0;
    1347           0 :             if ( bLockKeyOn && IsAutoCorrFlag( CorrectCapsLock ) &&
    1348           0 :                  FnCorrectCapsLock( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) )
    1349             :             {
    1350             :                 // Correct accidental use of cAPS LOCK key (do this only when
    1351             :                 // the caps or shift lock key is pressed).  Turn off the caps
    1352             :                 // lock afterwords.
    1353           0 :                 nRet |= CorrectCapsLock;
    1354           0 :                 pFrameWin->SimulateKeyPress( KEY_CAPSLOCK );
    1355             :             }
    1356             : 
    1357             :             // Capital letter at beginning of paragraph ?
    1358           0 :             if( !bUnsupported &&
    1359           0 :                 IsAutoCorrFlag( CptlSttSntnc ) &&
    1360           0 :                 FnCptlSttSntnc( rDoc, rTxt, sal_True, nCapLttrPos, nInsPos, eLang ) )
    1361           0 :                 nRet |= CptlSttSntnc;
    1362             : 
    1363             :             // Two capital letters at beginning of word ??
    1364           0 :             if( !bUnsupported &&
    1365           0 :                 IsAutoCorrFlag( CptlSttWrd ) &&
    1366           0 :                 FnCptlSttWrd( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) )
    1367           0 :                 nRet |= CptlSttWrd;
    1368             : 
    1369           0 :             if( IsAutoCorrFlag( ChgToEnEmDash ) &&
    1370           0 :                 FnChgToEnEmDash( rDoc, rTxt, nCapLttrPos, nInsPos, eLang ) )
    1371           0 :                 nRet |= ChgToEnEmDash;
    1372             :         }
    1373             : 
    1374             :     } while( sal_False );
    1375             : 
    1376           0 :     if( nRet )
    1377             :     {
    1378             :         const char* aHelpIds[] =
    1379             :         {
    1380             :             HID_AUTOCORR_HELP_WORD,
    1381             :             HID_AUTOCORR_HELP_SENT,
    1382             :             HID_AUTOCORR_HELP_SENTWORD,
    1383             :             HID_AUTOCORR_HELP_ACORWORD,
    1384             :             "",
    1385             :             HID_AUTOCORR_HELP_ACORSENTWORD,
    1386             :             "",
    1387             :             HID_AUTOCORR_HELP_CHGTOENEMDASH,
    1388             :             HID_AUTOCORR_HELP_WORDENEMDASH,
    1389             :             HID_AUTOCORR_HELP_SENTENEMDASH,
    1390             :             HID_AUTOCORR_HELP_SENTWORDENEMDASH,
    1391             :             HID_AUTOCORR_HELP_ACORWORDENEMDASH,
    1392             :             "",
    1393             :             HID_AUTOCORR_HELP_ACORSENTWORDENEMDASH,
    1394             :             "",
    1395             :             HID_AUTOCORR_HELP_CHGQUOTES,
    1396             :             HID_AUTOCORR_HELP_CHGSGLQUOTES,
    1397             :             HID_AUTOCORR_HELP_SETINETATTR,
    1398             :             HID_AUTOCORR_HELP_INGNOREDOUBLESPACE,
    1399             :             HID_AUTOCORR_HELP_CHGWEIGHTUNDERL,
    1400             :             HID_AUTOCORR_HELP_CHGFRACTIONSYMBOL,
    1401             :             HID_AUTOCORR_HELP_CHGORDINALNUMBER
    1402           0 :         };
    1403             : 
    1404           0 :         sal_uLong nHelpId = 0;
    1405           0 :         if( nRet & ( Autocorrect|CptlSttSntnc|CptlSttWrd|ChgToEnEmDash ) )
    1406             :         {
    1407             :             // from 0 - 15
    1408           0 :             if( nRet & ChgToEnEmDash )
    1409           0 :                 nHelpId += 8;
    1410           0 :             if( nRet & Autocorrect )
    1411           0 :                 nHelpId += 4;
    1412           0 :             if( nRet & CptlSttSntnc )
    1413           0 :                 nHelpId += 2;
    1414           0 :             if( nRet & CptlSttWrd )
    1415           0 :                 nHelpId += 1;
    1416             :         }
    1417             :         else
    1418             :         {
    1419           0 :                  if( nRet & ChgQuotes)          nHelpId = 16;
    1420           0 :             else if( nRet & ChgSglQuotes)       nHelpId = 17;
    1421           0 :             else if( nRet & SetINetAttr)        nHelpId = 18;
    1422           0 :             else if( nRet & IgnoreDoubleSpace)  nHelpId = 19;
    1423           0 :             else if( nRet & ChgWeightUnderl)    nHelpId = 20;
    1424           0 :             else if( nRet & AddNonBrkSpace)     nHelpId = 21;
    1425           0 :             else if( nRet & ChgOrdinalNumber)   nHelpId = 22;
    1426             :         }
    1427             : 
    1428           0 :         if( nHelpId )
    1429             :         {
    1430           0 :             nHelpId -= 1;
    1431           0 :             Application::GetHelp()->OpenHelpAgent( aHelpIds[nHelpId] );
    1432             :         }
    1433             :     }
    1434             : 
    1435             : 
    1436           0 :     return nRet;
    1437             : }
    1438             : 
    1439           0 : SvxAutoCorrectLanguageLists& SvxAutoCorrect::_GetLanguageList(
    1440             :                                                         LanguageType eLang )
    1441             : {
    1442           0 :     if(pLangTable->find(eLang) == pLangTable->end())
    1443           0 :         CreateLanguageFile(eLang, sal_True);
    1444           0 :     return *(pLangTable->find(eLang)->second);
    1445             : }
    1446             : 
    1447           0 : void SvxAutoCorrect::SaveCplSttExceptList( LanguageType eLang )
    1448             : {
    1449           0 :     boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists>::iterator nTmpVal = pLangTable->find(eLang);
    1450           0 :     if(nTmpVal != pLangTable->end() && nTmpVal->second)
    1451           0 :         nTmpVal->second->SaveCplSttExceptList();
    1452             : #ifdef DBG_UTIL
    1453             :     else
    1454             :     {
    1455             :         OSL_FAIL("Save an empty list? ");
    1456             :     }
    1457             : #endif
    1458           0 : }
    1459             : 
    1460           0 : void SvxAutoCorrect::SaveWrdSttExceptList(LanguageType eLang)
    1461             : {
    1462           0 :     boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists>::iterator nTmpVal = pLangTable->find(eLang);
    1463           0 :     if(nTmpVal != pLangTable->end() && nTmpVal->second)
    1464           0 :         nTmpVal->second->SaveWrdSttExceptList();
    1465             : #ifdef DBG_UTIL
    1466             :     else
    1467             :     {
    1468             :         OSL_FAIL("Save an empty list? ");
    1469             :     }
    1470             : #endif
    1471           0 : }
    1472             : 
    1473             :     // Adds a single word. The list will immediately be written to the file!
    1474           0 : sal_Bool SvxAutoCorrect::AddCplSttException( const String& rNew,
    1475             :                                         LanguageType eLang )
    1476             : {
    1477           0 :     SvxAutoCorrectLanguageLists* pLists = 0;
    1478             :     // either the right language is present or it will be this in the general list
    1479           0 :     boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists>::iterator nTmpVal = pLangTable->find(eLang);
    1480           0 :     if(nTmpVal != pLangTable->end())
    1481           0 :         pLists = nTmpVal->second;
    1482             :     else
    1483             :     {
    1484           0 :         nTmpVal = pLangTable->find(LANGUAGE_UNDETERMINED);
    1485           0 :         if(nTmpVal != pLangTable->end())
    1486           0 :             pLists = nTmpVal->second;
    1487           0 :         else if(CreateLanguageFile(LANGUAGE_UNDETERMINED, sal_True))
    1488           0 :             pLists = pLangTable->find(LANGUAGE_UNDETERMINED)->second;
    1489             :     }
    1490             :     OSL_ENSURE(pLists, "No auto correction data");
    1491           0 :     return pLists->AddToCplSttExceptList(rNew);
    1492             : }
    1493             : 
    1494             : // Adds a single word. The list will immediately be written to the file!
    1495           0 : sal_Bool SvxAutoCorrect::AddWrtSttException( const String& rNew,
    1496             :                                          LanguageType eLang )
    1497             : {
    1498           0 :     SvxAutoCorrectLanguageLists* pLists = 0;
    1499             :     //either the right language is present or it is set in the general list
    1500           0 :     boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists>::iterator nTmpVal = pLangTable->find(eLang);
    1501           0 :     if(nTmpVal != pLangTable->end())
    1502           0 :         pLists = nTmpVal->second;
    1503             :     else
    1504             :     {
    1505           0 :         nTmpVal = pLangTable->find(LANGUAGE_UNDETERMINED);
    1506           0 :         if(nTmpVal != pLangTable->end())
    1507           0 :             pLists = nTmpVal->second;
    1508           0 :         else if(CreateLanguageFile(LANGUAGE_UNDETERMINED, sal_True))
    1509           0 :             pLists = pLangTable->find(LANGUAGE_UNDETERMINED)->second;
    1510             :     }
    1511             :     OSL_ENSURE(pLists, "No auto correction file!");
    1512           0 :     return pLists->AddToWrdSttExceptList(rNew);
    1513             : }
    1514             : 
    1515           0 : sal_Bool SvxAutoCorrect::GetPrevAutoCorrWord( SvxAutoCorrDoc& rDoc,
    1516             :                                         const String& rTxt, xub_StrLen nPos,
    1517             :                                         String& rWord ) const
    1518             : {
    1519           0 :     if( !nPos )
    1520           0 :         return sal_False;
    1521             : 
    1522           0 :     xub_StrLen nEnde = nPos;
    1523             : 
    1524             :     // it must be followed by a blank or tab!
    1525           0 :     if( ( nPos < rTxt.Len() &&
    1526           0 :         !IsWordDelim( rTxt.GetChar( nPos ))) ||
    1527           0 :         IsWordDelim( rTxt.GetChar( --nPos )))
    1528           0 :         return sal_False;
    1529             : 
    1530           0 :     while( nPos && !IsWordDelim( rTxt.GetChar( --nPos )))
    1531             :         ;
    1532             : 
    1533             :     // Found a Paragraph-start or a Blank, search for the word shortcut in
    1534             :     // auto.
    1535           0 :     xub_StrLen nCapLttrPos = nPos+1;        // on the 1st Character
    1536           0 :     if( !nPos && !IsWordDelim( rTxt.GetChar( 0 )))
    1537           0 :         --nCapLttrPos;          // Beginning of pargraph and no Blank!
    1538             : 
    1539           0 :     while( lcl_IsInAsciiArr( sImplSttSkipChars, rTxt.GetChar( nCapLttrPos )) )
    1540           0 :         if( ++nCapLttrPos >= nEnde )
    1541           0 :             return sal_False;
    1542             : 
    1543           0 :     if( 3 > nEnde - nCapLttrPos )
    1544           0 :         return sal_False;
    1545             : 
    1546           0 :     LanguageType eLang = rDoc.GetLanguage( nCapLttrPos, sal_False );
    1547           0 :     if( LANGUAGE_SYSTEM == eLang )
    1548           0 :         eLang = MsLangId::getSystemLanguage();
    1549             : 
    1550           0 :     SvxAutoCorrect* pThis = (SvxAutoCorrect*)this;
    1551           0 :     CharClass& rCC = pThis->GetCharClass( eLang );
    1552             : 
    1553           0 :     if( lcl_IsSymbolChar( rCC, rTxt, nCapLttrPos, nEnde ))
    1554           0 :         return sal_False;
    1555             : 
    1556           0 :     rWord = rTxt.Copy( nCapLttrPos, nEnde - nCapLttrPos );
    1557           0 :     return sal_True;
    1558             : }
    1559             : 
    1560           0 : sal_Bool SvxAutoCorrect::CreateLanguageFile( LanguageType eLang, sal_Bool bNewFile )
    1561             : {
    1562             :     OSL_ENSURE(pLangTable->find(eLang) == pLangTable->end(), "Language already exists ");
    1563             : 
    1564           0 :     String sUserDirFile( GetAutoCorrFileName( eLang, sal_True, sal_False ));
    1565           0 :     String sShareDirFile( sUserDirFile );
    1566             : 
    1567           0 :     SvxAutoCorrectLanguageListsPtr pLists = 0;
    1568             : 
    1569           0 :     Time nMinTime( 0, 2 ), nAktTime( Time::SYSTEM ), nLastCheckTime( Time::EMPTY );
    1570             : 
    1571           0 :     std::map<LanguageType, long>::iterator nFndPos = aLastFileTable.find(eLang);
    1572           0 :     if(nFndPos != aLastFileTable.end() &&
    1573           0 :        (nLastCheckTime.SetTime(nFndPos->second), nLastCheckTime < nAktTime) &&
    1574           0 :        nAktTime - nLastCheckTime < nMinTime)
    1575             :     {
    1576             :         // no need to test the file, because the last check is not older then
    1577             :         // 2 minutes.
    1578           0 :         if( bNewFile )
    1579             :         {
    1580           0 :             sShareDirFile = sUserDirFile;
    1581           0 :             pLists = new SvxAutoCorrectLanguageLists( *this, sShareDirFile, sUserDirFile );
    1582           0 :             pLangTable->insert(eLang, pLists);
    1583           0 :             aLastFileTable.erase(nFndPos);
    1584             :         }
    1585             :     }
    1586           0 :     else if( ( FStatHelper::IsDocument( sUserDirFile ) ||
    1587             :                 FStatHelper::IsDocument( sShareDirFile =
    1588           0 :                               GetAutoCorrFileName( eLang, sal_False, sal_False ) ) ) ||
    1589             :         ( sShareDirFile = sUserDirFile, bNewFile ))
    1590             :     {
    1591           0 :         pLists = new SvxAutoCorrectLanguageLists( *this, sShareDirFile, sUserDirFile );
    1592           0 :         pLangTable->insert(eLang, pLists);
    1593           0 :         if (nFndPos != aLastFileTable.end())
    1594           0 :             aLastFileTable.erase(nFndPos);
    1595             :     }
    1596           0 :     else if( !bNewFile )
    1597             :     {
    1598           0 :         aLastFileTable[eLang] = nAktTime.GetTime();
    1599             :     }
    1600           0 :     return pLists != 0;
    1601             : }
    1602             : 
    1603           0 : sal_Bool SvxAutoCorrect::PutText( const String& rShort, const String& rLong,
    1604             :                                 LanguageType eLang )
    1605             : {
    1606           0 :     boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists>::iterator nTmpVal = pLangTable->find(eLang);
    1607           0 :     if(nTmpVal != pLangTable->end())
    1608           0 :         return nTmpVal->second->PutText(rShort, rLong);
    1609           0 :     if(CreateLanguageFile(eLang))
    1610           0 :         return pLangTable->find(eLang)->second->PutText(rShort, rLong);
    1611           0 :     return sal_False;
    1612             : }
    1613             : 
    1614           0 : sal_Bool SvxAutoCorrect::MakeCombinedChanges( std::vector<SvxAutocorrWord>& aNewEntries,
    1615             :                                               std::vector<SvxAutocorrWord>& aDeleteEntries,
    1616             :                                               LanguageType eLang )
    1617             : {
    1618           0 :     boost::ptr_map<LanguageType, SvxAutoCorrectLanguageLists>::iterator nTmpVal = pLangTable->find(eLang);
    1619           0 :     if(nTmpVal != pLangTable->end())
    1620             :     {
    1621           0 :         return nTmpVal->second->MakeCombinedChanges( aNewEntries, aDeleteEntries );
    1622             :     }
    1623           0 :     else if(CreateLanguageFile( eLang ))
    1624             :     {
    1625           0 :         return pLangTable->find( eLang )->second->MakeCombinedChanges( aNewEntries, aDeleteEntries );
    1626             :     }
    1627           0 :     return sal_False;
    1628             : 
    1629             : }
    1630             : 
    1631             : 
    1632             :     //  - return the replacement text (only for SWG-Format, all other
    1633             :     //      can be taken from the word list!)
    1634           0 : sal_Bool SvxAutoCorrect::GetLongText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String&, const String& , String& )
    1635             : {
    1636           0 :     return sal_False;
    1637             : }
    1638             : 
    1639             :     // Text with attribution (only the SWG - SWG format!)
    1640           0 : sal_Bool SvxAutoCorrect::PutText( const com::sun::star::uno::Reference < com::sun::star::embed::XStorage >&, const String&, const String&, SfxObjectShell&,
    1641             :                                 String& )
    1642             : {
    1643           0 :     return sal_False;
    1644             : }
    1645             : 
    1646           0 : void EncryptBlockName_Imp( String& rName )
    1647             : {
    1648           0 :     xub_StrLen nLen, nPos = 1;
    1649           0 :     rName.Insert( '#', 0 );
    1650           0 :     sal_Unicode* pName = rName.GetBufferAccess();
    1651           0 :     for ( nLen = rName.Len(), ++pName; nPos < nLen; ++nPos, ++pName )
    1652             :     {
    1653           0 :         if( lcl_IsInAsciiArr( "!/:.\\", *pName ))
    1654           0 :             *pName &= 0x0f;
    1655             :     }
    1656           0 : }
    1657             : 
    1658             : /* This code is copied from SwXMLTextBlocks::GeneratePackageName */
    1659           0 : static void GeneratePackageName ( const String& rShort, String& rPackageName )
    1660             : {
    1661           0 :     rPackageName = rShort;
    1662           0 :     xub_StrLen nPos = 0;
    1663           0 :     sal_Unicode pDelims[] = { '!', '/', ':', '.', '\\', 0 };
    1664           0 :     rtl::OString sByte(rtl::OUStringToOString(rPackageName, RTL_TEXTENCODING_UTF7));
    1665           0 :     rPackageName = rtl::OStringToOUString(sByte, RTL_TEXTENCODING_ASCII_US);
    1666           0 :     while( STRING_NOTFOUND != ( nPos = rPackageName.SearchChar( pDelims, nPos )))
    1667             :     {
    1668           0 :         rPackageName.SetChar( nPos, '_' );
    1669           0 :         ++nPos;
    1670           0 :     }
    1671           0 : }
    1672             : 
    1673           0 : static const SvxAutocorrWord* lcl_SearchWordsInList(
    1674             :                 SvxAutoCorrectLanguageListsPtr pList, const String& rTxt,
    1675             :                 xub_StrLen& rStt, xub_StrLen nEndPos)
    1676             : {
    1677           0 :     const SvxAutocorrWordList* pAutoCorrWordList = pList->GetAutocorrWordList();
    1678           0 :     return pAutoCorrWordList->SearchWordsInList( rTxt, rStt, nEndPos );
    1679             : }
    1680             : 
    1681             : // the search for the words in the substitution table
    1682           0 : const SvxAutocorrWord* SvxAutoCorrect::SearchWordsInList(
    1683             :                 const String& rTxt, xub_StrLen& rStt, xub_StrLen nEndPos,
    1684             :                 SvxAutoCorrDoc&, LanguageType& rLang )
    1685             : {
    1686           0 :     LanguageType eLang = rLang;
    1687           0 :     const SvxAutocorrWord* pRet = 0;
    1688           0 :     if( LANGUAGE_SYSTEM == eLang )
    1689           0 :         eLang = MsLangId::getSystemLanguage();
    1690             : 
    1691             :     // First search for eLang, then US-English -> English
    1692             :     // and last in LANGUAGE_UNDETERMINED
    1693           0 :     if(pLangTable->find(eLang) != pLangTable->end() || CreateLanguageFile(eLang, sal_False))
    1694             :     {
    1695             :         //the language is available - so bring it on
    1696           0 :         SvxAutoCorrectLanguageLists* pList = pLangTable->find(eLang)->second;
    1697           0 :         pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos );
    1698           0 :         if( pRet )
    1699             :         {
    1700           0 :             rLang = eLang;
    1701           0 :             return pRet;
    1702             :         }
    1703             :     }
    1704             : 
    1705             :     // If it still could not be found here, then keep on searching
    1706             : 
    1707           0 :     LanguageType nTmpKey1 = eLang & 0x7ff, // the main language in many cases DE
    1708           0 :                  nTmpKey2 = eLang & 0x3ff; // otherwise for example EN
    1709           0 :     if(nTmpKey1 != eLang && (pLangTable->find(nTmpKey1) != pLangTable->end() || CreateLanguageFile(nTmpKey1, sal_False)))
    1710             :     {
    1711             :         //the language is available - so bring it on
    1712           0 :         SvxAutoCorrectLanguageLists* pList = pLangTable->find(nTmpKey1)->second;
    1713           0 :         pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos );
    1714           0 :         if( pRet )
    1715             :         {
    1716           0 :             rLang = nTmpKey1;
    1717           0 :             return pRet;
    1718             :         }
    1719             :     }
    1720             : 
    1721           0 :     if(nTmpKey2 != eLang && (pLangTable->find(nTmpKey2) != pLangTable->end() || CreateLanguageFile(nTmpKey2, sal_False)))
    1722             :     {
    1723             :         //the language is available - so bring it on
    1724           0 :         SvxAutoCorrectLanguageLists* pList = pLangTable->find(nTmpKey2)->second;
    1725           0 :         pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos );
    1726           0 :         if( pRet )
    1727             :         {
    1728           0 :             rLang = nTmpKey2;
    1729           0 :             return pRet;
    1730             :         }
    1731             :     }
    1732             : 
    1733           0 :     if(pLangTable->find(LANGUAGE_UNDETERMINED) != pLangTable->end() || CreateLanguageFile(LANGUAGE_UNDETERMINED, sal_False))
    1734             :     {
    1735             :         //the language is available - so bring it on
    1736           0 :         SvxAutoCorrectLanguageLists* pList = pLangTable->find(LANGUAGE_UNDETERMINED)->second;
    1737           0 :         pRet = lcl_SearchWordsInList( pList, rTxt, rStt, nEndPos );
    1738           0 :         if( pRet )
    1739             :         {
    1740           0 :             rLang = LANGUAGE_UNDETERMINED;
    1741           0 :             return pRet;
    1742             :         }
    1743             :     }
    1744           0 :     return 0;
    1745             : }
    1746             : 
    1747           0 : sal_Bool SvxAutoCorrect::FindInWrdSttExceptList( LanguageType eLang,
    1748             :                                              const String& sWord )
    1749             : {
    1750             :     // First search for eLang, then US-English -> English
    1751             :     // and last in LANGUAGE_UNDETERMINED
    1752           0 :     LanguageType nTmpKey1 = eLang & 0x7ff, // the main language in many cases DE
    1753           0 :                  nTmpKey2 = eLang & 0x3ff; // otherwise for example EN
    1754           0 :     String sTemp(sWord);
    1755             : 
    1756           0 :     if(pLangTable->find(eLang) != pLangTable->end() || CreateLanguageFile(eLang, sal_False))
    1757             :     {
    1758             :         //the language is available - so bring it on
    1759           0 :         SvxAutoCorrectLanguageLists* pList = pLangTable->find(eLang)->second;
    1760           0 :         String _sTemp(sWord);
    1761           0 :         if(pList->GetWrdSttExceptList()->find(&_sTemp) != pList->GetWrdSttExceptList()->end() )
    1762           0 :             return sal_True;
    1763             :     }
    1764             : 
    1765             :     // If it still could not be found here, then keep on searching
    1766           0 :     if(nTmpKey1 != eLang && (pLangTable->find(nTmpKey1) != pLangTable->end() || CreateLanguageFile(nTmpKey1, sal_False)))
    1767             :     {
    1768             :         //the language is available - so bring it on
    1769           0 :         SvxAutoCorrectLanguageLists* pList = pLangTable->find(nTmpKey1)->second;
    1770           0 :         if(pList->GetWrdSttExceptList()->find(&sTemp) != pList->GetWrdSttExceptList()->end() )
    1771           0 :             return sal_True;
    1772             :     }
    1773             : 
    1774           0 :     if(nTmpKey2 != eLang && (pLangTable->find(nTmpKey2) != pLangTable->end() || CreateLanguageFile(nTmpKey2, sal_False)))
    1775             :     {
    1776             :         //the language is available - so bring it on
    1777           0 :         SvxAutoCorrectLanguageLists* pList = pLangTable->find(nTmpKey2)->second;
    1778           0 :         if(pList->GetWrdSttExceptList()->find(&sTemp) != pList->GetWrdSttExceptList()->end() )
    1779           0 :             return sal_True;
    1780             :     }
    1781             : 
    1782           0 :     if(pLangTable->find(LANGUAGE_UNDETERMINED) != pLangTable->end() || CreateLanguageFile(LANGUAGE_UNDETERMINED, sal_False))
    1783             :     {
    1784             :         //the language is available - so bring it on
    1785           0 :         SvxAutoCorrectLanguageLists* pList = pLangTable->find(LANGUAGE_UNDETERMINED)->second;
    1786           0 :         if(pList->GetWrdSttExceptList()->find(&sTemp) != pList->GetWrdSttExceptList()->end() )
    1787           0 :             return sal_True;
    1788             :     }
    1789           0 :     return sal_False;
    1790             : }
    1791             : 
    1792           0 : static sal_Bool lcl_FindAbbreviation( const SvStringsISortDtor* pList, const String& sWord)
    1793             : {
    1794           0 :     String sAbk(rtl::OUString('~'));
    1795           0 :     SvStringsISortDtor::const_iterator it = pList->find( &sAbk );
    1796           0 :     sal_uInt16 nPos = it - pList->begin();
    1797           0 :     if( nPos < pList->size() )
    1798             :     {
    1799           0 :         String sLowerWord( sWord ); sLowerWord.ToLowerAscii();
    1800             :         const String* pAbk;
    1801           0 :         for( sal_uInt16 n = nPos;
    1802           0 :                 n < pList->size() &&
    1803           0 :                 '~' == ( pAbk = (*pList)[ n ])->GetChar( 0 );
    1804             :             ++n )
    1805             :         {
    1806             :             // ~ and ~. are not allowed!
    1807           0 :             if( 2 < pAbk->Len() && pAbk->Len() - 1 <= sWord.Len() )
    1808             :             {
    1809           0 :                 String sLowerAbk( *pAbk ); sLowerAbk.ToLowerAscii();
    1810           0 :                 for( xub_StrLen i = sLowerAbk.Len(), ii = sLowerWord.Len(); i; )
    1811             :                 {
    1812           0 :                     if( !--i )      // agrees
    1813           0 :                         return sal_True;
    1814             : 
    1815           0 :                     if( sLowerAbk.GetChar( i ) != sLowerWord.GetChar( --ii ))
    1816           0 :                         break;
    1817           0 :                 }
    1818             :             }
    1819           0 :         }
    1820             :     }
    1821             :     OSL_ENSURE( !(nPos && '~' == (*pList)[ --nPos ]->GetChar( 0 ) ),
    1822             :             "Wrongly sorted exception list?" );
    1823           0 :     return sal_False;
    1824             : }
    1825             : 
    1826           0 : sal_Bool SvxAutoCorrect::FindInCplSttExceptList(LanguageType eLang,
    1827             :                                 const String& sWord, sal_Bool bAbbreviation)
    1828             : {
    1829             :     // First search for eLang, then US-English -> English
    1830             :     // and last in LANGUAGE_UNDETERMINED
    1831           0 :     LanguageType nTmpKey1 = eLang & 0x7ff, // the main language in many cases DE
    1832           0 :                  nTmpKey2 = eLang & 0x3ff; // otherwise for example EN
    1833           0 :     String sTemp( sWord );
    1834             : 
    1835           0 :     if(pLangTable->find(eLang) != pLangTable->end() || CreateLanguageFile(eLang, sal_False))
    1836             :     {
    1837             :         //the language is available - so bring it on
    1838           0 :         const SvStringsISortDtor* pList = pLangTable->find(eLang)->second->GetCplSttExceptList();
    1839           0 :         if(bAbbreviation ? lcl_FindAbbreviation(pList, sWord) : pList->find(&sTemp) != pList->end() )
    1840           0 :             return sal_True;
    1841             :     }
    1842             : 
    1843             :     // If it still could not be found here, then keep on searching
    1844           0 :     if(nTmpKey1 != eLang && (pLangTable->find(nTmpKey1) != pLangTable->end() || CreateLanguageFile(nTmpKey1, sal_False)))
    1845             :     {
    1846           0 :         const SvStringsISortDtor* pList = pLangTable->find(nTmpKey1)->second->GetCplSttExceptList();
    1847           0 :         if(bAbbreviation ? lcl_FindAbbreviation(pList, sWord) : pList->find(&sTemp) != pList->end() )
    1848           0 :             return sal_True;
    1849             :     }
    1850             : 
    1851           0 :     if(nTmpKey2 != eLang && (pLangTable->find(nTmpKey2) != pLangTable->end() || CreateLanguageFile(nTmpKey2, sal_False)))
    1852             :     {
    1853             :         //the language is available - so bring it on
    1854           0 :         const SvStringsISortDtor* pList = pLangTable->find(nTmpKey2)->second->GetCplSttExceptList();
    1855           0 :         if(bAbbreviation ? lcl_FindAbbreviation(pList, sWord) : pList->find(&sTemp) != pList->end() )
    1856           0 :             return sal_True;
    1857             :     }
    1858             : 
    1859           0 :     if(pLangTable->find(LANGUAGE_UNDETERMINED) != pLangTable->end() || CreateLanguageFile(LANGUAGE_UNDETERMINED, sal_False))
    1860             :     {
    1861             :         //the language is available - so bring it on
    1862           0 :         const SvStringsISortDtor* pList = pLangTable->find(LANGUAGE_UNDETERMINED)->second->GetCplSttExceptList();
    1863           0 :         if(bAbbreviation ? lcl_FindAbbreviation(pList, sWord) : pList->find(&sTemp) != pList->end() )
    1864           0 :             return sal_True;
    1865             :     }
    1866           0 :     return sal_False;
    1867             : }
    1868             : 
    1869           0 : String SvxAutoCorrect::GetAutoCorrFileName( LanguageType eLang,
    1870             :                                             sal_Bool bNewFile, sal_Bool bTst ) const
    1871             : {
    1872           0 :     String sRet, sExt( LanguageTag( eLang ).getBcp47() );
    1873             : 
    1874           0 :     sExt.Insert('_', 0);
    1875           0 :     sExt.AppendAscii( ".dat" );
    1876           0 :     if( bNewFile )
    1877           0 :         ( sRet = sUserAutoCorrFile )  += sExt;
    1878           0 :     else if( !bTst )
    1879           0 :         ( sRet = sShareAutoCorrFile )  += sExt;
    1880             :     else
    1881             :     {
    1882             :         // test first in the user directory - if not exist, then
    1883           0 :         ( sRet = sUserAutoCorrFile ) += sExt;
    1884           0 :         if( !FStatHelper::IsDocument( sRet ))
    1885           0 :             ( sRet = sShareAutoCorrFile ) += sExt;
    1886             :     }
    1887           0 :     return sRet;
    1888             : }
    1889             : 
    1890           0 : SvxAutoCorrectLanguageLists::SvxAutoCorrectLanguageLists(
    1891             :                 SvxAutoCorrect& rParent,
    1892             :                 const String& rShareAutoCorrectFile,
    1893             :                 const String& rUserAutoCorrectFile)
    1894             : :   sShareAutoCorrFile( rShareAutoCorrectFile ),
    1895             :     sUserAutoCorrFile( rUserAutoCorrectFile ),
    1896             :     aModifiedDate( Date::EMPTY ),
    1897             :     aModifiedTime( Time::EMPTY ),
    1898             :     aLastCheckTime( Time::EMPTY ),
    1899             :     pCplStt_ExcptLst( 0 ),
    1900             :     pWrdStt_ExcptLst( 0 ),
    1901             :     pAutocorr_List( 0 ),
    1902             :     rAutoCorrect(rParent),
    1903           0 :     nFlags(0)
    1904             : {
    1905           0 : }
    1906             : 
    1907           0 : SvxAutoCorrectLanguageLists::~SvxAutoCorrectLanguageLists()
    1908             : {
    1909           0 :     delete pCplStt_ExcptLst;
    1910           0 :     delete pWrdStt_ExcptLst;
    1911           0 :     delete pAutocorr_List;
    1912           0 : }
    1913             : 
    1914           0 : sal_Bool SvxAutoCorrectLanguageLists::IsFileChanged_Imp()
    1915             : {
    1916             :     // Access the file system only every 2 minutes to check the date stamp
    1917           0 :     sal_Bool bRet = sal_False;
    1918             : 
    1919           0 :     Time nMinTime( 0, 2 );
    1920           0 :     Time nAktTime( Time::SYSTEM );
    1921           0 :     if( aLastCheckTime > nAktTime ||                    // overflow?
    1922           0 :         ( nAktTime -= aLastCheckTime ) > nMinTime )     // min time past
    1923             :     {
    1924           0 :         Date aTstDate( Date::EMPTY ); Time aTstTime( Time::EMPTY );
    1925           0 :         if( FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile,
    1926           0 :                                             &aTstDate, &aTstTime ) &&
    1927           0 :             ( aModifiedDate != aTstDate || aModifiedTime != aTstTime ))
    1928             :         {
    1929           0 :             bRet = sal_True;
    1930             :             // then remove all the lists fast!
    1931           0 :             if( CplSttLstLoad & nFlags && pCplStt_ExcptLst )
    1932           0 :                 delete pCplStt_ExcptLst, pCplStt_ExcptLst = 0;
    1933           0 :             if( WrdSttLstLoad & nFlags && pWrdStt_ExcptLst )
    1934           0 :                 delete pWrdStt_ExcptLst, pWrdStt_ExcptLst = 0;
    1935           0 :             if( ChgWordLstLoad & nFlags && pAutocorr_List )
    1936           0 :                 delete pAutocorr_List, pAutocorr_List = 0;
    1937           0 :             nFlags &= ~(CplSttLstLoad | WrdSttLstLoad | ChgWordLstLoad );
    1938             :         }
    1939           0 :         aLastCheckTime = Time( Time::SYSTEM );
    1940             :     }
    1941           0 :     return bRet;
    1942             : }
    1943             : 
    1944           0 : void SvxAutoCorrectLanguageLists::LoadXMLExceptList_Imp(
    1945             :                                         SvStringsISortDtor*& rpLst,
    1946             :                                         const sal_Char* pStrmName,
    1947             :                                         SotStorageRef& rStg)
    1948             : {
    1949           0 :     if( rpLst )
    1950           0 :         rpLst->DeleteAndDestroyAll();
    1951             :     else
    1952           0 :         rpLst = new SvStringsISortDtor;
    1953             : 
    1954             :     {
    1955           0 :         String sStrmName( pStrmName, RTL_TEXTENCODING_MS_1252 );
    1956           0 :         String sTmp( sStrmName );
    1957             : 
    1958           0 :         if( rStg.Is() && rStg->IsStream( sStrmName ) )
    1959             :         {
    1960             :             SvStorageStreamRef xStrm = rStg->OpenSotStream( sTmp,
    1961           0 :                 ( STREAM_READ | STREAM_SHARE_DENYWRITE | STREAM_NOCREATE ) );
    1962           0 :             if( SVSTREAM_OK != xStrm->GetError())
    1963             :             {
    1964           0 :                 xStrm.Clear();
    1965           0 :                 rStg.Clear();
    1966           0 :                 RemoveStream_Imp( sStrmName );
    1967             :             }
    1968             :             else
    1969             :             {
    1970             :                 uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
    1971           0 :                     comphelper::getProcessServiceFactory();
    1972             :                 OSL_ENSURE( xServiceFactory.is(),
    1973             :                     "XMLReader::Read: got no service manager" );
    1974           0 :                 if( !xServiceFactory.is() )
    1975             :                 {
    1976             :                     // Throw an exception ?
    1977             :                 }
    1978             : 
    1979           0 :                 xml::sax::InputSource aParserInput;
    1980           0 :                 aParserInput.sSystemId = sStrmName;
    1981             : 
    1982           0 :                 xStrm->Seek( 0L );
    1983           0 :                 xStrm->SetBufferSize( 8 * 1024 );
    1984           0 :                 aParserInput.aInputStream = new utl::OInputStreamWrapper( *xStrm );
    1985             : 
    1986             :                 // get filter
    1987           0 :                 uno::Reference< xml::sax::XDocumentHandler > xFilter = new SvXMLExceptionListImport ( xServiceFactory, *rpLst );
    1988             : 
    1989             :                 // connect parser and filter
    1990           0 :                 uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create( comphelper::getComponentContext(xServiceFactory) );
    1991           0 :                 xParser->setDocumentHandler( xFilter );
    1992             : 
    1993             :                 // parse
    1994             :                 try
    1995             :                 {
    1996           0 :                     xParser->parseStream( aParserInput );
    1997             :                 }
    1998           0 :                 catch( const xml::sax::SAXParseException& )
    1999             :                 {
    2000             :                     // re throw ?
    2001             :                 }
    2002           0 :                 catch( const xml::sax::SAXException& )
    2003             :                 {
    2004             :                     // re throw ?
    2005             :                 }
    2006           0 :                 catch( const io::IOException& )
    2007             :                 {
    2008             :                     // re throw ?
    2009           0 :                 }
    2010           0 :             }
    2011             :         }
    2012             : 
    2013             :         // Set time stamp
    2014             :         FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile,
    2015           0 :                                         &aModifiedDate, &aModifiedTime );
    2016           0 :         aLastCheckTime = Time( Time::SYSTEM );
    2017             :     }
    2018             : 
    2019           0 : }
    2020             : 
    2021           0 : void SvxAutoCorrectLanguageLists::SaveExceptList_Imp(
    2022             :                             const SvStringsISortDtor& rLst,
    2023             :                             const sal_Char* pStrmName,
    2024             :                             SotStorageRef &rStg,
    2025             :                             sal_Bool bConvert )
    2026             : {
    2027           0 :     if( rStg.Is() )
    2028             :     {
    2029           0 :         String sStrmName( pStrmName, RTL_TEXTENCODING_MS_1252 );
    2030           0 :         if( rLst.empty() )
    2031             :         {
    2032           0 :             rStg->Remove( sStrmName );
    2033           0 :             rStg->Commit();
    2034             :         }
    2035             :         else
    2036             :         {
    2037             :             SotStorageStreamRef xStrm = rStg->OpenSotStream( sStrmName,
    2038           0 :                     ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE ) );
    2039           0 :             if( xStrm.Is() )
    2040             :             {
    2041           0 :                 xStrm->SetSize( 0 );
    2042           0 :                 xStrm->SetBufferSize( 8192 );
    2043           0 :                 OUString aMime( "text/xml" );
    2044           0 :                 uno::Any aAny;
    2045           0 :                 aAny <<= aMime;
    2046           0 :                 xStrm->SetProperty( rtl::OUString("MediaType"), aAny );
    2047             : 
    2048             : 
    2049             :                 uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
    2050           0 :                     comphelper::getProcessServiceFactory();
    2051             :                 uno::Reference< uno::XComponentContext > xContext =
    2052           0 :                     comphelper::getProcessComponentContext();
    2053             : 
    2054           0 :                 uno::Reference < xml::sax::XWriter > xWriter  = xml::sax::Writer::create(xContext);
    2055           0 :                 uno::Reference < io::XOutputStream> xOut = new utl::OOutputStreamWrapper( *xStrm );
    2056           0 :                 xWriter->setOutputStream(xOut);
    2057             : 
    2058           0 :                 uno::Reference < xml::sax::XDocumentHandler > xHandler(xWriter, UNO_QUERY_THROW);
    2059           0 :                 SvXMLExceptionListExport aExp( xServiceFactory, rLst, sStrmName, xHandler );
    2060             : 
    2061           0 :                 aExp.exportDoc( XML_BLOCK_LIST );
    2062             : 
    2063           0 :                 xStrm->Commit();
    2064           0 :                 if( xStrm->GetError() == SVSTREAM_OK )
    2065             :                 {
    2066           0 :                     xStrm.Clear();
    2067           0 :                     if (!bConvert)
    2068             :                     {
    2069           0 :                         rStg->Commit();
    2070           0 :                         if( SVSTREAM_OK != rStg->GetError() )
    2071             :                         {
    2072           0 :                             rStg->Remove( sStrmName );
    2073           0 :                             rStg->Commit();
    2074             :                         }
    2075             :                     }
    2076           0 :                 }
    2077           0 :             }
    2078           0 :         }
    2079             :     }
    2080           0 : }
    2081             : 
    2082           0 : SvxAutocorrWordList* SvxAutoCorrectLanguageLists::LoadAutocorrWordList()
    2083             : {
    2084           0 :     if( pAutocorr_List )
    2085           0 :         pAutocorr_List->DeleteAndDestroyAll();
    2086             :     else
    2087           0 :         pAutocorr_List = new SvxAutocorrWordList();
    2088             : 
    2089             :     try
    2090             :     {
    2091           0 :         uno::Reference < embed::XStorage > xStg = comphelper::OStorageHelper::GetStorageFromURL( sShareAutoCorrFile, embed::ElementModes::READ );
    2092           0 :         String aXMLWordListName( pXMLImplAutocorr_ListStr, RTL_TEXTENCODING_MS_1252 );
    2093           0 :         uno::Reference < io::XStream > xStrm = xStg->openStreamElement( aXMLWordListName, embed::ElementModes::READ );
    2094           0 :         uno::Reference< lang::XMultiServiceFactory > xServiceFactory = comphelper::getProcessServiceFactory();
    2095           0 :         uno::Reference< uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
    2096             : 
    2097           0 :         xml::sax::InputSource aParserInput;
    2098           0 :         aParserInput.sSystemId = aXMLWordListName;
    2099           0 :         aParserInput.aInputStream = xStrm->getInputStream();
    2100             : 
    2101             :         // get parser
    2102           0 :         uno::Reference< xml::sax::XParser > xParser = xml::sax::Parser::create(xContext);
    2103           0 :         RTL_LOGFILE_PRODUCT_CONTEXT( aLog, "AutoCorrect Import" );
    2104           0 :         uno::Reference< xml::sax::XDocumentHandler > xFilter = new SvXMLAutoCorrectImport( xServiceFactory, pAutocorr_List, rAutoCorrect, xStg );
    2105             : 
    2106             :         // connect parser and filter
    2107           0 :         xParser->setDocumentHandler( xFilter );
    2108             : 
    2109             :         // parse
    2110           0 :         xParser->parseStream( aParserInput );
    2111             :     }
    2112           0 :     catch ( const uno::Exception& )
    2113             :     {
    2114             :     }
    2115             : 
    2116             :     // Set time stamp
    2117             :     FStatHelper::GetModifiedDateTimeOfFile( sShareAutoCorrFile,
    2118           0 :                                     &aModifiedDate, &aModifiedTime );
    2119           0 :     aLastCheckTime = Time( Time::SYSTEM );
    2120             : 
    2121           0 :     return pAutocorr_List;
    2122             : }
    2123             : 
    2124           0 : void SvxAutoCorrectLanguageLists::SetAutocorrWordList( SvxAutocorrWordList* pList )
    2125             : {
    2126           0 :     if( pAutocorr_List && pList != pAutocorr_List )
    2127           0 :         delete pAutocorr_List;
    2128           0 :     pAutocorr_List = pList;
    2129           0 :     if( !pAutocorr_List )
    2130             :     {
    2131             :         OSL_ENSURE( !this, "No valid list" );
    2132           0 :         pAutocorr_List = new SvxAutocorrWordList();
    2133             :     }
    2134           0 :     nFlags |= ChgWordLstLoad;
    2135           0 : }
    2136             : 
    2137           0 : const SvxAutocorrWordList* SvxAutoCorrectLanguageLists::GetAutocorrWordList()
    2138             : {
    2139           0 :     if( !( ChgWordLstLoad & nFlags ) || IsFileChanged_Imp() )
    2140           0 :         SetAutocorrWordList( LoadAutocorrWordList() );
    2141           0 :     return pAutocorr_List;
    2142             : }
    2143             : 
    2144           0 : SvStringsISortDtor* SvxAutoCorrectLanguageLists::GetCplSttExceptList()
    2145             : {
    2146           0 :     if( !( CplSttLstLoad & nFlags ) || IsFileChanged_Imp() )
    2147           0 :         SetCplSttExceptList( LoadCplSttExceptList() );
    2148           0 :     return pCplStt_ExcptLst;
    2149             : }
    2150             : 
    2151           0 : sal_Bool SvxAutoCorrectLanguageLists::AddToCplSttExceptList(const String& rNew)
    2152             : {
    2153           0 :     String* pNew = new String( rNew );
    2154           0 :     if( rNew.Len() && GetCplSttExceptList()->insert( pNew ).second )
    2155             :     {
    2156           0 :         MakeUserStorage_Impl();
    2157           0 :         SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2158             : 
    2159           0 :         SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg );
    2160             : 
    2161           0 :         xStg = 0;
    2162             :         // Set time stamp
    2163             :         FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile,
    2164           0 :                                             &aModifiedDate, &aModifiedTime );
    2165           0 :         aLastCheckTime = Time( Time::SYSTEM );
    2166             :     }
    2167             :     else
    2168           0 :         delete pNew, pNew = 0;
    2169           0 :     return 0 != pNew;
    2170             : }
    2171             : 
    2172           0 : sal_Bool SvxAutoCorrectLanguageLists::AddToWrdSttExceptList(const String& rNew)
    2173             : {
    2174           0 :     String* pNew = new String( rNew );
    2175           0 :     SvStringsISortDtor* pExceptList = LoadWrdSttExceptList();
    2176           0 :     if( rNew.Len() && pExceptList && pExceptList->insert( pNew ).second )
    2177             :     {
    2178           0 :         MakeUserStorage_Impl();
    2179           0 :         SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2180             : 
    2181           0 :         SaveExceptList_Imp( *pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg );
    2182             : 
    2183           0 :         xStg = 0;
    2184             :         // Set time stamp
    2185             :         FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile,
    2186           0 :                                             &aModifiedDate, &aModifiedTime );
    2187           0 :         aLastCheckTime = Time( Time::SYSTEM );
    2188             :     }
    2189             :     else
    2190           0 :         delete pNew, pNew = 0;
    2191           0 :     return 0 != pNew;
    2192             : }
    2193             : 
    2194           0 : SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadCplSttExceptList()
    2195             : {
    2196           0 :     SotStorageRef xStg = new SotStorage( sShareAutoCorrFile, STREAM_READ | STREAM_SHARE_DENYNONE, sal_True );
    2197           0 :     String sTemp ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplCplStt_ExcptLstStr ) );
    2198           0 :     if( xStg.Is() && xStg->IsContained( sTemp ) )
    2199           0 :         LoadXMLExceptList_Imp( pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg );
    2200             : 
    2201           0 :     return pCplStt_ExcptLst;
    2202             : }
    2203             : 
    2204           0 : void SvxAutoCorrectLanguageLists::SaveCplSttExceptList()
    2205             : {
    2206           0 :     MakeUserStorage_Impl();
    2207           0 :     SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2208             : 
    2209           0 :     SaveExceptList_Imp( *pCplStt_ExcptLst, pXMLImplCplStt_ExcptLstStr, xStg );
    2210             : 
    2211           0 :     xStg = 0;
    2212             : 
    2213             :     // Set time stamp
    2214             :     FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile,
    2215           0 :                                             &aModifiedDate, &aModifiedTime );
    2216           0 :     aLastCheckTime = Time( Time::SYSTEM );
    2217           0 : }
    2218             : 
    2219           0 : void SvxAutoCorrectLanguageLists::SetCplSttExceptList( SvStringsISortDtor* pList )
    2220             : {
    2221           0 :     if( pCplStt_ExcptLst && pList != pCplStt_ExcptLst )
    2222           0 :         delete pCplStt_ExcptLst;
    2223             : 
    2224           0 :     pCplStt_ExcptLst = pList;
    2225           0 :     if( !pCplStt_ExcptLst )
    2226             :     {
    2227             :         OSL_ENSURE( !this, "No valid list" );
    2228           0 :         pCplStt_ExcptLst = new SvStringsISortDtor;
    2229             :     }
    2230           0 :     nFlags |= CplSttLstLoad;
    2231           0 : }
    2232             : 
    2233           0 : SvStringsISortDtor* SvxAutoCorrectLanguageLists::LoadWrdSttExceptList()
    2234             : {
    2235           0 :     SotStorageRef xStg = new SotStorage( sShareAutoCorrFile, STREAM_READ | STREAM_SHARE_DENYNONE, sal_True );
    2236           0 :     String sTemp ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplWrdStt_ExcptLstStr ) );
    2237           0 :     if( xStg.Is() && xStg->IsContained( sTemp ) )
    2238           0 :         LoadXMLExceptList_Imp( pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg );
    2239           0 :     return pWrdStt_ExcptLst;
    2240             : }
    2241             : 
    2242           0 : void SvxAutoCorrectLanguageLists::SaveWrdSttExceptList()
    2243             : {
    2244           0 :     MakeUserStorage_Impl();
    2245           0 :     SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2246             : 
    2247           0 :     SaveExceptList_Imp( *pWrdStt_ExcptLst, pXMLImplWrdStt_ExcptLstStr, xStg );
    2248             : 
    2249           0 :     xStg = 0;
    2250             :     // Set time stamp
    2251             :     FStatHelper::GetModifiedDateTimeOfFile( sUserAutoCorrFile,
    2252           0 :                                             &aModifiedDate, &aModifiedTime );
    2253           0 :     aLastCheckTime = Time( Time::SYSTEM );
    2254           0 : }
    2255             : 
    2256           0 : void SvxAutoCorrectLanguageLists::SetWrdSttExceptList( SvStringsISortDtor* pList )
    2257             : {
    2258           0 :     if( pWrdStt_ExcptLst && pList != pWrdStt_ExcptLst )
    2259           0 :         delete pWrdStt_ExcptLst;
    2260           0 :     pWrdStt_ExcptLst = pList;
    2261           0 :     if( !pWrdStt_ExcptLst )
    2262             :     {
    2263             :         OSL_ENSURE( !this, "No valid list" );
    2264           0 :         pWrdStt_ExcptLst = new SvStringsISortDtor;
    2265             :     }
    2266           0 :     nFlags |= WrdSttLstLoad;
    2267           0 : }
    2268             : 
    2269           0 : SvStringsISortDtor* SvxAutoCorrectLanguageLists::GetWrdSttExceptList()
    2270             : {
    2271           0 :     if( !( WrdSttLstLoad & nFlags ) || IsFileChanged_Imp() )
    2272           0 :         SetWrdSttExceptList( LoadWrdSttExceptList() );
    2273           0 :     return pWrdStt_ExcptLst;
    2274             : }
    2275             : 
    2276           0 : void SvxAutoCorrectLanguageLists::RemoveStream_Imp( const String& rName )
    2277             : {
    2278           0 :     if( sShareAutoCorrFile != sUserAutoCorrFile )
    2279             :     {
    2280           0 :         SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2281           0 :         if( xStg.Is() && SVSTREAM_OK == xStg->GetError() &&
    2282           0 :             xStg->IsStream( rName ) )
    2283             :         {
    2284           0 :             xStg->Remove( rName );
    2285           0 :             xStg->Commit();
    2286             : 
    2287           0 :             xStg = 0;
    2288           0 :         }
    2289             :     }
    2290           0 : }
    2291             : 
    2292           0 : void SvxAutoCorrectLanguageLists::MakeUserStorage_Impl()
    2293             : {
    2294             :     // The conversion needs to happen if the file is already in the user
    2295             :     // directory and is in the old format. Additionally it needs to
    2296             :     // happen when the file is being copied from share to user.
    2297             : 
    2298           0 :     sal_Bool bError = sal_False, bConvert = sal_False, bCopy = sal_False;
    2299           0 :     INetURLObject aDest;
    2300           0 :     INetURLObject aSource;
    2301             : 
    2302           0 :     if (sUserAutoCorrFile != sShareAutoCorrFile )
    2303             :     {
    2304           0 :         aSource = INetURLObject ( sShareAutoCorrFile );
    2305           0 :         aDest = INetURLObject ( sUserAutoCorrFile );
    2306           0 :         if ( SotStorage::IsOLEStorage ( sShareAutoCorrFile ) )
    2307             :         {
    2308           0 :             aDest.SetExtension ( rtl::OUString("bak") );
    2309           0 :             bConvert = sal_True;
    2310             :         }
    2311           0 :         bCopy = sal_True;
    2312             :     }
    2313           0 :     else if ( SotStorage::IsOLEStorage ( sUserAutoCorrFile ) )
    2314             :     {
    2315           0 :         aSource = INetURLObject ( sUserAutoCorrFile );
    2316           0 :         aDest = INetURLObject ( sUserAutoCorrFile );
    2317           0 :         aDest.SetExtension ( rtl::OUString("bak") );
    2318           0 :         bCopy = bConvert = sal_True;
    2319             :     }
    2320           0 :     if (bCopy)
    2321             :     {
    2322             :         try
    2323             :         {
    2324           0 :             String sMain(aDest.GetMainURL( INetURLObject::DECODE_TO_IURI ));
    2325           0 :             sal_Unicode cSlash = '/';
    2326           0 :             xub_StrLen nSlashPos = sMain.SearchBackward(cSlash);
    2327           0 :             sMain.Erase(nSlashPos);
    2328           0 :             ::ucbhelper::Content aNewContent( sMain, uno::Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext() );
    2329           0 :             Any aAny;
    2330           0 :             TransferInfo aInfo;
    2331           0 :             aInfo.NameClash = NameClash::OVERWRITE;
    2332           0 :             aInfo.NewTitle  = aDest.GetName();
    2333           0 :             aInfo.SourceURL = aSource.GetMainURL( INetURLObject::DECODE_TO_IURI );
    2334           0 :             aInfo.MoveData  = sal_False;
    2335           0 :             aAny <<= aInfo;
    2336           0 :             aNewContent.executeCommand( OUString (  "transfer"  ), aAny);
    2337             :         }
    2338           0 :         catch (...)
    2339             :         {
    2340           0 :             bError = sal_True;
    2341             :         }
    2342             :     }
    2343           0 :     if (bConvert && !bError)
    2344             :     {
    2345           0 :         SotStorageRef xSrcStg = new SotStorage( aDest.GetMainURL( INetURLObject::DECODE_TO_IURI ), STREAM_READ, sal_True );
    2346           0 :         SotStorageRef xDstStg = new SotStorage( sUserAutoCorrFile, STREAM_WRITE, sal_True );
    2347             : 
    2348           0 :         if( xSrcStg.Is() && xDstStg.Is() )
    2349             :         {
    2350           0 :             String sWord        ( RTL_CONSTASCII_USTRINGPARAM ( pImplWrdStt_ExcptLstStr ) );
    2351           0 :             String sSentence    ( RTL_CONSTASCII_USTRINGPARAM ( pImplCplStt_ExcptLstStr ) );
    2352           0 :             String sXMLWord     ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplWrdStt_ExcptLstStr ) );
    2353           0 :             String sXMLSentence ( RTL_CONSTASCII_USTRINGPARAM ( pXMLImplCplStt_ExcptLstStr ) );
    2354           0 :             SvStringsISortDtor  *pTmpWordList = NULL;
    2355             : 
    2356           0 :             if (xSrcStg->IsContained( sXMLWord ) )
    2357           0 :                 LoadXMLExceptList_Imp( pTmpWordList, pXMLImplWrdStt_ExcptLstStr, xSrcStg );
    2358             : 
    2359           0 :             if (pTmpWordList)
    2360             :             {
    2361           0 :                 SaveExceptList_Imp( *pTmpWordList, pXMLImplWrdStt_ExcptLstStr, xDstStg, sal_True );
    2362           0 :                 pTmpWordList->DeleteAndDestroyAll();
    2363           0 :                 pTmpWordList = NULL;
    2364             :             }
    2365             : 
    2366             : 
    2367           0 :             if (xSrcStg->IsContained( sXMLSentence ) )
    2368           0 :                 LoadXMLExceptList_Imp( pTmpWordList, pXMLImplCplStt_ExcptLstStr, xSrcStg );
    2369             : 
    2370           0 :             if (pTmpWordList)
    2371             :             {
    2372           0 :                 SaveExceptList_Imp( *pTmpWordList, pXMLImplCplStt_ExcptLstStr, xDstStg, sal_True );
    2373           0 :                 pTmpWordList->DeleteAndDestroyAll();
    2374             :             }
    2375             : 
    2376           0 :             GetAutocorrWordList();
    2377           0 :             MakeBlocklist_Imp( *xDstStg );
    2378           0 :             sShareAutoCorrFile = sUserAutoCorrFile;
    2379           0 :             xDstStg = 0;
    2380             :             try
    2381             :             {
    2382           0 :                 ::ucbhelper::Content aContent ( aDest.GetMainURL( INetURLObject::DECODE_TO_IURI ), uno::Reference < XCommandEnvironment >(), comphelper::getProcessComponentContext() );
    2383           0 :                 aContent.executeCommand ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "delete" ) ), makeAny ( sal_Bool (sal_True ) ) );
    2384             :             }
    2385           0 :             catch (...)
    2386             :             {
    2387           0 :             }
    2388           0 :         }
    2389             :     }
    2390           0 :     else if( bCopy && !bError )
    2391           0 :         sShareAutoCorrFile = sUserAutoCorrFile;
    2392           0 : }
    2393             : 
    2394           0 : sal_Bool SvxAutoCorrectLanguageLists::MakeBlocklist_Imp( SvStorage& rStg )
    2395             : {
    2396           0 :     String sStrmName( pXMLImplAutocorr_ListStr, RTL_TEXTENCODING_MS_1252 );
    2397           0 :     sal_Bool bRet = sal_True, bRemove = !pAutocorr_List || pAutocorr_List->empty();
    2398           0 :     if( !bRemove )
    2399             :     {
    2400             :         SvStorageStreamRef refList = rStg.OpenSotStream( sStrmName,
    2401           0 :                     ( STREAM_READ | STREAM_WRITE | STREAM_SHARE_DENYWRITE ) );
    2402           0 :         if( refList.Is() )
    2403             :         {
    2404           0 :             refList->SetSize( 0 );
    2405           0 :             refList->SetBufferSize( 8192 );
    2406           0 :             String aPropName( rtl::OUString( "MediaType" ) );
    2407           0 :             OUString aMime( "text/xml" );
    2408           0 :             uno::Any aAny;
    2409           0 :             aAny <<= aMime;
    2410           0 :             refList->SetProperty( aPropName, aAny );
    2411             : 
    2412             :             uno::Reference< lang::XMultiServiceFactory > xServiceFactory =
    2413           0 :                 comphelper::getProcessServiceFactory();
    2414             :             uno::Reference< uno::XComponentContext > xContext =
    2415           0 :                 comphelper::getProcessComponentContext();
    2416             : 
    2417           0 :             uno::Reference < xml::sax::XWriter > xWriter = xml::sax::Writer::create(xContext);
    2418           0 :             uno::Reference < io::XOutputStream> xOut = new utl::OOutputStreamWrapper( *refList );
    2419           0 :             xWriter->setOutputStream(xOut);
    2420             : 
    2421           0 :             uno::Reference<xml::sax::XDocumentHandler> xHandler(xWriter, uno::UNO_QUERY);
    2422           0 :             SvXMLAutoCorrectExport aExp( xServiceFactory, pAutocorr_List, sStrmName, xHandler );
    2423             : 
    2424           0 :             aExp.exportDoc( XML_BLOCK_LIST );
    2425             : 
    2426           0 :             refList->Commit();
    2427           0 :             bRet = SVSTREAM_OK == refList->GetError();
    2428           0 :             if( bRet )
    2429             :             {
    2430           0 :                 refList.Clear();
    2431           0 :                 rStg.Commit();
    2432           0 :                 if( SVSTREAM_OK != rStg.GetError() )
    2433             :                 {
    2434           0 :                     bRemove = sal_True;
    2435           0 :                     bRet = sal_False;
    2436             :                 }
    2437           0 :             }
    2438             :         }
    2439             :         else
    2440           0 :             bRet = sal_False;
    2441             :     }
    2442             : 
    2443           0 :     if( bRemove )
    2444             :     {
    2445           0 :         rStg.Remove( sStrmName );
    2446           0 :         rStg.Commit();
    2447             :     }
    2448             : 
    2449           0 :     return bRet;
    2450             : }
    2451             : 
    2452           0 : sal_Bool SvxAutoCorrectLanguageLists::MakeCombinedChanges( std::vector<SvxAutocorrWord>& aNewEntries, std::vector<SvxAutocorrWord>& aDeleteEntries )
    2453             : {
    2454             :     // First get the current list!
    2455           0 :     GetAutocorrWordList();
    2456             : 
    2457           0 :     MakeUserStorage_Impl();
    2458           0 :     SotStorageRef xStorage = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2459             : 
    2460           0 :     sal_Bool bRet = xStorage.Is() && SVSTREAM_OK == xStorage->GetError();
    2461             : 
    2462           0 :     if( bRet )
    2463             :     {
    2464           0 :         for ( sal_uInt32 i=0; i < aDeleteEntries.size(); i++ )
    2465             :         {
    2466           0 :             SvxAutocorrWord aWordToDelete = aDeleteEntries[i];
    2467           0 :             SvxAutocorrWord *pFoundEntry = pAutocorr_List->FindAndRemove( &aWordToDelete );
    2468           0 :             if( pFoundEntry )
    2469             :             {
    2470           0 :                 if( !pFoundEntry->IsTextOnly() )
    2471             :                 {
    2472           0 :                     String aName( aWordToDelete.GetShort() );
    2473           0 :                     if (xStorage->IsOLEStorage())
    2474           0 :                         EncryptBlockName_Imp( aName );
    2475             :                     else
    2476           0 :                         GeneratePackageName ( aWordToDelete.GetShort(), aName );
    2477             : 
    2478           0 :                     if( xStorage->IsContained( aName ) )
    2479             :                     {
    2480           0 :                         xStorage->Remove( aName );
    2481           0 :                         bRet = xStorage->Commit();
    2482           0 :                     }
    2483             :                 }
    2484           0 :                 delete pFoundEntry;
    2485             :             }
    2486           0 :         }
    2487             : 
    2488           0 :         for ( sal_uInt32 i=0; i < aNewEntries.size(); i++ )
    2489             :         {
    2490           0 :             SvxAutocorrWord *pWordToAdd = new SvxAutocorrWord( aNewEntries[i].GetShort(), aNewEntries[i].GetLong(), sal_True );
    2491           0 :             SvxAutocorrWord *pRemoved = pAutocorr_List->FindAndRemove( pWordToAdd );
    2492           0 :             if( pRemoved )
    2493             :             {
    2494           0 :                 if( !pRemoved->IsTextOnly() )
    2495             :                 {
    2496             :                     // Still have to remove the Storage
    2497           0 :                     String sStorageName( pWordToAdd->GetShort() );
    2498           0 :                     if (xStorage->IsOLEStorage())
    2499           0 :                         EncryptBlockName_Imp( sStorageName );
    2500             :                     else
    2501           0 :                         GeneratePackageName ( pWordToAdd->GetShort(), sStorageName);
    2502             : 
    2503           0 :                     if( xStorage->IsContained( sStorageName ) )
    2504           0 :                         xStorage->Remove( sStorageName );
    2505             :                 }
    2506           0 :                 delete pRemoved;
    2507             :             }
    2508           0 :             bRet = pAutocorr_List->Insert( pWordToAdd );
    2509             : 
    2510           0 :             if ( !bRet )
    2511             :             {
    2512           0 :                 delete pWordToAdd;
    2513           0 :                 break;
    2514             :             }
    2515             :         }
    2516             : 
    2517           0 :         if ( bRet )
    2518             :         {
    2519           0 :             bRet = MakeBlocklist_Imp( *xStorage );
    2520             :         }
    2521             :     }
    2522           0 :     return bRet;
    2523             : }
    2524             : 
    2525           0 : sal_Bool SvxAutoCorrectLanguageLists::PutText( const String& rShort, const String& rLong )
    2526             : {
    2527             :     // First get the current list!
    2528           0 :     GetAutocorrWordList();
    2529             : 
    2530           0 :     MakeUserStorage_Impl();
    2531           0 :     SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2532             : 
    2533           0 :     sal_Bool bRet = xStg.Is() && SVSTREAM_OK == xStg->GetError();
    2534             : 
    2535             :     // Update the word list
    2536           0 :     if( bRet )
    2537             :     {
    2538           0 :         SvxAutocorrWord* pNew = new SvxAutocorrWord( rShort, rLong, sal_True );
    2539           0 :         SvxAutocorrWord *pRemove = pAutocorr_List->FindAndRemove( pNew );
    2540           0 :         if( pRemove )
    2541             :         {
    2542           0 :             if( !pRemove->IsTextOnly() )
    2543             :             {
    2544             :                 // Still have to remove the Storage
    2545           0 :                 String sStgNm( rShort );
    2546           0 :                 if (xStg->IsOLEStorage())
    2547           0 :                     EncryptBlockName_Imp( sStgNm );
    2548             :                 else
    2549           0 :                     GeneratePackageName ( rShort, sStgNm);
    2550             : 
    2551           0 :                 if( xStg->IsContained( sStgNm ) )
    2552           0 :                     xStg->Remove( sStgNm );
    2553             :             }
    2554           0 :             delete pRemove;
    2555             :         }
    2556             : 
    2557           0 :         if( pAutocorr_List->Insert( pNew ) )
    2558             :         {
    2559           0 :             bRet = MakeBlocklist_Imp( *xStg );
    2560           0 :             xStg = 0;
    2561             :         }
    2562             :         else
    2563             :         {
    2564           0 :             delete pNew;
    2565           0 :             bRet = sal_False;
    2566             :         }
    2567             :     }
    2568           0 :     return bRet;
    2569             : }
    2570             : 
    2571           0 : sal_Bool SvxAutoCorrectLanguageLists::PutText( const String& rShort,
    2572             :                                                SfxObjectShell& rShell )
    2573             : {
    2574             :     // First get the current list!
    2575           0 :     GetAutocorrWordList();
    2576             : 
    2577           0 :     MakeUserStorage_Impl();
    2578             : 
    2579           0 :     sal_Bool bRet = sal_False;
    2580           0 :     String sLong;
    2581             :     try
    2582             :     {
    2583           0 :         uno::Reference < embed::XStorage > xStg = comphelper::OStorageHelper::GetStorageFromURL( sUserAutoCorrFile, embed::ElementModes::READWRITE );
    2584           0 :         bRet = rAutoCorrect.PutText( xStg, sUserAutoCorrFile, rShort, rShell, sLong );
    2585           0 :         xStg = 0;
    2586             : 
    2587             :         // Update the word list
    2588           0 :         if( bRet )
    2589             :         {
    2590           0 :             SvxAutocorrWord* pNew = new SvxAutocorrWord( rShort, sLong, sal_False );
    2591           0 :             if( pAutocorr_List->Insert( pNew ) )
    2592             :             {
    2593           0 :                 SotStorageRef xStor = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2594           0 :                 MakeBlocklist_Imp( *xStor );
    2595             :             }
    2596             :             else
    2597           0 :                 delete pNew;
    2598           0 :         }
    2599             :     }
    2600           0 :     catch ( const uno::Exception& )
    2601             :     {
    2602             :     }
    2603             : 
    2604           0 :     return bRet;
    2605             : }
    2606             : 
    2607             : // Delete an entry
    2608           0 : sal_Bool SvxAutoCorrectLanguageLists::DeleteText( const String& rShort )
    2609             : {
    2610             :     // First get the current list!
    2611           0 :     GetAutocorrWordList();
    2612             : 
    2613           0 :     MakeUserStorage_Impl();
    2614             : 
    2615           0 :     SotStorageRef xStg = new SotStorage( sUserAutoCorrFile, STREAM_READWRITE, sal_True );
    2616           0 :     sal_Bool bRet = xStg.Is() && SVSTREAM_OK == xStg->GetError();
    2617           0 :     if( bRet )
    2618             :     {
    2619           0 :         SvxAutocorrWord aTmp( rShort, rShort );
    2620           0 :         SvxAutocorrWord *pFnd = pAutocorr_List->FindAndRemove( &aTmp );
    2621           0 :         if( pFnd )
    2622             :         {
    2623           0 :             if( !pFnd->IsTextOnly() )
    2624             :             {
    2625           0 :                 String aName( rShort );
    2626           0 :                 if (xStg->IsOLEStorage())
    2627           0 :                     EncryptBlockName_Imp( aName );
    2628             :                 else
    2629           0 :                     GeneratePackageName ( rShort, aName );
    2630           0 :                 if( xStg->IsContained( aName ) )
    2631             :                 {
    2632           0 :                     xStg->Remove( aName );
    2633           0 :                     bRet = xStg->Commit();
    2634           0 :                 }
    2635             : 
    2636             :             }
    2637           0 :             delete pFnd;
    2638           0 :             MakeBlocklist_Imp( *xStg );
    2639           0 :             xStg = 0;
    2640             :         }
    2641             :         else
    2642           0 :             bRet = sal_False;
    2643             :     }
    2644           0 :     return bRet;
    2645             : }
    2646             : 
    2647             : // Keep the list sorted ...
    2648           0 : bool CompareSvxAutocorrWordList::operator()( SvxAutocorrWord* const& lhs, SvxAutocorrWord* const& rhs ) const
    2649             : {
    2650           0 :     CollatorWrapper& rCmp = ::GetCollatorWrapper();
    2651           0 :     return rCmp.compareString( lhs->GetShort(), rhs->GetShort() ) < 0;
    2652             : }
    2653             : 
    2654           0 : SvxAutocorrWordList::~SvxAutocorrWordList()
    2655             : {
    2656           0 :     DeleteAndDestroyAll();
    2657           0 : }
    2658             : 
    2659           0 : void SvxAutocorrWordList::DeleteAndDestroyAll()
    2660             : {
    2661           0 :     for( SvxAutocorrWordList_Hash::const_iterator it = maHash.begin(); it != maHash.end(); ++it )
    2662           0 :         delete it->second;
    2663           0 :     maHash.clear();
    2664             : 
    2665           0 :     for( SvxAutocorrWordList_Set::const_iterator it2 = maSet.begin(); it2 != maSet.end(); ++it2 )
    2666           0 :         delete *it2;
    2667           0 :     maSet.clear();
    2668           0 : }
    2669             : 
    2670             : // returns true if inserted
    2671           0 : bool SvxAutocorrWordList::Insert(SvxAutocorrWord *pWord)
    2672             : {
    2673           0 :     if ( maSet.empty() ) // use the hash
    2674             :     {
    2675           0 :         rtl::OUString aShort( pWord->GetShort() );
    2676           0 :         return maHash.insert( std::pair<rtl::OUString, SvxAutocorrWord *>( aShort, pWord ) ).second;
    2677             :     }
    2678             :     else
    2679           0 :         return maSet.insert( pWord ).second;
    2680             : }
    2681             : 
    2682           0 : void SvxAutocorrWordList::LoadEntry(String sWrong, String sRight, sal_Bool bOnlyTxt)
    2683             : {
    2684           0 :     SvxAutocorrWord* pNew = new SvxAutocorrWord( sWrong, sRight, bOnlyTxt );
    2685           0 :     if( !Insert( pNew ) )
    2686           0 :         delete pNew;
    2687           0 : }
    2688             : 
    2689           0 : bool SvxAutocorrWordList::empty() const
    2690             : {
    2691           0 :     return maHash.empty() && maSet.empty();
    2692             : }
    2693             : 
    2694           0 : SvxAutocorrWord *SvxAutocorrWordList::FindAndRemove(SvxAutocorrWord *pWord)
    2695             : {
    2696           0 :     SvxAutocorrWord *pMatch = NULL;
    2697             : 
    2698           0 :     if ( maSet.empty() ) // use the hash
    2699             :     {
    2700           0 :         SvxAutocorrWordList_Hash::iterator it = maHash.find( pWord->GetShort() );
    2701           0 :         if( it != maHash.end() )
    2702             :         {
    2703           0 :             pMatch = it->second;
    2704           0 :             maHash.erase (it);
    2705             :         }
    2706             :     }
    2707             :     else
    2708             :     {
    2709           0 :         SvxAutocorrWordList_Set::iterator it = maSet.find( pWord );
    2710           0 :         if( it != maSet.end() )
    2711             :         {
    2712           0 :             pMatch = *it;
    2713           0 :             maSet.erase (it);
    2714             :         }
    2715             :     }
    2716           0 :     return pMatch;
    2717             : }
    2718             : 
    2719             : // return the sorted contents - defer sorting until we have to.
    2720           0 : SvxAutocorrWordList::Content SvxAutocorrWordList::getSortedContent() const
    2721             : {
    2722           0 :     Content aContent;
    2723             : 
    2724             :     // convert from hash to set permanantly
    2725           0 :     if ( maSet.empty() )
    2726             :     {
    2727             :         // This beasty has some O(N log(N)) in a terribly slow ICU collate fn.
    2728           0 :         for( SvxAutocorrWordList_Hash::const_iterator it = maHash.begin(); it != maHash.end(); ++it )
    2729           0 :             maSet.insert( it->second );
    2730           0 :         maHash.clear();
    2731             :     }
    2732           0 :     for( SvxAutocorrWordList_Set::const_iterator it = maSet.begin(); it != maSet.end(); ++it )
    2733           0 :         aContent.push_back( *it );
    2734             : 
    2735           0 :     return aContent;
    2736             : }
    2737             : 
    2738           0 : bool SvxAutocorrWordList::WordMatches(const SvxAutocorrWord *pFnd,
    2739             :                                       const String &rTxt,
    2740             :                                       xub_StrLen &rStt,
    2741             :                                       xub_StrLen nEndPos) const
    2742             : {
    2743           0 :     const String& rChk = pFnd->GetShort();
    2744           0 :     if( nEndPos >= rChk.Len() )
    2745             :     {
    2746           0 :         xub_StrLen nCalcStt = nEndPos - rChk.Len();
    2747           0 :         if( ( !nCalcStt || nCalcStt == rStt ||
    2748             :               ( nCalcStt < rStt &&
    2749           0 :                 IsWordDelim( rTxt.GetChar( nCalcStt - 1 ) ))) )
    2750             :         {
    2751           0 :             TransliterationWrapper& rCmp = GetIgnoreTranslWrapper();
    2752             : 
    2753           0 :             rtl::OUString sWord(rTxt.GetBuffer() + nCalcStt, rChk.Len());
    2754           0 :             if( rCmp.isEqual( rChk, sWord ))
    2755             :             {
    2756           0 :                 rStt = nCalcStt;
    2757           0 :                 return true;
    2758           0 :             }
    2759             :         }
    2760             :     }
    2761           0 :     return false;
    2762             : }
    2763             : 
    2764           0 : const SvxAutocorrWord* SvxAutocorrWordList::SearchWordsInList(const String& rTxt, xub_StrLen& rStt,
    2765             :                                                               xub_StrLen nEndPos) const
    2766             : {
    2767           0 :     for( SvxAutocorrWordList_Hash::const_iterator it = maHash.begin(); it != maHash.end(); ++it )
    2768             :     {
    2769           0 :         if( WordMatches( it->second, rTxt, rStt, nEndPos ) )
    2770           0 :             return it->second;
    2771             :     }
    2772             : 
    2773           0 :     for( SvxAutocorrWordList_Set::const_iterator it2 = maSet.begin(); it2 != maSet.end(); ++it2 )
    2774             :     {
    2775           0 :         if( WordMatches( *it2, rTxt, rStt, nEndPos ) )
    2776           0 :             return *it2;
    2777             :     }
    2778           0 :     return 0;
    2779             : }
    2780             : 
    2781             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10