Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef SC_CELL_HXX
21 : #define SC_CELL_HXX
22 :
23 : #include <stddef.h>
24 :
25 : #include <set>
26 : #include <vector>
27 : #include <boost/shared_ptr.hpp>
28 :
29 : #include <tools/mempool.hxx>
30 : #include <svl/listener.hxx>
31 : #include "global.hxx"
32 : #include "rangenam.hxx"
33 : #include "formula/grammar.hxx"
34 : #include "tokenarray.hxx"
35 : #include "formularesult.hxx"
36 : #include <rtl/ustrbuf.hxx>
37 : #include <unotools/fontcvt.hxx>
38 : #include "scdllapi.h"
39 :
40 : #define USE_MEMPOOL
41 : #define TEXTWIDTH_DIRTY 0xffff
42 :
43 : // in addition to SCRIPTTYPE_... flags from scripttypeitem.hxx:
44 : // set (in nScriptType) if type has not been determined yet
45 : #define SC_SCRIPTTYPE_UNKNOWN 0x08
46 :
47 : class ScDocument;
48 : class EditTextObject;
49 : class ScMatrix;
50 : class SvtBroadcaster;
51 : class ScProgress;
52 : class ScPatternAttr;
53 :
54 : // ============================================================================
55 :
56 : /** Default cell clone flags: do not start listening, do not adjust 3D refs to
57 : old position, clone note captions of cell notes. */
58 : const int SC_CLONECELL_DEFAULT = 0x0000;
59 :
60 : /** If set, cloned formula cells will start to listen to the document. */
61 : const int SC_CLONECELL_STARTLISTENING = 0x0001;
62 :
63 : /** If set, relative 3D references of cloned formula cells will be adjusted to
64 : old position (used while swapping cells for sorting a cell range). */
65 : const int SC_CLONECELL_ADJUST3DREL = 0x0002;
66 :
67 : /** If set, the caption object of a cell note will not be cloned (used while
68 : copying cells to undo document, where captions are handled in drawing undo). */
69 : const int SC_CLONECELL_NOCAPTION = 0x0004;
70 :
71 : /** If set, absolute refs will not transformed to external references */
72 : const int SC_CLONECELL_NOMAKEABS_EXTERNAL = 0x0008;
73 : // ============================================================================
74 :
75 : class SC_DLLPUBLIC ScBaseCell
76 : {
77 : protected:
78 : ~ScBaseCell(); // not virtual - not to be called directly.
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,
87 : broadcaster will not be cloned. */
88 : ScBaseCell* Clone( ScDocument& rDestDoc, int nCloneFlags = SC_CLONECELL_DEFAULT ) const;
89 :
90 : /** Returns a clone of this cell for the passed document position,
91 : broadcaster will not be cloned. */
92 : ScBaseCell* Clone( ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags = SC_CLONECELL_DEFAULT ) const;
93 :
94 : /** Due to the fact that ScBaseCell does not have a vtable, this function
95 : deletes the cell by calling the appropriate d'tor of the derived class. */
96 : void Delete();
97 :
98 119195 : inline CellType GetCellType() const { return (CellType)eCellType; }
99 :
100 : /** Returns true, if the cell is empty (neither value nor formula nor cell note).
101 : Returns false for formula cells returning nothing, use HasEmptyData() for that. */
102 : bool IsBlank() const;
103 :
104 : // for idle-calculations
105 78 : inline sal_uInt16 GetTextWidth() const { return nTextWidth; }
106 1145 : inline void SetTextWidth( sal_uInt16 nNew ) { nTextWidth = nNew; }
107 :
108 12615 : inline sal_uInt8 GetScriptType() const { return nScriptType; }
109 4788 : inline void SetScriptType( sal_uInt8 nNew ) { nScriptType = nNew; }
110 :
111 : /** Returns true, if the cell contains a broadcaster. */
112 48 : inline bool HasBroadcaster() const { return mpBroadcaster != 0; }
113 : /** Returns the pointer to the cell broadcaster. */
114 7557 : inline SvtBroadcaster* GetBroadcaster() const { return mpBroadcaster; }
115 : /** Takes ownership of the passed cell broadcaster. */
116 : void TakeBroadcaster( SvtBroadcaster* pBroadcaster );
117 : /** Returns and forgets the own cell broadcaster. Caller takes ownership! */
118 : SvtBroadcaster* ReleaseBroadcaster();
119 : /** Deletes the own cell broadcaster. */
120 : void DeleteBroadcaster();
121 :
122 : // String- oder EditCell
123 : static ScBaseCell* CreateTextCell( const rtl::OUString& rString, ScDocument* );
124 :
125 : // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
126 : void StartListeningTo( ScDocument* pDoc );
127 : void EndListeningTo( ScDocument* pDoc,
128 : ScTokenArray* pArr = NULL,
129 : ScAddress aPos = ScAddress() );
130 :
131 : /** Error code if ScFormulaCell, else 0. */
132 : sal_uInt16 GetErrorCode() const;
133 : /** ScFormulaCell with formula::svEmptyCell result, or ScNoteCell (may have been
134 : created due to reference to empty cell). */
135 : bool HasEmptyData() const;
136 : bool HasValueData() const;
137 : bool HasStringData() const;
138 : rtl::OUString GetStringData() const; // only real strings
139 :
140 : static bool CellEqual( const ScBaseCell* pCell1, const ScBaseCell* pCell2 );
141 :
142 : private:
143 : ScBaseCell& operator=( const ScBaseCell& );
144 :
145 : private:
146 : SvtBroadcaster* mpBroadcaster; /// Broadcaster for changed values. Cell takes ownership!
147 :
148 : protected:
149 : sal_uInt16 nTextWidth;
150 : sal_uInt8 eCellType; // enum CellType - sal_uInt8 spart Speicher
151 : sal_uInt8 nScriptType;
152 : };
153 :
154 : // ============================================================================
155 :
156 184 : class SC_DLLPUBLIC ScNoteCell : public ScBaseCell
157 : {
158 : public:
159 : #ifdef USE_MEMPOOL
160 385 : DECL_FIXEDMEMPOOL_NEWDEL( ScNoteCell )
161 : #endif
162 :
163 : /** Cell takes ownership of the passed broadcaster. */
164 : explicit ScNoteCell( SvtBroadcaster* pBC = 0 );
165 :
166 : #if OSL_DEBUG_LEVEL > 0
167 : ~ScNoteCell();
168 : #endif
169 :
170 : private:
171 : ScNoteCell( const ScNoteCell& );
172 : };
173 :
174 18136 : class SC_DLLPUBLIC ScValueCell : public ScBaseCell
175 : {
176 : public:
177 : #ifdef USE_MEMPOOL
178 36927 : DECL_FIXEDMEMPOOL_NEWDEL( ScValueCell )
179 : #endif
180 :
181 : explicit ScValueCell( double fValue );
182 :
183 : #if OSL_DEBUG_LEVEL > 0
184 : ~ScValueCell();
185 : #endif
186 :
187 0 : inline void SetValue( double fValue ) { mfValue = fValue; }
188 13125 : inline double GetValue() const { return mfValue; }
189 :
190 : private:
191 : double mfValue;
192 : };
193 :
194 12142 : class SC_DLLPUBLIC ScStringCell : public ScBaseCell
195 : {
196 : public:
197 : #ifdef USE_MEMPOOL
198 24487 : DECL_FIXEDMEMPOOL_NEWDEL( ScStringCell )
199 : #endif
200 :
201 : explicit ScStringCell(const rtl::OUString& rString);
202 :
203 : #if OSL_DEBUG_LEVEL > 0
204 : ~ScStringCell();
205 : #endif
206 :
207 : inline void SetString( const rtl::OUString& rString ) { maString = rString; }
208 4022 : inline const rtl::OUString& GetString() const { return maString; }
209 :
210 : private:
211 : rtl::OUString maString;
212 : };
213 :
214 : class SC_DLLPUBLIC ScEditCell : public ScBaseCell
215 : {
216 : private:
217 : EditTextObject* pData;
218 : mutable rtl::OUString* pString; // for faster access to formulas
219 : ScDocument* pDoc; // for EditEngine access with Pool
220 :
221 : void SetTextObject( const EditTextObject* pObject,
222 : const SfxItemPool* pFromPool );
223 :
224 : // not implemented
225 : ScEditCell( const ScEditCell& );
226 :
227 : public:
228 :
229 : #ifdef USE_MEMPOOL
230 168 : DECL_FIXEDMEMPOOL_NEWDEL( ScEditCell )
231 : #endif
232 :
233 : ~ScEditCell(); // always because of pData!
234 :
235 : ScEditCell( const EditTextObject* pObject, ScDocument*,
236 : const SfxItemPool* pFromPool /* = NULL */ );
237 : ScEditCell(const ScEditCell& rCell, ScDocument& rDoc, const ScAddress& rDestPos);
238 : // for line breaks
239 : ScEditCell( const rtl::OUString& rString, ScDocument* );
240 :
241 : void SetData( const EditTextObject* pObject,
242 : const SfxItemPool* pFromPool /* = NULL */ );
243 : void GetData( const EditTextObject*& rpObject ) const;
244 : rtl::OUString GetString() const;
245 :
246 16 : const EditTextObject* GetData() const { return pData; }
247 :
248 : /** Removes character attribute based on new pattern attributes. */
249 : void RemoveCharAttribs( const ScPatternAttr& rAttr );
250 :
251 : /** Update field items if any. */
252 : void UpdateFields(SCTAB nTab);
253 : };
254 :
255 : class ScEditDataArray
256 : {
257 : public:
258 0 : class Item
259 : {
260 : public:
261 : explicit Item(SCTAB nTab, SCCOL nCol, SCROW nRow,
262 : EditTextObject* pOldData, EditTextObject* pNewData);
263 : ~Item();
264 :
265 : const EditTextObject* GetOldData() const;
266 : const EditTextObject* GetNewData() const;
267 : SCTAB GetTab() const;
268 : SCCOL GetCol() const;
269 : SCROW GetRow() const;
270 :
271 : private:
272 : Item(); // disabled
273 :
274 : private:
275 : ::boost::shared_ptr<EditTextObject> mpOldData;
276 : ::boost::shared_ptr<EditTextObject> mpNewData;
277 : SCTAB mnTab;
278 : SCCOL mnCol;
279 : SCROW mnRow;
280 :
281 : };
282 :
283 : ScEditDataArray();
284 : ~ScEditDataArray();
285 :
286 : void AddItem(SCTAB nTab, SCCOL nCol, SCROW nRow,
287 : EditTextObject* pOldData, EditTextObject* pNewData);
288 :
289 : const Item* First();
290 : const Item* Next();
291 :
292 : private:
293 : ::std::vector<Item>::const_iterator maIter;
294 : ::std::vector<Item> maArray;
295 : };
296 :
297 : enum ScMatrixMode {
298 : MM_NONE = 0, // No matrix formula
299 : MM_FORMULA = 1, // Upper left matrix formula cell
300 : MM_REFERENCE = 2, // Remaining cells, via ocMatRef reference token
301 : MM_FAKE = 3 // Interpret "as-if" matrix formula (legacy)
302 : };
303 :
304 : class SC_DLLPUBLIC ScFormulaCell : public ScBaseCell, public SvtListener
305 : {
306 : private:
307 : ScFormulaResult aResult;
308 : formula::FormulaGrammar::Grammar eTempGrammar; // used between string (creation) and (re)compilation
309 : ScTokenArray* pCode; // The (new) token array
310 : ScDocument* pDocument;
311 : ScFormulaCell* pPrevious;
312 : ScFormulaCell* pNext;
313 : ScFormulaCell* pPreviousTrack;
314 : ScFormulaCell* pNextTrack;
315 : sal_uLong nFormatIndex; // Number format set by calculation
316 : short nFormatType; // Number format type set by calculation
317 : sal_uInt16 nSeenInIteration; // Iteration cycle in which the cell was last encountered
318 : sal_uInt8 cMatrixFlag; // One of ScMatrixMode
319 : bool bDirty : 1; // Must be (re)calculated
320 : bool bChanged : 1; // Whether something changed regarding display/representation
321 : bool bRunning : 1; // Already interpreting right now
322 : bool bCompile : 1; // Must be (re)compiled
323 : bool bSubTotal : 1; // Cell is part of or contains a SubTotal
324 : bool bIsIterCell : 1; // Cell is part of a circular reference
325 : bool bInChangeTrack : 1; // Cell is in ChangeTrack
326 : bool bTableOpDirty : 1; // Dirty flag for TableOp
327 : bool bNeedListening : 1; // Listeners need to be re-established after UpdateReference
328 :
329 : enum ScInterpretTailParameter
330 : {
331 : SCITP_NORMAL,
332 : SCITP_FROM_ITERATION,
333 : SCITP_CLOSE_ITERATION_CIRCLE
334 : };
335 : void InterpretTail( ScInterpretTailParameter );
336 :
337 : ScFormulaCell( const ScFormulaCell& );
338 :
339 : public:
340 :
341 : #ifdef USE_MEMPOOL
342 6134 : DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
343 : #endif
344 :
345 : ScAddress aPos;
346 :
347 : ~ScFormulaCell();
348 :
349 : /** Empty formula cell, or with a preconstructed token array. */
350 : ScFormulaCell( ScDocument*, const ScAddress&, const ScTokenArray* = NULL,
351 : const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
352 : sal_uInt8 = MM_NONE );
353 :
354 : /** With formula string and grammar to compile with.
355 : formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that
356 : also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefor uses the address
357 : convention associated with rPos::nTab by default. */
358 : ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
359 : const rtl::OUString& rFormula,
360 : const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
361 : sal_uInt8 cMatInd = MM_NONE );
362 :
363 : ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags = SC_CLONECELL_DEFAULT );
364 :
365 : void GetFormula( rtl::OUString& rFormula,
366 : const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
367 : void GetFormula( rtl::OUStringBuffer& rBuffer,
368 : const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
369 :
370 : void SetDirty( bool bDirtyFlag=true );
371 : void SetDirtyVar();
372 : // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
373 : void SetDirtyAfterLoad();
374 0 : inline void ResetTableOpDirtyVar() { bTableOpDirty = false; }
375 : void SetTableOpDirty();
376 : bool IsDirtyOrInTableOpDirty() const;
377 110 : bool GetDirty() const { return bDirty; }
378 427 : void ResetDirty() { bDirty = false; }
379 4 : bool NeedsListening() const { return bNeedListening; }
380 3134 : void SetNeedsListening( bool bVar ) { bNeedListening = bVar; }
381 : void Compile(const rtl::OUString& rFormula,
382 : bool bNoListening = false,
383 : const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT );
384 : void CompileTokenArray( bool bNoListening = false );
385 : void CompileXML( ScProgress& rProgress ); // compile temporary string tokens
386 : void CalcAfterLoad();
387 : bool MarkUsedExternalReferences();
388 : void Interpret();
389 0 : inline bool IsIterCell() const { return bIsIterCell; }
390 0 : inline sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; }
391 :
392 : bool HasOneReference( ScRange& r ) const;
393 : /* Checks if the formula contains reference list that can be
394 : expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
395 : reference list is not required to be sorted (i.e. A3;A1;A2 is
396 : still recognized as A1:A3), but no overlapping is allowed.
397 : If one reference is recognized, the rRange is filled.
398 :
399 : It is similar to HasOneReference(), but more general.
400 : */
401 : bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
402 : bool HasRelNameReference() const;
403 : bool HasColRowName() const;
404 :
405 : bool UpdateReference(UpdateRefMode eUpdateRefMode,
406 : const ScRange& r,
407 : SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
408 : ScDocument* pUndoDoc = NULL,
409 : const ScAddress* pUndoCellPos = NULL );
410 :
411 : void TransposeReference();
412 : void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
413 : ScDocument* pUndoDoc );
414 :
415 : void UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
416 :
417 : void UpdateInsertTab(SCTAB nTable, SCTAB nNewSheets = 1);
418 : void UpdateInsertTabAbs(SCTAB nTable);
419 : bool UpdateDeleteTab(SCTAB nTable, bool bIsMove = false, SCTAB nSheets = 1);
420 : void UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo);
421 : void UpdateRenameTab(SCTAB nTable, const rtl::OUString& rName);
422 : bool TestTabRefAbs(SCTAB nTable);
423 : void UpdateCompile( bool bForceIfNameInUse = false );
424 : void FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const;
425 0 : bool IsSubTotal() const { return bSubTotal; }
426 : bool IsChanged() const;
427 : void ResetChanged();
428 : bool IsEmpty(); // formula::svEmptyCell result
429 : // display as empty string if formula::svEmptyCell result
430 : bool IsEmptyDisplayedAsString();
431 : bool IsValue(); // also true if formula::svEmptyCell
432 : double GetValue();
433 : double GetValueAlways(); // ignore errors
434 : rtl::OUString GetString();
435 : const ScMatrix* GetMatrix();
436 : bool GetMatrixOrigin( ScAddress& rPos ) const;
437 : void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
438 : sal_uInt16 GetMatrixEdge( ScAddress& rOrgPos );
439 : sal_uInt16 GetErrCode(); // interpret first if necessary
440 : sal_uInt16 GetRawError(); // don't interpret, just return code or result error
441 0 : short GetFormatType() const { return nFormatType; }
442 : sal_uLong GetFormatIndex() const { return nFormatIndex; }
443 487 : void GetFormatInfo( short& nType, sal_uLong& nIndex ) const
444 487 : { nType = nFormatType; nIndex = nFormatIndex; }
445 3010 : sal_uInt8 GetMatrixFlag() const { return cMatrixFlag; }
446 9679 : ScTokenArray* GetCode() const { return pCode; }
447 :
448 13 : bool IsRunning() const { return bRunning; }
449 0 : void SetRunning( bool bVal ) { bRunning = bVal; }
450 : void CompileDBFormula();
451 : void CompileDBFormula( bool bCreateFormulaString );
452 : void CompileNameFormula( bool bCreateFormulaString );
453 : void CompileColRowNameFormula();
454 13329 : ScFormulaCell* GetPrevious() const { return pPrevious; }
455 2961 : ScFormulaCell* GetNext() const { return pNext; }
456 8431 : void SetPrevious( ScFormulaCell* pF ) { pPrevious = pF; }
457 10500 : void SetNext( ScFormulaCell* pF ) { pNext = pF; }
458 915 : ScFormulaCell* GetPreviousTrack() const { return pPreviousTrack; }
459 1182 : ScFormulaCell* GetNextTrack() const { return pNextTrack; }
460 869 : void SetPreviousTrack( ScFormulaCell* pF ) { pPreviousTrack = pF; }
461 869 : void SetNextTrack( ScFormulaCell* pF ) { pNextTrack = pF; }
462 :
463 : virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
464 1 : void SetCompile( bool bVal ) { bCompile = bVal; }
465 534 : ScDocument* GetDocument() const { return pDocument; }
466 : void SetMatColsRows( SCCOL nCols, SCROW nRows, bool bDirtyFlag=true );
467 : void GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
468 :
469 : // cell belongs to ChangeTrack and not to the real document
470 0 : void SetInChangeTrack( bool bVal ) { bInChangeTrack = bVal; }
471 3570 : bool IsInChangeTrack() const { return bInChangeTrack; }
472 :
473 : // standard format for type and format
474 : // for format "Standard" possibly the format used in the formula cell
475 : sal_uLong GetStandardFormat( SvNumberFormatter& rFormatter, sal_uLong nFormat ) const;
476 :
477 : // For import filters!
478 : void AddRecalcMode( formula::ScRecalcMode );
479 : /** For import only: set a double result. */
480 369 : void SetHybridDouble( double n ) { aResult.SetHybridDouble( n); }
481 : /** For import only: set a string result.
482 : If for whatever reason you have to use both, SetHybridDouble() and
483 : SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
484 : for performance reasons.*/
485 56 : void SetHybridString( const rtl::OUString& r )
486 56 : { aResult.SetHybridString( r); }
487 : /** For import only: set a temporary formula string to be compiled later.
488 : If for whatever reason you have to use both, SetHybridDouble() and
489 : SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
490 : for performance reasons.*/
491 0 : void SetHybridFormula( const rtl::OUString& r,
492 : const formula::FormulaGrammar::Grammar eGrammar )
493 0 : { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; }
494 :
495 : /** For import only: set a double result.
496 : Use this instead of SetHybridDouble() if there is no (temporary)
497 : formula string because the formula is present as a token array, as it
498 : is the case for binary Excel import.
499 : */
500 2425 : void SetResultDouble( double n ) { aResult.SetDouble( n); }
501 :
502 : void SetErrCode( sal_uInt16 n );
503 0 : inline bool IsHyperLinkCell() const { return pCode && pCode->IsHyperLink(); }
504 : EditTextObject* CreateURLObject() ;
505 : void GetURLResult( rtl::OUString& rURL, rtl::OUString& rCellText );
506 :
507 : /** Determines whether or not the result string contains more than one paragraph */
508 : bool IsMultilineResult();
509 :
510 : void MaybeInterpret();
511 : };
512 :
513 : // Iterator for references in a formula cell
514 : class ScDetectiveRefIter
515 : {
516 : private:
517 : ScTokenArray* pCode;
518 : ScAddress aPos;
519 : public:
520 : ScDetectiveRefIter( ScFormulaCell* pCell );
521 : bool GetNextRef( ScRange& rRange );
522 : ScToken* GetNextRefToken();
523 : };
524 :
525 : #endif
526 :
527 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|