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