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