LCOV - code coverage report
Current view: top level - sc/inc - formulacell.hxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 26 28 92.9 %
Date: 2015-06-13 12:38:46 Functions: 21 23 91.3 %
Legend: Lines: hit not hit

          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 INCLUDED_SC_INC_FORMULACELL_HXX
      21             : #define INCLUDED_SC_INC_FORMULACELL_HXX
      22             : 
      23             : #include <set>
      24             : 
      25             : #include <boost/noncopyable.hpp>
      26             : 
      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>
      32             : 
      33             : #include "types.hxx"
      34             : 
      35             : #include "formularesult.hxx"
      36             : 
      37             : #define ENABLE_THREADED_OPENCL_KERNEL_COMPILATION 0
      38             : 
      39             : namespace sc {
      40             : 
      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;
      50             : class FormulaGroupAreaListener;
      51             : 
      52             : }
      53             : 
      54             : class ScFormulaCell;
      55             : class ScProgress;
      56             : class ScTokenArray;
      57             : 
      58             : struct SC_DLLPUBLIC ScFormulaCellGroup : boost::noncopyable
      59             : {
      60             : private:
      61             :     struct Impl;
      62             :     Impl* mpImpl;
      63             : 
      64             : public:
      65             : 
      66             :     mutable size_t mnRefCount;
      67             : 
      68             :     ScTokenArray* mpCode;
      69             :     sc::CompiledFormula* mpCompiledFormula;
      70             :     ScFormulaCell *mpTopCell;
      71             :     SCROW mnLength; // How many of these do we have ?
      72             :     short mnFormatType;
      73             :     bool mbInvariant:1;
      74             :     bool mbSubTotal:1;
      75             : 
      76             :     sal_uInt8 meCalcState;
      77             :     sal_uInt8 meKernelState;
      78             : 
      79             :     ScFormulaCellGroup();
      80             :     ~ScFormulaCellGroup();
      81             : #if ENABLE_THREADED_OPENCL_KERNEL_COMPILATION
      82             :     void scheduleCompilation();
      83             : #endif
      84             : 
      85             :     void setCode( const ScTokenArray& rCode );
      86             :     void setCode( ScTokenArray* pCode );
      87             :     void compileCode(
      88             :         ScDocument& rDoc, const ScAddress& rPos, formula::FormulaGrammar::Grammar eGram );
      89             :     void compileOpenCLKernel();
      90             : 
      91             :     sc::FormulaGroupAreaListener* getAreaListener(
      92             :         ScFormulaCell** ppTopCell, const ScRange& rRange, bool bStartFixed, bool bEndFixed );
      93             : 
      94             :     void endAllGroupListening( ScDocument& rDoc );
      95             : 
      96             : #if ENABLE_THREADED_OPENCL_KERNEL_COMPILATION
      97             :     static int snCount;
      98             :     static rtl::Reference<sc::CLBuildKernelThread> sxCompilationThread;
      99             : #endif
     100             : };
     101             : 
     102       15309 : inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
     103             : {
     104       15309 :     p->mnRefCount++;
     105       15309 : }
     106             : 
     107       15305 : inline void intrusive_ptr_release(const ScFormulaCellGroup *p)
     108             : {
     109       15305 :     if( --p->mnRefCount == 0 )
     110        1070 :         delete p;
     111       15305 : }
     112             : 
     113             : enum ScMatrixMode {
     114             :     MM_NONE      = 0,                   // No matrix formula
     115             :     MM_FORMULA   = 1,                   // Upper left matrix formula cell
     116             :     MM_REFERENCE = 2,                   // Remaining cells, via ocMatRef reference token
     117             :     MM_FAKE      = 3                    // Interpret "as-if" matrix formula (legacy)
     118             : };
     119             : 
     120             : class SC_DLLPUBLIC ScFormulaCell : public SvtListener
     121             : {
     122             : private:
     123             :     ScFormulaCellGroupRef mxGroup;       // re-factoring hack - group of formulae we're part of.
     124             :     ScFormulaResult aResult;
     125             :     formula::FormulaGrammar::Grammar  eTempGrammar;   // used between string (creation) and (re)compilation
     126             :     ScTokenArray*   pCode;              // The (new) token array
     127             :     ScDocument*     pDocument;
     128             :     ScFormulaCell*  pPrevious;
     129             :     ScFormulaCell*  pNext;
     130             :     ScFormulaCell*  pPreviousTrack;
     131             :     ScFormulaCell*  pNextTrack;
     132             :     sal_uInt16      nSeenInIteration;   // Iteration cycle in which the cell was last encountered
     133             :     short           nFormatType;
     134             :     sal_uInt8       cMatrixFlag    : 2; // One of ScMatrixMode
     135             :     bool            bDirty         : 1; // Must be (re)calculated
     136             :     bool            bChanged       : 1; // Whether something changed regarding display/representation
     137             :     bool            bRunning       : 1; // Already interpreting right now
     138             :     bool            bCompile       : 1; // Must be (re)compiled
     139             :     bool            bSubTotal      : 1; // Cell is part of or contains a SubTotal
     140             :     bool            bIsIterCell    : 1; // Cell is part of a circular reference
     141             :     bool            bInChangeTrack : 1; // Cell is in ChangeTrack
     142             :     bool            bTableOpDirty  : 1; // Dirty flag for TableOp
     143             :     bool            bNeedListening : 1; // Listeners need to be re-established after UpdateReference
     144             :     bool            mbNeedsNumberFormat : 1; // set the calculated number format as hard number format
     145             :     bool            mbPostponedDirty : 1;   // if cell needs to be set dirty later
     146             :     bool            mbIsExtRef       : 1; // has references in ScExternalRefManager; never cleared after set
     147             : 
     148             :                     enum ScInterpretTailParameter
     149             :                     {
     150             :                         SCITP_NORMAL,
     151             :                         SCITP_FROM_ITERATION,
     152             :                         SCITP_CLOSE_ITERATION_CIRCLE
     153             :                     };
     154             :     void            InterpretTail( ScInterpretTailParameter );
     155             : 
     156             :     /**
     157             :      * Update reference in response to cell copy-n-paste.
     158             :      */
     159             :     bool UpdateReferenceOnCopy(
     160             :         const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
     161             : 
     162             :     ScFormulaCell( const ScFormulaCell& ) SAL_DELETED_FUNCTION;
     163             : public:
     164             : 
     165             :     enum CompareState { NotEqual = 0, EqualInvariant, EqualRelativeRef };
     166             : 
     167             : #ifdef USE_MEMPOOL
     168             :     DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
     169             : #endif
     170             : 
     171             :     ScAddress       aPos;
     172             : 
     173             :                     virtual ~ScFormulaCell();
     174             : 
     175             :     ScFormulaCell* Clone() const;
     176             :     ScFormulaCell* Clone( const ScAddress& rPos, int nCloneFlags ) const;
     177             : 
     178             :     ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos );
     179             : 
     180             :     /**
     181             :      * Transfer the ownership of the passed token array instance to the
     182             :      * formula cell being constructed.  The caller <i>must not</i> pass a NULL
     183             :      * token array pointer.
     184             :      */
     185             :     ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, ScTokenArray* pArray,
     186             :                    const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
     187             :                    sal_uInt8 cMatInd = MM_NONE );
     188             : 
     189             :     ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScTokenArray& rArray,
     190             :                    const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
     191             :                    sal_uInt8 cMatInd = MM_NONE );
     192             : 
     193             :     ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup,
     194             :                    const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
     195             :                    sal_uInt8 = MM_NONE );
     196             : 
     197             :     /** With formula string and grammar to compile with.
     198             :        formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that
     199             :         also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefore uses the address
     200             :         convention associated with rPos::nTab by default. */
     201             :     ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
     202             :                     const OUString& rFormula,
     203             :                     const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
     204             :                     sal_uInt8 cMatInd = MM_NONE );
     205             : 
     206             :     ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags = SC_CLONECELL_DEFAULT );
     207             : 
     208             :     size_t GetHash() const;
     209             : 
     210             :     ScFormulaVectorState GetVectorState() const;
     211             : 
     212             :     void            GetFormula( OUString& rFormula,
     213             :                                 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
     214             :     void            GetFormula( OUStringBuffer& rBuffer,
     215             :                                 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
     216             : 
     217             :     OUString GetFormula( sc::CompileFormulaContext& rCxt ) const;
     218             : 
     219             :     void            SetDirty( bool bDirtyFlag=true );
     220             :     void            SetDirtyVar();
     221             :     // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
     222             :     void            SetDirtyAfterLoad();
     223             :     void ResetTableOpDirtyVar();
     224             :     void            SetTableOpDirty();
     225             :     bool            IsDirtyOrInTableOpDirty() const;
     226       12673 :     bool GetDirty() const { return bDirty; }
     227             :     void ResetDirty();
     228         618 :     bool NeedsListening() const { return bNeedListening; }
     229             :     void SetNeedsListening( bool bVar );
     230             :     void SetNeedsDirty( bool bVar );
     231             :     void SetNeedNumberFormat( bool bVal );
     232        1275 :     bool NeedsNumberFormat() const { return mbNeedsNumberFormat;}
     233        1672 :     short GetFormatType() const { return nFormatType; }
     234             :     void            Compile(const OUString& rFormula,
     235             :                             bool bNoListening = false,
     236             :                             const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT );
     237             :     void Compile(
     238             :         sc::CompileFormulaContext& rCxt, const OUString& rFormula, bool bNoListening = false );
     239             : 
     240             :     void CompileTokenArray( bool bNoListening = false );
     241             :     void CompileTokenArray( sc::CompileFormulaContext& rCxt, bool bNoListening = false );
     242             :     void CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress );        // compile temporary string tokens
     243             :     void CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartListening );
     244             :     bool            MarkUsedExternalReferences();
     245             :     void            Interpret();
     246           0 :     bool IsIterCell() const { return bIsIterCell; }
     247           0 :     sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; }
     248             : 
     249             :     bool            HasOneReference( ScRange& r ) const;
     250             :     /* Checks if the formula contains reference list that can be
     251             :        expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
     252             :        reference list is not required to be sorted (i.e. A3;A1;A2 is
     253             :        still recognized as A1:A3), but no overlapping is allowed.
     254             :        If one reference is recognized, the rRange is filled.
     255             : 
     256             :        It is similar to HasOneReference(), but more general.
     257             :      */
     258             :     bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
     259             :     bool            HasRelNameReference() const;
     260             : 
     261             :     bool UpdateReference(
     262             :         const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = NULL, const ScAddress* pUndoCellPos = NULL );
     263             : 
     264             :     /**
     265             :      * Shift the position of formula cell as part of reference update.
     266             :      *
     267             :      * @return true if the position has shifted, false otherwise.
     268             :      */
     269             :     bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
     270             : 
     271             :     /**
     272             :      * Update reference in response to cell insertion or deletion.
     273             :      */
     274             :     bool UpdateReferenceOnShift(
     275             :         const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
     276             : 
     277             :     /**
     278             :      * Update reference in response to cell move.
     279             :      */
     280             :     bool UpdateReferenceOnMove(
     281             :         const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
     282             : 
     283             :     void            TransposeReference();
     284             :     void            UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
     285             :                                         ScDocument* pUndoDoc );
     286             : 
     287             :     void            UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
     288             : 
     289             :     void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt );
     290             :     void            UpdateInsertTabAbs(SCTAB nTable);
     291             :     bool UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt );
     292             :     void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo );
     293             :     void            UpdateRenameTab(SCTAB nTable, const OUString& rName);
     294             :     bool            TestTabRefAbs(SCTAB nTable);
     295             :     void            UpdateCompile( bool bForceIfNameInUse = false );
     296             :     void            FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const;
     297        1533 :     bool IsSubTotal() const { return bSubTotal;}
     298        3980 :     bool            IsChanged() const { return bChanged;}
     299             :     void SetChanged(bool b);
     300             :     bool            IsEmpty();      // formula::svEmptyCell result
     301             :                     // display as empty string if formula::svEmptyCell result
     302             :     bool            IsEmptyDisplayedAsString();
     303             :     bool            IsValue();      // also true if formula::svEmptyCell
     304             :     bool IsValueNoError();
     305             :     bool IsValueNoError() const;
     306             :     bool            IsHybridValueCell(); // for cells after import to deal with inherited number formats
     307             :     double          GetValue();
     308             :     svl::SharedString GetString();
     309             :     const ScMatrix* GetMatrix();
     310             :     bool            GetMatrixOrigin( ScAddress& rPos ) const;
     311             :     void            GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
     312             :     sal_uInt16 GetMatrixEdge( ScAddress& rOrgPos ) const;
     313             :     sal_uInt16      GetErrCode();   // interpret first if necessary
     314             :     sal_uInt16      GetRawError();  // don't interpret, just return code or result error
     315             :     bool GetErrorOrValue( sal_uInt16& rErr, double& rVal );
     316             :     sc::FormulaResultValue GetResult();
     317             :     sc::FormulaResultValue GetResult() const;
     318       22997 :     sal_uInt8       GetMatrixFlag() const { return cMatrixFlag;}
     319      102081 :     ScTokenArray* GetCode() { return pCode;}
     320        2521 :     const ScTokenArray* GetCode() const { return pCode;}
     321             : 
     322             :     void SetCode( ScTokenArray* pNew );
     323             : 
     324       11172 :     bool            IsRunning() const { return bRunning;}
     325             :     void            SetRunning( bool bVal );
     326             :     void CompileDBFormula( sc::CompileFormulaContext& rCxt );
     327             :     void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
     328      158008 :     ScFormulaCell*  GetPrevious() const { return pPrevious; }
     329       29719 :     ScFormulaCell*  GetNext() const { return pNext; }
     330             :     void            SetPrevious( ScFormulaCell* pF );
     331             :     void            SetNext( ScFormulaCell* pF );
     332       66025 :     ScFormulaCell*  GetPreviousTrack() const { return pPreviousTrack; }
     333       73793 :     ScFormulaCell*  GetNextTrack() const { return pNextTrack; }
     334             :     void            SetPreviousTrack( ScFormulaCell* pF );
     335             :     void            SetNextTrack( ScFormulaCell* pF );
     336             : 
     337             :     virtual void Notify( const SfxHint& rHint ) SAL_OVERRIDE;
     338             :     virtual void Query( SvtListener::QueryBase& rQuery ) const SAL_OVERRIDE;
     339             : 
     340             :     void SetCompile( bool bVal );
     341        3763 :     ScDocument* GetDocument() const { return pDocument;}
     342             :     void            SetMatColsRows( SCCOL nCols, SCROW nRows, bool bDirtyFlag=true );
     343             :     void            GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
     344             : 
     345             :                     // cell belongs to ChangeTrack and not to the real document
     346             :     void SetInChangeTrack( bool bVal );
     347       53853 :     bool IsInChangeTrack() const { return bInChangeTrack;}
     348             : 
     349             :     // For import filters!
     350             :     void            AddRecalcMode( ScRecalcMode );
     351             :     /** For import only: set a double result. */
     352             :     void SetHybridDouble( double n );
     353             :     /** For import only: set a string result.
     354             :         If for whatever reason you have to use both, SetHybridDouble() and
     355             :         SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
     356             :         for performance reasons.*/
     357             :     void SetHybridString( const svl::SharedString& r );
     358             :     /** For import only: set a temporary formula string to be compiled later.
     359             :         If for whatever reason you have to use both, SetHybridDouble() and
     360             :         SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
     361             :         for performance reasons.*/
     362             :     void SetHybridFormula(
     363             :         const OUString& r, const formula::FormulaGrammar::Grammar eGrammar );
     364             : 
     365             :     OUString GetHybridFormula() const;
     366             : 
     367             :     void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL );
     368             : 
     369             :     /** For import only: set a double result.
     370             :         Use this instead of SetHybridDouble() if there is no (temporary)
     371             :         formula string because the formula is present as a token array, as it
     372             :         is the case for binary Excel import.
     373             :      */
     374             :     void SetResultDouble( double n );
     375             : 
     376             :     void SetResultToken( const formula::FormulaToken* pToken );
     377             : 
     378             :     svl::SharedString GetResultString() const;
     379             : 
     380             :     /* Sets the shared code array to error state in addition to the cell result */
     381             :     void SetErrCode( sal_uInt16 n );
     382             : 
     383             :     /* Sets just the result to error */
     384             :     void SetResultError( sal_uInt16 n );
     385             : 
     386             :     bool IsHyperLinkCell() const;
     387             :     EditTextObject* CreateURLObject();
     388             :     void GetURLResult( OUString& rURL, OUString& rCellText );
     389             : 
     390             :     /** Determines whether or not the result string contains more than one paragraph */
     391             :     bool            IsMultilineResult();
     392             : 
     393             :     bool NeedsInterpret() const;
     394             : 
     395             :     void            MaybeInterpret();
     396             : 
     397             :     /**
     398             :      * Turn a non-grouped cell into the top of a grouped cell.
     399             :      */
     400             :     ScFormulaCellGroupRef CreateCellGroup( SCROW nLen, bool bInvariant );
     401       12563 :     ScFormulaCellGroupRef GetCellGroup() const { return mxGroup;}
     402             :     void SetCellGroup( const ScFormulaCellGroupRef &xRef );
     403             : 
     404             :     CompareState CompareByTokenArray( ScFormulaCell& rOther ) const;
     405             : 
     406             :     bool InterpretFormulaGroup();
     407             :     bool InterpretInvariantFormulaGroup();
     408             : 
     409             :     // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
     410             :     void StartListeningTo( ScDocument* pDoc );
     411             :     void StartListeningTo( sc::StartListeningContext& rCxt );
     412             :     void EndListeningTo(
     413             :         ScDocument* pDoc, ScTokenArray* pArr = NULL, ScAddress aPos = ScAddress() );
     414             :     void EndListeningTo( sc::EndListeningContext& rCxt );
     415             : 
     416             :     bool IsShared() const;
     417             :     bool IsSharedTop() const;
     418             :     SCROW GetSharedTopRow() const;
     419             :     SCROW GetSharedLength() const;
     420             : 
     421             :     // An estimate of the number of cells referenced by the formula
     422             :     sal_Int32 GetWeight() const;
     423             : 
     424             :     ScTokenArray* GetSharedCode();
     425             :     const ScTokenArray* GetSharedCode() const;
     426             : 
     427             :     void SyncSharedCode();
     428             : 
     429         314 :     bool IsPostponedDirty() const { return mbPostponedDirty;}
     430             : 
     431         247 :     void SetIsExtRef() { mbIsExtRef = true; }
     432             : };
     433             : 
     434             : #endif
     435             : 
     436             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11