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