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

Generated by: LCOV version 1.10