update dev300-m58
[ooovba.git] / sw / source / core / layout / layact.cxx
blob68eb0469c9f9c9f289a3e23e61cccd813c77f6ed
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: layact.cxx,v $
10 * $Revision: 1.75 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
36 #include <time.h>
37 #include "rootfrm.hxx"
38 #include "pagefrm.hxx"
39 #include "cntfrm.hxx"
40 #include "doc.hxx"
41 #include "IDocumentDrawModelAccess.hxx"
42 #include "IDocumentSettingAccess.hxx"
43 #include "IDocumentLayoutAccess.hxx"
44 #include "IDocumentStatistics.hxx"
45 #include "IDocumentTimerAccess.hxx"
46 #include "viewimp.hxx"
47 #include "crsrsh.hxx"
48 #include "dflyobj.hxx"
49 #include "flyfrm.hxx"
50 #include "frmtool.hxx"
51 #include "dcontact.hxx"
52 #include "ndtxt.hxx" // OnlineSpelling
53 #include "frmfmt.hxx"
54 #include "swregion.hxx"
55 #include "viewopt.hxx" // OnlineSpelling ueber Internal-TabPage testen.
56 #include "pam.hxx" // OnlineSpelling wg. der aktuellen Cursorposition
57 #include "dbg_lay.hxx"
58 #include "layouter.hxx" // LoopControlling
59 #include "docstat.hxx"
60 #include "swevent.hxx"
62 #include <sfx2/event.hxx>
64 #include <ftnidx.hxx>
65 #include <vcl/window.hxx>
66 #include <vcl/svapp.hxx>
67 #include <svx/opaqitem.hxx>
68 #include <svx/brshitem.hxx>
69 #include <SwSmartTagMgr.hxx>
71 #define _SVSTDARR_BOOLS
72 #include <svtools/svstdarr.hxx>
74 #define _LAYACT_CXX
75 #include "layact.hxx"
76 #include <swwait.hxx>
77 #include <fmtsrnd.hxx>
78 #include <fmtanchr.hxx>
79 #include <tools/shl.hxx>
80 #include <sfx2/progress.hxx>
81 #ifndef _DOCSH_HXX
82 #include <docsh.hxx>
83 #endif
85 #include "swmodule.hxx"
86 #include "fmtline.hxx"
87 #include "tabfrm.hxx"
88 #include "ftnfrm.hxx"
89 #include "txtfrm.hxx"
90 #include "notxtfrm.hxx"
91 #include "flyfrms.hxx"
92 #include "mdiexp.hxx"
93 #include "fmtornt.hxx"
94 #include "sectfrm.hxx"
95 #include "lineinfo.hxx"
96 #include <acmplwrd.hxx>
97 // --> OD 2004-06-28 #i28701#
98 #include <sortedobjs.hxx>
99 #include <objectformatter.hxx>
100 #include <PostItMgr.hxx>
102 // <--
103 //#pragma optimize("ity",on)
105 /*************************************************************************
107 |* SwLayAction Statisches Geraffel
109 |* Ersterstellung MA 22. Dec. 93
110 |* Letzte Aenderung MA 22. Dec. 93
112 |*************************************************************************/
114 #define IS_FLYS (pPage->GetSortedObjs())
115 #define IS_INVAFLY (pPage->IsInvalidFly())
118 //Sparen von Schreibarbeit um den Zugriff auf zerstoerte Seiten zu vermeiden.
119 #ifndef PRODUCT
121 static void BreakPoint()
123 return;
126 #define CHECKPAGE \
127 { if ( IsAgain() ) \
128 { BreakPoint(); \
129 return; \
133 #define XCHECKPAGE \
134 { if ( IsAgain() ) \
135 { BreakPoint(); \
136 if( bNoLoop ) \
137 pLayoutAccess->GetLayouter()->EndLoopControl(); \
138 return; \
141 #else
142 #define CHECKPAGE \
143 { if ( IsAgain() ) \
144 return; \
147 #define XCHECKPAGE \
148 { if ( IsAgain() ) \
150 if( bNoLoop ) \
151 pLayoutAccess->GetLayouter()->EndLoopControl(); \
152 return; \
155 #endif
157 #define RESCHEDULE \
159 if ( IsReschedule() ) \
161 if (pProgress) pProgress->Reschedule(); \
162 ::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
166 inline ULONG Ticks()
168 return 1000 * clock() / CLOCKS_PER_SEC;
171 void SwLayAction::CheckWaitCrsr()
173 RESCHEDULE
174 if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
175 ((Ticks() - GetStartTicks()) >= CLOCKS_PER_SEC/2) )
177 pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), TRUE );
181 /*************************************************************************
183 |* SwLayAction::CheckIdleEnd()
185 |* Ersterstellung MA 12. Aug. 94
186 |* Letzte Aenderung MA 24. Jun. 96
188 |*************************************************************************/
189 //Ist es wirklich schon soweit...
190 inline void SwLayAction::CheckIdleEnd()
192 if ( !IsInput() )
193 bInput = GetInputType() && Application::AnyInput( GetInputType() );
196 /*************************************************************************
198 |* SwLayAction::SetStatBar()
200 |* Ersterstellung MA 10. Aug. 94
201 |* Letzte Aenderung MA 06. Aug. 95
203 |*************************************************************************/
204 void SwLayAction::SetStatBar( BOOL bNew )
206 if ( bNew )
208 nEndPage = pRoot->GetPageNum();
209 nEndPage += nEndPage * 10 / 100;
211 else
212 nEndPage = USHRT_MAX;
215 /*************************************************************************
217 |* SwLayAction::PaintCntnt()
219 |* Beschreibung Je nach Typ wird der Cntnt entsprechend seinen
220 |* Veraenderungen ausgegeben bzw. wird die auszugebende Flaeche in der
221 |* Region eingetragen.
222 |* PaintCntnt: fuellt die Region,
223 |* Ersterstellung BP 19. Jan. 92
224 |* Letzte Aenderung MA 10. Sep. 96
226 |*************************************************************************/
227 BOOL SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
228 const SwPageFrm *pPage )
230 SwRegionRects aTmp( rRect );
231 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
232 const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
233 USHORT i;
235 for ( i = 0; i < rObjs.Count() && aTmp.Count(); ++i )
237 SdrObject *pO = rObjs[i]->DrawObj();
238 if ( !pO->ISA(SwVirtFlyDrawObj) )
239 continue;
241 // OD 2004-01-15 #110582# - do not consider invisible objects
242 const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
243 if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
245 continue;
248 SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
250 if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
251 continue;
253 if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
254 continue;
256 if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
257 continue;
259 if ( pSelfFly )
261 const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
262 if ( pO->GetLayer() == pTmp->GetLayer() )
264 if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
265 //Im gleichen Layer werden nur obenliegende beachtet.
266 continue;
268 else
270 const BOOL bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
271 if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
272 //Aus anderem Layer interessieren uns nur nicht transparente
273 //oder innenliegende
274 continue;
278 /// OD 19.08.2002 #99657#
279 /// Fly frame without a lower have to be subtracted from paint region.
280 /// For checking, if fly frame contains transparent graphic or
281 /// has surrounded contour, assure that fly frame has a lower
282 if ( pFly->Lower() &&
283 pFly->Lower()->IsNoTxtFrm() &&
284 ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
285 pFly->GetFmt()->GetSurround().IsContour() )
288 continue;
291 /// OD 19.08.2002 #99657#
292 /// Region of a fly frame with transparent background or a transparent
293 /// shadow have not to be subtracted from paint region
294 if ( pFly->IsBackgroundTransparent() ||
295 pFly->IsShadowTransparent() )
297 continue;
300 aTmp -= pFly->Frm();
303 BOOL bRetPaint = FALSE;
304 const SwRect *pData = aTmp.GetData();
305 for ( i = 0; i < aTmp.Count(); ++pData, ++i )
306 bRetPaint |= pImp->GetShell()->AddPaintRect( *pData );
307 return bRetPaint;
310 inline BOOL SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
311 const SwPageFrm *pPage,
312 const SwRect &rRect )
314 if ( rRect.HasArea() )
316 if ( pPage->GetSortedObjs() )
317 return PaintWithoutFlys( rRect, pCntnt, pPage );
318 else
319 return pImp->GetShell()->AddPaintRect( rRect );
321 return FALSE;
324 void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
325 const SwPageFrm *pPage,
326 const SwRect &rOldRect,
327 long nOldBottom )
329 SWRECTFN( pCnt )
331 if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
333 SwRect aPaint( pCnt->PaintArea() );
334 if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
335 pCnt->ResetCompletePaint();
337 else
339 // paint the area between printing bottom and frame bottom and
340 // the area left and right beside the frame, if its height changed.
341 long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
342 long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
343 const bool bHeightDiff = nOldHeight != nNewHeight;
344 if( bHeightDiff )
346 // OD 05.11.2002 #94454# - consider whole potential paint area.
347 //SwRect aDrawRect( pCnt->UnionFrm( TRUE ) );
348 SwRect aDrawRect( pCnt->PaintArea() );
349 if( nOldHeight > nNewHeight )
350 nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
351 (aDrawRect.*fnRect->fnSetTop)( nOldBottom );
352 _PaintCntnt( pCnt, pPage, aDrawRect );
354 // paint content area
355 SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
356 _PaintCntnt( pCnt, pPage, aPaintRect );
359 if ( pCnt->IsRetouche() && !pCnt->GetNext() )
361 const SwFrm *pTmp = pCnt;
362 if( pCnt->IsInSct() )
364 const SwSectionFrm* pSct = pCnt->FindSctFrm();
365 if( pSct->IsRetouche() && !pSct->GetNext() )
366 pTmp = pSct;
368 SwRect aRect( pTmp->GetUpper()->PaintArea() );
369 (aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
370 if ( !_PaintCntnt( pCnt, pPage, aRect ) )
371 pCnt->ResetRetouche();
375 /*************************************************************************
377 |* SwLayAction::_AddScrollRect()
379 |* Ersterstellung MA 04. Mar. 94
380 |* Letzte Aenderung MA 04. Mar. 94
382 |*************************************************************************/
383 BOOL MA_FASTCALL lcl_IsOverObj( const SwFrm *pFrm, const SwPageFrm *pPage,
384 const SwRect &rRect1, const SwRect &rRect2,
385 const SwLayoutFrm *pLay )
387 const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
388 const SwFlyFrm *pSelfFly = pFrm->FindFlyFrm();
389 const BOOL bInCnt = pSelfFly && pSelfFly->IsFlyInCntFrm() ? TRUE : FALSE;
391 for ( sal_uInt32 j = 0; j < rObjs.Count(); ++j )
393 // --> OD 2004-07-07 #i28701# - consider changed type of <SwSortedObjs> entries
394 const SwAnchoredObject* pAnchoredObj = rObjs[j];
395 const SwRect aRect( pAnchoredObj->GetObjRect() );
396 if ( !rRect1.IsOver( aRect ) && !rRect2.IsOver( aRect ) )
397 continue; //Keine Ueberlappung, der naechste.
399 const SwFlyFrm *pFly = pAnchoredObj->ISA(SwFlyFrm)
400 ? static_cast<const SwFlyFrm*>(pAnchoredObj) : 0;
402 //Wenn der Rahmen innerhalb des LayFrm verankert ist, so darf er
403 //mitgescrollt werden, wenn er nicht seitlich aus dem Rechteck
404 //herausschaut.
405 if ( pLay && pFly && pFly->IsLowerOf( pLay ) )
407 if ( pFly->Frm().Left() < rRect1.Left() ||
408 pFly->Frm().Right()> rRect1.Right() )
409 return TRUE;
410 continue;
413 if ( !pSelfFly ) //Nur wenn der Frm in einem Fly steht kann
414 return TRUE; //es Einschraenkungen geben.
416 if ( !pFly ) //Keine Einschraenkung fuer Zeichenobjekte.
417 return TRUE;
419 if ( pFly != pSelfFly )
421 //Flys unter dem eigenen nur dann abziehen, wenn sie innerhalb des
422 //eigenen stehen.
423 //Fuer inhaltsgebundene Flys alle Flys abziehen fuer die gilt, dass
424 //pSelfFly nicht innerhalb von ihnen steht.
425 if ( bInCnt )
427 const SwFlyFrm *pTmp = pSelfFly->GetAnchorFrm()->FindFlyFrm();
428 while ( pTmp )
430 if ( pTmp == pFly )
431 return FALSE;
432 else
433 pTmp = pTmp->GetAnchorFrm()->FindFlyFrm();
435 } else if ( pAnchoredObj->GetDrawObj()->GetOrdNum() <
436 pSelfFly->GetVirtDrawObj()->GetOrdNum() )
438 const SwFlyFrm *pTmp = pFly;
440 { if ( pTmp == pSelfFly )
441 return TRUE;
442 else
443 pTmp = pTmp->GetAnchorFrm()->FindFlyFrm();
444 } while ( pTmp );
445 } else
446 return TRUE;
449 return FALSE;
452 void SwLayAction::_AddScrollRect( const SwCntntFrm *pCntnt,
453 const SwPageFrm *pPage,
454 const SwTwips nOfst,
455 const SwTwips nOldBottom )
457 // --> OD 2004-07-01 #i28701# - determine, if scrolling is allowed.
458 bool bScroll = mbScrollingAllowed;
459 SwRect aPaintRect( pCntnt->PaintArea() );
460 SWRECTFN( pCntnt )
462 // --> OD 2007-11-27 #notes2#
463 // if sidebar for notes is present, no scrolling is allowed
464 if ( bScroll )
466 const SwPostItMgr* pPostItMgr = pImp->GetShell()->GetPostItMgr();
467 if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
469 bScroll = false;
472 // <--
474 //Wenn altes oder neues Rechteck mit einem Fly ueberlappen, in dem der
475 //Cntnt nicht selbst steht, so ist nichts mit Scrollen.
476 if ( bScroll && pPage->GetSortedObjs() )
478 SwRect aRect( aPaintRect );
479 if( bVert )
480 aPaintRect.Pos().X() += nOfst;
481 else
482 aPaintRect.Pos().Y() -= nOfst;
484 if ( ::lcl_IsOverObj( pCntnt, pPage, aPaintRect, aRect, 0 ) )
485 bScroll = false;
487 if( bVert )
488 aPaintRect.Pos().X() -= nOfst;
489 else
490 aPaintRect.Pos().Y() += nOfst;
492 if ( bScroll && pPage->GetFmt()->GetBackground().GetGraphicPos() != GPOS_NONE )
493 bScroll = false;
495 if ( bScroll )
497 if( aPaintRect.HasArea() )
498 pImp->GetShell()->AddScrollRect( pCntnt, aPaintRect, nOfst );
499 if ( pCntnt->IsRetouche() && !pCntnt->GetNext() )
501 SwRect aRect( pCntnt->GetUpper()->PaintArea() );
502 (aRect.*fnRect->fnSetTop)( (pCntnt->*fnRect->fnGetPrtBottom)() );
503 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
504 pCntnt->ResetRetouche();
506 pCntnt->ResetCompletePaint();
508 else if( aPaintRect.HasArea() )
510 if( bVert )
511 aPaintRect.Pos().X() += nOfst;
512 else
513 aPaintRect.Pos().Y() -= nOfst;
514 PaintCntnt( pCntnt, pPage, aPaintRect, nOldBottom );
518 /*************************************************************************
520 |* SwLayAction::SwLayAction()
522 |* Ersterstellung MA 30. Oct. 92
523 |* Letzte Aenderung MA 09. Jun. 95
525 |*************************************************************************/
526 SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
527 pRoot( pRt ),
528 pImp( pI ),
529 pOptTab( 0 ),
530 pWait( 0 ),
531 pProgress(NULL),
532 nPreInvaPage( USHRT_MAX ),
533 nStartTicks( Ticks() ),
534 nInputType( 0 ),
535 nEndPage( USHRT_MAX ),
536 nCheckPageNum( USHRT_MAX )
538 bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
539 bPaint = bComplete = bWaitAllowed = bCheckPages = TRUE;
540 bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
541 bUpdateExpFlds = bBrowseActionStop = bActionInProgress = FALSE;
542 // OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
543 mbFormatCntntOnInterrupt = sal_False;
544 // --> OD 2004-06-14 #i28701#
545 mbScrollingAllowed = true;
547 pImp->pLayAct = this; //Anmelden
550 SwLayAction::~SwLayAction()
552 ASSERT( !pWait, "Wait object not destroyed" );
553 pImp->pLayAct = 0; //Abmelden
556 /*************************************************************************
558 |* SwLayAction::Reset()
560 |* Ersterstellung MA 11. Aug. 94
561 |* Letzte Aenderung MA 09. Jun. 95
563 |*************************************************************************/
564 void SwLayAction::Reset()
566 pOptTab = 0;
567 nStartTicks = Ticks();
568 nInputType = 0;
569 nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
570 bPaint = bComplete = bWaitAllowed = bCheckPages = TRUE;
571 bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
572 bUpdateExpFlds = bBrowseActionStop = FALSE;
575 /*************************************************************************
577 |* SwLayAction::RemoveEmptyBrowserPages()
579 |* Ersterstellung MA 10. Sep. 97
580 |* Letzte Aenderung MA 10. Sep. 97
582 |*************************************************************************/
584 BOOL SwLayAction::RemoveEmptyBrowserPages()
586 //Beim umschalten vom normalen in den Browsermodus bleiben u.U. einige
587 //unangenehm lange stehen. Diese beseiten wir mal schnell.
588 BOOL bRet = FALSE;
589 if ( pRoot->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
591 SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
594 if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->Count()) ||
595 pPage->ContainsCntnt() )
596 pPage = (SwPageFrm*)pPage->GetNext();
597 else
599 bRet = TRUE;
600 SwPageFrm *pDel = pPage;
601 pPage = (SwPageFrm*)pPage->GetNext();
602 pDel->Cut();
603 delete pDel;
605 } while ( pPage );
607 return bRet;
611 /*************************************************************************
613 |* SwLayAction::Action()
615 |* Ersterstellung MA 10. Aug. 94
616 |* Letzte Aenderung MA 06. Aug. 95
618 |*************************************************************************/
619 void SwLayAction::Action()
621 bActionInProgress = TRUE;
623 //TurboMode? Disqualifiziert fuer Idle-Format.
624 if ( IsPaint() && !IsIdle() && TurboAction() )
626 delete pWait, pWait = 0;
627 pRoot->ResetTurboFlag();
628 bActionInProgress = FALSE;
629 pRoot->DeleteEmptySct();
630 return;
632 else if ( pRoot->GetTurbo() )
634 pRoot->DisallowTurbo();
635 const SwFrm *pFrm = pRoot->GetTurbo();
636 pRoot->ResetTurbo();
637 pFrm->InvalidatePage();
639 pRoot->DisallowTurbo();
641 if ( IsCalcLayout() )
642 SetCheckPages( FALSE );
644 InternalAction();
645 bAgain |= RemoveEmptyBrowserPages();
646 while ( IsAgain() )
648 bAgain = bNextCycle = FALSE;
649 InternalAction();
650 bAgain |= RemoveEmptyBrowserPages();
652 pRoot->DeleteEmptySct();
654 delete pWait, pWait = 0;
656 //Turbo-Action ist auf jedenfall wieder erlaubt.
657 pRoot->ResetTurboFlag();
658 pRoot->ResetTurbo();
660 if ( IsInput() )
661 pImp->GetShell()->SetNoNextScroll();
662 SetCheckPages( TRUE );
664 bActionInProgress = FALSE;
667 SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
669 SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
670 SwCntntFrm *pChk = pCnt;
671 BOOL bPageChgd = FALSE;
672 while ( pCnt && pCnt->IsFollow() )
673 pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
674 if ( pCnt && pChk != pCnt )
675 { bPageChgd = TRUE;
676 pPage = pCnt->FindPageFrm();
679 if ( pPage->GetFmt()->GetDoc()->GetFtnIdxs().Count() )
681 SwFtnContFrm *pCont = pPage->FindFtnCont();
682 if ( pCont )
684 pCnt = pCont->ContainsCntnt();
685 pChk = pCnt;
686 while ( pCnt && pCnt->IsFollow() )
687 pCnt = (SwCntntFrm*)pCnt->FindPrev();
688 if ( pCnt && pCnt != pChk )
690 if ( bPageChgd )
692 //Die 'oberste' Seite benutzten.
693 SwPageFrm *pTmp = pCnt->FindPageFrm();
694 if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
695 pPage = pTmp;
697 else
698 pPage = pCnt->FindPageFrm();
702 return pPage;
705 // OD 2004-05-12 #i28701#
706 // --> OD 2004-11-03 #i114798# - unlock position on start and end of page
707 // layout process.
708 class NotifyLayoutOfPageInProgress
710 private:
711 SwPageFrm& mrPageFrm;
713 void _UnlockPositionOfObjs()
715 SwSortedObjs* pObjs = mrPageFrm.GetSortedObjs();
716 if ( pObjs )
718 sal_uInt32 i = 0;
719 for ( ; i < pObjs->Count(); ++i )
721 SwAnchoredObject* pObj = (*pObjs)[i];
722 pObj->UnlockPosition();
726 public:
727 NotifyLayoutOfPageInProgress( SwPageFrm& _rPageFrm )
728 : mrPageFrm( _rPageFrm )
730 _UnlockPositionOfObjs();
731 _rPageFrm.SetLayoutInProgress( true );
733 ~NotifyLayoutOfPageInProgress()
735 mrPageFrm.SetLayoutInProgress( false );
736 _UnlockPositionOfObjs();
739 // <--
741 // --> OD 2004-06-14 #i28701# - local method to determine, if scrolling during
742 // the format of the given page is allowed.
743 // Scrolling isn't allowed, if the wrapping style of floating screen objects
744 // is considered on object positioning and to-paragraph/to-character anchored
745 // floating screen objects are registered at the page.
746 bool lcl_ScrollingAllowed( const SwPageFrm& _rPageFrm )
748 bool bRetScrollAllowed = true;
750 if ( _rPageFrm.GetSortedObjs() &&
751 _rPageFrm.GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION) )
753 const SwSortedObjs* pObjs = _rPageFrm.GetSortedObjs();
754 sal_uInt32 i = 0;
755 for ( ; i < pObjs->Count(); ++i )
757 SwAnchoredObject* pObj = (*pObjs)[i];
758 if ( pObj->ConsiderObjWrapInfluenceOnObjPos() )
760 bRetScrollAllowed = false;
761 break;
766 return bRetScrollAllowed;
769 void SwLayAction::InternalAction()
771 ASSERT( pRoot->Lower()->IsPageFrm(), ":-( Keine Seite unterhalb der Root.");
773 pRoot->Calc();
775 //Die erste ungueltige bzw. zu formatierende Seite ermitteln.
776 //Bei einer Complete-Action ist es die erste ungueltige; mithin ist die
777 //erste zu formatierende Seite diejenige Seite mit der Numemr eins.
778 //Bei einer Luegen-Formatierung ist die Nummer der erste Seite die Nummer
779 //der ersten Sichtbaren Seite.
780 SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
781 pImp->GetFirstVisPage();
782 if ( !pPage )
783 pPage = (SwPageFrm*)pRoot->Lower();
785 //Wenn ein "Erster-Fliess-Cntnt" innerhalb der der ersten sichtbaren Seite
786 //ein Follow ist, so schalten wir die Seite zurueck auf den Ur-Master dieses
787 //Cntnt's
788 if ( !IsComplete() )
789 pPage = CheckFirstVisPage( pPage );
790 USHORT nFirstPageNum = pPage->GetPhyPageNum();
792 while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
793 pPage = (SwPageFrm*)pPage->GetNext();
795 IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
796 BOOL bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : FALSE;
797 USHORT nPercentPageNum = 0;
798 while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
800 if ( !pPage && nCheckPageNum != USHRT_MAX &&
801 (!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
803 if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
805 SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
806 while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
807 pPg = (SwPageFrm*)pPg->GetNext();
808 if ( pPg )
809 pPage = pPg;
810 if ( !pPage )
811 break;
813 SwPageFrm *pTmp = pPage->GetPrev() ?
814 (SwPageFrm*)pPage->GetPrev() : pPage;
815 SetCheckPages( TRUE );
816 SwFrm::CheckPageDescs( pPage );
817 SetCheckPages( FALSE );
818 nCheckPageNum = USHRT_MAX;
819 pPage = pTmp;
820 continue;
823 if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
825 nPercentPageNum = pPage->GetPhyPageNum();
826 ::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
828 pOptTab = 0;
829 //Kein ShortCut fuer Idle oder CalcLayout
830 if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
832 pRoot->DeleteEmptySct();
833 XCHECKPAGE;
834 if ( !IsInterrupt() &&
835 (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
837 if ( pRoot->IsAssertFlyPages() )
838 pRoot->AssertFlyPages();
839 if ( pRoot->IsSuperfluous() )
841 BOOL bOld = IsAgain();
842 pRoot->RemoveSuperfluous();
843 bAgain = bOld;
845 if ( IsAgain() )
847 if( bNoLoop )
848 pLayoutAccess->GetLayouter()->EndLoopControl();
849 return;
851 pPage = (SwPageFrm*)pRoot->Lower();
852 while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
853 pPage = (SwPageFrm*)pPage->GetNext();
854 while ( pPage && pPage->GetNext() &&
855 pPage->GetPhyPageNum() < nFirstPageNum )
856 pPage = (SwPageFrm*)pPage->GetNext();
857 continue;
859 break;
861 else
863 pRoot->DeleteEmptySct();
864 XCHECKPAGE;
866 // OD 2004-05-12 #i28701# - scope for instance of class
867 // <NotifyLayoutOfPageInProgress>
869 NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPage );
870 // --> OD 2004-07-01 #i28701# - determine, if scrolling is allowed.
871 mbScrollingAllowed = lcl_ScrollingAllowed( *pPage );
873 while ( !IsInterrupt() && !IsNextCycle() &&
874 ((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
876 // OD 2004-05-10 #i28701#
877 SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
878 if ( !IS_FLYS )
880 //Wenn keine Flys (mehr) da sind, sind die Flags
881 //mehr als fluessig.
882 pPage->ValidateFlyLayout();
883 pPage->ValidateFlyCntnt();
885 // OD 2004-05-10 #i28701# - change condition
886 while ( !IsInterrupt() && !IsNextCycle() &&
887 ( pPage->IsInvalid() ||
888 (IS_FLYS && IS_INVAFLY) ) )
890 PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
891 XCHECKPAGE;
893 // FME 2007-08-30 #i81146# new loop control
894 USHORT nLoopControlRuns_1 = 0;
895 const USHORT nLoopControlMax = 20;
897 while ( !IsNextCycle() && pPage->IsInvalidLayout() )
899 pPage->ValidateLayout();
901 if ( ++nLoopControlRuns_1 > nLoopControlMax )
903 #if OSL_DEBUG_LEVEL > 1
904 ASSERT( false, "LoopControl_1 in SwLayAction::InternalAction" )
905 #endif
906 break;
909 FormatLayout( pPage );
910 XCHECKPAGE;
912 // OD 2004-05-10 #i28701# - change condition
913 if ( !IsNextCycle() &&
914 ( pPage->IsInvalidCntnt() ||
915 (IS_FLYS && IS_INVAFLY) ) )
917 pPage->ValidateFlyInCnt();
918 pPage->ValidateCntnt();
919 // --> OD 2004-05-10 #i28701#
920 pPage->ValidateFlyLayout();
921 pPage->ValidateFlyCntnt();
922 // <--
923 if ( !FormatCntnt( pPage ) )
925 XCHECKPAGE;
926 pPage->InvalidateCntnt();
927 pPage->InvalidateFlyInCnt();
928 // --> OD 2004-05-10 #i28701#
929 pPage->InvalidateFlyLayout();
930 pPage->InvalidateFlyCntnt();
931 // <--
932 if ( IsBrowseActionStop() )
933 bInput = TRUE;
936 if( bNoLoop )
937 pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
940 } // end of scope for instance of class <NotifyLayoutOfPageInProgress>
943 //Eine vorige Seite kann wieder invalid sein.
944 XCHECKPAGE;
945 if ( !IS_FLYS )
947 //Wenn keine Flys (mehr) da sind, sind die Flags
948 //mehr als fluessig.
949 pPage->ValidateFlyLayout();
950 pPage->ValidateFlyCntnt();
952 if ( !IsInterrupt() )
954 SetNextCycle( FALSE );
956 if ( nPreInvaPage != USHRT_MAX )
958 if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
960 pImp->SetFirstVisPageInvalid();
961 SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
962 nFirstPageNum = pTmpPage->GetPhyPageNum();
963 if( nPreInvaPage < nFirstPageNum )
965 nPreInvaPage = nFirstPageNum;
966 pPage = pTmpPage;
969 while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
970 pPage = (SwPageFrm*)pPage->GetPrev();
971 nPreInvaPage = USHRT_MAX;
974 while ( pPage->GetPrev() &&
975 ( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
976 ( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
977 ((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
978 (((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
979 nFirstPageNum) )
981 pPage = (SwPageFrm*)pPage->GetPrev();
984 //Weiter bis zur naechsten invaliden Seite.
985 while ( pPage && !pPage->IsInvalid() &&
986 (!IS_FLYS || !IS_INVAFLY) )
988 pPage = (SwPageFrm*)pPage->GetNext();
990 if( bNoLoop )
991 pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
993 CheckIdleEnd();
995 if ( !pPage && !IsInterrupt() &&
996 (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
998 if ( pRoot->IsAssertFlyPages() )
999 pRoot->AssertFlyPages();
1000 if ( pRoot->IsSuperfluous() )
1002 BOOL bOld = IsAgain();
1003 pRoot->RemoveSuperfluous();
1004 bAgain = bOld;
1006 if ( IsAgain() )
1008 if( bNoLoop )
1009 pLayoutAccess->GetLayouter()->EndLoopControl();
1010 return;
1012 pPage = (SwPageFrm*)pRoot->Lower();
1013 while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
1014 pPage = (SwPageFrm*)pPage->GetNext();
1015 while ( pPage && pPage->GetNext() &&
1016 pPage->GetPhyPageNum() < nFirstPageNum )
1017 pPage = (SwPageFrm*)pPage->GetNext();
1020 if ( IsInterrupt() && pPage )
1022 //Wenn ein Input anliegt wollen wir keinen Inhalt mehr Formatieren,
1023 //Das Layout muessen wir aber schon in Ordnung bringen.
1024 //Andernfalls kann folgende Situation auftreten (Bug: 3244):
1025 //Am Ende des Absatz der letzten Seite wird Text eingegeben, so das
1026 //der Absatz einen Follow fuer die nachste Seite erzeugt, ausserdem
1027 //wird gleich schnell weitergetippt - Es liegt waehrend der
1028 //Verarbeitung ein Input an. Der Absatz auf der neuen Seite wurde
1029 //bereits anformatiert, die neue Seite ist Formatiert und steht
1030 //auf CompletePaint, hat sich aber noch nicht im Auszugebenden Bereich
1031 //eingetragen. Es wird gepaintet, das CompletePaint der Seite wird
1032 //zurueckgesetzt weil der neue Absatz sich bereits eingetragen hatte,
1033 //aber die Raender der Seite werden nicht gepaintet. Naja, bei der
1034 //zwangslaeufig auftretenden naechsten LayAction traegt sich die Seite
1035 //nicht mehr ein, weil ihre (LayoutFrm-)Flags bereits zurueckgesetzt
1036 //wurden -- Der Rand der Seite wird nie gepaintet.
1037 SwPageFrm *pPg = pPage;
1038 XCHECKPAGE;
1039 const SwRect &rVis = pImp->GetShell()->VisArea();
1041 while( pPg && pPg->Frm().Bottom() < rVis.Top() )
1042 pPg = (SwPageFrm*)pPg->GetNext();
1043 if( pPg != pPage )
1044 pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
1046 // OD 14.04.2003 #106346# - set flag for interrupt content formatting
1047 mbFormatCntntOnInterrupt = IsInput() && !IsStopPrt();
1048 long nBottom = rVis.Bottom();
1049 // --> OD 2005-02-15 #i42586# - format current page, if idle action is active
1050 // This is an optimization for the case that the interrupt is created by
1051 // the move of a form control object, which is represented by a window.
1052 while ( pPg && ( pPg->Frm().Top() < nBottom ||
1053 ( IsIdle() && pPg == pPage ) ) )
1054 // <--
1056 // --> OD 2004-10-11 #i26945# - follow-up of #i28701#
1057 NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPg );
1059 XCHECKPAGE;
1061 // FME 2007-08-30 #i81146# new loop control
1062 USHORT nLoopControlRuns_2 = 0;
1063 const USHORT nLoopControlMax = 20;
1065 // OD 14.04.2003 #106346# - special case: interrupt content formatting
1066 // --> OD 2004-07-08 #i28701# - conditions, introduced by #106346#,
1067 // are incorrect (marcos IS_FLYS and IS_INVAFLY only works for <pPage>)
1068 // and are too strict.
1069 // --> OD 2005-06-09 #i50432# - adjust interrupt formatting to
1070 // normal page formatting - see above.
1071 while ( ( mbFormatCntntOnInterrupt &&
1072 ( pPg->IsInvalid() ||
1073 ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
1074 ( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
1076 XCHECKPAGE;
1077 // --> OD 2005-06-09 #i50432# - format also at-page anchored objects
1078 SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
1079 // <--
1080 // --> OD 2005-06-09 #i50432#
1081 if ( !pPg->GetSortedObjs() )
1083 pPg->ValidateFlyLayout();
1084 pPg->ValidateFlyCntnt();
1086 // <--
1088 // FME 2007-08-30 #i81146# new loop control
1089 USHORT nLoopControlRuns_3 = 0;
1091 while ( pPg->IsInvalidLayout() )
1093 pPg->ValidateLayout();
1095 if ( ++nLoopControlRuns_3 > nLoopControlMax )
1097 #if OSL_DEBUG_LEVEL > 1
1098 ASSERT( false, "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" )
1099 #endif
1100 break;
1103 FormatLayout( pPg );
1104 XCHECKPAGE;
1107 // --> OD 2005-06-09 #i50432#
1108 if ( mbFormatCntntOnInterrupt &&
1109 ( pPg->IsInvalidCntnt() ||
1110 ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
1111 // <--
1113 pPg->ValidateFlyInCnt();
1114 pPg->ValidateCntnt();
1115 // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
1116 pPg->ValidateFlyLayout();
1117 pPg->ValidateFlyCntnt();
1118 // <--
1120 if ( ++nLoopControlRuns_2 > nLoopControlMax )
1122 #if OSL_DEBUG_LEVEL > 1
1123 ASSERT( false, "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" )
1124 #endif
1125 break;
1128 if ( !FormatCntnt( pPg ) )
1130 XCHECKPAGE;
1131 pPg->InvalidateCntnt();
1132 pPg->InvalidateFlyInCnt();
1133 // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
1134 pPg->InvalidateFlyLayout();
1135 pPg->InvalidateFlyCntnt();
1136 // <--
1138 // --> OD 2005-04-06 #i46807# - we are statisfied, if the
1139 // content is formatted once complete.
1140 else
1142 break;
1144 // <--
1147 // <--
1148 pPg = (SwPageFrm*)pPg->GetNext();
1150 // OD 14.04.2003 #106346# - reset flag for special interrupt content formatting.
1151 mbFormatCntntOnInterrupt = sal_False;
1153 pOptTab = 0;
1154 if( bNoLoop )
1155 pLayoutAccess->GetLayouter()->EndLoopControl();
1157 /*************************************************************************
1159 |* SwLayAction::TurboAction(), _TurboAction()
1161 |* Ersterstellung MA 04. Dec. 92
1162 |* Letzte Aenderung MA 15. Aug. 93
1164 |*************************************************************************/
1165 BOOL SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
1168 const SwPageFrm *pPage = 0;
1169 if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
1171 const SwRect aOldRect( pCnt->UnionFrm( TRUE ) );
1172 const long nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
1173 pCnt->Calc();
1174 if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
1175 pCnt->SetRetouche();
1177 pPage = pCnt->FindPageFrm();
1178 PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
1180 if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
1182 const ULONG nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
1183 ((SwTxtFrm*)pCnt)->RecalcAllLines();
1184 if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
1186 if ( IsPaintExtraData() )
1187 pImp->GetShell()->AddPaintRect( pCnt->Frm() );
1188 //Damit die restlichen LineNums auf der Seite bereichnet werden
1189 //und nicht hier abgebrochen wird.
1190 //Das im RecalcAllLines zu erledigen waere teuer, weil dort
1191 //auch in unnoetigen Faellen (normale Action) auch immer die
1192 //Seite benachrichtigt werden muesste.
1193 const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
1194 while ( pNxt &&
1195 (pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
1196 pNxt = pNxt->GetNextCntntFrm();
1197 if ( pNxt )
1198 pNxt->InvalidatePage();
1200 return FALSE;
1203 if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
1204 return FALSE;
1206 if ( !pPage )
1207 pPage = pCnt->FindPageFrm();
1209 // OD 2004-05-10 #i28701# - format floating screen objects at content frame.
1210 if ( pCnt->IsTxtFrm() &&
1211 !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
1212 *pPage, this ) )
1214 return FALSE;
1217 if ( pPage->IsInvalidCntnt() )
1218 return FALSE;
1219 return TRUE;
1222 BOOL SwLayAction::TurboAction()
1224 BOOL bRet = TRUE;
1226 if ( pRoot->GetTurbo() )
1228 if ( !_TurboAction( pRoot->GetTurbo() ) )
1230 CheckIdleEnd();
1231 bRet = FALSE;
1233 pRoot->ResetTurbo();
1235 else
1236 bRet = FALSE;
1237 return bRet;
1239 /*************************************************************************
1241 |* SwLayAction::IsShortCut()
1243 |* Beschreibung: Liefert ein True, wenn die Seite vollstaendig unter
1244 |* oder rechts neben dem sichbaren Bereich liegt.
1245 |* Es kann passieren, dass sich die Verhaeltnisse derart aendern, dass
1246 |* die Verarbeitung (des Aufrufers!) mit der Vorgaengerseite der
1247 |* uebergebenen Seite weitergefuehrt werden muss. Der Paramter wird also
1248 |* ggf. veraendert!
1249 |* Fuer den BrowseMode kann auch dann der ShortCut aktiviert werden,
1250 |* wenn der ungueltige Inhalt der Seite unterhalb des sichbaren
1251 |* bereiches liegt.
1252 |* Ersterstellung MA 30. Oct. 92
1253 |* Letzte Aenderung MA 18. Jul. 96
1255 |*************************************************************************/
1256 const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
1258 ASSERT( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
1260 if ( !pFrm->IsValid() || pFrm->IsCompletePaint() &&
1261 pFrm->Frm().Top() < nBottom )
1262 return pFrm;
1263 pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1264 while ( pFrm )
1266 if ( pFrm->IsLayoutFrm() )
1268 if ( !pFrm->IsValid() || pFrm->IsCompletePaint() &&
1269 pFrm->Frm().Top() < nBottom )
1270 return pFrm;
1271 const SwFrm *pTmp;
1272 if ( 0 != (pTmp = ::lcl_FindFirstInvaLay( pFrm, nBottom )) )
1273 return pTmp;
1275 pFrm = pFrm->GetNext();
1277 return 0;
1280 const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
1281 const SwCntntFrm *pFirst )
1283 const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
1284 pLay->ContainsCntnt();
1285 while ( pCnt )
1287 if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
1289 if ( pCnt->Frm().Top() <= nBottom )
1290 return pCnt;
1293 if ( pCnt->GetDrawObjs() )
1295 const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
1296 for ( USHORT i = 0; i < rObjs.Count(); ++i )
1298 const SwAnchoredObject* pObj = rObjs[i];
1299 if ( pObj->ISA(SwFlyFrm) )
1301 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
1302 if ( pFly->IsFlyInCntFrm() )
1304 if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
1305 pFly->IsCompletePaint() )
1307 if ( pFly->Frm().Top() <= nBottom )
1308 return pFly;
1310 const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
1311 if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
1312 return pFrm;
1317 if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
1318 return 0;
1319 pCnt = pCnt->GetNextCntntFrm();
1320 if ( !pLay->IsAnLower( pCnt ) )
1321 break;
1323 return 0;
1326 // --> OD 2005-02-21 #i37877# - consider drawing objects
1327 const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
1328 long _nBottom )
1330 ASSERT( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" )
1332 for ( USHORT i = 0; i < _pPage->GetSortedObjs()->Count(); ++i )
1334 const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
1335 if ( pObj->ISA(SwFlyFrm) )
1337 const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
1338 if ( pFly->Frm().Top() <= _nBottom )
1340 if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
1341 return pFly;
1343 const SwFrm* pTmp;
1344 if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
1345 pTmp->Frm().Top() <= _nBottom )
1346 return pFly;
1349 else if ( pObj->ISA(SwAnchoredDrawObject) )
1351 if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
1353 return pObj;
1357 return 0;
1359 // <--
1361 BOOL SwLayAction::IsShortCut( SwPageFrm *&prPage )
1363 BOOL bRet = FALSE;
1364 const BOOL bBrowse = pRoot->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE);
1366 //Wenn die Seite nicht Gueltig ist wird sie schnell formatiert, sonst
1367 //gibts nix als Aerger.
1368 if ( !prPage->IsValid() )
1370 if ( bBrowse )
1372 /// OD 15.10.2002 #103517# - format complete page
1373 /// Thus, loop on all lowers of the page <prPage>, instead of only
1374 /// format its first lower.
1375 /// NOTE: In online layout (bBrowse == TRUE) a page can contain
1376 /// a header frame and/or a footer frame beside the body frame.
1377 prPage->Calc();
1378 SwFrm* pPageLowerFrm = prPage->Lower();
1379 while ( pPageLowerFrm )
1381 pPageLowerFrm->Calc();
1382 pPageLowerFrm = pPageLowerFrm->GetNext();
1385 else
1386 FormatLayout( prPage );
1387 if ( IsAgain() )
1388 return FALSE;
1392 const SwRect &rVis = pImp->GetShell()->VisArea();
1393 if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
1394 (prPage->Frm().Left()>= rVis.Right()) )
1396 bRet = TRUE;
1398 //Jetzt wird es ein bischen unangenehm: Der erste CntntFrm dieser Seite
1399 //im Bodytext muss Formatiert werden, wenn er dabei die Seite
1400 //wechselt, muss ich nochmal eine Seite zuvor anfangen, denn
1401 //es wurde ein PageBreak verarbeitet.
1402 //Noch unangenehmer: Der naechste CntntFrm ueberhaupt muss
1403 //Formatiert werden, denn es kann passieren, dass kurzfristig
1404 //leere Seiten existieren (Bsp. Absatz ueber mehrere Seiten
1405 //wird geloescht oder verkleinert).
1407 //Ist fuer den Browser uninteressant, wenn der letzte Cnt davor bereits
1408 //nicht mehr sichbar ist.
1410 const SwPageFrm *p2ndPage = prPage;
1411 const SwCntntFrm *pCntnt;
1412 const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
1413 if( p2ndPage->IsFtnPage() && pBody )
1414 pBody = (SwLayoutFrm*)pBody->GetNext();
1415 pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1416 while ( p2ndPage && !pCntnt )
1418 p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
1419 if( p2ndPage )
1421 pBody = p2ndPage->FindBodyCont();
1422 if( p2ndPage->IsFtnPage() && pBody )
1423 pBody = (SwLayoutFrm*)pBody->GetNext();
1424 pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1427 if ( pCntnt )
1429 BOOL bTstCnt = TRUE;
1430 if ( bBrowse )
1432 //Der Cnt davor schon nicht mehr sichtbar?
1433 const SwFrm *pLst = pCntnt;
1434 if ( pLst->IsInTab() )
1435 pLst = pCntnt->FindTabFrm();
1436 if ( pLst->IsInSct() )
1437 pLst = pCntnt->FindSctFrm();
1438 pLst = pLst->FindPrev();
1439 if ( pLst &&
1440 (pLst->Frm().Top() >= rVis.Bottom() ||
1441 pLst->Frm().Left()>= rVis.Right()) )
1443 bTstCnt = FALSE;
1447 if ( bTstCnt )
1449 // --> OD 2004-06-04 #i27756# - check after each frame calculation,
1450 // if the content frame has changed the page. If yes, no other
1451 // frame calculation is performed
1452 bool bPageChg = false;
1454 if ( pCntnt->IsInSct() )
1456 const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1457 if ( !pSct->IsValid() )
1459 pSct->Calc();
1460 pSct->SetCompletePaint();
1461 if ( IsAgain() )
1462 return FALSE;
1463 // --> OD 2004-06-04 #i27756#
1464 bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1465 prPage->GetPrev();
1469 if ( !bPageChg && !pCntnt->IsValid() )
1471 pCntnt->Calc();
1472 pCntnt->SetCompletePaint();
1473 if ( IsAgain() )
1474 return FALSE;
1475 // --> OD 2004-06-04 #i27756#
1476 bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1477 prPage->GetPrev();
1480 if ( !bPageChg && pCntnt->IsInTab() )
1482 const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
1483 if ( !pTab->IsValid() )
1485 pTab->Calc();
1486 pTab->SetCompletePaint();
1487 if ( IsAgain() )
1488 return FALSE;
1489 // --> OD 2004-06-04 #i27756#
1490 bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1491 prPage->GetPrev();
1495 if ( !bPageChg && pCntnt->IsInSct() )
1497 const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1498 if ( !pSct->IsValid() )
1500 pSct->Calc();
1501 pSct->SetCompletePaint();
1502 if ( IsAgain() )
1503 return FALSE;
1504 // --> OD 2004-06-04 #i27756#
1505 bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1506 prPage->GetPrev();
1510 // --> OD 2004-06-04 #i27756#
1511 if ( bPageChg )
1513 bRet = FALSE;
1514 const SwPageFrm* pTmp = pCntnt->FindPageFrm();
1515 if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
1516 pTmp->IsInvalid() )
1518 prPage = (SwPageFrm*)pTmp;
1520 else
1522 prPage = (SwPageFrm*)prPage->GetPrev();
1525 // --> OD 2005-04-25 #121980# - no shortcut, if at previous page
1526 // an anchored object is registered, whose anchor is <pCntnt>.
1527 else if ( prPage->GetPrev() &&
1528 static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
1530 SwSortedObjs* pObjs =
1531 static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
1532 if ( pObjs )
1534 sal_uInt32 i = 0;
1535 for ( ; i < pObjs->Count(); ++i )
1537 SwAnchoredObject* pObj = (*pObjs)[i];
1538 if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
1540 bRet = FALSE;
1541 break;
1546 // <--
1551 if ( !bRet && bBrowse )
1553 const long nBottom = rVis.Bottom();
1554 const SwAnchoredObject* pObj( 0L );
1555 if ( prPage->GetSortedObjs() &&
1556 (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
1557 0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
1558 pObj->GetObjRect().Top() <= nBottom )
1560 return FALSE;
1562 const SwFrm* pFrm( 0L );
1563 if ( prPage->IsInvalidLayout() &&
1564 0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
1565 pFrm->Frm().Top() <= nBottom )
1567 return FALSE;
1569 if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
1570 0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
1571 pFrm->Frm().Top() <= nBottom )
1573 return FALSE;
1575 bRet = TRUE;
1577 return bRet;
1580 /*************************************************************************
1582 |* SwLayAction::FormatLayout(), FormatLayoutFly, FormatLayoutTab()
1584 |* Ersterstellung MA 30. Oct. 92
1585 |* Letzte Aenderung MA 18. May. 98
1587 |*************************************************************************/
1588 // OD 15.11.2002 #105155# - introduce support for vertical layout
1589 BOOL SwLayAction::FormatLayout( SwLayoutFrm *pLay, BOOL bAddRect )
1591 ASSERT( !IsAgain(), "Ungueltige Seite beachten." );
1592 if ( IsAgain() )
1593 return FALSE;
1595 BOOL bChanged = FALSE;
1596 BOOL bAlreadyPainted = FALSE;
1597 // OD 11.11.2002 #104414# - remember frame at complete paint
1598 SwRect aFrmAtCompletePaint;
1600 if ( !pLay->IsValid() || pLay->IsCompletePaint() )
1602 if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
1603 pLay->GetPrev()->SetCompletePaint();
1605 SwRect aOldRect( pLay->Frm() );
1606 pLay->Calc();
1607 if ( aOldRect != pLay->Frm() )
1608 bChanged = TRUE;
1610 BOOL bNoPaint = FALSE;
1611 if ( pLay->IsPageBodyFrm() &&
1612 pLay->Frm().Pos() == aOldRect.Pos() &&
1613 pLay->Lower() &&
1614 pLay->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
1616 //HotFix: Vobis Homepage, nicht so genau hinsehen, sonst
1617 //rpaints
1619 //Einschraenkungen wegen Kopf-/Fusszeilen
1620 if ( !( pLay->IsCompletePaint() &&
1621 pLay->FindPageFrm()->FindFtnCont() ) )
1623 bNoPaint = TRUE;
1627 if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
1629 SwRect aPaint( pLay->Frm() );
1630 // OD 13.02.2003 #i9719#, #105645# - consider border and shadow for
1631 // page frames -> enlarge paint rectangle correspondingly.
1632 if ( pLay->IsPageFrm() )
1634 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
1635 const int nBorderWidth =
1636 pImp->GetShell()->GetOut()->PixelToLogic( Size( pPageFrm->BorderPxWidth(), 0 ) ).Width();
1637 const int nShadowWidth =
1638 pImp->GetShell()->GetOut()->PixelToLogic( Size( pPageFrm->ShadowPxWidth(), 0 ) ).Width();
1640 //mod #i6193# added sidebar width
1641 const SwPostItMgr* pPostItMgr = pImp->GetShell()->GetPostItMgr();
1642 const int nSidebarWidth = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0;
1643 if (pPageFrm->MarginSide())
1645 aPaint.Left( aPaint.Left() - nBorderWidth - nSidebarWidth);
1646 aPaint.Right( aPaint.Right() + nBorderWidth + nShadowWidth);
1648 else
1650 aPaint.Left( aPaint.Left() - nBorderWidth );
1651 aPaint.Right( aPaint.Right() + nBorderWidth + nShadowWidth + nSidebarWidth);
1653 aPaint.Top( aPaint.Top() - nBorderWidth );
1654 aPaint.Bottom( aPaint.Bottom() + nBorderWidth + nShadowWidth);
1657 if ( pLay->IsPageFrm() &&
1658 pLay->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE) )
1660 // NOTE: no vertical layout in online layout
1661 //Ist die Aenderung ueberhaupt sichtbar?
1662 if ( pLay->IsCompletePaint() )
1664 pImp->GetShell()->AddPaintRect( aPaint );
1665 bAddRect = FALSE;
1667 else
1669 USHORT i;
1671 SwRegionRects aRegion( aOldRect );
1672 aRegion -= aPaint;
1673 for ( i = 0; i < aRegion.Count(); ++i )
1674 pImp->GetShell()->AddPaintRect( aRegion[i] );
1675 aRegion.ChangeOrigin( aPaint );
1676 aRegion.Remove( 0, aRegion.Count() );
1677 aRegion.Insert( aPaint, 0 );
1678 aRegion -= aOldRect;
1679 for ( i = 0; i < aRegion.Count(); ++i )
1680 pImp->GetShell()->AddPaintRect( aRegion[i] );
1684 else
1686 pImp->GetShell()->AddPaintRect( aPaint );
1687 bAlreadyPainted = TRUE;
1688 // OD 11.11.2002 #104414# - remember frame at complete paint
1689 aFrmAtCompletePaint = pLay->Frm();
1692 // OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
1693 // between pages (not only for in online mode).
1694 if ( pLay->IsPageFrm() )
1696 const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
1697 const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
1698 const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
1699 const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
1701 if ( bPrev )
1703 // top
1704 SwRect aSpaceToPrevPage( pLay->Frm() );
1705 const SwTwips nTop = aSpaceToPrevPage.Top() - nHalfDocBorder;
1706 if ( nTop >= 0 )
1707 aSpaceToPrevPage.Top( nTop );
1708 aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
1709 pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1711 // left
1712 aSpaceToPrevPage = pLay->Frm();
1713 const SwTwips nLeft = aSpaceToPrevPage.Left() - nHalfDocBorder;
1714 if ( nLeft >= 0 )
1715 aSpaceToPrevPage.Left( nLeft );
1716 aSpaceToPrevPage.Right( pLay->Frm().Left() );
1717 pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1719 if ( bNext )
1721 // bottom
1722 SwRect aSpaceToNextPage( pLay->Frm() );
1723 aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
1724 aSpaceToNextPage.Top( pLay->Frm().Bottom() );
1725 pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1727 // right
1728 aSpaceToNextPage = pLay->Frm();
1729 aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
1730 aSpaceToNextPage.Left( pLay->Frm().Right() );
1731 pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1735 pLay->ResetCompletePaint();
1738 if ( IsPaint() && bAddRect &&
1739 !pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
1741 // OD 15.11.2002 #105155# - vertical layout support
1742 SWRECTFN( pLay );
1743 SwRect aRect( pLay->GetUpper()->PaintArea() );
1744 (aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
1745 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1746 pLay->ResetRetouche();
1749 if( bAlreadyPainted )
1750 bAddRect = FALSE;
1752 CheckWaitCrsr();
1754 if ( IsAgain() )
1755 return FALSE;
1757 //Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
1759 if ( pLay->IsFtnFrm() ) //Hat keine LayFrms als Lower.
1760 return bChanged;
1762 SwFrm *pLow = pLay->Lower();
1763 BOOL bTabChanged = FALSE;
1764 while ( pLow && pLow->GetUpper() == pLay )
1766 if ( pLow->IsLayoutFrm() )
1768 if ( pLow->IsTabFrm() )
1769 bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1770 // bereits zum Loeschen angemeldete Ueberspringen
1771 else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
1772 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1774 else if ( pImp->GetShell()->IsPaintLocked() )
1775 //Abkuerzung im die Zyklen zu minimieren, bei Lock kommt das
1776 //Paint sowieso (Primaer fuer Browse)
1777 pLow->OptCalc();
1779 if ( IsAgain() )
1780 return FALSE;
1781 pLow = pLow->GetNext();
1783 // OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
1784 // area has been already added and after formating its lowers the frame area
1785 // is enlarged.
1786 if ( bAlreadyPainted &&
1787 ( pLay->Frm().Width() > aFrmAtCompletePaint.Width() ||
1788 pLay->Frm().Height() > aFrmAtCompletePaint.Height() )
1791 pImp->GetShell()->AddPaintRect( pLay->Frm() );
1793 return bChanged || bTabChanged;
1796 BOOL SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
1798 ASSERT( !IsAgain(), "Ungueltige Seite beachten." );
1799 if ( IsAgain() )
1800 return FALSE;
1802 BOOL bChanged = false;
1803 BOOL bAddRect = true;
1805 if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
1807 //Der Frame hat sich veraendert, er wird jetzt Formatiert
1808 const SwRect aOldRect( pFly->Frm() );
1809 pFly->Calc();
1810 bChanged = aOldRect != pFly->Frm();
1812 if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
1813 pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
1814 pImp->GetShell()->AddPaintRect( pFly->Frm() );
1816 if ( bChanged )
1817 pFly->Invalidate();
1818 else
1819 pFly->Validate();
1820 bAddRect = false;
1821 pFly->ResetCompletePaint();
1824 if ( IsAgain() )
1825 return FALSE;
1827 //Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
1828 BOOL bTabChanged = false;
1829 SwFrm *pLow = pFly->Lower();
1830 while ( pLow )
1832 if ( pLow->IsLayoutFrm() )
1834 if ( pLow->IsTabFrm() )
1835 bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1836 else
1837 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1839 pLow = pLow->GetNext();
1841 return bChanged || bTabChanged;
1844 BOOL MA_FASTCALL lcl_AreLowersScrollable( const SwLayoutFrm *pLay )
1846 const SwFrm *pLow = pLay->Lower();
1847 while ( pLow )
1849 if ( pLow->IsCompletePaint() || !pLow->IsValid() || pLow->IsCoveredCell() )
1850 return FALSE;
1851 if ( pLow->IsLayoutFrm() && !::lcl_AreLowersScrollable( (SwLayoutFrm*)pLow ))
1852 return FALSE;
1853 pLow = pLow->GetNext();
1855 return TRUE;
1858 SwLayoutFrm * MA_FASTCALL lcl_IsTabScrollable( SwTabFrm *pTab )
1860 //returnt die erste unveraenderte Zeile, oder 0 wenn nicht
1861 //gescrollt werden darf.
1862 if ( !pTab->IsCompletePaint() )
1864 SwLayoutFrm *pUnchgdRow = 0;
1865 SwLayoutFrm *pRow = (SwLayoutFrm*)pTab->Lower();
1866 while ( pRow )
1868 if ( ::lcl_AreLowersScrollable( pRow ) )
1870 if ( !pUnchgdRow )
1871 pUnchgdRow = pRow;
1873 else
1875 pUnchgdRow = 0;
1878 pRow = (SwLayoutFrm*)pRow->GetNext();
1880 return pUnchgdRow;
1882 return 0;
1885 // OD 2004-05-11 #i28701#
1886 void lcl_ValidateLowerObjs( SwFrm* pFrm,
1887 const SwTwips nOfst,
1888 SwPageFrm *pPage,
1889 bool bResetOnly );
1891 // OD 2004-05-11 #i28701# - correction: floating screen objects, which are
1892 // anchored at-fly, have also been to be considered.
1893 void MA_FASTCALL lcl_ValidateLowers( SwLayoutFrm *pLay, const SwTwips nOfst,
1894 SwLayoutFrm *pRow, SwPageFrm *pPage,
1895 BOOL bResetOnly )
1897 pLay->ResetCompletePaint();
1899 // OD 2004-05-11 #i28701# - consider floating screen objects, which are
1900 // anchored at-fly.
1901 if ( pLay->IsFlyFrm() )
1903 ::lcl_ValidateLowerObjs( pLay, nOfst, pPage, bResetOnly );
1906 SwFrm *pLow = pRow ? pRow : pLay->Lower();
1907 SwRootFrm *pRootFrm = 0;
1909 while ( pLow )
1911 if ( !bResetOnly )
1913 SwRect aOldFrm( pLow->Frm() );
1914 pLow->Frm().Pos().Y() += nOfst;
1915 if( pLow->IsAccessibleFrm() )
1917 if( !pRootFrm )
1918 pRootFrm = pPage->FindRootFrm();
1919 if( pRootFrm && pRootFrm->IsAnyShellAccessible() &&
1920 pRootFrm->GetCurrShell() )
1922 pRootFrm->GetCurrShell()->Imp()->MoveAccessibleFrm( pLow, aOldFrm );
1926 if ( pLow->IsLayoutFrm() )
1928 ::lcl_ValidateLowers( (SwLayoutFrm*)pLow, nOfst, 0, pPage, bResetOnly);
1930 else
1932 pLow->ResetCompletePaint();
1933 // OD 2004-05-11 #i28701# - use new local helper method
1934 // <lcl_ValidateLowerObjs(..)>
1935 ::lcl_ValidateLowerObjs( pLow, nOfst, pPage, bResetOnly);
1937 if ( !bResetOnly )
1938 pLow->Calc(); //#55435# Stabil halten.
1939 pLow = pLow->GetNext();
1943 // OD 2004-05-11 #i28701# - helper method for <lcl_ValidateLowers(..)> to
1944 // 'ValidateLowers' for floating screen objects
1945 void lcl_ValidateLowerObjs( SwFrm* pFrm,
1946 const SwTwips nOfst,
1947 SwPageFrm *pPage,
1948 bool bResetOnly )
1950 if ( pFrm->GetDrawObjs() )
1952 // --> OD 2004-10-15 #i26945# - consider layout direction
1953 SWRECTFN( pFrm )
1954 // <--
1955 for ( USHORT i = 0; i < pFrm->GetDrawObjs()->Count(); ++i )
1957 SwAnchoredObject* pAnchoredObj = (*pFrm->GetDrawObjs())[i];
1958 // --> OD 2004-10-08 #i26945# - check, if the anchor frame, which
1959 // contains the anchor position, is the given frame
1960 if ( pAnchoredObj->GetAnchorFrmContainingAnchPos() != pFrm )
1962 continue;
1964 if ( pAnchoredObj->ISA(SwFlyFrm) )
1966 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
1967 if ( !bResetOnly )
1969 // --> OD 2004-10-15 #i26945#
1970 // - consider layout direction
1971 // - consider condition for direct move
1972 const bool bNoDirectMove =
1973 WEIT_WECH == pFly->Frm().Top() ||
1974 pFly->ConsiderObjWrapInfluenceOnObjPos();
1975 if ( !bNoDirectMove )
1977 (pFly->Frm().*fnRect->fnSubTop)( -nOfst );
1978 (pFly->Frm().*fnRect->fnAddBottom)( nOfst );
1980 // <--
1981 pFly->GetVirtDrawObj()->SetRectsDirty();
1982 // --> OD 2004-08-17 - also notify view of <SdrObject>
1983 // instance, which represents the Writer fly frame in the
1984 // drawing layer
1985 pFly->GetVirtDrawObj()->SetChanged();
1986 // <--
1987 if ( pFly->IsFlyInCntFrm() )
1988 ((SwFlyInCntFrm*)pFly)->AddRefOfst( nOfst );
1989 // --> OD 2004-10-15 #i26945# - consider at-character
1990 // anchored Writer fly frames
1991 else if( pFly->IsAutoPos() )
1993 pFly->AddLastCharY( nOfst );
1994 // OD 2004-05-18 #i28701# - follow-up of #i22341#
1995 // <mnLastTopOfLine> has also been adjusted.
1996 pFly->AddLastTopOfLineY( nOfst );
1998 // <--
2000 ::lcl_ValidateLowers( pFly, nOfst, 0, pPage, bResetOnly);
2002 // --> OD 2004-10-15 #i26945# - consider drawing objects
2003 else
2005 if ( !bResetOnly )
2007 pAnchoredObj->AddLastCharY( nOfst );
2008 pAnchoredObj->AddLastTopOfLineY( nOfst );
2011 // <--
2012 pAnchoredObj->InvalidateObjPos();
2017 void MA_FASTCALL lcl_AddScrollRectTab( SwTabFrm *pTab, SwLayoutFrm *pRow,
2018 const SwRect &rRect,
2019 const SwTwips nOfst)
2021 // --> OD 2007-11-27 #notes2#
2022 // if sidebar for notes is present, no scrolling is allowed
2023 const SwPageFrm* pPage = pTab->FindPageFrm();
2024 ASSERT( pPage, "<lcl_AddScrollRectTab(..)> - no page frame found at table frame -> crash" );
2025 ViewShell* pSh = pPage->GetShell();
2026 if ( pSh )
2028 const SwPostItMgr* pPostItMgr = pSh->GetPostItMgr();
2029 if ( pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() )
2031 return;
2034 // <--
2035 //Wenn altes oder neues Rechteck mit einem Fly ueberlappen, in dem der
2036 //Frm nicht selbst steht, so ist nichts mit Scrollen.
2037 SwRect aRect( rRect );
2038 // OD 04.11.2002 #104100# - <SWRECTFN( pTab )> not needed.
2039 if( pTab->IsVertical() )
2040 aRect.Pos().X() -= nOfst;
2041 else
2042 aRect.Pos().Y() += nOfst;
2043 if ( pPage->GetSortedObjs() )
2045 if ( ::lcl_IsOverObj( pTab, pPage, rRect, aRect, pTab ) )
2046 return;
2048 if ( pPage->GetFmt()->GetBackground().GetGraphicPos() != GPOS_NONE )
2049 return;
2051 if ( pSh )
2052 pSh->AddScrollRect( pTab, aRect, nOfst );
2053 ::lcl_ValidateLowers( pTab, nOfst, pRow, pTab->FindPageFrm(),
2054 pTab->IsLowersFormatted() );
2057 // OD 31.10.2002 #104100#
2058 // NOTE: no adjustments for vertical layout support necessary
2059 BOOL CheckPos( SwFrm *pFrm )
2061 if ( !pFrm->GetValidPosFlag() )
2063 Point aOld( pFrm->Frm().Pos() );
2064 pFrm->MakePos();
2065 if ( aOld != pFrm->Frm().Pos() )
2067 pFrm->Frm().Pos( aOld );
2068 pFrm->_InvalidatePos();
2069 return FALSE;
2072 return TRUE;
2075 // OD 31.10.2002 #104100#
2076 // Implement vertical layout support
2077 BOOL SwLayAction::FormatLayoutTab( SwTabFrm *pTab, BOOL bAddRect )
2079 ASSERT( !IsAgain(), "8-) Ungueltige Seite beachten." );
2080 if ( IsAgain() || !pTab->Lower() )
2081 return FALSE;
2083 IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
2084 pTimerAccess->BlockIdling();
2086 BOOL bChanged = FALSE;
2087 BOOL bPainted = FALSE;
2089 const SwPageFrm *pOldPage = pTab->FindPageFrm();
2091 // OD 31.10.2002 #104100# - vertical layout support
2092 // use macro to declare and init <sal_Bool bVert>, <sal_Bool bRev> and
2093 // <SwRectFn fnRect> for table frame <pTab>.
2094 SWRECTFN( pTab );
2096 if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
2098 if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
2099 pTab->GetPrev()->SetCompletePaint();
2101 //Potenzielles Scrollrect ist die ganze Tabelle. Da bereits ein
2102 //Wachstum innerhalb der Tabelle - und damit der Tabelle selbst -
2103 //stattgefunden haben kann, muss die untere Kante durch die
2104 //Unterkante der letzten Zeile bestimmt werden.
2105 SwLayoutFrm* pRow = 0L;
2106 SwRect aScrollRect( pTab->PaintArea() );
2107 // --> OD 2004-07-01 #i28701# - check, if scrolling is allowed.
2108 if ( mbScrollingAllowed &&
2109 ( IsPaint() || bAddRect ) )
2111 pRow = static_cast<SwLayoutFrm*>(pTab->GetLastLower());
2112 // OD 31.10.2002 #104100# - vertical layout support
2113 (aScrollRect.*fnRect->fnSetBottom)( (pRow->Frm().*fnRect->fnGetBottom)() );
2114 //Die Oberkante wird ggf. durch die erste unveraenderte Zeile bestimmt.
2115 pRow = ::lcl_IsTabScrollable( pTab );
2116 if ( pRow && pRow != pTab->Lower() )
2117 // OD 31.10.2002 #104100# - vertical layout support
2118 (aScrollRect.*fnRect->fnSetTop)( (pRow->Frm().*fnRect->fnGetTop)() );
2121 const SwFrm *pOldUp = pTab->GetUpper();
2123 SwRect aOldRect( pTab->Frm() );
2124 pTab->SetLowersFormatted( FALSE );
2125 pTab->Calc();
2126 if ( aOldRect != pTab->Frm() )
2127 bChanged = TRUE;
2128 SwRect aPaintFrm = pTab->PaintArea();
2130 if ( IsPaint() && bAddRect )
2132 // --> OD 2004-07-01 #i28701# - check, if scrolling is allowed
2133 if ( mbScrollingAllowed &&
2134 pRow && pOldUp == pTab->GetUpper() &&
2135 pTab->Frm().SSize() == aOldRect.SSize() &&
2136 // OD 31.10.2002 #104100# - vertical layout support
2137 (pTab->Frm().*fnRect->fnGetLeft)() == (aOldRect.*fnRect->fnGetLeft)() &&
2138 pTab->IsAnLower( pRow ) )
2140 SwTwips nOfst;
2141 if ( pRow->GetPrev() )
2143 if ( pRow->GetPrev()->IsValid() ||
2144 ::CheckPos( pRow->GetPrev() ) )
2146 // OD 31.10.2002 #104100# - vertical layout support
2147 nOfst = -(pRow->Frm().*fnRect->fnTopDist)( (pRow->GetPrev()->Frm().*fnRect->fnGetBottom)() );
2149 else
2150 nOfst = 0;
2152 else
2153 // OD 31.10.2002 #104100# - vertical layout support
2154 nOfst = (pTab->Frm().*fnRect->fnTopDist)( (aOldRect.*fnRect->fnGetTop)() );
2156 if ( nOfst )
2158 ::lcl_AddScrollRectTab( pTab, pRow, aScrollRect, nOfst );
2159 bPainted = TRUE;
2163 // OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
2164 if ( !pTab->IsCompletePaint() && pTab->IsComplete() &&
2165 ( pTab->Frm().SSize() != pTab->Prt().SSize() ||
2166 // OD 31.10.2002 #104100# - vertical layout support
2167 (pTab->*fnRect->fnGetLeftMargin)()
2168 ) &&
2169 pTab->Frm().HasArea()
2172 // OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
2173 SwRect aMarginRect;
2175 SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
2176 if ( nLeftMargin > 0)
2178 aMarginRect = pTab->Frm();
2179 (aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
2180 pImp->GetShell()->AddPaintRect( aMarginRect );
2183 if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
2185 aMarginRect = pTab->Frm();
2186 (aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
2187 pImp->GetShell()->AddPaintRect( aMarginRect );
2190 SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
2191 if ( nTopMargin > 0)
2193 aMarginRect = pTab->Frm();
2194 (aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
2195 pImp->GetShell()->AddPaintRect( aMarginRect );
2198 if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
2200 aMarginRect = pTab->Frm();
2201 (aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
2202 pImp->GetShell()->AddPaintRect( aMarginRect );
2205 else if ( pTab->IsCompletePaint() )
2207 pImp->GetShell()->AddPaintRect( aPaintFrm );
2208 bAddRect = FALSE;
2209 bPainted = TRUE;
2212 if ( pTab->IsRetouche() && !pTab->GetNext() )
2214 SwRect aRect( pTab->GetUpper()->PaintArea() );
2215 // OD 04.11.2002 #104100# - vertical layout support
2216 (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
2217 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
2218 pTab->ResetRetouche();
2221 else
2222 bAddRect = FALSE;
2224 if ( pTab->IsCompletePaint() && !pOptTab )
2225 pOptTab = pTab;
2226 pTab->ResetCompletePaint();
2228 if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
2230 // OD 04.10.2002 #102779#
2231 // set correct rectangle for retouche: area between bottom of table frame
2232 // and bottom of paint area of the upper frame.
2233 SwRect aRect( pTab->GetUpper()->PaintArea() );
2234 // OD 04.11.2002 #104100# - vertical layout support
2235 (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
2236 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
2237 pTab->ResetRetouche();
2240 CheckWaitCrsr();
2242 pTimerAccess->UnblockIdling();
2244 //Heftige Abkuerzung!
2245 if ( pTab->IsLowersFormatted() &&
2246 (bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
2247 return FALSE;
2249 //Jetzt noch die Lowers versorgen
2250 if ( IsAgain() )
2251 return FALSE;
2253 // OD 20.10.2003 #112464# - for savety reasons:
2254 // check page number before formatting lowers.
2255 if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
2256 SetNextCycle( TRUE );
2258 // OD 20.10.2003 #112464# - format lowers, only if table frame is valid
2259 if ( pTab->IsValid() )
2261 SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
2262 while ( pLow )
2264 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
2265 if ( IsAgain() )
2266 return FALSE;
2267 pLow = (SwLayoutFrm*)pLow->GetNext();
2271 return bChanged;
2274 /*************************************************************************
2276 |* SwLayAction::FormatCntnt()
2278 |* Ersterstellung MA 30. Oct. 92
2279 |* Letzte Aenderung MA 16. Nov. 95
2281 |*************************************************************************/
2282 BOOL SwLayAction::FormatCntnt( const SwPageFrm *pPage )
2284 const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
2285 const BOOL bBrowse = pRoot->GetFmt()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::BROWSE_MODE);
2287 while ( pCntnt && pPage->IsAnLower( pCntnt ) )
2289 //Wenn der Cntnt sich eh nicht veraendert koennen wir ein paar
2290 //Abkuerzungen nutzen.
2291 const BOOL bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
2292 pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
2293 if ( bFull )
2295 //Damit wir nacher nicht suchen muessen.
2296 const BOOL bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
2297 const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
2298 const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
2300 const SwLayoutFrm*pOldUpper = pCntnt->GetUpper();
2301 const SwTabFrm *pTab = pCntnt->FindTabFrm();
2302 const BOOL bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
2303 const BOOL bOldPaint = IsPaint();
2304 bPaint = bOldPaint && !(pTab && pTab == pOptTab);
2305 _FormatCntnt( pCntnt, pPage );
2306 // --> OD 2004-11-05 #i26945# - reset <bPaint> before format objects
2307 bPaint = bOldPaint;
2308 // <--
2310 // OD 2004-05-10 #i28701# - format floating screen object at content frame.
2311 // No format, if action flag <bAgain> is set or action is interrupted.
2312 // OD 2004-08-30 #117736# - allow format on interruption of action, if
2313 // it's the format for this interrupt
2314 // --> OD 2004-11-01 #i23129#, #i36347# - pass correct page frame
2315 // to the object formatter.
2316 if ( !IsAgain() &&
2317 ( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
2318 pCntnt->IsTxtFrm() &&
2319 !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
2320 *(pCntnt->FindPageFrm()), this ) )
2321 // <--
2323 return FALSE;
2326 if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
2328 const ULONG nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
2329 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
2330 if ( IsPaintExtraData() && IsPaint() &&
2331 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
2332 pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
2335 if ( IsAgain() )
2336 return FALSE;
2338 //Wenn Layout oder Flys wieder Invalid sind breche ich die Verarbeitung
2339 //vorlaeufig ab - allerdings nicht fuer die BrowseView, denn dort wird
2340 //das Layout staendig ungueltig, weil die Seitenhoehe angepasst wird.
2341 //Desgleichen wenn der Benutzer weiterarbeiten will und mindestens ein
2342 //Absatz verarbeitet wurde.
2343 if ( (!pTab || (pTab && !bInValid)) )
2345 CheckIdleEnd();
2346 // OD 14.04.2003 #106346# - consider interrupt formatting.
2347 if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
2348 ( !bBrowse && pPage->IsInvalidLayout() ) ||
2349 // OD 07.05.2003 #109435# - consider interrupt formatting
2350 ( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
2352 return FALSE;
2354 if ( pOldUpper != pCntnt->GetUpper() )
2356 const USHORT nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
2357 if ( nCurNum < pPage->GetPhyPageNum() )
2358 nPreInvaPage = nCurNum;
2360 //Wenn der Frm mehr als eine Seite rueckwaerts geflossen ist, so
2361 //fangen wir nocheinmal von vorn an damit wir nichts auslassen.
2362 if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
2364 SetNextCycle( TRUE );
2365 // OD 07.05.2003 #109435# - consider interrupt formatting
2366 if ( !mbFormatCntntOnInterrupt )
2368 return FALSE;
2372 //Wenn der Frame die Seite vorwaerts gewechselt hat, so lassen wir
2373 //den Vorgaenger nocheinmal durchlaufen.
2374 //So werden einerseits Vorgaenger erwischt, die jetzt f?r Retouche
2375 //verantwortlich sind, andererseits werden die Fusszeilen
2376 //auch angefasst.
2377 BOOL bSetCntnt = TRUE;
2378 if ( pCntntPrev )
2380 if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
2381 pPage->InvalidateCntnt();
2382 if ( pOldUpper != pCntnt->GetUpper() &&
2383 pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
2385 pCntnt = pCntntPrev;
2386 bSetCntnt = FALSE;
2389 if ( bSetCntnt )
2391 if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
2392 pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
2394 const long nBottom = pImp->GetShell()->VisArea().Bottom();
2395 const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
2396 nBottom, pCntnt );
2397 if ( !pTmp )
2399 if ( (!(IS_FLYS && IS_INVAFLY) ||
2400 !lcl_FindFirstInvaObj( pPage, nBottom )) &&
2401 (!pPage->IsInvalidLayout() ||
2402 !lcl_FindFirstInvaLay( pPage, nBottom )))
2403 SetBrowseActionStop( TRUE );
2404 // OD 14.04.2003 #106346# - consider interrupt formatting.
2405 if ( !mbFormatCntntOnInterrupt )
2407 return FALSE;
2411 pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
2414 RESCHEDULE;
2416 else
2418 if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
2420 const ULONG nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
2421 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
2422 if ( IsPaintExtraData() && IsPaint() &&
2423 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
2424 pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
2427 //Falls der Frm schon vor der Abarbeitung hier formatiert wurde.
2428 if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
2429 IsPaint() )
2430 PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
2431 if ( IsIdle() )
2433 CheckIdleEnd();
2434 // OD 14.04.2003 #106346# - consider interrupt formatting.
2435 if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
2436 return FALSE;
2438 if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
2439 pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
2441 const long nBottom = pImp->GetShell()->VisArea().Bottom();
2442 const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
2443 nBottom, pCntnt );
2444 if ( !pTmp )
2446 if ( (!(IS_FLYS && IS_INVAFLY) ||
2447 !lcl_FindFirstInvaObj( pPage, nBottom )) &&
2448 (!pPage->IsInvalidLayout() ||
2449 !lcl_FindFirstInvaLay( pPage, nBottom )))
2450 SetBrowseActionStop( TRUE );
2451 // OD 14.04.2003 #106346# - consider interrupt formatting.
2452 if ( !mbFormatCntntOnInterrupt )
2454 return FALSE;
2458 pCntnt = pCntnt->GetNextCntntFrm();
2461 CheckWaitCrsr();
2462 // OD 14.04.2003 #106346# - consider interrupt formatting.
2463 return !IsInterrupt() || mbFormatCntntOnInterrupt;
2465 /*************************************************************************
2467 |* SwLayAction::_FormatCntnt()
2469 |* Beschreibung Returnt TRUE wenn der Absatz verarbeitet wurde,
2470 |* FALSE wenn es nichts zu verarbeiten gab.
2471 |* Ersterstellung MA 07. Dec. 92
2472 |* Letzte Aenderung MA 11. Mar. 98
2474 |*************************************************************************/
2475 void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
2476 const SwPageFrm *pPage )
2478 //wird sind hier evtl. nur angekommen, weil der Cntnt DrawObjekte haelt.
2479 const BOOL bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
2480 !pCntnt->IsRetouche();
2481 SWRECTFN( pCntnt )
2482 if ( !bDrawObjsOnly && IsPaint() )
2484 const BOOL bPosOnly = !pCntnt->GetValidPosFlag() &&
2485 !pCntnt->IsCompletePaint() &&
2486 pCntnt->GetValidSizeFlag() &&
2487 pCntnt->GetValidPrtAreaFlag() &&
2488 ( !pCntnt->IsTxtFrm() ||
2489 !((SwTxtFrm*)pCntnt)->HasAnimation() );
2490 const SwFrm *pOldUp = pCntnt->GetUpper();
2491 const SwRect aOldRect( pCntnt->UnionFrm() );
2492 const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
2493 pCntnt->OptCalc();
2494 if( IsAgain() )
2495 return;
2496 if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
2497 (aOldRect.*fnRect->fnGetBottom)() ) < 0 )
2498 pCntnt->SetRetouche();
2499 const SwRect aNewRect( pCntnt->UnionFrm() );
2500 if ( bPosOnly &&
2501 (aNewRect.*fnRect->fnGetTop)() != (aOldRect.*fnRect->fnGetTop)() &&
2502 !pCntnt->IsInTab() && !pCntnt->IsInSct() &&
2503 ( !pCntnt->GetPrev() || !pCntnt->GetPrev()->IsTabFrm() ) &&
2504 pOldUp == pCntnt->GetUpper() &&
2505 (aNewRect.*fnRect->fnGetLeft)() == (aOldRect.*fnRect->fnGetLeft)() &&
2506 aNewRect.SSize() == aOldRect.SSize()
2509 _AddScrollRect( pCntnt, pPage, (*fnRect->fnYDiff)(
2510 (pCntnt->Frm().*fnRect->fnGetTop)(),
2511 (aOldRect.*fnRect->fnGetTop)() ), nOldBottom );
2513 else
2514 PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
2516 else
2518 if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
2519 PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
2520 (pCntnt->Frm().*fnRect->fnGetBottom)() );
2521 pCntnt->OptCalc();
2525 /*************************************************************************
2527 |* SwLayAction::_FormatFlyCntnt()
2529 |* Beschreibung:
2530 |* - Returnt TRUE wenn alle Cntnts des Flys vollstaendig verarbeitet
2531 |* wurden. FALSE wenn vorzeitig unterbrochen wurde.
2532 |* Ersterstellung MA 02. Dec. 92
2533 |* Letzte Aenderung MA 24. Jun. 96
2535 |*************************************************************************/
2536 BOOL SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
2538 const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
2540 while ( pCntnt )
2542 // OD 2004-05-10 #i28701#
2543 _FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
2545 // --> OD 2004-07-23 #i28701# - format floating screen objects
2546 // at content text frame
2547 // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame
2548 // to the object formatter.
2549 if ( pCntnt->IsTxtFrm() &&
2550 !SwObjectFormatter::FormatObjsAtFrm(
2551 *(const_cast<SwCntntFrm*>(pCntnt)),
2552 *(pCntnt->FindPageFrm()), this ) )
2553 // <--
2555 // restart format with first content
2556 pCntnt = pFly->ContainsCntnt();
2557 continue;
2559 // <--
2561 if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
2563 const ULONG nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
2564 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
2565 if ( IsPaintExtraData() && IsPaint() &&
2566 nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
2567 pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
2570 if ( IsAgain() )
2571 return FALSE;
2573 //wenn eine Eingabe anliegt breche ich die Verarbeitung ab.
2574 if ( !pFly->IsFlyInCntFrm() )
2576 CheckIdleEnd();
2577 // OD 14.04.2003 #106346# - consider interrupt formatting.
2578 if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
2579 return FALSE;
2581 pCntnt = pCntnt->GetNextCntntFrm();
2583 CheckWaitCrsr();
2584 // OD 14.04.2003 #106346# - consider interrupt formatting.
2585 return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
2588 BOOL SwLayAction::IsStopPrt() const
2590 BOOL bResult = FALSE;
2592 if (pImp != NULL && pProgress != NULL)
2593 bResult = pImp->IsStopPrt();
2595 return bResult;
2598 /*************************************************************************
2600 |* SwLayAction::FormatSpelling(), _FormatSpelling()
2602 |* Ersterstellung AMA 01. Feb. 96
2603 |* Letzte Aenderung AMA 01. Feb. 96
2605 |*************************************************************************/
2606 BOOL SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
2608 ASSERT( pCnt->IsTxtFrm(), "NoTxt neighbour of Txt" );
2609 // robust against misuse by e.g. #i52542#
2610 if( !pCnt->IsTxtFrm() )
2611 return FALSE;
2613 const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
2615 bool bProcess = false;
2616 switch ( eJob )
2618 case ONLINE_SPELLING :
2619 bProcess = pTxtNode->IsWrongDirty(); break;
2620 case AUTOCOMPLETE_WORDS :
2621 bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
2622 case WORD_COUNT :
2623 bProcess = pTxtNode->IsWordCountDirty(); break;
2624 case SMART_TAGS : // SMARTTAGS
2625 bProcess = pTxtNode->IsSmartTagDirty(); break;
2628 if( bProcess )
2630 ViewShell *pSh = pImp->GetShell();
2631 if( STRING_LEN == nTxtPos )
2633 --nTxtPos;
2634 if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
2636 SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
2637 if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
2639 pCntntNode = pCrsr->GetCntntNode();
2640 nTxtPos = pCrsr->GetPoint()->nContent.GetIndex();
2645 switch ( eJob )
2647 case ONLINE_SPELLING :
2649 SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode, *pSh->GetViewOptions(), nTxtPos ) );
2650 bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
2651 if( !bPageValid )
2652 bAllValid = FALSE;
2653 if ( aRepaint.HasArea() )
2654 pImp->GetShell()->InvalidateWindows( aRepaint );
2655 if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
2656 return TRUE;
2657 break;
2659 case AUTOCOMPLETE_WORDS :
2660 ((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
2661 if ( Application::AnyInput( INPUT_ANY ) )
2662 return TRUE;
2663 break;
2664 case WORD_COUNT :
2666 const xub_StrLen nEnd = pTxtNode->GetTxt().Len();
2667 SwDocStat aStat;
2668 pTxtNode->CountWords( aStat, 0, nEnd );
2669 if ( Application::AnyInput( INPUT_ANY ) )
2670 return TRUE;
2671 break;
2673 case SMART_TAGS : // SMARTTAGS
2675 const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
2676 bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
2677 if( !bPageValid )
2678 bAllValid = FALSE;
2679 if ( aRepaint.HasArea() )
2680 pImp->GetShell()->InvalidateWindows( aRepaint );
2681 if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
2682 return TRUE;
2683 break;
2688 //Die im Absatz verankerten Flys wollen auch mitspielen.
2689 if ( pCnt->GetDrawObjs() )
2691 const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
2692 for ( USHORT i = 0; i < rObjs.Count(); ++i )
2694 SwAnchoredObject* pObj = rObjs[i];
2695 if ( pObj->ISA(SwFlyFrm) )
2697 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
2698 if ( pFly->IsFlyInCntFrm() )
2700 const SwCntntFrm *pC = pFly->ContainsCntnt();
2701 while( pC )
2703 if ( pC->IsTxtFrm() )
2705 if ( _DoIdleJob( pC, eJob ) )
2706 return TRUE;
2708 pC = pC->GetNextCntntFrm();
2714 return FALSE;
2717 BOOL SwLayIdle::DoIdleJob( IdleJobType eJob, BOOL bVisAreaOnly )
2719 //Spellchecken aller Inhalte der Seiten. Entweder nur der sichtbaren
2720 //Seiten oder eben aller.
2721 const ViewShell* pViewShell = pImp->GetShell();
2722 const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
2723 const SwDoc* pDoc = pViewShell->GetDoc();
2725 switch ( eJob )
2727 case ONLINE_SPELLING :
2728 if( !pViewOptions->IsOnlineSpell() )
2729 return FALSE;
2730 break;
2731 case AUTOCOMPLETE_WORDS :
2732 if( !pViewOptions->IsAutoCompleteWords() ||
2733 pDoc->GetAutoCompleteWords().IsLockWordLstLocked())
2734 return FALSE;
2735 break;
2736 case WORD_COUNT :
2737 if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
2738 return FALSE;
2739 break;
2740 case SMART_TAGS :
2741 if ( pDoc->GetDocShell()->IsHelpDocument() ||
2742 pDoc->isXForms() ||
2743 !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
2744 return FALSE;
2745 break;
2746 default: ASSERT( false, "Unknown idle job type" )
2749 SwPageFrm *pPage;
2750 if ( bVisAreaOnly )
2751 pPage = pImp->GetFirstVisPage();
2752 else
2753 pPage = (SwPageFrm*)pRoot->Lower();
2755 pCntntNode = NULL;
2756 nTxtPos = STRING_LEN;
2758 while ( pPage )
2760 bPageValid = TRUE;
2761 const SwCntntFrm *pCnt = pPage->ContainsCntnt();
2762 while( pCnt && pPage->IsAnLower( pCnt ) )
2764 if ( _DoIdleJob( pCnt, eJob ) )
2765 return TRUE;
2766 pCnt = pCnt->GetNextCntntFrm();
2768 if ( pPage->GetSortedObjs() )
2770 for ( USHORT i = 0; pPage->GetSortedObjs() &&
2771 i < pPage->GetSortedObjs()->Count(); ++i )
2773 const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
2774 if ( pObj->ISA(SwFlyFrm) )
2776 const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
2777 const SwCntntFrm *pC = pFly->ContainsCntnt();
2778 while( pC )
2780 if ( pC->IsTxtFrm() )
2782 if ( _DoIdleJob( pC, eJob ) )
2783 return TRUE;
2785 pC = pC->GetNextCntntFrm();
2791 if( bPageValid )
2793 switch ( eJob )
2795 case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
2796 case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
2797 case WORD_COUNT : pPage->ValidateWordCount(); break;
2798 case SMART_TAGS : pPage->ValidateSmartTags(); break; // SMARTTAGS
2802 pPage = (SwPageFrm*)pPage->GetNext();
2803 if ( pPage && bVisAreaOnly &&
2804 !pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
2805 break;
2807 return FALSE;
2811 #ifndef PRODUCT
2812 #if OSL_DEBUG_LEVEL > 1
2814 /*************************************************************************
2816 |* void SwLayIdle::SwLayIdle()
2818 |* Ersterstellung MA ??
2819 |* Letzte Aenderung MA 09. Jun. 94
2821 |*************************************************************************/
2822 void SwLayIdle::ShowIdle( ColorData eColorData )
2824 if ( !bIndicator )
2826 bIndicator = TRUE;
2827 Window *pWin = pImp->GetShell()->GetWin();
2828 if ( pWin )
2830 Rectangle aRect( 0, 0, 5, 5 );
2831 aRect = pWin->PixelToLogic( aRect );
2832 // OD 2004-04-23 #116347#
2833 pWin->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
2834 pWin->SetFillColor( eColorData );
2835 pWin->SetLineColor();
2836 pWin->DrawRect( aRect );
2837 pWin->Pop();
2841 #define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
2842 #else
2843 #define SHOW_IDLE( ColorData )
2844 #endif
2845 #else
2846 #define SHOW_IDLE( ColorData )
2847 #endif
2849 /*************************************************************************
2851 |* void SwLayIdle::SwLayIdle()
2853 |* Ersterstellung MA 30. Oct. 92
2854 |* Letzte Aenderung MA 23. May. 95
2856 |*************************************************************************/
2857 SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
2858 pRoot( pRt ),
2859 pImp( pI )
2860 #ifndef PRODUCT
2861 #if OSL_DEBUG_LEVEL > 1
2862 , bIndicator( FALSE )
2863 #endif
2864 #endif
2866 pImp->pIdleAct = this;
2868 SHOW_IDLE( COL_LIGHTRED );
2870 pImp->GetShell()->EnableSmooth( FALSE );
2872 //Zuerst den Sichtbaren Bereich Spellchecken, nur wenn dort nichts
2873 //zu tun war wird das IdleFormat angestossen.
2874 if ( !DoIdleJob( SMART_TAGS, TRUE ) &&
2875 !DoIdleJob( ONLINE_SPELLING, TRUE ) &&
2876 !DoIdleJob( AUTOCOMPLETE_WORDS, TRUE ) ) // SMARTTAGS
2878 //Formatieren und ggf. Repaint-Rechtecke an der ViewShell vormerken.
2879 //Dabei muessen kuenstliche Actions laufen, damit es z.B. bei
2880 //Veraenderungen der Seitenzahl nicht zu unerwuenschten Effekten kommt.
2881 //Wir merken uns bei welchen Shells der Cursor sichtbar ist, damit
2882 //wir ihn bei Dokumentaenderung ggf. wieder sichbar machen koennen.
2883 SvBools aBools;
2884 ViewShell *pSh = pImp->GetShell();
2886 { ++pSh->nStartAction;
2887 BOOL bVis = FALSE;
2888 if ( pSh->ISA(SwCrsrShell) )
2890 #ifdef SW_CRSR_TIMER
2891 ((SwCrsrShell*)pSh)->ChgCrsrTimerFlag( FALSE );
2892 #endif
2893 bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
2895 aBools.Insert( bVis, aBools.Count() );
2896 pSh = (ViewShell*)pSh->GetNext();
2897 } while ( pSh != pImp->GetShell() );
2899 SwLayAction aAction( pRoot, pImp );
2900 aAction.SetInputType( INPUT_ANY );
2901 aAction.SetIdle( TRUE );
2902 aAction.SetWaitAllowed( FALSE );
2903 aAction.Action();
2905 //Weitere Start-/EndActions nur auf wenn irgendwo Paints aufgelaufen
2906 //sind oder wenn sich die Sichtbarkeit des CharRects veraendert hat.
2907 BOOL bActions = FALSE;
2908 USHORT nBoolIdx = 0;
2911 --pSh->nStartAction;
2913 if ( pSh->Imp()->GetRegion() || pSh->Imp()->GetScrollRects() )
2914 bActions = TRUE;
2915 else
2917 SwRect aTmp( pSh->VisArea() );
2918 pSh->UISizeNotify();
2920 // --> FME 2006-08-03 #137134#
2921 // Are we supposed to crash if pSh isn't a cursor shell?!
2922 // bActions |= aTmp != pSh->VisArea() ||
2923 // aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
2925 // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
2926 // and the cursor is visible.
2927 bActions |= aTmp != pSh->VisArea();
2928 if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
2930 bActions |= aBools[nBoolIdx] !=
2931 static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
2935 pSh = (ViewShell*)pSh->GetNext();
2936 ++nBoolIdx;
2937 } while ( pSh != pImp->GetShell() );
2939 if ( bActions )
2941 //Start- EndActions aufsetzen. ueber die CrsrShell, damit der
2942 //Cursor/Selektion und die VisArea korrekt gesetzt werden.
2943 nBoolIdx = 0;
2946 BOOL bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
2948 if ( bCrsrShell )
2949 ((SwCrsrShell*)pSh)->SttCrsrMove();
2950 // else
2951 // pSh->StartAction();
2953 //Wenn Paints aufgelaufen sind, ist es am sinnvollsten schlicht das
2954 //gesamte Window zu invalidieren. Anderfalls gibt es Paintprobleme
2955 //deren Loesung unverhaeltnissmaessig aufwendig waere.
2956 //fix(18176):
2957 SwViewImp *pViewImp = pSh->Imp();
2958 BOOL bUnlock = FALSE;
2959 if ( pViewImp->GetRegion() || pViewImp->GetScrollRects() )
2961 pViewImp->DelRegions();
2963 //Fuer Repaint mit virtuellem Device sorgen.
2964 pSh->LockPaint();
2965 bUnlock = TRUE;
2968 if ( bCrsrShell )
2969 //Wenn der Crsr sichbar war wieder sichbar machen, sonst
2970 //EndCrsrMove mit TRUE fuer IdleEnd.
2971 ((SwCrsrShell*)pSh)->EndCrsrMove( TRUE^aBools[nBoolIdx] );
2972 // else
2973 // pSh->EndAction();
2974 if( bUnlock )
2976 if( bCrsrShell )
2978 // UnlockPaint overwrite the selection from the
2979 // CrsrShell and calls the virtual method paint
2980 // to fill the virtual device. This fill dont have
2981 // paint the selection! -> Set the focus flag at
2982 // CrsrShell and it dont paint the selection.
2983 ((SwCrsrShell*)pSh)->ShLooseFcs();
2984 pSh->UnlockPaint( TRUE );
2985 ((SwCrsrShell*)pSh)->ShGetFcs( FALSE );
2987 else
2988 pSh->UnlockPaint( TRUE );
2991 pSh = (ViewShell*)pSh->GetNext();
2992 ++nBoolIdx;
2994 } while ( pSh != pImp->GetShell() );
2997 if ( !aAction.IsInterrupt() )
2999 if ( !DoIdleJob( WORD_COUNT, FALSE ) )
3000 if ( !DoIdleJob( SMART_TAGS, FALSE ) )
3001 if ( !DoIdleJob( ONLINE_SPELLING, FALSE ) )
3002 DoIdleJob( AUTOCOMPLETE_WORDS, FALSE ); // SMARTTAGS
3005 bool bInValid = false;
3006 const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
3007 const ViewShell* pViewShell = pImp->GetShell();
3008 // See conditions in DoIdleJob()
3009 const BOOL bSpell = rVOpt.IsOnlineSpell();
3010 const BOOL bACmplWrd = rVOpt.IsAutoCompleteWords();
3011 const BOOL bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
3012 const BOOL bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
3013 !pViewShell->GetDoc()->isXForms() &&
3014 SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
3016 SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
3019 bInValid = pPg->IsInvalidCntnt() || pPg->IsInvalidLayout() ||
3020 pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
3021 pPg->IsInvalidFlyInCnt() ||
3022 (bSpell && pPg->IsInvalidSpelling()) ||
3023 (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
3024 (bWordCount && pPg->IsInvalidWordCount()) ||
3025 (bSmartTags && pPg->IsInvalidSmartTags()); // SMARTTAGS
3027 pPg = (SwPageFrm*)pPg->GetNext();
3029 } while ( pPg && !bInValid );
3031 if ( !bInValid )
3033 pRoot->ResetIdleFormat();
3034 pImp->GetShell()->GetDoc()->GetDocShell()->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED ) );
3038 pImp->GetShell()->EnableSmooth( TRUE );
3040 if( pImp->IsAccessible() )
3041 pImp->FireAccessibleEvents();
3043 #ifndef PRODUCT
3044 #if OSL_DEBUG_LEVEL > 1
3045 if ( bIndicator && pImp->GetShell()->GetWin() )
3047 // #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
3048 // This should be replaced by an overlay object in the future, anyways. Since it's only for debug
3049 // purposes, it is not urgent.
3050 static bool bCheckWithoutInvalidating(true);
3051 if(bCheckWithoutInvalidating)
3053 bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
3055 else
3057 Rectangle aRect( 0, 0, 5, 5 );
3058 aRect = pImp->GetShell()->GetWin()->PixelToLogic( aRect );
3059 pImp->GetShell()->GetWin()->Invalidate( aRect );
3062 #endif
3063 #endif
3066 SwLayIdle::~SwLayIdle()
3068 pImp->pIdleAct = 0;