LibreOffice Module sw (master)  1
layact.cxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  * Licensed to the Apache Software Foundation (ASF) under one or more
12  * contributor license agreements. See the NOTICE file distributed
13  * with this work for additional information regarding copyright
14  * ownership. The ASF licenses this file to you under the Apache
15  * License, Version 2.0 (the "License"); you may not use this file
16  * except in compliance with the License. You may obtain a copy of
17  * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <config_features.h>
21 
22 #include <ctime>
23 #include <rootfrm.hxx>
24 #include <pagefrm.hxx>
25 #include <viewimp.hxx>
26 #include <crsrsh.hxx>
27 #include <dflyobj.hxx>
28 #include <frmatr.hxx>
29 #include <frmtool.hxx>
30 #include <dcontact.hxx>
31 #include <viewopt.hxx>
32 #include <dbg_lay.hxx>
33 #include <layouter.hxx>
34 #include <docstat.hxx>
35 #include <swevent.hxx>
37 #include <IDocumentStatistics.hxx>
39 
40 #include <sfx2/event.hxx>
41 
42 #include <ftnidx.hxx>
43 #include <vcl/svapp.hxx>
44 #include <editeng/opaqitem.hxx>
45 #include <SwSmartTagMgr.hxx>
46 #include <sal/log.hxx>
47 
48 #include <layact.hxx>
49 #include <swwait.hxx>
50 #include <fmtsrnd.hxx>
51 #include <docsh.hxx>
52 
53 #include <ndtxt.hxx>
54 #include <tabfrm.hxx>
55 #include <ftnfrm.hxx>
56 #include <txtfrm.hxx>
57 #include <notxtfrm.hxx>
58 #include <flyfrms.hxx>
59 #include <mdiexp.hxx>
60 #include <sectfrm.hxx>
61 #include <acmplwrd.hxx>
62 #include <sortedobjs.hxx>
63 #include <objectformatter.hxx>
64 #include <fntcache.hxx>
65 #include <vector>
66 
67 // Save some typing work to avoid accessing destroyed pages.
68 #define XCHECKPAGE \
69  { if ( IsAgain() ) \
70  { \
71  if( bNoLoop ) \
72  rLayoutAccess.GetLayouter()->EndLoopControl(); \
73  return; \
74  } \
75  }
76 
78 {
79  if (IsReschedule())
80  {
82  }
83  if ( !m_pWait && IsWaitAllowed() && IsPaint() &&
84  ((std::clock() - m_nStartTicks) * 1000 / CLOCKS_PER_SEC >= CLOCKS_PER_SEC/2) )
85  {
86  m_pWait.reset( new SwWait( *m_pRoot->GetFormat()->GetDoc()->GetDocShell(), true ) );
87  }
88 }
89 
90 // Time over already?
92 {
93  if ( !IsInput() )
95 }
96 
97 void SwLayAction::SetStatBar( bool bNew )
98 {
99  if ( bNew )
100  {
102  m_nEndPage += m_nEndPage * 10 / 100;
103  }
104  else
106 }
107 
108 bool SwLayAction::PaintWithoutFlys( const SwRect &rRect, const SwContentFrame *pCnt,
109  const SwPageFrame *pPage )
110 {
111  SwRegionRects aTmp( rRect );
112  const SwSortedObjs &rObjs = *pPage->GetSortedObjs();
113  const SwFlyFrame *pSelfFly = pCnt->FindFlyFrame();
114 
115  for ( size_t i = 0; i < rObjs.size() && !aTmp.empty(); ++i )
116  {
117  SdrObject *pO = rObjs[i]->DrawObj();
118  if ( dynamic_cast< const SwVirtFlyDrawObj *>( pO ) == nullptr )
119  continue;
120 
121  // do not consider invisible objects
123  if ( !rIDDMA.IsVisibleLayerId( pO->GetLayer() ) )
124  {
125  continue;
126  }
127 
128  SwFlyFrame *pFly = static_cast<SwVirtFlyDrawObj*>(pO)->GetFlyFrame();
129 
130  if ( pFly == pSelfFly || !rRect.IsOver( pFly->getFrameArea() ) )
131  continue;
132 
133  if ( pSelfFly && pSelfFly->IsLowerOf( pFly ) )
134  continue;
135 
136  if ( pFly->GetVirtDrawObj()->GetLayer() == rIDDMA.GetHellId() )
137  continue;
138 
139  if ( pSelfFly )
140  {
141  const SdrObject *pTmp = pSelfFly->GetVirtDrawObj();
142  if ( pO->GetLayer() == pTmp->GetLayer() )
143  {
144  if ( pO->GetOrdNumDirect() < pTmp->GetOrdNumDirect() )
145  // Only look at things above us, if inside the same layer
146  continue;
147  }
148  else
149  {
150  const bool bLowerOfSelf = pFly->IsLowerOf( pSelfFly );
151  if ( !bLowerOfSelf && !pFly->GetFormat()->GetOpaque().GetValue() )
152  // Things from other layers are only interesting to us if
153  // they're not transparent or lie inwards
154  continue;
155  }
156  }
157 
158  // Fly frame without a lower have to be subtracted from paint region.
159  // For checking, if fly frame contains transparent graphic or
160  // has surrounded contour, assure that fly frame has a lower
161  if ( pFly->Lower() &&
162  pFly->Lower()->IsNoTextFrame() &&
163  ( static_cast<SwNoTextFrame*>(pFly->Lower())->IsTransparent() ||
164  pFly->GetFormat()->GetSurround().IsContour() )
165  )
166  {
167  continue;
168  }
169 
170  // vcl::Region of a fly frame with transparent background or a transparent
171  // shadow have not to be subtracted from paint region
172  if ( pFly->IsBackgroundTransparent() )
173  {
174  continue;
175  }
176 
177  aTmp -= pFly->getFrameArea();
178  }
179 
180  bool bRetPaint = false;
181  for ( const auto& rRegionRect : aTmp )
182  bRetPaint |= m_pImp->GetShell()->AddPaintRect( rRegionRect );
183  return bRetPaint;
184 }
185 
186 inline bool SwLayAction::PaintContent_( const SwContentFrame *pContent,
187  const SwPageFrame *pPage,
188  const SwRect &rRect )
189 {
190  if ( rRect.HasArea() )
191  {
192  if ( pPage->GetSortedObjs() )
193  return PaintWithoutFlys( rRect, pContent, pPage );
194  else
195  return m_pImp->GetShell()->AddPaintRect( rRect );
196  }
197  return false;
198 }
199 
205  const SwPageFrame *pPage,
206  const SwRect &rOldRect,
207  long nOldBottom )
208 {
209  SwRectFnSet aRectFnSet(pCnt);
210 
211  if ( pCnt->IsCompletePaint() || !pCnt->IsTextFrame() )
212  {
213  SwRect aPaint( pCnt->GetPaintArea() );
214  if ( !PaintContent_( pCnt, pPage, aPaint ) )
215  pCnt->ResetCompletePaint();
216  }
217  else
218  {
219  // paint the area between printing bottom and frame bottom and
220  // the area left and right beside the frame, if its height changed.
221  long nOldHeight = aRectFnSet.GetHeight(rOldRect);
222  long nNewHeight = aRectFnSet.GetHeight(pCnt->getFrameArea());
223  const bool bHeightDiff = nOldHeight != nNewHeight;
224  if( bHeightDiff )
225  {
226  // consider whole potential paint area.
227  SwRect aDrawRect( pCnt->GetPaintArea() );
228  if( nOldHeight > nNewHeight )
229  nOldBottom = aRectFnSet.GetPrtBottom(*pCnt);
230  aRectFnSet.SetTop( aDrawRect, nOldBottom );
231  PaintContent_( pCnt, pPage, aDrawRect );
232  }
233  // paint content area
234  SwRect aPaintRect = static_cast<SwTextFrame*>(const_cast<SwContentFrame*>(pCnt))->GetPaintSwRect();
235  PaintContent_( pCnt, pPage, aPaintRect );
236  }
237 
238  if ( pCnt->IsRetouche() && !pCnt->GetNext() )
239  {
240  const SwFrame *pTmp = pCnt;
241  if( pCnt->IsInSct() )
242  {
243  const SwSectionFrame* pSct = pCnt->FindSctFrame();
244  if( pSct->IsRetouche() && !pSct->GetNext() )
245  pTmp = pSct;
246  }
247  SwRect aRect( pTmp->GetUpper()->GetPaintArea() );
248  aRectFnSet.SetTop( aRect, aRectFnSet.GetPrtBottom(*pTmp) );
249  if ( !PaintContent_( pCnt, pPage, aRect ) )
250  pCnt->ResetRetouche();
251  }
252 }
253 
255  m_pRoot( pRt ),
256  m_pImp( pI ),
257  m_pOptTab( nullptr ),
258  m_nPreInvaPage( USHRT_MAX ),
259  m_nStartTicks( std::clock() ),
260  m_nInputType( VclInputFlags::NONE ),
261  m_nEndPage( USHRT_MAX ),
262  m_nCheckPageNum( USHRT_MAX ),
263  m_pCurPage( nullptr ),
264  m_nTabLevel( 0 ),
265  m_nCallCount( 0 )
266 {
271  // init new flag <mbFormatContentOnInterrupt>.
273 
274  assert(!m_pImp->m_pLayAction); // there can be only one SwLayAction
275  m_pImp->m_pLayAction = this; // register there
276 }
277 
279 {
280  OSL_ENSURE( !m_pWait, "Wait object not destroyed" );
281  m_pImp->m_pLayAction = nullptr; // unregister
282 }
283 
285 {
286  m_pOptTab = nullptr;
287  m_nStartTicks = std::clock();
288  m_nInputType = VclInputFlags::NONE;
293  m_pCurPage = nullptr;
294 }
295 
297 {
298  // switching from the normal to the browser mode, empty pages may be
299  // retained for an annoyingly long time, so delete them here
300  bool bRet = false;
301  const SwViewShell *pSh = m_pRoot->GetCurrShell();
302  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
303  {
304  SwPageFrame *pPage = static_cast<SwPageFrame*>(m_pRoot->Lower());
305  do
306  {
307  if ( (pPage->GetSortedObjs() && pPage->GetSortedObjs()->size()) ||
308  pPage->ContainsContent() )
309  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
310  else
311  {
312  bRet = true;
313  SwPageFrame *pDel = pPage;
314  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
315  pDel->Cut();
316  SwFrame::DestroyFrame(pDel);
317  }
318  } while ( pPage );
319  }
320  return bRet;
321 }
322 
323 void SwLayAction::Action(OutputDevice* pRenderContext)
324 {
325  m_bActionInProgress = true;
326 
327  //TurboMode? Hands-off during idle-format
328  if ( IsPaint() && !IsIdle() && TurboAction() )
329  {
330  m_pWait.reset();
332  m_bActionInProgress = false;
334  return;
335  }
336  else if ( m_pRoot->GetTurbo() )
337  {
339  const SwFrame *pFrame = m_pRoot->GetTurbo();
340  m_pRoot->ResetTurbo();
341  pFrame->InvalidatePage();
342  }
344 
345  if ( IsCalcLayout() )
346  SetCheckPages( false );
347 
348  InternalAction(pRenderContext);
350  while ( IsAgain() )
351  {
352  m_bAgain = m_bNextCycle = false;
353  InternalAction(pRenderContext);
355  }
357 
358  m_pWait.reset();
359 
360  //Turbo-Action permitted again for all cases.
362  m_pRoot->ResetTurbo();
363 
364  SetCheckPages( true );
365 
366  m_bActionInProgress = false;
367 }
368 
370 {
371  SwContentFrame *pCnt = pPage->FindFirstBodyContent();
372  SwContentFrame *pChk = pCnt;
373  bool bPageChgd = false;
374  while ( pCnt && pCnt->IsFollow() )
375  pCnt = pCnt->FindMaster();
376  if ( pCnt && pChk != pCnt )
377  { bPageChgd = true;
378  pPage = pCnt->FindPageFrame();
379  }
380 
381  if ( !pPage->GetFormat()->GetDoc()->GetFootnoteIdxs().empty() )
382  {
383  SwFootnoteContFrame *pCont = pPage->FindFootnoteCont();
384  if ( pCont )
385  {
386  pCnt = pCont->ContainsContent();
387  pChk = pCnt;
388  while ( pCnt && pCnt->IsFollow() )
389  pCnt = static_cast<SwContentFrame*>(pCnt->FindPrev());
390  if ( pCnt && pCnt != pChk )
391  {
392  if ( bPageChgd )
393  {
394  // Use the 'topmost' page
395  SwPageFrame *pTmp = pCnt->FindPageFrame();
396  if ( pPage->GetPhyPageNum() > pTmp->GetPhyPageNum() )
397  pPage = pTmp;
398  }
399  else
400  pPage = pCnt->FindPageFrame();
401  }
402  }
403  }
404  return pPage;
405 }
406 
407 // unlock position on start and end of page
408 // layout process.
409 static void unlockPositionOfObjects( SwPageFrame *pPageFrame )
410 {
411  assert( pPageFrame );
412 
413  SwSortedObjs* pObjs = pPageFrame->GetSortedObjs();
414  if ( pObjs )
415  {
416  for (SwAnchoredObject* pObj : *pObjs)
417  {
418  pObj->UnlockPosition();
419  }
420  }
421 }
422 
424 {
425  OSL_ENSURE( m_pRoot->Lower()->IsPageFrame(), ":-( No page below the root.");
426 
427  m_pRoot->Calc(pRenderContext);
428 
429  // Figure out the first invalid page or the first one to be formatted,
430  // respectively. A complete-action means the first invalid page.
431  // However, the first page to be formatted might be the one having the
432  // number 1. If we're doing a fake formatting, the number of the first
433  // page is the number of the first visible page.
434  SwPageFrame *pPage = IsComplete() ? static_cast<SwPageFrame*>(m_pRoot->Lower()) :
435  m_pImp->GetFirstVisPage(pRenderContext);
436  if ( !pPage )
437  pPage = static_cast<SwPageFrame*>(m_pRoot->Lower());
438 
439  // If there's a first-flow-Content in the first visible page that's also a Follow,
440  // we switch the page back to the original master of that Content.
441  if ( !IsComplete() )
442  pPage = CheckFirstVisPage( pPage );
443  sal_uInt16 nFirstPageNum = pPage->GetPhyPageNum();
444 
445  while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
446  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
447 
449  bool bNoLoop = pPage && SwLayouter::StartLoopControl( m_pRoot->GetFormat()->GetDoc(), pPage );
450  sal_uInt16 nPercentPageNum = 0;
451  while ( (pPage && !IsInterrupt()) || m_nCheckPageNum != USHRT_MAX )
452  {
453  if (!pPage && m_nCheckPageNum != USHRT_MAX)
454  {
455  SwPageFrame *pPg = static_cast<SwPageFrame*>(m_pRoot->Lower());
456  while (pPg && pPg->GetPhyPageNum() < m_nCheckPageNum)
457  pPg = static_cast<SwPageFrame*>(pPg->GetNext());
458  if (pPg)
459  pPage = pPg;
460  if (!pPage)
461  break;
462 
463  SwPageFrame *pTmp = pPage->GetPrev() ?
464  static_cast<SwPageFrame*>(pPage->GetPrev()) : pPage;
465  SetCheckPages( true );
466  SwFrame::CheckPageDescs( pPage, true, &pTmp );
467  SetCheckPages( false );
469  pPage = pTmp;
470  continue;
471  }
472 
473  if ( m_nEndPage != USHRT_MAX && pPage->GetPhyPageNum() > nPercentPageNum )
474  {
475  nPercentPageNum = pPage->GetPhyPageNum();
476  ::SetProgressState( nPercentPageNum, m_pImp->GetShell()->GetDoc()->GetDocShell());
477  }
478  m_pOptTab = nullptr;
479 
480  // No Shortcut for Idle or CalcLayout
481  if ( !IsIdle() && !IsComplete() && IsShortCut( pPage ) )
482  {
484  XCHECKPAGE;
485  if ( !IsInterrupt() &&
487  {
488  if ( m_pRoot->IsAssertFlyPages() )
490  if ( m_pRoot->IsSuperfluous() )
491  {
492  bool bOld = IsAgain();
494  m_bAgain = bOld;
495  }
496  if ( IsAgain() )
497  {
498  if( bNoLoop )
499  rLayoutAccess.GetLayouter()->EndLoopControl();
500  return;
501  }
502  pPage = static_cast<SwPageFrame*>(m_pRoot->Lower());
503  while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
504  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
505  while ( pPage && pPage->GetNext() &&
506  pPage->GetPhyPageNum() < nFirstPageNum )
507  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
508  continue;
509  }
510  break;
511  }
512  else
513  {
515  XCHECKPAGE;
516 
517  while ( !IsInterrupt() && !IsNextCycle() &&
518  ((pPage->GetSortedObjs() && pPage->IsInvalidFly()) || pPage->IsInvalid()) )
519  {
520  unlockPositionOfObjects( pPage );
521 
522  SwObjectFormatter::FormatObjsAtFrame( *pPage, *pPage, this );
523  if ( !pPage->GetSortedObjs() )
524  {
525  // If there are no (more) Flys, the flags are superfluous.
526  pPage->ValidateFlyLayout();
527  pPage->ValidateFlyContent();
528  }
529  // change condition
530  while ( !IsInterrupt() && !IsNextCycle() &&
531  ( pPage->IsInvalid() ||
532  (pPage->GetSortedObjs() && pPage->IsInvalidFly()) ) )
533  {
534  PROTOCOL( pPage, PROT::FileInit, DbgAction::NONE, nullptr)
535  XCHECKPAGE;
536 
537  // new loop control
538  int nLoopControlRuns_1 = 0;
539  const int nLoopControlMax = 20;
540 
541  while ( !IsNextCycle() && pPage->IsInvalidLayout() )
542  {
543  pPage->ValidateLayout();
544 
545  if ( ++nLoopControlRuns_1 > nLoopControlMax )
546  {
547  OSL_FAIL( "LoopControl_1 in SwLayAction::InternalAction" );
548  break;
549  }
550 
551  FormatLayout( pRenderContext, pPage );
552  XCHECKPAGE;
553  }
554  // change condition
555  if ( !IsNextCycle() &&
556  ( pPage->IsInvalidContent() ||
557  (pPage->GetSortedObjs() && pPage->IsInvalidFly()) ) )
558  {
559  pPage->ValidateFlyInCnt();
560  pPage->ValidateContent();
561  pPage->ValidateFlyLayout();
562  pPage->ValidateFlyContent();
563  if ( !FormatContent( pPage ) )
564  {
565  XCHECKPAGE;
566  pPage->InvalidateContent();
567  pPage->InvalidateFlyInCnt();
568  pPage->InvalidateFlyLayout();
569  pPage->InvalidateFlyContent();
570  if ( IsBrowseActionStop() )
571  m_bInput = true;
572  }
573  }
574  if( bNoLoop )
575  rLayoutAccess.GetLayouter()->LoopControl( pPage );
576  }
577 
578  unlockPositionOfObjects( pPage );
579  }
580 
581  // A previous page may be invalid again.
582  XCHECKPAGE;
583  if ( !pPage->GetSortedObjs() )
584  {
585  // If there are no (more) Flys, the flags are superfluous.
586  pPage->ValidateFlyLayout();
587  pPage->ValidateFlyContent();
588  }
589  if ( !IsInterrupt() )
590  {
591  SetNextCycle( false );
592 
593  if ( m_nPreInvaPage != USHRT_MAX )
594  {
595  if( !IsComplete() && m_nPreInvaPage + 2 < nFirstPageNum )
596  {
598  SwPageFrame *pTmpPage = m_pImp->GetFirstVisPage(pRenderContext);
599  nFirstPageNum = pTmpPage->GetPhyPageNum();
600  if( m_nPreInvaPage < nFirstPageNum )
601  {
602  m_nPreInvaPage = nFirstPageNum;
603  pPage = pTmpPage;
604  }
605  }
606  while ( pPage->GetPrev() && pPage->GetPhyPageNum() > m_nPreInvaPage )
607  pPage = static_cast<SwPageFrame*>(pPage->GetPrev());
609  }
610 
611  while ( pPage->GetPrev() &&
612  ( static_cast<SwPageFrame*>(pPage->GetPrev())->IsInvalid() ||
613  ( static_cast<SwPageFrame*>(pPage->GetPrev())->GetSortedObjs() &&
614  static_cast<SwPageFrame*>(pPage->GetPrev())->IsInvalidFly())) &&
615  (static_cast<SwPageFrame*>(pPage->GetPrev())->GetPhyPageNum() >=
616  nFirstPageNum) )
617  {
618  pPage = static_cast<SwPageFrame*>(pPage->GetPrev());
619  }
620 
621  // Continue to the next invalid page
622  while ( pPage && !pPage->IsInvalid() &&
623  (!pPage->GetSortedObjs() || !pPage->IsInvalidFly()) )
624  {
625  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
626  }
627  if( bNoLoop )
628  rLayoutAccess.GetLayouter()->LoopControl( pPage );
629  }
630  CheckIdleEnd();
631  }
632  if ( !pPage && !IsInterrupt() &&
634  {
635  if ( m_pRoot->IsAssertFlyPages() )
637  if ( m_pRoot->IsSuperfluous() )
638  {
639  bool bOld = IsAgain();
641  m_bAgain = bOld;
642  }
643  if ( IsAgain() )
644  {
645  if( bNoLoop )
646  rLayoutAccess.GetLayouter()->EndLoopControl();
647  return;
648  }
649  pPage = static_cast<SwPageFrame*>(m_pRoot->Lower());
650  while ( pPage && !pPage->IsInvalid() && !pPage->IsInvalidFly() )
651  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
652  while ( pPage && pPage->GetNext() &&
653  pPage->GetPhyPageNum() < nFirstPageNum )
654  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
655  }
656  }
657  if ( IsInterrupt() && pPage )
658  {
659  // If we have input, we don't want to format content anymore, but
660  // we still should clean the layout.
661  // Otherwise, the following situation might arise:
662  // The user enters some text at the end of the paragraph of the last
663  // page, causing the paragraph to create a Follow for the next page.
664  // Meanwhile the user continues typing, so we have input while
665  // still formatting.
666  // The paragraph on the new page has already been partially formatted,
667  // and the new page has been fully formatted and is set to CompletePaint,
668  // but hasn't added itself to the area to be output. Then we paint,
669  // the CompletePaint of the page is reset because the new paragraph
670  // already added itself, but the borders of the page haven't been painted
671  // yet.
672  // Oh well, with the inevitable following LayAction, the page doesn't
673  // register itself, because it's (LayoutFrame) flags have been reset
674  // already - the border of the page will never be painted.
675  SwPageFrame *pPg = pPage;
676  XCHECKPAGE;
677  const SwRect &rVis = m_pImp->GetShell()->VisArea();
678 
679  while( pPg && pPg->getFrameArea().Bottom() < rVis.Top() )
680  pPg = static_cast<SwPageFrame*>(pPg->GetNext());
681  if( pPg != pPage )
682  pPg = pPg ? static_cast<SwPageFrame*>(pPg->GetPrev()) : pPage;
683 
684  // set flag for interrupt content formatting
686  long nBottom = rVis.Bottom();
687  // #i42586# - format current page, if idle action is active
688  // This is an optimization for the case that the interrupt is created by
689  // the move of a form control object, which is represented by a window.
690  while ( pPg && ( pPg->getFrameArea().Top() < nBottom ||
691  ( IsIdle() && pPg == pPage ) ) )
692  {
694 
695  XCHECKPAGE;
696 
697  // new loop control
698  int nLoopControlRuns_2 = 0;
699  const int nLoopControlMax = 20;
700 
701  // special case: interrupt content formatting
702  // conditions are incorrect and are too strict.
703  // adjust interrupt formatting to normal page formatting - see above.
704  while ( ( mbFormatContentOnInterrupt &&
705  ( pPg->IsInvalid() ||
706  ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) ) ||
707  ( !mbFormatContentOnInterrupt && pPg->IsInvalidLayout() ) )
708  {
709  XCHECKPAGE;
710  // format also at-page anchored objects
711  SwObjectFormatter::FormatObjsAtFrame( *pPg, *pPg, this );
712  if ( !pPg->GetSortedObjs() )
713  {
714  pPg->ValidateFlyLayout();
715  pPg->ValidateFlyContent();
716  }
717 
718  // new loop control
719  int nLoopControlRuns_3 = 0;
720 
721  while ( pPg->IsInvalidLayout() )
722  {
723  pPg->ValidateLayout();
724 
725  if ( ++nLoopControlRuns_3 > nLoopControlMax )
726  {
727  OSL_FAIL( "LoopControl_3 in Interrupt formatting in SwLayAction::InternalAction" );
728  break;
729  }
730 
731  FormatLayout( pRenderContext, pPg );
732  XCHECKPAGE;
733  }
734 
735  if ( mbFormatContentOnInterrupt &&
736  ( pPg->IsInvalidContent() ||
737  ( pPg->GetSortedObjs() && pPg->IsInvalidFly() ) ) )
738  {
739  pPg->ValidateFlyInCnt();
740  pPg->ValidateContent();
741  pPg->ValidateFlyLayout();
742  pPg->ValidateFlyContent();
743 
744  if ( ++nLoopControlRuns_2 > nLoopControlMax )
745  {
746  OSL_FAIL( "LoopControl_2 in Interrupt formatting in SwLayAction::InternalAction" );
747  break;
748  }
749 
750  if ( !FormatContent( pPg ) )
751  {
752  XCHECKPAGE;
753  pPg->InvalidateContent();
754  pPg->InvalidateFlyInCnt();
755  pPg->InvalidateFlyLayout();
756  pPg->InvalidateFlyContent();
757  }
758  // we are satisfied if the content is formatted once complete.
759  else
760  {
761  break;
762  }
763  }
764  }
765 
767  pPg = static_cast<SwPageFrame*>(pPg->GetNext());
768  }
769  // reset flag for special interrupt content formatting.
770  mbFormatContentOnInterrupt = false;
771  }
772  m_pOptTab = nullptr;
773  if( bNoLoop )
774  rLayoutAccess.GetLayouter()->EndLoopControl();
775 }
776 
778 {
779 
780  const SwPageFrame *pPage = nullptr;
781  if ( !pCnt->isFrameAreaDefinitionValid() || pCnt->IsCompletePaint() || pCnt->IsRetouche() )
782  {
783  const SwRect aOldRect( pCnt->UnionFrame( true ) );
784  const long nOldBottom = pCnt->getFrameArea().Top() + pCnt->getFramePrintArea().Bottom();
785  pCnt->Calc(m_pImp->GetShell()->GetOut());
786  if ( pCnt->getFrameArea().Bottom() < aOldRect.Bottom() )
787  pCnt->SetRetouche();
788 
789  pPage = pCnt->FindPageFrame();
790  PaintContent( pCnt, pPage, aOldRect, nOldBottom );
791 
792  if ( !pCnt->GetValidLineNumFlag() && pCnt->IsTextFrame() )
793  {
794  const sal_uLong nAllLines = static_cast<const SwTextFrame*>(pCnt)->GetAllLines();
795  const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pCnt))->RecalcAllLines();
796  if ( nAllLines != static_cast<const SwTextFrame*>(pCnt)->GetAllLines() )
797  {
798  if ( IsPaintExtraData() )
799  m_pImp->GetShell()->AddPaintRect( pCnt->getFrameArea() );
800  // This is to calculate the remaining LineNums on the page,
801  // and we don't stop processing here. To perform this inside RecalcAllLines
802  // would be expensive, because we would have to notify the page even
803  // in unnecessary cases (normal actions).
804  const SwContentFrame *pNxt = pCnt->GetNextContentFrame();
805  while ( pNxt &&
806  (pNxt->IsInTab() || pNxt->IsInDocBody() != pCnt->IsInDocBody()) )
807  pNxt = pNxt->GetNextContentFrame();
808  if ( pNxt )
809  pNxt->InvalidatePage();
810  }
811  return false;
812  }
813 
814  if ( pPage->IsInvalidLayout() || (pPage->GetSortedObjs() && pPage->IsInvalidFly()) )
815  return false;
816  }
817  if ( !pPage )
818  pPage = pCnt->FindPageFrame();
819 
820  // format floating screen objects at content frame.
821  if ( pCnt->IsTextFrame() &&
822  !SwObjectFormatter::FormatObjsAtFrame( *const_cast<SwContentFrame*>(pCnt),
823  *pPage, this ) )
824  {
825  return false;
826  }
827 
828  if ( pPage->IsInvalidContent() )
829  return false;
830  return true;
831 }
832 
834 {
835  bool bRet = true;
836 
837  if ( m_pRoot->GetTurbo() )
838  {
839  if ( !TurboAction_( m_pRoot->GetTurbo() ) )
840  {
841  CheckIdleEnd();
842  bRet = false;
843  }
844  m_pRoot->ResetTurbo();
845  }
846  else
847  bRet = false;
848  return bRet;
849 }
850 
851 static bool lcl_IsInvaLay( const SwFrame *pFrame, long nBottom )
852 {
853  return !pFrame->isFrameAreaDefinitionValid() ||
854  (pFrame->IsCompletePaint() && ( pFrame->getFrameArea().Top() < nBottom ) );
855 }
856 
857 static const SwFrame *lcl_FindFirstInvaLay( const SwFrame *pFrame, long nBottom )
858 {
859  OSL_ENSURE( pFrame->IsLayoutFrame(), "FindFirstInvaLay, no LayFrame" );
860 
861  if (lcl_IsInvaLay(pFrame, nBottom))
862  return pFrame;
863  pFrame = static_cast<const SwLayoutFrame*>(pFrame)->Lower();
864  while ( pFrame )
865  {
866  if ( pFrame->IsLayoutFrame() )
867  {
868  if (lcl_IsInvaLay(pFrame, nBottom))
869  return pFrame;
870  const SwFrame *pTmp;
871  if ( nullptr != (pTmp = lcl_FindFirstInvaLay( pFrame, nBottom )) )
872  return pTmp;
873  }
874  pFrame = pFrame->GetNext();
875  }
876  return nullptr;
877 }
878 
879 static const SwFrame *lcl_FindFirstInvaContent( const SwLayoutFrame *pLay, long nBottom,
880  const SwContentFrame *pFirst )
881 {
882  const SwContentFrame *pCnt = pFirst ? pFirst->GetNextContentFrame() :
883  pLay->ContainsContent();
884  while ( pCnt )
885  {
886  if ( !pCnt->isFrameAreaDefinitionValid() || pCnt->IsCompletePaint() )
887  {
888  if ( pCnt->getFrameArea().Top() <= nBottom )
889  return pCnt;
890  }
891 
892  if ( pCnt->GetDrawObjs() )
893  {
894  const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
895  for (SwAnchoredObject* pObj : rObjs)
896  {
897  if ( auto pFly = dynamic_cast< const SwFlyFrame *>( pObj ) )
898  {
899  if ( pFly->IsFlyInContentFrame() )
900  {
901  if ( static_cast<const SwFlyInContentFrame*>(pFly)->IsInvalid() ||
902  pFly->IsCompletePaint() )
903  {
904  if ( pFly->getFrameArea().Top() <= nBottom )
905  return pFly;
906  }
907  const SwFrame *pFrame = lcl_FindFirstInvaContent( pFly, nBottom, nullptr );
908  if ( pFrame && pFrame->getFrameArea().Bottom() <= nBottom )
909  return pFrame;
910  }
911  }
912  }
913  }
914  if ( pCnt->getFrameArea().Top() > nBottom && !pCnt->IsInTab() )
915  return nullptr;
916  pCnt = pCnt->GetNextContentFrame();
917  if ( !pLay->IsAnLower( pCnt ) )
918  break;
919  }
920  return nullptr;
921 }
922 
923 // consider drawing objects
924 static const SwAnchoredObject* lcl_FindFirstInvaObj( const SwPageFrame* _pPage,
925  long _nBottom )
926 {
927  OSL_ENSURE( _pPage->GetSortedObjs(), "FindFirstInvaObj, no Objs" );
928 
929  for (SwAnchoredObject* pObj : *_pPage->GetSortedObjs())
930  {
931  if ( auto pFly = dynamic_cast< const SwFlyFrame *>( pObj ) )
932  {
933  if ( pFly->getFrameArea().Top() <= _nBottom )
934  {
935  if ( pFly->IsInvalid() || pFly->IsCompletePaint() )
936  return pFly;
937 
938  const SwFrame* pTmp;
939  if ( nullptr != (pTmp = lcl_FindFirstInvaContent( pFly, _nBottom, nullptr )) &&
940  pTmp->getFrameArea().Top() <= _nBottom )
941  return pFly;
942  }
943  }
944  else if ( auto pDrawObject = dynamic_cast< const SwAnchoredDrawObject *>( pObj ) )
945  {
946  if ( !pDrawObject->IsValidPos() )
947  {
948  return pObj;
949  }
950  }
951  }
952  return nullptr;
953 }
954 
955 /* Returns True if the page lies directly below or right of the visible area.
956  *
957  * It's possible for things to change in such a way that the processing
958  * (of the caller!) has to continue with the predecessor of the passed page.
959  * The parameter might therefore get modified!
960  * For BrowseMode, you may even activate the ShortCut if the invalid content
961  * of the page lies below the visible area.
962  */
964 {
965  vcl::RenderContext* pRenderContext = m_pImp->GetShell()->GetOut();
966  bool bRet = false;
967  const SwViewShell *pSh = m_pRoot->GetCurrShell();
968  const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
969 
970  // If the page is not valid, we quickly format it, otherwise
971  // there's gonna be no end of trouble
972  if ( !prPage->isFrameAreaDefinitionValid() )
973  {
974  if ( bBrowse )
975  {
976  // format complete page
977  // Thus, loop on all lowers of the page <prPage>, instead of only
978  // format its first lower.
979  // NOTE: In online layout (bBrowse == true) a page can contain
980  // a header frame and/or a footer frame beside the body frame.
981  prPage->Calc(pRenderContext);
982  SwFrame* pPageLowerFrame = prPage->Lower();
983  while ( pPageLowerFrame )
984  {
985  pPageLowerFrame->Calc(pRenderContext);
986  pPageLowerFrame = pPageLowerFrame->GetNext();
987  }
988  }
989  else
990  FormatLayout( pSh ? pSh->GetOut() : nullptr, prPage );
991  if ( IsAgain() )
992  return false;
993  }
994 
995  const SwRect &rVis = m_pImp->GetShell()->VisArea();
996  if ( (prPage->getFrameArea().Top() >= rVis.Bottom()) ||
997  (prPage->getFrameArea().Left()>= rVis.Right()) )
998  {
999  bRet = true;
1000 
1001  // This is going to be a bit nasty: The first ContentFrame of this
1002  // page in the Body text needs formatting; if it changes the page during
1003  // that process, I need to start over a page further back, because we
1004  // have been processing a PageBreak.
1005  // Even more uncomfortable: The next ContentFrame must be formatted,
1006  // because it's possible for empty pages to exist temporarily (for example
1007  // a paragraph across multiple pages gets deleted or reduced in size).
1008 
1009  // This is irrelevant for the browser, if the last Cnt above it
1010  // isn't visible anymore.
1011 
1012  const SwPageFrame *p2ndPage = prPage;
1013  const SwContentFrame *pContent;
1014  const SwLayoutFrame* pBody = p2ndPage->FindBodyCont();
1015  if( p2ndPage->IsFootnotePage() && pBody )
1016  pBody = static_cast<const SwLayoutFrame*>(pBody->GetNext());
1017  pContent = pBody ? pBody->ContainsContent() : nullptr;
1018  while ( p2ndPage && !pContent )
1019  {
1020  p2ndPage = static_cast<const SwPageFrame*>(p2ndPage->GetNext());
1021  if( p2ndPage )
1022  {
1023  pBody = p2ndPage->FindBodyCont();
1024  if( p2ndPage->IsFootnotePage() && pBody )
1025  pBody = static_cast<const SwLayoutFrame*>(pBody->GetNext());
1026  pContent = pBody ? pBody->ContainsContent() : nullptr;
1027  }
1028  }
1029  if ( pContent )
1030  {
1031  bool bTstCnt = true;
1032  if ( bBrowse )
1033  {
1034  // Is the Cnt before already invisible?
1035  const SwFrame *pLst = pContent;
1036  if ( pLst->IsInTab() )
1037  pLst = pContent->FindTabFrame();
1038  if ( pLst->IsInSct() )
1039  pLst = pContent->FindSctFrame();
1040  pLst = pLst->FindPrev();
1041  if ( pLst &&
1042  (pLst->getFrameArea().Top() >= rVis.Bottom() ||
1043  pLst->getFrameArea().Left()>= rVis.Right()) )
1044  {
1045  bTstCnt = false;
1046  }
1047  }
1048 
1049  if ( bTstCnt )
1050  {
1051  // check after each frame calculation,
1052  // if the content frame has changed the page. If yes, no other
1053  // frame calculation is performed
1054  bool bPageChg = false;
1055 
1056  if ( pContent->IsInSct() )
1057  {
1058  const SwSectionFrame *pSct = const_cast<SwFrame*>(static_cast<SwFrame const *>(pContent))->ImplFindSctFrame();
1059  if ( !pSct->isFrameAreaDefinitionValid() )
1060  {
1061  pSct->Calc(pRenderContext);
1062  pSct->SetCompletePaint();
1063  if ( IsAgain() )
1064  return false;
1065 
1066  bPageChg = pContent->FindPageFrame() != p2ndPage &&
1067  prPage->GetPrev();
1068  }
1069  }
1070 
1071  if ( !bPageChg && !pContent->isFrameAreaDefinitionValid() )
1072  {
1073  pContent->Calc(pRenderContext);
1074  pContent->SetCompletePaint();
1075  if ( IsAgain() )
1076  return false;
1077 
1078  bPageChg = pContent->FindPageFrame() != p2ndPage &&
1079  prPage->GetPrev();
1080  }
1081 
1082  if ( !bPageChg && pContent->IsInTab() )
1083  {
1084  const SwTabFrame *pTab = const_cast<SwFrame*>(static_cast<SwFrame const *>(pContent))->ImplFindTabFrame();
1085  if ( !pTab->isFrameAreaDefinitionValid() )
1086  {
1087  pTab->Calc(pRenderContext);
1088  pTab->SetCompletePaint();
1089  if ( IsAgain() )
1090  return false;
1091 
1092  bPageChg = pContent->FindPageFrame() != p2ndPage &&
1093  prPage->GetPrev();
1094  }
1095  }
1096 
1097  if ( !bPageChg && pContent->IsInSct() )
1098  {
1099  const SwSectionFrame *pSct = const_cast<SwFrame*>(static_cast<SwFrame const *>(pContent))->ImplFindSctFrame();
1100  if ( !pSct->isFrameAreaDefinitionValid() )
1101  {
1102  pSct->Calc(pRenderContext);
1103  pSct->SetCompletePaint();
1104  if ( IsAgain() )
1105  return false;
1106 
1107  bPageChg = pContent->FindPageFrame() != p2ndPage &&
1108  prPage->GetPrev();
1109  }
1110  }
1111 
1112  if ( bPageChg )
1113  {
1114  bRet = false;
1115  const SwPageFrame* pTmp = pContent->FindPageFrame();
1116  if ( pTmp->GetPhyPageNum() < prPage->GetPhyPageNum() &&
1117  pTmp->IsInvalid() )
1118  {
1119  prPage = const_cast<SwPageFrame*>(pTmp);
1120  }
1121  else
1122  {
1123  prPage = static_cast<SwPageFrame*>(prPage->GetPrev());
1124  }
1125  }
1126  // no shortcut, if at previous page
1127  // an anchored object is registered, whose anchor is <pContent>.
1128  else if ( prPage->GetPrev() )
1129  {
1130  SwSortedObjs* pObjs =
1131  static_cast<SwPageFrame*>(prPage->GetPrev())->GetSortedObjs();
1132  if ( pObjs )
1133  {
1134  for (SwAnchoredObject* pObj : *pObjs)
1135  {
1136  if ( pObj->GetAnchorFrameContainingAnchPos() == pContent )
1137  {
1138  bRet = false;
1139  break;
1140  }
1141  }
1142  }
1143  }
1144  }
1145  }
1146  }
1147 
1148  if ( !bRet && bBrowse )
1149  {
1150  const long nBottom = rVis.Bottom();
1151  const SwAnchoredObject* pObj( nullptr );
1152  if ( prPage->GetSortedObjs() &&
1153  (prPage->IsInvalidFlyLayout() || prPage->IsInvalidFlyContent()) &&
1154  nullptr != (pObj = lcl_FindFirstInvaObj( prPage, nBottom )) &&
1155  pObj->GetObjRect().Top() <= nBottom )
1156  {
1157  return false;
1158  }
1159  const SwFrame* pFrame( nullptr );
1160  if ( prPage->IsInvalidLayout() &&
1161  nullptr != (pFrame = lcl_FindFirstInvaLay( prPage, nBottom )) &&
1162  pFrame->getFrameArea().Top() <= nBottom )
1163  {
1164  return false;
1165  }
1166  if ( (prPage->IsInvalidContent() || prPage->IsInvalidFlyInCnt()) &&
1167  nullptr != (pFrame = lcl_FindFirstInvaContent( prPage, nBottom, nullptr )) &&
1168  pFrame->getFrameArea().Top() <= nBottom )
1169  {
1170  return false;
1171  }
1172  bRet = true;
1173  }
1174  return bRet;
1175 }
1176 
1177 // introduce support for vertical layout
1178 bool SwLayAction::FormatLayout( OutputDevice *pRenderContext, SwLayoutFrame *pLay, bool bAddRect )
1179 {
1180  // save page for loop control
1181  if( pLay->IsPageFrame() && static_cast<SwPageFrame*>(pLay) != m_pCurPage )
1182  {
1183  m_nCallCount = 0;
1184  m_pCurPage = static_cast<SwPageFrame*>(pLay);
1185  }
1186  OSL_ENSURE( !IsAgain(), "Attention to the invalid page." );
1187  if ( IsAgain() )
1188  return false;
1189 
1190  bool bChanged = false;
1191  bool bAlreadyPainted = false;
1192  // remember frame at complete paint
1193  SwRect aFrameAtCompletePaint;
1194 
1195  if ( !pLay->isFrameAreaDefinitionValid() || pLay->IsCompletePaint() )
1196  {
1197  if ( pLay->GetPrev() && !pLay->GetPrev()->isFrameAreaDefinitionValid() )
1198  pLay->GetPrev()->SetCompletePaint();
1199 
1200  SwRect aOldFrame( pLay->getFrameArea() );
1201  SwRect aOldRect( aOldFrame );
1202  if( pLay->IsPageFrame() )
1203  {
1204  aOldRect = static_cast<SwPageFrame*>(pLay)->GetBoundRect(pRenderContext);
1205  }
1206 
1207  {
1208  SwFrameDeleteGuard aDeleteGuard(pLay);
1209  pLay->Calc(pRenderContext);
1210  }
1211 
1212  if ( aOldFrame != pLay->getFrameArea() )
1213  bChanged = true;
1214 
1215  bool bNoPaint = false;
1216  if ( pLay->IsPageBodyFrame() &&
1217  pLay->getFrameArea().Pos() == aOldRect.Pos() &&
1218  pLay->Lower() )
1219  {
1220  const SwViewShell *pSh = pLay->getRootFrame()->GetCurrShell();
1221  // Limitations because of headers / footers
1222  if( pSh && pSh->GetViewOptions()->getBrowseMode() &&
1223  !( pLay->IsCompletePaint() && pLay->FindPageFrame()->FindFootnoteCont() ) )
1224  bNoPaint = true;
1225  }
1226 
1227  if ( !bNoPaint && IsPaint() && bAddRect && (pLay->IsCompletePaint() || bChanged) )
1228  {
1229  SwRect aPaint( pLay->getFrameArea() );
1230  // consider border and shadow for
1231  // page frames -> enlarge paint rectangle correspondingly.
1232  if ( pLay->IsPageFrame() )
1233  {
1234  SwPageFrame* pPageFrame = static_cast<SwPageFrame*>(pLay);
1235  aPaint = pPageFrame->GetBoundRect(pRenderContext);
1236  }
1237 
1238  bool bPageInBrowseMode = pLay->IsPageFrame();
1239  if( bPageInBrowseMode )
1240  {
1241  const SwViewShell *pSh = pLay->getRootFrame()->GetCurrShell();
1242  if( !pSh || !pSh->GetViewOptions()->getBrowseMode() )
1243  bPageInBrowseMode = false;
1244  }
1245  if( bPageInBrowseMode )
1246  {
1247  // NOTE: no vertical layout in online layout
1248  // Is the change even visible?
1249  if ( pLay->IsCompletePaint() )
1250  {
1251  m_pImp->GetShell()->AddPaintRect( aPaint );
1252  bAddRect = false;
1253  }
1254  else
1255  {
1256  SwRegionRects aRegion( aOldRect );
1257  aRegion -= aPaint;
1258  for ( size_t i = 0; i < aRegion.size(); ++i )
1259  m_pImp->GetShell()->AddPaintRect( aRegion[i] );
1260  aRegion.ChangeOrigin( aPaint );
1261  aRegion.clear();
1262  aRegion.push_back( aPaint );
1263  aRegion -= aOldRect;
1264  for ( size_t i = 0; i < aRegion.size(); ++i )
1265  m_pImp->GetShell()->AddPaintRect( aRegion[i] );
1266  }
1267  }
1268  else
1269  {
1270  m_pImp->GetShell()->AddPaintRect( aPaint );
1271  bAlreadyPainted = true;
1272  // remember frame at complete paint
1273  aFrameAtCompletePaint = pLay->getFrameArea();
1274  }
1275 
1276  // provide paint of spacing
1277  // between pages (not only for in online mode).
1278  if ( pLay->IsPageFrame() )
1279  {
1280  const SwViewShell *pSh = pLay->getRootFrame()->GetCurrShell();
1281  const SwTwips nHalfDocBorder = pSh ? pSh->GetViewOptions()->GetGapBetweenPages()
1283  const bool bLeftToRightViewLayout = m_pRoot->IsLeftToRightViewLayout();
1284  const bool bPrev = bLeftToRightViewLayout ? pLay->GetPrev() : pLay->GetNext();
1285  const bool bNext = bLeftToRightViewLayout ? pLay->GetNext() : pLay->GetPrev();
1286  SwPageFrame* pPageFrame = static_cast<SwPageFrame*>(pLay);
1287  SwRect aPageRect( pLay->getFrameArea() );
1288 
1289  if(pSh)
1290  {
1292  pRenderContext,
1293  aPageRect, pPageFrame->IsLeftShadowNeeded(), pPageFrame->IsRightShadowNeeded(),
1295  }
1296 
1297  if ( bPrev )
1298  {
1299  // top
1300  SwRect aSpaceToPrevPage( aPageRect );
1301  aSpaceToPrevPage.Top( aSpaceToPrevPage.Top() - nHalfDocBorder );
1302  aSpaceToPrevPage.Bottom( pLay->getFrameArea().Top() );
1303  if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
1304  m_pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1305 
1306  // left
1307  aSpaceToPrevPage = aPageRect;
1308  aSpaceToPrevPage.Left( aSpaceToPrevPage.Left() - nHalfDocBorder );
1309  aSpaceToPrevPage.Right( pLay->getFrameArea().Left() );
1310  if(aSpaceToPrevPage.Height() > 0 && aSpaceToPrevPage.Width() > 0)
1311  m_pImp->GetShell()->AddPaintRect( aSpaceToPrevPage );
1312  }
1313  if ( bNext )
1314  {
1315  // bottom
1316  SwRect aSpaceToNextPage( aPageRect );
1317  aSpaceToNextPage.Bottom( aSpaceToNextPage.Bottom() + nHalfDocBorder );
1318  aSpaceToNextPage.Top( pLay->getFrameArea().Bottom() );
1319  if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
1320  m_pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1321 
1322  // right
1323  aSpaceToNextPage = aPageRect;
1324  aSpaceToNextPage.Right( aSpaceToNextPage.Right() + nHalfDocBorder );
1325  aSpaceToNextPage.Left( pLay->getFrameArea().Right() );
1326  if(aSpaceToNextPage.Height() > 0 && aSpaceToNextPage.Width() > 0)
1327  m_pImp->GetShell()->AddPaintRect( aSpaceToNextPage );
1328  }
1329  }
1330  }
1331  pLay->ResetCompletePaint();
1332  }
1333 
1334  if ( IsPaint() && bAddRect &&
1335  !pLay->GetNext() && pLay->IsRetoucheFrame() && pLay->IsRetouche() )
1336  {
1337  // vertical layout support
1338  SwRectFnSet aRectFnSet(pLay);
1339  SwRect aRect( pLay->GetUpper()->GetPaintArea() );
1340  aRectFnSet.SetTop( aRect, aRectFnSet.GetPrtBottom(*pLay) );
1341  if ( !m_pImp->GetShell()->AddPaintRect( aRect ) )
1342  pLay->ResetRetouche();
1343  }
1344 
1345  if( bAlreadyPainted )
1346  bAddRect = false;
1347 
1348  CheckWaitCursor();
1349 
1350  if ( IsAgain() )
1351  return false;
1352 
1353  // Now, deal with the lowers that are LayoutFrames
1354 
1355  if ( pLay->IsFootnoteFrame() ) // no LayFrames as Lower
1356  return bChanged;
1357 
1358  SwFrame *pLow = pLay->Lower();
1359  bool bTabChanged = false;
1360  while ( pLow && pLow->GetUpper() == pLay )
1361  {
1362  if ( pLow->IsLayoutFrame() )
1363  {
1364  if ( pLow->IsTabFrame() )
1365  {
1366  // loop control for embedded tables
1367  if ( m_nTabLevel > 0 && ++m_nCallCount > 50 ) {
1368  static_cast<SwTabFrame*>(pLow)->SetSplitRowDisabled();
1369  }
1370 
1371  ++m_nTabLevel;
1372  bTabChanged |= FormatLayoutTab( static_cast<SwTabFrame*>(pLow), bAddRect );
1373  --m_nTabLevel;
1374  }
1375  // Skip the ones already registered for deletion
1376  else if( !pLow->IsSctFrame() || static_cast<SwSectionFrame*>(pLow)->GetSection() )
1377  bChanged |= FormatLayout( pRenderContext, static_cast<SwLayoutFrame*>(pLow), bAddRect );
1378  }
1379  else if ( m_pImp->GetShell()->IsPaintLocked() )
1380  // Shortcut to minimize the cycles. With Lock, the
1381  // paint is coming either way (primarily for browse)
1382  pLow->OptCalc();
1383 
1384  if ( IsAgain() )
1385  return false;
1386  pLow = pLow->GetNext();
1387  }
1388  // add complete frame area as paint area, if frame
1389  // area has been already added and after formatting its lowers the frame area
1390  // is enlarged.
1391  SwRect aBoundRect(pLay->IsPageFrame() ? static_cast<SwPageFrame*>(pLay)->GetBoundRect(pRenderContext) : pLay->getFrameArea() );
1392 
1393  if ( bAlreadyPainted &&
1394  ( aBoundRect.Width() > aFrameAtCompletePaint.Width() ||
1395  aBoundRect.Height() > aFrameAtCompletePaint.Height() )
1396  )
1397  {
1398  m_pImp->GetShell()->AddPaintRect( aBoundRect );
1399  }
1400  return bChanged || bTabChanged;
1401 }
1402 
1404 {
1405  vcl::RenderContext* pRenderContext = m_pImp->GetShell()->GetOut();
1406  OSL_ENSURE( !IsAgain(), "Attention to the invalid page." );
1407  if ( IsAgain() )
1408  return;
1409 
1410  bool bChanged = false;
1411  bool bAddRect = true;
1412 
1413  if ( !pFly->isFrameAreaDefinitionValid() || pFly->IsCompletePaint() || pFly->IsInvalid() )
1414  {
1415  // The Frame has changed, now it's getting formatted.
1416  const SwRect aOldRect( pFly->getFrameArea() );
1417  pFly->Calc(pRenderContext);
1418  bChanged = aOldRect != pFly->getFrameArea();
1419 
1420  if ( IsPaint() && (pFly->IsCompletePaint() || bChanged) &&
1421  pFly->getFrameArea().Top() > 0 && pFly->getFrameArea().Left() > 0 )
1422  m_pImp->GetShell()->AddPaintRect( pFly->getFrameArea() );
1423 
1424  if ( bChanged )
1425  pFly->Invalidate();
1426  else
1427  pFly->Validate();
1428 
1429  bAddRect = false;
1430  pFly->ResetCompletePaint();
1431  }
1432 
1433  if ( IsAgain() )
1434  return;
1435 
1436  // Now, deal with the lowers that are LayoutFrames
1437  bool bTabChanged = false;
1438  SwFrame *pLow = pFly->Lower();
1439  while ( pLow )
1440  {
1441  if ( pLow->IsLayoutFrame() )
1442  {
1443  if ( pLow->IsTabFrame() )
1444  bTabChanged |= FormatLayoutTab( static_cast<SwTabFrame*>(pLow), bAddRect );
1445  else
1446  bChanged |= FormatLayout( m_pImp->GetShell()->GetOut(), static_cast<SwLayoutFrame*>(pLow), bAddRect );
1447  }
1448  pLow = pLow->GetNext();
1449  }
1450 }
1451 
1452 // Implement vertical layout support
1453 bool SwLayAction::FormatLayoutTab( SwTabFrame *pTab, bool bAddRect )
1454 {
1455  OSL_ENSURE( !IsAgain(), "8-) Attention to the invalid page." );
1456  if ( IsAgain() || !pTab->Lower() )
1457  return false;
1458 
1459  vcl::RenderContext* pRenderContext = m_pImp->GetShell()->GetOut();
1461  rTimerAccess.BlockIdling();
1462 
1463  bool bChanged = false;
1464  bool bPainted = false;
1465 
1466  const SwPageFrame *pOldPage = pTab->FindPageFrame();
1467 
1468  // vertical layout support
1469  SwRectFnSet aRectFnSet(pTab);
1470 
1471  if ( !pTab->isFrameAreaDefinitionValid() || pTab->IsCompletePaint() || pTab->IsComplete() )
1472  {
1473  if ( pTab->GetPrev() && !pTab->GetPrev()->isFrameAreaDefinitionValid() )
1474  {
1475  pTab->GetPrev()->SetCompletePaint();
1476  }
1477 
1478  const SwRect aOldRect( pTab->getFrameArea() );
1479  pTab->SetLowersFormatted( false );
1480  pTab->Calc(pRenderContext);
1481  if ( aOldRect != pTab->getFrameArea() )
1482  {
1483  bChanged = true;
1484  }
1485  const SwRect aPaintFrame = pTab->GetPaintArea();
1486 
1487  if ( IsPaint() && bAddRect )
1488  {
1489  // add condition <pTab->getFrameArea().HasArea()>
1490  if ( !pTab->IsCompletePaint() &&
1491  pTab->IsComplete() &&
1492  ( pTab->getFrameArea().SSize() != pTab->getFramePrintArea().SSize() ||
1493  // vertical layout support
1494  aRectFnSet.GetLeftMargin(*pTab) ) &&
1495  pTab->getFrameArea().HasArea()
1496  )
1497  {
1498  // re-implement calculation of margin rectangles.
1499  SwRect aMarginRect;
1500 
1501  SwTwips nLeftMargin = aRectFnSet.GetLeftMargin(*pTab);
1502  if ( nLeftMargin > 0)
1503  {
1504  aMarginRect = pTab->getFrameArea();
1505  aRectFnSet.SetWidth( aMarginRect, nLeftMargin );
1506  m_pImp->GetShell()->AddPaintRect( aMarginRect );
1507  }
1508 
1509  if ( aRectFnSet.GetRightMargin(*pTab) > 0)
1510  {
1511  aMarginRect = pTab->getFrameArea();
1512  aRectFnSet.SetLeft( aMarginRect, aRectFnSet.GetPrtRight(*pTab) );
1513  m_pImp->GetShell()->AddPaintRect( aMarginRect );
1514  }
1515 
1516  SwTwips nTopMargin = aRectFnSet.GetTopMargin(*pTab);
1517  if ( nTopMargin > 0)
1518  {
1519  aMarginRect = pTab->getFrameArea();
1520  aRectFnSet.SetHeight( aMarginRect, nTopMargin );
1521  m_pImp->GetShell()->AddPaintRect( aMarginRect );
1522  }
1523 
1524  if ( aRectFnSet.GetBottomMargin(*pTab) > 0)
1525  {
1526  aMarginRect = pTab->getFrameArea();
1527  aRectFnSet.SetTop( aMarginRect, aRectFnSet.GetPrtBottom(*pTab) );
1528  m_pImp->GetShell()->AddPaintRect( aMarginRect );
1529  }
1530  }
1531  else if ( pTab->IsCompletePaint() )
1532  {
1533  m_pImp->GetShell()->AddPaintRect( aPaintFrame );
1534  bAddRect = false;
1535  bPainted = true;
1536  }
1537 
1538  if ( pTab->IsRetouche() && !pTab->GetNext() )
1539  {
1540  SwRect aRect( pTab->GetUpper()->GetPaintArea() );
1541  // vertical layout support
1542  aRectFnSet.SetTop( aRect, aRectFnSet.GetPrtBottom(*pTab) );
1543  if ( !m_pImp->GetShell()->AddPaintRect( aRect ) )
1544  pTab->ResetRetouche();
1545  }
1546  }
1547  else
1548  bAddRect = false;
1549 
1550  if ( pTab->IsCompletePaint() && !m_pOptTab )
1551  m_pOptTab = pTab;
1552  pTab->ResetCompletePaint();
1553  }
1554  if ( IsPaint() && bAddRect && pTab->IsRetouche() && !pTab->GetNext() )
1555  {
1556  // set correct rectangle for retouche: area between bottom of table frame
1557  // and bottom of paint area of the upper frame.
1558  SwRect aRect( pTab->GetUpper()->GetPaintArea() );
1559  // vertical layout support
1560  aRectFnSet.SetTop( aRect, aRectFnSet.GetPrtBottom(*pTab) );
1561  if ( !m_pImp->GetShell()->AddPaintRect( aRect ) )
1562  pTab->ResetRetouche();
1563  }
1564 
1565  CheckWaitCursor();
1566 
1567  rTimerAccess.UnblockIdling();
1568 
1569  // Ugly shortcut!
1570  if ( pTab->IsLowersFormatted() &&
1571  (bPainted || !m_pImp->GetShell()->VisArea().IsOver( pTab->getFrameArea())) )
1572  return false;
1573 
1574  // Now, deal with the lowers
1575  if ( IsAgain() )
1576  return false;
1577 
1578  // for safety reasons:
1579  // check page number before formatting lowers.
1580  if ( pOldPage->GetPhyPageNum() > (pTab->FindPageFrame()->GetPhyPageNum() + 1) )
1581  SetNextCycle( true );
1582 
1583  // format lowers, only if table frame is valid
1584  if ( pTab->isFrameAreaDefinitionValid() )
1585  {
1586  FlowFrameJoinLockGuard tabG(pTab); // tdf#124675 prevent Join() if pTab becomes empty
1587  SwLayoutFrame *pLow = static_cast<SwLayoutFrame*>(pTab->Lower());
1588  while ( pLow )
1589  {
1590  SwFrameDeleteGuard rowG(pLow); // tdf#124675 prevent RemoveFollowFlowLine()
1591  bChanged |= FormatLayout( m_pImp->GetShell()->GetOut(), pLow, bAddRect );
1592  if ( IsAgain() )
1593  return false;
1594  pLow = static_cast<SwLayoutFrame*>(pLow->GetNext());
1595  }
1596  }
1597 
1598  return bChanged;
1599 }
1600 
1602 {
1603  const SwContentFrame *pContent = pPage->ContainsContent();
1604  const SwViewShell *pSh = m_pRoot->GetCurrShell();
1605  const bool bBrowse = pSh && pSh->GetViewOptions()->getBrowseMode();
1606 
1607  while ( pContent && pPage->IsAnLower( pContent ) )
1608  {
1609  // If the content didn't change, we can use a few shortcuts.
1610  const bool bFull = !pContent->isFrameAreaDefinitionValid() || pContent->IsCompletePaint() ||
1611  pContent->IsRetouche() || pContent->GetDrawObjs();
1612  if ( bFull )
1613  {
1614  // We do this so we don't have to search later on.
1615  const bool bNxtCnt = IsCalcLayout() && !pContent->GetFollow();
1616  const SwContentFrame *pContentNext = bNxtCnt ? pContent->GetNextContentFrame() : nullptr;
1617  const SwContentFrame *pContentPrev = pContent->GetPrev() ? pContent->GetPrevContentFrame() : nullptr;
1618 
1619  const SwLayoutFrame*pOldUpper = pContent->GetUpper();
1620  const SwTabFrame *pTab = pContent->FindTabFrame();
1621  const bool bInValid = !pContent->isFrameAreaDefinitionValid() || pContent->IsCompletePaint();
1622  const bool bOldPaint = IsPaint();
1623  m_bPaint = bOldPaint && !(pTab && pTab == m_pOptTab);
1624  FormatContent_( pContent, pPage );
1625  // reset <bPaint> before format objects
1626  m_bPaint = bOldPaint;
1627 
1628  // format floating screen object at content frame.
1629  // No format, if action flag <bAgain> is set or action is interrupted.
1630  // allow format on interruption of action, if
1631  // it's the format for this interrupt
1632  // pass correct page frame
1633  // to the object formatter.
1634  if ( !IsAgain() &&
1636  pContent->IsTextFrame() &&
1637  !SwObjectFormatter::FormatObjsAtFrame( *const_cast<SwContentFrame*>(pContent),
1638  *(pContent->FindPageFrame()), this ) )
1639  {
1640  return false;
1641  }
1642 
1643  if ( !pContent->GetValidLineNumFlag() && pContent->IsTextFrame() )
1644  {
1645  const sal_uLong nAllLines = static_cast<const SwTextFrame*>(pContent)->GetAllLines();
1646  const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pContent))->RecalcAllLines();
1647  if ( IsPaintExtraData() && IsPaint() &&
1648  nAllLines != static_cast<const SwTextFrame*>(pContent)->GetAllLines() )
1649  m_pImp->GetShell()->AddPaintRect( pContent->getFrameArea() );
1650  }
1651 
1652  if ( IsAgain() )
1653  return false;
1654 
1655  // Temporarily interrupt processing if layout or Flys become invalid again.
1656  // However not for the BrowseView: The layout is getting invalid
1657  // all the time because the page height gets adjusted.
1658  // The same applies if the user wants to continue working and at least one
1659  // paragraph has been processed.
1660  if (!pTab || !bInValid)
1661  {
1662  CheckIdleEnd();
1663  // consider interrupt formatting.
1664  if ( ( IsInterrupt() && !mbFormatContentOnInterrupt ) ||
1665  ( !bBrowse && pPage->IsInvalidLayout() ) ||
1666  // consider interrupt formatting
1667  ( pPage->GetSortedObjs() && pPage->IsInvalidFly() && !mbFormatContentOnInterrupt )
1668  )
1669  return false;
1670  }
1671  if ( pOldUpper != pContent->GetUpper() )
1672  {
1673  const sal_uInt16 nCurNum = pContent->FindPageFrame()->GetPhyPageNum();
1674  if ( nCurNum < pPage->GetPhyPageNum() )
1675  m_nPreInvaPage = nCurNum;
1676 
1677  // If the frame flowed backwards more than one page, we need to
1678  // start over again from the beginning, so nothing gets left out.
1679  if ( !IsCalcLayout() && pPage->GetPhyPageNum() > nCurNum+1 )
1680  {
1681  SetNextCycle( true );
1682  // consider interrupt formatting
1684  {
1685  return false;
1686  }
1687  }
1688  }
1689  // If the frame moved forwards to the next page, we re-run through
1690  // the predecessor.
1691  // This way, we catch predecessors which are now responsible for
1692  // retouching, but the footers will be touched also.
1693  bool bSetContent = true;
1694  if ( pContentPrev )
1695  {
1696  if ( !pContentPrev->isFrameAreaDefinitionValid() && pPage->IsAnLower( pContentPrev ) )
1697  {
1698  pPage->InvalidateContent();
1699  }
1700 
1701  if ( pOldUpper != pContent->GetUpper() &&
1702  pPage->GetPhyPageNum() < pContent->FindPageFrame()->GetPhyPageNum() )
1703  {
1704  pContent = pContentPrev;
1705  bSetContent = false;
1706  }
1707  }
1708  if ( bSetContent )
1709  {
1710  if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
1711  pContent->getFrameArea().Top() > m_pImp->GetShell()->VisArea().Bottom())
1712  {
1713  const long nBottom = m_pImp->GetShell()->VisArea().Bottom();
1714  const SwFrame *pTmp = lcl_FindFirstInvaContent( pPage,
1715  nBottom, pContent );
1716  if ( !pTmp )
1717  {
1718  if ( (!(pPage->GetSortedObjs() && pPage->IsInvalidFly()) ||
1719  !lcl_FindFirstInvaObj( pPage, nBottom )) &&
1720  (!pPage->IsInvalidLayout() ||
1721  !lcl_FindFirstInvaLay( pPage, nBottom )))
1722  SetBrowseActionStop( true );
1723  // consider interrupt formatting.
1725  {
1726  return false;
1727  }
1728  }
1729  }
1730  pContent = bNxtCnt ? pContentNext : pContent->GetNextContentFrame();
1731  }
1732 
1733  if (IsReschedule())
1734  {
1736  }
1737  }
1738  else
1739  {
1740  if ( !pContent->GetValidLineNumFlag() && pContent->IsTextFrame() )
1741  {
1742  const sal_uLong nAllLines = static_cast<const SwTextFrame*>(pContent)->GetAllLines();
1743  const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pContent))->RecalcAllLines();
1744  if ( IsPaintExtraData() && IsPaint() &&
1745  nAllLines != static_cast<const SwTextFrame*>(pContent)->GetAllLines() )
1746  m_pImp->GetShell()->AddPaintRect( pContent->getFrameArea() );
1747  }
1748 
1749  // Do this if the frame has been formatted before.
1750  if ( pContent->IsTextFrame() && static_cast<const SwTextFrame*>(pContent)->HasRepaint() &&
1751  IsPaint() )
1752  PaintContent( pContent, pPage, pContent->getFrameArea(), pContent->getFrameArea().Bottom());
1753  if ( IsIdle() )
1754  {
1755  CheckIdleEnd();
1756  // consider interrupt formatting.
1758  return false;
1759  }
1760  if ( bBrowse && !IsIdle() && !IsCalcLayout() && !IsComplete() &&
1761  pContent->getFrameArea().Top() > m_pImp->GetShell()->VisArea().Bottom())
1762  {
1763  const long nBottom = m_pImp->GetShell()->VisArea().Bottom();
1764  const SwFrame *pTmp = lcl_FindFirstInvaContent( pPage,
1765  nBottom, pContent );
1766  if ( !pTmp )
1767  {
1768  if ( (!(pPage->GetSortedObjs() && pPage->IsInvalidFly()) ||
1769  !lcl_FindFirstInvaObj( pPage, nBottom )) &&
1770  (!pPage->IsInvalidLayout() ||
1771  !lcl_FindFirstInvaLay( pPage, nBottom )))
1772  SetBrowseActionStop( true );
1773  // consider interrupt formatting.
1775  {
1776  return false;
1777  }
1778  }
1779  }
1780  pContent = pContent->GetNextContentFrame();
1781  }
1782  }
1783  CheckWaitCursor();
1784  // consider interrupt formatting.
1786 }
1787 
1788 void SwLayAction::FormatContent_( const SwContentFrame *pContent, const SwPageFrame *pPage )
1789 {
1790  // We probably only ended up here because the Content holds DrawObjects.
1791  const bool bDrawObjsOnly = pContent->isFrameAreaDefinitionValid() && !pContent->IsCompletePaint() && !pContent->IsRetouche();
1792  SwRectFnSet aRectFnSet(pContent);
1793  if ( !bDrawObjsOnly && IsPaint() )
1794  {
1795  const SwRect aOldRect( pContent->UnionFrame() );
1796  const long nOldBottom = aRectFnSet.GetPrtBottom(*pContent);
1797  pContent->OptCalc();
1798  if( IsAgain() )
1799  return;
1800  if( aRectFnSet.YDiff( aRectFnSet.GetBottom(pContent->getFrameArea()),
1801  aRectFnSet.GetBottom(aOldRect) ) < 0 )
1802  {
1803  pContent->SetRetouche();
1804  }
1805  PaintContent( pContent, pContent->FindPageFrame(), aOldRect, nOldBottom);
1806  }
1807  else
1808  {
1809  if ( IsPaint() && pContent->IsTextFrame() && static_cast<const SwTextFrame*>(pContent)->HasRepaint() )
1810  PaintContent( pContent, pPage, pContent->getFrameArea(),
1811  aRectFnSet.GetBottom(pContent->getFrameArea()) );
1812  pContent->OptCalc();
1813  }
1814 }
1815 
1817 {
1818  const SwContentFrame *pContent = pFly->ContainsContent();
1819 
1820  while ( pContent )
1821  {
1822  FormatContent_( pContent, pContent->FindPageFrame() );
1823 
1824  // format floating screen objects at content text frame
1825  // pass correct page frame to the object formatter.
1826  if ( pContent->IsTextFrame() &&
1828  *const_cast<SwContentFrame*>(pContent),
1829  *(pContent->FindPageFrame()), this ) )
1830  {
1831  // restart format with first content
1832  pContent = pFly->ContainsContent();
1833  continue;
1834  }
1835 
1836  if ( !pContent->GetValidLineNumFlag() && pContent->IsTextFrame() )
1837  {
1838  const sal_uLong nAllLines = static_cast<const SwTextFrame*>(pContent)->GetAllLines();
1839  const_cast<SwTextFrame*>(static_cast<const SwTextFrame*>(pContent))->RecalcAllLines();
1840  if ( IsPaintExtraData() && IsPaint() &&
1841  nAllLines != static_cast<const SwTextFrame*>(pContent)->GetAllLines() )
1842  m_pImp->GetShell()->AddPaintRect( pContent->getFrameArea() );
1843  }
1844 
1845  if ( IsAgain() )
1846  return;
1847 
1848  // If there's input, we interrupt processing.
1849  if ( !pFly->IsFlyInContentFrame() )
1850  {
1851  CheckIdleEnd();
1852  // consider interrupt formatting.
1854  return;
1855  }
1856  pContent = pContent->GetNextContentFrame();
1857  }
1858  CheckWaitCursor();
1859 }
1860 
1862 {
1863  OSL_ENSURE( pCnt->IsTextFrame(), "NoText neighbour of Text" );
1864  // robust against misuse by e.g. #i52542#
1865  if( !pCnt->IsTextFrame() )
1866  return false;
1867 
1868  SwTextFrame const*const pTextFrame(static_cast<SwTextFrame const*>(pCnt));
1869  // sw_redlinehide: spell check only the nodes with visible content?
1870  SwTextNode* pTextNode = const_cast<SwTextNode*>(pTextFrame->GetTextNodeForParaProps());
1871 
1872  bool bProcess = false;
1873  for (size_t i = 0; pTextNode; )
1874  {
1875  switch ( eJob )
1876  {
1877  case ONLINE_SPELLING :
1878  bProcess = pTextNode->IsWrongDirty(); break;
1879  case AUTOCOMPLETE_WORDS :
1880  bProcess = pTextNode->IsAutoCompleteWordDirty(); break;
1881  case WORD_COUNT :
1882  bProcess = pTextNode->IsWordCountDirty(); break;
1883  case SMART_TAGS :
1884  bProcess = pTextNode->IsSmartTagDirty(); break;
1885  }
1886  if (bProcess)
1887  {
1888  break;
1889  }
1890  if (sw::MergedPara const* pMerged = pTextFrame->GetMergedPara())
1891  {
1892  while (true)
1893  {
1894  ++i;
1895  if (i < pMerged->extents.size())
1896  {
1897  if (pMerged->extents[i].pNode != pTextNode)
1898  {
1899  pTextNode = pMerged->extents[i].pNode;
1900  break;
1901  }
1902  }
1903  else
1904  {
1905  pTextNode = nullptr;
1906  break;
1907  }
1908  }
1909  }
1910  else
1911  pTextNode = nullptr;
1912  }
1913 
1914  if( bProcess )
1915  {
1916  assert(pTextNode);
1917  SwViewShell *pSh = pImp->GetShell();
1918  if( COMPLETE_STRING == nTextPos )
1919  {
1920  --nTextPos;
1921  if( dynamic_cast< const SwCursorShell *>( pSh ) != nullptr && !static_cast<SwCursorShell*>(pSh)->IsTableMode() )
1922  {
1923  SwPaM *pCursor = static_cast<SwCursorShell*>(pSh)->GetCursor();
1924  if( !pCursor->HasMark() && !pCursor->IsMultiSelection() )
1925  {
1926  pContentNode = pCursor->GetContentNode();
1927  nTextPos = pCursor->GetPoint()->nContent.GetIndex();
1928  }
1929  }
1930  }
1931  sal_Int32 const nPos((pContentNode && pTextNode == pContentNode)
1932  ? nTextPos
1933  : COMPLETE_STRING);
1934 
1935  switch ( eJob )
1936  {
1937  case ONLINE_SPELLING :
1938  {
1939  SwRect aRepaint( const_cast<SwTextFrame*>(pTextFrame)->AutoSpell_(*pTextNode, nPos) );
1940  // PENDING should stop idle spell checking
1942  if ( aRepaint.HasArea() )
1943  pImp->GetShell()->InvalidateWindows( aRepaint );
1944  if (Application::AnyInput(VCL_INPUT_ANY & VclInputFlags(~VclInputFlags::TIMER)))
1945  return true;
1946  break;
1947  }
1948  case AUTOCOMPLETE_WORDS :
1949  const_cast<SwTextFrame*>(pTextFrame)->CollectAutoCmplWrds(*pTextNode, nPos);
1950  // note: bPageValid remains true here even if the cursor
1951  // position is skipped, so no PENDING state needed currently
1952  if (Application::AnyInput(VCL_INPUT_ANY & VclInputFlags(~VclInputFlags::TIMER)))
1953  return true;
1954  break;
1955  case WORD_COUNT :
1956  {
1957  const sal_Int32 nEnd = pTextNode->GetText().getLength();
1958  SwDocStat aStat;
1959  pTextNode->CountWords( aStat, 0, nEnd );
1960  if ( Application::AnyInput() )
1961  return true;
1962  break;
1963  }
1964  case SMART_TAGS :
1965  {
1966  try {
1967  const SwRect aRepaint( const_cast<SwTextFrame*>(pTextFrame)->SmartTagScan(*pTextNode) );
1968  bPageValid = bPageValid && !pTextNode->IsSmartTagDirty();
1969  if ( aRepaint.HasArea() )
1970  pImp->GetShell()->InvalidateWindows( aRepaint );
1971  } catch( const css::uno::RuntimeException& e) {
1972  // handle smarttag problems gracefully and provide diagnostics
1973  SAL_WARN( "sw.core", "SMART_TAGS: " << e);
1974  }
1975  if (Application::AnyInput(VCL_INPUT_ANY & VclInputFlags(~VclInputFlags::TIMER)))
1976  return true;
1977  break;
1978  }
1979  }
1980  }
1981 
1982  // The Flys that are anchored to the paragraph need to be considered too.
1983  if ( pCnt->GetDrawObjs() )
1984  {
1985  const SwSortedObjs &rObjs = *pCnt->GetDrawObjs();
1986  for (SwAnchoredObject* pObj : rObjs)
1987  {
1988  if ( dynamic_cast< const SwFlyFrame *>( pObj ) != nullptr )
1989  {
1990  SwFlyFrame* pFly = static_cast<SwFlyFrame*>(pObj);
1991  if ( pFly->IsFlyInContentFrame() )
1992  {
1993  const SwContentFrame *pC = pFly->ContainsContent();
1994  while( pC )
1995  {
1996  if ( pC->IsTextFrame() )
1997  {
1998  if ( DoIdleJob_( pC, eJob ) )
1999  return true;
2000  }
2001  pC = pC->GetNextContentFrame();
2002  }
2003  }
2004  }
2005  }
2006  }
2007  return false;
2008 }
2009 
2010 bool SwLayIdle::DoIdleJob( IdleJobType eJob, bool bVisAreaOnly )
2011 {
2012  // Spellcheck all contents of the pages. Either only the
2013  // visible ones or all of them.
2014  const SwViewShell* pViewShell = pImp->GetShell();
2015  const SwViewOption* pViewOptions = pViewShell->GetViewOptions();
2016  const SwDoc* pDoc = pViewShell->GetDoc();
2017 
2018  switch ( eJob )
2019  {
2020  case ONLINE_SPELLING :
2021  if( !pViewOptions->IsOnlineSpell() )
2022  return false;
2023  break;
2024  case AUTOCOMPLETE_WORDS :
2027  return false;
2028  break;
2029  case WORD_COUNT :
2030  if ( !pViewShell->getIDocumentStatistics().GetDocStat().bModified )
2031  return false;
2032  break;
2033  case SMART_TAGS :
2034  if ( pDoc->GetDocShell()->IsHelpDocument() ||
2035  pDoc->isXForms() ||
2037  return false;
2038  break;
2039  default: OSL_FAIL( "Unknown idle job type" );
2040  }
2041 
2042  SwPageFrame *pPage;
2043  if ( bVisAreaOnly )
2044  pPage = pImp->GetFirstVisPage(pViewShell->GetOut());
2045  else
2046  pPage = static_cast<SwPageFrame*>(pRoot->Lower());
2047 
2048  pContentNode = nullptr;
2050 
2051  while ( pPage )
2052  {
2053  bPageValid = true;
2054  const SwContentFrame *pCnt = pPage->ContainsContent();
2055  while( pCnt && pPage->IsAnLower( pCnt ) )
2056  {
2057  if ( DoIdleJob_( pCnt, eJob ) )
2058  return true;
2059  pCnt = pCnt->GetNextContentFrame();
2060  }
2061  if ( pPage->GetSortedObjs() )
2062  {
2063  for ( size_t i = 0; pPage->GetSortedObjs() &&
2064  i < pPage->GetSortedObjs()->size(); ++i )
2065  {
2066  const SwAnchoredObject* pObj = (*pPage->GetSortedObjs())[i];
2067  if ( auto pFly = dynamic_cast< const SwFlyFrame *>( pObj ) )
2068  {
2069  const SwContentFrame *pC = pFly->ContainsContent();
2070  while( pC )
2071  {
2072  if ( pC->IsTextFrame() )
2073  {
2074  if ( DoIdleJob_( pC, eJob ) )
2075  return true;
2076  }
2077  pC = pC->GetNextContentFrame();
2078  }
2079  }
2080  }
2081  }
2082 
2083  if( bPageValid )
2084  {
2085  switch ( eJob )
2086  {
2087  case ONLINE_SPELLING : pPage->ValidateSpelling(); break;
2088  case AUTOCOMPLETE_WORDS : pPage->ValidateAutoCompleteWords(); break;
2089  case WORD_COUNT : pPage->ValidateWordCount(); break;
2090  case SMART_TAGS : pPage->ValidateSmartTags(); break;
2091  }
2092  }
2093 
2094  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
2095  if ( pPage && bVisAreaOnly &&
2096  !pPage->getFrameArea().IsOver( pImp->GetShell()->VisArea()))
2097  break;
2098  }
2099  return false;
2100 }
2101 
2102 #if HAVE_FEATURE_DESKTOP && defined DBG_UTIL
2103 void SwLayIdle::ShowIdle( Color eColor )
2104 {
2105  if ( !m_bIndicator )
2106  {
2107  m_bIndicator = true;
2108  vcl::Window *pWin = pImp->GetShell()->GetWin();
2109  if (pWin && !pWin->SupportsDoubleBuffering()) // FIXME make this work with double-buffering
2110  {
2111  tools::Rectangle aRect( 0, 0, 5, 5 );
2112  aRect = pWin->PixelToLogic( aRect );
2113  // Depending on if idle layout is in progress or not, draw a "red square" or a "green square".
2114  pWin->Push( PushFlags::FILLCOLOR|PushFlags::LINECOLOR );
2115  pWin->SetFillColor( eColor );
2116  pWin->SetLineColor();
2117  pWin->DrawRect( aRect );
2118  pWin->Pop();
2119  }
2120  }
2121 }
2122 #define SHOW_IDLE( Color ) ShowIdle( Color )
2123 #else
2124 #define SHOW_IDLE( Color )
2125 #endif // DBG_UTIL
2126 
2128  pRoot( pRt ),
2129  pImp( pI )
2130 #ifdef DBG_UTIL
2131  , m_bIndicator( false )
2132 #endif
2133 {
2134  SAL_INFO("sw.idle", "SwLayIdle() entry");
2135 
2136  pImp->m_pIdleAct = this;
2137 
2139 
2140  pImp->GetShell()->EnableSmooth( false );
2141 
2142  // First, spellcheck the visible area. Only if there's nothing
2143  // to do there, we trigger the IdleFormat.
2144  if ( !DoIdleJob( SMART_TAGS, true ) &&
2145  !DoIdleJob( ONLINE_SPELLING, true ) &&
2146  !DoIdleJob( AUTOCOMPLETE_WORDS, true ) )
2147  {
2148  // Format, then register repaint rectangles with the SwViewShell if necessary.
2149  // This requires running artificial actions, so we don't get undesired
2150  // effects when for instance the page count gets changed.
2151  // We remember the shells where the cursor is visible, so we can make
2152  // it visible again if needed after a document change.
2153  std::vector<bool> aBools;
2154  for(SwViewShell& rSh : pImp->GetShell()->GetRingContainer())
2155  {
2156  ++rSh.mnStartAction;
2157  bool bVis = false;
2158  if ( dynamic_cast<const SwCursorShell*>( &rSh) != nullptr )
2159  {
2160  bVis = static_cast<SwCursorShell*>(&rSh)->GetCharRect().IsOver(rSh.VisArea());
2161  }
2162  aBools.push_back( bVis );
2163  }
2164 
2165  bool bInterrupt(false);
2166  {
2167  SwLayAction aAction( pRoot, pImp );
2168  aAction.SetInputType( VCL_INPUT_ANY );
2169  aAction.SetIdle( true );
2170  aAction.SetWaitAllowed( false );
2171  aAction.Action(pImp->GetShell()->GetOut());
2172  bInterrupt = aAction.IsInterrupt();
2173  }
2174 
2175  // Further start/end actions only happen if there were paints started
2176  // somewhere or if the visibility of the CharRects has changed.
2177  bool bActions = false;
2178  size_t nBoolIdx = 0;
2179  for(SwViewShell& rSh : pImp->GetShell()->GetRingContainer())
2180  {
2181  --rSh.mnStartAction;
2182 
2183  if ( rSh.Imp()->GetRegion() )
2184  bActions = true;
2185  else
2186  {
2187  SwRect aTmp( rSh.VisArea() );
2188  rSh.UISizeNotify();
2189 
2190  // Are we supposed to crash if rSh isn't a cursor shell?!
2191  // bActions |= aTmp != rSh.VisArea() ||
2192  // aBools[nBoolIdx] != ((SwCursorShell*)&rSh)->GetCharRect().IsOver( rSh.VisArea() );
2193 
2194  // aBools[ i ] is true, if the i-th shell is a cursor shell (!!!)
2195  // and the cursor is visible.
2196  bActions |= aTmp != rSh.VisArea();
2197  if ( aTmp == rSh.VisArea() && dynamic_cast<const SwCursorShell*>( &rSh) != nullptr )
2198  {
2199  bActions |= aBools[nBoolIdx] !=
2200  static_cast<SwCursorShell*>(&rSh)->GetCharRect().IsOver( rSh.VisArea() );
2201  }
2202  }
2203 
2204  ++nBoolIdx;
2205  }
2206 
2207  if ( bActions )
2208  {
2209  // Prepare start/end actions via CursorShell, so the cursor, selection
2210  // and VisArea can be set correctly.
2211  nBoolIdx = 0;
2212  for(SwViewShell& rSh : pImp->GetShell()->GetRingContainer())
2213  {
2214  SwCursorShell* pCursorShell = nullptr;
2215  if(dynamic_cast<const SwCursorShell*>( &rSh) != nullptr)
2216  pCursorShell = static_cast<SwCursorShell*>(&rSh);
2217 
2218  if ( pCursorShell )
2219  pCursorShell->SttCursorMove();
2220 
2221  // If there are accrued paints, it's best to simply invalidate
2222  // the whole window. Otherwise there would arise paint problems whose
2223  // solution would be disproportionally expensive.
2224  SwViewShellImp *pViewImp = rSh.Imp();
2225  bool bUnlock = false;
2226  if ( pViewImp->GetRegion() )
2227  {
2228  pViewImp->DelRegion();
2229 
2230  // Cause a repaint with virtual device.
2231  rSh.LockPaint();
2232  bUnlock = true;
2233  }
2234 
2235  if ( pCursorShell )
2236  // If the Cursor was visible, we need to make it visible again.
2237  // Otherwise, EndCursorMove with true for IdleEnd
2238  pCursorShell->EndCursorMove( !aBools[nBoolIdx] );
2239  if( bUnlock )
2240  {
2241  if( pCursorShell )
2242  {
2243  // UnlockPaint overwrite the selection from the
2244  // CursorShell and calls the virtual method paint
2245  // to fill the virtual device. This fill don't have
2246  // paint the selection! -> Set the focus flag at
2247  // CursorShell and it doesn't paint the selection.
2248  pCursorShell->ShellLoseFocus();
2249  pCursorShell->UnlockPaint( true );
2250  pCursorShell->ShellGetFocus();
2251  }
2252  else
2253  rSh.UnlockPaint( true );
2254  }
2255  ++nBoolIdx;
2256 
2257  }
2258  }
2259 
2260  if (!bInterrupt)
2261  {
2262  if ( !DoIdleJob( WORD_COUNT, false ) )
2263  if ( !DoIdleJob( SMART_TAGS, false ) )
2264  if ( !DoIdleJob( ONLINE_SPELLING, false ) )
2265  DoIdleJob( AUTOCOMPLETE_WORDS, false );
2266  }
2267 
2268  bool bInValid = false;
2269  const SwViewOption& rVOpt = *pImp->GetShell()->GetViewOptions();
2270  const SwViewShell* pViewShell = pImp->GetShell();
2271  // See conditions in DoIdleJob()
2272  const bool bSpell = rVOpt.IsOnlineSpell();
2273  const bool bACmplWrd = SwViewOption::IsAutoCompleteWords();
2274  const bool bWordCount = pViewShell->getIDocumentStatistics().GetDocStat().bModified;
2275  const bool bSmartTags = !pViewShell->GetDoc()->GetDocShell()->IsHelpDocument() &&
2276  !pViewShell->GetDoc()->isXForms() &&
2278 
2279  SwPageFrame *pPg = static_cast<SwPageFrame*>(pRoot->Lower());
2280  do
2281  {
2282  bInValid = pPg->IsInvalidContent() || pPg->IsInvalidLayout() ||
2283  pPg->IsInvalidFlyContent() || pPg->IsInvalidFlyLayout() ||
2284  pPg->IsInvalidFlyInCnt() ||
2285  (bSpell && pPg->IsInvalidSpelling()) ||
2286  (bACmplWrd && pPg->IsInvalidAutoCompleteWords()) ||
2287  (bWordCount && pPg->IsInvalidWordCount()) ||
2288  (bSmartTags && pPg->IsInvalidSmartTags());
2289 
2290  pPg = static_cast<SwPageFrame*>(pPg->GetNext());
2291 
2292  } while ( pPg && !bInValid );
2293 
2294  if ( !bInValid )
2295  {
2297  SfxObjectShell* pDocShell = pImp->GetShell()->GetDoc()->GetDocShell();
2298  pDocShell->Broadcast( SfxEventHint( SfxEventHintId::SwEventLayoutFinished, SwDocShell::GetEventName(STR_SW_EVENT_LAYOUT_FINISHED), pDocShell ) );
2299  // Limit lifetime of the text glyphs cache to a single run of the
2300  // layout.
2302  }
2303  }
2304 
2305  pImp->GetShell()->EnableSmooth( true );
2306 
2307  if( pImp->IsAccessible() )
2309 
2310  SAL_INFO("sw.idle", "SwLayIdle() return");
2311 
2312 #ifdef DBG_UTIL
2313  if ( m_bIndicator && pImp->GetShell()->GetWin() )
2314  {
2315  // Do not invalidate indicator, this may cause a endless loop. Instead, just repaint it
2316  // This should be replaced by an overlay object in the future, anyways. Since it's only for debug
2317  // purposes, it is not urgent.
2319  }
2320 #endif
2321 }
2322 
2324 {
2325  pImp->m_pIdleAct = nullptr;
2326 }
2327 
2328 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void InternalAction(OutputDevice *pRenderContext)
Definition: layact.cxx:423
bool IsAnLower(const SwFrame *) const
Definition: findfrm.cxx:206
vcl::RenderContext * GetOut() const
Definition: viewsh.hxx:341
bool IsInterrupt() const
Definition: layact.hxx:145
bool IsPaintLocked() const
Definition: viewsh.hxx:471
bool IsContour() const
Definition: fmtsrnd.hxx:53
const SwVirtFlyDrawObj * GetVirtDrawObj() const
Definition: fly.cxx:2725
Base class of the Writer layout elements.
Definition: frame.hxx:295
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:149
void SwClearFntCacheTextGlyphs()
Clears the pre-calculated text glyphs in all SwFntObj instances.
Definition: fntcache.cxx:2693
bool PaintWithoutFlys(const SwRect &, const SwContentFrame *, const SwPageFrame *)
Definition: layact.cxx:108
void FireAccessibleEvents()
Fire all accessible events that have been collected so far.
Definition: viewimp.cxx:457
void DelRegion()
Definition: viewimp.cxx:122
bool IsFollow() const
Definition: flowfrm.hxx:166
bool m_bBrowseActionStop
Definition: layact.hxx:92
bool m_bCalcLayout
Definition: layact.hxx:84
virtual const SwFlyFrameFormat * GetFormat() const override
Definition: fly.cxx:2814
const SwSortedObjs * GetDrawObjs() const
Definition: frame.hxx:543
const SwPageFrame * m_pCurPage
Definition: layact.hxx:101
static const SwAnchoredObject * lcl_FindFirstInvaObj(const SwPageFrame *_pPage, long _nBottom)
Definition: layact.cxx:924
SwContentFrame * GetNextContentFrame() const
Definition: cntfrm.hxx:97
bool IsMultiSelection() const
Definition: pam.hxx:272
bool IsInDocBody() const
Definition: frame.hxx:919
void SetNextCycle(bool bNew)
Definition: layact.hxx:136
void DeleteEmptySct()
Definition: rootfrm.hxx:375
bool FormatLayout(OutputDevice *pRenderContext, SwLayoutFrame *, bool bAddRect=true)
Definition: layact.cxx:1178
void ShowIdle(Color eName)
void LoopControl(SwPageFrame *pPage)
Definition: layouter.cxx:236
bool TurboAction_(const SwContentFrame *)
Definition: layact.cxx:777
bool IsInSct() const
Definition: frame.hxx:943
void SetLowersFormatted(bool b)
Definition: tabfrm.hxx:150
const IDocumentStatistics & getIDocumentStatistics() const
Provides access to the document statistics interface.
Definition: viewsh.cxx:2602
bool IsComplete()
Definition: tabfrm.hxx:145
bool IsLowerOf(const SwLayoutFrame *pUpper) const
Definition: fly.cxx:2113
bool FormatLayoutTab(SwTabFrame *, bool bAddRect)
Definition: layact.cxx:1453
const OUString & GetText() const
Definition: ndtxt.hxx:211
static void CheckPageDescs(SwPageFrame *pStart, bool bNotifyFields=true, SwPageFrame **ppPrev=nullptr)
Check all pages (starting from the given one) if they use the right frame format. ...
Definition: pagechg.cxx:1004
void ResetTurboFlag() const
Definition: rootfrm.hxx:343
static SwAutoCompleteWord & GetAutoCompleteWords()
Definition: doc.hxx:1521
bool IsInvalidWordCount() const
Definition: pagefrm.hxx:224
void SetInputType(VclInputFlags nNew)
Definition: layact.hxx:153
bool IsWrongDirty() const
Definition: txtedt.cxx:2250
SwDocShell * GetDocShell()
Definition: doc.hxx:1340
bool m_bComplete
Definition: layact.hxx:83
constexpr::Color COL_LIGHTGREEN(0x00, 0xFF, 0x00)
void FormatFlyContent(const SwFlyFrame *)
Definition: layact.cxx:1816
void ValidateSpelling() const
Definition: pagefrm.hxx:403
void SetCompletePaint() const
Definition: frame.hxx:970
bool IsWaitAllowed() const
Definition: layact.hxx:138
#define PROTOCOL(pFrame, nFunc, nAct, pPar)
Definition: dbg_lay.hxx:88
bool DoIdleJob(IdleJobType, bool bVisAreaOnly)
Definition: layact.cxx:2010
sal_uIntPtr sal_uLong
sal_uInt16 m_nTabLevel
Definition: layact.hxx:102
const SwRect & getFramePrintArea() const
Definition: frame.hxx:176
Handle the background jobs of a Writer document.
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:30
sw::MergedPara * GetMergedPara()
Definition: txtfrm.hxx:438
static bool IsAutoCompleteWords()
Definition: viewopt.cxx:318
bool m_bReschedule
Definition: layact.hxx:89
const SwRect UnionFrame(bool bBorder=false) const
|* The unionframe is the framearea (getFrameArea()) of a frame expanded by the |* printarea...
Definition: ssfrm.cxx:713
Definition: doc.hxx:185
SwFrame * FindPrev()
Definition: frame.hxx:1131
bool IsComplete() const
Definition: layact.hxx:168
void ShellLoseFocus()
Definition: crsrsh.cxx:2330
void ValidateFlyContent() const
Definition: pagefrm.hxx:387
SwRootFrame * m_pRoot
Definition: layact.hxx:57
void ValidateContent() const
Definition: pagefrm.hxx:399
bool IsLeftToRightViewLayout() const
Definition: pagechg.cxx:2399
void Height(long nNew)
Definition: swrect.hxx:189
bool m_bPaintExtraData
Definition: layact.hxx:94
long GetBottom(const SwRect &rRect) const
Definition: frame.hxx:1339
sw::sidebarwindows::SidebarPosition SidebarPosition() const
asks the page on which side a margin should be shown, e.g for notes returns true for left side...
Definition: pagechg.cxx:1374
long SwTwips
Definition: swtypes.hxx:49
SwLayAction * m_pLayAction
Definition: viewimp.hxx:71
bool GetValidLineNumFlag() const
Definition: frame.hxx:740
void Invalidate() const
Definition: flyfrm.hxx:187
constexpr::Color COL_LIGHTRED(0xFF, 0x00, 0x00)
static void DestroyFrame(SwFrame *const pFrame)
this is the only way to delete a SwFrame instance
Definition: ssfrm.cxx:382
bool IsSmartTagDirty() const
Definition: txtedt.cxx:2276
static bool StartLoopControl(SwDoc *pDoc, SwPageFrame const *pPage)
Definition: layouter.cxx:290
void Pos(const Point &rNew)
Definition: swrect.hxx:167
bool IsBackgroundTransparent() const
SwFlyFrame::IsBackgroundTransparent.
Definition: paintfrm.cxx:3697
bool IsAccessible() const
Is this view accessible?
Definition: viewimp.hxx:220
virtual void Calc(vcl::RenderContext *pRenderContext) const
Definition: trvlfrm.cxx:1787
bool IsFootnotePage() const
Foot note interface.
Definition: pagefrm.hxx:184
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
void AssertFlyPages()
Ensures that enough pages exist, so that all page bound frames and draw objects can be placed...
Definition: pagechg.cxx:1516
SwContentFrame * FindFirstBodyContent()
Definition: pagefrm.hxx:332
bool IsLowersFormatted() const
Definition: tabfrm.hxx:149
IDocumentTimerAccess & getIDocumentTimerAccess()
Provides access to the document idle timer interface.
Definition: format.cxx:764
The root element of a Writer document layout.
Definition: rootfrm.hxx:79
void SetIdle(bool bNew)
Definition: layact.hxx:133
bool IsCalcLayout() const
Definition: layact.hxx:170
void InvalidateFlyInCnt() const
Definition: pagefrm.hxx:354
bool IsFootnoteFrame() const
Definition: frame.hxx:1178
bool isFrameAreaDefinitionValid() const
Definition: frame.hxx:167
SwRootFrame * pRoot
Definition: layact.hxx:191
bool m_bAgain
Definition: layact.hxx:85
VclInputFlags
const SwPageFrame * GetFirstVisPage(OutputDevice const *pRenderContext) const
Management of the first visible Page.
Definition: viewimp.cxx:276
void EnableSmooth(bool b)
Definition: viewsh.hxx:250
void PaintContent(const SwContentFrame *, const SwPageFrame *, const SwRect &rOldRect, long nOldBottom)
Depending of the type, the Content is output according to its changes, or the area to be outputted is...
Definition: layact.cxx:204
void ValidateWordCount() const
Definition: pagefrm.hxx:416
bool IsReschedule() const
Definition: layact.hxx:143
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:189
bool RemoveEmptyBrowserPages()
Definition: layact.cxx:296
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
SwSectionFrame * ImplFindSctFrame()
Definition: findfrm.cxx:480
long YDiff(long n1, long n2) const
Definition: frame.hxx:1384
bool AddPaintRect(const SwRect &rRect)
Definition: viewsh.cxx:535
virtual void UnblockIdling()=0
Decrement block count.
void ValidateAutoCompleteWords() const
Definition: pagefrm.hxx:412
bool m_bWaitAllowed
Definition: layact.hxx:93
void SetRetouche() const
Definition: frame.hxx:979
static const SwFrame * lcl_FindFirstInvaContent(const SwLayoutFrame *pLay, long nBottom, const SwContentFrame *pFirst)
Definition: layact.cxx:879
bool IsShortCut(SwPageFrame *&)
Definition: layact.cxx:963
wrapper class for the positioning of Writer fly frames and drawing objects
void SetFirstVisPageInvalid()
Definition: viewimp.hxx:148
virtual bool IsVisibleLayerId(SdrLayerID _nLayerId) const =0
method to determine, if a layer ID belongs to the visible ones.
static bool lcl_IsInvaLay(const SwFrame *pFrame, long nBottom)
Definition: layact.cxx:851
void ChangeOrigin(const SwRect &rRect)
Definition: swregion.hxx:48
long GetPrtBottom(const SwFrame &rFrame) const
Definition: frame.hxx:1371
bool IsInvalid() const
Definition: flyfrm.hxx:186
bool IsInvalidFlyInCnt() const
Definition: pagefrm.hxx:218
void Top(const long nTop)
Definition: swrect.hxx:202
void SttCursorMove()
Definition: crsrsh.cxx:291
SwIndex nContent
Definition: pam.hxx:38
const SwRect & getFrameArea() const
Definition: frame.hxx:175
SwFootnoteContFrame * FindFootnoteCont()
Definition: ftnfrm.cxx:964
bool getBrowseMode() const
Definition: viewopt.hxx:426
#define XCHECKPAGE
Definition: layact.cxx:68
bool IsInTab() const
Definition: frame.hxx:931
void EndLoopControl()
Definition: layouter.cxx:261
long GetBottomMargin(const SwFrame &rFrame) const
Definition: frame.hxx:1365
bool IsInvalidAutoCompleteWords() const
Definition: pagefrm.hxx:223
bool IsTextFrame() const
Definition: frame.hxx:1210
void InvalidateFlyContent() const
Definition: pagefrm.hxx:350
void Action(OutputDevice *pRenderContext)
Definition: layact.cxx:323
~SwLayIdle()
Definition: layact.cxx:2323
sal_uInt16 m_nEndPage
Definition: layact.hxx:78
bool IsInvalidSpelling() const
Definition: pagefrm.hxx:221
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
bool IsPageBodyFrame() const
Definition: layfrm.hxx:213
SwDoc * GetDoc() const
Definition: viewsh.hxx:284
bool IsInvalidSmartTags() const
Definition: pagefrm.hxx:222
Describes parts of multiple text nodes, which will form a text frame, even when redlines are hidden a...
Definition: txtfrm.hxx:952
SwContentFrame * GetPrevContentFrame() const
Definition: cntfrm.hxx:105
long GetLeftMargin(const SwFrame &rFrame) const
Definition: frame.hxx:1366
bool IsSctFrame() const
Definition: frame.hxx:1190
SwFlyFrame * FindFlyFrame()
Definition: frame.hxx:1087
bool IsWordCountDirty() const
Definition: txtedt.cxx:2232
void Right(const long nRight)
Definition: swrect.hxx:198
bool IsNextCycle() const
Definition: layact.hxx:139
bool IsFlyInContentFrame() const
Definition: flyfrm.hxx:193
void SetBrowseActionStop(bool bNew)
Definition: layact.hxx:135
virtual const SwRect GetObjRect() const =0
const SwRect GetPaintArea() const
|* The paintarea is the area, in which the content of a frame is allowed |* to be displayed...
Definition: ssfrm.cxx:619
void DrawRect(const tools::Rectangle &rRect)
void SetProgressState(long nPosition, SwDocShell const *pDocShell)
Definition: mainwn.cxx:78
sal_uInt32 GetOrdNumDirect() const
void InvalidateContent() const
Definition: pagefrm.hxx:362
const SwViewShell * GetShell() const
Only for SwViewShell::Init()
Definition: viewimp.hxx:140
bool IsInvalidContent() const
Definition: pagefrm.hxx:220
bool m_bIndicator
Definition: layact.hxx:198
VclInputFlags m_nInputType
Definition: layact.hxx:77
void ValidateFlyLayout() const
Definition: pagefrm.hxx:383
SwRect GetPaintSwRect()
Page number etc.
Definition: frmpaint.cxx:411
long const nTopMargin
void EndCursorMove(const bool bIdleEnd=false)
Definition: crsrsh.cxx:300
void SetHeight(SwRect &rRect, long nNew) const
Definition: frame.hxx:1352
void ResetTurbo()
Definition: rootfrm.hxx:346
void SetStatBar(bool bNew)
Definition: layact.cxx:97
bool IsInvalidFly() const
Definition: pagefrm.hxx:425
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
sal_Int32 nTextPos
Definition: layact.hxx:194
bool IsInvalidFlyContent() const
Definition: pagefrm.hxx:217
SwTextNode const * GetTextNodeForParaProps() const
Definition: txtfrm.cxx:1288
void SetLineColor()
SwTabFrame * ImplFindTabFrame()
Definition: findfrm.cxx:468
void SetWidth(SwRect &rRect, long nNew) const
Definition: frame.hxx:1351
void SetTop(SwRect &rRect, long nNew) const
Definition: frame.hxx:1347
void CheckWaitCursor()
Definition: layact.cxx:77
void Reset()
Definition: layact.cxx:284
sal_uInt16 m_nPreInvaPage
Definition: layact.hxx:72
void Validate() const
Definition: flyfrm.hxx:188
#define SHOW_IDLE(Color)
Definition: layact.cxx:2124
const SwContentFrame * GetFollow() const
Definition: cntfrm.hxx:113
static SwPageFrame * CheckFirstVisPage(SwPageFrame *pPage)
Definition: layact.cxx:369
const SwSortedObjs * GetSortedObjs() const
Definition: pagefrm.hxx:117
void ResetIdleFormat()
Definition: rootfrm.hxx:257
void ValidateFlyInCnt() const
Definition: pagefrm.hxx:391
const SwRect & VisArea() const
Definition: viewsh.cxx:570
bool m_bIdle
Definition: layact.hxx:88
std::unique_ptr< SwWait > m_pWait
Definition: layact.hxx:67
const SwPosition * GetPoint() const
Definition: pam.hxx:207
The usage of LayAction is always the same:
Definition: layact.hxx:55
static bool AnyInput(VclInputFlags nType=VCL_INPUT_ANY)
const IDocumentLayoutAccess & getIDocumentLayoutAccess() const
Provides access to the document layout interface.
Definition: format.cxx:762
SwRect GetBoundRect(OutputDevice const *pOutputDevice) const
Definition: paintfrm.cxx:6039
static SwSmartTagMgr & Get()
size_t size() const
Definition: sortedobjs.cxx:42
SwPageFrame * FindPageFrame()
Definition: frame.hxx:658
virtual void Cut() override
Definition: pagechg.cxx:838
bool IsCompletePaint() const
Definition: frame.hxx:579
const SwFrame * Lower() const
Definition: layfrm.hxx:100
virtual SwLayouter * GetLayouter()=0
int i
void InvalidatePage(const SwPageFrame *pPage=nullptr) const
Invalidates the page in which the Frame is currently placed.
Definition: wsfrm.cxx:590
void CheckIdleEnd()
Definition: layact.cxx:91
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
void RescheduleProgress(SwDocShell const *pDocShell)
Definition: mainwn.cxx:119
SwLayoutFrame * GetUpper()
Definition: frame.hxx:656
bool HasArea() const
Definition: swrect.hxx:290
void SetFillColor()
VclInputFlags GetInputType() const
Definition: layact.hxx:147
bool m_bUpdateExpFields
Definition: layact.hxx:91
long GetTopMargin(const SwFrame &rFrame) const
Definition: frame.hxx:1364
bool IsSmartTagsEnabled() const
bool IsRetoucheFrame() const
Definition: frame.hxx:1222
SwFrame * GetPrev()
Definition: frame.hxx:655
void RecalcAllLines()
Definition: txtfrm.cxx:3804
bool IsExtraData(const SwDoc *pDoc)
Definition: frmtool.cxx:3563
ring_container GetRingContainer()
Definition: ring.hxx:240
static constexpr sal_uInt16 defGapBetweenPages
Definition: viewopt.hxx:406
bool IsOnlineSpell() const
Definition: viewopt.hxx:325
bool empty() const
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:119
bool mbFormatContentOnInterrupt
Definition: layact.hxx:98
void SSize(const Size &rNew)
Definition: swrect.hxx:176
SwLayAction(SwRootFrame *pRt, SwViewShellImp *pImp)
Definition: layact.cxx:254
void InvalidateFlyLayout() const
Validate, invalidate and query the Page status Layout/Content and Fly/non-Fly respectively are inspec...
Definition: pagefrm.hxx:346
bool isXForms() const
Definition: docxforms.cxx:44
bool m_bInput
Definition: layact.hxx:87
A page of the document layout.
Definition: pagefrm.hxx:40
void OptCalc() const
Definition: frame.hxx:1056
sal_uInt16 m_nCheckPageNum
Definition: layact.hxx:79
long GetPrtRight(const SwFrame &rFrame) const
Definition: frame.hxx:1373
bool IsLeftShadowNeeded() const
Definition: paintfrm.cxx:5637
void InvalidateWindows(const SwRect &rRect)
Definition: viewsh.cxx:551
virtual SdrLayerID GetHellId() const =0
void ResetCompletePaint() const
Definition: frame.hxx:974
bool m_bActionInProgress
Definition: layact.hxx:95
SwSectionFrame * FindSctFrame()
Definition: frame.hxx:1091
virtual SdrLayerID GetLayer() const
SwLayoutFrame * FindBodyCont()
Searches the first ContentFrame in BodyText below the page.
Definition: findfrm.cxx:42
bool IsInput() const
Definition: layact.hxx:140
Point PixelToLogic(const Point &rDevicePt) const
void SetLeft(SwRect &rRect, long nNew) const
Definition: frame.hxx:1349
#define VCL_INPUT_ANY
void ResetRetouche() const
Definition: frame.hxx:983
bool IsInvalidFlyLayout() const
Definition: pagefrm.hxx:216
void ValidateLayout() const
Definition: pagefrm.hxx:395
~SwLayAction()
Definition: layact.cxx:278
void ValidateSmartTags() const
Definition: pagefrm.hxx:408
void FormatContent_(const SwContentFrame *pContent, const SwPageFrame *pPage)
Definition: layact.cxx:1788
bool m_bPaint
Definition: layact.hxx:82
std::clock_t m_nStartTicks
Definition: layact.hxx:74
bool m_bCheckPages
Definition: layact.hxx:90
static bool FormatObjsAtFrame(SwFrame &_rAnchorFrame, const SwPageFrame &_rPageFrame, SwLayAction *_pLayAction=nullptr)
method to format all floating screen objects at the given anchor frame
bool IsLayoutFrame() const
Definition: frame.hxx:1146
void Left(const long nLeft)
Definition: swrect.hxx:193
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
void Bottom(const long nBottom)
Definition: swrect.hxx:207
SwViewShellImp * m_pImp
Definition: layact.hxx:58
const SwContentFrame * GetTurbo()
Definition: rootfrm.hxx:347
sal_uInt32 m_nCallCount
Definition: layact.hxx:103
bool DoIdleJob_(const SwContentFrame *, IdleJobType)
Definition: layact.cxx:1861
const SwTabFrame * m_pOptTab
Definition: layact.hxx:65
const SvxOpaqueItem & GetOpaque(bool=true) const
Definition: frmatr.hxx:80
bool IsTabFrame() const
Definition: frame.hxx:1194
general base class for all free-flowing frames
Definition: flyfrm.hxx:60
long const nLeftMargin
SwViewShellImp * pImp
Definition: layact.hxx:192
void RemoveSuperfluous()
remove pages that are not needed at all
Definition: pagechg.cxx:1430
static void unlockPositionOfObjects(SwPageFrame *pPageFrame)
Definition: layact.cxx:409
bool IsBrowseActionStop() const
Definition: layact.hxx:172
SwTextFrame * FindMaster() const
Definition: flowfrm.cxx:677
WrongState GetWrongDirty() const
Definition: txtedt.cxx:2245
void ShellGetFocus()
Definition: crsrsh.cxx:2337
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:426
void Width(long nNew)
Definition: swrect.hxx:185
vcl::Window * GetWin() const
Definition: viewsh.hxx:340
bool IsPaintExtraData() const
Definition: layact.hxx:144
const o3tl::enumarray< SvxAdjust, unsigned short > aSvxToUnoAdjust USHRT_MAX
Definition: unosett.cxx:259
virtual const SwDocStat & GetDocStat() const =0
Document - Statistics.
#define SAL_INFO(area, stream)
sal_Int32 GetIndex() const
Definition: index.hxx:95
bool IsNoTextFrame() const
Definition: frame.hxx:1214
bool IsHelpDocument() const
bool IsAgain() const
Definition: layact.hxx:167
bool IsLockWordLstLocked() const
Definition: acmplwrd.hxx:59
void SetWaitAllowed(bool bNew)
Definition: layact.hxx:156
bool IsPageFrame() const
Definition: frame.hxx:1154
bool IsAutoCompleteWordDirty() const
Definition: txtedt.cxx:2289
bool CountWords(SwDocStat &rStat, sal_Int32 nStart, sal_Int32 nEnd) const
count words in given range - returns true if we refreshed out count
Definition: txtedt.cxx:1979
bool PaintContent_(const SwContentFrame *, const SwPageFrame *, const SwRect &)
Definition: layact.cxx:186
bool IsPaint() const
Definition: layact.hxx:141
bool bModified
Definition: docstat.hxx:39
long GetHeight(const SwRect &rRect) const
Definition: frame.hxx:1343
static OUString GetEventName(sal_Int32 nId)
Definition: docsh.cxx:1341
void DisallowTurbo() const
Definition: rootfrm.hxx:342
bool IsRetouche() const
Definition: frame.hxx:583
bool FormatContent(const SwPageFrame *pPage)
Definition: layact.cxx:1601
SwContentNode * pContentNode
Definition: layact.hxx:193
virtual void Calc(vcl::RenderContext *pRenderContext) const override
Definition: fly.cxx:2824
Provides access to the layout of a document.
#define STR_SW_EVENT_LAYOUT_FINISHED
Definition: swevent.hxx:32
SwFootnoteIdxs & GetFootnoteIdxs()
Definition: doc.hxx:628
#define SAL_WARN(area, stream)
void FormatLayoutFly(SwFlyFrame *)
Definition: layact.cxx:1403
void SetCheckPages(bool bNew)
Definition: layact.hxx:134
SwLayIdle * m_pIdleAct
Definition: viewimp.hxx:73
SwRegionRects * GetRegion()
Definition: viewimp.hxx:151
bool IsInvalid() const
Definition: pagefrm.hxx:421
bool IsIdle() const
Definition: layact.hxx:142
static void GetBorderAndShadowBoundRect(const SwRect &_rPageRect, const SwViewShell *_pViewShell, OutputDevice const *pRenderContext, SwRect &_orBorderAndShadowBoundRect, const bool bLeftShadow, const bool bRightShadow, const bool bRightSidebar)
get bound rectangle of border and shadow for repaints
Definition: paintfrm.cxx:6012
bool IsOver(const SwRect &rRect) const
Definition: swrect.cxx:128
long GetRightMargin(const SwFrame &rFrame) const
Definition: frame.hxx:1367
const SwContentFrame * ContainsContent() const
Checks if the frame contains one or more ContentFrame's anywhere in his subsidiary structure; if so t...
Definition: findfrm.cxx:66
void Push(PushFlags nFlags=PushFlags::ALL)
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:204
bool IsAssertFlyPages()
Definition: rootfrm.hxx:277
sal_Int32 nPos
class for collecting anchored objects
Definition: sortedobjs.hxx:48
bool SupportsDoubleBuffering() const
bool IsSuperfluous() const
Definition: rootfrm.hxx:297
bool bPageValid
Definition: layact.hxx:195
sal_uInt16 GetPageNum() const
Definition: rootfrm.hxx:307
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
SwRootFrame * getRootFrame()
Definition: frame.hxx:657
bool IsInvalidLayout() const
Definition: pagefrm.hxx:219
static const SwFrame * lcl_FindFirstInvaLay(const SwFrame *pFrame, long nBottom)
Definition: layact.cxx:857
sal_uInt16 GetGapBetweenPages() const
Definition: viewopt.hxx:411
void UnlockPaint(bool bVirDev=false)
Definition: viewsh.hxx:609
SwLayIdle(SwRootFrame *pRt, SwViewShellImp *pImp)
Definition: layact.cxx:2127
bool IsRightShadowNeeded() const
Definition: paintfrm.cxx:5624
const IDocumentDrawModelAccess & getIDocumentDrawModelAccess() const
Provides access to the document draw model interface.
Definition: format.cxx:760
virtual const SwFrameFormat * GetFormat() const
Definition: ssfrm.cxx:393
SwTabFrame * FindTabFrame()
Definition: frame.hxx:1075
bool m_bNextCycle
Definition: layact.hxx:86
SwFrame * GetNext()
Definition: frame.hxx:654
virtual void BlockIdling()=0
Increment block count.
bool TurboAction()
Definition: layact.cxx:833