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