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