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