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