LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/tool - compiler.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 1210 2733 44.3 %
Date: 2012-12-27 Functions: 91 143 63.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10