xref: /aoo41x/main/sc/inc/formularesult.hxx (revision 38d50f7b)
1*38d50f7bSAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*38d50f7bSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*38d50f7bSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*38d50f7bSAndrew Rist  * distributed with this work for additional information
6*38d50f7bSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*38d50f7bSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*38d50f7bSAndrew Rist  * "License"); you may not use this file except in compliance
9*38d50f7bSAndrew Rist  * with the License.  You may obtain a copy of the License at
10*38d50f7bSAndrew Rist  *
11*38d50f7bSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*38d50f7bSAndrew Rist  *
13*38d50f7bSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*38d50f7bSAndrew Rist  * software distributed under the License is distributed on an
15*38d50f7bSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*38d50f7bSAndrew Rist  * KIND, either express or implied.  See the License for the
17*38d50f7bSAndrew Rist  * specific language governing permissions and limitations
18*38d50f7bSAndrew Rist  * under the License.
19*38d50f7bSAndrew Rist  *
20*38d50f7bSAndrew Rist  *************************************************************/
21*38d50f7bSAndrew Rist 
22*38d50f7bSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir #ifndef SC_FORMULARESULT_HXX
25cdf0e10cSrcweir #define SC_FORMULARESULT_HXX
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include "token.hxx"
28cdf0e10cSrcweir 
29cdf0e10cSrcweir 
30cdf0e10cSrcweir /** Store a variable formula cell result, balancing between runtime performance
31cdf0e10cSrcweir     and memory consumption. */
32cdf0e10cSrcweir class ScFormulaResult
33cdf0e10cSrcweir {
34cdf0e10cSrcweir     typedef unsigned char Multiline;
35cdf0e10cSrcweir     static const Multiline MULTILINE_UNKNOWN = 0;
36cdf0e10cSrcweir     static const Multiline MULTILINE_FALSE   = 1;
37cdf0e10cSrcweir     static const Multiline MULTILINE_TRUE    = 2;
38cdf0e10cSrcweir 
39cdf0e10cSrcweir     union
40cdf0e10cSrcweir     {
41cdf0e10cSrcweir         double          mfValue;    // double result direct for performance and memory consumption
42cdf0e10cSrcweir         const formula::FormulaToken*  mpToken;    // if not, result token obtained from interpreter
43cdf0e10cSrcweir     };
44cdf0e10cSrcweir     sal_uInt16              mnError;    // error code
45cdf0e10cSrcweir     bool                mbToken :1; // whether content of union is a token
46cdf0e10cSrcweir     bool                mbEmpty :1; // empty cell result
47cdf0e10cSrcweir     bool                mbEmptyDisplayedAsString :1;    // only if mbEmpty
48cdf0e10cSrcweir     Multiline           meMultiline :2; // result is multiline
49cdf0e10cSrcweir 
50cdf0e10cSrcweir     /** Reset mnError, mbEmpty and mbEmptyDisplayedAsString to their defaults
51cdf0e10cSrcweir         prior to assigning other types */
52cdf0e10cSrcweir     inline  void                ResetToDefaults();
53cdf0e10cSrcweir 
54cdf0e10cSrcweir     /** If token is of formula::svError set error code and decrement RefCount.
55cdf0e10cSrcweir         If token is of formula::svEmptyCell set mbEmpty and mbEmptyAsString and
56cdf0e10cSrcweir         decrement RefCount.
57cdf0e10cSrcweir         If token is of formula::svDouble set mfValue and decrement RefCount.
58cdf0e10cSrcweir         Else assign token to mpToken. NULL is valid => svUnknown.
59cdf0e10cSrcweir         Other member variables are set accordingly.
60cdf0e10cSrcweir         @precondition: Token MUST had been IncRef'ed prior to this call!
61cdf0e10cSrcweir         @precondition: An already existing different mpToken MUST had been
62cdf0e10cSrcweir         DecRef'ed prior to this call, p will be assigned to mpToken if not
63cdf0e10cSrcweir         resolved.
64cdf0e10cSrcweir         ATTENTION! Token may get deleted in this call! */
65cdf0e10cSrcweir     inline  void                ResolveToken( const formula::FormulaToken * p );
66cdf0e10cSrcweir 
67cdf0e10cSrcweir public:
68cdf0e10cSrcweir                                 /** Effectively type svUnknown. */
ScFormulaResult()69cdf0e10cSrcweir                                 ScFormulaResult()
70cdf0e10cSrcweir                                     : mpToken(NULL), mnError(0), mbToken(true),
71cdf0e10cSrcweir                                     mbEmpty(false), mbEmptyDisplayedAsString(false),
72cdf0e10cSrcweir                                     meMultiline(MULTILINE_UNKNOWN) {}
73cdf0e10cSrcweir 
ScFormulaResult(const ScFormulaResult & r)74cdf0e10cSrcweir                                 ScFormulaResult( const ScFormulaResult & r )
75cdf0e10cSrcweir                                     : mnError( r.mnError), mbToken( r.mbToken),
76cdf0e10cSrcweir                                     mbEmpty( r.mbEmpty),
77cdf0e10cSrcweir                                     mbEmptyDisplayedAsString( r.mbEmptyDisplayedAsString),
78cdf0e10cSrcweir                                     meMultiline( r.meMultiline)
79cdf0e10cSrcweir                                 {
80cdf0e10cSrcweir                                     if (mbToken)
81cdf0e10cSrcweir                                     {
82cdf0e10cSrcweir                                         mpToken = r.mpToken;
83cdf0e10cSrcweir                                         if (mpToken)
84cdf0e10cSrcweir                                         {
85cdf0e10cSrcweir                                             // Since matrix dimension and
86cdf0e10cSrcweir                                             // results are assigned to a matrix
87cdf0e10cSrcweir                                             // cell formula token we have to
88cdf0e10cSrcweir                                             // clone that instead of sharing it.
89cdf0e10cSrcweir                                             const ScMatrixFormulaCellToken* pMatFormula =
90cdf0e10cSrcweir                                                 r.GetMatrixFormulaCellToken();
91cdf0e10cSrcweir                                             if (pMatFormula)
92cdf0e10cSrcweir                                                 mpToken = new ScMatrixFormulaCellToken( *pMatFormula);
93cdf0e10cSrcweir                                             mpToken->IncRef();
94cdf0e10cSrcweir                                         }
95cdf0e10cSrcweir                                     }
96cdf0e10cSrcweir                                     else
97cdf0e10cSrcweir                                         mfValue = r.mfValue;
98cdf0e10cSrcweir                                 }
99cdf0e10cSrcweir 
100cdf0e10cSrcweir     /** Same comments as for SetToken() apply! */
ScFormulaResult(const formula::FormulaToken * p)101cdf0e10cSrcweir     explicit                    ScFormulaResult( const formula::FormulaToken* p )
102cdf0e10cSrcweir                                     : mnError(0), mbToken(false),
103cdf0e10cSrcweir                                     mbEmpty(false), mbEmptyDisplayedAsString(false),
104cdf0e10cSrcweir                                     meMultiline(MULTILINE_UNKNOWN)
105cdf0e10cSrcweir                                 {
106cdf0e10cSrcweir                                     SetToken( p);
107cdf0e10cSrcweir                                 }
108cdf0e10cSrcweir 
~ScFormulaResult()109cdf0e10cSrcweir                                 ~ScFormulaResult()
110cdf0e10cSrcweir                                 {
111cdf0e10cSrcweir                                     if (mbToken && mpToken)
112cdf0e10cSrcweir                                         mpToken->DecRef();
113cdf0e10cSrcweir                                 }
114cdf0e10cSrcweir 
115cdf0e10cSrcweir     /** Well, guess what ... */
116cdf0e10cSrcweir     inline  ScFormulaResult &   operator=( const ScFormulaResult & r );
117cdf0e10cSrcweir 
118cdf0e10cSrcweir     /** Assignment as in operator=() but without return */
119cdf0e10cSrcweir     inline  void                Assign( const ScFormulaResult & r );
120cdf0e10cSrcweir 
121cdf0e10cSrcweir     /** Sets a direct double if token type is formula::svDouble, or mbEmpty if
122cdf0e10cSrcweir         formula::svEmptyCell, else token. If p is NULL, that is set as well, effectively
123cdf0e10cSrcweir         resulting in GetType()==svUnknown. If the already existing result is
124cdf0e10cSrcweir         ScMatrixFormulaCellToken, the upper left ist set to token.
125cdf0e10cSrcweir 
126cdf0e10cSrcweir         ATTENTION! formula::FormulaToken had to be allocated using 'new' and if of type
127cdf0e10cSrcweir         formula::svDouble and no RefCount was set may not be used after this call
128cdf0e10cSrcweir         because it was deleted after decrement! */
129cdf0e10cSrcweir     inline  void                SetToken( const formula::FormulaToken* p );
130cdf0e10cSrcweir 
131cdf0e10cSrcweir     /** May be NULL if SetToken() did so, also if type formula::svDouble or formula::svError! */
132cdf0e10cSrcweir     inline  formula::FormulaConstTokenRef     GetToken() const;
133cdf0e10cSrcweir 
134cdf0e10cSrcweir     /** Return upper left token if formula::svMatrixCell, else return GetToken().
135cdf0e10cSrcweir         May be NULL if SetToken() did so, also if type formula::svDouble or formula::svError! */
136cdf0e10cSrcweir     inline  formula::FormulaConstTokenRef     GetCellResultToken() const;
137cdf0e10cSrcweir 
138cdf0e10cSrcweir     /** Return type of result, including formula::svError, formula::svEmptyCell, formula::svDouble and
139cdf0e10cSrcweir         formula::svMatrixCell. */
140cdf0e10cSrcweir     inline  formula::StackVar            GetType() const;
141cdf0e10cSrcweir 
142cdf0e10cSrcweir     /** If type is formula::svMatrixCell return the type of upper left element, else
143cdf0e10cSrcweir         GetType() */
144cdf0e10cSrcweir     inline  formula::StackVar            GetCellResultType() const;
145cdf0e10cSrcweir 
146cdf0e10cSrcweir     /** If type is formula::svEmptyCell (including matrix upper left) and should be
147cdf0e10cSrcweir         displayed as empty string */
148cdf0e10cSrcweir     inline  bool                IsEmptyDisplayedAsString() const;
149cdf0e10cSrcweir 
150cdf0e10cSrcweir     /** Test for cell result type formula::svDouble, including upper left if
151cdf0e10cSrcweir         formula::svMatrixCell. Also included is formula::svError for legacy, because previously
152cdf0e10cSrcweir         an error result was treated like a numeric value at some places in
153cdf0e10cSrcweir         ScFormulaCell. Also included is formula::svEmptyCell as a reference to an empty
154cdf0e10cSrcweir         cell usually is treated as numeric 0. Use GetCellResultType() for
155cdf0e10cSrcweir         details instead. */
156cdf0e10cSrcweir     inline  bool                IsValue() const;
157cdf0e10cSrcweir 
158cdf0e10cSrcweir     /** Determines whether or not the result is a string containing more than
159cdf0e10cSrcweir         one paragraph */
160cdf0e10cSrcweir     inline  bool                IsMultiline() const;
161cdf0e10cSrcweir 
162cdf0e10cSrcweir     /** Get error code if set or GetCellResultType() is formula::svError or svUnknown,
163cdf0e10cSrcweir         else 0. */
164cdf0e10cSrcweir     inline  sal_uInt16              GetResultError() const;
165cdf0e10cSrcweir 
166cdf0e10cSrcweir     /** Set error code, don't touch token or double. */
167cdf0e10cSrcweir     inline  void                SetResultError( sal_uInt16 nErr );
168cdf0e10cSrcweir 
169cdf0e10cSrcweir     /** Set direct double. Shouldn't be used externally except in
170cdf0e10cSrcweir         ScFormulaCell for rounded CalcAsShown or SetErrCode(). If
171cdf0e10cSrcweir         ScMatrixFormulaCellToken the token isn't replaced but upper left result
172cdf0e10cSrcweir         is modified instead, but only if it was of type formula::svDouble before or not
173cdf0e10cSrcweir         set at all. */
174cdf0e10cSrcweir     inline  void                SetDouble( double f );
175cdf0e10cSrcweir 
176cdf0e10cSrcweir     /** Return value if type formula::svDouble or formula::svHybridCell or formula::svMatrixCell and upper
177cdf0e10cSrcweir         left formula::svDouble, else 0.0 */
178cdf0e10cSrcweir     inline  double              GetDouble() const;
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     /** Return string if type formula::svString or formula::svHybridCell or formula::svMatrixCell and
181cdf0e10cSrcweir         upper left formula::svString, else empty string. */
182cdf0e10cSrcweir     inline  const String &      GetString() const;
183cdf0e10cSrcweir 
184cdf0e10cSrcweir     /** Return matrix if type formula::svMatrixCell and ScMatrix present, else NULL. */
185cdf0e10cSrcweir     inline  ScConstMatrixRef    GetMatrix() const;
186cdf0e10cSrcweir 
187cdf0e10cSrcweir     /** Return formula string if type formula::svHybridCell, else empty string. */
188cdf0e10cSrcweir     inline  const String &      GetHybridFormula() const;
189cdf0e10cSrcweir 
190cdf0e10cSrcweir     /** Should only be used by import filters, best in the order
191cdf0e10cSrcweir         SetHybridDouble(), SetHybridString(), or only SetHybridString() for
192cdf0e10cSrcweir         formula string to be compiled later. */
193cdf0e10cSrcweir     inline  void                SetHybridDouble( double f );
194cdf0e10cSrcweir 
195cdf0e10cSrcweir     /** Should only be used by import filters, best in the order
196cdf0e10cSrcweir         SetHybridDouble(), SetHybridString()/SetHybridFormula(), or only
197cdf0e10cSrcweir         SetHybridFormula() for formula string to be compiled later. */
198cdf0e10cSrcweir     inline  void                SetHybridString( const String & rStr );
199cdf0e10cSrcweir 
200cdf0e10cSrcweir     /** Should only be used by import filters, best in the order
201cdf0e10cSrcweir         SetHybridDouble(), SetHybridString()/SetHybridFormula(), or only
202cdf0e10cSrcweir         SetHybridFormula() for formula string to be compiled later. */
203cdf0e10cSrcweir     inline  void                SetHybridFormula( const String & rFormula );
204cdf0e10cSrcweir 
205cdf0e10cSrcweir     /** Get the const ScMatrixFormulaCellToken* if token is of that type, else
206cdf0e10cSrcweir         NULL. */
207cdf0e10cSrcweir     inline const ScMatrixFormulaCellToken* GetMatrixFormulaCellToken() const;
208cdf0e10cSrcweir 
209cdf0e10cSrcweir     /** Get the ScMatrixFormulaCellToken* if token is of that type, else NULL.
210cdf0e10cSrcweir         Shouldn't be used externally except by ScFormulaCell::SetMatColsRows(). */
211cdf0e10cSrcweir     inline ScMatrixFormulaCellToken* GetMatrixFormulaCellTokenNonConst();
212cdf0e10cSrcweir };
213cdf0e10cSrcweir 
214cdf0e10cSrcweir 
ResetToDefaults()215cdf0e10cSrcweir inline void ScFormulaResult::ResetToDefaults()
216cdf0e10cSrcweir {
217cdf0e10cSrcweir     mnError = 0;
218cdf0e10cSrcweir     mbEmpty = false;
219cdf0e10cSrcweir     mbEmptyDisplayedAsString = false;
220cdf0e10cSrcweir     meMultiline = MULTILINE_UNKNOWN;
221cdf0e10cSrcweir }
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 
ResolveToken(const formula::FormulaToken * p)224cdf0e10cSrcweir inline void ScFormulaResult::ResolveToken( const formula::FormulaToken * p )
225cdf0e10cSrcweir {
226cdf0e10cSrcweir     ResetToDefaults();
227cdf0e10cSrcweir     if (!p)
228cdf0e10cSrcweir     {
229cdf0e10cSrcweir         mpToken = p;
230cdf0e10cSrcweir         mbToken = true;
231cdf0e10cSrcweir     }
232cdf0e10cSrcweir     else
233cdf0e10cSrcweir     {
234cdf0e10cSrcweir         switch (p->GetType())
235cdf0e10cSrcweir         {
236cdf0e10cSrcweir             case formula::svError:
237cdf0e10cSrcweir                 mnError = p->GetError();
238cdf0e10cSrcweir                 p->DecRef();
239cdf0e10cSrcweir                 mbToken = false;
240cdf0e10cSrcweir                 // set in case mnError is 0 now, which shouldn't happen but ...
241cdf0e10cSrcweir                 mfValue = 0.0;
242cdf0e10cSrcweir                 meMultiline = MULTILINE_FALSE;
243cdf0e10cSrcweir                 break;
244cdf0e10cSrcweir             case formula::svEmptyCell:
245cdf0e10cSrcweir                 mbEmpty = true;
246cdf0e10cSrcweir                 mbEmptyDisplayedAsString = static_cast<const ScEmptyCellToken*>(p)->IsDisplayedAsString();
247cdf0e10cSrcweir                 p->DecRef();
248cdf0e10cSrcweir                 mbToken = false;
249cdf0e10cSrcweir                 meMultiline = MULTILINE_FALSE;
250cdf0e10cSrcweir                 break;
251cdf0e10cSrcweir             case formula::svDouble:
252cdf0e10cSrcweir                 mfValue = p->GetDouble();
253cdf0e10cSrcweir                 p->DecRef();
254cdf0e10cSrcweir                 mbToken = false;
255cdf0e10cSrcweir                 meMultiline = MULTILINE_FALSE;
256cdf0e10cSrcweir                 break;
257cdf0e10cSrcweir             default:
258cdf0e10cSrcweir                 mpToken = p;
259cdf0e10cSrcweir                 mbToken = true;
260cdf0e10cSrcweir         }
261cdf0e10cSrcweir     }
262cdf0e10cSrcweir }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir 
operator =(const ScFormulaResult & r)265cdf0e10cSrcweir inline ScFormulaResult & ScFormulaResult::operator=( const ScFormulaResult & r )
266cdf0e10cSrcweir {
267cdf0e10cSrcweir     Assign( r);
268cdf0e10cSrcweir     return *this;
269cdf0e10cSrcweir }
270cdf0e10cSrcweir 
271cdf0e10cSrcweir 
Assign(const ScFormulaResult & r)272cdf0e10cSrcweir inline void ScFormulaResult::Assign( const ScFormulaResult & r )
273cdf0e10cSrcweir {
274cdf0e10cSrcweir     if (this == &r)
275cdf0e10cSrcweir         return;
276cdf0e10cSrcweir     if (r.mbEmpty)
277cdf0e10cSrcweir     {
278cdf0e10cSrcweir         if (mbToken && mpToken)
279cdf0e10cSrcweir             mpToken->DecRef();
280cdf0e10cSrcweir         mbToken = false;
281cdf0e10cSrcweir         mbEmpty = true;
282cdf0e10cSrcweir         mbEmptyDisplayedAsString = r.mbEmptyDisplayedAsString;
283cdf0e10cSrcweir         meMultiline = r.meMultiline;
284cdf0e10cSrcweir     }
285cdf0e10cSrcweir     else if (r.mbToken)
286cdf0e10cSrcweir     {
287cdf0e10cSrcweir         // Matrix formula cell token must be cloned, see copy-ctor.
288cdf0e10cSrcweir         const ScMatrixFormulaCellToken* pMatFormula =
289cdf0e10cSrcweir             r.GetMatrixFormulaCellToken();
290cdf0e10cSrcweir         if (pMatFormula)
291cdf0e10cSrcweir             SetToken( new ScMatrixFormulaCellToken( *pMatFormula));
292cdf0e10cSrcweir         else
293cdf0e10cSrcweir             SetToken( r.mpToken);
294cdf0e10cSrcweir     }
295cdf0e10cSrcweir     else
296cdf0e10cSrcweir         SetDouble( r.mfValue);
297cdf0e10cSrcweir     // If there was an error there will be an error, no matter what Set...()
298cdf0e10cSrcweir     // methods did.
299cdf0e10cSrcweir     mnError = r.mnError;
300cdf0e10cSrcweir }
301cdf0e10cSrcweir 
302cdf0e10cSrcweir 
SetToken(const formula::FormulaToken * p)303cdf0e10cSrcweir inline void ScFormulaResult::SetToken( const formula::FormulaToken* p )
304cdf0e10cSrcweir {
305cdf0e10cSrcweir     ResetToDefaults();
306cdf0e10cSrcweir     if (p)
307cdf0e10cSrcweir         p->IncRef();
308cdf0e10cSrcweir     // Handle a result obtained from the interpreter to be assigned to a matrix
309cdf0e10cSrcweir     // formula cell's ScMatrixFormulaCellToken.
310cdf0e10cSrcweir     ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
311cdf0e10cSrcweir     if (pMatFormula)
312cdf0e10cSrcweir     {
313cdf0e10cSrcweir         const ScMatrixCellResultToken* pMatResult =
314cdf0e10cSrcweir             (p && p->GetType() == formula::svMatrixCell ?
315cdf0e10cSrcweir              dynamic_cast<const ScMatrixCellResultToken*>(p) : NULL);
316cdf0e10cSrcweir         if (pMatResult)
317cdf0e10cSrcweir         {
318cdf0e10cSrcweir             const ScMatrixFormulaCellToken* pNewMatFormula =
319cdf0e10cSrcweir                 dynamic_cast<const ScMatrixFormulaCellToken*>(pMatResult);
320cdf0e10cSrcweir             if (pNewMatFormula)
321cdf0e10cSrcweir             {
322cdf0e10cSrcweir                 DBG_ERRORFILE( "ScFormulaResult::SetToken: pNewMatFormula and pMatFormula, overriding matrix formula dimension; intended?");
323cdf0e10cSrcweir                 pMatFormula->SetMatColsRows( pNewMatFormula->GetMatCols(),
324cdf0e10cSrcweir                         pNewMatFormula->GetMatRows());
325cdf0e10cSrcweir             }
326cdf0e10cSrcweir             pMatFormula->Assign( *pMatResult);
327cdf0e10cSrcweir             p->DecRef();
328cdf0e10cSrcweir         }
329cdf0e10cSrcweir         else if (p)
330cdf0e10cSrcweir         {
331cdf0e10cSrcweir             // This may be the result of some constant expression like
332cdf0e10cSrcweir             // {="string"} that doesn't result in a matrix but still would
333cdf0e10cSrcweir             // display the result in all cells of this matrix formula.
334cdf0e10cSrcweir             pMatFormula->Assign( *p);
335cdf0e10cSrcweir             p->DecRef();
336cdf0e10cSrcweir         }
337cdf0e10cSrcweir         else
338cdf0e10cSrcweir         {
339cdf0e10cSrcweir             // NULL result? Well, if you say so ...
340cdf0e10cSrcweir             pMatFormula->ResetResult();
341cdf0e10cSrcweir         }
342cdf0e10cSrcweir     }
343cdf0e10cSrcweir     else
344cdf0e10cSrcweir     {
345cdf0e10cSrcweir         if (mbToken && mpToken)
346cdf0e10cSrcweir             mpToken->DecRef();
347cdf0e10cSrcweir         ResolveToken( p);
348cdf0e10cSrcweir     }
349cdf0e10cSrcweir }
350cdf0e10cSrcweir 
351cdf0e10cSrcweir 
SetDouble(double f)352cdf0e10cSrcweir inline void ScFormulaResult::SetDouble( double f )
353cdf0e10cSrcweir {
354cdf0e10cSrcweir     ResetToDefaults();
355cdf0e10cSrcweir     // Handle a result obtained from the interpreter to be assigned to a matrix
356cdf0e10cSrcweir     // formula cell's ScMatrixFormulaCellToken.
357cdf0e10cSrcweir     ScMatrixFormulaCellToken* pMatFormula = GetMatrixFormulaCellTokenNonConst();
358cdf0e10cSrcweir     if (pMatFormula)
359cdf0e10cSrcweir         pMatFormula->SetUpperLeftDouble( f);
360cdf0e10cSrcweir     else
361cdf0e10cSrcweir     {
362cdf0e10cSrcweir         if (mbToken && mpToken)
363cdf0e10cSrcweir             mpToken->DecRef();
364cdf0e10cSrcweir         mfValue = f;
365cdf0e10cSrcweir         mbToken = false;
366cdf0e10cSrcweir         meMultiline = MULTILINE_FALSE;
367cdf0e10cSrcweir     }
368cdf0e10cSrcweir }
369cdf0e10cSrcweir 
370cdf0e10cSrcweir 
GetType() const371cdf0e10cSrcweir inline formula::StackVar ScFormulaResult::GetType() const
372cdf0e10cSrcweir {
373cdf0e10cSrcweir     // Order is significant.
374cdf0e10cSrcweir     if (mnError)
375cdf0e10cSrcweir         return formula::svError;
376cdf0e10cSrcweir     if (mbEmpty)
377cdf0e10cSrcweir         return formula::svEmptyCell;
378cdf0e10cSrcweir     if (!mbToken)
379cdf0e10cSrcweir         return formula::svDouble;
380cdf0e10cSrcweir     if (mpToken)
381cdf0e10cSrcweir         return mpToken->GetType();
382cdf0e10cSrcweir     return formula::svUnknown;
383cdf0e10cSrcweir }
384cdf0e10cSrcweir 
385cdf0e10cSrcweir 
GetCellResultType() const386cdf0e10cSrcweir inline formula::StackVar ScFormulaResult::GetCellResultType() const
387cdf0e10cSrcweir {
388cdf0e10cSrcweir     formula::StackVar sv = GetType();
389cdf0e10cSrcweir     if (sv == formula::svMatrixCell)
390cdf0e10cSrcweir         // don't need to test for mpToken here, GetType() already did it
391cdf0e10cSrcweir         sv = static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftType();
392cdf0e10cSrcweir     return sv;
393cdf0e10cSrcweir }
394cdf0e10cSrcweir 
395cdf0e10cSrcweir 
IsEmptyDisplayedAsString() const396cdf0e10cSrcweir inline bool ScFormulaResult::IsEmptyDisplayedAsString() const
397cdf0e10cSrcweir {
398cdf0e10cSrcweir     if (mbEmpty)
399cdf0e10cSrcweir         return mbEmptyDisplayedAsString;
400cdf0e10cSrcweir     if (GetType() == formula::svMatrixCell)
401cdf0e10cSrcweir     {
402cdf0e10cSrcweir         // don't need to test for mpToken here, GetType() already did it
403cdf0e10cSrcweir         const ScEmptyCellToken* p = dynamic_cast<const ScEmptyCellToken*>(
404cdf0e10cSrcweir                 static_cast<const ScMatrixCellResultToken*>(
405cdf0e10cSrcweir                     mpToken)->GetUpperLeftToken().operator->());
406cdf0e10cSrcweir         if (p)
407cdf0e10cSrcweir             return p->IsDisplayedAsString();
408cdf0e10cSrcweir     }
409cdf0e10cSrcweir     return false;
410cdf0e10cSrcweir }
411cdf0e10cSrcweir 
412cdf0e10cSrcweir 
IsValue() const413cdf0e10cSrcweir inline bool ScFormulaResult::IsValue() const
414cdf0e10cSrcweir {
415cdf0e10cSrcweir     formula::StackVar sv = GetCellResultType();
416cdf0e10cSrcweir     return sv == formula::svDouble || sv == formula::svError || sv == formula::svEmptyCell;
417cdf0e10cSrcweir }
418cdf0e10cSrcweir 
IsMultiline() const419cdf0e10cSrcweir inline bool ScFormulaResult::IsMultiline() const
420cdf0e10cSrcweir {
421cdf0e10cSrcweir     if (meMultiline == MULTILINE_UNKNOWN)
422cdf0e10cSrcweir     {
423cdf0e10cSrcweir         const String& rStr = GetString();
424cdf0e10cSrcweir         if (rStr.Len() && rStr.Search( _LF ) != STRING_NOTFOUND)
425cdf0e10cSrcweir             const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_TRUE;
426cdf0e10cSrcweir         else
427cdf0e10cSrcweir             const_cast<ScFormulaResult*>(this)->meMultiline = MULTILINE_FALSE;
428cdf0e10cSrcweir     }
429cdf0e10cSrcweir     return meMultiline == MULTILINE_TRUE;
430cdf0e10cSrcweir }
431cdf0e10cSrcweir 
432cdf0e10cSrcweir 
GetResultError() const433cdf0e10cSrcweir inline sal_uInt16 ScFormulaResult::GetResultError() const
434cdf0e10cSrcweir {
435cdf0e10cSrcweir     if (mnError)
436cdf0e10cSrcweir         return mnError;
437cdf0e10cSrcweir     formula::StackVar sv = GetCellResultType();
438cdf0e10cSrcweir     if (sv == formula::svError)
439cdf0e10cSrcweir     {
440cdf0e10cSrcweir         if (GetType() == formula::svMatrixCell)
441cdf0e10cSrcweir             // don't need to test for mpToken here, GetType() already did it
442cdf0e10cSrcweir             return static_cast<const ScMatrixCellResultToken*>(mpToken)->
443cdf0e10cSrcweir                 GetUpperLeftToken()->GetError();
444cdf0e10cSrcweir         if (mpToken)
445cdf0e10cSrcweir             return mpToken->GetError();
446cdf0e10cSrcweir     }
447cdf0e10cSrcweir     return 0;
448cdf0e10cSrcweir }
449cdf0e10cSrcweir 
450cdf0e10cSrcweir 
SetResultError(sal_uInt16 nErr)451cdf0e10cSrcweir inline void ScFormulaResult::SetResultError( sal_uInt16 nErr )
452cdf0e10cSrcweir {
453cdf0e10cSrcweir     mnError = nErr;
454cdf0e10cSrcweir }
455cdf0e10cSrcweir 
456cdf0e10cSrcweir 
GetToken() const457cdf0e10cSrcweir inline formula::FormulaConstTokenRef ScFormulaResult::GetToken() const
458cdf0e10cSrcweir {
459cdf0e10cSrcweir     if (mbToken)
460cdf0e10cSrcweir         return mpToken;
461cdf0e10cSrcweir     return NULL;
462cdf0e10cSrcweir }
463cdf0e10cSrcweir 
464cdf0e10cSrcweir 
GetCellResultToken() const465cdf0e10cSrcweir inline formula::FormulaConstTokenRef ScFormulaResult::GetCellResultToken() const
466cdf0e10cSrcweir {
467cdf0e10cSrcweir     if (GetType() == formula::svMatrixCell)
468cdf0e10cSrcweir         // don't need to test for mpToken here, GetType() already did it
469cdf0e10cSrcweir         return static_cast<const ScMatrixCellResultToken*>(mpToken)->GetUpperLeftToken();
470cdf0e10cSrcweir     return GetToken();
471cdf0e10cSrcweir }
472cdf0e10cSrcweir 
473cdf0e10cSrcweir 
GetDouble() const474cdf0e10cSrcweir inline double ScFormulaResult::GetDouble() const
475cdf0e10cSrcweir {
476cdf0e10cSrcweir     if (mbToken)
477cdf0e10cSrcweir     {
478cdf0e10cSrcweir         // Should really not be of type formula::svDouble here.
479cdf0e10cSrcweir         if (mpToken)
480cdf0e10cSrcweir         {
481cdf0e10cSrcweir             switch (mpToken->GetType())
482cdf0e10cSrcweir             {
483cdf0e10cSrcweir                 case formula::svHybridCell:
484cdf0e10cSrcweir                     return mpToken->GetDouble();
485cdf0e10cSrcweir                 case formula::svMatrixCell:
486cdf0e10cSrcweir                     {
487cdf0e10cSrcweir                         const ScMatrixCellResultToken* p =
488cdf0e10cSrcweir                             static_cast<const ScMatrixCellResultToken*>(mpToken);
489cdf0e10cSrcweir                         if (p->GetUpperLeftType() == formula::svDouble)
490cdf0e10cSrcweir                             return p->GetUpperLeftToken()->GetDouble();
491cdf0e10cSrcweir                     }
492cdf0e10cSrcweir                     break;
493cdf0e10cSrcweir                 default:
494cdf0e10cSrcweir                     ;   // nothing
495cdf0e10cSrcweir             }
496cdf0e10cSrcweir         }
497cdf0e10cSrcweir         return 0.0;
498cdf0e10cSrcweir     }
499cdf0e10cSrcweir     if (mbEmpty)
500cdf0e10cSrcweir         return 0.0;
501cdf0e10cSrcweir     return mfValue;
502cdf0e10cSrcweir }
503cdf0e10cSrcweir 
504cdf0e10cSrcweir 
GetString() const505cdf0e10cSrcweir inline const String & ScFormulaResult::GetString() const
506cdf0e10cSrcweir {
507cdf0e10cSrcweir     if (mbToken && mpToken)
508cdf0e10cSrcweir     {
509cdf0e10cSrcweir         switch (mpToken->GetType())
510cdf0e10cSrcweir         {
511cdf0e10cSrcweir             case formula::svString:
512cdf0e10cSrcweir             case formula::svHybridCell:
513cdf0e10cSrcweir                 return mpToken->GetString();
514cdf0e10cSrcweir             case formula::svMatrixCell:
515cdf0e10cSrcweir                 {
516cdf0e10cSrcweir                     const ScMatrixCellResultToken* p =
517cdf0e10cSrcweir                         static_cast<const ScMatrixCellResultToken*>(mpToken);
518cdf0e10cSrcweir                     if (p->GetUpperLeftType() == formula::svString)
519cdf0e10cSrcweir                         return p->GetUpperLeftToken()->GetString();
520cdf0e10cSrcweir                 }
521cdf0e10cSrcweir                 break;
522cdf0e10cSrcweir             default:
523cdf0e10cSrcweir                 ;   // nothing
524cdf0e10cSrcweir         }
525cdf0e10cSrcweir     }
526cdf0e10cSrcweir     return EMPTY_STRING;
527cdf0e10cSrcweir }
528cdf0e10cSrcweir 
529cdf0e10cSrcweir 
GetMatrix() const530cdf0e10cSrcweir inline ScConstMatrixRef ScFormulaResult::GetMatrix() const
531cdf0e10cSrcweir {
532cdf0e10cSrcweir     if (GetType() == formula::svMatrixCell)
533cdf0e10cSrcweir         return static_cast<const ScToken*>(mpToken)->GetMatrix();
534cdf0e10cSrcweir     return NULL;
535cdf0e10cSrcweir }
536cdf0e10cSrcweir 
537cdf0e10cSrcweir 
GetHybridFormula() const538cdf0e10cSrcweir inline const String & ScFormulaResult::GetHybridFormula() const
539cdf0e10cSrcweir {
540cdf0e10cSrcweir     if (GetType() == formula::svHybridCell)
541cdf0e10cSrcweir     {
542cdf0e10cSrcweir         const ScHybridCellToken* p = dynamic_cast<const ScHybridCellToken*>(mpToken);
543cdf0e10cSrcweir         if (p)
544cdf0e10cSrcweir             return p->GetFormula();
545cdf0e10cSrcweir     }
546cdf0e10cSrcweir     return EMPTY_STRING;
547cdf0e10cSrcweir }
548cdf0e10cSrcweir 
549cdf0e10cSrcweir 
SetHybridDouble(double f)550cdf0e10cSrcweir inline void ScFormulaResult::SetHybridDouble( double f )
551cdf0e10cSrcweir {
552cdf0e10cSrcweir     ResetToDefaults();
553cdf0e10cSrcweir     if (mbToken && mpToken)
554cdf0e10cSrcweir     {
555cdf0e10cSrcweir         String aString( GetString());
556cdf0e10cSrcweir         String aFormula( GetHybridFormula());
557cdf0e10cSrcweir         mpToken->DecRef();
558cdf0e10cSrcweir         mpToken = new ScHybridCellToken( f, aString, aFormula);
559cdf0e10cSrcweir         mpToken->IncRef();
560cdf0e10cSrcweir     }
561cdf0e10cSrcweir     else
562cdf0e10cSrcweir     {
563cdf0e10cSrcweir         mfValue = f;
564cdf0e10cSrcweir         mbToken = false;
565cdf0e10cSrcweir         meMultiline = MULTILINE_FALSE;
566cdf0e10cSrcweir     }
567cdf0e10cSrcweir }
568cdf0e10cSrcweir 
569cdf0e10cSrcweir 
SetHybridString(const String & rStr)570cdf0e10cSrcweir inline void ScFormulaResult::SetHybridString( const String & rStr )
571cdf0e10cSrcweir {
572cdf0e10cSrcweir     // Obtain values before changing anything.
573cdf0e10cSrcweir     double f = GetDouble();
574cdf0e10cSrcweir     String aFormula( GetHybridFormula());
575cdf0e10cSrcweir     ResetToDefaults();
576cdf0e10cSrcweir     if (mbToken && mpToken)
577cdf0e10cSrcweir         mpToken->DecRef();
578cdf0e10cSrcweir     mpToken = new ScHybridCellToken( f, rStr, aFormula);
579cdf0e10cSrcweir     mpToken->IncRef();
580cdf0e10cSrcweir     mbToken = true;
581cdf0e10cSrcweir }
582cdf0e10cSrcweir 
583cdf0e10cSrcweir 
SetHybridFormula(const String & rFormula)584cdf0e10cSrcweir inline void ScFormulaResult::SetHybridFormula( const String & rFormula )
585cdf0e10cSrcweir {
586cdf0e10cSrcweir     // Obtain values before changing anything.
587cdf0e10cSrcweir     double f = GetDouble();
588cdf0e10cSrcweir     String aStr( GetString());
589cdf0e10cSrcweir     ResetToDefaults();
590cdf0e10cSrcweir     if (mbToken && mpToken)
591cdf0e10cSrcweir         mpToken->DecRef();
592cdf0e10cSrcweir     mpToken = new ScHybridCellToken( f, aStr, rFormula);
593cdf0e10cSrcweir     mpToken->IncRef();
594cdf0e10cSrcweir     mbToken = true;
595cdf0e10cSrcweir }
596cdf0e10cSrcweir 
597cdf0e10cSrcweir 
GetMatrixFormulaCellToken() const598cdf0e10cSrcweir inline const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const
599cdf0e10cSrcweir {
600cdf0e10cSrcweir     return (GetType() == formula::svMatrixCell ?
601cdf0e10cSrcweir             dynamic_cast<const ScMatrixFormulaCellToken*>(mpToken) : NULL);
602cdf0e10cSrcweir }
603cdf0e10cSrcweir 
604cdf0e10cSrcweir 
GetMatrixFormulaCellTokenNonConst()605cdf0e10cSrcweir inline ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellTokenNonConst()
606cdf0e10cSrcweir {
607cdf0e10cSrcweir     return const_cast<ScMatrixFormulaCellToken*>( GetMatrixFormulaCellToken());
608cdf0e10cSrcweir }
609cdf0e10cSrcweir 
610cdf0e10cSrcweir 
611cdf0e10cSrcweir #endif // SC_FORMULARESULT_HXX
612