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

Generated by: LCOV version 1.10