summaryrefslogtreecommitdiff
path: root/binfilter/bf_sc/source/core/tool/sc_compiler.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'binfilter/bf_sc/source/core/tool/sc_compiler.cxx')
-rw-r--r--binfilter/bf_sc/source/core/tool/sc_compiler.cxx3240
1 files changed, 3240 insertions, 0 deletions
diff --git a/binfilter/bf_sc/source/core/tool/sc_compiler.cxx b/binfilter/bf_sc/source/core/tool/sc_compiler.cxx
new file mode 100644
index 000000000000..c238b6360f25
--- /dev/null
+++ b/binfilter/bf_sc/source/core/tool/sc_compiler.cxx
@@ -0,0 +1,3240 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifdef _MSC_VER
+#pragma hdrstop
+#endif
+
+// INCLUDE ---------------------------------------------------------------
+
+#include <bf_sfx2/app.hxx>
+#include <bf_sfx2/objsh.hxx>
+#include "bf_basic/sbmeth.hxx"
+#include "bf_basic/sbstar.hxx"
+#include <bf_svtools/zforlist.hxx>
+#include <tools/rcid.h>
+#include <tools/solar.h>
+#include <tools/urlobj.hxx>
+#include <rtl/math.hxx>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "rangenam.hxx"
+#include "dbcolect.hxx"
+#include "document.hxx"
+#include "callform.hxx"
+#include "addincol.hxx"
+#include "refupdat.hxx"
+#include "scresid.hxx"
+#include "bf_sc.hrc"
+#include "globstr.hrc"
+#include "cell.hxx"
+#include "dociter.hxx"
+#include "docoptio.hxx"
+namespace binfilter {
+
+
+/*N*/ String* ScCompiler::pSymbolTableNative = NULL;
+/*N*/ String* ScCompiler::pSymbolTableEnglish = NULL;
+/*N*/ USHORT ScCompiler::nAnzStrings = 0;
+/*N*/ ULONG* ScCompiler::pCharTable = 0;
+/*N*/ ScOpCodeHashMap* ScCompiler::pSymbolHashMapNative = NULL;
+/*N*/ ScOpCodeHashMap* ScCompiler::pSymbolHashMapEnglish = NULL;
+
+/*N*/ enum ScanState
+/*N*/ {
+/*N*/ ssGetChar,
+/*N*/ ssGetBool,
+/*N*/ ssGetString,
+/*N*/ ssSkipString,
+/*N*/ ssGetIdent,
+/*N*/ ssStop
+/*N*/ };
+
+/*N*/ struct ScArrayStack
+/*N*/ {
+/*N*/ ScArrayStack* pNext;
+/*N*/ ScTokenArray* pArr;
+/*N*/ BOOL bTemp;
+/*N*/ };
+
+/*N*/ static sal_Char* pInternal[ 5 ] = { "GAME", "SPEW", "TTT", "STARCALCTEAM", "ANTWORT" };
+
+
+/////////////////////////////////////////////////////////////////////////
+
+/*N*/ short lcl_GetRetFormat( OpCode eOpCode )
+/*N*/ {
+/*N*/ switch (eOpCode)
+/*N*/ {
+/*N*/ case ocEqual:
+/*N*/ case ocNotEqual:
+/*N*/ case ocLess:
+/*N*/ case ocGreater:
+/*N*/ case ocLessEqual:
+/*N*/ case ocGreaterEqual:
+/*N*/ case ocAnd:
+/*N*/ case ocOr:
+/*N*/ case ocNot:
+/*N*/ case ocTrue:
+/*N*/ case ocFalse:
+/*N*/ case ocIsEmpty:
+/*N*/ case ocIsString:
+/*N*/ case ocIsNonString:
+/*N*/ case ocIsLogical:
+/*N*/ case ocIsRef:
+/*N*/ case ocIsValue:
+/*N*/ case ocIsFormula:
+/*N*/ case ocIsNV:
+/*N*/ case ocIsErr:
+/*N*/ case ocIsError:
+/*N*/ case ocIsEven:
+/*N*/ case ocIsOdd:
+/*N*/ case ocExact:
+/*N*/ return NUMBERFORMAT_LOGICAL;
+/*N*/ case ocGetActDate:
+/*N*/ case ocGetDate:
+/*N*/ case ocEasterSunday :
+/*N*/ return NUMBERFORMAT_DATE;
+/*N*/ case ocGetActTime:
+/*N*/ return NUMBERFORMAT_DATETIME;
+/*N*/ case ocGetTime:
+/*N*/ return NUMBERFORMAT_TIME;
+/*N*/ case ocNBW:
+/*N*/ case ocBW:
+/*N*/ case ocDIA:
+/*N*/ case ocGDA:
+/*N*/ case ocGDA2:
+/*N*/ case ocVBD:
+/*N*/ case ocLIA:
+/*N*/ case ocRMZ:
+/*N*/ case ocZW:
+/*N*/ case ocZinsZ:
+/*N*/ case ocKapz:
+/*N*/ case ocKumZinsZ:
+/*N*/ case ocKumKapZ:
+/*N*/ return NUMBERFORMAT_CURRENCY;
+/*N*/ case ocZins:
+/*N*/ case ocIKV:
+/*N*/ case ocMIRR:
+/*N*/ case ocZGZ:
+/*N*/ case ocEffektiv:
+/*N*/ case ocNominal:
+/*N*/ case ocPercentSign:
+/*N*/ return NUMBERFORMAT_PERCENT;
+/*N*/ // case ocSum:
+/*N*/ // case ocSumSQ:
+/*N*/ // case ocProduct:
+/*N*/ // case ocAverage:
+/*N*/ // return -1;
+/*N*/ default:
+/*N*/ return NUMBERFORMAT_NUMBER;
+/*N*/ }
+/*N*/ return NUMBERFORMAT_NUMBER;
+/*N*/ }
+
+/////////////////////////////////////////////////////////////////////////
+
+/*N*/ class ScOpCodeList : public Resource // temp object fuer Resource
+/*N*/ {
+/*N*/ public:
+/*N*/ ScOpCodeList( USHORT, String[], ScOpCodeHashMap& );
+/*N*/ };
+
+/*N*/ ScOpCodeList::ScOpCodeList( USHORT nRID, String pSymbolTable[], ScOpCodeHashMap& rHashMap )
+/*N*/ :
+/*N*/ Resource( ScResId( nRID ) )
+/*N*/ {
+/*N*/ for (USHORT i = 0; i <= SC_OPCODE_LAST_OPCODE_ID; i++)
+/*N*/ {
+/*N*/ ScResId aRes(i);
+/*N*/ aRes.SetRT(RSC_STRING);
+/*N*/ if (IsAvailableRes(aRes))
+/*N*/ {
+/*N*/ pSymbolTable[i] = aRes;
+/*N*/ rHashMap.insert( ScOpCodeHashMap::value_type( pSymbolTable[i], (OpCode) i ) );
+/*N*/ }
+/*N*/ }
+/*N*/ FreeResource();
+/*N*/ }
+
+
+/*N*/ class ScCompilerRecursionGuard
+/*N*/ {
+/*N*/ private:
+/*N*/ short& rRecursion;
+/*N*/ public:
+/*N*/ ScCompilerRecursionGuard( short& rRec )
+/*N*/ : rRecursion( rRec ) { ++rRecursion; }
+/*N*/ ~ScCompilerRecursionGuard() { --rRecursion; }
+/*N*/ };
+
+
+/*N*/ void ScCompiler::Init()
+/*N*/ {
+/*N*/ pSymbolTableNative = new String[SC_OPCODE_LAST_OPCODE_ID+1];
+/*N*/ pSymbolHashMapNative = new ScOpCodeHashMap( SC_OPCODE_LAST_OPCODE_ID+1 );
+/*N*/ ScOpCodeList aOpCodeListNative( RID_SC_FUNCTION_NAMES, pSymbolTableNative,
+/*N*/ *pSymbolHashMapNative );
+/*N*/ nAnzStrings = SC_OPCODE_LAST_OPCODE_ID+1;
+/*N*/
+/*N*/ pCharTable = new ULONG [128];
+/*N*/ USHORT i;
+/*N*/ for (i = 0; i < 128; i++)
+/*N*/ pCharTable[i] = SC_COMPILER_C_ILLEGAL;
+/*N*/ /* */ pCharTable[32] = SC_COMPILER_C_CHAR_DONTCARE | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* ! */ pCharTable[33] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* " */ pCharTable[34] = SC_COMPILER_C_CHAR_STRING | SC_COMPILER_C_STRING_SEP;
+/*N*/ /* # */ pCharTable[35] = SC_COMPILER_C_WORD_SEP;
+/*N*/ /* $ */ pCharTable[36] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+/*N*/ /* % */ pCharTable[37] = SC_COMPILER_C_VALUE;
+/*N*/ /* & */ pCharTable[38] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* ' */ pCharTable[39] = SC_COMPILER_C_NAME_SEP;
+/*N*/ /* ( */ pCharTable[40] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* ) */ pCharTable[41] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* * */ pCharTable[42] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* + */ pCharTable[43] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
+/*N*/ /* , */ pCharTable[44] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE;
+/*N*/ /* - */ pCharTable[45] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
+/*N*/ /* . */ pCharTable[46] = SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE | SC_COMPILER_C_IDENT;
+/*N*/ /* / */ pCharTable[47] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ for (i = 48; i < 58; i++)
+/*N*/ /* 0-9 */ pCharTable[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;
+/*N*/ /* : */ pCharTable[58] = SC_COMPILER_C_WORD | SC_COMPILER_C_IDENT;
+/*N*/ /* ; */ pCharTable[59] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* < */ pCharTable[60] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* = */ pCharTable[61] = SC_COMPILER_C_CHAR | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* > */ pCharTable[62] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* ? */ pCharTable[63] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
+/*N*/ /* @ */ // FREI
+/*N*/ for (i = 65; i < 91; i++)
+/*N*/ /* A-Z */ pCharTable[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+/*N*/ /* [ */ // FREI
+/*N*/ /* \ */ // FREI
+/*N*/ /* ] */ // FREI
+/*N*/ /* ^ */ pCharTable[94] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
+/*N*/ /* _ */ pCharTable[95] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+/*N*/ /* ` */ // FREI
+/*N*/ for (i = 97; i < 123; i++)
+/*N*/ /* a-z */ pCharTable[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+/*N*/ /* { */ // FREI
+/*N*/ /* | */ // FREI
+/*N*/ /* } */ // FREI
+/*N*/ /* ~ */ // FREI
+/*N*/ /* 127 */ // FREI
+/*N*/ }
+
+/*N*/ void ScCompiler::DeInit()
+/*N*/ {
+/*N*/ if (pSymbolTableNative)
+/*N*/ {
+/*N*/ delete [] pSymbolTableNative;
+/*N*/ pSymbolTableNative = NULL;
+/*N*/ }
+/*N*/ if (pSymbolTableEnglish)
+/*N*/ {
+/*?*/ delete [] pSymbolTableEnglish;
+/*?*/ pSymbolTableEnglish = NULL;
+/*N*/ }
+/*N*/ if ( pSymbolHashMapNative )
+/*N*/ {
+/*?*/ pSymbolHashMapNative->clear();
+/*?*/ delete pSymbolHashMapNative;
+/*?*/ pSymbolHashMapNative = NULL;
+/*N*/ }
+/*N*/ if ( pSymbolHashMapEnglish )
+/*N*/ {
+/*?*/ pSymbolHashMapEnglish->clear();
+/*?*/ delete pSymbolHashMapEnglish;
+/*?*/ pSymbolHashMapEnglish = NULL;
+/*N*/ }
+/*N*/ delete [] pCharTable;
+/*N*/ pCharTable = NULL;
+/*N*/ }
+
+/*N*/ void ScCompiler::SetCompileEnglish( BOOL bCompileEnglish )
+/*N*/ {
+/*N*/ if ( bCompileEnglish )
+/*N*/ {
+/*N*/ if ( !pSymbolTableEnglish )
+/*N*/ {
+/*N*/ pSymbolTableEnglish = new String[SC_OPCODE_LAST_OPCODE_ID+1];
+/*N*/ pSymbolHashMapEnglish = new ScOpCodeHashMap( SC_OPCODE_LAST_OPCODE_ID+1 );
+/*N*/ ScOpCodeList aOpCodeListEnglish( RID_SC_FUNCTION_NAMES_ENGLISH,
+/*N*/ pSymbolTableEnglish, *pSymbolHashMapEnglish );
+/*N*/ }
+/*N*/ pSymbolTable = pSymbolTableEnglish;
+/*N*/ pSymbolHashMap = pSymbolHashMapEnglish;
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ pSymbolTable = pSymbolTableNative;
+/*N*/ pSymbolHashMap = pSymbolHashMapNative;
+/*N*/ }
+/*N*/ }
+
+//-----------------------Funktionen der Klasse ScCompiler----------------------
+
+/*N*/ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,
+/*N*/ const ScTokenArray& rArr )
+/*N*/ :
+/*N*/ aPos( rPos ),
+/*N*/ pSymbolTable( pSymbolTableNative ),
+/*N*/ pSymbolHashMap( pSymbolHashMapNative ),
+/*N*/ nRecursion(0),
+/*N*/ bAutoCorrect( FALSE ),
+/*N*/ bCorrected( FALSE ),
+/*N*/ bCompileForFAP( FALSE ),
+/*N*/ bIgnoreErrors( FALSE ),
+/*N*/ bCompileXML( FALSE ),
+/*N*/ bImportXML ( FALSE )
+/*N*/ {
+/*N*/ if (!nAnzStrings)
+/*?*/ Init();
+/*N*/ pArr = (ScTokenArray*) &rArr;
+/*N*/ pDoc = pDocument;
+/*N*/ nMaxTab = pDoc->GetTableCount() - 1;
+/*N*/ pStack = NULL;
+/*N*/ nNumFmt = NUMBERFORMAT_UNDEFINED;
+/*N*/ }
+
+/*N*/ ScCompiler::ScCompiler(ScDocument* pDocument, const ScAddress& rPos )
+/*N*/ :
+/*N*/ aPos( rPos ),
+/*N*/ pSymbolTable( pSymbolTableNative ),
+/*N*/ pSymbolHashMap( pSymbolHashMapNative ),
+/*N*/ nRecursion(0),
+/*N*/ bAutoCorrect( FALSE ),
+/*N*/ bCorrected( FALSE ),
+/*N*/ bCompileForFAP( FALSE ),
+/*N*/ bIgnoreErrors( FALSE ),
+/*N*/ bCompileXML( FALSE ),
+/*N*/ bImportXML ( FALSE )
+/*N*/ {
+/*N*/ if (!nAnzStrings)
+/*?*/ Init();
+/*N*/ pDoc = pDocument;
+/*N*/ nMaxTab = pDoc->GetTableCount() - 1;
+/*N*/ pStack = NULL;
+/*N*/ nNumFmt = NUMBERFORMAT_UNDEFINED;
+/*N*/ }
+
+
+/*N*/ void ScCompiler::MakeColStr( ::rtl::OUStringBuffer& rBuffer, USHORT nCol )
+/*N*/ {
+/*N*/ if ( nCol > MAXCOL )
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+/*N*/ else
+/*N*/ {
+/*N*/ if (nCol < 26)
+/*N*/ rBuffer.append( sal_Unicode('A' + (sal_uChar) nCol));
+/*N*/ else
+/*N*/ {
+/*?*/ USHORT nLoCol = nCol % 26;
+/*?*/ USHORT nHiCol = (nCol / 26) - 1;
+/*?*/ rBuffer.append( sal_Unicode('A' + (sal_uChar)nHiCol) );
+/*?*/ rBuffer.append( sal_Unicode('A' + (sal_uChar)nLoCol) );
+/*N*/ }
+/*N*/ }
+/*N*/ }
+
+/*N*/ void ScCompiler::MakeRowStr( ::rtl::OUStringBuffer& rBuffer, USHORT nRow )
+/*N*/ {
+/*N*/ if ( nRow > MAXROW )
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+/*N*/ else
+/*N*/ rBuffer.append(sal_Int32(nRow + 1));
+/*N*/ }
+
+/*N*/ String ScCompiler::MakeTabStr( USHORT nTab, String& aDoc )
+/*N*/ {
+/*N*/ String aString;
+/*N*/ if (!pDoc->GetName(nTab, aString))
+/*?*/ aString = ScGlobal::GetRscString(STR_NO_REF_TABLE);
+/*N*/ else
+/*N*/ {
+/*N*/ if ( aString.GetChar(0) == '\'' )
+/*N*/ { // "'Doc'#Tab"
+/*N*/ xub_StrLen nPos, nLen = 1;
+/*N*/ while( (nPos = aString.Search( '\'', nLen )) != STRING_NOTFOUND )
+/*N*/ nLen = nPos + 1;
+/*N*/ if ( aString.GetChar(nLen) == SC_COMPILER_FILE_TAB_SEP )
+/*N*/ {
+/*N*/ aDoc = aString.Copy( 0, nLen + 1 );
+/*N*/ aString.Erase( 0, nLen + 1 );
+/*N*/ aDoc = INetURLObject::decode( aDoc, INET_HEX_ESCAPE,
+/*N*/ INetURLObject::DECODE_UNAMBIGUOUS );
+/*N*/ }
+/*N*/ else
+/*?*/ aDoc.Erase();
+/*N*/ }
+/*N*/ else
+/*N*/ aDoc.Erase();
+/*N*/ CheckTabQuotes( aString );
+/*N*/ }
+/*N*/ aString += '.';
+/*N*/ return aString;
+/*N*/ }
+
+/*N*/ void ScCompiler::CheckTabQuotes( String& rString )
+/*N*/ {
+/*N*/ register const sal_Unicode* p = rString.GetBuffer();
+/*N*/ register const sal_Unicode* const pEnd = p + rString.Len();
+/*N*/ while ( p < pEnd )
+/*N*/ {
+/*N*/ if( !IsWordChar( *p ) )
+/*N*/ {
+/*N*/ rString.Insert( '\'', 0 );
+/*N*/ rString += '\'';
+/*N*/ return ;
+/*N*/ }
+/*N*/ p++;
+/*N*/ }
+/*N*/ if ( CharClass::isAsciiNumeric( rString ) )
+/*N*/ {
+/*N*/ rString.Insert( '\'', 0 );
+/*N*/ rString += '\'';
+/*N*/ }
+/*N*/ }
+
+/*N*/ void ScCompiler::MakeRefStr( ::rtl::OUStringBuffer& rBuffer, ComplRefData& rRef, BOOL bSingleRef )
+/*N*/ {
+/*N*/ if (bCompileXML)
+/*N*/ rBuffer.append(sal_Unicode('['));
+/*N*/ ComplRefData aRef( rRef );
+/*N*/ // falls abs/rel nicht separat: Relativ- in Abs-Referenzen wandeln!
+/*N*/ // AdjustReference( aRef.Ref1 );
+/*N*/ // if( !bSingleRef )
+/*N*/ // AdjustReference( aRef.Ref2 );
+/*N*/ aRef.Ref1.CalcAbsIfRel( aPos );
+/*N*/ if( !bSingleRef )
+/*N*/ aRef.Ref2.CalcAbsIfRel( aPos );
+/*N*/ if( aRef.Ref1.IsFlag3D() )
+/*N*/ {
+/*N*/ if (aRef.Ref1.IsTabDeleted())
+/*N*/ {
+/*?*/ if (!aRef.Ref1.IsTabRel())
+/*?*/ rBuffer.append(sal_Unicode('$'));
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+/*?*/ rBuffer.append(sal_Unicode('.'));
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ String aDoc;
+/*N*/ String aRefStr( MakeTabStr( aRef.Ref1.nTab, aDoc ) );
+/*N*/ rBuffer.append(aDoc);
+/*N*/ if (!aRef.Ref1.IsTabRel()) rBuffer.append(sal_Unicode('$'));
+/*N*/ rBuffer.append(aRefStr);
+/*N*/ }
+/*N*/ }
+/*N*/ else if (bCompileXML)
+/*N*/ rBuffer.append(sal_Unicode('.'));
+/*N*/ if (!aRef.Ref1.IsColRel())
+/*N*/ rBuffer.append(sal_Unicode('$'));
+/*N*/ if ( aRef.Ref1.IsColDeleted() )
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+/*N*/ else
+/*N*/ MakeColStr(rBuffer, aRef.Ref1.nCol );
+/*N*/ if (!aRef.Ref1.IsRowRel())
+/*N*/ rBuffer.append(sal_Unicode('$'));
+/*N*/ if ( aRef.Ref1.IsRowDeleted() )
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+/*N*/ else
+/*N*/ MakeRowStr( rBuffer, aRef.Ref1.nRow );
+/*N*/ if (!bSingleRef)
+/*N*/ {
+/*N*/ rBuffer.append(sal_Unicode(':'));
+/*N*/ if (aRef.Ref2.IsFlag3D() || aRef.Ref2.nTab != aRef.Ref1.nTab)
+/*N*/ {
+/*?*/ if (aRef.Ref2.IsTabDeleted())
+/*?*/ {
+/*?*/ if (!aRef.Ref2.IsTabRel())
+/*?*/ rBuffer.append(sal_Unicode('$'));
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+/*?*/ rBuffer.append(sal_Unicode('.'));
+/*?*/ }
+/*?*/ else
+/*?*/ {
+/*?*/ String aDoc;
+/*?*/ String aRefStr( MakeTabStr( aRef.Ref2.nTab, aDoc ) );
+/*?*/ rBuffer.append(aDoc);
+/*?*/ if (!aRef.Ref2.IsTabRel()) rBuffer.append(sal_Unicode('$'));
+/*?*/ rBuffer.append(aRefStr);
+/*?*/ }
+/*N*/ }
+/*N*/ else if (bCompileXML)
+/*N*/ rBuffer.append(sal_Unicode('.'));
+/*N*/ if (!aRef.Ref2.IsColRel())
+/*N*/ rBuffer.append(sal_Unicode('$'));
+/*N*/ if ( aRef.Ref2.IsColDeleted() )
+/*N*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+/*N*/ else
+/*N*/ MakeColStr( rBuffer, aRef.Ref2.nCol );
+/*N*/ if (!aRef.Ref2.IsRowRel())
+/*N*/ rBuffer.append(sal_Unicode('$'));
+/*N*/ if ( aRef.Ref2.IsRowDeleted() )
+/*N*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_REF_TABLE));
+/*N*/ else
+/*N*/ MakeRowStr( rBuffer, aRef.Ref2.nRow );
+/*N*/ }
+/*N*/ if (bCompileXML)
+/*N*/ rBuffer.append(sal_Unicode(']'));
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::SetError(USHORT nError)
+/*N*/ {
+/*N*/ if( !pArr->GetError() )
+/*N*/ pArr->nError = nError;
+/*N*/ }
+
+
+/*N*/ sal_Unicode* lcl_UnicodeStrNCpy( sal_Unicode* pDst, const sal_Unicode* pSrc, xub_StrLen nMax )
+/*N*/ {
+/*N*/ const sal_Unicode* const pStop = pDst + nMax;
+/*N*/ while ( *pSrc && pDst < pStop )
+/*N*/ {
+/*N*/ *pDst++ = *pSrc++;
+/*N*/ }
+/*N*/ *pDst = 0;
+/*N*/ return pDst;
+/*N*/ }
+
+
+//---------------------------------------------------------------------------
+// NextSymbol
+//---------------------------------------------------------------------------
+// Zerlegt die Formel in einzelne Symbole fuer die weitere
+// Verarbeitung (Turing-Maschine).
+//---------------------------------------------------------------------------
+// Ausgangs Zustand = GetChar
+//---------------+-------------------+-----------------------+---------------
+// Alter Zustand | gelesenes Zeichen | Aktion | Neuer Zustand
+//---------------+-------------------+-----------------------+---------------
+// GetChar | ;()+-*/^=& | Symbol=Zeichen | Stop
+// | <> | Symbol=Zeichen | GetBool
+// | $ Buchstabe | Symbol=Zeichen | GetWord
+// | Ziffer | Symbol=Zeichen | GetValue
+// | " | Keine | GetString
+// | Sonst | Keine | GetChar
+//---------------+-------------------+-----------------------+---------------
+// GetBool | => | Symbol=Symbol+Zeichen | Stop
+// | Sonst | Dec(CharPos) | Stop
+//---------------+-------------------+-----------------------+---------------
+// GetWord | SepSymbol | Dec(CharPos) | Stop
+// | ()+-*/^=<>&~ | |
+// | Leerzeichen | Dec(CharPos) | Stop
+// | $_:. | |
+// | Buchstabe,Ziffer | Symbol=Symbol+Zeichen | GetWord
+// | Sonst | Fehler | Stop
+//---------------|-------------------+-----------------------+---------------
+// GetValue | ;()*/^=<>& | |
+// | Leerzeichen | Dec(CharPos) | Stop
+// | Ziffer E+-%,. | Symbol=Symbol+Zeichen | GetValue
+// | Sonst | Fehler | Stop
+//---------------+-------------------+-----------------------+---------------
+// GetString | " | Keine | Stop
+// | Sonst | Symbol=Symbol+Zeichen | GetString
+//---------------+-------------------+-----------------------+---------------
+
+/*N*/ xub_StrLen ScCompiler::NextSymbol()
+/*N*/ {
+/*N*/ cSymbol[MAXSTRLEN-1] = 0; // Stopper
+/*N*/ sal_Unicode* pSym = cSymbol;
+/*N*/ const sal_Unicode* const pStart = aFormula.GetBuffer();
+/*N*/ const sal_Unicode* pSrc = pStart + nSrcPos;
+/*N*/ BOOL bi18n = FALSE;
+/*N*/ sal_Unicode c = *pSrc;
+/*N*/ sal_Unicode cLast = 0;
+/*N*/ BOOL bQuote = FALSE;
+/*N*/ ScanState eState = ssGetChar;
+/*N*/ xub_StrLen nSpaces = 0;
+/*N*/ // try to parse simple tokens before calling i18n parser
+/*N*/ while ((c != 0) && (eState != ssStop) )
+/*N*/ {
+/*N*/ pSrc++;
+/*N*/ ULONG nMask = GetCharTableFlags( c );
+/*N*/ switch (eState)
+/*N*/ {
+/*N*/ case ssGetChar :
+/*N*/ {
+/*N*/ if( nMask & SC_COMPILER_C_CHAR )
+/*N*/ {
+/*N*/ *pSym++ = c;
+/*N*/ eState = ssStop;
+/*N*/ }
+/*N*/ else if( nMask & SC_COMPILER_C_CHAR_BOOL )
+/*N*/ {
+/*N*/ *pSym++ = c;
+/*N*/ eState = ssGetBool;
+/*N*/ }
+/*N*/ else if( nMask & SC_COMPILER_C_CHAR_STRING )
+/*N*/ {
+/*N*/ *pSym++ = c;
+/*N*/ eState = ssGetString;
+/*N*/ }
+/*N*/ else if( nMask & SC_COMPILER_C_CHAR_DONTCARE )
+/*N*/ {
+/*N*/ nSpaces++;
+/*N*/ }
+/*N*/ else if( nMask & SC_COMPILER_C_CHAR_IDENT )
+/*N*/ { // try to get a simple ASCII identifier before calling
+/*N*/ // i18n, to gain performance during import
+/*N*/ *pSym++ = c;
+/*N*/ eState = ssGetIdent;
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ bi18n = TRUE;
+/*N*/ eState = ssStop;
+/*N*/ }
+/*N*/ }
+/*N*/ break;
+/*N*/ case ssGetIdent:
+/*N*/ {
+/*N*/ if ( nMask & SC_COMPILER_C_IDENT )
+/*N*/ { // this catches also $Sheet1.A1:A$2, for example
+/*N*/ *pSym++ = c;
+/*N*/ }
+/*N*/ else if ( 128 <= c || '\'' == c )
+/*N*/ { // High values need reparsing with i18n,
+/*N*/ // single quoted $'sheet' names too (otherwise we'd had to
+/*N*/ // implement everything twice).
+/*N*/ pSrc = pStart + nSrcPos + nSpaces;
+/*N*/ pSym = cSymbol;
+/*N*/ c = *pSrc;
+/*N*/ bi18n = TRUE;
+/*N*/ eState = ssStop;
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ pSrc--;
+/*N*/ eState = ssStop;
+/*N*/ }
+/*N*/ }
+/*N*/ break;
+/*N*/ case ssGetBool :
+/*N*/ {
+/*N*/ if( nMask & SC_COMPILER_C_BOOL )
+/*N*/ {
+/*N*/ *pSym++ = c;
+/*N*/ eState = ssStop;
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ pSrc--;
+/*N*/ eState = ssStop;
+/*N*/ }
+/*N*/ }
+/*N*/ break;
+/*N*/ case ssGetString :
+/*N*/ {
+/*N*/ if( nMask & SC_COMPILER_C_STRING_SEP )
+/*N*/ {
+/*N*/ if ( !bQuote )
+/*N*/ {
+/*N*/ if ( *pSrc == '"' )
+/*N*/ bQuote = TRUE; // "" => literal "
+/*N*/ else
+/*N*/ eState = ssStop;
+/*N*/ }
+/*N*/ else
+/*N*/ bQuote = FALSE;
+/*N*/ }
+/*N*/ if ( !bQuote )
+/*N*/ {
+/*N*/ if( pSym == &cSymbol[ MAXSTRLEN-1 ] )
+/*N*/ {
+/*N*/ SetError(errStringOverflow);
+/*N*/ eState = ssSkipString;
+/*N*/ }
+/*N*/ else
+/*N*/ *pSym++ = c;
+/*N*/ }
+/*N*/ }
+/*N*/ break;
+/*N*/ case ssSkipString:
+/*N*/ if( nMask & SC_COMPILER_C_STRING_SEP )
+/*N*/ eState = ssStop;
+/*N*/ break;
+/*N*/ }
+/*N*/ cLast = c;
+/*N*/ c = *pSrc;
+/*N*/ }
+/*N*/ if ( bi18n )
+/*N*/ {
+/*N*/ using namespace ::com::sun::star::i18n;
+/*N*/ nSrcPos += nSpaces;
+/*N*/ sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
+/*N*/ KParseTokens::ASC_UNDERSCORE | KParseTokens::ASC_DOLLAR;
+/*N*/ sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT |
+/*N*/ KParseTokens::ASC_COLON;
+/*N*/ // '?' allowed in range names because of Xcl :-/
+/*N*/ static const String aAddAllowed( '?' );
+/*N*/ String aSymbol;
+/*N*/ USHORT nErr = 0;
+/*N*/ do
+/*N*/ {
+/*N*/ bi18n = FALSE;
+/*N*/ // special case $'sheetname'
+/*N*/ if ( pStart[nSrcPos] == '$' && pStart[nSrcPos+1] == '\'' )
+/*N*/ aSymbol += pStart[nSrcPos++];
+/*N*/
+/*N*/ ParseResult aRes = ScGlobal::pCharClass->parseAnyToken( aFormula,
+/*N*/ nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
+/*N*/
+/*N*/ if ( !aRes.TokenType )
+/*N*/ SetError( nErr = errIllegalChar ); // parsed chars as string
+/*N*/ if ( aRes.EndPos <= nSrcPos )
+/*N*/ { // ?!?
+/*?*/ SetError( nErr = errIllegalChar );
+/*?*/ nSrcPos = aFormula.Len();
+/*?*/ aSymbol.Erase();
+/*?*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ aSymbol.Append( pStart + nSrcPos, aRes.EndPos - nSrcPos );
+/*N*/ nSrcPos = (xub_StrLen) aRes.EndPos;
+/*N*/ if ( aRes.TokenType & KParseType::SINGLE_QUOTE_NAME )
+/*N*/ { // special cases 'sheetname'. 'filename'#
+/*N*/ c = pStart[nSrcPos];
+/*N*/ bi18n = (c == '.' || c == SC_COMPILER_FILE_TAB_SEP);
+/*N*/ if ( bi18n )
+/*N*/ aSymbol += pStart[nSrcPos++];
+/*N*/ }
+/*N*/ else if ( aRes.TokenType & KParseType::IDENTNAME )
+/*N*/ { // special cases reference:[$]'sheetname'
+/*N*/ c = aSymbol.GetChar( aSymbol.Len()-1 );
+/*N*/ bi18n = ((c == ':' || c == '$') && pStart[nSrcPos] == '\'');
+/*N*/ }
+/*N*/ }
+/*N*/ } while ( bi18n && !nErr );
+/*N*/ xub_StrLen nLen = aSymbol.Len();
+/*N*/ if ( nLen >= MAXSTRLEN )
+/*N*/ {
+/*?*/ SetError( errStringOverflow );
+/*?*/ nLen = MAXSTRLEN-1;
+/*N*/ }
+/*N*/ lcl_UnicodeStrNCpy( cSymbol, aSymbol.GetBuffer(), nLen );
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ nSrcPos = pSrc - pStart;
+/*N*/ *pSym = 0;
+/*N*/ }
+/*N*/ if ( bAutoCorrect )
+/*N*/ aCorrectedSymbol = cSymbol;
+/*N*/ return nSpaces;
+/*N*/ }
+
+//---------------------------------------------------------------------------
+// Symbol in Token Umwandeln
+//---------------------------------------------------------------------------
+
+/*N*/ BOOL ScCompiler::IsOpCode( const String& rName )
+/*N*/ {
+/*N*/ ScOpCodeHashMap::const_iterator iLook( pSymbolHashMap->find( rName ) );
+/*N*/ BOOL bFound = (iLook != pSymbolHashMap->end());
+/*N*/ if (bFound)
+/*N*/ {
+/*N*/ ScRawToken aToken;
+/*N*/ aToken.SetOpCode( iLook->second );
+/*N*/ pRawToken = aToken.Clone();
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ USHORT nIndex;
+/*N*/ bFound = ScGlobal::GetFuncCollection()->SearchFunc(cSymbol, nIndex);
+/*N*/ if( bFound )
+/*N*/ {
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); /*N*/ ScRawToken aToken;
+/*N*/ /*?*/ aToken.SetExternal( cSymbol );
+/*N*/ /*?*/ pRawToken = aToken.Clone();
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ // bLocalFirst=FALSE for english
+/*N*/ String aIntName = ScGlobal::GetAddInCollection()->
+/*N*/ FindFunction( rName, ( pSymbolTable != pSymbolTableEnglish ) );
+/*N*/ if (aIntName.Len())
+/*N*/ {
+/*N*/ ScRawToken aToken;
+/*N*/ aToken.SetExternal( aIntName.GetBuffer() ); // international name
+/*N*/ pRawToken = aToken.Clone();
+/*N*/ bFound = TRUE;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ if ( bFound && pRawToken->GetOpCode() == ocSub &&
+/*N*/ (eLastOp == ocOpen || eLastOp == ocSep ||
+/*N*/ (eLastOp > ocEndDiv && eLastOp < ocEndBinOp /*ocEndUnOp*/)))
+/*N*/ pRawToken->NewOpCode( ocNegSub );
+/*N*/ return bFound;
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::IsOpCode2( const String& rName )
+/*N*/ {
+/*N*/ BOOL bFound = FALSE;
+/*N*/
+/*N*/ USHORT i = 0;
+/*N*/ for( i = ocInternalBegin; i <= ocInternalEnd && !bFound; i++ )
+/*N*/ bFound = rName.EqualsAscii( pInternal[ i-ocInternalBegin ] );
+/*N*/
+/*N*/ if (bFound)
+/*N*/ {
+/*?*/ ScRawToken aToken;
+/*?*/ aToken.SetOpCode( (OpCode) --i );
+/*?*/ pRawToken = aToken.Clone();
+/*N*/ }
+/*N*/ return bFound;
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::IsValue( const String& rSym )
+/*N*/ {
+/*N*/ double fVal;
+/*N*/ sal_uInt32 nIndex = ( pSymbolTable == pSymbolTableEnglish ?
+/*N*/ pDoc->GetFormatTable()->GetStandardIndex( LANGUAGE_ENGLISH_US ) : 0 );
+/*N*/ // ULONG nIndex = 0;
+/*N*/ //// ULONG nIndex = pDoc->GetFormatTable()->GetStandardIndex(ScGlobal::eLnge);
+/*N*/ if (pDoc->GetFormatTable()->IsNumberFormat( rSym, nIndex, fVal ) )
+/*N*/ {
+/*N*/ USHORT nType = pDoc->GetFormatTable()->GetType(nIndex);
+/*N*/ const sal_Unicode* p = aFormula.GetBuffer() + nSrcPos;
+/*N*/ while( *p == ' ' )
+/*N*/ p++;
+/*N*/ if ( *p == '(' && nType == NUMBERFORMAT_LOGICAL)
+/*N*/ return FALSE;
+/*N*/ else if( aFormula.GetChar(nSrcPos) == '.' )
+/*N*/ // Numerischer Tabellenname?
+/*N*/ return FALSE;
+/*N*/ else
+/*N*/ {
+/*N*/ if( nType == NUMBERFORMAT_TEXT )
+/*N*/ // HACK: Die Zahl ist zu gross!
+/*N*/ SetError( errIllegalArgument );
+/*N*/ ScRawToken aToken;
+/*N*/ aToken.SetDouble( fVal );
+/*N*/ pRawToken = aToken.Clone();
+/*N*/ return TRUE;
+/*N*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ return FALSE;
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::IsString()
+/*N*/ {
+/*N*/ register const sal_Unicode* p = cSymbol;
+/*N*/ while ( *p )
+/*N*/ p++;
+/*N*/ xub_StrLen nLen = p - cSymbol - 1;
+/*N*/ BOOL bQuote = ((cSymbol[0] == '"') && (cSymbol[nLen] == '"'));
+/*N*/ if ((bQuote ? nLen-2 : nLen) > MAXSTRLEN-1)
+/*N*/ {
+/*?*/ SetError(errStringOverflow);
+/*?*/ return FALSE;
+/*N*/ }
+/*N*/ if ( bQuote )
+/*N*/ {
+/*?*/ cSymbol[nLen] = '\0';
+/*?*/ ScRawToken aToken;
+/*?*/ aToken.SetString( cSymbol+1 );
+/*?*/ pRawToken = aToken.Clone();
+/*?*/ return TRUE;
+/*N*/ }
+/*N*/ return FALSE;
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::IsReference( const String& rName )
+/*N*/ {
+/*N*/ // Has to be called before IsValue
+/*N*/ sal_Unicode ch1 = rName.GetChar(0);
+/*N*/ sal_Unicode cDecSep = ( pSymbolTable == pSymbolTableEnglish ? '.' :
+/*N*/ ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0) );
+/*N*/ if ( ch1 == cDecSep )
+/*N*/ return FALSE;
+/*N*/ // Who was that imbecile introducing '.' as the sheet name separator!?!
+/*N*/ if ( CharClass::isAsciiNumeric( ch1 ) )
+/*N*/ { // Numerical sheet name is valid.
+/*N*/ // But English 1.E2 or 1.E+2 is value 100, 1.E-2 is 0.01
+/*N*/ // Don't create a #REF! of values.
+/*N*/ const xub_StrLen nPos = rName.Search( '.' );
+/*N*/ if ( nPos == STRING_NOTFOUND )
+/*N*/ return FALSE;
+/*N*/ sal_Unicode const * const pTabSep = rName.GetBuffer() + nPos;
+/*N*/ sal_Unicode ch2 = pTabSep[1]; // maybe a column identifier
+/*N*/ if ( !(ch2 == '$' || CharClass::isAsciiAlpha( ch2 )) )
+/*N*/ return FALSE;
+/*?*/ if ( cDecSep == '.' && (ch2 == 'E' || ch2 == 'e') // E + - digit
+/*?*/ && (GetCharTableFlags( pTabSep[2] ) & SC_COMPILER_C_VALUE_EXP) )
+/*?*/ { // #91053#
+/*?*/ // If it is an 1.E2 expression check if "1" is an existent sheet
+/*?*/ // name. If so, a desired value 1.E2 would have to be entered as
+/*?*/ // 1E2 or 1.0E2 or 1.E+2, sorry. Another possibility would be to
+/*?*/ // require numerical sheet names always being entered quoted, which
+/*?*/ // is not desirable (too many 1999, 2000, 2001 sheets in use).
+/*?*/ // Furthermore, XML files created with versions prior to SRC640e
+/*?*/ // wouldn't contain the quotes added by MakeTabStr()/CheckTabQuotes()
+/*?*/ // and would produce wrong formulas if the conditions here are met.
+/*?*/ // If you can live with these restrictions you may remove the
+/*?*/ // check and return an unconditional FALSE.
+/*?*/ String aTabName( rName.Copy( 0, nPos ) );
+/*?*/ USHORT nTab;
+/*?*/ if ( !pDoc->GetTable( aTabName, nTab ) )
+/*?*/ return FALSE;
+/*?*/ // If sheet "1" exists and the expression is 1.E+2 continue as
+/*?*/ // usual, the ScRange/ScAddress parser will take care of it.
+/*?*/ }
+/*N*/ }
+/*N*/ ScRange aRange( aPos, aPos );
+/*N*/ USHORT nFlags = aRange.Parse( rName, pDoc );
+/*N*/ if( nFlags & SCA_VALID )
+/*N*/ {
+/*N*/ ScRawToken aToken;
+/*N*/ ComplRefData aRef;
+/*N*/ aRef.InitRange( aRange );
+/*N*/ aRef.Ref1.SetColRel( (nFlags & SCA_COL_ABSOLUTE) == 0 );
+/*N*/ aRef.Ref1.SetRowRel( (nFlags & SCA_ROW_ABSOLUTE) == 0 );
+/*N*/ aRef.Ref1.SetTabRel( (nFlags & SCA_TAB_ABSOLUTE) == 0 );
+/*N*/ if ( !(nFlags & SCA_VALID_TAB) )
+/*?*/ aRef.Ref1.SetTabDeleted( TRUE ); // #REF!
+/*N*/ aRef.Ref1.SetFlag3D( ( nFlags & SCA_TAB_3D ) != 0 );
+/*N*/ aRef.Ref2.SetColRel( (nFlags & SCA_COL2_ABSOLUTE) == 0 );
+/*N*/ aRef.Ref2.SetRowRel( (nFlags & SCA_ROW2_ABSOLUTE) == 0 );
+/*N*/ aRef.Ref2.SetTabRel( (nFlags & SCA_TAB2_ABSOLUTE) == 0 );
+/*N*/ if ( !(nFlags & SCA_VALID_TAB2) )
+/*?*/ aRef.Ref2.SetTabDeleted( TRUE ); // #REF!
+/*N*/ aRef.Ref2.SetFlag3D( ( nFlags & SCA_TAB2_3D ) != 0 );
+/*N*/ aRef.CalcRelFromAbs( aPos );
+/*N*/ aToken.SetDoubleReference( aRef );
+/*N*/ pRawToken = aToken.Clone();
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ ScAddress aAddr( aPos );
+/*N*/ nFlags = aAddr.Parse( rName, pDoc );
+/*N*/ // Irgend etwas muss gueltig sein,
+/*N*/ // damit Tabelle1.blah oder blah.a1 als (falsche) ref erkannt wird
+/*N*/ if( nFlags & ( SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB ) )
+/*N*/ {
+/*N*/ ScRawToken aToken;
+/*N*/ SingleRefData aRef;
+/*N*/ aRef.InitAddress( aAddr );
+/*N*/ aRef.SetColRel( (nFlags & SCA_COL_ABSOLUTE) == 0 );
+/*N*/ aRef.SetRowRel( (nFlags & SCA_ROW_ABSOLUTE) == 0 );
+/*N*/ aRef.SetTabRel( (nFlags & SCA_TAB_ABSOLUTE) == 0 );
+/*N*/ aRef.SetFlag3D( ( nFlags & SCA_TAB_3D ) != 0 );
+/*N*/ // Die Referenz ist wirklich ungueltig!
+/*N*/ if( !( nFlags & SCA_VALID ) )
+/*N*/ {
+/*N*/ if( !( nFlags & SCA_VALID_COL ) )
+/*N*/ aRef.nCol = MAXCOL+1;
+/*N*/ if( !( nFlags & SCA_VALID_ROW ) )
+/*N*/ aRef.nRow = MAXROW+1;
+/*N*/ if( !( nFlags & SCA_VALID_TAB ) )
+/*N*/ aRef.nTab = MAXTAB+3;
+/*N*/ nFlags |= SCA_VALID;
+/*N*/ }
+/*N*/ aRef.CalcRelFromAbs( aPos );
+/*N*/ aToken.SetSingleReference( aRef );
+/*N*/ pRawToken = aToken.Clone();
+/*N*/ }
+/*N*/ }
+/*N*/ return ( nFlags & SCA_VALID ) != 0;
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::IsMacro( const String& rName )
+/*N*/ {
+/*N*/ StarBASIC* pObj = 0;
+/*N*/ SfxObjectShell* pDocSh = pDoc->GetDocumentShell();
+/*N*/
+/*N*/ SfxApplication* pSfxApp = SFX_APP();
+/*N*/ pSfxApp->EnterBasicCall(); // Dok-Basic anlegen etc.
+/*N*/
+/*N*/ if( pDocSh )//XXX
+/*N*/ pObj = pDocSh->GetBasic();
+/*N*/ else
+/*?*/ pObj = pSfxApp->GetBasic();
+/*N*/
+/*N*/ SbxMethod* pMeth = (SbxMethod*) pObj->Find( rName, SbxCLASS_METHOD );
+/*N*/ if( !pMeth )
+/*N*/ {
+/*N*/ pSfxApp->LeaveBasicCall();
+/*N*/ return FALSE;
+/*N*/ }
+/*N*/ // Es sollte schon eine BASIC-Function sein!
+/*N*/ if( pMeth->GetType() == SbxVOID
+/*N*/ || ( pMeth->IsFixed() && pMeth->GetType() == SbxEMPTY )
+/*N*/ || !pMeth->ISA(SbMethod) )
+/*N*/ {
+/*N*/ pSfxApp->LeaveBasicCall();
+/*N*/ return FALSE;
+/*N*/ }
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); /*N*/ ScRawToken aToken;
+/*N*/ /*?*/ aToken.SetExternal( rName.GetBuffer() );
+/*N*/ /*?*/ aToken.eOp = ocMacro;
+/*N*/ /*?*/ pRawToken = aToken.Clone();
+/*N*/ /*?*/ pSfxApp->LeaveBasicCall();
+/*?*/ return TRUE;
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::IsNamedRange( const String& rName )
+/*N*/ {
+/*N*/ USHORT n;
+/*N*/ ScRangeName* pRangeName = pDoc->GetRangeName();
+/*N*/ if (pRangeName->SearchName( rName, n ) )
+/*N*/ {
+/*N*/ ScRangeData* pData = (*pRangeName)[n];
+/*N*/ ScRawToken aToken;
+/*N*/ aToken.SetName( pData->GetIndex() );
+/*N*/ pRawToken = aToken.Clone();
+/*N*/ return TRUE;
+/*N*/ }
+/*N*/ else
+/*N*/ return FALSE;
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::IsDBRange( const String& rName )
+/*N*/ {
+/*N*/ USHORT n;
+/*N*/ ScDBCollection* pDBColl = pDoc->GetDBCollection();
+/*N*/ if (pDBColl->SearchName( rName, n ) )
+/*N*/ {
+/*?*/ ScDBData* pData = (*pDBColl)[n];
+/*?*/ ScRawToken aToken;
+/*?*/ aToken.SetName( pData->GetIndex() );
+/*?*/ aToken.eOp = ocDBArea;
+/*?*/ pRawToken = aToken.Clone();
+/*?*/ return TRUE;
+/*N*/ }
+/*N*/ else
+/*N*/ return FALSE;
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::IsColRowName( const String& rName )
+/*N*/ {
+/*N*/ BOOL bInList = FALSE;
+/*N*/ BOOL bFound = FALSE;
+/*N*/ SingleRefData aRef;
+/*N*/ String aName( rName );
+/*N*/ DeQuote( aName );
+/*N*/ USHORT nThisTab = aPos.Tab();
+/*N*/ for ( short jThisTab = 1; jThisTab >= 0 && !bInList; jThisTab-- )
+/*N*/ { // #50300# zuerst Bereiche auf dieser Tabelle pruefen, falls doppelte Namen
+/*N*/ for ( short jRow=0; jRow<2 && !bInList; jRow++ )
+/*N*/ {
+/*N*/ ScRangePairList* pRL;
+/*N*/ if ( !jRow )
+/*N*/ pRL = pDoc->GetColNameRanges();
+/*N*/ else
+/*N*/ pRL = pDoc->GetRowNameRanges();
+/*N*/ for ( ScRangePair* pR = pRL->First(); pR && !bInList; pR = pRL->Next() )
+/*N*/ {
+/*?*/ const ScRange& rNameRange = pR->GetRange(0);
+/*?*/ if ( jThisTab && !(rNameRange.aStart.Tab() <= nThisTab &&
+/*?*/ nThisTab <= rNameRange.aEnd.Tab()) )
+/*?*/ continue; // for
+/*?*/ ScCellIterator aIter( pDoc, rNameRange );
+/*?*/ for ( ScBaseCell* pCell = aIter.GetFirst(); pCell && !bInList;
+/*?*/ pCell = aIter.GetNext() )
+/*?*/ {
+/*?*/ // GPF wenn Zelle via CompileNameFormula auf Zelle ohne Code
+/*?*/ // trifft und HasStringData/Interpret/Compile ausgefuehrt wird
+/*?*/ // und das ganze dann auch noch rekursiv..
+/*?*/ // ausserdem wird *diese* Zelle hier nicht angefasst, da noch
+/*?*/ // kein RPN existiert
+/*?*/ CellType eType = pCell->GetCellType();
+/*?*/ BOOL bOk = (eType == CELLTYPE_FORMULA ?
+/*?*/ ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen() > 0
+/*?*/ && ((ScFormulaCell*)pCell)->aPos != aPos // noIter
+/*?*/ : TRUE );
+/*?*/ if ( bOk && pCell->HasStringData() )
+/*?*/ {
+/*?*/ String aStr;
+/*?*/ switch ( eType )
+/*?*/ {
+/*?*/ case CELLTYPE_STRING:
+/*?*/ ((ScStringCell*)pCell)->GetString( aStr );
+/*?*/ break;
+/*?*/ case CELLTYPE_FORMULA:
+/*?*/ ((ScFormulaCell*)pCell)->GetString( aStr );
+/*?*/ break;
+/*?*/ case CELLTYPE_EDIT:
+/*?*/ ((ScEditCell*)pCell)->GetString( aStr );
+/*?*/ break;
+/*?*/ }
+/*?*/ if ( ScGlobal::pTransliteration->isEqual( aStr, aName ) )
+/*?*/ {
+/*?*/ aRef.InitFlags();
+/*?*/ aRef.nCol = aIter.GetCol();
+/*?*/ aRef.nRow = aIter.GetRow();
+/*?*/ aRef.nTab = aIter.GetTab();
+/*?*/ if ( !jRow )
+/*?*/ aRef.SetColRel( TRUE ); // ColName
+/*?*/ else
+/*?*/ aRef.SetRowRel( TRUE ); // RowName
+/*?*/ aRef.CalcRelFromAbs( aPos );
+/*?*/ bInList = bFound = TRUE;
+/*?*/ }
+/*?*/ }
+/*?*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ if ( !bInList && pDoc->GetDocOptions().IsLookUpColRowNames() )
+/*N*/ { // in der aktuellen Tabelle suchen
+/*N*/ long nDistance, nMax;
+/*N*/ long nMyCol = (long) aPos.Col();
+/*N*/ long nMyRow = (long) aPos.Row();
+/*N*/ BOOL bTwo = FALSE;
+/*N*/ ScAddress aOne( 0, 0, aPos.Tab() );
+/*N*/ ScAddress aTwo( MAXCOL, MAXROW, aPos.Tab() );
+/*N*/ ScCellIterator aIter( pDoc, ScRange( aOne, aTwo ) );
+/*N*/ for ( ScBaseCell* pCell = aIter.GetFirst(); pCell; pCell = aIter.GetNext() )
+/*N*/ {
+/*N*/ if ( bFound )
+/*N*/ { // aufhoeren wenn alles andere weiter liegt
+/*N*/ if ( nMax < (long)aIter.GetCol() )
+/*N*/ break; // aIter
+/*N*/ }
+/*N*/ CellType eType = pCell->GetCellType();
+/*N*/ BOOL bOk = (eType == CELLTYPE_FORMULA ?
+/*N*/ ((ScFormulaCell*)pCell)->GetCode()->GetCodeLen() > 0
+/*N*/ && ((ScFormulaCell*)pCell)->aPos != aPos // noIter
+/*N*/ : TRUE );
+/*N*/ if ( bOk && pCell->HasStringData() )
+/*N*/ {
+/*N*/ String aStr;
+/*N*/ switch ( eType )
+/*N*/ {
+/*N*/ case CELLTYPE_STRING:
+/*N*/ ((ScStringCell*)pCell)->GetString( aStr );
+/*N*/ break;
+/*N*/ case CELLTYPE_FORMULA:
+/*N*/ ((ScFormulaCell*)pCell)->GetString( aStr );
+/*N*/ break;
+/*N*/ case CELLTYPE_EDIT:
+/*N*/ ((ScEditCell*)pCell)->GetString( aStr );
+/*N*/ break;
+/*N*/ }
+/*N*/ if ( ScGlobal::pTransliteration->isEqual( aStr, aName ) )
+/*N*/ {
+/*N*/ USHORT nCol = aIter.GetCol();
+/*N*/ USHORT nRow = aIter.GetRow();
+/*N*/ long nC = nMyCol - nCol;
+/*N*/ long nR = nMyRow - nRow;
+/*N*/ if ( bFound )
+/*N*/ {
+/*?*/ long nD = nC * nC + nR * nR;
+/*?*/ if ( nD < nDistance )
+/*?*/ {
+/*?*/ if ( nC < 0 || nR < 0 )
+/*?*/ { // rechts oder unterhalb
+/*?*/ bTwo = TRUE;
+/*?*/ aTwo.Set( nCol, nRow, aIter.GetTab() );
+/*?*/ nMax = Max( nMyCol + Abs( nC ), nMyRow + Abs( nR ) );
+/*?*/ nDistance = nD;
+/*?*/ }
+/*?*/ else if ( !(nRow < aOne.Row() && nMyRow >= (long)aOne.Row()) )
+/*?*/ { // links oben, nur wenn nicht weiter oberhalb
+/*?*/ // des bisherigen und nMyRow darunter
+/*?*/ // (CellIter geht spaltenweise!)
+/*?*/ bTwo = FALSE;
+/*?*/ aOne.Set( nCol, nRow, aIter.GetTab() );
+/*?*/ nMax = Max( nMyCol + nC, nMyRow + nR );
+/*?*/ nDistance = nD;
+/*?*/ }
+/*?*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ aOne.Set( nCol, nRow, aIter.GetTab() );
+/*N*/ nDistance = nC * nC + nR * nR;
+/*N*/ nMax = Max( nMyCol + Abs( nC ), nMyRow + Abs( nR ) );
+/*N*/ }
+/*N*/ bFound = TRUE;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ if ( bFound )
+/*N*/ {
+/*N*/ ScAddress aAdr;
+/*N*/ if ( bTwo )
+/*N*/ {
+/*?*/ if ( nMyCol >= (long)aOne.Col() && nMyRow >= (long)aOne.Row() )
+/*?*/ aAdr = aOne; // links oben hat Vorrang
+/*?*/ else
+/*?*/ {
+/*?*/ if ( nMyCol < (long)aOne.Col() )
+/*?*/ { // zwei rechts
+/*?*/ if ( nMyRow >= (long)aTwo.Row() )
+/*?*/ aAdr = aTwo; // direkt rechts
+/*?*/ else
+/*?*/ aAdr = aOne;
+/*?*/ }
+/*?*/ else
+/*?*/ { // zwei unten oder unten und rechts, der naechstgelegene
+/*?*/ long nC1 = nMyCol - aOne.Col();
+/*?*/ long nR1 = nMyRow - aOne.Row();
+/*?*/ long nC2 = nMyCol - aTwo.Col();
+/*?*/ long nR2 = nMyRow - aTwo.Row();
+/*?*/ if ( nC1 * nC1 + nR1 * nR1 <= nC2 * nC2 + nR2 * nR2 )
+/*?*/ aAdr = aOne;
+/*?*/ else
+/*?*/ aAdr = aTwo;
+/*?*/ }
+/*?*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ aAdr = aOne;
+/*N*/ aRef.InitAddress( aAdr );
+/*N*/ if ( (aRef.nRow != MAXROW && pDoc->HasStringData(
+/*N*/ aRef.nCol, aRef.nRow + 1, aRef.nTab ))
+/*N*/ || (aRef.nRow != 0 && pDoc->HasStringData(
+/*N*/ aRef.nCol, aRef.nRow - 1, aRef.nTab )) )
+/*N*/ aRef.SetRowRel( TRUE ); // RowName
+/*N*/ else
+/*N*/ aRef.SetColRel( TRUE ); // ColName
+/*N*/ aRef.CalcRelFromAbs( aPos );
+/*N*/ }
+/*N*/ }
+/*N*/ if ( bFound )
+/*N*/ {
+/*N*/ ScRawToken aToken;
+/*N*/ aToken.SetSingleReference( aRef );
+/*N*/ aToken.eOp = ocColRowName;
+/*N*/ pRawToken = aToken.Clone();
+/*N*/ return TRUE;
+/*N*/ }
+/*N*/ else
+/*N*/ return FALSE;
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::AutoCorrectParsedSymbol()
+/*N*/ {
+/*N*/ xub_StrLen nPos = aCorrectedSymbol.Len();
+/*N*/ if ( nPos )
+/*N*/ {
+/*N*/ nPos--;
+/*N*/ const sal_Unicode cQuote = '\"';
+/*N*/ const sal_Unicode cx = 'x';
+/*N*/ const sal_Unicode cX = 'X';
+/*N*/ sal_Unicode c1 = aCorrectedSymbol.GetChar( 0 );
+/*N*/ sal_Unicode c2 = aCorrectedSymbol.GetChar( nPos );
+/*N*/ if ( c1 == cQuote && c2 != cQuote )
+/*N*/ { // "...
+/*N*/ // was kein Wort bildet gehoert nicht dazu.
+/*N*/ // Don't be pedantic: c < 128 should be sufficient here.
+/*N*/ while ( nPos && ((aCorrectedSymbol.GetChar(nPos) < 128) &&
+/*N*/ ((GetCharTableFlags( aCorrectedSymbol.GetChar(nPos) ) &
+/*N*/ (SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_DONTCARE)) == 0)) )
+/*N*/ nPos--;
+/*N*/ if ( nPos == MAXSTRLEN - 2 )
+/*N*/ aCorrectedSymbol.SetChar( nPos, cQuote ); // '"' als 255. Zeichen
+/*N*/ else
+/*N*/ aCorrectedSymbol.Insert( cQuote, nPos + 1 );
+/*N*/ bCorrected = TRUE;
+/*N*/ }
+/*N*/ else if ( c1 != cQuote && c2 == cQuote )
+/*N*/ { // ..."
+/*N*/ aCorrectedSymbol.Insert( cQuote, 0 );
+/*N*/ bCorrected = TRUE;
+/*N*/ }
+/*N*/ else if ( nPos == 0 && (c1 == cx || c1 == cX) )
+/*N*/ { // x => *
+/*N*/ aCorrectedSymbol = pSymbolTable[ocMul];
+/*N*/ bCorrected = TRUE;
+/*N*/ }
+/*N*/ else if ( (GetCharTableFlags( c1 ) & SC_COMPILER_C_CHAR_VALUE)
+/*N*/ && (GetCharTableFlags( c2 ) & SC_COMPILER_C_CHAR_VALUE) )
+/*N*/ {
+/*N*/ xub_StrLen nXcount;
+/*N*/ if ( (nXcount = aCorrectedSymbol.GetTokenCount( cx )) > 1 )
+/*N*/ { // x => *
+/*N*/ xub_StrLen nIndex = 0;
+/*N*/ sal_Unicode c = pSymbolTable[ocMul].GetChar(0);
+/*N*/ while ( (nIndex = aCorrectedSymbol.SearchAndReplace(
+/*N*/ cx, c, nIndex )) != STRING_NOTFOUND )
+/*N*/ nIndex++;
+/*N*/ bCorrected = TRUE;
+/*N*/ }
+/*N*/ if ( (nXcount = aCorrectedSymbol.GetTokenCount( cX )) > 1 )
+/*N*/ { // X => *
+/*N*/ xub_StrLen nIndex = 0;
+/*N*/ sal_Unicode c = pSymbolTable[ocMul].GetChar(0);
+/*N*/ while ( (nIndex = aCorrectedSymbol.SearchAndReplace(
+/*N*/ cX, c, nIndex )) != STRING_NOTFOUND )
+/*N*/ nIndex++;
+/*N*/ bCorrected = TRUE;
+/*N*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ String aSymbol( aCorrectedSymbol );
+/*N*/ String aDoc;
+/*N*/ xub_StrLen nPos;
+/*N*/ if ( aSymbol.GetChar(0) == '\''
+/*N*/ && ((nPos = aSymbol.SearchAscii( "'#" )) != STRING_NOTFOUND) )
+/*N*/ { // 'Doc'# abspalten, kann d:\... und sonstwas sein
+/*N*/ aDoc = aSymbol.Copy( 0, nPos + 2 );
+/*N*/ aSymbol.Erase( 0, nPos + 2 );
+/*N*/ }
+/*N*/ xub_StrLen nRefs = aSymbol.GetTokenCount( ':' );
+/*N*/ BOOL bColons;
+/*N*/ if ( nRefs > 2 )
+/*N*/ { // doppelte oder zuviele ':'? B:2::C10 => B2:C10
+/*N*/ bColons = TRUE;
+/*N*/ xub_StrLen nIndex = 0;
+/*N*/ String aTmp1( aSymbol.GetToken( 0, ':', nIndex ) );
+/*N*/ xub_StrLen nLen1 = aTmp1.Len();
+/*N*/ String aSym, aTmp2;
+/*N*/ BOOL bLastAlp, bNextNum;
+/*N*/ bLastAlp = bNextNum = TRUE;
+/*N*/ xub_StrLen nStrip = 0;
+/*N*/ xub_StrLen nCount = nRefs;
+/*N*/ for ( xub_StrLen j=1; j<nCount; j++ )
+/*N*/ {
+/*N*/ aTmp2 = aSymbol.GetToken( 0, ':', nIndex );
+/*N*/ xub_StrLen nLen2 = aTmp2.Len();
+/*N*/ if ( nLen1 || nLen2 )
+/*N*/ {
+/*N*/ if ( nLen1 )
+/*N*/ {
+/*N*/ aSym += aTmp1;
+/*N*/ bLastAlp = CharClass::isAsciiAlpha( aTmp1 );
+/*N*/ }
+/*N*/ if ( nLen2 )
+/*N*/ {
+/*N*/ bNextNum = CharClass::isAsciiNumeric( aTmp2 );
+/*N*/ if ( bLastAlp == bNextNum && nStrip < 1 )
+/*N*/ { // muss abwechselnd nur Zahl/String sein,
+/*N*/ // nur innerhalb einer Ref strippen
+/*N*/ nRefs--;
+/*N*/ nStrip++;
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ xub_StrLen nSymLen = aSym.Len();
+/*N*/ if ( nSymLen
+/*N*/ && (aSym.GetChar( nSymLen - 1 ) != ':') )
+/*N*/ aSym += ':';
+/*N*/ nStrip = 0;
+/*N*/ }
+/*N*/ bLastAlp = !bNextNum;
+/*N*/ }
+/*N*/ else
+/*N*/ { // ::
+/*N*/ nRefs--;
+/*N*/ if ( nLen1 )
+/*N*/ { // B10::C10 ? naechste Runde ':' anhaengen
+/*N*/ if ( !bLastAlp && !CharClass::isAsciiNumeric( aTmp1 ) )
+/*N*/ nStrip++;
+/*N*/ }
+/*N*/ bNextNum = !bLastAlp;
+/*N*/ }
+/*N*/ aTmp1 = aTmp2;
+/*N*/ nLen1 = nLen2;
+/*N*/ }
+/*N*/ else
+/*N*/ nRefs--;
+/*N*/ }
+/*N*/ aSymbol = aSym;
+/*N*/ aSymbol += aTmp1;
+/*N*/ }
+/*N*/ else
+/*N*/ bColons = FALSE;
+/*N*/ if ( nRefs && nRefs <= 2 )
+/*N*/ { // Referenzdreher? 4A => A4 etc.
+/*N*/ String aTab[2], aRef[2];
+/*N*/ if ( nRefs == 2 )
+/*N*/ {
+/*N*/ aRef[0] = aSymbol.GetToken( 0, ':' );
+/*N*/ aRef[1] = aSymbol.GetToken( 1, ':' );
+/*N*/ }
+/*N*/ else
+/*N*/ aRef[0] = aSymbol;
+/*N*/
+/*N*/ BOOL bChanged = FALSE;
+/*N*/ BOOL bOk = TRUE;
+/*N*/ USHORT nMask = SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW;
+/*N*/ for ( int j=0; j<nRefs; j++ )
+/*N*/ {
+/*N*/ xub_StrLen nTmp = 0;
+/*N*/ xub_StrLen nPos = STRING_NOTFOUND;
+/*N*/ while ( (nTmp = aRef[j].Search( '.', nTmp )) != STRING_NOTFOUND )
+/*N*/ nPos = nTmp++; // der letzte zaehlt
+/*N*/ if ( nPos != STRING_NOTFOUND )
+/*N*/ {
+/*N*/ aTab[j] = aRef[j].Copy( 0, nPos + 1 ); // mit '.'
+/*N*/ aRef[j].Erase( 0, nPos + 1 );
+/*N*/ }
+/*N*/ String aOld( aRef[j] );
+/*N*/ String aStr2;
+/*N*/ const sal_Unicode* p = aRef[j].GetBuffer();
+/*N*/ while ( *p && CharClass::isAsciiNumeric( *p ) )
+/*N*/ aStr2 += *p++;
+/*N*/ aRef[j] = String( p );
+/*N*/ aRef[j] += aStr2;
+/*N*/ if ( bColons || aRef[j] != aOld )
+/*N*/ {
+/*N*/ bChanged = TRUE;
+/*N*/ ScAddress aAdr;
+/*N*/ bOk &= ((aAdr.Parse( aRef[j], pDoc ) & nMask) == nMask);
+/*N*/ }
+/*N*/ }
+/*N*/ if ( bChanged && bOk )
+/*N*/ {
+/*N*/ aCorrectedSymbol = aDoc;
+/*N*/ aCorrectedSymbol += aTab[0];
+/*N*/ aCorrectedSymbol += aRef[0];
+/*N*/ if ( nRefs == 2 )
+/*N*/ {
+/*N*/ aCorrectedSymbol += ':';
+/*N*/ aCorrectedSymbol += aTab[1];
+/*N*/ aCorrectedSymbol += aRef[1];
+/*N*/ }
+/*N*/ bCorrected = TRUE;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::NextNewToken()
+/*N*/ {
+/*N*/ xub_StrLen nSpaces = NextSymbol();
+/*N*/ ScRawToken aToken;
+/*N*/ if( cSymbol[0] )
+/*N*/ {
+/*N*/ if( nSpaces )
+/*N*/ {
+/*N*/ aToken.SetOpCode( ocSpaces );
+/*N*/ aToken.cByte = (BYTE) ( nSpaces > 255 ? 255 : nSpaces );
+/*N*/ if( !pArr->AddToken( aToken ) )
+/*N*/ {
+/*?*/ SetError(errCodeOverflow); return FALSE;
+/*N*/ }
+/*N*/ }
+/*N*/ if ( (cSymbol[0] == '#' || cSymbol[0] == '$') && cSymbol[1] == 0 &&
+/*N*/ !bAutoCorrect )
+/*N*/ { // #101100# special case to speed up broken [$]#REF documents
+/*N*/ String aBad( aFormula.Copy( nSrcPos-1 ) );
+/*N*/ eLastOp = pArr->AddBad( aBad )->GetOpCode();
+/*N*/ return FALSE;
+/*N*/ }
+/*N*/ if( !IsString() )
+/*N*/ {
+/*N*/ BOOL bMayBeFuncName;
+/*N*/ if ( cSymbol[0] < 128 )
+/*N*/ bMayBeFuncName = CharClass::isAsciiAlpha( cSymbol[0] );
+/*N*/ else
+/*N*/ {
+/*N*/ String aTmpStr( cSymbol[0] );
+/*N*/ bMayBeFuncName = ScGlobal::pCharClass->isLetter( aTmpStr, 0 );
+/*N*/ }
+/*N*/ if ( bMayBeFuncName )
+/*N*/ { // a function name must be followed by a parenthesis
+/*N*/ const sal_Unicode* p = aFormula.GetBuffer() + nSrcPos;
+/*N*/ while( *p == ' ' )
+/*N*/ p++;
+/*N*/ bMayBeFuncName = ( *p == '(' );
+/*N*/ }
+/*N*/ else
+/*N*/ bMayBeFuncName = TRUE; // operators and other opcodes
+/*N*/
+/*N*/ String aOrg( cSymbol ); // evtl. Dateinamen in IsReference erhalten
+/*N*/ String aUpper( ScGlobal::pCharClass->upper( aOrg ) );
+/*N*/ // Spalte DM konnte nicht referiert werden, IsReference vor IsValue
+/*N*/ // #42016# italian ARCTAN.2 gab #REF! => IsOpCode vor IsReference
+/*N*/ if ( !(bMayBeFuncName && IsOpCode( aUpper ))
+/*N*/ && !IsReference( aOrg )
+/*N*/ && !IsValue( aUpper )
+/*N*/ && !IsNamedRange( aUpper )
+/*N*/ && !IsDBRange( aUpper )
+/*N*/ && !IsColRowName( aUpper )
+/*N*/ && !(bMayBeFuncName && IsMacro( aUpper ))
+/*N*/ && !(bMayBeFuncName && IsOpCode2( aUpper )) )
+/*N*/ {
+/*N*/ SetError( errNoName );
+/*N*/ if ( bAutoCorrect )
+/*N*/ { // provide single token information and continue
+/*?*/ ScGlobal::pCharClass->toLower( aUpper );
+/*?*/ aToken.SetString( aUpper.GetBuffer() );
+/*?*/ aToken.NewOpCode( ocBad );
+/*?*/ pRawToken = aToken.Clone();
+/*?*/ AutoCorrectParsedSymbol();
+/*N*/ }
+/*N*/ else
+/*N*/ { // we don't need single token information, just a bad formula
+/*N*/ String aBad( aFormula.Copy( nSrcPos - aOrg.Len() ) );
+/*N*/ eLastOp = pArr->AddBad( aBad )->GetOpCode();
+/*N*/ return FALSE;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ return TRUE;
+/*N*/ }
+/*N*/ else
+/*N*/ return FALSE;
+/*N*/ }
+
+/*N*/ ScTokenArray* ScCompiler::CompileString( const String& rFormula )
+/*N*/ {
+/*N*/ ScTokenArray aArr;
+/*N*/ pArr = &aArr;
+/*N*/ aFormula = rFormula;
+/*N*/ aFormula.EraseLeadingChars();
+/*N*/ aFormula.EraseTrailingChars();
+/*N*/ nSrcPos = 0;
+/*N*/ bCorrected = FALSE;
+/*N*/ if ( bAutoCorrect )
+/*N*/ {
+/*?*/ aCorrectedFormula.Erase();
+/*?*/ aCorrectedSymbol.Erase();
+/*N*/ }
+/*N*/ BYTE nForced = 0; // ==Formel forciert Recalc auch wenn nicht sichtbar
+/*N*/ if( aFormula.GetChar(nSrcPos) == '=' )
+/*N*/ {
+/*N*/ nSrcPos++;
+/*N*/ nForced++;
+/*N*/ if ( bAutoCorrect )
+/*N*/ aCorrectedFormula += '=';
+/*N*/ }
+/*N*/ if( aFormula.GetChar(nSrcPos) == '=' )
+/*N*/ {
+/*N*/ nSrcPos++;
+/*N*/ nForced++;
+/*N*/ if ( bAutoCorrect )
+/*N*/ aCorrectedFormula += '=';
+/*N*/ }
+/*N*/ short nBrackets = 0;
+/*N*/ eLastOp = ocOpen;
+/*N*/ while( NextNewToken() )
+/*N*/ {
+/*N*/ if( pRawToken->GetOpCode() == ocOpen )
+/*N*/ nBrackets++;
+/*N*/ else if( pRawToken->GetOpCode() == ocClose )
+/*N*/ {
+/*N*/ if( !nBrackets )
+/*N*/ {
+/*?*/ SetError( errPairExpected );
+/*?*/ if ( bAutoCorrect )
+/*?*/ {
+/*?*/ bCorrected = TRUE;
+/*?*/ aCorrectedSymbol.Erase();
+/*?*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ nBrackets--;
+/*N*/ }
+/*N*/ if( !pArr->Add( pRawToken->CreateToken() ) )
+/*N*/ {
+/*?*/ SetError(errCodeOverflow); break;
+/*N*/ }
+/*N*/ eLastOp = pRawToken->GetOpCode();
+/*N*/ if ( bAutoCorrect )
+/*N*/ aCorrectedFormula += aCorrectedSymbol;
+/*N*/ }
+/*N*/ if ( eLastOp != ocBad )
+/*N*/ { // bei ocBad ist der Rest der Formel String, es wuerden zuviele
+/*N*/ // Klammern erscheinen
+/*N*/ ScByteToken aToken( ocClose );
+/*N*/ while( nBrackets-- )
+/*N*/ {
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); /*N*/ if( !pArr->AddToken( aToken ) )
+/*N*/ /*?*/ {
+/*N*/ /*?*/ SetError(errCodeOverflow); break;
+/*N*/ /*?*/ }
+/*N*/ /*?*/ if ( bAutoCorrect )
+/*N*/ /*?*/ aCorrectedFormula += pSymbolTable[ocClose];
+/*N*/ }
+/*N*/ }
+/*N*/ if ( nForced >= 2 )
+/*?*/ pArr->SetRecalcModeForced();
+/*N*/ // pArr merken, falls danach CompileTokenArray() kommt
+/*N*/ return pArr = new ScTokenArray( aArr );
+/*N*/ }
+
+/*N*/ void ScCompiler::PushTokenArray( ScTokenArray* pa, BOOL bTemp )
+/*N*/ {
+/*N*/ if ( bAutoCorrect && !pStack )
+/*N*/ { // #61426# don't merge stacked subroutine code into entered formula
+/*?*/ aCorrectedFormula += aCorrectedSymbol;
+/*?*/ aCorrectedSymbol.Erase();
+/*N*/ }
+/*N*/ ScArrayStack* p = new ScArrayStack;
+/*N*/ p->pNext = pStack;
+/*N*/ p->pArr = pArr;
+/*N*/ p->bTemp = bTemp;
+/*N*/ pStack = p;
+/*N*/ pArr = pa;
+/*N*/ }
+
+/*N*/ void ScCompiler::PopTokenArray()
+/*N*/ {
+/*N*/ if( pStack )
+/*N*/ {
+/*N*/ ScArrayStack* p = pStack;
+/*N*/ pStack = p->pNext;
+/*N*/ p->pArr->nRefs += pArr->nRefs;
+/*N*/ // special RecalcMode aus SharedFormula uebernehmen
+/*N*/ if ( pArr->IsRecalcModeAlways() )
+/*?*/ p->pArr->SetRecalcModeAlways();
+/*N*/ else if ( !pArr->IsRecalcModeNormal() && p->pArr->IsRecalcModeNormal() )
+/*?*/ p->pArr->SetMaskedRecalcMode( pArr->GetRecalcMode() );
+/*N*/ p->pArr->SetCombinedBitsRecalcMode( pArr->GetRecalcMode() );
+/*N*/ if( p->bTemp )
+/*N*/ delete pArr;
+/*N*/ pArr = p->pArr;
+/*N*/ delete p;
+/*N*/ }
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::GetToken()
+/*N*/ {
+/*N*/ static const short nRecursionMax = 42;
+/*N*/ ScCompilerRecursionGuard aRecursionGuard( nRecursion );
+/*N*/ if ( nRecursion > nRecursionMax )
+/*N*/ {
+/*?*/ SetError( errStackOverflow );
+/*?*/ pToken = new ScByteToken( ocStop );
+/*?*/ return FALSE;
+/*N*/ }
+/*N*/ if ( bAutoCorrect && !pStack )
+/*N*/ { // #61426# don't merge stacked subroutine code into entered formula
+/*?*/ aCorrectedFormula += aCorrectedSymbol;
+/*?*/ aCorrectedSymbol.Erase();
+/*N*/ }
+/*N*/ BOOL bStop = FALSE;
+/*N*/ if( pArr->GetError() && !bIgnoreErrors )
+/*N*/ bStop = TRUE;
+/*N*/ else
+/*N*/ {
+/*N*/ short nWasColRowName;
+/*N*/ if ( pArr->nIndex
+/*N*/ && pArr->pCode[ pArr->nIndex-1 ]->GetOpCode() == ocColRowName )
+/*N*/ nWasColRowName = 1;
+/*N*/ else
+/*N*/ nWasColRowName = 0;
+/*N*/ pToken = pArr->Next();
+/*N*/ while( pToken && pToken->GetOpCode() == ocSpaces )
+/*N*/ {
+/*N*/ if ( nWasColRowName )
+/*N*/ nWasColRowName++;
+/*N*/ if ( bAutoCorrect && !pStack )
+/*?*/ CreateStringFromToken( aCorrectedFormula, pToken, FALSE );
+/*N*/ pToken = pArr->Next();
+/*N*/ }
+/*N*/ if ( bAutoCorrect && !pStack && pToken )
+/*?*/ CreateStringFromToken( aCorrectedSymbol, pToken, FALSE );
+/*N*/ if( !pToken )
+/*N*/ {
+/*N*/ if( pStack )
+/*N*/ {
+/*N*/ PopTokenArray();
+/*N*/ return GetToken();
+/*N*/ }
+/*N*/ else
+/*N*/ bStop = TRUE;
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ if ( nWasColRowName >= 2 && pToken->GetOpCode() == ocColRowName )
+/*N*/ { // aus einem ocSpaces ein ocIntersect im RPN machen
+/*?*/ pToken = new ScByteToken( ocIntersect );
+/*?*/ pArr->nIndex--; // ganz schweinisch..
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ if( bStop )
+/*N*/ {
+/*N*/ pToken = new ScByteToken( ocStop );
+/*N*/ return FALSE;
+/*N*/ }
+/*N*/ if( pToken->GetOpCode() == ocSubTotal )
+/*N*/ glSubTotal = TRUE;
+/*N*/ else if( pToken->GetOpCode() == ocName )
+/*N*/ {
+/*N*/ ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->GetIndex() );
+/*N*/ if (pRangeData)
+/*N*/ {
+/*N*/ USHORT nErr = pRangeData->GetErrCode();
+/*N*/ if( nErr )
+/*N*/ SetError( errNoName );
+/*N*/ else if ( !bCompileForFAP )
+/*N*/ {
+/*N*/ ScTokenArray* pNew;
+/*N*/ // #35168# Bereichsformel klammern
+/*N*/ // #37680# aber nur wenn nicht schon Klammern da,
+/*N*/ // geklammerte ocSep geht nicht, z.B. SUMME((...;...))
+/*N*/ // und wenn nicht direkt zwischen ocSep/Klammer,
+/*N*/ // z.B. SUMME(...;(...;...)) nicht, SUMME(...;(...)*3) ja
+/*N*/ // kurz: wenn kein eigenstaendiger Ausdruck
+/*N*/ ScToken* p1 = pArr->PeekPrevNoSpaces();
+/*N*/ ScToken* p2 = pArr->PeekNextNoSpaces();
+/*N*/ OpCode eOp1 = (p1 ? p1->GetOpCode() : ocSep);
+/*N*/ OpCode eOp2 = (p2 ? p2->GetOpCode() : ocSep);
+/*N*/ BOOL bBorder1 = (eOp1 == ocSep || eOp1 == ocOpen);
+/*N*/ BOOL bBorder2 = (eOp2 == ocSep || eOp2 == ocClose);
+/*N*/ BOOL bAddPair = !(bBorder1 && bBorder2);
+/*N*/ if ( bAddPair )
+/*N*/ {
+/*N*/ pNew = new ScTokenArray;
+/*N*/ pNew->AddOpCode( ocClose );
+/*N*/ PushTokenArray( pNew, TRUE );
+/*N*/ pNew->Reset();
+/*N*/ }
+/*N*/ pNew = pRangeData->GetCode()->Clone();
+/*N*/ PushTokenArray( pNew, TRUE );
+/*N*/ if( pRangeData->HasReferences() )
+/*N*/ {
+/*N*/ SetRelNameReference();
+/*N*/ MoveRelWrap();
+/*N*/ }
+/*N*/ pNew->Reset();
+/*N*/ if ( bAddPair )
+/*N*/ {
+/*N*/ pNew = new ScTokenArray;
+/*N*/ pNew->AddOpCode( ocOpen );
+/*N*/ PushTokenArray( pNew, TRUE );
+/*N*/ pNew->Reset();
+/*N*/ }
+/*N*/ return GetToken();
+/*N*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ SetError(errNoName);
+/*N*/ }
+/*N*/ else if( pToken->GetOpCode() == ocColRowName )
+/*N*/ {
+/*N*/ SingleRefData& rRef = pToken->GetSingleRef();
+/*N*/ rRef.CalcAbsIfRel( aPos );
+/*N*/ if ( !rRef.Valid() )
+/*N*/ {
+/*N*/ SetError( errNoRef );
+/*N*/ return TRUE;
+/*N*/ }
+/*N*/ USHORT nCol = rRef.nCol;
+/*N*/ USHORT nRow = rRef.nRow;
+/*N*/ USHORT nTab = rRef.nTab;
+/*N*/ ScAddress aLook( nCol, nRow, nTab );
+/*N*/ BOOL bColName = rRef.IsColRel();
+/*N*/ USHORT nMyCol = aPos.Col();
+/*N*/ USHORT nMyRow = aPos.Row();
+/*N*/ BOOL bInList = FALSE;
+/*N*/ BOOL bValidName = FALSE;
+/*N*/ ScRangePairList* pRL = (bColName ?
+/*N*/ pDoc->GetColNameRanges() : pDoc->GetRowNameRanges());
+/*N*/ ScRange aRange;
+/*N*/ for ( ScRangePair* pR = pRL->First(); pR; pR = pRL->Next() )
+/*N*/ {
+/*?*/ if ( pR->GetRange(0).In( aLook ) )
+/*?*/ {
+/*?*/ bInList = bValidName = TRUE;
+/*?*/ aRange = pR->GetRange(1);
+/*?*/ if ( bColName )
+/*?*/ {
+/*?*/ aRange.aStart.SetCol( nCol );
+/*?*/ aRange.aEnd.SetCol( nCol );
+/*?*/ }
+/*?*/ else
+/*?*/ {
+/*?*/ aRange.aStart.SetRow( nRow );
+/*?*/ aRange.aEnd.SetRow( nRow );
+/*?*/ }
+/*?*/ break; // for
+/*?*/ }
+/*N*/ }
+/*N*/ if ( !bInList && pDoc->GetDocOptions().IsLookUpColRowNames() )
+/*N*/ { // automagically oder durch kopieren entstanden und NamePos nicht in Liste
+/*N*/ BOOL bString = pDoc->HasStringData( nCol, nRow, nTab );
+/*N*/ if ( !bString && !pDoc->GetCell( aLook ) )
+/*N*/ bString = TRUE; // leere Zelle ist ok
+/*N*/ if ( bString )
+/*N*/ { //! korrespondiert mit ScInterpreter::ScColRowNameAuto
+/*N*/ bValidName = TRUE;
+/*N*/ if ( bColName )
+/*N*/ { // ColName
+/*N*/ USHORT nStartRow = nRow + 1;
+/*N*/ if ( nStartRow > MAXROW )
+/*N*/ nStartRow = MAXROW;
+/*N*/ USHORT nMaxRow = MAXROW;
+/*N*/ if ( nMyCol == nCol )
+/*N*/ { // Formelzelle in gleicher Col
+/*?*/ if ( nMyRow == nStartRow )
+/*?*/ { // direkt unter dem Namen den Rest nehmen
+/*?*/ nStartRow++;
+/*?*/ if ( nStartRow > MAXROW )
+/*?*/ nStartRow = MAXROW;
+/*?*/ }
+/*?*/ else if ( nMyRow > nStartRow )
+/*?*/ { // weiter unten vom Namen bis zur Formelzelle
+/*?*/ nMaxRow = nMyRow - 1;
+/*?*/ }
+/*N*/ }
+/*N*/ for ( ScRangePair* pR = pRL->First(); pR; pR = pRL->Next() )
+/*N*/ { // naechster definierter ColNameRange unten ist Row-Begrenzung
+/*?*/ const ScRange& rRange = pR->GetRange(1);
+/*?*/ if ( rRange.aStart.Col() <= nCol && nCol <= rRange.aEnd.Col() )
+/*?*/ { // gleicher Col Bereich
+/*?*/ USHORT nTmp = rRange.aStart.Row();
+/*?*/ if ( nStartRow < nTmp && nTmp <= nMaxRow )
+/*?*/ nMaxRow = nTmp - 1;
+/*?*/ }
+/*N*/ }
+/*N*/ aRange.aStart.Set( nCol, nStartRow, nTab );
+/*N*/ aRange.aEnd.Set( nCol, nMaxRow, nTab );
+/*N*/ }
+/*N*/ else
+/*N*/ { // RowName
+/*N*/ USHORT nStartCol = nCol + 1;
+/*N*/ if ( nStartCol > MAXCOL )
+/*N*/ nStartCol = MAXCOL;
+/*N*/ USHORT nMaxCol = MAXCOL;
+/*N*/ if ( nMyRow == nRow )
+/*N*/ { // Formelzelle in gleicher Row
+/*N*/ if ( nMyCol == nStartCol )
+/*N*/ { // direkt neben dem Namen den Rest nehmen
+/*N*/ nStartCol++;
+/*N*/ if ( nStartCol > MAXCOL )
+/*N*/ nStartCol = MAXCOL;
+/*N*/ }
+/*N*/ else if ( nMyCol > nStartCol )
+/*N*/ { // weiter rechts vom Namen bis zur Formelzelle
+/*N*/ nMaxCol = nMyCol - 1;
+/*N*/ }
+/*N*/ }
+/*N*/ for ( ScRangePair* pR = pRL->First(); pR; pR = pRL->Next() )
+/*N*/ { // naechster definierter RowNameRange rechts ist Col-Begrenzung
+/*?*/ const ScRange& rRange = pR->GetRange(1);
+/*?*/ if ( rRange.aStart.Row() <= nRow && nRow <= rRange.aEnd.Row() )
+/*?*/ { // gleicher Row Bereich
+/*?*/ USHORT nTmp = rRange.aStart.Col();
+/*?*/ if ( nStartCol < nTmp && nTmp <= nMaxCol )
+/*?*/ nMaxCol = nTmp - 1;
+/*?*/ }
+/*N*/ }
+/*N*/ aRange.aStart.Set( nStartCol, nRow, nTab );
+/*N*/ aRange.aEnd.Set( nMaxCol, nRow, nTab );
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ if ( bValidName )
+/*N*/ {
+/*N*/ // Und nun der Zauber zur Unterscheidung zwischen
+/*N*/ // Bereich und einer einzelnen Zelle daraus, die
+/*N*/ // positionsabhaengig von der Formelzelle gewaehlt wird.
+/*N*/ // Ist ein direkter Nachbar ein binaerer Operator (ocAdd etc.)
+/*N*/ // so wird eine SingleRef passend zur Col/Row generiert,
+/*N*/ // ocColRowName bzw. ocIntersect als Nachbar => Range.
+/*N*/ // Spezialfall: Beschriftung gilt fuer eine einzelne Zelle,
+/*N*/ // dann wird eine positionsunabhaengige SingleRef generiert.
+/*N*/ BOOL bSingle = (aRange.aStart == aRange.aEnd);
+/*N*/ BOOL bFound;
+/*N*/ if ( bSingle )
+/*N*/ bFound = TRUE;
+/*N*/ else
+/*N*/ {
+/*N*/ ScToken* p1 = pArr->PeekPrevNoSpaces();
+/*N*/ ScToken* p2 = pArr->PeekNextNoSpaces();
+/*N*/ // Anfang/Ende einer Formel => Single
+/*N*/ OpCode eOp1 = p1 ? p1->GetOpCode() : ocAdd;
+/*N*/ OpCode eOp2 = p2 ? p2->GetOpCode() : ocAdd;
+/*N*/ if ( eOp1 != ocColRowName && eOp1 != ocIntersect
+/*N*/ && eOp2 != ocColRowName && eOp2 != ocIntersect )
+/*N*/ {
+/*N*/ if ( (ocEndDiv < eOp1 && eOp1 < ocEndBinOp)
+/*N*/ || (ocEndDiv < eOp2 && eOp2 < ocEndBinOp) )
+/*N*/ bSingle = TRUE;
+/*N*/ }
+/*N*/ if ( bSingle )
+/*N*/ { // Col bzw. Row muss zum Range passen
+/*N*/ if ( bColName )
+/*N*/ {
+/*N*/ bFound = (aRange.aStart.Row() <= nMyRow
+/*N*/ && nMyRow <= aRange.aEnd.Row());
+/*N*/ if ( bFound )
+/*N*/ aRange.aStart.SetRow( nMyRow );
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ bFound = (aRange.aStart.Col() <= nMyCol
+/*N*/ && nMyCol <= aRange.aEnd.Col());
+/*N*/ if ( bFound )
+/*?*/ aRange.aStart.SetCol( nMyCol );
+/*N*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ bFound = TRUE;
+/*N*/ }
+/*N*/ if ( !bFound )
+/*N*/ SetError(errNoRef);
+/*N*/ else if ( !bCompileForFAP )
+/*N*/ {
+/*N*/ ScTokenArray* pNew = new ScTokenArray;
+/*N*/ if ( bSingle )
+/*N*/ {
+/*N*/ SingleRefData aRefData;
+/*N*/ aRefData.InitAddress( aRange.aStart );
+/*N*/ if ( bColName )
+/*N*/ aRefData.SetColRel( TRUE );
+/*N*/ else
+/*?*/ aRefData.SetRowRel( TRUE );
+/*N*/ aRefData.CalcRelFromAbs( aPos );
+/*N*/ pNew->AddSingleReference( aRefData );
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*?*/ ComplRefData aRefData;
+/*?*/ aRefData.InitRange( aRange );
+/*?*/ if ( bColName )
+/*?*/ {
+/*?*/ aRefData.Ref1.SetColRel( TRUE );
+/*?*/ aRefData.Ref2.SetColRel( TRUE );
+/*?*/ }
+/*?*/ else
+/*?*/ {
+/*?*/ aRefData.Ref1.SetRowRel( TRUE );
+/*?*/ aRefData.Ref2.SetRowRel( TRUE );
+/*?*/ }
+/*?*/ aRefData.CalcRelFromAbs( aPos );
+/*?*/ if ( bInList )
+/*?*/ pNew->AddDoubleReference( aRefData );
+/*?*/ else
+/*?*/ { // automagically
+/*?*/ pNew->Add( new ScDoubleRefToken( ocColRowNameAuto,
+/*?*/ aRefData ) );
+/*?*/ }
+/*N*/ }
+/*N*/ PushTokenArray( pNew, TRUE );
+/*N*/ pNew->Reset();
+/*N*/ return GetToken();
+/*N*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ SetError(errNoName);
+/*N*/ }
+/*N*/ else if( pToken->GetOpCode() == ocDBArea )
+/*N*/ {
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); /*N*/ ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex( pToken->GetIndex() );
+/*N*/ /*?*/ if ( !pDBData )
+/*N*/ /*?*/ SetError(errNoName);
+/*N*/ /*?*/ else if ( !bCompileForFAP )
+/*N*/ /*?*/ {
+/*N*/ /*?*/ ComplRefData aRefData;
+/*N*/ /*?*/ aRefData.InitFlags();
+/*N*/ /*?*/ pDBData->GetArea( (USHORT&) aRefData.Ref1.nTab,
+/*N*/ /*?*/ (USHORT&) aRefData.Ref1.nCol,
+/*N*/ /*?*/ (USHORT&) aRefData.Ref1.nRow,
+/*N*/ /*?*/ (USHORT&) aRefData.Ref2.nCol,
+/*N*/ /*?*/ (USHORT&) aRefData.Ref2.nRow);
+/*N*/ /*?*/ aRefData.Ref2.nTab = aRefData.Ref1.nTab;
+/*N*/ /*?*/ aRefData.CalcRelFromAbs( aPos );
+/*N*/ /*?*/ ScTokenArray* pNew = new ScTokenArray;
+/*N*/ /*?*/ pNew->AddDoubleReference( aRefData );
+/*N*/ /*?*/ PushTokenArray( pNew, TRUE );
+/*N*/ /*?*/ pNew->Reset();
+/*N*/ /*?*/ return GetToken();
+/*N*/ /*?*/ }
+/*N*/ }
+/*N*/ else if( pToken->GetType() == svSingleRef )
+/*N*/ {
+/*N*/ // if (!pDoc->HasTable( pToken->aRef.Ref1.nTab ) )
+/*N*/ // SetError(errNoRef);
+/*N*/ pArr->nRefs++;
+/*N*/ }
+/*N*/ else if( pToken->GetType() == svDoubleRef )
+/*N*/ {
+/*N*/ // if (!pDoc->HasTable( pToken->aRef.Ref1.nTab ) ||
+/*N*/ // !pDoc->HasTable( pToken->aRef.Ref2.nTab ))
+/*N*/ // SetError(errNoRef);
+/*N*/ pArr->nRefs++;
+/*N*/ }
+/*N*/ return TRUE;
+/*N*/ }
+
+/*N*/ OpCode ScCompiler::NextToken()
+/*N*/ {
+/*N*/ if( !GetToken() )
+/*N*/ return ocStop;
+/*N*/ OpCode eOp = pToken->GetOpCode();
+/*N*/ // #38815# CompileTokenArray mit zurueckgesetztem Fehler gibt wieder Fehler
+/*N*/ if ( eOp == ocBad )
+/*N*/ SetError( errNoName );
+/*N*/ // Vor einem Push muss ein Operator kommen
+/*N*/ if ( (eOp == ocPush || eOp == ocColRowNameAuto) &&
+/*N*/ !( (eLastOp == ocOpen) || (eLastOp == ocSep) ||
+/*N*/ ((eLastOp > ocEndDiv) && (eLastOp < ocEndUnOp))) )
+/*?*/ SetError(errOperatorExpected);
+/*N*/ // Operator und Plus = Operator
+/*N*/ BOOL bLastOp = ( eLastOp == ocOpen || eLastOp == ocSep ||
+/*N*/ (eLastOp > ocEndDiv && eLastOp < ocEndUnOp)
+/*N*/ );
+/*N*/ if( bLastOp && eOp == ocAdd )
+/*N*/ eOp = NextToken();
+/*N*/ else
+/*N*/ {
+/*N*/ // Vor einem Operator darf kein weiterer Operator stehen
+/*N*/ // Aber AND, OR ist OK
+/*N*/ if ( eOp != ocAnd && eOp != ocOr
+/*N*/ && ( eOp > ocEndDiv && eOp < ocEndBinOp )
+/*N*/ && ( eLastOp == ocOpen || eLastOp == ocSep
+/*N*/ || (eLastOp > ocEndDiv && eLastOp < ocEndUnOp)) )
+/*N*/ {
+/*?*/ SetError(errVariableExpected);
+/*?*/ if ( bAutoCorrect && !pStack )
+/*?*/ {
+/*?*/ if ( eOp == eLastOp || eLastOp == ocOpen )
+/*?*/ { // doppelten Operator verwerfen
+/*?*/ aCorrectedSymbol.Erase();
+/*?*/ bCorrected = TRUE;
+/*?*/ }
+/*?*/ else
+/*?*/ {
+/*?*/ xub_StrLen nPos = aCorrectedFormula.Len();
+/*?*/ if ( nPos )
+/*?*/ {
+/*?*/ nPos--;
+/*?*/ sal_Unicode c = aCorrectedFormula.GetChar( nPos );
+/*?*/ switch ( eOp )
+/*?*/ { // Operatoren vertauschen
+/*?*/ case ocGreater:
+/*?*/ if ( c == pSymbolTable[ocEqual].GetChar(0) )
+/*?*/ { // >= ist richtig statt =>
+/*?*/ aCorrectedFormula.SetChar( nPos,
+/*?*/ pSymbolTable[ocGreater].GetChar(0) );
+/*?*/ aCorrectedSymbol = c;
+/*?*/ bCorrected = TRUE;
+/*?*/ }
+/*?*/ break;
+/*?*/ case ocLess:
+/*?*/ if ( c == pSymbolTable[ocEqual].GetChar(0) )
+/*?*/ { // <= ist richtig statt =<
+/*?*/ aCorrectedFormula.SetChar( nPos,
+/*?*/ pSymbolTable[ocLess].GetChar(0) );
+/*?*/ aCorrectedSymbol = c;
+/*?*/ bCorrected = TRUE;
+/*?*/ }
+/*?*/ else if ( c == pSymbolTable[ocGreater].GetChar(0) )
+/*?*/ { // <> ist richtig statt ><
+/*?*/ aCorrectedFormula.SetChar( nPos,
+/*?*/ pSymbolTable[ocLess].GetChar(0) );
+/*?*/ aCorrectedSymbol = c;
+/*?*/ bCorrected = TRUE;
+/*?*/ }
+/*?*/ break;
+/*?*/ case ocMul:
+/*?*/ if ( c == pSymbolTable[ocSub].GetChar(0) )
+/*?*/ { // *- statt -*
+/*?*/ aCorrectedFormula.SetChar( nPos,
+/*?*/ pSymbolTable[ocMul].GetChar(0) );
+/*?*/ aCorrectedSymbol = c;
+/*?*/ bCorrected = TRUE;
+/*?*/ }
+/*?*/ break;
+/*?*/ case ocDiv:
+/*?*/ if ( c == pSymbolTable[ocSub].GetChar(0) )
+/*?*/ { // /- statt -/
+/*?*/ aCorrectedFormula.SetChar( nPos,
+/*?*/ pSymbolTable[ocDiv].GetChar(0) );
+/*?*/ aCorrectedSymbol = c;
+/*?*/ bCorrected = TRUE;
+/*?*/ }
+/*?*/ break;
+/*?*/ }
+/*?*/ }
+/*?*/ }
+/*?*/ }
+/*N*/ }
+/*N*/ eLastOp = eOp;
+/*N*/ }
+/*N*/ return eOp;
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ BOOL ScCompiler::CompileTokenArray()
+/*N*/ {
+/*N*/ glSubTotal = FALSE;
+/*N*/ bCorrected = FALSE;
+/*N*/ if( !pArr->nError || bIgnoreErrors )
+/*N*/ {
+/*N*/ if ( bAutoCorrect )
+/*N*/ {
+/*?*/ aCorrectedFormula.Erase();
+/*?*/ aCorrectedSymbol.Erase();
+/*N*/ }
+/*N*/ pArr->nRefs = 0; // wird neu gezaehlt
+/*N*/ pArr->DelRPN();
+/*N*/ pStack = NULL;
+/*N*/ ScToken* pData[ MAXCODE ];
+/*N*/ pCode = pData;
+/*N*/ BOOL bWasForced = pArr->IsRecalcModeForced();
+/*N*/ if ( bWasForced )
+/*N*/ {
+/*N*/ if ( bAutoCorrect )
+/*N*/ aCorrectedFormula = '=';
+/*N*/ }
+/*N*/ pArr->ClearRecalcMode();
+/*N*/ pArr->Reset();
+/*N*/ eLastOp = ocOpen;
+/*N*/ pc = 0;
+/*N*/ NextToken();
+/*N*/ Expression();
+/*N*/
+/*N*/ USHORT nErrorBeforePop = pArr->nError;
+/*N*/
+/*N*/ while( pStack )
+/*?*/ PopTokenArray();
+/*N*/ if( pc )
+/*N*/ {
+/*N*/ pArr->pRPN = new ScToken*[ pc ];
+/*N*/ pArr->nRPN = pc;
+/*N*/ memcpy( pArr->pRPN, pData, pc * sizeof( ScToken* ) );
+/*N*/ }
+/*N*/
+/*N*/ if( !pArr->nError && nErrorBeforePop )
+/*N*/ pArr->nError = nErrorBeforePop; // einmal Fehler, immer Fehler
+/*N*/
+/*N*/ if( pArr->nError && !bIgnoreErrors )
+/*N*/ pArr->DelRPN();
+/*N*/
+/*N*/ if ( bWasForced )
+/*?*/ pArr->SetRecalcModeForced();
+/*N*/ }
+/*N*/ if( nNumFmt == NUMBERFORMAT_UNDEFINED )
+/*N*/ nNumFmt = NUMBERFORMAT_NUMBER;
+/*N*/ return glSubTotal;
+/*N*/ }
+
+//---------------------------------------------------------------------------
+// Token in den Code Eintragen
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::PutCode( ScToken* p )
+/*N*/ {
+/*N*/ if( pc >= MAXCODE-1 )
+/*N*/ {
+/*?*/ if ( pc == MAXCODE-1 )
+/*?*/ {
+/*?*/ p = new ScByteToken( ocStop );
+/*?*/ *pCode++ = p;
+/*?*/ ++pc;
+/*?*/ p->IncRef();
+/*?*/ }
+/*?*/ SetError(errCodeOverflow);
+/*?*/ return;
+/*N*/ }
+/*N*/ if( pArr->GetError() && !bCompileForFAP )
+/*N*/ return;
+/*N*/ *pCode++ = p; pc++;
+/*N*/ p->IncRef();
+/*N*/ }
+
+//---------------------------------------------------------------------------
+// UPN-Erzeugung (durch Rekursion)
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::Factor()
+/*N*/ {
+/*N*/ if ( pArr->GetError() && !bIgnoreErrors )
+/*N*/ return;
+/*N*/ ScTokenRef pFacToken;
+/*N*/ OpCode eOp = pToken->GetOpCode();
+/*N*/ if( eOp == ocPush || eOp == ocColRowNameAuto || eOp == ocMatRef ||
+/*N*/ eOp == ocDBArea
+/*N*/ || (bCompileForFAP && ((eOp == ocName) || (eOp == ocDBArea)
+/*N*/ || (eOp == ocColRowName) || (eOp == ocBad)))
+/*N*/ )
+/*N*/ {
+/*N*/ PutCode( pToken );
+/*N*/ eOp = NextToken();
+/*N*/ if( eOp == ocOpen )
+/*N*/ {
+/*?*/ // PUSH( ist ein Fehler, der durch eine unbekannte
+/*?*/ // Funktion hervorgerufen wird.
+/*?*/ SetError(
+/*?*/ ( pToken->GetType() == svString
+/*?*/ || pToken->GetType() == svSingleRef )
+/*?*/ ? errNoName : errOperatorExpected );
+/*?*/ if ( bAutoCorrect && !pStack )
+/*?*/ { // Multiplikation annehmen
+/*?*/ aCorrectedFormula += pSymbolTable[ocMul];
+/*?*/ bCorrected = TRUE;
+/*?*/ NextToken();
+/*?*/ eOp = Expression();
+/*?*/ if( eOp != ocClose )
+/*?*/ SetError(errPairExpected);
+/*?*/ else
+/*?*/ eOp = NextToken();
+/*?*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ else if( eOp == ocOpen )
+/*N*/ {
+/*N*/ NextToken();
+/*N*/ eOp = Expression();
+/*N*/ if( eOp != ocClose )
+/*N*/ SetError(errPairExpected);
+/*N*/ else
+/*N*/ eOp = NextToken();
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ if( nNumFmt == NUMBERFORMAT_UNDEFINED )
+/*N*/ nNumFmt = lcl_GetRetFormat( eOp );
+/*N*/ if( eOp > ocEndUnOp && eOp < ocEndNoPar)
+/*N*/ {
+/*N*/ // Diese Funktionen muessen immer neu berechnet werden
+/*N*/ switch( eOp )
+/*N*/ {
+/*N*/ case ocRandom:
+/*N*/ case ocGetActDate:
+/*N*/ case ocGetActTime:
+/*N*/ pArr->SetRecalcModeAlways();
+/*N*/ break;
+/*N*/ }
+/*N*/ pFacToken = pToken;
+/*N*/ eOp = NextToken();
+/*N*/ if (eOp != ocOpen)
+/*N*/ {
+/*?*/ SetError(errPairExpected);
+/*?*/ PutCode( pFacToken );
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ eOp = NextToken();
+/*N*/ if (eOp != ocClose)
+/*?*/ SetError(errPairExpected);
+/*N*/ PutCode(pFacToken);
+/*N*/ eOp = NextToken();
+/*N*/ }
+/*N*/ }
+/*N*/ // Spezialfall NICHT() und NEG()
+/*N*/ else if( eOp == ocNot || eOp == ocNeg
+/*N*/ || ( eOp > ocEndNoPar && eOp < ocEnd1Par) )
+/*N*/ {
+/*N*/ // Functions that have to be always recalculated
+/*N*/ switch( eOp )
+/*N*/ {
+/*N*/ case ocFormula:
+/*?*/ pArr->SetRecalcModeAlways();
+/*N*/ break;
+/*N*/ }
+/*N*/ pFacToken = pToken;
+/*N*/ eOp = NextToken();
+/*N*/ if( nNumFmt == NUMBERFORMAT_UNDEFINED && eOp == ocNot )
+/*N*/ nNumFmt = NUMBERFORMAT_LOGICAL;
+/*N*/ if (eOp == ocOpen)
+/*N*/ {
+/*N*/ NextToken();
+/*N*/ eOp = Expression();
+/*N*/ }
+/*N*/ else
+/*N*/ SetError(errPairExpected);
+/*N*/ if (eOp != ocClose)
+/*N*/ SetError(errPairExpected);
+/*N*/ else if ( !pArr->GetError() )
+/*N*/ pFacToken->SetByte( 1 );
+/*N*/ PutCode( pFacToken );
+/*N*/ eOp = NextToken();
+/*N*/ }
+/*N*/ else if ((eOp > ocEnd1Par && eOp < ocEnd2Par)
+/*N*/ || eOp == ocExternal
+/*N*/ || eOp == ocMacro
+/*N*/ || eOp == ocAnd
+/*N*/ || eOp == ocOr
+/*N*/ || ( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
+/*N*/ || (bCompileForFAP && ((eOp == ocIf) || (eOp == ocChose)))
+/*N*/ )
+/*N*/ {
+/*N*/ OpCode eFuncOp = eOp;
+/*N*/ pFacToken = pToken;
+/*N*/ eOp = NextToken();
+/*N*/ BOOL bNoParam = FALSE;
+/*N*/ BOOL bNoPair = FALSE;
+/*N*/ BYTE nMultiAreaSep = 0;
+/*N*/ if (eOp == ocOpen)
+/*N*/ {
+/*N*/ eOp = NextToken();
+/*N*/ if ( eFuncOp == ocIndex && eOp == ocOpen )
+/*N*/ { // Mehrfachbereiche
+/*?*/ BYTE SepCount = 0;
+/*?*/ do
+/*?*/ {
+/*?*/ eOp = NextToken();
+/*?*/ if ( eOp != ocClose )
+/*?*/ {
+/*?*/ SepCount++;
+/*?*/ eOp = Expression();
+/*?*/ }
+/*?*/ } while ( (eOp == ocSep) && (!pArr->GetError() || bIgnoreErrors) );
+/*?*/ if ( eOp != ocClose )
+/*?*/ SetError(errPairExpected);
+/*?*/ eOp = NextToken();
+/*?*/ if ( eOp == ocSep )
+/*?*/ {
+/*?*/ nMultiAreaSep = 1;
+/*?*/ eOp = NextToken();
+/*?*/ }
+/*?*/ if ( SepCount == 0 )
+/*?*/ {
+/*?*/ if ( eOp == ocClose )
+/*?*/ bNoParam = TRUE;
+/*?*/ }
+/*?*/ else
+/*?*/ {
+/*?*/ PutCode( new ScByteToken( ocPush, SepCount ) );
+/*?*/ if ( eOp != ocClose )
+/*?*/ eOp = Expression();
+/*?*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ if (eOp == ocClose)
+/*N*/ bNoParam = TRUE;
+/*N*/ else
+/*N*/ eOp = Expression();
+/*N*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*?*/ if (pFacToken->GetOpCode() == ocMultiArea)
+/*?*/ {
+/*?*/ bNoPair = TRUE;
+/*?*/ NextToken();
+/*?*/ eOp = Expression();
+/*?*/ }
+/*?*/ else
+/*?*/ SetError(errPairExpected);
+/*N*/ }
+/*N*/ BYTE SepCount = nMultiAreaSep;
+/*N*/ if( !bNoParam )
+/*N*/ {
+/*N*/ SepCount++;
+/*N*/ while ( (eOp == ocSep) && (!pArr->GetError() || bIgnoreErrors) )
+/*N*/ {
+/*N*/ SepCount++;
+/*N*/ NextToken();
+/*N*/ eOp = Expression();
+/*N*/ }
+/*N*/ }
+/*N*/ if ((eOp != ocClose) && !bNoPair )
+/*N*/ SetError(errPairExpected);
+/*N*/ else
+/*N*/ eOp = NextToken();
+/*N*/ // Jumps are just normal functions for the FunctionAutoPilot tree view
+/*N*/ if ( bCompileForFAP && pFacToken->GetType() == svJump )
+/*?*/ pFacToken = new ScFAPToken( pFacToken->GetOpCode(), SepCount, pFacToken );
+/*N*/ else
+/*N*/ pFacToken->SetByte( SepCount );
+/*N*/ PutCode( pFacToken );
+/*N*/ // Diese Funktionen muessen immer neu berechnet werden
+/*N*/ switch( eFuncOp )
+/*N*/ {
+/*?*/ // ocIndirect muesste sonst bei jedem Interpret StopListening
+/*?*/ // und StartListening fuer ein RefTripel ausfuehren
+/*?*/ case ocIndirect:
+/*?*/ // ocOffset und ocIndex liefern indirekte Refs
+/*?*/ case ocOffset:
+/*?*/ case ocIndex:
+/*?*/ pArr->SetRecalcModeAlways();
+/*?*/ break;
+/*?*/ // Functions recalculated on every document load.
+/*?*/ // Don't use SetRecalcModeOnLoad which would override ModeAlways
+/*N*/ case ocConvert :
+/*N*/ pArr->AddRecalcMode( RECALCMODE_ONLOAD );
+/*N*/ break;
+/*?*/ // wird die referierte verschoben, aendert sich der Wert
+/*?*/ case ocColumn :
+/*?*/ case ocRow :
+/*?*/ case ocCell : // CELL needs recalc on move for some possible type values
+/*?*/ pArr->SetRecalcModeOnRefMove();
+/*?*/ break;
+/*N*/ }
+/*N*/ }
+/*N*/ else if (eOp == ocIf || eOp == ocChose)
+/*N*/ {
+/*N*/ // Die PC-Staende sind -1
+/*N*/ pFacToken = pToken;
+/*N*/ if ( eOp == ocIf )
+/*N*/ pFacToken->GetJump()[ 0 ] = 3; // if, else, behind
+/*N*/ else
+/*?*/ pFacToken->GetJump()[ 0 ] = MAXJUMPCOUNT+1;
+/*N*/ eOp = NextToken();
+/*N*/ if (eOp == ocOpen)
+/*N*/ {
+/*N*/ NextToken();
+/*N*/ eOp = Expression();
+/*N*/ }
+/*N*/ else
+/*N*/ SetError(errPairExpected);
+/*N*/ short nJumpCount = 0;
+/*N*/ PutCode( pFacToken );
+/*N*/ // #36253# bei AutoCorrect (da pArr->nError ignoriert wird)
+/*N*/ // unbegrenztes ocIf gibt GPF weil ScRawToken::Clone den JumpBuffer
+/*N*/ // anhand von nJump[0]*2+2 alloziert, was bei ocIf 3*2+2 ist
+/*N*/ const short nJumpMax =
+/*N*/ (pFacToken->GetOpCode() == ocIf ? 3 : MAXJUMPCOUNT);
+/*N*/ while ( (nJumpCount < (MAXJUMPCOUNT - 1)) && (eOp == ocSep)
+/*N*/ && (!pArr->GetError() || bIgnoreErrors) )
+/*N*/ {
+/*N*/ if ( ++nJumpCount <= nJumpMax )
+/*N*/ pFacToken->GetJump()[nJumpCount] = pc-1;
+/*N*/ NextToken();
+/*N*/ eOp = Expression();
+/*N*/ PutCode( pToken ); // Als Terminator des Teilausdrucks
+/*N*/ }
+/*N*/ if (eOp != ocClose)
+/*N*/ SetError(errPairExpected);
+/*N*/ else
+/*N*/ {
+/*N*/ eOp = NextToken();
+/*N*/ // auch ohne AutoCorrect gibt es hier ohne nJumpMax bei
+/*N*/ // mehr als 3 Parametern in ocIf einen Ueberschreiber,
+/*N*/ // das war auch schon in der 312 so (jaja, die Tester..)
+/*N*/ if ( ++nJumpCount <= nJumpMax )
+/*N*/ pFacToken->GetJump()[ nJumpCount ] = pc-1;
+/*N*/ if ((pFacToken->GetOpCode() == ocIf && (nJumpCount > 3)) ||
+/*N*/ (nJumpCount >= MAXJUMPCOUNT))
+/*N*/ SetError(errIllegalParameter);
+/*N*/ else
+/*N*/ pFacToken->GetJump()[ 0 ] = nJumpCount;
+/*N*/ }
+/*N*/ }
+/*N*/ else if ( eOp == ocBad )
+/*N*/ {
+/*?*/ SetError( errNoName );
+/*N*/ }
+/*N*/ else if ( eOp == ocClose )
+/*N*/ {
+/*?*/ SetError( errParameterExpected );
+/*N*/ }
+/*N*/ else if ( eOp == ocMissing )
+/*N*/ { // #84460# May occur if imported from Xcl.
+/*?*/ // The real value for missing parameters depends on the function
+/*?*/ // where it is used, interpreter would have to handle this.
+/*?*/ // If it does remove this error case here, that could also be the
+/*?*/ // time to generate ocMissing in between subsequent ocSep.
+/*?*/ // Xcl import should map missings to values if possible.
+/*?*/ SetError( errParameterExpected );
+/*N*/ }
+/*N*/ else if ( eOp == ocSep )
+/*N*/ { // Subsequent ocSep
+/*N*/ SetError( errParameterExpected );
+/*N*/ if ( bAutoCorrect && !pStack )
+/*N*/ {
+/*?*/ aCorrectedSymbol.Erase();
+/*?*/ bCorrected = TRUE;
+/*N*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*?*/ SetError( errUnknownToken );
+/*?*/ if ( bAutoCorrect && !pStack )
+/*?*/ {
+/*?*/ if ( eOp == ocStop )
+/*?*/ { // trailing operator w/o operand
+/*?*/ xub_StrLen nLen = aCorrectedFormula.Len();
+/*?*/ if ( nLen )
+/*?*/ aCorrectedFormula.Erase( nLen - 1 );
+/*?*/ aCorrectedSymbol.Erase();
+/*?*/ bCorrected = TRUE;
+/*?*/ }
+/*?*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::Unary()
+/*N*/ {
+/*N*/ if( pToken->GetOpCode() == ocAdd )
+/*?*/ GetToken();
+/*N*/ else if ( pToken->GetOpCode() > ocNot && pToken->GetOpCode() < ocEndUnOp )
+/*N*/ {
+/*?*/ ScTokenRef p = pToken;
+/*?*/ NextToken();
+/*?*/ Factor();
+/*?*/ PutCode( p );
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ Factor();
+/*N*/ while ( pToken->GetOpCode() == ocPercentSign )
+/*N*/ { // this operator _follows_ its operand
+/*?*/ PutCode( pToken );
+/*?*/ NextToken();
+/*N*/ }
+/*N*/ }
+/*N*/ }
+
+/*N*/ void ScCompiler::PowLine()
+/*N*/ {
+/*N*/ Unary();
+/*N*/ while (pToken->GetOpCode() == ocPow)
+/*N*/ {
+/*?*/ ScTokenRef p = pToken;
+/*?*/ NextToken();
+/*?*/ Unary();
+/*?*/ PutCode(p);
+/*N*/ }
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::UnionCutLine()
+/*N*/ {
+/*N*/ PowLine();
+/*N*/ while (pToken->GetOpCode() == ocIntersect)
+/*N*/ {
+/*?*/ ScTokenRef p = pToken;
+/*?*/ NextToken();
+/*?*/ PowLine();
+/*?*/ PutCode(p);
+/*N*/ }
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::MulDivLine()
+/*N*/ {
+/*N*/ UnionCutLine();
+/*N*/ while (pToken->GetOpCode() == ocMul || pToken->GetOpCode() == ocDiv)
+/*N*/ {
+/*N*/ ScTokenRef p = pToken;
+/*N*/ NextToken();
+/*N*/ UnionCutLine();
+/*N*/ PutCode(p);
+/*N*/ }
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::AddSubLine()
+/*N*/ {
+/*N*/ MulDivLine();
+/*N*/ while (pToken->GetOpCode() == ocAdd || pToken->GetOpCode() == ocSub)
+/*N*/ {
+/*N*/ ScTokenRef p = pToken;
+/*N*/ NextToken();
+/*N*/ MulDivLine();
+/*N*/ PutCode(p);
+/*N*/ }
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::ConcatLine()
+/*N*/ {
+/*N*/ AddSubLine();
+/*N*/ while (pToken->GetOpCode() == ocAmpersand)
+/*N*/ {
+/*N*/ ScTokenRef p = pToken;
+/*N*/ NextToken();
+/*N*/ AddSubLine();
+/*N*/ PutCode(p);
+/*N*/ }
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::CompareLine()
+/*N*/ {
+/*N*/ ConcatLine();
+/*N*/ while (pToken->GetOpCode() >= ocEqual && pToken->GetOpCode() <= ocGreaterEqual)
+/*N*/ {
+/*N*/ ScTokenRef p = pToken;
+/*N*/ NextToken();
+/*N*/ ConcatLine();
+/*N*/ PutCode(p);
+/*N*/ }
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ void ScCompiler::NotLine()
+/*N*/ {
+/*N*/ CompareLine();
+/*N*/ while (pToken->GetOpCode() == ocNot)
+/*N*/ {
+/*?*/ ScTokenRef p = pToken;
+/*?*/ NextToken();
+/*?*/ CompareLine();
+/*?*/ PutCode(p);
+/*N*/ }
+/*N*/ }
+
+//---------------------------------------------------------------------------
+
+/*N*/ OpCode ScCompiler::Expression()
+/*N*/ {
+/*N*/ static const short nRecursionMax = 42;
+/*N*/ ScCompilerRecursionGuard aRecursionGuard( nRecursion );
+/*N*/ if ( nRecursion > nRecursionMax )
+/*N*/ {
+/*?*/ SetError( errStackOverflow );
+/*?*/ return ocStop; //! stattdessen Token generieren?
+/*N*/ }
+/*N*/ NotLine();
+/*N*/ while (pToken->GetOpCode() == ocAnd || pToken->GetOpCode() == ocOr)
+/*N*/ {
+/*?*/ ScTokenRef p = pToken;
+/*?*/ pToken->SetByte( 2 ); // 2 parameters!
+/*?*/ NextToken();
+/*?*/ NotLine();
+/*?*/ PutCode(p);
+/*N*/ }
+/*N*/ return pToken->GetOpCode();
+/*N*/ }
+
+// Referenz aus benanntem Bereich mit relativen Angaben
+
+/*N*/ void ScCompiler::SetRelNameReference()
+/*N*/ {
+/*N*/ pArr->Reset();
+/*N*/ for( ScToken* t = pArr->GetNextReference(); t;
+/*N*/ t = pArr->GetNextReference() )
+/*N*/ {
+/*N*/ SingleRefData& rRef1 = t->GetSingleRef();
+/*N*/ if ( rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel() )
+/*?*/ rRef1.SetRelName( TRUE );
+/*N*/ if ( t->GetType() == svDoubleRef )
+/*N*/ {
+/*?*/ SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
+/*?*/ if ( rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel() )
+/*?*/ rRef2.SetRelName( TRUE );
+/*N*/ }
+/*N*/ }
+/*N*/ }
+
+// nur relative aus RangeName mit Wrap an Position anpassen
+/*N*/ void ScCompiler::MoveRelWrap()
+/*N*/ {
+/*N*/ pArr->Reset();
+/*N*/ for( ScToken* t = pArr->GetNextReference(); t;
+/*N*/ t = pArr->GetNextReference() )
+/*N*/ {
+/*N*/ if ( t->GetType() == svSingleRef )
+/*N*/ ScRefUpdate::MoveRelWrap( pDoc, aPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
+/*N*/ else
+/*?*/ ScRefUpdate::MoveRelWrap( pDoc, aPos, t->GetDoubleRef() );
+/*N*/ }
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::UpdateNameReference(UpdateRefMode eUpdateRefMode,
+/*N*/ const ScRange& r,
+/*N*/ short nDx, short nDy, short nDz,
+/*N*/ BOOL& rChanged)
+/*N*/ {
+/*N*/ BOOL bRet = FALSE; // wird gesetzt, wenn rel-Ref
+/*N*/ rChanged = FALSE;
+/*N*/ pArr->Reset();
+/*N*/ for( ScToken* t = pArr->GetNextReference(); t;
+/*N*/ t = pArr->GetNextReference() )
+/*N*/ {
+/*N*/ SingleDoubleRefModifier aMod( *t );
+/*N*/ ComplRefData& rRef = aMod.Ref();
+/*N*/ if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
+/*N*/ (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
+/*N*/ ( t->GetType() == svSingleRef ||
+/*N*/ (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
+/*N*/ (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
+/*N*/ {
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); /*N*/ if (ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
+/*N*/ /*?*/ r, nDx, nDy, nDz, rRef ) != UR_NOTHING )
+/*N*/ /*?*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ else
+/*N*/ bRet = TRUE;
+/*N*/ }
+/*N*/ return bRet;
+/*N*/ }
+
+
+/*N*/ ScRangeData* ScCompiler::UpdateInsertTab( USHORT nTable, BOOL bIsName )
+/*N*/ {
+/*N*/ ScRangeData* pRangeData = NULL;
+/*N*/ short nTab;
+/*N*/ USHORT nPosTab = aPos.Tab(); // _nach_ evtl. Increment!
+/*N*/ USHORT nOldPosTab = ((nPosTab > nTable) ? (nPosTab - 1) : nPosTab);
+/*N*/ BOOL bIsRel = FALSE;
+/*N*/ ScToken* t;
+/*N*/ pArr->Reset();
+/*N*/ if (bIsName)
+/*?*/ t = pArr->GetNextReference();
+/*N*/ else
+/*N*/ t = pArr->GetNextReferenceOrName();
+/*N*/ while( t )
+/*N*/ {
+/*N*/ if( t->GetOpCode() == ocName )
+/*N*/ {
+/*?*/ if (!bIsName)
+/*?*/ {
+/*?*/ ScRangeData* pName = pDoc->GetRangeName()->FindIndex(t->GetIndex());
+/*?*/ if (pName && pName->HasType(RT_SHAREDMOD))
+/*?*/ pRangeData = pName;
+/*?*/ }
+/*N*/ }
+/*N*/ else if( t->GetType() != svIndex ) // es kann ein DB-Bereich sein !!!
+/*N*/ {
+/*N*/ if ( !(bIsName && t->GetSingleRef().IsTabRel()) )
+/*N*/ { // Namen nur absolute anpassen
+/*N*/ SingleRefData& rRef = t->GetSingleRef();
+/*N*/ if ( rRef.IsTabRel() )
+/*N*/ {
+/*N*/ nTab = rRef.nRelTab + nOldPosTab;
+/*N*/ if ( nTab < 0 )
+/*?*/ nTab += pDoc->GetTableCount(); // was a wrap
+/*N*/ }
+/*N*/ else
+/*N*/ nTab = rRef.nTab;
+/*N*/ if ( nTable <= nTab )
+/*N*/ rRef.nTab = nTab + 1;
+/*N*/ rRef.nRelTab = rRef.nTab - nPosTab;
+/*N*/ }
+/*N*/ else
+/*N*/ bIsRel = TRUE;
+/*N*/ if ( t->GetType() == svDoubleRef )
+/*N*/ {
+/*N*/ if ( !(bIsName && t->GetDoubleRef().Ref2.IsTabRel()) )
+/*N*/ { // Namen nur absolute anpassen
+/*N*/ SingleRefData& rRef = t->GetDoubleRef().Ref2;
+/*N*/ if ( rRef.IsTabRel() )
+/*N*/ {
+/*N*/ nTab = rRef.nRelTab + nOldPosTab;
+/*N*/ if ( nTab < 0 )
+/*?*/ nTab += pDoc->GetTableCount(); // was a wrap
+/*N*/ }
+/*N*/ else
+/*N*/ nTab = rRef.nTab;
+/*N*/ if ( nTable <= nTab )
+/*N*/ rRef.nTab = nTab + 1;
+/*N*/ rRef.nRelTab = rRef.nTab - nPosTab;
+/*N*/ }
+/*N*/ else
+/*N*/ bIsRel = TRUE;
+/*N*/ }
+/*N*/ if ( bIsName && bIsRel )
+/*N*/ pRangeData = (ScRangeData*) this; // wird in rangenam nicht dereferenziert
+/*N*/ }
+/*N*/ if (bIsName)
+/*?*/ t = pArr->GetNextReference();
+/*N*/ else
+/*N*/ t = pArr->GetNextReferenceOrName();
+/*N*/ }
+/*N*/ if ( !bIsName )
+/*N*/ {
+/*N*/ pArr->Reset();
+/*N*/ for ( t = pArr->GetNextReferenceRPN(); t;
+/*N*/ t = pArr->GetNextReferenceRPN() )
+/*N*/ {
+/*N*/ if ( t->GetRef() == 1 )
+/*N*/ {
+/*N*/ SingleRefData& rRef1 = t->GetSingleRef();
+/*N*/ if ( !(rRef1.IsRelName() && rRef1.IsTabRel()) )
+/*N*/ { // Namen nur absolute anpassen
+/*N*/ if ( rRef1.IsTabRel() )
+/*N*/ {
+/*?*/ nTab = rRef1.nRelTab + nOldPosTab;
+/*?*/ if ( nTab < 0 )
+/*?*/ nTab += pDoc->GetTableCount(); // was a wrap
+/*N*/ }
+/*N*/ else
+/*N*/ nTab = rRef1.nTab;
+/*N*/ if ( nTable <= nTab )
+/*N*/ rRef1.nTab = nTab + 1;
+/*N*/ rRef1.nRelTab = rRef1.nTab - nPosTab;
+/*N*/ }
+/*N*/ if ( t->GetType() == svDoubleRef )
+/*N*/ {
+/*?*/ SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
+/*?*/ if ( !(rRef2.IsRelName() && rRef2.IsTabRel()) )
+/*?*/ { // Namen nur absolute anpassen
+/*?*/ if ( rRef2.IsTabRel() )
+/*?*/ {
+/*?*/ nTab = rRef2.nRelTab + nOldPosTab;
+/*?*/ if ( nTab < 0 )
+/*?*/ nTab += pDoc->GetTableCount(); // was a wrap
+/*?*/ }
+/*?*/ else
+/*?*/ nTab = rRef2.nTab;
+/*?*/ if ( nTable <= nTab )
+/*?*/ rRef2.nTab = nTab + 1;
+/*?*/ rRef2.nRelTab = rRef2.nTab - nPosTab;
+/*?*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ return pRangeData;
+/*N*/ }
+
+/*N*/ ScRangeData* ScCompiler::UpdateDeleteTab(USHORT nTable, BOOL bIsMove, BOOL bIsName,
+/*N*/ BOOL& rChanged)
+/*N*/ {
+/*N*/ ScRangeData* pRangeData = NULL;
+/*N*/ USHORT nTab, nTab2;
+/*N*/ USHORT nPosTab = aPos.Tab(); // _nach_ evtl. Decrement!
+/*N*/ USHORT nOldPosTab = ((nPosTab >= nTable) ? (nPosTab + 1) : nPosTab);
+/*N*/ rChanged = FALSE;
+/*N*/ BOOL bIsRel = FALSE;
+/*N*/ ScToken* t;
+/*N*/ pArr->Reset();
+/*N*/ if (bIsName)
+/*N*/ t = pArr->GetNextReference();
+/*N*/ else
+/*N*/ t = pArr->GetNextReferenceOrName();
+/*N*/ while( t )
+/*N*/ {
+/*N*/ if( t->GetOpCode() == ocName )
+/*N*/ {
+/*N*/ if (!bIsName)
+/*N*/ {
+/*N*/ ScRangeData* pName = pDoc->GetRangeName()->FindIndex(t->GetIndex());
+/*N*/ if (pName && pName->HasType(RT_SHAREDMOD))
+/*N*/ pRangeData = pName;
+/*N*/ }
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ else if( t->GetType() != svIndex ) // es kann ein DB-Bereich sein !!!
+/*N*/ {
+/*N*/ if ( !(bIsName && t->GetSingleRef().IsTabRel()) )
+/*N*/ { // Namen nur absolute anpassen
+/*N*/ SingleRefData& rRef = t->GetSingleRef();
+/*N*/ if ( rRef.IsTabRel() )
+/*N*/ nTab = rRef.nRelTab + nOldPosTab;
+/*N*/ else
+/*N*/ nTab = rRef.nTab;
+/*N*/ if ( nTable < nTab )
+/*N*/ {
+/*N*/ rRef.nTab = nTab - 1;
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ else if ( nTable == nTab )
+/*N*/ {
+/*N*/ if ( t->GetType() == svDoubleRef )
+/*N*/ {
+/*N*/ SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
+/*N*/ if ( rRef2.IsTabRel() )
+/*N*/ nTab2 = rRef2.nRelTab + nOldPosTab;
+/*N*/ else
+/*N*/ nTab2 = rRef2.nTab;
+/*N*/ if ( nTab == nTab2
+/*N*/ || (nTab+1) >= pDoc->GetTableCount() )
+/*N*/ {
+/*N*/ rRef.nTab = MAXTAB+1;
+/*N*/ rRef.SetTabDeleted( TRUE );
+/*N*/ }
+/*N*/ // else: nTab zeigt spaeter auf jetziges nTable+1
+/*N*/ // => Bereich verkleinert
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ rRef.nTab = MAXTAB+1;
+/*N*/ rRef.SetTabDeleted( TRUE );
+/*N*/ }
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ rRef.nRelTab = rRef.nTab - nPosTab;
+/*N*/ }
+/*N*/ else
+/*N*/ bIsRel = TRUE;
+/*N*/ if ( t->GetType() == svDoubleRef )
+/*N*/ {
+/*N*/ if ( !(bIsName && t->GetDoubleRef().Ref2.IsTabRel()) )
+/*N*/ { // Namen nur absolute anpassen
+/*N*/ SingleRefData& rRef = t->GetDoubleRef().Ref2;
+/*N*/ if ( rRef.IsTabRel() )
+/*N*/ nTab = rRef.nRelTab + nOldPosTab;
+/*N*/ else
+/*N*/ nTab = rRef.nTab;
+/*N*/ if ( nTable < nTab )
+/*N*/ {
+/*N*/ rRef.nTab = nTab - 1;
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ else if ( nTable == nTab )
+/*N*/ {
+/*N*/ if ( !t->GetDoubleRef().Ref1.IsTabDeleted() )
+/*N*/ rRef.nTab = nTab - 1; // Bereich verkleinern
+/*N*/ else
+/*N*/ {
+/*N*/ rRef.nTab = MAXTAB+1;
+/*N*/ rRef.SetTabDeleted( TRUE );
+/*N*/ }
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ rRef.nRelTab = rRef.nTab - nPosTab;
+/*N*/ }
+/*N*/ else
+/*N*/ bIsRel = TRUE;
+/*N*/ }
+/*N*/ if ( bIsName && bIsRel )
+/*N*/ pRangeData = (ScRangeData*) this; // wird in rangenam nicht dereferenziert
+/*N*/ }
+/*N*/ if (bIsName)
+/*N*/ t = pArr->GetNextReference();
+/*N*/ else
+/*N*/ t = pArr->GetNextReferenceOrName();
+/*N*/ }
+/*N*/ if ( !bIsName )
+/*N*/ {
+/*N*/ pArr->Reset();
+/*N*/ for ( t = pArr->GetNextReferenceRPN(); t;
+/*N*/ t = pArr->GetNextReferenceRPN() )
+/*N*/ {
+/*N*/ if ( t->GetRef() == 1 )
+/*N*/ {
+/*N*/ SingleRefData& rRef1 = t->GetSingleRef();
+/*N*/ if ( !(rRef1.IsRelName() && rRef1.IsTabRel()) )
+/*N*/ { // Namen nur absolute anpassen
+/*N*/ if ( rRef1.IsTabRel() )
+/*N*/ nTab = rRef1.nRelTab + nOldPosTab;
+/*N*/ else
+/*N*/ nTab = rRef1.nTab;
+/*N*/ if ( nTable < nTab )
+/*N*/ {
+/*N*/ rRef1.nTab = nTab - 1;
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ else if ( nTable == nTab )
+/*N*/ {
+/*N*/ if ( t->GetType() == svDoubleRef )
+/*N*/ {
+/*N*/ SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
+/*N*/ if ( rRef2.IsTabRel() )
+/*N*/ nTab2 = rRef2.nRelTab + nOldPosTab;
+/*N*/ else
+/*N*/ nTab2 = rRef2.nTab;
+/*N*/ if ( nTab == nTab2
+/*N*/ || (nTab+1) >= pDoc->GetTableCount() )
+/*N*/ {
+/*N*/ rRef1.nTab = MAXTAB+1;
+/*N*/ rRef1.SetTabDeleted( TRUE );
+/*N*/ }
+/*N*/ // else: nTab zeigt spaeter auf jetziges nTable+1
+/*N*/ // => Bereich verkleinert
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ rRef1.nTab = MAXTAB+1;
+/*N*/ rRef1.SetTabDeleted( TRUE );
+/*N*/ }
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ rRef1.nRelTab = rRef1.nTab - nPosTab;
+/*N*/ }
+/*N*/ if ( t->GetType() == svDoubleRef )
+/*N*/ {
+/*N*/ SingleRefData& rRef2 = t->GetDoubleRef().Ref2;
+/*N*/ if ( !(rRef2.IsRelName() && rRef2.IsTabRel()) )
+/*N*/ { // Namen nur absolute anpassen
+/*N*/ if ( rRef2.IsTabRel() )
+/*N*/ nTab = rRef2.nRelTab + nOldPosTab;
+/*N*/ else
+/*N*/ nTab = rRef2.nTab;
+/*N*/ if ( nTable < nTab )
+/*N*/ {
+/*N*/ rRef2.nTab = nTab - 1;
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ else if ( nTable == nTab )
+/*N*/ {
+/*N*/ if ( !rRef1.IsTabDeleted() )
+/*N*/ rRef2.nTab = nTab - 1; // Bereich verkleinern
+/*N*/ else
+/*N*/ {
+/*N*/ rRef2.nTab = MAXTAB+1;
+/*N*/ rRef2.SetTabDeleted( TRUE );
+/*N*/ }
+/*N*/ rChanged = TRUE;
+/*N*/ }
+/*N*/ rRef2.nRelTab = rRef2.nTab - nPosTab;
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ }
+/*N*/ return pRangeData;
+/*N*/ }
+
+/*N*/ ScToken* ScCompiler::CreateStringFromToken( String& rFormula, ScToken* pToken,
+/*N*/ BOOL bAllowArrAdvance )
+/*N*/ {
+/*N*/ ::rtl::OUStringBuffer aBuffer;
+/*N*/ ScToken* p = CreateStringFromToken( aBuffer, pToken, bAllowArrAdvance );
+/*N*/ rFormula += aBuffer;
+/*N*/ return p;
+/*N*/ }
+
+/*N*/ ScToken* ScCompiler::CreateStringFromToken( ::rtl::OUStringBuffer& rBuffer, ScToken* pToken,
+/*N*/ BOOL bAllowArrAdvance )
+/*N*/ {
+/*N*/ BOOL bNext = TRUE;
+/*N*/ BOOL bSpaces = FALSE;
+/*N*/ ScToken* t = pToken;
+/*N*/ OpCode eOp = t->GetOpCode();
+/*N*/ if( eOp >= ocAnd && eOp <= ocOr )
+/*N*/ {
+/*N*/ // AND, OR infix?
+/*N*/ if ( bAllowArrAdvance )
+/*N*/ t = pArr->Next();
+/*N*/ else
+/*N*/ t = pArr->PeekNext();
+/*N*/ bNext = FALSE;
+/*N*/ bSpaces = ( !t || t->GetOpCode() != ocOpen );
+/*N*/ }
+/*N*/ if( bSpaces )
+/*?*/ rBuffer.append(sal_Unicode(' '));
+/*N*/
+/*N*/ if( eOp == ocSpaces )
+/*N*/ { // most times it's just one blank
+/*N*/ BYTE n = t->GetByte();
+/*N*/ for ( BYTE j=0; j<n; ++j )
+/*N*/ {
+/*N*/ rBuffer.append(sal_Unicode(' '));
+/*N*/ }
+/*N*/ }
+/*N*/ else if( eOp >= ocInternalBegin && eOp <= ocInternalEnd )
+/*?*/ rBuffer.appendAscii( pInternal[ eOp - ocInternalBegin ] );
+/*N*/ else if( (USHORT) eOp < nAnzStrings) // Keyword:
+/*N*/ rBuffer.append(pSymbolTable[eOp]);
+/*N*/ else
+/*N*/ {
+/*?*/ DBG_ERROR("Unbekannter OpCode");
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
+/*N*/ }
+/*N*/ if( bNext ) switch( t->GetType() )
+/*N*/ {
+/*N*/ case svDouble:
+/*N*/ {
+/*N*/ if ( pSymbolTable == pSymbolTableEnglish )
+/*N*/ { // Don't go via number formatter, slows down XML export
+/*N*/ // significantly because on every formula the number formatter
+/*N*/ // has to switch to/from English/native language.
+/*N*/ ::rtl::math::doubleToUStringBuffer( rBuffer, t->GetDouble(),
+/*N*/ rtl_math_StringFormat_Automatic,
+/*N*/ rtl_math_DecimalPlaces_Max, '.', TRUE );
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*N*/ ::rtl::math::doubleToUStringBuffer( rBuffer, t->GetDouble(),
+/*N*/ rtl_math_StringFormat_Automatic,
+/*N*/ rtl_math_DecimalPlaces_Max,
+/*N*/ ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0),
+/*N*/ TRUE );
+/*N*/ }
+/*N*/ }
+/*N*/ break;
+/*N*/ case svString:
+/*N*/ if( eOp == ocBad )
+/*N*/ rBuffer.append(t->GetString());
+/*N*/ else
+/*N*/ {
+/*N*/ if (bImportXML)
+/*?*/ rBuffer.append(t->GetString());
+/*N*/ else
+/*N*/ {
+/*N*/ rBuffer.append(sal_Unicode('"'));
+/*N*/ if ( ScGlobal::UnicodeStrChr( t->GetString().GetBuffer(), '"' ) == NULL )
+/*N*/ rBuffer.append(t->GetString());
+/*N*/ else
+/*N*/ {
+/*?*/ String aStr( t->GetString() );
+/*?*/ xub_StrLen nPos = 0;
+/*?*/ while ( (nPos = aStr.Search( '"', nPos)) != STRING_NOTFOUND )
+/*?*/ {
+/*?*/ aStr.Insert( '"', nPos );
+/*?*/ nPos += 2;
+/*?*/ }
+/*?*/ rBuffer.append(aStr);
+/*N*/ }
+/*N*/ rBuffer.append(sal_Unicode('"'));
+/*N*/ }
+/*N*/ }
+/*N*/ break;
+/*N*/ case svSingleRef:
+/*N*/ {
+/*N*/ SingleRefData& rRef = t->GetSingleRef();
+/*N*/ ComplRefData aRef;
+/*N*/ aRef.Ref1 = aRef.Ref2 = rRef;
+/*N*/ if ( eOp == ocColRowName )
+/*N*/ {
+/*N*/ rRef.CalcAbsIfRel( aPos );
+/*N*/ if ( pDoc->HasStringData( rRef.nCol, rRef.nRow, rRef.nTab ) )
+/*N*/ {
+/*N*/ String aStr;
+/*N*/ pDoc->GetString( rRef.nCol, rRef.nRow, rRef.nTab, aStr );
+/*N*/ EnQuote( aStr );
+/*N*/ rBuffer.append(aStr);
+/*N*/ }
+/*N*/ else
+/*N*/ {
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
+/*?*/ MakeRefStr( rBuffer, aRef, TRUE );
+/*N*/ }
+/*N*/ }
+/*N*/ else
+/*N*/ MakeRefStr( rBuffer, aRef, TRUE );
+/*N*/ }
+/*N*/ break;
+/*N*/ case svDoubleRef:
+/*N*/ MakeRefStr( rBuffer, t->GetDoubleRef(), FALSE );
+/*N*/ break;
+/*N*/ case svIndex:
+/*N*/ {
+/*N*/ ::rtl::OUStringBuffer aBuffer;
+/*N*/ switch ( eOp )
+/*N*/ {
+/*N*/ case ocName:
+/*N*/ {
+/*N*/ ScRangeData* pData = pDoc->GetRangeName()->FindIndex(t->GetIndex());
+/*N*/ if (pData)
+/*N*/ {
+/*N*/ if (pData->HasType(RT_SHARED))
+/*N*/ pData->UpdateSymbol( aBuffer, aPos,
+/*N*/ pSymbolTable == pSymbolTableEnglish,
+/*N*/ bCompileXML );
+/*N*/ else
+/*N*/ aBuffer.append(pData->GetName());
+/*N*/ }
+/*N*/ }
+/*N*/ break;
+/*?*/ case ocDBArea:
+/*?*/ {
+/*?*/ DBG_BF_ASSERT(0, "STRIP"); /*N*/ ScDBData* pDBData = pDoc->GetDBCollection()->FindIndex(t->GetIndex());
+/*N*/ /*?*/ if (pDBData)
+/*N*/ /*?*/ aBuffer.append(pDBData->GetName());
+/*?*/ }
+/*?*/ break;
+/*?*/ }
+/*N*/ if ( aBuffer.getLength() )
+/*N*/ rBuffer.append(aBuffer);
+/*N*/ else
+/*?*/ rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
+/*N*/ break;
+/*N*/ }
+/*N*/ case svExternal:
+/*N*/ {
+/*N*/ // show translated name of StarOne AddIns
+/*N*/ String aAddIn( t->GetExternal() );
+/*N*/ if ( pSymbolTable != pSymbolTableEnglish )
+/*?*/ {DBG_BF_ASSERT(0, "STRIP");} //STRIP001 ScGlobal::GetAddInCollection()->LocalizeString( aAddIn );
+/*N*/ rBuffer.append(aAddIn);
+/*N*/ }
+/*N*/ break;
+/*N*/ case svByte:
+/*N*/ case svJump:
+/*N*/ case svFAP:
+/*N*/ case svMissing:
+/*N*/ break; // Opcodes
+/*N*/ default:
+/*N*/ DBG_ERROR("ScCompiler:: GetStringFromToken errUnknownVariable");
+/*N*/ } // of switch
+/*N*/ if( bSpaces )
+/*?*/ rBuffer.append(sal_Unicode(' '));
+/*N*/ if ( bAllowArrAdvance )
+/*N*/ {
+/*N*/ if( bNext )
+/*N*/ t = pArr->Next();
+/*N*/ return t;
+/*N*/ }
+/*N*/ return pToken;
+/*N*/ }
+
+/*N*/ void ScCompiler::CreateStringFromTokenArray( String& rFormula )
+/*N*/ {
+/*N*/ ::rtl::OUStringBuffer aBuffer( pArr->GetLen() * 2 );
+/*N*/ CreateStringFromTokenArray( aBuffer );
+/*N*/ rFormula = aBuffer;
+/*N*/ }
+
+/*N*/ void ScCompiler::CreateStringFromTokenArray( ::rtl::OUStringBuffer& rBuffer )
+/*N*/ {
+/*N*/ rBuffer.setLength(0);
+/*N*/ if( !pArr->GetLen() )
+/*N*/ return;
+/*N*/
+/*N*/ // at least one char per token, plus some are references, some are function names
+/*N*/ rBuffer.ensureCapacity( pArr->GetLen() * 2 );
+/*N*/
+/*N*/ if ( pArr->IsRecalcModeForced() )
+/*?*/ rBuffer.append(sal_Unicode('='));
+/*N*/ ScToken* t = pArr->First();
+/*N*/ while( t )
+/*N*/ t = CreateStringFromToken( rBuffer, t, TRUE );
+/*N*/ }
+
+/*N*/ BOOL ScCompiler::EnQuote( String& rStr )
+/*N*/ {
+/*N*/ sal_Int32 nType = ScGlobal::pCharClass->getStringType( rStr, 0, rStr.Len() );
+/*N*/ if ( !CharClass::isNumericType( nType )
+/*N*/ && CharClass::isAlphaNumericType( nType ) )
+/*N*/ return FALSE;
+/*N*/ xub_StrLen nPos = 0;
+/*N*/ while ( (nPos = rStr.Search( '\'', nPos)) != STRING_NOTFOUND )
+/*N*/ {
+/*N*/ rStr.Insert( '\\', nPos );
+/*N*/ nPos += 2;
+/*N*/ }
+/*N*/ rStr.Insert( '\'', 0 );
+/*N*/ rStr += '\'';
+/*N*/ return TRUE;
+/*N*/ }
+
+
+/*N*/ BOOL ScCompiler::DeQuote( String& rStr )
+/*N*/ {
+/*N*/ xub_StrLen nLen = rStr.Len();
+/*N*/ if ( nLen > 1 && rStr.GetChar(0) == '\'' && rStr.GetChar( nLen-1 ) == '\'' )
+/*N*/ {
+/*N*/ rStr.Erase( nLen-1, 1 );
+/*N*/ rStr.Erase( 0, 1 );
+/*N*/ xub_StrLen nPos = 0;
+/*N*/ while ( (nPos = rStr.SearchAscii( "\\\'", nPos)) != STRING_NOTFOUND )
+/*N*/ {
+/*N*/ rStr.Erase( nPos, 1 );
+/*N*/ ++nPos;
+/*N*/ }
+/*N*/ return TRUE;
+/*N*/ }
+/*N*/ return FALSE;
+/*N*/ }
+
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */