1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_SC_INC_FORMULACELL_HXX
21 #define INCLUDED_SC_INC_FORMULACELL_HXX
25 #include <boost/noncopyable.hpp>
27 #include <formula/tokenarray.hxx>
28 #include <osl/conditn.hxx>
29 #include <osl/mutex.hxx>
30 #include <rtl/ref.hxx>
31 #include <svl/listener.hxx>
35 #include "formularesult.hxx"
37 #define ENABLE_THREADED_OPENCL_KERNEL_COMPILATION 0
41 class CLBuildKernelThread
;
42 class CompiledFormula
;
43 class StartListeningContext
;
44 class EndListeningContext
;
45 struct RefUpdateContext
;
46 struct RefUpdateInsertTabContext
;
47 struct RefUpdateDeleteTabContext
;
48 struct RefUpdateMoveTabContext
;
49 class CompileFormulaContext
;
56 struct ScSimilarFormulaDelta
;
58 struct SC_DLLPUBLIC ScFormulaCellGroup
: boost::noncopyable
60 mutable size_t mnRefCount
;
63 sc::CompiledFormula
* mpCompiledFormula
;
64 ScFormulaCell
*mpTopCell
;
65 SCROW mnLength
; // How many of these do we have ?
70 sal_uInt8 meCalcState
;
71 sal_uInt8 meKernelState
;
74 ~ScFormulaCellGroup();
76 void scheduleCompilation();
78 void setCode( const ScTokenArray
& rCode
);
79 void setCode( ScTokenArray
* pCode
);
81 ScDocument
& rDoc
, const ScAddress
& rPos
, formula::FormulaGrammar::Grammar eGram
);
82 void compileOpenCLKernel();
84 #if ENABLE_THREADED_OPENCL_KERNEL_COMPILATION
86 static rtl::Reference
<sc::CLBuildKernelThread
> sxCompilationThread
;
90 inline void intrusive_ptr_add_ref(const ScFormulaCellGroup
*p
)
95 inline void intrusive_ptr_release(const ScFormulaCellGroup
*p
)
97 if( --p
->mnRefCount
== 0 )
102 MM_NONE
= 0, // No matrix formula
103 MM_FORMULA
= 1, // Upper left matrix formula cell
104 MM_REFERENCE
= 2, // Remaining cells, via ocMatRef reference token
105 MM_FAKE
= 3 // Interpret "as-if" matrix formula (legacy)
108 class SC_DLLPUBLIC ScFormulaCell
: public SvtListener
111 ScFormulaCellGroupRef mxGroup
; // re-factoring hack - group of formulae we're part of.
112 ScFormulaResult aResult
;
113 formula::FormulaGrammar::Grammar eTempGrammar
; // used between string (creation) and (re)compilation
114 ScTokenArray
* pCode
; // The (new) token array
115 ScDocument
* pDocument
;
116 ScFormulaCell
* pPrevious
;
117 ScFormulaCell
* pNext
;
118 ScFormulaCell
* pPreviousTrack
;
119 ScFormulaCell
* pNextTrack
;
120 sal_uInt16 nSeenInIteration
; // Iteration cycle in which the cell was last encountered
121 sal_uInt8 cMatrixFlag
; // One of ScMatrixMode
123 bool bDirty
: 1; // Must be (re)calculated
124 bool bChanged
: 1; // Whether something changed regarding display/representation
125 bool bRunning
: 1; // Already interpreting right now
126 bool bCompile
: 1; // Must be (re)compiled
127 bool bSubTotal
: 1; // Cell is part of or contains a SubTotal
128 bool bIsIterCell
: 1; // Cell is part of a circular reference
129 bool bInChangeTrack
: 1; // Cell is in ChangeTrack
130 bool bTableOpDirty
: 1; // Dirty flag for TableOp
131 bool bNeedListening
: 1; // Listeners need to be re-established after UpdateReference
132 bool mbNeedsNumberFormat
: 1; // set the calculated number format as hard number format
133 bool mbPostponedDirty
: 1; // if cell needs to be set dirty later
135 enum ScInterpretTailParameter
138 SCITP_FROM_ITERATION
,
139 SCITP_CLOSE_ITERATION_CIRCLE
141 void InterpretTail( ScInterpretTailParameter
);
144 * Update reference in response to cell copy-n-paste.
146 bool UpdateReferenceOnCopy(
147 const sc::RefUpdateContext
& rCxt
, ScDocument
* pUndoDoc
, const ScAddress
* pUndoCellPos
);
149 ScFormulaCell( const ScFormulaCell
& );
152 enum CompareState
{ NotEqual
= 0, EqualInvariant
, EqualRelativeRef
};
155 DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell
)
160 virtual ~ScFormulaCell();
162 ScFormulaCell
* Clone() const;
163 ScFormulaCell
* Clone( const ScAddress
& rPos
, int nCloneFlags
) const;
165 ScFormulaCell( ScDocument
* pDoc
, const ScAddress
& rPos
);
168 * Transfer the ownership of the passed token array instance to the
169 * formula cell being constructed. The caller <i>must not</i> pass a NULL
170 * token array pointer.
172 ScFormulaCell( ScDocument
* pDoc
, const ScAddress
& rPos
, ScTokenArray
* pArray
,
173 const formula::FormulaGrammar::Grammar eGrammar
= formula::FormulaGrammar::GRAM_DEFAULT
,
174 sal_uInt8 cMatInd
= MM_NONE
);
176 ScFormulaCell( ScDocument
* pDoc
, const ScAddress
& rPos
, const ScTokenArray
& rArray
,
177 const formula::FormulaGrammar::Grammar eGrammar
= formula::FormulaGrammar::GRAM_DEFAULT
,
178 sal_uInt8 cMatInd
= MM_NONE
);
180 ScFormulaCell( ScDocument
* pDoc
, const ScAddress
& rPos
, const ScFormulaCellGroupRef
& xGroup
,
181 const formula::FormulaGrammar::Grammar
= formula::FormulaGrammar::GRAM_DEFAULT
,
182 sal_uInt8
= MM_NONE
);
184 /** With formula string and grammar to compile with.
185 formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that
186 also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefor uses the address
187 convention associated with rPos::nTab by default. */
188 ScFormulaCell( ScDocument
* pDoc
, const ScAddress
& rPos
,
189 const OUString
& rFormula
,
190 const formula::FormulaGrammar::Grammar
= formula::FormulaGrammar::GRAM_DEFAULT
,
191 sal_uInt8 cMatInd
= MM_NONE
);
193 ScFormulaCell( const ScFormulaCell
& rCell
, ScDocument
& rDoc
, const ScAddress
& rPos
, int nCloneFlags
= SC_CLONECELL_DEFAULT
);
195 size_t GetHash() const;
197 ScFormulaVectorState
GetVectorState() const;
199 void GetFormula( OUString
& rFormula
,
200 const formula::FormulaGrammar::Grammar
= formula::FormulaGrammar::GRAM_DEFAULT
) const;
201 void GetFormula( OUStringBuffer
& rBuffer
,
202 const formula::FormulaGrammar::Grammar
= formula::FormulaGrammar::GRAM_DEFAULT
) const;
204 OUString
GetFormula( sc::CompileFormulaContext
& rCxt
) const;
206 void SetDirty( bool bDirtyFlag
=true );
208 // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
209 void SetDirtyAfterLoad();
210 void ResetTableOpDirtyVar();
211 void SetTableOpDirty();
212 bool IsDirtyOrInTableOpDirty() const;
213 bool GetDirty() const;
215 bool NeedsListening() const;
216 void SetNeedsListening( bool bVar
);
217 void SetNeedsDirty( bool bVar
);
218 void SetNeedNumberFormat( bool bVal
);
219 bool NeedsNumberFormat() const;
220 short GetFormatType() const;
221 void Compile(const OUString
& rFormula
,
222 bool bNoListening
= false,
223 const formula::FormulaGrammar::Grammar
= formula::FormulaGrammar::GRAM_DEFAULT
);
225 sc::CompileFormulaContext
& rCxt
, const OUString
& rFormula
, bool bNoListening
= false );
227 void CompileTokenArray( bool bNoListening
= false );
228 void CompileTokenArray( sc::CompileFormulaContext
& rCxt
, bool bNoListening
= false );
229 void CompileXML( sc::CompileFormulaContext
& rCxt
, ScProgress
& rProgress
); // compile temporary string tokens
230 void CalcAfterLoad( sc::CompileFormulaContext
& rCxt
);
231 bool MarkUsedExternalReferences();
233 bool IsIterCell() const;
234 sal_uInt16
GetSeenInIteration() const;
236 bool HasOneReference( ScRange
& r
) const;
237 /* Checks if the formula contains reference list that can be
238 expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
239 reference list is not required to be sorted (i.e. A3;A1;A2 is
240 still recognized as A1:A3), but no overlapping is allowed.
241 If one reference is recognized, the rRange is filled.
243 It is similar to HasOneReference(), but more general.
245 bool HasRefListExpressibleAsOneReference(ScRange
& rRange
) const;
246 bool HasRelNameReference() const;
248 bool UpdateReference(
249 const sc::RefUpdateContext
& rCxt
, ScDocument
* pUndoDoc
= NULL
, const ScAddress
* pUndoCellPos
= NULL
);
252 * Shift the position of formula cell as part of reference update.
254 * @return true if the position has shifted, false otherwise.
256 bool UpdatePosOnShift( const sc::RefUpdateContext
& rCxt
);
259 * Update reference in response to cell insertion or deletion.
261 bool UpdateReferenceOnShift(
262 const sc::RefUpdateContext
& rCxt
, ScDocument
* pUndoDoc
, const ScAddress
* pUndoCellPos
);
265 * Update reference in response to cell move.
267 bool UpdateReferenceOnMove(
268 const sc::RefUpdateContext
& rCxt
, ScDocument
* pUndoDoc
, const ScAddress
* pUndoCellPos
);
270 void TransposeReference();
271 void UpdateTranspose( const ScRange
& rSource
, const ScAddress
& rDest
,
272 ScDocument
* pUndoDoc
);
274 void UpdateGrow( const ScRange
& rArea
, SCCOL nGrowX
, SCROW nGrowY
);
276 void UpdateInsertTab( sc::RefUpdateInsertTabContext
& rCxt
);
277 void UpdateInsertTabAbs(SCTAB nTable
);
278 bool UpdateDeleteTab( sc::RefUpdateDeleteTabContext
& rCxt
);
279 void UpdateMoveTab( sc::RefUpdateMoveTabContext
& rCxt
, SCTAB nTabNo
);
280 void UpdateRenameTab(SCTAB nTable
, const OUString
& rName
);
281 bool TestTabRefAbs(SCTAB nTable
);
282 void UpdateCompile( bool bForceIfNameInUse
= false );
283 void FindRangeNamesInUse(std::set
<sal_uInt16
>& rIndexes
) const;
284 bool IsSubTotal() const;
285 bool IsChanged() const;
286 void SetChanged(bool b
);
287 bool IsEmpty(); // formula::svEmptyCell result
288 // display as empty string if formula::svEmptyCell result
289 bool IsEmptyDisplayedAsString();
290 bool IsValue(); // also true if formula::svEmptyCell
291 bool IsValueNoError();
292 bool IsHybridValueCell(); // for cells after import to deal with inherited number formats
294 svl::SharedString
GetString();
295 const ScMatrix
* GetMatrix();
296 bool GetMatrixOrigin( ScAddress
& rPos
) const;
297 void GetResultDimensions( SCSIZE
& rCols
, SCSIZE
& rRows
);
298 sal_uInt16
GetMatrixEdge( ScAddress
& rOrgPos
) const;
299 sal_uInt16
GetErrCode(); // interpret first if necessary
300 sal_uInt16
GetRawError(); // don't interpret, just return code or result error
301 bool GetErrorOrValue( sal_uInt16
& rErr
, double& rVal
);
302 sc::FormulaResultValue
GetResult();
303 sal_uInt8
GetMatrixFlag() const;
304 ScTokenArray
* GetCode();
305 const ScTokenArray
* GetCode() const;
307 void SetCode( ScTokenArray
* pNew
);
309 bool IsRunning() const;
310 void SetRunning( bool bVal
);
311 void CompileDBFormula( sc::CompileFormulaContext
& rCxt
);
312 void CompileColRowNameFormula( sc::CompileFormulaContext
& rCxt
);
313 ScFormulaCell
* GetPrevious() const;
314 ScFormulaCell
* GetNext() const;
315 void SetPrevious( ScFormulaCell
* pF
);
316 void SetNext( ScFormulaCell
* pF
);
317 ScFormulaCell
* GetPreviousTrack() const;
318 ScFormulaCell
* GetNextTrack() const;
319 void SetPreviousTrack( ScFormulaCell
* pF
);
320 void SetNextTrack( ScFormulaCell
* pF
);
322 virtual void Notify( const SfxHint
& rHint
) SAL_OVERRIDE
;
323 virtual void Query( SvtListener::QueryBase
& rQuery
) const SAL_OVERRIDE
;
325 void SetCompile( bool bVal
);
326 ScDocument
* GetDocument() const;
327 void SetMatColsRows( SCCOL nCols
, SCROW nRows
, bool bDirtyFlag
=true );
328 void GetMatColsRows( SCCOL
& nCols
, SCROW
& nRows
) const;
330 // cell belongs to ChangeTrack and not to the real document
331 void SetInChangeTrack( bool bVal
);
332 bool IsInChangeTrack() const;
334 // For import filters!
335 void AddRecalcMode( formula::ScRecalcMode
);
336 /** For import only: set a double result. */
337 void SetHybridDouble( double n
);
338 /** For import only: set a string result.
339 If for whatever reason you have to use both, SetHybridDouble() and
340 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
341 for performance reasons.*/
342 void SetHybridString( const svl::SharedString
& r
);
343 /** For import only: set a temporary formula string to be compiled later.
344 If for whatever reason you have to use both, SetHybridDouble() and
345 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
346 for performance reasons.*/
347 void SetHybridFormula(
348 const OUString
& r
, const formula::FormulaGrammar::Grammar eGrammar
);
350 OUString
GetHybridFormula() const;
352 void SetResultMatrix( SCCOL nCols
, SCROW nRows
, const ScConstMatrixRef
& pMat
, formula::FormulaToken
* pUL
);
354 /** For import only: set a double result.
355 Use this instead of SetHybridDouble() if there is no (temporary)
356 formula string because the formula is present as a token array, as it
357 is the case for binary Excel import.
359 void SetResultDouble( double n
);
361 void SetResultToken( const formula::FormulaToken
* pToken
);
363 svl::SharedString
GetResultString() const;
365 void SetErrCode( sal_uInt16 n
);
366 bool IsHyperLinkCell() const;
367 EditTextObject
* CreateURLObject();
368 void GetURLResult( OUString
& rURL
, OUString
& rCellText
);
370 /** Determines whether or not the result string contains more than one paragraph */
371 bool IsMultilineResult();
373 void MaybeInterpret();
376 * Turn a non-grouped cell into the top of a grouped cell.
378 ScFormulaCellGroupRef
CreateCellGroup( SCROW nLen
, bool bInvariant
);
379 ScFormulaCellGroupRef
GetCellGroup();
380 void SetCellGroup( const ScFormulaCellGroupRef
&xRef
);
382 CompareState
CompareByTokenArray( ScFormulaCell
& rOther
) const;
384 bool InterpretFormulaGroup();
385 bool InterpretInvariantFormulaGroup();
387 // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
388 void StartListeningTo( ScDocument
* pDoc
);
389 void StartListeningTo( sc::StartListeningContext
& rCxt
);
391 ScDocument
* pDoc
, ScTokenArray
* pArr
= NULL
, ScAddress aPos
= ScAddress() );
392 void EndListeningTo( sc::EndListeningContext
& rCxt
);
394 bool IsShared() const;
395 bool IsSharedTop() const;
396 SCROW
GetSharedTopRow() const;
397 SCROW
GetSharedLength() const;
398 ScTokenArray
* GetSharedCode();
399 const ScTokenArray
* GetSharedCode() const;
401 void SyncSharedCode();
403 bool IsPostponedDirty() const;
408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */