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