LibreOffice Module sw (master)  1
laycache.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 
21 #include <sal/log.hxx>
22 #include <osl/diagnose.h>
23 #include <tools/stream.hxx>
24 #include <doc.hxx>
25 #include <IDocumentStatistics.hxx>
27 #include <docstat.hxx>
28 #include <fmtpdsc.hxx>
29 #include <laycache.hxx>
30 #include "layhelp.hxx"
31 #include <pagefrm.hxx>
32 #include <rootfrm.hxx>
33 #include <txtfrm.hxx>
34 #include <swtable.hxx>
35 #include <tabfrm.hxx>
36 #include <rowfrm.hxx>
37 #include <sectfrm.hxx>
38 #include <fmtcntnt.hxx>
39 #include <pagedesc.hxx>
40 #include <frmtool.hxx>
41 #include <dflyobj.hxx>
42 #include <dcontact.hxx>
43 #include <viewopt.hxx>
44 #include <flyfrm.hxx>
45 #include <sortedobjs.hxx>
46 #include <ndindex.hxx>
47 #include <node.hxx>
48 #include <ndtxt.hxx>
49 #include <frameformats.hxx>
50 
51 #include <limits>
52 
53 using namespace ::com::sun::star;
54 
55 SwLayoutCache::SwLayoutCache() : m_nLockCount( 0 ) {}
56 
57 /*
58  * Reading and writing of the layout cache.
59  * The layout cache is not necessary, but it improves
60  * the performance and reduces the text flow during
61  * the formatting.
62  * The layout cache contains the index of the paragraphs/tables
63  * at the top of every page, so it's possible to create
64  * the right count of pages and to distribute the document content
65  * to this pages before the formatting starts.
66  */
67 
68 void SwLayoutCache::Read( SvStream &rStream )
69 {
70  if( !m_pImpl )
71  {
72  m_pImpl.reset( new SwLayCacheImpl );
73  if( !m_pImpl->Read( rStream ) )
74  {
75  m_pImpl.reset();
76  }
77  }
78 }
79 
80 void SwLayCacheImpl::Insert( sal_uInt16 nType, sal_uLong nIndex, sal_Int32 nOffset )
81 {
82  m_aType.push_back( nType );
83  mIndices.push_back( nIndex );
84  m_aOffset.push_back( nOffset );
85 }
86 
88 {
89  SwLayCacheIoImpl aIo( rStream, false );
91  return false;
92 
93  // Due to an evil bug in the layout cache (#102759#), we cannot trust the
94  // sizes of fly frames which have been written using the "old" layout cache.
95  // This flag should indicate that we do not want to trust the width and
96  // height of fly frames
97  m_bUseFlyCache = aIo.GetMinorVersion() >= 1;
98 
100  aIo.OpenFlagRec();
101  aIo.CloseFlagRec();
102  while( aIo.BytesLeft() && !aIo.HasError() )
103  {
104  sal_uInt32 nIndex(0), nOffset(0);
105 
106  switch( aIo.Peek() )
107  {
109  {
111  sal_uInt8 cFlags = aIo.OpenFlagRec();
112  aIo.GetStream().ReadUInt32( nIndex );
113  if( (cFlags & 0x01) != 0 )
114  aIo.GetStream().ReadUInt32( nOffset );
115  else
116  nOffset = COMPLETE_STRING;
117  aIo.CloseFlagRec();
118  Insert( SW_LAYCACHE_IO_REC_PARA, nIndex, static_cast<sal_Int32>(nOffset) );
119  aIo.CloseRec();
120  break;
121  }
124  aIo.OpenFlagRec();
125  aIo.GetStream().ReadUInt32( nIndex )
126  .ReadUInt32( nOffset );
127  Insert( SW_LAYCACHE_IO_REC_TABLE, nIndex, static_cast<sal_Int32>(nOffset) );
128  aIo.CloseFlagRec();
129  aIo.CloseRec();
130  break;
132  {
134  aIo.OpenFlagRec();
135  aIo.CloseFlagRec();
136  sal_Int32 nX(0), nY(0), nW(0), nH(0);
137  sal_uInt16 nPgNum(0);
138  aIo.GetStream().ReadUInt16( nPgNum ).ReadUInt32( nIndex )
139  .ReadInt32( nX ).ReadInt32( nY ).ReadInt32( nW ).ReadInt32( nH );
140  m_FlyCache.emplace_back( nPgNum, nIndex, nX, nY, nW, nH );
141  aIo.CloseRec();
142  break;
143  }
144  default:
145  aIo.SkipRec();
146  break;
147  }
148  }
149  aIo.CloseRec();
150 
151  return !aIo.HasError();
152 }
153 
163 void SwLayoutCache::Write( SvStream &rStream, const SwDoc& rDoc )
164 {
165  if( !rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ) // the layout itself ..
166  return;
167 
168  SwLayCacheIoImpl aIo( rStream, true );
169  // We want to save the relative index, so we need the index
170  // of the first content
171  sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
172  StartOfSectionNode()->GetIndex();
173  // The first page...
174  SwPageFrame* pPage = const_cast<SwPageFrame*>(static_cast<const SwPageFrame*>(rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->Lower()));
175 
177  aIo.OpenFlagRec( 0, 0 );
178  aIo.CloseFlagRec();
179  while( pPage )
180  {
181  if( pPage->GetPrev() )
182  {
183  SwLayoutFrame* pLay = pPage->FindBodyCont();
184  SwFrame* pTmp = pLay ? pLay->ContainsAny() : nullptr;
185  // We are only interested in paragraph or table frames,
186  // a section frames contains paragraphs/tables.
187  if( pTmp && pTmp->IsSctFrame() )
188  pTmp = static_cast<SwSectionFrame*>(pTmp)->ContainsAny();
189 
190  if( pTmp ) // any content
191  {
192  if( pTmp->IsTextFrame() )
193  {
194  SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pTmp));
195  assert(!pFrame->GetMergedPara());
196  sal_uLong nNdIdx = pFrame->GetTextNodeFirst()->GetIndex();
197  if( nNdIdx > nStartOfContent )
198  {
199  /* Open Paragraph Record */
201  bool bFollow = static_cast<SwTextFrame*>(pTmp)->IsFollow();
202  aIo.OpenFlagRec( bFollow ? 0x01 : 0x00,
203  bFollow ? 8 : 4 );
204  nNdIdx -= nStartOfContent;
205  aIo.GetStream().WriteUInt32( nNdIdx );
206  if( bFollow )
207  aIo.GetStream().WriteUInt32( sal_Int32(static_cast<SwTextFrame*>(pTmp)->GetOffset()) );
208  aIo.CloseFlagRec();
209  /* Close Paragraph Record */
210  aIo.CloseRec();
211  }
212  }
213  else if( pTmp->IsTabFrame() )
214  {
215  SwTabFrame* pTab = static_cast<SwTabFrame*>(pTmp);
216  sal_uLong nOfst = COMPLETE_STRING;
217  if( pTab->IsFollow() )
218  {
219  // If the table is a follow, we have to look for the
220  // master and to count all rows to get the row number
221  nOfst = 0;
222  if( pTab->IsFollow() )
223  pTab = pTab->FindMaster( true );
224  while( pTab != pTmp )
225  {
226  SwFrame* pSub = pTab->Lower();
227  while( pSub )
228  {
229  ++nOfst;
230  pSub = pSub->GetNext();
231  }
232  pTab = pTab->GetFollow();
233  assert(pTab && "Table follow without master");
234  }
235  }
236  while (true)
237  {
238  sal_uLong nNdIdx =
239  pTab->GetTable()->GetTableNode()->GetIndex();
240  if( nNdIdx > nStartOfContent )
241  {
242  /* Open Table Record */
244  aIo.OpenFlagRec( 0, 8 );
245  nNdIdx -= nStartOfContent;
246  aIo.GetStream().WriteUInt32( nNdIdx )
247  .WriteUInt32( nOfst );
248  aIo.CloseFlagRec();
249  /* Close Table Record */
250  aIo.CloseRec();
251  }
252  // If the table has a follow on the next page,
253  // we know already the row number and store this
254  // immediately.
255  if( pTab->GetFollow() )
256  {
257  if( nOfst == sal_uLong(COMPLETE_STRING) )
258  nOfst = 0;
259  do
260  {
261  SwFrame* pSub = pTab->Lower();
262  while( pSub )
263  {
264  ++nOfst;
265  pSub = pSub->GetNext();
266  }
267  pTab = pTab->GetFollow();
268  SwPageFrame *pTabPage = pTab->FindPageFrame();
269  if( pTabPage != pPage )
270  {
271  OSL_ENSURE( pPage->GetPhyPageNum() <
272  pTabPage->GetPhyPageNum(),
273  "Looping Tableframes" );
274  pPage = pTabPage;
275  break;
276  }
277  } while ( pTab->GetFollow() );
278  }
279  else
280  break;
281  }
282  }
283  }
284  }
285  if( pPage->GetSortedObjs() )
286  {
287  SwSortedObjs &rObjs = *pPage->GetSortedObjs();
288  for (SwAnchoredObject* pAnchoredObj : rObjs)
289  {
290  if (SwFlyFrame *pFly = pAnchoredObj->DynCastFlyFrame())
291  {
292  if( pFly->getFrameArea().Left() != FAR_AWAY &&
293  !pFly->GetAnchorFrame()->FindFooterOrHeader() )
294  {
295  const SwContact *pC =
296  ::GetUserCall(pAnchoredObj->GetDrawObj());
297  if( pC )
298  {
299  sal_uInt32 nOrdNum = pAnchoredObj->GetDrawObj()->GetOrdNum();
300  sal_uInt16 nPageNum = pPage->GetPhyPageNum();
301  /* Open Fly Record */
303  aIo.OpenFlagRec( 0, 0 );
304  aIo.CloseFlagRec();
305  const SwRect& rRct = pFly->getFrameArea();
306  sal_Int32 nX = rRct.Left() - pPage->getFrameArea().Left();
307  sal_Int32 nY = rRct.Top() - pPage->getFrameArea().Top();
308  aIo.GetStream().WriteUInt16( nPageNum ).WriteUInt32( nOrdNum )
309  .WriteInt32( nX ).WriteInt32( nY )
310  .WriteInt32( rRct.Width() )
311  .WriteInt32( rRct.Height() );
312  /* Close Fly Record */
313  aIo.CloseRec();
314  }
315  }
316  }
317  }
318  }
319  pPage = static_cast<SwPageFrame*>(pPage->GetNext());
320  }
321  aIo.CloseRec();
322 }
323 
324 #ifdef DBG_UTIL
325 bool SwLayoutCache::CompareLayout( const SwDoc& rDoc ) const
326 {
327  if( !m_pImpl )
328  return true;
329  const SwRootFrame *pRootFrame = rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
330  if( pRootFrame )
331  {
332  size_t nIndex = 0;
333  sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
334  StartOfSectionNode()->GetIndex();
335  const SwPageFrame* pPage = static_cast<const SwPageFrame*>(pRootFrame->Lower());
336  if( pPage )
337  pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
338  while( pPage )
339  {
340  if( nIndex >= m_pImpl->size() )
341  return false;
342 
343  const SwLayoutFrame* pLay = pPage->FindBodyCont();
344  const SwFrame* pTmp = pLay ? pLay->ContainsAny() : nullptr;
345  if( pTmp && pTmp->IsSctFrame() )
346  pTmp = static_cast<const SwSectionFrame*>(pTmp)->ContainsAny();
347  if( pTmp )
348  {
349  if( pTmp->IsTextFrame() )
350  {
351 
352  SwTextFrame const*const pFrame(static_cast<SwTextFrame const*>(pTmp));
353  assert(!pFrame->GetMergedPara());
354  sal_uLong nNdIdx = pFrame->GetTextNodeFirst()->GetIndex();
355  if( nNdIdx > nStartOfContent )
356  {
357  bool bFollow = static_cast<const SwTextFrame*>(pTmp)->IsFollow();
358  nNdIdx -= nStartOfContent;
359  if( m_pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
361  m_pImpl->GetBreakType( nIndex ) ||
362  (bFollow
363  ? sal_Int32(static_cast<const SwTextFrame*>(pTmp)->GetOffset())
364  : COMPLETE_STRING) != m_pImpl->GetBreakOfst(nIndex))
365  {
366  return false;
367  }
368  ++nIndex;
369  }
370  }
371  else if( pTmp->IsTabFrame() )
372  {
373  const SwTabFrame* pTab = static_cast<const SwTabFrame*>(pTmp);
374  sal_Int32 nOfst = COMPLETE_STRING;
375  if( pTab->IsFollow() )
376  {
377  nOfst = 0;
378  if( pTab->IsFollow() )
379  pTab = pTab->FindMaster( true );
380  while( pTab != pTmp )
381  {
382  const SwFrame* pSub = pTab->Lower();
383  while( pSub )
384  {
385  ++nOfst;
386  pSub = pSub->GetNext();
387  }
388  pTab = pTab->GetFollow();
389  }
390  }
391  do
392  {
393  sal_uLong nNdIdx =
394  pTab->GetTable()->GetTableNode()->GetIndex();
395  if( nNdIdx > nStartOfContent )
396  {
397  nNdIdx -= nStartOfContent;
398  if( m_pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
400  m_pImpl->GetBreakType( nIndex ) ||
401  nOfst != m_pImpl->GetBreakOfst( nIndex ) )
402  {
403  return false;
404  }
405  ++nIndex;
406  }
407  if( pTab->GetFollow() )
408  {
409  if( nOfst == COMPLETE_STRING )
410  nOfst = 0;
411  do
412  {
413  const SwFrame* pSub = pTab->Lower();
414  while( pSub )
415  {
416  ++nOfst;
417  pSub = pSub->GetNext();
418  }
419  pTab = pTab->GetFollow();
420  const SwPageFrame *pTabPage = pTab->FindPageFrame();
421  if( pTabPage != pPage )
422  {
423  pPage = pTabPage;
424  break;
425  }
426  } while ( pTab->GetFollow() );
427  }
428  else
429  break;
430  } while( pTab );
431  }
432  }
433  pPage = static_cast<const SwPageFrame*>(pPage->GetNext());
434  }
435  }
436  return true;
437 }
438 #endif
439 
441 {
442  if( !IsLocked() )
443  {
444  m_pImpl.reset();
445  }
446 }
447 
449 {
450  OSL_ENSURE( !m_nLockCount, "Deleting a locked SwLayoutCache!?" );
451 }
452 
455  SwSectionFrame *pSect,
456  SwSectionNode *pNd ) :
457  m_pUpper( pUp ),
458  m_pSectFrame( pSect ),
459  m_pSectNode( pNd )
460 {
461  if ( !m_pSectNode )
462  {
463  const SwNodeIndex *pIndex = pSect->GetFormat()->GetContent().GetContentIdx();
464  m_pSectNode = pIndex->GetNode().FindSectionNode();
465  }
466 }
467 
468 namespace {
469 
470 bool sanityCheckLayoutCache(SwLayCacheImpl const& rCache,
471  SwNodes const& rNodes, sal_uLong nNodeIndex)
472 {
473  auto const nStartOfContent(rNodes.GetEndOfContent().StartOfSectionNode()->GetIndex());
474  nNodeIndex -= nStartOfContent;
475  auto const nMaxIndex(rNodes.GetEndOfContent().GetIndex() - nStartOfContent);
476  for (size_t nIndex = 0; nIndex < rCache.size(); ++nIndex)
477  {
478  auto const nBreakIndex(rCache.GetBreakIndex(nIndex));
479  if (nBreakIndex < nNodeIndex || nMaxIndex <= nBreakIndex)
480  {
481  SAL_WARN("sw.layout",
482  "invalid node index in layout-cache: " << nBreakIndex);
483  return false;
484  }
485  auto const nBreakType(rCache.GetBreakType(nIndex));
486  switch (nBreakType)
487  {
489  if (!rNodes[nBreakIndex + nStartOfContent]->IsTextNode())
490  {
491  SAL_WARN("sw.layout",
492  "invalid node of type 'P' in layout-cache");
493  return false;
494  }
495  break;
497  if (!rNodes[nBreakIndex + nStartOfContent]->IsTableNode())
498  {
499  SAL_WARN("sw.layout",
500  "invalid node of type 'T' in layout-cache");
501  return false;
502  }
503  break;
504  default:
505  assert(false); // Read shouldn't have inserted that
506  }
507  }
508  return true;
509 }
510 
511 } // namespace
512 
520  SwLayoutFrame* &rpL, std::unique_ptr<SwActualSection> &rpA,
521  sal_uLong nNodeIndex, bool bCache )
522  : mrpFrame( rpF )
523  , mrpPrv( rpP )
524  , mrpPage( rpPg )
525  , mrpLay( rpL )
526  , mrpActualSection( rpA )
527  , mbBreakAfter(false)
528  , mpDoc(pD)
529  , mnMaxParaPerPage( 25 )
530  , mnParagraphCnt( bCache ? 0 : USHRT_MAX )
531  , mnFlyIdx( 0 )
532  , mbFirst( bCache )
533 {
534  mpImpl = mpDoc->GetLayoutCache() ? mpDoc->GetLayoutCache()->LockImpl() : nullptr;
535  if( mpImpl )
536  {
537  SwNodes const& rNodes(mpDoc->GetNodes());
538  if (sanityCheckLayoutCache(*mpImpl, rNodes, nNodeIndex))
539  {
540  mnIndex = 0;
542  mnMaxParaPerPage = 1000;
543  }
544  else
545  {
547  mpImpl = nullptr;
548  mnIndex = std::numeric_limits<size_t>::max();
549  mnStartOfContent = USHRT_MAX;
550  }
551  }
552  else
553  {
554  mnIndex = std::numeric_limits<size_t>::max();
555  mnStartOfContent = ULONG_MAX;
556  }
557 }
558 
560 {
561  if( mpImpl )
562  {
563  OSL_ENSURE( mpDoc && mpDoc->GetLayoutCache(), "Missing layoutcache" );
565  }
566 }
567 
573 {
574  sal_uLong nPgCount;
575  SwLayCacheImpl *pCache = mpDoc->GetLayoutCache() ?
576  mpDoc->GetLayoutCache()->LockImpl() : nullptr;
577  if( pCache )
578  {
579  nPgCount = pCache->size() + 1;
581  }
582  else
583  {
585  if ( nPgCount <= 10 ) // no page insertion for less than 10 pages
586  nPgCount = 0;
588  if ( nNdCount <= 1 )
589  {
590  //Estimates the number of paragraphs.
593  //Tables have a little overhead...
594  nTmp -= mpDoc->GetTableFrameFormats()->size() * 25;
595  //Fly frames, too ..
596  nTmp -= (mpDoc->GetNodes().GetEndOfAutotext().GetIndex() -
597  mpDoc->GetNodes().GetEndOfInserts().GetIndex()) / 3 * 5;
598  if ( nTmp > 0 )
599  nNdCount = nTmp;
600  }
601  if ( nNdCount > 100 ) // no estimation below this value
602  {
603  if ( nPgCount > 0 )
604  { // tdf#129529 avoid 0...
605  mnMaxParaPerPage = std::max<sal_uLong>(3, nNdCount / nPgCount);
606  }
607  else
608  {
609  mnMaxParaPerPage = std::max( sal_uLong(20),
610  sal_uLong(20 + nNdCount / 1000 * 3) );
611  const sal_uLong nMax = 53;
612  mnMaxParaPerPage = std::min( mnMaxParaPerPage, nMax );
613  nPgCount = nNdCount / mnMaxParaPerPage;
614  }
615  if ( nNdCount < 1000 )
616  nPgCount = 0;// no progress bar for small documents
617  SwViewShell *pSh = nullptr;
618  if( mrpLay && mrpLay->getRootFrame() )
619  pSh = mrpLay->getRootFrame()->GetCurrShell();
620  if( pSh && pSh->GetViewOptions()->getBrowseMode() )
621  mnMaxParaPerPage *= 6;
622  }
623  }
624  return nPgCount;
625 }
626 
637 {
638  bool bEnd = nullptr == mrpPage->GetNext();
639  const SvxFormatBreakItem& rBrk = mrpFrame->GetBreakItem();
640  const SwFormatPageDesc& rDesc = mrpFrame->GetPageDescItem();
641  // #118195# Do not evaluate page description if frame
642  // is a follow frame!
643  const SwPageDesc* pDesc = mrpFrame->IsFlowFrame() &&
645  nullptr :
646  rDesc.GetPageDesc();
647 
649  mbBreakAfter = rBrk.GetBreak() == SvxBreak::PageAfter ||
650  rBrk.GetBreak() == SvxBreak::PageBoth;
651  if ( !bBrk )
652  bBrk = rBrk.GetBreak() == SvxBreak::PageBefore ||
653  rBrk.GetBreak() == SvxBreak::PageBoth;
654 
655  if ( bBrk || pDesc )
656  {
657  ::std::optional<sal_uInt16> oPgNum;
658  if ( !pDesc )
659  {
660  pDesc = mrpPage->GetPageDesc()->GetFollow();
661  }
662  else
663  {
664  oPgNum = rDesc.GetNumOffset();
665  if ( oPgNum )
666  static_cast<SwRootFrame*>(mrpPage->GetUpper())->SetVirtPageNum(true);
667  }
668  bool bNextPageRight = !mrpPage->OnRightPage();
669  bool bInsertEmpty = false;
670  assert(mrpPage->GetUpper()->GetLower());
671  if (oPgNum && bNextPageRight != IsRightPageByNumber(
672  *static_cast<SwRootFrame*>(mrpPage->GetUpper()), *oPgNum))
673  {
674  bNextPageRight = !bNextPageRight;
675  bInsertEmpty = true;
676  }
677  // If the page style is changing, we'll have a first page.
678  bool bNextPageFirst = pDesc != mrpPage->GetPageDesc();
679  ::InsertNewPage( const_cast<SwPageDesc&>(*pDesc), mrpPage->GetUpper(),
680  bNextPageRight, bNextPageFirst, bInsertEmpty, false, mrpPage->GetNext());
681  if ( bEnd )
682  {
683  OSL_ENSURE( mrpPage->GetNext(), "No new page?" );
684  do
685  { mrpPage = static_cast<SwPageFrame*>(mrpPage->GetNext());
686  } while ( mrpPage->GetNext() );
687  }
688  else
689  {
690  OSL_ENSURE( mrpPage->GetNext(), "No new page?" );
691  mrpPage = static_cast<SwPageFrame*>(mrpPage->GetNext());
692  if ( mrpPage->IsEmptyPage() )
693  {
694  OSL_ENSURE( mrpPage->GetNext(), "No new page?" );
695  mrpPage = static_cast<SwPageFrame*>(mrpPage->GetNext());
696  }
697  }
699  while( mrpLay->Lower() )
700  mrpLay = static_cast<SwLayoutFrame*>(mrpLay->Lower());
701  return true;
702  }
703  return false;
704 }
705 
714 {
715  bool bRet = false;
716  bool bLongTab = false;
717  sal_uLong nMaxRowPerPage( 0 );
718  nNodeIndex -= mnStartOfContent;
719  sal_uInt16 nRows( 0 );
720  if( mrpFrame->IsTabFrame() )
721  {
722  //Inside a table counts every row as a paragraph
723  SwFrame *pLow = static_cast<SwTabFrame*>(mrpFrame)->Lower();
724  nRows = 0;
725  do
726  {
727  ++nRows;
728  pLow = pLow->GetNext();
729  } while ( pLow );
730  mnParagraphCnt += nRows;
731  if( !mpImpl && mnParagraphCnt > mnMaxParaPerPage + 10 )
732  {
733  // OD 09.04.2003 #108698# - improve heuristics:
734  // Assume that a table, which has more than three times the quantity
735  // of maximal paragraphs per page rows, consists of rows, which have
736  // the height of a normal paragraph. Thus, allow as much rows per page
737  // as much paragraphs are allowed.
738  if ( nRows > ( 3*mnMaxParaPerPage ) )
739  {
740  nMaxRowPerPage = mnMaxParaPerPage;
741  }
742  else
743  {
744  SwFrame *pTmp = static_cast<SwTabFrame*>(mrpFrame)->Lower();
745  if( pTmp->GetNext() )
746  pTmp = pTmp->GetNext();
747  pTmp = static_cast<SwRowFrame*>(pTmp)->Lower();
748  sal_uInt16 nCnt = 0;
749  do
750  {
751  ++nCnt;
752  pTmp = pTmp->GetNext();
753  } while( pTmp );
754  nMaxRowPerPage = std::max( sal_uLong(2), mnMaxParaPerPage / nCnt );
755  }
756  bLongTab = true;
757  }
758  }
759  else
760  ++mnParagraphCnt;
761  if( mbFirst && mpImpl && mnIndex < mpImpl->size() &&
762  mpImpl->GetBreakIndex( mnIndex ) == nNodeIndex &&
764  ( ++mnIndex < mpImpl->size() &&
765  mpImpl->GetBreakIndex( mnIndex ) == nNodeIndex ) ) )
766  mbFirst = false;
767  // OD 09.04.2003 #108698# - always split a big tables.
768  if ( !mbFirst ||
769  ( mrpFrame->IsTabFrame() && bLongTab )
770  )
771  {
772  sal_Int32 nRowCount = 0;
773  do
774  {
775  if( mpImpl || bLongTab )
776  {
777  sal_Int32 nOfst = COMPLETE_STRING;
778  sal_uInt16 nType = SW_LAYCACHE_IO_REC_PAGES;
779  if( bLongTab )
780  {
781  mbBreakAfter = true;
782  nOfst = static_cast<sal_Int32>(nRowCount + nMaxRowPerPage);
783  }
784  else
785  {
786  while( mnIndex < mpImpl->size() &&
787  mpImpl->GetBreakIndex(mnIndex) < nNodeIndex)
788  ++mnIndex;
789  if( mnIndex < mpImpl->size() &&
790  mpImpl->GetBreakIndex(mnIndex) == nNodeIndex )
791  {
792  nType = mpImpl->GetBreakType( mnIndex );
793  nOfst = mpImpl->GetBreakOfst( mnIndex++ );
794  mbBreakAfter = true;
795  }
796  }
797 
798  if( nOfst < COMPLETE_STRING )
799  {
800  bool bSplit = false;
801  sal_uInt16 nRepeat( 0 );
802  if( !bLongTab && mrpFrame->IsTextFrame() &&
803  SW_LAYCACHE_IO_REC_PARA == nType &&
804  nOfst < static_cast<SwTextFrame*>(mrpFrame)->GetText().getLength())
805  bSplit = true;
806  else if( mrpFrame->IsTabFrame() && nRowCount < nOfst &&
807  ( bLongTab || SW_LAYCACHE_IO_REC_TABLE == nType ) )
808  {
809  nRepeat = static_cast<SwTabFrame*>(mrpFrame)->
810  GetTable()->GetRowsToRepeat();
811  bSplit = nOfst < nRows && nRowCount + nRepeat < nOfst;
812  bLongTab = bLongTab && bSplit;
813  }
814  if( bSplit )
815  {
817 
818  {
820  aFrm.Pos() = mrpLay->getFrameArea().Pos();
821  aFrm.Pos().AdjustY(1 );
822  }
823 
824  mrpPrv = mrpFrame;
825  if( mrpFrame->IsTabFrame() )
826  {
827  SwTabFrame* pTab = static_cast<SwTabFrame*>(mrpFrame);
828  // #i33629#, #i29955#
829  ::RegistFlys( pTab->FindPageFrame(), pTab );
830  SwFrame *pRow = pTab->Lower();
831  SwTabFrame *pFoll = new SwTabFrame( *pTab );
832 
833  SwFrame *pPrv;
834  if( nRepeat > 0 )
835  {
836  sw::FlyCreationSuppressor aSuppressor;
837  // Insert new headlines:
838  sal_uInt16 nRowIdx = 0;
839  SwRowFrame* pHeadline = nullptr;
840  while( nRowIdx < nRepeat )
841  {
842  OSL_ENSURE( pTab->GetTable()->GetTabLines()[ nRowIdx ], "Table without rows?" );
843  pHeadline =
844  new SwRowFrame( *pTab->GetTable()->GetTabLines()[ nRowIdx ], pTab );
845  pHeadline->SetRepeatedHeadline( true );
846  pHeadline->InsertBefore( pFoll, nullptr );
847  pHeadline->RegistFlys();
848 
849  ++nRowIdx;
850  }
851  pPrv = pHeadline;
852  nRows = nRows + nRepeat;
853  }
854  else
855  pPrv = nullptr;
856  while( pRow && nRowCount < nOfst )
857  {
858  pRow = pRow->GetNext();
859  ++nRowCount;
860  }
861  while ( pRow )
862  {
863  SwFrame* pNxt = pRow->GetNext();
864  pRow->RemoveFromLayout();
865  pRow->InsertBehind( pFoll, pPrv );
866  pPrv = pRow;
867  pRow = pNxt;
868  }
869  mrpFrame = pFoll;
870  }
871  else
872  {
873  SwTextFrame *const pNew = static_cast<SwTextFrame*>(
874  static_cast<SwTextFrame*>(mrpFrame)
875  ->GetTextNodeFirst()->MakeFrame(mrpFrame));
876  pNew->ManipOfst( TextFrameIndex(nOfst) );
877  pNew->SetFollow( static_cast<SwTextFrame*>(mrpFrame)->GetFollow() );
878  static_cast<SwTextFrame*>(mrpFrame)->SetFollow( pNew );
879  mrpFrame = pNew;
880  }
881  }
882  }
883  }
884 
885  SwPageFrame* pLastPage = mrpPage;
886  if( CheckInsertPage() )
887  {
888  CheckFlyCache_( pLastPage );
890  {
893  }
894 
895  bRet = true;
896  mrpPrv = nullptr;
897  mnParagraphCnt = 0;
898 
899  if ( mrpActualSection )
900  {
901  //Did the SectionFrame even have a content? If not, we can
902  //directly put it somewhere else
903  SwSectionFrame *pSct;
904  bool bInit = false;
905  if ( !mrpActualSection->GetSectionFrame()->ContainsContent())
906  {
907  pSct = mrpActualSection->GetSectionFrame();
908  pSct->RemoveFromLayout();
909  }
910  else
911  {
912  pSct = new SwSectionFrame(
913  *mrpActualSection->GetSectionFrame(), false );
914  mrpActualSection->GetSectionFrame()->SimpleFormat();
915  bInit = true;
916  }
917  mrpActualSection->SetSectionFrame( pSct );
918  pSct->InsertBehind( mrpLay, nullptr );
919 
920  if( bInit )
921  {
922  pSct->Init();
923  }
924 
925  {
927  aFrm.Pos() = mrpLay->getFrameArea().Pos();
928  aFrm.Pos().AdjustY(1 ); //because of the notifications
929  }
930 
931  mrpLay = pSct;
932  if ( mrpLay->Lower() && mrpLay->Lower()->IsLayoutFrame() )
934  }
935  }
936  } while( bLongTab || ( mpImpl && mnIndex < mpImpl->size() &&
937  mpImpl->GetBreakIndex( mnIndex ) == nNodeIndex ) );
938  }
939  mbFirst = false;
940  return bRet;
941 }
942 
943 namespace {
944 
945 struct SdrObjectCompare
946 {
947  bool operator()( const SdrObject* pF1, const SdrObject* pF2 ) const
948  {
949  return pF1->GetOrdNum() < pF2->GetOrdNum();
950  }
951 };
952 
953 struct FlyCacheCompare
954 {
955  bool operator()( const SwFlyCache* pC1, const SwFlyCache* pC2 ) const
956  {
957  return pC1->nOrdNum < pC2->nOrdNum;
958  }
959 };
960 
961 }
962 
969 {
970  if( !mpImpl || !pPage )
971  return;
972  const size_t nFlyCount = mpImpl->GetFlyCount();
973  // Any text frames at the page, fly cache available?
974  if( !(pPage->GetSortedObjs() && mnFlyIdx < nFlyCount) )
975  return;
976 
977  SwSortedObjs &rObjs = *pPage->GetSortedObjs();
978  sal_uInt16 nPgNum = pPage->GetPhyPageNum();
979 
980  // NOTE: Here we do not use the absolute ordnums but
981  // relative ordnums for the objects on this page.
982 
983  // skip fly frames from pages before the current page
984  while( mnFlyIdx < nFlyCount &&
986  ++mnFlyIdx;
987 
988  // sort cached objects on this page by ordnum
990  size_t nIdx = mnFlyIdx;
991 
992  SwFlyCache* pFlyC;
993  while( nIdx < nFlyCount &&
994  ( pFlyC = &mpImpl->GetFlyCache( nIdx ) )->nPageNum == nPgNum )
995  {
996  aFlyCacheSet.insert( pFlyC );
997  ++nIdx;
998  }
999 
1000  // sort objects on this page by ordnum
1002  for (SwAnchoredObject* pAnchoredObj : rObjs)
1003  {
1004  if (SwFlyFrame *pFly = pAnchoredObj->DynCastFlyFrame()) // a text frame?
1005  {
1006  if( pFly->GetAnchorFrame() &&
1007  !pFly->GetAnchorFrame()->FindFooterOrHeader() )
1008  {
1009  const SwContact *pC = ::GetUserCall( pAnchoredObj->GetDrawObj() );
1010  if( pC )
1011  {
1012  aFlySet.insert( pAnchoredObj->GetDrawObj() );
1013  }
1014  }
1015  }
1016  }
1017 
1018  if ( aFlyCacheSet.size() != aFlySet.size() )
1019  return;
1020 
1021  auto aFlySetIt = aFlySet.begin();
1022 
1023  for ( const SwFlyCache* pFlyCache : aFlyCacheSet )
1024  {
1025  SwFlyFrame* pFly = const_cast<SwVirtFlyDrawObj*>(static_cast<const SwVirtFlyDrawObj*>(*aFlySetIt))->GetFlyFrame();
1026 
1027  if ( pFly->getFrameArea().Left() == FAR_AWAY )
1028  {
1029  // we get the stored information
1031  aFrm.Pos().setX( pFlyCache->Left() + pPage->getFrameArea().Left() );
1032  aFrm.Pos().setY( pFlyCache->Top() + pPage->getFrameArea().Top() );
1033 
1034  if ( mpImpl->IsUseFlyCache() )
1035  {
1036  aFrm.Width( pFlyCache->Width() );
1037  aFrm.Height( pFlyCache->Height() );
1038  }
1039  }
1040 
1041  ++aFlySetIt;
1042  }
1043 }
1044 
1046  m_pStream( &rStrm ),
1047  m_nFlagRecEnd ( 0 ),
1048  m_nMajorVersion(SW_LAYCACHE_IO_VERSION_MAJOR),
1049  m_nMinorVersion(SW_LAYCACHE_IO_VERSION_MINOR),
1050  m_bWriteMode( bWrtMd ),
1051  m_bError( false )
1052 {
1053  if( m_bWriteMode )
1056 
1057  else
1060 }
1061 
1063 {
1064  sal_uInt32 nPos = m_pStream->Tell();
1065  if( m_bWriteMode )
1066  {
1067  m_aRecords.emplace_back(cType, nPos );
1068  m_pStream->WriteUInt32( 0 );
1069  }
1070  else
1071  {
1072  sal_uInt32 nVal(0);
1073  m_pStream->ReadUInt32( nVal );
1074  sal_uInt8 cRecTyp = static_cast<sal_uInt8>(nVal);
1075  if (!nVal || cRecTyp != cType || !m_pStream->good())
1076  {
1077  OSL_ENSURE( nVal, "OpenRec: Record-Header is 0" );
1078  OSL_ENSURE( cRecTyp == cType, "OpenRec: Wrong Record Type" );
1079  m_aRecords.emplace_back(0, m_pStream->Tell() );
1080  m_bError = true;
1081  }
1082  else
1083  {
1084  sal_uInt32 nSize = nVal >> 8;
1085  m_aRecords.emplace_back(cRecTyp, nPos+nSize );
1086  }
1087  }
1088 }
1089 
1090 // Close record
1092 {
1093  bool bRes = true;
1094  OSL_ENSURE( !m_aRecords.empty(), "CloseRec: no levels" );
1095  if( !m_aRecords.empty() )
1096  {
1097  sal_uInt32 nPos = m_pStream->Tell();
1098  if( m_bWriteMode )
1099  {
1100  sal_uInt32 nBgn = m_aRecords.back().size;
1101  m_pStream->Seek( nBgn );
1102  sal_uInt32 nSize = nPos - nBgn;
1103  sal_uInt32 nVal = ( nSize << 8 ) | m_aRecords.back().type;
1104  m_pStream->WriteUInt32( nVal );
1105  m_pStream->Seek( nPos );
1106  if( m_pStream->GetError() != ERRCODE_NONE )
1107  bRes = false;
1108  }
1109  else
1110  {
1111  sal_uInt32 n = m_aRecords.back().size;
1112  OSL_ENSURE( n >= nPos, "CloseRec: too much data read" );
1113  if( n != nPos )
1114  {
1115  m_pStream->Seek( n );
1116  if( n < nPos )
1117  bRes = false;
1118  }
1119  if( m_pStream->GetErrorCode() != ERRCODE_NONE )
1120  bRes = false;
1121  }
1122  m_aRecords.pop_back();
1123  }
1124 
1125  if( !bRes )
1126  m_bError = true;
1127 }
1128 
1130 {
1131  sal_uInt32 n = 0;
1132  if( !m_bError && !m_aRecords.empty() )
1133  {
1134  sal_uInt32 nEndPos = m_aRecords.back().size;
1135  sal_uInt32 nPos = m_pStream->Tell();
1136  if( nEndPos > nPos )
1137  n = nEndPos - nPos;
1138  }
1139  return n;
1140 }
1141 
1143 {
1144  sal_uInt8 c(0);
1145  if( !m_bError )
1146  {
1147  sal_uInt32 nPos = m_pStream->Tell();
1148  m_pStream->ReadUChar( c );
1149  m_pStream->Seek( nPos );
1150  if( m_pStream->GetErrorCode() != ERRCODE_NONE )
1151  {
1152  c = 0;
1153  m_bError = true;
1154  }
1155  }
1156  return c;
1157 }
1158 
1160 {
1161  sal_uInt8 c = Peek();
1162  OpenRec( c );
1163  m_pStream->Seek( m_aRecords.back().size );
1164  CloseRec();
1165 }
1166 
1168 {
1169  OSL_ENSURE( !m_bWriteMode, "OpenFlagRec illegal in write mode" );
1170  sal_uInt8 cFlags(0);
1171  m_pStream->ReadUChar( cFlags );
1172  m_nFlagRecEnd = m_pStream->Tell() + ( cFlags & 0x0F );
1173  return (cFlags >> 4);
1174 }
1175 
1177 {
1178  OSL_ENSURE( m_bWriteMode, "OpenFlagRec illegal in read mode" );
1179  OSL_ENSURE( (nFlags & 0xF0) == 0, "illegal flags set" );
1180  OSL_ENSURE( nLen < 16, "wrong flag record length" );
1181  sal_uInt8 cFlags = (nFlags << 4) + nLen;
1182  m_pStream->WriteUChar( cFlags );
1183  m_nFlagRecEnd = m_pStream->Tell() + nLen;
1184 }
1185 
1187 {
1188  if( m_bWriteMode )
1189  {
1190  OSL_ENSURE( m_pStream->Tell() == m_nFlagRecEnd, "Wrong amount of data written" );
1191  }
1192  else
1193  {
1194  OSL_ENSURE( m_pStream->Tell() <= m_nFlagRecEnd, "Too many data read" );
1195  if( m_pStream->Tell() != m_nFlagRecEnd )
1197  }
1198 }
1199 
1200 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SwSectionNode * FindSectionNode()
Search section node, in which it is.
Definition: ndsect.cxx:983
#define SW_LAYCACHE_IO_REC_FLY
Definition: layhelp.hxx:140
SwPageFlyCache m_FlyCache
Definition: layhelp.hxx:61
Base class for the following contact objects (frame + draw objects).
Definition: dcontact.hxx:66
Base class of the Writer layout elements.
Definition: frame.hxx:315
virtual const SwFlyFrame * DynCastFlyFrame() const override
Definition: fly.cxx:2960
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:158
const ::std::optional< sal_uInt16 > & GetNumOffset() const
Definition: fmtpdsc.hxx:64
SwNode & GetEndOfInserts() const
Section for all footnotes.
Definition: ndarr.hxx:151
sal_uLong GetIndex() const
Definition: node.hxx:291
IDocumentStatistics const & getIDocumentStatistics() const
Definition: doc.cxx:373
SwNode & GetEndOfAutotext() const
Section for all Flys/Header/Footers.
Definition: ndarr.hxx:153
sal_Int32 nIndex
bool IsFollow() const
Definition: flowfrm.hxx:166
std::deque< sal_Int32 > m_aOffset
either a textframe character offset, or a row index inside a table
Definition: layhelp.hxx:59
bool m_bUseFlyCache
Definition: layhelp.hxx:62
void CloseRec()
Close a record.
Definition: laycache.cxx:1091
Pagedescriptor Client of SwPageDesc that is "described" by the attribute.
Definition: fmtpdsc.hxx:35
SvStream & WriteUInt16(sal_uInt16 nUInt16)
void ClearImpl()
Definition: laycache.cxx:440
SwPageDesc * GetPageDesc()
Definition: fmtpdsc.hxx:61
sal_uLong nPara
paragraphs for document statistic: non-empty and non-hidden ones
Definition: docstat.hxx:32
virtual const SwRootFrame * GetCurrentLayout() const =0
SvStream & WriteInt32(sal_Int32 nInt32)
SvStream & ReadUInt16(sal_uInt16 &rUInt16)
const SwFrameFormats * GetTableFrameFormats() const
Definition: doc.hxx:811
static void Write(SvStream &rStream, const SwDoc &rDoc)
writes the index (more precise: the difference between the index and the first index of the document ...
Definition: laycache.cxx:163
bool IsUseFlyCache() const
Definition: layhelp.hxx:79
const SwTable * GetTable() const
Definition: tabfrm.hxx:158
void Left(const tools::Long nLeft)
Definition: swrect.hxx:197
SvStream * m_pStream
Definition: layhelp.hxx:155
sal_uInt16 char char * pDesc
SvxBreak GetBreak() const
SwActualSection(SwActualSection *pUpper, SwSectionFrame *pSect, SwSectionNode *pNd)
helper class to create not nested section frames for nested sections.
Definition: laycache.cxx:454
sal_uIntPtr sal_uLong
const SwRect & getFramePrintArea() const
Definition: frame.hxx:181
#define SW_LAYCACHE_IO_REC_TABLE
Definition: layhelp.hxx:139
SwTabFrame is one table in the document layout, containing rows (which contain cells).
Definition: tabfrm.hxx:46
sw::MergedPara * GetMergedPara()
Definition: txtfrm.hxx:450
sal_Int64 n
Definition: doc.hxx:188
#define SW_LAYCACHE_IO_REC_PAGES
Definition: layhelp.hxx:137
bool CheckInsert(sal_uLong nNodeIndex)
entry point for the InsertCnt_-function.
Definition: laycache.cxx:713
sal_uInt64 Seek(sal_uInt64 nPos)
sal_uLong GetBreakIndex(size_t nIdx) const
Definition: layhelp.hxx:72
SwFrame *& mrpPrv
Definition: layhelp.hxx:106
SwNode & GetNode() const
Definition: ndindex.hxx:119
void OpenRec(sal_uInt8 nType)
Open a record of type "nType".
Definition: laycache.cxx:1062
void Pos(const Point &rNew)
Definition: swrect.hxx:171
bool m_bError
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
virtual const SvxFormatBreakItem & GetBreakItem() const
Definition: findfrm.cxx:657
virtual const SwFormatPageDesc & GetPageDescItem() const
Definition: findfrm.cxx:662
static SwFlowFrame * CastFlowFrame(SwFrame *pFrame)
Definition: flowfrm.cxx:2705
size_t size() const
Definition: layhelp.hxx:68
The root element of a Writer document layout.
Definition: rootfrm.hxx:82
SwContact * GetUserCall(const SdrObject *pObj)
Returns the UserCall if applicable from the group object.
Definition: dcontact.cxx:171
sal_uLong nOrdNum
Id to recognize text frames.
Definition: layhelp.hxx:209
std::unique_ptr< SwActualSection > & mrpActualSection
Definition: layhelp.hxx:109
void Read(SvStream &rStream)
Definition: laycache.cxx:68
sal_uInt16 GetPhyPageNum() const
Definition: pagefrm.hxx:204
size_t GetFlyCount() const
Definition: layhelp.hxx:217
size_t mnIndex
the index in the page break array
Definition: layhelp.hxx:116
wrapper class for the positioning of Writer fly frames and drawing objects
sal_uInt16 GetMajorVersion() const
Definition: layhelp.hxx:201
ErrCode GetError() const
sal_uInt16 GetMinorVersion() const
Definition: layhelp.hxx:202
const SwRect & getFrameArea() const
Definition: frame.hxx:180
bool getBrowseMode() const
Definition: viewopt.hxx:472
bool IsTextFrame() const
Definition: frame.hxx:1235
void Width(tools::Long nNew)
Definition: swrect.hxx:189
SvStream & WriteUInt32(sal_uInt32 nUInt32)
bool OnRightPage() const
Definition: frame.hxx:734
bool IsSctFrame() const
Definition: frame.hxx:1215
sal_uInt8 OpenFlagRec()
Open a flag record for reading.
Definition: laycache.cxx:1167
size_type size() const
bool IsFlowFrame() const
Definition: frame.hxx:1243
std::vector< sal_uLong > mIndices
Definition: layhelp.hxx:57
void SkipRec()
Skip the current record.
Definition: laycache.cxx:1159
SwSectionNode * m_pSectNode
Definition: layhelp.hxx:88
SwLayoutCache * GetLayoutCache() const
Definition: doc.hxx:1547
sal_uInt16 m_nMajorVersion
Definition: layhelp.hxx:159
SwNode & GetEndOfContent() const
Regular ContentSection (i.e. the BodyText).
Definition: ndarr.hxx:160
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:457
SwTabFrame * FindMaster(bool bFirstMaster=false) const
Definition: flowfrm.cxx:774
sal_uInt16 nPageNum
page number
Definition: layhelp.hxx:210
const SwSortedObjs * GetSortedObjs() const
Definition: pagefrm.hxx:132
std::vector< RecTypeSize > m_aRecords
Definition: layhelp.hxx:153
bool Read(SvStream &rStream)
Definition: laycache.cxx:87
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:132
SwFlyCache & GetFlyCache(size_t nIdx)
Definition: layhelp.hxx:219
SwPageFrame * FindPageFrame()
Definition: frame.hxx:681
SwLayCacheImpl * LockImpl()
Definition: laycache.hxx:56
bool HasError() const
Definition: layhelp.hxx:199
const SwFrame * Lower() const
Definition: layfrm.hxx:101
SwPageDesc * GetPageDesc()
Definition: pagefrm.hxx:143
void ManipOfst(TextFrameIndex const nNewOfst)
Definition: txtfrm.hxx:441
void SetFollow(SwFlowFrame *const pFollow)
Definition: flowfrm.cxx:92
sal_uInt32 BytesLeft()
Return the number of bytes contained in the current record that haven't been read by now...
Definition: laycache.cxx:1129
SwLayCacheImpl * mpImpl
Definition: layhelp.hxx:112
sal_uInt16 GetBreakType(size_t nIdx) const
Definition: layhelp.hxx:74
SwLayoutFrame * GetUpper()
Definition: frame.hxx:679
void CloseFlagRec()
Close a flag record. Any bytes left are skipped.
Definition: laycache.cxx:1186
size_t mnFlyIdx
the index in the fly cache array
Definition: layhelp.hxx:117
sal_uInt32 GetOrdNum() const
SwFrame * GetPrev()
Definition: frame.hxx:678
size
void SetRepeatedHeadline(bool bNew)
Definition: rowfrm.hxx:91
Marks a node in the document model.
Definition: ndindex.hxx:31
SvStream & ReadUChar(unsigned char &rChar)
ErrCode const & GetErrorCode() const
bool isFrameAreaSizeValid() const
Definition: frame.hxx:168
A page of the document layout.
Definition: pagefrm.hxx:57
sal_uInt8 Peek()
Return the current record's type.
Definition: laycache.cxx:1142
SwTableLines & GetTabLines()
Definition: swtable.hxx:201
static sal_uInt16 nPgNum
Definition: viewport.cxx:52
sal_uLong mnMaxParaPerPage
Definition: layhelp.hxx:113
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:405
sal_uLong nPage
Definition: docstat.hxx:30
void UnlockImpl()
Definition: laycache.hxx:61
SvStream & ReadInt32(sal_Int32 &rInt32)
SwLayoutFrame * FindBodyCont()
Searches the first ContentFrame in BodyText below the page.
Definition: findfrm.cxx:43
const SwPageDesc * GetFollow() const
Definition: pagedesc.hxx:267
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
const_iterator begin() const
#define SW_LAYCACHE_IO_REC_PARA
Definition: layhelp.hxx:138
bool IsLayoutFrame() const
Definition: frame.hxx:1171
SwLayCacheIoImpl(SvStream &rStrm, bool bWrtMd)
Definition: laycache.cxx:1045
bool IsTabFrame() const
Definition: frame.hxx:1219
general base class for all free-flowing frames
Definition: flyfrm.hxx:78
SwLayoutFrame *& mrpLay
Definition: layhelp.hxx:108
bool IsRightPageByNumber(SwRootFrame const &rLayout, sal_uInt16 nPageNum)
Definition: frmtool.cxx:3078
#define ERRCODE_NONE
unsigned char sal_uInt8
const SwViewOption * GetViewOptions() const
Definition: viewsh.hxx:424
bool mbBreakAfter
Definition: layhelp.hxx:110
sal_uInt16 m_nLockCount
Definition: laycache.hxx:44
SwLayHelper(SwDoc *pD, SwFrame *&rpF, SwFrame *&rpP, SwPageFrame *&rpPg, SwLayoutFrame *&rpL, std::unique_ptr< SwActualSection > &rpA, sal_uLong nNodeIndex, bool bCache)
helper class, which utilizes the layout cache information to distribute the document content to the r...
Definition: laycache.cxx:519
SwFrame *& mrpFrame
Definition: layhelp.hxx:105
const SwFrame * ContainsAny(const bool _bInvestigateFootnoteForSections=false) const
Method doesn't investigate content of footnotes by default.
Definition: findfrm.cxx:126
void InsertBehind(SwLayoutFrame *pParent, SwFrame *pBefore)
Insert SwFrame into existing structure.
Definition: wsfrm.cxx:866
SvStream & GetStream() const
Get input or output stream.
Definition: layhelp.hxx:169
virtual const SwDocStat & GetDocStat() const =0
Document - Statistics.
SvStream & WriteUChar(unsigned char nChar)
void RemoveFromLayout()
Definition: wsfrm.cxx:1007
SwNodes & GetNodes()
Definition: doc.hxx:409
SwPageFrame * InsertNewPage(SwPageDesc &rDesc, SwFrame *pUpper, bool isRightPage, bool bFirst, bool bInsertEmpty, bool bFootnote, SwFrame *pSibling, bool bVeryFirstPage=false)
Definition: frmtool.cxx:3089
void Top(const tools::Long nTop)
Definition: swrect.hxx:206
SwFrame * GetLower()
Definition: findfrm.cxx:170
sal_uInt64 Tell() const
QPRO_FUNC_TYPE nType
bool mbFirst
Definition: layhelp.hxx:118
#define SW_LAYCACHE_IO_VERSION_MAJOR
Definition: layhelp.hxx:142
sal_Int32 GetBreakOfst(size_t nIdx) const
Definition: layhelp.hxx:73
std::unique_ptr< SwLayCacheImpl > m_pImpl
Definition: laycache.hxx:43
#define FAR_AWAY
Definition: frmtool.hxx:53
bool CheckInsertPage()
inserts a page and return true, if
Definition: laycache.cxx:636
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
#define SW_LAYCACHE_IO_VERSION_MINOR
Definition: layhelp.hxx:143
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:58
bool IsLocked() const
Definition: laycache.hxx:54
bool good() const
bool CompareLayout(const SwDoc &rDoc) const
Definition: laycache.cxx:325
const SwTabFrame * GetFollow() const
Definition: tabfrm.hxx:250
void Insert(sal_uInt16 nType, sal_uLong nIndex, sal_Int32 nOffset)
Definition: laycache.cxx:80
#define SAL_WARN(area, stream)
size_t size() const
A layout frame is a frame that contains other frames (m_pLower), e.g. SwPageFrame or SwTabFrame...
Definition: layfrm.hxx:35
void RegistFlys(SwPageFrame *, const SwLayoutFrame *)
Definition: frmtool.cxx:3194
SwDoc * mpDoc
Definition: layhelp.hxx:111
const SwLayoutFrame * GetNextLayoutLeaf() const
Definition: frame.hxx:1021
void CheckFlyCache_(SwPageFrame *pPage)
If a new page is inserted, the last page is analysed.
Definition: laycache.cxx:968
std::pair< const_iterator, bool > insert(Value &&x)
SwNode & GetEndOfExtras() const
This is the last EndNode of a special section.
Definition: ndarr.hxx:158
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:207
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
class for collecting anchored objects
Definition: sortedobjs.hxx:48
void Height(tools::Long nNew)
Definition: swrect.hxx:193
sal_uLong CalcPageCount()
Does NOT really calculate the page count, it returns the page count value from the layout cache...
Definition: laycache.cxx:572
sal_uLong mnParagraphCnt
Definition: layhelp.hxx:114
SwRootFrame * getRootFrame()
Definition: frame.hxx:680
sal_uLong mnStartOfContent
Definition: layhelp.hxx:115
sal_uLong m_nFlagRecEnd
Definition: layhelp.hxx:157
sal_uInt16 nPos
sal_uInt16 m_nMinorVersion
Definition: layhelp.hxx:160
SwRowFrame is one table row in the document layout.
Definition: rowfrm.hxx:28
std::vector< sal_uInt16 > m_aType
Definition: layhelp.hxx:60
SwPageFrame *& mrpPage
Definition: layhelp.hxx:107
virtual const SwFrameFormat * GetFormat() const
Definition: ssfrm.cxx:395
SwTableNode * GetTableNode() const
Definition: swtable.cxx:1973
SwFrame * GetNext()
Definition: frame.hxx:677