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