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

Generated by: LCOV version 1.10