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