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

Generated by: LCOV version 1.10