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

Generated by: LCOV version 1.10