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

Generated by: LCOV version 1.10