LCOV - code coverage report
Current view: top level - sw/source/core/layout - trvlfrm.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 671 1333 50.3 %
Date: 2014-04-11 Functions: 34 50 68.0 %
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 <hints.hxx>
      22             : #include <comphelper/flagguard.hxx>
      23             : #include <tools/bigint.hxx>
      24             : #include <tools/line.hxx>
      25             : #include <editeng/opaqitem.hxx>
      26             : #include <editeng/protitem.hxx>
      27             : #include <vcl/settings.hxx>
      28             : #include <vcl/outdev.hxx>
      29             : #include <fmtpdsc.hxx>
      30             : #include <fmtsrnd.hxx>
      31             : #include <pagedesc.hxx>
      32             : #include <pagefrm.hxx>
      33             : #include <rootfrm.hxx>
      34             : #include <cntfrm.hxx>
      35             : #include <ftnfrm.hxx>
      36             : #include <flyfrm.hxx>
      37             : #include <tabfrm.hxx>
      38             : #include <rowfrm.hxx>
      39             : #include <cellfrm.hxx>
      40             : #include <txtfrm.hxx>
      41             : #include <viewsh.hxx>
      42             : #include <viewopt.hxx>
      43             : #include <doc.hxx>
      44             : #include <viscrs.hxx>
      45             : #include <frmfmt.hxx>
      46             : #include <swtable.hxx>
      47             : #include <dflyobj.hxx>
      48             : #include <crstate.hxx>
      49             : #include <frmtool.hxx>
      50             : #include <ndtxt.hxx>
      51             : #include <dcontact.hxx>
      52             : #include <sortedobjs.hxx>
      53             : #include <txatbase.hxx>
      54             : #include <fmtfld.hxx>
      55             : #include <fldbas.hxx>
      56             : 
      57             : #include <cfloat>
      58             : #include <swselectionlist.hxx>
      59             : 
      60             : #include <basegfx/numeric/ftools.hxx>
      61             : 
      62             : namespace {
      63           4 :     bool lcl_GetCrsrOfst_Objects( const SwPageFrm* pPageFrm, bool bSearchBackground,
      64             :            SwPosition *pPos, Point& rPoint, SwCrsrMoveState* pCMS  )
      65             :     {
      66           4 :         bool bRet = false;
      67           4 :         Point aPoint( rPoint );
      68           4 :         SwOrderIter aIter( pPageFrm );
      69           4 :         aIter.Top();
      70          18 :         while ( aIter() )
      71             :         {
      72             :             const SwVirtFlyDrawObj* pObj =
      73          10 :                                 static_cast<const SwVirtFlyDrawObj*>(aIter());
      74          10 :             const SwAnchoredObject* pAnchoredObj = GetUserCall( aIter() )->GetAnchoredObj( aIter() );
      75          10 :             const SwFmtSurround& rSurround = pAnchoredObj->GetFrmFmt().GetSurround();
      76          10 :             const SvxOpaqueItem& rOpaque = pAnchoredObj->GetFrmFmt().GetOpaque();
      77          10 :             bool bInBackground = ( rSurround.GetSurround() == SURROUND_THROUGHT ) && !rOpaque.GetValue();
      78             : 
      79          24 :             bool bBackgroundMatches = ( bInBackground && bSearchBackground ) ||
      80          27 :                                       ( !bInBackground && !bSearchBackground );
      81             : 
      82          10 :             const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
      83          20 :             if ( pFly && bBackgroundMatches &&
      84           5 :                  ( ( pCMS ? pCMS->bSetInReadOnly : false ) ||
      85          20 :                    !pFly->IsProtected() ) &&
      86           5 :                  pFly->GetCrsrOfst( pPos, aPoint, pCMS ) )
      87             :             {
      88           0 :                 bRet = true;
      89           0 :                 break;
      90             :             }
      91             : 
      92          10 :             if ( pCMS && pCMS->bStop )
      93           0 :                 return false;
      94          10 :             aIter.Prev();
      95             :         }
      96           4 :         return bRet;
      97             :     }
      98             : 
      99           0 :     double lcl_getDistance( const SwRect& rRect, const Point& rPoint )
     100             :     {
     101           0 :         double nDist = 0.0;
     102             : 
     103             :         // If the point is inside the rectangle, then distance is 0
     104             :         // Otherwise, compute the distance to the center of the rectangle.
     105           0 :         if ( !rRect.IsInside( rPoint ) )
     106             :         {
     107           0 :             Line aLine( rPoint, rRect.Center( ) );
     108           0 :             nDist = aLine.GetLength( );
     109             :         }
     110             : 
     111           0 :         return nDist;
     112             :     }
     113             : }
     114             : 
     115             : //For SwFlyFrm::GetCrsrOfst
     116             : class SwCrsrOszControl
     117             : {
     118             : public:
     119             :     // So the compiler can initialize the class already. No DTOR and member
     120             :     // as public members
     121             :     const SwFlyFrm *pEntry;
     122             :     const SwFlyFrm *pStk1;
     123             :     const SwFlyFrm *pStk2;
     124             : 
     125           0 :     bool ChkOsz( const SwFlyFrm *pFly )
     126             :         {
     127           0 :             bool bRet = true;
     128           0 :             if ( pFly != pStk1 && pFly != pStk2 )
     129             :             {
     130           0 :                 pStk1 = pStk2;
     131           0 :                 pStk2 = pFly;
     132           0 :                 bRet  = false;
     133             :             }
     134           0 :             return bRet;
     135             :         }
     136             : 
     137           5 :     void Entry( const SwFlyFrm *pFly )
     138             :         {
     139           5 :             if ( !pEntry )
     140           5 :                 pEntry = pStk1 = pFly;
     141           5 :         }
     142             : 
     143           5 :     void Exit( const SwFlyFrm *pFly )
     144             :         {
     145           5 :             if ( pFly == pEntry )
     146           5 :                 pEntry = pStk1 = pStk2 = 0;
     147           5 :         }
     148             : };
     149             : 
     150             : static SwCrsrOszControl aOszCtrl = { 0, 0, 0 };
     151             : 
     152             : /** Searches the CntntFrm owning the PrtArea containing the point. */
     153         513 : bool SwLayoutFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
     154             :                                SwCrsrMoveState* pCMS, bool ) const
     155             : {
     156         513 :     bool bRet = false;
     157         513 :     const SwFrm *pFrm = Lower();
     158        1539 :     while ( !bRet && pFrm )
     159             :     {
     160         513 :         pFrm->Calc();
     161             : 
     162             :         // #i43742# New function
     163         513 :         const bool bCntntCheck = pFrm->IsTxtFrm() && pCMS && pCMS->bCntntCheck;
     164             :         const SwRect aPaintRect( bCntntCheck ?
     165             :                                  pFrm->UnionFrm() :
     166         513 :                                  pFrm->PaintArea() );
     167             : 
     168         725 :         if ( aPaintRect.IsInside( rPoint ) &&
     169         362 :              ( bCntntCheck || pFrm->GetCrsrOfst( pPos, rPoint, pCMS ) ) )
     170         212 :             bRet = true;
     171             :         else
     172         301 :             pFrm = pFrm->GetNext();
     173         513 :         if ( pCMS && pCMS->bStop )
     174           0 :             return false;
     175             :     }
     176         513 :     return bRet;
     177             : }
     178             : 
     179             : /** Searches the page containing the searched point. */
     180             : 
     181         259 : bool SwPageFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
     182             :                              SwCrsrMoveState* pCMS, bool bTestBackground ) const
     183             : {
     184         259 :     bool bRet = false;
     185         259 :     Point aPoint( rPoint );
     186             : 
     187             :     // check, if we have to adjust the point
     188         259 :     if ( !Frm().IsInside( aPoint ) )
     189             :     {
     190           2 :         aPoint.X() = std::max( aPoint.X(), Frm().Left() );
     191           2 :         aPoint.X() = std::min( aPoint.X(), Frm().Right() );
     192           2 :         aPoint.Y() = std::max( aPoint.Y(), Frm().Top() );
     193           2 :         aPoint.Y() = std::min( aPoint.Y(), Frm().Bottom() );
     194             :     }
     195             : 
     196         259 :     bool bTextRet = false;
     197         259 :     bool bBackRet = false;
     198             : 
     199             :     //Could it be a free flying one?
     200             :     //If his content should be protected, we can't set the Crsr in it, thus
     201             :     //all changes should be impossible.
     202         259 :     if ( GetSortedObjs() )
     203             :     {
     204           2 :         bRet = lcl_GetCrsrOfst_Objects( this, false, pPos, rPoint, pCMS );
     205             :     }
     206             : 
     207         259 :     if ( !bRet )
     208             :     {
     209         259 :         SwPosition aBackPos( *pPos );
     210         518 :         SwPosition aTextPos( *pPos );
     211             : 
     212             :         //We fix the StartPoint if no Cntnt below the page 'answers' and then
     213             :         //start all over again one page before the current one.
     214             :         //However we cant use Flys in such a case.
     215         259 :         if ( SwLayoutFrm::GetCrsrOfst( &aTextPos, aPoint, pCMS ) )
     216             :         {
     217         106 :             bTextRet = true;
     218             :         }
     219             :         else
     220             :         {
     221         153 :             if ( pCMS && (pCMS->bStop || pCMS->bExactOnly) )
     222             :             {
     223           0 :                 ((SwCrsrMoveState*)pCMS)->bStop = true;
     224           0 :                 return false;
     225             :             }
     226         153 :             const SwCntntFrm *pCnt = GetCntntPos( aPoint, false, false, false, pCMS, false );
     227         153 :             if ( pCMS && pCMS->bStop )
     228           0 :                 return false;
     229             : 
     230             :             OSL_ENSURE( pCnt, "Crsr is gone to a Black hole" );
     231         153 :             if( pCMS && pCMS->pFill && pCnt->IsTxtFrm() )
     232           0 :                 bTextRet = pCnt->GetCrsrOfst( &aTextPos, rPoint, pCMS );
     233             :             else
     234         153 :                 bTextRet = pCnt->GetCrsrOfst( &aTextPos, aPoint, pCMS );
     235             : 
     236         153 :             if ( !bTextRet )
     237             :             {
     238             :                 // Set point to pCnt, delete mark
     239             :                 // this may happen, if pCnt is hidden
     240          30 :                 aTextPos = SwPosition( *pCnt->GetNode(), SwIndex( (SwTxtNode*)pCnt->GetNode(), 0 ) );
     241          30 :                 bTextRet = true;
     242             :             }
     243             :         }
     244             : 
     245         259 :         SwCntntNode* pTextNd = aTextPos.nNode.GetNode( ).GetCntntNode( );
     246         259 :         bool bConsiderBackground = true;
     247             :         // If the text position is a clickable field, then that should have priority.
     248         259 :         if (pTextNd && pTextNd->IsTxtNode())
     249             :         {
     250         259 :             SwTxtNode* pTxtNd = pTextNd->GetTxtNode();
     251         259 :             SwTxtAttr* pTxtAttr = pTxtNd->GetTxtAttrForCharAt(aTextPos.nContent.GetIndex(), RES_TXTATR_FIELD);
     252         259 :             if (pTxtAttr)
     253             :             {
     254           0 :                 const SwField* pField = pTxtAttr->GetFmtFld().GetField();
     255           0 :                 if (pField->IsClickable())
     256           0 :                     bConsiderBackground = false;
     257             :             }
     258             :         }
     259             : 
     260             :         // Check objects in the background if nothing else matched
     261         259 :         if ( GetSortedObjs() )
     262             :         {
     263           2 :             bBackRet = lcl_GetCrsrOfst_Objects( this, true, &aBackPos, rPoint, pCMS );
     264             :         }
     265             : 
     266         259 :         if ( ( bConsiderBackground && bTestBackground && bBackRet ) || !bTextRet )
     267             :         {
     268           0 :             bRet = bBackRet;
     269           0 :             (*pPos) = aBackPos;
     270             :         }
     271         259 :         else if (bTextRet && !bBackRet)
     272             :         {
     273         259 :             bRet = bTextRet;
     274         259 :             (*pPos) = aTextPos;
     275             :         }
     276             :         else
     277             :         {
     278             :             /* In order to provide a selection as accurable as possible when we have both
     279             :              * text and brackground object, then we compute the distance between both
     280             :              * would-be positions and the click point. The shortest distance wins.
     281             :              */
     282           0 :             double nTextDistance = 0;
     283           0 :             bool bValidTextDistance = false;
     284           0 :             if ( pTextNd )
     285             :             {
     286           0 :                 SwCntntFrm* pTextFrm = pTextNd->getLayoutFrm( getRootFrm( ) );
     287             : 
     288             :                 // try this again but prefer the "previous" position
     289           0 :                 SwCrsrMoveState aMoveState;
     290           0 :                 SwCrsrMoveState *const pState((pCMS) ? pCMS : &aMoveState);
     291             :                 comphelper::FlagRestorationGuard g(
     292           0 :                         pState->bPosMatchesBounds, true);
     293           0 :                 SwPosition prevTextPos(*pPos);
     294           0 :                 SwLayoutFrm::GetCrsrOfst(&prevTextPos, aPoint, pState);
     295             : 
     296           0 :                 SwRect aTextRect;
     297           0 :                 pTextFrm->GetCharRect(aTextRect, prevTextPos);
     298             : 
     299           0 :                 if (prevTextPos.nContent < pTextNd->Len())
     300             :                 {
     301             :                     // aRextRect is just a line on the left edge of the
     302             :                     // previous character; to get a better measure from
     303             :                     // lcl_getDistance, extend that to a rectangle over
     304             :                     // the entire character.
     305             :                     SwPosition const nextTextPos(prevTextPos.nNode,
     306           0 :                             SwIndex(prevTextPos.nContent, +1));
     307           0 :                     SwRect nextTextRect;
     308           0 :                     pTextFrm->GetCharRect(nextTextRect, nextTextPos);
     309           0 :                     SWRECTFN(pTextFrm);
     310           0 :                     if ((aTextRect.*fnRect->fnGetTop)() ==
     311           0 :                         (nextTextRect.*fnRect->fnGetTop)()) // same line?
     312             :                     {
     313             :                         // need to handle mixed RTL/LTR portions somehow
     314           0 :                         if ((aTextRect.*fnRect->fnGetLeft)() <
     315           0 :                             (nextTextRect.*fnRect->fnGetLeft)())
     316             :                         {
     317             :                             (aTextRect.*fnRect->fnSetRight)(
     318           0 :                                     (nextTextRect.*fnRect->fnGetLeft)());
     319             :                         }
     320             :                         else // RTL
     321             :                         {
     322             :                             (aTextRect.*fnRect->fnSetLeft)(
     323           0 :                                     (nextTextRect.*fnRect->fnGetLeft)());
     324             :                         }
     325           0 :                     }
     326             :                 }
     327             : 
     328           0 :                 nTextDistance = lcl_getDistance(aTextRect, rPoint);
     329           0 :                 bValidTextDistance = true;
     330             :             }
     331             : 
     332           0 :             double nBackDistance = 0;
     333           0 :             bool bValidBackDistance = false;
     334           0 :             SwCntntNode* pBackNd = aBackPos.nNode.GetNode( ).GetCntntNode( );
     335           0 :             if ( pBackNd && bConsiderBackground)
     336             :             {
     337             :                 // FIXME There are still cases were we don't have the proper node here.
     338           0 :                 SwCntntFrm* pBackFrm = pBackNd->getLayoutFrm( getRootFrm( ) );
     339           0 :                 SwRect rBackRect;
     340           0 :                 if (pBackFrm)
     341             :                 {
     342           0 :                     pBackFrm->GetCharRect( rBackRect, aBackPos );
     343             : 
     344           0 :                     nBackDistance = lcl_getDistance( rBackRect, rPoint );
     345           0 :                     bValidBackDistance = true;
     346             :                 }
     347             :             }
     348             : 
     349           0 :             if ( bValidTextDistance && bValidBackDistance && basegfx::fTools::more( nTextDistance, nBackDistance ) )
     350             :             {
     351           0 :                 bRet = bBackRet;
     352           0 :                 (*pPos) = aBackPos;
     353             :             }
     354             :             else
     355             :             {
     356           0 :                 bRet = bTextRet;
     357           0 :                 (*pPos) = aTextPos;
     358             :             }
     359         259 :         }
     360             :     }
     361             : 
     362         259 :     if ( bRet )
     363         259 :         rPoint = aPoint;
     364             : 
     365         259 :     return bRet;
     366             : }
     367             : 
     368           0 : bool SwLayoutFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
     369             : {
     370           0 :     bool bRet = false;
     371           0 :     if( rRect.IsOver(PaintArea()) )
     372             :     {
     373           0 :         const SwFrm* pFrm = Lower();
     374           0 :         while( pFrm )
     375             :         {
     376           0 :             pFrm->FillSelection( rList, rRect );
     377           0 :             pFrm = pFrm->GetNext();
     378             :         }
     379             :     }
     380           0 :     return bRet;
     381             : }
     382             : 
     383           0 : bool SwPageFrm::FillSelection( SwSelectionList& rList, const SwRect& rRect ) const
     384             : {
     385           0 :     bool bRet = false;
     386           0 :     if( rRect.IsOver(PaintArea()) )
     387             :     {
     388           0 :         bRet = SwLayoutFrm::FillSelection( rList, rRect );
     389           0 :         if( GetSortedObjs() )
     390             :         {
     391           0 :             const SwSortedObjs &rObjs = *GetSortedObjs();
     392           0 :             for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
     393             :             {
     394           0 :                 const SwAnchoredObject* pAnchoredObj = rObjs[i];
     395           0 :                 if( !pAnchoredObj->ISA(SwFlyFrm) )
     396           0 :                     continue;
     397           0 :                 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
     398           0 :                 if( pFly->FillSelection( rList, rRect ) )
     399           0 :                     bRet = true;
     400             :             }
     401             :         }
     402             :     }
     403           0 :     return bRet;
     404             : }
     405             : 
     406           0 : bool SwRootFrm::FillSelection( SwSelectionList& aSelList, const SwRect& rRect) const
     407             : {
     408           0 :     const SwFrm *pPage = Lower();
     409           0 :     const long nBottom = rRect.Bottom();
     410           0 :     while( pPage )
     411             :     {
     412           0 :         if( pPage->Frm().Top() < nBottom )
     413             :         {
     414           0 :             if( pPage->Frm().Bottom() > rRect.Top() )
     415           0 :                 pPage->FillSelection( aSelList, rRect );
     416           0 :             pPage = pPage->GetNext();
     417             :         }
     418             :         else
     419           0 :             pPage = 0;
     420             :     }
     421           0 :     return !aSelList.isEmpty();
     422             : }
     423             : 
     424             : /** Primary passes the call to the first page.
     425             :  *
     426             :  *  @return sal_False, if the passed Point gets changed
     427             :  */
     428         259 : bool SwRootFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
     429             :                              SwCrsrMoveState* pCMS, bool bTestBackground ) const
     430             : {
     431         259 :     const bool bOldAction = IsCallbackActionEnabled();
     432         259 :     ((SwRootFrm*)this)->SetCallbackActionEnabled( sal_False );
     433             :     OSL_ENSURE( (Lower() && Lower()->IsPageFrm()), "No PageFrm found." );
     434         259 :     if( pCMS && pCMS->pFill )
     435           0 :         ((SwCrsrMoveState*)pCMS)->bFillRet = false;
     436         259 :     Point aOldPoint = rPoint;
     437             : 
     438             :     // search for page containing rPoint. The borders around the pages are considerd
     439         259 :     const SwPageFrm* pPage = GetPageAtPos( rPoint, 0, true );
     440             : 
     441             :     // #i95626#
     442             :     // special handling for <rPoint> beyond root frames area
     443         261 :     if ( !pPage &&
     444         261 :          rPoint.X() > Frm().Right() &&
     445           2 :          rPoint.Y() > Frm().Bottom() )
     446             :     {
     447           2 :         pPage = dynamic_cast<const SwPageFrm*>(Lower());
     448           4 :         while ( pPage && pPage->GetNext() )
     449             :         {
     450           0 :             pPage = dynamic_cast<const SwPageFrm*>(pPage->GetNext());
     451             :         }
     452             :     }
     453         259 :     if ( pPage )
     454             :     {
     455         259 :         pPage->SwPageFrm::GetCrsrOfst( pPos, rPoint, pCMS, bTestBackground );
     456             :     }
     457             : 
     458         259 :     ((SwRootFrm*)this)->SetCallbackActionEnabled( bOldAction );
     459         259 :     if( pCMS )
     460             :     {
     461         259 :         if( pCMS->bStop )
     462           0 :             return false;
     463         259 :         if( pCMS->pFill )
     464           0 :             return pCMS->bFillRet;
     465             :     }
     466         259 :     return aOldPoint == rPoint;
     467             : }
     468             : 
     469             : /**
     470             :  * If this is about a Cntnt-carrying cell the Crsr will be force inserted into one of the CntntFrms
     471             :  * if there are no other options.
     472             :  *
     473             :  * There is no entry for protected cells.
     474             :  */
     475           0 : bool SwCellFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
     476             :                              SwCrsrMoveState* pCMS, bool ) const
     477             : {
     478             :     // cell frame does not necessarily have a lower (split table cell)
     479           0 :     if ( !Lower() )
     480           0 :         return false;
     481             : 
     482           0 :     if ( !(pCMS && pCMS->bSetInReadOnly) &&
     483           0 :          GetFmt()->GetProtect().IsCntntProtected() )
     484           0 :         return false;
     485             : 
     486           0 :     if ( pCMS && pCMS->eState == MV_TBLSEL )
     487             :     {
     488           0 :         const SwTabFrm *pTab = FindTabFrm();
     489           0 :         if ( pTab->IsFollow() && pTab->IsInHeadline( *this ) )
     490             :         {
     491           0 :             ((SwCrsrMoveState*)pCMS)->bStop = true;
     492           0 :             return false;
     493             :         }
     494             :     }
     495             : 
     496           0 :     if ( Lower() )
     497             :     {
     498           0 :         if ( Lower()->IsLayoutFrm() )
     499           0 :             return SwLayoutFrm::GetCrsrOfst( pPos, rPoint, pCMS );
     500             :         else
     501             :         {
     502           0 :             Calc();
     503           0 :             bool bRet = false;
     504             : 
     505           0 :             const SwFrm *pFrm = Lower();
     506           0 :             while ( pFrm && !bRet )
     507             :             {
     508           0 :                 pFrm->Calc();
     509           0 :                 if ( pFrm->Frm().IsInside( rPoint ) )
     510             :                 {
     511           0 :                     bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
     512           0 :                     if ( pCMS && pCMS->bStop )
     513           0 :                         return false;
     514             :                 }
     515           0 :                 pFrm = pFrm->GetNext();
     516             :             }
     517           0 :             if ( !bRet )
     518             :             {
     519           0 :                 const bool bFill = pCMS && pCMS->pFill;
     520           0 :                 Point aPoint( rPoint );
     521           0 :                 const SwCntntFrm *pCnt = GetCntntPos( rPoint, true );
     522           0 :                 if( bFill && pCnt->IsTxtFrm() )
     523             :                 {
     524           0 :                     rPoint = aPoint;
     525             :                 }
     526           0 :                 pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
     527             :             }
     528           0 :             return true;
     529             :         }
     530             :     }
     531             : 
     532           0 :     return false;
     533             : }
     534             : 
     535             : //Problem: If two Flys have the same size and share the same position then
     536             : //they end inside each other.
     537             : //Because we recursively check if a Point doesn't randomly lie inside an other
     538             : //fly which lies completely inside the current Fly we could trigger an endless
     539             : //loop with the mentioned situation above.
     540             : //Using the helper class SwCrsrOszControl we prevent the recursion. During
     541             : //a recursion GetCrsrOfst picks the one which lies on top.
     542           5 : bool SwFlyFrm::GetCrsrOfst( SwPosition *pPos, Point &rPoint,
     543             :                             SwCrsrMoveState* pCMS, bool ) const
     544             : {
     545           5 :     aOszCtrl.Entry( this );
     546             : 
     547             :     //If the Points lies inside the Fly, we try hard to set the Crsr inside it.
     548             :     //However if the Point sits inside a Fly which is completely located inside
     549             :     //the current one, we call GetCrsrOfst for it.
     550           5 :     Calc();
     551           5 :     bool bInside = Frm().IsInside( rPoint ) && Lower();
     552           5 :     bool bRet = false;
     553             : 
     554             :     //If an Frm contains a graphic, but only text was requested, it basically
     555             :     //won't accept the Crsr.
     556           5 :     if ( bInside && pCMS && pCMS->eState == MV_SETONLYTEXT &&
     557           0 :          (!Lower() || Lower()->IsNoTxtFrm()) )
     558           0 :         bInside = false;
     559             : 
     560           5 :     const SwPageFrm *pPage = FindPageFrm();
     561           5 :     if ( bInside && pPage && pPage->GetSortedObjs() )
     562             :     {
     563           0 :         SwOrderIter aIter( pPage );
     564           0 :         aIter.Top();
     565           0 :         while ( aIter() && !bRet )
     566             :         {
     567           0 :             const SwVirtFlyDrawObj* pObj = static_cast<const SwVirtFlyDrawObj*>(aIter());
     568           0 :             const SwFlyFrm* pFly = pObj ? pObj->GetFlyFrm() : 0;
     569           0 :             if ( pFly && pFly->Frm().IsInside( rPoint ) &&
     570           0 :                  Frm().IsInside( pFly->Frm() ) )
     571             :             {
     572           0 :                 if ( aOszCtrl.ChkOsz( pFly ) )
     573           0 :                     break;
     574           0 :                 bRet = pFly->GetCrsrOfst( pPos, rPoint, pCMS );
     575           0 :                 if ( bRet )
     576           0 :                     break;
     577           0 :                 if ( pCMS && pCMS->bStop )
     578           0 :                     return false;
     579             :             }
     580           0 :             aIter.Next();
     581             :         }
     582             :     }
     583             : 
     584          10 :     while ( bInside && !bRet )
     585             :     {
     586           0 :         const SwFrm *pFrm = Lower();
     587           0 :         while ( pFrm && !bRet )
     588             :         {
     589           0 :             pFrm->Calc();
     590           0 :             if ( pFrm->Frm().IsInside( rPoint ) )
     591             :             {
     592           0 :                 bRet = pFrm->GetCrsrOfst( pPos, rPoint, pCMS );
     593           0 :                 if ( pCMS && pCMS->bStop )
     594           0 :                     return false;
     595             :             }
     596           0 :             pFrm = pFrm->GetNext();
     597             :         }
     598           0 :         if ( !bRet )
     599             :         {
     600           0 :             const bool bFill = pCMS && pCMS->pFill;
     601           0 :             Point aPoint( rPoint );
     602           0 :             const SwCntntFrm *pCnt = GetCntntPos( rPoint, true, false, false, pCMS );
     603           0 :             if ( pCMS && pCMS->bStop )
     604           0 :                 return false;
     605           0 :             if( bFill && pCnt->IsTxtFrm() )
     606             :             {
     607           0 :                 rPoint = aPoint;
     608             :             }
     609           0 :             pCnt->GetCrsrOfst( pPos, rPoint, pCMS );
     610           0 :             bRet = true;
     611             :         }
     612             :     }
     613           5 :     aOszCtrl.Exit( this );
     614           5 :     return bRet;
     615             : }
     616             : 
     617             : /** Layout dependent cursor travelling */
     618           0 : bool SwCntntFrm::LeftMargin(SwPaM *pPam) const
     619             : {
     620           0 :     if( pPam->GetNode() != (SwCntntNode*)GetNode() )
     621           0 :         return false;
     622           0 :     ((SwCntntNode*)GetNode())->
     623           0 :         MakeStartIndex((SwIndex *) &pPam->GetPoint()->nContent);
     624           0 :     return true;
     625             : }
     626             : 
     627           0 : bool SwCntntFrm::RightMargin(SwPaM *pPam, bool) const
     628             : {
     629           0 :     if( pPam->GetNode() != (SwCntntNode*)GetNode() )
     630           0 :         return false;
     631           0 :     ((SwCntntNode*)GetNode())->
     632           0 :         MakeEndIndex((SwIndex *) &pPam->GetPoint()->nContent);
     633           0 :     return true;
     634             : }
     635             : 
     636           2 : static const SwCntntFrm *lcl_GetNxtCnt( const SwCntntFrm* pCnt )
     637             : {
     638           2 :     return pCnt->GetNextCntntFrm();
     639             : }
     640             : 
     641           4 : static const SwCntntFrm *lcl_GetPrvCnt( const SwCntntFrm* pCnt )
     642             : {
     643           4 :     return pCnt->GetPrevCntntFrm();
     644             : }
     645             : 
     646             : typedef const SwCntntFrm *(*GetNxtPrvCnt)( const SwCntntFrm* );
     647             : 
     648             : /// Frame in repeated headline?
     649           6 : static bool lcl_IsInRepeatedHeadline( const SwFrm *pFrm,
     650             :                                     const SwTabFrm** ppTFrm = 0 )
     651             : {
     652           6 :     const SwTabFrm *pTab = pFrm->FindTabFrm();
     653           6 :     if( ppTFrm )
     654           0 :         *ppTFrm = pTab;
     655           6 :     return pTab && pTab->IsFollow() && pTab->IsInHeadline( *pFrm );
     656             : }
     657             : 
     658             : /// Skip protected table cells. Optionally also skip repeated headlines.
     659             : //MA 1998-01-26: Chg also skip other protected areas
     660             : //FME: Skip follow flow cells
     661         293 : static const SwCntntFrm * lcl_MissProtectedFrames( const SwCntntFrm *pCnt,
     662             :                                                        GetNxtPrvCnt fnNxtPrv,
     663             :                                                        sal_Bool bMissHeadline,
     664             :                                                        sal_Bool bInReadOnly,
     665             :                                                        sal_Bool bMissFollowFlowLine )
     666             : {
     667         293 :     if ( pCnt && pCnt->IsInTab() )
     668             :     {
     669           6 :         sal_Bool bProtect = sal_True;
     670          18 :         while ( pCnt && bProtect )
     671             :         {
     672           6 :             const SwLayoutFrm *pCell = pCnt->GetUpper();
     673          12 :             while ( pCell && !pCell->IsCellFrm() )
     674           0 :                 pCell = pCell->GetUpper();
     675          12 :             if ( !pCell ||
     676           0 :                     (( ( bInReadOnly || !pCell->GetFmt()->GetProtect().IsCntntProtected() ) &&
     677           6 :                       ( !bMissHeadline || !lcl_IsInRepeatedHeadline( pCell ) ) &&
     678           6 :                       ( !bMissFollowFlowLine || !pCell->IsInFollowFlowRow() ) &&
     679           6 :                        !pCell->IsCoveredCell()) ) )
     680           6 :                 bProtect = sal_False;
     681             :             else
     682           0 :                 pCnt = (*fnNxtPrv)( pCnt );
     683             :         }
     684             :     }
     685         287 :     else if ( !bInReadOnly )
     686         514 :         while ( pCnt && pCnt->IsProtected() )
     687           0 :             pCnt = (*fnNxtPrv)( pCnt );
     688             : 
     689         293 :     return pCnt;
     690             : }
     691             : 
     692           3 : static bool lcl_UpDown( SwPaM *pPam, const SwCntntFrm *pStart,
     693             :                     GetNxtPrvCnt fnNxtPrv, bool bInReadOnly )
     694             : {
     695             :     OSL_ENSURE( pPam->GetNode() == (SwCntntNode*)pStart->GetNode(),
     696             :             "lcl_UpDown doesn't work for others." );
     697             : 
     698           3 :     const SwCntntFrm *pCnt = 0;
     699             : 
     700             :     //We have to cheat a little bit during a table selection: Go to the
     701             :     //beginning of the cell while going up and go to the end of the cell while
     702             :     //going down.
     703           3 :     bool bTblSel = false;
     704           6 :     if ( pStart->IsInTab() &&
     705           3 :         pPam->GetNode( true )->StartOfSectionNode() !=
     706           3 :         pPam->GetNode( false )->StartOfSectionNode() )
     707             :     {
     708           0 :         bTblSel = true;
     709           0 :         const SwLayoutFrm  *pCell = pStart->GetUpper();
     710           0 :         while ( !pCell->IsCellFrm() )
     711           0 :             pCell = pCell->GetUpper();
     712             : 
     713             :         // Check, if cell has a Prev/Follow cell:
     714           0 :         const bool bFwd = ( fnNxtPrv == lcl_GetNxtCnt );
     715             :         const SwLayoutFrm* pTmpCell = bFwd ?
     716             :             ((SwCellFrm*)pCell)->GetFollowCell() :
     717           0 :             ((SwCellFrm*)pCell)->GetPreviousCell();
     718             : 
     719           0 :         const SwCntntFrm* pTmpStart = pStart;
     720           0 :         while ( pTmpCell && 0 != ( pTmpStart = pTmpCell->ContainsCntnt() ) )
     721             :         {
     722           0 :             pCell = pTmpCell;
     723             :             pTmpCell = bFwd ?
     724             :                 ((SwCellFrm*)pCell)->GetFollowCell() :
     725           0 :                 ((SwCellFrm*)pCell)->GetPreviousCell();
     726             :         }
     727           0 :         const SwCntntFrm *pNxt = pCnt = pTmpStart;
     728             : 
     729           0 :         while ( pCell->IsAnLower( pNxt ) )
     730             :         {
     731           0 :             pCnt = pNxt;
     732           0 :             pNxt = (*fnNxtPrv)( pNxt );
     733             :         }
     734             :     }
     735             : 
     736           3 :     pCnt = (*fnNxtPrv)( pCnt ? pCnt : pStart );
     737           3 :     pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
     738             : 
     739           3 :     const SwTabFrm *pStTab = pStart->FindTabFrm();
     740           3 :     const SwTabFrm *pTable = 0;
     741           3 :     const bool bTab = pStTab || (pCnt && pCnt->IsInTab());
     742           3 :     bool bEnd = !bTab;
     743             : 
     744           3 :     const SwFrm* pVertRefFrm = pStart;
     745           3 :     if ( bTblSel && pStTab )
     746           0 :         pVertRefFrm = pStTab;
     747           3 :     SWRECTFN( pVertRefFrm )
     748             : 
     749           3 :     SwTwips nX = 0;
     750           3 :     if ( bTab )
     751             :     {
     752             :         // pStart or pCnt is inside a table. nX will be used for travelling:
     753           3 :         SwRect aRect( pStart->Frm() );
     754           3 :         pStart->GetCharRect( aRect, *pPam->GetPoint() );
     755           3 :         Point aCenter = aRect.Center();
     756           3 :         nX = bVert ? aCenter.Y() : aCenter.X();
     757             : 
     758           3 :         pTable = pCnt ? pCnt->FindTabFrm() : 0;
     759           3 :         if ( !pTable )
     760           0 :             pTable = pStTab;
     761             : 
     762           6 :         if ( pStTab &&
     763           6 :             !pStTab->GetUpper()->IsInTab() &&
     764           3 :             !pTable->GetUpper()->IsInTab() )
     765             :         {
     766           3 :             const SwFrm *pCell = pStart->GetUpper();
     767           6 :             while ( pCell && !pCell->IsCellFrm() )
     768           0 :                 pCell = pCell->GetUpper();
     769             :             OSL_ENSURE( pCell, "could not find the cell" );
     770           3 :             nX =  (pCell->Frm().*fnRect->fnGetLeft)() +
     771           3 :                   (pCell->Frm().*fnRect->fnGetWidth)() / 2;
     772             : 
     773             :             //The flow leads from one table to the next. The X-value needs to be
     774             :             //corrected based on the middle of the starting cell by the amount
     775             :             //of the offset of the tables.
     776           3 :             if ( pStTab != pTable )
     777             :             {
     778           0 :                 nX += (pTable->Frm().*fnRect->fnGetLeft)() -
     779           0 :                       (pStTab->Frm().*fnRect->fnGetLeft)();
     780             :             }
     781             :         }
     782             : 
     783             :         // Restrict nX to the left and right borders of pTab:
     784             :         // (is this really necessary?)
     785           3 :         if ( !pTable->GetUpper()->IsInTab() )
     786             :         {
     787           3 :             const bool bRTL = pTable->IsRightToLeft();
     788             :             const long nPrtLeft = bRTL ?
     789           0 :                                 (pTable->*fnRect->fnGetPrtRight)() :
     790           3 :                                 (pTable->*fnRect->fnGetPrtLeft)();
     791           3 :             if ( bRTL != (nX < nPrtLeft) )
     792           0 :                 nX = nPrtLeft;
     793             :             else
     794             :             {
     795             :                    const long nPrtRight = bRTL ?
     796           0 :                                     (pTable->*fnRect->fnGetPrtLeft)() :
     797           3 :                                     (pTable->*fnRect->fnGetPrtRight)();
     798           3 :                 if ( bRTL != (nX > nPrtRight) )
     799           0 :                     nX = nPrtRight;
     800             :             }
     801             :         }
     802             :     }
     803             : 
     804           6 :     do
     805             :     {
     806             :         //If I'm in the DocumentBody, I wan't to stay there.
     807           6 :         if ( pStart->IsInDocBody() )
     808             :         {
     809          18 :             while ( pCnt && (!pCnt->IsInDocBody() ||
     810          12 :                              (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
     811             :             {
     812           0 :                 pCnt = (*fnNxtPrv)( pCnt );
     813           0 :                 pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
     814             :             }
     815             :         }
     816             : 
     817             :         //If I'm in the FootNoteArea, I try to reach the next FootNoteArea in
     818             :         //case of necessity.
     819           0 :         else if ( pStart->IsInFtn() )
     820             :         {
     821           0 :             while ( pCnt && (!pCnt->IsInFtn() ||
     822           0 :                             (pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow())))
     823             :             {
     824           0 :                 pCnt = (*fnNxtPrv)( pCnt );
     825           0 :                 pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
     826             :             }
     827             :         }
     828             : 
     829             :         //In Flys we can go ahead blindly as long as we find a Cntnt.
     830           0 :         else if ( pStart->IsInFly() )
     831             :         {
     832           0 :             if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() )
     833             :             {
     834           0 :                 pCnt = (*fnNxtPrv)( pCnt );
     835           0 :                 pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
     836             :             }
     837             :         }
     838             : 
     839             :         //Otherwise I'll just refuse to leave to current area.
     840           0 :         else if ( pCnt )
     841             :         {
     842           0 :             const SwFrm *pUp = pStart->GetUpper();               //Head/Foot
     843           0 :             while ( pUp && pUp->GetUpper() && !(pUp->GetType() & 0x0018 ) )
     844           0 :                 pUp = pUp->GetUpper();
     845           0 :             bool bSame = false;
     846           0 :             const SwFrm *pCntUp = pCnt->GetUpper();
     847           0 :             while ( pCntUp && !bSame )
     848             :             {
     849           0 :                 if ( pUp == pCntUp )
     850           0 :                     bSame = true;
     851             :                 else
     852           0 :                     pCntUp = pCntUp->GetUpper();
     853             :             }
     854           0 :             if ( !bSame )
     855           0 :                 pCnt = 0;
     856           0 :             else if ( pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow() ) // i73332
     857             :             {
     858           0 :                 pCnt = (*fnNxtPrv)( pCnt );
     859           0 :                 pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
     860             :             }
     861             :         }
     862             : 
     863           6 :         if ( bTab )
     864             :         {
     865           6 :             if ( !pCnt )
     866           0 :                 bEnd = true;
     867             :             else
     868             :             {
     869           6 :                 const SwTabFrm *pTab = pCnt->FindTabFrm();
     870           6 :                 if( !pTab )
     871           0 :                     bEnd = true;
     872             :                 else
     873             :                 {
     874           6 :                     if ( pTab != pTable )
     875             :                     {
     876             :                         //The flow leads from one table to the next. The X-value
     877             :                         //needs to be corrected by the amount of the offset of
     878             :                         //the tables
     879           0 :                          if ( pTable &&
     880           0 :                               !pTab->GetUpper()->IsInTab() &&
     881           0 :                             !pTable->GetUpper()->IsInTab() )
     882           0 :                             nX += pTab->Frm().Left() - pTable->Frm().Left();
     883           0 :                         pTable = pTab;
     884             :                     }
     885           6 :                     const SwLayoutFrm *pCell = pCnt->GetUpper();
     886          12 :                     while ( pCell && !pCell->IsCellFrm() )
     887           0 :                         pCell = pCell->GetUpper();
     888             : 
     889           6 :                     Point aInsideCell;
     890           6 :                     Point aInsideCnt;
     891           6 :                     if ( pCell )
     892             :                     {
     893           6 :                         long nTmpTop = (pCell->Frm().*fnRect->fnGetTop)();
     894           6 :                         if ( bVert )
     895             :                         {
     896           0 :                             if ( nTmpTop )
     897           0 :                                 --nTmpTop;
     898             : 
     899           0 :                             aInsideCell = Point( nTmpTop, nX );
     900             :                         }
     901             :                         else
     902           6 :                             aInsideCell = Point( nX, nTmpTop );
     903             :                     }
     904             : 
     905           6 :                     long nTmpTop = (pCnt->Frm().*fnRect->fnGetTop)();
     906           6 :                     if ( bVert )
     907             :                     {
     908           0 :                         if ( nTmpTop )
     909           0 :                             --nTmpTop;
     910             : 
     911           0 :                         aInsideCnt = Point( nTmpTop, nX );
     912             :                     }
     913             :                     else
     914           6 :                         aInsideCnt = Point( nX, nTmpTop );
     915             : 
     916           6 :                     if ( pCell && pCell->Frm().IsInside( aInsideCell ) )
     917             :                     {
     918           3 :                         bEnd = true;
     919             :                         //Get the right Cntnt out of the cell.
     920           3 :                         if ( !pCnt->Frm().IsInside( aInsideCnt ) )
     921             :                         {
     922           0 :                             pCnt = pCell->ContainsCntnt();
     923           0 :                             if ( fnNxtPrv == lcl_GetPrvCnt )
     924           0 :                                 while ( pCell->IsAnLower(pCnt->GetNextCntntFrm()) )
     925           0 :                                     pCnt = pCnt->GetNextCntntFrm();
     926             :                         }
     927             :                     }
     928           3 :                     else if ( pCnt->Frm().IsInside( aInsideCnt ) )
     929           0 :                         bEnd = true;
     930             :                 }
     931             :             }
     932           6 :             if ( !bEnd )
     933             :             {
     934           3 :                 pCnt = (*fnNxtPrv)( pCnt );
     935           3 :                 pCnt = ::lcl_MissProtectedFrames( pCnt, fnNxtPrv, true, bInReadOnly, bTblSel );
     936             :             }
     937             :         }
     938             : 
     939           9 :     } while ( !bEnd ||
     940           3 :               (pCnt && pCnt->IsTxtFrm() && ((SwTxtFrm*)pCnt)->IsHiddenNow()));
     941             : 
     942           3 :     if( pCnt )
     943             :     {   // set the Point on the Content-Node
     944           3 :         SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
     945           3 :         pPam->GetPoint()->nNode = *pCNd;
     946           3 :         if ( fnNxtPrv == lcl_GetPrvCnt )
     947           2 :             pCNd->MakeEndIndex( (SwIndex*)&pPam->GetPoint()->nContent );
     948             :         else
     949           1 :             pCNd->MakeStartIndex( (SwIndex*)&pPam->GetPoint()->nContent );
     950           3 :         return true;
     951             :     }
     952           0 :     return false;
     953             : }
     954             : 
     955           2 : bool SwCntntFrm::UnitUp( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const
     956             : {
     957           2 :     return ::lcl_UpDown( pPam, this, lcl_GetPrvCnt, bInReadOnly );
     958             : }
     959             : 
     960           1 : bool SwCntntFrm::UnitDown( SwPaM* pPam, const SwTwips, bool bInReadOnly ) const
     961             : {
     962           1 :     return ::lcl_UpDown( pPam, this, lcl_GetNxtCnt, bInReadOnly );
     963             : }
     964             : 
     965             : /** Returns the number of the current page.
     966             :  *
     967             :  * If the method gets a PaM then the current page is the one in which the PaM sits. Otherwise the
     968             :  * current page is the first one inside the VisibleArea. We only work on available pages!
     969             :  */
     970           0 : sal_uInt16 SwRootFrm::GetCurrPage( const SwPaM *pActualCrsr ) const
     971             : {
     972             :     OSL_ENSURE( pActualCrsr, "got no page cursor" );
     973           0 :     SwFrm const*const pActFrm = pActualCrsr->GetPoint()->nNode.GetNode().
     974             :                                     GetCntntNode()->getLayoutFrm( this, 0,
     975             :                                                     pActualCrsr->GetPoint(),
     976           0 :                                                     false );
     977           0 :     return pActFrm->FindPageFrm()->GetPhyPageNum();
     978             : }
     979             : 
     980             : /** Returns a PaM which sits at the beginning of the requested page.
     981             :  *
     982             :  * Formatting is done as far as necessary.
     983             :  * The PaM sits on the last page, if the page number was chosen to big.
     984             :  *
     985             :  * @return Null, if the operation was not possible.
     986             :  */
     987           1 : sal_uInt16 SwRootFrm::SetCurrPage( SwCursor* pToSet, sal_uInt16 nPageNum )
     988             : {
     989             :     OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "No page available." );
     990             : 
     991           1 :     SwPageFrm *pPage = (SwPageFrm*)Lower();
     992           1 :     sal_Bool bEnd =sal_False;
     993           2 :     while ( !bEnd && pPage->GetPhyPageNum() != nPageNum )
     994           0 :     {   if ( pPage->GetNext() )
     995           0 :             pPage = (SwPageFrm*)pPage->GetNext();
     996             :         else
     997             :         {   //Search the first CntntFrm and format until a new page is started
     998             :             //or until the CntntFrm are all done.
     999           0 :             const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
    1000           0 :             while ( pCntnt && pPage->IsAnLower( pCntnt ) )
    1001             :             {
    1002           0 :                 pCntnt->Calc();
    1003           0 :                 pCntnt = pCntnt->GetNextCntntFrm();
    1004             :             }
    1005             :             //Either this is a new page or we found the last page.
    1006           0 :             if ( pPage->GetNext() )
    1007           0 :                 pPage = (SwPageFrm*)pPage->GetNext();
    1008             :             else
    1009           0 :                 bEnd = sal_True;
    1010             :         }
    1011             :     }
    1012             :     //pPage now points to the 'requested' page. Now we have to create the PaM
    1013             :     //on the beginning of the first CntntFrm in the body-text.
    1014             :     //If this is a footnote-page, the PaM will be set in the first footnote.
    1015           1 :     const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
    1016           1 :     if ( pPage->IsFtnPage() )
    1017           0 :         while ( pCntnt && !pCntnt->IsInFtn() )
    1018           0 :             pCntnt = pCntnt->GetNextCntntFrm();
    1019             :     else
    1020           2 :         while ( pCntnt && !pCntnt->IsInDocBody() )
    1021           0 :             pCntnt = pCntnt->GetNextCntntFrm();
    1022           1 :     if ( pCntnt )
    1023             :     {
    1024           1 :         SwCntntNode* pCNd = (SwCntntNode*)pCntnt->GetNode();
    1025           1 :         pToSet->GetPoint()->nNode = *pCNd;
    1026           1 :         pCNd->MakeStartIndex( (SwIndex*)&pToSet->GetPoint()->nContent );
    1027           1 :         pToSet->GetPoint()->nContent = ((SwTxtFrm*)pCntnt)->GetOfst();
    1028             : 
    1029           1 :         SwShellCrsr* pSCrsr = dynamic_cast<SwShellCrsr*>(pToSet);
    1030           1 :         if( pSCrsr )
    1031             :         {
    1032           1 :             Point &rPt = pSCrsr->GetPtPos();
    1033           1 :             rPt = pCntnt->Frm().Pos();
    1034           1 :             rPt += pCntnt->Prt().Pos();
    1035             :         }
    1036           1 :         return pPage->GetPhyPageNum();
    1037             :     }
    1038           0 :     return 0;
    1039             : }
    1040             : 
    1041          25 : SwCntntFrm *GetFirstSub( const SwLayoutFrm *pLayout )
    1042             : {
    1043          25 :     return ((SwPageFrm*)pLayout)->FindFirstBodyCntnt();
    1044             : }
    1045             : 
    1046           2 : SwCntntFrm *GetLastSub( const SwLayoutFrm *pLayout )
    1047             : {
    1048           2 :     return ((SwPageFrm*)pLayout)->FindLastBodyCntnt();
    1049             : }
    1050             : 
    1051           1 : SwLayoutFrm *GetNextFrm( const SwLayoutFrm *pFrm )
    1052             : {
    1053             :     SwLayoutFrm *pNext =
    1054           2 :         (pFrm->GetNext() && pFrm->GetNext()->IsLayoutFrm()) ?
    1055           2 :                                             (SwLayoutFrm*)pFrm->GetNext() : 0;
    1056             :     // #i39402# in case of an empty page
    1057           1 :     if(pNext && !pNext->ContainsCntnt())
    1058           0 :         pNext = (pNext->GetNext() && pNext->GetNext()->IsLayoutFrm()) ?
    1059           0 :                                             (SwLayoutFrm*)pNext->GetNext() : 0;
    1060           1 :     return pNext;
    1061             : }
    1062             : 
    1063          25 : SwLayoutFrm *GetThisFrm( const SwLayoutFrm *pFrm )
    1064             : {
    1065          25 :     return (SwLayoutFrm*)pFrm;
    1066             : }
    1067             : 
    1068           1 : SwLayoutFrm *GetPrevFrm( const SwLayoutFrm *pFrm )
    1069             : {
    1070             :     SwLayoutFrm *pPrev =
    1071           2 :         (pFrm->GetPrev() && pFrm->GetPrev()->IsLayoutFrm()) ?
    1072           2 :                                             (SwLayoutFrm*)pFrm->GetPrev() : 0;
    1073             :     // #i39402# in case of an empty page
    1074           1 :     if(pPrev && !pPrev->ContainsCntnt())
    1075           0 :         pPrev = (pPrev->GetPrev() && pPrev->GetPrev()->IsLayoutFrm()) ?
    1076           0 :                                             (SwLayoutFrm*)pPrev->GetPrev() : 0;
    1077           1 :     return pPrev;
    1078             : }
    1079             : 
    1080             : //Now we can also initialize de function pointers;
    1081             : //they are declared in cshtyp.hxx
    1082             : SwPosPage fnPageStart = GetFirstSub;
    1083             : SwPosPage fnPageEnd = GetLastSub;
    1084             : SwWhichPage fnPagePrev = GetPrevFrm;
    1085             : SwWhichPage fnPageCurr = GetThisFrm;
    1086             : SwWhichPage fnPageNext = GetNextFrm;
    1087             : 
    1088             : /**
    1089             :  * Returns the first/last Contentframe (controlled using the parameter fnPosPage)
    1090             :  * of the current/previous/next page (controlled using the parameter fnWhichPage).
    1091             :  */
    1092          27 : sal_Bool GetFrmInPage( const SwCntntFrm *pCnt, SwWhichPage fnWhichPage,
    1093             :                    SwPosPage fnPosPage, SwPaM *pPam )
    1094             : {
    1095             :     //First find the requested page, at first the current, then the one which
    1096             :     //was requests through fnWichPage.
    1097          27 :     const SwLayoutFrm *pLayoutFrm = pCnt->FindPageFrm();
    1098          27 :     if ( !pLayoutFrm || (0 == (pLayoutFrm = (*fnWhichPage)(pLayoutFrm))) )
    1099           0 :         return sal_False;
    1100             : 
    1101             :     //Now the desired CntntFrm below the page
    1102          27 :     if( 0 == (pCnt = (*fnPosPage)(pLayoutFrm)) )
    1103           0 :         return sal_False;
    1104             :     else
    1105             :     {
    1106             :         // repeated headlines in tables
    1107          27 :         if ( pCnt->IsInTab() && fnPosPage == GetFirstSub )
    1108             :         {
    1109           6 :             const SwTabFrm* pTab = pCnt->FindTabFrm();
    1110           6 :             if ( pTab->IsFollow() )
    1111             :             {
    1112           4 :                 if ( pTab->IsInHeadline( *pCnt ) )
    1113             :                 {
    1114           0 :                     SwLayoutFrm* pRow = pTab->GetFirstNonHeadlineRow();
    1115           0 :                     if ( pRow )
    1116             :                     {
    1117             :                         // We are in the first line of a follow table
    1118             :                         // with repeated headings.
    1119             :                         // To actually make a "real" move we take the first content
    1120             :                         // of the next row
    1121           0 :                         pCnt = pRow->ContainsCntnt();
    1122           0 :                         if ( ! pCnt )
    1123           0 :                             return sal_False;
    1124             :                     }
    1125             :                 }
    1126             :             }
    1127             :         }
    1128             : 
    1129          27 :         SwCntntNode *pCNd = (SwCntntNode*)pCnt->GetNode();
    1130          27 :         pPam->GetPoint()->nNode = *pCNd;
    1131             :         sal_Int32 nIdx;
    1132          27 :         if( fnPosPage == GetFirstSub )
    1133          25 :             nIdx = ((SwTxtFrm*)pCnt)->GetOfst();
    1134             :         else
    1135           2 :             nIdx = pCnt->GetFollow() ?
    1136           2 :                     ((SwTxtFrm*)pCnt)->GetFollow()->GetOfst()-1 : pCNd->Len();
    1137          27 :         pPam->GetPoint()->nContent.Assign( pCNd, nIdx );
    1138          27 :         return sal_True;
    1139             :     }
    1140             : }
    1141             : 
    1142         255 : static sal_uInt64 CalcDiff(const Point &rPt1, const Point &rPt2)
    1143             : {
    1144             :     //Calculate the distance between the two points.
    1145             :     //'delta' X^2 + 'delta'Y^2 = 'distance'^2
    1146         765 :     sal_uInt64 dX = std::max( rPt1.X(), rPt2.X() ) -
    1147         510 :                std::min( rPt1.X(), rPt2.X() ),
    1148         765 :           dY = std::max( rPt1.Y(), rPt2.Y() ) -
    1149         510 :                std::min( rPt1.Y(), rPt2.Y() );
    1150         255 :     return (dX * dX) + (dY * dY);
    1151             : }
    1152             : 
    1153             : /** Check if the point lies inside the page part in wich also the CntntFrame lies.
    1154             :  *
    1155             :  * In this context header, page body, footer and footnote-container count as page part.
    1156             :  * This will suit the purpose that the CntntFrm which lies in the "right" page part will be
    1157             :  * accepted instead of one which doesn't lie there although his distance to the point is shorter.
    1158             :  */
    1159         255 : static const SwLayoutFrm* lcl_Inside( const SwCntntFrm *pCnt, Point& rPt )
    1160             : {
    1161         255 :     const SwLayoutFrm* pUp = pCnt->GetUpper();
    1162         564 :     while( pUp )
    1163             :     {
    1164         309 :         if( pUp->IsPageBodyFrm() || pUp->IsFooterFrm() || pUp->IsHeaderFrm() )
    1165             :         {
    1166         255 :             if( rPt.Y() >= pUp->Frm().Top() && rPt.Y() <= pUp->Frm().Bottom() )
    1167         121 :                 return pUp;
    1168         134 :             return NULL;
    1169             :         }
    1170          54 :         if( pUp->IsFtnContFrm() )
    1171           0 :             return pUp->Frm().IsInside( rPt ) ? pUp : NULL;
    1172          54 :         pUp = pUp->GetUpper();
    1173             :     }
    1174           0 :     return NULL;
    1175             : }
    1176             : 
    1177             : /** Search for the nearest Cntnt to pass.
    1178             :  *
    1179             :  * Considers the previous, the current and the next page.
    1180             :  * If no content is found, the area gets expanded until one is found.
    1181             :  *
    1182             :  * @return The 'semantically correct' position inside the PrtArea of the found CntntFrm.
    1183             :  */
    1184         163 : const SwCntntFrm *SwLayoutFrm::GetCntntPos( Point& rPoint,
    1185             :                                             const sal_Bool bDontLeave,
    1186             :                                             const sal_Bool bBodyOnly,
    1187             :                                             const sal_Bool bCalc,
    1188             :                                             const SwCrsrMoveState *pCMS,
    1189             :                                             const sal_Bool bDefaultExpand ) const
    1190             : {
    1191             :     //Determine the first CntntFrm.
    1192         163 :     const SwLayoutFrm *pStart = (!bDontLeave && bDefaultExpand && GetPrev()) ?
    1193         168 :                                     (SwLayoutFrm*)GetPrev() : this;
    1194         163 :     const SwCntntFrm *pCntnt = pStart->ContainsCntnt();
    1195             : 
    1196         163 :     if ( !pCntnt && (GetPrev() && !bDontLeave) )
    1197           0 :         pCntnt = ContainsCntnt();
    1198             : 
    1199         163 :     if ( bBodyOnly && pCntnt && !pCntnt->IsInDocBody() )
    1200           0 :         while ( pCntnt && !pCntnt->IsInDocBody() )
    1201           0 :             pCntnt = pCntnt->GetNextCntntFrm();
    1202             : 
    1203         163 :     const SwCntntFrm *pActual= pCntnt;
    1204         163 :     const SwLayoutFrm *pInside = NULL;
    1205         163 :     sal_uInt16 nMaxPage = GetPhyPageNum() + (bDefaultExpand ? 1 : 0);
    1206         163 :     Point aPoint = rPoint;
    1207         163 :     sal_uInt64 nDistance = SAL_MAX_UINT64;
    1208             : 
    1209             :     while ( true )  //A loop to be sure we always find one.
    1210             :     {
    1211        1110 :         while ( pCntnt &&
    1212         393 :                 ((!bDontLeave || IsAnLower( pCntnt )) &&
    1213         393 :                 (pCntnt->GetPhyPageNum() <= nMaxPage)) )
    1214             :         {
    1215         680 :             if ( ( bCalc || pCntnt->Frm().Width() ) &&
    1216         133 :                  ( !bBodyOnly || pCntnt->IsInDocBody() ) )
    1217             :             {
    1218             :                 //If the Cntnt lies in a protected area (cell, Ftn, section),
    1219             :                 //we search the next Cntnt which is not protected.
    1220         287 :                 const SwCntntFrm *pComp = pCntnt;
    1221             :                 pCntnt = ::lcl_MissProtectedFrames( pCntnt, lcl_GetNxtCnt, sal_False,
    1222         287 :                                         pCMS ? pCMS->bSetInReadOnly : sal_False, sal_False );
    1223         287 :                 if ( pComp != pCntnt )
    1224           0 :                     continue;
    1225             : 
    1226         287 :                 if ( !pCntnt->IsTxtFrm() || !((SwTxtFrm*)pCntnt)->IsHiddenNow() )
    1227             :                 {
    1228         257 :                     if ( bCalc )
    1229           0 :                         pCntnt->Calc();
    1230             : 
    1231         257 :                     SwRect aCntFrm( pCntnt->UnionFrm() );
    1232         257 :                     if ( aCntFrm.IsInside( rPoint ) )
    1233             :                     {
    1234           2 :                         pActual = pCntnt;
    1235           2 :                         aPoint = rPoint;
    1236           2 :                         break;
    1237             :                     }
    1238             :                     //The distance from rPoint to the nearest Point of pCntnt
    1239             :                     //will now be calculated.
    1240         255 :                     Point aCntntPoint( rPoint );
    1241             : 
    1242             :                     //First set the vertical position
    1243         255 :                     if ( aCntFrm.Top() > aCntntPoint.Y() )
    1244           3 :                         aCntntPoint.Y() = aCntFrm.Top();
    1245         252 :                     else if ( aCntFrm.Bottom() < aCntntPoint.Y() )
    1246         252 :                         aCntntPoint.Y() = aCntFrm.Bottom();
    1247             : 
    1248             :                     //Now the horizontal position
    1249         255 :                     if ( aCntFrm.Left() > aCntntPoint.X() )
    1250           2 :                         aCntntPoint.X() = aCntFrm.Left();
    1251         253 :                     else if ( aCntFrm.Right() < aCntntPoint.X() )
    1252          20 :                         aCntntPoint.X() = aCntFrm.Right();
    1253             : 
    1254             :                     // pInside is a page area in which the point lies. As soon
    1255             :                     // as pInside != 0 only frames are accepted which are
    1256             :                     // placed inside.
    1257         510 :                     if( !pInside || ( pInside->IsAnLower( pCntnt ) &&
    1258           0 :                         ( !pCntnt->IsInFtn() || pInside->IsFtnContFrm() ) ) )
    1259             :                     {
    1260         255 :                         const sal_uInt64 nDiff = ::CalcDiff(aCntntPoint, rPoint);
    1261         255 :                         sal_Bool bBetter = nDiff < nDistance;  // This one is nearer
    1262         255 :                         if( !pInside )
    1263             :                         {
    1264         255 :                             pInside = lcl_Inside( pCntnt, rPoint );
    1265         255 :                             if( pInside )  // In the "right" page area
    1266         121 :                                 bBetter = sal_True;
    1267             :                         }
    1268         255 :                         if( bBetter )
    1269             :                         {
    1270         253 :                             aPoint = aCntntPoint;
    1271         253 :                             nDistance = nDiff;
    1272         253 :                             pActual = pCntnt;
    1273             :                         }
    1274             :                     }
    1275             :                 }
    1276             :             }
    1277         391 :             pCntnt = pCntnt->GetNextCntntFrm();
    1278         391 :             if ( bBodyOnly )
    1279         476 :                 while ( pCntnt && !pCntnt->IsInDocBody() )
    1280          10 :                     pCntnt = pCntnt->GetNextCntntFrm();
    1281             :         }
    1282         163 :         if ( !pActual )
    1283             :         {   //If we not yet found one we have to expand the searched
    1284             :             //area, sometime we will find one!
    1285             :             //MA 1997-01-09: Opt for many empty pages - if we only search inside
    1286             :             //the body, we can expand the searched area sufficiently in one step.
    1287           0 :             if ( bBodyOnly )
    1288             :             {
    1289           0 :                 while ( !pCntnt && pStart->GetPrev() )
    1290             :                 {
    1291           0 :                     ++nMaxPage;
    1292           0 :                     if( !pStart->GetPrev()->IsLayoutFrm() )
    1293           0 :                         return 0;
    1294           0 :                     pStart = (SwLayoutFrm*)pStart->GetPrev();
    1295           0 :                     pCntnt = pStart->IsInDocBody()
    1296             :                                 ? pStart->ContainsCntnt()
    1297           0 :                                 : pStart->FindPageFrm()->FindFirstBodyCntnt();
    1298             :                 }
    1299           0 :                 if ( !pCntnt )  // Somewhere down the road we have to start with one!
    1300             :                 {
    1301           0 :                     pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
    1302           0 :                     while ( pCntnt && !pCntnt->IsInDocBody() )
    1303           0 :                         pCntnt = pCntnt->GetNextCntntFrm();
    1304           0 :                     if ( !pCntnt )
    1305           0 :                         return 0;   // There is no document content yet!
    1306             :                 }
    1307             :             }
    1308             :             else
    1309             :             {
    1310           0 :                 ++nMaxPage;
    1311           0 :                 if ( pStart->GetPrev() )
    1312             :                 {
    1313           0 :                     if( !pStart->GetPrev()->IsLayoutFrm() )
    1314           0 :                         return 0;
    1315           0 :                     pStart = (SwLayoutFrm*)pStart->GetPrev();
    1316           0 :                     pCntnt = pStart->ContainsCntnt();
    1317             :                 }
    1318             :                 else // Somewhere down the road we have to start with one!
    1319           0 :                     pCntnt = pStart->FindPageFrm()->GetUpper()->ContainsCntnt();
    1320             :             }
    1321           0 :             pActual = pCntnt;
    1322             :         }
    1323             :         else
    1324         163 :             break;
    1325             :     }
    1326             : 
    1327             :     OSL_ENSURE( pActual, "no Cntnt found." );
    1328             :     OSL_ENSURE( !bBodyOnly || pActual->IsInDocBody(), "Cntnt not in Body." );
    1329             : 
    1330             :     //Special case for selecting tables not in repeated TblHeadlines.
    1331         163 :     if ( pActual->IsInTab() && pCMS && pCMS->eState == MV_TBLSEL )
    1332             :     {
    1333           0 :         const SwTabFrm *pTab = pActual->FindTabFrm();
    1334           0 :         if ( pTab->IsFollow() && pTab->IsInHeadline( *pActual ) )
    1335             :         {
    1336           0 :             ((SwCrsrMoveState*)pCMS)->bStop = sal_True;
    1337           0 :             return 0;
    1338             :         }
    1339             :     }
    1340             : 
    1341             :     //A small correction at the first/last
    1342         163 :     Size aActualSize( pActual->Prt().SSize() );
    1343         163 :     if ( aActualSize.Height() > pActual->GetUpper()->Prt().Height() )
    1344           0 :         aActualSize.Height() = pActual->GetUpper()->Prt().Height();
    1345             : 
    1346         163 :     SWRECTFN( pActual )
    1347         318 :     if ( !pActual->GetPrev() &&
    1348         310 :          (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtTop)(),
    1349         465 :                               bVert ? rPoint.X() : rPoint.Y() ) > 0 )
    1350             :     {
    1351           3 :         aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Top();
    1352           9 :         aPoint.X() = pActual->Frm().Left() +
    1353           6 :                         ( pActual->IsRightToLeft() || bVert ?
    1354           0 :                           pActual->Prt().Right() :
    1355           6 :                           pActual->Prt().Left() );
    1356             :     }
    1357         316 :     else if ( !pActual->GetNext() &&
    1358         312 :               (*fnRect->fnYDiff)( (pActual->*fnRect->fnGetPrtBottom)(),
    1359         468 :                                    bVert ? rPoint.X() : rPoint.Y() ) < 0 )
    1360             :     {
    1361         154 :         aPoint.Y() = pActual->Frm().Top() + pActual->Prt().Bottom();
    1362         462 :         aPoint.X() = pActual->Frm().Left() +
    1363         308 :                         ( pActual->IsRightToLeft() || bVert ?
    1364           0 :                           pActual->Prt().Left() :
    1365         308 :                           pActual->Prt().Right() );
    1366             :     }
    1367             : 
    1368             :     //Bring the Point in to the PrtArea
    1369         163 :     if ( bCalc )
    1370           0 :         pActual->Calc();
    1371         326 :     const SwRect aRect( pActual->Frm().Pos() + pActual->Prt().Pos(),
    1372         163 :                         aActualSize );
    1373         163 :     if ( aPoint.Y() < aRect.Top() )
    1374           0 :         aPoint.Y() = aRect.Top();
    1375         163 :     else if ( aPoint.Y() > aRect.Bottom() )
    1376           0 :         aPoint.Y() = aRect.Bottom();
    1377         163 :     if ( aPoint.X() < aRect.Left() )
    1378           0 :         aPoint.X() = aRect.Left();
    1379         163 :     else if ( aPoint.X() > aRect.Right() )
    1380           0 :         aPoint.X() = aRect.Right();
    1381         163 :     rPoint = aPoint;
    1382         163 :     return pActual;
    1383             : }
    1384             : 
    1385             : /** Same as SwLayoutFrm::GetCntntPos(). Specialized for fields and border. */
    1386           0 : void SwPageFrm::GetCntntPosition( const Point &rPt, SwPosition &rPos ) const
    1387             : {
    1388             :     //Determine the first CntntFrm.
    1389           0 :     const SwCntntFrm *pCntnt = ContainsCntnt();
    1390           0 :     if ( pCntnt )
    1391             :     {
    1392             :         //Look back one more (if possible).
    1393           0 :         const SwCntntFrm *pTmp = pCntnt->GetPrevCntntFrm();
    1394           0 :         while ( pTmp && !pTmp->IsInDocBody() )
    1395           0 :             pTmp = pTmp->GetPrevCntntFrm();
    1396           0 :         if ( pTmp )
    1397           0 :             pCntnt = pTmp;
    1398             :     }
    1399             :     else
    1400           0 :         pCntnt = GetUpper()->ContainsCntnt();
    1401             : 
    1402           0 :     const SwCntntFrm *pAct = pCntnt;
    1403           0 :     Point aAct       = rPt;
    1404           0 :     sal_uInt64 nDist = SAL_MAX_UINT64;
    1405             : 
    1406           0 :     while ( pCntnt )
    1407             :     {
    1408           0 :         SwRect aCntFrm( pCntnt->UnionFrm() );
    1409           0 :         if ( aCntFrm.IsInside( rPt ) )
    1410             :         {
    1411             :             //This is the nearest one.
    1412           0 :             pAct = pCntnt;
    1413           0 :             break;
    1414             :         }
    1415             : 
    1416             :         //Calculate the distance from rPt to the nearest point of pCntnt.
    1417           0 :         Point aPoint( rPt );
    1418             : 
    1419             :         //Calculate the vertical position first
    1420           0 :         if ( aCntFrm.Top() > rPt.Y() )
    1421           0 :             aPoint.Y() = aCntFrm.Top();
    1422           0 :         else if ( aCntFrm.Bottom() < rPt.Y() )
    1423           0 :             aPoint.Y() = aCntFrm.Bottom();
    1424             : 
    1425             :         //And now the horizontal position
    1426           0 :         if ( aCntFrm.Left() > rPt.X() )
    1427           0 :             aPoint.X() = aCntFrm.Left();
    1428           0 :         else if ( aCntFrm.Right() < rPt.X() )
    1429           0 :             aPoint.X() = aCntFrm.Right();
    1430             : 
    1431           0 :         const sal_uInt64 nDiff = ::CalcDiff( aPoint, rPt );
    1432           0 :         if ( nDiff < nDist )
    1433             :         {
    1434           0 :             aAct    = aPoint;
    1435           0 :             nDist   = nDiff;
    1436           0 :             pAct    = pCntnt;
    1437             :         }
    1438           0 :         else if ( aCntFrm.Top() > Frm().Bottom() )
    1439             :             //In terms of fields, it's not possible to be closer any more!
    1440           0 :             break;
    1441             : 
    1442           0 :         pCntnt = pCntnt->GetNextCntntFrm();
    1443           0 :         while ( pCntnt && !pCntnt->IsInDocBody() )
    1444           0 :             pCntnt = pCntnt->GetNextCntntFrm();
    1445             :     }
    1446             : 
    1447             :     //Bring the point into the PrtArea.
    1448           0 :     const SwRect aRect( pAct->Frm().Pos() + pAct->Prt().Pos(), pAct->Prt().SSize() );
    1449           0 :     if ( aAct.Y() < aRect.Top() )
    1450           0 :         aAct.Y() = aRect.Top();
    1451           0 :     else if ( aAct.Y() > aRect.Bottom() )
    1452           0 :         aAct.Y() = aRect.Bottom();
    1453           0 :     if ( aAct.X() < aRect.Left() )
    1454           0 :         aAct.X() = aRect.Left();
    1455           0 :     else if ( aAct.X() > aRect.Right() )
    1456           0 :         aAct.X() = aRect.Right();
    1457             : 
    1458           0 :     if( !pAct->IsValid() )
    1459             :     {
    1460             :         // CntntFrm not formated -> always on node-beginning
    1461           0 :         SwCntntNode* pCNd = (SwCntntNode*)pAct->GetNode();
    1462             :         OSL_ENSURE( pCNd, "Where is my CntntNode?" );
    1463           0 :         rPos.nNode = *pCNd;
    1464           0 :         rPos.nContent.Assign( pCNd, 0 );
    1465             :     }
    1466             :     else
    1467             :     {
    1468           0 :         SwCrsrMoveState aTmpState( MV_SETONLYTEXT );
    1469           0 :         pAct->GetCrsrOfst( &rPos, aAct, &aTmpState );
    1470             :     }
    1471           0 : }
    1472             : 
    1473             : // #123110# - helper class to disable creation of an action
    1474             : // by a callback event - e.g., change event from a drawing object
    1475             : class DisableCallbackAction
    1476             : {
    1477             :     private:
    1478             :         SwRootFrm& mrRootFrm;
    1479             :         sal_Bool mbOldCallbackActionState;
    1480             : 
    1481             :     public:
    1482           0 :         DisableCallbackAction( const SwRootFrm& _rRootFrm ) :
    1483             :             mrRootFrm( const_cast<SwRootFrm&>(_rRootFrm) ),
    1484           0 :             mbOldCallbackActionState( _rRootFrm.IsCallbackActionEnabled() )
    1485             :         {
    1486           0 :             mrRootFrm.SetCallbackActionEnabled( sal_False );
    1487           0 :         }
    1488             : 
    1489           0 :         ~DisableCallbackAction()
    1490             :         {
    1491           0 :             mrRootFrm.SetCallbackActionEnabled( mbOldCallbackActionState );
    1492           0 :         }
    1493             : };
    1494             : 
    1495             : /** Search the nearest Cntnt to the passed point.
    1496             :  *
    1497             :  * Only search inside the BodyText.
    1498             :  * @note Only the nearest vertically one will be searched.
    1499             :  * @note JP 11.10.2001: only in tables we try to find the right column - Bug 72294
    1500             :  */
    1501           0 : Point SwRootFrm::GetNextPrevCntntPos( const Point& rPoint, sal_Bool bNext ) const
    1502             : {
    1503             :     // #123110# - disable creation of an action by a callback
    1504             :     // event during processing of this method. Needed because formatting is
    1505             :     // triggered by this method.
    1506           0 :     DisableCallbackAction aDisableCallbackAction( *this );
    1507             :     //Search the first CntntFrm and his successor in the body area.
    1508             :     //To be efficient (and not formatting too much) we'll start at the correct
    1509             :     //page.
    1510           0 :     SwLayoutFrm *pPage = (SwLayoutFrm*)Lower();
    1511           0 :     if( pPage )
    1512           0 :         while( pPage->GetNext() && pPage->Frm().Bottom() < rPoint.Y() )
    1513           0 :             pPage = (SwLayoutFrm*)pPage->GetNext();
    1514             : 
    1515           0 :     const SwCntntFrm *pCnt = pPage ? pPage->ContainsCntnt() : ContainsCntnt();
    1516           0 :     while ( pCnt && !pCnt->IsInDocBody() )
    1517           0 :         pCnt = pCnt->GetNextCntntFrm();
    1518             : 
    1519           0 :     if ( !pCnt )
    1520           0 :         return Point( 0, 0 );
    1521             : 
    1522           0 :     pCnt->Calc();
    1523           0 :     if( !bNext )
    1524             :     {
    1525             :         // As long as the point lies before the first CntntFrm and there are
    1526             :         // still precedent pages I'll go to the next page.
    1527           0 :         while ( rPoint.Y() < pCnt->Frm().Top() && pPage->GetPrev() )
    1528             :         {
    1529           0 :             pPage = (SwLayoutFrm*)pPage->GetPrev();
    1530           0 :             pCnt = pPage->ContainsCntnt();
    1531           0 :             while ( !pCnt )
    1532             :             {
    1533           0 :                 pPage = (SwLayoutFrm*)pPage->GetPrev();
    1534           0 :                 if ( pPage )
    1535           0 :                     pCnt = pPage->ContainsCntnt();
    1536             :                 else
    1537           0 :                     return ContainsCntnt()->UnionFrm().Pos();
    1538             :             }
    1539           0 :             pCnt->Calc();
    1540             :         }
    1541             :     }
    1542             : 
    1543             :     //Does the point lie above the first CntntFrm?
    1544           0 :     if ( rPoint.Y() < pCnt->Frm().Top() && !lcl_IsInRepeatedHeadline( pCnt ) )
    1545           0 :         return pCnt->UnionFrm().Pos();
    1546             : 
    1547           0 :     while ( pCnt )
    1548             :     {
    1549             :         //Does the point lie in the current CntntFrm?
    1550           0 :         SwRect aCntFrm( pCnt->UnionFrm() );
    1551           0 :         if ( aCntFrm.IsInside( rPoint ) && !lcl_IsInRepeatedHeadline( pCnt ))
    1552           0 :             return rPoint;
    1553             : 
    1554             :         //Is the current one the last CntntFrm?
    1555             :         //If the next CntntFrm lies behind the point, then the current on is the
    1556             :         //one we searched.
    1557           0 :         const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
    1558           0 :         while ( pNxt && !pNxt->IsInDocBody() )
    1559           0 :             pNxt = pNxt->GetNextCntntFrm();
    1560             : 
    1561             :         //Does the point lie behind the last CntntFrm?
    1562           0 :         if ( !pNxt )
    1563           0 :             return Point( aCntFrm.Right(), aCntFrm.Bottom() );
    1564             : 
    1565             :         //If the next CntntFrm lies behind the point then it is the one we
    1566             :         //searched.
    1567             :         const SwTabFrm* pTFrm;
    1568           0 :         pNxt->Calc();
    1569           0 :         if( pNxt->Frm().Top() > rPoint.Y() &&
    1570           0 :             !lcl_IsInRepeatedHeadline( pCnt, &pTFrm ) &&
    1571           0 :             ( !pTFrm || pNxt->Frm().Left() > rPoint.X() ))
    1572             :         {
    1573           0 :             if( bNext )
    1574           0 :                 return pNxt->Frm().Pos();
    1575           0 :             return Point( aCntFrm.Right(), aCntFrm.Bottom() );
    1576             :         }
    1577           0 :         pCnt = pNxt;
    1578             :     }
    1579           0 :     return Point( 0, 0 );
    1580             : }
    1581             : 
    1582             : /** Returns the absolute document position of the desired page.
    1583             :  *
    1584             :  * Formatting is done only as far as needed and only if bFormat=sal_True.
    1585             :  * Pos is set to the one of the last page, if the page number was chosen to big.
    1586             :  *
    1587             :  * @return Null, if the operation failed.
    1588             :  */
    1589           0 : Point SwRootFrm::GetPagePos( sal_uInt16 nPageNum ) const
    1590             : {
    1591             :     OSL_ENSURE( Lower() && Lower()->IsPageFrm(), "No page available." );
    1592             : 
    1593           0 :     const SwPageFrm *pPage = (const SwPageFrm*)Lower();
    1594             :     while ( true )
    1595             :     {
    1596           0 :         if ( pPage->GetPhyPageNum() >= nPageNum || !pPage->GetNext() )
    1597           0 :             break;
    1598           0 :         pPage = (const SwPageFrm*)pPage->GetNext();
    1599             :     }
    1600           0 :     return pPage->Frm().Pos();
    1601             : }
    1602             : 
    1603             : /** get page frame by phyiscal page number
    1604             :  *
    1605             :  * @return pointer to the page frame with the given physical page number
    1606             :  */
    1607           0 : SwPageFrm* SwRootFrm::GetPageByPageNum( sal_uInt16 _nPageNum ) const
    1608             : {
    1609           0 :     const SwPageFrm* pPageFrm = static_cast<const SwPageFrm*>( Lower() );
    1610           0 :     while ( pPageFrm && pPageFrm->GetPhyPageNum() < _nPageNum )
    1611             :     {
    1612           0 :           pPageFrm = static_cast<const SwPageFrm*>( pPageFrm->GetNext() );
    1613             :     }
    1614             : 
    1615           0 :     if ( pPageFrm && pPageFrm->GetPhyPageNum() == _nPageNum )
    1616             :     {
    1617           0 :         return const_cast<SwPageFrm*>( pPageFrm );
    1618             :     }
    1619             :     else
    1620             :     {
    1621           0 :         return 0;
    1622             :     }
    1623             : }
    1624             : 
    1625             : /**
    1626             :  * @return sal_True, when the given physical pagenumber does't exist or this page is an empty page.
    1627             :  */
    1628           0 : sal_Bool SwRootFrm::IsDummyPage( sal_uInt16 nPageNum ) const
    1629             : {
    1630           0 :     if( !Lower() || !nPageNum || nPageNum > GetPageNum() )
    1631           0 :         return sal_True;
    1632             : 
    1633           0 :     const SwPageFrm *pPage = (const SwPageFrm*)Lower();
    1634           0 :     while( pPage && nPageNum < pPage->GetPhyPageNum() )
    1635           0 :         pPage = (const SwPageFrm*)pPage->GetNext();
    1636           0 :     return pPage ? pPage->IsEmptyPage() : sal_True;
    1637             : }
    1638             : 
    1639             : /** Is the Frm or rather the Section in which it lies protected?
    1640             :  *
    1641             :  * Also Fly in Fly in ... and Footnotes
    1642             :  */
    1643       15136 : sal_Bool SwFrm::IsProtected() const
    1644             : {
    1645       15136 :     if (this->IsCntntFrm() && ((SwCntntFrm*)this)->GetNode())
    1646             :     {
    1647       15117 :         const SwDoc *pDoc=((SwCntntFrm*)this)->GetNode()->GetDoc();
    1648       15117 :         bool isFormProtected=pDoc->get(IDocumentSettingAccess::PROTECT_FORM );
    1649       15117 :         if (isFormProtected)
    1650             :         {
    1651           2 :             return sal_False; // TODO a hack for now, well deal with it later, I we return true here we have a "double" locking
    1652             :         }
    1653             :     }
    1654             :     //The Frm can be protected in borders, cells or sections.
    1655             :     //Also goes up FlyFrms recursive and from footnote to anchor.
    1656       15134 :     const SwFrm *pFrm = this;
    1657       62343 :     do
    1658             :     {
    1659       62343 :         if ( pFrm->IsCntntFrm() )
    1660             :         {
    1661       30282 :             if ( ((SwCntntFrm*)pFrm)->GetNode() &&
    1662       15141 :                  ((SwCntntFrm*)pFrm)->GetNode()->IsInProtectSect() )
    1663           0 :                 return sal_True;
    1664             :         }
    1665             :         else
    1666             :         {
    1667       94404 :             if ( ((SwLayoutFrm*)pFrm)->GetFmt() &&
    1668       47202 :                  ((SwLayoutFrm*)pFrm)->GetFmt()->
    1669       47202 :                  GetProtect().IsCntntProtected() )
    1670           0 :                 return sal_True;
    1671       47202 :             if ( pFrm->IsCoveredCell() )
    1672           0 :                 return sal_True;
    1673             :         }
    1674       62343 :         if ( pFrm->IsFlyFrm() )
    1675             :         {
    1676             :             //In a chain the protection of the content can be specified by the
    1677             :             //master of the chain.
    1678          19 :             if ( ((SwFlyFrm*)pFrm)->GetPrevLink() )
    1679             :             {
    1680           0 :                 SwFlyFrm *pMaster = (SwFlyFrm*)pFrm;
    1681           0 :                 do
    1682           0 :                 {   pMaster = pMaster->GetPrevLink();
    1683           0 :                 } while ( pMaster->GetPrevLink() );
    1684           0 :                 if ( pMaster->IsProtected() )
    1685           0 :                     return sal_True;
    1686             :             }
    1687          19 :             pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
    1688             :         }
    1689       62324 :         else if ( pFrm->IsFtnFrm() )
    1690          13 :             pFrm = ((SwFtnFrm*)pFrm)->GetRef();
    1691             :         else
    1692       62311 :             pFrm = pFrm->GetUpper();
    1693             : 
    1694             :     } while ( pFrm );
    1695             : 
    1696       15134 :     return sal_False;
    1697             : }
    1698             : 
    1699             : /** @return the physical page number */
    1700        7477 : sal_uInt16 SwFrm::GetPhyPageNum() const
    1701             : {
    1702        7477 :     const SwPageFrm *pPage = FindPageFrm();
    1703        7477 :     return pPage ? pPage->GetPhyPageNum() : 0;
    1704             : }
    1705             : 
    1706             : /** Decides if the page want to be a rightpage or not.
    1707             :  *
    1708             :  * If the first content of the page has a page descriptor, we take the follow
    1709             :  * of the page descriptor of the last not empty page. If this descriptor allows
    1710             :  * only right(left) pages and the page isn't an empty page then it wanna be
    1711             :  * such right(left) page. If the descriptor allows right and left pages, we
    1712             :  * look for a number offset in the first content. If there is one, odd number
    1713             :  * results right pages, even number results left pages.
    1714             :  * If there is no number offset, we take the physical page number instead,
    1715             :  * but a previous empty page don't count.
    1716             :  */
    1717         911 : sal_Bool SwFrm::WannaRightPage() const
    1718             : {
    1719         911 :     const SwPageFrm *pPage = FindPageFrm();
    1720         911 :     if ( !pPage || !pPage->GetUpper() )
    1721           0 :         return sal_True;
    1722             : 
    1723         911 :     const SwFrm *pFlow = pPage->FindFirstBodyCntnt();
    1724         911 :     const SwPageDesc *pDesc = 0;
    1725         911 :     ::boost::optional<sal_uInt16> oPgNum;
    1726         911 :     if ( pFlow )
    1727             :     {
    1728         763 :         if ( pFlow->IsInTab() )
    1729          59 :             pFlow = pFlow->FindTabFrm();
    1730         763 :         const SwFlowFrm *pTmp = SwFlowFrm::CastFlowFrm( pFlow );
    1731         763 :         if ( !pTmp->IsFollow() )
    1732             :         {
    1733         693 :             const SwFmtPageDesc& rPgDesc = pFlow->GetAttrSet()->GetPageDesc();
    1734         693 :             pDesc = rPgDesc.GetPageDesc();
    1735         693 :             oPgNum = rPgDesc.GetNumOffset();
    1736             :         }
    1737             :     }
    1738         911 :     if ( !pDesc )
    1739             :     {
    1740         827 :         SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
    1741         827 :         if( pPrv && pPrv->IsEmptyPage() )
    1742           0 :             pPrv = (SwPageFrm*)pPrv->GetPrev();
    1743         827 :         if( pPrv )
    1744         677 :             pDesc = pPrv->GetPageDesc()->GetFollow();
    1745             :         else
    1746             :         {
    1747         150 :             const SwDoc* pDoc = pPage->GetFmt()->GetDoc();
    1748         150 :             pDesc = &pDoc->GetPageDesc( 0 );
    1749             :         }
    1750             :     }
    1751             :     OSL_ENSURE( pDesc, "No pagedescriptor" );
    1752             :     sal_Bool bOdd;
    1753         911 :     if( oPgNum )
    1754           4 :         bOdd = (oPgNum.get() % 2) ? sal_True : sal_False;
    1755             :     else
    1756             :     {
    1757         907 :         bOdd = pPage->OnRightPage();
    1758         907 :         if( pPage->GetPrev() && ((SwPageFrm*)pPage->GetPrev())->IsEmptyPage() )
    1759           4 :             bOdd = !bOdd;
    1760             :     }
    1761         911 :     if( !pPage->IsEmptyPage() )
    1762             :     {
    1763         907 :         if( !pDesc->GetRightFmt() )
    1764           4 :             bOdd = sal_False;
    1765         903 :         else if( !pDesc->GetLeftFmt() )
    1766           5 :             bOdd = sal_True;
    1767             :     }
    1768         911 :     return bOdd;
    1769             : }
    1770             : 
    1771        1667 : bool SwFrm::OnFirstPage() const
    1772             : {
    1773        1667 :     bool bRet = false;
    1774        1667 :     const SwPageFrm *pPage = FindPageFrm();
    1775             : 
    1776        1667 :     if (pPage)
    1777             :     {
    1778        1667 :         const SwPageFrm* pPrevFrm = dynamic_cast<const SwPageFrm*>(pPage->GetPrev());
    1779        1667 :         if (pPrevFrm)
    1780             :         {
    1781        1445 :             const SwPageDesc* pDesc = pPage->GetPageDesc();
    1782        1445 :             bRet = pPrevFrm->GetPageDesc() != pDesc;
    1783             :         }
    1784             :         else
    1785         222 :             bRet = true;
    1786             :     }
    1787        1667 :     return bRet;
    1788             : }
    1789             : 
    1790             : /** @return the virtual page number with the offset. */
    1791        1916 : sal_uInt16 SwFrm::GetVirtPageNum() const
    1792             : {
    1793        1916 :     const SwPageFrm *pPage = FindPageFrm();
    1794        1916 :     if ( !pPage || !pPage->GetUpper() )
    1795           0 :         return 0;
    1796             : 
    1797        1916 :     sal_uInt16 nPhyPage = pPage->GetPhyPageNum();
    1798        1916 :     if ( !(static_cast<const SwRootFrm*>(pPage->GetUpper()))->IsVirtPageNum() )
    1799        1762 :         return nPhyPage;
    1800             : 
    1801             :     //Search the nearest section using the virtual page number.
    1802             :     //Because searching backwards needs a lot of time we search specific using
    1803             :     //the dependencies. From the PageDescs we get the attributes and from the
    1804             :     //attributes we get the sections.
    1805         154 :     const SwPageFrm *pVirtPage = 0;
    1806         154 :     const SwFrm *pFrm = 0;
    1807         154 :     const SfxItemPool &rPool = pPage->GetFmt()->GetDoc()->GetAttrPool();
    1808             :     const SfxPoolItem* pItem;
    1809         154 :     sal_uInt32 nMaxItems = rPool.GetItemCount2( RES_PAGEDESC );
    1810        1141 :     for( sal_uInt32 n = 0; n < nMaxItems; ++n )
    1811             :     {
    1812         987 :         if( 0 == (pItem = rPool.GetItem2( RES_PAGEDESC, n ) ))
    1813         462 :             continue;
    1814             : 
    1815         525 :         const SwFmtPageDesc *pDesc = (SwFmtPageDesc*)pItem;
    1816         525 :         if ( pDesc->GetNumOffset() && pDesc->GetDefinedIn() )
    1817             :         {
    1818         217 :             const SwModify *pMod = pDesc->GetDefinedIn();
    1819         217 :             SwVirtPageNumInfo aInfo( pPage );
    1820         217 :             pMod->GetInfo( aInfo );
    1821         217 :             if ( aInfo.GetPage() )
    1822             :             {
    1823         120 :                 if( !pVirtPage || ( pVirtPage && aInfo.GetPage()->
    1824           0 :                     GetPhyPageNum() > pVirtPage->GetPhyPageNum() ) )
    1825             :                 {
    1826         120 :                     pVirtPage = aInfo.GetPage();
    1827         120 :                     pFrm = aInfo.GetFrm();
    1828             :                 }
    1829         217 :             }
    1830             :         }
    1831             :     }
    1832         154 :     if ( pFrm )
    1833             :     {
    1834         120 :         ::boost::optional<sal_uInt16> oNumOffset = pFrm->GetAttrSet()->GetPageDesc().GetNumOffset();
    1835         120 :         if (oNumOffset)
    1836             :         {
    1837         120 :             return nPhyPage - pFrm->GetPhyPageNum() + oNumOffset.get();
    1838             :         }
    1839             :         else
    1840             :         {
    1841           0 :             return nPhyPage - pFrm->GetPhyPageNum();
    1842         120 :         }
    1843             :     }
    1844          34 :     return nPhyPage;
    1845             : }
    1846             : 
    1847             : /** Determines and sets those cells which are enclosed by the selection. */
    1848         413 : bool SwRootFrm::MakeTblCrsrs( SwTableCursor& rTblCrsr )
    1849             : {
    1850             :     //Find Union-Rects and tables (Follows) of the selection.
    1851             :     OSL_ENSURE( rTblCrsr.GetCntntNode() && rTblCrsr.GetCntntNode( false ),
    1852             :             "Tabselection nicht auf Cnt." );
    1853             : 
    1854         413 :     bool bRet = false;
    1855             : 
    1856             :     // For new table models there's no need to ask the layout..
    1857         413 :     if( rTblCrsr.NewTableSelection() )
    1858         413 :         return true;
    1859             : 
    1860           0 :     Point aPtPt, aMkPt;
    1861             :     {
    1862           0 :         SwShellCrsr* pShCrsr = dynamic_cast<SwShellCrsr*>(&rTblCrsr);
    1863             : 
    1864           0 :         if( pShCrsr )
    1865             :         {
    1866           0 :             aPtPt = pShCrsr->GetPtPos();
    1867           0 :             aMkPt = pShCrsr->GetMkPos();
    1868             :         }
    1869             :     }
    1870             : 
    1871             :     // #151012# Made code robust here
    1872           0 :     const SwCntntNode* pTmpStartNode = rTblCrsr.GetCntntNode();
    1873           0 :     const SwCntntNode* pTmpEndNode   = rTblCrsr.GetCntntNode(false);
    1874             : 
    1875           0 :     const SwFrm* pTmpStartFrm = pTmpStartNode ? pTmpStartNode->getLayoutFrm( this, &aPtPt, 0, false ) : 0;
    1876           0 :     const SwFrm* pTmpEndFrm   = pTmpEndNode   ?   pTmpEndNode->getLayoutFrm( this, &aMkPt, 0, false ) : 0;
    1877             : 
    1878           0 :     const SwLayoutFrm* pStart = pTmpStartFrm ? pTmpStartFrm->GetUpper() : 0;
    1879           0 :     const SwLayoutFrm* pEnd   = pTmpEndFrm   ? pTmpEndFrm->GetUpper() : 0;
    1880             : 
    1881             :     OSL_ENSURE( pStart && pEnd, "MakeTblCrsrs: Good to have the code robust here!" );
    1882             : 
    1883             :     /* #109590# Only change table boxes if the frames are
    1884             :         valid. Needed because otherwise the table cursor after moving
    1885             :         table cells by dnd resulted in an empty tables cursor.  */
    1886           0 :     if ( pStart && pEnd && pStart->IsValid() && pEnd->IsValid())
    1887             :     {
    1888           0 :         SwSelUnions aUnions;
    1889           0 :         ::MakeSelUnions( aUnions, pStart, pEnd );
    1890             : 
    1891           0 :         SwSelBoxes aNew;
    1892             : 
    1893           0 :         const sal_Bool bReadOnlyAvailable = rTblCrsr.IsReadOnlyAvailable();
    1894             : 
    1895           0 :         for ( sal_uInt16 i = 0; i < aUnions.size(); ++i )
    1896             :         {
    1897           0 :             SwSelUnion *pUnion = &aUnions[i];
    1898           0 :             const SwTabFrm *pTable = pUnion->GetTable();
    1899             : 
    1900             :             // Skip any repeated headlines in the follow:
    1901           0 :             SwLayoutFrm* pRow = pTable->IsFollow() ?
    1902             :                                 pTable->GetFirstNonHeadlineRow() :
    1903           0 :                                 (SwLayoutFrm*)pTable->Lower();
    1904             : 
    1905           0 :             while ( pRow )
    1906             :             {
    1907           0 :                 if ( pRow->Frm().IsOver( pUnion->GetUnion() ) )
    1908             :                 {
    1909           0 :                     const SwLayoutFrm *pCell = pRow->FirstCell();
    1910             : 
    1911           0 :                     while ( pCell && pRow->IsAnLower( pCell ) )
    1912             :                     {
    1913             :                         OSL_ENSURE( pCell->IsCellFrm(), "Frame without cell" );
    1914           0 :                         if( IsFrmInTblSel( pUnion->GetUnion(), pCell ) &&
    1915           0 :                             (bReadOnlyAvailable ||
    1916           0 :                              !pCell->GetFmt()->GetProtect().IsCntntProtected()))
    1917             :                         {
    1918             :                             SwTableBox* pInsBox = (SwTableBox*)
    1919           0 :                                 ((SwCellFrm*)pCell)->GetTabBox();
    1920           0 :                             aNew.insert( pInsBox );
    1921             :                         }
    1922           0 :                         if ( pCell->GetNext() )
    1923             :                         {
    1924           0 :                             pCell = (const SwLayoutFrm*)pCell->GetNext();
    1925           0 :                             if ( pCell->Lower() && pCell->Lower()->IsRowFrm() )
    1926           0 :                                 pCell = pCell->FirstCell();
    1927             :                         }
    1928             :                         else
    1929             :                         {
    1930           0 :                             const SwLayoutFrm* pLastCell = pCell;
    1931           0 :                             do
    1932             :                             {
    1933           0 :                                 pCell = pCell->GetNextLayoutLeaf();
    1934           0 :                             } while ( pCell && pLastCell->IsAnLower( pCell ) );
    1935             :                             // For sections with columns
    1936           0 :                             if( pCell && pCell->IsInTab() )
    1937             :                             {
    1938           0 :                                 while( !pCell->IsCellFrm() )
    1939             :                                 {
    1940           0 :                                     pCell = pCell->GetUpper();
    1941             :                                     OSL_ENSURE( pCell, "Where's my cell?" );
    1942             :                                 }
    1943             :                             }
    1944             :                         }
    1945             :                     }
    1946             :                 }
    1947           0 :                 pRow = (SwLayoutFrm*)pRow->GetNext();
    1948             :             }
    1949             :         }
    1950             : 
    1951           0 :         rTblCrsr.ActualizeSelection( aNew );
    1952           0 :         bRet = true;
    1953             :     }
    1954             : 
    1955           0 :     return bRet;
    1956             : }
    1957             : 
    1958         900 : inline void Sub( SwRegionRects& rRegion, const SwRect& rRect )
    1959             : {
    1960        1726 :     if( rRect.Width() > 1 && rRect.Height() > 1 &&
    1961         826 :         rRect.IsOver( rRegion.GetOrigin() ))
    1962         810 :         rRegion -= rRect;
    1963         900 : }
    1964             : 
    1965             : /*
    1966             :  * The following situations can happen:
    1967             :  *  1. Start and end lie in one screen-row and in the same node
    1968             :  *     -> one rectangle out of start and end; and we're okay
    1969             :  *  2. Start and end lie in one frame (therefore in the same node!)
    1970             :  *     -> expand start to the right, end to the left and if more than two
    1971             :  *        screen-rows are involved - calculate the in-between
    1972             :  *  3. Start and end lie in different frames
    1973             :  *     -> expand start to the right until frame-end, calculate Rect
    1974             :  *        expand end to the left until frame-start, calculate Rect
    1975             :  *        and if more than two frames are involved add the PrtArea of all
    1976             :  *        frames which lie in between
    1977             :  *  4. If it's about a table-selection we have to obtain the CellFrm for every
    1978             :  *     PaM in the ring - its PrtArea will be added to the Rect.
    1979             :  *
    1980             :  * Big reorganization because of the FlyFrm - those need to be locked out.
    1981             :  * Exceptions:  - The Fly in which the selection took place (if it took place
    1982             :  *                 in a Fly)
    1983             :  *              - The Flys which are underrun by the text
    1984             :  * Functioning: First a SwRegion with a root gets initialized.
    1985             :  *              Out of the region the inverted sections are cut out. The
    1986             :  *              section gets compressed and finally inverted and thereby the
    1987             :  *              inverted rectangles are available.
    1988             :  *              In the end the Flys are cut out of the section.
    1989             :  */
    1990         554 : void SwRootFrm::CalcFrmRects(
    1991             :     SwShellCrsr &rCrsr,
    1992             :     const sal_Bool bIsTblMode)
    1993             : {
    1994         554 :     SwPosition *pStartPos = rCrsr.Start(),
    1995         554 :                *pEndPos   = rCrsr.GetPoint() == pStartPos ? rCrsr.GetMark() : rCrsr.GetPoint();
    1996             : 
    1997         554 :     SwViewShell *pSh = GetCurrShell();
    1998             : 
    1999             :     // #i12836# enhanced pdf
    2000         554 :     SwRegionRects aRegion( pSh && !pSh->GetViewOptions()->IsPDFExport() ?
    2001             :                            pSh->VisArea() :
    2002        1108 :                            Frm() );
    2003        1662 :     if( !pStartPos->nNode.GetNode().IsCntntNode() ||
    2004        1108 :         !pStartPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ||
    2005         643 :         ( pStartPos->nNode != pEndPos->nNode &&
    2006         178 :           ( !pEndPos->nNode.GetNode().IsCntntNode() ||
    2007          89 :             !pEndPos->nNode.GetNode().GetCntntNode()->getLayoutFrm(this) ) ) )
    2008             :     {
    2009         554 :         return;
    2010             :     }
    2011             : 
    2012             :     //First obtain the CntntFrms for the start and the end - those are needed
    2013             :     //anyway.
    2014         554 :     SwCntntFrm const* pStartFrm = pStartPos->nNode.GetNode().
    2015        1108 :         GetCntntNode()->getLayoutFrm( this, &rCrsr.GetSttPos(), pStartPos );
    2016             : 
    2017         554 :     SwCntntFrm const* pEndFrm   = pEndPos->nNode.GetNode().
    2018        1108 :         GetCntntNode()->getLayoutFrm( this, &rCrsr.GetEndPos(), pEndPos );
    2019             : 
    2020             :     OSL_ENSURE( (pStartFrm && pEndFrm), "Keine CntntFrms gefunden." );
    2021             : 
    2022             :     //Do not subtract the FlyFrms in which selected Frames lie.
    2023        1108 :     SwSortedObjs aSortObjs;
    2024         554 :     if ( pStartFrm->IsInFly() )
    2025             :     {
    2026           0 :         const SwAnchoredObject* pObj = pStartFrm->FindFlyFrm();
    2027             :         OSL_ENSURE( pObj, "No Start Object." );
    2028           0 :         if (pObj) aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
    2029           0 :         const SwAnchoredObject* pObj2 = pEndFrm->FindFlyFrm();
    2030             :         OSL_ENSURE( pObj2, "SwRootFrm::CalcFrmRects(..) - FlyFrame missing - looks like an invalid selection" );
    2031           0 :         if ( pObj2 != NULL && pObj2 != pObj )
    2032             :         {
    2033           0 :             aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj2)) );
    2034             :         }
    2035             :     }
    2036             : 
    2037             :     //Case 4: Table selection
    2038         554 :     if( bIsTblMode )
    2039             :     {
    2040           0 :         const SwFrm *pCell = pStartFrm->GetUpper();
    2041           0 :         while ( !pCell->IsCellFrm() )
    2042           0 :             pCell = pCell->GetUpper();
    2043           0 :         SwRect aTmp( pCell->Prt() );
    2044           0 :         aTmp.Pos() += pCell->Frm().Pos();
    2045           0 :         aRegion.ChangeOrigin( aTmp );
    2046           0 :         aRegion.clear();
    2047           0 :         aRegion.push_back( aTmp);
    2048             :     }
    2049             :     else
    2050             :     {
    2051             :         // if a selection which is not allowed exists, we correct what is not
    2052             :         // allowed (header/footer/table-headline) for two pages.
    2053             :         do {    // middle check loop
    2054         554 :             const SwLayoutFrm* pSttLFrm = pStartFrm->GetUpper();
    2055         554 :             const sal_uInt16 cHdFtTblHd = FRM_HEADER | FRM_FOOTER | FRM_TAB;
    2056        4409 :             while( pSttLFrm &&
    2057        1662 :                 ! (cHdFtTblHd & pSttLFrm->GetType() ))
    2058        1639 :                 pSttLFrm = pSttLFrm->GetUpper();
    2059         554 :             if( !pSttLFrm )
    2060         531 :                 break;
    2061          23 :             const SwLayoutFrm* pEndLFrm = pEndFrm->GetUpper();
    2062         183 :             while( pEndLFrm &&
    2063          69 :                 ! (cHdFtTblHd & pEndLFrm->GetType() ))
    2064          68 :                 pEndLFrm = pEndLFrm->GetUpper();
    2065          23 :             if( !pEndLFrm )
    2066          22 :                 break;
    2067             : 
    2068             :             OSL_ENSURE( pEndLFrm->GetType() == pSttLFrm->GetType(),
    2069             :                 "Selection over different content" );
    2070           1 :             switch( pSttLFrm->GetType() )
    2071             :             {
    2072             :             case FRM_HEADER:
    2073             :             case FRM_FOOTER:
    2074             :                 // On different pages? Then always on the start-page
    2075           0 :                 if( pEndLFrm->FindPageFrm() != pSttLFrm->FindPageFrm() )
    2076             :                 {
    2077             :                     // Set end- to the start-CntntFrame
    2078           0 :                     if( pStartPos == rCrsr.GetPoint() )
    2079           0 :                         pEndFrm = pStartFrm;
    2080             :                     else
    2081           0 :                         pStartFrm = pEndFrm;
    2082             :                 }
    2083           0 :                 break;
    2084             :             case FRM_TAB:
    2085             :                 // On different pages? Then check for table-headline
    2086             :                 {
    2087           1 :                     const SwTabFrm* pTabFrm = (SwTabFrm*)pSttLFrm;
    2088           3 :                     if( ( pTabFrm->GetFollow() ||
    2089           1 :                         ((SwTabFrm*)pEndLFrm)->GetFollow() ) &&
    2090           0 :                         pTabFrm->GetTable()->GetRowsToRepeat() > 0 &&
    2091           1 :                         pTabFrm->GetLower() != ((SwTabFrm*)pEndLFrm)->GetLower() &&
    2092           0 :                         ( lcl_IsInRepeatedHeadline( pStartFrm ) ||
    2093           0 :                         lcl_IsInRepeatedHeadline( pEndFrm ) ) )
    2094             :                     {
    2095             :                         // Set end- to the start-CntntFrame
    2096           0 :                         if( pStartPos == rCrsr.GetPoint() )
    2097           0 :                             pEndFrm = pStartFrm;
    2098             :                         else
    2099           0 :                             pStartFrm = pEndFrm;
    2100             :                     }
    2101             :                 }
    2102           1 :                 break;
    2103             :             }
    2104             :         } while( false );
    2105             : 
    2106         554 :         SwCrsrMoveState aTmpState( MV_NONE );
    2107         554 :         aTmpState.b2Lines = sal_True;
    2108         554 :         aTmpState.bNoScroll = sal_True;
    2109         554 :         aTmpState.nCursorBidiLevel = pStartFrm->IsRightToLeft() ? 1 : 0;
    2110             : 
    2111             :         //CntntRects to Start- and EndFrms.
    2112         554 :         SwRect aStRect, aEndRect;
    2113         554 :         pStartFrm->GetCharRect( aStRect, *pStartPos, &aTmpState );
    2114         554 :         Sw2LinesPos *pSt2Pos = aTmpState.p2Lines;
    2115         554 :         aTmpState.p2Lines = NULL;
    2116         554 :         aTmpState.nCursorBidiLevel = pEndFrm->IsRightToLeft() ? 1 : 0;
    2117             : 
    2118         554 :         pEndFrm->GetCharRect( aEndRect, *pEndPos, &aTmpState );
    2119         554 :         Sw2LinesPos *pEnd2Pos = aTmpState.p2Lines;
    2120             : 
    2121         554 :         SwRect aStFrm ( pStartFrm->UnionFrm( sal_True ) );
    2122         554 :         aStFrm.Intersection( pStartFrm->PaintArea() );
    2123         554 :         SwRect aEndFrm( pStartFrm == pEndFrm ? aStFrm : pEndFrm->UnionFrm( sal_True ) );
    2124         554 :         if( pStartFrm != pEndFrm )
    2125             :         {
    2126          92 :             aEndFrm.Intersection( pEndFrm->PaintArea() );
    2127             :         }
    2128         554 :         SWRECTFN( pStartFrm )
    2129         554 :         const sal_Bool bR2L = pStartFrm->IsRightToLeft();
    2130         554 :         const sal_Bool bEndR2L = pEndFrm->IsRightToLeft();
    2131             : 
    2132             :         // If there's no doubleline portion involved or start and end are both
    2133             :         // in the same doubleline portion, all works fine, but otherwise
    2134             :         // we need the following...
    2135         554 :         if( pSt2Pos != pEnd2Pos && ( !pSt2Pos || !pEnd2Pos ||
    2136           0 :             pSt2Pos->aPortion != pEnd2Pos->aPortion ) )
    2137             :         {
    2138             :             // If we have a start(end) position inside a doubleline portion
    2139             :             // the surrounded part of the doubleline portion is subtracted
    2140             :             // from the region and the aStRect(aEndRect) is set to the
    2141             :             // end(start) of the doubleline portion.
    2142          69 :             if( pSt2Pos )
    2143             :             {
    2144           0 :                 SwRect aTmp( aStRect );
    2145             : 
    2146             :                 // BiDi-Portions are swimming against the current.
    2147           0 :                 const sal_Bool bPorR2L = ( MT_BIDI == pSt2Pos->nMultiType ) ?
    2148           0 :                     ! bR2L :
    2149           0 :                 bR2L;
    2150             : 
    2151           0 :                 if( MT_BIDI == pSt2Pos->nMultiType &&
    2152           0 :                     (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
    2153             :                 {
    2154             :                     // nested bidi portion
    2155           0 :                     long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
    2156           0 :                     nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
    2157           0 :                     long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
    2158             : 
    2159           0 :                     (aTmp.*fnRect->fnSetRight)( nRightAbs );
    2160             : 
    2161           0 :                     if ( ! pEnd2Pos || pEnd2Pos->aPortion != pSt2Pos->aPortion )
    2162             :                     {
    2163           0 :                         SwRect aTmp2( pSt2Pos->aPortion );
    2164           0 :                         (aTmp2.*fnRect->fnSetRight)( nLeftAbs );
    2165           0 :                         aTmp2.Intersection( aEndFrm );
    2166           0 :                         Sub( aRegion, aTmp2 );
    2167             :                     }
    2168             :                 }
    2169             :                 else
    2170             :                 {
    2171           0 :                     if( bPorR2L )
    2172             :                         (aTmp.*fnRect->fnSetLeft)(
    2173           0 :                             (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
    2174             :                     else
    2175             :                         (aTmp.*fnRect->fnSetRight)(
    2176           0 :                             (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
    2177             :                 }
    2178             : 
    2179           0 :                 if( MT_ROT_90 == pSt2Pos->nMultiType ||
    2180           0 :                     (pSt2Pos->aPortion.*fnRect->fnGetTop)() ==
    2181           0 :                     (aTmp.*fnRect->fnGetTop)() )
    2182             :                 {
    2183             :                     (aTmp.*fnRect->fnSetTop)(
    2184           0 :                         (pSt2Pos->aLine.*fnRect->fnGetTop)() );
    2185             :                 }
    2186             : 
    2187           0 :                 aTmp.Intersection( aStFrm );
    2188           0 :                 Sub( aRegion, aTmp );
    2189             : 
    2190           0 :                 SwTwips nTmp = (pSt2Pos->aLine.*fnRect->fnGetBottom)();
    2191           0 :                 if( MT_ROT_90 != pSt2Pos->nMultiType &&
    2192           0 :                     (aStRect.*fnRect->fnBottomDist)( nTmp ) > 0 )
    2193             :                 {
    2194           0 :                     (aTmp.*fnRect->fnSetTop)( (aTmp.*fnRect->fnGetBottom)() );
    2195           0 :                     (aTmp.*fnRect->fnSetBottom)( nTmp );
    2196           0 :                     if( (aStRect.*fnRect->fnBottomDist)(
    2197           0 :                         (pSt2Pos->aPortion.*fnRect->fnGetBottom)() ) > 0 )
    2198             :                     {
    2199           0 :                         if( bPorR2L )
    2200             :                             (aTmp.*fnRect->fnSetRight)(
    2201           0 :                                 (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
    2202             :                         else
    2203             :                             (aTmp.*fnRect->fnSetLeft)(
    2204           0 :                                 (pSt2Pos->aPortion.*fnRect->fnGetLeft)() );
    2205             :                     }
    2206           0 :                     aTmp.Intersection( aStFrm );
    2207           0 :                     Sub( aRegion, aTmp );
    2208             :                 }
    2209             : 
    2210           0 :                 aStRect = pSt2Pos->aLine;
    2211             :                 (aStRect.*fnRect->fnSetLeft)( bR2L ?
    2212           0 :                         (pSt2Pos->aPortion.*fnRect->fnGetLeft)() :
    2213           0 :                         (pSt2Pos->aPortion.*fnRect->fnGetRight)() );
    2214           0 :                 (aStRect.*fnRect->fnSetWidth)( 1 );
    2215             :             }
    2216             : 
    2217          69 :             if( pEnd2Pos )
    2218             :             {
    2219          69 :                 SWRECTFNX( pEndFrm )
    2220          69 :                 SwRect aTmp( aEndRect );
    2221             : 
    2222             :                 // BiDi-Portions are swimming against the current.
    2223          69 :                 const sal_Bool bPorR2L = ( MT_BIDI == pEnd2Pos->nMultiType ) ?
    2224           0 :                                            ! bEndR2L :
    2225          69 :                                              bEndR2L;
    2226             : 
    2227          69 :                 if( MT_BIDI == pEnd2Pos->nMultiType &&
    2228           0 :                     (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
    2229             :                 {
    2230             :                     // nested bidi portion
    2231           0 :                     long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
    2232           0 :                     nRightAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
    2233           0 :                     long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
    2234             : 
    2235           0 :                     (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
    2236             : 
    2237           0 :                     if ( ! pSt2Pos || pSt2Pos->aPortion != pEnd2Pos->aPortion )
    2238             :                     {
    2239           0 :                         SwRect aTmp2( pEnd2Pos->aPortion );
    2240           0 :                         (aTmp2.*fnRectX->fnSetLeft)( nRightAbs );
    2241           0 :                         aTmp2.Intersection( aEndFrm );
    2242           0 :                         Sub( aRegion, aTmp2 );
    2243             :                     }
    2244             :                 }
    2245             :                 else
    2246             :                 {
    2247          69 :                     if ( bPorR2L )
    2248             :                         (aTmp.*fnRectX->fnSetRight)(
    2249           0 :                             (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
    2250             :                     else
    2251             :                         (aTmp.*fnRectX->fnSetLeft)(
    2252          69 :                             (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
    2253             :                 }
    2254             : 
    2255         138 :                 if( MT_ROT_90 == pEnd2Pos->nMultiType ||
    2256          69 :                     (pEnd2Pos->aPortion.*fnRectX->fnGetBottom)() ==
    2257          69 :                     (aEndRect.*fnRectX->fnGetBottom)() )
    2258             :                 {
    2259             :                     (aTmp.*fnRectX->fnSetBottom)(
    2260          25 :                         (pEnd2Pos->aLine.*fnRectX->fnGetBottom)() );
    2261             :                 }
    2262             : 
    2263          69 :                 aTmp.Intersection( aEndFrm );
    2264          69 :                 Sub( aRegion, aTmp );
    2265             : 
    2266             :                 // The next statement means neither ruby nor rotate(90):
    2267          69 :                 if( !( MT_RUBY & pEnd2Pos->nMultiType ) )
    2268             :                 {
    2269          16 :                     SwTwips nTmp = (pEnd2Pos->aLine.*fnRectX->fnGetTop)();
    2270          16 :                     if( (aEndRect.*fnRectX->fnGetTop)() != nTmp )
    2271             :                     {
    2272             :                         (aTmp.*fnRectX->fnSetBottom)(
    2273          16 :                             (aTmp.*fnRectX->fnGetTop)() );
    2274          16 :                         (aTmp.*fnRectX->fnSetTop)( nTmp );
    2275          32 :                         if( (aEndRect.*fnRectX->fnGetTop)() !=
    2276          16 :                             (pEnd2Pos->aPortion.*fnRectX->fnGetTop)() )
    2277             :                         {
    2278          16 :                             if( bPorR2L )
    2279             :                                 (aTmp.*fnRectX->fnSetLeft)(
    2280           0 :                                     (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
    2281             :                             else
    2282             :                                 (aTmp.*fnRectX->fnSetRight)(
    2283          16 :                                     (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() );
    2284             :                         }
    2285          16 :                         aTmp.Intersection( aEndFrm );
    2286          16 :                         Sub( aRegion, aTmp );
    2287             :                     }
    2288             :                 }
    2289             : 
    2290          69 :                 aEndRect = pEnd2Pos->aLine;
    2291             :                 (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ?
    2292           0 :                         (pEnd2Pos->aPortion.*fnRectX->fnGetRight)() :
    2293          69 :                         (pEnd2Pos->aPortion.*fnRectX->fnGetLeft)() );
    2294          69 :                 (aEndRect.*fnRectX->fnSetWidth)( 1 );
    2295             :             }
    2296             :         }
    2297         485 :         else if( pSt2Pos && pEnd2Pos &&
    2298           0 :                  MT_BIDI == pSt2Pos->nMultiType &&
    2299           0 :                  MT_BIDI == pEnd2Pos->nMultiType &&
    2300         485 :                  pSt2Pos->aPortion == pEnd2Pos->aPortion &&
    2301           0 :                  pSt2Pos->aPortion2 != pEnd2Pos->aPortion2 )
    2302             :         {
    2303             :             // This is the ugly special case, where the selection starts and
    2304             :             // ends in the same bidi portion but one start or end is inside a
    2305             :             // nested bidi portion.
    2306             : 
    2307           0 :             if ( (pSt2Pos->aPortion2.*fnRect->fnGetWidth)() )
    2308             :             {
    2309           0 :                 SwRect aTmp( aStRect );
    2310           0 :                 long nRightAbs = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
    2311           0 :                 nRightAbs -= (pSt2Pos->aPortion2.*fnRect->fnGetLeft)();
    2312           0 :                 long nLeftAbs = nRightAbs - (pSt2Pos->aPortion2.*fnRect->fnGetWidth)();
    2313             : 
    2314           0 :                 (aTmp.*fnRect->fnSetRight)( nRightAbs );
    2315           0 :                 aTmp.Intersection( aStFrm );
    2316           0 :                 Sub( aRegion, aTmp );
    2317             : 
    2318           0 :                 aStRect = pSt2Pos->aLine;
    2319           0 :                 (aStRect.*fnRect->fnSetLeft)( bR2L ? nRightAbs : nLeftAbs );
    2320           0 :                 (aStRect.*fnRect->fnSetWidth)( 1 );
    2321             :             }
    2322             : 
    2323           0 :             SWRECTFNX( pEndFrm )
    2324           0 :             if ( (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)() )
    2325             :             {
    2326           0 :                 SwRect aTmp( aEndRect );
    2327           0 :                 long nRightAbs = (pEnd2Pos->aPortion.*fnRectX->fnGetRight)();
    2328           0 :                 nRightAbs -= (pEnd2Pos->aPortion2.*fnRectX->fnGetLeft)();
    2329           0 :                 long nLeftAbs = nRightAbs - (pEnd2Pos->aPortion2.*fnRectX->fnGetWidth)();
    2330             : 
    2331           0 :                 (aTmp.*fnRectX->fnSetLeft)( nLeftAbs );
    2332           0 :                 aTmp.Intersection( aEndFrm );
    2333           0 :                 Sub( aRegion, aTmp );
    2334             : 
    2335           0 :                 aEndRect = pEnd2Pos->aLine;
    2336           0 :                 (aEndRect.*fnRectX->fnSetLeft)( bEndR2L ? nLeftAbs : nRightAbs );
    2337           0 :                 (aEndRect.*fnRectX->fnSetWidth)( 1 );
    2338             :             }
    2339             :         }
    2340             : 
    2341             :         // The charrect may be outside the paintarea (for cursortravelling)
    2342             :         // but the selection has to be restricted to the paintarea
    2343         554 :         if( aStRect.Left() < aStFrm.Left() )
    2344           1 :             aStRect.Left( aStFrm.Left() );
    2345         553 :         else if( aStRect.Left() > aStFrm.Right() )
    2346           0 :             aStRect.Left( aStFrm.Right() );
    2347         554 :         SwTwips nTmp = aStRect.Right();
    2348         554 :         if( nTmp < aStFrm.Left() )
    2349           1 :             aStRect.Right( aStFrm.Left() );
    2350         553 :         else if( nTmp > aStFrm.Right() )
    2351           0 :             aStRect.Right( aStFrm.Right() );
    2352         554 :         if( aEndRect.Left() < aEndFrm.Left() )
    2353           1 :             aEndRect.Left( aEndFrm.Left() );
    2354         553 :         else if( aEndRect.Left() > aEndFrm.Right() )
    2355           0 :             aEndRect.Left( aEndFrm.Right() );
    2356         554 :         nTmp = aEndRect.Right();
    2357         554 :         if( nTmp < aEndFrm.Left() )
    2358           1 :             aEndRect.Right( aEndFrm.Left() );
    2359         553 :         else if( nTmp > aEndFrm.Right() )
    2360           0 :             aEndRect.Right( aEndFrm.Right() );
    2361             : 
    2362         554 :         if( pStartFrm == pEndFrm )
    2363             :         {
    2364           0 :             sal_Bool bSameRotatedOrBidi = pSt2Pos && pEnd2Pos &&
    2365         462 :                 ( MT_BIDI & pSt2Pos->nMultiType ) &&
    2366         462 :                 pSt2Pos->aPortion == pEnd2Pos->aPortion;
    2367             :             //case 1: (Same frame and same row)
    2368         924 :             if( bSameRotatedOrBidi ||
    2369         462 :                 (aStRect.*fnRect->fnGetTop)() == (aEndRect.*fnRect->fnGetTop)() )
    2370             :             {
    2371         436 :                 Point aTmpSt( aStRect.Pos() );
    2372         436 :                 Point aTmpEnd( aEndRect.Right(), aEndRect.Bottom() );
    2373         436 :                 if( bSameRotatedOrBidi || bR2L )
    2374             :                 {
    2375           0 :                     if( aTmpSt.Y() > aTmpEnd.Y() )
    2376             :                     {
    2377           0 :                         long nTmpY = aTmpEnd.Y();
    2378           0 :                         aTmpEnd.Y() = aTmpSt.Y();
    2379           0 :                         aTmpSt.Y() = nTmpY;
    2380             :                     }
    2381           0 :                     if( aTmpSt.X() > aTmpEnd.X() )
    2382             :                     {
    2383           0 :                         long nTmpX = aTmpEnd.X();
    2384           0 :                         aTmpEnd.X() = aTmpSt.X();
    2385           0 :                         aTmpSt.X() = nTmpX;
    2386             :                     }
    2387             :                 }
    2388             : 
    2389         436 :                 SwRect aTmp = SwRect( aTmpSt, aTmpEnd );
    2390             :                 // Bug 34888: If content is selected which doesn't take space
    2391             :                 //            away (i.e. PostIts, RefMarks, TOXMarks), then at
    2392             :                 //            least set the width of the Crsr.
    2393         521 :                 if( 1 == (aTmp.*fnRect->fnGetWidth)() &&
    2394          85 :                     pStartPos->nContent.GetIndex() !=
    2395          85 :                     pEndPos->nContent.GetIndex() )
    2396             :                 {
    2397          70 :                     OutputDevice* pOut = pSh->GetOut();
    2398          70 :                     long nCrsrWidth = pOut->GetSettings().GetStyleSettings().
    2399          70 :                         GetCursorSize();
    2400             :                     (aTmp.*fnRect->fnSetWidth)( pOut->PixelToLogic(
    2401          70 :                         Size( nCrsrWidth, 0 ) ).Width() );
    2402             :                 }
    2403         436 :                 aTmp.Intersection( aStFrm );
    2404         436 :                 Sub( aRegion, aTmp );
    2405             :             }
    2406             :             //case 2: (Same frame, but not the same line)
    2407             :             else
    2408             :             {
    2409             :                 SwTwips lLeft, lRight;
    2410          26 :                 if( pSt2Pos && pEnd2Pos && pSt2Pos->aPortion == pEnd2Pos->aPortion )
    2411             :                 {
    2412           0 :                     lLeft = (pSt2Pos->aPortion.*fnRect->fnGetLeft)();
    2413           0 :                     lRight = (pSt2Pos->aPortion.*fnRect->fnGetRight)();
    2414             :                 }
    2415             :                 else
    2416             :                 {
    2417          26 :                     lLeft = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
    2418          26 :                         (pStartFrm->Prt().*fnRect->fnGetLeft)();
    2419          26 :                     lRight = (pStartFrm->Frm().*fnRect->fnGetLeft)() +
    2420          26 :                         (pStartFrm->Prt().*fnRect->fnGetRight)();
    2421             :                 }
    2422          26 :                 if( lLeft < (aStFrm.*fnRect->fnGetLeft)() )
    2423           0 :                     lLeft = (aStFrm.*fnRect->fnGetLeft)();
    2424          26 :                 if( lRight > (aStFrm.*fnRect->fnGetRight)() )
    2425           0 :                     lRight = (aStFrm.*fnRect->fnGetRight)();
    2426          26 :                 SwRect aSubRect( aStRect );
    2427             :                 //First line
    2428          26 :                 if( bR2L )
    2429           0 :                     (aSubRect.*fnRect->fnSetLeft)( lLeft );
    2430             :                 else
    2431          26 :                     (aSubRect.*fnRect->fnSetRight)( lRight );
    2432          26 :                 Sub( aRegion, aSubRect );
    2433             : 
    2434             :                 //If there's at least a twips between start- and endline,
    2435             :                 //so the whole area between will be added.
    2436          26 :                 SwTwips aTmpBottom = (aStRect.*fnRect->fnGetBottom)();
    2437          26 :                 SwTwips aTmpTop = (aEndRect.*fnRect->fnGetTop)();
    2438          26 :                 if( aTmpBottom != aTmpTop )
    2439             :                 {
    2440           8 :                     (aSubRect.*fnRect->fnSetLeft)( lLeft );
    2441           8 :                     (aSubRect.*fnRect->fnSetRight)( lRight );
    2442           8 :                     (aSubRect.*fnRect->fnSetTop)( aTmpBottom );
    2443           8 :                     (aSubRect.*fnRect->fnSetBottom)( aTmpTop );
    2444           8 :                     Sub( aRegion, aSubRect );
    2445             :                 }
    2446             :                 //and the last line
    2447          26 :                 aSubRect = aEndRect;
    2448          26 :                 if( bR2L )
    2449           0 :                     (aSubRect.*fnRect->fnSetRight)( lRight );
    2450             :                 else
    2451          26 :                     (aSubRect.*fnRect->fnSetLeft)( lLeft );
    2452          26 :                 Sub( aRegion, aSubRect );
    2453             :             }
    2454             :         }
    2455             :         //case 3: (Different frames, maybe with other frames between)
    2456             :         else
    2457             :         {
    2458             :             //The startframe first...
    2459          92 :             SwRect aSubRect( aStRect );
    2460          92 :             if( bR2L )
    2461           0 :                 (aSubRect.*fnRect->fnSetLeft)( (aStFrm.*fnRect->fnGetLeft)());
    2462             :             else
    2463          92 :                 (aSubRect.*fnRect->fnSetRight)( (aStFrm.*fnRect->fnGetRight)());
    2464          92 :             Sub( aRegion, aSubRect );
    2465          92 :             SwTwips nTmpTwips = (aStRect.*fnRect->fnGetBottom)();
    2466          92 :             if( (aStFrm.*fnRect->fnGetBottom)() != nTmpTwips )
    2467             :             {
    2468          28 :                 aSubRect = aStFrm;
    2469          28 :                 (aSubRect.*fnRect->fnSetTop)( nTmpTwips );
    2470          28 :                 Sub( aRegion, aSubRect );
    2471             :             }
    2472             : 
    2473             :             //Now the frames between, if there are any
    2474          92 :             bool const bBody = pStartFrm->IsInDocBody();
    2475          92 :             const SwTableBox* pCellBox = pStartFrm->GetUpper()->IsCellFrm() ?
    2476          92 :                 ((SwCellFrm*)pStartFrm->GetUpper())->GetTabBox() : 0;
    2477          92 :             if (pSh->IsSelectAll())
    2478          22 :                 pCellBox = 0;
    2479             : 
    2480          92 :             const SwCntntFrm *pCntnt = pStartFrm->GetNextCntntFrm();
    2481          92 :             SwRect aPrvRect;
    2482             : 
    2483             :             OSL_ENSURE( pCntnt,
    2484             :                 "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect -> please inform OD" );
    2485         290 :             while ( pCntnt && pCntnt != pEndFrm )
    2486             :             {
    2487         106 :                 if ( pCntnt->IsInFly() )
    2488             :                 {
    2489           0 :                     const SwAnchoredObject* pObj = pCntnt->FindFlyFrm();
    2490           0 :                     aSortObjs.Insert( *(const_cast<SwAnchoredObject*>(pObj)) );
    2491             :                 }
    2492             : 
    2493             :                 // Consider only frames which have the same IsInDocBody value like pStartFrm
    2494             :                 // If pStartFrm is inside a SwCellFrm, consider only frames which are inside the
    2495             :                 // same cell frame (or its follow cell)
    2496         106 :                 const SwTableBox* pTmpCellBox = pCntnt->GetUpper()->IsCellFrm() ?
    2497         106 :                     ((SwCellFrm*)pCntnt->GetUpper())->GetTabBox() : 0;
    2498         106 :                 if (pSh->IsSelectAll())
    2499          46 :                     pTmpCellBox = 0;
    2500         212 :                 if ( bBody == pCntnt->IsInDocBody() &&
    2501           0 :                     ( !pCellBox || pCellBox == pTmpCellBox ) )
    2502             :                 {
    2503         106 :                     SwRect aCRect( pCntnt->UnionFrm( sal_True ) );
    2504         106 :                     aCRect.Intersection( pCntnt->PaintArea() );
    2505         106 :                     if( aCRect.IsOver( aRegion.GetOrigin() ))
    2506             :                     {
    2507          72 :                         SwRect aTmp( aPrvRect );
    2508          72 :                         aTmp.Union( aCRect );
    2509         216 :                         if ( (aPrvRect.Height() * aPrvRect.Width() +
    2510          72 :                             aCRect.Height()   * aCRect.Width()) ==
    2511          72 :                             (aTmp.Height() * aTmp.Width()) )
    2512             :                         {
    2513           4 :                             aPrvRect.Union( aCRect );
    2514             :                         }
    2515             :                         else
    2516             :                         {
    2517          68 :                             if ( aPrvRect.HasArea() )
    2518          27 :                                 Sub( aRegion, aPrvRect );
    2519          68 :                             aPrvRect = aCRect;
    2520             :                         }
    2521             :                     }
    2522             :                 }
    2523         106 :                 pCntnt = pCntnt->GetNextCntntFrm();
    2524             :                 OSL_ENSURE( pCntnt,
    2525             :                     "<SwRootFrm::CalcFrmRects(..)> - no content frame. This is a serious defect!" );
    2526             :             }
    2527          92 :             if ( aPrvRect.HasArea() )
    2528          41 :                 Sub( aRegion, aPrvRect );
    2529             : 
    2530             :             //At least the endframe...
    2531          92 :             bVert = pEndFrm->IsVertical();
    2532          92 :             bRev = pEndFrm->IsReverse();
    2533             :             //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
    2534           0 :             fnRect = bVert ? ( bRev ? fnRectVL2R : ( pEndFrm->IsVertLR() ? fnRectVertL2R : fnRectVert ) ) :
    2535          92 :                 ( bRev ? fnRectB2T : fnRectHori );
    2536          92 :             nTmpTwips = (aEndRect.*fnRect->fnGetTop)();
    2537          92 :             if( (aEndFrm.*fnRect->fnGetTop)() != nTmpTwips )
    2538             :             {
    2539          39 :                 aSubRect = aEndFrm;
    2540          39 :                 (aSubRect.*fnRect->fnSetBottom)( nTmpTwips );
    2541          39 :                 Sub( aRegion, aSubRect );
    2542             :             }
    2543          92 :             aSubRect = aEndRect;
    2544          92 :             if( bEndR2L )
    2545           0 :                 (aSubRect.*fnRect->fnSetRight)((aEndFrm.*fnRect->fnGetRight)());
    2546             :             else
    2547          92 :                 (aSubRect.*fnRect->fnSetLeft)( (aEndFrm.*fnRect->fnGetLeft)() );
    2548          92 :             Sub( aRegion, aSubRect );
    2549             :         }
    2550             : 
    2551         554 :         aRegion.Invert();
    2552         554 :         delete pSt2Pos;
    2553         554 :         delete pEnd2Pos;
    2554             :     }
    2555             : 
    2556             :     // Cut out Flys during loop. We don't cut out Flys when:
    2557             :     // - the Lower is StartFrm/EndFrm (FlyInCnt and all other Flys which again
    2558             :     //   sit in it)
    2559             :     // - if in the Z-order we have Flys above those in which the StartFrm is
    2560             :     //   placed
    2561         554 :     const SwPageFrm *pPage      = pStartFrm->FindPageFrm();
    2562         554 :     const SwPageFrm *pEndPage   = pEndFrm->FindPageFrm();
    2563             : 
    2564        1115 :     while ( pPage )
    2565             :     {
    2566         561 :         if ( pPage->GetSortedObjs() )
    2567             :         {
    2568           0 :             const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
    2569           0 :             for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
    2570             :             {
    2571           0 :                 SwAnchoredObject* pAnchoredObj = rObjs[i];
    2572           0 :                 if ( !pAnchoredObj->ISA(SwFlyFrm) )
    2573           0 :                     continue;
    2574           0 :                 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pAnchoredObj);
    2575           0 :                 const SwVirtFlyDrawObj* pObj = pFly->GetVirtDrawObj();
    2576           0 :                 const SwFmtSurround &rSur = pFly->GetFmt()->GetSurround();
    2577           0 :                 if ( !pFly->IsAnLower( pStartFrm ) &&
    2578           0 :                     (rSur.GetSurround() != SURROUND_THROUGHT &&
    2579           0 :                     !rSur.IsContour()) )
    2580             :                 {
    2581           0 :                     if ( aSortObjs.Contains( *pAnchoredObj ) )
    2582           0 :                         continue;
    2583             : 
    2584           0 :                     sal_Bool bSub = sal_True;
    2585           0 :                     const sal_uInt32 nPos = pObj->GetOrdNum();
    2586           0 :                     for ( sal_uInt16 k = 0; bSub && k < aSortObjs.Count(); ++k )
    2587             :                     {
    2588             :                         OSL_ENSURE( aSortObjs[k]->ISA(SwFlyFrm),
    2589             :                             "<SwRootFrm::CalcFrmRects(..)> - object in <aSortObjs> of unexcepted type" );
    2590           0 :                         const SwFlyFrm* pTmp = static_cast<SwFlyFrm*>(aSortObjs[k]);
    2591           0 :                         do
    2592             :                         {
    2593           0 :                             if ( nPos < pTmp->GetVirtDrawObj()->GetOrdNumDirect() )
    2594             :                             {
    2595           0 :                                 bSub = sal_False;
    2596             :                             }
    2597             :                             else
    2598             :                             {
    2599           0 :                                 pTmp = pTmp->GetAnchorFrm()->FindFlyFrm();
    2600             :                             }
    2601           0 :                         } while ( bSub && pTmp );
    2602             :                     }
    2603           0 :                     if ( bSub )
    2604           0 :                         Sub( aRegion, pFly->Frm() );
    2605             :                 }
    2606             :             }
    2607             :         }
    2608         561 :         if ( pPage == pEndPage )
    2609         554 :             break;
    2610             :         else
    2611           7 :             pPage = (SwPageFrm*)pPage->GetNext();
    2612             :     }
    2613             : 
    2614             :     //Because it looks better, we close the DropCaps.
    2615         554 :     SwRect aDropRect;
    2616         554 :     if ( pStartFrm->IsTxtFrm() )
    2617             :     {
    2618         554 :         if ( ((SwTxtFrm*)pStartFrm)->GetDropRect( aDropRect ) )
    2619           0 :             Sub( aRegion, aDropRect );
    2620             :     }
    2621         554 :     if ( pEndFrm != pStartFrm && pEndFrm->IsTxtFrm() )
    2622             :     {
    2623          92 :         if ( ((SwTxtFrm*)pEndFrm)->GetDropRect( aDropRect ) )
    2624           0 :             Sub( aRegion, aDropRect );
    2625             :     }
    2626             : 
    2627        1108 :     rCrsr.assign( aRegion.begin(), aRegion.end() );
    2628         111 : }
    2629             : 
    2630             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10