office-gobmx/starmath/inc/visitors.hxx
2014-03-29 19:16:27 +01:00

506 lines
20 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_STARMATH_INC_VISITORS_HXX
#define INCLUDED_STARMATH_INC_VISITORS_HXX
#include "node.hxx"
#include "caret.hxx"
/** Base class for visitors that visits a tree of SmNodes
* @remarks all methods have been left abstract to ensure that implementers
* don't forget to implement one.
*/
class SmVisitor
{
public:
virtual void Visit( SmTableNode* pNode ) = 0;
virtual void Visit( SmBraceNode* pNode ) = 0;
virtual void Visit( SmBracebodyNode* pNode ) = 0;
virtual void Visit( SmOperNode* pNode ) = 0;
virtual void Visit( SmAlignNode* pNode ) = 0;
virtual void Visit( SmAttributNode* pNode ) = 0;
virtual void Visit( SmFontNode* pNode ) = 0;
virtual void Visit( SmUnHorNode* pNode ) = 0;
virtual void Visit( SmBinHorNode* pNode ) = 0;
virtual void Visit( SmBinVerNode* pNode ) = 0;
virtual void Visit( SmBinDiagonalNode* pNode ) = 0;
virtual void Visit( SmSubSupNode* pNode ) = 0;
virtual void Visit( SmMatrixNode* pNode ) = 0;
virtual void Visit( SmPlaceNode* pNode ) = 0;
virtual void Visit( SmTextNode* pNode ) = 0;
virtual void Visit( SmSpecialNode* pNode ) = 0;
virtual void Visit( SmGlyphSpecialNode* pNode ) = 0;
virtual void Visit( SmMathSymbolNode* pNode ) = 0;
virtual void Visit( SmBlankNode* pNode ) = 0;
virtual void Visit( SmErrorNode* pNode ) = 0;
virtual void Visit( SmLineNode* pNode ) = 0;
virtual void Visit( SmExpressionNode* pNode ) = 0;
virtual void Visit( SmPolyLineNode* pNode ) = 0;
virtual void Visit( SmDynIntegralNode* pNode ) = 0;
virtual void Visit( SmDynIntegralSymbolNode* pNode ) = 0;
virtual void Visit( SmRootNode* pNode ) = 0;
virtual void Visit( SmRootSymbolNode* pNode ) = 0;
virtual void Visit( SmRectangleNode* pNode ) = 0;
virtual void Visit( SmVerticalBraceNode* pNode ) = 0;
protected:
~SmVisitor() {}
};
/** Simple visitor for testing SmVisitor */
class SmVisitorTest : public SmVisitor
{
public:
virtual ~SmVisitorTest() {}
void Visit( SmTableNode* pNode ) SAL_OVERRIDE;
void Visit( SmBraceNode* pNode ) SAL_OVERRIDE;
void Visit( SmBracebodyNode* pNode ) SAL_OVERRIDE;
void Visit( SmOperNode* pNode ) SAL_OVERRIDE;
void Visit( SmAlignNode* pNode ) SAL_OVERRIDE;
void Visit( SmAttributNode* pNode ) SAL_OVERRIDE;
void Visit( SmFontNode* pNode ) SAL_OVERRIDE;
void Visit( SmUnHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinVerNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinDiagonalNode* pNode ) SAL_OVERRIDE;
void Visit( SmSubSupNode* pNode ) SAL_OVERRIDE;
void Visit( SmMatrixNode* pNode ) SAL_OVERRIDE;
void Visit( SmPlaceNode* pNode ) SAL_OVERRIDE;
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
void Visit( SmSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmGlyphSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmMathSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmBlankNode* pNode ) SAL_OVERRIDE;
void Visit( SmErrorNode* pNode ) SAL_OVERRIDE;
void Visit( SmLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmExpressionNode* pNode ) SAL_OVERRIDE;
void Visit( SmPolyLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmRectangleNode* pNode ) SAL_OVERRIDE;
void Visit( SmVerticalBraceNode* pNode ) SAL_OVERRIDE;
private:
/** Auxiliary method for visiting the children of a pNode */
void VisitChildren( SmNode* pNode );
};
// SmDefaultingVisitor
/** Visitor that uses DefaultVisit for handling visits by default
*
* This abstract baseclass is useful for visitors where many methods share the same
* implementation.
*/
class SmDefaultingVisitor : public SmVisitor
{
public:
void Visit( SmTableNode* pNode ) SAL_OVERRIDE;
void Visit( SmBraceNode* pNode ) SAL_OVERRIDE;
void Visit( SmBracebodyNode* pNode ) SAL_OVERRIDE;
void Visit( SmOperNode* pNode ) SAL_OVERRIDE;
void Visit( SmAlignNode* pNode ) SAL_OVERRIDE;
void Visit( SmAttributNode* pNode ) SAL_OVERRIDE;
void Visit( SmFontNode* pNode ) SAL_OVERRIDE;
void Visit( SmUnHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinVerNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinDiagonalNode* pNode ) SAL_OVERRIDE;
void Visit( SmSubSupNode* pNode ) SAL_OVERRIDE;
void Visit( SmMatrixNode* pNode ) SAL_OVERRIDE;
void Visit( SmPlaceNode* pNode ) SAL_OVERRIDE;
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
void Visit( SmSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmGlyphSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmMathSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmBlankNode* pNode ) SAL_OVERRIDE;
void Visit( SmErrorNode* pNode ) SAL_OVERRIDE;
void Visit( SmLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmExpressionNode* pNode ) SAL_OVERRIDE;
void Visit( SmPolyLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmRectangleNode* pNode ) SAL_OVERRIDE;
void Visit( SmVerticalBraceNode* pNode ) SAL_OVERRIDE;
protected:
~SmDefaultingVisitor() {}
/** Method invoked by Visit methods by default */
virtual void DefaultVisit( SmNode* pNode ) = 0;
};
// SmCaretDrawingVisitor
/** Visitor for drawing a caret position */
class SmCaretDrawingVisitor : public SmDefaultingVisitor
{
public:
/** Given position and device this constructor will draw the caret */
SmCaretDrawingVisitor( OutputDevice& rDevice, SmCaretPos position, Point offset, bool caretVisible );
virtual ~SmCaretDrawingVisitor() {}
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
using SmDefaultingVisitor::Visit;
private:
OutputDevice &rDev;
SmCaretPos pos;
/** Offset to draw from */
Point Offset;
bool isCaretVisible;
protected:
/** Default method for drawing pNodes */
void DefaultVisit( SmNode* pNode ) SAL_OVERRIDE;
};
// SmCaretPos2LineVisitor
/** Visitor getting a line from a caret position */
class SmCaretPos2LineVisitor : public SmDefaultingVisitor
{
public:
/** Given position and device this constructor will compute a line for the caret */
SmCaretPos2LineVisitor( OutputDevice *pDevice, SmCaretPos position ) {
pDev = pDevice;
pos = position;
SAL_WARN_IF( !position.IsValid(), "starmath", "Cannot draw invalid position!" );
pos.pSelectedNode->Accept( this );
}
virtual ~SmCaretPos2LineVisitor() {}
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
using SmDefaultingVisitor::Visit;
SmCaretLine GetResult( ){
return line;
}
private:
SmCaretLine line;
OutputDevice *pDev;
SmCaretPos pos;
protected:
/** Default method for computing lines for pNodes */
void DefaultVisit( SmNode* pNode ) SAL_OVERRIDE;
};
// SmDrawingVisitor
/** Visitor for drawing SmNodes to OutputDevice */
class SmDrawingVisitor : public SmVisitor
{
public:
/** Create an instance of SmDrawingVisitor, and use it to draw a formula
* @param rDevice Device to draw on
* @param position Offset on device to draw the formula
* @param pTree Formula tree to draw
* @remarks This constructor will do the drawing, no need to anything more.
*/
SmDrawingVisitor( OutputDevice &rDevice, Point position, SmNode* pTree )
: rDev( rDevice ) {
this->Position = position;
pTree->Accept( this );
}
virtual ~SmDrawingVisitor() {}
void Visit( SmTableNode* pNode ) SAL_OVERRIDE;
void Visit( SmBraceNode* pNode ) SAL_OVERRIDE;
void Visit( SmBracebodyNode* pNode ) SAL_OVERRIDE;
void Visit( SmOperNode* pNode ) SAL_OVERRIDE;
void Visit( SmAlignNode* pNode ) SAL_OVERRIDE;
void Visit( SmAttributNode* pNode ) SAL_OVERRIDE;
void Visit( SmFontNode* pNode ) SAL_OVERRIDE;
void Visit( SmUnHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinVerNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinDiagonalNode* pNode ) SAL_OVERRIDE;
void Visit( SmSubSupNode* pNode ) SAL_OVERRIDE;
void Visit( SmMatrixNode* pNode ) SAL_OVERRIDE;
void Visit( SmPlaceNode* pNode ) SAL_OVERRIDE;
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
void Visit( SmSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmGlyphSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmMathSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmBlankNode* pNode ) SAL_OVERRIDE;
void Visit( SmErrorNode* pNode ) SAL_OVERRIDE;
void Visit( SmLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmExpressionNode* pNode ) SAL_OVERRIDE;
void Visit( SmPolyLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmRectangleNode* pNode ) SAL_OVERRIDE;
void Visit( SmVerticalBraceNode* pNode ) SAL_OVERRIDE;
private:
/** Draw the children of a pNode
* This the default method, use by most pNodes
*/
void DrawChildren( SmNode* pNode );
/** Draw an SmTextNode or a subclass of this */
void DrawTextNode( SmTextNode* pNode );
/** Draw an SmSpecialNode or a subclass of this */
void DrawSpecialNode( SmSpecialNode* pNode );
/** OutputDevice to draw on */
OutputDevice& rDev;
/** Position to draw on the rDev
* @remarks This variable is used to pass parameters in DrawChildren( ), this means
that after a call to DrawChildren( ) the contents of this method is undefined
so if needed cache it locally on the stack.
*/
Point Position;
};
// SmSetSelectionVisitor
/** Set Selection Visitor
* Sets the IsSelected( ) property on all SmNodes of the tree
*/
class SmSetSelectionVisitor : public SmDefaultingVisitor
{
public:
SmSetSelectionVisitor( SmCaretPos startPos, SmCaretPos endPos, SmNode* pNode);
virtual ~SmSetSelectionVisitor() {}
void Visit( SmBinHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmUnHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmFontNode* pNode ) SAL_OVERRIDE;
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
void Visit( SmExpressionNode* pNode ) SAL_OVERRIDE;
void Visit( SmLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmAlignNode* pNode ) SAL_OVERRIDE;
using SmDefaultingVisitor::Visit;
/** Set IsSelected on all pNodes of pSubTree */
static void SetSelectedOnAll( SmNode* pSubTree, bool IsSelected = true );
private:
/** Visit a selectable pNode
* Can be used to handle pNodes that can be selected, that doesn't have more SmCaretPos'
* than 0 and 1 inside them. SmTextNode should be handle separately!
* Also note that pNodes such as SmBinVerNode cannot be selected, don't this method for
* it.
*/
void DefaultVisit( SmNode* pNode ) SAL_OVERRIDE;
void VisitCompositionNode( SmNode* pNode );
/** Caret position where the selection starts */
SmCaretPos StartPos;
/** Caret position where the selection ends */
SmCaretPos EndPos;
/** The current state of this visitor
* This property changes when the visitor meets either StartPos
* or EndPos. This means that anything visited in between will be
* selected.
*/
bool IsSelecting;
};
// SmCaretPosGraphBuildingVisitor
/** A visitor for building a SmCaretPosGraph
*
* Visit invariant:
* Each pNode, except SmExpressionNode, SmBinHorNode and a few others, constitutes an entry
* in a line. Consider the line entry "H", this entry creates one carat position, here
* denoted by | in "H|".
*
* Parameter variables:
* The following variables are used to transfer parameters in to calls and results out
* of calls.
* pRightMost : SmCaretPosGraphEntry*
*
* Prior to a Visit call:
* pRightMost: A pointer to right most position in front of the current line entry.
*
* After a Visit call:
* pRightMost: A pointer to the right most position in the called line entry, if no there's
* no caret positions in called line entry don't change this variable.
*/
class SmCaretPosGraphBuildingVisitor : public SmVisitor
{
public:
/** Builds a caret position graph for pRootNode */
SmCaretPosGraphBuildingVisitor( SmNode* pRootNode );
virtual ~SmCaretPosGraphBuildingVisitor();
void Visit( SmTableNode* pNode ) SAL_OVERRIDE;
void Visit( SmBraceNode* pNode ) SAL_OVERRIDE;
void Visit( SmBracebodyNode* pNode ) SAL_OVERRIDE;
void Visit( SmOperNode* pNode ) SAL_OVERRIDE;
void Visit( SmAlignNode* pNode ) SAL_OVERRIDE;
void Visit( SmAttributNode* pNode ) SAL_OVERRIDE;
void Visit( SmFontNode* pNode ) SAL_OVERRIDE;
void Visit( SmUnHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinVerNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinDiagonalNode* pNode ) SAL_OVERRIDE;
void Visit( SmSubSupNode* pNode ) SAL_OVERRIDE;
void Visit( SmMatrixNode* pNode ) SAL_OVERRIDE;
void Visit( SmPlaceNode* pNode ) SAL_OVERRIDE;
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
void Visit( SmSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmGlyphSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmMathSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmBlankNode* pNode ) SAL_OVERRIDE;
void Visit( SmErrorNode* pNode ) SAL_OVERRIDE;
void Visit( SmLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmExpressionNode* pNode ) SAL_OVERRIDE;
void Visit( SmPolyLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmRectangleNode* pNode ) SAL_OVERRIDE;
void Visit( SmVerticalBraceNode* pNode ) SAL_OVERRIDE;
SmCaretPosGraph* takeGraph()
{
SmCaretPosGraph *pRet = pGraph;
pGraph = 0;
return pRet;
}
private:
SmCaretPosGraphEntry* pRightMost;
SmCaretPosGraph* pGraph;
};
// SmCloningVisitor
/** Visitor for cloning a pNode
*
* This visitor creates deep clones.
*/
class SmCloningVisitor : public SmVisitor
{
public:
SmCloningVisitor( ){ pResult = NULL; }
virtual ~SmCloningVisitor() {}
void Visit( SmTableNode* pNode ) SAL_OVERRIDE;
void Visit( SmBraceNode* pNode ) SAL_OVERRIDE;
void Visit( SmBracebodyNode* pNode ) SAL_OVERRIDE;
void Visit( SmOperNode* pNode ) SAL_OVERRIDE;
void Visit( SmAlignNode* pNode ) SAL_OVERRIDE;
void Visit( SmAttributNode* pNode ) SAL_OVERRIDE;
void Visit( SmFontNode* pNode ) SAL_OVERRIDE;
void Visit( SmUnHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinVerNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinDiagonalNode* pNode ) SAL_OVERRIDE;
void Visit( SmSubSupNode* pNode ) SAL_OVERRIDE;
void Visit( SmMatrixNode* pNode ) SAL_OVERRIDE;
void Visit( SmPlaceNode* pNode ) SAL_OVERRIDE;
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
void Visit( SmSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmGlyphSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmMathSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmBlankNode* pNode ) SAL_OVERRIDE;
void Visit( SmErrorNode* pNode ) SAL_OVERRIDE;
void Visit( SmLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmExpressionNode* pNode ) SAL_OVERRIDE;
void Visit( SmPolyLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmRectangleNode* pNode ) SAL_OVERRIDE;
void Visit( SmVerticalBraceNode* pNode ) SAL_OVERRIDE;
/** Clone a pNode */
SmNode* Clone( SmNode* pNode );
private:
SmNode* pResult;
/** Clone children of pSource and give them to pTarget */
void CloneKids( SmStructureNode* pSource, SmStructureNode* pTarget );
/** Clone attributes on a pNode */
void CloneNodeAttr( SmNode* pSource, SmNode* pTarget );
};
// SmSelectionDrawingVisitor
class SmSelectionDrawingVisitor : public SmDefaultingVisitor
{
public:
/** Draws a selection on rDevice for the selection on pTree */
SmSelectionDrawingVisitor( OutputDevice& rDevice, SmNode* pTree, Point Offset );
virtual ~SmSelectionDrawingVisitor() {}
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
using SmDefaultingVisitor::Visit;
private:
/** Reference to drawing device */
OutputDevice& rDev;
/** True if aSelectionArea have been initialized */
bool bHasSelectionArea;
/** The current area that is selected */
Rectangle aSelectionArea;
/** Extend the area that must be selected */
void ExtendSelectionArea( Rectangle aArea );
/** Default visiting method */
void DefaultVisit( SmNode* pNode ) SAL_OVERRIDE;
/** Visit the children of a given pNode */
void VisitChildren( SmNode* pNode );
};
// SmNodeToTextVisitor
/** Extract command text from pNodes */
class SmNodeToTextVisitor : public SmVisitor
{
public:
SmNodeToTextVisitor( SmNode* pNode, OUString &rText );
virtual ~SmNodeToTextVisitor() {}
void Visit( SmTableNode* pNode ) SAL_OVERRIDE;
void Visit( SmBraceNode* pNode ) SAL_OVERRIDE;
void Visit( SmBracebodyNode* pNode ) SAL_OVERRIDE;
void Visit( SmOperNode* pNode ) SAL_OVERRIDE;
void Visit( SmAlignNode* pNode ) SAL_OVERRIDE;
void Visit( SmAttributNode* pNode ) SAL_OVERRIDE;
void Visit( SmFontNode* pNode ) SAL_OVERRIDE;
void Visit( SmUnHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinHorNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinVerNode* pNode ) SAL_OVERRIDE;
void Visit( SmBinDiagonalNode* pNode ) SAL_OVERRIDE;
void Visit( SmSubSupNode* pNode ) SAL_OVERRIDE;
void Visit( SmMatrixNode* pNode ) SAL_OVERRIDE;
void Visit( SmPlaceNode* pNode ) SAL_OVERRIDE;
void Visit( SmTextNode* pNode ) SAL_OVERRIDE;
void Visit( SmSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmGlyphSpecialNode* pNode ) SAL_OVERRIDE;
void Visit( SmMathSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmBlankNode* pNode ) SAL_OVERRIDE;
void Visit( SmErrorNode* pNode ) SAL_OVERRIDE;
void Visit( SmLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmExpressionNode* pNode ) SAL_OVERRIDE;
void Visit( SmPolyLineNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootNode* pNode ) SAL_OVERRIDE;
void Visit( SmRootSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralNode* pNode ) SAL_OVERRIDE;
void Visit( SmDynIntegralSymbolNode* pNode ) SAL_OVERRIDE;
void Visit( SmRectangleNode* pNode ) SAL_OVERRIDE;
void Visit( SmVerticalBraceNode* pNode ) SAL_OVERRIDE;
private:
/** Extract text from a pNode that constitutes a line */
void LineToText( SmNode* pNode ) {
Separate( );
if( pNode )
pNode->Accept( this );
Separate( );
}
void Append( const OUString &rText ) {
aCmdText.append( rText );
}
/** Append a blank for separation, if needed */
inline void Separate( ){
if( aCmdText.isEmpty() || aCmdText[ aCmdText.getLength() - 1 ] != ' ' )
aCmdText.append(' ');
}
/** Output text generated from the pNodes */
OUStringBuffer aCmdText;
};
#endif // INCLUDED_STARMATH_INC_VISITORS_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */