update credits
[LibreOffice.git] / sw / source / core / layout / layact.cxx
blob71659ce4ab95c47bbe019c96c440b219e63628f3
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <time.h>
22 #include "rootfrm.hxx"
23 #include "pagefrm.hxx"
24 #include "cntfrm.hxx"
25 #include "doc.hxx"
26 #include "IDocumentDrawModelAccess.hxx"
27 #include "IDocumentSettingAccess.hxx"
28 #include "IDocumentLayoutAccess.hxx"
29 #include "IDocumentStatistics.hxx"
30 #include "IDocumentTimerAccess.hxx"
31 #include "viewimp.hxx"
32 #include "crsrsh.hxx"
33 #include "dflyobj.hxx"
34 #include "flyfrm.hxx"
35 #include "frmtool.hxx"
36 #include "dcontact.hxx"
37 #include "ndtxt.hxx" // OnlineSpelling
38 #include "frmfmt.hxx"
39 #include "swregion.hxx"
40 #include "viewopt.hxx" // test OnlineSpelling using internal TabPage
41 #include "pam.hxx" // OnlineSpelling needed because of the current cursor position
42 #include "dbg_lay.hxx"
43 #include "layouter.hxx" // LoopControlling
44 #include "docstat.hxx"
45 #include "swevent.hxx"
47 #include <sfx2/event.hxx>
49 #include <ftnidx.hxx>
50 #include <vcl/window.hxx>
51 #include <vcl/svapp.hxx>
52 #include <editeng/opaqitem.hxx>
53 #include <editeng/brushitem.hxx>
54 #include <SwSmartTagMgr.hxx>
56 #define _LAYACT_CXX
57 #include "layact.hxx"
58 #include <swwait.hxx>
59 #include <fmtsrnd.hxx>
60 #include <fmtanchr.hxx>
61 #include <tools/shl.hxx>
62 #include <sfx2/progress.hxx>
63 #include <docsh.hxx>
65 #include "swmodule.hxx"
66 #include "fmtline.hxx"
67 #include "tabfrm.hxx"
68 #include "ftnfrm.hxx"
69 #include "txtfrm.hxx"
70 #include "notxtfrm.hxx"
71 #include "flyfrms.hxx"
72 #include "mdiexp.hxx"
73 #include "fmtornt.hxx"
74 #include "sectfrm.hxx"
75 #include "lineinfo.hxx"
76 #include <acmplwrd.hxx>
77 // #i28701#
78 #include <sortedobjs.hxx>
79 #include <objectformatter.hxx>
80 #include <PostItMgr.hxx>
81 #include <vector>
83 /*************************************************************************
85 |* SwLayAction static stuff
87 |*************************************************************************/
89 #define IS_FLYS (pPage->GetSortedObjs())
90 #define IS_INVAFLY (pPage->IsInvalidFly())
93 // Save some typing work to avoid accessing destroyed pages.
94 #if OSL_DEBUG_LEVEL > 1
96 static void BreakPoint()
98 return;
101 #define XCHECKPAGE \
102 { if ( IsAgain() ) \
103 { BreakPoint(); \
104 if( bNoLoop ) \
105 pLayoutAccess->GetLayouter()->EndLoopControl(); \
106 return; \
109 #else
110 #define XCHECKPAGE \
111 { if ( IsAgain() ) \
113 if( bNoLoop ) \
114 pLayoutAccess->GetLayouter()->EndLoopControl(); \
115 return; \
118 #endif
120 #define RESCHEDULE \
122 if ( IsReschedule() ) \
124 if (pProgress) pProgress->Reschedule(); \
125 ::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
129 inline sal_uLong Ticks()
131 return 1000 * clock() / CLOCKS_PER_SEC;
134 void SwLayAction::CheckWaitCrsr()
136 RESCHEDULE
137 if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
138 ((Ticks() - GetStartTicks()) >= CLOCKS_PER_SEC/2) )
140 pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), sal_True );
144 /*************************************************************************
146 |* SwLayAction::CheckIdleEnd()
148 |*************************************************************************/
149 // Time over already?
150 inline void SwLayAction::CheckIdleEnd()
152 if ( !IsInput() )
153 bInput = GetInputType() && Application::AnyInput( GetInputType() );
156 /*************************************************************************
158 |* SwLayAction::SetStatBar()
160 |*************************************************************************/
161 void SwLayAction::SetStatBar( sal_Bool bNew )
163 if ( bNew )
165 nEndPage = pRoot->GetPageNum();
166 nEndPage += nEndPage * 10 / 100;
168 else
169 nEndPage = USHRT_MAX;
172 /*************************************************************************
174 |* SwLayAction::PaintCntnt()
176 |* Description Depending of the type, the Cntnt is output
177 |* according to it's changes, or the area to be outputted is
178 |* registered with the region, respectively.
179 |* PaintCntnt: fills the region
181 |*************************************************************************/
182 sal_Bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
183 const SwPageFrm *pPage )
185 SwRegionRects aTmp( rRect );
186 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
187 const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
188 sal_uInt16 i;
190 for ( i = 0; i < rObjs.Count() && !aTmp.empty(); ++i )
192 SdrObject *pO = rObjs[i]->DrawObj();
193 if ( !pO->ISA(SwVirtFlyDrawObj) )
194 continue;
196 // OD 2004-01-15 #110582# - do not consider invisible objects
197 const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
198 if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
200 continue;
203 SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
205 if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
206 continue;
208 if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
209 continue;
211 if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
212 continue;
214 if ( pSelfFly )
216 const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
217 if ( pO->GetLayer() == pTmp->GetLayer() )
219 if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
220 // Only look at things above us, if inside the same layer
221 continue;
223 else
225 const sal_Bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
226 if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
227 // Things from other layers are only interesting to us if
228 // they're not transparent or lie inwards
229 continue;
233 /// OD 19.08.2002 #99657#
234 /// Fly frame without a lower have to be subtracted from paint region.
235 /// For checking, if fly frame contains transparent graphic or
236 /// has surrounded contour, assure that fly frame has a lower
237 if ( pFly->Lower() &&
238 pFly->Lower()->IsNoTxtFrm() &&
239 ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
240 pFly->GetFmt()->GetSurround().IsContour() )
243 continue;
246 /// OD 19.08.2002 #99657#
247 /// Region of a fly frame with transparent background or a transparent
248 /// shadow have not to be subtracted from paint region
249 if ( pFly->IsBackgroundTransparent() ||
250 pFly->IsShadowTransparent() )
252 continue;
255 aTmp -= pFly->Frm();
258 sal_Bool bRetPaint = sal_False;
259 for ( SwRects::const_iterator it = aTmp.begin(); it != aTmp.end(); ++it )
260 bRetPaint |= pImp->GetShell()->AddPaintRect( *it );
261 return bRetPaint;
264 inline sal_Bool SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
265 const SwPageFrm *pPage,
266 const SwRect &rRect )
268 if ( rRect.HasArea() )
270 if ( pPage->GetSortedObjs() )
271 return PaintWithoutFlys( rRect, pCntnt, pPage );
272 else
273 return pImp->GetShell()->AddPaintRect( rRect );
275 return sal_False;
278 void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
279 const SwPageFrm *pPage,
280 const SwRect &rOldRect,
281 long nOldBottom )
283 SWRECTFN( pCnt )
285 if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
287 SwRect aPaint( pCnt->PaintArea() );
288 if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
289 pCnt->ResetCompletePaint();
291 else
293 // paint the area between printing bottom and frame bottom and
294 // the area left and right beside the frame, if its height changed.
295 long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
296 long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
297 const bool bHeightDiff = nOldHeight != nNewHeight;
298 if( bHeightDiff )
300 // OD 05.11.2002 #94454# - consider whole potential paint area.
301 //SwRect aDrawRect( pCnt->UnionFrm( sal_True ) );
302 SwRect aDrawRect( pCnt->PaintArea() );
303 if( nOldHeight > nNewHeight )
304 nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
305 (aDrawRect.*fnRect->fnSetTop)( nOldBottom );
306 _PaintCntnt( pCnt, pPage, aDrawRect );
308 // paint content area
309 SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
310 _PaintCntnt( pCnt, pPage, aPaintRect );
313 if ( pCnt->IsRetouche() && !pCnt->GetNext() )
315 const SwFrm *pTmp = pCnt;
316 if( pCnt->IsInSct() )
318 const SwSectionFrm* pSct = pCnt->FindSctFrm();
319 if( pSct->IsRetouche() && !pSct->GetNext() )
320 pTmp = pSct;
322 SwRect aRect( pTmp->GetUpper()->PaintArea() );
323 (aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
324 if ( !_PaintCntnt( pCnt, pPage, aRect ) )
325 pCnt->ResetRetouche();
329 /*************************************************************************
331 |* SwLayAction::SwLayAction()
333 |*************************************************************************/
334 SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
335 pRoot( pRt ),
336 pImp( pI ),
337 pOptTab( 0 ),
338 pWait( 0 ),
339 pProgress(NULL),
340 nPreInvaPage( USHRT_MAX ),
341 nStartTicks( Ticks() ),
342 nInputType( 0 ),
343 nEndPage( USHRT_MAX ),
344 nCheckPageNum( USHRT_MAX )
346 bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
347 bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
348 bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
349 bUpdateExpFlds = bBrowseActionStop = bActionInProgress = sal_False;
350 // OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
351 mbFormatCntntOnInterrupt = sal_False;
353 pImp->pLayAct = this; // register there
356 SwLayAction::~SwLayAction()
358 OSL_ENSURE( !pWait, "Wait object not destroyed" );
359 pImp->pLayAct = 0; // unregister
362 /*************************************************************************
364 |* SwLayAction::Reset()
366 |*************************************************************************/
367 void SwLayAction::Reset()
369 pOptTab = 0;
370 nStartTicks = Ticks();
371 nInputType = 0;
372 nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
373 bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
374 bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
375 bUpdateExpFlds = bBrowseActionStop = sal_False;
378 /*************************************************************************
380 |* SwLayAction::RemoveEmptyBrowserPages()
382 |*************************************************************************/
384 sal_Bool SwLayAction::RemoveEmptyBrowserPages()
386 // switching from the normal to the browser mode, empty pages may be
387 // retained for an annoyingly long time, so delete them here
388 sal_Bool bRet = sal_False;
389 const ViewShell *pSh = pRoot->GetCurrShell();
390 if( pSh && pSh->GetViewOptions()->getBrowseMode() )
392 SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
395 if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->Count()) ||
396 pPage->ContainsCntnt() )
397 pPage = (SwPageFrm*)pPage->GetNext();
398 else
400 bRet = sal_True;
401 SwPageFrm *pDel = pPage;
402 pPage = (SwPageFrm*)pPage->GetNext();
403 pDel->Cut();
404 delete pDel;
406 } while ( pPage );
408 return bRet;
412 /*************************************************************************
414 |* SwLayAction::Action()
416 |*************************************************************************/
417 void SwLayAction::Action()
419 bActionInProgress = sal_True;
421 //TurboMode? Hands-off during idle-format
422 if ( IsPaint() && !IsIdle() && TurboAction() )
424 delete pWait, pWait = 0;
425 pRoot->ResetTurboFlag();
426 bActionInProgress = sal_False;
427 pRoot->DeleteEmptySct();
428 return;
430 else if ( pRoot->GetTurbo() )
432 pRoot->DisallowTurbo();
433 const SwFrm *pFrm = pRoot->GetTurbo();
434 pRoot->ResetTurbo();
435 pFrm->InvalidatePage();
437 pRoot->DisallowTurbo();
439 if ( IsCalcLayout() )
440 SetCheckPages( sal_False );
442 InternalAction();
443 bAgain |= RemoveEmptyBrowserPages();
444 while ( IsAgain() )
446 bAgain = bNextCycle = sal_False;
447 InternalAction();
448 bAgain |= RemoveEmptyBrowserPages();
450 pRoot->DeleteEmptySct();
452 delete pWait, pWait = 0;
454 //Turbo-Action permitted again for all cases.
455 pRoot->ResetTurboFlag();
456 pRoot->ResetTurbo();
458 SetCheckPages( sal_True );
460 bActionInProgress = sal_False;
463 SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
465 SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
466 SwCntntFrm *pChk = pCnt;
467 sal_Bool bPageChgd = sal_False;
468 while ( pCnt && pCnt->IsFollow() )
469 pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
470 if ( pCnt && pChk != pCnt )
471 { bPageChgd = sal_True;
472 pPage = pCnt->FindPageFrm();
475 if ( !pPage->GetFmt()->GetDoc()->GetFtnIdxs().empty() )
477 SwFtnContFrm *pCont = pPage->FindFtnCont();
478 if ( pCont )
480 pCnt = pCont->ContainsCntnt();
481 pChk = pCnt;
482 while ( pCnt && pCnt->IsFollow() )
483 pCnt = (SwCntntFrm*)pCnt->FindPrev();
484 if ( pCnt && pCnt != pChk )
486 if ( bPageChgd )
488 // Use the 'topmost' page
489 SwPageFrm *pTmp = pCnt->FindPageFrm();
490 if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
491 pPage = pTmp;
493 else
494 pPage = pCnt->FindPageFrm();
498 return pPage;
501 // #114798# - unlock position on start and end of page
502 // layout process.
503 static void unlockPositionOfObjects( SwPageFrm *pPageFrm )
505 assert( pPageFrm );
507 SwSortedObjs* pObjs = pPageFrm->GetSortedObjs();
508 if ( pObjs )
510 sal_uInt32 i = 0;
511 for ( ; i < pObjs->Count(); ++i )
513 SwAnchoredObject* pObj = (*pObjs)[i];
514 pObj->UnlockPosition();
519 void SwLayAction::InternalAction()
521 OSL_ENSURE( pRoot->Lower()->IsPageFrm(), ":-( No page below the root.");
523 pRoot->Calc();
525 // Figure out the first invalid page or the first one to be formatted,
526 // respectively. A complete-action means the first invalid page.
527 // However, the first page to be formatted might be the one having the
528 // number 1. If we're doing a fake formatting, the number of the first
529 // page is the number of the first visible page.
530 SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
531 pImp->GetFirstVisPage();
532 if ( !pPage )
533 pPage = (SwPageFrm*)pRoot->Lower();
535 // If there's a first-flow-Cntnt in the first visible page that's also a Follow,
536 // we switch the page back to the original master of that Cntnt.
537 if ( !IsComplete() )
538 pPage = CheckFirstVisPage( pPage );
539 sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
541 while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
542 pPage = (SwPageFrm*)pPage->GetNext();
544 IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
545 sal_Bool bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : sal_False;
546 sal_uInt16 nPercentPageNum = 0;
547 while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
549 if ( !pPage && nCheckPageNum != USHRT_MAX &&
550 (!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
552 if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
554 SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
555 while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
556 pPg = (SwPageFrm*)pPg->GetNext();
557 if ( pPg )
558 pPage = pPg;
559 if ( !pPage )
560 break;
562 SwPageFrm *pTmp = pPage->GetPrev() ?
563 (SwPageFrm*)pPage->GetPrev() : pPage;
564 SetCheckPages( sal_True );
565 SwFrm::CheckPageDescs( pPage );
566 SetCheckPages( sal_False );
567 nCheckPageNum = USHRT_MAX;
568 pPage = pTmp;
569 continue;
572 if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
574 nPercentPageNum = pPage->GetPhyPageNum();
575 ::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
577 pOptTab = 0;
578 // No Shortcut for Idle or CalcLayout
579 if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
581 pRoot->DeleteEmptySct();
582 XCHECKPAGE;
583 if ( !IsInterrupt() &&
584 (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
586 if ( pRoot->IsAssertFlyPages() )
587 pRoot->AssertFlyPages();
588 if ( pRoot->IsSuperfluous() )
590 sal_Bool bOld = IsAgain();
591 pRoot->RemoveSuperfluous();
592 bAgain = bOld;
594 if ( IsAgain() )
596 if( bNoLoop )
597 pLayoutAccess->GetLayouter()->EndLoopControl();
598 return;
600 pPage = (SwPageFrm*)pRoot->Lower();
601 while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
602 pPage = (SwPageFrm*)pPage->GetNext();
603 while ( pPage && pPage->GetNext() &&
604 pPage->GetPhyPageNum() < nFirstPageNum )
605 pPage = (SwPageFrm*)pPage->GetNext();
606 continue;
608 break;
610 else
612 pRoot->DeleteEmptySct();
613 XCHECKPAGE;
615 while ( !IsInterrupt() && !IsNextCycle() &&
616 ((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
618 unlockPositionOfObjects( pPage );
620 // #i28701#
621 SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
622 if ( !IS_FLYS )
624 // If there are no (more) Flys, the flags are superfluous.
625 pPage->ValidateFlyLayout();
626 pPage->ValidateFlyCntnt();
628 // #i28701# - change condition
629 while ( !IsInterrupt() && !IsNextCycle() &&
630 ( pPage->IsInvalid() ||
631 (IS_FLYS && IS_INVAFLY) ) )
633 PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
634 XCHECKPAGE;
636 // #i81146# new loop control
637 sal_uInt16 nLoopControlRuns_1 = 0;
638 const sal_uInt16 nLoopControlMax = 20;
640 while ( !IsNextCycle() && pPage->IsInvalidLayout() )
642 pPage->ValidateLayout();
644 if ( ++nLoopControlRuns_1 > nLoopControlMax )
646 OSL_FAIL( "LoopControl_1 in SwLayAction::InternalAction" );
647 break;
650 FormatLayout( pPage );
651 XCHECKPAGE;
653 // #i28701# - change condition
654 if ( !IsNextCycle() &&
655 ( pPage->IsInvalidCntnt() ||
656 (IS_FLYS && IS_INVAFLY) ) )
658 pPage->ValidateFlyInCnt();
659 pPage->ValidateCntnt();
660 // #i28701#
661 pPage->ValidateFlyLayout();
662 pPage->ValidateFlyCntnt();
663 if ( !FormatCntnt( pPage ) )
665 XCHECKPAGE;
666 pPage->InvalidateCntnt();
667 pPage->InvalidateFlyInCnt();
668 // #i28701#
669 pPage->InvalidateFlyLayout();
670 pPage->InvalidateFlyCntnt();
671 if ( IsBrowseActionStop() )
672 bInput = sal_True;
675 if( bNoLoop )
676 pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
679 unlockPositionOfObjects( pPage );
682 // A previous page may be invalid again.
683 XCHECKPAGE;
684 if ( !IS_FLYS )
686 // If there are no (more) Flys, the flags are superfluous.
687 pPage->ValidateFlyLayout();
688 pPage->ValidateFlyCntnt();
690 if ( !IsInterrupt() )
692 SetNextCycle( sal_False );
694 if ( nPreInvaPage != USHRT_MAX )
696 if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
698 pImp->SetFirstVisPageInvalid();
699 SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
700 nFirstPageNum = pTmpPage->GetPhyPageNum();
701 if( nPreInvaPage < nFirstPageNum )
703 nPreInvaPage = nFirstPageNum;
704 pPage = pTmpPage;
707 while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
708 pPage = (SwPageFrm*)pPage->GetPrev();
709 nPreInvaPage = USHRT_MAX;
712 while ( pPage->GetPrev() &&
713 ( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
714 ( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
715 ((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
716 (((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
717 nFirstPageNum) )
719 pPage = (SwPageFrm*)pPage->GetPrev();
722 // Continue to the next invalid page
723 while ( pPage && !pPage->IsInvalid() &&
724 (!IS_FLYS || !IS_INVAFLY) )
726 pPage = (SwPageFrm*)pPage->GetNext();
728 if( bNoLoop )
729 pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
731 CheckIdleEnd();
733 if ( !pPage && !IsInterrupt() &&
734 (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
736 if ( pRoot->IsAssertFlyPages() )
737 pRoot->AssertFlyPages();
738 if ( pRoot->IsSuperfluous() )
740 sal_Bool bOld = IsAgain();
741 pRoot->RemoveSuperfluous();
742 bAgain = bOld;
744 if ( IsAgain() )
746 if( bNoLoop )
747 pLayoutAccess->GetLayouter()->EndLoopControl();
748 return;
750 pPage = (SwPageFrm*)pRoot->Lower();
751 while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
752 pPage = (SwPageFrm*)pPage->GetNext();
753 while ( pPage && pPage->GetNext() &&
754 pPage->GetPhyPageNum() < nFirstPageNum )
755 pPage = (SwPageFrm*)pPage->GetNext();
758 if ( IsInterrupt() && pPage )
760 // If we have input, we don't want to format content anymore, but
761 // we still should clean the layout.
762 // Otherwise, the following situation might arise:
763 // The user enters some text at the end of the paragraph of the last
764 // page, causing the paragraph to create a Follow for the next page.
765 // Meanwhile the user continues typing, so we have input while
766 // still formatting.
767 // The paragraph on the new page has already been partially formatted,
768 // and the new page has been fully formatted and is set to CompletePaint,
769 // but hasn't added itself to the area to be output. Then we paint,
770 // the CompletePaint of the page is reset because the new paragraph
771 // already added itself, but the borders of the page haven't been painted
772 // yet.
773 // Oh well, with the inevitable following LayAction, the page doesn't
774 // register itself, because it's (LayoutFrm) flags have been reset
775 // already - the border of the page will never be painted.
776 SwPageFrm *pPg = pPage;
777 XCHECKPAGE;
778 const SwRect &rVis = pImp->GetShell()->VisArea();
780 while( pPg && pPg->Frm().Bottom() < rVis.Top() )
781 pPg = (SwPageFrm*)pPg->GetNext();
782 if( pPg != pPage )
783 pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
785 // set flag for interrupt content formatting
786 mbFormatCntntOnInterrupt = IsInput() && !IsStopPrt();
787 long nBottom = rVis.Bottom();
788 // #i42586# - format current page, if idle action is active
789 // This is an optimization for the case that the interrupt is created by
790 // the move of a form control object, which is represented by a window.
791 while ( pPg && ( pPg->Frm().Top() < nBottom ||
792 ( IsIdle() && pPg == pPage ) ) )
794 unlockPositionOfObjects( pPg );
796 XCHECKPAGE;
798 // #i81146# new loop control
799 sal_uInt16 nLoopControlRuns_2 = 0;
800 const sal_uInt16 nLoopControlMax = 20;
802 // special case: interrupt content formatting
803 // #i28701# - conditions are incorrect (macros IS_FLYS and IS_INVAFLY only
804 // works for <pPage>) and are too strict.
805 // #i50432# - adjust interrupt formatting to normal page formatting - see above.
806 while ( ( mbFormatCntntOnInterrupt &&
807 ( pPg->IsInvalid() ||
808 ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
809 ( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
811 XCHECKPAGE;
812 // #i50432# - format also at-page anchored objects
813 SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
814 if ( !pPg->GetSortedObjs() )
816 pPg->ValidateFlyLayout();
817 pPg->ValidateFlyCntnt();
820 // #i81146# new loop control
821 sal_uInt16 nLoopControlRuns_3 = 0;
823 while ( pPg->IsInvalidLayout() )
825 pPg->ValidateLayout();
827 if ( ++nLoopControlRuns_3 > nLoopControlMax )
829 OSL_FAIL( "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" );
830 break;
833 FormatLayout( pPg );
834 XCHECKPAGE;
837 // #i50432#
838 if ( mbFormatCntntOnInterrupt &&
839 ( pPg->IsInvalidCntnt() ||
840 ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
842 pPg->ValidateFlyInCnt();
843 pPg->ValidateCntnt();
844 // #i26945#
845 pPg->ValidateFlyLayout();
846 pPg->ValidateFlyCntnt();
848 if ( ++nLoopControlRuns_2 > nLoopControlMax )
850 OSL_FAIL( "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" );
851 break;
854 if ( !FormatCntnt( pPg ) )
856 XCHECKPAGE;
857 pPg->InvalidateCntnt();
858 pPg->InvalidateFlyInCnt();
859 // #i26945#
860 pPg->InvalidateFlyLayout();
861 pPg->InvalidateFlyCntnt();
863 // #i46807# - we are statisfied, if the content is formatted once complete.
864 else
866 break;
871 unlockPositionOfObjects( pPg );
872 pPg = (SwPageFrm*)pPg->GetNext();
874 // reset flag for special interrupt content formatting.
875 mbFormatCntntOnInterrupt = sal_False;
877 pOptTab = 0;
878 if( bNoLoop )
879 pLayoutAccess->GetLayouter()->EndLoopControl();
881 /*************************************************************************
883 |* SwLayAction::TurboAction(), _TurboAction()
885 |*************************************************************************/
886 sal_Bool SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
889 const SwPageFrm *pPage = 0;
890 if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
892 const SwRect aOldRect( pCnt->UnionFrm( sal_True ) );
893 const long nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
894 pCnt->Calc();
895 if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
896 pCnt->SetRetouche();
898 pPage = pCnt->FindPageFrm();
899 PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
901 if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
903 const sal_uLong nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
904 ((SwTxtFrm*)pCnt)->RecalcAllLines();
905 if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
907 if ( IsPaintExtraData() )
908 pImp->GetShell()->AddPaintRect( pCnt->Frm() );
909 // This is to calculate the remaining LineNums on the page,
910 // and we don't stop processing here. To perform this inside RecalcAllLines
911 // would be expensive, because we would have to notify the page even
912 // in unnecessary cases (normal actions).
913 const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
914 while ( pNxt &&
915 (pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
916 pNxt = pNxt->GetNextCntntFrm();
917 if ( pNxt )
918 pNxt->InvalidatePage();
920 return sal_False;
923 if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
924 return sal_False;
926 if ( !pPage )
927 pPage = pCnt->FindPageFrm();
929 // OD 2004-05-10 #i28701# - format floating screen objects at content frame.
930 if ( pCnt->IsTxtFrm() &&
931 !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
932 *pPage, this ) )
934 return sal_False;
937 if ( pPage->IsInvalidCntnt() )
938 return sal_False;
939 return sal_True;
942 sal_Bool SwLayAction::TurboAction()
944 sal_Bool bRet = sal_True;
946 if ( pRoot->GetTurbo() )
948 if ( !_TurboAction( pRoot->GetTurbo() ) )
950 CheckIdleEnd();
951 bRet = sal_False;
953 pRoot->ResetTurbo();
955 else
956 bRet = sal_False;
957 return bRet;
959 /*************************************************************************
961 |* SwLayAction::IsShortCut()
963 |* Description: Returns True if the page lies directly below or
964 |* right of the visible area.
965 |* It's possible for things to change in such a way that the processing
966 |* (of the caller!) has to continue with the predecessor of the passed
967 |* page. The parameter might therefore get modified!
968 |* For BrowseMode, you may even activate the ShortCut if the invalid
969 |* content of the page lies below the visible area.
971 |*************************************************************************/
972 static bool lcl_IsInvaLay( const SwFrm *pFrm, long nBottom )
974 if (
975 !pFrm->IsValid() ||
976 (pFrm->IsCompletePaint() && ( pFrm->Frm().Top() < nBottom ) )
979 return true;
981 return false;
984 static const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
986 OSL_ENSURE( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
988 if (lcl_IsInvaLay(pFrm, nBottom))
989 return pFrm;
990 pFrm = ((SwLayoutFrm*)pFrm)->Lower();
991 while ( pFrm )
993 if ( pFrm->IsLayoutFrm() )
995 if (lcl_IsInvaLay(pFrm, nBottom))
996 return pFrm;
997 const SwFrm *pTmp;
998 if ( 0 != (pTmp = lcl_FindFirstInvaLay( pFrm, nBottom )) )
999 return pTmp;
1001 pFrm = pFrm->GetNext();
1003 return 0;
1006 static const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
1007 const SwCntntFrm *pFirst )
1009 const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
1010 pLay->ContainsCntnt();
1011 while ( pCnt )
1013 if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
1015 if ( pCnt->Frm().Top() <= nBottom )
1016 return pCnt;
1019 if ( pCnt->GetDrawObjs() )
1021 const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
1022 for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
1024 const SwAnchoredObject* pObj = rObjs[i];
1025 if ( pObj->ISA(SwFlyFrm) )
1027 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
1028 if ( pFly->IsFlyInCntFrm() )
1030 if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
1031 pFly->IsCompletePaint() )
1033 if ( pFly->Frm().Top() <= nBottom )
1034 return pFly;
1036 const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
1037 if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
1038 return pFrm;
1043 if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
1044 return 0;
1045 pCnt = pCnt->GetNextCntntFrm();
1046 if ( !pLay->IsAnLower( pCnt ) )
1047 break;
1049 return 0;
1052 // #i37877# - consider drawing objects
1053 static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
1054 long _nBottom )
1056 OSL_ENSURE( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" );
1058 for ( sal_uInt16 i = 0; i < _pPage->GetSortedObjs()->Count(); ++i )
1060 const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
1061 if ( pObj->ISA(SwFlyFrm) )
1063 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
1064 if ( pFly->Frm().Top() <= _nBottom )
1066 if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
1067 return pFly;
1069 const SwFrm* pTmp;
1070 if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
1071 pTmp->Frm().Top() <= _nBottom )
1072 return pFly;
1075 else if ( pObj->ISA(SwAnchoredDrawObject) )
1077 if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
1079 return pObj;
1083 return 0;
1086 sal_Bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
1088 sal_Bool bRet = sal_False;
1089 const ViewShell *pSh = pRoot->GetCurrShell();
1090 const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1092 // If the page is not valid, we quickly format it, otherwise
1093 // there's gonna be no end of trouble
1094 if ( !prPage->IsValid() )
1096 if ( bBrowse )
1098 /// OD 15.10.2002 #103517# - format complete page
1099 /// Thus, loop on all lowers of the page <prPage>, instead of only
1100 /// format its first lower.
1101 /// NOTE: In online layout (bBrowse == true) a page can contain
1102 /// a header frame and/or a footer frame beside the body frame.
1103 prPage->Calc();
1104 SwFrm* pPageLowerFrm = prPage->Lower();
1105 while ( pPageLowerFrm )
1107 pPageLowerFrm->Calc();
1108 pPageLowerFrm = pPageLowerFrm->GetNext();
1111 else
1112 FormatLayout( prPage );
1113 if ( IsAgain() )
1114 return sal_False;
1118 const SwRect &rVis = pImp->GetShell()->VisArea();
1119 if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
1120 (prPage->Frm().Left()>= rVis.Right()) )
1122 bRet = sal_True;
1124 // This is going to be a bit nasty: The first CntntFrm of this
1125 // page in the Body text needs formatting; if it changes the page during
1126 // that process, I need to start over a page further back, because we
1127 // have been processing a PageBreak.
1128 // Even more uncomfortable: The next CntntFrm must be formatted,
1129 // because it's possible for empty pages to exist temporarily (for example
1130 // a paragraph across multiple pages gets deleted or reduced in size).
1132 // This is irrelevant for the browser, if the last Cnt above it
1133 // isn't visible anymore.
1135 const SwPageFrm *p2ndPage = prPage;
1136 const SwCntntFrm *pCntnt;
1137 const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
1138 if( p2ndPage->IsFtnPage() && pBody )
1139 pBody = (SwLayoutFrm*)pBody->GetNext();
1140 pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1141 while ( p2ndPage && !pCntnt )
1143 p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
1144 if( p2ndPage )
1146 pBody = p2ndPage->FindBodyCont();
1147 if( p2ndPage->IsFtnPage() && pBody )
1148 pBody = (SwLayoutFrm*)pBody->GetNext();
1149 pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1152 if ( pCntnt )
1154 bool bTstCnt = true;
1155 if ( bBrowse )
1157 // Is the Cnt before already invisible?
1158 const SwFrm *pLst = pCntnt;
1159 if ( pLst->IsInTab() )
1160 pLst = pCntnt->FindTabFrm();
1161 if ( pLst->IsInSct() )
1162 pLst = pCntnt->FindSctFrm();
1163 pLst = pLst->FindPrev();
1164 if ( pLst &&
1165 (pLst->Frm().Top() >= rVis.Bottom() ||
1166 pLst->Frm().Left()>= rVis.Right()) )
1168 bTstCnt = false;
1172 if ( bTstCnt )
1174 // #i27756# - check after each frame calculation,
1175 // if the content frame has changed the page. If yes, no other
1176 // frame calculation is performed
1177 bool bPageChg = false;
1179 if ( pCntnt->IsInSct() )
1181 const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1182 if ( !pSct->IsValid() )
1184 pSct->Calc();
1185 pSct->SetCompletePaint();
1186 if ( IsAgain() )
1187 return sal_False;
1188 // #i27756#
1189 bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1190 prPage->GetPrev();
1194 if ( !bPageChg && !pCntnt->IsValid() )
1196 pCntnt->Calc();
1197 pCntnt->SetCompletePaint();
1198 if ( IsAgain() )
1199 return sal_False;
1200 // #i27756#
1201 bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1202 prPage->GetPrev();
1205 if ( !bPageChg && pCntnt->IsInTab() )
1207 const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
1208 if ( !pTab->IsValid() )
1210 pTab->Calc();
1211 pTab->SetCompletePaint();
1212 if ( IsAgain() )
1213 return sal_False;
1214 // #i27756#
1215 bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1216 prPage->GetPrev();
1220 if ( !bPageChg && pCntnt->IsInSct() )
1222 const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1223 if ( !pSct->IsValid() )
1225 pSct->Calc();
1226 pSct->SetCompletePaint();
1227 if ( IsAgain() )
1228 return sal_False;
1229 // #i27756#
1230 bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1231 prPage->GetPrev();
1235 // #i27756#
1236 if ( bPageChg )
1238 bRet = sal_False;
1239 const SwPageFrm* pTmp = pCntnt->FindPageFrm();
1240 if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
1241 pTmp->IsInvalid() )
1243 prPage = (SwPageFrm*)pTmp;
1245 else
1247 prPage = (SwPageFrm*)prPage->GetPrev();
1250 // #121980# - no shortcut, if at previous page
1251 // an anchored object is registered, whose anchor is <pCntnt>.
1252 else if ( prPage->GetPrev() &&
1253 static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
1255 SwSortedObjs* pObjs =
1256 static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
1257 if ( pObjs )
1259 sal_uInt32 i = 0;
1260 for ( ; i < pObjs->Count(); ++i )
1262 SwAnchoredObject* pObj = (*pObjs)[i];
1263 if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
1265 bRet = sal_False;
1266 break;
1275 if ( !bRet && bBrowse )
1277 const long nBottom = rVis.Bottom();
1278 const SwAnchoredObject* pObj( 0L );
1279 if ( prPage->GetSortedObjs() &&
1280 (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
1281 0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
1282 pObj->GetObjRect().Top() <= nBottom )
1284 return sal_False;
1286 const SwFrm* pFrm( 0L );
1287 if ( prPage->IsInvalidLayout() &&
1288 0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
1289 pFrm->Frm().Top() <= nBottom )
1291 return sal_False;
1293 if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
1294 0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
1295 pFrm->Frm().Top() <= nBottom )
1297 return sal_False;
1299 bRet = sal_True;
1301 return bRet;
1304 /*************************************************************************
1306 |* SwLayAction::FormatLayout(), FormatLayoutFly, FormatLayoutTab()
1308 |*************************************************************************/
1309 // OD 15.11.2002 #105155# - introduce support for vertical layout
1310 sal_Bool SwLayAction::FormatLayout( SwLayoutFrm *pLay, sal_Bool bAddRect )
1312 OSL_ENSURE( !IsAgain(), "Attention to the invalid page." );
1313 if ( IsAgain() )
1314 return sal_False;
1316 sal_Bool bChanged = sal_False;
1317 bool bAlreadyPainted = false;
1318 // OD 11.11.2002 #104414# - remember frame at complete paint
1319 SwRect aFrmAtCompletePaint;
1321 if ( !pLay->IsValid() || pLay->IsCompletePaint() )
1323 if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
1324 pLay->GetPrev()->SetCompletePaint();
1326 SwRect aOldFrame( pLay->Frm() );
1327 SwRect aOldRect( aOldFrame );
1328 if( pLay->IsPageFrm() )
1330 aOldRect = static_cast<SwPageFrm*>(pLay)->GetBoundRect();
1333 pLay->Calc();
1334 if ( aOldFrame != pLay->Frm() )
1335 bChanged = sal_True;
1337 bool bNoPaint = false;
1338 if ( pLay->IsPageBodyFrm() &&
1339 pLay->Frm().Pos() == aOldRect.Pos() &&
1340 pLay->Lower() )
1342 const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1343 // Limitations because of headers / footers
1344 if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
1345 !( pLay->IsCompletePaint() && pLay->FindPageFrm()->FindFtnCont() ) )
1346 bNoPaint = true;
1349 if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
1351 SwRect aPaint( pLay->Frm() );
1352 // OD 13.02.2003 #i9719#, #105645# - consider border and shadow for
1353 // page frames -> enlarge paint rectangle correspondingly.
1354 if ( pLay->IsPageFrm() )
1356 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
1357 aPaint = pPageFrm->GetBoundRect();
1360 bool bPageInBrowseMode = pLay->IsPageFrm();
1361 if( bPageInBrowseMode )
1363 const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1364 if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
1365 bPageInBrowseMode = false;
1367 if( bPageInBrowseMode )
1369 // NOTE: no vertical layout in online layout
1370 // Is the change even visible?
1371 if ( pLay->IsCompletePaint() )
1373 pImp->GetShell()->AddPaintRect( aPaint );
1374 bAddRect = sal_False;
1376 else
1378 sal_uInt16 i;
1380 SwRegionRects aRegion( aOldRect );
1381 aRegion -= aPaint;
1382 for ( i = 0; i < aRegion.size(); ++i )
1383 pImp->GetShell()->AddPaintRect( aRegion[i] );
1384 aRegion.ChangeOrigin( aPaint );
1385 aRegion.clear();
1386 aRegion.push_back( aPaint );
1387 aRegion -= aOldRect;
1388 for ( i = 0; i < aRegion.size(); ++i )
1389 pImp->GetShell()->AddPaintRect( aRegion[i] );
1393 else
1395 pImp->GetShell()->AddPaintRect( aPaint );
1396 bAlreadyPainted = true;
1397 // OD 11.11.2002 #104414# - remember frame at complete paint
1398 aFrmAtCompletePaint = pLay->Frm();
1401 // OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
1402 // between pages (not only for in online mode).
1403 if ( pLay->IsPageFrm() )
1405 const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
1406 const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
1407 const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
1408 const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
1409 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
1410 const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1411 SwRect aPageRect( pLay->Frm() );
1413 if(pSh)
1415 SwPageFrm::GetBorderAndShadowBoundRect(aPageRect, pSh,
1416 aPageRect, pPageFrm->IsLeftShadowNeeded(), pPageFrm->IsRightShadowNeeded(),
1417 pPageFrm->SidebarPosition() == sw::sidebarwindows::SIDEBAR_RIGHT);
1420 if ( bPrev )
1422 // top
1423 SwRect aSpaceToPrevPage( aPageRect );
1424 aSpaceToPrevPage.Top( aSpaceToPrevPage.Top() - nHalfDocBorder );
1425 aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
1426 if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
1427 pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1429 pSh->GetOut()->DrawRect( aSpaceToPrevPage.SVRect() );
1431 // left
1432 aSpaceToPrevPage = aPageRect;
1433 aSpaceToPrevPage.Left( aSpaceToPrevPage.Left() - nHalfDocBorder );
1434 aSpaceToPrevPage.Right( pLay->Frm().Left() );
1435 if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
1436 pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1438 if ( bNext )
1440 // bottom
1441 SwRect aSpaceToNextPage( aPageRect );
1442 aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
1443 aSpaceToNextPage.Top( pLay->Frm().Bottom() );
1444 if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
1445 pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1447 // right
1448 aSpaceToNextPage = aPageRect;
1449 aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
1450 aSpaceToNextPage.Left( pLay->Frm().Right() );
1451 if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
1452 pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1456 pLay->ResetCompletePaint();
1459 if ( IsPaint() && bAddRect &&
1460 !pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
1462 // OD 15.11.2002 #105155# - vertical layout support
1463 SWRECTFN( pLay );
1464 SwRect aRect( pLay->GetUpper()->PaintArea() );
1465 (aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
1466 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1467 pLay->ResetRetouche();
1470 if( bAlreadyPainted )
1471 bAddRect = sal_False;
1473 CheckWaitCrsr();
1475 if ( IsAgain() )
1476 return sal_False;
1478 // Now, deal with the lowers that are LayoutFrms
1480 if ( pLay->IsFtnFrm() ) // no LayFrms as Lower
1481 return bChanged;
1483 SwFrm *pLow = pLay->Lower();
1484 sal_Bool bTabChanged = sal_False;
1485 while ( pLow && pLow->GetUpper() == pLay )
1487 if ( pLow->IsLayoutFrm() )
1489 if ( pLow->IsTabFrm() )
1490 bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1491 // Skip the ones already registered for deletion
1492 else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
1493 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1495 else if ( pImp->GetShell()->IsPaintLocked() )
1496 // Shortcut to minimize the cycles. With Lock, the
1497 // paint is coming either way (primarily for browse)
1498 pLow->OptCalc();
1500 if ( IsAgain() )
1501 return sal_False;
1502 pLow = pLow->GetNext();
1504 // OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
1505 // area has been already added and after formating its lowers the frame area
1506 // is enlarged.
1507 SwRect aBoundRect(pLay->IsPageFrm() ? static_cast<SwPageFrm*>(pLay)->GetBoundRect() : pLay->Frm() );
1509 if ( bAlreadyPainted &&
1510 ( aBoundRect.Width() > aFrmAtCompletePaint.Width() ||
1511 aBoundRect.Height() > aFrmAtCompletePaint.Height() )
1514 pImp->GetShell()->AddPaintRect( aBoundRect );
1516 return bChanged || bTabChanged;
1519 sal_Bool SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
1521 OSL_ENSURE( !IsAgain(), "Attention to the invalid page." );
1522 if ( IsAgain() )
1523 return sal_False;
1525 sal_Bool bChanged = false;
1526 sal_Bool bAddRect = true;
1528 if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
1530 // The Frame has changed, now it's getting formatted.
1531 const SwRect aOldRect( pFly->Frm() );
1532 pFly->Calc();
1533 bChanged = aOldRect != pFly->Frm();
1535 if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
1536 pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
1537 pImp->GetShell()->AddPaintRect( pFly->Frm() );
1539 if ( bChanged )
1540 pFly->Invalidate();
1541 else
1542 pFly->Validate();
1544 //mba: it's unclear why we should invalidate always, so I remove it
1545 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1546 if ( IsPaint() && bAddRect && pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
1547 pImp->GetShell()->AddPaintRect( pFly->Frm() );
1549 pFly->Invalidate();
1551 bAddRect = false;
1552 pFly->ResetCompletePaint();
1555 if ( IsAgain() )
1556 return sal_False;
1558 // Now, deal with the lowers that are LayoutFrms
1559 sal_Bool bTabChanged = false;
1560 SwFrm *pLow = pFly->Lower();
1561 while ( pLow )
1563 if ( pLow->IsLayoutFrm() )
1565 if ( pLow->IsTabFrm() )
1566 bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1567 else
1568 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1570 pLow = pLow->GetNext();
1572 return bChanged || bTabChanged;
1575 // OD 31.10.2002 #104100#
1576 // Implement vertical layout support
1577 sal_Bool SwLayAction::FormatLayoutTab( SwTabFrm *pTab, sal_Bool bAddRect )
1579 OSL_ENSURE( !IsAgain(), "8-) Attention to the invalid page." );
1580 if ( IsAgain() || !pTab->Lower() )
1581 return sal_False;
1583 IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
1584 pTimerAccess->BlockIdling();
1586 sal_Bool bChanged = sal_False;
1587 bool bPainted = false;
1589 const SwPageFrm *pOldPage = pTab->FindPageFrm();
1591 // OD 31.10.2002 #104100# - vertical layout support
1592 // use macro to declare and init <sal_Bool bVert>, <sal_Bool bRev> and
1593 // <SwRectFn fnRect> for table frame <pTab>.
1594 SWRECTFN( pTab );
1596 if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
1598 if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
1600 pTab->GetPrev()->SetCompletePaint();
1603 const SwRect aOldRect( pTab->Frm() );
1604 pTab->SetLowersFormatted( sal_False );
1605 pTab->Calc();
1606 if ( aOldRect != pTab->Frm() )
1608 bChanged = sal_True;
1610 const SwRect aPaintFrm = pTab->PaintArea();
1612 if ( IsPaint() && bAddRect )
1614 // OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
1615 if ( !pTab->IsCompletePaint() &&
1616 pTab->IsComplete() &&
1617 ( pTab->Frm().SSize() != pTab->Prt().SSize() ||
1618 // OD 31.10.2002 #104100# - vertical layout support
1619 (pTab->*fnRect->fnGetLeftMargin)() ) &&
1620 pTab->Frm().HasArea()
1623 // OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
1624 SwRect aMarginRect;
1626 SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
1627 if ( nLeftMargin > 0)
1629 aMarginRect = pTab->Frm();
1630 (aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
1631 pImp->GetShell()->AddPaintRect( aMarginRect );
1634 if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
1636 aMarginRect = pTab->Frm();
1637 (aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
1638 pImp->GetShell()->AddPaintRect( aMarginRect );
1641 SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
1642 if ( nTopMargin > 0)
1644 aMarginRect = pTab->Frm();
1645 (aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
1646 pImp->GetShell()->AddPaintRect( aMarginRect );
1649 if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
1651 aMarginRect = pTab->Frm();
1652 (aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1653 pImp->GetShell()->AddPaintRect( aMarginRect );
1656 else if ( pTab->IsCompletePaint() )
1658 pImp->GetShell()->AddPaintRect( aPaintFrm );
1659 bAddRect = sal_False;
1660 bPainted = true;
1663 if ( pTab->IsRetouche() && !pTab->GetNext() )
1665 SwRect aRect( pTab->GetUpper()->PaintArea() );
1666 // OD 04.11.2002 #104100# - vertical layout support
1667 (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1668 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1669 pTab->ResetRetouche();
1672 else
1673 bAddRect = sal_False;
1675 if ( pTab->IsCompletePaint() && !pOptTab )
1676 pOptTab = pTab;
1677 pTab->ResetCompletePaint();
1679 if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
1681 // OD 04.10.2002 #102779#
1682 // set correct rectangle for retouche: area between bottom of table frame
1683 // and bottom of paint area of the upper frame.
1684 SwRect aRect( pTab->GetUpper()->PaintArea() );
1685 // OD 04.11.2002 #104100# - vertical layout support
1686 (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1687 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1688 pTab->ResetRetouche();
1691 CheckWaitCrsr();
1693 pTimerAccess->UnblockIdling();
1695 // Ugly shortcut!
1696 if ( pTab->IsLowersFormatted() &&
1697 (bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
1698 return sal_False;
1700 // Now, deal with the lowers
1701 if ( IsAgain() )
1702 return sal_False;
1704 // OD 20.10.2003 #112464# - for savety reasons:
1705 // check page number before formatting lowers.
1706 if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
1707 SetNextCycle( sal_True );
1709 // OD 20.10.2003 #112464# - format lowers, only if table frame is valid
1710 if ( pTab->IsValid() )
1712 SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
1713 while ( pLow )
1715 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1716 if ( IsAgain() )
1717 return sal_False;
1718 pLow = (SwLayoutFrm*)pLow->GetNext();
1722 return bChanged;
1725 /*************************************************************************
1727 |* SwLayAction::FormatCntnt()
1729 |*************************************************************************/
1730 sal_Bool SwLayAction::FormatCntnt( const SwPageFrm *pPage )
1732 const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
1733 const ViewShell *pSh = pRoot->GetCurrShell();
1734 const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1736 while ( pCntnt && pPage->IsAnLower( pCntnt ) )
1738 // If the Cntnt didn't change, we can use a few shortcuts.
1739 const bool bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
1740 pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
1741 if ( bFull )
1743 // We do this so we don't have to search later on.
1744 const bool bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
1745 const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
1746 const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
1748 const SwLayoutFrm*pOldUpper = pCntnt->GetUpper();
1749 const SwTabFrm *pTab = pCntnt->FindTabFrm();
1750 const bool bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
1751 const sal_Bool bOldPaint = IsPaint();
1752 bPaint = bOldPaint && !(pTab && pTab == pOptTab);
1753 _FormatCntnt( pCntnt, pPage );
1754 // #i26945# - reset <bPaint> before format objects
1755 bPaint = bOldPaint;
1757 // OD 2004-05-10 #i28701# - format floating screen object at content frame.
1758 // No format, if action flag <bAgain> is set or action is interrupted.
1759 // OD 2004-08-30 #117736# - allow format on interruption of action, if
1760 // it's the format for this interrupt
1761 // #i23129#, #i36347# - pass correct page frame
1762 // to the object formatter.
1763 if ( !IsAgain() &&
1764 ( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
1765 pCntnt->IsTxtFrm() &&
1766 !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
1767 *(pCntnt->FindPageFrm()), this ) )
1769 return sal_False;
1772 if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1774 const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1775 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
1776 if ( IsPaintExtraData() && IsPaint() &&
1777 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1778 pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1781 if ( IsAgain() )
1782 return sal_False;
1784 // Temporarily interrupt processing if layout or Flys become invalid again.
1785 // However not for the BrowseView: The layout is getting invalid
1786 // all the time because the page height gets adjusted.
1787 // The same applies if the user wants to continue working and at least one
1788 // paragraph has been processed.
1789 if ( (!pTab || (pTab && !bInValid)) )
1791 CheckIdleEnd();
1792 // OD 14.04.2003 #106346# - consider interrupt formatting.
1793 if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
1794 ( !bBrowse && pPage->IsInvalidLayout() ) ||
1795 // OD 07.05.2003 #109435# - consider interrupt formatting
1796 ( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
1798 return sal_False;
1800 if ( pOldUpper != pCntnt->GetUpper() )
1802 const sal_uInt16 nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
1803 if ( nCurNum < pPage->GetPhyPageNum() )
1804 nPreInvaPage = nCurNum;
1806 // If the Frm flowed backwards more than one page, we need to
1807 // start over again from the beginning, so nothing gets left out.
1808 if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
1810 SetNextCycle( sal_True );
1811 // OD 07.05.2003 #109435# - consider interrupt formatting
1812 if ( !mbFormatCntntOnInterrupt )
1814 return sal_False;
1818 // If the Frame moved forwards to the next page, we re-run through
1819 // the predecessor.
1820 // This way, we catch predecessors which are now responsible for
1821 // retouching, but the footers will be touched also.
1822 bool bSetCntnt = true;
1823 if ( pCntntPrev )
1825 if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
1826 pPage->InvalidateCntnt();
1827 if ( pOldUpper != pCntnt->GetUpper() &&
1828 pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
1830 pCntnt = pCntntPrev;
1831 bSetCntnt = false;
1834 if ( bSetCntnt )
1836 if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
1837 pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
1839 const long nBottom = pImp->GetShell()->VisArea().Bottom();
1840 const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
1841 nBottom, pCntnt );
1842 if ( !pTmp )
1844 if ( (!(IS_FLYS && IS_INVAFLY) ||
1845 !lcl_FindFirstInvaObj( pPage, nBottom )) &&
1846 (!pPage->IsInvalidLayout() ||
1847 !lcl_FindFirstInvaLay( pPage, nBottom )))
1848 SetBrowseActionStop( sal_True );
1849 // OD 14.04.2003 #106346# - consider interrupt formatting.
1850 if ( !mbFormatCntntOnInterrupt )
1852 return sal_False;
1856 pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
1859 RESCHEDULE;
1861 else
1863 if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1865 const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1866 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
1867 if ( IsPaintExtraData() && IsPaint() &&
1868 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1869 pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1872 // Do this if the Frm has been formatted before.
1873 if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
1874 IsPaint() )
1875 PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
1876 if ( IsIdle() )
1878 CheckIdleEnd();
1879 // OD 14.04.2003 #106346# - consider interrupt formatting.
1880 if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
1881 return sal_False;
1883 if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
1884 pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
1886 const long nBottom = pImp->GetShell()->VisArea().Bottom();
1887 const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
1888 nBottom, pCntnt );
1889 if ( !pTmp )
1891 if ( (!(IS_FLYS && IS_INVAFLY) ||
1892 !lcl_FindFirstInvaObj( pPage, nBottom )) &&
1893 (!pPage->IsInvalidLayout() ||
1894 !lcl_FindFirstInvaLay( pPage, nBottom )))
1895 SetBrowseActionStop( sal_True );
1896 // OD 14.04.2003 #106346# - consider interrupt formatting.
1897 if ( !mbFormatCntntOnInterrupt )
1899 return sal_False;
1903 pCntnt = pCntnt->GetNextCntntFrm();
1906 CheckWaitCrsr();
1907 // OD 14.04.2003 #106346# - consider interrupt formatting.
1908 return !IsInterrupt() || mbFormatCntntOnInterrupt;
1910 /*************************************************************************
1912 |* SwLayAction::_FormatCntnt()
1914 |* Description Returns sal_True if the paragraph has been processed,
1915 |* sal_False if there wasn't anything to be processed.
1917 |*************************************************************************/
1918 void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
1919 const SwPageFrm *pPage )
1921 // We probably only ended up here because the Cntnt holds DrawObjects.
1922 const bool bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
1923 !pCntnt->IsRetouche();
1924 SWRECTFN( pCntnt )
1925 if ( !bDrawObjsOnly && IsPaint() )
1927 const SwRect aOldRect( pCntnt->UnionFrm() );
1928 const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
1929 pCntnt->OptCalc();
1930 if( IsAgain() )
1931 return;
1932 if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
1933 (aOldRect.*fnRect->fnGetBottom)() ) < 0 )
1935 pCntnt->SetRetouche();
1937 PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
1939 else
1941 if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
1942 PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
1943 (pCntnt->Frm().*fnRect->fnGetBottom)() );
1944 pCntnt->OptCalc();
1948 /*************************************************************************
1950 |* SwLayAction::_FormatFlyCntnt()
1952 |* Description:
1953 |* - Returns sal_True if all Cntnts of the Fly have been processed completely.
1954 |* Returns sal_False if processing has been interrupted prematurely.
1956 |*************************************************************************/
1957 sal_Bool SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
1959 const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
1961 while ( pCntnt )
1963 // OD 2004-05-10 #i28701#
1964 _FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
1966 // #i28701# - format floating screen objects
1967 // at content text frame
1968 // #i23129#, #i36347# - pass correct page frame
1969 // to the object formatter.
1970 if ( pCntnt->IsTxtFrm() &&
1971 !SwObjectFormatter::FormatObjsAtFrm(
1972 *(const_cast<SwCntntFrm*>(pCntnt)),
1973 *(pCntnt->FindPageFrm()), this ) )
1975 // restart format with first content
1976 pCntnt = pFly->ContainsCntnt();
1977 continue;
1980 if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1982 const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1983 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
1984 if ( IsPaintExtraData() && IsPaint() &&
1985 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1986 pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1989 if ( IsAgain() )
1990 return sal_False;
1992 // If there's input, we interrupt processing.
1993 if ( !pFly->IsFlyInCntFrm() )
1995 CheckIdleEnd();
1996 // OD 14.04.2003 #106346# - consider interrupt formatting.
1997 if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
1998 return sal_False;
2000 pCntnt = pCntnt->GetNextCntntFrm();
2002 CheckWaitCrsr();
2003 // OD 14.04.2003 #106346# - consider interrupt formatting.
2004 return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
2007 sal_Bool SwLayAction::IsStopPrt() const
2009 sal_Bool bResult = sal_False;
2011 if (pImp != NULL && pProgress != NULL)
2012 bResult = pImp->IsStopPrt();
2014 return bResult;
2017 /*************************************************************************
2019 |* SwLayAction::FormatSpelling(), _FormatSpelling()
2021 |*************************************************************************/
2022 sal_Bool SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
2024 OSL_ENSURE( pCnt->IsTxtFrm(), "NoTxt neighbour of Txt" );
2025 // robust against misuse by e.g. #i52542#
2026 if( !pCnt->IsTxtFrm() )
2027 return sal_False;
2029 const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
2031 bool bProcess = false;
2032 switch ( eJob )
2034 case ONLINE_SPELLING :
2035 bProcess = pTxtNode->IsWrongDirty(); break;
2036 case AUTOCOMPLETE_WORDS :
2037 bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
2038 case WORD_COUNT :
2039 bProcess = pTxtNode->IsWordCountDirty(); break;
2040 case SMART_TAGS : // SMARTTAGS
2041 bProcess = pTxtNode->IsSmartTagDirty(); break;
2044 if( bProcess )
2046 ViewShell *pSh = pImp->GetShell();
2047 if( STRING_LEN == nTxtPos )
2049 --nTxtPos;
2050 if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
2052 SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
2053 if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
2055 pCntntNode = pCrsr->GetCntntNode();
2056 nTxtPos = pCrsr->GetPoint()->nContent.GetIndex();
2061 switch ( eJob )
2063 case ONLINE_SPELLING :
2065 SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode, *pSh->GetViewOptions(), nTxtPos ) );
2066 bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
2067 if( !bPageValid )
2068 bAllValid = sal_False;
2069 if ( aRepaint.HasArea() )
2070 pImp->GetShell()->InvalidateWindows( aRepaint );
2071 if ( Application::AnyInput( VCL_INPUT_MOUSEANDKEYBOARD|VCL_INPUT_OTHER|VCL_INPUT_PAINT ) )
2072 return sal_True;
2073 break;
2075 case AUTOCOMPLETE_WORDS :
2076 ((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
2077 if ( Application::AnyInput( VCL_INPUT_ANY ) )
2078 return sal_True;
2079 break;
2080 case WORD_COUNT :
2082 const xub_StrLen nEnd = pTxtNode->GetTxt().getLength();
2083 SwDocStat aStat;
2084 pTxtNode->CountWords( aStat, 0, nEnd );
2085 if ( Application::AnyInput( VCL_INPUT_ANY ) )
2086 return sal_True;
2087 break;
2089 case SMART_TAGS : // SMARTTAGS
2091 const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
2092 bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
2093 if( !bPageValid )
2094 bAllValid = sal_False;
2095 if ( aRepaint.HasArea() )
2096 pImp->GetShell()->InvalidateWindows( aRepaint );
2097 if ( Application::AnyInput( VCL_INPUT_MOUSEANDKEYBOARD|VCL_INPUT_OTHER|VCL_INPUT_PAINT ) )
2098 return sal_True;
2099 break;
2104 // The Flys that are anchored to the paragraph need to be considered too.
2105 if ( pCnt->GetDrawObjs() )
2107 const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
2108 for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2110 SwAnchoredObject* pObj = rObjs[i];
2111 if ( pObj->ISA(SwFlyFrm) )
2113 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
2114 if ( pFly->IsFlyInCntFrm() )
2116 const SwCntntFrm *pC = pFly->ContainsCntnt();
2117 while( pC )
2119 if ( pC->IsTxtFrm() )
2121 if ( _DoIdleJob( pC, eJob ) )
2122 return sal_True;
2124 pC = pC->GetNextCntntFrm();
2130 return sal_False;
2133 sal_Bool SwLayIdle::DoIdleJob( IdleJobType eJob, sal_Bool bVisAreaOnly )
2135 // Spellcheck all contents of the pages. Either only the
2136 // visible ones or all of them.
2137 const ViewShell* pViewShell = pImp->GetShell();
2138 const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
2139 const SwDoc* pDoc = pViewShell->GetDoc();
2141 switch ( eJob )
2143 case ONLINE_SPELLING :
2144 if( !pViewOptions->IsOnlineSpell() )
2145 return sal_False;
2146 break;
2147 case AUTOCOMPLETE_WORDS :
2148 if( !pViewOptions->IsAutoCompleteWords() ||
2149 pDoc->GetAutoCompleteWords().IsLockWordLstLocked())
2150 return sal_False;
2151 break;
2152 case WORD_COUNT :
2153 if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
2154 return sal_False;
2155 break;
2156 case SMART_TAGS :
2157 if ( pDoc->GetDocShell()->IsHelpDocument() ||
2158 pDoc->isXForms() ||
2159 !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
2160 return sal_False;
2161 break;
2162 default: OSL_FAIL( "Unknown idle job type" );
2165 SwPageFrm *pPage;
2166 if ( bVisAreaOnly )
2167 pPage = pImp->GetFirstVisPage();
2168 else
2169 pPage = (SwPageFrm*)pRoot->Lower();
2171 pCntntNode = NULL;
2172 nTxtPos = STRING_LEN;
2174 while ( pPage )
2176 bPageValid = sal_True;
2177 const SwCntntFrm *pCnt = pPage->ContainsCntnt();
2178 while( pCnt && pPage->IsAnLower( pCnt ) )
2180 if ( _DoIdleJob( pCnt, eJob ) )
2181 return sal_True;
2182 pCnt = pCnt->GetNextCntntFrm();
2184 if ( pPage->GetSortedObjs() )
2186 for ( sal_uInt16 i = 0; pPage->GetSortedObjs() &&
2187 i < pPage->GetSortedObjs()->Count(); ++i )
2189 const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
2190 if ( pObj->ISA(SwFlyFrm) )
2192 const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
2193 const SwCntntFrm *pC = pFly->ContainsCntnt();
2194 while( pC )
2196 if ( pC->IsTxtFrm() )
2198 if ( _DoIdleJob( pC, eJob ) )
2199 return sal_True;
2201 pC = pC->GetNextCntntFrm();
2207 if( bPageValid )
2209 switch ( eJob )
2211 case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
2212 case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
2213 case WORD_COUNT : pPage->ValidateWordCount(); break;
2214 case SMART_TAGS : pPage->ValidateSmartTags(); break; // SMARTTAGS
2218 pPage = (SwPageFrm*)pPage->GetNext();
2219 if ( pPage && bVisAreaOnly &&
2220 !pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
2221 break;
2223 return sal_False;
2226 #ifdef DBG_UTIL
2227 /*************************************************************************
2229 |* void SwLayIdle::SwLayIdle()
2231 |*************************************************************************/
2232 void SwLayIdle::ShowIdle( ColorData eColorData )
2234 if ( !m_bIndicator )
2236 m_bIndicator = true;
2237 Window *pWin = pImp->GetShell()->GetWin();
2238 if ( pWin )
2240 Rectangle aRect( 0, 0, 5, 5 );
2241 aRect = pWin->PixelToLogic( aRect );
2242 // OD 2004-04-23 #116347#
2243 pWin->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
2244 pWin->SetFillColor( eColorData );
2245 pWin->SetLineColor();
2246 pWin->DrawRect( aRect );
2247 pWin->Pop();
2251 #define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
2252 #else
2253 #define SHOW_IDLE( ColorData )
2254 #endif // DBG_UTIL
2256 /*************************************************************************
2258 |* void SwLayIdle::SwLayIdle()
2260 |*************************************************************************/
2261 SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
2262 pRoot( pRt ),
2263 pImp( pI )
2264 #ifdef DBG_UTIL
2265 , m_bIndicator( false )
2266 #endif
2268 pImp->pIdleAct = this;
2270 SHOW_IDLE( COL_LIGHTRED );
2272 pImp->GetShell()->EnableSmooth( sal_False );
2274 // First, spellcheck the visible area. Only if there's nothing
2275 // to do there, we trigger the IdleFormat.
2276 if ( !DoIdleJob( SMART_TAGS, sal_True ) &&
2277 !DoIdleJob( ONLINE_SPELLING, sal_True ) &&
2278 !DoIdleJob( AUTOCOMPLETE_WORDS, sal_True ) ) // SMARTTAGS
2280 // Format, then register repaint rectangles with the ViewShell if necessary.
2281 // This requires running artificial actions, so we don't get undesired
2282 // effects when for instance the page count gets changed.
2283 // We remember the shells where the cursor is visible, so we can make
2284 // it visible again if needed after a document change.
2285 std::vector<bool> aBools;
2286 ViewShell *pSh = pImp->GetShell();
2288 { ++pSh->mnStartAction;
2289 sal_Bool bVis = sal_False;
2290 if ( pSh->ISA(SwCrsrShell) )
2292 bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
2294 aBools.push_back( bVis );
2295 pSh = (ViewShell*)pSh->GetNext();
2296 } while ( pSh != pImp->GetShell() );
2298 SwLayAction aAction( pRoot, pImp );
2299 aAction.SetInputType( VCL_INPUT_ANY );
2300 aAction.SetIdle( sal_True );
2301 aAction.SetWaitAllowed( sal_False );
2302 aAction.Action();
2304 // Further start/end actions only happen if there were paints started
2305 // somewhere or if the visibility of the CharRects has changed.
2306 sal_Bool bActions = sal_False;
2307 sal_uInt16 nBoolIdx = 0;
2310 --pSh->mnStartAction;
2312 if ( pSh->Imp()->GetRegion() )
2313 bActions = sal_True;
2314 else
2316 SwRect aTmp( pSh->VisArea() );
2317 pSh->UISizeNotify();
2319 // #137134#
2320 // Are we supposed to crash if pSh isn't a cursor shell?!
2321 // bActions |= aTmp != pSh->VisArea() ||
2322 // aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
2324 // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
2325 // and the cursor is visible.
2326 bActions |= aTmp != pSh->VisArea();
2327 if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
2329 bActions |= ((sal_Bool) aBools[nBoolIdx]) !=
2330 static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
2334 pSh = (ViewShell*)pSh->GetNext();
2335 ++nBoolIdx;
2336 } while ( pSh != pImp->GetShell() );
2338 if ( bActions )
2340 // Prepare start/end actions via CrsrShell, so the cursor, selection
2341 // and VisArea can be set correctly.
2342 nBoolIdx = 0;
2345 sal_Bool bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
2347 if ( bCrsrShell )
2348 ((SwCrsrShell*)pSh)->SttCrsrMove();
2349 // else
2350 // pSh->StartAction();
2352 // If there are accrued paints, it's best to simply invalidate
2353 // the whole window. Otherwise there would arise paint problems whose
2354 // solution would be disproportionally expensive.
2355 //fix(18176):
2356 SwViewImp *pViewImp = pSh->Imp();
2357 bool bUnlock = false;
2358 if ( pViewImp->GetRegion() )
2360 pViewImp->DelRegion();
2362 // Cause a repaint with virtual device.
2363 pSh->LockPaint();
2364 bUnlock = true;
2367 if ( bCrsrShell )
2368 // If the Crsr was visible, we need to make it visible again.
2369 // Otherwise, EndCrsrMove with sal_True for IdleEnd
2370 ((SwCrsrShell*)pSh)->EndCrsrMove( sal_True^aBools[nBoolIdx] );
2371 // else
2372 // pSh->EndAction();
2373 if( bUnlock )
2375 if( bCrsrShell )
2377 // UnlockPaint overwrite the selection from the
2378 // CrsrShell and calls the virtual method paint
2379 // to fill the virtual device. This fill dont have
2380 // paint the selection! -> Set the focus flag at
2381 // CrsrShell and it dont paint the selection.
2382 ((SwCrsrShell*)pSh)->ShLooseFcs();
2383 pSh->UnlockPaint( sal_True );
2384 ((SwCrsrShell*)pSh)->ShGetFcs( sal_False );
2386 else
2387 pSh->UnlockPaint( sal_True );
2390 pSh = (ViewShell*)pSh->GetNext();
2391 ++nBoolIdx;
2393 } while ( pSh != pImp->GetShell() );
2396 if ( !aAction.IsInterrupt() )
2398 if ( !DoIdleJob( WORD_COUNT, sal_False ) )
2399 if ( !DoIdleJob( SMART_TAGS, sal_False ) )
2400 if ( !DoIdleJob( ONLINE_SPELLING, sal_False ) )
2401 DoIdleJob( AUTOCOMPLETE_WORDS, sal_False ); // SMARTTAGS
2404 bool bInValid = false;
2405 const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
2406 const ViewShell* pViewShell = pImp->GetShell();
2407 // See conditions in DoIdleJob()
2408 const sal_Bool bSpell = rVOpt.IsOnlineSpell();
2409 const sal_Bool bACmplWrd = rVOpt.IsAutoCompleteWords();
2410 const sal_Bool bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
2411 const bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
2412 !pViewShell->GetDoc()->isXForms() &&
2413 SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
2415 SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
2418 bInValid = pPg->IsInvalidCntnt() || pPg->IsInvalidLayout() ||
2419 pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
2420 pPg->IsInvalidFlyInCnt() ||
2421 (bSpell && pPg->IsInvalidSpelling()) ||
2422 (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
2423 (bWordCount && pPg->IsInvalidWordCount()) ||
2424 (bSmartTags && pPg->IsInvalidSmartTags()); // SMARTTAGS
2426 pPg = (SwPageFrm*)pPg->GetNext();
2428 } while ( pPg && !bInValid );
2430 if ( !bInValid )
2432 pRoot->ResetIdleFormat();
2433 SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
2434 pDocShell->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
2438 pImp->GetShell()->EnableSmooth( sal_True );
2440 if( pImp->IsAccessible() )
2441 pImp->FireAccessibleEvents();
2443 #ifdef DBG_UTIL
2444 if ( m_bIndicator && pImp->GetShell()->GetWin() )
2446 // #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
2447 // This should be replaced by an overlay object in the future, anyways. Since it's only for debug
2448 // purposes, it is not urgent.
2449 m_bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
2451 #endif
2454 SwLayIdle::~SwLayIdle()
2456 pImp->pIdleAct = 0;
2459 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */