xref: /trunk/main/sw/source/core/layout/layact.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 
33 #include <time.h>
34 #include "rootfrm.hxx"
35 #include "pagefrm.hxx"
36 #include "cntfrm.hxx"
37 #include "doc.hxx"
38 #include "IDocumentDrawModelAccess.hxx"
39 #include "IDocumentSettingAccess.hxx"
40 #include "IDocumentLayoutAccess.hxx"
41 #include "IDocumentStatistics.hxx"
42 #include "IDocumentTimerAccess.hxx"
43 #include "viewimp.hxx"
44 #include "crsrsh.hxx"
45 #include "dflyobj.hxx"
46 #include "flyfrm.hxx"
47 #include "frmtool.hxx"
48 #include "dcontact.hxx"
49 #include "ndtxt.hxx"    // OnlineSpelling
50 #include "frmfmt.hxx"
51 #include "swregion.hxx"
52 #include "viewopt.hxx"  // OnlineSpelling ueber Internal-TabPage testen.
53 #include "pam.hxx"      // OnlineSpelling wg. der aktuellen Cursorposition
54 #include "dbg_lay.hxx"
55 #include "layouter.hxx" // LoopControlling
56 #include "docstat.hxx"
57 #include "swevent.hxx"
58 
59 #include <sfx2/event.hxx>
60 
61 #include <ftnidx.hxx>
62 #include <vcl/window.hxx>
63 #include <vcl/svapp.hxx>
64 #include <editeng/opaqitem.hxx>
65 #include <editeng/brshitem.hxx>
66 #include <SwSmartTagMgr.hxx>
67 
68 #define _SVSTDARR_BOOLS
69 #include <svl/svstdarr.hxx>
70 
71 #define _LAYACT_CXX
72 #include "layact.hxx"
73 #include <swwait.hxx>
74 #include <fmtsrnd.hxx>
75 #include <fmtanchr.hxx>
76 #include <tools/shl.hxx>
77 #include <sfx2/progress.hxx>
78 #ifndef _DOCSH_HXX
79 #include <docsh.hxx>
80 #endif
81 
82 #include "swmodule.hxx"
83 #include "fmtline.hxx"
84 #include "tabfrm.hxx"
85 #include "ftnfrm.hxx"
86 #include "txtfrm.hxx"
87 #include "notxtfrm.hxx"
88 #include "flyfrms.hxx"
89 #include "mdiexp.hxx"
90 #include "fmtornt.hxx"
91 #include "sectfrm.hxx"
92 #include "lineinfo.hxx"
93 #include <acmplwrd.hxx>
94 // --> OD 2004-06-28 #i28701#
95 #include <sortedobjs.hxx>
96 #include <objectformatter.hxx>
97 #include <PostItMgr.hxx>
98 
99 // <--
100 //#pragma optimize("ity",on)
101 
102 /*************************************************************************
103 |*
104 |*  SwLayAction Statisches Geraffel
105 |*
106 |*  Ersterstellung      MA 22. Dec. 93
107 |*  Letzte Aenderung    MA 22. Dec. 93
108 |*
109 |*************************************************************************/
110 
111 #define IS_FLYS (pPage->GetSortedObjs())
112 #define IS_INVAFLY (pPage->IsInvalidFly())
113 
114 
115 //Sparen von Schreibarbeit um den Zugriff auf zerstoerte Seiten zu vermeiden.
116 #ifdef DBG_UTIL
117 
118 static void BreakPoint()
119 {
120     return;
121 }
122 
123 #define CHECKPAGE \
124             {   if ( IsAgain() ) \
125                 {   BreakPoint(); \
126                     return; \
127                 } \
128             }
129 
130 #define XCHECKPAGE \
131             {   if ( IsAgain() ) \
132                 {   BreakPoint(); \
133                     if( bNoLoop ) \
134                         pLayoutAccess->GetLayouter()->EndLoopControl(); \
135                     return; \
136                 } \
137             }
138 #else
139 #define CHECKPAGE \
140             {   if ( IsAgain() ) \
141                     return; \
142             }
143 
144 #define XCHECKPAGE \
145             {   if ( IsAgain() ) \
146                 { \
147                     if( bNoLoop ) \
148                         pLayoutAccess->GetLayouter()->EndLoopControl(); \
149                     return; \
150                 } \
151             }
152 #endif
153 
154 #define RESCHEDULE \
155     { \
156         if ( IsReschedule() )  \
157         { \
158             if (pProgress) pProgress->Reschedule(); \
159             ::RescheduleProgress( pImp->GetShell()->GetDoc()->GetDocShell() ); \
160         } \
161     }
162 
163 inline sal_uLong Ticks()
164 {
165     return 1000 * clock() / CLOCKS_PER_SEC;
166 }
167 
168 void SwLayAction::CheckWaitCrsr()
169 {
170     RESCHEDULE
171     if ( !IsWait() && IsWaitAllowed() && IsPaint() &&
172          ((Ticks() - GetStartTicks()) >= CLOCKS_PER_SEC/2) )
173     {
174         pWait = new SwWait( *pRoot->GetFmt()->GetDoc()->GetDocShell(), sal_True );
175     }
176 }
177 
178 /*************************************************************************
179 |*
180 |*  SwLayAction::CheckIdleEnd()
181 |*
182 |*  Ersterstellung      MA 12. Aug. 94
183 |*  Letzte Aenderung    MA 24. Jun. 96
184 |*
185 |*************************************************************************/
186 //Ist es wirklich schon soweit...
187 inline void SwLayAction::CheckIdleEnd()
188 {
189     if ( !IsInput() )
190         bInput = GetInputType() && Application::AnyInput( GetInputType() );
191 }
192 
193 /*************************************************************************
194 |*
195 |*  SwLayAction::SetStatBar()
196 |*
197 |*  Ersterstellung      MA 10. Aug. 94
198 |*  Letzte Aenderung    MA 06. Aug. 95
199 |*
200 |*************************************************************************/
201 void SwLayAction::SetStatBar( sal_Bool bNew )
202 {
203     if ( bNew )
204     {
205         nEndPage = pRoot->GetPageNum();
206         nEndPage += nEndPage * 10 / 100;
207     }
208     else
209         nEndPage = USHRT_MAX;
210 }
211 
212 /*************************************************************************
213 |*
214 |*  SwLayAction::PaintCntnt()
215 |*
216 |*  Beschreibung        Je nach Typ wird der Cntnt entsprechend seinen
217 |*      Veraenderungen ausgegeben bzw. wird die auszugebende Flaeche in der
218 |*      Region eingetragen.
219 |*      PaintCntnt:  fuellt die Region,
220 |*  Ersterstellung      BP 19. Jan. 92
221 |*  Letzte Aenderung    MA 10. Sep. 96
222 |*
223 |*************************************************************************/
224 sal_Bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwCntntFrm *pCnt,
225                                     const SwPageFrm *pPage )
226 {
227     SwRegionRects aTmp( rRect );
228     const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
229     const SwFlyFrm *pSelfFly = pCnt->FindFlyFrm();
230     sal_uInt16 i;
231 
232     for ( i = 0; i < rObjs.Count() && aTmp.Count(); ++i )
233     {
234         SdrObject *pO = rObjs[i]->DrawObj();
235         if ( !pO->ISA(SwVirtFlyDrawObj) )
236             continue;
237 
238         // OD 2004-01-15 #110582# - do not consider invisible objects
239         const IDocumentDrawModelAccess* pIDDMA = pPage->GetFmt()->getIDocumentDrawModelAccess();
240         if ( !pIDDMA->IsVisibleLayerId( pO->GetLayer() ) )
241         {
242             continue;
243         }
244 
245         SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pO)->GetFlyFrm();
246 
247         if ( pFly == pSelfFly || !rRect.IsOver( pFly->Frm() ) )
248             continue;
249 
250         if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
251             continue;
252 
253         if ( pFly->GetVirtDrawObj()->GetLayer() == pIDDMA->GetHellId() )
254             continue;
255 
256         if ( pSelfFly )
257         {
258             const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
259             if ( pO->GetLayer() == pTmp->GetLayer() )
260             {
261                 if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
262                     //Im gleichen Layer werden nur obenliegende beachtet.
263                     continue;
264             }
265             else
266             {
267                 const sal_Bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
268                 if ( !bLowerOfSelf && !pFly->GetFmt()->GetOpaque().GetValue() )
269                     //Aus anderem Layer interessieren uns nur nicht transparente
270                     //oder innenliegende
271                     continue;
272             }
273         }
274 
275         /// OD 19.08.2002 #99657#
276         ///     Fly frame without a lower have to be subtracted from paint region.
277         ///     For checking, if fly frame contains transparent graphic or
278         ///     has surrounded contour, assure that fly frame has a lower
279         if ( pFly->Lower() &&
280              pFly->Lower()->IsNoTxtFrm() &&
281              ( ((SwNoTxtFrm*)pFly->Lower())->IsTransparent() ||
282                pFly->GetFmt()->GetSurround().IsContour() )
283            )
284         {
285             continue;
286         }
287 
288         /// OD 19.08.2002 #99657#
289         ///     Region of a fly frame with transparent background or a transparent
290         ///     shadow have not to be subtracted from paint region
291         if ( pFly->IsBackgroundTransparent() ||
292              pFly->IsShadowTransparent() )
293         {
294             continue;
295         }
296 
297         aTmp -= pFly->Frm();
298     }
299 
300     sal_Bool bRetPaint = sal_False;
301     const SwRect *pData = aTmp.GetData();
302     for ( i = 0; i < aTmp.Count(); ++pData, ++i )
303         bRetPaint |= pImp->GetShell()->AddPaintRect( *pData );
304     return bRetPaint;
305 }
306 
307 inline sal_Bool SwLayAction::_PaintCntnt( const SwCntntFrm *pCntnt,
308                                       const SwPageFrm *pPage,
309                                       const SwRect &rRect )
310 {
311     if ( rRect.HasArea() )
312     {
313         if ( pPage->GetSortedObjs() )
314             return PaintWithoutFlys( rRect, pCntnt, pPage );
315         else
316             return pImp->GetShell()->AddPaintRect( rRect );
317     }
318     return sal_False;
319 }
320 
321 void SwLayAction::PaintCntnt( const SwCntntFrm *pCnt,
322                               const SwPageFrm *pPage,
323                               const SwRect &rOldRect,
324                               long nOldBottom )
325 {
326     SWRECTFN( pCnt )
327 
328     if ( pCnt->IsCompletePaint() || !pCnt->IsTxtFrm() )
329     {
330         SwRect aPaint( pCnt->PaintArea() );
331         if ( !_PaintCntnt( pCnt, pPage, aPaint ) )
332             pCnt->ResetCompletePaint();
333     }
334     else
335     {
336         // paint the area between printing bottom and frame bottom and
337         // the area left and right beside the frame, if its height changed.
338         long nOldHeight = (rOldRect.*fnRect->fnGetHeight)();
339         long nNewHeight = (pCnt->Frm().*fnRect->fnGetHeight)();
340         const bool bHeightDiff = nOldHeight != nNewHeight;
341         if( bHeightDiff )
342         {
343             // OD 05.11.2002 #94454# - consider whole potential paint area.
344             //SwRect aDrawRect( pCnt->UnionFrm( sal_True ) );
345             SwRect aDrawRect( pCnt->PaintArea() );
346             if( nOldHeight > nNewHeight )
347                 nOldBottom = (pCnt->*fnRect->fnGetPrtBottom)();
348             (aDrawRect.*fnRect->fnSetTop)( nOldBottom );
349             _PaintCntnt( pCnt, pPage, aDrawRect );
350         }
351         // paint content area
352         SwRect aPaintRect = static_cast<SwTxtFrm*>(const_cast<SwCntntFrm*>(pCnt))->Paint();
353         _PaintCntnt( pCnt, pPage, aPaintRect );
354     }
355 
356     if ( pCnt->IsRetouche() && !pCnt->GetNext() )
357     {
358         const SwFrm *pTmp = pCnt;
359         if( pCnt->IsInSct() )
360         {
361             const SwSectionFrm* pSct = pCnt->FindSctFrm();
362             if( pSct->IsRetouche() && !pSct->GetNext() )
363                 pTmp = pSct;
364         }
365         SwRect aRect( pTmp->GetUpper()->PaintArea() );
366         (aRect.*fnRect->fnSetTop)( (pTmp->*fnRect->fnGetPrtBottom)() );
367         if ( !_PaintCntnt( pCnt, pPage, aRect ) )
368             pCnt->ResetRetouche();
369     }
370 }
371 
372 /*************************************************************************
373 |*
374 |*  SwLayAction::SwLayAction()
375 |*
376 |*  Ersterstellung      MA 30. Oct. 92
377 |*  Letzte Aenderung    MA 09. Jun. 95
378 |*
379 |*************************************************************************/
380 SwLayAction::SwLayAction( SwRootFrm *pRt, SwViewImp *pI ) :
381     pRoot( pRt ),
382     pImp( pI ),
383     pOptTab( 0 ),
384     pWait( 0 ),
385     pProgress(NULL),
386     nPreInvaPage( USHRT_MAX ),
387     nStartTicks( Ticks() ),
388     nInputType( 0 ),
389     nEndPage( USHRT_MAX ),
390     nCheckPageNum( USHRT_MAX )
391 {
392     bPaintExtraData = ::IsExtraData( pImp->GetShell()->GetDoc() );
393     bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
394     bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
395     bUpdateExpFlds = bBrowseActionStop = bActionInProgress = sal_False;
396     // OD 14.04.2003 #106346# - init new flag <mbFormatCntntOnInterrupt>.
397     mbFormatCntntOnInterrupt = sal_False;
398 
399     pImp->pLayAct = this;   //Anmelden
400 }
401 
402 SwLayAction::~SwLayAction()
403 {
404     ASSERT( !pWait, "Wait object not destroyed" );
405     pImp->pLayAct = 0;      //Abmelden
406 }
407 
408 /*************************************************************************
409 |*
410 |*  SwLayAction::Reset()
411 |*
412 |*  Ersterstellung      MA 11. Aug. 94
413 |*  Letzte Aenderung    MA 09. Jun. 95
414 |*
415 |*************************************************************************/
416 void SwLayAction::Reset()
417 {
418     pOptTab = 0;
419     nStartTicks = Ticks();
420     nInputType = 0;
421     nEndPage = nPreInvaPage = nCheckPageNum = USHRT_MAX;
422     bPaint = bComplete = bWaitAllowed = bCheckPages = sal_True;
423     bInput = bAgain = bNextCycle = bCalcLayout = bIdle = bReschedule =
424     bUpdateExpFlds = bBrowseActionStop = sal_False;
425 }
426 
427 /*************************************************************************
428 |*
429 |*  SwLayAction::RemoveEmptyBrowserPages()
430 |*
431 |*  Ersterstellung      MA 10. Sep. 97
432 |*  Letzte Aenderung    MA 10. Sep. 97
433 |*
434 |*************************************************************************/
435 
436 sal_Bool SwLayAction::RemoveEmptyBrowserPages()
437 {
438     //Beim umschalten vom normalen in den Browsermodus bleiben u.U. einige
439     //unangenehm lange stehen. Diese beseiten wir mal schnell.
440     sal_Bool bRet = sal_False;
441     const ViewShell *pSh = pRoot->GetCurrShell();
442     if( pSh && pSh->GetViewOptions()->getBrowseMode() )
443     {
444         SwPageFrm *pPage = (SwPageFrm*)pRoot->Lower();
445         do
446         {
447             if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->Count()) ||
448                  pPage->ContainsCntnt() )
449                 pPage = (SwPageFrm*)pPage->GetNext();
450             else
451             {
452                 bRet = sal_True;
453                 SwPageFrm *pDel = pPage;
454                 pPage = (SwPageFrm*)pPage->GetNext();
455                 pDel->Cut();
456                 delete pDel;
457             }
458         } while ( pPage );
459     }
460     return bRet;
461 }
462 
463 
464 /*************************************************************************
465 |*
466 |*  SwLayAction::Action()
467 |*
468 |*  Ersterstellung      MA 10. Aug. 94
469 |*  Letzte Aenderung    MA 06. Aug. 95
470 |*
471 |*************************************************************************/
472 void SwLayAction::Action()
473 {
474     bActionInProgress = sal_True;
475 
476     //TurboMode? Disqualifiziert fuer Idle-Format.
477     if ( IsPaint() && !IsIdle() && TurboAction() )
478     {
479         delete pWait, pWait = 0;
480         pRoot->ResetTurboFlag();
481         bActionInProgress = sal_False;
482         pRoot->DeleteEmptySct();
483         return;
484     }
485     else if ( pRoot->GetTurbo() )
486     {
487         pRoot->DisallowTurbo();
488         const SwFrm *pFrm = pRoot->GetTurbo();
489         pRoot->ResetTurbo();
490         pFrm->InvalidatePage();
491     }
492     pRoot->DisallowTurbo();
493 
494     if ( IsCalcLayout() )
495         SetCheckPages( sal_False );
496 
497     InternalAction();
498     bAgain |= RemoveEmptyBrowserPages();
499     while ( IsAgain() )
500     {
501         bAgain = bNextCycle = sal_False;
502         InternalAction();
503         bAgain |= RemoveEmptyBrowserPages();
504     }
505     pRoot->DeleteEmptySct();
506 
507     delete pWait, pWait = 0;
508 
509     //Turbo-Action ist auf jedenfall wieder erlaubt.
510     pRoot->ResetTurboFlag();
511     pRoot->ResetTurbo();
512 
513     SetCheckPages( sal_True );
514 
515     bActionInProgress = sal_False;
516 }
517 
518 SwPageFrm* SwLayAction::CheckFirstVisPage( SwPageFrm *pPage )
519 {
520     SwCntntFrm *pCnt = pPage->FindFirstBodyCntnt();
521     SwCntntFrm *pChk = pCnt;
522     sal_Bool bPageChgd = sal_False;
523     while ( pCnt && pCnt->IsFollow() )
524         pCnt = static_cast<SwCntntFrm*>(pCnt)->FindMaster();
525     if ( pCnt && pChk != pCnt )
526     {   bPageChgd = sal_True;
527         pPage = pCnt->FindPageFrm();
528     }
529 
530     if ( pPage->GetFmt()->GetDoc()->GetFtnIdxs().Count() )
531     {
532         SwFtnContFrm *pCont = pPage->FindFtnCont();
533         if ( pCont )
534         {
535             pCnt = pCont->ContainsCntnt();
536             pChk = pCnt;
537             while ( pCnt && pCnt->IsFollow() )
538                 pCnt = (SwCntntFrm*)pCnt->FindPrev();
539             if ( pCnt && pCnt != pChk )
540             {
541                 if ( bPageChgd )
542                 {
543                     //Die 'oberste' Seite benutzten.
544                     SwPageFrm *pTmp = pCnt->FindPageFrm();
545                     if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
546                         pPage = pTmp;
547                 }
548                 else
549                     pPage = pCnt->FindPageFrm();
550             }
551         }
552     }
553     return pPage;
554 }
555 
556 // OD 2004-05-12 #i28701#
557 // --> OD 2004-11-03 #i114798# - unlock position on start and end of page
558 // layout process.
559 class NotifyLayoutOfPageInProgress
560 {
561     private:
562         SwPageFrm& mrPageFrm;
563 
564         void _UnlockPositionOfObjs()
565         {
566             SwSortedObjs* pObjs = mrPageFrm.GetSortedObjs();
567             if ( pObjs )
568             {
569                 sal_uInt32 i = 0;
570                 for ( ; i < pObjs->Count(); ++i )
571                 {
572                     SwAnchoredObject* pObj = (*pObjs)[i];
573                     pObj->UnlockPosition();
574                 }
575             }
576         }
577     public:
578         NotifyLayoutOfPageInProgress( SwPageFrm& _rPageFrm )
579             : mrPageFrm( _rPageFrm )
580         {
581             _UnlockPositionOfObjs();
582             _rPageFrm.SetLayoutInProgress( true );
583         }
584         ~NotifyLayoutOfPageInProgress()
585         {
586             mrPageFrm.SetLayoutInProgress( false );
587             _UnlockPositionOfObjs();
588         }
589 };
590 // <--
591 
592 void SwLayAction::InternalAction()
593 {
594     ASSERT( pRoot->Lower()->IsPageFrm(), ":-( Keine Seite unterhalb der Root.");
595 
596     pRoot->Calc();
597 
598     //Die erste ungueltige bzw. zu formatierende Seite ermitteln.
599     //Bei einer Complete-Action ist es die erste ungueltige; mithin ist die
600     //erste zu formatierende Seite diejenige Seite mit der Numemr eins.
601     //Bei einer Luegen-Formatierung ist die Nummer der erste Seite die Nummer
602     //der ersten Sichtbaren Seite.
603     SwPageFrm *pPage = IsComplete() ? (SwPageFrm*)pRoot->Lower() :
604                 pImp->GetFirstVisPage();
605     if ( !pPage )
606         pPage = (SwPageFrm*)pRoot->Lower();
607 
608     //Wenn ein "Erster-Fliess-Cntnt" innerhalb der der ersten sichtbaren Seite
609     //ein Follow ist, so schalten wir die Seite zurueck auf den Ur-Master dieses
610     //Cntnt's
611     if ( !IsComplete() )
612         pPage = CheckFirstVisPage( pPage );
613     sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
614 
615     while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
616         pPage = (SwPageFrm*)pPage->GetNext();
617 
618     IDocumentLayoutAccess *pLayoutAccess = pRoot->GetFmt()->getIDocumentLayoutAccess();
619     sal_Bool bNoLoop = pPage ? SwLayouter::StartLoopControl( pRoot->GetFmt()->GetDoc(), pPage ) : sal_False;
620     sal_uInt16 nPercentPageNum = 0;
621     while ( (pPage && !IsInterrupt()) || nCheckPageNum != USHRT_MAX )
622     {
623         if ( !pPage && nCheckPageNum != USHRT_MAX &&
624              (!pPage || pPage->GetPhyPageNum() >= nCheckPageNum) )
625         {
626             if ( !pPage || pPage->GetPhyPageNum() > nCheckPageNum )
627             {
628                 SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
629                 while ( pPg && pPg->GetPhyPageNum() < nCheckPageNum )
630                     pPg = (SwPageFrm*)pPg->GetNext();
631                 if ( pPg )
632                     pPage = pPg;
633                 if ( !pPage )
634                     break;
635             }
636             SwPageFrm *pTmp = pPage->GetPrev() ?
637                                         (SwPageFrm*)pPage->GetPrev() : pPage;
638             SetCheckPages( sal_True );
639             SwFrm::CheckPageDescs( pPage );
640             SetCheckPages( sal_False );
641             nCheckPageNum = USHRT_MAX;
642             pPage = pTmp;
643             continue;
644         }
645 
646         if ( nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
647         {
648             nPercentPageNum = pPage->GetPhyPageNum();
649             ::SetProgressState( nPercentPageNum, pImp->GetShell()->GetDoc()->GetDocShell());
650         }
651         pOptTab = 0;
652              //Kein ShortCut fuer Idle oder CalcLayout
653         if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
654         {
655             pRoot->DeleteEmptySct();
656             XCHECKPAGE;
657             if ( !IsInterrupt() &&
658                  (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
659             {
660                 if ( pRoot->IsAssertFlyPages() )
661                     pRoot->AssertFlyPages();
662                 if ( pRoot->IsSuperfluous() )
663                 {
664                     sal_Bool bOld = IsAgain();
665                     pRoot->RemoveSuperfluous();
666                     bAgain = bOld;
667                 }
668                 if ( IsAgain() )
669                 {
670                     if( bNoLoop )
671                         pLayoutAccess->GetLayouter()->EndLoopControl();
672                     return;
673                 }
674                 pPage = (SwPageFrm*)pRoot->Lower();
675                 while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
676                     pPage = (SwPageFrm*)pPage->GetNext();
677                 while ( pPage && pPage->GetNext() &&
678                         pPage->GetPhyPageNum() < nFirstPageNum )
679                     pPage = (SwPageFrm*)pPage->GetNext();
680                 continue;
681             }
682             break;
683         }
684         else
685         {
686             pRoot->DeleteEmptySct();
687             XCHECKPAGE;
688 
689             // OD 2004-05-12 #i28701# - scope for instance of class
690             // <NotifyLayoutOfPageInProgress>
691             {
692                 NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPage );
693 
694                 while ( !IsInterrupt() && !IsNextCycle() &&
695                         ((IS_FLYS && IS_INVAFLY) || pPage->IsInvalid()) )
696                 {
697                     // OD 2004-05-10 #i28701#
698                     SwObjectFormatter::FormatObjsAtFrm( *pPage, *pPage, this );
699                     if ( !IS_FLYS )
700                     {
701                         //Wenn keine Flys (mehr) da sind, sind die Flags
702                         //mehr als fluessig.
703                         pPage->ValidateFlyLayout();
704                         pPage->ValidateFlyCntnt();
705                     }
706                     // OD 2004-05-10 #i28701# - change condition
707                     while ( !IsInterrupt() && !IsNextCycle() &&
708                             ( pPage->IsInvalid() ||
709                               (IS_FLYS && IS_INVAFLY) ) )
710                     {
711                         PROTOCOL( pPage, PROT_FILE_INIT, 0, 0)
712                         XCHECKPAGE;
713 
714                         // FME 2007-08-30 #i81146# new loop control
715                         sal_uInt16 nLoopControlRuns_1 = 0;
716                         const sal_uInt16 nLoopControlMax = 20;
717 
718                         while ( !IsNextCycle() && pPage->IsInvalidLayout() )
719                         {
720                             pPage->ValidateLayout();
721 
722                             if ( ++nLoopControlRuns_1 > nLoopControlMax )
723                             {
724 #if OSL_DEBUG_LEVEL > 1
725                                 ASSERT( false, "LoopControl_1 in SwLayAction::InternalAction" )
726 #endif
727                                 break;
728                             }
729 
730                             FormatLayout( pPage );
731                             XCHECKPAGE;
732                         }
733                         // OD 2004-05-10 #i28701# - change condition
734                         if ( !IsNextCycle() &&
735                              ( pPage->IsInvalidCntnt() ||
736                                (IS_FLYS && IS_INVAFLY) ) )
737                         {
738                             pPage->ValidateFlyInCnt();
739                             pPage->ValidateCntnt();
740                             // --> OD 2004-05-10 #i28701#
741                             pPage->ValidateFlyLayout();
742                             pPage->ValidateFlyCntnt();
743                             // <--
744                             if ( !FormatCntnt( pPage ) )
745                             {
746                                 XCHECKPAGE;
747                                 pPage->InvalidateCntnt();
748                                 pPage->InvalidateFlyInCnt();
749                                 // --> OD 2004-05-10 #i28701#
750                                 pPage->InvalidateFlyLayout();
751                                 pPage->InvalidateFlyCntnt();
752                                 // <--
753                                 if ( IsBrowseActionStop() )
754                                     bInput = sal_True;
755                             }
756                         }
757                         if( bNoLoop )
758                             pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
759                     }
760                 }
761             } // end of scope for instance of class <NotifyLayoutOfPageInProgress>
762 
763 
764             //Eine vorige Seite kann wieder invalid sein.
765             XCHECKPAGE;
766             if ( !IS_FLYS )
767             {
768                 //Wenn keine Flys (mehr) da sind, sind die Flags
769                 //mehr als fluessig.
770                 pPage->ValidateFlyLayout();
771                 pPage->ValidateFlyCntnt();
772             }
773             if ( !IsInterrupt() )
774             {
775                 SetNextCycle( sal_False );
776 
777                 if ( nPreInvaPage != USHRT_MAX )
778                 {
779                     if( !IsComplete() && nPreInvaPage + 2 < nFirstPageNum )
780                     {
781                         pImp->SetFirstVisPageInvalid();
782                         SwPageFrm *pTmpPage = pImp->GetFirstVisPage();
783                         nFirstPageNum = pTmpPage->GetPhyPageNum();
784                         if( nPreInvaPage < nFirstPageNum )
785                         {
786                             nPreInvaPage = nFirstPageNum;
787                             pPage = pTmpPage;
788                         }
789                     }
790                     while ( pPage->GetPrev() && pPage->GetPhyPageNum() > nPreInvaPage )
791                         pPage = (SwPageFrm*)pPage->GetPrev();
792                     nPreInvaPage = USHRT_MAX;
793                 }
794 
795                 while ( pPage->GetPrev() &&
796                         ( ((SwPageFrm*)pPage->GetPrev())->IsInvalid() ||
797                           ( ((SwPageFrm*)pPage->GetPrev())->GetSortedObjs() &&
798                             ((SwPageFrm*)pPage->GetPrev())->IsInvalidFly())) &&
799                         (((SwPageFrm*)pPage->GetPrev())->GetPhyPageNum() >=
800                             nFirstPageNum) )
801                 {
802                     pPage = (SwPageFrm*)pPage->GetPrev();
803                 }
804 
805                 //Weiter bis zur naechsten invaliden Seite.
806                 while ( pPage && !pPage->IsInvalid() &&
807                         (!IS_FLYS || !IS_INVAFLY) )
808                 {
809                     pPage = (SwPageFrm*)pPage->GetNext();
810                 }
811                 if( bNoLoop )
812                     pLayoutAccess->GetLayouter()->LoopControl( pPage, LOOP_PAGE );
813             }
814             CheckIdleEnd();
815         }
816         if ( !pPage && !IsInterrupt() &&
817              (pRoot->IsSuperfluous() || pRoot->IsAssertFlyPages()) )
818         {
819             if ( pRoot->IsAssertFlyPages() )
820                 pRoot->AssertFlyPages();
821             if ( pRoot->IsSuperfluous() )
822             {
823                 sal_Bool bOld = IsAgain();
824                 pRoot->RemoveSuperfluous();
825                 bAgain = bOld;
826             }
827             if ( IsAgain() )
828             {
829                 if( bNoLoop )
830                     pLayoutAccess->GetLayouter()->EndLoopControl();
831                 return;
832             }
833             pPage = (SwPageFrm*)pRoot->Lower();
834             while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
835                 pPage = (SwPageFrm*)pPage->GetNext();
836             while ( pPage && pPage->GetNext() &&
837                     pPage->GetPhyPageNum() < nFirstPageNum )
838                 pPage = (SwPageFrm*)pPage->GetNext();
839         }
840     }
841     if ( IsInterrupt() && pPage )
842     {
843         //Wenn ein Input anliegt wollen wir keinen Inhalt mehr Formatieren,
844         //Das Layout muessen wir aber schon in Ordnung bringen.
845         //Andernfalls kann folgende Situation auftreten (Bug: 3244):
846         //Am Ende des Absatz der letzten Seite wird Text eingegeben, so das
847         //der Absatz einen Follow fuer die nachste Seite erzeugt, ausserdem
848         //wird gleich schnell weitergetippt - Es liegt waehrend der
849         //Verarbeitung ein Input an. Der Absatz auf der neuen Seite wurde
850         //bereits anformatiert, die neue Seite ist Formatiert und steht
851         //auf CompletePaint, hat sich aber noch nicht im Auszugebenden Bereich
852         //eingetragen. Es wird gepaintet, das CompletePaint der Seite wird
853         //zurueckgesetzt weil der neue Absatz sich bereits eingetragen hatte,
854         //aber die Raender der Seite werden nicht gepaintet. Naja, bei der
855         //zwangslaeufig auftretenden naechsten LayAction traegt sich die Seite
856         //nicht mehr ein, weil ihre (LayoutFrm-)Flags bereits zurueckgesetzt
857         //wurden -- Der Rand der Seite wird nie gepaintet.
858         SwPageFrm *pPg = pPage;
859         XCHECKPAGE;
860         const SwRect &rVis = pImp->GetShell()->VisArea();
861 
862         while( pPg && pPg->Frm().Bottom() < rVis.Top() )
863             pPg = (SwPageFrm*)pPg->GetNext();
864         if( pPg != pPage )
865             pPg = pPg ? (SwPageFrm*)pPg->GetPrev() : pPage;
866 
867         // OD 14.04.2003 #106346# - set flag for interrupt content formatting
868         mbFormatCntntOnInterrupt = IsInput() && !IsStopPrt();
869         long nBottom = rVis.Bottom();
870         // --> OD 2005-02-15 #i42586# - format current page, if idle action is active
871         // This is an optimization for the case that the interrupt is created by
872         // the move of a form control object, which is represented by a window.
873         while ( pPg && ( pPg->Frm().Top() < nBottom ||
874                          ( IsIdle() && pPg == pPage ) ) )
875         // <--
876         {
877             // --> OD 2004-10-11 #i26945# - follow-up of #i28701#
878             NotifyLayoutOfPageInProgress aLayoutOfPageInProgress( *pPg );
879 
880             XCHECKPAGE;
881 
882             // FME 2007-08-30 #i81146# new loop control
883             sal_uInt16 nLoopControlRuns_2 = 0;
884             const sal_uInt16 nLoopControlMax = 20;
885 
886             // OD 14.04.2003 #106346# - special case: interrupt content formatting
887             // --> OD 2004-07-08 #i28701# - conditions, introduced by #106346#,
888             // are incorrect (marcos IS_FLYS and IS_INVAFLY only works for <pPage>)
889             // and are too strict.
890             // --> OD 2005-06-09 #i50432# - adjust interrupt formatting to
891             // normal page formatting - see above.
892             while ( ( mbFormatCntntOnInterrupt &&
893                       ( pPg->IsInvalid() ||
894                         ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
895                     ( !mbFormatCntntOnInterrupt && pPg->IsInvalidLayout() ) )
896             {
897                 XCHECKPAGE;
898                 // --> OD 2005-06-09 #i50432# - format also at-page anchored objects
899                 SwObjectFormatter::FormatObjsAtFrm( *pPg, *pPg, this );
900                 // <--
901                 // --> OD 2005-06-09 #i50432#
902                 if ( !pPg->GetSortedObjs() )
903                 {
904                     pPg->ValidateFlyLayout();
905                     pPg->ValidateFlyCntnt();
906                 }
907                 // <--
908 
909                 // FME 2007-08-30 #i81146# new loop control
910                 sal_uInt16 nLoopControlRuns_3 = 0;
911 
912                 while ( pPg->IsInvalidLayout() )
913                 {
914                     pPg->ValidateLayout();
915 
916                     if ( ++nLoopControlRuns_3 > nLoopControlMax )
917                     {
918 #if OSL_DEBUG_LEVEL > 1
919                         ASSERT( false, "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" )
920 #endif
921                         break;
922                     }
923 
924                     FormatLayout( pPg );
925                     XCHECKPAGE;
926                 }
927 
928                 // --> OD 2005-06-09 #i50432#
929                 if ( mbFormatCntntOnInterrupt &&
930                      ( pPg->IsInvalidCntnt() ||
931                        ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
932                 // <--
933                 {
934                     pPg->ValidateFlyInCnt();
935                     pPg->ValidateCntnt();
936                     // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
937                     pPg->ValidateFlyLayout();
938                     pPg->ValidateFlyCntnt();
939                     // <--
940 
941                     if ( ++nLoopControlRuns_2 > nLoopControlMax )
942                     {
943 #if OSL_DEBUG_LEVEL > 1
944                         ASSERT( false, "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" )
945 #endif
946                         break;
947                     }
948 
949                     if ( !FormatCntnt( pPg ) )
950                     {
951                         XCHECKPAGE;
952                         pPg->InvalidateCntnt();
953                         pPg->InvalidateFlyInCnt();
954                         // --> OD 2004-05-10 #i26945# - follow-up of fix #117736#
955                         pPg->InvalidateFlyLayout();
956                         pPg->InvalidateFlyCntnt();
957                         // <--
958                     }
959                     // --> OD 2005-04-06 #i46807# - we are statisfied, if the
960                     // content is formatted once complete.
961                     else
962                     {
963                         break;
964                     }
965                     // <--
966                 }
967             }
968             // <--
969             pPg = (SwPageFrm*)pPg->GetNext();
970         }
971         // OD 14.04.2003 #106346# - reset flag for special interrupt content formatting.
972         mbFormatCntntOnInterrupt = sal_False;
973     }
974     pOptTab = 0;
975     if( bNoLoop )
976         pLayoutAccess->GetLayouter()->EndLoopControl();
977 }
978 /*************************************************************************
979 |*
980 |*  SwLayAction::TurboAction(), _TurboAction()
981 |*
982 |*  Ersterstellung      MA 04. Dec. 92
983 |*  Letzte Aenderung    MA 15. Aug. 93
984 |*
985 |*************************************************************************/
986 sal_Bool SwLayAction::_TurboAction( const SwCntntFrm *pCnt )
987 {
988 
989     const SwPageFrm *pPage = 0;
990     if ( !pCnt->IsValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
991     {
992         const SwRect aOldRect( pCnt->UnionFrm( sal_True ) );
993         const long   nOldBottom = pCnt->Frm().Top() + pCnt->Prt().Bottom();
994         pCnt->Calc();
995         if ( pCnt->Frm().Bottom() < aOldRect.Bottom() )
996             pCnt->SetRetouche();
997 
998         pPage = pCnt->FindPageFrm();
999         PaintCntnt( pCnt, pPage, aOldRect, nOldBottom );
1000 
1001         if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTxtFrm() )
1002         {
1003             const sal_uLong nAllLines = ((SwTxtFrm*)pCnt)->GetAllLines();
1004             ((SwTxtFrm*)pCnt)->RecalcAllLines();
1005             if ( nAllLines != ((SwTxtFrm*)pCnt)->GetAllLines() )
1006             {
1007                 if ( IsPaintExtraData() )
1008                     pImp->GetShell()->AddPaintRect( pCnt->Frm() );
1009                 //Damit die restlichen LineNums auf der Seite bereichnet werden
1010                 //und nicht hier abgebrochen wird.
1011                 //Das im RecalcAllLines zu erledigen waere teuer, weil dort
1012                 //auch in unnoetigen Faellen (normale Action) auch immer die
1013                 //Seite benachrichtigt werden muesste.
1014                 const SwCntntFrm *pNxt = pCnt->GetNextCntntFrm();
1015                 while ( pNxt &&
1016                         (pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
1017                     pNxt = pNxt->GetNextCntntFrm();
1018                 if ( pNxt )
1019                     pNxt->InvalidatePage();
1020             }
1021             return sal_False;
1022         }
1023 
1024         if ( pPage->IsInvalidLayout() || (IS_FLYS && IS_INVAFLY) )
1025             return sal_False;
1026     }
1027     if ( !pPage )
1028         pPage = pCnt->FindPageFrm();
1029 
1030     // OD 2004-05-10 #i28701# - format floating screen objects at content frame.
1031     if ( pCnt->IsTxtFrm() &&
1032          !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCnt)),
1033                                               *pPage, this ) )
1034     {
1035         return sal_False;
1036     }
1037 
1038     if ( pPage->IsInvalidCntnt() )
1039         return sal_False;
1040     return sal_True;
1041 }
1042 
1043 sal_Bool SwLayAction::TurboAction()
1044 {
1045     sal_Bool bRet = sal_True;
1046 
1047     if ( pRoot->GetTurbo() )
1048     {
1049         if ( !_TurboAction( pRoot->GetTurbo() ) )
1050         {
1051             CheckIdleEnd();
1052             bRet = sal_False;
1053         }
1054         pRoot->ResetTurbo();
1055     }
1056     else
1057         bRet = sal_False;
1058     return bRet;
1059 }
1060 /*************************************************************************
1061 |*
1062 |*  SwLayAction::IsShortCut()
1063 |*
1064 |*  Beschreibung:       Liefert ein True, wenn die Seite vollstaendig unter
1065 |*      oder rechts neben dem sichbaren Bereich liegt.
1066 |*      Es kann passieren, dass sich die Verhaeltnisse derart aendern, dass
1067 |*      die Verarbeitung (des Aufrufers!) mit der Vorgaengerseite der
1068 |*      uebergebenen Seite weitergefuehrt werden muss. Der Paramter wird also
1069 |*      ggf. veraendert!
1070 |*      Fuer den BrowseMode kann auch dann der ShortCut aktiviert werden,
1071 |*      wenn der ungueltige Inhalt der Seite unterhalb des sichbaren
1072 |*      bereiches liegt.
1073 |*  Ersterstellung      MA 30. Oct. 92
1074 |*  Letzte Aenderung    MA 18. Jul. 96
1075 |*
1076 |*************************************************************************/
1077 static bool lcl_IsInvaLay( const SwFrm *pFrm, long nBottom )
1078 {
1079     if (
1080          !pFrm->IsValid() ||
1081          (pFrm->IsCompletePaint() && ( pFrm->Frm().Top() < nBottom ) )
1082        )
1083     {
1084         return true;
1085     }
1086     return false;
1087 }
1088 
1089 static const SwFrm *lcl_FindFirstInvaLay( const SwFrm *pFrm, long nBottom )
1090 {
1091     ASSERT( pFrm->IsLayoutFrm(), "FindFirstInvaLay, no LayFrm" );
1092 
1093     if (lcl_IsInvaLay(pFrm, nBottom))
1094         return pFrm;
1095     pFrm = ((SwLayoutFrm*)pFrm)->Lower();
1096     while ( pFrm )
1097     {
1098         if ( pFrm->IsLayoutFrm() )
1099         {
1100             if (lcl_IsInvaLay(pFrm, nBottom))
1101                 return pFrm;
1102             const SwFrm *pTmp;
1103             if ( 0 != (pTmp = lcl_FindFirstInvaLay( pFrm, nBottom )) )
1104                 return pTmp;
1105         }
1106         pFrm = pFrm->GetNext();
1107     }
1108     return 0;
1109 }
1110 
1111 static const SwFrm *lcl_FindFirstInvaCntnt( const SwLayoutFrm *pLay, long nBottom,
1112                                      const SwCntntFrm *pFirst )
1113 {
1114     const SwCntntFrm *pCnt = pFirst ? pFirst->GetNextCntntFrm() :
1115                                       pLay->ContainsCntnt();
1116     while ( pCnt )
1117     {
1118         if ( !pCnt->IsValid() || pCnt->IsCompletePaint() )
1119         {
1120             if ( pCnt->Frm().Top() <= nBottom )
1121                 return pCnt;
1122         }
1123 
1124         if ( pCnt->GetDrawObjs() )
1125         {
1126             const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
1127             for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
1128             {
1129                 const SwAnchoredObject* pObj = rObjs[i];
1130                 if ( pObj->ISA(SwFlyFrm) )
1131                 {
1132                     const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
1133                     if ( pFly->IsFlyInCntFrm() )
1134                     {
1135                         if ( ((SwFlyInCntFrm*)pFly)->IsInvalid() ||
1136                              pFly->IsCompletePaint() )
1137                         {
1138                             if ( pFly->Frm().Top() <= nBottom )
1139                                 return pFly;
1140                         }
1141                         const SwFrm *pFrm = lcl_FindFirstInvaCntnt( pFly, nBottom, 0 );
1142                         if ( pFrm && pFrm->Frm().Bottom() <= nBottom )
1143                             return pFrm;
1144                     }
1145                 }
1146             }
1147         }
1148         if ( pCnt->Frm().Top() > nBottom && !pCnt->IsInTab() )
1149             return 0;
1150         pCnt = pCnt->GetNextCntntFrm();
1151         if ( !pLay->IsAnLower( pCnt ) )
1152             break;
1153     }
1154     return 0;
1155 }
1156 
1157 // --> OD 2005-02-21 #i37877# - consider drawing objects
1158 static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrm* _pPage,
1159                                               long _nBottom )
1160 {
1161     ASSERT( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" )
1162 
1163     for ( sal_uInt16 i = 0; i < _pPage->GetSortedObjs()->Count(); ++i )
1164     {
1165         const SwAnchoredObject* pObj = (*_pPage->GetSortedObjs())[i];
1166         if ( pObj->ISA(SwFlyFrm) )
1167         {
1168             const SwFlyFrm* pFly = static_cast<const SwFlyFrm*>(pObj);
1169             if ( pFly->Frm().Top() <= _nBottom )
1170             {
1171                 if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
1172                     return pFly;
1173 
1174                 const SwFrm* pTmp;
1175                 if ( 0 != (pTmp = lcl_FindFirstInvaCntnt( pFly, _nBottom, 0 )) &&
1176                      pTmp->Frm().Top() <= _nBottom )
1177                     return pFly;
1178             }
1179         }
1180         else if ( pObj->ISA(SwAnchoredDrawObject) )
1181         {
1182             if ( !static_cast<const SwAnchoredDrawObject*>(pObj)->IsValidPos() )
1183             {
1184                 return pObj;
1185             }
1186         }
1187     }
1188     return 0;
1189 }
1190 // <--
1191 
1192 sal_Bool SwLayAction::IsShortCut( SwPageFrm *&prPage )
1193 {
1194     sal_Bool bRet = sal_False;
1195     const ViewShell *pSh = pRoot->GetCurrShell();
1196     const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1197 
1198     //Wenn die Seite nicht Gueltig ist wird sie schnell formatiert, sonst
1199     //gibts nix als Aerger.
1200     if ( !prPage->IsValid() )
1201     {
1202         if ( bBrowse )
1203         {
1204             /// OD 15.10.2002 #103517# - format complete page
1205             /// Thus, loop on all lowers of the page <prPage>, instead of only
1206             /// format its first lower.
1207             /// NOTE: In online layout (bBrowse == sal_True) a page can contain
1208             ///     a header frame and/or a footer frame beside the body frame.
1209             prPage->Calc();
1210             SwFrm* pPageLowerFrm = prPage->Lower();
1211             while ( pPageLowerFrm )
1212             {
1213                 pPageLowerFrm->Calc();
1214                 pPageLowerFrm = pPageLowerFrm->GetNext();
1215             }
1216         }
1217         else
1218             FormatLayout( prPage );
1219         if ( IsAgain() )
1220             return sal_False;
1221     }
1222 
1223 
1224     const SwRect &rVis = pImp->GetShell()->VisArea();
1225     if ( (prPage->Frm().Top() >= rVis.Bottom()) ||
1226          (prPage->Frm().Left()>= rVis.Right()) )
1227     {
1228         bRet = sal_True;
1229 
1230         //Jetzt wird es ein bischen unangenehm: Der erste CntntFrm dieser Seite
1231         //im Bodytext muss Formatiert werden, wenn er dabei die Seite
1232         //wechselt, muss ich nochmal eine Seite zuvor anfangen, denn
1233         //es wurde ein PageBreak verarbeitet.
1234 //Noch unangenehmer: Der naechste CntntFrm ueberhaupt muss
1235         //Formatiert werden, denn es kann passieren, dass kurzfristig
1236         //leere Seiten existieren (Bsp. Absatz ueber mehrere Seiten
1237         //wird geloescht oder verkleinert).
1238 
1239         //Ist fuer den Browser uninteressant, wenn der letzte Cnt davor bereits
1240         //nicht mehr sichbar ist.
1241 
1242         const SwPageFrm *p2ndPage = prPage;
1243         const SwCntntFrm *pCntnt;
1244         const SwLayoutFrm* pBody = p2ndPage->FindBodyCont();
1245         if( p2ndPage->IsFtnPage() && pBody )
1246             pBody = (SwLayoutFrm*)pBody->GetNext();
1247         pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1248         while ( p2ndPage && !pCntnt )
1249         {
1250             p2ndPage = (SwPageFrm*)p2ndPage->GetNext();
1251             if( p2ndPage )
1252             {
1253                 pBody = p2ndPage->FindBodyCont();
1254                 if( p2ndPage->IsFtnPage() && pBody )
1255                     pBody = (SwLayoutFrm*)pBody->GetNext();
1256                 pCntnt = pBody ? pBody->ContainsCntnt() : 0;
1257             }
1258         }
1259         if ( pCntnt )
1260         {
1261             sal_Bool bTstCnt = sal_True;
1262             if ( bBrowse )
1263             {
1264                 //Der Cnt davor schon nicht mehr sichtbar?
1265                 const SwFrm *pLst = pCntnt;
1266                 if ( pLst->IsInTab() )
1267                     pLst = pCntnt->FindTabFrm();
1268                 if ( pLst->IsInSct() )
1269                     pLst = pCntnt->FindSctFrm();
1270                 pLst = pLst->FindPrev();
1271                 if ( pLst &&
1272                      (pLst->Frm().Top() >= rVis.Bottom() ||
1273                       pLst->Frm().Left()>= rVis.Right()) )
1274                 {
1275                     bTstCnt = sal_False;
1276                 }
1277             }
1278 
1279             if ( bTstCnt )
1280             {
1281                 // --> OD 2004-06-04 #i27756# - check after each frame calculation,
1282                 // if the content frame has changed the page. If yes, no other
1283                 // frame calculation is performed
1284                 bool bPageChg = false;
1285 
1286                 if ( pCntnt->IsInSct() )
1287                 {
1288                     const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1289                     if ( !pSct->IsValid() )
1290                     {
1291                         pSct->Calc();
1292                         pSct->SetCompletePaint();
1293                         if ( IsAgain() )
1294                             return sal_False;
1295                         // --> OD 2004-06-04 #i27756#
1296                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1297                                    prPage->GetPrev();
1298                     }
1299                 }
1300 
1301                 if ( !bPageChg && !pCntnt->IsValid() )
1302                 {
1303                     pCntnt->Calc();
1304                     pCntnt->SetCompletePaint();
1305                     if ( IsAgain() )
1306                         return sal_False;
1307                     // --> OD 2004-06-04 #i27756#
1308                     bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1309                                prPage->GetPrev();
1310                 }
1311 
1312                 if ( !bPageChg && pCntnt->IsInTab() )
1313                 {
1314                     const SwTabFrm *pTab = ((SwFrm*)pCntnt)->ImplFindTabFrm();
1315                     if ( !pTab->IsValid() )
1316                     {
1317                         pTab->Calc();
1318                         pTab->SetCompletePaint();
1319                         if ( IsAgain() )
1320                             return sal_False;
1321                         // --> OD 2004-06-04 #i27756#
1322                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1323                                    prPage->GetPrev();
1324                     }
1325                 }
1326 
1327                 if ( !bPageChg && pCntnt->IsInSct() )
1328                 {
1329                     const SwSectionFrm *pSct = ((SwFrm*)pCntnt)->ImplFindSctFrm();
1330                     if ( !pSct->IsValid() )
1331                     {
1332                         pSct->Calc();
1333                         pSct->SetCompletePaint();
1334                         if ( IsAgain() )
1335                             return sal_False;
1336                         // --> OD 2004-06-04 #i27756#
1337                         bPageChg = pCntnt->FindPageFrm() != p2ndPage &&
1338                                    prPage->GetPrev();
1339                     }
1340                 }
1341 
1342                 // --> OD 2004-06-04 #i27756#
1343                 if ( bPageChg )
1344                 {
1345                     bRet = sal_False;
1346                     const SwPageFrm* pTmp = pCntnt->FindPageFrm();
1347                     if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
1348                          pTmp->IsInvalid() )
1349                     {
1350                         prPage = (SwPageFrm*)pTmp;
1351                     }
1352                     else
1353                     {
1354                         prPage = (SwPageFrm*)prPage->GetPrev();
1355                     }
1356                 }
1357                 // --> OD 2005-04-25 #121980# - no shortcut, if at previous page
1358                 // an anchored object is registered, whose anchor is <pCntnt>.
1359                 else if ( prPage->GetPrev() &&
1360                           static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs() )
1361                 {
1362                     SwSortedObjs* pObjs =
1363                         static_cast<SwPageFrm*>(prPage->GetPrev())->GetSortedObjs();
1364                     if ( pObjs )
1365                     {
1366                         sal_uInt32 i = 0;
1367                         for ( ; i < pObjs->Count(); ++i )
1368                         {
1369                             SwAnchoredObject* pObj = (*pObjs)[i];
1370                             if ( pObj->GetAnchorFrmContainingAnchPos() == pCntnt )
1371                             {
1372                                 bRet = sal_False;
1373                                 break;
1374                             }
1375                         }
1376                     }
1377                 }
1378                 // <--
1379             }
1380         }
1381     }
1382 
1383     if ( !bRet && bBrowse )
1384     {
1385         const long nBottom = rVis.Bottom();
1386         const SwAnchoredObject* pObj( 0L );
1387         if ( prPage->GetSortedObjs() &&
1388              (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyCntnt()) &&
1389              0 != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
1390              pObj->GetObjRect().Top() <= nBottom )
1391         {
1392             return sal_False;
1393         }
1394         const SwFrm* pFrm( 0L );
1395         if ( prPage->IsInvalidLayout() &&
1396              0 != (pFrm = lcl_FindFirstInvaLay( prPage, nBottom )) &&
1397              pFrm->Frm().Top() <= nBottom )
1398         {
1399             return sal_False;
1400         }
1401         if ( (prPage->IsInvalidCntnt() || prPage->IsInvalidFlyInCnt()) &&
1402              0 != (pFrm = lcl_FindFirstInvaCntnt( prPage, nBottom, 0 )) &&
1403              pFrm->Frm().Top() <= nBottom )
1404         {
1405             return sal_False;
1406         }
1407         bRet = sal_True;
1408     }
1409     return bRet;
1410 }
1411 
1412 /*************************************************************************
1413 |*
1414 |*  SwLayAction::FormatLayout(), FormatLayoutFly, FormatLayoutTab()
1415 |*
1416 |*  Ersterstellung      MA 30. Oct. 92
1417 |*  Letzte Aenderung    MA 18. May. 98
1418 |*
1419 |*************************************************************************/
1420 // OD 15.11.2002 #105155# - introduce support for vertical layout
1421 sal_Bool SwLayAction::FormatLayout( SwLayoutFrm *pLay, sal_Bool bAddRect )
1422 {
1423     ASSERT( !IsAgain(), "Ungueltige Seite beachten." );
1424     if ( IsAgain() )
1425         return sal_False;
1426 
1427     sal_Bool bChanged = sal_False;
1428     sal_Bool bAlreadyPainted = sal_False;
1429     // OD 11.11.2002 #104414# - remember frame at complete paint
1430     SwRect aFrmAtCompletePaint;
1431 
1432     if ( !pLay->IsValid() || pLay->IsCompletePaint() )
1433     {
1434         if ( pLay->GetPrev() && !pLay->GetPrev()->IsValid() )
1435             pLay->GetPrev()->SetCompletePaint();
1436 
1437         SwRect aOldRect( pLay->Frm() );
1438         pLay->Calc();
1439         if ( aOldRect != pLay->Frm() )
1440             bChanged = sal_True;
1441 
1442         sal_Bool bNoPaint = sal_False;
1443         if ( pLay->IsPageBodyFrm() &&
1444              pLay->Frm().Pos() == aOldRect.Pos() &&
1445              pLay->Lower() )
1446         {
1447             const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1448             //Einschraenkungen wegen Kopf-/Fusszeilen
1449             if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
1450                 !( pLay->IsCompletePaint() && pLay->FindPageFrm()->FindFtnCont() ) )
1451                 bNoPaint = sal_True;
1452         }
1453 
1454         if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
1455         {
1456             SwRect aPaint( pLay->Frm() );
1457             // OD 13.02.2003 #i9719#, #105645# - consider border and shadow for
1458             // page frames -> enlarge paint rectangle correspondingly.
1459             if ( pLay->IsPageFrm() )
1460             {
1461                 SwPageFrm* pPageFrm = static_cast<SwPageFrm*>(pLay);
1462                 const int nBorderWidth =
1463                         pImp->GetShell()->GetOut()->PixelToLogic( Size( pPageFrm->BorderPxWidth(), 0 ) ).Width();
1464                 const int nShadowWidth =
1465                         pImp->GetShell()->GetOut()->PixelToLogic( Size( pPageFrm->ShadowPxWidth(), 0 ) ).Width();
1466 
1467                 //mod #i6193# added sidebar width
1468                 const SwPostItMgr* pPostItMgr = pImp->GetShell()->GetPostItMgr();
1469                 const int nSidebarWidth = pPostItMgr && pPostItMgr->HasNotes() && pPostItMgr->ShowNotes() ? pPostItMgr->GetSidebarWidth() + pPostItMgr->GetSidebarBorderWidth() : 0;
1470                 switch ( pPageFrm->SidebarPosition() )
1471                 {
1472                     case sw::sidebarwindows::SIDEBAR_LEFT:
1473                     {
1474                         aPaint.Left( aPaint.Left() - nBorderWidth - nSidebarWidth);
1475                         aPaint.Right( aPaint.Right() + nBorderWidth + nShadowWidth);
1476                     }
1477                     break;
1478                     case sw::sidebarwindows::SIDEBAR_RIGHT:
1479                     {
1480                         aPaint.Left( aPaint.Left() - nBorderWidth );
1481                         aPaint.Right( aPaint.Right() + nBorderWidth + nShadowWidth + nSidebarWidth);
1482                     }
1483                     break;
1484                     case sw::sidebarwindows::SIDEBAR_NONE:
1485                         // nothing to do
1486                     break;
1487                 }
1488                 aPaint.Top( aPaint.Top() - nBorderWidth );
1489                 aPaint.Bottom( aPaint.Bottom() + nBorderWidth + nShadowWidth);
1490             }
1491 
1492             sal_Bool bPageInBrowseMode = pLay->IsPageFrm();
1493             if( bPageInBrowseMode )
1494             {
1495                 const ViewShell *pSh = pLay->getRootFrm()->GetCurrShell();
1496                 if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
1497                     bPageInBrowseMode = sal_False;
1498             }
1499             if( bPageInBrowseMode )
1500             {
1501                 // NOTE: no vertical layout in online layout
1502                 //Ist die Aenderung ueberhaupt sichtbar?
1503                 if ( pLay->IsCompletePaint() )
1504                 {
1505                     pImp->GetShell()->AddPaintRect( aPaint );
1506                     bAddRect = sal_False;
1507                 }
1508                 else
1509                 {
1510                     sal_uInt16 i;
1511 
1512                     SwRegionRects aRegion( aOldRect );
1513                     aRegion -= aPaint;
1514                     for ( i = 0; i < aRegion.Count(); ++i )
1515                         pImp->GetShell()->AddPaintRect( aRegion[i] );
1516                     aRegion.ChangeOrigin( aPaint );
1517                     aRegion.Remove( 0, aRegion.Count() );
1518                     aRegion.Insert( aPaint, 0 );
1519                     aRegion -= aOldRect;
1520                     for ( i = 0; i < aRegion.Count(); ++i )
1521                         pImp->GetShell()->AddPaintRect( aRegion[i] );
1522                 }
1523 
1524             }
1525             else
1526             {
1527                 pImp->GetShell()->AddPaintRect( aPaint );
1528                 bAlreadyPainted = sal_True;
1529                 // OD 11.11.2002 #104414# - remember frame at complete paint
1530                 aFrmAtCompletePaint = pLay->Frm();
1531             }
1532 
1533             // OD 13.02.2003 #i9719#, #105645# - provide paint of spacing
1534             // between pages (not only for in online mode).
1535             if ( pLay->IsPageFrm() )
1536             {
1537                 const SwTwips nHalfDocBorder = GAPBETWEENPAGES;
1538                 const bool bLeftToRightViewLayout = pRoot->IsLeftToRightViewLayout();
1539                 const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
1540                 const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
1541 
1542                 if ( bPrev )
1543                 {
1544                     // top
1545                     SwRect aSpaceToPrevPage( pLay->Frm() );
1546                     const SwTwips nTop = aSpaceToPrevPage.Top() - nHalfDocBorder;
1547                     if ( nTop >= 0 )
1548                         aSpaceToPrevPage.Top( nTop );
1549                     aSpaceToPrevPage.Bottom( pLay->Frm().Top() );
1550                     pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1551 
1552                     // left
1553                     aSpaceToPrevPage = pLay->Frm();
1554                     const SwTwips nLeft = aSpaceToPrevPage.Left() - nHalfDocBorder;
1555                     if ( nLeft >= 0 )
1556                         aSpaceToPrevPage.Left( nLeft );
1557                     aSpaceToPrevPage.Right( pLay->Frm().Left() );
1558                     pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1559                 }
1560                 if ( bNext )
1561                 {
1562                     // bottom
1563                     SwRect aSpaceToNextPage( pLay->Frm() );
1564                     aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
1565                     aSpaceToNextPage.Top( pLay->Frm().Bottom() );
1566                     pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1567 
1568                     // right
1569                     aSpaceToNextPage = pLay->Frm();
1570                     aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
1571                     aSpaceToNextPage.Left( pLay->Frm().Right() );
1572                     pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1573                 }
1574             }
1575         }
1576         pLay->ResetCompletePaint();
1577     }
1578 
1579     if ( IsPaint() && bAddRect &&
1580          !pLay->GetNext() && pLay->IsRetoucheFrm() && pLay->IsRetouche() )
1581     {
1582         // OD 15.11.2002 #105155# - vertical layout support
1583         SWRECTFN( pLay );
1584         SwRect aRect( pLay->GetUpper()->PaintArea() );
1585         (aRect.*fnRect->fnSetTop)( (pLay->*fnRect->fnGetPrtBottom)() );
1586         if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1587             pLay->ResetRetouche();
1588     }
1589 
1590     if( bAlreadyPainted )
1591         bAddRect = sal_False;
1592 
1593     CheckWaitCrsr();
1594 
1595     if ( IsAgain() )
1596         return sal_False;
1597 
1598     //Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
1599 
1600     if ( pLay->IsFtnFrm() ) //Hat keine LayFrms als Lower.
1601         return bChanged;
1602 
1603     SwFrm *pLow = pLay->Lower();
1604     sal_Bool bTabChanged = sal_False;
1605     while ( pLow && pLow->GetUpper() == pLay )
1606     {
1607         if ( pLow->IsLayoutFrm() )
1608         {
1609             if ( pLow->IsTabFrm() )
1610                 bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1611             // bereits zum Loeschen angemeldete Ueberspringen
1612             else if( !pLow->IsSctFrm() || ((SwSectionFrm*)pLow)->GetSection() )
1613                 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1614         }
1615         else if ( pImp->GetShell()->IsPaintLocked() )
1616             //Abkuerzung im die Zyklen zu minimieren, bei Lock kommt das
1617             //Paint sowieso (Primaer fuer Browse)
1618             pLow->OptCalc();
1619 
1620         if ( IsAgain() )
1621             return sal_False;
1622         pLow = pLow->GetNext();
1623     }
1624     // OD 11.11.2002 #104414# - add complete frame area as paint area, if frame
1625     // area has been already added and after formating its lowers the frame area
1626     // is enlarged.
1627     if ( bAlreadyPainted &&
1628          ( pLay->Frm().Width() > aFrmAtCompletePaint.Width() ||
1629            pLay->Frm().Height() > aFrmAtCompletePaint.Height() )
1630        )
1631     {
1632         pImp->GetShell()->AddPaintRect( pLay->Frm() );
1633     }
1634     return bChanged || bTabChanged;
1635 }
1636 
1637 sal_Bool SwLayAction::FormatLayoutFly( SwFlyFrm* pFly )
1638 {
1639     ASSERT( !IsAgain(), "Ungueltige Seite beachten." );
1640     if ( IsAgain() )
1641         return sal_False;
1642 
1643     sal_Bool bChanged = false;
1644     sal_Bool bAddRect = true;
1645 
1646     if ( !pFly->IsValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
1647     {
1648         //Der Frame hat sich veraendert, er wird jetzt Formatiert
1649         const SwRect aOldRect( pFly->Frm() );
1650         pFly->Calc();
1651         bChanged = aOldRect != pFly->Frm();
1652 
1653         if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
1654                     pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
1655             pImp->GetShell()->AddPaintRect( pFly->Frm() );
1656 
1657         if ( bChanged )
1658             pFly->Invalidate();
1659         else
1660             pFly->Validate();
1661 /*
1662         //mba: it's unclear why we should invalidate always, so I remove it
1663         //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
1664         if ( IsPaint() && bAddRect && pFly->Frm().Top() > 0 && pFly->Frm().Left() > 0 )
1665             pImp->GetShell()->AddPaintRect( pFly->Frm() );
1666 
1667         pFly->Invalidate();
1668 */
1669         bAddRect = false;
1670         pFly->ResetCompletePaint();
1671     }
1672 
1673     if ( IsAgain() )
1674         return sal_False;
1675 
1676     //Jetzt noch diejenigen Lowers versorgen die LayoutFrm's sind
1677     sal_Bool bTabChanged = false;
1678     SwFrm *pLow = pFly->Lower();
1679     while ( pLow )
1680     {
1681         if ( pLow->IsLayoutFrm() )
1682         {
1683             if ( pLow->IsTabFrm() )
1684                 bTabChanged |= FormatLayoutTab( (SwTabFrm*)pLow, bAddRect );
1685             else
1686                 bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1687         }
1688         pLow = pLow->GetNext();
1689     }
1690     return bChanged || bTabChanged;
1691 }
1692 
1693 // OD 31.10.2002 #104100#
1694 // Implement vertical layout support
1695 sal_Bool SwLayAction::FormatLayoutTab( SwTabFrm *pTab, sal_Bool bAddRect )
1696 {
1697     ASSERT( !IsAgain(), "8-) Ungueltige Seite beachten." );
1698     if ( IsAgain() || !pTab->Lower() )
1699         return sal_False;
1700 
1701     IDocumentTimerAccess *pTimerAccess = pRoot->GetFmt()->getIDocumentTimerAccess();
1702     pTimerAccess->BlockIdling();
1703 
1704     sal_Bool bChanged = sal_False;
1705     sal_Bool bPainted = sal_False;
1706 
1707     const SwPageFrm *pOldPage = pTab->FindPageFrm();
1708 
1709     // OD 31.10.2002 #104100# - vertical layout support
1710     // use macro to declare and init <sal_Bool bVert>, <sal_Bool bRev> and
1711     // <SwRectFn fnRect> for table frame <pTab>.
1712     SWRECTFN( pTab );
1713 
1714     if ( !pTab->IsValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
1715     {
1716         if ( pTab->GetPrev() && !pTab->GetPrev()->IsValid() )
1717         {
1718             pTab->GetPrev()->SetCompletePaint();
1719         }
1720 
1721         const SwRect aOldRect( pTab->Frm() );
1722         pTab->SetLowersFormatted( sal_False );
1723         pTab->Calc();
1724         if ( aOldRect != pTab->Frm() )
1725         {
1726             bChanged = sal_True;
1727         }
1728         const SwRect aPaintFrm = pTab->PaintArea();
1729 
1730         if ( IsPaint() && bAddRect )
1731         {
1732             // OD 01.11.2002 #104100# - add condition <pTab->Frm().HasArea()>
1733             if ( !pTab->IsCompletePaint() &&
1734                  pTab->IsComplete() &&
1735                  ( pTab->Frm().SSize() != pTab->Prt().SSize() ||
1736                    // OD 31.10.2002 #104100# - vertical layout support
1737                    (pTab->*fnRect->fnGetLeftMargin)() ) &&
1738                  pTab->Frm().HasArea()
1739                )
1740             {
1741                 // OD 01.11.2002 #104100# - re-implement calculation of margin rectangles.
1742                 SwRect aMarginRect;
1743 
1744                 SwTwips nLeftMargin = (pTab->*fnRect->fnGetLeftMargin)();
1745                 if ( nLeftMargin > 0)
1746                 {
1747                     aMarginRect = pTab->Frm();
1748                     (aMarginRect.*fnRect->fnSetWidth)( nLeftMargin );
1749                     pImp->GetShell()->AddPaintRect( aMarginRect );
1750                 }
1751 
1752                 if ( (pTab->*fnRect->fnGetRightMargin)() > 0)
1753                 {
1754                     aMarginRect = pTab->Frm();
1755                     (aMarginRect.*fnRect->fnSetLeft)( (pTab->*fnRect->fnGetPrtRight)() );
1756                     pImp->GetShell()->AddPaintRect( aMarginRect );
1757                 }
1758 
1759                 SwTwips nTopMargin = (pTab->*fnRect->fnGetTopMargin)();
1760                 if ( nTopMargin > 0)
1761                 {
1762                     aMarginRect = pTab->Frm();
1763                     (aMarginRect.*fnRect->fnSetHeight)( nTopMargin );
1764                     pImp->GetShell()->AddPaintRect( aMarginRect );
1765                 }
1766 
1767                 if ( (pTab->*fnRect->fnGetBottomMargin)() > 0)
1768                 {
1769                     aMarginRect = pTab->Frm();
1770                     (aMarginRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1771                     pImp->GetShell()->AddPaintRect( aMarginRect );
1772                 }
1773             }
1774             else if ( pTab->IsCompletePaint() )
1775             {
1776                 pImp->GetShell()->AddPaintRect( aPaintFrm );
1777                 bAddRect = sal_False;
1778                 bPainted = sal_True;
1779             }
1780 
1781             if ( pTab->IsRetouche() && !pTab->GetNext() )
1782             {
1783                 SwRect aRect( pTab->GetUpper()->PaintArea() );
1784                 // OD 04.11.2002 #104100# - vertical layout support
1785                 (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1786                 if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1787                     pTab->ResetRetouche();
1788             }
1789         }
1790         else
1791             bAddRect = sal_False;
1792 
1793         if ( pTab->IsCompletePaint() && !pOptTab )
1794             pOptTab = pTab;
1795         pTab->ResetCompletePaint();
1796     }
1797     if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
1798     {
1799         // OD 04.10.2002 #102779#
1800         // set correct rectangle for retouche: area between bottom of table frame
1801         // and bottom of paint area of the upper frame.
1802         SwRect aRect( pTab->GetUpper()->PaintArea() );
1803         // OD 04.11.2002 #104100# - vertical layout support
1804         (aRect.*fnRect->fnSetTop)( (pTab->*fnRect->fnGetPrtBottom)() );
1805         if ( !pImp->GetShell()->AddPaintRect( aRect ) )
1806             pTab->ResetRetouche();
1807     }
1808 
1809     CheckWaitCrsr();
1810 
1811     pTimerAccess->UnblockIdling();
1812 
1813     //Heftige Abkuerzung!
1814     if ( pTab->IsLowersFormatted() &&
1815          (bPainted || !pImp->GetShell()->VisArea().IsOver( pTab->Frm())) )
1816         return sal_False;
1817 
1818     //Jetzt noch die Lowers versorgen
1819     if ( IsAgain() )
1820         return sal_False;
1821 
1822     // OD 20.10.2003 #112464# - for savety reasons:
1823     // check page number before formatting lowers.
1824     if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrm()->GetPhyPageNum() + 1) )
1825         SetNextCycle( sal_True );
1826 
1827     // OD 20.10.2003 #112464# - format lowers, only if table frame is valid
1828     if ( pTab->IsValid() )
1829     {
1830         SwLayoutFrm *pLow = (SwLayoutFrm*)pTab->Lower();
1831         while ( pLow )
1832         {
1833             bChanged |= FormatLayout( (SwLayoutFrm*)pLow, bAddRect );
1834             if ( IsAgain() )
1835                 return sal_False;
1836             pLow = (SwLayoutFrm*)pLow->GetNext();
1837         }
1838     }
1839 
1840     return bChanged;
1841 }
1842 
1843 /*************************************************************************
1844 |*
1845 |*  SwLayAction::FormatCntnt()
1846 |*
1847 |*  Ersterstellung      MA 30. Oct. 92
1848 |*  Letzte Aenderung    MA 16. Nov. 95
1849 |*
1850 |*************************************************************************/
1851 sal_Bool SwLayAction::FormatCntnt( const SwPageFrm *pPage )
1852 {
1853     const SwCntntFrm *pCntnt = pPage->ContainsCntnt();
1854     const ViewShell *pSh = pRoot->GetCurrShell();
1855     const sal_Bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1856 
1857     while ( pCntnt && pPage->IsAnLower( pCntnt ) )
1858     {
1859         //Wenn der Cntnt sich eh nicht veraendert koennen wir ein paar
1860         //Abkuerzungen nutzen.
1861         const sal_Bool bFull = !pCntnt->IsValid() || pCntnt->IsCompletePaint() ||
1862                            pCntnt->IsRetouche() || pCntnt->GetDrawObjs();
1863         if ( bFull )
1864         {
1865             //Damit wir nacher nicht suchen muessen.
1866             const sal_Bool bNxtCnt = IsCalcLayout() && !pCntnt->GetFollow();
1867             const SwCntntFrm *pCntntNext = bNxtCnt ? pCntnt->GetNextCntntFrm() : 0;
1868             const SwCntntFrm *pCntntPrev = pCntnt->GetPrev() ? pCntnt->GetPrevCntntFrm() : 0;
1869 
1870             const SwLayoutFrm*pOldUpper  = pCntnt->GetUpper();
1871             const SwTabFrm *pTab = pCntnt->FindTabFrm();
1872             const sal_Bool bInValid = !pCntnt->IsValid() || pCntnt->IsCompletePaint();
1873             const sal_Bool bOldPaint = IsPaint();
1874             bPaint = bOldPaint && !(pTab && pTab == pOptTab);
1875             _FormatCntnt( pCntnt, pPage );
1876             // --> OD 2004-11-05 #i26945# - reset <bPaint> before format objects
1877             bPaint = bOldPaint;
1878             // <--
1879 
1880             // OD 2004-05-10 #i28701# - format floating screen object at content frame.
1881             // No format, if action flag <bAgain> is set or action is interrupted.
1882             // OD 2004-08-30 #117736# - allow format on interruption of action, if
1883             // it's the format for this interrupt
1884             // --> OD 2004-11-01 #i23129#, #i36347# - pass correct page frame
1885             // to the object formatter.
1886             if ( !IsAgain() &&
1887                  ( !IsInterrupt() || mbFormatCntntOnInterrupt ) &&
1888                  pCntnt->IsTxtFrm() &&
1889                  !SwObjectFormatter::FormatObjsAtFrm( *(const_cast<SwCntntFrm*>(pCntnt)),
1890                                                       *(pCntnt->FindPageFrm()), this ) )
1891             // <--
1892             {
1893                 return sal_False;
1894             }
1895 
1896             if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1897             {
1898                 const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1899                 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
1900                 if ( IsPaintExtraData() && IsPaint() &&
1901                      nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1902                     pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1903             }
1904 
1905             if ( IsAgain() )
1906                 return sal_False;
1907 
1908             //Wenn Layout oder Flys wieder Invalid sind breche ich die Verarbeitung
1909             //vorlaeufig ab - allerdings nicht fuer die BrowseView, denn dort wird
1910             //das Layout staendig ungueltig, weil die Seitenhoehe angepasst wird.
1911             //Desgleichen wenn der Benutzer weiterarbeiten will und mindestens ein
1912             //Absatz verarbeitet wurde.
1913             if ( (!pTab || (pTab && !bInValid)) )
1914             {
1915                 CheckIdleEnd();
1916                 // OD 14.04.2003 #106346# - consider interrupt formatting.
1917                 if ( ( IsInterrupt() && !mbFormatCntntOnInterrupt ) ||
1918                      ( !bBrowse && pPage->IsInvalidLayout() ) ||
1919                      // OD 07.05.2003 #109435# - consider interrupt formatting
1920                      ( IS_FLYS && IS_INVAFLY && !mbFormatCntntOnInterrupt )
1921                    )
1922                     return sal_False;
1923             }
1924             if ( pOldUpper != pCntnt->GetUpper() )
1925             {
1926                 const sal_uInt16 nCurNum = pCntnt->FindPageFrm()->GetPhyPageNum();
1927                 if (  nCurNum < pPage->GetPhyPageNum() )
1928                     nPreInvaPage = nCurNum;
1929 
1930                 //Wenn der Frm mehr als eine Seite rueckwaerts geflossen ist, so
1931                 //fangen wir nocheinmal von vorn an damit wir nichts auslassen.
1932                 if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
1933                 {
1934                     SetNextCycle( sal_True );
1935                     // OD 07.05.2003 #109435# - consider interrupt formatting
1936                     if ( !mbFormatCntntOnInterrupt )
1937                     {
1938                         return sal_False;
1939                     }
1940                 }
1941             }
1942             //Wenn der Frame die Seite vorwaerts gewechselt hat, so lassen wir
1943             //den Vorgaenger nocheinmal durchlaufen.
1944             //So werden einerseits Vorgaenger erwischt, die jetzt f?r Retouche
1945             //verantwortlich sind, andererseits werden die Fusszeilen
1946             //auch angefasst.
1947             sal_Bool bSetCntnt = sal_True;
1948             if ( pCntntPrev )
1949             {
1950                 if ( !pCntntPrev->IsValid() && pPage->IsAnLower( pCntntPrev ) )
1951                     pPage->InvalidateCntnt();
1952                 if ( pOldUpper != pCntnt->GetUpper() &&
1953                      pPage->GetPhyPageNum() < pCntnt->FindPageFrm()->GetPhyPageNum() )
1954                 {
1955                     pCntnt = pCntntPrev;
1956                     bSetCntnt = sal_False;
1957                 }
1958             }
1959             if ( bSetCntnt )
1960             {
1961                 if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
1962                      pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
1963                 {
1964                     const long nBottom = pImp->GetShell()->VisArea().Bottom();
1965                     const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
1966                                                             nBottom, pCntnt );
1967                     if ( !pTmp )
1968                     {
1969                         if ( (!(IS_FLYS && IS_INVAFLY) ||
1970                               !lcl_FindFirstInvaObj( pPage, nBottom )) &&
1971                               (!pPage->IsInvalidLayout() ||
1972                                !lcl_FindFirstInvaLay( pPage, nBottom )))
1973                             SetBrowseActionStop( sal_True );
1974                         // OD 14.04.2003 #106346# - consider interrupt formatting.
1975                         if ( !mbFormatCntntOnInterrupt )
1976                         {
1977                             return sal_False;
1978                         }
1979                     }
1980                 }
1981                 pCntnt = bNxtCnt ? pCntntNext : pCntnt->GetNextCntntFrm();
1982             }
1983 
1984             RESCHEDULE;
1985         }
1986         else
1987         {
1988             if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
1989             {
1990                 const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
1991                 ((SwTxtFrm*)pCntnt)->RecalcAllLines();
1992                 if ( IsPaintExtraData() && IsPaint() &&
1993                      nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
1994                     pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
1995             }
1996 
1997             //Falls der Frm schon vor der Abarbeitung hier formatiert wurde.
1998             if ( pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() &&
1999                   IsPaint() )
2000                 PaintCntnt( pCntnt, pPage, pCntnt->Frm(), pCntnt->Frm().Bottom());
2001             if ( IsIdle() )
2002             {
2003                 CheckIdleEnd();
2004                 // OD 14.04.2003 #106346# - consider interrupt formatting.
2005                 if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
2006                     return sal_False;
2007             }
2008             if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
2009                  pCntnt->Frm().Top() > pImp->GetShell()->VisArea().Bottom())
2010             {
2011                 const long nBottom = pImp->GetShell()->VisArea().Bottom();
2012                 const SwFrm *pTmp = lcl_FindFirstInvaCntnt( pPage,
2013                                                     nBottom, pCntnt );
2014                 if ( !pTmp )
2015                 {
2016                     if ( (!(IS_FLYS && IS_INVAFLY) ||
2017                             !lcl_FindFirstInvaObj( pPage, nBottom )) &&
2018                             (!pPage->IsInvalidLayout() ||
2019                             !lcl_FindFirstInvaLay( pPage, nBottom )))
2020                         SetBrowseActionStop( sal_True );
2021                     // OD 14.04.2003 #106346# - consider interrupt formatting.
2022                     if ( !mbFormatCntntOnInterrupt )
2023                     {
2024                         return sal_False;
2025                     }
2026                 }
2027             }
2028             pCntnt = pCntnt->GetNextCntntFrm();
2029         }
2030     }
2031     CheckWaitCrsr();
2032     // OD 14.04.2003 #106346# - consider interrupt formatting.
2033     return !IsInterrupt() || mbFormatCntntOnInterrupt;
2034 }
2035 /*************************************************************************
2036 |*
2037 |*  SwLayAction::_FormatCntnt()
2038 |*
2039 |*  Beschreibung        Returnt sal_True wenn der Absatz verarbeitet wurde,
2040 |*                      sal_False wenn es nichts zu verarbeiten gab.
2041 |*  Ersterstellung      MA 07. Dec. 92
2042 |*  Letzte Aenderung    MA 11. Mar. 98
2043 |*
2044 |*************************************************************************/
2045 void SwLayAction::_FormatCntnt( const SwCntntFrm *pCntnt,
2046                                 const SwPageFrm  *pPage )
2047 {
2048     //wird sind hier evtl. nur angekommen, weil der Cntnt DrawObjekte haelt.
2049     const sal_Bool bDrawObjsOnly = pCntnt->IsValid() && !pCntnt->IsCompletePaint() &&
2050                          !pCntnt->IsRetouche();
2051     SWRECTFN( pCntnt )
2052     if ( !bDrawObjsOnly && IsPaint() )
2053     {
2054         const SwRect aOldRect( pCntnt->UnionFrm() );
2055         const long nOldBottom = (pCntnt->*fnRect->fnGetPrtBottom)();
2056         pCntnt->OptCalc();
2057         if( IsAgain() )
2058             return;
2059         if( (*fnRect->fnYDiff)( (pCntnt->Frm().*fnRect->fnGetBottom)(),
2060                                 (aOldRect.*fnRect->fnGetBottom)() ) < 0 )
2061         {
2062             pCntnt->SetRetouche();
2063         }
2064         PaintCntnt( pCntnt, pCntnt->FindPageFrm(), aOldRect, nOldBottom);
2065     }
2066     else
2067     {
2068         if ( IsPaint() && pCntnt->IsTxtFrm() && ((SwTxtFrm*)pCntnt)->HasRepaint() )
2069             PaintCntnt( pCntnt, pPage, pCntnt->Frm(),
2070                         (pCntnt->Frm().*fnRect->fnGetBottom)() );
2071         pCntnt->OptCalc();
2072     }
2073 }
2074 
2075 /*************************************************************************
2076 |*
2077 |*  SwLayAction::_FormatFlyCntnt()
2078 |*
2079 |*  Beschreibung:
2080 |*      - Returnt sal_True wenn alle Cntnts des Flys vollstaendig verarbeitet
2081 |*        wurden. sal_False wenn vorzeitig unterbrochen wurde.
2082 |*  Ersterstellung      MA 02. Dec. 92
2083 |*  Letzte Aenderung    MA 24. Jun. 96
2084 |*
2085 |*************************************************************************/
2086 sal_Bool SwLayAction::_FormatFlyCntnt( const SwFlyFrm *pFly )
2087 {
2088     const SwCntntFrm *pCntnt = pFly->ContainsCntnt();
2089 
2090     while ( pCntnt )
2091     {
2092         // OD 2004-05-10 #i28701#
2093         _FormatCntnt( pCntnt, pCntnt->FindPageFrm() );
2094 
2095         // --> OD 2004-07-23 #i28701# - format floating screen objects
2096         // at content text frame
2097         // --> OD 2004-11-02 #i23129#, #i36347# - pass correct page frame
2098         // to the object formatter.
2099         if ( pCntnt->IsTxtFrm() &&
2100              !SwObjectFormatter::FormatObjsAtFrm(
2101                                             *(const_cast<SwCntntFrm*>(pCntnt)),
2102                                             *(pCntnt->FindPageFrm()), this ) )
2103         // <--
2104         {
2105             // restart format with first content
2106             pCntnt = pFly->ContainsCntnt();
2107             continue;
2108         }
2109         // <--
2110 
2111         if ( !pCntnt->GetValidLineNumFlag() && pCntnt->IsTxtFrm() )
2112         {
2113             const sal_uLong nAllLines = ((SwTxtFrm*)pCntnt)->GetAllLines();
2114             ((SwTxtFrm*)pCntnt)->RecalcAllLines();
2115             if ( IsPaintExtraData() && IsPaint() &&
2116                  nAllLines != ((SwTxtFrm*)pCntnt)->GetAllLines() )
2117                 pImp->GetShell()->AddPaintRect( pCntnt->Frm() );
2118         }
2119 
2120         if ( IsAgain() )
2121             return sal_False;
2122 
2123         //wenn eine Eingabe anliegt breche ich die Verarbeitung ab.
2124         if ( !pFly->IsFlyInCntFrm() )
2125         {
2126             CheckIdleEnd();
2127             // OD 14.04.2003 #106346# - consider interrupt formatting.
2128             if ( IsInterrupt() && !mbFormatCntntOnInterrupt )
2129                 return sal_False;
2130         }
2131         pCntnt = pCntnt->GetNextCntntFrm();
2132     }
2133     CheckWaitCrsr();
2134     // OD 14.04.2003 #106346# - consider interrupt formatting.
2135     return !(IsInterrupt() && !mbFormatCntntOnInterrupt);
2136 }
2137 
2138 sal_Bool SwLayAction::IsStopPrt() const
2139 {
2140     sal_Bool bResult = sal_False;
2141 
2142     if (pImp != NULL && pProgress != NULL)
2143         bResult = pImp->IsStopPrt();
2144 
2145     return bResult;
2146 }
2147 
2148 /*************************************************************************
2149 |*
2150 |*  SwLayAction::FormatSpelling(), _FormatSpelling()
2151 |*
2152 |*  Ersterstellung      AMA 01. Feb. 96
2153 |*  Letzte Aenderung    AMA 01. Feb. 96
2154 |*
2155 |*************************************************************************/
2156 sal_Bool SwLayIdle::_DoIdleJob( const SwCntntFrm *pCnt, IdleJobType eJob )
2157 {
2158     ASSERT( pCnt->IsTxtFrm(), "NoTxt neighbour of Txt" );
2159     // robust against misuse by e.g. #i52542#
2160     if( !pCnt->IsTxtFrm() )
2161         return sal_False;
2162 
2163     const SwTxtNode* pTxtNode = pCnt->GetNode()->GetTxtNode();
2164 
2165     bool bProcess = false;
2166     switch ( eJob )
2167     {
2168         case ONLINE_SPELLING :
2169             bProcess = pTxtNode->IsWrongDirty(); break;
2170         case AUTOCOMPLETE_WORDS :
2171             bProcess = pTxtNode->IsAutoCompleteWordDirty(); break;
2172         case WORD_COUNT :
2173             bProcess = pTxtNode->IsWordCountDirty(); break;
2174         case SMART_TAGS :   // SMARTTAGS
2175             bProcess = pTxtNode->IsSmartTagDirty(); break;
2176     }
2177 
2178     if( bProcess )
2179     {
2180         ViewShell *pSh = pImp->GetShell();
2181         if( STRING_LEN == nTxtPos )
2182         {
2183             --nTxtPos;
2184             if( pSh->ISA(SwCrsrShell) && !((SwCrsrShell*)pSh)->IsTableMode() )
2185             {
2186                 SwPaM *pCrsr = ((SwCrsrShell*)pSh)->GetCrsr();
2187                 if( !pCrsr->HasMark() && pCrsr == pCrsr->GetNext() )
2188                 {
2189                     pCntntNode = pCrsr->GetCntntNode();
2190                     nTxtPos =  pCrsr->GetPoint()->nContent.GetIndex();
2191                 }
2192             }
2193         }
2194 
2195         switch ( eJob )
2196         {
2197             case ONLINE_SPELLING :
2198             {
2199                 SwRect aRepaint( ((SwTxtFrm*)pCnt)->_AutoSpell( pCntntNode,  *pSh->GetViewOptions(), nTxtPos ) );
2200                 bPageValid = bPageValid && !pTxtNode->IsWrongDirty();
2201                 if( !bPageValid )
2202                     bAllValid = sal_False;
2203                 if ( aRepaint.HasArea() )
2204                     pImp->GetShell()->InvalidateWindows( aRepaint );
2205                 if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
2206                     return sal_True;
2207                 break;
2208             }
2209             case AUTOCOMPLETE_WORDS :
2210                 ((SwTxtFrm*)pCnt)->CollectAutoCmplWrds( pCntntNode, nTxtPos );
2211                 if ( Application::AnyInput( INPUT_ANY ) )
2212                     return sal_True;
2213                 break;
2214             case WORD_COUNT :
2215             {
2216                 const xub_StrLen nEnd = pTxtNode->GetTxt().Len();
2217                 SwDocStat aStat;
2218                 pTxtNode->CountWords( aStat, 0, nEnd );
2219                 if ( Application::AnyInput( INPUT_ANY ) )
2220                     return sal_True;
2221                 break;
2222             }
2223             case SMART_TAGS : // SMARTTAGS
2224             {
2225                 const SwRect aRepaint( ((SwTxtFrm*)pCnt)->SmartTagScan( pCntntNode, nTxtPos ) );
2226                 bPageValid = bPageValid && !pTxtNode->IsSmartTagDirty();
2227                 if( !bPageValid )
2228                     bAllValid = sal_False;
2229                 if ( aRepaint.HasArea() )
2230                     pImp->GetShell()->InvalidateWindows( aRepaint );
2231                 if ( Application::AnyInput( INPUT_MOUSEANDKEYBOARD|INPUT_OTHER|INPUT_PAINT ) )
2232                     return sal_True;
2233                 break;
2234             }
2235         }
2236     }
2237 
2238     //Die im Absatz verankerten Flys wollen auch mitspielen.
2239     if ( pCnt->GetDrawObjs() )
2240     {
2241         const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
2242         for ( sal_uInt16 i = 0; i < rObjs.Count(); ++i )
2243         {
2244             SwAnchoredObject* pObj = rObjs[i];
2245             if ( pObj->ISA(SwFlyFrm) )
2246             {
2247                 SwFlyFrm* pFly = static_cast<SwFlyFrm*>(pObj);
2248                 if ( pFly->IsFlyInCntFrm() )
2249                 {
2250                     const SwCntntFrm *pC = pFly->ContainsCntnt();
2251                     while( pC )
2252                     {
2253                         if ( pC->IsTxtFrm() )
2254                         {
2255                             if ( _DoIdleJob( pC, eJob ) )
2256                                 return sal_True;
2257                         }
2258                         pC = pC->GetNextCntntFrm();
2259                     }
2260                 }
2261             }
2262         }
2263     }
2264     return sal_False;
2265 }
2266 
2267 sal_Bool SwLayIdle::DoIdleJob( IdleJobType eJob, sal_Bool bVisAreaOnly )
2268 {
2269     //Spellchecken aller Inhalte der Seiten. Entweder nur der sichtbaren
2270     //Seiten oder eben aller.
2271     const ViewShell* pViewShell = pImp->GetShell();
2272     const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
2273     const SwDoc* pDoc = pViewShell->GetDoc();
2274 
2275     switch ( eJob )
2276     {
2277         case ONLINE_SPELLING :
2278             if( !pViewOptions->IsOnlineSpell() )
2279                 return sal_False;
2280             break;
2281         case AUTOCOMPLETE_WORDS :
2282             if( !pViewOptions->IsAutoCompleteWords() ||
2283                  pDoc->GetAutoCompleteWords().IsLockWordLstLocked())
2284                 return sal_False;
2285             break;
2286         case WORD_COUNT :
2287             if ( !pViewShell->getIDocumentStatistics()->GetDocStat().bModified )
2288                 return sal_False;
2289             break;
2290         case SMART_TAGS :
2291             if ( pDoc->GetDocShell()->IsHelpDocument() ||
2292                  pDoc->isXForms() ||
2293                 !SwSmartTagMgr::Get().IsSmartTagsEnabled() )
2294                 return sal_False;
2295             break;
2296         default: ASSERT( false, "Unknown idle job type" )
2297     }
2298 
2299     SwPageFrm *pPage;
2300     if ( bVisAreaOnly )
2301         pPage = pImp->GetFirstVisPage();
2302     else
2303         pPage = (SwPageFrm*)pRoot->Lower();
2304 
2305     pCntntNode = NULL;
2306     nTxtPos = STRING_LEN;
2307 
2308     while ( pPage )
2309     {
2310         bPageValid = sal_True;
2311         const SwCntntFrm *pCnt = pPage->ContainsCntnt();
2312         while( pCnt && pPage->IsAnLower( pCnt ) )
2313         {
2314             if ( _DoIdleJob( pCnt, eJob ) )
2315                 return sal_True;
2316             pCnt = pCnt->GetNextCntntFrm();
2317         }
2318         if ( pPage->GetSortedObjs() )
2319         {
2320             for ( sal_uInt16 i = 0; pPage->GetSortedObjs() &&
2321                                 i < pPage->GetSortedObjs()->Count(); ++i )
2322             {
2323                 const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
2324                 if ( pObj->ISA(SwFlyFrm) )
2325                 {
2326                     const SwFlyFrm *pFly = static_cast<const SwFlyFrm*>(pObj);
2327                     const SwCntntFrm *pC = pFly->ContainsCntnt();
2328                     while( pC )
2329                     {
2330                         if ( pC->IsTxtFrm() )
2331                         {
2332                             if ( _DoIdleJob( pC, eJob ) )
2333                                 return sal_True;
2334                         }
2335                         pC = pC->GetNextCntntFrm();
2336                     }
2337                 }
2338             }
2339         }
2340 
2341         if( bPageValid )
2342         {
2343             switch ( eJob )
2344             {
2345                 case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
2346                 case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
2347                 case WORD_COUNT : pPage->ValidateWordCount(); break;
2348                 case SMART_TAGS : pPage->ValidateSmartTags(); break; // SMARTTAGS
2349             }
2350         }
2351 
2352         pPage = (SwPageFrm*)pPage->GetNext();
2353         if ( pPage && bVisAreaOnly &&
2354              !pPage->Frm().IsOver( pImp->GetShell()->VisArea()))
2355              break;
2356     }
2357     return sal_False;
2358 }
2359 
2360 
2361 #ifdef DBG_UTIL
2362 #if OSL_DEBUG_LEVEL > 1
2363 
2364 /*************************************************************************
2365 |*
2366 |*  void SwLayIdle::SwLayIdle()
2367 |*
2368 |*  Ersterstellung      MA ??
2369 |*  Letzte Aenderung    MA 09. Jun. 94
2370 |*
2371 |*************************************************************************/
2372 void SwLayIdle::ShowIdle( ColorData eColorData )
2373 {
2374     if ( !bIndicator )
2375     {
2376         bIndicator = sal_True;
2377         Window *pWin = pImp->GetShell()->GetWin();
2378         if ( pWin )
2379         {
2380             Rectangle aRect( 0, 0, 5, 5 );
2381             aRect = pWin->PixelToLogic( aRect );
2382             // OD 2004-04-23 #116347#
2383             pWin->Push( PUSH_FILLCOLOR|PUSH_LINECOLOR );
2384             pWin->SetFillColor( eColorData );
2385             pWin->SetLineColor();
2386             pWin->DrawRect( aRect );
2387             pWin->Pop();
2388         }
2389     }
2390 }
2391 #define SHOW_IDLE( ColorData ) ShowIdle( ColorData )
2392 #else
2393 #define SHOW_IDLE( ColorData )
2394 #endif
2395 #else
2396 #define SHOW_IDLE( ColorData )
2397 #endif
2398 
2399 /*************************************************************************
2400 |*
2401 |*  void SwLayIdle::SwLayIdle()
2402 |*
2403 |*  Ersterstellung      MA 30. Oct. 92
2404 |*  Letzte Aenderung    MA 23. May. 95
2405 |*
2406 |*************************************************************************/
2407 SwLayIdle::SwLayIdle( SwRootFrm *pRt, SwViewImp *pI ) :
2408     pRoot( pRt ),
2409     pImp( pI )
2410 #ifdef DBG_UTIL
2411 #if OSL_DEBUG_LEVEL > 1
2412     , bIndicator( sal_False )
2413 #endif
2414 #endif
2415 {
2416     pImp->pIdleAct = this;
2417 
2418     SHOW_IDLE( COL_LIGHTRED );
2419 
2420     pImp->GetShell()->EnableSmooth( sal_False );
2421 
2422     //Zuerst den Sichtbaren Bereich Spellchecken, nur wenn dort nichts
2423     //zu tun war wird das IdleFormat angestossen.
2424     if ( !DoIdleJob( SMART_TAGS, sal_True ) &&
2425          !DoIdleJob( ONLINE_SPELLING, sal_True ) &&
2426          !DoIdleJob( AUTOCOMPLETE_WORDS, sal_True ) ) // SMARTTAGS
2427     {
2428         //Formatieren und ggf. Repaint-Rechtecke an der ViewShell vormerken.
2429         //Dabei muessen kuenstliche Actions laufen, damit es z.B. bei
2430         //Veraenderungen der Seitenzahl nicht zu unerwuenschten Effekten kommt.
2431         //Wir merken uns bei welchen Shells der Cursor sichtbar ist, damit
2432         //wir ihn bei Dokumentaenderung ggf. wieder sichbar machen koennen.
2433         SvBools aBools;
2434         ViewShell *pSh = pImp->GetShell();
2435         do
2436         {   ++pSh->nStartAction;
2437             sal_Bool bVis = sal_False;
2438             if ( pSh->ISA(SwCrsrShell) )
2439             {
2440 #ifdef SW_CRSR_TIMER
2441                 ((SwCrsrShell*)pSh)->ChgCrsrTimerFlag( sal_False );
2442 #endif
2443                 bVis = ((SwCrsrShell*)pSh)->GetCharRect().IsOver(pSh->VisArea());
2444             }
2445             aBools.push_back( bVis );
2446             pSh = (ViewShell*)pSh->GetNext();
2447         } while ( pSh != pImp->GetShell() );
2448 
2449         SwLayAction aAction( pRoot, pImp );
2450         aAction.SetInputType( INPUT_ANY );
2451         aAction.SetIdle( sal_True );
2452         aAction.SetWaitAllowed( sal_False );
2453         aAction.Action();
2454 
2455         //Weitere Start-/EndActions nur auf wenn irgendwo Paints aufgelaufen
2456         //sind oder wenn sich die Sichtbarkeit des CharRects veraendert hat.
2457         sal_Bool bActions = sal_False;
2458         sal_uInt16 nBoolIdx = 0;
2459         do
2460         {
2461             --pSh->nStartAction;
2462 
2463             if ( pSh->Imp()->GetRegion() )
2464                 bActions = sal_True;
2465             else
2466             {
2467                 SwRect aTmp( pSh->VisArea() );
2468                 pSh->UISizeNotify();
2469 
2470                 // --> FME 2006-08-03 #137134#
2471                 // Are we supposed to crash if pSh isn't a cursor shell?!
2472                 // bActions |= aTmp != pSh->VisArea() ||
2473                 //             aBools[nBoolIdx] != ((SwCrsrShell*)pSh)->GetCharRect().IsOver( pSh->VisArea() );
2474 
2475                 // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
2476                 // and the cursor is visible.
2477                 bActions |= aTmp != pSh->VisArea();
2478                 if ( aTmp == pSh->VisArea() && pSh->ISA(SwCrsrShell) )
2479                 {
2480                     bActions |= aBools[nBoolIdx] !=
2481                                 static_cast<SwCrsrShell*>(pSh)->GetCharRect().IsOver( pSh->VisArea() );
2482                 }
2483             }
2484 
2485             pSh = (ViewShell*)pSh->GetNext();
2486             ++nBoolIdx;
2487         } while ( pSh != pImp->GetShell() );
2488 
2489         if ( bActions )
2490         {
2491             //Start- EndActions aufsetzen. ueber die CrsrShell, damit der
2492             //Cursor/Selektion und die VisArea korrekt gesetzt werden.
2493             nBoolIdx = 0;
2494             do
2495             {
2496                 sal_Bool bCrsrShell = pSh->IsA( TYPE(SwCrsrShell) );
2497 
2498                 if ( bCrsrShell )
2499                     ((SwCrsrShell*)pSh)->SttCrsrMove();
2500 //              else
2501 //                  pSh->StartAction();
2502 
2503                 //Wenn Paints aufgelaufen sind, ist es am sinnvollsten schlicht das
2504                 //gesamte Window zu invalidieren. Anderfalls gibt es Paintprobleme
2505                 //deren Loesung unverhaeltnissmaessig aufwendig waere.
2506                 //fix(18176):
2507                 SwViewImp *pViewImp = pSh->Imp();
2508                 sal_Bool bUnlock = sal_False;
2509                 if ( pViewImp->GetRegion() )
2510                 {
2511                     pViewImp->DelRegion();
2512 
2513                     //Fuer Repaint mit virtuellem Device sorgen.
2514                     pSh->LockPaint();
2515                     bUnlock = sal_True;
2516                 }
2517 
2518                 if ( bCrsrShell )
2519                     //Wenn der Crsr sichbar war wieder sichbar machen, sonst
2520                     //EndCrsrMove mit sal_True fuer IdleEnd.
2521                     ((SwCrsrShell*)pSh)->EndCrsrMove( sal_True^aBools[nBoolIdx] );
2522 //              else
2523 //                  pSh->EndAction();
2524                 if( bUnlock )
2525                 {
2526                     if( bCrsrShell )
2527                     {
2528                         // UnlockPaint overwrite the selection from the
2529                         // CrsrShell and calls the virtual method paint
2530                         // to fill the virtual device. This fill dont have
2531                         // paint the selection! -> Set the focus flag at
2532                         // CrsrShell and it dont paint the selection.
2533                         ((SwCrsrShell*)pSh)->ShLooseFcs();
2534                         pSh->UnlockPaint( sal_True );
2535                         ((SwCrsrShell*)pSh)->ShGetFcs( sal_False );
2536                     }
2537                     else
2538                         pSh->UnlockPaint( sal_True );
2539                 }
2540 
2541                 pSh = (ViewShell*)pSh->GetNext();
2542                 ++nBoolIdx;
2543 
2544             } while ( pSh != pImp->GetShell() );
2545         }
2546 
2547         if ( !aAction.IsInterrupt() )
2548         {
2549             if ( !DoIdleJob( WORD_COUNT, sal_False ) )
2550                 if ( !DoIdleJob( SMART_TAGS, sal_False ) )
2551                     if ( !DoIdleJob( ONLINE_SPELLING, sal_False ) )
2552                         DoIdleJob( AUTOCOMPLETE_WORDS, sal_False ); // SMARTTAGS
2553         }
2554 
2555         bool bInValid = false;
2556         const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
2557         const ViewShell* pViewShell = pImp->GetShell();
2558         // See conditions in DoIdleJob()
2559         const sal_Bool bSpell     = rVOpt.IsOnlineSpell();
2560         const sal_Bool bACmplWrd  = rVOpt.IsAutoCompleteWords();
2561         const sal_Bool bWordCount = pViewShell->getIDocumentStatistics()->GetDocStat().bModified;
2562         const sal_Bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
2563                                 !pViewShell->GetDoc()->isXForms() &&
2564                                 SwSmartTagMgr::Get().IsSmartTagsEnabled(); // SMARTTAGS
2565 
2566         SwPageFrm *pPg = (SwPageFrm*)pRoot->Lower();
2567         do
2568         {
2569             bInValid = pPg->IsInvalidCntnt()    || pPg->IsInvalidLayout() ||
2570                        pPg->IsInvalidFlyCntnt() || pPg->IsInvalidFlyLayout() ||
2571                        pPg->IsInvalidFlyInCnt() ||
2572                        (bSpell && pPg->IsInvalidSpelling()) ||
2573                        (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
2574                        (bWordCount && pPg->IsInvalidWordCount()) ||
2575                        (bSmartTags && pPg->IsInvalidSmartTags()); // SMARTTAGS
2576 
2577             pPg = (SwPageFrm*)pPg->GetNext();
2578 
2579         } while ( pPg && !bInValid );
2580 
2581         if ( !bInValid )
2582         {
2583             pRoot->ResetIdleFormat();
2584             SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
2585             pDocShell->Broadcast( SfxEventHint( SW_EVENT_LAYOUT_FINISHED, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
2586         }
2587     }
2588 
2589     pImp->GetShell()->EnableSmooth( sal_True );
2590 
2591     if( pImp->IsAccessible() )
2592         pImp->FireAccessibleEvents();
2593 
2594 #ifdef DBG_UTIL
2595 #if OSL_DEBUG_LEVEL > 1
2596     if ( bIndicator && pImp->GetShell()->GetWin() )
2597     {
2598         // #i75172# Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
2599         // This should be replaced by an overlay object in the future, anyways. Since it's only for debug
2600         // purposes, it is not urgent.
2601         static bool bCheckWithoutInvalidating(true);
2602         if(bCheckWithoutInvalidating)
2603         {
2604             bIndicator = false; SHOW_IDLE( COL_LIGHTGREEN );
2605         }
2606         else
2607         {
2608             Rectangle aRect( 0, 0, 5, 5 );
2609             aRect = pImp->GetShell()->GetWin()->PixelToLogic( aRect );
2610             pImp->GetShell()->GetWin()->Invalidate( aRect );
2611         }
2612     }
2613 #endif
2614 #endif
2615 }
2616 
2617 SwLayIdle::~SwLayIdle()
2618 {
2619     pImp->pIdleAct = 0;
2620 }
2621 
2622