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