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

Generated by: LCOV version 1.10