LCOV - code coverage report
Current view: top level - sw/source/core/crsr - swcrsr.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 740 1279 57.9 %
Date: 2014-11-03 Functions: 57 81 70.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <hintids.hxx>
      21             : #include <editeng/protitem.hxx>
      22             : #include <com/sun/star/i18n/WordType.hpp>
      23             : #include <com/sun/star/i18n/CharType.hpp>
      24             : #include <unotools/charclass.hxx>
      25             : #include <svl/ctloptions.hxx>
      26             : #include <swmodule.hxx>
      27             : #include <fmtcntnt.hxx>
      28             : #include <swtblfmt.hxx>
      29             : #include <swcrsr.hxx>
      30             : #include <unocrsr.hxx>
      31             : #include <doc.hxx>
      32             : #include <IDocumentUndoRedo.hxx>
      33             : #include <IDocumentRedlineAccess.hxx>
      34             : #include <IDocumentLayoutAccess.hxx>
      35             : #include <docary.hxx>
      36             : #include <ndtxt.hxx>
      37             : #include <section.hxx>
      38             : #include <swtable.hxx>
      39             : #include <cntfrm.hxx>
      40             : #include <rootfrm.hxx>
      41             : #include <txtfrm.hxx>
      42             : #include <scriptinfo.hxx>
      43             : #include <crstate.hxx>
      44             : #include <docsh.hxx>
      45             : #include <viewsh.hxx>
      46             : #include <frmatr.hxx>
      47             : #include <breakit.hxx>
      48             : #include <crsskip.hxx>
      49             : #include <vcl/msgbox.hxx>
      50             : #include <mdiexp.hxx>
      51             : #include <statstr.hrc>
      52             : #include <redline.hxx>
      53             : #include <txatbase.hxx>
      54             : 
      55             : using namespace ::com::sun::star::i18n;
      56             : 
      57             : static const sal_uInt16 coSrchRplcThreshold = 60000;
      58             : 
      59             : struct _PercentHdl
      60             : {
      61             :     SwDocShell* pDSh;
      62             :     sal_uLong nActPos;
      63             :     bool bBack, bNodeIdx;
      64             : 
      65           0 :     _PercentHdl( sal_uLong nStt, sal_uLong nEnd, SwDocShell* pSh )
      66           0 :         : pDSh(pSh), bBack(false), bNodeIdx(false)
      67             :     {
      68           0 :         nActPos = nStt;
      69           0 :         if( ( bBack = (nStt > nEnd )) )
      70             :         {
      71           0 :             sal_uLong n = nStt; nStt = nEnd; nEnd = n;
      72             :         }
      73           0 :         ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, 0 );
      74           0 :     }
      75             : 
      76           0 :     _PercentHdl( const SwPaM& rPam )
      77           0 :         : pDSh( (SwDocShell*)rPam.GetDoc()->GetDocShell() )
      78             :     {
      79             :         sal_uLong nStt, nEnd;
      80           0 :         if( rPam.GetPoint()->nNode == rPam.GetMark()->nNode )
      81             :         {
      82           0 :             bNodeIdx = false;
      83           0 :             nStt = rPam.GetMark()->nContent.GetIndex();
      84           0 :             nEnd = rPam.GetPoint()->nContent.GetIndex();
      85             :         }
      86             :         else
      87             :         {
      88           0 :             bNodeIdx = true;
      89           0 :             nStt = rPam.GetMark()->nNode.GetIndex();
      90           0 :             nEnd = rPam.GetPoint()->nNode.GetIndex();
      91             :         }
      92           0 :         nActPos = nStt;
      93           0 :         if( ( bBack = (nStt > nEnd )) )
      94             :         {
      95           0 :             sal_uLong n = nStt; nStt = nEnd; nEnd = n;
      96             :         }
      97           0 :         ::StartProgress( STR_STATSTR_SEARCH, nStt, nEnd, pDSh );
      98           0 :     }
      99             : 
     100           0 :     ~_PercentHdl()                      { ::EndProgress( pDSh ); }
     101             : 
     102           0 :     void NextPos( sal_uLong nPos ) const
     103           0 :         { ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh ); }
     104             : 
     105           0 :     void NextPos( SwPosition& rPos ) const
     106             :         {
     107             :             sal_uLong nPos;
     108           0 :             if( bNodeIdx )
     109           0 :                 nPos = rPos.nNode.GetIndex();
     110             :             else
     111           0 :                 nPos = rPos.nContent.GetIndex();
     112           0 :             ::SetProgressState( bBack ? nActPos - nPos : nPos, pDSh );
     113           0 :         }
     114             : };
     115             : 
     116      451844 : SwCursor::SwCursor( const SwPosition &rPos, SwPaM* pRing, bool bColumnSel )
     117             :     : SwPaM( rPos, pRing ), pSavePos( 0 ), mnRowSpanOffset( 0 ), nCursorBidiLevel( 0 ),
     118      451844 :     mbColumnSelection( bColumnSel )
     119             : {
     120      451844 : }
     121             : 
     122             : // @@@ semantic: no copy ctor.
     123           0 : SwCursor::SwCursor( SwCursor& rCpy )
     124             :     : SwPaM( rCpy ), pSavePos( 0 ), mnRowSpanOffset( rCpy.mnRowSpanOffset ),
     125           0 :     nCursorBidiLevel( rCpy.nCursorBidiLevel ), mbColumnSelection( rCpy.mbColumnSelection )
     126             : {
     127           0 : }
     128             : 
     129      904190 : SwCursor::~SwCursor()
     130             : {
     131      903684 :     while( pSavePos )
     132             :     {
     133           0 :         _SwCursor_SavePos* pNxt = pSavePos->pNext;
     134           0 :         delete pSavePos;
     135           0 :         pSavePos = pNxt;
     136             :     }
     137      452348 : }
     138             : 
     139         506 : SwCursor* SwCursor::Create( SwPaM* pRing ) const
     140             : {
     141         506 :     return new SwCursor( *GetPoint(), pRing, false );
     142             : }
     143             : 
     144          70 : bool SwCursor::IsReadOnlyAvailable() const
     145             : {
     146          70 :     return false;
     147             : }
     148             : 
     149         442 : bool SwCursor::IsSkipOverHiddenSections() const
     150             : {
     151         442 :     return true;
     152             : }
     153             : 
     154         442 : bool SwCursor::IsSkipOverProtectSections() const
     155             : {
     156         442 :     return !IsReadOnlyAvailable();
     157             : }
     158             : 
     159             : // CreateNewSavePos is virtual so that derived classes of cursor can implement
     160             : // own SaveObjects if needed and validate them in the virtual check routines.
     161      173400 : void SwCursor::SaveState()
     162             : {
     163      173400 :     _SwCursor_SavePos* pNew = CreateNewSavePos();
     164      173400 :     pNew->pNext = pSavePos;
     165      173400 :     pSavePos = pNew;
     166      173400 : }
     167             : 
     168      173400 : void SwCursor::RestoreState()
     169             : {
     170      173400 :     if( pSavePos ) // Robust
     171             :     {
     172      173400 :         _SwCursor_SavePos* pDel = pSavePos;
     173      173400 :         pSavePos = pSavePos->pNext;
     174      173400 :         delete pDel;
     175             :     }
     176      173400 : }
     177             : 
     178      173400 : _SwCursor_SavePos* SwCursor::CreateNewSavePos() const
     179             : {
     180      173400 :     return new _SwCursor_SavePos( *this );
     181             : }
     182             : 
     183             : /// determine if point is outside of the node-array's content area
     184          18 : bool SwCursor::IsNoCntnt() const
     185             : {
     186          18 :     return GetPoint()->nNode.GetIndex() <
     187          18 :             GetDoc()->GetNodes().GetEndOfExtras().GetIndex();
     188             : }
     189             : 
     190      118756 : bool SwCursor::IsSelOvrCheck(int)
     191             : {
     192      118756 :     return false;
     193             : }
     194             : 
     195             : // extracted from IsSelOvr()
     196          46 : bool SwTableCursor::IsSelOvrCheck(int eFlags)
     197             : {
     198          46 :     SwNodes& rNds = GetDoc()->GetNodes();
     199             :     // check sections of nodes array
     200          92 :     if( (nsSwCursorSelOverFlags::SELOVER_CHECKNODESSECTION & eFlags)
     201          46 :         && HasMark() )
     202             :     {
     203          16 :         SwNodeIndex aOldPos( rNds, GetSavePos()->nNode );
     204          16 :         if( !CheckNodesRange( aOldPos, GetPoint()->nNode, true ))
     205             :         {
     206           0 :             GetPoint()->nNode = aOldPos;
     207           0 :             GetPoint()->nContent.Assign( GetCntntNode(), GetSavePos()->nCntnt );
     208           0 :             return true;
     209          16 :         }
     210             :     }
     211          46 :     return SwCursor::IsSelOvrCheck(eFlags);
     212             : }
     213             : 
     214      118756 : bool SwCursor::IsSelOvr( int eFlags )
     215             : {
     216      118756 :     SwDoc* pDoc = GetDoc();
     217      118756 :     SwNodes& rNds = pDoc->GetNodes();
     218             : 
     219      118756 :     bool bSkipOverHiddenSections = IsSkipOverHiddenSections();
     220      118756 :     bool bSkipOverProtectSections = IsSkipOverProtectSections();
     221             : 
     222      118756 :     if ( IsSelOvrCheck( eFlags ) )
     223             :     {
     224           0 :         return true;
     225             :     }
     226             : 
     227      278644 :     if( pSavePos->nNode != GetPoint()->nNode.GetIndex() &&
     228             :         // (1997) in UI-ReadOnly everything is allowed
     229      159888 :         ( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() ))
     230             :     {
     231             :         // check new sections
     232       79944 :         SwNodeIndex& rPtIdx = GetPoint()->nNode;
     233       79944 :         const SwSectionNode* pSectNd = rPtIdx.GetNode().FindSectionNode();
     234       79944 :         if( pSectNd &&
     235          12 :             ((bSkipOverHiddenSections && pSectNd->GetSection().IsHiddenFlag() ) ||
     236           0 :             (bSkipOverProtectSections && pSectNd->GetSection().IsProtectFlag() )))
     237             :         {
     238           0 :             if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
     239             :             {
     240             :                 // then we're already done
     241           0 :                 RestoreSavePos();
     242           0 :                 return true;
     243             :             }
     244             : 
     245             :             // set cursor to new position:
     246           0 :             SwNodeIndex aIdx( rPtIdx );
     247           0 :             sal_Int32 nCntntPos = pSavePos->nCntnt;
     248           0 :             bool bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
     249             :             SwCntntNode* pCNd = bGoNxt
     250           0 :                 ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
     251           0 :                 : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
     252           0 :             if( !pCNd && ( nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION & eFlags ))
     253             :             {
     254           0 :                 bGoNxt = !bGoNxt;
     255           0 :                 pCNd = bGoNxt ? rNds.GoNextSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections)
     256           0 :                     : rNds.GoPrevSection( &rPtIdx, bSkipOverHiddenSections, bSkipOverProtectSections);
     257             :             }
     258             : 
     259           0 :             bool bIsValidPos = 0 != pCNd;
     260           0 :             const bool bValidNodesRange = bIsValidPos &&
     261           0 :                 ::CheckNodesRange( rPtIdx, aIdx, true );
     262           0 :             if( !bValidNodesRange )
     263             :             {
     264           0 :                 rPtIdx = pSavePos->nNode;
     265           0 :                 if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
     266             :                 {
     267           0 :                     bIsValidPos = false;
     268           0 :                     nCntntPos = 0;
     269           0 :                     rPtIdx = aIdx;
     270           0 :                     if( 0 == ( pCNd = rPtIdx.GetNode().GetCntntNode() ) )
     271             :                     {
     272             :                         // then to the beginning of the document
     273           0 :                         rPtIdx = rNds.GetEndOfExtras();
     274           0 :                         pCNd = rNds.GoNext( &rPtIdx );
     275             :                     }
     276             :                 }
     277             :             }
     278             : 
     279             :             // register ContentIndex:
     280           0 :             const sal_Int32 nTmpPos = bIsValidPos ? (bGoNxt ? 0 : pCNd->Len()) : nCntntPos;
     281           0 :             GetPoint()->nContent.Assign( pCNd, nTmpPos );
     282           0 :             if( !bIsValidPos || !bValidNodesRange ||
     283           0 :                 IsInProtectTable( true ) )
     284           0 :                 return true;
     285             :         }
     286             : 
     287             :         // is there a protected section in the section?
     288       79944 :         if( HasMark() && bSkipOverProtectSections)
     289             :         {
     290          28 :             sal_uLong nSttIdx = GetMark()->nNode.GetIndex(),
     291          28 :                 nEndIdx = GetPoint()->nNode.GetIndex();
     292          28 :             if( nEndIdx <= nSttIdx )
     293             :             {
     294           0 :                 sal_uLong nTmp = nSttIdx;
     295           0 :                 nSttIdx = nEndIdx;
     296           0 :                 nEndIdx = nTmp;
     297             :             }
     298             : 
     299          28 :             const SwSectionFmts& rFmts = pDoc->GetSections();
     300          28 :             for( sal_uInt16 n = 0; n < rFmts.size(); ++n )
     301             :             {
     302           0 :                 const SwSectionFmt* pFmt = rFmts[n];
     303           0 :                 const SvxProtectItem& rProtect = pFmt->GetProtect();
     304           0 :                 if( rProtect.IsCntntProtected() )
     305             :                 {
     306           0 :                     const SwFmtCntnt& rCntnt = pFmt->GetCntnt(false);
     307             :                     OSL_ENSURE( rCntnt.GetCntntIdx(), "No SectionNode?" );
     308           0 :                     sal_uLong nIdx = rCntnt.GetCntntIdx()->GetIndex();
     309           0 :                     if( nSttIdx <= nIdx && nEndIdx >= nIdx )
     310             :                     {
     311             :                         // if it is no linked section then we cannot select it
     312           0 :                         const SwSection& rSect = *pFmt->GetSection();
     313           0 :                         if( CONTENT_SECTION == rSect.GetType() )
     314             :                         {
     315           0 :                             RestoreSavePos();
     316           0 :                             return true;
     317             :                         }
     318             :                     }
     319             :                 }
     320             :             }
     321             :         }
     322             :     }
     323             : 
     324      118756 :     const SwNode* pNd = &GetPoint()->nNode.GetNode();
     325      118756 :     if( pNd->IsCntntNode() && !dynamic_cast<SwUnoCrsr*>(this) )
     326             :     {
     327         442 :         const SwCntntFrm* pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() );
     328         842 :         if( pFrm && pFrm->IsValid()
     329         346 :             && 0 == pFrm->Frm().Height()
     330         442 :             && 0 != ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) )
     331             :         {
     332             :             // skip to the next/prev valid paragraph with a layout
     333           0 :             SwNodeIndex& rPtIdx = GetPoint()->nNode;
     334           0 :             bool bGoNxt = pSavePos->nNode < rPtIdx.GetIndex();
     335           0 :             while( 0 != ( pFrm = ( bGoNxt ? pFrm->GetNextCntntFrm() : pFrm->GetPrevCntntFrm() ))
     336           0 :                    && 0 == pFrm->Frm().Height() )
     337             :                 ;
     338             : 
     339             :             // #i72394# skip to prev/next valid paragraph with a layout in case
     340             :             // the first search did not succeed:
     341           0 :             if( !pFrm )
     342             :             {
     343           0 :                 bGoNxt = !bGoNxt;
     344           0 :                 pFrm = ((SwCntntNode*)pNd)->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() );
     345           0 :                 while ( pFrm && 0 == pFrm->Frm().Height() )
     346             :                 {
     347             :                     pFrm = bGoNxt ? pFrm->GetNextCntntFrm()
     348           0 :                         :   pFrm->GetPrevCntntFrm();
     349             :                 }
     350             :             }
     351             : 
     352           0 :             SwCntntNode* pCNd = (pFrm != NULL) ? (SwCntntNode*)pFrm->GetNode() : NULL;
     353           0 :             if ( pCNd != NULL )
     354             :             {
     355             :                 // set this CntntNode as new position
     356           0 :                 rPtIdx = *pCNd;
     357           0 :                 pNd = pCNd;
     358             : 
     359             :                 // assign corresponding ContentIndex
     360           0 :                 const sal_Int32 nTmpPos = bGoNxt ? 0 : pCNd->Len();
     361           0 :                 GetPoint()->nContent.Assign( pCNd, nTmpPos );
     362             : 
     363           0 :                 if ( rPtIdx.GetIndex() == pSavePos->nNode
     364           0 :                      && nTmpPos == pSavePos->nCntnt )
     365             :                 {
     366             :                     // new position equals saved one
     367             :                     // --> trigger restore of saved pos by setting <pFrm> to NULL - see below
     368           0 :                     pFrm = NULL;
     369             :                 }
     370             : 
     371           0 :                 if ( IsInProtectTable( true ) )
     372             :                 {
     373             :                     // new position in protected table
     374             :                     // --> trigger restore of saved pos by setting <pFrm> to NULL - see below
     375           0 :                     pFrm = NULL;
     376             :                 }
     377             :             }
     378             :         }
     379             : 
     380         442 :         if( !pFrm )
     381             :         {
     382          42 :             DeleteMark();
     383          42 :             RestoreSavePos();
     384          42 :             return true; // we need a frame
     385             :         }
     386             :     }
     387             : 
     388             :     // is the cursor allowed to be in a protected node?
     389      118714 :     if( 0 == ( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags ) && !IsAtValidPos() )
     390             :     {
     391           0 :         DeleteMark();
     392           0 :         RestoreSavePos();
     393           0 :         return true;
     394             :     }
     395             : 
     396      118714 :     if( !HasMark() )
     397       30762 :         return false;
     398             : 
     399             :     // check for invalid sections
     400       87952 :     if( !::CheckNodesRange( GetMark()->nNode, GetPoint()->nNode, true ))
     401             :     {
     402           0 :         DeleteMark();
     403           0 :         RestoreSavePos();
     404           0 :         return true; // we need a frame
     405             :     }
     406             : 
     407      263856 :     if( (pNd = &GetMark()->nNode.GetNode())->IsCntntNode()
     408       87952 :         && !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() )
     409      254970 :         && !dynamic_cast<SwUnoCrsr*>(this) )
     410             :     {
     411           0 :         DeleteMark();
     412           0 :         RestoreSavePos();
     413           0 :         return true; // we need a frame
     414             :     }
     415             : 
     416             :     // assure that selection is only inside an InputField or contains the InputField completely
     417             :     {
     418       87952 :         const SwTxtAttr* pInputFldTxtAttrAtPoint = NULL;
     419       87952 :         SwTxtNode* pTxtNdAtPoint = GetPoint()->nNode.GetNode().GetTxtNode();
     420       87952 :         if ( pTxtNdAtPoint != NULL )
     421             :         {
     422             :             pInputFldTxtAttrAtPoint =
     423       87952 :                 pTxtNdAtPoint->GetTxtAttrAt( GetPoint()->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTxtNode::PARENT );
     424             :         }
     425             : 
     426       87952 :         const SwTxtAttr* pInputFldTxtAttrAtMark = NULL;
     427       87952 :         SwTxtNode* pTxtNdAtMark = GetMark()->nNode.GetNode().GetTxtNode();
     428       87952 :         if ( pTxtNdAtMark != NULL )
     429             :         {
     430             :             pInputFldTxtAttrAtMark =
     431       87952 :                 pTxtNdAtMark->GetTxtAttrAt( GetMark()->nContent.GetIndex(), RES_TXTATR_INPUTFIELD, SwTxtNode::PARENT );
     432             :         }
     433             : 
     434       87952 :         if ( pInputFldTxtAttrAtPoint != pInputFldTxtAttrAtMark )
     435             :         {
     436             :             const sal_uLong nRefNodeIdx =
     437           0 :                 ( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags )
     438             :                 ? pSavePos->nNode
     439           0 :                 : GetMark()->nNode.GetIndex();
     440             :             const sal_Int32 nRefContentIdx =
     441           0 :                 ( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags )
     442             :                 ? pSavePos->nCntnt
     443           0 :                 : GetMark()->nContent.GetIndex();
     444             :             const bool bIsForwardSelection =
     445           0 :                 nRefNodeIdx < GetPoint()->nNode.GetIndex()
     446           0 :                 || ( nRefNodeIdx == GetPoint()->nNode.GetIndex()
     447           0 :                      && nRefContentIdx < GetPoint()->nContent.GetIndex() );
     448             : 
     449           0 :             if ( pInputFldTxtAttrAtPoint != NULL )
     450             :             {
     451             :                 const sal_Int32 nNewPointPos =
     452           0 :                     bIsForwardSelection ? *(pInputFldTxtAttrAtPoint->End()) : pInputFldTxtAttrAtPoint->GetStart();
     453           0 :                 GetPoint()->nContent.Assign( pTxtNdAtPoint, nNewPointPos );
     454             :             }
     455             : 
     456           0 :             if ( pInputFldTxtAttrAtMark != NULL )
     457             :             {
     458             :                 const sal_Int32 nNewMarkPos =
     459           0 :                     bIsForwardSelection ? pInputFldTxtAttrAtMark->GetStart() : *(pInputFldTxtAttrAtMark->End());
     460           0 :                 GetMark()->nContent.Assign( pTxtNdAtMark, nNewMarkPos );
     461             :             }
     462             :         }
     463             :     }
     464             : 
     465       87952 :     const SwTableNode* pPtNd = GetPoint()->nNode.GetNode().FindTableNode();
     466       87952 :     const SwTableNode* pMrkNd = GetMark()->nNode.GetNode().FindTableNode();
     467             :     // both in no or in same table node
     468       87952 :     if( ( !pMrkNd && !pPtNd ) || pPtNd == pMrkNd )
     469       87952 :         return false;
     470             : 
     471             :     // in different tables or only mark in table
     472           0 :     if( ( pPtNd && pMrkNd ) || pMrkNd )
     473             :     {
     474             :         // not allowed, so go back to old position
     475           0 :         RestoreSavePos();
     476             :         // Crsr stays at old position
     477           0 :         return true;
     478             :     }
     479             : 
     480             :     // Note: this cannot happen in TableMode
     481           0 :     if( pPtNd )     // if only Point in Table then go behind/in front of table
     482             :     {
     483           0 :         if( nsSwCursorSelOverFlags::SELOVER_CHANGEPOS & eFlags )
     484             :         {
     485           0 :             bool bSelTop = GetPoint()->nNode.GetIndex() <
     486           0 :                 (( nsSwCursorSelOverFlags::SELOVER_TOGGLE & eFlags ) ? pSavePos->nNode
     487           0 :                 : GetMark()->nNode.GetIndex());
     488             : 
     489             :             do { // loop for table after table
     490           0 :                 sal_uLong nSEIdx = pPtNd->EndOfSectionIndex();
     491           0 :                 sal_uLong nSttEndTbl = nSEIdx + 1;
     492             : 
     493           0 :                 if( bSelTop )
     494           0 :                     nSttEndTbl = rNds[ nSEIdx ]->StartOfSectionIndex() - 1;
     495             : 
     496           0 :                 GetPoint()->nNode = nSttEndTbl;
     497           0 :                 const SwNode* pMyNd = &(GetNode());
     498             : 
     499           0 :                 if( pMyNd->IsSectionNode() || ( pMyNd->IsEndNode() &&
     500           0 :                     pMyNd->StartOfSectionNode()->IsSectionNode() ) )
     501             :                 {
     502           0 :                     pMyNd = bSelTop
     503           0 :                         ? rNds.GoPrevSection( &GetPoint()->nNode,true,false )
     504           0 :                         : rNds.GoNextSection( &GetPoint()->nNode,true,false );
     505             : 
     506             :                     /* #i12312# Handle failure of Go{Prev|Next}Section */
     507           0 :                     if ( 0 == pMyNd)
     508           0 :                         break;
     509             : 
     510           0 :                     if( 0 != ( pPtNd = pMyNd->FindTableNode() ))
     511           0 :                         continue;
     512             :                 }
     513             : 
     514             :                 // we permit these
     515           0 :                 if( pMyNd->IsCntntNode() &&
     516           0 :                     ::CheckNodesRange( GetMark()->nNode,
     517           0 :                     GetPoint()->nNode, true ))
     518             :                 {
     519             :                     // table in table
     520           0 :                     const SwTableNode* pOuterTableNd = pMyNd->FindTableNode();
     521           0 :                     if ( pOuterTableNd )
     522           0 :                         pMyNd = pOuterTableNd;
     523             :                     else
     524             :                     {
     525           0 :                         SwCntntNode* pCNd = (SwCntntNode*)pMyNd;
     526           0 :                         GetPoint()->nContent.Assign( pCNd, bSelTop ? pCNd->Len() : 0 );
     527           0 :                         return false;
     528             :                     }
     529             :                 }
     530           0 :                 if( bSelTop
     531           0 :                     ? ( !pMyNd->IsEndNode() || 0 == ( pPtNd = pMyNd->FindTableNode() ))
     532             :                     : 0 == ( pPtNd = pMyNd->GetTableNode() ))
     533           0 :                     break;
     534           0 :             } while( true );
     535             :         }
     536             : 
     537             :         // stay on old position
     538           0 :         RestoreSavePos();
     539           0 :         return true;
     540             :     }
     541             : 
     542           0 :     return false;
     543             : }
     544             : 
     545      119494 : bool SwCursor::IsInProtectTable( bool bMove, bool bChgCrsr )
     546             : {
     547      119494 :     SwCntntNode* pCNd = GetCntntNode();
     548      119494 :     if( !pCNd )
     549           0 :         return false;
     550             : 
     551             :     // No table, no protected cell:
     552      119494 :     const SwTableNode* pTableNode = pCNd->FindTableNode();
     553      119494 :     if ( !pTableNode )
     554       89614 :         return false;
     555             : 
     556             :     // Current position == last save position?
     557       29880 :     if ( pSavePos->nNode == GetPoint()->nNode.GetIndex() )
     558       23094 :         return false;
     559             : 
     560             :     // Check for convered cell:
     561        6786 :     bool bInCoveredCell = false;
     562        6786 :     const SwStartNode* pTmpSttNode = pCNd->FindTableBoxStartNode();
     563             :     OSL_ENSURE( pTmpSttNode, "In table, therefore I expect to get a SwTableBoxStartNode" );
     564        6786 :     const SwTableBox* pBox = pTmpSttNode ? pTableNode->GetTable().GetTblBox( pTmpSttNode->GetIndex() ) : 0; //Robust #151355
     565        6786 :     if ( pBox && pBox->getRowSpan() < 1 ) // Robust #151270
     566          18 :         bInCoveredCell = true;
     567             : 
     568             :     // Positions of covered cells are not acceptable:
     569        6786 :     if ( !bInCoveredCell )
     570             :     {
     571             :         // Position not protected?
     572        6768 :         if ( !pCNd->IsProtect() )
     573        6768 :             return false;
     574             : 
     575             :         // Cursor in protected cells allowed?
     576           0 :         if ( IsReadOnlyAvailable() )
     577           0 :             return false;
     578             :     }
     579             : 
     580             :     // If we reach this point, we are in a protected or covered table cell!
     581             : 
     582          18 :     if( !bMove )
     583             :     {
     584           0 :         if( bChgCrsr )
     585             :             // restore the last save position
     586           0 :             RestoreSavePos();
     587             : 
     588           0 :         return true; // Crsr stays at old position
     589             :     }
     590             : 
     591             :     // We are in a protected table cell. Traverse top to bottom?
     592          18 :     if( pSavePos->nNode < GetPoint()->nNode.GetIndex() )
     593             :     {
     594             :         // search next valid box
     595             :         // if there is another StartNode after the EndNode of a cell then
     596             :         // there is another cell
     597          18 :         SwNodeIndex aCellStt( *GetNode().FindTableBoxStartNode()->EndOfSectionNode(), 1 );
     598          18 :         bool bProt = true;
     599             : GoNextCell:
     600           0 :         do {
     601          18 :             if( !aCellStt.GetNode().IsStartNode() )
     602           6 :                 break;
     603          12 :             ++aCellStt;
     604          12 :             if( 0 == ( pCNd = aCellStt.GetNode().GetCntntNode() ))
     605           0 :                 pCNd = aCellStt.GetNodes().GoNext( &aCellStt );
     606          12 :             if( !( bProt = pCNd->IsProtect() ))
     607          12 :                 break;
     608           0 :             aCellStt.Assign( *pCNd->FindTableBoxStartNode()->EndOfSectionNode(), 1 );
     609             :         } while( bProt );
     610             : 
     611             : SetNextCrsr:
     612          24 :         if( !bProt ) // found free cell
     613             :         {
     614          18 :             GetPoint()->nNode = aCellStt;
     615          18 :             SwCntntNode* pTmpCNd = GetCntntNode();
     616          18 :             if( pTmpCNd )
     617             :             {
     618          18 :                 GetPoint()->nContent.Assign( pTmpCNd, 0 );
     619          18 :                 return false;
     620             :             }
     621             :             return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
     622           0 :                              nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
     623             :         }
     624             :         // end of table, so go to next node
     625           6 :         ++aCellStt;
     626             :         SwNode* pNd;
     627           6 :         if( ( pNd = &aCellStt.GetNode())->IsEndNode() || HasMark())
     628             :         {
     629             :             // if only table in FlyFrame or SSelection then stay on old position
     630           0 :             if( bChgCrsr )
     631           0 :                 RestoreSavePos();
     632           0 :             return true;
     633             :         }
     634           6 :         else if( pNd->IsTableNode() && aCellStt++ )
     635           0 :             goto GoNextCell;
     636             : 
     637           6 :         bProt = false; // index is now on a content node
     638           6 :         goto SetNextCrsr;
     639             :     }
     640             : 
     641             :     // search for the previous valid box
     642             :     {
     643             :         // if there is another EndNode in front of the StartNode than there
     644             :         // exists a previous cell
     645           0 :         SwNodeIndex aCellStt( *GetNode().FindTableBoxStartNode(), -1 );
     646             :         SwNode* pNd;
     647           0 :         bool bProt = true;
     648             : GoPrevCell:
     649           0 :         do {
     650           0 :             if( !( pNd = &aCellStt.GetNode())->IsEndNode() )
     651           0 :                 break;
     652           0 :             aCellStt.Assign( *pNd->StartOfSectionNode(), +1 );
     653           0 :             if( 0 == ( pCNd = aCellStt.GetNode().GetCntntNode() ))
     654           0 :                 pCNd = pNd->GetNodes().GoNext( &aCellStt );
     655           0 :             if( !( bProt = pCNd->IsProtect() ))
     656           0 :                 break;
     657           0 :             aCellStt.Assign( *pNd->FindTableBoxStartNode(), -1 );
     658             :         } while( bProt );
     659             : 
     660             : SetPrevCrsr:
     661           0 :         if( !bProt ) // found free cell
     662             :         {
     663           0 :             GetPoint()->nNode = aCellStt;
     664           0 :             SwCntntNode* pTmpCNd = GetCntntNode();
     665           0 :             if( pTmpCNd )
     666             :             {
     667           0 :                 GetPoint()->nContent.Assign( pTmpCNd, 0 );
     668           0 :                 return false;
     669             :             }
     670             :             return IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
     671           0 :                              nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
     672             :         }
     673             :         // at the beginning of a table, so go to next node
     674           0 :         aCellStt--;
     675           0 :         if( ( pNd = &aCellStt.GetNode())->IsStartNode() || HasMark() )
     676             :         {
     677             :             // if only table in FlyFrame or SSelection then stay on old position
     678           0 :             if( bChgCrsr )
     679           0 :                 RestoreSavePos();
     680           0 :             return true;
     681             :         }
     682           0 :         else if( pNd->StartOfSectionNode()->IsTableNode() && aCellStt-- )
     683           0 :             goto GoPrevCell;
     684             : 
     685           0 :         bProt = false; // index is now on a content node
     686           0 :         goto SetPrevCrsr;
     687             :     }
     688             : }
     689             : 
     690             : /// Return <true> if cursor can be set to this position
     691          46 : bool SwCursor::IsAtValidPos( bool bPoint ) const
     692             : {
     693          46 :     const SwDoc* pDoc = GetDoc();
     694          46 :     const SwPosition* pPos = bPoint ? GetPoint() : GetMark();
     695          46 :     const SwNode* pNd = &pPos->nNode.GetNode();
     696             : 
     697          46 :     if( pNd->IsCntntNode() && !((SwCntntNode*)pNd)->getLayoutFrm( pDoc->getIDocumentLayoutAccess().GetCurrentLayout() ) &&
     698           0 :         !dynamic_cast<const SwUnoCrsr*>(this) )
     699             :     {
     700           0 :         return false;
     701             :     }
     702             : 
     703             :     // #i45129# - in UI-ReadOnly everything is allowed
     704          46 :     if( !pDoc->GetDocShell() || !pDoc->GetDocShell()->IsReadOnlyUI() )
     705          46 :         return true;
     706             : 
     707           0 :     const bool bCrsrInReadOnly = IsReadOnlyAvailable();
     708           0 :     if( !bCrsrInReadOnly && pNd->IsProtect() )
     709           0 :         return false;
     710             : 
     711           0 :     const SwSectionNode* pSectNd = pNd->FindSectionNode();
     712           0 :     if( pSectNd && (pSectNd->GetSection().IsHiddenFlag() ||
     713           0 :                     ( !bCrsrInReadOnly && pSectNd->GetSection().IsProtectFlag() )))
     714           0 :         return false;
     715             : 
     716           0 :     return true;
     717             : }
     718             : 
     719          88 : void SwCursor::SaveTblBoxCntnt( const SwPosition* ) {}
     720             : 
     721             : /// set range for search in document
     722          46 : SwMoveFnCollection* SwCursor::MakeFindRange( SwDocPositions nStart,
     723             :                                 SwDocPositions nEnd, SwPaM* pRange ) const
     724             : {
     725          46 :     pRange->SetMark();
     726          46 :     FillFindPos( nStart, *pRange->GetMark() );
     727          46 :     FillFindPos( nEnd, *pRange->GetPoint() );
     728             : 
     729             :     // determine direction of search
     730          20 :     return ( DOCPOS_START == nStart || DOCPOS_OTHERSTART == nStart ||
     731          10 :               (DOCPOS_CURR == nStart &&
     732           0 :                 (DOCPOS_END == nEnd || DOCPOS_OTHEREND == nEnd ) ))
     733          92 :                 ? fnMoveForward : fnMoveBackward;
     734             : }
     735             : 
     736          10 : static sal_uLong lcl_FindSelection( SwFindParas& rParas, SwCursor* pCurCrsr,
     737             :                         SwMoveFn fnMove, SwCursor*& pFndRing,
     738             :                         SwPaM& aRegion, FindRanges eFndRngs,
     739             :                         bool bInReadOnly, bool& bCancel )
     740             : {
     741          10 :     SwDoc* pDoc = pCurCrsr->GetDoc();
     742          10 :     bool const bDoesUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
     743          10 :     int nFndRet = 0;
     744          10 :     sal_uLong nFound = 0;
     745          10 :     const bool bSrchBkwrd = fnMove == fnMoveBackward;
     746          10 :     SwPaM *pTmpCrsr = pCurCrsr, *pSaveCrsr = pCurCrsr;
     747             : 
     748             :     // only create progress bar for ShellCrsr
     749          10 :     bool bIsUnoCrsr = 0 != dynamic_cast<SwUnoCrsr*>(pCurCrsr);
     750          10 :     _PercentHdl* pPHdl = 0;
     751          10 :     sal_uInt16 nCrsrCnt = 0;
     752          10 :     if( FND_IN_SEL & eFndRngs )
     753             :     {
     754           0 :         while( pCurCrsr != ( pTmpCrsr = (SwPaM*)pTmpCrsr->GetNext() ))
     755           0 :             ++nCrsrCnt;
     756           0 :         if( nCrsrCnt && !bIsUnoCrsr )
     757           0 :             pPHdl = new _PercentHdl( 0, nCrsrCnt, pDoc->GetDocShell() );
     758             :     }
     759             :     else
     760          10 :         pSaveCrsr = (SwPaM*)pSaveCrsr->GetPrev();
     761             : 
     762          10 :     bool bEnd = false;
     763           8 :     do {
     764          10 :         aRegion.SetMark();
     765             :         // independent from search direction: SPoint is always bigger than mark
     766             :         // if the search area is valid
     767          10 :         SwPosition *pSttPos = aRegion.GetMark(),
     768          10 :                         *pEndPos = aRegion.GetPoint();
     769          10 :         *pSttPos = *pTmpCrsr->Start();
     770          10 :         *pEndPos = *pTmpCrsr->End();
     771          10 :         if( bSrchBkwrd )
     772           0 :             aRegion.Exchange();
     773             : 
     774          10 :         if( !nCrsrCnt && !pPHdl && !bIsUnoCrsr )
     775           0 :             pPHdl = new _PercentHdl( aRegion );
     776             : 
     777             :         // as long as found and not at same position
     778         526 :         while(  *pSttPos <= *pEndPos &&
     779             :                 0 != ( nFndRet = rParas.Find( pCurCrsr, fnMove,
     780         496 :                                             &aRegion, bInReadOnly )) &&
     781         232 :                 ( !pFndRing ||
     782          70 :                     *pFndRing->GetPoint() != *pCurCrsr->GetPoint() ||
     783           0 :                     *pFndRing->GetMark() != *pCurCrsr->GetMark() ))
     784             :         {
     785         162 :             if( !( FIND_NO_RING & nFndRet ))
     786             :             {
     787             :                 // #i24084# - create ring similar to the one in CreateCrsr
     788          74 :                 SwCursor* pNew = pCurCrsr->Create( pFndRing );
     789          74 :                 if( !pFndRing )
     790           4 :                     pFndRing = pNew;
     791             : 
     792          74 :                 pNew->SetMark();
     793          74 :                 *pNew->GetMark() = *pCurCrsr->GetMark();
     794             :             }
     795             : 
     796         162 :             ++nFound;
     797             : 
     798         162 :             if( !( eFndRngs & FND_IN_SELALL) )
     799             :             {
     800           0 :                 bEnd = true;
     801           0 :                 break;
     802             :             }
     803             : 
     804         162 :             if ((coSrchRplcThreshold == nFound)
     805           0 :                 && pDoc->GetIDocumentUndoRedo().DoesUndo()
     806         162 :                 && rParas.IsReplaceMode())
     807             :             {
     808           0 :                 short nRet = pCurCrsr->MaxReplaceArived();
     809           0 :                 if( RET_YES == nRet )
     810             :                 {
     811           0 :                     pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
     812           0 :                     pDoc->GetIDocumentUndoRedo().DoUndo(false);
     813             :                 }
     814             :                 else
     815             :                 {
     816           0 :                     bEnd = true;
     817           0 :                     if(RET_CANCEL == nRet)
     818             :                     {
     819           0 :                         bCancel = true;
     820             :                     }
     821           0 :                     break;
     822             :                 }
     823             :             }
     824             : 
     825         162 :             if( bSrchBkwrd )
     826             :                 // move pEndPos in front of the found area
     827           0 :                 *pEndPos = *pCurCrsr->Start();
     828             :             else
     829             :                 // move pSttPos behind the found area
     830         162 :                 *pSttPos = *pCurCrsr->End();
     831             : 
     832         162 :             if( *pSttPos == *pEndPos )
     833             :                 // in area but at the end => done
     834           0 :                 break;
     835             : 
     836         162 :             if( !nCrsrCnt && pPHdl )
     837             :             {
     838           0 :                 pPHdl->NextPos( *aRegion.GetMark() );
     839             :             }
     840             :         }
     841             : 
     842          10 :         if( bEnd || !( eFndRngs & ( FND_IN_SELALL | FND_IN_SEL )) )
     843             :             break;
     844             : 
     845           8 :         pTmpCrsr = ((SwPaM*)pTmpCrsr->GetNext());
     846           8 :         if( nCrsrCnt && pPHdl )
     847             :         {
     848           0 :             pPHdl->NextPos( ++pPHdl->nActPos );
     849             :         }
     850             : 
     851             :     } while( pTmpCrsr != pSaveCrsr );
     852             : 
     853          10 :     if( nFound && !pFndRing ) // if no ring should be created
     854           4 :         pFndRing = pCurCrsr->Create();
     855             : 
     856          10 :     delete pPHdl;
     857          10 :     pDoc->GetIDocumentUndoRedo().DoUndo(bDoesUndo);
     858          10 :     return nFound;
     859             : }
     860             : 
     861          10 : static bool lcl_MakeSelFwrd( const SwNode& rSttNd, const SwNode& rEndNd,
     862             :                         SwPaM& rPam, bool bFirst )
     863             : {
     864          10 :     if( rSttNd.GetIndex() + 1 == rEndNd.GetIndex() )
     865           0 :         return false;
     866             : 
     867          10 :     SwNodes& rNds = rPam.GetDoc()->GetNodes();
     868          10 :     rPam.DeleteMark();
     869             :     SwCntntNode* pCNd;
     870          10 :     if( !bFirst )
     871             :     {
     872          10 :         rPam.GetPoint()->nNode = rSttNd;
     873          10 :         pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
     874          10 :         if( !pCNd )
     875           0 :             return false;
     876          10 :         pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
     877             :     }
     878           0 :     else if( rSttNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
     879           0 :              rPam.GetPoint()->nNode.GetIndex() >= rEndNd.GetIndex() )
     880             :         // not in this section
     881           0 :         return false;
     882             : 
     883          10 :     rPam.SetMark();
     884          10 :     rPam.GetPoint()->nNode = rEndNd;
     885          10 :     pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
     886          10 :     if( !pCNd )
     887           0 :         return false;
     888          10 :     pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
     889             : 
     890          10 :     return *rPam.GetMark() < *rPam.GetPoint();
     891             : }
     892             : 
     893           0 : static bool lcl_MakeSelBkwrd( const SwNode& rSttNd, const SwNode& rEndNd,
     894             :                         SwPaM& rPam, bool bFirst )
     895             : {
     896           0 :     if( rEndNd.GetIndex() + 1 == rSttNd.GetIndex() )
     897           0 :         return false;
     898             : 
     899           0 :     SwNodes& rNds = rPam.GetDoc()->GetNodes();
     900           0 :     rPam.DeleteMark();
     901             :     SwCntntNode* pCNd;
     902           0 :     if( !bFirst )
     903             :     {
     904           0 :         rPam.GetPoint()->nNode = rSttNd;
     905           0 :         pCNd = rNds.GoPrevious( &rPam.GetPoint()->nNode );
     906           0 :         if( !pCNd )
     907           0 :             return false;
     908           0 :         pCNd->MakeEndIndex( &rPam.GetPoint()->nContent );
     909             :     }
     910           0 :     else if( rEndNd.GetIndex() > rPam.GetPoint()->nNode.GetIndex() ||
     911           0 :              rPam.GetPoint()->nNode.GetIndex() >= rSttNd.GetIndex() )
     912           0 :         return false;       // not in this section
     913             : 
     914           0 :     rPam.SetMark();
     915           0 :     rPam.GetPoint()->nNode = rEndNd;
     916           0 :     pCNd = rNds.GoNext( &rPam.GetPoint()->nNode );
     917           0 :     if( !pCNd )
     918           0 :         return false;
     919           0 :     pCNd->MakeStartIndex( &rPam.GetPoint()->nContent );
     920             : 
     921           0 :     return *rPam.GetPoint() < *rPam.GetMark();
     922             : }
     923             : 
     924             : // this method "searches" for all use cases because in SwFindParas is always the
     925             : // correct parameters and respective search method
     926          18 : sal_uLong SwCursor::FindAll( SwFindParas& rParas,
     927             :                             SwDocPositions nStart, SwDocPositions nEnde,
     928             :                             FindRanges eFndRngs, bool& bCancel )
     929             : {
     930          18 :     bCancel = false;
     931          18 :     SwCrsrSaveState aSaveState( *this );
     932             : 
     933             :     // create region without adding it to the ring
     934          36 :     SwPaM aRegion( *GetPoint() );
     935          18 :     SwMoveFn fnMove = MakeFindRange( nStart, nEnde, &aRegion );
     936             : 
     937          18 :     sal_uLong nFound = 0;
     938          18 :     const bool bMvBkwrd = fnMove == fnMoveBackward;
     939          18 :     bool bInReadOnly = IsReadOnlyAvailable();
     940             : 
     941          18 :     SwCursor* pFndRing = 0;
     942          18 :     SwNodes& rNds = GetDoc()->GetNodes();
     943             : 
     944             :     // search in sections?
     945          18 :     if( FND_IN_SEL & eFndRngs )
     946             :     {
     947             :         // if string was not found in region then get all sections (cursors
     948             :         // stays unchanged)
     949           0 :         if( 0 == ( nFound = lcl_FindSelection( rParas, this, fnMove,
     950             :                                                 pFndRing, aRegion, eFndRngs,
     951           0 :                                                 bInReadOnly, bCancel ) ))
     952           0 :             return nFound;
     953             : 
     954             :         // found string at least once; it's all in new Crsr ring thus delete old one
     955           0 :         while( GetNext() != this )
     956           0 :             delete GetNext();
     957             : 
     958           0 :         *GetPoint() = *pFndRing->GetPoint();
     959           0 :         SetMark();
     960           0 :         *GetMark() = *pFndRing->GetMark();
     961           0 :         pFndRing->MoveRingTo( this );
     962           0 :         delete pFndRing;
     963             :     }
     964          18 :     else if( FND_IN_OTHER & eFndRngs )
     965             :     {
     966             :         // put cursor as copy of current into ring
     967             :         // chaining points always to first created, so forward
     968           2 :         std::unique_ptr< SwCursor > pSav( Create( this ) ); // save the current cursor
     969             : 
     970             :         // if already outside of body text search from this position or start at
     971             :         // 1. base section
     972           4 :         if( bMvBkwrd
     973           0 :             ? lcl_MakeSelBkwrd( rNds.GetEndOfExtras(),
     974           0 :                     *rNds.GetEndOfPostIts().StartOfSectionNode(),
     975           0 :                      *this, rNds.GetEndOfExtras().GetIndex() >=
     976           0 :                     GetPoint()->nNode.GetIndex() )
     977           2 :             : lcl_MakeSelFwrd( *rNds.GetEndOfPostIts().StartOfSectionNode(),
     978           2 :                     rNds.GetEndOfExtras(), *this,
     979           2 :                     rNds.GetEndOfExtras().GetIndex() >=
     980           4 :                     GetPoint()->nNode.GetIndex() ))
     981             :         {
     982             :             nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
     983           2 :                                         aRegion, eFndRngs, bInReadOnly, bCancel );
     984             :         }
     985             : 
     986           2 :         if( !nFound )
     987             :         {
     988             :             // put back the old one
     989           2 :             *GetPoint() = *pSav->GetPoint();
     990           2 :             if( pSav->HasMark() )
     991             :             {
     992           0 :                 SetMark();
     993           0 :                 *GetMark() = *pSav->GetMark();
     994             :             }
     995             :             else
     996           2 :                 DeleteMark();
     997           2 :             return 0;
     998             :         }
     999           0 :         pSav.release();
    1000             : 
    1001           0 :         if( !( FND_IN_SELALL & eFndRngs ))
    1002             :         {
    1003             :             // there should only be a single one, thus add it
    1004             :             // independent from search direction: SPoint is always bigger than
    1005             :             // mark if the search area is valid
    1006           0 :             *GetPoint() = *pFndRing->GetPoint();
    1007           0 :             SetMark();
    1008           0 :             *GetMark() = *pFndRing->GetMark();
    1009             :         }
    1010             :         else
    1011             :         {
    1012             :             // found string at least once; it's all in new Crsr ring thus delete old one
    1013           0 :             while( GetNext() != this )
    1014           0 :                 delete GetNext();
    1015             : 
    1016           0 :             *GetPoint() = *pFndRing->GetPoint();
    1017           0 :             SetMark();
    1018           0 :             *GetMark() = *pFndRing->GetMark();
    1019           0 :             pFndRing->MoveRingTo( this );
    1020             :         }
    1021           0 :         delete pFndRing;
    1022             :     }
    1023          16 :     else if( FND_IN_SELALL & eFndRngs )
    1024             :     {
    1025           8 :         ::std::unique_ptr< SwCursor> pSav( Create( this ) );  // save the current cursor
    1026             : 
    1027           8 :         const SwNode* pSttNd = ( FND_IN_BODYONLY & eFndRngs )
    1028           0 :                             ? rNds.GetEndOfContent().StartOfSectionNode()
    1029           8 :                             : rNds.GetEndOfPostIts().StartOfSectionNode();
    1030             : 
    1031          16 :         if( bMvBkwrd
    1032           0 :             ? lcl_MakeSelBkwrd( rNds.GetEndOfContent(), *pSttNd, *this, false )
    1033           8 :             : lcl_MakeSelFwrd( *pSttNd, rNds.GetEndOfContent(), *this, false ))
    1034             :         {
    1035             :             nFound = lcl_FindSelection( rParas, this, fnMove, pFndRing,
    1036           8 :                                         aRegion, eFndRngs, bInReadOnly, bCancel );
    1037             :         }
    1038             : 
    1039           8 :         if( !nFound )
    1040             :         {
    1041             :             // put back the old one
    1042           0 :             *GetPoint() = *pSav->GetPoint();
    1043           0 :             if( pSav->HasMark() )
    1044             :             {
    1045           0 :                 SetMark();
    1046           0 :                 *GetMark() = *pSav->GetMark();
    1047             :             }
    1048             :             else
    1049           0 :                 DeleteMark();
    1050           0 :             return 0;
    1051             :         }
    1052           8 :         pSav.release();
    1053          24 :         while( GetNext() != this )
    1054           8 :             delete GetNext();
    1055             : 
    1056           8 :         *GetPoint() = *pFndRing->GetPoint();
    1057           8 :         SetMark();
    1058           8 :         *GetMark() = *pFndRing->GetMark();
    1059           8 :         pFndRing->MoveRingTo( this );
    1060           8 :         delete pFndRing;
    1061             :     }
    1062             :     else
    1063             :     {
    1064             :         // if a GetMark is set then keep the GetMark of the found object
    1065             :         // This allows spanning an area with this search.
    1066           8 :         SwPosition aMarkPos( *GetMark() );
    1067           8 :         const bool bMarkPos = HasMark() && !eFndRngs;
    1068             : 
    1069          16 :         if( 0 != (nFound = rParas.Find( this, fnMove,
    1070           8 :                                         &aRegion, bInReadOnly ) ? 1 : 0)
    1071           8 :             && bMarkPos )
    1072           0 :             *GetMark() = aMarkPos;
    1073             :     }
    1074             : 
    1075          16 :     if( nFound && SwCursor::IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE ) )
    1076           0 :         nFound = 0;
    1077          34 :     return nFound;
    1078             : }
    1079             : 
    1080         100 : void SwCursor::FillFindPos( SwDocPositions ePos, SwPosition& rPos ) const
    1081             : {
    1082         100 :     bool bIsStart = true;
    1083         100 :     SwCntntNode* pCNd = 0;
    1084         100 :     SwNodes& rNds = GetDoc()->GetNodes();
    1085             : 
    1086         100 :     switch( ePos )
    1087             :     {
    1088             :     case DOCPOS_START:
    1089          34 :         rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
    1090          34 :         pCNd = rNds.GoNext( &rPos.nNode );
    1091          34 :         break;
    1092             :     case DOCPOS_END:
    1093          36 :         rPos.nNode = rNds.GetEndOfContent();
    1094          36 :         pCNd = rNds.GoPrevious( &rPos.nNode );
    1095          36 :         bIsStart = false;
    1096          36 :         break;
    1097             :     case DOCPOS_OTHERSTART:
    1098          10 :         rPos.nNode = *rNds[ sal_uLong(0) ];
    1099          10 :         pCNd = rNds.GoNext( &rPos.nNode );
    1100          10 :         break;
    1101             :     case DOCPOS_OTHEREND:
    1102          10 :         rPos.nNode = *rNds.GetEndOfContent().StartOfSectionNode();
    1103          10 :         pCNd = rNds.GoPrevious( &rPos.nNode );
    1104          10 :         bIsStart = false;
    1105          10 :         break;
    1106             :     default:
    1107          10 :         rPos = *GetPoint();
    1108             :     }
    1109             : 
    1110         100 :     if( pCNd )
    1111             :     {
    1112          82 :         rPos.nContent.Assign( pCNd, bIsStart ? 0 : pCNd->Len() );
    1113             :     }
    1114         100 : }
    1115             : 
    1116           0 : short SwCursor::MaxReplaceArived()
    1117             : {
    1118           0 :     return RET_YES;
    1119             : }
    1120             : 
    1121          10 : bool SwCursor::IsStartWord( sal_Int16 nWordType ) const
    1122             : {
    1123          10 :     return IsStartWordWT( nWordType );
    1124             : }
    1125             : 
    1126           0 : bool SwCursor::IsEndWord( sal_Int16 nWordType ) const
    1127             : {
    1128           0 :     return IsEndWordWT( nWordType );
    1129             : }
    1130             : 
    1131           0 : bool SwCursor::IsInWord( sal_Int16 nWordType ) const
    1132             : {
    1133           0 :     return IsInWordWT( nWordType );
    1134             : }
    1135             : 
    1136           0 : bool SwCursor::GoStartWord()
    1137             : {
    1138           0 :     return GoStartWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
    1139             : }
    1140             : 
    1141           0 : bool SwCursor::GoEndWord()
    1142             : {
    1143           0 :     return GoEndWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
    1144             : }
    1145             : 
    1146           6 : bool SwCursor::GoNextWord()
    1147             : {
    1148           6 :     return GoNextWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
    1149             : }
    1150             : 
    1151           0 : bool SwCursor::GoPrevWord()
    1152             : {
    1153           0 :     return GoPrevWordWT( WordType::ANYWORD_IGNOREWHITESPACES );
    1154             : }
    1155             : 
    1156           2 : bool SwCursor::SelectWord( SwViewShell* pViewShell, const Point* pPt )
    1157             : {
    1158           2 :     return SelectWordWT( pViewShell, WordType::ANYWORD_IGNOREWHITESPACES, pPt );
    1159             : }
    1160             : 
    1161          36 : bool SwCursor::IsStartWordWT( sal_Int16 nWordType ) const
    1162             : {
    1163          36 :     bool bRet = false;
    1164          36 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1165          36 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1166             :     {
    1167          36 :         const sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1168          72 :         bRet = g_pBreakIt->GetBreakIter()->isBeginWord(
    1169          36 :                             pTxtNd->GetTxt(), nPtPos,
    1170          36 :                             g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos )),
    1171          72 :                             nWordType );
    1172             :     }
    1173          36 :     return bRet;
    1174             : }
    1175             : 
    1176          50 : bool SwCursor::IsEndWordWT( sal_Int16 nWordType ) const
    1177             : {
    1178          50 :     bool bRet = false;
    1179          50 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1180          50 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1181             :     {
    1182          50 :         const sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1183         100 :         bRet = g_pBreakIt->GetBreakIter()->isEndWord(
    1184          50 :                             pTxtNd->GetTxt(), nPtPos,
    1185          50 :                             g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
    1186         100 :                             nWordType );
    1187             : 
    1188             :     }
    1189          50 :     return bRet;
    1190             : }
    1191             : 
    1192           0 : bool SwCursor::IsInWordWT( sal_Int16 nWordType ) const
    1193             : {
    1194           0 :     bool bRet = false;
    1195           0 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1196           0 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1197             :     {
    1198           0 :         const sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1199           0 :         Boundary aBoundary = g_pBreakIt->GetBreakIter()->getWordBoundary(
    1200           0 :                             pTxtNd->GetTxt(), nPtPos,
    1201           0 :                             g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
    1202             :                             nWordType,
    1203           0 :                             sal_True );
    1204             : 
    1205           0 :         bRet = aBoundary.startPos != aBoundary.endPos &&
    1206           0 :                 aBoundary.startPos <= nPtPos &&
    1207           0 :                     nPtPos <= aBoundary.endPos;
    1208           0 :         if(bRet)
    1209             :         {
    1210           0 :             const CharClass& rCC = GetAppCharClass();
    1211           0 :             bRet = rCC.isLetterNumeric( pTxtNd->GetTxt(), aBoundary.startPos );
    1212             :         }
    1213             :     }
    1214           0 :     return bRet;
    1215             : }
    1216             : 
    1217           0 : bool SwCursor::IsStartEndSentence( bool bEnd ) const
    1218             : {
    1219             :     bool bRet = bEnd ?
    1220           0 :                     GetCntntNode() && GetPoint()->nContent == GetCntntNode()->Len() :
    1221           0 :                     GetPoint()->nContent.GetIndex() == 0;
    1222             : 
    1223           0 :     if( !bRet )
    1224             :     {
    1225           0 :         SwCursor aCrsr(*GetPoint(), 0, false);
    1226           0 :         SwPosition aOrigPos = *aCrsr.GetPoint();
    1227           0 :         aCrsr.GoSentence( bEnd ? SwCursor::END_SENT : SwCursor::START_SENT );
    1228           0 :         bRet = aOrigPos == *aCrsr.GetPoint();
    1229             :     }
    1230           0 :     return bRet;
    1231             : }
    1232             : 
    1233          10 : bool SwCursor::GoStartWordWT( sal_Int16 nWordType )
    1234             : {
    1235          10 :     bool bRet = false;
    1236          10 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1237          10 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1238             :     {
    1239          10 :         SwCrsrSaveState aSave( *this );
    1240          10 :         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1241          20 :         nPtPos = g_pBreakIt->GetBreakIter()->getWordBoundary(
    1242          10 :                             pTxtNd->GetTxt(), nPtPos,
    1243          10 :                             g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
    1244             :                             nWordType,
    1245          20 :                             sal_False ).startPos;
    1246             : 
    1247          10 :         if (nPtPos < pTxtNd->GetTxt().getLength() && nPtPos >= 0)
    1248             :         {
    1249          10 :             GetPoint()->nContent = nPtPos;
    1250          10 :             if( !IsSelOvr() )
    1251          10 :                 bRet = true;
    1252          10 :         }
    1253             :     }
    1254          10 :     return bRet;
    1255             : }
    1256             : 
    1257          24 : bool SwCursor::GoEndWordWT( sal_Int16 nWordType )
    1258             : {
    1259          24 :     bool bRet = false;
    1260          24 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1261          24 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1262             :     {
    1263          24 :         SwCrsrSaveState aSave( *this );
    1264          24 :         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1265          48 :         nPtPos = g_pBreakIt->GetBreakIter()->getWordBoundary(
    1266          24 :                             pTxtNd->GetTxt(), nPtPos,
    1267          24 :                             g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
    1268             :                             nWordType,
    1269          48 :                             sal_True ).endPos;
    1270             : 
    1271          48 :         if (nPtPos <= pTxtNd->GetTxt().getLength() && nPtPos >= 0 &&
    1272          24 :             GetPoint()->nContent.GetIndex() != nPtPos )
    1273             :         {
    1274          24 :             GetPoint()->nContent = nPtPos;
    1275          24 :             if( !IsSelOvr() )
    1276          24 :                 bRet = true;
    1277          24 :         }
    1278             :     }
    1279          24 :     return bRet;
    1280             : }
    1281             : 
    1282          14 : bool SwCursor::GoNextWordWT( sal_Int16 nWordType )
    1283             : {
    1284          14 :     bool bRet = false;
    1285          14 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1286          14 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1287             :     {
    1288          14 :         SwCrsrSaveState aSave( *this );
    1289          14 :         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1290             : 
    1291          28 :         nPtPos = g_pBreakIt->GetBreakIter()->nextWord(
    1292          14 :                                 pTxtNd->GetTxt(), nPtPos,
    1293          14 :             g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
    1294          28 :                     nWordType ).startPos;
    1295             : 
    1296          14 :         if (nPtPos < pTxtNd->GetTxt().getLength() && nPtPos >= 0)
    1297             :         {
    1298           8 :             GetPoint()->nContent = nPtPos;
    1299           8 :             if( !IsSelOvr() )
    1300           8 :                 bRet = true;
    1301          14 :         }
    1302             :     }
    1303          14 :     return bRet;
    1304             : }
    1305             : 
    1306          10 : bool SwCursor::GoPrevWordWT( sal_Int16 nWordType )
    1307             : {
    1308          10 :     bool bRet = false;
    1309          10 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1310          10 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1311             :     {
    1312          10 :         SwCrsrSaveState aSave( *this );
    1313          10 :         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1314          10 :         const sal_Int32 nPtStart = nPtPos;
    1315             : 
    1316          10 :         if( nPtPos )
    1317          10 :             --nPtPos;
    1318          20 :         nPtPos = g_pBreakIt->GetBreakIter()->previousWord(
    1319          10 :                                 pTxtNd->GetTxt(), nPtStart,
    1320          10 :             g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos, 1 ) ),
    1321          20 :                     nWordType ).startPos;
    1322             : 
    1323          10 :         if (nPtPos < pTxtNd->GetTxt().getLength() && nPtPos >= 0)
    1324             :         {
    1325          10 :             GetPoint()->nContent = nPtPos;
    1326          10 :             if( !IsSelOvr() )
    1327          10 :                 bRet = true;
    1328          10 :         }
    1329             :     }
    1330          10 :     return bRet;
    1331             : }
    1332             : 
    1333           2 : bool SwCursor::SelectWordWT( SwViewShell* pViewShell, sal_Int16 nWordType, const Point* pPt )
    1334             : {
    1335           2 :     SwCrsrSaveState aSave( *this );
    1336             : 
    1337           2 :     bool bRet = false;
    1338           2 :     bool bForward = true;
    1339           2 :     DeleteMark();
    1340           2 :     const SwRootFrm* pLayout = pViewShell->GetLayout();
    1341           2 :     if( pPt && 0 != pLayout )
    1342             :     {
    1343             :         // set the cursor to the layout position
    1344           0 :         Point aPt( *pPt );
    1345           0 :         pLayout->GetCrsrOfst( GetPoint(), aPt );
    1346             :     }
    1347             : 
    1348           2 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1349           2 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1350             :     {
    1351             :         // Should we select the whole fieldmark?
    1352           2 :         const IDocumentMarkAccess* pMarksAccess = GetDoc()->getIDocumentMarkAccess( );
    1353           2 :         sw::mark::IMark* pMark = GetPoint() ? pMarksAccess->getFieldmarkFor( *GetPoint( ) ) : NULL;
    1354           2 :         if ( pMark )
    1355             :         {
    1356           0 :             const SwPosition rStart = pMark->GetMarkStart();
    1357           0 :             GetPoint()->nNode = rStart.nNode;
    1358           0 :             GetPoint()->nContent = rStart.nContent;
    1359           0 :             GetPoint()->nContent++; // Don't select the start delimiter
    1360             : 
    1361           0 :             const SwPosition rEnd = pMark->GetMarkEnd();
    1362             : 
    1363           0 :             if ( rStart != rEnd )
    1364             :             {
    1365           0 :                 SetMark();
    1366           0 :                 GetMark()->nNode = rEnd.nNode;
    1367           0 :                 GetMark()->nContent = rEnd.nContent;
    1368           0 :                 GetMark()->nContent--; //Don't select the end delimiter
    1369             :             }
    1370           0 :             bRet = true;
    1371             :         }
    1372             :         else
    1373             :         {
    1374           2 :             const sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1375           4 :             Boundary aBndry( g_pBreakIt->GetBreakIter()->getWordBoundary(
    1376           2 :                                 pTxtNd->GetTxt(), nPtPos,
    1377           2 :                                 g_pBreakIt->GetLocale( pTxtNd->GetLang( nPtPos ) ),
    1378             :                                 nWordType,
    1379           4 :                                 bForward ));
    1380             : 
    1381           2 :             if( aBndry.startPos != aBndry.endPos )
    1382             :             {
    1383           2 :                 GetPoint()->nContent = aBndry.endPos;
    1384           2 :                 if( !IsSelOvr() )
    1385             :                 {
    1386           2 :                     SetMark();
    1387           2 :                     GetMark()->nContent = aBndry.startPos;
    1388           2 :                     if (sw::mark::IMark* pAnnotationMark = pMarksAccess->getAnnotationMarkFor(*GetPoint()))
    1389             :                     {
    1390             :                         // An annotation mark covers the selected word. Check
    1391             :                         // if it covers only the word: in that case we select
    1392             :                         // the comment anchor as well.
    1393           4 :                         bool bStartMatch = GetMark()->nNode == pAnnotationMark->GetMarkStart().nNode &&
    1394           4 :                             GetMark()->nContent == pAnnotationMark->GetMarkStart().nContent;
    1395           4 :                         bool bEndMatch = GetPoint()->nNode == pAnnotationMark->GetMarkEnd().nNode &&
    1396           4 :                             GetPoint()->nContent.GetIndex() + 1 == pAnnotationMark->GetMarkEnd().nContent.GetIndex();
    1397           2 :                         if (bStartMatch && bEndMatch)
    1398           2 :                             GetPoint()->nContent++;
    1399             :                     }
    1400           2 :                     if( !IsSelOvr() )
    1401           2 :                         bRet = true;
    1402             :                 }
    1403             :             }
    1404             :         }
    1405             :     }
    1406             : 
    1407           2 :     if( !bRet )
    1408             :     {
    1409           0 :         DeleteMark();
    1410           0 :         RestoreSavePos();
    1411             :     }
    1412           2 :     return bRet;
    1413             : }
    1414             : 
    1415          44 : static OUString lcl_MaskDeletedRedlines( const SwTxtNode* pTxtNd )
    1416             : {
    1417          44 :     OUString aRes;
    1418          44 :     if (pTxtNd)
    1419             :     {
    1420             :         //mask deleted redlines
    1421          44 :         OUString sNodeText(pTxtNd->GetTxt());
    1422          44 :         const SwDoc& rDoc = *pTxtNd->GetDoc();
    1423          44 :         const bool nShowChg = IDocumentRedlineAccess::IsShowChanges( rDoc.getIDocumentRedlineAccess().GetRedlineMode() );
    1424          44 :         if ( nShowChg )
    1425             :         {
    1426          44 :             sal_uInt16 nAct = rDoc.getIDocumentRedlineAccess().GetRedlinePos( *pTxtNd, USHRT_MAX );
    1427          44 :             for ( ; nAct < rDoc.getIDocumentRedlineAccess().GetRedlineTbl().size(); nAct++ )
    1428             :             {
    1429           0 :                 const SwRangeRedline* pRed = rDoc.getIDocumentRedlineAccess().GetRedlineTbl()[ nAct ];
    1430           0 :                 if ( pRed->Start()->nNode > pTxtNd->GetIndex() )
    1431           0 :                     break;
    1432             : 
    1433           0 :                 if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
    1434             :                 {
    1435             :                     sal_Int32 nStart, nEnd;
    1436           0 :                     pRed->CalcStartEnd( pTxtNd->GetIndex(), nStart, nEnd );
    1437             : 
    1438           0 :                     while ( nStart < nEnd && nStart < sNodeText.getLength() )
    1439           0 :                         sNodeText = sNodeText.replaceAt( nStart++, 1, OUString(CH_TXTATR_INWORD) );
    1440             :                 }
    1441             :             }
    1442             :         }
    1443          44 :         aRes = sNodeText;
    1444             :     }
    1445          44 :     return aRes;
    1446             : }
    1447             : 
    1448          44 : bool SwCursor::GoSentence( SentenceMoveType eMoveType )
    1449             : {
    1450          44 :     bool bRet = false;
    1451          44 :     const SwTxtNode* pTxtNd = GetNode().GetTxtNode();
    1452          44 :     if( pTxtNd && g_pBreakIt->GetBreakIter().is() )
    1453             :     {
    1454          44 :         OUString sNodeText( lcl_MaskDeletedRedlines( pTxtNd ) );
    1455             : 
    1456          86 :         SwCrsrSaveState aSave( *this );
    1457          44 :         sal_Int32 nPtPos = GetPoint()->nContent.GetIndex();
    1458          44 :         switch ( eMoveType )
    1459             :         {
    1460             :         case START_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
    1461          16 :             nPtPos = g_pBreakIt->GetBreakIter()->beginOfSentence(
    1462             :                                     sNodeText,
    1463             :                                     nPtPos, g_pBreakIt->GetLocale(
    1464           8 :                                             pTxtNd->GetLang( nPtPos ) ));
    1465           8 :             break;
    1466             :         case END_SENT: /* when modifying: see also ExpandToSentenceBorders below! */
    1467          28 :             nPtPos = g_pBreakIt->GetBreakIter()->endOfSentence(
    1468             :                                     sNodeText,
    1469             :                                     nPtPos, g_pBreakIt->GetLocale(
    1470          14 :                                                 pTxtNd->GetLang( nPtPos ) ));
    1471          14 :             break;
    1472             :         case NEXT_SENT:
    1473             :             {
    1474          20 :                 nPtPos = g_pBreakIt->GetBreakIter()->endOfSentence(
    1475             :                                         sNodeText,
    1476             :                                         nPtPos, g_pBreakIt->GetLocale(
    1477          10 :                                                     pTxtNd->GetLang( nPtPos ) ));
    1478          30 :                 while (nPtPos>=0 && ++nPtPos < sNodeText.getLength()
    1479          14 :                        && sNodeText[nPtPos] == ' ' /*isWhiteSpace( aTxt.GetChar(nPtPos)*/ )
    1480             :                     ;
    1481          10 :                 break;
    1482             :             }
    1483             :         case PREV_SENT:
    1484          24 :             nPtPos = g_pBreakIt->GetBreakIter()->beginOfSentence(
    1485             :                                     sNodeText,
    1486             :                                     nPtPos, g_pBreakIt->GetLocale(
    1487          12 :                                                 pTxtNd->GetLang( nPtPos ) ));
    1488          12 :             if (nPtPos == 0)
    1489           2 :                 return false;   // the previous sentence is not in this paragraph
    1490          10 :             if (nPtPos > 0)
    1491          20 :                 nPtPos = g_pBreakIt->GetBreakIter()->beginOfSentence(
    1492             :                                     sNodeText,
    1493             :                                     nPtPos - 1, g_pBreakIt->GetLocale(
    1494          10 :                                                 pTxtNd->GetLang( nPtPos ) ));
    1495          10 :             break;
    1496             :         }
    1497             : 
    1498             :         // it is allowed to place the PaM just behind the last
    1499             :         // character in the text thus <= ...Len
    1500          42 :         if (nPtPos <= pTxtNd->GetTxt().getLength() && nPtPos >= 0)
    1501             :         {
    1502          42 :             GetPoint()->nContent = nPtPos;
    1503          42 :             if( !IsSelOvr() )
    1504          42 :                 bRet = true;
    1505          42 :         }
    1506             :     }
    1507          42 :     return bRet;
    1508             : }
    1509             : 
    1510           0 : bool SwCursor::ExpandToSentenceBorders()
    1511             : {
    1512           0 :     bool bRes = false;
    1513           0 :     const SwTxtNode* pStartNd = Start()->nNode.GetNode().GetTxtNode();
    1514           0 :     const SwTxtNode* pEndNd   = End()->nNode.GetNode().GetTxtNode();
    1515           0 :     if (pStartNd && pEndNd && g_pBreakIt->GetBreakIter().is())
    1516             :     {
    1517           0 :         if (!HasMark())
    1518           0 :             SetMark();
    1519             : 
    1520           0 :         OUString sStartText( lcl_MaskDeletedRedlines( pStartNd ) );
    1521           0 :         OUString sEndText( pStartNd == pEndNd? sStartText : lcl_MaskDeletedRedlines( pEndNd ) );
    1522             : 
    1523           0 :         SwCrsrSaveState aSave( *this );
    1524           0 :         sal_Int32 nStartPos = Start()->nContent.GetIndex();
    1525           0 :         sal_Int32 nEndPos   = End()->nContent.GetIndex();
    1526             : 
    1527           0 :         nStartPos = g_pBreakIt->GetBreakIter()->beginOfSentence(
    1528             :                                 sStartText, nStartPos,
    1529           0 :                                 g_pBreakIt->GetLocale( pStartNd->GetLang( nStartPos ) ) );
    1530           0 :         nEndPos   = g_pBreakIt->GetBreakIter()->endOfSentence(
    1531             :                                 sEndText, nEndPos,
    1532           0 :                                 g_pBreakIt->GetLocale( pEndNd->GetLang( nEndPos ) ) );
    1533             : 
    1534             :         // it is allowed to place the PaM just behind the last
    1535             :         // character in the text thus <= ...Len
    1536           0 :         bool bChanged = false;
    1537           0 :         if (nStartPos <= pStartNd->GetTxt().getLength() && nStartPos >= 0)
    1538             :         {
    1539           0 :             GetMark()->nContent = nStartPos;
    1540           0 :             bChanged = true;
    1541             :         }
    1542           0 :         if (nEndPos <= pEndNd->GetTxt().getLength() && nEndPos >= 0)
    1543             :         {
    1544           0 :             GetPoint()->nContent = nEndPos;
    1545           0 :             bChanged = true;
    1546             :         }
    1547           0 :         if (bChanged && !IsSelOvr())
    1548           0 :             bRes = true;
    1549             :     }
    1550           0 :     return bRes;
    1551             : }
    1552             : 
    1553           8 : bool SwTableCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 /*nMode*/,
    1554             :     bool /*bVisualAllowed*/, bool /*bSkipHidden*/, bool /*bInsertCrsr*/ )
    1555             : {
    1556           4 :     return bLeft ? GoPrevCell( nCnt )
    1557          12 :                  : GoNextCell( nCnt );
    1558             : }
    1559             : 
    1560             : // calculate cursor bidi level: extracted from LeftRight()
    1561             : const SwCntntFrm*
    1562          90 : SwCursor::DoSetBidiLevelLeftRight(
    1563             :     bool & io_rbLeft, bool bVisualAllowed, bool bInsertCrsr)
    1564             : {
    1565             :     // calculate cursor bidi level
    1566          90 :     const SwCntntFrm* pSttFrm = NULL;
    1567          90 :     SwNode& rNode = GetPoint()->nNode.GetNode();
    1568             : 
    1569          90 :     if( rNode.IsTxtNode() )
    1570             :     {
    1571          90 :         const SwTxtNode& rTNd = *rNode.GetTxtNode();
    1572          90 :         SwIndex& rIdx = GetPoint()->nContent;
    1573          90 :         sal_Int32 nPos = rIdx.GetIndex();
    1574             : 
    1575          90 :         const SvtCTLOptions& rCTLOptions = SW_MOD()->GetCTLOptions();
    1576          90 :         if ( bVisualAllowed && rCTLOptions.IsCTLFontEnabled() &&
    1577             :              SvtCTLOptions::MOVEMENT_VISUAL ==
    1578           0 :              rCTLOptions.GetCTLCursorMovement() )
    1579             :         {
    1580             :             // for visual cursor travelling (used in bidi layout)
    1581             :             // we first have to convert the logic to a visual position
    1582           0 :             Point aPt;
    1583           0 :             pSttFrm = rTNd.getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
    1584           0 :             if( pSttFrm )
    1585             :             {
    1586           0 :                 sal_uInt8 nCrsrLevel = GetCrsrBidiLevel();
    1587           0 :                 bool bForward = ! io_rbLeft;
    1588             :                 ((SwTxtFrm*)pSttFrm)->PrepareVisualMove( nPos, nCrsrLevel,
    1589           0 :                                                          bForward, bInsertCrsr );
    1590           0 :                 rIdx = nPos;
    1591           0 :                 SetCrsrBidiLevel( nCrsrLevel );
    1592           0 :                 io_rbLeft = ! bForward;
    1593             :             }
    1594             :         }
    1595             :         else
    1596             :         {
    1597          90 :             const SwScriptInfo* pSI = SwScriptInfo::GetScriptInfo( rTNd );
    1598          90 :             if ( pSI )
    1599             :             {
    1600             :                 const sal_Int32 nMoveOverPos = io_rbLeft ?
    1601          18 :                                                ( nPos ? nPos - 1 : 0 ) :
    1602          70 :                                                 nPos;
    1603          52 :                 SetCrsrBidiLevel( pSI->DirType( nMoveOverPos ) );
    1604             :             }
    1605             :         }
    1606             :     }
    1607          90 :     return pSttFrm;
    1608             : }
    1609             : 
    1610       74736 : bool SwCursor::LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode,
    1611             :                           bool bVisualAllowed,bool bSkipHidden, bool bInsertCrsr )
    1612             : {
    1613             :     // calculate cursor bidi level
    1614       74736 :     SwNode& rNode = GetPoint()->nNode.GetNode();
    1615             :     const SwCntntFrm* pSttFrm = // may side-effect bLeft!
    1616       74736 :         DoSetBidiLevelLeftRight(bLeft, bVisualAllowed, bInsertCrsr);
    1617             : 
    1618             :     // can the cursor be moved n times?
    1619       74736 :     SwCrsrSaveState aSave( *this );
    1620       74736 :     SwMoveFn fnMove = bLeft ? fnMoveBackward : fnMoveForward;
    1621             : 
    1622             :     SwGoInDoc fnGo;
    1623       74736 :     if ( bSkipHidden )
    1624          52 :         fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCellsSkipHidden : fnGoCntntSkipHidden;
    1625             :     else
    1626       74684 :         fnGo = CRSR_SKIP_CELLS == nMode ? fnGoCntntCells : fnGoCntnt;
    1627             : 
    1628      374028 :     while( nCnt )
    1629             :     {
    1630      227046 :         SwNodeIndex aOldNodeIdx( GetPoint()->nNode );
    1631             : 
    1632      227046 :         if ( !Move( fnMove, fnGo ) )
    1633        2490 :             break;
    1634             : 
    1635             :         // If we were located inside a covered cell but our position has been
    1636             :         // corrected, we check if the last move has moved the cursor to a
    1637             :         // different table cell. In this case we set the cursor to the stored
    1638             :         // covered position and redo the move:
    1639      224556 :         if ( mnRowSpanOffset )
    1640             :         {
    1641           0 :             const SwNode* pOldTabBoxSttNode = aOldNodeIdx.GetNode().FindTableBoxStartNode();
    1642           0 :             const SwTableNode* pOldTabSttNode = pOldTabBoxSttNode ? pOldTabBoxSttNode->FindTableNode() : 0;
    1643           0 :             const SwNode* pNewTabBoxSttNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
    1644           0 :             const SwTableNode* pNewTabSttNode = pNewTabBoxSttNode ? pNewTabBoxSttNode->FindTableNode() : 0;
    1645             : 
    1646           0 :             const bool bCellChanged = pOldTabSttNode && pNewTabSttNode &&
    1647           0 :                                       pOldTabSttNode == pNewTabSttNode &&
    1648           0 :                                       pOldTabBoxSttNode && pNewTabBoxSttNode &&
    1649           0 :                                       pOldTabBoxSttNode != pNewTabBoxSttNode;
    1650             : 
    1651           0 :             if ( bCellChanged )
    1652             :             {
    1653             :                 // Set cursor to start/end of covered cell:
    1654           0 :                 SwTableBox* pTableBox = pOldTabBoxSttNode->GetTblBox();
    1655           0 :                 if ( pTableBox && pTableBox->getRowSpan() > 1 )
    1656             :                 {
    1657           0 :                     pTableBox = & pTableBox->FindEndOfRowSpan( pOldTabSttNode->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset ) );
    1658           0 :                     SwNodeIndex& rPtIdx = GetPoint()->nNode;
    1659           0 :                     SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
    1660           0 :                     rPtIdx = aNewIdx;
    1661             : 
    1662           0 :                     GetDoc()->GetNodes().GoNextSection( &rPtIdx, false, false );
    1663           0 :                     SwCntntNode* pCntntNode = GetCntntNode();
    1664           0 :                     if ( pCntntNode )
    1665             :                     {
    1666           0 :                         GetPoint()->nContent.Assign( pCntntNode, bLeft ? pCntntNode->Len() : 0 );
    1667             : 
    1668             :                         // Redo the move:
    1669           0 :                         if ( !Move( fnMove, fnGo ) )
    1670           0 :                             break;
    1671           0 :                     }
    1672             :                 }
    1673           0 :                 mnRowSpanOffset = 0;
    1674             :             }
    1675             :         }
    1676             : 
    1677             :         // Check if I'm inside a covered cell. Correct cursor if necessary and
    1678             :         // store covered cell:
    1679      224556 :         const SwNode* pTableBoxStartNode = GetPoint()->nNode.GetNode().FindTableBoxStartNode();
    1680      224556 :         if ( pTableBoxStartNode )
    1681             :         {
    1682         314 :             const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
    1683         314 :             if ( pTableBox && pTableBox->getRowSpan() < 1 )
    1684             :             {
    1685             :                 // Store the row span offset:
    1686           0 :                 mnRowSpanOffset = pTableBox->getRowSpan();
    1687             : 
    1688             :                 // Move cursor to non-covered cell:
    1689           0 :                 const SwTableNode* pTblNd = pTableBoxStartNode->FindTableNode();
    1690           0 :                 pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
    1691           0 :                  SwNodeIndex& rPtIdx = GetPoint()->nNode;
    1692           0 :                 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
    1693           0 :                 rPtIdx = aNewIdx;
    1694             : 
    1695           0 :                 GetDoc()->GetNodes().GoNextSection( &rPtIdx, false, false );
    1696           0 :                 SwCntntNode* pCntntNode = GetCntntNode();
    1697           0 :                 if ( pCntntNode )
    1698             :                 {
    1699           0 :                     GetPoint()->nContent.Assign( pCntntNode, bLeft ? pCntntNode->Len() : 0 );
    1700           0 :                 }
    1701             :             }
    1702             :         }
    1703      224556 :         --nCnt;
    1704      224556 :     }
    1705             : 
    1706             :     // here come some special rules for visual cursor travelling
    1707       74736 :     if ( pSttFrm )
    1708             :     {
    1709           0 :         SwNode& rTmpNode = GetPoint()->nNode.GetNode();
    1710           0 :         if ( &rTmpNode != &rNode && rTmpNode.IsTxtNode() )
    1711             :         {
    1712           0 :             Point aPt;
    1713           0 :             const SwCntntFrm* pEndFrm = ((SwTxtNode&)rTmpNode).getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
    1714           0 :             if ( pEndFrm )
    1715             :             {
    1716           0 :                 if ( ! pEndFrm->IsRightToLeft() != ! pSttFrm->IsRightToLeft() )
    1717             :                 {
    1718           0 :                     if ( ! bLeft )
    1719           0 :                         pEndFrm->RightMargin( this );
    1720             :                     else
    1721           0 :                         pEndFrm->LeftMargin( this );
    1722             :                 }
    1723             :             }
    1724             :         }
    1725             :     }
    1726             : 
    1727      146982 :     return 0 == nCnt && !IsInProtectTable( true ) &&
    1728             :             !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
    1729      146982 :                        nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
    1730             : }
    1731             : 
    1732             : // calculate cursor bidi level: extracted from UpDown()
    1733           0 : void SwCursor::DoSetBidiLevelUpDown()
    1734             : {
    1735           0 :     SwNode& rNode = GetPoint()->nNode.GetNode();
    1736           0 :     if ( rNode.IsTxtNode() )
    1737             :     {
    1738             :         const SwScriptInfo* pSI =
    1739           0 :             SwScriptInfo::GetScriptInfo( (SwTxtNode&)rNode );
    1740           0 :         if ( pSI )
    1741             :         {
    1742           0 :             SwIndex& rIdx = GetPoint()->nContent;
    1743           0 :             const sal_Int32 nPos = rIdx.GetIndex();
    1744             : 
    1745           0 :             if (nPos && nPos <
    1746           0 :                     static_cast<SwTxtNode&>(rNode).GetTxt().getLength())
    1747             :             {
    1748           0 :                 const sal_uInt8 nCurrLevel = pSI->DirType( nPos );
    1749           0 :                 const sal_uInt8 nPrevLevel = pSI->DirType( nPos - 1 );
    1750             : 
    1751           0 :                 if ( nCurrLevel % 2 != nPrevLevel % 2 )
    1752             :                 {
    1753             :                     // set cursor level to the lower of the two levels
    1754           0 :                     SetCrsrBidiLevel( std::min( nCurrLevel, nPrevLevel ) );
    1755             :                 }
    1756             :                 else
    1757           0 :                     SetCrsrBidiLevel( nCurrLevel );
    1758             :             }
    1759             :         }
    1760             :     }
    1761           0 : }
    1762             : 
    1763           6 : bool SwCursor::UpDown( bool bUp, sal_uInt16 nCnt,
    1764             :                             Point* pPt, long nUpDownX )
    1765             : {
    1766           6 :     SwTableCursor* pTblCrsr = dynamic_cast<SwTableCursor*>(this);
    1767           6 :     bool bAdjustTableCrsr = false;
    1768             : 
    1769             :     // If the point/mark of the table cursor in the same box then set cursor to
    1770             :     // beginning of the box
    1771          12 :     if( pTblCrsr && GetNode( true ).StartOfSectionNode() ==
    1772           6 :                     GetNode( false ).StartOfSectionNode() )
    1773             :     {
    1774           6 :         if ( End() != GetPoint() )
    1775           0 :             Exchange();
    1776           6 :         bAdjustTableCrsr = true;
    1777             :     }
    1778             : 
    1779           6 :     bool bRet = false;
    1780           6 :     Point aPt;
    1781           6 :     if( pPt )
    1782           0 :         aPt = *pPt;
    1783           6 :     SwCntntFrm* pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
    1784             : 
    1785           6 :     if( pFrm )
    1786             :     {
    1787           6 :         SwCrsrSaveState aSave( *this );
    1788             : 
    1789           6 :         if( !pPt )
    1790             :         {
    1791           6 :             SwRect aTmpRect;
    1792           6 :             pFrm->GetCharRect( aTmpRect, *GetPoint() );
    1793           6 :             aPt = aTmpRect.Pos();
    1794             : 
    1795           6 :             nUpDownX = pFrm->IsVertical() ?
    1796           0 :                 aPt.getY() - pFrm->Frm().Top() :
    1797           6 :                 aPt.getX() - pFrm->Frm().Left();
    1798             :         }
    1799             : 
    1800             :         // It is allowed to move footnotes in other footnotes but not sections
    1801           6 :         const bool bChkRange = pFrm->IsInFtn() && !HasMark();
    1802          12 :         const SwPosition aOldPos( *GetPoint() );
    1803           6 :         const bool bInReadOnly = IsReadOnlyAvailable();
    1804             : 
    1805           6 :         if ( bAdjustTableCrsr && !bUp )
    1806             :         {
    1807             :             // Special case: We have a table cursor but the start box has more
    1808             :             // than one paragraph. If we want to go down, we have to set the
    1809             :             // point to the last frame in the table box. This is only necessary
    1810             :             // if we do not already have a table selection
    1811           2 :             const SwStartNode* pTblNd = GetNode( true ).FindTableBoxStartNode();
    1812             :             OSL_ENSURE( pTblNd, "pTblCrsr without SwTableNode?" );
    1813             : 
    1814           2 :             if ( pTblNd ) // safety first
    1815             :             {
    1816           2 :                 const SwNode* pEndNd = pTblNd->EndOfSectionNode();
    1817           2 :                 GetPoint()->nNode = *pEndNd;
    1818           2 :                 pTblCrsr->Move( fnMoveBackward, fnGoNode );
    1819           2 :                    pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
    1820             :             }
    1821             :         }
    1822             : 
    1823          24 :         while( nCnt &&
    1824           4 :                (bUp ? pFrm->UnitUp( this, nUpDownX, bInReadOnly )
    1825          20 :                     : pFrm->UnitDown( this, nUpDownX, bInReadOnly ) ) &&
    1826           6 :                 CheckNodesRange( aOldPos.nNode, GetPoint()->nNode, bChkRange ))
    1827             :         {
    1828           6 :                pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
    1829           6 :             --nCnt;
    1830             :         }
    1831             : 
    1832             :         // iterate over whole number of items?
    1833          12 :         if( !nCnt && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
    1834           6 :                                 nsSwCursorSelOverFlags::SELOVER_CHANGEPOS ) )
    1835             :         {
    1836           6 :             if( !pTblCrsr )
    1837             :             {
    1838             :                 // try to position the cursor at half of the char-rect's height
    1839           0 :                 pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
    1840           0 :                 SwCrsrMoveState eTmpState( MV_UPDOWN );
    1841           0 :                 eTmpState.bSetInReadOnly = bInReadOnly;
    1842           0 :                 SwRect aTmpRect;
    1843           0 :                 pFrm->GetCharRect( aTmpRect, *GetPoint(), &eTmpState );
    1844           0 :                 if ( pFrm->IsVertical() )
    1845             :                 {
    1846           0 :                     aPt.setX(aTmpRect.Center().getX());
    1847           0 :                     pFrm->Calc();
    1848           0 :                     aPt.setY(pFrm->Frm().Top() + nUpDownX);
    1849             :                 }
    1850             :                 else
    1851             :                 {
    1852           0 :                     aPt.setY(aTmpRect.Center().getY());
    1853           0 :                     pFrm->Calc();
    1854           0 :                     aPt.setX(pFrm->Frm().Left() + nUpDownX);
    1855             :                 }
    1856           0 :                 pFrm->GetCrsrOfst( GetPoint(), aPt, &eTmpState );
    1857             :             }
    1858           6 :             bRet = !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
    1859             :         }
    1860             :         else
    1861           0 :             *GetPoint() = aOldPos;
    1862             : 
    1863          12 :         DoSetBidiLevelUpDown(); // calculate cursor bidi level
    1864             :     }
    1865           6 :     return bRet;
    1866             : }
    1867             : 
    1868           0 : bool SwCursor::LeftRightMargin( bool bLeft, bool bAPI )
    1869             : {
    1870           0 :     Point aPt;
    1871           0 :     SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
    1872             : 
    1873             :     // calculate cursor bidi level
    1874           0 :     if ( pFrm )
    1875           0 :         SetCrsrBidiLevel( pFrm->IsRightToLeft() ? 1 : 0 );
    1876             : 
    1877           0 :     SwCrsrSaveState aSave( *this );
    1878             :     return pFrm
    1879           0 :            && (bLeft ? pFrm->LeftMargin( this ) : pFrm->RightMargin( this, bAPI ) )
    1880           0 :            && !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE | nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
    1881             : }
    1882             : 
    1883           0 : bool SwCursor::IsAtLeftRightMargin( bool bLeft, bool bAPI ) const
    1884             : {
    1885           0 :     bool bRet = false;
    1886           0 :     Point aPt;
    1887           0 :     SwCntntFrm * pFrm = GetCntntNode()->getLayoutFrm( GetDoc()->getIDocumentLayoutAccess().GetCurrentLayout(), &aPt, GetPoint() );
    1888           0 :     if( pFrm )
    1889             :     {
    1890           0 :         SwPaM aPam( *GetPoint() );
    1891           0 :         if( !bLeft && aPam.GetPoint()->nContent.GetIndex() )
    1892           0 :             aPam.GetPoint()->nContent--;
    1893           0 :         bRet = (bLeft ? pFrm->LeftMargin( &aPam )
    1894           0 :                       : pFrm->RightMargin( &aPam, bAPI ))
    1895           0 :                 && *aPam.GetPoint() == *GetPoint();
    1896             :     }
    1897           0 :     return bRet;
    1898             : }
    1899             : 
    1900         124 : bool SwCursor::SttEndDoc( bool bStt )
    1901             : {
    1902         124 :     SwCrsrSaveState aSave( *this );
    1903             :     // Never jump over section boundaries during selection!
    1904             :     // Can the cursor still moved on?
    1905         124 :     SwMoveFn fnMove = bStt ? fnMoveBackward : fnMoveForward;
    1906         266 :     bool bRet = (!HasMark() || !IsNoCntnt() ) &&
    1907         248 :                     Move( fnMove, fnGoDoc ) &&
    1908         372 :                     !IsInProtectTable( true ) &&
    1909             :                     !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
    1910             :                                nsSwCursorSelOverFlags::SELOVER_CHANGEPOS |
    1911         248 :                                nsSwCursorSelOverFlags::SELOVER_ENABLEREVDIREKTION );
    1912         124 :     return bRet;
    1913             : }
    1914             : 
    1915           8 : bool SwCursor::GoPrevNextCell( bool bNext, sal_uInt16 nCnt )
    1916             : {
    1917           8 :     const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
    1918           8 :     if( !pTblNd )
    1919           0 :         return false;
    1920             : 
    1921             :     // If there is another EndNode in front of the cell's StartNode then there
    1922             :     // exists a previous cell
    1923           8 :     SwCrsrSaveState aSave( *this );
    1924           8 :     SwNodeIndex& rPtIdx = GetPoint()->nNode;
    1925             : 
    1926          24 :     while( nCnt-- )
    1927             :     {
    1928           8 :         const SwNode* pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
    1929           8 :         const SwTableBox* pTableBox = pTableBoxStartNode->GetTblBox();
    1930             : 
    1931             :         // Check if we have to move the cursor to a covered cell before
    1932             :         // proceeding:
    1933           8 :         if ( mnRowSpanOffset )
    1934             :         {
    1935           0 :             if ( pTableBox && pTableBox->getRowSpan() > 1 )
    1936             :             {
    1937           0 :                 pTableBox = & pTableBox->FindEndOfRowSpan( pTblNd->GetTable(), (sal_uInt16)(pTableBox->getRowSpan() + mnRowSpanOffset) );
    1938           0 :                 SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
    1939           0 :                 rPtIdx = aNewIdx;
    1940           0 :                 pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
    1941             :             }
    1942           0 :             mnRowSpanOffset = 0;
    1943             :         }
    1944             : 
    1945             :         const SwNode* pTmpNode = bNext ?
    1946             :                                  pTableBoxStartNode->EndOfSectionNode() :
    1947           8 :                                  pTableBoxStartNode;
    1948             : 
    1949           8 :         SwNodeIndex aCellIdx( *pTmpNode, bNext ? 1 : -1 );
    1950          16 :         if(  (bNext && !aCellIdx.GetNode().IsStartNode()) ||
    1951          12 :             (!bNext && !aCellIdx.GetNode().IsEndNode()) )
    1952           0 :             return false;
    1953             : 
    1954           8 :         rPtIdx = bNext ? aCellIdx : SwNodeIndex(*aCellIdx.GetNode().StartOfSectionNode());
    1955             : 
    1956           8 :         pTableBoxStartNode = rPtIdx.GetNode().FindTableBoxStartNode();
    1957           8 :         pTableBox = pTableBoxStartNode->GetTblBox();
    1958           8 :         if ( pTableBox && pTableBox->getRowSpan() < 1 )
    1959             :         {
    1960           0 :             mnRowSpanOffset = pTableBox->getRowSpan();
    1961             :             // move cursor to non-covered cell:
    1962           0 :             pTableBox = & pTableBox->FindStartOfRowSpan( pTblNd->GetTable(), USHRT_MAX );
    1963           0 :             SwNodeIndex aNewIdx( *pTableBox->GetSttNd() );
    1964           0 :             rPtIdx = aNewIdx;
    1965             :         }
    1966           8 :     }
    1967             : 
    1968           8 :     ++rPtIdx;
    1969           8 :     if( !rPtIdx.GetNode().IsCntntNode() )
    1970           0 :         GetDoc()->GetNodes().GoNextSection( &rPtIdx, true, false );
    1971           8 :     GetPoint()->nContent.Assign( GetCntntNode(), 0 );
    1972             : 
    1973           8 :     return !IsInProtectTable( true );
    1974             : }
    1975             : 
    1976           0 : bool SwTableCursor::GotoTable( const OUString& )
    1977             : {
    1978           0 :     return false; // invalid action
    1979             : }
    1980             : 
    1981          18 : bool SwCursor::GotoTable( const OUString& rName )
    1982             : {
    1983          18 :     bool bRet = false;
    1984          18 :     if ( !HasMark() )
    1985             :     {
    1986          18 :         SwTable* pTmpTbl = SwTable::FindTable( GetDoc()->FindTblFmtByName( rName ) );
    1987          18 :         if( pTmpTbl )
    1988             :         {
    1989             :             // a table in a normal nodes array
    1990          18 :             SwCrsrSaveState aSave( *this );
    1991          36 :             GetPoint()->nNode = *pTmpTbl->GetTabSortBoxes()[ 0 ]->
    1992          36 :                                 GetSttNd()->FindTableNode();
    1993          18 :             Move( fnMoveForward, fnGoCntnt );
    1994          18 :             bRet = !IsSelOvr();
    1995             :         }
    1996             :     }
    1997          18 :     return bRet;
    1998             : }
    1999             : 
    2000           6 : bool SwCursor::GotoTblBox( const OUString& rName )
    2001             : {
    2002           6 :     bool bRet = false;
    2003           6 :     const SwTableNode* pTblNd = GetPoint()->nNode.GetNode().FindTableNode();
    2004           6 :     if( pTblNd )
    2005             :     {
    2006             :         // retrieve box by name
    2007           6 :         const SwTableBox* pTblBox = pTblNd->GetTable().GetTblBox( rName );
    2008          18 :         if( pTblBox && pTblBox->GetSttNd() &&
    2009           6 :             ( !pTblBox->GetFrmFmt()->GetProtect().IsCntntProtected() ||
    2010           0 :               IsReadOnlyAvailable() ) )
    2011             :         {
    2012           6 :             SwCrsrSaveState aSave( *this );
    2013           6 :             GetPoint()->nNode = *pTblBox->GetSttNd();
    2014           6 :             Move( fnMoveForward, fnGoCntnt );
    2015           6 :             bRet = !IsSelOvr();
    2016             :         }
    2017             :     }
    2018           6 :     return bRet;
    2019             : }
    2020             : 
    2021       68498 : bool SwCursor::MovePara(SwWhichPara fnWhichPara, SwPosPara fnPosPara )
    2022             : {
    2023             :     // for optimization test something before
    2024       68498 :     const SwNode* pNd = &GetPoint()->nNode.GetNode();
    2025       68498 :     bool bShortCut = false;
    2026       68498 :     if ( fnWhichPara == fnParaCurr )
    2027             :     {
    2028             :         // #i41048#
    2029             :         // If fnWhichPara == fnParaCurr then (*fnWhichPara)( *this, fnPosPara )
    2030             :         // can already move the cursor to a different text node. In this case
    2031             :         // we better check if IsSelOvr().
    2032       44992 :         const SwCntntNode* pCntntNd = pNd->GetCntntNode();
    2033       44992 :         if ( pCntntNd )
    2034             :         {
    2035       44992 :             const sal_Int32 nSttEnd = fnPosPara == fnMoveForward ? 0 : pCntntNd->Len();
    2036       44992 :             if ( GetPoint()->nContent.GetIndex() != nSttEnd )
    2037       44936 :                 bShortCut = true;
    2038             :         }
    2039             :     }
    2040             :     else
    2041             :     {
    2042       47012 :         if ( pNd->IsTxtNode() &&
    2043       47012 :              pNd->GetNodes()[ pNd->GetIndex() +
    2044       47012 :                     (fnWhichPara == fnParaNext ? 1 : -1 ) ]->IsTxtNode() )
    2045        7218 :             bShortCut = true;
    2046             :     }
    2047             : 
    2048       68498 :     if ( bShortCut )
    2049       52154 :         return (*fnWhichPara)( *this, fnPosPara );
    2050             : 
    2051             :     // else we must use the SaveStructure, because the next/prev is not
    2052             :     // a same node type.
    2053       16344 :     SwCrsrSaveState aSave( *this );
    2054       25192 :     return (*fnWhichPara)( *this, fnPosPara ) &&
    2055       25192 :             !IsInProtectTable( true ) &&
    2056             :             !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
    2057       25192 :                        nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
    2058             : }
    2059             : 
    2060       81842 : bool SwCursor::MoveSection( SwWhichSection fnWhichSect,
    2061             :                                 SwPosSection fnPosSect)
    2062             : {
    2063       81842 :     SwCrsrSaveState aSave( *this );
    2064      120068 :     return (*fnWhichSect)( *this, fnPosSect ) &&
    2065      120068 :             !IsInProtectTable( true ) &&
    2066             :             !IsSelOvr( nsSwCursorSelOverFlags::SELOVER_TOGGLE |
    2067      120068 :                        nsSwCursorSelOverFlags::SELOVER_CHANGEPOS );
    2068             : }
    2069             : 
    2070          42 : void SwCursor::RestoreSavePos()
    2071             : {
    2072             :     // This method is not supposed to be used in cases when nodes may be
    2073             :     // deleted; detect such cases, but do not crash (example: fdo#40831).
    2074          42 :     sal_uLong uNodeCount = GetPoint()->nNode.GetNodes().Count();
    2075             :     OSL_ENSURE(!pSavePos || pSavePos->nNode < uNodeCount,
    2076             :         "SwCursor::RestoreSavePos: invalid node: "
    2077             :         "probably something was deleted; consider using SwUnoCrsr instead");
    2078          42 :     if( pSavePos && pSavePos->nNode < uNodeCount )
    2079             :     {
    2080          42 :         GetPoint()->nNode = pSavePos->nNode;
    2081             : 
    2082          42 :         sal_Int32 nIdx = 0;
    2083          42 :         if ( GetCntntNode() )
    2084             :         {
    2085          42 :             if ( pSavePos->nCntnt <= GetCntntNode()->Len() )
    2086          42 :                 nIdx = pSavePos->nCntnt;
    2087             :             else
    2088             :             {
    2089           0 :                 nIdx = GetCntntNode()->Len();
    2090             :                 OSL_FAIL("SwCursor::RestoreSavePos: invalid content index");
    2091             :             }
    2092             :         }
    2093          42 :         GetPoint()->nContent.Assign( GetCntntNode(), nIdx );
    2094             :     }
    2095          42 : }
    2096             : 
    2097          80 : SwTableCursor::SwTableCursor( const SwPosition &rPos, SwPaM* pRing )
    2098          80 :     : SwCursor( rPos, pRing, false )
    2099             : {
    2100          80 :     bParked = false;
    2101          80 :     bChg = false;
    2102          80 :     nTblPtNd = 0, nTblMkNd = 0;
    2103          80 :     nTblPtCnt = 0, nTblMkCnt = 0;
    2104          80 : }
    2105             : 
    2106          80 : SwTableCursor::~SwTableCursor() {}
    2107             : 
    2108             : static bool
    2109          34 : lcl_SeekEntry(const SwSelBoxes& rTmp, SwStartNode const*const pSrch,
    2110             :         size_t & o_rFndPos)
    2111             : {
    2112          34 :     sal_uLong nIdx = pSrch->GetIndex();
    2113             : 
    2114          34 :     size_t nO = rTmp.size();
    2115          34 :     if( nO > 0 )
    2116             :     {
    2117          22 :         nO--;
    2118          22 :         size_t nU = 0;
    2119          52 :         while( nU <= nO )
    2120             :         {
    2121          28 :             size_t nM = nU + ( nO - nU ) / 2;
    2122          28 :             if( rTmp[ nM ]->GetSttNd() == pSrch )
    2123             :             {
    2124          10 :                 o_rFndPos = nM;
    2125          10 :                 return true;
    2126             :             }
    2127          18 :             else if( rTmp[ nM ]->GetSttIdx() < nIdx )
    2128           8 :                 nU = nM + 1;
    2129          10 :             else if( nM == 0 )
    2130          10 :                 return false;
    2131             :             else
    2132           0 :                 nO = nM - 1;
    2133             :         }
    2134             :     }
    2135          14 :     return false;
    2136             : }
    2137             : 
    2138          94 : SwCursor* SwTableCursor::MakeBoxSels( SwCursor* pAktCrsr )
    2139             : {
    2140          94 :     if( bChg )
    2141             :     {
    2142          94 :         if( bParked )
    2143             :         {
    2144             :             // move back into content
    2145           0 :             Exchange();
    2146           0 :             Move( fnMoveForward );
    2147           0 :             Exchange();
    2148           0 :             Move( fnMoveForward );
    2149           0 :             bParked = false;
    2150             :         }
    2151             : 
    2152          94 :         bChg = false;
    2153             : 
    2154             :         // create temporary copies so that all boxes that
    2155             :         // have already cursors can be removed
    2156          94 :         SwSelBoxes aTmp(m_SelectedBoxes);
    2157             : 
    2158             :         // compare old and new ones
    2159          94 :         SwNodes& rNds = pAktCrsr->GetDoc()->GetNodes();
    2160             :         const SwStartNode* pSttNd;
    2161          94 :         SwPaM* pCur = pAktCrsr;
    2162         116 :         do {
    2163             :             size_t nPos;
    2164         116 :             bool bDel = false;
    2165         116 :             pSttNd = pCur->GetPoint()->nNode.GetNode().FindTableBoxStartNode();
    2166         150 :             if( !pCur->HasMark() || !pSttNd ||
    2167          34 :                 pSttNd != pCur->GetMark()->nNode.GetNode().FindTableBoxStartNode() )
    2168          82 :                 bDel = true;
    2169             : 
    2170          34 :             else if( lcl_SeekEntry( aTmp, pSttNd, nPos ))
    2171             :             {
    2172          10 :                 SwNodeIndex aIdx( *pSttNd, 1 );
    2173          10 :                 const SwNode* pNd = &aIdx.GetNode();
    2174          10 :                 if( !pNd->IsCntntNode() )
    2175           0 :                     pNd = rNds.GoNextSection( &aIdx, true, false );
    2176             : 
    2177          10 :                 SwPosition* pPos = pCur->GetMark();
    2178          10 :                 if( pNd != &pPos->nNode.GetNode() )
    2179           0 :                     pPos->nNode = *pNd;
    2180          10 :                 pPos->nContent.Assign( (SwCntntNode*)pNd, 0 );
    2181             : 
    2182          10 :                 aIdx.Assign( *pSttNd->EndOfSectionNode(), - 1 );
    2183          10 :                 if( !( pNd = &aIdx.GetNode())->IsCntntNode() )
    2184           0 :                     pNd = rNds.GoPrevSection( &aIdx, true, false );
    2185             : 
    2186          10 :                 pPos = pCur->GetPoint();
    2187          10 :                 if (pNd && pNd != &pPos->nNode.GetNode())
    2188           0 :                     pPos->nNode = *pNd;
    2189          10 :                 pPos->nContent.Assign((SwCntntNode*)pNd, pNd ? ((SwCntntNode*)pNd)->Len() : 0);
    2190             : 
    2191          10 :                 aTmp.erase( aTmp.begin() + nPos );
    2192             :             }
    2193             :             else
    2194          24 :                 bDel = true;
    2195             : 
    2196         116 :             pCur = (SwPaM*)pCur->GetNext();
    2197         116 :             if( bDel )
    2198             :             {
    2199         106 :                 SwPaM* pDel = (SwPaM*)pCur->GetPrev();
    2200             : 
    2201         106 :                 if( pDel == pAktCrsr )
    2202          86 :                     pAktCrsr->DeleteMark();
    2203             :                 else
    2204          20 :                     delete pDel;
    2205             :             }
    2206             :         } while ( pAktCrsr != pCur );
    2207             : 
    2208         624 :         for (size_t nPos = 0; nPos < aTmp.size(); ++nPos)
    2209             :         {
    2210         530 :             pSttNd = aTmp[ nPos ]->GetSttNd();
    2211             : 
    2212         530 :             SwNodeIndex aIdx( *pSttNd, 1 );
    2213         530 :             if( &aIdx.GetNodes() != &rNds )
    2214           0 :                 break;
    2215         530 :             const SwNode* pNd = &aIdx.GetNode();
    2216         530 :             if( !pNd->IsCntntNode() )
    2217           0 :                 pNd = rNds.GoNextSection( &aIdx, true, false );
    2218             : 
    2219         672 :             SwPaM *const pNew = (pAktCrsr->GetNext() == pAktCrsr && !pAktCrsr->HasMark())
    2220             :                 ? pAktCrsr
    2221         976 :                 : pAktCrsr->Create( pAktCrsr );
    2222         530 :             pNew->GetPoint()->nNode = *pNd;
    2223         530 :             pNew->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
    2224         530 :             pNew->SetMark();
    2225             : 
    2226         530 :             SwPosition* pPos = pNew->GetPoint();
    2227         530 :             pPos->nNode.Assign( *pSttNd->EndOfSectionNode(), - 1 );
    2228         530 :             if( !( pNd = &pPos->nNode.GetNode())->IsCntntNode() )
    2229           0 :                 pNd = rNds.GoPrevSection( &pPos->nNode, true, false );
    2230             : 
    2231         530 :             pPos->nContent.Assign((SwCntntNode*)pNd, pNd ? ((SwCntntNode*)pNd)->Len() : 0);
    2232         624 :         }
    2233             :     }
    2234          94 :     return pAktCrsr;
    2235             : }
    2236             : 
    2237         532 : void SwTableCursor::InsertBox( const SwTableBox& rTblBox )
    2238             : {
    2239         532 :     SwTableBox* pBox = (SwTableBox*)&rTblBox;
    2240         532 :     m_SelectedBoxes.insert(pBox);
    2241         532 :     bChg = true;
    2242         532 : }
    2243             : 
    2244          32 : void SwTableCursor::DeleteBox(size_t const nPos)
    2245             : {
    2246          32 :     m_SelectedBoxes.erase(m_SelectedBoxes.begin() + nPos);
    2247          32 :     bChg = true;
    2248          32 : }
    2249             : 
    2250         826 : bool SwTableCursor::NewTableSelection()
    2251             : {
    2252         826 :     bool bRet = false;
    2253         826 :     const SwNode *pStart = GetCntntNode()->FindTableBoxStartNode();
    2254         826 :     const SwNode *pEnd = GetCntntNode(false)->FindTableBoxStartNode();
    2255         826 :     if( pStart && pEnd )
    2256             :     {
    2257         826 :         const SwTableNode *pTableNode = pStart->FindTableNode();
    2258        1652 :         if( pTableNode == pEnd->FindTableNode() &&
    2259         826 :             pTableNode->GetTable().IsNewModel() )
    2260             :         {
    2261         826 :             bRet = true;
    2262         826 :             SwSelBoxes aNew(m_SelectedBoxes);
    2263         826 :             pTableNode->GetTable().CreateSelection( pStart, pEnd, aNew,
    2264         826 :                 SwTable::SEARCH_NONE, false );
    2265         826 :             ActualizeSelection( aNew );
    2266             :         }
    2267             :     }
    2268         826 :     return bRet;
    2269             : }
    2270             : 
    2271         826 : void SwTableCursor::ActualizeSelection( const SwSelBoxes &rNew )
    2272             : {
    2273         826 :     size_t nOld = 0, nNew = 0;
    2274        5188 :     while (nOld < m_SelectedBoxes.size() && nNew < rNew.size())
    2275             :     {
    2276        3536 :         SwTableBox const*const pPOld = m_SelectedBoxes[ nOld ];
    2277        3536 :         const SwTableBox* pPNew = rNew[ nNew ];
    2278        3536 :         if( pPOld == pPNew )
    2279             :         {   // this box will stay
    2280        3516 :             ++nOld;
    2281        3516 :             ++nNew;
    2282             :         }
    2283          20 :         else if( pPOld->GetSttIdx() < pPNew->GetSttIdx() )
    2284             :         {
    2285          10 :             DeleteBox( nOld ); // this box has to go
    2286             :         }
    2287             :         else
    2288             :         {
    2289          10 :             InsertBox( *pPNew ); // this is a new one
    2290          10 :             ++nOld;
    2291          10 :             ++nNew;
    2292             :         }
    2293             :     }
    2294             : 
    2295        1666 :     while (nOld < m_SelectedBoxes.size())
    2296             :     {
    2297          14 :         DeleteBox( nOld ); // some more to delete
    2298             :     }
    2299             : 
    2300        1348 :     for ( ; nNew < rNew.size(); ++nNew ) // some more to insert
    2301             :     {
    2302         522 :         InsertBox( *rNew[ nNew ] );
    2303             :     }
    2304         826 : }
    2305             : 
    2306         374 : bool SwTableCursor::IsCrsrMovedUpdt()
    2307             : {
    2308         374 :     if( !IsCrsrMoved() )
    2309         358 :         return false;
    2310             : 
    2311          16 :     nTblMkNd = GetMark()->nNode.GetIndex();
    2312          16 :     nTblPtNd = GetPoint()->nNode.GetIndex();
    2313          16 :     nTblMkCnt = GetMark()->nContent.GetIndex();
    2314          16 :     nTblPtCnt = GetPoint()->nContent.GetIndex();
    2315          16 :     return true;
    2316             : }
    2317             : 
    2318             : /// park table cursor on the boxes' start node
    2319           0 : void SwTableCursor::ParkCrsr()
    2320             : {
    2321             :     // de-register index from text node
    2322           0 :     SwNode* pNd = &GetPoint()->nNode.GetNode();
    2323           0 :     if( !pNd->IsStartNode() )
    2324           0 :         pNd = pNd->StartOfSectionNode();
    2325           0 :     GetPoint()->nNode = *pNd;
    2326           0 :     GetPoint()->nContent.Assign( 0, 0 );
    2327             : 
    2328           0 :     pNd = &GetMark()->nNode.GetNode();
    2329           0 :     if( !pNd->IsStartNode() )
    2330           0 :         pNd = pNd->StartOfSectionNode();
    2331           0 :     GetMark()->nNode = *pNd;
    2332           0 :     GetMark()->nContent.Assign( 0, 0 );
    2333             : 
    2334           0 :     bChg = true;
    2335           0 :     bParked = true;
    2336           0 : }
    2337             : 
    2338          36 : bool SwTableCursor::HasReadOnlyBoxSel() const
    2339             : {
    2340          36 :     bool bRet = false;
    2341         176 :     for (size_t n = m_SelectedBoxes.size(); n; )
    2342             :     {
    2343         104 :         if (m_SelectedBoxes[--n]->GetFrmFmt()->GetProtect().IsCntntProtected())
    2344             :         {
    2345           0 :             bRet = true;
    2346           0 :             break;
    2347             :         }
    2348             :     }
    2349          36 :     return bRet;
    2350         270 : }
    2351             : 
    2352             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10