LCOV - code coverage report
Current view: top level - sw/source/core/layout - layact.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1035 1176 88.0 %
Date: 2014-11-03 Functions: 33 33 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <config_features.h>
      21             : 
      22             : #include <ctime>
      23             : #include "rootfrm.hxx"
      24             : #include "pagefrm.hxx"
      25             : #include "viewimp.hxx"
      26             : #include "crsrsh.hxx"
      27             : #include "dflyobj.hxx"
      28             : #include "frmtool.hxx"
      29             : #include "dcontact.hxx"
      30             : #include "viewopt.hxx"
      31             : #include "dbg_lay.hxx"
      32             : #include "layouter.hxx"
      33             : #include "docstat.hxx"
      34             : #include "swevent.hxx"
      35             : #include <IDocumentStatistics.hxx>
      36             : #include <IDocumentLayoutAccess.hxx>
      37             : 
      38             : #include <sfx2/event.hxx>
      39             : 
      40             : #include <ftnidx.hxx>
      41             : #include <vcl/svapp.hxx>
      42             : #include <editeng/opaqitem.hxx>
      43             : #include <SwSmartTagMgr.hxx>
      44             : 
      45             : #include "layact.hxx"
      46             : #include <swwait.hxx>
      47             : #include <fmtsrnd.hxx>
      48             : #include <docsh.hxx>
      49             : 
      50             : #include "tabfrm.hxx"
      51             : #include "ftnfrm.hxx"
      52             : #include "txtfrm.hxx"
      53             : #include "notxtfrm.hxx"
      54             : #include "flyfrms.hxx"
      55             : #include "mdiexp.hxx"
      56             : #include "sectfrm.hxx"
      57             : #include <acmplwrd.hxx>
      58             : #include <sortedobjs.hxx>
      59             : #include <objectformatter.hxx>
      60             : #include <vector>
      61             : 
      62             : // SwLayAction static stuff
      63             : 
      64             : #define IS_FLYS (pPage->GetSortedObjs())
      65             : #define IS_INVAFLY (pPage->IsInvalidFly())
      66             : 
      67             : // Save some typing work to avoid accessing destroyed pages.
      68             : #if OSL_DEBUG_LEVEL > 1
      69             : 
      70             : static void BreakPoint()
      71             : {
      72             :     return;
      73             : }
      74             : 
      75             : #define XCHECKPAGE \
      76             :             {   if ( IsAgain() ) \
      77             :                 {   BreakPoint(); \
      78             :                     if( bNoLoop ) \
      79             :                         pLayoutAccess->GetLayouter()->EndLoopControl(); \
      80             :                     return; \
      81             :                 } \
      82             :             }
      83             : #else
      84             : #define XCHECKPAGE \
      85             :             {   if ( IsAgain() ) \
      86             :                 { \
      87             :                     if( bNoLoop ) \
      88             :                         pLayoutAccess->GetLayouter()->EndLoopControl(); \
      89             :                     return; \
      90             :                 } \
      91             :             }
      92             : #endif
      93             : 
      94             : #define RESCHEDULE \
      95             :     { \
      96             :         if ( IsReschedule() )  \
      97             :         { \
      98             :             ::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
      99             :         } \
     100             :     }
     101             : 
     102      132525 : void SwLayAction::CheckWaitCrsr()
     103             : {
     104      132525 :     RESCHEDULE
     105      152786 :     if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
     106       20261 :          ((std::clock() - GetStartTicks()) * 1000 / CLOCKS_PER_SEC >= CLOCKS_PER_SEC/2) )
     107             :     {
     108           0 :         pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), true );
     109             :     }
     110      132525 : }
     111             : 
     112             : // Time over already?
     113      135039 : inline void SwLayAction::CheckIdleEnd()
     114             : {
     115      135039 :     if ( !IsInput() )
     116      134939 :         bInput = GetInputType() && Application::AnyInput( GetInputType() );
     117      135039 : }
     118             : 
     119        4892 : void SwLayAction::SetStatBar( bool bNew )
     120             : {
     121        4892 :     if ( bNew )
     122             :     {
     123        4892 :         nEndPage = pRoot->GetPageNum();
     124        4892 :         nEndPage += nEndPage * 10 / 100;
     125             :     }
     126             :     else
     127           0 :         nEndPage = USHRT_MAX;
     128        4892 : }
     129             : 
     130        7399 : bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
     131             :                                     const SwPageFrm *pPage )
     132             : {
     133        7399 :     SwRegionRects aTmp( rRect );
     134        7399 :     const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
     135        7399 :     const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
     136             : 
     137       47768 :     for ( size_t i = 0; i < rObjs.size() && !aTmp.empty(); ++i )
     138             :     {
     139       40369 :         SdrObject *pO = rObjs[i]->DrawObj();
     140       40369 :         if ( !pO->ISA(SwVirtFlyDrawObj) )
     141       28996 :             continue;
     142             : 
     143             :         // OD 2004-01-15 #110582# - do not consider invisible objects
     144       11373 :         const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
     145       11373 :         if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
     146             :         {
     147           0 :             continue;
     148             :         }
     149             : 
     150       11373 :         SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
     151             : 
     152       11373 :         if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
     153       10344 :             continue;
     154             : 
     155        1029 :         if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
     156           2 :             continue;
     157             : 
     158        1027 :         if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
     159         312 :             continue;
     160             : 
     161         715 :         if ( pSelfFly )
     162             :         {
     163         254 :             const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
     164         254 :             if ( pO->GetLayer() == pTmp->GetLayer() )
     165             :             {
     166         254 :                 if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
     167             :                     // Only look at things above us, if inside the same layer
     168         217 :                     continue;
     169             :             }
     170             :             else
     171             :             {
     172           0 :                 const bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
     173           0 :                 if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
     174             :                     // Things from other layers are only interesting to us if
     175             :                     // they're not transparent or lie inwards
     176           0 :                     continue;
     177             :             }
     178             :         }
     179             : 
     180             :         // OD 19.08.2002 #99657#
     181             :         //     Fly frame without a lower have to be subtracted from paint region.
     182             :         //     For checking, if fly frame contains transparent graphic or
     183             :         //     has surrounded contour, assure that fly frame has a lower
     184        1494 :         if ( pFly->Lower() &&
     185         948 :              pFly->Lower()->IsNoTxtFrm() &&
     186         225 :              ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
     187           0 :                pFly->GetFmt()->GetSurround().IsContour() )
     188             :            )
     189             :         {
     190         225 :             continue;
     191             :         }
     192             : 
     193             :         // OD 19.08.2002 #99657#
     194             :         //     vcl::Region of a fly frame with transparent background or a transparent
     195             :         //     shadow have not to be subtracted from paint region
     196         532 :         if ( pFly->IsBackgroundTransparent() ||
     197         259 :              pFly->IsShadowTransparent() )
     198             :         {
     199          14 :             continue;
     200             :         }
     201             : 
     202         259 :         aTmp -= pFly->Frm();
     203             :     }
     204             : 
     205        7399 :     bool bRetPaint = false;
     206       15165 :     for ( SwRects::const_iterator it = aTmp.begin(); it != aTmp.end(); ++it )
     207        7766 :         bRetPaint |= pImp->GetShell()->AddPaintRect( *it );
     208        7399 :     return bRetPaint;
     209             : }
     210             : 
     211       36274 : inline bool SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
     212             :                                       const SwPageFrm *pPage,
     213             :                                       const SwRect &rRect )
     214             : {
     215       36274 :     if ( rRect.HasArea() )
     216             :     {
     217       33968 :         if ( pPage->GetSortedObjs() )
     218        7399 :             return PaintWithoutFlys( rRect, pCntnt, pPage );
     219             :         else
     220       26569 :             return pImp->GetShell()->AddPaintRect( rRect );
     221             :     }
     222        2306 :     return false;
     223             : }
     224             : 
     225             : /**
     226             :  * Depending of the type, the Cntnt is output according to it's changes, or the area
     227             :  * to be outputted is registered with the region, respectively.
     228             :  */
     229       29399 : void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
     230             :                               const SwPageFrm *pPage,
     231             :                               const SwRect &rOldRect,
     232             :                               long nOldBottom )
     233             : {
     234       29399 :     SWRECTFN( pCnt )
     235             : 
     236       29399 :     if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
     237             :     {
     238       14911 :         SwRect aPaint( pCnt->PaintArea() );
     239       14911 :         if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
     240        3550 :             pCnt->ResetCompletePaint();
     241             :     }
     242             :     else
     243             :     {
     244             :         // paint the area between printing bottom and frame bottom and
     245             :         // the area left and right beside the frame, if its height changed.
     246       14488 :         long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
     247       14488 :         long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
     248       14488 :         const bool bHeightDiff = nOldHeight != nNewHeight;
     249       14488 :         if( bHeightDiff )
     250             :         {
     251             :             // OD 05.11.2002 #94454# - consider whole potential paint area.
     252             :             //SwRect aDrawRect( pCnt->UnionFrm( sal_True ) );
     253        1278 :             SwRect aDrawRect( pCnt->PaintArea() );
     254        1278 :             if( nOldHeight > nNewHeight )
     255         114 :                 nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
     256        1278 :             (aDrawRect.*fnRect->fnSetTop)( nOldBottom );
     257        1278 :             _PaintCntnt( pCnt, pPage, aDrawRect );
     258             :         }
     259             :         // paint content area
     260       14488 :         SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
     261       14488 :         _PaintCntnt( pCnt, pPage, aPaintRect );
     262             :     }
     263             : 
     264       29399 :     if ( pCnt->IsRetouche() && !pCnt->GetNext() )
     265             :     {
     266        5597 :         const SwFrm *pTmp = pCnt;
     267        5597 :         if( pCnt->IsInSct() )
     268             :         {
     269         140 :             const SwSectionFrm* pSct = pCnt->FindSctFrm();
     270         140 :             if( pSct->IsRetouche() && !pSct->GetNext() )
     271          20 :                 pTmp = pSct;
     272             :         }
     273        5597 :         SwRect aRect( pTmp->GetUpper()->PaintArea() );
     274        5597 :         (aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
     275        5597 :         if ( !_PaintCntnt( pCnt, pPage, aRect ) )
     276        2166 :             pCnt->ResetRetouche();
     277             :     }
     278       29399 : }
     279             : 
     280       74836 : SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
     281             :     pRoot( pRt ),
     282             :     pImp( pI ),
     283             :     pOptTab( 0 ),
     284             :     pWait( 0 ),
     285             :     nPreInvaPage( USHRT_MAX ),
     286       74836 :     nStartTicks( std::clock() ),
     287             :     nInputType( 0 ),
     288             :     nEndPage( USHRT_MAX ),
     289      149672 :     nCheckPageNum( USHRT_MAX )
     290             : {
     291       74836 :     bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
     292       74836 :     bPaint = bComplete = bWaitAllowed = bCheckPages = true;
     293             :     bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
     294       74836 :     bUpdateExpFlds = bBrowseActionStop = bActionInProgress = false;
     295             :     // OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
     296       74836 :     mbFormatCntntOnInterrupt = false;
     297             : 
     298             :     assert(!pImp->pLayAct); // there can be only one SwLayAction
     299       74836 :     pImp->pLayAct = this;   // register there
     300       74836 : }
     301             : 
     302       74836 : SwLayAction::~SwLayAction()
     303             : {
     304             :     OSL_ENSURE( !pWait, "Wait object not destroyed" );
     305       74836 :     pImp->pLayAct = 0;      // unregister
     306       74836 : }
     307             : 
     308         164 : void SwLayAction::Reset()
     309             : {
     310         164 :     pOptTab = 0;
     311         164 :     nStartTicks = std::clock();
     312         164 :     nInputType = 0;
     313         164 :     nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
     314         164 :     bPaint = bComplete = bWaitAllowed = bCheckPages = true;
     315             :     bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
     316         164 :     bUpdateExpFlds = bBrowseActionStop = false;
     317         164 : }
     318             : 
     319       68070 : bool SwLayAction::RemoveEmptyBrowserPages()
     320             : {
     321             :     // switching from the normal to the browser mode, empty pages may be
     322             :     // retained for an annoyingly long time, so delete them here
     323       68070 :     bool bRet = false;
     324       68070 :     const SwViewShell *pSh = pRoot->GetCurrShell();
     325       68070 :     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
     326             :     {
     327         649 :         SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
     328         649 :         do
     329             :         {
     330        1290 :             if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->size()) ||
     331         641 :                  pPage->ContainsCntnt() )
     332         649 :                 pPage = (SwPageFrm*)pPage->GetNext();
     333             :             else
     334             :             {
     335           0 :                 bRet = true;
     336           0 :                 SwPageFrm *pDel = pPage;
     337           0 :                 pPage = (SwPageFrm*)pPage->GetNext();
     338           0 :                 pDel->Cut();
     339           0 :                 delete pDel;
     340             :             }
     341             :         } while ( pPage );
     342             :     }
     343       68070 :     return bRet;
     344             : }
     345             : 
     346       75000 : void SwLayAction::Action()
     347             : {
     348       75000 :     bActionInProgress = true;
     349             : 
     350             :     //TurboMode? Hands-off during idle-format
     351       75000 :     if ( IsPaint() && !IsIdle() && TurboAction() )
     352             :     {
     353        6948 :         delete pWait, pWait = 0;
     354        6948 :         pRoot->ResetTurboFlag();
     355        6948 :         bActionInProgress = false;
     356        6948 :         pRoot->DeleteEmptySct();
     357       81948 :         return;
     358             :     }
     359       68052 :     else if ( pRoot->GetTurbo() )
     360             :     {
     361          32 :         pRoot->DisallowTurbo();
     362          32 :         const SwFrm *pFrm = pRoot->GetTurbo();
     363          32 :         pRoot->ResetTurbo();
     364          32 :         pFrm->InvalidatePage();
     365             :     }
     366       68052 :     pRoot->DisallowTurbo();
     367             : 
     368       68052 :     if ( IsCalcLayout() )
     369        4728 :         SetCheckPages( false );
     370             : 
     371       68052 :     InternalAction();
     372       68052 :     bAgain |= RemoveEmptyBrowserPages();
     373      136122 :     while ( IsAgain() )
     374             :     {
     375          18 :         bAgain = bNextCycle = false;
     376          18 :         InternalAction();
     377          18 :         bAgain |= RemoveEmptyBrowserPages();
     378             :     }
     379       68052 :     pRoot->DeleteEmptySct();
     380             : 
     381       68052 :     delete pWait, pWait = 0;
     382             : 
     383             :     //Turbo-Action permitted again for all cases.
     384       68052 :     pRoot->ResetTurboFlag();
     385       68052 :     pRoot->ResetTurbo();
     386             : 
     387       68052 :     SetCheckPages( true );
     388             : 
     389       68052 :     bActionInProgress = false;
     390             : }
     391             : 
     392       62535 : SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
     393             : {
     394       62535 :     SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
     395       62535 :     SwCntntFrm *pChk = pCnt;
     396       62535 :     bool bPageChgd = false;
     397      140003 :     while ( pCnt && pCnt->IsFollow() )
     398       14933 :         pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
     399       62535 :     if ( pCnt && pChk != pCnt )
     400        8376 :     {   bPageChgd = true;
     401        8376 :         pPage = pCnt->FindPageFrm();
     402             :     }
     403             : 
     404       62535 :     if ( !pPage->GetFmt()->GetDoc()->GetFtnIdxs().empty() )
     405             :     {
     406         949 :         SwFtnContFrm *pCont = pPage->FindFtnCont();
     407         949 :         if ( pCont )
     408             :         {
     409         670 :             pCnt = pCont->ContainsCntnt();
     410         670 :             pChk = pCnt;
     411        1340 :             while ( pCnt && pCnt->IsFollow() )
     412           0 :                 pCnt = (SwCntntFrm*)pCnt->FindPrev();
     413         670 :             if ( pCnt && pCnt != pChk )
     414             :             {
     415           0 :                 if ( bPageChgd )
     416             :                 {
     417             :                     // Use the 'topmost' page
     418           0 :                     SwPageFrm *pTmp = pCnt->FindPageFrm();
     419           0 :                     if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
     420           0 :                         pPage = pTmp;
     421             :                 }
     422             :                 else
     423           0 :                     pPage = pCnt->FindPageFrm();
     424             :             }
     425             :         }
     426             :     }
     427       62535 :     return pPage;
     428             : }
     429             : 
     430             : // #114798# - unlock position on start and end of page
     431             : // layout process.
     432       24320 : static void unlockPositionOfObjects( SwPageFrm *pPageFrm )
     433             : {
     434             :     assert( pPageFrm );
     435             : 
     436       24320 :     SwSortedObjs* pObjs = pPageFrm->GetSortedObjs();
     437       24320 :     if ( pObjs )
     438             :     {
     439       23068 :         for ( size_t i = 0; i < pObjs->size(); ++i )
     440             :         {
     441       17616 :             SwAnchoredObject* pObj = (*pObjs)[i];
     442       17616 :             pObj->UnlockPosition();
     443             :         }
     444             :     }
     445       24320 : }
     446             : 
     447       68070 : void SwLayAction::InternalAction()
     448             : {
     449             :     OSL_ENSURE( pRoot->Lower()->IsPageFrm(), ":-( No page below the root.");
     450             : 
     451       68070 :     pRoot->Calc();
     452             : 
     453             :     // Figure out the first invalid page or the first one to be formatted,
     454             :     // respectively. A complete-action means the first invalid page.
     455             :     // However, the first page to be formatted might be the one having the
     456             :     // number 1.  If we're doing a fake formatting, the number of the first
     457             :     // page is the number of the first visible page.
     458       73605 :     SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
     459       73605 :                 pImp->GetFirstVisPage();
     460       68070 :     if ( !pPage )
     461           0 :         pPage = (SwPageFrm*)pRoot->Lower();
     462             : 
     463             :     // If there's a first-flow-Cntnt in the first visible page that's also a Follow,
     464             :     // we switch the page back to the original master of that Cntnt.
     465       68070 :     if ( !IsComplete() )
     466       62535 :         pPage = CheckFirstVisPage( pPage );
     467       68070 :     sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
     468             : 
     469      216002 :     while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
     470       79862 :         pPage = (SwPageFrm*)pPage->GetNext();
     471             : 
     472       68070 :     IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
     473       68070 :     bool bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : sal_False;
     474       68070 :     sal_uInt16 nPercentPageNum = 0;
     475      150246 :     while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
     476             :     {
     477       25203 :         if ( !pPage && nCheckPageNum != USHRT_MAX &&
     478          42 :              (!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
     479             :         {
     480          42 :             if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
     481             :             {
     482          42 :                 SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
     483         284 :                 while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
     484         200 :                     pPg = (SwPageFrm*)pPg->GetNext();
     485          42 :                 if ( pPg )
     486          42 :                     pPage = pPg;
     487          42 :                 if ( !pPage )
     488           0 :                     break;
     489             :             }
     490          42 :             SwPageFrm *pTmp = pPage->GetPrev() ?
     491          42 :                                         (SwPageFrm*)pPage->GetPrev() : pPage;
     492          42 :             SetCheckPages( true );
     493          42 :             SwFrm::CheckPageDescs( pPage, true, &pTmp );
     494          42 :             SetCheckPages( false );
     495          42 :             nCheckPageNum = USHRT_MAX;
     496          42 :             pPage = pTmp;
     497          42 :             continue;
     498             :         }
     499             : 
     500       25077 :         if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
     501             :         {
     502        2188 :             nPercentPageNum = pPage->GetPhyPageNum();
     503        2188 :             ::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
     504             :         }
     505       25077 :         pOptTab = 0;
     506             :              // No Shortcut for Idle or CalcLayout
     507       25077 :         if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
     508             :         {
     509       12847 :             pRoot->DeleteEmptySct();
     510       12865 :             XCHECKPAGE;
     511       27546 :             if ( !IsInterrupt() &&
     512       25526 :                  (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
     513             :             {
     514        1852 :                 if ( pRoot->IsAssertFlyPages() )
     515        1844 :                     pRoot->AssertFlyPages();
     516        1852 :                 if ( pRoot->IsSuperfluous() )
     517             :                 {
     518         168 :                     bool bOld = IsAgain();
     519         168 :                     pRoot->RemoveSuperfluous();
     520         168 :                     bAgain = bOld;
     521             :                 }
     522        1852 :                 if ( IsAgain() )
     523             :                 {
     524           0 :                     if( bNoLoop )
     525           0 :                         pLayoutAccess->GetLayouter()->EndLoopControl();
     526           0 :                     return;
     527             :                 }
     528        1852 :                 pPage = (SwPageFrm*)pRoot->Lower();
     529        4364 :                 while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
     530         660 :                     pPage = (SwPageFrm*)pPage->GetNext();
     531        3946 :                 while ( pPage && pPage->GetNext() &&
     532         236 :                         pPage->GetPhyPageNum() < nFirstPageNum )
     533           6 :                     pPage = (SwPageFrm*)pPage->GetNext();
     534        1852 :                 continue;
     535             :             }
     536       10995 :             break;
     537             :         }
     538             :         else
     539             :         {
     540       12230 :             pRoot->DeleteEmptySct();
     541       12230 :             XCHECKPAGE;
     542             : 
     543       73049 :             while ( !IsInterrupt() && !IsNextCycle() &&
     544       29781 :                     ((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
     545             :             {
     546       12142 :                 unlockPositionOfObjects( pPage );
     547             : 
     548             :                 // #i28701#
     549       12142 :                 SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
     550       12142 :                 if ( !IS_FLYS )
     551             :                 {
     552             :                     // If there are no (more) Flys, the flags are superfluous.
     553        9416 :                     pPage->ValidateFlyLayout();
     554        9416 :                     pPage->ValidateFlyCntnt();
     555             :                 }
     556             :                 // #i28701# - change condition
     557       89468 :                 while ( !IsInterrupt() && !IsNextCycle() &&
     558       42048 :                         ( pPage->IsInvalid() ||
     559       15075 :                           (IS_FLYS && IS_INVAFLY) ) )
     560             :                 {
     561             :                     PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
     562       17691 :                     XCHECKPAGE;
     563             : 
     564             :                     // #i81146# new loop control
     565       17691 :                     sal_uInt16 nLoopControlRuns_1 = 0;
     566       17691 :                     const sal_uInt16 nLoopControlMax = 20;
     567             : 
     568       46106 :                     while ( !IsNextCycle() && pPage->IsInvalidLayout() )
     569             :                     {
     570       10724 :                         pPage->ValidateLayout();
     571             : 
     572       10724 :                         if ( ++nLoopControlRuns_1 > nLoopControlMax )
     573             :                         {
     574             :                             OSL_FAIL( "LoopControl_1 in SwLayAction::InternalAction" );
     575           0 :                             break;
     576             :                         }
     577             : 
     578       10724 :                         FormatLayout( pPage );
     579       10724 :                         XCHECKPAGE;
     580             :                     }
     581             :                     // #i28701# - change condition
     582       53019 :                     if ( !IsNextCycle() &&
     583       17864 :                          ( pPage->IsInvalidCntnt() ||
     584         304 :                            (IS_FLYS && IS_INVAFLY) ) )
     585             :                     {
     586       17639 :                         pPage->ValidateFlyInCnt();
     587       17639 :                         pPage->ValidateCntnt();
     588             :                         // #i28701#
     589       17639 :                         pPage->ValidateFlyLayout();
     590       17639 :                         pPage->ValidateFlyCntnt();
     591       17639 :                         if ( !FormatCntnt( pPage ) )
     592             :                         {
     593        2843 :                             XCHECKPAGE;
     594        2837 :                             pPage->InvalidateCntnt();
     595        2837 :                             pPage->InvalidateFlyInCnt();
     596             :                             // #i28701#
     597        2837 :                             pPage->InvalidateFlyLayout();
     598        2837 :                             pPage->InvalidateFlyCntnt();
     599        2837 :                             if ( IsBrowseActionStop() )
     600           2 :                                 bInput = true;
     601             :                         }
     602             :                     }
     603       17685 :                     if( bNoLoop )
     604       17685 :                         pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
     605             :                 }
     606             : 
     607       12136 :                 unlockPositionOfObjects( pPage );
     608             :             }
     609             : 
     610             :             // A previous page may be invalid again.
     611       12212 :             XCHECKPAGE;
     612       12212 :             if ( !IS_FLYS )
     613             :             {
     614             :                 // If there are no (more) Flys, the flags are superfluous.
     615        9486 :                 pPage->ValidateFlyLayout();
     616        9486 :                 pPage->ValidateFlyCntnt();
     617             :             }
     618       12212 :             if ( !IsInterrupt() )
     619             :             {
     620       12195 :                 SetNextCycle( false );
     621             : 
     622       12195 :                 if ( nPreInvaPage != USHRT_MAX )
     623             :                 {
     624         614 :                     if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
     625             :                     {
     626           0 :                         pImp->SetFirstVisPageInvalid();
     627           0 :                         SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
     628           0 :                         nFirstPageNum = pTmpPage->GetPhyPageNum();
     629           0 :                         if( nPreInvaPage < nFirstPageNum )
     630             :                         {
     631           0 :                             nPreInvaPage = nFirstPageNum;
     632           0 :                             pPage = pTmpPage;
     633             :                         }
     634             :                     }
     635        2988 :                     while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
     636        1760 :                         pPage = (SwPageFrm*)pPage->GetPrev();
     637         614 :                     nPreInvaPage = USHRT_MAX;
     638             :                 }
     639             : 
     640       41468 :                 while ( pPage->GetPrev() &&
     641        8346 :                         ( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
     642        4813 :                           ( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
     643       13665 :                             ((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
     644         380 :                         (((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
     645             :                             nFirstPageNum) )
     646             :                 {
     647         260 :                     pPage = (SwPageFrm*)pPage->GetPrev();
     648             :                 }
     649             : 
     650             :                 // Continue to the next invalid page
     651       65653 :                 while ( pPage && !pPage->IsInvalid() &&
     652       16931 :                         (!IS_FLYS || !IS_INVAFLY) )
     653             :                 {
     654       13751 :                     pPage = (SwPageFrm*)pPage->GetNext();
     655             :                 }
     656       12195 :                 if( bNoLoop )
     657       12195 :                     pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
     658             :             }
     659       12212 :             CheckIdleEnd();
     660             :         }
     661       23312 :         if ( !pPage && !IsInterrupt() &&
     662       14466 :              (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
     663             :         {
     664        3788 :             if ( pRoot->IsAssertFlyPages() )
     665        3700 :                 pRoot->AssertFlyPages();
     666        3788 :             if ( pRoot->IsSuperfluous() )
     667             :             {
     668         158 :                 bool bOld = IsAgain();
     669         158 :                 pRoot->RemoveSuperfluous();
     670         158 :                 bAgain = bOld;
     671             :             }
     672        3788 :             if ( IsAgain() )
     673             :             {
     674           0 :                 if( bNoLoop )
     675           0 :                     pLayoutAccess->GetLayouter()->EndLoopControl();
     676           0 :                 return;
     677             :             }
     678        3788 :             pPage = (SwPageFrm*)pRoot->Lower();
     679       12498 :             while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
     680        4922 :                 pPage = (SwPageFrm*)pPage->GetNext();
     681        7656 :             while ( pPage && pPage->GetNext() &&
     682          42 :                     pPage->GetPhyPageNum() < nFirstPageNum )
     683          38 :                 pPage = (SwPageFrm*)pPage->GetNext();
     684             :         }
     685             :     }
     686       68052 :     if ( IsInterrupt() && pPage )
     687             :     {
     688             :         // If we have input, we don't want to format content anymore, but
     689             :         // we still should clean the layout.
     690             :         // Otherwise, the following situation might arise:
     691             :         // The user enters some text at the end of the paragraph of the last
     692             :         // page, causing the paragraph to create a Follow for the next page.
     693             :         // Meanwhile the user continues typing, so we have input while
     694             :         // still formatting.
     695             :         // The paragraph on the new page has already been partially formatted,
     696             :         // and the new page has been fully formatted and is set to CompletePaint,
     697             :         // but hasn't added itself to the area to be output. Then we paint,
     698             :         // the CompletePaint of the page is reset because the new paragraph
     699             :         // already added itself, but the borders of the page haven't been painted
     700             :         // yet.
     701             :         // Oh well, with the inevitable following LayAction, the page doesn't
     702             :         // register itself, because it's (LayoutFrm) flags have been reset
     703             :         // already - the border of the page will never be painted.
     704          17 :         SwPageFrm *pPg = pPage;
     705          17 :         XCHECKPAGE;
     706          17 :         const SwRect &rVis = pImp->GetShell()->VisArea();
     707             : 
     708          44 :         while( pPg && pPg->Frm().Bottom() < rVis.Top() )
     709          10 :             pPg = (SwPageFrm*)pPg->GetNext();
     710          17 :         if( pPg != pPage )
     711           4 :             pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
     712             : 
     713             :         // set flag for interrupt content formatting
     714          17 :         mbFormatCntntOnInterrupt = IsInput();
     715          17 :         long nBottom = rVis.Bottom();
     716             :         // #i42586# - format current page, if idle action is active
     717             :         // This is an optimization for the case that the interrupt is created by
     718             :         // the move of a form control object, which is represented by a window.
     719          92 :         while ( pPg && ( pPg->Frm().Top() < nBottom ||
     720          32 :                          ( IsIdle() && pPg == pPage ) ) )
     721             :         {
     722          21 :             unlockPositionOfObjects( pPg );
     723             : 
     724          21 :             XCHECKPAGE;
     725             : 
     726             :             // #i81146# new loop control
     727          21 :             sal_uInt16 nLoopControlRuns_2 = 0;
     728          21 :             const sal_uInt16 nLoopControlMax = 20;
     729             : 
     730             :             // special case: interrupt content formatting
     731             :             // #i28701# - conditions are incorrect (macros IS_FLYS and IS_INVAFLY only
     732             :             //            works for <pPage>) and are too strict.
     733             :             // #i50432# - adjust interrupt formatting to normal page formatting - see above.
     734          63 :             while ( ( mbFormatCntntOnInterrupt &&
     735          25 :                       ( pPg->IsInvalid() ||
     736          46 :                         ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
     737           4 :                     ( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
     738             :             {
     739          17 :                 XCHECKPAGE;
     740             :                 // #i50432# - format also at-page anchored objects
     741          17 :                 SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
     742          17 :                 if ( !pPg->GetSortedObjs() )
     743             :                 {
     744          13 :                     pPg->ValidateFlyLayout();
     745          13 :                     pPg->ValidateFlyCntnt();
     746             :                 }
     747             : 
     748             :                 // #i81146# new loop control
     749          17 :                 sal_uInt16 nLoopControlRuns_3 = 0;
     750             : 
     751          34 :                 while ( pPg->IsInvalidLayout() )
     752             :                 {
     753           0 :                     pPg->ValidateLayout();
     754             : 
     755           0 :                     if ( ++nLoopControlRuns_3 > nLoopControlMax )
     756             :                     {
     757             :                         OSL_FAIL( "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" );
     758           0 :                         break;
     759             :                     }
     760             : 
     761           0 :                     FormatLayout( pPg );
     762           0 :                     XCHECKPAGE;
     763             :                 }
     764             : 
     765             :                 // #i50432#
     766          51 :                 if ( mbFormatCntntOnInterrupt &&
     767          17 :                      ( pPg->IsInvalidCntnt() ||
     768           0 :                        ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
     769             :                 {
     770          17 :                     pPg->ValidateFlyInCnt();
     771          17 :                     pPg->ValidateCntnt();
     772             :                     // #i26945#
     773          17 :                     pPg->ValidateFlyLayout();
     774          17 :                     pPg->ValidateFlyCntnt();
     775             : 
     776          17 :                     if ( ++nLoopControlRuns_2 > nLoopControlMax )
     777             :                     {
     778             :                         OSL_FAIL( "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" );
     779           0 :                         break;
     780             :                     }
     781             : 
     782          17 :                     if ( !FormatCntnt( pPg ) )
     783             :                     {
     784           0 :                         XCHECKPAGE;
     785           0 :                         pPg->InvalidateCntnt();
     786           0 :                         pPg->InvalidateFlyInCnt();
     787             :                         // #i26945#
     788           0 :                         pPg->InvalidateFlyLayout();
     789           0 :                         pPg->InvalidateFlyCntnt();
     790             :                     }
     791             :                     // #i46807# - we are statisfied, if the content is formatted once complete.
     792             :                     else
     793             :                     {
     794          17 :                         break;
     795             :                     }
     796             :                 }
     797             :             }
     798             : 
     799          21 :             unlockPositionOfObjects( pPg );
     800          21 :             pPg = (SwPageFrm*)pPg->GetNext();
     801             :         }
     802             :         // reset flag for special interrupt content formatting.
     803          17 :         mbFormatCntntOnInterrupt = false;
     804             :     }
     805       68052 :     pOptTab = 0;
     806       68052 :     if( bNoLoop )
     807       18314 :         pLayoutAccess->GetLayouter()->EndLoopControl();
     808             : }
     809             : 
     810        8286 : bool SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
     811             : {
     812             : 
     813        8286 :     const SwPageFrm *pPage = 0;
     814        8286 :     if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
     815             :     {
     816        8282 :         const SwRect aOldRect( pCnt->UnionFrm( true ) );
     817        8282 :         const long   nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
     818        8282 :         pCnt->Calc();
     819        8282 :         if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
     820          84 :             pCnt->SetRetouche();
     821             : 
     822        8282 :         pPage = pCnt->FindPageFrm();
     823        8282 :         PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
     824             : 
     825        8282 :         if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
     826             :         {
     827         414 :             const sal_uLong nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
     828         414 :             ((SwTxtFrm*)pCnt)->RecalcAllLines();
     829         414 :             if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
     830             :             {
     831          28 :                 if ( IsPaintExtraData() )
     832           0 :                     pImp->GetShell()->AddPaintRect( pCnt->Frm() );
     833             :                 // This is to calculate the remaining LineNums on the page,
     834             :                 // and we don't stop processing here. To perform this inside RecalcAllLines
     835             :                 // would be expensive, because we would have to notify the page even
     836             :                 // in unnecessary cases (normal actions).
     837          28 :                 const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
     838          70 :                 while ( pNxt &&
     839          28 :                         (pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
     840           0 :                     pNxt = pNxt->GetNextCntntFrm();
     841          28 :                 if ( pNxt )
     842          14 :                     pNxt->InvalidatePage();
     843             :             }
     844         922 :             return false;
     845             :         }
     846             : 
     847        7868 :         if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
     848          94 :             return false;
     849             :     }
     850        7778 :     if ( !pPage )
     851           4 :         pPage = pCnt->FindPageFrm();
     852             : 
     853             :     // OD 2004-05-10 #i28701# - format floating screen objects at content frame.
     854       15548 :     if ( pCnt->IsTxtFrm() &&
     855             :          !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
     856        7770 :                                               *pPage, this ) )
     857             :     {
     858           0 :         return false;
     859             :     }
     860             : 
     861        7778 :     if ( pPage->IsInvalidCntnt() )
     862         830 :         return false;
     863        6948 :     return true;
     864             : }
     865             : 
     866       45793 : bool SwLayAction::TurboAction()
     867             : {
     868       45793 :     bool bRet = true;
     869             : 
     870       45793 :     if ( pRoot->GetTurbo() )
     871             :     {
     872        8286 :         if ( !_TurboAction( pRoot->GetTurbo() ) )
     873             :         {
     874        1338 :             CheckIdleEnd();
     875        1338 :             bRet = false;
     876             :         }
     877        8286 :         pRoot->ResetTurbo();
     878             :     }
     879             :     else
     880       37507 :         bRet = false;
     881       45793 :     return bRet;
     882             : }
     883             : 
     884        1721 : static bool lcl_IsInvaLay( const SwFrm *pFrm, long nBottom )
     885             : {
     886        1721 :     if (
     887        3452 :          !pFrm->IsValid() ||
     888        1731 :          (pFrm->IsCompletePaint() && ( pFrm->Frm().Top() < nBottom ) )
     889             :        )
     890             :     {
     891          10 :         return true;
     892             :     }
     893        1711 :     return false;
     894             : }
     895             : 
     896        1148 : static const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
     897             : {
     898             :     OSL_ENSURE( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
     899             : 
     900        1148 :     if (lcl_IsInvaLay(pFrm, nBottom))
     901           8 :         return pFrm;
     902        1140 :     pFrm = ((SwLayoutFrm*)pFrm)->Lower();
     903        3418 :     while ( pFrm )
     904             :     {
     905        1142 :         if ( pFrm->IsLayoutFrm() )
     906             :         {
     907         573 :             if (lcl_IsInvaLay(pFrm, nBottom))
     908           2 :                 return pFrm;
     909             :             const SwFrm *pTmp;
     910         571 :             if ( 0 != (pTmp = lcl_FindFirstInvaLay( pFrm, nBottom )) )
     911           2 :                 return pTmp;
     912             :         }
     913        1138 :         pFrm = pFrm->GetNext();
     914             :     }
     915        1136 :     return 0;
     916             : }
     917             : 
     918          68 : static const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
     919             :                                      const SwCntntFrm *pFirst )
     920             : {
     921             :     const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
     922          68 :                                       pLay->ContainsCntnt();
     923         136 :     while ( pCnt )
     924             :     {
     925          64 :         if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
     926             :         {
     927          50 :             if ( pCnt->Frm().Top() <= nBottom )
     928          50 :                 return pCnt;
     929             :         }
     930             : 
     931          14 :         if ( pCnt->GetDrawObjs() )
     932             :         {
     933           6 :             const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
     934          12 :             for ( size_t i = 0; i < rObjs.size(); ++i )
     935             :             {
     936           6 :                 const SwAnchoredObject* pObj = rObjs[i];
     937           6 :                 if ( pObj->ISA(SwFlyFrm) )
     938             :                 {
     939           0 :                     const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
     940           0 :                     if ( pFly->IsFlyInCntFrm() )
     941             :                     {
     942           0 :                         if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
     943           0 :                              pFly->IsCompletePaint() )
     944             :                         {
     945           0 :                             if ( pFly->Frm().Top() <= nBottom )
     946           0 :                                 return pFly;
     947             :                         }
     948           0 :                         const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
     949           0 :                         if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
     950           0 :                             return pFrm;
     951             :                     }
     952             :                 }
     953             :             }
     954             :         }
     955          14 :         if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
     956          14 :             return 0;
     957           0 :         pCnt = pCnt->GetNextCntntFrm();
     958           0 :         if ( !pLay->IsAnLower( pCnt ) )
     959           0 :             break;
     960             :     }
     961           4 :     return 0;
     962             : }
     963             : 
     964             : // #i37877# - consider drawing objects
     965           2 : static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
     966             :                                               long _nBottom )
     967             : {
     968             :     OSL_ENSURE( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" );
     969             : 
     970           4 :     for ( size_t i = 0; i < _pPage->GetSortedObjs()->size(); ++i )
     971             :     {
     972           2 :         const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
     973           2 :         if ( pObj->ISA(SwFlyFrm) )
     974             :         {
     975           2 :             const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
     976           2 :             if ( pFly->Frm().Top() <= _nBottom )
     977             :             {
     978           0 :                 if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
     979           0 :                     return pFly;
     980             : 
     981             :                 const SwFrm* pTmp;
     982           0 :                 if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
     983           0 :                      pTmp->Frm().Top() <= _nBottom )
     984           0 :                     return pFly;
     985             :             }
     986             :         }
     987           0 :         else if ( pObj->ISA(SwAnchoredDrawObject) )
     988             :         {
     989           0 :             if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
     990             :             {
     991           0 :                 return pObj;
     992             :             }
     993             :         }
     994             :     }
     995           2 :     return 0;
     996             : }
     997             : 
     998             : /* Returns True if the page lies directly below or right of the visible area.
     999             :  *
    1000             :  * It's possible for things to change in such a way that the processing
    1001             :  * (of the caller!) has to continue with the predecessor of the passed page.
    1002             :  * The parameter might therefore get modified!
    1003             :  * For BrowseMode, you may even activate the ShortCut if the invalid content
    1004             :  * of the page lies below the visible area.
    1005             :  */
    1006       21912 : bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
    1007             : {
    1008       21912 :     bool bRet = false;
    1009       21912 :     const SwViewShell *pSh = pRoot->GetCurrShell();
    1010       21912 :     const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
    1011             : 
    1012             :     // If the page is not valid, we quickly format it, otherwise
    1013             :     // there's gonna be no end of trouble
    1014       21912 :     if ( !prPage->IsValid() )
    1015             :     {
    1016         300 :         if ( bBrowse )
    1017             :         {
    1018             :             // OD 15.10.2002 #103517# - format complete page
    1019             :             // Thus, loop on all lowers of the page <prPage>, instead of only
    1020             :             // format its first lower.
    1021             :             // NOTE: In online layout (bBrowse == true) a page can contain
    1022             :             //     a header frame and/or a footer frame beside the body frame.
    1023         182 :             prPage->Calc();
    1024         182 :             SwFrm* pPageLowerFrm = prPage->Lower();
    1025         546 :             while ( pPageLowerFrm )
    1026             :             {
    1027         182 :                 pPageLowerFrm->Calc();
    1028         182 :                 pPageLowerFrm = pPageLowerFrm->GetNext();
    1029             :             }
    1030             :         }
    1031             :         else
    1032         118 :             FormatLayout( prPage );
    1033         300 :         if ( IsAgain() )
    1034           0 :             return false;
    1035             :     }
    1036             : 
    1037       21912 :     const SwRect &rVis = pImp->GetShell()->VisArea();
    1038       30490 :     if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
    1039        8578 :          (prPage->Frm().Left()>= rVis.Right()) )
    1040             :     {
    1041       13334 :         bRet = true;
    1042             : 
    1043             :         // This is going to be a bit nasty: The first CntntFrm of this
    1044             :         // page in the Body text needs formatting; if it changes the page during
    1045             :         // that process, I need to start over a page further back, because we
    1046             :         // have been processing a PageBreak.
    1047             :         // Even more uncomfortable: The next CntntFrm must be formatted,
    1048             :         // because it's possible for empty pages to exist temporarily (for example
    1049             :         // a paragraph across multiple pages gets deleted or reduced in size).
    1050             : 
    1051             :         // This is irrelevant for the browser, if the last Cnt above it
    1052             :         // isn't visible anymore.
    1053             : 
    1054       13334 :         const SwPageFrm *p2ndPage = prPage;
    1055             :         const SwCntntFrm *pCntnt;
    1056       13334 :         const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
    1057       13334 :         if( p2ndPage->IsFtnPage() && pBody )
    1058         165 :             pBody = (SwLayoutFrm*)pBody->GetNext();
    1059       13334 :         pCntnt = pBody ? pBody->ContainsCntnt() : 0;
    1060       27002 :         while ( p2ndPage && !pCntnt )
    1061             :         {
    1062         334 :             p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
    1063         334 :             if( p2ndPage )
    1064             :             {
    1065         278 :                 pBody = p2ndPage->FindBodyCont();
    1066         278 :                 if( p2ndPage->IsFtnPage() && pBody )
    1067           0 :                     pBody = (SwLayoutFrm*)pBody->GetNext();
    1068         278 :                 pCntnt = pBody ? pBody->ContainsCntnt() : 0;
    1069             :             }
    1070             :         }
    1071       13334 :         if ( pCntnt )
    1072             :         {
    1073       13278 :             bool bTstCnt = true;
    1074       13278 :             if ( bBrowse )
    1075             :             {
    1076             :                 // Is the Cnt before already invisible?
    1077          16 :                 const SwFrm *pLst = pCntnt;
    1078          16 :                 if ( pLst->IsInTab() )
    1079           0 :                     pLst = pCntnt->FindTabFrm();
    1080          16 :                 if ( pLst->IsInSct() )
    1081           0 :                     pLst = pCntnt->FindSctFrm();
    1082          16 :                 pLst = pLst->FindPrev();
    1083          16 :                 if ( pLst &&
    1084           0 :                      (pLst->Frm().Top() >= rVis.Bottom() ||
    1085           0 :                       pLst->Frm().Left()>= rVis.Right()) )
    1086             :                 {
    1087           0 :                     bTstCnt = false;
    1088             :                 }
    1089             :             }
    1090             : 
    1091       13278 :             if ( bTstCnt )
    1092             :             {
    1093             :                 // #i27756# - check after each frame calculation,
    1094             :                 // if the content frame has changed the page. If yes, no other
    1095             :                 // frame calculation is performed
    1096       13278 :                 bool bPageChg = false;
    1097             : 
    1098       13278 :                 if ( pCntnt->IsInSct() )
    1099             :                 {
    1100         730 :                     const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
    1101         730 :                     if ( !pSct->IsValid() )
    1102             :                     {
    1103         240 :                         pSct->Calc();
    1104         240 :                         pSct->SetCompletePaint();
    1105         240 :                         if ( IsAgain() )
    1106           0 :                             return false;
    1107             :                         // #i27756#
    1108         262 :                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
    1109         262 :                                    prPage->GetPrev();
    1110             :                     }
    1111             :                 }
    1112             : 
    1113       13278 :                 if ( !bPageChg && !pCntnt->IsValid() )
    1114             :                 {
    1115        2416 :                     pCntnt->Calc();
    1116        2416 :                     pCntnt->SetCompletePaint();
    1117        2416 :                     if ( IsAgain() )
    1118          12 :                         return false;
    1119             :                     // #i27756#
    1120        3386 :                     bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
    1121        3386 :                                prPage->GetPrev();
    1122             :                 }
    1123             : 
    1124       13266 :                 if ( !bPageChg && pCntnt->IsInTab() )
    1125             :                 {
    1126         660 :                     const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
    1127         660 :                     if ( !pTab->IsValid() )
    1128             :                     {
    1129          48 :                         pTab->Calc();
    1130          48 :                         pTab->SetCompletePaint();
    1131          48 :                         if ( IsAgain() )
    1132           0 :                             return false;
    1133             :                         // #i27756#
    1134          48 :                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
    1135          48 :                                    prPage->GetPrev();
    1136             :                     }
    1137             :                 }
    1138             : 
    1139       13266 :                 if ( !bPageChg && pCntnt->IsInSct() )
    1140             :                 {
    1141         400 :                     const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
    1142         400 :                     if ( !pSct->IsValid() )
    1143             :                     {
    1144           0 :                         pSct->Calc();
    1145           0 :                         pSct->SetCompletePaint();
    1146           0 :                         if ( IsAgain() )
    1147           0 :                             return false;
    1148             :                         // #i27756#
    1149           0 :                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
    1150           0 :                                    prPage->GetPrev();
    1151             :                     }
    1152             :                 }
    1153             : 
    1154             :                 // #i27756#
    1155       13266 :                 if ( bPageChg )
    1156             :                 {
    1157        1000 :                     bRet = false;
    1158        1000 :                     const SwPageFrm* pTmp = pCntnt->FindPageFrm();
    1159        1962 :                     if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
    1160         962 :                          pTmp->IsInvalid() )
    1161             :                     {
    1162         962 :                         prPage = (SwPageFrm*)pTmp;
    1163             :                     }
    1164             :                     else
    1165             :                     {
    1166          38 :                         prPage = (SwPageFrm*)prPage->GetPrev();
    1167             :                     }
    1168             :                 }
    1169             :                 // #121980# - no shortcut, if at previous page
    1170             :                 // an anchored object is registered, whose anchor is <pCntnt>.
    1171       12266 :                 else if ( prPage->GetPrev() )
    1172             :                 {
    1173             :                     SwSortedObjs* pObjs =
    1174        7284 :                         static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
    1175        7284 :                     if ( pObjs )
    1176             :                     {
    1177       10165 :                         for ( size_t i = 0; i < pObjs->size(); ++i )
    1178             :                         {
    1179        9248 :                             SwAnchoredObject* pObj = (*pObjs)[i];
    1180        9248 :                             if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
    1181             :                             {
    1182           4 :                                 bRet = false;
    1183           4 :                                 break;
    1184             :                             }
    1185             :                         }
    1186             :                     }
    1187             :                 }
    1188             :             }
    1189             :         }
    1190             :     }
    1191             : 
    1192       21900 :     if ( !bRet && bBrowse )
    1193             :     {
    1194         575 :         const long nBottom = rVis.Bottom();
    1195         575 :         const SwAnchoredObject* pObj( 0L );
    1196        2302 :         if ( prPage->GetSortedObjs() &&
    1197           4 :              (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
    1198        1152 :              0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
    1199         575 :              pObj->GetObjRect().Top() <= nBottom )
    1200             :         {
    1201           0 :             return false;
    1202             :         }
    1203         575 :         const SwFrm* pFrm( 0L );
    1204        1725 :         if ( prPage->IsInvalidLayout() &&
    1205         583 :              0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
    1206           8 :              pFrm->Frm().Top() <= nBottom )
    1207             :         {
    1208           8 :             return false;
    1209             :         }
    1210        1701 :         if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
    1211         643 :              0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
    1212          38 :              pFrm->Frm().Top() <= nBottom )
    1213             :         {
    1214          38 :             return false;
    1215             :         }
    1216         529 :         bRet = true;
    1217             :     }
    1218       21854 :     return bRet;
    1219             : }
    1220             : 
    1221             : // OD 15.11.2002 #105155# - introduce support for vertical layout
    1222      101412 : bool SwLayAction::FormatLayout( SwLayoutFrm *pLay, bool bAddRect )
    1223             : {
    1224             :     OSL_ENSURE( !IsAgain(), "Attention to the invalid page." );
    1225      101412 :     if ( IsAgain() )
    1226           0 :         return false;
    1227             : 
    1228      101412 :     bool bChanged = false;
    1229      101412 :     bool bAlreadyPainted = false;
    1230             :     // OD 11.11.2002 #104414# - remember frame at complete paint
    1231      101412 :     SwRect aFrmAtCompletePaint;
    1232             : 
    1233      101412 :     if ( !pLay->IsValid() || pLay->IsCompletePaint() )
    1234             :     {
    1235       55630 :         if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
    1236        3208 :             pLay->GetPrev()->SetCompletePaint();
    1237             : 
    1238       55630 :         SwRect aOldFrame( pLay->Frm() );
    1239       55630 :         SwRect aOldRect( aOldFrame );
    1240       55630 :         if( pLay->IsPageFrm() )
    1241             :         {
    1242        7305 :             aOldRect = static_cast<SwPageFrm*>(pLay)->GetBoundRect();
    1243             :         }
    1244             : 
    1245       55630 :         pLay->Calc();
    1246       55630 :         if ( aOldFrame != pLay->Frm() )
    1247       16690 :             bChanged = true;
    1248             : 
    1249       55630 :         bool bNoPaint = false;
    1250      119497 :         if ( pLay->IsPageBodyFrm() &&
    1251       63541 :              pLay->Frm().Pos() == aOldRect.Pos() &&
    1252        7911 :              pLay->Lower() )
    1253             :         {
    1254        7213 :             const SwViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
    1255             :             // Limitations because of headers / footers
    1256        7229 :             if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
    1257          16 :                 !( pLay->IsCompletePaint() && pLay->FindPageFrm()->FindFtnCont() ) )
    1258           8 :                 bNoPaint = true;
    1259             :         }
    1260             : 
    1261       55630 :         if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
    1262             :         {
    1263        1113 :             SwRect aPaint( pLay->Frm() );
    1264             :             // OD 13.02.2003 #i9719#, #105645# - consider border and shadow for
    1265             :             // page frames -> enlarge paint rectangle correspondingly.
    1266        1113 :             if ( pLay->IsPageFrm() )
    1267             :             {
    1268         347 :                 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
    1269         347 :                 aPaint = pPageFrm->GetBoundRect();
    1270             :             }
    1271             : 
    1272        1113 :             bool bPageInBrowseMode = pLay->IsPageFrm();
    1273        1113 :             if( bPageInBrowseMode )
    1274             :             {
    1275         347 :                 const SwViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
    1276         347 :                 if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
    1277         337 :                     bPageInBrowseMode = false;
    1278             :             }
    1279        1113 :             if( bPageInBrowseMode )
    1280             :             {
    1281             :                 // NOTE: no vertical layout in online layout
    1282             :                 // Is the change even visible?
    1283          10 :                 if ( pLay->IsCompletePaint() )
    1284             :                 {
    1285          10 :                     pImp->GetShell()->AddPaintRect( aPaint );
    1286          10 :                     bAddRect = false;
    1287             :                 }
    1288             :                 else
    1289             :                 {
    1290             :                     sal_uInt16 i;
    1291             : 
    1292           0 :                     SwRegionRects aRegion( aOldRect );
    1293           0 :                     aRegion -= aPaint;
    1294           0 :                     for ( i = 0; i < aRegion.size(); ++i )
    1295           0 :                         pImp->GetShell()->AddPaintRect( aRegion[i] );
    1296           0 :                     aRegion.ChangeOrigin( aPaint );
    1297           0 :                     aRegion.clear();
    1298           0 :                     aRegion.push_back( aPaint );
    1299           0 :                     aRegion -= aOldRect;
    1300           0 :                     for ( i = 0; i < aRegion.size(); ++i )
    1301           0 :                         pImp->GetShell()->AddPaintRect( aRegion[i] );
    1302             :                 }
    1303             :             }
    1304             :             else
    1305             :             {
    1306        1103 :                 pImp->GetShell()->AddPaintRect( aPaint );
    1307        1103 :                 bAlreadyPainted = true;
    1308             :                 // OD 11.11.2002 #104414# - remember frame at complete paint
    1309        1103 :                 aFrmAtCompletePaint = pLay->Frm();
    1310             :             }
    1311             : 
    1312             :             // OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
    1313             :             // between pages (not only for in online mode).
    1314        1113 :             if ( pLay->IsPageFrm() )
    1315             :             {
    1316         347 :                 const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
    1317         347 :                 const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
    1318         347 :                 const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
    1319         347 :                 const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
    1320         347 :                 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
    1321         347 :                 const SwViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
    1322         347 :                 SwRect aPageRect( pLay->Frm() );
    1323             : 
    1324         347 :                 if(pSh)
    1325             :                 {
    1326             :                     SwPageFrm::GetBorderAndShadowBoundRect(aPageRect, pSh,
    1327         694 :                         aPageRect, pPageFrm->IsLeftShadowNeeded(), pPageFrm->IsRightShadowNeeded(),
    1328        1041 :                         pPageFrm->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
    1329             :                 }
    1330             : 
    1331         347 :                 if ( bPrev )
    1332             :                 {
    1333             :                     // top
    1334         223 :                     SwRect aSpaceToPrevPage( aPageRect );
    1335         223 :                     aSpaceToPrevPage.Top( aSpaceToPrevPage.Top() - nHalfDocBorder );
    1336         223 :                     aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
    1337         223 :                     if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
    1338         223 :                         pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
    1339             : 
    1340         223 :                     if (pSh)
    1341         223 :                         pSh->GetOut()->DrawRect( aSpaceToPrevPage.SVRect() );
    1342             : 
    1343             :                     // left
    1344         223 :                     aSpaceToPrevPage = aPageRect;
    1345         223 :                     aSpaceToPrevPage.Left( aSpaceToPrevPage.Left() - nHalfDocBorder );
    1346         223 :                     aSpaceToPrevPage.Right( pLay->Frm().Left() );
    1347         223 :                     if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
    1348         223 :                         pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
    1349             :                 }
    1350         347 :                 if ( bNext )
    1351             :                 {
    1352             :                     // bottom
    1353         147 :                     SwRect aSpaceToNextPage( aPageRect );
    1354         147 :                     aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
    1355         147 :                     aSpaceToNextPage.Top( pLay->Frm().Bottom() );
    1356         147 :                     if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
    1357         147 :                         pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
    1358             : 
    1359             :                     // right
    1360         147 :                     aSpaceToNextPage = aPageRect;
    1361         147 :                     aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
    1362         147 :                     aSpaceToNextPage.Left( pLay->Frm().Right() );
    1363         147 :                     if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
    1364         147 :                         pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
    1365             :                 }
    1366             :             }
    1367             :         }
    1368       55630 :         pLay->ResetCompletePaint();
    1369             :     }
    1370             : 
    1371      228341 :     if ( IsPaint() && bAddRect &&
    1372      116647 :          !pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
    1373             :     {
    1374             :         // OD 15.11.2002 #105155# - vertical layout support
    1375          24 :         SWRECTFN( pLay );
    1376          24 :         SwRect aRect( pLay->GetUpper()->PaintArea() );
    1377          24 :         (aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
    1378          24 :         if ( !pImp->GetShell()->AddPaintRect( aRect ) )
    1379          16 :             pLay->ResetRetouche();
    1380             :     }
    1381             : 
    1382      101412 :     if( bAlreadyPainted )
    1383        1103 :         bAddRect = false;
    1384             : 
    1385      101412 :     CheckWaitCrsr();
    1386             : 
    1387      101412 :     if ( IsAgain() )
    1388           0 :         return false;
    1389             : 
    1390             :     // Now, deal with the lowers that are LayoutFrms
    1391             : 
    1392      101412 :     if ( pLay->IsFtnFrm() ) // no LayFrms as Lower
    1393         322 :         return bChanged;
    1394             : 
    1395      101090 :     SwFrm *pLow = pLay->Lower();
    1396      101090 :     bool bTabChanged = false;
    1397      399052 :     while ( pLow && pLow->GetUpper() == pLay )
    1398             :     {
    1399      196872 :         if ( pLow->IsLayoutFrm() )
    1400             :         {
    1401       75226 :             if ( pLow->IsTabFrm() )
    1402        3756 :                 bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
    1403             :             // Skip the ones already registered for deletion
    1404       71470 :             else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
    1405       71454 :                 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
    1406             :         }
    1407      121646 :         else if ( pImp->GetShell()->IsPaintLocked() )
    1408             :             // Shortcut to minimize the cycles. With Lock, the
    1409             :             // paint is coming either way (primarily for browse)
    1410       53240 :             pLow->OptCalc();
    1411             : 
    1412      196872 :         if ( IsAgain() )
    1413           0 :             return false;
    1414      196872 :         pLow = pLow->GetNext();
    1415             :     }
    1416             :     // OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
    1417             :     // area has been already added and after formatting its lowers the frame area
    1418             :     // is enlarged.
    1419      101090 :     SwRect aBoundRect(pLay->IsPageFrm() ? static_cast<SwPageFrm*>(pLay)->GetBoundRect() : pLay->Frm() );
    1420             : 
    1421      102530 :     if ( bAlreadyPainted &&
    1422        1869 :          ( aBoundRect.Width() > aFrmAtCompletePaint.Width() ||
    1423         766 :            aBoundRect.Height() > aFrmAtCompletePaint.Height() )
    1424             :        )
    1425             :     {
    1426         337 :         pImp->GetShell()->AddPaintRect( aBoundRect );
    1427             :     }
    1428      101090 :     return bChanged || bTabChanged;
    1429             : }
    1430             : 
    1431       10750 : bool SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
    1432             : {
    1433             :     OSL_ENSURE( !IsAgain(), "Attention to the invalid page." );
    1434       10750 :     if ( IsAgain() )
    1435           0 :         return false;
    1436             : 
    1437       10750 :     bool bChanged = false;
    1438       10750 :     bool bAddRect = true;
    1439             : 
    1440       10750 :     if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
    1441             :     {
    1442             :         // The Frame has changed, now it's getting formatted.
    1443        5932 :         const SwRect aOldRect( pFly->Frm() );
    1444        5932 :         pFly->Calc();
    1445        5932 :         bChanged = aOldRect != pFly->Frm();
    1446             : 
    1447       12785 :         if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
    1448        6790 :                     pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
    1449         427 :             pImp->GetShell()->AddPaintRect( pFly->Frm() );
    1450             : 
    1451        5932 :         if ( bChanged )
    1452        1720 :             pFly->Invalidate();
    1453             :         else
    1454        4212 :             pFly->Validate();
    1455             : 
    1456        5932 :         bAddRect = false;
    1457        5932 :         pFly->ResetCompletePaint();
    1458             :     }
    1459             : 
    1460       10750 :     if ( IsAgain() )
    1461           0 :         return false;
    1462             : 
    1463             :     // Now, deal with the lowers that are LayoutFrms
    1464       10750 :     bool bTabChanged = false;
    1465       10750 :     SwFrm *pLow = pFly->Lower();
    1466       34852 :     while ( pLow )
    1467             :     {
    1468       13352 :         if ( pLow->IsLayoutFrm() )
    1469             :         {
    1470         732 :             if ( pLow->IsTabFrm() )
    1471         424 :                 bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
    1472             :             else
    1473         308 :                 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
    1474             :         }
    1475       13352 :         pLow = pLow->GetNext();
    1476             :     }
    1477       10750 :     return bChanged || bTabChanged;
    1478             : }
    1479             : 
    1480             : // OD 31.10.2002 #104100#
    1481             : // Implement vertical layout support
    1482        4180 : bool SwLayAction::FormatLayoutTab( SwTabFrm *pTab, bool bAddRect )
    1483             : {
    1484             :     OSL_ENSURE( !IsAgain(), "8-) Attention to the invalid page." );
    1485        4180 :     if ( IsAgain() || !pTab->Lower() )
    1486           0 :         return false;
    1487             : 
    1488        4180 :     IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
    1489        4180 :     pTimerAccess->BlockIdling();
    1490             : 
    1491        4180 :     bool bChanged = false;
    1492        4180 :     bool bPainted = false;
    1493             : 
    1494        4180 :     const SwPageFrm *pOldPage = pTab->FindPageFrm();
    1495             : 
    1496             :     // OD 31.10.2002 #104100# - vertical layout support
    1497             :     // use macro to declare and init <bool bVert>, <bool bRev> and
    1498             :     // <SwRectFn fnRect> for table frame <pTab>.
    1499        4180 :     SWRECTFN( pTab );
    1500             : 
    1501        4180 :     if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
    1502             :     {
    1503        3878 :         if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
    1504             :         {
    1505         128 :             pTab->GetPrev()->SetCompletePaint();
    1506             :         }
    1507             : 
    1508        3878 :         const SwRect aOldRect( pTab->Frm() );
    1509        3878 :         pTab->SetLowersFormatted( false );
    1510        3878 :         pTab->Calc();
    1511        3878 :         if ( aOldRect != pTab->Frm() )
    1512             :         {
    1513        1124 :             bChanged = true;
    1514             :         }
    1515        3878 :         const SwRect aPaintFrm = pTab->PaintArea();
    1516             : 
    1517        3878 :         if ( IsPaint() && bAddRect )
    1518             :         {
    1519             :             // OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
    1520        1088 :             if ( !pTab->IsCompletePaint() &&
    1521         564 :                  pTab->IsComplete() &&
    1522         276 :                  ( pTab->Frm().SSize() != pTab->Prt().SSize() ||
    1523             :                    // OD 31.10.2002 #104100# - vertical layout support
    1524         676 :                    (pTab->*fnRect->fnGetLeftMargin)() ) &&
    1525         276 :                  pTab->Frm().HasArea()
    1526             :                )
    1527             :             {
    1528             :                 // OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
    1529         270 :                 SwRect aMarginRect;
    1530             : 
    1531         270 :                 SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
    1532         270 :                 if ( nLeftMargin > 0)
    1533             :                 {
    1534          14 :                     aMarginRect = pTab->Frm();
    1535          14 :                     (aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
    1536          14 :                     pImp->GetShell()->AddPaintRect( aMarginRect );
    1537             :                 }
    1538             : 
    1539         270 :                 if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
    1540             :                 {
    1541          52 :                     aMarginRect = pTab->Frm();
    1542          52 :                     (aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
    1543          52 :                     pImp->GetShell()->AddPaintRect( aMarginRect );
    1544             :                 }
    1545             : 
    1546         270 :                 SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
    1547         270 :                 if ( nTopMargin > 0)
    1548             :                 {
    1549          34 :                     aMarginRect = pTab->Frm();
    1550          34 :                     (aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
    1551          34 :                     pImp->GetShell()->AddPaintRect( aMarginRect );
    1552             :                 }
    1553             : 
    1554         270 :                 if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
    1555             :                 {
    1556         260 :                     aMarginRect = pTab->Frm();
    1557         260 :                     (aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
    1558         260 :                     pImp->GetShell()->AddPaintRect( aMarginRect );
    1559             :                 }
    1560             :             }
    1561         130 :             else if ( pTab->IsCompletePaint() )
    1562             :             {
    1563         112 :                 pImp->GetShell()->AddPaintRect( aPaintFrm );
    1564         112 :                 bAddRect = false;
    1565         112 :                 bPainted = true;
    1566             :             }
    1567             : 
    1568         400 :             if ( pTab->IsRetouche() && !pTab->GetNext() )
    1569             :             {
    1570          66 :                 SwRect aRect( pTab->GetUpper()->PaintArea() );
    1571             :                 // OD 04.11.2002 #104100# - vertical layout support
    1572          66 :                 (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
    1573          66 :                 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
    1574           6 :                     pTab->ResetRetouche();
    1575             :             }
    1576             :         }
    1577             :         else
    1578        3478 :             bAddRect = false;
    1579             : 
    1580        3878 :         if ( pTab->IsCompletePaint() && !pOptTab )
    1581         992 :             pOptTab = pTab;
    1582        3878 :         pTab->ResetCompletePaint();
    1583             :     }
    1584        4180 :     if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
    1585             :     {
    1586             :         // OD 04.10.2002 #102779#
    1587             :         // set correct rectangle for retouche: area between bottom of table frame
    1588             :         // and bottom of paint area of the upper frame.
    1589          58 :         SwRect aRect( pTab->GetUpper()->PaintArea() );
    1590             :         // OD 04.11.2002 #104100# - vertical layout support
    1591          58 :         (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
    1592          58 :         if ( !pImp->GetShell()->AddPaintRect( aRect ) )
    1593           0 :             pTab->ResetRetouche();
    1594             :     }
    1595             : 
    1596        4180 :     CheckWaitCrsr();
    1597             : 
    1598        4180 :     pTimerAccess->UnblockIdling();
    1599             : 
    1600             :     // Ugly shortcut!
    1601        4294 :     if ( pTab->IsLowersFormatted() &&
    1602         106 :          (bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
    1603         114 :         return false;
    1604             : 
    1605             :     // Now, deal with the lowers
    1606        4066 :     if ( IsAgain() )
    1607           0 :         return false;
    1608             : 
    1609             :     // OD 20.10.2003 #112464# - for savety reasons:
    1610             :     // check page number before formatting lowers.
    1611        4066 :     if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
    1612           2 :         SetNextCycle( true );
    1613             : 
    1614             :     // OD 20.10.2003 #112464# - format lowers, only if table frame is valid
    1615        4066 :     if ( pTab->IsValid() )
    1616             :     {
    1617        4066 :         SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
    1618       26940 :         while ( pLow )
    1619             :         {
    1620       18808 :             bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
    1621       18808 :             if ( IsAgain() )
    1622           0 :                 return false;
    1623       18808 :             pLow = (SwLayoutFrm*)pLow->GetNext();
    1624             :         }
    1625             :     }
    1626             : 
    1627        4066 :     return bChanged;
    1628             : }
    1629             : 
    1630       17656 : bool SwLayAction::FormatCntnt( const SwPageFrm *pPage )
    1631             : {
    1632       17656 :     const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
    1633       17656 :     const SwViewShell *pSh = pRoot->GetCurrShell();
    1634       17656 :     const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
    1635             : 
    1636      186732 :     while ( pCntnt && pPage->IsAnLower( pCntnt ) )
    1637             :     {
    1638             :         // If the Cntnt didn't change, we can use a few shortcuts.
    1639      289168 :         const bool bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
    1640      179567 :                            pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
    1641      154263 :         if ( bFull )
    1642             :         {
    1643             :             // We do this so we don't have to search later on.
    1644      142826 :             const bool bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
    1645      142826 :             const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
    1646      142826 :             const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
    1647             : 
    1648      142826 :             const SwLayoutFrm*pOldUpper  = pCntnt->GetUpper();
    1649      142826 :             const SwTabFrm *pTab = pCntnt->FindTabFrm();
    1650      142826 :             const bool bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
    1651      142826 :             const bool bOldPaint = IsPaint();
    1652      142826 :             bPaint = bOldPaint && !(pTab && pTab == pOptTab);
    1653      142826 :             _FormatCntnt( pCntnt, pPage );
    1654             :             // #i26945# - reset <bPaint> before format objects
    1655      142826 :             bPaint = bOldPaint;
    1656             : 
    1657             :             // OD 2004-05-10 #i28701# - format floating screen object at content frame.
    1658             :             // No format, if action flag <bAgain> is set or action is interrupted.
    1659             :             // OD 2004-08-30 #117736# - allow format on interruption of action, if
    1660             :             // it's the format for this interrupt
    1661             :             // #i23129#, #i36347# - pass correct page frame
    1662             :             // to the object formatter.
    1663      428472 :             if ( !IsAgain() &&
    1664      285704 :                  ( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
    1665      428466 :                  pCntnt->IsTxtFrm() &&
    1666             :                  !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
    1667      142820 :                                                       *(pCntnt->FindPageFrm()), this ) )
    1668             :             {
    1669         574 :                 return false;
    1670             :             }
    1671             : 
    1672      142252 :             if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
    1673             :             {
    1674       58382 :                 const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
    1675       58382 :                 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
    1676       58450 :                 if ( IsPaintExtraData() && IsPaint() &&
    1677          68 :                      nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
    1678          56 :                     pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
    1679             :             }
    1680             : 
    1681      142252 :             if ( IsAgain() )
    1682           6 :                 return false;
    1683             : 
    1684             :             // Temporarily interrupt processing if layout or Flys become invalid again.
    1685             :             // However not for the BrowseView: The layout is getting invalid
    1686             :             // all the time because the page height gets adjusted.
    1687             :             // The same applies if the user wants to continue working and at least one
    1688             :             // paragraph has been processed.
    1689      142246 :             if ( (!pTab || (pTab && !bInValid)) )
    1690             :             {
    1691      108122 :                 CheckIdleEnd();
    1692             :                 // OD 14.04.2003 #106346# - consider interrupt formatting.
    1693      324430 :                 if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
    1694      433477 :                      ( !bBrowse && pPage->IsInvalidLayout() ) ||
    1695             :                      // OD 07.05.2003 #109435# - consider interrupt formatting
    1696      151068 :                      ( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
    1697             :                    )
    1698        2258 :                     return false;
    1699             :             }
    1700      139988 :             if ( pOldUpper != pCntnt->GetUpper() )
    1701             :             {
    1702        8972 :                 const sal_uInt16 nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
    1703        8972 :                 if (  nCurNum < pPage->GetPhyPageNum() )
    1704        8876 :                     nPreInvaPage = nCurNum;
    1705             : 
    1706             :                 // If the Frm flowed backwards more than one page, we need to
    1707             :                 // start over again from the beginning, so nothing gets left out.
    1708        8972 :                 if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
    1709             :                 {
    1710           0 :                     SetNextCycle( true );
    1711             :                     // OD 07.05.2003 #109435# - consider interrupt formatting
    1712           0 :                     if ( !mbFormatCntntOnInterrupt )
    1713             :                     {
    1714           0 :                         return false;
    1715             :                     }
    1716             :                 }
    1717             :             }
    1718             :             // If the Frame moved forwards to the next page, we re-run through
    1719             :             // the predecessor.
    1720             :             // This way, we catch predecessors which are now responsible for
    1721             :             // retouching, but the footers will be touched also.
    1722      139988 :             bool bSetCntnt = true;
    1723      139988 :             if ( pCntntPrev )
    1724             :             {
    1725       78836 :                 if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
    1726          88 :                     pPage->InvalidateCntnt();
    1727       78936 :                 if ( pOldUpper != pCntnt->GetUpper() &&
    1728         100 :                      pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
    1729             :                 {
    1730          94 :                     pCntnt = pCntntPrev;
    1731          94 :                     bSetCntnt = false;
    1732             :                 }
    1733             :             }
    1734      139988 :             if ( bSetCntnt )
    1735             :             {
    1736      139987 :                 if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
    1737          93 :                      pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
    1738             :                 {
    1739          18 :                     const long nBottom = pImp->GetShell()->VisArea().Bottom();
    1740             :                     const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
    1741          18 :                                                             nBottom, pCntnt );
    1742          18 :                     if ( !pTmp )
    1743             :                     {
    1744          18 :                         if ( (!(IS_FLYS && IS_INVAFLY) ||
    1745          16 :                               !lcl_FindFirstInvaObj( pPage, nBottom )) &&
    1746           8 :                               (!pPage->IsInvalidLayout() ||
    1747           2 :                                !lcl_FindFirstInvaLay( pPage, nBottom )))
    1748           4 :                             SetBrowseActionStop( true );
    1749             :                         // OD 14.04.2003 #106346# - consider interrupt formatting.
    1750           6 :                         if ( !mbFormatCntntOnInterrupt )
    1751             :                         {
    1752           2 :                             return false;
    1753             :                         }
    1754             :                     }
    1755             :                 }
    1756      139892 :                 pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
    1757             :             }
    1758             : 
    1759      139986 :             RESCHEDULE;
    1760             :         }
    1761             :         else
    1762             :         {
    1763       11437 :             if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
    1764             :             {
    1765          24 :                 const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
    1766          24 :                 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
    1767          24 :                 if ( IsPaintExtraData() && IsPaint() &&
    1768           0 :                      nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
    1769           0 :                     pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
    1770             :             }
    1771             : 
    1772             :             // Do this if the Frm has been formatted before.
    1773       12054 :             if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
    1774         617 :                   IsPaint() )
    1775         305 :                 PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
    1776       11437 :             if ( IsIdle() )
    1777             :             {
    1778          44 :                 CheckIdleEnd();
    1779             :                 // OD 14.04.2003 #106346# - consider interrupt formatting.
    1780          44 :                 if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
    1781           1 :                     return false;
    1782             :             }
    1783       11461 :             if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
    1784          25 :                  pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
    1785             :             {
    1786          12 :                 const long nBottom = pImp->GetShell()->VisArea().Bottom();
    1787             :                 const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
    1788          12 :                                                     nBottom, pCntnt );
    1789          12 :                 if ( !pTmp )
    1790             :                 {
    1791          36 :                     if ( (!(IS_FLYS && IS_INVAFLY) ||
    1792          36 :                             !lcl_FindFirstInvaObj( pPage, nBottom )) &&
    1793          12 :                             (!pPage->IsInvalidLayout() ||
    1794           0 :                             !lcl_FindFirstInvaLay( pPage, nBottom )))
    1795          12 :                         SetBrowseActionStop( true );
    1796             :                     // OD 14.04.2003 #106346# - consider interrupt formatting.
    1797          12 :                     if ( !mbFormatCntntOnInterrupt )
    1798             :                     {
    1799           2 :                         return false;
    1800             :                     }
    1801             :                 }
    1802             :             }
    1803       11434 :             pCntnt = pCntnt->GetNextCntntFrm();
    1804             :         }
    1805             :     }
    1806       14813 :     CheckWaitCrsr();
    1807             :     // OD 14.04.2003 #106346# - consider interrupt formatting.
    1808       14813 :     return !IsInterrupt() || mbFormatCntntOnInterrupt;
    1809             : }
    1810             : 
    1811      160622 : void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
    1812             :                                 const SwPageFrm  *pPage )
    1813             : {
    1814             :     // We probably only ended up here because the Cntnt holds DrawObjects.
    1815      163923 :     const bool bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
    1816      163923 :                          !pCntnt->IsRetouche();
    1817      160622 :     SWRECTFN( pCntnt )
    1818      160622 :     if ( !bDrawObjsOnly && IsPaint() )
    1819             :     {
    1820       20764 :         const SwRect aOldRect( pCntnt->UnionFrm() );
    1821       20764 :         const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
    1822       20764 :         pCntnt->OptCalc();
    1823       20764 :         if( IsAgain() )
    1824      160622 :             return;
    1825       62292 :         if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
    1826       62292 :                                 (aOldRect.*fnRect->fnGetBottom)() ) < 0 )
    1827             :         {
    1828         247 :             pCntnt->SetRetouche();
    1829             :         }
    1830       20764 :         PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
    1831             :     }
    1832             :     else
    1833             :     {
    1834      139858 :         if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
    1835          48 :             PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
    1836          96 :                         (pCntnt->Frm().*fnRect->fnGetBottom)() );
    1837      139858 :         pCntnt->OptCalc();
    1838             :     }
    1839             : }
    1840             : 
    1841             : /// Returns sal_True if all Cntnts of the Fly have been processed completely.
    1842             : /// Returns sal_False if processing has been interrupted prematurely.
    1843       10750 : bool SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
    1844             : {
    1845       10750 :     const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
    1846             : 
    1847       39296 :     while ( pCntnt )
    1848             :     {
    1849             :         // OD 2004-05-10 #i28701#
    1850       17796 :         _FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
    1851             : 
    1852             :         // #i28701# - format floating screen objects
    1853             :         // at content text frame
    1854             :         // #i23129#, #i36347# - pass correct page frame
    1855             :         // to the object formatter.
    1856       31977 :         if ( pCntnt->IsTxtFrm() &&
    1857             :              !SwObjectFormatter::FormatObjsAtFrm(
    1858             :                                             *(const_cast<SwCntntFrm*>(pCntnt)),
    1859       14181 :                                             *(pCntnt->FindPageFrm()), this ) )
    1860             :         {
    1861             :             // restart format with first content
    1862           0 :             pCntnt = pFly->ContainsCntnt();
    1863           0 :             continue;
    1864             :         }
    1865             : 
    1866       17796 :         if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
    1867             :         {
    1868        3728 :             const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
    1869        3728 :             ((SwTxtFrm*)pCntnt)->RecalcAllLines();
    1870        3728 :             if ( IsPaintExtraData() && IsPaint() &&
    1871           0 :                  nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
    1872           0 :                 pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
    1873             :         }
    1874             : 
    1875       17796 :         if ( IsAgain() )
    1876           0 :             return false;
    1877             : 
    1878             :         // If there's input, we interrupt processing.
    1879       17796 :         if ( !pFly->IsFlyInCntFrm() )
    1880             :         {
    1881       13323 :             CheckIdleEnd();
    1882             :             // OD 14.04.2003 #106346# - consider interrupt formatting.
    1883       13323 :             if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
    1884           0 :                 return false;
    1885             :         }
    1886       17796 :         pCntnt = pCntnt->GetNextCntntFrm();
    1887             :     }
    1888       10750 :     CheckWaitCrsr();
    1889             :     // OD 14.04.2003 #106346# - consider interrupt formatting.
    1890       10750 :     return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
    1891             : }
    1892             : 
    1893        4205 : bool SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
    1894             : {
    1895             :     OSL_ENSURE( pCnt->IsTxtFrm(), "NoTxt neighbour of Txt" );
    1896             :     // robust against misuse by e.g. #i52542#
    1897        4205 :     if( !pCnt->IsTxtFrm() )
    1898           0 :         return false;
    1899             : 
    1900        4205 :     const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
    1901             : 
    1902        4205 :     bool bProcess = false;
    1903        4205 :     switch ( eJob )
    1904             :     {
    1905             :         case ONLINE_SPELLING :
    1906        1682 :             bProcess = pTxtNode->IsWrongDirty(); break;
    1907             :         case AUTOCOMPLETE_WORDS :
    1908        1690 :             bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
    1909             :         case WORD_COUNT :
    1910         833 :             bProcess = pTxtNode->IsWordCountDirty(); break;
    1911             :         case SMART_TAGS :
    1912           0 :             bProcess = pTxtNode->IsSmartTagDirty(); break;
    1913             :     }
    1914             : 
    1915        4205 :     if( bProcess )
    1916             :     {
    1917        1561 :         SwViewShell *pSh = pImp->GetShell();
    1918        1561 :         if( COMPLETE_STRING == nTxtPos )
    1919             :         {
    1920        1252 :             --nTxtPos;
    1921        1252 :             if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
    1922             :             {
    1923        1248 :                 SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
    1924        1248 :                 if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
    1925             :                 {
    1926        1248 :                     pCntntNode = pCrsr->GetCntntNode();
    1927        1248 :                     nTxtPos =  pCrsr->GetPoint()->nContent.GetIndex();
    1928             :                 }
    1929             :             }
    1930             :         }
    1931             : 
    1932        1561 :         switch ( eJob )
    1933             :         {
    1934             :             case ONLINE_SPELLING :
    1935             :             {
    1936        1334 :                 SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode,  *pSh->GetViewOptions(), nTxtPos ) );
    1937        1334 :                 bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
    1938        1334 :                 if( !bPageValid )
    1939         831 :                     bAllValid = false;
    1940        1334 :                 if ( aRepaint.HasArea() )
    1941          14 :                     pImp->GetShell()->InvalidateWindows( aRepaint );
    1942        1334 :                 if ( Application::AnyInput( VCL_INPUT_MOUSEANDKEYBOARD|VCL_INPUT_OTHER|VCL_INPUT_PAINT ) )
    1943           0 :                     return true;
    1944        1334 :                 break;
    1945             :             }
    1946             :             case AUTOCOMPLETE_WORDS :
    1947           8 :                 ((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
    1948           8 :                 if ( Application::AnyInput( VCL_INPUT_ANY ) )
    1949           0 :                     return true;
    1950           8 :                 break;
    1951             :             case WORD_COUNT :
    1952             :             {
    1953         219 :                 const sal_Int32 nEnd = pTxtNode->GetTxt().getLength();
    1954         219 :                 SwDocStat aStat;
    1955         219 :                 pTxtNode->CountWords( aStat, 0, nEnd );
    1956         219 :                 if ( Application::AnyInput( VCL_INPUT_ANY ) )
    1957          14 :                     return true;
    1958         205 :                 break;
    1959             :             }
    1960             :             case SMART_TAGS :
    1961             :             {
    1962             :                 try {
    1963           0 :                     const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
    1964           0 :                     bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
    1965           0 :                     if( !bPageValid )
    1966           0 :                         bAllValid = false;
    1967           0 :                     if ( aRepaint.HasArea() )
    1968           0 :                         pImp->GetShell()->InvalidateWindows( aRepaint );
    1969           0 :                 } catch( const ::com::sun::star::uno::RuntimeException& e) {
    1970             :                     // #i122885# handle smarttag problems gracefully and provide diagnostics
    1971             :                     SAL_WARN( "sw.core", "SMART_TAGS Exception:" << e.Message);
    1972             :                 }
    1973           0 :                 if ( Application::AnyInput( VCL_INPUT_MOUSEANDKEYBOARD|VCL_INPUT_OTHER|VCL_INPUT_PAINT ) )
    1974           0 :                     return true;
    1975           0 :                 break;
    1976             :             }
    1977             :         }
    1978             :     }
    1979             : 
    1980             :     // The Flys that are anchored to the paragraph need to be considered too.
    1981        4191 :     if ( pCnt->GetDrawObjs() )
    1982             :     {
    1983         565 :         const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
    1984        1655 :         for ( size_t i = 0; i < rObjs.size(); ++i )
    1985             :         {
    1986        1090 :             SwAnchoredObject* pObj = rObjs[i];
    1987        1090 :             if ( pObj->ISA(SwFlyFrm) )
    1988             :             {
    1989          96 :                 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
    1990          96 :                 if ( pFly->IsFlyInCntFrm() )
    1991             :                 {
    1992           0 :                     const SwCntntFrm *pC = pFly->ContainsCntnt();
    1993           0 :                     while( pC )
    1994             :                     {
    1995           0 :                         if ( pC->IsTxtFrm() )
    1996             :                         {
    1997           0 :                             if ( _DoIdleJob( pC, eJob ) )
    1998           0 :                                 return true;
    1999             :                         }
    2000           0 :                         pC = pC->GetNextCntntFrm();
    2001             :                     }
    2002             :                 }
    2003             :             }
    2004             :         }
    2005             :     }
    2006        4191 :     return false;
    2007             : }
    2008             : 
    2009        4357 : bool SwLayIdle::DoIdleJob( IdleJobType eJob, bool bVisAreaOnly )
    2010             : {
    2011             :     // Spellcheck all contents of the pages. Either only the
    2012             :     // visible ones or all of them.
    2013        4357 :     const SwViewShell* pViewShell = pImp->GetShell();
    2014        4357 :     const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
    2015        4357 :     const SwDoc* pDoc = pViewShell->GetDoc();
    2016             : 
    2017        4357 :     switch ( eJob )
    2018             :     {
    2019             :         case ONLINE_SPELLING :
    2020        1245 :             if( !pViewOptions->IsOnlineSpell() )
    2021           8 :                 return false;
    2022        1237 :             break;
    2023             :         case AUTOCOMPLETE_WORDS :
    2024        2490 :             if( !pViewOptions->IsAutoCompleteWords() ||
    2025        1245 :                  SwDoc::GetAutoCompleteWords().IsLockWordLstLocked())
    2026           0 :                 return false;
    2027        1245 :             break;
    2028             :         case WORD_COUNT :
    2029         622 :             if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
    2030           0 :                 return false;
    2031         622 :             break;
    2032             :         case SMART_TAGS :
    2033        3735 :             if ( pDoc->GetDocShell()->IsHelpDocument() ||
    2034        2490 :                  pDoc->isXForms() ||
    2035        1245 :                 !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
    2036        1245 :                 return false;
    2037           0 :             break;
    2038             :         default: OSL_FAIL( "Unknown idle job type" );
    2039             :     }
    2040             : 
    2041             :     SwPageFrm *pPage;
    2042        3104 :     if ( bVisAreaOnly )
    2043        1270 :         pPage = pImp->GetFirstVisPage();
    2044             :     else
    2045        1834 :         pPage = (SwPageFrm*)pRoot->Lower();
    2046             : 
    2047        3104 :     pCntntNode = NULL;
    2048        3104 :     nTxtPos = COMPLETE_STRING;
    2049             : 
    2050        9369 :     while ( pPage )
    2051             :     {
    2052        3201 :         bPageValid = true;
    2053        3201 :         const SwCntntFrm *pCnt = pPage->ContainsCntnt();
    2054       10501 :         while( pCnt && pPage->IsAnLower( pCnt ) )
    2055             :         {
    2056        4113 :             if ( _DoIdleJob( pCnt, eJob ) )
    2057          14 :                 return true;
    2058        4099 :             pCnt = pCnt->GetNextCntntFrm();
    2059             :         }
    2060        3187 :         if ( pPage->GetSortedObjs() )
    2061             :         {
    2062         492 :             for ( size_t i = 0; pPage->GetSortedObjs() &&
    2063         246 :                                 i < pPage->GetSortedObjs()->size(); ++i )
    2064             :             {
    2065         182 :                 const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
    2066         182 :                 if ( pObj->ISA(SwFlyFrm) )
    2067             :                 {
    2068          82 :                     const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
    2069          82 :                     const SwCntntFrm *pC = pFly->ContainsCntnt();
    2070         282 :                     while( pC )
    2071             :                     {
    2072         118 :                         if ( pC->IsTxtFrm() )
    2073             :                         {
    2074          92 :                             if ( _DoIdleJob( pC, eJob ) )
    2075           0 :                                 return true;
    2076             :                         }
    2077         118 :                         pC = pC->GetNextCntntFrm();
    2078             :                     }
    2079             :                 }
    2080             :             }
    2081             :         }
    2082             : 
    2083        3187 :         if( bPageValid )
    2084             :         {
    2085        2356 :             switch ( eJob )
    2086             :             {
    2087         439 :                 case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
    2088        1278 :                 case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
    2089         639 :                 case WORD_COUNT : pPage->ValidateWordCount(); break;
    2090           0 :                 case SMART_TAGS : pPage->ValidateSmartTags(); break;
    2091             :             }
    2092             :         }
    2093             : 
    2094        3187 :         pPage = (SwPageFrm*)pPage->GetNext();
    2095        3217 :         if ( pPage && bVisAreaOnly &&
    2096          30 :              !pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
    2097          26 :              break;
    2098             :     }
    2099        3090 :     return false;
    2100             : }
    2101             : 
    2102             : #if HAVE_FEATURE_DESKTOP && defined DBG_UTIL
    2103             : void SwLayIdle::ShowIdle( ColorData eColorData )
    2104             : {
    2105             :     if ( !m_bIndicator )
    2106             :     {
    2107             :         m_bIndicator = true;
    2108             :         vcl::Window *pWin = pImp->GetShell()->GetWin();
    2109             :         if ( pWin )
    2110             :         {
    2111             :             Rectangle aRect( 0, 0, 5, 5 );
    2112             :             aRect = pWin->PixelToLogic( aRect );
    2113             :             // OD 2004-04-23 #116347#
    2114             :             pWin->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
    2115             :             pWin->SetFillColor( eColorData );
    2116             :             pWin->SetLineColor();
    2117             :             pWin->DrawRect( aRect );
    2118             :             pWin->Pop();
    2119             :         }
    2120             :     }
    2121             : }
    2122             : #define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
    2123             : #else
    2124             : #define SHOW_IDLE( ColorData )
    2125             : #endif // DBG_UTIL
    2126             : 
    2127         637 : SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
    2128             :     pRoot( pRt ),
    2129         637 :     pImp( pI )
    2130             : #ifdef DBG_UTIL
    2131             :     , m_bIndicator( false )
    2132             : #endif
    2133             : {
    2134             :     SAL_INFO("sw.idle", "SwLayIdle() entry");
    2135             : 
    2136         637 :     pImp->pIdleAct = this;
    2137             : 
    2138             :     SHOW_IDLE( COL_LIGHTRED );
    2139             : 
    2140         637 :     pImp->GetShell()->EnableSmooth( false );
    2141             : 
    2142             :     // First, spellcheck the visible area. Only if there's nothing
    2143             :     // to do there, we trigger the IdleFormat.
    2144        1911 :     if ( !DoIdleJob( SMART_TAGS, true ) &&
    2145        1274 :          !DoIdleJob( ONLINE_SPELLING, true ) &&
    2146         637 :          !DoIdleJob( AUTOCOMPLETE_WORDS, true ) )
    2147             :     {
    2148             :         // Format, then register repaint rectangles with the SwViewShell if necessary.
    2149             :         // This requires running artificial actions, so we don't get undesired
    2150             :         // effects when for instance the page count gets changed.
    2151             :         // We remember the shells where the cursor is visible, so we can make
    2152             :         // it visible again if needed after a document change.
    2153         637 :         std::vector<bool> aBools;
    2154         637 :         SwViewShell *pSh = pImp->GetShell();
    2155         637 :         do
    2156         637 :         {   ++pSh->mnStartAction;
    2157         637 :             bool bVis = false;
    2158         637 :             if ( pSh->ISA(SwCrsrShell) )
    2159             :             {
    2160         637 :                 bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
    2161             :             }
    2162         637 :             aBools.push_back( bVis );
    2163         637 :             pSh = (SwViewShell*)pSh->GetNext();
    2164         637 :         } while ( pSh != pImp->GetShell() );
    2165             : 
    2166         637 :         bool bInterrupt(false);
    2167             :         {
    2168         637 :             SwLayAction aAction( pRoot, pImp );
    2169         637 :             aAction.SetInputType( VCL_INPUT_ANY );
    2170         637 :             aAction.SetIdle( true );
    2171         637 :             aAction.SetWaitAllowed( false );
    2172         637 :             aAction.Action();
    2173         637 :             bInterrupt = aAction.IsInterrupt();
    2174             :         }
    2175             : 
    2176             :         // Further start/end actions only happen if there were paints started
    2177             :         // somewhere or if the visibility of the CharRects has changed.
    2178         637 :         bool bActions = false;
    2179         637 :         sal_uInt16 nBoolIdx = 0;
    2180         637 :         do
    2181             :         {
    2182         637 :             --pSh->mnStartAction;
    2183             : 
    2184         637 :             if ( pSh->Imp()->GetRegion() )
    2185           6 :                 bActions = true;
    2186             :             else
    2187             :             {
    2188         631 :                 SwRect aTmp( pSh->VisArea() );
    2189         631 :                 pSh->UISizeNotify();
    2190             : 
    2191             :                 // #137134#
    2192             :                 // Are we supposed to crash if pSh isn't a cursor shell?!
    2193             :                 // bActions |= aTmp != pSh->VisArea() ||
    2194             :                 //             aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
    2195             : 
    2196             :                 // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
    2197             :                 // and the cursor is visible.
    2198         631 :                 bActions |= aTmp != pSh->VisArea();
    2199         631 :                 if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
    2200             :                 {
    2201         631 :                     bActions |= (aBools[nBoolIdx]) !=
    2202         631 :                                  static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
    2203             :                 }
    2204             :             }
    2205             : 
    2206         637 :             pSh = (SwViewShell*)pSh->GetNext();
    2207         637 :             ++nBoolIdx;
    2208         637 :         } while ( pSh != pImp->GetShell() );
    2209             : 
    2210         637 :         if ( bActions )
    2211             :         {
    2212             :             // Prepare start/end actions via CrsrShell, so the cursor, selection
    2213             :             // and VisArea can be set correctly.
    2214           6 :             nBoolIdx = 0;
    2215           6 :             do
    2216             :             {
    2217           6 :                 bool bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
    2218             : 
    2219           6 :                 if ( bCrsrShell )
    2220           6 :                     ((SwCrsrShell*)pSh)->SttCrsrMove();
    2221             : 
    2222             :                 // If there are accrued paints, it's best to simply invalidate
    2223             :                 // the whole window. Otherwise there would arise paint problems whose
    2224             :                 // solution would be disproportionally expensive.
    2225             :                 //fix(18176):
    2226           6 :                 SwViewImp *pViewImp = pSh->Imp();
    2227           6 :                 bool bUnlock = false;
    2228           6 :                 if ( pViewImp->GetRegion() )
    2229             :                 {
    2230           6 :                     pViewImp->DelRegion();
    2231             : 
    2232             :                     // Cause a repaint with virtual device.
    2233           6 :                     pSh->LockPaint();
    2234           6 :                     bUnlock = true;
    2235             :                 }
    2236             : 
    2237           6 :                 if ( bCrsrShell )
    2238             :                     // If the Crsr was visible, we need to make it visible again.
    2239             :                     // Otherwise, EndCrsrMove with sal_True for IdleEnd
    2240           6 :                     ((SwCrsrShell*)pSh)->EndCrsrMove( sal_True^aBools[nBoolIdx] );
    2241           6 :                 if( bUnlock )
    2242             :                 {
    2243           6 :                     if( bCrsrShell )
    2244             :                     {
    2245             :                         // UnlockPaint overwrite the selection from the
    2246             :                         // CrsrShell and calls the virtual method paint
    2247             :                         // to fill the virtual device. This fill dont have
    2248             :                         // paint the selection! -> Set the focus flag at
    2249             :                         // CrsrShell and it dont paint the selection.
    2250           6 :                         ((SwCrsrShell*)pSh)->ShLooseFcs();
    2251           6 :                         pSh->UnlockPaint( true );
    2252           6 :                         ((SwCrsrShell*)pSh)->ShGetFcs( false );
    2253             :                     }
    2254             :                     else
    2255           0 :                         pSh->UnlockPaint( true );
    2256             :                 }
    2257             : 
    2258           6 :                 pSh = (SwViewShell*)pSh->GetNext();
    2259           6 :                 ++nBoolIdx;
    2260             : 
    2261           6 :             } while ( pSh != pImp->GetShell() );
    2262             :         }
    2263             : 
    2264         637 :         if (!bInterrupt)
    2265             :         {
    2266         622 :             if ( !DoIdleJob( WORD_COUNT, false ) )
    2267         608 :                 if ( !DoIdleJob( SMART_TAGS, false ) )
    2268         608 :                     if ( !DoIdleJob( ONLINE_SPELLING, false ) )
    2269         608 :                         DoIdleJob( AUTOCOMPLETE_WORDS, false );
    2270             :         }
    2271             : 
    2272         637 :         bool bInValid = false;
    2273         637 :         const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
    2274         637 :         const SwViewShell* pViewShell = pImp->GetShell();
    2275             :         // See conditions in DoIdleJob()
    2276         637 :         const bool bSpell     = rVOpt.IsOnlineSpell();
    2277         637 :         const bool bACmplWrd  = rVOpt.IsAutoCompleteWords();
    2278         637 :         const bool bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
    2279        1274 :         const bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
    2280        1274 :                                 !pViewShell->GetDoc()->isXForms() &&
    2281        1274 :                                 SwSmartTagMgr::Get().IsSmartTagsEnabled();
    2282             : 
    2283         637 :         SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
    2284         668 :         do
    2285             :         {
    2286        2000 :             bInValid = pPg->IsInvalidCntnt()    || pPg->IsInvalidLayout() ||
    2287        1998 :                        pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
    2288        1332 :                        pPg->IsInvalidFlyInCnt() ||
    2289         662 :                        (bSpell && pPg->IsInvalidSpelling()) ||
    2290         243 :                        (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
    2291        1354 :                        (bWordCount && pPg->IsInvalidWordCount()) ||
    2292         668 :                        (bSmartTags && pPg->IsInvalidSmartTags());
    2293             : 
    2294         668 :             pPg = (SwPageFrm*)pPg->GetNext();
    2295             : 
    2296          47 :         } while ( pPg && !bInValid );
    2297             : 
    2298         637 :         if ( !bInValid )
    2299             :         {
    2300         194 :             pRoot->ResetIdleFormat();
    2301         194 :             SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
    2302         194 :             pDocShell->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
    2303         637 :         }
    2304             :     }
    2305             : 
    2306         637 :     pImp->GetShell()->EnableSmooth( true );
    2307             : 
    2308         637 :     if( pImp->IsAccessible() )
    2309          11 :         pImp->FireAccessibleEvents();
    2310             : 
    2311             :     SAL_INFO("sw.idle", "SwLayIdle() return");
    2312             : 
    2313             : #ifdef DBG_UTIL
    2314             :     if ( m_bIndicator && pImp->GetShell()->GetWin() )
    2315             :     {
    2316             :         // #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
    2317             :         // This should be replaced by an overlay object in the future, anyways. Since it's only for debug
    2318             :         // purposes, it is not urgent.
    2319             :             m_bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
    2320             :     }
    2321             : #endif
    2322         637 : }
    2323             : 
    2324         637 : SwLayIdle::~SwLayIdle()
    2325             : {
    2326         637 :     pImp->pIdleAct = 0;
    2327         907 : }
    2328             : 
    2329             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10