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