1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #ifndef SC_TOKEN_HXX 29 #define SC_TOKEN_HXX 30 31 #include <memory> 32 #include <vector> 33 #include <boost/shared_ptr.hpp> 34 35 #include "formula/opcode.hxx" 36 #include "refdata.hxx" 37 #include "scmatrix.hxx" 38 #include "formula/intruref.hxx" 39 #include <tools/mempool.hxx> 40 #include "scdllapi.h" 41 #include "formula/IFunctionDescription.hxx" 42 #include "formula/token.hxx" 43 44 45 class ScJumpMatrix; 46 class ScToken; 47 48 typedef ::std::vector< ScComplexRefData > ScRefList; 49 typedef formula::SimpleIntrusiveReference< class ScToken > ScTokenRef; 50 51 /** 52 * Another ref-counted token type using shared_ptr. <b>Be extra careful 53 * not to mix use of this smart pointer type with ScTokenRef</b>, since 54 * mixing them might cause a premature object deletion because the same 55 * object may be ref-counted by two different smart pointer wrappers. 56 * 57 * You have been warned. 58 */ 59 typedef ::boost::shared_ptr< ScToken > ScSharedTokenRef; 60 61 class SC_DLLPUBLIC ScToken : public formula::FormulaToken 62 { 63 private: 64 // not implemented, prevent usage 65 ScToken(); 66 ScToken& operator=( const ScToken& ); 67 68 protected: 69 70 ScToken( formula::StackVar eTypeP,OpCode e = ocPush ) : formula::FormulaToken(eTypeP,e) {} 71 ScToken( const ScToken& r ): formula::FormulaToken(r) {} 72 73 public: 74 75 virtual ~ScToken(); 76 77 /** 78 Dummy methods to avoid switches and casts where possible, 79 the real token classes have to overload the appropriate method[s]. 80 The only methods valid anytime if not overloaded are: 81 82 - GetByte() since this represents the count of parameters to a function 83 which of course is 0 on non-functions. formula::FormulaByteToken and ScExternal do 84 overload it. 85 86 - HasForceArray() since also this is only used for operators and 87 functions and is 0 for other tokens. 88 89 Any other non-overloaded method pops up an assertion. 90 */ 91 92 virtual const ScSingleRefData& GetSingleRef() const; 93 virtual ScSingleRefData& GetSingleRef(); 94 virtual const ScComplexRefData& GetDoubleRef() const; 95 virtual ScComplexRefData& GetDoubleRef(); 96 virtual const ScSingleRefData& GetSingleRef2() const; 97 virtual ScSingleRefData& GetSingleRef2(); 98 virtual void CalcAbsIfRel( const ScAddress& ); 99 virtual void CalcRelFromAbs( const ScAddress& ); 100 virtual const ScMatrix* GetMatrix() const; 101 virtual ScMatrix* GetMatrix(); 102 virtual ScJumpMatrix* GetJumpMatrix() const; 103 virtual const ScRefList* GetRefList() const; 104 virtual ScRefList* GetRefList(); 105 106 virtual sal_Bool TextEqual( const formula::FormulaToken& rToken ) const; 107 virtual sal_Bool Is3DRef() const; // reference with 3D flag set 108 109 /** If rTok1 and rTok2 both are SingleRef or DoubleRef tokens, extend/merge 110 ranges as needed for ocRange. 111 @param rPos 112 The formula's position, used to calculate absolute positions from 113 relative references. 114 @param bReuseDoubleRef 115 If sal_True, a DoubleRef token is reused if passed as rTok1 or rTok2, 116 else a new DoubleRef token is created and returned. 117 @return 118 A reused or new'ed ScDoubleRefToken, or a NULL TokenRef if rTok1 or 119 rTok2 are not of sv(Single|Double)Ref 120 */ 121 static formula::FormulaTokenRef ExtendRangeReference( formula::FormulaToken & rTok1, formula::FormulaToken & rTok2, const ScAddress & rPos, bool bReuseDoubleRef ); 122 }; 123 124 class ScSingleRefToken : public ScToken 125 { 126 private: 127 ScSingleRefData aSingleRef; 128 public: 129 ScSingleRefToken( const ScSingleRefData& r, OpCode e = ocPush ) : 130 ScToken( formula::svSingleRef, e ), aSingleRef( r ) {} 131 ScSingleRefToken( const ScSingleRefToken& r ) : 132 ScToken( r ), aSingleRef( r.aSingleRef ) {} 133 virtual const ScSingleRefData& GetSingleRef() const; 134 virtual ScSingleRefData& GetSingleRef(); 135 virtual void CalcAbsIfRel( const ScAddress& ); 136 virtual void CalcRelFromAbs( const ScAddress& ); 137 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 138 virtual FormulaToken* Clone() const { return new ScSingleRefToken(*this); } 139 140 DECL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken ); 141 }; 142 143 class ScDoubleRefToken : public ScToken 144 { 145 private: 146 ScComplexRefData aDoubleRef; 147 public: 148 ScDoubleRefToken( const ScComplexRefData& r, OpCode e = ocPush ) : 149 ScToken( formula::svDoubleRef, e ), aDoubleRef( r ) {} 150 ScDoubleRefToken( const ScSingleRefData& r, OpCode e = ocPush ) : 151 ScToken( formula::svDoubleRef, e ) 152 { 153 aDoubleRef.Ref1 = r; 154 aDoubleRef.Ref2 = r; 155 } 156 ScDoubleRefToken( const ScDoubleRefToken& r ) : 157 ScToken( r ), aDoubleRef( r.aDoubleRef ) {} 158 virtual const ScSingleRefData& GetSingleRef() const; 159 virtual ScSingleRefData& GetSingleRef(); 160 virtual const ScComplexRefData& GetDoubleRef() const; 161 virtual ScComplexRefData& GetDoubleRef(); 162 virtual const ScSingleRefData& GetSingleRef2() const; 163 virtual ScSingleRefData& GetSingleRef2(); 164 virtual void CalcAbsIfRel( const ScAddress& ); 165 virtual void CalcRelFromAbs( const ScAddress& ); 166 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 167 virtual FormulaToken* Clone() const { return new ScDoubleRefToken(*this); } 168 169 DECL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken ); 170 }; 171 172 class ScMatrixToken : public ScToken 173 { 174 private: 175 ScMatrixRef pMatrix; 176 public: 177 ScMatrixToken( ScMatrix* p ) : 178 ScToken( formula::svMatrix ), pMatrix( p ) {} 179 ScMatrixToken( const ScMatrixToken& r ) : 180 ScToken( r ), pMatrix( r.pMatrix ) {} 181 virtual const ScMatrix* GetMatrix() const; 182 virtual ScMatrix* GetMatrix(); 183 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 184 virtual FormulaToken* Clone() const { return new ScMatrixToken(*this); } 185 }; 186 187 188 class ScExternalSingleRefToken : public ScToken 189 { 190 private: 191 sal_uInt16 mnFileId; 192 String maTabName; 193 ScSingleRefData maSingleRef; 194 195 ScExternalSingleRefToken(); // disabled 196 public: 197 ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r ); 198 ScExternalSingleRefToken( const ScExternalSingleRefToken& r ); 199 virtual ~ScExternalSingleRefToken(); 200 201 virtual sal_uInt16 GetIndex() const; 202 virtual const String& GetString() const; 203 virtual const ScSingleRefData& GetSingleRef() const; 204 virtual ScSingleRefData& GetSingleRef(); 205 virtual void CalcAbsIfRel( const ScAddress& ); 206 virtual void CalcRelFromAbs( const ScAddress& ); 207 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 208 virtual FormulaToken* Clone() const { return new ScExternalSingleRefToken(*this); } 209 }; 210 211 212 class ScExternalDoubleRefToken : public ScToken 213 { 214 private: 215 sal_uInt16 mnFileId; 216 String maTabName; // name of the first sheet 217 ScComplexRefData maDoubleRef; 218 219 ScExternalDoubleRefToken(); // disabled 220 public: 221 ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& r ); 222 ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ); 223 explicit ScExternalDoubleRefToken( const ScExternalSingleRefToken& r ); 224 virtual ~ScExternalDoubleRefToken(); 225 226 virtual sal_uInt16 GetIndex() const; 227 virtual const String& GetString() const; 228 virtual const ScSingleRefData& GetSingleRef() const; 229 virtual ScSingleRefData& GetSingleRef(); 230 virtual const ScSingleRefData& GetSingleRef2() const; 231 virtual ScSingleRefData& GetSingleRef2(); 232 virtual const ScComplexRefData& GetDoubleRef() const; 233 virtual ScComplexRefData& GetDoubleRef(); 234 virtual void CalcAbsIfRel( const ScAddress& ); 235 virtual void CalcRelFromAbs( const ScAddress& ); 236 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 237 virtual FormulaToken* Clone() const { return new ScExternalDoubleRefToken(*this); } 238 }; 239 240 241 class ScExternalNameToken : public ScToken 242 { 243 private: 244 sal_uInt16 mnFileId; 245 String maName; 246 private: 247 ScExternalNameToken(); // disabled 248 public: 249 ScExternalNameToken( sal_uInt16 nFileId, const String& rName ); 250 ScExternalNameToken( const ScExternalNameToken& r ); 251 virtual ~ScExternalNameToken(); 252 virtual sal_uInt16 GetIndex() const; 253 virtual const String& GetString() const; 254 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 255 virtual FormulaToken* Clone() const { return new ScExternalNameToken(*this); } 256 }; 257 258 259 // Only created from within the interpreter, no conversion from ScRawToken, 260 // never added to ScTokenArray! 261 class ScJumpMatrixToken : public ScToken 262 { 263 private: 264 ScJumpMatrix* pJumpMatrix; 265 public: 266 ScJumpMatrixToken( ScJumpMatrix* p ) : 267 ScToken( formula::svJumpMatrix ), pJumpMatrix( p ) {} 268 ScJumpMatrixToken( const ScJumpMatrixToken& r ) : 269 ScToken( r ), pJumpMatrix( r.pJumpMatrix ) {} 270 virtual ~ScJumpMatrixToken(); 271 virtual ScJumpMatrix* GetJumpMatrix() const; 272 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 273 virtual FormulaToken* Clone() const { return new ScJumpMatrixToken(*this); } 274 }; 275 276 277 // Only created from within the interpreter, no conversion from ScRawToken, 278 // never added to ScTokenArray! 279 class ScRefListToken : public ScToken 280 { 281 private: 282 ScRefList aRefList; 283 public: 284 ScRefListToken() : 285 ScToken( formula::svRefList ) {} 286 ScRefListToken( const ScRefListToken & r ) : 287 ScToken( r ), aRefList( r.aRefList ) {} 288 virtual void CalcAbsIfRel( const ScAddress& ); 289 virtual void CalcRelFromAbs( const ScAddress& ); 290 virtual const ScRefList* GetRefList() const; 291 virtual ScRefList* GetRefList(); 292 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 293 virtual FormulaToken* Clone() const { return new ScRefListToken(*this); } 294 }; 295 296 297 class SC_DLLPUBLIC ScEmptyCellToken : public ScToken 298 { 299 bool bInherited :1; 300 bool bDisplayedAsString :1; 301 public: 302 explicit ScEmptyCellToken( bool bInheritedP, bool bDisplayAsString ) : 303 ScToken( formula::svEmptyCell ), 304 bInherited( bInheritedP ), 305 bDisplayedAsString( bDisplayAsString ) {} 306 ScEmptyCellToken( const ScEmptyCellToken& r ) : 307 ScToken( r ), 308 bInherited( r.bInherited ), 309 bDisplayedAsString( r.bDisplayedAsString ) {} 310 bool IsInherited() const { return bInherited; } 311 bool IsDisplayedAsString() const { return bDisplayedAsString; } 312 virtual double GetDouble() const; 313 virtual const String & GetString() const; 314 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 315 virtual FormulaToken* Clone() const { return new ScEmptyCellToken(*this); } 316 }; 317 318 319 /** Transports the result from the interpreter to the formula cell. */ 320 class SC_DLLPUBLIC ScMatrixCellResultToken : public ScToken 321 { 322 // No non-const access implemented, silence down unxsols4 complaining about 323 // the public GetMatrix() hiding the one from ScToken. 324 virtual ScMatrix* GetMatrix(); 325 326 protected: 327 ScConstMatrixRef xMatrix; 328 formula::FormulaConstTokenRef xUpperLeft; 329 public: 330 ScMatrixCellResultToken( ScMatrix* pMat, formula::FormulaToken* pUL ) : 331 ScToken( formula::svMatrixCell ), 332 xMatrix( pMat), xUpperLeft( pUL) {} 333 ScMatrixCellResultToken( const ScMatrixCellResultToken& r ) : 334 ScToken( r ), xMatrix( r.xMatrix ), 335 xUpperLeft( r.xUpperLeft ) {} 336 virtual double GetDouble() const; 337 virtual const String & GetString() const; 338 virtual const ScMatrix* GetMatrix() const; 339 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 340 virtual FormulaToken* Clone() const { return new ScMatrixCellResultToken(*this); } 341 formula::StackVar GetUpperLeftType() const 342 { 343 return xUpperLeft ? 344 xUpperLeft->GetType() : 345 static_cast<formula::StackVar>(formula::svUnknown); 346 } 347 inline formula::FormulaConstTokenRef GetUpperLeftToken() const { return xUpperLeft; } 348 void Assign( const ScMatrixCellResultToken & r ) 349 { 350 xMatrix = r.xMatrix; 351 xUpperLeft = r.xUpperLeft; 352 } 353 }; 354 355 356 /** Stores the matrix result at the formula cell, additionally the range the 357 matrix formula occupies. */ 358 class SC_DLLPUBLIC ScMatrixFormulaCellToken : public ScMatrixCellResultToken 359 { 360 private: 361 SCROW nRows; 362 SCCOL nCols; 363 public: 364 ScMatrixFormulaCellToken( SCCOL nC, SCROW nR ) : 365 ScMatrixCellResultToken( NULL, NULL ), 366 nRows( nR ), nCols( nC ) {} 367 ScMatrixFormulaCellToken( const ScMatrixFormulaCellToken& r ) : 368 ScMatrixCellResultToken( r ), 369 nRows( r.nRows ), nCols( r.nCols ) 370 { 371 // xUpperLeft is modifiable through 372 // SetUpperLeftDouble(), so clone it. 373 if (xUpperLeft) 374 xUpperLeft = xUpperLeft->Clone(); 375 } 376 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 377 virtual FormulaToken* Clone() const { return new ScMatrixFormulaCellToken(*this); } 378 void SetMatColsRows( SCCOL nC, SCROW nR ) 379 { 380 nRows = nR; 381 nCols = nC; 382 } 383 void GetMatColsRows( SCCOL & nC, SCROW & nR ) const 384 { 385 nR = nRows; 386 nC = nCols; 387 } 388 SCCOL GetMatCols() const { return nCols; } 389 SCROW GetMatRows() const { return nRows; } 390 391 /** Assign matrix result, keep matrix formula 392 dimension. */ 393 void Assign( const ScMatrixCellResultToken & r ) 394 { 395 ScMatrixCellResultToken::Assign( r); 396 } 397 398 /** Assign any result, keep matrix formula 399 dimension. If token is of type 400 ScMatrixCellResultToken uses the 401 appropriate Assign() call, other tokens 402 are assigned to xUpperLeft and xMatrix will 403 be assigned NULL. */ 404 void Assign( const formula::FormulaToken & r ); 405 406 /** Modify xUpperLeft if formula::svDouble, or create 407 new formula::FormulaDoubleToken if not set yet. Does 408 nothing if xUpperLeft is of different type! */ 409 void SetUpperLeftDouble( double f); 410 411 /** Reset matrix and upper left, keep matrix 412 formula dimension. */ 413 void ResetResult() 414 { 415 xMatrix = NULL; 416 xUpperLeft = NULL; 417 } 418 }; 419 420 421 class SC_DLLPUBLIC ScHybridCellToken : public ScToken 422 { 423 private: 424 double fDouble; 425 String aString; 426 String aFormula; 427 public: 428 ScHybridCellToken( double f, 429 const String & rStr, 430 const String & rFormula ) : 431 ScToken( formula::svHybridCell ), 432 fDouble( f ), aString( rStr ), 433 aFormula( rFormula ) {} 434 ScHybridCellToken( const ScHybridCellToken& r ) : 435 ScToken( r ), fDouble( r.fDouble), 436 aString( r.aString), aFormula( r.aFormula) {} 437 const String & GetFormula() const { return aFormula; } 438 virtual double GetDouble() const; 439 virtual const String & GetString() const; 440 virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; 441 virtual FormulaToken* Clone() const { return new ScHybridCellToken(*this); } 442 }; 443 444 445 // Simplify argument passing to RefUpdate methods with ScSingleRefToken or 446 // ScDoubleRefToken 447 class SingleDoubleRefModifier 448 { 449 ScComplexRefData aDub; 450 ScSingleRefData* pS; 451 ScComplexRefData* pD; 452 453 // not implemented, prevent usage 454 SingleDoubleRefModifier( const SingleDoubleRefModifier& ); 455 SingleDoubleRefModifier& operator=( const SingleDoubleRefModifier& ); 456 457 public: 458 SingleDoubleRefModifier( ScToken& rT ) 459 { 460 if ( rT.GetType() == formula::svSingleRef ) 461 { 462 pS = &rT.GetSingleRef(); 463 aDub.Ref1 = aDub.Ref2 = *pS; 464 pD = &aDub; 465 } 466 else 467 { 468 pS = 0; 469 pD = &rT.GetDoubleRef(); 470 } 471 } 472 SingleDoubleRefModifier( ScSingleRefData& rS ) 473 { 474 pS = &rS; 475 aDub.Ref1 = aDub.Ref2 = *pS; 476 pD = &aDub; 477 } 478 ~SingleDoubleRefModifier() 479 { 480 if ( pS ) 481 *pS = (*pD).Ref1; 482 } 483 inline ScComplexRefData& Ref() { return *pD; } 484 }; 485 486 class SingleDoubleRefProvider 487 { 488 public: 489 490 const ScSingleRefData& Ref1; 491 const ScSingleRefData& Ref2; 492 493 SingleDoubleRefProvider( const ScToken& r ) 494 : Ref1( r.GetSingleRef() ), 495 Ref2( r.GetType() == formula::svDoubleRef ? 496 r.GetDoubleRef().Ref2 : Ref1 ) 497 {} 498 SingleDoubleRefProvider( const ScSingleRefData& r ) 499 : Ref1( r ), Ref2( r ) 500 {} 501 SingleDoubleRefProvider( const ScComplexRefData& r ) 502 : Ref1( r.Ref1 ), Ref2( r.Ref2 ) 503 {} 504 ~SingleDoubleRefProvider() 505 {} 506 }; 507 508 #endif 509