2010-12-23 16:28:48 +00:00
|
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
2010-10-23 16:39:57 +01:00
|
|
|
|
/*
|
2013-04-24 17:14:03 +01:00
|
|
|
|
* This file is part of the LibreOffice project.
|
2010-10-23 16:39:57 +01:00
|
|
|
|
*
|
2013-04-24 17:14:03 +01:00
|
|
|
|
* 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/.
|
2010-10-23 16:39:57 +01:00
|
|
|
|
*/
|
2010-10-01 22:04:50 +02:00
|
|
|
|
#include "visitors.hxx"
|
|
|
|
|
#include "cursor.hxx"
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmVisitorTest
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmTableNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NTABLE );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmBraceNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NBRACE );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmBracebodyNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NBRACEBODY );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmOperNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NOPER );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmAlignNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NALIGN );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmAttributNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NATTRIBUT );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmFontNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NFONT );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmUnHorNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NUNHOR );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmBinHorNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NBINHOR );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmBinVerNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NBINVER );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmBinDiagonalNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NBINDIAGONAL );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmSubSupNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NSUBSUP );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmMatrixNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NMATRIX );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmPlaceNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NPLACE );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NTEXT );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmSpecialNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NSPECIAL );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmGlyphSpecialNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NGLYPH_SPECIAL );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmMathSymbolNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NMATH || pNode->GetType( ) == NMATHIDENT );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmBlankNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NBLANK );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmErrorNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NERROR );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmLineNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NLINE );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmExpressionNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NEXPRESSION );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmPolyLineNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NPOLYLINE );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmRootNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NROOT );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmRootSymbolNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NROOTSYMBOL );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 14:37:55 -05:00
|
|
|
|
void SmVisitorTest::Visit( SmDynIntegralNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
assert( pNode->GetType( ) == NDYNINT );
|
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmDynIntegralSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
assert( pNode->GetType( ) == NDYNINTSYMBOL );
|
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
void SmVisitorTest::Visit( SmRectangleNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NRECTANGLE );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::Visit( SmVerticalBraceNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
assert( pNode->GetType( ) == NVERTICAL_BRACE );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmVisitorTest::VisitChildren( SmNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmDefaultingVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmTableNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmBracebodyNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmOperNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmAlignNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmAttributNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmFontNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmUnHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmBinHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmBinVerNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmBinDiagonalNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmSubSupNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmMatrixNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmPlaceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmGlyphSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmMathSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmBlankNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmErrorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmLineNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmExpressionNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmPolyLineNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmRootNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmRootSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 14:37:55 -05:00
|
|
|
|
void SmDefaultingVisitor::Visit( SmDynIntegralNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmDynIntegralSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
void SmDefaultingVisitor::Visit( SmRectangleNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDefaultingVisitor::Visit( SmVerticalBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DefaultVisit( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmCaretDrawingVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
SmCaretDrawingVisitor::SmCaretDrawingVisitor( OutputDevice& rDevice,
|
|
|
|
|
SmCaretPos position,
|
2010-11-16 23:37:09 +00:00
|
|
|
|
Point offset,
|
|
|
|
|
bool caretVisible )
|
2010-10-01 22:04:50 +02:00
|
|
|
|
: rDev( rDevice )
|
|
|
|
|
{
|
|
|
|
|
pos = position;
|
|
|
|
|
Offset = offset;
|
2010-11-16 23:37:09 +00:00
|
|
|
|
isCaretVisible = caretVisible;
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( !position.IsValid(), "starmath", "Cannot draw invalid position!" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
if( !position.IsValid( ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//Save device state
|
|
|
|
|
rDev.Push( PUSH_FONT | PUSH_MAPMODE | PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_TEXTCOLOR );
|
|
|
|
|
|
|
|
|
|
pos.pSelectedNode->Accept( this );
|
|
|
|
|
//Restore device state
|
|
|
|
|
rDev.Pop( );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCaretDrawingVisitor::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
long i = pos.Index;
|
|
|
|
|
|
|
|
|
|
rDev.SetFont( pNode->GetFont( ) );
|
|
|
|
|
|
|
|
|
|
//Find the line
|
|
|
|
|
SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode );
|
|
|
|
|
|
|
|
|
|
//Find coordinates
|
|
|
|
|
long left = pNode->GetLeft( ) + rDev.GetTextWidth( pNode->GetText( ), 0, i ) + Offset.X( );
|
|
|
|
|
long top = pLine->GetTop( ) + Offset.Y( );
|
|
|
|
|
long height = pLine->GetHeight( );
|
2010-11-16 23:37:09 +00:00
|
|
|
|
long left_line = pLine->GetLeft( ) + Offset.X( );
|
|
|
|
|
long right_line = pLine->GetRight( ) + Offset.X( );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
//Set color
|
|
|
|
|
rDev.SetLineColor( Color( COL_BLACK ) );
|
|
|
|
|
|
2010-11-16 23:37:09 +00:00
|
|
|
|
if ( isCaretVisible ) {
|
|
|
|
|
//Draw vertical line
|
|
|
|
|
Point p1( left, top );
|
|
|
|
|
Point p2( left, top + height );
|
|
|
|
|
rDev.DrawLine( p1, p2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Underline the line
|
|
|
|
|
Point pLeft( left_line, top + height );
|
|
|
|
|
Point pRight( right_line, top + height );
|
|
|
|
|
rDev.DrawLine( pLeft, pRight );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCaretDrawingVisitor::DefaultVisit( SmNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
rDev.SetLineColor( Color( COL_BLACK ) );
|
|
|
|
|
|
|
|
|
|
//Find the line
|
|
|
|
|
SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode );
|
|
|
|
|
|
|
|
|
|
//Find coordinates
|
|
|
|
|
long left = pNode->GetLeft( ) + Offset.X( ) + ( pos.Index == 1 ? pNode->GetWidth( ) : 0 );
|
|
|
|
|
long top = pLine->GetTop( ) + Offset.Y( );
|
|
|
|
|
long height = pLine->GetHeight( );
|
2010-11-16 23:37:09 +00:00
|
|
|
|
long left_line = pLine->GetLeft( ) + Offset.X( );
|
|
|
|
|
long right_line = pLine->GetRight( ) + Offset.X( );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
//Set color
|
|
|
|
|
rDev.SetLineColor( Color( COL_BLACK ) );
|
|
|
|
|
|
2010-11-16 23:37:09 +00:00
|
|
|
|
if ( isCaretVisible ) {
|
|
|
|
|
//Draw vertical line
|
|
|
|
|
Point p1( left, top );
|
|
|
|
|
Point p2( left, top + height );
|
|
|
|
|
rDev.DrawLine( p1, p2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Underline the line
|
|
|
|
|
Point pLeft( left_line, top + height );
|
|
|
|
|
Point pRight( right_line, top + height );
|
|
|
|
|
rDev.DrawLine( pLeft, pRight );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmCaretPos2LineVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
void SmCaretPos2LineVisitor::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
//Save device state
|
|
|
|
|
pDev->Push( PUSH_FONT | PUSH_TEXTCOLOR );
|
|
|
|
|
|
|
|
|
|
long i = pos.Index;
|
|
|
|
|
|
|
|
|
|
pDev->SetFont( pNode->GetFont( ) );
|
|
|
|
|
|
|
|
|
|
//Find coordinates
|
|
|
|
|
long left = pNode->GetLeft( ) + pDev->GetTextWidth( pNode->GetText( ), 0, i );
|
|
|
|
|
long top = pNode->GetTop( );
|
|
|
|
|
long height = pNode->GetHeight( );
|
|
|
|
|
|
|
|
|
|
line = SmCaretLine( left, top, height );
|
|
|
|
|
|
|
|
|
|
//Restore device state
|
|
|
|
|
pDev->Pop( );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCaretPos2LineVisitor::DefaultVisit( SmNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
//Vertical line ( code from SmCaretDrawingVisitor )
|
|
|
|
|
Point p1 = pNode->GetTopLeft( );
|
|
|
|
|
if( pos.Index == 1 )
|
|
|
|
|
p1.Move( pNode->GetWidth( ), 0 );
|
|
|
|
|
|
|
|
|
|
line = SmCaretLine( p1.X( ), p1.Y( ), pNode->GetHeight( ) );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// Nasty temporary device!!!
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
2014-04-14 21:37:24 +02:00
|
|
|
|
#include <boost/noncopyable.hpp>
|
2010-10-01 22:04:50 +02:00
|
|
|
|
#include <tools/gen.hxx>
|
|
|
|
|
#include <tools/fract.hxx>
|
|
|
|
|
#include <rtl/math.hxx>
|
|
|
|
|
#include <tools/color.hxx>
|
|
|
|
|
#include <vcl/metric.hxx>
|
|
|
|
|
#include <vcl/lineinfo.hxx>
|
|
|
|
|
#include <vcl/outdev.hxx>
|
|
|
|
|
#include <sfx2/module.hxx>
|
|
|
|
|
#include "symbol.hxx"
|
|
|
|
|
#include "smmod.hxx"
|
|
|
|
|
|
2014-04-14 21:37:24 +02:00
|
|
|
|
class SmTmpDevice2: private boost::noncopyable
|
2010-10-01 22:04:50 +02:00
|
|
|
|
{
|
|
|
|
|
OutputDevice &rOutDev;
|
|
|
|
|
|
|
|
|
|
Color Impl_GetColor( const Color& rColor );
|
|
|
|
|
|
|
|
|
|
public:
|
2010-11-06 01:33:05 +01:00
|
|
|
|
SmTmpDevice2( OutputDevice &rTheDev, bool bUseMap100th_mm );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
~SmTmpDevice2( ) { rOutDev.Pop( ); }
|
|
|
|
|
|
|
|
|
|
void SetFont( const Font &rNewFont );
|
|
|
|
|
|
|
|
|
|
void SetLineColor( const Color& rColor ) { rOutDev.SetLineColor( Impl_GetColor( rColor ) ); }
|
|
|
|
|
void SetFillColor( const Color& rColor ) { rOutDev.SetFillColor( Impl_GetColor( rColor ) ); }
|
|
|
|
|
};
|
|
|
|
|
|
2010-11-06 01:33:05 +01:00
|
|
|
|
SmTmpDevice2::SmTmpDevice2( OutputDevice &rTheDev, bool bUseMap100th_mm ) :
|
2010-10-01 22:04:50 +02:00
|
|
|
|
rOutDev( rTheDev )
|
|
|
|
|
{
|
|
|
|
|
rOutDev.Push( PUSH_FONT | PUSH_MAPMODE |
|
|
|
|
|
PUSH_LINECOLOR | PUSH_FILLCOLOR | PUSH_TEXTCOLOR );
|
|
|
|
|
if ( bUseMap100th_mm && MAP_100TH_MM != rOutDev.GetMapMode( ).GetMapUnit( ) )
|
|
|
|
|
{
|
2013-09-09 08:52:34 +02:00
|
|
|
|
SAL_WARN("starmath", "incorrect MapMode?");
|
2011-02-18 09:17:02 +01:00
|
|
|
|
rOutDev.SetMapMode( MAP_100TH_MM ); //format for 100% always
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Color SmTmpDevice2::Impl_GetColor( const Color& rColor )
|
|
|
|
|
{
|
|
|
|
|
ColorData nNewCol = rColor.GetColor( );
|
|
|
|
|
if ( COL_AUTO == nNewCol )
|
|
|
|
|
{
|
|
|
|
|
if ( OUTDEV_PRINTER == rOutDev.GetOutDevType( ) )
|
|
|
|
|
nNewCol = COL_BLACK;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Color aBgCol( rOutDev.GetBackground( ).GetColor( ) );
|
|
|
|
|
if ( OUTDEV_WINDOW == rOutDev.GetOutDevType( ) )
|
|
|
|
|
aBgCol = ( ( Window & ) rOutDev ).GetDisplayBackground( ).GetColor( );
|
|
|
|
|
|
|
|
|
|
nNewCol = SM_MOD( )->GetColorConfig( ).GetColorValue( svtools::FONTCOLOR ).nColor;
|
|
|
|
|
|
|
|
|
|
Color aTmpColor( nNewCol );
|
|
|
|
|
if ( aBgCol.IsDark( ) && aTmpColor.IsDark( ) )
|
|
|
|
|
nNewCol = COL_WHITE;
|
|
|
|
|
else if ( aBgCol.IsBright( ) && aTmpColor.IsBright( ) )
|
|
|
|
|
nNewCol = COL_BLACK;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Color( nNewCol );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmTmpDevice2::SetFont( const Font &rNewFont )
|
|
|
|
|
{
|
|
|
|
|
rOutDev.SetFont( rNewFont );
|
|
|
|
|
rOutDev.SetTextColor( Impl_GetColor( rNewFont.GetColor( ) ) );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmDrawingVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmTableNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmBracebodyNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmOperNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmAlignNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmAttributNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmFontNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmUnHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmBinHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmBinVerNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmBinDiagonalNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmSubSupNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmMatrixNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmPlaceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawSpecialNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawTextNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawSpecialNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmGlyphSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawSpecialNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmMathSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawSpecialNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmBlankNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmErrorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawSpecialNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmLineNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmExpressionNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmRootNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 14:37:55 -05:00
|
|
|
|
void SmDrawingVisitor::Visit(SmDynIntegralNode* pNode)
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
void SmDrawingVisitor::Visit( SmVerticalBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
DrawChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmRootSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if ( pNode->IsPhantom( ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// draw root-sign itself
|
|
|
|
|
DrawSpecialNode( pNode );
|
|
|
|
|
|
2010-11-06 01:33:05 +01:00
|
|
|
|
SmTmpDevice2 aTmpDev( ( OutputDevice & ) rDev, true );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
aTmpDev.SetFillColor( pNode->GetFont( ).GetColor( ) );
|
|
|
|
|
rDev.SetLineColor( );
|
|
|
|
|
aTmpDev.SetFont( pNode->GetFont( ) );
|
|
|
|
|
|
|
|
|
|
// since the width is always unscaled it corresponds ot the _original_
|
|
|
|
|
// _unscaled_ font height to be used, we use that to calculate the
|
|
|
|
|
// bar height. Thus it is independent of the arguments height.
|
|
|
|
|
// ( see display of sqrt QQQ versus sqrt stack{Q#Q#Q#Q} )
|
|
|
|
|
long nBarHeight = pNode->GetWidth( ) * 7L / 100L;
|
|
|
|
|
long nBarWidth = pNode->GetBodyWidth( ) + pNode->GetBorderWidth( );
|
|
|
|
|
Point aBarOffset( pNode->GetWidth( ), +pNode->GetBorderWidth( ) );
|
|
|
|
|
Point aBarPos( Position + aBarOffset );
|
|
|
|
|
|
|
|
|
|
Rectangle aBar( aBarPos, Size( nBarWidth, nBarHeight ) );
|
|
|
|
|
//! avoid GROWING AND SHRINKING of drawn rectangle when constantly
|
|
|
|
|
//! increasing zoomfactor.
|
2011-04-12 21:06:27 +09:00
|
|
|
|
// This is done by shifting its output-position to a point that
|
2010-10-01 22:04:50 +02:00
|
|
|
|
// corresponds exactly to a pixel on the output device.
|
|
|
|
|
Point aDrawPos( rDev.PixelToLogic( rDev.LogicToPixel( aBar.TopLeft( ) ) ) );
|
|
|
|
|
aBar.SetPos( aDrawPos );
|
|
|
|
|
|
|
|
|
|
rDev.DrawRect( aBar );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 14:37:55 -05:00
|
|
|
|
void SmDrawingVisitor::Visit( SmDynIntegralSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if ( pNode->IsPhantom( ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// draw integral-sign itself
|
|
|
|
|
DrawSpecialNode( pNode );
|
|
|
|
|
|
|
|
|
|
//! the rest of this may not be needed at all
|
|
|
|
|
|
|
|
|
|
// this should be something like:
|
|
|
|
|
// instead of just drawing the node, take some information about the body.
|
|
|
|
|
// This is also how SmRootSymbol does it (probably by means of SmRootNode)
|
|
|
|
|
// NEXT: Check out SmRootNode
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
void SmDrawingVisitor::Visit( SmPolyLineNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if ( pNode->IsPhantom( ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
long nBorderwidth = pNode->GetFont( ).GetBorderWidth( );
|
|
|
|
|
|
|
|
|
|
LineInfo aInfo;
|
|
|
|
|
aInfo.SetWidth( pNode->GetWidth( ) - 2 * nBorderwidth );
|
|
|
|
|
|
|
|
|
|
Point aOffset ( Point( ) - pNode->GetPolygon( ).GetBoundRect( ).TopLeft( )
|
|
|
|
|
+ Point( nBorderwidth, nBorderwidth ) ),
|
|
|
|
|
aPos ( Position + aOffset );
|
|
|
|
|
pNode->GetPolygon( ).Move( aPos.X( ), aPos.Y( ) ); //Works because Polygon wraps a pointer
|
|
|
|
|
|
2010-11-06 01:33:05 +01:00
|
|
|
|
SmTmpDevice2 aTmpDev ( ( OutputDevice & ) rDev, false );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
aTmpDev.SetLineColor( pNode->GetFont( ).GetColor( ) );
|
|
|
|
|
|
|
|
|
|
rDev.DrawPolyLine( pNode->GetPolygon( ), aInfo );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::Visit( SmRectangleNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if ( pNode->IsPhantom( ) )
|
|
|
|
|
return;
|
|
|
|
|
|
2010-11-06 01:33:05 +01:00
|
|
|
|
SmTmpDevice2 aTmpDev ( ( OutputDevice & ) rDev, false );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
aTmpDev.SetFillColor( pNode->GetFont( ).GetColor( ) );
|
|
|
|
|
rDev.SetLineColor( );
|
|
|
|
|
aTmpDev.SetFont( pNode->GetFont( ) );
|
|
|
|
|
|
2011-03-14 16:51:14 +00:00
|
|
|
|
sal_uLong nTmpBorderWidth = pNode->GetFont( ).GetBorderWidth( );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
// get rectangle and remove borderspace
|
|
|
|
|
Rectangle aTmp ( pNode->AsRectangle( ) + Position - pNode->GetTopLeft( ) );
|
|
|
|
|
aTmp.Left( ) += nTmpBorderWidth;
|
|
|
|
|
aTmp.Right( ) -= nTmpBorderWidth;
|
|
|
|
|
aTmp.Top( ) += nTmpBorderWidth;
|
|
|
|
|
aTmp.Bottom( ) -= nTmpBorderWidth;
|
|
|
|
|
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( aTmp.GetHeight() == 0 || aTmp.GetWidth() == 0,
|
|
|
|
|
"starmath", "Empty rectangle" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
//! avoid GROWING AND SHRINKING of drawn rectangle when constantly
|
|
|
|
|
//! increasing zoomfactor.
|
2011-04-12 21:06:27 +09:00
|
|
|
|
// This is done by shifting its output-position to a point that
|
2010-10-01 22:04:50 +02:00
|
|
|
|
// corresponds exactly to a pixel on the output device.
|
|
|
|
|
Point aPos ( rDev.PixelToLogic( rDev.LogicToPixel( aTmp.TopLeft( ) ) ) );
|
|
|
|
|
aTmp.SetPos( aPos );
|
|
|
|
|
|
|
|
|
|
rDev.DrawRect( aTmp );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::DrawTextNode( SmTextNode* pNode )
|
|
|
|
|
{
|
2012-10-01 20:46:34 +04:00
|
|
|
|
if ( pNode->IsPhantom() || pNode->GetText().isEmpty() || pNode->GetText()[0] == '\0' )
|
2010-10-01 22:04:50 +02:00
|
|
|
|
return;
|
|
|
|
|
|
2010-11-06 01:33:05 +01:00
|
|
|
|
SmTmpDevice2 aTmpDev ( ( OutputDevice & ) rDev, false );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
aTmpDev.SetFont( pNode->GetFont( ) );
|
|
|
|
|
|
|
|
|
|
Point aPos ( Position );
|
|
|
|
|
aPos.Y( ) += pNode->GetBaselineOffset( );
|
|
|
|
|
// auf Pixelkoordinaten runden
|
|
|
|
|
aPos = rDev.PixelToLogic( rDev.LogicToPixel( aPos ) );
|
|
|
|
|
|
|
|
|
|
rDev.DrawStretchText( aPos, pNode->GetWidth( ), pNode->GetText( ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::DrawSpecialNode( SmSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
//! since this chars might come from any font, that we may not have
|
|
|
|
|
//! set to ALIGN_BASELINE yet, we do it now.
|
|
|
|
|
pNode->GetFont( ).SetAlign( ALIGN_BASELINE );
|
|
|
|
|
|
|
|
|
|
DrawTextNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmDrawingVisitor::DrawChildren( SmNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if ( pNode->IsPhantom( ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
Point rPosition = Position;
|
|
|
|
|
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
{
|
|
|
|
|
Point aOffset ( it->GetTopLeft( ) - pNode->GetTopLeft( ) );
|
|
|
|
|
Position = rPosition + aOffset;
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmSetSelectionVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
SmSetSelectionVisitor::SmSetSelectionVisitor( SmCaretPos startPos, SmCaretPos endPos, SmNode* pTree) {
|
|
|
|
|
StartPos = startPos;
|
|
|
|
|
EndPos = endPos;
|
|
|
|
|
IsSelecting = false;
|
|
|
|
|
|
|
|
|
|
//Assume that pTree is a SmTableNode
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF(pTree->GetType() != NTABLE, "starmath", "pTree should be a SmTableNode!");
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Visit root node, this is special as this node cannot be selected, but its children can!
|
2010-10-16 20:57:58 +02:00
|
|
|
|
if(pTree->GetType() == NTABLE){
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Change state if StartPos is in front of this node
|
2010-10-16 20:57:58 +02:00
|
|
|
|
if( StartPos.pSelectedNode == pTree && StartPos.Index == 0 )
|
|
|
|
|
IsSelecting = !IsSelecting;
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Change state if EndPos is in front of this node
|
2010-10-16 20:57:58 +02:00
|
|
|
|
if( EndPos.pSelectedNode == pTree && EndPos.Index == 0 )
|
|
|
|
|
IsSelecting = !IsSelecting;
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF(IsSelecting, "starmath", "Caret positions needed to set IsSelecting about, shouldn't be possible!");
|
2010-10-16 20:57:58 +02:00
|
|
|
|
|
|
|
|
|
//Visit lines
|
|
|
|
|
SmNodeIterator it( pTree );
|
|
|
|
|
while( it.Next( ) ) {
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
//If we started a selection in this line and it haven't ended, we do that now!
|
|
|
|
|
if(IsSelecting) {
|
|
|
|
|
IsSelecting = false;
|
|
|
|
|
SetSelectedOnAll(it.Current(), true);
|
|
|
|
|
//Set StartPos and EndPos to invalid positions, this ensures that an unused
|
|
|
|
|
//start or end (because we forced end above), doesn't start a new selection.
|
|
|
|
|
StartPos = EndPos = SmCaretPos();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
//Check if pTree isn't selected
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF(pTree->IsSelected(), "starmath", "pTree should never be selected!");
|
2010-10-16 20:57:58 +02:00
|
|
|
|
//Discard the selection if there's a bug (it's better than crashing)
|
|
|
|
|
if(pTree->IsSelected())
|
|
|
|
|
SetSelectedOnAll(pTree, false);
|
|
|
|
|
}else //This shouldn't happen, but I don't see any reason to die if it does
|
|
|
|
|
pTree->Accept(this);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmSetSelectionVisitor::SetSelectedOnAll( SmNode* pSubTree, bool IsSelected ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
pSubTree->SetSelected( IsSelected );
|
|
|
|
|
|
|
|
|
|
//Quick BFS to set all selections
|
|
|
|
|
SmNodeIterator it( pSubTree );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
SetSelectedOnAll( it.Current( ), IsSelected );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::DefaultVisit( SmNode* pNode ) {
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Change state if StartPos is in front of this node
|
2010-10-01 22:04:50 +02:00
|
|
|
|
if( StartPos.pSelectedNode == pNode && StartPos.Index == 0 )
|
|
|
|
|
IsSelecting = !IsSelecting;
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Change state if EndPos is in front of this node
|
2010-10-01 22:04:50 +02:00
|
|
|
|
if( EndPos.pSelectedNode == pNode && EndPos.Index == 0 )
|
|
|
|
|
IsSelecting = !IsSelecting;
|
|
|
|
|
|
|
|
|
|
//Cache current state
|
2010-11-06 01:33:05 +01:00
|
|
|
|
bool WasSelecting = IsSelecting;
|
|
|
|
|
bool ChangedState = false;
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
//Set selected
|
|
|
|
|
pNode->SetSelected( IsSelecting );
|
|
|
|
|
|
|
|
|
|
//Visit children
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
{
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
ChangedState = ( WasSelecting != IsSelecting ) || ChangedState;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//If state changed
|
|
|
|
|
if( ChangedState )
|
|
|
|
|
{
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Select this node and all of its children
|
2010-10-01 22:04:50 +02:00
|
|
|
|
//(Make exception for SmBracebodyNode)
|
|
|
|
|
if( pNode->GetType() != NBRACEBODY ||
|
|
|
|
|
!pNode->GetParent() ||
|
|
|
|
|
pNode->GetParent()->GetType() != NBRACE )
|
|
|
|
|
SetSelectedOnAll( pNode, true );
|
|
|
|
|
else
|
|
|
|
|
SetSelectedOnAll( pNode->GetParent(), true );
|
|
|
|
|
/* If the equation is: sqrt{2 + 4} + 5
|
|
|
|
|
* And the selection is: sqrt{2 + [4} +] 5
|
|
|
|
|
* Where [ denotes StartPos and ] denotes EndPos
|
|
|
|
|
* Then the sqrt node should be selected, so that the
|
|
|
|
|
* effective selection is: [sqrt{2 + 4} +] 5
|
|
|
|
|
* The same is the case if we swap StartPos and EndPos.
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Change state if StartPos is after this node
|
|
|
|
|
if( StartPos.pSelectedNode == pNode && StartPos.Index == 1 )
|
|
|
|
|
{
|
|
|
|
|
IsSelecting = !IsSelecting;
|
|
|
|
|
}
|
|
|
|
|
//Change state if EndPos is after of this node
|
|
|
|
|
if( EndPos.pSelectedNode == pNode && EndPos.Index == 1 )
|
|
|
|
|
{
|
|
|
|
|
IsSelecting = !IsSelecting;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::VisitCompositionNode( SmNode* pNode ) {
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Change state if StartPos is in front of this node
|
2010-10-01 22:04:50 +02:00
|
|
|
|
if( StartPos.pSelectedNode == pNode && StartPos.Index == 0 )
|
|
|
|
|
IsSelecting = !IsSelecting;
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Change state if EndPos is in front of this node
|
2010-10-01 22:04:50 +02:00
|
|
|
|
if( EndPos.pSelectedNode == pNode && EndPos.Index == 0 )
|
|
|
|
|
IsSelecting = !IsSelecting;
|
|
|
|
|
|
|
|
|
|
//Cache current state
|
|
|
|
|
bool WasSelecting = IsSelecting;
|
|
|
|
|
|
|
|
|
|
//Visit children
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
|
|
|
|
|
//Set selected, if everything was selected
|
|
|
|
|
pNode->SetSelected( WasSelecting && IsSelecting );
|
|
|
|
|
|
|
|
|
|
//Change state if StartPos is after this node
|
|
|
|
|
if( StartPos.pSelectedNode == pNode && StartPos.Index == 1 )
|
|
|
|
|
IsSelecting = !IsSelecting;
|
|
|
|
|
//Change state if EndPos is after of this node
|
|
|
|
|
if( EndPos.pSelectedNode == pNode && EndPos.Index == 1 )
|
|
|
|
|
IsSelecting = !IsSelecting;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::Visit( SmTextNode* pNode ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
long i1 = -1,
|
|
|
|
|
i2 = -1;
|
|
|
|
|
if( StartPos.pSelectedNode == pNode )
|
|
|
|
|
i1 = StartPos.Index;
|
|
|
|
|
if( EndPos.pSelectedNode == pNode )
|
|
|
|
|
i2 = EndPos.Index;
|
|
|
|
|
|
|
|
|
|
long start, end;
|
|
|
|
|
pNode->SetSelected( true );
|
|
|
|
|
if( i1 != -1 && i2 != -1 ) {
|
|
|
|
|
start = i1 < i2 ? i1 : i2; //MIN
|
|
|
|
|
end = i1 > i2 ? i1 : i2; //MAX
|
|
|
|
|
} else if( IsSelecting && i1 != -1 ) {
|
|
|
|
|
start = 0;
|
|
|
|
|
end = i1;
|
|
|
|
|
IsSelecting = false;
|
|
|
|
|
} else if( IsSelecting && i2 != -1 ) {
|
|
|
|
|
start = 0;
|
|
|
|
|
end = i2;
|
|
|
|
|
IsSelecting = false;
|
|
|
|
|
} else if( !IsSelecting && i1 != -1 ) {
|
|
|
|
|
start = i1;
|
2012-10-01 20:46:34 +04:00
|
|
|
|
end = pNode->GetText().getLength();
|
2010-10-01 22:04:50 +02:00
|
|
|
|
IsSelecting = true;
|
|
|
|
|
} else if( !IsSelecting && i2 != -1 ) {
|
|
|
|
|
start = i2;
|
2012-10-01 20:46:34 +04:00
|
|
|
|
end = pNode->GetText().getLength();
|
2010-10-01 22:04:50 +02:00
|
|
|
|
IsSelecting = true;
|
|
|
|
|
} else if( IsSelecting ) {
|
|
|
|
|
start = 0;
|
2012-10-01 20:46:34 +04:00
|
|
|
|
end = pNode->GetText().getLength();
|
2010-10-01 22:04:50 +02:00
|
|
|
|
} else {
|
|
|
|
|
pNode->SetSelected( false );
|
|
|
|
|
start = 0;
|
|
|
|
|
end = 0;
|
|
|
|
|
}
|
|
|
|
|
pNode->SetSelected( start != end );
|
|
|
|
|
pNode->SetSelectionStart( start );
|
|
|
|
|
pNode->SetSelectionEnd( end );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::Visit( SmExpressionNode* pNode ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitCompositionNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::Visit( SmLineNode* pNode ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitCompositionNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::Visit( SmAlignNode* pNode ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitCompositionNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::Visit( SmBinHorNode* pNode ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitCompositionNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::Visit( SmUnHorNode* pNode ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
VisitCompositionNode( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
void SmSetSelectionVisitor::Visit( SmFontNode* pNode ) {
|
|
|
|
|
VisitCompositionNode( pNode );
|
|
|
|
|
}
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmCaretPosGraphBuildingVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
2010-10-16 20:57:58 +02:00
|
|
|
|
SmCaretPosGraphBuildingVisitor::SmCaretPosGraphBuildingVisitor( SmNode* pRootNode ) {
|
2010-10-03 16:16:52 +02:00
|
|
|
|
pRightMost = NULL;
|
|
|
|
|
pGraph = new SmCaretPosGraph( );
|
|
|
|
|
//pRootNode should always be a table
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( pRootNode->GetType( ) != NTABLE, "starmath", "pRootNode must be a table node");
|
2010-10-03 16:16:52 +02:00
|
|
|
|
//Handle the special case where NTABLE is used a rootnode
|
|
|
|
|
if( pRootNode->GetType( ) == NTABLE ){
|
|
|
|
|
//Children are SmLineNodes
|
|
|
|
|
//Or so I thought... Aparently, the children can be instances of SmExpression
|
|
|
|
|
//especially if there's a error in the formula... So he we go, a simple work around.
|
|
|
|
|
SmNodeIterator it( pRootNode );
|
|
|
|
|
while( it.Next( ) ){
|
|
|
|
|
//There's a special invariant between this method and the Visit( SmLineNode* )
|
|
|
|
|
//Usually pRightMost may not be NULL, to avoid this pRightMost should here be
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//set to a new SmCaretPos in front of it.Current( ), however, if it.Current( ) is
|
|
|
|
|
//an instance of SmLineNode we let SmLineNode create this position in front of
|
2010-10-03 16:16:52 +02:00
|
|
|
|
//the visual line.
|
|
|
|
|
//The argument for doing this is that we now don't have to worry about SmLineNode
|
|
|
|
|
//being a visual line composition node. Thus, no need for yet another special case
|
|
|
|
|
//in SmCursor::IsLineCompositionNode and everywhere this method is used.
|
2010-10-16 20:57:58 +02:00
|
|
|
|
//if( it->GetType( ) != NLINE )
|
2010-10-03 16:16:52 +02:00
|
|
|
|
pRightMost = pGraph->Add( SmCaretPos( it.Current( ), 0 ) );
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
}else
|
|
|
|
|
pRootNode->Accept(this);
|
|
|
|
|
}
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
2013-10-03 11:17:11 +01:00
|
|
|
|
SmCaretPosGraphBuildingVisitor::~SmCaretPosGraphBuildingVisitor()
|
|
|
|
|
{
|
|
|
|
|
delete pGraph;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-03 16:16:52 +02:00
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmLineNode* pNode ){
|
2010-10-01 22:04:50 +02:00
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) ){
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-10-03 16:16:52 +02:00
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmTableNode
|
|
|
|
|
* This method covers cases where SmTableNode is used in a binom or stack,
|
|
|
|
|
* the special case where it is used as root node for the entire formula is
|
|
|
|
|
* handled in the constructor.
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmTableNode* pNode ){
|
|
|
|
|
SmCaretPosGraphEntry *left = pRightMost,
|
|
|
|
|
*right = pGraph->Add( SmCaretPos( pNode, 1) );
|
2010-11-06 01:33:05 +01:00
|
|
|
|
bool bIsFirst = true;
|
2010-10-01 22:04:50 +02:00
|
|
|
|
SmNodeIterator it( pNode );
|
2010-10-03 16:16:52 +02:00
|
|
|
|
while( it.Next() ){
|
|
|
|
|
pRightMost = pGraph->Add( SmCaretPos( it.Current(), 0 ), left);
|
|
|
|
|
if(bIsFirst)
|
|
|
|
|
left->SetRight(pRightMost);
|
2010-10-01 22:04:50 +02:00
|
|
|
|
it->Accept( this );
|
2010-10-03 16:16:52 +02:00
|
|
|
|
pRightMost->SetRight(right);
|
|
|
|
|
if(bIsFirst)
|
|
|
|
|
right->SetLeft(pRightMost);
|
2010-11-06 01:33:05 +01:00
|
|
|
|
bIsFirst = false;
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
2010-10-03 16:16:52 +02:00
|
|
|
|
pRightMost = right;
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmSubSupNode
|
|
|
|
|
*
|
|
|
|
|
* The child positions in a SubSupNode, where H is the body:
|
|
|
|
|
* \code
|
|
|
|
|
* CSUP
|
|
|
|
|
*
|
|
|
|
|
* LSUP H H RSUP
|
|
|
|
|
* H H
|
|
|
|
|
* HHHH
|
|
|
|
|
* H H
|
|
|
|
|
* LSUB H H RSUB
|
|
|
|
|
*
|
|
|
|
|
* CSUB
|
|
|
|
|
* \endcode
|
|
|
|
|
*
|
|
|
|
|
* Graph over these, where "left" is before the SmSubSupNode and "right" is after:
|
|
|
|
|
* \dot
|
|
|
|
|
* digraph Graph{
|
|
|
|
|
* left -> H;
|
|
|
|
|
* H -> right;
|
|
|
|
|
* LSUP -> H;
|
|
|
|
|
* LSUB -> H;
|
|
|
|
|
* CSUP -> right;
|
|
|
|
|
* CSUB -> right;
|
|
|
|
|
* RSUP -> right;
|
|
|
|
|
* RSUB -> right;
|
|
|
|
|
* };
|
|
|
|
|
* \enddot
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmSubSupNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmCaretPosGraphEntry *left,
|
|
|
|
|
*right,
|
|
|
|
|
*bodyLeft,
|
|
|
|
|
*bodyRight;
|
|
|
|
|
|
|
|
|
|
left = pRightMost;
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( !pRightMost, "starmath", "pRightMost shouldn't be NULL here!" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
//Create bodyLeft
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( !pNode->GetBody(), "starmath", "SmSubSupNode Doesn't have a body!" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
bodyLeft = pGraph->Add( SmCaretPos( pNode->GetBody( ), 0 ), left );
|
|
|
|
|
left->SetRight( bodyLeft ); //TODO: Don't make this if LSUP or LSUB are NULL ( not sure??? )
|
|
|
|
|
|
|
|
|
|
//Create right
|
|
|
|
|
right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
|
|
|
|
//Visit the body, to get bodyRight
|
|
|
|
|
pRightMost = bodyLeft;
|
|
|
|
|
pNode->GetBody( )->Accept( this );
|
|
|
|
|
bodyRight = pRightMost;
|
|
|
|
|
bodyRight->SetRight( right );
|
|
|
|
|
right->SetLeft( bodyRight );
|
|
|
|
|
|
|
|
|
|
SmNode* pChild;
|
|
|
|
|
//If there's an LSUP
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( LSUP ) ) ){
|
|
|
|
|
SmCaretPosGraphEntry *cLeft; //Child left
|
|
|
|
|
cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
|
|
|
|
|
pRightMost = cLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
//If there's an LSUB
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( LSUB ) ) ){
|
|
|
|
|
SmCaretPosGraphEntry *cLeft; //Child left
|
|
|
|
|
cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
|
|
|
|
|
pRightMost = cLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
//If there's an CSUP
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( CSUP ) ) ){
|
|
|
|
|
SmCaretPosGraphEntry *cLeft; //Child left
|
|
|
|
|
cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
|
|
|
|
|
pRightMost = cLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
}
|
|
|
|
|
//If there's an CSUB
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( CSUB ) ) ){
|
|
|
|
|
SmCaretPosGraphEntry *cLeft; //Child left
|
|
|
|
|
cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
|
|
|
|
|
pRightMost = cLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
}
|
|
|
|
|
//If there's an RSUP
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( RSUP ) ) ){
|
|
|
|
|
SmCaretPosGraphEntry *cLeft; //Child left
|
|
|
|
|
cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), bodyRight );
|
|
|
|
|
|
|
|
|
|
pRightMost = cLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
}
|
|
|
|
|
//If there's an RSUB
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( RSUB ) ) ){
|
|
|
|
|
SmCaretPosGraphEntry *cLeft; //Child left
|
|
|
|
|
cLeft = pGraph->Add( SmCaretPos( pChild, 0 ), bodyRight );
|
|
|
|
|
|
|
|
|
|
pRightMost = cLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Set return parameters
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build caret position for SmOperNode
|
|
|
|
|
*
|
2011-04-12 21:06:27 +09:00
|
|
|
|
* If first child is an SmSubSupNode we will ignore its
|
2010-10-01 22:04:50 +02:00
|
|
|
|
* body, as this body is a SmMathSymbol, for SUM, INT or similar
|
|
|
|
|
* that shouldn't be subject to modification.
|
|
|
|
|
* If first child is not a SmSubSupNode, ignore it completely
|
|
|
|
|
* as it is a SmMathSymbol.
|
|
|
|
|
*
|
|
|
|
|
* The child positions in a SmOperNode, where H is symbol, e.g. int, sum or similar:
|
|
|
|
|
* \code
|
|
|
|
|
* TO
|
|
|
|
|
*
|
|
|
|
|
* LSUP H H RSUP BBB BB BBB B B
|
|
|
|
|
* H H B B B B B B B B
|
|
|
|
|
* HHHH BBB B B B B B
|
|
|
|
|
* H H B B B B B B B
|
|
|
|
|
* LSUB H H RSUB BBB BB BBB B
|
|
|
|
|
*
|
|
|
|
|
* FROM
|
|
|
|
|
* \endcode
|
|
|
|
|
* Notice, CSUP, etc. are actually granchildren, but inorder to ignore H, these are visited
|
|
|
|
|
* from here. If they are present, that is if pOper is an instance of SmSubSupNode.
|
|
|
|
|
*
|
|
|
|
|
* Graph over these, where "left" is before the SmOperNode and "right" is after:
|
|
|
|
|
* \dot
|
|
|
|
|
* digraph Graph{
|
|
|
|
|
* left -> BODY;
|
|
|
|
|
* BODY -> right;
|
|
|
|
|
* LSUP -> BODY;
|
|
|
|
|
* LSUB -> BODY;
|
|
|
|
|
* TO -> BODY;
|
|
|
|
|
* FROM -> BODY;
|
|
|
|
|
* RSUP -> BODY;
|
|
|
|
|
* RSUB -> BODY;
|
|
|
|
|
* };
|
|
|
|
|
* \enddot
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmOperNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pOper = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pBody = pNode->GetSubNode( 1 );
|
|
|
|
|
|
|
|
|
|
SmCaretPosGraphEntry *left = pRightMost,
|
|
|
|
|
*bodyLeft,
|
|
|
|
|
*bodyRight,
|
|
|
|
|
*right;
|
|
|
|
|
//Create body left
|
|
|
|
|
bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left );
|
|
|
|
|
left->SetRight( bodyLeft );
|
|
|
|
|
|
|
|
|
|
//Visit body, get bodyRight
|
|
|
|
|
pRightMost = bodyLeft;
|
|
|
|
|
pBody->Accept( this );
|
|
|
|
|
bodyRight = pRightMost;
|
|
|
|
|
|
|
|
|
|
//Create right
|
|
|
|
|
right = pGraph->Add( SmCaretPos( pNode, 1 ), bodyRight );
|
|
|
|
|
bodyRight->SetRight( right );
|
|
|
|
|
|
|
|
|
|
//Get subsup pNode if any
|
|
|
|
|
SmSubSupNode* pSubSup = pOper->GetType( ) == NSUBSUP ? ( SmSubSupNode* )pOper : NULL;
|
|
|
|
|
|
|
|
|
|
SmNode* pChild;
|
|
|
|
|
SmCaretPosGraphEntry *childLeft;
|
|
|
|
|
if( pSubSup && ( pChild = pSubSup->GetSubSup( LSUP ) ) ) {
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Create position in front of pChild
|
2010-10-01 22:04:50 +02:00
|
|
|
|
childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
//Visit pChild
|
|
|
|
|
pRightMost = childLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
//Set right on pRightMost from pChild
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
if( pSubSup && ( pChild = pSubSup->GetSubSup( LSUB ) ) ) {
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Create position in front of pChild
|
2010-10-01 22:04:50 +02:00
|
|
|
|
childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
//Visit pChild
|
|
|
|
|
pRightMost = childLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
//Set right on pRightMost from pChild
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
if( pSubSup && ( pChild = pSubSup->GetSubSup( CSUP ) ) ) {//TO
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Create position in front of pChild
|
2010-10-01 22:04:50 +02:00
|
|
|
|
childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
//Visit pChild
|
|
|
|
|
pRightMost = childLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
//Set right on pRightMost from pChild
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
if( pSubSup && ( pChild = pSubSup->GetSubSup( CSUB ) ) ) { //FROM
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Create position in front of pChild
|
2010-10-01 22:04:50 +02:00
|
|
|
|
childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
//Visit pChild
|
|
|
|
|
pRightMost = childLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
//Set right on pRightMost from pChild
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
if( pSubSup && ( pChild = pSubSup->GetSubSup( RSUP ) ) ) {
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Create position in front of pChild
|
2010-10-01 22:04:50 +02:00
|
|
|
|
childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
//Visit pChild
|
|
|
|
|
pRightMost = childLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
//Set right on pRightMost from pChild
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
if( pSubSup && ( pChild = pSubSup->GetSubSup( RSUB ) ) ) {
|
2011-04-12 21:06:27 +09:00
|
|
|
|
//Create position in front of pChild
|
2010-10-01 22:04:50 +02:00
|
|
|
|
childLeft = pGraph->Add( SmCaretPos( pChild, 0 ), left );
|
|
|
|
|
//Visit pChild
|
|
|
|
|
pRightMost = childLeft;
|
|
|
|
|
pChild->Accept( this );
|
|
|
|
|
//Set right on pRightMost from pChild
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Return right
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmMatrixNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmCaretPosGraphEntry *left = pRightMost,
|
|
|
|
|
*right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
2011-03-14 16:51:14 +00:00
|
|
|
|
for ( sal_uInt16 i = 0; i < pNode->GetNumRows( ); i++ ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
SmCaretPosGraphEntry* r = left;
|
2011-03-14 16:51:14 +00:00
|
|
|
|
for ( sal_uInt16 j = 0; j < pNode->GetNumCols( ); j++ ){
|
2010-10-01 22:04:50 +02:00
|
|
|
|
SmNode* pSubNode = pNode->GetSubNode( i * pNode->GetNumCols( ) + j );
|
|
|
|
|
|
|
|
|
|
pRightMost = pGraph->Add( SmCaretPos( pSubNode, 0 ), r );
|
|
|
|
|
if( j != 0 || ( pNode->GetNumRows( ) - 1 ) / 2 == i )
|
|
|
|
|
r->SetRight( pRightMost );
|
|
|
|
|
|
|
|
|
|
pSubNode->Accept( this );
|
|
|
|
|
|
|
|
|
|
r = pRightMost;
|
|
|
|
|
}
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
if( ( pNode->GetNumRows( ) - 1 ) / 2 == i )
|
|
|
|
|
right->SetLeft( pRightMost );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmTextNode
|
|
|
|
|
*
|
|
|
|
|
* Lines in an SmTextNode:
|
|
|
|
|
* \code
|
|
|
|
|
* A B C
|
|
|
|
|
* \endcode
|
|
|
|
|
* Where A B and C are characters in the text.
|
|
|
|
|
*
|
|
|
|
|
* Graph over these, where "left" is before the SmTextNode and "right" is after:
|
|
|
|
|
* \dot
|
|
|
|
|
* digraph Graph{
|
|
|
|
|
* left -> A;
|
|
|
|
|
* A -> B
|
|
|
|
|
* B -> right;
|
|
|
|
|
* };
|
|
|
|
|
* \enddot
|
|
|
|
|
* Notice that C and right is the same position here.
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( pNode->GetText().isEmpty(), "starmath", "Empty SmTextNode is bad" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
2012-10-01 20:46:34 +04:00
|
|
|
|
int size = pNode->GetText().getLength();
|
2010-10-01 22:04:50 +02:00
|
|
|
|
for( int i = 1; i <= size; i++ ){
|
|
|
|
|
SmCaretPosGraphEntry* pRight = pRightMost;
|
|
|
|
|
pRightMost = pGraph->Add( SmCaretPos( pNode, i ), pRight );
|
|
|
|
|
pRight->SetRight( pRightMost );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmBinVerNode
|
|
|
|
|
*
|
|
|
|
|
* Lines in an SmBinVerNode:
|
|
|
|
|
* \code
|
|
|
|
|
* A
|
|
|
|
|
* -----
|
|
|
|
|
* B
|
|
|
|
|
* \endcode
|
|
|
|
|
*
|
|
|
|
|
* Graph over these, where "left" is before the SmBinVerNode and "right" is after:
|
|
|
|
|
* \dot
|
|
|
|
|
* digraph Graph{
|
|
|
|
|
* left -> A;
|
|
|
|
|
* A -> right;
|
|
|
|
|
* B -> right;
|
|
|
|
|
* };
|
|
|
|
|
* \enddot
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmBinVerNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
//None if these children can be NULL, see SmBinVerNode::Arrange
|
|
|
|
|
SmNode *pNum = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pDenom = pNode->GetSubNode( 2 );
|
|
|
|
|
|
2010-10-03 16:16:52 +02:00
|
|
|
|
SmCaretPosGraphEntry *left,
|
|
|
|
|
*right,
|
|
|
|
|
*numLeft,
|
|
|
|
|
*denomLeft;
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
//Set left
|
|
|
|
|
left = pRightMost;
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( !pRightMost, "starmath", "There must be a position in front of this" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
//Create right
|
|
|
|
|
right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
|
|
|
|
//Create numLeft
|
|
|
|
|
numLeft = pGraph->Add( SmCaretPos( pNum, 0 ), left );
|
|
|
|
|
left->SetRight( numLeft );
|
|
|
|
|
|
|
|
|
|
//Visit pNum
|
|
|
|
|
pRightMost = numLeft;
|
|
|
|
|
pNum->Accept( this );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
right->SetLeft( pRightMost );
|
|
|
|
|
|
|
|
|
|
//Create denomLeft
|
|
|
|
|
denomLeft = pGraph->Add( SmCaretPos( pDenom, 0 ), left );
|
|
|
|
|
|
|
|
|
|
//Visit pDenom
|
|
|
|
|
pRightMost = denomLeft;
|
|
|
|
|
pDenom->Accept( this );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
|
|
|
|
|
//Set return parameter
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmVerticalBraceNode
|
|
|
|
|
*
|
|
|
|
|
* Lines in an SmVerticalBraceNode:
|
|
|
|
|
* \code
|
|
|
|
|
* pScript
|
|
|
|
|
* ________
|
|
|
|
|
* / \
|
|
|
|
|
* pBody
|
|
|
|
|
* \endcode
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmVerticalBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pBody = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pScript = pNode->GetSubNode( 2 );
|
|
|
|
|
//None of these children can be NULL
|
|
|
|
|
|
|
|
|
|
SmCaretPosGraphEntry *left,
|
|
|
|
|
*bodyLeft,
|
|
|
|
|
*scriptLeft,
|
|
|
|
|
*right;
|
|
|
|
|
|
|
|
|
|
left = pRightMost;
|
|
|
|
|
|
|
|
|
|
//Create right
|
|
|
|
|
right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
|
|
|
|
//Create bodyLeft
|
|
|
|
|
bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left );
|
|
|
|
|
left->SetRight( bodyLeft );
|
|
|
|
|
pRightMost = bodyLeft;
|
|
|
|
|
pBody->Accept( this );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
right->SetLeft( pRightMost );
|
|
|
|
|
|
|
|
|
|
//Create script
|
|
|
|
|
scriptLeft = pGraph->Add( SmCaretPos( pScript, 0 ), left );
|
|
|
|
|
pRightMost = scriptLeft;
|
|
|
|
|
pScript->Accept( this );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
|
|
|
|
|
//Set return value
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmBinDiagonalNode
|
|
|
|
|
*
|
|
|
|
|
* Lines in an SmBinDiagonalNode:
|
|
|
|
|
* \code
|
|
|
|
|
* A /
|
|
|
|
|
* /
|
|
|
|
|
* / B
|
|
|
|
|
* \endcode
|
|
|
|
|
* Where A and B are lines.
|
|
|
|
|
*
|
|
|
|
|
* Used in formulas such as "A wideslash B"
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmBinDiagonalNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *A = pNode->GetSubNode( 0 ),
|
|
|
|
|
*B = pNode->GetSubNode( 1 );
|
|
|
|
|
|
|
|
|
|
SmCaretPosGraphEntry *left,
|
|
|
|
|
*leftA,
|
|
|
|
|
*rightA,
|
|
|
|
|
*leftB,
|
|
|
|
|
*right;
|
|
|
|
|
left = pRightMost;
|
|
|
|
|
|
|
|
|
|
//Create right
|
|
|
|
|
right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
|
|
|
|
//Create left A
|
|
|
|
|
leftA = pGraph->Add( SmCaretPos( A, 0 ), left );
|
|
|
|
|
left->SetRight( leftA );
|
|
|
|
|
|
|
|
|
|
//Visit A
|
|
|
|
|
pRightMost = leftA;
|
|
|
|
|
A->Accept( this );
|
|
|
|
|
rightA = pRightMost;
|
|
|
|
|
|
|
|
|
|
//Create left B
|
|
|
|
|
leftB = pGraph->Add( SmCaretPos( B, 0 ), rightA );
|
|
|
|
|
rightA->SetRight( leftB );
|
|
|
|
|
|
|
|
|
|
//Visit B
|
|
|
|
|
pRightMost = leftB;
|
|
|
|
|
B->Accept( this );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
right->SetLeft( pRightMost );
|
|
|
|
|
|
|
|
|
|
//Set return value
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Straigt forward ( I think )
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmBinHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmUnHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
// Unary operator node
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmExpressionNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmFontNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
//Has only got one child, should act as an expression if possible
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmBracebodyNode
|
|
|
|
|
* Acts as an SmExpressionNode
|
|
|
|
|
*
|
|
|
|
|
* Below is an example of a formula tree that has multiple children for SmBracebodyNode
|
|
|
|
|
* \dot
|
|
|
|
|
* digraph {
|
|
|
|
|
* labelloc = "t";
|
|
|
|
|
* label= "Equation: \"lbrace i mline i in setZ rbrace\"";
|
|
|
|
|
* n0 [label="SmTableNode"];
|
|
|
|
|
* n0 -> n1 [label="0"];
|
|
|
|
|
* n1 [label="SmLineNode"];
|
|
|
|
|
* n1 -> n2 [label="0"];
|
|
|
|
|
* n2 [label="SmExpressionNode"];
|
|
|
|
|
* n2 -> n3 [label="0"];
|
|
|
|
|
* n3 [label="SmBraceNode"];
|
|
|
|
|
* n3 -> n4 [label="0"];
|
|
|
|
|
* n4 [label="SmMathSymbolNode: {"];
|
|
|
|
|
* n3 -> n5 [label="1"];
|
|
|
|
|
* n5 [label="SmBracebodyNode"];
|
|
|
|
|
* n5 -> n6 [label="0"];
|
|
|
|
|
* n6 [label="SmExpressionNode"];
|
|
|
|
|
* n6 -> n7 [label="0"];
|
|
|
|
|
* n7 [label="SmTextNode: i"];
|
|
|
|
|
* n5 -> n8 [label="1"];
|
|
|
|
|
* n8 [label="SmMathSymbolNode: ∣"];
|
|
|
|
|
* n5 -> n9 [label="2"];
|
|
|
|
|
* n9 [label="SmExpressionNode"];
|
|
|
|
|
* n9 -> n10 [label="0"];
|
|
|
|
|
* n10 [label="SmBinHorNode"];
|
|
|
|
|
* n10 -> n11 [label="0"];
|
|
|
|
|
* n11 [label="SmTextNode: i"];
|
|
|
|
|
* n10 -> n12 [label="1"];
|
|
|
|
|
* n12 [label="SmMathSymbolNode: ∈"];
|
|
|
|
|
* n10 -> n13 [label="2"];
|
|
|
|
|
* n13 [label="SmMathSymbolNode: ℤ"];
|
|
|
|
|
* n3 -> n14 [label="2"];
|
|
|
|
|
* n14 [label="SmMathSymbolNode: }"];
|
|
|
|
|
* }
|
|
|
|
|
* \enddot
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmBracebodyNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) ) {
|
|
|
|
|
SmCaretPosGraphEntry* pStart = pGraph->Add( SmCaretPos( it.Current(), 0), pRightMost );
|
|
|
|
|
pRightMost->SetRight( pStart );
|
|
|
|
|
pRightMost = pStart;
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmAlignNode
|
|
|
|
|
* Acts as an SmExpressionNode, as it only has one child this okay
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmAlignNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmRootNode
|
|
|
|
|
*
|
|
|
|
|
* Lines in an SmRootNode:
|
|
|
|
|
* \code
|
|
|
|
|
* _________
|
|
|
|
|
* A/
|
|
|
|
|
* \/ B
|
|
|
|
|
*
|
|
|
|
|
* \endcode
|
|
|
|
|
* A: pExtra ( optional, can be NULL ),
|
|
|
|
|
* B: pBody
|
|
|
|
|
*
|
|
|
|
|
* Graph over these, where "left" is before the SmRootNode and "right" is after:
|
|
|
|
|
* \dot
|
|
|
|
|
* digraph Graph{
|
|
|
|
|
* left -> B;
|
|
|
|
|
* B -> right;
|
|
|
|
|
* A -> B;
|
|
|
|
|
* }
|
|
|
|
|
* \enddot
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmRootNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pExtra = pNode->GetSubNode( 0 ), //Argument, NULL for sqrt, and SmTextNode if cubicroot
|
|
|
|
|
*pBody = pNode->GetSubNode( 2 ); //Body of the root
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( !pBody, "starmath", "pBody cannot be NULL" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
SmCaretPosGraphEntry *left,
|
|
|
|
|
*right,
|
|
|
|
|
*bodyLeft,
|
|
|
|
|
*bodyRight;
|
|
|
|
|
|
|
|
|
|
//Get left and save it
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( !pRightMost, "starmath", "There must be a position in front of this" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
left = pRightMost;
|
|
|
|
|
|
|
|
|
|
//Create body left
|
|
|
|
|
bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left );
|
|
|
|
|
left->SetRight( bodyLeft );
|
|
|
|
|
|
|
|
|
|
//Create right
|
|
|
|
|
right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
|
|
|
|
//Visit body
|
|
|
|
|
pRightMost = bodyLeft;
|
|
|
|
|
pBody->Accept( this );
|
|
|
|
|
bodyRight = pRightMost;
|
|
|
|
|
bodyRight->SetRight( right );
|
|
|
|
|
right->SetLeft( bodyRight );
|
|
|
|
|
|
|
|
|
|
//Visit pExtra
|
|
|
|
|
if( pExtra ){
|
|
|
|
|
pRightMost = pGraph->Add( SmCaretPos( pExtra, 0 ), left );
|
|
|
|
|
pExtra->Accept( this );
|
|
|
|
|
pRightMost->SetRight( bodyLeft );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 14:37:55 -05:00
|
|
|
|
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmDynIntegralNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
//! To be changed: Integrals don't have args.
|
|
|
|
|
SmNode *pBody = pNode->Body(); //Body of the root
|
|
|
|
|
SAL_WARN_IF( !pBody, "starmath", "pBody cannot be NULL" );
|
|
|
|
|
|
|
|
|
|
SmCaretPosGraphEntry *left,
|
|
|
|
|
*right,
|
|
|
|
|
*bodyLeft,
|
|
|
|
|
*bodyRight;
|
|
|
|
|
|
|
|
|
|
//Get left and save it
|
|
|
|
|
SAL_WARN_IF( !pRightMost, "starmath", "There must be a position in front of this" );
|
|
|
|
|
left = pRightMost;
|
|
|
|
|
|
|
|
|
|
//Create body left
|
|
|
|
|
bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left );
|
|
|
|
|
left->SetRight( bodyLeft );
|
|
|
|
|
|
|
|
|
|
//Create right
|
|
|
|
|
right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
|
|
|
|
//Visit body
|
|
|
|
|
pRightMost = bodyLeft;
|
|
|
|
|
pBody->Accept( this );
|
|
|
|
|
bodyRight = pRightMost;
|
|
|
|
|
bodyRight->SetRight( right );
|
|
|
|
|
right->SetLeft( bodyRight );
|
|
|
|
|
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
/** Build SmCaretPosGraph for SmPlaceNode
|
|
|
|
|
* Consider this a single character.
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmPlaceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** SmErrorNode is context dependent metadata, it can't be selected
|
|
|
|
|
*
|
|
|
|
|
* @remarks There's no point in deleting, copying and/or moving an instance
|
|
|
|
|
* of SmErrorNode as it may not exist in an other context! Thus there are no
|
|
|
|
|
* positions to select an SmErrorNode.
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmErrorNode* )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmBlankNode
|
|
|
|
|
* Consider this a single character, as it is only a blank space
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmBlankNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmBraceNode
|
|
|
|
|
*
|
|
|
|
|
* Lines in an SmBraceNode:
|
|
|
|
|
* \code
|
|
|
|
|
* | |
|
|
|
|
|
* | B |
|
|
|
|
|
* | |
|
|
|
|
|
* \endcode
|
|
|
|
|
* B: Body
|
|
|
|
|
*
|
|
|
|
|
* Graph over these, where "left" is before the SmBraceNode and "right" is after:
|
|
|
|
|
* \dot
|
|
|
|
|
* digraph Graph{
|
|
|
|
|
* left -> B;
|
|
|
|
|
* B -> right;
|
|
|
|
|
* }
|
|
|
|
|
* \enddot
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode* pBody = pNode->GetSubNode( 1 );
|
|
|
|
|
|
|
|
|
|
SmCaretPosGraphEntry *left = pRightMost,
|
|
|
|
|
*right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
|
|
|
|
if( pBody->GetType() != NBRACEBODY ) {
|
|
|
|
|
pRightMost = pGraph->Add( SmCaretPos( pBody, 0 ), left );
|
|
|
|
|
left->SetRight( pRightMost );
|
|
|
|
|
}else
|
|
|
|
|
pRightMost = left;
|
|
|
|
|
|
|
|
|
|
pBody->Accept( this );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
right->SetLeft( pRightMost );
|
|
|
|
|
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Build SmCaretPosGraph for SmAttributNode
|
|
|
|
|
*
|
|
|
|
|
* Lines in an SmAttributNode:
|
|
|
|
|
* \code
|
|
|
|
|
* Attr
|
|
|
|
|
* Body
|
|
|
|
|
* \endcode
|
|
|
|
|
*
|
|
|
|
|
* There's a body and an attribute, the construction is used for "widehat A", where "A" is the body
|
|
|
|
|
* and "^" is the attribute ( note GetScaleMode( ) on SmAttributNode tells how the attribute should be
|
|
|
|
|
* scaled ).
|
|
|
|
|
*/
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmAttributNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pAttr = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pBody = pNode->GetSubNode( 1 );
|
|
|
|
|
//None of the children can be NULL
|
|
|
|
|
|
|
|
|
|
SmCaretPosGraphEntry *left = pRightMost,
|
|
|
|
|
*attrLeft,
|
|
|
|
|
*bodyLeft,
|
|
|
|
|
*bodyRight,
|
|
|
|
|
*right;
|
|
|
|
|
|
|
|
|
|
//Creating bodyleft
|
|
|
|
|
bodyLeft = pGraph->Add( SmCaretPos( pBody, 0 ), left );
|
|
|
|
|
left->SetRight( bodyLeft );
|
|
|
|
|
|
|
|
|
|
//Creating right
|
|
|
|
|
right = pGraph->Add( SmCaretPos( pNode, 1 ) );
|
|
|
|
|
|
|
|
|
|
//Visit the body
|
|
|
|
|
pRightMost = bodyLeft;
|
|
|
|
|
pBody->Accept( this );
|
|
|
|
|
bodyRight = pRightMost;
|
|
|
|
|
bodyRight->SetRight( right );
|
|
|
|
|
right->SetLeft( bodyRight );
|
|
|
|
|
|
|
|
|
|
//Create attrLeft
|
|
|
|
|
attrLeft = pGraph->Add( SmCaretPos( pAttr, 0 ), left );
|
|
|
|
|
|
|
|
|
|
//Visit attribute
|
|
|
|
|
pRightMost = attrLeft;
|
|
|
|
|
pAttr->Accept( this );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
|
|
|
|
|
//Set return value
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Consider these single symboles
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmGlyphSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmMathSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmCaretPosGraphEntry* right = pGraph->Add( SmCaretPos( pNode, 1 ), pRightMost );
|
|
|
|
|
pRightMost->SetRight( right );
|
|
|
|
|
pRightMost = right;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmRootSymbolNode* )
|
|
|
|
|
{
|
|
|
|
|
//Do nothing
|
|
|
|
|
}
|
2014-02-25 14:37:55 -05:00
|
|
|
|
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmDynIntegralSymbolNode* )
|
|
|
|
|
{
|
|
|
|
|
//Do nothing
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmRectangleNode* )
|
|
|
|
|
{
|
|
|
|
|
//Do nothing
|
|
|
|
|
}
|
|
|
|
|
void SmCaretPosGraphBuildingVisitor::Visit( SmPolyLineNode* )
|
|
|
|
|
{
|
|
|
|
|
//Do nothing
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmCloningVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
SmNode* SmCloningVisitor::Clone( SmNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode* pCurrResult = pResult;
|
|
|
|
|
pNode->Accept( this );
|
|
|
|
|
SmNode* pClone = pResult;
|
|
|
|
|
pResult = pCurrResult;
|
|
|
|
|
return pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::CloneNodeAttr( SmNode* pSource, SmNode* pTarget )
|
|
|
|
|
{
|
|
|
|
|
pTarget->SetScaleMode( pSource->GetScaleMode( ) );
|
|
|
|
|
//Other attributes are set when prepare or arrange is executed
|
|
|
|
|
//and may depend on stuff not being cloned here.
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::CloneKids( SmStructureNode* pSource, SmStructureNode* pTarget )
|
|
|
|
|
{
|
|
|
|
|
//Cache current result
|
|
|
|
|
SmNode* pCurrResult = pResult;
|
|
|
|
|
|
|
|
|
|
//Create array for holding clones
|
2011-03-14 16:51:14 +00:00
|
|
|
|
sal_uInt16 nSize = pSource->GetNumSubNodes( );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
SmNodeArray aNodes( nSize );
|
|
|
|
|
|
|
|
|
|
//Clone children
|
|
|
|
|
SmNode* pKid;
|
2011-03-14 16:51:14 +00:00
|
|
|
|
for( sal_uInt16 i = 0; i < nSize; i++ ){
|
2010-10-01 22:04:50 +02:00
|
|
|
|
if( NULL != ( pKid = pSource->GetSubNode( i ) ) )
|
|
|
|
|
pKid->Accept( this );
|
|
|
|
|
else
|
|
|
|
|
pResult = NULL;
|
|
|
|
|
aNodes[i] = pResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Set subnodes of pTarget
|
|
|
|
|
pTarget->SetSubNodes( aNodes );
|
|
|
|
|
|
|
|
|
|
//Restore result as where prior to call
|
|
|
|
|
pResult = pCurrResult;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmTableNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmTableNode* pClone = new SmTableNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmBraceNode* pClone = new SmBraceNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmBracebodyNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmBracebodyNode* pClone = new SmBracebodyNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmOperNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmOperNode* pClone = new SmOperNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmAlignNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmAlignNode* pClone = new SmAlignNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmAttributNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmAttributNode* pClone = new SmAttributNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmFontNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmFontNode* pClone = new SmFontNode( pNode->GetToken( ) );
|
|
|
|
|
pClone->SetSizeParameter( pNode->GetSizeParameter( ), pNode->GetSizeType( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmUnHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmUnHorNode* pClone = new SmUnHorNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmBinHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmBinHorNode* pClone = new SmBinHorNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmBinVerNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmBinVerNode* pClone = new SmBinVerNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmBinDiagonalNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmBinDiagonalNode *pClone = new SmBinDiagonalNode( pNode->GetToken( ) );
|
|
|
|
|
pClone->SetAscending( pNode->IsAscending( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmSubSupNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmSubSupNode *pClone = new SmSubSupNode( pNode->GetToken( ) );
|
|
|
|
|
pClone->SetUseLimits( pNode->IsUseLimits( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmMatrixNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmMatrixNode *pClone = new SmMatrixNode( pNode->GetToken( ) );
|
|
|
|
|
pClone->SetRowCol( pNode->GetNumRows( ), pNode->GetNumCols( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmPlaceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
pResult = new SmPlaceNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmTextNode* pClone = new SmTextNode( pNode->GetToken( ), pNode->GetFontDesc( ) );
|
|
|
|
|
pClone->ChangeText( pNode->GetText( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
pResult = new SmSpecialNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmGlyphSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
pResult = new SmGlyphSpecialNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmMathSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
pResult = new SmMathSymbolNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmBlankNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmBlankNode* pClone = new SmBlankNode( pNode->GetToken( ) );
|
|
|
|
|
pClone->SetBlankNum( pNode->GetBlankNum( ) );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmErrorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
//PE_NONE is used the information have been discarded and isn't used
|
|
|
|
|
pResult = new SmErrorNode( PE_NONE, pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmLineNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmLineNode* pClone = new SmLineNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmExpressionNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmExpressionNode* pClone = new SmExpressionNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmPolyLineNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
pResult = new SmPolyLineNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmRootNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmRootNode* pClone = new SmRootNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmRootSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
pResult = new SmRootSymbolNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 14:37:55 -05:00
|
|
|
|
void SmCloningVisitor::Visit( SmDynIntegralNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmDynIntegralNode* pClone = new SmDynIntegralNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmDynIntegralSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
pResult = new SmDynIntegralSymbolNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
void SmCloningVisitor::Visit( SmRectangleNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
pResult = new SmRectangleNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pResult );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmCloningVisitor::Visit( SmVerticalBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmVerticalBraceNode* pClone = new SmVerticalBraceNode( pNode->GetToken( ) );
|
|
|
|
|
CloneNodeAttr( pNode, pClone );
|
|
|
|
|
CloneKids( pNode, pClone );
|
|
|
|
|
pResult = pClone;
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmSelectionDrawingVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
SmSelectionDrawingVisitor::SmSelectionDrawingVisitor( OutputDevice& rDevice, SmNode* pTree, Point Offset )
|
|
|
|
|
: rDev( rDevice ) {
|
2010-11-06 01:33:05 +01:00
|
|
|
|
bHasSelectionArea = false;
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
|
|
|
|
//Visit everything
|
2013-09-09 09:07:24 +02:00
|
|
|
|
SAL_WARN_IF( !pTree, "starmath", "pTree can't be null!" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
if( pTree )
|
|
|
|
|
pTree->Accept( this );
|
|
|
|
|
|
|
|
|
|
//Draw selection if there's any
|
|
|
|
|
if( bHasSelectionArea ){
|
|
|
|
|
aSelectionArea.Move( Offset.X( ), Offset.Y( ) );
|
|
|
|
|
|
|
|
|
|
//Save device state
|
|
|
|
|
rDev.Push( PUSH_LINECOLOR | PUSH_FILLCOLOR );
|
|
|
|
|
//Change colors
|
|
|
|
|
rDev.SetLineColor( );
|
|
|
|
|
rDev.SetFillColor( Color( COL_LIGHTGRAY ) );
|
|
|
|
|
|
|
|
|
|
//Draw rectangle
|
|
|
|
|
rDev.DrawRect( aSelectionArea );
|
|
|
|
|
|
|
|
|
|
//Restore device state
|
|
|
|
|
rDev.Pop( );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmSelectionDrawingVisitor::ExtendSelectionArea( Rectangle aArea )
|
|
|
|
|
{
|
|
|
|
|
if ( ! bHasSelectionArea ) {
|
|
|
|
|
aSelectionArea = aArea;
|
|
|
|
|
bHasSelectionArea = true;
|
|
|
|
|
} else
|
|
|
|
|
aSelectionArea.Union( aArea );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmSelectionDrawingVisitor::DefaultVisit( SmNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if( pNode->IsSelected( ) )
|
|
|
|
|
ExtendSelectionArea( pNode->AsRectangle( ) );
|
|
|
|
|
VisitChildren( pNode );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmSelectionDrawingVisitor::VisitChildren( SmNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) )
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmSelectionDrawingVisitor::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if( pNode->IsSelected( ) ){
|
|
|
|
|
rDev.Push( PUSH_TEXTCOLOR | PUSH_FONT );
|
|
|
|
|
|
|
|
|
|
rDev.SetFont( pNode->GetFont( ) );
|
|
|
|
|
Point Position = pNode->GetTopLeft( );
|
|
|
|
|
long left = Position.getX( ) + rDev.GetTextWidth( pNode->GetText( ), 0, pNode->GetSelectionStart( ) );
|
|
|
|
|
long right = Position.getX( ) + rDev.GetTextWidth( pNode->GetText( ), 0, pNode->GetSelectionEnd( ) );
|
|
|
|
|
long top = Position.getY( );
|
|
|
|
|
long bottom = top + pNode->GetHeight( );
|
|
|
|
|
Rectangle rect( left, top, right, bottom );
|
|
|
|
|
|
|
|
|
|
ExtendSelectionArea( rect );
|
|
|
|
|
|
|
|
|
|
rDev.Pop( );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 20:41:20 +01:00
|
|
|
|
// SmNodeToTextVisitor
|
2010-10-01 22:04:50 +02:00
|
|
|
|
|
2012-09-27 21:07:25 +04:00
|
|
|
|
SmNodeToTextVisitor::SmNodeToTextVisitor( SmNode* pNode, OUString &rText )
|
|
|
|
|
{
|
|
|
|
|
pNode->Accept( this );
|
|
|
|
|
rText = aCmdText.makeStringAndClear();
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
void SmNodeToTextVisitor::Visit( SmTableNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if( pNode->GetToken( ).eType == TBINOM ) {
|
2010-12-19 15:24:46 +00:00
|
|
|
|
Append( "{ binom" );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pNode->GetSubNode( 0 ) );
|
|
|
|
|
LineToText( pNode->GetSubNode( 1 ) );
|
2010-12-19 15:24:46 +00:00
|
|
|
|
Append("} ");
|
2010-10-01 22:04:50 +02:00
|
|
|
|
} else if( pNode->GetToken( ).eType == TSTACK ) {
|
|
|
|
|
Append( "stack{ " );
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
it.Next( );
|
|
|
|
|
while( true ) {
|
|
|
|
|
LineToText( it.Current( ) );
|
|
|
|
|
if( it.Next( ) ) {
|
|
|
|
|
Separate( );
|
2010-11-23 10:36:18 +00:00
|
|
|
|
Append( "# " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
Separate( );
|
|
|
|
|
Append( "}" );
|
|
|
|
|
} else { //Assume it's a toplevel table, containing lines
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
it.Next( );
|
|
|
|
|
while( true ) {
|
|
|
|
|
Separate( );
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
if( it.Next( ) ) {
|
|
|
|
|
Separate( );
|
|
|
|
|
Append( "newline" );
|
|
|
|
|
}else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pLeftBrace = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pBody = pNode->GetSubNode( 1 ),
|
|
|
|
|
*pRightBrace = pNode->GetSubNode( 2 );
|
|
|
|
|
//Handle special case where it's absolute function
|
|
|
|
|
if( pNode->GetToken( ).eType == TABS ) {
|
|
|
|
|
Append( "abs" );
|
|
|
|
|
LineToText( pBody );
|
|
|
|
|
} else {
|
|
|
|
|
if( pNode->GetScaleMode( ) == SCALE_HEIGHT )
|
|
|
|
|
Append( "left " );
|
|
|
|
|
pLeftBrace->Accept( this );
|
|
|
|
|
Separate( );
|
|
|
|
|
pBody->Accept( this );
|
|
|
|
|
Separate( );
|
|
|
|
|
if( pNode->GetScaleMode( ) == SCALE_HEIGHT )
|
|
|
|
|
Append( "right " );
|
|
|
|
|
pRightBrace->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmBracebodyNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) ){
|
|
|
|
|
Separate( );
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmOperNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Append( pNode->GetToken( ).aText );
|
|
|
|
|
Separate( );
|
|
|
|
|
if( pNode->GetToken( ).eType == TOPER ){
|
|
|
|
|
//There's an SmGlyphSpecialNode if eType == TOPER
|
|
|
|
|
if( pNode->GetSubNode( 0 )->GetType( ) == NSUBSUP )
|
|
|
|
|
Append( pNode->GetSubNode( 0 )->GetSubNode( 0 )->GetToken( ).aText );
|
|
|
|
|
else
|
|
|
|
|
Append( pNode->GetSubNode( 0 )->GetToken( ).aText );
|
|
|
|
|
}
|
|
|
|
|
if( pNode->GetSubNode( 0 )->GetType( ) == NSUBSUP ) {
|
|
|
|
|
SmSubSupNode *pSubSup = ( SmSubSupNode* )pNode->GetSubNode( 0 );
|
|
|
|
|
SmNode* pChild;
|
|
|
|
|
if( ( pChild = pSubSup->GetSubSup( LSUP ) ) ) {
|
|
|
|
|
Separate( );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "lsup { " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
if( ( pChild = pSubSup->GetSubSup( LSUB ) ) ) {
|
|
|
|
|
Separate( );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "lsub { " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
if( ( pChild = pSubSup->GetSubSup( RSUP ) ) ) {
|
|
|
|
|
Separate( );
|
2012-07-17 21:39:07 +04:00
|
|
|
|
Append( "^ { " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
if( ( pChild = pSubSup->GetSubSup( RSUB ) ) ) {
|
|
|
|
|
Separate( );
|
2012-07-17 21:39:07 +04:00
|
|
|
|
Append( "_ { " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
2012-07-17 23:38:37 +04:00
|
|
|
|
if( ( pChild = pSubSup->GetSubSup( CSUB ) ) ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
Separate( );
|
2012-07-17 23:38:37 +04:00
|
|
|
|
if (pSubSup->IsUseLimits())
|
|
|
|
|
Append( "from { " );
|
|
|
|
|
else
|
|
|
|
|
Append( "csub { " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
2012-07-17 23:38:37 +04:00
|
|
|
|
if( ( pChild = pSubSup->GetSubSup( CSUP ) ) ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
Separate( );
|
2012-07-17 23:38:37 +04:00
|
|
|
|
if (pSubSup->IsUseLimits())
|
|
|
|
|
Append( "to { " );
|
|
|
|
|
else
|
|
|
|
|
Append( "csup { " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
LineToText( pNode->GetSubNode( 1 ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmAlignNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Append( pNode->GetToken( ).aText );
|
|
|
|
|
LineToText( pNode->GetSubNode( 0 ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmAttributNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Append( pNode->GetToken( ).aText );
|
|
|
|
|
LineToText( pNode->GetSubNode( 1 ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmFontNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
switch ( pNode->GetToken( ).eType )
|
|
|
|
|
{
|
|
|
|
|
case TBOLD:
|
|
|
|
|
Append( "bold " );
|
|
|
|
|
break;
|
|
|
|
|
case TNBOLD:
|
|
|
|
|
Append( "nbold " );
|
|
|
|
|
break;
|
|
|
|
|
case TITALIC:
|
|
|
|
|
Append( "italic " );
|
|
|
|
|
break;
|
|
|
|
|
case TNITALIC:
|
|
|
|
|
Append( "nitalic " );
|
|
|
|
|
break;
|
|
|
|
|
case TPHANTOM:
|
|
|
|
|
Append( "phantom " );
|
|
|
|
|
break;
|
|
|
|
|
case TSIZE:
|
|
|
|
|
{
|
|
|
|
|
Append( "size " );
|
|
|
|
|
switch ( pNode->GetSizeType( ) )
|
|
|
|
|
{
|
|
|
|
|
case FNTSIZ_PLUS:
|
|
|
|
|
Append( "+" );
|
|
|
|
|
break;
|
|
|
|
|
case FNTSIZ_MINUS:
|
|
|
|
|
Append( "-" );
|
|
|
|
|
break;
|
|
|
|
|
case FNTSIZ_MULTIPLY:
|
|
|
|
|
Append( "*" );
|
|
|
|
|
break;
|
|
|
|
|
case FNTSIZ_DIVIDE:
|
|
|
|
|
Append( "/" );
|
|
|
|
|
break;
|
|
|
|
|
case FNTSIZ_ABSOLUT:
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-10-01 20:46:34 +04:00
|
|
|
|
Append( ::rtl::math::doubleToUString(
|
2010-10-01 22:04:50 +02:00
|
|
|
|
static_cast<double>( pNode->GetSizeParameter( ) ),
|
|
|
|
|
rtl_math_StringFormat_Automatic,
|
2014-01-28 20:00:11 +01:00
|
|
|
|
rtl_math_DecimalPlaces_Max, '.', true ) );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
Append( " " );
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case TBLACK:
|
|
|
|
|
Append( "color black " );
|
|
|
|
|
break;
|
|
|
|
|
case TWHITE:
|
|
|
|
|
Append( "color white " );
|
|
|
|
|
break;
|
|
|
|
|
case TRED:
|
|
|
|
|
Append( "color red " );
|
|
|
|
|
break;
|
|
|
|
|
case TGREEN:
|
|
|
|
|
Append( "color green " );
|
|
|
|
|
break;
|
|
|
|
|
case TBLUE:
|
|
|
|
|
Append( "color blue " );
|
|
|
|
|
break;
|
|
|
|
|
case TCYAN:
|
|
|
|
|
Append( "color cyan " );
|
|
|
|
|
break;
|
|
|
|
|
case TMAGENTA:
|
|
|
|
|
Append( "color magenta " );
|
|
|
|
|
break;
|
|
|
|
|
case TYELLOW:
|
|
|
|
|
Append( "color yellow " );
|
|
|
|
|
break;
|
|
|
|
|
case TSANS:
|
|
|
|
|
Append( "font sans " );
|
|
|
|
|
break;
|
|
|
|
|
case TSERIF:
|
|
|
|
|
Append( "font serif " );
|
|
|
|
|
break;
|
|
|
|
|
case TFIXED:
|
|
|
|
|
Append( "font fixed " );
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
LineToText( pNode->GetSubNode( 1 ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmUnHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode, pNode->GetSubNode( 1 )->GetToken( ).eType == TFACT );
|
|
|
|
|
while( it.Next( ) ) {
|
|
|
|
|
Separate( );
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmBinHorNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pLeft = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pOper = pNode->GetSubNode( 1 ),
|
|
|
|
|
*pRight = pNode->GetSubNode( 2 );
|
|
|
|
|
Separate( );
|
|
|
|
|
pLeft->Accept( this );
|
|
|
|
|
Separate( );
|
|
|
|
|
pOper->Accept( this );
|
|
|
|
|
Separate( );
|
|
|
|
|
pRight->Accept( this );
|
|
|
|
|
Separate( );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmBinVerNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pNum = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pDenom = pNode->GetSubNode( 2 );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "{ " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pNum );
|
|
|
|
|
Append( "over" );
|
|
|
|
|
LineToText( pDenom );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmBinDiagonalNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pLeftOperand = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pRightOperand = pNode->GetSubNode( 1 );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "{ " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pLeftOperand );
|
|
|
|
|
Separate( );
|
|
|
|
|
Append( "wideslash " );
|
|
|
|
|
LineToText( pRightOperand );
|
2011-01-29 12:32:53 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmSubSupNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
LineToText( pNode->GetBody( ) );
|
|
|
|
|
SmNode *pChild;
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( LSUP ) ) ) {
|
|
|
|
|
Separate( );
|
|
|
|
|
Append( "lsup " );
|
|
|
|
|
LineToText( pChild );
|
|
|
|
|
}
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( LSUB ) ) ) {
|
|
|
|
|
Separate( );
|
|
|
|
|
Append( "lsub " );
|
|
|
|
|
LineToText( pChild );
|
|
|
|
|
}
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( RSUP ) ) ) {
|
|
|
|
|
Separate( );
|
2012-07-17 21:39:07 +04:00
|
|
|
|
Append( "^ " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
|
|
|
|
}
|
|
|
|
|
if( ( pChild = pNode->GetSubSup( RSUB ) ) ) {
|
|
|
|
|
Separate( );
|
2012-07-17 21:39:07 +04:00
|
|
|
|
Append( "_ " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
|
|
|
|
}
|
2012-07-17 23:38:37 +04:00
|
|
|
|
if( ( pChild = pNode->GetSubSup( CSUB ) ) ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
Separate( );
|
2012-07-17 23:38:37 +04:00
|
|
|
|
if (pNode->IsUseLimits())
|
|
|
|
|
Append( "from " );
|
|
|
|
|
else
|
|
|
|
|
Append( "csub " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
|
|
|
|
}
|
2012-07-17 23:38:37 +04:00
|
|
|
|
if( ( pChild = pNode->GetSubSup( CSUP ) ) ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
Separate( );
|
2012-07-17 23:38:37 +04:00
|
|
|
|
if (pNode->IsUseLimits())
|
|
|
|
|
Append( "to " );
|
|
|
|
|
else
|
|
|
|
|
Append( "csup " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
LineToText( pChild );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmMatrixNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Append( "matrix{" );
|
2011-03-14 16:51:14 +00:00
|
|
|
|
for ( sal_uInt16 i = 0; i < pNode->GetNumRows( ); i++ ) {
|
|
|
|
|
for ( sal_uInt16 j = 0; j < pNode->GetNumCols( ); j++ ) {
|
2010-10-01 22:04:50 +02:00
|
|
|
|
SmNode* pSubNode = pNode->GetSubNode( i * pNode->GetNumCols( ) + j );
|
|
|
|
|
Separate( );
|
|
|
|
|
pSubNode->Accept( this );
|
|
|
|
|
Separate( );
|
|
|
|
|
if( j != pNode->GetNumCols( ) - 1 )
|
|
|
|
|
Append( "#" );
|
|
|
|
|
}
|
|
|
|
|
Separate( );
|
|
|
|
|
if( i != pNode->GetNumRows( ) - 1 )
|
|
|
|
|
Append( "##" );
|
|
|
|
|
}
|
2010-12-05 17:09:57 +00:00
|
|
|
|
Append( "} " );
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmPlaceNode* )
|
|
|
|
|
{
|
|
|
|
|
Append( "<?>" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmTextNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
//TODO: This method might need improvements, see SmTextNode::CreateTextFromNode
|
|
|
|
|
if( pNode->GetToken( ).eType == TTEXT )
|
|
|
|
|
Append( "\"" );
|
|
|
|
|
Append( pNode->GetText( ) );
|
|
|
|
|
if( pNode->GetToken( ).eType == TTEXT )
|
|
|
|
|
Append( "\"" );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Append( pNode->GetToken( ).aText );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmGlyphSpecialNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
if( pNode->GetToken( ).eType == TBOPER )
|
|
|
|
|
Append( "boper " );
|
|
|
|
|
else
|
|
|
|
|
Append( "uoper " );
|
|
|
|
|
Append( pNode->GetToken( ).aText );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmMathSymbolNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Append( pNode->GetToken( ).aText );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmBlankNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
Append( pNode->GetToken( ).aText );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmErrorNode* )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmLineNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) ){
|
|
|
|
|
Separate( );
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmExpressionNode* pNode )
|
|
|
|
|
{
|
2011-01-29 12:32:53 +00:00
|
|
|
|
bool bracketsNeeded = pNode->GetNumSubNodes() != 1 || pNode->GetSubNode(0)->GetType() == NBINHOR;
|
2012-11-23 11:30:00 +00:00
|
|
|
|
if (!bracketsNeeded)
|
|
|
|
|
{
|
|
|
|
|
const SmNode *pParent = pNode->GetParent();
|
|
|
|
|
// nested subsups
|
|
|
|
|
bracketsNeeded =
|
|
|
|
|
pParent && pParent->GetType() == NSUBSUP &&
|
|
|
|
|
pNode->GetNumSubNodes() == 1 &&
|
|
|
|
|
pNode->GetSubNode(0)->GetType() == NSUBSUP;
|
|
|
|
|
}
|
2012-07-21 12:37:19 +04:00
|
|
|
|
|
2010-12-05 17:09:57 +00:00
|
|
|
|
if (bracketsNeeded) {
|
2010-11-23 10:36:18 +00:00
|
|
|
|
Append( "{ " );
|
|
|
|
|
}
|
2010-10-01 22:04:50 +02:00
|
|
|
|
SmNodeIterator it( pNode );
|
|
|
|
|
while( it.Next( ) ) {
|
|
|
|
|
it->Accept( this );
|
|
|
|
|
Separate( );
|
|
|
|
|
}
|
2010-12-05 17:09:57 +00:00
|
|
|
|
if (bracketsNeeded) {
|
2010-11-23 10:36:18 +00:00
|
|
|
|
Append( "} " );
|
|
|
|
|
}
|
2010-10-01 22:04:50 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmPolyLineNode* )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmRootNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pExtra = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pBody = pNode->GetSubNode( 2 );
|
|
|
|
|
if( pExtra ) {
|
|
|
|
|
Append( "nroot" );
|
|
|
|
|
LineToText( pExtra );
|
|
|
|
|
} else
|
|
|
|
|
Append( "sqrt" );
|
|
|
|
|
LineToText( pBody );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmRootSymbolNode* )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2014-02-25 14:37:55 -05:00
|
|
|
|
void SmNodeToTextVisitor::Visit( SmDynIntegralNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pBody = pNode->Body();
|
|
|
|
|
Append( "intd" );
|
|
|
|
|
LineToText( pBody );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmDynIntegralSymbolNode* )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-01 22:04:50 +02:00
|
|
|
|
void SmNodeToTextVisitor::Visit( SmRectangleNode* )
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void SmNodeToTextVisitor::Visit( SmVerticalBraceNode* pNode )
|
|
|
|
|
{
|
|
|
|
|
SmNode *pBody = pNode->GetSubNode( 0 ),
|
|
|
|
|
*pScript = pNode->GetSubNode( 2 );
|
|
|
|
|
LineToText( pBody );
|
|
|
|
|
Append( pNode->GetToken( ).aText );
|
|
|
|
|
LineToText( pScript );
|
|
|
|
|
}
|
2010-12-23 16:28:48 +00:00
|
|
|
|
|
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|