LCOV - code coverage report
Current view: top level - sw/source/core/layout - laycache.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 421 527 79.9 %
Date: 2014-11-03 Functions: 24 26 92.3 %
Legend: Lines: hit not hit

          Line data    Source code
       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 <editeng/formatbreakitem.hxx>
      21             : #include <doc.hxx>
      22             : #include <IDocumentStatistics.hxx>
      23             : #include <IDocumentLayoutAccess.hxx>
      24             : #include <docstat.hxx>
      25             : #include <docary.hxx>
      26             : #include <fmtpdsc.hxx>
      27             : #include <laycache.hxx>
      28             : #include <layhelp.hxx>
      29             : #include <pagefrm.hxx>
      30             : #include <rootfrm.hxx>
      31             : #include <txtfrm.hxx>
      32             : #include <swtable.hxx>
      33             : #include <tabfrm.hxx>
      34             : #include <rowfrm.hxx>
      35             : #include <sectfrm.hxx>
      36             : #include <fmtcntnt.hxx>
      37             : #include <pagedesc.hxx>
      38             : #include <frmtool.hxx>
      39             : #include <dflyobj.hxx>
      40             : #include <dcontact.hxx>
      41             : #include "viewopt.hxx"
      42             : #include <flyfrm.hxx>
      43             : #include <sortedobjs.hxx>
      44             : 
      45             : #include <set>
      46             : 
      47             : using namespace ::com::sun::star;
      48             : 
      49             : /*
      50             :  *  Reading and writing of the layout cache.
      51             :  *  The layout cache is not necessary, but it improves
      52             :  *  the performance and reduces the text flow during
      53             :  *  the formatting.
      54             :  *  The layout cache contains the index of the paragraphs/tables
      55             :  *  at the top of every page, so it's possible to create
      56             :  *  the right count of pages and to distribute the document content
      57             :  *  to this pages before the formatting starts.
      58             :  */
      59             : 
      60          32 : void SwLayoutCache::Read( SvStream &rStream )
      61             : {
      62          32 :     if( !pImpl )
      63             :     {
      64          32 :         pImpl = new SwLayCacheImpl;
      65          32 :         if( !pImpl->Read( rStream ) )
      66             :         {
      67           0 :             delete pImpl;
      68           0 :             pImpl = 0;
      69             :         }
      70             :     }
      71          32 : }
      72             : 
      73         104 : void SwLayCacheImpl::Insert( sal_uInt16 nType, sal_uLong nIndex, sal_Int32 nOffset )
      74             : {
      75         104 :     aType.push_back( nType );
      76         104 :     mIndices.push_back( nIndex );
      77         104 :     aOffset.push_back( nOffset );
      78         104 : }
      79             : 
      80          32 : bool SwLayCacheImpl::Read( SvStream& rStream )
      81             : {
      82          32 :     SwLayCacheIoImpl aIo( rStream, false );
      83          32 :     if( aIo.GetMajorVersion() > SW_LAYCACHE_IO_VERSION_MAJOR )
      84           0 :         return false;
      85             : 
      86             :     // Due to an evil bug in the layout cache (#102759#), we cannot trust the
      87             :     // sizes of fly frames which have been written using the "old" layout cache.
      88             :     // This flag should indicate that we do not want to trust the width and
      89             :     // height of fly frames
      90          32 :     bUseFlyCache = aIo.GetMinorVersion() >= 1;
      91             : 
      92          32 :     aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
      93          32 :     aIo.OpenFlagRec();
      94          32 :     aIo.CloseFlagRec();
      95         178 :     while( aIo.BytesLeft() && !aIo.HasError() )
      96             :     {
      97         114 :         sal_uInt32 nIndex(0), nOffset(0);
      98             : 
      99         114 :         switch( aIo.Peek() )
     100             :         {
     101             :         case SW_LAYCACHE_IO_REC_PARA:
     102             :         {
     103         102 :             aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
     104         102 :             sal_uInt8 cFlags = aIo.OpenFlagRec();
     105         102 :             aIo.GetStream().ReadUInt32( nIndex );
     106         102 :             if( (cFlags & 0x01) != 0 )
     107          10 :                 aIo.GetStream().ReadUInt32( nOffset );
     108             :             else
     109          92 :                 nOffset = COMPLETE_STRING;
     110         102 :             aIo.CloseFlagRec();
     111         102 :             Insert( SW_LAYCACHE_IO_REC_PARA, nIndex, (sal_Int32)nOffset );
     112         102 :             aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
     113         102 :             break;
     114             :         }
     115             :         case SW_LAYCACHE_IO_REC_TABLE:
     116           2 :             aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
     117           2 :             aIo.OpenFlagRec();
     118           2 :             aIo.GetStream().ReadUInt32( nIndex )
     119           2 :                            .ReadUInt32( nOffset );
     120           2 :             Insert( SW_LAYCACHE_IO_REC_TABLE, nIndex, (sal_Int32)nOffset );
     121           2 :             aIo.CloseFlagRec();
     122           2 :             aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
     123           2 :             break;
     124             :         case SW_LAYCACHE_IO_REC_FLY:
     125             :         {
     126          10 :             aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
     127          10 :             aIo.OpenFlagRec();
     128          10 :             aIo.CloseFlagRec();
     129          10 :             sal_Int32 nX(0), nY(0), nW(0), nH(0);
     130          10 :             sal_uInt16 nPgNum(0);
     131          10 :             aIo.GetStream().ReadUInt16( nPgNum ).ReadUInt32( nIndex )
     132          10 :                    .ReadInt32( nX ).ReadInt32( nY ).ReadInt32( nW ).ReadInt32( nH );
     133          10 :             SwFlyCache* pFly = new SwFlyCache( nPgNum, nIndex, nX, nY, nW, nH );
     134          10 :             aFlyCache.push_back( pFly );
     135          10 :             aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
     136          10 :             break;
     137             :         }
     138             :         default:
     139           0 :             aIo.SkipRec();
     140           0 :             break;
     141             :         }
     142             :     }
     143          32 :     aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
     144             : 
     145          32 :     return !aIo.HasError();
     146             : }
     147             : 
     148             : /** writes the index (more precise: the difference between
     149             :  * the index and the first index of the document content)
     150             :  * of the first paragraph/table at the top of every page.
     151             :  * If at the top of a page is the rest of a paragraph/table
     152             :  * from the bottom of the previous page, the character/row
     153             :  * number is stored, too.
     154             :  * The position, size and page number of the text frames
     155             :  * are stored, too
     156             :  */
     157           6 : void SwLayoutCache::Write( SvStream &rStream, const SwDoc& rDoc )
     158             : {
     159           6 :     if( rDoc.getIDocumentLayoutAccess().GetCurrentLayout() ) // the layout itself ..
     160             :     {
     161           6 :         SwLayCacheIoImpl aIo( rStream, true );
     162             :         // We want to save the relative index, so we need the index
     163             :         // of the first content
     164           6 :         sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
     165           6 :                                 StartOfSectionNode()->GetIndex();
     166             :         // The first page..
     167           6 :         SwPageFrm* pPage = (SwPageFrm*)rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->Lower();
     168             : 
     169           6 :         aIo.OpenRec( SW_LAYCACHE_IO_REC_PAGES );
     170           6 :         aIo.OpenFlagRec( 0, 0 );
     171           6 :         aIo.CloseFlagRec();
     172          40 :         while( pPage )
     173             :         {
     174          28 :             if( pPage->GetPrev() )
     175             :             {
     176          22 :                 SwLayoutFrm* pLay = pPage->FindBodyCont();
     177          22 :                 SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
     178             :                 // We are only interested in paragraph or table frames,
     179             :                 // a section frames contains paragraphs/tables.
     180          22 :                 if( pTmp && pTmp->IsSctFrm() )
     181           0 :                     pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
     182             : 
     183          22 :                 if( pTmp ) // any content
     184             :                 {
     185          22 :                     if( pTmp->IsTxtFrm() )
     186             :                     {
     187          22 :                         sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
     188          22 :                         if( nNdIdx > nStartOfContent )
     189             :                         {
     190             :                             /*  Open Paragraph Record */
     191          22 :                             aIo.OpenRec( SW_LAYCACHE_IO_REC_PARA );
     192          22 :                             bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
     193             :                             aIo.OpenFlagRec( bFollow ? 0x01 : 0x00,
     194          22 :                                             bFollow ? 8 : 4 );
     195          22 :                             nNdIdx -= nStartOfContent;
     196          22 :                             aIo.GetStream().WriteUInt32( nNdIdx );
     197          22 :                             if( bFollow )
     198           8 :                                 aIo.GetStream().WriteUInt32( ((SwTxtFrm*)pTmp)->GetOfst() );
     199          22 :                             aIo.CloseFlagRec();
     200             :                             /*  Close Paragraph Record */
     201          22 :                             aIo.CloseRec( SW_LAYCACHE_IO_REC_PARA );
     202             :                         }
     203             :                     }
     204           0 :                     else if( pTmp->IsTabFrm() )
     205             :                     {
     206           0 :                         SwTabFrm* pTab = (SwTabFrm*)pTmp;
     207           0 :                         sal_uLong nOfst = COMPLETE_STRING;
     208           0 :                         if( pTab->IsFollow() )
     209             :                         {
     210             :                             // If the table is a follow, we have to look for the
     211             :                             // master and to count all rows to get the row number
     212           0 :                             nOfst = 0;
     213           0 :                             if( pTab->IsFollow() )
     214           0 :                                 pTab = pTab->FindMaster( true );
     215           0 :                             while( pTab != pTmp )
     216             :                             {
     217           0 :                                 SwFrm* pSub = pTab->Lower();
     218           0 :                                 while( pSub )
     219             :                                 {
     220           0 :                                     ++nOfst;
     221           0 :                                     pSub = pSub->GetNext();
     222             :                                 }
     223           0 :                                 pTab = pTab->GetFollow();
     224             :                                 OSL_ENSURE( pTab, "Table follow without master" );
     225             :                             }
     226             :                         }
     227           0 :                         do
     228             :                         {
     229             :                             sal_uLong nNdIdx =
     230           0 :                                     pTab->GetTable()->GetTableNode()->GetIndex();
     231           0 :                             if( nNdIdx > nStartOfContent )
     232             :                             {
     233             :                                 /* Open Table Record */
     234           0 :                                 aIo.OpenRec( SW_LAYCACHE_IO_REC_TABLE );
     235           0 :                                 aIo.OpenFlagRec( 0, 8 );
     236           0 :                                 nNdIdx -= nStartOfContent;
     237           0 :                                 aIo.GetStream().WriteUInt32( nNdIdx )
     238           0 :                                                .WriteUInt32( nOfst );
     239           0 :                                 aIo.CloseFlagRec();
     240             :                                 /* Close Table Record  */
     241           0 :                                 aIo.CloseRec( SW_LAYCACHE_IO_REC_TABLE );
     242             :                             }
     243             :                             // If the table has a follow on the next page,
     244             :                             // we know already the row number and store this
     245             :                             // immediately.
     246           0 :                             if( pTab->GetFollow() )
     247             :                             {
     248           0 :                                 if( nOfst == (sal_uLong) COMPLETE_STRING )
     249           0 :                                     nOfst = 0;
     250           0 :                                 do
     251             :                                 {
     252           0 :                                     SwFrm* pSub = pTab->Lower();
     253           0 :                                     while( pSub )
     254             :                                     {
     255           0 :                                         ++nOfst;
     256           0 :                                         pSub = pSub->GetNext();
     257             :                                     }
     258           0 :                                     pTab = pTab->GetFollow();
     259           0 :                                     SwPageFrm *pTabPage = pTab->FindPageFrm();
     260           0 :                                     if( pTabPage != pPage )
     261             :                                     {
     262             :                                         OSL_ENSURE( pPage->GetPhyPageNum() <
     263             :                                                 pTabPage->GetPhyPageNum(),
     264             :                                                 "Looping Tableframes" );
     265           0 :                                         pPage = pTabPage;
     266           0 :                                         break;
     267             :                                     }
     268           0 :                                 } while ( pTab->GetFollow() );
     269             :                             }
     270             :                             else
     271           0 :                                 break;
     272             :                         } while( pTab );
     273             :                     }
     274             :                 }
     275             :             }
     276          28 :             if( pPage->GetSortedObjs() )
     277             :             {
     278           4 :                 SwSortedObjs &rObjs = *pPage->GetSortedObjs();
     279           8 :                 for ( size_t i = 0; i < rObjs.size(); ++i )
     280             :                 {
     281           4 :                     SwAnchoredObject* pAnchoredObj = rObjs[i];
     282           4 :                     if ( pAnchoredObj->ISA(SwFlyFrm) )
     283             :                     {
     284           0 :                         SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
     285           0 :                         if( pFly->Frm().Left() != FAR_AWAY &&
     286           0 :                             !pFly->GetAnchorFrm()->FindFooterOrHeader() )
     287             :                         {
     288             :                             const SwContact *pC =
     289           0 :                                     ::GetUserCall(pAnchoredObj->GetDrawObj());
     290           0 :                             if( pC )
     291             :                             {
     292           0 :                                 sal_uInt32 nOrdNum = pAnchoredObj->GetDrawObj()->GetOrdNum();
     293           0 :                                 sal_uInt16 nPageNum = pPage->GetPhyPageNum();
     294             :                                 /* Open Fly Record */
     295           0 :                                 aIo.OpenRec( SW_LAYCACHE_IO_REC_FLY );
     296           0 :                                 aIo.OpenFlagRec( 0, 0 );
     297           0 :                                 aIo.CloseFlagRec();
     298           0 :                                 SwRect &rRct = pFly->Frm();
     299           0 :                                 sal_Int32 nX = rRct.Left() - pPage->Frm().Left();
     300           0 :                                 sal_Int32 nY = rRct.Top() - pPage->Frm().Top();
     301           0 :                                 aIo.GetStream().WriteUInt16( nPageNum ).WriteUInt32( nOrdNum )
     302           0 :                                                .WriteInt32( nX ).WriteInt32( nY )
     303           0 :                                                .WriteInt32( rRct.Width() )
     304           0 :                                                .WriteInt32( rRct.Height() );
     305             :                                 /* Close Fly Record  */
     306           0 :                                 aIo.CloseRec( SW_LAYCACHE_IO_REC_FLY );
     307             :                             }
     308             :                         }
     309             :                     }
     310             :                 }
     311             :             }
     312          28 :             pPage = (SwPageFrm*)pPage->GetNext();
     313             :         }
     314           6 :         aIo.CloseRec( SW_LAYCACHE_IO_REC_PAGES );
     315             :     }
     316           6 : }
     317             : 
     318             : #ifdef DBG_UTIL
     319             : bool SwLayoutCache::CompareLayout( const SwDoc& rDoc ) const
     320             : {
     321             :     if( !pImpl )
     322             :         return true;
     323             :     const SwRootFrm *pRootFrm = rDoc.getIDocumentLayoutAccess().GetCurrentLayout();
     324             :     if( pRootFrm )
     325             :     {
     326             :         sal_uInt16 nIndex = 0;
     327             :         sal_uLong nStartOfContent = rDoc.GetNodes().GetEndOfContent().
     328             :                                 StartOfSectionNode()->GetIndex();
     329             :         SwPageFrm* pPage = (SwPageFrm*)pRootFrm->Lower();
     330             :         if( pPage )
     331             :             pPage = (SwPageFrm*)pPage->GetNext();
     332             :         while( pPage )
     333             :         {
     334             :             if( nIndex >= pImpl->size() )
     335             :                 return false;
     336             : 
     337             :             SwLayoutFrm* pLay = pPage->FindBodyCont();
     338             :             SwFrm* pTmp = pLay ? pLay->ContainsAny() : NULL;
     339             :             if( pTmp && pTmp->IsSctFrm() )
     340             :                 pTmp = ((SwSectionFrm*)pTmp)->ContainsAny();
     341             :             if( pTmp )
     342             :             {
     343             :                 if( pTmp->IsTxtFrm() )
     344             :                 {
     345             :                     sal_uLong nNdIdx = ((SwTxtFrm*)pTmp)->GetNode()->GetIndex();
     346             :                     if( nNdIdx > nStartOfContent )
     347             :                     {
     348             :                         bool bFollow = ((SwTxtFrm*)pTmp)->IsFollow();
     349             :                         nNdIdx -= nStartOfContent;
     350             :                         if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
     351             :                             SW_LAYCACHE_IO_REC_PARA !=
     352             :                             pImpl->GetBreakType( nIndex ) ||
     353             :                             ( bFollow ? ((SwTxtFrm*)pTmp)->GetOfst()
     354             :                               : COMPLETE_STRING ) != pImpl->GetBreakOfst( nIndex ) )
     355             :                         {
     356             :                             return false;
     357             :                         }
     358             :                         ++nIndex;
     359             :                     }
     360             :                 }
     361             :                 else if( pTmp->IsTabFrm() )
     362             :                 {
     363             :                     SwTabFrm* pTab = (SwTabFrm*)pTmp;
     364             :                     sal_Int32 nOfst = COMPLETE_STRING;
     365             :                     if( pTab->IsFollow() )
     366             :                     {
     367             :                         nOfst = 0;
     368             :                         if( pTab->IsFollow() )
     369             :                             pTab = pTab->FindMaster( true );
     370             :                         while( pTab != pTmp )
     371             :                         {
     372             :                             SwFrm* pSub = pTab->Lower();
     373             :                             while( pSub )
     374             :                             {
     375             :                                 ++nOfst;
     376             :                                 pSub = pSub->GetNext();
     377             :                             }
     378             :                             pTab = pTab->GetFollow();
     379             :                         }
     380             :                     }
     381             :                     do
     382             :                     {
     383             :                         sal_uLong nNdIdx =
     384             :                                 pTab->GetTable()->GetTableNode()->GetIndex();
     385             :                         if( nNdIdx > nStartOfContent )
     386             :                         {
     387             :                             nNdIdx -= nStartOfContent;
     388             :                             if( pImpl->GetBreakIndex( nIndex ) != nNdIdx ||
     389             :                                 SW_LAYCACHE_IO_REC_TABLE !=
     390             :                                 pImpl->GetBreakType( nIndex ) ||
     391             :                                nOfst != pImpl->GetBreakOfst( nIndex ) )
     392             :                             {
     393             :                                 return false;
     394             :                             }
     395             :                             ++nIndex;
     396             :                         }
     397             :                         if( pTab->GetFollow() )
     398             :                         {
     399             :                             if( nOfst == COMPLETE_STRING )
     400             :                                 nOfst = 0;
     401             :                             do
     402             :                             {
     403             :                                 SwFrm* pSub = pTab->Lower();
     404             :                                 while( pSub )
     405             :                                 {
     406             :                                     ++nOfst;
     407             :                                     pSub = pSub->GetNext();
     408             :                                 }
     409             :                                 pTab = pTab->GetFollow();
     410             :                                 SwPageFrm *pTabPage = pTab->FindPageFrm();
     411             :                                 if( pTabPage != pPage )
     412             :                                 {
     413             :                                     pPage = pTabPage;
     414             :                                     break;
     415             :                                 }
     416             :                             } while ( pTab->GetFollow() );
     417             :                         }
     418             :                         else
     419             :                             break;
     420             :                     } while( pTab );
     421             :                 }
     422             :             }
     423             :             pPage = (SwPageFrm*)pPage->GetNext();
     424             :         }
     425             :     }
     426             :     return true;
     427             : }
     428             : #endif
     429             : 
     430          28 : void SwLayoutCache::ClearImpl()
     431             : {
     432          28 :     if( !IsLocked() )
     433             :     {
     434          28 :         delete pImpl;
     435          28 :         pImpl = 0;
     436             :     }
     437          28 : }
     438             : 
     439          32 : SwLayoutCache::~SwLayoutCache()
     440             : {
     441             :     OSL_ENSURE( !nLockCount, "Deleting a locked SwLayoutCache!?" );
     442          32 :     delete pImpl;
     443          32 : }
     444             : 
     445             : /// helper class to create not nested section frames for nested sections.
     446         592 : SwActualSection::SwActualSection( SwActualSection *pUp,
     447             :                                   SwSectionFrm    *pSect,
     448             :                                   SwSectionNode   *pNd ) :
     449             :     pUpper( pUp ),
     450             :     pSectFrm( pSect ),
     451         592 :     pSectNode( pNd )
     452             : {
     453         592 :     if ( !pSectNode )
     454             :     {
     455           6 :         const SwNodeIndex *pIndex = pSect->GetFmt()->GetCntnt().GetCntntIdx();
     456           6 :         pSectNode = pIndex->GetNode().FindSectionNode();
     457             :     }
     458         592 : }
     459             : 
     460             : /** helper class, which utilizes the layout cache information
     461             :  *  to distribute the document content to the right pages.
     462             :  * It's used by the _InsertCnt(..)-function.
     463             :  * If there's no layout cache, the distibution to the pages is more
     464             :  * a guess, but a guess with statistical background.
     465             :  */
     466        5266 : SwLayHelper::SwLayHelper( SwDoc *pD, SwFrm* &rpF, SwFrm* &rpP, SwPageFrm* &rpPg,
     467             :                           SwLayoutFrm* &rpL, SwActualSection* &rpA, bool &rB,
     468             :                           sal_uLong nNodeIndex, bool bCache )
     469             :     : rpFrm( rpF )
     470             :     , rpPrv( rpP )
     471             :     , rpPage( rpPg )
     472             :     , rpLay( rpL )
     473             :     , rpActualSection( rpA )
     474             :     , rbBreakAfter(rB)
     475             :     , pDoc(pD)
     476             :     , nMaxParaPerPage( 25 )
     477             :     , nParagraphCnt( bCache ? 0 : USHRT_MAX )
     478             :     , nFlyIdx( 0 )
     479        5266 :     , bFirst( bCache )
     480             : {
     481        5266 :     pImpl = pDoc->GetLayoutCache() ? pDoc->GetLayoutCache()->LockImpl() : NULL;
     482        5266 :     if( pImpl )
     483             :     {
     484          28 :         nMaxParaPerPage = 1000;
     485          28 :         nStartOfContent = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()
     486          28 :                           ->GetIndex();
     487          28 :         nNodeIndex -= nStartOfContent;
     488          28 :         nIndex = 0;
     489          56 :         while( nIndex < pImpl->size() && pImpl->GetBreakIndex( nIndex ) < nNodeIndex )
     490             :         {
     491           0 :             ++nIndex;
     492             :         }
     493          28 :         if( nIndex >= pImpl->size() )
     494             :         {
     495           0 :             pDoc->GetLayoutCache()->UnlockImpl();
     496           0 :             pImpl = NULL;
     497             :         }
     498             :     }
     499             :     else
     500             :     {
     501        5238 :         nIndex = USHRT_MAX;
     502        5238 :         nStartOfContent = ULONG_MAX;
     503             :     }
     504        5266 : }
     505             : 
     506        5266 : SwLayHelper::~SwLayHelper()
     507             : {
     508        5266 :     if( pImpl )
     509             :     {
     510             :         OSL_ENSURE( pDoc && pDoc->GetLayoutCache(), "Missing layoutcache" );
     511          28 :         pDoc->GetLayoutCache()->UnlockImpl();
     512             :     }
     513        5266 : }
     514             : 
     515             : /** Does NOT really calculate the page count,
     516             :  * it returns the page count value from the layout cache, if available,
     517             :  * otherwise it estimates the page count.
     518             :  */
     519        5266 : sal_uLong SwLayHelper::CalcPageCount()
     520             : {
     521             :     sal_uLong nPgCount;
     522        5266 :     SwLayCacheImpl *pCache = pDoc->GetLayoutCache() ?
     523        5266 :                              pDoc->GetLayoutCache()->LockImpl() : NULL;
     524        5266 :     if( pCache )
     525             :     {
     526          28 :         nPgCount = pCache->size() + 1;
     527          28 :         pDoc->GetLayoutCache()->UnlockImpl();
     528             :     }
     529             :     else
     530             :     {
     531        5238 :         nPgCount = pDoc->getIDocumentStatistics().GetDocStat().nPage;
     532        5238 :         if ( nPgCount <= 10 ) // no page insertion for less than 10 pages
     533        5238 :             nPgCount = 0;
     534        5238 :         sal_uLong nNdCount = pDoc->getIDocumentStatistics().GetDocStat().nPara;
     535        5238 :         if ( nNdCount <= 1 )
     536             :         {
     537             :             //Estimates the number of paragraphs.
     538        5108 :             sal_uLong nTmp = pDoc->GetNodes().GetEndOfContent().GetIndex() -
     539        5108 :                         pDoc->GetNodes().GetEndOfExtras().GetIndex();
     540             :             //Tables have a little overhead..
     541        5108 :             nTmp -= pDoc->GetTblFrmFmts()->size() * 25;
     542             :             //Fly frames, too ..
     543       10216 :             nTmp -= (pDoc->GetNodes().GetEndOfAutotext().GetIndex() -
     544       10216 :                        pDoc->GetNodes().GetEndOfInserts().GetIndex()) / 3 * 5;
     545        5108 :             if ( nTmp > 0 )
     546        5070 :                 nNdCount = nTmp;
     547             :         }
     548        5238 :         if ( nNdCount > 100 ) // no estimation below this value
     549             :         {
     550        1910 :             if ( nPgCount > 0 )
     551           0 :                 nMaxParaPerPage = nNdCount / nPgCount;
     552             :             else
     553             :             {
     554             :                 nMaxParaPerPage = std::max( sal_uLong(20),
     555        1910 :                                        sal_uLong(20 + nNdCount / 1000 * 3) );
     556        1910 :                 const sal_uLong nMax = 53;
     557        1910 :                 nMaxParaPerPage = std::min( nMaxParaPerPage, nMax );
     558        1910 :                 nPgCount = nNdCount / nMaxParaPerPage;
     559             :             }
     560        1910 :             if ( nNdCount < 1000 )
     561          90 :                 nPgCount = 0;// no progress bar for small documents
     562        1910 :             SwViewShell *pSh = 0;
     563        1910 :             if( rpLay && rpLay->getRootFrm() )
     564        1910 :                 pSh = rpLay->getRootFrm()->GetCurrShell();
     565        1910 :             if( pSh && pSh->GetViewOptions()->getBrowseMode() )
     566           0 :                 nMaxParaPerPage *= 6;
     567             :         }
     568             :     }
     569        5266 :     return nPgCount;
     570             : }
     571             : 
     572             : /**
     573             :  * inserts a page and return true, if
     574             :  * - the break after flag is set
     575             :  * - the actual content wants a break before
     576             :  * - the maximum count of paragraph/rows is reached
     577             :  *
     578             :  * The break after flag is set, if the actual content
     579             :  * wants a break after.
     580             :  */
     581       24940 : bool SwLayHelper::CheckInsertPage()
     582             : {
     583       24940 :     bool bEnd = 0 == rpPage->GetNext();
     584       24940 :     const SwAttrSet* pAttr = rpFrm->GetAttrSet();
     585       24940 :     const SvxFmtBreakItem& rBrk = pAttr->GetBreak();
     586       24940 :     const SwFmtPageDesc& rDesc = pAttr->GetPageDesc();
     587             :     // #118195# Do not evaluate page description if frame
     588             :     // is a follow frame!
     589       49880 :     const SwPageDesc* pDesc = rpFrm->IsFlowFrm() &&
     590       24940 :                               SwFlowFrm::CastFlowFrm( rpFrm )->IsFollow() ?
     591             :                               0 :
     592       49730 :                               rDesc.GetPageDesc();
     593             : 
     594       24940 :     bool bBrk = nParagraphCnt > nMaxParaPerPage || rbBreakAfter;
     595       49880 :     rbBreakAfter = rBrk.GetBreak() == SVX_BREAK_PAGE_AFTER ||
     596       74820 :                    rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
     597       24940 :     if ( !bBrk )
     598       47652 :         bBrk = rBrk.GetBreak() == SVX_BREAK_PAGE_BEFORE ||
     599       47652 :                rBrk.GetBreak() == SVX_BREAK_PAGE_BOTH;
     600             : 
     601       24940 :     if ( bBrk || pDesc )
     602             :     {
     603        1662 :         ::boost::optional<sal_uInt16> oPgNum;
     604        1662 :         if ( !pDesc )
     605             :         {
     606        1432 :             pDesc = rpPage->GetPageDesc()->GetFollow();
     607             : 
     608        1432 :             SwFmtPageDesc aFollowDesc( pDesc );
     609        1432 :             oPgNum = aFollowDesc.GetNumOffset();
     610        1432 :             if ( oPgNum )
     611           0 :                 ((SwRootFrm*)rpPage->GetUpper())->SetVirtPageNum(true);
     612             :         }
     613             :         else
     614             :         {
     615         230 :             oPgNum = rDesc.GetNumOffset();
     616         230 :             if ( oPgNum )
     617          30 :                 ((SwRootFrm*)rpPage->GetUpper())->SetVirtPageNum(true);
     618             :         }
     619        1662 :         bool bNextPageOdd = !rpPage->OnRightPage();
     620        1662 :         bool bInsertEmpty = false;
     621        1662 :         if( oPgNum && bNextPageOdd != ( ( oPgNum.get() % 2 ) != 0 ) )
     622             :         {
     623          18 :             bNextPageOdd = !bNextPageOdd;
     624          18 :             bInsertEmpty = true;
     625             :         }
     626             :         // If the page style is changing, we'll have a first page.
     627        1662 :         bool bNextPageFirst = pDesc != rpPage->GetPageDesc();
     628        1662 :         ::InsertNewPage( (SwPageDesc&)*pDesc, rpPage->GetUpper(),
     629        3324 :                          bNextPageOdd, bNextPageFirst, bInsertEmpty, false, rpPage->GetNext() );
     630        1662 :         if ( bEnd )
     631             :         {
     632             :             OSL_ENSURE( rpPage->GetNext(), "No new page?" );
     633        1684 :             do
     634        1684 :             {   rpPage = (SwPageFrm*)rpPage->GetNext();
     635        1684 :             } while ( rpPage->GetNext() );
     636             :         }
     637             :         else
     638             :         {
     639             :             OSL_ENSURE( rpPage->GetNext(), "No new page?" );
     640           0 :             rpPage = (SwPageFrm*)rpPage->GetNext();
     641           0 :             if ( rpPage->IsEmptyPage() )
     642             :             {
     643             :                 OSL_ENSURE( rpPage->GetNext(), "No new page?" );
     644           0 :                 rpPage = (SwPageFrm*)rpPage->GetNext();
     645             :             }
     646             :         }
     647        1662 :         rpLay = rpPage->FindBodyCont();
     648        3344 :         while( rpLay->Lower() )
     649          20 :             rpLay = (SwLayoutFrm*)rpLay->Lower();
     650        1662 :         return true;
     651             :     }
     652       23278 :     return false;
     653             : }
     654             : 
     655             : /** entry point for the _InsertCnt-function.
     656             :  *  The document content index is checked either it is
     657             :  *  in the layout cache either it's time to insert a page
     658             :  *  cause the maximal estimation of content per page is reached.
     659             :  *  A really big table or long paragraph may contains more than
     660             :  *  one page, in this case the needed count of pages will inserted.
     661             :  */
     662       30072 : bool SwLayHelper::CheckInsert( sal_uLong nNodeIndex )
     663             : {
     664       30072 :     bool bRet = false;
     665       30072 :     bool bLongTab = false;
     666       30072 :     sal_uLong nMaxRowPerPage( 0 );
     667       30072 :     nNodeIndex -= nStartOfContent;
     668       30072 :     sal_uInt16 nRows( 0 );
     669       30072 :     if( rpFrm->IsTabFrm() )
     670             :     {
     671             :         //Inside a table counts every row as a paragraph
     672         784 :         SwFrm *pLow = ((SwTabFrm*)rpFrm)->Lower();
     673         784 :         nRows = 0;
     674        4392 :         do
     675             :         {
     676        4392 :             ++nRows;
     677        4392 :             pLow = pLow->GetNext();
     678             :         } while ( pLow );
     679         784 :         nParagraphCnt += nRows;
     680         784 :         if( !pImpl && nParagraphCnt > nMaxParaPerPage + 10 )
     681             :         {
     682             :             // OD 09.04.2003 #108698# - improve heuristics:
     683             :             // Assume that a table, which has more than three times the quantity
     684             :             // of maximal paragraphs per page rows, consists of rows, which have
     685             :             // the height of a normal paragraph. Thus, allow as much rows per page
     686             :             // as much paragraphs are allowed.
     687          30 :             if ( nRows > ( 3*nMaxParaPerPage ) )
     688             :             {
     689           8 :                 nMaxRowPerPage = nMaxParaPerPage;
     690             :             }
     691             :             else
     692             :             {
     693          22 :                 SwFrm *pTmp = ((SwTabFrm*)rpFrm)->Lower();
     694          22 :                 if( pTmp->GetNext() )
     695          22 :                     pTmp = pTmp->GetNext();
     696          22 :                 pTmp = ((SwRowFrm*)pTmp)->Lower();
     697          22 :                 sal_uInt16 nCnt = 0;
     698          62 :                 do
     699             :                 {
     700          62 :                     ++nCnt;
     701          62 :                     pTmp = pTmp->GetNext();
     702             :                 } while( pTmp );
     703          22 :                 nMaxRowPerPage = std::max( sal_uLong(2), nMaxParaPerPage / nCnt );
     704             :             }
     705          30 :             bLongTab = true;
     706             :         }
     707             :     }
     708             :     else
     709       29288 :         ++nParagraphCnt;
     710       35366 :     if( bFirst && pImpl && nIndex < pImpl->size() &&
     711       30102 :         pImpl->GetBreakIndex( nIndex ) == nNodeIndex &&
     712           6 :         ( pImpl->GetBreakOfst( nIndex ) < COMPLETE_STRING ||
     713           6 :           ( ++nIndex < pImpl->size() &&
     714           2 :           pImpl->GetBreakIndex( nIndex ) == nNodeIndex ) ) )
     715           0 :         bFirst = false;
     716             : #if OSL_DEBUG_LEVEL > 1
     717             :     sal_uLong nBreakIndex = ( pImpl && nIndex < pImpl->size() ) ?
     718             :                         pImpl->GetBreakIndex(nIndex) : 0xffff;
     719             :     (void)nBreakIndex;
     720             : #endif
     721             :     // OD 09.04.2003 #108698# - always split a big tables.
     722       60156 :     if ( !bFirst ||
     723        5630 :          ( rpFrm->IsTabFrm() && bLongTab )
     724             :        )
     725             :     {
     726       24818 :         sal_Int32 nRowCount = 0;
     727       24940 :         do
     728             :         {
     729       24940 :             if( pImpl || bLongTab )
     730             :             {
     731             : #if OSL_DEBUG_LEVEL > 1
     732             :                 sal_uLong nBrkIndex = ( pImpl && nIndex < pImpl->size() ) ?
     733             :                         pImpl->GetBreakIndex(nIndex) : 0xffff;
     734             :                 (void)nBrkIndex;
     735             : #endif
     736         322 :                 sal_Int32 nOfst = COMPLETE_STRING;
     737         322 :                 sal_uInt16 nType = SW_LAYCACHE_IO_REC_PAGES;
     738         322 :                 if( bLongTab )
     739             :                 {
     740         150 :                     rbBreakAfter = true;
     741         150 :                     nOfst = static_cast<sal_Int32>(nRowCount + nMaxRowPerPage);
     742             :                 }
     743             :                 else
     744             :                 {
     745         506 :                     while( nIndex < pImpl->size() &&
     746         162 :                            pImpl->GetBreakIndex(nIndex) < nNodeIndex)
     747           0 :                         ++nIndex;
     748         334 :                     if( nIndex < pImpl->size() &&
     749         162 :                         pImpl->GetBreakIndex(nIndex) == nNodeIndex )
     750             :                     {
     751          64 :                         nType = pImpl->GetBreakType( nIndex );
     752          64 :                         nOfst = pImpl->GetBreakOfst( nIndex++ );
     753          64 :                         rbBreakAfter = true;
     754             :                     }
     755             :                 }
     756             : 
     757         322 :                 if( nOfst < COMPLETE_STRING )
     758             :                 {
     759         158 :                     bool bSplit = false;
     760         158 :                     sal_uInt16 nRepeat( 0 );
     761         324 :                     if( !bLongTab && rpFrm->IsTxtFrm() &&
     762         166 :                         SW_LAYCACHE_IO_REC_PARA == nType &&
     763           8 :                         nOfst<((SwTxtFrm*)rpFrm)->GetTxtNode()->GetTxt().getLength())
     764           8 :                         bSplit = true;
     765         300 :                     else if( rpFrm->IsTabFrm() && nRowCount < nOfst &&
     766           0 :                              ( bLongTab || SW_LAYCACHE_IO_REC_TABLE == nType ) )
     767             :                     {
     768             :                         nRepeat = ((SwTabFrm*)rpFrm)->
     769         150 :                                   GetTable()->GetRowsToRepeat();
     770         150 :                         bSplit = nOfst < nRows && nRowCount + nRepeat < nOfst;
     771         150 :                         bLongTab = bLongTab && bSplit;
     772             :                     }
     773         158 :                     if( bSplit )
     774             :                     {
     775         128 :                         rpFrm->InsertBehind( rpLay, rpPrv );
     776         128 :                         rpFrm->Frm().Pos() = rpLay->Frm().Pos();
     777         128 :                         rpFrm->Frm().Pos().Y() += 1;
     778         128 :                         rpPrv = rpFrm;
     779         128 :                         if( rpFrm->IsTabFrm() )
     780             :                         {
     781         120 :                             SwTabFrm* pTab = (SwTabFrm*)rpFrm;
     782             :                             // #i33629#, #i29955#
     783         120 :                             ::RegistFlys( pTab->FindPageFrm(), pTab );
     784         120 :                             SwFrm *pRow = pTab->Lower();
     785         120 :                             SwTabFrm *pFoll = new SwTabFrm( *pTab );
     786             : 
     787             :                             SwFrm *pPrv;
     788         120 :                             if( nRepeat > 0 )
     789             :                             {
     790           0 :                                 bDontCreateObjects = true; //frmtool
     791             : 
     792             :                                 // Insert new headlines:
     793           0 :                                 sal_uInt16 nRowIdx = 0;
     794           0 :                                 SwRowFrm* pHeadline = 0;
     795           0 :                                 while( nRowIdx < nRepeat )
     796             :                                 {
     797             :                                     OSL_ENSURE( pTab->GetTable()->GetTabLines()[ nRowIdx ], "Table ohne Zeilen?" );
     798             :                                     pHeadline =
     799           0 :                                         new SwRowFrm( *pTab->GetTable()->GetTabLines()[ nRowIdx ], pTab );
     800           0 :                                     pHeadline->SetRepeatedHeadline( true );
     801           0 :                                     pHeadline->InsertBefore( pFoll, 0 );
     802           0 :                                     pHeadline->RegistFlys();
     803             : 
     804           0 :                                     ++nRowIdx;
     805             :                                 }
     806             : 
     807           0 :                                 bDontCreateObjects = false;
     808           0 :                                 pPrv = pHeadline;
     809           0 :                                 nRows = nRows + nRepeat;
     810             :                             }
     811             :                             else
     812         120 :                                 pPrv = 0;
     813        1788 :                             while( pRow && nRowCount < nOfst )
     814             :                             {
     815        1548 :                                 pRow = pRow->GetNext();
     816        1548 :                                 ++nRowCount;
     817             :                             }
     818        6728 :                             while ( pRow )
     819             :                             {
     820        6488 :                                 SwFrm* pNxt = pRow->GetNext();
     821        6488 :                                 pRow->Remove();
     822        6488 :                                 pRow->InsertBehind( pFoll, pPrv );
     823        6488 :                                 pPrv = pRow;
     824        6488 :                                 pRow = pNxt;
     825             :                             }
     826         120 :                             rpFrm = pFoll;
     827             :                         }
     828             :                         else
     829             :                         {
     830             :                             SwTxtFrm *const pNew = static_cast<SwTxtFrm*>(
     831             :                                 static_cast<SwTxtFrm*>(rpFrm)
     832           8 :                                     ->GetTxtNode()->MakeFrm(rpFrm));
     833           8 :                             pNew->ManipOfst( nOfst );
     834           8 :                             pNew->SetFollow( ((SwTxtFrm*)rpFrm)->GetFollow() );
     835           8 :                             ((SwTxtFrm*)rpFrm)->SetFollow( pNew );
     836           8 :                             rpFrm = pNew;
     837             :                         }
     838             :                     }
     839             :                 }
     840             :             }
     841             : 
     842       24940 :             SwPageFrm* pLastPage = rpPage;
     843       24940 :             if( CheckInsertPage() )
     844             :             {
     845        1662 :                 _CheckFlyCache( pLastPage );
     846        1662 :                 if( rpPrv && rpPrv->IsTxtFrm() && !rpPrv->GetValidSizeFlag() )
     847        1444 :                     rpPrv->Frm().Height( rpPrv->GetUpper()->Prt().Height() );
     848             : 
     849        1662 :                 bRet = true;
     850        1662 :                 rpPrv = 0;
     851        1662 :                 nParagraphCnt = 0;
     852             : 
     853        1662 :                 if ( rpActualSection )
     854             :                 {
     855             :                     //Did the SectionFrm even have a content? If not, we can
     856             :                     //directly put it somewhere else
     857             :                     SwSectionFrm *pSct;
     858         106 :                     bool bInit = false;
     859         106 :                     if ( !rpActualSection->GetSectionFrm()->ContainsCntnt())
     860             :                     {
     861          22 :                         pSct = rpActualSection->GetSectionFrm();
     862          22 :                         pSct->Remove();
     863             :                     }
     864             :                     else
     865             :                     {
     866             :                         pSct = new SwSectionFrm(
     867          84 :                             *rpActualSection->GetSectionFrm(), false );
     868          84 :                         rpActualSection->GetSectionFrm()->SimpleFormat();
     869          84 :                         bInit = true;
     870             :                     }
     871         106 :                     rpActualSection->SetSectionFrm( pSct );
     872         106 :                     pSct->InsertBehind( rpLay, 0 );
     873         106 :                     if( bInit )
     874          84 :                         pSct->Init();
     875         106 :                     pSct->Frm().Pos() = rpLay->Frm().Pos();
     876         106 :                     pSct->Frm().Pos().Y() += 1; //because of the notifications
     877             : 
     878         106 :                     rpLay = pSct;
     879         106 :                     if ( rpLay->Lower() && rpLay->Lower()->IsLayoutFrm() )
     880          28 :                         rpLay = rpLay->GetNextLayoutLeaf();
     881             :                 }
     882             :             }
     883       25076 :         } while( bLongTab || ( pImpl && nIndex < pImpl->size() &&
     884         136 :                  pImpl->GetBreakIndex( nIndex ) == nNodeIndex ) );
     885             :     }
     886       30072 :     bFirst = false;
     887       30072 :     return bRet;
     888             : }
     889             : 
     890             : struct SdrObjectCompare
     891             : {
     892           0 :   bool operator()( const SdrObject* pF1, const SdrObject* pF2 ) const
     893             :   {
     894           0 :     return pF1->GetOrdNum() < pF2->GetOrdNum();
     895             :   }
     896             : };
     897             : 
     898             : struct FlyCacheCompare
     899             : {
     900          14 :   bool operator()( const SwFlyCache* pC1, const SwFlyCache* pC2 ) const
     901             :   {
     902          14 :     return pC1->nOrdNum < pC2->nOrdNum;
     903             :   }
     904             : };
     905             : 
     906             : /**
     907             :  * If a new page is inserted, the last page is analysed.
     908             :  * If there are text frames with default position, the fly cache
     909             :  * is checked, if these frames are stored in the cache.
     910             :  */
     911        1664 : void SwLayHelper::_CheckFlyCache( SwPageFrm* pPage )
     912             : {
     913        1664 :     if( !pImpl || !pPage )
     914        3262 :         return;
     915          66 :     sal_uInt16 nFlyCount = pImpl->GetFlyCount();
     916             :     // Any text frames at the page, fly cache available?
     917          66 :     if( pPage->GetSortedObjs() && nFlyIdx < nFlyCount )
     918             :     {
     919           4 :         SwSortedObjs &rObjs = *pPage->GetSortedObjs();
     920           4 :         sal_uInt16 nPgNum = pPage->GetPhyPageNum();
     921             : 
     922             :         // NOTE: Here we do not use the absolute ordnums but
     923             :         // relative ordnums for the objects on this page.
     924             : 
     925             :         // skip fly frames from pages before the current page
     926          24 :         while( nFlyIdx < nFlyCount &&
     927          10 :                pImpl->GetFlyCache(nFlyIdx).nPageNum < nPgNum )
     928           6 :             ++nFlyIdx;
     929             : 
     930             :         // sort cached objects on this page by ordnum
     931           4 :         std::set< const SwFlyCache*, FlyCacheCompare > aFlyCacheSet;
     932           4 :         sal_uInt16 nIdx = nFlyIdx;
     933             : 
     934             :         SwFlyCache* pFlyC;
     935          36 :         while( nIdx < nFlyCount &&
     936          20 :                ( pFlyC = &pImpl->GetFlyCache( nIdx ) )->nPageNum == nPgNum )
     937             :         {
     938           8 :             aFlyCacheSet.insert( pFlyC );
     939           8 :             ++nIdx;
     940             :         }
     941             : 
     942             :         // sort objects on this page by ordnum
     943           8 :         std::set< const SdrObject*, SdrObjectCompare > aFlySet;
     944           8 :         for ( size_t i = 0; i < rObjs.size(); ++i )
     945             :         {
     946           4 :             SwAnchoredObject* pAnchoredObj = rObjs[i];
     947           4 :             if ( pAnchoredObj->ISA(SwFlyFrm) )  // a text frame?
     948             :             {
     949           4 :                 SwFlyFrm *pFly = static_cast<SwFlyFrm*>(pAnchoredObj);
     950           8 :                 if( pFly->GetAnchorFrm() &&
     951           4 :                     !pFly->GetAnchorFrm()->FindFooterOrHeader() )
     952             :                 {
     953           4 :                     const SwContact *pC = ::GetUserCall( pAnchoredObj->GetDrawObj() );
     954           4 :                     if( pC )
     955             :                     {
     956           4 :                         aFlySet.insert( pAnchoredObj->GetDrawObj() );
     957             :                     }
     958             :                 }
     959             :             }
     960             :         }
     961             : 
     962           4 :         if ( aFlyCacheSet.size() == aFlySet.size() )
     963             :         {
     964             :             std::set< const SwFlyCache*, FlyCacheCompare >::iterator aFlyCacheSetIt =
     965           2 :                     aFlyCacheSet.begin();
     966             :             std::set< const SdrObject*, SdrObjectCompare >::iterator aFlySetIt =
     967           2 :                     aFlySet.begin();
     968             : 
     969           6 :             while ( aFlyCacheSetIt != aFlyCacheSet.end() )
     970             :             {
     971           2 :                 const SwFlyCache* pFlyCache = *aFlyCacheSetIt;
     972           2 :                 SwFlyFrm* pFly = ((SwVirtFlyDrawObj*)*aFlySetIt)->GetFlyFrm();
     973             : 
     974           2 :                 if ( pFly->Frm().Left() == FAR_AWAY )
     975             :                 {
     976             :                     // we get the stored information
     977           4 :                     pFly->Frm().Pos().X() = pFlyCache->Left() +
     978           4 :                                             pPage->Frm().Left();
     979           4 :                     pFly->Frm().Pos().Y() = pFlyCache->Top() +
     980           4 :                                             pPage->Frm().Top();
     981           2 :                     if ( pImpl->IsUseFlyCache() )
     982             :                     {
     983           2 :                         pFly->Frm().Width( pFlyCache->Width() );
     984           2 :                         pFly->Frm().Height( pFlyCache->Height() );
     985             :                     }
     986             :                 }
     987             : 
     988           2 :                 ++aFlyCacheSetIt;
     989           2 :                 ++aFlySetIt;
     990             :             }
     991           4 :         }
     992             :     }
     993             : }
     994             : 
     995          38 : SwLayCacheIoImpl::SwLayCacheIoImpl( SvStream& rStrm, bool bWrtMd ) :
     996             :     pStream( &rStrm ),
     997             :     nFlagRecEnd ( 0 ),
     998             :     nMajorVersion(SW_LAYCACHE_IO_VERSION_MAJOR),
     999             :     nMinorVersion(SW_LAYCACHE_IO_VERSION_MINOR),
    1000             :     bWriteMode( bWrtMd ),
    1001          38 :     bError( false  )
    1002             : {
    1003          38 :     if( bWriteMode )
    1004           6 :         pStream->WriteUInt16( nMajorVersion )
    1005          12 :                 .WriteUInt16( nMinorVersion );
    1006             : 
    1007             :     else
    1008          32 :         pStream->ReadUInt16( nMajorVersion )
    1009          64 :                 .ReadUInt16( nMinorVersion );
    1010          38 : }
    1011             : 
    1012         174 : bool SwLayCacheIoImpl::OpenRec( sal_uInt8 cType )
    1013             : {
    1014         174 :     bool bRes = true;
    1015         174 :     sal_uInt32 nPos = pStream->Tell();
    1016         174 :     if( bWriteMode )
    1017             :     {
    1018          28 :         aRecords.push_back( RecTypeSize(cType, nPos) );
    1019          28 :         pStream->WriteUInt32( 0 );
    1020             :     }
    1021             :     else
    1022             :     {
    1023         146 :         sal_uInt32 nVal(0);
    1024         146 :         pStream->ReadUInt32( nVal );
    1025         146 :         sal_uInt8 cRecTyp = (sal_uInt8)nVal;
    1026         584 :         if( !nVal || cRecTyp != cType ||
    1027         438 :             pStream->GetErrorCode() != SVSTREAM_OK || pStream->IsEof() )
    1028             :         {
    1029             :             OSL_ENSURE( nVal, "OpenRec: Record-Header is 0" );
    1030             :             OSL_ENSURE( cRecTyp == cType, "OpenRec: Wrong Record Type" );
    1031           0 :             aRecords.push_back( RecTypeSize(0, pStream->Tell()) );
    1032           0 :             bRes = false;
    1033           0 :             bError = true;
    1034             :         }
    1035             :         else
    1036             :         {
    1037         146 :             sal_uInt32 nSize = nVal >> 8;
    1038         146 :             aRecords.push_back( RecTypeSize(cRecTyp, nPos+nSize) );
    1039             :         }
    1040             :     }
    1041         174 :     return bRes;
    1042             : }
    1043             : 
    1044             : // Close record
    1045         174 : bool SwLayCacheIoImpl::CloseRec( sal_uInt8 )
    1046             : {
    1047         174 :     bool bRes = true;
    1048             :     OSL_ENSURE( !aRecords.empty(), "CloseRec: no levels" );
    1049         174 :     if( !aRecords.empty() )
    1050             :     {
    1051         174 :         sal_uInt32 nPos = pStream->Tell();
    1052         174 :         if( bWriteMode )
    1053             :         {
    1054          28 :             sal_uInt32 nBgn = aRecords.back().size;
    1055          28 :             pStream->Seek( nBgn );
    1056          28 :             sal_uInt32 nSize = nPos - nBgn;
    1057          28 :             sal_uInt32 nVal = ( nSize << 8 ) | aRecords.back().type;
    1058          28 :             pStream->WriteUInt32( nVal );
    1059          28 :             pStream->Seek( nPos );
    1060          28 :             if( pStream->GetError() != SVSTREAM_OK )
    1061           0 :                  bRes = false;
    1062             :         }
    1063             :         else
    1064             :         {
    1065         146 :             sal_uInt32 n = aRecords.back().size;
    1066             :             OSL_ENSURE( n >= nPos, "CloseRec: to much data read" );
    1067         146 :             if( n != nPos )
    1068             :             {
    1069           0 :                 pStream->Seek( n );
    1070           0 :                 if( n < nPos )
    1071           0 :                      bRes = false;
    1072             :             }
    1073         146 :             if( pStream->GetErrorCode() != SVSTREAM_OK )
    1074           0 :                 bRes = false;
    1075             :         }
    1076         174 :         aRecords.pop_back();
    1077             :     }
    1078             : 
    1079         174 :     if( !bRes )
    1080           0 :         bError = true;
    1081             : 
    1082         174 :     return bRes;
    1083             : }
    1084             : 
    1085         146 : sal_uInt32 SwLayCacheIoImpl::BytesLeft()
    1086             : {
    1087         146 :     sal_uInt32 n = 0;
    1088         146 :     if( !bError && !aRecords.empty() )
    1089             :     {
    1090         146 :         sal_uInt32 nEndPos = aRecords.back().size;
    1091         146 :         sal_uInt32 nPos = pStream->Tell();
    1092         146 :         if( nEndPos > nPos )
    1093         114 :             n = nEndPos - nPos;
    1094             :     }
    1095         146 :     return n;
    1096             : }
    1097             : 
    1098         114 : sal_uInt8 SwLayCacheIoImpl::Peek()
    1099             : {
    1100         114 :     sal_uInt8 c(0);
    1101         114 :     if( !bError )
    1102             :     {
    1103         114 :         sal_uInt32 nPos = pStream->Tell();
    1104         114 :         pStream->ReadUChar( c );
    1105         114 :         pStream->Seek( nPos );
    1106         114 :         if( pStream->GetErrorCode() != SVSTREAM_OK )
    1107             :         {
    1108           0 :             c = 0;
    1109           0 :             bError = true;
    1110             :         }
    1111             :     }
    1112         114 :     return c;
    1113             : }
    1114             : 
    1115           0 : void SwLayCacheIoImpl::SkipRec()
    1116             : {
    1117           0 :     sal_uInt8 c = Peek();
    1118           0 :     OpenRec( c );
    1119           0 :     pStream->Seek( aRecords.back().size );
    1120           0 :     CloseRec( c );
    1121           0 : }
    1122             : 
    1123         146 : sal_uInt8 SwLayCacheIoImpl::OpenFlagRec()
    1124             : {
    1125             :     OSL_ENSURE( !bWriteMode, "OpenFlagRec illegal in write  mode" );
    1126         146 :     sal_uInt8 cFlags(0);
    1127         146 :     pStream->ReadUChar( cFlags );
    1128         146 :     nFlagRecEnd = pStream->Tell() + ( cFlags & 0x0F );
    1129         146 :     return (cFlags >> 4);
    1130             : }
    1131             : 
    1132          28 : void SwLayCacheIoImpl::OpenFlagRec( sal_uInt8 nFlags, sal_uInt8 nLen )
    1133             : {
    1134             :     OSL_ENSURE( bWriteMode, "OpenFlagRec illegal in read  mode" );
    1135             :     OSL_ENSURE( (nFlags & 0xF0) == 0, "illegal flags set" );
    1136             :     OSL_ENSURE( nLen < 16, "wrong flag record length" );
    1137          28 :     sal_uInt8 cFlags = (nFlags << 4) + nLen;
    1138          28 :     pStream->WriteUChar( cFlags );
    1139          28 :     nFlagRecEnd = pStream->Tell() + nLen;
    1140          28 : }
    1141             : 
    1142         174 : void SwLayCacheIoImpl::CloseFlagRec()
    1143             : {
    1144         174 :     if( bWriteMode )
    1145             :     {
    1146             :         OSL_ENSURE( pStream->Tell() == nFlagRecEnd, "Wrong amount of data written" );
    1147             :     }
    1148             :     else
    1149             :     {
    1150             :         OSL_ENSURE( pStream->Tell() <= nFlagRecEnd, "To many data read" );
    1151         146 :         if( pStream->Tell() != nFlagRecEnd )
    1152           0 :             pStream->Seek( nFlagRecEnd );
    1153             :     }
    1154         444 : }
    1155             : 
    1156             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10