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