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

Generated by: LCOV version 1.10