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

Generated by: LCOV version 1.10