xref: /trunk/main/sw/source/core/crsr/viscrs.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #ifndef _SVSTDARR_HXX
33 #define _SVSTDARR_USHORTS
34 #include <svl/svstdarr.hxx>
35 #endif
36 
37 #include <vcl/dialog.hxx>
38 #include <vcl/msgbox.hxx>
39 #include <vcl/wrkwin.hxx>
40 #include <viewopt.hxx>
41 #include <frmtool.hxx>
42 #include <viscrs.hxx>
43 #include <crsrsh.hxx>
44 #include <doc.hxx>
45 #include <swtable.hxx>
46 #include <viewimp.hxx>
47 #include <dview.hxx>
48 #include <rootfrm.hxx>
49 #include <txtfrm.hxx>   // SwTxtFrm
50 #include <docary.hxx>
51 #include <extinput.hxx>
52 #include <ndtxt.hxx>
53 #include <scriptinfo.hxx>
54 #include <mdiexp.hxx>           // GetSearchDialog
55 #ifndef _COMCORE_HRC
56 #include <comcore.hrc>          // ResId fuer Abfrage wenn zu Search & Replaces
57 #endif
58 
59 #include <svx/sdr/overlay/overlaymanager.hxx>
60 #include <svx/sdrpaintwindow.hxx>
61 #include <vcl/svapp.hxx>
62 #include <svx/sdr/overlay/overlayselection.hxx>
63 
64 extern void SwCalcPixStatics( OutputDevice *pOut );
65 
66 //Damit beim ShowCrsr nicht immer wieder die gleiche Size teuer ermittelt
67 //werden muss, hier statische Member, die beim Wechsel des MapModes
68 // angepasst werden
69 
70 long SwSelPaintRects::nPixPtX = 0;
71 long SwSelPaintRects::nPixPtY = 0;
72 MapMode* SwSelPaintRects::pMapMode = 0;
73 
74 
75 #ifdef SHOW_BOOKMARKS
76 // #include <IMark.hxx>
77 //
78 // class SwBookmarkRects : public SwSelPaintRects
79 // {
80 //  virtual void Paint( const Rectangle& rRect );
81 //  virtual void FillRects();
82 //
83 // public:
84 //  SwBookmarkRects( const SwCrsrShell& rSh ) : SwSelPaintRects( rSh ) {}
85 // };
86 //
87 // void SwBookmarkRects::Paint( const Rectangle& rRect )
88 // {
89 //  Window* pWin = GetShell()->GetWin();
90 //
91 //  RasterOp eOld( pWin->GetRasterOp() );
92 //  sal_Bool bLCol = pWin->IsLineColor();
93 //  Color aLCol( pWin->GetLineColor() );
94 //  sal_Bool bFCol = pWin->IsFillColor();
95 //  Color aFCol( pWin->GetFillColor() );
96 //
97 //  pWin->SetRasterOp( ROP_XOR );
98 //  Color aCol( RGB_COLORDATA( 0xF0, 0xC8, 0xF0 ) ^ COL_WHITE );
99 //  pWin->SetFillColor( aCol );
100 //  pWin->SetLineColor( aCol );
101 //
102 //  pWin->DrawRect( rRect );
103 //
104 //  if( bLCol ) pWin->SetLineColor( aLCol ); else pWin->SetLineColor();
105 //  if( bFCol ) pWin->SetFillColor( aFCol ); else pWin->SetFillColor();
106 //  pWin->SetRasterOp( eOld );
107 // }
108 //
109 // void SwBookmarkRects::FillRects()
110 // {
111 //  SwRegionRects aReg( GetShell()->VisArea() );
112 //
113 //     const SwBookmarks& rBkmkTbl = GetShell()->getIDocumentMarkAccess()->getBookmarks();
114 //  SwShellCrsr* pCrsr = 0;
115 //  for( sal_uInt16 n = 0; n < rBkmkTbl.Count(); ++n )
116 //  {
117 //      const SwBookmark& rBkmk = *rBkmkTbl[ n ];
118 //      if( rBkmk.IsBookMark() && rBkmk.GetOtherPos() )
119 //      {
120 //          if( !pCrsr )
121 //          {
122 //              pCrsr = new SwShellCrsr( *GetShell(), rBkmk.GetPos() );
123 //              pCrsr->SetMark();
124 //          }
125 //          else
126 //              *pCrsr->GetPoint() = rBkmk.GetPos();
127 //          *pCrsr->GetMark() = *rBkmk.GetOtherPos();
128 //          pCrsr->FillRects();
129 //          for( sal_uInt16 i = 0; i < pCrsr->Count(); ++i )
130 //              aReg -= (*pCrsr)[ i ];
131 //
132 //          pCrsr->Remove( 0, i );
133 //      }
134 //  }
135 //  if( pCrsr ) delete pCrsr;
136 //
137 //  aReg.Invert();
138 //  SwRects::Insert( &aReg, 0 );
139 // }
140 //
141 // SwBookmarkRects* pBookMarkRects = 0;
142 //
143 // void ShowBookmarks( const SwCrsrShell* pSh, int nAction, const SwRect* pRect = 0 )
144 // {
145 //     if( !pBookMarkRects && pSh->getIDocumentMarkAccess()->getBookmarks().Count() )
146 //      pBookMarkRects = new SwBookmarkRects( *pSh );
147 //
148 //  if( pBookMarkRects )
149 //  {
150 //      switch( nAction )
151 //      {
152 //      case 1: pBookMarkRects->Show(); break;
153 //      case 2: pBookMarkRects->Hide(); break;
154 //      case 3: pBookMarkRects->Invalidate( *pRect ); break;
155 //      }
156 //
157 //      if( !pBookMarkRects->Count() )
158 //          delete pBookMarkRects, pBookMarkRects = 0;
159 //  }
160 // }
161 //
162 // #define SHOWBOOKMARKS1( nAct )           ShowBookmarks( GetShell(),nAct );
163 // #define SHOWBOOKMARKS2( nAct, pRect )    ShowBookmarks( GetShell(),nAct, pRect );
164 
165 #else
166 
167 #define SHOWBOOKMARKS1( nAct )
168 #define SHOWBOOKMARKS2( nAct, pRect )
169 
170 #endif
171 
172 #ifdef SHOW_REDLINES
173 #include <redline.hxx>
174 
175 class SwRedlineRects : public SwSelPaintRects
176 {
177     sal_uInt16 nMode;
178     sal_uInt16 nNm;
179 
180     virtual void Paint( const Rectangle& rRect );
181     virtual void FillRects();
182 
183 public:
184     SwRedlineRects( const SwCrsrShell& rSh, sal_uInt16 nName, sal_uInt16 n )
185         : SwSelPaintRects( rSh ), nMode( n ), nNm( nName )
186     {}
187 };
188 
189 void SwRedlineRects::Paint( const Rectangle& rRect )
190 {
191     Window* pWin = GetShell()->GetWin();
192 
193     RasterOp eOld( pWin->GetRasterOp() );
194     sal_Bool bLCol = pWin->IsLineColor();
195     Color aLCol( pWin->GetLineColor() );
196     sal_Bool bFCol = pWin->IsFillColor();
197     Color aFCol( pWin->GetFillColor() );
198 
199     pWin->SetRasterOp( ROP_XOR );
200     Color aCol;
201 
202     sal_uInt8 nVal = 0xc8 - ( (nMode / 4) * 16 );
203     switch( nMode % 4 )
204     {
205     case 0: aCol = RGB_COLORDATA( nVal, nVal, 0xFF );   break;
206     case 1: aCol = RGB_COLORDATA( 0xFF, 0xc8, nVal );   break;
207     case 2: aCol = RGB_COLORDATA( nVal, 0xFF, nVal );   break;
208     case 3: aCol = RGB_COLORDATA( 0xFF, nVal, nVal );   break;
209     }
210     aCol = aCol.GetColor() ^ COL_WHITE;
211 
212     pWin->SetFillColor( aCol );
213     pWin->SetLineColor( aCol );
214 
215     pWin->DrawRect( rRect );
216 
217     if( bLCol ) pWin->SetLineColor( aLCol ); else pWin->SetLineColor();
218     if( bFCol ) pWin->SetFillColor( aFCol ); else pWin->SetFillColor();
219     pWin->SetRasterOp( eOld );
220 }
221 
222 void SwRedlineRects::FillRects()
223 {
224     SwRegionRects aReg( GetShell()->VisArea() );
225 
226     const SwRedlineTbl& rTbl = GetShell()->GetDoc()->GetRedlineTbl();
227     SwShellCrsr* pCrsr = 0;
228     for( sal_uInt16 n = 0; n < rTbl.Count(); ++n )
229     {
230         const SwRedline& rRed = *rTbl[ n ];
231         if( rRed.HasMark() && (nMode % 4 ) == rRed.GetType() &&
232             nNm == rRed.GetAuthor() )
233         {
234             if( !pCrsr )
235             {
236                 pCrsr = new SwShellCrsr( *GetShell(), *rRed.GetPoint() );
237                 pCrsr->SetMark();
238             }
239             else
240                 *pCrsr->GetPoint() = *rRed.GetPoint();
241             *pCrsr->GetMark() = *rRed.GetMark();
242             pCrsr->FillRects();
243             for( sal_uInt16 i = 0; i < pCrsr->Count(); ++i )
244                 aReg -= (*pCrsr)[ i ];
245 
246             pCrsr->Remove( 0, i );
247         }
248     }
249     if( pCrsr ) delete pCrsr;
250 
251     aReg.Invert();
252     SwRects::Insert( &aReg, 0 );
253 }
254 
255 SwRedlineRects* aRedlines[ 10 * 4 ];
256 static int bFirstCall = sal_True;
257 
258 void ShowRedlines( const SwCrsrShell* pSh, int nAction, const SwRect* pRect = 0 )
259 {
260     if( bFirstCall )
261     {
262         memset( aRedlines, 0, sizeof(aRedlines));
263         bFirstCall = sal_False;
264     }
265 
266     const SwRedlineTbl& rTbl = pSh->GetDoc()->GetRedlineTbl();
267     const SwRedlineAuthorTbl& rAuthorTbl = pSh->GetDoc()->GetRedlineAuthorTbl();
268 
269     for( sal_uInt16 n = 0; n < rAuthorTbl.Count(); ++n )
270     {
271         for( int i = 0; i < 4; ++i  )
272         {
273             SwRedlineRects** ppRedRect = &aRedlines[ n * 4 + i ];
274             if( rTbl.Count() && !*ppRedRect )
275                 *ppRedRect = new SwRedlineRects( *pSh, n, n * 4 + i );
276 
277             if( *ppRedRect )
278             {
279                 switch( nAction )
280                 {
281                 case 1: (*ppRedRect)->Show(); break;
282                 case 2: (*ppRedRect)->Hide(); break;
283                 case 3: (*ppRedRect)->Invalidate( *pRect ); break;
284                 }
285 
286                 if( !(*ppRedRect)->Count() )
287                     delete *ppRedRect, *ppRedRect = 0;
288             }
289         }
290     }
291 }
292 
293 #define SHOWREDLINES1( nAct )           ShowRedlines( GetShell(),nAct );
294 #define SHOWREDLINES2( nAct, pRect )    ShowRedlines( GetShell(),nAct, pRect );
295 
296 #else
297 
298 #define SHOWREDLINES1( nAct )
299 #define SHOWREDLINES2( nAct, pRect )
300 
301 #endif
302 
303 #ifdef JP_REDLINE
304     if( GetDoc()->GetRedlineTbl().Count() )
305     {
306         SwRedlineTbl& rRedlineTbl = (SwRedlineTbl&)GetDoc()->GetRedlineTbl();
307         for( sal_uInt16 i = 0; i < rRedlineTbl.Count(); ++i )
308             rRedlineTbl[ i ]->HideRects( *GetShell() );
309     }
310 #endif
311 
312 // --------  Ab hier Klassen / Methoden fuer den nicht Text-Cursor ------
313 
314 SwVisCrsr::SwVisCrsr( const SwCrsrShell * pCShell )
315     : pCrsrShell( pCShell )
316 {
317     pCShell->GetWin()->SetCursor( &aTxtCrsr );
318     bIsVisible = aTxtCrsr.IsVisible();
319     bIsDragCrsr = sal_False;
320     aTxtCrsr.SetWidth( 0 );
321 
322 #ifdef SW_CRSR_TIMER
323     bTimerOn = sal_True;
324     SetTimeout( 50 );       // 50msec Verzoegerung
325 #endif
326 }
327 
328 
329 
330 SwVisCrsr::~SwVisCrsr()
331 {
332 #ifdef SW_CRSR_TIMER
333     if( bTimerOn )
334         Stop();     // Timer stoppen
335 #endif
336 
337     if( bIsVisible && aTxtCrsr.IsVisible() )
338         aTxtCrsr.Hide();
339 
340     pCrsrShell->GetWin()->SetCursor( 0 );
341 }
342 
343 
344 
345 
346 void SwVisCrsr::Show()
347 {
348     if( !bIsVisible )
349     {
350         bIsVisible = sal_True;
351 
352         // muss ueberhaupt angezeigt werden ?
353         if( pCrsrShell->VisArea().IsOver( pCrsrShell->aCharRect ) )
354 #ifdef SW_CRSR_TIMER
355         {
356             if( bTimerOn )
357                 Start();            // Timer aufsetzen
358             else
359             {
360                 if( IsActive() )
361                     Stop();         // Timer Stoppen
362 
363                 _SetPosAndShow();
364             }
365         }
366 #else
367             _SetPosAndShow();
368 #endif
369     }
370 }
371 
372 
373 
374 void SwVisCrsr::Hide()
375 {
376     if( bIsVisible )
377     {
378         bIsVisible = sal_False;
379 
380 #ifdef SW_CRSR_TIMER
381         if( IsActive() )
382             Stop();         // Timer Stoppen
383 #endif
384 
385         if( aTxtCrsr.IsVisible() )      // sollten die Flags nicht gueltig sein?
386             aTxtCrsr.Hide();
387     }
388 }
389 
390 #ifdef SW_CRSR_TIMER
391 
392 void __EXPORT SwVisCrsr::Timeout()
393 {
394     ASSERT( !bIsDragCrsr, "Timer vorher abschalten" );
395     if( bIsVisible )
396     {
397         if ( !pCrsrShell->GetWin() ) //SwFrmFmt::GetGraphic setzt das Win temp aus!
398             Start();
399         else
400             _SetPosAndShow();
401     }
402 }
403 
404 sal_Bool SwCrsrShell::ChgCrsrTimerFlag( sal_Bool bTimerOn )
405 {
406     return pVisCrsr->ChgTimerFlag( bTimerOn );
407 }
408 
409 
410 sal_Bool SwVisCrsr::ChgTimerFlag( sal_Bool bFlag )
411 {
412     bOld = bTimerOn;
413     if( !bFlag && bIsVisible && IsActive() )
414     {
415         Stop();         // Timer Stoppen
416         _SetPosAndShow();
417     }
418     bTimerOn = bFlag;
419     return bOld;
420 }
421 
422 #endif
423 
424 
425 void SwVisCrsr::_SetPosAndShow()
426 {
427     SwRect aRect;
428     long nTmpY = pCrsrShell->aCrsrHeight.Y();
429     if( 0 > nTmpY )
430     {
431         nTmpY = -nTmpY;
432         aTxtCrsr.SetOrientation( 900 );
433         aRect = SwRect( pCrsrShell->aCharRect.Pos(),
434            Size( pCrsrShell->aCharRect.Height(), nTmpY ) );
435         aRect.Pos().X() += pCrsrShell->aCrsrHeight.X();
436         if( pCrsrShell->IsOverwriteCrsr() )
437             aRect.Pos().Y() += aRect.Width();
438     }
439     else
440     {
441         aTxtCrsr.SetOrientation( 0 );
442         aRect = SwRect( pCrsrShell->aCharRect.Pos(),
443            Size( pCrsrShell->aCharRect.Width(), nTmpY ) );
444         aRect.Pos().Y() += pCrsrShell->aCrsrHeight.X();
445     }
446 
447     // check if cursor should show the current cursor bidi level
448     aTxtCrsr.SetDirection( CURSOR_DIRECTION_NONE );
449     const SwCursor* pTmpCrsr = pCrsrShell->_GetCrsr();
450 
451     if ( pTmpCrsr && !pCrsrShell->IsOverwriteCrsr() )
452     {
453         SwNode& rNode = pTmpCrsr->GetPoint()->nNode.GetNode();
454         if( rNode.IsTxtNode() )
455         {
456             const SwTxtNode& rTNd = *rNode.GetTxtNode();
457             const SwFrm* pFrm = rTNd.getLayoutFrm( pCrsrShell->GetLayout(), 0, 0, sal_False );
458             if ( pFrm )
459             {
460                 const SwScriptInfo* pSI = ((SwTxtFrm*)pFrm)->GetScriptInfo();
461                  // cursor level has to be shown
462                 if ( pSI && pSI->CountDirChg() > 1 )
463                 {
464                     aTxtCrsr.SetDirection(
465                         ( pTmpCrsr->GetCrsrBidiLevel() % 2 ) ?
466                           CURSOR_DIRECTION_RTL :
467                           CURSOR_DIRECTION_LTR );
468                 }
469 
470                 if ( pFrm->IsRightToLeft() )
471                 {
472                     const OutputDevice *pOut = pCrsrShell->GetOut();
473                     if ( pOut )
474                     {
475                         long nSize = pOut->GetSettings().GetStyleSettings().GetCursorSize();
476                         Size aSize( nSize, nSize );
477                         aSize = pOut->PixelToLogic( aSize );
478                         aRect.Left( aRect.Left() - aSize.Width() );
479                     }
480                 }
481             }
482         }
483     }
484 
485     if( aRect.Height() )
486     {
487         ::SwCalcPixStatics( pCrsrShell->GetOut() );
488         ::SwAlignRect( aRect, (ViewShell*)pCrsrShell );
489     }
490     if( !pCrsrShell->IsOverwriteCrsr() || bIsDragCrsr ||
491         pCrsrShell->IsSelection() )
492         aRect.Width( 0 );
493 
494     aTxtCrsr.SetSize( aRect.SSize() );
495 
496     aTxtCrsr.SetPos( aRect.Pos() );
497     if ( !pCrsrShell->IsCrsrReadonly()  || pCrsrShell->GetViewOptions()->IsSelectionInReadonly() )
498     {
499         if ( pCrsrShell->GetDrawView() )
500             ((SwDrawView*)pCrsrShell->GetDrawView())->SetAnimationEnabled(
501                     !pCrsrShell->IsSelection() );
502 
503         sal_uInt16 nStyle = bIsDragCrsr ? CURSOR_SHADOW : 0;
504         if( nStyle != aTxtCrsr.GetStyle() )
505         {
506             aTxtCrsr.SetStyle( nStyle );
507             aTxtCrsr.SetWindow( bIsDragCrsr ? pCrsrShell->GetWin() : 0 );
508         }
509 
510         aTxtCrsr.Show();
511     }
512 }
513 
514 //////////////////////////////////////////////////////////////////////////////
515 
516 SwSelPaintRects::SwSelPaintRects( const SwCrsrShell& rCSh )
517 :   SwRects( 0 ),
518     pCShell( &rCSh ),
519     mpCursorOverlay(0)
520 {
521 }
522 
523 SwSelPaintRects::~SwSelPaintRects()
524 {
525     Hide();
526 }
527 
528 void SwSelPaintRects::swapContent(SwSelPaintRects& rSwap)
529 {
530     SwRects aTempRects;
531     aTempRects.Insert(this, 0);
532 
533     Remove(0, Count());
534     Insert(&rSwap, 0);
535 
536     rSwap.Remove(0, rSwap.Count());
537     rSwap.Insert(&aTempRects, 0);
538 
539     // #i75172# also swap mpCursorOverlay
540     sdr::overlay::OverlayObject* pTempOverlay = getCursorOverlay();
541     setCursorOverlay(rSwap.getCursorOverlay());
542     rSwap.setCursorOverlay(pTempOverlay);
543 }
544 
545 void SwSelPaintRects::Hide()
546 {
547     if(mpCursorOverlay)
548     {
549         delete mpCursorOverlay;
550         mpCursorOverlay = 0;
551     }
552 
553     SwRects::Remove( 0, Count() );
554 }
555 
556 void SwSelPaintRects::Show()
557 {
558     SdrView* pView = (SdrView*)pCShell->GetDrawView();
559 
560     if(pView && pView->PaintWindowCount())
561     {
562         // reset rects
563         SwRects::Remove( 0, SwRects::Count() );
564         FillRects();
565 
566         // get new rects
567         std::vector< basegfx::B2DRange > aNewRanges;
568 
569         for(sal_uInt16 a(0); a < Count(); a++)
570         {
571             const SwRect aNextRect((*this)[a]);
572             const Rectangle aPntRect(aNextRect.SVRect());
573 
574             aNewRanges.push_back(basegfx::B2DRange(
575                 aPntRect.Left(), aPntRect.Top(),
576                 aPntRect.Right() + 1, aPntRect.Bottom() + 1));
577         }
578 
579         if(mpCursorOverlay)
580         {
581             if(aNewRanges.size())
582             {
583                 static_cast< sdr::overlay::OverlaySelection* >(mpCursorOverlay)->setRanges(aNewRanges);
584             }
585             else
586             {
587                 delete mpCursorOverlay;
588                 mpCursorOverlay = 0;
589             }
590         }
591         else if(Count())
592         {
593             SdrPaintWindow* pCandidate = pView->GetPaintWindow(0);
594             sdr::overlay::OverlayManager* pTargetOverlay = pCandidate->GetOverlayManager();
595 
596             if(pTargetOverlay)
597             {
598                 // #i97672# get the system's hilight color and limit it to the maximum
599                 // allowed luminance. This is needed to react on too bright hilight colors
600                 // which would otherwise vive a bad visualisation
601                 const OutputDevice *pOut = Application::GetDefaultDevice();
602                 Color aHighlight(pOut->GetSettings().GetStyleSettings().GetHighlightColor());
603                 const SvtOptionsDrawinglayer aSvtOptionsDrawinglayer;
604                 const basegfx::BColor aSelection(aHighlight.getBColor());
605                 const double fLuminance(aSelection.luminance());
606                 const double fMaxLum(aSvtOptionsDrawinglayer.GetSelectionMaximumLuminancePercent() / 100.0);
607 
608                 if(fLuminance > fMaxLum)
609                 {
610                     const double fFactor(fMaxLum / fLuminance);
611                     const basegfx::BColor aNewSelection(
612                         aSelection.getRed() * fFactor,
613                         aSelection.getGreen() * fFactor,
614                         aSelection.getBlue() * fFactor);
615 
616                     aHighlight = Color(aNewSelection);
617                 }
618 
619                 // create correct selection
620                 mpCursorOverlay = new sdr::overlay::OverlaySelection(
621                     sdr::overlay::OVERLAY_TRANSPARENT,
622                     aHighlight,
623                     aNewRanges,
624                     true);
625 
626                 pTargetOverlay->add(*mpCursorOverlay);
627             }
628         }
629     }
630 }
631 
632 void SwSelPaintRects::Invalidate( const SwRect& rRect )
633 {
634     sal_uInt16 nSz = Count();
635     if( !nSz )
636         return;
637 
638     SwRegionRects aReg( GetShell()->VisArea() );
639     aReg.Remove( 0, aReg.Count() );
640     aReg.Insert( this, 0 );
641     aReg -= rRect;
642     SwRects::Remove( 0, nSz );
643     SwRects::Insert( &aReg, 0 );
644 
645     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
646     // Liegt die Selection rechts oder unten ausserhalb des sichtbaren
647     // Bereiches, so ist diese nie auf eine Pixel rechts/unten aligned.
648     // Das muss hier erkannt und ggf. das Rechteckt erweitert werden.
649     // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
650     if( GetShell()->bVisPortChgd && 0 != ( nSz = Count()) )
651     {
652         SwSelPaintRects::Get1PixelInLogic( *GetShell() );
653         SwRect* pRect = (SwRect*)GetData();
654         for( ; nSz--; ++pRect )
655         {
656             if( pRect->Right() == GetShell()->aOldRBPos.X() )
657                 pRect->Right( pRect->Right() + nPixPtX );
658             if( pRect->Bottom() == GetShell()->aOldRBPos.Y() )
659                 pRect->Bottom( pRect->Bottom() + nPixPtY );
660         }
661     }
662 }
663 
664 void SwSelPaintRects::Paint( const Rectangle& /*rRect*/ )
665 {
666     // nothing to do with overlays
667 }
668 
669 
670 // check current MapMode of the shell and set possibly the static members.
671 // Optional set the parameters pX, pY
672 void SwSelPaintRects::Get1PixelInLogic( const ViewShell& rSh,
673                                         long* pX, long* pY )
674 {
675     const OutputDevice* pOut = rSh.GetWin();
676     if ( ! pOut )
677         pOut = rSh.GetOut();
678 
679     const MapMode& rMM = pOut->GetMapMode();
680     if( pMapMode->GetMapUnit() != rMM.GetMapUnit() ||
681         pMapMode->GetScaleX() != rMM.GetScaleX() ||
682         pMapMode->GetScaleY() != rMM.GetScaleY() )
683     {
684         *pMapMode = rMM;
685         Size aTmp( 1, 1 );
686         aTmp = pOut->PixelToLogic( aTmp );
687         nPixPtX = aTmp.Width();
688         nPixPtY = aTmp.Height();
689     }
690     if( pX )
691         *pX = nPixPtX;
692     if( pY )
693         *pY = nPixPtY;
694 }
695 
696 
697 /*  */
698 
699 SwShellCrsr::SwShellCrsr( const SwCrsrShell& rCShell, const SwPosition &rPos )
700     : SwCursor(rPos,0,false), SwSelPaintRects(rCShell), pPt(SwPaM::GetPoint())
701 {}
702 
703 
704 SwShellCrsr::SwShellCrsr( const SwCrsrShell& rCShell, const SwPosition &rPos,
705                             const Point& rPtPos, SwPaM* pRing )
706     : SwCursor(rPos, pRing, false), SwSelPaintRects(rCShell), aMkPt(rPtPos),
707     aPtPt(rPtPos), pPt(SwPaM::GetPoint())
708 {}
709 
710 
711 SwShellCrsr::SwShellCrsr( SwShellCrsr& rICrsr )
712     : SwCursor(rICrsr), SwSelPaintRects(*rICrsr.GetShell()),
713     aMkPt(rICrsr.GetMkPos()), aPtPt(rICrsr.GetPtPos()), pPt(SwPaM::GetPoint())
714 {}
715 
716 SwShellCrsr::~SwShellCrsr() {}
717 
718 
719 bool SwShellCrsr::IsReadOnlyAvailable() const
720 {
721     return GetShell()->IsReadOnlyAvailable();
722 }
723 
724 void SwShellCrsr::SetMark()
725 {
726     if( SwPaM::GetPoint() == pPt )
727         aMkPt = aPtPt;
728     else
729         aPtPt = aMkPt;
730     SwPaM::SetMark();
731 }
732 
733 void SwShellCrsr::FillRects()
734 {
735     // die neuen Rechtecke berechnen
736     if( HasMark() &&
737         GetPoint()->nNode.GetNode().IsCntntNode() &&
738         GetPoint()->nNode.GetNode().GetCntntNode()->getLayoutFrm( GetShell()->GetLayout() ) &&
739         (GetMark()->nNode == GetPoint()->nNode ||
740         (GetMark()->nNode.GetNode().IsCntntNode() &&
741          GetMark()->nNode.GetNode().GetCntntNode()->getLayoutFrm( GetShell()->GetLayout() ) )   ))
742         GetShell()->GetLayout()->CalcFrmRects( *this, GetShell()->IsTableMode() );  //swmod 071107//swmod 071225
743 }
744 
745 
746 void SwShellCrsr::Show()
747 {
748     SwShellCrsr * pTmp = this;
749     do {
750         pTmp->SwSelPaintRects::Show();
751     } while( this != ( pTmp = dynamic_cast<SwShellCrsr*>(pTmp->GetNext()) ) );
752 
753     SHOWBOOKMARKS1( 1 )
754     SHOWREDLINES1( 1 )
755 }
756 
757 
758     // Dieses Rechteck wird neu gepaintet, also ist die SSelection in
759     // dem Bereich ungueltig
760 void SwShellCrsr::Invalidate( const SwRect& rRect )
761 {
762     SwShellCrsr * pTmp = this;
763 
764     do
765     {
766         pTmp->SwSelPaintRects::Invalidate( rRect );
767 
768         // --> FME 2005-08-18 #125102#
769         // skip any non SwShellCrsr objects in the ring
770         // (see:SwAutoFormat::DeleteSel()
771         // <--
772         Ring* pTmpRing = pTmp;
773         pTmp = 0;
774         do
775         {
776             pTmpRing = pTmpRing->GetNext();
777             pTmp = dynamic_cast<SwShellCrsr*>(pTmpRing);
778         }
779         while ( !pTmp );
780     }
781     while( this != pTmp );
782 
783     SHOWBOOKMARKS2( 3, &rRect )
784     SHOWREDLINES2( 3, &rRect )
785 }
786 
787 
788 void SwShellCrsr::Hide()
789 {
790     SwShellCrsr * pTmp = this;
791     do {
792         pTmp->SwSelPaintRects::Hide();
793     } while( this != ( pTmp = dynamic_cast<SwShellCrsr*>(pTmp->GetNext()) ) );
794 
795     SHOWBOOKMARKS1( 2 )
796     SHOWREDLINES1( 2 )
797 }
798 
799 SwCursor* SwShellCrsr::Create( SwPaM* pRing ) const
800 {
801     return new SwShellCrsr( *GetShell(), *GetPoint(), GetPtPos(), pRing );
802 }
803 
804 
805 short SwShellCrsr::MaxReplaceArived()
806 {
807     short nRet = RET_YES;
808     Window* pDlg = LAYOUT_THIS_WINDOW (::GetSearchDialog());
809     if( pDlg )
810     {
811         // alte Actions beenden; die Tabellen-Frames werden angelegt und
812         // eine SSelection kann erzeugt werden
813         SvUShorts aArr;
814         sal_uInt16 nActCnt;
815         ViewShell *pShell = const_cast< SwCrsrShell* >( GetShell() ),
816                   *pSh = pShell;
817         do {
818             for( nActCnt = 0; pSh->ActionPend(); ++nActCnt )
819                 pSh->EndAction();
820             aArr.Insert( nActCnt, aArr.Count() );
821         } while( pShell != ( pSh = (ViewShell*)pSh->GetNext() ) );
822 
823         {
824             nRet = QueryBox( pDlg, SW_RES( MSG_COMCORE_ASKSEARCH )).Execute();
825         }
826 
827         for( sal_uInt16 n = 0; n < aArr.Count(); ++n )
828         {
829             for( nActCnt = aArr[n]; nActCnt--; )
830                 pSh->StartAction();
831             pSh = (ViewShell*)pSh->GetNext();
832         }   //swmod 071107//swmod 071225
833     }
834     else
835         // ansonsten aus dem Basic, und dann auf RET_YES schalten
836         nRet = RET_YES;
837 
838     return nRet;
839 }
840 
841 void SwShellCrsr::SaveTblBoxCntnt( const SwPosition* pPos )
842 {
843     ((SwCrsrShell*)GetShell())->SaveTblBoxCntnt( pPos );
844 }
845 
846 sal_Bool SwShellCrsr::UpDown( sal_Bool bUp, sal_uInt16 nCnt )
847 {
848     return SwCursor::UpDown( bUp, nCnt,
849                             &GetPtPos(), GetShell()->GetUpDownX() );
850 }
851 
852 #ifdef DBG_UTIL
853 
854 // JP 05.03.98: zum Testen des UNO-Crsr Verhaltens hier die Implementierung
855 //              am sichtbaren Cursor
856 
857 sal_Bool SwShellCrsr::IsSelOvr( int eFlags )
858 {
859     return SwCursor::IsSelOvr( eFlags );
860 }
861 
862 #endif
863 
864 // sal_True: an die Position kann der Cursor gesetzt werden
865 sal_Bool SwShellCrsr::IsAtValidPos( sal_Bool bPoint ) const
866 {
867     if( GetShell() && ( GetShell()->IsAllProtect() ||
868         GetShell()->GetViewOptions()->IsReadonly() ||
869         ( GetShell()->Imp()->GetDrawView() &&
870           GetShell()->Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() )))
871         return sal_True;
872 
873     return SwCursor::IsAtValidPos( bPoint );
874 }
875 
876 /*  */
877 
878 SwShellTableCrsr::SwShellTableCrsr( const SwCrsrShell& rCrsrSh,
879                                     const SwPosition& rPos )
880     : SwCursor(rPos,0,false), SwShellCrsr(rCrsrSh, rPos), SwTableCursor(rPos)
881 {
882 }
883 
884 SwShellTableCrsr::SwShellTableCrsr( const SwCrsrShell& rCrsrSh,
885                     const SwPosition& rMkPos, const Point& rMkPt,
886                     const SwPosition& rPtPos, const Point& rPtPt )
887     : SwCursor(rPtPos,0,false), SwShellCrsr(rCrsrSh, rPtPos), SwTableCursor(rPtPos)
888 {
889     SetMark();
890     *GetMark() = rMkPos;
891     GetMkPos() = rMkPt;
892     GetPtPos() = rPtPt;
893 }
894 
895 SwShellTableCrsr::~SwShellTableCrsr() {}
896 
897 void SwShellTableCrsr::SetMark()                { SwShellCrsr::SetMark(); }
898 
899 SwCursor* SwShellTableCrsr::Create( SwPaM* pRing ) const
900 {
901     return SwShellCrsr::Create( pRing );
902 }
903 short SwShellTableCrsr::MaxReplaceArived()
904 {
905     return SwShellCrsr::MaxReplaceArived();
906 }
907 void SwShellTableCrsr::SaveTblBoxCntnt( const SwPosition* pPos )
908 {
909     SwShellCrsr::SaveTblBoxCntnt( pPos );
910 }
911 
912 
913 void SwShellTableCrsr::FillRects()
914 {
915     // die neuen Rechtecke berechnen
916     // JP 16.01.98: wenn der Cursor noch "geparkt" ist nichts machen!!
917     if( !aSelBoxes.Count() || bParked ||
918         !GetPoint()->nNode.GetIndex() )
919         return;
920 
921     SwRegionRects aReg( GetShell()->VisArea() );
922     SwNodes& rNds = GetDoc()->GetNodes();
923     for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n )
924     {
925         const SwStartNode* pSttNd = (*(aSelBoxes.GetData() + n ))->GetSttNd();
926         const SwTableNode* pSelTblNd = pSttNd->FindTableNode();
927 
928         SwNodeIndex aIdx( *pSttNd );
929         SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
930 
931         // TABLE IN TABLE
932         // (see also lcl_FindTopLevelTable in unoobj2.cxx for a different
933         // version to do this)
934         const SwTableNode* pCurTblNd = pCNd->FindTableNode();
935         while ( pSelTblNd != pCurTblNd && pCurTblNd )
936         {
937             aIdx = pCurTblNd->EndOfSectionIndex();
938             pCNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
939             pCurTblNd = pCNd->FindTableNode();
940         }
941 
942         if( !pCNd )
943             continue;
944 
945         SwFrm* pFrm = pCNd->getLayoutFrm( GetShell()->GetLayout(), &GetSttPos() );
946         while( pFrm && !pFrm->IsCellFrm() )
947             pFrm = pFrm->GetUpper();
948 
949         ASSERT( pFrm, "Node nicht in einer Tabelle" );
950 
951         while ( pFrm )
952         {
953             if( pFrm && aReg.GetOrigin().IsOver( pFrm->Frm() ) )
954                 aReg -= pFrm->Frm();
955 
956             pFrm = pFrm->GetNextCellLeaf( MAKEPAGE_NONE );
957         }
958     }
959     aReg.Invert();
960     Insert( &aReg, 0 );
961 }
962 
963 
964 // Pruefe, ob sich der SPoint innerhalb der Tabellen-SSelection befindet
965 sal_Bool SwShellTableCrsr::IsInside( const Point& rPt ) const
966 {
967     // die neuen Rechtecke berechnen
968     // JP 16.01.98: wenn der Cursor noch "geparkt" ist nichts machen!!
969     if( !aSelBoxes.Count() || bParked ||
970         !GetPoint()->nNode.GetIndex()  )
971         return sal_False;
972 
973     SwNodes& rNds = GetDoc()->GetNodes();
974     for( sal_uInt16 n = 0; n < aSelBoxes.Count(); ++n )
975     {
976         SwNodeIndex aIdx( *(*(aSelBoxes.GetData() + n ))->GetSttNd() );
977         SwCntntNode* pCNd = rNds.GoNextSection( &aIdx, sal_True, sal_False );
978         if( !pCNd )
979             continue;
980 
981         SwFrm* pFrm = pCNd->getLayoutFrm( GetShell()->GetLayout(), &GetPtPos() );
982         while( pFrm && !pFrm->IsCellFrm() )
983             pFrm = pFrm->GetUpper();
984         ASSERT( pFrm, "Node nicht in einer Tabelle" );
985         if( pFrm && pFrm->Frm().IsInside( rPt ) )
986             return sal_True;
987     }
988     return sal_False;
989 }
990 
991 #ifdef DBG_UTIL
992 
993 // JP 05.03.98: zum Testen des UNO-Crsr Verhaltens hier die Implementierung
994 //              am sichtbaren Cursor
995 sal_Bool SwShellTableCrsr::IsSelOvr( int eFlags )
996 {
997     return SwShellCrsr::IsSelOvr( eFlags );
998 }
999 
1000 #endif
1001 
1002 sal_Bool SwShellTableCrsr::IsAtValidPos( sal_Bool bPoint ) const
1003 {
1004     return SwShellCrsr::IsAtValidPos( bPoint );
1005 }
1006 
1007