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