Version 4.3.0.0.beta1, tag libreoffice-4.3.0.0.beta1
[LibreOffice.git] / starmath / inc / node.hxx
blob220e30d2ffc9d22fe80586d99ff9f6f4157be011
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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_STARMATH_INC_NODE_HXX
21 #define INCLUDED_STARMATH_INC_NODE_HXX
23 #include <vector>
24 #include <ostream>
25 #include <stdio.h>
27 #include "parse.hxx"
28 #include "types.hxx"
29 #include "rect.hxx"
30 #include "format.hxx"
33 #define ATTR_BOLD 0x0001
34 #define ATTR_ITALIC 0x0002
37 #define FNTSIZ_ABSOLUT 1
38 #define FNTSIZ_PLUS 2
39 #define FNTSIZ_MINUS 3
40 #define FNTSIZ_MULTIPLY 4
41 #define FNTSIZ_DIVIDE 5
43 // flags to interdict respective status changes
44 #define FLG_FONT 0x0001
45 #define FLG_SIZE 0x0002
46 #define FLG_BOLD 0x0004
47 #define FLG_ITALIC 0x0008
48 #define FLG_COLOR 0x0010
49 #define FLG_VISIBLE 0x0020
50 #define FLG_HORALIGN 0x0040
53 extern SmFormat *pActiveFormat;
55 class SmVisitor;
56 class SmDocShell;
57 class SmNode;
58 class SmStructureNode;
60 typedef boost::shared_ptr<SmNode> SmNodePointer;
61 typedef std::vector< SmNode * > SmNodeArray;
62 typedef std::vector< SmStructureNode * > SmStructureNodeArray;
67 enum SmScaleMode { SCALE_NONE, SCALE_WIDTH, SCALE_HEIGHT };
69 enum SmNodeType
71 /* 0*/ NTABLE, NBRACE, NBRACEBODY, NOPER, NALIGN,
72 /* 5*/ NATTRIBUT, NFONT, NUNHOR, NBINHOR, NBINVER,
73 /*10*/ NBINDIAGONAL, NSUBSUP, NMATRIX, NPLACE, NTEXT,
74 /*15*/ NSPECIAL, NGLYPH_SPECIAL, NMATH, NBLANK, NERROR,
75 /*20*/ NLINE, NEXPRESSION, NPOLYLINE, NROOT, NROOTSYMBOL,
76 /*25*/ NRECTANGLE, NVERTICAL_BRACE, NMATHIDENT, NDYNINT, NDYNINTSYMBOL
83 class SmNode : public SmRect
85 SmFace aFace;
87 SmToken aNodeToken;
88 SmNodeType eType;
89 SmScaleMode eScaleMode;
90 RectHorAlign eRectHorAlign;
91 sal_uInt16 nFlags,
92 nAttributes;
93 bool bIsPhantom,
94 bIsDebug;
96 bool bIsSelected;
98 protected:
99 SmNode(SmNodeType eNodeType, const SmToken &rNodeToken);
101 // index in accessible text -1 if not (yet) applicable
102 sal_Int32 nAccIndex;
104 public:
105 virtual ~SmNode();
107 virtual bool IsVisible() const;
109 virtual sal_uInt16 GetNumSubNodes() const;
110 virtual SmNode * GetSubNode(sal_uInt16 nIndex);
111 const SmNode * GetSubNode(sal_uInt16 nIndex) const
113 return const_cast<SmNode *>(this)->GetSubNode(nIndex);
116 virtual SmNode * GetLeftMost();
117 const SmNode * GetLeftMost() const
119 return const_cast<SmNode *>(this)->GetLeftMost();
122 sal_uInt16 & Flags() { return nFlags; }
123 sal_uInt16 & Attributes() { return nAttributes; }
125 bool IsDebug() const { return bIsDebug; }
126 bool IsPhantom() const { return bIsPhantom; }
127 void SetPhantom(bool bIsPhantom);
128 void SetColor(const Color &rColor);
130 void SetAttribut(sal_uInt16 nAttrib);
131 void ClearAttribut(sal_uInt16 nAttrib);
133 const SmFace & GetFont() const { return aFace; };
134 SmFace & GetFont() { return aFace; };
136 void SetFont(const SmFace &rFace);
137 void SetFontSize(const Fraction &rRelSize, sal_uInt16 nType);
138 void SetSize(const Fraction &rScale);
140 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell);
141 virtual void PrepareAttributes();
143 sal_uInt16 FindIndex() const;
145 #if OSL_DEBUG_LEVEL
146 void ToggleDebug() const;
147 #endif
149 void SetRectHorAlign(RectHorAlign eHorAlign, bool bApplyToSubTree = true );
150 RectHorAlign GetRectHorAlign() const { return eRectHorAlign; }
152 const SmRect & GetRect() const { return *this; }
153 SmRect & GetRect() { return *this; }
155 virtual void Move(const Point &rPosition);
156 void MoveTo(const Point &rPosition) { Move(rPosition - GetTopLeft()); }
157 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat);
158 virtual void CreateTextFromNode(OUString &rText);
160 virtual void GetAccessibleText( OUStringBuffer &rText ) const;
161 sal_Int32 GetAccessibleIndex() const { return nAccIndex; }
162 const SmNode * FindNodeWithAccessibleIndex(sal_Int32 nAccIndex) const;
164 sal_uInt16 GetRow() const { return (sal_uInt16)aNodeToken.nRow; }
165 sal_uInt16 GetColumn() const { return (sal_uInt16)aNodeToken.nCol; }
167 SmScaleMode GetScaleMode() const { return eScaleMode; }
168 void SetScaleMode(SmScaleMode eMode) { eScaleMode = eMode; }
170 virtual void AdaptToX(const OutputDevice &rDev, sal_uLong nWidth);
171 virtual void AdaptToY(const OutputDevice &rDev, sal_uLong nHeight);
173 SmNodeType GetType() const { return eType; }
174 const SmToken & GetToken() const { return aNodeToken; }
176 const SmNode * FindTokenAt(sal_uInt16 nRow, sal_uInt16 nCol) const;
177 const SmNode * FindRectClosestTo(const Point &rPoint) const;
179 virtual long GetFormulaBaseline() const;
181 /** Accept a visitor
182 * Calls the method for this class on the visitor
184 virtual void Accept(SmVisitor* pVisitor);
186 /** True if this node is selected */
187 bool IsSelected() const {return bIsSelected;}
188 void SetSelected(bool Selected = true) {bIsSelected = Selected;}
190 #ifdef DEBUG_ENABLE_DUMPASDOT
191 /** The tree as dot graph for graphviz, usable for debugging
192 * Convert the output to a image using $ dot graph.gv -Tpng > graph.png
194 inline void DumpAsDot(std::ostream &out, OUString* label = NULL) const{
195 int id = 0;
196 DumpAsDot(out, label, -1, id, -1);
198 #endif /* DEBUG_ENABLE_DUMPASDOT */
200 /** Get the parent node of this node */
201 SmStructureNode* GetParent(){ return aParentNode; }
202 const SmStructureNode* GetParent() const { return aParentNode; }
203 /** Set the parent node */
204 void SetParent(SmStructureNode* parent){
205 aParentNode = parent;
208 /** Get the index of a child node
210 * Returns -1, if pSubNode isn't a subnode of this.
212 int IndexOfSubNode(SmNode* pSubNode){
213 sal_uInt16 nSize = GetNumSubNodes();
214 for(sal_uInt16 i = 0; i < nSize; i++)
215 if(pSubNode == GetSubNode(i))
216 return i;
217 return -1;
219 /** Set the token for this node */
220 void SetToken(SmToken& token){
221 aNodeToken = token;
223 protected:
224 /** Sets parent on children of this node */
225 void ClaimPaternity(){
226 SmNode* pNode;
227 sal_uInt16 nSize = GetNumSubNodes();
228 for (sal_uInt16 i = 0; i < nSize; i++)
229 if (NULL != (pNode = GetSubNode(i)))
230 pNode->SetParent((SmStructureNode*)this); //Cast is valid if we have children
232 private:
233 SmStructureNode* aParentNode;
234 void DumpAsDot(std::ostream &out, OUString* label, int number, int& id, int parent) const;
239 /** A simple auxiliary iterator class for SmNode
241 * Example of iteration over children of pMyNode:
242 * \code
243 * //Node to iterate over:
244 * SmNode* pMyNode = 0;// A pointer from somewhere
245 * //The iterator:
246 * SmNodeIterator it(pMyNode);
247 * //The iteration:
248 * while(it.Next()) {
249 * it->SetSelected(true);
251 * \endcode
253 class SmNodeIterator{
254 public:
255 SmNodeIterator(SmNode* node, bool bReverse = false){
256 pNode = node;
257 nSize = pNode->GetNumSubNodes();
258 nIndex = 0;
259 pChildNode = NULL;
260 bIsReverse = bReverse;
262 /** Get the subnode or NULL if none */
263 SmNode* Next(){
264 while(!bIsReverse && nIndex < nSize){
265 if(NULL != (pChildNode = pNode->GetSubNode(nIndex++)))
266 return pChildNode;
268 while(bIsReverse && nSize > 0){
269 if(NULL != (pChildNode = pNode->GetSubNode((nSize--)-1)))
270 return pChildNode;
272 pChildNode = NULL;
273 return NULL;
275 /** Get the current child node, NULL if none */
276 SmNode* Current(){
277 return pChildNode;
279 /** Get the current child node, NULL if none */
280 SmNode* operator->(){
281 return pChildNode;
283 private:
284 /** Current child */
285 SmNode* pChildNode;
286 /** Node whos children we're iterating over */
287 SmNode* pNode;
288 /** Size of the node */
289 sal_uInt16 nSize;
290 /** Current index in the node */
291 sal_uInt16 nIndex;
292 /** Move reverse */
293 bool bIsReverse;
298 /** Abstract baseclass for all composite node
300 * Subclasses of this class can have subnodes. Nodes that doesn't derivate from
301 * this class does not have subnodes.
303 class SmStructureNode : public SmNode
305 SmNodeArray aSubNodes;
307 protected:
308 SmStructureNode(SmNodeType eNodeType, const SmToken &rNodeToken)
309 : SmNode(eNodeType, rNodeToken)
312 public:
313 SmStructureNode( const SmStructureNode &rNode );
314 virtual ~SmStructureNode();
316 virtual bool IsVisible() const SAL_OVERRIDE;
318 virtual sal_uInt16 GetNumSubNodes() const SAL_OVERRIDE;
319 void SetNumSubNodes(sal_uInt16 nSize) { aSubNodes.resize(nSize); }
321 using SmNode::GetSubNode;
322 virtual SmNode * GetSubNode(sal_uInt16 nIndex) SAL_OVERRIDE;
323 void SetSubNodes(SmNode *pFirst, SmNode *pSecond, SmNode *pThird = NULL);
324 void SetSubNodes(const SmNodeArray &rNodeArray);
326 SmStructureNode & operator = ( const SmStructureNode &rNode );
328 virtual void GetAccessibleText( OUStringBuffer &rText ) const SAL_OVERRIDE;
330 void SetSubNode(size_t nIndex, SmNode* pNode)
332 size_t size = aSubNodes.size();
333 if (size <= nIndex)
335 //Resize subnodes array
336 aSubNodes.resize(nIndex + 1);
337 //Set new slots to NULL
338 for (size_t i = size; i < nIndex+1; i++)
339 aSubNodes[i] = NULL;
341 aSubNodes[nIndex] = pNode;
342 ClaimPaternity();
349 /** Abstract base class for all visible node
351 * Nodes that doesn't derivate from this class doesn't draw anything, but their
352 * children.
354 class SmVisibleNode : public SmNode
356 protected:
357 SmVisibleNode(SmNodeType eNodeType, const SmToken &rNodeToken)
358 : SmNode(eNodeType, rNodeToken)
361 public:
363 virtual bool IsVisible() const SAL_OVERRIDE;
364 virtual sal_uInt16 GetNumSubNodes() const SAL_OVERRIDE;
365 using SmNode::GetSubNode;
366 virtual SmNode * GetSubNode(sal_uInt16 nIndex) SAL_OVERRIDE;
373 class SmGraphicNode : public SmVisibleNode
375 protected:
376 SmGraphicNode(SmNodeType eNodeType, const SmToken &rNodeToken)
377 : SmVisibleNode(eNodeType, rNodeToken)
380 public:
382 virtual void GetAccessibleText( OUStringBuffer &rText ) const SAL_OVERRIDE;
388 /** Draws a rectangle
390 * Used for drawing the line in the OVER and OVERSTRIKE commands.
392 class SmRectangleNode : public SmGraphicNode
394 Size aToSize;
396 public:
397 SmRectangleNode(const SmToken &rNodeToken)
398 : SmGraphicNode(NRECTANGLE, rNodeToken)
401 virtual void AdaptToX(const OutputDevice &rDev, sal_uLong nWidth) SAL_OVERRIDE;
402 virtual void AdaptToY(const OutputDevice &rDev, sal_uLong nHeight) SAL_OVERRIDE;
404 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
406 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
407 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
413 /** Polygon line node
415 * Used to draw the slash of the WIDESLASH command by SmBinDiagonalNode.
417 class SmPolyLineNode : public SmGraphicNode
419 Polygon aPoly;
420 Size aToSize;
421 long nWidth;
423 public:
424 SmPolyLineNode(const SmToken &rNodeToken);
426 long GetWidth() const { return nWidth; }
427 Size GetToSize() const { return aToSize; }
428 Polygon &GetPolygon() { return aPoly; }
430 virtual void AdaptToX(const OutputDevice &rDev, sal_uLong nWidth) SAL_OVERRIDE;
431 virtual void AdaptToY(const OutputDevice &rDev, sal_uLong nHeight) SAL_OVERRIDE;
433 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
435 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
441 /** Text node
443 * @remarks This class also serves as baseclass for all nodes that contains text.
445 class SmTextNode : public SmVisibleNode
447 OUString aText;
448 sal_uInt16 nFontDesc;
449 /** Index within text where the selection starts
450 * @remarks Only valid if SmNode::IsSelected() is true
452 sal_Int32 nSelectionStart;
453 /** Index within text where the selection ends
454 * @remarks Only valid if SmNode::IsSelected() is true
456 sal_Int32 nSelectionEnd;
458 protected:
459 SmTextNode(SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 nFontDescP );
461 public:
462 SmTextNode(const SmToken &rNodeToken, sal_uInt16 nFontDescP );
464 sal_uInt16 GetFontDesc() const { return nFontDesc; }
465 void SetText(const OUString &rText) { aText = rText; }
466 const OUString & GetText() const { return aText; }
467 /** Change the text of this node, including the underlying token */
468 void ChangeText(const OUString &rText) {
469 aText = rText;
470 SmToken token = GetToken();
471 token.aText = rText;
472 SetToken(token); //TODO: Merge this with AdjustFontDesc for better performance
473 AdjustFontDesc();
475 /** Try to guess the correct FontDesc, used during visual editing */
476 void AdjustFontDesc();
477 /** Index within GetText() where the selection starts
478 * @remarks Only valid of SmNode::IsSelected() is true
480 sal_Int32 GetSelectionStart() const {return nSelectionStart;}
481 /** Index within GetText() where the selection end
482 * @remarks Only valid of SmNode::IsSelected() is true
484 sal_Int32 GetSelectionEnd() const {return nSelectionEnd;}
485 /** Set the index within GetText() where the selection starts */
486 void SetSelectionStart(sal_Int32 index) {nSelectionStart = index;}
487 /** Set the index within GetText() where the selection end */
488 void SetSelectionEnd(sal_Int32 index) {nSelectionEnd = index;}
490 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) SAL_OVERRIDE;
491 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
492 virtual void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
494 virtual void GetAccessibleText( OUStringBuffer &rText ) const SAL_OVERRIDE;
495 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
497 Converts the character from StarMath's private area symbols to a matching Unicode
498 character, if necessary. To be used when converting GetText() to a normal text.
500 static sal_Unicode ConvertSymbolToUnicode(sal_Unicode nIn);
506 /** Special node for user defined characters
508 * Node used for pre- and user-defined characters from:
509 * officecfg/registry/data/org/openoffice/Office/Math.xcu
511 * This is just single characters, I think.
513 class SmSpecialNode : public SmTextNode
515 bool bIsFromGreekSymbolSet;
517 protected:
518 SmSpecialNode(SmNodeType eNodeType, const SmToken &rNodeToken, sal_uInt16 _nFontDesc);
520 public:
521 SmSpecialNode(const SmToken &rNodeToken);
523 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) SAL_OVERRIDE;
524 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
526 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
532 /** Glyph node for custom operators
534 * This node is used with commands: oper, uoper and boper.
535 * E.g. in "A boper op B", "op" will be an instance of SmGlyphSpecialNode.
536 * "boper" simply inteprets "op", the following token, as an binary operator.
537 * The command "uoper" interprets the following token as unary operator.
538 * For these commands an instance of SmGlyphSpecialNode is used for the
539 * operator token, following the command.
541 class SmGlyphSpecialNode : public SmSpecialNode
543 public:
544 SmGlyphSpecialNode(const SmToken &rNodeToken)
545 : SmSpecialNode(NGLYPH_SPECIAL, rNodeToken, FNT_MATH)
548 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
549 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
555 /** Math symbol node
557 * Use for math symbols such as plus, minus and integrale in the INT command.
559 class SmMathSymbolNode : public SmSpecialNode
561 protected:
562 SmMathSymbolNode(SmNodeType eNodeType, const SmToken &rNodeToken)
563 : SmSpecialNode(eNodeType, rNodeToken, FNT_MATH)
565 sal_Unicode cChar = GetToken().cMathChar;
566 if ((sal_Unicode) '\0' != cChar)
567 SetText(OUString(cChar));
570 public:
571 SmMathSymbolNode(const SmToken &rNodeToken);
573 virtual void AdaptToX(const OutputDevice &rDev, sal_uLong nWidth) SAL_OVERRIDE;
574 virtual void AdaptToY(const OutputDevice &rDev, sal_uLong nHeight) SAL_OVERRIDE;
576 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) SAL_OVERRIDE;
577 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
578 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
579 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
584 /** Math Identifier
586 * This behaves essentially the same as SmMathSymbolNode and is only used to
587 * represent math symbols that should be exported as <mi> elements rather than
588 * <mo> elements.
590 class SmMathIdentifierNode : public SmMathSymbolNode
592 public:
593 SmMathIdentifierNode(const SmToken &rNodeToken)
594 : SmMathSymbolNode(NMATHIDENT, rNodeToken) {}
599 /** Root symbol node
601 * Root symbol node used by SmRootNode to create the root symbol, in front of
602 * the line with the line above. I don't think this node should be used for
603 * anything else.
605 class SmRootSymbolNode : public SmMathSymbolNode
607 sal_uLong nBodyWidth; // width of body (argument) of root sign
609 public:
610 SmRootSymbolNode(const SmToken &rNodeToken)
611 : SmMathSymbolNode(NROOTSYMBOL, rNodeToken)
612 , nBodyWidth(0)
616 sal_uLong GetBodyWidth() const {return nBodyWidth;};
617 virtual void AdaptToX(const OutputDevice &rDev, sal_uLong nHeight) SAL_OVERRIDE;
618 virtual void AdaptToY(const OutputDevice &rDev, sal_uLong nHeight) SAL_OVERRIDE;
620 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
624 /** Dynamic Integral symbol node
626 * Node for drawing dynamically sized integral symbols.
628 * TODO: It might be created a parent class SmDynamicSizedNode
629 (for both dynamic integrals, roots and other dynamic symbols)
632 class SmDynIntegralSymbolNode : public SmMathSymbolNode
636 public:
637 SmDynIntegralSymbolNode(const SmToken &rNodeToken)
638 : SmMathSymbolNode(NDYNINTSYMBOL, rNodeToken)
641 virtual void AdaptToY(const OutputDevice &rDev, sal_uLong nHeight) SAL_OVERRIDE;
643 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
649 /** Place node
651 * Used to create the <?> command, that denotes place where something can be
652 * written.
653 * It is drawn as a square with a shadow.
655 class SmPlaceNode : public SmMathSymbolNode
657 public:
658 SmPlaceNode(const SmToken &rNodeToken)
659 : SmMathSymbolNode(NPLACE, rNodeToken)
662 SmPlaceNode() : SmMathSymbolNode(NPLACE, SmToken(TPLACE, MS_PLACE, "<?>")) {};
664 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) SAL_OVERRIDE;
665 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
666 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
672 /** Error node, for parsing errors
674 * This node is used for parsing errors and draws an questionmark turned upside
675 * down (inverted question mark).
677 class SmErrorNode : public SmMathSymbolNode
679 public:
680 SmErrorNode(SmParseError /*eError*/, const SmToken &rNodeToken)
681 : SmMathSymbolNode(NERROR, rNodeToken)
683 SetText(OUString(MS_ERROR));
686 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) SAL_OVERRIDE;
687 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
688 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
694 /** Table node
696 * This is the root node for the formula tree. This node is also used for the
697 * STACK and BINOM commands. When used for root node, its
698 * children are instances of SmLineNode, and in some obscure cases the a child
699 * can be an instance of SmExpressionNode, mainly when errors occur.
701 class SmTableNode : public SmStructureNode
703 long nFormulaBaseline;
704 public:
705 SmTableNode(const SmToken &rNodeToken)
706 : SmStructureNode(NTABLE, rNodeToken)
707 , nFormulaBaseline(0)
711 using SmNode::GetLeftMost;
712 virtual SmNode * GetLeftMost() SAL_OVERRIDE;
714 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
715 virtual long GetFormulaBaseline() const SAL_OVERRIDE;
717 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
723 /** A line
725 * Used as child of SmTableNode when the SmTableNode is the root node of the
726 * formula tree.
728 class SmLineNode : public SmStructureNode
730 bool bUseExtraSpaces;
732 protected:
733 SmLineNode(SmNodeType eNodeType, const SmToken &rNodeToken)
734 : SmStructureNode(eNodeType, rNodeToken)
736 bUseExtraSpaces = true;
739 public:
740 SmLineNode(const SmToken &rNodeToken)
741 : SmStructureNode(NLINE, rNodeToken)
743 bUseExtraSpaces = true;
746 void SetUseExtraSpaces(bool bVal) { bUseExtraSpaces = bVal; }
747 bool IsUseExtraSpaces() const { return bUseExtraSpaces; };
749 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) SAL_OVERRIDE;
750 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
751 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
757 /** Expression node
759 * Used whenever you have an expression such as "A OVER {B + C}", here there is
760 * an expression node that allows "B + C" to be the denominator of the
761 * SmBinVerNode, that the OVER command creates.
763 class SmExpressionNode : public SmLineNode
765 public:
766 SmExpressionNode(const SmToken &rNodeToken)
767 : SmLineNode(NEXPRESSION, rNodeToken)
770 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
771 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
772 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
778 /** Unary horizontal node
780 * The same as SmBinHorNode except this is for unary operators.
782 class SmUnHorNode : public SmStructureNode
784 public:
785 SmUnHorNode(const SmToken &rNodeToken)
786 : SmStructureNode(NUNHOR, rNodeToken)
788 SetNumSubNodes(2);
791 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
792 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
798 /** Root node
800 * Used for create square roots and other roots, example:
801 * \f$ \sqrt[\mbox{[Argument]}]{\mbox{[Body]}} \f$.
803 * Children:<BR>
804 * 0: Argument (optional)<BR>
805 * 1: Symbol (instance of SmRootSymbolNode)<BR>
806 * 2: Body<BR>
807 * Where argument is optional and may be NULL.
809 class SmRootNode : public SmStructureNode
811 protected:
812 void GetHeightVerOffset(const SmRect &rRect,
813 long &rHeight, long &rVerOffset) const;
814 Point GetExtraPos(const SmRect &rRootSymbol, const SmRect &rExtra) const;
816 public:
817 SmRootNode(const SmToken &rNodeToken)
818 : SmStructureNode(NROOT, rNodeToken)
820 SetNumSubNodes(3);
823 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
824 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
825 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
827 SmNode* Argument();
828 const SmNode* Argument() const;
829 SmRootSymbolNode* Symbol();
830 const SmRootSymbolNode* Symbol() const;
831 SmNode* Body();
832 const SmNode* Body() const;
836 /** Dynamic Integral node
838 * Used to create Dynamically sized integrals
840 * Children:<BR>
841 * 0: Symbol (instance of DynIntegralSymbolNode)<BR>
842 * 1: Body<BR>
844 class SmDynIntegralNode : public SmStructureNode
846 protected:
847 void GetHeightVerOffset(const SmRect &rRect,
848 long &rHeight, long &rVerOffset) const;
850 public:
851 SmDynIntegralNode(const SmToken &rNodeToken)
852 : SmStructureNode(NDYNINT, rNodeToken)
854 SetNumSubNodes(2);
857 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
858 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
859 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
861 SmDynIntegralSymbolNode* Symbol();
862 const SmDynIntegralSymbolNode* Symbol() const;
863 SmNode* Body();
864 const SmNode* Body() const;
870 /** Binary horizontal node
872 * This node is used for binary operators. In a formula such as "A + B".
874 * Children:<BR>
875 * 0: Left operand<BR>
876 * 1: Binary operator<BR>
877 * 2: Right operand<BR>
879 * None of the children may be NULL.
881 class SmBinHorNode : public SmStructureNode
883 public:
884 SmBinHorNode(const SmToken &rNodeToken)
885 : SmStructureNode(NBINHOR, rNodeToken)
887 SetNumSubNodes(3);
890 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
891 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
893 SmMathSymbolNode* Symbol();
894 const SmMathSymbolNode* Symbol() const;
895 SmNode* LeftOperand();
896 const SmNode* LeftOperand() const;
897 SmNode* RightOperand();
898 const SmNode* RightOperand() const;
904 /** Binary horizontal node
906 * This node is used for creating the OVER command, consider the formula:
907 * "numerator OVER denominator", which looks like
908 * \f$ \frac{\mbox{numerator}}{\mbox{denominator}} \f$
910 * Children:<BR>
911 * 0: Numerator<BR>
912 * 1: Line (instance of SmRectangleNode)<BR>
913 * 2: Denominator<BR>
914 * None of the children may be NULL.
916 class SmBinVerNode : public SmStructureNode
918 public:
919 SmBinVerNode(const SmToken &rNodeToken)
920 : SmStructureNode(NBINVER, rNodeToken)
922 SetNumSubNodes(3);
925 using SmNode::GetLeftMost;
926 virtual SmNode * GetLeftMost() SAL_OVERRIDE;
928 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
929 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
930 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
936 /** Binary diagonal node
938 * Used for implementing the WIDESLASH command, example: "A WIDESLASH B".
940 * Children:<BR>
941 * 0: Left operand<BR>
942 * 1: right operand<BR>
943 * 2: Line (instance of SmPolyLineNode).<BR>
944 * None of the children may be NULL.
946 class SmBinDiagonalNode : public SmStructureNode
948 bool bAscending;
950 void GetOperPosSize(Point &rPos, Size &rSize,
951 const Point &rDiagPoint, double fAngleDeg) const;
953 public:
954 SmBinDiagonalNode(const SmToken &rNodeToken);
956 bool IsAscending() const { return bAscending; }
957 void SetAscending(bool bVal) { bAscending = bVal; }
959 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
960 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
967 /** Enum used to index sub-/supscripts in the 'aSubNodes' array
968 * in 'SmSubSupNode'
970 * See graphic for positions at char:
972 * \code
973 * CSUP
975 * LSUP H H RSUP
976 * H H
977 * HHHH
978 * H H
979 * LSUB H H RSUB
981 * CSUB
982 * \endcode
984 enum SmSubSup
985 { CSUB, CSUP, RSUB, RSUP, LSUB, LSUP
988 /** numbers of entries in the above enum (that is: the number of possible
989 * sub-/supscripts)
991 #define SUBSUP_NUM_ENTRIES 6
993 /** Super- and subscript node
995 * Used for creating super- and subscripts for commands such as:
996 * "^", "_", "lsup", "lsub", "csup" and "csub".
997 * Example: "A^2" which looks like: \f$ A^2 \f$
999 * This node is also used for creating limits on SmOperNode, when
1000 * "FROM" and "TO" commands are used with "INT", "SUM" or similar.
1002 * Children of this node can be enumerated using the SmSubSup enum.
1003 * Please note that children may be NULL, except for the body.
1004 * It is recommended that you access children using GetBody() and
1005 * GetSubSup().
1007 class SmSubSupNode : public SmStructureNode
1009 bool bUseLimits;
1011 public:
1012 SmSubSupNode(const SmToken &rNodeToken)
1013 : SmStructureNode(NSUBSUP, rNodeToken)
1015 SetNumSubNodes(1 + SUBSUP_NUM_ENTRIES);
1016 bUseLimits = false;
1019 /** Get body (Not NULL) */
1020 SmNode * GetBody() { return GetSubNode(0); }
1021 /** Get body (Not NULL) */
1022 const SmNode * GetBody() const
1024 return ((SmSubSupNode *) this)->GetBody();
1027 void SetUseLimits(bool bVal) { bUseLimits = bVal; }
1028 bool IsUseLimits() const { return bUseLimits; };
1030 /** Get super- or subscript
1031 * @remarks this method may return NULL.
1033 SmNode * GetSubSup(SmSubSup eSubSup) { return GetSubNode( sal::static_int_cast< sal_uInt16 >(1 + eSubSup) ); };
1034 const SmNode * GetSubSup(SmSubSup eSubSup) const { return const_cast< SmSubSupNode* >( this )->GetSubSup( eSubSup ); }
1036 /** Set the body */
1037 void SetBody(SmNode* pBody) { SetSubNode(0, pBody); }
1038 void SetSubSup(SmSubSup eSubSup, SmNode* pScript) { SetSubNode( 1 + eSubSup, pScript); }
1040 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1041 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
1042 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1049 /** Node for brace construction
1051 * Used for "lbrace [body] rbrace" and similar constructions.
1052 * Should look like \f$ \{\mbox{[body]}\} \f$
1054 * Children:<BR>
1055 * 0: Opening brace<BR>
1056 * 1: Body (usually SmBracebodyNode)<BR>
1057 * 2: Closing brace<BR>
1058 * None of the children can be NULL.
1060 * Note that child 1 (Body) is usually SmBracebodyNode, but it can also be e.g. SmExpressionNode.
1062 class SmBraceNode : public SmStructureNode
1064 public:
1065 SmBraceNode(const SmToken &rNodeToken)
1066 : SmStructureNode(NBRACE, rNodeToken)
1068 SetNumSubNodes(3);
1071 SmMathSymbolNode* OpeningBrace();
1072 const SmMathSymbolNode* OpeningBrace() const;
1073 SmNode* Body();
1074 const SmNode* Body() const;
1075 SmMathSymbolNode* ClosingBrace();
1076 const SmMathSymbolNode* ClosingBrace() const;
1078 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1079 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
1080 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1086 /** Body of an SmBraceNode
1088 * This usually only has one child an SmExpressionNode, however, it can also
1089 * have other children.
1090 * Consider the formula "lbrace [body1] mline [body2] rbrace", looks like:
1091 * \f$ \{\mbox{[body1] | [body2]}\} \f$.
1092 * In this case SmBracebodyNode will have three children, "[body1]", "|" and
1093 * [body2].
1095 class SmBracebodyNode : public SmStructureNode
1097 long nBodyHeight;
1099 public:
1100 inline SmBracebodyNode(const SmToken &rNodeToken);
1102 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1103 long GetBodyHeight() const { return nBodyHeight; }
1104 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1108 inline SmBracebodyNode::SmBracebodyNode(const SmToken &rNodeToken) :
1109 SmStructureNode(NBRACEBODY, rNodeToken)
1111 nBodyHeight = 0;
1117 /** Node for vertical brace construction
1119 * Used to implement commands "[body] underbrace [script]" and
1120 * "[body] overbrace [script]".
1121 * Underbrace should look like this \f$ \underbrace{\mbox{body}}_{\mbox{script}}\f$.
1123 * Children:<BR>
1124 * 0: body<BR>
1125 * 1: brace<BR>
1126 * 2: script<BR>
1127 * (None of these children are optional, e.g. they must all be not NULL).
1129 class SmVerticalBraceNode : public SmStructureNode
1131 public:
1132 inline SmVerticalBraceNode(const SmToken &rNodeToken);
1134 SmNode* Body();
1135 const SmNode* Body() const;
1136 SmMathSymbolNode* Brace();
1137 const SmMathSymbolNode* Brace() const;
1138 SmNode* Script();
1139 const SmNode* Script() const;
1141 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1142 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1146 inline SmVerticalBraceNode::SmVerticalBraceNode(const SmToken &rNodeToken) :
1147 SmStructureNode(NVERTICAL_BRACE, rNodeToken)
1149 SetNumSubNodes(3);
1156 /** Operation Node
1158 * Used for commands like SUM, INT and similar.
1160 * Children:<BR>
1161 * 0: Operation (instance of SmMathSymbolNode or SmSubSupNode)<BR>
1162 * 1: Body<BR>
1163 * None of the children may be NULL.
1166 class SmOperNode : public SmStructureNode
1168 public:
1169 SmOperNode(const SmToken &rNodeToken)
1170 : SmStructureNode(NOPER, rNodeToken)
1172 SetNumSubNodes(2);
1175 SmNode * GetSymbol();
1176 const SmNode * GetSymbol() const
1178 return ((SmOperNode *) this)->GetSymbol();
1181 long CalcSymbolHeight(const SmNode &rSymbol, const SmFormat &rFormat) const;
1183 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1184 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1190 /** Node used for alignment
1192 class SmAlignNode : public SmStructureNode
1194 public:
1195 SmAlignNode(const SmToken &rNodeToken)
1196 : SmStructureNode(NALIGN, rNodeToken)
1199 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1200 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1206 /** Attribute node
1208 * Used to give an attribute to another node. Used for commands such as:
1209 * UNDERLINE, OVERLINE, OVERSTRIKE, WIDEVEC, WIDEHAT and WIDETILDE.
1211 * Children:<BR>
1212 * 0: Attribute<BR>
1213 * 1: Body<BR>
1214 * None of these may be NULL.
1216 class SmAttributNode : public SmStructureNode
1218 public:
1219 SmAttributNode(const SmToken &rNodeToken)
1220 : SmStructureNode(NATTRIBUT, rNodeToken)
1223 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1224 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
1225 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1227 SmNode* Attribute();
1228 const SmNode* Attribute() const;
1229 SmNode* Body();
1230 const SmNode* Body() const;
1236 /** Font node
1238 * Used to change the font of its children.
1240 class SmFontNode : public SmStructureNode
1242 sal_uInt16 nSizeType;
1243 Fraction aFontSize;
1245 public:
1246 SmFontNode(const SmToken &rNodeToken)
1247 : SmStructureNode(NFONT, rNodeToken)
1249 nSizeType = FNTSIZ_MULTIPLY;
1250 aFontSize = Fraction(1L);
1253 void SetSizeParameter(const Fraction &rValue, sal_uInt16 nType);
1254 const Fraction & GetSizeParameter() const {return aFontSize;}
1255 const sal_uInt16& GetSizeType() const {return nSizeType;}
1257 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) SAL_OVERRIDE;
1258 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1259 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
1260 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1266 /** Matrix node
1268 * Used to implement the MATRIX command, example:
1269 * "matrix{ 1 # 2 ## 3 # 4}".
1271 class SmMatrixNode : public SmStructureNode
1273 sal_uInt16 nNumRows,
1274 nNumCols;
1276 public:
1277 SmMatrixNode(const SmToken &rNodeToken)
1278 : SmStructureNode(NMATRIX, rNodeToken)
1280 nNumRows = nNumCols = 0;
1283 sal_uInt16 GetNumRows() const {return nNumRows;}
1284 sal_uInt16 GetNumCols() const {return nNumCols;}
1285 void SetRowCol(sal_uInt16 nMatrixRows, sal_uInt16 nMatrixCols);
1287 using SmNode::GetLeftMost;
1288 virtual SmNode * GetLeftMost() SAL_OVERRIDE;
1290 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1291 void CreateTextFromNode(OUString &rText) SAL_OVERRIDE;
1292 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1298 /** Node for whitespace
1300 * Used to implement the "~" command. This node is just a blank space.
1302 class SmBlankNode : public SmGraphicNode
1304 sal_uInt16 nNum;
1306 public:
1307 SmBlankNode(const SmToken &rNodeToken)
1308 : SmGraphicNode(NBLANK, rNodeToken)
1310 nNum = 0;
1313 void IncreaseBy(const SmToken &rToken);
1314 void Clear() { nNum = 0; }
1315 sal_uInt16 GetBlankNum() const { return nNum; }
1316 void SetBlankNum(sal_uInt16 nNumber) { nNum = nNumber; }
1318 virtual void Prepare(const SmFormat &rFormat, const SmDocShell &rDocShell) SAL_OVERRIDE;
1319 virtual void Arrange(const OutputDevice &rDev, const SmFormat &rFormat) SAL_OVERRIDE;
1320 void Accept(SmVisitor* pVisitor) SAL_OVERRIDE;
1327 inline SmNode* SmRootNode::Argument()
1329 OSL_ASSERT( GetNumSubNodes() > 0 );
1330 return GetSubNode( 0 );
1332 inline const SmNode* SmRootNode::Argument() const
1334 return const_cast< SmRootNode* >( this )->Argument();
1336 inline SmRootSymbolNode* SmRootNode::Symbol()
1338 OSL_ASSERT( GetNumSubNodes() > 1 && GetSubNode( 1 )->GetType() == NROOTSYMBOL );
1339 return static_cast< SmRootSymbolNode* >( GetSubNode( 1 ));
1341 inline const SmRootSymbolNode* SmRootNode::Symbol() const
1343 return const_cast< SmRootNode* >( this )->Symbol();
1345 inline SmNode* SmRootNode::Body()
1347 OSL_ASSERT( GetNumSubNodes() > 2 );
1348 return GetSubNode( 2 );
1350 inline const SmNode* SmRootNode::Body() const
1352 return const_cast< SmRootNode* >( this )->Body();
1357 inline SmDynIntegralSymbolNode* SmDynIntegralNode::Symbol()
1359 OSL_ASSERT( GetNumSubNodes() > 0 && GetSubNode( 0 )->GetType() == NDYNINTSYMBOL );
1360 return static_cast< SmDynIntegralSymbolNode* >( GetSubNode( 0 ));
1362 inline const SmDynIntegralSymbolNode* SmDynIntegralNode::Symbol() const
1364 return const_cast< SmDynIntegralNode* >( this )->Symbol();
1366 inline SmNode* SmDynIntegralNode::Body()
1368 OSL_ASSERT( GetNumSubNodes() > 1 );
1369 return GetSubNode( 1 );
1371 inline const SmNode* SmDynIntegralNode::Body() const
1373 return const_cast< SmDynIntegralNode* >( this )->Body();
1377 inline SmMathSymbolNode* SmBinHorNode::Symbol()
1379 OSL_ASSERT( GetNumSubNodes() > 1 && GetSubNode( 1 )->GetType() == NMATH );
1380 return static_cast< SmMathSymbolNode* >( GetSubNode( 1 ));
1382 inline const SmMathSymbolNode* SmBinHorNode::Symbol() const
1384 return const_cast< SmBinHorNode* >( this )->Symbol();
1386 inline SmNode* SmBinHorNode::LeftOperand()
1388 OSL_ASSERT( GetNumSubNodes() > 0 );
1389 return GetSubNode( 0 );
1391 inline const SmNode* SmBinHorNode::LeftOperand() const
1393 return const_cast< SmBinHorNode* >( this )->LeftOperand();
1395 inline SmNode* SmBinHorNode::RightOperand()
1397 OSL_ASSERT( GetNumSubNodes() > 2 );
1398 return GetSubNode( 2 );
1400 inline const SmNode* SmBinHorNode::RightOperand() const
1402 return const_cast< SmBinHorNode* >( this )->RightOperand();
1405 inline SmNode* SmAttributNode::Attribute()
1407 OSL_ASSERT( GetNumSubNodes() > 0 );
1408 return GetSubNode( 0 );
1410 inline const SmNode* SmAttributNode::Attribute() const
1412 return const_cast< SmAttributNode* >( this )->Attribute();
1414 inline SmNode* SmAttributNode::Body()
1416 OSL_ASSERT( GetNumSubNodes() > 1 );
1417 return GetSubNode( 1 );
1419 inline const SmNode* SmAttributNode::Body() const
1421 return const_cast< SmAttributNode* >( this )->Body();
1424 inline SmMathSymbolNode* SmBraceNode::OpeningBrace()
1426 OSL_ASSERT( GetNumSubNodes() > 0 && GetSubNode( 0 )->GetType() == NMATH );
1427 return static_cast< SmMathSymbolNode* >( GetSubNode( 0 ));
1429 inline const SmMathSymbolNode* SmBraceNode::OpeningBrace() const
1431 return const_cast< SmBraceNode* >( this )->OpeningBrace();
1433 inline SmNode* SmBraceNode::Body()
1435 OSL_ASSERT( GetNumSubNodes() > 1 );
1436 return GetSubNode( 1 );
1438 inline const SmNode* SmBraceNode::Body() const
1440 return const_cast< SmBraceNode* >( this )->Body();
1442 inline SmMathSymbolNode* SmBraceNode::ClosingBrace()
1444 OSL_ASSERT( GetNumSubNodes() > 2 && GetSubNode( 2 )->GetType() == NMATH );
1445 return static_cast< SmMathSymbolNode* >( GetSubNode( 2 ));
1447 inline const SmMathSymbolNode* SmBraceNode::ClosingBrace() const
1449 return const_cast< SmBraceNode* >( this )->ClosingBrace();
1452 inline SmNode* SmVerticalBraceNode::Body()
1454 OSL_ASSERT( GetNumSubNodes() > 0 );
1455 return GetSubNode( 0 );
1457 inline const SmNode* SmVerticalBraceNode::Body() const
1459 return const_cast< SmVerticalBraceNode* >( this )->Body();
1461 inline SmMathSymbolNode* SmVerticalBraceNode::Brace()
1463 OSL_ASSERT( GetNumSubNodes() > 1 && GetSubNode( 1 )->GetType() == NMATH );
1464 return static_cast< SmMathSymbolNode* >( GetSubNode( 1 ));
1466 inline const SmMathSymbolNode* SmVerticalBraceNode::Brace() const
1468 return const_cast< SmVerticalBraceNode* >( this )->Brace();
1470 inline SmNode* SmVerticalBraceNode::Script()
1472 OSL_ASSERT( GetNumSubNodes() > 2 );
1473 return GetSubNode( 2 );
1475 inline const SmNode* SmVerticalBraceNode::Script() const
1477 return const_cast< SmVerticalBraceNode* >( this )->Script();
1480 #endif
1483 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */