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