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