Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / core / tool / interpr4.cxx
blobc5ebbd3009c2c7af7841f388421ee1f8cc8c64dc
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "interpre.hxx"
22 #include <rangelst.hxx>
23 #include <sfx2/app.hxx>
24 #include <sfx2/docfile.hxx>
25 #include <sfx2/objsh.hxx>
26 #include <sfx2/docfilt.hxx>
27 #include <basic/sbmeth.hxx>
28 #include <basic/sbmod.hxx>
29 #include <basic/sbstar.hxx>
30 #include <basic/sbx.hxx>
31 #include <basic/sbxobj.hxx>
32 #include <basic/sbuno.hxx>
33 #include <svl/zforlist.hxx>
34 #include "svl/sharedstringpool.hxx"
35 #include <stdlib.h>
36 #include <string.h>
37 #include <signal.h>
39 #include <com/sun/star/table/XCellRange.hpp>
40 #include <com/sun/star/sheet/XSheetCellRange.hpp>
41 #include <comphelper/processfactory.hxx>
43 #include "global.hxx"
44 #include "dbdata.hxx"
45 #include "formulacell.hxx"
46 #include "callform.hxx"
47 #include "addincol.hxx"
48 #include "document.hxx"
49 #include "dociter.hxx"
50 #include "docoptio.hxx"
51 #include "scmatrix.hxx"
52 #include "adiasync.hxx"
53 #include "sc.hrc"
54 #include "cellsuno.hxx"
55 #include "optuno.hxx"
56 #include "rangeseq.hxx"
57 #include "addinlis.hxx"
58 #include "jumpmatrix.hxx"
59 #include "parclass.hxx"
60 #include "externalrefmgr.hxx"
61 #include "formula/FormulaCompiler.hxx"
62 #include "macromgr.hxx"
63 #include "doubleref.hxx"
64 #include "queryparam.hxx"
65 #include "tokenarray.hxx"
67 #include <math.h>
68 #include <float.h>
69 #include <map>
70 #include <algorithm>
71 #include <functional>
72 #include <basic/basmgr.hxx>
73 #include <vbahelper/vbaaccesshelper.hxx>
74 #include <memory>
76 using namespace com::sun::star;
77 using namespace formula;
78 using ::std::auto_ptr;
80 #define ADDIN_MAXSTRLEN 256
82 //-----------------------------static data -----------------
84 //-------------------------------------------------------------------------
85 // Funktionen fuer den Zugriff auf das Document
86 //-------------------------------------------------------------------------
89 void ScInterpreter::ReplaceCell( ScAddress& rPos )
91 size_t ListSize = pDok->aTableOpList.size();
92 for ( size_t i = 0; i < ListSize; ++i )
94 ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
95 if ( rPos == pTOp->aOld1 )
97 rPos = pTOp->aNew1;
98 return ;
100 else if ( rPos == pTOp->aOld2 )
102 rPos = pTOp->aNew2;
103 return ;
109 void ScInterpreter::ReplaceCell( SCCOL& rCol, SCROW& rRow, SCTAB& rTab )
111 ScAddress aCellPos( rCol, rRow, rTab );
112 size_t ListSize = pDok->aTableOpList.size();
113 for ( size_t i = 0; i < ListSize; ++i )
115 ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
116 if ( aCellPos == pTOp->aOld1 )
118 rCol = pTOp->aNew1.Col();
119 rRow = pTOp->aNew1.Row();
120 rTab = pTOp->aNew1.Tab();
121 return ;
123 else if ( aCellPos == pTOp->aOld2 )
125 rCol = pTOp->aNew2.Col();
126 rRow = pTOp->aNew2.Row();
127 rTab = pTOp->aNew2.Tab();
128 return ;
134 bool ScInterpreter::IsTableOpInRange( const ScRange& rRange )
136 if ( rRange.aStart == rRange.aEnd )
137 return false; // not considered to be a range in TableOp sense
139 // we can't replace a single cell in a range
140 size_t ListSize = pDok->aTableOpList.size();
141 for ( size_t i = 0; i < ListSize; ++i )
143 ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
144 if ( rRange.In( pTOp->aOld1 ) )
145 return true;
146 if ( rRange.In( pTOp->aOld2 ) )
147 return true;
149 return false;
153 sal_uLong ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, ScRefCellValue& rCell )
155 sal_uLong nFormat;
156 sal_uInt16 nErr;
157 if (rCell.isEmpty())
159 nFormat = pDok->GetNumberFormat( rPos );
160 nErr = 0;
162 else
164 if (rCell.meType == CELLTYPE_FORMULA)
165 nErr = rCell.mpFormula->GetErrCode();
166 else
167 nErr = 0;
168 nFormat = pDok->GetNumberFormat( rPos );
171 SetError(nErr);
172 return nFormat;
176 /// Only ValueCell, formula cells already store the result rounded.
177 double ScInterpreter::GetValueCellValue( const ScAddress& rPos, double fOrig )
179 if ( bCalcAsShown && fOrig != 0.0 )
181 sal_uLong nFormat = pDok->GetNumberFormat( rPos );
182 fOrig = pDok->RoundValueAsShown( fOrig, nFormat );
184 return fOrig;
187 sal_uInt16 ScInterpreter::GetCellErrCode( const ScRefCellValue& rCell )
189 return rCell.meType == CELLTYPE_FORMULA ? rCell.mpFormula->GetErrCode() : 0;
192 /** Convert string content to numeric value.
194 Converted are only integer numbers including exponent, and ISO 8601 dates
195 and times in their extended formats with separators. Anything else,
196 especially fractional numeric values with decimal separators or dates other
197 than ISO 8601 would be locale dependent and is a no-no. Leading and
198 trailing blanks are ignored.
200 The following ISO 8601 formats are converted:
202 CCYY-MM-DD
203 CCYY-MM-DDThh:mm
204 CCYY-MM-DDThh:mm:ss
205 CCYY-MM-DDThh:mm:ss,s
206 CCYY-MM-DDThh:mm:ss.s
207 hh:mm
208 hh:mm:ss
209 hh:mm:ss,s
210 hh:mm:ss.s
212 The century CC may not be omitted and the two-digit year setting is not
213 taken into account. Instead of the T date and time separator exactly one
214 blank may be used.
216 If a date is given, it must be a valid Gregorian calendar date. In this
217 case the optional time must be in the range 00:00 to 23:59:59.99999...
218 If only time is given, it may have any value for hours, taking elapsed time
219 into account; minutes and seconds are limited to the value 59 as well.
222 double ScInterpreter::ConvertStringToValue( const OUString& rStr )
224 #if 1
225 // We keep this code until we provide a friendly way to convert string
226 // numbers into numbers in the UI.
227 double fValue = 0.0;
228 if (mnStringNoValueError == errCellNoValue)
230 // Requested that all strings result in 0, error handled by caller.
231 SetError( mnStringNoValueError);
232 return fValue;
235 if (GetGlobalConfig().mbEmptyStringAsZero)
237 // The number scanner does not accept empty strings or strings
238 // containing only spaces, be on par in these cases with what was
239 // accepted in OOo and is in AOO (see also the else branch below) and
240 // convert to 0 to prevent interoperability nightmares.
241 if (rStr.isEmpty())
242 return fValue;
243 else if (rStr[0] == ' ')
245 const sal_Unicode* p = rStr.getStr() + 1;
246 const sal_Unicode* const pStop = p - 1 + rStr.getLength();
247 while (p < pStop && *p == ' ')
248 ++p;
249 if (p == pStop)
250 return fValue;
254 sal_uInt32 nFIndex = 0;
255 if (!pFormatter->IsNumberFormat(rStr, nFIndex, fValue))
257 SetError( mnStringNoValueError);
258 fValue = 0.0;
260 return fValue;
261 #else
262 double fValue = 0.0;
263 if (mnStringNoValueError == errCellNoValue)
265 // Requested that all strings result in 0, error handled by caller.
266 SetError( mnStringNoValueError);
267 return fValue;
269 OUString aStr( rStr);
270 rtl_math_ConversionStatus eStatus;
271 sal_Int32 nParseEnd;
272 // Decimal and group separator 0 => only integer and possibly exponent,
273 // stops at first non-digit non-sign.
274 fValue = ::rtl::math::stringToDouble( aStr, 0, 0, &eStatus, &nParseEnd);
275 sal_Int32 nLen;
276 if (eStatus == rtl_math_ConversionStatus_Ok && nParseEnd < (nLen = aStr.getLength()))
278 // Not at string end, check for trailing blanks or switch to date or
279 // time parsing or bail out.
280 const sal_Unicode* const pStart = aStr.getStr();
281 const sal_Unicode* p = pStart + nParseEnd;
282 const sal_Unicode* const pStop = pStart + nLen;
283 switch (*p++)
285 case ' ':
286 while (p < pStop && *p == ' ')
287 ++p;
288 if (p < pStop)
289 SetError( mnStringNoValueError);
290 break;
291 case '-':
292 case ':':
294 bool bDate = (*(p-1) == '-');
295 enum State { year = 0, month, day, hour, minute, second, fraction, done, blank, stop };
296 sal_Int32 nUnit[done] = {0,0,0,0,0,0,0};
297 const sal_Int32 nLimit[done] = {0,12,31,0,59,59,0};
298 State eState = (bDate ? month : minute);
299 nCurFmtType = (bDate ? NUMBERFORMAT_DATE : NUMBERFORMAT_TIME);
300 nUnit[eState-1] = aStr.copy( 0, nParseEnd).toInt32();
301 const sal_Unicode* pLastStart = p;
302 // Ensure there's no preceding sign. Negative dates
303 // currently aren't handled correctly. Also discard
304 // +CCYY-MM-DD
305 p = pStart;
306 while (p < pStop && *p == ' ')
307 ++p;
308 if (p < pStop && !CharClass::isAsciiDigit(*p))
309 SetError( mnStringNoValueError);
310 p = pLastStart;
311 while (p < pStop && !nGlobalError && eState < blank)
313 if (eState == minute)
314 nCurFmtType |= NUMBERFORMAT_TIME;
315 if (CharClass::isAsciiDigit(*p))
317 // Maximum 2 digits per unit, except fractions.
318 if (p - pLastStart >= 2 && eState != fraction)
319 SetError( mnStringNoValueError);
321 else if (p > pLastStart)
323 // We had at least one digit.
324 if (eState < done)
326 nUnit[eState] = aStr.copy( pLastStart - pStart, p - pLastStart).toInt32();
327 if (nLimit[eState] && nLimit[eState] < nUnit[eState])
328 SetError( mnStringNoValueError);
330 pLastStart = p + 1; // hypothetical next start
331 // Delimiters must match, a trailing delimiter
332 // yields an invalid date/time.
333 switch (eState)
335 case month:
336 // Month must be followed by separator and
337 // day, no trailing blanks.
338 if (*p != '-' || (p+1 == pStop))
339 SetError( mnStringNoValueError);
340 break;
341 case day:
342 if ((*p != 'T' || (p+1 == pStop)) && *p != ' ')
343 SetError( mnStringNoValueError);
344 // Take one blank as a valid delimiter
345 // between date and time.
346 break;
347 case hour:
348 // Hour must be followed by separator and
349 // minute, no trailing blanks.
350 if (*p != ':' || (p+1 == pStop))
351 SetError( mnStringNoValueError);
352 break;
353 case minute:
354 if ((*p != ':' || (p+1 == pStop)) && *p != ' ')
355 SetError( mnStringNoValueError);
356 if (*p == ' ')
357 eState = done;
358 break;
359 case second:
360 if (((*p != ',' && *p != '.') || (p+1 == pStop)) && *p != ' ')
361 SetError( mnStringNoValueError);
362 if (*p == ' ')
363 eState = done;
364 break;
365 case fraction:
366 eState = done;
367 break;
368 case year:
369 case done:
370 case blank:
371 case stop:
372 SetError( mnStringNoValueError);
373 break;
375 eState = static_cast<State>(eState + 1);
377 else
378 SetError( mnStringNoValueError);
379 ++p;
381 if (eState == blank)
383 while (p < pStop && *p == ' ')
384 ++p;
385 if (p < pStop)
386 SetError( mnStringNoValueError);
387 eState = stop;
390 // Month without day, or hour without minute.
391 if (eState == month || (eState == day && p <= pLastStart) ||
392 eState == hour || (eState == minute && p <= pLastStart))
393 SetError( mnStringNoValueError);
395 if (!nGlobalError)
397 // Catch the very last unit at end of string.
398 if (p > pLastStart && eState < done)
400 nUnit[eState] = aStr.copy( pLastStart - pStart, p - pLastStart).toInt32();
401 if (nLimit[eState] && nLimit[eState] < nUnit[eState])
402 SetError( mnStringNoValueError);
404 if (bDate && nUnit[hour] > 23)
405 SetError( mnStringNoValueError);
406 if (!nGlobalError)
408 if (bDate && nUnit[day] == 0)
409 nUnit[day] = 1;
410 double fFraction = (nUnit[fraction] <= 0 ? 0.0 :
411 ::rtl::math::pow10Exp( nUnit[fraction],
412 static_cast<int>( -ceil( log10( static_cast<double>( nUnit[fraction]))))));
413 fValue = (bDate ? GetDateSerial(
414 sal::static_int_cast<sal_Int16>(nUnit[year]),
415 sal::static_int_cast<sal_Int16>(nUnit[month]),
416 sal::static_int_cast<sal_Int16>(nUnit[day]),
417 true, false) : 0.0);
418 fValue += ((nUnit[hour] * 3600) + (nUnit[minute] * 60) + nUnit[second] + fFraction) / 86400.0;
422 break;
423 default:
424 SetError( mnStringNoValueError);
426 if (nGlobalError)
427 fValue = 0.0;
429 return fValue;
430 #endif
433 double ScInterpreter::GetCellValue( const ScAddress& rPos, ScRefCellValue& rCell )
435 sal_uInt16 nErr = nGlobalError;
436 nGlobalError = 0;
437 double nVal = GetCellValueOrZero(rPos, rCell);
438 if ( !nGlobalError || nGlobalError == errCellNoValue )
439 nGlobalError = nErr;
440 return nVal;
443 double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, ScRefCellValue& rCell )
445 double fValue = 0.0;
447 CellType eType = rCell.meType;
448 switch (eType)
450 case CELLTYPE_FORMULA:
452 ScFormulaCell* pFCell = rCell.mpFormula;
453 sal_uInt16 nErr = pFCell->GetErrCode();
454 if( !nErr )
456 if (pFCell->IsValue())
458 fValue = pFCell->GetValue();
459 pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex,
460 rPos );
462 else
464 fValue = ConvertStringToValue(pFCell->GetString().getString());
467 else
469 fValue = 0.0;
470 SetError(nErr);
473 break;
474 case CELLTYPE_VALUE:
476 fValue = rCell.mfValue;
477 nCurFmtIndex = pDok->GetNumberFormat( rPos );
478 nCurFmtType = pFormatter->GetType( nCurFmtIndex );
479 if ( bCalcAsShown && fValue != 0.0 )
480 fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex );
482 break;
483 case CELLTYPE_STRING:
484 case CELLTYPE_EDIT:
486 // SUM(A1:A2) differs from A1+A2. No good. But people insist on
487 // it ... #i5658#
488 OUString aStr = rCell.getString(pDok);
489 fValue = ConvertStringToValue( aStr );
491 break;
492 case CELLTYPE_NONE:
493 fValue = 0.0; // empty or broadcaster cell
494 break;
497 return fValue;
500 void ScInterpreter::GetCellString( svl::SharedString& rStr, ScRefCellValue& rCell )
502 sal_uInt16 nErr = 0;
504 switch (rCell.meType)
506 case CELLTYPE_STRING:
507 case CELLTYPE_EDIT:
508 rStr = mrStrPool.intern(rCell.getString(pDok));
509 break;
510 case CELLTYPE_FORMULA:
512 ScFormulaCell* pFCell = rCell.mpFormula;
513 nErr = pFCell->GetErrCode();
514 if (pFCell->IsValue())
516 double fVal = pFCell->GetValue();
517 sal_uLong nIndex = pFormatter->GetStandardFormat(
518 NUMBERFORMAT_NUMBER,
519 ScGlobal::eLnge);
520 OUString aStr;
521 pFormatter->GetInputLineString(fVal, nIndex, aStr);
522 rStr = mrStrPool.intern(aStr);
524 else
525 rStr = pFCell->GetString();
527 break;
528 case CELLTYPE_VALUE:
530 double fVal = rCell.mfValue;
531 sal_uLong nIndex = pFormatter->GetStandardFormat(
532 NUMBERFORMAT_NUMBER,
533 ScGlobal::eLnge);
534 OUString aStr;
535 pFormatter->GetInputLineString(fVal, nIndex, aStr);
536 rStr = mrStrPool.intern(aStr);
538 break;
539 default:
540 rStr = svl::SharedString::getEmptyString();
541 break;
544 SetError(nErr);
547 bool ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
548 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr)
551 // Old Add-Ins are hard limited to sal_uInt16 values.
552 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
553 #error Add check for columns > USHRT_MAX!
554 #endif
555 if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
556 return false;
558 sal_uInt16 nCount = 0;
559 sal_uInt16* p = (sal_uInt16*) pCellArr;
560 *p++ = static_cast<sal_uInt16>(nCol1);
561 *p++ = static_cast<sal_uInt16>(nRow1);
562 *p++ = static_cast<sal_uInt16>(nTab1);
563 *p++ = static_cast<sal_uInt16>(nCol2);
564 *p++ = static_cast<sal_uInt16>(nRow2);
565 *p++ = static_cast<sal_uInt16>(nTab2);
566 sal_uInt16* pCount = p;
567 *p++ = 0;
568 sal_uInt16 nPos = 14;
569 SCTAB nTab = nTab1;
570 ScAddress aAdr;
571 while (nTab <= nTab2)
573 aAdr.SetTab( nTab );
574 SCROW nRow = nRow1;
575 while (nRow <= nRow2)
577 aAdr.SetRow( nRow );
578 SCCOL nCol = nCol1;
579 while (nCol <= nCol2)
581 aAdr.SetCol( nCol );
583 ScRefCellValue aCell;
584 aCell.assign(*pDok, aAdr);
585 if (!aCell.isEmpty())
587 sal_uInt16 nErr = 0;
588 double nVal = 0.0;
589 bool bOk = true;
590 switch (aCell.meType)
592 case CELLTYPE_VALUE :
593 nVal = GetValueCellValue(aAdr, aCell.mfValue);
594 break;
595 case CELLTYPE_FORMULA :
596 if (aCell.mpFormula->IsValue())
598 nErr = aCell.mpFormula->GetErrCode();
599 nVal = aCell.mpFormula->GetValue();
601 else
602 bOk = false;
603 break;
604 default :
605 bOk = false;
606 break;
608 if (bOk)
610 if ((nPos + (4 * sizeof(sal_uInt16)) + sizeof(double)) > MAXARRSIZE)
611 return false;
612 *p++ = static_cast<sal_uInt16>(nCol);
613 *p++ = static_cast<sal_uInt16>(nRow);
614 *p++ = static_cast<sal_uInt16>(nTab);
615 *p++ = nErr;
616 memcpy( p, &nVal, sizeof(double));
617 nPos += 8 + sizeof(double);
618 p = (sal_uInt16*) ( pCellArr + nPos );
619 nCount++;
622 nCol++;
624 nRow++;
626 nTab++;
628 *pCount = nCount;
629 return true;
633 bool ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
634 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
635 sal_uInt8* pCellArr)
638 // Old Add-Ins are hard limited to sal_uInt16 values.
639 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
640 #error Add check for columns > USHRT_MAX!
641 #endif
642 if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
643 return false;
645 sal_uInt16 nCount = 0;
646 sal_uInt16* p = (sal_uInt16*) pCellArr;
647 *p++ = static_cast<sal_uInt16>(nCol1);
648 *p++ = static_cast<sal_uInt16>(nRow1);
649 *p++ = static_cast<sal_uInt16>(nTab1);
650 *p++ = static_cast<sal_uInt16>(nCol2);
651 *p++ = static_cast<sal_uInt16>(nRow2);
652 *p++ = static_cast<sal_uInt16>(nTab2);
653 sal_uInt16* pCount = p;
654 *p++ = 0;
655 sal_uInt16 nPos = 14;
656 SCTAB nTab = nTab1;
657 while (nTab <= nTab2)
659 SCROW nRow = nRow1;
660 while (nRow <= nRow2)
662 SCCOL nCol = nCol1;
663 while (nCol <= nCol2)
665 ScRefCellValue aCell;
666 aCell.assign(*pDok, ScAddress(nCol, nRow, nTab));
667 if (!aCell.isEmpty())
669 OUString aStr;
670 sal_uInt16 nErr = 0;
671 bool bOk = true;
672 switch (aCell.meType)
674 case CELLTYPE_STRING:
675 case CELLTYPE_EDIT:
676 aStr = aCell.getString(pDok);
677 break;
678 case CELLTYPE_FORMULA:
679 if (!aCell.mpFormula->IsValue())
681 nErr = aCell.mpFormula->GetErrCode();
682 aStr = aCell.mpFormula->GetString().getString();
684 else
685 bOk = false;
686 break;
687 default :
688 bOk = false;
689 break;
691 if (bOk)
693 OString aTmp(OUStringToOString(aStr,
694 osl_getThreadTextEncoding()));
695 // In case the xub_StrLen will be longer than USHORT
696 // one day, and room for pad byte check.
697 if ( aTmp.getLength() > ((sal_uInt16)(~0)) - 2 )
698 return false;
699 // Append a 0-pad-byte if string length is not even
700 //! MUST be sal_uInt16 and not xub_StrLen
701 sal_uInt16 nStrLen = (sal_uInt16) aTmp.getLength();
702 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
704 if (((sal_uLong)nPos + (5 * sizeof(sal_uInt16)) + nLen) > MAXARRSIZE)
705 return false;
706 *p++ = static_cast<sal_uInt16>(nCol);
707 *p++ = static_cast<sal_uInt16>(nRow);
708 *p++ = static_cast<sal_uInt16>(nTab);
709 *p++ = nErr;
710 *p++ = nLen;
711 memcpy( p, aTmp.getStr(), nStrLen + 1);
712 nPos += 10 + nStrLen + 1;
713 sal_uInt8* q = ( pCellArr + nPos );
714 if( !nStrLen & 1 )
715 *q++ = 0, nPos++;
716 p = (sal_uInt16*) ( pCellArr + nPos );
717 nCount++;
720 nCol++;
722 nRow++;
724 nTab++;
726 *pCount = nCount;
727 return true;
731 bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
732 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
733 sal_uInt8* pCellArr)
736 // Old Add-Ins are hard limited to sal_uInt16 values.
737 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
738 #error Add check for columns > USHRT_MAX!
739 #endif
740 if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
741 return false;
743 sal_uInt16 nCount = 0;
744 sal_uInt16* p = (sal_uInt16*) pCellArr;
745 *p++ = static_cast<sal_uInt16>(nCol1);
746 *p++ = static_cast<sal_uInt16>(nRow1);
747 *p++ = static_cast<sal_uInt16>(nTab1);
748 *p++ = static_cast<sal_uInt16>(nCol2);
749 *p++ = static_cast<sal_uInt16>(nRow2);
750 *p++ = static_cast<sal_uInt16>(nTab2);
751 sal_uInt16* pCount = p;
752 *p++ = 0;
753 sal_uInt16 nPos = 14;
754 SCTAB nTab = nTab1;
755 ScAddress aAdr;
756 while (nTab <= nTab2)
758 aAdr.SetTab( nTab );
759 SCROW nRow = nRow1;
760 while (nRow <= nRow2)
762 aAdr.SetRow( nRow );
763 SCCOL nCol = nCol1;
764 while (nCol <= nCol2)
766 aAdr.SetCol( nCol );
767 ScRefCellValue aCell;
768 aCell.assign(*pDok, aAdr);
769 if (!aCell.isEmpty())
771 sal_uInt16 nErr = 0;
772 sal_uInt16 nType = 0; // 0 = Zahl; 1 = String
773 double nVal = 0.0;
774 OUString aStr;
775 bool bOk = true;
776 switch (aCell.meType)
778 case CELLTYPE_STRING :
779 case CELLTYPE_EDIT :
780 aStr = aCell.getString(pDok);
781 nType = 1;
782 break;
783 case CELLTYPE_VALUE :
784 nVal = GetValueCellValue(aAdr, aCell.mfValue);
785 break;
786 case CELLTYPE_FORMULA :
787 nErr = aCell.mpFormula->GetErrCode();
788 if (aCell.mpFormula->IsValue())
789 nVal = aCell.mpFormula->GetValue();
790 else
791 aStr = aCell.mpFormula->GetString().getString();
792 break;
793 default :
794 bOk = false;
795 break;
797 if (bOk)
799 if ((nPos + (5 * sizeof(sal_uInt16))) > MAXARRSIZE)
800 return false;
801 *p++ = static_cast<sal_uInt16>(nCol);
802 *p++ = static_cast<sal_uInt16>(nRow);
803 *p++ = static_cast<sal_uInt16>(nTab);
804 *p++ = nErr;
805 *p++ = nType;
806 nPos += 10;
807 if (nType == 0)
809 if ((nPos + sizeof(double)) > MAXARRSIZE)
810 return false;
811 memcpy( p, &nVal, sizeof(double));
812 nPos += sizeof(double);
814 else
816 OString aTmp(OUStringToOString(aStr,
817 osl_getThreadTextEncoding()));
818 // In case the xub_StrLen will be longer than USHORT
819 // one day, and room for pad byte check.
820 if ( aTmp.getLength() > ((sal_uInt16)(~0)) - 2 )
821 return false;
822 // Append a 0-pad-byte if string length is not even
823 //! MUST be sal_uInt16 and not xub_StrLen
824 sal_uInt16 nStrLen = (sal_uInt16) aTmp.getLength();
825 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
826 if ( ((sal_uLong)nPos + 2 + nLen) > MAXARRSIZE)
827 return false;
828 *p++ = nLen;
829 memcpy( p, aTmp.getStr(), nStrLen + 1);
830 nPos += 2 + nStrLen + 1;
831 sal_uInt8* q = ( pCellArr + nPos );
832 if( !nStrLen & 1 )
833 *q++ = 0, nPos++;
835 nCount++;
836 p = (sal_uInt16*) ( pCellArr + nPos );
839 nCol++;
841 nRow++;
843 nTab++;
845 *pCount = nCount;
846 return true;
850 //-----------------------------------------------------------------------------
851 // Stack operations
852 //-----------------------------------------------------------------------------
855 // Also releases a TempToken if appropriate.
857 void ScInterpreter::PushWithoutError( FormulaToken& r )
859 if ( sp >= MAXSTACK )
860 SetError( errStackOverflow );
861 else
863 nCurFmtType = NUMBERFORMAT_UNDEFINED;
864 r.IncRef();
865 if( sp >= maxsp )
866 maxsp = sp + 1;
867 else
868 pStack[ sp ]->DecRef();
869 pStack[ sp ] = (ScToken*) &r;
870 ++sp;
874 void ScInterpreter::Push( FormulaToken& r )
876 if ( sp >= MAXSTACK )
877 SetError( errStackOverflow );
878 else
880 if (nGlobalError)
882 if (r.GetType() == svError)
884 r.SetError( nGlobalError);
885 PushWithoutError( r);
887 else
888 PushWithoutError( *(new FormulaErrorToken( nGlobalError)));
890 else
891 PushWithoutError( r);
896 void ScInterpreter::PushTempToken( FormulaToken* p )
898 if ( sp >= MAXSTACK )
900 SetError( errStackOverflow );
901 if (!p->GetRef())
902 //! p is a dangling pointer hereafter!
903 p->Delete();
905 else
907 if (nGlobalError)
909 if (p->GetType() == svError)
911 p->SetError( nGlobalError);
912 PushTempTokenWithoutError( p);
914 else
916 if (!p->GetRef())
917 //! p is a dangling pointer hereafter!
918 p->Delete();
919 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
922 else
923 PushTempTokenWithoutError( p);
928 void ScInterpreter::PushTempTokenWithoutError( FormulaToken* p )
930 p->IncRef();
931 if ( sp >= MAXSTACK )
933 SetError( errStackOverflow );
934 //! p may be a dangling pointer hereafter!
935 p->DecRef();
937 else
939 if( sp >= maxsp )
940 maxsp = sp + 1;
941 else
942 pStack[ sp ]->DecRef();
943 pStack[ sp ] = p;
944 ++sp;
949 void ScInterpreter::PushTempToken( const FormulaToken& r )
951 if (!IfErrorPushError())
952 PushTempTokenWithoutError( r.Clone());
956 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
957 const ScAddress & rAddress, short * pRetTypeExpr, sal_uLong * pRetIndexExpr )
959 ScRefCellValue aCell;
960 aCell.assign(*pDok, rAddress);
961 if (aCell.hasEmptyValue())
963 bool bInherited = (aCell.meType == CELLTYPE_FORMULA);
964 if (pRetTypeExpr && pRetIndexExpr)
965 pDok->GetNumberFormatInfo(*pRetTypeExpr, *pRetIndexExpr, rAddress);
966 PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString));
967 return;
970 sal_uInt16 nErr = 0;
971 if (aCell.meType == CELLTYPE_FORMULA)
972 nErr = aCell.mpFormula->GetErrCode();
974 if (nErr)
976 PushError( nErr);
977 if (pRetTypeExpr)
978 *pRetTypeExpr = NUMBERFORMAT_UNDEFINED;
979 if (pRetIndexExpr)
980 *pRetIndexExpr = 0;
982 else if (aCell.hasString())
984 svl::SharedString aRes;
985 GetCellString( aRes, aCell);
986 PushString( aRes);
987 if (pRetTypeExpr)
988 *pRetTypeExpr = NUMBERFORMAT_TEXT;
989 if (pRetIndexExpr)
990 *pRetIndexExpr = 0;
992 else
994 double fVal = GetCellValue(rAddress, aCell);
995 PushDouble( fVal);
996 if (pRetTypeExpr)
997 *pRetTypeExpr = nCurFmtType;
998 if (pRetIndexExpr)
999 *pRetIndexExpr = nCurFmtIndex;
1004 // Simply throw away TOS.
1006 void ScInterpreter::Pop()
1008 if( sp )
1009 sp--;
1010 else
1011 SetError(errUnknownStackVariable);
1015 // Simply throw away TOS and set error code, used with ocIsError et al.
1017 void ScInterpreter::PopError()
1019 if( sp )
1021 sp--;
1022 if (pStack[sp]->GetType() == svError)
1023 nGlobalError = pStack[sp]->GetError();
1025 else
1026 SetError(errUnknownStackVariable);
1030 FormulaTokenRef ScInterpreter::PopToken()
1032 if (sp)
1034 sp--;
1035 FormulaToken* p = pStack[ sp ];
1036 if (p->GetType() == svError)
1037 nGlobalError = p->GetError();
1038 return p;
1040 else
1041 SetError(errUnknownStackVariable);
1042 return NULL;
1046 double ScInterpreter::PopDouble()
1048 nCurFmtType = NUMBERFORMAT_NUMBER;
1049 nCurFmtIndex = 0;
1050 if( sp )
1052 --sp;
1053 FormulaToken* p = pStack[ sp ];
1054 switch (p->GetType())
1056 case svError:
1057 nGlobalError = p->GetError();
1058 break;
1059 case svDouble:
1060 return p->GetDouble();
1061 case svEmptyCell:
1062 case svMissing:
1063 return 0.0;
1064 default:
1065 SetError( errIllegalArgument);
1068 else
1069 SetError( errUnknownStackVariable);
1070 return 0.0;
1074 svl::SharedString ScInterpreter::PopString()
1076 nCurFmtType = NUMBERFORMAT_TEXT;
1077 nCurFmtIndex = 0;
1078 if( sp )
1080 --sp;
1081 FormulaToken* p = pStack[ sp ];
1082 switch (p->GetType())
1084 case svError:
1085 nGlobalError = p->GetError();
1086 break;
1087 case svString:
1088 return p->GetString();
1089 case svEmptyCell:
1090 case svMissing:
1091 return svl::SharedString::getEmptyString();
1092 default:
1093 SetError( errIllegalArgument);
1096 else
1097 SetError( errUnknownStackVariable);
1099 return svl::SharedString::getEmptyString();
1103 void ScInterpreter::ValidateRef( const ScSingleRefData & rRef )
1105 SCCOL nCol;
1106 SCROW nRow;
1107 SCTAB nTab;
1108 SingleRefToVars( rRef, nCol, nRow, nTab);
1112 void ScInterpreter::ValidateRef( const ScComplexRefData & rRef )
1114 ValidateRef( rRef.Ref1);
1115 ValidateRef( rRef.Ref2);
1119 void ScInterpreter::ValidateRef( const ScRefList & rRefList )
1121 ScRefList::const_iterator it( rRefList.begin());
1122 ScRefList::const_iterator end( rRefList.end());
1123 for ( ; it != end; ++it)
1125 ValidateRef( *it);
1130 void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef,
1131 SCCOL & rCol, SCROW & rRow, SCTAB & rTab )
1133 if ( rRef.IsColRel() )
1134 rCol = aPos.Col() + rRef.Col();
1135 else
1136 rCol = rRef.Col();
1138 if ( rRef.IsRowRel() )
1139 rRow = aPos.Row() + rRef.Row();
1140 else
1141 rRow = rRef.Row();
1143 if ( rRef.IsTabRel() )
1144 rTab = aPos.Tab() + rRef.Tab();
1145 else
1146 rTab = rRef.Tab();
1148 if( !ValidCol( rCol) || rRef.IsColDeleted() )
1149 SetError( errNoRef ), rCol = 0;
1150 if( !ValidRow( rRow) || rRef.IsRowDeleted() )
1151 SetError( errNoRef ), rRow = 0;
1152 if( !ValidTab( rTab, pDok->GetTableCount() - 1) || rRef.IsTabDeleted() )
1153 SetError( errNoRef ), rTab = 0;
1157 void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
1159 if( sp )
1161 --sp;
1162 FormulaToken* p = pStack[ sp ];
1163 switch (p->GetType())
1165 case svError:
1166 nGlobalError = p->GetError();
1167 break;
1168 case svSingleRef:
1169 SingleRefToVars( static_cast<ScToken*>(p)->GetSingleRef(), rCol, rRow, rTab);
1170 if ( !pDok->aTableOpList.empty() )
1171 ReplaceCell( rCol, rRow, rTab );
1172 break;
1173 default:
1174 SetError( errIllegalParameter);
1177 else
1178 SetError( errUnknownStackVariable);
1182 void ScInterpreter::PopSingleRef( ScAddress& rAdr )
1184 if( sp )
1186 --sp;
1187 FormulaToken* p = pStack[ sp ];
1188 switch (p->GetType())
1190 case svError:
1191 nGlobalError = p->GetError();
1192 break;
1193 case svSingleRef:
1195 SCCOL nCol;
1196 SCROW nRow;
1197 SCTAB nTab;
1198 SingleRefToVars( static_cast<ScToken*>(p)->GetSingleRef(), nCol, nRow, nTab);
1199 rAdr.Set( nCol, nRow, nTab );
1200 if ( !pDok->aTableOpList.empty() )
1201 ReplaceCell( rAdr );
1203 break;
1204 default:
1205 SetError( errIllegalParameter);
1208 else
1209 SetError( errUnknownStackVariable);
1213 void ScInterpreter::DoubleRefToVars( const ScToken* p,
1214 SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1215 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1216 bool bDontCheckForTableOp )
1218 const ScComplexRefData& rCRef = p->GetDoubleRef();
1219 SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1);
1220 SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2);
1221 if ( !pDok->aTableOpList.empty() && !bDontCheckForTableOp )
1223 ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 );
1224 if ( IsTableOpInRange( aRange ) )
1225 SetError( errIllegalParameter );
1229 ScDBRangeBase* ScInterpreter::PopDBDoubleRef()
1231 StackVar eType = GetStackType();
1232 switch (eType)
1234 case svUnknown:
1235 SetError(errUnknownStackVariable);
1236 break;
1237 case svError:
1238 PopError();
1239 break;
1240 case svDoubleRef:
1242 SCCOL nCol1, nCol2;
1243 SCROW nRow1, nRow2;
1244 SCTAB nTab1, nTab2;
1245 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
1246 if (nGlobalError)
1247 break;
1248 return new ScDBInternalRange(pDok,
1249 ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
1251 case svMatrix:
1252 case svExternalDoubleRef:
1254 ScMatrixRef pMat;
1255 if (eType == svMatrix)
1256 pMat = PopMatrix();
1257 else
1258 PopExternalDoubleRef(pMat);
1259 if (nGlobalError)
1260 break;
1261 return new ScDBExternalRange(pDok, pMat);
1263 default:
1264 SetError( errIllegalParameter);
1267 return NULL;
1270 void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1271 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1272 bool bDontCheckForTableOp )
1274 if( sp )
1276 --sp;
1277 FormulaToken* p = pStack[ sp ];
1278 switch (p->GetType())
1280 case svError:
1281 nGlobalError = p->GetError();
1282 break;
1283 case svDoubleRef:
1284 DoubleRefToVars( static_cast<ScToken*>(p), rCol1, rRow1, rTab1, rCol2, rRow2, rTab2,
1285 bDontCheckForTableOp);
1286 break;
1287 default:
1288 SetError( errIllegalParameter);
1291 else
1292 SetError( errUnknownStackVariable);
1296 void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef,
1297 ScRange & rRange, bool bDontCheckForTableOp )
1299 SCCOL nCol;
1300 SCROW nRow;
1301 SCTAB nTab;
1302 SingleRefToVars( rCRef.Ref1, nCol, nRow, nTab);
1303 rRange.aStart.Set( nCol, nRow, nTab );
1304 SingleRefToVars( rCRef.Ref2, nCol, nRow, nTab);
1305 rRange.aEnd.Set( nCol, nRow, nTab );
1306 if (! pDok->aTableOpList.empty() && !bDontCheckForTableOp )
1308 if ( IsTableOpInRange( rRange ) )
1309 SetError( errIllegalParameter );
1314 void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList )
1316 if (sp)
1318 formula::FormulaToken* pToken = pStack[ sp-1 ];
1319 ScToken* p = static_cast<ScToken*>(pToken);
1320 switch (pToken->GetType())
1322 case svError:
1323 nGlobalError = p->GetError();
1324 break;
1325 case svDoubleRef:
1326 --sp;
1327 DoubleRefToRange( p->GetDoubleRef(), rRange);
1328 break;
1329 case svRefList:
1331 const ScRefList* pList = p->GetRefList();
1332 if (rRefInList < pList->size())
1334 DoubleRefToRange( (*pList)[rRefInList], rRange);
1335 if (++rRefInList < pList->size())
1336 ++rParam;
1337 else
1339 --sp;
1340 rRefInList = 0;
1343 else
1345 --sp;
1346 rRefInList = 0;
1347 SetError( errIllegalParameter);
1350 break;
1351 default:
1352 SetError( errIllegalParameter);
1355 else
1356 SetError( errUnknownStackVariable);
1360 void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
1362 if( sp )
1364 --sp;
1365 FormulaToken* p = pStack[ sp ];
1366 switch (p->GetType())
1368 case svError:
1369 nGlobalError = p->GetError();
1370 break;
1371 case svDoubleRef:
1372 DoubleRefToRange( static_cast<ScToken*>(p)->GetDoubleRef(), rRange, bDontCheckForTableOp);
1373 break;
1374 default:
1375 SetError( errIllegalParameter);
1378 else
1379 SetError( errUnknownStackVariable);
1382 void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef)
1384 if (!sp)
1386 SetError(errUnknownStackVariable);
1387 return;
1390 --sp;
1391 FormulaToken* p = pStack[sp];
1392 StackVar eType = p->GetType();
1394 if (eType == svError)
1396 nGlobalError = p->GetError();
1397 return;
1400 if (eType != svExternalSingleRef)
1402 SetError( errIllegalParameter);
1403 return;
1406 rFileId = p->GetIndex();
1407 rTabName = p->GetString().getString();
1408 rRef = static_cast<ScToken*>(p)->GetSingleRef();
1411 void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1413 sal_uInt16 nFileId;
1414 OUString aTabName;
1415 ScSingleRefData aData;
1416 PopExternalSingleRef(nFileId, aTabName, aData, rToken, pFmt);
1419 void ScInterpreter::PopExternalSingleRef(
1420 sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef,
1421 ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1423 PopExternalSingleRef(rFileId, rTabName, rRef);
1424 if (nGlobalError)
1425 return;
1427 ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1428 const OUString* pFile = pRefMgr->getExternalFileName(rFileId);
1429 if (!pFile)
1431 SetError(errNoName);
1432 return;
1435 if (rRef.IsTabRel())
1437 OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!");
1438 SetError(errNoRef);
1439 return;
1442 ScAddress aAddr = rRef.toAbs(aPos);
1443 ScExternalRefCache::CellFormat aFmt;
1444 ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
1445 rFileId, rTabName, aAddr, &aPos, NULL, &aFmt);
1447 if (!xNew)
1449 SetError(errNoRef);
1450 return;
1453 rToken = xNew;
1454 if (pFmt)
1455 *pFmt = aFmt;
1458 void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName, ScComplexRefData& rRef)
1460 if (!sp)
1462 SetError(errUnknownStackVariable);
1463 return;
1466 --sp;
1467 FormulaToken* p = pStack[sp];
1468 StackVar eType = p->GetType();
1470 if (eType == svError)
1472 nGlobalError = p->GetError();
1473 return;
1476 if (eType != svExternalDoubleRef)
1478 SetError( errIllegalParameter);
1479 return;
1482 rFileId = p->GetIndex();
1483 rTabName = p->GetString().getString();
1484 rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1487 void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray)
1489 sal_uInt16 nFileId;
1490 OUString aTabName;
1491 ScComplexRefData aData;
1492 PopExternalDoubleRef(nFileId, aTabName, aData);
1493 if (nGlobalError)
1494 return;
1496 GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
1497 if (nGlobalError)
1498 return;
1501 void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
1503 ScExternalRefCache::TokenArrayRef pArray;
1504 PopExternalDoubleRef(pArray);
1505 if (nGlobalError)
1506 return;
1508 // For now, we only support single range data for external
1509 // references, which means the array should only contain a
1510 // single matrix token.
1511 ScToken* p = static_cast<ScToken*>(pArray->First());
1512 if (!p || p->GetType() != svMatrix)
1513 SetError( errIllegalParameter);
1514 else
1516 rMat = p->GetMatrix();
1517 if (!rMat)
1518 SetError( errUnknownVariable);
1522 void ScInterpreter::GetExternalDoubleRef(
1523 sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
1525 ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1526 const OUString* pFile = pRefMgr->getExternalFileName(nFileId);
1527 if (!pFile)
1529 SetError(errNoName);
1530 return;
1532 if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
1534 OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
1535 SetError(errNoRef);
1536 return;
1539 ScComplexRefData aData(rData);
1540 ScRange aRange = aData.toAbs(aPos);
1541 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
1542 nFileId, rTabName, aRange, &aPos);
1544 if (!pArray)
1546 SetError(errIllegalArgument);
1547 return;
1550 ScToken* pToken = static_cast<ScToken*>(pArray->First());
1551 if (pToken->GetType() != svMatrix)
1553 SetError(errIllegalArgument);
1554 return;
1557 if (pArray->Next())
1559 // Can't handle more than one matrix per parameter.
1560 SetError( errIllegalArgument);
1561 return;
1564 rArray = pArray;
1567 bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
1569 switch ( GetStackType() )
1571 case svDoubleRef :
1573 ScRange aRange;
1574 PopDoubleRef( aRange, true );
1575 return DoubleRefToPosSingleRef( aRange, rAdr );
1577 case svSingleRef :
1579 PopSingleRef( rAdr );
1580 return true;
1582 default:
1583 PopError();
1584 SetError( errNoRef );
1586 return false;
1590 void ScInterpreter::PopDoubleRefPushMatrix()
1592 if ( GetStackType() == svDoubleRef )
1594 ScMatrixRef pMat = GetMatrix();
1595 if ( pMat )
1596 PushMatrix( pMat );
1597 else
1598 PushIllegalParameter();
1600 else
1601 SetError( errNoRef );
1605 ScTokenMatrixMap* ScInterpreter::CreateTokenMatrixMap()
1607 return new ScTokenMatrixMap;
1611 bool ScInterpreter::ConvertMatrixParameters()
1613 sal_uInt16 nParams = pCur->GetParamCount();
1614 OSL_ENSURE( nParams <= sp, "ConvertMatrixParameters: stack/param count mismatch");
1615 SCSIZE nJumpCols = 0, nJumpRows = 0;
1616 for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i )
1618 FormulaToken* p = pStack[ sp - i ];
1619 if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing)
1621 OSL_FAIL( "ConvertMatrixParameters: not a push");
1623 else
1625 switch ( p->GetType() )
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 break;
1636 case svMatrix:
1638 if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
1639 == ScParameterClassification::Value )
1640 { // only if single value expected
1641 ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
1642 if ( !pMat )
1643 SetError( errUnknownVariable);
1644 else
1646 SCSIZE nCols, nRows;
1647 pMat->GetDimensions( nCols, nRows);
1648 if ( nJumpCols < nCols )
1649 nJumpCols = nCols;
1650 if ( nJumpRows < nRows )
1651 nJumpRows = nRows;
1655 break;
1656 case svDoubleRef:
1658 ScParameterClassification::Type eType =
1659 ScParameterClassification::GetParameterType( pCur, nParams - i);
1660 if ( eType != ScParameterClassification::Reference &&
1661 eType != ScParameterClassification::ReferenceOrForceArray)
1663 SCCOL nCol1, nCol2;
1664 SCROW nRow1, nRow2;
1665 SCTAB nTab1, nTab2;
1666 DoubleRefToVars( static_cast<const ScToken*>( p), nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1667 // Make sure the map exists, created if not.
1668 GetTokenMatrixMap();
1669 ScMatrixRef pMat = CreateMatrixFromDoubleRef( p,
1670 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1671 if (pMat)
1673 if ( eType == ScParameterClassification::Value )
1674 { // only if single value expected
1675 if ( nJumpCols < static_cast<SCSIZE>(nCol2 - nCol1 + 1) )
1676 nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
1677 if ( nJumpRows < static_cast<SCSIZE>(nRow2 - nRow1 + 1) )
1678 nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
1680 ScToken* pNew = new ScMatrixToken( pMat);
1681 pNew->IncRef();
1682 pStack[ sp - i ] = pNew;
1683 p->DecRef(); // p may be dead now!
1687 break;
1688 case svExternalDoubleRef:
1690 ScParameterClassification::Type eType =
1691 ScParameterClassification::GetParameterType( pCur, nParams - i);
1692 if (eType == ScParameterClassification::Array)
1694 sal_uInt16 nFileId = p->GetIndex();
1695 OUString aTabName = p->GetString().getString();
1696 const ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef();
1697 ScExternalRefCache::TokenArrayRef pArray;
1698 GetExternalDoubleRef(nFileId, aTabName, rRef, pArray);
1699 if (nGlobalError)
1700 break;
1702 ScToken* pTemp = static_cast<ScToken*>(pArray->First());
1703 if (!pTemp)
1704 break;
1706 ScMatrixRef pMat = pTemp->GetMatrix();
1707 if (pMat)
1709 ScToken* pNew = new ScMatrixToken( pMat);
1710 pNew->IncRef();
1711 pStack[ sp - i ] = pNew;
1712 p->DecRef(); // p may be dead now!
1716 break;
1717 case svRefList:
1719 ScParameterClassification::Type eType =
1720 ScParameterClassification::GetParameterType( pCur, nParams - i);
1721 if ( eType != ScParameterClassification::Reference &&
1722 eType != ScParameterClassification::ReferenceOrForceArray)
1724 // can't convert to matrix
1725 SetError( errNoValue);
1728 break;
1729 default:
1730 OSL_FAIL( "ConvertMatrixParameters: unknown parameter type");
1734 if( nJumpCols && nJumpRows )
1736 short nPC = aCode.GetPC();
1737 short nStart = nPC - 1; // restart on current code (-1)
1738 short nNext = nPC; // next instruction after subroutine
1739 short nStop = nPC + 1; // stop subroutine before reaching that
1740 FormulaTokenRef xNew;
1741 ScTokenMatrixMap::const_iterator aMapIter;
1742 if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) !=
1743 pTokenMatrixMap->end()))
1744 xNew = (*aMapIter).second;
1745 else
1747 ScJumpMatrix* pJumpMat = new ScJumpMatrix( nJumpCols, nJumpRows);
1748 pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop);
1749 // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1750 ScTokenVec* pParams = new ScTokenVec( nParams);
1751 for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i )
1753 FormulaToken* p = pStack[ --sp ];
1754 p->IncRef();
1755 // store in reverse order such that a push may simply iterate
1756 (*pParams)[ nParams - i ] = p;
1758 pJumpMat->SetJumpParameters( pParams);
1759 xNew = new ScJumpMatrixToken( pJumpMat );
1760 GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur,
1761 xNew));
1763 PushTempToken( xNew.get());
1764 // set continuation point of path for main code line
1765 aCode.Jump( nNext, nNext);
1766 return true;
1768 return false;
1772 ScMatrixRef ScInterpreter::PopMatrix()
1774 if( sp )
1776 --sp;
1777 FormulaToken* p = pStack[ sp ];
1778 switch (p->GetType())
1780 case svError:
1781 nGlobalError = p->GetError();
1782 break;
1783 case svMatrix:
1785 ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix();
1786 if ( pMat )
1787 pMat->SetErrorInterpreter( this);
1788 else
1789 SetError( errUnknownVariable);
1790 return pMat;
1792 default:
1793 SetError( errIllegalParameter);
1796 else
1797 SetError( errUnknownStackVariable);
1798 return NULL;
1801 sc::RangeMatrix ScInterpreter::PopRangeMatrix()
1803 sc::RangeMatrix aRet;
1804 if (sp)
1806 switch (pStack[sp-1]->GetType())
1808 case svMatrix:
1810 --sp;
1811 FormulaToken* p = pStack[sp];
1812 ScToken* p2 = static_cast<ScToken*>(p);
1813 aRet.mpMat = p2->GetMatrix();
1814 if (aRet.mpMat)
1816 aRet.mpMat->SetErrorInterpreter(this);
1817 if (p2->GetByte() == MATRIX_TOKEN_HAS_RANGE)
1819 const ScComplexRefData& rRef = p2->GetDoubleRef();
1820 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel())
1822 aRet.mnCol1 = rRef.Ref1.Col();
1823 aRet.mnRow1 = rRef.Ref1.Row();
1824 aRet.mnTab1 = rRef.Ref1.Tab();
1825 aRet.mnCol2 = rRef.Ref2.Col();
1826 aRet.mnRow2 = rRef.Ref2.Row();
1827 aRet.mnTab2 = rRef.Ref2.Tab();
1831 else
1832 SetError( errUnknownVariable);
1834 break;
1835 default:
1836 aRet.mpMat = PopMatrix();
1839 return aRet;
1842 void ScInterpreter::QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr)
1844 if (xMat)
1846 ScMatrixValue nMatVal = xMat->Get(0, 0);
1847 ScMatValType nMatValType = nMatVal.nType;
1848 if (ScMatrix::IsNonValueType( nMatValType))
1850 if ( xMat->IsEmptyPath( 0, 0))
1851 { // result of empty FALSE jump path
1852 FormulaTokenRef xRes = new FormulaDoubleToken( 0.0);
1853 PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
1854 rRetTypeExpr = NUMBERFORMAT_LOGICAL;
1856 else
1858 svl::SharedString aStr( nMatVal.GetString());
1859 FormulaTokenRef xRes = new FormulaStringToken( aStr);
1860 PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
1861 rRetTypeExpr = NUMBERFORMAT_TEXT;
1864 else
1866 sal_uInt16 nErr = GetDoubleErrorValue( nMatVal.fVal);
1867 FormulaTokenRef xRes;
1868 if (nErr)
1869 xRes = new FormulaErrorToken( nErr);
1870 else
1871 xRes = new FormulaDoubleToken( nMatVal.fVal);
1872 PushTempToken( new ScMatrixCellResultToken( xMat, xRes.get()));
1873 if ( rRetTypeExpr != NUMBERFORMAT_LOGICAL )
1874 rRetTypeExpr = NUMBERFORMAT_NUMBER;
1876 rRetIndexExpr = 0;
1877 xMat->SetErrorInterpreter( NULL);
1879 else
1880 SetError( errUnknownStackVariable);
1884 void ScInterpreter::PushDouble(double nVal)
1886 TreatDoubleError( nVal );
1887 if (!IfErrorPushError())
1888 PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1892 void ScInterpreter::PushInt(int nVal)
1894 if (!IfErrorPushError())
1895 PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1899 void ScInterpreter::PushStringBuffer( const sal_Unicode* pString )
1901 if ( pString )
1903 svl::SharedString aSS = pDok->GetSharedStringPool().intern(OUString(pString));
1904 PushString(aSS);
1906 else
1907 PushString(svl::SharedString::getEmptyString());
1910 void ScInterpreter::PushString( const OUString& rStr )
1912 PushString(pDok->GetSharedStringPool().intern(rStr));
1915 void ScInterpreter::PushString( const svl::SharedString& rString )
1917 if (!IfErrorPushError())
1918 PushTempTokenWithoutError( new FormulaStringToken( rString ) );
1922 void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
1924 if (!IfErrorPushError())
1926 ScSingleRefData aRef;
1927 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1928 PushTempTokenWithoutError( new ScSingleRefToken( aRef ) );
1933 void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1934 SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1936 if (!IfErrorPushError())
1938 ScComplexRefData aRef;
1939 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1940 PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) );
1945 void ScInterpreter::PushExternalSingleRef(
1946 sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
1948 if (!IfErrorPushError())
1950 ScSingleRefData aRef;
1951 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1952 PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId, rTabName, aRef)) ;
1957 void ScInterpreter::PushExternalDoubleRef(
1958 sal_uInt16 nFileId, const OUString& rTabName,
1959 SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1961 if (!IfErrorPushError())
1963 ScComplexRefData aRef;
1964 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1965 PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId, rTabName, aRef) );
1969 void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat )
1971 if (!rMat.isRangeValid())
1973 // Just push the matrix part only.
1974 PushMatrix(rMat.mpMat);
1975 return;
1978 rMat.mpMat->SetErrorInterpreter(NULL);
1979 nGlobalError = 0;
1980 PushTempTokenWithoutError(new ScMatrixRangeToken(rMat));
1983 void ScInterpreter::PushMatrix(const ScMatrixRef& pMat)
1985 pMat->SetErrorInterpreter( NULL);
1986 // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
1987 // but with notifying ScInterpreter via nGlobalError, substituting it would
1988 // mean to inherit the error on all array elements in all following
1989 // operations.
1990 nGlobalError = 0;
1991 PushTempTokenWithoutError( new ScMatrixToken( pMat ) );
1995 void ScInterpreter::PushError( sal_uInt16 nError )
1997 SetError( nError ); // only sets error if not already set
1998 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
2001 void ScInterpreter::PushParameterExpected()
2003 PushError( errParameterExpected);
2007 void ScInterpreter::PushIllegalParameter()
2009 PushError( errIllegalParameter);
2013 void ScInterpreter::PushIllegalArgument()
2015 PushError( errIllegalArgument);
2019 void ScInterpreter::PushNA()
2021 PushError( NOTAVAILABLE);
2025 void ScInterpreter::PushNoValue()
2027 PushError( errNoValue);
2031 bool ScInterpreter::IsMissing()
2033 return sp && pStack[sp - 1]->GetType() == svMissing;
2037 StackVar ScInterpreter::GetRawStackType()
2039 StackVar eRes;
2040 if( sp )
2042 eRes = pStack[sp - 1]->GetType();
2044 else
2046 SetError(errUnknownStackVariable);
2047 eRes = svUnknown;
2049 return eRes;
2053 StackVar ScInterpreter::GetStackType()
2055 StackVar eRes;
2056 if( sp )
2058 eRes = pStack[sp - 1]->GetType();
2059 if( eRes == svMissing || eRes == svEmptyCell )
2060 eRes = svDouble; // default!
2062 else
2064 SetError(errUnknownStackVariable);
2065 eRes = svUnknown;
2067 return eRes;
2071 StackVar ScInterpreter::GetStackType( sal_uInt8 nParam )
2073 StackVar eRes;
2074 if( sp > nParam-1 )
2076 eRes = pStack[sp - nParam]->GetType();
2077 if( eRes == svMissing || eRes == svEmptyCell )
2078 eRes = svDouble; // default!
2080 else
2081 eRes = svUnknown;
2082 return eRes;
2086 bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
2088 // Check for a singleton first - no implicit intersection for them.
2089 if( rRange.aStart == rRange.aEnd )
2091 rAdr = rRange.aStart;
2092 return true;
2095 bool bOk = false;
2097 if ( pJumpMatrix )
2099 bOk = rRange.aStart.Tab() == rRange.aEnd.Tab();
2100 if ( !bOk )
2101 SetError( errIllegalArgument);
2102 else
2104 SCSIZE nC, nR;
2105 pJumpMatrix->GetPos( nC, nR);
2106 rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) );
2107 rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) );
2108 rAdr.SetTab( rRange.aStart.Tab());
2109 bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <=
2110 rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() &&
2111 rAdr.Row() <= rRange.aEnd.Row();
2112 if ( !bOk )
2113 SetError( errNoValue);
2115 return bOk;
2118 SCCOL nMyCol = aPos.Col();
2119 SCROW nMyRow = aPos.Row();
2120 SCTAB nMyTab = aPos.Tab();
2121 SCCOL nCol = 0;
2122 SCROW nRow = 0;
2123 SCTAB nTab;
2124 nTab = rRange.aStart.Tab();
2125 if ( rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
2127 nRow = rRange.aStart.Row();
2128 if ( nRow == rRange.aEnd.Row() )
2130 bOk = true;
2131 nCol = nMyCol;
2133 else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
2134 && rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
2136 bOk = true;
2137 nCol = nMyCol;
2138 nRow = nMyRow;
2141 else if ( rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
2143 nCol = rRange.aStart.Col();
2144 if ( nCol == rRange.aEnd.Col() )
2146 bOk = true;
2147 nRow = nMyRow;
2149 else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
2150 && rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
2152 bOk = true;
2153 nCol = nMyCol;
2154 nRow = nMyRow;
2157 if ( bOk )
2159 if ( nTab == rRange.aEnd.Tab() )
2160 ; // all done
2161 else if ( nTab <= nMyTab && nMyTab <= rRange.aEnd.Tab() )
2162 nTab = nMyTab;
2163 else
2164 bOk = false;
2165 if ( bOk )
2166 rAdr.Set( nCol, nRow, nTab );
2168 if ( !bOk )
2169 SetError( errNoValue );
2170 return bOk;
2173 double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat)
2175 if (!pMat)
2176 return 0.0;
2178 if ( !pJumpMatrix )
2179 return pMat->GetDouble( 0 );
2181 SCSIZE nCols, nRows, nC, nR;
2182 pMat->GetDimensions( nCols, nRows);
2183 pJumpMatrix->GetPos( nC, nR);
2184 if ( nC < nCols && nR < nRows )
2185 return pMat->GetDouble( nC, nR);
2187 SetError( errNoValue);
2188 return 0.0;
2191 double ScInterpreter::GetDouble()
2193 double nVal(0.0);
2194 switch( GetRawStackType() )
2196 case svDouble:
2197 nVal = PopDouble();
2198 break;
2199 case svString:
2200 nVal = ConvertStringToValue( PopString().getString());
2201 break;
2202 case svSingleRef:
2204 ScAddress aAdr;
2205 PopSingleRef( aAdr );
2206 ScRefCellValue aCell;
2207 aCell.assign(*pDok, aAdr);
2208 nVal = GetCellValue(aAdr, aCell);
2210 break;
2211 case svDoubleRef:
2212 { // generate position dependent SingleRef
2213 ScRange aRange;
2214 PopDoubleRef( aRange );
2215 ScAddress aAdr;
2216 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
2218 ScRefCellValue aCell;
2219 aCell.assign(*pDok, aAdr);
2220 nVal = GetCellValue(aAdr, aCell);
2222 else
2223 nVal = 0.0;
2225 break;
2226 case svExternalSingleRef:
2228 ScExternalRefCache::TokenRef pToken;
2229 PopExternalSingleRef(pToken);
2230 if (!nGlobalError && pToken)
2231 nVal = pToken->GetDouble();
2233 break;
2234 case svExternalDoubleRef:
2236 ScMatrixRef pMat;
2237 PopExternalDoubleRef(pMat);
2238 if (nGlobalError)
2239 break;
2241 nVal = GetDoubleFromMatrix(pMat);
2243 break;
2244 case svMatrix:
2246 ScMatrixRef pMat = PopMatrix();
2247 nVal = GetDoubleFromMatrix(pMat);
2249 break;
2250 case svError:
2251 PopError();
2252 nVal = 0.0;
2253 break;
2254 case svEmptyCell:
2255 case svMissing:
2256 Pop();
2257 nVal = 0.0;
2258 break;
2259 default:
2260 PopError();
2261 SetError( errIllegalParameter);
2262 nVal = 0.0;
2264 if ( nFuncFmtType == nCurFmtType )
2265 nFuncFmtIndex = nCurFmtIndex;
2266 return nVal;
2270 double ScInterpreter::GetDoubleWithDefault(double nDefault)
2272 bool bMissing = IsMissing();
2273 double nResultVal = GetDouble();
2274 if ( bMissing )
2275 nResultVal = nDefault;
2276 return nResultVal;
2280 svl::SharedString ScInterpreter::GetString()
2282 switch (GetRawStackType())
2284 case svError:
2285 PopError();
2286 return svl::SharedString::getEmptyString();
2287 case svMissing:
2288 case svEmptyCell:
2289 Pop();
2290 return svl::SharedString::getEmptyString();
2291 case svDouble:
2293 double fVal = PopDouble();
2294 sal_uLong nIndex = pFormatter->GetStandardFormat(
2295 NUMBERFORMAT_NUMBER,
2296 ScGlobal::eLnge);
2297 OUString aStr;
2298 pFormatter->GetInputLineString(fVal, nIndex, aStr);
2299 return mrStrPool.intern(aStr);
2301 case svString:
2302 return PopString();
2303 case svSingleRef:
2305 ScAddress aAdr;
2306 PopSingleRef( aAdr );
2307 if (nGlobalError == 0)
2309 ScRefCellValue aCell;
2310 aCell.assign(*pDok, aAdr);
2311 svl::SharedString aSS;
2312 GetCellString(aSS, aCell);
2313 return aSS;
2315 else
2316 return svl::SharedString::getEmptyString();
2318 case svDoubleRef:
2319 { // generate position dependent SingleRef
2320 ScRange aRange;
2321 PopDoubleRef( aRange );
2322 ScAddress aAdr;
2323 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
2325 ScRefCellValue aCell;
2326 aCell.assign(*pDok, aAdr);
2327 svl::SharedString aSS;
2328 GetCellString(aSS, aCell);
2329 return aSS;
2331 else
2332 return svl::SharedString::getEmptyString();
2334 case svExternalSingleRef:
2336 ScExternalRefCache::TokenRef pToken;
2337 PopExternalSingleRef(pToken);
2338 if (nGlobalError)
2339 return svl::SharedString::getEmptyString();
2341 return pToken->GetString();
2343 case svExternalDoubleRef:
2345 ScMatrixRef pMat;
2346 PopExternalDoubleRef(pMat);
2347 return GetStringFromMatrix(pMat);
2349 case svMatrix:
2351 ScMatrixRef pMat = PopMatrix();
2352 return GetStringFromMatrix(pMat);
2354 break;
2355 default:
2356 PopError();
2357 SetError( errIllegalArgument);
2359 return svl::SharedString::getEmptyString();
2362 svl::SharedString ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
2364 if ( !pMat )
2365 ; // nothing
2366 else if ( !pJumpMatrix )
2368 return pMat->GetString( *pFormatter, 0, 0);
2370 else
2372 SCSIZE nCols, nRows, nC, nR;
2373 pMat->GetDimensions( nCols, nRows);
2374 pJumpMatrix->GetPos( nC, nR);
2375 if ( nC < nCols && nR < nRows )
2377 return pMat->GetString( *pFormatter, nC, nR);
2379 else
2380 SetError( errNoValue);
2382 return svl::SharedString::getEmptyString();
2385 ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix(
2386 double& rDouble, svl::SharedString& rString )
2389 rDouble = 0.0;
2390 rString = svl::SharedString::getEmptyString();
2391 ScMatValType nMatValType = SC_MATVAL_EMPTY;
2393 ScMatrixRef pMat;
2394 StackVar eType = GetStackType();
2395 if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
2397 pMat = GetMatrix();
2399 else
2401 PopError();
2402 SetError( errIllegalParameter);
2403 return nMatValType;
2406 ScMatrixValue nMatVal;
2407 if (!pMat)
2409 // nothing
2411 else if (!pJumpMatrix)
2413 nMatVal = pMat->Get(0, 0);
2414 nMatValType = nMatVal.nType;
2416 else
2418 SCSIZE nCols, nRows, nC, nR;
2419 pMat->GetDimensions( nCols, nRows);
2420 pJumpMatrix->GetPos( nC, nR);
2421 if ( nC < nCols && nR < nRows )
2423 nMatVal = pMat->Get( nC, nR);
2424 nMatValType = nMatVal.nType;
2426 else
2427 SetError( errNoValue);
2430 if (nMatValType == SC_MATVAL_VALUE)
2431 rDouble = nMatVal.fVal;
2432 else if (nMatValType == SC_MATVAL_BOOLEAN)
2434 rDouble = nMatVal.fVal;
2435 nMatValType = SC_MATVAL_VALUE;
2437 else
2438 rString = nMatVal.GetString();
2440 if (ScMatrix::IsValueType( nMatValType))
2442 sal_uInt16 nError = nMatVal.GetError();
2443 if (nError)
2444 SetError( nError);
2447 return nMatValType;
2451 void ScInterpreter::ScDBGet()
2453 bool bMissingField = false;
2454 SAL_WNODEPRECATED_DECLARATIONS_PUSH
2455 auto_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2456 SAL_WNODEPRECATED_DECLARATIONS_POP
2457 if (!pQueryParam.get())
2459 // Failed to create query param.
2460 PushIllegalParameter();
2461 return;
2464 pQueryParam->mbSkipString = false;
2465 ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
2466 ScDBQueryDataIterator::Value aValue;
2467 if (!aValIter.GetFirst(aValue) || aValue.mnError)
2469 // No match found.
2470 PushNoValue();
2471 return;
2474 ScDBQueryDataIterator::Value aValNext;
2475 if (aValIter.GetNext(aValNext) && !aValNext.mnError)
2477 // There should be only one unique match.
2478 PushIllegalArgument();
2479 return;
2482 if (aValue.mbIsNumber)
2483 PushDouble(aValue.mfValue);
2484 else
2485 PushString(aValue.maString);
2489 void ScInterpreter::ScExternal()
2491 sal_uInt8 nParamCount = GetByte();
2492 OUString aUnoName;
2493 OUString aFuncName( ScGlobal::pCharClass->uppercase( pCur->GetExternal() ) );
2494 FuncData* pFuncData = ScGlobal::GetFuncCollection()->findByName(aFuncName);
2495 if (pFuncData)
2497 // Old binary non-UNO add-in function.
2498 // NOTE: parameter count is 1-based with the 0th "parameter" being the
2499 // return value, included in pFuncDatat->GetParamCount()
2500 if (nParamCount < MAXFUNCPARAM && nParamCount == pFuncData->GetParamCount() - 1)
2502 ParamType eParamType[MAXFUNCPARAM];
2503 void* ppParam[MAXFUNCPARAM];
2504 double nVal[MAXFUNCPARAM];
2505 sal_Char* pStr[MAXFUNCPARAM];
2506 sal_uInt8* pCellArr[MAXFUNCPARAM];
2507 short i;
2509 for (i = 0; i < MAXFUNCPARAM; i++)
2511 eParamType[i] = pFuncData->GetParamType(i);
2512 ppParam[i] = NULL;
2513 nVal[i] = 0.0;
2514 pStr[i] = NULL;
2515 pCellArr[i] = NULL;
2518 for (i = nParamCount; (i > 0) && (nGlobalError == 0); i--)
2520 switch (eParamType[i])
2522 case PTR_DOUBLE :
2524 nVal[i-1] = GetDouble();
2525 ppParam[i] = &nVal[i-1];
2527 break;
2528 case PTR_STRING :
2530 OString aStr(OUStringToOString(GetString().getString(),
2531 osl_getThreadTextEncoding()));
2532 if ( aStr.getLength() >= ADDIN_MAXSTRLEN )
2533 SetError( errStringOverflow );
2534 else
2536 pStr[i-1] = new sal_Char[ADDIN_MAXSTRLEN];
2537 strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN );
2538 pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2539 ppParam[i] = pStr[i-1];
2542 break;
2543 case PTR_DOUBLE_ARR :
2545 SCCOL nCol1;
2546 SCROW nRow1;
2547 SCTAB nTab1;
2548 SCCOL nCol2;
2549 SCROW nRow2;
2550 SCTAB nTab2;
2551 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2552 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2553 if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2554 SetError(errCodeOverflow);
2555 else
2556 ppParam[i] = pCellArr[i-1];
2558 break;
2559 case PTR_STRING_ARR :
2561 SCCOL nCol1;
2562 SCROW nRow1;
2563 SCTAB nTab1;
2564 SCCOL nCol2;
2565 SCROW nRow2;
2566 SCTAB nTab2;
2567 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2568 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2569 if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2570 SetError(errCodeOverflow);
2571 else
2572 ppParam[i] = pCellArr[i-1];
2574 break;
2575 case PTR_CELL_ARR :
2577 SCCOL nCol1;
2578 SCROW nRow1;
2579 SCTAB nTab1;
2580 SCCOL nCol2;
2581 SCROW nRow2;
2582 SCTAB nTab2;
2583 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2584 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2585 if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2586 SetError(errCodeOverflow);
2587 else
2588 ppParam[i] = pCellArr[i-1];
2590 break;
2591 default :
2592 SetError(errIllegalParameter);
2593 break;
2596 while ( i-- )
2597 Pop(); // im Fehlerfall (sonst ist i==0) Parameter wegpoppen
2599 if (nGlobalError == 0)
2601 if ( pFuncData->GetAsyncType() == NONE )
2603 switch ( eParamType[0] )
2605 case PTR_DOUBLE :
2607 double nErg = 0.0;
2608 ppParam[0] = &nErg;
2609 pFuncData->Call(ppParam);
2610 PushDouble(nErg);
2612 break;
2613 case PTR_STRING :
2615 sal_Char* pcErg = new sal_Char[ADDIN_MAXSTRLEN];
2616 ppParam[0] = pcErg;
2617 pFuncData->Call(ppParam);
2618 OUString aUni( pcErg, strlen(pcErg), osl_getThreadTextEncoding() );
2619 PushString( aUni );
2620 delete[] pcErg;
2622 break;
2623 default:
2624 PushError( errUnknownState );
2627 else
2629 // nach dem Laden Asyncs wieder anwerfen
2630 if ( rArr.IsRecalcModeNormal() )
2631 rArr.SetExclusiveRecalcModeOnLoad();
2632 // garantiert identischer Handle bei identischem Aufruf?!?
2633 // sonst schei*e ...
2634 double nErg = 0.0;
2635 ppParam[0] = &nErg;
2636 pFuncData->Call(ppParam);
2637 sal_uLong nHandle = sal_uLong( nErg );
2638 if ( nHandle >= 65536 )
2640 ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2641 if ( !pAs )
2643 pAs = new ScAddInAsync(nHandle, pFuncData, pDok);
2644 pMyFormulaCell->StartListening( *pAs );
2646 else
2648 // falls per cut/copy/paste
2649 pMyFormulaCell->StartListening( *pAs );
2650 // in anderes Dokument?
2651 if ( !pAs->HasDocument( pDok ) )
2652 pAs->AddDocument( pDok );
2654 if ( pAs->IsValid() )
2656 switch ( pAs->GetType() )
2658 case PTR_DOUBLE :
2659 PushDouble( pAs->GetValue() );
2660 break;
2661 case PTR_STRING :
2662 PushString( pAs->GetString() );
2663 break;
2664 default:
2665 PushError( errUnknownState );
2668 else
2669 PushNA();
2671 else
2672 PushNoValue();
2676 for (i = 0; i < MAXFUNCPARAM; i++)
2678 delete[] pStr[i];
2679 delete[] pCellArr[i];
2682 else
2684 while( nParamCount-- > 0)
2685 Pop();
2686 PushIllegalParameter();
2689 else if ( !( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).isEmpty() )
2691 // bLocalFirst=false in FindFunction, cFunc should be the stored
2692 // internal name
2694 ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
2696 if ( !aCall.ValidParamCount() )
2697 SetError( errIllegalParameter );
2699 if ( aCall.NeedsCaller() && !GetError() )
2701 SfxObjectShell* pShell = pDok->GetDocumentShell();
2702 if (pShell)
2703 aCall.SetCallerFromObjectShell( pShell );
2704 else
2706 // use temporary model object (without document) to supply options
2707 aCall.SetCaller( static_cast<beans::XPropertySet*>(
2708 new ScDocOptionsObj( pDok->GetDocOptions() ) ) );
2712 short nPar = nParamCount;
2713 while ( nPar > 0 && !GetError() )
2715 --nPar; // 0 .. (nParamCount-1)
2717 ScAddInArgumentType eType = aCall.GetArgType( nPar );
2718 sal_uInt8 nStackType = sal::static_int_cast<sal_uInt8>( GetStackType() );
2720 uno::Any aParam;
2721 switch (eType)
2723 case SC_ADDINARG_INTEGER:
2725 double fVal = GetDouble();
2726 double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2727 ::rtl::math::approxCeil( fVal );
2728 if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2729 aParam <<= (sal_Int32)fInt;
2730 else
2731 SetError(errIllegalArgument);
2733 break;
2735 case SC_ADDINARG_DOUBLE:
2736 aParam <<= (double) GetDouble();
2737 break;
2739 case SC_ADDINARG_STRING:
2740 aParam <<= GetString().getString();
2741 break;
2743 case SC_ADDINARG_INTEGER_ARRAY:
2744 switch( nStackType )
2746 case svDouble:
2747 case svString:
2748 case svSingleRef:
2750 double fVal = GetDouble();
2751 double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2752 ::rtl::math::approxCeil( fVal );
2753 if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2755 sal_Int32 nIntVal = (long)fInt;
2756 uno::Sequence<sal_Int32> aInner( &nIntVal, 1 );
2757 uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 );
2758 aParam <<= aOuter;
2760 else
2761 SetError(errIllegalArgument);
2763 break;
2764 case svDoubleRef:
2766 ScRange aRange;
2767 PopDoubleRef( aRange );
2768 if (!ScRangeToSequence::FillLongArray( aParam, pDok, aRange ))
2769 SetError(errIllegalParameter);
2771 break;
2772 case svMatrix:
2773 if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() ))
2774 SetError(errIllegalParameter);
2775 break;
2776 default:
2777 PopError();
2778 SetError(errIllegalParameter);
2780 break;
2782 case SC_ADDINARG_DOUBLE_ARRAY:
2783 switch( nStackType )
2785 case svDouble:
2786 case svString:
2787 case svSingleRef:
2789 double fVal = GetDouble();
2790 uno::Sequence<double> aInner( &fVal, 1 );
2791 uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2792 aParam <<= aOuter;
2794 break;
2795 case svDoubleRef:
2797 ScRange aRange;
2798 PopDoubleRef( aRange );
2799 if (!ScRangeToSequence::FillDoubleArray( aParam, pDok, aRange ))
2800 SetError(errIllegalParameter);
2802 break;
2803 case svMatrix:
2804 if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() ))
2805 SetError(errIllegalParameter);
2806 break;
2807 default:
2808 PopError();
2809 SetError(errIllegalParameter);
2811 break;
2813 case SC_ADDINARG_STRING_ARRAY:
2814 switch( nStackType )
2816 case svDouble:
2817 case svString:
2818 case svSingleRef:
2820 OUString aString = GetString().getString();
2821 uno::Sequence<OUString> aInner( &aString, 1 );
2822 uno::Sequence< uno::Sequence<OUString> > aOuter( &aInner, 1 );
2823 aParam <<= aOuter;
2825 break;
2826 case svDoubleRef:
2828 ScRange aRange;
2829 PopDoubleRef( aRange );
2830 if (!ScRangeToSequence::FillStringArray( aParam, pDok, aRange ))
2831 SetError(errIllegalParameter);
2833 break;
2834 case svMatrix:
2835 if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), pFormatter ))
2836 SetError(errIllegalParameter);
2837 break;
2838 default:
2839 PopError();
2840 SetError(errIllegalParameter);
2842 break;
2844 case SC_ADDINARG_MIXED_ARRAY:
2845 switch( nStackType )
2847 case svDouble:
2848 case svString:
2849 case svSingleRef:
2851 uno::Any aElem;
2852 if ( nStackType == svDouble )
2853 aElem <<= (double) GetDouble();
2854 else if ( nStackType == svString )
2855 aElem <<= GetString().getString();
2856 else
2858 ScAddress aAdr;
2859 if ( PopDoubleRefOrSingleRef( aAdr ) )
2861 ScRefCellValue aCell;
2862 aCell.assign(*pDok, aAdr);
2863 if (aCell.hasString())
2865 svl::SharedString aStr;
2866 GetCellString(aStr, aCell);
2867 aElem <<= aStr.getString();
2869 else
2870 aElem <<= GetCellValue(aAdr, aCell);
2873 uno::Sequence<uno::Any> aInner( &aElem, 1 );
2874 uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2875 aParam <<= aOuter;
2877 break;
2878 case svDoubleRef:
2880 ScRange aRange;
2881 PopDoubleRef( aRange );
2882 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2883 SetError(errIllegalParameter);
2885 break;
2886 case svMatrix:
2887 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2888 SetError(errIllegalParameter);
2889 break;
2890 default:
2891 PopError();
2892 SetError(errIllegalParameter);
2894 break;
2896 case SC_ADDINARG_VALUE_OR_ARRAY:
2897 if ( IsMissing() )
2898 nStackType = svMissing;
2899 switch( nStackType )
2901 case svDouble:
2902 aParam <<= (double) GetDouble();
2903 break;
2904 case svString:
2905 aParam <<= GetString().getString();
2906 break;
2907 case svSingleRef:
2909 ScAddress aAdr;
2910 if ( PopDoubleRefOrSingleRef( aAdr ) )
2912 ScRefCellValue aCell;
2913 aCell.assign(*pDok, aAdr);
2914 if (aCell.hasString())
2916 svl::SharedString aStr;
2917 GetCellString(aStr, aCell);
2918 aParam <<= aStr.getString();
2920 else
2921 aParam <<= GetCellValue(aAdr, aCell);
2924 break;
2925 case svDoubleRef:
2927 ScRange aRange;
2928 PopDoubleRef( aRange );
2929 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2930 SetError(errIllegalParameter);
2932 break;
2933 case svMatrix:
2934 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2935 SetError(errIllegalParameter);
2936 break;
2937 case svMissing:
2938 Pop();
2939 aParam.clear();
2940 break;
2941 default:
2942 PopError();
2943 SetError(errIllegalParameter);
2945 break;
2947 case SC_ADDINARG_CELLRANGE:
2948 switch( nStackType )
2950 case svSingleRef:
2952 ScAddress aAdr;
2953 PopSingleRef( aAdr );
2954 ScRange aRange( aAdr );
2955 uno::Reference<table::XCellRange> xObj =
2956 ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2957 if (xObj.is())
2958 aParam <<= xObj;
2959 else
2960 SetError(errIllegalParameter);
2962 break;
2963 case svDoubleRef:
2965 ScRange aRange;
2966 PopDoubleRef( aRange );
2967 uno::Reference<table::XCellRange> xObj =
2968 ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2969 if (xObj.is())
2971 aParam <<= xObj;
2973 else
2975 SetError(errIllegalParameter);
2978 break;
2979 default:
2980 PopError();
2981 SetError(errIllegalParameter);
2983 break;
2985 default:
2986 PopError();
2987 SetError(errIllegalParameter);
2989 aCall.SetParam( nPar, aParam );
2992 while (nPar-- > 0)
2994 Pop(); // in case of error, remove remaining args
2996 if ( !GetError() )
2998 aCall.ExecuteCall();
3000 if ( aCall.HasVarRes() ) // handle async functions
3002 if ( rArr.IsRecalcModeNormal() )
3004 rArr.SetExclusiveRecalcModeOnLoad();
3006 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
3007 ScAddInListener* pLis = ScAddInListener::Get( xRes );
3008 if ( !pLis )
3010 pLis = ScAddInListener::CreateListener( xRes, pDok );
3011 pMyFormulaCell->StartListening( *pLis );
3013 else
3015 pMyFormulaCell->StartListening( *pLis );
3016 if ( !pLis->HasDocument( pDok ) )
3018 pLis->AddDocument( pDok );
3022 aCall.SetResult( pLis->GetResult() ); // use result from async
3025 if ( aCall.GetErrCode() )
3027 PushError( aCall.GetErrCode() );
3029 else if ( aCall.HasMatrix() )
3031 ScMatrixRef xMat = aCall.GetMatrix();
3032 PushMatrix( xMat );
3034 else if ( aCall.HasString() )
3036 PushString( aCall.GetString() );
3038 else
3040 PushDouble( aCall.GetValue() );
3043 else // error...
3044 PushError( GetError());
3046 else
3048 while( nParamCount-- > 0)
3050 Pop();
3052 PushError( errNoAddin );
3057 void ScInterpreter::ScMissing()
3059 PushTempToken( new FormulaMissingToken );
3062 #ifndef DISABLE_SCRIPTING
3064 static uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, ScDocument* pDok )
3066 uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW );
3067 uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
3068 OUString sCodeName;
3069 xProps->getPropertyValue("CodeName") >>= sCodeName;
3070 // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
3071 // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
3072 // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
3073 // the document in the future could fix this, especially IF the switching of the vba mode takes care to
3074 // create the special document module objects if they don't exist.
3075 BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager();
3077 uno::Reference< uno::XInterface > xIf;
3078 if ( pBasMgr && !pBasMgr->GetName().isEmpty() )
3080 OUString sProj( "Standard" );
3081 if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
3083 sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName();
3085 StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj );
3086 if ( pBasic )
3088 SbModule* pMod = pBasic->FindModule( sCodeName );
3089 if ( pMod )
3091 xIf = pMod->GetUnoModule();
3095 return uno::makeAny( xIf );
3098 static bool lcl_setVBARange( ScRange& aRange, ScDocument* pDok, SbxVariable* pPar )
3100 bool bOk = false;
3103 uno::Reference< uno::XInterface > xVBARange;
3104 uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
3105 uno::Sequence< uno::Any > aArgs(2);
3106 aArgs[0] = lcl_getSheetModule( xCellRange, pDok );
3107 aArgs[1] = uno::Any( xCellRange );
3108 xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( pDok->GetDocumentShell(), "ooo.vba.excel.Range", aArgs );
3109 if ( xVBARange.is() )
3111 OUString sDummy("A-Range");
3112 SbxObjectRef aObj = GetSbUnoObject( sDummy, uno::Any( xVBARange ) );
3113 SetSbUnoObjectDfltPropName( aObj );
3114 bOk = pPar->PutObject( aObj );
3117 catch( uno::Exception& )
3120 return bOk;
3123 #endif
3125 void ScInterpreter::ScMacro()
3128 #ifdef DISABLE_SCRIPTING
3129 PushNoValue(); // ohne DocShell kein CallBasic
3130 return;
3131 #else
3132 SbxBase::ResetError();
3134 sal_uInt8 nParamCount = GetByte();
3135 OUString aMacro( pCur->GetExternal() );
3137 SfxObjectShell* pDocSh = pDok->GetDocumentShell();
3138 if ( !pDocSh || !pDok->CheckMacroWarn() )
3140 PushNoValue(); // ohne DocShell kein CallBasic
3141 return;
3144 // keine Sicherheitsabfrage mehr vorneweg (nur CheckMacroWarn), das passiert im CallBasic
3146 // Wenn das Dok waehrend eines Basic-Calls geladen wurde,
3147 // ist das Sbx-Objekt evtl. nicht angelegt (?)
3148 // pDocSh->GetSbxObject();
3150 // Funktion ueber den einfachen Namen suchen,
3151 // dann aBasicStr, aMacroStr fuer SfxObjectShell::CallBasic zusammenbauen
3153 StarBASIC* pRoot = pDocSh->GetBasic();
3154 SbxVariable* pVar = pRoot->Find( aMacro, SbxCLASS_METHOD );
3155 if( !pVar || pVar->GetType() == SbxVOID || !pVar->ISA(SbMethod) )
3157 PushError( errNoMacro );
3158 return;
3161 bool bVolatileMacro = false;
3162 SbMethod* pMethod = (SbMethod*)pVar;
3164 SbModule* pModule = pMethod->GetModule();
3165 bool bUseVBAObjects = pModule->IsVBACompat();
3166 SbxObject* pObject = pModule->GetParent();
3167 OSL_ENSURE(pObject->IsA(TYPE(StarBASIC)), "No Basic found!");
3168 OUString aMacroStr = pObject->GetName() + "." + pModule->GetName() + "." + pMethod->GetName();
3169 OUString aBasicStr;
3170 if (pObject->GetParent())
3172 aBasicStr = pObject->GetParent()->GetName(); // Dokumentenbasic
3174 else
3176 aBasicStr = SFX_APP()->GetName(); // Applikationsbasic
3178 // Parameter-Array zusammenbauen
3180 SbxArrayRef refPar = new SbxArray;
3181 bool bOk = true;
3182 for( short i = nParamCount; i && bOk ; i-- )
3184 SbxVariable* pPar = refPar->Get( (sal_uInt16) i );
3185 sal_uInt8 nStackType = sal::static_int_cast<sal_uInt8>( GetStackType() );
3186 switch( nStackType )
3188 case svDouble:
3189 pPar->PutDouble( GetDouble() );
3190 break;
3191 case svString:
3192 pPar->PutString( GetString().getString() );
3193 break;
3194 case svExternalSingleRef:
3196 ScExternalRefCache::TokenRef pToken;
3197 PopExternalSingleRef(pToken);
3198 if ( pToken->GetType() == svString )
3199 pPar->PutString( pToken->GetString().getString() );
3200 else if ( pToken->GetType() == svDouble )
3201 pPar->PutDouble( pToken->GetDouble() );
3202 else
3204 SetError( errIllegalArgument );
3205 bOk = false;
3208 break;
3209 case svSingleRef:
3211 ScAddress aAdr;
3212 PopSingleRef( aAdr );
3213 if ( bUseVBAObjects )
3215 ScRange aRange( aAdr );
3216 bOk = lcl_setVBARange( aRange, pDok, pPar );
3218 else
3220 bOk = SetSbxVariable( pPar, aAdr );
3223 break;
3224 case svDoubleRef:
3226 SCCOL nCol1;
3227 SCROW nRow1;
3228 SCTAB nTab1;
3229 SCCOL nCol2;
3230 SCROW nRow2;
3231 SCTAB nTab2;
3232 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3233 if( nTab1 != nTab2 )
3235 SetError( errIllegalParameter );
3236 bOk = false;
3238 else
3240 if ( bUseVBAObjects )
3242 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3243 bOk = lcl_setVBARange( aRange, pDok, pPar );
3245 else
3247 SbxDimArrayRef refArray = new SbxDimArray;
3248 refArray->AddDim32( 1, nRow2 - nRow1 + 1 );
3249 refArray->AddDim32( 1, nCol2 - nCol1 + 1 );
3250 ScAddress aAdr( nCol1, nRow1, nTab1 );
3251 for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
3253 aAdr.SetRow( nRow );
3254 sal_Int32 nIdx[ 2 ];
3255 nIdx[ 0 ] = nRow-nRow1+1;
3256 for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
3258 aAdr.SetCol( nCol );
3259 nIdx[ 1 ] = nCol-nCol1+1;
3260 SbxVariable* p = refArray->Get32( nIdx );
3261 bOk = SetSbxVariable( p, aAdr );
3264 pPar->PutObject( refArray );
3268 break;
3269 case svExternalDoubleRef:
3270 case svMatrix:
3272 ScMatrixRef pMat = GetMatrix();
3273 SCSIZE nC, nR;
3274 if (pMat && !nGlobalError)
3276 pMat->GetDimensions(nC, nR);
3277 SbxDimArrayRef refArray = new SbxDimArray;
3278 refArray->AddDim32( 1, static_cast<sal_Int32>(nR) );
3279 refArray->AddDim32( 1, static_cast<sal_Int32>(nC) );
3280 for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
3282 sal_Int32 nIdx[ 2 ];
3283 nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1);
3284 for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
3286 nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1);
3287 SbxVariable* p = refArray->Get32( nIdx );
3288 if (pMat->IsString(nMatCol, nMatRow))
3290 p->PutString( pMat->GetString(nMatCol, nMatRow).getString() );
3292 else
3294 p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
3298 pPar->PutObject( refArray );
3300 else
3302 SetError( errIllegalParameter );
3305 break;
3306 default:
3307 SetError( errIllegalParameter );
3308 bOk = false;
3311 if( bOk )
3313 pDok->LockTable( aPos.Tab() );
3314 SbxVariableRef refRes = new SbxVariable;
3315 pDok->IncMacroInterpretLevel();
3316 ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar, refRes );
3317 pDok->DecMacroInterpretLevel();
3318 pDok->UnlockTable( aPos.Tab() );
3320 ScMacroManager* pMacroMgr = pDok->GetMacroManager();
3321 if (pMacroMgr)
3323 bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
3324 pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
3327 SbxDataType eResType = refRes->GetType();
3328 if( pVar->GetError() )
3330 SetError( errNoValue);
3332 if ( eRet != ERRCODE_NONE )
3334 PushNoValue();
3336 else if( eResType >= SbxINTEGER && eResType <= SbxDOUBLE )
3338 PushDouble( refRes->GetDouble() );
3340 else if ( eResType & SbxARRAY )
3342 SbxBase* pElemObj = refRes->GetObject();
3343 SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
3344 short nDim = pDimArray->GetDims();
3345 if ( 1 <= nDim && nDim <= 2 )
3347 sal_Int32 nCs, nCe, nRs, nRe;
3348 SCSIZE nC, nR;
3349 SCCOL nColIdx;
3350 SCROW nRowIdx;
3351 if ( nDim == 1 )
3352 { // array( cols ) eine Zeile, mehrere Spalten
3353 pDimArray->GetDim32( 1, nCs, nCe );
3354 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3355 nRs = nRe = 0;
3356 nR = 1;
3357 nColIdx = 0;
3358 nRowIdx = 1;
3360 else
3361 { // array( rows, cols )
3362 pDimArray->GetDim32( 1, nRs, nRe );
3363 nR = static_cast<SCSIZE>(nRe - nRs + 1);
3364 pDimArray->GetDim32( 2, nCs, nCe );
3365 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3366 nColIdx = 1;
3367 nRowIdx = 0;
3369 ScMatrixRef pMat = GetNewMat( nC, nR);
3370 if ( pMat )
3372 SbxVariable* pV;
3373 SbxDataType eType;
3374 for ( SCSIZE j=0; j < nR; j++ )
3376 sal_Int32 nIdx[ 2 ];
3377 // bei eindimensionalem array( cols ) wird nIdx[1]
3378 // von SbxDimArray::Get ignoriert
3379 nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j);
3380 for ( SCSIZE i=0; i < nC; i++ )
3382 nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i);
3383 pV = pDimArray->Get32( nIdx );
3384 eType = pV->GetType();
3385 if ( eType >= SbxINTEGER && eType <= SbxDOUBLE )
3387 pMat->PutDouble( pV->GetDouble(), i, j );
3389 else
3391 pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j);
3395 PushMatrix( pMat );
3397 else
3399 PushIllegalArgument();
3402 else
3404 PushNoValue();
3407 else
3409 PushString( refRes->GetOUString() );
3413 if (bVolatileMacro && meVolatileType == NOT_VOLATILE)
3414 meVolatileType = VOLATILE_MACRO;
3415 #endif
3418 #ifndef DISABLE_SCRIPTING
3420 bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
3422 bool bOk = true;
3423 ScRefCellValue aCell;
3424 aCell.assign(*pDok, rPos);
3425 if (!aCell.isEmpty())
3427 sal_uInt16 nErr;
3428 double nVal;
3429 switch (aCell.meType)
3431 case CELLTYPE_VALUE :
3432 nVal = GetValueCellValue(rPos, aCell.mfValue);
3433 pVar->PutDouble( nVal );
3434 break;
3435 case CELLTYPE_STRING :
3436 case CELLTYPE_EDIT :
3437 pVar->PutString(aCell.getString(pDok));
3438 break;
3439 case CELLTYPE_FORMULA :
3440 nErr = aCell.mpFormula->GetErrCode();
3441 if( !nErr )
3443 if (aCell.mpFormula->IsValue())
3445 nVal = aCell.mpFormula->GetValue();
3446 pVar->PutDouble(aCell.mpFormula->GetValue());
3448 else
3449 pVar->PutString(aCell.mpFormula->GetString().getString());
3451 else
3452 SetError( nErr ), bOk = false;
3453 break;
3454 default :
3455 pVar->PutDouble( 0.0 );
3458 else
3459 pVar->PutDouble( 0.0 );
3460 return bOk;
3463 #endif
3465 namespace {
3467 class FindByPointer : ::std::unary_function<ScInterpreterTableOpParams, bool>
3469 const ScInterpreterTableOpParams* mpTableOp;
3470 public:
3471 FindByPointer(const ScInterpreterTableOpParams* p) : mpTableOp(p) {}
3472 bool operator() (const ScInterpreterTableOpParams& val) const
3474 return &val == mpTableOp;
3480 void ScInterpreter::ScTableOp()
3482 sal_uInt8 nParamCount = GetByte();
3483 if (nParamCount != 3 && nParamCount != 5)
3485 PushIllegalParameter();
3486 return;
3488 ScInterpreterTableOpParams* pTableOp = new ScInterpreterTableOpParams;
3489 if (nParamCount == 5)
3491 PopSingleRef( pTableOp->aNew2 );
3492 PopSingleRef( pTableOp->aOld2 );
3494 PopSingleRef( pTableOp->aNew1 );
3495 PopSingleRef( pTableOp->aOld1 );
3496 PopSingleRef( pTableOp->aFormulaPos );
3498 pTableOp->bValid = true;
3499 pDok->aTableOpList.push_back( pTableOp );
3500 pDok->IncInterpreterTableOpLevel();
3502 bool bReuseLastParams = (pDok->aLastTableOpParams == *pTableOp);
3503 if ( bReuseLastParams )
3505 pTableOp->aNotifiedFormulaPos = pDok->aLastTableOpParams.aNotifiedFormulaPos;
3506 pTableOp->bRefresh = true;
3507 for ( ::std::vector< ScAddress >::const_iterator iBroadcast(
3508 pTableOp->aNotifiedFormulaPos.begin() );
3509 iBroadcast != pTableOp->aNotifiedFormulaPos.end();
3510 ++iBroadcast )
3511 { // emulate broadcast and indirectly collect cell pointers
3512 ScRefCellValue aCell;
3513 aCell.assign(*pDok, *iBroadcast);
3514 if (aCell.meType == CELLTYPE_FORMULA)
3515 aCell.mpFormula->SetTableOpDirty();
3518 else
3519 { // broadcast and indirectly collect cell pointers and positions
3520 pDok->SetTableOpDirty( pTableOp->aOld1 );
3521 if ( nParamCount == 5 )
3522 pDok->SetTableOpDirty( pTableOp->aOld2 );
3524 pTableOp->bCollectNotifications = false;
3526 ScRefCellValue aCell;
3527 aCell.assign(*pDok, pTableOp->aFormulaPos);
3528 if (aCell.meType == CELLTYPE_FORMULA)
3529 aCell.mpFormula->SetDirtyVar();
3530 if (aCell.hasNumeric())
3532 PushDouble(GetCellValue(pTableOp->aFormulaPos, aCell));
3534 else
3536 svl::SharedString aCellString;
3537 GetCellString(aCellString, aCell);
3538 PushString( aCellString );
3541 boost::ptr_vector< ScInterpreterTableOpParams >::iterator itr =
3542 ::std::find_if(pDok->aTableOpList.begin(), pDok->aTableOpList.end(), FindByPointer(pTableOp));
3543 if (itr != pDok->aTableOpList.end())
3544 pTableOp = pDok->aTableOpList.release(itr).release();
3546 // set dirty again once more to be able to recalculate original
3547 for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast(
3548 pTableOp->aNotifiedFormulaCells.begin() );
3549 iBroadcast != pTableOp->aNotifiedFormulaCells.end();
3550 ++iBroadcast )
3552 (*iBroadcast)->SetTableOpDirty();
3555 // save these params for next incarnation
3556 if ( !bReuseLastParams )
3557 pDok->aLastTableOpParams = *pTableOp;
3559 if (aCell.meType == CELLTYPE_FORMULA)
3561 aCell.mpFormula->SetDirtyVar();
3562 aCell.mpFormula->GetErrCode(); // recalculate original
3565 // Reset all dirty flags so next incarnation does really collect all cell
3566 // pointers during notifications and not just non-dirty ones, which may
3567 // happen if a formula cell is used by more than one TableOp block.
3568 for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast2(
3569 pTableOp->aNotifiedFormulaCells.begin() );
3570 iBroadcast2 != pTableOp->aNotifiedFormulaCells.end();
3571 ++iBroadcast2 )
3573 (*iBroadcast2)->ResetTableOpDirtyVar();
3575 delete pTableOp;
3577 pDok->DecInterpreterTableOpLevel();
3580 void ScInterpreter::ScDBArea()
3582 ScDBData* pDBData = pDok->GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex());
3583 if (pDBData)
3585 ScComplexRefData aRefData;
3586 aRefData.InitFlags();
3587 ScRange aRange;
3588 pDBData->GetArea(aRange);
3589 aRange.aEnd.SetTab(aRange.aStart.Tab());
3590 aRefData.SetRange(aRange, aPos);
3591 PushTempToken( new ScDoubleRefToken( aRefData ) );
3593 else
3594 PushError( errNoName);
3598 void ScInterpreter::ScColRowNameAuto()
3600 ScComplexRefData aRefData( static_cast<const ScToken*>(pCur)->GetDoubleRef() );
3601 ScRange aAbs = aRefData.toAbs(aPos);
3602 if (!ValidRange(aAbs))
3604 PushError( errNoRef );
3605 return;
3608 SCsCOL nStartCol;
3609 SCsROW nStartRow;
3611 // evtl. Begrenzung durch definierte ColRowNameRanges merken
3612 SCsCOL nCol2 = aAbs.aEnd.Col();
3613 SCsROW nRow2 = aAbs.aEnd.Row();
3614 // DataArea of the first cell
3615 nStartCol = aAbs.aStart.Col();
3616 nStartRow = aAbs.aStart.Row();
3617 aAbs.aEnd = aAbs.aStart; // Shrink to the top-left cell.
3620 // Expand to the data area. Only modify the end position.
3621 SCCOL nDACol1 = aAbs.aStart.Col(), nDACol2 = aAbs.aEnd.Col();
3622 SCROW nDARow1 = aAbs.aStart.Row(), nDARow2 = aAbs.aEnd.Row();
3623 pDok->GetDataArea(aAbs.aStart.Tab(), nDACol1, nDARow1, nDACol2, nDARow2, true, false);
3624 aAbs.aEnd.SetCol(nDACol2);
3625 aAbs.aEnd.SetRow(nDARow2);
3628 //! korrespondiert mit ScCompiler::GetToken
3629 if ( aRefData.Ref1.IsColRel() )
3630 { // ColName
3631 aAbs.aEnd.SetCol(nStartCol);
3632 // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
3633 if (aAbs.aEnd.Row() > nRow2)
3634 aAbs.aEnd.SetRow(nRow2);
3635 SCROW nMyRow;
3636 if ( aPos.Col() == nStartCol
3637 && nStartRow <= (nMyRow = aPos.Row()) && nMyRow <= aAbs.aEnd.Row())
3638 { // Formel in gleicher Spalte und innerhalb des Range
3639 if ( nMyRow == nStartRow )
3640 { // direkt unter dem Namen den Rest nehmen
3641 nStartRow++;
3642 if ( nStartRow > MAXROW )
3643 nStartRow = MAXROW;
3644 aAbs.aStart.SetRow(nStartRow);
3646 else
3647 { // weiter unten vom Namen bis zur Formelzelle
3648 aAbs.aEnd.SetRow(nMyRow - 1);
3652 else
3653 { // RowName
3654 aAbs.aEnd.SetRow(nStartRow);
3655 // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
3656 if (aAbs.aEnd.Col() > nCol2)
3657 aAbs.aEnd.SetCol(nCol2);
3658 SCCOL nMyCol;
3659 if ( aPos.Row() == nStartRow
3660 && nStartCol <= (nMyCol = aPos.Col()) && nMyCol <= aAbs.aEnd.Col())
3661 { // Formel in gleicher Zeile und innerhalb des Range
3662 if ( nMyCol == nStartCol )
3663 { // direkt neben dem Namen den Rest nehmen
3664 nStartCol++;
3665 if ( nStartCol > MAXCOL )
3666 nStartCol = MAXCOL;
3667 aAbs.aStart.SetCol(nStartCol);
3669 else
3670 { // weiter rechts vom Namen bis zur Formelzelle
3671 aAbs.aEnd.SetCol(nMyCol - 1);
3675 aRefData.SetRange(aAbs, aPos);
3676 PushTempToken( new ScDoubleRefToken( aRefData ) );
3679 // --- internals ------------------------------------------------------------
3682 void ScInterpreter::ScTTT()
3683 { // Temporaerer Test-Tanz, zum auspropieren von Funktionen etc.
3684 sal_uInt8 nParamCount = GetByte();
3685 // do something, nParamCount bei Pops runterzaehlen!
3687 // Stack aufraeumen
3688 while ( nParamCount-- > 0)
3689 Pop();
3690 PushError(errNoValue);
3693 // -------------------------------------------------------------------------
3696 ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc,
3697 const ScAddress& rPos, ScTokenArray& r ) :
3698 aCode( r ),
3699 aPos( rPos ),
3700 rArr( r ),
3701 pDok( pDoc ),
3702 mrStrPool(pDoc->GetSharedStringPool()),
3703 pTokenMatrixMap( NULL ),
3704 pMyFormulaCell( pCell ),
3705 pFormatter( pDoc->GetFormatTable() ),
3706 mnStringNoValueError( errNoValue),
3707 bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() ),
3708 meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE)
3711 if(pMyFormulaCell)
3713 sal_uInt8 cMatFlag = pMyFormulaCell->GetMatrixFlag();
3714 bMatrixFormula = ( cMatFlag == MM_FORMULA || cMatFlag == MM_FAKE );
3716 else
3717 bMatrixFormula = false;
3719 if (!bGlobalStackInUse)
3721 bGlobalStackInUse = true;
3722 if (!pGlobalStack)
3723 pGlobalStack = new ScTokenStack;
3724 pStackObj = pGlobalStack;
3726 else
3728 pStackObj = new ScTokenStack;
3730 pStack = pStackObj->pPointer;
3733 ScInterpreter::~ScInterpreter()
3735 // delete pStack;
3737 if ( pStackObj == pGlobalStack )
3738 bGlobalStackInUse = false;
3739 else
3740 delete pStackObj;
3741 if (pTokenMatrixMap)
3742 delete pTokenMatrixMap;
3745 void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig)
3747 maGlobalConfig = rConfig;
3750 const ScCalcConfig& ScInterpreter::GetGlobalConfig()
3752 return maGlobalConfig;
3755 void ScInterpreter::GlobalExit()
3757 OSL_ENSURE(!bGlobalStackInUse, "who is still using the TokenStack?");
3758 DELETEZ(pGlobalStack);
3761 namespace {
3763 double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
3765 if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
3767 SCROW nOffset = rPos.Row() - rMat.mnRow1;
3768 return rMat.mpMat->GetDouble(0, nOffset);
3771 if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
3773 SCROW nOffset = rPos.Col() - rMat.mnCol1;
3774 return rMat.mpMat->GetDouble(nOffset, 0);
3777 double fVal;
3778 rtl::math::setNan(&fVal);
3779 return fVal;
3784 StackVar ScInterpreter::Interpret()
3786 short nRetTypeExpr = NUMBERFORMAT_UNDEFINED;
3787 sal_uLong nRetIndexExpr = 0;
3788 sal_uInt16 nErrorFunction = 0;
3789 sal_uInt16 nErrorFunctionCount = 0;
3790 sal_uInt16 nStackBase;
3792 nGlobalError = 0;
3793 nStackBase = sp = maxsp = 0;
3794 nRetFmtType = NUMBERFORMAT_UNDEFINED;
3795 nFuncFmtType = NUMBERFORMAT_UNDEFINED;
3796 nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
3797 xResult = NULL;
3798 pJumpMatrix = NULL;
3799 glSubTotal = false;
3800 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
3802 // Once upon a time we used to have FP exceptions on, and there was a
3803 // Windows printer driver that kept switching off exceptions, so we had to
3804 // switch them back on again every time. Who knows if there isn't a driver
3805 // that keeps switching exceptions on, now that we run with exceptions off,
3806 // so reassure exceptions are really off.
3807 SAL_MATH_FPEXCEPTIONS_OFF();
3809 aCode.Reset();
3810 while( ( pCur = aCode.Next() ) != NULL
3811 && (!nGlobalError || nErrorFunction <= nErrorFunctionCount) )
3813 OpCode eOp = pCur->GetOpCode();
3814 cPar = pCur->GetByte();
3815 if ( eOp == ocPush )
3817 // RPN code push without error
3818 PushWithoutError( (FormulaToken&) *pCur );
3820 else if (pTokenMatrixMap &&
3821 !(eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChose) &&
3822 ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
3823 pTokenMatrixMap->end()) &&
3824 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
3826 // Path already calculated, reuse result.
3827 nStackBase = sp - pCur->GetParamCount();
3828 if ( nStackBase > sp )
3829 nStackBase = sp; // underflow?!?
3830 sp = nStackBase;
3831 PushTempToken( (*aTokenMatrixMapIter).second.get());
3833 else
3835 // previous expression determines the current number format
3836 nCurFmtType = nRetTypeExpr;
3837 nCurFmtIndex = nRetIndexExpr;
3838 // default function's format, others are set if needed
3839 nFuncFmtType = NUMBERFORMAT_NUMBER;
3840 nFuncFmtIndex = 0;
3842 if ( eOp == ocIf || eOp == ocChose || eOp == ocIfError || eOp == ocIfNA )
3843 nStackBase = sp; // don't mess around with the jumps
3844 else
3846 // Convert parameters to matrix if in array/matrix formula and
3847 // parameters of function indicate doing so. Create JumpMatrix
3848 // if necessary.
3849 if ( MatrixParameterConversion() )
3851 eOp = ocNone; // JumpMatrix created
3852 nStackBase = sp;
3854 else
3855 nStackBase = sp - pCur->GetParamCount();
3857 if ( nStackBase > sp )
3858 nStackBase = sp; // underflow?!?
3860 switch( eOp )
3862 case ocSep:
3863 case ocClose: // pushed by the compiler
3864 case ocMissing : ScMissing(); break;
3865 case ocMacro : ScMacro(); break;
3866 case ocDBArea : ScDBArea(); break;
3867 case ocColRowNameAuto : ScColRowNameAuto(); break;
3868 case ocIf : ScIfJump(); break;
3869 case ocIfError : ScIfError( false ); break;
3870 case ocIfNA : ScIfError( true ); break;
3871 case ocChose : ScChoseJump(); break;
3872 case ocAdd : ScAdd(); break;
3873 case ocSub : ScSub(); break;
3874 case ocMul : ScMul(); break;
3875 case ocDiv : ScDiv(); break;
3876 case ocAmpersand : ScAmpersand(); break;
3877 case ocPow : ScPow(); break;
3878 case ocEqual : ScEqual(); break;
3879 case ocNotEqual : ScNotEqual(); break;
3880 case ocLess : ScLess(); break;
3881 case ocGreater : ScGreater(); break;
3882 case ocLessEqual : ScLessEqual(); break;
3883 case ocGreaterEqual : ScGreaterEqual(); break;
3884 case ocAnd : ScAnd(); break;
3885 case ocOr : ScOr(); break;
3886 case ocXor : ScXor(); break;
3887 case ocIntersect : ScIntersect(); break;
3888 case ocRange : ScRangeFunc(); break;
3889 case ocUnion : ScUnionFunc(); break;
3890 case ocNot : ScNot(); break;
3891 case ocNegSub :
3892 case ocNeg : ScNeg(); break;
3893 case ocPercentSign : ScPercentSign(); break;
3894 case ocPi : ScPi(); break;
3895 case ocRandom : ScRandom(); break;
3896 case ocTrue : ScTrue(); break;
3897 case ocFalse : ScFalse(); break;
3898 case ocGetActDate : ScGetActDate(); break;
3899 case ocGetActTime : ScGetActTime(); break;
3900 case ocNotAvail : PushError( NOTAVAILABLE); break;
3901 case ocDeg : ScDeg(); break;
3902 case ocRad : ScRad(); break;
3903 case ocSin : ScSin(); break;
3904 case ocCos : ScCos(); break;
3905 case ocTan : ScTan(); break;
3906 case ocCot : ScCot(); break;
3907 case ocArcSin : ScArcSin(); break;
3908 case ocArcCos : ScArcCos(); break;
3909 case ocArcTan : ScArcTan(); break;
3910 case ocArcCot : ScArcCot(); break;
3911 case ocSinHyp : ScSinHyp(); break;
3912 case ocCosHyp : ScCosHyp(); break;
3913 case ocTanHyp : ScTanHyp(); break;
3914 case ocCotHyp : ScCotHyp(); break;
3915 case ocArcSinHyp : ScArcSinHyp(); break;
3916 case ocArcCosHyp : ScArcCosHyp(); break;
3917 case ocArcTanHyp : ScArcTanHyp(); break;
3918 case ocArcCotHyp : ScArcCotHyp(); break;
3919 case ocCosecant : ScCosecant(); break;
3920 case ocSecant : ScSecant(); break;
3921 case ocCosecantHyp : ScCosecantHyp(); break;
3922 case ocSecantHyp : ScSecantHyp(); break;
3923 case ocExp : ScExp(); break;
3924 case ocLn : ScLn(); break;
3925 case ocLog10 : ScLog10(); break;
3926 case ocSqrt : ScSqrt(); break;
3927 case ocFact : ScFact(); break;
3928 case ocGetYear : ScGetYear(); break;
3929 case ocGetMonth : ScGetMonth(); break;
3930 case ocGetDay : ScGetDay(); break;
3931 case ocGetDayOfWeek : ScGetDayOfWeek(); break;
3932 case ocWeek : ScGetWeekOfYear(); break;
3933 case ocEasterSunday : ScEasterSunday(); break;
3934 case ocGetHour : ScGetHour(); break;
3935 case ocGetMin : ScGetMin(); break;
3936 case ocGetSec : ScGetSec(); break;
3937 case ocPlusMinus : ScPlusMinus(); break;
3938 case ocAbs : ScAbs(); break;
3939 case ocInt : ScInt(); break;
3940 case ocEven : ScEven(); break;
3941 case ocOdd : ScOdd(); break;
3942 case ocPhi : ScPhi(); break;
3943 case ocGauss : ScGauss(); break;
3944 case ocStdNormDist : ScStdNormDist(); break;
3945 case ocFisher : ScFisher(); break;
3946 case ocFisherInv : ScFisherInv(); break;
3947 case ocIsEmpty : ScIsEmpty(); break;
3948 case ocIsString : ScIsString(); break;
3949 case ocIsNonString : ScIsNonString(); break;
3950 case ocIsLogical : ScIsLogical(); break;
3951 case ocType : ScType(); break;
3952 case ocCell : ScCell(); break;
3953 case ocIsRef : ScIsRef(); break;
3954 case ocIsValue : ScIsValue(); break;
3955 case ocIsFormula : ScIsFormula(); break;
3956 case ocFormula : ScFormula(); break;
3957 case ocIsNA : ScIsNV(); break;
3958 case ocIsErr : ScIsErr(); break;
3959 case ocIsError : ScIsError(); break;
3960 case ocIsEven : ScIsEven(); break;
3961 case ocIsOdd : ScIsOdd(); break;
3962 case ocN : ScN(); break;
3963 case ocGetDateValue : ScGetDateValue(); break;
3964 case ocGetTimeValue : ScGetTimeValue(); break;
3965 case ocCode : ScCode(); break;
3966 case ocTrim : ScTrim(); break;
3967 case ocUpper : ScUpper(); break;
3968 case ocPropper : ScPropper(); break;
3969 case ocLower : ScLower(); break;
3970 case ocLen : ScLen(); break;
3971 case ocT : ScT(); break;
3972 case ocClean : ScClean(); break;
3973 case ocValue : ScValue(); break;
3974 case ocNumberValue : ScNumberValue(); break;
3975 case ocChar : ScChar(); break;
3976 case ocArcTan2 : ScArcTan2(); break;
3977 case ocMod : ScMod(); break;
3978 case ocPower : ScPower(); break;
3979 case ocRound : ScRound(); break;
3980 case ocRoundUp : ScRoundUp(); break;
3981 case ocTrunc :
3982 case ocRoundDown : ScRoundDown(); break;
3983 case ocCeil : ScCeil(); break;
3984 case ocFloor : ScFloor(); break;
3985 case ocSumProduct : ScSumProduct(); break;
3986 case ocSumSQ : ScSumSQ(); break;
3987 case ocSumX2MY2 : ScSumX2MY2(); break;
3988 case ocSumX2DY2 : ScSumX2DY2(); break;
3989 case ocSumXMY2 : ScSumXMY2(); break;
3990 case ocLog : ScLog(); break;
3991 case ocGCD : ScGCD(); break;
3992 case ocLCM : ScLCM(); break;
3993 case ocGetDate : ScGetDate(); break;
3994 case ocGetTime : ScGetTime(); break;
3995 case ocGetDiffDate : ScGetDiffDate(); break;
3996 case ocGetDiffDate360 : ScGetDiffDate360(); break;
3997 case ocGetDateDif : ScGetDateDif(); break;
3998 case ocMin : ScMin( false ); break;
3999 case ocMinA : ScMin( true ); break;
4000 case ocMax : ScMax( false ); break;
4001 case ocMaxA : ScMax( true ); break;
4002 case ocSum : ScSum(); break;
4003 case ocProduct : ScProduct(); break;
4004 case ocNPV : ScNPV(); break;
4005 case ocIRR : ScIRR(); break;
4006 case ocMIRR : ScMIRR(); break;
4007 case ocISPMT : ScISPMT(); break;
4008 case ocAverage : ScAverage( false ); break;
4009 case ocAverageA : ScAverage( true ); break;
4010 case ocCount : ScCount(); break;
4011 case ocCount2 : ScCount2(); break;
4012 case ocVar :
4013 case ocVarS : ScVar( false ); break;
4014 case ocVarA : ScVar( true ); break;
4015 case ocVarP :
4016 case ocVarP_MS : ScVarP( false ); break;
4017 case ocVarPA : ScVarP( true ); break;
4018 case ocStDev :
4019 case ocStDevS : ScStDev( false ); break;
4020 case ocStDevA : ScStDev( true ); break;
4021 case ocStDevP :
4022 case ocStDevP_MS : ScStDevP( false ); break;
4023 case ocStDevPA : ScStDevP( true ); break;
4024 case ocBW : ScBW(); break;
4025 case ocDIA : ScDIA(); break;
4026 case ocGDA : ScGDA(); break;
4027 case ocGDA2 : ScGDA2(); break;
4028 case ocVBD : ScVDB(); break;
4029 case ocLaufz : ScLaufz(); break;
4030 case ocLIA : ScLIA(); break;
4031 case ocRMZ : ScRMZ(); break;
4032 case ocColumns : ScColumns(); break;
4033 case ocRows : ScRows(); break;
4034 case ocTables : ScTables(); break;
4035 case ocColumn : ScColumn(); break;
4036 case ocRow : ScRow(); break;
4037 case ocTable : ScTable(); break;
4038 case ocZGZ : ScZGZ(); break;
4039 case ocZW : ScZW(); break;
4040 case ocZZR : ScZZR(); break;
4041 case ocZins : ScZins(); break;
4042 case ocFilterXML : ScFilterXML(); break;
4043 case ocWebservice : ScWebservice(); break;
4044 case ocZinsZ : ScZinsZ(); break;
4045 case ocKapz : ScKapz(); break;
4046 case ocKumZinsZ : ScKumZinsZ(); break;
4047 case ocKumKapZ : ScKumKapZ(); break;
4048 case ocEffektiv : ScEffektiv(); break;
4049 case ocNominal : ScNominal(); break;
4050 case ocSubTotal : ScSubTotal(); break;
4051 case ocDBSum : ScDBSum(); break;
4052 case ocDBCount : ScDBCount(); break;
4053 case ocDBCount2 : ScDBCount2(); break;
4054 case ocDBAverage : ScDBAverage(); break;
4055 case ocDBGet : ScDBGet(); break;
4056 case ocDBMax : ScDBMax(); break;
4057 case ocDBMin : ScDBMin(); break;
4058 case ocDBProduct : ScDBProduct(); break;
4059 case ocDBStdDev : ScDBStdDev(); break;
4060 case ocDBStdDevP : ScDBStdDevP(); break;
4061 case ocDBVar : ScDBVar(); break;
4062 case ocDBVarP : ScDBVarP(); break;
4063 case ocIndirect : ScIndirect(); break;
4064 case ocAddress : ScAddressFunc(); break;
4065 case ocMatch : ScMatch(); break;
4066 case ocCountEmptyCells : ScCountEmptyCells(); break;
4067 case ocCountIf : ScCountIf(); break;
4068 case ocSumIf : ScSumIf(); break;
4069 case ocAverageIf : ScAverageIf(); break;
4070 case ocSumIfs : ScSumIfs(); break;
4071 case ocAverageIfs : ScAverageIfs(); break;
4072 case ocCountIfs : ScCountIfs(); break;
4073 case ocLookup : ScLookup(); break;
4074 case ocVLookup : ScVLookup(); break;
4075 case ocHLookup : ScHLookup(); break;
4076 case ocIndex : ScIndex(); break;
4077 case ocMultiArea : ScMultiArea(); break;
4078 case ocOffset : ScOffset(); break;
4079 case ocAreas : ScAreas(); break;
4080 case ocCurrency : ScCurrency(); break;
4081 case ocReplace : ScReplace(); break;
4082 case ocFixed : ScFixed(); break;
4083 case ocFind : ScFind(); break;
4084 case ocExact : ScExact(); break;
4085 case ocLeft : ScLeft(); break;
4086 case ocRight : ScRight(); break;
4087 case ocSearch : ScSearch(); break;
4088 case ocMid : ScMid(); break;
4089 case ocText : ScText(); break;
4090 case ocSubstitute : ScSubstitute(); break;
4091 case ocRept : ScRept(); break;
4092 case ocConcat : ScConcat(); break;
4093 case ocMatValue : ScMatValue(); break;
4094 case ocMatrixUnit : ScEMat(); break;
4095 case ocMatDet : ScMatDet(); break;
4096 case ocMatInv : ScMatInv(); break;
4097 case ocMatMult : ScMatMult(); break;
4098 case ocMatTrans : ScMatTrans(); break;
4099 case ocMatRef : ScMatRef(); break;
4100 case ocB : ScB(); break;
4101 case ocNormDist : ScNormDist(); break;
4102 case ocExpDist :
4103 case ocExpDist_MS : ScExpDist(); break;
4104 case ocBinomDist :
4105 case ocBinomDist_MS : ScBinomDist(); break;
4106 case ocPoissonDist :
4107 case ocPoissonDist_MS : ScPoissonDist(); break;
4108 case ocKombin : ScKombin(); break;
4109 case ocKombin2 : ScKombin2(); break;
4110 case ocVariationen : ScVariationen(); break;
4111 case ocVariationen2 : ScVariationen2(); break;
4112 case ocHypGeomDist : ScHypGeomDist(); break;
4113 case ocHypGeomDist_MS : ScHypGeomDist_MS(); break;
4114 case ocLogNormDist : ScLogNormDist(); break;
4115 case ocTDist : ScTDist(); break;
4116 case ocFDist :
4117 case ocFDist_RT : ScFDist(); break;
4118 case ocFDist_LT : ScFDist_LT(); break;
4119 case ocChiDist :
4120 case ocChiDist_MS : ScChiDist(); break;
4121 case ocChiSqDist : ScChiSqDist(); break;
4122 case ocChiSqDist_MS : ScChiSqDist_MS(); break;
4123 case ocStandard : ScStandard(); break;
4124 case ocAveDev : ScAveDev(); break;
4125 case ocDevSq : ScDevSq(); break;
4126 case ocKurt : ScKurt(); break;
4127 case ocSchiefe : ScSkew(); break;
4128 case ocSkewp : ScSkewp(); break;
4129 case ocModalValue : ScModalValue(); break;
4130 case ocMedian : ScMedian(); break;
4131 case ocGeoMean : ScGeoMean(); break;
4132 case ocHarMean : ScHarMean(); break;
4133 case ocWeibull :
4134 case ocWeibull_MS : ScWeibull(); break;
4135 case ocBinomInv :
4136 case ocKritBinom : ScCritBinom(); break;
4137 case ocNegBinomVert : ScNegBinomDist(); break;
4138 case ocNoName : ScNoName(); break;
4139 case ocBad : ScBadName(); break;
4140 case ocZTest : ScZTest(); break;
4141 case ocTTest : ScTTest(); break;
4142 case ocFTest :
4143 case ocFTest_MS : ScFTest(); break;
4144 case ocRank : ScRank(); break;
4145 case ocPercentile : ScPercentile(); break;
4146 case ocPercentrank : ScPercentrank(); break;
4147 case ocLarge : ScLarge(); break;
4148 case ocSmall : ScSmall(); break;
4149 case ocFrequency : ScFrequency(); break;
4150 case ocQuartile : ScQuartile(); break;
4151 case ocNormInv : ScNormInv(); break;
4152 case ocSNormInv : ScSNormInv(); break;
4153 case ocConfidence :
4154 case ocConfidence_N : ScConfidence(); break;
4155 case ocConfidence_T : ScConfidenceT(); break;
4156 case ocTrimMean : ScTrimMean(); break;
4157 case ocProb : ScProbability(); break;
4158 case ocCorrel : ScCorrel(); break;
4159 case ocCovar :
4160 case ocCovarianceP : ScCovarianceP(); break;
4161 case ocCovarianceS : ScCovarianceS(); break;
4162 case ocPearson : ScPearson(); break;
4163 case ocRSQ : ScRSQ(); break;
4164 case ocSTEYX : ScSTEXY(); break;
4165 case ocSlope : ScSlope(); break;
4166 case ocIntercept : ScIntercept(); break;
4167 case ocTrend : ScTrend(); break;
4168 case ocGrowth : ScGrowth(); break;
4169 case ocRGP : ScRGP(); break;
4170 case ocRKP : ScRKP(); break;
4171 case ocForecast : ScForecast(); break;
4172 case ocGammaLn : ScLogGamma(); break;
4173 case ocGamma : ScGamma(); break;
4174 case ocGammaDist : ScGammaDist(); break;
4175 case ocGammaInv : ScGammaInv(); break;
4176 case ocChiTest :
4177 case ocChiTest_MS : ScChiTest(); break;
4178 case ocChiInv :
4179 case ocChiInv_MS : ScChiInv(); break;
4180 case ocChiSqInv :
4181 case ocChiSqInv_MS : ScChiSqInv(); break;
4182 case ocTInv : ScTInv(); break;
4183 case ocFInv :
4184 case ocFInv_RT : ScFInv(); break;
4185 case ocFInv_LT : ScFInv_LT(); break;
4186 case ocLogInv : ScLogNormInv(); break;
4187 case ocBetaDist : ScBetaDist(); break;
4188 case ocBetaDist_MS : ScBetaDist_MS(); break;
4189 case ocBetaInv :
4190 case ocBetaInv_MS : ScBetaInv(); break;
4191 case ocExternal : ScExternal(); break;
4192 case ocTableOp : ScTableOp(); break;
4193 case ocStop : break;
4194 case ocErrorType : ScErrorType(); break;
4195 case ocCurrent : ScCurrent(); break;
4196 case ocStyle : ScStyle(); break;
4197 case ocDde : ScDde(); break;
4198 case ocBase : ScBase(); break;
4199 case ocDecimal : ScDecimal(); break;
4200 case ocConvert : ScConvert(); break;
4201 case ocEuroConvert : ScEuroConvert(); break;
4202 case ocRoman : ScRoman(); break;
4203 case ocArabic : ScArabic(); break;
4204 case ocInfo : ScInfo(); break;
4205 case ocHyperLink : ScHyperLink(); break;
4206 case ocBahtText : ScBahtText(); break;
4207 case ocGetPivotData : ScGetPivotData(); break;
4208 case ocJis : ScJis(); break;
4209 case ocAsc : ScAsc(); break;
4210 case ocLenB : ScLenB(); break;
4211 case ocRightB : ScRightB(); break;
4212 case ocLeftB : ScLeftB(); break;
4213 case ocMidB : ScMidB(); break;
4214 case ocUnicode : ScUnicode(); break;
4215 case ocUnichar : ScUnichar(); break;
4216 case ocBitAnd : ScBitAnd(); break;
4217 case ocBitOr : ScBitOr(); break;
4218 case ocBitXor : ScBitXor(); break;
4219 case ocBitRshift : ScBitRshift(); break;
4220 case ocBitLshift : ScBitLshift(); break;
4221 case ocTTT : ScTTT(); break;
4222 case ocDebugVar : ScDebugVar(); break;
4223 case ocNone : nFuncFmtType = NUMBERFORMAT_UNDEFINED; break;
4224 default : PushError( errUnknownOpCode); break;
4227 // If the function pushed a subroutine as result, continue with
4228 // execution of the subroutine.
4229 if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall
4230 /* && pStack[sp-1]->GetType() == svSubroutine */)
4232 Pop(); continue;
4235 if (FormulaCompiler::IsOpCodeVolatile(eOp))
4236 meVolatileType = VOLATILE;
4238 // Remember result matrix in case it could be reused.
4239 if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
4240 pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
4241 pStack[sp-1]));
4243 // outer function determines format of an expression
4244 if ( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
4246 nRetTypeExpr = nFuncFmtType;
4247 // inherit the format index only for currency formats
4248 nRetIndexExpr = ( nFuncFmtType == NUMBERFORMAT_CURRENCY ?
4249 nFuncFmtIndex : 0 );
4253 // Need a clean stack environment for the JumpMatrix to work.
4254 if (nGlobalError && eOp != ocPush && sp > nStackBase + 1)
4256 // Not all functions pop all parameters in case an error is
4257 // generated. Clean up stack. Assumes that every function pushes a
4258 // result, may be arbitrary in case of error.
4259 const FormulaToken* pLocalResult = pStack[ sp - 1 ];
4260 while (sp > nStackBase)
4261 Pop();
4262 PushTempToken( *pLocalResult );
4265 bool bGotResult;
4268 bGotResult = false;
4269 sal_uInt8 nLevel = 0;
4270 if ( GetStackType( ++nLevel ) == svJumpMatrix )
4271 ; // nothing
4272 else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4273 ; // nothing
4274 else
4275 nLevel = 0;
4276 if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
4277 bGotResult = JumpMatrix( nLevel );
4278 else
4279 pJumpMatrix = NULL;
4280 } while ( bGotResult );
4283 // Functions that evaluate an error code and directly set nGlobalError to 0,
4284 // usage: switch( OpCode ) { CASE_OCERRFUNC statements; }
4285 #define CASE_OCERRFUNC \
4286 case ocCount : \
4287 case ocCount2 : \
4288 case ocErrorType : \
4289 case ocIsEmpty : \
4290 case ocIsErr : \
4291 case ocIsError : \
4292 case ocIsFormula : \
4293 case ocIsLogical : \
4294 case ocIsNA : \
4295 case ocIsNonString : \
4296 case ocIsRef : \
4297 case ocIsString : \
4298 case ocIsValue : \
4299 case ocN : \
4300 case ocType : \
4301 case ocIfError : \
4302 case ocIfNA :
4304 switch ( eOp )
4306 CASE_OCERRFUNC
4307 ++ nErrorFunction;
4308 default:
4309 ; // nothing
4311 if ( nGlobalError )
4313 if ( !nErrorFunctionCount )
4314 { // count of errorcode functions in formula
4315 for ( FormulaToken* t = rArr.FirstRPN(); t; t = rArr.NextRPN() )
4317 switch ( t->GetOpCode() )
4319 CASE_OCERRFUNC
4320 ++nErrorFunctionCount;
4321 default:
4322 ; // nothing
4326 if ( nErrorFunction >= nErrorFunctionCount )
4327 ++nErrorFunction; // that's it, error => terminate
4331 // End: obtain result
4333 if( sp )
4335 pCur = pStack[ sp-1 ];
4336 if( pCur->GetOpCode() == ocPush )
4338 switch( pCur->GetType() )
4340 case svEmptyCell:
4341 ; // nothing
4342 break;
4343 case svError:
4344 nGlobalError = pCur->GetError();
4345 break;
4346 case svDouble :
4347 if ( nFuncFmtType == NUMBERFORMAT_UNDEFINED )
4349 nRetTypeExpr = NUMBERFORMAT_NUMBER;
4350 nRetIndexExpr = 0;
4352 break;
4353 case svString :
4354 nRetTypeExpr = NUMBERFORMAT_TEXT;
4355 nRetIndexExpr = 0;
4356 break;
4357 case svSingleRef :
4359 ScAddress aAdr;
4360 PopSingleRef( aAdr );
4361 if( !nGlobalError )
4362 PushCellResultToken( false, aAdr,
4363 &nRetTypeExpr, &nRetIndexExpr);
4365 break;
4366 case svRefList :
4367 PopError(); // maybe #REF! takes precedence over #VALUE!
4368 PushError( errNoValue);
4369 break;
4370 case svDoubleRef :
4372 if ( bMatrixFormula )
4373 { // create matrix for {=A1:A5}
4374 PopDoubleRefPushMatrix();
4375 ScMatrixRef xMat = PopMatrix();
4376 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4378 else
4380 ScRange aRange;
4381 PopDoubleRef( aRange );
4382 ScAddress aAdr;
4383 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr))
4384 PushCellResultToken( false, aAdr,
4385 &nRetTypeExpr, &nRetIndexExpr);
4388 break;
4389 case svExternalDoubleRef:
4391 ScMatrixRef xMat;
4392 PopExternalDoubleRef(xMat);
4393 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4395 break;
4396 case svMatrix :
4398 sc::RangeMatrix aMat = PopRangeMatrix();
4399 if (aMat.isRangeValid())
4401 // This matrix represents a range reference. Apply implicit intersection.
4402 double fVal = applyImplicitIntersection(aMat, aPos);
4403 if (rtl::math::isNan(fVal))
4404 PushError(errCellNoValue);
4405 else
4406 PushInt(fVal);
4408 else
4409 // This is a normal matrix.
4410 QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr);
4412 break;
4413 case svExternalSingleRef:
4415 ScExternalRefCache::TokenRef pToken;
4416 ScExternalRefCache::CellFormat aFmt;
4417 PopExternalSingleRef(pToken, &aFmt);
4418 if (nGlobalError)
4419 break;
4421 PushTempToken(*pToken);
4423 if (aFmt.mbIsSet)
4425 nFuncFmtType = aFmt.mnType;
4426 nFuncFmtIndex = aFmt.mnIndex;
4429 break;
4430 default :
4431 SetError( errUnknownStackVariable);
4434 else
4435 SetError( errUnknownStackVariable);
4437 else
4438 SetError( errNoCode);
4440 if( nRetTypeExpr != NUMBERFORMAT_UNDEFINED )
4442 nRetFmtType = nRetTypeExpr;
4443 nRetFmtIndex = nRetIndexExpr;
4445 else if( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
4447 nRetFmtType = nFuncFmtType;
4448 nRetFmtIndex = nFuncFmtIndex;
4450 else
4451 nRetFmtType = NUMBERFORMAT_NUMBER;
4452 // inherit the format index only for currency formats
4453 if ( nRetFmtType != NUMBERFORMAT_CURRENCY )
4454 nRetFmtIndex = 0;
4456 if (nGlobalError && GetStackType() != svError )
4457 PushError( nGlobalError);
4459 // THE final result.
4460 xResult = PopToken();
4461 if (!xResult)
4462 xResult = new FormulaErrorToken( errUnknownStackVariable);
4464 // release tokens in expression stack
4465 FormulaToken** p = pStack;
4466 while( maxsp-- )
4467 (*p++)->DecRef();
4469 StackVar eType = xResult->GetType();
4470 if (eType == svMatrix)
4471 // Results are immutable in case they would be reused as input for new
4472 // interpreters.
4473 static_cast<ScToken*>(xResult.get())->GetMatrix()->SetImmutable( true);
4474 return eType;
4477 svl::SharedString ScInterpreter::GetStringResult() const
4479 return xResult->GetString();
4482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */