LCOV - code coverage report
Current view: top level - libreoffice/starmath/source - visitors.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 594 1349 44.0 %
Date: 2012-12-27 Functions: 81 200 40.5 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10