xref: /trunk/main/sw/source/core/crsr/crsrsh.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 #include <com/sun/star/util/SearchOptions.hpp>
31 #include <com/sun/star/text/XTextRange.hpp>
32 #include <hintids.hxx>
33 #include <svx/svdmodel.hxx>
34 #include <editeng/frmdiritem.hxx>
35 
36 #include <SwSmartTagMgr.hxx>
37 #include <doc.hxx>
38 #include <rootfrm.hxx>
39 #include <pagefrm.hxx>
40 #include <cntfrm.hxx>
41 #include <viewimp.hxx>
42 #include <pam.hxx>
43 #include <swselectionlist.hxx>
44 #include <IBlockCursor.hxx>
45 #include "BlockCursor.hxx"
46 #include <ndtxt.hxx>
47 #include <flyfrm.hxx>
48 #include <dview.hxx>
49 #include <viewopt.hxx>
50 #include <frmtool.hxx>
51 #include <crsrsh.hxx>
52 #include <tabfrm.hxx>
53 #include <txtfrm.hxx>
54 #include <sectfrm.hxx>
55 #include <swtable.hxx>
56 #include <callnk.hxx>
57 #include <viscrs.hxx>
58 #include <section.hxx>
59 #include <docsh.hxx>
60 #include <scriptinfo.hxx>
61 #include <globdoc.hxx>
62 #include <pamtyp.hxx>
63 #include <mdiexp.hxx>           // ...Percent()
64 #include <fmteiro.hxx>
65 #include <wrong.hxx> // SMARTTAGS
66 #include <unotextrange.hxx> // SMARTTAGS
67 #include <vcl/svapp.hxx>
68 #include <numrule.hxx>
69 #include <IGrammarContact.hxx>
70 
71 #include <globals.hrc>
72 
73 #include <comcore.hrc>
74 
75 using namespace com::sun::star;
76 using namespace util;
77 
78 TYPEINIT2(SwCrsrShell,ViewShell,SwModify);
79 
80 
81 // Funktion loescht, alle ueberlappenden Cursor aus einem Cursor-Ring
82 void CheckRange( SwCursor* );
83 
84 //-----------------------------------------------------------------------
85 
86 /*
87  * Ueberpruefe ob der pCurCrsr in einen schon bestehenden Bereich zeigt.
88  * Wenn ja, dann hebe den alten Bereich auf.
89  */
90 
91 
92 void CheckRange( SwCursor* pCurCrsr )
93 {
94     const SwPosition *pStt = pCurCrsr->Start(),
95         *pEnd = pCurCrsr->GetPoint() == pStt ? pCurCrsr->GetMark() : pCurCrsr->GetPoint();
96 
97     SwPaM *pTmpDel = 0,
98           *pTmp = (SwPaM*)pCurCrsr->GetNext();
99 
100     // durchsuche den gesamten Ring
101     while( pTmp != pCurCrsr )
102     {
103         const SwPosition *pTmpStt = pTmp->Start(),
104                         *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
105                                         pTmp->GetMark() : pTmp->GetPoint();
106         if( *pStt <= *pTmpStt )
107         {
108             if( *pEnd > *pTmpStt ||
109                 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
110                 pTmpDel = pTmp;
111         }
112         else
113             if( *pStt < *pTmpEnd )
114                 pTmpDel = pTmp;
115         /*
116          * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
117          * muss der alte Bereich aufgehoben werden.
118          * Beim Vergleich ist darauf zu achten, das SPoint nicht mehr zum
119          * Bereich gehoert !
120          */
121         pTmp = (SwPaM*)pTmp->GetNext();
122         if( pTmpDel )
123         {
124             delete pTmpDel;         // hebe alten Bereich auf
125             pTmpDel = 0;
126         }
127     }
128 }
129 
130 // -------------- Methoden von der SwCrsrShell -------------
131 
132 SwPaM * SwCrsrShell::CreateCrsr()
133 {
134     // Innerhalb der Tabellen-SSelection keinen neuen Crsr anlegen
135     ASSERT( !IsTableMode(), "in Tabellen SSelection" );
136 
137     // neuen Cursor als Kopie vom akt. und in den Ring aufnehmen
138     // Verkettung zeigt immer auf den zuerst erzeugten, also vorwaerts
139     SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
140 
141     // hier den akt. Pam nur logisch Hiden, weil sonst die Invertierung
142     // vom kopierten Pam aufgehoben wird !!
143 
144     // #i75172# to be able to make a complete content swap, i moved this to a method
145     // pNew->Insert( pCurCrsr, 0 );
146     // pCurCrsr->Remove( 0, pCurCrsr->Count() );
147     pNew->swapContent(*pCurCrsr);
148 
149     pCurCrsr->DeleteMark();
150 
151     UpdateCrsr( SwCrsrShell::SCROLLWIN );
152 //  return pCurCrsr;
153     return pNew;
154 }
155 
156 // loesche den aktuellen Cursor und der folgende wird zum Aktuellen
157 
158 
159 sal_Bool SwCrsrShell::DestroyCrsr()
160 {
161     // Innerhalb der Tabellen-SSelection keinen neuen Crsr loeschen
162     ASSERT( !IsTableMode(), "in Tabellen SSelection" );
163 
164     // ist ueberhaupt ein naechtser vorhanden ?
165     if(pCurCrsr->GetNext() == pCurCrsr)
166         return sal_False;
167 
168     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
169     SwCursor* pNextCrsr = (SwCursor*)pCurCrsr->GetNext();
170     delete pCurCrsr;
171     pCurCrsr = dynamic_cast<SwShellCrsr*>(pNextCrsr);
172     UpdateCrsr();
173     return sal_True;
174 }
175 
176 
177 SwPaM & SwCrsrShell::CreateNewShellCursor()
178 {
179     if (HasSelection())
180     {
181         (void) CreateCrsr(); // n.b. returns old cursor
182     }
183     return *GetCrsr();
184 }
185 
186 SwPaM & SwCrsrShell::GetCurrentShellCursor()
187 {
188     return *GetCrsr();
189 }
190 
191 
192 // gebe den aktuellen zurueck
193 
194 SwPaM* SwCrsrShell::GetCrsr( sal_Bool bMakeTblCrsr ) const
195 {
196     if( pTblCrsr )
197     {
198         if( bMakeTblCrsr && pTblCrsr->IsCrsrMovedUpdt() )
199         {
200             // geparkte Cursor werden nicht wieder erzeugt
201             const SwCntntNode* pCNd;
202             if( pTblCrsr->GetPoint()->nNode.GetIndex() &&
203                 pTblCrsr->GetMark()->nNode.GetIndex() &&
204                 0 != ( pCNd = pTblCrsr->GetCntntNode() ) && pCNd->getLayoutFrm( GetLayout() ) &&
205                 0 != ( pCNd = pTblCrsr->GetCntntNode(sal_False) ) && pCNd->getLayoutFrm( GetLayout() ) )
206             {
207                 SwShellTableCrsr* pTC = (SwShellTableCrsr*)pTblCrsr;
208                 GetLayout()->MakeTblCrsrs( *pTC );
209             }
210         }
211 
212         if( pTblCrsr->IsChgd() )
213         {
214             const_cast<SwCrsrShell*>(this)->pCurCrsr =
215                 dynamic_cast<SwShellCrsr*>(pTblCrsr->MakeBoxSels( pCurCrsr ));
216         }
217     }
218     return pCurCrsr;
219 }
220 
221 
222 void SwCrsrShell::StartAction()
223 {
224     if( !ActionPend() )
225     {
226         // fuer das Update des Ribbon-Bars merken
227         const SwNode& rNd = pCurCrsr->GetPoint()->nNode.GetNode();
228         nAktNode = rNd.GetIndex();
229         nAktCntnt = pCurCrsr->GetPoint()->nContent.GetIndex();
230         nAktNdTyp = rNd.GetNodeType();
231         bAktSelection = *pCurCrsr->GetPoint() != *pCurCrsr->GetMark();
232         if( ND_TEXTNODE & nAktNdTyp )
233             nLeftFrmPos = SwCallLink::getLayoutFrm( GetLayout(), (SwTxtNode&)rNd, nAktCntnt, sal_True );
234         else
235             nLeftFrmPos = 0;
236     }
237     ViewShell::StartAction();           // zur ViewShell
238 }
239 
240 
241 void SwCrsrShell::EndAction( const sal_Bool bIdleEnd )
242 {
243 /*
244 //OS: Wird z.B. eine Basic-Action im Hintergrund ausgefuehrt, geht es so nicht
245     if( !bHasFocus )
246     {
247         // hat die Shell nicht den Focus, dann nur das EndAction an
248         // die ViewShell weitergeben.
249         ViewShell::EndAction( bIdleEnd );
250         return;
251     }
252 */
253 
254     sal_Bool bVis = bSVCrsrVis;
255 
256     // Idle-Formatierung ?
257     if( bIdleEnd && Imp()->GetRegion() )
258     {
259         pCurCrsr->Hide();
260 
261 #ifdef SHOW_IDLE_REGION
262 if( GetWin() )
263 {
264     GetWin()->Push();
265     GetWin()->ChangePen( Pen( Color( COL_YELLOW )));
266     for( sal_uInt16 n = 0; n < aPntReg.Count(); ++n )
267     {
268         SwRect aIRect( aPntReg[n] );
269         GetWin()->DrawRect( aIRect.SVRect() );
270     }
271     GetWin()->Pop();
272 }
273 #endif
274 
275     }
276 
277     // vor der letzten Action alle invaliden Numerierungen updaten
278     if( 1 == nStartAction )
279         GetDoc()->UpdateNumRule();
280 
281     // Task: 76923: dont show the cursor in the ViewShell::EndAction() - call.
282     //              Only the UpdateCrsr shows the cursor.
283     sal_Bool bSavSVCrsrVis = bSVCrsrVis;
284     bSVCrsrVis = sal_False;
285 
286     ViewShell::EndAction( bIdleEnd );   //der ViewShell den Vortritt lassen
287 
288     bSVCrsrVis = bSavSVCrsrVis;
289 
290     if( ActionPend() )
291     {
292         if( bVis )    // auch SV-Cursor wieder anzeigen
293             pVisCrsr->Show();
294 
295         // falls noch ein ChgCall vorhanden ist und nur noch die Basic
296         // Klammerung vorhanden ist, dann rufe ihn. Dadurch wird die interne
297         // mit der Basic-Klammerung entkoppelt; die Shells werden umgeschaltet
298         if( !BasicActionPend() )
299         {
300             //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction
301             //              der Cursor geupdatet werden; um z.B. den
302             //              TabellenCursor zu erzeugen. Im UpdateCrsr wird
303             //              das jetzt beruecksichtigt!
304             UpdateCrsr( SwCrsrShell::CHKRANGE, bIdleEnd );
305 
306             {
307                 // Crsr-Moves ueberwachen, evt. Link callen
308                 // der DTOR ist das interressante!!
309                 SwCallLink aLk( *this, nAktNode, nAktCntnt, (sal_uInt8)nAktNdTyp,
310                                 nLeftFrmPos, bAktSelection );
311 
312             }
313             if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
314             {
315                 aChgLnk.Call( this );
316                 bChgCallFlag = sal_False;       // Flag zuruecksetzen
317             }
318         }
319         return;
320     }
321 
322     sal_uInt16 nParm = SwCrsrShell::CHKRANGE;
323     if ( !bIdleEnd )
324         nParm |= SwCrsrShell::SCROLLWIN;
325 //    if( !IsViewLocked() )
326     UpdateCrsr( nParm, bIdleEnd );      // Cursor-Aenderungen anzeigen
327 
328     {
329         SwCallLink aLk( *this );        // Crsr-Moves ueberwachen,
330         aLk.nNode = nAktNode;           // evt. Link callen
331         aLk.nNdTyp = (sal_uInt8)nAktNdTyp;
332         aLk.nCntnt = nAktCntnt;
333         aLk.nLeftFrmPos = nLeftFrmPos;
334 
335         if( !nCrsrMove ||
336             ( 1 == nCrsrMove && bInCMvVisportChgd ) )
337             ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );    // Cursor & Selektionen wieder anzeigen
338     }
339     // falls noch ein ChgCall vorhanden ist, dann rufe ihn
340     if( bCallChgLnk && bChgCallFlag && aChgLnk.IsSet() )
341     {
342         aChgLnk.Call( this );
343         bChgCallFlag = sal_False;       // Flag zuruecksetzen
344     }
345 }
346 
347 
348 #if defined(DBG_UTIL)
349 
350 void SwCrsrShell::SttCrsrMove()
351 {
352     ASSERT( nCrsrMove < USHRT_MAX, "To many nested CrsrMoves." );
353     ++nCrsrMove;
354     StartAction();
355 }
356 
357 void SwCrsrShell::EndCrsrMove( const sal_Bool bIdleEnd )
358 {
359     ASSERT( nCrsrMove, "EndCrsrMove() ohne SttCrsrMove()." );
360     EndAction( bIdleEnd );
361     if( !--nCrsrMove )
362         bInCMvVisportChgd = sal_False;
363 }
364 
365 #endif
366 
367 
368 sal_Bool SwCrsrShell::LeftRight( sal_Bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
369                                  sal_Bool bVisualAllowed )
370 {
371     if( IsTableMode() )
372         return bLeft ? GoPrevCell() : GoNextCell();
373 
374     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
375     sal_Bool bRet = sal_False;
376 
377     // #i27615# Handle cursor in front of label.
378     const SwTxtNode* pTxtNd = 0;
379 
380     if( pBlockCrsr )
381         pBlockCrsr->clearPoints();
382 
383     //
384     // 1. CASE: Cursor is in front of label. A move to the right
385     // will simply reset the bInFrontOfLabel flag:
386     //
387     SwShellCrsr* pShellCrsr = getShellCrsr( true );
388     if ( !bLeft && pShellCrsr->IsInFrontOfLabel() )
389     {
390         SetInFrontOfLabel( sal_False );
391         bRet = sal_True;
392     }
393     //
394     // 2. CASE: Cursor is at beginning of numbered paragraph. A move
395     // to the left will simply set the bInFrontOfLabel flag:
396     //
397     else if ( bLeft && 0 == pShellCrsr->GetPoint()->nContent.GetIndex() &&
398              !pShellCrsr->IsInFrontOfLabel() && !pShellCrsr->HasMark() &&
399              0 != ( pTxtNd = pShellCrsr->GetNode()->GetTxtNode() ) &&
400              pTxtNd->HasVisibleNumberingOrBullet() )
401     {
402         SetInFrontOfLabel( sal_True );
403         bRet = sal_True;
404     }
405     //
406     // 3. CASE: Regular cursor move. Reset the bInFrontOfLabel flag:
407     //
408     else
409     {
410         const sal_Bool bSkipHidden = !GetViewOptions()->IsShowHiddenChar();
411         // --> OD 2009-12-30 #i107447#
412         // To avoid loop the reset of <bInFrontOfLabel> flag is no longer
413         // reflected in the return value <bRet>.
414         const bool bResetOfInFrontOfLabel = SetInFrontOfLabel( sal_False );
415         bRet = pShellCrsr->LeftRight( bLeft, nCnt, nMode, bVisualAllowed,
416                                       bSkipHidden, !IsOverwriteCrsr() );
417         if ( !bRet && bLeft && bResetOfInFrontOfLabel )
418         {
419             // undo reset of <bInFrontOfLabel> flag
420             SetInFrontOfLabel( sal_True );
421         }
422         // <--
423     }
424 
425     if( bRet )
426     {
427         UpdateCrsr();
428     }
429     return bRet;
430 }
431 
432 // --> OD 2008-04-02 #refactorlists#
433 void SwCrsrShell::MarkListLevel( const String& sListId,
434                                  const int nListLevel )
435 {
436     if ( sListId != sMarkedListId ||
437          nListLevel != nMarkedListLevel)
438     {
439         if ( sMarkedListId.Len() > 0 )
440             pDoc->MarkListLevel( sMarkedListId, nMarkedListLevel, sal_False );
441 
442         if ( sListId.Len() > 0 )
443         {
444             pDoc->MarkListLevel( sListId, nListLevel, sal_True );
445         }
446 
447         sMarkedListId = sListId;
448         nMarkedListLevel = nListLevel;
449     }
450 }
451 
452 void SwCrsrShell::UpdateMarkedListLevel()
453 {
454     SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
455 
456     if ( pTxtNd )
457     {
458         if ( !pTxtNd->IsNumbered() )
459         {
460             pCurCrsr->_SetInFrontOfLabel( sal_False );
461             MarkListLevel( String(), 0 );
462         }
463         else if ( pCurCrsr->IsInFrontOfLabel() )
464         {
465             if ( pTxtNd->IsInList() )
466             {
467                 ASSERT( pTxtNd->GetActualListLevel() >= 0 &&
468                         pTxtNd->GetActualListLevel() < MAXLEVEL, "Which level?")
469                 MarkListLevel( pTxtNd->GetListId(),
470                                pTxtNd->GetActualListLevel() );
471             }
472         }
473         else
474         {
475             MarkListLevel( String(), 0 );
476         }
477     }
478 }
479 // <--
480 
481 sal_Bool SwCrsrShell::UpDown( sal_Bool bUp, sal_uInt16 nCnt )
482 {
483     SET_CURR_SHELL( this );
484     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
485 
486     sal_Bool bTableMode = IsTableMode();
487     SwShellCrsr* pTmpCrsr = getShellCrsr( true );
488 
489     sal_Bool bRet = pTmpCrsr->UpDown( bUp, nCnt );
490     // --> FME 2005-01-10 #i40019# UpDown should always reset the
491     // bInFrontOfLabel flag:
492     bRet = SetInFrontOfLabel(sal_False) || bRet;
493     // <--
494 
495     if( pBlockCrsr )
496         pBlockCrsr->clearPoints();
497 
498     if( bRet )
499     {
500         eMvState = MV_UPDOWN;       // Status fuers Crsr-Travelling - GetCrsrOfst
501         if( !ActionPend() )
502         {
503             CrsrFlag eUpdtMode = SwCrsrShell::SCROLLWIN;
504             if( !bTableMode )
505                 eUpdtMode = (CrsrFlag) (eUpdtMode
506                             | SwCrsrShell::UPDOWN | SwCrsrShell::CHKRANGE);
507             UpdateCrsr( static_cast<sal_uInt16>(eUpdtMode) );
508         }
509     }
510     return bRet;
511 }
512 
513 
514 sal_Bool SwCrsrShell::LRMargin( sal_Bool bLeft, sal_Bool bAPI)
515 {
516     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
517     SET_CURR_SHELL( this );
518     eMvState = MV_LEFTMARGIN;       // Status fuers Crsr-Travelling - GetCrsrOfst
519 
520     const sal_Bool bTableMode = IsTableMode();
521     SwShellCrsr* pTmpCrsr = getShellCrsr( true );
522 
523     if( pBlockCrsr )
524         pBlockCrsr->clearPoints();
525 
526     const sal_Bool bWasAtLM =
527             ( 0 == _GetCrsr()->GetPoint()->nContent.GetIndex() );
528 
529     sal_Bool bRet = pTmpCrsr->LeftRightMargin( bLeft, bAPI );
530 
531     if ( bLeft && !bTableMode && bRet && bWasAtLM && !_GetCrsr()->HasMark() )
532     {
533         const SwTxtNode * pTxtNd = _GetCrsr()->GetNode()->GetTxtNode();
534         if ( pTxtNd && pTxtNd->HasVisibleNumberingOrBullet() )
535             SetInFrontOfLabel( sal_True );
536     }
537     else if ( !bLeft )
538     {
539         bRet = SetInFrontOfLabel( sal_False ) || bRet;
540     }
541 
542     if( bRet )
543     {
544         UpdateCrsr();
545     }
546     return bRet;
547 }
548 
549 sal_Bool SwCrsrShell::IsAtLRMargin( sal_Bool bLeft, sal_Bool bAPI ) const
550 {
551     const SwShellCrsr* pTmpCrsr = getShellCrsr( true );
552     return pTmpCrsr->IsAtLeftRightMargin( bLeft, bAPI );
553 }
554 
555 
556 sal_Bool SwCrsrShell::SttEndDoc( sal_Bool bStt )
557 {
558     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
559 
560     SwShellCrsr* pTmpCrsr = pBlockCrsr ? &pBlockCrsr->getShellCrsr() : pCurCrsr;
561     sal_Bool bRet = pTmpCrsr->SttEndDoc( bStt );
562     if( bRet )
563     {
564         if( bStt )
565             pTmpCrsr->GetPtPos().Y() = 0;       // expl. 0 setzen (TabellenHeader)
566         if( pBlockCrsr )
567         {
568             pBlockCrsr->clearPoints();
569             RefreshBlockCursor();
570         }
571 
572         UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
573     }
574     return bRet;
575 }
576 
577 void SwCrsrShell::ExtendedSelectAll()
578 {
579     SwNodes& rNodes = GetDoc()->GetNodes();
580     SwPosition* pPos = pCurCrsr->GetPoint();
581     pPos->nNode = rNodes.GetEndOfPostIts();
582     pPos->nContent.Assign( rNodes.GoNext( &pPos->nNode ), 0 );
583     pPos = pCurCrsr->GetMark();
584     pPos->nNode = rNodes.GetEndOfContent();
585     SwCntntNode* pCNd = rNodes.GoPrevious( &pPos->nNode );
586     pPos->nContent.Assign( pCNd, pCNd ? pCNd->Len() : 0 );
587 }
588 
589 sal_Bool SwCrsrShell::MovePage( SwWhichPage fnWhichPage, SwPosPage fnPosPage )
590 {
591     sal_Bool bRet = sal_False;
592 
593     // Springe beim Selektieren nie ueber Section-Grenzen !!
594     if( !pCurCrsr->HasMark() || !pCurCrsr->IsNoCntnt() )
595     {
596         SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
597         SET_CURR_SHELL( this );
598 
599         SwCrsrSaveState aSaveState( *pCurCrsr );
600         Point& rPt = pCurCrsr->GetPtPos();
601         SwCntntFrm * pFrm = pCurCrsr->GetCntntNode()->
602                             getLayoutFrm( GetLayout(), &rPt, pCurCrsr->GetPoint(), sal_False );
603         if( pFrm && sal_True == ( bRet = GetFrmInPage( pFrm, fnWhichPage,
604                                                 fnPosPage, pCurCrsr )  ) &&
605             !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
606                                  nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ))
607             UpdateCrsr();
608         else
609             bRet = sal_False;
610     }
611     return bRet;
612 }
613 
614 
615 sal_Bool SwCrsrShell::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
616 {
617     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
618     SwCursor* pTmpCrsr = getShellCrsr( true );
619     sal_Bool bRet = pTmpCrsr->MovePara( fnWhichPara, fnPosPara );
620     if( bRet )
621         UpdateCrsr();
622     return bRet;
623 }
624 
625 
626 sal_Bool SwCrsrShell::MoveSection( SwWhichSection fnWhichSect,
627                                 SwPosSection fnPosSect)
628 {
629     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
630     SwCursor* pTmpCrsr = getShellCrsr( true );
631     sal_Bool bRet = pTmpCrsr->MoveSection( fnWhichSect, fnPosSect );
632     if( bRet )
633         UpdateCrsr();
634     return bRet;
635 
636 }
637 
638 
639 // Positionieren des Cursors
640 
641 
642 SwFrm* lcl_IsInHeaderFooter( const SwNodeIndex& rIdx, Point& rPt )
643 {
644     SwFrm* pFrm = 0;
645     SwCntntNode* pCNd = rIdx.GetNode().GetCntntNode();
646     if( pCNd )
647     {
648         pFrm = pCNd->getLayoutFrm( pCNd->GetDoc()->GetCurrentLayout(), &rPt, 0, sal_False )->GetUpper();
649         while( pFrm && !pFrm->IsHeaderFrm() && !pFrm->IsFooterFrm() )
650             pFrm = pFrm->IsFlyFrm() ? ((SwFlyFrm*)pFrm)->AnchorFrm()
651                                     : pFrm->GetUpper();
652     }
653     return pFrm;
654 }
655 
656 sal_Bool SwCrsrShell::IsInHeaderFooter( sal_Bool* pbInHeader ) const
657 {
658     Point aPt;
659     SwFrm* pFrm = ::lcl_IsInHeaderFooter( pCurCrsr->GetPoint()->nNode, aPt );
660     if( pFrm && pbInHeader )
661         *pbInHeader = pFrm->IsHeaderFrm();
662     return 0 != pFrm;
663 }
664 
665 int SwCrsrShell::SetCrsr( const Point &rLPt, sal_Bool bOnlyText, bool bBlock )
666 {
667     SET_CURR_SHELL( this );
668 
669     SwShellCrsr* pCrsr = getShellCrsr( bBlock );
670     SwPosition aPos( *pCrsr->GetPoint() );
671     Point aPt( rLPt );
672     Point & rAktCrsrPt = pCrsr->GetPtPos();
673     SwCrsrMoveState aTmpState( IsTableMode() ? MV_TBLSEL :
674                                     bOnlyText ?  MV_SETONLYTEXT : MV_NONE );
675     aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
676 
677     SwTxtNode * pTxtNd = pCrsr->GetNode()->GetTxtNode();
678 
679     if ( pTxtNd && !IsTableMode() &&
680         // --> FME 2004-11-25 #i37515# No bInFrontOfLabel during selection
681         !pCrsr->HasMark() &&
682         // <--
683         pTxtNd->HasVisibleNumberingOrBullet() )
684     {
685         aTmpState.bInFrontOfLabel = sal_True; // #i27615#
686     }
687     else
688     {
689         aTmpState.bInFrontOfLabel = sal_False;
690     }
691 
692     int bRet = CRSR_POSOLD |
693                 ( GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState )
694                     ? 0 : CRSR_POSCHG );
695 
696     const bool bOldInFrontOfLabel = IsInFrontOfLabel();
697     const bool bNewInFrontOfLabel = aTmpState.bInFrontOfLabel;
698 
699     pCrsr->SetCrsrBidiLevel( aTmpState.nCursorBidiLevel );
700 
701     if( MV_RIGHTMARGIN == aTmpState.eState )
702         eMvState = MV_RIGHTMARGIN;
703     // steht neu Pos im Header/Footer ?
704     SwFrm* pFrm = lcl_IsInHeaderFooter( aPos.nNode, aPt );
705     if( IsTableMode() && !pFrm && aPos.nNode.GetNode().StartOfSectionNode() ==
706         pCrsr->GetPoint()->nNode.GetNode().StartOfSectionNode() )
707         // gleiche Tabellenzelle und nicht im Header/Footer
708         // -> zurueck
709         return bRet;
710 
711     if( pBlockCrsr && bBlock )
712     {
713         pBlockCrsr->setEndPoint( rLPt );
714         if( !pCrsr->HasMark() )
715             pBlockCrsr->setStartPoint( rLPt );
716         else if( !pBlockCrsr->getStartPoint() )
717             pBlockCrsr->setStartPoint( pCrsr->GetMkPos() );
718     }
719     if( !pCrsr->HasMark() )
720     {
721         // steht an der gleichen Position und wenn im Header/Footer,
722         // dann im gleichen
723         if( aPos == *pCrsr->GetPoint() &&
724             bOldInFrontOfLabel == bNewInFrontOfLabel )
725         {
726             if( pFrm )
727             {
728                 if( pFrm->Frm().IsInside( rAktCrsrPt ))
729                     return bRet;
730             }
731             else if( aPos.nNode.GetNode().IsCntntNode() )
732             {
733                 // im gleichen Frame gelandet?
734                 SwFrm* pOld = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
735                                 GetLayout(), &aCharRect.Pos(), 0, sal_False );
736                 SwFrm* pNew = ((SwCntntNode&)aPos.nNode.GetNode()).getLayoutFrm(
737                                 GetLayout(), &aPt, 0, sal_False );
738                 if( pNew == pOld )
739                     return bRet;
740             }
741         }
742     }
743     else
744     {
745         // SSelection ueber nicht erlaubte Sections oder wenn im Header/Footer
746         // dann in verschiedene
747         if( !CheckNodesRange( aPos.nNode, pCrsr->GetMark()->nNode, sal_True )
748             || ( pFrm && !pFrm->Frm().IsInside( pCrsr->GetMkPos() ) ))
749             return bRet;
750 
751         // steht an der gleichen Position und nicht im Header/Footer
752         if( aPos == *pCrsr->GetPoint() )
753             return bRet;
754     }
755 
756     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
757     SwCrsrSaveState aSaveState( *pCrsr );
758 
759     *pCrsr->GetPoint() = aPos;
760     rAktCrsrPt = aPt;
761 
762     // --> FME 2005-01-31 #i41424# Only update the marked number levels if necessary
763     // Force update of marked number levels if necessary.
764     if ( bNewInFrontOfLabel || bOldInFrontOfLabel )
765         pCurCrsr->_SetInFrontOfLabel( !bNewInFrontOfLabel );
766     SetInFrontOfLabel( bNewInFrontOfLabel );
767     // <--
768 
769     if( !pCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
770     {
771         sal_uInt16 nFlag = SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE;
772         UpdateCrsr( nFlag );
773         bRet &= ~CRSR_POSOLD;
774     }
775     else if( bOnlyText && !pCurCrsr->HasMark() )
776     {
777         if( FindValidCntntNode( bOnlyText ) )
778         {
779             // Cursor in einen gueltigen Content stellen
780             if( aPos == *pCrsr->GetPoint() )
781                 bRet = CRSR_POSOLD;
782             else
783             {
784                 UpdateCrsr( SwCrsrShell::SCROLLWIN | SwCrsrShell::CHKRANGE );
785                 bRet &= ~CRSR_POSOLD;
786             }
787         }
788         else
789         {
790             // es gibt keinen gueltigen Inhalt -> Cursor verstecken
791             pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
792             eMvState = MV_NONE;     // Status fuers Crsr-Travelling
793             bAllProtect = sal_True;
794             if( GetDoc()->GetDocShell() )
795             {
796                 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
797                 CallChgLnk();           // UI bescheid sagen!
798             }
799         }
800     }
801 
802     return bRet;
803 }
804 
805 
806 void SwCrsrShell::TblCrsrToCursor()
807 {
808     ASSERT( pTblCrsr, "TblCrsrToCursor: Why?" );
809     delete pTblCrsr, pTblCrsr = 0;
810 }
811 
812 void SwCrsrShell::BlockCrsrToCrsr()
813 {
814     ASSERT( pBlockCrsr, "BlockCrsrToCrsr: Why?" );
815     if( pBlockCrsr && !HasSelection() )
816     {
817         SwPaM& rPam = pBlockCrsr->getShellCrsr();
818         pCurCrsr->SetMark();
819         *pCurCrsr->GetPoint() = *rPam.GetPoint();
820         if( rPam.HasMark() )
821             *pCurCrsr->GetMark() = *rPam.GetMark();
822         else
823             pCurCrsr->DeleteMark();
824     }
825     delete pBlockCrsr, pBlockCrsr = 0;
826 }
827 
828 void SwCrsrShell::CrsrToBlockCrsr()
829 {
830     if( !pBlockCrsr )
831     {
832         SwPosition aPos( *pCurCrsr->GetPoint() );
833         pBlockCrsr = createBlockCursor( *this, aPos );
834         SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
835         rBlock.GetPtPos() = pCurCrsr->GetPtPos();
836         if( pCurCrsr->HasMark() )
837         {
838             rBlock.SetMark();
839             *rBlock.GetMark() = *pCurCrsr->GetMark();
840             rBlock.GetMkPos() = pCurCrsr->GetMkPos();
841         }
842     }
843     pBlockCrsr->clearPoints();
844     RefreshBlockCursor();
845 }
846 
847 void SwCrsrShell::ClearMark()
848 {
849     // ist ueberhaupt ein GetMark gesetzt ?
850     if( pTblCrsr )
851     {
852         while( pCurCrsr->GetNext() != pCurCrsr )
853             delete pCurCrsr->GetNext();
854         pTblCrsr->DeleteMark();
855 
856         if( pCurCrsr->HasMark() )
857         {
858             // falls doch nicht alle Indizies richtig verschoben werden
859             //  (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
860             //  Mark aufs Nodes-Array setzen
861             SwPosition& rPos = *pCurCrsr->GetMark();
862             rPos.nNode.Assign( pDoc->GetNodes(), 0 );
863             rPos.nContent.Assign( 0, 0 );
864             pCurCrsr->DeleteMark();
865         }
866 
867         *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
868         pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
869         delete pTblCrsr, pTblCrsr = 0;
870         pCurCrsr->SwSelPaintRects::Show();
871     }
872     else
873     {
874         if( !pCurCrsr->HasMark() )
875             return;
876         // falls doch nicht alle Indizies richtig verschoben werden
877         //  (z.B.: Kopf-/Fusszeile loeschen) den Content-Anteil vom
878         //  Mark aufs Nodes-Array setzen
879         SwPosition& rPos = *pCurCrsr->GetMark();
880         rPos.nNode.Assign( pDoc->GetNodes(), 0 );
881         rPos.nContent.Assign( 0, 0 );
882         pCurCrsr->DeleteMark();
883         if( !nCrsrMove )
884             pCurCrsr->SwSelPaintRects::Show();
885     }
886 }
887 
888 
889 void SwCrsrShell::NormalizePam(sal_Bool bPointFirst)
890 {
891     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
892     pCurCrsr->Normalize(bPointFirst);
893 }
894 
895 void SwCrsrShell::SwapPam()
896 {
897     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
898     pCurCrsr->Exchange();
899 }
900 
901 
902 // suche innerhalb der Selektierten-Bereiche nach einer Selektion, die
903 // den angebenen SPoint umschliesst
904 // Ist das Flag bTstOnly gesetzt, dann wird nur getestet, ob dort eine
905 // SSelection besteht; des akt. Cursr wird nicht umgesetzt!
906 // Ansonsten wird er auf die gewaehlte SSelection gesetzt.
907 
908 
909 sal_Bool SwCrsrShell::ChgCurrPam( const Point & rPt,
910                               sal_Bool bTstOnly, sal_Bool bTstHit )
911 {
912     SET_CURR_SHELL( this );
913 
914     // Pruefe ob der SPoint in einer Tabellen-Selektion liegt
915     if( bTstOnly && pTblCrsr )
916         return pTblCrsr->IsInside( rPt );
917 
918     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
919     // Suche die Position rPt im Dokument
920     SwPosition aPtPos( *pCurCrsr->GetPoint() );
921     Point aPt( rPt );
922 
923     SwCrsrMoveState aTmpState( MV_NONE );
924     aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
925     if ( !GetLayout()->GetCrsrOfst( &aPtPos, aPt, &aTmpState ) && bTstHit )
926         return sal_False;
927 
928     // suche in allen Selektionen nach dieser Position
929     SwShellCrsr* pCmp = (SwShellCrsr*)pCurCrsr;        // sicher den Pointer auf Cursor
930     do {
931         if( pCmp->HasMark() &&
932             *pCmp->Start() <= aPtPos && *pCmp->End() > aPtPos )
933         {
934             if( bTstOnly || pCurCrsr == pCmp )     // ist der aktuelle.
935                 return sal_True;                       // return ohne Update
936 
937             pCurCrsr = pCmp;
938             UpdateCrsr();     // Cursor steht schon richtig
939             return sal_True;
940         }
941     } while( pCurCrsr !=
942         ( pCmp = dynamic_cast<SwShellCrsr*>(pCmp->GetNext()) ) );
943     return sal_False;
944 }
945 
946 
947 void SwCrsrShell::KillPams()
948 {
949     // keiner zum loeschen vorhanden?
950     if( !pTblCrsr && !pBlockCrsr && pCurCrsr->GetNext() == pCurCrsr )
951         return;
952 
953     while( pCurCrsr->GetNext() != pCurCrsr )
954         delete pCurCrsr->GetNext();
955     pCurCrsr->SetColumnSelection( false );
956 
957     if( pTblCrsr )
958     {
959         // Cursor Ring loeschen
960         pCurCrsr->DeleteMark();
961         *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
962         pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
963         delete pTblCrsr;
964         pTblCrsr = 0;
965     }
966     else if( pBlockCrsr )
967     {
968         // delete the ring of cursors
969         pCurCrsr->DeleteMark();
970         SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
971         *pCurCrsr->GetPoint() = *rBlock.GetPoint();
972         pCurCrsr->GetPtPos() = rBlock.GetPtPos();
973         rBlock.DeleteMark();
974         pBlockCrsr->clearPoints();
975     }
976     UpdateCrsr( SwCrsrShell::SCROLLWIN );
977 }
978 
979 
980 int SwCrsrShell::CompareCursor( CrsrCompareType eType ) const
981 {
982     int nRet = 0;
983     const SwPosition *pFirst = 0, *pSecond = 0;
984     const SwPaM *pCur = GetCrsr(), *pStk = pCrsrStk;
985     if( CurrPtCurrMk != eType && pStk )
986     {
987         switch ( eType)
988         {
989         case StackPtStackMk:
990             pFirst = pStk->GetPoint();
991             pSecond = pStk->GetMark();
992             break;
993         case StackPtCurrPt:
994             pFirst = pStk->GetPoint();
995             pSecond = pCur->GetPoint();
996             break;
997         case StackPtCurrMk:
998             pFirst = pStk->GetPoint();
999             pSecond = pCur->GetMark();
1000             break;
1001         case StackMkCurrPt:
1002             pFirst = pStk->GetMark();
1003             pSecond = pCur->GetPoint();
1004             break;
1005         case StackMkCurrMk:
1006             pFirst = pStk->GetMark();
1007             pSecond = pStk->GetMark();
1008             break;
1009         case CurrPtCurrMk:
1010             pFirst = pCur->GetPoint();
1011             pSecond = pCur->GetMark();
1012             break;
1013         }
1014     }
1015     if( !pFirst || !pSecond )
1016         nRet = INT_MAX;
1017     else if( *pFirst < *pSecond )
1018         nRet = -1;
1019     else if( *pFirst == *pSecond )
1020         nRet = 0;
1021     else
1022         nRet = 1;
1023     return nRet;
1024 }
1025 
1026 
1027 sal_Bool SwCrsrShell::IsSttPara() const
1028 {   return( pCurCrsr->GetPoint()->nContent == 0 ? sal_True : sal_False ); }
1029 
1030 
1031 sal_Bool SwCrsrShell::IsEndPara() const
1032 {   return( pCurCrsr->GetPoint()->nContent == pCurCrsr->GetCntntNode()->Len() ? sal_True : sal_False ); }
1033 
1034 
1035 sal_Bool SwCrsrShell::IsInFrontOfLabel() const
1036 {
1037     return pCurCrsr->IsInFrontOfLabel();
1038 }
1039 
1040 bool SwCrsrShell::SetInFrontOfLabel( sal_Bool bNew )
1041 {
1042     if ( bNew != IsInFrontOfLabel() )
1043     {
1044         pCurCrsr->_SetInFrontOfLabel( bNew );
1045         UpdateMarkedListLevel();
1046         return true;
1047     }
1048     return false;
1049 }
1050 
1051 sal_Bool SwCrsrShell::GotoPage( sal_uInt16 nPage )
1052 {
1053     SET_CURR_SHELL( this );
1054     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
1055     SwCrsrSaveState aSaveState( *pCurCrsr );
1056     sal_Bool bRet = GetLayout()->SetCurrPage( pCurCrsr, nPage ) &&
1057                     !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
1058                                          nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
1059     if( bRet )
1060         UpdateCrsr(SwCrsrShell::SCROLLWIN|SwCrsrShell::CHKRANGE|SwCrsrShell::READONLY);
1061     return bRet;
1062 }
1063 
1064 
1065 void SwCrsrShell::GetPageNum( sal_uInt16 &rnPhyNum, sal_uInt16 &rnVirtNum,
1066                               sal_Bool bAtCrsrPos, const sal_Bool bCalcFrm )
1067 {
1068     SET_CURR_SHELL( this );
1069     // Seitennummer: die erste sichtbare Seite oder die am Cursor
1070     const SwCntntFrm* pCFrm;
1071     const SwPageFrm *pPg = 0;
1072 
1073     if( !bAtCrsrPos || 0 == (pCFrm = GetCurrFrm( bCalcFrm )) ||
1074                        0 == (pPg   = pCFrm->FindPageFrm()) )
1075     {
1076         pPg = Imp()->GetFirstVisPage();
1077         while( pPg && pPg->IsEmptyPage() )
1078             pPg = (const SwPageFrm *)pPg->GetNext();
1079     }
1080     // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
1081     // standard.vor sein.
1082     rnPhyNum  = pPg? pPg->GetPhyPageNum() : 1;
1083     rnVirtNum = pPg? pPg->GetVirtPageNum() : 1;
1084 }
1085 
1086 
1087 sal_uInt16 SwCrsrShell::GetNextPrevPageNum( sal_Bool bNext )
1088 {
1089     SET_CURR_SHELL( this );
1090 
1091     // Seitennummer: die erste sichtbare Seite oder die am Cursor
1092     const SwPageFrm *pPg = Imp()->GetFirstVisPage();
1093     if( pPg )
1094     {
1095         const SwTwips nPageTop = pPg->Frm().Top();
1096 
1097         if( bNext )
1098         {
1099             // go to next view layout row:
1100             do
1101             {
1102                 pPg = (const SwPageFrm *)pPg->GetNext();
1103             }
1104             while( pPg && pPg->Frm().Top() == nPageTop );
1105 
1106             while( pPg && pPg->IsEmptyPage() )
1107                 pPg = (const SwPageFrm *)pPg->GetNext();
1108         }
1109         else
1110         {
1111             // go to previous view layout row:
1112             do
1113             {
1114                 pPg = (const SwPageFrm *)pPg->GetPrev();
1115             }
1116             while( pPg && pPg->Frm().Top() == nPageTop );
1117 
1118             while( pPg && pPg->IsEmptyPage() )
1119                 pPg = (const SwPageFrm *)pPg->GetPrev();
1120         }
1121     }
1122     // Abfrage auf pPg muss fuer den Sonderfall Writerstart mit
1123     // standard.vor sein.
1124     return pPg ? pPg->GetPhyPageNum() : USHRT_MAX;
1125 }
1126 
1127 
1128 sal_uInt16 SwCrsrShell::GetPageCnt()
1129 {
1130     SET_CURR_SHELL( this );
1131     // gebe die Anzahl der Seiten zurueck
1132     return GetLayout()->GetPageNum();
1133 }
1134 
1135 // Gehe zur naechsten SSelection
1136 
1137 
1138 sal_Bool SwCrsrShell::GoNextCrsr()
1139 {
1140     // besteht ueberhaupt ein Ring ?
1141     if( pCurCrsr->GetNext() == pCurCrsr )
1142         return sal_False;
1143 
1144     SET_CURR_SHELL( this );
1145     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
1146     pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1147 
1148     // Bug 24086: auch alle anderen anzeigen
1149     if( !ActionPend() )
1150     {
1151         UpdateCrsr();
1152         pCurCrsr->Show();
1153     }
1154     return sal_True;
1155 }
1156 
1157 // gehe zur vorherigen SSelection
1158 
1159 
1160 sal_Bool SwCrsrShell::GoPrevCrsr()
1161 {
1162     // besteht ueberhaupt ein Ring ?
1163     if( pCurCrsr->GetNext() == pCurCrsr )
1164         return sal_False;
1165 
1166     SET_CURR_SHELL( this );
1167     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
1168     pCurCrsr = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetPrev());
1169 
1170     // Bug 24086: auch alle anderen anzeigen
1171     if( !ActionPend() )
1172     {
1173         UpdateCrsr();
1174         pCurCrsr->Show();
1175     }
1176 
1177     return sal_True;
1178 }
1179 
1180 
1181 void SwCrsrShell::Paint( const Rectangle &rRect)
1182 {
1183     SET_CURR_SHELL( this );
1184 
1185     // beim Painten immer alle Cursor ausschalten
1186     SwRect aRect( rRect );
1187 
1188     sal_Bool bVis = sal_False;
1189     // ist Cursor sichtbar, dann verstecke den SV-Cursor
1190     if( pVisCrsr->IsVisible() && !aRect.IsOver( aCharRect ) )   //JP 18.06.97: ???
1191     {
1192         bVis = sal_True;
1193         pVisCrsr->Hide();
1194     }
1195 
1196     // Bereich neu painten
1197     ViewShell::Paint( rRect );
1198 
1199     if( bHasFocus && !bBasicHideCrsr )
1200     {
1201         SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
1202 //      pAktCrsr->Invalidate( aRect );
1203         if( !ActionPend() )
1204         {
1205             // damit nicht rechts/unten die Raender abgeschnitten werden
1206             pAktCrsr->Invalidate( VisArea() );
1207             pAktCrsr->Show();
1208         }
1209         else
1210             pAktCrsr->Invalidate( aRect );
1211 
1212     }
1213     if( bSVCrsrVis && bVis )        // auch SV-Cursor wieder anzeigen
1214         pVisCrsr->Show();
1215 }
1216 
1217 
1218 
1219 void SwCrsrShell::VisPortChgd( const SwRect & rRect )
1220 {
1221     SET_CURR_SHELL( this );
1222     sal_Bool bVis;      // beim Scrollen immer alle Cursor ausschalten
1223 
1224     // ist Cursor sichtbar, dann verstecke den SV-Cursor
1225     if( sal_True == ( bVis = pVisCrsr->IsVisible() ))
1226         pVisCrsr->Hide();
1227 
1228     bVisPortChgd = sal_True;
1229     aOldRBPos.X() = VisArea().Right();
1230     aOldRBPos.Y() = VisArea().Bottom();
1231 
1232     //Damit es es keine Probleme mit dem SV-Cursor gibt, wird in
1233     //ViewShell::VisPo.. ein Update() auf das Window gerufen.
1234     //Waehrend des Paintens duerfen aber nun wieder keine Selectionen
1235     //angezeigt werden, deshalb wird der Aufruf hier geklammert.
1236     ViewShell::VisPortChgd( rRect );        // Bereich verschieben
1237 
1238 /*
1239     SwRect aRect( rRect );
1240     if( VisArea().IsOver( aRect ) )
1241         pCurCrsr->Invalidate( aRect );
1242 */
1243 
1244     if( bSVCrsrVis && bVis )    // auch SV-Cursor wieder anzeigen
1245         pVisCrsr->Show();
1246 
1247     if( nCrsrMove )
1248         bInCMvVisportChgd = sal_True;
1249 
1250     bVisPortChgd = sal_False;
1251 }
1252 
1253 // aktualisiere den Crsrs, d.H. setze ihn wieder in den Content.
1254 // Das sollte nur aufgerufen werden, wenn der Cursor z.B. beim
1255 // Loeschen von Rahmen irgendwohin gesetzt wurde. Die Position
1256 // ergibt sich aus seiner aktuellen Position im Layout !!
1257 
1258 
1259 void SwCrsrShell::UpdateCrsrPos()
1260 {
1261     SET_CURR_SHELL( this );
1262     ++nStartAction;
1263     SwShellCrsr* pShellCrsr = getShellCrsr( true );
1264     Size aOldSz( GetDocSize() );
1265     SwCntntNode *pCNode = pShellCrsr->GetCntntNode();
1266     SwCntntFrm  *pFrm = pCNode ?
1267         pCNode->getLayoutFrm( GetLayout(), &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False ) :0;
1268     if( !pFrm || (pFrm->IsTxtFrm() && ((SwTxtFrm*)pFrm)->IsHiddenNow()) )
1269     {
1270         SwCrsrMoveState aTmpState( MV_NONE );
1271         aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1272         GetLayout()->GetCrsrOfst( pShellCrsr->GetPoint(), pShellCrsr->GetPtPos(),
1273                                      &aTmpState );
1274         if( pShellCrsr->HasMark())
1275             pShellCrsr->DeleteMark();
1276     }
1277     IGrammarContact *pGrammarContact = GetDoc() ? GetDoc()->getGrammarContact() : 0;
1278     if( pGrammarContact )
1279         pGrammarContact->updateCursorPosition( *pCurCrsr->GetPoint() );
1280     --nStartAction;
1281     if( aOldSz != GetDocSize() )
1282         SizeChgNotify();
1283 }
1284 
1285 // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1286 //              stehen, so mussen diese daraus verschoben werden
1287 static void lcl_CheckHiddenSection( SwNodeIndex& rIdx )
1288 {
1289     const SwSectionNode* pSectNd = rIdx.GetNode().FindSectionNode();
1290     if( pSectNd && pSectNd->GetSection().IsHiddenFlag() )
1291     {
1292         SwNodeIndex aTmp( *pSectNd );
1293 #if OSL_DEBUG_LEVEL > 1
1294         const SwNode* pFrmNd =
1295 #endif
1296         rIdx.GetNodes().FindPrvNxtFrmNode( aTmp, pSectNd->EndOfSectionNode() );
1297 
1298 #if OSL_DEBUG_LEVEL > 1
1299         (void) pFrmNd;
1300         ASSERT( pFrmNd, "keinen Node mit Frames gefunden" );
1301 #endif
1302         rIdx = aTmp;
1303     }
1304 }
1305 
1306 // Try to set the cursor to the next visible content node.
1307 static void lcl_CheckHiddenPara( SwPosition& rPos )
1308 {
1309     SwNodeIndex aTmp( rPos.nNode );
1310     SwTxtNode* pTxtNd = aTmp.GetNode().GetTxtNode();
1311     while( pTxtNd && pTxtNd->HasHiddenCharAttribute( true ) )
1312     {
1313         SwCntntNode* pCntnt = aTmp.GetNodes().GoNext( &aTmp );
1314         if ( pCntnt && pCntnt->IsTxtNode() )
1315             pTxtNd = (SwTxtNode*)pCntnt;
1316         else
1317             pTxtNd = 0;
1318     }
1319 
1320     if ( pTxtNd )
1321         rPos = SwPosition( aTmp, SwIndex( pTxtNd, 0 ) );
1322 }
1323 
1324 // --> OD 2005-12-14 #i27301# - helper class, which notifies the accessibility
1325 // about invalid text selections in its destructor
1326 class SwNotifyAccAboutInvalidTextSelections
1327 {
1328     private:
1329         SwCrsrShell& mrCrsrSh;
1330 
1331     public:
1332         SwNotifyAccAboutInvalidTextSelections( SwCrsrShell& _rCrsrSh )
1333             : mrCrsrSh( _rCrsrSh )
1334         {}
1335 
1336         ~SwNotifyAccAboutInvalidTextSelections()
1337         {
1338             mrCrsrSh.InvalidateAccessibleParaTextSelection();
1339         }
1340 };
1341 // <--
1342 void SwCrsrShell::UpdateCrsr( sal_uInt16 eFlags, sal_Bool bIdleEnd )
1343 {
1344     SET_CURR_SHELL( this );
1345 
1346     ClearUpCrsrs();
1347 
1348     // erfrage den Count fuer die Start-/End-Actions und ob die Shell
1349     // ueberhaupt den Focus hat
1350 //  if( ActionPend() /*|| !bHasFocus*/ )
1351     //JP 12.01.98: Bug #46496# - es muss innerhalb einer BasicAction der
1352     //              Cursor geupdatet werden; um z.B. den TabellenCursor zu
1353     //              erzeugen. Im EndAction wird jetzt das UpdateCrsr gerufen!
1354     if( ActionPend() && BasicActionPend() )
1355     {
1356         if ( eFlags & SwCrsrShell::READONLY )
1357             bIgnoreReadonly = sal_True;
1358         return;             // wenn nicht, dann kein Update !!
1359     }
1360 
1361     // --> OD 2005-12-14 #i27301#
1362     SwNotifyAccAboutInvalidTextSelections aInvalidateTextSelections( *this );
1363     // <--
1364 
1365     if ( bIgnoreReadonly )
1366     {
1367         bIgnoreReadonly = sal_False;
1368         eFlags |= SwCrsrShell::READONLY;
1369     }
1370 
1371     if( eFlags & SwCrsrShell::CHKRANGE )    // alle Cursor-Bewegungen auf
1372         CheckRange( pCurCrsr );         // ueberlappende Bereiche testen
1373 
1374     if( !bIdleEnd )
1375         CheckTblBoxCntnt();
1376 
1377     // steht der akt. Crsr in einer Tabelle und in unterschiedlichen Boxen
1378     // (oder ist noch TabellenMode), dann gilt der Tabellen Mode
1379     SwPaM* pTstCrsr = getShellCrsr( true );
1380     if( pTstCrsr->HasMark() && !pBlockCrsr &&
1381         pDoc->IsIdxInTbl( pTstCrsr->GetPoint()->nNode ) &&
1382           ( pTblCrsr ||
1383             pTstCrsr->GetNode( sal_True )->StartOfSectionNode() !=
1384             pTstCrsr->GetNode( sal_False )->StartOfSectionNode() ) )
1385     {
1386         SwShellCrsr* pITmpCrsr = getShellCrsr( true );
1387         Point aTmpPt( pITmpCrsr->GetPtPos() );
1388         Point aTmpMk( pITmpCrsr->GetMkPos() );
1389         SwPosition* pPos = pITmpCrsr->GetPoint();
1390 
1391         // JP 30.04.99: Bug 65475 - falls Point/Mark in versteckten Bereichen
1392         //              stehen, so mussen diese daraus verschoben werden
1393         lcl_CheckHiddenSection( pPos->nNode );
1394         lcl_CheckHiddenSection( pITmpCrsr->GetMark()->nNode );
1395 
1396         // Move cursor out of hidden paragraphs
1397         if ( !GetViewOptions()->IsShowHiddenChar() )
1398         {
1399             lcl_CheckHiddenPara( *pPos );
1400             lcl_CheckHiddenPara( *pITmpCrsr->GetMark() );
1401         }
1402 
1403         SwCntntFrm *pTblFrm = pPos->nNode.GetNode().GetCntntNode()->
1404                               getLayoutFrm( GetLayout(), &aTmpPt, pPos, sal_False );
1405 
1406         ASSERT( pTblFrm, "Tabelle Crsr nicht im Content ??" );
1407 
1408         // --> FME 2005-12-02 #126107# Make code robust. The table
1409         // cursor may point to a table in a currently inactive header.
1410         SwTabFrm *pTab = pTblFrm ? pTblFrm->FindTabFrm() : 0;
1411         // <--
1412 
1413         if ( pTab && pTab->GetTable()->GetRowsToRepeat() > 0 )
1414         {
1415             // First check if point is in repeated headline:
1416             bool bInRepeatedHeadline = pTab->IsFollow() && pTab->IsInHeadline( *pTblFrm );
1417 
1418             // Second check if mark is in repeated headline:
1419             if ( !bInRepeatedHeadline )
1420             {
1421                 SwCntntFrm* pMarkTblFrm = pITmpCrsr->GetCntntNode( sal_False )->
1422                     getLayoutFrm( GetLayout(), &aTmpMk, pITmpCrsr->GetMark(), sal_False );
1423                 ASSERT( pMarkTblFrm, "Tabelle Crsr nicht im Content ??" );
1424 
1425                 if ( pMarkTblFrm )
1426                 {
1427                     SwTabFrm* pMarkTab = pMarkTblFrm->FindTabFrm();
1428                     ASSERT( pMarkTab, "Tabelle Crsr nicht im Content ??" );
1429 
1430                     // --> FME 2005-11-28 #120360# Make code robust:
1431                     if ( pMarkTab )
1432                     {
1433                         bInRepeatedHeadline = pMarkTab->IsFollow() && pMarkTab->IsInHeadline( *pMarkTblFrm );
1434                     }
1435                     // <--
1436                 }
1437             }
1438 
1439             // No table cursor in repeaded headlines:
1440             if ( bInRepeatedHeadline )
1441             {
1442                 pTblFrm = 0;
1443 
1444                 SwPosSection fnPosSect = *pPos <  *pITmpCrsr->GetMark()
1445                                             ? fnSectionStart
1446                                             : fnSectionEnd;
1447 
1448                 // dann nur innerhalb der Box selektieren
1449                 if( pTblCrsr )
1450                 {
1451                     pCurCrsr->SetMark();
1452                     *pCurCrsr->GetMark() = *pTblCrsr->GetMark();
1453                     pCurCrsr->GetMkPos() = pTblCrsr->GetMkPos();
1454                     pTblCrsr->DeleteMark();
1455                     pTblCrsr->SwSelPaintRects::Hide();
1456                 }
1457 
1458                 *pCurCrsr->GetPoint() = *pCurCrsr->GetMark();
1459                 (*fnSectionCurr)( *pCurCrsr, fnPosSect );
1460             }
1461         }
1462 
1463         // wir wollen wirklich eine Tabellen-Selektion
1464         if( pTab && pTblFrm )
1465         {
1466             if( !pTblCrsr )
1467             {
1468                 pTblCrsr = new SwShellTableCrsr( *this,
1469                                 *pCurCrsr->GetMark(), pCurCrsr->GetMkPos(),
1470                                 *pPos, aTmpPt );
1471                 pCurCrsr->DeleteMark();
1472                 pCurCrsr->SwSelPaintRects::Hide();
1473 
1474                 CheckTblBoxCntnt();
1475             }
1476 
1477             SwCrsrMoveState aTmpState( MV_NONE );
1478             aTmpState.bRealHeight = sal_True;
1479             if( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint(), &aTmpState ) )
1480             {
1481                 Point aCentrPt( aCharRect.Center() );
1482                 aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1483                 pTblFrm->GetCrsrOfst( pTblCrsr->GetPoint(), aCentrPt, &aTmpState );
1484 #ifndef DBG_UTIL
1485                 pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() );
1486 #else
1487                 if ( !pTblFrm->GetCharRect( aCharRect, *pTblCrsr->GetPoint() ) )
1488                     ASSERT( !this, "GetCharRect failed." );
1489 #endif
1490             }
1491 //          ALIGNRECT( aCharRect );
1492 
1493             pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
1494             // Curosr in den sichtbaren Bereich scrollen
1495             if( (eFlags & SwCrsrShell::SCROLLWIN) &&
1496                 (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1497                  !IsCrsrReadonly()) )
1498             {
1499                 SwFrm* pBoxFrm = pTblFrm;
1500                 while( pBoxFrm && !pBoxFrm->IsCellFrm() )
1501                     pBoxFrm = pBoxFrm->GetUpper();
1502                 if( pBoxFrm && pBoxFrm->Frm().HasArea() )
1503                     MakeVisible( pBoxFrm->Frm() );
1504                 else
1505                     MakeVisible( aCharRect );
1506             }
1507 
1508             // lasse vom Layout die Crsr in den Boxen erzeugen
1509             if( pTblCrsr->IsCrsrMovedUpdt() )
1510                 GetLayout()->MakeTblCrsrs( *pTblCrsr );
1511             if( bHasFocus && !bBasicHideCrsr )
1512                 pTblCrsr->Show();
1513 
1514             // Cursor-Points auf die neuen Positionen setzen
1515             pTblCrsr->GetPtPos().X() = aCharRect.Left();
1516             pTblCrsr->GetPtPos().Y() = aCharRect.Top();
1517 
1518             if( bSVCrsrVis )
1519             {
1520                 aCrsrHeight.X() = 0;
1521                 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1522                                   -aCharRect.Width() : aCharRect.Height();
1523                 pVisCrsr->Show();           // wieder anzeigen
1524             }
1525             eMvState = MV_NONE;     // Status fuers Crsr-Travelling - GetCrsrOfst
1526             if( pTblFrm && Imp()->IsAccessible() )
1527                 Imp()->InvalidateAccessibleCursorPosition( pTblFrm );
1528             return;
1529         }
1530     }
1531 
1532     if( pTblCrsr )
1533     {
1534         // Cursor Ring loeschen
1535         while( pCurCrsr->GetNext() != pCurCrsr )
1536             delete pCurCrsr->GetNext();
1537         pCurCrsr->DeleteMark();
1538         *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
1539         pCurCrsr->GetPtPos() = pTblCrsr->GetPtPos();
1540         delete pTblCrsr, pTblCrsr = 0;
1541     }
1542 
1543     pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
1544 
1545     // sind wir vielleicht in einer geschuetzten/versteckten Section ?
1546     {
1547         SwShellCrsr* pShellCrsr = getShellCrsr( true );
1548         sal_Bool bChgState = sal_True;
1549         const SwSectionNode* pSectNd = pShellCrsr->GetNode()->FindSectionNode();
1550         if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
1551             ( !IsReadOnlyAvailable() &&
1552               pSectNd->GetSection().IsProtectFlag() &&
1553              ( !pDoc->GetDocShell() ||
1554                !pDoc->GetDocShell()->IsReadOnly() || bAllProtect )) ) )
1555         {
1556             if( !FindValidCntntNode( !HasDrawView() ||
1557                     0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1558             {
1559                 // alles ist geschuetzt / versteckt -> besonderer Mode
1560                 if( bAllProtect && !IsReadOnlyAvailable() &&
1561                     pSectNd->GetSection().IsProtectFlag() )
1562                     bChgState = sal_False;
1563                 else
1564                 {
1565                     eMvState = MV_NONE;     // Status fuers Crsr-Travelling
1566                     bAllProtect = sal_True;
1567                     if( GetDoc()->GetDocShell() )
1568                     {
1569                         GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1570                         CallChgLnk();       // UI bescheid sagen!
1571                     }
1572                     return;
1573                 }
1574             }
1575         }
1576         if( bChgState )
1577         {
1578             sal_Bool bWasAllProtect = bAllProtect;
1579             bAllProtect = sal_False;
1580             if( bWasAllProtect && GetDoc()->GetDocShell() &&
1581                 GetDoc()->GetDocShell()->IsReadOnlyUI() )
1582             {
1583                 GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1584                 CallChgLnk();       // UI bescheid sagen!
1585             }
1586         }
1587     }
1588 
1589     UpdateCrsrPos();
1590 
1591     // #100722# The cursor must always point into content; there's some code
1592     // that relies on this. (E.g. in SwEditShell::GetScriptType, which always
1593     // loops _behind_ the last node in the selection, which always works if you
1594     // are in content.) To achieve this, we'll force cursor(s) to point into
1595     // content, if UpdateCrsrPos() hasn't already done so.
1596     SwPaM* pCmp = pCurCrsr;
1597     do
1598     {
1599         // start will move forwards, end will move backwards
1600         bool bPointIsStart = ( pCmp->Start() == pCmp->GetPoint() );
1601 
1602         // move point; forward if it's the start, backwards if it's the end
1603         if( ! pCmp->GetPoint()->nNode.GetNode().IsCntntNode() )
1604             pCmp->Move( bPointIsStart ? fnMoveForward : fnMoveBackward,
1605                         fnGoCntnt );
1606 
1607         // move mark (if exists); forward if it's the start, else backwards
1608         if( pCmp->HasMark() )
1609         {
1610             if( ! pCmp->GetMark()->nNode.GetNode().IsCntntNode() )
1611             {
1612                 pCmp->Exchange();
1613                 pCmp->Move( !bPointIsStart ? fnMoveForward : fnMoveBackward,
1614                             fnGoCntnt );
1615                 pCmp->Exchange();
1616             }
1617         }
1618 
1619         // iterate to next PaM in ring
1620         pCmp = static_cast<SwPaM*>( pCmp->GetNext() );
1621     }
1622     while( pCmp != pCurCrsr );
1623 
1624 
1625     SwRect aOld( aCharRect );
1626     sal_Bool bFirst = sal_True;
1627     SwCntntFrm *pFrm;
1628     int nLoopCnt = 100;
1629     SwShellCrsr* pShellCrsr = getShellCrsr( true );
1630 
1631     do {
1632         sal_Bool bAgainst;
1633         do {
1634             bAgainst = sal_False;
1635             pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1636                         &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1637             // ist der Frm nicht mehr vorhanden, dann muss das gesamte Layout
1638             // erzeugt werden, weil ja mal hier einer vorhanden war !!
1639             if ( !pFrm )
1640             {
1641                 do
1642                 {
1643                     CalcLayout();
1644                     pFrm = pShellCrsr->GetCntntNode()->getLayoutFrm( GetLayout(),
1645                                 &pShellCrsr->GetPtPos(), pShellCrsr->GetPoint(), sal_False );
1646                 }  while( !pFrm );
1647             }
1648             else if ( Imp()->IsIdleAction() )
1649                 //Wir stellen sicher, dass anstaendig Formatiert wurde #42224#
1650                 pFrm->PrepareCrsr();
1651 
1652             // im geschuetzten Fly? aber bei Rahmenselektion ignorieren
1653             if( !IsReadOnlyAvailable() && pFrm->IsProtected() &&
1654                 ( !Imp()->GetDrawView() ||
1655                   !Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount() ) &&
1656                 (!pDoc->GetDocShell() ||
1657                  !pDoc->GetDocShell()->IsReadOnly() || bAllProtect ) )
1658             {
1659                 // dann suche eine gueltige Position
1660                 sal_Bool bChgState = sal_True;
1661                 if( !FindValidCntntNode(!HasDrawView() ||
1662                     0 == Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount()))
1663                 {
1664                     // alles ist geschuetzt / versteckt -> besonderer Mode
1665                     if( bAllProtect )
1666                         bChgState = sal_False;
1667                     else
1668                     {
1669                         eMvState = MV_NONE;     // Status fuers Crsr-Travelling
1670                         bAllProtect = sal_True;
1671                         if( GetDoc()->GetDocShell() )
1672                         {
1673                             GetDoc()->GetDocShell()->SetReadOnlyUI( sal_True );
1674                             CallChgLnk();       // UI bescheid sagen!
1675                         }
1676                         return;
1677                     }
1678                 }
1679 
1680                 if( bChgState )
1681                 {
1682                     sal_Bool bWasAllProtect = bAllProtect;
1683                     bAllProtect = sal_False;
1684                     if( bWasAllProtect && GetDoc()->GetDocShell() &&
1685                         GetDoc()->GetDocShell()->IsReadOnlyUI() )
1686                     {
1687                         GetDoc()->GetDocShell()->SetReadOnlyUI( sal_False );
1688                         CallChgLnk();       // UI bescheid sagen!
1689                     }
1690                     bAllProtect = sal_False;
1691                     bAgainst = sal_True;        // nochmal den richigen Frm suchen
1692                 }
1693             }
1694         } while( bAgainst );
1695 
1696         if( !( eFlags & SwCrsrShell::NOCALRECT ))
1697         {
1698             SwCrsrMoveState aTmpState( eMvState );
1699             aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
1700             aTmpState.bRealHeight = sal_True;
1701             aTmpState.bRealWidth = IsOverwriteCrsr();
1702             aTmpState.nCursorBidiLevel = pShellCrsr->GetCrsrBidiLevel();
1703 
1704             // #i27615#,#i30453#
1705             SwSpecialPos aSpecialPos;
1706             aSpecialPos.nExtendRange = SP_EXTEND_RANGE_BEFORE;
1707             if (pShellCrsr->IsInFrontOfLabel())
1708             {
1709                 aTmpState.pSpecialPos = &aSpecialPos;
1710             }
1711 
1712             if( !pFrm->GetCharRect( aCharRect, *pShellCrsr->GetPoint(), &aTmpState ) )
1713             {
1714                 Point& rPt = pShellCrsr->GetPtPos();
1715                 rPt = aCharRect.Center();
1716                 pFrm->GetCrsrOfst( pShellCrsr->GetPoint(), rPt, &aTmpState );
1717             }
1718 //          ALIGNRECT( aCharRect );
1719 
1720             if( !pShellCrsr->HasMark() )
1721                 aCrsrHeight = aTmpState.aRealHeight;
1722             else
1723             {
1724                 aCrsrHeight.X() = 0;
1725                 aCrsrHeight.Y() = aTmpState.aRealHeight.Y() < 0 ?
1726                                   -aCharRect.Width() : aCharRect.Height();
1727             }
1728         }
1729         else
1730         {
1731             aCrsrHeight.X() = 0;
1732             aCrsrHeight.Y() = aCharRect.Height();
1733         }
1734 
1735         if( !bFirst && aOld == aCharRect )
1736             break;
1737 
1738         // falls das Layout meint, nach dem 100 durchlauf ist man immer noch
1739         // im Fluss, sollte man die akt. Pos. als gegeben hinnehmen!
1740         // siehe Bug: 29658
1741         if( !--nLoopCnt )
1742         {
1743             ASSERT( !this, "Endlosschleife? CharRect != OldCharRect ");
1744             break;
1745         }
1746         aOld = aCharRect;
1747         bFirst = sal_False;
1748 
1749         // Cursor-Points auf die neuen Positionen setzen
1750         pShellCrsr->GetPtPos().X() = aCharRect.Left();
1751         pShellCrsr->GetPtPos().Y() = aCharRect.Top();
1752 
1753         if( !(eFlags & SwCrsrShell::UPDOWN ))   // alte Pos. von Up/Down loeschen
1754         {
1755             pFrm->Calc();
1756             nUpDownX = pFrm->IsVertical() ?
1757                        aCharRect.Top() - pFrm->Frm().Top() :
1758                        aCharRect.Left() - pFrm->Frm().Left();
1759         }
1760 
1761         // Curosr in den sichtbaren Bereich scrollen
1762         if( bHasFocus && eFlags & SwCrsrShell::SCROLLWIN &&
1763             (HasSelection() || eFlags & SwCrsrShell::READONLY ||
1764              !IsCrsrReadonly() || GetViewOptions()->IsSelectionInReadonly()) )
1765         {
1766             //JP 30.04.99:  damit das EndAction, beim evtuellen Scrollen, den
1767             //      SV-Crsr nicht wieder sichtbar macht, wird hier das Flag
1768             //      gesichert und zurueckgesetzt.
1769             sal_Bool bSav = bSVCrsrVis; bSVCrsrVis = sal_False;
1770             MakeSelVisible();
1771             bSVCrsrVis = bSav;
1772         }
1773 
1774     } while( eFlags & SwCrsrShell::SCROLLWIN );
1775 
1776     if( pBlockCrsr )
1777         RefreshBlockCursor();
1778 
1779     if( !bIdleEnd && bHasFocus && !bBasicHideCrsr )
1780     {
1781         if( pTblCrsr )
1782             pTblCrsr->SwSelPaintRects::Show();
1783         else
1784         {
1785             pCurCrsr->SwSelPaintRects::Show();
1786             if( pBlockCrsr )
1787             {
1788                 SwShellCrsr* pNxt = dynamic_cast<SwShellCrsr*>(pCurCrsr->GetNext());
1789                 while( pNxt && pNxt != pCurCrsr )
1790                 {
1791                     pNxt->SwSelPaintRects::Show();
1792                     pNxt = dynamic_cast<SwShellCrsr*>(pNxt->GetNext());
1793                 }
1794             }
1795         }
1796     }
1797 
1798     eMvState = MV_NONE;     // Status fuers Crsr-Travelling - GetCrsrOfst
1799 
1800     if( pFrm && Imp()->IsAccessible() )
1801         Imp()->InvalidateAccessibleCursorPosition( pFrm );
1802 
1803     // switch from blinking cursor to read-only-text-selection cursor
1804     static const long nNoBlinkTime = STYLE_CURSOR_NOBLINKTIME;
1805     const long nBlinkTime = GetOut()->GetSettings().GetStyleSettings().
1806                             GetCursorBlinkTime();
1807 
1808     if ( (IsCrsrReadonly() && GetViewOptions()->IsSelectionInReadonly()) ==
1809         ( nBlinkTime != nNoBlinkTime ) )
1810     {
1811         // non blinking cursor in read only - text selection mode
1812         AllSettings aSettings = GetOut()->GetSettings();
1813         StyleSettings aStyleSettings = aSettings.GetStyleSettings();
1814         const long nNewBlinkTime = nBlinkTime == nNoBlinkTime ?
1815                                    Application::GetSettings().GetStyleSettings().GetCursorBlinkTime() :
1816                                    nNoBlinkTime;
1817         aStyleSettings.SetCursorBlinkTime( nNewBlinkTime );
1818         aSettings.SetStyleSettings( aStyleSettings );
1819         GetOut()->SetSettings( aSettings );
1820     }
1821 
1822     if( bSVCrsrVis )
1823         pVisCrsr->Show();           // wieder anzeigen
1824 }
1825 
1826 void SwCrsrShell::RefreshBlockCursor()
1827 {
1828     ASSERT( pBlockCrsr, "Don't call me without a block cursor" );
1829     SwShellCrsr &rBlock = pBlockCrsr->getShellCrsr();
1830     Point aPt = rBlock.GetPtPos();
1831     SwCntntFrm* pFrm = rBlock.GetCntntNode()->getLayoutFrm( GetLayout(), &aPt, rBlock.GetPoint(), sal_False );
1832     Point aMk;
1833     if( pBlockCrsr->getEndPoint() && pBlockCrsr->getStartPoint() )
1834     {
1835         aPt = *pBlockCrsr->getStartPoint();
1836         aMk = *pBlockCrsr->getEndPoint();
1837     }
1838     else
1839     {
1840         aPt = rBlock.GetPtPos();
1841         if( pFrm )
1842         {
1843             if( pFrm->IsVertical() )
1844                 aPt.Y() = pFrm->Frm().Top() + GetUpDownX();
1845             else
1846                 aPt.X() = pFrm->Frm().Left() + GetUpDownX();
1847         }
1848         aMk = rBlock.GetMkPos();
1849     }
1850     SwRect aRect( aMk, aPt );
1851     aRect.Justify();
1852     SwSelectionList aSelList( pFrm );
1853 
1854     if( GetLayout()->FillSelection( aSelList, aRect ) )
1855     {
1856         SwCursor* pNxt = (SwCursor*)pCurCrsr->GetNext();
1857         while( pNxt != pCurCrsr )
1858         {
1859             delete pNxt;
1860             pNxt = (SwCursor*)pCurCrsr->GetNext();
1861         }
1862 
1863         std::list<SwPaM*>::iterator pStart = aSelList.getStart();
1864         std::list<SwPaM*>::iterator pPam = aSelList.getEnd();
1865         ASSERT( pPam != pStart, "FillSelection should deliver at least one PaM" )
1866         pCurCrsr->SetMark();
1867         --pPam;
1868         // If there is only one text portion inside the rectangle, a simple
1869         // selection is created
1870         if( pPam == pStart )
1871         {
1872             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint();
1873             if( (*pPam)->HasMark() )
1874                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1875             else
1876                 pCurCrsr->DeleteMark();
1877             delete *pPam;
1878             pCurCrsr->SetColumnSelection( false );
1879         }
1880         else
1881         {
1882             // The order of the SwSelectionList has to be preserved but
1883             // the order inside the ring created by CreateCrsr() is not like
1884             // exspected => First create the selections before the last one
1885             // downto the first selection.
1886             // At least create the cursor for the last selection
1887             --pPam;
1888             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-1 (if n == number of selections)
1889             if( (*pPam)->HasMark() )
1890                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1891             else
1892                 pCurCrsr->DeleteMark();
1893             delete *pPam;
1894             pCurCrsr->SetColumnSelection( true );
1895             while( pPam != pStart )
1896             {
1897                 --pPam;
1898 
1899                 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1900                 pNew->Insert( pCurCrsr, 0 );
1901                 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1902                 pCurCrsr->DeleteMark();
1903 
1904                 *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n-2, n-3, .., 2, 1
1905                 if( (*pPam)->HasMark() )
1906                 {
1907                     pCurCrsr->SetMark();
1908                     *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1909                 }
1910                 else
1911                     pCurCrsr->DeleteMark();
1912                 pCurCrsr->SetColumnSelection( true );
1913                 delete *pPam;
1914             }
1915             {
1916                 SwShellCrsr* pNew = new SwShellCrsr( *pCurCrsr );
1917                 pNew->Insert( pCurCrsr, 0 );
1918                 pCurCrsr->Remove( 0, pCurCrsr->Count() );
1919                 pCurCrsr->DeleteMark();
1920             }
1921             pPam = aSelList.getEnd();
1922             --pPam;
1923             *pCurCrsr->GetPoint() = *(*pPam)->GetPoint(); // n, the last selection
1924             if( (*pPam)->HasMark() )
1925             {
1926                 pCurCrsr->SetMark();
1927                 *pCurCrsr->GetMark() = *(*pPam)->GetMark();
1928             }
1929             else
1930                 pCurCrsr->DeleteMark();
1931             pCurCrsr->SetColumnSelection( true );
1932             delete *pPam;
1933         }
1934     }
1935 }
1936 
1937 // erzeuge eine Kopie vom Cursor und speicher diese im Stack
1938 
1939 
1940 void SwCrsrShell::Push()
1941 {
1942     pCrsrStk = new SwShellCrsr( *this, *pCurCrsr->GetPoint(),
1943                                     pCurCrsr->GetPtPos(), pCrsrStk );
1944 
1945     if( pCurCrsr->HasMark() )
1946     {
1947         pCrsrStk->SetMark();
1948         *pCrsrStk->GetMark() = *pCurCrsr->GetMark();
1949     }
1950 }
1951 
1952 /*
1953  *  Loescht einen Cursor (gesteuert durch bOldCrsr)
1954  *      - vom Stack oder    ( bOldCrsr = sal_True )
1955  *      - den aktuellen und der auf dem Stack stehende wird zum aktuellen
1956  *
1957  *  Return:  es war auf dem Stack noch einer vorhanden
1958  */
1959 
1960 
1961 sal_Bool SwCrsrShell::Pop( sal_Bool bOldCrsr )
1962 {
1963     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
1964 
1965     // noch weitere vorhanden ?
1966     if( 0 == pCrsrStk )
1967         return sal_False;
1968 
1969     SwShellCrsr *pTmp = 0, *pOldStk = pCrsrStk;
1970 
1971     // der Nachfolger wird der Aktuelle
1972     if( pCrsrStk->GetNext() != pCrsrStk )
1973     {
1974         pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
1975     }
1976 
1977     if( bOldCrsr )              // loesche vom Stack
1978         delete pCrsrStk;        //
1979 
1980     pCrsrStk = pTmp;            // neu zuweisen
1981 
1982     if( !bOldCrsr )
1983     {
1984         SwCrsrSaveState aSaveState( *pCurCrsr );
1985 
1986         // wurde die sichtbare SSelection nicht veraendert
1987         if( pOldStk->GetPtPos() == pCurCrsr->GetPtPos() ||
1988             pOldStk->GetPtPos() == pCurCrsr->GetMkPos() )
1989         {
1990             // "Selektions-Rechtecke" verschieben
1991             pCurCrsr->Insert( pOldStk, 0 );
1992             pOldStk->Remove( 0, pOldStk->Count() );
1993         }
1994 
1995         if( pOldStk->HasMark() )
1996         {
1997             pCurCrsr->SetMark();
1998             *pCurCrsr->GetMark() = *pOldStk->GetMark();
1999             pCurCrsr->GetMkPos() = pOldStk->GetMkPos();
2000         }
2001         else
2002             // keine Selection also alte aufheben und auf die alte Pos setzen
2003             pCurCrsr->DeleteMark();
2004         *pCurCrsr->GetPoint() = *pOldStk->GetPoint();
2005         pCurCrsr->GetPtPos() = pOldStk->GetPtPos();
2006         delete pOldStk;
2007 
2008         if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2009             !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2010                                  nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2011             UpdateCrsr();             // akt. Cursor Updaten
2012     }
2013     return sal_True;
2014 }
2015 
2016 /*
2017  * Verbinde zwei Cursor miteinander.
2018  * Loesche vom Stack den obersten und setzen dessen GetMark im Aktuellen.
2019  */
2020 
2021 
2022 void SwCrsrShell::Combine()
2023 {
2024     // noch weitere vorhanden ?
2025     if( 0 == pCrsrStk )
2026         return;
2027 
2028     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
2029     SwCrsrSaveState aSaveState( *pCurCrsr );
2030     if( pCrsrStk->HasMark() )           // nur wenn GetMark gesetzt wurde
2031     {
2032 #ifndef DBG_UTIL
2033         CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True );
2034 #else
2035         if( !CheckNodesRange( pCrsrStk->GetMark()->nNode, pCurCrsr->GetPoint()->nNode, sal_True ))
2036             ASSERT( !this, "StackCrsr & akt. Crsr nicht in gleicher Section." );
2037 #endif
2038         // kopiere das GetMark
2039         if( !pCurCrsr->HasMark() )
2040             pCurCrsr->SetMark();
2041         *pCurCrsr->GetMark() = *pCrsrStk->GetMark();
2042         pCurCrsr->GetMkPos() = pCrsrStk->GetMkPos();
2043     }
2044 
2045     SwShellCrsr * pTmp = 0;
2046     if( pCrsrStk->GetNext() != pCrsrStk )
2047     {
2048         pTmp = dynamic_cast<SwShellCrsr*>(pCrsrStk->GetNext());
2049     }
2050     delete pCrsrStk;
2051     pCrsrStk = pTmp;
2052     if( !pCurCrsr->IsInProtectTable( sal_True ) &&
2053         !pCurCrsr->IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
2054                              nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
2055         UpdateCrsr();             // akt. Cursor Updaten
2056 }
2057 
2058 
2059 void SwCrsrShell::HideCrsrs()
2060 {
2061     if( !bHasFocus || bBasicHideCrsr )
2062         return;
2063 
2064     // ist Cursor sichtbar, dann verstecke den SV-Cursor
2065     if( pVisCrsr->IsVisible() )
2066     {
2067         SET_CURR_SHELL( this );
2068         pVisCrsr->Hide();
2069     }
2070     // hebe die Invertierung der SSelection auf
2071     SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2072     pAktCrsr->Hide();
2073 }
2074 
2075 
2076 
2077 void SwCrsrShell::ShowCrsrs( sal_Bool bCrsrVis )
2078 {
2079     if( !bHasFocus || bAllProtect || bBasicHideCrsr )
2080         return;
2081 
2082     SET_CURR_SHELL( this );
2083     SwShellCrsr* pAktCrsr = pTblCrsr ? pTblCrsr : pCurCrsr;
2084     pAktCrsr->Show();
2085 
2086     if( bSVCrsrVis && bCrsrVis )    // auch SV-Cursor wieder anzeigen
2087         pVisCrsr->Show();
2088 }
2089 
2090 // Methoden zum Anzeigen bzw. Verstecken des sichtbaren Text-Cursors
2091 
2092 
2093 void SwCrsrShell::ShowCrsr()
2094 {
2095     if( !bBasicHideCrsr )
2096     {
2097         bSVCrsrVis = sal_True;
2098         UpdateCrsr();
2099     }
2100 }
2101 
2102 
2103 void SwCrsrShell::HideCrsr()
2104 {
2105     if( !bBasicHideCrsr )
2106     {
2107         bSVCrsrVis = sal_False;
2108         // evt. die sel. Bereiche aufheben !!
2109         SET_CURR_SHELL( this );
2110         pVisCrsr->Hide();
2111     }
2112 }
2113 
2114 
2115 void SwCrsrShell::ShLooseFcs()
2116 {
2117     if( !bBasicHideCrsr )
2118         HideCrsrs();
2119     bHasFocus = sal_False;
2120 }
2121 
2122 
2123 void SwCrsrShell::ShGetFcs( sal_Bool bUpdate )
2124 {
2125     bHasFocus = sal_True;
2126     if( !bBasicHideCrsr && VisArea().Width() )
2127     {
2128         UpdateCrsr( static_cast<sal_uInt16>( bUpdate ?
2129                     SwCrsrShell::CHKRANGE|SwCrsrShell::SCROLLWIN
2130                     : SwCrsrShell::CHKRANGE ) );
2131         ShowCrsrs( bSVCrsrVis ? sal_True : sal_False );
2132     }
2133 }
2134 
2135 // gebe den aktuellen Frame, in dem der Cursor steht, zurueck
2136 
2137 SwCntntFrm *SwCrsrShell::GetCurrFrm( const sal_Bool bCalcFrm ) const
2138 {
2139     SET_CURR_SHELL( (ViewShell*)this );
2140     SwCntntFrm *pRet = 0;
2141     SwCntntNode *pNd = pCurCrsr->GetCntntNode();
2142     if ( pNd )
2143     {
2144         if ( bCalcFrm )
2145         {
2146             const sal_uInt16* pST = &nStartAction;
2147             ++(*((sal_uInt16*)pST));
2148             const Size aOldSz( GetDocSize() );
2149             pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint() );
2150             --(*((sal_uInt16*)pST));
2151             if( aOldSz != GetDocSize() )
2152                 ((SwCrsrShell*)this)->SizeChgNotify();
2153         }
2154         else
2155             pRet = pNd->getLayoutFrm( GetLayout(), &pCurCrsr->GetPtPos(), pCurCrsr->GetPoint(), sal_False);
2156     }
2157     return pRet;
2158 }
2159 
2160 
2161 // alle Attribut/Format-Aenderungen am akt. Node werden an den
2162 // Link weitergeleitet.
2163 
2164 
2165 void SwCrsrShell::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
2166 {
2167     const sal_uInt16 nWhich = pOld ?
2168                           pOld->Which() :
2169                           pNew ?
2170                           pNew->Which() :
2171                           sal::static_int_cast<sal_uInt16>(RES_MSG_BEGIN);
2172 
2173     if( bCallChgLnk &&
2174         ( nWhich < RES_MSG_BEGIN || nWhich >= RES_MSG_END ||
2175             nWhich == RES_FMT_CHG || nWhich == RES_UPDATE_ATTR ||
2176             nWhich == RES_ATTRSET_CHG ))
2177         // die Messages werden nicht weitergemeldet
2178         //MA 07. Apr. 94 fix(6681): RES_UPDATE_ATTR wird implizit vom
2179         //SwTxtNode::Insert(SwTxtHint*, sal_uInt16) abgesetzt; hier wird reagiert und
2180         //vom Insert brauch nicht mehr die Keule RES_FMT_CHG versandt werden.
2181         CallChgLnk();
2182 
2183     if( aGrfArrivedLnk.IsSet() &&
2184         ( RES_GRAPHIC_ARRIVED == nWhich || RES_GRAPHIC_SWAPIN == nWhich ))
2185         aGrfArrivedLnk.Call( this );
2186 }
2187 
2188 
2189 // Abfrage, ob der aktuelle Cursor eine Selektion aufspannt,
2190 // also, ob GetMark gesetzt und SPoint und GetMark unterschiedlich sind.
2191 
2192 
2193 sal_Bool SwCrsrShell::HasSelection() const
2194 {
2195     const SwPaM* pCrsr = getShellCrsr( true );
2196     return( IsTableMode() || ( pCrsr->HasMark() &&
2197             *pCrsr->GetPoint() != *pCrsr->GetMark())
2198         ? sal_True : sal_False );
2199 }
2200 
2201 
2202 void SwCrsrShell::CallChgLnk()
2203 {
2204     // innerhalb von Start-/End-Action kein Call, sondern nur merken,
2205     // das sich etwas geaendert hat. Wird bei EndAction beachtet.
2206     if( BasicActionPend() )
2207         bChgCallFlag = sal_True;        // das Change merken
2208     else if( aChgLnk.IsSet() )
2209     {
2210         if( bCallChgLnk )
2211             aChgLnk.Call( this );
2212         bChgCallFlag = sal_False;       // Flag zuruecksetzen
2213     }
2214 }
2215 
2216 // returne den am akt.Cursor selektierten Text eines Nodes.
2217 
2218 
2219 String SwCrsrShell::GetSelTxt() const
2220 {
2221     String aTxt;
2222     if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2223         pCurCrsr->GetMark()->nNode.GetIndex() )
2224     {
2225         SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2226         if( pTxtNd )
2227         {
2228             xub_StrLen nStt = pCurCrsr->Start()->nContent.GetIndex();
2229             aTxt = pTxtNd->GetExpandTxt( nStt,
2230                     pCurCrsr->End()->nContent.GetIndex() - nStt );
2231         }
2232     }
2233     return aTxt;
2234 }
2235 
2236 // gebe nur den Text ab der akt. Cursor Position zurueck (bis zum NodeEnde)
2237 
2238 
2239 String SwCrsrShell::GetText() const
2240 {
2241     String aTxt;
2242     if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
2243         pCurCrsr->GetMark()->nNode.GetIndex() )
2244     {
2245         SwTxtNode* pTxtNd = pCurCrsr->GetNode()->GetTxtNode();
2246         if( pTxtNd )
2247             aTxt = pTxtNd->GetTxt().Copy(
2248                     pCurCrsr->GetPoint()->nContent.GetIndex() );
2249     }
2250     return aTxt;
2251 }
2252 
2253 // hole vom Start/Ende der akt. SSelection das nte Zeichen
2254 sal_Unicode SwCrsrShell::GetChar( sal_Bool bEnd, long nOffset )
2255 {
2256     if( IsTableMode() )         // im TabelleMode nicht moeglich
2257         return 0;
2258 
2259     const SwPosition* pPos = !pCurCrsr->HasMark() ? pCurCrsr->GetPoint()
2260                                 : bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2261     SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2262     if( !pTxtNd )
2263         return 0;
2264 
2265     xub_StrLen nPos = pPos->nContent.GetIndex();
2266     const String& rStr = pTxtNd->GetTxt();
2267     sal_Unicode cCh = 0;
2268 
2269     if( ((nPos+nOffset) >= 0 ) && (nPos+nOffset) < rStr.Len() )
2270         cCh = rStr.GetChar( static_cast<xub_StrLen>(nPos+nOffset) );
2271 
2272     return cCh;
2273 }
2274 
2275 // erweiter die akt. SSelection am Anfang/Ende um n Zeichen
2276 
2277 
2278 sal_Bool SwCrsrShell::ExtendSelection( sal_Bool bEnd, xub_StrLen nCount )
2279 {
2280     if( !pCurCrsr->HasMark() || IsTableMode() )
2281         return sal_False;           // keine Selektion
2282 
2283     SwPosition* pPos = bEnd ? pCurCrsr->End() : pCurCrsr->Start();
2284     SwTxtNode* pTxtNd = pPos->nNode.GetNode().GetTxtNode();
2285     ASSERT( pTxtNd, "kein TextNode, wie soll erweitert werden?" );
2286 
2287     xub_StrLen nPos = pPos->nContent.GetIndex();
2288     if( bEnd )
2289     {
2290         if( ( nPos + nCount ) <= pTxtNd->GetTxt().Len() )
2291             nPos = nPos + nCount;
2292         else
2293             return sal_False;       // nicht mehr moeglich
2294     }
2295     else if( nPos >= nCount )
2296         nPos = nPos - nCount;
2297     else
2298         return sal_False;           // nicht mehr moeglich
2299 
2300     SwCallLink aLk( *this );    // Crsr-Moves ueberwachen,
2301 
2302     pPos->nContent = nPos;
2303     UpdateCrsr();
2304 
2305     return sal_True;
2306 }
2307 
2308 // setze nur den sichtbaren Cursor an die angegebene Dokument-Pos.
2309 // returnt sal_False: wenn der SPoint vom Layout korrigiert wurde.
2310 
2311 sal_Bool SwCrsrShell::SetVisCrsr( const Point &rPt )
2312 {
2313     SET_CURR_SHELL( this );
2314     Point aPt( rPt );
2315     SwPosition aPos( *pCurCrsr->GetPoint() );
2316     SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
2317     aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2318     aTmpState.bRealHeight = sal_True;
2319 
2320     sal_Bool bRet = GetLayout()->GetCrsrOfst( &aPos, aPt /*, &aTmpState*/ );
2321 
2322     SetInFrontOfLabel( sal_False ); // #i27615#
2323 
2324     // nur in TextNodes anzeigen !!
2325     SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode();
2326     if( !pTxtNd )
2327         return sal_False;
2328 
2329     const SwSectionNode* pSectNd = pTxtNd->FindSectionNode();
2330     if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
2331                     ( !IsReadOnlyAvailable() &&
2332                       pSectNd->GetSection().IsProtectFlag())) )
2333         return sal_False;
2334 
2335     SwCntntFrm *pFrm = pTxtNd->getLayoutFrm( GetLayout(), &aPt, &aPos );
2336     if ( Imp()->IsIdleAction() )
2337         pFrm->PrepareCrsr();
2338     SwRect aTmp( aCharRect );
2339 
2340     pFrm->GetCharRect( aCharRect, aPos, &aTmpState );
2341 //  ALIGNRECT( aCharRect );
2342 
2343     if( aTmp == aCharRect &&        // BUG 10137: bleibt der Cursor auf der
2344         pVisCrsr->IsVisible() )     // Position nicht hidden & showen
2345         return sal_True;
2346 
2347     pVisCrsr->Hide();       // sichtbaren Cursor immer verstecken
2348     if( IsScrollMDI( this, aCharRect ))
2349     {
2350         MakeVisible( aCharRect );
2351         pCurCrsr->Show();
2352     }
2353 
2354     // Bug 29584: bei Rahmenselektion ist der Cursor versteckt, aber den
2355     //          D&D-Cursor will man trotzdem haben
2356 //  if( bSVCrsrVis )
2357     {
2358         if( aTmpState.bRealHeight )
2359             aCrsrHeight = aTmpState.aRealHeight;
2360         else
2361         {
2362             aCrsrHeight.X() = 0;
2363             aCrsrHeight.Y() = aCharRect.Height();
2364         }
2365 
2366         pVisCrsr->SetDragCrsr( sal_True );
2367         pVisCrsr->Show();           // wieder anzeigen
2368     }
2369     return bRet;
2370 }
2371 
2372 sal_Bool SwCrsrShell::IsOverReadOnlyPos( const Point& rPt ) const
2373 {
2374     Point aPt( rPt );
2375     SwPaM aPam( *pCurCrsr->GetPoint() );
2376     GetLayout()->GetCrsrOfst( aPam.GetPoint(), aPt );
2377     // --> FME 2004-06-29 #114856# Formular view
2378     return aPam.HasReadonlySel( GetViewOptions()->IsFormView() );
2379     // <--
2380 }
2381 
2382 
2383     // returne die Anzahl der Cursor im Ring (Flag besagt ob man nur
2384     // aufgepspannte haben will - sprich etwas selektiert ist (Basic))
2385 sal_uInt16 SwCrsrShell::GetCrsrCnt( sal_Bool bAll ) const
2386 {
2387     Ring* pTmp = GetCrsr()->GetNext();
2388     sal_uInt16 n = (bAll || ( pCurCrsr->HasMark() &&
2389                     *pCurCrsr->GetPoint() != *pCurCrsr->GetMark())) ? 1 : 0;
2390     while( pTmp != pCurCrsr )
2391     {
2392         if( bAll || ( ((SwPaM*)pTmp)->HasMark() &&
2393                 *((SwPaM*)pTmp)->GetPoint() != *((SwPaM*)pTmp)->GetMark()))
2394             ++n;
2395         pTmp = pTmp->GetNext();
2396     }
2397     return n;
2398 }
2399 
2400 
2401 sal_Bool SwCrsrShell::IsStartOfDoc() const
2402 {
2403     if( pCurCrsr->GetPoint()->nContent.GetIndex() )
2404         return sal_False;
2405 
2406     // Hinter EndOfIcons kommt die Content-Section (EndNd+StNd+CntntNd)
2407     SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfExtras(), 2 );
2408     if( !aIdx.GetNode().IsCntntNode() )
2409         GetDoc()->GetNodes().GoNext( &aIdx );
2410     return aIdx == pCurCrsr->GetPoint()->nNode;
2411 }
2412 
2413 
2414 sal_Bool SwCrsrShell::IsEndOfDoc() const
2415 {
2416     SwNodeIndex aIdx( GetDoc()->GetNodes().GetEndOfContent(), -1 );
2417     SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
2418     if( !pCNd )
2419         pCNd = GetDoc()->GetNodes().GoPrevious( &aIdx );
2420 
2421     return aIdx == pCurCrsr->GetPoint()->nNode &&
2422             pCNd->Len() == pCurCrsr->GetPoint()->nContent.GetIndex();
2423 }
2424 
2425 
2426 // loesche alle erzeugten Crsr, setze den Tabellen-Crsr und den letzten
2427 // Cursor auf seinen TextNode (oder StartNode?).
2428 // Beim naechsten ::GetCrsr werden sie wieder alle erzeugt
2429 // Wird fuers Drag&Drop / ClipBorad-Paste in Tabellen benoetigt.
2430 sal_Bool SwCrsrShell::ParkTblCrsr()
2431 {
2432     if( !pTblCrsr )
2433         return sal_False;
2434 
2435     pTblCrsr->ParkCrsr();
2436 
2437     while( pCurCrsr->GetNext() != pCurCrsr )
2438         delete pCurCrsr->GetNext();
2439 
2440     // vom Cursor !immer! SPoint und Mark umsetzen
2441     pCurCrsr->SetMark();
2442     *pCurCrsr->GetMark() = *pCurCrsr->GetPoint() = *pTblCrsr->GetPoint();
2443     pCurCrsr->DeleteMark();
2444 
2445     return sal_True;
2446 }
2447 
2448 /***********************************************************************
2449 #*  Class       :  SwCrsrShell
2450 #*  Methode     :  ParkCrsr
2451 #*  Beschreibung:  Vernichtet Selektionen und zus. Crsr aller Shell der
2452 #*                 verbleibende Crsr der Shell wird geparkt.
2453 #*  Datum       :  MA 05. Nov. 92
2454 #*  Update      :  JP 19.09.97
2455 #***********************************************************************/
2456 
2457 void SwCrsrShell::_ParkPams( SwPaM* pDelRg, SwShellCrsr** ppDelRing )
2458 {
2459     const SwPosition *pStt = pDelRg->Start(),
2460         *pEnd = pDelRg->GetPoint() == pStt ? pDelRg->GetMark() : pDelRg->GetPoint();
2461 
2462     SwPaM *pTmpDel = 0, *pTmp = *ppDelRing;
2463 
2464     // durchsuche den gesamten Ring
2465     sal_Bool bGoNext;
2466     do {
2467         const SwPosition *pTmpStt = pTmp->Start(),
2468                         *pTmpEnd = pTmp->GetPoint() == pTmpStt ?
2469                                         pTmp->GetMark() : pTmp->GetPoint();
2470         /*
2471          * liegt ein SPoint oder GetMark innerhalb vom Crsr-Bereich
2472          * muss der alte Bereich aufgehoben werden.
2473          * Beim Vergleich ist darauf zu achten, das End() nicht mehr zum
2474          * Bereich gehoert !
2475          */
2476         if( *pStt <= *pTmpStt )
2477         {
2478             if( *pEnd > *pTmpStt ||
2479                 ( *pEnd == *pTmpStt && *pEnd == *pTmpEnd ))
2480                 pTmpDel = pTmp;
2481         }
2482         else
2483             if( *pStt < *pTmpEnd )
2484                 pTmpDel = pTmp;
2485 
2486         bGoNext = sal_True;
2487         if( pTmpDel )           // ist der Pam im Bereich ?? loesche ihn
2488         {
2489             sal_Bool bDelete = sal_True;
2490             if( *ppDelRing == pTmpDel )
2491             {
2492                 if( *ppDelRing == pCurCrsr )
2493                 {
2494                     if( sal_True == ( bDelete = GoNextCrsr() ))
2495                     {
2496                         bGoNext = sal_False;
2497                         pTmp = (SwPaM*)pTmp->GetNext();
2498                     }
2499                 }
2500                 else
2501                     bDelete = sal_False;        // StackCrsr nie loeschen !!
2502             }
2503 
2504             if( bDelete )
2505                 delete pTmpDel;         // hebe alten Bereich auf
2506             else
2507             {
2508                 pTmpDel->GetPoint()->nContent.Assign( 0, 0 );
2509                 pTmpDel->GetPoint()->nNode = 0;
2510                 pTmpDel->SetMark();
2511                 pTmpDel->DeleteMark();
2512             }
2513             pTmpDel = 0;
2514         }
2515         else if( !pTmp->HasMark() )     // sorge auf jedenfall dafuer, das
2516         {                       // nicht benutzte Indizies beachtet werden!
2517             pTmp->SetMark();            // SPoint liegt nicht im Bereich,
2518             pTmp->DeleteMark();         // aber vielleicht GetMark, also setzen
2519         }
2520         if( bGoNext )
2521             pTmp = (SwPaM*)pTmp->GetNext();
2522     } while( !bGoNext || *ppDelRing != pTmp );
2523 }
2524 
2525 void SwCrsrShell::ParkCrsr( const SwNodeIndex &rIdx )
2526 {
2527     SwNode *pNode = &rIdx.GetNode();
2528 
2529     // erzeuge einen neuen Pam
2530     SwPaM * pNew = new SwPaM( *GetCrsr()->GetPoint() );
2531     if( pNode->GetStartNode() )
2532     {
2533         if( ( pNode = pNode->StartOfSectionNode())->IsTableNode() )
2534         {
2535             // der angegebene Node steht in einer Tabelle, also Parke
2536             // den Crsr auf dem Tabellen-Node (ausserhalb der Tabelle)
2537             pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2538         }
2539         else    // also auf dem StartNode selbst.
2540                 // Dann immer ueber seinen EndNode den StartNode erfragen !!!
2541                 // (StartOfSection vom StartNode ist der Parent !)
2542             pNew->GetPoint()->nNode = *pNode->EndOfSectionNode()->StartOfSectionNode();
2543     }
2544     else
2545         pNew->GetPoint()->nNode = *pNode->StartOfSectionNode();
2546     pNew->SetMark();
2547     pNew->GetPoint()->nNode = *pNode->EndOfSectionNode();
2548 
2549     //Alle Shells wollen etwas davon haben.
2550     ViewShell *pTmp = this;
2551     do {
2552         if( pTmp->IsA( TYPE( SwCrsrShell )))
2553         {
2554             SwCrsrShell* pSh = (SwCrsrShell*)pTmp;
2555             if( pSh->pCrsrStk )
2556                 pSh->_ParkPams( pNew, &pSh->pCrsrStk );
2557 
2558             pSh->_ParkPams( pNew, &pSh->pCurCrsr );
2559             if( pSh->pTblCrsr )
2560             {
2561                 // setze den Tabellen Cursor immer auf 0, den aktuellen
2562                 // immer auf den Anfang der Tabelle
2563                 SwPaM* pTCrsr = pSh->GetTblCrs();
2564                 SwNode* pTblNd = pTCrsr->GetPoint()->nNode.GetNode().FindTableNode();
2565                 if ( pTblNd )
2566                 {
2567                     pTCrsr->GetPoint()->nContent.Assign( 0, 0 );
2568                     pTCrsr->GetPoint()->nNode = 0;
2569                     pTCrsr->SetMark();
2570                     pTCrsr->DeleteMark();
2571                     pSh->pCurCrsr->GetPoint()->nNode = *pTblNd;
2572                 }
2573             }
2574         }
2575     } while ( this != (pTmp = (ViewShell*)pTmp->GetNext() ));
2576     delete pNew;
2577 }
2578 
2579 //=========================================================================
2580 
2581 /*
2582  * der Copy-Constructor
2583  * Cursor-Position kopieren, in den Ring eingetragen.
2584  * Alle Ansichten eines Dokumentes stehen im Ring der Shells.
2585  */
2586 
2587 SwCrsrShell::SwCrsrShell( SwCrsrShell& rShell, Window *pInitWin )
2588     : ViewShell( rShell, pInitWin ),
2589     SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2590     pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2591     eMvState( MV_NONE ),
2592     // --> OD 2008-04-02 #refactorlists#
2593     sMarkedListId(),
2594     nMarkedListLevel( 0 )
2595     // <--
2596 {
2597     SET_CURR_SHELL( this );
2598     // Nur die Position vom aktuellen Cursor aus der Copy-Shell uebernehmen
2599     pCurCrsr = new SwShellCrsr( *this, *(rShell.pCurCrsr->GetPoint()) );
2600     pCurCrsr->GetCntntNode()->Add( this );
2601 
2602     bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2603     bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2604     bOverwriteCrsr = sal_False;
2605     bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2606     bSetCrsrInReadOnly = sal_True;
2607     pVisCrsr = new SwVisCrsr( this );
2608 //  UpdateCrsr( 0 );
2609     // OD 11.02.2003 #100556#
2610     mbMacroExecAllowed = rShell.IsMacroExecAllowed();
2611 }
2612 
2613 
2614 /*
2615  * der normale Constructor
2616  */
2617 
2618 SwCrsrShell::SwCrsrShell( SwDoc& rDoc, Window *pInitWin,
2619                             const SwViewOption *pInitOpt )
2620     : ViewShell( rDoc, pInitWin, pInitOpt ),
2621     SwModify( 0 ), pCrsrStk( 0 ), pBlockCrsr( 0 ), pTblCrsr( 0 ),
2622     pBoxIdx( 0 ), pBoxPtr( 0 ), nCrsrMove( 0 ), nBasicActionCnt( 0 ),
2623     eMvState( MV_NONE ), // state for crsr-travelling - GetCrsrOfst
2624     // --> OD 2008-04-02 #refactorlists#
2625     sMarkedListId(),
2626     nMarkedListLevel( 0 )
2627     // <--
2628 {
2629     SET_CURR_SHELL( this );
2630     /*
2631      * Erzeugen des initialen Cursors, wird auf die erste
2632      * Inhaltsposition gesetzt
2633      */
2634     SwNodes& rNds = rDoc.GetNodes();
2635 
2636     SwNodeIndex aNodeIdx( *rNds.GetEndOfContent().StartOfSectionNode() );
2637     SwCntntNode* pCNd = rNds.GoNext( &aNodeIdx ); // gehe zum 1. ContentNode
2638 
2639     pCurCrsr = new SwShellCrsr( *this, SwPosition( aNodeIdx, SwIndex( pCNd, 0 )));
2640 
2641     // melde die Shell beim akt. Node als abhaengig an, dadurch koennen alle
2642     // Attribut-Aenderungen ueber den Link weiter gemeldet werden.
2643     pCNd->Add( this );
2644 
2645     bAllProtect = bVisPortChgd = bChgCallFlag = bInCMvVisportChgd =
2646     bGCAttr = bIgnoreReadonly = bSelTblCells = bBasicHideCrsr =
2647     bOverwriteCrsr = sal_False;
2648     bCallChgLnk = bHasFocus = bSVCrsrVis = bAutoUpdateCells = sal_True;
2649     bSetCrsrInReadOnly = sal_True;
2650 
2651     pVisCrsr = new SwVisCrsr( this );
2652 //  UpdateCrsr( 0 );
2653     // OD 11.02.2003 #100556#
2654     mbMacroExecAllowed = true;
2655 }
2656 
2657 
2658 
2659 SwCrsrShell::~SwCrsrShell()
2660 {
2661     // wenn es nicht die letzte View so sollte zu mindest das
2662     // Feld noch geupdatet werden.
2663     if( GetNext() != this )
2664         CheckTblBoxCntnt( pCurCrsr->GetPoint() );
2665     else
2666         ClearTblBoxCntnt();
2667 
2668     delete pVisCrsr;
2669     delete pBlockCrsr;
2670     delete pTblCrsr;
2671 
2672     /*
2673      * Freigabe der Cursor
2674      */
2675     while(pCurCrsr->GetNext() != pCurCrsr)
2676         delete pCurCrsr->GetNext();
2677     delete pCurCrsr;
2678 
2679     // Stack freigeben
2680     if( pCrsrStk )
2681     {
2682         while( pCrsrStk->GetNext() != pCrsrStk )
2683             delete pCrsrStk->GetNext();
2684         delete pCrsrStk;
2685     }
2686 
2687     // JP 27.07.98: Bug 54025 - ggfs. den HTML-Parser, der als Client in
2688     //              der CursorShell haengt keine Chance geben, sich an den
2689     //              TextNode zu haengen.
2690     if( GetRegisteredIn() )
2691         GetRegisteredInNonConst()->Remove( this );
2692 }
2693 
2694 SwShellCrsr* SwCrsrShell::getShellCrsr( bool bBlock )
2695 {
2696     if( pTblCrsr )
2697         return pTblCrsr;
2698     if( pBlockCrsr && bBlock )
2699         return &pBlockCrsr->getShellCrsr();
2700     return pCurCrsr;
2701 }
2702 
2703 //Sollte fuer das Clipboard der WaitPtr geschaltet werden?
2704 //Warten bei TableMode, Mehrfachselektion und mehr als x Selektieren Absaetzen.
2705 
2706 sal_Bool SwCrsrShell::ShouldWait() const
2707 {
2708     if ( IsTableMode() || GetCrsrCnt() > 1 )
2709         return sal_True;
2710 
2711     if( HasDrawView() && GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2712         return sal_True;
2713 
2714     SwPaM* pPam = GetCrsr();
2715     return pPam->Start()->nNode.GetIndex() + 10 <
2716             pPam->End()->nNode.GetIndex();
2717 }
2718 
2719 
2720 sal_uInt16 SwCrsrShell::UpdateTblSelBoxes()
2721 {
2722     if( pTblCrsr && ( pTblCrsr->IsChgd() || !pTblCrsr->GetBoxesCount() ))
2723          GetLayout()->MakeTblCrsrs( *pTblCrsr );
2724     return pTblCrsr ? pTblCrsr->GetBoxesCount() : 0;
2725 }
2726 
2727 // zeige das akt. selektierte "Object" an
2728 void SwCrsrShell::MakeSelVisible()
2729 {
2730     ASSERT( bHasFocus, "kein Focus aber Cursor sichtbar machen?" );
2731     if( aCrsrHeight.Y() < aCharRect.Height() && aCharRect.Height() > VisArea().Height() )
2732     {
2733         SwRect aTmp( aCharRect );
2734         long nDiff = aCharRect.Height() - VisArea().Height();
2735         if( nDiff < aCrsrHeight.X() )
2736             aTmp.Top( nDiff + aCharRect.Top() );
2737         else
2738         {
2739             aTmp.Top( aCrsrHeight.X() + aCharRect.Top() );
2740             aTmp.Height( aCrsrHeight.Y() );
2741         }
2742         if( !aTmp.HasArea() )
2743         {
2744             aTmp.SSize().Height() += 1;
2745             aTmp.SSize().Width() += 1;
2746         }
2747         MakeVisible( aTmp );
2748     }
2749     else
2750     {
2751         if( aCharRect.HasArea() )
2752             MakeVisible( aCharRect );
2753         else
2754         {
2755             SwRect aTmp( aCharRect );
2756             aTmp.SSize().Height() += 1; aTmp.SSize().Width() += 1;
2757             MakeVisible( aTmp );
2758         }
2759     }
2760 }
2761 
2762 
2763 // suche eine gueltige ContentPosition (nicht geschuetzt/nicht versteckt)
2764 sal_Bool SwCrsrShell::FindValidCntntNode( sal_Bool bOnlyText )
2765 {
2766     if( pTblCrsr )      // was soll ich jetzt machen ??
2767     {
2768         ASSERT( !this, "TabellenSelection nicht aufgehoben!" );
2769         return sal_False;
2770     }
2771 
2772     //JP 28.10.97: Bug 45129 - im UI-ReadOnly ist alles erlaubt
2773     if( !bAllProtect && GetDoc()->GetDocShell() &&
2774         GetDoc()->GetDocShell()->IsReadOnlyUI() )
2775         return sal_True;
2776 
2777     // dann raus da!
2778     if( pCurCrsr->HasMark() )
2779         ClearMark();
2780 
2781     // als erstes mal auf Rahmen abpruefen
2782     SwNodeIndex& rNdIdx = pCurCrsr->GetPoint()->nNode;
2783     sal_uLong nNdIdx = rNdIdx.GetIndex();       // sichern
2784     SwNodes& rNds = pDoc->GetNodes();
2785     SwCntntNode* pCNd = rNdIdx.GetNode().GetCntntNode();
2786     const SwCntntFrm * pFrm;
2787 
2788     if( pCNd && 0 != (pFrm = pCNd->getLayoutFrm( GetLayout(),0,pCurCrsr->GetPoint(),sal_False)) &&
2789         !IsReadOnlyAvailable() && pFrm->IsProtected() &&
2790         nNdIdx < rNds.GetEndOfExtras().GetIndex() )
2791     {
2792         // geschuetzter Rahmen ueberspringen
2793         SwPaM aPam( *pCurCrsr->GetPoint() );
2794         aPam.SetMark();
2795         aPam.GetMark()->nNode = rNds.GetEndOfContent();
2796         aPam.GetPoint()->nNode = *pCNd->EndOfSectionNode();
2797 
2798         sal_Bool bFirst = sal_False;
2799         if( 0 == (pCNd = ::GetNode( aPam, bFirst, fnMoveForward, sal_False )))
2800         {
2801             aPam.GetMark()->nNode = *rNds.GetEndOfPostIts().StartOfSectionNode();
2802             pCNd = ::GetNode( aPam, bFirst, fnMoveBackward, sal_False );
2803         }
2804 
2805         if( !pCNd )     // sollte nie passieren !!!
2806         {
2807             rNdIdx = nNdIdx;        // alten Node zurueck
2808             return sal_False;
2809         }
2810         *pCurCrsr->GetPoint() = *aPam.GetPoint();
2811     }
2812     else if( bOnlyText && pCNd && pCNd->IsNoTxtNode() )
2813     {
2814         // dann auf den Anfang vom Doc stellen
2815         rNdIdx = pDoc->GetNodes().GetEndOfExtras();
2816         pCurCrsr->GetPoint()->nContent.Assign( pDoc->GetNodes().GoNext(
2817                                                             &rNdIdx ), 0 );
2818         nNdIdx = rNdIdx.GetIndex();
2819     }
2820 
2821     sal_Bool bOk = sal_True;
2822 
2823     // #i9059# cursor may not stand in protected cells
2824     //         (unless cursor in protected areas is OK.)
2825     const SwTableNode* pTableNode = rNdIdx.GetNode().FindTableNode();
2826     if( !IsReadOnlyAvailable()  &&
2827         pTableNode != NULL  &&  rNdIdx.GetNode().IsProtect() )
2828     {
2829         // we're in a table, and we're in a protected area, so we're
2830         // probably in a protected cell.
2831 
2832         // move forward into non-protected area.
2833         SwPaM aPam( rNdIdx.GetNode(), 0 );
2834         while( aPam.GetNode()->IsProtect() &&
2835                aPam.Move( fnMoveForward, fnGoCntnt ) )
2836             ; // nothing to do in the loop; the aPam.Move does the moving!
2837 
2838         // didn't work? then go backwards!
2839         if( aPam.GetNode()->IsProtect() )
2840         {
2841             SwPaM aTmpPaM( rNdIdx.GetNode(), 0 );
2842             aPam = aTmpPaM;
2843             while( aPam.GetNode()->IsProtect() &&
2844                    aPam.Move( fnMoveBackward, fnGoCntnt ) )
2845                 ; // nothing to do in the loop; the aPam.Move does the moving!
2846         }
2847 
2848         // if we're successful, set the new position
2849         if( ! aPam.GetNode()->IsProtect() )
2850         {
2851             *pCurCrsr->GetPoint() = *aPam.GetPoint();
2852         }
2853     }
2854 
2855     // in einem geschuetzten Bereich
2856     const SwSectionNode* pSectNd = rNdIdx.GetNode().FindSectionNode();
2857     if( pSectNd && ( pSectNd->GetSection().IsHiddenFlag() ||
2858         ( !IsReadOnlyAvailable() &&
2859            pSectNd->GetSection().IsProtectFlag() )) )
2860     {
2861         typedef SwCntntNode* (SwNodes:: *FNGoSection)( SwNodeIndex *, int, int ) const;
2862         FNGoSection funcGoSection = &SwNodes::GoNextSection;
2863 
2864         bOk = sal_False;
2865 
2866         for( int nLoopCnt = 0; !bOk && nLoopCnt < 2; ++nLoopCnt )
2867         {
2868             sal_Bool bWeiter;
2869             do {
2870                 bWeiter = sal_False;
2871                 while( 0 != ( pCNd = (rNds.*funcGoSection)( &rNdIdx,
2872                                             sal_True, !IsReadOnlyAvailable() )) )
2873                 {
2874                     // in eine Tabelle verschoben -> pruefe ob die
2875                     // vielleicht geschuetzt ist
2876                     if( pCNd->FindTableNode() )
2877                     {
2878                         SwCallLink aTmp( *this );
2879                         SwCrsrSaveState aSaveState( *pCurCrsr );
2880                         aTmp.nNdTyp = 0;        // im DTOR nichts machen!
2881                         if( !pCurCrsr->IsInProtectTable( sal_True, sal_True ) )
2882                         {
2883                             const SwSectionNode* pSNd = pCNd->FindSectionNode();
2884                             if( !pSNd || !pSNd->GetSection().IsHiddenFlag()
2885                                 || (!IsReadOnlyAvailable()  &&
2886                                     pSNd->GetSection().IsProtectFlag() ))
2887                             {
2888                                 bOk = sal_True;
2889                                 break;      // eine nicht geschuetzte Zelle gef.
2890                             }
2891                             continue;       // dann weiter suchen
2892                         }
2893                     }
2894                     else
2895                     {
2896                         bOk = sal_True;
2897                         break;      // eine nicht geschuetzte Zelle gef.
2898                     }
2899                 }
2900 
2901                 if( bOk && rNdIdx.GetIndex() < rNds.GetEndOfExtras().GetIndex() )
2902                 {
2903                     // Teste mal auf Fly - kann auch noch geschuetzt sein!!
2904                     if( 0 == (pFrm = pCNd->getLayoutFrm( GetLayout(),0,0,sal_False)) ||
2905                         ( !IsReadOnlyAvailable() && pFrm->IsProtected() ) ||
2906                         ( bOnlyText && pCNd->IsNoTxtNode() ) )
2907                     {
2908                         // dann weiter suchen!
2909                         bOk = sal_False;
2910                         bWeiter = sal_True;
2911                     }
2912                 }
2913             } while( bWeiter );
2914 
2915             if( !bOk )
2916             {
2917                 if( !nLoopCnt )
2918                     funcGoSection = &SwNodes::GoPrevSection;
2919                 rNdIdx = nNdIdx;
2920             }
2921         }
2922     }
2923     if( bOk )
2924     {
2925         pCNd = rNdIdx.GetNode().GetCntntNode();
2926 //      sal_uInt16 nCntnt = Min( pCNd->Len(), pCurCrsr->GetPoint()->nContent.GetIndex() );
2927         xub_StrLen nCntnt = rNdIdx.GetIndex() < nNdIdx ? pCNd->Len() : 0;
2928         pCurCrsr->GetPoint()->nContent.Assign( pCNd, nCntnt );
2929     }
2930     else
2931     {
2932         pCNd = rNdIdx.GetNode().GetCntntNode();
2933 
2934         // falls Cursor im versteckten Bereich ist, auf jedenfall schon mal
2935         // verschieben!!
2936         if( !pCNd || !pCNd->getLayoutFrm( GetLayout(),0,0,sal_False) )
2937         {
2938             SwCrsrMoveState aTmpState( MV_NONE );
2939             aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
2940             GetLayout()->GetCrsrOfst( pCurCrsr->GetPoint(), pCurCrsr->GetPtPos(),
2941                                         &aTmpState );
2942         }
2943     }
2944     return bOk;
2945 }
2946 
2947 
2948 void SwCrsrShell::NewCoreSelection()
2949 {
2950 }
2951 
2952 
2953 sal_Bool SwCrsrShell::IsCrsrReadonly() const
2954 {
2955     if ( GetViewOptions()->IsReadonly() ||
2956          // --> FME 2004-06-29 #114856# Formular view
2957          GetViewOptions()->IsFormView() )
2958          // <--
2959     {
2960         SwFrm *pFrm = GetCurrFrm( sal_False );
2961         const SwFlyFrm* pFly;
2962         const SwSection* pSection;
2963 
2964         if( pFrm && pFrm->IsInFly() &&
2965              (pFly = pFrm->FindFlyFrm())->GetFmt()->GetEditInReadonly().GetValue() &&
2966              pFly->Lower() &&
2967              !pFly->Lower()->IsNoTxtFrm() &&
2968              !GetDrawView()->GetMarkedObjectList().GetMarkCount() )
2969         {
2970             return sal_False;
2971         }
2972         // --> FME 2004-06-22 #114856# edit in readonly sections
2973         else if ( pFrm && pFrm->IsInSct() &&
2974                   0 != ( pSection = pFrm->FindSctFrm()->GetSection() ) &&
2975                   pSection->IsEditInReadonlyFlag() )
2976         {
2977             return sal_False;
2978         }
2979         // <--
2980 
2981         return sal_True;
2982     }
2983     return sal_False;
2984 }
2985 
2986 
2987 // darf der Cursor in ReadOnlyBereiche?
2988 void SwCrsrShell::SetReadOnlyAvailable( sal_Bool bFlag )
2989 {
2990     // im GlobalDoc darf NIE umgeschaltet werden
2991     if( (!GetDoc()->GetDocShell() ||
2992          !GetDoc()->GetDocShell()->IsA( SwGlobalDocShell::StaticType() )) &&
2993         bFlag != bSetCrsrInReadOnly )
2994     {
2995         // wenn das Flag ausgeschaltet wird, dann muessen erstmal alle
2996         // Selektionen aufgehoben werden. Denn sonst wird sich darauf
2997         // verlassen, das nichts geschuetztes selektiert ist!
2998         if( !bFlag )
2999         {
3000             ClearMark();
3001         }
3002         bSetCrsrInReadOnly = bFlag;
3003         UpdateCrsr();
3004     }
3005 }
3006 
3007 sal_Bool SwCrsrShell::HasReadonlySel() const
3008 {
3009     sal_Bool bRet = sal_False;
3010     if( IsReadOnlyAvailable() ||
3011         // --> FME 2004-06-29 #114856# Formular view
3012         GetViewOptions()->IsFormView() )
3013         // <--
3014     {
3015         if( pTblCrsr )
3016             bRet = pTblCrsr->HasReadOnlyBoxSel() ||
3017                    pTblCrsr->HasReadonlySel(
3018                             // --> FME 2004-06-29 #114856# Formular view
3019                             GetViewOptions()->IsFormView() );
3020                             // <--
3021         else
3022         {
3023             const SwPaM* pCrsr = pCurCrsr;
3024 
3025             do {
3026                 if( pCrsr->HasReadonlySel(
3027                         // --> FME 2004-06-29 #114856# Formular view
3028                         GetViewOptions()->IsFormView() ) )
3029                         // <--
3030                     bRet = sal_True;
3031             } while( !bRet && pCurCrsr != ( pCrsr = (SwPaM*)pCrsr->GetNext() ));
3032         }
3033     }
3034     return bRet;
3035 }
3036 
3037 sal_Bool SwCrsrShell::IsSelFullPara() const
3038 {
3039     sal_Bool bRet = sal_False;
3040 
3041     if( pCurCrsr->GetPoint()->nNode.GetIndex() ==
3042         pCurCrsr->GetMark()->nNode.GetIndex() && pCurCrsr == pCurCrsr->GetNext() )
3043     {
3044         xub_StrLen nStt = pCurCrsr->GetPoint()->nContent.GetIndex(),
3045                    nEnd = pCurCrsr->GetMark()->nContent.GetIndex();
3046         if( nStt > nEnd )
3047         {
3048             xub_StrLen nTmp = nStt;
3049             nStt = nEnd;
3050             nEnd = nTmp;
3051         }
3052         const SwCntntNode* pCNd = pCurCrsr->GetCntntNode();
3053         bRet = pCNd && !nStt && nEnd == pCNd->Len();
3054     }
3055     return bRet;
3056 }
3057 
3058 short SwCrsrShell::GetTextDirection( const Point* pPt ) const
3059 {
3060     SwPosition aPos( *pCurCrsr->GetPoint() );
3061     Point aPt( pPt ? *pPt : pCurCrsr->GetPtPos() );
3062     if( pPt )
3063     {
3064         SwCrsrMoveState aTmpState( MV_NONE );
3065         aTmpState.bSetInReadOnly = IsReadOnlyAvailable();
3066 
3067         GetLayout()->GetCrsrOfst( &aPos, aPt, &aTmpState );
3068     }
3069 
3070     return pDoc->GetTextDirection( aPos, &aPt );
3071 }
3072 
3073 sal_Bool SwCrsrShell::IsInVerticalText( const Point* pPt ) const
3074 {
3075     const short nDir = GetTextDirection( pPt );
3076     return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
3077 }
3078 
3079 sal_Bool SwCrsrShell::IsInRightToLeftText( const Point* pPt ) const
3080 {
3081     const short nDir = GetTextDirection( pPt );
3082     // GetTextDirection uses FRMDIR_VERT_TOP_LEFT to indicate RTL in
3083     // vertical environment
3084     return FRMDIR_VERT_TOP_LEFT == nDir || FRMDIR_HORI_RIGHT_TOP == nDir;
3085 }
3086 
3087 //
3088 // If the current cursor position is inside a hidden range, the hidden range
3089 // is selected:
3090 //
3091 bool SwCrsrShell::SelectHiddenRange()
3092 {
3093     bool bRet = false;
3094     if ( !GetViewOptions()->IsShowHiddenChar() && !pCurCrsr->HasMark() )
3095     {
3096         SwPosition& rPt = *(SwPosition*)pCurCrsr->GetPoint();
3097         const SwTxtNode* pNode = rPt.nNode.GetNode().GetTxtNode();
3098         if ( pNode )
3099         {
3100             const xub_StrLen nPos = rPt.nContent.GetIndex();
3101 
3102             // check if nPos is in hidden range
3103             xub_StrLen nHiddenStart;
3104             xub_StrLen nHiddenEnd;
3105             SwScriptInfo::GetBoundsOfHiddenRange( *pNode, nPos, nHiddenStart, nHiddenEnd );
3106             if ( STRING_LEN != nHiddenStart )
3107             {
3108                 // make selection:
3109                 pCurCrsr->SetMark();
3110                 pCurCrsr->GetMark()->nContent = nHiddenEnd;
3111                 bRet = true;
3112             }
3113         }
3114     }
3115 
3116     return bRet;
3117 }
3118 
3119 /*  */
3120 
3121     // die Suchfunktionen
3122 sal_uLong SwCrsrShell::Find( const SearchOptions& rSearchOpt, sal_Bool bSearchInNotes,
3123                             SwDocPositions eStart, SwDocPositions eEnde,
3124                             sal_Bool& bCancel,
3125                             FindRanges eRng, int bReplace )
3126 {
3127     if( pTblCrsr )
3128         GetCrsr();
3129     delete pTblCrsr, pTblCrsr = 0;
3130     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3131     sal_uLong nRet = pCurCrsr->Find( rSearchOpt, bSearchInNotes, eStart, eEnde, bCancel, eRng, bReplace );
3132     if( nRet || bCancel )
3133         UpdateCrsr();
3134     return nRet;
3135 }
3136 
3137 sal_uLong SwCrsrShell::Find( const SwTxtFmtColl& rFmtColl,
3138                             SwDocPositions eStart, SwDocPositions eEnde,
3139                             sal_Bool& bCancel,
3140                             FindRanges eRng, const SwTxtFmtColl* pReplFmt )
3141 {
3142     if( pTblCrsr )
3143         GetCrsr();
3144     delete pTblCrsr, pTblCrsr = 0;
3145     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3146     sal_uLong nRet = pCurCrsr->Find( rFmtColl, eStart, eEnde, bCancel, eRng, pReplFmt );
3147     if( nRet )
3148         UpdateCrsr();
3149     return nRet;
3150 }
3151 
3152 sal_uLong SwCrsrShell::Find( const SfxItemSet& rSet, sal_Bool bNoCollections,
3153                             SwDocPositions eStart, SwDocPositions eEnde,
3154                             sal_Bool& bCancel,
3155                             FindRanges eRng, const SearchOptions* pSearchOpt,
3156                             const SfxItemSet* rReplSet )
3157 {
3158     if( pTblCrsr )
3159         GetCrsr();
3160     delete pTblCrsr, pTblCrsr = 0;
3161     SwCallLink aLk( *this );        // Crsr-Moves ueberwachen, evt. Link callen
3162     sal_uLong nRet = pCurCrsr->Find( rSet, bNoCollections, eStart, eEnde, bCancel,
3163                                 eRng, pSearchOpt, rReplSet );
3164     if( nRet )
3165         UpdateCrsr();
3166     return nRet;
3167 }
3168 
3169 void SwCrsrShell::SetSelection( const SwPaM& rCrsr )
3170 {
3171     StartAction();
3172     SwPaM* pCrsr = GetCrsr();
3173     *pCrsr->GetPoint() = *rCrsr.GetPoint();
3174     if(rCrsr.HasMark())
3175     {
3176         pCrsr->SetMark();
3177         *pCrsr->GetMark() = *rCrsr.GetMark();
3178     }
3179     if((SwPaM*)rCrsr.GetNext() != &rCrsr)
3180     {
3181         const SwPaM *_pStartCrsr = (SwPaM*)rCrsr.GetNext();
3182         do
3183         {
3184             SwPaM* pCurrentCrsr = CreateCrsr();
3185             *pCurrentCrsr->GetPoint() = *_pStartCrsr->GetPoint();
3186             if(_pStartCrsr->HasMark())
3187             {
3188                 pCurrentCrsr->SetMark();
3189                 *pCurrentCrsr->GetMark() = *_pStartCrsr->GetMark();
3190             }
3191         } while( (_pStartCrsr=(SwPaM *)_pStartCrsr->GetNext()) != &rCrsr );
3192     }
3193     EndAction();
3194 }
3195 
3196 void lcl_RemoveMark( SwPaM* pPam )
3197 {
3198     ASSERT( pPam->HasMark(), "Don't remove pPoint!" )
3199     pPam->GetMark()->nContent.Assign( 0, 0 );
3200     pPam->GetMark()->nNode = 0;
3201     pPam->DeleteMark();
3202 }
3203 
3204 const SwStartNode* lcl_NodeContext( const SwNode& rNode )
3205 {
3206     const SwStartNode *pRet = rNode.StartOfSectionNode();
3207     while( pRet->IsSectionNode() || pRet->IsTableNode() ||
3208         pRet->GetStartNodeType() == SwTableBoxStartNode )
3209     {
3210         pRet = pRet->StartOfSectionNode();
3211     }
3212     return pRet;
3213 }
3214 
3215 /**
3216    Checks if a position is valid. To be valid the position's node must
3217    be a content node and the content must not be unregistered.
3218 
3219    @param aPos the position to check.
3220 */
3221 bool lcl_PosOk(const SwPosition & aPos)
3222 {
3223     return NULL != aPos.nNode.GetNode().GetCntntNode() &&
3224            SwIndexReg::pEmptyIndexArray != aPos.nContent.GetIdxReg();
3225 }
3226 
3227 /**
3228    Checks if a PaM is valid. For a PaM to be valid its point must be
3229    valid. Additionaly if the PaM has a mark this has to be valid, too.
3230 
3231    @param aPam the PaM to check
3232 */
3233 static bool lcl_CrsrOk(SwPaM & aPam)
3234 {
3235     return lcl_PosOk(*aPam.GetPoint()) && (! aPam.HasMark()
3236         || lcl_PosOk(*aPam.GetMark()));
3237 }
3238 
3239 void SwCrsrShell::ClearUpCrsrs()
3240 {
3241     // start of the ring
3242     SwPaM * pStartCrsr = GetCrsr();
3243     // start loop with second entry of the ring
3244     SwPaM * pCrsr = (SwPaM *) pStartCrsr->GetNext();
3245     SwPaM * pTmpCrsr;
3246     bool bChanged = false;
3247 
3248     /*
3249        For all entries in the ring except the start entry delete the
3250        entry if it is invalid.
3251     */
3252     while (pCrsr != pStartCrsr)
3253     {
3254         pTmpCrsr = (SwPaM *) pCrsr->GetNext();
3255 
3256         if ( ! lcl_CrsrOk(*pCrsr))
3257         {
3258             delete pCrsr;
3259 
3260             bChanged = true;
3261         }
3262 
3263         pCrsr = pTmpCrsr;
3264     }
3265 
3266     if( pStartCrsr->HasMark() && !lcl_PosOk( *pStartCrsr->GetMark() ) )
3267     {
3268         lcl_RemoveMark( pStartCrsr );
3269         bChanged = true;
3270     }
3271     if( !lcl_PosOk( *pStartCrsr->GetPoint() ) )
3272     {
3273         SwNodes & aNodes = GetDoc()->GetNodes();
3274         const SwNode* pStart = lcl_NodeContext( pStartCrsr->GetPoint()->nNode.GetNode() );
3275         SwNodeIndex aIdx( pStartCrsr->GetPoint()->nNode );
3276         SwNode * pNode = aNodes.GoPrevious(&aIdx);
3277         if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3278             aNodes.GoNext( &aIdx );
3279         if( pNode == NULL || lcl_NodeContext( *pNode ) != pStart )
3280         {
3281             /*
3282               If the start entry of the ring is invalid replace it with a
3283               cursor pointing to the beginning of the first content node in
3284               the document.
3285             */
3286             aIdx = (*(aNodes.GetEndOfContent().StartOfSectionNode()));
3287             pNode = aNodes.GoNext( &aIdx );
3288         }
3289         bool bFound = (pNode != NULL);
3290 
3291         ASSERT(bFound, "no content node found");
3292 
3293         if (bFound)
3294         {
3295             SwPaM aTmpPam(*pNode);
3296             *pStartCrsr = aTmpPam;
3297         }
3298 
3299         bChanged = true;
3300     }
3301 
3302     /*
3303       If at least one of the cursors in the ring have been deleted or
3304       replaced, remove the table cursor.
3305     */
3306     if (pTblCrsr != NULL && bChanged)
3307         TblCrsrToCursor();
3308 }
3309 
3310 // #111827#
3311 String SwCrsrShell::GetCrsrDescr() const
3312 {
3313     String aResult;
3314 
3315     if (IsMultiSelection())
3316         aResult += String(SW_RES(STR_MULTISEL));
3317     else
3318         aResult = GetDoc()->GetPaMDescr(*GetCrsr());
3319 
3320     return aResult;
3321 }
3322 
3323 // SMARTTAGS
3324 
3325 void lcl_FillRecognizerData( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3326                              uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3327                              const SwWrongList& rSmartTagList, xub_StrLen nCurrent )
3328 {
3329     // Insert smart tag information
3330     std::vector< rtl::OUString > aSmartTagTypes;
3331     std::vector< uno::Reference< container::XStringKeyMap > > aStringKeyMaps;
3332 
3333     for ( sal_uInt16 i = 0; i < rSmartTagList.Count(); ++i )
3334     {
3335         const xub_StrLen nSTPos = rSmartTagList.Pos( i );
3336         const xub_StrLen nSTLen = rSmartTagList.Len( i );
3337 
3338         if ( nSTPos <= nCurrent && nCurrent < nSTPos + nSTLen )
3339         {
3340             const SwWrongArea* pArea = rSmartTagList.GetElement( i );
3341             if ( pArea )
3342             {
3343                 aSmartTagTypes.push_back( pArea->maType );
3344                 aStringKeyMaps.push_back( pArea->mxPropertyBag );
3345             }
3346         }
3347     }
3348 
3349     if ( aSmartTagTypes.size() )
3350     {
3351         rSmartTagTypes.realloc( aSmartTagTypes.size() );
3352         rStringKeyMaps.realloc( aSmartTagTypes.size() );
3353 
3354         std::vector< rtl::OUString >::const_iterator aTypesIter = aSmartTagTypes.begin();
3355         sal_uInt16 i = 0;
3356         for ( aTypesIter = aSmartTagTypes.begin(); aTypesIter != aSmartTagTypes.end(); ++aTypesIter )
3357             rSmartTagTypes[i++] = *aTypesIter;
3358 
3359         std::vector< uno::Reference< container::XStringKeyMap > >::const_iterator aMapsIter = aStringKeyMaps.begin();
3360         i = 0;
3361         for ( aMapsIter = aStringKeyMaps.begin(); aMapsIter != aStringKeyMaps.end(); ++aMapsIter )
3362             rStringKeyMaps[i++] = *aMapsIter;
3363     }
3364 }
3365 
3366 void lcl_FillTextRange( uno::Reference<text::XTextRange>& rRange,
3367                    SwTxtNode& rNode, xub_StrLen nBegin, xub_StrLen nLen )
3368 {
3369     // create SwPosition for nStartIndex
3370     SwIndex aIndex( &rNode, nBegin );
3371     SwPosition aStartPos( rNode, aIndex );
3372 
3373     // create SwPosition for nEndIndex
3374     SwPosition aEndPos( aStartPos );
3375     aEndPos.nContent = nBegin + nLen;
3376 
3377     const uno::Reference<text::XTextRange> xRange =
3378         SwXTextRange::CreateXTextRange(*rNode.GetDoc(), aStartPos, &aEndPos);
3379 
3380     rRange = xRange;
3381 }
3382 
3383 void SwCrsrShell::GetSmartTagTerm( uno::Sequence< rtl::OUString >& rSmartTagTypes,
3384                                    uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3385                                    uno::Reference< text::XTextRange>& rRange ) const
3386 {
3387     if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3388         return;
3389 
3390     SwPaM* pCrsr = GetCrsr();
3391     SwPosition aPos( *pCrsr->GetPoint() );
3392     SwTxtNode *pNode = aPos.nNode.GetNode().GetTxtNode();
3393     if ( pNode && !pNode->IsInProtectSect() )
3394     {
3395         const SwWrongList *pSmartTagList = pNode->GetSmartTags();
3396         if ( pSmartTagList )
3397         {
3398             xub_StrLen nCurrent = aPos.nContent.GetIndex();
3399             xub_StrLen nBegin = nCurrent;
3400             xub_StrLen nLen = 1;
3401 
3402             if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3403             {
3404                 const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3405                 const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3406                 if ( pSubList )
3407                 {
3408                     pSmartTagList = pSubList;
3409                     nCurrent = 0;
3410                 }
3411 
3412                 lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3413                 lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3414             }
3415         }
3416     }
3417 }
3418 
3419 // see also SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
3420 void SwCrsrShell::GetSmartTagTerm( const Point& rPt, SwRect& rSelectRect,
3421                                    uno::Sequence< rtl::OUString >& rSmartTagTypes,
3422                                    uno::Sequence< uno::Reference< container::XStringKeyMap > >& rStringKeyMaps,
3423                                    uno::Reference<text::XTextRange>& rRange )
3424 {
3425     if ( !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
3426         return;
3427 
3428     SwPaM* pCrsr = GetCrsr();
3429     SwPosition aPos( *pCrsr->GetPoint() );
3430     Point aPt( rPt );
3431     SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
3432     SwSpecialPos aSpecialPos;
3433     eTmpState.pSpecialPos = &aSpecialPos;
3434     SwTxtNode *pNode;
3435     const SwWrongList *pSmartTagList;
3436 
3437     if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
3438         0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
3439         0 != (pSmartTagList = pNode->GetSmartTags()) &&
3440         !pNode->IsInProtectSect() )
3441     {
3442         xub_StrLen nCurrent = aPos.nContent.GetIndex();
3443         xub_StrLen nBegin = nCurrent;
3444         xub_StrLen nLen = 1;
3445 
3446         if( pSmartTagList->InWrongWord( nBegin, nLen ) && !pNode->IsSymbol(nBegin) )
3447         {
3448             const sal_uInt16 nIndex = pSmartTagList->GetWrongPos( nBegin );
3449             const SwWrongList* pSubList = pSmartTagList->SubList( nIndex );
3450             if ( pSubList )
3451             {
3452                 pSmartTagList = pSubList;
3453                 nCurrent = eTmpState.pSpecialPos->nCharOfst;
3454             }
3455 
3456             lcl_FillRecognizerData( rSmartTagTypes, rStringKeyMaps, *pSmartTagList, nCurrent );
3457             lcl_FillTextRange( rRange, *pNode, nBegin, nLen );
3458 
3459             // get smarttag word
3460             String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
3461 
3462             //save the start and end positons of the line and the starting point
3463             Push();
3464             LeftMargin();
3465             xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
3466             RightMargin();
3467             xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
3468             Pop(sal_False);
3469 
3470             // make sure the selection build later from the
3471             // data below does not include footnotes and other
3472             // "in word" character to the left and right in order
3473             // to preserve those. Therefore count those "in words"
3474             // in order to modify the selection accordingly.
3475             const sal_Unicode* pChar = aText.GetBuffer();
3476             xub_StrLen nLeft = 0;
3477             while (pChar && *pChar++ == CH_TXTATR_INWORD)
3478                 ++nLeft;
3479             pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
3480             xub_StrLen nRight = 0;
3481             while (pChar && *pChar-- == CH_TXTATR_INWORD)
3482                 ++nRight;
3483 
3484             aPos.nContent = nBegin + nLeft;
3485             pCrsr = GetCrsr();
3486             *pCrsr->GetPoint() = aPos;
3487             pCrsr->SetMark();
3488             ExtendSelection( sal_True, nLen - nLeft - nRight );
3489             //no determine the rectangle in the current line
3490             xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
3491             //take one less than the line end - otherwise the next line would be calculated
3492             xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
3493             Push();
3494             pCrsr->DeleteMark();
3495             SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
3496             rContent = nWordStart;
3497             SwRect aStartRect;
3498             SwCrsrMoveState aState;
3499             aState.bRealWidth = sal_True;
3500             SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
3501             SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), &rPt, pCrsr->GetPoint(), sal_False);
3502 
3503             pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
3504             rContent = nWordEnd;
3505             SwRect aEndRect;
3506             pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
3507             rSelectRect = aStartRect.Union( aEndRect );
3508             Pop(sal_False);
3509         }
3510     }
3511 }
3512 
3513