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 31 32 33 // INCLUDE --------------------------------------------------------------- 34 35 #if STLPORT_VERSION<321 36 #include <stddef.h> 37 #else 38 #include <cstddef> 39 #endif 40 #include <cstdio> 41 42 #include <string.h> 43 #include <tools/mempool.hxx> 44 #include <tools/debug.hxx> 45 46 #include "token.hxx" 47 #include "tokenarray.hxx" 48 #include "compiler.hxx" 49 #include <formula/compiler.hrc> 50 #include "rechead.hxx" 51 #include "parclass.hxx" 52 #include "jumpmatrix.hxx" 53 #include "rangeseq.hxx" 54 #include "externalrefmgr.hxx" 55 #include "document.hxx" 56 57 using ::std::vector; 58 59 #include <com/sun/star/sheet/ComplexReference.hpp> 60 #include <com/sun/star/sheet/ExternalReference.hpp> 61 #include <com/sun/star/sheet/ReferenceFlags.hpp> 62 63 using namespace formula; 64 using namespace com::sun::star; 65 66 namespace 67 { 68 void lcl_SingleRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI ) 69 { 70 rRef.InitFlags(); 71 72 rRef.nCol = static_cast<SCsCOL>(rAPI.Column); 73 rRef.nRow = static_cast<SCsROW>(rAPI.Row); 74 rRef.nTab = static_cast<SCsTAB>(rAPI.Sheet); 75 rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn); 76 rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow); 77 rRef.nRelTab = static_cast<SCsTAB>(rAPI.RelativeSheet); 78 79 rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 ); 80 rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 ); 81 rRef.SetTabRel( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_RELATIVE ) != 0 ); 82 rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 ); 83 rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 ); 84 rRef.SetTabDeleted( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_DELETED ) != 0 ); 85 rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 ); 86 rRef.SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 ); 87 } 88 89 void lcl_ExternalRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI ) 90 { 91 rRef.InitFlags(); 92 93 rRef.nCol = static_cast<SCsCOL>(rAPI.Column); 94 rRef.nRow = static_cast<SCsROW>(rAPI.Row); 95 rRef.nTab = 0; 96 rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn); 97 rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow); 98 rRef.nRelTab = 0; 99 100 rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 ); 101 rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 ); 102 rRef.SetTabRel( false ); // sheet index must be absolute for external refs 103 rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 ); 104 rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 ); 105 rRef.SetTabDeleted( false ); // sheet must not be deleted for external refs 106 rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 ); 107 rRef.SetRelName( false ); 108 } 109 // 110 } // namespace 111 // 112 // ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch 113 // SubCode via FormulaTokenIterator Push/Pop moeglich 114 IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 ) 115 116 // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2) 117 118 // Since RawTokens are temporary for the compiler, don't align on 4k and waste memory. 119 // ScRawToken size is FixMembers + MAXSTRLEN + ~4 ~= 1036 120 IMPL_FIXEDMEMPOOL_NEWDEL( ScRawToken, 8, 4 ) 121 // Some ScDoubleRawToken, FixMembers + sizeof(double) ~= 16 122 const sal_uInt16 nMemPoolDoubleRawToken = 0x0400 / sizeof(ScDoubleRawToken); 123 IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken, nMemPoolDoubleRawToken, nMemPoolDoubleRawToken ) 124 125 // Need a whole bunch of ScSingleRefToken 126 const sal_uInt16 nMemPoolSingleRefToken = (0x4000 - 64) / sizeof(ScSingleRefToken); 127 IMPL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken, nMemPoolSingleRefToken, nMemPoolSingleRefToken ) 128 // Need quite a lot of ScDoubleRefToken 129 const sal_uInt16 nMemPoolDoubleRefToken = (0x2000 - 64) / sizeof(ScDoubleRefToken); 130 IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken, nMemPoolDoubleRefToken, nMemPoolDoubleRefToken ) 131 132 // --- helpers -------------------------------------------------------------- 133 134 inline sal_Bool lcl_IsReference( OpCode eOp, StackVar eType ) 135 { 136 return 137 (eOp == ocPush && (eType == svSingleRef || eType == svDoubleRef)) 138 || (eOp == ocColRowNameAuto && eType == svDoubleRef) 139 || (eOp == ocColRowName && eType == svSingleRef) 140 || (eOp == ocMatRef && eType == svSingleRef) 141 ; 142 } 143 144 145 // --- class ScRawToken ----------------------------------------------------- 146 147 xub_StrLen ScRawToken::GetStrLen( const sal_Unicode* pStr ) 148 { 149 if ( !pStr ) 150 return 0; 151 register const sal_Unicode* p = pStr; 152 while ( *p ) 153 p++; 154 return sal::static_int_cast<xub_StrLen>( p - pStr ); 155 } 156 157 158 void ScRawToken::SetOpCode( OpCode e ) 159 { 160 eOp = e; 161 switch (eOp) 162 { 163 case ocIf: 164 eType = svJump; 165 nJump[ 0 ] = 3; // If, Else, Behind 166 break; 167 case ocChose: 168 eType = svJump; 169 nJump[ 0 ] = MAXJUMPCOUNT+1; 170 break; 171 case ocMissing: 172 eType = svMissing; 173 break; 174 case ocSep: 175 case ocOpen: 176 case ocClose: 177 case ocArrayRowSep: 178 case ocArrayColSep: 179 case ocArrayOpen: 180 case ocArrayClose: 181 eType = svSep; 182 break; 183 default: 184 eType = svByte; 185 sbyte.cByte = 0; 186 sbyte.bHasForceArray = ScParameterClassification::HasForceArray( eOp); 187 } 188 nRefCnt = 0; 189 } 190 191 void ScRawToken::SetString( const sal_Unicode* pStr ) 192 { 193 eOp = ocPush; 194 eType = svString; 195 if ( pStr ) 196 { 197 xub_StrLen nLen = GetStrLen( pStr ) + 1; 198 if( nLen > MAXSTRLEN ) 199 nLen = MAXSTRLEN; 200 memcpy( cStr, pStr, GetStrLenBytes( nLen ) ); 201 cStr[ nLen-1 ] = 0; 202 } 203 else 204 cStr[0] = 0; 205 nRefCnt = 0; 206 } 207 208 void ScRawToken::SetSingleReference( const ScSingleRefData& rRef ) 209 { 210 eOp = ocPush; 211 eType = svSingleRef; 212 aRef.Ref1 = 213 aRef.Ref2 = rRef; 214 nRefCnt = 0; 215 } 216 217 void ScRawToken::SetDoubleReference( const ScComplexRefData& rRef ) 218 { 219 eOp = ocPush; 220 eType = svDoubleRef; 221 aRef = rRef; 222 nRefCnt = 0; 223 } 224 225 void ScRawToken::SetDouble(double rVal) 226 { 227 eOp = ocPush; 228 eType = svDouble; 229 nValue = rVal; 230 nRefCnt = 0; 231 } 232 233 void ScRawToken::SetName( sal_uInt16 n ) 234 { 235 eOp = ocName; 236 eType = svIndex; 237 nIndex = n; 238 nRefCnt = 0; 239 } 240 241 void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef ) 242 { 243 eOp = ocExternalRef; 244 eType = svExternalSingleRef; 245 nRefCnt = 0; 246 247 extref.nFileId = nFileId; 248 extref.aRef.Ref1 = 249 extref.aRef.Ref2 = rRef; 250 251 xub_StrLen n = rTabName.Len(); 252 memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode)); 253 extref.cTabName[n] = 0; 254 } 255 256 void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef ) 257 { 258 eOp = ocExternalRef; 259 eType = svExternalDoubleRef; 260 nRefCnt = 0; 261 262 extref.nFileId = nFileId; 263 extref.aRef = rRef; 264 265 xub_StrLen n = rTabName.Len(); 266 memcpy(extref.cTabName, rTabName.GetBuffer(), n*sizeof(sal_Unicode)); 267 extref.cTabName[n] = 0; 268 } 269 270 void ScRawToken::SetExternalName( sal_uInt16 nFileId, const String& rName ) 271 { 272 eOp = ocExternalRef; 273 eType = svExternalName; 274 nRefCnt = 0; 275 276 extname.nFileId = nFileId; 277 278 xub_StrLen n = rName.Len(); 279 memcpy(extname.cName, rName.GetBuffer(), n*sizeof(sal_Unicode)); 280 extname.cName[n] = 0; 281 } 282 283 //UNUSED2008-05 void ScRawToken::SetInt(int rVal) 284 //UNUSED2008-05 { 285 //UNUSED2008-05 eOp = ocPush; 286 //UNUSED2008-05 eType = svDouble; 287 //UNUSED2008-05 nValue = (double)rVal; 288 //UNUSED2008-05 nRefCnt = 0; 289 //UNUSED2008-05 290 //UNUSED2008-05 } 291 //UNUSED2008-05 void ScRawToken::SetMatrix( ScMatrix* p ) 292 //UNUSED2008-05 { 293 //UNUSED2008-05 eOp = ocPush; 294 //UNUSED2008-05 eType = svMatrix; 295 //UNUSED2008-05 pMat = p; 296 //UNUSED2008-05 nRefCnt = 0; 297 //UNUSED2008-05 } 298 //UNUSED2008-05 299 //UNUSED2008-05 ScComplexRefData& ScRawToken::GetReference() 300 //UNUSED2008-05 { 301 //UNUSED2008-05 DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "GetReference: no Ref" ); 302 //UNUSED2008-05 return aRef; 303 //UNUSED2008-05 } 304 //UNUSED2008-05 305 //UNUSED2008-05 void ScRawToken::SetReference( ScComplexRefData& rRef ) 306 //UNUSED2008-05 { 307 //UNUSED2008-05 DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "SetReference: no Ref" ); 308 //UNUSED2008-05 aRef = rRef; 309 //UNUSED2008-05 if( GetType() == svSingleRef ) 310 //UNUSED2008-05 aRef.Ref2 = aRef.Ref1; 311 //UNUSED2008-05 } 312 313 void ScRawToken::SetExternal( const sal_Unicode* pStr ) 314 { 315 eOp = ocExternal; 316 eType = svExternal; 317 xub_StrLen nLen = GetStrLen( pStr ) + 1; 318 if( nLen >= MAXSTRLEN ) 319 nLen = MAXSTRLEN-1; 320 // Platz fuer Byte-Parameter lassen! 321 memcpy( cStr+1, pStr, GetStrLenBytes( nLen ) ); 322 cStr[ nLen+1 ] = 0; 323 nRefCnt = 0; 324 } 325 326 sal_uInt16 lcl_ScRawTokenOffset() 327 { 328 // offset of sbyte in ScRawToken 329 // offsetof(ScRawToken, sbyte) gives a warning with gcc, because ScRawToken is no POD 330 331 ScRawToken aToken; 332 return static_cast<sal_uInt16>( reinterpret_cast<char*>(&aToken.sbyte) - reinterpret_cast<char*>(&aToken) ); 333 } 334 335 ScRawToken* ScRawToken::Clone() const 336 { 337 ScRawToken* p; 338 if ( eType == svDouble ) 339 { 340 p = (ScRawToken*) new ScDoubleRawToken; 341 p->eOp = eOp; 342 p->eType = eType; 343 p->nValue = nValue; 344 } 345 else 346 { 347 static sal_uInt16 nOffset = lcl_ScRawTokenOffset(); // offset of sbyte 348 sal_uInt16 n = nOffset; 349 350 if (eOp == ocExternalRef) 351 { 352 switch (eType) 353 { 354 case svExternalSingleRef: 355 case svExternalDoubleRef: n += sizeof(extref); break; 356 case svExternalName: n += sizeof(extname); break; 357 default: 358 { 359 DBG_ERROR1( "unknown ScRawToken::Clone() external type %d", int(eType)); 360 } 361 } 362 } 363 else 364 { 365 switch( eType ) 366 { 367 case svSep: break; 368 case svByte: n += sizeof(ScRawToken::sbyte); break; 369 case svDouble: n += sizeof(double); break; 370 case svString: n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr ) + GetStrLenBytes( 1 ) ); break; 371 case svSingleRef: 372 case svDoubleRef: n += sizeof(aRef); break; 373 case svMatrix: n += sizeof(ScMatrix*); break; 374 case svIndex: n += sizeof(sal_uInt16); break; 375 case svJump: n += nJump[ 0 ] * 2 + 2; break; 376 case svExternal: n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break; 377 default: 378 { 379 DBG_ERROR1( "unknown ScRawToken::Clone() type %d", int(eType)); 380 } 381 } 382 } 383 p = (ScRawToken*) new sal_uInt8[ n ]; 384 memcpy( p, this, n * sizeof(sal_uInt8) ); 385 } 386 p->nRefCnt = 0; 387 p->bRaw = sal_False; 388 return p; 389 } 390 391 392 FormulaToken* ScRawToken::CreateToken() const 393 { 394 #ifdef DBG_UTIL 395 #define IF_NOT_OPCODE_ERROR(o,c) if (eOp!=o) DBG_ERROR1( #c "::ctor: OpCode %d lost, converted to " #o "; maybe inherit from FormulaToken instead!", int(eOp)) 396 #else 397 #define IF_NOT_OPCODE_ERROR(o,c) 398 #endif 399 switch ( GetType() ) 400 { 401 case svByte : 402 return new FormulaByteToken( eOp, sbyte.cByte, sbyte.bHasForceArray ); 403 case svDouble : 404 IF_NOT_OPCODE_ERROR( ocPush, FormulaDoubleToken); 405 return new FormulaDoubleToken( nValue ); 406 case svString : 407 if (eOp == ocPush) 408 return new FormulaStringToken( String( cStr ) ); 409 else 410 return new FormulaStringOpToken( eOp, String( cStr ) ); 411 case svSingleRef : 412 if (eOp == ocPush) 413 return new ScSingleRefToken( aRef.Ref1 ); 414 else 415 return new ScSingleRefToken( aRef.Ref1, eOp ); 416 case svDoubleRef : 417 if (eOp == ocPush) 418 return new ScDoubleRefToken( aRef ); 419 else 420 return new ScDoubleRefToken( aRef, eOp ); 421 case svMatrix : 422 IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken); 423 return new ScMatrixToken( pMat ); 424 case svIndex : 425 return new FormulaIndexToken( eOp, nIndex ); 426 case svExternalSingleRef: 427 { 428 String aTabName(extref.cTabName); 429 return new ScExternalSingleRefToken(extref.nFileId, aTabName, extref.aRef.Ref1); 430 } 431 case svExternalDoubleRef: 432 { 433 String aTabName(extref.cTabName); 434 return new ScExternalDoubleRefToken(extref.nFileId, aTabName, extref.aRef); 435 } 436 case svExternalName: 437 { 438 String aName(extname.cName); 439 return new ScExternalNameToken( extname.nFileId, aName ); 440 } 441 case svJump : 442 return new FormulaJumpToken( eOp, (short*) nJump ); 443 case svExternal : 444 return new FormulaExternalToken( eOp, sbyte.cByte, String( cStr+1 ) ); 445 case svFAP : 446 return new FormulaFAPToken( eOp, sbyte.cByte, NULL ); 447 case svMissing : 448 IF_NOT_OPCODE_ERROR( ocMissing, FormulaMissingToken); 449 return new FormulaMissingToken; 450 case svSep : 451 return new FormulaToken( svSep,eOp ); 452 case svUnknown : 453 return new FormulaUnknownToken( eOp ); 454 default: 455 { 456 DBG_ERROR1( "unknown ScRawToken::CreateToken() type %d", int(GetType())); 457 return new FormulaUnknownToken( ocBad ); 458 } 459 } 460 #undef IF_NOT_OPCODE_ERROR 461 } 462 463 464 void ScRawToken::Delete() 465 { 466 if ( bRaw ) 467 delete this; // FixedMemPool ScRawToken 468 else 469 { // created per Clone 470 switch ( eType ) 471 { 472 case svDouble : 473 delete (ScDoubleRawToken*) this; // FixedMemPool ScDoubleRawToken 474 break; 475 default: 476 delete [] (sal_uInt8*) this; 477 } 478 } 479 } 480 481 482 // --- class ScToken -------------------------------------------------------- 483 484 ScSingleRefData lcl_ScToken_InitSingleRef() 485 { 486 ScSingleRefData aRef; 487 aRef.InitAddress( ScAddress() ); 488 return aRef; 489 } 490 491 ScComplexRefData lcl_ScToken_InitDoubleRef() 492 { 493 ScComplexRefData aRef; 494 aRef.Ref1 = lcl_ScToken_InitSingleRef(); 495 aRef.Ref2 = aRef.Ref1; 496 return aRef; 497 } 498 499 ScToken::~ScToken() 500 { 501 } 502 503 // TextEqual: if same formula entered (for optimization in sort) 504 sal_Bool ScToken::TextEqual( const FormulaToken& _rToken ) const 505 { 506 if ( eType == svSingleRef || eType == svDoubleRef ) 507 { 508 // in relative Refs only compare relative parts 509 510 if ( eType != _rToken.GetType() || GetOpCode() != _rToken.GetOpCode() ) 511 return sal_False; 512 513 const ScToken& rToken = static_cast<const ScToken&>(_rToken); 514 ScComplexRefData aTemp1; 515 if ( eType == svSingleRef ) 516 { 517 aTemp1.Ref1 = GetSingleRef(); 518 aTemp1.Ref2 = aTemp1.Ref1; 519 } 520 else 521 aTemp1 = GetDoubleRef(); 522 523 ScComplexRefData aTemp2; 524 if ( rToken.eType == svSingleRef ) 525 { 526 aTemp2.Ref1 = rToken.GetSingleRef(); 527 aTemp2.Ref2 = aTemp2.Ref1; 528 } 529 else 530 aTemp2 = rToken.GetDoubleRef(); 531 532 ScAddress aPos; 533 aTemp1.SmartRelAbs(aPos); 534 aTemp2.SmartRelAbs(aPos); 535 536 // memcmp doesn't work because of the alignment byte after bFlags. 537 // After SmartRelAbs only absolute parts have to be compared. 538 return aTemp1.Ref1.nCol == aTemp2.Ref1.nCol && 539 aTemp1.Ref1.nRow == aTemp2.Ref1.nRow && 540 aTemp1.Ref1.nTab == aTemp2.Ref1.nTab && 541 aTemp1.Ref1.bFlags == aTemp2.Ref1.bFlags && 542 aTemp1.Ref2.nCol == aTemp2.Ref2.nCol && 543 aTemp1.Ref2.nRow == aTemp2.Ref2.nRow && 544 aTemp1.Ref2.nTab == aTemp2.Ref2.nTab && 545 aTemp1.Ref2.bFlags == aTemp2.Ref2.bFlags; 546 } 547 else 548 return *this == _rToken; // else normal operator== 549 } 550 551 552 sal_Bool ScToken::Is3DRef() const 553 { 554 switch ( eType ) 555 { 556 case svDoubleRef : 557 if ( GetSingleRef2().IsFlag3D() ) 558 return sal_True; 559 //! fallthru 560 case svSingleRef : 561 if ( GetSingleRef().IsFlag3D() ) 562 return sal_True; 563 break; 564 case svExternalSingleRef: 565 case svExternalDoubleRef: 566 return sal_True; 567 default: 568 { 569 // added to avoid warnings 570 } 571 } 572 return sal_False; 573 } 574 575 // static 576 FormulaTokenRef ScToken::ExtendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2, 577 const ScAddress & rPos, bool bReuseDoubleRef ) 578 { 579 580 StackVar sv1, sv2; 581 // Doing a RangeOp with RefList is probably utter nonsense, but Xcl 582 // supports it, so do we. 583 if (((sv1 = rTok1.GetType()) != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList && 584 sv1 != svExternalSingleRef && sv1 != svExternalDoubleRef ) || 585 ((sv2 = rTok2.GetType()) != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList)) 586 return NULL; 587 588 ScToken *p1 = static_cast<ScToken*>(&rTok1); 589 ScToken *p2 = static_cast<ScToken*>(&rTok2); 590 591 ScTokenRef xRes; 592 bool bExternal = (sv1 == svExternalSingleRef); 593 if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef) 594 { 595 // Range references like Sheet1.A1:A2 are generalized and built by 596 // first creating a DoubleRef from the first SingleRef, effectively 597 // generating Sheet1.A1:A1, and then extending that with A2 as if 598 // Sheet1.A1:A1:A2 was encountered, so the mechanisms to adjust the 599 // references apply as well. 600 601 /* Given the current structure of external references an external 602 * reference can only be extended if the second reference does not 603 * point to a different sheet. 'file'#Sheet1.A1:A2 is ok, 604 * 'file'#Sheet1.A1:Sheet2.A2 is not. Since we can't determine from a 605 * svSingleRef whether the sheet would be different from the one given 606 * in the external reference, we have to bail out if there is any sheet 607 * specified. NOTE: Xcl does handle external 3D references as in 608 * '[file]Sheet1:Sheet2'!A1:A2 609 * 610 * FIXME: For OOo syntax be smart and remember an external singleref 611 * encountered and if followed by ocRange and singleref, create an 612 * external singleref for the second singleref. Both could then be 613 * merged here. For Xcl syntax already parse an external range 614 * reference entirely, cumbersome. */ 615 616 const ScSingleRefData& rRef2 = p2->GetSingleRef(); 617 if (bExternal && rRef2.IsFlag3D()) 618 return NULL; 619 620 ScComplexRefData aRef; 621 aRef.Ref1 = aRef.Ref2 = p1->GetSingleRef(); 622 aRef.Ref2.SetFlag3D( false); 623 aRef.Extend( rRef2, rPos); 624 if (bExternal) 625 xRes = new ScExternalDoubleRefToken( p1->GetIndex(), p1->GetString(), aRef); 626 else 627 xRes = new ScDoubleRefToken( aRef); 628 } 629 else 630 { 631 bExternal |= (sv1 == svExternalDoubleRef); 632 const ScRefList* pRefList = NULL; 633 if (sv1 == svDoubleRef) 634 { 635 xRes = (bReuseDoubleRef && p1->GetRef() == 1 ? p1 : static_cast<ScToken*>(p1->Clone())); 636 sv1 = svUnknown; // mark as handled 637 } 638 else if (sv2 == svDoubleRef) 639 { 640 xRes = (bReuseDoubleRef && p2->GetRef() == 1 ? p2 : static_cast<ScToken*>(p2->Clone())); 641 sv2 = svUnknown; // mark as handled 642 } 643 else if (sv1 == svRefList) 644 pRefList = p1->GetRefList(); 645 else if (sv2 == svRefList) 646 pRefList = p2->GetRefList(); 647 if (pRefList) 648 { 649 if (!pRefList->size()) 650 return NULL; 651 if (bExternal) 652 return NULL; // external reference list not possible 653 xRes = new ScDoubleRefToken( (*pRefList)[0] ); 654 } 655 if (!xRes) 656 return NULL; // shouldn't happen.. 657 StackVar sv[2] = { sv1, sv2 }; 658 ScToken* pt[2] = { p1, p2 }; 659 ScComplexRefData& rRef = xRes->GetDoubleRef(); 660 for (size_t i=0; i<2; ++i) 661 { 662 switch (sv[i]) 663 { 664 case svSingleRef: 665 rRef.Extend( pt[i]->GetSingleRef(), rPos); 666 break; 667 case svDoubleRef: 668 rRef.Extend( pt[i]->GetDoubleRef(), rPos); 669 break; 670 case svRefList: 671 { 672 const ScRefList* p = pt[i]->GetRefList(); 673 if (!p->size()) 674 return NULL; 675 ScRefList::const_iterator it( p->begin()); 676 ScRefList::const_iterator end( p->end()); 677 for ( ; it != end; ++it) 678 { 679 rRef.Extend( *it, rPos); 680 } 681 } 682 break; 683 case svExternalSingleRef: 684 if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D()) 685 return NULL; // no other sheets with external refs 686 else 687 rRef.Extend( pt[i]->GetSingleRef(), rPos); 688 break; 689 case svExternalDoubleRef: 690 if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D()) 691 return NULL; // no other sheets with external refs 692 else 693 rRef.Extend( pt[i]->GetDoubleRef(), rPos); 694 break; 695 default: 696 ; // nothing, prevent compiler warning 697 } 698 } 699 } 700 return FormulaTokenRef(xRes.get()); 701 } 702 703 const ScSingleRefData& ScToken::GetSingleRef() const 704 { 705 DBG_ERRORFILE( "ScToken::GetSingleRef: virtual dummy called" ); 706 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef(); 707 return aDummySingleRef; 708 } 709 710 ScSingleRefData& ScToken::GetSingleRef() 711 { 712 DBG_ERRORFILE( "ScToken::GetSingleRef: virtual dummy called" ); 713 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef(); 714 return aDummySingleRef; 715 } 716 717 const ScComplexRefData& ScToken::GetDoubleRef() const 718 { 719 DBG_ERRORFILE( "ScToken::GetDoubleRef: virtual dummy called" ); 720 static ScComplexRefData aDummyDoubleRef = lcl_ScToken_InitDoubleRef(); 721 return aDummyDoubleRef; 722 } 723 724 ScComplexRefData& ScToken::GetDoubleRef() 725 { 726 DBG_ERRORFILE( "ScToken::GetDoubleRef: virtual dummy called" ); 727 static ScComplexRefData aDummyDoubleRef = lcl_ScToken_InitDoubleRef(); 728 return aDummyDoubleRef; 729 } 730 731 const ScSingleRefData& ScToken::GetSingleRef2() const 732 { 733 DBG_ERRORFILE( "ScToken::GetSingleRef2: virtual dummy called" ); 734 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef(); 735 return aDummySingleRef; 736 } 737 738 ScSingleRefData& ScToken::GetSingleRef2() 739 { 740 DBG_ERRORFILE( "ScToken::GetSingleRef2: virtual dummy called" ); 741 static ScSingleRefData aDummySingleRef = lcl_ScToken_InitSingleRef(); 742 return aDummySingleRef; 743 } 744 745 void ScToken::CalcAbsIfRel( const ScAddress& /* rPos */ ) 746 { 747 DBG_ERRORFILE( "ScToken::CalcAbsIfRel: virtual dummy called" ); 748 } 749 750 void ScToken::CalcRelFromAbs( const ScAddress& /* rPos */ ) 751 { 752 DBG_ERRORFILE( "ScToken::CalcRelFromAbs: virtual dummy called" ); 753 } 754 755 const ScMatrix* ScToken::GetMatrix() const 756 { 757 DBG_ERRORFILE( "ScToken::GetMatrix: virtual dummy called" ); 758 return NULL; 759 } 760 761 ScMatrix* ScToken::GetMatrix() 762 { 763 DBG_ERRORFILE( "ScToken::GetMatrix: virtual dummy called" ); 764 return NULL; 765 } 766 767 768 ScJumpMatrix* ScToken::GetJumpMatrix() const 769 { 770 DBG_ERRORFILE( "ScToken::GetJumpMatrix: virtual dummy called" ); 771 return NULL; 772 } 773 const ScRefList* ScToken::GetRefList() const 774 { 775 DBG_ERRORFILE( "ScToken::GetRefList: virtual dummy called" ); 776 return NULL; 777 } 778 779 ScRefList* ScToken::GetRefList() 780 { 781 DBG_ERRORFILE( "ScToken::GetRefList: virtual dummy called" ); 782 return NULL; 783 } 784 // ========================================================================== 785 // real implementations of virtual functions 786 // -------------------------------------------------------------------------- 787 788 789 790 791 const ScSingleRefData& ScSingleRefToken::GetSingleRef() const { return aSingleRef; } 792 ScSingleRefData& ScSingleRefToken::GetSingleRef() { return aSingleRef; } 793 void ScSingleRefToken::CalcAbsIfRel( const ScAddress& rPos ) 794 { aSingleRef.CalcAbsIfRel( rPos ); } 795 void ScSingleRefToken::CalcRelFromAbs( const ScAddress& rPos ) 796 { aSingleRef.CalcRelFromAbs( rPos ); } 797 sal_Bool ScSingleRefToken::operator==( const FormulaToken& r ) const 798 { 799 return FormulaToken::operator==( r ) && aSingleRef == static_cast<const ScToken&>(r).GetSingleRef(); 800 } 801 802 803 const ScSingleRefData& ScDoubleRefToken::GetSingleRef() const { return aDoubleRef.Ref1; } 804 ScSingleRefData& ScDoubleRefToken::GetSingleRef() { return aDoubleRef.Ref1; } 805 const ScComplexRefData& ScDoubleRefToken::GetDoubleRef() const { return aDoubleRef; } 806 ScComplexRefData& ScDoubleRefToken::GetDoubleRef() { return aDoubleRef; } 807 const ScSingleRefData& ScDoubleRefToken::GetSingleRef2() const { return aDoubleRef.Ref2; } 808 ScSingleRefData& ScDoubleRefToken::GetSingleRef2() { return aDoubleRef.Ref2; } 809 void ScDoubleRefToken::CalcAbsIfRel( const ScAddress& rPos ) 810 { aDoubleRef.CalcAbsIfRel( rPos ); } 811 void ScDoubleRefToken::CalcRelFromAbs( const ScAddress& rPos ) 812 { aDoubleRef.CalcRelFromAbs( rPos ); } 813 sal_Bool ScDoubleRefToken::operator==( const FormulaToken& r ) const 814 { 815 return FormulaToken::operator==( r ) && aDoubleRef == static_cast<const ScToken&>(r).GetDoubleRef(); 816 } 817 818 819 const ScRefList* ScRefListToken::GetRefList() const { return &aRefList; } 820 ScRefList* ScRefListToken::GetRefList() { return &aRefList; } 821 void ScRefListToken::CalcAbsIfRel( const ScAddress& rPos ) 822 { 823 for (ScRefList::iterator it( aRefList.begin()); it != aRefList.end(); ++it) 824 (*it).CalcAbsIfRel( rPos); 825 } 826 void ScRefListToken::CalcRelFromAbs( const ScAddress& rPos ) 827 { 828 for (ScRefList::iterator it( aRefList.begin()); it != aRefList.end(); ++it) 829 (*it).CalcRelFromAbs( rPos); 830 } 831 sal_Bool ScRefListToken::operator==( const FormulaToken& r ) const 832 { 833 return FormulaToken::operator==( r ) && &aRefList == static_cast<const ScToken&>(r).GetRefList(); 834 } 835 836 837 const ScMatrix* ScMatrixToken::GetMatrix() const { return pMatrix; } 838 ScMatrix* ScMatrixToken::GetMatrix() { return pMatrix; } 839 sal_Bool ScMatrixToken::operator==( const FormulaToken& r ) const 840 { 841 return FormulaToken::operator==( r ) && pMatrix == static_cast<const ScToken&>(r).GetMatrix(); 842 } 843 844 // ============================================================================ 845 846 ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ) : 847 ScToken( svExternalSingleRef, ocExternalRef), 848 mnFileId(nFileId), 849 maTabName(rTabName), 850 maSingleRef(r) 851 { 852 } 853 854 ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) : 855 ScToken(r), 856 mnFileId(r.mnFileId), 857 maTabName(r.maTabName), 858 maSingleRef(r.maSingleRef) 859 { 860 } 861 862 ScExternalSingleRefToken::~ScExternalSingleRefToken() 863 { 864 } 865 866 sal_uInt16 ScExternalSingleRefToken::GetIndex() const 867 { 868 return mnFileId; 869 } 870 871 const String& ScExternalSingleRefToken::GetString() const 872 { 873 return maTabName; 874 } 875 876 const ScSingleRefData& ScExternalSingleRefToken::GetSingleRef() const 877 { 878 return maSingleRef; 879 } 880 881 ScSingleRefData& ScExternalSingleRefToken::GetSingleRef() 882 { 883 return maSingleRef; 884 } 885 886 void ScExternalSingleRefToken::CalcAbsIfRel( const ScAddress& rPos ) 887 { 888 maSingleRef.CalcAbsIfRel( rPos ); 889 } 890 891 void ScExternalSingleRefToken::CalcRelFromAbs( const ScAddress& rPos ) 892 { 893 maSingleRef.CalcRelFromAbs( rPos ); 894 } 895 896 sal_Bool ScExternalSingleRefToken::operator ==( const FormulaToken& r ) const 897 { 898 if (!FormulaToken::operator==(r)) 899 return false; 900 901 if (mnFileId != r.GetIndex()) 902 return false; 903 904 if (maTabName != r.GetString()) 905 return false; 906 907 return maSingleRef == static_cast<const ScToken&>(r).GetSingleRef(); 908 } 909 910 // ============================================================================ 911 912 ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& r ) : 913 ScToken( svExternalDoubleRef, ocExternalRef), 914 mnFileId(nFileId), 915 maTabName(rTabName), 916 maDoubleRef(r) 917 { 918 } 919 920 ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) : 921 ScToken(r), 922 mnFileId(r.mnFileId), 923 maTabName(r.maTabName), 924 maDoubleRef(r.maDoubleRef) 925 { 926 } 927 928 ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalSingleRefToken& r ) : 929 ScToken( svExternalDoubleRef, ocExternalRef), 930 mnFileId( r.GetIndex()), 931 maTabName( r.GetString()) 932 { 933 maDoubleRef.Ref1 = maDoubleRef.Ref2 = r.GetSingleRef(); 934 } 935 936 ScExternalDoubleRefToken::~ScExternalDoubleRefToken() 937 { 938 } 939 940 sal_uInt16 ScExternalDoubleRefToken::GetIndex() const 941 { 942 return mnFileId; 943 } 944 945 const String& ScExternalDoubleRefToken::GetString() const 946 { 947 return maTabName; 948 } 949 950 const ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef() const 951 { 952 return maDoubleRef.Ref1; 953 } 954 955 ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef() 956 { 957 return maDoubleRef.Ref1; 958 } 959 960 const ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef2() const 961 { 962 return maDoubleRef.Ref2; 963 } 964 965 ScSingleRefData& ScExternalDoubleRefToken::GetSingleRef2() 966 { 967 return maDoubleRef.Ref2; 968 } 969 970 const ScComplexRefData& ScExternalDoubleRefToken::GetDoubleRef() const 971 { 972 return maDoubleRef; 973 } 974 975 ScComplexRefData& ScExternalDoubleRefToken::GetDoubleRef() 976 { 977 return maDoubleRef; 978 } 979 980 void ScExternalDoubleRefToken::CalcAbsIfRel( const ScAddress& rPos ) 981 { 982 maDoubleRef.CalcAbsIfRel( rPos ); 983 } 984 985 void ScExternalDoubleRefToken::CalcRelFromAbs( const ScAddress& rPos ) 986 { 987 maDoubleRef.CalcRelFromAbs( rPos ); 988 } 989 990 sal_Bool ScExternalDoubleRefToken::operator ==( const FormulaToken& r ) const 991 { 992 if (!ScToken::operator==(r)) 993 return false; 994 995 if (mnFileId != r.GetIndex()) 996 return false; 997 998 if (maTabName != r.GetString()) 999 return false; 1000 1001 return maDoubleRef == static_cast<const ScToken&>(r).GetDoubleRef(); 1002 } 1003 1004 // ============================================================================ 1005 1006 ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const String& rName ) : 1007 ScToken( svExternalName, ocExternalRef), 1008 mnFileId(nFileId), 1009 maName(rName) 1010 { 1011 } 1012 1013 ScExternalNameToken::ScExternalNameToken( const ScExternalNameToken& r ) : 1014 ScToken(r), 1015 mnFileId(r.mnFileId), 1016 maName(r.maName) 1017 { 1018 } 1019 1020 ScExternalNameToken::~ScExternalNameToken() {} 1021 1022 sal_uInt16 ScExternalNameToken::GetIndex() const 1023 { 1024 return mnFileId; 1025 } 1026 1027 const String& ScExternalNameToken::GetString() const 1028 { 1029 return maName; 1030 } 1031 1032 sal_Bool ScExternalNameToken::operator==( const FormulaToken& r ) const 1033 { 1034 if ( !FormulaToken::operator==(r) ) 1035 return false; 1036 1037 if (mnFileId != r.GetIndex()) 1038 return false; 1039 1040 xub_StrLen nLen = maName.Len(); 1041 const String& rName = r.GetString(); 1042 if (nLen != rName.Len()) 1043 return false; 1044 1045 const sal_Unicode* p1 = maName.GetBuffer(); 1046 const sal_Unicode* p2 = rName.GetBuffer(); 1047 for (xub_StrLen j = 0; j < nLen; ++j) 1048 { 1049 if (p1[j] != p2[j]) 1050 return false; 1051 } 1052 return true; 1053 } 1054 1055 // ============================================================================ 1056 1057 ScJumpMatrix* ScJumpMatrixToken::GetJumpMatrix() const { return pJumpMatrix; } 1058 sal_Bool ScJumpMatrixToken::operator==( const FormulaToken& r ) const 1059 { 1060 return FormulaToken::operator==( r ) && pJumpMatrix == static_cast<const ScToken&>(r).GetJumpMatrix(); 1061 } 1062 ScJumpMatrixToken::~ScJumpMatrixToken() 1063 { 1064 delete pJumpMatrix; 1065 } 1066 1067 double ScEmptyCellToken::GetDouble() const { return 0.0; } 1068 const String & ScEmptyCellToken::GetString() const 1069 { 1070 static String aDummyString; 1071 return aDummyString; 1072 } 1073 sal_Bool ScEmptyCellToken::operator==( const FormulaToken& r ) const 1074 { 1075 return FormulaToken::operator==( r ) && 1076 bInherited == static_cast< const ScEmptyCellToken & >(r).IsInherited() && 1077 bDisplayedAsString == static_cast< const ScEmptyCellToken & >(r).IsDisplayedAsString(); 1078 } 1079 1080 1081 double ScMatrixCellResultToken::GetDouble() const { return xUpperLeft->GetDouble(); } 1082 const String & ScMatrixCellResultToken::GetString() const { return xUpperLeft->GetString(); } 1083 const ScMatrix* ScMatrixCellResultToken::GetMatrix() const { return xMatrix; } 1084 // Non-const GetMatrix() is private and unused but must be implemented to 1085 // satisfy vtable linkage. 1086 ScMatrix* ScMatrixCellResultToken::GetMatrix() 1087 { 1088 return const_cast<ScMatrix*>(xMatrix.operator->()); 1089 } 1090 sal_Bool ScMatrixCellResultToken::operator==( const FormulaToken& r ) const 1091 { 1092 return FormulaToken::operator==( r ) && 1093 xUpperLeft == static_cast<const ScMatrixCellResultToken &>(r).xUpperLeft && 1094 xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix; 1095 } 1096 1097 1098 sal_Bool ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const 1099 { 1100 const ScMatrixFormulaCellToken* p = dynamic_cast<const ScMatrixFormulaCellToken*>(&r); 1101 return p && ScMatrixCellResultToken::operator==( r ) && 1102 nCols == p->nCols && nRows == p->nRows; 1103 } 1104 void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r ) 1105 { 1106 if (this == &r) 1107 return; 1108 const ScMatrixCellResultToken* p = dynamic_cast<const ScMatrixCellResultToken*>(&r); 1109 if (p) 1110 ScMatrixCellResultToken::Assign( *p); 1111 else 1112 { 1113 DBG_ASSERT( r.GetType() != svMatrix, "ScMatrixFormulaCellToken::operator=: assigning ScMatrixToken to ScMatrixFormulaCellToken is not proper, use ScMatrixCellResultToken instead"); 1114 if (r.GetType() == svMatrix) 1115 { 1116 xUpperLeft = NULL; 1117 xMatrix = static_cast<const ScToken&>(r).GetMatrix(); 1118 } 1119 else 1120 { 1121 xUpperLeft = &r; 1122 xMatrix = NULL; 1123 } 1124 } 1125 } 1126 void ScMatrixFormulaCellToken::SetUpperLeftDouble( double f ) 1127 { 1128 switch (GetUpperLeftType()) 1129 { 1130 case svDouble: 1131 const_cast<FormulaToken*>(xUpperLeft.get())->GetDoubleAsReference() = f; 1132 break; 1133 case svUnknown: 1134 if (!xUpperLeft) 1135 { 1136 xUpperLeft = new FormulaDoubleToken( f); 1137 break; 1138 } 1139 // fall thru 1140 default: 1141 { 1142 DBG_ERRORFILE("ScMatrixFormulaCellToken::SetUpperLeftDouble: not modifying unhandled token type"); 1143 } 1144 } 1145 } 1146 1147 1148 double ScHybridCellToken::GetDouble() const { return fDouble; } 1149 const String & ScHybridCellToken::GetString() const { return aString; } 1150 sal_Bool ScHybridCellToken::operator==( const FormulaToken& r ) const 1151 { 1152 return FormulaToken::operator==( r ) && 1153 fDouble == r.GetDouble() && aString == r.GetString() && 1154 aFormula == static_cast<const ScHybridCellToken &>(r).GetFormula(); 1155 } 1156 1157 1158 1159 1160 ////////////////////////////////////////////////////////////////////////// 1161 1162 bool ScTokenArray::AddFormulaToken(const com::sun::star::sheet::FormulaToken& _aToken,formula::ExternalReferenceHelper* _pRef) 1163 { 1164 bool bError = FormulaTokenArray::AddFormulaToken(_aToken,_pRef); 1165 if ( bError ) 1166 { 1167 bError = false; 1168 const OpCode eOpCode = static_cast<OpCode>(_aToken.OpCode); //! assuming equal values for the moment 1169 1170 const uno::TypeClass eClass = _aToken.Data.getValueTypeClass(); 1171 switch ( eClass ) 1172 { 1173 case uno::TypeClass_STRUCT: 1174 { 1175 uno::Type aType = _aToken.Data.getValueType(); 1176 if ( aType.equals( cppu::UnoType<sheet::SingleReference>::get() ) ) 1177 { 1178 ScSingleRefData aSingleRef; 1179 sheet::SingleReference aApiRef; 1180 _aToken.Data >>= aApiRef; 1181 lcl_SingleRefToCalc( aSingleRef, aApiRef ); 1182 if ( eOpCode == ocPush ) 1183 AddSingleReference( aSingleRef ); 1184 else if ( eOpCode == ocColRowName ) 1185 AddColRowName( aSingleRef ); 1186 else 1187 bError = true; 1188 } 1189 else if ( aType.equals( cppu::UnoType<sheet::ComplexReference>::get() ) ) 1190 { 1191 ScComplexRefData aComplRef; 1192 sheet::ComplexReference aApiRef; 1193 _aToken.Data >>= aApiRef; 1194 lcl_SingleRefToCalc( aComplRef.Ref1, aApiRef.Reference1 ); 1195 lcl_SingleRefToCalc( aComplRef.Ref2, aApiRef.Reference2 ); 1196 1197 if ( eOpCode == ocPush ) 1198 AddDoubleReference( aComplRef ); 1199 else 1200 bError = true; 1201 } 1202 else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) ) 1203 { 1204 sheet::ExternalReference aApiExtRef; 1205 if( (eOpCode == ocPush) && (_aToken.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) ) 1206 { 1207 sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index ); 1208 sheet::SingleReference aApiSRef; 1209 sheet::ComplexReference aApiCRef; 1210 ::rtl::OUString aName; 1211 if( aApiExtRef.Reference >>= aApiSRef ) 1212 { 1213 // try to resolve cache index to sheet name 1214 size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet ); 1215 String aTabName = _pRef->getCacheTableName( nFileId, nCacheId ); 1216 if( aTabName.Len() > 0 ) 1217 { 1218 ScSingleRefData aSingleRef; 1219 // convert column/row settings, set sheet index to absolute 1220 lcl_ExternalRefToCalc( aSingleRef, aApiSRef ); 1221 AddExternalSingleReference( nFileId, aTabName, aSingleRef ); 1222 } 1223 else 1224 bError = true; 1225 } 1226 else if( aApiExtRef.Reference >>= aApiCRef ) 1227 { 1228 // try to resolve cache index to sheet name. 1229 size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet ); 1230 String aTabName = _pRef->getCacheTableName( nFileId, nCacheId ); 1231 if( aTabName.Len() > 0 ) 1232 { 1233 ScComplexRefData aComplRef; 1234 // convert column/row settings, set sheet index to absolute 1235 lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 ); 1236 lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 ); 1237 // NOTE: This assumes that cached sheets are in consecutive order! 1238 aComplRef.Ref2.nTab = aComplRef.Ref1.nTab + static_cast<SCsTAB>(aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet); 1239 AddExternalDoubleReference( nFileId, aTabName, aComplRef ); 1240 } 1241 else 1242 bError = true; 1243 } 1244 else if( aApiExtRef.Reference >>= aName ) 1245 { 1246 if( aName.getLength() > 0 ) 1247 AddExternalName( nFileId, aName ); 1248 else 1249 bError = true; 1250 } 1251 else 1252 bError = true; 1253 } 1254 else 1255 bError = true; 1256 } 1257 else 1258 bError = true; // unknown struct 1259 } 1260 break; 1261 case uno::TypeClass_SEQUENCE: 1262 { 1263 if ( eOpCode != ocPush ) 1264 bError = true; // not an inline array 1265 else if (!_aToken.Data.getValueType().equals( getCppuType( 1266 (uno::Sequence< uno::Sequence< uno::Any > > *)0))) 1267 bError = true; // unexpected sequence type 1268 else 1269 { 1270 ScMatrixRef xMat = ScSequenceToMatrix::CreateMixedMatrix( _aToken.Data); 1271 if (xMat) 1272 AddMatrix( xMat); 1273 else 1274 bError = true; 1275 } 1276 } 1277 break; 1278 default: 1279 bError = true; 1280 } 1281 } 1282 return bError; 1283 } 1284 sal_Bool ScTokenArray::ImplGetReference( ScRange& rRange, sal_Bool bValidOnly ) const 1285 { 1286 sal_Bool bIs = sal_False; 1287 if ( pCode && nLen == 1 ) 1288 { 1289 const FormulaToken* pToken = pCode[0]; 1290 if ( pToken ) 1291 { 1292 if ( pToken->GetType() == svSingleRef ) 1293 { 1294 const ScSingleRefData& rRef = ((const ScSingleRefToken*)pToken)->GetSingleRef(); 1295 rRange.aStart = rRange.aEnd = ScAddress( rRef.nCol, rRef.nRow, rRef.nTab ); 1296 bIs = !bValidOnly || !rRef.IsDeleted(); 1297 } 1298 else if ( pToken->GetType() == svDoubleRef ) 1299 { 1300 const ScComplexRefData& rCompl = ((const ScDoubleRefToken*)pToken)->GetDoubleRef(); 1301 const ScSingleRefData& rRef1 = rCompl.Ref1; 1302 const ScSingleRefData& rRef2 = rCompl.Ref2; 1303 rRange.aStart = ScAddress( rRef1.nCol, rRef1.nRow, rRef1.nTab ); 1304 rRange.aEnd = ScAddress( rRef2.nCol, rRef2.nRow, rRef2.nTab ); 1305 bIs = !bValidOnly || (!rRef1.IsDeleted() && !rRef2.IsDeleted()); 1306 } 1307 } 1308 } 1309 return bIs; 1310 } 1311 1312 sal_Bool ScTokenArray::IsReference( ScRange& rRange ) const 1313 { 1314 return ImplGetReference( rRange, sal_False ); 1315 } 1316 1317 sal_Bool ScTokenArray::IsValidReference( ScRange& rRange ) const 1318 { 1319 return ImplGetReference( rRange, sal_True ); 1320 } 1321 1322 //////////////////////////////////////////////////////////////////////////// 1323 1324 ScTokenArray::ScTokenArray() 1325 { 1326 } 1327 1328 ScTokenArray::ScTokenArray( const ScTokenArray& rArr ) : FormulaTokenArray(rArr) 1329 { 1330 } 1331 1332 ScTokenArray::~ScTokenArray() 1333 { 1334 } 1335 1336 1337 1338 ScTokenArray& ScTokenArray::operator=( const ScTokenArray& rArr ) 1339 { 1340 Clear(); 1341 Assign( rArr ); 1342 return *this; 1343 } 1344 1345 ScTokenArray* ScTokenArray::Clone() const 1346 { 1347 ScTokenArray* p = new ScTokenArray(); 1348 p->nLen = nLen; 1349 p->nRPN = nRPN; 1350 p->nRefs = nRefs; 1351 p->nMode = nMode; 1352 p->nError = nError; 1353 p->bHyperLink = bHyperLink; 1354 FormulaToken** pp; 1355 if( nLen ) 1356 { 1357 pp = p->pCode = new FormulaToken*[ nLen ]; 1358 memcpy( pp, pCode, nLen * sizeof( ScToken* ) ); 1359 for( sal_uInt16 i = 0; i < nLen; i++, pp++ ) 1360 { 1361 *pp = (*pp)->Clone(); 1362 (*pp)->IncRef(); 1363 } 1364 } 1365 if( nRPN ) 1366 { 1367 pp = p->pRPN = new FormulaToken*[ nRPN ]; 1368 memcpy( pp, pRPN, nRPN * sizeof( ScToken* ) ); 1369 for( sal_uInt16 i = 0; i < nRPN; i++, pp++ ) 1370 { 1371 FormulaToken* t = *pp; 1372 if( t->GetRef() > 1 ) 1373 { 1374 FormulaToken** p2 = pCode; 1375 sal_uInt16 nIdx = 0xFFFF; 1376 for( sal_uInt16 j = 0; j < nLen; j++, p2++ ) 1377 { 1378 if( *p2 == t ) 1379 { 1380 nIdx = j; break; 1381 } 1382 } 1383 if( nIdx == 0xFFFF ) 1384 *pp = t->Clone(); 1385 else 1386 *pp = p->pCode[ nIdx ]; 1387 } 1388 else 1389 *pp = t->Clone(); 1390 (*pp)->IncRef(); 1391 } 1392 } 1393 return p; 1394 } 1395 1396 FormulaToken* ScTokenArray::AddRawToken( const ScRawToken& r ) 1397 { 1398 return Add( r.CreateToken() ); 1399 } 1400 1401 // Utility function to ensure that there is strict alternation of values and 1402 // seperators. 1403 static bool 1404 checkArraySep( bool & bPrevWasSep, bool bNewVal ) 1405 { 1406 bool bResult = (bPrevWasSep == bNewVal); 1407 bPrevWasSep = bNewVal; 1408 return bResult; 1409 } 1410 1411 FormulaToken* ScTokenArray::MergeArray( ) 1412 { 1413 int nCol = -1, nRow = 0; 1414 int i, nPrevRowSep = -1, nStart = 0; 1415 bool bPrevWasSep = false; // top of stack is ocArrayClose 1416 FormulaToken* t; 1417 bool bNumeric = false; // numeric value encountered in current element 1418 1419 // (1) Iterate from the end to the start to find matrix dims 1420 // and do basic validation. 1421 for ( i = nLen ; i-- > nStart ; ) 1422 { 1423 t = pCode[i]; 1424 switch ( t->GetOpCode() ) 1425 { 1426 case ocPush : 1427 if( checkArraySep( bPrevWasSep, false ) ) 1428 { 1429 return NULL; 1430 } 1431 1432 // no references or nested arrays 1433 if ( t->GetType() != svDouble && t->GetType() != svString ) 1434 { 1435 return NULL; 1436 } 1437 bNumeric = (t->GetType() == svDouble); 1438 break; 1439 1440 case ocMissing : 1441 case ocTrue : 1442 case ocFalse : 1443 if( checkArraySep( bPrevWasSep, false ) ) 1444 { 1445 return NULL; 1446 } 1447 bNumeric = false; 1448 break; 1449 1450 case ocArrayColSep : 1451 case ocSep : 1452 if( checkArraySep( bPrevWasSep, true ) ) 1453 { 1454 return NULL; 1455 } 1456 bNumeric = false; 1457 break; 1458 1459 case ocArrayClose : 1460 // not possible with the , but check just in case 1461 // something changes in the future 1462 if( i != (nLen-1)) 1463 { 1464 return NULL; 1465 } 1466 1467 if( checkArraySep( bPrevWasSep, true ) ) 1468 { 1469 return NULL; 1470 } 1471 1472 nPrevRowSep = i; 1473 bNumeric = false; 1474 break; 1475 1476 case ocArrayOpen : 1477 nStart = i; // stop iteration 1478 // fall through to ArrayRowSep 1479 1480 case ocArrayRowSep : 1481 if( checkArraySep( bPrevWasSep, true ) ) 1482 { 1483 return NULL; 1484 } 1485 1486 if( nPrevRowSep < 0 || // missing ocArrayClose 1487 ((nPrevRowSep - i) % 2) == 1) // no complex elements 1488 { 1489 return NULL; 1490 } 1491 1492 if( nCol < 0 ) 1493 { 1494 nCol = (nPrevRowSep - i) / 2; 1495 } 1496 else if( (nPrevRowSep - i)/2 != nCol) // irregular array 1497 { 1498 return NULL; 1499 } 1500 1501 nPrevRowSep = i; 1502 nRow++; 1503 bNumeric = false; 1504 break; 1505 1506 case ocNegSub : 1507 case ocAdd : 1508 // negation or unary plus must precede numeric value 1509 if( !bNumeric ) 1510 { 1511 return NULL; 1512 } 1513 --nPrevRowSep; // shorten this row by 1 1514 bNumeric = false; // one level only, no --42 1515 break; 1516 1517 case ocSpaces : 1518 // ignore spaces 1519 --nPrevRowSep; // shorten this row by 1 1520 break; 1521 1522 default : 1523 // no functions or operators 1524 return NULL; 1525 } 1526 } 1527 if( nCol <= 0 || nRow <= 0 ) 1528 return NULL; 1529 1530 // fprintf (stderr, "Array (cols = %d, rows = %d)\n", nCol, nRow ); 1531 1532 int nSign = 1; 1533 ScMatrix* pArray = new ScMatrix( nCol, nRow ); 1534 for ( i = nStart, nCol = 0, nRow = 0 ; i < nLen ; i++ ) 1535 { 1536 t = pCode[i]; 1537 1538 switch ( t->GetOpCode() ) 1539 { 1540 case ocPush : 1541 if ( t->GetType() == svDouble ) 1542 { 1543 pArray->PutDouble( t->GetDouble() * nSign, nCol, nRow ); 1544 nSign = 1; 1545 } 1546 else if ( t->GetType() == svString ) 1547 { 1548 pArray->PutString( t->GetString(), nCol, nRow ); 1549 } 1550 break; 1551 1552 case ocMissing : 1553 pArray->PutEmpty( nCol, nRow ); 1554 break; 1555 1556 case ocTrue : 1557 pArray->PutBoolean( true, nCol, nRow ); 1558 break; 1559 1560 case ocFalse : 1561 pArray->PutBoolean( false, nCol, nRow ); 1562 break; 1563 1564 case ocArrayColSep : 1565 case ocSep : 1566 nCol++; 1567 break; 1568 1569 case ocArrayRowSep : 1570 nRow++; nCol = 0; 1571 break; 1572 1573 case ocNegSub : 1574 nSign = -nSign; 1575 break; 1576 1577 default : 1578 break; 1579 } 1580 pCode[i] = NULL; 1581 t->DecRef(); 1582 } 1583 nLen = sal_uInt16( nStart ); 1584 return AddMatrix( pArray ); 1585 } 1586 1587 1588 FormulaToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos ) 1589 { 1590 if (!pCode || !nLen) 1591 return NULL; 1592 sal_uInt16 nIdx = nLen; 1593 FormulaToken *p1, *p2, *p3; // ref, ocRange, ref 1594 // The actual types are checked in ExtendRangeReference(). 1595 if (((p3 = PeekPrev(nIdx)) != 0) && 1596 (((p2 = PeekPrev(nIdx)) != 0) && p2->GetOpCode() == ocRange) && 1597 ((p1 = PeekPrev(nIdx)) != 0)) 1598 { 1599 FormulaTokenRef p = ScToken::ExtendRangeReference( *p1, *p3, rPos, true); 1600 if (p) 1601 { 1602 p->IncRef(); 1603 p1->DecRef(); 1604 p2->DecRef(); 1605 p3->DecRef(); 1606 nLen -= 2; 1607 pCode[ nLen-1 ] = p; 1608 nRefs--; 1609 } 1610 } 1611 return pCode[ nLen-1 ]; 1612 } 1613 1614 FormulaToken* ScTokenArray::AddOpCode( OpCode e ) 1615 { 1616 ScRawToken t; 1617 t.SetOpCode( e ); 1618 return AddRawToken( t ); 1619 } 1620 1621 FormulaToken* ScTokenArray::AddSingleReference( const ScSingleRefData& rRef ) 1622 { 1623 return Add( new ScSingleRefToken( rRef ) ); 1624 } 1625 1626 FormulaToken* ScTokenArray::AddMatrixSingleReference( const ScSingleRefData& rRef ) 1627 { 1628 return Add( new ScSingleRefToken( rRef, ocMatRef ) ); 1629 } 1630 1631 FormulaToken* ScTokenArray::AddDoubleReference( const ScComplexRefData& rRef ) 1632 { 1633 return Add( new ScDoubleRefToken( rRef ) ); 1634 } 1635 1636 FormulaToken* ScTokenArray::AddMatrix( ScMatrix* p ) 1637 { 1638 return Add( new ScMatrixToken( p ) ); 1639 } 1640 1641 FormulaToken* ScTokenArray::AddExternalName( sal_uInt16 nFileId, const String& rName ) 1642 { 1643 return Add( new ScExternalNameToken(nFileId, rName) ); 1644 } 1645 1646 FormulaToken* ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& rRef ) 1647 { 1648 return Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) ); 1649 } 1650 1651 FormulaToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& rRef ) 1652 { 1653 return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) ); 1654 } 1655 1656 FormulaToken* ScTokenArray::AddColRowName( const ScSingleRefData& rRef ) 1657 { 1658 return Add( new ScSingleRefToken( rRef, ocColRowName ) ); 1659 } 1660 1661 sal_Bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend, 1662 const ScAddress& rPos, ScDirection eDir ) 1663 { 1664 SCCOL nCol = 0; 1665 SCROW nRow = 0; 1666 switch ( eDir ) 1667 { 1668 case DIR_BOTTOM : 1669 if ( rPos.Row() < MAXROW ) 1670 nRow = (nExtend = rPos.Row()) + 1; 1671 else 1672 return sal_False; 1673 break; 1674 case DIR_RIGHT : 1675 if ( rPos.Col() < MAXCOL ) 1676 nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1; 1677 else 1678 return sal_False; 1679 break; 1680 case DIR_TOP : 1681 if ( rPos.Row() > 0 ) 1682 nRow = (nExtend = rPos.Row()) - 1; 1683 else 1684 return sal_False; 1685 break; 1686 case DIR_LEFT : 1687 if ( rPos.Col() > 0 ) 1688 nCol = static_cast<SCCOL>(nExtend = rPos.Col()) - 1; 1689 else 1690 return sal_False; 1691 break; 1692 default: 1693 DBG_ERRORFILE( "unknown Direction" ); 1694 return sal_False; 1695 } 1696 if ( pRPN && nRPN ) 1697 { 1698 FormulaToken* t = pRPN[nRPN-1]; 1699 if ( t->GetType() == svByte ) 1700 { 1701 sal_uInt8 nParamCount = t->GetByte(); 1702 if ( nParamCount && nRPN > nParamCount ) 1703 { 1704 sal_Bool bRet = sal_False; 1705 sal_uInt16 nParam = nRPN - nParamCount - 1; 1706 for ( ; nParam < nRPN-1; nParam++ ) 1707 { 1708 FormulaToken* p = pRPN[nParam]; 1709 switch ( p->GetType() ) 1710 { 1711 case svSingleRef : 1712 { 1713 ScSingleRefData& rRef = static_cast<ScToken*>(p)->GetSingleRef(); 1714 rRef.CalcAbsIfRel( rPos ); 1715 switch ( eDir ) 1716 { 1717 case DIR_BOTTOM : 1718 if ( rRef.nRow == nRow 1719 && rRef.nRow > nExtend ) 1720 { 1721 nExtend = rRef.nRow; 1722 bRet = sal_True; 1723 } 1724 break; 1725 case DIR_RIGHT : 1726 if ( rRef.nCol == nCol 1727 && static_cast<SCCOLROW>(rRef.nCol) 1728 > nExtend ) 1729 { 1730 nExtend = rRef.nCol; 1731 bRet = sal_True; 1732 } 1733 break; 1734 case DIR_TOP : 1735 if ( rRef.nRow == nRow 1736 && rRef.nRow < nExtend ) 1737 { 1738 nExtend = rRef.nRow; 1739 bRet = sal_True; 1740 } 1741 break; 1742 case DIR_LEFT : 1743 if ( rRef.nCol == nCol 1744 && static_cast<SCCOLROW>(rRef.nCol) 1745 < nExtend ) 1746 { 1747 nExtend = rRef.nCol; 1748 bRet = sal_True; 1749 } 1750 break; 1751 } 1752 } 1753 break; 1754 case svDoubleRef : 1755 { 1756 ScComplexRefData& rRef = static_cast<ScToken*>(p)->GetDoubleRef(); 1757 rRef.CalcAbsIfRel( rPos ); 1758 switch ( eDir ) 1759 { 1760 case DIR_BOTTOM : 1761 if ( rRef.Ref1.nRow == nRow 1762 && rRef.Ref2.nRow > nExtend ) 1763 { 1764 nExtend = rRef.Ref2.nRow; 1765 bRet = sal_True; 1766 } 1767 break; 1768 case DIR_RIGHT : 1769 if ( rRef.Ref1.nCol == nCol && 1770 static_cast<SCCOLROW>(rRef.Ref2.nCol) 1771 > nExtend ) 1772 { 1773 nExtend = rRef.Ref2.nCol; 1774 bRet = sal_True; 1775 } 1776 break; 1777 case DIR_TOP : 1778 if ( rRef.Ref2.nRow == nRow 1779 && rRef.Ref1.nRow < nExtend ) 1780 { 1781 nExtend = rRef.Ref1.nRow; 1782 bRet = sal_True; 1783 } 1784 break; 1785 case DIR_LEFT : 1786 if ( rRef.Ref2.nCol == nCol && 1787 static_cast<SCCOLROW>(rRef.Ref1.nCol) 1788 < nExtend ) 1789 { 1790 nExtend = rRef.Ref1.nCol; 1791 bRet = sal_True; 1792 } 1793 break; 1794 } 1795 } 1796 break; 1797 default: 1798 { 1799 // added to avoid warnings 1800 } 1801 } // switch 1802 } // for 1803 return bRet; 1804 } 1805 } 1806 } 1807 return sal_False; 1808 } 1809 1810 1811 void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos, 1812 const ScAddress& rNewPos ) 1813 { 1814 for ( sal_uInt16 j=0; j<nLen; ++j ) 1815 { 1816 switch ( pCode[j]->GetType() ) 1817 { 1818 case svDoubleRef : 1819 { 1820 ScSingleRefData& rRef2 = static_cast<ScToken*>(pCode[j])->GetSingleRef2(); 1821 // Also adjust if the reference is of the form Sheet1.A2:A3 1822 if ( rRef2.IsFlag3D() || static_cast<ScToken*>(pCode[j])->GetSingleRef().IsFlag3D() ) 1823 { 1824 rRef2.CalcAbsIfRel( rOldPos ); 1825 rRef2.CalcRelFromAbs( rNewPos ); 1826 } 1827 } 1828 //! fallthru 1829 case svSingleRef : 1830 { 1831 ScSingleRefData& rRef1 = static_cast<ScToken*>(pCode[j])->GetSingleRef(); 1832 if ( rRef1.IsFlag3D() ) 1833 { 1834 rRef1.CalcAbsIfRel( rOldPos ); 1835 rRef1.CalcRelFromAbs( rNewPos ); 1836 } 1837 } 1838 break; 1839 case svExternalDoubleRef: 1840 { 1841 ScSingleRefData& rRef2 = static_cast<ScToken*>(pCode[j])->GetSingleRef2(); 1842 rRef2.CalcAbsIfRel( rOldPos ); 1843 rRef2.CalcRelFromAbs( rNewPos ); 1844 } 1845 //! fallthru 1846 case svExternalSingleRef: 1847 { 1848 ScSingleRefData& rRef1 = static_cast<ScToken*>(pCode[j])->GetSingleRef(); 1849 rRef1.CalcAbsIfRel( rOldPos ); 1850 rRef1.CalcRelFromAbs( rNewPos ); 1851 } 1852 break; 1853 default: 1854 { 1855 // added to avoid warnings 1856 } 1857 } 1858 } 1859 } 1860 1861 1862