LCOV - code coverage report
Current view: top level - sw/source/core/layout - layact.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 1042 1169 89.1 %
Date: 2015-06-13 12:38:46 Functions: 33 33 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.11