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