LCOV - code coverage report
Current view: top level - sw/source/core/docnode - node2lay.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 170 220 77.3 %
Date: 2014-11-03 Functions: 16 18 88.9 %
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        5670 :     ~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 bool bCalcFrm = true ) const;
      58             : };
      59             : 
      60        1084 : SwNode* GoNextWithFrm(const SwNodes& rNodes, SwNodeIndex *pIdx)
      61             : {
      62        1084 :     if( pIdx->GetIndex() >= rNodes.Count() - 1 )
      63           0 :         return 0;
      64             : 
      65        1084 :     SwNodeIndex aTmp(*pIdx, +1);
      66        1084 :     SwNode* pNd = 0;
      67       20700 :     while( aTmp < rNodes.Count()-1 )
      68             :     {
      69       18816 :         pNd = &aTmp.GetNode();
      70       18816 :         bool bFound = false;
      71       18816 :         if ( pNd->IsCntntNode() )
      72       18356 :             bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
      73         460 :         else if ( pNd->IsTableNode() )
      74          94 :             bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
      75         366 :         else if( pNd->IsEndNode() && !pNd->StartOfSectionNode()->IsSectionNode() )
      76             :         {
      77         262 :             pNd = 0;
      78         262 :             break;
      79             :         }
      80       18554 :         if ( bFound )
      81          22 :                 break;
      82       18532 :         ++aTmp;
      83             :     }
      84             : 
      85        1084 :     if( aTmp == rNodes.Count()-1 )
      86         800 :         pNd = 0;
      87         284 :     else if( pNd )
      88          22 :         (*pIdx) = aTmp;
      89        1084 :     return pNd;
      90             : }
      91             : 
      92          20 : SwNode* GoPreviousWithFrm(SwNodeIndex *pIdx)
      93             : {
      94          20 :     if( !pIdx->GetIndex() )
      95           0 :         return 0;
      96             : 
      97          20 :     SwNodeIndex aTmp( *pIdx, -1 );
      98          20 :     SwNode* pNd(0);
      99         102 :     while( aTmp.GetIndex() )
     100             :     {
     101          82 :         pNd = &aTmp.GetNode();
     102          82 :         bool bFound = false;
     103          82 :         if ( pNd->IsCntntNode() )
     104          24 :             bFound = ( SwIterator<SwFrm,SwCntntNode>::FirstElement(*(SwCntntNode*)pNd) != 0);
     105          58 :         else if ( pNd->IsTableNode() )
     106           0 :             bFound = ( SwIterator<SwFrm,SwFmt>::FirstElement(*((SwTableNode*)pNd)->GetTable().GetFrmFmt()) != 0 );
     107          58 :         else if( pNd->IsStartNode() && !pNd->IsSectionNode() )
     108             :         {
     109          16 :             pNd = 0;
     110          16 :             break;
     111             :         }
     112          66 :         if ( bFound )
     113           4 :                 break;
     114          62 :         aTmp--;
     115             :     }
     116             : 
     117          20 :     if( !aTmp.GetIndex() )
     118           0 :         pNd = 0;
     119          20 :     else if( pNd )
     120           4 :         (*pIdx) = aTmp;
     121          20 :     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        5670 : SwNode2LayImpl::SwNode2LayImpl( const SwNode& rNode, sal_uLong nIdx, bool bSearch )
     134        5670 :     : pUpperFrms( NULL ), nIndex( nIdx ), bInit( false )
     135             : {
     136             :     const SwNode* pNd;
     137        5670 :     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        1104 :         if( !bSearch && rNode.GetIndex() < nIndex )
     142             :         {
     143          20 :             SwNodeIndex aTmp( *rNode.EndOfSectionNode(), +1 );
     144          20 :             pNd = GoPreviousWithFrm( &aTmp );
     145          20 :             if( !bSearch && pNd && rNode.GetIndex() > pNd->GetIndex() )
     146           4 :                 pNd = NULL; // Do not go over the limits
     147          20 :             bMaster = false;
     148             :         }
     149             :         else
     150             :         {
     151        1084 :             SwNodeIndex aTmp( rNode, -1 );
     152        1084 :             pNd = GoNextWithFrm( rNode.GetNodes(), &aTmp );
     153        1084 :             bMaster = true;
     154        1084 :             if( !bSearch && pNd && rNode.EndOfSectionIndex() < pNd->GetIndex() )
     155           0 :                 pNd = NULL; // Do not go over the limits
     156             :         }
     157             :     }
     158             :     else
     159             :     {
     160        4566 :         pNd = &rNode;
     161        4566 :         bMaster = nIndex < rNode.GetIndex();
     162             :     }
     163        5670 :     if( pNd )
     164             :     {
     165        4588 :         if( pNd->IsCntntNode() )
     166        4570 :             pMod = (SwModify*)pNd->GetCntntNode();
     167             :         else
     168             :         {
     169             :             OSL_ENSURE( pNd->IsTableNode(), "For Tablenodes only" );
     170          18 :             pMod = pNd->GetTableNode()->GetTable().GetFrmFmt();
     171             :         }
     172        4588 :         pIter = new SwIterator<SwFrm,SwModify>( *pMod );
     173             :     }
     174             :     else
     175             :     {
     176        1082 :         pIter = NULL;
     177        1082 :         pMod = 0;
     178             :     }
     179        5670 : }
     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       10078 : SwFrm* SwNode2LayImpl::NextFrm()
     196             : {
     197             :     SwFrm* pRet;
     198       10078 :     if( !pIter )
     199        1082 :         return NULL;
     200        8996 :     if( !bInit )
     201             :     {
     202        4588 :          pRet = pIter->First();
     203        4588 :          bInit = true;
     204             :     }
     205             :     else
     206        4408 :         pRet = pIter->Next();
     207       18016 :     while( pRet )
     208             :     {
     209        4432 :         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        4432 :         if( !pFlow->IsFollow() )
     215             :         {
     216        4408 :             if( !bMaster )
     217             :             {
     218        7344 :                 while( pFlow->HasFollow() )
     219           4 :                     pFlow = pFlow->GetFollow();
     220        3670 :                 pRet = &(pFlow->GetFrm());
     221             :             }
     222        4408 :             if( pRet->IsInSct() )
     223             :             {
     224         436 :                 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         436 :                 if( !pRet->IsInFtn() || pSct->IsInFtn() )
     231             :                 {
     232             :                     OSL_ENSURE( pSct && pSct->GetSection(), "Where's my section?" );
     233         436 :                     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         436 :                     if( bMaster )
     239             :                     {
     240          68 :                         if( pNd->GetIndex() >= nIndex )
     241          16 :                             pRet = pSct;
     242             :                     }
     243         368 :                     else if( pNd->EndOfSectionIndex() < nIndex )
     244          28 :                         pRet = pSct;
     245             :                 }
     246             :             }
     247        4408 :             return pRet;
     248             :         }
     249          24 :         pRet = pIter->Next();
     250             :     }
     251        4588 :     return NULL;
     252             : }
     253             : 
     254        1080 : void SwNode2LayImpl::SaveUpperFrms()
     255             : {
     256        1080 :     pUpperFrms = new std::vector<SwFrm*>;
     257             :     SwFrm* pFrm;
     258        2178 :     while( 0 != (pFrm = NextFrm()) )
     259             :     {
     260          18 :         SwFrm* pPrv = pFrm->GetPrev();
     261          18 :         pFrm = pFrm->GetUpper();
     262          18 :         if( pFrm )
     263             :         {
     264          18 :             if( pFrm->IsFtnFrm() )
     265           0 :                 ((SwFtnFrm*)pFrm)->ColLock();
     266          18 :             else if( pFrm->IsInSct() )
     267           0 :                 pFrm->FindSctFrm()->ColLock();
     268          18 :             if( pPrv && pPrv->IsSctFrm() )
     269           0 :                 ((SwSectionFrm*)pPrv)->LockJoin();
     270          18 :             pUpperFrms->push_back( pPrv );
     271          18 :             pUpperFrms->push_back( pFrm );
     272             :         }
     273             :     }
     274        1080 :     delete pIter;
     275        1080 :     pIter = NULL;
     276        1080 :     pMod = 0;
     277        1080 : }
     278             : 
     279        8784 : SwLayoutFrm* SwNode2LayImpl::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
     280             : {
     281        8784 :     rpFrm = NextFrm();
     282        8784 :     if( !rpFrm )
     283        4480 :         return NULL;
     284        4304 :     SwLayoutFrm* pUpper = rpFrm->GetUpper();
     285        4304 :     if( rpFrm->IsSctFrm() )
     286             :     {
     287          20 :         const SwNode* pNode = rNode.StartOfSectionNode();
     288          20 :         if( pNode->IsSectionNode() )
     289             :         {
     290           2 :             SwFrm* pFrm = bMaster ? rpFrm->FindPrev() : rpFrm->FindNext();
     291           2 :             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        4304 :     if( !bMaster )
     335        3628 :         rpFrm = rpFrm->GetNext();
     336        4304 :     return pUpper;
     337             : }
     338             : 
     339        1080 : void SwNode2LayImpl::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
     340             : {
     341             :     OSL_ENSURE( pUpperFrms, "RestoreUpper without SaveUpper?" );
     342             :     SwNode* pNd;
     343        1080 :     SwDoc *pDoc = rNds.GetDoc();
     344        1080 :     bool bFirst = true;
     345        2160 :     for( ; nStt < nEnd; ++nStt )
     346             :     {
     347        1080 :         SwFrm* pNew = 0;
     348             :         SwFrm* pNxt;
     349             :         SwLayoutFrm* pUp;
     350        1080 :         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        1080 :         else if( pNd->IsTableNode() )
     366        2148 :             for( sal_uInt16 x = 0; x < pUpperFrms->size(); )
     367             :             {
     368           8 :                 pNxt = (*pUpperFrms)[x++];
     369           8 :                 if( bFirst && pNxt && pNxt->IsSctFrm() )
     370           0 :                     ((SwSectionFrm*)pNxt)->UnlockJoin();
     371           8 :                 pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
     372           8 :                 if( pNxt )
     373           0 :                     pNxt = pNxt->GetNext();
     374             :                 else
     375           8 :                     pNxt = pUp->Lower();
     376           8 :                 pNew = ((SwTableNode*)pNd)->MakeFrm( pUp );
     377             :                 OSL_ENSURE( pNew->IsTabFrm(), "Table expected" );
     378           8 :                 pNew->Paste( pUp, pNxt );
     379           8 :                 ((SwTabFrm*)pNew)->RegistFlys();
     380           8 :                 (*pUpperFrms)[x-2] = pNew;
     381             :             }
     382          10 :         else if( pNd->IsSectionNode() )
     383             :         {
     384          10 :             nStt = pNd->EndOfSectionIndex();
     385          30 :             for( sal_uInt16 x = 0; x < pUpperFrms->size(); )
     386             :             {
     387          10 :                 pNxt = (*pUpperFrms)[x++];
     388          10 :                 if( bFirst && pNxt && pNxt->IsSctFrm() )
     389           0 :                     ((SwSectionFrm*)pNxt)->UnlockJoin();
     390          10 :                 pUp = (SwLayoutFrm*)(*pUpperFrms)[x++];
     391             :                 OSL_ENSURE( pUp->GetUpper() || pUp->IsFlyFrm(), "Lost Upper" );
     392          10 :                 ::_InsertCnt( pUp, pDoc, pNd->GetIndex(), false, nStt+1, pNxt );
     393          10 :                 pNxt = pUp->GetLastLower();
     394          10 :                 (*pUpperFrms)[x-2] = pNxt;
     395             :             }
     396             :         }
     397        1080 :         bFirst = false;
     398             :     }
     399        1098 :     for( sal_uInt16 x = 0; x < pUpperFrms->size(); ++x )
     400             :     {
     401          18 :         SwFrm* pTmp = (*pUpperFrms)[++x];
     402          18 :         if( pTmp->IsFtnFrm() )
     403           0 :             ((SwFtnFrm*)pTmp)->ColUnlock();
     404          18 :         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        1080 : }
     415             : 
     416           0 : SwFrm* SwNode2LayImpl::GetFrm( const Point* pDocPos,
     417             :                                 const SwPosition *pPos,
     418             :                                 const 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        4590 : SwNode2Layout::SwNode2Layout( const SwNode& rNd, sal_uLong nIdx )
     425             : {
     426        4590 :     pImpl = new SwNode2LayImpl( rNd, nIdx, false );
     427        4590 : }
     428             : 
     429        1080 : SwNode2Layout::SwNode2Layout( const SwNode& rNd )
     430             : {
     431        1080 :     pImpl = new SwNode2LayImpl( rNd, rNd.GetIndex(), true );
     432        1080 :     pImpl->SaveUpperFrms();
     433        1080 : }
     434             : 
     435        1080 : void SwNode2Layout::RestoreUpperFrms( SwNodes& rNds, sal_uLong nStt, sal_uLong nEnd )
     436             : {
     437             :     OSL_ENSURE( pImpl, "RestoreUpperFrms without SaveUpperFrms" );
     438        1080 :     pImpl->RestoreUpperFrms( rNds, nStt, nEnd );
     439        1080 : }
     440             : 
     441         196 : SwFrm* SwNode2Layout::NextFrm()
     442             : {
     443         196 :     return pImpl->NextFrm();
     444             : }
     445             : 
     446        8784 : SwLayoutFrm* SwNode2Layout::UpperFrm( SwFrm* &rpFrm, const SwNode &rNode )
     447             : {
     448        8784 :     return pImpl->UpperFrm( rpFrm, rNode );
     449             : }
     450             : 
     451        5670 : SwNode2Layout::~SwNode2Layout()
     452             : {
     453        5670 :     delete pImpl;
     454        5670 : }
     455             : 
     456           0 : SwFrm* SwNode2Layout::GetFrm( const Point* pDocPos,
     457             :                               const SwPosition *pPos,
     458             :                               const bool bCalcFrm ) const
     459             : {
     460           0 :     return pImpl->GetFrm( pDocPos, pPos, bCalcFrm );
     461         270 : }
     462             : 
     463             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10