blob: 05cbb474a96de6b98f88a8e2297c2cb6ec685335 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <time.h>
#include "rootfrm.hxx"
#include "pagefrm.hxx"
#include "cntfrm.hxx"
#include "doc.hxx"
#include "IDocumentDrawModelAccess.hxx"
#include "IDocumentSettingAccess.hxx"
#include "IDocumentLayoutAccess.hxx"
#include "IDocumentStatistics.hxx"
#include "IDocumentTimerAccess.hxx"
#include "viewimp.hxx"
#include "crsrsh.hxx"
#include "dflyobj.hxx"
#include "flyfrm.hxx"
#include "frmtool.hxx"
#include "dcontact.hxx"
#include "ndtxt.hxx" // OnlineSpelling
#include "frmfmt.hxx"
#include "swregion.hxx"
#include "viewopt.hxx" // OnlineSpelling ueber Internal-TabPage testen.
#include "pam.hxx" // OnlineSpelling wg. der aktuellen Cursorposition
#include "dbg_lay.hxx"
#include "layouter.hxx" // LoopControlling
#include "docstat.hxx"
#include "swevent.hxx"
#include <sfx2/event.hxx>
#include <ftnidx.hxx>
#include <vcl/window.hxx>
#include <vcl/svapp.hxx>
#include <editeng/opaqitem.hxx>
#include <editeng/brshitem.hxx>
#include <SwSmartTagMgr.hxx>
#define _SVSTDARR_BOOLS
#include <svl/svstdarr.hxx>
#define _LAYACT_CXX
#include "layact.hxx"
#include <swwait.hxx>
#include <fmtsrnd.hxx>
#include <fmtanchr.hxx>
#include <tools/shl.hxx>
#include <sfx2/progress.hxx>
#ifndef _DOCSH_HXX
#include <docsh.hxx>
#endif
#include "swmodule.hxx"
#include "fmtline.hxx"
#include "tabfrm.hxx"
#include "ftnfrm.hxx"
#include "txtfrm.hxx"
#include "notxtfrm.hxx"
#include "flyfrms.hxx"
#include "mdiexp.hxx"
#include "fmtornt.hxx"
#include "sectfrm.hxx"
#include "lineinfo.hxx"
#include <acmplwrd.hxx>
// --> OD 2004-06-28 #i28701#
#include <sortedobjs.hxx>
#include <objectformatter.hxx>
#include <PostItMgr.hxx>
// <--
//#pragma optimize("ity",on)
/*************************************************************************
|*
|* SwLayAction Statisches Geraffel
|*
|* Ersterstellung MA 22. Dec. 93
|* Letzte Aenderung MA 22. Dec. 93
|*
|*************************************************************************/
#define IS_FLYS (pPage->GetSortedObjs())
#define IS_INVAFLY (pPage->IsInvalidFly())
//Sparen von Schreibarbeit um den Zugriff auf zerstoerte Seiten zu vermeiden.
#ifdef DBG_UTIL
static void BreakPoint()
{
return;
}
#define CHECKPAGE \
{ if ( IsAgain() ) \
{ BreakPoint(); \
return; \
} \
}
#define XCHECKPAGE \
{ if ( IsAgain() ) \
{ BreakPoint(); \
if( bNoLoop ) \
pLayoutAccess->GetLayouter()->EndLoopControl(); \
return; \
} \
}
#else
#define CHECKPAGE \
{ if ( IsAgain() ) \
return; \
}
#define XCHECKPAGE \
{ if ( IsAgain() ) \
{ \
if( bNoLoop ) \
pLayoutAccess->GetLayouter()->EndLoopControl(); \
return; \
} \
}
#endif
#define RESCHEDULE \
{ \
if ( IsReschedule() ) \
{ \
if (pProgress) pProgress->Reschedule(); \
::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
} \
}
inline sal_uLong Ticks()
{
return 1000 * clock() / CLOCKS_PER_SEC;
}
void SwLayAction::CheckWaitCrsr()
{
RESCHEDULE
if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
((Ticks() - GetStartTicks()) >= CLOCKS_PER_SEC/2) )
{
pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), true );
}
}
/*************************************************************************
|*
|* SwLayAction::CheckIdleEnd()
|*
|* Ersterstellung MA 12. Aug. 94
|* Letzte Aenderung MA 24. Jun. 96
|*
|*************************************************************************/
//Ist es wirklich schon soweit...
inline void SwLayAction::CheckIdleEnd()
{
if ( !IsInput() )
bInput = GetInputType() && Application::AnyInput( GetInputType() );
}
/*************************************************************************
|*
|* SwLayAction::SetStatBar()
|*
|* Ersterstellung MA 10. Aug. 94
|* Letzte Aenderung MA 06. Aug. 95
|*
|*************************************************************************/
void SwLayAction::SetStatBar( sal_Bool bNew )
{
if ( bNew )
{
nEndPage = pRoot->GetPageNum();
nEndPage += nEndPage * 10 / 100;
}
else
nEndPage = USHRT_MAX;
}
/*************************************************************************
|*
|* SwLayAction::PaintCntnt()
|*
|* Beschreibung Je nach Typ wird der Cntnt entsprechend seinen
|* Veraenderungen ausgegeben bzw. wird die auszugebende Flaeche in der
|* Region eingetragen.
|* PaintCntnt: fuellt die Region,
|* Ersterstellung BP 19. Jan. 92
|* Letzte Aenderung MA 10. Sep. 96
|*
|*************************************************************************/
sal_Bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
const SwPageFrm *pPage )
{
SwRegionRects aTmp( rRect );
const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
sal_uInt16 i;
for ( i = 0; i < rObjs.Count() && aTmp.Count(); ++i )
{
SdrObject *pO = rObjs[i]->DrawObj();
if ( !pO->ISA(SwVirtFlyDrawObj) )
continue;
// OD 2004-01-15 #110582# - do not consider invisible objects
const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
{
continue;
}
SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
continue;
if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
continue;
if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
continue;
if ( pSelfFly )
{
const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
if ( pO->GetLayer() == pTmp->GetLayer() )
{
if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
//Im gleichen Layer werden nur obenliegende beachtet.
continue;
}
else
{
const sal_Bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
//Aus anderem Layer interessieren uns nur nicht transparente
//oder innenliegende
continue;
}
}
/// OD 19.08.2002 #99657#
/// Fly frame without a lower have to be subtracted from paint region.
/// For checking, if fly frame contains transparent graphic or
/// has surrounded contour, assure that fly frame has a lower
if ( pFly->Lower() &&
pFly->Lower()->IsNoTxtFrm() &&
( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
pFly->GetFmt()->GetSurround().IsContour() )
)
{
continue;
}
/// OD 19.08.2002 #99657#
/// Region of a fly frame with transparent background or a transparent
/// shadow have not to be subtracted from paint region
if ( pFly->IsBackgroundTransparent() ||
pFly->IsShadowTransparent() )
{
continue;
}
aTmp -= pFly->Frm();
}
sal_Bool bRetPaint = sal_False;
const SwRect *pData = aTmp.GetData();
for ( i = 0; i < aTmp.Count(); ++pData, ++i )
bRetPaint |= pImp->GetShell()->AddPaintRect( *pData );
return bRetPaint;
}
inline sal_Bool SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
const SwPageFrm *pPage,
const SwRect &rRect )
{
if ( rRect.HasArea() )
{
if ( pPage->GetSortedObjs() )
return PaintWithoutFlys( rRect, pCntnt, pPage );
else
return pImp->GetShell()->AddPaintRect( rRect );
}
return sal_False;
}
void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
const SwPageFrm *pPage,
const SwRect &rOldRect,
long nOldBottom )
{
SWRECTFN( pCnt )
if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
{
SwRect aPaint( pCnt->PaintArea() );
if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
pCnt->ResetCompletePaint();
}
else
{
// paint the area between printing bottom and frame bottom and
// the area left and right beside the frame, if its height changed.
long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
const bool bHeightDiff = nOldHeight != nNewHeight;
if( bHeightDiff )
{
// OD 05.11.2002 #94454# - consider whole potential paint area.
//SwRect aDrawRect( pCnt->UnionFrm( sal_True ) );
SwRect aDrawRect( pCnt->PaintArea() );
if( nOldHeight > nNewHeight )
nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
(aDrawRect.*fnRect->fnSetTop)( nOldBottom );
_PaintCntnt( pCnt, pPage, aDrawRect );
}
// paint content area
SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
_PaintCntnt( pCnt, pPage, aPaintRect );
}
if ( pCnt->IsRetouche() && !pCnt->GetNext() )
{
const SwFrm *pTmp = pCnt;
if( pCnt->IsInSct() )
{
const SwSectionFrm* pSct = pCnt->FindSctFrm();
if( pSct->IsRetouche() && !pSct->GetNext() )
pTmp = pSct;
}
SwRect aRect( pTmp->GetUpper()->PaintArea() );
(aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
if ( !_PaintCntnt( pCnt, pPage, aRect ) )
pCnt->ResetRetouche();
}
}
/*************************************************************************
|*
|* SwLayAction::SwLayAction()
|*
|* Ersterstellung MA 30. Oct. 92
|* Letzte Aenderung MA 09. Jun. 95
|*
|*************************************************************************/
SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
pRoot( pRt ),
pImp( pI ),
pOptTab( 0 ),
pWait( 0 ),
pProgress(NULL),
nPreInvaPage( USHRT_MAX ),
nStartTicks( Ticks() ),
nInputType( 0 ),
nEndPage( USHRT_MAX ),
nCheckPageNum( USHRT_MAX )
{
bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
bUpdateExpFlds = bBrowseActionStop = bActionInProgress = sal_False;
// OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
mbFormatCntntOnInterrupt = sal_False;
pImp->pLayAct = this; //Anmelden
}
SwLayAction::~SwLayAction()
{
ASSERT( !pWait, "Wait object not destroyed" );
pImp->pLayAct = 0; //Abmelden
}
/*************************************************************************
|*
|* SwLayAction::Reset()
|*
|* Ersterstellung MA 11. Aug. 94
|* Letzte Aenderung MA 09. Jun. 95
|*
|*************************************************************************/
void SwLayAction::Reset()
{
pOptTab = 0;
nStartTicks = Ticks();
nInputType = 0;
nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
bUpdateExpFlds = bBrowseActionStop = sal_False;
}
/*************************************************************************
|*
|* SwLayAction::RemoveEmptyBrowserPages()
|*
|* Ersterstellung MA 10. Sep. 97
|* Letzte Aenderung MA 10. Sep. 97
|*
|*************************************************************************/
sal_Bool SwLayAction::RemoveEmptyBrowserPages()
{
//Beim umschalten vom normalen in den Browsermodus bleiben u.U. einige
//unangenehm lange stehen. Diese beseiten wir mal schnell.
sal_Bool bRet = sal_False;
const ViewShell *pSh = pRoot->GetCurrShell();
if( pSh && pSh->GetViewOptions()->getBrowseMode() )
{
SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
do
{
if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->Count()) ||
pPage->ContainsCntnt() )
pPage = (SwPageFrm*)pPage->GetNext();
else
{
bRet = sal_True;
SwPageFrm *pDel = pPage;
pPage = (SwPageFrm*)pPage->GetNext();
pDel->Cut();
delete pDel;
}
} while ( pPage );
}
return bRet;
}
/*************************************************************************
|*
|* SwLayAction::Action()
|*
|* Ersterstellung MA 10. Aug. 94
|* Letzte Aenderung MA 06. Aug. 95
|*
|*************************************************************************/
void SwLayAction::Action()
{
bActionInProgress = sal_True;
//TurboMode? Disqualifiziert fuer Idle-Format.
if ( IsPaint() && !IsIdle() && TurboAction() )
{
delete pWait, pWait = 0;
pRoot->ResetTurboFlag();
bActionInProgress = sal_False;
pRoot->DeleteEmptySct();
return;
}
else if ( pRoot->GetTurbo() )
{
pRoot->DisallowTurbo();
const SwFrm *pFrm = pRoot->GetTurbo();
pRoot->ResetTurbo();
pFrm->InvalidatePage();
}
pRoot->DisallowTurbo();
if ( IsCalcLayout() )
SetCheckPages( sal_False );
InternalAction();
bAgain |= RemoveEmptyBrowserPages();
while ( IsAgain() )
{
bAgain = bNextCycle = sal_False;
InternalAction();
bAgain |= RemoveEmptyBrowserPages();
}
pRoot->DeleteEmptySct();
delete pWait, pWait = 0;
//Turbo-Action ist auf jedenfall wieder erlaubt.
pRoot->ResetTurboFlag();
pRoot->ResetTurbo();
SetCheckPages( sal_True );
bActionInProgress = sal_False;
}
SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
{
SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
SwCntntFrm *pChk = pCnt;
sal_Bool bPageChgd = sal_False;
while ( pCnt && pCnt->IsFollow() )
pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
if ( pCnt && pChk != pCnt )
{ bPageChgd = sal_True;
pPage = pCnt->FindPageFrm();
}
if ( pPage->GetFmt()->GetDoc()->GetFtnIdxs().Count() )
{
SwFtnContFrm *pCont = pPage->FindFtnCont();
if ( pCont )
{
pCnt = pCont->ContainsCntnt();
pChk = pCnt;
while ( pCnt && pCnt->IsFollow() )
pCnt = (SwCntntFrm*)pCnt->FindPrev();
if ( pCnt && pCnt != pChk )
{
if ( bPageChgd )
{
//Die 'oberste' Seite benutzten.
SwPageFrm *pTmp = pCnt->FindPageFrm();
if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
pPage = pTmp;
}
else
pPage = pCnt->FindPageFrm();
}
}
}
return pPage;
}
// OD 2004-05-12 #i28701#
// --> OD 2004-11-03 #i114798# - unlock position on start and end of page
// layout process.
class NotifyLayoutOfPageInProgress
{
private:
SwPageFrm& mrPageFrm;
void _UnlockPositionOfObjs()
{
SwSortedObjs* pObjs = mrPageFrm.GetSortedObjs();
if ( pObjs )
{
sal_uInt32 i = 0;
for ( ; i < pObjs->Count(); ++i )
{
SwAnchoredObject* pObj = (*pObjs)[i];
pObj->UnlockPosition();
}
}
}
public:
NotifyLayoutOfPageInProgress( SwPageFrm& _rPageFrm )
: mrPageFrm( _rPageFrm )
{
_UnlockPositionOfObjs();
_rPageFrm.SetLayoutInProgress( true );
}
~NotifyLayoutOfPageInProgress()
{
mrPageFrm.SetLayoutInProgress( false );
_UnlockPositionOfObjs();
}
};
// <--
void SwLayAction::InternalAction()
{
ASSERT( pRoot->Lower()->IsPageFrm(), ":-( Keine Seite unterhalb der Root.");
pRoot->Calc();
//Die erste ungueltige bzw. zu formatierende Seite ermitteln.
//Bei einer Complete-Action ist es die erste ungueltige; mithin ist die
//erste zu formatierende Seite diejenige Seite mit der Numemr eins.
//Bei einer Luegen-Formatierung ist die Nummer der erste Seite die Nummer
//der ersten Sichtbaren Seite.
SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
pImp->GetFirstVisPage();
if ( !pPage )
pPage = (SwPageFrm*)pRoot->Lower();
//Wenn ein "Erster-Fliess-Cntnt" innerhalb der der ersten sichtbaren Seite
//ein Follow ist, so schalten wir die Seite zurueck auf den Ur-Master dieses
//Cntnt's
if ( !IsComplete() )
pPage = CheckFirstVisPage( pPage );
sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
pPage = (SwPageFrm*)pPage->GetNext();
IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
sal_Bool bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : sal_False;
sal_uInt16 nPercentPageNum = 0;
while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
{
if ( !pPage && nCheckPageNum != USHRT_MAX &&
(!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
{
if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
{
SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
pPg = (SwPageFrm*)pPg->GetNext();
if ( pPg )
pPage = pPg;
if ( !pPage )
break;
}
SwPageFrm *pTmp = pPage->GetPrev() ?
(SwPageFrm*)pPage->GetPrev() : pPage;
SetCheckPages( sal_True );
SwFrm::CheckPageDescs( pPage );
SetCheckPages( sal_False );
nCheckPageNum = USHRT_MAX;
pPage = pTmp;
continue;
}
if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
{
nPercentPageNum = pPage->GetPhyPageNum();
::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
}
pOptTab = 0;
//Kein ShortCut fuer Idle oder CalcLayout
if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
{
pRoot->DeleteEmptySct();
XCHECKPAGE;
if ( !IsInterrupt() &&
(pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
{
if ( pRoot->IsAssertFlyPages() )
pRoot->AssertFlyPages();
if ( pRoot->IsSuperfluous() )
{
sal_Bool bOld = IsAgain();
pRoot->RemoveSuperfluous();
bAgain = bOld;
}
if ( IsAgain() )
{
if( bNoLoop )
pLayoutAccess->GetLayouter()->EndLoopControl();
return;
}
pPage = (SwPageFrm*)pRoot->Lower();
while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
pPage = (SwPageFrm*)pPage->GetNext();
while ( pPage && pPage->GetNext() &&
pPage->GetPhyPageNum() < nFirstPageNum )
pPage = (SwPageFrm*)pPage->GetNext();
continue;
}
break;
}
else
{
pRoot->DeleteEmptySct();
XCHECKPAGE;
// OD 2004-05-12 #i28701# - scope for instance of class
// <NotifyLayoutOfPageInProgress>
{
NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPage );
while ( !IsInterrupt() && !IsNextCycle() &&
((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
{
// OD 2004-05-10 #i28701#
SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
if ( !IS_FLYS )
{
//Wenn keine Flys (mehr) da sind, sind die Flags
//mehr als fluessig.
pPage->ValidateFlyLayout();
pPage->ValidateFlyCntnt();
}
// OD 2004-05-10 #i28701# - change condition
while ( !IsInterrupt() && !IsNextCycle() &&
( pPage->IsInvalid() ||
(IS_FLYS && IS_INVAFLY) ) )
{
PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
XCHECKPAGE;
// FME 2007-08-30 #i81146# new loop control
sal_uInt16 nLoopControlRuns_1 = 0;
const sal_uInt16 nLoopControlMax = 20;
while ( !IsNextCycle() && pPage->IsInvalidLayout() )
{
pPage->ValidateLayout();
if ( ++nLoopControlRuns_1 > nLoopControlMax )
{
#if OSL_DEBUG_LEVEL > 1
ASSERT( false, "LoopControl_1 in SwLayAction::InternalAction" )
#endif
break;
}
FormatLayout( pPage );
XCHECKPAGE;
}
// OD 2004-05-10 #i28701# - change condition
if ( !IsNextCycle() &&
( pPage->IsInvalidCntnt() ||
(IS_FLYS && IS_INVAFLY) ) )
{
pPage->ValidateFlyInCnt();
pPage->ValidateCntnt();
// --> OD 2004-05-10 #i28701#
pPage->ValidateFlyLayout();
pPage->ValidateFlyCntnt();
// <--
if ( !FormatCntnt( pPage ) )
{
XCHECKPAGE;
pPage->InvalidateCntnt();
pPage->InvalidateFlyInCnt();
// --> OD 2004-05-10 #i28701#
pPage->InvalidateFlyLayout();
pPage->InvalidateFlyCntnt();
// <--
if ( IsBrowseActionStop() )
bInput = sal_True;
}
}
if( bNoLoop )
pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
}
}
} // end of scope for instance of class <NotifyLayoutOfPageInProgress>
//Eine vorige Seite kann wieder invalid sein.
XCHECKPAGE;
if ( !IS_FLYS )
{
//Wenn keine Flys (mehr) da sind, sind die Flags
//mehr als fluessig.
pPage->ValidateFlyLayout();
pPage->ValidateFlyCntnt();
}
if ( !IsInterrupt() )
{
SetNextCycle( sal_False );
if ( nPreInvaPage != USHRT_MAX )
{
if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
{
pImp->SetFirstVisPageInvalid();
SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
nFirstPageNum = pTmpPage->GetPhyPageNum();
if( nPreInvaPage < nFirstPageNum )
{
nPreInvaPage = nFirstPageNum;
pPage = pTmpPage;
}
}
while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
pPage = (SwPageFrm*)pPage->GetPrev();
nPreInvaPage = USHRT_MAX;
}
while ( pPage->GetPrev() &&
( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
(((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
nFirstPageNum) )
{
pPage = (SwPageFrm*)pPage->GetPrev();
}
//Weiter bis zur naechsten invaliden Seite.
while ( pPage && !pPage->IsInvalid() &&
(!IS_FLYS || !IS_INVAFLY) )
{
pPage = (SwPageFrm*)pPage->GetNext();
}
if( bNoLoop )
pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
}
CheckIdleEnd();
}
if ( !pPage && !IsInterrupt() &&
(pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
{
if ( pRoot->IsAssertFlyPages() )
pRoot->AssertFlyPages();
if ( pRoot->IsSuperfluous() )
{
sal_Bool bOld = IsAgain();
pRoot->RemoveSuperfluous();
bAgain = bOld;
}
if ( IsAgain() )
{
if( bNoLoop )
pLayoutAccess->GetLayouter()->EndLoopControl();
return;
}
pPage = (SwPageFrm*)pRoot->Lower();
while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
pPage = (SwPageFrm*)pPage->GetNext();
while ( pPage && pPage->GetNext() &&
pPage->GetPhyPageNum() < nFirstPageNum )
pPage = (SwPageFrm*)pPage->GetNext();
}
}
if ( IsInterrupt() && pPage )
{
//Wenn ein Input anliegt wollen wir keinen Inhalt mehr Formatieren,
//Das Layout muessen wir aber schon in Ordnung bringen.
//Andernfalls kann folgende Situation auftreten (Bug: 3244):
//Am Ende des Absatz der letzten Seite wird Text eingegeben, so das
//der Absatz einen Follow fuer die nachste Seite erzeugt, ausserdem
//wird gleich schnell weitergetippt - Es liegt waehrend der
//Verarbeitung ein Input an. Der Absatz auf der neuen Seite wurde
//bereits anformatiert, die neue Seite ist Formatiert und steht
//auf CompletePaint, hat sich aber noch nicht im Auszugebenden Bereich
//eingetragen. Es wird gepaintet, das CompletePaint der Seite wird
//zurueckgesetzt weil der neue Absatz sich bereits eingetragen hatte,
//aber die Raender der Seite werden nicht gepaintet. Naja, bei der
//zwangslaeufig auftretenden naechsten LayAction traegt sich die Seite
//nicht mehr ein, weil ihre (LayoutFrm-)Flags bereits zurueckgesetzt
//wurden -- Der Rand der Seite wird nie gepaintet.
SwPageFrm *pPg = pPage;
XCHECKPAGE;
const SwRect &rVis = pImp->GetShell()->VisArea();
while( pPg && pPg->Frm().Bottom() < rVis.Top() )
pPg = (SwPageFrm*)pPg->GetNext();
if( pPg != pPage )
pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
// OD 14.04.2003 #106346# - set flag for interrupt content formatting
mbFormatCntntOnInterrupt = IsInput() && !IsStopPrt();
long nBottom = rVis.Bottom();
// --> OD 2005-02-15 #i42586# - format current page, if idle action is active
// This is an optimization for the case that the interrupt is created by
// the move of a form control object, which is represented by a window.
while ( pPg && ( pPg->Frm().Top() < nBottom ||
( IsIdle() && pPg == pPage ) ) )
// <--
{
// --> OD 2004-10-11 #i26945# - follow-up of #i28701#
NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPg );
XCHECKPAGE;
// FME 2007-08-30 #i81146# new loop control
sal_uInt16 nLoopControlRuns_2 = 0;
const sal_uInt16 nLoopControlMax = 20;
// OD 14.04.2003 #106346# - special case: interrupt content formatting
// --> OD 2004-07-08 #i28701# - conditions, introduced by #106346#,
// are incorrect (marcos IS_FLYS and IS_INVAFLY only works for <pPage>)
// and are too strict.
// --> OD 2005-06-09 #i50432# - adjust interrupt formatting to
// normal page formatting - see above.
while ( ( mbFormatCntntOnInterrupt &&
( pPg->IsInvalid() ||
( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
{
XCHECKPAGE;
// --> OD 2005-06-09 #i50432# - format also at-page anchored objects
SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
// <--
// --> OD 2005-06-09 #i50432#
if ( !pPg->GetSortedObjs() )
{
pPg->ValidateFlyLayout();
pPg->ValidateFlyCntnt();
}
// <--
// FME 2007-08-30 #i81146# new loop control
sal_uInt16 nLoopControlRuns_3 = 0;
while ( pPg->IsInvalidLayout() )
{
pPg->ValidateLayout();
if ( ++nLoopControlRuns_3 > nLoopControlMax )
{
#if OSL_DEBUG_LEVEL > 1
ASSERT( false, "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" )
#endif
break;
}
FormatLayout( pPg );
XCHECKPAGE;
}
// --> OD 2005-06-09 #i50432#
if ( mbFormatCntntOnInterrupt &&
( pPg->IsInvalidCntnt() ||
( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
// <--
{
pPg->ValidateFlyInCnt();
pPg->ValidateCntnt();
// --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
pPg->ValidateFlyLayout();
pPg->ValidateFlyCntnt();
// <--
if ( ++nLoopControlRuns_2 > nLoopControlMax )
{
#if OSL_DEBUG_LEVEL > 1
ASSERT( false, "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" )
#endif
break;
}
if ( !FormatCntnt( pPg ) )
{
XCHECKPAGE;
pPg->InvalidateCntnt();
pPg->InvalidateFlyInCnt();
// --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
pPg->InvalidateFlyLayout();
pPg->InvalidateFlyCntnt();
// <--
}
// --> OD 2005-04-06 #i46807# - we are statisfied, if the
// content is formatted once complete.
else
{
break;
}
// <--
}
}
// <--
pPg = (SwPageFrm*)pPg->GetNext();
}
// OD 14.04.2003 #106346# - reset flag for special interrupt content formatting.
mbFormatCntntOnInterrupt = sal_False;
}
pOptTab = 0;
if( bNoLoop )
pLayoutAccess->GetLayouter()->EndLoopControl();
}
/*************************************************************************
|*
|* SwLayAction::TurboAction(), _TurboAction()
|*
|* Ersterstellung MA 04. Dec. 92
|* Letzte Aenderung MA 15. Aug. 93
|*
|*************************************************************************/
sal_Bool SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
{
const SwPageFrm *pPage = 0;
if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
{
const SwRect aOldRect( pCnt->UnionFrm( sal_True ) );
const long nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
pCnt->Calc();
if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
pCnt->SetRetouche();
pPage = pCnt->FindPageFrm();
PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
{
const sal_uLong nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
((SwTxtFrm*)pCnt)->RecalcAllLines();
if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
{
if ( IsPaintExtraData() )
pImp->GetShell()->AddPaintRect( pCnt->Frm() );
//Damit die restlichen LineNums auf der Seite bereichnet werden
//und nicht hier abgebrochen wird.
//Das im RecalcAllLines zu erledigen waere teuer, weil dort
//auch in unnoetigen Faellen (normale Action) auch immer die
//Seite benachrichtigt werden muesste.
const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
while ( pNxt &&
(pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
pNxt = pNxt->GetNextCntntFrm();
if ( pNxt )
pNxt->InvalidatePage();
}
return sal_False;
}
if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
return sal_False;
}
if ( !pPage )
pPage = pCnt->FindPageFrm();
// OD 2004-05-10 #i28701# - format floating screen objects at content frame.
if ( pCnt->IsTxtFrm() &&
!SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
*pPage, this ) )
{
return sal_False;
}
if ( pPage->IsInvalidCntnt() )
return sal_False;
return sal_True;
}
sal_Bool SwLayAction::TurboAction()
{
sal_Bool bRet = sal_True;
if ( pRoot->GetTurbo() )
{
if ( !_TurboAction( pRoot->GetTurbo() ) )
{
CheckIdleEnd();
bRet = sal_False;
}
pRoot->ResetTurbo();
}
else
bRet = sal_False;
return bRet;
}
/*************************************************************************
|*
|* SwLayAction::IsShortCut()
|*
|* Beschreibung: Liefert ein True, wenn die Seite vollstaendig unter
|* oder rechts neben dem sichbaren Bereich liegt.
|* Es kann passieren, dass sich die Verhaeltnisse derart aendern, dass
|* die Verarbeitung (des Aufrufers!) mit der Vorgaengerseite der
|* uebergebenen Seite weitergefuehrt werden muss. Der Paramter wird also
|* ggf. veraendert!
|* Fuer den BrowseMode kann auch dann der ShortCut aktiviert werden,
|* wenn der ungueltige Inhalt der Seite unterhalb des sichbaren
|* bereiches liegt.
|* Ersterstellung MA 30. Oct. 92
|* Letzte Aenderung MA 18. Jul. 96
|*
|*************************************************************************/
static bool lcl_IsInvaLay( const SwFrm *pFrm, long nBottom )
{
if (
!pFrm->IsValid() ||
(pFrm->IsCompletePaint() && ( pFrm->Frm().Top() < nBottom ) )
)
{
return true;
}
return false;
}
static const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
{
ASSERT( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
if (lcl_IsInvaLay(pFrm, nBottom))
return pFrm;
pFrm = ((SwLayoutFrm*)pFrm)->Lower();
while ( pFrm )
{
if ( pFrm->IsLayoutFrm() )
{
if (lcl_IsInvaLay(pFrm, nBottom))
return pFrm;
const SwFrm *pTmp;
if ( 0 != (pTmp = lcl_FindFirstInvaLay( pFrm, nBottom )) )
return pTmp;
}
pFrm = pFrm->GetNext();
}
return 0;
}
static const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
const SwCntntFrm *pFirst )
{
const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
pLay->ContainsCntnt();
while ( pCnt )
{
if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
{
if ( pCnt->Frm().Top() <= nBottom )
return pCnt;
}
if ( pCnt->GetDrawObjs() )
{
const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
{
const SwAnchoredObject* pObj = rObjs[i];
if ( pObj->ISA(SwFlyFrm) )
{
const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
if ( pFly->IsFlyInCntFrm() )
{
if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
pFly->IsCompletePaint() )
{
if ( pFly->Frm().Top() <= nBottom )
return pFly;
}
const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
return pFrm;
}
}
}
}
if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
return 0;
pCnt = pCnt->GetNextCntntFrm();
if ( !pLay->IsAnLower( pCnt ) )
break;
}
return 0;
}
// --> OD 2005-02-21 #i37877# - consider drawing objects
static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
long _nBottom )
{
ASSERT( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" )
for ( sal_uInt16 i = 0; i < _pPage->GetSortedObjs()->Count(); ++i )
{
const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
if ( pObj->ISA(SwFlyFrm) )
{
const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
if ( pFly->Frm().Top() <= _nBottom )
{
if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
return pFly;
const SwFrm* pTmp;
if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
pTmp->Frm().Top() <= _nBottom )
return pFly;
}
}
else if ( pObj->ISA(SwAnchoredDrawObject) )
{
if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
{
return pObj;
}
}
}
return 0;
}
// <--
sal_Bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
{
sal_Bool bRet = sal_False;
const ViewShell *pSh = pRoot->GetCurrShell();
const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
//Wenn die Seite nicht Gueltig ist wird sie schnell formatiert, sonst
//gibts nix als Aerger.
if ( !prPage->IsValid() )
{
if ( bBrowse )
{
/// OD 15.10.2002 #103517# - format complete page
/// Thus, loop on all lowers of the page <prPage>, instead of only
/// format its first lower.
/// NOTE: In online layout (bBrowse == sal_True) a page can contain
/// a header frame and/or a footer frame beside the body frame.
prPage->Calc();
SwFrm* pPageLowerFrm = prPage->Lower();
while ( pPageLowerFrm )
{
pPageLowerFrm->Calc();
pPageLowerFrm = pPageLowerFrm->GetNext();
}
}
else
FormatLayout( prPage );
if ( IsAgain() )
return sal_False;
}
const SwRect &rVis = pImp->GetShell()->VisArea();
if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
(prPage->Frm().Left()>= rVis.Right()) )
{
bRet = sal_True;
//Jetzt wird es ein bischen unangenehm: Der erste CntntFrm dieser Seite
//im Bodytext muss Formatiert werden, wenn er dabei die Seite
//wechselt, muss ich nochmal eine Seite zuvor anfangen, denn
//es wurde ein PageBreak verarbeitet.
//Noch unangenehmer: Der naechste CntntFrm ueberhaupt muss
//Formatiert werden, denn es kann passieren, dass kurzfristig
//leere Seiten existieren (Bsp. Absatz ueber mehrere Seiten
//wird geloescht oder verkleinert).
//Ist fuer den Browser uninteressant, wenn der letzte Cnt davor bereits
//nicht mehr sichbar ist.
const SwPageFrm *p2ndPage = prPage;
const SwCntntFrm *pCntnt;
const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
if( p2ndPage->IsFtnPage() && pBody )
pBody = (SwLayoutFrm*)pBody->GetNext();
pCntnt = pBody ? pBody->ContainsCntnt() : 0;
while ( p2ndPage && !pCntnt )
{
p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
if( p2ndPage )
{
pBody = p2ndPage->FindBodyCont();
if( p2ndPage->IsFtnPage() && pBody )
pBody = (SwLayoutFrm*)pBody->GetNext();
pCntnt = pBody ? pBody->ContainsCntnt() : 0;
}
}
if ( pCntnt )
{
sal_Bool bTstCnt = sal_True;
if ( bBrowse )
{
//Der Cnt davor schon nicht mehr sichtbar?
const SwFrm *pLst = pCntnt;
if ( pLst->IsInTab() )
pLst = pCntnt->FindTabFrm();
if ( pLst->IsInSct() )
pLst = pCntnt->FindSctFrm();
pLst = pLst->FindPrev();
if ( pLst &&
(pLst->Frm().Top() >= rVis.Bottom() ||
pLst->Frm().Left()>= rVis.Right()) )
{
bTstCnt = sal_False;
}
}
if ( bTstCnt )
{
// --> OD 2004-06-04 #i27756# - check after each frame calculation,
// if the content frame has changed the page. If yes, no other
// frame calculation is performed
bool bPageChg = false;
if ( pCntnt->IsInSct() )
{
const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
if ( !pSct->IsValid() )
{
pSct->Calc();
pSct->SetCompletePaint();
if ( IsAgain() )
return sal_False;
// --> OD 2004-06-04 #i27756#
bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
prPage->GetPrev();
}
}
if ( !bPageChg && !pCntnt->IsValid() )
{
pCntnt->Calc();
pCntnt->SetCompletePaint();
if ( IsAgain() )
return sal_False;
// --> OD 2004-06-04 #i27756#
bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
prPage->GetPrev();
}
if ( !bPageChg && pCntnt->IsInTab() )
{
const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
if ( !pTab->IsValid() )
{
pTab->Calc();
pTab->SetCompletePaint();
if ( IsAgain() )
return sal_False;
// --> OD 2004-06-04 #i27756#
bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
prPage->GetPrev();
}
}
if ( !bPageChg && pCntnt->IsInSct() )
{
const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
if ( !pSct->IsValid() )
{
pSct->Calc();
pSct->SetCompletePaint();
if ( IsAgain() )
return sal_False;
// --> OD 2004-06-04 #i27756#
bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
prPage->GetPrev();
}
}
// --> OD 2004-06-04 #i27756#
if ( bPageChg )
{
bRet = sal_False;
const SwPageFrm* pTmp = pCntnt->FindPageFrm();
if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
pTmp->IsInvalid() )
{
prPage = (SwPageFrm*)pTmp;
}
else
{
prPage = (SwPageFrm*)prPage->GetPrev();
}
}
// --> OD 2005-04-25 #121980# - no shortcut, if at previous page
// an anchored object is registered, whose anchor is <pCntnt>.
else if ( prPage->GetPrev() &&
static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
{
SwSortedObjs* pObjs =
static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
if ( pObjs )
{
sal_uInt32 i = 0;
for ( ; i < pObjs->Count(); ++i )
{
SwAnchoredObject* pObj = (*pObjs)[i];
if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
{
bRet = sal_False;
break;
}
}
}
}
// <--
}
}
}
if ( !bRet && bBrowse )
{
const long nBottom = rVis.Bottom();
const SwAnchoredObject* pObj( 0L );
if ( prPage->GetSortedObjs() &&
(prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
pObj->GetObjRect().Top() <= nBottom )
{
return sal_False;
}
const SwFrm* pFrm( 0L );
if ( prPage->IsInvalidLayout() &&
0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
pFrm->Frm().Top() <= nBottom )
{
return sal_False;
}
if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
pFrm->Frm().Top() <= nBottom )
{
return sal_False;
}
bRet = sal_True;
}
return bRet;
}
/*************************************************************************
|*
|* SwLayAction::FormatLayout(), FormatLayoutFly, FormatLayoutTab()
|*
|* Ersterstellung MA 30. Oct. 92
|* Letzte Aenderung MA 18. May. 98
|*
|*************************************************************************/
// OD 15.11.2002 #105155# - introduce support for vertical layout
sal_Bool SwLayAction::FormatLayout( SwLayoutFrm *pLay, sal_Bool bAddRect )
{
ASSERT( !IsAgain(), "Ungueltige Seite beachten." );
if ( IsAgain() )
return sal_False;
sal_Bool bChanged = sal_False;
sal_Bool bAlreadyPainted = sal_False;
// OD 11.11.2002 #104414# - remember frame at complete paint
SwRect aFrmAtCompletePaint;
if ( !pLay->IsValid() || pLay->IsCompletePaint() )
{
if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
pLay->GetPrev()->SetCompletePaint();
SwRect aOldRect( pLay->Frm() );
pLay->Calc();
if ( aOldRect != pLay->Frm() )
bChanged = sal_True;
sal_Bool bNoPaint = sal_False;
if ( pLay->IsPageBodyFrm() &&
pLay->Frm().Pos() == aOldRect.Pos() &&
pLay->Lower() )
{
const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
//Einschraenkungen wegen Kopf-/Fusszeilen
if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
!( pLay->IsCompletePaint() && pLay->FindPageFrm()->FindFtnCont() ) )
bNoPaint = sal_True;
}
if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
{
SwRect aPaint( pLay->Frm() );
// OD 13.02.2003 #i9719#, #105645# - consider border and shadow for
// page frames -> enlarge paint rectangle correspondingly.
if ( pLay->IsPageFrm() )
{
SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
const int nBorderWidth =
pImp->GetShell()->GetOut()->PixelToLogic( Size( pPageFrm->BorderPxWidth(), 0 ) ).Width();
const int nShadowWidth =
pImp->GetShell()->GetOut()->PixelToLogic( Size( pPageFrm->ShadowPxWidth(), 0 ) ).Width();
//mod #i6193# added sidebar width
const SwPostItMgr* pPostItMgr = pImp->GetShell()->GetPostItMgr();
const int nSidebarWidth = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0;
switch ( pPageFrm->SidebarPosition() )
{
case sw::sidebarwindows::SIDEBAR_LEFT:
{
aPaint.Left( aPaint.Left() - nBorderWidth - nSidebarWidth);
aPaint.Right( aPaint.Right() + nBorderWidth + nShadowWidth);
}
break;
case sw::sidebarwindows::SIDEBAR_RIGHT:
{
aPaint.Left( aPaint.Left() - nBorderWidth );
aPaint.Right( aPaint.Right() + nBorderWidth + nShadowWidth + nSidebarWidth);
}
break;
case sw::sidebarwindows::SIDEBAR_NONE:
// nothing to do
break;
}
aPaint.Top( aPaint.Top() - nBorderWidth );
aPaint.Bottom( aPaint.Bottom() + nBorderWidth + nShadowWidth);
}
sal_Bool bPageInBrowseMode = pLay->IsPageFrm();
if( bPageInBrowseMode )
{
const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
bPageInBrowseMode = sal_False;
}
if( bPageInBrowseMode )
{
// NOTE: no vertical layout in online layout
//Ist die Aenderung ueberhaupt sichtbar?
if ( pLay->IsCompletePaint() )
{
pImp->GetShell()->AddPaintRect( aPaint );
bAddRect = sal_False;
}
else
{
sal_uInt16 i;
SwRegionRects aRegion( aOldRect );
aRegion -= aPaint;
for ( i = 0; i < aRegion.Count(); ++i )
pImp->GetShell()->AddPaintRect( aRegion[i] );
aRegion.ChangeOrigin( aPaint );
aRegion.Remove( 0, aRegion.Count() );
aRegion.Insert( aPaint, 0 );
aRegion -= aOldRect;
for ( i = 0; i < aRegion.Count(); ++i )
pImp->GetShell()->AddPaintRect( aRegion[i] );
}
}
else
{
pImp->GetShell()->AddPaintRect( aPaint );
bAlreadyPainted = sal_True;
// OD 11.11.2002 #104414# - remember frame at complete paint
aFrmAtCompletePaint = pLay->Frm();
}
// OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
// between pages (not only for in online mode).
if ( pLay->IsPageFrm() )
{
const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
if ( bPrev )
{
// top
SwRect aSpaceToPrevPage( pLay->Frm() );
const SwTwips nTop = aSpaceToPrevPage.Top() - nHalfDocBorder;
if ( nTop >= 0 )
aSpaceToPrevPage.Top( nTop );
aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
// left
aSpaceToPrevPage = pLay->Frm();
const SwTwips nLeft = aSpaceToPrevPage.Left() - nHalfDocBorder;
if ( nLeft >= 0 )
aSpaceToPrevPage.Left( nLeft );
aSpaceToPrevPage.Right( pLay->Frm().Left() );
pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
}
if ( bNext )
{
// bottom
SwRect aSpaceToNextPage( pLay->Frm() );
aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
aSpaceToNextPage.Top( pLay->Frm().Bottom() );
pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
// right
aSpaceToNextPage = pLay->Frm();
aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
aSpaceToNextPage.Left( pLay->Frm().Right() );
pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
}
}
}
pLay->ResetCompletePaint();
}
if ( IsPaint() && bAddRect &&
!pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
{
// OD 15.11.2002 #105155# - vertical layout support
SWRECTFN( pLay );
SwRect aRect( pLay->GetUpper()->PaintArea() );
(aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
if ( !pImp->GetShell()->AddPaintRect( aRect ) )
pLay->ResetRetouche();
}
if( bAlreadyPainted )
bAddRect = sal_False;
CheckWaitCrsr();
if ( IsAgain() )
return sal_False;
//Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
if ( pLay->IsFtnFrm() ) //Hat keine LayFrms als Lower.
return bChanged;
SwFrm *pLow = pLay->Lower();
sal_Bool bTabChanged = sal_False;
while ( pLow && pLow->GetUpper() == pLay )
{
if ( pLow->IsLayoutFrm() )
{
if ( pLow->IsTabFrm() )
bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
// bereits zum Loeschen angemeldete Ueberspringen
else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
}
else if ( pImp->GetShell()->IsPaintLocked() )
//Abkuerzung im die Zyklen zu minimieren, bei Lock kommt das
//Paint sowieso (Primaer fuer Browse)
pLow->OptCalc();
if ( IsAgain() )
return sal_False;
pLow = pLow->GetNext();
}
// OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
// area has been already added and after formating its lowers the frame area
// is enlarged.
if ( bAlreadyPainted &&
( pLay->Frm().Width() > aFrmAtCompletePaint.Width() ||
pLay->Frm().Height() > aFrmAtCompletePaint.Height() )
)
{
pImp->GetShell()->AddPaintRect( pLay->Frm() );
}
return bChanged || bTabChanged;
}
sal_Bool SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
{
ASSERT( !IsAgain(), "Ungueltige Seite beachten." );
if ( IsAgain() )
return sal_False;
sal_Bool bChanged = false;
sal_Bool bAddRect = true;
if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
{
//Der Frame hat sich veraendert, er wird jetzt Formatiert
const SwRect aOldRect( pFly->Frm() );
pFly->Calc();
bChanged = aOldRect != pFly->Frm();
if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
pImp->GetShell()->AddPaintRect( pFly->Frm() );
if ( bChanged )
pFly->Invalidate();
else
pFly->Validate();
/*
//mba: it's unclear why we should invalidate always, so I remove it
//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
if ( IsPaint() && bAddRect && pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
pImp->GetShell()->AddPaintRect( pFly->Frm() );
pFly->Invalidate();
*/
bAddRect = false;
pFly->ResetCompletePaint();
}
if ( IsAgain() )
return sal_False;
//Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
sal_Bool bTabChanged = false;
SwFrm *pLow = pFly->Lower();
while ( pLow )
{
if ( pLow->IsLayoutFrm() )
{
if ( pLow->IsTabFrm() )
bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
else
bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
}
pLow = pLow->GetNext();
}
return bChanged || bTabChanged;
}
// OD 31.10.2002 #104100#
// Implement vertical layout support
sal_Bool SwLayAction::FormatLayoutTab( SwTabFrm *pTab, sal_Bool bAddRect )
{
ASSERT( !IsAgain(), "8-) Ungueltige Seite beachten." );
if ( IsAgain() || !pTab->Lower() )
return sal_False;
IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
pTimerAccess->BlockIdling();
sal_Bool bChanged = sal_False;
sal_Bool bPainted = sal_False;
const SwPageFrm *pOldPage = pTab->FindPageFrm();
// OD 31.10.2002 #104100# - vertical layout support
// use macro to declare and init <sal_Bool bVert>, <sal_Bool bRev> and
// <SwRectFn fnRect> for table frame <pTab>.
SWRECTFN( pTab );
if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
{
if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
{
pTab->GetPrev()->SetCompletePaint();
}
const SwRect aOldRect( pTab->Frm() );
pTab->SetLowersFormatted( sal_False );
pTab->Calc();
if ( aOldRect != pTab->Frm() )
{
bChanged = sal_True;
}
const SwRect aPaintFrm = pTab->PaintArea();
if ( IsPaint() && bAddRect )
{
// OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
if ( !pTab->IsCompletePaint() &&
pTab->IsComplete() &&
( pTab->Frm().SSize() != pTab->Prt().SSize() ||
// OD 31.10.2002 #104100# - vertical layout support
(pTab->*fnRect->fnGetLeftMargin)() ) &&
pTab->Frm().HasArea()
)
{
// OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
SwRect aMarginRect;
SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
if ( nLeftMargin > 0)
{
aMarginRect = pTab->Frm();
(aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
pImp->GetShell()->AddPaintRect( aMarginRect );
}
if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
{
aMarginRect = pTab->Frm();
(aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
pImp->GetShell()->AddPaintRect( aMarginRect );
}
SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
if ( nTopMargin > 0)
{
aMarginRect = pTab->Frm();
(aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
pImp->GetShell()->AddPaintRect( aMarginRect );
}
if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
{
aMarginRect = pTab->Frm();
(aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
pImp->GetShell()->AddPaintRect( aMarginRect );
}
}
else if ( pTab->IsCompletePaint() )
{
pImp->GetShell()->AddPaintRect( aPaintFrm );
bAddRect = sal_False;
bPainted = sal_True;
}
if ( pTab->IsRetouche() && !pTab->GetNext() )
{
SwRect aRect( pTab->GetUpper()->PaintArea() );
// OD 04.11.2002 #104100# - vertical layout support
(aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
if ( !pImp->GetShell()->AddPaintRect( aRect ) )
pTab->ResetRetouche();
}
}
else
bAddRect = sal_False;
if ( pTab->IsCompletePaint() && !pOptTab )
pOptTab = pTab;
pTab->ResetCompletePaint();
}
if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
{
// OD 04.10.2002 #102779#
// set correct rectangle for retouche: area between bottom of table frame
// and bottom of paint area of the upper frame.
SwRect aRect( pTab->GetUpper()->PaintArea() );
// OD 04.11.2002 #104100# - vertical layout support
(aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
if ( !pImp->GetShell()->AddPaintRect( aRect ) )
pTab->ResetRetouche();
}
CheckWaitCrsr();
pTimerAccess->UnblockIdling();
//Heftige Abkuerzung!
if ( pTab->IsLowersFormatted() &&
(bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
return sal_False;
//Jetzt noch die Lowers versorgen
if ( IsAgain() )
return sal_False;
// OD 20.10.2003 #112464# - for savety reasons:
// check page number before formatting lowers.
if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
SetNextCycle( sal_True );
// OD 20.10.2003 #112464# - format lowers, only if table frame is valid
if ( pTab->IsValid() )
{
SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
while ( pLow )
{
bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
if ( IsAgain() )
return sal_False;
pLow = (SwLayoutFrm*)pLow->GetNext();
}
}
return bChanged;
}
/*************************************************************************
|*
|* SwLayAction::FormatCntnt()
|*
|* Ersterstellung MA 30. Oct. 92
|* Letzte Aenderung MA 16. Nov. 95
|*
|*************************************************************************/
sal_Bool SwLayAction::FormatCntnt( const SwPageFrm *pPage )
{
const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
const ViewShell *pSh = pRoot->GetCurrShell();
const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
while ( pCntnt && pPage->IsAnLower( pCntnt ) )
{
//Wenn der Cntnt sich eh nicht veraendert koennen wir ein paar
//Abkuerzungen nutzen.
const sal_Bool bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
if ( bFull )
{
//Damit wir nacher nicht suchen muessen.
const sal_Bool bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
const SwLayoutFrm*pOldUpper = pCntnt->GetUpper();
const SwTabFrm *pTab = pCntnt->FindTabFrm();
const sal_Bool bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
const sal_Bool bOldPaint = IsPaint();
bPaint = bOldPaint && !(pTab && pTab == pOptTab);
_FormatCntnt( pCntnt, pPage );
// --> OD 2004-11-05 #i26945# - reset <bPaint> before format objects
bPaint = bOldPaint;
// <--
// OD 2004-05-10 #i28701# - format floating screen object at content frame.
// No format, if action flag <bAgain> is set or action is interrupted.
// OD 2004-08-30 #117736# - allow format on interruption of action, if
// it's the format for this interrupt
// --> OD 2004-11-01 #i23129#, #i36347# - pass correct page frame
// to the object formatter.
if ( !IsAgain() &&
( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
pCntnt->IsTxtFrm() &&
!SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
*(pCntnt->FindPageFrm()), this ) )
// <--
{
return sal_False;
}
if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
{
const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
((SwTxtFrm*)pCntnt)->RecalcAllLines();
if ( IsPaintExtraData() && IsPaint() &&
nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
}
if ( IsAgain() )
return sal_False;
//Wenn Layout oder Flys wieder Invalid sind breche ich die Verarbeitung
//vorlaeufig ab - allerdings nicht fuer die BrowseView, denn dort wird
//das Layout staendig ungueltig, weil die Seitenhoehe angepasst wird.
//Desgleichen wenn der Benutzer weiterarbeiten will und mindestens ein
//Absatz verarbeitet wurde.
if ( (!pTab || (pTab && !bInValid)) )
{
CheckIdleEnd();
// OD 14.04.2003 #106346# - consider interrupt formatting.
if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
( !bBrowse && pPage->IsInvalidLayout() ) ||
// OD 07.05.2003 #109435# - consider interrupt formatting
( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
)
return sal_False;
}
if ( pOldUpper != pCntnt->GetUpper() )
{
const sal_uInt16 nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
if ( nCurNum < pPage->GetPhyPageNum() )
nPreInvaPage = nCurNum;
//Wenn der Frm mehr als eine Seite rueckwaerts geflossen ist, so
//fangen wir nocheinmal von vorn an damit wir nichts auslassen.
if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
{
SetNextCycle( sal_True );
// OD 07.05.2003 #109435# - consider interrupt formatting
if ( !mbFormatCntntOnInterrupt )
{
return sal_False;
}
}
}
//Wenn der Frame die Seite vorwaerts gewechselt hat, so lassen wir
//den Vorgaenger nocheinmal durchlaufen.
//So werden einerseits Vorgaenger erwischt, die jetzt f?r Retouche
//verantwortlich sind, andererseits werden die Fusszeilen
//auch angefasst.
sal_Bool bSetCntnt = sal_True;
if ( pCntntPrev )
{
if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
pPage->InvalidateCntnt();
if ( pOldUpper != pCntnt->GetUpper() &&
pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
{
pCntnt = pCntntPrev;
bSetCntnt = sal_False;
}
}
if ( bSetCntnt )
{
if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
{
const long nBottom = pImp->GetShell()->VisArea().Bottom();
const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
nBottom, pCntnt );
if ( !pTmp )
{
if ( (!(IS_FLYS && IS_INVAFLY) ||
!lcl_FindFirstInvaObj( pPage, nBottom )) &&
(!pPage->IsInvalidLayout() ||
!lcl_FindFirstInvaLay( pPage, nBottom )))
SetBrowseActionStop( sal_True );
// OD 14.04.2003 #106346# - consider interrupt formatting.
if ( !mbFormatCntntOnInterrupt )
{
return sal_False;
}
}
}
pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
}
RESCHEDULE;
}
else
{
if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
{
const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
((SwTxtFrm*)pCntnt)->RecalcAllLines();
if ( IsPaintExtraData() && IsPaint() &&
nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
}
//Falls der Frm schon vor der Abarbeitung hier formatiert wurde.
if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
IsPaint() )
PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
if ( IsIdle() )
{
CheckIdleEnd();
// OD 14.04.2003 #106346# - consider interrupt formatting.
if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
return sal_False;
}
if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
{
const long nBottom = pImp->GetShell()->VisArea().Bottom();
const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
nBottom, pCntnt );
if ( !pTmp )
{
if ( (!(IS_FLYS && IS_INVAFLY) ||
!lcl_FindFirstInvaObj( pPage, nBottom )) &&
(!pPage->IsInvalidLayout() ||
!lcl_FindFirstInvaLay( pPage, nBottom )))
SetBrowseActionStop( sal_True );
// OD 14.04.2003 #106346# - consider interrupt formatting.
if ( !mbFormatCntntOnInterrupt )
{
return sal_False;
}
}
}
pCntnt = pCntnt->GetNextCntntFrm();
}
}
CheckWaitCrsr();
// OD 14.04.2003 #106346# - consider interrupt formatting.
return !IsInterrupt() || mbFormatCntntOnInterrupt;
}
/*************************************************************************
|*
|* SwLayAction::_FormatCntnt()
|*
|* Beschreibung Returnt sal_True wenn der Absatz verarbeitet wurde,
|* sal_False wenn es nichts zu verarbeiten gab.
|* Ersterstellung MA 07. Dec. 92
|* Letzte Aenderung MA 11. Mar. 98
|*
|*************************************************************************/
void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
const SwPageFrm *pPage )
{
//wird sind hier evtl. nur angekommen, weil der Cntnt DrawObjekte haelt.
const sal_Bool bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
!pCntnt->IsRetouche();
SWRECTFN( pCntnt )
if ( !bDrawObjsOnly && IsPaint() )
{
const SwRect aOldRect( pCntnt->UnionFrm() );
const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
pCntnt->OptCalc();
if( IsAgain() )
return;
if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
(aOldRect.*fnRect->fnGetBottom)() ) < 0 )
{
pCntnt->SetRetouche();
}
PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
}
else
{
if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
(pCntnt->Frm().*fnRect->fnGetBottom)() );
pCntnt->OptCalc();
}
}
/*************************************************************************
|*
|* SwLayAction::_FormatFlyCntnt()
|*
|* Beschreibung:
|* - Returnt sal_True wenn alle Cntnts des Flys vollstaendig verarbeitet
|* wurden. sal_False wenn vorzeitig unterbrochen wurde.
|* Ersterstellung MA 02. Dec. 92
|* Letzte Aenderung MA 24. Jun. 96
|*
|*************************************************************************/
sal_Bool SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
{
const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
while ( pCntnt )
{
// OD 2004-05-10 #i28701#
_FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
// --> OD 2004-07-23 #i28701# - format floating screen objects
// at content text frame
// --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame
// to the object formatter.
if ( pCntnt->IsTxtFrm() &&
!SwObjectFormatter::FormatObjsAtFrm(
*(const_cast<SwCntntFrm*>(pCntnt)),
*(pCntnt->FindPageFrm()), this ) )
// <--
{
// restart format with first content
pCntnt = pFly->ContainsCntnt();
continue;
}
// <--
if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
{
const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
((SwTxtFrm*)pCntnt)->RecalcAllLines();
if ( IsPaintExtraData() && IsPaint() &&
nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
}
if ( IsAgain() )
return sal_False;
//wenn eine Eingabe anliegt breche ich die Verarbeitung ab.
if ( !pFly->IsFlyInCntFrm() )
{
CheckIdleEnd();
// OD 14.04.2003 #106346# - consider interrupt formatting.
if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
return sal_False;
}
pCntnt = pCntnt->GetNextCntntFrm();
}
CheckWaitCrsr();
// OD 14.04.2003 #106346# - consider interrupt formatting.
return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
}
sal_Bool SwLayAction::IsStopPrt() const
{
sal_Bool bResult = sal_False;
if (pImp != NULL && pProgress != NULL)
bResult = pImp->IsStopPrt();
return bResult;
}
/*************************************************************************
|*
|* SwLayAction::FormatSpelling(), _FormatSpelling()
|*
|* Ersterstellung AMA 01. Feb. 96
|* Letzte Aenderung AMA 01. Feb. 96
|*
|*************************************************************************/
sal_Bool SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
{
ASSERT( pCnt->IsTxtFrm(), "NoTxt neighbour of Txt" );
// robust against misuse by e.g. #i52542#
if( !pCnt->IsTxtFrm() )
return sal_False;
const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
bool bProcess = false;
switch ( eJob )
{
case ONLINE_SPELLING :
bProcess = pTxtNode->IsWrongDirty(); break;
case AUTOCOMPLETE_WORDS :
bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
case WORD_COUNT :
bProcess = pTxtNode->IsWordCountDirty(); break;
case SMART_TAGS : // SMARTTAGS
bProcess = pTxtNode->IsSmartTagDirty(); break;
}
if( bProcess )
{
ViewShell *pSh = pImp->GetShell();
if( STRING_LEN == nTxtPos )
{
--nTxtPos;
if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
{
SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
{
pCntntNode = pCrsr->GetCntntNode();
nTxtPos = pCrsr->GetPoint()->nContent.GetIndex();
}
}
}
switch ( eJob )
{
case ONLINE_SPELLING :
{
SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode, *pSh->GetViewOptions(), nTxtPos ) );
bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
if( !bPageValid )
bAllValid = sal_False;
if ( aRepaint.HasArea() )
pImp->GetShell()->InvalidateWindows( aRepaint );
if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
return sal_True;
break;
}
case AUTOCOMPLETE_WORDS :
((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
if ( Application::AnyInput( INPUT_ANY ) )
return sal_True;
break;
case WORD_COUNT :
{
const xub_StrLen nEnd = pTxtNode->GetTxt().Len();
SwDocStat aStat;
pTxtNode->CountWords( aStat, 0, nEnd );
if ( Application::AnyInput( INPUT_ANY ) )
return sal_True;
break;
}
case SMART_TAGS : // SMARTTAGS
{
try {
const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
if( !bPageValid )
bAllValid = sal_False;
if ( aRepaint.HasArea() )
pImp->GetShell()->InvalidateWindows( aRepaint );
} catch( const ::com::sun::star::uno::RuntimeException& e) {
// #i122885# handle smarttag problems gracefully and provide diagnostics
DBG_WARNING( rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
}
if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
return sal_True;
break;
}
}
}
//Die im Absatz verankerten Flys wollen auch mitspielen.
if ( pCnt->GetDrawObjs() )
{
const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
{
SwAnchoredObject* pObj = rObjs[i];
if ( pObj->ISA(SwFlyFrm) )
{
SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
if ( pFly->IsFlyInCntFrm() )
{
const SwCntntFrm *pC = pFly->ContainsCntnt();
while( pC )
{
if ( pC->IsTxtFrm() )
{
if ( _DoIdleJob( pC, eJob ) )
return sal_True;
}
pC = pC->GetNextCntntFrm();
}
}
}
}
}
return sal_False;
}
sal_Bool SwLayIdle::DoIdleJob( IdleJobType eJob, sal_Bool bVisAreaOnly )
{
//Spellchecken aller Inhalte der Seiten. Entweder nur der sichtbaren
//Seiten oder eben aller.
const ViewShell* pViewShell = pImp->GetShell();
const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
const SwDoc* pDoc = pViewShell->GetDoc();
switch ( eJob )
{
case ONLINE_SPELLING :
if( !pViewOptions->IsOnlineSpell() )
return sal_False;
break;
case AUTOCOMPLETE_WORDS :
if( !pViewOptions->IsAutoCompleteWords() ||
pDoc->GetAutoCompleteWords().IsLockWordLstLocked())
return sal_False;
break;
case WORD_COUNT :
if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
return sal_False;
break;
case SMART_TAGS :
if ( pDoc->GetDocShell()->IsHelpDocument() ||
pDoc->isXForms() ||
!SwSmartTagMgr::Get().IsSmartTagsEnabled() )
return sal_False;
break;
default: ASSERT( false, "Unknown idle job type" )
}
SwPageFrm *pPage;
if ( bVisAreaOnly )
pPage = pImp->GetFirstVisPage();
else
pPage = (SwPageFrm*)pRoot->Lower();
pCntntNode = NULL;
nTxtPos = STRING_LEN;
while ( pPage )
{
bPageValid = sal_True;
const SwCntntFrm *pCnt = pPage->ContainsCntnt();
while( pCnt && pPage->IsAnLower( pCnt ) )
{
if ( _DoIdleJob( pCnt, eJob ) )
return sal_True;
pCnt = pCnt->GetNextCntntFrm();
}
if ( pPage->GetSortedObjs() )
{
for ( sal_uInt16 i = 0; pPage->GetSortedObjs() &&
i < pPage->GetSortedObjs()->Count(); ++i )
{
const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
if ( pObj->ISA(SwFlyFrm) )
{
const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
const SwCntntFrm *pC = pFly->ContainsCntnt();
while( pC )
{
if ( pC->IsTxtFrm() )
{
if ( _DoIdleJob( pC, eJob ) )
return sal_True;
}
pC = pC->GetNextCntntFrm();
}
}
}
}
if( bPageValid )
{
switch ( eJob )
{
case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
case WORD_COUNT : pPage->ValidateWordCount(); break;
case SMART_TAGS : pPage->ValidateSmartTags(); break; // SMARTTAGS
}
}
pPage = (SwPageFrm*)pPage->GetNext();
if ( pPage && bVisAreaOnly &&
!pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
break;
}
return sal_False;
}
#ifdef DBG_UTIL
#if OSL_DEBUG_LEVEL > 1
/*************************************************************************
|*
|* void SwLayIdle::SwLayIdle()
|*
|* Ersterstellung MA ??
|* Letzte Aenderung MA 09. Jun. 94
|*
|*************************************************************************/
void SwLayIdle::ShowIdle( ColorData eColorData )
{
if ( !bIndicator )
{
bIndicator = sal_True;
Window *pWin = pImp->GetShell()->GetWin();
if ( pWin )
{
Rectangle aRect( 0, 0, 5, 5 );
aRect = pWin->PixelToLogic( aRect );
// OD 2004-04-23 #116347#
pWin->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
pWin->SetFillColor( eColorData );
pWin->SetLineColor();
pWin->DrawRect( aRect );
pWin->Pop();
}
}
}
#define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
#else
#define SHOW_IDLE( ColorData )
#endif
#else
#define SHOW_IDLE( ColorData )
#endif
/*************************************************************************
|*
|* void SwLayIdle::SwLayIdle()
|*
|* Ersterstellung MA 30. Oct. 92
|* Letzte Aenderung MA 23. May. 95
|*
|*************************************************************************/
SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
pRoot( pRt ),
pImp( pI )
#ifdef DBG_UTIL
#if OSL_DEBUG_LEVEL > 1
, bIndicator( sal_False )
#endif
#endif
{
pImp->pIdleAct = this;
SHOW_IDLE( COL_LIGHTRED );
pImp->GetShell()->EnableSmooth( sal_False );
//Zuerst den Sichtbaren Bereich Spellchecken, nur wenn dort nichts
//zu tun war wird das IdleFormat angestossen.
if ( !DoIdleJob( SMART_TAGS, sal_True ) &&
!DoIdleJob( ONLINE_SPELLING, sal_True ) &&
!DoIdleJob( AUTOCOMPLETE_WORDS, sal_True ) ) // SMARTTAGS
{
//Formatieren und ggf. Repaint-Rechtecke an der ViewShell vormerken.
//Dabei muessen kuenstliche Actions laufen, damit es z.B. bei
//Veraenderungen der Seitenzahl nicht zu unerwuenschten Effekten kommt.
//Wir merken uns bei welchen Shells der Cursor sichtbar ist, damit
//wir ihn bei Dokumentaenderung ggf. wieder sichbar machen koennen.
SvBools aBools;
ViewShell *pSh = pImp->GetShell();
do
{ ++pSh->nStartAction;
sal_Bool bVis = sal_False;
if ( pSh->ISA(SwCrsrShell) )
{
#ifdef SW_CRSR_TIMER
((SwCrsrShell*)pSh)->ChgCrsrTimerFlag( sal_False );
#endif
bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
}
aBools.push_back( bVis );
pSh = (ViewShell*)pSh->GetNext();
} while ( pSh != pImp->GetShell() );
SwLayAction aAction( pRoot, pImp );
aAction.SetInputType( INPUT_ANY );
aAction.SetIdle( sal_True );
aAction.SetWaitAllowed( sal_False );
aAction.Action();
//Weitere Start-/EndActions nur auf wenn irgendwo Paints aufgelaufen
//sind oder wenn sich die Sichtbarkeit des CharRects veraendert hat.
sal_Bool bActions = sal_False;
sal_uInt16 nBoolIdx = 0;
do
{
--pSh->nStartAction;
if ( pSh->Imp()->GetRegion() )
bActions = sal_True;
else
{
SwRect aTmp( pSh->VisArea() );
pSh->UISizeNotify();
// --> FME 2006-08-03 #137134#
// Are we supposed to crash if pSh isn't a cursor shell?!
// bActions |= aTmp != pSh->VisArea() ||
// aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
// aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
// and the cursor is visible.
bActions |= aTmp != pSh->VisArea();
if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
{
bActions |= aBools[nBoolIdx] !=
static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
}
}
pSh = (ViewShell*)pSh->GetNext();
++nBoolIdx;
} while ( pSh != pImp->GetShell() );
if ( bActions )
{
//Start- EndActions aufsetzen. ueber die CrsrShell, damit der
//Cursor/Selektion und die VisArea korrekt gesetzt werden.
nBoolIdx = 0;
do
{
sal_Bool bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
if ( bCrsrShell )
((SwCrsrShell*)pSh)->SttCrsrMove();
// else
// pSh->StartAction();
//Wenn Paints aufgelaufen sind, ist es am sinnvollsten schlicht das
//gesamte Window zu invalidieren. Anderfalls gibt es Paintprobleme
//deren Loesung unverhaeltnissmaessig aufwendig waere.
//fix(18176):
SwViewImp *pViewImp = pSh->Imp();
sal_Bool bUnlock = sal_False;
if ( pViewImp->GetRegion() )
{
pViewImp->DelRegion();
//Fuer Repaint mit virtuellem Device sorgen.
pSh->LockPaint();
bUnlock = sal_True;
}
if ( bCrsrShell )
//Wenn der Crsr sichbar war wieder sichbar machen, sonst
//EndCrsrMove mit sal_True fuer IdleEnd.
((SwCrsrShell*)pSh)->EndCrsrMove( sal_True^aBools[nBoolIdx] );
// else
// pSh->EndAction();
if( bUnlock )
{
if( bCrsrShell )
{
// UnlockPaint overwrite the selection from the
// CrsrShell and calls the virtual method paint
// to fill the virtual device. This fill dont have
// paint the selection! -> Set the focus flag at
// CrsrShell and it dont paint the selection.
((SwCrsrShell*)pSh)->ShLooseFcs();
pSh->UnlockPaint( sal_True );
((SwCrsrShell*)pSh)->ShGetFcs( sal_False );
}
else
pSh->UnlockPaint( sal_True );
}
pSh = (ViewShell*)pSh->GetNext();
++nBoolIdx;
} while ( pSh != pImp->GetShell() );
}
if ( !aAction.IsInterrupt() )
{
if ( !DoIdleJob( WORD_COUNT, sal_False ) )
if ( !DoIdleJob( SMART_TAGS, sal_False ) )
if ( !DoIdleJob( ONLINE_SPELLING, sal_False ) )
DoIdleJob( AUTOCOMPLETE_WORDS, sal_False ); // SMARTTAGS
}
bool bInValid = false;
const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
const ViewShell* pViewShell = pImp->GetShell();
// See conditions in DoIdleJob()
const sal_Bool bSpell = rVOpt.IsOnlineSpell();
const sal_Bool bACmplWrd = rVOpt.IsAutoCompleteWords();
const sal_Bool bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
const sal_Bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
!pViewShell->GetDoc()->isXForms() &&
SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
do
{
bInValid = pPg->IsInvalidCntnt() || pPg->IsInvalidLayout() ||
pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
pPg->IsInvalidFlyInCnt() ||
(bSpell && pPg->IsInvalidSpelling()) ||
(bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
(bWordCount && pPg->IsInvalidWordCount()) ||
(bSmartTags && pPg->IsInvalidSmartTags()); // SMARTTAGS
pPg = (SwPageFrm*)pPg->GetNext();
} while ( pPg && !bInValid );
if ( !bInValid )
{
pRoot->ResetIdleFormat();
SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
pDocShell->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
}
}
pImp->GetShell()->EnableSmooth( sal_True );
if( pImp->IsAccessible() )
pImp->FireAccessibleEvents();
#ifdef DBG_UTIL
#if OSL_DEBUG_LEVEL > 1
if ( bIndicator && pImp->GetShell()->GetWin() )
{
// #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
// This should be replaced by an overlay object in the future, anyways. Since it's only for debug
// purposes, it is not urgent.
static bool bCheckWithoutInvalidating(true);
if(bCheckWithoutInvalidating)
{
bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
}
else
{
Rectangle aRect( 0, 0, 5, 5 );
aRect = pImp->GetShell()->GetWin()->PixelToLogic( aRect );
pImp->GetShell()->GetWin()->Invalidate( aRect );
}
}
#endif
#endif
}
SwLayIdle::~SwLayIdle()
{
pImp->pIdleAct = 0;
}