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