update dev300-m57
[ooovba.git] / sc / source / core / tool / interpr4.cxx
blob5419420d28c653751a4a5d69550ce6a59e0bb710
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: interpr4.cxx,v $
10 * $Revision: 1.57.92.5 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
33 // INCLUDE ---------------------------------------------------------------
35 #include <rangelst.hxx>
36 #include <sfx2/app.hxx>
37 #include <sfx2/docfile.hxx>
38 #include <sfx2/objsh.hxx>
39 #include <sfx2/docfilt.hxx>
40 #include <basic/sbmeth.hxx>
41 #include <basic/sbmod.hxx>
42 #include <basic/sbstar.hxx>
43 #include <basic/sbx.hxx>
44 #include <basic/sbxobj.hxx>
45 #include <basic/sbuno.hxx>
46 #include <svtools/zforlist.hxx>
47 #include <tools/urlobj.hxx>
48 #include <rtl/logfile.hxx>
49 #include <stdlib.h>
50 #include <string.h>
51 #include <signal.h>
53 #include <com/sun/star/table/XCellRange.hpp>
54 #include <comphelper/processfactory.hxx>
56 #include "interpre.hxx"
57 #include "global.hxx"
58 #include "dbcolect.hxx"
59 #include "cell.hxx"
60 #include "callform.hxx"
61 #include "addincol.hxx"
62 #include "document.hxx"
63 #include "dociter.hxx"
64 #include "docoptio.hxx"
65 #include "scmatrix.hxx"
66 #include "adiasync.hxx"
67 #include "sc.hrc"
68 #include "cellsuno.hxx"
69 #include "optuno.hxx"
70 #include "rangeseq.hxx"
71 #include "addinlis.hxx"
72 #include "jumpmatrix.hxx"
73 #include "parclass.hxx"
74 #include "externalrefmgr.hxx"
75 #include "formula/FormulaCompiler.hxx"
76 #include "macromgr.hxx"
78 #include <math.h>
79 #include <float.h>
80 #include <map>
81 #include <algorithm>
82 #include <functional>
83 #include <vbahelper/vbahelper.hxx>
84 #include <basic/basmgr.hxx>
86 using namespace com::sun::star;
87 using namespace formula;
89 #define ADDIN_MAXSTRLEN 256
91 // Implementiert in ui\miscdlgs\teamdlg.cxx
93 extern void ShowTheTeam();
95 extern BOOL bOderSo; // in GLOBAL.CXX
97 //-----------------------------static data -----------------
99 #if SC_SPEW_ENABLED
100 ScSpew ScInterpreter::theSpew;
101 #endif
103 //-------------------------------------------------------------------------
104 // Funktionen fuer den Zugriff auf das Document
105 //-------------------------------------------------------------------------
108 void ScInterpreter::ReplaceCell( ScAddress& rPos )
110 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ReplaceCell" );
111 ScInterpreterTableOpParams* pTOp = pDok->aTableOpList.First();
112 while (pTOp)
114 if ( rPos == pTOp->aOld1 )
116 rPos = pTOp->aNew1;
117 return ;
119 else if ( rPos == pTOp->aOld2 )
121 rPos = pTOp->aNew2;
122 return ;
124 else
125 pTOp = pDok->aTableOpList.Next();
130 void ScInterpreter::ReplaceCell( SCCOL& rCol, SCROW& rRow, SCTAB& rTab )
132 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ReplaceCell" );
133 ScAddress aCellPos( rCol, rRow, rTab );
134 ScInterpreterTableOpParams* pTOp = pDok->aTableOpList.First();
135 while (pTOp)
137 if ( aCellPos == pTOp->aOld1 )
139 rCol = pTOp->aNew1.Col();
140 rRow = pTOp->aNew1.Row();
141 rTab = pTOp->aNew1.Tab();
142 return ;
144 else if ( aCellPos == pTOp->aOld2 )
146 rCol = pTOp->aNew2.Col();
147 rRow = pTOp->aNew2.Row();
148 rTab = pTOp->aNew2.Tab();
149 return ;
151 else
152 pTOp = pDok->aTableOpList.Next();
157 BOOL ScInterpreter::IsTableOpInRange( const ScRange& rRange )
159 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::IsTableOpInRange" );
160 if ( rRange.aStart == rRange.aEnd )
161 return FALSE; // not considered to be a range in TableOp sense
163 // we can't replace a single cell in a range
164 ScInterpreterTableOpParams* pTOp = pDok->aTableOpList.First();
165 while (pTOp)
167 if ( rRange.In( pTOp->aOld1 ) )
168 return TRUE;
169 if ( rRange.In( pTOp->aOld2 ) )
170 return TRUE;
171 pTOp = pDok->aTableOpList.Next();
173 return FALSE;
177 ULONG ScInterpreter::GetCellNumberFormat( const ScAddress& rPos, const ScBaseCell* pCell)
179 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetCellNumberFormat" );
180 ULONG nFormat;
181 USHORT nErr;
182 if ( pCell )
184 if ( pCell->GetCellType() == CELLTYPE_FORMULA )
185 nErr = ((ScFormulaCell*)pCell)->GetErrCode();
186 else
187 nErr = 0;
188 nFormat = pDok->GetNumberFormat( rPos );
189 if ( pCell->GetCellType() == CELLTYPE_FORMULA
190 && ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0) )
191 nFormat = ((ScFormulaCell*)pCell)->GetStandardFormat( *pFormatter,
192 nFormat );
194 else
196 nFormat = pDok->GetNumberFormat( rPos );
197 nErr = 0;
199 SetError(nErr);
200 return nFormat;
204 // nur ValueCell, Formelzellen speichern das Ergebnis bereits gerundet
205 double ScInterpreter::GetValueCellValue( const ScAddress& rPos, const ScValueCell* pCell )
207 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetValueCellValue" );
208 double fVal = pCell->GetValue();
209 if ( bCalcAsShown && fVal != 0.0 )
211 ULONG nFormat = pDok->GetNumberFormat( rPos );
212 fVal = pDok->RoundValueAsShown( fVal, nFormat );
214 return fVal;
218 double ScInterpreter::GetCellValue( const ScAddress& rPos, const ScBaseCell* pCell,
219 bool bNoValueAsError, bool bBlankAsZero )
221 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetCellValue" );
222 USHORT nErr = nGlobalError;
223 nGlobalError = 0;
224 double nVal = GetCellValueOrZero( rPos, pCell, bBlankAsZero );
225 if (!nGlobalError)
226 // no global error. good.
227 nGlobalError = nErr;
228 else if (nGlobalError == errCellNoValue)
229 // Internal cell-no-value error. If the caller wants to treat no
230 // value as error, then we need to translate this to a legitimate
231 // error number (#VALUE!). If not, we should re-assign the prior error
232 // number.
233 nGlobalError = bNoValueAsError ? errNoValue : nErr;
234 return nVal;
238 double ScInterpreter::GetCellValueOrZero( const ScAddress& rPos, const ScBaseCell* pCell, bool bBlankAsZero )
240 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetCellValueOrZero" );
241 double fValue;
242 if (pCell)
244 CellType eType = pCell->GetCellType();
245 switch ( eType )
247 case CELLTYPE_FORMULA:
249 ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
250 USHORT nErr = pFCell->GetErrCode();
251 if( !nErr )
253 if (pFCell->IsValue())
255 fValue = pFCell->GetValue();
256 pDok->GetNumberFormatInfo( nCurFmtType, nCurFmtIndex,
257 rPos, pFCell );
259 else
261 String aStr;
262 pFCell->GetString(aStr);
263 sal_uInt32 nFIndex = 0;
264 if (!pFormatter->IsNumberFormat(aStr, nFIndex, fValue))
266 SetError(errCellNoValue);
267 fValue = 0.0;
271 else
273 fValue = 0.0;
274 SetError(nErr);
277 break;
278 case CELLTYPE_VALUE:
280 fValue = ((ScValueCell*)pCell)->GetValue();
281 nCurFmtIndex = pDok->GetNumberFormat( rPos );
282 nCurFmtType = pFormatter->GetType( nCurFmtIndex );
283 if ( bCalcAsShown && fValue != 0.0 )
284 fValue = pDok->RoundValueAsShown( fValue, nCurFmtIndex );
286 break;
287 case CELLTYPE_STRING:
288 case CELLTYPE_EDIT:
289 #if 1 /* JEG : re-enable because compatibility is more important than consistency for this */
290 // Xcl does it, but SUM(A1:A2) differs from A1+A2. No good.
292 String aStr;
293 if ( eType == CELLTYPE_STRING )
294 ((ScStringCell*)pCell)->GetString( aStr );
295 else
296 ((ScEditCell*)pCell)->GetString( aStr );
297 sal_uInt32 nFIndex = 0; // damit default Land/Spr.
298 if ( !pFormatter->IsNumberFormat( aStr, nFIndex, fValue ) )
300 SetError(errCellNoValue); /* CellNoValue is not really an error */
301 fValue = 0.0;
304 break;
305 #endif
306 default:
307 if (!bBlankAsZero)
308 SetError(errCellNoValue);
309 fValue = 0.0;
312 else
313 fValue = 0.0;
314 return fValue;
318 void ScInterpreter::GetCellString( String& rStr, const ScBaseCell* pCell )
320 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetCellString" );
321 USHORT nErr = 0;
322 if (pCell)
324 switch (pCell->GetCellType())
326 case CELLTYPE_STRING:
327 ((ScStringCell*) pCell)->GetString(rStr);
328 break;
329 case CELLTYPE_EDIT:
330 ((ScEditCell*) pCell)->GetString(rStr);
331 break;
332 case CELLTYPE_FORMULA:
334 ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
335 nErr = pFCell->GetErrCode();
336 if (pFCell->IsValue())
338 double fVal = pFCell->GetValue();
339 ULONG nIndex = pFormatter->GetStandardFormat(
340 NUMBERFORMAT_NUMBER,
341 ScGlobal::eLnge);
342 pFormatter->GetInputLineString(fVal, nIndex, rStr);
344 else
345 pFCell->GetString(rStr);
347 break;
348 case CELLTYPE_VALUE:
350 double fVal = ((ScValueCell*) pCell)->GetValue();
351 ULONG nIndex = pFormatter->GetStandardFormat(
352 NUMBERFORMAT_NUMBER,
353 ScGlobal::eLnge);
354 pFormatter->GetInputLineString(fVal, nIndex, rStr);
356 break;
357 default:
358 rStr = ScGlobal::GetEmptyString();
359 break;
362 else
363 rStr = ScGlobal::GetEmptyString();
364 SetError(nErr);
367 static sal_Bool lcl_IsHalfWidthKatakana ( const String& rString )
369 sal_Int32 nLen = rString.Len();
371 for ( sal_Int32 i = 0; i < nLen; ++i )
373 if ( rString.GetChar(i) < 0xFF00 || rString.GetChar(i) > 0xFFEF )
374 return sal_False;
377 return sal_True;
380 static sal_Bool lcl_IsFullWidthKatakana ( const String& rString )
382 sal_Int32 nLen = rString.Len();
384 for ( sal_Int32 i = 0; i < nLen; ++i )
386 if ( rString.GetChar(i) < 0x30A0 || rString.GetChar(i) > 0x30FF )
387 return sal_False;
390 return sal_True;
393 static sal_Bool lcl_IsFullWidthHiragana ( const String& rString )
395 sal_Int32 nLen = rString.Len();
397 for ( sal_Int32 i = 0; i < nLen; ++i )
399 if ( rString.GetChar(i) < 0x3040 || rString.GetChar(i) > 0x309F )
400 return sal_False;
403 return sal_True;
406 static sal_uInt16 lcl_GetKanaType ( const String rText )
408 sal_uInt16 aKanaType = 0;
410 if ( lcl_IsHalfWidthKatakana ( rText ) )
411 aKanaType = 0x00;
412 else if ( lcl_IsFullWidthKatakana ( rText ) )
413 aKanaType = 0x01;
414 else if ( lcl_IsFullWidthHiragana ( rText ) )
415 aKanaType = 0x02;
417 return aKanaType;
420 static void lcl_ConvertToKatakana( ScDocument* pDoc, String& rStr )
422 sal_uInt16 nKanaType = lcl_GetKanaType(rStr);
423 sal_Int32 nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
424 switch (nKanaType)
426 case 0x00:
427 // half-width katakana or full-width alphabet.
428 nType = com::sun::star::i18n::TransliterationModules_HALFWIDTH_FULLWIDTH;
429 break;
430 case 0x02:
431 // full-width hiragana.
432 nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
433 break;
434 case 0x01:
435 default:
436 // full-width katakana. no need to convert this.
437 return;
439 utl::TransliterationWrapper aTranslitarationWrapper( pDoc->GetServiceManager(), nType );
440 com::sun::star::uno::Sequence<sal_Int32> aOffsets;
441 rStr = aTranslitarationWrapper.transliterate( rStr, LANGUAGE_JAPANESE, 0, rStr.Len(), &aOffsets );
444 static void lcl_GetPhoneticString ( ScDocument *pDoc, String& rStr, const ScBaseCell* pCell )
446 ScPhonetic aPhonetic;
447 String aBaseString;
448 switch (pCell->GetCellType())
450 case CELLTYPE_STRING:
451 static_cast<const ScStringCell*>(pCell)->GetString(aBaseString);
452 static_cast<const ScAsianStringCell*>(pCell)->GetPhonetic(aPhonetic);
453 break;
454 case CELLTYPE_EDIT:
455 static_cast<const ScEditCell*>(pCell)->GetString(aBaseString);
456 static_cast<const ScAsianEditCell*>(pCell)->GetPhonetic(aPhonetic);
457 break;
458 default:
459 // Not a supported cell type.
460 return;
463 if (aPhonetic.IsEmpty())
464 // No phonetic string exists. Bail out.
465 return;
467 const String& rPhoneticString = aPhonetic.GetString();
468 PhoneticPortionVec portions = aPhonetic.GetPortions();
469 sal_uInt16 nPortionCount = portions.size();
471 String tmpString;
472 if ( nPortionCount > 0 )
474 sal_uInt16 pos = 0;
475 for ( sal_uInt16 idx = 0; idx < nPortionCount; ++idx )
477 const PhoneticPortion& portion = portions[idx];
479 // Get the end position in the phonetic text.
480 sal_uInt16 nPhEndPos = idx < nPortionCount-1 ? portions[idx+1].mncpa : rPhoneticString.Len();
482 tmpString += aBaseString.Copy(pos, portion.mncpm - pos);
483 pos = portion.mncpm + portion.mnccm;
484 tmpString += rPhoneticString.Copy(portion.mncpa, nPhEndPos - portion.mncpa);
486 if ( pos < aBaseString.Len() )
487 tmpString += aBaseString.Copy(pos, aBaseString.Len() - pos);
489 else
491 tmpString = rPhoneticString;
494 sal_Int32 nType;
495 switch ( lcl_GetKanaType ( rPhoneticString ))
497 case 0x00:
498 nType = com::sun::star::i18n::TransliterationModules_FULLWIDTH_HALFWIDTH;
499 break;
500 case 0x01:
501 nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
502 break;
503 case 0x02:
504 nType = com::sun::star::i18n::TransliterationModules_KATAKANA_HIRAGANA;
505 break;
506 default:
507 nType = com::sun::star::i18n::TransliterationModules_HIRAGANA_KATAKANA;
508 break;
511 utl::TransliterationWrapper aTranslitarationWrapper( pDoc->GetServiceManager(), nType );
512 com::sun::star::uno::Sequence<sal_Int32> aOffsets;
513 rStr = aTranslitarationWrapper.transliterate( tmpString, LANGUAGE_JAPANESE, 0, tmpString.Len(), &aOffsets );
516 void ScInterpreter::GetCellPhoneticString( String& rStr, const ScBaseCell* pCell )
518 USHORT nErr = 0;
519 if ( pCell )
521 switch ( pCell->GetCellType() )
523 case CELLTYPE_STRING:
524 if ( static_cast<const ScStringCell*>(pCell)->HasPhonetic() )
525 lcl_GetPhoneticString(pDok, rStr, pCell);
526 else
528 static_cast<const ScStringCell*>(pCell)->GetString(rStr);
529 lcl_ConvertToKatakana(pDok, rStr);
531 break;
532 case CELLTYPE_EDIT:
533 if ( static_cast<const ScEditCell*>(pCell)->HasPhonetic() )
534 lcl_GetPhoneticString(pDok, rStr, pCell);
535 else
537 static_cast<const ScEditCell*>(pCell)->GetString(rStr);
538 lcl_ConvertToKatakana(pDok, rStr);
540 break;
541 default:
542 rStr = ScGlobal::GetEmptyString();
543 break;
546 else
547 rStr = ScGlobal::GetEmptyString();
548 SetError(nErr);
551 BOOL ScInterpreter::CreateDoubleArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
552 SCCOL nCol2, SCROW nRow2, SCTAB nTab2, BYTE* pCellArr)
554 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::CreateDoubleArr" );
555 #if SC_ROWLIMIT_MORE_THAN_64K
556 #error row limit 64k
557 #endif
558 USHORT nCount = 0;
559 USHORT* p = (USHORT*) pCellArr;
560 *p++ = static_cast<USHORT>(nCol1);
561 *p++ = static_cast<USHORT>(nRow1);
562 *p++ = static_cast<USHORT>(nTab1);
563 *p++ = static_cast<USHORT>(nCol2);
564 *p++ = static_cast<USHORT>(nRow2);
565 *p++ = static_cast<USHORT>(nTab2);
566 USHORT* pCount = p;
567 *p++ = 0;
568 USHORT nPos = 14;
569 SCTAB nTab = nTab1;
570 ScAddress aAdr;
571 while (nTab <= nTab2)
573 aAdr.SetTab( nTab );
574 SCROW nRow = nRow1;
575 while (nRow <= nRow2)
577 aAdr.SetRow( nRow );
578 SCCOL nCol = nCol1;
579 while (nCol <= nCol2)
581 aAdr.SetCol( nCol );
582 ScBaseCell* pCell = pDok->GetCell( aAdr );
583 if (pCell)
585 USHORT nErr = 0;
586 double nVal = 0.0;
587 BOOL bOk = TRUE;
588 switch ( pCell->GetCellType() )
590 case CELLTYPE_VALUE :
591 nVal = GetValueCellValue( aAdr, (ScValueCell*)pCell );
592 break;
593 case CELLTYPE_FORMULA :
594 if (((ScFormulaCell*)pCell)->IsValue())
596 nErr = ((ScFormulaCell*)pCell)->GetErrCode();
597 nVal = ((ScFormulaCell*)pCell)->GetValue();
599 else
600 bOk = FALSE;
601 break;
602 default :
603 bOk = FALSE;
604 break;
606 if (bOk)
608 if ((nPos + (4 * sizeof(USHORT)) + sizeof(double)) > MAXARRSIZE)
609 return FALSE;
610 *p++ = static_cast<USHORT>(nCol);
611 *p++ = static_cast<USHORT>(nRow);
612 *p++ = static_cast<USHORT>(nTab);
613 *p++ = nErr;
614 memcpy( p, &nVal, sizeof(double));
615 nPos += 8 + sizeof(double);
616 p = (USHORT*) ( pCellArr + nPos );
617 nCount++;
620 nCol++;
622 nRow++;
624 nTab++;
626 *pCount = nCount;
627 return TRUE;
631 BOOL ScInterpreter::CreateStringArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
632 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
633 BYTE* pCellArr)
635 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::CreateStringArr" );
636 #if SC_ROWLIMIT_MORE_THAN_64K
637 #error row limit 64k
638 #endif
639 USHORT nCount = 0;
640 USHORT* p = (USHORT*) pCellArr;
641 *p++ = static_cast<USHORT>(nCol1);
642 *p++ = static_cast<USHORT>(nRow1);
643 *p++ = static_cast<USHORT>(nTab1);
644 *p++ = static_cast<USHORT>(nCol2);
645 *p++ = static_cast<USHORT>(nRow2);
646 *p++ = static_cast<USHORT>(nTab2);
647 USHORT* pCount = p;
648 *p++ = 0;
649 USHORT nPos = 14;
650 SCTAB nTab = nTab1;
651 while (nTab <= nTab2)
653 SCROW nRow = nRow1;
654 while (nRow <= nRow2)
656 SCCOL nCol = nCol1;
657 while (nCol <= nCol2)
659 ScBaseCell* pCell;
660 pDok->GetCell(nCol, nRow, nTab, pCell);
661 if (pCell)
663 String aStr;
664 USHORT nErr = 0;
665 BOOL bOk = TRUE;
666 switch ( pCell->GetCellType() )
668 case CELLTYPE_STRING :
669 ((ScStringCell*)pCell)->GetString(aStr);
670 break;
671 case CELLTYPE_EDIT :
672 ((ScEditCell*)pCell)->GetString(aStr);
673 break;
674 case CELLTYPE_FORMULA :
675 if (!((ScFormulaCell*)pCell)->IsValue())
677 nErr = ((ScFormulaCell*)pCell)->GetErrCode();
678 ((ScFormulaCell*)pCell)->GetString(aStr);
680 else
681 bOk = FALSE;
682 break;
683 default :
684 bOk = FALSE;
685 break;
687 if (bOk)
689 ByteString aTmp( aStr, osl_getThreadTextEncoding() );
690 // In case the xub_StrLen will be longer than USHORT
691 // one day, and room for pad byte check.
692 if ( aTmp.Len() > ((USHORT)(~0)) - 2 )
693 return FALSE;
694 // Append a 0-pad-byte if string length is not even
695 //! MUST be USHORT and not xub_StrLen
696 USHORT nStrLen = (USHORT) aTmp.Len();
697 USHORT nLen = ( nStrLen + 2 ) & ~1;
699 if (((ULONG)nPos + (5 * sizeof(USHORT)) + nLen) > MAXARRSIZE)
700 return FALSE;
701 *p++ = static_cast<USHORT>(nCol);
702 *p++ = static_cast<USHORT>(nRow);
703 *p++ = static_cast<USHORT>(nTab);
704 *p++ = nErr;
705 *p++ = nLen;
706 memcpy( p, aTmp.GetBuffer(), nStrLen + 1);
707 nPos += 10 + nStrLen + 1;
708 BYTE* q = ( pCellArr + nPos );
709 if( !nStrLen & 1 )
710 *q++ = 0, nPos++;
711 p = (USHORT*) ( pCellArr + nPos );
712 nCount++;
715 nCol++;
717 nRow++;
719 nTab++;
721 *pCount = nCount;
722 return TRUE;
726 BOOL ScInterpreter::CreateCellArr(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
727 SCCOL nCol2, SCROW nRow2, SCTAB nTab2,
728 BYTE* pCellArr)
730 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::CreateCellArr" );
731 #if SC_ROWLIMIT_MORE_THAN_64K
732 #error row limit 64k
733 #endif
734 USHORT nCount = 0;
735 USHORT* p = (USHORT*) pCellArr;
736 *p++ = static_cast<USHORT>(nCol1);
737 *p++ = static_cast<USHORT>(nRow1);
738 *p++ = static_cast<USHORT>(nTab1);
739 *p++ = static_cast<USHORT>(nCol2);
740 *p++ = static_cast<USHORT>(nRow2);
741 *p++ = static_cast<USHORT>(nTab2);
742 USHORT* pCount = p;
743 *p++ = 0;
744 USHORT nPos = 14;
745 SCTAB nTab = nTab1;
746 ScAddress aAdr;
747 while (nTab <= nTab2)
749 aAdr.SetTab( nTab );
750 SCROW nRow = nRow1;
751 while (nRow <= nRow2)
753 aAdr.SetRow( nRow );
754 SCCOL nCol = nCol1;
755 while (nCol <= nCol2)
757 aAdr.SetCol( nCol );
758 ScBaseCell* pCell = pDok->GetCell( aAdr );
759 if (pCell)
761 USHORT nErr = 0;
762 USHORT nType = 0; // 0 = Zahl; 1 = String
763 double nVal = 0.0;
764 String aStr;
765 BOOL bOk = TRUE;
766 switch ( pCell->GetCellType() )
768 case CELLTYPE_STRING :
769 ((ScStringCell*)pCell)->GetString(aStr);
770 nType = 1;
771 break;
772 case CELLTYPE_EDIT :
773 ((ScEditCell*)pCell)->GetString(aStr);
774 nType = 1;
775 break;
776 case CELLTYPE_VALUE :
777 nVal = GetValueCellValue( aAdr, (ScValueCell*)pCell );
778 break;
779 case CELLTYPE_FORMULA :
780 nErr = ((ScFormulaCell*)pCell)->GetErrCode();
781 if (((ScFormulaCell*)pCell)->IsValue())
782 nVal = ((ScFormulaCell*)pCell)->GetValue();
783 else
784 ((ScFormulaCell*)pCell)->GetString(aStr);
785 break;
786 default :
787 bOk = FALSE;
788 break;
790 if (bOk)
792 if ((nPos + (5 * sizeof(USHORT))) > MAXARRSIZE)
793 return FALSE;
794 *p++ = static_cast<USHORT>(nCol);
795 *p++ = static_cast<USHORT>(nRow);
796 *p++ = static_cast<USHORT>(nTab);
797 *p++ = nErr;
798 *p++ = nType;
799 nPos += 10;
800 if (nType == 0)
802 if ((nPos + sizeof(double)) > MAXARRSIZE)
803 return FALSE;
804 memcpy( p, &nVal, sizeof(double));
805 nPos += sizeof(double);
807 else
809 ByteString aTmp( aStr, osl_getThreadTextEncoding() );
810 // In case the xub_StrLen will be longer than USHORT
811 // one day, and room for pad byte check.
812 if ( aTmp.Len() > ((USHORT)(~0)) - 2 )
813 return FALSE;
814 // Append a 0-pad-byte if string length is not even
815 //! MUST be USHORT and not xub_StrLen
816 USHORT nStrLen = (USHORT) aTmp.Len();
817 USHORT nLen = ( nStrLen + 2 ) & ~1;
818 if ( ((ULONG)nPos + 2 + nLen) > MAXARRSIZE)
819 return FALSE;
820 *p++ = nLen;
821 memcpy( p, aTmp.GetBuffer(), nStrLen + 1);
822 nPos += 2 + nStrLen + 1;
823 BYTE* q = ( pCellArr + nPos );
824 if( !nStrLen & 1 )
825 *q++ = 0, nPos++;
827 nCount++;
828 p = (USHORT*) ( pCellArr + nPos );
831 nCol++;
833 nRow++;
835 nTab++;
837 *pCount = nCount;
838 return TRUE;
842 //-----------------------------------------------------------------------------
843 // Stack operations
844 //-----------------------------------------------------------------------------
847 // Also releases a TempToken if appropriate.
849 void ScInterpreter::PushWithoutError( FormulaToken& r )
851 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushWithoutError" );
852 if ( sp >= MAXSTACK )
853 SetError( errStackOverflow );
854 else
856 nCurFmtType = NUMBERFORMAT_UNDEFINED;
857 r.IncRef();
858 if( sp >= maxsp )
859 maxsp = sp + 1;
860 else
861 pStack[ sp ]->DecRef();
862 pStack[ sp ] = (ScToken*) &r;
863 ++sp;
867 void ScInterpreter::Push( FormulaToken& r )
869 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::Push" );
870 if ( sp >= MAXSTACK )
871 SetError( errStackOverflow );
872 else
874 if (nGlobalError)
876 if (r.GetType() == svError)
878 r.SetError( nGlobalError);
879 PushWithoutError( r);
881 else
882 PushWithoutError( *(new FormulaErrorToken( nGlobalError)));
884 else
885 PushWithoutError( r);
890 void ScInterpreter::PushTempToken( FormulaToken* p )
892 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushTempToken" );
893 if ( sp >= MAXSTACK )
895 SetError( errStackOverflow );
896 if (!p->GetRef())
897 //! p is a dangling pointer hereafter!
898 p->Delete();
900 else
902 if (nGlobalError)
904 if (p->GetType() == svError)
906 p->SetError( nGlobalError);
907 PushTempTokenWithoutError( p);
909 else
911 if (!p->GetRef())
912 //! p is a dangling pointer hereafter!
913 p->Delete();
914 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
917 else
918 PushTempTokenWithoutError( p);
923 void ScInterpreter::PushTempTokenWithoutError( FormulaToken* p )
925 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushTempTokenWithoutError" );
926 p->IncRef();
927 if ( sp >= MAXSTACK )
929 SetError( errStackOverflow );
930 //! p may be a dangling pointer hereafter!
931 p->DecRef();
933 else
935 if( sp >= maxsp )
936 maxsp = sp + 1;
937 else
938 pStack[ sp ]->DecRef();
939 pStack[ sp ] = p;
940 ++sp;
945 void ScInterpreter::PushTempToken( const FormulaToken& r )
947 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushTempToken" );
948 if (!IfErrorPushError())
949 PushTempTokenWithoutError( r.Clone());
953 void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
954 const ScAddress & rAddress, short * pRetTypeExpr, ULONG * pRetIndexExpr )
956 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushCellResultToken" );
957 ScBaseCell* pCell = pDok->GetCell( rAddress);
958 if (!pCell || pCell->HasEmptyData())
960 if (pRetTypeExpr && pRetIndexExpr)
961 pDok->GetNumberFormatInfo( *pRetTypeExpr, *pRetIndexExpr, rAddress, pCell);
962 bool bInherited = (GetCellType( pCell) == CELLTYPE_FORMULA);
963 PushTempToken( new ScEmptyCellToken( bInherited, bDisplayEmptyAsString));
964 return;
966 USHORT nErr;
967 if ((nErr = pCell->GetErrorCode()) != 0)
969 PushError( nErr);
970 if (pRetTypeExpr)
971 *pRetTypeExpr = NUMBERFORMAT_UNDEFINED;
972 if (pRetIndexExpr)
973 *pRetIndexExpr = 0;
975 else if (pCell->HasStringData())
977 String aRes;
978 GetCellString( aRes, pCell);
979 PushString( aRes);
980 if (pRetTypeExpr)
981 *pRetTypeExpr = NUMBERFORMAT_TEXT;
982 if (pRetIndexExpr)
983 *pRetIndexExpr = 0;
985 else
987 double fVal = GetCellValue( rAddress, pCell);
988 PushDouble( fVal);
989 if (pRetTypeExpr)
990 *pRetTypeExpr = nCurFmtType;
991 if (pRetIndexExpr)
992 *pRetIndexExpr = nCurFmtIndex;
997 // Simply throw away TOS.
999 void ScInterpreter::Pop()
1001 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::Pop" );
1002 if( sp )
1003 sp--;
1004 else
1005 SetError(errUnknownStackVariable);
1009 // Simply throw away TOS and set error code, used with ocIsError et al.
1011 void ScInterpreter::PopError()
1013 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopError" );
1014 if( sp )
1016 sp--;
1017 if (pStack[sp]->GetType() == svError)
1018 nGlobalError = pStack[sp]->GetError();
1020 else
1021 SetError(errUnknownStackVariable);
1025 FormulaTokenRef ScInterpreter::PopToken()
1027 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopToken" );
1028 if (sp)
1030 sp--;
1031 FormulaToken* p = pStack[ sp ];
1032 if (p->GetType() == svError)
1033 nGlobalError = p->GetError();
1034 return p;
1036 else
1037 SetError(errUnknownStackVariable);
1038 return NULL;
1042 double ScInterpreter::PopDouble()
1044 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopDouble" );
1045 nCurFmtType = NUMBERFORMAT_NUMBER;
1046 nCurFmtIndex = 0;
1047 if( sp )
1049 --sp;
1050 FormulaToken* p = pStack[ sp ];
1051 switch (p->GetType())
1053 case svError:
1054 nGlobalError = p->GetError();
1055 break;
1056 case svDouble:
1057 return p->GetDouble();
1058 case svEmptyCell:
1059 case svMissing:
1060 return 0.0;
1061 default:
1062 SetError( errIllegalArgument);
1065 else
1066 SetError( errUnknownStackVariable);
1067 return 0.0;
1071 const String& ScInterpreter::PopString()
1073 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopString" );
1074 nCurFmtType = NUMBERFORMAT_TEXT;
1075 nCurFmtIndex = 0;
1076 if( sp )
1078 --sp;
1079 FormulaToken* p = pStack[ sp ];
1080 switch (p->GetType())
1082 case svError:
1083 nGlobalError = p->GetError();
1084 break;
1085 case svString:
1086 return p->GetString();
1087 case svEmptyCell:
1088 case svMissing:
1089 return EMPTY_STRING;
1090 default:
1091 SetError( errIllegalArgument);
1094 else
1095 SetError( errUnknownStackVariable);
1096 return EMPTY_STRING;
1100 void ScInterpreter::ValidateRef( const ScSingleRefData & rRef )
1102 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ValidateRef" );
1103 SCCOL nCol;
1104 SCROW nRow;
1105 SCTAB nTab;
1106 SingleRefToVars( rRef, nCol, nRow, nTab);
1110 void ScInterpreter::ValidateRef( const ScComplexRefData & rRef )
1112 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ValidateRef" );
1113 ValidateRef( rRef.Ref1);
1114 ValidateRef( rRef.Ref2);
1118 void ScInterpreter::ValidateRef( const ScRefList & rRefList )
1120 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ValidateRef" );
1121 ScRefList::const_iterator it( rRefList.begin());
1122 ScRefList::const_iterator end( rRefList.end());
1123 for ( ; it != end; ++it)
1125 ValidateRef( *it);
1130 void ScInterpreter::SingleRefToVars( const ScSingleRefData & rRef,
1131 SCCOL & rCol, SCROW & rRow, SCTAB & rTab )
1133 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::SingleRefToVars" );
1134 if ( rRef.IsColRel() )
1135 rCol = aPos.Col() + rRef.nRelCol;
1136 else
1137 rCol = rRef.nCol;
1138 if ( rRef.IsRowRel() )
1139 rRow = aPos.Row() + rRef.nRelRow;
1140 else
1141 rRow = rRef.nRow;
1142 if ( rRef.IsTabRel() )
1143 rTab = aPos.Tab() + rRef.nRelTab;
1144 else
1145 rTab = rRef.nTab;
1146 if( !ValidCol( rCol) || rRef.IsColDeleted() )
1147 SetError( errNoRef ), rCol = 0;
1148 if( !ValidRow( rRow) || rRef.IsRowDeleted() )
1149 SetError( errNoRef ), rRow = 0;
1150 if( !ValidTab( rTab, pDok->GetTableCount() - 1) || rRef.IsTabDeleted() )
1151 SetError( errNoRef ), rTab = 0;
1155 void ScInterpreter::PopSingleRef(SCCOL& rCol, SCROW &rRow, SCTAB& rTab)
1157 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopSingleRef" );
1158 if( sp )
1160 --sp;
1161 FormulaToken* p = pStack[ sp ];
1162 switch (p->GetType())
1164 case svError:
1165 nGlobalError = p->GetError();
1166 break;
1167 case svSingleRef:
1168 SingleRefToVars( static_cast<ScToken*>(p)->GetSingleRef(), rCol, rRow, rTab);
1169 if ( pDok->aTableOpList.Count() > 0 )
1170 ReplaceCell( rCol, rRow, rTab );
1171 break;
1172 default:
1173 SetError( errIllegalParameter);
1176 else
1177 SetError( errUnknownStackVariable);
1181 void ScInterpreter::PopSingleRef( ScAddress& rAdr )
1183 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopSingleRef" );
1184 if( sp )
1186 --sp;
1187 FormulaToken* p = pStack[ sp ];
1188 switch (p->GetType())
1190 case svError:
1191 nGlobalError = p->GetError();
1192 break;
1193 case svSingleRef:
1195 SCCOL nCol;
1196 SCROW nRow;
1197 SCTAB nTab;
1198 SingleRefToVars( static_cast<ScToken*>(p)->GetSingleRef(), nCol, nRow, nTab);
1199 rAdr.Set( nCol, nRow, nTab );
1200 if ( pDok->aTableOpList.Count() > 0 )
1201 ReplaceCell( rAdr );
1203 break;
1204 default:
1205 SetError( errIllegalParameter);
1208 else
1209 SetError( errUnknownStackVariable);
1213 void ScInterpreter::DoubleRefToVars( const ScToken* p,
1214 SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1215 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1216 BOOL bDontCheckForTableOp )
1218 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::DoubleRefToVars" );
1219 const ScComplexRefData& rCRef = p->GetDoubleRef();
1220 SingleRefToVars( rCRef.Ref1, rCol1, rRow1, rTab1);
1221 SingleRefToVars( rCRef.Ref2, rCol2, rRow2, rTab2);
1222 if ( pDok->aTableOpList.Count() > 0 && !bDontCheckForTableOp )
1224 ScRange aRange( rCol1, rRow1, rTab1, rCol2, rRow2, rTab2 );
1225 if ( IsTableOpInRange( aRange ) )
1226 SetError( errIllegalParameter );
1231 void ScInterpreter::PopDoubleRef(SCCOL& rCol1, SCROW &rRow1, SCTAB& rTab1,
1232 SCCOL& rCol2, SCROW &rRow2, SCTAB& rTab2,
1233 BOOL bDontCheckForTableOp )
1235 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopDoubleRef" );
1236 if( sp )
1238 --sp;
1239 FormulaToken* p = pStack[ sp ];
1240 switch (p->GetType())
1242 case svError:
1243 nGlobalError = p->GetError();
1244 break;
1245 case svDoubleRef:
1246 DoubleRefToVars( static_cast<ScToken*>(p), rCol1, rRow1, rTab1, rCol2, rRow2, rTab2,
1247 bDontCheckForTableOp);
1248 break;
1249 default:
1250 SetError( errIllegalParameter);
1253 else
1254 SetError( errUnknownStackVariable);
1258 void ScInterpreter::DoubleRefToRange( const ScComplexRefData & rCRef,
1259 ScRange & rRange, BOOL bDontCheckForTableOp )
1261 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::DoubleRefToRange" );
1262 SCCOL nCol;
1263 SCROW nRow;
1264 SCTAB nTab;
1265 SingleRefToVars( rCRef.Ref1, nCol, nRow, nTab);
1266 rRange.aStart.Set( nCol, nRow, nTab );
1267 SingleRefToVars( rCRef.Ref2, nCol, nRow, nTab);
1268 rRange.aEnd.Set( nCol, nRow, nTab );
1269 if ( pDok->aTableOpList.Count() > 0 && !bDontCheckForTableOp )
1271 if ( IsTableOpInRange( rRange ) )
1272 SetError( errIllegalParameter );
1277 void ScInterpreter::PopDoubleRef( ScRange & rRange, short & rParam, size_t & rRefInList )
1279 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopDoubleRef" );
1280 if (sp)
1282 formula::FormulaToken* pToken = pStack[ sp-1 ];
1283 ScToken* p = static_cast<ScToken*>(pToken);
1284 switch (pToken->GetType())
1286 case svError:
1287 nGlobalError = p->GetError();
1288 break;
1289 case svDoubleRef:
1290 --sp;
1291 DoubleRefToRange( p->GetDoubleRef(), rRange);
1292 break;
1293 case svRefList:
1295 const ScRefList* pList = p->GetRefList();
1296 if (rRefInList < pList->size())
1298 DoubleRefToRange( (*pList)[rRefInList], rRange);
1299 if (++rRefInList < pList->size())
1300 ++rParam;
1301 else
1303 --sp;
1304 rRefInList = 0;
1307 else
1309 --sp;
1310 rRefInList = 0;
1311 SetError( errIllegalParameter);
1314 break;
1315 default:
1316 SetError( errIllegalParameter);
1319 else
1320 SetError( errUnknownStackVariable);
1324 void ScInterpreter::PopDoubleRef( ScRange& rRange, BOOL bDontCheckForTableOp )
1326 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopDoubleRef" );
1327 if( sp )
1329 --sp;
1330 FormulaToken* p = pStack[ sp ];
1331 switch (p->GetType())
1333 case svError:
1334 nGlobalError = p->GetError();
1335 break;
1336 case svDoubleRef:
1337 DoubleRefToRange( static_cast<ScToken*>(p)->GetDoubleRef(), rRange, bDontCheckForTableOp);
1338 break;
1339 default:
1340 SetError( errIllegalParameter);
1343 else
1344 SetError( errUnknownStackVariable);
1348 BOOL ScInterpreter::PopDoubleRefOrSingleRef( ScAddress& rAdr )
1350 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopDoubleRefOrSingleRef" );
1351 switch ( GetStackType() )
1353 case svDoubleRef :
1355 ScRange aRange;
1356 PopDoubleRef( aRange, TRUE );
1357 return DoubleRefToPosSingleRef( aRange, rAdr );
1359 //break;
1360 case svSingleRef :
1362 PopSingleRef( rAdr );
1363 return TRUE;
1365 //break;
1366 default:
1367 PopError();
1368 SetError( errNoRef );
1370 return FALSE;
1374 void ScInterpreter::PopDoubleRefPushMatrix()
1376 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopDoubleRefPushMatrix" );
1377 if ( GetStackType() == svDoubleRef )
1379 ScMatrixRef pMat = GetMatrix();
1380 if ( pMat )
1381 PushMatrix( pMat );
1382 else
1383 PushIllegalParameter();
1385 else
1386 SetError( errNoRef );
1390 ScTokenMatrixMap* ScInterpreter::CreateTokenMatrixMap()
1392 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::CreateTokenMatrixMap" );
1393 return new ScTokenMatrixMap;
1397 bool ScInterpreter::ConvertMatrixParameters()
1399 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ConvertMatrixParameters" );
1400 USHORT nParams = pCur->GetParamCount();
1401 DBG_ASSERT( nParams <= sp, "ConvertMatrixParameters: stack/param count mismatch");
1402 SCSIZE nJumpCols = 0, nJumpRows = 0;
1403 for ( USHORT i=1; i <= nParams && i <= sp; ++i )
1405 FormulaToken* p = pStack[ sp - i ];
1406 if ( p->GetOpCode() != ocPush )
1408 DBG_ERRORFILE( "ConvertMatrixParameters: not a push");
1410 else
1412 switch ( p->GetType() )
1414 case svDouble:
1415 case svString:
1416 case svSingleRef:
1417 case svMissing:
1418 case svError:
1419 case svEmptyCell:
1420 // nothing to do
1421 break;
1422 case svMatrix:
1424 if ( ScParameterClassification::GetParameterType( pCur, nParams - i)
1425 == ScParameterClassification::Value )
1426 { // only if single value expected
1427 ScMatrixRef pMat = static_cast<ScToken*>(p)->GetMatrix();
1428 if ( !pMat )
1429 SetError( errUnknownVariable);
1430 else
1432 SCSIZE nCols, nRows;
1433 pMat->GetDimensions( nCols, nRows);
1434 if ( nJumpCols < nCols )
1435 nJumpCols = nCols;
1436 if ( nJumpRows < nRows )
1437 nJumpRows = nRows;
1441 break;
1442 case svDoubleRef:
1444 ScParameterClassification::Type eType =
1445 ScParameterClassification::GetParameterType( pCur, nParams - i);
1446 if ( eType != ScParameterClassification::Reference )
1448 SCCOL nCol1, nCol2;
1449 SCROW nRow1, nRow2;
1450 SCTAB nTab1, nTab2;
1451 DoubleRefToVars( static_cast<const ScToken*>( p), nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1452 // Make sure the map exists, created if not.
1453 GetTokenMatrixMap();
1454 ScMatrixRef pMat = CreateMatrixFromDoubleRef( p,
1455 nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
1456 if (pMat)
1458 if ( eType == ScParameterClassification::Value )
1459 { // only if single value expected
1460 if ( nJumpCols < static_cast<SCSIZE>(nCol2 - nCol1 + 1) )
1461 nJumpCols = static_cast<SCSIZE>(nCol2 - nCol1 + 1);
1462 if ( nJumpRows < static_cast<SCSIZE>(nRow2 - nRow1 + 1) )
1463 nJumpRows = static_cast<SCSIZE>(nRow2 - nRow1 + 1);
1465 ScToken* pNew = new ScMatrixToken( pMat);
1466 pNew->IncRef();
1467 pStack[ sp - i ] = pNew;
1468 p->DecRef(); // p may be dead now!
1472 break;
1473 case svRefList:
1475 ScParameterClassification::Type eType =
1476 ScParameterClassification::GetParameterType( pCur, nParams - i);
1477 if ( eType != ScParameterClassification::Reference )
1479 // can't convert to matrix
1480 SetError( errNoValue);
1483 break;
1484 default:
1485 DBG_ERRORFILE( "ConvertMatrixParameters: unknown parameter type");
1489 if( nJumpCols && nJumpRows )
1491 short nPC = aCode.GetPC();
1492 short nStart = nPC - 1; // restart on current code (-1)
1493 short nNext = nPC; // next instruction after subroutine
1494 short nStop = nPC + 1; // stop subroutine before reaching that
1495 FormulaTokenRef xNew;
1496 ScTokenMatrixMap::const_iterator aMapIter;
1497 if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find( pCur)) !=
1498 pTokenMatrixMap->end()))
1499 xNew = (*aMapIter).second;
1500 else
1502 ScJumpMatrix* pJumpMat = new ScJumpMatrix( nJumpCols, nJumpRows);
1503 pJumpMat->SetAllJumps( 1.0, nStart, nNext, nStop);
1504 // pop parameters and store in ScJumpMatrix, push in JumpMatrix()
1505 ScTokenVec* pParams = new ScTokenVec( nParams);
1506 for ( USHORT i=1; i <= nParams && sp > 0; ++i )
1508 FormulaToken* p = pStack[ --sp ];
1509 p->IncRef();
1510 // store in reverse order such that a push may simply iterate
1511 (*pParams)[ nParams - i ] = p;
1513 pJumpMat->SetJumpParameters( pParams);
1514 xNew = new ScJumpMatrixToken( pJumpMat );
1515 GetTokenMatrixMap().insert( ScTokenMatrixMap::value_type( pCur,
1516 xNew));
1518 PushTempToken( xNew);
1519 // set continuation point of path for main code line
1520 aCode.Jump( nNext, nNext);
1521 return true;
1523 return false;
1527 ScMatrixRef ScInterpreter::PopMatrix()
1529 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PopMatrix" );
1530 if( sp )
1532 --sp;
1533 FormulaToken* p = pStack[ sp ];
1534 switch (p->GetType())
1536 case svError:
1537 nGlobalError = p->GetError();
1538 break;
1539 case svMatrix:
1541 ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix();
1542 if ( pMat )
1543 pMat->SetErrorInterpreter( this);
1544 else
1545 SetError( errUnknownVariable);
1546 return pMat;
1548 default:
1549 SetError( errIllegalParameter);
1552 else
1553 SetError( errUnknownStackVariable);
1554 return NULL;
1558 void ScInterpreter::PushDouble(double nVal)
1560 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushDouble" );
1561 TreatDoubleError( nVal );
1562 if (!IfErrorPushError())
1563 PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1567 void ScInterpreter::PushInt(int nVal)
1569 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushInt" );
1570 if (!IfErrorPushError())
1571 PushTempTokenWithoutError( new FormulaDoubleToken( nVal ) );
1575 void ScInterpreter::PushStringBuffer( const sal_Unicode* pString )
1577 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushStringBuffer" );
1578 if ( pString )
1579 PushString( String( pString ) );
1580 else
1581 PushString( EMPTY_STRING );
1585 void ScInterpreter::PushString( const String& rString )
1587 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushString" );
1588 if (!IfErrorPushError())
1589 PushTempTokenWithoutError( new FormulaStringToken( rString ) );
1593 void ScInterpreter::PushSingleRef(SCCOL nCol, SCROW nRow, SCTAB nTab)
1595 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushSingleRef" );
1596 if (!IfErrorPushError())
1598 ScSingleRefData aRef;
1599 aRef.InitFlags();
1600 aRef.nCol = nCol;
1601 aRef.nRow = nRow;
1602 aRef.nTab = nTab;
1603 PushTempTokenWithoutError( new ScSingleRefToken( aRef ) );
1608 void ScInterpreter::PushDoubleRef(SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
1609 SCCOL nCol2, SCROW nRow2, SCTAB nTab2)
1611 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushDoubleRef" );
1612 if (!IfErrorPushError())
1614 ScComplexRefData aRef;
1615 aRef.InitFlags();
1616 aRef.Ref1.nCol = nCol1;
1617 aRef.Ref1.nRow = nRow1;
1618 aRef.Ref1.nTab = nTab1;
1619 aRef.Ref2.nCol = nCol2;
1620 aRef.Ref2.nRow = nRow2;
1621 aRef.Ref2.nTab = nTab2;
1622 PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) );
1627 void ScInterpreter::PushMatrix(ScMatrix* pMat)
1629 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushMatrix" );
1630 pMat->SetErrorInterpreter( NULL);
1631 // No if (!IfErrorPushError()) because ScMatrix stores errors itself,
1632 // but with notifying ScInterpreter via nGlobalError, substituting it would
1633 // mean to inherit the error on all array elements in all following
1634 // operations.
1635 nGlobalError = 0;
1636 PushTempTokenWithoutError( new ScMatrixToken( pMat ) );
1640 void ScInterpreter::PushError( USHORT nError )
1642 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushError" );
1643 SetError( nError ); // only sets error if not already set
1644 PushTempTokenWithoutError( new FormulaErrorToken( nGlobalError));
1647 void ScInterpreter::PushParameterExpected()
1649 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushParameterExpected" );
1650 PushError( errParameterExpected);
1654 void ScInterpreter::PushIllegalParameter()
1656 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushIllegalParameter" );
1657 PushError( errIllegalParameter);
1661 void ScInterpreter::PushIllegalArgument()
1663 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushIllegalArgument" );
1664 PushError( errIllegalArgument);
1668 void ScInterpreter::PushNA()
1670 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushNA" );
1671 PushError( NOTAVAILABLE);
1675 void ScInterpreter::PushNoValue()
1677 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::PushNoValue" );
1678 PushError( errNoValue);
1682 BOOL ScInterpreter::IsMissing()
1684 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::IsMissing" );
1685 return sp && pStack[sp - 1]->GetType() == svMissing;
1689 StackVar ScInterpreter::GetRawStackType()
1691 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetRawStackType" );
1692 StackVar eRes;
1693 if( sp )
1695 eRes = pStack[sp - 1]->GetType();
1697 else
1699 SetError(errUnknownStackVariable);
1700 eRes = svUnknown;
1702 return eRes;
1706 StackVar ScInterpreter::GetStackType()
1708 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetStackType" );
1709 StackVar eRes;
1710 if( sp )
1712 eRes = pStack[sp - 1]->GetType();
1713 if( eRes == svMissing || eRes == svEmptyCell )
1714 eRes = svDouble; // default!
1716 else
1718 SetError(errUnknownStackVariable);
1719 eRes = svUnknown;
1721 return eRes;
1725 StackVar ScInterpreter::GetStackType( BYTE nParam )
1727 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetStackType" );
1728 StackVar eRes;
1729 if( sp > nParam-1 )
1731 eRes = pStack[sp - nParam]->GetType();
1732 if( eRes == svMissing || eRes == svEmptyCell )
1733 eRes = svDouble; // default!
1735 else
1736 eRes = svUnknown;
1737 return eRes;
1741 BOOL ScInterpreter::DoubleRefToPosSingleRef( const ScRange& rRange, ScAddress& rAdr )
1743 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::DoubleRefToPosSingleRef" );
1744 // Check for a singleton first - no implicit intersection for them.
1745 if( rRange.aStart == rRange.aEnd )
1747 rAdr = rRange.aStart;
1748 return TRUE;
1751 BOOL bOk = FALSE;
1753 if ( pJumpMatrix )
1755 bOk = rRange.aStart.Tab() == rRange.aEnd.Tab();
1756 if ( !bOk )
1757 SetError( errIllegalArgument);
1758 else
1760 SCSIZE nC, nR;
1761 pJumpMatrix->GetPos( nC, nR);
1762 rAdr.SetCol( sal::static_int_cast<SCCOL>( rRange.aStart.Col() + nC ) );
1763 rAdr.SetRow( sal::static_int_cast<SCROW>( rRange.aStart.Row() + nR ) );
1764 rAdr.SetTab( rRange.aStart.Tab());
1765 bOk = rRange.aStart.Col() <= rAdr.Col() && rAdr.Col() <=
1766 rRange.aEnd.Col() && rRange.aStart.Row() <= rAdr.Row() &&
1767 rAdr.Row() <= rRange.aEnd.Row();
1768 if ( !bOk )
1769 SetError( errNoValue);
1771 return bOk;
1774 SCCOL nMyCol = aPos.Col();
1775 SCROW nMyRow = aPos.Row();
1776 SCTAB nMyTab = aPos.Tab();
1777 SCCOL nCol = 0;
1778 SCROW nRow = 0;
1779 SCTAB nTab;
1780 nTab = rRange.aStart.Tab();
1781 if ( rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
1783 nRow = rRange.aStart.Row();
1784 if ( nRow == rRange.aEnd.Row() )
1786 bOk = TRUE;
1787 nCol = nMyCol;
1789 else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
1790 && rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
1792 bOk = TRUE;
1793 nCol = nMyCol;
1794 nRow = nMyRow;
1797 else if ( rRange.aStart.Row() <= nMyRow && nMyRow <= rRange.aEnd.Row() )
1799 nCol = rRange.aStart.Col();
1800 if ( nCol == rRange.aEnd.Col() )
1802 bOk = TRUE;
1803 nRow = nMyRow;
1805 else if ( nTab != nMyTab && nTab == rRange.aEnd.Tab()
1806 && rRange.aStart.Col() <= nMyCol && nMyCol <= rRange.aEnd.Col() )
1808 bOk = TRUE;
1809 nCol = nMyCol;
1810 nRow = nMyRow;
1813 if ( bOk )
1815 if ( nTab == rRange.aEnd.Tab() )
1816 ; // all done
1817 else if ( nTab <= nMyTab && nMyTab <= rRange.aEnd.Tab() )
1818 nTab = nMyTab;
1819 else
1820 bOk = FALSE;
1821 if ( bOk )
1822 rAdr.Set( nCol, nRow, nTab );
1824 if ( !bOk )
1825 SetError( errNoValue );
1826 return bOk;
1830 double ScInterpreter::GetDouble( bool bNoValueAsError, bool bBlankAsZero )
1832 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetDouble" );
1833 double nVal;
1834 switch( GetRawStackType() )
1836 case svDouble:
1837 nVal = PopDouble();
1838 break;
1839 case svString:
1841 String aStr(PopString());
1842 sal_uInt32 nFIndex = 0; // damit default Land/Spr.
1843 if(!pFormatter->IsNumberFormat( aStr, nFIndex, nVal ) )
1845 SetError( errIllegalArgument); //! fit to ScN()
1846 nVal = 0.0;
1849 break;
1850 case svSingleRef:
1852 ScAddress aAdr;
1853 PopSingleRef( aAdr );
1854 ScBaseCell* pCell = GetCell( aAdr );
1855 nVal = GetCellValue( aAdr, pCell, bNoValueAsError, bBlankAsZero );
1857 break;
1858 case svDoubleRef:
1859 { // generate position dependent SingleRef
1860 ScRange aRange;
1861 PopDoubleRef( aRange );
1862 ScAddress aAdr;
1863 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
1865 ScBaseCell* pCell = GetCell( aAdr );
1866 nVal = GetCellValue( aAdr, pCell );
1868 else
1869 nVal = 0.0;
1871 break;
1872 case svMatrix:
1874 ScMatrixRef pMat = PopMatrix();
1875 if ( !pMat )
1876 nVal = 0.0;
1877 else if ( !pJumpMatrix )
1878 nVal = pMat->GetDouble( 0 );
1879 else
1881 SCSIZE nCols, nRows, nC, nR;
1882 pMat->GetDimensions( nCols, nRows);
1883 pJumpMatrix->GetPos( nC, nR);
1884 if ( nC < nCols && nR < nRows )
1885 nVal = pMat->GetDouble( nC, nR);
1886 else
1888 SetError( errNoValue);
1889 nVal = 0.0;
1893 break;
1894 case svError:
1895 PopError();
1896 nVal = 0.0;
1897 break;
1898 case svEmptyCell:
1899 case svMissing:
1900 Pop();
1901 nVal = 0.0;
1902 break;
1903 default:
1904 PopError();
1905 SetError( errIllegalParameter);
1906 nVal = 0.0;
1908 if ( nFuncFmtType == nCurFmtType )
1909 nFuncFmtIndex = nCurFmtIndex;
1910 return nVal;
1914 double ScInterpreter::GetDoubleWithDefault(double nDefault)
1916 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetDoubleWithDefault" );
1917 bool bMissing = IsMissing();
1918 double nResultVal = GetDouble();
1919 if ( bMissing )
1920 nResultVal = nDefault;
1921 return nResultVal;
1925 const String& ScInterpreter::GetString()
1927 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetString" );
1928 switch (GetRawStackType())
1930 case svError:
1931 PopError();
1932 return EMPTY_STRING;
1933 //break;
1934 case svMissing:
1935 case svEmptyCell:
1936 Pop();
1937 return EMPTY_STRING;
1938 //break;
1939 case svDouble:
1941 double fVal = PopDouble();
1942 ULONG nIndex = pFormatter->GetStandardFormat(
1943 NUMBERFORMAT_NUMBER,
1944 ScGlobal::eLnge);
1945 pFormatter->GetInputLineString(fVal, nIndex, aTempStr);
1946 return aTempStr;
1948 //break;
1949 case svString:
1950 return PopString();
1951 //break;
1952 case svSingleRef:
1954 ScAddress aAdr;
1955 PopSingleRef( aAdr );
1956 if (nGlobalError == 0)
1958 ScBaseCell* pCell = GetCell( aAdr );
1959 GetCellString( aTempStr, pCell );
1960 return aTempStr;
1962 else
1963 return EMPTY_STRING;
1965 //break;
1966 case svDoubleRef:
1967 { // generate position dependent SingleRef
1968 ScRange aRange;
1969 PopDoubleRef( aRange );
1970 ScAddress aAdr;
1971 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr ) )
1973 ScBaseCell* pCell = GetCell( aAdr );
1974 GetCellString( aTempStr, pCell );
1975 return aTempStr;
1977 else
1978 return EMPTY_STRING;
1980 //break;
1981 case svMatrix:
1983 ScMatrixRef pMat = PopMatrix();
1984 if ( !pMat )
1985 ; // nothing
1986 else if ( !pJumpMatrix )
1988 aTempStr = pMat->GetString( *pFormatter, 0, 0);
1989 return aTempStr;
1991 else
1993 SCSIZE nCols, nRows, nC, nR;
1994 pMat->GetDimensions( nCols, nRows);
1995 pJumpMatrix->GetPos( nC, nR);
1996 if ( nC < nCols && nR < nRows )
1998 aTempStr = pMat->GetString( *pFormatter, nC, nR);
1999 return aTempStr;
2001 else
2002 SetError( errNoValue);
2005 break;
2006 default:
2007 PopError();
2008 SetError( errIllegalArgument);
2010 return EMPTY_STRING;
2015 ScMatValType ScInterpreter::GetDoubleOrStringFromMatrix( double& rDouble,
2016 String& rString )
2018 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GetDoubleOrStringFromMatrix" );
2019 ScMatValType nMatValType = SC_MATVAL_EMPTY;
2020 switch ( GetStackType() )
2022 case svMatrix:
2024 const ScMatrixValue* pMatVal = 0;
2025 ScMatrixRef pMat = PopMatrix();
2026 if (!pMat)
2027 ; // nothing
2028 else if (!pJumpMatrix)
2029 pMatVal = pMat->Get( 0, 0, nMatValType);
2030 else
2032 SCSIZE nCols, nRows, nC, nR;
2033 pMat->GetDimensions( nCols, nRows);
2034 pJumpMatrix->GetPos( nC, nR);
2035 if ( nC < nCols && nR < nRows )
2036 pMatVal = pMat->Get( nC, nR, nMatValType);
2037 else
2038 SetError( errNoValue);
2040 if (!pMatVal)
2042 rDouble = 0.0;
2043 rString.Erase();
2045 else if (nMatValType == SC_MATVAL_VALUE)
2046 rDouble = pMatVal->fVal;
2047 else if (nMatValType == SC_MATVAL_BOOLEAN)
2049 rDouble = pMatVal->fVal;
2050 nMatValType = SC_MATVAL_VALUE;
2052 else
2053 rString = pMatVal->GetString();
2055 break;
2056 default:
2057 PopError();
2058 rDouble = 0.0;
2059 rString.Erase();
2060 SetError( errIllegalParameter);
2062 return nMatValType;
2066 void ScInterpreter::ScDBGet()
2068 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScDBGet" );
2069 SCTAB nTab;
2070 ScQueryParam aQueryParam;
2071 BOOL bMissingField = FALSE;
2072 if (GetDBParams( nTab, aQueryParam, bMissingField))
2074 ScBaseCell* pCell;
2075 ScQueryCellIterator aCellIter(pDok, nTab, aQueryParam);
2076 if ( (pCell = aCellIter.GetFirst()) != NULL )
2078 if (aCellIter.GetNext())
2079 PushIllegalArgument();
2080 else
2082 switch (pCell->GetCellType())
2084 case CELLTYPE_VALUE:
2086 double rValue = ((ScValueCell*)pCell)->GetValue();
2087 if ( bCalcAsShown )
2089 ULONG nFormat;
2090 nFormat = aCellIter.GetNumberFormat();
2091 rValue = pDok->RoundValueAsShown( rValue, nFormat );
2093 PushDouble(rValue);
2095 break;
2096 case CELLTYPE_STRING:
2098 String rString;
2099 ((ScStringCell*)pCell)->GetString(rString);
2100 PushString(rString);
2102 break;
2103 case CELLTYPE_EDIT:
2105 String rString;
2106 ((ScEditCell*)pCell)->GetString(rString);
2107 PushString(rString);
2109 break;
2110 case CELLTYPE_FORMULA:
2112 USHORT rErr = ((ScFormulaCell*)pCell)->GetErrCode();
2113 if (rErr)
2114 PushError(rErr);
2115 else if (((ScFormulaCell*)pCell)->IsValue())
2117 double rValue = ((ScFormulaCell*)pCell)->GetValue();
2118 PushDouble(rValue);
2120 else
2122 String rString;
2123 ((ScFormulaCell*)pCell)->GetString(rString);
2124 PushString(rString);
2127 break;
2128 case CELLTYPE_NONE:
2129 case CELLTYPE_NOTE:
2130 default:
2131 PushIllegalArgument();
2132 break;
2136 else
2137 PushNoValue();
2139 else
2140 PushIllegalParameter();
2144 void ScInterpreter::ScExternal()
2146 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScExternal" );
2147 USHORT nIndex;
2148 BYTE nParamCount = GetByte();
2149 String aUnoName;
2150 String aFuncName( ScGlobal::pCharClass->upper( pCur->GetExternal() ) );
2151 if (ScGlobal::GetFuncCollection()->SearchFunc(aFuncName, nIndex))
2153 FuncData* pFuncData = (FuncData*)ScGlobal::GetFuncCollection()->At(nIndex);
2154 if (nParamCount == pFuncData->GetParamCount() - 1)
2156 ParamType eParamType[MAXFUNCPARAM];
2157 void* ppParam[MAXFUNCPARAM];
2158 double nVal[MAXFUNCPARAM];
2159 sal_Char* pStr[MAXFUNCPARAM];
2160 BYTE* pCellArr[MAXFUNCPARAM];
2161 short i;
2163 for (i = 0; i < MAXFUNCPARAM; i++)
2165 eParamType[i] = pFuncData->GetParamType(i);
2166 ppParam[i] = NULL;
2167 nVal[i] = 0.0;
2168 pStr[i] = NULL;
2169 pCellArr[i] = NULL;
2172 for (i = nParamCount; (i > 0) && (nGlobalError == 0); i--)
2174 switch (eParamType[i])
2176 case PTR_DOUBLE :
2178 nVal[i-1] = GetDouble();
2179 ppParam[i] = &nVal[i-1];
2181 break;
2182 case PTR_STRING :
2184 ByteString aStr( GetString(), osl_getThreadTextEncoding() );
2185 if ( aStr.Len() >= ADDIN_MAXSTRLEN )
2186 SetError( errStringOverflow );
2187 else
2189 pStr[i-1] = new sal_Char[ADDIN_MAXSTRLEN];
2190 strncpy( pStr[i-1], aStr.GetBuffer(), ADDIN_MAXSTRLEN );
2191 pStr[i-1][ADDIN_MAXSTRLEN-1] = 0;
2192 ppParam[i] = pStr[i-1];
2195 break;
2196 case PTR_DOUBLE_ARR :
2198 SCCOL nCol1;
2199 SCROW nRow1;
2200 SCTAB nTab1;
2201 SCCOL nCol2;
2202 SCROW nRow2;
2203 SCTAB nTab2;
2204 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2205 pCellArr[i-1] = new BYTE[MAXARRSIZE];
2206 if (!CreateDoubleArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2207 SetError(errCodeOverflow);
2208 else
2209 ppParam[i] = pCellArr[i-1];
2211 break;
2212 case PTR_STRING_ARR :
2214 SCCOL nCol1;
2215 SCROW nRow1;
2216 SCTAB nTab1;
2217 SCCOL nCol2;
2218 SCROW nRow2;
2219 SCTAB nTab2;
2220 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2221 pCellArr[i-1] = new BYTE[MAXARRSIZE];
2222 if (!CreateStringArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2223 SetError(errCodeOverflow);
2224 else
2225 ppParam[i] = pCellArr[i-1];
2227 break;
2228 case PTR_CELL_ARR :
2230 SCCOL nCol1;
2231 SCROW nRow1;
2232 SCTAB nTab1;
2233 SCCOL nCol2;
2234 SCROW nRow2;
2235 SCTAB nTab2;
2236 PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2);
2237 pCellArr[i-1] = new BYTE[MAXARRSIZE];
2238 if (!CreateCellArr(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2, pCellArr[i-1]))
2239 SetError(errCodeOverflow);
2240 else
2241 ppParam[i] = pCellArr[i-1];
2243 break;
2244 default :
2245 SetError(errIllegalParameter);
2246 break;
2249 while ( i-- )
2250 Pop(); // im Fehlerfall (sonst ist i==0) Parameter wegpoppen
2252 if (nGlobalError == 0)
2254 if ( pFuncData->GetAsyncType() == NONE )
2256 switch ( eParamType[0] )
2258 case PTR_DOUBLE :
2260 double nErg = 0.0;
2261 ppParam[0] = &nErg;
2262 pFuncData->Call(ppParam);
2263 PushDouble(nErg);
2265 break;
2266 case PTR_STRING :
2268 sal_Char* pcErg = new sal_Char[ADDIN_MAXSTRLEN];
2269 ppParam[0] = pcErg;
2270 pFuncData->Call(ppParam);
2271 String aUni( pcErg, osl_getThreadTextEncoding() );
2272 PushString( aUni );
2273 delete[] pcErg;
2275 break;
2276 default:
2277 PushError( errUnknownState );
2280 else
2282 // nach dem Laden Asyncs wieder anwerfen
2283 if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
2284 pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
2285 // garantiert identischer Handle bei identischem Aufruf?!?
2286 // sonst schei*e ...
2287 double nErg = 0.0;
2288 ppParam[0] = &nErg;
2289 pFuncData->Call(ppParam);
2290 ULONG nHandle = ULONG( nErg );
2291 if ( nHandle >= 65536 )
2293 ScAddInAsync* pAs = ScAddInAsync::Get( nHandle );
2294 if ( !pAs )
2296 pAs = new ScAddInAsync( nHandle, nIndex, pDok );
2297 pMyFormulaCell->StartListening( *pAs );
2299 else
2301 // falls per cut/copy/paste
2302 pMyFormulaCell->StartListening( *pAs );
2303 // in anderes Dokument?
2304 if ( !pAs->HasDocument( pDok ) )
2305 pAs->AddDocument( pDok );
2307 if ( pAs->IsValid() )
2309 switch ( pAs->GetType() )
2311 case PTR_DOUBLE :
2312 PushDouble( pAs->GetValue() );
2313 break;
2314 case PTR_STRING :
2315 PushString( pAs->GetString() );
2316 break;
2317 default:
2318 PushError( errUnknownState );
2321 else
2322 PushNA();
2324 else
2325 PushNoValue();
2329 for (i = 0; i < MAXFUNCPARAM; i++)
2331 delete[] pStr[i];
2332 delete[] pCellArr[i];
2335 else
2337 while( nParamCount-- > 0)
2338 Pop();
2339 PushIllegalParameter();
2342 else if ( ( aUnoName = ScGlobal::GetAddInCollection()->FindFunction(aFuncName, FALSE) ).Len() )
2344 // bLocalFirst=FALSE in FindFunction, cFunc should be the stored internal name
2346 ScUnoAddInCall aCall( *ScGlobal::GetAddInCollection(), aUnoName, nParamCount );
2348 if ( !aCall.ValidParamCount() )
2349 SetError( errIllegalParameter );
2351 if ( aCall.NeedsCaller() && !GetError() )
2353 SfxObjectShell* pShell = pDok->GetDocumentShell();
2354 if (pShell)
2355 aCall.SetCallerFromObjectShell( pShell );
2356 else
2358 // use temporary model object (without document) to supply options
2359 aCall.SetCaller( static_cast<beans::XPropertySet*>(
2360 new ScDocOptionsObj( pDok->GetDocOptions() ) ) );
2364 short nPar = nParamCount;
2365 while ( nPar > 0 && !GetError() )
2367 --nPar; // 0 .. (nParamCount-1)
2369 ScAddInArgumentType eType = aCall.GetArgType( nPar );
2370 BYTE nStackType = sal::static_int_cast<BYTE>( GetStackType() );
2372 uno::Any aParam;
2373 switch (eType)
2375 case SC_ADDINARG_INTEGER:
2377 double fVal = GetDouble();
2378 double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2379 ::rtl::math::approxCeil( fVal );
2380 if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2381 aParam <<= (INT32)fInt;
2382 else
2383 SetError(errIllegalArgument);
2385 break;
2387 case SC_ADDINARG_DOUBLE:
2388 aParam <<= (double) GetDouble();
2389 break;
2391 case SC_ADDINARG_STRING:
2392 aParam <<= rtl::OUString( GetString() );
2393 break;
2395 case SC_ADDINARG_INTEGER_ARRAY:
2396 switch( nStackType )
2398 case svDouble:
2399 case svString:
2400 case svSingleRef:
2402 double fVal = GetDouble();
2403 double fInt = (fVal >= 0.0) ? ::rtl::math::approxFloor( fVal ) :
2404 ::rtl::math::approxCeil( fVal );
2405 if ( fInt >= LONG_MIN && fInt <= LONG_MAX )
2407 INT32 nIntVal = (long)fInt;
2408 uno::Sequence<INT32> aInner( &nIntVal, 1 );
2409 uno::Sequence< uno::Sequence<INT32> > aOuter( &aInner, 1 );
2410 aParam <<= aOuter;
2412 else
2413 SetError(errIllegalArgument);
2415 break;
2416 case svDoubleRef:
2418 ScRange aRange;
2419 PopDoubleRef( aRange );
2420 if (!ScRangeToSequence::FillLongArray( aParam, pDok, aRange ))
2421 SetError(errIllegalParameter);
2423 break;
2424 case svMatrix:
2425 if (!ScRangeToSequence::FillLongArray( aParam, PopMatrix() ))
2426 SetError(errIllegalParameter);
2427 break;
2428 default:
2429 PopError();
2430 SetError(errIllegalParameter);
2432 break;
2434 case SC_ADDINARG_DOUBLE_ARRAY:
2435 switch( nStackType )
2437 case svDouble:
2438 case svString:
2439 case svSingleRef:
2441 double fVal = GetDouble();
2442 uno::Sequence<double> aInner( &fVal, 1 );
2443 uno::Sequence< uno::Sequence<double> > aOuter( &aInner, 1 );
2444 aParam <<= aOuter;
2446 break;
2447 case svDoubleRef:
2449 ScRange aRange;
2450 PopDoubleRef( aRange );
2451 if (!ScRangeToSequence::FillDoubleArray( aParam, pDok, aRange ))
2452 SetError(errIllegalParameter);
2454 break;
2455 case svMatrix:
2456 if (!ScRangeToSequence::FillDoubleArray( aParam, PopMatrix() ))
2457 SetError(errIllegalParameter);
2458 break;
2459 default:
2460 PopError();
2461 SetError(errIllegalParameter);
2463 break;
2465 case SC_ADDINARG_STRING_ARRAY:
2466 switch( nStackType )
2468 case svDouble:
2469 case svString:
2470 case svSingleRef:
2472 rtl::OUString aString = rtl::OUString( GetString() );
2473 uno::Sequence<rtl::OUString> aInner( &aString, 1 );
2474 uno::Sequence< uno::Sequence<rtl::OUString> > aOuter( &aInner, 1 );
2475 aParam <<= aOuter;
2477 break;
2478 case svDoubleRef:
2480 ScRange aRange;
2481 PopDoubleRef( aRange );
2482 if (!ScRangeToSequence::FillStringArray( aParam, pDok, aRange ))
2483 SetError(errIllegalParameter);
2485 break;
2486 case svMatrix:
2487 if (!ScRangeToSequence::FillStringArray( aParam, PopMatrix(), pFormatter ))
2488 SetError(errIllegalParameter);
2489 break;
2490 default:
2491 PopError();
2492 SetError(errIllegalParameter);
2494 break;
2496 case SC_ADDINARG_MIXED_ARRAY:
2497 switch( nStackType )
2499 case svDouble:
2500 case svString:
2501 case svSingleRef:
2503 uno::Any aElem;
2504 if ( nStackType == svDouble )
2505 aElem <<= (double) GetDouble();
2506 else if ( nStackType == svString )
2507 aElem <<= rtl::OUString( GetString() );
2508 else
2510 ScAddress aAdr;
2511 if ( PopDoubleRefOrSingleRef( aAdr ) )
2513 ScBaseCell* pCell = GetCell( aAdr );
2514 if ( pCell && pCell->HasStringData() )
2516 String aStr;
2517 GetCellString( aStr, pCell );
2518 aElem <<= rtl::OUString( aStr );
2520 else
2521 aElem <<= (double) GetCellValue( aAdr, pCell );
2524 uno::Sequence<uno::Any> aInner( &aElem, 1 );
2525 uno::Sequence< uno::Sequence<uno::Any> > aOuter( &aInner, 1 );
2526 aParam <<= aOuter;
2528 break;
2529 case svDoubleRef:
2531 ScRange aRange;
2532 PopDoubleRef( aRange );
2533 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2534 SetError(errIllegalParameter);
2536 break;
2537 case svMatrix:
2538 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix() ))
2539 SetError(errIllegalParameter);
2540 break;
2541 default:
2542 PopError();
2543 SetError(errIllegalParameter);
2545 break;
2547 case SC_ADDINARG_VALUE_OR_ARRAY:
2548 if ( IsMissing() )
2549 nStackType = svMissing;
2550 switch( nStackType )
2552 case svDouble:
2553 aParam <<= (double) GetDouble();
2554 break;
2555 case svString:
2556 aParam <<= rtl::OUString( GetString() );
2557 break;
2558 case svSingleRef:
2560 ScAddress aAdr;
2561 if ( PopDoubleRefOrSingleRef( aAdr ) )
2563 ScBaseCell* pCell = GetCell( aAdr );
2564 if ( pCell && pCell->HasStringData() )
2566 String aStr;
2567 GetCellString( aStr, pCell );
2568 aParam <<= rtl::OUString( aStr );
2570 else
2571 aParam <<= (double) GetCellValue( aAdr, pCell );
2574 break;
2575 case svDoubleRef:
2577 ScRange aRange;
2578 PopDoubleRef( aRange );
2579 if (!ScRangeToSequence::FillMixedArray( aParam, pDok, aRange ))
2580 SetError(errIllegalParameter);
2582 break;
2583 case svMatrix:
2584 if (!ScRangeToSequence::FillMixedArray( aParam, PopMatrix() ))
2585 SetError(errIllegalParameter);
2586 break;
2587 case svMissing:
2588 Pop();
2589 aParam.clear();
2590 break;
2591 default:
2592 PopError();
2593 SetError(errIllegalParameter);
2595 break;
2597 case SC_ADDINARG_CELLRANGE:
2598 switch( nStackType )
2600 case svSingleRef:
2602 ScAddress aAdr;
2603 PopSingleRef( aAdr );
2604 ScRange aRange( aAdr );
2605 uno::Reference<table::XCellRange> xObj =
2606 ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2607 if (xObj.is())
2608 aParam <<= xObj;
2609 else
2610 SetError(errIllegalParameter);
2612 break;
2613 case svDoubleRef:
2615 ScRange aRange;
2616 PopDoubleRef( aRange );
2617 uno::Reference<table::XCellRange> xObj =
2618 ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2619 if (xObj.is())
2620 aParam <<= xObj;
2621 else
2622 SetError(errIllegalParameter);
2624 break;
2625 default:
2626 PopError();
2627 SetError(errIllegalParameter);
2629 break;
2631 default:
2632 PopError();
2633 SetError(errIllegalParameter);
2635 aCall.SetParam( nPar, aParam );
2638 while (nPar-- > 0)
2639 Pop(); // in case of error, remove remaining args
2641 if ( !GetError() )
2643 aCall.ExecuteCall();
2645 if ( aCall.HasVarRes() ) // handle async functions
2647 if ( pMyFormulaCell->GetCode()->IsRecalcModeNormal() )
2648 pMyFormulaCell->GetCode()->SetRecalcModeOnLoad();
2650 uno::Reference<sheet::XVolatileResult> xRes = aCall.GetVarRes();
2651 ScAddInListener* pLis = ScAddInListener::Get( xRes );
2652 if ( !pLis )
2654 pLis = ScAddInListener::CreateListener( xRes, pDok );
2655 pMyFormulaCell->StartListening( *pLis );
2657 else
2659 pMyFormulaCell->StartListening( *pLis );
2660 if ( !pLis->HasDocument( pDok ) )
2661 pLis->AddDocument( pDok );
2664 aCall.SetResult( pLis->GetResult() ); // use result from async
2667 if ( aCall.GetErrCode() )
2668 PushError( aCall.GetErrCode() );
2669 else if ( aCall.HasMatrix() )
2671 ScMatrixRef xMat = aCall.GetMatrix();
2672 PushMatrix( xMat );
2674 else if ( aCall.HasString() )
2675 PushString( aCall.GetString() );
2676 else
2677 PushDouble( aCall.GetValue() );
2679 else // error...
2680 PushError( GetError());
2682 else
2684 while( nParamCount-- > 0)
2685 Pop();
2686 PushError( errNoAddin );
2691 void ScInterpreter::ScMissing()
2693 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScMissing" );
2694 PushTempToken( new FormulaMissingToken );
2697 bool
2698 lcl_setVBARange( ScRange& aRange, ScDocument* pDok, SbxVariable* pPar )
2700 bool bOk = false;
2703 uno::Reference< uno::XInterface > xVBARange;
2704 uno::Reference<table::XCellRange> xCellRange = ScCellRangeObj::CreateRangeFromDoc( pDok, aRange );
2705 uno::Sequence< uno::Any > aArgs(2);
2706 aArgs[0] = uno::Any( uno::Reference< uno::XInterface >() ); // dummy parent
2707 aArgs[1] = uno::Any( xCellRange );
2708 xVBARange = ov::createVBAUnoAPIServiceWithArgs( pDok->GetDocumentShell(), "ooo.vba.excel.Range", aArgs );
2709 if ( xVBARange.is() )
2711 String sDummy(RTL_CONSTASCII_USTRINGPARAM("A-Range") );
2712 SbxObjectRef aObj = GetSbUnoObject( sDummy, uno::Any( xVBARange ) );
2713 SetSbUnoObjectDfltPropName( aObj );
2714 bOk = pPar->PutObject( aObj );
2717 catch( uno::Exception& )
2720 return bOk;
2722 void ScInterpreter::ScMacro()
2724 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScMacro" );
2725 SbxBase::ResetError();
2727 BYTE nParamCount = GetByte();
2728 String aMacro( pCur->GetExternal() );
2730 SfxObjectShell* pDocSh = pDok->GetDocumentShell();
2731 if ( !pDocSh || !pDok->CheckMacroWarn() )
2733 PushNoValue(); // ohne DocShell kein CallBasic
2734 return;
2737 // keine Sicherheitsabfrage mehr vorneweg (nur CheckMacroWarn), das passiert im CallBasic
2739 SfxApplication* pSfxApp = SFX_APP();
2740 pSfxApp->EnterBasicCall(); // Dok-Basic anlegen etc.
2742 // Wenn das Dok waehrend eines Basic-Calls geladen wurde,
2743 // ist das Sbx-Objekt evtl. nicht angelegt (?)
2744 // pDocSh->GetSbxObject();
2746 // Funktion ueber den einfachen Namen suchen,
2747 // dann aBasicStr, aMacroStr fuer SfxObjectShell::CallBasic zusammenbauen
2749 StarBASIC* pRoot = pDocSh->GetBasic();
2750 SbxVariable* pVar = pRoot->Find( aMacro, SbxCLASS_METHOD );
2751 if( !pVar || pVar->GetType() == SbxVOID || !pVar->ISA(SbMethod) )
2753 PushError( errNoMacro );
2754 pSfxApp->LeaveBasicCall();
2755 return;
2758 bool bVolatileMacro = false;
2759 SbMethod* pMethod = (SbMethod*)pVar;
2761 SbModule* pModule = pMethod->GetModule();
2762 bool bUseVBAObjects = pModule->IsVBACompat();
2763 SbxObject* pObject = pModule->GetParent();
2764 DBG_ASSERT(pObject->IsA(TYPE(StarBASIC)), "Kein Basic gefunden!");
2765 String aMacroStr = pObject->GetName();
2766 aMacroStr += '.';
2767 aMacroStr += pModule->GetName();
2768 aMacroStr += '.';
2769 aMacroStr += pMethod->GetName();
2770 String aBasicStr;
2771 if (pObject->GetParent())
2773 aBasicStr = pObject->GetParent()->GetName(); // Dokumentenbasic
2774 const SfxFilter* pFilter = NULL;
2775 SfxMedium* pMedium = pDok->GetDocumentShell()->GetMedium();
2776 if ( pMedium )
2777 pFilter = pMedium->GetFilter();
2779 else
2780 aBasicStr = SFX_APP()->GetName(); // Applikationsbasic
2782 // Parameter-Array zusammenbauen
2784 SbxArrayRef refPar = new SbxArray;
2785 BOOL bOk = TRUE;
2786 for( short i = nParamCount; i && bOk ; i-- )
2788 SbxVariable* pPar = refPar->Get( (USHORT) i );
2789 BYTE nStackType = sal::static_int_cast<BYTE>( GetStackType() );
2790 switch( nStackType )
2792 case svDouble:
2793 pPar->PutDouble( GetDouble() );
2794 break;
2795 case svString:
2796 pPar->PutString( GetString() );
2797 break;
2798 case svSingleRef:
2800 ScAddress aAdr;
2801 PopSingleRef( aAdr );
2802 if ( bUseVBAObjects )
2804 ScRange aRange( aAdr );
2805 bOk = lcl_setVBARange( aRange, pDok, pPar );
2807 else
2808 bOk = SetSbxVariable( pPar, aAdr );
2810 break;
2811 case svDoubleRef:
2813 SCCOL nCol1;
2814 SCROW nRow1;
2815 SCTAB nTab1;
2816 SCCOL nCol2;
2817 SCROW nRow2;
2818 SCTAB nTab2;
2819 PopDoubleRef( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
2820 if( nTab1 != nTab2 )
2822 SetError( errIllegalParameter );
2823 bOk = FALSE;
2825 else
2827 if ( bUseVBAObjects )
2829 ScRange aRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
2830 bOk = lcl_setVBARange( aRange, pDok, pPar );
2832 else
2834 SbxDimArrayRef refArray = new SbxDimArray;
2835 refArray->AddDim32( 1, nRow2 - nRow1 + 1 );
2836 refArray->AddDim32( 1, nCol2 - nCol1 + 1 );
2837 ScAddress aAdr( nCol1, nRow1, nTab1 );
2838 for( SCROW nRow = nRow1; bOk && nRow <= nRow2; nRow++ )
2840 aAdr.SetRow( nRow );
2841 INT32 nIdx[ 2 ];
2842 nIdx[ 0 ] = nRow-nRow1+1;
2843 for( SCCOL nCol = nCol1; bOk && nCol <= nCol2; nCol++ )
2845 aAdr.SetCol( nCol );
2846 nIdx[ 1 ] = nCol-nCol1+1;
2847 SbxVariable* p = refArray->Get32( nIdx );
2848 bOk = SetSbxVariable( p, aAdr );
2851 pPar->PutObject( refArray );
2855 break;
2856 case svMatrix:
2858 ScMatrixRef pMat = PopMatrix();
2859 SCSIZE nC, nR;
2860 if (pMat)
2862 pMat->GetDimensions(nC, nR);
2863 SbxDimArrayRef refArray = new SbxDimArray;
2864 refArray->AddDim32( 1, static_cast<INT32>(nR) );
2865 refArray->AddDim32( 1, static_cast<INT32>(nC) );
2866 for( SCSIZE nMatRow = 0; nMatRow < nR; nMatRow++ )
2868 INT32 nIdx[ 2 ];
2869 nIdx[ 0 ] = static_cast<INT32>(nMatRow+1);
2870 for( SCSIZE nMatCol = 0; nMatCol < nC; nMatCol++ )
2872 nIdx[ 1 ] = static_cast<INT32>(nMatCol+1);
2873 SbxVariable* p = refArray->Get32( nIdx );
2874 if (pMat->IsString(nMatCol, nMatRow))
2875 p->PutString( pMat->GetString(nMatCol, nMatRow) );
2876 else
2877 p->PutDouble( pMat->GetDouble(nMatCol, nMatRow));
2880 pPar->PutObject( refArray );
2882 else
2883 SetError( errIllegalParameter );
2885 break;
2886 default:
2887 SetError( errIllegalParameter );
2888 bOk = FALSE;
2891 if( bOk )
2893 pDok->LockTable( aPos.Tab() );
2894 SbxVariableRef refRes = new SbxVariable;
2895 pDok->IncMacroInterpretLevel();
2896 ErrCode eRet = pDocSh->CallBasic( aMacroStr, aBasicStr, NULL, refPar, refRes );
2897 pDok->DecMacroInterpretLevel();
2898 pDok->UnlockTable( aPos.Tab() );
2900 ScMacroManager* pMacroMgr = pDok->GetMacroManager();
2901 if (pMacroMgr)
2903 bVolatileMacro = pMacroMgr->GetUserFuncVolatile( pMethod->GetName() );
2904 pMacroMgr->AddDependentCell(pModule->GetName(), pMyFormulaCell);
2907 SbxDataType eResType = refRes->GetType();
2908 if( pVar->GetError() )
2909 SetError( errNoValue);
2910 if ( eRet != ERRCODE_NONE )
2911 PushNoValue();
2912 else if( eResType >= SbxINTEGER && eResType <= SbxDOUBLE )
2913 PushDouble( refRes->GetDouble() );
2914 else if ( eResType & SbxARRAY )
2916 SbxBase* pElemObj = refRes->GetObject();
2917 SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
2918 short nDim = pDimArray->GetDims();
2919 if ( 1 <= nDim && nDim <= 2 )
2921 INT32 nCs, nCe, nRs, nRe;
2922 SCSIZE nC, nR;
2923 SCCOL nColIdx;
2924 SCROW nRowIdx;
2925 if ( nDim == 1 )
2926 { // array( cols ) eine Zeile, mehrere Spalten
2927 pDimArray->GetDim32( 1, nCs, nCe );
2928 nC = static_cast<SCSIZE>(nCe - nCs + 1);
2929 nRs = nRe = 0;
2930 nR = 1;
2931 nColIdx = 0;
2932 nRowIdx = 1;
2934 else
2935 { // array( rows, cols )
2936 pDimArray->GetDim32( 1, nRs, nRe );
2937 nR = static_cast<SCSIZE>(nRe - nRs + 1);
2938 pDimArray->GetDim32( 2, nCs, nCe );
2939 nC = static_cast<SCSIZE>(nCe - nCs + 1);
2940 nColIdx = 1;
2941 nRowIdx = 0;
2943 ScMatrixRef pMat = GetNewMat( nC, nR);
2944 if ( pMat )
2946 SbxVariable* pV;
2947 SbxDataType eType;
2948 for ( SCSIZE j=0; j < nR; j++ )
2950 INT32 nIdx[ 2 ];
2951 // bei eindimensionalem array( cols ) wird nIdx[1]
2952 // von SbxDimArray::Get ignoriert
2953 nIdx[ nRowIdx ] = nRs + static_cast<INT32>(j);
2954 for ( SCSIZE i=0; i < nC; i++ )
2956 nIdx[ nColIdx ] = nCs + static_cast<INT32>(i);
2957 pV = pDimArray->Get32( nIdx );
2958 eType = pV->GetType();
2959 if ( eType >= SbxINTEGER && eType <= SbxDOUBLE )
2960 pMat->PutDouble( pV->GetDouble(), i, j );
2961 else
2962 pMat->PutString( pV->GetString(), i, j );
2965 PushMatrix( pMat );
2967 else
2968 PushIllegalArgument();
2970 else
2971 PushNoValue();
2973 else
2974 PushString( refRes->GetString() );
2977 pSfxApp->LeaveBasicCall();
2979 if (bVolatileMacro && meVolaileType == NOT_VOLATILE)
2980 meVolaileType = VOLATILE_MACRO;
2984 BOOL ScInterpreter::SetSbxVariable( SbxVariable* pVar, const ScAddress& rPos )
2986 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::SetSbxVariable" );
2987 BOOL bOk = TRUE;
2988 ScBaseCell* pCell = pDok->GetCell( rPos );
2989 if (pCell)
2991 USHORT nErr;
2992 double nVal;
2993 switch( pCell->GetCellType() )
2995 case CELLTYPE_VALUE :
2996 nVal = GetValueCellValue( rPos, (ScValueCell*)pCell );
2997 pVar->PutDouble( nVal );
2998 break;
2999 case CELLTYPE_STRING :
3001 String aVal;
3002 ((ScStringCell*)pCell)->GetString( aVal );
3003 pVar->PutString( aVal );
3004 break;
3006 case CELLTYPE_EDIT :
3008 String aVal;
3009 ((ScEditCell*) pCell)->GetString( aVal );
3010 pVar->PutString( aVal );
3011 break;
3013 case CELLTYPE_FORMULA :
3014 nErr = ((ScFormulaCell*)pCell)->GetErrCode();
3015 if( !nErr )
3017 if( ((ScFormulaCell*)pCell)->IsValue() )
3019 nVal = ((ScFormulaCell*)pCell)->GetValue();
3020 pVar->PutDouble( nVal );
3022 else
3024 String aVal;
3025 ((ScFormulaCell*)pCell)->GetString( aVal );
3026 pVar->PutString( aVal );
3029 else
3030 SetError( nErr ), bOk = FALSE;
3031 break;
3032 default :
3033 pVar->PutDouble( 0.0 );
3036 else
3037 pVar->PutDouble( 0.0 );
3038 return bOk;
3042 void ScInterpreter::ScTableOp()
3044 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScTableOp" );
3045 BYTE nParamCount = GetByte();
3046 if (nParamCount != 3 && nParamCount != 5)
3048 PushIllegalParameter();
3049 return;
3051 ScInterpreterTableOpParams* pTableOp = new ScInterpreterTableOpParams;
3052 if (nParamCount == 5)
3054 PopSingleRef( pTableOp->aNew2 );
3055 PopSingleRef( pTableOp->aOld2 );
3057 PopSingleRef( pTableOp->aNew1 );
3058 PopSingleRef( pTableOp->aOld1 );
3059 PopSingleRef( pTableOp->aFormulaPos );
3061 pTableOp->bValid = TRUE;
3062 pDok->aTableOpList.Insert( pTableOp );
3063 pDok->IncInterpreterTableOpLevel();
3065 BOOL bReuseLastParams = (pDok->aLastTableOpParams == *pTableOp);
3066 if ( bReuseLastParams )
3068 pTableOp->aNotifiedFormulaPos = pDok->aLastTableOpParams.aNotifiedFormulaPos;
3069 pTableOp->bRefresh = TRUE;
3070 for ( ::std::vector< ScAddress >::const_iterator iBroadcast(
3071 pTableOp->aNotifiedFormulaPos.begin() );
3072 iBroadcast != pTableOp->aNotifiedFormulaPos.end();
3073 ++iBroadcast )
3074 { // emulate broadcast and indirectly collect cell pointers
3075 ScBaseCell* pCell = pDok->GetCell( *iBroadcast );
3076 if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA )
3077 ((ScFormulaCell*)pCell)->SetTableOpDirty();
3080 else
3081 { // broadcast and indirectly collect cell pointers and positions
3082 pDok->SetTableOpDirty( pTableOp->aOld1 );
3083 if ( nParamCount == 5 )
3084 pDok->SetTableOpDirty( pTableOp->aOld2 );
3086 pTableOp->bCollectNotifications = FALSE;
3088 ScBaseCell* pFCell = pDok->GetCell( pTableOp->aFormulaPos );
3089 if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA )
3090 ((ScFormulaCell*)pFCell)->SetDirtyVar();
3091 if ( HasCellValueData( pFCell ) )
3092 PushDouble( GetCellValue( pTableOp->aFormulaPos, pFCell ));
3093 else
3095 String aCellString;
3096 GetCellString( aCellString, pFCell );
3097 PushString( aCellString );
3100 pDok->aTableOpList.Remove( pTableOp );
3101 // set dirty again once more to be able to recalculate original
3102 for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast(
3103 pTableOp->aNotifiedFormulaCells.begin() );
3104 iBroadcast != pTableOp->aNotifiedFormulaCells.end();
3105 ++iBroadcast )
3107 (*iBroadcast)->SetTableOpDirty();
3110 // save these params for next incarnation
3111 if ( !bReuseLastParams )
3112 pDok->aLastTableOpParams = *pTableOp;
3114 if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA )
3116 ((ScFormulaCell*)pFCell)->SetDirtyVar();
3117 ((ScFormulaCell*)pFCell)->GetErrCode(); // recalculate original
3120 // Reset all dirty flags so next incarnation does really collect all cell
3121 // pointers during notifications and not just non-dirty ones, which may
3122 // happen if a formula cell is used by more than one TableOp block.
3123 for ( ::std::vector< ScFormulaCell* >::const_iterator iBroadcast2(
3124 pTableOp->aNotifiedFormulaCells.begin() );
3125 iBroadcast2 != pTableOp->aNotifiedFormulaCells.end();
3126 ++iBroadcast2 )
3128 (*iBroadcast2)->ResetTableOpDirtyVar();
3130 delete pTableOp;
3132 pDok->DecInterpreterTableOpLevel();
3138 void ScInterpreter::ScErrCell()
3140 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScErrCell" );
3141 double fErrNum = GetDouble();
3142 PushError((USHORT) fErrNum);
3146 void ScInterpreter::ScDBArea()
3148 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScDBArea" );
3149 ScDBData* pDBData = pDok->GetDBCollection()->FindIndex( pCur->GetIndex());
3150 if (pDBData)
3152 ScComplexRefData aRefData;
3153 aRefData.InitFlags();
3154 pDBData->GetArea( (SCTAB&) aRefData.Ref1.nTab,
3155 (SCCOL&) aRefData.Ref1.nCol,
3156 (SCROW&) aRefData.Ref1.nRow,
3157 (SCCOL&) aRefData.Ref2.nCol,
3158 (SCROW&) aRefData.Ref2.nRow);
3159 aRefData.Ref2.nTab = aRefData.Ref1.nTab;
3160 aRefData.CalcRelFromAbs( aPos );
3161 PushTempToken( new ScDoubleRefToken( aRefData ) );
3163 else
3164 PushError( errNoName);
3168 void ScInterpreter::ScColRowNameAuto()
3170 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScColRowNameAuto" );
3171 ScComplexRefData aRefData( static_cast<const ScToken*>(pCur)->GetDoubleRef() );
3172 aRefData.CalcAbsIfRel( aPos );
3173 if ( aRefData.Valid() )
3175 SCsCOL nStartCol;
3176 SCsROW nStartRow;
3177 SCsCOL nCol2;
3178 SCsROW nRow2;
3179 // evtl. Begrenzung durch definierte ColRowNameRanges merken
3180 nCol2 = aRefData.Ref2.nCol;
3181 nRow2 = aRefData.Ref2.nRow;
3182 // DataArea der ersten Zelle
3183 nStartCol = aRefData.Ref2.nCol = aRefData.Ref1.nCol;
3184 nStartRow = aRefData.Ref2.nRow = aRefData.Ref1.nRow;
3185 aRefData.Ref2.nTab = aRefData.Ref1.nTab;
3186 pDok->GetDataArea( (SCTAB&) aRefData.Ref1.nTab,
3187 (SCCOL&) aRefData.Ref1.nCol,
3188 (SCROW&) aRefData.Ref1.nRow,
3189 (SCCOL&) aRefData.Ref2.nCol,
3190 (SCROW&) aRefData.Ref2.nRow,
3191 TRUE );
3192 // DataArea im Ursprung begrenzen
3193 aRefData.Ref1.nCol = nStartCol;
3194 aRefData.Ref1.nRow = nStartRow;
3196 //! korrespondiert mit ScCompiler::GetToken
3197 if ( aRefData.Ref1.IsColRel() )
3198 { // ColName
3199 aRefData.Ref2.nCol = nStartCol;
3200 // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
3201 if ( aRefData.Ref2.nRow > nRow2 )
3202 aRefData.Ref2.nRow = nRow2;
3203 SCROW nMyRow;
3204 if ( aPos.Col() == nStartCol
3205 && nStartRow <= (nMyRow = aPos.Row()) && nMyRow <= aRefData.Ref2.nRow )
3206 { // Formel in gleicher Spalte und innerhalb des Range
3207 if ( nMyRow == nStartRow )
3208 { // direkt unter dem Namen den Rest nehmen
3209 nStartRow++;
3210 if ( nStartRow > MAXROW )
3211 nStartRow = MAXROW;
3212 aRefData.Ref1.nRow = nStartRow;
3214 else
3215 { // weiter unten vom Namen bis zur Formelzelle
3216 aRefData.Ref2.nRow = nMyRow - 1;
3220 else
3221 { // RowName
3222 aRefData.Ref2.nRow = nStartRow;
3223 // evtl. vorherige Begrenzung durch definierte ColRowNameRanges erhalten
3224 if ( aRefData.Ref2.nCol > nCol2 )
3225 aRefData.Ref2.nCol = nCol2;
3226 SCCOL nMyCol;
3227 if ( aPos.Row() == nStartRow
3228 && nStartCol <= (nMyCol = aPos.Col()) && nMyCol <= aRefData.Ref2.nCol )
3229 { // Formel in gleicher Zeile und innerhalb des Range
3230 if ( nMyCol == nStartCol )
3231 { // direkt neben dem Namen den Rest nehmen
3232 nStartCol++;
3233 if ( nStartCol > MAXCOL )
3234 nStartCol = MAXCOL;
3235 aRefData.Ref1.nCol = nStartCol;
3237 else
3238 { // weiter rechts vom Namen bis zur Formelzelle
3239 aRefData.Ref2.nCol = nMyCol - 1;
3243 aRefData.CalcRelFromAbs( aPos );
3244 PushTempToken( new ScDoubleRefToken( aRefData ) );
3246 else
3247 PushError( errNoRef );
3250 void ScInterpreter::ScExternalRef()
3252 ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
3253 const String* pFile = pRefMgr->getExternalFileName(pCur->GetIndex());
3254 if (!pFile)
3255 PushError(errNoName);
3257 switch (pCur->GetType())
3259 case svExternalSingleRef:
3261 ScSingleRefData aData(static_cast<const ScToken*>(pCur)->GetSingleRef());
3262 if (aData.IsTabRel())
3264 DBG_ERROR("ScCompiler::GetToken: external single reference must have an absolute table reference!");
3265 break;
3268 aData.CalcAbsIfRel(aPos);
3269 ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
3270 ScExternalRefCache::CellFormat aFmt;
3271 ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
3272 pCur->GetIndex(), pCur->GetString(), aAddr, &aPos, NULL, &aFmt);
3274 if (!xNew)
3275 break;
3277 PushTempToken( *xNew); // push a clone
3279 if (aFmt.mbIsSet)
3281 nFuncFmtType = aFmt.mnType;
3282 nFuncFmtIndex = aFmt.mnIndex;
3284 return;
3286 //break; // unreachable, prevent compiler warning
3287 case svExternalDoubleRef:
3289 ScComplexRefData aData(static_cast<const ScToken*>(pCur)->GetDoubleRef());
3290 if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
3292 DBG_ERROR("ScCompiler::GetToken: external double reference must have an absolute table reference!");
3293 break;
3296 aData.CalcAbsIfRel(aPos);
3297 ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
3298 aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
3299 ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getDoubleRefTokens(
3300 pCur->GetIndex(), pCur->GetString(), aRange, &aPos);
3302 if (!xNew)
3303 break;
3305 ScToken* p = static_cast<ScToken*>(xNew->First());
3306 if (p->GetType() != svMatrix)
3307 break;
3309 if (xNew->Next())
3311 // Can't handle more than one matrix per parameter.
3312 SetError( errIllegalArgument);
3313 break;
3316 PushMatrix(p->GetMatrix());
3317 return;
3319 //break; // unreachable, prevent compiler warning
3320 default:
3323 PushError(errNoRef);
3326 // --- internals ------------------------------------------------------------
3329 void ScInterpreter::ScAnswer()
3331 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScAnswer" );
3332 String aStr( GetString() );
3333 if( aStr.EqualsIgnoreCaseAscii( "Das Leben, das Universum und der ganze Rest" ) )
3335 PushInt( 42 );
3336 bOderSo = TRUE;
3338 else
3339 PushNoValue();
3343 void ScInterpreter::ScCalcTeam()
3345 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScCalcTeam" );
3346 static BOOL bShown = FALSE;
3347 if( !bShown )
3349 ShowTheTeam();
3350 String aTeam( RTL_CONSTASCII_USTRINGPARAM( "Ballach, Nebel, Rentz, Rathke, Marmion" ) );
3351 if ( (GetByte() == 1) && ::rtl::math::approxEqual( GetDouble(), 1996) )
3352 aTeam.AppendAscii( " (a word with 'B': -Olk, -Nietsch, -Daeumling)" );
3353 PushString( aTeam );
3354 bShown = TRUE;
3356 else
3357 PushInt( 42 );
3361 void ScInterpreter::ScSpewFunc()
3363 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScSpewFunc" );
3364 BOOL bRefresh = FALSE;
3365 BOOL bClear = FALSE;
3366 // Stack aufraeumen
3367 BYTE nParamCount = GetByte();
3368 while ( nParamCount-- > 0)
3370 switch ( GetStackType() )
3372 case svString:
3373 case svSingleRef:
3374 case svDoubleRef:
3376 const sal_Unicode ch = GetString().GetChar(0);
3377 if ( !bRefresh && ch < 256 )
3378 bRefresh = (tolower( (sal_uChar) ch ) == 'r');
3379 if ( !bClear && ch < 256 )
3380 bClear = (tolower( (sal_uChar) ch ) == 'c');
3382 break;
3383 default:
3384 PopError();
3387 String aStr;
3388 #if SC_SPEW_ENABLED
3389 if ( bRefresh )
3390 theSpew.Clear(); // GetSpew liest SpewRulesFile neu
3391 theSpew.GetSpew( aStr );
3392 if ( bClear )
3393 theSpew.Clear(); // release Memory
3394 xub_StrLen nPos = 0;
3395 while ( (nPos = aStr.SearchAndReplace( '\n', ' ', nPos )) != STRING_NOTFOUND )
3396 nPos++;
3397 #else
3398 aStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "spitted out all spew :-(" ) );
3399 #endif
3400 PushString( aStr );
3404 #include "sctictac.hxx"
3405 #include "scmod.hxx"
3407 extern "C" { static void SAL_CALL thisModule() {} }
3409 void ScInterpreter::ScGame()
3411 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScGame" );
3412 enum GameType {
3413 SC_GAME_NONE,
3414 SC_GAME_ONCE,
3415 SC_GAME_START,
3416 SC_GAME_TICTACTOE = SC_GAME_START,
3417 SC_GAME_STARWARS,
3418 SC_GAME_FROGGER,
3419 SC_GAME_COUNT
3421 // ein grep im binary laeuft ins leere
3422 static sal_Char sGameNone[] = "\14\36\6\137\10\27\36\13\100";
3423 static sal_Char sGameOnce[] = "\20\27\137\21\20\123\137\21\20\13\137\36\30\36\26\21\136";
3424 static sal_Char sGameTicTacToe[] = "\53\26\34\53\36\34\53\20\32";
3425 static sal_Char sGameStarWars[] = "\54\13\36\15\50\36\15\14";
3426 static sal_Char sGameFrogger[] = "\71\15\20\30\30\26\32";
3427 sal_Char* const pGames[SC_GAME_COUNT] = {
3428 sGameNone,
3429 sGameOnce,
3430 sGameTicTacToe,
3431 sGameStarWars,
3432 sGameFrogger
3434 #if 0
3435 say what?
3436 oh no, not again!
3437 TicTacToe
3438 StarWars
3439 Froggie
3440 // Routine um Datenblock zu erzeugen:
3441 #include <stdio.h>
3442 int main()
3444 int b = 1;
3445 int c;
3446 while ( (c = getchar()) != EOF )
3448 if ( b == 1 )
3450 printf( "\"" );
3451 b = 0;
3453 if ( c != 10 )
3455 c ^= 0x7F;
3456 printf( "\\%o", c );
3459 else
3461 printf( "\";\n" );
3462 b = 1;
3465 return 0;
3467 #endif
3468 static BOOL bRun[SC_GAME_COUNT] = { FALSE };
3469 static BOOL bFirst = TRUE;
3470 if ( bFirst )
3472 bFirst = FALSE;
3473 for ( int j = SC_GAME_NONE; j < SC_GAME_COUNT; j++ )
3475 sal_Char* p = pGames[j];
3476 while ( *p )
3477 *p++ ^= 0x7F;
3480 String aFuncResult;
3481 GameType eGame = SC_GAME_NONE;
3482 BYTE nParamCount = GetByte();
3483 if ( nParamCount >= 1 )
3485 String aStr( GetString() );
3486 nParamCount--;
3487 for ( int j = SC_GAME_START; j < SC_GAME_COUNT; j++ )
3489 if ( aStr.EqualsAscii( pGames[j] ) )
3491 eGame = (GameType) j;
3492 break; // for
3495 if ( eGame != SC_GAME_NONE )
3497 // jedes Game nur ein einziges Mal starten, um nicht durch Recalc
3498 // o.ae. mehrere Instanzen zu haben, ideal waere eine Abfrage an den
3499 // Games, ob sie bereits laufen ...
3500 if ( bRun[ eGame ] && eGame != SC_GAME_TICTACTOE )
3501 eGame = SC_GAME_ONCE;
3502 else
3504 bRun[ eGame ] = TRUE;
3505 switch ( eGame )
3507 case SC_GAME_TICTACTOE :
3509 static ScTicTacToe* pTicTacToe = NULL;
3510 static ScRange aTTTrange;
3511 static BOOL bHumanFirst = FALSE;
3512 if ( nParamCount >= 1 )
3514 if ( GetStackType() == svDoubleRef )
3516 ScRange aRange;
3517 PopDoubleRef( aRange );
3518 nParamCount--;
3519 if ( aRange.aEnd.Col() - aRange.aStart.Col() == 2
3520 && aRange.aEnd.Row() - aRange.aStart.Row() == 2 )
3522 BOOL bOk;
3523 if ( pTicTacToe )
3524 bOk = (aRange == aTTTrange);
3525 else
3527 bOk =TRUE;
3528 aTTTrange = aRange;
3529 pTicTacToe = new ScTicTacToe( pDok,
3530 aRange.aStart );
3531 pTicTacToe->Initialize( bHumanFirst );
3533 // nur einmal und das auf dem gleichen Range
3534 if ( !bOk )
3535 eGame = SC_GAME_ONCE;
3536 else
3538 Square_Type aWinner = pTicTacToe->CalcMove();
3539 pTicTacToe->GetOutput( aFuncResult );
3540 if ( aWinner != pTicTacToe->GetEmpty() )
3542 delete pTicTacToe;
3543 pTicTacToe = NULL;
3544 bRun[ eGame ] = FALSE;
3545 bHumanFirst = !bHumanFirst;
3547 pDok->GetDocumentShell()->Broadcast(
3548 SfxSimpleHint( FID_DATACHANGED ) );
3549 pDok->ResetChanged( aRange );
3552 else
3553 SetError( errIllegalArgument );
3555 else
3556 SetError( errIllegalParameter );
3558 else
3559 SetError( errIllegalParameter );
3561 break;
3562 case SC_GAME_STARWARS :
3564 oslModule m_tfu = osl_loadModuleRelative(&thisModule, rtl::OUString::createFromAscii( SVLIBRARY( "tfu" ) ).pData, SAL_LOADMODULE_NOW);
3565 typedef void StartInvader_Type (Window*, ResMgr*);
3567 StartInvader_Type *StartInvader = (StartInvader_Type *) osl_getFunctionSymbol( m_tfu, rtl::OUString::createFromAscii("StartInvader").pData );
3568 if ( StartInvader )
3569 StartInvader( Application::GetDefDialogParent(), ResMgr::CreateResMgr( "tfu" ));
3571 break;
3572 case SC_GAME_FROGGER :
3573 //Game();
3574 break;
3575 default:
3577 // added to avoid warnings
3583 // Stack aufraeumen
3584 while ( nParamCount-- > 0)
3585 Pop();
3586 if ( !aFuncResult.Len() )
3587 PushString( String( pGames[ eGame ], RTL_TEXTENCODING_ASCII_US ) );
3588 else
3589 PushString( aFuncResult );
3592 void ScInterpreter::ScTTT()
3593 { // Temporaerer Test-Tanz, zum auspropieren von Funktionen etc.
3594 BOOL bOk = TRUE;
3595 BYTE nParamCount = GetByte();
3596 // do something, nParamCount bei Pops runterzaehlen!
3598 if ( bOk && nParamCount )
3600 bOk = GetBool();
3601 --nParamCount;
3603 // Stack aufraeumen
3604 while ( nParamCount-- > 0)
3605 Pop();
3606 static const sal_Unicode __FAR_DATA sEyes[] = { ',',';',':','|','8','B', 0 };
3607 static const sal_Unicode __FAR_DATA sGoods[] = { ')',']','}', 0 };
3608 static const sal_Unicode __FAR_DATA sBads[] = { '(','[','{','/', 0 };
3609 sal_Unicode aFace[4];
3610 if ( bOk )
3612 aFace[0] = sEyes[ rand() % ((sizeof( sEyes )/sizeof(sal_Unicode)) - 1) ];
3613 aFace[1] = '-';
3614 aFace[2] = sGoods[ rand() % ((sizeof( sGoods )/sizeof(sal_Unicode)) - 1) ];
3616 else
3618 aFace[0] = ':';
3619 aFace[1] = '-';
3620 aFace[2] = sBads[ rand() % ((sizeof( sBads )/sizeof(sal_Unicode)) - 1) ];
3622 aFace[3] = 0;
3623 PushStringBuffer( aFace );
3626 // -------------------------------------------------------------------------
3629 ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc,
3630 const ScAddress& rPos, ScTokenArray& r ) :
3631 aCode( r ),
3632 aPos( rPos ),
3633 rArr( r ),
3634 pDok( pDoc ),
3635 pTokenMatrixMap( NULL ),
3636 pMyFormulaCell( pCell ),
3637 pFormatter( pDoc->GetFormatTable() ),
3638 bCalcAsShown( pDoc->GetDocOptions().IsCalcAsShown() ),
3639 meVolaileType(NOT_VOLATILE)
3641 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScTTT" );
3642 // pStack = new ScToken*[ MAXSTACK ];
3644 BYTE cMatFlag = pMyFormulaCell->GetMatrixFlag();
3645 bMatrixFormula = ( cMatFlag == MM_FORMULA || cMatFlag == MM_FAKE );
3646 if (!bGlobalStackInUse)
3648 bGlobalStackInUse = TRUE;
3649 if (!pGlobalStack)
3650 pGlobalStack = new ScTokenStack;
3651 pStackObj = pGlobalStack;
3653 else
3655 pStackObj = new ScTokenStack;
3657 pStack = pStackObj->pPointer;
3660 ScInterpreter::~ScInterpreter()
3662 // delete pStack;
3664 if ( pStackObj == pGlobalStack )
3665 bGlobalStackInUse = FALSE;
3666 else
3667 delete pStackObj;
3668 if (pTokenMatrixMap)
3669 delete pTokenMatrixMap;
3673 void ScInterpreter::GlobalExit() // static
3675 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::GlobalExit" );
3676 DBG_ASSERT(!bGlobalStackInUse, "wer benutzt noch den TokenStack?");
3677 DELETEZ(pGlobalStack);
3681 StackVar ScInterpreter::Interpret()
3683 RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::Interpret" );
3684 short nRetTypeExpr = NUMBERFORMAT_UNDEFINED;
3685 ULONG nRetIndexExpr = 0;
3686 USHORT nErrorFunction = 0;
3687 USHORT nErrorFunctionCount = 0;
3688 USHORT nStackBase;
3690 nGlobalError = 0;
3691 nStackBase = sp = maxsp = 0;
3692 nRetFmtType = NUMBERFORMAT_UNDEFINED;
3693 nFuncFmtType = NUMBERFORMAT_UNDEFINED;
3694 nFuncFmtIndex = nCurFmtIndex = nRetFmtIndex = 0;
3695 xResult = NULL;
3696 pJumpMatrix = NULL;
3697 glSubTotal = FALSE;
3698 ScTokenMatrixMap::const_iterator aTokenMatrixMapIter;
3700 // Once upon a time we used to have FP exceptions on, and there was a
3701 // Windows printer driver that kept switching off exceptions, so we had to
3702 // switch them back on again every time. Who knows if there isn't a driver
3703 // that keeps switching exceptions on, now that we run with exceptions off,
3704 // so reassure exceptions are really off.
3705 SAL_MATH_FPEXCEPTIONS_OFF();
3707 aCode.Reset();
3708 while( ( pCur = aCode.Next() ) != NULL
3709 && (!nGlobalError || nErrorFunction <= nErrorFunctionCount) )
3711 OpCode eOp = pCur->GetOpCode();
3712 cPar = pCur->GetByte();
3713 if ( eOp == ocPush )
3715 // RPN code push without error
3716 PushWithoutError( (FormulaToken&) *pCur );
3718 else if (pTokenMatrixMap && !(eOp == ocIf || eOp == ocChose) &&
3719 ((aTokenMatrixMapIter = pTokenMatrixMap->find( pCur)) !=
3720 pTokenMatrixMap->end()) &&
3721 (*aTokenMatrixMapIter).second->GetType() != svJumpMatrix)
3723 // Path already calculated, reuse result.
3724 nStackBase = sp - pCur->GetParamCount();
3725 if ( nStackBase > sp )
3726 nStackBase = sp; // underflow?!?
3727 sp = nStackBase;
3728 PushTempToken( (*aTokenMatrixMapIter).second);
3730 else
3732 // previous expression determines the current number format
3733 nCurFmtType = nRetTypeExpr;
3734 nCurFmtIndex = nRetIndexExpr;
3735 // default function's format, others are set if needed
3736 nFuncFmtType = NUMBERFORMAT_NUMBER;
3737 nFuncFmtIndex = 0;
3739 if ( eOp == ocIf || eOp == ocChose )
3740 nStackBase = sp; // don't mess around with the jumps
3741 else
3743 // Convert parameters to matrix if in array/matrix formula and
3744 // parameters of function indicate doing so. Create JumpMatrix
3745 // if necessary.
3746 if ( MatrixParameterConversion() )
3748 eOp = ocNone; // JumpMatrix created
3749 nStackBase = sp;
3751 else
3752 nStackBase = sp - pCur->GetParamCount();
3754 if ( nStackBase > sp )
3755 nStackBase = sp; // underflow?!?
3757 switch( eOp )
3759 case ocSep:
3760 case ocClose: // pushed by the compiler
3761 case ocMissing : ScMissing(); break;
3762 case ocMacro : ScMacro(); break;
3763 case ocDBArea : ScDBArea(); break;
3764 case ocColRowNameAuto : ScColRowNameAuto(); break;
3765 // separated case ocPush : Push( (ScToken&) *pCur ); break;
3766 case ocExternalRef : ScExternalRef(); break;
3767 case ocIf : ScIfJump(); break;
3768 case ocChose : ScChoseJump(); break;
3769 case ocAdd : ScAdd(); break;
3770 case ocSub : ScSub(); break;
3771 case ocMul : ScMul(); break;
3772 case ocDiv : ScDiv(); break;
3773 case ocAmpersand : ScAmpersand(); break;
3774 case ocPow : ScPow(); break;
3775 case ocEqual : ScEqual(); break;
3776 case ocNotEqual : ScNotEqual(); break;
3777 case ocLess : ScLess(); break;
3778 case ocGreater : ScGreater(); break;
3779 case ocLessEqual : ScLessEqual(); break;
3780 case ocGreaterEqual : ScGreaterEqual(); break;
3781 case ocAnd : ScAnd(); break;
3782 case ocOr : ScOr(); break;
3783 case ocIntersect : ScIntersect(); break;
3784 case ocRange : ScRangeFunc(); break;
3785 case ocUnion : ScUnionFunc(); break;
3786 case ocNot : ScNot(); break;
3787 case ocNegSub :
3788 case ocNeg : ScNeg(); break;
3789 case ocPercentSign : ScPercentSign(); break;
3790 case ocPi : ScPi(); break;
3791 // case ocDefPar : ScDefPar(); break;
3792 case ocRandom : ScRandom(); break;
3793 case ocTrue : ScTrue(); break;
3794 case ocFalse : ScFalse(); break;
3795 case ocGetActDate : ScGetActDate(); break;
3796 case ocGetActTime : ScGetActTime(); break;
3797 case ocNotAvail : PushError( NOTAVAILABLE); break;
3798 case ocDeg : ScDeg(); break;
3799 case ocRad : ScRad(); break;
3800 case ocSin : ScSin(); break;
3801 case ocCos : ScCos(); break;
3802 case ocTan : ScTan(); break;
3803 case ocCot : ScCot(); break;
3804 case ocArcSin : ScArcSin(); break;
3805 case ocArcCos : ScArcCos(); break;
3806 case ocArcTan : ScArcTan(); break;
3807 case ocArcCot : ScArcCot(); break;
3808 case ocSinHyp : ScSinHyp(); break;
3809 case ocCosHyp : ScCosHyp(); break;
3810 case ocTanHyp : ScTanHyp(); break;
3811 case ocCotHyp : ScCotHyp(); break;
3812 case ocArcSinHyp : ScArcSinHyp(); break;
3813 case ocArcCosHyp : ScArcCosHyp(); break;
3814 case ocArcTanHyp : ScArcTanHyp(); break;
3815 case ocArcCotHyp : ScArcCotHyp(); break;
3816 case ocExp : ScExp(); break;
3817 case ocLn : ScLn(); break;
3818 case ocLog10 : ScLog10(); break;
3819 case ocSqrt : ScSqrt(); break;
3820 case ocFact : ScFact(); break;
3821 case ocGetYear : ScGetYear(); break;
3822 case ocGetMonth : ScGetMonth(); break;
3823 case ocGetDay : ScGetDay(); break;
3824 case ocGetDayOfWeek : ScGetDayOfWeek(); break;
3825 case ocWeek : ScGetWeekOfYear(); break;
3826 case ocEasterSunday : ScEasterSunday(); break;
3827 case ocGetHour : ScGetHour(); break;
3828 case ocGetMin : ScGetMin(); break;
3829 case ocGetSec : ScGetSec(); break;
3830 case ocPlusMinus : ScPlusMinus(); break;
3831 case ocAbs : ScAbs(); break;
3832 case ocInt : ScInt(); break;
3833 case ocEven : ScEven(); break;
3834 case ocOdd : ScOdd(); break;
3835 case ocPhi : ScPhi(); break;
3836 case ocGauss : ScGauss(); break;
3837 case ocStdNormDist : ScStdNormDist(); break;
3838 case ocFisher : ScFisher(); break;
3839 case ocFisherInv : ScFisherInv(); break;
3840 case ocIsEmpty : ScIsEmpty(); break;
3841 case ocIsString : ScIsString(); break;
3842 case ocIsNonString : ScIsNonString(); break;
3843 case ocIsLogical : ScIsLogical(); break;
3844 case ocType : ScType(); break;
3845 case ocCell : ScCell(); break;
3846 case ocIsRef : ScIsRef(); break;
3847 case ocIsValue : ScIsValue(); break;
3848 case ocIsFormula : ScIsFormula(); break;
3849 case ocFormula : ScFormula(); break;
3850 case ocIsNA : ScIsNV(); break;
3851 case ocIsErr : ScIsErr(); break;
3852 case ocIsError : ScIsError(); break;
3853 case ocIsEven : ScIsEven(); break;
3854 case ocIsOdd : ScIsOdd(); break;
3855 case ocN : ScN(); break;
3856 case ocGetDateValue : ScGetDateValue(); break;
3857 case ocGetTimeValue : ScGetTimeValue(); break;
3858 case ocCode : ScCode(); break;
3859 case ocTrim : ScTrim(); break;
3860 case ocUpper : ScUpper(); break;
3861 case ocPropper : ScPropper(); break;
3862 case ocLower : ScLower(); break;
3863 case ocLen : ScLen(); break;
3864 case ocT : ScT(); break;
3865 case ocClean : ScClean(); break;
3866 case ocValue : ScValue(); break;
3867 case ocChar : ScChar(); break;
3868 case ocArcTan2 : ScArcTan2(); break;
3869 case ocMod : ScMod(); break;
3870 case ocPower : ScPower(); break;
3871 case ocRound : ScRound(); break;
3872 case ocRoundUp : ScRoundUp(); break;
3873 case ocTrunc :
3874 case ocRoundDown : ScRoundDown(); break;
3875 case ocCeil : ScCeil(); break;
3876 case ocFloor : ScFloor(); break;
3877 case ocSumProduct : ScSumProduct(); break;
3878 case ocSumSQ : ScSumSQ(); break;
3879 case ocSumX2MY2 : ScSumX2MY2(); break;
3880 case ocSumX2DY2 : ScSumX2DY2(); break;
3881 case ocSumXMY2 : ScSumXMY2(); break;
3882 case ocLog : ScLog(); break;
3883 case ocGCD : ScGCD(); break;
3884 case ocLCM : ScLCM(); break;
3885 case ocGetDate : ScGetDate(); break;
3886 case ocGetTime : ScGetTime(); break;
3887 case ocGetDiffDate : ScGetDiffDate(); break;
3888 case ocGetDiffDate360 : ScGetDiffDate360(); break;
3889 case ocMin : ScMin( FALSE ); break;
3890 case ocMinA : ScMin( TRUE ); break;
3891 case ocMax : ScMax( FALSE ); break;
3892 case ocMaxA : ScMax( TRUE ); break;
3893 case ocSum : ScSum(); break;
3894 case ocProduct : ScProduct(); break;
3895 case ocNPV : ScNPV(); break;
3896 case ocIRR : ScIRR(); break;
3897 case ocMIRR : ScMIRR(); break;
3898 case ocISPMT : ScISPMT(); break;
3899 case ocAverage : ScAverage( FALSE ); break;
3900 case ocAverageA : ScAverage( TRUE ); break;
3901 case ocCount : ScCount(); break;
3902 case ocCount2 : ScCount2(); break;
3903 case ocVar : ScVar( FALSE ); break;
3904 case ocVarA : ScVar( TRUE ); break;
3905 case ocVarP : ScVarP( FALSE ); break;
3906 case ocVarPA : ScVarP( TRUE ); break;
3907 case ocStDev : ScStDev( FALSE ); break;
3908 case ocStDevA : ScStDev( TRUE ); break;
3909 case ocStDevP : ScStDevP( FALSE ); break;
3910 case ocStDevPA : ScStDevP( TRUE ); break;
3911 case ocBW : ScBW(); break;
3912 case ocDIA : ScDIA(); break;
3913 case ocGDA : ScGDA(); break;
3914 case ocGDA2 : ScGDA2(); break;
3915 case ocVBD : ScVDB(); break;
3916 case ocLaufz : ScLaufz(); break;
3917 case ocLIA : ScLIA(); break;
3918 case ocRMZ : ScRMZ(); break;
3919 case ocColumns : ScColumns(); break;
3920 case ocRows : ScRows(); break;
3921 case ocTables : ScTables(); break;
3922 case ocColumn : ScColumn(); break;
3923 case ocRow : ScRow(); break;
3924 case ocTable : ScTable(); break;
3925 case ocZGZ : ScZGZ(); break;
3926 case ocZW : ScZW(); break;
3927 case ocZZR : ScZZR(); break;
3928 case ocZins : ScZins(); break;
3929 case ocZinsZ : ScZinsZ(); break;
3930 case ocKapz : ScKapz(); break;
3931 case ocKumZinsZ : ScKumZinsZ(); break;
3932 case ocKumKapZ : ScKumKapZ(); break;
3933 case ocEffektiv : ScEffektiv(); break;
3934 case ocNominal : ScNominal(); break;
3935 case ocSubTotal : ScSubTotal(); break;
3936 case ocDBSum : ScDBSum(); break;
3937 case ocDBCount : ScDBCount(); break;
3938 case ocDBCount2 : ScDBCount2(); break;
3939 case ocDBAverage : ScDBAverage(); break;
3940 case ocDBGet : ScDBGet(); break;
3941 case ocDBMax : ScDBMax(); break;
3942 case ocDBMin : ScDBMin(); break;
3943 case ocDBProduct : ScDBProduct(); break;
3944 case ocDBStdDev : ScDBStdDev(); break;
3945 case ocDBStdDevP : ScDBStdDevP(); break;
3946 case ocDBVar : ScDBVar(); break;
3947 case ocDBVarP : ScDBVarP(); break;
3948 case ocIndirect : ScIndirect(); break;
3949 case ocAddress : ScAddressFunc(); break;
3950 case ocMatch : ScMatch(); break;
3951 case ocCountEmptyCells : ScCountEmptyCells(); break;
3952 case ocCountIf : ScCountIf(); break;
3953 case ocSumIf : ScSumIf(); break;
3954 case ocLookup : ScLookup(); break;
3955 case ocVLookup : ScVLookup(); break;
3956 case ocHLookup : ScHLookup(); break;
3957 case ocIndex : ScIndex(); break;
3958 case ocMultiArea : ScMultiArea(); break;
3959 case ocOffset : ScOffset(); break;
3960 case ocAreas : ScAreas(); break;
3961 case ocCurrency : ScCurrency(); break;
3962 case ocReplace : ScReplace(); break;
3963 case ocFixed : ScFixed(); break;
3964 case ocFind : ScFind(); break;
3965 case ocExact : ScExact(); break;
3966 case ocLeft : ScLeft(); break;
3967 case ocRight : ScRight(); break;
3968 case ocSearch : ScSearch(); break;
3969 case ocMid : ScMid(); break;
3970 case ocText : ScText(); break;
3971 case ocSubstitute : ScSubstitute(); break;
3972 case ocRept : ScRept(); break;
3973 case ocConcat : ScConcat(); break;
3974 case ocMatValue : ScMatValue(); break;
3975 case ocMatrixUnit : ScEMat(); break;
3976 case ocMatDet : ScMatDet(); break;
3977 case ocMatInv : ScMatInv(); break;
3978 case ocMatMult : ScMatMult(); break;
3979 case ocMatTrans : ScMatTrans(); break;
3980 case ocMatRef : ScMatRef(); break;
3981 case ocBackSolver : ScBackSolver(); break;
3982 case ocB : ScB(); break;
3983 case ocNormDist : ScNormDist(); break;
3984 case ocExpDist : ScExpDist(); break;
3985 case ocBinomDist : ScBinomDist(); break;
3986 case ocPoissonDist : ScPoissonDist(); break;
3987 case ocKombin : ScKombin(); break;
3988 case ocKombin2 : ScKombin2(); break;
3989 case ocVariationen : ScVariationen(); break;
3990 case ocVariationen2 : ScVariationen2(); break;
3991 case ocHypGeomDist : ScHypGeomDist(); break;
3992 case ocLogNormDist : ScLogNormDist(); break;
3993 case ocTDist : ScTDist(); break;
3994 case ocFDist : ScFDist(); break;
3995 case ocChiDist : ScChiDist(); break;
3996 case ocChiSqDist : ScChiSqDist(); break;
3997 case ocStandard : ScStandard(); break;
3998 case ocAveDev : ScAveDev(); break;
3999 case ocDevSq : ScDevSq(); break;
4000 case ocKurt : ScKurt(); break;
4001 case ocSchiefe : ScSkew(); break;
4002 case ocModalValue : ScModalValue(); break;
4003 case ocMedian : ScMedian(); break;
4004 case ocGeoMean : ScGeoMean(); break;
4005 case ocHarMean : ScHarMean(); break;
4006 case ocWeibull : ScWeibull(); break;
4007 case ocKritBinom : ScCritBinom(); break;
4008 case ocNegBinomVert : ScNegBinomDist(); break;
4009 case ocNoName : ScNoName(); break;
4010 case ocBad : ScBadName(); break;
4011 case ocZTest : ScZTest(); break;
4012 case ocTTest : ScTTest(); break;
4013 case ocFTest : ScFTest(); break;
4014 case ocRank : ScRank(); break;
4015 case ocPercentile : ScPercentile(); break;
4016 case ocPercentrank : ScPercentrank(); break;
4017 case ocLarge : ScLarge(); break;
4018 case ocSmall : ScSmall(); break;
4019 case ocFrequency : ScFrequency(); break;
4020 case ocQuartile : ScQuartile(); break;
4021 case ocNormInv : ScNormInv(); break;
4022 case ocSNormInv : ScSNormInv(); break;
4023 case ocConfidence : ScConfidence(); break;
4024 case ocTrimMean : ScTrimMean(); break;
4025 case ocProb : ScProbability(); break;
4026 case ocCorrel : ScCorrel(); break;
4027 case ocCovar : ScCovar(); break;
4028 case ocPearson : ScPearson(); break;
4029 case ocRSQ : ScRSQ(); break;
4030 case ocSTEYX : ScSTEXY(); break;
4031 case ocSlope : ScSlope(); break;
4032 case ocIntercept : ScIntercept(); break;
4033 case ocTrend : ScTrend(); break;
4034 case ocGrowth : ScGrowth(); break;
4035 case ocRGP : ScRGP(); break;
4036 case ocRKP : ScRKP(); break;
4037 case ocForecast : ScForecast(); break;
4038 case ocGammaLn : ScLogGamma(); break;
4039 case ocGamma : ScGamma(); break;
4040 case ocGammaDist : ScGammaDist(); break;
4041 case ocGammaInv : ScGammaInv(); break;
4042 case ocChiTest : ScChiTest(); break;
4043 case ocChiInv : ScChiInv(); break;
4044 case ocChiSqInv : ScChiSqInv(); break;
4045 case ocTInv : ScTInv(); break;
4046 case ocFInv : ScFInv(); break;
4047 case ocLogInv : ScLogNormInv(); break;
4048 case ocBetaDist : ScBetaDist(); break;
4049 case ocBetaInv : ScBetaInv(); break;
4050 case ocExternal : ScExternal(); break;
4051 case ocTableOp : ScTableOp(); break;
4052 // case ocErrCell : ScErrCell(); break;
4053 case ocStop : break;
4054 case ocErrorType : ScErrorType(); break;
4055 case ocCurrent : ScCurrent(); break;
4056 case ocStyle : ScStyle(); break;
4057 case ocDde : ScDde(); break;
4058 case ocBase : ScBase(); break;
4059 case ocDecimal : ScDecimal(); break;
4060 case ocConvert : ScConvert(); break;
4061 case ocEuroConvert : ScEuroConvert(); break;
4062 case ocRoman : ScRoman(); break;
4063 case ocArabic : ScArabic(); break;
4064 case ocInfo : ScInfo(); break;
4065 case ocHyperLink : ScHyperLink(); break;
4066 case ocBahtText : ScBahtText(); break;
4067 case ocPhonetic : ScPhoneticString(); break;
4068 case ocGetPivotData : ScGetPivotData(); break;
4069 case ocJis : ScJis(); break;
4070 case ocAsc : ScAsc(); break;
4071 case ocAnswer : ScAnswer(); break;
4072 case ocTeam : ScCalcTeam(); break;
4073 case ocTTT : ScTTT(); break;
4074 case ocSpew : ScSpewFunc(); break;
4075 case ocGame : ScGame(); break;
4076 case ocNone : nFuncFmtType = NUMBERFORMAT_UNDEFINED; break;
4077 default : PushError( errUnknownOpCode); break;
4080 // If the function signalled that it pushed a subroutine on the
4081 // instruction code stack instead of a result, continue with
4082 // execution of the subroutine.
4083 if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall)
4085 Pop();
4086 continue; // while( ( pCur = aCode.Next() ) != NULL ...
4089 if (FormulaCompiler::IsOpCodeVolatile(eOp))
4090 meVolaileType = VOLATILE;
4092 // Remember result matrix in case it could be reused.
4093 if (pTokenMatrixMap && sp && GetStackType() == svMatrix)
4094 pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur,
4095 pStack[sp-1]));
4097 // outer function determines format of an expression
4098 if ( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
4100 nRetTypeExpr = nFuncFmtType;
4101 // inherit the format index only for currency formats
4102 nRetIndexExpr = ( nFuncFmtType == NUMBERFORMAT_CURRENCY ?
4103 nFuncFmtIndex : 0 );
4107 // Need a clean stack environment for the JumpMatrix to work.
4108 if (nGlobalError && eOp != ocPush && sp > nStackBase + 1)
4110 // Not all functions pop all parameters in case an error is
4111 // generated. Clean up stack. Assumes that every function pushes a
4112 // result, may be arbitrary in case of error.
4113 const FormulaToken* pLocalResult = pStack[ sp - 1 ];
4114 while (sp > nStackBase)
4115 Pop();
4116 PushTempToken( *pLocalResult );
4119 bool bGotResult;
4122 bGotResult = false;
4123 BYTE nLevel = 0;
4124 if ( GetStackType( ++nLevel ) == svJumpMatrix )
4125 ; // nothing
4126 else if ( GetStackType( ++nLevel ) == svJumpMatrix )
4127 ; // nothing
4128 else
4129 nLevel = 0;
4130 if ( nLevel == 1 || (nLevel == 2 && aCode.IsEndOfPath()) )
4131 bGotResult = JumpMatrix( nLevel );
4132 else
4133 pJumpMatrix = NULL;
4134 } while ( bGotResult );
4137 // Functions that evaluate an error code and directly set nGlobalError to 0,
4138 // usage: switch( OpCode ) { CASE_OCERRFUNC statements; }
4139 #define CASE_OCERRFUNC \
4140 case ocCount : \
4141 case ocCount2 : \
4142 case ocErrorType : \
4143 case ocIsEmpty : \
4144 case ocIsErr : \
4145 case ocIsError : \
4146 case ocIsFormula : \
4147 case ocIsLogical : \
4148 case ocIsNA : \
4149 case ocIsNonString : \
4150 case ocIsRef : \
4151 case ocIsString : \
4152 case ocIsValue : \
4153 case ocN : \
4154 case ocType :
4156 switch ( eOp )
4158 CASE_OCERRFUNC
4159 ++ nErrorFunction;
4160 default:
4161 ; // nothing
4163 if ( nGlobalError )
4165 if ( !nErrorFunctionCount )
4166 { // count of errorcode functions in formula
4167 for ( FormulaToken* t = rArr.FirstRPN(); t; t = rArr.NextRPN() )
4169 switch ( t->GetOpCode() )
4171 CASE_OCERRFUNC
4172 ++nErrorFunctionCount;
4173 default:
4174 ; // nothing
4178 if ( nErrorFunction >= nErrorFunctionCount )
4179 ++nErrorFunction; // that's it, error => terminate
4183 // End: obtain result
4185 if( sp )
4187 pCur = pStack[ sp-1 ];
4188 if( pCur->GetOpCode() == ocPush )
4190 switch( pCur->GetType() )
4192 case svEmptyCell:
4193 ; // nothing
4194 break;
4195 case svError:
4196 nGlobalError = pCur->GetError();
4197 break;
4198 case svDouble :
4199 if ( nFuncFmtType == NUMBERFORMAT_UNDEFINED )
4201 nRetTypeExpr = NUMBERFORMAT_NUMBER;
4202 nRetIndexExpr = 0;
4204 break;
4205 case svString :
4206 nRetTypeExpr = NUMBERFORMAT_TEXT;
4207 nRetIndexExpr = 0;
4208 break;
4209 case svSingleRef :
4211 ScAddress aAdr;
4212 PopSingleRef( aAdr );
4213 if( !nGlobalError )
4214 PushCellResultToken( false, aAdr,
4215 &nRetTypeExpr, &nRetIndexExpr);
4217 break;
4218 case svRefList :
4219 PopError(); // maybe #REF! takes precedence over #VALUE!
4220 PushError( errNoValue);
4221 break;
4222 case svDoubleRef :
4224 if ( bMatrixFormula )
4225 { // create matrix for {=A1:A5}
4226 PopDoubleRefPushMatrix();
4227 // no break, continue with svMatrix
4229 else
4231 ScRange aRange;
4232 PopDoubleRef( aRange );
4233 ScAddress aAdr;
4234 if ( !nGlobalError && DoubleRefToPosSingleRef( aRange, aAdr))
4235 PushCellResultToken( false, aAdr,
4236 &nRetTypeExpr, &nRetIndexExpr);
4237 break;
4240 // no break
4241 case svMatrix :
4243 ScMatrixRef xMat = PopMatrix();
4244 if (xMat)
4246 ScMatValType nMatValType;
4247 const ScMatrixValue* pMatVal = xMat->Get(0, 0, nMatValType);
4248 if ( pMatVal )
4250 if (ScMatrix::IsNonValueType( nMatValType))
4252 if ( xMat->IsEmptyPath( 0, 0))
4253 { // result of empty FALSE jump path
4254 FormulaTokenRef xRes = new FormulaDoubleToken( 0.0);
4255 PushTempToken( new ScMatrixCellResultToken( xMat, xRes));
4256 nRetTypeExpr = NUMBERFORMAT_LOGICAL;
4258 else
4260 String aStr( pMatVal->GetString());
4261 FormulaTokenRef xRes = new FormulaStringToken( aStr);
4262 PushTempToken( new ScMatrixCellResultToken( xMat, xRes));
4263 nRetTypeExpr = NUMBERFORMAT_TEXT;
4266 else
4268 USHORT nErr = GetDoubleErrorValue( pMatVal->fVal);
4269 FormulaTokenRef xRes;
4270 if (nErr)
4271 xRes = new FormulaErrorToken( nErr);
4272 else
4273 xRes = new FormulaDoubleToken( pMatVal->fVal);
4274 PushTempToken( new ScMatrixCellResultToken( xMat, xRes));
4275 if ( nRetTypeExpr != NUMBERFORMAT_LOGICAL )
4276 nRetTypeExpr = NUMBERFORMAT_NUMBER;
4278 nRetIndexExpr = 0;
4280 else
4281 SetError( errUnknownStackVariable);
4282 xMat->SetErrorInterpreter( NULL);
4284 else
4285 SetError( errUnknownStackVariable);
4287 break;
4288 default :
4289 SetError( errUnknownStackVariable);
4292 else
4293 SetError( errUnknownStackVariable);
4295 else
4296 SetError( errNoCode);
4298 if( nRetTypeExpr != NUMBERFORMAT_UNDEFINED )
4300 nRetFmtType = nRetTypeExpr;
4301 nRetFmtIndex = nRetIndexExpr;
4303 else if( nFuncFmtType != NUMBERFORMAT_UNDEFINED )
4305 nRetFmtType = nFuncFmtType;
4306 nRetFmtIndex = nFuncFmtIndex;
4308 else
4309 nRetFmtType = NUMBERFORMAT_NUMBER;
4310 // inherit the format index only for currency formats
4311 if ( nRetFmtType != NUMBERFORMAT_CURRENCY )
4312 nRetFmtIndex = 0;
4314 if (nGlobalError && GetStackType() != svError )
4315 PushError( nGlobalError);
4317 // THE final result.
4318 xResult = PopToken();
4319 if (!xResult)
4320 xResult = new FormulaErrorToken( errUnknownStackVariable);
4322 // release tokens in expression stack
4323 FormulaToken** p = pStack;
4324 while( maxsp-- )
4325 (*p++)->DecRef();
4327 return xResult->GetType();