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