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