LCOV - code coverage report
Current view: top level - sw/source/core/layout - trvlfrm.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 694 1350 51.4 %
Date: 2015-06-13 12:38:46 Functions: 34 52 65.4 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11