Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <rangelst.hxx>
21 : #include <sfx2/app.hxx>
22 : #include <sfx2/docfile.hxx>
23 : #include <sfx2/objsh.hxx>
24 : #include <sfx2/docfilt.hxx>
25 : #include <basic/sbmeth.hxx>
26 : #include <basic/sbmod.hxx>
27 : #include <basic/sbstar.hxx>
28 : #include <basic/sbx.hxx>
29 : #include <basic/sbxobj.hxx>
30 : #include <basic/sbuno.hxx>
31 : #include <svl/zforlist.hxx>
32 : #include <rtl/logfile.hxx>
33 : #include <stdlib.h>
34 : #include <string.h>
35 : #include <signal.h>
36 :
37 : #include <com/sun/star/table/XCellRange.hpp>
38 : #include <com/sun/star/sheet/XSheetCellRange.hpp>
39 : #include <comphelper/processfactory.hxx>
40 :
41 : #include "interpre.hxx"
42 : #include "global.hxx"
43 : #include "dbdata.hxx"
44 : #include "cell.hxx"
45 : #include "callform.hxx"
46 : #include "addincol.hxx"
47 : #include "document.hxx"
48 : #include "dociter.hxx"
49 : #include "docoptio.hxx"
50 : #include "scmatrix.hxx"
51 : #include "adiasync.hxx"
52 : #include "sc.hrc"
53 : #include "cellsuno.hxx"
54 : #include "optuno.hxx"
55 : #include "rangeseq.hxx"
56 : #include "addinlis.hxx"
57 : #include "jumpmatrix.hxx"
58 : #include "parclass.hxx"
59 : #include "externalrefmgr.hxx"
60 : #include "formula/FormulaCompiler.hxx"
61 : #include "macromgr.hxx"
62 : #include "doubleref.hxx"
63 : #include "queryparam.hxx"
64 :
65 : #include <math.h>
66 : #include <float.h>
67 : #include <map>
68 : #include <algorithm>
69 : #include <functional>
70 : #include <basic/basmgr.hxx>
71 : #include <vbahelper/vbaaccesshelper.hxx>
72 : #include <memory>
73 :
74 : using namespace com::sun::star;
75 : using namespace formula;
76 : using ::std::auto_ptr;
77 :
78 : #define ADDIN_MAXSTRLEN 256
79 :
80 : //-----------------------------static data -----------------
81 :
82 : //-------------------------------------------------------------------------
83 : // Funktionen fuer den Zugriff auf das Document
84 : //-------------------------------------------------------------------------
85 :
86 :
87 0 : void ScInterpreter::ReplaceCell( ScAddress& rPos )
88 : {
89 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ReplaceCell" );
90 0 : size_t ListSize = pDok->aTableOpList.size();
91 0 : for ( size_t i = 0; i < ListSize; ++i )
92 : {
93 0 : ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
94 0 : if ( rPos == pTOp->aOld1 )
95 : {
96 0 : rPos = pTOp->aNew1;
97 0 : return ;
98 : }
99 0 : else if ( rPos == pTOp->aOld2 )
100 : {
101 0 : rPos = pTOp->aNew2;
102 0 : return ;
103 : }
104 : }
105 : }
106 :
107 :
108 0 : void ScInterpreter::ReplaceCell( SCCOL& rCol, SCROW& rRow, SCTAB& rTab )
109 : {
110 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ReplaceCell" );
111 0 : ScAddress aCellPos( rCol, rRow, rTab );
112 0 : size_t ListSize = pDok->aTableOpList.size();
113 0 : for ( size_t i = 0; i < ListSize; ++i )
114 : {
115 0 : ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
116 0 : if ( aCellPos == pTOp->aOld1 )
117 : {
118 0 : rCol = pTOp->aNew1.Col();
119 0 : rRow = pTOp->aNew1.Row();
120 0 : rTab = pTOp->aNew1.Tab();
121 : return ;
122 : }
123 0 : else if ( aCellPos == pTOp->aOld2 )
124 : {
125 0 : rCol = pTOp->aNew2.Col();
126 0 : rRow = pTOp->aNew2.Row();
127 0 : rTab = pTOp->aNew2.Tab();
128 : return ;
129 : }
130 : }
131 : }
132 :
133 :
134 0 : bool ScInterpreter::IsTableOpInRange( const ScRange& rRange )
135 : {
136 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsTableOpInRange" );
137 0 : if ( rRange.aStart == rRange.aEnd )
138 0 : return false; // not considered to be a range in TableOp sense
139 :
140 : // we can't replace a single cell in a range
141 0 : size_t ListSize = pDok->aTableOpList.size();
142 0 : for ( size_t i = 0; i < ListSize; ++i )
143 : {
144 0 : ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
145 0 : if ( rRange.In( pTOp->aOld1 ) )
146 0 : return true;
147 0 : if ( rRange.In( pTOp->aOld2 ) )
148 0 : return true;
149 : }
150 0 : return false;
151 : }
152 :
153 :
154 1 : sal_uLong ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, const ScBaseCell* pCell)
155 : {
156 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetCellNumberFormat" );
157 : sal_uLong nFormat;
158 : sal_uInt16 nErr;
159 1 : if ( pCell )
160 : {
161 1 : if ( pCell->GetCellType() == CELLTYPE_FORMULA )
162 1 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
163 : else
164 0 : nErr = 0;
165 1 : nFormat = pDok->GetNumberFormat( rPos );
166 1 : if ( pCell->GetCellType() == CELLTYPE_FORMULA
167 : && ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) )
168 : nFormat = ((ScFormulaCell*)pCell)->GetStandardFormat( *pFormatter,
169 0 : nFormat );
170 : }
171 : else
172 : {
173 0 : nFormat = pDok->GetNumberFormat( rPos );
174 0 : nErr = 0;
175 : }
176 1 : SetError(nErr);
177 1 : return nFormat;
178 : }
179 :
180 :
181 : /// Only ValueCell, formula cells already store the result rounded.
182 0 : double ScInterpreter::GetValueCellValue( const ScAddress& rPos, const ScValueCell* pCell )
183 : {
184 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetValueCellValue" );
185 0 : double fVal = pCell->GetValue();
186 0 : if ( bCalcAsShown && fVal != 0.0 )
187 : {
188 0 : sal_uLong nFormat = pDok->GetNumberFormat( rPos );
189 0 : fVal = pDok->RoundValueAsShown( fVal, nFormat );
190 : }
191 0 : return fVal;
192 : }
193 :
194 :
195 : /** Convert string content to numeric value.
196 :
197 : Converted are only integer numbers including exponent, and ISO 8601 dates
198 : and times in their extended formats with separators. Anything else,
199 : especially fractional numeric values with decimal separators or dates other
200 : than ISO 8601 would be locale dependent and is a no-no. Leading and
201 : trailing blanks are ignored.
202 :
203 : The following ISO 8601 formats are converted:
204 :
205 : CCYY-MM-DD
206 : CCYY-MM-DDThh:mm
207 : CCYY-MM-DDThh:mm:ss
208 : CCYY-MM-DDThh:mm:ss,s
209 : CCYY-MM-DDThh:mm:ss.s
210 : hh:mm
211 : hh:mm:ss
212 : hh:mm:ss,s
213 : hh:mm:ss.s
214 :
215 : The century CC may not be omitted and the two-digit year setting is not
216 : taken into account. Instead of the T date and time separator exactly one
217 : blank may be used.
218 :
219 : If a date is given, it must be a valid Gregorian calendar date. In this
220 : case the optional time must be in the range 00:00 to 23:59:59.99999...
221 : If only time is given, it may have any value for hours, taking elapsed time
222 : into account; minutes and seconds are limited to the value 59 as well.
223 : */
224 :
225 33 : double ScInterpreter::ConvertStringToValue( const String& rStr )
226 : {
227 : #if 1
228 : // We keep this code until we provide a friendly way to convert string
229 : // numbers into numbers in the UI.
230 33 : double fValue = 0.0;
231 33 : if (mnStringNoValueError == errCellNoValue)
232 : {
233 : // Requested that all strings result in 0, error handled by caller.
234 13 : SetError( mnStringNoValueError);
235 13 : return fValue;
236 : }
237 :
238 20 : if (GetGlobalConfig().mbEmptyStringAsZero)
239 : {
240 : // The number scanner does not accept empty strings or strings
241 : // containing only spaces, be on par in these cases with what was
242 : // accepted in OOo and is in AOO (see also the else branch below) and
243 : // convert to 0 to prevent interoperability nightmares.
244 4 : if (!rStr.Len())
245 1 : return fValue;
246 3 : else if (rStr.GetChar(0) == ' ')
247 : {
248 3 : const sal_Unicode* p = rStr.GetBuffer() + 1;
249 3 : const sal_Unicode* const pStop = p - 1 + rStr.Len();
250 6 : while (p < pStop && *p == ' ')
251 0 : ++p;
252 3 : if (p == pStop)
253 1 : return fValue;
254 : }
255 : }
256 :
257 18 : sal_uInt32 nFIndex = 0;
258 18 : if (!pFormatter->IsNumberFormat(rStr, nFIndex, fValue))
259 : {
260 16 : SetError( mnStringNoValueError);
261 16 : fValue = 0.0;
262 : }
263 18 : return fValue;
264 : #else
265 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ConvertStringToValue" );
266 : double fValue = 0.0;
267 : if (mnStringNoValueError == errCellNoValue)
268 : {
269 : // Requested that all strings result in 0, error handled by caller.
270 : SetError( mnStringNoValueError);
271 : return fValue;
272 : }
273 : ::rtl::OUString aStr( rStr);
274 : rtl_math_ConversionStatus eStatus;
275 : sal_Int32 nParseEnd;
276 : // Decimal and group separator 0 => only integer and possibly exponent,
277 : // stops at first non-digit non-sign.
278 : fValue = ::rtl::math::stringToDouble( aStr, 0, 0, &eStatus, &nParseEnd);
279 : sal_Int32 nLen;
280 : if (eStatus == rtl_math_ConversionStatus_Ok && nParseEnd < (nLen = aStr.getLength()))
281 : {
282 : // Not at string end, check for trailing blanks or switch to date or
283 : // time parsing or bail out.
284 : const sal_Unicode* const pStart = aStr.getStr();
285 : const sal_Unicode* p = pStart + nParseEnd;
286 : const sal_Unicode* const pStop = pStart + nLen;
287 : switch (*p++)
288 : {
289 : case ' ':
290 : while (p < pStop && *p == ' ')
291 : ++p;
292 : if (p < pStop)
293 : SetError( mnStringNoValueError);
294 : break;
295 : case '-':
296 : case ':':
297 : {
298 : bool bDate = (*(p-1) == '-');
299 : enum State { year = 0, month, day, hour, minute, second, fraction, done, blank, stop };
300 : sal_Int32 nUnit[done] = {0,0,0,0,0,0,0};
301 : const sal_Int32 nLimit[done] = {0,12,31,0,59,59,0};
302 : State eState = (bDate ? month : minute);
303 : nCurFmtType = (bDate ? NUMBERFORMAT_DATE : NUMBERFORMAT_TIME);
304 : nUnit[eState-1] = aStr.copy( 0, nParseEnd).toInt32();
305 : const sal_Unicode* pLastStart = p;
306 : // Ensure there's no preceding sign. Negative dates
307 : // currently aren't handled correctly. Also discard
308 : // +CCYY-MM-DD
309 : p = pStart;
310 : while (p < pStop && *p == ' ')
311 : ++p;
312 : if (p < pStop && !CharClass::isAsciiDigit(*p))
313 : SetError( mnStringNoValueError);
314 : p = pLastStart;
315 : while (p < pStop && !nGlobalError && eState < blank)
316 : {
317 : if (eState == minute)
318 : nCurFmtType |= NUMBERFORMAT_TIME;
319 : if (CharClass::isAsciiDigit(*p))
320 : {
321 : // Maximum 2 digits per unit, except fractions.
322 : if (p - pLastStart >= 2 && eState != fraction)
323 : SetError( mnStringNoValueError);
324 : }
325 : else if (p > pLastStart)
326 : {
327 : // We had at least one digit.
328 : if (eState < done)
329 : {
330 : nUnit[eState] = aStr.copy( pLastStart - pStart, p - pLastStart).toInt32();
331 : if (nLimit[eState] && nLimit[eState] < nUnit[eState])
332 : SetError( mnStringNoValueError);
333 : }
334 : pLastStart = p + 1; // hypothetical next start
335 : // Delimiters must match, a trailing delimiter
336 : // yields an invalid date/time.
337 : switch (eState)
338 : {
339 : case month:
340 : // Month must be followed by separator and
341 : // day, no trailing blanks.
342 : if (*p != '-' || (p+1 == pStop))
343 : SetError( mnStringNoValueError);
344 : break;
345 : case day:
346 : if ((*p != 'T' || (p+1 == pStop)) && *p != ' ')
347 : SetError( mnStringNoValueError);
348 : // Take one blank as a valid delimiter
349 : // between date and time.
350 : break;
351 : case hour:
352 : // Hour must be followed by separator and
353 : // minute, no trailing blanks.
354 : if (*p != ':' || (p+1 == pStop))
355 : SetError( mnStringNoValueError);
356 : break;
357 : case minute:
358 : if ((*p != ':' || (p+1 == pStop)) && *p != ' ')
359 : SetError( mnStringNoValueError);
360 : if (*p == ' ')
361 : eState = done;
362 : break;
363 : case second:
364 : if (((*p != ',' && *p != '.') || (p+1 == pStop)) && *p != ' ')
365 : SetError( mnStringNoValueError);
366 : if (*p == ' ')
367 : eState = done;
368 : break;
369 : case fraction:
370 : eState = done;
371 : break;
372 : case year:
373 : case done:
374 : case blank:
375 : case stop:
376 : SetError( mnStringNoValueError);
377 : break;
378 : }
379 : eState = static_cast<State>(eState + 1);
380 : }
381 : else
382 : SetError( mnStringNoValueError);
383 : ++p;
384 : }
385 : if (eState == blank)
386 : {
387 : while (p < pStop && *p == ' ')
388 : ++p;
389 : if (p < pStop)
390 : SetError( mnStringNoValueError);
391 : eState = stop;
392 : }
393 :
394 : // Month without day, or hour without minute.
395 : if (eState == month || (eState == day && p <= pLastStart) ||
396 : eState == hour || (eState == minute && p <= pLastStart))
397 : SetError( mnStringNoValueError);
398 :
399 : if (!nGlobalError)
400 : {
401 : // Catch the very last unit at end of string.
402 : if (p > pLastStart && eState < done)
403 : {
404 : nUnit[eState] = aStr.copy( pLastStart - pStart, p - pLastStart).toInt32();
405 : if (nLimit[eState] && nLimit[eState] < nUnit[eState])
406 : SetError( mnStringNoValueError);
407 : }
408 : if (bDate && nUnit[hour] > 23)
409 : SetError( mnStringNoValueError);
410 : if (!nGlobalError)
411 : {
412 : if (bDate && nUnit[day] == 0)
413 : nUnit[day] = 1;
414 : double fFraction = (nUnit[fraction] <= 0 ? 0.0 :
415 : ::rtl::math::pow10Exp( nUnit[fraction],
416 : static_cast<int>( -ceil( log10( static_cast<double>( nUnit[fraction]))))));
417 : fValue = (bDate ? GetDateSerial(
418 : sal::static_int_cast<sal_Int16>(nUnit[year]),
419 : sal::static_int_cast<sal_Int16>(nUnit[month]),
420 : sal::static_int_cast<sal_Int16>(nUnit[day]),
421 : true, false) : 0.0);
422 : fValue += ((nUnit[hour] * 3600) + (nUnit[minute] * 60) + nUnit[second] + fFraction) / 86400.0;
423 : }
424 : }
425 : }
426 : break;
427 : default:
428 : SetError( mnStringNoValueError);
429 : }
430 : if (nGlobalError)
431 : fValue = 0.0;
432 : }
433 : return fValue;
434 : #endif
435 : }
436 :
437 :
438 5448 : double ScInterpreter::GetCellValue( const ScAddress& rPos, const ScBaseCell* pCell )
439 : {
440 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetCellValue" );
441 5448 : sal_uInt16 nErr = nGlobalError;
442 5448 : nGlobalError = 0;
443 5448 : double nVal = GetCellValueOrZero( rPos, pCell );
444 5448 : if ( !nGlobalError || nGlobalError == errCellNoValue )
445 5428 : nGlobalError = nErr;
446 5448 : return nVal;
447 : }
448 :
449 :
450 5448 : double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, const ScBaseCell* pCell )
451 : {
452 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetCellValueOrZero" );
453 5448 : double fValue = 0.0;
454 5448 : if (pCell)
455 : {
456 5448 : CellType eType = pCell->GetCellType();
457 5448 : switch ( eType )
458 : {
459 : case CELLTYPE_FORMULA:
460 : {
461 1773 : ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
462 1773 : sal_uInt16 nErr = pFCell->GetErrCode();
463 1773 : if( !nErr )
464 : {
465 1765 : if (pFCell->IsValue())
466 : {
467 1756 : fValue = pFCell->GetValue();
468 : pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex,
469 1756 : rPos, pFCell );
470 : }
471 : else
472 : {
473 9 : String aStr = pFCell->GetString();
474 9 : fValue = ConvertStringToValue( aStr );
475 : }
476 : }
477 : else
478 : {
479 8 : fValue = 0.0;
480 8 : SetError(nErr);
481 : }
482 : }
483 1773 : break;
484 : case CELLTYPE_VALUE:
485 : {
486 3637 : fValue = ((ScValueCell*)pCell)->GetValue();
487 3637 : nCurFmtIndex = pDok->GetNumberFormat( rPos );
488 3637 : nCurFmtType = pFormatter->GetType( nCurFmtIndex );
489 3637 : if ( bCalcAsShown && fValue != 0.0 )
490 0 : fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex );
491 : }
492 3637 : break;
493 : case CELLTYPE_STRING:
494 : case CELLTYPE_EDIT:
495 : {
496 : // SUM(A1:A2) differs from A1+A2. No good. But people insist on
497 : // it ... #i5658#
498 6 : String aStr;
499 6 : if ( eType == CELLTYPE_STRING )
500 6 : aStr = ((ScStringCell*)pCell)->GetString();
501 : else
502 0 : aStr = ((ScEditCell*)pCell)->GetString();
503 6 : fValue = ConvertStringToValue( aStr );
504 : }
505 6 : break;
506 : case CELLTYPE_NONE:
507 : case CELLTYPE_NOTE:
508 32 : fValue = 0.0; // empty or broadcaster cell
509 32 : break;
510 : case CELLTYPE_SYMBOLS:
511 : #if OSL_DEBUG_LEVEL > 0
512 : case CELLTYPE_DESTROYED:
513 : #endif
514 0 : SetError(errCellNoValue);
515 0 : fValue = 0.0;
516 0 : break;
517 : }
518 : }
519 : else
520 0 : fValue = 0.0;
521 5448 : return fValue;
522 : }
523 :
524 :
525 151 : void ScInterpreter::GetCellString( String& rStr, const ScBaseCell* pCell )
526 : {
527 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetCellString" );
528 151 : sal_uInt16 nErr = 0;
529 151 : if (pCell)
530 : {
531 151 : switch (pCell->GetCellType())
532 : {
533 : case CELLTYPE_STRING:
534 151 : rStr = ((ScStringCell*) pCell)->GetString();
535 151 : break;
536 : case CELLTYPE_EDIT:
537 0 : rStr = ((ScEditCell*) pCell)->GetString();
538 0 : break;
539 : case CELLTYPE_FORMULA:
540 : {
541 0 : ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
542 0 : nErr = pFCell->GetErrCode();
543 0 : if (pFCell->IsValue())
544 : {
545 0 : double fVal = pFCell->GetValue();
546 : sal_uLong nIndex = pFormatter->GetStandardFormat(
547 : NUMBERFORMAT_NUMBER,
548 0 : ScGlobal::eLnge);
549 0 : pFormatter->GetInputLineString(fVal, nIndex, rStr);
550 : }
551 : else
552 0 : rStr = pFCell->GetString();
553 : }
554 0 : break;
555 : case CELLTYPE_VALUE:
556 : {
557 0 : double fVal = ((ScValueCell*) pCell)->GetValue();
558 : sal_uLong nIndex = pFormatter->GetStandardFormat(
559 : NUMBERFORMAT_NUMBER,
560 0 : ScGlobal::eLnge);
561 0 : pFormatter->GetInputLineString(fVal, nIndex, rStr);
562 : }
563 0 : break;
564 : default:
565 0 : rStr = ScGlobal::GetEmptyString();
566 0 : break;
567 : }
568 : }
569 : else
570 0 : rStr = ScGlobal::GetEmptyString();
571 151 : SetError(nErr);
572 151 : }
573 :
574 :
575 0 : bool ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
576 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr)
577 : {
578 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateDoubleArr" );
579 :
580 : // Old Add-Ins are hard limited to sal_uInt16 values.
581 : #if MAXCOLCOUNT_DEFINE > USHRT_MAX
582 : #error Add check for columns > USHRT_MAX!
583 : #endif
584 0 : if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
585 0 : return false;
586 :
587 0 : sal_uInt16 nCount = 0;
588 0 : sal_uInt16* p = (sal_uInt16*) pCellArr;
589 0 : *p++ = static_cast<sal_uInt16>(nCol1);
590 0 : *p++ = static_cast<sal_uInt16>(nRow1);
591 0 : *p++ = static_cast<sal_uInt16>(nTab1);
592 0 : *p++ = static_cast<sal_uInt16>(nCol2);
593 0 : *p++ = static_cast<sal_uInt16>(nRow2);
594 0 : *p++ = static_cast<sal_uInt16>(nTab2);
595 0 : sal_uInt16* pCount = p;
596 0 : *p++ = 0;
597 0 : sal_uInt16 nPos = 14;
598 0 : SCTAB nTab = nTab1;
599 0 : ScAddress aAdr;
600 0 : while (nTab <= nTab2)
601 : {
602 0 : aAdr.SetTab( nTab );
603 0 : SCROW nRow = nRow1;
604 0 : while (nRow <= nRow2)
605 : {
606 0 : aAdr.SetRow( nRow );
607 0 : SCCOL nCol = nCol1;
608 0 : while (nCol <= nCol2)
609 : {
610 0 : aAdr.SetCol( nCol );
611 0 : ScBaseCell* pCell = pDok->GetCell( aAdr );
612 0 : if (pCell)
613 : {
614 0 : sal_uInt16 nErr = 0;
615 0 : double nVal = 0.0;
616 0 : bool bOk = true;
617 0 : switch ( pCell->GetCellType() )
618 : {
619 : case CELLTYPE_VALUE :
620 0 : nVal = GetValueCellValue( aAdr, (ScValueCell*)pCell );
621 0 : break;
622 : case CELLTYPE_FORMULA :
623 0 : if (((ScFormulaCell*)pCell)->IsValue())
624 : {
625 0 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
626 0 : nVal = ((ScFormulaCell*)pCell)->GetValue();
627 : }
628 : else
629 0 : bOk = false;
630 0 : break;
631 : default :
632 0 : bOk = false;
633 0 : break;
634 : }
635 0 : if (bOk)
636 : {
637 0 : if ((nPos + (4 * sizeof(sal_uInt16)) + sizeof(double)) > MAXARRSIZE)
638 0 : return false;
639 0 : *p++ = static_cast<sal_uInt16>(nCol);
640 0 : *p++ = static_cast<sal_uInt16>(nRow);
641 0 : *p++ = static_cast<sal_uInt16>(nTab);
642 0 : *p++ = nErr;
643 0 : memcpy( p, &nVal, sizeof(double));
644 0 : nPos += 8 + sizeof(double);
645 0 : p = (sal_uInt16*) ( pCellArr + nPos );
646 0 : nCount++;
647 : }
648 : }
649 0 : nCol++;
650 : }
651 0 : nRow++;
652 : }
653 0 : nTab++;
654 : }
655 0 : *pCount = nCount;
656 0 : return true;
657 : }
658 :
659 :
660 0 : bool ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
661 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
662 : sal_uInt8* pCellArr)
663 : {
664 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateStringArr" );
665 :
666 : // Old Add-Ins are hard limited to sal_uInt16 values.
667 : #if MAXCOLCOUNT_DEFINE > USHRT_MAX
668 : #error Add check for columns > USHRT_MAX!
669 : #endif
670 0 : if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
671 0 : return false;
672 :
673 0 : sal_uInt16 nCount = 0;
674 0 : sal_uInt16* p = (sal_uInt16*) pCellArr;
675 0 : *p++ = static_cast<sal_uInt16>(nCol1);
676 0 : *p++ = static_cast<sal_uInt16>(nRow1);
677 0 : *p++ = static_cast<sal_uInt16>(nTab1);
678 0 : *p++ = static_cast<sal_uInt16>(nCol2);
679 0 : *p++ = static_cast<sal_uInt16>(nRow2);
680 0 : *p++ = static_cast<sal_uInt16>(nTab2);
681 0 : sal_uInt16* pCount = p;
682 0 : *p++ = 0;
683 0 : sal_uInt16 nPos = 14;
684 0 : SCTAB nTab = nTab1;
685 0 : while (nTab <= nTab2)
686 : {
687 0 : SCROW nRow = nRow1;
688 0 : while (nRow <= nRow2)
689 : {
690 0 : SCCOL nCol = nCol1;
691 0 : while (nCol <= nCol2)
692 : {
693 : ScBaseCell* pCell;
694 0 : pDok->GetCell(nCol, nRow, nTab, pCell);
695 0 : if (pCell)
696 : {
697 0 : String aStr;
698 0 : sal_uInt16 nErr = 0;
699 0 : bool bOk = true;
700 0 : switch ( pCell->GetCellType() )
701 : {
702 : case CELLTYPE_STRING :
703 0 : aStr = ((ScStringCell*)pCell)->GetString();
704 0 : break;
705 : case CELLTYPE_EDIT :
706 0 : aStr = ((ScEditCell*)pCell)->GetString();
707 0 : break;
708 : case CELLTYPE_FORMULA :
709 0 : if (!((ScFormulaCell*)pCell)->IsValue())
710 : {
711 0 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
712 0 : aStr = ((ScFormulaCell*)pCell)->GetString();
713 : }
714 : else
715 0 : bOk = false;
716 0 : break;
717 : default :
718 0 : bOk = false;
719 0 : break;
720 : }
721 0 : if (bOk)
722 : {
723 : rtl::OString aTmp(rtl::OUStringToOString(aStr,
724 0 : osl_getThreadTextEncoding()));
725 : // In case the xub_StrLen will be longer than USHORT
726 : // one day, and room for pad byte check.
727 0 : if ( aTmp.getLength() > ((sal_uInt16)(~0)) - 2 )
728 0 : return false;
729 : // Append a 0-pad-byte if string length is not even
730 : //! MUST be sal_uInt16 and not xub_StrLen
731 0 : sal_uInt16 nStrLen = (sal_uInt16) aTmp.getLength();
732 0 : sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
733 :
734 0 : if (((sal_uLong)nPos + (5 * sizeof(sal_uInt16)) + nLen) > MAXARRSIZE)
735 0 : return false;
736 0 : *p++ = static_cast<sal_uInt16>(nCol);
737 0 : *p++ = static_cast<sal_uInt16>(nRow);
738 0 : *p++ = static_cast<sal_uInt16>(nTab);
739 0 : *p++ = nErr;
740 0 : *p++ = nLen;
741 0 : memcpy( p, aTmp.getStr(), nStrLen + 1);
742 0 : nPos += 10 + nStrLen + 1;
743 0 : sal_uInt8* q = ( pCellArr + nPos );
744 0 : if( !nStrLen & 1 )
745 0 : *q++ = 0, nPos++;
746 0 : p = (sal_uInt16*) ( pCellArr + nPos );
747 0 : nCount++;
748 0 : }
749 : }
750 0 : nCol++;
751 : }
752 0 : nRow++;
753 : }
754 0 : nTab++;
755 : }
756 0 : *pCount = nCount;
757 0 : return true;
758 : }
759 :
760 :
761 0 : bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
762 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
763 : sal_uInt8* pCellArr)
764 : {
765 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateCellArr" );
766 :
767 : // Old Add-Ins are hard limited to sal_uInt16 values.
768 : #if MAXCOLCOUNT_DEFINE > USHRT_MAX
769 : #error Add check for columns > USHRT_MAX!
770 : #endif
771 0 : if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
772 0 : return false;
773 :
774 0 : sal_uInt16 nCount = 0;
775 0 : sal_uInt16* p = (sal_uInt16*) pCellArr;
776 0 : *p++ = static_cast<sal_uInt16>(nCol1);
777 0 : *p++ = static_cast<sal_uInt16>(nRow1);
778 0 : *p++ = static_cast<sal_uInt16>(nTab1);
779 0 : *p++ = static_cast<sal_uInt16>(nCol2);
780 0 : *p++ = static_cast<sal_uInt16>(nRow2);
781 0 : *p++ = static_cast<sal_uInt16>(nTab2);
782 0 : sal_uInt16* pCount = p;
783 0 : *p++ = 0;
784 0 : sal_uInt16 nPos = 14;
785 0 : SCTAB nTab = nTab1;
786 0 : ScAddress aAdr;
787 0 : while (nTab <= nTab2)
788 : {
789 0 : aAdr.SetTab( nTab );
790 0 : SCROW nRow = nRow1;
791 0 : while (nRow <= nRow2)
792 : {
793 0 : aAdr.SetRow( nRow );
794 0 : SCCOL nCol = nCol1;
795 0 : while (nCol <= nCol2)
796 : {
797 0 : aAdr.SetCol( nCol );
798 0 : ScBaseCell* pCell = pDok->GetCell( aAdr );
799 0 : if (pCell)
800 : {
801 0 : sal_uInt16 nErr = 0;
802 0 : sal_uInt16 nType = 0; // 0 = Zahl; 1 = String
803 0 : double nVal = 0.0;
804 0 : String aStr;
805 0 : bool bOk = true;
806 0 : switch ( pCell->GetCellType() )
807 : {
808 : case CELLTYPE_STRING :
809 0 : aStr = ((ScStringCell*)pCell)->GetString();
810 0 : nType = 1;
811 0 : break;
812 : case CELLTYPE_EDIT :
813 0 : aStr = ((ScEditCell*)pCell)->GetString();
814 0 : nType = 1;
815 0 : break;
816 : case CELLTYPE_VALUE :
817 0 : nVal = GetValueCellValue( aAdr, (ScValueCell*)pCell );
818 0 : break;
819 : case CELLTYPE_FORMULA :
820 0 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
821 0 : if (((ScFormulaCell*)pCell)->IsValue())
822 0 : nVal = ((ScFormulaCell*)pCell)->GetValue();
823 : else
824 0 : aStr = ((ScFormulaCell*)pCell)->GetString();
825 0 : break;
826 : default :
827 0 : bOk = false;
828 0 : break;
829 : }
830 0 : if (bOk)
831 : {
832 0 : if ((nPos + (5 * sizeof(sal_uInt16))) > MAXARRSIZE)
833 0 : return false;
834 0 : *p++ = static_cast<sal_uInt16>(nCol);
835 0 : *p++ = static_cast<sal_uInt16>(nRow);
836 0 : *p++ = static_cast<sal_uInt16>(nTab);
837 0 : *p++ = nErr;
838 0 : *p++ = nType;
839 0 : nPos += 10;
840 0 : if (nType == 0)
841 : {
842 0 : if ((nPos + sizeof(double)) > MAXARRSIZE)
843 0 : return false;
844 0 : memcpy( p, &nVal, sizeof(double));
845 0 : nPos += sizeof(double);
846 : }
847 : else
848 : {
849 : rtl::OString aTmp(rtl::OUStringToOString(aStr,
850 0 : osl_getThreadTextEncoding()));
851 : // In case the xub_StrLen will be longer than USHORT
852 : // one day, and room for pad byte check.
853 0 : if ( aTmp.getLength() > ((sal_uInt16)(~0)) - 2 )
854 0 : return false;
855 : // Append a 0-pad-byte if string length is not even
856 : //! MUST be sal_uInt16 and not xub_StrLen
857 0 : sal_uInt16 nStrLen = (sal_uInt16) aTmp.getLength();
858 0 : sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
859 0 : if ( ((sal_uLong)nPos + 2 + nLen) > MAXARRSIZE)
860 0 : return false;
861 0 : *p++ = nLen;
862 0 : memcpy( p, aTmp.getStr(), nStrLen + 1);
863 0 : nPos += 2 + nStrLen + 1;
864 0 : sal_uInt8* q = ( pCellArr + nPos );
865 0 : if( !nStrLen & 1 )
866 0 : *q++ = 0, nPos++;
867 : }
868 0 : nCount++;
869 0 : p = (sal_uInt16*) ( pCellArr + nPos );
870 0 : }
871 : }
872 0 : nCol++;
873 : }
874 0 : nRow++;
875 : }
876 0 : nTab++;
877 : }
878 0 : *pCount = nCount;
879 0 : return true;
880 : }
881 :
882 :
883 : //-----------------------------------------------------------------------------
884 : // Stack operations
885 : //-----------------------------------------------------------------------------
886 :
887 :
888 : // Also releases a TempToken if appropriate.
889 :
890 8044 : void ScInterpreter::PushWithoutError( FormulaToken& r )
891 : {
892 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushWithoutError" );
893 8044 : if ( sp >= MAXSTACK )
894 0 : SetError( errStackOverflow );
895 : else
896 : {
897 8044 : nCurFmtType = NUMBERFORMAT_UNDEFINED;
898 8044 : r.IncRef();
899 8044 : if( sp >= maxsp )
900 5869 : maxsp = sp + 1;
901 : else
902 2175 : pStack[ sp ]->DecRef();
903 8044 : pStack[ sp ] = (ScToken*) &r;
904 8044 : ++sp;
905 : }
906 8044 : }
907 :
908 42 : void ScInterpreter::Push( FormulaToken& r )
909 : {
910 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Push" );
911 42 : if ( sp >= MAXSTACK )
912 0 : SetError( errStackOverflow );
913 : else
914 : {
915 42 : if (nGlobalError)
916 : {
917 0 : if (r.GetType() == svError)
918 : {
919 0 : r.SetError( nGlobalError);
920 0 : PushWithoutError( r);
921 : }
922 : else
923 0 : PushWithoutError( *(new FormulaErrorToken( nGlobalError)));
924 : }
925 : else
926 42 : PushWithoutError( r);
927 : }
928 42 : }
929 :
930 :
931 32 : void ScInterpreter::PushTempToken( FormulaToken* p )
932 : {
933 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushTempToken" );
934 32 : if ( sp >= MAXSTACK )
935 : {
936 0 : SetError( errStackOverflow );
937 0 : if (!p->GetRef())
938 : //! p is a dangling pointer hereafter!
939 0 : p->Delete();
940 : }
941 : else
942 : {
943 32 : if (nGlobalError)
944 : {
945 0 : if (p->GetType() == svError)
946 : {
947 0 : p->SetError( nGlobalError);
948 0 : PushTempTokenWithoutError( p);
949 : }
950 : else
951 : {
952 0 : if (!p->GetRef())
953 : //! p is a dangling pointer hereafter!
954 0 : p->Delete();
955 0 : PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
956 : }
957 : }
958 : else
959 32 : PushTempTokenWithoutError( p);
960 : }
961 32 : }
962 :
963 :
964 5986 : void ScInterpreter::PushTempTokenWithoutError( FormulaToken* p )
965 : {
966 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushTempTokenWithoutError" );
967 5986 : p->IncRef();
968 5986 : if ( sp >= MAXSTACK )
969 : {
970 0 : SetError( errStackOverflow );
971 : //! p may be a dangling pointer hereafter!
972 0 : p->DecRef();
973 : }
974 : else
975 : {
976 5986 : if( sp >= maxsp )
977 45 : maxsp = sp + 1;
978 : else
979 5941 : pStack[ sp ]->DecRef();
980 5986 : pStack[ sp ] = p;
981 5986 : ++sp;
982 : }
983 5986 : }
984 :
985 :
986 21 : void ScInterpreter::PushTempToken( const FormulaToken& r )
987 : {
988 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushTempToken" );
989 21 : if (!IfErrorPushError())
990 20 : PushTempTokenWithoutError( r.Clone());
991 21 : }
992 :
993 :
994 138 : void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
995 : const ScAddress & rAddress, short * pRetTypeExpr, sal_uLong * pRetIndexExpr )
996 : {
997 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushCellResultToken" );
998 138 : ScBaseCell* pCell = pDok->GetCell( rAddress);
999 138 : if (!pCell || pCell->HasEmptyData())
1000 : {
1001 11 : if (pRetTypeExpr && pRetIndexExpr)
1002 11 : pDok->GetNumberFormatInfo( *pRetTypeExpr, *pRetIndexExpr, rAddress, pCell);
1003 11 : bool bInherited = (GetCellType( pCell) == CELLTYPE_FORMULA);
1004 11 : PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString));
1005 149 : return;
1006 : }
1007 : sal_uInt16 nErr;
1008 127 : if ((nErr = pCell->GetErrorCode()) != 0)
1009 : {
1010 0 : PushError( nErr);
1011 0 : if (pRetTypeExpr)
1012 0 : *pRetTypeExpr = NUMBERFORMAT_UNDEFINED;
1013 0 : if (pRetIndexExpr)
1014 0 : *pRetIndexExpr = 0;
1015 : }
1016 127 : else if (pCell->HasStringData())
1017 : {
1018 12 : String aRes;
1019 12 : GetCellString( aRes, pCell);
1020 12 : PushString( aRes);
1021 12 : if (pRetTypeExpr)
1022 12 : *pRetTypeExpr = NUMBERFORMAT_TEXT;
1023 12 : if (pRetIndexExpr)
1024 12 : *pRetIndexExpr = 0;
1025 : }
1026 : else
1027 : {
1028 115 : double fVal = GetCellValue( rAddress, pCell);
1029 115 : PushDouble( fVal);
1030 115 : if (pRetTypeExpr)
1031 99 : *pRetTypeExpr = nCurFmtType;
1032 115 : if (pRetIndexExpr)
1033 99 : *pRetIndexExpr = nCurFmtIndex;
1034 : }
1035 : }
1036 :
1037 :
1038 : // Simply throw away TOS.
1039 :
1040 15 : void ScInterpreter::Pop()
1041 : {
1042 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Pop" );
1043 15 : if( sp )
1044 15 : sp--;
1045 : else
1046 0 : SetError(errUnknownStackVariable);
1047 15 : }
1048 :
1049 :
1050 : // Simply throw away TOS and set error code, used with ocIsError et al.
1051 :
1052 12 : void ScInterpreter::PopError()
1053 : {
1054 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopError" );
1055 12 : if( sp )
1056 : {
1057 12 : sp--;
1058 12 : if (pStack[sp]->GetType() == svError)
1059 7 : nGlobalError = pStack[sp]->GetError();
1060 : }
1061 : else
1062 0 : SetError(errUnknownStackVariable);
1063 12 : }
1064 :
1065 :
1066 3011 : FormulaTokenRef ScInterpreter::PopToken()
1067 : {
1068 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopToken" );
1069 3011 : if (sp)
1070 : {
1071 3011 : sp--;
1072 3011 : FormulaToken* p = pStack[ sp ];
1073 3011 : if (p->GetType() == svError)
1074 62 : nGlobalError = p->GetError();
1075 3011 : return p;
1076 : }
1077 : else
1078 0 : SetError(errUnknownStackVariable);
1079 0 : return NULL;
1080 : }
1081 :
1082 :
1083 4427 : double ScInterpreter::PopDouble()
1084 : {
1085 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDouble" );
1086 4427 : nCurFmtType = NUMBERFORMAT_NUMBER;
1087 4427 : nCurFmtIndex = 0;
1088 4427 : if( sp )
1089 : {
1090 4427 : --sp;
1091 4427 : FormulaToken* p = pStack[ sp ];
1092 4427 : switch (p->GetType())
1093 : {
1094 : case svError:
1095 0 : nGlobalError = p->GetError();
1096 0 : break;
1097 : case svDouble:
1098 4427 : return p->GetDouble();
1099 : case svEmptyCell:
1100 : case svMissing:
1101 0 : return 0.0;
1102 : default:
1103 0 : SetError( errIllegalArgument);
1104 : }
1105 : }
1106 : else
1107 0 : SetError( errUnknownStackVariable);
1108 0 : return 0.0;
1109 : }
1110 :
1111 :
1112 83 : const String& ScInterpreter::PopString()
1113 : {
1114 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopString" );
1115 83 : nCurFmtType = NUMBERFORMAT_TEXT;
1116 83 : nCurFmtIndex = 0;
1117 83 : if( sp )
1118 : {
1119 83 : --sp;
1120 83 : FormulaToken* p = pStack[ sp ];
1121 83 : switch (p->GetType())
1122 : {
1123 : case svError:
1124 0 : nGlobalError = p->GetError();
1125 0 : break;
1126 : case svString:
1127 83 : return p->GetString();
1128 : case svEmptyCell:
1129 : case svMissing:
1130 0 : return EMPTY_STRING;
1131 : default:
1132 0 : SetError( errIllegalArgument);
1133 : }
1134 : }
1135 : else
1136 0 : SetError( errUnknownStackVariable);
1137 0 : return EMPTY_STRING;
1138 : }
1139 :
1140 :
1141 0 : void ScInterpreter::ValidateRef( const ScSingleRefData & rRef )
1142 : {
1143 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ValidateRef" );
1144 : SCCOL nCol;
1145 : SCROW nRow;
1146 : SCTAB nTab;
1147 0 : SingleRefToVars( rRef, nCol, nRow, nTab);
1148 0 : }
1149 :
1150 :
1151 0 : void ScInterpreter::ValidateRef( const ScComplexRefData & rRef )
1152 : {
1153 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ValidateRef" );
1154 0 : ValidateRef( rRef.Ref1);
1155 0 : ValidateRef( rRef.Ref2);
1156 0 : }
1157 :
1158 :
1159 0 : void ScInterpreter::ValidateRef( const ScRefList & rRefList )
1160 : {
1161 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ValidateRef" );
1162 0 : ScRefList::const_iterator it( rRefList.begin());
1163 0 : ScRefList::const_iterator end( rRefList.end());
1164 0 : for ( ; it != end; ++it)
1165 : {
1166 0 : ValidateRef( *it);
1167 : }
1168 0 : }
1169 :
1170 :
1171 7234 : void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef,
1172 : SCCOL & rCol, SCROW & rRow, SCTAB & rTab )
1173 : {
1174 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::SingleRefToVars" );
1175 7234 : if ( rRef.IsColRel() )
1176 7141 : rCol = aPos.Col() + rRef.nRelCol;
1177 : else
1178 93 : rCol = rRef.nCol;
1179 7234 : if ( rRef.IsRowRel() )
1180 7114 : rRow = aPos.Row() + rRef.nRelRow;
1181 : else
1182 120 : rRow = rRef.nRow;
1183 7234 : if ( rRef.IsTabRel() )
1184 7144 : rTab = aPos.Tab() + rRef.nRelTab;
1185 : else
1186 90 : rTab = rRef.nTab;
1187 7234 : if( !ValidCol( rCol) || rRef.IsColDeleted() )
1188 0 : SetError( errNoRef ), rCol = 0;
1189 7234 : if( !ValidRow( rRow) || rRef.IsRowDeleted() )
1190 0 : SetError( errNoRef ), rRow = 0;
1191 7234 : if( !ValidTab( rTab, pDok->GetTableCount() - 1) || rRef.IsTabDeleted() )
1192 0 : SetError( errNoRef ), rTab = 0;
1193 7234 : }
1194 :
1195 :
1196 11 : void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
1197 : {
1198 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopSingleRef" );
1199 11 : if( sp )
1200 : {
1201 11 : --sp;
1202 11 : FormulaToken* p = pStack[ sp ];
1203 11 : switch (p->GetType())
1204 : {
1205 : case svError:
1206 0 : nGlobalError = p->GetError();
1207 0 : break;
1208 : case svSingleRef:
1209 11 : SingleRefToVars( static_cast<ScToken*>(p)->GetSingleRef(), rCol, rRow, rTab);
1210 11 : if ( !pDok->aTableOpList.empty() )
1211 0 : ReplaceCell( rCol, rRow, rTab );
1212 11 : break;
1213 : default:
1214 0 : SetError( errIllegalParameter);
1215 : }
1216 : }
1217 : else
1218 0 : SetError( errUnknownStackVariable);
1219 11 : }
1220 :
1221 :
1222 5609 : void ScInterpreter::PopSingleRef( ScAddress& rAdr )
1223 : {
1224 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopSingleRef" );
1225 5609 : if( sp )
1226 : {
1227 5609 : --sp;
1228 5609 : FormulaToken* p = pStack[ sp ];
1229 5609 : switch (p->GetType())
1230 : {
1231 : case svError:
1232 0 : nGlobalError = p->GetError();
1233 0 : break;
1234 : case svSingleRef:
1235 : {
1236 : SCCOL nCol;
1237 : SCROW nRow;
1238 : SCTAB nTab;
1239 5609 : SingleRefToVars( static_cast<ScToken*>(p)->GetSingleRef(), nCol, nRow, nTab);
1240 5609 : rAdr.Set( nCol, nRow, nTab );
1241 5609 : if ( !pDok->aTableOpList.empty() )
1242 0 : ReplaceCell( rAdr );
1243 : }
1244 5609 : break;
1245 : default:
1246 0 : SetError( errIllegalParameter);
1247 : }
1248 : }
1249 : else
1250 0 : SetError( errUnknownStackVariable);
1251 5609 : }
1252 :
1253 :
1254 91 : void ScInterpreter::DoubleRefToVars( const ScToken* p,
1255 : SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1256 : SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1257 : bool bDontCheckForTableOp )
1258 : {
1259 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DoubleRefToVars" );
1260 91 : const ScComplexRefData& rCRef = p->GetDoubleRef();
1261 91 : SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1);
1262 91 : SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2);
1263 91 : if ( !pDok->aTableOpList.empty() && !bDontCheckForTableOp )
1264 : {
1265 0 : ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 );
1266 0 : if ( IsTableOpInRange( aRange ) )
1267 0 : SetError( errIllegalParameter );
1268 : }
1269 91 : }
1270 :
1271 16 : ScDBRangeBase* ScInterpreter::PopDBDoubleRef()
1272 : {
1273 16 : StackVar eType = GetStackType();
1274 16 : switch (eType)
1275 : {
1276 : case svUnknown:
1277 0 : SetError(errUnknownStackVariable);
1278 0 : break;
1279 : case svError:
1280 0 : PopError();
1281 0 : break;
1282 : case svDoubleRef:
1283 : {
1284 : SCCOL nCol1, nCol2;
1285 : SCROW nRow1, nRow2;
1286 : SCTAB nTab1, nTab2;
1287 16 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
1288 16 : if (nGlobalError)
1289 : break;
1290 : return new ScDBInternalRange(pDok,
1291 16 : ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
1292 : }
1293 : case svMatrix:
1294 : case svExternalDoubleRef:
1295 : {
1296 0 : ScMatrixRef pMat;
1297 0 : if (eType == svMatrix)
1298 0 : pMat = PopMatrix();
1299 : else
1300 0 : PopExternalDoubleRef(pMat);
1301 0 : if (nGlobalError)
1302 : break;
1303 0 : return new ScDBExternalRange(pDok, pMat);
1304 : }
1305 : default:
1306 0 : SetError( errIllegalParameter);
1307 : }
1308 :
1309 0 : return NULL;
1310 : }
1311 :
1312 79 : void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1313 : SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1314 : bool bDontCheckForTableOp )
1315 : {
1316 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRef" );
1317 79 : if( sp )
1318 : {
1319 79 : --sp;
1320 79 : FormulaToken* p = pStack[ sp ];
1321 79 : switch (p->GetType())
1322 : {
1323 : case svError:
1324 0 : nGlobalError = p->GetError();
1325 0 : break;
1326 : case svDoubleRef:
1327 : DoubleRefToVars( static_cast<ScToken*>(p), rCol1, rRow1, rTab1, rCol2, rRow2, rTab2,
1328 79 : bDontCheckForTableOp);
1329 79 : break;
1330 : default:
1331 0 : SetError( errIllegalParameter);
1332 : }
1333 : }
1334 : else
1335 0 : SetError( errUnknownStackVariable);
1336 79 : }
1337 :
1338 :
1339 716 : void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef,
1340 : ScRange & rRange, bool bDontCheckForTableOp )
1341 : {
1342 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DoubleRefToRange" );
1343 : SCCOL nCol;
1344 : SCROW nRow;
1345 : SCTAB nTab;
1346 716 : SingleRefToVars( rCRef.Ref1, nCol, nRow, nTab);
1347 716 : rRange.aStart.Set( nCol, nRow, nTab );
1348 716 : SingleRefToVars( rCRef.Ref2, nCol, nRow, nTab);
1349 716 : rRange.aEnd.Set( nCol, nRow, nTab );
1350 716 : if (! pDok->aTableOpList.empty() && !bDontCheckForTableOp )
1351 : {
1352 0 : if ( IsTableOpInRange( rRange ) )
1353 0 : SetError( errIllegalParameter );
1354 : }
1355 716 : }
1356 :
1357 :
1358 702 : void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList )
1359 : {
1360 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRef" );
1361 702 : if (sp)
1362 : {
1363 702 : formula::FormulaToken* pToken = pStack[ sp-1 ];
1364 702 : ScToken* p = static_cast<ScToken*>(pToken);
1365 702 : switch (pToken->GetType())
1366 : {
1367 : case svError:
1368 0 : nGlobalError = p->GetError();
1369 0 : break;
1370 : case svDoubleRef:
1371 702 : --sp;
1372 702 : DoubleRefToRange( p->GetDoubleRef(), rRange);
1373 702 : break;
1374 : case svRefList:
1375 : {
1376 0 : const ScRefList* pList = p->GetRefList();
1377 0 : if (rRefInList < pList->size())
1378 : {
1379 0 : DoubleRefToRange( (*pList)[rRefInList], rRange);
1380 0 : if (++rRefInList < pList->size())
1381 0 : ++rParam;
1382 : else
1383 : {
1384 0 : --sp;
1385 0 : rRefInList = 0;
1386 : }
1387 : }
1388 : else
1389 : {
1390 0 : --sp;
1391 0 : rRefInList = 0;
1392 0 : SetError( errIllegalParameter);
1393 : }
1394 : }
1395 0 : break;
1396 : default:
1397 0 : SetError( errIllegalParameter);
1398 : }
1399 : }
1400 : else
1401 0 : SetError( errUnknownStackVariable);
1402 702 : }
1403 :
1404 :
1405 14 : void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
1406 : {
1407 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRef" );
1408 14 : if( sp )
1409 : {
1410 14 : --sp;
1411 14 : FormulaToken* p = pStack[ sp ];
1412 14 : switch (p->GetType())
1413 : {
1414 : case svError:
1415 0 : nGlobalError = p->GetError();
1416 0 : break;
1417 : case svDoubleRef:
1418 14 : DoubleRefToRange( static_cast<ScToken*>(p)->GetDoubleRef(), rRange, bDontCheckForTableOp);
1419 14 : break;
1420 : default:
1421 0 : SetError( errIllegalParameter);
1422 : }
1423 : }
1424 : else
1425 0 : SetError( errUnknownStackVariable);
1426 14 : }
1427 :
1428 23 : void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, String& rTabName, ScSingleRefData& rRef)
1429 : {
1430 23 : if (!sp)
1431 : {
1432 0 : SetError(errUnknownStackVariable);
1433 0 : return;
1434 : }
1435 :
1436 23 : --sp;
1437 23 : FormulaToken* p = pStack[sp];
1438 23 : StackVar eType = p->GetType();
1439 :
1440 23 : if (eType == svError)
1441 : {
1442 0 : nGlobalError = p->GetError();
1443 0 : return;
1444 : }
1445 :
1446 23 : if (eType != svExternalSingleRef)
1447 : {
1448 0 : SetError( errIllegalParameter);
1449 0 : return;
1450 : }
1451 :
1452 23 : rFileId = p->GetIndex();
1453 23 : rTabName = p->GetString();
1454 23 : rRef = static_cast<ScToken*>(p)->GetSingleRef();
1455 : }
1456 :
1457 23 : void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1458 : {
1459 : sal_uInt16 nFileId;
1460 23 : String aTabName;
1461 : ScSingleRefData aData;
1462 23 : PopExternalSingleRef(nFileId, aTabName, aData, rToken, pFmt);
1463 23 : }
1464 :
1465 23 : void ScInterpreter::PopExternalSingleRef(
1466 : sal_uInt16& rFileId, String& rTabName, ScSingleRefData& rRef,
1467 : ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1468 : {
1469 23 : PopExternalSingleRef(rFileId, rTabName, rRef);
1470 23 : if (nGlobalError)
1471 : return;
1472 :
1473 23 : ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1474 23 : const rtl::OUString* pFile = pRefMgr->getExternalFileName(rFileId);
1475 23 : if (!pFile)
1476 : {
1477 0 : SetError(errNoName);
1478 : return;
1479 : }
1480 :
1481 23 : if (rRef.IsTabRel())
1482 : {
1483 : OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!");
1484 0 : SetError(errNoRef);
1485 : return;
1486 : }
1487 :
1488 23 : rRef.CalcAbsIfRel(aPos);
1489 23 : ScAddress aAddr(rRef.nCol, rRef.nRow, rRef.nTab);
1490 23 : ScExternalRefCache::CellFormat aFmt;
1491 : ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
1492 23 : rFileId, rTabName, aAddr, &aPos, NULL, &aFmt);
1493 :
1494 23 : if (!xNew)
1495 : {
1496 0 : SetError(errNoRef);
1497 : return;
1498 : }
1499 :
1500 23 : rToken = xNew;
1501 23 : if (pFmt)
1502 20 : *pFmt = aFmt;
1503 : }
1504 :
1505 6 : void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, String& rTabName, ScComplexRefData& rRef)
1506 : {
1507 6 : if (!sp)
1508 : {
1509 0 : SetError(errUnknownStackVariable);
1510 0 : return;
1511 : }
1512 :
1513 6 : --sp;
1514 6 : FormulaToken* p = pStack[sp];
1515 6 : StackVar eType = p->GetType();
1516 :
1517 6 : if (eType == svError)
1518 : {
1519 0 : nGlobalError = p->GetError();
1520 0 : return;
1521 : }
1522 :
1523 6 : if (eType != svExternalDoubleRef)
1524 : {
1525 0 : SetError( errIllegalParameter);
1526 0 : return;
1527 : }
1528 :
1529 6 : rFileId = p->GetIndex();
1530 6 : rTabName = p->GetString();
1531 6 : rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1532 : }
1533 :
1534 6 : void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray)
1535 : {
1536 : sal_uInt16 nFileId;
1537 6 : String aTabName;
1538 : ScComplexRefData aData;
1539 6 : PopExternalDoubleRef(nFileId, aTabName, aData);
1540 6 : if (nGlobalError)
1541 : return;
1542 :
1543 6 : GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
1544 6 : if (nGlobalError)
1545 6 : return;
1546 : }
1547 :
1548 6 : void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
1549 : {
1550 6 : ScExternalRefCache::TokenArrayRef pArray;
1551 6 : PopExternalDoubleRef(pArray);
1552 6 : if (nGlobalError)
1553 6 : return;
1554 :
1555 : // For now, we only support single range data for external
1556 : // references, which means the array should only contain a
1557 : // single matrix token.
1558 6 : ScToken* p = static_cast<ScToken*>(pArray->First());
1559 6 : if (!p || p->GetType() != svMatrix)
1560 0 : SetError( errIllegalParameter);
1561 : else
1562 : {
1563 6 : rMat = p->GetMatrix();
1564 6 : if (!rMat)
1565 0 : SetError( errUnknownVariable);
1566 6 : }
1567 : }
1568 :
1569 6 : void ScInterpreter::GetExternalDoubleRef(
1570 : sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
1571 : {
1572 6 : ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1573 6 : const rtl::OUString* pFile = pRefMgr->getExternalFileName(nFileId);
1574 6 : if (!pFile)
1575 : {
1576 0 : SetError(errNoName);
1577 : return;
1578 : }
1579 6 : if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
1580 : {
1581 : OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
1582 0 : SetError(errNoRef);
1583 : return;
1584 : }
1585 :
1586 6 : ScComplexRefData aData(rData);
1587 6 : aData.CalcAbsIfRel(aPos);
1588 : ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
1589 6 : aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
1590 : ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
1591 6 : nFileId, rTabName, aRange, &aPos);
1592 :
1593 6 : if (!pArray)
1594 : {
1595 0 : SetError(errIllegalArgument);
1596 : return;
1597 : }
1598 :
1599 6 : ScToken* pToken = static_cast<ScToken*>(pArray->First());
1600 6 : if (pToken->GetType() != svMatrix)
1601 : {
1602 0 : SetError(errIllegalArgument);
1603 : return;
1604 : }
1605 :
1606 6 : if (pArray->Next())
1607 : {
1608 : // Can't handle more than one matrix per parameter.
1609 0 : SetError( errIllegalArgument);
1610 : return;
1611 : }
1612 :
1613 6 : rArray = pArray;
1614 : }
1615 :
1616 98 : bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
1617 : {
1618 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRefOrSingleRef" );
1619 98 : switch ( GetStackType() )
1620 : {
1621 : case svDoubleRef :
1622 : {
1623 0 : ScRange aRange;
1624 0 : PopDoubleRef( aRange, true );
1625 0 : return DoubleRefToPosSingleRef( aRange, rAdr );
1626 : }
1627 : case svSingleRef :
1628 : {
1629 98 : PopSingleRef( rAdr );
1630 98 : return true;
1631 : }
1632 : default:
1633 0 : PopError();
1634 0 : SetError( errNoRef );
1635 : }
1636 0 : return false;
1637 : }
1638 :
1639 :
1640 2 : void ScInterpreter::PopDoubleRefPushMatrix()
1641 : {
1642 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopDoubleRefPushMatrix" );
1643 2 : if ( GetStackType() == svDoubleRef )
1644 : {
1645 2 : ScMatrixRef pMat = GetMatrix();
1646 2 : if ( pMat )
1647 2 : PushMatrix( pMat );
1648 : else
1649 0 : PushIllegalParameter();
1650 : }
1651 : else
1652 0 : SetError( errNoRef );
1653 2 : }
1654 :
1655 :
1656 6 : ScTokenMatrixMap* ScInterpreter::CreateTokenMatrixMap()
1657 : {
1658 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::CreateTokenMatrixMap" );
1659 6 : return new ScTokenMatrixMap;
1660 : }
1661 :
1662 :
1663 24 : bool ScInterpreter::ConvertMatrixParameters()
1664 : {
1665 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ConvertMatrixParameters" );
1666 24 : sal_uInt16 nParams = pCur->GetParamCount();
1667 : OSL_ENSURE( nParams <= sp, "ConvertMatrixParameters: stack/param count mismatch");
1668 24 : SCSIZE nJumpCols = 0, nJumpRows = 0;
1669 68 : for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i )
1670 : {
1671 44 : FormulaToken* p = pStack[ sp - i ];
1672 44 : if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing)
1673 : {
1674 : OSL_FAIL( "ConvertMatrixParameters: not a push");
1675 : }
1676 : else
1677 : {
1678 44 : switch ( p->GetType() )
1679 : {
1680 : case svDouble:
1681 : case svString:
1682 : case svSingleRef:
1683 : case svExternalSingleRef:
1684 : case svMissing:
1685 : case svError:
1686 : case svEmptyCell:
1687 : // nothing to do
1688 15 : break;
1689 : case svMatrix:
1690 : {
1691 12 : if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
1692 : == ScParameterClassification::Value )
1693 : { // only if single value expected
1694 0 : ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
1695 0 : if ( !pMat )
1696 0 : SetError( errUnknownVariable);
1697 : else
1698 : {
1699 : SCSIZE nCols, nRows;
1700 0 : pMat->GetDimensions( nCols, nRows);
1701 0 : if ( nJumpCols < nCols )
1702 0 : nJumpCols = nCols;
1703 0 : if ( nJumpRows < nRows )
1704 0 : nJumpRows = nRows;
1705 0 : }
1706 : }
1707 : }
1708 12 : break;
1709 : case svDoubleRef:
1710 : {
1711 : ScParameterClassification::Type eType =
1712 17 : ScParameterClassification::GetParameterType( pCur, nParams - i);
1713 17 : if ( eType != ScParameterClassification::Reference &&
1714 : eType != ScParameterClassification::ReferenceOrForceArray)
1715 : {
1716 : SCCOL nCol1, nCol2;
1717 : SCROW nRow1, nRow2;
1718 : SCTAB nTab1, nTab2;
1719 12 : DoubleRefToVars( static_cast<const ScToken*>( p), nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1720 : // Make sure the map exists, created if not.
1721 12 : GetTokenMatrixMap();
1722 : ScMatrixRef pMat = CreateMatrixFromDoubleRef( p,
1723 12 : nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1724 12 : if (pMat)
1725 : {
1726 12 : if ( eType == ScParameterClassification::Value )
1727 : { // only if single value expected
1728 0 : if ( nJumpCols < static_cast<SCSIZE>(nCol2 - nCol1 + 1) )
1729 0 : nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
1730 0 : if ( nJumpRows < static_cast<SCSIZE>(nRow2 - nRow1 + 1) )
1731 0 : nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
1732 : }
1733 12 : ScToken* pNew = new ScMatrixToken( pMat);
1734 12 : pNew->IncRef();
1735 12 : pStack[ sp - i ] = pNew;
1736 12 : p->DecRef(); // p may be dead now!
1737 12 : }
1738 : }
1739 : }
1740 17 : break;
1741 : case svExternalDoubleRef:
1742 : {
1743 : ScParameterClassification::Type eType =
1744 0 : ScParameterClassification::GetParameterType( pCur, nParams - i);
1745 0 : if (eType == ScParameterClassification::Array)
1746 : {
1747 0 : sal_uInt16 nFileId = p->GetIndex();
1748 0 : const String& rTabName = p->GetString();
1749 0 : const ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1750 0 : ScExternalRefCache::TokenArrayRef pArray;
1751 0 : GetExternalDoubleRef(nFileId, rTabName, rRef, pArray);
1752 0 : if (nGlobalError)
1753 : break;
1754 :
1755 0 : ScToken* pTemp = static_cast<ScToken*>(pArray->First());
1756 0 : if (!pTemp)
1757 : break;
1758 :
1759 0 : ScMatrixRef pMat = pTemp->GetMatrix();
1760 0 : if (pMat)
1761 : {
1762 0 : ScToken* pNew = new ScMatrixToken( pMat);
1763 0 : pNew->IncRef();
1764 0 : pStack[ sp - i ] = pNew;
1765 0 : p->DecRef(); // p may be dead now!
1766 0 : }
1767 : }
1768 : }
1769 0 : break;
1770 : case svRefList:
1771 : {
1772 : ScParameterClassification::Type eType =
1773 0 : ScParameterClassification::GetParameterType( pCur, nParams - i);
1774 0 : if ( eType != ScParameterClassification::Reference &&
1775 : eType != ScParameterClassification::ReferenceOrForceArray)
1776 : {
1777 : // can't convert to matrix
1778 0 : SetError( errNoValue);
1779 : }
1780 : }
1781 0 : break;
1782 : default:
1783 : OSL_FAIL( "ConvertMatrixParameters: unknown parameter type");
1784 : }
1785 : }
1786 : }
1787 24 : if( nJumpCols && nJumpRows )
1788 : {
1789 0 : short nPC = aCode.GetPC();
1790 0 : short nStart = nPC - 1; // restart on current code (-1)
1791 0 : short nNext = nPC; // next instruction after subroutine
1792 0 : short nStop = nPC + 1; // stop subroutine before reaching that
1793 0 : FormulaTokenRef xNew;
1794 0 : ScTokenMatrixMap::const_iterator aMapIter;
1795 0 : if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) !=
1796 0 : pTokenMatrixMap->end()))
1797 0 : xNew = (*aMapIter).second;
1798 : else
1799 : {
1800 0 : ScJumpMatrix* pJumpMat = new ScJumpMatrix( nJumpCols, nJumpRows);
1801 0 : pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop);
1802 : // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1803 0 : ScTokenVec* pParams = new ScTokenVec( nParams);
1804 0 : for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i )
1805 : {
1806 0 : FormulaToken* p = pStack[ --sp ];
1807 0 : p->IncRef();
1808 : // store in reverse order such that a push may simply iterate
1809 0 : (*pParams)[ nParams - i ] = p;
1810 : }
1811 0 : pJumpMat->SetJumpParameters( pParams);
1812 0 : xNew = new ScJumpMatrixToken( pJumpMat );
1813 0 : GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur,
1814 0 : xNew));
1815 : }
1816 0 : PushTempToken( xNew.get());
1817 : // set continuation point of path for main code line
1818 0 : aCode.Jump( nNext, nNext);
1819 0 : return true;
1820 : }
1821 24 : return false;
1822 : }
1823 :
1824 :
1825 38 : ScMatrixRef ScInterpreter::PopMatrix()
1826 : {
1827 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PopMatrix" );
1828 38 : if( sp )
1829 : {
1830 38 : --sp;
1831 38 : FormulaToken* p = pStack[ sp ];
1832 38 : switch (p->GetType())
1833 : {
1834 : case svError:
1835 0 : nGlobalError = p->GetError();
1836 0 : break;
1837 : case svMatrix:
1838 : {
1839 38 : ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix();
1840 38 : if ( pMat )
1841 38 : pMat->SetErrorInterpreter( this);
1842 : else
1843 0 : SetError( errUnknownVariable);
1844 38 : return pMat;
1845 : }
1846 : default:
1847 0 : SetError( errIllegalParameter);
1848 : }
1849 : }
1850 : else
1851 0 : SetError( errUnknownStackVariable);
1852 0 : return NULL;
1853 : }
1854 :
1855 12 : void ScInterpreter::QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr)
1856 : {
1857 12 : if (xMat)
1858 : {
1859 12 : ScMatrixValue nMatVal = xMat->Get(0, 0);
1860 12 : ScMatValType nMatValType = nMatVal.nType;
1861 12 : if (ScMatrix::IsNonValueType( nMatValType))
1862 : {
1863 1 : if ( xMat->IsEmptyPath( 0, 0))
1864 : { // result of empty FALSE jump path
1865 0 : FormulaTokenRef xRes = new FormulaDoubleToken( 0.0);
1866 0 : PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
1867 0 : rRetTypeExpr = NUMBERFORMAT_LOGICAL;
1868 : }
1869 : else
1870 : {
1871 1 : String aStr( nMatVal.GetString());
1872 1 : FormulaTokenRef xRes = new FormulaStringToken( aStr);
1873 1 : PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
1874 1 : rRetTypeExpr = NUMBERFORMAT_TEXT;
1875 : }
1876 : }
1877 : else
1878 : {
1879 11 : sal_uInt16 nErr = GetDoubleErrorValue( nMatVal.fVal);
1880 11 : FormulaTokenRef xRes;
1881 11 : if (nErr)
1882 0 : xRes = new FormulaErrorToken( nErr);
1883 : else
1884 11 : xRes = new FormulaDoubleToken( nMatVal.fVal);
1885 11 : PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
1886 11 : if ( rRetTypeExpr != NUMBERFORMAT_LOGICAL )
1887 11 : rRetTypeExpr = NUMBERFORMAT_NUMBER;
1888 : }
1889 12 : rRetIndexExpr = 0;
1890 12 : xMat->SetErrorInterpreter( NULL);
1891 : }
1892 : else
1893 0 : SetError( errUnknownStackVariable);
1894 12 : }
1895 :
1896 :
1897 5667 : void ScInterpreter::PushDouble(double nVal)
1898 : {
1899 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushDouble" );
1900 5667 : TreatDoubleError( nVal );
1901 5667 : if (!IfErrorPushError())
1902 5660 : PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1903 5667 : }
1904 :
1905 :
1906 118 : void ScInterpreter::PushInt(int nVal)
1907 : {
1908 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushInt" );
1909 118 : if (!IfErrorPushError())
1910 118 : PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1911 118 : }
1912 :
1913 :
1914 0 : void ScInterpreter::PushStringBuffer( const sal_Unicode* pString )
1915 : {
1916 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushStringBuffer" );
1917 0 : if ( pString )
1918 0 : PushString( rtl::OUString(pString) );
1919 : else
1920 0 : PushString( EMPTY_STRING );
1921 0 : }
1922 :
1923 :
1924 36 : void ScInterpreter::PushString( const String& rString )
1925 : {
1926 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushString" );
1927 36 : if (!IfErrorPushError())
1928 36 : PushTempTokenWithoutError( new FormulaStringToken( rString ) );
1929 36 : }
1930 :
1931 :
1932 26 : void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
1933 : {
1934 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushSingleRef" );
1935 26 : if (!IfErrorPushError())
1936 : {
1937 : ScSingleRefData aRef;
1938 26 : aRef.InitFlags();
1939 26 : aRef.nCol = nCol;
1940 26 : aRef.nRow = nRow;
1941 26 : aRef.nTab = nTab;
1942 26 : PushTempTokenWithoutError( new ScSingleRefToken( aRef ) );
1943 : }
1944 26 : }
1945 :
1946 :
1947 0 : void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1948 : SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1949 : {
1950 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushDoubleRef" );
1951 0 : if (!IfErrorPushError())
1952 : {
1953 : ScComplexRefData aRef;
1954 0 : aRef.InitFlags();
1955 0 : aRef.Ref1.nCol = nCol1;
1956 0 : aRef.Ref1.nRow = nRow1;
1957 0 : aRef.Ref1.nTab = nTab1;
1958 0 : aRef.Ref2.nCol = nCol2;
1959 0 : aRef.Ref2.nRow = nRow2;
1960 0 : aRef.Ref2.nTab = nTab2;
1961 0 : PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) );
1962 : }
1963 0 : }
1964 :
1965 :
1966 0 : void ScInterpreter::PushExternalSingleRef(
1967 : sal_uInt16 nFileId, const String& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
1968 : {
1969 0 : if (!IfErrorPushError())
1970 : {
1971 : ScSingleRefData aRef;
1972 0 : aRef.InitFlags();
1973 0 : aRef.nCol = nCol;
1974 0 : aRef.nRow = nRow;
1975 0 : aRef.nTab = nTab;
1976 0 : PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId, rTabName, aRef)) ;
1977 : }
1978 0 : }
1979 :
1980 :
1981 0 : void ScInterpreter::PushExternalDoubleRef(
1982 : sal_uInt16 nFileId, const String& rTabName,
1983 : SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1984 : {
1985 0 : if (!IfErrorPushError())
1986 : {
1987 : ScComplexRefData aRef;
1988 0 : aRef.InitFlags();
1989 0 : aRef.Ref1.nCol = nCol1;
1990 0 : aRef.Ref1.nRow = nRow1;
1991 0 : aRef.Ref1.nTab = nTab1;
1992 0 : aRef.Ref2.nCol = nCol2;
1993 0 : aRef.Ref2.nRow = nRow2;
1994 0 : aRef.Ref2.nTab = nTab2;
1995 0 : PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId, rTabName, aRef) );
1996 : }
1997 0 : }
1998 :
1999 :
2000 21 : void ScInterpreter::PushMatrix(const ScMatrixRef& pMat)
2001 : {
2002 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushMatrix" );
2003 21 : pMat->SetErrorInterpreter( NULL);
2004 : // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
2005 : // but with notifying ScInterpreter via nGlobalError, substituting it would
2006 : // mean to inherit the error on all array elements in all following
2007 : // operations.
2008 21 : nGlobalError = 0;
2009 21 : PushTempTokenWithoutError( new ScMatrixToken( pMat ) );
2010 21 : }
2011 :
2012 :
2013 65 : void ScInterpreter::PushError( sal_uInt16 nError )
2014 : {
2015 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushError" );
2016 65 : SetError( nError ); // only sets error if not already set
2017 65 : PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
2018 65 : }
2019 :
2020 1 : void ScInterpreter::PushParameterExpected()
2021 : {
2022 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushParameterExpected" );
2023 1 : PushError( errParameterExpected);
2024 1 : }
2025 :
2026 :
2027 0 : void ScInterpreter::PushIllegalParameter()
2028 : {
2029 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushIllegalParameter" );
2030 0 : PushError( errIllegalParameter);
2031 0 : }
2032 :
2033 :
2034 14 : void ScInterpreter::PushIllegalArgument()
2035 : {
2036 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushIllegalArgument" );
2037 14 : PushError( errIllegalArgument);
2038 14 : }
2039 :
2040 :
2041 6 : void ScInterpreter::PushNA()
2042 : {
2043 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushNA" );
2044 6 : PushError( NOTAVAILABLE);
2045 6 : }
2046 :
2047 :
2048 0 : void ScInterpreter::PushNoValue()
2049 : {
2050 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::PushNoValue" );
2051 0 : PushError( errNoValue);
2052 0 : }
2053 :
2054 :
2055 4 : bool ScInterpreter::IsMissing()
2056 : {
2057 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::IsMissing" );
2058 4 : return sp && pStack[sp - 1]->GetType() == svMissing;
2059 : }
2060 :
2061 :
2062 9817 : StackVar ScInterpreter::GetRawStackType()
2063 : {
2064 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetRawStackType" );
2065 : StackVar eRes;
2066 9817 : if( sp )
2067 : {
2068 9817 : eRes = pStack[sp - 1]->GetType();
2069 : }
2070 : else
2071 : {
2072 0 : SetError(errUnknownStackVariable);
2073 0 : eRes = svUnknown;
2074 : }
2075 9817 : return eRes;
2076 : }
2077 :
2078 :
2079 10429 : StackVar ScInterpreter::GetStackType()
2080 : {
2081 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetStackType" );
2082 : StackVar eRes;
2083 10429 : if( sp )
2084 : {
2085 10429 : eRes = pStack[sp - 1]->GetType();
2086 10429 : if( eRes == svMissing || eRes == svEmptyCell )
2087 5 : eRes = svDouble; // default!
2088 : }
2089 : else
2090 : {
2091 0 : SetError(errUnknownStackVariable);
2092 0 : eRes = svUnknown;
2093 : }
2094 10429 : return eRes;
2095 : }
2096 :
2097 :
2098 27694 : StackVar ScInterpreter::GetStackType( sal_uInt8 nParam )
2099 : {
2100 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetStackType" );
2101 : StackVar eRes;
2102 27694 : if( sp > nParam-1 )
2103 : {
2104 20316 : eRes = pStack[sp - nParam]->GetType();
2105 20316 : if( eRes == svMissing || eRes == svEmptyCell )
2106 10 : eRes = svDouble; // default!
2107 : }
2108 : else
2109 7378 : eRes = svUnknown;
2110 27694 : return eRes;
2111 : }
2112 :
2113 :
2114 13 : bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
2115 : {
2116 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::DoubleRefToPosSingleRef" );
2117 : // Check for a singleton first - no implicit intersection for them.
2118 13 : if( rRange.aStart == rRange.aEnd )
2119 : {
2120 0 : rAdr = rRange.aStart;
2121 0 : return true;
2122 : }
2123 :
2124 13 : bool bOk = false;
2125 :
2126 13 : if ( pJumpMatrix )
2127 : {
2128 0 : bOk = rRange.aStart.Tab() == rRange.aEnd.Tab();
2129 0 : if ( !bOk )
2130 0 : SetError( errIllegalArgument);
2131 : else
2132 : {
2133 : SCSIZE nC, nR;
2134 0 : pJumpMatrix->GetPos( nC, nR);
2135 0 : rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) );
2136 0 : rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) );
2137 0 : rAdr.SetTab( rRange.aStart.Tab());
2138 0 : bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <=
2139 0 : rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() &&
2140 0 : rAdr.Row() <= rRange.aEnd.Row();
2141 0 : if ( !bOk )
2142 0 : SetError( errNoValue);
2143 : }
2144 0 : return bOk;
2145 : }
2146 :
2147 13 : SCCOL nMyCol = aPos.Col();
2148 13 : SCROW nMyRow = aPos.Row();
2149 13 : SCTAB nMyTab = aPos.Tab();
2150 13 : SCCOL nCol = 0;
2151 13 : SCROW nRow = 0;
2152 : SCTAB nTab;
2153 13 : nTab = rRange.aStart.Tab();
2154 13 : if ( rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
2155 : {
2156 0 : nRow = rRange.aStart.Row();
2157 0 : if ( nRow == rRange.aEnd.Row() )
2158 : {
2159 0 : bOk = true;
2160 0 : nCol = nMyCol;
2161 : }
2162 0 : else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
2163 0 : && rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
2164 : {
2165 0 : bOk = true;
2166 0 : nCol = nMyCol;
2167 0 : nRow = nMyRow;
2168 : }
2169 : }
2170 13 : else if ( rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
2171 : {
2172 13 : nCol = rRange.aStart.Col();
2173 13 : if ( nCol == rRange.aEnd.Col() )
2174 : {
2175 13 : bOk = true;
2176 13 : nRow = nMyRow;
2177 : }
2178 0 : else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
2179 0 : && rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
2180 : {
2181 0 : bOk = true;
2182 0 : nCol = nMyCol;
2183 0 : nRow = nMyRow;
2184 : }
2185 : }
2186 13 : if ( bOk )
2187 : {
2188 13 : if ( nTab == rRange.aEnd.Tab() )
2189 : ; // all done
2190 0 : else if ( nTab <= nMyTab && nMyTab <= rRange.aEnd.Tab() )
2191 0 : nTab = nMyTab;
2192 : else
2193 0 : bOk = false;
2194 13 : if ( bOk )
2195 13 : rAdr.Set( nCol, nRow, nTab );
2196 : }
2197 13 : if ( !bOk )
2198 0 : SetError( errNoValue );
2199 13 : return bOk;
2200 : }
2201 :
2202 0 : double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat)
2203 : {
2204 0 : if (!pMat)
2205 0 : return 0.0;
2206 :
2207 0 : if ( !pJumpMatrix )
2208 0 : return pMat->GetDouble( 0 );
2209 :
2210 : SCSIZE nCols, nRows, nC, nR;
2211 0 : pMat->GetDimensions( nCols, nRows);
2212 0 : pJumpMatrix->GetPos( nC, nR);
2213 0 : if ( nC < nCols && nR < nRows )
2214 0 : return pMat->GetDouble( nC, nR);
2215 :
2216 0 : SetError( errNoValue);
2217 0 : return 0.0;
2218 : }
2219 :
2220 9581 : double ScInterpreter::GetDouble()
2221 : {
2222 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDouble" );
2223 9581 : double nVal(0.0);
2224 9581 : switch( GetRawStackType() )
2225 : {
2226 : case svDouble:
2227 4393 : nVal = PopDouble();
2228 4393 : break;
2229 : case svString:
2230 18 : nVal = ConvertStringToValue( PopString());
2231 18 : break;
2232 : case svSingleRef:
2233 : {
2234 5151 : ScAddress aAdr;
2235 5151 : PopSingleRef( aAdr );
2236 5151 : ScBaseCell* pCell = GetCell( aAdr );
2237 5151 : nVal = GetCellValue( aAdr, pCell );
2238 : }
2239 5151 : break;
2240 : case svDoubleRef:
2241 : { // generate position dependent SingleRef
2242 13 : ScRange aRange;
2243 13 : PopDoubleRef( aRange );
2244 13 : ScAddress aAdr;
2245 13 : if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
2246 : {
2247 13 : ScBaseCell* pCell = GetCell( aAdr );
2248 13 : nVal = GetCellValue( aAdr, pCell );
2249 : }
2250 : else
2251 0 : nVal = 0.0;
2252 : }
2253 13 : break;
2254 : case svExternalSingleRef:
2255 : {
2256 0 : ScExternalRefCache::TokenRef pToken;
2257 0 : PopExternalSingleRef(pToken);
2258 0 : if (!nGlobalError && pToken)
2259 0 : nVal = pToken->GetDouble();
2260 : }
2261 0 : break;
2262 : case svExternalDoubleRef:
2263 : {
2264 0 : ScMatrixRef pMat;
2265 0 : PopExternalDoubleRef(pMat);
2266 0 : if (nGlobalError)
2267 : break;
2268 :
2269 0 : nVal = GetDoubleFromMatrix(pMat);
2270 : }
2271 0 : break;
2272 : case svMatrix:
2273 : {
2274 0 : ScMatrixRef pMat = PopMatrix();
2275 0 : nVal = GetDoubleFromMatrix(pMat);
2276 : }
2277 0 : break;
2278 : case svError:
2279 0 : PopError();
2280 0 : nVal = 0.0;
2281 0 : break;
2282 : case svEmptyCell:
2283 : case svMissing:
2284 6 : Pop();
2285 6 : nVal = 0.0;
2286 6 : break;
2287 : default:
2288 0 : PopError();
2289 0 : SetError( errIllegalParameter);
2290 0 : nVal = 0.0;
2291 : }
2292 9581 : if ( nFuncFmtType == nCurFmtType )
2293 9233 : nFuncFmtIndex = nCurFmtIndex;
2294 9581 : return nVal;
2295 : }
2296 :
2297 :
2298 4 : double ScInterpreter::GetDoubleWithDefault(double nDefault)
2299 : {
2300 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDoubleWithDefault" );
2301 4 : bool bMissing = IsMissing();
2302 4 : double nResultVal = GetDouble();
2303 4 : if ( bMissing )
2304 1 : nResultVal = nDefault;
2305 4 : return nResultVal;
2306 : }
2307 :
2308 :
2309 164 : const String& ScInterpreter::GetString()
2310 : {
2311 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetString" );
2312 164 : switch (GetRawStackType())
2313 : {
2314 : case svError:
2315 0 : PopError();
2316 0 : return EMPTY_STRING;
2317 : case svMissing:
2318 : case svEmptyCell:
2319 0 : Pop();
2320 0 : return EMPTY_STRING;
2321 : case svDouble:
2322 : {
2323 0 : double fVal = PopDouble();
2324 : sal_uLong nIndex = pFormatter->GetStandardFormat(
2325 : NUMBERFORMAT_NUMBER,
2326 0 : ScGlobal::eLnge);
2327 0 : pFormatter->GetInputLineString(fVal, nIndex, aTempStr);
2328 0 : return aTempStr;
2329 : }
2330 : case svString:
2331 65 : return PopString();
2332 : case svSingleRef:
2333 : {
2334 99 : ScAddress aAdr;
2335 99 : PopSingleRef( aAdr );
2336 99 : if (nGlobalError == 0)
2337 : {
2338 99 : ScBaseCell* pCell = GetCell( aAdr );
2339 99 : GetCellString( aTempStr, pCell );
2340 99 : return aTempStr;
2341 : }
2342 : else
2343 0 : return EMPTY_STRING;
2344 : }
2345 : case svDoubleRef:
2346 : { // generate position dependent SingleRef
2347 0 : ScRange aRange;
2348 0 : PopDoubleRef( aRange );
2349 0 : ScAddress aAdr;
2350 0 : if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
2351 : {
2352 0 : ScBaseCell* pCell = GetCell( aAdr );
2353 0 : GetCellString( aTempStr, pCell );
2354 0 : return aTempStr;
2355 : }
2356 : else
2357 0 : return EMPTY_STRING;
2358 : }
2359 : case svExternalSingleRef:
2360 : {
2361 0 : ScExternalRefCache::TokenRef pToken;
2362 0 : PopExternalSingleRef(pToken);
2363 0 : return nGlobalError ? EMPTY_STRING : pToken->GetString();
2364 : }
2365 : case svExternalDoubleRef:
2366 : {
2367 0 : ScMatrixRef pMat;
2368 0 : PopExternalDoubleRef(pMat);
2369 0 : return GetStringFromMatrix(pMat);
2370 : }
2371 : case svMatrix:
2372 : {
2373 0 : ScMatrixRef pMat = PopMatrix();
2374 0 : return GetStringFromMatrix(pMat);
2375 : }
2376 : break;
2377 : default:
2378 0 : PopError();
2379 0 : SetError( errIllegalArgument);
2380 : }
2381 0 : return EMPTY_STRING;
2382 : }
2383 :
2384 0 : const String& ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
2385 : {
2386 0 : if ( !pMat )
2387 : ; // nothing
2388 0 : else if ( !pJumpMatrix )
2389 : {
2390 0 : aTempStr = pMat->GetString( *pFormatter, 0, 0);
2391 0 : return aTempStr;
2392 : }
2393 : else
2394 : {
2395 : SCSIZE nCols, nRows, nC, nR;
2396 0 : pMat->GetDimensions( nCols, nRows);
2397 0 : pJumpMatrix->GetPos( nC, nR);
2398 0 : if ( nC < nCols && nR < nRows )
2399 : {
2400 0 : aTempStr = pMat->GetString( *pFormatter, nC, nR);
2401 0 : return aTempStr;
2402 : }
2403 : else
2404 0 : SetError( errNoValue);
2405 : }
2406 0 : return EMPTY_STRING;
2407 : }
2408 :
2409 3 : ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
2410 : String& rString )
2411 : {
2412 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GetDoubleOrStringFromMatrix" );
2413 :
2414 3 : rDouble = 0.0;
2415 3 : rString.Erase();
2416 3 : ScMatValType nMatValType = SC_MATVAL_EMPTY;
2417 :
2418 3 : ScMatrixRef pMat;
2419 3 : StackVar eType = GetStackType();
2420 3 : if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
2421 : {
2422 3 : pMat = GetMatrix();
2423 : }
2424 : else
2425 : {
2426 0 : PopError();
2427 0 : SetError( errIllegalParameter);
2428 0 : return nMatValType;
2429 : }
2430 :
2431 3 : ScMatrixValue nMatVal;
2432 3 : if (!pMat)
2433 : {
2434 : // nothing
2435 : }
2436 3 : else if (!pJumpMatrix)
2437 : {
2438 3 : nMatVal = pMat->Get(0, 0);
2439 3 : nMatValType = nMatVal.nType;
2440 : }
2441 : else
2442 : {
2443 : SCSIZE nCols, nRows, nC, nR;
2444 0 : pMat->GetDimensions( nCols, nRows);
2445 0 : pJumpMatrix->GetPos( nC, nR);
2446 0 : if ( nC < nCols && nR < nRows )
2447 : {
2448 0 : nMatVal = pMat->Get( nC, nR);
2449 0 : nMatValType = nMatVal.nType;
2450 : }
2451 : else
2452 0 : SetError( errNoValue);
2453 : }
2454 :
2455 3 : if (nMatValType == SC_MATVAL_VALUE)
2456 1 : rDouble = nMatVal.fVal;
2457 2 : else if (nMatValType == SC_MATVAL_BOOLEAN)
2458 : {
2459 0 : rDouble = nMatVal.fVal;
2460 0 : nMatValType = SC_MATVAL_VALUE;
2461 : }
2462 : else
2463 2 : rString = nMatVal.GetString();
2464 :
2465 3 : if (ScMatrix::IsValueType( nMatValType))
2466 : {
2467 1 : sal_uInt16 nError = nMatVal.GetError();
2468 1 : if (nError)
2469 0 : SetError( nError);
2470 : }
2471 :
2472 3 : return nMatValType;
2473 : }
2474 :
2475 :
2476 0 : void ScInterpreter::ScDBGet()
2477 : {
2478 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScDBGet" );
2479 0 : bool bMissingField = false;
2480 : SAL_WNODEPRECATED_DECLARATIONS_PUSH
2481 0 : auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2482 : SAL_WNODEPRECATED_DECLARATIONS_POP
2483 0 : if (!pQueryParam.get())
2484 : {
2485 : // Failed to create query param.
2486 0 : PushIllegalParameter();
2487 : return;
2488 : }
2489 :
2490 0 : pQueryParam->mbSkipString = false;
2491 0 : ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
2492 0 : ScDBQueryDataIterator::Value aValue;
2493 0 : if (!aValIter.GetFirst(aValue) || aValue.mnError)
2494 : {
2495 : // No match found.
2496 0 : PushNoValue();
2497 : return;
2498 : }
2499 :
2500 0 : ScDBQueryDataIterator::Value aValNext;
2501 0 : if (aValIter.GetNext(aValNext) && !aValNext.mnError)
2502 : {
2503 : // There should be only one unique match.
2504 0 : PushIllegalArgument();
2505 : return;
2506 : }
2507 :
2508 0 : if (aValue.mbIsNumber)
2509 0 : PushDouble(aValue.mfValue);
2510 : else
2511 0 : PushString(aValue.maString);
2512 : }
2513 :
2514 :
2515 0 : void ScInterpreter::ScExternal()
2516 : {
2517 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScExternal" );
2518 0 : sal_uInt8 nParamCount = GetByte();
2519 0 : String aUnoName;
2520 0 : String aFuncName( ScGlobal::pCharClass->uppercase( pCur->GetExternal() ) );
2521 0 : FuncData* pFuncData = ScGlobal::GetFuncCollection()->findByName(aFuncName);
2522 0 : if (pFuncData)
2523 : {
2524 0 : if (nParamCount <= MAXFUNCPARAM && nParamCount == pFuncData->GetParamCount() - 1)
2525 : {
2526 : ParamType eParamType[MAXFUNCPARAM];
2527 : void* ppParam[MAXFUNCPARAM];
2528 : double nVal[MAXFUNCPARAM];
2529 : sal_Char* pStr[MAXFUNCPARAM];
2530 : sal_uInt8* pCellArr[MAXFUNCPARAM];
2531 : short i;
2532 :
2533 0 : for (i = 0; i < MAXFUNCPARAM; i++)
2534 : {
2535 0 : eParamType[i] = pFuncData->GetParamType(i);
2536 0 : ppParam[i] = NULL;
2537 0 : nVal[i] = 0.0;
2538 0 : pStr[i] = NULL;
2539 0 : pCellArr[i] = NULL;
2540 : }
2541 :
2542 0 : for (i = nParamCount; (i > 0) && (nGlobalError == 0); i--)
2543 : {
2544 0 : switch (eParamType[i])
2545 : {
2546 : case PTR_DOUBLE :
2547 : {
2548 0 : nVal[i-1] = GetDouble();
2549 0 : ppParam[i] = &nVal[i-1];
2550 : }
2551 0 : break;
2552 : case PTR_STRING :
2553 : {
2554 0 : rtl::OString aStr(rtl::OUStringToOString(GetString(),
2555 0 : osl_getThreadTextEncoding()));
2556 0 : if ( aStr.getLength() >= ADDIN_MAXSTRLEN )
2557 0 : SetError( errStringOverflow );
2558 : else
2559 : {
2560 0 : pStr[i-1] = new sal_Char[ADDIN_MAXSTRLEN];
2561 0 : strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN );
2562 0 : pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2563 0 : ppParam[i] = pStr[i-1];
2564 0 : }
2565 : }
2566 0 : break;
2567 : case PTR_DOUBLE_ARR :
2568 : {
2569 : SCCOL nCol1;
2570 : SCROW nRow1;
2571 : SCTAB nTab1;
2572 : SCCOL nCol2;
2573 : SCROW nRow2;
2574 : SCTAB nTab2;
2575 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2576 0 : pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2577 0 : if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2578 0 : SetError(errCodeOverflow);
2579 : else
2580 0 : ppParam[i] = pCellArr[i-1];
2581 : }
2582 0 : break;
2583 : case PTR_STRING_ARR :
2584 : {
2585 : SCCOL nCol1;
2586 : SCROW nRow1;
2587 : SCTAB nTab1;
2588 : SCCOL nCol2;
2589 : SCROW nRow2;
2590 : SCTAB nTab2;
2591 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2592 0 : pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2593 0 : if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2594 0 : SetError(errCodeOverflow);
2595 : else
2596 0 : ppParam[i] = pCellArr[i-1];
2597 : }
2598 0 : break;
2599 : case PTR_CELL_ARR :
2600 : {
2601 : SCCOL nCol1;
2602 : SCROW nRow1;
2603 : SCTAB nTab1;
2604 : SCCOL nCol2;
2605 : SCROW nRow2;
2606 : SCTAB nTab2;
2607 0 : PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2608 0 : pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2609 0 : if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2610 0 : SetError(errCodeOverflow);
2611 : else
2612 0 : ppParam[i] = pCellArr[i-1];
2613 : }
2614 0 : break;
2615 : default :
2616 0 : SetError(errIllegalParameter);
2617 0 : break;
2618 : }
2619 : }
2620 0 : while ( i-- )
2621 0 : Pop(); // im Fehlerfall (sonst ist i==0) Parameter wegpoppen
2622 :
2623 0 : if (nGlobalError == 0)
2624 : {
2625 0 : if ( pFuncData->GetAsyncType() == NONE )
2626 : {
2627 0 : switch ( eParamType[0] )
2628 : {
2629 : case PTR_DOUBLE :
2630 : {
2631 0 : double nErg = 0.0;
2632 0 : ppParam[0] = &nErg;
2633 0 : pFuncData->Call(ppParam);
2634 0 : PushDouble(nErg);
2635 : }
2636 0 : break;
2637 : case PTR_STRING :
2638 : {
2639 0 : sal_Char* pcErg = new sal_Char[ADDIN_MAXSTRLEN];
2640 0 : ppParam[0] = pcErg;
2641 0 : pFuncData->Call(ppParam);
2642 0 : String aUni( pcErg, osl_getThreadTextEncoding() );
2643 0 : PushString( aUni );
2644 0 : delete[] pcErg;
2645 : }
2646 0 : break;
2647 : default:
2648 0 : PushError( errUnknownState );
2649 : }
2650 : }
2651 : else
2652 : {
2653 : // nach dem Laden Asyncs wieder anwerfen
2654 0 : if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
2655 0 : pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
2656 : // garantiert identischer Handle bei identischem Aufruf?!?
2657 : // sonst schei*e ...
2658 0 : double nErg = 0.0;
2659 0 : ppParam[0] = &nErg;
2660 0 : pFuncData->Call(ppParam);
2661 0 : sal_uLong nHandle = sal_uLong( nErg );
2662 0 : if ( nHandle >= 65536 )
2663 : {
2664 0 : ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2665 0 : if ( !pAs )
2666 : {
2667 0 : pAs = new ScAddInAsync(nHandle, pFuncData, pDok);
2668 0 : pMyFormulaCell->StartListening( *pAs );
2669 : }
2670 : else
2671 : {
2672 : // falls per cut/copy/paste
2673 0 : pMyFormulaCell->StartListening( *pAs );
2674 : // in anderes Dokument?
2675 0 : if ( !pAs->HasDocument( pDok ) )
2676 0 : pAs->AddDocument( pDok );
2677 : }
2678 0 : if ( pAs->IsValid() )
2679 : {
2680 0 : switch ( pAs->GetType() )
2681 : {
2682 : case PTR_DOUBLE :
2683 0 : PushDouble( pAs->GetValue() );
2684 0 : break;
2685 : case PTR_STRING :
2686 0 : PushString( pAs->GetString() );
2687 0 : break;
2688 : default:
2689 0 : PushError( errUnknownState );
2690 : }
2691 : }
2692 : else
2693 0 : PushNA();
2694 : }
2695 : else
2696 0 : PushNoValue();
2697 : }
2698 : }
2699 :
2700 0 : for (i = 0; i < MAXFUNCPARAM; i++)
2701 : {
2702 0 : delete[] pStr[i];
2703 0 : delete[] pCellArr[i];
2704 : }
2705 : }
2706 : else
2707 : {
2708 0 : while( nParamCount-- > 0)
2709 0 : Pop();
2710 0 : PushIllegalParameter();
2711 : }
2712 : }
2713 0 : else if ( ( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).Len() )
2714 : {
2715 : // bLocalFirst=false in FindFunction, cFunc should be the stored
2716 : // internal name
2717 :
2718 0 : ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
2719 :
2720 0 : if ( !aCall.ValidParamCount() )
2721 0 : SetError( errIllegalParameter );
2722 :
2723 0 : if ( aCall.NeedsCaller() && !GetError() )
2724 : {
2725 0 : SfxObjectShell* pShell = pDok->GetDocumentShell();
2726 0 : if (pShell)
2727 0 : aCall.SetCallerFromObjectShell( pShell );
2728 : else
2729 : {
2730 : // use temporary model object (without document) to supply options
2731 : aCall.SetCaller( static_cast<beans::XPropertySet*>(
2732 0 : new ScDocOptionsObj( pDok->GetDocOptions() ) ) );
2733 : }
2734 : }
2735 :
2736 0 : short nPar = nParamCount;
2737 0 : while ( nPar > 0 && !GetError() )
2738 : {
2739 0 : --nPar; // 0 .. (nParamCount-1)
2740 :
2741 0 : ScAddInArgumentType eType = aCall.GetArgType( nPar );
2742 0 : sal_uInt8 nStackType = sal::static_int_cast<sal_uInt8>( GetStackType() );
2743 :
2744 0 : uno::Any aParam;
2745 0 : switch (eType)
2746 : {
2747 : case SC_ADDINARG_INTEGER:
2748 : {
2749 0 : double fVal = GetDouble();
2750 : double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2751 0 : ::rtl::math::approxCeil( fVal );
2752 0 : if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2753 0 : aParam <<= (sal_Int32)fInt;
2754 : else
2755 0 : SetError(errIllegalArgument);
2756 : }
2757 0 : break;
2758 :
2759 : case SC_ADDINARG_DOUBLE:
2760 0 : aParam <<= (double) GetDouble();
2761 0 : break;
2762 :
2763 : case SC_ADDINARG_STRING:
2764 0 : aParam <<= rtl::OUString( GetString() );
2765 0 : break;
2766 :
2767 : case SC_ADDINARG_INTEGER_ARRAY:
2768 0 : switch( nStackType )
2769 : {
2770 : case svDouble:
2771 : case svString:
2772 : case svSingleRef:
2773 : {
2774 0 : double fVal = GetDouble();
2775 : double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2776 0 : ::rtl::math::approxCeil( fVal );
2777 0 : if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2778 : {
2779 0 : sal_Int32 nIntVal = (long)fInt;
2780 0 : uno::Sequence<sal_Int32> aInner( &nIntVal, 1 );
2781 0 : uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 );
2782 0 : aParam <<= aOuter;
2783 : }
2784 : else
2785 0 : SetError(errIllegalArgument);
2786 : }
2787 0 : break;
2788 : case svDoubleRef:
2789 : {
2790 0 : ScRange aRange;
2791 0 : PopDoubleRef( aRange );
2792 0 : if (!ScRangeToSequence::FillLongArray( aParam, pDok, aRange ))
2793 0 : SetError(errIllegalParameter);
2794 : }
2795 0 : break;
2796 : case svMatrix:
2797 0 : if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() ))
2798 0 : SetError(errIllegalParameter);
2799 0 : break;
2800 : default:
2801 0 : PopError();
2802 0 : SetError(errIllegalParameter);
2803 : }
2804 0 : break;
2805 :
2806 : case SC_ADDINARG_DOUBLE_ARRAY:
2807 0 : switch( nStackType )
2808 : {
2809 : case svDouble:
2810 : case svString:
2811 : case svSingleRef:
2812 : {
2813 0 : double fVal = GetDouble();
2814 0 : uno::Sequence<double> aInner( &fVal, 1 );
2815 0 : uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2816 0 : aParam <<= aOuter;
2817 : }
2818 0 : break;
2819 : case svDoubleRef:
2820 : {
2821 0 : ScRange aRange;
2822 0 : PopDoubleRef( aRange );
2823 0 : if (!ScRangeToSequence::FillDoubleArray( aParam, pDok, aRange ))
2824 0 : SetError(errIllegalParameter);
2825 : }
2826 0 : break;
2827 : case svMatrix:
2828 0 : if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() ))
2829 0 : SetError(errIllegalParameter);
2830 0 : break;
2831 : default:
2832 0 : PopError();
2833 0 : SetError(errIllegalParameter);
2834 : }
2835 0 : break;
2836 :
2837 : case SC_ADDINARG_STRING_ARRAY:
2838 0 : switch( nStackType )
2839 : {
2840 : case svDouble:
2841 : case svString:
2842 : case svSingleRef:
2843 : {
2844 0 : rtl::OUString aString = rtl::OUString( GetString() );
2845 0 : uno::Sequence<rtl::OUString> aInner( &aString, 1 );
2846 0 : uno::Sequence< uno::Sequence<rtl::OUString> > aOuter( &aInner, 1 );
2847 0 : aParam <<= aOuter;
2848 : }
2849 0 : break;
2850 : case svDoubleRef:
2851 : {
2852 0 : ScRange aRange;
2853 0 : PopDoubleRef( aRange );
2854 0 : if (!ScRangeToSequence::FillStringArray( aParam, pDok, aRange ))
2855 0 : SetError(errIllegalParameter);
2856 : }
2857 0 : break;
2858 : case svMatrix:
2859 0 : if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), pFormatter ))
2860 0 : SetError(errIllegalParameter);
2861 0 : break;
2862 : default:
2863 0 : PopError();
2864 0 : SetError(errIllegalParameter);
2865 : }
2866 0 : break;
2867 :
2868 : case SC_ADDINARG_MIXED_ARRAY:
2869 0 : switch( nStackType )
2870 : {
2871 : case svDouble:
2872 : case svString:
2873 : case svSingleRef:
2874 : {
2875 0 : uno::Any aElem;
2876 0 : if ( nStackType == svDouble )
2877 0 : aElem <<= (double) GetDouble();
2878 0 : else if ( nStackType == svString )
2879 0 : aElem <<= rtl::OUString( GetString() );
2880 : else
2881 : {
2882 0 : ScAddress aAdr;
2883 0 : if ( PopDoubleRefOrSingleRef( aAdr ) )
2884 : {
2885 0 : ScBaseCell* pCell = GetCell( aAdr );
2886 0 : if ( pCell && pCell->HasStringData() )
2887 : {
2888 0 : String aStr;
2889 0 : GetCellString( aStr, pCell );
2890 0 : aElem <<= rtl::OUString( aStr );
2891 : }
2892 : else
2893 0 : aElem <<= (double) GetCellValue( aAdr, pCell );
2894 : }
2895 : }
2896 0 : uno::Sequence<uno::Any> aInner( &aElem, 1 );
2897 0 : uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2898 0 : aParam <<= aOuter;
2899 : }
2900 0 : break;
2901 : case svDoubleRef:
2902 : {
2903 0 : ScRange aRange;
2904 0 : PopDoubleRef( aRange );
2905 0 : if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2906 0 : SetError(errIllegalParameter);
2907 : }
2908 0 : break;
2909 : case svMatrix:
2910 0 : if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2911 0 : SetError(errIllegalParameter);
2912 0 : break;
2913 : default:
2914 0 : PopError();
2915 0 : SetError(errIllegalParameter);
2916 : }
2917 0 : break;
2918 :
2919 : case SC_ADDINARG_VALUE_OR_ARRAY:
2920 0 : if ( IsMissing() )
2921 0 : nStackType = svMissing;
2922 0 : switch( nStackType )
2923 : {
2924 : case svDouble:
2925 0 : aParam <<= (double) GetDouble();
2926 0 : break;
2927 : case svString:
2928 0 : aParam <<= rtl::OUString( GetString() );
2929 0 : break;
2930 : case svSingleRef:
2931 : {
2932 0 : ScAddress aAdr;
2933 0 : if ( PopDoubleRefOrSingleRef( aAdr ) )
2934 : {
2935 0 : ScBaseCell* pCell = GetCell( aAdr );
2936 0 : if ( pCell && pCell->HasStringData() )
2937 : {
2938 0 : String aStr;
2939 0 : GetCellString( aStr, pCell );
2940 0 : aParam <<= rtl::OUString( aStr );
2941 : }
2942 : else
2943 0 : aParam <<= (double) GetCellValue( aAdr, pCell );
2944 : }
2945 : }
2946 0 : break;
2947 : case svDoubleRef:
2948 : {
2949 0 : ScRange aRange;
2950 0 : PopDoubleRef( aRange );
2951 0 : if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2952 0 : SetError(errIllegalParameter);
2953 : }
2954 0 : break;
2955 : case svMatrix:
2956 0 : if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2957 0 : SetError(errIllegalParameter);
2958 0 : break;
2959 : case svMissing:
2960 0 : Pop();
2961 0 : aParam.clear();
2962 0 : break;
2963 : default:
2964 0 : PopError();
2965 0 : SetError(errIllegalParameter);
2966 : }
2967 0 : break;
2968 :
2969 : case SC_ADDINARG_CELLRANGE:
2970 0 : switch( nStackType )
2971 : {
2972 : case svSingleRef:
2973 : {
2974 0 : ScAddress aAdr;
2975 0 : PopSingleRef( aAdr );
2976 0 : ScRange aRange( aAdr );
2977 : uno::Reference<table::XCellRange> xObj =
2978 0 : ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2979 0 : if (xObj.is())
2980 0 : aParam <<= xObj;
2981 : else
2982 0 : SetError(errIllegalParameter);
2983 : }
2984 0 : break;
2985 : case svDoubleRef:
2986 : {
2987 0 : ScRange aRange;
2988 0 : PopDoubleRef( aRange );
2989 : uno::Reference<table::XCellRange> xObj =
2990 0 : ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2991 0 : if (xObj.is())
2992 : {
2993 0 : aParam <<= xObj;
2994 : }
2995 : else
2996 : {
2997 0 : SetError(errIllegalParameter);
2998 0 : }
2999 : }
3000 0 : break;
3001 : default:
3002 0 : PopError();
3003 0 : SetError(errIllegalParameter);
3004 : }
3005 0 : break;
3006 :
3007 : default:
3008 0 : PopError();
3009 0 : SetError(errIllegalParameter);
3010 : }
3011 0 : aCall.SetParam( nPar, aParam );
3012 0 : }
3013 :
3014 0 : while (nPar-- > 0)
3015 : {
3016 0 : Pop(); // in case of error, remove remaining args
3017 : }
3018 0 : if ( !GetError() )
3019 : {
3020 0 : aCall.ExecuteCall();
3021 :
3022 0 : if ( aCall.HasVarRes() ) // handle async functions
3023 : {
3024 0 : if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
3025 : {
3026 0 : pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
3027 : }
3028 0 : uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
3029 0 : ScAddInListener* pLis = ScAddInListener::Get( xRes );
3030 0 : if ( !pLis )
3031 : {
3032 0 : pLis = ScAddInListener::CreateListener( xRes, pDok );
3033 0 : pMyFormulaCell->StartListening( *pLis );
3034 : }
3035 : else
3036 : {
3037 0 : pMyFormulaCell->StartListening( *pLis );
3038 0 : if ( !pLis->HasDocument( pDok ) )
3039 : {
3040 0 : pLis->AddDocument( pDok );
3041 : }
3042 : }
3043 :
3044 0 : aCall.SetResult( pLis->GetResult() ); // use result from async
3045 : }
3046 :
3047 0 : if ( aCall.GetErrCode() )
3048 : {
3049 0 : PushError( aCall.GetErrCode() );
3050 : }
3051 0 : else if ( aCall.HasMatrix() )
3052 : {
3053 0 : ScMatrixRef xMat = aCall.GetMatrix();
3054 0 : PushMatrix( xMat );
3055 : }
3056 0 : else if ( aCall.HasString() )
3057 : {
3058 0 : PushString( aCall.GetString() );
3059 : }
3060 : else
3061 : {
3062 0 : PushDouble( aCall.GetValue() );
3063 : }
3064 : }
3065 : else // error...
3066 0 : PushError( GetError());
3067 : }
3068 : else
3069 : {
3070 0 : while( nParamCount-- > 0)
3071 : {
3072 0 : Pop();
3073 : }
3074 0 : PushError( errNoAddin );
3075 0 : }
3076 0 : }
3077 :
3078 :
3079 6 : void ScInterpreter::ScMissing()
3080 : {
3081 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMissing" );
3082 6 : PushTempToken( new FormulaMissingToken );
3083 6 : }
3084 :
3085 : #ifndef DISABLE_SCRIPTING
3086 :
3087 0 : static uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, ScDocument* pDok )
3088 : {
3089 0 : uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW );
3090 0 : uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
3091 0 : rtl::OUString sCodeName;
3092 0 : xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("CodeName") ) ) >>= sCodeName;
3093 : // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
3094 : // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
3095 : // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
3096 : // the document in the future could fix this, especially IF the switching of the vba mode takes care to
3097 : // create the special document module objects if they don't exist.
3098 0 : BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager();
3099 :
3100 0 : uno::Reference< uno::XInterface > xIf;
3101 0 : if ( pBasMgr && !pBasMgr->GetName().isEmpty() )
3102 : {
3103 0 : String sProj = String( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
3104 0 : if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
3105 : {
3106 0 : sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName();
3107 : }
3108 0 : StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj );
3109 0 : if ( pBasic )
3110 : {
3111 0 : SbModule* pMod = pBasic->FindModule( sCodeName );
3112 0 : if ( pMod )
3113 : {
3114 0 : xIf = pMod->GetUnoModule();
3115 : }
3116 0 : }
3117 : }
3118 0 : return uno::makeAny( xIf );
3119 : }
3120 :
3121 0 : static bool lcl_setVBARange( ScRange& aRange, ScDocument* pDok, SbxVariable* pPar )
3122 : {
3123 0 : bool bOk = false;
3124 : try
3125 : {
3126 0 : uno::Reference< uno::XInterface > xVBARange;
3127 0 : uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
3128 0 : uno::Sequence< uno::Any > aArgs(2);
3129 0 : aArgs[0] = lcl_getSheetModule( xCellRange, pDok );
3130 0 : aArgs[1] = uno::Any( xCellRange );
3131 0 : xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( pDok->GetDocumentShell(), "ooo.vba.excel.Range", aArgs );
3132 0 : if ( xVBARange.is() )
3133 : {
3134 0 : String sDummy(RTL_CONSTASCII_USTRINGPARAM("A-Range") );
3135 0 : SbxObjectRef aObj = GetSbUnoObject( sDummy, uno::Any( xVBARange ) );
3136 0 : SetSbUnoObjectDfltPropName( aObj );
3137 0 : bOk = pPar->PutObject( aObj );
3138 0 : }
3139 : }
3140 0 : catch( uno::Exception& )
3141 : {
3142 : }
3143 0 : return bOk;
3144 : }
3145 :
3146 : #endif
3147 :
3148 0 : void ScInterpreter::ScMacro()
3149 : {
3150 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScMacro" );
3151 :
3152 : #ifdef DISABLE_SCRIPTING
3153 : PushNoValue(); // ohne DocShell kein CallBasic
3154 : return;
3155 : #else
3156 0 : SbxBase::ResetError();
3157 :
3158 0 : sal_uInt8 nParamCount = GetByte();
3159 0 : String aMacro( pCur->GetExternal() );
3160 :
3161 0 : SfxObjectShell* pDocSh = pDok->GetDocumentShell();
3162 0 : if ( !pDocSh || !pDok->CheckMacroWarn() )
3163 : {
3164 0 : PushNoValue(); // ohne DocShell kein CallBasic
3165 : return;
3166 : }
3167 :
3168 : // keine Sicherheitsabfrage mehr vorneweg (nur CheckMacroWarn), das passiert im CallBasic
3169 :
3170 : // Wenn das Dok waehrend eines Basic-Calls geladen wurde,
3171 : // ist das Sbx-Objekt evtl. nicht angelegt (?)
3172 : // pDocSh->GetSbxObject();
3173 :
3174 : // Funktion ueber den einfachen Namen suchen,
3175 : // dann aBasicStr, aMacroStr fuer SfxObjectShell::CallBasic zusammenbauen
3176 :
3177 0 : StarBASIC* pRoot = pDocSh->GetBasic();
3178 0 : SbxVariable* pVar = pRoot->Find( aMacro, SbxCLASS_METHOD );
3179 0 : if( !pVar || pVar->GetType() == SbxVOID || !pVar->ISA(SbMethod) )
3180 : {
3181 0 : PushError( errNoMacro );
3182 : return;
3183 : }
3184 :
3185 0 : bool bVolatileMacro = false;
3186 0 : SbMethod* pMethod = (SbMethod*)pVar;
3187 :
3188 0 : SbModule* pModule = pMethod->GetModule();
3189 0 : bool bUseVBAObjects = pModule->IsVBACompat();
3190 0 : SbxObject* pObject = pModule->GetParent();
3191 : OSL_ENSURE(pObject->IsA(TYPE(StarBASIC)), "Kein Basic gefunden!");
3192 0 : String aMacroStr = pObject->GetName();
3193 0 : aMacroStr += '.';
3194 0 : aMacroStr += pModule->GetName();
3195 0 : aMacroStr += '.';
3196 0 : aMacroStr += pMethod->GetName();
3197 0 : String aBasicStr;
3198 0 : if (pObject->GetParent())
3199 : {
3200 0 : aBasicStr = pObject->GetParent()->GetName(); // Dokumentenbasic
3201 : }
3202 : else
3203 : {
3204 0 : aBasicStr = SFX_APP()->GetName(); // Applikationsbasic
3205 : }
3206 : // Parameter-Array zusammenbauen
3207 :
3208 0 : SbxArrayRef refPar = new SbxArray;
3209 0 : bool bOk = true;
3210 0 : for( short i = nParamCount; i && bOk ; i-- )
3211 : {
3212 0 : SbxVariable* pPar = refPar->Get( (sal_uInt16) i );
3213 0 : sal_uInt8 nStackType = sal::static_int_cast<sal_uInt8>( GetStackType() );
3214 0 : switch( nStackType )
3215 : {
3216 : case svDouble:
3217 0 : pPar->PutDouble( GetDouble() );
3218 0 : break;
3219 : case svString:
3220 0 : pPar->PutString( GetString() );
3221 0 : break;
3222 : case svSingleRef:
3223 : {
3224 0 : ScAddress aAdr;
3225 0 : PopSingleRef( aAdr );
3226 0 : if ( bUseVBAObjects )
3227 : {
3228 0 : ScRange aRange( aAdr );
3229 0 : bOk = lcl_setVBARange( aRange, pDok, pPar );
3230 : }
3231 : else
3232 : {
3233 0 : bOk = SetSbxVariable( pPar, aAdr );
3234 : }
3235 : }
3236 0 : break;
3237 : case svDoubleRef:
3238 : {
3239 : SCCOL nCol1;
3240 : SCROW nRow1;
3241 : SCTAB nTab1;
3242 : SCCOL nCol2;
3243 : SCROW nRow2;
3244 : SCTAB nTab2;
3245 0 : PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3246 0 : if( nTab1 != nTab2 )
3247 : {
3248 0 : SetError( errIllegalParameter );
3249 0 : bOk = false;
3250 : }
3251 : else
3252 : {
3253 0 : if ( bUseVBAObjects )
3254 : {
3255 0 : ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3256 0 : bOk = lcl_setVBARange( aRange, pDok, pPar );
3257 : }
3258 : else
3259 : {
3260 0 : SbxDimArrayRef refArray = new SbxDimArray;
3261 0 : refArray->AddDim32( 1, nRow2 - nRow1 + 1 );
3262 0 : refArray->AddDim32( 1, nCol2 - nCol1 + 1 );
3263 0 : ScAddress aAdr( nCol1, nRow1, nTab1 );
3264 0 : for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
3265 : {
3266 0 : aAdr.SetRow( nRow );
3267 : sal_Int32 nIdx[ 2 ];
3268 0 : nIdx[ 0 ] = nRow-nRow1+1;
3269 0 : for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
3270 : {
3271 0 : aAdr.SetCol( nCol );
3272 0 : nIdx[ 1 ] = nCol-nCol1+1;
3273 0 : SbxVariable* p = refArray->Get32( nIdx );
3274 0 : bOk = SetSbxVariable( p, aAdr );
3275 : }
3276 : }
3277 0 : pPar->PutObject( refArray );
3278 : }
3279 : }
3280 : }
3281 0 : break;
3282 : case svMatrix:
3283 : {
3284 0 : ScMatrixRef pMat = PopMatrix();
3285 : SCSIZE nC, nR;
3286 0 : if (pMat)
3287 : {
3288 0 : pMat->GetDimensions(nC, nR);
3289 0 : SbxDimArrayRef refArray = new SbxDimArray;
3290 0 : refArray->AddDim32( 1, static_cast<sal_Int32>(nR) );
3291 0 : refArray->AddDim32( 1, static_cast<sal_Int32>(nC) );
3292 0 : for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
3293 : {
3294 : sal_Int32 nIdx[ 2 ];
3295 0 : nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1);
3296 0 : for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
3297 : {
3298 0 : nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1);
3299 0 : SbxVariable* p = refArray->Get32( nIdx );
3300 0 : if (pMat->IsString(nMatCol, nMatRow))
3301 : {
3302 0 : p->PutString( pMat->GetString(nMatCol, nMatRow) );
3303 : }
3304 : else
3305 : {
3306 0 : p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
3307 : }
3308 : }
3309 : }
3310 0 : pPar->PutObject( refArray );
3311 : }
3312 : else
3313 : {
3314 0 : SetError( errIllegalParameter );
3315 0 : }
3316 : }
3317 0 : break;
3318 : default:
3319 0 : SetError( errIllegalParameter );
3320 0 : bOk = false;
3321 : }
3322 : }
3323 0 : if( bOk )
3324 : {
3325 0 : pDok->LockTable( aPos.Tab() );
3326 0 : SbxVariableRef refRes = new SbxVariable;
3327 0 : pDok->IncMacroInterpretLevel();
3328 0 : ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar, refRes );
3329 0 : pDok->DecMacroInterpretLevel();
3330 0 : pDok->UnlockTable( aPos.Tab() );
3331 :
3332 0 : ScMacroManager* pMacroMgr = pDok->GetMacroManager();
3333 0 : if (pMacroMgr)
3334 : {
3335 0 : bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
3336 0 : pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
3337 : }
3338 :
3339 0 : SbxDataType eResType = refRes->GetType();
3340 0 : if( pVar->GetError() )
3341 : {
3342 0 : SetError( errNoValue);
3343 : }
3344 0 : if ( eRet != ERRCODE_NONE )
3345 : {
3346 0 : PushNoValue();
3347 : }
3348 0 : else if( eResType >= SbxINTEGER && eResType <= SbxDOUBLE )
3349 : {
3350 0 : PushDouble( refRes->GetDouble() );
3351 : }
3352 0 : else if ( eResType & SbxARRAY )
3353 : {
3354 0 : SbxBase* pElemObj = refRes->GetObject();
3355 0 : SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
3356 0 : short nDim = pDimArray->GetDims();
3357 0 : if ( 1 <= nDim && nDim <= 2 )
3358 : {
3359 : sal_Int32 nCs, nCe, nRs, nRe;
3360 : SCSIZE nC, nR;
3361 : SCCOL nColIdx;
3362 : SCROW nRowIdx;
3363 0 : if ( nDim == 1 )
3364 : { // array( cols ) eine Zeile, mehrere Spalten
3365 0 : pDimArray->GetDim32( 1, nCs, nCe );
3366 0 : nC = static_cast<SCSIZE>(nCe - nCs + 1);
3367 0 : nRs = nRe = 0;
3368 0 : nR = 1;
3369 0 : nColIdx = 0;
3370 0 : nRowIdx = 1;
3371 : }
3372 : else
3373 : { // array( rows, cols )
3374 0 : pDimArray->GetDim32( 1, nRs, nRe );
3375 0 : nR = static_cast<SCSIZE>(nRe - nRs + 1);
3376 0 : pDimArray->GetDim32( 2, nCs, nCe );
3377 0 : nC = static_cast<SCSIZE>(nCe - nCs + 1);
3378 0 : nColIdx = 1;
3379 0 : nRowIdx = 0;
3380 : }
3381 0 : ScMatrixRef pMat = GetNewMat( nC, nR);
3382 0 : if ( pMat )
3383 : {
3384 : SbxVariable* pV;
3385 : SbxDataType eType;
3386 0 : for ( SCSIZE j=0; j < nR; j++ )
3387 : {
3388 : sal_Int32 nIdx[ 2 ];
3389 : // bei eindimensionalem array( cols ) wird nIdx[1]
3390 : // von SbxDimArray::Get ignoriert
3391 0 : nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j);
3392 0 : for ( SCSIZE i=0; i < nC; i++ )
3393 : {
3394 0 : nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i);
3395 0 : pV = pDimArray->Get32( nIdx );
3396 0 : eType = pV->GetType();
3397 0 : if ( eType >= SbxINTEGER && eType <= SbxDOUBLE )
3398 : {
3399 0 : pMat->PutDouble( pV->GetDouble(), i, j );
3400 : }
3401 : else
3402 : {
3403 0 : pMat->PutString( pV->GetOUString(), i, j );
3404 : }
3405 : }
3406 : }
3407 0 : PushMatrix( pMat );
3408 : }
3409 : else
3410 : {
3411 0 : PushIllegalArgument();
3412 0 : }
3413 : }
3414 : else
3415 : {
3416 0 : PushNoValue();
3417 : }
3418 : }
3419 : else
3420 : {
3421 0 : PushString( refRes->GetOUString() );
3422 0 : }
3423 : }
3424 :
3425 0 : if (bVolatileMacro && meVolatileType == NOT_VOLATILE)
3426 0 : meVolatileType = VOLATILE_MACRO;
3427 : #endif
3428 : }
3429 :
3430 : #ifndef DISABLE_SCRIPTING
3431 :
3432 0 : bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
3433 : {
3434 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::SetSbxVariable" );
3435 0 : bool bOk = true;
3436 0 : ScBaseCell* pCell = pDok->GetCell( rPos );
3437 0 : if (pCell)
3438 : {
3439 : sal_uInt16 nErr;
3440 : double nVal;
3441 0 : switch( pCell->GetCellType() )
3442 : {
3443 : case CELLTYPE_VALUE :
3444 0 : nVal = GetValueCellValue( rPos, (ScValueCell*)pCell );
3445 0 : pVar->PutDouble( nVal );
3446 0 : break;
3447 : case CELLTYPE_STRING :
3448 : {
3449 0 : rtl::OUString aVal = ((ScStringCell*)pCell)->GetString();
3450 0 : pVar->PutString( aVal );
3451 0 : break;
3452 : }
3453 : case CELLTYPE_EDIT :
3454 : {
3455 0 : rtl::OUString aVal = ((ScEditCell*) pCell)->GetString();
3456 0 : pVar->PutString( aVal );
3457 0 : break;
3458 : }
3459 : case CELLTYPE_FORMULA :
3460 0 : nErr = ((ScFormulaCell*)pCell)->GetErrCode();
3461 0 : if( !nErr )
3462 : {
3463 0 : if( ((ScFormulaCell*)pCell)->IsValue() )
3464 : {
3465 0 : nVal = ((ScFormulaCell*)pCell)->GetValue();
3466 0 : pVar->PutDouble( nVal );
3467 : }
3468 : else
3469 : {
3470 0 : rtl::OUString aVal = ((ScFormulaCell*)pCell)->GetString();
3471 0 : pVar->PutString( aVal );
3472 : }
3473 : }
3474 : else
3475 0 : SetError( nErr ), bOk = false;
3476 0 : break;
3477 : default :
3478 0 : pVar->PutDouble( 0.0 );
3479 : }
3480 : }
3481 : else
3482 0 : pVar->PutDouble( 0.0 );
3483 0 : return bOk;
3484 : }
3485 :
3486 : #endif
3487 :
3488 : namespace {
3489 :
3490 : class FindByPointer : ::std::unary_function<ScInterpreterTableOpParams, bool>
3491 : {
3492 : const ScInterpreterTableOpParams* mpTableOp;
3493 : public:
3494 0 : FindByPointer(const ScInterpreterTableOpParams* p) : mpTableOp(p) {}
3495 0 : bool operator() (const ScInterpreterTableOpParams& val) const
3496 : {
3497 0 : return &val == mpTableOp;
3498 : }
3499 : };
3500 :
3501 : }
3502 :
3503 0 : void ScInterpreter::ScTableOp()
3504 : {
3505 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTableOp" );
3506 0 : sal_uInt8 nParamCount = GetByte();
3507 0 : if (nParamCount != 3 && nParamCount != 5)
3508 : {
3509 0 : PushIllegalParameter();
3510 0 : return;
3511 : }
3512 0 : ScInterpreterTableOpParams* pTableOp = new ScInterpreterTableOpParams;
3513 0 : if (nParamCount == 5)
3514 : {
3515 0 : PopSingleRef( pTableOp->aNew2 );
3516 0 : PopSingleRef( pTableOp->aOld2 );
3517 : }
3518 0 : PopSingleRef( pTableOp->aNew1 );
3519 0 : PopSingleRef( pTableOp->aOld1 );
3520 0 : PopSingleRef( pTableOp->aFormulaPos );
3521 :
3522 0 : pTableOp->bValid = true;
3523 0 : pDok->aTableOpList.push_back( pTableOp );
3524 0 : pDok->IncInterpreterTableOpLevel();
3525 :
3526 0 : bool bReuseLastParams = (pDok->aLastTableOpParams == *pTableOp);
3527 0 : if ( bReuseLastParams )
3528 : {
3529 0 : pTableOp->aNotifiedFormulaPos = pDok->aLastTableOpParams.aNotifiedFormulaPos;
3530 0 : pTableOp->bRefresh = true;
3531 0 : for ( ::std::vector< ScAddress >::const_iterator iBroadcast(
3532 0 : pTableOp->aNotifiedFormulaPos.begin() );
3533 0 : iBroadcast != pTableOp->aNotifiedFormulaPos.end();
3534 : ++iBroadcast )
3535 : { // emulate broadcast and indirectly collect cell pointers
3536 0 : ScBaseCell* pCell = pDok->GetCell( *iBroadcast );
3537 0 : if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
3538 0 : ((ScFormulaCell*)pCell)->SetTableOpDirty();
3539 : }
3540 : }
3541 : else
3542 : { // broadcast and indirectly collect cell pointers and positions
3543 0 : pDok->SetTableOpDirty( pTableOp->aOld1 );
3544 0 : if ( nParamCount == 5 )
3545 0 : pDok->SetTableOpDirty( pTableOp->aOld2 );
3546 : }
3547 0 : pTableOp->bCollectNotifications = false;
3548 :
3549 0 : ScBaseCell* pFCell = pDok->GetCell( pTableOp->aFormulaPos );
3550 0 : if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA )
3551 0 : ((ScFormulaCell*)pFCell)->SetDirtyVar();
3552 0 : if ( HasCellValueData( pFCell ) )
3553 0 : PushDouble( GetCellValue( pTableOp->aFormulaPos, pFCell ));
3554 : else
3555 : {
3556 0 : String aCellString;
3557 0 : GetCellString( aCellString, pFCell );
3558 0 : PushString( aCellString );
3559 : }
3560 :
3561 : boost::ptr_vector< ScInterpreterTableOpParams >::iterator itr =
3562 0 : ::std::find_if(pDok->aTableOpList.begin(), pDok->aTableOpList.end(), FindByPointer(pTableOp));
3563 0 : if (itr != pDok->aTableOpList.end())
3564 0 : pTableOp = pDok->aTableOpList.release(itr).release();
3565 :
3566 : // set dirty again once more to be able to recalculate original
3567 0 : for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast(
3568 0 : pTableOp->aNotifiedFormulaCells.begin() );
3569 0 : iBroadcast != pTableOp->aNotifiedFormulaCells.end();
3570 : ++iBroadcast )
3571 : {
3572 0 : (*iBroadcast)->SetTableOpDirty();
3573 : }
3574 :
3575 : // save these params for next incarnation
3576 0 : if ( !bReuseLastParams )
3577 0 : pDok->aLastTableOpParams = *pTableOp;
3578 :
3579 0 : if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA )
3580 : {
3581 0 : ((ScFormulaCell*)pFCell)->SetDirtyVar();
3582 0 : ((ScFormulaCell*)pFCell)->GetErrCode(); // recalculate original
3583 : }
3584 :
3585 : // Reset all dirty flags so next incarnation does really collect all cell
3586 : // pointers during notifications and not just non-dirty ones, which may
3587 : // happen if a formula cell is used by more than one TableOp block.
3588 0 : for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast2(
3589 0 : pTableOp->aNotifiedFormulaCells.begin() );
3590 0 : iBroadcast2 != pTableOp->aNotifiedFormulaCells.end();
3591 : ++iBroadcast2 )
3592 : {
3593 0 : (*iBroadcast2)->ResetTableOpDirtyVar();
3594 : }
3595 0 : delete pTableOp;
3596 :
3597 0 : pDok->DecInterpreterTableOpLevel();
3598 : }
3599 :
3600 0 : void ScInterpreter::ScDBArea()
3601 : {
3602 0 : ScDBData* pDBData = pDok->GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex());
3603 0 : if (pDBData)
3604 : {
3605 : ScComplexRefData aRefData;
3606 0 : aRefData.InitFlags();
3607 : pDBData->GetArea( (SCTAB&) aRefData.Ref1.nTab,
3608 : (SCCOL&) aRefData.Ref1.nCol,
3609 : (SCROW&) aRefData.Ref1.nRow,
3610 : (SCCOL&) aRefData.Ref2.nCol,
3611 0 : (SCROW&) aRefData.Ref2.nRow);
3612 0 : aRefData.Ref2.nTab = aRefData.Ref1.nTab;
3613 0 : aRefData.CalcRelFromAbs( aPos );
3614 0 : PushTempToken( new ScDoubleRefToken( aRefData ) );
3615 : }
3616 : else
3617 0 : PushError( errNoName);
3618 0 : }
3619 :
3620 :
3621 0 : void ScInterpreter::ScColRowNameAuto()
3622 : {
3623 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScColRowNameAuto" );
3624 0 : ScComplexRefData aRefData( static_cast<const ScToken*>(pCur)->GetDoubleRef() );
3625 0 : aRefData.CalcAbsIfRel( aPos );
3626 0 : if ( aRefData.Valid() )
3627 : {
3628 : SCsCOL nStartCol;
3629 : SCsROW nStartRow;
3630 : SCsCOL nCol2;
3631 : SCsROW nRow2;
3632 : // evtl. Begrenzung durch definierte ColRowNameRanges merken
3633 0 : nCol2 = aRefData.Ref2.nCol;
3634 0 : nRow2 = aRefData.Ref2.nRow;
3635 : // DataArea der ersten Zelle
3636 0 : nStartCol = aRefData.Ref2.nCol = aRefData.Ref1.nCol;
3637 0 : nStartRow = aRefData.Ref2.nRow = aRefData.Ref1.nRow;
3638 0 : aRefData.Ref2.nTab = aRefData.Ref1.nTab;
3639 : pDok->GetDataArea( (SCTAB&) aRefData.Ref1.nTab,
3640 : (SCCOL&) aRefData.Ref1.nCol,
3641 : (SCROW&) aRefData.Ref1.nRow,
3642 : (SCCOL&) aRefData.Ref2.nCol,
3643 : (SCROW&) aRefData.Ref2.nRow,
3644 0 : true, false );
3645 : // DataArea im Ursprung begrenzen
3646 0 : aRefData.Ref1.nCol = nStartCol;
3647 0 : aRefData.Ref1.nRow = nStartRow;
3648 :
3649 : //! korrespondiert mit ScCompiler::GetToken
3650 0 : if ( aRefData.Ref1.IsColRel() )
3651 : { // ColName
3652 0 : aRefData.Ref2.nCol = nStartCol;
3653 : // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
3654 0 : if ( aRefData.Ref2.nRow > nRow2 )
3655 0 : aRefData.Ref2.nRow = nRow2;
3656 : SCROW nMyRow;
3657 0 : if ( aPos.Col() == nStartCol
3658 0 : && nStartRow <= (nMyRow = aPos.Row()) && nMyRow <= aRefData.Ref2.nRow )
3659 : { // Formel in gleicher Spalte und innerhalb des Range
3660 0 : if ( nMyRow == nStartRow )
3661 : { // direkt unter dem Namen den Rest nehmen
3662 0 : nStartRow++;
3663 0 : if ( nStartRow > MAXROW )
3664 0 : nStartRow = MAXROW;
3665 0 : aRefData.Ref1.nRow = nStartRow;
3666 : }
3667 : else
3668 : { // weiter unten vom Namen bis zur Formelzelle
3669 0 : aRefData.Ref2.nRow = nMyRow - 1;
3670 : }
3671 : }
3672 : }
3673 : else
3674 : { // RowName
3675 0 : aRefData.Ref2.nRow = nStartRow;
3676 : // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
3677 0 : if ( aRefData.Ref2.nCol > nCol2 )
3678 0 : aRefData.Ref2.nCol = nCol2;
3679 : SCCOL nMyCol;
3680 0 : if ( aPos.Row() == nStartRow
3681 0 : && nStartCol <= (nMyCol = aPos.Col()) && nMyCol <= aRefData.Ref2.nCol )
3682 : { // Formel in gleicher Zeile und innerhalb des Range
3683 0 : if ( nMyCol == nStartCol )
3684 : { // direkt neben dem Namen den Rest nehmen
3685 0 : nStartCol++;
3686 0 : if ( nStartCol > MAXCOL )
3687 0 : nStartCol = MAXCOL;
3688 0 : aRefData.Ref1.nCol = nStartCol;
3689 : }
3690 : else
3691 : { // weiter rechts vom Namen bis zur Formelzelle
3692 0 : aRefData.Ref2.nCol = nMyCol - 1;
3693 : }
3694 : }
3695 : }
3696 0 : aRefData.CalcRelFromAbs( aPos );
3697 0 : PushTempToken( new ScDoubleRefToken( aRefData ) );
3698 : }
3699 : else
3700 0 : PushError( errNoRef );
3701 0 : }
3702 :
3703 : // --- internals ------------------------------------------------------------
3704 :
3705 :
3706 0 : void ScInterpreter::ScTTT()
3707 : { // Temporaerer Test-Tanz, zum auspropieren von Funktionen etc.
3708 0 : sal_uInt8 nParamCount = GetByte();
3709 : // do something, nParamCount bei Pops runterzaehlen!
3710 :
3711 : // Stack aufraeumen
3712 0 : while ( nParamCount-- > 0)
3713 0 : Pop();
3714 0 : PushError(errNoValue);
3715 0 : }
3716 :
3717 : // -------------------------------------------------------------------------
3718 :
3719 :
3720 3010 : ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc,
3721 : const ScAddress& rPos, ScTokenArray& r ) :
3722 : aCode( r ),
3723 : aPos( rPos ),
3724 : rArr( r ),
3725 : pDok( pDoc ),
3726 : pTokenMatrixMap( NULL ),
3727 : pMyFormulaCell( pCell ),
3728 3010 : pFormatter( pDoc->GetFormatTable() ),
3729 : mnStringNoValueError( errNoValue),
3730 3010 : bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() ),
3731 9030 : meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE)
3732 : {
3733 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScTTT" );
3734 :
3735 3010 : sal_uInt8 cMatFlag = pMyFormulaCell->GetMatrixFlag();
3736 3010 : bMatrixFormula = ( cMatFlag == MM_FORMULA || cMatFlag == MM_FAKE );
3737 3010 : if (!bGlobalStackInUse)
3738 : {
3739 780 : bGlobalStackInUse = true;
3740 780 : if (!pGlobalStack)
3741 3 : pGlobalStack = new ScTokenStack;
3742 780 : pStackObj = pGlobalStack;
3743 : }
3744 : else
3745 : {
3746 2230 : pStackObj = new ScTokenStack;
3747 : }
3748 3010 : pStack = pStackObj->pPointer;
3749 3010 : }
3750 :
3751 6020 : ScInterpreter::~ScInterpreter()
3752 : {
3753 : // delete pStack;
3754 :
3755 3010 : if ( pStackObj == pGlobalStack )
3756 780 : bGlobalStackInUse = false;
3757 : else
3758 2230 : delete pStackObj;
3759 3010 : if (pTokenMatrixMap)
3760 6 : delete pTokenMatrixMap;
3761 3010 : }
3762 :
3763 76 : void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig)
3764 : {
3765 76 : maGlobalConfig = rConfig;
3766 76 : }
3767 :
3768 54 : const ScCalcConfig& ScInterpreter::GetGlobalConfig()
3769 : {
3770 54 : return maGlobalConfig;
3771 : }
3772 :
3773 0 : void ScInterpreter::GlobalExit()
3774 : {
3775 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::GlobalExit" );
3776 : OSL_ENSURE(!bGlobalStackInUse, "wer benutzt noch den TokenStack?");
3777 0 : DELETEZ(pGlobalStack);
3778 0 : }
3779 :
3780 :
3781 3010 : StackVar ScInterpreter::Interpret()
3782 : {
3783 : RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Interpret" );
3784 3010 : short nRetTypeExpr = NUMBERFORMAT_UNDEFINED;
3785 3010 : sal_uLong nRetIndexExpr = 0;
3786 3010 : sal_uInt16 nErrorFunction = 0;
3787 3010 : sal_uInt16 nErrorFunctionCount = 0;
3788 : sal_uInt16 nStackBase;
3789 :
3790 3010 : nGlobalError = 0;
3791 3010 : nStackBase = sp = maxsp = 0;
3792 3010 : nRetFmtType = NUMBERFORMAT_UNDEFINED;
3793 3010 : nFuncFmtType = NUMBERFORMAT_UNDEFINED;
3794 3010 : nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
3795 3010 : xResult = NULL;
3796 3010 : pJumpMatrix = NULL;
3797 3010 : glSubTotal = false;
3798 3010 : ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
3799 :
3800 : // Once upon a time we used to have FP exceptions on, and there was a
3801 : // Windows printer driver that kept switching off exceptions, so we had to
3802 : // switch them back on again every time. Who knows if there isn't a driver
3803 : // that keeps switching exceptions on, now that we run with exceptions off,
3804 : // so reassure exceptions are really off.
3805 : SAL_MATH_FPEXCEPTIONS_OFF();
3806 :
3807 3010 : aCode.Reset();
3808 33698 : while( ( pCur = aCode.Next() ) != NULL
3809 13840 : && (!nGlobalError || nErrorFunction <= nErrorFunctionCount) )
3810 : {
3811 13838 : OpCode eOp = pCur->GetOpCode();
3812 13838 : cPar = pCur->GetByte();
3813 13838 : if ( eOp == ocPush )
3814 : {
3815 : // RPN code push without error
3816 8002 : PushWithoutError( (FormulaToken&) *pCur );
3817 : }
3818 11696 : else if (pTokenMatrixMap && !(eOp == ocIf || eOp == ocChose) &&
3819 5860 : ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
3820 11708 : pTokenMatrixMap->end()) &&
3821 0 : (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
3822 : {
3823 : // Path already calculated, reuse result.
3824 0 : nStackBase = sp - pCur->GetParamCount();
3825 0 : if ( nStackBase > sp )
3826 0 : nStackBase = sp; // underflow?!?
3827 0 : sp = nStackBase;
3828 0 : PushTempToken( (*aTokenMatrixMapIter).second.get());
3829 : }
3830 : else
3831 : {
3832 : // previous expression determines the current number format
3833 5836 : nCurFmtType = nRetTypeExpr;
3834 5836 : nCurFmtIndex = nRetIndexExpr;
3835 : // default function's format, others are set if needed
3836 5836 : nFuncFmtType = NUMBERFORMAT_NUMBER;
3837 5836 : nFuncFmtIndex = 0;
3838 :
3839 5836 : if ( eOp == ocIf || eOp == ocChose )
3840 12 : nStackBase = sp; // don't mess around with the jumps
3841 : else
3842 : {
3843 : // Convert parameters to matrix if in array/matrix formula and
3844 : // parameters of function indicate doing so. Create JumpMatrix
3845 : // if necessary.
3846 5824 : if ( MatrixParameterConversion() )
3847 : {
3848 0 : eOp = ocNone; // JumpMatrix created
3849 0 : nStackBase = sp;
3850 : }
3851 : else
3852 5824 : nStackBase = sp - pCur->GetParamCount();
3853 : }
3854 5836 : if ( nStackBase > sp )
3855 0 : nStackBase = sp; // underflow?!?
3856 :
3857 5836 : switch( eOp )
3858 : {
3859 : case ocSep:
3860 : case ocClose: // pushed by the compiler
3861 6 : case ocMissing : ScMissing(); break;
3862 0 : case ocMacro : ScMacro(); break;
3863 0 : case ocDBArea : ScDBArea(); break;
3864 0 : case ocColRowNameAuto : ScColRowNameAuto(); break;
3865 12 : case ocIf : ScIfJump(); break;
3866 0 : case ocChose : ScChoseJump(); break;
3867 1031 : case ocAdd : ScAdd(); break;
3868 1143 : case ocSub : ScSub(); break;
3869 1153 : case ocMul : ScMul(); break;
3870 1224 : case ocDiv : ScDiv(); break;
3871 0 : case ocAmpersand : ScAmpersand(); break;
3872 0 : case ocPow : ScPow(); break;
3873 12 : case ocEqual : ScEqual(); break;
3874 0 : case ocNotEqual : ScNotEqual(); break;
3875 0 : case ocLess : ScLess(); break;
3876 3 : case ocGreater : ScGreater(); break;
3877 0 : case ocLessEqual : ScLessEqual(); break;
3878 0 : case ocGreaterEqual : ScGreaterEqual(); break;
3879 7 : case ocAnd : ScAnd(); break;
3880 9 : case ocOr : ScOr(); break;
3881 0 : case ocXor : ScXor(); break;
3882 0 : case ocIntersect : ScIntersect(); break;
3883 0 : case ocRange : ScRangeFunc(); break;
3884 0 : case ocUnion : ScUnionFunc(); break;
3885 3 : case ocNot : ScNot(); break;
3886 : case ocNegSub :
3887 42 : case ocNeg : ScNeg(); break;
3888 0 : case ocPercentSign : ScPercentSign(); break;
3889 10 : case ocPi : ScPi(); break;
3890 0 : case ocRandom : ScRandom(); break;
3891 5 : case ocTrue : ScTrue(); break;
3892 4 : case ocFalse : ScFalse(); break;
3893 0 : case ocGetActDate : ScGetActDate(); break;
3894 3 : case ocGetActTime : ScGetActTime(); break;
3895 8 : case ocNotAvail : PushError( NOTAVAILABLE); break;
3896 0 : case ocDeg : ScDeg(); break;
3897 0 : case ocRad : ScRad(); break;
3898 2 : case ocSin : ScSin(); break;
3899 2 : case ocCos : ScCos(); break;
3900 0 : case ocTan : ScTan(); break;
3901 0 : case ocCot : ScCot(); break;
3902 0 : case ocArcSin : ScArcSin(); break;
3903 3 : case ocArcCos : ScArcCos(); break;
3904 0 : case ocArcTan : ScArcTan(); break;
3905 3 : case ocArcCot : ScArcCot(); break;
3906 0 : case ocSinHyp : ScSinHyp(); break;
3907 0 : case ocCosHyp : ScCosHyp(); break;
3908 0 : case ocTanHyp : ScTanHyp(); break;
3909 0 : case ocCotHyp : ScCotHyp(); break;
3910 0 : case ocArcSinHyp : ScArcSinHyp(); break;
3911 2 : case ocArcCosHyp : ScArcCosHyp(); break;
3912 0 : case ocArcTanHyp : ScArcTanHyp(); break;
3913 0 : case ocArcCotHyp : ScArcCotHyp(); break;
3914 0 : case ocCosecant : ScCosecant(); break;
3915 0 : case ocSecant : ScSecant(); break;
3916 0 : case ocCosecantHyp : ScCosecantHyp(); break;
3917 0 : case ocSecantHyp : ScSecantHyp(); break;
3918 0 : case ocExp : ScExp(); break;
3919 0 : case ocLn : ScLn(); break;
3920 0 : case ocLog10 : ScLog10(); break;
3921 5 : case ocSqrt : ScSqrt(); break;
3922 0 : case ocFact : ScFact(); break;
3923 0 : case ocGetYear : ScGetYear(); break;
3924 0 : case ocGetMonth : ScGetMonth(); break;
3925 0 : case ocGetDay : ScGetDay(); break;
3926 0 : case ocGetDayOfWeek : ScGetDayOfWeek(); break;
3927 0 : case ocWeek : ScGetWeekOfYear(); break;
3928 0 : case ocEasterSunday : ScEasterSunday(); break;
3929 0 : case ocGetHour : ScGetHour(); break;
3930 0 : case ocGetMin : ScGetMin(); break;
3931 0 : case ocGetSec : ScGetSec(); break;
3932 0 : case ocPlusMinus : ScPlusMinus(); break;
3933 3 : case ocAbs : ScAbs(); break;
3934 0 : case ocInt : ScInt(); break;
3935 6 : case ocEven : ScEven(); break;
3936 6 : case ocOdd : ScOdd(); break;
3937 0 : case ocPhi : ScPhi(); break;
3938 0 : case ocGauss : ScGauss(); break;
3939 0 : case ocStdNormDist : ScStdNormDist(); break;
3940 0 : case ocFisher : ScFisher(); break;
3941 0 : case ocFisherInv : ScFisherInv(); break;
3942 3 : case ocIsEmpty : ScIsEmpty(); break;
3943 4 : case ocIsString : ScIsString(); break;
3944 3 : case ocIsNonString : ScIsNonString(); break;
3945 4 : case ocIsLogical : ScIsLogical(); break;
3946 5 : case ocType : ScType(); break;
3947 19 : case ocCell : ScCell(); break;
3948 6 : case ocIsRef : ScIsRef(); break;
3949 3 : case ocIsValue : ScIsValue(); break;
3950 3 : case ocIsFormula : ScIsFormula(); break;
3951 6 : case ocFormula : ScFormula(); break;
3952 4 : case ocIsNA : ScIsNV(); break;
3953 4 : case ocIsErr : ScIsErr(); break;
3954 4 : case ocIsError : ScIsError(); break;
3955 4 : case ocIsEven : ScIsEven(); break;
3956 5 : case ocIsOdd : ScIsOdd(); break;
3957 58 : case ocN : ScN(); break;
3958 0 : case ocGetDateValue : ScGetDateValue(); break;
3959 0 : case ocGetTimeValue : ScGetTimeValue(); break;
3960 0 : case ocCode : ScCode(); break;
3961 0 : case ocTrim : ScTrim(); break;
3962 0 : case ocUpper : ScUpper(); break;
3963 0 : case ocPropper : ScPropper(); break;
3964 0 : case ocLower : ScLower(); break;
3965 0 : case ocLen : ScLen(); break;
3966 3 : case ocT : ScT(); break;
3967 0 : case ocClean : ScClean(); break;
3968 0 : case ocValue : ScValue(); break;
3969 0 : case ocChar : ScChar(); break;
3970 0 : case ocArcTan2 : ScArcTan2(); break;
3971 0 : case ocMod : ScMod(); break;
3972 0 : case ocPower : ScPower(); break;
3973 4 : case ocRound : ScRound(); break;
3974 0 : case ocRoundUp : ScRoundUp(); break;
3975 : case ocTrunc :
3976 0 : case ocRoundDown : ScRoundDown(); break;
3977 0 : case ocCeil : ScCeil(); break;
3978 0 : case ocFloor : ScFloor(); break;
3979 0 : case ocSumProduct : ScSumProduct(); break;
3980 0 : case ocSumSQ : ScSumSQ(); break;
3981 0 : case ocSumX2MY2 : ScSumX2MY2(); break;
3982 0 : case ocSumX2DY2 : ScSumX2DY2(); break;
3983 0 : case ocSumXMY2 : ScSumXMY2(); break;
3984 0 : case ocLog : ScLog(); break;
3985 0 : case ocGCD : ScGCD(); break;
3986 0 : case ocLCM : ScLCM(); break;
3987 0 : case ocGetDate : ScGetDate(); break;
3988 0 : case ocGetTime : ScGetTime(); break;
3989 0 : case ocGetDiffDate : ScGetDiffDate(); break;
3990 0 : case ocGetDiffDate360 : ScGetDiffDate360(); break;
3991 90 : case ocGetDateDif : ScGetDateDif(); break;
3992 0 : case ocMin : ScMin( false ); break;
3993 0 : case ocMinA : ScMin( true ); break;
3994 0 : case ocMax : ScMax( false ); break;
3995 0 : case ocMaxA : ScMax( true ); break;
3996 682 : case ocSum : ScSum(); break;
3997 3 : case ocProduct : ScProduct(); break;
3998 0 : case ocNPV : ScNPV(); break;
3999 0 : case ocIRR : ScIRR(); break;
4000 0 : case ocMIRR : ScMIRR(); break;
4001 0 : case ocISPMT : ScISPMT(); break;
4002 4 : case ocAverage : ScAverage( false ); break;
4003 0 : case ocAverageA : ScAverage( true ); break;
4004 3 : case ocCount : ScCount(); break;
4005 1 : case ocCount2 : ScCount2(); break;
4006 0 : case ocVar : ScVar( false ); break;
4007 0 : case ocVarA : ScVar( true ); break;
4008 0 : case ocVarP : ScVarP( false ); break;
4009 0 : case ocVarPA : ScVarP( true ); break;
4010 0 : case ocStDev : ScStDev( false ); break;
4011 0 : case ocStDevA : ScStDev( true ); break;
4012 0 : case ocStDevP : ScStDevP( false ); break;
4013 0 : case ocStDevPA : ScStDevP( true ); break;
4014 0 : case ocBW : ScBW(); break;
4015 0 : case ocDIA : ScDIA(); break;
4016 0 : case ocGDA : ScGDA(); break;
4017 0 : case ocGDA2 : ScGDA2(); break;
4018 0 : case ocVBD : ScVDB(); break;
4019 0 : case ocLaufz : ScLaufz(); break;
4020 0 : case ocLIA : ScLIA(); break;
4021 0 : case ocRMZ : ScRMZ(); break;
4022 0 : case ocColumns : ScColumns(); break;
4023 0 : case ocRows : ScRows(); break;
4024 3 : case ocTables : ScTables(); break;
4025 10 : case ocColumn : ScColumn(); break;
4026 5 : case ocRow : ScRow(); break;
4027 0 : case ocTable : ScTable(); break;
4028 0 : case ocZGZ : ScZGZ(); break;
4029 0 : case ocZW : ScZW(); break;
4030 0 : case ocZZR : ScZZR(); break;
4031 0 : case ocZins : ScZins(); break;
4032 0 : case ocZinsZ : ScZinsZ(); break;
4033 0 : case ocKapz : ScKapz(); break;
4034 0 : case ocKumZinsZ : ScKumZinsZ(); break;
4035 0 : case ocKumKapZ : ScKumKapZ(); break;
4036 0 : case ocEffektiv : ScEffektiv(); break;
4037 0 : case ocNominal : ScNominal(); break;
4038 0 : case ocSubTotal : ScSubTotal(); break;
4039 0 : case ocDBSum : ScDBSum(); break;
4040 8 : case ocDBCount : ScDBCount(); break;
4041 0 : case ocDBCount2 : ScDBCount2(); break;
4042 0 : case ocDBAverage : ScDBAverage(); break;
4043 0 : case ocDBGet : ScDBGet(); break;
4044 0 : case ocDBMax : ScDBMax(); break;
4045 0 : case ocDBMin : ScDBMin(); break;
4046 0 : case ocDBProduct : ScDBProduct(); break;
4047 0 : case ocDBStdDev : ScDBStdDev(); break;
4048 0 : case ocDBStdDevP : ScDBStdDevP(); break;
4049 0 : case ocDBVar : ScDBVar(); break;
4050 0 : case ocDBVarP : ScDBVarP(); break;
4051 34 : case ocIndirect : ScIndirect(); break;
4052 4 : case ocAddress : ScAddressFunc(); break;
4053 35 : case ocMatch : ScMatch(); break;
4054 1 : case ocCountEmptyCells : ScCountEmptyCells(); break;
4055 23 : case ocCountIf : ScCountIf(); break;
4056 3 : case ocSumIf : ScSumIf(); break;
4057 1 : case ocAverageIf : ScAverageIf(); break;
4058 0 : case ocSumIfs : ScSumIfs(); break;
4059 0 : case ocAverageIfs : ScAverageIfs(); break;
4060 0 : case ocCountIfs : ScCountIfs(); break;
4061 0 : case ocLookup : ScLookup(); break;
4062 17 : case ocVLookup : ScVLookup(); break;
4063 0 : case ocHLookup : ScHLookup(); break;
4064 0 : case ocIndex : ScIndex(); break;
4065 0 : case ocMultiArea : ScMultiArea(); break;
4066 0 : case ocOffset : ScOffset(); break;
4067 0 : case ocAreas : ScAreas(); break;
4068 0 : case ocCurrency : ScCurrency(); break;
4069 0 : case ocReplace : ScReplace(); break;
4070 0 : case ocFixed : ScFixed(); break;
4071 0 : case ocFind : ScFind(); break;
4072 0 : case ocExact : ScExact(); break;
4073 0 : case ocLeft : ScLeft(); break;
4074 0 : case ocRight : ScRight(); break;
4075 0 : case ocSearch : ScSearch(); break;
4076 0 : case ocMid : ScMid(); break;
4077 0 : case ocText : ScText(); break;
4078 0 : case ocSubstitute : ScSubstitute(); break;
4079 0 : case ocRept : ScRept(); break;
4080 0 : case ocConcat : ScConcat(); break;
4081 0 : case ocMatValue : ScMatValue(); break;
4082 0 : case ocMatrixUnit : ScEMat(); break;
4083 0 : case ocMatDet : ScMatDet(); break;
4084 0 : case ocMatInv : ScMatInv(); break;
4085 0 : case ocMatMult : ScMatMult(); break;
4086 0 : case ocMatTrans : ScMatTrans(); break;
4087 42 : case ocMatRef : ScMatRef(); break;
4088 0 : case ocBackSolver : ScBackSolver(); break;
4089 0 : case ocB : ScB(); break;
4090 0 : case ocNormDist : ScNormDist(); break;
4091 0 : case ocExpDist : ScExpDist(); break;
4092 0 : case ocBinomDist : ScBinomDist(); break;
4093 0 : case ocPoissonDist : ScPoissonDist(); break;
4094 0 : case ocKombin : ScKombin(); break;
4095 0 : case ocKombin2 : ScKombin2(); break;
4096 0 : case ocVariationen : ScVariationen(); break;
4097 0 : case ocVariationen2 : ScVariationen2(); break;
4098 0 : case ocHypGeomDist : ScHypGeomDist(); break;
4099 0 : case ocLogNormDist : ScLogNormDist(); break;
4100 0 : case ocTDist : ScTDist(); break;
4101 0 : case ocFDist : ScFDist(); break;
4102 0 : case ocChiDist : ScChiDist(); break;
4103 0 : case ocChiSqDist : ScChiSqDist(); break;
4104 0 : case ocStandard : ScStandard(); break;
4105 0 : case ocAveDev : ScAveDev(); break;
4106 0 : case ocDevSq : ScDevSq(); break;
4107 0 : case ocKurt : ScKurt(); break;
4108 0 : case ocSchiefe : ScSkew(); break;
4109 0 : case ocModalValue : ScModalValue(); break;
4110 0 : case ocMedian : ScMedian(); break;
4111 0 : case ocGeoMean : ScGeoMean(); break;
4112 0 : case ocHarMean : ScHarMean(); break;
4113 0 : case ocWeibull : ScWeibull(); break;
4114 0 : case ocKritBinom : ScCritBinom(); break;
4115 0 : case ocNegBinomVert : ScNegBinomDist(); break;
4116 0 : case ocNoName : ScNoName(); break;
4117 4 : case ocBad : ScBadName(); break;
4118 0 : case ocZTest : ScZTest(); break;
4119 0 : case ocTTest : ScTTest(); break;
4120 0 : case ocFTest : ScFTest(); break;
4121 0 : case ocRank : ScRank(); break;
4122 0 : case ocPercentile : ScPercentile(); break;
4123 0 : case ocPercentrank : ScPercentrank(); break;
4124 0 : case ocLarge : ScLarge(); break;
4125 0 : case ocSmall : ScSmall(); break;
4126 2 : case ocFrequency : ScFrequency(); break;
4127 0 : case ocQuartile : ScQuartile(); break;
4128 0 : case ocNormInv : ScNormInv(); break;
4129 0 : case ocSNormInv : ScSNormInv(); break;
4130 0 : case ocConfidence : ScConfidence(); break;
4131 0 : case ocTrimMean : ScTrimMean(); break;
4132 0 : case ocProb : ScProbability(); break;
4133 0 : case ocCorrel : ScCorrel(); break;
4134 0 : case ocCovar : ScCovar(); break;
4135 0 : case ocPearson : ScPearson(); break;
4136 0 : case ocRSQ : ScRSQ(); break;
4137 0 : case ocSTEYX : ScSTEXY(); break;
4138 0 : case ocSlope : ScSlope(); break;
4139 0 : case ocIntercept : ScIntercept(); break;
4140 0 : case ocTrend : ScTrend(); break;
4141 0 : case ocGrowth : ScGrowth(); break;
4142 0 : case ocRGP : ScRGP(); break;
4143 0 : case ocRKP : ScRKP(); break;
4144 0 : case ocForecast : ScForecast(); break;
4145 0 : case ocGammaLn : ScLogGamma(); break;
4146 0 : case ocGamma : ScGamma(); break;
4147 0 : case ocGammaDist : ScGammaDist(); break;
4148 0 : case ocGammaInv : ScGammaInv(); break;
4149 0 : case ocChiTest : ScChiTest(); break;
4150 0 : case ocChiInv : ScChiInv(); break;
4151 0 : case ocChiSqInv : ScChiSqInv(); break;
4152 0 : case ocTInv : ScTInv(); break;
4153 0 : case ocFInv : ScFInv(); break;
4154 0 : case ocLogInv : ScLogNormInv(); break;
4155 0 : case ocBetaDist : ScBetaDist(); break;
4156 0 : case ocBetaInv : ScBetaInv(); break;
4157 0 : case ocExternal : ScExternal(); break;
4158 0 : case ocTableOp : ScTableOp(); break;
4159 0 : case ocStop : break;
4160 0 : case ocErrorType : ScErrorType(); break;
4161 1 : case ocCurrent : ScCurrent(); break;
4162 0 : case ocStyle : ScStyle(); break;
4163 0 : case ocDde : ScDde(); break;
4164 0 : case ocBase : ScBase(); break;
4165 0 : case ocDecimal : ScDecimal(); break;
4166 0 : case ocConvert : ScConvert(); break;
4167 0 : case ocEuroConvert : ScEuroConvert(); break;
4168 0 : case ocRoman : ScRoman(); break;
4169 0 : case ocArabic : ScArabic(); break;
4170 0 : case ocInfo : ScInfo(); break;
4171 0 : case ocHyperLink : ScHyperLink(); break;
4172 0 : case ocBahtText : ScBahtText(); break;
4173 0 : case ocGetPivotData : ScGetPivotData(); break;
4174 0 : case ocJis : ScJis(); break;
4175 0 : case ocAsc : ScAsc(); break;
4176 0 : case ocUnicode : ScUnicode(); break;
4177 0 : case ocUnichar : ScUnichar(); break;
4178 3 : case ocBitAnd : ScBitAnd(); break;
4179 2 : case ocBitOr : ScBitOr(); break;
4180 2 : case ocBitXor : ScBitXor(); break;
4181 2 : case ocBitRshift : ScBitRshift(); break;
4182 2 : case ocBitLshift : ScBitLshift(); break;
4183 0 : case ocTTT : ScTTT(); break;
4184 0 : case ocNone : nFuncFmtType = NUMBERFORMAT_UNDEFINED; break;
4185 0 : default : PushError( errUnknownOpCode); break;
4186 : }
4187 :
4188 : // If the function pushed a subroutine as result, continue with
4189 : // execution of the subroutine.
4190 5836 : if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall
4191 : /* && pStack[sp-1]->GetType() == svSubroutine */)
4192 : {
4193 0 : Pop(); continue;
4194 : }
4195 :
4196 5836 : if (FormulaCompiler::IsOpCodeVolatile(eOp))
4197 43 : meVolatileType = VOLATILE;
4198 :
4199 : // Remember result matrix in case it could be reused.
4200 5836 : if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
4201 : pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
4202 12 : pStack[sp-1]));
4203 :
4204 : // outer function determines format of an expression
4205 5836 : if ( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
4206 : {
4207 5794 : nRetTypeExpr = nFuncFmtType;
4208 : // inherit the format index only for currency formats
4209 : nRetIndexExpr = ( nFuncFmtType == NUMBERFORMAT_CURRENCY ?
4210 5794 : nFuncFmtIndex : 0 );
4211 : }
4212 : }
4213 :
4214 : // Need a clean stack environment for the JumpMatrix to work.
4215 13838 : if (nGlobalError && eOp != ocPush && sp > nStackBase + 1)
4216 : {
4217 : // Not all functions pop all parameters in case an error is
4218 : // generated. Clean up stack. Assumes that every function pushes a
4219 : // result, may be arbitrary in case of error.
4220 1 : const FormulaToken* pLocalResult = pStack[ sp - 1 ];
4221 5 : while (sp > nStackBase)
4222 3 : Pop();
4223 1 : PushTempToken( *pLocalResult );
4224 : }
4225 :
4226 : bool bGotResult;
4227 13838 : do
4228 : {
4229 13838 : bGotResult = false;
4230 13838 : sal_uInt8 nLevel = 0;
4231 13838 : if ( GetStackType( ++nLevel ) == svJumpMatrix )
4232 : ; // nothing
4233 13838 : else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4234 : ; // nothing
4235 : else
4236 13838 : nLevel = 0;
4237 13838 : if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
4238 0 : bGotResult = JumpMatrix( nLevel );
4239 : else
4240 13838 : pJumpMatrix = NULL;
4241 : } while ( bGotResult );
4242 :
4243 :
4244 : // Functions that evaluate an error code and directly set nGlobalError to 0,
4245 : // usage: switch( OpCode ) { CASE_OCERRFUNC statements; }
4246 : #define CASE_OCERRFUNC \
4247 : case ocCount : \
4248 : case ocCount2 : \
4249 : case ocErrorType : \
4250 : case ocIsEmpty : \
4251 : case ocIsErr : \
4252 : case ocIsError : \
4253 : case ocIsFormula : \
4254 : case ocIsLogical : \
4255 : case ocIsNA : \
4256 : case ocIsNonString : \
4257 : case ocIsRef : \
4258 : case ocIsString : \
4259 : case ocIsValue : \
4260 : case ocN : \
4261 : case ocType :
4262 :
4263 13838 : switch ( eOp )
4264 : {
4265 : CASE_OCERRFUNC
4266 105 : ++ nErrorFunction;
4267 : default:
4268 : ; // nothing
4269 : }
4270 13838 : if ( nGlobalError )
4271 : {
4272 71 : if ( !nErrorFunctionCount )
4273 : { // count of errorcode functions in formula
4274 295 : for ( FormulaToken* t = rArr.FirstRPN(); t; t = rArr.NextRPN() )
4275 : {
4276 224 : switch ( t->GetOpCode() )
4277 : {
4278 : CASE_OCERRFUNC
4279 9 : ++nErrorFunctionCount;
4280 : default:
4281 : ; // nothing
4282 : }
4283 : }
4284 : }
4285 71 : if ( nErrorFunction >= nErrorFunctionCount )
4286 62 : ++nErrorFunction; // that's it, error => terminate
4287 : }
4288 : }
4289 :
4290 : // End: obtain result
4291 :
4292 3010 : if( sp )
4293 : {
4294 3010 : pCur = pStack[ sp-1 ];
4295 3010 : if( pCur->GetOpCode() == ocPush )
4296 : {
4297 3010 : switch( pCur->GetType() )
4298 : {
4299 : case svEmptyCell:
4300 : ; // nothing
4301 1 : break;
4302 : case svError:
4303 62 : nGlobalError = pCur->GetError();
4304 62 : break;
4305 : case svDouble :
4306 2762 : if ( nFuncFmtType == NUMBERFORMAT_UNDEFINED )
4307 : {
4308 6 : nRetTypeExpr = NUMBERFORMAT_NUMBER;
4309 6 : nRetIndexExpr = 0;
4310 : }
4311 2762 : break;
4312 : case svString :
4313 31 : nRetTypeExpr = NUMBERFORMAT_TEXT;
4314 31 : nRetIndexExpr = 0;
4315 31 : break;
4316 : case svSingleRef :
4317 : {
4318 122 : ScAddress aAdr;
4319 122 : PopSingleRef( aAdr );
4320 122 : if( !nGlobalError )
4321 : PushCellResultToken( false, aAdr,
4322 122 : &nRetTypeExpr, &nRetIndexExpr);
4323 : }
4324 122 : break;
4325 : case svRefList :
4326 0 : PopError(); // maybe #REF! takes precedence over #VALUE!
4327 0 : PushError( errNoValue);
4328 0 : break;
4329 : case svDoubleRef :
4330 : {
4331 2 : if ( bMatrixFormula )
4332 : { // create matrix for {=A1:A5}
4333 2 : PopDoubleRefPushMatrix();
4334 2 : ScMatrixRef xMat = PopMatrix();
4335 2 : QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4336 : }
4337 : else
4338 : {
4339 0 : ScRange aRange;
4340 0 : PopDoubleRef( aRange );
4341 0 : ScAddress aAdr;
4342 0 : if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr))
4343 : PushCellResultToken( false, aAdr,
4344 0 : &nRetTypeExpr, &nRetIndexExpr);
4345 : }
4346 : }
4347 2 : break;
4348 : case svExternalDoubleRef:
4349 : case svMatrix :
4350 : {
4351 10 : ScMatrixRef xMat;
4352 10 : if (pCur->GetType() == svMatrix)
4353 10 : xMat = PopMatrix();
4354 : else
4355 0 : PopExternalDoubleRef(xMat);
4356 :
4357 10 : QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4358 : }
4359 10 : break;
4360 : case svExternalSingleRef:
4361 : {
4362 20 : ScExternalRefCache::TokenRef pToken;
4363 20 : ScExternalRefCache::CellFormat aFmt;
4364 20 : PopExternalSingleRef(pToken, &aFmt);
4365 20 : if (nGlobalError)
4366 : break;
4367 :
4368 20 : PushTempToken(*pToken);
4369 :
4370 20 : if (aFmt.mbIsSet)
4371 : {
4372 20 : nFuncFmtType = aFmt.mnType;
4373 20 : nFuncFmtIndex = aFmt.mnIndex;
4374 20 : }
4375 : }
4376 20 : break;
4377 : default :
4378 0 : SetError( errUnknownStackVariable);
4379 : }
4380 : }
4381 : else
4382 0 : SetError( errUnknownStackVariable);
4383 : }
4384 : else
4385 0 : SetError( errNoCode);
4386 :
4387 3010 : if( nRetTypeExpr != NUMBERFORMAT_UNDEFINED )
4388 : {
4389 2990 : nRetFmtType = nRetTypeExpr;
4390 2990 : nRetFmtIndex = nRetIndexExpr;
4391 : }
4392 20 : else if( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
4393 : {
4394 20 : nRetFmtType = nFuncFmtType;
4395 20 : nRetFmtIndex = nFuncFmtIndex;
4396 : }
4397 : else
4398 0 : nRetFmtType = NUMBERFORMAT_NUMBER;
4399 : // inherit the format index only for currency formats
4400 3010 : if ( nRetFmtType != NUMBERFORMAT_CURRENCY )
4401 3010 : nRetFmtIndex = 0;
4402 :
4403 3010 : if (nGlobalError && GetStackType() != svError )
4404 0 : PushError( nGlobalError);
4405 :
4406 : // THE final result.
4407 3010 : xResult = PopToken();
4408 3010 : if (!xResult)
4409 0 : xResult = new FormulaErrorToken( errUnknownStackVariable);
4410 :
4411 : // release tokens in expression stack
4412 3010 : FormulaToken** p = pStack;
4413 11934 : while( maxsp-- )
4414 5914 : (*p++)->DecRef();
4415 :
4416 3010 : StackVar eType = xResult->GetType();
4417 3010 : if (eType == svMatrix)
4418 : // Results are immutable in case they would be reused as input for new
4419 : // interpreters.
4420 0 : static_cast<ScToken*>(xResult.get())->GetMatrix()->SetImmutable( true);
4421 3010 : return eType;
4422 : }
4423 :
4424 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|