LCOV - code coverage report
Current view: top level - starmath/source - visitors.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 596 1280 46.6 %
Date: 2015-06-13 12:38:46 Functions: 81 178 45.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #include <tools/gen.hxx>
      11             : #include <vcl/lineinfo.hxx>
      12             : #include "visitors.hxx"
      13             : #include "tmpdevice.hxx"
      14             : #include "cursor.hxx"
      15             : 
      16             : // SmDefaultingVisitor
      17             : 
      18           2 : void SmDefaultingVisitor::Visit( SmTableNode* pNode )
      19             : {
      20           2 :     DefaultVisit( pNode );
      21           2 : }
      22             : 
      23           0 : void SmDefaultingVisitor::Visit( SmBraceNode* pNode )
      24             : {
      25           0 :     DefaultVisit( pNode );
      26           0 : }
      27             : 
      28           0 : void SmDefaultingVisitor::Visit( SmBracebodyNode* pNode )
      29             : {
      30           0 :     DefaultVisit( pNode );
      31           0 : }
      32             : 
      33           0 : void SmDefaultingVisitor::Visit( SmOperNode* pNode )
      34             : {
      35           0 :     DefaultVisit( pNode );
      36           0 : }
      37             : 
      38           0 : void SmDefaultingVisitor::Visit( SmAlignNode* pNode )
      39             : {
      40           0 :     DefaultVisit( pNode );
      41           0 : }
      42             : 
      43           0 : void SmDefaultingVisitor::Visit( SmAttributNode* pNode )
      44             : {
      45           0 :     DefaultVisit( pNode );
      46           0 : }
      47             : 
      48           0 : void SmDefaultingVisitor::Visit( SmFontNode* pNode )
      49             : {
      50           0 :     DefaultVisit( pNode );
      51           0 : }
      52             : 
      53           0 : void SmDefaultingVisitor::Visit( SmUnHorNode* pNode )
      54             : {
      55           0 :     DefaultVisit( pNode );
      56           0 : }
      57             : 
      58           0 : void SmDefaultingVisitor::Visit( SmBinHorNode* pNode )
      59             : {
      60           0 :     DefaultVisit( pNode );
      61           0 : }
      62             : 
      63           9 : void SmDefaultingVisitor::Visit( SmBinVerNode* pNode )
      64             : {
      65           9 :     DefaultVisit( pNode );
      66           9 : }
      67             : 
      68           0 : void SmDefaultingVisitor::Visit( SmBinDiagonalNode* pNode )
      69             : {
      70           0 :     DefaultVisit( pNode );
      71           0 : }
      72             : 
      73           6 : void SmDefaultingVisitor::Visit( SmSubSupNode* pNode )
      74             : {
      75           6 :     DefaultVisit( pNode );
      76           6 : }
      77             : 
      78           0 : void SmDefaultingVisitor::Visit( SmMatrixNode* pNode )
      79             : {
      80           0 :     DefaultVisit( pNode );
      81           0 : }
      82             : 
      83           6 : void SmDefaultingVisitor::Visit( SmPlaceNode* pNode )
      84             : {
      85           6 :     DefaultVisit( pNode );
      86           6 : }
      87             : 
      88           0 : void SmDefaultingVisitor::Visit( SmTextNode* pNode )
      89             : {
      90           0 :     DefaultVisit( pNode );
      91           0 : }
      92             : 
      93           0 : void SmDefaultingVisitor::Visit( SmSpecialNode* pNode )
      94             : {
      95           0 :     DefaultVisit( pNode );
      96           0 : }
      97             : 
      98           0 : void SmDefaultingVisitor::Visit( SmGlyphSpecialNode* pNode )
      99             : {
     100           0 :     DefaultVisit( pNode );
     101           0 : }
     102             : 
     103          23 : void SmDefaultingVisitor::Visit( SmMathSymbolNode* pNode )
     104             : {
     105          23 :     DefaultVisit( pNode );
     106          23 : }
     107             : 
     108           0 : void SmDefaultingVisitor::Visit( SmBlankNode* pNode )
     109             : {
     110           0 :     DefaultVisit( pNode );
     111           0 : }
     112             : 
     113           4 : void SmDefaultingVisitor::Visit( SmErrorNode* pNode )
     114             : {
     115           4 :     DefaultVisit( pNode );
     116           4 : }
     117             : 
     118           0 : void SmDefaultingVisitor::Visit( SmLineNode* pNode )
     119             : {
     120           0 :     DefaultVisit( pNode );
     121           0 : }
     122             : 
     123           4 : void SmDefaultingVisitor::Visit( SmExpressionNode* pNode )
     124             : {
     125           4 :     DefaultVisit( pNode );
     126           4 : }
     127             : 
     128           0 : void SmDefaultingVisitor::Visit( SmPolyLineNode* pNode )
     129             : {
     130           0 :     DefaultVisit( pNode );
     131           0 : }
     132             : 
     133           0 : void SmDefaultingVisitor::Visit( SmRootNode* pNode )
     134             : {
     135           0 :     DefaultVisit( pNode );
     136           0 : }
     137             : 
     138           0 : void SmDefaultingVisitor::Visit( SmRootSymbolNode* pNode )
     139             : {
     140           0 :     DefaultVisit( pNode );
     141           0 : }
     142             : 
     143           0 : void SmDefaultingVisitor::Visit( SmDynIntegralNode* pNode )
     144             : {
     145           0 :     DefaultVisit( pNode );
     146           0 : }
     147             : 
     148           0 : void SmDefaultingVisitor::Visit( SmDynIntegralSymbolNode* pNode )
     149             : {
     150           0 :     DefaultVisit( pNode );
     151           0 : }
     152             : 
     153           7 : void SmDefaultingVisitor::Visit( SmRectangleNode* pNode )
     154             : {
     155           7 :     DefaultVisit( pNode );
     156           7 : }
     157             : 
     158           0 : void SmDefaultingVisitor::Visit( SmVerticalBraceNode* pNode )
     159             : {
     160           0 :     DefaultVisit( pNode );
     161           0 : }
     162             : 
     163             : // SmCaretDrawingVisitor
     164             : 
     165           0 : SmCaretDrawingVisitor::SmCaretDrawingVisitor( OutputDevice& rDevice,
     166             :                                              SmCaretPos position,
     167             :                                              Point offset,
     168             :                                              bool caretVisible )
     169           0 :  : rDev( rDevice )
     170             : {
     171           0 :     pos = position;
     172           0 :     Offset = offset;
     173           0 :     isCaretVisible = caretVisible;
     174             :     SAL_WARN_IF( !position.IsValid(), "starmath", "Cannot draw invalid position!" );
     175           0 :     if( !position.IsValid( ) )
     176           0 :         return;
     177             : 
     178             :     //Save device state
     179           0 :     rDev.Push( PushFlags::FONT | PushFlags::MAPMODE | PushFlags::LINECOLOR | PushFlags::FILLCOLOR | PushFlags::TEXTCOLOR );
     180             : 
     181           0 :     pos.pSelectedNode->Accept( this );
     182             :     //Restore device state
     183           0 :     rDev.Pop( );
     184             : }
     185             : 
     186           0 : void SmCaretDrawingVisitor::Visit( SmTextNode* pNode )
     187             : {
     188           0 :     long i = pos.Index;
     189             : 
     190           0 :     rDev.SetFont( pNode->GetFont( ) );
     191             : 
     192             :     //Find the line
     193           0 :     SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode );
     194             : 
     195             :     //Find coordinates
     196           0 :     long left = pNode->GetLeft( ) + rDev.GetTextWidth( pNode->GetText( ), 0, i ) + Offset.X( );
     197           0 :     long top = pLine->GetTop( ) + Offset.Y( );
     198           0 :     long height = pLine->GetHeight( );
     199           0 :     long left_line = pLine->GetLeft( ) + Offset.X( );
     200           0 :     long right_line = pLine->GetRight( ) + Offset.X( );
     201             : 
     202             :     //Set color
     203           0 :     rDev.SetLineColor( Color( COL_BLACK ) );
     204             : 
     205           0 :     if ( isCaretVisible ) {
     206             :         //Draw vertical line
     207           0 :         Point p1( left, top );
     208           0 :         Point p2( left, top + height );
     209           0 :         rDev.DrawLine( p1, p2 );
     210             :     }
     211             : 
     212             :     //Underline the line
     213           0 :     Point pLeft( left_line, top + height );
     214           0 :     Point pRight( right_line, top + height );
     215           0 :     rDev.DrawLine( pLeft, pRight );
     216           0 : }
     217             : 
     218           0 : void SmCaretDrawingVisitor::DefaultVisit( SmNode* pNode )
     219             : {
     220           0 :     rDev.SetLineColor( Color( COL_BLACK ) );
     221             : 
     222             :     //Find the line
     223           0 :     SmNode* pLine = SmCursor::FindTopMostNodeInLine( pNode );
     224             : 
     225             :     //Find coordinates
     226           0 :     long left = pNode->GetLeft( ) + Offset.X( ) + ( pos.Index == 1 ? pNode->GetWidth( ) : 0 );
     227           0 :     long top = pLine->GetTop( ) + Offset.Y( );
     228           0 :     long height = pLine->GetHeight( );
     229           0 :     long left_line = pLine->GetLeft( ) + Offset.X( );
     230           0 :     long right_line = pLine->GetRight( ) + Offset.X( );
     231             : 
     232             :     //Set color
     233           0 :     rDev.SetLineColor( Color( COL_BLACK ) );
     234             : 
     235           0 :     if ( isCaretVisible ) {
     236             :         //Draw vertical line
     237           0 :         Point p1( left, top );
     238           0 :         Point p2( left, top + height );
     239           0 :         rDev.DrawLine( p1, p2 );
     240             :     }
     241             : 
     242             :     //Underline the line
     243           0 :     Point pLeft( left_line, top + height );
     244           0 :     Point pRight( right_line, top + height );
     245           0 :     rDev.DrawLine( pLeft, pRight );
     246           0 : }
     247             : 
     248             : // SmCaretPos2LineVisitor
     249             : 
     250           2 : void SmCaretPos2LineVisitor::Visit( SmTextNode* pNode )
     251             : {
     252             :     //Save device state
     253           2 :     pDev->Push( PushFlags::FONT | PushFlags::TEXTCOLOR );
     254             : 
     255           2 :     long i = pos.Index;
     256             : 
     257           2 :     pDev->SetFont( pNode->GetFont( ) );
     258             : 
     259             :     //Find coordinates
     260           2 :     long left = pNode->GetLeft( ) + pDev->GetTextWidth( pNode->GetText( ), 0, i );
     261           2 :     long top = pNode->GetTop( );
     262           2 :     long height = pNode->GetHeight( );
     263             : 
     264           2 :     line = SmCaretLine( left, top, height );
     265             : 
     266             :     //Restore device state
     267           2 :     pDev->Pop( );
     268           2 : }
     269             : 
     270          12 : void SmCaretPos2LineVisitor::DefaultVisit( SmNode* pNode )
     271             : {
     272             :     //Vertical line ( code from SmCaretDrawingVisitor )
     273          12 :     Point p1 = pNode->GetTopLeft( );
     274          12 :     if( pos.Index == 1 )
     275           6 :         p1.Move( pNode->GetWidth( ), 0 );
     276             : 
     277          12 :     line = SmCaretLine( p1.X( ), p1.Y( ), pNode->GetHeight( ) );
     278          12 : }
     279             : 
     280             : 
     281             : // SmDrawingVisitor
     282             : 
     283        5097 : void SmDrawingVisitor::Visit( SmTableNode* pNode )
     284             : {
     285        5097 :     DrawChildren( pNode );
     286        5097 : }
     287             : 
     288        2482 : void SmDrawingVisitor::Visit( SmBraceNode* pNode )
     289             : {
     290        2482 :     DrawChildren( pNode );
     291        2482 : }
     292             : 
     293        2482 : void SmDrawingVisitor::Visit( SmBracebodyNode* pNode )
     294             : {
     295        2482 :     DrawChildren( pNode );
     296        2482 : }
     297             : 
     298         906 : void SmDrawingVisitor::Visit( SmOperNode* pNode )
     299             : {
     300         906 :     DrawChildren( pNode );
     301         906 : }
     302             : 
     303           0 : void SmDrawingVisitor::Visit( SmAlignNode* pNode )
     304             : {
     305           0 :     DrawChildren( pNode );
     306           0 : }
     307             : 
     308        1431 : void SmDrawingVisitor::Visit( SmAttributNode* pNode )
     309             : {
     310        1431 :     DrawChildren( pNode );
     311        1431 : }
     312             : 
     313          16 : void SmDrawingVisitor::Visit( SmFontNode* pNode )
     314             : {
     315          16 :     DrawChildren( pNode );
     316          16 : }
     317             : 
     318         466 : void SmDrawingVisitor::Visit( SmUnHorNode* pNode )
     319             : {
     320         466 :     DrawChildren( pNode );
     321         466 : }
     322             : 
     323        3962 : void SmDrawingVisitor::Visit( SmBinHorNode* pNode )
     324             : {
     325        3962 :     DrawChildren( pNode );
     326        3962 : }
     327             : 
     328        1247 : void SmDrawingVisitor::Visit( SmBinVerNode* pNode )
     329             : {
     330        1247 :     DrawChildren( pNode );
     331        1247 : }
     332             : 
     333          64 : void SmDrawingVisitor::Visit( SmBinDiagonalNode* pNode )
     334             : {
     335          64 :     DrawChildren( pNode );
     336          64 : }
     337             : 
     338        3962 : void SmDrawingVisitor::Visit( SmSubSupNode* pNode )
     339             : {
     340        3962 :     DrawChildren( pNode );
     341        3962 : }
     342             : 
     343         102 : void SmDrawingVisitor::Visit( SmMatrixNode* pNode )
     344             : {
     345         102 :     DrawChildren( pNode );
     346         102 : }
     347             : 
     348        1566 : void SmDrawingVisitor::Visit( SmPlaceNode* pNode )
     349             : {
     350        1566 :     DrawSpecialNode( pNode );
     351        1566 : }
     352             : 
     353       23065 : void SmDrawingVisitor::Visit( SmTextNode* pNode )
     354             : {
     355       23065 :     DrawTextNode( pNode );
     356       23065 : }
     357             : 
     358           0 : void SmDrawingVisitor::Visit( SmSpecialNode* pNode )
     359             : {
     360           0 :     DrawSpecialNode( pNode );
     361           0 : }
     362             : 
     363           0 : void SmDrawingVisitor::Visit( SmGlyphSpecialNode* pNode )
     364             : {
     365           0 :     DrawSpecialNode( pNode );
     366           0 : }
     367             : 
     368       12152 : void SmDrawingVisitor::Visit( SmMathSymbolNode* pNode )
     369             : {
     370       12152 :     DrawSpecialNode( pNode );
     371       12152 : }
     372             : 
     373           0 : void SmDrawingVisitor::Visit( SmBlankNode* pNode )
     374             : {
     375           0 :     DrawChildren( pNode );
     376           0 : }
     377             : 
     378         136 : void SmDrawingVisitor::Visit( SmErrorNode* pNode )
     379             : {
     380         136 :     DrawSpecialNode( pNode );
     381         136 : }
     382             : 
     383        4587 : void SmDrawingVisitor::Visit( SmLineNode* pNode )
     384             : {
     385        4587 :     DrawChildren( pNode );
     386        4587 : }
     387             : 
     388        3496 : void SmDrawingVisitor::Visit( SmExpressionNode* pNode )
     389             : {
     390        3496 :     DrawChildren( pNode );
     391        3496 : }
     392             : 
     393         442 : void SmDrawingVisitor::Visit( SmRootNode* pNode )
     394             : {
     395         442 :     DrawChildren( pNode );
     396         442 : }
     397             : 
     398           0 : void SmDrawingVisitor::Visit(SmDynIntegralNode* pNode)
     399             : {
     400           0 :     DrawChildren( pNode );
     401           0 : }
     402             : 
     403         204 : void SmDrawingVisitor::Visit( SmVerticalBraceNode* pNode )
     404             : {
     405         204 :     DrawChildren( pNode );
     406         204 : }
     407             : 
     408         442 : void SmDrawingVisitor::Visit( SmRootSymbolNode* pNode )
     409             : {
     410         442 :     if ( pNode->IsPhantom( ) )
     411         442 :         return;
     412             : 
     413             :     // draw root-sign itself
     414         442 :     DrawSpecialNode( pNode );
     415             : 
     416         442 :     SmTmpDevice aTmpDev( ( OutputDevice & ) rDev, true );
     417         442 :     aTmpDev.SetFillColor( pNode->GetFont( ).GetColor( ) );
     418         442 :     rDev.SetLineColor( );
     419         442 :     aTmpDev.SetFont( pNode->GetFont( ) );
     420             : 
     421             :     // since the width is always unscaled it corresponds ot the _original_
     422             :     // _unscaled_ font height to be used, we use that to calculate the
     423             :     // bar height. Thus it is independent of the arguments height.
     424             :     // ( see display of sqrt QQQ versus sqrt stack{Q#Q#Q#Q} )
     425         442 :     long nBarHeight = pNode->GetWidth( ) * 7L / 100L;
     426         442 :     long nBarWidth = pNode->GetBodyWidth( ) + pNode->GetBorderWidth( );
     427         442 :     Point aBarOffset( pNode->GetWidth( ), +pNode->GetBorderWidth( ) );
     428         442 :     Point aBarPos( Position + aBarOffset );
     429             : 
     430         442 :     Rectangle  aBar( aBarPos, Size( nBarWidth, nBarHeight ) );
     431             :     //! avoid GROWING AND SHRINKING of drawn rectangle when constantly
     432             :     //! increasing zoomfactor.
     433             :     //  This is done by shifting its output-position to a point that
     434             :     //  corresponds exactly to a pixel on the output device.
     435         442 :     Point  aDrawPos( rDev.PixelToLogic( rDev.LogicToPixel( aBar.TopLeft( ) ) ) );
     436         442 :     aBar.SetPos( aDrawPos );
     437             : 
     438         442 :     rDev.DrawRect( aBar );
     439             : }
     440             : 
     441           0 : void SmDrawingVisitor::Visit( SmDynIntegralSymbolNode* pNode )
     442             : {
     443           0 :     if ( pNode->IsPhantom( ) )
     444           0 :         return;
     445             : 
     446             :     // draw integral-sign itself
     447           0 :     DrawSpecialNode( pNode );
     448             : 
     449             :     //! the rest of this may not be needed at all
     450             : 
     451             :     // this should be something like:
     452             :     // instead of just drawing the node, take some information about the body.
     453             :     // This is also how SmRootSymbol does it (probably by means of SmRootNode)
     454             :     // NEXT: Check out SmRootNode
     455             : }
     456             : 
     457          64 : void SmDrawingVisitor::Visit( SmPolyLineNode* pNode )
     458             : {
     459          64 :     if ( pNode->IsPhantom( ) )
     460          64 :         return;
     461             : 
     462          64 :     long nBorderwidth = pNode->GetFont( ).GetBorderWidth( );
     463             : 
     464          64 :     LineInfo  aInfo;
     465          64 :     aInfo.SetWidth( pNode->GetWidth( ) - 2 * nBorderwidth );
     466             : 
     467         128 :     Point aOffset ( Point( ) - pNode->GetPolygon( ).GetBoundRect( ).TopLeft( )
     468         192 :                    + Point( nBorderwidth, nBorderwidth ) ),
     469          64 :           aPos ( Position + aOffset );
     470          64 :     pNode->GetPolygon( ).Move( aPos.X( ), aPos.Y( ) );    //Works because Polygon wraps a pointer
     471             : 
     472         128 :     SmTmpDevice aTmpDev ( ( OutputDevice & ) rDev, false );
     473          64 :     aTmpDev.SetLineColor( pNode->GetFont( ).GetColor( ) );
     474             : 
     475         128 :     rDev.DrawPolyLine( pNode->GetPolygon( ), aInfo );
     476             : }
     477             : 
     478        1451 : void SmDrawingVisitor::Visit( SmRectangleNode* pNode )
     479             : {
     480        1451 :     if ( pNode->IsPhantom( ) )
     481        1451 :         return;
     482             : 
     483        1451 :     SmTmpDevice aTmpDev ( ( OutputDevice & ) rDev, false );
     484        1451 :     aTmpDev.SetFillColor( pNode->GetFont( ).GetColor( ) );
     485        1451 :     rDev.SetLineColor( );
     486        1451 :     aTmpDev.SetFont( pNode->GetFont( ) );
     487             : 
     488        1451 :     sal_uLong  nTmpBorderWidth = pNode->GetFont( ).GetBorderWidth( );
     489             : 
     490             :     // get rectangle and remove borderspace
     491        1451 :     Rectangle  aTmp ( pNode->AsRectangle( ) + Position - pNode->GetTopLeft( ) );
     492        1451 :     aTmp.Left( )   += nTmpBorderWidth;
     493        1451 :     aTmp.Right( )  -= nTmpBorderWidth;
     494        1451 :     aTmp.Top( )    += nTmpBorderWidth;
     495        1451 :     aTmp.Bottom( ) -= nTmpBorderWidth;
     496             : 
     497             :     SAL_WARN_IF( aTmp.GetHeight() == 0 || aTmp.GetWidth() == 0,
     498             :                 "starmath", "Empty rectangle" );
     499             : 
     500             :     //! avoid GROWING AND SHRINKING of drawn rectangle when constantly
     501             :     //! increasing zoomfactor.
     502             :     //  This is done by shifting its output-position to a point that
     503             :     //  corresponds exactly to a pixel on the output device.
     504        1451 :     Point  aPos ( rDev.PixelToLogic( rDev.LogicToPixel( aTmp.TopLeft( ) ) ) );
     505        1451 :     aTmp.SetPos( aPos );
     506             : 
     507        1451 :     rDev.DrawRect( aTmp );
     508             : }
     509             : 
     510       37361 : void SmDrawingVisitor::DrawTextNode( SmTextNode* pNode )
     511             : {
     512       37361 :     if ( pNode->IsPhantom() || pNode->GetText().isEmpty() || pNode->GetText()[0] == '\0' )
     513       37548 :         return;
     514             : 
     515       37174 :     SmTmpDevice aTmpDev ( ( OutputDevice & ) rDev, false );
     516       37174 :     aTmpDev.SetFont( pNode->GetFont( ) );
     517             : 
     518       37174 :     Point  aPos ( Position );
     519       37174 :     aPos.Y( ) += pNode->GetBaselineOffset( );
     520             :     // auf Pixelkoordinaten runden
     521       37174 :     aPos = rDev.PixelToLogic( rDev.LogicToPixel( aPos ) );
     522             : 
     523       37174 :     rDev.DrawStretchText( aPos, pNode->GetWidth( ), pNode->GetText( ) );
     524             : }
     525             : 
     526       14296 : void SmDrawingVisitor::DrawSpecialNode( SmSpecialNode* pNode )
     527             : {
     528             :     //! since this chars might come from any font, that we may not have
     529             :     //! set to ALIGN_BASELINE yet, we do it now.
     530       14296 :     pNode->GetFont( ).SetAlign( ALIGN_BASELINE );
     531             : 
     532       14296 :     DrawTextNode( pNode );
     533       14296 : }
     534             : 
     535       30946 : void SmDrawingVisitor::DrawChildren( SmNode* pNode )
     536             : {
     537       30946 :     if ( pNode->IsPhantom( ) )
     538       30946 :         return;
     539             : 
     540       30946 :     Point rPosition = Position;
     541             : 
     542       30946 :     SmNodeIterator it( pNode );
     543      126519 :     while( it.Next( ) )
     544             :     {
     545       64627 :         Point  aOffset ( it->GetTopLeft( ) - pNode->GetTopLeft( ) );
     546       64627 :         Position = rPosition + aOffset;
     547       64627 :         it->Accept( this );
     548             :     }
     549             : }
     550             : 
     551             : // SmSetSelectionVisitor
     552             : 
     553          19 : SmSetSelectionVisitor::SmSetSelectionVisitor( SmCaretPos startPos, SmCaretPos endPos, SmNode* pTree) {
     554          19 :     StartPos    = startPos;
     555          19 :     EndPos      = endPos;
     556          19 :     IsSelecting = false;
     557             : 
     558             :     //Assume that pTree is a SmTableNode
     559             :     SAL_WARN_IF(pTree->GetType() != NTABLE, "starmath", "pTree should be a SmTableNode!");
     560             :     //Visit root node, this is special as this node cannot be selected, but its children can!
     561          19 :     if(pTree->GetType() == NTABLE){
     562             :         //Change state if StartPos is in front of this node
     563          19 :         if( StartPos.pSelectedNode == pTree && StartPos.Index == 0 )
     564           0 :             IsSelecting = !IsSelecting;
     565             :         //Change state if EndPos is in front of this node
     566          19 :         if( EndPos.pSelectedNode == pTree && EndPos.Index == 0 )
     567           0 :             IsSelecting = !IsSelecting;
     568             :         SAL_WARN_IF(IsSelecting, "starmath", "Caret positions needed to set IsSelecting about, shouldn't be possible!");
     569             : 
     570             :         //Visit lines
     571          19 :         SmNodeIterator it( pTree );
     572          57 :         while( it.Next( ) ) {
     573          19 :             it->Accept( this );
     574             :             //If we started a selection in this line and it haven't ended, we do that now!
     575          19 :             if(IsSelecting) {
     576           0 :                 IsSelecting = false;
     577           0 :                 SetSelectedOnAll(it.Current(), true);
     578             :                 //Set StartPos and EndPos to invalid positions, this ensures that an unused
     579             :                 //start or end (because we forced end above), doesn't start a new selection.
     580           0 :                 StartPos = EndPos = SmCaretPos();
     581             :             }
     582             :         }
     583             :         //Check if pTree isn't selected
     584             :         SAL_WARN_IF(pTree->IsSelected(), "starmath", "pTree should never be selected!");
     585             :         //Discard the selection if there's a bug (it's better than crashing)
     586          19 :         if(pTree->IsSelected())
     587           0 :             SetSelectedOnAll(pTree, false);
     588             :     }else //This shouldn't happen, but I don't see any reason to die if it does
     589           0 :         pTree->Accept(this);
     590          19 : }
     591             : 
     592           0 : void SmSetSelectionVisitor::SetSelectedOnAll( SmNode* pSubTree, bool IsSelected ) {
     593           0 :     pSubTree->SetSelected( IsSelected );
     594             : 
     595             :     //Quick BFS to set all selections
     596           0 :     SmNodeIterator it( pSubTree );
     597           0 :     while( it.Next( ) )
     598           0 :         SetSelectedOnAll( it.Current( ), IsSelected );
     599           0 : }
     600             : 
     601          49 : void SmSetSelectionVisitor::DefaultVisit( SmNode* pNode ) {
     602             :     //Change state if StartPos is in front of this node
     603          49 :     if( StartPos.pSelectedNode == pNode && StartPos.Index == 0 )
     604           0 :         IsSelecting = !IsSelecting;
     605             :     //Change state if EndPos is in front of this node
     606          49 :     if( EndPos.pSelectedNode == pNode && EndPos.Index == 0 )
     607           0 :         IsSelecting = !IsSelecting;
     608             : 
     609             :     //Cache current state
     610          49 :     bool WasSelecting = IsSelecting;
     611          49 :     bool ChangedState = false;
     612             : 
     613             :     //Set selected
     614          49 :     pNode->SetSelected( IsSelecting );
     615             : 
     616             :     //Visit children
     617          49 :     SmNodeIterator it( pNode );
     618         135 :     while( it.Next( ) )
     619             :     {
     620          37 :         it->Accept( this );
     621          37 :         ChangedState = ( WasSelecting != IsSelecting ) || ChangedState;
     622             :     }
     623             : 
     624             :     //If state changed
     625          49 :     if( ChangedState )
     626             :     {
     627             :         //Select this node and all of its children
     628             :         //(Make exception for SmBracebodyNode)
     629           0 :         if( pNode->GetType() != NBRACEBODY ||
     630           0 :             !pNode->GetParent() ||
     631           0 :             pNode->GetParent()->GetType() != NBRACE )
     632           0 :             SetSelectedOnAll( pNode, true );
     633             :         else
     634           0 :             SetSelectedOnAll( pNode->GetParent(), true );
     635             :         /* If the equation is:      sqrt{2 + 4} + 5
     636             :          * And the selection is:    sqrt{2 + [4} +] 5
     637             :          *      Where [ denotes StartPos and ] denotes EndPos
     638             :          * Then the sqrt node should be selected, so that the
     639             :          * effective selection is:  [sqrt{2 + 4} +] 5
     640             :          * The same is the case if we swap StartPos and EndPos.
     641             :          */
     642             :     }
     643             : 
     644             :     //Change state if StartPos is after this node
     645          49 :     if( StartPos.pSelectedNode == pNode && StartPos.Index == 1 )
     646             :     {
     647           0 :         IsSelecting = !IsSelecting;
     648             :     }
     649             :     //Change state if EndPos is after of this node
     650          49 :     if( EndPos.pSelectedNode == pNode && EndPos.Index == 1 )
     651             :     {
     652           1 :         IsSelecting = !IsSelecting;
     653             :     }
     654          49 : }
     655             : 
     656          58 : void SmSetSelectionVisitor::VisitCompositionNode( SmNode* pNode ) {
     657             :     //Change state if StartPos is in front of this node
     658          58 :     if( StartPos.pSelectedNode == pNode && StartPos.Index == 0 )
     659          16 :         IsSelecting = !IsSelecting;
     660             :     //Change state if EndPos is in front of this node
     661          58 :     if( EndPos.pSelectedNode == pNode && EndPos.Index == 0 )
     662          17 :         IsSelecting = !IsSelecting;
     663             : 
     664             :     //Cache current state
     665          58 :     bool WasSelecting = IsSelecting;
     666             : 
     667             :     //Visit children
     668          58 :     SmNodeIterator it( pNode );
     669         209 :     while( it.Next( ) )
     670          93 :         it->Accept( this );
     671             : 
     672             :     //Set selected, if everything was selected
     673          58 :     pNode->SetSelected( WasSelecting && IsSelecting );
     674             : 
     675             :     //Change state if StartPos is after this node
     676          58 :     if( StartPos.pSelectedNode == pNode && StartPos.Index == 1 )
     677           0 :         IsSelecting = !IsSelecting;
     678             :     //Change state if EndPos is after of this node
     679          58 :     if( EndPos.pSelectedNode == pNode && EndPos.Index == 1 )
     680           0 :         IsSelecting = !IsSelecting;
     681          58 : }
     682             : 
     683          42 : void SmSetSelectionVisitor::Visit( SmTextNode* pNode ) {
     684          42 :     long    i1 = -1,
     685          42 :             i2 = -1;
     686          42 :     if( StartPos.pSelectedNode == pNode )
     687           3 :         i1 = StartPos.Index;
     688          42 :     if( EndPos.pSelectedNode == pNode )
     689           1 :         i2 = EndPos.Index;
     690             : 
     691             :     long start, end;
     692          42 :     pNode->SetSelected( true );
     693          42 :     if( i1 != -1 && i2 != -1 ) {
     694           1 :         start = i1 < i2 ? i1 : i2; //MIN
     695           1 :         end   = i1 > i2 ? i1 : i2; //MAX
     696          41 :     } else if( IsSelecting && i1 != -1 ) {
     697           2 :         start = 0;
     698           2 :         end = i1;
     699           2 :         IsSelecting = false;
     700          39 :     } else if( IsSelecting && i2 != -1 ) {
     701           0 :         start = 0;
     702           0 :         end = i2;
     703           0 :         IsSelecting = false;
     704          39 :     } else if( !IsSelecting && i1 != -1 ) {
     705           0 :         start = i1;
     706           0 :         end = pNode->GetText().getLength();
     707           0 :         IsSelecting = true;
     708          39 :     } else if( !IsSelecting && i2 != -1 ) {
     709           0 :         start = i2;
     710           0 :         end = pNode->GetText().getLength();
     711           0 :         IsSelecting = true;
     712          39 :     } else if( IsSelecting ) {
     713           0 :         start = 0;
     714           0 :         end = pNode->GetText().getLength();
     715             :     } else {
     716          39 :         pNode->SetSelected( false );
     717          39 :         start = 0;
     718          39 :         end = 0;
     719             :     }
     720          42 :     pNode->SetSelected( start != end );
     721          42 :     pNode->SetSelectionStart( start );
     722          42 :     pNode->SetSelectionEnd( end );
     723          42 : }
     724             : 
     725          35 : void SmSetSelectionVisitor::Visit( SmExpressionNode* pNode ) {
     726          35 :     VisitCompositionNode( pNode );
     727          35 : }
     728             : 
     729           2 : void SmSetSelectionVisitor::Visit( SmLineNode* pNode ) {
     730           2 :     VisitCompositionNode( pNode );
     731           2 : }
     732             : 
     733           0 : void SmSetSelectionVisitor::Visit( SmAlignNode* pNode ) {
     734           0 :     VisitCompositionNode( pNode );
     735           0 : }
     736             : 
     737          12 : void SmSetSelectionVisitor::Visit( SmBinHorNode* pNode ) {
     738          12 :     VisitCompositionNode( pNode );
     739          12 : }
     740             : 
     741           9 : void SmSetSelectionVisitor::Visit( SmUnHorNode* pNode ) {
     742           9 :     VisitCompositionNode( pNode );
     743           9 : }
     744             : 
     745           0 : void SmSetSelectionVisitor::Visit( SmFontNode* pNode ) {
     746           0 :     VisitCompositionNode( pNode );
     747           0 : }
     748             : 
     749             : // SmCaretPosGraphBuildingVisitor
     750             : 
     751          20 : SmCaretPosGraphBuildingVisitor::SmCaretPosGraphBuildingVisitor( SmNode* pRootNode )
     752             :     : mpRightMost(nullptr)
     753          20 :     , mpGraph(new SmCaretPosGraph)
     754             : {
     755             :     //pRootNode should always be a table
     756             :     SAL_WARN_IF( pRootNode->GetType( ) != NTABLE, "starmath", "pRootNode must be a table node");
     757             :     //Handle the special case where NTABLE is used a rootnode
     758          20 :     if( pRootNode->GetType( ) == NTABLE ){
     759             :         //Children are SmLineNodes
     760             :         //Or so I thought... Aparently, the children can be instances of SmExpression
     761             :         //especially if there's a error in the formula... So he we go, a simple work around.
     762          20 :         SmNodeIterator it( pRootNode );
     763          60 :         while( it.Next( ) ){
     764             :             //There's a special invariant between this method and the Visit( SmLineNode* )
     765             :             //Usually mpRightMost may not be NULL, to avoid this mpRightMost should here be
     766             :             //set to a new SmCaretPos in front of it.Current( ), however, if it.Current( ) is
     767             :             //an instance of SmLineNode we let SmLineNode create this position in front of
     768             :             //the visual line.
     769             :             //The argument for doing this is that we now don't have to worry about SmLineNode
     770             :             //being a visual line composition node. Thus, no need for yet another special case
     771             :             //in SmCursor::IsLineCompositionNode and everywhere this method is used.
     772             :             //if( it->GetType( ) != NLINE )
     773          20 :                 mpRightMost = mpGraph->Add( SmCaretPos( it.Current( ), 0 ) );
     774          20 :             it->Accept( this );
     775             :         }
     776             :     }else
     777           0 :         pRootNode->Accept(this);
     778          20 : }
     779             : 
     780          20 : SmCaretPosGraphBuildingVisitor::~SmCaretPosGraphBuildingVisitor()
     781             : {
     782          20 : }
     783             : 
     784           4 : void SmCaretPosGraphBuildingVisitor::Visit( SmLineNode* pNode ){
     785           4 :     SmNodeIterator it( pNode );
     786          12 :     while( it.Next( ) ){
     787           4 :         it->Accept( this );
     788             :     }
     789           4 : }
     790             : 
     791             : /** Build SmCaretPosGraph for SmTableNode
     792             :  * This method covers cases where SmTableNode is used in a binom or stack,
     793             :  * the special case where it is used as root node for the entire formula is
     794             :  * handled in the constructor.
     795             :  */
     796           3 : void SmCaretPosGraphBuildingVisitor::Visit( SmTableNode* pNode ){
     797           3 :     SmCaretPosGraphEntry *left  = mpRightMost,
     798           3 :                          *right = mpGraph->Add( SmCaretPos( pNode, 1) );
     799           3 :     bool bIsFirst = true;
     800           3 :     SmNodeIterator it( pNode );
     801          12 :     while( it.Next() ){
     802           6 :         mpRightMost = mpGraph->Add( SmCaretPos( it.Current(), 0 ), left);
     803           6 :         if(bIsFirst)
     804           3 :             left->SetRight(mpRightMost);
     805           6 :         it->Accept( this );
     806           6 :         mpRightMost->SetRight(right);
     807           6 :         if(bIsFirst)
     808           3 :             right->SetLeft(mpRightMost);
     809           6 :         bIsFirst = false;
     810             :     }
     811           3 :     mpRightMost = right;
     812           3 : }
     813             : 
     814             : /** Build SmCaretPosGraph for SmSubSupNode
     815             :  *
     816             :  * The child positions in a SubSupNode, where H is the body:
     817             :  * \code
     818             :  *      CSUP
     819             :  *
     820             :  * LSUP H  H RSUP
     821             :  *      H  H
     822             :  *      HHHH
     823             :  *      H  H
     824             :  * LSUB H  H RSUB
     825             :  *
     826             :  *      CSUB
     827             :  * \endcode
     828             :  *
     829             :  * Graph over these, where "left" is before the SmSubSupNode and "right" is after:
     830             :  * \dot
     831             :  *  digraph Graph{
     832             :  *      left -> H;
     833             :  *      H -> right;
     834             :  *      LSUP -> H;
     835             :  *      LSUB -> H;
     836             :  *      CSUP -> right;
     837             :  *      CSUB -> right;
     838             :  *      RSUP -> right;
     839             :  *      RSUB -> right;
     840             :  *  };
     841             :  * \enddot
     842             :  *
     843             :  */
     844           6 : void SmCaretPosGraphBuildingVisitor::Visit( SmSubSupNode* pNode )
     845             : {
     846             :     SmCaretPosGraphEntry *left,
     847             :                          *right,
     848             :                          *bodyLeft,
     849             :                          *bodyRight;
     850             : 
     851           6 :     left = mpRightMost;
     852             :     SAL_WARN_IF( !mpRightMost, "starmath", "mpRightMost shouldn't be NULL here!" );
     853             : 
     854             :     //Create bodyLeft
     855             :     SAL_WARN_IF( !pNode->GetBody(), "starmath", "SmSubSupNode Doesn't have a body!" );
     856           6 :     bodyLeft = mpGraph->Add( SmCaretPos( pNode->GetBody( ), 0 ), left );
     857           6 :     left->SetRight( bodyLeft ); //TODO: Don't make this if LSUP or LSUB are NULL ( not sure??? )
     858             : 
     859             :     //Create right
     860           6 :     right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
     861             : 
     862             :     //Visit the body, to get bodyRight
     863           6 :     mpRightMost = bodyLeft;
     864           6 :     pNode->GetBody( )->Accept( this );
     865           6 :     bodyRight = mpRightMost;
     866           6 :     bodyRight->SetRight( right );
     867           6 :     right->SetLeft( bodyRight );
     868             : 
     869             :     SmNode* pChild;
     870             :     //If there's an LSUP
     871           6 :     if( ( pChild = pNode->GetSubSup( LSUP ) ) ){
     872             :         SmCaretPosGraphEntry *cLeft; //Child left
     873           0 :         cLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
     874             : 
     875           0 :         mpRightMost = cLeft;
     876           0 :         pChild->Accept( this );
     877             : 
     878           0 :         mpRightMost->SetRight( bodyLeft );
     879             :     }
     880             :     //If there's an LSUB
     881           6 :     if( ( pChild = pNode->GetSubSup( LSUB ) ) ){
     882             :         SmCaretPosGraphEntry *cLeft; //Child left
     883           0 :         cLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
     884             : 
     885           0 :         mpRightMost = cLeft;
     886           0 :         pChild->Accept( this );
     887             : 
     888           0 :         mpRightMost->SetRight( bodyLeft );
     889             :     }
     890             :     //If there's an CSUP
     891           6 :     if( ( pChild = pNode->GetSubSup( CSUP ) ) ){
     892             :         SmCaretPosGraphEntry *cLeft; //Child left
     893           0 :         cLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
     894             : 
     895           0 :         mpRightMost = cLeft;
     896           0 :         pChild->Accept( this );
     897             : 
     898           0 :         mpRightMost->SetRight( right );
     899             :     }
     900             :     //If there's an CSUB
     901           6 :     if( ( pChild = pNode->GetSubSup( CSUB ) ) ){
     902             :         SmCaretPosGraphEntry *cLeft; //Child left
     903           0 :         cLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
     904             : 
     905           0 :         mpRightMost = cLeft;
     906           0 :         pChild->Accept( this );
     907             : 
     908           0 :         mpRightMost->SetRight( right );
     909             :     }
     910             :     //If there's an RSUP
     911           6 :     if( ( pChild = pNode->GetSubSup( RSUP ) ) ){
     912             :         SmCaretPosGraphEntry *cLeft; //Child left
     913           6 :         cLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), bodyRight );
     914             : 
     915           6 :         mpRightMost = cLeft;
     916           6 :         pChild->Accept( this );
     917             : 
     918           6 :         mpRightMost->SetRight( right );
     919             :     }
     920             :     //If there's an RSUB
     921           6 :     if( ( pChild = pNode->GetSubSup( RSUB ) ) ){
     922             :         SmCaretPosGraphEntry *cLeft; //Child left
     923           0 :         cLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), bodyRight );
     924             : 
     925           0 :         mpRightMost = cLeft;
     926           0 :         pChild->Accept( this );
     927             : 
     928           0 :         mpRightMost->SetRight( right );
     929             :     }
     930             : 
     931             :     //Set return parameters
     932           6 :     mpRightMost = right;
     933           6 : }
     934             : 
     935             : /** Build caret position for SmOperNode
     936             :  *
     937             :  * If first child is an SmSubSupNode we will ignore its
     938             :  * body, as this body is a SmMathSymbol, for SUM, INT or similar
     939             :  * that shouldn't be subject to modification.
     940             :  * If first child is not a SmSubSupNode, ignore it completely
     941             :  * as it is a SmMathSymbol.
     942             :  *
     943             :  * The child positions in a SmOperNode, where H is symbol, e.g. int, sum or similar:
     944             :  * \code
     945             :  *       TO
     946             :  *
     947             :  * LSUP H  H RSUP    BBB    BB  BBB  B   B
     948             :  *      H  H         B  B  B  B B  B  B B
     949             :  *      HHHH         BBB   B  B B  B   B
     950             :  *      H  H         B  B  B  B B  B   B
     951             :  * LSUB H  H RSUB    BBB    BB  BBB    B
     952             :  *
     953             :  *      FROM
     954             :  * \endcode
     955             :  * Notice, CSUP, etc. are actually granchildren, but inorder to ignore H, these are visited
     956             :  * from here. If they are present, that is if pOper is an instance of SmSubSupNode.
     957             :  *
     958             :  * Graph over these, where "left" is before the SmOperNode and "right" is after:
     959             :  * \dot
     960             :  *  digraph Graph{
     961             :  *      left -> BODY;
     962             :  *      BODY -> right;
     963             :  *      LSUP -> BODY;
     964             :  *      LSUB -> BODY;
     965             :  *      TO   -> BODY;
     966             :  *      FROM -> BODY;
     967             :  *      RSUP -> BODY;
     968             :  *      RSUB -> BODY;
     969             :  *  };
     970             :  * \enddot
     971             :  */
     972           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmOperNode* pNode )
     973             : {
     974           0 :     SmNode *pOper = pNode->GetSubNode( 0 ),
     975           0 :            *pBody = pNode->GetSubNode( 1 );
     976             : 
     977           0 :     SmCaretPosGraphEntry *left = mpRightMost,
     978             :                          *bodyLeft,
     979             :                          *bodyRight,
     980             :                          *right;
     981             :     //Create body left
     982           0 :     bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
     983           0 :     left->SetRight( bodyLeft );
     984             : 
     985             :     //Visit body, get bodyRight
     986           0 :     mpRightMost = bodyLeft;
     987           0 :     pBody->Accept( this );
     988           0 :     bodyRight = mpRightMost;
     989             : 
     990             :     //Create right
     991           0 :     right = mpGraph->Add( SmCaretPos( pNode, 1 ), bodyRight );
     992           0 :     bodyRight->SetRight( right );
     993             : 
     994             :     //Get subsup pNode if any
     995           0 :     SmSubSupNode* pSubSup = pOper->GetType( ) == NSUBSUP ? static_cast<SmSubSupNode*>(pOper) : NULL;
     996             : 
     997             :     SmNode* pChild;
     998             :     SmCaretPosGraphEntry *childLeft;
     999           0 :     if( pSubSup && ( pChild = pSubSup->GetSubSup( LSUP ) ) ) {
    1000             :         //Create position in front of pChild
    1001           0 :         childLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
    1002             :         //Visit pChild
    1003           0 :         mpRightMost = childLeft;
    1004           0 :         pChild->Accept( this );
    1005             :         //Set right on mpRightMost from pChild
    1006           0 :         mpRightMost->SetRight( bodyLeft );
    1007             :     }
    1008           0 :     if( pSubSup && ( pChild = pSubSup->GetSubSup( LSUB ) ) ) {
    1009             :         //Create position in front of pChild
    1010           0 :         childLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
    1011             :         //Visit pChild
    1012           0 :         mpRightMost = childLeft;
    1013           0 :         pChild->Accept( this );
    1014             :         //Set right on mpRightMost from pChild
    1015           0 :         mpRightMost->SetRight( bodyLeft );
    1016             :     }
    1017           0 :     if( pSubSup && ( pChild = pSubSup->GetSubSup( CSUP ) ) ) {//TO
    1018             :         //Create position in front of pChild
    1019           0 :         childLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
    1020             :         //Visit pChild
    1021           0 :         mpRightMost = childLeft;
    1022           0 :         pChild->Accept( this );
    1023             :         //Set right on mpRightMost from pChild
    1024           0 :         mpRightMost->SetRight( bodyLeft );
    1025             :     }
    1026           0 :     if( pSubSup && ( pChild = pSubSup->GetSubSup( CSUB ) ) ) { //FROM
    1027             :         //Create position in front of pChild
    1028           0 :         childLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
    1029             :         //Visit pChild
    1030           0 :         mpRightMost = childLeft;
    1031           0 :         pChild->Accept( this );
    1032             :         //Set right on mpRightMost from pChild
    1033           0 :         mpRightMost->SetRight( bodyLeft );
    1034             :     }
    1035           0 :     if( pSubSup && ( pChild = pSubSup->GetSubSup( RSUP ) ) ) {
    1036             :         //Create position in front of pChild
    1037           0 :         childLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
    1038             :         //Visit pChild
    1039           0 :         mpRightMost = childLeft;
    1040           0 :         pChild->Accept( this );
    1041             :         //Set right on mpRightMost from pChild
    1042           0 :         mpRightMost->SetRight( bodyLeft );
    1043             :     }
    1044           0 :     if( pSubSup && ( pChild = pSubSup->GetSubSup( RSUB ) ) ) {
    1045             :         //Create position in front of pChild
    1046           0 :         childLeft = mpGraph->Add( SmCaretPos( pChild, 0 ), left );
    1047             :         //Visit pChild
    1048           0 :         mpRightMost = childLeft;
    1049           0 :         pChild->Accept( this );
    1050             :         //Set right on mpRightMost from pChild
    1051           0 :         mpRightMost->SetRight( bodyLeft );
    1052             :     }
    1053             : 
    1054             :     //Return right
    1055           0 :     mpRightMost = right;
    1056           0 : }
    1057             : 
    1058           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmMatrixNode* pNode )
    1059             : {
    1060           0 :     SmCaretPosGraphEntry *left  = mpRightMost,
    1061           0 :                          *right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
    1062             : 
    1063           0 :     for ( sal_uInt16 i = 0;  i < pNode->GetNumRows( ); i++ ) {
    1064           0 :         SmCaretPosGraphEntry* r = left;
    1065           0 :         for ( sal_uInt16 j = 0;  j < pNode->GetNumCols( ); j++ ){
    1066           0 :             SmNode* pSubNode = pNode->GetSubNode( i * pNode->GetNumCols( ) + j );
    1067             : 
    1068           0 :             mpRightMost = mpGraph->Add( SmCaretPos( pSubNode, 0 ), r );
    1069           0 :             if( j != 0 || ( pNode->GetNumRows( ) - 1 ) / 2 == i )
    1070           0 :                 r->SetRight( mpRightMost );
    1071             : 
    1072           0 :             pSubNode->Accept( this );
    1073             : 
    1074           0 :             r = mpRightMost;
    1075             :         }
    1076           0 :         mpRightMost->SetRight( right );
    1077           0 :         if( ( pNode->GetNumRows( ) - 1 ) / 2 == i )
    1078           0 :             right->SetLeft( mpRightMost );
    1079             :     }
    1080             : 
    1081           0 :     mpRightMost = right;
    1082           0 : }
    1083             : 
    1084             : /** Build SmCaretPosGraph for SmTextNode
    1085             :  *
    1086             :  * Lines in an SmTextNode:
    1087             :  * \code
    1088             :  * A B C
    1089             :  * \endcode
    1090             :  * Where A B and C are characters in the text.
    1091             :  *
    1092             :  * Graph over these, where "left" is before the SmTextNode and "right" is after:
    1093             :  * \dot
    1094             :  *  digraph Graph{
    1095             :  *      left -> A;
    1096             :  *      A -> B
    1097             :  *      B -> right;
    1098             :  *  };
    1099             :  * \enddot
    1100             :  * Notice that C and right is the same position here.
    1101             :  */
    1102          44 : void SmCaretPosGraphBuildingVisitor::Visit( SmTextNode* pNode )
    1103             : {
    1104             :     SAL_WARN_IF( pNode->GetText().isEmpty(), "starmath", "Empty SmTextNode is bad" );
    1105             : 
    1106          44 :     int size = pNode->GetText().getLength();
    1107          88 :     for( int i = 1; i <= size; i++ ){
    1108          44 :         SmCaretPosGraphEntry* pRight = mpRightMost;
    1109          44 :         mpRightMost = mpGraph->Add( SmCaretPos( pNode, i ), pRight );
    1110          44 :         pRight->SetRight( mpRightMost );
    1111             :     }
    1112          44 : }
    1113             : 
    1114             : /** Build SmCaretPosGraph for SmBinVerNode
    1115             :  *
    1116             :  * Lines in an SmBinVerNode:
    1117             :  * \code
    1118             :  *    A
    1119             :  *  -----
    1120             :  *    B
    1121             :  * \endcode
    1122             :  *
    1123             :  * Graph over these, where "left" is before the SmBinVerNode and "right" is after:
    1124             :  * \dot
    1125             :  *  digraph Graph{
    1126             :  *      left -> A;
    1127             :  *      A -> right;
    1128             :  *      B -> right;
    1129             :  *  };
    1130             :  * \enddot
    1131             :  */
    1132           7 : void SmCaretPosGraphBuildingVisitor::Visit( SmBinVerNode* pNode )
    1133             : {
    1134             :     //None if these children can be NULL, see SmBinVerNode::Arrange
    1135           7 :     SmNode  *pNum   = pNode->GetSubNode( 0 ),
    1136           7 :             *pDenom = pNode->GetSubNode( 2 );
    1137             : 
    1138             :     SmCaretPosGraphEntry *left,
    1139             :                          *right,
    1140             :                          *numLeft,
    1141             :                          *denomLeft;
    1142             : 
    1143             :     //Set left
    1144           7 :     left = mpRightMost;
    1145             :     SAL_WARN_IF( !mpRightMost, "starmath", "There must be a position in front of this" );
    1146             : 
    1147             :     //Create right
    1148           7 :     right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
    1149             : 
    1150             :     //Create numLeft
    1151           7 :     numLeft = mpGraph->Add( SmCaretPos( pNum, 0 ), left );
    1152           7 :     left->SetRight( numLeft );
    1153             : 
    1154             :     //Visit pNum
    1155           7 :     mpRightMost = numLeft;
    1156           7 :     pNum->Accept( this );
    1157           7 :     mpRightMost->SetRight( right );
    1158           7 :     right->SetLeft( mpRightMost );
    1159             : 
    1160             :     //Create denomLeft
    1161           7 :     denomLeft = mpGraph->Add( SmCaretPos( pDenom, 0 ), left );
    1162             : 
    1163             :     //Visit pDenom
    1164           7 :     mpRightMost = denomLeft;
    1165           7 :     pDenom->Accept( this );
    1166           7 :     mpRightMost->SetRight( right );
    1167             : 
    1168             :     //Set return parameter
    1169           7 :     mpRightMost = right;
    1170           7 : }
    1171             : 
    1172             : /** Build SmCaretPosGraph for SmVerticalBraceNode
    1173             :  *
    1174             :  * Lines in an SmVerticalBraceNode:
    1175             :  * \code
    1176             :  *   pScript
    1177             :  *  ________
    1178             :  * /        \
    1179             :  *   pBody
    1180             :  * \endcode
    1181             :  *
    1182             :  */
    1183           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmVerticalBraceNode* pNode )
    1184             : {
    1185           0 :     SmNode  *pBody   = pNode->GetSubNode( 0 ),
    1186           0 :             *pScript = pNode->GetSubNode( 2 );
    1187             :     //None of these children can be NULL
    1188             : 
    1189             :     SmCaretPosGraphEntry  *left,
    1190             :                         *bodyLeft,
    1191             :                         *scriptLeft,
    1192             :                         *right;
    1193             : 
    1194           0 :     left = mpRightMost;
    1195             : 
    1196             :     //Create right
    1197           0 :     right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
    1198             : 
    1199             :     //Create bodyLeft
    1200           0 :     bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
    1201           0 :     left->SetRight( bodyLeft );
    1202           0 :     mpRightMost = bodyLeft;
    1203           0 :     pBody->Accept( this );
    1204           0 :     mpRightMost->SetRight( right );
    1205           0 :     right->SetLeft( mpRightMost );
    1206             : 
    1207             :     //Create script
    1208           0 :     scriptLeft = mpGraph->Add( SmCaretPos( pScript, 0 ), left );
    1209           0 :     mpRightMost = scriptLeft;
    1210           0 :     pScript->Accept( this );
    1211           0 :     mpRightMost->SetRight( right );
    1212             : 
    1213             :     //Set return value
    1214           0 :     mpRightMost = right;
    1215           0 : }
    1216             : 
    1217             : /** Build SmCaretPosGraph for SmBinDiagonalNode
    1218             :  *
    1219             :  * Lines in an SmBinDiagonalNode:
    1220             :  * \code
    1221             :  *  A /
    1222             :  *   /
    1223             :  *  / B
    1224             :  * \endcode
    1225             :  * Where A and B are lines.
    1226             :  *
    1227             :  * Used in formulas such as "A wideslash B"
    1228             :  */
    1229           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmBinDiagonalNode* pNode )
    1230             : {
    1231           0 :     SmNode  *A = pNode->GetSubNode( 0 ),
    1232           0 :             *B = pNode->GetSubNode( 1 );
    1233             : 
    1234             :     SmCaretPosGraphEntry  *left,
    1235             :                         *leftA,
    1236             :                         *rightA,
    1237             :                         *leftB,
    1238             :                         *right;
    1239           0 :     left = mpRightMost;
    1240             : 
    1241             :     //Create right
    1242           0 :     right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
    1243             : 
    1244             :     //Create left A
    1245           0 :     leftA = mpGraph->Add( SmCaretPos( A, 0 ), left );
    1246           0 :     left->SetRight( leftA );
    1247             : 
    1248             :     //Visit A
    1249           0 :     mpRightMost = leftA;
    1250           0 :     A->Accept( this );
    1251           0 :     rightA = mpRightMost;
    1252             : 
    1253             :     //Create left B
    1254           0 :     leftB = mpGraph->Add( SmCaretPos( B, 0 ), rightA );
    1255           0 :     rightA->SetRight( leftB );
    1256             : 
    1257             :     //Visit B
    1258           0 :     mpRightMost = leftB;
    1259           0 :     B->Accept( this );
    1260           0 :     mpRightMost->SetRight( right );
    1261           0 :     right->SetLeft( mpRightMost );
    1262             : 
    1263             :     //Set return value
    1264           0 :     mpRightMost = right;
    1265           0 : }
    1266             : 
    1267             : //Straigt forward ( I think )
    1268          13 : void SmCaretPosGraphBuildingVisitor::Visit( SmBinHorNode* pNode )
    1269             : {
    1270          13 :     SmNodeIterator it( pNode );
    1271          65 :     while( it.Next( ) )
    1272          39 :         it->Accept( this );
    1273          13 : }
    1274           9 : void SmCaretPosGraphBuildingVisitor::Visit( SmUnHorNode* pNode )
    1275             : {
    1276             :     // Unary operator node
    1277           9 :     SmNodeIterator it( pNode );
    1278          36 :     while( it.Next( ) )
    1279          18 :         it->Accept( this );
    1280             : 
    1281           9 : }
    1282             : 
    1283          35 : void SmCaretPosGraphBuildingVisitor::Visit( SmExpressionNode* pNode )
    1284             : {
    1285          35 :     SmNodeIterator it( pNode );
    1286         106 :     while( it.Next( ) )
    1287          36 :         it->Accept( this );
    1288          35 : }
    1289             : 
    1290           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmFontNode* pNode )
    1291             : {
    1292             :     //Has only got one child, should act as an expression if possible
    1293           0 :     SmNodeIterator it( pNode );
    1294           0 :     while( it.Next( ) )
    1295           0 :         it->Accept( this );
    1296           0 : }
    1297             : 
    1298             : /** Build SmCaretPosGraph for SmBracebodyNode
    1299             :  * Acts as an SmExpressionNode
    1300             :  *
    1301             :  * Below is an example of a formula tree that has multiple children for SmBracebodyNode
    1302             :  * \dot
    1303             :  * digraph {
    1304             :  * labelloc = "t";
    1305             :  * label= "Equation: \"lbrace i mline i in setZ rbrace\"";
    1306             :  * n0 [label="SmTableNode"];
    1307             :  * n0 -> n1 [label="0"];
    1308             :  * n1 [label="SmLineNode"];
    1309             :  * n1 -> n2 [label="0"];
    1310             :  * n2 [label="SmExpressionNode"];
    1311             :  * n2 -> n3 [label="0"];
    1312             :  * n3 [label="SmBraceNode"];
    1313             :  * n3 -> n4 [label="0"];
    1314             :  * n4 [label="SmMathSymbolNode: {"];
    1315             :  * n3 -> n5 [label="1"];
    1316             :  * n5 [label="SmBracebodyNode"];
    1317             :  * n5 -> n6 [label="0"];
    1318             :  * n6 [label="SmExpressionNode"];
    1319             :  * n6 -> n7 [label="0"];
    1320             :  * n7 [label="SmTextNode: i"];
    1321             :  * n5 -> n8 [label="1"];
    1322             :  * n8 [label="SmMathSymbolNode: ∣"];
    1323             :  * n5 -> n9 [label="2"];
    1324             :  * n9 [label="SmExpressionNode"];
    1325             :  * n9 -> n10 [label="0"];
    1326             :  * n10 [label="SmBinHorNode"];
    1327             :  * n10 -> n11 [label="0"];
    1328             :  * n11 [label="SmTextNode: i"];
    1329             :  * n10 -> n12 [label="1"];
    1330             :  * n12 [label="SmMathSymbolNode: ∈"];
    1331             :  * n10 -> n13 [label="2"];
    1332             :  * n13 [label="SmMathSymbolNode: ℤ"];
    1333             :  * n3 -> n14 [label="2"];
    1334             :  * n14 [label="SmMathSymbolNode: }"];
    1335             :  * }
    1336             :  * \enddot
    1337             :  */
    1338           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmBracebodyNode* pNode )
    1339             : {
    1340           0 :     SmNodeIterator it( pNode );
    1341           0 :     while( it.Next( ) ) {
    1342           0 :         SmCaretPosGraphEntry* pStart = mpGraph->Add( SmCaretPos( it.Current(), 0), mpRightMost );
    1343           0 :         mpRightMost->SetRight( pStart );
    1344           0 :         mpRightMost = pStart;
    1345           0 :         it->Accept( this );
    1346             :     }
    1347           0 : }
    1348             : 
    1349             : /** Build SmCaretPosGraph for SmAlignNode
    1350             :  * Acts as an SmExpressionNode, as it only has one child this okay
    1351             :  */
    1352           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmAlignNode* pNode )
    1353             : {
    1354           0 :     SmNodeIterator it( pNode );
    1355           0 :     while( it.Next( ) )
    1356           0 :         it->Accept( this );
    1357           0 : }
    1358             : 
    1359             : /** Build SmCaretPosGraph for SmRootNode
    1360             :  *
    1361             :  * Lines in an SmRootNode:
    1362             :  * \code
    1363             :  *    _________
    1364             :  *  A/
    1365             :  * \/    B
    1366             :  *
    1367             :  * \endcode
    1368             :  * A: pExtra ( optional, can be NULL ),
    1369             :  * B: pBody
    1370             :  *
    1371             :  * Graph over these, where "left" is before the SmRootNode and "right" is after:
    1372             :  * \dot
    1373             :  *  digraph Graph{
    1374             :  *      left -> B;
    1375             :  *      B -> right;
    1376             :  *      A -> B;
    1377             :  *  }
    1378             :  * \enddot
    1379             :  */
    1380           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmRootNode* pNode )
    1381             : {
    1382           0 :     SmNode  *pExtra = pNode->GetSubNode( 0 ), //Argument, NULL for sqrt, and SmTextNode if cubicroot
    1383           0 :             *pBody  = pNode->GetSubNode( 2 ); //Body of the root
    1384             :     SAL_WARN_IF( !pBody, "starmath", "pBody cannot be NULL" );
    1385             : 
    1386             :     SmCaretPosGraphEntry  *left,
    1387             :                         *right,
    1388             :                         *bodyLeft,
    1389             :                         *bodyRight;
    1390             : 
    1391             :     //Get left and save it
    1392             :     SAL_WARN_IF( !mpRightMost, "starmath", "There must be a position in front of this" );
    1393           0 :     left = mpRightMost;
    1394             : 
    1395             :     //Create body left
    1396           0 :     bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
    1397           0 :     left->SetRight( bodyLeft );
    1398             : 
    1399             :     //Create right
    1400           0 :     right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
    1401             : 
    1402             :     //Visit body
    1403           0 :     mpRightMost = bodyLeft;
    1404           0 :     pBody->Accept( this );
    1405           0 :     bodyRight = mpRightMost;
    1406           0 :     bodyRight->SetRight( right );
    1407           0 :     right->SetLeft( bodyRight );
    1408             : 
    1409             :     //Visit pExtra
    1410           0 :     if( pExtra ){
    1411           0 :         mpRightMost = mpGraph->Add( SmCaretPos( pExtra, 0 ), left );
    1412           0 :         pExtra->Accept( this );
    1413           0 :         mpRightMost->SetRight( bodyLeft );
    1414             :     }
    1415             : 
    1416           0 :     mpRightMost = right;
    1417           0 : }
    1418             : 
    1419             : 
    1420           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmDynIntegralNode* pNode )
    1421             : {
    1422             :     //! To be changed: Integrals don't have args.
    1423           0 :     SmNode  *pBody  = pNode->Body(); //Body of the root
    1424             :     SAL_WARN_IF( !pBody, "starmath", "pBody cannot be NULL" );
    1425             : 
    1426             :     SmCaretPosGraphEntry  *left,
    1427             :                         *right,
    1428             :                         *bodyLeft,
    1429             :                         *bodyRight;
    1430             : 
    1431             :     //Get left and save it
    1432             :     SAL_WARN_IF( !mpRightMost, "starmath", "There must be a position in front of this" );
    1433           0 :     left = mpRightMost;
    1434             : 
    1435             :     //Create body left
    1436           0 :     bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
    1437           0 :     left->SetRight( bodyLeft );
    1438             : 
    1439             :     //Create right
    1440           0 :     right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
    1441             : 
    1442             :     //Visit body
    1443           0 :     mpRightMost = bodyLeft;
    1444           0 :     pBody->Accept( this );
    1445           0 :     bodyRight = mpRightMost;
    1446           0 :     bodyRight->SetRight( right );
    1447           0 :     right->SetLeft( bodyRight );
    1448             : 
    1449           0 :     mpRightMost = right;
    1450           0 : }
    1451             : 
    1452             : 
    1453             : /** Build SmCaretPosGraph for SmPlaceNode
    1454             :  * Consider this a single character.
    1455             :  */
    1456           2 : void SmCaretPosGraphBuildingVisitor::Visit( SmPlaceNode* pNode )
    1457             : {
    1458           2 :     SmCaretPosGraphEntry* right = mpGraph->Add( SmCaretPos( pNode, 1 ), mpRightMost );
    1459           2 :     mpRightMost->SetRight( right );
    1460           2 :     mpRightMost = right;
    1461           2 : }
    1462             : 
    1463             : /** SmErrorNode is context dependent metadata, it can't be selected
    1464             :  *
    1465             :  * @remarks There's no point in deleting, copying and/or moving an instance
    1466             :  * of SmErrorNode as it may not exist in an other context! Thus there are no
    1467             :  * positions to select an SmErrorNode.
    1468             :  */
    1469           4 : void SmCaretPosGraphBuildingVisitor::Visit( SmErrorNode* )
    1470             : {
    1471           4 : }
    1472             : 
    1473             : /** Build SmCaretPosGraph for SmBlankNode
    1474             :  * Consider this a single character, as it is only a blank space
    1475             :  */
    1476           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmBlankNode* pNode )
    1477             : {
    1478           0 :     SmCaretPosGraphEntry* right = mpGraph->Add( SmCaretPos( pNode, 1 ), mpRightMost );
    1479           0 :     mpRightMost->SetRight( right );
    1480           0 :     mpRightMost = right;
    1481           0 : }
    1482             : 
    1483             : /** Build SmCaretPosGraph for SmBraceNode
    1484             :  *
    1485             :  * Lines in an SmBraceNode:
    1486             :  * \code
    1487             :  * |     |
    1488             :  * |  B  |
    1489             :  * |     |
    1490             :  * \endcode
    1491             :  * B: Body
    1492             :  *
    1493             :  * Graph over these, where "left" is before the SmBraceNode and "right" is after:
    1494             :  * \dot
    1495             :  *  digraph Graph{
    1496             :  *      left -> B;
    1497             :  *      B -> right;
    1498             :  *  }
    1499             :  * \enddot
    1500             :  */
    1501           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmBraceNode* pNode )
    1502             : {
    1503           0 :     SmNode* pBody = pNode->GetSubNode( 1 );
    1504             : 
    1505           0 :     SmCaretPosGraphEntry  *left = mpRightMost,
    1506           0 :                         *right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
    1507             : 
    1508           0 :     if( pBody->GetType() != NBRACEBODY ) {
    1509           0 :         mpRightMost = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
    1510           0 :         left->SetRight( mpRightMost );
    1511             :     }else
    1512           0 :         mpRightMost = left;
    1513             : 
    1514           0 :     pBody->Accept( this );
    1515           0 :     mpRightMost->SetRight( right );
    1516           0 :     right->SetLeft( mpRightMost );
    1517             : 
    1518           0 :     mpRightMost = right;
    1519           0 : }
    1520             : 
    1521             : /** Build SmCaretPosGraph for SmAttributNode
    1522             :  *
    1523             :  * Lines in an SmAttributNode:
    1524             :  * \code
    1525             :  *   Attr
    1526             :  *   Body
    1527             :  * \endcode
    1528             :  *
    1529             :  * There's a body and an attribute, the construction is used for "widehat A", where "A" is the body
    1530             :  * and "^" is the attribute ( note GetScaleMode( ) on SmAttributNode tells how the attribute should be
    1531             :  * scaled ).
    1532             :  */
    1533           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmAttributNode* pNode )
    1534             : {
    1535           0 :     SmNode  *pAttr = pNode->GetSubNode( 0 ),
    1536           0 :             *pBody = pNode->GetSubNode( 1 );
    1537             :     //None of the children can be NULL
    1538             : 
    1539           0 :     SmCaretPosGraphEntry  *left = mpRightMost,
    1540             :                         *attrLeft,
    1541             :                         *bodyLeft,
    1542             :                         *bodyRight,
    1543             :                         *right;
    1544             : 
    1545             :     //Creating bodyleft
    1546           0 :     bodyLeft = mpGraph->Add( SmCaretPos( pBody, 0 ), left );
    1547           0 :     left->SetRight( bodyLeft );
    1548             : 
    1549             :     //Creating right
    1550           0 :     right = mpGraph->Add( SmCaretPos( pNode, 1 ) );
    1551             : 
    1552             :     //Visit the body
    1553           0 :     mpRightMost = bodyLeft;
    1554           0 :     pBody->Accept( this );
    1555           0 :     bodyRight = mpRightMost;
    1556           0 :     bodyRight->SetRight( right );
    1557           0 :     right->SetLeft( bodyRight );
    1558             : 
    1559             :     //Create attrLeft
    1560           0 :     attrLeft = mpGraph->Add( SmCaretPos( pAttr, 0 ), left );
    1561             : 
    1562             :     //Visit attribute
    1563           0 :     mpRightMost = attrLeft;
    1564           0 :     pAttr->Accept( this );
    1565           0 :     mpRightMost->SetRight( right );
    1566             : 
    1567             :     //Set return value
    1568           0 :     mpRightMost = right;
    1569           0 : }
    1570             : 
    1571             : //Consider these single symboles
    1572           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmSpecialNode* pNode )
    1573             : {
    1574           0 :     SmCaretPosGraphEntry* right = mpGraph->Add( SmCaretPos( pNode, 1 ), mpRightMost );
    1575           0 :     mpRightMost->SetRight( right );
    1576           0 :     mpRightMost = right;
    1577           0 : }
    1578           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmGlyphSpecialNode* pNode )
    1579             : {
    1580           0 :     SmCaretPosGraphEntry* right = mpGraph->Add( SmCaretPos( pNode, 1 ), mpRightMost );
    1581           0 :     mpRightMost->SetRight( right );
    1582           0 :     mpRightMost = right;
    1583           0 : }
    1584          22 : void SmCaretPosGraphBuildingVisitor::Visit( SmMathSymbolNode* pNode )
    1585             : {
    1586          22 :     SmCaretPosGraphEntry* right = mpGraph->Add( SmCaretPos( pNode, 1 ), mpRightMost );
    1587          22 :     mpRightMost->SetRight( right );
    1588          22 :     mpRightMost = right;
    1589          22 : }
    1590             : 
    1591           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmRootSymbolNode* )
    1592             : {
    1593             :     //Do nothing
    1594           0 : }
    1595             : 
    1596           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmDynIntegralSymbolNode* )
    1597             : {
    1598             :     //Do nothing
    1599           0 : }
    1600             : 
    1601             : 
    1602           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmRectangleNode* )
    1603             : {
    1604             :     //Do nothing
    1605           0 : }
    1606           0 : void SmCaretPosGraphBuildingVisitor::Visit( SmPolyLineNode* )
    1607             : {
    1608             :     //Do nothing
    1609           0 : }
    1610             : 
    1611             : // SmCloningVisitor
    1612             : 
    1613           0 : SmNode* SmCloningVisitor::Clone( SmNode* pNode )
    1614             : {
    1615           0 :     SmNode* pCurrResult = pResult;
    1616           0 :     pNode->Accept( this );
    1617           0 :     SmNode* pClone = pResult;
    1618           0 :     pResult = pCurrResult;
    1619           0 :     return pClone;
    1620             : }
    1621             : 
    1622           0 : void SmCloningVisitor::CloneNodeAttr( SmNode* pSource, SmNode* pTarget )
    1623             : {
    1624           0 :     pTarget->SetScaleMode( pSource->GetScaleMode( ) );
    1625             :     //Other attributes are set when prepare or arrange is executed
    1626             :     //and may depend on stuff not being cloned here.
    1627           0 : }
    1628             : 
    1629           0 : void SmCloningVisitor::CloneKids( SmStructureNode* pSource, SmStructureNode* pTarget )
    1630             : {
    1631             :     //Cache current result
    1632           0 :     SmNode* pCurrResult = pResult;
    1633             : 
    1634             :     //Create array for holding clones
    1635           0 :     sal_uInt16 nSize = pSource->GetNumSubNodes( );
    1636           0 :     SmNodeArray aNodes( nSize );
    1637             : 
    1638             :     //Clone children
    1639           0 :     for( sal_uInt16 i = 0; i < nSize; i++ ){
    1640             :         SmNode* pKid;
    1641           0 :         if( NULL != ( pKid = pSource->GetSubNode( i ) ) )
    1642           0 :             pKid->Accept( this );
    1643             :         else
    1644           0 :             pResult = NULL;
    1645           0 :         aNodes[i] = pResult;
    1646             :     }
    1647             : 
    1648             :     //Set subnodes of pTarget
    1649           0 :     pTarget->SetSubNodes( aNodes );
    1650             : 
    1651             :     //Restore result as where prior to call
    1652           0 :     pResult = pCurrResult;
    1653           0 : }
    1654             : 
    1655           0 : void SmCloningVisitor::Visit( SmTableNode* pNode )
    1656             : {
    1657           0 :     SmTableNode* pClone = new SmTableNode( pNode->GetToken( ) );
    1658           0 :     CloneNodeAttr( pNode, pClone );
    1659           0 :     CloneKids( pNode, pClone );
    1660           0 :     pResult = pClone;
    1661           0 : }
    1662             : 
    1663           0 : void SmCloningVisitor::Visit( SmBraceNode* pNode )
    1664             : {
    1665           0 :     SmBraceNode* pClone = new SmBraceNode( pNode->GetToken( ) );
    1666           0 :     CloneNodeAttr( pNode, pClone );
    1667           0 :     CloneKids( pNode, pClone );
    1668           0 :     pResult = pClone;
    1669           0 : }
    1670             : 
    1671           0 : void SmCloningVisitor::Visit( SmBracebodyNode* pNode )
    1672             : {
    1673           0 :     SmBracebodyNode* pClone = new SmBracebodyNode( pNode->GetToken( ) );
    1674           0 :     CloneNodeAttr( pNode, pClone );
    1675           0 :     CloneKids( pNode, pClone );
    1676           0 :     pResult = pClone;
    1677           0 : }
    1678             : 
    1679           0 : void SmCloningVisitor::Visit( SmOperNode* pNode )
    1680             : {
    1681           0 :     SmOperNode* pClone = new SmOperNode( pNode->GetToken( ) );
    1682           0 :     CloneNodeAttr( pNode, pClone );
    1683           0 :     CloneKids( pNode, pClone );
    1684           0 :     pResult = pClone;
    1685           0 : }
    1686             : 
    1687           0 : void SmCloningVisitor::Visit( SmAlignNode* pNode )
    1688             : {
    1689           0 :     SmAlignNode* pClone = new SmAlignNode( pNode->GetToken( ) );
    1690           0 :     CloneNodeAttr( pNode, pClone );
    1691           0 :     CloneKids( pNode, pClone );
    1692           0 :     pResult = pClone;
    1693           0 : }
    1694             : 
    1695           0 : void SmCloningVisitor::Visit( SmAttributNode* pNode )
    1696             : {
    1697           0 :     SmAttributNode* pClone = new SmAttributNode( pNode->GetToken( ) );
    1698           0 :     CloneNodeAttr( pNode, pClone );
    1699           0 :     CloneKids( pNode, pClone );
    1700           0 :     pResult = pClone;
    1701           0 : }
    1702             : 
    1703           0 : void SmCloningVisitor::Visit( SmFontNode* pNode )
    1704             : {
    1705           0 :     SmFontNode* pClone = new SmFontNode( pNode->GetToken( ) );
    1706           0 :     pClone->SetSizeParameter( pNode->GetSizeParameter( ), pNode->GetSizeType( ) );
    1707           0 :     CloneNodeAttr( pNode, pClone );
    1708           0 :     CloneKids( pNode, pClone );
    1709           0 :     pResult = pClone;
    1710           0 : }
    1711             : 
    1712           0 : void SmCloningVisitor::Visit( SmUnHorNode* pNode )
    1713             : {
    1714           0 :     SmUnHorNode* pClone = new SmUnHorNode( pNode->GetToken( ) );
    1715           0 :     CloneNodeAttr( pNode, pClone );
    1716           0 :     CloneKids( pNode, pClone );
    1717           0 :     pResult = pClone;
    1718           0 : }
    1719             : 
    1720           0 : void SmCloningVisitor::Visit( SmBinHorNode* pNode )
    1721             : {
    1722           0 :     SmBinHorNode* pClone = new SmBinHorNode( pNode->GetToken( ) );
    1723           0 :     CloneNodeAttr( pNode, pClone );
    1724           0 :     CloneKids( pNode, pClone );
    1725           0 :     pResult = pClone;
    1726           0 : }
    1727             : 
    1728           0 : void SmCloningVisitor::Visit( SmBinVerNode* pNode )
    1729             : {
    1730           0 :     SmBinVerNode* pClone = new SmBinVerNode( pNode->GetToken( ) );
    1731           0 :     CloneNodeAttr( pNode, pClone );
    1732           0 :     CloneKids( pNode, pClone );
    1733           0 :     pResult = pClone;
    1734           0 : }
    1735             : 
    1736           0 : void SmCloningVisitor::Visit( SmBinDiagonalNode* pNode )
    1737             : {
    1738           0 :     SmBinDiagonalNode *pClone = new SmBinDiagonalNode( pNode->GetToken( ) );
    1739           0 :     pClone->SetAscending( pNode->IsAscending( ) );
    1740           0 :     CloneNodeAttr( pNode, pClone );
    1741           0 :     CloneKids( pNode, pClone );
    1742           0 :     pResult = pClone;
    1743           0 : }
    1744             : 
    1745           0 : void SmCloningVisitor::Visit( SmSubSupNode* pNode )
    1746             : {
    1747           0 :     SmSubSupNode *pClone = new SmSubSupNode( pNode->GetToken( ) );
    1748           0 :     pClone->SetUseLimits( pNode->IsUseLimits( ) );
    1749           0 :     CloneNodeAttr( pNode, pClone );
    1750           0 :     CloneKids( pNode, pClone );
    1751           0 :     pResult = pClone;
    1752           0 : }
    1753             : 
    1754           0 : void SmCloningVisitor::Visit( SmMatrixNode* pNode )
    1755             : {
    1756           0 :     SmMatrixNode *pClone = new SmMatrixNode( pNode->GetToken( ) );
    1757           0 :     pClone->SetRowCol( pNode->GetNumRows( ), pNode->GetNumCols( ) );
    1758           0 :     CloneNodeAttr( pNode, pClone );
    1759           0 :     CloneKids( pNode, pClone );
    1760           0 :     pResult = pClone;
    1761           0 : }
    1762             : 
    1763           0 : void SmCloningVisitor::Visit( SmPlaceNode* pNode )
    1764             : {
    1765           0 :     pResult = new SmPlaceNode( pNode->GetToken( ) );
    1766           0 :     CloneNodeAttr( pNode, pResult );
    1767           0 : }
    1768             : 
    1769           0 : void SmCloningVisitor::Visit( SmTextNode* pNode )
    1770             : {
    1771           0 :     SmTextNode* pClone = new SmTextNode( pNode->GetToken( ), pNode->GetFontDesc( ) );
    1772           0 :     pClone->ChangeText( pNode->GetText( ) );
    1773           0 :     CloneNodeAttr( pNode, pClone );
    1774           0 :     pResult = pClone;
    1775           0 : }
    1776             : 
    1777           0 : void SmCloningVisitor::Visit( SmSpecialNode* pNode )
    1778             : {
    1779           0 :     pResult = new SmSpecialNode( pNode->GetToken( ) );
    1780           0 :     CloneNodeAttr( pNode, pResult );
    1781           0 : }
    1782             : 
    1783           0 : void SmCloningVisitor::Visit( SmGlyphSpecialNode* pNode )
    1784             : {
    1785           0 :     pResult = new SmGlyphSpecialNode( pNode->GetToken( ) );
    1786           0 :     CloneNodeAttr( pNode, pResult );
    1787           0 : }
    1788             : 
    1789           0 : void SmCloningVisitor::Visit( SmMathSymbolNode* pNode )
    1790             : {
    1791           0 :     pResult = new SmMathSymbolNode( pNode->GetToken( ) );
    1792           0 :     CloneNodeAttr( pNode, pResult );
    1793           0 : }
    1794             : 
    1795           0 : void SmCloningVisitor::Visit( SmBlankNode* pNode )
    1796             : {
    1797           0 :     SmBlankNode* pClone = new SmBlankNode( pNode->GetToken( ) );
    1798           0 :     pClone->SetBlankNum( pNode->GetBlankNum( ) );
    1799           0 :     pResult = pClone;
    1800           0 :     CloneNodeAttr( pNode, pResult );
    1801           0 : }
    1802             : 
    1803           0 : void SmCloningVisitor::Visit( SmErrorNode* pNode )
    1804             : {
    1805             :     //PE_NONE is used the information have been discarded and isn't used
    1806           0 :     pResult = new SmErrorNode( PE_NONE, pNode->GetToken( ) );
    1807           0 :     CloneNodeAttr( pNode, pResult );
    1808           0 : }
    1809             : 
    1810           0 : void SmCloningVisitor::Visit( SmLineNode* pNode )
    1811             : {
    1812           0 :     SmLineNode* pClone = new SmLineNode( pNode->GetToken( ) );
    1813           0 :     CloneNodeAttr( pNode, pClone );
    1814           0 :     CloneKids( pNode, pClone );
    1815           0 :     pResult = pClone;
    1816           0 : }
    1817             : 
    1818           0 : void SmCloningVisitor::Visit( SmExpressionNode* pNode )
    1819             : {
    1820           0 :     SmExpressionNode* pClone = new SmExpressionNode( pNode->GetToken( ) );
    1821           0 :     CloneNodeAttr( pNode, pClone );
    1822           0 :     CloneKids( pNode, pClone );
    1823           0 :     pResult = pClone;
    1824           0 : }
    1825             : 
    1826           0 : void SmCloningVisitor::Visit( SmPolyLineNode* pNode )
    1827             : {
    1828           0 :     pResult = new SmPolyLineNode( pNode->GetToken( ) );
    1829           0 :     CloneNodeAttr( pNode, pResult );
    1830           0 : }
    1831             : 
    1832           0 : void SmCloningVisitor::Visit( SmRootNode* pNode )
    1833             : {
    1834           0 :     SmRootNode* pClone = new SmRootNode( pNode->GetToken( ) );
    1835           0 :     CloneNodeAttr( pNode, pClone );
    1836           0 :     CloneKids( pNode, pClone );
    1837           0 :     pResult = pClone;
    1838           0 : }
    1839             : 
    1840           0 : void SmCloningVisitor::Visit( SmRootSymbolNode* pNode )
    1841             : {
    1842           0 :     pResult = new SmRootSymbolNode( pNode->GetToken( ) );
    1843           0 :     CloneNodeAttr( pNode, pResult );
    1844           0 : }
    1845             : 
    1846           0 : void SmCloningVisitor::Visit( SmDynIntegralNode* pNode )
    1847             : {
    1848           0 :     SmDynIntegralNode* pClone = new SmDynIntegralNode( pNode->GetToken( ) );
    1849           0 :     CloneNodeAttr( pNode, pClone );
    1850           0 :     CloneKids( pNode, pClone );
    1851           0 :     pResult = pClone;
    1852           0 : }
    1853             : 
    1854           0 : void SmCloningVisitor::Visit( SmDynIntegralSymbolNode* pNode )
    1855             : {
    1856           0 :     pResult = new SmDynIntegralSymbolNode( pNode->GetToken( ) );
    1857           0 :     CloneNodeAttr( pNode, pResult );
    1858           0 : }
    1859             : 
    1860           0 : void SmCloningVisitor::Visit( SmRectangleNode* pNode )
    1861             : {
    1862           0 :     pResult = new SmRectangleNode( pNode->GetToken( ) );
    1863           0 :     CloneNodeAttr( pNode, pResult );
    1864           0 : }
    1865             : 
    1866           0 : void SmCloningVisitor::Visit( SmVerticalBraceNode* pNode )
    1867             : {
    1868           0 :     SmVerticalBraceNode* pClone = new SmVerticalBraceNode( pNode->GetToken( ) );
    1869           0 :     CloneNodeAttr( pNode, pClone );
    1870           0 :     CloneKids( pNode, pClone );
    1871           0 :     pResult = pClone;
    1872           0 : }
    1873             : 
    1874             : // SmSelectionDrawingVisitor
    1875             : 
    1876           0 : SmSelectionDrawingVisitor::SmSelectionDrawingVisitor( OutputDevice& rDevice, SmNode* pTree, Point Offset )
    1877           0 :     : rDev( rDevice ) {
    1878           0 :     bHasSelectionArea = false;
    1879             : 
    1880             :     //Visit everything
    1881             :     SAL_WARN_IF( !pTree, "starmath", "pTree can't be null!" );
    1882           0 :     if( pTree )
    1883           0 :         pTree->Accept( this );
    1884             : 
    1885             :     //Draw selection if there's any
    1886           0 :     if( bHasSelectionArea ){
    1887           0 :         aSelectionArea.Move( Offset.X( ), Offset.Y( ) );
    1888             : 
    1889             :         //Save device state
    1890           0 :         rDev.Push( PushFlags::LINECOLOR | PushFlags::FILLCOLOR );
    1891             :         //Change colors
    1892           0 :         rDev.SetLineColor( );
    1893           0 :         rDev.SetFillColor( Color( COL_LIGHTGRAY ) );
    1894             : 
    1895             :         //Draw rectangle
    1896           0 :         rDev.DrawRect( aSelectionArea );
    1897             : 
    1898             :         //Restore device state
    1899           0 :         rDev.Pop( );
    1900             :     }
    1901           0 : }
    1902             : 
    1903           0 : void SmSelectionDrawingVisitor::ExtendSelectionArea(const Rectangle& rArea)
    1904             : {
    1905           0 :     if ( ! bHasSelectionArea ) {
    1906           0 :         aSelectionArea = rArea;
    1907           0 :         bHasSelectionArea = true;
    1908             :     } else
    1909           0 :         aSelectionArea.Union(rArea);
    1910           0 : }
    1911             : 
    1912           0 : void SmSelectionDrawingVisitor::DefaultVisit( SmNode* pNode )
    1913             : {
    1914           0 :     if( pNode->IsSelected( ) )
    1915           0 :         ExtendSelectionArea( pNode->AsRectangle( ) );
    1916           0 :     VisitChildren( pNode );
    1917           0 : }
    1918             : 
    1919           0 : void SmSelectionDrawingVisitor::VisitChildren( SmNode* pNode )
    1920             : {
    1921           0 :     SmNodeIterator it( pNode );
    1922           0 :     while( it.Next( ) )
    1923           0 :         it->Accept( this );
    1924           0 : }
    1925             : 
    1926           0 : void SmSelectionDrawingVisitor::Visit( SmTextNode* pNode )
    1927             : {
    1928           0 :     if( pNode->IsSelected( ) ){
    1929           0 :         rDev.Push( PushFlags::TEXTCOLOR | PushFlags::FONT );
    1930             : 
    1931           0 :         rDev.SetFont( pNode->GetFont( ) );
    1932           0 :         Point Position = pNode->GetTopLeft( );
    1933           0 :         long left   = Position.getX( ) + rDev.GetTextWidth( pNode->GetText( ), 0, pNode->GetSelectionStart( ) );
    1934           0 :         long right  = Position.getX( ) + rDev.GetTextWidth( pNode->GetText( ), 0, pNode->GetSelectionEnd( ) );
    1935           0 :         long top    = Position.getY( );
    1936           0 :         long bottom = top + pNode->GetHeight( );
    1937           0 :         Rectangle rect( left, top, right, bottom );
    1938             : 
    1939           0 :         ExtendSelectionArea( rect );
    1940             : 
    1941           0 :         rDev.Pop( );
    1942             :     }
    1943           0 : }
    1944             : 
    1945             : // SmNodeToTextVisitor
    1946             : 
    1947         559 : SmNodeToTextVisitor::SmNodeToTextVisitor( SmNode* pNode, OUString &rText )
    1948             : {
    1949         559 :     pNode->Accept( this );
    1950         559 :     rText = aCmdText.makeStringAndClear();
    1951         559 : }
    1952             : 
    1953          36 : void SmNodeToTextVisitor::Visit( SmTableNode* pNode )
    1954             : {
    1955          36 :     if( pNode->GetToken( ).eType == TBINOM ) {
    1956           4 :         Append( "{ binom" );
    1957           4 :         LineToText( pNode->GetSubNode( 0 ) );
    1958           4 :         LineToText( pNode->GetSubNode( 1 ) );
    1959           4 :         Append("} ");
    1960          32 :     } else if( pNode->GetToken( ).eType == TSTACK ) {
    1961          16 :         Append( "stack{ " );
    1962          16 :         SmNodeIterator it( pNode );
    1963          16 :         it.Next( );
    1964             :         while( true ) {
    1965          36 :             LineToText( it.Current( ) );
    1966          36 :             if( it.Next( ) ) {
    1967          20 :                 Separate( );
    1968          20 :                 Append( "# " );
    1969             :             }else
    1970          16 :                 break;
    1971             :         }
    1972          16 :         Separate( );
    1973          36 :         Append( "}" );
    1974             :     } else { //Assume it's a toplevel table, containing lines
    1975          16 :         SmNodeIterator it( pNode );
    1976          16 :         it.Next( );
    1977             :         while( true ) {
    1978          16 :             Separate( );
    1979          16 :             it->Accept( this );
    1980          16 :             if( it.Next( ) ) {
    1981           0 :                 Separate( );
    1982           0 :                 Append( "newline" );
    1983             :             }else
    1984          16 :                 break;
    1985           0 :         }
    1986             :     }
    1987          36 : }
    1988             : 
    1989          84 : void SmNodeToTextVisitor::Visit( SmBraceNode* pNode )
    1990             : {
    1991          84 :     SmNode *pLeftBrace  = pNode->GetSubNode( 0 ),
    1992          84 :            *pBody       = pNode->GetSubNode( 1 ),
    1993          84 :            *pRightBrace = pNode->GetSubNode( 2 );
    1994             :     //Handle special case where it's absolute function
    1995          84 :     if( pNode->GetToken( ).eType == TABS ) {
    1996           4 :         Append( "abs" );
    1997           4 :         LineToText( pBody );
    1998             :     } else {
    1999          80 :         if( pNode->GetScaleMode( ) == SCALE_HEIGHT )
    2000          18 :             Append( "left " );
    2001          80 :         pLeftBrace->Accept( this );
    2002          80 :         Separate( );
    2003          80 :         pBody->Accept( this );
    2004          80 :         Separate( );
    2005          80 :         if( pNode->GetScaleMode( ) == SCALE_HEIGHT )
    2006          18 :             Append( "right " );
    2007          80 :         pRightBrace->Accept( this );
    2008             :     }
    2009          84 : }
    2010             : 
    2011          80 : void SmNodeToTextVisitor::Visit( SmBracebodyNode* pNode )
    2012             : {
    2013          80 :     SmNodeIterator it( pNode );
    2014         248 :     while( it.Next( ) ){
    2015          88 :         Separate( );
    2016          88 :         it->Accept( this );
    2017             :     }
    2018          80 : }
    2019             : 
    2020          27 : void SmNodeToTextVisitor::Visit( SmOperNode* pNode )
    2021             : {
    2022          27 :     Append( pNode->GetToken( ).aText );
    2023          27 :     Separate( );
    2024          27 :     if( pNode->GetToken( ).eType == TOPER ){
    2025             :         //There's an SmGlyphSpecialNode if eType == TOPER
    2026           0 :         if( pNode->GetSubNode( 0 )->GetType( ) == NSUBSUP )
    2027           0 :             Append( pNode->GetSubNode( 0 )->GetSubNode( 0 )->GetToken( ).aText );
    2028             :         else
    2029           0 :             Append( pNode->GetSubNode( 0 )->GetToken( ).aText );
    2030             :     }
    2031          27 :     if( pNode->GetSubNode( 0 )->GetType( ) == NSUBSUP ) {
    2032           7 :         SmSubSupNode *pSubSup = static_cast<SmSubSupNode*>( pNode->GetSubNode( 0 ) );
    2033             :         SmNode* pChild;
    2034           7 :         if( ( pChild = pSubSup->GetSubSup( LSUP ) ) ) {
    2035           0 :             Separate( );
    2036           0 :             Append( "lsup { " );
    2037           0 :             LineToText( pChild );
    2038           0 :             Append( "} " );
    2039             :         }
    2040           7 :         if( ( pChild = pSubSup->GetSubSup( LSUB ) ) ) {
    2041           0 :             Separate( );
    2042           0 :             Append( "lsub { " );
    2043           0 :             LineToText( pChild );
    2044           0 :             Append( "} " );
    2045             :         }
    2046           7 :         if( ( pChild = pSubSup->GetSubSup( RSUP ) ) ) {
    2047           0 :             Separate( );
    2048           0 :             Append( "^ { " );
    2049           0 :             LineToText( pChild );
    2050           0 :             Append( "} " );
    2051             :         }
    2052           7 :         if( ( pChild = pSubSup->GetSubSup( RSUB ) ) ) {
    2053           0 :             Separate( );
    2054           0 :             Append( "_ { " );
    2055           0 :             LineToText( pChild );
    2056           0 :             Append( "} " );
    2057             :         }
    2058           7 :         if( ( pChild = pSubSup->GetSubSup( CSUP ) ) ) {
    2059           5 :             Separate( );
    2060           5 :             if (pSubSup->IsUseLimits())
    2061           4 :                 Append( "to { " );
    2062             :             else
    2063           1 :                 Append( "csup { " );
    2064           5 :             LineToText( pChild );
    2065           5 :             Append( "} " );
    2066             :         }
    2067           7 :         if( ( pChild = pSubSup->GetSubSup( CSUB ) ) ) {
    2068           7 :             Separate( );
    2069           7 :             if (pSubSup->IsUseLimits())
    2070           6 :                 Append( "from { " );
    2071             :             else
    2072           1 :                 Append( "csub { " );
    2073           7 :             LineToText( pChild );
    2074           7 :             Append( "} " );
    2075             :         }
    2076             :     }
    2077          27 :     LineToText( pNode->GetSubNode( 1 ) );
    2078          27 : }
    2079             : 
    2080          14 : void SmNodeToTextVisitor::Visit( SmAlignNode* pNode )
    2081             : {
    2082          14 :     Append( pNode->GetToken( ).aText );
    2083          14 :     LineToText( pNode->GetSubNode( 0 ) );
    2084          14 : }
    2085             : 
    2086          36 : void SmNodeToTextVisitor::Visit( SmAttributNode* pNode )
    2087             : {
    2088          36 :     Append( pNode->GetToken( ).aText );
    2089          36 :     LineToText( pNode->GetSubNode( 1 ) );
    2090          36 : }
    2091             : 
    2092          34 : void SmNodeToTextVisitor::Visit( SmFontNode* pNode )
    2093             : {
    2094          34 :     switch ( pNode->GetToken( ).eType )
    2095             :     {
    2096             :         case TBOLD:
    2097           2 :             Append( "bold " );
    2098           2 :             break;
    2099             :         case TNBOLD:
    2100           0 :             Append( "nbold " );
    2101           0 :             break;
    2102             :         case TITALIC:
    2103           2 :             Append( "italic " );
    2104           2 :             break;
    2105             :         case TNITALIC:
    2106           2 :             Append( "nitalic " );
    2107           2 :             break;
    2108             :         case TPHANTOM:
    2109           4 :             Append( "phantom " );
    2110           4 :             break;
    2111             :         case TSIZE:
    2112             :             {
    2113           2 :                 Append( "size " );
    2114           2 :                 switch ( pNode->GetSizeType( ) )
    2115             :                 {
    2116             :                     case FontSizeType::PLUS:
    2117           0 :                         Append( "+" );
    2118           0 :                         break;
    2119             :                     case FontSizeType::MINUS:
    2120           0 :                         Append( "-" );
    2121           0 :                         break;
    2122             :                     case FontSizeType::MULTIPLY:
    2123           0 :                         Append( "*" );
    2124           0 :                         break;
    2125             :                     case FontSizeType::DIVIDE:
    2126           0 :                         Append( "/" );
    2127           0 :                         break;
    2128             :                     case FontSizeType::ABSOLUT:
    2129             :                     default:
    2130           2 :                         break;
    2131             :                 }
    2132             :                 Append( ::rtl::math::doubleToUString(
    2133           2 :                             static_cast<double>( pNode->GetSizeParameter( ) ),
    2134             :                             rtl_math_StringFormat_Automatic,
    2135           2 :                             rtl_math_DecimalPlaces_Max, '.', true ) );
    2136           2 :                 Append( " " );
    2137             :             }
    2138           2 :             break;
    2139             :         case TBLACK:
    2140           0 :             Append( "color black " );
    2141           0 :             break;
    2142             :         case TWHITE:
    2143           2 :             Append( "color white " );
    2144           2 :             break;
    2145             :         case TRED:
    2146           2 :             Append( "color red " );
    2147           2 :             break;
    2148             :         case TGREEN:
    2149           6 :             Append( "color green " );
    2150           6 :             break;
    2151             :         case TBLUE:
    2152           2 :             Append( "color blue " );
    2153           2 :             break;
    2154             :         case TCYAN:
    2155           2 :             Append( "color cyan " );
    2156           2 :             break;
    2157             :         case TMAGENTA:
    2158           0 :             Append( "color magenta " );
    2159           0 :             break;
    2160             :         case TYELLOW:
    2161           2 :             Append( "color yellow " );
    2162           2 :             break;
    2163             :         case TSANS:
    2164           2 :             Append( "font sans " );
    2165           2 :             break;
    2166             :         case TSERIF:
    2167           2 :             Append( "font serif " );
    2168           2 :             break;
    2169             :         case TFIXED:
    2170           2 :             Append( "font fixed " );
    2171           2 :             break;
    2172             :         default:
    2173           0 :             break;
    2174             :     }
    2175          34 :     LineToText( pNode->GetSubNode( 1 ) );
    2176          34 : }
    2177             : 
    2178          38 : void SmNodeToTextVisitor::Visit( SmUnHorNode* pNode )
    2179             : {
    2180          38 :     SmNodeIterator it( pNode, pNode->GetSubNode( 1 )->GetToken( ).eType == TFACT );
    2181         152 :     while( it.Next( ) ) {
    2182          76 :         Separate( );
    2183          76 :         it->Accept( this );
    2184             :     }
    2185          38 : }
    2186             : 
    2187         116 : void SmNodeToTextVisitor::Visit( SmBinHorNode* pNode )
    2188             : {
    2189         116 :     SmNode *pLeft  = pNode->GetSubNode( 0 ),
    2190         116 :            *pOper  = pNode->GetSubNode( 1 ),
    2191         116 :            *pRight = pNode->GetSubNode( 2 );
    2192         116 :     Separate( );
    2193         116 :     pLeft->Accept( this );
    2194         116 :     Separate( );
    2195         116 :     pOper->Accept( this );
    2196         116 :     Separate( );
    2197         116 :     pRight->Accept( this );
    2198         116 :     Separate( );
    2199         116 : }
    2200             : 
    2201          26 : void SmNodeToTextVisitor::Visit( SmBinVerNode* pNode )
    2202             : {
    2203          26 :     SmNode *pNum    = pNode->GetSubNode( 0 ),
    2204          26 :            *pDenom  = pNode->GetSubNode( 2 );
    2205          26 :     Append( "{ " );
    2206          26 :     LineToText( pNum );
    2207          26 :     Append( "over" );
    2208          26 :     LineToText( pDenom );
    2209          26 :     Append( "} " );
    2210          26 : }
    2211             : 
    2212           0 : void SmNodeToTextVisitor::Visit( SmBinDiagonalNode* pNode )
    2213             : {
    2214           0 :     SmNode *pLeftOperand  = pNode->GetSubNode( 0 ),
    2215           0 :            *pRightOperand = pNode->GetSubNode( 1 );
    2216           0 :     Append( "{ " );
    2217           0 :     LineToText( pLeftOperand );
    2218           0 :     Separate( );
    2219           0 :     Append( "wideslash " );
    2220           0 :     LineToText( pRightOperand );
    2221           0 :     Append( "} " );
    2222           0 : }
    2223             : 
    2224          34 : void SmNodeToTextVisitor::Visit( SmSubSupNode* pNode )
    2225             : {
    2226          34 :     LineToText( pNode->GetBody( ) );
    2227             :     SmNode *pChild;
    2228          34 :     if( ( pChild = pNode->GetSubSup( LSUP ) ) ) {
    2229           2 :         Separate( );
    2230           2 :         Append( "lsup " );
    2231           2 :         LineToText( pChild );
    2232             :     }
    2233          34 :     if( ( pChild = pNode->GetSubSup( LSUB ) ) ) {
    2234           2 :         Separate( );
    2235           2 :         Append( "lsub " );
    2236           2 :         LineToText( pChild );
    2237             :     }
    2238          34 :     if( ( pChild = pNode->GetSubSup( RSUP ) ) ) {
    2239          16 :         Separate( );
    2240          16 :         Append( "^ " );
    2241          16 :         LineToText( pChild );
    2242             :     }
    2243          34 :     if( ( pChild = pNode->GetSubSup( RSUB ) ) ) {
    2244          10 :         Separate( );
    2245          10 :         Append( "_ " );
    2246          10 :         LineToText( pChild );
    2247             :     }
    2248          34 :     if( ( pChild = pNode->GetSubSup( CSUP ) ) ) {
    2249           2 :         Separate( );
    2250           2 :         if (pNode->IsUseLimits())
    2251           0 :             Append( "to " );
    2252             :         else
    2253           2 :             Append( "csup " );
    2254           2 :         LineToText( pChild );
    2255             :     }
    2256          34 :     if( ( pChild = pNode->GetSubSup( CSUB ) ) ) {
    2257           2 :         Separate( );
    2258           2 :         if (pNode->IsUseLimits())
    2259           0 :             Append( "from " );
    2260             :         else
    2261           2 :             Append( "csub " );
    2262           2 :         LineToText( pChild );
    2263             :     }
    2264          34 : }
    2265             : 
    2266           4 : void SmNodeToTextVisitor::Visit( SmMatrixNode* pNode )
    2267             : {
    2268           4 :     Append( "matrix{" );
    2269          12 :     for ( sal_uInt16 i = 0; i < pNode->GetNumRows( ); i++ ) {
    2270          28 :         for ( sal_uInt16 j = 0; j < pNode->GetNumCols( ); j++ ) {
    2271          20 :             SmNode* pSubNode = pNode->GetSubNode( i * pNode->GetNumCols( ) + j );
    2272          20 :             Separate( );
    2273          20 :             pSubNode->Accept( this );
    2274          20 :             Separate( );
    2275          20 :             if( j != pNode->GetNumCols( ) - 1 )
    2276          12 :                 Append( "#" );
    2277             :         }
    2278           8 :         Separate( );
    2279           8 :         if( i != pNode->GetNumRows( ) - 1 )
    2280           4 :             Append( "##" );
    2281             :     }
    2282           4 :     Append( "} " );
    2283           4 : }
    2284             : 
    2285           2 : void SmNodeToTextVisitor::Visit( SmPlaceNode* )
    2286             : {
    2287           2 :     Append( "<?>" );
    2288           2 : }
    2289             : 
    2290         680 : void SmNodeToTextVisitor::Visit( SmTextNode* pNode )
    2291             : {
    2292             :     //TODO: This method might need improvements, see SmTextNode::CreateTextFromNode
    2293         680 :     if( pNode->GetToken( ).eType == TTEXT )
    2294           6 :         Append( "\"" );
    2295         680 :     Append( pNode->GetText( ) );
    2296         680 :     if( pNode->GetToken( ).eType == TTEXT )
    2297           6 :         Append( "\"" );
    2298         680 : }
    2299             : 
    2300         131 : void SmNodeToTextVisitor::Visit( SmSpecialNode* pNode )
    2301             : {
    2302         131 :     Append( pNode->GetToken( ).aText );
    2303         131 : }
    2304             : 
    2305           0 : void SmNodeToTextVisitor::Visit( SmGlyphSpecialNode* pNode )
    2306             : {
    2307           0 :     if( pNode->GetToken( ).eType == TBOPER )
    2308           0 :         Append( "boper " );
    2309             :     else
    2310           0 :         Append( "uoper " );
    2311           0 :     Append( pNode->GetToken( ).aText );
    2312           0 : }
    2313             : 
    2314         380 : void SmNodeToTextVisitor::Visit( SmMathSymbolNode* pNode )
    2315             : {
    2316         380 :     Append( pNode->GetToken( ).aText );
    2317         380 : }
    2318             : 
    2319           4 : void SmNodeToTextVisitor::Visit( SmBlankNode* pNode )
    2320             : {
    2321           4 :     Append( pNode->GetToken( ).aText );
    2322           4 : }
    2323             : 
    2324           4 : void SmNodeToTextVisitor::Visit( SmErrorNode* )
    2325             : {
    2326           4 : }
    2327             : 
    2328           0 : void SmNodeToTextVisitor::Visit( SmLineNode* pNode )
    2329             : {
    2330           0 :     SmNodeIterator it( pNode );
    2331           0 :     while( it.Next( ) ){
    2332           0 :         Separate( );
    2333           0 :         it->Accept( this );
    2334             :     }
    2335           0 : }
    2336             : 
    2337         112 : void SmNodeToTextVisitor::Visit( SmExpressionNode* pNode )
    2338             : {
    2339         112 :     bool bracketsNeeded = pNode->GetNumSubNodes() != 1 || pNode->GetSubNode(0)->GetType() == NBINHOR;
    2340         112 :     if (!bracketsNeeded)
    2341             :     {
    2342          22 :         const SmNode *pParent = pNode->GetParent();
    2343             :         // nested subsups
    2344             :         bracketsNeeded =
    2345          23 :             pParent && pParent->GetType() == NSUBSUP &&
    2346          24 :             pNode->GetNumSubNodes() == 1 &&
    2347          23 :             pNode->GetSubNode(0)->GetType() == NSUBSUP;
    2348             :     }
    2349             : 
    2350         112 :     if (bracketsNeeded) {
    2351          90 :         Append( "{ " );
    2352             :     }
    2353         112 :     SmNodeIterator it( pNode );
    2354         422 :     while( it.Next( ) ) {
    2355         198 :         it->Accept( this );
    2356         198 :         Separate( );
    2357             :     }
    2358         112 :     if (bracketsNeeded) {
    2359          90 :         Append( "} " );
    2360             :     }
    2361         112 : }
    2362             : 
    2363           0 : void SmNodeToTextVisitor::Visit( SmPolyLineNode* )
    2364             : {
    2365           0 : }
    2366             : 
    2367           4 : void SmNodeToTextVisitor::Visit( SmRootNode* pNode )
    2368             : {
    2369           4 :     SmNode *pExtra   = pNode->GetSubNode( 0 ),
    2370           4 :            *pBody    = pNode->GetSubNode( 2 );
    2371           4 :     if( pExtra ) {
    2372           2 :         Append( "nroot" );
    2373           2 :         LineToText( pExtra );
    2374             :     } else
    2375           2 :         Append( "sqrt" );
    2376           4 :     LineToText( pBody );
    2377           4 : }
    2378             : 
    2379           0 : void SmNodeToTextVisitor::Visit( SmRootSymbolNode* )
    2380             : {
    2381           0 : }
    2382             : 
    2383           0 : void SmNodeToTextVisitor::Visit( SmDynIntegralNode* pNode )
    2384             : {
    2385           0 :     SmNode *pBody    = pNode->Body();
    2386           0 :     Append( "intd" );
    2387           0 :     LineToText( pBody );
    2388           0 : }
    2389             : 
    2390           0 : void SmNodeToTextVisitor::Visit( SmDynIntegralSymbolNode* )
    2391             : {
    2392           0 : }
    2393             : 
    2394           0 : void SmNodeToTextVisitor::Visit( SmRectangleNode* )
    2395             : {
    2396           0 : }
    2397             : 
    2398           4 : void SmNodeToTextVisitor::Visit( SmVerticalBraceNode* pNode )
    2399             : {
    2400           4 :     SmNode *pBody   = pNode->GetSubNode( 0 ),
    2401           4 :            *pScript = pNode->GetSubNode( 2 );
    2402           4 :     LineToText( pBody );
    2403           4 :     Append( pNode->GetToken( ).aText );
    2404           4 :     LineToText( pScript );
    2405          46 : }
    2406             : 
    2407             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11