xref: /aoo41x/main/sc/inc/token.hxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef SC_TOKEN_HXX
29 #define SC_TOKEN_HXX
30 
31 #include <memory>
32 #include <vector>
33 #include <boost/shared_ptr.hpp>
34 
35 #include "formula/opcode.hxx"
36 #include "refdata.hxx"
37 #include "scmatrix.hxx"
38 #include "formula/intruref.hxx"
39 #include <tools/mempool.hxx>
40 #include "scdllapi.h"
41 #include "formula/IFunctionDescription.hxx"
42 #include "formula/token.hxx"
43 
44 
45 class ScJumpMatrix;
46 class ScToken;
47 
48 typedef ::std::vector< ScComplexRefData > ScRefList;
49 typedef formula::SimpleIntrusiveReference< class ScToken > ScTokenRef;
50 
51 /**
52  * Another ref-counted token type using shared_ptr.  <b>Be extra careful
53  * not to mix use of this smart pointer type with ScTokenRef</b>, since
54  * mixing them might cause a premature object deletion because the same
55  * object may be ref-counted by two different smart pointer wrappers.
56  *
57  * You have been warned.
58  */
59 typedef ::boost::shared_ptr< ScToken > ScSharedTokenRef;
60 
61 class SC_DLLPUBLIC ScToken : public formula::FormulaToken
62 {
63 private:
64                                 // not implemented, prevent usage
65                                 ScToken();
66             ScToken&            operator=( const ScToken& );
67 
68 protected:
69 
70     ScToken( formula::StackVar eTypeP,OpCode e = ocPush ) : formula::FormulaToken(eTypeP,e) {}
71     ScToken( const ScToken& r ): formula::FormulaToken(r) {}
72 
73 public:
74 
75     virtual                     ~ScToken();
76 
77     /**
78         Dummy methods to avoid switches and casts where possible,
79         the real token classes have to overload the appropriate method[s].
80         The only methods valid anytime if not overloaded are:
81 
82         - GetByte() since this represents the count of parameters to a function
83           which of course is 0 on non-functions. formula::FormulaByteToken and ScExternal do
84           overload it.
85 
86         - HasForceArray() since also this is only used for operators and
87           functions and is 0 for other tokens.
88 
89         Any other non-overloaded method pops up an assertion.
90      */
91 
92     virtual const ScSingleRefData&    GetSingleRef() const;
93     virtual ScSingleRefData&      GetSingleRef();
94     virtual const ScComplexRefData& GetDoubleRef() const;
95     virtual ScComplexRefData&       GetDoubleRef();
96     virtual const ScSingleRefData&    GetSingleRef2() const;
97     virtual ScSingleRefData&      GetSingleRef2();
98     virtual void                CalcAbsIfRel( const ScAddress& );
99     virtual void                CalcRelFromAbs( const ScAddress& );
100     virtual const ScMatrix*     GetMatrix() const;
101     virtual ScMatrix*           GetMatrix();
102     virtual ScJumpMatrix*       GetJumpMatrix() const;
103     virtual const ScRefList*    GetRefList() const;
104     virtual       ScRefList*    GetRefList();
105 
106     virtual sal_Bool                TextEqual( const formula::FormulaToken& rToken ) const;
107     virtual sal_Bool                Is3DRef() const;    // reference with 3D flag set
108 
109     /** If rTok1 and rTok2 both are SingleRef or DoubleRef tokens, extend/merge
110         ranges as needed for ocRange.
111         @param rPos
112             The formula's position, used to calculate absolute positions from
113             relative references.
114         @param bReuseDoubleRef
115             If sal_True, a DoubleRef token is reused if passed as rTok1 or rTok2,
116             else a new DoubleRef token is created and returned.
117         @return
118             A reused or new'ed ScDoubleRefToken, or a NULL TokenRef if rTok1 or
119             rTok2 are not of sv(Single|Double)Ref
120      */
121     static  formula::FormulaTokenRef          ExtendRangeReference( formula::FormulaToken & rTok1, formula::FormulaToken & rTok2, const ScAddress & rPos, bool bReuseDoubleRef );
122 };
123 
124 class ScSingleRefToken : public ScToken
125 {
126 private:
127             ScSingleRefData       aSingleRef;
128 public:
129                                 ScSingleRefToken( const ScSingleRefData& r, OpCode e = ocPush ) :
130                                     ScToken( formula::svSingleRef, e ), aSingleRef( r ) {}
131                                 ScSingleRefToken( const ScSingleRefToken& r ) :
132                                     ScToken( r ), aSingleRef( r.aSingleRef ) {}
133     virtual const ScSingleRefData&    GetSingleRef() const;
134     virtual ScSingleRefData&      GetSingleRef();
135     virtual void                CalcAbsIfRel( const ScAddress& );
136     virtual void                CalcRelFromAbs( const ScAddress& );
137     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
138     virtual FormulaToken*       Clone() const { return new ScSingleRefToken(*this); }
139 
140     DECL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken );
141 };
142 
143 class ScDoubleRefToken : public ScToken
144 {
145 private:
146             ScComplexRefData        aDoubleRef;
147 public:
148                                 ScDoubleRefToken( const ScComplexRefData& r, OpCode e = ocPush  ) :
149                                     ScToken( formula::svDoubleRef, e ), aDoubleRef( r ) {}
150                                 ScDoubleRefToken( const ScSingleRefData& r, OpCode e = ocPush  ) :
151                                     ScToken( formula::svDoubleRef, e )
152                                 {
153                                     aDoubleRef.Ref1 = r;
154                                     aDoubleRef.Ref2 = r;
155                                 }
156                                 ScDoubleRefToken( const ScDoubleRefToken& r ) :
157                                     ScToken( r ), aDoubleRef( r.aDoubleRef ) {}
158     virtual const ScSingleRefData&    GetSingleRef() const;
159     virtual ScSingleRefData&      GetSingleRef();
160     virtual const ScComplexRefData& GetDoubleRef() const;
161     virtual ScComplexRefData&       GetDoubleRef();
162     virtual const ScSingleRefData&    GetSingleRef2() const;
163     virtual ScSingleRefData&      GetSingleRef2();
164     virtual void                CalcAbsIfRel( const ScAddress& );
165     virtual void                CalcRelFromAbs( const ScAddress& );
166     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
167     virtual FormulaToken*       Clone() const { return new ScDoubleRefToken(*this); }
168 
169     DECL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken );
170 };
171 
172 class ScMatrixToken : public ScToken
173 {
174 private:
175             ScMatrixRef         pMatrix;
176 public:
177                                 ScMatrixToken( ScMatrix* p ) :
178                                     ScToken( formula::svMatrix ), pMatrix( p ) {}
179                                 ScMatrixToken( const ScMatrixToken& r ) :
180                                     ScToken( r ), pMatrix( r.pMatrix ) {}
181     virtual const ScMatrix*     GetMatrix() const;
182     virtual ScMatrix*           GetMatrix();
183     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
184     virtual FormulaToken*       Clone() const { return new ScMatrixToken(*this); }
185 };
186 
187 
188 class ScExternalSingleRefToken : public ScToken
189 {
190 private:
191     sal_uInt16                  mnFileId;
192     String                      maTabName;
193     ScSingleRefData             maSingleRef;
194 
195                                 ScExternalSingleRefToken(); // disabled
196 public:
197                                 ScExternalSingleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScSingleRefData& r );
198                                 ScExternalSingleRefToken( const ScExternalSingleRefToken& r );
199     virtual                     ~ScExternalSingleRefToken();
200 
201     virtual sal_uInt16              GetIndex() const;
202     virtual const String&           GetString() const;
203     virtual const ScSingleRefData&  GetSingleRef() const;
204     virtual ScSingleRefData&        GetSingleRef();
205     virtual void                    CalcAbsIfRel( const ScAddress& );
206     virtual void                    CalcRelFromAbs( const ScAddress& );
207     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
208     virtual FormulaToken*           Clone() const { return new ScExternalSingleRefToken(*this); }
209 };
210 
211 
212 class ScExternalDoubleRefToken : public ScToken
213 {
214 private:
215     sal_uInt16                  mnFileId;
216     String                      maTabName;  // name of the first sheet
217     ScComplexRefData            maDoubleRef;
218 
219                                 ScExternalDoubleRefToken(); // disabled
220 public:
221                                 ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& r );
222                                 ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r );
223     explicit                    ScExternalDoubleRefToken( const ScExternalSingleRefToken& r );
224     virtual                     ~ScExternalDoubleRefToken();
225 
226     virtual sal_uInt16              GetIndex() const;
227     virtual const String&           GetString() const;
228     virtual const ScSingleRefData&  GetSingleRef() const;
229     virtual ScSingleRefData&        GetSingleRef();
230     virtual const ScSingleRefData&  GetSingleRef2() const;
231     virtual ScSingleRefData&        GetSingleRef2();
232     virtual const ScComplexRefData& GetDoubleRef() const;
233     virtual ScComplexRefData&       GetDoubleRef();
234     virtual void                    CalcAbsIfRel( const ScAddress& );
235     virtual void                    CalcRelFromAbs( const ScAddress& );
236     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
237     virtual FormulaToken*           Clone() const { return new ScExternalDoubleRefToken(*this); }
238 };
239 
240 
241 class ScExternalNameToken : public ScToken
242 {
243 private:
244     sal_uInt16                  mnFileId;
245     String                      maName;
246 private:
247                                 ScExternalNameToken(); // disabled
248 public:
249                                 ScExternalNameToken( sal_uInt16 nFileId, const String& rName );
250                                 ScExternalNameToken( const ScExternalNameToken& r );
251     virtual                     ~ScExternalNameToken();
252     virtual sal_uInt16              GetIndex() const;
253     virtual const String&       GetString() const;
254     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
255     virtual FormulaToken*       Clone() const { return new ScExternalNameToken(*this); }
256 };
257 
258 
259 // Only created from within the interpreter, no conversion from ScRawToken,
260 // never added to ScTokenArray!
261 class ScJumpMatrixToken : public ScToken
262 {
263 private:
264             ScJumpMatrix*       pJumpMatrix;
265 public:
266                                 ScJumpMatrixToken( ScJumpMatrix* p ) :
267                                     ScToken( formula::svJumpMatrix ), pJumpMatrix( p ) {}
268                                 ScJumpMatrixToken( const ScJumpMatrixToken& r ) :
269                                     ScToken( r ), pJumpMatrix( r.pJumpMatrix ) {}
270     virtual                     ~ScJumpMatrixToken();
271     virtual ScJumpMatrix*       GetJumpMatrix() const;
272     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
273     virtual FormulaToken*       Clone() const { return new ScJumpMatrixToken(*this); }
274 };
275 
276 
277 // Only created from within the interpreter, no conversion from ScRawToken,
278 // never added to ScTokenArray!
279 class ScRefListToken : public ScToken
280 {
281 private:
282             ScRefList           aRefList;
283 public:
284                                 ScRefListToken() :
285                                     ScToken( formula::svRefList ) {}
286                                 ScRefListToken( const ScRefListToken & r ) :
287                                     ScToken( r ), aRefList( r.aRefList ) {}
288     virtual void                CalcAbsIfRel( const ScAddress& );
289     virtual void                CalcRelFromAbs( const ScAddress& );
290     virtual const ScRefList*    GetRefList() const;
291     virtual       ScRefList*    GetRefList();
292     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
293     virtual FormulaToken*       Clone() const { return new ScRefListToken(*this); }
294 };
295 
296 
297 class SC_DLLPUBLIC ScEmptyCellToken : public ScToken
298 {
299             bool                bInherited          :1;
300             bool                bDisplayedAsString  :1;
301 public:
302     explicit                    ScEmptyCellToken( bool bInheritedP, bool bDisplayAsString ) :
303                                     ScToken( formula::svEmptyCell ),
304                                     bInherited( bInheritedP ),
305                                     bDisplayedAsString( bDisplayAsString ) {}
306                                 ScEmptyCellToken( const ScEmptyCellToken& r ) :
307                                     ScToken( r ),
308                                     bInherited( r.bInherited ),
309                                     bDisplayedAsString( r.bDisplayedAsString ) {}
310             bool                IsInherited() const { return bInherited; }
311             bool                IsDisplayedAsString() const { return bDisplayedAsString; }
312     virtual double              GetDouble() const;
313     virtual const String &      GetString() const;
314     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
315     virtual FormulaToken*       Clone() const { return new ScEmptyCellToken(*this); }
316 };
317 
318 
319 /**  Transports the result from the interpreter to the formula cell. */
320 class SC_DLLPUBLIC ScMatrixCellResultToken : public ScToken
321 {
322     // No non-const access implemented, silence down unxsols4 complaining about
323     // the public GetMatrix() hiding the one from ScToken.
324     virtual ScMatrix*           GetMatrix();
325 
326 protected:
327             ScConstMatrixRef    xMatrix;
328             formula::FormulaConstTokenRef     xUpperLeft;
329 public:
330                                 ScMatrixCellResultToken( ScMatrix* pMat, formula::FormulaToken* pUL ) :
331                                     ScToken( formula::svMatrixCell ),
332                                     xMatrix( pMat), xUpperLeft( pUL) {}
333                                 ScMatrixCellResultToken( const ScMatrixCellResultToken& r ) :
334                                     ScToken( r ), xMatrix( r.xMatrix ),
335                                     xUpperLeft( r.xUpperLeft ) {}
336     virtual double              GetDouble() const;
337     virtual const String &      GetString() const;
338     virtual const ScMatrix*     GetMatrix() const;
339     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
340     virtual FormulaToken*       Clone() const { return new ScMatrixCellResultToken(*this); }
341     formula::StackVar           GetUpperLeftType() const
342                                     {
343                                         return xUpperLeft ?
344                                             xUpperLeft->GetType() :
345                                             static_cast<formula::StackVar>(formula::svUnknown);
346                                     }
347     inline formula::FormulaConstTokenRef     GetUpperLeftToken() const   { return xUpperLeft; }
348             void                Assign( const ScMatrixCellResultToken & r )
349                                     {
350                                         xMatrix = r.xMatrix;
351                                         xUpperLeft = r.xUpperLeft;
352                                     }
353 };
354 
355 
356 /** Stores the matrix result at the formula cell, additionally the range the
357     matrix formula occupies. */
358 class SC_DLLPUBLIC ScMatrixFormulaCellToken : public ScMatrixCellResultToken
359 {
360 private:
361             SCROW               nRows;
362             SCCOL               nCols;
363 public:
364                                 ScMatrixFormulaCellToken( SCCOL nC, SCROW nR ) :
365                                     ScMatrixCellResultToken( NULL, NULL ),
366                                     nRows( nR ), nCols( nC ) {}
367                                 ScMatrixFormulaCellToken( const ScMatrixFormulaCellToken& r ) :
368                                     ScMatrixCellResultToken( r ),
369                                     nRows( r.nRows ), nCols( r.nCols )
370                                     {
371                                         // xUpperLeft is modifiable through
372                                         // SetUpperLeftDouble(), so clone it.
373                                         if (xUpperLeft)
374                                             xUpperLeft = xUpperLeft->Clone();
375                                     }
376     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
377     virtual FormulaToken*       Clone() const { return new ScMatrixFormulaCellToken(*this); }
378             void                SetMatColsRows( SCCOL nC, SCROW nR )
379                                     {
380                                         nRows = nR;
381                                         nCols = nC;
382                                     }
383             void                GetMatColsRows( SCCOL & nC, SCROW & nR ) const
384                                     {
385                                         nR = nRows;
386                                         nC = nCols;
387                                     }
388             SCCOL               GetMatCols() const  { return nCols; }
389             SCROW               GetMatRows() const  { return nRows; }
390 
391                                 /** Assign matrix result, keep matrix formula
392                                     dimension. */
393             void                Assign( const ScMatrixCellResultToken & r )
394                                     {
395                                         ScMatrixCellResultToken::Assign( r);
396                                     }
397 
398                                 /** Assign any result, keep matrix formula
399                                     dimension. If token is of type
400                                     ScMatrixCellResultToken uses the
401                                     appropriate Assign() call, other tokens
402                                     are assigned to xUpperLeft and xMatrix will
403                                     be assigned NULL. */
404             void                Assign( const formula::FormulaToken & r );
405 
406                                 /** Modify xUpperLeft if formula::svDouble, or create
407                                     new formula::FormulaDoubleToken if not set yet. Does
408                                     nothing if xUpperLeft is of different type! */
409             void                SetUpperLeftDouble( double f);
410 
411                                 /** Reset matrix and upper left, keep matrix
412                                     formula dimension. */
413             void                ResetResult()
414                                     {
415                                         xMatrix = NULL;
416                                         xUpperLeft = NULL;
417                                     }
418 };
419 
420 
421 class SC_DLLPUBLIC ScHybridCellToken : public ScToken
422 {
423 private:
424             double              fDouble;
425             String              aString;
426             String              aFormula;
427 public:
428                                 ScHybridCellToken( double f,
429                                         const String & rStr,
430                                         const String & rFormula ) :
431                                     ScToken( formula::svHybridCell ),
432                                     fDouble( f ), aString( rStr ),
433                                     aFormula( rFormula ) {}
434                                 ScHybridCellToken( const ScHybridCellToken& r ) :
435                                     ScToken( r ), fDouble( r.fDouble),
436                                     aString( r.aString), aFormula( r.aFormula) {}
437             const String &      GetFormula() const  { return aFormula; }
438     virtual double              GetDouble() const;
439     virtual const String &      GetString() const;
440     virtual sal_Bool                operator==( const formula::FormulaToken& rToken ) const;
441     virtual FormulaToken*       Clone() const { return new ScHybridCellToken(*this); }
442 };
443 
444 
445 // Simplify argument passing to RefUpdate methods with ScSingleRefToken or
446 // ScDoubleRefToken
447 class SingleDoubleRefModifier
448 {
449     ScComplexRefData    aDub;
450     ScSingleRefData*  pS;
451     ScComplexRefData*   pD;
452 
453                 // not implemented, prevent usage
454                 SingleDoubleRefModifier( const SingleDoubleRefModifier& );
455         SingleDoubleRefModifier& operator=( const SingleDoubleRefModifier& );
456 
457 public:
458                 SingleDoubleRefModifier( ScToken& rT )
459                     {
460                         if ( rT.GetType() == formula::svSingleRef )
461                         {
462                             pS = &rT.GetSingleRef();
463                             aDub.Ref1 = aDub.Ref2 = *pS;
464                             pD = &aDub;
465                         }
466                         else
467                         {
468                             pS = 0;
469                             pD = &rT.GetDoubleRef();
470                         }
471                     }
472                 SingleDoubleRefModifier( ScSingleRefData& rS )
473                     {
474                         pS = &rS;
475                         aDub.Ref1 = aDub.Ref2 = *pS;
476                         pD = &aDub;
477                     }
478                 ~SingleDoubleRefModifier()
479                     {
480                         if ( pS )
481                             *pS = (*pD).Ref1;
482                     }
483     inline  ScComplexRefData& Ref() { return *pD; }
484 };
485 
486 class SingleDoubleRefProvider
487 {
488 public:
489 
490     const ScSingleRefData&    Ref1;
491     const ScSingleRefData&    Ref2;
492 
493                 SingleDoubleRefProvider( const ScToken& r )
494                         : Ref1( r.GetSingleRef() ),
495                         Ref2( r.GetType() == formula::svDoubleRef ?
496                         r.GetDoubleRef().Ref2 : Ref1 )
497                     {}
498                 SingleDoubleRefProvider( const ScSingleRefData& r )
499                         : Ref1( r ), Ref2( r )
500                     {}
501                 SingleDoubleRefProvider( const ScComplexRefData& r )
502                         : Ref1( r.Ref1 ), Ref2( r.Ref2 )
503                     {}
504                 ~SingleDoubleRefProvider()
505                     {}
506 };
507 
508 #endif
509