fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / core / tool / interpr4.cxx
blob44e25c7786cf478348f683ffa2cb6b053d810612
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 <config_features.h>
22 #include "interpre.hxx"
24 #include <rangelst.hxx>
25 #include <sfx2/app.hxx>
26 #include <sfx2/docfile.hxx>
27 #include <sfx2/objsh.hxx>
28 #include <sfx2/docfilt.hxx>
29 #include <basic/sbmeth.hxx>
30 #include <basic/sbmod.hxx>
31 #include <basic/sbstar.hxx>
32 #include <basic/sbx.hxx>
33 #include <basic/sbxobj.hxx>
34 #include <basic/sbuno.hxx>
35 #include <svl/zforlist.hxx>
36 #include <svl/sharedstringpool.hxx>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <signal.h>
41 #include <com/sun/star/table/XCellRange.hpp>
42 #include <com/sun/star/sheet/XSheetCellRange.hpp>
43 #include <comphelper/processfactory.hxx>
45 #include "global.hxx"
46 #include "dbdata.hxx"
47 #include "formulacell.hxx"
48 #include "callform.hxx"
49 #include "addincol.hxx"
50 #include "document.hxx"
51 #include "dociter.hxx"
52 #include "docoptio.hxx"
53 #include "scmatrix.hxx"
54 #include "adiasync.hxx"
55 #include "sc.hrc"
56 #include "cellsuno.hxx"
57 #include "optuno.hxx"
58 #include "rangeseq.hxx"
59 #include "addinlis.hxx"
60 #include "jumpmatrix.hxx"
61 #include "parclass.hxx"
62 #include "externalrefmgr.hxx"
63 #include <formula/FormulaCompiler.hxx>
64 #include "macromgr.hxx"
65 #include "doubleref.hxx"
66 #include "queryparam.hxx"
67 #include "tokenarray.hxx"
69 #include <math.h>
70 #include <float.h>
71 #include <map>
72 #include <algorithm>
73 #include <functional>
74 #include <basic/basmgr.hxx>
75 #include <vbahelper/vbaaccesshelper.hxx>
76 #include <memory>
77 #include <boost/scoped_array.hpp>
79 using namespace com::sun::star;
80 using namespace formula;
81 using ::std::unique_ptr;
83 #define ADDIN_MAXSTRLEN 256
85 //-----------------------------static data -----------------
87 // document access functions
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 ;
108 void ScInterpreter::ReplaceCell( SCCOL& rCol, SCROW& rRow, SCTAB& rTab )
110 ScAddress aCellPos( rCol, rRow, rTab );
111 size_t ListSize = pDok->aTableOpList.size();
112 for ( size_t i = 0; i < ListSize; ++i )
114 ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
115 if ( aCellPos == pTOp->aOld1 )
117 rCol = pTOp->aNew1.Col();
118 rRow = pTOp->aNew1.Row();
119 rTab = pTOp->aNew1.Tab();
120 return ;
122 else if ( aCellPos == pTOp->aOld2 )
124 rCol = pTOp->aNew2.Col();
125 rRow = pTOp->aNew2.Row();
126 rTab = pTOp->aNew2.Tab();
127 return ;
132 bool ScInterpreter::IsTableOpInRange( const ScRange& rRange )
134 if ( rRange.aStart == rRange.aEnd )
135 return false; // not considered to be a range in TableOp sense
137 // we can't replace a single cell in a range
138 size_t ListSize = pDok->aTableOpList.size();
139 for ( size_t i = 0; i < ListSize; ++i )
141 ScInterpreterTableOpParams* pTOp = &pDok->aTableOpList[ i ];
142 if ( rRange.In( pTOp->aOld1 ) )
143 return true;
144 if ( rRange.In( pTOp->aOld2 ) )
145 return true;
147 return false;
150 sal_uLong ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, ScRefCellValue& rCell )
152 sal_uLong nFormat;
153 sal_uInt16 nErr;
154 if (rCell.isEmpty())
156 nFormat = pDok->GetNumberFormat( rPos );
157 nErr = 0;
159 else
161 if (rCell.meType == CELLTYPE_FORMULA)
162 nErr = rCell.mpFormula->GetErrCode();
163 else
164 nErr = 0;
165 nFormat = pDok->GetNumberFormat( rPos );
168 SetError(nErr);
169 return nFormat;
172 /// Only ValueCell, formula cells already store the result rounded.
173 double ScInterpreter::GetValueCellValue( const ScAddress& rPos, double fOrig )
175 if ( bCalcAsShown && fOrig != 0.0 )
177 sal_uLong nFormat = pDok->GetNumberFormat( rPos );
178 fOrig = pDok->RoundValueAsShown( fOrig, nFormat );
180 return fOrig;
183 sal_uInt16 ScInterpreter::GetCellErrCode( const ScRefCellValue& rCell )
185 return rCell.meType == CELLTYPE_FORMULA ? rCell.mpFormula->GetErrCode() : 0;
188 double ScInterpreter::ConvertStringToValue( const OUString& rStr )
190 double fValue = ScGlobal::ConvertStringToValue( rStr, maCalcConfig, nGlobalError, mnStringNoValueError,
191 pFormatter, nCurFmtType);
192 if (nGlobalError)
193 SetError(nGlobalError);
194 return fValue;
197 double ScInterpreter::ConvertStringToValue( const OUString& rStr, sal_uInt16& rError, short& rCurFmtType )
199 return ScGlobal::ConvertStringToValue( rStr, maCalcConfig, rError, mnStringNoValueError, pFormatter, rCurFmtType);
202 double ScInterpreter::GetCellValue( const ScAddress& rPos, ScRefCellValue& rCell )
204 sal_uInt16 nErr = nGlobalError;
205 nGlobalError = 0;
206 double nVal = GetCellValueOrZero(rPos, rCell);
207 if ( !nGlobalError || nGlobalError == errCellNoValue )
208 nGlobalError = nErr;
209 return nVal;
212 double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, ScRefCellValue& rCell )
214 double fValue = 0.0;
216 CellType eType = rCell.meType;
217 switch (eType)
219 case CELLTYPE_FORMULA:
221 ScFormulaCell* pFCell = rCell.mpFormula;
222 sal_uInt16 nErr = pFCell->GetErrCode();
223 if( !nErr )
225 if (pFCell->IsValue())
227 fValue = pFCell->GetValue();
228 pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex,
229 rPos );
231 else
233 fValue = ConvertStringToValue(pFCell->GetString().getString());
236 else
238 fValue = 0.0;
239 SetError(nErr);
242 break;
243 case CELLTYPE_VALUE:
245 fValue = rCell.mfValue;
246 nCurFmtIndex = pDok->GetNumberFormat( rPos );
247 nCurFmtType = pFormatter->GetType( nCurFmtIndex );
248 if ( bCalcAsShown && fValue != 0.0 )
249 fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex );
251 break;
252 case CELLTYPE_STRING:
253 case CELLTYPE_EDIT:
255 // SUM(A1:A2) differs from A1+A2. No good. But people insist on
256 // it ... #i5658#
257 OUString aStr = rCell.getString(pDok);
258 fValue = ConvertStringToValue( aStr );
260 break;
261 case CELLTYPE_NONE:
262 fValue = 0.0; // empty or broadcaster cell
263 break;
266 return fValue;
269 void ScInterpreter::GetCellString( svl::SharedString& rStr, ScRefCellValue& rCell )
271 sal_uInt16 nErr = 0;
273 switch (rCell.meType)
275 case CELLTYPE_STRING:
276 case CELLTYPE_EDIT:
277 rStr = mrStrPool.intern(rCell.getString(pDok));
278 break;
279 case CELLTYPE_FORMULA:
281 ScFormulaCell* pFCell = rCell.mpFormula;
282 nErr = pFCell->GetErrCode();
283 if (pFCell->IsValue())
285 double fVal = pFCell->GetValue();
286 sal_uLong nIndex = pFormatter->GetStandardFormat(
287 css::util::NumberFormat::NUMBER,
288 ScGlobal::eLnge);
289 OUString aStr;
290 pFormatter->GetInputLineString(fVal, nIndex, aStr);
291 rStr = mrStrPool.intern(aStr);
293 else
294 rStr = pFCell->GetString();
296 break;
297 case CELLTYPE_VALUE:
299 double fVal = rCell.mfValue;
300 sal_uLong nIndex = pFormatter->GetStandardFormat(
301 css::util::NumberFormat::NUMBER,
302 ScGlobal::eLnge);
303 OUString aStr;
304 pFormatter->GetInputLineString(fVal, nIndex, aStr);
305 rStr = mrStrPool.intern(aStr);
307 break;
308 default:
309 rStr = svl::SharedString::getEmptyString();
310 break;
313 SetError(nErr);
316 bool ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
317 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, sal_uInt8* pCellArr)
320 // Old Add-Ins are hard limited to sal_uInt16 values.
321 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
322 #error Add check for columns > USHRT_MAX!
323 #endif
324 if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
325 return false;
327 sal_uInt16 nCount = 0;
328 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
329 *p++ = static_cast<sal_uInt16>(nCol1);
330 *p++ = static_cast<sal_uInt16>(nRow1);
331 *p++ = static_cast<sal_uInt16>(nTab1);
332 *p++ = static_cast<sal_uInt16>(nCol2);
333 *p++ = static_cast<sal_uInt16>(nRow2);
334 *p++ = static_cast<sal_uInt16>(nTab2);
335 sal_uInt16* pCount = p;
336 *p++ = 0;
337 sal_uInt16 nPos = 14;
338 SCTAB nTab = nTab1;
339 ScAddress aAdr;
340 while (nTab <= nTab2)
342 aAdr.SetTab( nTab );
343 SCROW nRow = nRow1;
344 while (nRow <= nRow2)
346 aAdr.SetRow( nRow );
347 SCCOL nCol = nCol1;
348 while (nCol <= nCol2)
350 aAdr.SetCol( nCol );
352 ScRefCellValue aCell;
353 aCell.assign(*pDok, aAdr);
354 if (!aCell.isEmpty())
356 sal_uInt16 nErr = 0;
357 double nVal = 0.0;
358 bool bOk = true;
359 switch (aCell.meType)
361 case CELLTYPE_VALUE :
362 nVal = GetValueCellValue(aAdr, aCell.mfValue);
363 break;
364 case CELLTYPE_FORMULA :
365 if (aCell.mpFormula->IsValue())
367 nErr = aCell.mpFormula->GetErrCode();
368 nVal = aCell.mpFormula->GetValue();
370 else
371 bOk = false;
372 break;
373 default :
374 bOk = false;
375 break;
377 if (bOk)
379 if ((nPos + (4 * sizeof(sal_uInt16)) + sizeof(double)) > MAXARRSIZE)
380 return false;
381 *p++ = static_cast<sal_uInt16>(nCol);
382 *p++ = static_cast<sal_uInt16>(nRow);
383 *p++ = static_cast<sal_uInt16>(nTab);
384 *p++ = nErr;
385 memcpy( p, &nVal, sizeof(double));
386 nPos += 8 + sizeof(double);
387 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
388 nCount++;
391 nCol++;
393 nRow++;
395 nTab++;
397 *pCount = nCount;
398 return true;
401 bool ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
402 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
403 sal_uInt8* pCellArr)
406 // Old Add-Ins are hard limited to sal_uInt16 values.
407 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
408 #error Add check for columns > USHRT_MAX!
409 #endif
410 if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
411 return false;
413 sal_uInt16 nCount = 0;
414 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
415 *p++ = static_cast<sal_uInt16>(nCol1);
416 *p++ = static_cast<sal_uInt16>(nRow1);
417 *p++ = static_cast<sal_uInt16>(nTab1);
418 *p++ = static_cast<sal_uInt16>(nCol2);
419 *p++ = static_cast<sal_uInt16>(nRow2);
420 *p++ = static_cast<sal_uInt16>(nTab2);
421 sal_uInt16* pCount = p;
422 *p++ = 0;
423 sal_uInt16 nPos = 14;
424 SCTAB nTab = nTab1;
425 while (nTab <= nTab2)
427 SCROW nRow = nRow1;
428 while (nRow <= nRow2)
430 SCCOL nCol = nCol1;
431 while (nCol <= nCol2)
433 ScRefCellValue aCell;
434 aCell.assign(*pDok, ScAddress(nCol, nRow, nTab));
435 if (!aCell.isEmpty())
437 OUString aStr;
438 sal_uInt16 nErr = 0;
439 bool bOk = true;
440 switch (aCell.meType)
442 case CELLTYPE_STRING:
443 case CELLTYPE_EDIT:
444 aStr = aCell.getString(pDok);
445 break;
446 case CELLTYPE_FORMULA:
447 if (!aCell.mpFormula->IsValue())
449 nErr = aCell.mpFormula->GetErrCode();
450 aStr = aCell.mpFormula->GetString().getString();
452 else
453 bOk = false;
454 break;
455 default :
456 bOk = false;
457 break;
459 if (bOk)
461 OString aTmp(OUStringToOString(aStr,
462 osl_getThreadTextEncoding()));
463 // Old Add-Ins are limited to sal_uInt16 string
464 // lengths, and room for pad byte check.
465 if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 )
466 return false;
467 // Append a 0-pad-byte if string length is odd
468 // MUST be sal_uInt16
469 sal_uInt16 nStrLen = (sal_uInt16) aTmp.getLength();
470 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
472 if (((sal_uLong)nPos + (5 * sizeof(sal_uInt16)) + nLen) > MAXARRSIZE)
473 return false;
474 *p++ = static_cast<sal_uInt16>(nCol);
475 *p++ = static_cast<sal_uInt16>(nRow);
476 *p++ = static_cast<sal_uInt16>(nTab);
477 *p++ = nErr;
478 *p++ = nLen;
479 memcpy( p, aTmp.getStr(), nStrLen + 1);
480 nPos += 10 + nStrLen + 1;
481 sal_uInt8* q = ( pCellArr + nPos );
482 if( (nStrLen & 1) == 0 )
483 *q++ = 0, nPos++;
484 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
485 nCount++;
488 nCol++;
490 nRow++;
492 nTab++;
494 *pCount = nCount;
495 return true;
498 bool ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
499 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
500 sal_uInt8* pCellArr)
503 // Old Add-Ins are hard limited to sal_uInt16 values.
504 #if MAXCOLCOUNT_DEFINE > USHRT_MAX
505 #error Add check for columns > USHRT_MAX!
506 #endif
507 if (nRow1 > USHRT_MAX || nRow2 > USHRT_MAX)
508 return false;
510 sal_uInt16 nCount = 0;
511 sal_uInt16* p = reinterpret_cast<sal_uInt16*>(pCellArr);
512 *p++ = static_cast<sal_uInt16>(nCol1);
513 *p++ = static_cast<sal_uInt16>(nRow1);
514 *p++ = static_cast<sal_uInt16>(nTab1);
515 *p++ = static_cast<sal_uInt16>(nCol2);
516 *p++ = static_cast<sal_uInt16>(nRow2);
517 *p++ = static_cast<sal_uInt16>(nTab2);
518 sal_uInt16* pCount = p;
519 *p++ = 0;
520 sal_uInt16 nPos = 14;
521 SCTAB nTab = nTab1;
522 ScAddress aAdr;
523 while (nTab <= nTab2)
525 aAdr.SetTab( nTab );
526 SCROW nRow = nRow1;
527 while (nRow <= nRow2)
529 aAdr.SetRow( nRow );
530 SCCOL nCol = nCol1;
531 while (nCol <= nCol2)
533 aAdr.SetCol( nCol );
534 ScRefCellValue aCell;
535 aCell.assign(*pDok, aAdr);
536 if (!aCell.isEmpty())
538 sal_uInt16 nErr = 0;
539 sal_uInt16 nType = 0; // 0 = Zahl; 1 = String
540 double nVal = 0.0;
541 OUString aStr;
542 bool bOk = true;
543 switch (aCell.meType)
545 case CELLTYPE_STRING :
546 case CELLTYPE_EDIT :
547 aStr = aCell.getString(pDok);
548 nType = 1;
549 break;
550 case CELLTYPE_VALUE :
551 nVal = GetValueCellValue(aAdr, aCell.mfValue);
552 break;
553 case CELLTYPE_FORMULA :
554 nErr = aCell.mpFormula->GetErrCode();
555 if (aCell.mpFormula->IsValue())
556 nVal = aCell.mpFormula->GetValue();
557 else
558 aStr = aCell.mpFormula->GetString().getString();
559 break;
560 default :
561 bOk = false;
562 break;
564 if (bOk)
566 if ((nPos + (5 * sizeof(sal_uInt16))) > MAXARRSIZE)
567 return false;
568 *p++ = static_cast<sal_uInt16>(nCol);
569 *p++ = static_cast<sal_uInt16>(nRow);
570 *p++ = static_cast<sal_uInt16>(nTab);
571 *p++ = nErr;
572 *p++ = nType;
573 nPos += 10;
574 if (nType == 0)
576 if ((nPos + sizeof(double)) > MAXARRSIZE)
577 return false;
578 memcpy( p, &nVal, sizeof(double));
579 nPos += sizeof(double);
581 else
583 OString aTmp(OUStringToOString(aStr,
584 osl_getThreadTextEncoding()));
585 // Old Add-Ins are limited to sal_uInt16 string
586 // lengths, and room for pad byte check.
587 if ( aTmp.getLength() > SAL_MAX_UINT16 - 2 )
588 return false;
589 // Append a 0-pad-byte if string length is odd
590 // MUST be sal_uInt16
591 sal_uInt16 nStrLen = (sal_uInt16) aTmp.getLength();
592 sal_uInt16 nLen = ( nStrLen + 2 ) & ~1;
593 if ( ((sal_uLong)nPos + 2 + nLen) > MAXARRSIZE)
594 return false;
595 *p++ = nLen;
596 memcpy( p, aTmp.getStr(), nStrLen + 1);
597 nPos += 2 + nStrLen + 1;
598 sal_uInt8* q = ( pCellArr + nPos );
599 if( (nStrLen & 1) == 0 )
600 *q++ = 0, nPos++;
602 nCount++;
603 p = reinterpret_cast<sal_uInt16*>( pCellArr + nPos );
606 nCol++;
608 nRow++;
610 nTab++;
612 *pCount = nCount;
613 return true;
616 // Stack operations
618 // Also releases a TempToken if appropriate.
620 void ScInterpreter::PushWithoutError( FormulaToken& r )
622 if ( sp >= MAXSTACK )
623 SetError( errStackOverflow );
624 else
626 nCurFmtType = css::util::NumberFormat::UNDEFINED;
627 r.IncRef();
628 if( sp >= maxsp )
629 maxsp = sp + 1;
630 else
631 pStack[ sp ]->DecRef();
632 pStack[ sp ] = &r;
633 ++sp;
637 void ScInterpreter::Push( FormulaToken& r )
639 if ( sp >= MAXSTACK )
640 SetError( errStackOverflow );
641 else
643 if (nGlobalError)
645 if (r.GetType() == svError)
647 r.SetError( nGlobalError);
648 PushWithoutError( r);
650 else
651 PushWithoutError( *(new FormulaErrorToken( nGlobalError)));
653 else
654 PushWithoutError( r);
658 void ScInterpreter::PushTempToken( FormulaToken* p )
660 if ( sp >= MAXSTACK )
662 SetError( errStackOverflow );
663 if (!p->GetRef())
664 // p is a dangling pointer hereafter!
665 p->Delete();
667 else
669 if (nGlobalError)
671 if (p->GetType() == svError)
673 p->SetError( nGlobalError);
674 PushTempTokenWithoutError( p);
676 else
678 if (!p->GetRef())
679 // p is a dangling pointer hereafter!
680 p->Delete();
681 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
684 else
685 PushTempTokenWithoutError( p);
689 void ScInterpreter::PushTempTokenWithoutError( FormulaToken* p )
691 p->IncRef();
692 if ( sp >= MAXSTACK )
694 SetError( errStackOverflow );
695 // p may be a dangling pointer hereafter!
696 p->DecRef();
698 else
700 if( sp >= maxsp )
701 maxsp = sp + 1;
702 else
703 pStack[ sp ]->DecRef();
704 pStack[ sp ] = p;
705 ++sp;
709 void ScInterpreter::PushTempToken( const FormulaToken& r )
711 if (!IfErrorPushError())
712 PushTempTokenWithoutError( r.Clone());
715 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
716 const ScAddress & rAddress, short * pRetTypeExpr, sal_uLong * pRetIndexExpr )
718 ScRefCellValue aCell;
719 aCell.assign(*pDok, rAddress);
720 if (aCell.hasEmptyValue())
722 bool bInherited = (aCell.meType == CELLTYPE_FORMULA);
723 if (pRetTypeExpr && pRetIndexExpr)
724 pDok->GetNumberFormatInfo(*pRetTypeExpr, *pRetIndexExpr, rAddress);
725 PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString));
726 return;
729 sal_uInt16 nErr = 0;
730 if (aCell.meType == CELLTYPE_FORMULA)
731 nErr = aCell.mpFormula->GetErrCode();
733 if (nErr)
735 PushError( nErr);
736 if (pRetTypeExpr)
737 *pRetTypeExpr = css::util::NumberFormat::UNDEFINED;
738 if (pRetIndexExpr)
739 *pRetIndexExpr = 0;
741 else if (aCell.hasString())
743 svl::SharedString aRes;
744 GetCellString( aRes, aCell);
745 PushString( aRes);
746 if (pRetTypeExpr)
747 *pRetTypeExpr = css::util::NumberFormat::TEXT;
748 if (pRetIndexExpr)
749 *pRetIndexExpr = 0;
751 else
753 double fVal = GetCellValue(rAddress, aCell);
754 PushDouble( fVal);
755 if (pRetTypeExpr)
756 *pRetTypeExpr = nCurFmtType;
757 if (pRetIndexExpr)
758 *pRetIndexExpr = nCurFmtIndex;
762 // Simply throw away TOS.
764 void ScInterpreter::Pop()
766 if( sp )
767 sp--;
768 else
769 SetError(errUnknownStackVariable);
772 // Simply throw away TOS and set error code, used with ocIsError et al.
774 void ScInterpreter::PopError()
776 if( sp )
778 sp--;
779 if (pStack[sp]->GetType() == svError)
780 nGlobalError = pStack[sp]->GetError();
782 else
783 SetError(errUnknownStackVariable);
786 FormulaTokenRef ScInterpreter::PopToken()
788 if (sp)
790 sp--;
791 FormulaToken* p = pStack[ sp ];
792 if (p->GetType() == svError)
793 nGlobalError = p->GetError();
794 return p;
796 else
797 SetError(errUnknownStackVariable);
798 return NULL;
801 double ScInterpreter::PopDouble()
803 nCurFmtType = css::util::NumberFormat::NUMBER;
804 nCurFmtIndex = 0;
805 if( sp )
807 --sp;
808 FormulaToken* p = pStack[ sp ];
809 switch (p->GetType())
811 case svError:
812 nGlobalError = p->GetError();
813 break;
814 case svDouble:
815 return p->GetDouble();
816 case svEmptyCell:
817 case svMissing:
818 return 0.0;
819 default:
820 SetError( errIllegalArgument);
823 else
824 SetError( errUnknownStackVariable);
825 return 0.0;
828 svl::SharedString ScInterpreter::PopString()
830 nCurFmtType = css::util::NumberFormat::TEXT;
831 nCurFmtIndex = 0;
832 if( sp )
834 --sp;
835 FormulaToken* p = pStack[ sp ];
836 switch (p->GetType())
838 case svError:
839 nGlobalError = p->GetError();
840 break;
841 case svString:
842 return p->GetString();
843 case svEmptyCell:
844 case svMissing:
845 return svl::SharedString::getEmptyString();
846 default:
847 SetError( errIllegalArgument);
850 else
851 SetError( errUnknownStackVariable);
853 return svl::SharedString::getEmptyString();
856 void ScInterpreter::ValidateRef( const ScSingleRefData & rRef )
858 SCCOL nCol;
859 SCROW nRow;
860 SCTAB nTab;
861 SingleRefToVars( rRef, nCol, nRow, nTab);
864 void ScInterpreter::ValidateRef( const ScComplexRefData & rRef )
866 ValidateRef( rRef.Ref1);
867 ValidateRef( rRef.Ref2);
870 void ScInterpreter::ValidateRef( const ScRefList & rRefList )
872 ScRefList::const_iterator it( rRefList.begin());
873 ScRefList::const_iterator end( rRefList.end());
874 for ( ; it != end; ++it)
876 ValidateRef( *it);
880 void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef,
881 SCCOL & rCol, SCROW & rRow, SCTAB & rTab )
883 if ( rRef.IsColRel() )
884 rCol = aPos.Col() + rRef.Col();
885 else
886 rCol = rRef.Col();
888 if ( rRef.IsRowRel() )
889 rRow = aPos.Row() + rRef.Row();
890 else
891 rRow = rRef.Row();
893 if ( rRef.IsTabRel() )
894 rTab = aPos.Tab() + rRef.Tab();
895 else
896 rTab = rRef.Tab();
898 if( !ValidCol( rCol) || rRef.IsColDeleted() )
899 SetError( errNoRef ), rCol = 0;
900 if( !ValidRow( rRow) || rRef.IsRowDeleted() )
901 SetError( errNoRef ), rRow = 0;
902 if( !ValidTab( rTab, pDok->GetTableCount() - 1) || rRef.IsTabDeleted() )
903 SetError( errNoRef ), rTab = 0;
906 void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
908 if( sp )
910 --sp;
911 FormulaToken* p = pStack[ sp ];
912 switch (p->GetType())
914 case svError:
915 nGlobalError = p->GetError();
916 break;
917 case svSingleRef:
918 SingleRefToVars( *p->GetSingleRef(), rCol, rRow, rTab);
919 if ( !pDok->aTableOpList.empty() )
920 ReplaceCell( rCol, rRow, rTab );
921 break;
922 default:
923 SetError( errIllegalParameter);
926 else
927 SetError( errUnknownStackVariable);
930 void ScInterpreter::PopSingleRef( ScAddress& rAdr )
932 if( sp )
934 --sp;
935 FormulaToken* p = pStack[ sp ];
936 switch (p->GetType())
938 case svError:
939 nGlobalError = p->GetError();
940 break;
941 case svSingleRef:
943 SCCOL nCol;
944 SCROW nRow;
945 SCTAB nTab;
946 SingleRefToVars( *p->GetSingleRef(), nCol, nRow, nTab);
947 rAdr.Set( nCol, nRow, nTab );
948 if ( !pDok->aTableOpList.empty() )
949 ReplaceCell( rAdr );
951 break;
952 default:
953 SetError( errIllegalParameter);
956 else
957 SetError( errUnknownStackVariable);
960 void ScInterpreter::DoubleRefToVars( const formula::FormulaToken* p,
961 SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
962 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
963 bool bDontCheckForTableOp )
965 const ScComplexRefData& rCRef = *p->GetDoubleRef();
966 SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1);
967 SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2);
968 if ( !pDok->aTableOpList.empty() && !bDontCheckForTableOp )
970 ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 );
971 if ( IsTableOpInRange( aRange ) )
972 SetError( errIllegalParameter );
976 ScDBRangeBase* ScInterpreter::PopDBDoubleRef()
978 StackVar eType = GetStackType();
979 switch (eType)
981 case svUnknown:
982 SetError(errUnknownStackVariable);
983 break;
984 case svError:
985 PopError();
986 break;
987 case svDoubleRef:
989 SCCOL nCol1, nCol2;
990 SCROW nRow1, nRow2;
991 SCTAB nTab1, nTab2;
992 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, false);
993 if (nGlobalError)
994 break;
995 return new ScDBInternalRange(pDok,
996 ScRange(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2));
998 case svMatrix:
999 case svExternalDoubleRef:
1001 ScMatrixRef pMat;
1002 if (eType == svMatrix)
1003 pMat = PopMatrix();
1004 else
1005 PopExternalDoubleRef(pMat);
1006 if (nGlobalError)
1007 break;
1008 return new ScDBExternalRange(pDok, pMat);
1010 default:
1011 SetError( errIllegalParameter);
1014 return NULL;
1017 void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1018 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1019 bool bDontCheckForTableOp )
1021 if( sp )
1023 --sp;
1024 FormulaToken* p = pStack[ sp ];
1025 switch (p->GetType())
1027 case svError:
1028 nGlobalError = p->GetError();
1029 break;
1030 case svDoubleRef:
1031 DoubleRefToVars( p, rCol1, rRow1, rTab1, rCol2, rRow2, rTab2,
1032 bDontCheckForTableOp);
1033 break;
1034 default:
1035 SetError( errIllegalParameter);
1038 else
1039 SetError( errUnknownStackVariable);
1042 void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef,
1043 ScRange & rRange, bool bDontCheckForTableOp )
1045 SCCOL nCol;
1046 SCROW nRow;
1047 SCTAB nTab;
1048 SingleRefToVars( rCRef.Ref1, nCol, nRow, nTab);
1049 rRange.aStart.Set( nCol, nRow, nTab );
1050 SingleRefToVars( rCRef.Ref2, nCol, nRow, nTab);
1051 rRange.aEnd.Set( nCol, nRow, nTab );
1052 rRange.Justify();
1053 if (! pDok->aTableOpList.empty() && !bDontCheckForTableOp )
1055 if ( IsTableOpInRange( rRange ) )
1056 SetError( errIllegalParameter );
1060 void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList )
1062 if (sp)
1064 formula::FormulaToken* pToken = pStack[ sp-1 ];
1065 switch (pToken->GetType())
1067 case svError:
1068 nGlobalError = pToken->GetError();
1069 break;
1070 case svDoubleRef:
1071 --sp;
1072 DoubleRefToRange( *pToken->GetDoubleRef(), rRange);
1073 break;
1074 case svRefList:
1076 const ScRefList* pList = pToken->GetRefList();
1077 if (rRefInList < pList->size())
1079 DoubleRefToRange( (*pList)[rRefInList], rRange);
1080 if (++rRefInList < pList->size())
1081 ++rParam;
1082 else
1084 --sp;
1085 rRefInList = 0;
1088 else
1090 --sp;
1091 rRefInList = 0;
1092 SetError( errIllegalParameter);
1095 break;
1096 default:
1097 SetError( errIllegalParameter);
1100 else
1101 SetError( errUnknownStackVariable);
1104 void ScInterpreter::PopDoubleRef( ScRange& rRange, bool bDontCheckForTableOp )
1106 if( sp )
1108 --sp;
1109 FormulaToken* p = pStack[ sp ];
1110 switch (p->GetType())
1112 case svError:
1113 nGlobalError = p->GetError();
1114 break;
1115 case svDoubleRef:
1116 DoubleRefToRange( *p->GetDoubleRef(), rRange, bDontCheckForTableOp);
1117 break;
1118 default:
1119 SetError( errIllegalParameter);
1122 else
1123 SetError( errUnknownStackVariable);
1126 void ScInterpreter::PopExternalSingleRef(sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef)
1128 if (!sp)
1130 SetError(errUnknownStackVariable);
1131 return;
1134 --sp;
1135 FormulaToken* p = pStack[sp];
1136 StackVar eType = p->GetType();
1138 if (eType == svError)
1140 nGlobalError = p->GetError();
1141 return;
1144 if (eType != svExternalSingleRef)
1146 SetError( errIllegalParameter);
1147 return;
1150 rFileId = p->GetIndex();
1151 rTabName = p->GetString().getString();
1152 rRef = *p->GetSingleRef();
1155 void ScInterpreter::PopExternalSingleRef(ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1157 sal_uInt16 nFileId;
1158 OUString aTabName;
1159 ScSingleRefData aData;
1160 PopExternalSingleRef(nFileId, aTabName, aData, rToken, pFmt);
1163 void ScInterpreter::PopExternalSingleRef(
1164 sal_uInt16& rFileId, OUString& rTabName, ScSingleRefData& rRef,
1165 ScExternalRefCache::TokenRef& rToken, ScExternalRefCache::CellFormat* pFmt)
1167 PopExternalSingleRef(rFileId, rTabName, rRef);
1168 if (nGlobalError)
1169 return;
1171 ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1172 const OUString* pFile = pRefMgr->getExternalFileName(rFileId);
1173 if (!pFile)
1175 SetError(errNoName);
1176 return;
1179 if (rRef.IsTabRel())
1181 OSL_FAIL("ScCompiler::GetToken: external single reference must have an absolute table reference!");
1182 SetError(errNoRef);
1183 return;
1186 ScAddress aAddr = rRef.toAbs(aPos);
1187 ScExternalRefCache::CellFormat aFmt;
1188 ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
1189 rFileId, rTabName, aAddr, &aPos, NULL, &aFmt);
1191 if (!xNew)
1193 SetError(errNoRef);
1194 return;
1197 rToken = xNew;
1198 if (pFmt)
1199 *pFmt = aFmt;
1202 void ScInterpreter::PopExternalDoubleRef(sal_uInt16& rFileId, OUString& rTabName, ScComplexRefData& rRef)
1204 if (!sp)
1206 SetError(errUnknownStackVariable);
1207 return;
1210 --sp;
1211 FormulaToken* p = pStack[sp];
1212 StackVar eType = p->GetType();
1214 if (eType == svError)
1216 nGlobalError = p->GetError();
1217 return;
1220 if (eType != svExternalDoubleRef)
1222 SetError( errIllegalParameter);
1223 return;
1226 rFileId = p->GetIndex();
1227 rTabName = p->GetString().getString();
1228 rRef = *p->GetDoubleRef();
1231 void ScInterpreter::PopExternalDoubleRef(ScExternalRefCache::TokenArrayRef& rArray)
1233 sal_uInt16 nFileId;
1234 OUString aTabName;
1235 ScComplexRefData aData;
1236 PopExternalDoubleRef(nFileId, aTabName, aData);
1237 if (nGlobalError)
1238 return;
1240 GetExternalDoubleRef(nFileId, aTabName, aData, rArray);
1241 if (nGlobalError)
1242 return;
1245 void ScInterpreter::PopExternalDoubleRef(ScMatrixRef& rMat)
1247 ScExternalRefCache::TokenArrayRef pArray;
1248 PopExternalDoubleRef(pArray);
1249 if (nGlobalError)
1250 return;
1252 // For now, we only support single range data for external
1253 // references, which means the array should only contain a
1254 // single matrix token.
1255 formula::FormulaToken* p = pArray->First();
1256 if (!p || p->GetType() != svMatrix)
1257 SetError( errIllegalParameter);
1258 else
1260 rMat = p->GetMatrix();
1261 if (!rMat)
1262 SetError( errUnknownVariable);
1266 void ScInterpreter::GetExternalDoubleRef(
1267 sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rData, ScExternalRefCache::TokenArrayRef& rArray)
1269 ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
1270 const OUString* pFile = pRefMgr->getExternalFileName(nFileId);
1271 if (!pFile)
1273 SetError(errNoName);
1274 return;
1276 if (rData.Ref1.IsTabRel() || rData.Ref2.IsTabRel())
1278 OSL_FAIL("ScCompiler::GetToken: external double reference must have an absolute table reference!");
1279 SetError(errNoRef);
1280 return;
1283 ScComplexRefData aData(rData);
1284 ScRange aRange = aData.toAbs(aPos);
1285 ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(
1286 nFileId, rTabName, aRange, &aPos);
1288 if (!pArray)
1290 SetError(errIllegalArgument);
1291 return;
1294 formula::FormulaToken* pToken = pArray->First();
1295 if (pToken->GetType() != svMatrix)
1297 SetError(errIllegalArgument);
1298 return;
1301 if (pArray->Next())
1303 // Can't handle more than one matrix per parameter.
1304 SetError( errIllegalArgument);
1305 return;
1308 rArray = pArray;
1311 bool ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
1313 switch ( GetStackType() )
1315 case svDoubleRef :
1317 ScRange aRange;
1318 PopDoubleRef( aRange, true );
1319 return DoubleRefToPosSingleRef( aRange, rAdr );
1321 case svSingleRef :
1323 PopSingleRef( rAdr );
1324 return true;
1326 default:
1327 PopError();
1328 SetError( errNoRef );
1330 return false;
1333 void ScInterpreter::PopDoubleRefPushMatrix()
1335 if ( GetStackType() == svDoubleRef )
1337 ScMatrixRef pMat = GetMatrix();
1338 if ( pMat )
1339 PushMatrix( pMat );
1340 else
1341 PushIllegalParameter();
1343 else
1344 SetError( errNoRef );
1347 ScTokenMatrixMap* ScInterpreter::CreateTokenMatrixMap()
1349 return new ScTokenMatrixMap;
1352 bool ScInterpreter::ConvertMatrixParameters()
1354 sal_uInt16 nParams = pCur->GetParamCount();
1355 OSL_ENSURE( nParams <= sp, "ConvertMatrixParameters: stack/param count mismatch");
1356 SCSIZE nJumpCols = 0, nJumpRows = 0;
1357 for ( sal_uInt16 i=1; i <= nParams && i <= sp; ++i )
1359 FormulaToken* p = pStack[ sp - i ];
1360 if ( p->GetOpCode() != ocPush && p->GetOpCode() != ocMissing)
1362 OSL_FAIL( "ConvertMatrixParameters: not a push");
1364 else
1366 switch ( p->GetType() )
1368 case svDouble:
1369 case svString:
1370 case svSingleRef:
1371 case svExternalSingleRef:
1372 case svMissing:
1373 case svError:
1374 case svEmptyCell:
1375 // nothing to do
1376 break;
1377 case svMatrix:
1379 if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
1380 == ScParameterClassification::Value )
1381 { // only if single value expected
1382 ScMatrixRef pMat = p->GetMatrix();
1383 if ( !pMat )
1384 SetError( errUnknownVariable);
1385 else
1387 SCSIZE nCols, nRows;
1388 pMat->GetDimensions( nCols, nRows);
1389 if ( nJumpCols < nCols )
1390 nJumpCols = nCols;
1391 if ( nJumpRows < nRows )
1392 nJumpRows = nRows;
1396 break;
1397 case svDoubleRef:
1399 ScParameterClassification::Type eType =
1400 ScParameterClassification::GetParameterType( pCur, nParams - i);
1401 if ( eType != ScParameterClassification::Reference &&
1402 eType != ScParameterClassification::ReferenceOrForceArray &&
1403 // For scalar Value: convert to Array/JumpMatrix
1404 // only if in array formula context, else (function
1405 // has ForceArray or ReferenceOrForceArray
1406 // parameter *somewhere else*) pick a normal
1407 // position dependent implicit intersection later.
1408 (eType != ScParameterClassification::Value || bMatrixFormula || pCur->HasForceArray()))
1410 SCCOL nCol1, nCol2;
1411 SCROW nRow1, nRow2;
1412 SCTAB nTab1, nTab2;
1413 DoubleRefToVars( p, nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1414 // Make sure the map exists, created if not.
1415 GetTokenMatrixMap();
1416 ScMatrixRef pMat = CreateMatrixFromDoubleRef( p,
1417 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1418 if (pMat)
1420 if ( eType == ScParameterClassification::Value )
1421 { // only if single value expected
1422 if ( nJumpCols < static_cast<SCSIZE>(nCol2 - nCol1 + 1) )
1423 nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
1424 if ( nJumpRows < static_cast<SCSIZE>(nRow2 - nRow1 + 1) )
1425 nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
1427 formula::FormulaToken* pNew = new ScMatrixToken( pMat);
1428 pNew->IncRef();
1429 pStack[ sp - i ] = pNew;
1430 p->DecRef(); // p may be dead now!
1434 break;
1435 case svExternalDoubleRef:
1437 ScParameterClassification::Type eType =
1438 ScParameterClassification::GetParameterType( pCur, nParams - i);
1439 if (eType == ScParameterClassification::Array)
1441 sal_uInt16 nFileId = p->GetIndex();
1442 OUString aTabName = p->GetString().getString();
1443 const ScComplexRefData& rRef = *p->GetDoubleRef();
1444 ScExternalRefCache::TokenArrayRef pArray;
1445 GetExternalDoubleRef(nFileId, aTabName, rRef, pArray);
1446 if (nGlobalError || !pArray)
1447 break;
1448 formula::FormulaToken* pTemp = pArray->First();
1449 if (!pTemp)
1450 break;
1452 ScMatrixRef pMat = pTemp->GetMatrix();
1453 if (pMat)
1455 formula::FormulaToken* pNew = new ScMatrixToken( pMat);
1456 pNew->IncRef();
1457 pStack[ sp - i ] = pNew;
1458 p->DecRef(); // p may be dead now!
1462 break;
1463 case svRefList:
1465 ScParameterClassification::Type eType =
1466 ScParameterClassification::GetParameterType( pCur, nParams - i);
1467 if ( eType != ScParameterClassification::Reference &&
1468 eType != ScParameterClassification::ReferenceOrForceArray)
1470 // can't convert to matrix
1471 SetError( errNoValue);
1474 break;
1475 default:
1476 OSL_FAIL( "ConvertMatrixParameters: unknown parameter type");
1480 if( nJumpCols && nJumpRows )
1482 short nPC = aCode.GetPC();
1483 short nStart = nPC - 1; // restart on current code (-1)
1484 short nNext = nPC; // next instruction after subroutine
1485 short nStop = nPC + 1; // stop subroutine before reaching that
1486 FormulaTokenRef xNew;
1487 ScTokenMatrixMap::const_iterator aMapIter;
1488 if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) !=
1489 pTokenMatrixMap->end()))
1490 xNew = (*aMapIter).second;
1491 else
1493 ScJumpMatrix* pJumpMat = new ScJumpMatrix( nJumpCols, nJumpRows);
1494 pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop);
1495 // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1496 ScTokenVec* pParams = new ScTokenVec( nParams);
1497 for ( sal_uInt16 i=1; i <= nParams && sp > 0; ++i )
1499 FormulaToken* p = pStack[ --sp ];
1500 p->IncRef();
1501 // store in reverse order such that a push may simply iterate
1502 (*pParams)[ nParams - i ] = p;
1504 pJumpMat->SetJumpParameters( pParams);
1505 xNew = new ScJumpMatrixToken( pJumpMat );
1506 GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur,
1507 xNew));
1509 PushTempToken( xNew.get());
1510 // set continuation point of path for main code line
1511 aCode.Jump( nNext, nNext);
1512 return true;
1514 return false;
1517 ScMatrixRef ScInterpreter::PopMatrix()
1519 if( sp )
1521 --sp;
1522 FormulaToken* p = pStack[ sp ];
1523 switch (p->GetType())
1525 case svError:
1526 nGlobalError = p->GetError();
1527 break;
1528 case svMatrix:
1530 ScMatrix* pMat = p->GetMatrix();
1531 if ( pMat )
1532 pMat->SetErrorInterpreter( this);
1533 else
1534 SetError( errUnknownVariable);
1535 return pMat;
1537 default:
1538 SetError( errIllegalParameter);
1541 else
1542 SetError( errUnknownStackVariable);
1543 return NULL;
1546 sc::RangeMatrix ScInterpreter::PopRangeMatrix()
1548 sc::RangeMatrix aRet;
1549 if (sp)
1551 switch (pStack[sp-1]->GetType())
1553 case svMatrix:
1555 --sp;
1556 FormulaToken* p = pStack[sp];
1557 aRet.mpMat = p->GetMatrix();
1558 if (aRet.mpMat)
1560 aRet.mpMat->SetErrorInterpreter(this);
1561 if (p->GetByte() == MATRIX_TOKEN_HAS_RANGE)
1563 const ScComplexRefData& rRef = *p->GetDoubleRef();
1564 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel())
1566 aRet.mnCol1 = rRef.Ref1.Col();
1567 aRet.mnRow1 = rRef.Ref1.Row();
1568 aRet.mnTab1 = rRef.Ref1.Tab();
1569 aRet.mnCol2 = rRef.Ref2.Col();
1570 aRet.mnRow2 = rRef.Ref2.Row();
1571 aRet.mnTab2 = rRef.Ref2.Tab();
1575 else
1576 SetError( errUnknownVariable);
1578 break;
1579 default:
1580 aRet.mpMat = PopMatrix();
1583 return aRet;
1586 void ScInterpreter::QueryMatrixType(ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr)
1588 if (xMat)
1590 SCSIZE nCols, nRows;
1591 xMat->GetDimensions(nCols, nRows);
1592 ScMatrixValue nMatVal = xMat->Get(0, 0);
1593 ScMatValType nMatValType = nMatVal.nType;
1594 if (ScMatrix::IsNonValueType( nMatValType))
1596 if ( xMat->IsEmptyPath( 0, 0))
1597 { // result of empty FALSE jump path
1598 FormulaTokenRef xRes = new FormulaDoubleToken( 0.0);
1599 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1600 rRetTypeExpr = css::util::NumberFormat::LOGICAL;
1602 else if ( xMat->IsEmptyResult( 0, 0))
1603 { // empty formula result
1604 FormulaTokenRef xRes = new ScEmptyCellToken( true, true); // inherited, display empty
1605 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1607 else if ( xMat->IsEmpty( 0, 0))
1608 { // empty or empty cell
1609 FormulaTokenRef xRes = new ScEmptyCellToken( false, true); // not inherited, display empty
1610 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1612 else
1614 svl::SharedString aStr( nMatVal.GetString());
1615 FormulaTokenRef xRes = new FormulaStringToken( aStr);
1616 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1617 rRetTypeExpr = css::util::NumberFormat::TEXT;
1620 else
1622 sal_uInt16 nErr = GetDoubleErrorValue( nMatVal.fVal);
1623 FormulaTokenRef xRes;
1624 if (nErr)
1625 xRes = new FormulaErrorToken( nErr);
1626 else
1627 xRes = new FormulaDoubleToken( nMatVal.fVal);
1628 PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
1629 if ( rRetTypeExpr != css::util::NumberFormat::LOGICAL )
1630 rRetTypeExpr = css::util::NumberFormat::NUMBER;
1632 rRetIndexExpr = 0;
1633 xMat->SetErrorInterpreter( NULL);
1635 else
1636 SetError( errUnknownStackVariable);
1639 void ScInterpreter::PushDouble(double nVal)
1641 TreatDoubleError( nVal );
1642 if (!IfErrorPushError())
1643 PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1646 void ScInterpreter::PushInt(int nVal)
1648 if (!IfErrorPushError())
1649 PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1652 void ScInterpreter::PushStringBuffer( const sal_Unicode* pString )
1654 if ( pString )
1656 svl::SharedString aSS = pDok->GetSharedStringPool().intern(OUString(pString));
1657 PushString(aSS);
1659 else
1660 PushString(svl::SharedString::getEmptyString());
1663 void ScInterpreter::PushString( const OUString& rStr )
1665 PushString(pDok->GetSharedStringPool().intern(rStr));
1668 void ScInterpreter::PushString( const svl::SharedString& rString )
1670 if (!IfErrorPushError())
1671 PushTempTokenWithoutError( new FormulaStringToken( rString ) );
1674 void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
1676 if (!IfErrorPushError())
1678 ScSingleRefData aRef;
1679 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1680 PushTempTokenWithoutError( new ScSingleRefToken( aRef ) );
1684 void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1685 SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1687 if (!IfErrorPushError())
1689 ScComplexRefData aRef;
1690 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1691 PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) );
1695 void ScInterpreter::PushExternalSingleRef(
1696 sal_uInt16 nFileId, const OUString& rTabName, SCCOL nCol, SCROW nRow, SCTAB nTab)
1698 if (!IfErrorPushError())
1700 ScSingleRefData aRef;
1701 aRef.InitAddress(ScAddress(nCol,nRow,nTab));
1702 PushTempTokenWithoutError( new ScExternalSingleRefToken(nFileId, rTabName, aRef)) ;
1706 void ScInterpreter::PushExternalDoubleRef(
1707 sal_uInt16 nFileId, const OUString& rTabName,
1708 SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1710 if (!IfErrorPushError())
1712 ScComplexRefData aRef;
1713 aRef.InitRange(ScRange(nCol1,nRow1,nTab1,nCol2,nRow2,nTab2));
1714 PushTempTokenWithoutError( new ScExternalDoubleRefToken(nFileId, rTabName, aRef) );
1718 void ScInterpreter::PushSingleRef( const ScRefAddress& rRef )
1720 if (!IfErrorPushError())
1722 ScSingleRefData aRef;
1723 aRef.InitFromRefAddress( rRef, aPos);
1724 PushTempTokenWithoutError( new ScSingleRefToken( aRef ) );
1728 void ScInterpreter::PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 )
1730 if (!IfErrorPushError())
1732 ScComplexRefData aRef;
1733 aRef.InitFromRefAddresses( rRef1, rRef2, aPos);
1734 PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) );
1738 void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat )
1740 if (!rMat.isRangeValid())
1742 // Just push the matrix part only.
1743 PushMatrix(rMat.mpMat);
1744 return;
1747 rMat.mpMat->SetErrorInterpreter(NULL);
1748 nGlobalError = 0;
1749 PushTempTokenWithoutError(new ScMatrixRangeToken(rMat));
1752 void ScInterpreter::PushMatrix(const ScMatrixRef& pMat)
1754 pMat->SetErrorInterpreter( NULL);
1755 // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
1756 // but with notifying ScInterpreter via nGlobalError, substituting it would
1757 // mean to inherit the error on all array elements in all following
1758 // operations.
1759 nGlobalError = 0;
1760 PushTempTokenWithoutError( new ScMatrixToken( pMat ) );
1763 void ScInterpreter::PushError( sal_uInt16 nError )
1765 SetError( nError ); // only sets error if not already set
1766 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
1769 void ScInterpreter::PushParameterExpected()
1771 PushError( errParameterExpected);
1774 void ScInterpreter::PushIllegalParameter()
1776 PushError( errIllegalParameter);
1779 void ScInterpreter::PushIllegalArgument()
1781 PushError( errIllegalArgument);
1784 void ScInterpreter::PushNA()
1786 PushError( NOTAVAILABLE);
1789 void ScInterpreter::PushNoValue()
1791 PushError( errNoValue);
1794 bool ScInterpreter::IsMissing()
1796 return sp && pStack[sp - 1]->GetType() == svMissing;
1799 StackVar ScInterpreter::GetRawStackType()
1801 StackVar eRes;
1802 if( sp )
1804 eRes = pStack[sp - 1]->GetType();
1806 else
1808 SetError(errUnknownStackVariable);
1809 eRes = svUnknown;
1811 return eRes;
1814 StackVar ScInterpreter::GetStackType()
1816 StackVar eRes;
1817 if( sp )
1819 eRes = pStack[sp - 1]->GetType();
1820 if( eRes == svMissing || eRes == svEmptyCell )
1821 eRes = svDouble; // default!
1823 else
1825 SetError(errUnknownStackVariable);
1826 eRes = svUnknown;
1828 return eRes;
1831 StackVar ScInterpreter::GetStackType( sal_uInt8 nParam )
1833 StackVar eRes;
1834 if( sp > nParam-1 )
1836 eRes = pStack[sp - nParam]->GetType();
1837 if( eRes == svMissing || eRes == svEmptyCell )
1838 eRes = svDouble; // default!
1840 else
1841 eRes = svUnknown;
1842 return eRes;
1845 bool ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
1847 // Check for a singleton first - no implicit intersection for them.
1848 if( rRange.aStart == rRange.aEnd )
1850 rAdr = rRange.aStart;
1851 return true;
1854 bool bOk = false;
1856 if ( pJumpMatrix )
1858 bOk = rRange.aStart.Tab() == rRange.aEnd.Tab();
1859 if ( !bOk )
1860 SetError( errIllegalArgument);
1861 else
1863 SCSIZE nC, nR;
1864 pJumpMatrix->GetPos( nC, nR);
1865 rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) );
1866 rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) );
1867 rAdr.SetTab( rRange.aStart.Tab());
1868 bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <=
1869 rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() &&
1870 rAdr.Row() <= rRange.aEnd.Row();
1871 if ( !bOk )
1872 SetError( errNoValue);
1874 return bOk;
1877 SCCOL nMyCol = aPos.Col();
1878 SCROW nMyRow = aPos.Row();
1879 SCTAB nMyTab = aPos.Tab();
1880 SCCOL nCol = 0;
1881 SCROW nRow = 0;
1882 SCTAB nTab;
1883 nTab = rRange.aStart.Tab();
1884 if ( rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
1886 nRow = rRange.aStart.Row();
1887 if ( nRow == rRange.aEnd.Row() )
1889 bOk = true;
1890 nCol = nMyCol;
1892 else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
1893 && rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
1895 bOk = true;
1896 nCol = nMyCol;
1897 nRow = nMyRow;
1900 else if ( rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
1902 nCol = rRange.aStart.Col();
1903 if ( nCol == rRange.aEnd.Col() )
1905 bOk = true;
1906 nRow = nMyRow;
1908 else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
1909 && rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
1911 bOk = true;
1912 nCol = nMyCol;
1913 nRow = nMyRow;
1916 if ( bOk )
1918 if ( nTab == rRange.aEnd.Tab() )
1919 ; // all done
1920 else if ( nTab <= nMyTab && nMyTab <= rRange.aEnd.Tab() )
1921 nTab = nMyTab;
1922 else
1923 bOk = false;
1924 if ( bOk )
1925 rAdr.Set( nCol, nRow, nTab );
1927 if ( !bOk )
1928 SetError( errNoValue );
1929 return bOk;
1932 double ScInterpreter::GetDoubleFromMatrix(const ScMatrixRef& pMat)
1934 if (!pMat)
1935 return 0.0;
1937 if ( !pJumpMatrix )
1938 return pMat->GetDouble( 0 );
1940 SCSIZE nCols, nRows, nC, nR;
1941 pMat->GetDimensions( nCols, nRows);
1942 pJumpMatrix->GetPos( nC, nR);
1943 // Use vector replication for single row/column arrays.
1944 if ( (nC < nCols || nCols == 1) && (nR < nRows || nRows == 1) )
1945 return pMat->GetDouble( nC, nR);
1947 SetError( errNoValue);
1948 return 0.0;
1951 double ScInterpreter::GetDouble()
1953 double nVal(0.0);
1954 switch( GetRawStackType() )
1956 case svDouble:
1957 nVal = PopDouble();
1958 break;
1959 case svString:
1960 nVal = ConvertStringToValue( PopString().getString());
1961 break;
1962 case svSingleRef:
1964 ScAddress aAdr;
1965 PopSingleRef( aAdr );
1966 ScRefCellValue aCell;
1967 aCell.assign(*pDok, aAdr);
1968 nVal = GetCellValue(aAdr, aCell);
1970 break;
1971 case svDoubleRef:
1972 { // generate position dependent SingleRef
1973 ScRange aRange;
1974 PopDoubleRef( aRange );
1975 ScAddress aAdr;
1976 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
1978 ScRefCellValue aCell;
1979 aCell.assign(*pDok, aAdr);
1980 nVal = GetCellValue(aAdr, aCell);
1982 else
1983 nVal = 0.0;
1985 break;
1986 case svExternalSingleRef:
1988 ScExternalRefCache::TokenRef pToken;
1989 PopExternalSingleRef(pToken);
1990 if (!nGlobalError && pToken)
1991 nVal = pToken->GetDouble();
1993 break;
1994 case svExternalDoubleRef:
1996 ScMatrixRef pMat;
1997 PopExternalDoubleRef(pMat);
1998 if (nGlobalError)
1999 break;
2001 nVal = GetDoubleFromMatrix(pMat);
2003 break;
2004 case svMatrix:
2006 ScMatrixRef pMat = PopMatrix();
2007 nVal = GetDoubleFromMatrix(pMat);
2009 break;
2010 case svError:
2011 PopError();
2012 nVal = 0.0;
2013 break;
2014 case svEmptyCell:
2015 case svMissing:
2016 Pop();
2017 nVal = 0.0;
2018 break;
2019 default:
2020 PopError();
2021 SetError( errIllegalParameter);
2022 nVal = 0.0;
2024 if ( nFuncFmtType == nCurFmtType )
2025 nFuncFmtIndex = nCurFmtIndex;
2026 return nVal;
2029 double ScInterpreter::GetDoubleWithDefault(double nDefault)
2031 bool bMissing = IsMissing();
2032 double nResultVal = GetDouble();
2033 if ( bMissing )
2034 nResultVal = nDefault;
2035 return nResultVal;
2038 svl::SharedString ScInterpreter::GetString()
2040 switch (GetRawStackType())
2042 case svError:
2043 PopError();
2044 return svl::SharedString::getEmptyString();
2045 case svMissing:
2046 case svEmptyCell:
2047 Pop();
2048 return svl::SharedString::getEmptyString();
2049 case svDouble:
2051 double fVal = PopDouble();
2052 sal_uLong nIndex = pFormatter->GetStandardFormat(
2053 css::util::NumberFormat::NUMBER,
2054 ScGlobal::eLnge);
2055 OUString aStr;
2056 pFormatter->GetInputLineString(fVal, nIndex, aStr);
2057 return mrStrPool.intern(aStr);
2059 case svString:
2060 return PopString();
2061 case svSingleRef:
2063 ScAddress aAdr;
2064 PopSingleRef( aAdr );
2065 if (nGlobalError == 0)
2067 ScRefCellValue aCell;
2068 aCell.assign(*pDok, aAdr);
2069 svl::SharedString aSS;
2070 GetCellString(aSS, aCell);
2071 return aSS;
2073 else
2074 return svl::SharedString::getEmptyString();
2076 case svDoubleRef:
2077 { // generate position dependent SingleRef
2078 ScRange aRange;
2079 PopDoubleRef( aRange );
2080 ScAddress aAdr;
2081 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
2083 ScRefCellValue aCell;
2084 aCell.assign(*pDok, aAdr);
2085 svl::SharedString aSS;
2086 GetCellString(aSS, aCell);
2087 return aSS;
2089 else
2090 return svl::SharedString::getEmptyString();
2092 case svExternalSingleRef:
2094 ScExternalRefCache::TokenRef pToken;
2095 PopExternalSingleRef(pToken);
2096 if (nGlobalError)
2097 return svl::SharedString::getEmptyString();
2099 return pToken->GetString();
2101 case svExternalDoubleRef:
2103 ScMatrixRef pMat;
2104 PopExternalDoubleRef(pMat);
2105 return GetStringFromMatrix(pMat);
2107 case svMatrix:
2109 ScMatrixRef pMat = PopMatrix();
2110 return GetStringFromMatrix(pMat);
2112 break;
2113 default:
2114 PopError();
2115 SetError( errIllegalArgument);
2117 return svl::SharedString::getEmptyString();
2120 svl::SharedString ScInterpreter::GetStringFromMatrix(const ScMatrixRef& pMat)
2122 if ( !pMat )
2123 ; // nothing
2124 else if ( !pJumpMatrix )
2126 return pMat->GetString( *pFormatter, 0, 0);
2128 else
2130 SCSIZE nCols, nRows, nC, nR;
2131 pMat->GetDimensions( nCols, nRows);
2132 pJumpMatrix->GetPos( nC, nR);
2133 if ( nC < nCols && nR < nRows )
2135 return pMat->GetString( *pFormatter, nC, nR);
2137 else
2138 SetError( errNoValue);
2140 return svl::SharedString::getEmptyString();
2143 ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix(
2144 double& rDouble, svl::SharedString& rString )
2147 rDouble = 0.0;
2148 rString = svl::SharedString::getEmptyString();
2149 ScMatValType nMatValType = SC_MATVAL_EMPTY;
2151 ScMatrixRef pMat;
2152 StackVar eType = GetStackType();
2153 if (eType == svExternalDoubleRef || eType == svExternalSingleRef || eType == svMatrix)
2155 pMat = GetMatrix();
2157 else
2159 PopError();
2160 SetError( errIllegalParameter);
2161 return nMatValType;
2164 ScMatrixValue nMatVal;
2165 if (!pMat)
2167 // nothing
2169 else if (!pJumpMatrix)
2171 nMatVal = pMat->Get(0, 0);
2172 nMatValType = nMatVal.nType;
2174 else
2176 SCSIZE nCols, nRows, nC, nR;
2177 pMat->GetDimensions( nCols, nRows);
2178 pJumpMatrix->GetPos( nC, nR);
2179 if ( nC < nCols && nR < nRows )
2181 nMatVal = pMat->Get( nC, nR);
2182 nMatValType = nMatVal.nType;
2184 else
2185 SetError( errNoValue);
2188 if (nMatValType == SC_MATVAL_VALUE)
2189 rDouble = nMatVal.fVal;
2190 else if (nMatValType == SC_MATVAL_BOOLEAN)
2192 rDouble = nMatVal.fVal;
2193 nMatValType = SC_MATVAL_VALUE;
2195 else
2196 rString = nMatVal.GetString();
2198 if (ScMatrix::IsValueType( nMatValType))
2200 sal_uInt16 nError = nMatVal.GetError();
2201 if (nError)
2202 SetError( nError);
2205 return nMatValType;
2208 void ScInterpreter::ScDBGet()
2210 bool bMissingField = false;
2211 unique_ptr<ScDBQueryParamBase> pQueryParam( GetDBParams(bMissingField) );
2212 if (!pQueryParam.get())
2214 // Failed to create query param.
2215 PushIllegalParameter();
2216 return;
2219 pQueryParam->mbSkipString = false;
2220 ScDBQueryDataIterator aValIter(pDok, pQueryParam.release());
2221 ScDBQueryDataIterator::Value aValue;
2222 if (!aValIter.GetFirst(aValue) || aValue.mnError)
2224 // No match found.
2225 PushNoValue();
2226 return;
2229 ScDBQueryDataIterator::Value aValNext;
2230 if (aValIter.GetNext(aValNext) && !aValNext.mnError)
2232 // There should be only one unique match.
2233 PushIllegalArgument();
2234 return;
2237 if (aValue.mbIsNumber)
2238 PushDouble(aValue.mfValue);
2239 else
2240 PushString(aValue.maString);
2243 void ScInterpreter::ScExternal()
2245 sal_uInt8 nParamCount = GetByte();
2246 OUString aUnoName;
2247 OUString aFuncName( ScGlobal::pCharClass->uppercase( pCur->GetExternal() ) );
2248 FuncData* pFuncData = ScGlobal::GetFuncCollection()->findByName(aFuncName);
2249 if (pFuncData)
2251 // Old binary non-UNO add-in function.
2252 // NOTE: parameter count is 1-based with the 0th "parameter" being the
2253 // return value, included in pFuncDatat->GetParamCount()
2254 if (nParamCount < MAXFUNCPARAM && nParamCount == pFuncData->GetParamCount() - 1)
2256 ParamType eParamType[MAXFUNCPARAM];
2257 void* ppParam[MAXFUNCPARAM];
2258 double nVal[MAXFUNCPARAM];
2259 sal_Char* pStr[MAXFUNCPARAM];
2260 sal_uInt8* pCellArr[MAXFUNCPARAM];
2261 short i;
2263 for (i = 0; i < MAXFUNCPARAM; i++)
2265 eParamType[i] = pFuncData->GetParamType(i);
2266 ppParam[i] = NULL;
2267 nVal[i] = 0.0;
2268 pStr[i] = NULL;
2269 pCellArr[i] = NULL;
2272 for (i = nParamCount; (i > 0) && (nGlobalError == 0); i--)
2274 switch (eParamType[i])
2276 case ParamType::PTR_DOUBLE :
2278 nVal[i-1] = GetDouble();
2279 ppParam[i] = &nVal[i-1];
2281 break;
2282 case ParamType::PTR_STRING :
2284 OString aStr(OUStringToOString(GetString().getString(),
2285 osl_getThreadTextEncoding()));
2286 if ( aStr.getLength() >= ADDIN_MAXSTRLEN )
2287 SetError( errStringOverflow );
2288 else
2290 pStr[i-1] = new sal_Char[ADDIN_MAXSTRLEN];
2291 strncpy( pStr[i-1], aStr.getStr(), ADDIN_MAXSTRLEN );
2292 pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2293 ppParam[i] = pStr[i-1];
2296 break;
2297 case ParamType::PTR_DOUBLE_ARR :
2299 SCCOL nCol1;
2300 SCROW nRow1;
2301 SCTAB nTab1;
2302 SCCOL nCol2;
2303 SCROW nRow2;
2304 SCTAB nTab2;
2305 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2306 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2307 if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2308 SetError(errCodeOverflow);
2309 else
2310 ppParam[i] = pCellArr[i-1];
2312 break;
2313 case ParamType::PTR_STRING_ARR :
2315 SCCOL nCol1;
2316 SCROW nRow1;
2317 SCTAB nTab1;
2318 SCCOL nCol2;
2319 SCROW nRow2;
2320 SCTAB nTab2;
2321 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2322 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2323 if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2324 SetError(errCodeOverflow);
2325 else
2326 ppParam[i] = pCellArr[i-1];
2328 break;
2329 case ParamType::PTR_CELL_ARR :
2331 SCCOL nCol1;
2332 SCROW nRow1;
2333 SCTAB nTab1;
2334 SCCOL nCol2;
2335 SCROW nRow2;
2336 SCTAB nTab2;
2337 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2338 pCellArr[i-1] = new sal_uInt8[MAXARRSIZE];
2339 if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2340 SetError(errCodeOverflow);
2341 else
2342 ppParam[i] = pCellArr[i-1];
2344 break;
2345 default :
2346 SetError(errIllegalParameter);
2347 break;
2350 while ( i-- )
2351 Pop(); // im Fehlerfall (sonst ist i==0) Parameter wegpoppen
2353 if (nGlobalError == 0)
2355 if ( pFuncData->GetAsyncType() == ParamType::NONE )
2357 switch ( eParamType[0] )
2359 case ParamType::PTR_DOUBLE :
2361 double nErg = 0.0;
2362 ppParam[0] = &nErg;
2363 pFuncData->Call(ppParam);
2364 PushDouble(nErg);
2366 break;
2367 case ParamType::PTR_STRING :
2369 boost::scoped_array<sal_Char> pcErg(new sal_Char[ADDIN_MAXSTRLEN]);
2370 ppParam[0] = pcErg.get();
2371 pFuncData->Call(ppParam);
2372 OUString aUni( pcErg.get(), strlen(pcErg.get()), osl_getThreadTextEncoding() );
2373 PushString( aUni );
2375 break;
2376 default:
2377 PushError( errUnknownState );
2380 else
2382 // enable asyncs after loading
2383 if ( rArr.IsRecalcModeNormal() )
2384 rArr.SetExclusiveRecalcModeOnLoad();
2385 // assure identical handler with identical call?
2386 double nErg = 0.0;
2387 ppParam[0] = &nErg;
2388 pFuncData->Call(ppParam);
2389 sal_uLong nHandle = sal_uLong( nErg );
2390 if ( nHandle >= 65536 )
2392 ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2393 if ( !pAs )
2395 pAs = new ScAddInAsync(nHandle, pFuncData, pDok);
2396 pMyFormulaCell->StartListening( *pAs );
2398 else
2400 pMyFormulaCell->StartListening( *pAs );
2401 if ( !pAs->HasDocument( pDok ) )
2402 pAs->AddDocument( pDok );
2404 if ( pAs->IsValid() )
2406 switch ( pAs->GetType() )
2408 case ParamType::PTR_DOUBLE :
2409 PushDouble( pAs->GetValue() );
2410 break;
2411 case ParamType::PTR_STRING :
2412 PushString( pAs->GetString() );
2413 break;
2414 default:
2415 PushError( errUnknownState );
2418 else
2419 PushNA();
2421 else
2422 PushNoValue();
2426 for (i = 0; i < MAXFUNCPARAM; i++)
2428 delete[] pStr[i];
2429 delete[] pCellArr[i];
2432 else
2434 while( nParamCount-- > 0)
2435 Pop();
2436 PushIllegalParameter();
2439 else if ( !( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, false) ).isEmpty() )
2441 // bLocalFirst=false in FindFunction, cFunc should be the stored
2442 // internal name
2444 ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
2446 if ( !aCall.ValidParamCount() )
2447 SetError( errIllegalParameter );
2449 if ( aCall.NeedsCaller() && !GetError() )
2451 SfxObjectShell* pShell = pDok->GetDocumentShell();
2452 if (pShell)
2453 aCall.SetCallerFromObjectShell( pShell );
2454 else
2456 // use temporary model object (without document) to supply options
2457 aCall.SetCaller( static_cast<beans::XPropertySet*>(
2458 new ScDocOptionsObj( pDok->GetDocOptions() ) ) );
2462 short nPar = nParamCount;
2463 while ( nPar > 0 && !GetError() )
2465 --nPar; // 0 .. (nParamCount-1)
2467 ScAddInArgumentType eType = aCall.GetArgType( nPar );
2468 sal_uInt8 nStackType = sal::static_int_cast<sal_uInt8>( GetStackType() );
2470 uno::Any aParam;
2471 switch (eType)
2473 case SC_ADDINARG_INTEGER:
2475 double fVal = GetDouble();
2476 double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2477 ::rtl::math::approxCeil( fVal );
2478 if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2479 aParam <<= (sal_Int32)fInt;
2480 else
2481 SetError(errIllegalArgument);
2483 break;
2485 case SC_ADDINARG_DOUBLE:
2486 aParam <<= (double) GetDouble();
2487 break;
2489 case SC_ADDINARG_STRING:
2490 aParam <<= GetString().getString();
2491 break;
2493 case SC_ADDINARG_INTEGER_ARRAY:
2494 switch( nStackType )
2496 case svDouble:
2497 case svString:
2498 case svSingleRef:
2500 double fVal = GetDouble();
2501 double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2502 ::rtl::math::approxCeil( fVal );
2503 if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2505 sal_Int32 nIntVal = (long)fInt;
2506 uno::Sequence<sal_Int32> aInner( &nIntVal, 1 );
2507 uno::Sequence< uno::Sequence<sal_Int32> > aOuter( &aInner, 1 );
2508 aParam <<= aOuter;
2510 else
2511 SetError(errIllegalArgument);
2513 break;
2514 case svDoubleRef:
2516 ScRange aRange;
2517 PopDoubleRef( aRange );
2518 if (!ScRangeToSequence::FillLongArray( aParam, pDok, aRange ))
2519 SetError(errIllegalParameter);
2521 break;
2522 case svMatrix:
2523 if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix().get() ))
2524 SetError(errIllegalParameter);
2525 break;
2526 default:
2527 PopError();
2528 SetError(errIllegalParameter);
2530 break;
2532 case SC_ADDINARG_DOUBLE_ARRAY:
2533 switch( nStackType )
2535 case svDouble:
2536 case svString:
2537 case svSingleRef:
2539 double fVal = GetDouble();
2540 uno::Sequence<double> aInner( &fVal, 1 );
2541 uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2542 aParam <<= aOuter;
2544 break;
2545 case svDoubleRef:
2547 ScRange aRange;
2548 PopDoubleRef( aRange );
2549 if (!ScRangeToSequence::FillDoubleArray( aParam, pDok, aRange ))
2550 SetError(errIllegalParameter);
2552 break;
2553 case svMatrix:
2554 if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix().get() ))
2555 SetError(errIllegalParameter);
2556 break;
2557 default:
2558 PopError();
2559 SetError(errIllegalParameter);
2561 break;
2563 case SC_ADDINARG_STRING_ARRAY:
2564 switch( nStackType )
2566 case svDouble:
2567 case svString:
2568 case svSingleRef:
2570 OUString aString = GetString().getString();
2571 uno::Sequence<OUString> aInner( &aString, 1 );
2572 uno::Sequence< uno::Sequence<OUString> > aOuter( &aInner, 1 );
2573 aParam <<= aOuter;
2575 break;
2576 case svDoubleRef:
2578 ScRange aRange;
2579 PopDoubleRef( aRange );
2580 if (!ScRangeToSequence::FillStringArray( aParam, pDok, aRange ))
2581 SetError(errIllegalParameter);
2583 break;
2584 case svMatrix:
2585 if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix().get(), pFormatter ))
2586 SetError(errIllegalParameter);
2587 break;
2588 default:
2589 PopError();
2590 SetError(errIllegalParameter);
2592 break;
2594 case SC_ADDINARG_MIXED_ARRAY:
2595 switch( nStackType )
2597 case svDouble:
2598 case svString:
2599 case svSingleRef:
2601 uno::Any aElem;
2602 if ( nStackType == svDouble )
2603 aElem <<= (double) GetDouble();
2604 else if ( nStackType == svString )
2605 aElem <<= GetString().getString();
2606 else
2608 ScAddress aAdr;
2609 if ( PopDoubleRefOrSingleRef( aAdr ) )
2611 ScRefCellValue aCell;
2612 aCell.assign(*pDok, aAdr);
2613 if (aCell.hasString())
2615 svl::SharedString aStr;
2616 GetCellString(aStr, aCell);
2617 aElem <<= aStr.getString();
2619 else
2620 aElem <<= GetCellValue(aAdr, aCell);
2623 uno::Sequence<uno::Any> aInner( &aElem, 1 );
2624 uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2625 aParam <<= aOuter;
2627 break;
2628 case svDoubleRef:
2630 ScRange aRange;
2631 PopDoubleRef( aRange );
2632 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2633 SetError(errIllegalParameter);
2635 break;
2636 case svMatrix:
2637 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2638 SetError(errIllegalParameter);
2639 break;
2640 default:
2641 PopError();
2642 SetError(errIllegalParameter);
2644 break;
2646 case SC_ADDINARG_VALUE_OR_ARRAY:
2647 if ( IsMissing() )
2648 nStackType = svMissing;
2649 switch( nStackType )
2651 case svDouble:
2652 aParam <<= (double) GetDouble();
2653 break;
2654 case svString:
2655 aParam <<= GetString().getString();
2656 break;
2657 case svSingleRef:
2659 ScAddress aAdr;
2660 if ( PopDoubleRefOrSingleRef( aAdr ) )
2662 ScRefCellValue aCell;
2663 aCell.assign(*pDok, aAdr);
2664 if (aCell.hasString())
2666 svl::SharedString aStr;
2667 GetCellString(aStr, aCell);
2668 aParam <<= aStr.getString();
2670 else
2671 aParam <<= GetCellValue(aAdr, aCell);
2674 break;
2675 case svDoubleRef:
2677 ScRange aRange;
2678 PopDoubleRef( aRange );
2679 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2680 SetError(errIllegalParameter);
2682 break;
2683 case svMatrix:
2684 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix().get() ))
2685 SetError(errIllegalParameter);
2686 break;
2687 case svMissing:
2688 Pop();
2689 aParam.clear();
2690 break;
2691 default:
2692 PopError();
2693 SetError(errIllegalParameter);
2695 break;
2697 case SC_ADDINARG_CELLRANGE:
2698 switch( nStackType )
2700 case svSingleRef:
2702 ScAddress aAdr;
2703 PopSingleRef( aAdr );
2704 ScRange aRange( aAdr );
2705 uno::Reference<table::XCellRange> xObj =
2706 ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2707 if (xObj.is())
2708 aParam <<= xObj;
2709 else
2710 SetError(errIllegalParameter);
2712 break;
2713 case svDoubleRef:
2715 ScRange aRange;
2716 PopDoubleRef( aRange );
2717 uno::Reference<table::XCellRange> xObj =
2718 ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2719 if (xObj.is())
2721 aParam <<= xObj;
2723 else
2725 SetError(errIllegalParameter);
2728 break;
2729 default:
2730 PopError();
2731 SetError(errIllegalParameter);
2733 break;
2735 default:
2736 PopError();
2737 SetError(errIllegalParameter);
2739 aCall.SetParam( nPar, aParam );
2742 while (nPar-- > 0)
2744 Pop(); // in case of error, remove remaining args
2746 if ( !GetError() )
2748 aCall.ExecuteCall();
2750 if ( aCall.HasVarRes() ) // handle async functions
2752 if ( rArr.IsRecalcModeNormal() )
2754 rArr.SetExclusiveRecalcModeOnLoad();
2756 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
2757 ScAddInListener* pLis = ScAddInListener::Get( xRes );
2758 if ( !pLis )
2760 pLis = ScAddInListener::CreateListener( xRes, pDok );
2761 pMyFormulaCell->StartListening( *pLis );
2763 else
2765 pMyFormulaCell->StartListening( *pLis );
2766 if ( !pLis->HasDocument( pDok ) )
2768 pLis->AddDocument( pDok );
2772 aCall.SetResult( pLis->GetResult() ); // use result from async
2775 if ( aCall.GetErrCode() )
2777 PushError( aCall.GetErrCode() );
2779 else if ( aCall.HasMatrix() )
2781 ScMatrixRef xMat = aCall.GetMatrix();
2782 PushMatrix( xMat );
2784 else if ( aCall.HasString() )
2786 PushString( aCall.GetString() );
2788 else
2790 PushDouble( aCall.GetValue() );
2793 else // error...
2794 PushError( GetError());
2796 else
2798 while( nParamCount-- > 0)
2800 Pop();
2802 PushError( errNoAddin );
2806 void ScInterpreter::ScMissing()
2808 if ( aCode.IsEndOfPath() )
2809 PushTempToken( new ScEmptyCellToken( false, false ) );
2810 else
2811 PushTempToken( new FormulaMissingToken );
2814 #if HAVE_FEATURE_SCRIPTING
2816 static uno::Any lcl_getSheetModule( const uno::Reference<table::XCellRange>& xCellRange, ScDocument* pDok )
2818 uno::Reference< sheet::XSheetCellRange > xSheetRange( xCellRange, uno::UNO_QUERY_THROW );
2819 uno::Reference< beans::XPropertySet > xProps( xSheetRange->getSpreadsheet(), uno::UNO_QUERY_THROW );
2820 OUString sCodeName;
2821 xProps->getPropertyValue("CodeName") >>= sCodeName;
2822 // #TODO #FIXME ideally we should 'throw' here if we don't get a valid parent, but... it is possible
2823 // to create a module ( and use 'Option VBASupport 1' ) for a calc document, in this scenario there
2824 // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at
2825 // the document in the future could fix this, especially IF the switching of the vba mode takes care to
2826 // create the special document module objects if they don't exist.
2827 BasicManager* pBasMgr = pDok->GetDocumentShell()->GetBasicManager();
2829 uno::Reference< uno::XInterface > xIf;
2830 if ( pBasMgr && !pBasMgr->GetName().isEmpty() )
2832 OUString sProj( "Standard" );
2833 if ( !pDok->GetDocumentShell()->GetBasicManager()->GetName().isEmpty() )
2835 sProj = pDok->GetDocumentShell()->GetBasicManager()->GetName();
2837 StarBASIC* pBasic = pDok->GetDocumentShell()->GetBasicManager()->GetLib( sProj );
2838 if ( pBasic )
2840 SbModule* pMod = pBasic->FindModule( sCodeName );
2841 if ( pMod )
2843 xIf = pMod->GetUnoModule();
2847 return uno::makeAny( xIf );
2850 static bool lcl_setVBARange( ScRange& aRange, ScDocument* pDok, SbxVariable* pPar )
2852 bool bOk = false;
2855 uno::Reference< uno::XInterface > xVBARange;
2856 uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2857 uno::Sequence< uno::Any > aArgs(2);
2858 aArgs[0] = lcl_getSheetModule( xCellRange, pDok );
2859 aArgs[1] = uno::Any( xCellRange );
2860 xVBARange = ooo::vba::createVBAUnoAPIServiceWithArgs( pDok->GetDocumentShell(), "ooo.vba.excel.Range", aArgs );
2861 if ( xVBARange.is() )
2863 OUString sDummy("A-Range");
2864 SbxObjectRef aObj = GetSbUnoObject( sDummy, uno::Any( xVBARange ) );
2865 SetSbUnoObjectDfltPropName( aObj );
2866 bOk = pPar->PutObject( aObj );
2869 catch( uno::Exception& )
2872 return bOk;
2875 #endif
2877 void ScInterpreter::ScMacro()
2880 #if !HAVE_FEATURE_SCRIPTING
2881 PushNoValue(); // without DocShell no CallBasic
2882 return;
2883 #else
2884 SbxBase::ResetError();
2886 sal_uInt8 nParamCount = GetByte();
2887 OUString aMacro( pCur->GetExternal() );
2889 SfxObjectShell* pDocSh = pDok->GetDocumentShell();
2890 if ( !pDocSh || !ScDocument::CheckMacroWarn() )
2892 PushNoValue(); // without DocShell no CallBasic
2893 return;
2896 // no security queue beforehand (just CheckMacroWarn), moved to CallBasic
2898 // If the Dok was loaded during a Basic-Calls,
2899 // is the Sbx-Objekt created(?)
2900 // pDocSh->GetSbxObject();
2902 // search function with the name,
2903 // then assemble SfxObjectShell::CallBasic from aBasicStr, aMacroStr
2905 StarBASIC* pRoot;
2909 pRoot = pDocSh->GetBasic();
2911 catch (...)
2913 pRoot = NULL;
2916 SbxVariable* pVar = pRoot ? pRoot->Find(aMacro, SbxCLASS_METHOD) : NULL;
2917 if( !pVar || pVar->GetType() == SbxVOID || !pVar->ISA(SbMethod) )
2919 PushError( errNoMacro );
2920 return;
2923 bool bVolatileMacro = false;
2924 SbMethod* pMethod = static_cast<SbMethod*>(pVar);
2926 SbModule* pModule = pMethod->GetModule();
2927 bool bUseVBAObjects = pModule->IsVBACompat();
2928 SbxObject* pObject = pModule->GetParent();
2929 OSL_ENSURE(pObject->IsA(TYPE(StarBASIC)), "No Basic found!");
2930 OUString aMacroStr = pObject->GetName() + "." + pModule->GetName() + "." + pMethod->GetName();
2931 OUString aBasicStr;
2932 if (pObject->GetParent())
2934 aBasicStr = pObject->GetParent()->GetName(); // Dokumentenbasic
2936 else
2938 aBasicStr = SfxGetpApp()->GetName(); // Applikationsbasic
2940 // Parameter-Array zusammenbauen
2942 SbxArrayRef refPar = new SbxArray;
2943 bool bOk = true;
2944 for( short i = nParamCount; i && bOk ; i-- )
2946 SbxVariable* pPar = refPar->Get( (sal_uInt16) i );
2947 sal_uInt8 nStackType = sal::static_int_cast<sal_uInt8>( GetStackType() );
2948 switch( nStackType )
2950 case svDouble:
2951 pPar->PutDouble( GetDouble() );
2952 break;
2953 case svString:
2954 pPar->PutString( GetString().getString() );
2955 break;
2956 case svExternalSingleRef:
2958 ScExternalRefCache::TokenRef pToken;
2959 PopExternalSingleRef(pToken);
2960 if ( pToken->GetType() == svString )
2961 pPar->PutString( pToken->GetString().getString() );
2962 else if ( pToken->GetType() == svDouble )
2963 pPar->PutDouble( pToken->GetDouble() );
2964 else
2966 SetError( errIllegalArgument );
2967 bOk = false;
2970 break;
2971 case svSingleRef:
2973 ScAddress aAdr;
2974 PopSingleRef( aAdr );
2975 if ( bUseVBAObjects )
2977 ScRange aRange( aAdr );
2978 bOk = lcl_setVBARange( aRange, pDok, pPar );
2980 else
2982 bOk = SetSbxVariable( pPar, aAdr );
2985 break;
2986 case svDoubleRef:
2988 SCCOL nCol1;
2989 SCROW nRow1;
2990 SCTAB nTab1;
2991 SCCOL nCol2;
2992 SCROW nRow2;
2993 SCTAB nTab2;
2994 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
2995 if( nTab1 != nTab2 )
2997 SetError( errIllegalParameter );
2998 bOk = false;
3000 else
3002 if ( bUseVBAObjects )
3004 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
3005 bOk = lcl_setVBARange( aRange, pDok, pPar );
3007 else
3009 SbxDimArrayRef refArray = new SbxDimArray;
3010 refArray->AddDim32( 1, nRow2 - nRow1 + 1 );
3011 refArray->AddDim32( 1, nCol2 - nCol1 + 1 );
3012 ScAddress aAdr( nCol1, nRow1, nTab1 );
3013 for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
3015 aAdr.SetRow( nRow );
3016 sal_Int32 nIdx[ 2 ];
3017 nIdx[ 0 ] = nRow-nRow1+1;
3018 for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
3020 aAdr.SetCol( nCol );
3021 nIdx[ 1 ] = nCol-nCol1+1;
3022 SbxVariable* p = refArray->Get32( nIdx );
3023 bOk = SetSbxVariable( p, aAdr );
3026 pPar->PutObject( refArray );
3030 break;
3031 case svExternalDoubleRef:
3032 case svMatrix:
3034 ScMatrixRef pMat = GetMatrix();
3035 SCSIZE nC, nR;
3036 if (pMat && !nGlobalError)
3038 pMat->GetDimensions(nC, nR);
3039 SbxDimArrayRef refArray = new SbxDimArray;
3040 refArray->AddDim32( 1, static_cast<sal_Int32>(nR) );
3041 refArray->AddDim32( 1, static_cast<sal_Int32>(nC) );
3042 for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
3044 sal_Int32 nIdx[ 2 ];
3045 nIdx[ 0 ] = static_cast<sal_Int32>(nMatRow+1);
3046 for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
3048 nIdx[ 1 ] = static_cast<sal_Int32>(nMatCol+1);
3049 SbxVariable* p = refArray->Get32( nIdx );
3050 if (pMat->IsString(nMatCol, nMatRow))
3052 p->PutString( pMat->GetString(nMatCol, nMatRow).getString() );
3054 else
3056 p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
3060 pPar->PutObject( refArray );
3062 else
3064 SetError( errIllegalParameter );
3067 break;
3068 default:
3069 SetError( errIllegalParameter );
3070 bOk = false;
3073 if( bOk )
3075 pDok->LockTable( aPos.Tab() );
3076 SbxVariableRef refRes = new SbxVariable;
3077 pDok->IncMacroInterpretLevel();
3078 ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, refPar, refRes );
3079 pDok->DecMacroInterpretLevel();
3080 pDok->UnlockTable( aPos.Tab() );
3082 ScMacroManager* pMacroMgr = pDok->GetMacroManager();
3083 if (pMacroMgr)
3085 bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
3086 pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
3089 SbxDataType eResType = refRes->GetType();
3090 if( SbxBase::GetError() )
3092 SetError( errNoValue);
3094 if ( eRet != ERRCODE_NONE )
3096 PushNoValue();
3098 else if( eResType >= SbxINTEGER && eResType <= SbxDOUBLE )
3100 PushDouble( refRes->GetDouble() );
3102 else if ( eResType & SbxARRAY )
3104 SbxBase* pElemObj = refRes->GetObject();
3105 SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
3106 short nDim = pDimArray->GetDims();
3107 if ( 1 <= nDim && nDim <= 2 )
3109 sal_Int32 nCs, nCe, nRs, nRe;
3110 SCSIZE nC, nR;
3111 SCCOL nColIdx;
3112 SCROW nRowIdx;
3113 if ( nDim == 1 )
3114 { // array( cols ) one line, several columns
3115 pDimArray->GetDim32( 1, nCs, nCe );
3116 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3117 nRs = nRe = 0;
3118 nR = 1;
3119 nColIdx = 0;
3120 nRowIdx = 1;
3122 else
3123 { // array( rows, cols )
3124 pDimArray->GetDim32( 1, nRs, nRe );
3125 nR = static_cast<SCSIZE>(nRe - nRs + 1);
3126 pDimArray->GetDim32( 2, nCs, nCe );
3127 nC = static_cast<SCSIZE>(nCe - nCs + 1);
3128 nColIdx = 1;
3129 nRowIdx = 0;
3131 ScMatrixRef pMat = GetNewMat( nC, nR);
3132 if ( pMat )
3134 SbxVariable* pV;
3135 SbxDataType eType;
3136 for ( SCSIZE j=0; j < nR; j++ )
3138 sal_Int32 nIdx[ 2 ];
3139 // in one-dimensional array( cols ) nIdx[1]
3140 // from SbxDimArray::Get is ignored
3141 nIdx[ nRowIdx ] = nRs + static_cast<sal_Int32>(j);
3142 for ( SCSIZE i=0; i < nC; i++ )
3144 nIdx[ nColIdx ] = nCs + static_cast<sal_Int32>(i);
3145 pV = pDimArray->Get32( nIdx );
3146 eType = pV->GetType();
3147 if ( eType >= SbxINTEGER && eType <= SbxDOUBLE )
3149 pMat->PutDouble( pV->GetDouble(), i, j );
3151 else
3153 pMat->PutString(mrStrPool.intern(pV->GetOUString()), i, j);
3157 PushMatrix( pMat );
3159 else
3161 PushIllegalArgument();
3164 else
3166 PushNoValue();
3169 else
3171 PushString( refRes->GetOUString() );
3175 if (bVolatileMacro && meVolatileType == NOT_VOLATILE)
3176 meVolatileType = VOLATILE_MACRO;
3177 #endif
3180 #if HAVE_FEATURE_SCRIPTING
3182 bool ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
3184 bool bOk = true;
3185 ScRefCellValue aCell;
3186 aCell.assign(*pDok, rPos);
3187 if (!aCell.isEmpty())
3189 sal_uInt16 nErr;
3190 double nVal;
3191 switch (aCell.meType)
3193 case CELLTYPE_VALUE :
3194 nVal = GetValueCellValue(rPos, aCell.mfValue);
3195 pVar->PutDouble( nVal );
3196 break;
3197 case CELLTYPE_STRING :
3198 case CELLTYPE_EDIT :
3199 pVar->PutString(aCell.getString(pDok));
3200 break;
3201 case CELLTYPE_FORMULA :
3202 nErr = aCell.mpFormula->GetErrCode();
3203 if( !nErr )
3205 if (aCell.mpFormula->IsValue())
3207 nVal = aCell.mpFormula->GetValue();
3208 pVar->PutDouble(aCell.mpFormula->GetValue());
3210 else
3211 pVar->PutString(aCell.mpFormula->GetString().getString());
3213 else
3214 SetError( nErr ), bOk = false;
3215 break;
3216 default :
3217 pVar->PutDouble( 0.0 );
3220 else
3221 pVar->PutDouble( 0.0 );
3222 return bOk;
3225 #endif
3227 namespace {
3229 class FindByPointer : ::std::unary_function<ScInterpreterTableOpParams, bool>
3231 const ScInterpreterTableOpParams* mpTableOp;
3232 public:
3233 FindByPointer(const ScInterpreterTableOpParams* p) : mpTableOp(p) {}
3234 bool operator() (const ScInterpreterTableOpParams& val) const
3236 return &val == mpTableOp;
3242 void ScInterpreter::ScTableOp()
3244 sal_uInt8 nParamCount = GetByte();
3245 if (nParamCount != 3 && nParamCount != 5)
3247 PushIllegalParameter();
3248 return;
3250 ScInterpreterTableOpParams* pTableOp = new ScInterpreterTableOpParams;
3251 if (nParamCount == 5)
3253 PopSingleRef( pTableOp->aNew2 );
3254 PopSingleRef( pTableOp->aOld2 );
3256 PopSingleRef( pTableOp->aNew1 );
3257 PopSingleRef( pTableOp->aOld1 );
3258 PopSingleRef( pTableOp->aFormulaPos );
3260 pTableOp->bValid = true;
3261 pDok->aTableOpList.push_back( pTableOp );
3262 pDok->IncInterpreterTableOpLevel();
3264 bool bReuseLastParams = (pDok->aLastTableOpParams == *pTableOp);
3265 if ( bReuseLastParams )
3267 pTableOp->aNotifiedFormulaPos = pDok->aLastTableOpParams.aNotifiedFormulaPos;
3268 pTableOp->bRefresh = true;
3269 for ( ::std::vector< ScAddress >::const_iterator iBroadcast(
3270 pTableOp->aNotifiedFormulaPos.begin() );
3271 iBroadcast != pTableOp->aNotifiedFormulaPos.end();
3272 ++iBroadcast )
3273 { // emulate broadcast and indirectly collect cell pointers
3274 ScRefCellValue aCell;
3275 aCell.assign(*pDok, *iBroadcast);
3276 if (aCell.meType == CELLTYPE_FORMULA)
3277 aCell.mpFormula->SetTableOpDirty();
3280 else
3281 { // broadcast and indirectly collect cell pointers and positions
3282 pDok->SetTableOpDirty( pTableOp->aOld1 );
3283 if ( nParamCount == 5 )
3284 pDok->SetTableOpDirty( pTableOp->aOld2 );
3286 pTableOp->bCollectNotifications = false;
3288 ScRefCellValue aCell;
3289 aCell.assign(*pDok, pTableOp->aFormulaPos);
3290 if (aCell.meType == CELLTYPE_FORMULA)
3291 aCell.mpFormula->SetDirtyVar();
3292 if (aCell.hasNumeric())
3294 PushDouble(GetCellValue(pTableOp->aFormulaPos, aCell));
3296 else
3298 svl::SharedString aCellString;
3299 GetCellString(aCellString, aCell);
3300 PushString( aCellString );
3303 boost::ptr_vector< ScInterpreterTableOpParams >::iterator itr =
3304 ::std::find_if(pDok->aTableOpList.begin(), pDok->aTableOpList.end(), FindByPointer(pTableOp));
3305 if (itr != pDok->aTableOpList.end())
3306 pTableOp = pDok->aTableOpList.release(itr).release();
3308 // set dirty again once more to be able to recalculate original
3309 for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast(
3310 pTableOp->aNotifiedFormulaCells.begin() );
3311 iBroadcast != pTableOp->aNotifiedFormulaCells.end();
3312 ++iBroadcast )
3314 (*iBroadcast)->SetTableOpDirty();
3317 // save these params for next incarnation
3318 if ( !bReuseLastParams )
3319 pDok->aLastTableOpParams = *pTableOp;
3321 if (aCell.meType == CELLTYPE_FORMULA)
3323 aCell.mpFormula->SetDirtyVar();
3324 aCell.mpFormula->GetErrCode(); // recalculate original
3327 // Reset all dirty flags so next incarnation does really collect all cell
3328 // pointers during notifications and not just non-dirty ones, which may
3329 // happen if a formula cell is used by more than one TableOp block.
3330 for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast2(
3331 pTableOp->aNotifiedFormulaCells.begin() );
3332 iBroadcast2 != pTableOp->aNotifiedFormulaCells.end();
3333 ++iBroadcast2 )
3335 (*iBroadcast2)->ResetTableOpDirtyVar();
3337 delete pTableOp;
3339 pDok->DecInterpreterTableOpLevel();
3342 void ScInterpreter::ScDBArea()
3344 ScDBData* pDBData = pDok->GetDBCollection()->getNamedDBs().findByIndex(pCur->GetIndex());
3345 if (pDBData)
3347 ScComplexRefData aRefData;
3348 aRefData.InitFlags();
3349 ScRange aRange;
3350 pDBData->GetArea(aRange);
3351 aRange.aEnd.SetTab(aRange.aStart.Tab());
3352 aRefData.SetRange(aRange, aPos);
3353 PushTempToken( new ScDoubleRefToken( aRefData ) );
3355 else
3356 PushError( errNoName);
3359 void ScInterpreter::ScColRowNameAuto()
3361 ScComplexRefData aRefData( *pCur->GetDoubleRef() );
3362 ScRange aAbs = aRefData.toAbs(aPos);
3363 if (!ValidRange(aAbs))
3365 PushError( errNoRef );
3366 return;
3369 SCsCOL nStartCol;
3370 SCsROW nStartRow;
3372 // maybe remember limit by using defined ColRowNameRange
3373 SCsCOL nCol2 = aAbs.aEnd.Col();
3374 SCsROW nRow2 = aAbs.aEnd.Row();
3375 // DataArea of the first cell
3376 nStartCol = aAbs.aStart.Col();
3377 nStartRow = aAbs.aStart.Row();
3378 aAbs.aEnd = aAbs.aStart; // Shrink to the top-left cell.
3381 // Expand to the data area. Only modify the end position.
3382 SCCOL nDACol1 = aAbs.aStart.Col(), nDACol2 = aAbs.aEnd.Col();
3383 SCROW nDARow1 = aAbs.aStart.Row(), nDARow2 = aAbs.aEnd.Row();
3384 pDok->GetDataArea(aAbs.aStart.Tab(), nDACol1, nDARow1, nDACol2, nDARow2, true, false);
3385 aAbs.aEnd.SetCol(nDACol2);
3386 aAbs.aEnd.SetRow(nDARow2);
3389 // corresponds with ScCompiler::GetToken
3390 if ( aRefData.Ref1.IsColRel() )
3391 { // ColName
3392 aAbs.aEnd.SetCol(nStartCol);
3393 // maybe get previous limit by using defined ColRowNameRange
3394 if (aAbs.aEnd.Row() > nRow2)
3395 aAbs.aEnd.SetRow(nRow2);
3396 SCROW nMyRow;
3397 if ( aPos.Col() == nStartCol
3398 && nStartRow <= (nMyRow = aPos.Row()) && nMyRow <= aAbs.aEnd.Row())
3399 { //Formula in the same column and within the range
3400 if ( nMyRow == nStartRow )
3401 { // take the rest under the name
3402 nStartRow++;
3403 if ( nStartRow > MAXROW )
3404 nStartRow = MAXROW;
3405 aAbs.aStart.SetRow(nStartRow);
3407 else
3408 { // below the name to the formula cell
3409 aAbs.aEnd.SetRow(nMyRow - 1);
3413 else
3414 { // RowName
3415 aAbs.aEnd.SetRow(nStartRow);
3416 // maybe get previous limit by using defined ColRowNameRange
3417 if (aAbs.aEnd.Col() > nCol2)
3418 aAbs.aEnd.SetCol(nCol2);
3419 SCCOL nMyCol;
3420 if ( aPos.Row() == nStartRow
3421 && nStartCol <= (nMyCol = aPos.Col()) && nMyCol <= aAbs.aEnd.Col())
3422 { //Formula in the same column and within the range
3423 if ( nMyCol == nStartCol )
3424 { // take the rest under the name
3425 nStartCol++;
3426 if ( nStartCol > MAXCOL )
3427 nStartCol = MAXCOL;
3428 aAbs.aStart.SetCol(nStartCol);
3430 else
3431 { // below the name to the formula cell
3432 aAbs.aEnd.SetCol(nMyCol - 1);
3436 aRefData.SetRange(aAbs, aPos);
3437 PushTempToken( new ScDoubleRefToken( aRefData ) );
3440 // --- internals ------------------------------------------------------------
3442 void ScInterpreter::ScTTT()
3443 { // temporary test, testing functions etc.
3444 sal_uInt8 nParamCount = GetByte();
3445 // do something, count down nParamCount with Pops!
3447 // clean up Stack
3448 while ( nParamCount-- > 0)
3449 Pop();
3450 PushError(errNoValue);
3453 ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc,
3454 const ScAddress& rPos, ScTokenArray& r )
3455 : aCode(r)
3456 , aPos(rPos)
3457 , rArr(r)
3458 , pDok(pDoc)
3459 , mrStrPool(pDoc->GetSharedStringPool())
3460 , pJumpMatrix(NULL)
3461 , pTokenMatrixMap(NULL)
3462 , pMyFormulaCell(pCell)
3463 , pFormatter(pDoc->GetFormatTable())
3464 , pCur(NULL)
3465 , nGlobalError(0)
3466 , sp(0)
3467 , maxsp(0)
3468 , nFuncFmtIndex(0)
3469 , nCurFmtIndex(0)
3470 , nRetFmtIndex(0)
3471 , nFuncFmtType(0)
3472 , nCurFmtType(0)
3473 , nRetFmtType(0)
3474 , mnStringNoValueError(errNoValue)
3475 , mnSubTotalFlags(0)
3476 , cPar(0)
3477 , bCalcAsShown(pDoc->GetDocOptions().IsCalcAsShown())
3478 , meVolatileType(r.IsRecalcModeAlways() ? VOLATILE : NOT_VOLATILE)
3480 MergeCalcConfig();
3482 if(pMyFormulaCell)
3484 sal_uInt8 cMatFlag = pMyFormulaCell->GetMatrixFlag();
3485 bMatrixFormula = ( cMatFlag == MM_FORMULA || cMatFlag == MM_FAKE );
3487 else
3488 bMatrixFormula = false;
3490 if (!bGlobalStackInUse)
3492 bGlobalStackInUse = true;
3493 if (!pGlobalStack)
3494 pGlobalStack = new ScTokenStack;
3495 pStackObj = pGlobalStack;
3497 else
3499 pStackObj = new ScTokenStack;
3501 pStack = pStackObj->pPointer;
3504 ScInterpreter::~ScInterpreter()
3506 // delete pStack;
3508 if ( pStackObj == pGlobalStack )
3509 bGlobalStackInUse = false;
3510 else
3511 delete pStackObj;
3512 if (pTokenMatrixMap)
3513 delete pTokenMatrixMap;
3516 void ScInterpreter::SetGlobalConfig(const ScCalcConfig& rConfig)
3518 maGlobalConfig = rConfig;
3521 const ScCalcConfig& ScInterpreter::GetGlobalConfig()
3523 return maGlobalConfig;
3526 void ScInterpreter::MergeCalcConfig()
3528 maCalcConfig = maGlobalConfig;
3529 maCalcConfig.MergeDocumentSpecific( pDok->GetCalcConfig());
3532 void ScInterpreter::GlobalExit()
3534 OSL_ENSURE(!bGlobalStackInUse, "who is still using the TokenStack?");
3535 DELETEZ(pGlobalStack);
3538 namespace {
3540 double applyImplicitIntersection(const sc::RangeMatrix& rMat, const ScAddress& rPos)
3542 if (rMat.mnRow1 <= rPos.Row() && rPos.Row() <= rMat.mnRow2 && rMat.mnCol1 == rMat.mnCol2)
3544 SCROW nOffset = rPos.Row() - rMat.mnRow1;
3545 return rMat.mpMat->GetDouble(0, nOffset);
3548 if (rMat.mnCol1 <= rPos.Col() && rPos.Col() <= rMat.mnCol2 && rMat.mnRow1 == rMat.mnRow2)
3550 SCROW nOffset = rPos.Col() - rMat.mnCol1;
3551 return rMat.mpMat->GetDouble(nOffset, 0);
3554 double fVal;
3555 rtl::math::setNan(&fVal);
3556 return fVal;
3561 StackVar ScInterpreter::Interpret()
3563 short nRetTypeExpr = css::util::NumberFormat::UNDEFINED;
3564 sal_uLong nRetIndexExpr = 0;
3565 sal_uInt16 nErrorFunction = 0;
3566 sal_uInt16 nErrorFunctionCount = 0;
3567 sal_uInt16 nStackBase;
3569 nGlobalError = 0;
3570 nStackBase = sp = maxsp = 0;
3571 nRetFmtType = css::util::NumberFormat::UNDEFINED;
3572 nFuncFmtType = css::util::NumberFormat::UNDEFINED;
3573 nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
3574 xResult = NULL;
3575 pJumpMatrix = NULL;
3576 mnSubTotalFlags = 0x00;
3577 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
3579 // Once upon a time we used to have FP exceptions on, and there was a
3580 // Windows printer driver that kept switching off exceptions, so we had to
3581 // switch them back on again every time. Who knows if there isn't a driver
3582 // that keeps switching exceptions on, now that we run with exceptions off,
3583 // so reassure exceptions are really off.
3584 SAL_MATH_FPEXCEPTIONS_OFF();
3586 aCode.Reset();
3587 while( ( pCur = aCode.Next() ) != NULL
3588 && (!nGlobalError || nErrorFunction <= nErrorFunctionCount) )
3590 OpCode eOp = pCur->GetOpCode();
3591 cPar = pCur->GetByte();
3592 if ( eOp == ocPush )
3594 // RPN code push without error
3595 PushWithoutError( (FormulaToken&) *pCur );
3597 else if (pTokenMatrixMap &&
3598 !(eOp == ocIf || eOp == ocIfError || eOp == ocIfNA || eOp == ocChoose) &&
3599 ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
3600 pTokenMatrixMap->end()) &&
3601 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
3603 // Path already calculated, reuse result.
3604 nStackBase = sp - pCur->GetParamCount();
3605 if ( nStackBase > sp )
3606 nStackBase = sp; // underflow?!?
3607 sp = nStackBase;
3608 PushTempToken( (*aTokenMatrixMapIter).second.get());
3610 else
3612 // previous expression determines the current number format
3613 nCurFmtType = nRetTypeExpr;
3614 nCurFmtIndex = nRetIndexExpr;
3615 // default function's format, others are set if needed
3616 nFuncFmtType = css::util::NumberFormat::NUMBER;
3617 nFuncFmtIndex = 0;
3619 if ( eOp == ocIf || eOp == ocChoose || eOp == ocIfError || eOp == ocIfNA )
3620 nStackBase = sp; // don't mess around with the jumps
3621 else
3623 // Convert parameters to matrix if in array/matrix formula and
3624 // parameters of function indicate doing so. Create JumpMatrix
3625 // if necessary.
3626 if ( MatrixParameterConversion() )
3628 eOp = ocNone; // JumpMatrix created
3629 nStackBase = sp;
3631 else
3632 nStackBase = sp - pCur->GetParamCount();
3634 if ( nStackBase > sp )
3635 nStackBase = sp; // underflow?!?
3637 switch( eOp )
3639 case ocSep:
3640 case ocClose: // pushed by the compiler
3641 case ocMissing : ScMissing(); break;
3642 case ocMacro : ScMacro(); break;
3643 case ocDBArea : ScDBArea(); break;
3644 case ocColRowNameAuto : ScColRowNameAuto(); break;
3645 case ocIf : ScIfJump(); break;
3646 case ocIfError : ScIfError( false ); break;
3647 case ocIfNA : ScIfError( true ); break;
3648 case ocChoose : ScChooseJump(); break;
3649 case ocAdd : ScAdd(); break;
3650 case ocSub : ScSub(); break;
3651 case ocMul : ScMul(); break;
3652 case ocDiv : ScDiv(); break;
3653 case ocAmpersand : ScAmpersand(); break;
3654 case ocPow : ScPow(); break;
3655 case ocEqual : ScEqual(); break;
3656 case ocNotEqual : ScNotEqual(); break;
3657 case ocLess : ScLess(); break;
3658 case ocGreater : ScGreater(); break;
3659 case ocLessEqual : ScLessEqual(); break;
3660 case ocGreaterEqual : ScGreaterEqual(); break;
3661 case ocAnd : ScAnd(); break;
3662 case ocOr : ScOr(); break;
3663 case ocXor : ScXor(); break;
3664 case ocIntersect : ScIntersect(); break;
3665 case ocRange : ScRangeFunc(); break;
3666 case ocUnion : ScUnionFunc(); break;
3667 case ocNot : ScNot(); break;
3668 case ocNegSub :
3669 case ocNeg : ScNeg(); break;
3670 case ocPercentSign : ScPercentSign(); break;
3671 case ocPi : ScPi(); break;
3672 case ocRandom : ScRandom(); break;
3673 case ocTrue : ScTrue(); break;
3674 case ocFalse : ScFalse(); break;
3675 case ocGetActDate : ScGetActDate(); break;
3676 case ocGetActTime : ScGetActTime(); break;
3677 case ocNotAvail : PushError( NOTAVAILABLE); break;
3678 case ocDeg : ScDeg(); break;
3679 case ocRad : ScRad(); break;
3680 case ocSin : ScSin(); break;
3681 case ocCos : ScCos(); break;
3682 case ocTan : ScTan(); break;
3683 case ocCot : ScCot(); break;
3684 case ocArcSin : ScArcSin(); break;
3685 case ocArcCos : ScArcCos(); break;
3686 case ocArcTan : ScArcTan(); break;
3687 case ocArcCot : ScArcCot(); break;
3688 case ocSinHyp : ScSinHyp(); break;
3689 case ocCosHyp : ScCosHyp(); break;
3690 case ocTanHyp : ScTanHyp(); break;
3691 case ocCotHyp : ScCotHyp(); break;
3692 case ocArcSinHyp : ScArcSinHyp(); break;
3693 case ocArcCosHyp : ScArcCosHyp(); break;
3694 case ocArcTanHyp : ScArcTanHyp(); break;
3695 case ocArcCotHyp : ScArcCotHyp(); break;
3696 case ocCosecant : ScCosecant(); break;
3697 case ocSecant : ScSecant(); break;
3698 case ocCosecantHyp : ScCosecantHyp(); break;
3699 case ocSecantHyp : ScSecantHyp(); break;
3700 case ocExp : ScExp(); break;
3701 case ocLn : ScLn(); break;
3702 case ocLog10 : ScLog10(); break;
3703 case ocSqrt : ScSqrt(); break;
3704 case ocFact : ScFact(); break;
3705 case ocGetYear : ScGetYear(); break;
3706 case ocGetMonth : ScGetMonth(); break;
3707 case ocGetDay : ScGetDay(); break;
3708 case ocGetDayOfWeek : ScGetDayOfWeek(); break;
3709 case ocWeek : ScGetWeekOfYear(); break;
3710 case ocEasterSunday : ScEasterSunday(); break;
3711 case ocNetWorkdays : ScNetWorkdays( false); break;
3712 case ocNetWorkdays_MS : ScNetWorkdays( true ); break;
3713 case ocWorkday_MS : ScWorkday_MS(); break;
3714 case ocGetHour : ScGetHour(); break;
3715 case ocGetMin : ScGetMin(); break;
3716 case ocGetSec : ScGetSec(); break;
3717 case ocPlusMinus : ScPlusMinus(); break;
3718 case ocAbs : ScAbs(); break;
3719 case ocInt : ScInt(); break;
3720 case ocEven : ScEven(); break;
3721 case ocOdd : ScOdd(); break;
3722 case ocPhi : ScPhi(); break;
3723 case ocGauss : ScGauss(); break;
3724 case ocStdNormDist : ScStdNormDist(); break;
3725 case ocStdNormDist_MS : ScStdNormDist_MS(); break;
3726 case ocFisher : ScFisher(); break;
3727 case ocFisherInv : ScFisherInv(); break;
3728 case ocIsEmpty : ScIsEmpty(); break;
3729 case ocIsString : ScIsString(); break;
3730 case ocIsNonString : ScIsNonString(); break;
3731 case ocIsLogical : ScIsLogical(); break;
3732 case ocType : ScType(); break;
3733 case ocCell : ScCell(); break;
3734 case ocIsRef : ScIsRef(); break;
3735 case ocIsValue : ScIsValue(); break;
3736 case ocIsFormula : ScIsFormula(); break;
3737 case ocFormula : ScFormula(); break;
3738 case ocIsNA : ScIsNV(); break;
3739 case ocIsErr : ScIsErr(); break;
3740 case ocIsError : ScIsError(); break;
3741 case ocIsEven : ScIsEven(); break;
3742 case ocIsOdd : ScIsOdd(); break;
3743 case ocN : ScN(); break;
3744 case ocGetDateValue : ScGetDateValue(); break;
3745 case ocGetTimeValue : ScGetTimeValue(); break;
3746 case ocCode : ScCode(); break;
3747 case ocTrim : ScTrim(); break;
3748 case ocUpper : ScUpper(); break;
3749 case ocProper : ScProper(); break;
3750 case ocLower : ScLower(); break;
3751 case ocLen : ScLen(); break;
3752 case ocT : ScT(); break;
3753 case ocClean : ScClean(); break;
3754 case ocValue : ScValue(); break;
3755 case ocNumberValue : ScNumberValue(); break;
3756 case ocChar : ScChar(); break;
3757 case ocArcTan2 : ScArcTan2(); break;
3758 case ocMod : ScMod(); break;
3759 case ocPower : ScPower(); break;
3760 case ocRound : ScRound(); break;
3761 case ocRoundUp : ScRoundUp(); break;
3762 case ocTrunc :
3763 case ocRoundDown : ScRoundDown(); break;
3764 case ocCeil : ScCeil( true ); break;
3765 case ocCeil_MS : ScCeil_MS(); break;
3766 case ocCeil_Precise :
3767 case ocCeil_ISO : ScCeil_Precise(); break;
3768 case ocCeil_Math : ScCeil( false ); break;
3769 case ocFloor : ScFloor( true ); break;
3770 case ocFloor_MS : ScFloor_MS(); break;
3771 case ocFloor_Precise : ScFloor_Precise(); break;
3772 case ocFloor_Math : ScFloor( false ); break;
3773 case ocSumProduct : ScSumProduct(); break;
3774 case ocSumSQ : ScSumSQ(); break;
3775 case ocSumX2MY2 : ScSumX2MY2(); break;
3776 case ocSumX2DY2 : ScSumX2DY2(); break;
3777 case ocSumXMY2 : ScSumXMY2(); break;
3778 case ocLog : ScLog(); break;
3779 case ocGCD : ScGCD(); break;
3780 case ocLCM : ScLCM(); break;
3781 case ocGetDate : ScGetDate(); break;
3782 case ocGetTime : ScGetTime(); break;
3783 case ocGetDiffDate : ScGetDiffDate(); break;
3784 case ocGetDiffDate360 : ScGetDiffDate360(); break;
3785 case ocGetDateDif : ScGetDateDif(); break;
3786 case ocMin : ScMin( false ); break;
3787 case ocMinA : ScMin( true ); break;
3788 case ocMax : ScMax( false ); break;
3789 case ocMaxA : ScMax( true ); break;
3790 case ocSum : ScSum(); break;
3791 case ocProduct : ScProduct(); break;
3792 case ocNPV : ScNPV(); break;
3793 case ocIRR : ScIRR(); break;
3794 case ocMIRR : ScMIRR(); break;
3795 case ocISPMT : ScISPMT(); break;
3796 case ocAverage : ScAverage( false ); break;
3797 case ocAverageA : ScAverage( true ); break;
3798 case ocCount : ScCount(); break;
3799 case ocCount2 : ScCount2(); break;
3800 case ocVar :
3801 case ocVarS : ScVar( false ); break;
3802 case ocVarA : ScVar( true ); break;
3803 case ocVarP :
3804 case ocVarP_MS : ScVarP( false ); break;
3805 case ocVarPA : ScVarP( true ); break;
3806 case ocStDev :
3807 case ocStDevS : ScStDev( false ); break;
3808 case ocStDevA : ScStDev( true ); break;
3809 case ocStDevP :
3810 case ocStDevP_MS : ScStDevP( false ); break;
3811 case ocStDevPA : ScStDevP( true ); break;
3812 case ocPV : ScPV(); break;
3813 case ocSYD : ScSYD(); break;
3814 case ocDDB : ScDDB(); break;
3815 case ocDB : ScDB(); break;
3816 case ocVBD : ScVDB(); break;
3817 case ocDuration : ScDuration(); break;
3818 case ocSLN : ScSLN(); break;
3819 case ocPMT : ScPMT(); break;
3820 case ocColumns : ScColumns(); break;
3821 case ocRows : ScRows(); break;
3822 case ocSheets : ScSheets(); break;
3823 case ocColumn : ScColumn(); break;
3824 case ocRow : ScRow(); break;
3825 case ocSheet : ScSheet(); break;
3826 case ocRRI : ScRRI(); break;
3827 case ocFV : ScFV(); break;
3828 case ocNper : ScNper(); break;
3829 case ocRate : ScRate(); break;
3830 case ocFilterXML : ScFilterXML(); break;
3831 case ocWebservice : ScWebservice(); break;
3832 case ocEncodeURL : ScEncodeURL(); break;
3833 case ocColor : ScColor(); break;
3834 case ocErf_MS : ScErf(); break;
3835 case ocErfc_MS : ScErfc(); break;
3836 case ocIpmt : ScIpmt(); break;
3837 case ocPpmt : ScPpmt(); break;
3838 case ocCumIpmt : ScCumIpmt(); break;
3839 case ocCumPrinc : ScCumPrinc(); break;
3840 case ocEffective : ScEffective(); break;
3841 case ocNominal : ScNominal(); break;
3842 case ocSubTotal : ScSubTotal(); break;
3843 case ocAggregate : ScAggregate(); break;
3844 case ocDBSum : ScDBSum(); break;
3845 case ocDBCount : ScDBCount(); break;
3846 case ocDBCount2 : ScDBCount2(); break;
3847 case ocDBAverage : ScDBAverage(); break;
3848 case ocDBGet : ScDBGet(); break;
3849 case ocDBMax : ScDBMax(); break;
3850 case ocDBMin : ScDBMin(); break;
3851 case ocDBProduct : ScDBProduct(); break;
3852 case ocDBStdDev : ScDBStdDev(); break;
3853 case ocDBStdDevP : ScDBStdDevP(); break;
3854 case ocDBVar : ScDBVar(); break;
3855 case ocDBVarP : ScDBVarP(); break;
3856 case ocIndirect : ScIndirect(); break;
3857 case ocAddress : ScAddressFunc(); break;
3858 case ocMatch : ScMatch(); break;
3859 case ocCountEmptyCells : ScCountEmptyCells(); break;
3860 case ocCountIf : ScCountIf(); break;
3861 case ocSumIf : ScSumIf(); break;
3862 case ocAverageIf : ScAverageIf(); break;
3863 case ocSumIfs : ScSumIfs(); break;
3864 case ocAverageIfs : ScAverageIfs(); break;
3865 case ocCountIfs : ScCountIfs(); break;
3866 case ocLookup : ScLookup(); break;
3867 case ocVLookup : ScVLookup(); break;
3868 case ocHLookup : ScHLookup(); break;
3869 case ocIndex : ScIndex(); break;
3870 case ocMultiArea : ScMultiArea(); break;
3871 case ocOffset : ScOffset(); break;
3872 case ocAreas : ScAreas(); break;
3873 case ocCurrency : ScCurrency(); break;
3874 case ocReplace : ScReplace(); break;
3875 case ocFixed : ScFixed(); break;
3876 case ocFind : ScFind(); break;
3877 case ocExact : ScExact(); break;
3878 case ocLeft : ScLeft(); break;
3879 case ocRight : ScRight(); break;
3880 case ocSearch : ScSearch(); break;
3881 case ocMid : ScMid(); break;
3882 case ocText : ScText(); break;
3883 case ocSubstitute : ScSubstitute(); break;
3884 case ocRept : ScRept(); break;
3885 case ocConcat : ScConcat(); break;
3886 case ocMatValue : ScMatValue(); break;
3887 case ocMatrixUnit : ScEMat(); break;
3888 case ocMatDet : ScMatDet(); break;
3889 case ocMatInv : ScMatInv(); break;
3890 case ocMatMult : ScMatMult(); break;
3891 case ocMatTrans : ScMatTrans(); break;
3892 case ocMatRef : ScMatRef(); break;
3893 case ocB : ScB(); break;
3894 case ocNormDist : ScNormDist( 3 ); break;
3895 case ocNormDist_MS : ScNormDist( 4 ); break;
3896 case ocExpDist :
3897 case ocExpDist_MS : ScExpDist(); break;
3898 case ocBinomDist :
3899 case ocBinomDist_MS : ScBinomDist(); break;
3900 case ocPoissonDist :
3901 case ocPoissonDist_MS : ScPoissonDist(); break;
3902 case ocCombin : ScCombin(); break;
3903 case ocCombinA : ScCombinA(); break;
3904 case ocPermut : ScPermut(); break;
3905 case ocPermutationA : ScPermutationA(); break;
3906 case ocHypGeomDist : ScHypGeomDist(); break;
3907 case ocHypGeomDist_MS : ScHypGeomDist_MS(); break;
3908 case ocLogNormDist : ScLogNormDist( 1 ); break;
3909 case ocLogNormDist_MS : ScLogNormDist( 4 ); break;
3910 case ocTDist : ScTDist(); break;
3911 case ocTDist_MS : ScTDist_MS(); break;
3912 case ocTDist_RT : ScTDist_T( 1 ); break;
3913 case ocTDist_2T : ScTDist_T( 2 ); break;
3914 case ocFDist :
3915 case ocFDist_RT : ScFDist(); break;
3916 case ocFDist_LT : ScFDist_LT(); break;
3917 case ocChiDist :
3918 case ocChiDist_MS : ScChiDist(); break;
3919 case ocChiSqDist : ScChiSqDist(); break;
3920 case ocChiSqDist_MS : ScChiSqDist_MS(); break;
3921 case ocStandard : ScStandard(); break;
3922 case ocAveDev : ScAveDev(); break;
3923 case ocDevSq : ScDevSq(); break;
3924 case ocKurt : ScKurt(); break;
3925 case ocSkew : ScSkew(); break;
3926 case ocSkewp : ScSkewp(); break;
3927 case ocModalValue : ScModalValue(); break;
3928 case ocModalValue_MS : ScModalValue(); break;
3929 case ocModalValue_Multi : ScModalValue_Multi(); break;
3930 case ocMedian : ScMedian(); break;
3931 case ocGeoMean : ScGeoMean(); break;
3932 case ocHarMean : ScHarMean(); break;
3933 case ocWeibull :
3934 case ocWeibull_MS : ScWeibull(); break;
3935 case ocBinomInv :
3936 case ocCritBinom : ScCritBinom(); break;
3937 case ocNegBinomVert : ScNegBinomDist(); break;
3938 case ocNegBinomDist_MS : ScNegBinomDist_MS(); break;
3939 case ocNoName : ScNoName(); break;
3940 case ocBad : ScBadName(); break;
3941 case ocZTest :
3942 case ocZTest_MS : ScZTest(); break;
3943 case ocTTest :
3944 case ocTTest_MS : ScTTest(); break;
3945 case ocFTest :
3946 case ocFTest_MS : ScFTest(); break;
3947 case ocRank :
3948 case ocRank_Eq : ScRank( false ); break;
3949 case ocRank_Avg : ScRank( true ); break;
3950 case ocPercentile :
3951 case ocPercentile_Inc : ScPercentile( true ); break;
3952 case ocPercentile_Exc : ScPercentile( false ); break;
3953 case ocPercentrank :
3954 case ocPercentrank_Inc : ScPercentrank( true ); break;
3955 case ocPercentrank_Exc : ScPercentrank( false ); break;
3956 case ocLarge : ScLarge(); break;
3957 case ocSmall : ScSmall(); break;
3958 case ocFrequency : ScFrequency(); break;
3959 case ocQuartile :
3960 case ocQuartile_Inc : ScQuartile( true ); break;
3961 case ocQuartile_Exc : ScQuartile( false ); break;
3962 case ocNormInv :
3963 case ocNormInv_MS : ScNormInv(); break;
3964 case ocSNormInv :
3965 case ocSNormInv_MS : ScSNormInv(); break;
3966 case ocConfidence :
3967 case ocConfidence_N : ScConfidence(); break;
3968 case ocConfidence_T : ScConfidenceT(); break;
3969 case ocTrimMean : ScTrimMean(); break;
3970 case ocProb : ScProbability(); break;
3971 case ocCorrel : ScCorrel(); break;
3972 case ocCovar :
3973 case ocCovarianceP : ScCovarianceP(); break;
3974 case ocCovarianceS : ScCovarianceS(); break;
3975 case ocPearson : ScPearson(); break;
3976 case ocRSQ : ScRSQ(); break;
3977 case ocSTEYX : ScSTEYX(); break;
3978 case ocSlope : ScSlope(); break;
3979 case ocIntercept : ScIntercept(); break;
3980 case ocTrend : ScTrend(); break;
3981 case ocGrowth : ScGrowth(); break;
3982 case ocLinest : ScLinest(); break;
3983 case ocLogest : ScLogest(); break;
3984 case ocForecast : ScForecast(); break;
3985 case ocGammaLn :
3986 case ocGammaLn_MS : ScLogGamma(); break;
3987 case ocGamma : ScGamma(); break;
3988 case ocGammaDist : ScGammaDist( 3 ); break;
3989 case ocGammaDist_MS : ScGammaDist( 4 ); break;
3990 case ocGammaInv :
3991 case ocGammaInv_MS : ScGammaInv(); break;
3992 case ocChiTest :
3993 case ocChiTest_MS : ScChiTest(); break;
3994 case ocChiInv :
3995 case ocChiInv_MS : ScChiInv(); break;
3996 case ocChiSqInv :
3997 case ocChiSqInv_MS : ScChiSqInv(); break;
3998 case ocTInv :
3999 case ocTInv_2T : ScTInv( 2 ); break;
4000 case ocTInv_MS : ScTInv( 4 ); break;
4001 case ocFInv :
4002 case ocFInv_RT : ScFInv(); break;
4003 case ocFInv_LT : ScFInv_LT(); break;
4004 case ocLogInv :
4005 case ocLogInv_MS : ScLogNormInv(); break;
4006 case ocBetaDist : ScBetaDist(); break;
4007 case ocBetaDist_MS : ScBetaDist_MS(); break;
4008 case ocBetaInv :
4009 case ocBetaInv_MS : ScBetaInv(); break;
4010 case ocExternal : ScExternal(); break;
4011 case ocTableOp : ScTableOp(); break;
4012 case ocStop : break;
4013 case ocErrorType : ScErrorType(); break;
4014 case ocErrorType_ODF : ScErrorType_ODF(); break;
4015 case ocCurrent : ScCurrent(); break;
4016 case ocStyle : ScStyle(); break;
4017 case ocDde : ScDde(); break;
4018 case ocBase : ScBase(); break;
4019 case ocDecimal : ScDecimal(); break;
4020 case ocConvert : ScConvert(); break;
4021 case ocEuroConvert : ScEuroConvert(); break;
4022 case ocRoman : ScRoman(); break;
4023 case ocArabic : ScArabic(); break;
4024 case ocInfo : ScInfo(); break;
4025 case ocHyperLink : ScHyperLink(); break;
4026 case ocBahtText : ScBahtText(); break;
4027 case ocGetPivotData : ScGetPivotData(); break;
4028 case ocJis : ScJis(); break;
4029 case ocAsc : ScAsc(); break;
4030 case ocLenB : ScLenB(); break;
4031 case ocRightB : ScRightB(); break;
4032 case ocLeftB : ScLeftB(); break;
4033 case ocMidB : ScMidB(); break;
4034 case ocUnicode : ScUnicode(); break;
4035 case ocUnichar : ScUnichar(); break;
4036 case ocBitAnd : ScBitAnd(); break;
4037 case ocBitOr : ScBitOr(); break;
4038 case ocBitXor : ScBitXor(); break;
4039 case ocBitRshift : ScBitRshift(); break;
4040 case ocBitLshift : ScBitLshift(); break;
4041 case ocTTT : ScTTT(); break;
4042 case ocDebugVar : ScDebugVar(); break;
4043 case ocNone : nFuncFmtType = css::util::NumberFormat::UNDEFINED; break;
4044 default : PushError( errUnknownOpCode); break;
4047 // If the function pushed a subroutine as result, continue with
4048 // execution of the subroutine.
4049 if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall
4050 /* && pStack[sp-1]->GetType() == svSubroutine */)
4052 Pop(); continue;
4055 if (FormulaCompiler::IsOpCodeVolatile(eOp))
4056 meVolatileType = VOLATILE;
4058 // Remember result matrix in case it could be reused.
4059 if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
4060 pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
4061 pStack[sp-1]));
4063 // outer function determines format of an expression
4064 if ( nFuncFmtType != css::util::NumberFormat::UNDEFINED )
4066 nRetTypeExpr = nFuncFmtType;
4067 // inherit the format index only for currency formats
4068 nRetIndexExpr = ( nFuncFmtType == css::util::NumberFormat::CURRENCY ?
4069 nFuncFmtIndex : 0 );
4073 // Need a clean stack environment for the JumpMatrix to work.
4074 if (nGlobalError && eOp != ocPush && sp > nStackBase + 1)
4076 // Not all functions pop all parameters in case an error is
4077 // generated. Clean up stack. Assumes that every function pushes a
4078 // result, may be arbitrary in case of error.
4079 const FormulaToken* pLocalResult = pStack[ sp - 1 ];
4080 while (sp > nStackBase)
4081 Pop();
4082 PushTempToken( *pLocalResult );
4085 bool bGotResult;
4088 bGotResult = false;
4089 sal_uInt8 nLevel = 0;
4090 if ( GetStackType( ++nLevel ) == svJumpMatrix )
4091 ; // nothing
4092 else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4093 ; // nothing
4094 else
4095 nLevel = 0;
4096 if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
4097 bGotResult = JumpMatrix( nLevel );
4098 else
4099 pJumpMatrix = NULL;
4100 } while ( bGotResult );
4102 // Functions that evaluate an error code and directly set nGlobalError to 0,
4103 // usage: switch( OpCode ) { CASE_OCERRFUNC statements; }
4104 #define CASE_OCERRFUNC \
4105 case ocCount : \
4106 case ocCount2 : \
4107 case ocErrorType : \
4108 case ocIsEmpty : \
4109 case ocIsErr : \
4110 case ocIsError : \
4111 case ocIsFormula : \
4112 case ocIsLogical : \
4113 case ocIsNA : \
4114 case ocIsNonString : \
4115 case ocIsRef : \
4116 case ocIsString : \
4117 case ocIsValue : \
4118 case ocN : \
4119 case ocType : \
4120 case ocIfError : \
4121 case ocIfNA : \
4122 case ocErrorType_ODF :
4124 switch ( eOp )
4126 CASE_OCERRFUNC
4127 ++ nErrorFunction;
4128 default:
4129 ; // nothing
4131 if ( nGlobalError )
4133 if ( !nErrorFunctionCount )
4134 { // count of errorcode functions in formula
4135 for ( FormulaToken* t = rArr.FirstRPN(); t; t = rArr.NextRPN() )
4137 switch ( t->GetOpCode() )
4139 CASE_OCERRFUNC
4140 ++nErrorFunctionCount;
4141 default:
4142 ; // nothing
4146 if ( nErrorFunction >= nErrorFunctionCount )
4147 ++nErrorFunction; // that's it, error => terminate
4151 // End: obtain result
4153 if( sp )
4155 pCur = pStack[ sp-1 ];
4156 if( pCur->GetOpCode() == ocPush )
4158 switch( pCur->GetType() )
4160 case svEmptyCell:
4161 ; // nothing
4162 break;
4163 case svError:
4164 nGlobalError = pCur->GetError();
4165 break;
4166 case svDouble :
4167 if ( nFuncFmtType == css::util::NumberFormat::UNDEFINED )
4169 nRetTypeExpr = css::util::NumberFormat::NUMBER;
4170 nRetIndexExpr = 0;
4172 break;
4173 case svString :
4174 nRetTypeExpr = css::util::NumberFormat::TEXT;
4175 nRetIndexExpr = 0;
4176 break;
4177 case svSingleRef :
4179 ScAddress aAdr;
4180 PopSingleRef( aAdr );
4181 if( !nGlobalError )
4182 PushCellResultToken( false, aAdr,
4183 &nRetTypeExpr, &nRetIndexExpr);
4185 break;
4186 case svRefList :
4187 PopError(); // maybe #REF! takes precedence over #VALUE!
4188 PushError( errNoValue);
4189 break;
4190 case svDoubleRef :
4192 if ( bMatrixFormula )
4193 { // create matrix for {=A1:A5}
4194 PopDoubleRefPushMatrix();
4195 ScMatrixRef xMat = PopMatrix();
4196 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4198 else
4200 ScRange aRange;
4201 PopDoubleRef( aRange );
4202 ScAddress aAdr;
4203 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr))
4204 PushCellResultToken( false, aAdr,
4205 &nRetTypeExpr, &nRetIndexExpr);
4208 break;
4209 case svExternalDoubleRef:
4211 ScMatrixRef xMat;
4212 PopExternalDoubleRef(xMat);
4213 QueryMatrixType(xMat, nRetTypeExpr, nRetIndexExpr);
4215 break;
4216 case svMatrix :
4218 sc::RangeMatrix aMat = PopRangeMatrix();
4219 if (aMat.isRangeValid())
4221 // This matrix represents a range reference. Apply implicit intersection.
4222 double fVal = applyImplicitIntersection(aMat, aPos);
4223 if (rtl::math::isNan(fVal))
4224 PushNoValue();
4225 else
4226 PushInt(fVal);
4228 else
4229 // This is a normal matrix.
4230 QueryMatrixType(aMat.mpMat, nRetTypeExpr, nRetIndexExpr);
4232 break;
4233 case svExternalSingleRef:
4235 ScExternalRefCache::TokenRef pToken;
4236 ScExternalRefCache::CellFormat aFmt;
4237 PopExternalSingleRef(pToken, &aFmt);
4238 if (nGlobalError)
4239 break;
4241 PushTempToken(*pToken);
4243 if (aFmt.mbIsSet)
4245 nFuncFmtType = aFmt.mnType;
4246 nFuncFmtIndex = aFmt.mnIndex;
4249 break;
4250 default :
4251 SetError( errUnknownStackVariable);
4254 else
4255 SetError( errUnknownStackVariable);
4257 else
4258 SetError( errNoCode);
4260 if( nRetTypeExpr != css::util::NumberFormat::UNDEFINED )
4262 nRetFmtType = nRetTypeExpr;
4263 nRetFmtIndex = nRetIndexExpr;
4265 else if( nFuncFmtType != css::util::NumberFormat::UNDEFINED )
4267 nRetFmtType = nFuncFmtType;
4268 nRetFmtIndex = nFuncFmtIndex;
4270 else
4271 nRetFmtType = css::util::NumberFormat::NUMBER;
4273 if (nGlobalError && GetStackType() != svError )
4274 PushError( nGlobalError);
4276 // THE final result.
4277 xResult = PopToken();
4278 if (!xResult)
4279 xResult = new FormulaErrorToken( errUnknownStackVariable);
4281 // release tokens in expression stack
4282 FormulaToken** p = pStack;
4283 while( maxsp-- )
4284 (*p++)->DecRef();
4286 StackVar eType = xResult->GetType();
4287 if (eType == svMatrix)
4288 // Results are immutable in case they would be reused as input for new
4289 // interpreters.
4290 xResult.get()->GetMatrix()->SetImmutable( true);
4291 return eType;
4294 svl::SharedString ScInterpreter::GetStringResult() const
4296 return xResult->GetString();
4299 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */