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