LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sw/source/core/layout - colfrm.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 162 202 80.2 %
Date: 2013-07-09 Functions: 9 10 90.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 <editeng/ulspitem.hxx>
      22             : #include <fmtclds.hxx>
      23             : #include <fmtfordr.hxx>
      24             : #include <frmfmt.hxx>
      25             : #include "frmtool.hxx"
      26             : #include "colfrm.hxx"
      27             : #include "pagefrm.hxx"
      28             : #include "bodyfrm.hxx"   // ColumnFrms now with BodyFrm
      29             : #include "rootfrm.hxx"   // wg. RemoveFtns
      30             : #include "sectfrm.hxx"   // wg. FtnAtEnd-Flag
      31             : #include "switerator.hxx"
      32             : 
      33             : // ftnfrm.cxx:
      34             : void sw_RemoveFtns( SwFtnBossFrm* pBoss, sal_Bool bPageOnly, sal_Bool bEndNotes );
      35             : 
      36             : 
      37             : /*************************************************************************
      38             : |*
      39             : |*  SwColumnFrm::SwColumnFrm()
      40             : |*
      41             : |*************************************************************************/
      42          60 : SwColumnFrm::SwColumnFrm( SwFrmFmt *pFmt, SwFrm* pSib ):
      43          60 :     SwFtnBossFrm( pFmt, pSib )
      44             : {
      45          60 :     mnType = FRMC_COLUMN;
      46          60 :     SwBodyFrm* pColBody = new SwBodyFrm( pFmt->GetDoc()->GetDfltFrmFmt(), pSib );
      47          60 :     pColBody->InsertBehind( this, 0 ); // ColumnFrms now with BodyFrm
      48          60 :     SetMaxFtnHeight( LONG_MAX );
      49          60 : }
      50             : 
      51         180 : SwColumnFrm::~SwColumnFrm()
      52             : {
      53          60 :     SwFrmFmt *pFmt = GetFmt();
      54             :     SwDoc *pDoc;
      55          60 :     if ( !(pDoc = pFmt->GetDoc())->IsInDtor() && pFmt->IsLastDepend() )
      56             :     {
      57             :         //I'm the only one, delete the format.
      58             :         //Get default format before, so the base class can cope with it.
      59          19 :         pDoc->GetDfltFrmFmt()->Add( this );
      60          19 :         pDoc->DelFrmFmt( pFmt );
      61             :     }
      62         120 : }
      63             : 
      64             : /*************************************************************************
      65             : |*
      66             : |*  SwLayoutFrm::ChgColumns()
      67             : |*
      68             : |*************************************************************************/
      69             : 
      70           0 : static void lcl_RemoveColumns( SwLayoutFrm *pCont, sal_uInt16 nCnt )
      71             : {
      72             :     OSL_ENSURE( pCont && pCont->Lower() && pCont->Lower()->IsColumnFrm(),
      73             :             "Keine Spalten zu entfernen." );
      74             : 
      75           0 :     SwColumnFrm *pColumn = (SwColumnFrm*)pCont->Lower();
      76           0 :     sw_RemoveFtns( pColumn, sal_True, sal_True );
      77           0 :     while ( pColumn->GetNext() )
      78             :     {
      79             :         OSL_ENSURE( pColumn->GetNext()->IsColumnFrm(),
      80             :                 "Nachbar von ColFrm kein ColFrm." );
      81           0 :         pColumn = (SwColumnFrm*)pColumn->GetNext();
      82             :     }
      83           0 :     for ( sal_uInt16 i = 0; i < nCnt; ++i )
      84             :     {
      85           0 :         SwColumnFrm *pTmp = (SwColumnFrm*)pColumn->GetPrev();
      86           0 :         pColumn->Cut();
      87           0 :         delete pColumn; //format is going to be destroyed in the DTor if needed.
      88           0 :         pColumn = pTmp;
      89             :     }
      90           0 : }
      91             : 
      92          39 : static SwLayoutFrm * lcl_FindColumns( SwLayoutFrm *pLay, sal_uInt16 nCount )
      93             : {
      94          39 :     SwFrm *pCol = pLay->Lower();
      95          39 :     if ( pLay->IsPageFrm() )
      96           2 :         pCol = ((SwPageFrm*)pLay)->FindBodyCont()->Lower();
      97             : 
      98          39 :     if ( pCol && pCol->IsColumnFrm() )
      99             :     {
     100          15 :         SwFrm *pTmp = pCol;
     101             :         sal_uInt16 i;
     102          15 :         for ( i = 0; pTmp; pTmp = pTmp->GetNext(), ++i )
     103             :             /* do nothing */;
     104          15 :         return i == nCount ? (SwLayoutFrm*)pCol : 0;
     105             :     }
     106          24 :     return 0;
     107             : }
     108             : 
     109             : 
     110          24 : static sal_Bool lcl_AddColumns( SwLayoutFrm *pCont, sal_uInt16 nCount )
     111             : {
     112          24 :     SwDoc *pDoc = pCont->GetFmt()->GetDoc();
     113          24 :     const sal_Bool bMod = pDoc->IsModified();
     114             : 
     115             :     //Formats should be shared whenever possible. If a neighbour already has
     116             :     //the same column settings we can add them to the same format.
     117             :     //The neighbour can be searched using the format, however the owner of the
     118             :     //attribute depends on the frame type.
     119          24 :     SwLayoutFrm *pAttrOwner = pCont;
     120          24 :     if ( pCont->IsBodyFrm() )
     121           2 :         pAttrOwner = pCont->FindPageFrm();
     122          24 :     SwLayoutFrm *pNeighbourCol = 0;
     123          24 :     SwIterator<SwLayoutFrm,SwFmt> aIter( *pAttrOwner->GetFmt() );
     124          24 :     SwLayoutFrm *pNeighbour = aIter.First();
     125             : 
     126          24 :     sal_uInt16 nAdd = 0;
     127          24 :     SwFrm *pCol = pCont->Lower();
     128          24 :     if ( pCol && pCol->IsColumnFrm() )
     129           0 :         for ( nAdd = 1; pCol; pCol = pCol->GetNext(), ++nAdd )
     130             :             /* do nothing */;
     131          72 :     while ( pNeighbour )
     132             :     {
     133          39 :         if ( 0 != (pNeighbourCol = lcl_FindColumns( pNeighbour, nCount+nAdd )) &&
     134             :              pNeighbourCol != pCont )
     135          15 :             break;
     136          24 :         pNeighbourCol = 0;
     137          24 :         pNeighbour = aIter.Next();
     138             :     }
     139             : 
     140             :     sal_Bool bRet;
     141          24 :     SwTwips nMax = pCont->IsPageBodyFrm() ?
     142          24 :                    pCont->FindPageFrm()->GetMaxFtnHeight() : LONG_MAX;
     143          24 :     if ( pNeighbourCol )
     144             :     {
     145          15 :         bRet = sal_False;
     146          15 :         SwFrm *pTmp = pCont->Lower();
     147          30 :         while ( pTmp )
     148             :         {
     149           0 :             pTmp = pTmp->GetNext();
     150           0 :             pNeighbourCol = (SwLayoutFrm*)pNeighbourCol->GetNext();
     151             :         }
     152          56 :         for ( sal_uInt16 i = 0; i < nCount; ++i )
     153             :         {
     154          41 :             SwColumnFrm *pTmpCol = new SwColumnFrm( pNeighbourCol->GetFmt(), pCont );
     155          41 :             pTmpCol->SetMaxFtnHeight( nMax );
     156          41 :             pTmpCol->InsertBefore( pCont, NULL );
     157          41 :             pNeighbourCol = (SwLayoutFrm*)pNeighbourCol->GetNext();
     158             :         }
     159             :     }
     160             :     else
     161             :     {
     162           9 :         bRet = sal_True;
     163          28 :         for ( sal_uInt16 i = 0; i < nCount; ++i )
     164             :         {
     165          19 :             SwFrmFmt *pFmt = pDoc->MakeFrmFmt( aEmptyStr, pDoc->GetDfltFrmFmt());
     166          19 :             SwColumnFrm *pTmp = new SwColumnFrm( pFmt, pCont );
     167          19 :             pTmp->SetMaxFtnHeight( nMax );
     168          19 :             pTmp->Paste( pCont );
     169             :         }
     170             :     }
     171             : 
     172          24 :     if ( !bMod )
     173           6 :         pDoc->ResetModified();
     174          24 :     return bRet;
     175             : }
     176             : 
     177             : /*--------------------------------------------------
     178             :  * ChgColumns() adds or removes columns from a layoutframe.
     179             :  * Normally, a layoutframe with a column attribut of 1 or 0 columns contains
     180             :  * no columnframe. However, a sectionframe with "footnotes at the end" needs
     181             :  * a columnframe. If the bChgFtn-flag is set, the columnframe will be inserted
     182             :  * or remove, if necessary.
     183             :  * --------------------------------------------------*/
     184             : 
     185          39 : void SwLayoutFrm::ChgColumns( const SwFmtCol &rOld, const SwFmtCol &rNew,
     186             :     const sal_Bool bChgFtn )
     187             : {
     188          39 :     if ( rOld.GetNumCols() <= 1 && rNew.GetNumCols() <= 1 && !bChgFtn )
     189           7 :         return;
     190             :     // #i97379#
     191             :     // If current lower is a no text frame, then columns are not allowed
     192          32 :     if ( Lower() && Lower()->IsNoTxtFrm() &&
     193           0 :          rNew.GetNumCols() > 1 )
     194             :     {
     195           0 :         return;
     196             :     }
     197             : 
     198          32 :     sal_uInt16 nNewNum, nOldNum = 1;
     199          32 :     if( Lower() && Lower()->IsColumnFrm() )
     200             :     {
     201           8 :         SwFrm* pCol = Lower();
     202          16 :         while( 0 != (pCol=pCol->GetNext()) )
     203           0 :             ++nOldNum;
     204             :     }
     205          32 :     nNewNum = rNew.GetNumCols();
     206          32 :     if( !nNewNum )
     207          12 :         ++nNewNum;
     208             :     sal_Bool bAtEnd;
     209          32 :     if( IsSctFrm() )
     210          30 :         bAtEnd = ((SwSectionFrm*)this)->IsAnyNoteAtEnd();
     211             :     else
     212           2 :         bAtEnd = sal_False;
     213             : 
     214             :     //Setting the column width is only needed for new formats.
     215          32 :     sal_Bool bAdjustAttributes = nOldNum != rOld.GetNumCols();
     216             : 
     217             :     //The content is saved and restored if the column count is different.
     218          32 :     SwFrm *pSave = 0;
     219          32 :     if( nOldNum != nNewNum || bChgFtn )
     220             :     {
     221          32 :         SwDoc *pDoc = GetFmt()->GetDoc();
     222             :         OSL_ENSURE( pDoc, "FrmFmt doesn't return a document." );
     223             :         // SaveCntnt would also suck up the content of the footnote container
     224             :         // and store it within the normal text flow.
     225          32 :         if( IsPageBodyFrm() )
     226           2 :             pDoc->GetCurrentLayout()->RemoveFtns( (SwPageFrm*)GetUpper(), sal_True, sal_False );    //swmod 080218
     227          32 :         pSave = ::SaveCntnt( this );
     228             : 
     229             :         //If columns exist, they get deleted if a column count of 0 or 1 is requested.
     230          32 :         if ( nNewNum == 1 && !bAtEnd )
     231             :         {
     232           0 :             ::lcl_RemoveColumns( this, nOldNum );
     233           0 :             if ( IsBodyFrm() )
     234           0 :                 SetFrmFmt( pDoc->GetDfltFrmFmt() );
     235             :             else
     236           0 :                 GetFmt()->SetFmtAttr( SwFmtFillOrder() );
     237           0 :             if ( pSave )
     238           0 :                 ::RestoreCntnt( pSave, this, 0, true );
     239           0 :             return;
     240             :         }
     241          32 :         if ( nOldNum == 1 )
     242             :         {
     243          32 :             if ( IsBodyFrm() )
     244           2 :                 SetFrmFmt( pDoc->GetColumnContFmt() );
     245             :             else
     246          30 :                 GetFmt()->SetFmtAttr( SwFmtFillOrder( ATT_LEFT_TO_RIGHT ) );
     247          32 :             if( !Lower() || !Lower()->IsColumnFrm() )
     248          24 :                 --nOldNum;
     249             :         }
     250          32 :         if ( nOldNum > nNewNum )
     251             :         {
     252           0 :             ::lcl_RemoveColumns( this, nOldNum - nNewNum );
     253           0 :             bAdjustAttributes = sal_True;
     254             :         }
     255          32 :         else if( nOldNum < nNewNum )
     256             :         {
     257          24 :             sal_uInt16 nAdd = nNewNum - nOldNum;
     258          24 :             bAdjustAttributes = lcl_AddColumns( this, nAdd );
     259             :         }
     260             :     }
     261             : 
     262          32 :     if ( !bAdjustAttributes )
     263             :     {
     264          45 :         if ( rOld.GetLineWidth()    != rNew.GetLineWidth() ||
     265          30 :              rOld.GetWishWidth()    != rNew.GetWishWidth() ||
     266          15 :              rOld.IsOrtho()         != rNew.IsOrtho() )
     267           0 :             bAdjustAttributes = sal_True;
     268             :         else
     269             :         {
     270          15 :             sal_uInt16 nCount = std::min( rNew.GetColumns().size(), rOld.GetColumns().size() );
     271          15 :             for ( sal_uInt16 i = 0; i < nCount; ++i )
     272           0 :                 if ( !(rOld.GetColumns()[i] == rNew.GetColumns()[i]) )
     273             :                 {
     274           0 :                     bAdjustAttributes = sal_True;
     275           0 :                     break;
     276             :                 }
     277             :         }
     278             :     }
     279             : 
     280             :     //The columns can now be easily adjusted.
     281          32 :     AdjustColumns( &rNew, bAdjustAttributes );
     282             : 
     283             :     //Don't restore the content before. An earlier restore would trigger useless
     284             :     //actions during setup.
     285          32 :     if ( pSave )
     286             :     {
     287             :         OSL_ENSURE( Lower() && Lower()->IsLayoutFrm() &&
     288             :                 ((SwLayoutFrm*)Lower())->Lower() &&
     289             :                 ((SwLayoutFrm*)Lower())->Lower()->IsLayoutFrm(),
     290             :                 "Gesucht: Spaltenbody (Tod oder Lebend)." );   // ColumnFrms jetzt mit BodyFrm
     291          11 :         ::RestoreCntnt( pSave, (SwLayoutFrm*)((SwLayoutFrm*)Lower())->Lower(), 0, true );
     292             :     }
     293             : }
     294             : 
     295             : /*************************************************************************
     296             : |*
     297             : |*  SwLayoutFrm::AdjustColumns()
     298             : |*
     299             : |*************************************************************************/
     300             : 
     301          83 : void SwLayoutFrm::AdjustColumns( const SwFmtCol *pAttr, sal_Bool bAdjustAttributes )
     302             : {
     303          83 :     if( !Lower()->GetNext() )
     304             :     {
     305          12 :         Lower()->ChgSize( Prt().SSize() );
     306          27 :         return;
     307             :     }
     308             : 
     309          71 :     const sal_Bool bVert = IsVertical();
     310             :     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
     311          71 :     SwRectFn fnRect = bVert ? ( IsVertLR() ? fnRectVertL2R : fnRectVert ) : fnRectHori;
     312             : 
     313             :     //If we have a pointer or we have to configure an attribute, we set the
     314             :     //column widths in any case. Otherwise we check if a configuration is needed.
     315          71 :     if ( !pAttr )
     316             :     {
     317           3 :         pAttr = &GetFmt()->GetCol();
     318           3 :         if ( !bAdjustAttributes )
     319             :         {
     320           3 :             long nAvail = (Prt().*fnRect->fnGetWidth)();
     321          11 :             for ( SwLayoutFrm *pCol = (SwLayoutFrm*)Lower();
     322             :                   pCol;
     323           8 :                   pCol = (SwLayoutFrm*)pCol->GetNext() )
     324           8 :                 nAvail -= (pCol->Frm().*fnRect->fnGetWidth)();
     325           3 :             if ( !nAvail )
     326           3 :                 return;
     327             :         }
     328             :     }
     329             : 
     330             :     //The columns can now be easily adjusted.
     331             :     //The widths get counted so we can give the reminder to the last one.
     332          68 :     SwTwips nAvail = (Prt().*fnRect->fnGetWidth)();
     333          68 :     const sal_Bool bLine = pAttr->GetLineAdj() != COLADJ_NONE;
     334          68 :     const sal_uInt16 nMin = bLine ? sal_uInt16( 20 + ( pAttr->GetLineWidth() / 2) ) : 0;
     335             : 
     336          68 :     const sal_Bool bR2L = IsRightToLeft();
     337          68 :     SwFrm *pCol = bR2L ? GetLastLower() : Lower();
     338             : 
     339             :     // #i27399#
     340             :     // bOrtho means we have to adjust the column frames manually. Otherwise
     341             :     // we may use the values returned by CalcColWidth:
     342          68 :     const sal_Bool bOrtho = pAttr->IsOrtho() && pAttr->GetNumCols() > 0;
     343          68 :     long nGutter = 0;
     344             : 
     345         270 :     for ( sal_uInt16 i = 0; i < pAttr->GetNumCols() && pCol; ++i ) //i118878, value returned by GetNumCols() can't be trusted
     346             :     {
     347         202 :         if( !bOrtho )
     348             :         {
     349           4 :             const SwTwips nWidth = i == (pAttr->GetNumCols() - 1) ?
     350             :                                    nAvail :
     351           4 :                                    pAttr->CalcColWidth( i, sal_uInt16( (Prt().*fnRect->fnGetWidth)() ) );
     352             : 
     353             :             const Size aColSz = bVert ?
     354           0 :                                 Size( Prt().Width(), nWidth ) :
     355           4 :                                 Size( nWidth, Prt().Height() );
     356             : 
     357           4 :             pCol->ChgSize( aColSz );
     358             : 
     359             :             // With this, the ColumnBodyFrms from page columns gets adjusted and
     360             :             // their bFixHeight flag is set so they won't shrink/grow.
     361             :             // Don't use the flag with frame columns because BodyFrms in frame
     362             :             // columns can grow/shrink.
     363           4 :             if( IsBodyFrm() )
     364           4 :                 ((SwLayoutFrm*)pCol)->Lower()->ChgSize( aColSz );
     365             : 
     366           4 :             nAvail -= nWidth;
     367             :         }
     368             : 
     369         202 :         if ( bOrtho || bAdjustAttributes )
     370             :         {
     371         202 :             const SwColumn *pC = &pAttr->GetColumns()[i];
     372         202 :             const SwAttrSet* pSet = pCol->GetAttrSet();
     373         202 :             SvxLRSpaceItem aLR( pSet->GetLRSpace() );
     374             : 
     375             :             //In order to have enough space for the separation lines, we have to
     376             :             //take them into account here. Every time two columns meet we
     377             :             //calculate a clearance of 20 + half the pen width on the left or
     378             :             //right side, respectively.
     379         202 :             const sal_uInt16 nLeft = pC->GetLeft();
     380         202 :             const sal_uInt16 nRight = pC->GetRight();
     381             : 
     382         202 :             aLR.SetLeft ( nLeft );
     383         202 :             aLR.SetRight( nRight );
     384             : 
     385         202 :             if ( bLine )
     386             :             {
     387           0 :                 if ( i == 0 )
     388             :                 {
     389           0 :                     aLR.SetRight( std::max( nRight, nMin ) );
     390             :                 }
     391           0 :                 else if ( i == pAttr->GetNumCols() - 1 )
     392             :                 {
     393           0 :                     aLR.SetLeft ( std::max( nLeft, nMin ) );
     394             :                 }
     395             :                 else
     396             :                 {
     397           0 :                     aLR.SetLeft ( std::max( nLeft,  nMin ) );
     398           0 :                     aLR.SetRight( std::max( nRight, nMin ) );
     399             :                 }
     400             :             }
     401             : 
     402         202 :             if ( bAdjustAttributes )
     403             :             {
     404          16 :                 SvxULSpaceItem aUL( pSet->GetULSpace() );
     405          16 :                 aUL.SetUpper( pC->GetUpper());
     406          16 :                 aUL.SetLower( pC->GetLower());
     407             : 
     408          16 :                 ((SwLayoutFrm*)pCol)->GetFmt()->SetFmtAttr( aLR );
     409          16 :                 ((SwLayoutFrm*)pCol)->GetFmt()->SetFmtAttr( aUL );
     410             :             }
     411             : 
     412         202 :             nGutter += aLR.GetLeft() + aLR.GetRight();
     413             :         }
     414             : 
     415         202 :         pCol = bR2L ? pCol->GetPrev() : pCol->GetNext();
     416             :     }
     417             : 
     418          68 :     if( bOrtho )
     419             :     {
     420          66 :         long nInnerWidth = ( nAvail - nGutter ) / pAttr->GetNumCols();
     421          66 :         pCol = Lower();
     422         264 :         for( sal_uInt16 i = 0; i < pAttr->GetNumCols() && pCol; pCol = pCol->GetNext(), ++i ) //i118878, value returned by GetNumCols() can't be trusted
     423             :         {
     424             :             SwTwips nWidth;
     425         198 :             if ( i == pAttr->GetNumCols() - 1 )
     426          66 :                 nWidth = nAvail;
     427             :             else
     428             :             {
     429         132 :                 SvxLRSpaceItem aLR( pCol->GetAttrSet()->GetLRSpace() );
     430         132 :                 nWidth = nInnerWidth + aLR.GetLeft() + aLR.GetRight();
     431             :             }
     432         198 :             if( nWidth < 0 )
     433           0 :                 nWidth = 0;
     434             : 
     435             :             const Size aColSz = bVert ?
     436           0 :                                 Size( Prt().Width(), nWidth ) :
     437         198 :                                 Size( nWidth, Prt().Height() );
     438             : 
     439         198 :             pCol->ChgSize( aColSz );
     440             : 
     441         198 :             if( IsBodyFrm() )
     442           0 :                 ((SwLayoutFrm*)pCol)->Lower()->ChgSize( aColSz );
     443             : 
     444         198 :             nAvail -= nWidth;
     445             :         }
     446             :     }
     447          99 : }
     448             : 
     449             : 
     450             : 
     451             : 
     452             : 
     453             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10