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