LCOV - code coverage report
Current view: top level - sw/source/core/text - widorp.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 126 201 62.7 %
Date: 2012-08-25 Functions: 9 9 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 147 382 38.5 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*************************************************************************
       3                 :            :  *
       4                 :            :  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       5                 :            :  *
       6                 :            :  * Copyright 2000, 2010 Oracle and/or its affiliates.
       7                 :            :  *
       8                 :            :  * OpenOffice.org - a multi-platform office productivity suite
       9                 :            :  *
      10                 :            :  * This file is part of OpenOffice.org.
      11                 :            :  *
      12                 :            :  * OpenOffice.org is free software: you can redistribute it and/or modify
      13                 :            :  * it under the terms of the GNU Lesser General Public License version 3
      14                 :            :  * only, as published by the Free Software Foundation.
      15                 :            :  *
      16                 :            :  * OpenOffice.org is distributed in the hope that it will be useful,
      17                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      18                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19                 :            :  * GNU Lesser General Public License version 3 for more details
      20                 :            :  * (a copy is included in the LICENSE file that accompanied this code).
      21                 :            :  *
      22                 :            :  * You should have received a copy of the GNU Lesser General Public License
      23                 :            :  * version 3 along with OpenOffice.org.  If not, see
      24                 :            :  * <http://www.openoffice.org/license.html>
      25                 :            :  * for a copy of the LGPLv3 License.
      26                 :            :  *
      27                 :            :  ************************************************************************/
      28                 :            : 
      29                 :            : #include "hintids.hxx"
      30                 :            : 
      31                 :            : #include "layfrm.hxx"
      32                 :            : #include "ftnboss.hxx"
      33                 :            : #include "ndtxt.hxx"
      34                 :            : #include "paratr.hxx"
      35                 :            : #include <editeng/orphitem.hxx>
      36                 :            : #include <editeng/widwitem.hxx>
      37                 :            : #include <editeng/keepitem.hxx>
      38                 :            : #include <editeng/spltitem.hxx>
      39                 :            : #include <frmatr.hxx>
      40                 :            : #include <txtftn.hxx>
      41                 :            : #include <fmtftn.hxx>
      42                 :            : #include <rowfrm.hxx>
      43                 :            : 
      44                 :            : #include "widorp.hxx"
      45                 :            : #include "txtfrm.hxx"
      46                 :            : #include "itrtxt.hxx"
      47                 :            : #include "sectfrm.hxx"  //SwSectionFrm
      48                 :            : #include "ftnfrm.hxx"
      49                 :            : 
      50                 :            : #undef WIDOWTWIPS
      51                 :            : 
      52                 :            : 
      53                 :            : /*************************************************************************
      54                 :            :  *                  inline IsNastyFollow()
      55                 :            :  *************************************************************************/
      56                 :            : // Ein Follow, der auf der selben Seite steht, wie sein Master ist nasty.
      57                 :      12410 : inline sal_Bool IsNastyFollow( const SwTxtFrm *pFrm )
      58                 :            : {
      59                 :            :     OSL_ENSURE( !pFrm->IsFollow() || !pFrm->GetPrev() ||
      60                 :            :             ((const SwTxtFrm*)pFrm->GetPrev())->GetFollow() == pFrm,
      61                 :            :             "IsNastyFollow: Was ist denn hier los?" );
      62 [ +  + ][ -  + ]:      12410 :     return  pFrm->IsFollow() && pFrm->GetPrev();
      63                 :            : }
      64                 :            : 
      65                 :            : /*************************************************************************
      66                 :            :  *                  SwTxtFrmBreak::SwTxtFrmBreak()
      67                 :            :  *************************************************************************/
      68                 :            : 
      69                 :      14871 : SwTxtFrmBreak::SwTxtFrmBreak( SwTxtFrm *pNewFrm, const SwTwips nRst )
      70                 :      14871 :     : nRstHeight(nRst), pFrm(pNewFrm)
      71                 :            : {
      72 [ -  + ][ #  # ]:      14871 :     SWAP_IF_SWAPPED( pFrm )
                 [ -  + ]
      73 [ -  + ][ #  # ]:      14871 :     SWRECTFN( pFrm )
         [ #  # ][ -  + ]
      74         [ +  - ]:      14871 :     nOrigin = (pFrm->*fnRect->fnGetPrtTop)();
      75                 :            :     SwSectionFrm* pSct;
      76                 :      27281 :     bKeep = !pFrm->IsMoveable() || IsNastyFollow( pFrm ) ||
      77                 :      12595 :             ( pFrm->IsInSct() && (pSct=pFrm->FindSctFrm())->Lower()->IsColumnFrm()
      78                 :         34 :               && !pSct->MoveAllowed( pFrm ) ) ||
      79                 :      12402 :             !pFrm->GetTxtNode()->GetSwAttrSet().GetSplit().GetValue() ||
      80   [ +  +  +  +  :      52312 :             pFrm->GetTxtNode()->GetSwAttrSet().GetKeep().GetValue();
           +  + ][ +  + ]
           [ +  +  +  -  
                   +  + ]
      81                 :      14871 :     bBreak = sal_False;
      82                 :            : 
      83 [ +  + ][ +  + ]:      14871 :     if( !nRstHeight && !pFrm->IsFollow() && pFrm->IsInFtn() && pFrm->HasPara() )
         [ +  + ][ +  - ]
                 [ +  + ]
      84                 :            :     {
      85                 :        231 :         nRstHeight = pFrm->GetFtnFrmHeight();
      86         [ +  - ]:        231 :         nRstHeight += (pFrm->Prt().*fnRect->fnGetHeight)() -
      87         [ +  - ]:        231 :                       (pFrm->Frm().*fnRect->fnGetHeight)();
      88         [ -  + ]:        231 :         if( nRstHeight < 0 )
      89                 :          0 :             nRstHeight = 0;
      90                 :            :     }
      91                 :            : 
      92         [ -  + ]:      14871 :     UNDO_SWAP( pFrm )
      93                 :      14871 : }
      94                 :            : 
      95                 :            : /* BP 18.6.93: Widows.
      96                 :            :  * Im Gegensatz zur ersten Implementierung werden die Widows nicht
      97                 :            :  * mehr vorausschauend berechnet, sondern erst beim Formatieren des
      98                 :            :  * gesplitteten Follows festgestellt. Im Master faellt die Widows-
      99                 :            :  * Berechnung also generell weg (nWidows wird manipuliert).
     100                 :            :  * Wenn der Follow feststellt, dass die Widowsregel zutrifft,
     101                 :            :  * verschickt er an seinen Vorgaenger ein Prepare.
     102                 :            :  * Ein besonderes Problem ergibt sich, wenn die Widows zuschlagen,
     103                 :            :  * aber im Master noch ein paar Zeilen zur Verfuegung stehen.
     104                 :            :  *
     105                 :            :  */
     106                 :            : 
     107                 :            : /*************************************************************************
     108                 :            :  *                  SwTxtFrmBreak::IsInside()
     109                 :            :  *************************************************************************/
     110                 :            : 
     111                 :            : /* BP(22.07.92): Berechnung von Witwen und Waisen.
     112                 :            :  * Die Methode liefert sal_True zurueck, wenn eine dieser Regelung zutrifft.
     113                 :            :  *
     114                 :            :  * Eine Schwierigkeit gibt es im Zusammenhang mit Widows und
     115                 :            :  * unterschiedlichen Formaten zwischen Master- und Folgeframes:
     116                 :            :  * Beispiel: Wenn die erste Spalte 3cm und die zweite 4cm breit ist
     117                 :            :  * und Widows auf sagen wir 3 gesetzt ist, so ist erst bei der Formatierung
     118                 :            :  * des Follows entscheidbar, ob die Widowsbedingung einhaltbar ist oder
     119                 :            :  * nicht. Leider ist davon abhaengig, ob der Absatz als Ganzes auf die
     120                 :            :  * naechste Seite rutscht.
     121                 :            :  */
     122                 :            : 
     123                 :      86340 : sal_Bool SwTxtFrmBreak::IsInside( SwTxtMargin &rLine ) const
     124                 :            : {
     125                 :      86340 :     sal_Bool bFit = sal_False;
     126                 :            : 
     127 [ -  + ][ #  # ]:      86340 :     SWAP_IF_SWAPPED( pFrm )
                 [ -  + ]
     128 [ -  + ][ #  # ]:      86340 :     SWRECTFN( pFrm )
         [ #  # ][ -  + ]
     129                 :            :     // nOrigin is an absolut value, rLine referes to the swapped situation.
     130                 :            : 
     131                 :            :     SwTwips nTmpY;
     132         [ -  + ]:      86340 :     if ( pFrm->IsVertical() )
     133                 :          0 :         nTmpY = pFrm->SwitchHorizontalToVertical( rLine.Y() + rLine.GetLineHeight() );
     134                 :            :     else
     135                 :      86340 :         nTmpY = rLine.Y() + rLine.GetLineHeight();
     136                 :            : 
     137                 :      86340 :     SwTwips nLineHeight = (*fnRect->fnYDiff)( nTmpY , nOrigin );
     138                 :            : 
     139                 :            :     // 7455 und 6114: Raum fuer die Umrandung unten einkalkulieren.
     140         [ +  - ]:      86340 :     nLineHeight += (pFrm->*fnRect->fnGetBottomMargin)();
     141                 :            : 
     142         [ +  + ]:      86340 :     if( nRstHeight )
     143                 :       1723 :         bFit = nRstHeight >= nLineHeight;
     144                 :            :     else
     145                 :            :     {
     146                 :            :         // Der Frm besitzt eine Hoehe, mit der er auf die Seite passt.
     147                 :            :         SwTwips nHeight =
     148         [ +  - ]:      84617 :             (*fnRect->fnYDiff)( (pFrm->GetUpper()->*fnRect->fnGetPrtBottom)(), nOrigin );
     149                 :            :         // Wenn sich alles innerhalb des bestehenden Frames abspielt,
     150                 :            :         // ist das Ergebnis sal_True;
     151                 :      84617 :         bFit = nHeight >= nLineHeight;
     152                 :            : 
     153                 :            :         // --> OD #i103292#
     154         [ +  + ]:      84617 :         if ( !bFit )
     155                 :            :         {
     156   [ +  +  -  +  :       2093 :             if ( rLine.GetNext() &&
             #  #  #  # ]
                 [ -  + ]
     157                 :         54 :                  pFrm->IsInTab() && !pFrm->GetFollow() && !pFrm->GetIndNext() )
     158                 :            :             {
     159                 :            :                 // add additional space taken as lower space as last content in a table
     160                 :            :                 // for all text lines except the last one.
     161                 :          0 :                 nHeight += pFrm->CalcAddLowerSpaceAsLastInTableCell();
     162                 :          0 :                 bFit = nHeight >= nLineHeight;
     163                 :            :             }
     164                 :            :         }
     165                 :            :         // <--
     166         [ +  + ]:      84617 :         if( !bFit )
     167                 :            :         {
     168                 :            :             // Die LineHeight sprengt die aktuelle Frm-Hoehe.
     169                 :            :             // Nun rufen wir ein Probe-Grow, um zu ermitteln, ob der
     170                 :            :             // Frame um den gewuenschten Bereich wachsen wuerde.
     171                 :       2039 :             nHeight += pFrm->GrowTst( LONG_MAX );
     172                 :            : 
     173                 :            :             // Das Grow() returnt die Hoehe, um die der Upper des TxtFrm
     174                 :            :             // den TxtFrm wachsen lassen wuerde.
     175                 :            :             // Der TxtFrm selbst darf wachsen wie er will.
     176                 :       2039 :             bFit = nHeight >= nLineHeight;
     177                 :            :         }
     178                 :            :     }
     179                 :            : 
     180         [ -  + ]:      86340 :     UNDO_SWAP( pFrm );
     181                 :            : 
     182                 :      86340 :     return bFit;
     183                 :            : }
     184                 :            : 
     185                 :            : /*************************************************************************
     186                 :            :  *                  SwTxtFrmBreak::IsBreakNow()
     187                 :            :  *************************************************************************/
     188                 :            : 
     189                 :      99056 : sal_Bool SwTxtFrmBreak::IsBreakNow( SwTxtMargin &rLine )
     190                 :            : {
     191 [ -  + ][ #  # ]:      99056 :     SWAP_IF_SWAPPED( pFrm )
                 [ -  + ]
     192                 :            : 
     193                 :            :     // bKeep ist staerker als IsBreakNow()
     194                 :            :     // Ist noch genug Platz ?
     195 [ +  + ][ +  + ]:      99056 :     if( bKeep || IsInside( rLine ) )
                 [ +  + ]
     196                 :      96520 :         bBreak = sal_False;
     197                 :            :     else
     198                 :            :     {
     199                 :            :         /* Diese Klasse geht davon aus, dass der SwTxtMargin von Top nach Bottom
     200                 :            :          * durchgearbeitet wird. Aus Performancegruenden wird in folgenden
     201                 :            :          * Faellen der Laden fuer das weitere Aufspalten dicht gemacht:
     202                 :            :          * Wenn eine einzige Zeile nicht mehr passt.
     203                 :            :          * Sonderfall: bei DummyPortions ist LineNr == 1, obwohl wir splitten
     204                 :            :          * wollen.
     205                 :            :          */
     206                 :            :         // 6010: DropLines mit einbeziehen
     207                 :            : 
     208 [ +  + ][ +  + ]:       2536 :         sal_Bool bFirstLine = 1 == rLine.GetLineNr() && !rLine.GetPrev();
     209                 :       2536 :         bBreak = sal_True;
     210         [ +  + ]:       5045 :         if( ( bFirstLine && pFrm->GetIndPrev() )
           [ +  +  -  + ]
                 [ +  + ]
     211                 :       2509 :             || ( rLine.GetLineNr() <= rLine.GetDropLines() ) )
     212                 :            :         {
     213                 :         27 :             bKeep = sal_True;
     214                 :         27 :             bBreak = sal_False;
     215                 :            :         }
     216 [ +  + ][ -  + ]:       2509 :         else if(bFirstLine && pFrm->IsInFtn() && !pFrm->FindFtnFrm()->GetPrev())
         [ #  # ][ -  + ]
     217                 :            :         {
     218                 :          0 :             SwLayoutFrm* pTmp = pFrm->FindFtnBossFrm()->FindBodyCont();
     219 [ #  # ][ #  # ]:          0 :             if( !pTmp || !pTmp->Lower() )
                 [ #  # ]
     220                 :          0 :                 bBreak = sal_False;
     221                 :            :         }
     222                 :            :     }
     223                 :            : 
     224         [ -  + ]:      99056 :     UNDO_SWAP( pFrm )
     225                 :            : 
     226                 :      99056 :     return bBreak;
     227                 :            : }
     228                 :            : 
     229                 :            : // OD 2004-02-27 #106629# - no longer inline
     230                 :        323 : void SwTxtFrmBreak::SetRstHeight( const SwTxtMargin &rLine )
     231                 :            : {
     232                 :            :     // OD, FME 2004-02-27 #106629# - consider bottom margin
     233 [ -  + ][ #  # ]:        323 :     SWRECTFN( pFrm )
         [ #  # ][ -  + ]
     234                 :            : 
     235         [ +  - ]:        323 :     nRstHeight = (pFrm->*fnRect->fnGetBottomMargin)();
     236                 :            : 
     237         [ -  + ]:        323 :     if ( bVert )
     238                 :            :     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
     239                 :            :     {
     240         [ #  # ]:          0 :            if ( pFrm->IsVertLR() )
     241                 :          0 :               nRstHeight = (*fnRect->fnYDiff)( pFrm->SwitchHorizontalToVertical( rLine.Y() ) , nOrigin );
     242                 :            :            else
     243                 :          0 :                nRstHeight += nOrigin - pFrm->SwitchHorizontalToVertical( rLine.Y() );
     244                 :            :     }
     245                 :            :     else
     246                 :        323 :         nRstHeight += rLine.Y() - nOrigin;
     247                 :        323 : }
     248                 :            : 
     249                 :            : /*************************************************************************
     250                 :            :  *                  WidowsAndOrphans::WidowsAndOrphans()
     251                 :            :  *************************************************************************/
     252                 :            : 
     253                 :      14871 : WidowsAndOrphans::WidowsAndOrphans( SwTxtFrm *pNewFrm, const SwTwips nRst,
     254                 :            :     sal_Bool bChkKeep   )
     255                 :      14871 :     : SwTxtFrmBreak( pNewFrm, nRst ), nWidLines( 0 ), nOrphLines( 0 )
     256                 :            : {
     257 [ #  # ][ -  + ]:      14871 :     SWAP_IF_SWAPPED( pFrm )
                 [ -  + ]
     258                 :            : 
     259         [ +  + ]:      14871 :     if( bKeep )
     260                 :            :     {
     261                 :            :         // 5652: bei Absaetzen, die zusammengehalten werden sollen und
     262                 :            :         // groesser sind als die Seite wird bKeep aufgehoben.
     263 [ +  - ][ +  + ]:       5111 :         if( bChkKeep && !pFrm->GetPrev() && !pFrm->IsInFtn() &&
           [ +  -  +  +  
             +  +  -  + ]
                 [ +  + ]
     264                 :       2464 :             pFrm->IsMoveable() &&
     265                 :         91 :             ( !pFrm->IsInSct() || pFrm->FindSctFrm()->MoveAllowed(pFrm) ) )
     266                 :         15 :             bKeep = sal_False;
     267                 :            :         //Auch bei gesetztem Keep muessen Orphans beachtet werden,
     268                 :            :         //z.B. bei verketteten Rahmen erhaelt ein Follow im letzten Rahmen ein Keep,
     269                 :            :         //da er nicht (vorwaerts) Moveable ist,
     270                 :            :         //er darf aber trotzdem vom Master Zeilen anfordern wg. der Orphanregel.
     271         [ -  + ]:       2556 :         if( pFrm->IsFollow() )
     272                 :          0 :             nWidLines = pFrm->GetTxtNode()->GetSwAttrSet().GetWidows().GetValue();
     273                 :            :     }
     274                 :            :     else
     275                 :            :     {
     276                 :      12315 :         const SwAttrSet& rSet = pFrm->GetTxtNode()->GetSwAttrSet();
     277                 :      12315 :         const SvxOrphansItem  &rOrph = rSet.GetOrphans();
     278         [ +  + ]:      12315 :         if ( rOrph.GetValue() > 1 )
     279                 :        301 :             nOrphLines = rOrph.GetValue();
     280         [ +  + ]:      12315 :         if ( pFrm->IsFollow() )
     281                 :       1726 :             nWidLines = rSet.GetWidows().GetValue();
     282                 :            : 
     283                 :            :     }
     284                 :            : 
     285 [ +  + ][ +  - ]:      14871 :     if ( bKeep || nWidLines || nOrphLines )
                 [ +  + ]
     286                 :            :     {
     287                 :       2842 :         bool bResetFlags = false;
     288                 :            : 
     289         [ +  + ]:       2842 :         if ( pFrm->IsInTab() )
     290                 :            :         {
     291                 :            :             // For compatibility reasons, we disable Keep/Widows/Orphans
     292                 :            :             // inside splittable row frames:
     293 [ +  - ][ -  + ]:       2078 :             if ( pFrm->GetNextCellLeaf( MAKEPAGE_NONE ) || pFrm->IsInFollowFlowRow() )
                 [ -  + ]
     294                 :            :             {
     295                 :          0 :                 const SwFrm* pTmpFrm = pFrm->GetUpper();
     296         [ #  # ]:          0 :                 while ( !pTmpFrm->IsRowFrm() )
     297                 :          0 :                     pTmpFrm = pTmpFrm->GetUpper();
     298         [ #  # ]:          0 :                 if ( static_cast<const SwRowFrm*>(pTmpFrm)->IsRowSplitAllowed() )
     299                 :          0 :                     bResetFlags = true;
     300                 :            :             }
     301                 :            :         }
     302                 :            : 
     303 [ -  + ][ #  # ]:       2842 :         if( pFrm->IsInFtn() && !pFrm->GetIndPrev() )
                 [ -  + ]
     304                 :            :         {
     305                 :            :             // Innerhalb von Fussnoten gibt es gute Gruende, das Keep-Attribut und
     306                 :            :             // die Widows/Orphans abzuschalten.
     307                 :          0 :             SwFtnFrm *pFtn = pFrm->FindFtnFrm();
     308                 :          0 :             sal_Bool bFt = !pFtn->GetAttr()->GetFtn().IsEndNote();
     309 [ #  # ][ #  #  :          0 :             if( !pFtn->GetPrev() &&
          #  #  #  #  #  
                      # ]
     310                 :          0 :                 pFtn->FindFtnBossFrm( bFt ) != pFtn->GetRef()->FindFtnBossFrm( bFt )
     311                 :          0 :                 && ( !pFrm->IsInSct() || pFrm->FindSctFrm()->MoveAllowed(pFrm) ) )
     312                 :            :             {
     313                 :          0 :                 bResetFlags = true;
     314                 :            :             }
     315                 :            :         }
     316                 :            : 
     317         [ -  + ]:       2842 :         if ( bResetFlags )
     318                 :            :         {
     319                 :          0 :             bKeep = sal_False;
     320                 :          0 :             nOrphLines = 0;
     321                 :          0 :             nWidLines = 0;
     322                 :            :         }
     323                 :            :     }
     324                 :            : 
     325         [ -  + ]:      14871 :     UNDO_SWAP( pFrm )
     326                 :      14871 : }
     327                 :            : 
     328                 :            : /*************************************************************************
     329                 :            :  *                  WidowsAndOrphans::FindBreak()
     330                 :            :  *************************************************************************/
     331                 :            : 
     332                 :            : /* Die Find*-Methoden suchen nicht nur, sondern stellen den SwTxtMargin auf
     333                 :            :  * die Zeile ein, wo der Absatz gebrochen werden soll und kuerzen ihn dort.
     334                 :            :  * FindBreak()
     335                 :            :  */
     336                 :            : 
     337                 :      14711 : sal_Bool WidowsAndOrphans::FindBreak( SwTxtFrm *pFrame, SwTxtMargin &rLine,
     338                 :            :     sal_Bool bHasToFit )
     339                 :            : {
     340                 :            :     // OD 2004-02-25 #i16128# - Why member <pFrm> _*and*_ parameter <pFrame>??
     341                 :            :     // Thus, assertion on situation, that these are different to figure out why.
     342                 :            :     OSL_ENSURE( pFrm == pFrame, "<WidowsAndOrphans::FindBreak> - pFrm != pFrame" );
     343                 :            : 
     344 [ -  + ][ #  # ]:      14711 :     SWAP_IF_SWAPPED( pFrm )
                 [ -  + ]
     345                 :            : 
     346                 :      14711 :     sal_Bool bRet = sal_True;
     347                 :      14711 :     MSHORT nOldOrphans = nOrphLines;
     348         [ +  + ]:      14711 :     if( bHasToFit )
     349                 :         26 :         nOrphLines = 0;
     350                 :      14711 :     rLine.Bottom();
     351                 :            :     // OD 2004-02-25 #i16128# - method renamed
     352         [ +  + ]:      14711 :     if( !IsBreakNowWidAndOrp( rLine ) )
     353                 :      13891 :         bRet = sal_False;
     354         [ +  - ]:      14711 :     if( !FindWidows( pFrame, rLine ) )
     355                 :            :     {
     356                 :      14711 :         sal_Bool bBack = sal_False;
     357                 :            :         // OD 2004-02-25 #i16128# - method renamed
     358         [ +  + ]:      15426 :         while( IsBreakNowWidAndOrp( rLine ) )
     359                 :            :         {
     360         [ +  + ]:        841 :             if( rLine.PrevLine() )
     361                 :        715 :                 bBack = sal_True;
     362                 :            :             else
     363                 :        126 :                 break;
     364                 :            :         }
     365                 :            :         // Eigentlich werden bei HasToFit Schusterjungen (Orphans) nicht
     366                 :            :         // beruecksichtigt, wenn allerdings Dummy-Lines im Spiel sind und
     367                 :            :         // die Orphansregel verletzt wird, machen wir mal eine Ausnahme:
     368                 :            :         // Wir lassen einfach eine Dummyline zurueck und wandern mit dem Text
     369                 :            :         // komplett auf die naechste Seite/Spalte.
     370   [ +  +  +  + ]:      15021 :         if( rLine.GetLineNr() <= nOldOrphans &&
                 [ -  + ]
           [ #  #  -  + ]
                 [ -  + ]
     371                 :        286 :             rLine.GetInfo().GetParaPortion()->IsDummy() &&
     372                 :         24 :             ( ( bHasToFit && bRet ) || IsBreakNow( rLine ) ) )
     373                 :          0 :             rLine.Top();
     374                 :            : 
     375                 :      14711 :         rLine.TruncLines( sal_True );
     376                 :      14711 :         bRet = bBack;
     377                 :            :     }
     378                 :      14711 :     nOrphLines = nOldOrphans;
     379                 :            : 
     380         [ -  + ]:      14711 :     UNDO_SWAP( pFrm )
     381                 :            : 
     382                 :      14711 :     return bRet;
     383                 :            : }
     384                 :            : 
     385                 :            : /*************************************************************************
     386                 :            :  *                  WidowsAndOrphans::FindWidows()
     387                 :            :  *************************************************************************/
     388                 :            : 
     389                 :            : /*  FindWidows positioniert den SwTxtMargin des Masters auf die umzubrechende
     390                 :            :  *  Zeile, indem der Follow formatiert und untersucht wird.
     391                 :            :  *  Liefert sal_True zurueck, wenn die Widows-Regelung in Kraft tritt,
     392                 :            :  *  d.h. der Absatz _zusammengehalten_ werden soll !
     393                 :            :  */
     394                 :            : 
     395                 :      14711 : sal_Bool WidowsAndOrphans::FindWidows( SwTxtFrm *pFrame, SwTxtMargin &rLine )
     396                 :            : {
     397                 :            :     OSL_ENSURE( ! pFrame->IsVertical() || ! pFrame->IsSwapped(),
     398                 :            :             "WidowsAndOrphans::FindWidows with swapped frame" );
     399                 :            : 
     400 [ -  + ][ #  # ]:      14711 :     if( !nWidLines || !pFrame->IsFollow() )
                 [ +  - ]
     401                 :      14711 :         return sal_False;
     402                 :            : 
     403         [ #  # ]:          0 :     rLine.Bottom();
     404                 :            : 
     405                 :            :     // Wir koennen noch was abzwacken
     406         [ #  # ]:          0 :     SwTxtFrm *pMaster = pFrame->FindMaster();
     407                 :            :     OSL_ENSURE(pMaster, "+WidowsAndOrphans::FindWidows: Widows in a master?");
     408         [ #  # ]:          0 :     if( !pMaster )
     409                 :          0 :         return sal_False;
     410                 :            : 
     411                 :            :     // 5156: Wenn die erste Zeile des Follows nicht passt, wird der Master
     412                 :            :     // wohl voll mit Dummies sein. In diesem Fall waere ein PREP_WIDOWS fatal.
     413         [ #  # ]:          0 :     if( pMaster->GetOfst() == pFrame->GetOfst() )
     414                 :          0 :         return sal_False;
     415                 :            : 
     416                 :            :     // Resthoehe des Masters
     417 [ #  # ][ #  # ]:          0 :     SWRECTFN( pFrame )
         [ #  # ][ #  # ]
                 [ #  # ]
     418                 :            : 
     419 [ #  # ][ #  # ]:          0 :     const SwTwips nDocPrtTop = (pFrame->*fnRect->fnGetPrtTop)();
     420                 :            :     SwTwips nOldHeight;
     421                 :          0 :     SwTwips nTmpY = rLine.Y() + rLine.GetLineHeight();
     422                 :            : 
     423         [ #  # ]:          0 :     if ( bVert )
     424                 :            :     {
     425         [ #  # ]:          0 :         nTmpY = pFrame->SwitchHorizontalToVertical( nTmpY );
     426 [ #  # ][ #  # ]:          0 :         nOldHeight = -(pFrame->Prt().*fnRect->fnGetHeight)();
     427                 :            :     }
     428                 :            :     else
     429 [ #  # ][ #  # ]:          0 :         nOldHeight = (pFrame->Prt().*fnRect->fnGetHeight)();
     430                 :            : 
     431         [ #  # ]:          0 :     const SwTwips nChg = (*fnRect->fnYDiff)( nTmpY, nDocPrtTop + nOldHeight );
     432                 :            : 
     433                 :            :     // Unterhalb der Widows-Schwelle...
     434         [ #  # ]:          0 :     if( rLine.GetLineNr() >= nWidLines )
     435                 :            :     {
     436                 :            :         // 8575: Follow to Master I
     437                 :            :         // Wenn der Follow *waechst*, so besteht fuer den Master die Chance,
     438                 :            :         // Zeilen entgegenzunehmen, die er vor Kurzem gezwungen war an den
     439                 :            :         // Follow abzugeben: Prepare(Need); diese Abfrage unterhalb von nChg!
     440                 :            :         // (0W, 2O, 2M, 2F) + 1F = 3M, 2F
     441 [ #  # ][ #  # ]:          0 :         if( rLine.GetLineNr() > nWidLines && pFrame->IsJustWidow() )
                 [ #  # ]
     442                 :            :         {
     443                 :            :             // Wenn der Master gelockt ist, so hat er vermutlich gerade erst
     444                 :            :             // eine Zeile an uns abgegeben, diese geben nicht zurueck, nur
     445                 :            :             // weil bei uns daraus mehrere geworden sind (z.B. durch Rahmen).
     446 [ #  # ][ #  # ]:          0 :             if( !pMaster->IsLocked() && pMaster->GetUpper() )
                 [ #  # ]
     447                 :            :             {
     448                 :          0 :                 const SwTwips nTmpRstHeight = (pMaster->Frm().*fnRect->fnBottomDist)
     449 [ #  # ][ #  # ]:          0 :                             ( (pMaster->GetUpper()->*fnRect->fnGetPrtBottom)() );
         [ #  # ][ #  # ]
     450         [ #  # ]:          0 :                 if ( nTmpRstHeight >=
     451                 :          0 :                      SwTwips(rLine.GetInfo().GetParaPortion()->Height() ) )
     452                 :            :                 {
     453         [ #  # ]:          0 :                     pMaster->Prepare( PREP_ADJUST_FRM );
     454         [ #  # ]:          0 :                     pMaster->_InvalidateSize();
     455         [ #  # ]:          0 :                     pMaster->InvalidatePage();
     456                 :            :                 }
     457                 :            :             }
     458                 :            : 
     459                 :          0 :             pFrame->SetJustWidow( sal_False );
     460                 :            :         }
     461                 :          0 :         return sal_False;
     462                 :            :     }
     463                 :            : 
     464                 :            :     // 8575: Follow to Master II
     465                 :            :     // Wenn der Follow *schrumpft*, so besteht fuer den Master die Chance,
     466                 :            :     // den kompletten Orphan zu inhalieren.
     467                 :            :     // (0W, 2O, 2M, 1F) - 1F = 3M, 0F     -> PREP_ADJUST_FRM
     468                 :            :     // (0W, 2O, 3M, 2F) - 1F = 2M, 2F     -> PREP_WIDOWS
     469                 :            : 
     470 [ #  # ][ #  # ]:          0 :     if( 0 > nChg && !pMaster->IsLocked() && pMaster->GetUpper() )
         [ #  # ][ #  # ]
     471                 :            :     {
     472                 :          0 :         SwTwips nTmpRstHeight = (pMaster->Frm().*fnRect->fnBottomDist)
     473 [ #  # ][ #  # ]:          0 :                              ( (pMaster->GetUpper()->*fnRect->fnGetPrtBottom)() );
         [ #  # ][ #  # ]
     474         [ #  # ]:          0 :         if( nTmpRstHeight >= SwTwips(rLine.GetInfo().GetParaPortion()->Height() ) )
     475                 :            :         {
     476         [ #  # ]:          0 :             pMaster->Prepare( PREP_ADJUST_FRM );
     477         [ #  # ]:          0 :             pMaster->_InvalidateSize();
     478         [ #  # ]:          0 :             pMaster->InvalidatePage();
     479                 :          0 :             pFrame->SetJustWidow( sal_False );
     480                 :          0 :             return sal_False;
     481                 :            :         }
     482                 :            :     }
     483                 :            : 
     484                 :            :     // Master to Follow
     485                 :            :     // Wenn der Follow nach seiner Formatierung weniger Zeilen enthaelt
     486                 :            :     // als Widows, so besteht noch die Chance, einige Zeilen des Masters
     487                 :            :     // abzuzwacken. Wenn dadurch die Orphans-Regel des Masters in Kraft
     488                 :            :     // tritt muss im CalcPrep() des Master-Frame der Frame so vergroessert
     489                 :            :     // werden, dass er nicht mehr auf seine urspruengliche Seite passt.
     490                 :            :     // Wenn er noch ein paar Zeilen entbehren kann, dann muss im CalcPrep()
     491                 :            :     // ein Shrink() erfolgen, der Follow mit dem Widows rutscht dann auf
     492                 :            :     // die Seite des Masters, haelt sich aber zusammen, so dass er (endlich)
     493                 :            :     // auf die naechste Seite rutscht. - So die Theorie!
     494                 :            : 
     495                 :            : 
     496                 :            :     // Wir fordern nur noch ein Zeile zur Zeit an, weil eine Zeile des Masters
     497                 :            :     // bei uns durchaus mehrere Zeilen ergeben koennten.
     498                 :            :     // Dafuer behaelt CalcFollow solange die Kontrolle, bis der Follow alle
     499                 :            :     // notwendigen Zeilen bekommen hat.
     500                 :          0 :     MSHORT nNeed = 1; // frueher: nWidLines - rLine.GetLineNr();
     501                 :            : 
     502                 :            :     // Special case: Master cannot give lines to follow
     503                 :            :     // #i91421#
     504 [ #  # ][ #  # ]:          0 :     if ( !pMaster->GetIndPrev() )
     505                 :            :     {
     506                 :          0 :         sal_uLong nLines = pMaster->GetThisLines();
     507 [ #  # ][ #  # ]:          0 :         if(nLines == 0 && pMaster->HasPara())
         [ #  # ][ #  # ]
     508                 :            :         {
     509         [ #  # ]:          0 :             const SwParaPortion *pMasterPara = pMaster->GetPara();
     510 [ #  # ][ #  # ]:          0 :             if(pMasterPara && pMasterPara->GetNext())
                 [ #  # ]
     511                 :          0 :                 nLines = 2;
     512                 :            :         }
     513         [ #  # ]:          0 :         if( nLines <= nNeed )
     514                 :          0 :             return sal_False;
     515                 :            :     }
     516                 :            : 
     517         [ #  # ]:          0 :     pMaster->Prepare( PREP_WIDOWS, (void*)&nNeed );
     518                 :      14711 :     return sal_True;
     519                 :            : }
     520                 :            : 
     521                 :            : /*************************************************************************
     522                 :            :  *                  WidowsAndOrphans::WouldFit()
     523                 :            :  *************************************************************************/
     524                 :            : 
     525                 :         60 : sal_Bool WidowsAndOrphans::WouldFit( SwTxtMargin &rLine, SwTwips &rMaxHeight, sal_Bool bTst )
     526                 :            : {
     527                 :            :     // Here it does not matter, if pFrm is swapped or not.
     528                 :            :     // IsInside() takes care for itself
     529                 :            : 
     530                 :            :     // Wir erwarten, dass rLine auf der letzten Zeile steht!!
     531                 :            :     OSL_ENSURE( !rLine.GetNext(), "WouldFit: aLine::Bottom missed!" );
     532                 :         60 :     MSHORT nLineCnt = rLine.GetLineNr();
     533                 :            : 
     534                 :            :     // Erstmal die Orphansregel und den Initialenwunsch erfuellen ...
     535                 :         60 :     const MSHORT nMinLines = Max( GetOrphansLines(), rLine.GetDropLines() );
     536         [ -  + ]:         60 :     if ( nLineCnt < nMinLines )
     537                 :          0 :         return sal_False;
     538                 :            : 
     539                 :         60 :     rLine.Top();
     540                 :         60 :     SwTwips nLineSum = rLine.GetLineHeight();
     541                 :            : 
     542         [ -  + ]:         60 :     while( nMinLines > rLine.GetLineNr() )
     543                 :            :     {
     544         [ #  # ]:          0 :         if( !rLine.NextLine() )
     545                 :          0 :             return sal_False;
     546                 :          0 :         nLineSum += rLine.GetLineHeight();
     547                 :            :     }
     548                 :            : 
     549                 :            :     // Wenn wir jetzt schon nicht mehr passen ...
     550         [ +  + ]:         60 :     if( !IsInside( rLine ) )
     551                 :         54 :         return sal_False;
     552                 :            : 
     553                 :            :     // Jetzt noch die Widows-Regel ueberpruefen
     554 [ +  - ][ +  - ]:          6 :     if( !nWidLines && !pFrm->IsFollow() )
                 [ +  - ]
     555                 :            :     {
     556                 :            :         // I.A. brauchen Widows nur ueberprueft werden, wenn wir ein Follow
     557                 :            :         // sind. Bei WouldFit muss aber auch fuer den Master die Regel ueber-
     558                 :            :         // prueft werden, weil wir ja gerade erst die Trennstelle ermitteln.
     559                 :            :         // Im Ctor von WidowsAndOrphans wurde nWidLines aber nur fuer Follows
     560                 :            :         // aus dem AttrSet ermittelt, deshalb holen wir es hier nach:
     561                 :          6 :         const SwAttrSet& rSet = pFrm->GetTxtNode()->GetSwAttrSet();
     562                 :          6 :         nWidLines = rSet.GetWidows().GetValue();
     563                 :            :     }
     564                 :            : 
     565                 :            :     // Sind nach Orphans/Initialen noch genug Zeilen fuer die Widows uebrig?
     566                 :            :     // #111937#: If we are currently doing a test formatting, we may not
     567                 :            :     // consider the widows rule for two reasons:
     568                 :            :     // 1. The columns may have different widths.
     569                 :            :     //    Widow lines would have wrong width.
     570                 :            :     // 2. Test formatting is only done up to the given space.
     571                 :            :     //    we do not have any lines for widows at all.
     572 [ +  + ][ +  - ]:          6 :     if( bTst || nLineCnt - nMinLines >= GetWidowsLines() )
                 [ +  - ]
     573                 :            :     {
     574         [ +  - ]:          6 :         if( rMaxHeight >= nLineSum )
     575                 :            :         {
     576                 :          6 :             rMaxHeight -= nLineSum;
     577                 :          6 :             return sal_True;
     578                 :            :         }
     579                 :            :     }
     580                 :         60 :     return sal_False;
     581                 :            : }
     582                 :            : 
     583                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10