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 #ifndef SC_CELL_HXX 23 #define SC_CELL_HXX 24 25 #include <stddef.h> 26 27 #include <set> 28 #include <tools/mempool.hxx> 29 #include <svl/listener.hxx> 30 #include "global.hxx" 31 #include "rangenam.hxx" 32 #include "formula/grammar.hxx" 33 #include "tokenarray.hxx" 34 #include "formularesult.hxx" 35 #include <rtl/ustrbuf.hxx> 36 #include <unotools/fontcvt.hxx> 37 #include "scdllapi.h" 38 39 #include <cellform.hxx> 40 41 #define USE_MEMPOOL 42 #define TEXTWIDTH_DIRTY 0xffff 43 44 // in addition to SCRIPTTYPE_... flags from scripttypeitem.hxx: 45 // set (in nScriptType) if type has not been determined yet 46 #define SC_SCRIPTTYPE_UNKNOWN 0x08 47 48 class ScDocument; 49 class EditTextObject; 50 class ScMatrix; 51 class SvtBroadcaster; 52 class ScCodeArray; 53 class ScProgress; 54 class ScPostIt; 55 56 // ============================================================================ 57 58 /** Default cell clone flags: do not start listening, do not adjust 3D refs to 59 old position, clone note captions of cell notes. */ 60 const int SC_CLONECELL_DEFAULT = 0x0000; 61 62 /** If set, cloned formula cells will start to listen to the document. */ 63 const int SC_CLONECELL_STARTLISTENING = 0x0001; 64 65 /** If set, relative 3D references of cloned formula cells will be adjusted to 66 old position (used while swapping cells for sorting a cell range). */ 67 const int SC_CLONECELL_ADJUST3DREL = 0x0002; 68 69 /** If set, the caption object of a cell note will not be cloned (used while 70 copying cells to undo document, where captions are handled in drawing undo). */ 71 const int SC_CLONECELL_NOCAPTION = 0x0004; 72 73 // ============================================================================ 74 75 class SC_DLLPUBLIC ScBaseCell 76 { 77 protected: 78 ~ScBaseCell(); // nicht virtuell -> darf nicht direkt aufgerufen werden 79 80 public: 81 explicit ScBaseCell( CellType eNewType ); 82 83 /** Base copy constructor. Does NOT clone cell note or broadcaster! */ 84 ScBaseCell( const ScBaseCell& rCell ); 85 86 /** Returns a clone of this cell at the same position, cell note and 87 broadcaster will not be cloned. */ 88 ScBaseCell* CloneWithoutNote( ScDocument& rDestDoc, int nCloneFlags = SC_CLONECELL_DEFAULT ) const; 89 90 /** Returns a clone of this cell for the passed document position, cell 91 note and broadcaster will not be cloned. */ 92 ScBaseCell* CloneWithoutNote( ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags = SC_CLONECELL_DEFAULT ) const; 93 94 /** Returns a clone of this cell, clones cell note and caption object too 95 (unless SC_CLONECELL_NOCAPTION flag is set). Broadcaster will not be cloned. */ 96 ScBaseCell* CloneWithNote( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags = SC_CLONECELL_DEFAULT ) const; 97 98 /** Due to the fact that ScBaseCell does not have a vtable, this function 99 deletes the cell by calling the appropriate d'tor of the derived class. */ 100 void Delete(); 101 102 inline CellType GetCellType() const { return (CellType)eCellType; } 103 104 /** Returns true, if the cell is empty (neither value nor formula nor cell note). 105 Returns false for formula cells returning nothing, use HasEmptyData() for that. */ 106 bool IsBlank( bool bIgnoreNotes = false ) const; 107 108 // fuer Idle-Berechnung 109 inline sal_uInt16 GetTextWidth() const { return nTextWidth; } 110 inline void SetTextWidth( sal_uInt16 nNew ) { nTextWidth = nNew; } 111 112 inline sal_uInt8 GetScriptType() const { return nScriptType; } 113 inline void SetScriptType( sal_uInt8 nNew ) { nScriptType = nNew; } 114 115 /** Returns true, if the cell contains a note. */ 116 inline bool HasNote() const { return mpNote != 0; } 117 /** Returns the pointer to a cell note object (read-only). */ 118 inline const ScPostIt* GetNote() const { return mpNote; } 119 /** Returns the pointer to a cell note object. */ 120 inline ScPostIt* GetNote() { return mpNote; } 121 /** Takes ownership of the passed cell note object. */ 122 void TakeNote( ScPostIt* pNote ); 123 /** Returns and forgets the own cell note object. Caller takes ownership! */ 124 ScPostIt* ReleaseNote(); 125 /** Deletes the own cell note object. */ 126 void DeleteNote(); 127 128 /** Returns true, if the cell contains a broadcaster. */ 129 inline bool HasBroadcaster() const { return mpBroadcaster != 0; } 130 /** Returns the pointer to the cell broadcaster. */ 131 inline SvtBroadcaster* GetBroadcaster() const { return mpBroadcaster; } 132 /** Takes ownership of the passed cell broadcaster. */ 133 void TakeBroadcaster( SvtBroadcaster* pBroadcaster ); 134 /** Returns and forgets the own cell broadcaster. Caller takes ownership! */ 135 SvtBroadcaster* ReleaseBroadcaster(); 136 /** Deletes the own cell broadcaster. */ 137 void DeleteBroadcaster(); 138 139 // String- oder EditCell 140 static ScBaseCell* CreateTextCell( const String& rString, ScDocument* ); 141 142 // nOnlyNames may be one or more of SC_LISTENING_NAMES_* 143 void StartListeningTo( ScDocument* pDoc ); 144 void EndListeningTo( ScDocument* pDoc, 145 ScTokenArray* pArr = NULL, 146 ScAddress aPos = ScAddress() ); 147 148 /** Error code if ScFormulaCell, else 0. */ 149 sal_uInt16 GetErrorCode() const; 150 /** ScFormulaCell with formula::svEmptyCell result, or ScNoteCell (may have been 151 created due to reference to empty cell). */ 152 sal_Bool HasEmptyData() const; 153 sal_Bool HasValueData() const; 154 sal_Bool HasStringData() const; 155 String GetStringData() const; // nur echte Strings 156 157 static sal_Bool CellEqual( const ScBaseCell* pCell1, const ScBaseCell* pCell2 ); 158 159 private: 160 ScBaseCell& operator=( const ScBaseCell& ); 161 162 private: 163 ScPostIt* mpNote; /// The cell note. Cell takes ownership! 164 SvtBroadcaster* mpBroadcaster; /// Broadcaster for changed values. Cell takes ownership! 165 166 protected: 167 sal_uInt16 nTextWidth; 168 sal_uInt8 eCellType; // enum CellType - sal_uInt8 spart Speicher 169 sal_uInt8 nScriptType; 170 }; 171 172 // ============================================================================ 173 174 class SC_DLLPUBLIC ScNoteCell : public ScBaseCell 175 { 176 public: 177 #ifdef USE_MEMPOOL 178 DECL_FIXEDMEMPOOL_NEWDEL( ScNoteCell ) 179 #endif 180 181 /** Cell takes ownership of the passed broadcaster. */ 182 explicit ScNoteCell( SvtBroadcaster* pBC = 0 ); 183 /** Cell takes ownership of the passed note and broadcaster. */ 184 explicit ScNoteCell( ScPostIt* pNote, SvtBroadcaster* pBC = 0 ); 185 186 #ifdef DBG_UTIL 187 ~ScNoteCell(); 188 #endif 189 190 private: 191 ScNoteCell( const ScNoteCell& ); 192 }; 193 194 // ============================================================================ 195 196 class SC_DLLPUBLIC ScValueCell : public ScBaseCell 197 { 198 public: 199 #ifdef USE_MEMPOOL 200 DECL_FIXEDMEMPOOL_NEWDEL( ScValueCell ) 201 #endif 202 ScValueCell(); 203 explicit ScValueCell( double fValue ); 204 205 #ifdef DBG_UTIL 206 ~ScValueCell(); 207 #endif 208 209 inline void SetValue( double fValue ) { mfValue = fValue; } 210 inline double GetValue() const { return mfValue; } 211 212 private: 213 double mfValue; 214 }; 215 216 // ============================================================================ 217 218 class SC_DLLPUBLIC ScStringCell : public ScBaseCell 219 { 220 public: 221 #ifdef USE_MEMPOOL 222 DECL_FIXEDMEMPOOL_NEWDEL( ScStringCell ) 223 #endif 224 225 ScStringCell(); 226 explicit ScStringCell( const String& rString ); 227 228 #ifdef DBG_UTIL 229 ~ScStringCell(); 230 #endif 231 232 inline void SetString( const String& rString ) { maString = rString; } 233 inline void GetString( String& rString ) const { rString = maString; } 234 inline const String& GetString() const { return maString; } 235 236 private: 237 String maString; 238 }; 239 240 // ============================================================================ 241 242 class SC_DLLPUBLIC ScEditCell : public ScBaseCell 243 { 244 private: 245 EditTextObject* pData; 246 String* pString; // fuer schnelleren Zugriff von Formeln 247 ScDocument* pDoc; // fuer EditEngine Zugriff mit Pool 248 249 void SetTextObject( const EditTextObject* pObject, 250 const SfxItemPool* pFromPool ); 251 252 // not implemented 253 ScEditCell( const ScEditCell& ); 254 255 public: 256 257 #ifdef USE_MEMPOOL 258 DECL_FIXEDMEMPOOL_NEWDEL( ScEditCell ) 259 #endif 260 261 ~ScEditCell(); // wegen pData immer! 262 263 ScEditCell( const EditTextObject* pObject, ScDocument*, 264 const SfxItemPool* pFromPool /* = NULL */ ); 265 ScEditCell( const ScEditCell& rCell, ScDocument& rDoc ); 266 // fuer Zeilenumbrueche 267 ScEditCell( const String& rString, ScDocument* ); 268 269 void SetData( const EditTextObject* pObject, 270 const SfxItemPool* pFromPool /* = NULL */ ); 271 void GetData( const EditTextObject*& rpObject ) const; 272 void GetString( String& rString ) const; 273 274 const EditTextObject* GetData() const { return pData; } 275 }; 276 277 // ============================================================================ 278 279 enum ScMatrixMode { 280 MM_NONE = 0, // No matrix formula 281 MM_FORMULA = 1, // Upper left matrix formula cell 282 MM_REFERENCE = 2, // Remaining cells, via ocMatRef reference token 283 MM_FAKE = 3 // Interpret "as-if" matrix formula (legacy) 284 }; 285 286 class SC_DLLPUBLIC ScFormulaCell : public ScBaseCell, public SvtListener 287 { 288 private: 289 ScFormulaResult aResult; 290 formula::FormulaGrammar::Grammar eTempGrammar; // used between string (creation) and (re)compilation 291 ScTokenArray* pCode; // The (new) token array 292 ScDocument* pDocument; 293 ScFormulaCell* pPrevious; 294 ScFormulaCell* pNext; 295 ScFormulaCell* pPreviousTrack; 296 ScFormulaCell* pNextTrack; 297 sal_uLong nFormatIndex; // Number format set by calculation 298 short nFormatType; // Number format type set by calculation 299 sal_uInt16 nSeenInIteration; // Iteration cycle in which the cell was last encountered 300 sal_uInt8 cMatrixFlag; // One of ScMatrixMode 301 sal_Bool bDirty : 1; // Must be (re)calculated 302 sal_Bool bChanged : 1; // Whether something changed regarding display/representation 303 sal_Bool bRunning : 1; // Already interpreting right now 304 sal_Bool bCompile : 1; // Must be (re)compiled 305 sal_Bool bSubTotal : 1; // Cell is part of or contains a SubTotal 306 sal_Bool bIsIterCell : 1; // Cell is part of a circular reference 307 sal_Bool bInChangeTrack : 1; // Cell is in ChangeTrack 308 sal_Bool bTableOpDirty : 1; // Dirty flag for TableOp 309 sal_Bool bNeedListening : 1; // Listeners need to be re-established after UpdateReference 310 ScToken* pValidRefToken; // i120962, get the valid reference token if the cell was applied a reference formula 311 312 enum ScInterpretTailParameter 313 { 314 SCITP_NORMAL, 315 SCITP_FROM_ITERATION, 316 SCITP_CLOSE_ITERATION_CIRCLE 317 }; 318 void InterpretTail( ScInterpretTailParameter ); 319 320 ScFormulaCell( const ScFormulaCell& ); 321 322 public: 323 324 #ifdef USE_MEMPOOL 325 DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell ) 326 #endif 327 328 ScAddress aPos; 329 330 ~ScFormulaCell(); 331 ScFormulaCell(); 332 333 /** Empty formula cell, or with a preconstructed token array. */ 334 ScFormulaCell( ScDocument*, const ScAddress&, const ScTokenArray* = NULL, 335 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT, 336 sal_uInt8 = MM_NONE ); 337 338 /** With formula string and grammar to compile with. 339 formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that 340 also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefor uses the address 341 convention associated with rPos::nTab by default. */ 342 ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, 343 const String& rFormula, 344 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT, 345 sal_uInt8 cMatInd = MM_NONE ); 346 347 ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags = SC_CLONECELL_DEFAULT ); 348 349 void GetFormula( String& rFormula, 350 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const; 351 void GetFormula( rtl::OUStringBuffer& rBuffer, 352 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const; 353 354 void SetDirty(); 355 inline void SetDirtyVar() { bDirty = sal_True; } 356 // If setting entire document dirty after load, no broadcasts but still append to FormulaTree. 357 void SetDirtyAfterLoad(); 358 inline void ResetTableOpDirtyVar() { bTableOpDirty = sal_False; } 359 void SetTableOpDirty(); 360 sal_Bool IsDirtyOrInTableOpDirty() const; 361 sal_Bool GetDirty() const { return bDirty; } 362 sal_Bool NeedsListening() const { return bNeedListening; } 363 void SetNeedsListening( sal_Bool bVar ) { bNeedListening = bVar; } 364 void Compile(const String& rFormula, 365 sal_Bool bNoListening = sal_False, 366 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ); 367 void CompileTokenArray( sal_Bool bNoListening = sal_False ); 368 void CompileXML( ScProgress& rProgress ); // compile temporary string tokens 369 void CalcAfterLoad(); 370 bool MarkUsedExternalReferences(); 371 void Interpret(); 372 inline sal_Bool IsIterCell() const { return bIsIterCell; } 373 inline sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; } 374 375 sal_Bool HasOneReference( ScRange& r ) const; 376 /* Checks if the formula contains reference list that can be 377 expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The 378 reference list is not required to be sorted (i.e. A3;A1;A2 is 379 still recognized as A1:A3), but no overlapping is allowed. 380 If one reference is recognized, the rRange is filled. 381 382 It is similar to HasOneReference(), but more general. 383 */ 384 bool HasRefListExpressibleAsOneReference(ScRange& rRange) const; 385 sal_Bool HasRelNameReference() const; 386 sal_Bool HasColRowName() const; 387 388 void UpdateReference(UpdateRefMode eUpdateRefMode, 389 const ScRange& r, 390 SCsCOL nDx, SCsROW nDy, SCsTAB nDz, 391 ScDocument* pUndoDoc = NULL, 392 const ScAddress* pUndoCellPos = NULL ); 393 394 void TransposeReference(); 395 void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest, 396 ScDocument* pUndoDoc ); 397 398 void UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY ); 399 400 void UpdateInsertTab(SCTAB nTable); 401 void UpdateInsertTabAbs(SCTAB nTable); 402 sal_Bool UpdateDeleteTab(SCTAB nTable, sal_Bool bIsMove = sal_False); 403 void UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo); 404 void UpdateRenameTab(SCTAB nTable, const String& rName); 405 sal_Bool TestTabRefAbs(SCTAB nTable); 406 void UpdateCompile( sal_Bool bForceIfNameInUse = sal_False ); 407 sal_Bool IsRangeNameInUse(sal_uInt16 nIndex) const; 408 void FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const; 409 void ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap ); 410 sal_Bool IsSubTotal() const { return bSubTotal; } 411 sal_Bool IsChanged() const { return bChanged; } 412 void ResetChanged() { bChanged = sal_False; } 413 sal_Bool IsEmpty(); // formula::svEmptyCell result 414 // display as empty string if formula::svEmptyCell result 415 sal_Bool IsEmptyDisplayedAsString(); 416 sal_Bool IsValue(); // also sal_True if formula::svEmptyCell 417 double GetValue(); 418 double GetValueAlways(); // ignore errors 419 void GetString( String& rString ); 420 const ScMatrix* GetMatrix(); 421 sal_Bool GetMatrixOrigin( ScAddress& rPos ) const; 422 void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows ); 423 sal_uInt16 GetMatrixEdge( ScAddress& rOrgPos ); 424 sal_uInt16 GetErrCode(); // interpret first if necessary 425 sal_uInt16 GetRawError(); // don't interpret, just return code or result error 426 short GetFormatType() const { return nFormatType; } 427 sal_uLong GetFormatIndex() const { return nFormatIndex; } 428 void GetFormatInfo( short& nType, sal_uLong& nIndex ) const 429 { nType = nFormatType; nIndex = nFormatIndex; } 430 sal_uInt8 GetMatrixFlag() const { return cMatrixFlag; } 431 ScTokenArray* GetCode() const { return pCode; } 432 433 sal_Bool IsRunning() const { return bRunning; } 434 void SetRunning( sal_Bool bVal ) { bRunning = bVal; } 435 void CompileDBFormula(); 436 void CompileDBFormula( sal_Bool bCreateFormulaString ); 437 void CompileNameFormula( sal_Bool bCreateFormulaString ); 438 void CompileColRowNameFormula(); 439 ScFormulaCell* GetPrevious() const { return pPrevious; } 440 ScFormulaCell* GetNext() const { return pNext; } 441 void SetPrevious( ScFormulaCell* pF ) { pPrevious = pF; } 442 void SetNext( ScFormulaCell* pF ) { pNext = pF; } 443 ScFormulaCell* GetPreviousTrack() const { return pPreviousTrack; } 444 ScFormulaCell* GetNextTrack() const { return pNextTrack; } 445 void SetPreviousTrack( ScFormulaCell* pF ) { pPreviousTrack = pF; } 446 void SetNextTrack( ScFormulaCell* pF ) { pNextTrack = pF; } 447 448 virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint); 449 void SetCompile( sal_Bool bVal ) { bCompile = bVal; } 450 ScDocument* GetDocument() const { return pDocument; } 451 void SetMatColsRows( SCCOL nCols, SCROW nRows ); 452 void GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const; 453 454 // ob Zelle im ChangeTrack und nicht im echten Dokument ist 455 void SetInChangeTrack( sal_Bool bVal ) { bInChangeTrack = bVal; } 456 sal_Bool IsInChangeTrack() const { return bInChangeTrack; } 457 458 // Zu Typ und Format das entsprechende Standardformat. 459 // Bei Format "Standard" evtl. das in die Formelzelle 460 // uebernommene Format. 461 sal_uLong GetStandardFormat( SvNumberFormatter& rFormatter, sal_uLong nFormat ) const; 462 463 // For import filters! 464 void AddRecalcMode( formula::ScRecalcMode ); 465 /** For import only: set a double result. */ 466 void SetHybridDouble( double n ) { aResult.SetHybridDouble( n); } 467 /** For import only: set a string result. 468 If for whatever reason you have to use both, SetHybridDouble() and 469 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first 470 for performance reasons.*/ 471 void SetHybridString( const String& r ) 472 { aResult.SetHybridString( r); } 473 /** For import only: set a temporary formula string to be compiled later. 474 If for whatever reason you have to use both, SetHybridDouble() and 475 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first 476 for performance reasons.*/ 477 void SetHybridFormula( const String& r, 478 const formula::FormulaGrammar::Grammar eGrammar ) 479 { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; } 480 void SetErrCode( sal_uInt16 n ); 481 inline sal_Bool IsHyperLinkCell() const { return pCode && pCode->IsHyperLink(); } 482 EditTextObject* CreateURLObject() ; 483 void GetURLResult( String& rURL, String& rCellText ); 484 485 /** Determines whether or not the result string contains more than one paragraph */ 486 bool IsMultilineResult(); 487 ScToken* GetValidRefToken() { return pValidRefToken; } // i120962 488 }; 489 490 // Iterator fuer Referenzen in einer Formelzelle 491 class ScDetectiveRefIter 492 { 493 private: 494 ScTokenArray* pCode; 495 ScAddress aPos; 496 public: 497 ScDetectiveRefIter( ScFormulaCell* pCell ); 498 sal_Bool GetNextRef( ScRange& rRange ); 499 }; 500 501 // ============================================================================ 502 inline double GetValueFromCell( const ScBaseCell * pCell ) 503 { 504 switch (pCell->GetCellType()) 505 { 506 case CELLTYPE_VALUE: 507 return ((ScValueCell*)pCell)->GetValue(); 508 case CELLTYPE_FORMULA: 509 { 510 if (((ScFormulaCell*)pCell)->IsValue()) 511 return ((ScFormulaCell*)pCell)->GetValue(); 512 else 513 return 0.0; 514 } 515 default: 516 return 0.0; 517 } 518 } 519 // ============================================================================ 520 521 522 inline String GetStringFromCell( const ScBaseCell * pCell, sal_uLong nFormat, SvNumberFormatter* pFormatter ) 523 { 524 if (pCell->GetCellType() != CELLTYPE_NOTE) 525 { 526 String strResult; 527 Color* pColor = NULL; 528 ScCellFormat::GetString( const_cast<ScBaseCell*>(pCell), nFormat, strResult, &pColor, *(pFormatter) ); 529 return strResult; 530 } 531 else 532 return String(); 533 } 534 535 #endif 536 537