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