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