LCOV - code coverage report
Current view: top level - sw/source/core/docnode - node2lay.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 144 219 65.8 %
Date: 2014-04-11 Functions: 13 16 81.2 %
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 <switerator.hxx>
      21             : #include <calbck.hxx>
      22             : #include <node.hxx>
      23             : #include <ndindex.hxx>
      24             : #include <swtable.hxx>
      25             : #include <ftnfrm.hxx>
      26             : #include <sectfrm.hxx>
      27             : #include "frmfmt.hxx"
      28             : #include "cntfrm.hxx"
      29             : #include "tabfrm.hxx"
      30             : #include "frmtool.hxx"
      31             : #include "section.hxx"
      32             : #include "node2lay.hxx"
      33             : 
      34             : /**
      35             :  * The SwNode2LayImpl class does the actual work, the SwNode2Layout class is
      36             :  * just the public interface.
      37             :  */
      38             : class SwNode2LayImpl
      39             : {
      40             :     SwIterator<SwFrm,SwModify>* pIter;
      41             :     SwModify* pMod;
      42             :     std::vector<SwFrm*>* pUpperFrms; // To collect the Upper
      43             :     sal_uLong nIndex;        // The Index of the to-be-inserted Nodes
      44             :     bool bMaster    : 1; // true => only Master, false => only Frames without Follow
      45             :     bool bInit      : 1; // Did we already call First() at SwClient?
      46             : public:
      47             :     SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, bool bSearch );
      48        2511 :     ~SwNode2LayImpl() { delete pIter; delete pUpperFrms; }
      49             :     SwFrm* NextFrm(); // Returns the next "useful" Frame
      50             :     SwLayoutFrm* UpperFrm( SwFrm* &rpFrm, const SwNode &rNode );
      51             :     void SaveUpperFrms(); // Saves (and locks if needed) the pUpper
      52             :     // Inserts a Frame under every pUpper of the array
      53             :     void RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd );
      54             : 
      55             :     SwFrm* GetFrm( const Point* pDocPos = 0,
      56             :                     const SwPosition *pPos = 0,
      57             :                     const sal_Bool bCalcFrm = sal_True ) const;
      58             : };
      59             : 
      60         393 : SwNode* GoNextWithFrm(const SwNodes& rNodes, SwNodeIndex *pIdx)
      61             : {
      62         393 :     if( pIdx->GetIndex() >= rNodes.Count() - 1 )
      63           0 :         return 0;
      64             : 
      65         393 :     SwNodeIndex aTmp(*pIdx, +1);
      66         393 :     SwNode* pNd = 0;
      67        8985 :     while( aTmp < rNodes.Count()-1 )
      68             :     {
      69        8295 :         pNd = &aTmp.GetNode();
      70        8295 :         bool bFound = false;
      71        8295 :         if ( pNd->IsCntntNode() )
      72        8113 :             bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
      73         182 :         else if ( pNd->IsTableNode() )
      74          32 :             bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
      75         150 :         else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() )
      76             :         {
      77          86 :             pNd = 0;
      78          86 :             break;
      79             :         }
      80        8209 :         if ( bFound )
      81          10 :                 break;
      82        8199 :         ++aTmp;
      83             :     }
      84             : 
      85         393 :     if( aTmp == rNodes.Count()-1 )
      86         297 :         pNd = 0;
      87          96 :     else if( pNd )
      88          10 :         (*pIdx) = aTmp;
      89         393 :     return pNd;
      90             : }
      91             : 
      92           0 : SwNode* GoPreviousWithFrm(SwNodeIndex *pIdx)
      93             : {
      94           0 :     if( !pIdx->GetIndex() )
      95           0 :         return 0;
      96             : 
      97           0 :     SwNodeIndex aTmp( *pIdx, -1 );
      98           0 :     SwNode* pNd(0);
      99           0 :     while( aTmp.GetIndex() )
     100             :     {
     101           0 :         pNd = &aTmp.GetNode();
     102           0 :         bool bFound = false;
     103           0 :         if ( pNd->IsCntntNode() )
     104           0 :             bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
     105           0 :         else if ( pNd->IsTableNode() )
     106           0 :             bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
     107           0 :         else if( pNd->IsStartNode() && !pNd->IsSectionNode() )
     108             :         {
     109           0 :             pNd = 0;
     110           0 :             break;
     111             :         }
     112           0 :         if ( bFound )
     113           0 :                 break;
     114           0 :         aTmp--;
     115             :     }
     116             : 
     117           0 :     if( !aTmp.GetIndex() )
     118           0 :         pNd = 0;
     119           0 :     else if( pNd )
     120           0 :         (*pIdx) = aTmp;
     121           0 :     return pNd;
     122             : }
     123             : 
     124             : /**
     125             :  * The main purpose of this ctor is to find the right SwModify to iterate over.
     126             :  *
     127             :  * @param bSearch sal_True: find the next Content or TableNode which contains
     128             :  *                          Frames (to collect the pUpper).
     129             :  *                          Else we assume that rNode points already to such a
     130             :  *                          Content or TableNode.
     131             :  *                          We insert before or after it.
     132             :  */
     133        2511 : SwNode2LayImpl::SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, bool bSearch )
     134        2511 :     : pUpperFrms( NULL ), nIndex( nIdx ), bInit( false )
     135             : {
     136             :     const SwNode* pNd;
     137        2511 :     if( bSearch || rNode.IsSectionNode() )
     138             :     {
     139             :         // Find the next Cntnt/TableNode that contains a Frame, so that we can add
     140             :         // ourselves before/after it
     141         393 :         if( !bSearch && rNode.GetIndex() < nIndex )
     142             :         {
     143           0 :             SwNodeIndex aTmp( *rNode.EndOfSectionNode(), +1 );
     144           0 :             pNd = GoPreviousWithFrm( &aTmp );
     145           0 :             if( !bSearch && pNd && rNode.GetIndex() > pNd->GetIndex() )
     146           0 :                 pNd = NULL; // Do not go over the limits
     147           0 :             bMaster = false;
     148             :         }
     149             :         else
     150             :         {
     151         393 :             SwNodeIndex aTmp( rNode, -1 );
     152         393 :             pNd = GoNextWithFrm( rNode.GetNodes(), &aTmp );
     153         393 :             bMaster = true;
     154         393 :             if( !bSearch && pNd && rNode.EndOfSectionIndex() < pNd->GetIndex() )
     155           0 :                 pNd = NULL; // Do not go over the limits
     156             :         }
     157             :     }
     158             :     else
     159             :     {
     160        2118 :         pNd = &rNode;
     161        2118 :         bMaster = nIndex < rNode.GetIndex();
     162             :     }
     163        2511 :     if( pNd )
     164             :     {
     165        2128 :         if( pNd->IsCntntNode() )
     166        2119 :             pMod = (SwModify*)pNd->GetCntntNode();
     167             :         else
     168             :         {
     169             :             OSL_ENSURE( pNd->IsTableNode(), "For Tablenodes only" );
     170           9 :             pMod = pNd->GetTableNode()->GetTable().GetFrmFmt();
     171             :         }
     172        2128 :         pIter = new SwIterator<SwFrm,SwModify>( *pMod );
     173             :     }
     174             :     else
     175             :     {
     176         383 :         pIter = NULL;
     177         383 :         pMod = 0;
     178             :     }
     179        2511 : }
     180             : 
     181             : /**
     182             :  * Returns the next "useful" Frame.
     183             :  *
     184             :  * When calling this method for the first time, a First is triggered at the
     185             :  * actual Iterator. The result is check for suitability: Follows are not
     186             :  * accepted, a Master is accepted when collecting the pUpper and when
     187             :  * inserting before it.
     188             :  * When inserting after it, we find and return the last Follow starting
     189             :  * from the Master.
     190             :  *
     191             :  * If the Frame is located in a SectionFrm, we check to see whether the
     192             :  * SectionFrame is the suitable return value (instead of the Frame itself).
     193             :  * This is the case if the to-be-inserted Node is outside of the Section.
     194             :  */
     195        4567 : SwFrm* SwNode2LayImpl::NextFrm()
     196             : {
     197             :     SwFrm* pRet;
     198        4567 :     if( !pIter )
     199         383 :         return NULL;
     200        4184 :     if( !bInit )
     201             :     {
     202        2128 :          pRet = pIter->First();
     203        2128 :          bInit = true;
     204             :     }
     205             :     else
     206        2056 :         pRet = pIter->Next();
     207        8380 :     while( pRet )
     208             :     {
     209        2068 :         SwFlowFrm* pFlow = SwFlowFrm::CastFlowFrm( pRet );
     210             :         OSL_ENSURE( pFlow, "Cntnt or Table expected?!" );
     211             :         // Follows are pretty volatile, thus we ignore them.
     212             :         // Even if we insert after the Frame, we start from the Master
     213             :         // and iterate through it until the last Follow
     214        2068 :         if( !pFlow->IsFollow() )
     215             :         {
     216        2056 :             if( !bMaster )
     217             :             {
     218        3476 :                 while( pFlow->HasFollow() )
     219           2 :                     pFlow = pFlow->GetFollow();
     220        1737 :                 pRet = pFlow->GetFrm();
     221             :             }
     222        2056 :             if( pRet->IsInSct() )
     223             :             {
     224         212 :                 SwSectionFrm* pSct = pRet->FindSctFrm();
     225             :                 // ATTENTION: If we are in a Footnote, from a Layout point of view
     226             :                 // it could be located in a Section with columns, although it
     227             :                 // should be outside of it when looking at the Nodes.
     228             :                 // Thus, when dealing with Footnotes, we need to check whether the
     229             :                 // SectionFrm is also located within the Footnote and not outside of it.
     230         212 :                 if( !pRet->IsInFtn() || pSct->IsInFtn() )
     231             :                 {
     232             :                     OSL_ENSURE( pSct && pSct->GetSection(), "Where's my section?" );
     233         212 :                     SwSectionNode* pNd = pSct->GetSection()->GetFmt()->GetSectionNode();
     234             :                     OSL_ENSURE( pNd, "Lost SectionNode" );
     235             :                     // If the result Frame is located within a Section Frame
     236             :                     // whose Section does not contain the Node, we return with
     237             :                     // the SectionFrm, else we return with the Cntnt/TabFrm
     238         212 :                     if( bMaster )
     239             :                     {
     240          32 :                         if( pNd->GetIndex() >= nIndex )
     241           8 :                             pRet = pSct;
     242             :                     }
     243         180 :                     else if( pNd->EndOfSectionIndex() < nIndex )
     244          12 :                         pRet = pSct;
     245             :                 }
     246             :             }
     247        2056 :             return pRet;
     248             :         }
     249          12 :         pRet = pIter->Next();
     250             :     }
     251        2128 :     return NULL;
     252             : }
     253             : 
     254         391 : void SwNode2LayImpl::SaveUpperFrms()
     255             : {
     256         391 :     pUpperFrms = new std::vector<SwFrm*>;
     257             :     SwFrm* pFrm;
     258         790 :     while( 0 != (pFrm = NextFrm()) )
     259             :     {
     260           8 :         SwFrm* pPrv = pFrm->GetPrev();
     261           8 :         pFrm = pFrm->GetUpper();
     262           8 :         if( pFrm )
     263             :         {
     264           8 :             if( pFrm->IsFtnFrm() )
     265           0 :                 ((SwFtnFrm*)pFrm)->ColLock();
     266           8 :             else if( pFrm->IsInSct() )
     267           0 :                 pFrm->FindSctFrm()->ColLock();
     268           8 :             if( pPrv && pPrv->IsSctFrm() )
     269           0 :                 ((SwSectionFrm*)pPrv)->LockJoin();
     270           8 :             pUpperFrms->push_back( pPrv );
     271           8 :             pUpperFrms->push_back( pFrm );
     272             :         }
     273             :     }
     274         391 :     delete pIter;
     275         391 :     pIter = NULL;
     276         391 :     pMod = 0;
     277         391 : }
     278             : 
     279        4086 : SwLayoutFrm* SwNode2LayImpl::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
     280             : {
     281        4086 :     rpFrm = NextFrm();
     282        4086 :     if( !rpFrm )
     283        2078 :         return NULL;
     284        2008 :     SwLayoutFrm* pUpper = rpFrm->GetUpper();
     285        2008 :     if( rpFrm->IsSctFrm() )
     286             :     {
     287           9 :         const SwNode* pNode = rNode.StartOfSectionNode();
     288           9 :         if( pNode->IsSectionNode() )
     289             :         {
     290           1 :             SwFrm* pFrm = bMaster ? rpFrm->FindPrev() : rpFrm->FindNext();
     291           1 :             if( pFrm && pFrm->IsSctFrm() )
     292             :             {
     293             :                 // pFrm could be a "dummy"-section
     294           0 :                 if( ((SwSectionFrm*)pFrm)->GetSection() &&
     295           0 :                     (&((SwSectionNode*)pNode)->GetSection() ==
     296           0 :                      ((SwSectionFrm*)pFrm)->GetSection()) )
     297             :                 {
     298             :                     // #i22922# - consider columned sections
     299             :                     // 'Go down' the section frame as long as the layout frame
     300             :                     // is found, which would contain content.
     301           0 :                     while ( pFrm->IsLayoutFrm() &&
     302           0 :                             static_cast<SwLayoutFrm*>(pFrm)->Lower() &&
     303           0 :                             !static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsFlowFrm() &&
     304           0 :                             static_cast<SwLayoutFrm*>(pFrm)->Lower()->IsLayoutFrm() )
     305             :                     {
     306           0 :                         pFrm = static_cast<SwLayoutFrm*>(pFrm)->Lower();
     307             :                     }
     308             :                     OSL_ENSURE( pFrm->IsLayoutFrm(),
     309             :                             "<SwNode2LayImpl::UpperFrm(..)> - expected upper frame isn't a layout frame." );
     310             :                     rpFrm = bMaster ? NULL
     311           0 :                                     : static_cast<SwLayoutFrm*>(pFrm)->Lower();
     312             :                     OSL_ENSURE( !rpFrm || rpFrm->IsFlowFrm(),
     313             :                             "<SwNode2LayImpl::UpperFrm(..)> - expected sibling isn't a flow frame." );
     314           0 :                     return static_cast<SwLayoutFrm*>(pFrm);
     315             :                 }
     316             : 
     317           0 :                 pUpper = new SwSectionFrm(((SwSectionNode*)pNode)->GetSection(), rpFrm);
     318           0 :                 pUpper->Paste( rpFrm->GetUpper(),
     319           0 :                                bMaster ? rpFrm : rpFrm->GetNext() );
     320           0 :                 static_cast<SwSectionFrm*>(pUpper)->Init();
     321           0 :                 rpFrm = NULL;
     322             :                 // 'Go down' the section frame as long as the layout frame
     323             :                 // is found, which would contain content.
     324           0 :                 while ( pUpper->Lower() &&
     325           0 :                         !pUpper->Lower()->IsFlowFrm() &&
     326           0 :                         pUpper->Lower()->IsLayoutFrm() )
     327             :                 {
     328           0 :                     pUpper = static_cast<SwLayoutFrm*>(pUpper->Lower());
     329             :                 }
     330           0 :                 return pUpper;
     331             :             }
     332             :         }
     333             :     };
     334        2008 :     if( !bMaster )
     335        1719 :         rpFrm = rpFrm->GetNext();
     336        2008 :     return pUpper;
     337             : }
     338             : 
     339         391 : void SwNode2LayImpl::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
     340             : {
     341             :     OSL_ENSURE( pUpperFrms, "RestoreUpper without SaveUpper?" );
     342             :     SwNode* pNd;
     343         391 :     SwDoc *pDoc = rNds.GetDoc();
     344         391 :     bool bFirst = true;
     345         782 :     for( ; nStt < nEnd; ++nStt )
     346             :     {
     347         391 :         SwFrm* pNew = 0;
     348             :         SwFrm* pNxt;
     349             :         SwLayoutFrm* pUp;
     350         391 :         if( (pNd = rNds[nStt])->IsCntntNode() )
     351           0 :             for( sal_uInt16 n = 0; n < pUpperFrms->size(); )
     352             :             {
     353           0 :                 pNxt = (*pUpperFrms)[n++];
     354           0 :                 if( bFirst && pNxt && pNxt->IsSctFrm() )
     355           0 :                     ((SwSectionFrm*)pNxt)->UnlockJoin();
     356           0 :                 pUp = (SwLayoutFrm*)(*pUpperFrms)[n++];
     357           0 :                 if( pNxt )
     358           0 :                     pNxt = pNxt->GetNext();
     359             :                 else
     360           0 :                     pNxt = pUp->Lower();
     361           0 :                 pNew = ((SwCntntNode*)pNd)->MakeFrm( pUp );
     362           0 :                 pNew->Paste( pUp, pNxt );
     363           0 :                 (*pUpperFrms)[n-2] = pNew;
     364             :             }
     365         391 :         else if( pNd->IsTableNode() )
     366         778 :             for( sal_uInt16 x = 0; x < pUpperFrms->size(); )
     367             :             {
     368           4 :                 pNxt = (*pUpperFrms)[x++];
     369           4 :                 if( bFirst && pNxt && pNxt->IsSctFrm() )
     370           0 :                     ((SwSectionFrm*)pNxt)->UnlockJoin();
     371           4 :                 pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
     372           4 :                 if( pNxt )
     373           0 :                     pNxt = pNxt->GetNext();
     374             :                 else
     375           4 :                     pNxt = pUp->Lower();
     376           4 :                 pNew = ((SwTableNode*)pNd)->MakeFrm( pUp );
     377             :                 OSL_ENSURE( pNew->IsTabFrm(), "Table expected" );
     378           4 :                 pNew->Paste( pUp, pNxt );
     379           4 :                 ((SwTabFrm*)pNew)->RegistFlys();
     380           4 :                 (*pUpperFrms)[x-2] = pNew;
     381             :             }
     382           4 :         else if( pNd->IsSectionNode() )
     383             :         {
     384           4 :             nStt = pNd->EndOfSectionIndex();
     385          12 :             for( sal_uInt16 x = 0; x < pUpperFrms->size(); )
     386             :             {
     387           4 :                 pNxt = (*pUpperFrms)[x++];
     388           4 :                 if( bFirst && pNxt && pNxt->IsSctFrm() )
     389           0 :                     ((SwSectionFrm*)pNxt)->UnlockJoin();
     390           4 :                 pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
     391             :                 OSL_ENSURE( pUp->GetUpper() || pUp->IsFlyFrm(), "Lost Upper" );
     392           4 :                 ::_InsertCnt( pUp, pDoc, pNd->GetIndex(), sal_False, nStt+1, pNxt );
     393           4 :                 pNxt = pUp->GetLastLower();
     394           4 :                 (*pUpperFrms)[x-2] = pNxt;
     395             :             }
     396             :         }
     397         391 :         bFirst = false;
     398             :     }
     399         399 :     for( sal_uInt16 x = 0; x < pUpperFrms->size(); ++x )
     400             :     {
     401           8 :         SwFrm* pTmp = (*pUpperFrms)[++x];
     402           8 :         if( pTmp->IsFtnFrm() )
     403           0 :             ((SwFtnFrm*)pTmp)->ColUnlock();
     404           8 :         else if ( pTmp->IsInSct() )
     405             :         {
     406           0 :             SwSectionFrm* pSctFrm = pTmp->FindSctFrm();
     407           0 :             pSctFrm->ColUnlock();
     408             :             // #i18103# - invalidate size of section in order to
     409             :             // assure, that the section is formatted, unless it was 'Collocked'
     410             :             // from its 'collection' until its 'restoration'.
     411           0 :             pSctFrm->_InvalidateSize();
     412             :         }
     413             :     }
     414         391 : }
     415             : 
     416           0 : SwFrm* SwNode2LayImpl::GetFrm( const Point* pDocPos,
     417             :                                 const SwPosition *pPos,
     418             :                                 const sal_Bool bCalcFrm ) const
     419             : {
     420             :     // test if change of member pIter -> pMod broke anything
     421           0 :     return pMod ? ::GetFrmOfModify( 0, *pMod, USHRT_MAX, pDocPos, pPos, bCalcFrm ) : 0;
     422             : }
     423             : 
     424        2120 : SwNode2Layout::SwNode2Layout( const SwNode& rNd, sal_uLong nIdx )
     425             : {
     426        2120 :     pImpl = new SwNode2LayImpl( rNd, nIdx, false );
     427        2120 : }
     428             : 
     429         391 : SwNode2Layout::SwNode2Layout( const SwNode& rNd )
     430             : {
     431         391 :     pImpl = new SwNode2LayImpl( rNd, rNd.GetIndex(), true );
     432         391 :     pImpl->SaveUpperFrms();
     433         391 : }
     434             : 
     435         391 : void SwNode2Layout::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
     436             : {
     437             :     OSL_ENSURE( pImpl, "RestoreUpperFrms without SaveUpperFrms" );
     438         391 :     pImpl->RestoreUpperFrms( rNds, nStt, nEnd );
     439         391 : }
     440             : 
     441          82 : SwFrm* SwNode2Layout::NextFrm()
     442             : {
     443          82 :     return pImpl->NextFrm();
     444             : }
     445             : 
     446        4086 : SwLayoutFrm* SwNode2Layout::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
     447             : {
     448        4086 :     return pImpl->UpperFrm( rpFrm, rNode );
     449             : }
     450             : 
     451        2511 : SwNode2Layout::~SwNode2Layout()
     452             : {
     453        2511 :     delete pImpl;
     454        2511 : }
     455             : 
     456           0 : SwFrm* SwNode2Layout::GetFrm( const Point* pDocPos,
     457             :                                 const SwPosition *pPos,
     458             :                                 const sal_Bool bCalcFrm ) const
     459             : {
     460           0 :     return pImpl->GetFrm( pDocPos, pPos, bCalcFrm );
     461             : }
     462             : 
     463             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10