LCOV - code coverage report
Current view: top level - sc/source/core/tool - compiler.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1255 2730 46.0 %
Date: 2012-08-25 Functions: 92 142 64.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1088 4160 26.2 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include <sfx2/app.hxx>
      30                 :            : #include <sfx2/objsh.hxx>
      31                 :            : #include <basic/sbmeth.hxx>
      32                 :            : #include <basic/sbstar.hxx>
      33                 :            : #include <svl/zforlist.hxx>
      34                 :            : #include <sal/macros.h>
      35                 :            : #include <tools/rcid.h>
      36                 :            : #include <tools/solar.h>
      37                 :            : #include <unotools/charclass.hxx>
      38                 :            : #include <com/sun/star/lang/Locale.hpp>
      39                 :            : #include <com/sun/star/sheet/FormulaOpCodeMapEntry.hpp>
      40                 :            : #include <com/sun/star/sheet/FormulaLanguage.hpp>
      41                 :            : #include <com/sun/star/sheet/FormulaMapGroup.hpp>
      42                 :            : #include <comphelper/processfactory.hxx>
      43                 :            : #include <comphelper/string.hxx>
      44                 :            : #include <unotools/transliterationwrapper.hxx>
      45                 :            : #include <tools/urlobj.hxx>
      46                 :            : #include <rtl/math.hxx>
      47                 :            : #include <rtl/ustring.hxx>
      48                 :            : #include <ctype.h>
      49                 :            : #include <stdio.h>
      50                 :            : #include <stdlib.h>
      51                 :            : #include <string.h>
      52                 :            : #include <math.h>
      53                 :            : #include "compiler.hxx"
      54                 :            : #include "rangenam.hxx"
      55                 :            : #include "dbdata.hxx"
      56                 :            : #include "document.hxx"
      57                 :            : #include "callform.hxx"
      58                 :            : #include "addincol.hxx"
      59                 :            : #include "refupdat.hxx"
      60                 :            : #include "scresid.hxx"
      61                 :            : #include "sc.hrc"
      62                 :            : #include "globstr.hrc"
      63                 :            : #include "cell.hxx"
      64                 :            : #include "dociter.hxx"
      65                 :            : #include "docoptio.hxx"
      66                 :            : #include <formula/errorcodes.hxx>
      67                 :            : #include "parclass.hxx"
      68                 :            : #include "autonamecache.hxx"
      69                 :            : #include "externalrefmgr.hxx"
      70                 :            : #include "rangeutl.hxx"
      71                 :            : #include "convuno.hxx"
      72                 :            : #include "tokenuno.hxx"
      73                 :            : #include "formulaparserpool.hxx"
      74                 :            : 
      75                 :            : using namespace formula;
      76                 :            : using namespace ::com::sun::star;
      77                 :            : using rtl::OUString;
      78                 :            : using ::std::vector;
      79                 :            : 
      80                 :            : 
      81                 :            : CharClass*                          ScCompiler::pCharClassEnglish = NULL;
      82                 :            : const ScCompiler::Convention*       ScCompiler::pConventions[ ]   = { NULL, NULL, NULL, NULL, NULL, NULL };
      83                 :            : 
      84                 :            : enum ScanState
      85                 :            : {
      86                 :            :     ssGetChar,
      87                 :            :     ssGetBool,
      88                 :            :     ssGetValue,
      89                 :            :     ssGetString,
      90                 :            :     ssSkipString,
      91                 :            :     ssGetIdent,
      92                 :            :     ssGetReference,
      93                 :            :     ssSkipReference,
      94                 :            :     ssGetErrorConstant,
      95                 :            :     ssStop
      96                 :            : };
      97                 :            : 
      98                 :            : static const sal_Char* pInternal[ 1 ] = { "TTT" };
      99                 :            : 
     100                 :            : using namespace ::com::sun::star::i18n;
     101                 :            : 
     102                 :            : /////////////////////////////////////////////////////////////////////////
     103                 :            : 
     104                 :            : 
     105                 :            : 
     106                 :            : class ScCompilerRecursionGuard
     107                 :            : {
     108                 :            : private:
     109                 :            :             short&              rRecursion;
     110                 :            : public:
     111                 :            :                                 ScCompilerRecursionGuard( short& rRec )
     112                 :            :                                     : rRecursion( rRec ) { ++rRecursion; }
     113                 :            :                                 ~ScCompilerRecursionGuard() { --rRecursion; }
     114                 :            : };
     115                 :            : 
     116                 :            : 
     117                 :         29 : void ScCompiler::fillFromAddInMap( NonConstOpCodeMapPtr xMap,FormulaGrammar::Grammar _eGrammar  ) const
     118                 :            : {
     119                 :            :     size_t nSymbolOffset;
     120      [ +  +  + ]:         29 :     switch( _eGrammar )
     121                 :            :     {
     122                 :            :         case FormulaGrammar::GRAM_PODF:
     123                 :         11 :             nSymbolOffset = offsetof( AddInMap, pUpper);
     124                 :         11 :             break;
     125                 :            :         default:
     126                 :            :         case FormulaGrammar::GRAM_ODFF:
     127                 :         14 :             nSymbolOffset = offsetof( AddInMap, pODFF);
     128                 :         14 :             break;
     129                 :            :         case FormulaGrammar::GRAM_ENGLISH:
     130                 :          4 :             nSymbolOffset = offsetof( AddInMap, pEnglish);
     131                 :          4 :             break;
     132                 :            :     }
     133                 :         29 :     const AddInMap* pMap = GetAddInMap();
     134                 :         29 :     const AddInMap* const pStop = pMap + GetAddInMapCount();
     135         [ +  + ]:       3190 :     for ( ; pMap < pStop; ++pMap)
     136                 :            :     {
     137                 :            :         char const * const * ppSymbol =
     138                 :            :             reinterpret_cast< char const * const * >(
     139                 :       3161 :                     reinterpret_cast< char const * >(pMap) + nSymbolOffset);
     140                 :            :         xMap->putExternal( rtl::OUString::createFromAscii( *ppSymbol),
     141 [ +  - ][ +  - ]:       3161 :                 rtl::OUString::createFromAscii( pMap->pOriginal));
         [ +  - ][ +  - ]
                 [ +  - ]
     142                 :            :     }
     143                 :         29 : }
     144                 :            : 
     145                 :         25 : void ScCompiler::fillFromAddInCollectionUpperName( NonConstOpCodeMapPtr xMap ) const
     146                 :            : {
     147                 :         25 :     ScUnoAddInCollection* pColl = ScGlobal::GetAddInCollection();
     148                 :         25 :     long nCount = pColl->GetFuncCount();
     149         [ +  + ]:       1664 :     for (long i=0; i < nCount; ++i)
     150                 :            :     {
     151                 :       1639 :         const ScUnoAddInFuncData* pFuncData = pColl->GetFuncData(i);
     152         [ +  + ]:       1639 :         if (pFuncData)
     153                 :       1199 :             xMap->putExternalSoftly( pFuncData->GetUpperName(),
     154 [ +  - ][ +  - ]:       2398 :                     pFuncData->GetOriginalName());
                 [ +  - ]
     155                 :            :     }
     156                 :         25 : }
     157                 :            : 
     158                 :          4 : void ScCompiler::fillFromAddInCollectionEnglishName( NonConstOpCodeMapPtr xMap ) const
     159                 :            : {
     160                 :          4 :     ScUnoAddInCollection* pColl = ScGlobal::GetAddInCollection();
     161                 :          4 :     long nCount = pColl->GetFuncCount();
     162         [ +  + ]:        153 :     for (long i=0; i < nCount; ++i)
     163                 :            :     {
     164                 :        149 :         const ScUnoAddInFuncData* pFuncData = pColl->GetFuncData(i);
     165         [ +  + ]:        149 :         if (pFuncData)
     166                 :            :         {
     167                 :        109 :             ::rtl::OUString aName;
     168 [ +  - ][ +  - ]:        109 :             if (pFuncData->GetExcelName( LANGUAGE_ENGLISH_US, aName))
     169 [ +  - ][ +  - ]:        109 :                 xMap->putExternalSoftly( aName, pFuncData->GetOriginalName());
         [ +  - ][ +  - ]
                 [ +  - ]
     170                 :            :             else
     171                 :          0 :                 xMap->putExternalSoftly( pFuncData->GetUpperName(),
     172   [ #  #  #  # ]:        109 :                         pFuncData->GetOriginalName());
         [ #  # ][ #  # ]
                 [ #  # ]
     173                 :            :         }
     174                 :            :     }
     175                 :          4 : }
     176                 :            : 
     177                 :         18 : void ScCompiler::DeInit()
     178                 :            : {
     179         [ +  + ]:         18 :     if (pCharClassEnglish)
     180                 :            :     {
     181         [ +  - ]:          5 :         delete pCharClassEnglish;
     182                 :          5 :         pCharClassEnglish = NULL;
     183                 :            :     }
     184                 :         18 : }
     185                 :            : 
     186                 :          0 : bool ScCompiler::IsEnglishSymbol( const String& rName )
     187                 :            : {
     188                 :            :     // function names are always case-insensitive
     189 [ #  # ][ #  # ]:          0 :     rtl::OUString aUpper = ScGlobal::pCharClass->uppercase(rName);
     190                 :            : 
     191                 :            :     // 1. built-in function name
     192 [ #  # ][ #  # ]:          0 :     OpCode eOp = ScCompiler::GetEnglishOpCode( aUpper );
                 [ #  # ]
     193         [ #  # ]:          0 :     if ( eOp != ocNone )
     194                 :            :     {
     195                 :          0 :         return true;
     196                 :            :     }
     197                 :            :     // 2. old add in functions
     198 [ #  # ][ #  # ]:          0 :     if (ScGlobal::GetFuncCollection()->findByName(aUpper))
                 [ #  # ]
     199                 :            :     {
     200                 :          0 :         return true;
     201                 :            :     }
     202                 :            : 
     203                 :            :     // 3. new (uno) add in functions
     204 [ #  # ][ #  # ]:          0 :     rtl::OUString aIntName = ScGlobal::GetAddInCollection()->FindFunction(aUpper, false);
     205         [ #  # ]:          0 :     if (!aIntName.isEmpty())
     206                 :            :     {
     207                 :          0 :         return true;
     208                 :            :     }
     209                 :          0 :     return false;       // no valid function name
     210                 :            : }
     211                 :            : 
     212                 :         22 : void ScCompiler::InitCharClassEnglish()
     213                 :            : {
     214                 :            :     ::com::sun::star::lang::Locale aLocale(
     215                 :            :             OUString( RTL_CONSTASCII_USTRINGPARAM( "en")),
     216                 :            :             OUString( RTL_CONSTASCII_USTRINGPARAM( "US")),
     217 [ +  - ][ +  - ]:         22 :             OUString());
     218                 :            :     pCharClassEnglish = new CharClass(
     219 [ +  - ][ +  - ]:         22 :             ::comphelper::getProcessServiceFactory(), aLocale);
                 [ +  - ]
     220                 :         22 : }
     221                 :            : 
     222                 :            : 
     223                 :      33484 : void ScCompiler::SetGrammar( const FormulaGrammar::Grammar eGrammar )
     224                 :            : {
     225                 :            :     OSL_ENSURE( eGrammar != FormulaGrammar::GRAM_UNSPECIFIED, "ScCompiler::SetGrammar: don't pass FormulaGrammar::GRAM_UNSPECIFIED");
     226         [ +  + ]:      33484 :     if (eGrammar == GetGrammar())
     227                 :      33484 :         return;     // nothing to be done
     228                 :            : 
     229         [ -  + ]:      33361 :     if( eGrammar == FormulaGrammar::GRAM_EXTERNAL )
     230                 :            :     {
     231                 :          0 :         meGrammar = eGrammar;
     232         [ #  # ]:          0 :         mxSymbols = GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE);
     233                 :            :     }
     234                 :            :     else
     235                 :            :     {
     236                 :      33361 :         FormulaGrammar::Grammar eMyGrammar = eGrammar;
     237                 :      33361 :         const sal_Int32 nFormulaLanguage = FormulaGrammar::extractFormulaLanguage( eMyGrammar);
     238         [ +  - ]:      33361 :         OpCodeMapPtr xMap = GetOpCodeMap( nFormulaLanguage);
     239                 :            :         OSL_ENSURE( xMap, "ScCompiler::SetGrammar: unknown formula language");
     240         [ -  + ]:      33361 :         if (!xMap)
     241                 :            :         {
     242 [ #  # ][ #  # ]:          0 :             xMap = GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE);
                 [ #  # ]
     243                 :          0 :             eMyGrammar = xMap->getGrammar();
     244                 :            :         }
     245                 :            : 
     246                 :            :         // Save old grammar for call to SetGrammarAndRefConvention().
     247                 :      33361 :         FormulaGrammar::Grammar eOldGrammar = GetGrammar();
     248                 :            :         // This also sets the grammar associated with the map!
     249         [ +  - ]:      33361 :         SetFormulaLanguage( xMap);
     250                 :            : 
     251                 :            :         // Override if necessary.
     252         [ +  + ]:      33361 :         if (eMyGrammar != GetGrammar())
     253 [ +  - ][ +  - ]:      33361 :             SetGrammarAndRefConvention( eMyGrammar, eOldGrammar);
     254                 :            :     }
     255                 :            : }
     256                 :            : 
     257                 :         11 : ScCompiler::EncodeUrlMode ScCompiler::GetEncodeUrlMode() const
     258                 :            : {
     259                 :         11 :     return meEncodeUrlMode;
     260                 :            : }
     261                 :            : 
     262                 :      33478 : void ScCompiler::SetFormulaLanguage( const ScCompiler::OpCodeMapPtr & xMap )
     263                 :            : {
     264         [ +  - ]:      33478 :     if (xMap.get())
     265                 :            :     {
     266                 :      33478 :         mxSymbols = xMap;
     267         [ +  + ]:      33478 :         if (mxSymbols->isEnglish())
     268                 :            :         {
     269         [ +  + ]:       3083 :             if (!pCharClassEnglish)
     270                 :         22 :                 InitCharClassEnglish();
     271                 :       3083 :             pCharClass = pCharClassEnglish;
     272                 :            :         }
     273                 :            :         else
     274                 :      30395 :             pCharClass = ScGlobal::pCharClass;
     275                 :      33478 :         SetGrammarAndRefConvention( mxSymbols->getGrammar(), GetGrammar());
     276                 :            :     }
     277                 :      33478 : }
     278                 :            : 
     279                 :            : 
     280                 :      35825 : void ScCompiler::SetGrammarAndRefConvention(
     281                 :            :         const FormulaGrammar::Grammar eNewGrammar, const FormulaGrammar::Grammar eOldGrammar )
     282                 :            : {
     283                 :      35825 :     meGrammar = eNewGrammar;    //! SetRefConvention needs the new grammar set!
     284                 :      35825 :     FormulaGrammar::AddressConvention eConv = FormulaGrammar::extractRefConvention( meGrammar);
     285 [ +  + ][ +  + ]:      35825 :     if (eConv == FormulaGrammar::CONV_UNSPECIFIED && eOldGrammar == FormulaGrammar::GRAM_UNSPECIFIED)
     286                 :            :     {
     287         [ +  - ]:      64816 :         if (pDoc)
     288                 :      32408 :             SetRefConvention( pDoc->GetAddressConvention());
     289                 :            :         else
     290                 :          0 :             SetRefConvention( pConvOOO_A1);
     291                 :            :     }
     292                 :            :     else
     293                 :       3417 :         SetRefConvention( eConv );
     294                 :      35825 : }
     295                 :            : 
     296                 :          0 : String ScCompiler::FindAddInFunction( const String& rUpperName, bool bLocalFirst ) const
     297                 :            : {
     298 [ #  # ][ #  # ]:          0 :     return ScGlobal::GetAddInCollection()->FindFunction(rUpperName, bLocalFirst);    // bLocalFirst=false for english
                 [ #  # ]
     299                 :            : }
     300                 :            : 
     301                 :            : 
     302                 :            : //-----------------------------------------------------------------------------
     303                 :            : 
     304                 :        255 : ScCompiler::Convention::~Convention()
     305                 :            : {
     306         [ +  - ]:        255 :     delete [] mpCharTable;
     307                 :        255 :     mpCharTable = NULL;
     308         [ -  + ]:        255 : }
     309                 :            : 
     310                 :        255 : ScCompiler::Convention::Convention( FormulaGrammar::AddressConvention eConv )
     311                 :            :         :
     312                 :        255 :     meConv( eConv )
     313                 :            : {
     314                 :            :     int i;
     315                 :        255 :     sal_uLong *t= new sal_uLong [128];
     316                 :            : 
     317                 :        255 :     ScCompiler::pConventions[ meConv ] = this;
     318                 :        255 :     mpCharTable = t;
     319                 :            : 
     320         [ +  + ]:      32895 :     for (i = 0; i < 128; i++)
     321                 :      32640 :         t[i] = SC_COMPILER_C_ILLEGAL;
     322                 :            : 
     323                 :        255 : /*   */     t[32] = SC_COMPILER_C_CHAR_DONTCARE | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     324                 :        255 : /* ! */     t[33] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     325         [ +  + ]:        255 :     if (FormulaGrammar::CONV_ODF == meConv)
     326                 :         51 : /* ! */     t[33] |= SC_COMPILER_C_ODF_LABEL_OP;
     327                 :        255 : /* " */     t[34] = SC_COMPILER_C_CHAR_STRING | SC_COMPILER_C_STRING_SEP;
     328                 :        255 : /* # */     t[35] = SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_CHAR_ERRCONST;
     329                 :        255 : /* $ */     t[36] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
     330         [ +  + ]:        255 :     if (FormulaGrammar::CONV_ODF == meConv)
     331                 :         51 : /* $ */     t[36] |= SC_COMPILER_C_ODF_NAME_MARKER;
     332                 :        255 : /* % */     t[37] = SC_COMPILER_C_VALUE;
     333                 :        255 : /* & */     t[38] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     334                 :        255 : /* ' */     t[39] = SC_COMPILER_C_NAME_SEP;
     335                 :        255 : /* ( */     t[40] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     336                 :        255 : /* ) */     t[41] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     337                 :        255 : /* * */     t[42] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     338                 :        255 : /* + */     t[43] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
     339                 :        255 : /* , */     t[44] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE;
     340                 :        255 : /* - */     t[45] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
     341                 :        255 : /* . */     t[46] = SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE | SC_COMPILER_C_IDENT | SC_COMPILER_C_NAME;
     342                 :        255 : /* / */     t[47] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     343                 :            : 
     344         [ +  + ]:       2805 :     for (i = 48; i < 58; i++)
     345                 :       2550 : /* 0-9 */   t[i] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_WORD | SC_COMPILER_C_VALUE | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_VALUE | SC_COMPILER_C_IDENT | SC_COMPILER_C_NAME;
     346                 :            : 
     347                 :        255 : /* : */     t[58] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD;
     348                 :        255 : /* ; */     t[59] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     349                 :        255 : /* < */     t[60] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     350                 :        255 : /* = */     t[61] = SC_COMPILER_C_CHAR | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     351                 :        255 : /* > */     t[62] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     352                 :        255 : /* ? */     t[63] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_NAME;
     353                 :            : /* @ */     // FREE
     354                 :            : 
     355         [ +  + ]:       6885 :     for (i = 65; i < 91; i++)
     356                 :       6630 : /* A-Z */   t[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT | SC_COMPILER_C_CHAR_NAME | SC_COMPILER_C_NAME;
     357                 :            : 
     358         [ +  + ]:        255 :     if (FormulaGrammar::CONV_ODF == meConv)
     359                 :            :     {
     360                 :         51 : /* [ */     t[91] = SC_COMPILER_C_ODF_LBRACKET;
     361                 :            : /* \ */     // FREE
     362                 :         51 : /* ] */     t[93] = SC_COMPILER_C_ODF_RBRACKET;
     363                 :            :     }
     364                 :            :     else
     365                 :            :     {
     366                 :            : /* [ */     // FREE
     367                 :            : /* \ */     // FREE
     368                 :            : /* ] */     // FREE
     369                 :            :     }
     370                 :        255 : /* ^ */     t[94] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     371                 :        255 : /* _ */     t[95] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT | SC_COMPILER_C_CHAR_NAME | SC_COMPILER_C_NAME;
     372                 :            : /* ` */     // FREE
     373                 :            : 
     374         [ +  + ]:       6885 :     for (i = 97; i < 123; i++)
     375                 :       6630 : /* a-z */   t[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT | SC_COMPILER_C_CHAR_NAME | SC_COMPILER_C_NAME;
     376                 :            : 
     377                 :        255 : /* { */     t[123] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP; // array open
     378                 :        255 : /* | */     t[124] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP; // array row sep (Should be OOo specific)
     379                 :        255 : /* } */     t[125] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP; // array close
     380                 :        255 : /* ~ */     t[126] = SC_COMPILER_C_CHAR;        // OOo specific
     381                 :            : /* 127 */   // FREE
     382                 :            : 
     383 [ +  + ][ +  + ]:        255 :     if( FormulaGrammar::CONV_XL_A1 == meConv || FormulaGrammar::CONV_XL_R1C1 == meConv || FormulaGrammar::CONV_XL_OOX == meConv )
                 [ +  + ]
     384                 :            :     {
     385                 :        153 : /*   */     t[32] |=   SC_COMPILER_C_WORD;
     386                 :        153 : /* ! */     t[33] |=   SC_COMPILER_C_IDENT | SC_COMPILER_C_WORD;
     387                 :        153 : /* " */     t[34] |=   SC_COMPILER_C_WORD;
     388                 :        153 : /* # */     t[35] &= (~SC_COMPILER_C_WORD_SEP);
     389                 :        153 : /* # */     t[35] |=   SC_COMPILER_C_WORD;
     390                 :        153 : /* % */     t[37] |=   SC_COMPILER_C_WORD;
     391                 :        153 : /* ' */     t[39] |=   SC_COMPILER_C_WORD;
     392                 :            : 
     393                 :        153 : /* % */     t[37] |=   SC_COMPILER_C_WORD;
     394                 :        153 : /* & */     t[38] |=   SC_COMPILER_C_WORD;
     395                 :        153 : /* ' */     t[39] |=   SC_COMPILER_C_WORD;
     396                 :        153 : /* ( */     t[40] |=   SC_COMPILER_C_WORD;
     397                 :        153 : /* ) */     t[41] |=   SC_COMPILER_C_WORD;
     398                 :        153 : /* * */     t[42] |=   SC_COMPILER_C_WORD;
     399                 :        153 : /* + */     t[43] |=   SC_COMPILER_C_WORD;
     400                 :            : #if 0 /* this really needs to be locale specific. */
     401                 :            : /* , */     t[44]  =   SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
     402                 :            : #else
     403                 :        153 : /* , */     t[44] |=   SC_COMPILER_C_WORD;
     404                 :            : #endif
     405                 :        153 : /* - */     t[45] |=   SC_COMPILER_C_WORD;
     406                 :            : 
     407                 :        153 : /* ; */     t[59] |=   SC_COMPILER_C_WORD;
     408                 :        153 : /* < */     t[60] |=   SC_COMPILER_C_WORD;
     409                 :        153 : /* = */     t[61] |=   SC_COMPILER_C_WORD;
     410                 :        153 : /* > */     t[62] |=   SC_COMPILER_C_WORD;
     411                 :            : /* ? */     // question really is not permitted in sheet name
     412                 :        153 : /* @ */     t[64] |=   SC_COMPILER_C_WORD;
     413                 :        153 : /* [ */     t[91] |=   SC_COMPILER_C_WORD;
     414                 :        153 : /* ] */     t[93] |=   SC_COMPILER_C_WORD;
     415                 :        153 : /* { */     t[123]|=   SC_COMPILER_C_WORD;
     416                 :        153 : /* | */     t[124]|=   SC_COMPILER_C_WORD;
     417                 :        153 : /* } */     t[125]|=   SC_COMPILER_C_WORD;
     418                 :        153 : /* ~ */     t[126]|=   SC_COMPILER_C_WORD;
     419                 :            : 
     420         [ +  + ]:        153 :         if( FormulaGrammar::CONV_XL_R1C1 == meConv )
     421                 :            :         {
     422                 :         51 : /* [ */     t[91] |= SC_COMPILER_C_IDENT;
     423                 :         51 : /* ] */     t[93] |= SC_COMPILER_C_IDENT;
     424                 :            :         }
     425         [ +  + ]:        153 :         if( FormulaGrammar::CONV_XL_OOX == meConv )
     426                 :            :         {
     427                 :         51 : /* [ */     t[91] |= SC_COMPILER_C_CHAR_IDENT;
     428                 :         51 : /* ] */     t[93] |= SC_COMPILER_C_IDENT;
     429                 :            :         }
     430                 :            :     }
     431                 :        255 : }
     432                 :            : 
     433                 :            : //-----------------------------------------------------------------------------
     434                 :            : 
     435                 :        192 : static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, ParseResult& rRes )
     436                 :            : {
     437                 :            :     // Tokens that start at ' can have anything in them until a final '
     438                 :            :     // but '' marks an escaped '
     439                 :            :     // We've earlier guaranteed that a string containing '' will be
     440                 :            :     // surrounded by '
     441         [ +  + ]:        192 :     if (rFormula.GetChar(nSrcPos) == '\'')
     442                 :            :     {
     443                 :         87 :         xub_StrLen nPos = nSrcPos+1;
     444         [ +  - ]:       1827 :         while (nPos < rFormula.Len())
     445                 :            :         {
     446         [ +  + ]:       1827 :             if (rFormula.GetChar(nPos) == '\'')
     447                 :            :             {
     448 [ +  - ][ +  - ]:         87 :                 if ( (nPos+1 == rFormula.Len()) || (rFormula.GetChar(nPos+1) != '\'') )
                 [ +  - ]
     449                 :            :                 {
     450                 :         87 :                     rRes.TokenType = KParseType::SINGLE_QUOTE_NAME;
     451                 :         87 :                     rRes.EndPos = nPos+1;
     452                 :         87 :                     return true;
     453                 :            :                 }
     454                 :          0 :                 ++nPos;
     455                 :            :             }
     456                 :       1740 :             ++nPos;
     457                 :            :         }
     458                 :            :     }
     459                 :            : 
     460                 :        192 :     return false;
     461                 :            : }
     462                 :            : 
     463                 :         33 : static bool lcl_parseExternalName(
     464                 :            :         const String& rSymbol,
     465                 :            :         String& rFile,
     466                 :            :         String& rName,
     467                 :            :         const sal_Unicode cSep,
     468                 :            :         const ScDocument* pDoc = NULL,
     469                 :            :         const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks = NULL )
     470                 :            : {
     471                 :            :     /* TODO: future versions will have to support sheet-local names too, thus
     472                 :            :      * return a possible sheet name as well. */
     473                 :         33 :     const sal_Unicode* const pStart = rSymbol.GetBuffer();
     474                 :         33 :     const sal_Unicode* p = pStart;
     475                 :         33 :     xub_StrLen nLen = rSymbol.Len();
     476                 :         33 :     sal_Unicode cPrev = 0;
     477 [ +  - ][ +  - ]:         33 :     String aTmpFile, aTmpName;
     478                 :         33 :     xub_StrLen i = 0;
     479                 :         33 :     bool bInName = false;
     480         [ +  + ]:         33 :     if (cSep == '!')
     481                 :            :     {
     482                 :            :         // For XL use existing parser that resolves bracketed and quoted and
     483                 :            :         // indexed external document names.
     484                 :         12 :         ScRange aRange;
     485 [ +  - ][ +  - ]:         12 :         String aStartTabName, aEndTabName;
     486                 :         12 :         sal_uInt16 nFlags = 0;
     487                 :            :         p = aRange.Parse_XL_Header( p, pDoc, aTmpFile, aStartTabName,
     488         [ +  - ]:         12 :                 aEndTabName, nFlags, true, pExternalLinks );
     489 [ +  - ][ +  - ]:         12 :         if (!p || p == pStart)
     490                 :         12 :             return false;
     491                 :          0 :         i = xub_StrLen(p - pStart);
     492 [ +  - ][ +  - ]:         12 :         cPrev = *(p-1);
         [ +  - ][ -  + ]
     493                 :            :     }
     494         [ +  + ]:        162 :     for ( ; i < nLen; ++i, ++p)
     495                 :            :     {
     496                 :        141 :         sal_Unicode c = *p;
     497         [ +  + ]:        141 :         if (i == 0)
     498                 :            :         {
     499 [ +  - ][ -  + ]:         21 :             if (c == '.' || c == cSep)
     500                 :          0 :                 return false;
     501                 :            : 
     502         [ -  + ]:         21 :             if (c == '\'')
     503                 :            :             {
     504                 :            :                 // Move to the next char and loop until the second single
     505                 :            :                 // quote.
     506                 :          0 :                 cPrev = c;
     507                 :          0 :                 ++i; ++p;
     508         [ #  # ]:          0 :                 for (xub_StrLen j = i; j < nLen; ++j, ++p)
     509                 :            :                 {
     510                 :          0 :                     c = *p;
     511         [ #  # ]:          0 :                     if (c == '\'')
     512                 :            :                     {
     513         [ #  # ]:          0 :                         if (j == i)
     514                 :            :                         {
     515                 :            :                             // empty quote e.g. (=''!Name)
     516                 :          0 :                             return false;
     517                 :            :                         }
     518                 :            : 
     519         [ #  # ]:          0 :                         if (cPrev == '\'')
     520                 :            :                         {
     521                 :            :                             // two consecutive quotes equal a single quote in
     522                 :            :                             // the file name.
     523         [ #  # ]:          0 :                             aTmpFile.Append(c);
     524                 :          0 :                             cPrev = 'a';
     525                 :            :                         }
     526                 :            :                         else
     527                 :          0 :                             cPrev = c;
     528                 :            : 
     529                 :          0 :                         continue;
     530                 :            :                     }
     531                 :            : 
     532 [ #  # ][ #  # ]:          0 :                     if (cPrev == '\'' && j != i)
     533                 :            :                     {
     534                 :            :                         // this is not a quote but the previous one is.  This
     535                 :            :                         // ends the parsing of the quoted segment.  At this
     536                 :            :                         // point, the current char must equal the separator
     537                 :            :                         // char.
     538                 :            : 
     539                 :          0 :                         i = j;
     540                 :          0 :                         bInName = true;
     541         [ #  # ]:          0 :                         aTmpName.Append(c); // Keep the separator as part of the name.
     542                 :          0 :                         break;
     543                 :            :                     }
     544         [ #  # ]:          0 :                     aTmpFile.Append(c);
     545                 :          0 :                     cPrev = c;
     546                 :            :                 }
     547                 :            : 
     548         [ #  # ]:          0 :                 if (!bInName)
     549                 :            :                 {
     550                 :            :                     // premature ending of the quoted segment.
     551                 :          0 :                     return false;
     552                 :            :                 }
     553                 :            : 
     554         [ #  # ]:          0 :                 if (c != cSep)
     555                 :            :                 {
     556                 :            :                     // only the separator is allowed after the closing quote.
     557                 :          0 :                     return false;
     558                 :            :                 }
     559                 :            : 
     560                 :          0 :                 cPrev = c;
     561                 :          0 :                 continue;
     562                 :            :             }
     563                 :            :         }
     564                 :            : 
     565         [ -  + ]:        141 :         if (bInName)
     566                 :            :         {
     567         [ #  # ]:          0 :             if (c == cSep)
     568                 :            :             {
     569                 :            :                 // A second separator ?  Not a valid external name.
     570                 :          0 :                 return false;
     571                 :            :             }
     572         [ #  # ]:          0 :             aTmpName.Append(c);
     573                 :            :         }
     574                 :            :         else
     575                 :            :         {
     576         [ -  + ]:        141 :             if (c == cSep)
     577                 :            :             {
     578                 :          0 :                 bInName = true;
     579         [ #  # ]:          0 :                 aTmpName.Append(c); // Keep the separator as part of the name.
     580                 :            :             }
     581                 :            :             else
     582                 :            :             {
     583                 :            :                 do
     584                 :            :                 {
     585         [ +  - ]:        141 :                     if (CharClass::isAsciiAlphaNumeric(c))
     586                 :            :                         // allowed.
     587                 :        141 :                         break;
     588                 :            : 
     589         [ #  # ]:          0 :                     if (c > 128)
     590                 :            :                         // non-ASCII character is allowed.
     591                 :          0 :                         break;
     592                 :            : 
     593                 :          0 :                     bool bValid = false;
     594         [ #  # ]:          0 :                     switch (c)
     595                 :            :                     {
     596                 :            :                         case '_':
     597                 :            :                         case '-':
     598                 :            :                         case '.':
     599                 :            :                             // these special characters are allowed.
     600                 :          0 :                             bValid = true;
     601                 :          0 :                             break;
     602                 :            :                     }
     603         [ #  # ]:          0 :                     if (bValid)
     604                 :          0 :                         break;
     605                 :            : 
     606                 :          0 :                     return false;
     607                 :            :                 }
     608                 :            :                 while (false);
     609         [ +  - ]:        141 :                 aTmpFile.Append(c);
     610                 :            :             }
     611                 :            :         }
     612                 :        141 :         cPrev = c;
     613                 :            :     }
     614                 :            : 
     615         [ +  - ]:         21 :     if (!bInName)
     616                 :            :     {
     617                 :            :         // No name found - most likely the symbol has no '!'s.
     618                 :         21 :         return false;
     619                 :            :     }
     620                 :            : 
     621                 :          0 :     xub_StrLen nNameLen = aTmpName.Len();
     622         [ #  # ]:          0 :     if (nNameLen < 2)
     623                 :            :     {
     624                 :            :         // Name must be at least 2-char long (separator plus name).
     625                 :          0 :         return false;
     626                 :            :     }
     627                 :            : 
     628         [ #  # ]:          0 :     if (aTmpName.GetChar(0) != cSep)
     629                 :            :     {
     630                 :            :         // 1st char of the name must equal the separator.
     631                 :          0 :         return false;
     632                 :            :     }
     633                 :            : 
     634                 :          0 :     sal_Unicode cLast = aTmpName.GetChar(nNameLen-1);
     635         [ #  # ]:          0 :     if (cLast == sal_Unicode('!'))
     636                 :            :     {
     637                 :            :         // Check against #REF!.
     638 [ #  # ][ #  # ]:          0 :         if (aTmpName.EqualsAscii("#REF!"))
     639                 :          0 :             return false;
     640                 :            :     }
     641                 :            : 
     642         [ #  # ]:          0 :     rFile = aTmpFile;
     643 [ #  # ][ #  # ]:          0 :     rName = aTmpName.Copy(1); // Skip the first char as it is always the separator.
                 [ #  # ]
     644 [ +  - ][ +  - ]:         33 :     return true;
     645                 :            : }
     646                 :            : 
     647                 :          0 : static String lcl_makeExternalNameStr( const String& rFile, const String& rName,
     648                 :            :         const sal_Unicode cSep, bool bODF )
     649                 :            : {
     650 [ #  # ][ #  # ]:          0 :     String aFile( rFile), aName( rName), aEscQuote( RTL_CONSTASCII_USTRINGPARAM("''"));
                 [ #  # ]
     651         [ #  # ]:          0 :     aFile.SearchAndReplaceAllAscii( "'", aEscQuote);
     652         [ #  # ]:          0 :     if (bODF)
     653         [ #  # ]:          0 :         aName.SearchAndReplaceAllAscii( "'", aEscQuote);
     654                 :          0 :     rtl::OUStringBuffer aBuf( aFile.Len() + aName.Len() + 9);
     655         [ #  # ]:          0 :     if (bODF)
     656         [ #  # ]:          0 :         aBuf.append( sal_Unicode( '['));
     657         [ #  # ]:          0 :     aBuf.append( sal_Unicode( '\''));
     658 [ #  # ][ #  # ]:          0 :     aBuf.append( aFile);
     659         [ #  # ]:          0 :     aBuf.append( sal_Unicode( '\''));
     660         [ #  # ]:          0 :     aBuf.append( cSep);
     661         [ #  # ]:          0 :     if (bODF)
     662         [ #  # ]:          0 :         aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "$$'"));
     663 [ #  # ][ #  # ]:          0 :     aBuf.append( aName);
     664         [ #  # ]:          0 :     if (bODF)
     665         [ #  # ]:          0 :         aBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM( "']"));
     666 [ #  # ][ #  # ]:          0 :     return String( aBuf.makeStringAndClear());
         [ #  # ][ #  # ]
                 [ #  # ]
     667                 :            : }
     668                 :            : 
     669                 :          0 : static bool lcl_getLastTabName( OUString& rTabName2, const OUString& rTabName1,
     670                 :            :                                 const vector<OUString>& rTabNames, const ScComplexRefData& rRef )
     671                 :            : {
     672                 :          0 :     SCsTAB nTabSpan = rRef.Ref2.nTab - rRef.Ref1.nTab;
     673         [ #  # ]:          0 :     if (nTabSpan > 0)
     674                 :            :     {
     675                 :          0 :         size_t nCount = rTabNames.size();
     676                 :          0 :         vector<OUString>::const_iterator itrBeg = rTabNames.begin(), itrEnd = rTabNames.end();
     677         [ #  # ]:          0 :         vector<OUString>::const_iterator itr = ::std::find(itrBeg, itrEnd, rTabName1);
     678 [ #  # ][ #  # ]:          0 :         if (itr == rTabNames.end())
     679                 :            :         {
     680 [ #  # ][ #  # ]:          0 :             rTabName2 = ScGlobal::GetRscString(STR_NO_REF_TABLE);
     681                 :          0 :             return false;
     682                 :            :         }
     683                 :            : 
     684         [ #  # ]:          0 :         size_t nDist = ::std::distance(itrBeg, itr);
     685         [ #  # ]:          0 :         if (nDist + static_cast<size_t>(nTabSpan) >= nCount)
     686                 :            :         {
     687 [ #  # ][ #  # ]:          0 :             rTabName2 = ScGlobal::GetRscString(STR_NO_REF_TABLE);
     688                 :          0 :             return false;
     689                 :            :         }
     690                 :            : 
     691                 :          0 :         rTabName2 = rTabNames[nDist+nTabSpan];
     692                 :            :     }
     693                 :            :     else
     694                 :          0 :         rTabName2 = rTabName1;
     695                 :            : 
     696                 :          0 :     return true;
     697                 :            : }
     698                 :            : 
     699         [ -  + ]:        204 : struct Convention_A1 : public ScCompiler::Convention
     700                 :            : {
     701                 :        204 :     Convention_A1( FormulaGrammar::AddressConvention eConv ) : ScCompiler::Convention( eConv ) { }
     702                 :            :     static void MakeColStr( rtl::OUStringBuffer& rBuffer, SCCOL nCol );
     703                 :            :     static void MakeRowStr( rtl::OUStringBuffer& rBuffer, SCROW nRow );
     704                 :            : 
     705                 :        192 :     ParseResult parseAnyToken( const String& rFormula,
     706                 :            :                                xub_StrLen nSrcPos,
     707                 :            :                                const CharClass* pCharClass) const
     708                 :            :     {
     709                 :        192 :         ParseResult aRet;
     710         [ +  + ]:        192 :         if ( lcl_isValidQuotedText(rFormula, nSrcPos, aRet) )
     711                 :         87 :             return aRet;
     712                 :            : 
     713                 :            :         static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
     714                 :            :             KParseTokens::ASC_UNDERSCORE | KParseTokens::ASC_DOLLAR;
     715                 :            :         static const sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT;
     716                 :            :         // '?' allowed in range names because of Xcl :-/
     717 [ +  + ][ +  - ]:        105 :         static const String aAddAllowed(rtl::OUString("?#"));
         [ +  - ][ #  # ]
     718                 :            :         return pCharClass->parseAnyToken( rFormula,
     719         [ +  - ]:        192 :                 nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
     720                 :            :     }
     721                 :            : 
     722                 :      63707 :     virtual sal_uLong getCharTableFlags( sal_Unicode c, sal_Unicode /*cLast*/ ) const
     723                 :            :     {
     724                 :      63707 :         return mpCharTable[static_cast<sal_uInt8>(c)];
     725                 :            :     }
     726                 :            : };
     727                 :            : 
     728                 :      37743 : void Convention_A1::MakeColStr( rtl::OUStringBuffer& rBuffer, SCCOL nCol )
     729                 :            : {
     730         [ -  + ]:      37743 :     if ( !ValidCol( nCol) )
     731         [ #  # ]:          0 :         rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
     732                 :            :     else
     733                 :      37743 :         ::ScColToAlpha( rBuffer, nCol);
     734                 :      37743 : }
     735                 :            : 
     736                 :      37743 : void Convention_A1::MakeRowStr( rtl::OUStringBuffer& rBuffer, SCROW nRow )
     737                 :            : {
     738         [ -  + ]:      37743 :     if ( !ValidRow(nRow) )
     739         [ #  # ]:          0 :         rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
     740                 :            :     else
     741                 :      37743 :         rBuffer.append(sal_Int32(nRow + 1));
     742                 :      37743 : }
     743                 :            : 
     744                 :            : //-----------------------------------------------------------------------------
     745                 :            : 
     746         [ -  + ]:        102 : struct ConventionOOO_A1 : public Convention_A1
     747                 :            : {
     748                 :         51 :     ConventionOOO_A1() : Convention_A1 (FormulaGrammar::CONV_OOO) { }
     749                 :         51 :     ConventionOOO_A1( FormulaGrammar::AddressConvention eConv ) : Convention_A1 (eConv) { }
     750                 :      24925 :     static String MakeTabStr( const ScCompiler& rComp, SCTAB nTab, String& aDoc )
     751                 :            :     {
     752         [ +  - ]:      24925 :         String aString;
     753                 :      24925 :         rtl::OUString aTmp;
     754 [ -  + ][ +  - ]:      24925 :         if (!rComp.GetDoc()->GetName( nTab, aTmp ))
     755 [ #  # ][ #  # ]:          0 :             aString = ScGlobal::GetRscString(STR_NO_REF_TABLE);
     756                 :            :         else
     757                 :            :         {
     758         [ +  - ]:      24925 :             aString = aTmp;
     759         [ -  + ]:      24925 :             if ( aString.GetChar(0) == '\'' )
     760                 :            :             {   // "'Doc'#Tab"
     761         [ #  # ]:          0 :                 xub_StrLen nPos = ScGlobal::FindUnquoted( aString, SC_COMPILER_FILE_TAB_SEP);
     762 [ #  # ][ #  # ]:          0 :                 if (nPos != STRING_NOTFOUND && nPos > 0 && aString.GetChar(nPos-1) == '\'')
         [ #  # ][ #  # ]
     763                 :            :                 {
     764 [ #  # ][ #  # ]:          0 :                     aDoc = aString.Copy( 0, nPos + 1 );
                 [ #  # ]
     765         [ #  # ]:          0 :                     aString.Erase( 0, nPos + 1 );
     766                 :            :                     aDoc = INetURLObject::decode( aDoc, INET_HEX_ESCAPE,
     767 [ #  # ][ #  # ]:          0 :                         INetURLObject::DECODE_UNAMBIGUOUS );
                 [ #  # ]
     768                 :            :                 }
     769                 :            :                 else
     770         [ #  # ]:          0 :                     aDoc.Erase();
     771                 :            :             }
     772                 :            :             else
     773         [ +  - ]:      24925 :                 aDoc.Erase();
     774         [ +  - ]:      24925 :             ScCompiler::CheckTabQuotes( aString, FormulaGrammar::CONV_OOO );
     775                 :            :         }
     776         [ +  - ]:      24925 :         aString += '.';
     777                 :      24925 :         return aString;
     778                 :            :     }
     779                 :            : 
     780                 :            : 
     781                 :      37732 :     void MakeOneRefStrImpl( rtl::OUStringBuffer&    rBuffer,
     782                 :            :                             const ScCompiler&       rComp,
     783                 :            :                             const ScSingleRefData&  rRef,
     784                 :            :                             bool                    bForceTab,
     785                 :            :                             bool                    bODF ) const
     786                 :            :     {
     787 [ +  + ][ -  + ]:      37732 :         if( rRef.IsFlag3D() || bForceTab )
                 [ +  + ]
     788                 :            :         {
     789         [ -  + ]:      24925 :             if (rRef.IsTabDeleted())
     790                 :            :             {
     791         [ #  # ]:          0 :                 if (!rRef.IsTabRel())
     792                 :          0 :                     rBuffer.append(sal_Unicode('$'));
     793 [ #  # ][ #  # ]:          0 :                 rBuffer.append( rComp.GetCurrentOpCodeMap()->getSymbol( ocErrRef));
                 [ #  # ]
     794                 :          0 :                 rBuffer.append(sal_Unicode('.'));
     795                 :            :             }
     796                 :            :             else
     797                 :            :             {
     798         [ +  - ]:      24925 :                 String aDoc;
     799         [ +  - ]:      24925 :                 String aRefStr( MakeTabStr( rComp, rRef.nTab, aDoc ) );
     800 [ +  - ][ +  - ]:      24925 :                 rBuffer.append(aDoc);
     801         [ +  + ]:      24925 :                 if (!rRef.IsTabRel())
     802         [ +  - ]:      24809 :                     rBuffer.append(sal_Unicode('$'));
     803 [ +  - ][ +  - ]:      24925 :                 rBuffer.append(aRefStr);
         [ +  - ][ +  - ]
     804                 :            :             }
     805                 :            :         }
     806         [ -  + ]:      12807 :         else if (bODF)
     807                 :          0 :             rBuffer.append(sal_Unicode('.'));
     808         [ +  + ]:      37732 :         if (!rRef.IsColRel())
     809                 :      37493 :             rBuffer.append(sal_Unicode('$'));
     810         [ -  + ]:      37732 :         if ( rRef.IsColDeleted() )
     811 [ #  # ][ #  # ]:          0 :             rBuffer.append( rComp.GetCurrentOpCodeMap()->getSymbol( ocErrRef));
                 [ #  # ]
     812                 :            :         else
     813                 :      37732 :             MakeColStr(rBuffer, rRef.nCol );
     814         [ +  + ]:      37732 :         if (!rRef.IsRowRel())
     815                 :      37496 :             rBuffer.append(sal_Unicode('$'));
     816         [ -  + ]:      37732 :         if ( rRef.IsRowDeleted() )
     817 [ #  # ][ #  # ]:          0 :             rBuffer.append( rComp.GetCurrentOpCodeMap()->getSymbol( ocErrRef));
                 [ #  # ]
     818                 :            :         else
     819                 :      37732 :             MakeRowStr( rBuffer, rRef.nRow );
     820                 :      37732 :     }
     821                 :            : 
     822                 :            : 
     823                 :      25057 :     void MakeRefStrImpl( rtl::OUStringBuffer&   rBuffer,
     824                 :            :                          const ScCompiler&      rComp,
     825                 :            :                          const ScComplexRefData&    rRef,
     826                 :            :                          bool bSingleRef,
     827                 :            :                          bool bODF ) const
     828                 :            :     {
     829         [ -  + ]:      25057 :         if (bODF)
     830         [ #  # ]:          0 :             rBuffer.append(sal_Unicode('['));
     831                 :      25057 :         ScComplexRefData aRef( rRef );
     832                 :            :         // In case absolute/relative positions weren't separately available:
     833                 :            :         // transform relative to absolute!
     834         [ +  - ]:      25057 :         aRef.Ref1.CalcAbsIfRel( rComp.GetPos() );
     835         [ +  + ]:      25057 :         if( !bSingleRef )
     836         [ +  - ]:      12675 :             aRef.Ref2.CalcAbsIfRel( rComp.GetPos() );
     837 [ -  + ][ #  #  :      25057 :         if (bODF && FormulaGrammar::isODFF( rComp.GetGrammar()) &&
          #  #  #  #  #  
          #  #  #  #  #  
           #  # ][ -  + ]
     838                 :          0 :                 (aRef.Ref1.IsColDeleted() || aRef.Ref1.IsRowDeleted() || aRef.Ref1.IsTabDeleted() ||
     839                 :          0 :                  aRef.Ref2.IsColDeleted() || aRef.Ref2.IsRowDeleted() || aRef.Ref2.IsTabDeleted()))
     840 [ #  # ][ #  # ]:          0 :             rBuffer.append( rComp.GetCurrentOpCodeMap()->getSymbol( ocErrRef));
         [ #  # ][ #  # ]
                 [ #  # ]
     841                 :            :             // For ODFF write [#REF!], but not for PODF so apps reading ODF
     842                 :            :             // 1.0/1.1 may have a better chance if they implemented the old
     843                 :            :             // form.
     844                 :            :         else
     845                 :            :         {
     846         [ +  - ]:      25057 :             MakeOneRefStrImpl( rBuffer, rComp, aRef.Ref1, false, bODF);
     847         [ +  + ]:      25057 :             if (!bSingleRef)
     848                 :            :             {
     849         [ +  - ]:      12675 :                 rBuffer.append(sal_Unicode(':'));
     850         [ +  - ]:      12675 :                 MakeOneRefStrImpl( rBuffer, rComp, aRef.Ref2, (aRef.Ref2.nTab != aRef.Ref1.nTab), bODF);
     851                 :            :             }
     852                 :            :         }
     853         [ -  + ]:      25057 :         if (bODF)
     854         [ #  # ]:          0 :             rBuffer.append(sal_Unicode(']'));
     855                 :      25057 :     }
     856                 :            : 
     857                 :      25057 :     void MakeRefStr( rtl::OUStringBuffer&   rBuffer,
     858                 :            :                      const ScCompiler&      rComp,
     859                 :            :                      const ScComplexRefData& rRef,
     860                 :            :                      bool bSingleRef ) const
     861                 :            :     {
     862                 :      25057 :         MakeRefStrImpl( rBuffer, rComp, rRef, bSingleRef, false);
     863                 :      25057 :     }
     864                 :            : 
     865                 :      30486 :     virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const
     866                 :            :     {
     867      [ +  +  - ]:      30486 :         switch (eSymType)
     868                 :            :         {
     869                 :            :             case ScCompiler::Convention::ABS_SHEET_PREFIX:
     870                 :      15243 :                 return '$';
     871                 :            :             case ScCompiler::Convention::SHEET_SEPARATOR:
     872                 :      15243 :                 return '.';
     873                 :            :         }
     874                 :            : 
     875                 :      30486 :         return sal_Unicode(0);
     876                 :            :     }
     877                 :            : 
     878                 :         21 :     virtual bool parseExternalName( const String& rSymbol, String& rFile, String& rName,
     879                 :            :             const ScDocument* pDoc,
     880                 :            :             const ::com::sun::star::uno::Sequence<
     881                 :            :                 const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks ) const
     882                 :            :     {
     883                 :         21 :         return lcl_parseExternalName(rSymbol, rFile, rName, sal_Unicode('#'), pDoc, pExternalLinks);
     884                 :            :     }
     885                 :            : 
     886                 :          0 :     virtual String makeExternalNameStr( const String& rFile, const String& rName ) const
     887                 :            :     {
     888                 :          0 :         return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('#'), false);
     889                 :            :     }
     890                 :            : 
     891                 :         11 :     bool makeExternalSingleRefStr( ::rtl::OUStringBuffer& rBuffer, sal_uInt16 nFileId,
     892                 :            :                                    const String& rTabName, const ScSingleRefData& rRef,
     893                 :            :                                    ScExternalRefManager* pRefMgr, bool bDisplayTabName, bool bEncodeUrl ) const
     894                 :            :     {
     895         [ +  - ]:         11 :         if (bDisplayTabName)
     896                 :            :         {
     897         [ +  - ]:         11 :             String aFile;
     898         [ +  - ]:         11 :             const OUString* p = pRefMgr->getExternalFileName(nFileId);
     899         [ +  - ]:         11 :             if (p)
     900                 :            :             {
     901         [ -  + ]:         11 :                 if (bEncodeUrl)
     902         [ #  # ]:          0 :                     aFile = *p;
     903                 :            :                 else
     904 [ +  - ][ +  - ]:         11 :                     aFile = INetURLObject::decode(*p, INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS);
     905                 :            :             }
     906 [ +  - ][ +  - ]:         11 :             aFile.SearchAndReplaceAllAscii("'", rtl::OUString("''"));
                 [ +  - ]
     907                 :            : 
     908         [ +  - ]:         11 :             rBuffer.append(sal_Unicode('\''));
     909 [ +  - ][ +  - ]:         11 :             rBuffer.append(aFile);
     910         [ +  - ]:         11 :             rBuffer.append(sal_Unicode('\''));
     911         [ +  - ]:         11 :             rBuffer.append(sal_Unicode('#'));
     912                 :            : 
     913         [ +  - ]:         11 :             if (!rRef.IsTabRel())
     914         [ +  - ]:         11 :                 rBuffer.append(sal_Unicode('$'));
     915 [ +  - ][ +  - ]:         11 :             ScRangeStringConverter::AppendTableName(rBuffer, rTabName);
     916                 :            : 
     917 [ +  - ][ +  - ]:         11 :             rBuffer.append(sal_Unicode('.'));
     918                 :            :         }
     919                 :            : 
     920         [ +  + ]:         11 :         if (!rRef.IsColRel())
     921                 :          5 :             rBuffer.append(sal_Unicode('$'));
     922                 :         11 :         MakeColStr( rBuffer, rRef.nCol);
     923         [ +  + ]:         11 :         if (!rRef.IsRowRel())
     924                 :          8 :             rBuffer.append(sal_Unicode('$'));
     925                 :         11 :         MakeRowStr( rBuffer, rRef.nRow);
     926                 :            : 
     927                 :         11 :         return true;
     928                 :            :     }
     929                 :            : 
     930                 :         11 :     void makeExternalRefStrImpl( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
     931                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef,
     932                 :            :                                      ScExternalRefManager* pRefMgr, bool bODF ) const
     933                 :            :     {
     934                 :         11 :         ScSingleRefData aRef(rRef);
     935         [ +  - ]:         11 :         aRef.CalcAbsIfRel(rCompiler.GetPos());
     936                 :            : 
     937         [ -  + ]:         11 :         if (bODF)
     938         [ #  # ]:          0 :             rBuffer.append( sal_Unicode('['));
     939                 :            : 
     940                 :         11 :         bool bEncodeUrl = true;
     941         [ +  - ]:         11 :         switch (rCompiler.GetEncodeUrlMode())
           [ +  -  -  - ]
     942                 :            :         {
     943                 :            :             case ScCompiler::ENCODE_BY_GRAMMAR:
     944                 :         11 :                 bEncodeUrl = bODF;
     945                 :         11 :             break;
     946                 :            :             case ScCompiler::ENCODE_ALWAYS:
     947                 :          0 :                 bEncodeUrl = true;
     948                 :          0 :             break;
     949                 :            :             case ScCompiler::ENCODE_NEVER:
     950                 :          0 :                 bEncodeUrl = false;
     951                 :          0 :             break;
     952                 :            :             default:
     953                 :            :                 ;
     954                 :            :         }
     955         [ +  - ]:         11 :         makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef, pRefMgr, true, bEncodeUrl);
     956         [ -  + ]:         11 :         if (bODF)
     957         [ #  # ]:          0 :             rBuffer.append( sal_Unicode(']'));
     958                 :         11 :     }
     959                 :            : 
     960                 :         11 :     virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
     961                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef,
     962                 :            :                                      ScExternalRefManager* pRefMgr ) const
     963                 :            :     {
     964                 :         11 :         makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, false);
     965                 :         11 :     }
     966                 :            : 
     967                 :          0 :     void makeExternalRefStrImpl( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
     968                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef,
     969                 :            :                                      ScExternalRefManager* pRefMgr, bool bODF ) const
     970                 :            :     {
     971                 :          0 :         ScComplexRefData aRef(rRef);
     972         [ #  # ]:          0 :         aRef.CalcAbsIfRel(rCompiler.GetPos());
     973                 :            : 
     974         [ #  # ]:          0 :         if (bODF)
     975         [ #  # ]:          0 :             rBuffer.append( sal_Unicode('['));
     976                 :            :         // Ensure that there's always a closing bracket, no premature returns.
     977                 :          0 :         bool bEncodeUrl = true;
     978         [ #  # ]:          0 :         switch (rCompiler.GetEncodeUrlMode())
           [ #  #  #  # ]
     979                 :            :         {
     980                 :            :             case ScCompiler::ENCODE_BY_GRAMMAR:
     981                 :          0 :                 bEncodeUrl = bODF;
     982                 :          0 :             break;
     983                 :            :             case ScCompiler::ENCODE_ALWAYS:
     984                 :          0 :                 bEncodeUrl = true;
     985                 :          0 :             break;
     986                 :            :             case ScCompiler::ENCODE_NEVER:
     987                 :          0 :                 bEncodeUrl = false;
     988                 :          0 :             break;
     989                 :            :             default:
     990                 :            :                 ;
     991                 :            :         }
     992                 :            : 
     993                 :            :         do
     994                 :            :         {
     995 [ #  # ][ #  # ]:          0 :             if (!makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef.Ref1, pRefMgr, true, bEncodeUrl))
     996                 :            :                 break;
     997                 :            : 
     998         [ #  # ]:          0 :             rBuffer.append(sal_Unicode(':'));
     999                 :            : 
    1000                 :          0 :             OUString aLastTabName;
    1001                 :          0 :             bool bDisplayTabName = (aRef.Ref1.nTab != aRef.Ref2.nTab);
    1002         [ #  # ]:          0 :             if (bDisplayTabName)
    1003                 :            :             {
    1004                 :            :                 // Get the name of the last table.
    1005         [ #  # ]:          0 :                 vector<OUString> aTabNames;
    1006         [ #  # ]:          0 :                 pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
    1007                 :          0 :                 if (aTabNames.empty())
    1008                 :            :                 {
    1009                 :            :                     OSL_TRACE( "ConventionOOO_A1::makeExternalRefStrImpl: no sheet names for document ID %s", nFileId);
    1010                 :            :                 }
    1011                 :            : 
    1012 [ #  # ][ #  # ]:          0 :                 if (!lcl_getLastTabName(aLastTabName, rTabName, aTabNames, aRef))
    1013                 :            :                 {
    1014                 :            :                     OSL_FAIL( "ConventionOOO_A1::makeExternalRefStrImpl: sheet name not found");
    1015                 :            :                     // aLastTabName contains #REF!, proceed.
    1016                 :          0 :                 }
    1017                 :            :             }
    1018         [ #  # ]:          0 :             else if (bODF)
    1019         [ #  # ]:          0 :                 rBuffer.append( sal_Unicode('.'));      // need at least the sheet separator in ODF
    1020                 :            :             makeExternalSingleRefStr( rBuffer, nFileId, aLastTabName,
    1021 [ #  # ][ #  # ]:          0 :                     aRef.Ref2, pRefMgr, bDisplayTabName, bEncodeUrl);
                 [ #  # ]
    1022                 :            :         } while (0);
    1023         [ #  # ]:          0 :         if (bODF)
    1024         [ #  # ]:          0 :             rBuffer.append( sal_Unicode(']'));
    1025                 :          0 :     }
    1026                 :            : 
    1027                 :          0 :     virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
    1028                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef,
    1029                 :            :                                      ScExternalRefManager* pRefMgr ) const
    1030                 :            :     {
    1031                 :          0 :         makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, false);
    1032                 :          0 :     }
    1033                 :            : };
    1034                 :            : 
    1035                 :            : 
    1036                 :         51 : static const ConventionOOO_A1 ConvOOO_A1;
    1037                 :            : const ScCompiler::Convention * const ScCompiler::pConvOOO_A1 = &ConvOOO_A1;
    1038                 :            : 
    1039                 :            : //-----------------------------------------------------------------------------
    1040                 :            : 
    1041         [ -  + ]:         51 : struct ConventionOOO_A1_ODF : public ConventionOOO_A1
    1042                 :            : {
    1043                 :         51 :     ConventionOOO_A1_ODF() : ConventionOOO_A1 (FormulaGrammar::CONV_ODF) { }
    1044                 :          0 :     void MakeRefStr( rtl::OUStringBuffer&   rBuffer,
    1045                 :            :                      const ScCompiler&      rComp,
    1046                 :            :                      const ScComplexRefData& rRef,
    1047                 :            :                      bool bSingleRef ) const
    1048                 :            :     {
    1049                 :          0 :         MakeRefStrImpl( rBuffer, rComp, rRef, bSingleRef, true);
    1050                 :          0 :     }
    1051                 :            : 
    1052                 :          0 :     virtual String makeExternalNameStr( const String& rFile, const String& rName ) const
    1053                 :            :     {
    1054                 :          0 :         return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('#'), true);
    1055                 :            :     }
    1056                 :            : 
    1057                 :          0 :     virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
    1058                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef,
    1059                 :            :                                      ScExternalRefManager* pRefMgr ) const
    1060                 :            :     {
    1061                 :          0 :         makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, true);
    1062                 :          0 :     }
    1063                 :            : 
    1064                 :          0 :     virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
    1065                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef,
    1066                 :            :                                      ScExternalRefManager* pRefMgr ) const
    1067                 :            :     {
    1068                 :          0 :         makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, true);
    1069                 :          0 :     }
    1070                 :            : };
    1071                 :            : 
    1072                 :         51 : static const ConventionOOO_A1_ODF ConvOOO_A1_ODF;
    1073                 :            : const ScCompiler::Convention * const ScCompiler::pConvOOO_A1_ODF = &ConvOOO_A1_ODF;
    1074                 :            : 
    1075                 :            : //-----------------------------------------------------------------------------
    1076                 :            : 
    1077                 :        153 : struct ConventionXL
    1078                 :            : {
    1079                 :          0 :     static bool GetDocAndTab( const ScCompiler& rComp,
    1080                 :            :                               const ScSingleRefData& rRef,
    1081                 :            :                               String& rDocName,
    1082                 :            :                               String& rTabName )
    1083                 :            :     {
    1084                 :          0 :         bool bHasDoc = false;
    1085                 :            : 
    1086         [ #  # ]:          0 :         rDocName.Erase();
    1087                 :          0 :         rtl::OUString aTmp;
    1088 [ #  # ][ #  # ]:          0 :         if (rRef.IsTabDeleted() ||
                 [ #  # ]
    1089         [ #  # ]:          0 :             !rComp.GetDoc()->GetName( rRef.nTab, aTmp ))
    1090                 :            :         {
    1091 [ #  # ][ #  # ]:          0 :             rTabName = ScGlobal::GetRscString( STR_NO_REF_TABLE );
    1092                 :          0 :             return false;
    1093                 :            :         }
    1094         [ #  # ]:          0 :         rTabName = aTmp;
    1095                 :            : 
    1096                 :            :         // Cheesy hack to unparse the OOO style "'Doc'#Tab"
    1097         [ #  # ]:          0 :         if ( rTabName.GetChar(0) == '\'' )
    1098                 :            :         {
    1099         [ #  # ]:          0 :             xub_StrLen nPos = ScGlobal::FindUnquoted( rTabName, SC_COMPILER_FILE_TAB_SEP);
    1100 [ #  # ][ #  # ]:          0 :             if (nPos != STRING_NOTFOUND && nPos > 0 && rTabName.GetChar(nPos-1) == '\'')
         [ #  # ][ #  # ]
    1101                 :            :             {
    1102 [ #  # ][ #  # ]:          0 :                 rDocName = rTabName.Copy( 0, nPos );
                 [ #  # ]
    1103                 :            :                 // TODO : More research into how XL escapes the doc path
    1104                 :            :                 rDocName = INetURLObject::decode( rDocName, INET_HEX_ESCAPE,
    1105 [ #  # ][ #  # ]:          0 :                     INetURLObject::DECODE_UNAMBIGUOUS );
                 [ #  # ]
    1106         [ #  # ]:          0 :                 rTabName.Erase( 0, nPos + 1 );
    1107                 :          0 :                 bHasDoc = true;
    1108                 :            :             }
    1109                 :            :         }
    1110                 :            : 
    1111                 :            :         // XL uses the same sheet name quoting conventions in both modes
    1112                 :            :         // it is safe to use A1 here
    1113         [ #  # ]:          0 :         ScCompiler::CheckTabQuotes( rTabName, FormulaGrammar::CONV_XL_A1 );
    1114                 :          0 :         return bHasDoc;
    1115                 :            :     }
    1116                 :            : 
    1117                 :          0 :     static void MakeDocStr( rtl::OUStringBuffer& rBuf,
    1118                 :            :                             const ScCompiler& rComp,
    1119                 :            :                             const ScComplexRefData& rRef,
    1120                 :            :                             bool bSingleRef )
    1121                 :            :     {
    1122         [ #  # ]:          0 :         if( rRef.Ref1.IsFlag3D() )
    1123                 :            :         {
    1124 [ #  # ][ #  # ]:          0 :             String aStartTabName, aStartDocName, aEndTabName, aEndDocName;
         [ #  # ][ #  # ]
    1125                 :          0 :             bool bStartHasDoc = false, bEndHasDoc = false;
    1126                 :            : 
    1127                 :            :             bStartHasDoc = GetDocAndTab( rComp, rRef.Ref1,
    1128         [ #  # ]:          0 :                                          aStartDocName, aStartTabName);
    1129                 :            : 
    1130 [ #  # ][ #  # ]:          0 :             if( !bSingleRef && rRef.Ref2.IsFlag3D() )
                 [ #  # ]
    1131                 :            :             {
    1132                 :            :                 bEndHasDoc = GetDocAndTab( rComp, rRef.Ref2,
    1133         [ #  # ]:          0 :                                            aEndDocName, aEndTabName);
    1134                 :            :             }
    1135                 :            :             else
    1136                 :          0 :                 bEndHasDoc = bStartHasDoc;
    1137                 :            : 
    1138         [ #  # ]:          0 :             if( bStartHasDoc )
    1139                 :            :             {
    1140                 :            :                 // A ref across multipled workbooks ?
    1141         [ #  # ]:          0 :                 if( !bEndHasDoc )
    1142                 :          0 :                     return;
    1143                 :            : 
    1144         [ #  # ]:          0 :                 rBuf.append( sal_Unicode( '[' ) );
    1145 [ #  # ][ #  # ]:          0 :                 rBuf.append( aStartDocName );
    1146         [ #  # ]:          0 :                 rBuf.append( sal_Unicode( ']' ) );
    1147                 :            :             }
    1148                 :            : 
    1149 [ #  # ][ #  # ]:          0 :             rBuf.append( aStartTabName );
    1150 [ #  # ][ #  # ]:          0 :             if( !bSingleRef && rRef.Ref2.IsFlag3D() && aStartTabName != aEndTabName )
         [ #  # ][ #  # ]
                 [ #  # ]
    1151                 :            :             {
    1152         [ #  # ]:          0 :                 rBuf.append( sal_Unicode( ':' ) );
    1153 [ #  # ][ #  # ]:          0 :                 rBuf.append( aEndTabName );
    1154                 :            :             }
    1155                 :            : 
    1156 [ #  # ][ #  # ]:          0 :             rBuf.append( sal_Unicode( '!' ) );
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1157                 :            :         }
    1158                 :            :     }
    1159                 :            : 
    1160                 :        840 :     static sal_Unicode getSpecialSymbol( ScCompiler::Convention::SpecialSymbolType eSymType )
    1161                 :            :     {
    1162      [ +  +  - ]:        840 :         switch (eSymType)
    1163                 :            :         {
    1164                 :            :             case ScCompiler::Convention::ABS_SHEET_PREFIX:
    1165                 :        420 :                 return sal_Unicode(0);
    1166                 :            :             case ScCompiler::Convention::SHEET_SEPARATOR:
    1167                 :        420 :                 return '!';
    1168                 :            :         }
    1169                 :        840 :         return sal_Unicode(0);
    1170                 :            :     }
    1171                 :            : 
    1172                 :         12 :     static bool parseExternalName( const String& rSymbol, String& rFile, String& rName,
    1173                 :            :             const ScDocument* pDoc,
    1174                 :            :             const ::com::sun::star::uno::Sequence<
    1175                 :            :                 const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks )
    1176                 :            :     {
    1177                 :         12 :         return lcl_parseExternalName( rSymbol, rFile, rName, sal_Unicode('!'), pDoc, pExternalLinks);
    1178                 :            :     }
    1179                 :            : 
    1180                 :          0 :     static String makeExternalNameStr( const String& rFile, const String& rName )
    1181                 :            :     {
    1182                 :          0 :         return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('!'), false);
    1183                 :            :     }
    1184                 :            : 
    1185                 :          0 :     static void makeExternalDocStr( ::rtl::OUStringBuffer& rBuffer, const String& rFullName, bool bEncodeUrl )
    1186                 :            :     {
    1187                 :            :         // Format that is easier to deal with inside OOo, because we use file
    1188                 :            :         // URL, and all characetrs are allowed.  Check if it makes sense to do
    1189                 :            :         // it the way Gnumeric does it.  Gnumeric doesn't use the URL form
    1190                 :            :         // and allows relative file path.
    1191                 :            :         //
    1192                 :            :         //   ['file:///path/to/source/filename.xls']
    1193                 :            : 
    1194         [ #  # ]:          0 :         rBuffer.append(sal_Unicode('['));
    1195         [ #  # ]:          0 :         rBuffer.append(sal_Unicode('\''));
    1196         [ #  # ]:          0 :         String aFullName;
    1197         [ #  # ]:          0 :         if (bEncodeUrl)
    1198         [ #  # ]:          0 :             aFullName = rFullName;
    1199                 :            :         else
    1200 [ #  # ][ #  # ]:          0 :             aFullName = INetURLObject::decode(rFullName, INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS);
                 [ #  # ]
    1201                 :            : 
    1202                 :          0 :         const sal_Unicode* pBuf = aFullName.GetBuffer();
    1203                 :          0 :         xub_StrLen nLen = aFullName.Len();
    1204         [ #  # ]:          0 :         for (xub_StrLen i = 0; i < nLen; ++i)
    1205                 :            :         {
    1206                 :          0 :             const sal_Unicode c = pBuf[i];
    1207         [ #  # ]:          0 :             if (c == sal_Unicode('\''))
    1208         [ #  # ]:          0 :                 rBuffer.append(c);
    1209         [ #  # ]:          0 :             rBuffer.append(c);
    1210                 :            :         }
    1211         [ #  # ]:          0 :         rBuffer.append(sal_Unicode('\''));
    1212 [ #  # ][ #  # ]:          0 :         rBuffer.append(sal_Unicode(']'));
    1213                 :          0 :     }
    1214                 :            : 
    1215                 :          0 :     static void makeExternalTabNameRange( ::rtl::OUStringBuffer& rBuf, const OUString& rTabName,
    1216                 :            :                                           const vector<OUString>& rTabNames,
    1217                 :            :                                           const ScComplexRefData& rRef )
    1218                 :            :     {
    1219                 :          0 :         OUString aLastTabName;
    1220 [ #  # ][ #  # ]:          0 :         if (!lcl_getLastTabName(aLastTabName, rTabName, rTabNames, rRef))
    1221                 :            :         {
    1222         [ #  # ]:          0 :             ScRangeStringConverter::AppendTableName(rBuf, aLastTabName);
    1223                 :          0 :             return;
    1224                 :            :         }
    1225                 :            : 
    1226         [ #  # ]:          0 :         ScRangeStringConverter::AppendTableName(rBuf, rTabName);
    1227         [ #  # ]:          0 :         if (rTabName != aLastTabName)
    1228                 :            :         {
    1229         [ #  # ]:          0 :             rBuf.append(sal_Unicode(':'));
    1230         [ #  # ]:          0 :             ScRangeStringConverter::AppendTableName(rBuf, rTabName);
    1231         [ #  # ]:          0 :         }
    1232                 :            :     }
    1233                 :            : 
    1234                 :          0 :     static void parseExternalDocName( const String& rFormula, xub_StrLen& rSrcPos )
    1235                 :            :     {
    1236                 :          0 :         xub_StrLen nLen = rFormula.Len();
    1237                 :          0 :         const sal_Unicode* p = rFormula.GetBuffer();
    1238                 :          0 :         sal_Unicode cPrev = 0;
    1239         [ #  # ]:          0 :         for (xub_StrLen i = rSrcPos; i < nLen; ++i)
    1240                 :            :         {
    1241                 :          0 :             sal_Unicode c = p[i];
    1242         [ #  # ]:          0 :             if (i == rSrcPos)
    1243                 :            :             {
    1244                 :            :                 // first character must be '['.
    1245         [ #  # ]:          0 :                 if (c != '[')
    1246                 :          0 :                     return;
    1247                 :            :             }
    1248         [ #  # ]:          0 :             else if (i == rSrcPos + 1)
    1249                 :            :             {
    1250                 :            :                 // second character must be a single quote.
    1251         [ #  # ]:          0 :                 if (c != '\'')
    1252                 :          0 :                     return;
    1253                 :            :             }
    1254         [ #  # ]:          0 :             else if (c == '\'')
    1255                 :            :             {
    1256         [ #  # ]:          0 :                 if (cPrev == '\'')
    1257                 :            :                     // two successive single quote is treated as a single
    1258                 :            :                     // valid character.
    1259                 :          0 :                     c = 'a';
    1260                 :            :             }
    1261         [ #  # ]:          0 :             else if (c == ']')
    1262                 :            :             {
    1263         [ #  # ]:          0 :                 if (cPrev == '\'')
    1264                 :            :                 {
    1265                 :            :                     // valid source document path found.  Increment the
    1266                 :            :                     // current position to skip the source path.
    1267                 :          0 :                     rSrcPos = i + 1;
    1268         [ #  # ]:          0 :                     if (rSrcPos >= nLen)
    1269                 :          0 :                         rSrcPos = nLen - 1;
    1270                 :          0 :                     return;
    1271                 :            :                 }
    1272                 :            :                 else
    1273                 :          0 :                     return;
    1274                 :            :             }
    1275                 :            :             else
    1276                 :            :             {
    1277                 :            :                 // any other character
    1278 [ #  # ][ #  # ]:          0 :                 if (i > rSrcPos + 2 && cPrev == '\'')
    1279                 :            :                     // unless it's the 3rd character, a normal character
    1280                 :            :                     // following immediately a single quote is invalid.
    1281                 :          0 :                     return;
    1282                 :            :             }
    1283                 :          0 :             cPrev = c;
    1284                 :            :         }
    1285                 :            :     }
    1286                 :            : };
    1287                 :            : 
    1288         [ -  + ]:        102 : struct ConventionXL_A1 : public Convention_A1, public ConventionXL
    1289                 :            : {
    1290                 :         51 :     ConventionXL_A1() : Convention_A1( FormulaGrammar::CONV_XL_A1 ) { }
    1291                 :         51 :     ConventionXL_A1( FormulaGrammar::AddressConvention eConv ) : Convention_A1( eConv ) { }
    1292                 :            : 
    1293                 :          0 :     void makeSingleCellStr( ::rtl::OUStringBuffer& rBuf, const ScSingleRefData& rRef ) const
    1294                 :            :     {
    1295         [ #  # ]:          0 :         if (!rRef.IsColRel())
    1296                 :          0 :             rBuf.append(sal_Unicode('$'));
    1297                 :          0 :         MakeColStr(rBuf, rRef.nCol);
    1298         [ #  # ]:          0 :         if (!rRef.IsRowRel())
    1299                 :          0 :             rBuf.append(sal_Unicode('$'));
    1300                 :          0 :         MakeRowStr(rBuf, rRef.nRow);
    1301                 :          0 :     }
    1302                 :            : 
    1303                 :          0 :     void MakeRefStr( rtl::OUStringBuffer&   rBuf,
    1304                 :            :                      const ScCompiler&      rComp,
    1305                 :            :                      const ScComplexRefData& rRef,
    1306                 :            :                      bool bSingleRef ) const
    1307                 :            :     {
    1308                 :          0 :         ScComplexRefData aRef( rRef );
    1309                 :            : 
    1310                 :            :         // Play fast and loose with invalid refs.  There is not much point in producing
    1311                 :            :         // Foo!A1:#REF! versus #REF! at this point
    1312         [ #  # ]:          0 :         aRef.Ref1.CalcAbsIfRel( rComp.GetPos() );
    1313                 :            : 
    1314         [ #  # ]:          0 :         MakeDocStr( rBuf, rComp, aRef, bSingleRef );
    1315                 :            : 
    1316 [ #  # ][ #  # ]:          0 :         if( aRef.Ref1.IsColDeleted() || aRef.Ref1.IsRowDeleted() )
                 [ #  # ]
    1317                 :            :         {
    1318 [ #  # ][ #  # ]:          0 :             rBuf.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
                 [ #  # ]
    1319                 :            :             return;
    1320                 :            :         }
    1321                 :            : 
    1322         [ #  # ]:          0 :         if( !bSingleRef )
    1323                 :            :         {
    1324         [ #  # ]:          0 :             aRef.Ref2.CalcAbsIfRel( rComp.GetPos() );
    1325 [ #  # ][ #  # ]:          0 :             if( aRef.Ref2.IsColDeleted() || aRef.Ref2.IsRowDeleted() )
                 [ #  # ]
    1326                 :            :             {
    1327 [ #  # ][ #  # ]:          0 :                 rBuf.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
                 [ #  # ]
    1328                 :            :                 return;
    1329                 :            :             }
    1330                 :            : 
    1331 [ #  # ][ #  # ]:          0 :             if( aRef.Ref1.nCol == 0 && aRef.Ref2.nCol >= MAXCOL )
    1332                 :            :             {
    1333         [ #  # ]:          0 :                 if (!aRef.Ref1.IsRowRel())
    1334         [ #  # ]:          0 :                     rBuf.append(sal_Unicode( '$' ));
    1335         [ #  # ]:          0 :                 MakeRowStr( rBuf, aRef.Ref1.nRow );
    1336         [ #  # ]:          0 :                 rBuf.append(sal_Unicode( ':' ));
    1337         [ #  # ]:          0 :                 if (!aRef.Ref2.IsRowRel())
    1338         [ #  # ]:          0 :                     rBuf.append(sal_Unicode( '$' ));
    1339         [ #  # ]:          0 :                 MakeRowStr( rBuf, aRef.Ref2.nRow );
    1340                 :            :                 return;
    1341                 :            :             }
    1342                 :            : 
    1343 [ #  # ][ #  # ]:          0 :             if( aRef.Ref1.nRow == 0 && aRef.Ref2.nRow >= MAXROW )
    1344                 :            :             {
    1345         [ #  # ]:          0 :                 if (!aRef.Ref1.IsColRel())
    1346         [ #  # ]:          0 :                     rBuf.append(sal_Unicode( '$' ));
    1347         [ #  # ]:          0 :                 MakeColStr(rBuf, aRef.Ref1.nCol );
    1348         [ #  # ]:          0 :                 rBuf.append(sal_Unicode( ':' ));
    1349         [ #  # ]:          0 :                 if (!aRef.Ref2.IsColRel())
    1350         [ #  # ]:          0 :                     rBuf.append(sal_Unicode( '$' ));
    1351         [ #  # ]:          0 :                 MakeColStr(rBuf, aRef.Ref2.nCol );
    1352                 :            :                 return;
    1353                 :            :             }
    1354                 :            :         }
    1355                 :            : 
    1356         [ #  # ]:          0 :         makeSingleCellStr(rBuf, aRef.Ref1);
    1357         [ #  # ]:          0 :         if (!bSingleRef)
    1358                 :            :         {
    1359         [ #  # ]:          0 :             rBuf.append(sal_Unicode( ':' ));
    1360         [ #  # ]:          0 :             makeSingleCellStr(rBuf, aRef.Ref2);
    1361                 :            :         }
    1362                 :            :     }
    1363                 :            : 
    1364                 :          0 :     virtual ParseResult parseAnyToken( const String& rFormula,
    1365                 :            :                                        xub_StrLen nSrcPos,
    1366                 :            :                                        const CharClass* pCharClass) const
    1367                 :            :     {
    1368                 :          0 :         ParseResult aRet;
    1369         [ #  # ]:          0 :         if ( lcl_isValidQuotedText(rFormula, nSrcPos, aRet) )
    1370                 :          0 :             return aRet;
    1371                 :            : 
    1372                 :            :         static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
    1373                 :            :             KParseTokens::ASC_UNDERSCORE | KParseTokens::ASC_DOLLAR;
    1374                 :            :         static const sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT;
    1375                 :            :         // '?' allowed in range names
    1376                 :          0 :         const rtl::OUString aAddAllowed("?!");
    1377                 :            :         return pCharClass->parseAnyToken( rFormula,
    1378 [ #  # ][ #  # ]:          0 :                 nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
         [ #  # ][ #  # ]
                 [ #  # ]
    1379                 :            :     }
    1380                 :            : 
    1381                 :        840 :     virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const
    1382                 :            :     {
    1383                 :        840 :         return ConventionXL::getSpecialSymbol(eSymType);
    1384                 :            :     }
    1385                 :            : 
    1386                 :         12 :     virtual bool parseExternalName( const String& rSymbol, String& rFile, String& rName,
    1387                 :            :             const ScDocument* pDoc,
    1388                 :            :             const ::com::sun::star::uno::Sequence<
    1389                 :            :                 const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks ) const
    1390                 :            :     {
    1391                 :         12 :         return ConventionXL::parseExternalName( rSymbol, rFile, rName, pDoc, pExternalLinks);
    1392                 :            :     }
    1393                 :            : 
    1394                 :          0 :     virtual String makeExternalNameStr( const String& rFile, const String& rName ) const
    1395                 :            :     {
    1396                 :          0 :         return ConventionXL::makeExternalNameStr(rFile, rName);
    1397                 :            :     }
    1398                 :            : 
    1399                 :          0 :     virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
    1400                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef,
    1401                 :            :                                      ScExternalRefManager* pRefMgr ) const
    1402                 :            :     {
    1403                 :            :         // ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
    1404                 :            :         // This is a little different from the format Excel uses, as Excel
    1405                 :            :         // puts [] only around the file name.  But we need to enclose the
    1406                 :            :         // whole file path with [] because the file name can contain any
    1407                 :            :         // characters.
    1408                 :            : 
    1409         [ #  # ]:          0 :         const OUString* pFullName = pRefMgr->getExternalFileName(nFileId);
    1410         [ #  # ]:          0 :         if (!pFullName)
    1411                 :          0 :             return;
    1412                 :            : 
    1413                 :          0 :         ScSingleRefData aRef(rRef);
    1414         [ #  # ]:          0 :         aRef.CalcAbsIfRel(rCompiler.GetPos());
    1415                 :            : 
    1416                 :            :         ConventionXL::makeExternalDocStr(
    1417 [ #  # ][ #  # ]:          0 :             rBuffer, *pFullName, rCompiler.GetEncodeUrlMode() == ScCompiler::ENCODE_ALWAYS);
         [ #  # ][ #  # ]
    1418 [ #  # ][ #  # ]:          0 :         ScRangeStringConverter::AppendTableName(rBuffer, rTabName);
    1419         [ #  # ]:          0 :         rBuffer.append(sal_Unicode('!'));
    1420                 :            : 
    1421         [ #  # ]:          0 :         makeSingleCellStr(rBuffer, aRef);
    1422                 :            :     }
    1423                 :            : 
    1424                 :          0 :     virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
    1425                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef,
    1426                 :            :                                      ScExternalRefManager* pRefMgr ) const
    1427                 :            :     {
    1428         [ #  # ]:          0 :         const OUString* pFullName = pRefMgr->getExternalFileName(nFileId);
    1429         [ #  # ]:          0 :         if (!pFullName)
    1430                 :            :             return;
    1431                 :            : 
    1432         [ #  # ]:          0 :         vector<OUString> aTabNames;
    1433         [ #  # ]:          0 :         pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
    1434         [ #  # ]:          0 :         if (aTabNames.empty())
    1435                 :            :             return;
    1436                 :            : 
    1437                 :          0 :         ScComplexRefData aRef(rRef);
    1438         [ #  # ]:          0 :         aRef.CalcAbsIfRel(rCompiler.GetPos());
    1439                 :            : 
    1440                 :            :         ConventionXL::makeExternalDocStr(
    1441 [ #  # ][ #  # ]:          0 :             rBuffer, *pFullName, rCompiler.GetEncodeUrlMode() == ScCompiler::ENCODE_ALWAYS);
         [ #  # ][ #  # ]
    1442 [ #  # ][ #  # ]:          0 :         ConventionXL::makeExternalTabNameRange(rBuffer, rTabName, aTabNames, aRef);
    1443         [ #  # ]:          0 :         rBuffer.append(sal_Unicode('!'));
    1444                 :            : 
    1445         [ #  # ]:          0 :         makeSingleCellStr(rBuffer, aRef.Ref1);
    1446 [ #  # ][ #  # ]:          0 :         if (aRef.Ref1 != aRef.Ref2)
    1447                 :            :         {
    1448         [ #  # ]:          0 :             rBuffer.append(sal_Unicode(':'));
    1449         [ #  # ]:          0 :             makeSingleCellStr(rBuffer, aRef.Ref2);
    1450         [ #  # ]:          0 :         }
    1451                 :            :     }
    1452                 :            : };
    1453                 :            : 
    1454                 :         51 : static const ConventionXL_A1 ConvXL_A1;
    1455                 :            : const ScCompiler::Convention * const ScCompiler::pConvXL_A1 = &ConvXL_A1;
    1456                 :            : 
    1457                 :            : 
    1458         [ -  + ]:         51 : struct ConventionXL_OOX : public ConventionXL_A1
    1459                 :            : {
    1460                 :         51 :     ConventionXL_OOX() : ConventionXL_A1( FormulaGrammar::CONV_XL_OOX ) { }
    1461                 :            : };
    1462                 :            : 
    1463                 :         51 : static const ConventionXL_OOX ConvXL_OOX;
    1464                 :            : const ScCompiler::Convention * const ScCompiler::pConvXL_OOX = &ConvXL_OOX;
    1465                 :            : 
    1466                 :            : 
    1467                 :            : //-----------------------------------------------------------------------------
    1468                 :            : 
    1469                 :            : static void
    1470                 :          0 : r1c1_add_col( rtl::OUStringBuffer &rBuf, const ScSingleRefData& rRef )
    1471                 :            : {
    1472                 :          0 :     rBuf.append( sal_Unicode( 'C' ) );
    1473         [ #  # ]:          0 :     if( rRef.IsColRel() )
    1474                 :            :     {
    1475         [ #  # ]:          0 :         if (rRef.nRelCol != 0)
    1476                 :            :         {
    1477                 :          0 :             rBuf.append( sal_Unicode( '[' ) );
    1478 [ #  # ][ #  # ]:          0 :             rBuf.append( String::CreateFromInt32( rRef.nRelCol ) );
    1479                 :          0 :             rBuf.append( sal_Unicode( ']' ) );
    1480                 :            :         }
    1481                 :            :     }
    1482                 :            :     else
    1483 [ #  # ][ #  # ]:          0 :         rBuf.append( String::CreateFromInt32( rRef.nCol + 1 ) );
    1484                 :          0 : }
    1485                 :            : static void
    1486                 :          0 : r1c1_add_row( rtl::OUStringBuffer &rBuf, const ScSingleRefData& rRef )
    1487                 :            : {
    1488                 :          0 :     rBuf.append( sal_Unicode( 'R' ) );
    1489         [ #  # ]:          0 :     if( rRef.IsRowRel() )
    1490                 :            :     {
    1491         [ #  # ]:          0 :         if (rRef.nRelRow != 0)
    1492                 :            :         {
    1493                 :          0 :             rBuf.append( sal_Unicode( '[' ) );
    1494 [ #  # ][ #  # ]:          0 :             rBuf.append( String::CreateFromInt32( rRef.nRelRow ) );
    1495                 :          0 :             rBuf.append( sal_Unicode( ']' ) );
    1496                 :            :         }
    1497                 :            :     }
    1498                 :            :     else
    1499 [ #  # ][ #  # ]:          0 :         rBuf.append( String::CreateFromInt32( rRef.nRow + 1 ) );
    1500                 :          0 : }
    1501                 :            : 
    1502         [ -  + ]:         51 : struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
    1503                 :            : {
    1504                 :         51 :     ConventionXL_R1C1() : ScCompiler::Convention( FormulaGrammar::CONV_XL_R1C1 ) { }
    1505                 :          0 :     void MakeRefStr( rtl::OUStringBuffer&   rBuf,
    1506                 :            :                      const ScCompiler&      rComp,
    1507                 :            :                      const ScComplexRefData& rRef,
    1508                 :            :                      bool bSingleRef ) const
    1509                 :            :     {
    1510                 :          0 :         ScComplexRefData aRef( rRef );
    1511                 :            : 
    1512         [ #  # ]:          0 :         MakeDocStr( rBuf, rComp, aRef, bSingleRef );
    1513                 :            : 
    1514                 :            :         // Play fast and loose with invalid refs.  There is not much point in producing
    1515                 :            :         // Foo!A1:#REF! versus #REF! at this point
    1516         [ #  # ]:          0 :         aRef.Ref1.CalcAbsIfRel( rComp.GetPos() );
    1517 [ #  # ][ #  # ]:          0 :         if( aRef.Ref1.IsColDeleted() || aRef.Ref1.IsRowDeleted() )
                 [ #  # ]
    1518                 :            :         {
    1519 [ #  # ][ #  # ]:          0 :             rBuf.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
                 [ #  # ]
    1520                 :            :             return;
    1521                 :            :         }
    1522                 :            : 
    1523         [ #  # ]:          0 :         if( !bSingleRef )
    1524                 :            :         {
    1525         [ #  # ]:          0 :             aRef.Ref2.CalcAbsIfRel( rComp.GetPos() );
    1526 [ #  # ][ #  # ]:          0 :             if( aRef.Ref2.IsColDeleted() || aRef.Ref2.IsRowDeleted() )
                 [ #  # ]
    1527                 :            :             {
    1528 [ #  # ][ #  # ]:          0 :                 rBuf.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
                 [ #  # ]
    1529                 :            :                 return;
    1530                 :            :             }
    1531                 :            : 
    1532 [ #  # ][ #  # ]:          0 :             if( aRef.Ref1.nCol == 0 && aRef.Ref2.nCol >= MAXCOL )
    1533                 :            :             {
    1534         [ #  # ]:          0 :                 r1c1_add_row( rBuf,  rRef.Ref1 );
    1535   [ #  #  #  # ]:          0 :                 if( rRef.Ref1.nRow != rRef.Ref2.nRow ||
                 [ #  # ]
    1536                 :          0 :                     rRef.Ref1.IsRowRel() != rRef.Ref2.IsRowRel() ) {
    1537         [ #  # ]:          0 :                     rBuf.append (sal_Unicode ( ':' ) );
    1538         [ #  # ]:          0 :                     r1c1_add_row( rBuf,  rRef.Ref2 );
    1539                 :            :                 }
    1540                 :            :                 return;
    1541                 :            : 
    1542                 :            :             }
    1543                 :            : 
    1544 [ #  # ][ #  # ]:          0 :             if( aRef.Ref1.nRow == 0 && aRef.Ref2.nRow >= MAXROW )
    1545                 :            :             {
    1546         [ #  # ]:          0 :                 r1c1_add_col( rBuf, rRef.Ref1 );
    1547   [ #  #  #  # ]:          0 :                 if( rRef.Ref1.nCol != rRef.Ref2.nCol ||
                 [ #  # ]
    1548                 :          0 :                     rRef.Ref1.IsColRel() != rRef.Ref2.IsColRel() )
    1549                 :            :                 {
    1550         [ #  # ]:          0 :                     rBuf.append (sal_Unicode ( ':' ) );
    1551         [ #  # ]:          0 :                     r1c1_add_col( rBuf,  rRef.Ref2 );
    1552                 :            :                 }
    1553                 :            :                 return;
    1554                 :            :             }
    1555                 :            :         }
    1556                 :            : 
    1557         [ #  # ]:          0 :         r1c1_add_row( rBuf, rRef.Ref1 );
    1558         [ #  # ]:          0 :         r1c1_add_col( rBuf, rRef.Ref1 );
    1559         [ #  # ]:          0 :         if (!bSingleRef)
    1560                 :            :         {
    1561         [ #  # ]:          0 :             rBuf.append (sal_Unicode ( ':' ) );
    1562         [ #  # ]:          0 :             r1c1_add_row( rBuf, rRef.Ref2 );
    1563         [ #  # ]:          0 :             r1c1_add_col( rBuf, rRef.Ref2 );
    1564                 :            :         }
    1565                 :            :     }
    1566                 :            : 
    1567                 :          0 :     ParseResult parseAnyToken( const String& rFormula,
    1568                 :            :                                xub_StrLen nSrcPos,
    1569                 :            :                                const CharClass* pCharClass) const
    1570                 :            :     {
    1571                 :          0 :         ConventionXL::parseExternalDocName(rFormula, nSrcPos);
    1572                 :            : 
    1573                 :          0 :         ParseResult aRet;
    1574         [ #  # ]:          0 :         if ( lcl_isValidQuotedText(rFormula, nSrcPos, aRet) )
    1575                 :          0 :             return aRet;
    1576                 :            : 
    1577                 :            :         static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
    1578                 :            :             KParseTokens::ASC_UNDERSCORE ;
    1579                 :            :         static const sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT;
    1580                 :            :         // '?' allowed in range names
    1581                 :          0 :         const rtl::OUString aAddAllowed("?-[]!");
    1582                 :            : 
    1583                 :            :         return pCharClass->parseAnyToken( rFormula,
    1584 [ #  # ][ #  # ]:          0 :                 nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
         [ #  # ][ #  # ]
                 [ #  # ]
    1585                 :            :     }
    1586                 :            : 
    1587                 :          0 :     virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const
    1588                 :            :     {
    1589                 :          0 :         return ConventionXL::getSpecialSymbol(eSymType);
    1590                 :            :     }
    1591                 :            : 
    1592                 :          0 :     virtual bool parseExternalName( const String& rSymbol, String& rFile, String& rName,
    1593                 :            :             const ScDocument* pDoc,
    1594                 :            :             const ::com::sun::star::uno::Sequence<
    1595                 :            :                 const ::com::sun::star::sheet::ExternalLinkInfo > * pExternalLinks ) const
    1596                 :            :     {
    1597                 :          0 :         return ConventionXL::parseExternalName( rSymbol, rFile, rName, pDoc, pExternalLinks);
    1598                 :            :     }
    1599                 :            : 
    1600                 :          0 :     virtual String makeExternalNameStr( const String& rFile, const String& rName ) const
    1601                 :            :     {
    1602                 :          0 :         return ConventionXL::makeExternalNameStr(rFile, rName);
    1603                 :            :     }
    1604                 :            : 
    1605                 :          0 :     virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
    1606                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef,
    1607                 :            :                                      ScExternalRefManager* pRefMgr ) const
    1608                 :            :     {
    1609                 :            :         // ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
    1610                 :            :         // This is a little different from the format Excel uses, as Excel
    1611                 :            :         // puts [] only around the file name.  But we need to enclose the
    1612                 :            :         // whole file path with [] because the file name can contain any
    1613                 :            :         // characters.
    1614                 :            : 
    1615         [ #  # ]:          0 :         const OUString* pFullName = pRefMgr->getExternalFileName(nFileId);
    1616         [ #  # ]:          0 :         if (!pFullName)
    1617                 :          0 :             return;
    1618                 :            : 
    1619                 :          0 :         ScSingleRefData aRef(rRef);
    1620         [ #  # ]:          0 :         aRef.CalcAbsIfRel(rCompiler.GetPos());
    1621                 :            : 
    1622                 :            :         ConventionXL::makeExternalDocStr(
    1623 [ #  # ][ #  # ]:          0 :             rBuffer, *pFullName, rCompiler.GetEncodeUrlMode() == ScCompiler::ENCODE_ALWAYS);
         [ #  # ][ #  # ]
    1624 [ #  # ][ #  # ]:          0 :         ScRangeStringConverter::AppendTableName(rBuffer, rTabName);
    1625         [ #  # ]:          0 :         rBuffer.append(sal_Unicode('!'));
    1626                 :            : 
    1627         [ #  # ]:          0 :         r1c1_add_row(rBuffer, aRef);
    1628         [ #  # ]:          0 :         r1c1_add_col(rBuffer, aRef);
    1629                 :            :     }
    1630                 :            : 
    1631                 :          0 :     virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
    1632                 :            :                                      sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef,
    1633                 :            :                                      ScExternalRefManager* pRefMgr ) const
    1634                 :            :     {
    1635         [ #  # ]:          0 :         const OUString* pFullName = pRefMgr->getExternalFileName(nFileId);
    1636         [ #  # ]:          0 :         if (!pFullName)
    1637                 :            :             return;
    1638                 :            : 
    1639         [ #  # ]:          0 :         vector<OUString> aTabNames;
    1640         [ #  # ]:          0 :         pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
    1641         [ #  # ]:          0 :         if (aTabNames.empty())
    1642                 :            :             return;
    1643                 :            : 
    1644                 :          0 :         ScComplexRefData aRef(rRef);
    1645         [ #  # ]:          0 :         aRef.CalcAbsIfRel(rCompiler.GetPos());
    1646                 :            : 
    1647                 :            :         ConventionXL::makeExternalDocStr(
    1648 [ #  # ][ #  # ]:          0 :             rBuffer, *pFullName, rCompiler.GetEncodeUrlMode() == ScCompiler::ENCODE_ALWAYS);
         [ #  # ][ #  # ]
    1649 [ #  # ][ #  # ]:          0 :         ConventionXL::makeExternalTabNameRange(rBuffer, rTabName, aTabNames, aRef);
    1650         [ #  # ]:          0 :         rBuffer.append(sal_Unicode('!'));
    1651                 :            : 
    1652 [ #  # ][ #  # ]:          0 :         if (aRef.Ref2.IsColDeleted() || aRef.Ref2.IsRowDeleted())
                 [ #  # ]
    1653                 :            :         {
    1654 [ #  # ][ #  # ]:          0 :             rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
                 [ #  # ]
    1655                 :            :             return;
    1656                 :            :         }
    1657                 :            : 
    1658 [ #  # ][ #  # ]:          0 :         if (aRef.Ref1.nCol == 0 && aRef.Ref2.nCol >= MAXCOL)
    1659                 :            :         {
    1660         [ #  # ]:          0 :             r1c1_add_row(rBuffer, rRef.Ref1);
    1661 [ #  # ][ #  # ]:          0 :             if (rRef.Ref1.nRow != rRef.Ref2.nRow || rRef.Ref1.IsRowRel() != rRef.Ref2.IsRowRel())
                 [ #  # ]
    1662                 :            :             {
    1663         [ #  # ]:          0 :                 rBuffer.append (sal_Unicode(':'));
    1664         [ #  # ]:          0 :                 r1c1_add_row(rBuffer, rRef.Ref2);
    1665                 :            :             }
    1666                 :            :             return;
    1667                 :            :         }
    1668                 :            : 
    1669 [ #  # ][ #  # ]:          0 :         if (aRef.Ref1.nRow == 0 && aRef.Ref2.nRow >= MAXROW)
    1670                 :            :         {
    1671         [ #  # ]:          0 :             r1c1_add_col(rBuffer, aRef.Ref1);
    1672 [ #  # ][ #  # ]:          0 :             if (aRef.Ref1.nCol != aRef.Ref2.nCol || aRef.Ref1.IsColRel() != aRef.Ref2.IsColRel())
                 [ #  # ]
    1673                 :            :             {
    1674         [ #  # ]:          0 :                 rBuffer.append (sal_Unicode(':'));
    1675         [ #  # ]:          0 :                 r1c1_add_col(rBuffer, aRef.Ref2);
    1676                 :            :             }
    1677                 :            :             return;
    1678                 :            :         }
    1679                 :            : 
    1680         [ #  # ]:          0 :         r1c1_add_row(rBuffer, aRef.Ref1);
    1681         [ #  # ]:          0 :         r1c1_add_col(rBuffer, aRef.Ref1);
    1682         [ #  # ]:          0 :         rBuffer.append (sal_Unicode (':'));
    1683         [ #  # ]:          0 :         r1c1_add_row(rBuffer, aRef.Ref2);
    1684 [ #  # ][ #  # ]:          0 :         r1c1_add_col(rBuffer, aRef.Ref2);
    1685                 :            :     }
    1686                 :            : 
    1687                 :        558 :     virtual sal_uLong getCharTableFlags( sal_Unicode c, sal_Unicode cLast ) const
    1688                 :            :     {
    1689                 :        558 :         sal_uLong nFlags = mpCharTable[static_cast<sal_uInt8>(c)];
    1690 [ -  + ][ #  # ]:        558 :         if (c == '-' && cLast == '[')
    1691                 :            :             // '-' can occur within a reference string only after '[' e.g. R[-1]C.
    1692                 :          0 :             nFlags |= SC_COMPILER_C_IDENT;
    1693                 :        558 :         return nFlags;
    1694                 :            :     }
    1695                 :            : };
    1696                 :            : 
    1697                 :         51 : static const ConventionXL_R1C1 ConvXL_R1C1;
    1698                 :            : const ScCompiler::Convention * const ScCompiler::pConvXL_R1C1 = &ConvXL_R1C1;
    1699                 :            : 
    1700                 :            : //-----------------------------------------------------------------------------
    1701                 :       5336 : ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArray& rArr)
    1702                 :            :         : FormulaCompiler(rArr),
    1703                 :            :         pDoc( pDocument ),
    1704                 :            :         aPos( rPos ),
    1705                 :            :         pCharClass( ScGlobal::pCharClass ),
    1706                 :            :         mnPredetectedReference(0),
    1707                 :            :         mnRangeOpPosInSymbol(-1),
    1708                 :            :         pConv( pConvOOO_A1 ),
    1709                 :            :         meEncodeUrlMode( ENCODE_BY_GRAMMAR ),
    1710                 :            :         meExtendedErrorDetection( EXTENDED_ERROR_DETECTION_NONE ),
    1711                 :            :         mbCloseBrackets( true ),
    1712 [ +  - ][ +  - ]:       5336 :         mbRewind( false )
    1713                 :            : {
    1714 [ +  - ][ +  - ]:       5336 :     nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
    1715                 :       5336 : }
    1716                 :            : 
    1717                 :      28025 : ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos)
    1718                 :            :         :
    1719                 :            :         pDoc( pDocument ),
    1720                 :            :         aPos( rPos ),
    1721                 :            :         pCharClass( ScGlobal::pCharClass ),
    1722                 :            :         mnPredetectedReference(0),
    1723                 :            :         mnRangeOpPosInSymbol(-1),
    1724                 :            :         pConv( pConvOOO_A1 ),
    1725                 :            :         meEncodeUrlMode( ENCODE_BY_GRAMMAR ),
    1726                 :            :         meExtendedErrorDetection( EXTENDED_ERROR_DETECTION_NONE ),
    1727                 :            :         mbCloseBrackets( true ),
    1728 [ +  - ][ +  - ]:      28025 :         mbRewind( false )
    1729                 :            : {
    1730 [ +  - ][ +  - ]:      28025 :     nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0;
    1731                 :      28025 : }
    1732                 :            : 
    1733                 :      25105 : void ScCompiler::CheckTabQuotes( String& rString,
    1734                 :            :                                  const FormulaGrammar::AddressConvention eConv )
    1735                 :            : {
    1736                 :            :     using namespace ::com::sun::star::i18n;
    1737                 :      25105 :     sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER | KParseTokens::ASC_UNDERSCORE;
    1738                 :      25105 :     sal_Int32 nContFlags = nStartFlags;
    1739                 :            :     ParseResult aRes = ScGlobal::pCharClass->parsePredefinedToken(
    1740 [ +  - ][ +  - ]:      25105 :         KParseType::IDENTNAME, rString, 0, nStartFlags, EMPTY_STRING, nContFlags, EMPTY_STRING);
                 [ +  - ]
    1741 [ +  - ][ -  + ]:      25105 :     bool bNeedsQuote = !((aRes.TokenType & KParseType::IDENTNAME) && aRes.EndPos == rString.Len());
    1742                 :            : 
    1743         [ -  + ]:      25105 :     switch ( eConv )
    1744                 :            :     {
    1745                 :            :         default :
    1746                 :            :         case FormulaGrammar::CONV_UNSPECIFIED :
    1747                 :          0 :             break;
    1748                 :            :         case FormulaGrammar::CONV_OOO :
    1749                 :            :         case FormulaGrammar::CONV_XL_A1 :
    1750                 :            :         case FormulaGrammar::CONV_XL_R1C1 :
    1751                 :            :         case FormulaGrammar::CONV_XL_OOX :
    1752         [ -  + ]:      25105 :             if( bNeedsQuote )
    1753                 :            :             {
    1754                 :          0 :                 const rtl::OUString one_quote(static_cast<sal_Unicode>('\''));
    1755                 :          0 :                 const rtl::OUString two_quote("''");
    1756                 :            :                 // escape embedded quotes
    1757 [ #  # ][ #  # ]:          0 :                 rString.SearchAndReplaceAll( one_quote, two_quote );
         [ #  # ][ #  # ]
                 [ #  # ]
    1758                 :            :             }
    1759                 :      25105 :             break;
    1760                 :            :     }
    1761                 :            : 
    1762 [ +  - ][ +  - ]:      25105 :     if ( !bNeedsQuote && CharClass::isAsciiNumeric( rString ) )
         [ -  + ][ -  + ]
    1763                 :            :     {
    1764                 :            :         // Prevent any possible confusion resulting from pure numeric sheet names.
    1765                 :          0 :         bNeedsQuote = true;
    1766                 :            :     }
    1767                 :            : 
    1768         [ -  + ]:      25105 :     if( bNeedsQuote )
    1769                 :            :     {
    1770         [ #  # ]:          0 :         rString.Insert( '\'', 0 );
    1771         [ #  # ]:          0 :         rString += '\'';
    1772                 :      25105 :     }
    1773                 :      25105 : }
    1774                 :            : 
    1775                 :            : //---------------------------------------------------------------------------
    1776                 :            : 
    1777                 :      35942 : void ScCompiler::SetRefConvention( FormulaGrammar::AddressConvention eConv )
    1778                 :            : {
    1779   [ +  +  +  -  :      35942 :     switch ( eConv ) {
                   -  + ]
    1780                 :            :         case FormulaGrammar::CONV_UNSPECIFIED :
    1781                 :        117 :             break;
    1782                 :            :         default :
    1783                 :      32811 :         case FormulaGrammar::CONV_OOO :      SetRefConvention( pConvOOO_A1 ); break;
    1784                 :       2897 :         case FormulaGrammar::CONV_ODF :      SetRefConvention( pConvOOO_A1_ODF ); break;
    1785                 :          0 :         case FormulaGrammar::CONV_XL_A1 :    SetRefConvention( pConvXL_A1 );  break;
    1786                 :          0 :         case FormulaGrammar::CONV_XL_R1C1 :  SetRefConvention( pConvXL_R1C1 ); break;
    1787                 :        117 :         case FormulaGrammar::CONV_XL_OOX :   SetRefConvention( pConvXL_OOX ); break;
    1788                 :            :     }
    1789                 :      35942 : }
    1790                 :            : 
    1791                 :      35825 : void ScCompiler::SetRefConvention( const ScCompiler::Convention *pConvP )
    1792                 :            : {
    1793                 :      35825 :     pConv = pConvP;
    1794                 :      35825 :     meGrammar = FormulaGrammar::mergeToGrammar( meGrammar, pConv->meConv);
    1795                 :            :     OSL_ENSURE( FormulaGrammar::isSupported( meGrammar),
    1796                 :            :             "ScCompiler::SetRefConvention: unsupported grammar resulting");
    1797                 :      35825 : }
    1798                 :            : 
    1799                 :       2137 : void ScCompiler::SetError(sal_uInt16 nError)
    1800                 :            : {
    1801         [ +  + ]:       2137 :     if( !pArr->GetCodeError() )
    1802                 :       1070 :         pArr->SetCodeError( nError);
    1803                 :       2137 : }
    1804                 :            : 
    1805                 :            : 
    1806                 :         87 : sal_Unicode* lcl_UnicodeStrNCpy( sal_Unicode* pDst, const sal_Unicode* pSrc, xub_StrLen nMax )
    1807                 :            : {
    1808                 :         87 :     const sal_Unicode* const pStop = pDst + nMax;
    1809 [ +  + ][ +  - ]:       2811 :     while ( *pSrc && pDst < pStop )
                 [ +  + ]
    1810                 :            :     {
    1811                 :       2724 :         *pDst++ = *pSrc++;
    1812                 :            :     }
    1813                 :         87 :     *pDst = 0;
    1814                 :         87 :     return pDst;
    1815                 :            : }
    1816                 :            : 
    1817                 :            : 
    1818                 :            : //---------------------------------------------------------------------------
    1819                 :            : // NextSymbol
    1820                 :            : //---------------------------------------------------------------------------
    1821                 :            : // Zerlegt die Formel in einzelne Symbole fuer die weitere
    1822                 :            : // Verarbeitung (Turing-Maschine).
    1823                 :            : //---------------------------------------------------------------------------
    1824                 :            : // Ausgangs Zustand = GetChar
    1825                 :            : //---------------+-------------------+-----------------------+---------------
    1826                 :            : // Alter Zustand | gelesenes Zeichen | Aktion                | Neuer Zustand
    1827                 :            : //---------------+-------------------+-----------------------+---------------
    1828                 :            : // GetChar       | ;()+-*/^=&        | Symbol=Zeichen        | Stop
    1829                 :            : //               | <>                | Symbol=Zeichen        | GetBool
    1830                 :            : //               | $ Buchstabe       | Symbol=Zeichen        | GetWord
    1831                 :            : //               | Ziffer            | Symbol=Zeichen        | GetValue
    1832                 :            : //               | "                 | Keine                 | GetString
    1833                 :            : //               | Sonst             | Keine                 | GetChar
    1834                 :            : //---------------+-------------------+-----------------------+---------------
    1835                 :            : // GetBool       | =>                | Symbol=Symbol+Zeichen | Stop
    1836                 :            : //               | Sonst             | Dec(CharPos)          | Stop
    1837                 :            : //---------------+-------------------+-----------------------+---------------
    1838                 :            : // GetWord       | SepSymbol         | Dec(CharPos)          | Stop
    1839                 :            : //               | ()+-*/^=<>&~      |                       |
    1840                 :            : //               | Leerzeichen       | Dec(CharPos)          | Stop
    1841                 :            : //               | $_:.              |                       |
    1842                 :            : //               | Buchstabe,Ziffer  | Symbol=Symbol+Zeichen | GetWord
    1843                 :            : //               | Sonst             | Fehler                | Stop
    1844                 :            : //---------------|-------------------+-----------------------+---------------
    1845                 :            : // GetValue      | ;()*/^=<>&        |                       |
    1846                 :            : //               | Leerzeichen       | Dec(CharPos)          | Stop
    1847                 :            : //               | Ziffer E+-%,.     | Symbol=Symbol+Zeichen | GetValue
    1848                 :            : //               | Sonst             | Fehler                | Stop
    1849                 :            : //---------------+-------------------+-----------------------+---------------
    1850                 :            : // GetString     | "                 | Keine                 | Stop
    1851                 :            : //               | Sonst             | Symbol=Symbol+Zeichen | GetString
    1852                 :            : //---------------+-------------------+-----------------------+---------------
    1853                 :            : 
    1854                 :      15663 : xub_StrLen ScCompiler::NextSymbol(bool bInArray)
    1855                 :            : {
    1856                 :      15663 :     cSymbol[MAXSTRLEN-1] = 0;       // Stopper
    1857                 :      15663 :     sal_Unicode* pSym = cSymbol;
    1858                 :      15663 :     const sal_Unicode* const pStart = aFormula.GetBuffer();
    1859                 :      15663 :     const sal_Unicode* pSrc = pStart + nSrcPos;
    1860                 :      15663 :     bool bi18n = false;
    1861                 :      15663 :     sal_Unicode c = *pSrc;
    1862                 :      15663 :     sal_Unicode cLast = 0;
    1863                 :      15663 :     bool bQuote = false;
    1864                 :      15663 :     mnRangeOpPosInSymbol = -1;
    1865                 :      15663 :     ScanState eState = ssGetChar;
    1866                 :      15663 :     xub_StrLen nSpaces = 0;
    1867                 :      15663 :     sal_Unicode cSep = mxSymbols->getSymbol( ocSep).GetChar(0);
    1868                 :      15663 :     sal_Unicode cArrayColSep = mxSymbols->getSymbol( ocArrayColSep).GetChar(0);
    1869                 :      15663 :     sal_Unicode cArrayRowSep = mxSymbols->getSymbol( ocArrayRowSep).GetChar(0);
    1870                 :      15663 :     sal_Unicode cDecSep = (mxSymbols->isEnglish() ? '.' :
    1871         [ +  + ]:      15663 :             ScGlobal::pLocaleData->getNumDecimalSep()[0]);
    1872                 :            : 
    1873                 :            :     // special symbols specific to address convention used
    1874                 :      15663 :     sal_Unicode cSheetPrefix = pConv->getSpecialSymbol(ScCompiler::Convention::ABS_SHEET_PREFIX);
    1875                 :      15663 :     sal_Unicode cSheetSep    = pConv->getSpecialSymbol(ScCompiler::Convention::SHEET_SEPARATOR);
    1876                 :            : 
    1877                 :      15663 :     int nDecSeps = 0;
    1878                 :      15663 :     bool bAutoIntersection = false;
    1879                 :      15663 :     int nRefInName = 0;
    1880                 :      15663 :     bool bErrorConstantHadSlash = false;
    1881                 :      15663 :     mnPredetectedReference = 0;
    1882                 :            :     // try to parse simple tokens before calling i18n parser
    1883 [ +  + ][ +  + ]:      77138 :     while ((c != 0) && (eState != ssStop) )
                 [ +  + ]
    1884                 :            :     {
    1885                 :      61475 :         pSrc++;
    1886                 :      61475 :         sal_uLong nMask = GetCharTableFlags( c, cLast );
    1887                 :            : 
    1888                 :            :         // The parameter separator and the array column and row separators end
    1889                 :            :         // things unconditionally if not in string or reference.
    1890 [ +  + ][ +  - ]:      61475 :         if (c == cSep || (bInArray && (c == cArrayColSep || c == cArrayRowSep)))
         [ +  + ][ +  + ]
    1891                 :            :         {
    1892         [ -  + ]:       1824 :             switch (eState)
    1893                 :            :             {
    1894                 :            :                 // these are to be continued
    1895                 :            :                 case ssGetString:
    1896                 :            :                 case ssSkipString:
    1897                 :            :                 case ssGetReference:
    1898                 :            :                 case ssSkipReference:
    1899                 :          0 :                     break;
    1900                 :            :                 default:
    1901         [ +  + ]:       1824 :                     if (eState == ssGetChar)
    1902                 :       1010 :                         *pSym++ = c;
    1903                 :            :                     else
    1904                 :        814 :                         pSrc--;
    1905                 :       1824 :                     eState = ssStop;
    1906                 :            :             }
    1907                 :            :         }
    1908                 :            : Label_MaskStateMachine:
    1909   [ +  +  +  +  :      61475 :         switch (eState)
          +  -  -  +  -  
                   +  - ]
    1910                 :            :         {
    1911                 :            :             case ssGetChar :
    1912                 :            :             {
    1913                 :            :                 // Order is important!
    1914         [ -  + ]:      10527 :                 if( nMask & SC_COMPILER_C_ODF_LABEL_OP )
    1915                 :            :                 {
    1916                 :            :                     // '!!' automatic intersection
    1917         [ #  # ]:          0 :                     if (GetCharTableFlags( pSrc[0], 0 ) & SC_COMPILER_C_ODF_LABEL_OP)
    1918                 :            :                     {
    1919                 :            :                         /* TODO: For now the UI "space operator" is used, this
    1920                 :            :                          * could be enhanced using a specialized OpCode to get
    1921                 :            :                          * rid of the space ambiguity, which would need some
    1922                 :            :                          * places to be adapted though. And we would still need
    1923                 :            :                          * to support the ambiguous space operator for UI
    1924                 :            :                          * purposes anyway. However, we then could check for
    1925                 :            :                          * invalid usage of '!!', which currently isn't
    1926                 :            :                          * possible. */
    1927         [ #  # ]:          0 :                         if (!bAutoIntersection)
    1928                 :            :                         {
    1929                 :          0 :                             ++pSrc;
    1930                 :          0 :                             nSpaces += 2;   // must match the character count
    1931                 :          0 :                             bAutoIntersection = true;
    1932                 :            :                         }
    1933                 :            :                         else
    1934                 :            :                         {
    1935                 :          0 :                             pSrc--;
    1936                 :          0 :                             eState = ssStop;
    1937                 :            :                         }
    1938                 :            :                     }
    1939                 :            :                     else
    1940                 :            :                     {
    1941                 :          0 :                         nMask &= ~SC_COMPILER_C_ODF_LABEL_OP;
    1942                 :          0 :                         goto Label_MaskStateMachine;
    1943                 :            :                     }
    1944                 :            :                 }
    1945         [ -  + ]:      10527 :                 else if( nMask & SC_COMPILER_C_ODF_NAME_MARKER )
    1946                 :            :                 {
    1947                 :            :                     // '$$' defined name marker
    1948         [ #  # ]:          0 :                     if (GetCharTableFlags( pSrc[0], 0 ) & SC_COMPILER_C_ODF_NAME_MARKER)
    1949                 :            :                     {
    1950                 :            :                         // both eaten, not added to pSym
    1951                 :          0 :                         ++pSrc;
    1952                 :            :                     }
    1953                 :            :                     else
    1954                 :            :                     {
    1955                 :          0 :                         nMask &= ~SC_COMPILER_C_ODF_NAME_MARKER;
    1956                 :          0 :                         goto Label_MaskStateMachine;
    1957                 :            :                     }
    1958                 :            :                 }
    1959         [ +  + ]:      10527 :                 else if( nMask & SC_COMPILER_C_CHAR )
    1960                 :            :                 {
    1961                 :       3602 :                     *pSym++ = c;
    1962                 :       3602 :                     eState = ssStop;
    1963                 :            :                 }
    1964         [ +  + ]:       6925 :                 else if( nMask & SC_COMPILER_C_ODF_LBRACKET )
    1965                 :            :                 {
    1966                 :            :                     // eaten, not added to pSym
    1967                 :        417 :                     eState = ssGetReference;
    1968                 :        417 :                     mnPredetectedReference = 1;
    1969                 :            :                 }
    1970         [ +  + ]:       6508 :                 else if( nMask & SC_COMPILER_C_CHAR_BOOL )
    1971                 :            :                 {
    1972                 :          3 :                     *pSym++ = c;
    1973                 :          3 :                     eState = ssGetBool;
    1974                 :            :                 }
    1975         [ +  + ]:       6505 :                 else if( nMask & SC_COMPILER_C_CHAR_VALUE )
    1976                 :            :                 {
    1977                 :       1284 :                     *pSym++ = c;
    1978                 :       1284 :                     eState = ssGetValue;
    1979                 :            :                 }
    1980         [ +  + ]:       5221 :                 else if( nMask & SC_COMPILER_C_CHAR_STRING )
    1981                 :            :                 {
    1982                 :        258 :                     *pSym++ = c;
    1983                 :        258 :                     eState = ssGetString;
    1984                 :            :                 }
    1985         [ -  + ]:       4963 :                 else if( nMask & SC_COMPILER_C_CHAR_ERRCONST )
    1986                 :            :                 {
    1987                 :          0 :                     *pSym++ = c;
    1988                 :          0 :                     eState = ssGetErrorConstant;
    1989                 :            :                 }
    1990         [ +  + ]:       4963 :                 else if( nMask & SC_COMPILER_C_CHAR_DONTCARE )
    1991                 :            :                 {
    1992                 :         80 :                     nSpaces++;
    1993                 :            :                 }
    1994         [ +  + ]:       4883 :                 else if( nMask & SC_COMPILER_C_CHAR_IDENT )
    1995                 :            :                 {   // try to get a simple ASCII identifier before calling
    1996                 :            :                     // i18n, to gain performance during import
    1997                 :       4796 :                     *pSym++ = c;
    1998                 :       4796 :                     eState = ssGetIdent;
    1999                 :            :                 }
    2000                 :            :                 else
    2001                 :            :                 {
    2002                 :         87 :                     bi18n = true;
    2003                 :         87 :                     eState = ssStop;
    2004                 :            :                 }
    2005                 :            :             }
    2006                 :      10527 :             break;
    2007                 :            :             case ssGetIdent:
    2008                 :            :             {
    2009         [ +  + ]:      43258 :                 if ( nMask & SC_COMPILER_C_IDENT )
    2010                 :            :                 {   // This catches also $Sheet1.A$1, for example.
    2011         [ -  + ]:      39706 :                     if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
    2012                 :            :                     {
    2013                 :          0 :                         SetError(errStringOverflow);
    2014                 :          0 :                         eState = ssStop;
    2015                 :            :                     }
    2016                 :            :                     else
    2017                 :      39706 :                         *pSym++ = c;
    2018                 :            :                 }
    2019 [ +  + ][ +  - ]:       3552 :                 else if (c == ':' && mnRangeOpPosInSymbol < 0)
    2020                 :            :                 {
    2021                 :            :                     // One range operator may form Sheet1.A:A, which we need to
    2022                 :            :                     // pass as one entity to IsReference().
    2023                 :       1650 :                     mnRangeOpPosInSymbol = pSym - &cSymbol[0];
    2024         [ -  + ]:       3300 :                     if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
    2025                 :            :                     {
    2026                 :          0 :                         SetError(errStringOverflow);
    2027                 :          0 :                         eState = ssStop;
    2028                 :            :                     }
    2029                 :            :                     else
    2030                 :       1650 :                         *pSym++ = c;
    2031                 :            :                 }
    2032 [ +  - ][ -  + ]:       1902 :                 else if ( 128 <= c || '\'' == c )
    2033                 :            :                 {   // High values need reparsing with i18n,
    2034                 :            :                     // single quoted $'sheet' names too (otherwise we'd had to
    2035                 :            :                     // implement everything twice).
    2036                 :          0 :                     bi18n = true;
    2037                 :          0 :                     eState = ssStop;
    2038                 :            :                 }
    2039                 :            :                 else
    2040                 :            :                 {
    2041                 :       1902 :                     pSrc--;
    2042                 :       1902 :                     eState = ssStop;
    2043                 :            :                 }
    2044                 :            :             }
    2045                 :      43258 :             break;
    2046                 :            :             case ssGetBool :
    2047                 :            :             {
    2048         [ -  + ]:          3 :                 if( nMask & SC_COMPILER_C_BOOL )
    2049                 :            :                 {
    2050                 :          0 :                     *pSym++ = c;
    2051                 :          0 :                     eState = ssStop;
    2052                 :            :                 }
    2053                 :            :                 else
    2054                 :            :                 {
    2055                 :          3 :                     pSrc--;
    2056                 :          3 :                     eState = ssStop;
    2057                 :            :                 }
    2058                 :            :             }
    2059                 :          3 :             break;
    2060                 :            :             case ssGetValue :
    2061                 :            :             {
    2062         [ -  + ]:       1111 :                 if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
    2063                 :            :                 {
    2064                 :          0 :                     SetError(errStringOverflow);
    2065                 :          0 :                     eState = ssStop;
    2066                 :            :                 }
    2067         [ +  + ]:       1111 :                 else if (c == cDecSep)
    2068                 :            :                 {
    2069         [ -  + ]:         42 :                     if (++nDecSeps > 1)
    2070                 :            :                     {
    2071                 :            :                         // reparse with i18n, may be numeric sheet name as well
    2072                 :          0 :                         bi18n = true;
    2073                 :          0 :                         eState = ssStop;
    2074                 :            :                     }
    2075                 :            :                     else
    2076                 :         42 :                         *pSym++ = c;
    2077                 :            :                 }
    2078         [ +  + ]:       1069 :                 else if( nMask & SC_COMPILER_C_VALUE )
    2079                 :        348 :                     *pSym++ = c;
    2080         [ +  + ]:        721 :                 else if( nMask & SC_COMPILER_C_VALUE_SEP )
    2081                 :            :                 {
    2082                 :        696 :                     pSrc--;
    2083                 :        696 :                     eState = ssStop;
    2084                 :            :                 }
    2085 [ +  - ][ -  + ]:         25 :                 else if (c == 'E' || c == 'e')
    2086                 :            :                 {
    2087         [ #  # ]:          0 :                     if (GetCharTableFlags( pSrc[0], 0 ) & SC_COMPILER_C_VALUE_EXP)
    2088                 :          0 :                         *pSym++ = c;
    2089                 :            :                     else
    2090                 :            :                     {
    2091                 :            :                         // reparse with i18n
    2092                 :          0 :                         bi18n = true;
    2093                 :          0 :                         eState = ssStop;
    2094                 :            :                     }
    2095                 :            :                 }
    2096         [ +  - ]:         25 :                 else if( nMask & SC_COMPILER_C_VALUE_SIGN )
    2097                 :            :                 {
    2098         [ +  - ]:         25 :                     if (((cLast == 'E') || (cLast == 'e')) &&
           [ -  +  #  # ]
                 [ -  + ]
    2099                 :          0 :                             (GetCharTableFlags( pSrc[0], 0 ) & SC_COMPILER_C_VALUE_VALUE))
    2100                 :            :                     {
    2101                 :          0 :                         *pSym++ = c;
    2102                 :            :                     }
    2103                 :            :                     else
    2104                 :            :                     {
    2105                 :         25 :                         pSrc--;
    2106                 :         25 :                         eState = ssStop;
    2107                 :            :                     }
    2108                 :            :                 }
    2109                 :            :                 else
    2110                 :            :                 {
    2111                 :            :                     // reparse with i18n
    2112                 :          0 :                     bi18n = true;
    2113                 :          0 :                     eState = ssStop;
    2114                 :            :                 }
    2115                 :            :             }
    2116                 :       1111 :             break;
    2117                 :            :             case ssGetString :
    2118                 :            :             {
    2119         [ +  + ]:       2022 :                 if( nMask & SC_COMPILER_C_STRING_SEP )
    2120                 :            :                 {
    2121         [ +  - ]:        258 :                     if ( !bQuote )
    2122                 :            :                     {
    2123         [ -  + ]:        258 :                         if ( *pSrc == '"' )
    2124                 :          0 :                             bQuote = true;      // "" => literal "
    2125                 :            :                         else
    2126                 :        258 :                             eState = ssStop;
    2127                 :            :                     }
    2128                 :            :                     else
    2129                 :          0 :                         bQuote = false;
    2130                 :            :                 }
    2131         [ +  - ]:       2022 :                 if ( !bQuote )
    2132                 :            :                 {
    2133         [ -  + ]:       2022 :                     if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
    2134                 :            :                     {
    2135                 :          0 :                         SetError(errStringOverflow);
    2136                 :          0 :                         eState = ssSkipString;
    2137                 :            :                     }
    2138                 :            :                     else
    2139                 :       2022 :                         *pSym++ = c;
    2140                 :            :                 }
    2141                 :            :             }
    2142                 :       2022 :             break;
    2143                 :            :             case ssSkipString:
    2144         [ #  # ]:          0 :                 if( nMask & SC_COMPILER_C_STRING_SEP )
    2145                 :          0 :                     eState = ssStop;
    2146                 :          0 :                 break;
    2147                 :            :             case ssGetErrorConstant:
    2148                 :            :                 {
    2149                 :            :                     // ODFF Error ::= '#' [A-Z0-9]+ ([!?] | ('/' ([A-Z] | ([0-9] [!?]))))
    2150                 :            :                     // BUT, in UI these may have been translated! So don't
    2151                 :            :                     // check for ASCII alnum. Note that this construct can't be
    2152                 :            :                     // parsed with i18n.
    2153                 :            :                     /* TODO: be strict when reading ODFF, check for ASCII alnum
    2154                 :            :                      * and proper continuation after '/'. However, even with
    2155                 :            :                      * the lax parsing only the error constants we have defined
    2156                 :            :                      * as opcode symbols will be recognized and others result
    2157                 :            :                      * in ocBad, so the result is actually conformant. */
    2158                 :          0 :                     bool bAdd = true;
    2159 [ #  # ][ #  # ]:          0 :                     if ('!' == c || '?' == c)
    2160                 :          0 :                         eState = ssStop;
    2161         [ #  # ]:          0 :                     else if ('/' == c)
    2162                 :            :                     {
    2163         [ #  # ]:          0 :                         if (!bErrorConstantHadSlash)
    2164                 :          0 :                             bErrorConstantHadSlash = true;
    2165                 :            :                         else
    2166                 :            :                         {
    2167                 :          0 :                             bAdd = false;
    2168                 :          0 :                             eState = ssStop;
    2169                 :            :                         }
    2170                 :            :                     }
    2171         [ #  # ]:          0 :                     else if ((nMask & SC_COMPILER_C_WORD_SEP) ||
           [ #  #  #  # ]
                 [ #  # ]
    2172                 :          0 :                             (c < 128 && !CharClass::isAsciiAlphaNumeric( c)))
    2173                 :            :                     {
    2174                 :          0 :                         bAdd = false;
    2175                 :          0 :                         eState = ssStop;
    2176                 :            :                     }
    2177         [ #  # ]:          0 :                     if (!bAdd)
    2178                 :          0 :                         --pSrc;
    2179                 :            :                     else
    2180                 :            :                     {
    2181         [ #  # ]:          0 :                         if (pSym == &cSymbol[ MAXSTRLEN-1 ])
    2182                 :            :                         {
    2183                 :          0 :                             SetError( errStringOverflow);
    2184                 :          0 :                             eState = ssStop;
    2185                 :            :                         }
    2186                 :            :                         else
    2187                 :          0 :                             *pSym++ = c;
    2188                 :            :                     }
    2189                 :            :                 }
    2190                 :          0 :                 break;
    2191                 :            :             case ssGetReference:
    2192         [ -  + ]:       2730 :                 if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
    2193                 :            :                 {
    2194                 :          0 :                     SetError( errStringOverflow);
    2195                 :          0 :                     eState = ssSkipReference;
    2196                 :            :                 }
    2197                 :            :                 // fall through and follow logic
    2198                 :            :             case ssSkipReference:
    2199                 :            :                 // ODF reference: ['External'#$'Sheet'.A1:.B2] with dots being
    2200                 :            :                 // mandatory also if no sheet name. 'External'# is optional,
    2201                 :            :                 // sheet name is optional, quotes around sheet name are
    2202                 :            :                 // optional if no quote contained. [#REF!] is valid.
    2203                 :            :                 // 2nd usage: ['Sheet'.$$'DefinedName']
    2204                 :            :                 // 3rd usage: ['External'#$$'DefinedName']
    2205                 :            :                 // 4th usage: ['External'#$'Sheet'.$$'DefinedName']
    2206                 :            :                 // Also for all these names quotes are optional if no quote
    2207                 :            :                 // contained.
    2208                 :            :                 {
    2209                 :            : 
    2210                 :            :                     // nRefInName: 0 := not in sheet name yet. 'External'
    2211                 :            :                     // is parsed as if it was a sheet name and nRefInName
    2212                 :            :                     // is reset when # is encountered immediately after closing
    2213                 :            :                     // quote. Same with 'DefinedName', nRefInName is cleared
    2214                 :            :                     // when : is encountered.
    2215                 :            : 
    2216                 :            :                     // Encountered leading $ before sheet name.
    2217                 :            :                     static const int kDollar    = (1 << 1);
    2218                 :            :                     // Encountered ' opening quote, which may be after $ or
    2219                 :            :                     // not.
    2220                 :            :                     static const int kOpen      = (1 << 2);
    2221                 :            :                     // Somewhere in name.
    2222                 :            :                     static const int kName      = (1 << 3);
    2223                 :            :                     // Encountered ' in name, will be cleared if double or
    2224                 :            :                     // transformed to kClose if not, in which case kOpen is
    2225                 :            :                     // cleared.
    2226                 :            :                     static const int kQuote     = (1 << 4);
    2227                 :            :                     // Past ' closing quote.
    2228                 :            :                     static const int kClose     = (1 << 5);
    2229                 :            :                     // Encountered # file/sheet separator.
    2230                 :            :                     static const int kFileSep   = (1 << 6);
    2231                 :            :                     // Past . sheet name separator.
    2232                 :            :                     static const int kPast      = (1 << 7);
    2233                 :            :                     // Marked name $$ follows sheet name separator, detected
    2234                 :            :                     // while we're still on the separator. Will be cleared when
    2235                 :            :                     // entering the name.
    2236                 :            :                     static const int kMarkAhead = (1 << 8);
    2237                 :            :                     // In marked defined name.
    2238                 :            :                     static const int kDefName   = (1 << 9);
    2239                 :            :                     // Encountered # of #REF!
    2240                 :            :                     static const int kRefErr    = (1 << 10);
    2241                 :            : 
    2242                 :       2730 :                     bool bAddToSymbol = true;
    2243 [ +  + ][ +  - ]:       2730 :                     if ((nMask & SC_COMPILER_C_ODF_RBRACKET) && !(nRefInName & kOpen))
    2244                 :            :                     {
    2245                 :            :                         OSL_ENSURE( nRefInName & (kPast | kDefName | kRefErr),
    2246                 :            :                                 "ScCompiler::NextSymbol: reference: "
    2247                 :            :                                 "closing bracket ']' without prior sheet name separator '.' violates ODF spec");
    2248                 :            :                         // eaten, not added to pSym
    2249                 :        417 :                         bAddToSymbol = false;
    2250                 :        417 :                         eState = ssStop;
    2251                 :            :                     }
    2252 [ +  + ][ +  + ]:       2313 :                     else if (cSheetSep == c && nRefInName == 0)
    2253                 :            :                     {
    2254                 :            :                         // eat it, no sheet name [.A1]
    2255                 :        507 :                         bAddToSymbol = false;
    2256                 :        507 :                         nRefInName |= kPast;
    2257 [ -  + ][ #  # ]:        507 :                         if ('$' == pSrc[0] && '$' == pSrc[1])
    2258                 :          0 :                             nRefInName |= kMarkAhead;
    2259                 :            :                     }
    2260 [ +  + ][ -  + ]:       1806 :                     else if (!(nRefInName & kPast) || (nRefInName & (kMarkAhead | kDefName)))
    2261                 :            :                     {
    2262                 :            :                         // Not in col/row yet.
    2263                 :            : 
    2264 [ -  + ][ #  # ]:        792 :                         if (SC_COMPILER_FILE_TAB_SEP == c && (nRefInName & kFileSep))
    2265                 :          0 :                             nRefInName = 0;
    2266 [ -  + ][ #  # ]:        396 :                         else if ('$' == c && '$' == pSrc[0] && !(nRefInName & kOpen))
                 [ #  # ]
    2267                 :            :                         {
    2268                 :          0 :                             nRefInName &= ~kMarkAhead;
    2269         [ #  # ]:          0 :                             if (!(nRefInName & kDefName))
    2270                 :            :                             {
    2271                 :            :                                 // eaten, not added to pSym (2 chars)
    2272                 :          0 :                                 bAddToSymbol = false;
    2273                 :          0 :                                 ++pSrc;
    2274                 :          0 :                                 nRefInName &= kPast;
    2275                 :          0 :                                 nRefInName |= kDefName;
    2276                 :            :                             }
    2277                 :            :                             else
    2278                 :            :                             {
    2279                 :            :                                 // ScAddress::Parse() will recognize this as
    2280                 :            :                                 // invalid later.
    2281         [ #  # ]:          0 :                                 if (eState != ssSkipReference)
    2282                 :            :                                 {
    2283                 :          0 :                                     *pSym++ = c;
    2284                 :          0 :                                     *pSym++ = *pSrc++;
    2285                 :            :                                 }
    2286                 :          0 :                                 bAddToSymbol = false;
    2287                 :            :                             }
    2288                 :            :                         }
    2289 [ -  + ][ #  # ]:        396 :                         else if (cSheetPrefix == c && nRefInName == 0)
    2290                 :          0 :                             nRefInName |= kDollar;
    2291         [ -  + ]:        396 :                         else if ('\'' == c)
    2292                 :            :                         {
    2293                 :            :                             // TODO: The conventions' parseExternalName()
    2294                 :            :                             // should handle quoted names, but as long as they
    2295                 :            :                             // don't remove non-embedded quotes here.
    2296         [ #  # ]:          0 :                             if (!(nRefInName & kName))
    2297                 :            :                             {
    2298                 :          0 :                                 nRefInName |= (kOpen | kName);
    2299                 :          0 :                                 bAddToSymbol = !(nRefInName & kDefName);
    2300                 :            :                             }
    2301         [ #  # ]:          0 :                             else if (!(nRefInName & kOpen))
    2302                 :            :                             {
    2303                 :            :                                 OSL_FAIL("ScCompiler::NextSymbol: reference: "
    2304                 :            :                                         "a ''' without the name being enclosed in '...' violates ODF spec");
    2305                 :            :                             }
    2306         [ #  # ]:          0 :                             else if (nRefInName & kQuote)
    2307                 :            :                             {
    2308                 :            :                                 // escaped embedded quote
    2309                 :          0 :                                 nRefInName &= ~kQuote;
    2310                 :            :                             }
    2311                 :            :                             else
    2312                 :            :                             {
    2313      [ #  #  # ]:          0 :                                 switch (pSrc[0])
    2314                 :            :                                 {
    2315                 :            :                                     case '\'':
    2316                 :            :                                         // escapes embedded quote
    2317                 :          0 :                                         nRefInName |= kQuote;
    2318                 :          0 :                                         break;
    2319                 :            :                                     case SC_COMPILER_FILE_TAB_SEP:
    2320                 :            :                                         // sheet name should follow
    2321                 :          0 :                                         nRefInName |= kFileSep;
    2322                 :            :                                         // fallthru
    2323                 :            :                                     default:
    2324                 :            :                                         // quote not followed by quote => close
    2325                 :          0 :                                         nRefInName |= kClose;
    2326                 :          0 :                                         nRefInName &= ~kOpen;
    2327                 :            :                                 }
    2328                 :          0 :                                 bAddToSymbol = !(nRefInName & kDefName);
    2329                 :            :                             }
    2330                 :            :                         }
    2331 [ -  + ][ #  # ]:        396 :                         else if ('#' == c && nRefInName == 0)
    2332                 :          0 :                             nRefInName |= kRefErr;
    2333 [ +  + ][ +  - ]:        396 :                         else if (cSheetSep == c && !(nRefInName & kOpen))
    2334                 :            :                         {
    2335                 :            :                             // unquoted sheet name separator
    2336                 :         36 :                             nRefInName |= kPast;
    2337 [ -  + ][ #  # ]:         36 :                             if ('$' == pSrc[0] && '$' == pSrc[1])
    2338                 :          0 :                                 nRefInName |= kMarkAhead;
    2339                 :            :                         }
    2340 [ -  + ][ #  # ]:        360 :                         else if (':' == c && !(nRefInName & kOpen))
    2341                 :            :                         {
    2342                 :            :                             OSL_FAIL("ScCompiler::NextSymbol: reference: "
    2343                 :            :                                     "range operator ':' without prior sheet name separator '.' violates ODF spec");
    2344                 :          0 :                             nRefInName = 0;
    2345                 :          0 :                             ++mnPredetectedReference;
    2346                 :            :                         }
    2347         [ +  + ]:        360 :                         else if (!(nRefInName & kName))
    2348                 :            :                         {
    2349                 :            :                             // start unquoted name
    2350                 :         36 :                             nRefInName |= kName;
    2351                 :            :                         }
    2352                 :            :                     }
    2353         [ +  + ]:       1410 :                     else if (':' == c)
    2354                 :            :                     {
    2355                 :            :                         // range operator
    2356                 :        126 :                         nRefInName = 0;
    2357                 :        126 :                         ++mnPredetectedReference;
    2358                 :            :                     }
    2359 [ +  + ][ +  - ]:       2730 :                     if (bAddToSymbol && eState != ssSkipReference)
    2360                 :       1806 :                         *pSym++ = c;    // everything is part of reference
    2361                 :            :                 }
    2362                 :       2730 :                 break;
    2363                 :            :             case ssStop:
    2364                 :            :                 ;   // nothing, prevent warning
    2365                 :       1824 :                 break;
    2366                 :            :         }
    2367                 :      61475 :         cLast = c;
    2368                 :      61475 :         c = *pSrc;
    2369                 :            :     }
    2370         [ +  + ]:      15663 :     if ( bi18n )
    2371                 :            :     {
    2372                 :         87 :         nSrcPos = sal::static_int_cast<xub_StrLen>( nSrcPos + nSpaces );
    2373         [ +  - ]:         87 :         String aSymbol;
    2374                 :         87 :         mnRangeOpPosInSymbol = -1;
    2375                 :         87 :         sal_uInt16 nErr = 0;
    2376 [ +  - ][ +  + ]:        192 :         do
                 [ +  + ]
    2377                 :            :         {
    2378                 :        192 :             bi18n = false;
    2379                 :            :             // special case  (e.g. $'sheetname' in OOO A1)
    2380 [ -  + ][ #  # ]:        192 :             if ( pStart[nSrcPos] == cSheetPrefix && pStart[nSrcPos+1] == '\'' )
    2381         [ #  # ]:          0 :                 aSymbol += pStart[nSrcPos++];
    2382                 :            : 
    2383         [ +  - ]:        192 :             ParseResult aRes = pConv->parseAnyToken( aFormula, nSrcPos, pCharClass );
    2384                 :            : 
    2385         [ -  + ]:        192 :             if ( !aRes.TokenType )
    2386         [ #  # ]:          0 :                 SetError( nErr = errIllegalChar );      // parsed chars as string
    2387         [ -  + ]:        192 :             if ( aRes.EndPos <= nSrcPos )
    2388                 :            :             {   // ?!?
    2389         [ #  # ]:          0 :                 SetError( nErr = errIllegalChar );
    2390                 :          0 :                 nSrcPos = aFormula.Len();
    2391         [ #  # ]:          0 :                 aSymbol.Erase();
    2392                 :            :             }
    2393                 :            :             else
    2394                 :            :             {
    2395         [ +  - ]:        192 :                 aSymbol.Append( pStart + nSrcPos, (xub_StrLen)aRes.EndPos - nSrcPos );
    2396                 :        192 :                 nSrcPos = (xub_StrLen) aRes.EndPos;
    2397                 :        192 :                 c = pStart[nSrcPos];
    2398         [ +  + ]:        192 :                 if ( aRes.TokenType & KParseType::SINGLE_QUOTE_NAME )
    2399                 :            :                 {   // special cases (e.g. 'sheetname'. or 'filename'# in OOO A1)
    2400 [ +  - ][ +  - ]:         87 :                     bi18n = (c == cSheetSep || c == SC_COMPILER_FILE_TAB_SEP);
    2401                 :            :                 }
    2402                 :            :                 // One range operator restarts parsing for second reference.
    2403 [ +  + ][ +  - ]:        192 :                 if (c == ':' && mnRangeOpPosInSymbol < 0)
    2404                 :            :                 {
    2405                 :         18 :                     mnRangeOpPosInSymbol = aSymbol.Len();
    2406                 :         18 :                     bi18n = true;
    2407                 :            :                 }
    2408         [ +  + ]:        192 :                 if ( bi18n )
    2409         [ +  - ]:        105 :                     aSymbol += pStart[nSrcPos++];
    2410                 :        192 :             }
    2411                 :            :         } while ( bi18n && !nErr );
    2412                 :         87 :         xub_StrLen nLen = aSymbol.Len();
    2413         [ -  + ]:         87 :         if ( nLen >= MAXSTRLEN )
    2414                 :            :         {
    2415         [ #  # ]:          0 :             SetError( errStringOverflow );
    2416                 :          0 :             nLen = MAXSTRLEN-1;
    2417                 :            :         }
    2418                 :         87 :         lcl_UnicodeStrNCpy( cSymbol, aSymbol.GetBuffer(), nLen );
    2419         [ +  - ]:         87 :         pSym = &cSymbol[nLen];
    2420                 :            :     }
    2421                 :            :     else
    2422                 :            :     {
    2423                 :      15576 :         nSrcPos = sal::static_int_cast<xub_StrLen>( pSrc - pStart );
    2424                 :      15576 :         *pSym = 0;
    2425                 :            :     }
    2426 [ +  + ][ -  + ]:      15663 :     if (mnRangeOpPosInSymbol >= 0 && mnRangeOpPosInSymbol == (pSym-1) - &cSymbol[0])
    2427                 :            :     {
    2428                 :            :         // This is a trailing range operator, which is nonsense. Will be caught
    2429                 :            :         // in next round.
    2430                 :          0 :         mnRangeOpPosInSymbol = -1;
    2431                 :          0 :         *--pSym = 0;
    2432                 :          0 :         --nSrcPos;
    2433                 :            :     }
    2434         [ -  + ]:      15663 :     if ( bAutoCorrect )
    2435                 :          0 :         aCorrectedSymbol = cSymbol;
    2436 [ -  + ][ #  # ]:      15663 :     if (bAutoIntersection && nSpaces > 1)
    2437                 :          0 :         --nSpaces;  // replace '!!' with only one space
    2438                 :      15663 :     return nSpaces;
    2439                 :            : }
    2440                 :            : 
    2441                 :            : //---------------------------------------------------------------------------
    2442                 :            : // Convert symbol to token
    2443                 :            : //---------------------------------------------------------------------------
    2444                 :            : 
    2445                 :       8588 : bool ScCompiler::IsOpCode( const String& rName, bool bInArray )
    2446                 :            : {
    2447         [ +  - ]:       8588 :     OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap()->find( rName));
    2448         [ +  - ]:       8588 :     bool bFound = (iLook != mxSymbols->getHashMap()->end());
    2449         [ +  + ]:       8588 :     if (bFound)
    2450                 :            :     {
    2451                 :       6213 :         ScRawToken aToken;
    2452         [ +  - ]:       6213 :         OpCode eOp = iLook->second;
    2453         [ +  + ]:       6213 :         if (bInArray)
    2454                 :            :         {
    2455 [ +  - ][ +  - ]:         57 :             if (rName.Equals(mxSymbols->getSymbol(ocArrayColSep)))
                 [ +  + ]
    2456                 :         36 :                 eOp = ocArrayColSep;
    2457 [ +  - ][ +  - ]:         21 :             else if (rName.Equals(mxSymbols->getSymbol(ocArrayRowSep)))
                 [ +  + ]
    2458                 :          6 :                 eOp = ocArrayRowSep;
    2459                 :            :         }
    2460         [ +  - ]:       6213 :         aToken.SetOpCode(eOp);
    2461 [ +  - ][ +  - ]:       6213 :         pRawToken = aToken.Clone();
    2462                 :            :     }
    2463         [ +  + ]:       2375 :     else if (mxSymbols->isODFF())
    2464                 :            :     {
    2465                 :            :         // ODFF names that are not written in the current mapping but to be
    2466                 :            :         // recognized. New names will be written in a future relase, then
    2467                 :            :         // exchange (!) with the names in
    2468                 :            :         // formula/source/core/resource/core_resource.src to be able to still
    2469                 :            :         // read the old names as well.
    2470                 :            :         struct FunctionName
    2471                 :            :         {
    2472                 :            :             const sal_Char* pName;
    2473                 :            :             OpCode          eOp;
    2474                 :            :         };
    2475                 :            :         static const FunctionName aOdffAliases[] = {
    2476                 :            :             // Renamed old names:
    2477                 :            :             { "B",              ocB },              // B -> BINOM.DIST.RANGE
    2478                 :            :             { "TDIST",          ocTDist },          // TDIST -> LEGACY.TDIST
    2479                 :            :             { "EASTERSUNDAY",   ocEasterSunday }    // EASTERSUNDAY -> ORG.OPENOFFICE.EASTERSUNDAY
    2480                 :            :             // Renamed new names:
    2481                 :            :             // XXX none currently. Example:
    2482                 :            :             //{ "ORG.OPENOFFICE.EASTERSUNDAY", ocEasterSunday }
    2483                 :            :         };
    2484                 :            :         static const size_t nOdffAliases = sizeof(aOdffAliases) / sizeof(aOdffAliases[0]);
    2485         [ +  + ]:        248 :         for (size_t i=0; i<nOdffAliases; ++i)
    2486                 :            :         {
    2487 [ +  - ][ -  + ]:        186 :             if (rName.EqualsIgnoreCaseAscii( aOdffAliases[i].pName))
    2488                 :            :             {
    2489                 :          0 :                 ScRawToken aToken;
    2490         [ #  # ]:          0 :                 aToken.SetOpCode( aOdffAliases[i].eOp);
    2491 [ #  # ][ #  # ]:          0 :                 pRawToken = aToken.Clone();
    2492                 :          0 :                 bFound = true;
    2493                 :          0 :                 break;  // for
    2494                 :            :             }
    2495                 :            :         }
    2496                 :            :     }
    2497         [ +  + ]:       8588 :     if (!bFound)
    2498                 :            :     {
    2499         [ +  - ]:       2375 :         String aIntName;
    2500 [ +  - ][ +  + ]:       2375 :         if (mxSymbols->hasExternals())
    2501                 :            :         {
    2502                 :            :             // If symbols are set by filters get mapping to exact name.
    2503                 :            :             ExternalHashMap::const_iterator iExt(
    2504         [ +  - ]:         83 :                     mxSymbols->getExternalHashMap()->find( rName));
    2505 [ +  - ][ -  + ]:         83 :             if (iExt != mxSymbols->getExternalHashMap()->end())
    2506                 :            :             {
    2507 [ #  # ][ #  # ]:          0 :                 if (ScGlobal::GetAddInCollection()->GetFuncData( (*iExt).second))
         [ #  # ][ #  # ]
                 [ #  # ]
    2508 [ #  # ][ #  # ]:          0 :                     aIntName = (*iExt).second;
    2509                 :            :             }
    2510         [ +  - ]:         83 :             if (!aIntName.Len())
    2511                 :            :             {
    2512                 :            :                 // If that isn't found we might continue with rName lookup as a
    2513                 :            :                 // last resort by just falling through to FindFunction(), but
    2514                 :            :                 // it shouldn't happen if the map was setup correctly. Don't
    2515                 :            :                 // waste time and bail out.
    2516                 :         83 :                 return false;
    2517                 :            :             }
    2518                 :            :         }
    2519         [ +  - ]:       2292 :         if (!aIntName.Len())
    2520                 :            :         {
    2521                 :            :             // Old (deprecated) addins first for legacy.
    2522 [ +  - ][ +  - ]:       2292 :             if (ScGlobal::GetFuncCollection()->findByName(cSymbol))
                 [ -  + ]
    2523                 :            :             {
    2524                 :          0 :                 ScRawToken aToken;
    2525         [ #  # ]:          0 :                 aToken.SetExternal( cSymbol );
    2526 [ #  # ][ #  # ]:          0 :                 pRawToken = aToken.Clone();
    2527                 :            :             }
    2528                 :            :             else
    2529                 :            :                 // bLocalFirst=false for (English) upper full original name
    2530                 :            :                 // (service.function)
    2531                 :            :                 aIntName = ScGlobal::GetAddInCollection()->FindFunction(
    2532 [ +  - ][ +  - ]:       2292 :                         rName, !mxSymbols->isEnglish());
         [ +  - ][ +  - ]
    2533                 :            :         }
    2534         [ -  + ]:       2292 :         if (aIntName.Len())
    2535                 :            :         {
    2536                 :          0 :             ScRawToken aToken;
    2537         [ #  # ]:          0 :             aToken.SetExternal( aIntName.GetBuffer() );     // international name
    2538 [ #  # ][ #  # ]:          0 :             pRawToken = aToken.Clone();
    2539                 :       2292 :             bFound = true;
    2540 [ +  - ][ +  + ]:       2375 :         }
    2541                 :            :     }
    2542                 :            :     OpCode eOp;
    2543 [ +  + ][ +  + ]:       8505 :     if (bFound && ((eOp = pRawToken->GetOpCode()) == ocSub || eOp == ocNegSub))
         [ +  + ][ +  + ]
    2544                 :            :     {
    2545                 :            :         bool bShouldBeNegSub =
    2546                 :            :             (eLastOp == ocOpen || eLastOp == ocSep || eLastOp == ocNegSub ||
    2547                 :            :              (SC_OPCODE_START_BIN_OP <= eLastOp && eLastOp < SC_OPCODE_STOP_BIN_OP) ||
    2548                 :            :              eLastOp == ocArrayOpen ||
    2549 [ +  + ][ +  + ]:        186 :              eLastOp == ocArrayColSep || eLastOp == ocArrayRowSep);
         [ +  - ][ -  + ]
         [ #  # ][ +  - ]
         [ +  - ][ -  + ]
    2550 [ +  + ][ +  - ]:        186 :         if (bShouldBeNegSub && eOp == ocSub)
    2551                 :        178 :             pRawToken->NewOpCode( ocNegSub );
    2552                 :            :             //! if ocNegSub had ForceArray we'd have to set it here
    2553 [ +  - ][ +  + ]:          8 :         else if (!bShouldBeNegSub && eOp == ocNegSub)
    2554                 :        186 :             pRawToken->NewOpCode( ocSub );
    2555                 :            :     }
    2556                 :       8588 :     return bFound;
    2557                 :            : }
    2558                 :            : 
    2559                 :          3 : bool ScCompiler::IsOpCode2( const String& rName )
    2560                 :            : {
    2561                 :          3 :     bool bFound = false;
    2562                 :            :     sal_uInt16 i;
    2563                 :            : 
    2564 [ +  + ][ +  - ]:          6 :     for( i = ocInternalBegin; i <= ocInternalEnd && !bFound; i++ )
                 [ +  + ]
    2565                 :          3 :         bFound = rName.EqualsAscii( pInternal[ i-ocInternalBegin ] );
    2566                 :            : 
    2567         [ -  + ]:          3 :     if (bFound)
    2568                 :            :     {
    2569                 :          0 :         ScRawToken aToken;
    2570         [ #  # ]:          0 :         aToken.SetOpCode( (OpCode) --i );
    2571 [ #  # ][ #  # ]:          0 :         pRawToken = aToken.Clone();
    2572                 :            :     }
    2573                 :          3 :     return bFound;
    2574                 :            : }
    2575                 :            : 
    2576                 :       1433 : bool ScCompiler::IsValue( const String& rSym )
    2577                 :            : {
    2578                 :            :     double fVal;
    2579                 :       1433 :     sal_uInt32 nIndex = ( mxSymbols->isEnglish() ?
    2580 [ +  - ][ +  - ]:       1433 :         pDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US ) : 0 );
                 [ +  + ]
    2581                 :            : 
    2582 [ +  - ][ +  - ]:       1433 :     if (pDoc->GetFormatTable()->IsNumberFormat( rSym, nIndex, fVal ) )
                 [ +  + ]
    2583                 :            :     {
    2584 [ +  - ][ +  - ]:       1284 :         sal_uInt16 nType = pDoc->GetFormatTable()->GetType(nIndex);
    2585                 :            : 
    2586                 :            :         // Don't accept 3:3 as time, it is a reference to entire row 3 instead.
    2587                 :            :         // Dates should never be entered directly and automatically converted
    2588                 :            :         // to serial, because the serial would be wrong if null-date changed.
    2589                 :            :         // Usually it wouldn't be accepted anyway because the date separator
    2590                 :            :         // clashed with other separators or operators.
    2591         [ -  + ]:       1284 :         if (nType & (NUMBERFORMAT_TIME | NUMBERFORMAT_DATE))
    2592                 :          0 :             return false;
    2593                 :            : 
    2594         [ -  + ]:       1284 :         if (nType == NUMBERFORMAT_LOGICAL)
    2595                 :            :         {
    2596                 :          0 :             const sal_Unicode* p = aFormula.GetBuffer() + nSrcPos;
    2597         [ #  # ]:          0 :             while( *p == ' ' )
    2598                 :          0 :                 p++;
    2599         [ #  # ]:          0 :             if (*p == '(')
    2600                 :          0 :                 return false;   // Boolean function instead.
    2601                 :            :         }
    2602                 :            : 
    2603         [ -  + ]:       1284 :         if( nType == NUMBERFORMAT_TEXT )
    2604                 :            :             // HACK: number too big!
    2605         [ #  # ]:          0 :             SetError( errIllegalArgument );
    2606                 :       1284 :         ScRawToken aToken;
    2607         [ +  - ]:       1284 :         aToken.SetDouble( fVal );
    2608 [ +  - ][ +  - ]:       1284 :         pRawToken = aToken.Clone();
    2609                 :       1284 :         return true;
    2610                 :            :     }
    2611                 :            :     else
    2612                 :       1433 :         return false;
    2613                 :            : }
    2614                 :            : 
    2615                 :      11040 : bool ScCompiler::IsString()
    2616                 :            : {
    2617                 :      11040 :     register const sal_Unicode* p = cSymbol;
    2618         [ +  + ]:      68485 :     while ( *p )
    2619                 :      57445 :         p++;
    2620                 :      11040 :     xub_StrLen nLen = sal::static_int_cast<xub_StrLen>( p - cSymbol - 1 );
    2621 [ +  - ][ +  + ]:      11040 :     bool bQuote = ((cSymbol[0] == '"') && (cSymbol[nLen] == '"'));
    2622 [ +  + ][ -  + ]:      11040 :     if ((bQuote ? nLen-2 : nLen) > MAXSTRLEN-1)
    2623                 :            :     {
    2624                 :          0 :         SetError(errStringOverflow);
    2625                 :          0 :         return false;
    2626                 :            :     }
    2627         [ +  + ]:      11040 :     if ( bQuote )
    2628                 :            :     {
    2629                 :        258 :         cSymbol[nLen] = '\0';
    2630                 :        258 :         ScRawToken aToken;
    2631         [ +  - ]:        258 :         aToken.SetString( cSymbol+1 );
    2632 [ +  - ][ +  - ]:        258 :         pRawToken = aToken.Clone();
    2633                 :        258 :         return true;
    2634                 :            :     }
    2635                 :      11040 :     return false;
    2636                 :            : }
    2637                 :            : 
    2638                 :            : 
    2639                 :        417 : bool ScCompiler::IsPredetectedReference( const String& rName )
    2640                 :            : {
    2641                 :            :     // Speedup documents with lots of broken references, e.g. sheet deleted.
    2642                 :        417 :     xub_StrLen nPos = rName.SearchAscii( "#REF!");
    2643         [ -  + ]:        417 :     if (nPos != STRING_NOTFOUND)
    2644                 :            :     {
    2645                 :            :         /* TODO: this may be enhanced by reusing scan information from
    2646                 :            :          * NextSymbol(), the positions of quotes and special characters found
    2647                 :            :          * there for $'sheet'.A1:... could be stored in a vector. We don't
    2648                 :            :          * fully rescan here whether found positions are within single quotes
    2649                 :            :          * for performance reasons. This code does not check for possible
    2650                 :            :          * occurrences of insane "valid" sheet names like
    2651                 :            :          * 'haha.#REF!1fooledyou' and will generate an error on such. */
    2652         [ #  # ]:          0 :         if (nPos == 0)
    2653                 :            :         {
    2654                 :            :             // Per ODFF the correct string for a reference error is just #REF!,
    2655                 :            :             // so pass it on.
    2656         [ #  # ]:          0 :             if (rName.Len() == 5)
    2657                 :          0 :                 return IsErrorConstant( rName);
    2658                 :          0 :             return false;           // #REF!.AB42 or #REF!42 or #REF!#REF!
    2659                 :            :         }
    2660                 :          0 :         sal_Unicode c = rName.GetChar(nPos-1);      // before #REF!
    2661         [ #  # ]:          0 :         if ('$' == c)
    2662                 :            :         {
    2663         [ #  # ]:          0 :             if (nPos == 1)
    2664                 :          0 :                 return false;       // $#REF!.AB42 or $#REF!42 or $#REF!#REF!
    2665                 :          0 :             c = rName.GetChar(nPos-2);              // before $#REF!
    2666                 :            :         }
    2667                 :          0 :         sal_Unicode c2 = rName.GetChar(nPos+5);     // after #REF!
    2668      [ #  #  # ]:          0 :         switch (c)
    2669                 :            :         {
    2670                 :            :             case '.':
    2671 [ #  # ][ #  # ]:          0 :                 if ('$' == c2 || '#' == c2 || ('0' <= c2 && c2 <= '9'))
         [ #  # ][ #  # ]
    2672                 :          0 :                     return false;   // sheet.#REF!42 or sheet.#REF!#REF!
    2673                 :          0 :                 break;
    2674                 :            :             case ':':
    2675 [ #  # ][ #  # ]:          0 :                 if (mnPredetectedReference > 1 &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2676                 :            :                         ('.' == c2 || '$' == c2 || '#' == c2 ||
    2677                 :            :                          ('0' <= c2 && c2 <= '9')))
    2678                 :          0 :                     return false;   // :#REF!.AB42 or :#REF!42 or :#REF!#REF!
    2679                 :          0 :                 break;
    2680                 :            :             default:
    2681 [ #  # ][ #  # ]:          0 :                 if (comphelper::string::isalphaAscii(c) &&
         [ #  # ][ #  # ]
                 [ #  # ]
    2682                 :            :                         ((mnPredetectedReference > 1 && ':' == c2) || 0 == c2))
    2683                 :          0 :                     return false;   // AB#REF!: or AB#REF!
    2684                 :            :         }
    2685                 :            :     }
    2686      [ +  +  - ]:        417 :     switch (mnPredetectedReference)
    2687                 :            :     {
    2688                 :            :         case 1:
    2689                 :        291 :             return IsSingleReference( rName);
    2690                 :            :         case 2:
    2691                 :        126 :             return IsDoubleReference( rName);
    2692                 :            :     }
    2693                 :        417 :     return false;
    2694                 :            : }
    2695                 :            : 
    2696                 :            : 
    2697                 :       1794 : bool ScCompiler::IsDoubleReference( const String& rName )
    2698                 :            : {
    2699                 :       1794 :     ScRange aRange( aPos, aPos );
    2700         [ +  - ]:       1794 :     const ScAddress::Details aDetails( pConv->meConv, aPos );
    2701                 :       1794 :     ScAddress::ExternalInfo aExtInfo;
    2702         [ +  - ]:       1794 :     sal_uInt16 nFlags = aRange.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
    2703         [ +  - ]:       1794 :     if( nFlags & SCA_VALID )
    2704                 :            :     {
    2705                 :       1794 :         ScRawToken aToken;
    2706                 :            :         ScComplexRefData aRef;
    2707                 :       1794 :         aRef.InitRange( aRange );
    2708                 :       1794 :         aRef.Ref1.SetColRel( (nFlags & SCA_COL_ABSOLUTE) == 0 );
    2709                 :       1794 :         aRef.Ref1.SetRowRel( (nFlags & SCA_ROW_ABSOLUTE) == 0 );
    2710                 :       1794 :         aRef.Ref1.SetTabRel( (nFlags & SCA_TAB_ABSOLUTE) == 0 );
    2711         [ -  + ]:       1794 :         if ( !(nFlags & SCA_VALID_TAB) )
    2712                 :          0 :             aRef.Ref1.SetTabDeleted( true );        // #REF!
    2713                 :       1794 :         aRef.Ref1.SetFlag3D( ( nFlags & SCA_TAB_3D ) != 0 );
    2714                 :       1794 :         aRef.Ref2.SetColRel( (nFlags & SCA_COL2_ABSOLUTE) == 0 );
    2715                 :       1794 :         aRef.Ref2.SetRowRel( (nFlags & SCA_ROW2_ABSOLUTE) == 0 );
    2716                 :       1794 :         aRef.Ref2.SetTabRel( (nFlags & SCA_TAB2_ABSOLUTE) == 0 );
    2717         [ -  + ]:       1794 :         if ( !(nFlags & SCA_VALID_TAB2) )
    2718                 :          0 :             aRef.Ref2.SetTabDeleted( true );        // #REF!
    2719                 :       1794 :         aRef.Ref2.SetFlag3D( ( nFlags & SCA_TAB2_3D ) != 0 );
    2720         [ +  - ]:       1794 :         aRef.CalcRelFromAbs( aPos );
    2721         [ +  + ]:       1794 :         if (aExtInfo.mbExternal)
    2722                 :            :         {
    2723         [ +  - ]:         18 :             ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
    2724         [ +  - ]:         18 :             const OUString* pRealTab = pRefMgr->getRealTableName(aExtInfo.mnFileId, aExtInfo.maTabName);
    2725                 :            :             aToken.SetExternalDoubleRef(
    2726 [ -  + ][ +  - ]:         18 :                 aExtInfo.mnFileId, pRealTab ? *pRealTab : aExtInfo.maTabName, aRef);
         [ +  - ][ +  - ]
    2727                 :            :         }
    2728                 :            :         else
    2729                 :            :         {
    2730         [ +  - ]:       1776 :             aToken.SetDoubleReference(aRef);
    2731                 :            :         }
    2732 [ +  - ][ +  - ]:       1794 :         pRawToken = aToken.Clone();
    2733                 :            :     }
    2734                 :            : 
    2735                 :       1794 :     return ( nFlags & SCA_VALID ) != 0;
    2736                 :            : }
    2737                 :            : 
    2738                 :            : 
    2739                 :       3576 : bool ScCompiler::IsSingleReference( const String& rName )
    2740                 :            : {
    2741                 :       3576 :     ScAddress aAddr( aPos );
    2742         [ +  - ]:       3576 :     const ScAddress::Details aDetails( pConv->meConv, aPos );
    2743                 :       3576 :     ScAddress::ExternalInfo aExtInfo;
    2744         [ +  - ]:       3576 :     sal_uInt16 nFlags = aAddr.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
    2745                 :            :     // Something must be valid in order to recognize Sheet1.blah or blah.a1
    2746                 :            :     // as a (wrong) reference.
    2747         [ +  + ]:       3576 :     if( nFlags & ( SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB ) )
    2748                 :            :     {
    2749                 :       1759 :         ScRawToken aToken;
    2750                 :            :         ScSingleRefData aRef;
    2751                 :       1759 :         aRef.InitAddress( aAddr );
    2752                 :       1759 :         aRef.SetColRel( (nFlags & SCA_COL_ABSOLUTE) == 0 );
    2753                 :       1759 :         aRef.SetRowRel( (nFlags & SCA_ROW_ABSOLUTE) == 0 );
    2754                 :       1759 :         aRef.SetTabRel( (nFlags & SCA_TAB_ABSOLUTE) == 0 );
    2755                 :       1759 :         aRef.SetFlag3D( ( nFlags & SCA_TAB_3D ) != 0 );
    2756                 :            :         // the reference is really invalid
    2757         [ -  + ]:       1759 :         if( !( nFlags & SCA_VALID ) )
    2758                 :            :         {
    2759         [ #  # ]:          0 :             if( !( nFlags & SCA_VALID_COL ) )
    2760                 :          0 :                 aRef.nCol = MAXCOL+1;
    2761         [ #  # ]:          0 :             if( !( nFlags & SCA_VALID_ROW ) )
    2762                 :          0 :                 aRef.nRow = MAXROW+1;
    2763         [ #  # ]:          0 :             if( !( nFlags & SCA_VALID_TAB ) )
    2764                 :          0 :                 aRef.nTab = MAXTAB+3;
    2765                 :          0 :             nFlags |= SCA_VALID;
    2766                 :            :         }
    2767         [ +  - ]:       1759 :         aRef.CalcRelFromAbs( aPos );
    2768                 :            : 
    2769         [ +  + ]:       1759 :         if (aExtInfo.mbExternal)
    2770                 :            :         {
    2771         [ +  - ]:         69 :             ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
    2772         [ +  - ]:         69 :             const OUString* pRealTab = pRefMgr->getRealTableName(aExtInfo.mnFileId, aExtInfo.maTabName);
    2773                 :            :             aToken.SetExternalSingleRef(
    2774 [ -  + ][ +  - ]:         69 :                 aExtInfo.mnFileId, pRealTab ? *pRealTab : aExtInfo.maTabName, aRef);
         [ +  - ][ +  - ]
    2775                 :            :         }
    2776                 :            :         else
    2777         [ +  - ]:       1690 :             aToken.SetSingleReference(aRef);
    2778 [ +  - ][ +  - ]:       1759 :         pRawToken = aToken.Clone();
    2779                 :            :     }
    2780                 :            : 
    2781                 :       3576 :     return ( nFlags & SCA_VALID ) != 0;
    2782                 :            : }
    2783                 :            : 
    2784                 :            : 
    2785                 :       4569 : bool ScCompiler::IsReference( const String& rName )
    2786                 :            : {
    2787                 :            :     // Has to be called before IsValue
    2788                 :       4569 :     sal_Unicode ch1 = rName.GetChar(0);
    2789                 :       4569 :     sal_Unicode cDecSep = ( mxSymbols->isEnglish() ? '.' :
    2790         [ +  + ]:       4569 :         ScGlobal::pLocaleData->getNumDecimalSep()[0] );
    2791         [ -  + ]:       4569 :     if ( ch1 == cDecSep )
    2792                 :          0 :         return false;
    2793                 :            :     // Who was that imbecile introducing '.' as the sheet name separator!?!
    2794 [ +  - ][ +  - ]:       4569 :     if ( CharClass::isAsciiNumeric( rtl::OUString(ch1) ) )
         [ +  - ][ +  + ]
    2795                 :            :     {
    2796                 :            :         // Numerical sheet name is valid.
    2797                 :            :         // But English 1.E2 or 1.E+2 is value 100, 1.E-2 is 0.01
    2798                 :            :         // Don't create a #REF! of values. But also do not bail out on
    2799                 :            :         // something like 3:3, meaning entire row 3.
    2800                 :            :         do
    2801                 :            :         {
    2802                 :       1284 :             const xub_StrLen nPos = ScGlobal::FindUnquoted( rName, '.');
    2803         [ +  + ]:       1284 :             if ( nPos == STRING_NOTFOUND )
    2804                 :            :             {
    2805         [ -  + ]:       1242 :                 if (ScGlobal::FindUnquoted( rName, ':') != STRING_NOTFOUND)
    2806                 :          0 :                     break;      // may be 3:3, continue as usual
    2807                 :       1242 :                 return false;
    2808                 :            :             }
    2809                 :         42 :             sal_Unicode const * const pTabSep = rName.GetBuffer() + nPos;
    2810                 :         42 :             sal_Unicode ch2 = pTabSep[1];   // maybe a column identifier
    2811 [ +  - ][ +  - ]:         42 :             if ( !(ch2 == '$' || CharClass::isAsciiAlpha( ch2 )) )
                 [ +  - ]
    2812                 :         42 :                 return false;
    2813 [ #  # ][ #  # ]:          0 :             if ( cDecSep == '.' && (ch2 == 'E' || ch2 == 'e')   // E + - digit
           [ #  #  #  # ]
                 [ #  # ]
    2814                 :          0 :                     && (GetCharTableFlags( pTabSep[2], pTabSep[1] ) & SC_COMPILER_C_VALUE_EXP) )
    2815                 :            :             {   // #91053#
    2816                 :            :                 // If it is an 1.E2 expression check if "1" is an existent sheet
    2817                 :            :                 // name. If so, a desired value 1.E2 would have to be entered as
    2818                 :            :                 // 1E2 or 1.0E2 or 1.E+2, sorry. Another possibility would be to
    2819                 :            :                 // require numerical sheet names always being entered quoted, which
    2820                 :            :                 // is not desirable (too many 1999, 2000, 2001 sheets in use).
    2821                 :            :                 // Furthermore, XML files created with versions prior to SRC640e
    2822                 :            :                 // wouldn't contain the quotes added by MakeTabStr()/CheckTabQuotes()
    2823                 :            :                 // and would produce wrong formulas if the conditions here are met.
    2824                 :            :                 // If you can live with these restrictions you may remove the
    2825                 :            :                 // check and return an unconditional FALSE.
    2826         [ #  # ]:          0 :                 String aTabName( rName.Copy( 0, nPos ) );
    2827                 :            :                 SCTAB nTab;
    2828 [ #  # ][ #  # ]:          0 :                 if ( !pDoc->GetTable( aTabName, nTab ) )
                 [ #  # ]
    2829 [ #  # ][ #  # ]:          0 :                     return false;
    2830                 :            :                 // If sheet "1" exists and the expression is 1.E+2 continue as
    2831                 :            :                 // usual, the ScRange/ScAddress parser will take care of it.
    2832                 :            :             }
    2833                 :            :         } while(0);
    2834                 :            :     }
    2835                 :            : 
    2836         [ +  + ]:       3285 :     if (IsSingleReference( rName))
    2837                 :       1468 :         return true;
    2838                 :            : 
    2839                 :            :     // Though the range operator is handled explicitly, when encountering
    2840                 :            :     // something like Sheet1.A:A we will have to treat it as one entity if it
    2841                 :            :     // doesn't pass as single cell reference.
    2842         [ +  + ]:       1817 :     if (mnRangeOpPosInSymbol > 0)   // ":foo" would be nonsense
    2843                 :            :     {
    2844         [ +  - ]:       1668 :         if (IsDoubleReference( rName))
    2845                 :       1668 :             return true;
    2846                 :            :         // Now try with a symbol up to the range operator, rewind source
    2847                 :            :         // position.
    2848                 :          0 :         sal_Int32 nLen = mnRangeOpPosInSymbol;
    2849         [ #  # ]:          0 :         while (cSymbol[++nLen])
    2850                 :            :             ;
    2851                 :          0 :         cSymbol[mnRangeOpPosInSymbol] = 0;
    2852                 :          0 :         nSrcPos -= static_cast<xub_StrLen>(nLen - mnRangeOpPosInSymbol);
    2853                 :          0 :         mnRangeOpPosInSymbol = -1;
    2854                 :          0 :         mbRewind = true;
    2855                 :          0 :         return true;    // end all checks
    2856                 :            :     }
    2857                 :            :     else
    2858                 :            :     {
    2859                 :            :         // Special treatment for the 'E:\[doc]Sheet1:Sheet3'!D5 Excel sickness,
    2860                 :            :         // mnRangeOpPosInSymbol did not catch the range operator as it is
    2861                 :            :         // within a quoted name.
    2862         [ +  + ]:        149 :         switch (pConv->meConv)
    2863                 :            :         {
    2864                 :            :             case FormulaGrammar::CONV_XL_A1:
    2865                 :            :             case FormulaGrammar::CONV_XL_R1C1:
    2866                 :            :             case FormulaGrammar::CONV_XL_OOX:
    2867 [ -  + ][ #  # ]:         39 :                 if (rName.GetChar(0) == '\'' && IsDoubleReference( rName))
                 [ -  + ]
    2868                 :          0 :                     return true;
    2869                 :         39 :                 break;
    2870                 :            :             default:
    2871                 :            :                 ;   // nothing
    2872                 :            :         }
    2873                 :            :     }
    2874                 :       4569 :     return false;
    2875                 :            : }
    2876                 :            : 
    2877                 :          3 : bool ScCompiler::IsMacro( const String& rName )
    2878                 :            : {
    2879                 :            : #ifdef DISABLE_SCRIPTING
    2880                 :            :     (void) rName;
    2881                 :            : 
    2882                 :            :     return false;
    2883                 :            : #else
    2884         [ +  - ]:          3 :     String aName( rName);
    2885                 :          3 :     StarBASIC* pObj = 0;
    2886                 :          3 :     SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
    2887                 :            : 
    2888         [ +  - ]:          3 :     SfxApplication* pSfxApp = SFX_APP();
    2889                 :            : 
    2890         [ +  - ]:          3 :     if( pDocSh )//XXX
    2891         [ +  - ]:          3 :         pObj = pDocSh->GetBasic();
    2892                 :            :     else
    2893         [ #  # ]:          0 :         pObj = pSfxApp->GetBasic();
    2894                 :            : 
    2895                 :            :     // ODFF recommends to store user-defined functions prefixed with "USER.",
    2896                 :            :     // use only unprefixed name if encountered. BASIC doesn't allow '.' in a
    2897                 :            :     // function name so a function "USER.FOO" could not exist, and macro check
    2898                 :            :     // is assigned the lowest priority in function name check.
    2899 [ -  + ][ #  # ]:          3 :     if (FormulaGrammar::isODFF( GetGrammar()) && aName.EqualsIgnoreCaseAscii( "USER.", 0, 5))
         [ #  # ][ -  + ]
    2900         [ #  # ]:          0 :         aName.Erase( 0, 5);
    2901                 :            : 
    2902 [ +  - ][ +  - ]:          3 :     SbxMethod* pMeth = (SbxMethod*) pObj->Find( aName, SbxCLASS_METHOD );
    2903         [ +  - ]:          3 :     if( !pMeth )
    2904                 :            :     {
    2905                 :          3 :         return false;
    2906                 :            :     }
    2907                 :            :     // It really should be a BASIC function!
    2908 [ #  # ][ #  # ]:          0 :     if( pMeth->GetType() == SbxVOID
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2909 [ #  # ][ #  # ]:          0 :      || ( pMeth->IsFixed() && pMeth->GetType() == SbxEMPTY )
    2910 [ #  # ][ #  # ]:          0 :      || !pMeth->ISA(SbMethod) )
    2911                 :            :     {
    2912                 :          0 :         return false;
    2913                 :            :     }
    2914                 :          0 :     ScRawToken aToken;
    2915         [ #  # ]:          0 :     aToken.SetExternal( aName.GetBuffer() );
    2916                 :          0 :     aToken.eOp = ocMacro;
    2917 [ #  # ][ #  # ]:          0 :     pRawToken = aToken.Clone();
    2918         [ +  - ]:          3 :     return true;
    2919                 :            : #endif
    2920                 :            : }
    2921                 :            : 
    2922                 :        149 : bool ScCompiler::IsNamedRange( const String& rUpperName )
    2923                 :            : {
    2924                 :            :     // IsNamedRange is called only from NextNewToken, with an upper-case string
    2925                 :            : 
    2926                 :            :     // try local names first
    2927                 :        149 :     bool bGlobal = false;
    2928                 :        149 :     ScRangeName* pRangeName = pDoc->GetRangeName(aPos.Tab());
    2929                 :        149 :     const ScRangeData* pData = NULL;
    2930         [ +  + ]:        149 :     if (pRangeName)
    2931         [ +  - ]:        146 :         pData = pRangeName->findByUpperName(rUpperName);
    2932         [ +  + ]:        149 :     if (!pData)
    2933                 :            :     {
    2934                 :        104 :         pRangeName = pDoc->GetRangeName();
    2935         [ +  - ]:        104 :         if (pRangeName)
    2936         [ +  - ]:        104 :             pData = pRangeName->findByUpperName(rUpperName);
    2937         [ +  + ]:        104 :         if (pData)
    2938                 :         71 :             bGlobal = true;
    2939                 :            :     }
    2940                 :            : 
    2941         [ +  + ]:        149 :     if (pData)
    2942                 :            :     {
    2943                 :        116 :         ScRawToken aToken;
    2944         [ +  - ]:        116 :         aToken.SetName(bGlobal, pData->GetIndex());
    2945 [ +  - ][ +  - ]:        116 :         pRawToken = aToken.Clone();
    2946                 :        116 :         return true;
    2947                 :            :     }
    2948                 :            :     else
    2949                 :        149 :         return false;
    2950                 :            : }
    2951                 :            : 
    2952                 :         33 : bool ScCompiler::IsExternalNamedRange( const String& rSymbol )
    2953                 :            : {
    2954                 :            :     /* FIXME: This code currently (2008-12-02T15:41+0100 in CWS mooxlsc)
    2955                 :            :      * correctly parses external named references in OOo, as required per RFE
    2956                 :            :      * #i3740#, just that we can't store them in ODF yet. We will need an OASIS
    2957                 :            :      * spec first. Until then don't pretend to support external names that
    2958                 :            :      * wouldn't survive a save and reload cycle, return false instead. */
    2959                 :            : 
    2960         [ -  + ]:         33 :     if (!pConv)
    2961                 :          0 :         return false;
    2962                 :            : 
    2963 [ +  - ][ +  - ]:         33 :     String aFile, aName;
    2964 [ +  - ][ +  - ]:         33 :     if (!pConv->parseExternalName( rSymbol, aFile, aName, pDoc, &maExternalLinks))
    2965                 :         33 :         return false;
    2966                 :            : 
    2967                 :          0 :     ScRawToken aToken;
    2968 [ #  # ][ #  # ]:          0 :     if (aFile.Len() > MAXSTRLEN || aName.Len() > MAXSTRLEN)
                 [ #  # ]
    2969                 :          0 :         return false;
    2970                 :            : 
    2971         [ #  # ]:          0 :     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
    2972         [ #  # ]:          0 :     OUString aTmp = aFile;
    2973         [ #  # ]:          0 :     pRefMgr->convertToAbsName(aTmp);
    2974         [ #  # ]:          0 :     aFile = aTmp;
    2975 [ #  # ][ #  # ]:          0 :     sal_uInt16 nFileId = pRefMgr->getExternalFileId(aFile);
    2976 [ #  # ][ #  # ]:          0 :     if (!pRefMgr->getRangeNameTokens(nFileId, aName).get())
         [ #  # ][ #  # ]
    2977                 :            :         // range name doesn't exist in the source document.
    2978                 :          0 :         return false;
    2979                 :            : 
    2980 [ #  # ][ #  # ]:          0 :     const OUString* pRealName = pRefMgr->getRealRangeName(nFileId, aName);
    2981 [ #  # ][ #  # ]:          0 :     aToken.SetExternalName(nFileId, pRealName ? *pRealName : OUString(aTmp));
         [ #  # ][ #  # ]
    2982 [ #  # ][ #  # ]:          0 :     pRawToken = aToken.Clone();
    2983 [ +  - ][ +  - ]:         33 :     return true;
    2984                 :            : }
    2985                 :            : 
    2986                 :         33 : bool ScCompiler::IsDBRange( const String& rName )
    2987                 :            : {
    2988 [ +  - ][ -  + ]:         33 :     if (rName.EqualsAscii("[]"))
    2989                 :            :     {
    2990 [ #  # ][ #  # ]:          0 :         if (pRawToken && pRawToken->GetOpCode() == ocDBArea)
                 [ #  # ]
    2991                 :            :         {
    2992                 :            :             // In OOXML, a database range is named Table1[], Table2[] etc.
    2993                 :            :             // Skip the [] part if the previous token is a valid db range.
    2994                 :          0 :             ScRawToken aToken;
    2995                 :          0 :             aToken.eOp = ocSkip;
    2996 [ #  # ][ #  # ]:          0 :             pRawToken = aToken.Clone();
    2997                 :          0 :             return true;
    2998                 :            :         }
    2999                 :            :     }
    3000 [ +  - ][ +  - ]:         33 :     ScDBCollection::NamedDBs& rDBs = pDoc->GetDBCollection()->getNamedDBs();
    3001 [ +  - ][ +  - ]:         33 :     const ScDBData* p = rDBs.findByUpperName(rName);
    3002         [ +  + ]:         33 :     if (!p)
    3003                 :         27 :         return false;
    3004                 :            : 
    3005                 :          6 :     ScRawToken aToken;
    3006         [ +  - ]:          6 :     aToken.SetName(true, p->GetIndex()); // DB range is always global.
    3007                 :          6 :     aToken.eOp = ocDBArea;
    3008 [ +  - ][ +  - ]:          6 :     pRawToken = aToken.Clone();
    3009                 :         33 :     return true;
    3010                 :            : }
    3011                 :            : 
    3012                 :         27 : bool ScCompiler::IsColRowName( const String& rName )
    3013                 :            : {
    3014                 :         27 :     bool bInList = false;
    3015                 :         27 :     bool bFound = false;
    3016                 :            :     ScSingleRefData aRef;
    3017         [ +  - ]:         27 :     String aName( rName );
    3018         [ +  - ]:         27 :     DeQuote( aName );
    3019                 :         27 :     SCTAB nThisTab = aPos.Tab();
    3020 [ +  + ][ +  - ]:         81 :     for ( short jThisTab = 1; jThisTab >= 0 && !bInList; jThisTab-- )
                 [ +  + ]
    3021                 :            :     {   // first check ranges on this sheet, in case of duplicated names
    3022 [ +  + ][ +  - ]:        162 :         for ( short jRow=0; jRow<2 && !bInList; jRow++ )
                 [ +  + ]
    3023                 :            :         {
    3024                 :            :             ScRangePairList* pRL;
    3025         [ +  + ]:        108 :             if ( !jRow )
    3026                 :         54 :                 pRL = pDoc->GetColNameRanges();
    3027                 :            :             else
    3028                 :         54 :                 pRL = pDoc->GetRowNameRanges();
    3029 [ +  - ][ -  + ]:        108 :             for ( size_t iPair = 0, nPairs = pRL->size(); iPair < nPairs && !bInList; ++iPair )
         [ #  # ][ -  + ]
    3030                 :            :             {
    3031         [ #  # ]:          0 :                 ScRangePair* pR = (*pRL)[iPair];
    3032                 :          0 :                 const ScRange& rNameRange = pR->GetRange(0);
    3033 [ #  # ][ #  # ]:          0 :                 if ( jThisTab && !(rNameRange.aStart.Tab() <= nThisTab &&
                 [ #  # ]
    3034         [ #  # ]:          0 :                         nThisTab <= rNameRange.aEnd.Tab()) )
    3035                 :          0 :                     continue;   // for
    3036         [ #  # ]:          0 :                 ScCellIterator aIter( pDoc, rNameRange );
    3037 [ #  # ][ #  # ]:          0 :                 for ( ScBaseCell* pCell = aIter.GetFirst(); pCell && !bInList;
         [ #  # ][ #  # ]
                 [ #  # ]
    3038                 :            :                         pCell = aIter.GetNext() )
    3039                 :            :                 {
    3040                 :            :                     // Don't crash if cell (via CompileNameFormula) encounters
    3041                 :            :                     // a formula cell without code and
    3042                 :            :                     // HasStringData/Interpret/Compile is executed and all that
    3043                 :            :                     // recursive..
    3044                 :            :                     // Furthermore, *this* cell won't be touched, since no RPN exists yet.
    3045                 :          0 :                     CellType eType = pCell->GetCellType();
    3046                 :            :                     bool bOk = ( (eType == CELLTYPE_FORMULA ?
    3047         [ #  # ]:          0 :                         ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen() > 0
    3048         [ #  # ]:          0 :                         && ((ScFormulaCell*)pCell)->aPos != aPos    // noIter
    3049   [ #  #  #  #  :          0 :                         : true ) );
                   #  # ]
    3050 [ #  # ][ #  # ]:          0 :                     if ( bOk && pCell->HasStringData() )
         [ #  # ][ #  # ]
    3051                 :            :                     {
    3052         [ #  # ]:          0 :                         String aStr;
    3053   [ #  #  #  #  :          0 :                         switch ( eType )
                      # ]
    3054                 :            :                         {
    3055                 :            :                             case CELLTYPE_STRING:
    3056         [ #  # ]:          0 :                                 aStr = ((ScStringCell*)pCell)->GetString();
    3057                 :          0 :                             break;
    3058                 :            :                             case CELLTYPE_FORMULA:
    3059 [ #  # ][ #  # ]:          0 :                                 aStr = ((ScFormulaCell*)pCell)->GetString();
                 [ #  # ]
    3060                 :          0 :                             break;
    3061                 :            :                             case CELLTYPE_EDIT:
    3062 [ #  # ][ #  # ]:          0 :                                 aStr = ((ScEditCell*)pCell)->GetString();
    3063                 :          0 :                             break;
    3064                 :            :                             case CELLTYPE_NONE:
    3065                 :            :                             case CELLTYPE_VALUE:
    3066                 :            :                             case CELLTYPE_NOTE:
    3067                 :            :                             case CELLTYPE_SYMBOLS:
    3068                 :            : #if OSL_DEBUG_LEVEL > 0
    3069                 :            :                             case CELLTYPE_DESTROYED:
    3070                 :            : #endif
    3071                 :            :                                 ;   // nothing, prevent compiler warning
    3072                 :          0 :                             break;
    3073                 :            :                         }
    3074 [ #  # ][ #  # ]:          0 :                         if ( ScGlobal::GetpTransliteration()->isEqual( aStr, aName ) )
                 [ #  # ]
    3075                 :            :                         {
    3076                 :          0 :                             aRef.InitFlags();
    3077                 :          0 :                             aRef.nCol = aIter.GetCol();
    3078                 :          0 :                             aRef.nRow = aIter.GetRow();
    3079                 :          0 :                             aRef.nTab = aIter.GetTab();
    3080         [ #  # ]:          0 :                             if ( !jRow )
    3081                 :          0 :                                 aRef.SetColRel( true );     // ColName
    3082                 :            :                             else
    3083                 :          0 :                                 aRef.SetRowRel( true );     // RowName
    3084         [ #  # ]:          0 :                             aRef.CalcRelFromAbs( aPos );
    3085                 :          0 :                             bInList = bFound = true;
    3086         [ #  # ]:          0 :                         }
    3087                 :            :                     }
    3088                 :            :                 }
    3089                 :            :             }
    3090                 :            :         }
    3091                 :            :     }
    3092 [ +  - ][ +  - ]:         27 :     if ( !bInList && pDoc->GetDocOptions().IsLookUpColRowNames() )
         [ +  + ][ +  + ]
    3093                 :            :     {   // search in current sheet
    3094                 :         18 :         long nDistance = 0, nMax = 0;
    3095                 :         18 :         long nMyCol = (long) aPos.Col();
    3096                 :         18 :         long nMyRow = (long) aPos.Row();
    3097                 :         18 :         bool bTwo = false;
    3098                 :         18 :         ScAddress aOne( 0, 0, aPos.Tab() );
    3099                 :         18 :         ScAddress aTwo( MAXCOL, MAXROW, aPos.Tab() );
    3100                 :            : 
    3101                 :         18 :         ScAutoNameCache* pNameCache = pDoc->GetAutoNameCache();
    3102         [ +  + ]:         18 :         if ( pNameCache )
    3103                 :            :         {
    3104                 :            :             //  use GetNameOccurrences to collect all positions of aName on the sheet
    3105                 :            :             //  (only once), similar to the outer part of the loop in the "else" branch.
    3106                 :            : 
    3107         [ +  - ]:         12 :             const ScAutoNameAddresses& rAddresses = pNameCache->GetNameOccurrences( aName, aPos.Tab() );
    3108                 :            : 
    3109                 :            :             //  Loop through the found positions, similar to the inner part of the loop in the "else" branch.
    3110                 :            :             //  The order of addresses in the vector is the same as from ScCellIterator.
    3111                 :            : 
    3112                 :         12 :             ScAutoNameAddresses::const_iterator aEnd(rAddresses.end());
    3113 [ +  - ][ -  + ]:         12 :             for ( ScAutoNameAddresses::const_iterator aAdrIter(rAddresses.begin()); aAdrIter != aEnd; ++aAdrIter )
    3114                 :            :             {
    3115                 :          0 :                 ScAddress aAddress( *aAdrIter );        // cell address with an equal string
    3116                 :            : 
    3117         [ #  # ]:          0 :                 if ( bFound )
    3118                 :            :                 {   // stop if everything else is further away
    3119         [ #  # ]:          0 :                     if ( nMax < (long)aAddress.Col() )
    3120                 :            :                         break;      // aIter
    3121                 :            :                 }
    3122         [ #  # ]:          0 :                 if ( aAddress != aPos )
    3123                 :            :                 {
    3124                 :            :                     // same treatment as in isEqual case below
    3125                 :            : 
    3126                 :          0 :                     SCCOL nCol = aAddress.Col();
    3127                 :          0 :                     SCROW nRow = aAddress.Row();
    3128                 :          0 :                     long nC = nMyCol - nCol;
    3129                 :          0 :                     long nR = nMyRow - nRow;
    3130         [ #  # ]:          0 :                     if ( bFound )
    3131                 :            :                     {
    3132                 :          0 :                         long nD = nC * nC + nR * nR;
    3133         [ #  # ]:          0 :                         if ( nD < nDistance )
    3134                 :            :                         {
    3135 [ #  # ][ #  # ]:          0 :                             if ( nC < 0 || nR < 0 )
    3136                 :            :                             {   // right or below
    3137                 :          0 :                                 bTwo = true;
    3138                 :          0 :                                 aTwo.Set( nCol, nRow, aAddress.Tab() );
    3139                 :          0 :                                 nMax = Max( nMyCol + Abs( nC ), nMyRow + Abs( nR ) );
    3140                 :          0 :                                 nDistance = nD;
    3141                 :            :                             }
    3142 [ #  # ][ #  # ]:          0 :                             else if ( !(nRow < aOne.Row() && nMyRow >= (long)aOne.Row()) )
                 [ #  # ]
    3143                 :            :                             {
    3144                 :            :                                 // upper left, only if not further up than the
    3145                 :            :                                 // current entry and nMyRow is below (CellIter
    3146                 :            :                                 // runs column-wise)
    3147                 :          0 :                                 bTwo = false;
    3148                 :          0 :                                 aOne.Set( nCol, nRow, aAddress.Tab() );
    3149                 :          0 :                                 nMax = Max( nMyCol + nC, nMyRow + nR );
    3150                 :          0 :                                 nDistance = nD;
    3151                 :            :                             }
    3152                 :            :                         }
    3153                 :            :                     }
    3154                 :            :                     else
    3155                 :            :                     {
    3156                 :          0 :                         aOne.Set( nCol, nRow, aAddress.Tab() );
    3157                 :          0 :                         nDistance = nC * nC + nR * nR;
    3158                 :          0 :                         nMax = Max( nMyCol + Abs( nC ), nMyRow + Abs( nR ) );
    3159                 :            :                     }
    3160                 :          0 :                     bFound = true;
    3161                 :            :                 }
    3162                 :            :             }
    3163                 :            :         }
    3164                 :            :         else
    3165                 :            :         {
    3166         [ +  - ]:          6 :             ScCellIterator aIter( pDoc, ScRange( aOne, aTwo ) );
    3167 [ +  - ][ +  - ]:         39 :             for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
                 [ +  + ]
    3168                 :            :             {
    3169         [ -  + ]:         33 :                 if ( bFound )
    3170                 :            :                 {   // stop if everything else is further away
    3171         [ #  # ]:          0 :                     if ( nMax < (long)aIter.GetCol() )
    3172                 :          0 :                         break;      // aIter
    3173                 :            :                 }
    3174                 :         33 :                 CellType eType = pCell->GetCellType();
    3175                 :            :                 bool bOk = ( (eType == CELLTYPE_FORMULA ?
    3176         [ +  - ]:         27 :                     ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen() > 0
    3177         [ +  - ]:         15 :                     && ((ScFormulaCell*)pCell)->aPos != aPos    // noIter
    3178   [ +  +  +  +  :         75 :                     : true ) );
                   +  + ]
    3179 [ +  + ][ +  - ]:         33 :                 if ( bOk && pCell->HasStringData() )
         [ -  + ][ -  + ]
    3180                 :            :                 {
    3181         [ #  # ]:          0 :                     String aStr;
    3182   [ #  #  #  #  :          0 :                     switch ( eType )
                      # ]
    3183                 :            :                     {
    3184                 :            :                         case CELLTYPE_STRING:
    3185         [ #  # ]:          0 :                             aStr = ((ScStringCell*)pCell)->GetString();
    3186                 :          0 :                         break;
    3187                 :            :                         case CELLTYPE_FORMULA:
    3188 [ #  # ][ #  # ]:          0 :                             aStr = ((ScFormulaCell*)pCell)->GetString();
                 [ #  # ]
    3189                 :          0 :                         break;
    3190                 :            :                         case CELLTYPE_EDIT:
    3191 [ #  # ][ #  # ]:          0 :                             aStr = ((ScEditCell*)pCell)->GetString();
    3192                 :          0 :                         break;
    3193                 :            :                         case CELLTYPE_NONE:
    3194                 :            :                         case CELLTYPE_VALUE:
    3195                 :            :                         case CELLTYPE_NOTE:
    3196                 :            :                         case CELLTYPE_SYMBOLS:
    3197                 :            : #if OSL_DEBUG_LEVEL > 0
    3198                 :            :                         case CELLTYPE_DESTROYED:
    3199                 :            : #endif
    3200                 :            :                             ;   // nothing, prevent compiler warning
    3201                 :          0 :                         break;
    3202                 :            :                     }
    3203 [ #  # ][ #  # ]:          0 :                     if ( ScGlobal::GetpTransliteration()->isEqual( aStr, aName ) )
                 [ #  # ]
    3204                 :            :                     {
    3205                 :          0 :                         SCCOL nCol = aIter.GetCol();
    3206                 :          0 :                         SCROW nRow = aIter.GetRow();
    3207                 :          0 :                         long nC = nMyCol - nCol;
    3208                 :          0 :                         long nR = nMyRow - nRow;
    3209         [ #  # ]:          0 :                         if ( bFound )
    3210                 :            :                         {
    3211                 :          0 :                             long nD = nC * nC + nR * nR;
    3212         [ #  # ]:          0 :                             if ( nD < nDistance )
    3213                 :            :                             {
    3214 [ #  # ][ #  # ]:          0 :                                 if ( nC < 0 || nR < 0 )
    3215                 :            :                                 {   // right or below
    3216                 :          0 :                                     bTwo = true;
    3217                 :          0 :                                     aTwo.Set( nCol, nRow, aIter.GetTab() );
    3218                 :          0 :                                     nMax = Max( nMyCol + Abs( nC ), nMyRow + Abs( nR ) );
    3219                 :          0 :                                     nDistance = nD;
    3220                 :            :                                 }
    3221 [ #  # ][ #  # ]:          0 :                                 else if ( !(nRow < aOne.Row() && nMyRow >= (long)aOne.Row()) )
                 [ #  # ]
    3222                 :            :                                 {
    3223                 :            :                                     // upper left, only if not further up than the
    3224                 :            :                                     // current entry and nMyRow is below (CellIter
    3225                 :            :                                     // runs column-wise)
    3226                 :          0 :                                     bTwo = false;
    3227                 :          0 :                                     aOne.Set( nCol, nRow, aIter.GetTab() );
    3228                 :          0 :                                     nMax = Max( nMyCol + nC, nMyRow + nR );
    3229                 :          0 :                                     nDistance = nD;
    3230                 :            :                                 }
    3231                 :            :                             }
    3232                 :            :                         }
    3233                 :            :                         else
    3234                 :            :                         {
    3235                 :          0 :                             aOne.Set( nCol, nRow, aIter.GetTab() );
    3236                 :          0 :                             nDistance = nC * nC + nR * nR;
    3237                 :          0 :                             nMax = Max( nMyCol + Abs( nC ), nMyRow + Abs( nR ) );
    3238                 :            :                         }
    3239                 :          0 :                         bFound = true;
    3240         [ #  # ]:          0 :                     }
    3241                 :            :                 }
    3242                 :            :             }
    3243                 :            :         }
    3244                 :            : 
    3245         [ -  + ]:         18 :         if ( bFound )
    3246                 :            :         {
    3247                 :          0 :             ScAddress aAdr;
    3248         [ #  # ]:          0 :             if ( bTwo )
    3249                 :            :             {
    3250 [ #  # ][ #  # ]:          0 :                 if ( nMyCol >= (long)aOne.Col() && nMyRow >= (long)aOne.Row() )
                 [ #  # ]
    3251                 :          0 :                     aAdr = aOne;        // upper left takes precedence
    3252                 :            :                 else
    3253                 :            :                 {
    3254         [ #  # ]:          0 :                     if ( nMyCol < (long)aOne.Col() )
    3255                 :            :                     {   // two to the right
    3256         [ #  # ]:          0 :                         if ( nMyRow >= (long)aTwo.Row() )
    3257                 :          0 :                             aAdr = aTwo;        // directly right
    3258                 :            :                         else
    3259                 :          0 :                             aAdr = aOne;
    3260                 :            :                     }
    3261                 :            :                     else
    3262                 :            :                     {   // two below or below and right, take the nearest
    3263                 :          0 :                         long nC1 = nMyCol - aOne.Col();
    3264                 :          0 :                         long nR1 = nMyRow - aOne.Row();
    3265                 :          0 :                         long nC2 = nMyCol - aTwo.Col();
    3266                 :          0 :                         long nR2 = nMyRow - aTwo.Row();
    3267         [ #  # ]:          0 :                         if ( nC1 * nC1 + nR1 * nR1 <= nC2 * nC2 + nR2 * nR2 )
    3268                 :          0 :                             aAdr = aOne;
    3269                 :            :                         else
    3270                 :          0 :                             aAdr = aTwo;
    3271                 :            :                     }
    3272                 :            :                 }
    3273                 :            :             }
    3274                 :            :             else
    3275                 :          0 :                 aAdr = aOne;
    3276                 :          0 :             aRef.InitAddress( aAdr );
    3277 [ #  # ][ #  # ]:          0 :             if ( (aRef.nRow != MAXROW && pDoc->HasStringData(
         [ #  # ][ #  # ]
                 [ #  # ]
    3278         [ #  # ]:          0 :                     aRef.nCol, aRef.nRow + 1, aRef.nTab ))
    3279                 :            :               || (aRef.nRow != 0 && pDoc->HasStringData(
    3280         [ #  # ]:          0 :                     aRef.nCol, aRef.nRow - 1, aRef.nTab )) )
    3281                 :          0 :                 aRef.SetRowRel( true );     // RowName
    3282                 :            :             else
    3283                 :          0 :                 aRef.SetColRel( true );     // ColName
    3284         [ #  # ]:         18 :             aRef.CalcRelFromAbs( aPos );
    3285                 :            :         }
    3286                 :            :     }
    3287         [ -  + ]:         27 :     if ( bFound )
    3288                 :            :     {
    3289                 :          0 :         ScRawToken aToken;
    3290         [ #  # ]:          0 :         aToken.SetSingleReference( aRef );
    3291                 :          0 :         aToken.eOp = ocColRowName;
    3292 [ #  # ][ #  # ]:          0 :         pRawToken = aToken.Clone();
    3293                 :          0 :         return true;
    3294                 :            :     }
    3295                 :            :     else
    3296         [ +  - ]:         27 :         return false;
    3297                 :            : }
    3298                 :            : 
    3299                 :         57 : bool ScCompiler::IsBoolean( const String& rName )
    3300                 :            : {
    3301         [ +  - ]:         57 :     OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap()->find( rName ) );
    3302 [ +  - ][ -  + ]:         57 :     if( iLook != mxSymbols->getHashMap()->end() &&
         [ #  # ][ #  # ]
                 [ +  - ]
           [ -  +  #  # ]
    3303         [ #  # ]:          0 :         ((*iLook).second == ocTrue ||
    3304         [ #  # ]:          0 :          (*iLook).second == ocFalse) )
    3305                 :            :     {
    3306                 :          0 :         ScRawToken aToken;
    3307 [ #  # ][ #  # ]:          0 :         aToken.SetOpCode( (*iLook).second );
    3308 [ #  # ][ #  # ]:          0 :         pRawToken = aToken.Clone();
    3309                 :          0 :         return true;
    3310                 :            :     }
    3311                 :            :     else
    3312                 :         57 :         return false;
    3313                 :            : }
    3314                 :            : 
    3315                 :            : 
    3316                 :          0 : bool ScCompiler::IsErrorConstant( const String& rName )
    3317                 :            : {
    3318                 :          0 :     sal_uInt16 nError = GetErrorConstant( rName);
    3319         [ #  # ]:          0 :     if (nError)
    3320                 :            :     {
    3321                 :          0 :         ScRawToken aToken;
    3322         [ #  # ]:          0 :         aToken.SetErrorConstant( nError);
    3323 [ #  # ][ #  # ]:          0 :         pRawToken = aToken.Clone();
    3324                 :          0 :         return true;
    3325                 :            :     }
    3326                 :            :     else
    3327                 :          0 :         return false;
    3328                 :            : }
    3329                 :            : 
    3330                 :            : //---------------------------------------------------------------------------
    3331                 :            : 
    3332                 :          0 : void ScCompiler::AutoCorrectParsedSymbol()
    3333                 :            : {
    3334                 :          0 :     xub_StrLen nPos = aCorrectedSymbol.Len();
    3335         [ #  # ]:          0 :     if ( nPos )
    3336                 :            :     {
    3337                 :          0 :         nPos--;
    3338                 :          0 :         const sal_Unicode cQuote = '\"';
    3339                 :          0 :         const sal_Unicode cx = 'x';
    3340                 :          0 :         const sal_Unicode cX = 'X';
    3341                 :          0 :         sal_Unicode c1 = aCorrectedSymbol.GetChar( 0 );
    3342                 :          0 :         sal_Unicode c2 = aCorrectedSymbol.GetChar( nPos );
    3343         [ #  # ]:          0 :         sal_Unicode c2p = nPos > 0 ? aCorrectedSymbol.GetChar( nPos-1 ) : 0;
    3344 [ #  # ][ #  # ]:          0 :         if ( c1 == cQuote && c2 != cQuote  )
    3345                 :            :         {   // "...
    3346                 :            :             // What's not a word doesn't belong to it.
    3347                 :            :             // Don't be pedantic: c < 128 should be sufficient here.
    3348         [ #  # ]:          0 :             while ( nPos && ((aCorrectedSymbol.GetChar(nPos) < 128) &&
           [ #  #  #  # ]
                 [ #  # ]
    3349                 :          0 :                     ((GetCharTableFlags(aCorrectedSymbol.GetChar(nPos), aCorrectedSymbol.GetChar(nPos-1)) &
    3350                 :            :                     (SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_DONTCARE)) == 0)) )
    3351                 :          0 :                 nPos--;
    3352         [ #  # ]:          0 :             if ( nPos == MAXSTRLEN - 2 )
    3353                 :          0 :                 aCorrectedSymbol.SetChar( nPos, cQuote );   // '"' the 255th character
    3354                 :            :             else
    3355                 :          0 :                 aCorrectedSymbol.Insert( cQuote, nPos + 1 );
    3356                 :          0 :             bCorrected = true;
    3357                 :            :         }
    3358 [ #  # ][ #  # ]:          0 :         else if ( c1 != cQuote && c2 == cQuote )
    3359                 :            :         {   // ..."
    3360                 :          0 :             aCorrectedSymbol.Insert( cQuote, 0 );
    3361                 :          0 :             bCorrected = true;
    3362                 :            :         }
    3363 [ #  # ][ #  # ]:          0 :         else if ( nPos == 0 && (c1 == cx || c1 == cX) )
                 [ #  # ]
    3364                 :            :         {   // x => *
    3365                 :          0 :             aCorrectedSymbol = mxSymbols->getSymbol(ocMul);
    3366                 :          0 :             bCorrected = true;
    3367                 :            :         }
    3368   [ #  #  #  # ]:          0 :         else if ( (GetCharTableFlags( c1, 0 ) & SC_COMPILER_C_CHAR_VALUE)
                 [ #  # ]
    3369                 :          0 :                && (GetCharTableFlags( c2, c2p ) & SC_COMPILER_C_CHAR_VALUE) )
    3370                 :            :         {
    3371                 :            :             xub_StrLen nXcount;
    3372 [ #  # ][ #  # ]:          0 :             if ( (nXcount = comphelper::string::getTokenCount(aCorrectedSymbol, cx)) > 1 )
    3373                 :            :             {   // x => *
    3374                 :          0 :                 xub_StrLen nIndex = 0;
    3375                 :          0 :                 sal_Unicode c = mxSymbols->getSymbol(ocMul).GetChar(0);
    3376         [ #  # ]:          0 :                 while ( (nIndex = aCorrectedSymbol.SearchAndReplace(
    3377                 :          0 :                         cx, c, nIndex )) != STRING_NOTFOUND )
    3378                 :          0 :                     nIndex++;
    3379                 :          0 :                 bCorrected = true;
    3380                 :            :             }
    3381 [ #  # ][ #  # ]:          0 :             if ( (nXcount = comphelper::string::getTokenCount(aCorrectedSymbol, cX)) > 1 )
    3382                 :            :             {   // X => *
    3383                 :          0 :                 xub_StrLen nIndex = 0;
    3384                 :          0 :                 sal_Unicode c = mxSymbols->getSymbol(ocMul).GetChar(0);
    3385         [ #  # ]:          0 :                 while ( (nIndex = aCorrectedSymbol.SearchAndReplace(
    3386                 :          0 :                         cX, c, nIndex )) != STRING_NOTFOUND )
    3387                 :          0 :                     nIndex++;
    3388                 :          0 :                 bCorrected = true;
    3389                 :            :             }
    3390                 :            :         }
    3391                 :            :         else
    3392                 :            :         {
    3393         [ #  # ]:          0 :             String aSymbol( aCorrectedSymbol );
    3394         [ #  # ]:          0 :             String aDoc;
    3395                 :            :             xub_StrLen nPosition;
    3396 [ #  # ][ #  # ]:          0 :             if ( aSymbol.GetChar(0) == '\''
         [ #  # ][ #  # ]
    3397                 :            :               && ((nPosition = aSymbol.SearchAscii( "'#" )) != STRING_NOTFOUND) )
    3398                 :            :             {   // Split off 'Doc'#, may be d:\... or whatever
    3399 [ #  # ][ #  # ]:          0 :                 aDoc = aSymbol.Copy( 0, nPosition + 2 );
                 [ #  # ]
    3400         [ #  # ]:          0 :                 aSymbol.Erase( 0, nPosition + 2 );
    3401                 :            :             }
    3402 [ #  # ][ #  # ]:          0 :             xub_StrLen nRefs = comphelper::string::getTokenCount(aSymbol, ':');
    3403                 :            :             bool bColons;
    3404         [ #  # ]:          0 :             if ( nRefs > 2 )
    3405                 :            :             {   // duplicated or too many ':'? B:2::C10 => B2:C10
    3406                 :          0 :                 bColons = true;
    3407                 :          0 :                 xub_StrLen nIndex = 0;
    3408         [ #  # ]:          0 :                 String aTmp1( aSymbol.GetToken( 0, ':', nIndex ) );
    3409                 :          0 :                 xub_StrLen nLen1 = aTmp1.Len();
    3410 [ #  # ][ #  # ]:          0 :                 String aSym, aTmp2;
    3411                 :            :                 bool bLastAlp, bNextNum;
    3412                 :          0 :                 bLastAlp = bNextNum = true;
    3413                 :          0 :                 xub_StrLen nStrip = 0;
    3414                 :          0 :                 xub_StrLen nCount = nRefs;
    3415         [ #  # ]:          0 :                 for ( xub_StrLen j=1; j<nCount; j++ )
    3416                 :            :                 {
    3417 [ #  # ][ #  # ]:          0 :                     aTmp2 = aSymbol.GetToken( 0, ':', nIndex );
                 [ #  # ]
    3418                 :          0 :                     xub_StrLen nLen2 = aTmp2.Len();
    3419 [ #  # ][ #  # ]:          0 :                     if ( nLen1 || nLen2 )
    3420                 :            :                     {
    3421         [ #  # ]:          0 :                         if ( nLen1 )
    3422                 :            :                         {
    3423         [ #  # ]:          0 :                             aSym += aTmp1;
    3424         [ #  # ]:          0 :                             bLastAlp = CharClass::isAsciiAlpha( aTmp1 );
    3425                 :            :                         }
    3426         [ #  # ]:          0 :                         if ( nLen2 )
    3427                 :            :                         {
    3428         [ #  # ]:          0 :                             bNextNum = CharClass::isAsciiNumeric( aTmp2 );
    3429 [ #  # ][ #  # ]:          0 :                             if ( bLastAlp == bNextNum && nStrip < 1 )
    3430                 :            :                             {
    3431                 :            :                                 // Must be alternating number/string, only
    3432                 :            :                                 // strip within a reference.
    3433                 :          0 :                                 nRefs--;
    3434                 :          0 :                                 nStrip++;
    3435                 :            :                             }
    3436                 :            :                             else
    3437                 :            :                             {
    3438                 :          0 :                                 xub_StrLen nSymLen = aSym.Len();
    3439         [ #  # ]:          0 :                                 if ( nSymLen
           [ #  #  #  # ]
    3440                 :          0 :                                   && (aSym.GetChar( nSymLen - 1 ) != ':') )
    3441         [ #  # ]:          0 :                                     aSym += ':';
    3442                 :          0 :                                 nStrip = 0;
    3443                 :            :                             }
    3444                 :          0 :                             bLastAlp = !bNextNum;
    3445                 :            :                         }
    3446                 :            :                         else
    3447                 :            :                         {   // ::
    3448                 :          0 :                             nRefs--;
    3449         [ #  # ]:          0 :                             if ( nLen1 )
    3450                 :            :                             {   // B10::C10 ? append ':' on next round
    3451 [ #  # ][ #  # ]:          0 :                                 if ( !bLastAlp && !CharClass::isAsciiNumeric( aTmp1 ) )
         [ #  # ][ #  # ]
    3452                 :          0 :                                     nStrip++;
    3453                 :            :                             }
    3454                 :          0 :                             bNextNum = !bLastAlp;
    3455                 :            :                         }
    3456         [ #  # ]:          0 :                         aTmp1 = aTmp2;
    3457                 :          0 :                         nLen1 = nLen2;
    3458                 :            :                     }
    3459                 :            :                     else
    3460                 :          0 :                         nRefs--;
    3461                 :            :                 }
    3462         [ #  # ]:          0 :                 aSymbol = aSym;
    3463 [ #  # ][ #  # ]:          0 :                 aSymbol += aTmp1;
         [ #  # ][ #  # ]
    3464                 :            :             }
    3465                 :            :             else
    3466                 :          0 :                 bColons = false;
    3467 [ #  # ][ #  # ]:          0 :             if ( nRefs && nRefs <= 2 )
    3468                 :            :             {   // reference twisted? 4A => A4 etc.
    3469 [ #  # ][ #  # ]:          0 :                 String aTab[2], aRef[2];
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
          #  #  #  #  #  
                #  #  # ]
    3470         [ #  # ]:          0 :                 const ScAddress::Details aDetails( pConv->meConv, aPos );
    3471         [ #  # ]:          0 :                 if ( nRefs == 2 )
    3472                 :            :                 {
    3473 [ #  # ][ #  # ]:          0 :                     aRef[0] = aSymbol.GetToken( 0, ':' );
                 [ #  # ]
    3474 [ #  # ][ #  # ]:          0 :                     aRef[1] = aSymbol.GetToken( 1, ':' );
                 [ #  # ]
    3475                 :            :                 }
    3476                 :            :                 else
    3477         [ #  # ]:          0 :                     aRef[0] = aSymbol;
    3478                 :            : 
    3479                 :          0 :                 bool bChanged = false;
    3480                 :          0 :                 bool bOk = true;
    3481                 :          0 :                 sal_uInt16 nMask = SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW;
    3482         [ #  # ]:          0 :                 for ( int j=0; j<nRefs; j++ )
    3483                 :            :                 {
    3484                 :          0 :                     xub_StrLen nTmp = 0;
    3485                 :          0 :                     xub_StrLen nDotPos = STRING_NOTFOUND;
    3486 [ #  # ][ #  # ]:          0 :                     while ( (nTmp = aRef[j].Search( '.', nTmp )) != STRING_NOTFOUND )
    3487                 :          0 :                         nDotPos = nTmp++;      // the last one counts
    3488         [ #  # ]:          0 :                     if ( nDotPos != STRING_NOTFOUND )
    3489                 :            :                     {
    3490 [ #  # ][ #  # ]:          0 :                         aTab[j] = aRef[j].Copy( 0, nDotPos + 1 );  // with '.'
                 [ #  # ]
    3491         [ #  # ]:          0 :                         aRef[j].Erase( 0, nDotPos + 1 );
    3492                 :            :                     }
    3493         [ #  # ]:          0 :                     String aOld( aRef[j] );
    3494         [ #  # ]:          0 :                     String aStr2;
    3495                 :          0 :                     const sal_Unicode* p = aRef[j].GetBuffer();
    3496 [ #  # ][ #  # ]:          0 :                     while ( *p && CharClass::isAsciiNumeric( rtl::OUString(*p) ) )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  #  
             #  #  #  # ]
    3497         [ #  # ]:          0 :                         aStr2 += *p++;
    3498         [ #  # ]:          0 :                     aRef[j] = rtl::OUString( p );
    3499         [ #  # ]:          0 :                     aRef[j] += aStr2;
    3500 [ #  # ][ #  # ]:          0 :                     if ( bColons || aRef[j] != aOld )
         [ #  # ][ #  # ]
    3501                 :            :                     {
    3502                 :          0 :                         bChanged = true;
    3503                 :          0 :                         ScAddress aAdr;
    3504         [ #  # ]:          0 :                         bOk &= ((aAdr.Parse( aRef[j], pDoc, aDetails ) & nMask) == nMask);
    3505                 :            :                     }
    3506 [ #  # ][ #  # ]:          0 :                 }
    3507 [ #  # ][ #  # ]:          0 :                 if ( bChanged && bOk )
    3508                 :            :                 {
    3509         [ #  # ]:          0 :                     aCorrectedSymbol = aDoc;
    3510         [ #  # ]:          0 :                     aCorrectedSymbol += aTab[0];
    3511         [ #  # ]:          0 :                     aCorrectedSymbol += aRef[0];
    3512         [ #  # ]:          0 :                     if ( nRefs == 2 )
    3513                 :            :                     {
    3514         [ #  # ]:          0 :                         aCorrectedSymbol += ':';
    3515         [ #  # ]:          0 :                         aCorrectedSymbol += aTab[1];
    3516         [ #  # ]:          0 :                         aCorrectedSymbol += aRef[1];
    3517                 :            :                     }
    3518                 :          0 :                     bCorrected = true;
    3519 [ #  # ][ #  # ]:          0 :                 }
           [ #  #  #  # ]
    3520 [ #  # ][ #  # ]:          0 :             }
    3521                 :            :         }
    3522                 :            :     }
    3523                 :          0 : }
    3524                 :            : 
    3525                 :       3031 : inline bool lcl_UpperAsciiOrI18n( String& rUpper, const String& rOrg, FormulaGrammar::Grammar eGrammar )
    3526                 :            : {
    3527         [ +  + ]:       3031 :     if (FormulaGrammar::isODFF( eGrammar ))
    3528                 :            :     {
    3529                 :            :         // ODFF has a defined set of English function names, avoid i18n
    3530                 :            :         // overhead.
    3531                 :       2183 :         rUpper = rOrg;
    3532                 :       2183 :         rUpper.ToUpperAscii();
    3533                 :       2183 :         return true;
    3534                 :            :     }
    3535                 :            :     else
    3536                 :            :     {
    3537 [ +  - ][ +  - ]:        848 :         rUpper = ScGlobal::pCharClass->uppercase( rOrg );
    3538                 :       3031 :         return false;
    3539                 :            :     }
    3540                 :            : }
    3541                 :            : 
    3542                 :      15663 : bool ScCompiler::NextNewToken( bool bInArray )
    3543                 :            : {
    3544                 :      15663 :     bool bAllowBooleans = bInArray;
    3545         [ +  - ]:      15663 :     xub_StrLen nSpaces = NextSymbol(bInArray);
    3546                 :            : 
    3547         [ +  + ]:      15663 :     if (!cSymbol[0])
    3548                 :       4206 :         return false;
    3549                 :            : 
    3550         [ +  + ]:      11457 :     if( nSpaces )
    3551                 :            :     {
    3552                 :         80 :         ScRawToken aToken;
    3553         [ +  - ]:         80 :         aToken.SetOpCode( ocSpaces );
    3554         [ +  - ]:         80 :         aToken.sbyte.cByte = (sal_uInt8) ( nSpaces > 255 ? 255 : nSpaces );
    3555 [ +  - ][ -  + ]:         80 :         if( !static_cast<ScTokenArray*>(pArr)->AddRawToken( aToken ) )
    3556                 :            :         {
    3557         [ #  # ]:          0 :             SetError(errCodeOverflow);
    3558                 :         80 :             return false;
    3559         [ +  - ]:         80 :         }
    3560                 :            :     }
    3561                 :            : 
    3562                 :            :     // Short cut for references when reading ODF to speedup things.
    3563         [ +  + ]:      11457 :     if (mnPredetectedReference)
    3564                 :            :     {
    3565                 :        417 :         rtl::OUString aStr( cSymbol);
    3566 [ +  - ][ -  + ]:        417 :         if (!IsPredetectedReference( aStr) && !IsExternalNamedRange( aStr))
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
         [ #  # ][ +  - ]
         [ +  - ][ -  +  
             #  #  #  # ]
                 [ +  - ]
    3567                 :            :         {
    3568                 :            :             /* TODO: it would be nice to generate a #REF! error here, which
    3569                 :            :              * would need an ocBad token with additional error value.
    3570                 :            :              * FormulaErrorToken wouldn't do because we want to preserve the
    3571                 :            :              * original string containing partial valid address
    3572                 :            :              * information if not ODFF (in that case it was already handled).
    3573                 :            :              * */
    3574                 :          0 :             ScRawToken aToken;
    3575         [ #  # ]:          0 :             aToken.SetString( aStr.getStr() );
    3576                 :          0 :             aToken.NewOpCode( ocBad );
    3577 [ #  # ][ #  # ]:          0 :             pRawToken = aToken.Clone();
    3578                 :            :         }
    3579                 :        417 :         return true;
    3580                 :            :     }
    3581                 :            : 
    3582 [ +  - ][ +  + ]:      11040 :     if ( (cSymbol[0] == '#' || cSymbol[0] == '$') && cSymbol[1] == 0 &&
         [ -  + ][ #  # ]
    3583                 :          0 :             !bAutoCorrect )
    3584                 :            :     {   // special case to speed up broken [$]#REF documents
    3585                 :            :         /* FIXME: ISERROR(#REF!) would be valid and TRUE and the formula to
    3586                 :            :          * be processed as usual. That would need some special treatment,
    3587                 :            :          * also in NextSymbol() because of possible combinations of
    3588                 :            :          * #REF!.#REF!#REF! parts. In case of reading ODF that is all
    3589                 :            :          * handled by IsPredetectedReference(), this case here remains for
    3590                 :            :          * manual/API input. */
    3591         [ #  # ]:          0 :         String aBad( aFormula.Copy( nSrcPos-1 ) );
    3592         [ #  # ]:          0 :         eLastOp = pArr->AddBad( aBad )->GetOpCode();
    3593         [ #  # ]:          0 :         return false;
    3594                 :            :     }
    3595                 :            : 
    3596 [ +  - ][ +  + ]:      11040 :     if( IsString() )
    3597                 :        258 :         return true;
    3598                 :            : 
    3599                 :            :     bool bMayBeFuncName;
    3600                 :            :     bool bAsciiNonAlnum;    // operators, separators, ...
    3601         [ +  - ]:      10782 :     if ( cSymbol[0] < 128 )
    3602                 :            :     {
    3603                 :      10782 :         bMayBeFuncName = CharClass::isAsciiAlpha( cSymbol[0] );
    3604 [ +  + ][ +  + ]:      10782 :         bAsciiNonAlnum = !bMayBeFuncName && !CharClass::isAsciiDigit( cSymbol[0] );
    3605                 :            :     }
    3606                 :            :     else
    3607                 :            :     {
    3608                 :          0 :         rtl::OUString aTmpStr( cSymbol[0] );
    3609 [ #  # ][ #  # ]:          0 :         bMayBeFuncName = ScGlobal::pCharClass->isLetter( aTmpStr, 0 );
                 [ #  # ]
    3610                 :          0 :         bAsciiNonAlnum = false;
    3611                 :            :     }
    3612         [ +  + ]:      10782 :     if ( bMayBeFuncName )
    3613                 :            :     {
    3614                 :            :         // a function name must be followed by a parenthesis
    3615                 :       2511 :         const sal_Unicode* p = aFormula.GetBuffer() + nSrcPos;
    3616         [ +  + ]:       2515 :         while( *p == ' ' )
    3617                 :          4 :             p++;
    3618                 :       2511 :         bMayBeFuncName = ( *p == '(' );
    3619                 :            :     }
    3620                 :            : 
    3621                 :            :     // Italian ARCTAN.2 resulted in #REF! => IsOpcode() before
    3622                 :            :     // IsReference().
    3623                 :            : 
    3624         [ +  - ]:      10782 :     String aUpper;
    3625                 :            : 
    3626         [ -  + ]:         27 :     do
    3627                 :            :     {
    3628                 :      10782 :         mbRewind = false;
    3629                 :      10782 :         const rtl::OUString aOrg( cSymbol );
    3630                 :            : 
    3631         [ +  + ]:      10782 :         if (bAsciiNonAlnum)
    3632                 :            :         {
    3633         [ -  + ]:       6987 :             if (cSymbol[0] == '#')
    3634                 :            :             {
    3635                 :            :                 // This can be only an error constant, if any.
    3636 [ #  # ][ #  # ]:          0 :                 lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
                 [ #  # ]
    3637 [ #  # ][ #  # ]:          0 :                 if (IsErrorConstant( aUpper))
    3638                 :          0 :                     return true;
    3639                 :            :                 break;  // do; create ocBad token or set error.
    3640                 :            :             }
    3641 [ +  - ][ +  - ]:       6987 :             if (IsOpCode( aOrg, bInArray ))
         [ +  - ][ +  + ]
    3642                 :       4615 :                 return true;
    3643                 :            :         }
    3644                 :            : 
    3645         [ +  - ]:       6167 :         aUpper.Erase();
    3646                 :       6167 :         bool bAsciiUpper = false;
    3647         [ +  + ]:       6167 :         if (bMayBeFuncName)
    3648                 :            :         {
    3649 [ +  - ][ +  - ]:       1601 :             bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
                 [ +  - ]
    3650 [ +  - ][ +  + ]:       1601 :             if (IsOpCode( aUpper, bInArray ))
    3651                 :       1598 :                 return true;
    3652                 :            :         }
    3653                 :            : 
    3654                 :            :         // Column 'DM' ("Deutsche Mark", German currency) couldn't be
    3655                 :            :         // referred => IsReference() before IsValue().
    3656                 :            :         // Preserve case of file names in external references.
    3657 [ +  - ][ +  - ]:       4569 :         if (IsReference( aOrg ))
         [ +  - ][ +  + ]
    3658                 :            :         {
    3659         [ -  + ]:       3136 :             if (mbRewind)   // Range operator, but no direct reference.
    3660                 :          0 :                 continue;   // do; up to range operator.
    3661                 :            :             // If a syntactically correct reference was recognized but invalid
    3662                 :            :             // e.g. because of non-existing sheet name => entire reference
    3663                 :            :             // ocBad to preserve input instead of #REF!.A1
    3664 [ +  - ][ -  + ]:       3136 :             if (!pRawToken->IsValidReference())
    3665                 :            :             {
    3666         [ #  # ]:          0 :                 aUpper = aOrg;          // ensure for ocBad
    3667                 :            :                 break;                  // do; create ocBad token or set error.
    3668                 :            :             }
    3669                 :       3136 :             return true;
    3670                 :            :         }
    3671                 :            : 
    3672         [ +  + ]:       1433 :         if (!aUpper.Len())
    3673 [ +  - ][ +  - ]:       1430 :             bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar);
                 [ +  - ]
    3674                 :            : 
    3675                 :            :         // IsBoolean() before IsValue() to catch inline bools without the kludge
    3676                 :            :         //    for inline arrays.
    3677 [ +  + ][ +  - ]:       1433 :         if (bAllowBooleans && IsBoolean( aUpper ))
         [ -  + ][ -  + ]
    3678                 :          0 :             return true;
    3679                 :            : 
    3680 [ +  - ][ +  + ]:       1433 :         if (IsValue( aUpper ))
    3681                 :       1284 :             return true;
    3682                 :            : 
    3683                 :            :         // User defined names and such do need i18n upper also in ODF.
    3684         [ +  + ]:        149 :         if (bAsciiUpper)
    3685 [ +  - ][ +  - ]:        101 :             aUpper = ScGlobal::pCharClass->uppercase( aOrg );
    3686                 :            : 
    3687 [ +  - ][ +  + ]:        149 :         if (IsNamedRange( aUpper ))
    3688                 :        116 :             return true;
    3689                 :            :         // Preserve case of file names in external references.
    3690 [ +  - ][ +  - ]:         33 :         if (IsExternalNamedRange( aOrg ))
         [ +  - ][ -  + ]
    3691                 :          0 :             return true;
    3692 [ +  - ][ +  + ]:         33 :         if (IsDBRange( aUpper ))
    3693                 :          6 :             return true;
    3694 [ +  - ][ -  + ]:         27 :         if (IsColRowName( aUpper ))
    3695                 :          0 :             return true;
    3696 [ +  + ][ +  - ]:         27 :         if (bMayBeFuncName && IsMacro( aUpper ))
         [ -  + ][ -  + ]
    3697                 :          0 :             return true;
    3698 [ +  + ][ +  - ]:         27 :         if (bMayBeFuncName && IsOpCode2( aUpper ))
         [ -  + ][ -  + ]
    3699   [ +  +  -  - ]:      10782 :             return true;
    3700                 :            : 
    3701                 :            :     } while (mbRewind);
    3702                 :            : 
    3703         [ +  + ]:         27 :     if ( meExtendedErrorDetection != EXTENDED_ERROR_DETECTION_NONE )
    3704                 :            :     {
    3705                 :            :         // set an error
    3706         [ +  - ]:          3 :         SetError( errNoName );
    3707         [ -  + ]:          3 :         if (meExtendedErrorDetection == EXTENDED_ERROR_DETECTION_NAME_BREAK)
    3708                 :          0 :             return false;   // end compilation
    3709                 :            :     }
    3710                 :            : 
    3711                 :            :     // Provide single token information and continue. Do not set an error, that
    3712                 :            :     // would prematurely end compilation. Simple unknown names are handled by
    3713                 :            :     // the interpreter.
    3714 [ +  - ][ +  - ]:         27 :     aUpper = ScGlobal::pCharClass->lowercase( aUpper );
                 [ +  - ]
    3715                 :         27 :     ScRawToken aToken;
    3716         [ +  - ]:         27 :     aToken.SetString( aUpper.GetBuffer() );
    3717                 :         27 :     aToken.NewOpCode( ocBad );
    3718 [ +  - ][ +  - ]:         27 :     pRawToken = aToken.Clone();
    3719         [ -  + ]:         27 :     if ( bAutoCorrect )
    3720         [ #  # ]:          0 :         AutoCorrectParsedSymbol();
    3721         [ +  - ]:      15663 :     return true;
    3722                 :            : }
    3723                 :            : 
    3724                 :       1067 : void ScCompiler::CreateStringFromXMLTokenArray( String& rFormula, String& rFormulaNmsp )
    3725                 :            : {
    3726                 :       1067 :     bool bExternal = GetGrammar() == FormulaGrammar::GRAM_EXTERNAL;
    3727         [ -  + ]:       1067 :     sal_uInt16 nExpectedCount = bExternal ? 2 : 1;
    3728                 :            :     OSL_ENSURE( pArr->GetLen() == nExpectedCount, "ScCompiler::CreateStringFromXMLTokenArray - wrong number of tokens" );
    3729         [ +  - ]:       1067 :     if( pArr->GetLen() == nExpectedCount )
    3730                 :            :     {
    3731                 :       1067 :         FormulaToken** ppTokens = pArr->GetArray();
    3732                 :            :         // string tokens expected, GetString() will assert if token type is wrong
    3733                 :       1067 :         rFormula = ppTokens[ 0 ]->GetString();
    3734         [ -  + ]:       1067 :         if( bExternal )
    3735                 :          0 :             rFormulaNmsp = ppTokens[ 1 ]->GetString();
    3736                 :            :     }
    3737                 :       1067 : }
    3738                 :            : 
    3739                 :       1067 : void ScCompiler::CreateStringFromXMLTokenArray( rtl::OUString& rFormula, rtl::OUString& rFormulaNmsp )
    3740                 :            : {
    3741 [ +  - ][ +  - ]:       1067 :     String sFormula, aFormulaNmsp;
    3742         [ +  - ]:       1067 :     CreateStringFromXMLTokenArray(sFormula, aFormulaNmsp);
    3743         [ +  - ]:       1067 :     rFormula = sFormula;
    3744 [ +  - ][ +  - ]:       1067 :     rFormulaNmsp = aFormulaNmsp;
                 [ +  - ]
    3745                 :       1067 : }
    3746                 :            : 
    3747                 :       4206 : ScTokenArray* ScCompiler::CompileString( const String& rFormula )
    3748                 :            : {
    3749                 :            :     OSL_ENSURE( meGrammar != FormulaGrammar::GRAM_EXTERNAL, "ScCompiler::CompileString - unexpected grammar GRAM_EXTERNAL" );
    3750         [ -  + ]:       4206 :     if( meGrammar == FormulaGrammar::GRAM_EXTERNAL )
    3751         [ #  # ]:          0 :         SetGrammar( FormulaGrammar::GRAM_PODF );
    3752                 :            : 
    3753         [ +  - ]:       4206 :     ScTokenArray aArr;
    3754                 :       4206 :     pArr = &aArr;
    3755 [ +  - ][ +  - ]:       4206 :     aFormula = comphelper::string::strip(rFormula, ' ');
                 [ +  - ]
    3756                 :            : 
    3757                 :       4206 :     nSrcPos = 0;
    3758                 :       4206 :     bCorrected = false;
    3759         [ -  + ]:       4206 :     if ( bAutoCorrect )
    3760                 :            :     {
    3761         [ #  # ]:          0 :         aCorrectedFormula.Erase();
    3762         [ #  # ]:          0 :         aCorrectedSymbol.Erase();
    3763                 :            :     }
    3764                 :       4206 :     sal_uInt8 nForced = 0;   // ==formula forces recalc even if cell is not visible
    3765         [ +  + ]:       4206 :     if( aFormula.GetChar(nSrcPos) == '=' )
    3766                 :            :     {
    3767                 :       1652 :         nSrcPos++;
    3768                 :       1652 :         nForced++;
    3769         [ -  + ]:       1652 :         if ( bAutoCorrect )
    3770         [ #  # ]:          0 :             aCorrectedFormula += '=';
    3771                 :            :     }
    3772         [ -  + ]:       4206 :     if( aFormula.GetChar(nSrcPos) == '=' )
    3773                 :            :     {
    3774                 :          0 :         nSrcPos++;
    3775                 :          0 :         nForced++;
    3776         [ #  # ]:          0 :         if ( bAutoCorrect )
    3777         [ #  # ]:          0 :             aCorrectedFormula += '=';
    3778                 :            :     }
    3779                 :            :     struct FunctionStack
    3780                 :            :     {
    3781                 :            :         OpCode  eOp;
    3782                 :            :         short   nPar;
    3783                 :            :     };
    3784                 :            :     // FunctionStack only used if PODF!
    3785                 :       4206 :     bool bPODF = FormulaGrammar::isPODF( meGrammar);
    3786                 :       4206 :     const size_t nAlloc = 512;
    3787                 :            :     FunctionStack aFuncs[ nAlloc ];
    3788                 :        108 :     FunctionStack* pFunctionStack = (bPODF && rFormula.Len() > nAlloc ?
    3789         [ #  # ]:       4314 :             new FunctionStack[ rFormula.Len() ] : &aFuncs[0]);
           [ +  +  -  + ]
    3790                 :       4206 :     pFunctionStack[0].eOp = ocNone;
    3791                 :       4206 :     pFunctionStack[0].nPar = 0;
    3792                 :       4206 :     size_t nFunction = 0;
    3793                 :       4206 :     short nBrackets = 0;
    3794                 :       4206 :     bool bInArray = false;
    3795                 :       4206 :     eLastOp = ocOpen;
    3796 [ +  - ][ +  + ]:      15663 :     while( NextNewToken( bInArray ) )
    3797                 :            :     {
    3798                 :      11457 :         const OpCode eOp = pRawToken->GetOpCode();
    3799         [ -  + ]:      11457 :         if (eOp == ocSkip)
    3800                 :          0 :             continue;
    3801                 :            : 
    3802   [ +  +  +  +  :      11457 :         switch (eOp)
                   +  + ]
    3803                 :            :         {
    3804                 :            :             case ocOpen:
    3805                 :            :             {
    3806                 :       1603 :                 ++nBrackets;
    3807         [ +  + ]:       1603 :                 if (bPODF)
    3808                 :            :                 {
    3809                 :         55 :                     ++nFunction;
    3810                 :         55 :                     pFunctionStack[ nFunction ].eOp = eLastOp;
    3811                 :         55 :                     pFunctionStack[ nFunction ].nPar = 0;
    3812                 :            :                 }
    3813                 :            :             }
    3814                 :       1603 :             break;
    3815                 :            :             case ocClose:
    3816                 :            :             {
    3817         [ -  + ]:       1592 :                 if( !nBrackets )
    3818                 :            :                 {
    3819         [ #  # ]:          0 :                     SetError( errPairExpected );
    3820         [ #  # ]:          0 :                     if ( bAutoCorrect )
    3821                 :            :                     {
    3822                 :          0 :                         bCorrected = true;
    3823         [ #  # ]:          0 :                         aCorrectedSymbol.Erase();
    3824                 :            :                     }
    3825                 :            :                 }
    3826                 :            :                 else
    3827                 :       1592 :                     nBrackets--;
    3828 [ +  + ][ +  - ]:       1592 :                 if (bPODF && nFunction)
    3829                 :         47 :                     --nFunction;
    3830                 :            :             }
    3831                 :       1592 :             break;
    3832                 :            :             case ocSep:
    3833                 :            :             {
    3834         [ +  + ]:        968 :                 if (bPODF)
    3835                 :         16 :                     ++pFunctionStack[ nFunction ].nPar;
    3836                 :            :             }
    3837                 :        968 :             break;
    3838                 :            :             case ocArrayOpen:
    3839                 :            :             {
    3840         [ -  + ]:         15 :                 if( bInArray )
    3841         [ #  # ]:          0 :                     SetError( errNestedArray );
    3842                 :            :                 else
    3843                 :         15 :                     bInArray = true;
    3844                 :            :                 // Don't count following column separator as parameter separator.
    3845         [ -  + ]:         15 :                 if (bPODF)
    3846                 :            :                 {
    3847                 :          0 :                     ++nFunction;
    3848                 :          0 :                     pFunctionStack[ nFunction ].eOp = eOp;
    3849                 :          0 :                     pFunctionStack[ nFunction ].nPar = 0;
    3850                 :            :                 }
    3851                 :            :             }
    3852                 :         15 :             break;
    3853                 :            :             case ocArrayClose:
    3854                 :            :             {
    3855         [ +  - ]:         15 :                 if( bInArray )
    3856                 :            :                 {
    3857                 :         15 :                     bInArray = false;
    3858                 :            :                 }
    3859                 :            :                 else
    3860                 :            :                 {
    3861         [ #  # ]:          0 :                     SetError( errPairExpected );
    3862         [ #  # ]:          0 :                     if ( bAutoCorrect )
    3863                 :            :                     {
    3864                 :          0 :                         bCorrected = true;
    3865         [ #  # ]:          0 :                         aCorrectedSymbol.Erase();
    3866                 :            :                     }
    3867                 :            :                 }
    3868 [ -  + ][ #  # ]:         15 :                 if (bPODF && nFunction)
    3869                 :          0 :                     --nFunction;
    3870                 :            :             }
    3871                 :            :             default:
    3872                 :       7279 :             break;
    3873                 :            :         }
    3874 [ +  + ][ +  + ]:      11457 :         if( (eLastOp == ocSep ||
         [ +  + ][ +  + ]
         [ +  + ][ +  + ]
         [ +  - ][ +  - ]
                 [ -  + ]
    3875                 :            :              eLastOp == ocArrayRowSep ||
    3876                 :            :              eLastOp == ocArrayColSep ||
    3877                 :            :              eLastOp == ocArrayOpen) &&
    3878                 :            :             (eOp == ocSep ||
    3879                 :            :              eOp == ocClose ||
    3880                 :            :              eOp == ocArrayRowSep ||
    3881                 :            :              eOp == ocArrayColSep ||
    3882                 :            :              eOp == ocArrayClose) )
    3883                 :            :         {
    3884                 :            :             // FIXME: should we check for known functions with optional empty
    3885                 :            :             // args so the correction dialog can do better?
    3886 [ +  - ][ +  - ]:         18 :             if ( !static_cast<ScTokenArray*>(pArr)->Add( new FormulaMissingToken ) )
         [ +  - ][ -  + ]
    3887                 :            :             {
    3888         [ #  # ]:          0 :                 SetError(errCodeOverflow); break;
    3889                 :            :             }
    3890                 :            :         }
    3891         [ +  + ]:      11457 :         if (bPODF)
    3892                 :            :         {
    3893                 :            :             /* TODO: for now this is the only PODF adapter. If there were more,
    3894                 :            :              * factor this out. */
    3895                 :            :             // Insert ADDRESS() new empty parameter 4 if there is a 4th, now to be 5th.
    3896 [ +  + ][ -  + ]:        340 :             if (eOp == ocSep &&
                 [ #  # ]
    3897                 :         16 :                     pFunctionStack[ nFunction ].eOp == ocAddress &&
    3898                 :          0 :                     pFunctionStack[ nFunction ].nPar == 3)
    3899                 :            :             {
    3900 [ #  # ][ #  # ]:          0 :                 if (!static_cast<ScTokenArray*>(pArr)->Add( new FormulaToken( svSep,ocSep)) ||
         [ #  # ][ #  # ]
                 [ #  # ]
    3901 [ #  # ][ #  # ]:          0 :                         !static_cast<ScTokenArray*>(pArr)->Add( new FormulaDoubleToken( 1.0)))
                 [ #  # ]
    3902                 :            :                 {
    3903         [ #  # ]:          0 :                     SetError(errCodeOverflow); break;
    3904                 :            :                 }
    3905                 :          0 :                 ++pFunctionStack[ nFunction ].nPar;
    3906                 :            :             }
    3907                 :            :         }
    3908 [ +  - ][ +  - ]:      11457 :         FormulaToken* pNewToken = static_cast<ScTokenArray*>(pArr)->Add( pRawToken->CreateToken());
    3909         [ -  + ]:      11457 :         if (!pNewToken)
    3910                 :            :         {
    3911         [ #  # ]:          0 :             SetError(errCodeOverflow); break;
    3912                 :            :         }
    3913         [ -  + ]:      11457 :         else if (eLastOp == ocRange && pNewToken->GetOpCode() == ocPush &&
           [ #  #  #  # ]
                 [ -  + ]
    3914                 :          0 :                 pNewToken->GetType() == svSingleRef)
    3915         [ #  # ]:          0 :             static_cast<ScTokenArray*>(pArr)->MergeRangeReference( aPos);
    3916                 :      11457 :         eLastOp = pRawToken->GetOpCode();
    3917         [ -  + ]:      11457 :         if ( bAutoCorrect )
    3918         [ #  # ]:          0 :             aCorrectedFormula += aCorrectedSymbol;
    3919                 :            :     }
    3920         [ +  - ]:       4206 :     if ( mbCloseBrackets )
    3921                 :            :     {
    3922         [ -  + ]:       4206 :         if( bInArray )
    3923                 :            :         {
    3924         [ #  # ]:          0 :             FormulaByteToken aToken( ocArrayClose );
    3925 [ #  # ][ #  # ]:          0 :             if( !pArr->AddToken( aToken ) )
    3926                 :            :             {
    3927         [ #  # ]:          0 :                 SetError(errCodeOverflow);
    3928                 :            :             }
    3929         [ #  # ]:          0 :             else if ( bAutoCorrect )
    3930 [ #  # ][ #  # ]:          0 :                 aCorrectedFormula += mxSymbols->getSymbol(ocArrayClose);
                 [ #  # ]
    3931                 :            :         }
    3932                 :            : 
    3933         [ +  - ]:       4206 :         FormulaByteToken aToken( ocClose );
    3934         [ +  + ]:       4217 :         while( nBrackets-- )
    3935                 :            :         {
    3936 [ +  - ][ -  + ]:         11 :             if( !pArr->AddToken( aToken ) )
    3937                 :            :             {
    3938         [ #  # ]:          0 :                 SetError(errCodeOverflow); break;
    3939                 :            :             }
    3940         [ -  + ]:         11 :             if ( bAutoCorrect )
    3941 [ #  # ][ #  # ]:          0 :                 aCorrectedFormula += mxSymbols->getSymbol(ocClose);
    3942         [ +  - ]:       4206 :         }
    3943                 :            :     }
    3944         [ -  + ]:       4206 :     if ( nForced >= 2 )
    3945                 :          0 :         pArr->SetRecalcModeForced();
    3946                 :            : 
    3947         [ -  + ]:       4206 :     if (pFunctionStack != &aFuncs[0])
    3948         [ #  # ]:          0 :         delete [] pFunctionStack;
    3949                 :            : 
    3950                 :            :     // remember pArr, in case a subsequent CompileTokenArray() is executed.
    3951 [ +  - ][ +  - ]:       4206 :     ScTokenArray* pNew = new ScTokenArray( aArr );
    3952                 :       4206 :     pArr = pNew;
    3953         [ +  - ]:       4206 :     return pNew;
    3954                 :            : }
    3955                 :            : 
    3956                 :            : 
    3957                 :       1222 : ScTokenArray* ScCompiler::CompileString( const String& rFormula, const String& rFormulaNmsp )
    3958                 :            : {
    3959                 :            :     OSL_ENSURE( (GetGrammar() == FormulaGrammar::GRAM_EXTERNAL) || (rFormulaNmsp.Len() == 0),
    3960                 :            :         "ScCompiler::CompileString - unexpected formula namespace for internal grammar" );
    3961         [ -  + ]:       1222 :     if( GetGrammar() == FormulaGrammar::GRAM_EXTERNAL ) try
    3962                 :            :     {
    3963         [ #  # ]:          0 :         ScFormulaParserPool& rParserPool = pDoc->GetFormulaParserPool();
    3964 [ #  # ][ #  # ]:          0 :         uno::Reference< sheet::XFormulaParser > xParser( rParserPool.getFormulaParser( rFormulaNmsp ), uno::UNO_SET_THROW );
                 [ #  # ]
    3965                 :          0 :         table::CellAddress aReferencePos;
    3966                 :          0 :         ScUnoConversion::FillApiAddress( aReferencePos, aPos );
    3967 [ #  # ][ #  # ]:          0 :         uno::Sequence< sheet::FormulaToken > aTokenSeq = xParser->parseFormula( rFormula, aReferencePos );
                 [ #  # ]
    3968         [ #  # ]:          0 :         ScTokenArray aTokenArray;
    3969 [ #  # ][ #  # ]:          0 :         if( ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, aTokenSeq ) )
    3970                 :            :         {
    3971                 :            :             // remember pArr, in case a subsequent CompileTokenArray() is executed.
    3972 [ #  # ][ #  # ]:          0 :             ScTokenArray* pNew = new ScTokenArray( aTokenArray );
    3973                 :          0 :             pArr = pNew;
    3974                 :          0 :             return pNew;
    3975 [ #  # ][ #  # ]:          0 :         }
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    3976                 :            :     }
    3977                 :          0 :     catch( uno::Exception& )
    3978                 :            :     {
    3979                 :            :     }
    3980                 :            :     // no success - fallback to some internal grammar and hope the best
    3981                 :       1222 :     return CompileString( rFormula );
    3982                 :            : }
    3983                 :            : 
    3984                 :            : 
    3985                 :        282 : ScRangeData* ScCompiler::GetRangeData( const FormulaToken& rToken ) const
    3986                 :            : {
    3987                 :        282 :     ScRangeData* pRangeData = NULL;
    3988                 :        282 :     bool bGlobal = rToken.IsGlobal();
    3989         [ +  + ]:        282 :     if (bGlobal)
    3990                 :            :         // global named range.
    3991                 :        198 :         pRangeData = pDoc->GetRangeName()->findByIndex( rToken.GetIndex());
    3992                 :            :     else
    3993                 :            :     {
    3994                 :            :         // sheet local named range.
    3995                 :         84 :         const ScRangeName* pRN = pDoc->GetRangeName( aPos.Tab());
    3996         [ +  - ]:         84 :         if (pRN)
    3997                 :         84 :             pRangeData = pRN->findByIndex( rToken.GetIndex());
    3998                 :            :     }
    3999                 :        282 :     return pRangeData;
    4000                 :            : }
    4001                 :            : 
    4002                 :            : 
    4003                 :        218 : bool ScCompiler::HandleRange()
    4004                 :            : {
    4005                 :        218 :     const ScRangeData* pRangeData = GetRangeData( *mpToken);
    4006         [ +  - ]:        218 :     if (pRangeData)
    4007                 :            :     {
    4008                 :        218 :         sal_uInt16 nErr = pRangeData->GetErrCode();
    4009         [ -  + ]:        218 :         if( nErr )
    4010                 :          0 :             SetError( errNoName );
    4011         [ +  - ]:        218 :         else if ( !bCompileForFAP )
    4012                 :            :         {
    4013                 :            :             ScTokenArray* pNew;
    4014                 :            :             // put named formula into parentheses.
    4015                 :            :             // But only if there aren't any yet, parenthetical
    4016                 :            :             // ocSep doesn't work, e.g. SUM((...;...))
    4017                 :            :             // or if not directly between ocSep/parenthesis,
    4018                 :            :             // e.g. SUM(...;(...;...)) no, SUM(...;(...)*3) yes,
    4019                 :            :             // in short: if it isn't a self-contained expression.
    4020                 :        218 :             FormulaToken* p1 = pArr->PeekPrevNoSpaces();
    4021                 :        218 :             FormulaToken* p2 = pArr->PeekNextNoSpaces();
    4022         [ +  + ]:        218 :             OpCode eOp1 = (p1 ? p1->GetOpCode() : static_cast<OpCode>( ocSep ) );
    4023         [ +  + ]:        218 :             OpCode eOp2 = (p2 ? p2->GetOpCode() : static_cast<OpCode>( ocSep ) );
    4024 [ +  + ][ +  + ]:        218 :             bool bBorder1 = (eOp1 == ocSep || eOp1 == ocOpen);
    4025 [ +  + ][ +  + ]:        218 :             bool bBorder2 = (eOp2 == ocSep || eOp2 == ocClose);
    4026 [ +  + ][ +  + ]:        218 :             bool bAddPair = !(bBorder1 && bBorder2);
    4027         [ +  + ]:        218 :             if ( bAddPair )
    4028                 :            :             {
    4029         [ +  - ]:         30 :                 pNew = new ScTokenArray();
    4030                 :         30 :                 pNew->AddOpCode( ocClose );
    4031                 :         30 :                 PushTokenArray( pNew, true );
    4032                 :         30 :                 pNew->Reset();
    4033                 :            :             }
    4034                 :        218 :             pNew = pRangeData->GetCode()->Clone();
    4035                 :        218 :             PushTokenArray( pNew, true );
    4036         [ +  + ]:        218 :             if( pRangeData->HasReferences() )
    4037                 :            :             {
    4038                 :        200 :                 SetRelNameReference();
    4039                 :        200 :                 MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
    4040                 :            :             }
    4041                 :        218 :             pNew->Reset();
    4042         [ +  + ]:        218 :             if ( bAddPair )
    4043                 :            :             {
    4044         [ +  - ]:         30 :                 pNew = new ScTokenArray();
    4045                 :         30 :                 pNew->AddOpCode( ocOpen );
    4046                 :         30 :                 PushTokenArray( pNew, true );
    4047                 :         30 :                 pNew->Reset();
    4048                 :            :             }
    4049                 :        218 :             return GetToken();
    4050                 :            :         }
    4051                 :            :     }
    4052                 :            :     else
    4053                 :          0 :         SetError(errNoName);
    4054                 :        218 :     return true;
    4055                 :            : }
    4056                 :            : // -----------------------------------------------------------------------------
    4057                 :        100 : bool ScCompiler::HandleExternalReference(const FormulaToken& _aToken)
    4058                 :            : {
    4059                 :            :     // Handle external range names.
    4060      [ +  -  - ]:        100 :     switch (_aToken.GetType())
    4061                 :            :     {
    4062                 :            :         case svExternalSingleRef:
    4063                 :            :         case svExternalDoubleRef:
    4064                 :        100 :             pArr->IncrementRefs();
    4065                 :        100 :         break;
    4066                 :            :         case svExternalName:
    4067                 :            :         {
    4068         [ #  # ]:          0 :             ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
    4069 [ #  # ][ #  # ]:          0 :             const OUString* pFile = pRefMgr->getExternalFileName(_aToken.GetIndex());
    4070         [ #  # ]:          0 :             if (!pFile)
    4071                 :            :             {
    4072         [ #  # ]:          0 :                 SetError(errNoName);
    4073                 :          0 :                 return true;
    4074                 :            :             }
    4075                 :            : 
    4076         [ #  # ]:          0 :             const String& rName = _aToken.GetString();
    4077                 :            :             ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getRangeNameTokens(
    4078 [ #  # ][ #  # ]:          0 :                 _aToken.GetIndex(), rName, &aPos);
                 [ #  # ]
    4079                 :            : 
    4080         [ #  # ]:          0 :             if (!xNew)
    4081                 :            :             {
    4082         [ #  # ]:          0 :                 SetError(errNoName);
    4083                 :          0 :                 return true;
    4084                 :            :             }
    4085                 :            : 
    4086         [ #  # ]:          0 :             ScTokenArray* pNew = xNew->Clone();
    4087         [ #  # ]:          0 :             PushTokenArray( pNew, true);
    4088 [ #  # ][ #  # ]:          0 :             if (pNew->GetNextReference() != NULL)
    4089                 :            :             {
    4090         [ #  # ]:          0 :                 SetRelNameReference();
    4091         [ #  # ]:          0 :                 MoveRelWrap(MAXCOL, MAXROW);
    4092                 :            :             }
    4093                 :          0 :             pNew->Reset();
    4094 [ #  # ][ #  # ]:          0 :             return GetToken();
    4095                 :            :         }
    4096                 :            :         default:
    4097                 :            :             OSL_FAIL("Wrong type for external reference!");
    4098                 :          0 :             return false;
    4099                 :            :     }
    4100                 :        100 :     return true;
    4101                 :            : }
    4102                 :            : 
    4103                 :            : 
    4104                 :            : //---------------------------------------------------------------------------
    4105                 :            : 
    4106                 :            : 
    4107                 :            : //---------------------------------------------------------------------------
    4108                 :            : // Append token to RPN code
    4109                 :            : //---------------------------------------------------------------------------
    4110                 :            : 
    4111                 :            : 
    4112                 :            : //-----------------------------------------------------------------------------
    4113                 :            : 
    4114                 :            : //---------------------------------------------------------------------------
    4115                 :            : // RPN creation by recursion
    4116                 :            : //---------------------------------------------------------------------------
    4117                 :            : 
    4118                 :            : 
    4119                 :            : 
    4120                 :            : //-----------------------------------------------------------------------------
    4121                 :            : 
    4122                 :         64 : bool ScCompiler::HasModifiedRange()
    4123                 :            : {
    4124                 :         64 :     pArr->Reset();
    4125         [ +  + ]:        219 :     for ( FormulaToken* t = pArr->Next(); t; t = pArr->Next() )
    4126                 :            :     {
    4127                 :        155 :         OpCode eOpCode = t->GetOpCode();
    4128         [ +  + ]:        155 :         if ( eOpCode == ocName )
    4129                 :            :         {
    4130                 :         14 :             const ScRangeData* pRangeData = GetRangeData( *t);
    4131 [ -  + ][ -  + ]:         14 :             if (pRangeData && pRangeData->IsModified())
                 [ +  - ]
    4132                 :          0 :                 return true;
    4133                 :            :         }
    4134         [ -  + ]:        141 :         else if ( eOpCode == ocDBArea )
    4135                 :            :         {
    4136                 :          0 :             ScDBData* pDBData = pDoc->GetDBCollection()->getNamedDBs().findByIndex(t->GetIndex());
    4137 [ #  # ][ #  # ]:          0 :             if (pDBData && pDBData->IsModified())
                 [ #  # ]
    4138                 :          0 :                 return true;
    4139                 :            :         }
    4140                 :            :     }
    4141                 :         64 :     return false;
    4142                 :            : }
    4143                 :            : 
    4144                 :            : 
    4145                 :            : //---------------------------------------------------------------------------
    4146                 :            : 
    4147                 :            : template< typename T, typename S >
    4148                 :            : S lcl_adjval( S& n, T pos, T max, bool bRel )
    4149                 :            : {
    4150                 :            :     max++;
    4151                 :            :     if( bRel )
    4152                 :            :         n = sal::static_int_cast<S>( n + pos );
    4153                 :            :     if( n < 0 )
    4154                 :            :         n = sal::static_int_cast<S>( n + max );
    4155                 :            :     else if( n >= max )
    4156                 :            :         n = sal::static_int_cast<S>( n - max );
    4157                 :            :     if( bRel )
    4158                 :            :         n = sal::static_int_cast<S>( n - pos );
    4159                 :            :     return n;
    4160                 :            : }
    4161                 :            : 
    4162                 :            : // reference of named range with relative references
    4163                 :            : 
    4164                 :        200 : void ScCompiler::SetRelNameReference()
    4165                 :            : {
    4166                 :        200 :     pArr->Reset();
    4167         [ +  + ]:        400 :     for( ScToken* t = static_cast<ScToken*>(pArr->GetNextReference()); t;
    4168                 :        200 :                   t = static_cast<ScToken*>(pArr->GetNextReference()) )
    4169                 :            :     {
    4170                 :        200 :         ScSingleRefData& rRef1 = t->GetSingleRef();
    4171 [ +  - ][ -  + ]:        200 :         if ( rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel() )
         [ +  + ][ +  + ]
    4172                 :         21 :             rRef1.SetRelName( true );
    4173         [ +  + ]:        200 :         if ( t->GetType() == svDoubleRef )
    4174                 :            :         {
    4175                 :         15 :             ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
    4176 [ +  - ][ -  + ]:         15 :             if ( rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel() )
         [ -  + ][ +  - ]
    4177                 :          0 :                 rRef2.SetRelName( true );
    4178                 :            :         }
    4179                 :            :     }
    4180                 :        200 : }
    4181                 :            : 
    4182                 :            : // Wrap-adjust relative references of a RangeName to current position,
    4183                 :            : // don't call for other token arrays!
    4184                 :        233 : void ScCompiler::MoveRelWrap( SCCOL nMaxCol, SCROW nMaxRow )
    4185                 :            : {
    4186                 :        233 :     pArr->Reset();
    4187         [ +  + ]:        466 :     for( ScToken* t = static_cast<ScToken*>(pArr->GetNextReference()); t;
    4188                 :        233 :                   t = static_cast<ScToken*>(pArr->GetNextReference()) )
    4189                 :            :     {
    4190 [ +  + ][ +  + ]:        233 :         if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
                 [ +  + ]
    4191         [ +  - ]:        203 :             ScRefUpdate::MoveRelWrap( pDoc, aPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
    4192                 :            :         else
    4193                 :         30 :             ScRefUpdate::MoveRelWrap( pDoc, aPos, nMaxCol, nMaxRow, t->GetDoubleRef() );
    4194                 :            :     }
    4195                 :        233 : }
    4196                 :            : 
    4197                 :            : // Wrap-adjust relative references of a RangeName to current position,
    4198                 :            : // don't call for other token arrays!
    4199                 :          0 : void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc, const ScAddress& rPos,
    4200                 :            :                               SCCOL nMaxCol, SCROW nMaxRow )
    4201                 :            : {
    4202                 :          0 :     rArr.Reset();
    4203         [ #  # ]:          0 :     for( ScToken* t = static_cast<ScToken*>(rArr.GetNextReference()); t;
    4204                 :          0 :                   t = static_cast<ScToken*>(rArr.GetNextReference()) )
    4205                 :            :     {
    4206 [ #  # ][ #  # ]:          0 :         if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
                 [ #  # ]
    4207         [ #  # ]:          0 :             ScRefUpdate::MoveRelWrap( pDoc, rPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
    4208                 :            :         else
    4209                 :          0 :             ScRefUpdate::MoveRelWrap( pDoc, rPos, nMaxCol, nMaxRow, t->GetDoubleRef() );
    4210                 :            :     }
    4211                 :          0 : }
    4212                 :            : 
    4213                 :         64 : ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode,
    4214                 :            :                                  const ScAddress& rOldPos, const ScRange& r,
    4215                 :            :                                  SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
    4216                 :            :                                  bool& rChanged, bool& rRefSizeChanged )
    4217                 :            : {
    4218                 :         64 :     rChanged = rRefSizeChanged = false;
    4219         [ +  + ]:         64 :     if ( eUpdateRefMode == URM_COPY )
    4220                 :            :     {   // Normally nothing has to be done here since RelRefs are used, also
    4221                 :            :         // SharedFormulas don't need any special handling, except if they
    4222                 :            :         // wrapped around sheet borders.
    4223                 :            :         // But ColRowName tokens pointing to a ColRow header which was
    4224                 :            :         // copied along with this formula need to be updated to point to the
    4225                 :            :         // copied header instead of the old position's new intersection.
    4226                 :            :         ScToken* t;
    4227                 :         46 :         pArr->Reset();
    4228         [ -  + ]:         46 :         while( (t = static_cast<ScToken*>(pArr->GetNextColRowName())) != NULL )
    4229                 :            :         {
    4230         [ #  # ]:          0 :             ScSingleRefData& rRef = t->GetSingleRef();
    4231         [ #  # ]:          0 :             rRef.CalcAbsIfRel( rOldPos );
    4232                 :          0 :             ScAddress aNewRef( rRef.nCol + nDx, rRef.nRow + nDy, rRef.nTab + nDz );
    4233         [ #  # ]:          0 :             if ( r.In( aNewRef ) )
    4234                 :            :             {   // yes, this is URM_MOVE
    4235         [ #  # ]:          0 :                 if ( ScRefUpdate::Update( pDoc, URM_MOVE, aPos,
    4236                 :            :                         r, nDx, nDy, nDz,
    4237         [ #  # ]:          0 :                         SingleDoubleRefModifier( rRef ).Ref() )
    4238                 :            :                         != UR_NOTHING
    4239                 :            :                     )
    4240                 :          0 :                     rChanged = true;
    4241                 :            :             }
    4242                 :            :         }
    4243                 :            :         // Check for SharedFormulas.
    4244                 :         46 :         ScRangeData* pRangeData = NULL;
    4245                 :         46 :         pArr->Reset();
    4246 [ +  + ][ +  - ]:         60 :         for( FormulaToken* j = pArr->GetNextName(); j && !pRangeData;
                 [ +  + ]
    4247                 :         14 :              j = pArr->GetNextName() )
    4248                 :            :         {
    4249         [ +  - ]:         14 :             if( j->GetOpCode() == ocName )
    4250                 :            :             {
    4251                 :         14 :                 ScRangeData* pName = GetRangeData( *j);
    4252 [ -  + ][ -  + ]:         14 :                 if (pName && pName->HasType(RT_SHARED))
                 [ +  - ]
    4253                 :          0 :                     pRangeData = pName;
    4254                 :            :             }
    4255                 :            :         }
    4256                 :            :         // Check SharedFormulas for wraps.
    4257         [ -  + ]:         46 :         if (pRangeData)
    4258                 :            :         {
    4259                 :          0 :             ScRangeData* pName = pRangeData;
    4260                 :          0 :             pRangeData = NULL;
    4261                 :          0 :             pArr->Reset();
    4262 [ #  # ][ #  # ]:          0 :             for( t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()); t && !pRangeData;
                 [ #  # ]
    4263                 :          0 :                  t = static_cast<ScToken*>(pArr->GetNextReferenceRPN()) )
    4264                 :            :             {
    4265                 :          0 :                 bool bRelName = (t->GetType() == svSingleRef ?
    4266                 :          0 :                         t->GetSingleRef().IsRelName() :
    4267                 :          0 :                         (t->GetDoubleRef().Ref1.IsRelName() ||
    4268         [ #  # ]:          0 :                          t->GetDoubleRef().Ref2.IsRelName()));
           [ #  #  #  # ]
    4269         [ #  # ]:          0 :                 if (bRelName)
    4270                 :            :                 {
    4271                 :          0 :                     t->CalcAbsIfRel( rOldPos);
    4272                 :          0 :                     bool bValid = (t->GetType() == svSingleRef ?
    4273                 :          0 :                             t->GetSingleRef().Valid() :
    4274         [ #  # ]:          0 :                             t->GetDoubleRef().Valid());
    4275                 :            :                     // If the reference isn't valid, copying the formula
    4276                 :            :                     // wrapped it. Replace SharedFormula.
    4277         [ #  # ]:          0 :                     if (!bValid)
    4278                 :            :                     {
    4279                 :          0 :                         pRangeData = pName;
    4280                 :          0 :                         rChanged = true;
    4281                 :            :                     }
    4282                 :            :                 }
    4283                 :            :             }
    4284                 :            :         }
    4285                 :         46 :         return pRangeData;
    4286                 :            :     }
    4287                 :            :     else
    4288                 :            :     {
    4289                 :            : /*
    4290                 :            :  * Set SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE to 1 if we wanted to preserve as
    4291                 :            :  * many shared formulas as possible instead of replacing them with direct code.
    4292                 :            :  * Note that this may produce shared formula usage Excel doesn't understand,
    4293                 :            :  * which would have to be adapted for in the export filter. Advisable as a long
    4294                 :            :  * term goal, since it could decrease memory footprint.
    4295                 :            :  */
    4296                 :            : #define SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE 0
    4297                 :         18 :         ScRangeData* pRangeData = NULL;
    4298                 :            :         ScToken* t;
    4299                 :         18 :         pArr->Reset();
    4300         [ +  + ]:         36 :         while( (t = static_cast<ScToken*>(pArr->GetNextReferenceOrName())) != NULL )
    4301                 :            :         {
    4302         [ -  + ]:         18 :             if( t->GetOpCode() == ocName )
    4303                 :            :             {
    4304                 :          0 :                 ScRangeData* pName = GetRangeData( *t);
    4305 [ #  # ][ #  # ]:          0 :                 if (pName && pName->HasType(RT_SHAREDMOD))
                 [ #  # ]
    4306                 :            :                 {
    4307                 :          0 :                     pRangeData = pName;     // maybe need a replacement of shared with own code
    4308                 :            : #if ! SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE
    4309                 :          0 :                     rChanged = true;
    4310                 :            : #endif
    4311                 :            :                 }
    4312                 :            :             }
    4313         [ +  - ]:         18 :             else if( t->GetType() != svIndex )  // it may be a DB area!!!
    4314                 :            :             {
    4315                 :         18 :                 t->CalcAbsIfRel( rOldPos );
    4316      [ -  +  + ]:         18 :                 switch (t->GetType())
    4317                 :            :                 {
    4318                 :            :                     case svExternalSingleRef:
    4319                 :            :                     case svExternalDoubleRef:
    4320                 :            :                         // External references never change their positioning
    4321                 :            :                         // nor point to parts that will be removed or expanded.
    4322                 :            :                         // In fact, calling ScRefUpdate::Update() for URM_MOVE
    4323                 :            :                         // may have negative side effects. Simply adapt
    4324                 :            :                         // relative references to the new position.
    4325                 :          0 :                         t->CalcRelFromAbs( aPos);
    4326                 :          0 :                         break;
    4327                 :            :                     case svSingleRef:
    4328                 :            :                         {
    4329         [ +  + ]:         12 :                             if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
    4330                 :            :                                         aPos, r, nDx, nDy, nDz,
    4331                 :            :                                         SingleDoubleRefModifier(
    4332         [ +  - ]:         12 :                                             t->GetSingleRef()).Ref())
    4333                 :            :                                     != UR_NOTHING)
    4334                 :          6 :                                 rChanged = true;
    4335                 :            :                         }
    4336                 :         12 :                         break;
    4337                 :            :                     default:
    4338                 :            :                         {
    4339                 :          6 :                             ScComplexRefData& rRef = t->GetDoubleRef();
    4340                 :          6 :                             SCCOL nCols = rRef.Ref2.nCol - rRef.Ref1.nCol;
    4341                 :          6 :                             SCROW nRows = rRef.Ref2.nRow - rRef.Ref1.nRow;
    4342                 :          6 :                             SCTAB nTabs = rRef.Ref2.nTab - rRef.Ref1.nTab;
    4343         [ +  + ]:          6 :                             if ( ScRefUpdate::Update( pDoc, eUpdateRefMode,
    4344                 :            :                                         aPos, r, nDx, nDy, nDz,
    4345                 :          6 :                                         t->GetDoubleRef()) != UR_NOTHING)
    4346                 :            :                             {
    4347                 :          3 :                                 rChanged = true;
    4348 [ +  - ][ +  + ]:          3 :                                 if (rRef.Ref2.nCol - rRef.Ref1.nCol != nCols ||
                 [ -  + ]
    4349                 :            :                                         rRef.Ref2.nRow - rRef.Ref1.nRow != nRows ||
    4350                 :            :                                         rRef.Ref2.nTab - rRef.Ref1.nTab != nTabs)
    4351                 :         18 :                                     rRefSizeChanged = true;
    4352                 :            :                             }
    4353                 :            :                         }
    4354                 :            :                 }
    4355                 :            :             }
    4356                 :            :         }
    4357                 :            : #if SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE
    4358                 :            :         bool bEasyShared, bPosInRange;
    4359                 :            :         if ( !pRangeData )
    4360                 :            :             bEasyShared = bPosInRange = false;
    4361                 :            :         else
    4362                 :            :         {
    4363                 :            :             bEasyShared = true;
    4364                 :            :             bPosInRange = r.In( eUpdateRefMode == URM_MOVE ? aPos : rOldPos );
    4365                 :            :         }
    4366                 :            : #endif
    4367                 :         18 :         pArr->Reset();
    4368         [ +  + ]:         36 :         while ( (t = static_cast<ScToken*>(pArr->GetNextReferenceRPN())) != NULL )
    4369                 :            :         {
    4370         [ -  + ]:         18 :             if ( t->GetRef() != 1 )
    4371                 :            :             {
    4372                 :            : #if SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE
    4373                 :            :                 bEasyShared = false;
    4374                 :            : #endif
    4375                 :            :             }
    4376                 :            :             else
    4377                 :            :             {   // if nRefCnt>1 it's already updated in token code
    4378         [ #  # ]:          0 :                 if ( t->GetType() == svSingleRef )
    4379                 :            :                 {
    4380         [ #  # ]:          0 :                     ScSingleRefData& rRef = t->GetSingleRef();
    4381                 :          0 :                     SingleDoubleRefModifier aMod( rRef );
    4382         [ #  # ]:          0 :                     if ( rRef.IsRelName() )
    4383                 :            :                     {
    4384         [ #  # ]:          0 :                         ScRefUpdate::MoveRelWrap( pDoc, aPos, MAXCOL, MAXROW, aMod.Ref() );
    4385                 :          0 :                         rChanged = true;
    4386                 :            :                     }
    4387                 :            :                     else
    4388                 :            :                     {
    4389         [ #  # ]:          0 :                         aMod.Ref().CalcAbsIfRel( rOldPos );
    4390         [ #  # ]:          0 :                         if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
    4391         [ #  # ]:          0 :                                     r, nDx, nDy, nDz, aMod.Ref() )
    4392                 :            :                                 != UR_NOTHING
    4393                 :            :                             )
    4394                 :          0 :                             rChanged = true;
    4395                 :          0 :                     }
    4396                 :            : #if SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE
    4397                 :            :                     if ( bEasyShared )
    4398                 :            :                     {
    4399                 :            :                         const ScSingleRefData& rSRD = aMod.Ref().Ref1;
    4400                 :            :                         ScAddress aRef( rSRD.nCol, rSRD.nRow, rSRD.nTab );
    4401                 :            :                         if ( r.In( aRef ) != bPosInRange )
    4402                 :            :                             bEasyShared = false;
    4403                 :            :                     }
    4404                 :            : #endif
    4405                 :            :                 }
    4406                 :            :                 else
    4407                 :            :                 {
    4408                 :          0 :                     ScComplexRefData& rRef = t->GetDoubleRef();
    4409                 :          0 :                     SCCOL nCols = rRef.Ref2.nCol - rRef.Ref1.nCol;
    4410                 :          0 :                     SCROW nRows = rRef.Ref2.nRow - rRef.Ref1.nRow;
    4411                 :          0 :                     SCTAB nTabs = rRef.Ref2.nTab - rRef.Ref1.nTab;
    4412 [ #  # ][ #  # ]:          0 :                     if ( rRef.Ref1.IsRelName() || rRef.Ref2.IsRelName() )
                 [ #  # ]
    4413                 :            :                     {
    4414                 :          0 :                         ScRefUpdate::MoveRelWrap( pDoc, aPos, MAXCOL, MAXROW, rRef );
    4415                 :          0 :                         rChanged = true;
    4416                 :            :                     }
    4417                 :            :                     else
    4418                 :            :                     {
    4419         [ #  # ]:          0 :                         if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
    4420                 :          0 :                                     r, nDx, nDy, nDz, rRef )
    4421                 :            :                                 != UR_NOTHING
    4422                 :            :                             )
    4423                 :            :                         {
    4424                 :          0 :                             rChanged = true;
    4425 [ #  # ][ #  # ]:          0 :                             if (rRef.Ref2.nCol - rRef.Ref1.nCol != nCols ||
                 [ #  # ]
    4426                 :            :                                     rRef.Ref2.nRow - rRef.Ref1.nRow != nRows ||
    4427                 :            :                                     rRef.Ref2.nTab - rRef.Ref1.nTab != nTabs)
    4428                 :            :                             {
    4429                 :          0 :                                 rRefSizeChanged = true;
    4430                 :            : #if SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE
    4431                 :            :                                 bEasyShared = false;
    4432                 :            : #endif
    4433                 :            :                             }
    4434                 :            :                         }
    4435                 :            :                     }
    4436                 :            : #if SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE
    4437                 :            :                     if ( bEasyShared )
    4438                 :            :                     {
    4439                 :            :                         ScRange aRef( rRef.Ref1.nCol, rRef.Ref1.nRow,
    4440                 :            :                                 rRef.Ref1.nTab, rRef.Ref2.nCol, rRef.Ref2.nRow,
    4441                 :            :                                 rRef.Ref2.nTab );
    4442                 :            :                         if ( r.In( aRef ) != bPosInRange )
    4443                 :            :                             bEasyShared = false;
    4444                 :            :                     }
    4445                 :            : #endif
    4446                 :            :                 }
    4447                 :            :             }
    4448                 :            :         }
    4449                 :            : #if SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE
    4450                 :            :         if ( pRangeData )
    4451                 :            :         {
    4452                 :            :             if ( bEasyShared )
    4453                 :            :                 pRangeData = 0;
    4454                 :            :             else
    4455                 :            :                 rChanged = true;
    4456                 :            :         }
    4457                 :            : #endif
    4458                 :            : #undef SC_PRESERVE_SHARED_FORMULAS_IF_POSSIBLE
    4459                 :         64 :         return pRangeData;
    4460                 :            :     }
    4461                 :            : }
    4462                 :            : 
    4463                 :          3 : bool ScCompiler::UpdateNameReference(UpdateRefMode eUpdateRefMode,
    4464                 :            :                                      const ScRange& r,
    4465                 :            :                                      SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
    4466                 :            :                                      bool& rChanged, bool bSharedFormula, bool bLocal)
    4467                 :            : {
    4468                 :          3 :     bool bRelRef = false;   // set if relative reference
    4469                 :          3 :     rChanged = false;
    4470                 :          3 :     pArr->Reset();
    4471                 :            :     ScToken* t;
    4472         [ +  + ]:          6 :     while ( (t = static_cast<ScToken*>(pArr->GetNextReference())) != NULL )
    4473                 :            :     {
    4474         [ +  - ]:          3 :         SingleDoubleRefModifier aMod( *t );
    4475                 :          3 :         ScComplexRefData& rRef = aMod.Ref();
    4476                 :          6 :         bRelRef = rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() ||
    4477         [ -  + ]:          6 :             rRef.Ref1.IsTabRel();
           [ +  -  +  - ]
    4478 [ +  - ][ -  + ]:          3 :         if (!bRelRef && t->GetType() == svDoubleRef)
                 [ -  + ]
    4479                 :          0 :             bRelRef = rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() ||
    4480         [ #  # ]:          0 :                 rRef.Ref2.IsTabRel();
           [ #  #  #  # ]
    4481                 :          3 :         bool bUpdate = !rRef.Ref1.IsColRel() || !rRef.Ref1.IsRowRel() ||
    4482         [ #  # ]:          3 :             !rRef.Ref1.IsTabRel();
           [ -  +  #  # ]
    4483 [ -  + ][ #  # ]:          3 :         if (!bUpdate && t->GetType() == svDoubleRef)
                 [ -  + ]
    4484                 :          0 :             bUpdate = !rRef.Ref2.IsColRel() || !rRef.Ref2.IsRowRel() ||
    4485         [ #  # ]:          0 :                 !rRef.Ref2.IsTabRel();
           [ #  #  #  # ]
    4486 [ +  - ][ -  + ]:          3 :         if (!bSharedFormula && !bLocal)
    4487                 :            :         {
    4488                 :            :             // We cannot update names with sheet-relative references, they may
    4489                 :            :             // be used on other sheets as well and the resulting reference
    4490                 :            :             // would be wrong. This is a dilemma if col/row would need to be
    4491                 :            :             // updated for the current usage.
    4492 [ #  # ][ #  # ]:          0 :             bUpdate = bUpdate && !rRef.Ref1.IsTabRel() && !rRef.Ref2.IsTabRel();
                 [ #  # ]
    4493                 :            :         }
    4494         [ +  - ]:          3 :         if (bUpdate)
    4495                 :            :         {
    4496         [ +  - ]:          3 :             rRef.CalcAbsIfRel( aPos);
    4497         [ -  + ]:          3 :             if (ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos, r,
    4498         [ +  - ]:          3 :                         nDx, nDy, nDz, rRef, ScRefUpdate::ABSOLUTE)
    4499                 :            :                     != UR_NOTHING )
    4500                 :          0 :                 rChanged = true;
    4501                 :            :         }
    4502                 :          3 :     }
    4503                 :          3 :     return bRelRef;
    4504                 :            : }
    4505                 :            : 
    4506                 :            : 
    4507                 :          0 : void ScCompiler::UpdateSharedFormulaReference( UpdateRefMode eUpdateRefMode,
    4508                 :            :                                   const ScAddress& rOldPos, const ScRange& r,
    4509                 :            :                                   SCsCOL nDx, SCsROW nDy, SCsTAB nDz )
    4510                 :            : {
    4511         [ #  # ]:          0 :     if ( eUpdateRefMode == URM_COPY )
    4512                 :          0 :         return ;
    4513                 :            :     else
    4514                 :            :     {
    4515                 :            :         ScToken* t;
    4516                 :          0 :         pArr->Reset();
    4517         [ #  # ]:          0 :         while ( (t = static_cast<ScToken*>(pArr->GetNextReference())) != NULL )
    4518                 :            :         {
    4519         [ #  # ]:          0 :             if( t->GetType() != svIndex )   // it may be a DB area!!!
    4520                 :            :             {
    4521         [ #  # ]:          0 :                 t->CalcAbsIfRel( rOldPos );
    4522                 :            :                 // Absolute references have been already adjusted in the named
    4523                 :            :                 // shared formula itself prior to breaking the shared formula
    4524                 :            :                 // and calling this function. Don't readjust them again.
    4525         [ #  # ]:          0 :                 SingleDoubleRefModifier aMod( *t );
    4526                 :          0 :                 ScComplexRefData& rRef = aMod.Ref();
    4527                 :          0 :                 ScComplexRefData aBkp = rRef;
    4528                 :            :                 ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
    4529         [ #  # ]:          0 :                                             r, nDx, nDy, nDz, rRef );
    4530                 :            :                 // restore absolute parts
    4531         [ #  # ]:          0 :                 if ( !aBkp.Ref1.IsColRel() )
    4532                 :            :                 {
    4533                 :          0 :                     rRef.Ref1.nCol = aBkp.Ref1.nCol;
    4534                 :          0 :                     rRef.Ref1.nRelCol = aBkp.Ref1.nRelCol;
    4535                 :          0 :                     rRef.Ref1.SetColDeleted( aBkp.Ref1.IsColDeleted() );
    4536                 :            :                 }
    4537         [ #  # ]:          0 :                 if ( !aBkp.Ref1.IsRowRel() )
    4538                 :            :                 {
    4539                 :          0 :                     rRef.Ref1.nRow = aBkp.Ref1.nRow;
    4540                 :          0 :                     rRef.Ref1.nRelRow = aBkp.Ref1.nRelRow;
    4541                 :          0 :                     rRef.Ref1.SetRowDeleted( aBkp.Ref1.IsRowDeleted() );
    4542                 :            :                 }
    4543         [ #  # ]:          0 :                 if ( !aBkp.Ref1.IsTabRel() )
    4544                 :            :                 {
    4545                 :          0 :                     rRef.Ref1.nTab = aBkp.Ref1.nTab;
    4546                 :          0 :                     rRef.Ref1.nRelTab = aBkp.Ref1.nRelTab;
    4547                 :          0 :                     rRef.Ref1.SetTabDeleted( aBkp.Ref1.IsTabDeleted() );
    4548                 :            :                 }
    4549         [ #  # ]:          0 :                 if ( t->GetType() == svDoubleRef )
    4550                 :            :                 {
    4551         [ #  # ]:          0 :                     if ( !aBkp.Ref2.IsColRel() )
    4552                 :            :                     {
    4553                 :          0 :                         rRef.Ref2.nCol = aBkp.Ref2.nCol;
    4554                 :          0 :                         rRef.Ref2.nRelCol = aBkp.Ref2.nRelCol;
    4555                 :          0 :                         rRef.Ref2.SetColDeleted( aBkp.Ref2.IsColDeleted() );
    4556                 :            :                     }
    4557         [ #  # ]:          0 :                     if ( !aBkp.Ref2.IsRowRel() )
    4558                 :            :                     {
    4559                 :          0 :                         rRef.Ref2.nRow = aBkp.Ref2.nRow;
    4560                 :          0 :                         rRef.Ref2.nRelRow = aBkp.Ref2.nRelRow;
    4561                 :          0 :                         rRef.Ref2.SetRowDeleted( aBkp.Ref2.IsRowDeleted() );
    4562                 :            :                     }
    4563         [ #  # ]:          0 :                     if ( !aBkp.Ref2.IsTabRel() )
    4564                 :            :                     {
    4565                 :          0 :                         rRef.Ref2.nTab = aBkp.Ref2.nTab;
    4566                 :          0 :                         rRef.Ref2.nRelTab = aBkp.Ref2.nRelTab;
    4567                 :          0 :                         rRef.Ref2.SetTabDeleted( aBkp.Ref2.IsTabDeleted() );
    4568                 :            :                     }
    4569                 :          0 :                 }
    4570                 :            :             }
    4571                 :            :         }
    4572                 :            :     }
    4573                 :            : }
    4574                 :            : 
    4575                 :            : 
    4576                 :         26 : ScRangeData* ScCompiler::UpdateInsertTab( SCTAB nTable, bool bIsName , SCTAB nNewSheets)
    4577                 :            : {
    4578                 :         26 :     ScRangeData* pRangeData = NULL;
    4579                 :         26 :     SCTAB nPosTab = aPos.Tab();     // _after_ incremented!
    4580         [ +  + ]:         26 :     SCTAB nOldPosTab = ((nPosTab > nTable) ? (nPosTab - nNewSheets) : nPosTab);
    4581                 :         26 :     bool bIsRel = false;
    4582                 :            :     ScToken* t;
    4583                 :         26 :     pArr->Reset();
    4584         [ +  + ]:         26 :     if (bIsName)
    4585                 :          8 :         t = static_cast<ScToken*>(pArr->GetNextReference());
    4586                 :            :     else
    4587                 :         18 :         t = static_cast<ScToken*>(pArr->GetNextReferenceOrName());
    4588         [ +  + ]:         70 :     while( t )
    4589                 :            :     {
    4590         [ -  + ]:         44 :         if( t->GetOpCode() == ocName )
    4591                 :            :         {
    4592         [ #  # ]:          0 :             if (!bIsName)
    4593                 :            :             {
    4594                 :          0 :                 ScRangeData* pName = GetRangeData( *t);
    4595 [ #  # ][ #  # ]:          0 :                 if (pName && pName->HasType(RT_SHAREDMOD))
                 [ #  # ]
    4596                 :          0 :                     pRangeData = pName;
    4597                 :            :             }
    4598                 :            :         }
    4599         [ +  - ]:         44 :         else if( t->GetType() != svIndex )  // it may be a DB area!!!
    4600                 :            :         {
    4601 [ +  + ][ +  + ]:         44 :             if ( !(bIsName && t->GetSingleRef().IsTabRel()) )
                 [ +  + ]
    4602                 :            :             {   // of names only adjust absolute references
    4603                 :         42 :                 ScSingleRefData& rRef = t->GetSingleRef();
    4604         [ +  + ]:         42 :                 if ( rRef.IsTabRel() )
    4605                 :            :                 {
    4606                 :         36 :                     rRef.nTab = rRef.nRelTab + nOldPosTab;
    4607         [ -  + ]:         36 :                     if ( rRef.nTab < 0 )
    4608                 :          0 :                         rRef.nTab = sal::static_int_cast<SCsTAB>( rRef.nTab + pDoc->GetTableCount() );  // was a wrap
    4609                 :            :                 }
    4610         [ +  - ]:         42 :                 if (nTable <= rRef.nTab)
    4611                 :         42 :                     rRef.nTab += nNewSheets;
    4612                 :         42 :                 rRef.nRelTab = rRef.nTab - nPosTab;
    4613                 :            :             }
    4614                 :            :             else
    4615                 :          2 :                 bIsRel = true;
    4616         [ -  + ]:         44 :             if ( t->GetType() == svDoubleRef )
    4617                 :            :             {
    4618 [ #  # ][ #  # ]:          0 :                 if ( !(bIsName && t->GetDoubleRef().Ref2.IsTabRel()) )
                 [ #  # ]
    4619                 :            :                 {   // of names only adjust absolute references
    4620                 :          0 :                     ScSingleRefData& rRef = t->GetDoubleRef().Ref2;
    4621         [ #  # ]:          0 :                     if ( rRef.IsTabRel() )
    4622                 :            :                     {
    4623                 :          0 :                         rRef.nTab = rRef.nRelTab + nOldPosTab;
    4624         [ #  # ]:          0 :                         if ( rRef.nTab < 0 )
    4625                 :          0 :                             rRef.nTab = sal::static_int_cast<SCsTAB>( rRef.nTab + pDoc->GetTableCount() );  // was a wrap
    4626                 :            :                     }
    4627         [ #  # ]:          0 :                     if (nTable <= rRef.nTab)
    4628                 :          0 :                         rRef.nTab += nNewSheets;
    4629                 :          0 :                     rRef.nRelTab = rRef.nTab - nPosTab;
    4630                 :            :                 }
    4631                 :            :                 else
    4632                 :          0 :                     bIsRel = true;
    4633                 :            :             }
    4634 [ +  + ][ +  + ]:         44 :             if ( bIsName && bIsRel )
    4635                 :          2 :                 pRangeData = (ScRangeData*) this;   // not dereferenced in rangenam
    4636                 :            :         }
    4637         [ +  + ]:         44 :         if (bIsName)
    4638                 :          8 :             t = static_cast<ScToken*>(pArr->GetNextReference());
    4639                 :            :         else
    4640                 :         36 :             t = static_cast<ScToken*>(pArr->GetNextReferenceOrName());
    4641                 :            :     }
    4642         [ +  + ]:         26 :     if ( !bIsName )
    4643                 :            :     {
    4644                 :         18 :         pArr->Reset();
    4645         [ +  + ]:         54 :         while ( (t = static_cast<ScToken*>(pArr->GetNextReferenceRPN())) != NULL )
    4646                 :            :         {
    4647         [ -  + ]:         36 :             if ( t->GetRef() == 1 )
    4648                 :            :             {
    4649                 :          0 :                 ScSingleRefData& rRef1 = t->GetSingleRef();
    4650 [ #  # ][ #  # ]:          0 :                 if ( !(rRef1.IsRelName() && rRef1.IsTabRel()) )
                 [ #  # ]
    4651                 :            :                 {   // of names only adjust absolute references
    4652         [ #  # ]:          0 :                     if ( rRef1.IsTabRel() )
    4653                 :            :                     {
    4654                 :          0 :                         rRef1.nTab = rRef1.nRelTab + nOldPosTab;
    4655         [ #  # ]:          0 :                         if ( rRef1.nTab < 0 )
    4656                 :          0 :                             rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + pDoc->GetTableCount() );  // was a wrap
    4657                 :            :                     }
    4658         [ #  # ]:          0 :                     if (nTable <= rRef1.nTab)
    4659                 :          0 :                         rRef1.nTab += nNewSheets;
    4660                 :          0 :                     rRef1.nRelTab = rRef1.nTab - nPosTab;
    4661                 :            :                 }
    4662         [ #  # ]:          0 :                 if ( t->GetType() == svDoubleRef )
    4663                 :            :                 {
    4664                 :          0 :                     ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
    4665 [ #  # ][ #  # ]:          0 :                     if ( !(rRef2.IsRelName() && rRef2.IsTabRel()) )
                 [ #  # ]
    4666                 :            :                     {   // of names only adjust absolute references
    4667         [ #  # ]:          0 :                         if ( rRef2.IsTabRel() )
    4668                 :            :                         {
    4669                 :          0 :                             rRef2.nTab = rRef2.nRelTab + nOldPosTab;
    4670         [ #  # ]:          0 :                             if ( rRef2.nTab < 0 )
    4671                 :          0 :                                 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + pDoc->GetTableCount() );  // was a wrap
    4672                 :            :                         }
    4673         [ #  # ]:          0 :                         if (nTable <= rRef2.nTab)
    4674                 :          0 :                             rRef2.nTab += nNewSheets;
    4675                 :          0 :                         rRef2.nRelTab = rRef2.nTab - nPosTab;
    4676                 :            :                     }
    4677                 :            :                 }
    4678                 :            :             }
    4679                 :            :         }
    4680                 :            :     }
    4681                 :         26 :     return pRangeData;
    4682                 :            : }
    4683                 :            : 
    4684                 :        105 : ScRangeData* ScCompiler::UpdateDeleteTab(SCTAB nTable, bool /* bIsMove */, bool bIsName,
    4685                 :            :                                  bool& rChanged, SCTAB nSheets)
    4686                 :            : {
    4687                 :        105 :     ScRangeData* pRangeData = NULL;
    4688                 :            :     SCTAB nTab, nTab2;
    4689                 :        105 :     SCTAB nPosTab = aPos.Tab();          // _after_ decremented!
    4690         [ +  + ]:        105 :     SCTAB nOldPosTab = ((nPosTab >= nTable) ? (nPosTab + nSheets) : nPosTab);
    4691                 :        105 :     rChanged = false;
    4692                 :        105 :     bool bIsRel = false;
    4693                 :            :     ScToken* t;
    4694                 :        105 :     pArr->Reset();
    4695         [ +  + ]:        105 :     if (bIsName)
    4696                 :         29 :         t = static_cast<ScToken*>(pArr->GetNextReference());
    4697                 :            :     else
    4698                 :         76 :         t = static_cast<ScToken*>(pArr->GetNextReferenceOrName());
    4699         [ +  + ]:        254 :     while( t )
    4700                 :            :     {
    4701         [ +  + ]:        149 :         if( t->GetOpCode() == ocName )
    4702                 :            :         {
    4703         [ +  - ]:         20 :             if (!bIsName)
    4704                 :            :             {
    4705                 :         20 :                 ScRangeData* pName = GetRangeData( *t);
    4706 [ -  + ][ -  + ]:         20 :                 if (pName && pName->HasType(RT_SHAREDMOD))
                 [ +  - ]
    4707                 :          0 :                     pRangeData = pName;
    4708                 :            :             }
    4709                 :         20 :             rChanged = true;
    4710                 :            :         }
    4711         [ +  - ]:        129 :         else if( t->GetType() != svIndex )  // it may be a DB area!!!
    4712                 :            :         {
    4713 [ +  + ][ +  - ]:        129 :             if ( !(bIsName && t->GetSingleRef().IsTabRel()) )
                 [ +  - ]
    4714                 :            :             {   // of names only adjust absolute references
    4715                 :        129 :                 ScSingleRefData& rRef = t->GetSingleRef();
    4716         [ +  + ]:        129 :                 if ( rRef.IsTabRel() )
    4717                 :        100 :                     nTab = rRef.nTab = rRef.nRelTab + nOldPosTab;
    4718                 :            :                 else
    4719                 :         29 :                     nTab = rRef.nTab;
    4720         [ +  + ]:        129 :                 if ( nTable < nTab )
    4721                 :            :                 {
    4722                 :         62 :                     rRef.nTab = nTab - nSheets;
    4723                 :         62 :                     rChanged = true;
    4724                 :            :                 }
    4725         [ +  + ]:         67 :                 else if ( nTable == nTab )
    4726                 :            :                 {
    4727         [ -  + ]:          9 :                     if ( t->GetType() == svDoubleRef )
    4728                 :            :                     {
    4729                 :          0 :                         ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
    4730         [ #  # ]:          0 :                         if ( rRef2.IsTabRel() )
    4731                 :          0 :                             nTab2 = rRef2.nRelTab + nOldPosTab;
    4732                 :            :                         else
    4733                 :          0 :                             nTab2 = rRef2.nTab;
    4734   [ #  #  #  # ]:          0 :                         if ( nTab == nTab2
                 [ #  # ]
    4735                 :          0 :                           || (nTab+nSheets) >= pDoc->GetTableCount() )
    4736                 :            :                         {
    4737                 :          0 :                             rRef.nTab = MAXTAB+1;
    4738                 :          0 :                             rRef.SetTabDeleted( true );
    4739                 :            :                         }
    4740                 :            :                         // else: nTab later points to what's nTable+1 now
    4741                 :            :                         // => area shrunk
    4742                 :            :                     }
    4743                 :            :                     else
    4744                 :            :                     {
    4745                 :          9 :                         rRef.nTab = MAXTAB+1;
    4746                 :          9 :                         rRef.SetTabDeleted( true );
    4747                 :            :                     }
    4748                 :          9 :                     rChanged = true;
    4749                 :            :                 }
    4750                 :        129 :                 rRef.nRelTab = rRef.nTab - nPosTab;
    4751                 :            :             }
    4752                 :            :             else
    4753                 :          0 :                 bIsRel = true;
    4754         [ +  + ]:        129 :             if ( t->GetType() == svDoubleRef )
    4755                 :            :             {
    4756 [ -  + ][ #  # ]:          6 :                 if ( !(bIsName && t->GetDoubleRef().Ref2.IsTabRel()) )
                 [ +  - ]
    4757                 :            :                 {   // of names only adjust absolute references
    4758                 :          6 :                     ScSingleRefData& rRef = t->GetDoubleRef().Ref2;
    4759         [ +  - ]:          6 :                     if ( rRef.IsTabRel() )
    4760                 :          6 :                         nTab = rRef.nTab = rRef.nRelTab + nOldPosTab;
    4761                 :            :                     else
    4762                 :          0 :                         nTab = rRef.nTab;
    4763         [ +  + ]:          6 :                     if ( nTable < nTab )
    4764                 :            :                     {
    4765                 :          3 :                         rRef.nTab = nTab - nSheets;
    4766                 :          3 :                         rChanged = true;
    4767                 :            :                     }
    4768         [ -  + ]:          3 :                     else if ( nTable == nTab )
    4769                 :            :                     {
    4770         [ #  # ]:          0 :                         if ( !t->GetDoubleRef().Ref1.IsTabDeleted() )
    4771                 :          0 :                             rRef.nTab = nTab - nSheets;   // shrink area
    4772                 :            :                         else
    4773                 :            :                         {
    4774                 :          0 :                             rRef.nTab = MAXTAB+1;
    4775                 :          0 :                             rRef.SetTabDeleted( true );
    4776                 :            :                         }
    4777                 :          0 :                         rChanged = true;
    4778                 :            :                     }
    4779                 :          6 :                     rRef.nRelTab = rRef.nTab - nPosTab;
    4780                 :            :                 }
    4781                 :            :                 else
    4782                 :          0 :                     bIsRel = true;
    4783                 :            :             }
    4784 [ +  + ][ -  + ]:        129 :             if ( bIsName && bIsRel )
    4785                 :          0 :                 pRangeData = (ScRangeData*) this;   // not dereferenced in rangenam
    4786                 :            :         }
    4787         [ +  + ]:        149 :         if (bIsName)
    4788                 :         29 :             t = static_cast<ScToken*>(pArr->GetNextReference());
    4789                 :            :         else
    4790                 :        120 :             t = static_cast<ScToken*>(pArr->GetNextReferenceOrName());
    4791                 :            :     }
    4792         [ +  + ]:        105 :     if ( !bIsName )
    4793                 :            :     {
    4794                 :         76 :         pArr->Reset();
    4795         [ +  + ]:        196 :         while ( (t = static_cast<ScToken*>(pArr->GetNextReferenceRPN())) != NULL )
    4796                 :            :         {
    4797         [ +  + ]:        120 :             if ( t->GetRef() == 1 )
    4798                 :            :             {
    4799                 :         20 :                 ScSingleRefData& rRef1 = t->GetSingleRef();
    4800 [ #  # ][ +  - ]:         20 :                 if ( !(rRef1.IsRelName() && rRef1.IsTabRel()) )
                 [ -  + ]
    4801                 :            :                 {   // of names only adjust absolute references
    4802         [ -  + ]:         20 :                     if ( rRef1.IsTabRel() )
    4803                 :          0 :                         nTab = rRef1.nTab = rRef1.nRelTab + nOldPosTab;
    4804                 :            :                     else
    4805                 :         20 :                         nTab = rRef1.nTab;
    4806         [ +  + ]:         20 :                     if ( nTable < nTab )
    4807                 :            :                     {
    4808                 :          4 :                         rRef1.nTab = nTab - nSheets;
    4809                 :          4 :                         rChanged = true;
    4810                 :            :                     }
    4811         [ -  + ]:         16 :                     else if ( nTable == nTab )
    4812                 :            :                     {
    4813         [ #  # ]:          0 :                         if ( t->GetType() == svDoubleRef )
    4814                 :            :                         {
    4815                 :          0 :                             ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
    4816         [ #  # ]:          0 :                             if ( rRef2.IsTabRel() )
    4817                 :          0 :                                 nTab2 = rRef2.nRelTab + nOldPosTab;
    4818                 :            :                             else
    4819                 :          0 :                                 nTab2 = rRef2.nTab;
    4820   [ #  #  #  # ]:          0 :                             if ( nTab == nTab2
                 [ #  # ]
    4821                 :          0 :                               || (nTab+1) >= pDoc->GetTableCount() )
    4822                 :            :                             {
    4823                 :          0 :                                 rRef1.nTab = MAXTAB+1;
    4824                 :          0 :                                 rRef1.SetTabDeleted( true );
    4825                 :            :                             }
    4826                 :            :                             // else: nTab later points to what's nTable+1 now
    4827                 :            :                             // => area shrunk
    4828                 :            :                         }
    4829                 :            :                         else
    4830                 :            :                         {
    4831                 :          0 :                             rRef1.nTab = MAXTAB+1;
    4832                 :          0 :                             rRef1.SetTabDeleted( true );
    4833                 :            :                         }
    4834                 :          0 :                         rChanged = true;
    4835                 :            :                     }
    4836                 :         20 :                     rRef1.nRelTab = rRef1.nTab - nPosTab;
    4837                 :            :                 }
    4838         [ -  + ]:         20 :                 if ( t->GetType() == svDoubleRef )
    4839                 :            :                 {
    4840                 :          0 :                     ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
    4841 [ #  # ][ #  # ]:          0 :                     if ( !(rRef2.IsRelName() && rRef2.IsTabRel()) )
                 [ #  # ]
    4842                 :            :                     {   // of names only adjust absolute references
    4843         [ #  # ]:          0 :                         if ( rRef2.IsTabRel() )
    4844                 :          0 :                             nTab = rRef2.nTab = rRef2.nRelTab + nOldPosTab;
    4845                 :            :                         else
    4846                 :          0 :                             nTab = rRef2.nTab;
    4847         [ #  # ]:          0 :                         if ( nTable < nTab )
    4848                 :            :                         {
    4849                 :          0 :                             rRef2.nTab = nTab - nSheets;
    4850                 :          0 :                             rChanged = true;
    4851                 :            :                         }
    4852         [ #  # ]:          0 :                         else if ( nTable == nTab )
    4853                 :            :                         {
    4854         [ #  # ]:          0 :                             if ( !rRef1.IsTabDeleted() )
    4855                 :          0 :                                 rRef2.nTab = nTab - nSheets;  // shrink area
    4856                 :            :                             else
    4857                 :            :                             {
    4858                 :          0 :                                 rRef2.nTab = MAXTAB+1;
    4859                 :          0 :                                 rRef2.SetTabDeleted( true );
    4860                 :            :                             }
    4861                 :          0 :                             rChanged = true;
    4862                 :            :                         }
    4863                 :          0 :                         rRef2.nRelTab = rRef2.nTab - nPosTab;
    4864                 :            :                     }
    4865                 :            :                 }
    4866                 :            :             }
    4867                 :            :         }
    4868                 :            :     }
    4869                 :        105 :     return pRangeData;
    4870                 :            : }
    4871                 :            : 
    4872                 :            : // aPos.Tab() must be already adjusted!
    4873                 :          3 : ScRangeData* ScCompiler::UpdateMoveTab( SCTAB nOldTab, SCTAB nNewTab,
    4874                 :            :         bool bIsName )
    4875                 :            : {
    4876                 :          3 :     ScRangeData* pRangeData = NULL;
    4877                 :            :     SCsTAB nTab;
    4878                 :            : 
    4879                 :            :     SCTAB nStart, nEnd;
    4880                 :            :     short nDir;                         // direction in which others move
    4881         [ -  + ]:          3 :     if ( nOldTab < nNewTab )
    4882                 :            :     {
    4883                 :          0 :         nDir = -1;
    4884                 :          0 :         nStart = nOldTab;
    4885                 :          0 :         nEnd = nNewTab;
    4886                 :            :     }
    4887                 :            :     else
    4888                 :            :     {
    4889                 :          3 :         nDir = 1;
    4890                 :          3 :         nStart = nNewTab;
    4891                 :          3 :         nEnd = nOldTab;
    4892                 :            :     }
    4893                 :          3 :     SCTAB nPosTab = aPos.Tab();        // current sheet
    4894                 :            :     SCTAB nOldPosTab;                  // previously it was this one
    4895         [ +  - ]:          3 :     if ( nPosTab == nNewTab )
    4896                 :          3 :         nOldPosTab = nOldTab;           // look, it's me!
    4897 [ #  # ][ #  # ]:          0 :     else if ( nPosTab < nStart || nEnd < nPosTab )
    4898                 :          0 :         nOldPosTab = nPosTab;           // wasn't moved
    4899                 :            :     else
    4900                 :          0 :         nOldPosTab = nPosTab - nDir;    // moved by one
    4901                 :            : 
    4902                 :          3 :     bool bIsRel = false;
    4903                 :            :     ScToken* t;
    4904                 :          3 :     pArr->Reset();
    4905         [ +  - ]:          3 :     if (bIsName)
    4906                 :          3 :         t = static_cast<ScToken*>(pArr->GetNextReference());
    4907                 :            :     else
    4908                 :          0 :         t = static_cast<ScToken*>(pArr->GetNextReferenceOrName());
    4909         [ +  + ]:          6 :     while( t )
    4910                 :            :     {
    4911         [ -  + ]:          3 :         if( t->GetOpCode() == ocName )
    4912                 :            :         {
    4913         [ #  # ]:          0 :             if (!bIsName)
    4914                 :            :             {
    4915                 :          0 :                 ScRangeData* pName = GetRangeData( *t);
    4916 [ #  # ][ #  # ]:          0 :                 if (pName && pName->HasType(RT_SHAREDMOD))
                 [ #  # ]
    4917                 :          0 :                     pRangeData = pName;
    4918                 :            :             }
    4919                 :            :         }
    4920         [ +  - ]:          3 :         else if( t->GetType() != svIndex )  // it may be a DB area!!!
    4921                 :            :         {
    4922                 :          3 :             ScSingleRefData& rRef1 = t->GetSingleRef();
    4923 [ +  - ][ +  - ]:          3 :             if ( !(bIsName && rRef1.IsTabRel()) )
                 [ +  - ]
    4924                 :            :             {   // of names only adjust absolute references
    4925         [ -  + ]:          3 :                 if ( rRef1.IsTabRel() )
    4926                 :          0 :                     nTab = rRef1.nRelTab + nOldPosTab;
    4927                 :            :                 else
    4928                 :          3 :                     nTab = rRef1.nTab;
    4929         [ -  + ]:          3 :                 if ( nTab == nOldTab )
    4930                 :          0 :                     rRef1.nTab = nNewTab;
    4931 [ +  - ][ +  - ]:          3 :                 else if ( nStart <= nTab && nTab <= nEnd )
    4932                 :          3 :                     rRef1.nTab = nTab + nDir;
    4933                 :          3 :                 rRef1.nRelTab = rRef1.nTab - nPosTab;
    4934                 :            :             }
    4935                 :            :             else
    4936                 :          0 :                 bIsRel = true;
    4937         [ +  - ]:          3 :             if ( t->GetType() == svDoubleRef )
    4938                 :            :             {
    4939                 :          3 :                 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
    4940 [ +  - ][ +  - ]:          3 :                 if ( !(bIsName && rRef2.IsTabRel()) )
                 [ +  - ]
    4941                 :            :                 {   // of names only adjust absolute references
    4942         [ -  + ]:          3 :                     if ( rRef2.IsTabRel() )
    4943                 :          0 :                         nTab = rRef2.nRelTab + nOldPosTab;
    4944                 :            :                     else
    4945                 :          3 :                         nTab = rRef2.nTab;
    4946         [ -  + ]:          3 :                     if ( nTab == nOldTab )
    4947                 :          0 :                         rRef2.nTab = nNewTab;
    4948 [ +  - ][ +  - ]:          3 :                     else if ( nStart <= nTab && nTab <= nEnd )
    4949                 :          3 :                         rRef2.nTab = nTab + nDir;
    4950                 :          3 :                     rRef2.nRelTab = rRef2.nTab - nPosTab;
    4951                 :            :                 }
    4952                 :            :                 else
    4953                 :          0 :                     bIsRel = true;
    4954                 :            :                 SCsTAB nTab1, nTab2;
    4955         [ -  + ]:          3 :                 if ( rRef1.IsTabRel() )
    4956                 :          0 :                     nTab1 = rRef1.nRelTab + nPosTab;
    4957                 :            :                 else
    4958                 :          3 :                     nTab1 = rRef1.nTab;
    4959         [ -  + ]:          3 :                 if ( rRef2.IsTabRel() )
    4960                 :          0 :                     nTab2 = rRef2.nRelTab + nPosTab;
    4961                 :            :                 else
    4962                 :          3 :                     nTab2 = rRef1.nTab;
    4963         [ -  + ]:          3 :                 if ( nTab2 < nTab1 )
    4964                 :            :                 {   // PutInOrder
    4965                 :          0 :                     rRef1.nTab = nTab2;
    4966                 :          0 :                     rRef2.nTab = nTab1;
    4967                 :          0 :                     rRef1.nRelTab = rRef1.nTab - nPosTab;
    4968                 :          0 :                     rRef2.nRelTab = rRef2.nTab - nPosTab;
    4969                 :            :                 }
    4970                 :            :             }
    4971 [ +  - ][ -  + ]:          3 :             if ( bIsName && bIsRel )
    4972                 :          0 :                 pRangeData = (ScRangeData*) this;   // not dereferenced in rangenam
    4973                 :            :         }
    4974         [ +  - ]:          3 :         if (bIsName)
    4975                 :          3 :             t = static_cast<ScToken*>(pArr->GetNextReference());
    4976                 :            :         else
    4977                 :          0 :             t = static_cast<ScToken*>(pArr->GetNextReferenceOrName());
    4978                 :            :     }
    4979         [ -  + ]:          3 :     if ( !bIsName )
    4980                 :            :     {
    4981                 :          0 :         SCsTAB nMaxTabMod = (SCsTAB) pDoc->GetTableCount();
    4982                 :          0 :         pArr->Reset();
    4983         [ #  # ]:          0 :         while ( (t = static_cast<ScToken*>(pArr->GetNextReferenceRPN())) != NULL )
    4984                 :            :         {
    4985         [ #  # ]:          0 :             if ( t->GetRef() == 1 )
    4986                 :            :             {
    4987                 :          0 :                 ScSingleRefData& rRef1 = t->GetSingleRef();
    4988 [ #  # ][ #  # ]:          0 :                 if ( rRef1.IsRelName() && rRef1.IsTabRel() )
                 [ #  # ]
    4989                 :            :                 {   // possibly wrap RelName, like lcl_MoveItWrap in refupdat.cxx
    4990                 :          0 :                     nTab = rRef1.nRelTab + nPosTab;
    4991         [ #  # ]:          0 :                     if ( nTab < 0 )
    4992                 :          0 :                         nTab = sal::static_int_cast<SCsTAB>( nTab + nMaxTabMod );
    4993         [ #  # ]:          0 :                     else if ( nTab > nMaxTab )
    4994                 :          0 :                         nTab = sal::static_int_cast<SCsTAB>( nTab - nMaxTabMod );
    4995                 :          0 :                     rRef1.nRelTab = nTab - nPosTab;
    4996                 :            :                 }
    4997                 :            :                 else
    4998                 :            :                 {
    4999         [ #  # ]:          0 :                     if ( rRef1.IsTabRel() )
    5000                 :          0 :                         nTab = rRef1.nRelTab + nOldPosTab;
    5001                 :            :                     else
    5002                 :          0 :                         nTab = rRef1.nTab;
    5003         [ #  # ]:          0 :                     if ( nTab == nOldTab )
    5004                 :          0 :                         rRef1.nTab = nNewTab;
    5005 [ #  # ][ #  # ]:          0 :                     else if ( nStart <= nTab && nTab <= nEnd )
    5006                 :          0 :                         rRef1.nTab = nTab + nDir;
    5007                 :          0 :                     rRef1.nRelTab = rRef1.nTab - nPosTab;
    5008                 :            :                 }
    5009         [ #  # ]:          0 :                 if( t->GetType() == svDoubleRef )
    5010                 :            :                 {
    5011                 :          0 :                     ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
    5012 [ #  # ][ #  # ]:          0 :                     if ( rRef2.IsRelName() && rRef2.IsTabRel() )
                 [ #  # ]
    5013                 :            :                     {   // possibly wrap RelName, like lcl_MoveItWrap in refupdat.cxx
    5014                 :          0 :                         nTab = rRef2.nRelTab + nPosTab;
    5015         [ #  # ]:          0 :                         if ( nTab < 0 )
    5016                 :          0 :                             nTab = sal::static_int_cast<SCsTAB>( nTab + nMaxTabMod );
    5017         [ #  # ]:          0 :                         else if ( nTab > nMaxTab )
    5018                 :          0 :                             nTab = sal::static_int_cast<SCsTAB>( nTab - nMaxTabMod );
    5019                 :          0 :                         rRef2.nRelTab = nTab - nPosTab;
    5020                 :            :                     }
    5021                 :            :                     else
    5022                 :            :                     {
    5023         [ #  # ]:          0 :                         if ( rRef2.IsTabRel() )
    5024                 :          0 :                             nTab = rRef2.nRelTab + nOldPosTab;
    5025                 :            :                         else
    5026                 :          0 :                             nTab = rRef2.nTab;
    5027         [ #  # ]:          0 :                         if ( nTab == nOldTab )
    5028                 :          0 :                             rRef2.nTab = nNewTab;
    5029 [ #  # ][ #  # ]:          0 :                         else if ( nStart <= nTab && nTab <= nEnd )
    5030                 :          0 :                             rRef2.nTab = nTab + nDir;
    5031                 :          0 :                         rRef2.nRelTab = rRef2.nTab - nPosTab;
    5032                 :            :                     }
    5033                 :            :                     SCsTAB nTab1, nTab2;
    5034         [ #  # ]:          0 :                     if ( rRef1.IsTabRel() )
    5035                 :          0 :                         nTab1 = rRef1.nRelTab + nPosTab;
    5036                 :            :                     else
    5037                 :          0 :                         nTab1 = rRef1.nTab;
    5038         [ #  # ]:          0 :                     if ( rRef2.IsTabRel() )
    5039                 :          0 :                         nTab2 = rRef2.nRelTab + nPosTab;
    5040                 :            :                     else
    5041                 :          0 :                         nTab2 = rRef1.nTab;
    5042         [ #  # ]:          0 :                     if ( nTab2 < nTab1 )
    5043                 :            :                     {   // PutInOrder
    5044                 :          0 :                         rRef1.nTab = nTab2;
    5045                 :          0 :                         rRef2.nTab = nTab1;
    5046                 :          0 :                         rRef1.nRelTab = rRef1.nTab - nPosTab;
    5047                 :          0 :                         rRef2.nRelTab = rRef2.nTab - nPosTab;
    5048                 :            :                     }
    5049                 :            :                 }
    5050                 :            :             }
    5051                 :            :         }
    5052                 :            :     }
    5053                 :          3 :     return pRangeData;
    5054                 :            : }
    5055                 :            : 
    5056                 :            : 
    5057                 :         11 : void ScCompiler::CreateStringFromExternal(rtl::OUStringBuffer& rBuffer, FormulaToken* pTokenP)
    5058                 :            : {
    5059                 :         11 :     FormulaToken* t = pTokenP;
    5060                 :         11 :     ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
    5061   [ -  +  -  - ]:         11 :     switch (t->GetType())
    5062                 :            :     {
    5063                 :            :         case svExternalName:
    5064                 :            :         {
    5065 [ #  # ][ #  # ]:          0 :             const OUString *pStr = pRefMgr->getExternalFileName(t->GetIndex());
    5066 [ #  # ][ #  # ]:          0 :             OUString aFileName = pStr ? *pStr : OUString(ScGlobal::GetRscString(STR_NO_NAME_REF));
                 [ #  # ]
    5067 [ #  # ][ #  # ]:          0 :             rBuffer.append(pConv->makeExternalNameStr( aFileName, t->GetString()));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    5068                 :            :         }
    5069                 :          0 :         break;
    5070                 :            :         case svExternalSingleRef:
    5071                 :            :             pConv->makeExternalRefStr(
    5072                 :         11 :                    rBuffer, *this, t->GetIndex(), t->GetString(), static_cast<ScToken*>(t)->GetSingleRef(), pRefMgr);
    5073                 :         11 :         break;
    5074                 :            :         case svExternalDoubleRef:
    5075                 :            :             pConv->makeExternalRefStr(
    5076                 :          0 :                         rBuffer, *this, t->GetIndex(), t->GetString(), static_cast<ScToken*>(t)->GetDoubleRef(), pRefMgr);
    5077                 :          0 :            break;
    5078                 :            :         default:
    5079                 :            :             // warning, not error, otherwise we may end up with a never
    5080                 :            :             // ending message box loop if this was the cursor cell to be redrawn.
    5081                 :            :             OSL_FAIL("ScCompiler::CreateStringFromToken: unknown type of ocExternalRef");
    5082                 :            :     }
    5083                 :         11 : }
    5084                 :            : 
    5085                 :          0 : void ScCompiler::CreateStringFromMatrix( rtl::OUStringBuffer& rBuffer,
    5086                 :            :                                            FormulaToken* pTokenP)
    5087                 :            : {
    5088         [ #  # ]:          0 :     const ScMatrix* pMatrix = static_cast<ScToken*>(pTokenP)->GetMatrix();
    5089                 :            :     SCSIZE nC, nMaxC, nR, nMaxR;
    5090                 :            : 
    5091         [ #  # ]:          0 :     pMatrix->GetDimensions( nMaxC, nMaxR);
    5092                 :            : 
    5093 [ #  # ][ #  # ]:          0 :     rBuffer.append( mxSymbols->getSymbol(ocArrayOpen) );
                 [ #  # ]
    5094         [ #  # ]:          0 :     for( nR = 0 ; nR < nMaxR ; nR++)
    5095                 :            :     {
    5096         [ #  # ]:          0 :         if( nR > 0)
    5097                 :            :         {
    5098 [ #  # ][ #  # ]:          0 :             rBuffer.append( mxSymbols->getSymbol(ocArrayRowSep) );
                 [ #  # ]
    5099                 :            :         }
    5100                 :            : 
    5101         [ #  # ]:          0 :         for( nC = 0 ; nC < nMaxC ; nC++)
    5102                 :            :         {
    5103         [ #  # ]:          0 :             if( nC > 0)
    5104                 :            :             {
    5105 [ #  # ][ #  # ]:          0 :                 rBuffer.append( mxSymbols->getSymbol(ocArrayColSep) );
                 [ #  # ]
    5106                 :            :             }
    5107                 :            : 
    5108 [ #  # ][ #  # ]:          0 :             if( pMatrix->IsValue( nC, nR ) )
    5109                 :            :             {
    5110 [ #  # ][ #  # ]:          0 :                 if (pMatrix->IsBoolean(nC, nR))
    5111 [ #  # ][ #  # ]:          0 :                     AppendBoolean(rBuffer, pMatrix->GetDouble(nC, nR) != 0.0);
    5112                 :            :                 else
    5113                 :            :                 {
    5114         [ #  # ]:          0 :                     sal_uInt16 nErr = pMatrix->GetError(nC, nR);
    5115         [ #  # ]:          0 :                     if (nErr)
    5116 [ #  # ][ #  # ]:          0 :                         rBuffer.append(ScGlobal::GetErrorString(nErr));
         [ #  # ][ #  # ]
    5117                 :            :                     else
    5118 [ #  # ][ #  # ]:          0 :                         AppendDouble(rBuffer, pMatrix->GetDouble(nC, nR));
    5119                 :            :                 }
    5120                 :            :             }
    5121 [ #  # ][ #  # ]:          0 :             else if( pMatrix->IsEmpty( nC, nR ) )
    5122                 :            :                 ;
    5123 [ #  # ][ #  # ]:          0 :             else if( pMatrix->IsString( nC, nR ) )
    5124 [ #  # ][ #  # ]:          0 :                 AppendString( rBuffer, pMatrix->GetString( nC, nR ) );
         [ #  # ][ #  # ]
    5125                 :            :         }
    5126                 :            :     }
    5127 [ #  # ][ #  # ]:          0 :     rBuffer.append( mxSymbols->getSymbol(ocArrayClose) );
                 [ #  # ]
    5128                 :          0 : }
    5129                 :            : 
    5130                 :      12382 : void ScCompiler::CreateStringFromSingleRef(rtl::OUStringBuffer& rBuffer,FormulaToken* _pTokenP)
    5131                 :            : {
    5132                 :      12382 :     const OpCode eOp = _pTokenP->GetOpCode();
    5133         [ +  - ]:      12382 :     ScSingleRefData& rRef = static_cast<ScToken*>(_pTokenP)->GetSingleRef();
    5134                 :            :     ScComplexRefData aRef;
    5135                 :      12382 :     aRef.Ref1 = aRef.Ref2 = rRef;
    5136         [ -  + ]:      12382 :     if ( eOp == ocColRowName )
    5137                 :            :     {
    5138         [ #  # ]:          0 :         rRef.CalcAbsIfRel( aPos );
    5139 [ #  # ][ #  # ]:          0 :         if ( pDoc->HasStringData( rRef.nCol, rRef.nRow, rRef.nTab ) )
    5140                 :            :         {
    5141         [ #  # ]:          0 :             String aStr;
    5142         [ #  # ]:          0 :             pDoc->GetString( rRef.nCol, rRef.nRow, rRef.nTab, aStr );
    5143         [ #  # ]:          0 :             EnQuote( aStr );
    5144 [ #  # ][ #  # ]:          0 :             rBuffer.append(aStr);
                 [ #  # ]
    5145                 :            :         }
    5146                 :            :         else
    5147                 :            :         {
    5148 [ #  # ][ #  # ]:          0 :             rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
                 [ #  # ]
    5149         [ #  # ]:          0 :             pConv->MakeRefStr (rBuffer, *this, aRef, true );
    5150                 :            :         }
    5151                 :            :     }
    5152                 :            :     else
    5153         [ +  - ]:      12382 :         pConv->MakeRefStr( rBuffer, *this, aRef, true );
    5154                 :      12382 : }
    5155                 :            : // -----------------------------------------------------------------------------
    5156                 :      12675 : void ScCompiler::CreateStringFromDoubleRef(rtl::OUStringBuffer& rBuffer,FormulaToken* _pTokenP)
    5157                 :            : {
    5158                 :      12675 :     pConv->MakeRefStr( rBuffer, *this, static_cast<ScToken*>(_pTokenP)->GetDoubleRef(), false );
    5159                 :      12675 : }
    5160                 :            : // -----------------------------------------------------------------------------
    5161                 :         16 : void ScCompiler::CreateStringFromIndex(rtl::OUStringBuffer& rBuffer,FormulaToken* _pTokenP)
    5162                 :            : {
    5163                 :         16 :     const OpCode eOp = _pTokenP->GetOpCode();
    5164                 :         16 :     rtl::OUStringBuffer aBuffer;
    5165      [ +  -  - ]:         16 :     switch ( eOp )
    5166                 :            :     {
    5167                 :            :         case ocName:
    5168                 :            :         {
    5169         [ +  - ]:         16 :             ScRangeData* pData = GetRangeData( *_pTokenP);
    5170         [ +  - ]:         16 :             if (pData)
    5171                 :            :             {
    5172         [ -  + ]:         16 :                 if (pData->HasType(RT_SHARED))
    5173         [ #  # ]:          0 :                     pData->UpdateSymbol( aBuffer, aPos, GetGrammar());
    5174                 :            :                 else
    5175         [ +  - ]:         16 :                     aBuffer.append(pData->GetName());
    5176                 :            :             }
    5177                 :            :         }
    5178                 :         16 :         break;
    5179                 :            :         case ocDBArea:
    5180                 :            :         {
    5181 [ #  # ][ #  # ]:          0 :             ScDBData* pDBData = pDoc->GetDBCollection()->getNamedDBs().findByIndex(_pTokenP->GetIndex());
         [ #  # ][ #  # ]
    5182         [ #  # ]:          0 :             if (pDBData)
    5183         [ #  # ]:          0 :                 aBuffer.append(pDBData->GetName());
    5184                 :            :         }
    5185                 :          0 :         break;
    5186                 :            :         default:
    5187                 :            :             ;   // nothing
    5188                 :            :     }
    5189         [ +  - ]:         16 :     if ( aBuffer.getLength() )
    5190 [ +  - ][ +  - ]:         16 :         rBuffer.append(aBuffer.makeStringAndClear());
    5191                 :            :     else
    5192 [ #  # ][ #  # ]:         16 :         rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
                 [ #  # ]
    5193                 :         16 : }
    5194                 :            : // -----------------------------------------------------------------------------
    5195                 :          0 : void ScCompiler::LocalizeString( String& rName )
    5196                 :            : {
    5197         [ #  # ]:          0 :     ::rtl::OUString aName(rName);
    5198 [ #  # ][ #  # ]:          0 :     ScGlobal::GetAddInCollection()->LocalizeString( aName );
    5199         [ #  # ]:          0 :     rName = aName;
    5200                 :          0 : }
    5201                 :            : // -----------------------------------------------------------------------------
    5202                 :            : 
    5203                 :            : // Put quotes around string if non-alphanumeric characters are contained,
    5204                 :            : // quote characters contained within are escaped by '\\'.
    5205                 :          0 : bool ScCompiler::EnQuote( String& rStr )
    5206                 :            : {
    5207                 :          0 :     sal_Int32 nType = ScGlobal::pCharClass->getStringType( rStr, 0, rStr.Len() );
    5208         [ #  # ]:          0 :     if ( !CharClass::isNumericType( nType )
           [ #  #  #  # ]
    5209                 :          0 :             && CharClass::isAlphaNumericType( nType ) )
    5210                 :          0 :         return false;
    5211                 :            : 
    5212                 :          0 :     xub_StrLen nPos = 0;
    5213         [ #  # ]:          0 :     while ( (nPos = rStr.Search( '\'', nPos)) != STRING_NOTFOUND )
    5214                 :            :     {
    5215                 :          0 :         rStr.Insert( '\\', nPos );
    5216                 :          0 :         nPos += 2;
    5217                 :            :     }
    5218                 :          0 :     rStr.Insert( '\'', 0 );
    5219                 :          0 :     rStr += '\'';
    5220                 :          0 :     return true;
    5221                 :            : }
    5222                 :            : 
    5223                 :          0 : sal_Unicode ScCompiler::GetNativeAddressSymbol( Convention::SpecialSymbolType eType ) const
    5224                 :            : {
    5225                 :          0 :     return pConv->getSpecialSymbol(eType);
    5226                 :            : }
    5227                 :            : 
    5228                 :          0 : void ScCompiler::fillAddInToken(::std::vector< ::com::sun::star::sheet::FormulaOpCodeMapEntry >& _rVec,bool _bIsEnglish) const
    5229                 :            : {
    5230                 :            :     // All known AddIn functions.
    5231                 :          0 :     sheet::FormulaOpCodeMapEntry aEntry;
    5232                 :          0 :     aEntry.Token.OpCode = ocExternal;
    5233                 :            : 
    5234         [ #  # ]:          0 :     ScUnoAddInCollection* pColl = ScGlobal::GetAddInCollection();
    5235         [ #  # ]:          0 :     const long nCount = pColl->GetFuncCount();
    5236         [ #  # ]:          0 :     for (long i=0; i < nCount; ++i)
    5237                 :            :     {
    5238         [ #  # ]:          0 :         const ScUnoAddInFuncData* pFuncData = pColl->GetFuncData(i);
    5239         [ #  # ]:          0 :         if (pFuncData)
    5240                 :            :         {
    5241         [ #  # ]:          0 :             if ( _bIsEnglish )
    5242                 :            :             {
    5243                 :          0 :                 ::rtl::OUString aName;
    5244 [ #  # ][ #  # ]:          0 :                 if (pFuncData->GetExcelName( LANGUAGE_ENGLISH_US, aName))
    5245                 :          0 :                     aEntry.Name = aName;
    5246                 :            :                 else
    5247                 :          0 :                     aEntry.Name = pFuncData->GetUpperName();
    5248                 :            :             }
    5249                 :            :             else
    5250                 :          0 :                 aEntry.Name = pFuncData->GetUpperLocal();
    5251         [ #  # ]:          0 :             aEntry.Token.Data <<= ::rtl::OUString( pFuncData->GetOriginalName());
    5252         [ #  # ]:          0 :             _rVec.push_back( aEntry);
    5253                 :            :         }
    5254                 :          0 :     }
    5255                 :            :     // FIXME: what about those old non-UNO AddIns?
    5256                 :          0 : }
    5257                 :            : // -----------------------------------------------------------------------------
    5258                 :          0 : bool ScCompiler::HandleSingleRef()
    5259                 :            : {
    5260         [ #  # ]:          0 :     ScSingleRefData& rRef = static_cast<ScToken*>(mpToken.get())->GetSingleRef();
    5261         [ #  # ]:          0 :     rRef.CalcAbsIfRel( aPos );
    5262         [ #  # ]:          0 :     if ( !rRef.Valid() )
    5263                 :            :     {
    5264         [ #  # ]:          0 :         SetError( errNoRef );
    5265                 :          0 :         return true;
    5266                 :            :     }
    5267                 :          0 :     SCCOL nCol = rRef.nCol;
    5268                 :          0 :     SCROW nRow = rRef.nRow;
    5269                 :          0 :     SCTAB nTab = rRef.nTab;
    5270                 :          0 :     ScAddress aLook( nCol, nRow, nTab );
    5271                 :          0 :     bool bColName = rRef.IsColRel();
    5272                 :          0 :     SCCOL nMyCol = aPos.Col();
    5273                 :          0 :     SCROW nMyRow = aPos.Row();
    5274                 :          0 :     bool bInList = false;
    5275                 :          0 :     bool bValidName = false;
    5276                 :            :     ScRangePairList* pRL = (bColName ?
    5277         [ #  # ]:          0 :         pDoc->GetColNameRanges() : pDoc->GetRowNameRanges());
    5278                 :          0 :     ScRange aRange;
    5279 [ #  # ][ #  # ]:          0 :     for ( size_t i = 0, nPairs = pRL->size(); i < nPairs; ++i )
    5280                 :            :     {
    5281         [ #  # ]:          0 :         ScRangePair* pR = (*pRL)[i];
    5282         [ #  # ]:          0 :         if ( pR->GetRange(0).In( aLook ) )
    5283                 :            :         {
    5284                 :          0 :             bInList = bValidName = true;
    5285                 :          0 :             aRange = pR->GetRange(1);
    5286         [ #  # ]:          0 :             if ( bColName )
    5287                 :            :             {
    5288                 :          0 :                 aRange.aStart.SetCol( nCol );
    5289                 :          0 :                 aRange.aEnd.SetCol( nCol );
    5290                 :            :             }
    5291                 :            :             else
    5292                 :            :             {
    5293                 :          0 :                 aRange.aStart.SetRow( nRow );
    5294                 :          0 :                 aRange.aEnd.SetRow( nRow );
    5295                 :            :             }
    5296                 :          0 :             break;  // for
    5297                 :            :         }
    5298                 :            :     }
    5299 [ #  # ][ #  # ]:          0 :     if ( !bInList && pDoc->GetDocOptions().IsLookUpColRowNames() )
         [ #  # ][ #  # ]
    5300                 :            :     {   // automagically or created by copying and NamePos isn't in list
    5301         [ #  # ]:          0 :         bool bString = pDoc->HasStringData( nCol, nRow, nTab );
    5302 [ #  # ][ #  # ]:          0 :         if ( !bString && !pDoc->GetCell( aLook ) )
         [ #  # ][ #  # ]
    5303                 :          0 :             bString = true;     // empty cell is ok
    5304         [ #  # ]:          0 :         if ( bString )
    5305                 :            :         {   //! coresponds with ScInterpreter::ScColRowNameAuto()
    5306                 :          0 :             bValidName = true;
    5307         [ #  # ]:          0 :             if ( bColName )
    5308                 :            :             {   // ColName
    5309                 :          0 :                 SCROW nStartRow = nRow + 1;
    5310         [ #  # ]:          0 :                 if ( nStartRow > MAXROW )
    5311                 :          0 :                     nStartRow = MAXROW;
    5312                 :          0 :                 SCROW nMaxRow = MAXROW;
    5313         [ #  # ]:          0 :                 if ( nMyCol == nCol )
    5314                 :            :                 {   // formula cell in same column
    5315         [ #  # ]:          0 :                     if ( nMyRow == nStartRow )
    5316                 :            :                     {   // take remainder under name cell
    5317                 :          0 :                         nStartRow++;
    5318         [ #  # ]:          0 :                         if ( nStartRow > MAXROW )
    5319                 :          0 :                             nStartRow = MAXROW;
    5320                 :            :                     }
    5321         [ #  # ]:          0 :                     else if ( nMyRow > nStartRow )
    5322                 :            :                     {   // from name cell down to formula cell
    5323                 :          0 :                         nMaxRow = nMyRow - 1;
    5324                 :            :                     }
    5325                 :            :                 }
    5326 [ #  # ][ #  # ]:          0 :                 for ( size_t i = 0, nPairs = pRL->size(); i < nPairs; ++i )
    5327                 :            :                 {   // next defined ColNameRange below limits row
    5328         [ #  # ]:          0 :                     ScRangePair* pR = (*pRL)[i];
    5329                 :          0 :                     const ScRange& rRange = pR->GetRange(1);
    5330 [ #  # ][ #  # ]:          0 :                     if ( rRange.aStart.Col() <= nCol && nCol <= rRange.aEnd.Col() )
                 [ #  # ]
    5331                 :            :                     {   // identical column range
    5332                 :          0 :                         SCROW nTmp = rRange.aStart.Row();
    5333 [ #  # ][ #  # ]:          0 :                         if ( nStartRow < nTmp && nTmp <= nMaxRow )
    5334                 :          0 :                             nMaxRow = nTmp - 1;
    5335                 :            :                     }
    5336                 :            :                 }
    5337                 :          0 :                 aRange.aStart.Set( nCol, nStartRow, nTab );
    5338                 :          0 :                 aRange.aEnd.Set( nCol, nMaxRow, nTab );
    5339                 :            :             }
    5340                 :            :             else
    5341                 :            :             {   // RowName
    5342                 :          0 :                 SCCOL nStartCol = nCol + 1;
    5343         [ #  # ]:          0 :                 if ( nStartCol > MAXCOL )
    5344                 :          0 :                     nStartCol = MAXCOL;
    5345                 :          0 :                 SCCOL nMaxCol = MAXCOL;
    5346         [ #  # ]:          0 :                 if ( nMyRow == nRow )
    5347                 :            :                 {   // formula cell in same row
    5348         [ #  # ]:          0 :                     if ( nMyCol == nStartCol )
    5349                 :            :                     {   // take remainder right from name cell
    5350                 :          0 :                         nStartCol++;
    5351         [ #  # ]:          0 :                         if ( nStartCol > MAXCOL )
    5352                 :          0 :                             nStartCol = MAXCOL;
    5353                 :            :                     }
    5354         [ #  # ]:          0 :                     else if ( nMyCol > nStartCol )
    5355                 :            :                     {   // from name cell right to formula cell
    5356                 :          0 :                         nMaxCol = nMyCol - 1;
    5357                 :            :                     }
    5358                 :            :                 }
    5359 [ #  # ][ #  # ]:          0 :                 for ( size_t i = 0, nPairs = pRL->size(); i < nPairs; ++i )
    5360                 :            :                 {   // next defined RowNameRange to the right limits column
    5361         [ #  # ]:          0 :                     ScRangePair* pR = (*pRL)[i];
    5362                 :          0 :                     const ScRange& rRange = pR->GetRange(1);
    5363 [ #  # ][ #  # ]:          0 :                     if ( rRange.aStart.Row() <= nRow && nRow <= rRange.aEnd.Row() )
                 [ #  # ]
    5364                 :            :                     {   // identical row range
    5365                 :          0 :                         SCCOL nTmp = rRange.aStart.Col();
    5366 [ #  # ][ #  # ]:          0 :                         if ( nStartCol < nTmp && nTmp <= nMaxCol )
    5367                 :          0 :                             nMaxCol = nTmp - 1;
    5368                 :            :                     }
    5369                 :            :                 }
    5370                 :          0 :                 aRange.aStart.Set( nStartCol, nRow, nTab );
    5371                 :          0 :                 aRange.aEnd.Set( nMaxCol, nRow, nTab );
    5372                 :            :             }
    5373                 :            :         }
    5374                 :            :     }
    5375         [ #  # ]:          0 :     if ( bValidName )
    5376                 :            :     {
    5377                 :            :         // And now the magic to distinguish between a range and a single
    5378                 :            :         // cell thereof, which is picked position-dependent of the formula
    5379                 :            :         // cell. If a direct neighbor is a binary operator (ocAdd, ...) a
    5380                 :            :         // SingleRef matching the column/row of the formula cell is
    5381                 :            :         // generated. A ocColRowName or ocIntersect as a neighbor results
    5382                 :            :         // in a range. Special case: if label is valid for a single cell, a
    5383                 :            :         // position independent SingleRef is generated.
    5384                 :          0 :         bool bSingle = (aRange.aStart == aRange.aEnd);
    5385                 :            :         bool bFound;
    5386         [ #  # ]:          0 :         if ( bSingle )
    5387                 :          0 :             bFound = true;
    5388                 :            :         else
    5389                 :            :         {
    5390         [ #  # ]:          0 :             FormulaToken* p1 = pArr->PeekPrevNoSpaces();
    5391         [ #  # ]:          0 :             FormulaToken* p2 = pArr->PeekNextNoSpaces();
    5392                 :            :             // begin/end of a formula => single
    5393         [ #  # ]:          0 :             OpCode eOp1 = p1 ? p1->GetOpCode() : static_cast<OpCode>( ocAdd );
    5394         [ #  # ]:          0 :             OpCode eOp2 = p2 ? p2->GetOpCode() : static_cast<OpCode>( ocAdd );
    5395 [ #  # ][ #  # ]:          0 :             if ( eOp1 != ocColRowName && eOp1 != ocIntersect
         [ #  # ][ #  # ]
    5396                 :            :                 && eOp2 != ocColRowName && eOp2 != ocIntersect )
    5397                 :            :             {
    5398 [ #  # ][ #  # ]:          0 :                 if (    (SC_OPCODE_START_BIN_OP <= eOp1 && eOp1 < SC_OPCODE_STOP_BIN_OP) ||
         [ #  # ][ #  # ]
    5399                 :            :                         (SC_OPCODE_START_BIN_OP <= eOp2 && eOp2 < SC_OPCODE_STOP_BIN_OP))
    5400                 :          0 :                     bSingle = true;
    5401                 :            :             }
    5402         [ #  # ]:          0 :             if ( bSingle )
    5403                 :            :             {   // column and/or row must match range
    5404         [ #  # ]:          0 :                 if ( bColName )
    5405                 :            :                 {
    5406                 :          0 :                     bFound = (aRange.aStart.Row() <= nMyRow
    5407 [ #  # ][ #  # ]:          0 :                         && nMyRow <= aRange.aEnd.Row());
    5408         [ #  # ]:          0 :                     if ( bFound )
    5409                 :          0 :                         aRange.aStart.SetRow( nMyRow );
    5410                 :            :                 }
    5411                 :            :                 else
    5412                 :            :                 {
    5413                 :          0 :                     bFound = (aRange.aStart.Col() <= nMyCol
    5414 [ #  # ][ #  # ]:          0 :                         && nMyCol <= aRange.aEnd.Col());
    5415         [ #  # ]:          0 :                     if ( bFound )
    5416                 :          0 :                         aRange.aStart.SetCol( nMyCol );
    5417                 :            :                 }
    5418                 :            :             }
    5419                 :            :             else
    5420                 :          0 :                 bFound = true;
    5421                 :            :         }
    5422         [ #  # ]:          0 :         if ( !bFound )
    5423         [ #  # ]:          0 :             SetError(errNoRef);
    5424         [ #  # ]:          0 :         else if ( !bCompileForFAP )
    5425                 :            :         {
    5426 [ #  # ][ #  # ]:          0 :             ScTokenArray* pNew = new ScTokenArray();
    5427         [ #  # ]:          0 :             if ( bSingle )
    5428                 :            :             {
    5429                 :            :                 ScSingleRefData aRefData;
    5430                 :          0 :                 aRefData.InitAddress( aRange.aStart );
    5431         [ #  # ]:          0 :                 if ( bColName )
    5432                 :          0 :                     aRefData.SetColRel( true );
    5433                 :            :                 else
    5434                 :          0 :                     aRefData.SetRowRel( true );
    5435         [ #  # ]:          0 :                 aRefData.CalcRelFromAbs( aPos );
    5436         [ #  # ]:          0 :                 pNew->AddSingleReference( aRefData );
    5437                 :            :             }
    5438                 :            :             else
    5439                 :            :             {
    5440                 :            :                 ScComplexRefData aRefData;
    5441                 :          0 :                 aRefData.InitRange( aRange );
    5442         [ #  # ]:          0 :                 if ( bColName )
    5443                 :            :                 {
    5444                 :          0 :                     aRefData.Ref1.SetColRel( true );
    5445                 :          0 :                     aRefData.Ref2.SetColRel( true );
    5446                 :            :                 }
    5447                 :            :                 else
    5448                 :            :                 {
    5449                 :          0 :                     aRefData.Ref1.SetRowRel( true );
    5450                 :          0 :                     aRefData.Ref2.SetRowRel( true );
    5451                 :            :                 }
    5452         [ #  # ]:          0 :                 aRefData.CalcRelFromAbs( aPos );
    5453         [ #  # ]:          0 :                 if ( bInList )
    5454         [ #  # ]:          0 :                     pNew->AddDoubleReference( aRefData );
    5455                 :            :                 else
    5456                 :            :                 {   // automagically
    5457 [ #  # ][ #  # ]:          0 :                     pNew->Add( new ScDoubleRefToken( aRefData, ocColRowNameAuto ) );
                 [ #  # ]
    5458                 :            :                 }
    5459                 :            :             }
    5460         [ #  # ]:          0 :             PushTokenArray( pNew, true );
    5461                 :          0 :             pNew->Reset();
    5462         [ #  # ]:          0 :             return GetToken();
    5463                 :            :         }
    5464                 :            :     }
    5465                 :            :     else
    5466         [ #  # ]:          0 :         SetError(errNoName);
    5467                 :          0 :     return true;
    5468                 :            : }
    5469                 :            : // -----------------------------------------------------------------------------
    5470                 :          6 : bool ScCompiler::HandleDbData()
    5471                 :            : {
    5472                 :          6 :     ScDBData* pDBData = pDoc->GetDBCollection()->getNamedDBs().findByIndex(mpToken->GetIndex());
    5473         [ -  + ]:          6 :     if ( !pDBData )
    5474                 :          0 :         SetError(errNoName);
    5475         [ +  - ]:          6 :     else if ( !bCompileForFAP )
    5476                 :            :     {
    5477                 :            :         ScComplexRefData aRefData;
    5478                 :          6 :         aRefData.InitFlags();
    5479                 :            :         pDBData->GetArea(   (SCTAB&) aRefData.Ref1.nTab,
    5480                 :            :                             (SCCOL&) aRefData.Ref1.nCol,
    5481                 :            :                             (SCROW&) aRefData.Ref1.nRow,
    5482                 :            :                             (SCCOL&) aRefData.Ref2.nCol,
    5483         [ +  - ]:          6 :                             (SCROW&) aRefData.Ref2.nRow);
    5484                 :          6 :         aRefData.Ref2.nTab    = aRefData.Ref1.nTab;
    5485         [ +  - ]:          6 :         aRefData.CalcRelFromAbs( aPos );
    5486 [ +  - ][ +  - ]:          6 :         ScTokenArray* pNew = new ScTokenArray();
    5487         [ +  - ]:          6 :         pNew->AddDoubleReference( aRefData );
    5488         [ +  - ]:          6 :         PushTokenArray( pNew, true );
    5489                 :          6 :         pNew->Reset();
    5490         [ +  - ]:          6 :         return GetToken();
    5491                 :            :     }
    5492                 :          6 :     return true;
    5493                 :            : }
    5494                 :            : 
    5495                 :            : // -----------------------------------------------------------------------------
    5496                 :          0 : FormulaTokenRef ScCompiler::ExtendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2, bool bReuseDoubleRef )
    5497                 :            : {
    5498                 :          0 :     return ScToken::ExtendRangeReference( rTok1, rTok2, aPos,bReuseDoubleRef );
    5499 [ +  - ][ +  - ]:        153 : }
    5500                 :            : 
    5501                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10