LCOV - code coverage report
Current view: top level - sw/source/core/text - itradj.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 99 398 24.9 %
Date: 2012-08-25 Functions: 5 11 45.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75 489 15.3 %

           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 <com/sun/star/i18n/ScriptType.hpp>
      30                 :            : #include <vcl/outdev.hxx>
      31                 :            : #include <IDocumentSettingAccess.hxx>
      32                 :            : 
      33                 :            : #include "frame.hxx"       // CalcFlyAdjust()
      34                 :            : #include "paratr.hxx"
      35                 :            : #include "itrtxt.hxx"
      36                 :            : #include "porglue.hxx"
      37                 :            : #include "porlay.hxx"
      38                 :            : #include "porfly.hxx"       // CalcFlyAdjust()
      39                 :            : #include "pordrop.hxx"       // CalcFlyAdjust()
      40                 :            : #include "pormulti.hxx"
      41                 :            : #include <portab.hxx>
      42                 :            : 
      43                 :            : #define MIN_TAB_WIDTH 60
      44                 :            : 
      45                 :            : using namespace ::com::sun::star;
      46                 :            : 
      47                 :            : /*************************************************************************
      48                 :            :  * SwTxtAdjuster::FormatBlock()
      49                 :            :  *************************************************************************/
      50                 :            : 
      51                 :          0 : void SwTxtAdjuster::FormatBlock( )
      52                 :            : {
      53                 :            :     // Block format does not apply to the last line.
      54                 :            :     // And for tabs it doesn't exist out of tradition
      55                 :            :     // If we have Flys we continue.
      56                 :            : 
      57                 :          0 :     const SwLinePortion *pFly = 0;
      58                 :            : 
      59                 :          0 :     sal_Bool bSkip = !IsLastBlock() &&
      60 [ #  # ][ #  # ]:          0 :         nStart + pCurr->GetLen() >= GetInfo().GetTxt().Len();
      61                 :            : 
      62                 :            :     // Multi-line fields are tricky, because we need to check whether there are
      63                 :            :     // any other text portions in the paragraph.
      64         [ #  # ]:          0 :     if( bSkip )
      65                 :            :     {
      66                 :          0 :         const SwLineLayout *pLay = pCurr->GetNext();
      67 [ #  # ][ #  # ]:          0 :         while( pLay && !pLay->GetLen() )
                 [ #  # ]
      68                 :            :         {
      69                 :          0 :             const SwLinePortion *pPor = pCurr->GetFirstPortion();
      70 [ #  # ][ #  # ]:          0 :             while( pPor && bSkip )
                 [ #  # ]
      71                 :            :             {
      72         [ #  # ]:          0 :                 if( pPor->InTxtGrp() )
      73                 :          0 :                     bSkip = sal_False;
      74                 :          0 :                 pPor = pPor->GetPortion();
      75                 :            :             }
      76         [ #  # ]:          0 :             pLay = bSkip ? pLay->GetNext() : 0;
      77                 :            :         }
      78                 :            :     }
      79                 :            : 
      80         [ #  # ]:          0 :     if( bSkip )
      81                 :            :     {
      82         [ #  # ]:          0 :         if( !GetInfo().GetParaPortion()->HasFly() )
      83                 :            :         {
      84         [ #  # ]:          0 :             if( IsLastCenter() )
      85                 :          0 :                 CalcFlyAdjust( pCurr );
      86                 :          0 :             pCurr->FinishSpaceAdd();
      87                 :          0 :             return;
      88                 :            :         }
      89                 :            :         else
      90                 :            :         {
      91                 :          0 :             const SwLinePortion *pTmpFly = NULL;
      92                 :            : 
      93                 :            :             // End at the last Fly
      94                 :          0 :             const SwLinePortion *pPos = pCurr->GetFirstPortion();
      95         [ #  # ]:          0 :             while( pPos )
      96                 :            :             {
      97                 :            :                 // Look for the last Fly which has text coming after it:
      98         [ #  # ]:          0 :                 if( pPos->IsFlyPortion() )
      99                 :          0 :                     pTmpFly = pPos; // Found a Fly
     100 [ #  # ][ #  # ]:          0 :                 else if ( pTmpFly && pPos->InTxtGrp() )
                 [ #  # ]
     101                 :            :                 {
     102                 :          0 :                     pFly = pTmpFly; // A Fly with follow-up text!
     103                 :          0 :                     pTmpFly = NULL;
     104                 :            :                 }
     105                 :          0 :                 pPos = pPos->GetPortion();
     106                 :            :             }
     107                 :            :             // End if we didn't find one
     108         [ #  # ]:          0 :             if( !pFly )
     109                 :            :             {
     110         [ #  # ]:          0 :                 if( IsLastCenter() )
     111                 :          0 :                     CalcFlyAdjust( pCurr );
     112                 :          0 :                 pCurr->FinishSpaceAdd();
     113                 :          0 :                 return;
     114                 :            :             }
     115                 :            :         }
     116                 :            :     }
     117                 :            : 
     118                 :          0 :     const xub_StrLen nOldIdx = GetInfo().GetIdx();
     119                 :          0 :     GetInfo().SetIdx( nStart );
     120                 :          0 :     CalcNewBlock( pCurr, pFly );
     121                 :          0 :     GetInfo().SetIdx( nOldIdx );
     122                 :          0 :     GetInfo().GetParaPortion()->GetRepaint()->SetOfst(0);
     123                 :            : }
     124                 :            : 
     125                 :            : /*************************************************************************
     126                 :            :  * lcl_CheckKashidaPositions()
     127                 :            :  *************************************************************************/
     128                 :          0 : bool lcl_CheckKashidaPositions( SwScriptInfo& rSI, SwTxtSizeInfo& rInf, SwTxtIter& rItr,
     129                 :            :                                 xub_StrLen& nKashidas, xub_StrLen& nGluePortion )
     130                 :            : {
     131                 :            :     // i60594 validate Kashida justification
     132                 :          0 :     xub_StrLen nIdx = rItr.GetStart();
     133                 :          0 :     xub_StrLen nEnd = rItr.GetEnd();
     134                 :            : 
     135                 :            :     // Note on calling KashidaJustify():
     136                 :            :     // Kashida positions may be marked as invalid. Therefore KashidaJustify may return the clean
     137                 :            :     // total number of kashida positions, or the number of kashida positions after some positions
     138                 :            :     // have been dropped.
     139                 :            :     // Here we want the clean total, which is OK: We have called ClearKashidaInvalid() before.
     140                 :          0 :     nKashidas = rSI.KashidaJustify ( 0, 0, rItr.GetStart(), rItr.GetLength(), 0 );
     141                 :            : 
     142         [ #  # ]:          0 :     if (!nKashidas) // nothing to do
     143                 :          0 :         return true;
     144                 :            : 
     145                 :            :     // kashida positions found in SwScriptInfo are not necessarily valid in every font
     146                 :            :     // if two characters are replaced by a ligature glyph, there will be no place for a kashida
     147                 :          0 :     xub_StrLen* pKashidaPos = new xub_StrLen [ nKashidas ];
     148                 :          0 :     xub_StrLen* pKashidaPosDropped = new xub_StrLen [ nKashidas ];
     149                 :          0 :     rSI.GetKashidaPositions ( nIdx, rItr.GetLength(), pKashidaPos );
     150                 :          0 :     xub_StrLen nKashidaIdx = 0;
     151 [ #  # ][ #  # ]:          0 :     while ( nKashidas && nIdx < nEnd )
                 [ #  # ]
     152                 :            :     {
     153                 :          0 :         rItr.SeekAndChgAttrIter( nIdx, rInf.GetOut() );
     154                 :          0 :         xub_StrLen nNext = rItr.GetNextAttr();
     155                 :            : 
     156                 :            :         // is there also a script change before?
     157                 :            :         // if there is, nNext should point to the script change
     158                 :          0 :         xub_StrLen nNextScript = rSI.NextScriptChg( nIdx );
     159         [ #  # ]:          0 :         if( nNextScript < nNext )
     160                 :          0 :             nNext = nNextScript;
     161                 :            : 
     162 [ #  # ][ #  # ]:          0 :         if ( nNext == STRING_LEN || nNext > nEnd )
     163                 :          0 :             nNext = nEnd;
     164                 :          0 :         xub_StrLen nKashidasInAttr = rSI.KashidaJustify ( 0, 0, nIdx, nNext - nIdx );
     165         [ #  # ]:          0 :         if ( nKashidasInAttr )
     166                 :            :         {
     167                 :            :             // Kashida glyph looks suspicious, skip Kashida justification
     168         [ #  # ]:          0 :             if ( rInf.GetOut()->GetMinKashida() <= 0 )
     169                 :          0 :                 return false;
     170                 :            : 
     171                 :          0 :             xub_StrLen nKashidasDropped = 0;
     172 [ #  # ][ #  # ]:          0 :             if ( !SwScriptInfo::IsArabicText( rInf.GetTxt(), nIdx, nNext - nIdx ) )
     173                 :            :             {
     174                 :          0 :                 nKashidasDropped = nKashidasInAttr;
     175                 :          0 :                 nKashidas -= nKashidasDropped;
     176                 :            :             }
     177                 :            :             else
     178                 :            :             {
     179                 :          0 :                 sal_uLong nOldLayout = rInf.GetOut()->GetLayoutMode();
     180                 :          0 :                 rInf.GetOut()->SetLayoutMode ( nOldLayout | TEXT_LAYOUT_BIDI_RTL );
     181                 :          0 :                 nKashidasDropped = rInf.GetOut()->ValidateKashidas ( rInf.GetTxt(), nIdx, nNext - nIdx,
     182                 :            :                                                nKashidasInAttr, pKashidaPos + nKashidaIdx,
     183                 :          0 :                                                pKashidaPosDropped );
     184                 :          0 :                 rInf.GetOut()->SetLayoutMode ( nOldLayout );
     185         [ #  # ]:          0 :                 if ( nKashidasDropped )
     186                 :            :                 {
     187                 :          0 :                     rSI.MarkKashidasInvalid ( nKashidasDropped, pKashidaPosDropped );
     188                 :          0 :                     nKashidas -= nKashidasDropped;
     189                 :          0 :                     nGluePortion -= nKashidasDropped;
     190                 :            :                 }
     191                 :            :             }
     192                 :          0 :             nKashidaIdx += nKashidasInAttr;
     193                 :            :         }
     194                 :          0 :         nIdx = nNext;
     195                 :            :     }
     196         [ #  # ]:          0 :     delete[] pKashidaPos;
     197         [ #  # ]:          0 :     delete[] pKashidaPosDropped;
     198                 :            : 
     199                 :            :     // return false if all kashidas have been eliminated
     200                 :          0 :     return (nKashidas > 0);
     201                 :            : }
     202                 :            : 
     203                 :            : /*************************************************************************
     204                 :            :  * lcl_CheckKashidaWidth()
     205                 :            :  *************************************************************************/
     206                 :          0 : bool lcl_CheckKashidaWidth ( SwScriptInfo& rSI, SwTxtSizeInfo& rInf, SwTxtIter& rItr, xub_StrLen& nKashidas,
     207                 :            :                              xub_StrLen& nGluePortion, const long nGluePortionWidth, long& nSpaceAdd )
     208                 :            : {
     209                 :            :     // check kashida width
     210                 :            :     // if width is smaller than minimal kashida width allowed by fonts in the current line
     211                 :            :     // drop one kashida after the other until kashida width is OK
     212                 :            :     bool bAddSpaceChanged;
     213         [ #  # ]:          0 :     while ( nKashidas )
     214                 :            :     {
     215                 :          0 :         bAddSpaceChanged = false;
     216                 :          0 :         xub_StrLen nIdx = rItr.GetStart();
     217                 :          0 :         xub_StrLen nEnd = rItr.GetEnd();
     218         [ #  # ]:          0 :         while ( nIdx < nEnd )
     219                 :            :         {
     220                 :          0 :             rItr.SeekAndChgAttrIter( nIdx, rInf.GetOut() );
     221                 :          0 :             xub_StrLen nNext = rItr.GetNextAttr();
     222                 :            : 
     223                 :            :             // is there also a script change before?
     224                 :            :             // if there is, nNext should point to the script change
     225                 :          0 :             xub_StrLen nNextScript = rSI.NextScriptChg( nIdx );
     226         [ #  # ]:          0 :             if( nNextScript < nNext )
     227                 :          0 :                nNext = nNextScript;
     228                 :            : 
     229 [ #  # ][ #  # ]:          0 :             if ( nNext == STRING_LEN || nNext > nEnd )
     230                 :          0 :                 nNext = nEnd;
     231                 :          0 :             xub_StrLen nKashidasInAttr = rSI.KashidaJustify ( 0, 0, nIdx, nNext - nIdx );
     232                 :            : 
     233                 :          0 :             long nFontMinKashida = rInf.GetOut()->GetMinKashida();
     234 [ #  # ][ #  # ]:          0 :             if ( nFontMinKashida && nKashidasInAttr && SwScriptInfo::IsArabicText( rInf.GetTxt(), nIdx, nNext - nIdx ) )
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
                 [ #  # ]
     235                 :            :             {
     236                 :          0 :                 xub_StrLen nKashidasDropped = 0;
     237 [ #  # ][ #  # ]:          0 :                 while ( nKashidas && nGluePortion && nKashidasInAttr &&
         [ #  # ][ #  # ]
                 [ #  # ]
     238                 :            :                         nSpaceAdd / SPACING_PRECISION_FACTOR < nFontMinKashida )
     239                 :            :                 {
     240                 :          0 :                     --nGluePortion;
     241                 :          0 :                     --nKashidas;
     242                 :          0 :                     --nKashidasInAttr;
     243                 :          0 :                     ++nKashidasDropped;
     244 [ #  # ][ #  # ]:          0 :                     if( !nKashidas || !nGluePortion ) // nothing left, return false to
     245                 :          0 :                         return false;                 // do regular blank justification
     246                 :            : 
     247                 :          0 :                     nSpaceAdd = nGluePortionWidth / nGluePortion;
     248                 :          0 :                     bAddSpaceChanged = true;
     249                 :            :                }
     250         [ #  # ]:          0 :                if( nKashidasDropped )
     251                 :          0 :                    rSI.MarkKashidasInvalid( nKashidasDropped, nIdx, nNext - nIdx );
     252                 :            :             }
     253         [ #  # ]:          0 :             if ( bAddSpaceChanged )
     254                 :          0 :                 break; // start all over again
     255                 :          0 :             nIdx = nNext;
     256                 :            :         }
     257         [ #  # ]:          0 :         if ( !bAddSpaceChanged )
     258                 :          0 :             break; // everything was OK
     259                 :            :     }
     260                 :          0 :    return true;
     261                 :            : }
     262                 :            : 
     263                 :            : /*************************************************************************
     264                 :            :  * SwTxtAdjuster::CalcNewBlock()
     265                 :            :  *
     266                 :            :  * CalcNewBlock() must only be called _after_ CalcLine()!
     267                 :            :  * We always span between two RandPortions or FixPortions (Tabs and Flys).
     268                 :            :  * We count the Glues and call ExpandBlock.
     269                 :            :  *************************************************************************/
     270                 :            : 
     271                 :         20 : void SwTxtAdjuster::CalcNewBlock( SwLineLayout *pCurrent,
     272                 :            :                                   const SwLinePortion *pStopAt, SwTwips nReal, bool bSkipKashida )
     273                 :            : {
     274                 :            :     OSL_ENSURE( GetInfo().IsMulti() || SVX_ADJUST_BLOCK == GetAdjust(),
     275                 :            :             "CalcNewBlock: Why?" );
     276                 :            :     OSL_ENSURE( pCurrent->Height(), "SwTxtAdjuster::CalcBlockAdjust: missing CalcLine()" );
     277                 :            : 
     278         [ +  - ]:         20 :     pCurrent->InitSpaceAdd();
     279                 :         20 :     xub_StrLen nGluePortion = 0;
     280                 :         20 :     xub_StrLen nCharCnt = 0;
     281                 :         20 :     MSHORT nSpaceIdx = 0;
     282                 :            : 
     283                 :            :     // i60591: hennerdrews
     284                 :         20 :     SwScriptInfo& rSI = GetInfo().GetParaPortion()->GetScriptInfo();
     285         [ +  - ]:         20 :     SwTxtSizeInfo aInf ( GetTxtFrm() );
     286         [ +  - ]:         20 :     SwTxtIter aItr ( GetTxtFrm(), &aInf );
     287                 :            : 
     288         [ -  + ]:         20 :     if ( rSI.CountKashida() )
     289                 :            :     {
     290 [ #  # ][ #  # ]:          0 :         while (aItr.GetCurr() != pCurrent && aItr.GetNext())
                 [ #  # ]
     291         [ #  # ]:          0 :            aItr.Next();
     292                 :            : 
     293         [ #  # ]:          0 :         if( bSkipKashida )
     294                 :            :         {
     295         [ #  # ]:          0 :             rSI.SetNoKashidaLine ( aItr.GetStart(), aItr.GetLength());
     296                 :            :         }
     297                 :            :         else
     298                 :            :         {
     299         [ #  # ]:          0 :             rSI.ClearKashidaInvalid ( aItr.GetStart(), aItr.GetLength() );
     300         [ #  # ]:          0 :             rSI.ClearNoKashidaLine( aItr.GetStart(), aItr.GetLength() );
     301                 :            :         }
     302                 :            :     }
     303                 :            : 
     304                 :            :     // Do not forget: CalcRightMargin() sets pCurrent->Width() to the line width!
     305         [ +  - ]:         20 :     if (!bSkipKashida)
     306         [ +  - ]:         20 :         CalcRightMargin( pCurrent, nReal );
     307                 :            : 
     308                 :            :     // #i49277#
     309                 :            :     const sal_Bool bDoNotJustifyLinesWithManualBreak =
     310 [ +  - ][ +  - ]:         20 :                 GetTxtFrm()->GetNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK);
     311                 :            : 
     312                 :         20 :     SwLinePortion *pPos = pCurrent->GetPortion();
     313                 :            : 
     314         [ +  + ]:         60 :     while( pPos )
     315                 :            :     {
     316   [ -  +  #  #  :         40 :         if ( bDoNotJustifyLinesWithManualBreak &&
           #  # ][ -  + ]
     317                 :          0 :              pPos->IsBreakPortion() && !IsLastBlock() )
     318                 :            :         {
     319                 :          0 :            pCurrent->FinishSpaceAdd();
     320                 :          0 :            break;
     321                 :            :         }
     322                 :            : 
     323         [ +  + ]:         40 :         if ( pPos->InTxtGrp() )
     324         [ +  - ]:         20 :             nGluePortion = nGluePortion + ((SwTxtPortion*)pPos)->GetSpaceCnt( GetInfo(), nCharCnt );
     325         [ -  + ]:         20 :         else if( pPos->IsMultiPortion() )
     326                 :            :         {
     327                 :          0 :             SwMultiPortion* pMulti = (SwMultiPortion*)pPos;
     328                 :            :             // a multiportion with a tabulator inside breaks the text adjustment
     329                 :            :             // a ruby portion will not be stretched by text adjustment
     330                 :            :             // a double line portion takes additional space for each blank
     331                 :            :             // in the wider line
     332         [ #  # ]:          0 :             if( pMulti->HasTabulator() )
     333                 :            :             {
     334 [ #  # ][ #  # ]:          0 :                 if ( nSpaceIdx == pCurrent->GetLLSpaceAddCount() )
     335         [ #  # ]:          0 :                     pCurrent->SetLLSpaceAdd( 0, nSpaceIdx );
     336                 :            : 
     337                 :          0 :                 nSpaceIdx++;
     338                 :          0 :                 nGluePortion = 0;
     339                 :          0 :                 nCharCnt = 0;
     340                 :            :             }
     341         [ #  # ]:          0 :             else if( pMulti->IsDouble() )
     342                 :          0 :                 nGluePortion = nGluePortion + ((SwDoubleLinePortion*)pMulti)->GetSpaceCnt();
     343         [ #  # ]:          0 :             else if ( pMulti->IsBidi() )
     344         [ #  # ]:          0 :                 nGluePortion = nGluePortion + ((SwBidiPortion*)pMulti)->GetSpaceCnt( GetInfo() );  // i60594
     345                 :            :         }
     346                 :            : 
     347         [ +  + ]:         40 :         if( pPos->InGlueGrp() )
     348                 :            :         {
     349         [ +  - ]:         20 :             if( pPos->InFixMargGrp() )
     350                 :            :             {
     351 [ +  - ][ -  + ]:         20 :                 if ( nSpaceIdx == pCurrent->GetLLSpaceAddCount() )
     352         [ #  # ]:          0 :                     pCurrent->SetLLSpaceAdd( 0, nSpaceIdx );
     353                 :            : 
     354                 :         20 :                 const long nGluePortionWidth = static_cast<SwGluePortion*>(pPos)->GetPrtGlue() *
     355                 :         20 :                                                SPACING_PRECISION_FACTOR;
     356                 :            : 
     357                 :         20 :                 xub_StrLen nKashidas = 0;
     358 [ #  # ][ #  # ]:         20 :                 if( nGluePortion && rSI.CountKashida() && !bSkipKashida )
         [ -  + ][ -  + ]
     359                 :            :                 {
     360                 :            :                     // kashida positions found in SwScriptInfo are not necessarily valid in every font
     361                 :            :                     // if two characters are replaced by a ligature glyph, there will be no place for a kashida
     362 [ #  # ][ #  # ]:          0 :                     if ( !lcl_CheckKashidaPositions ( rSI, aInf, aItr, nKashidas, nGluePortion ))
     363                 :            :                     {
     364                 :            :                         // all kashida positions are invalid
     365                 :            :                         // do regular blank justification
     366                 :          0 :                         pCurrent->FinishSpaceAdd();
     367                 :          0 :                         GetInfo().SetIdx( nStart );
     368         [ #  # ]:          0 :                         CalcNewBlock( pCurrent, pStopAt, nReal, true );
     369                 :            :                         return;
     370                 :            :                     }
     371                 :            :                 }
     372                 :            : 
     373         [ -  + ]:         20 :                 if( nGluePortion )
     374                 :            :                 {
     375                 :          0 :                     long nSpaceAdd = nGluePortionWidth / nGluePortion;
     376                 :            : 
     377                 :            :                     // i60594
     378 [ #  # ][ #  # ]:          0 :                     if( rSI.CountKashida() && !bSkipKashida )
                 [ #  # ]
     379                 :            :                     {
     380 [ #  # ][ #  # ]:          0 :                         if( !lcl_CheckKashidaWidth( rSI, aInf, aItr, nKashidas, nGluePortion, nGluePortionWidth, nSpaceAdd ))
     381                 :            :                         {
     382                 :            :                             // no kashidas left
     383                 :            :                             // do regular blank justification
     384                 :          0 :                             pCurrent->FinishSpaceAdd();
     385                 :          0 :                             GetInfo().SetIdx( nStart );
     386         [ #  # ]:          0 :                             CalcNewBlock( pCurrent, pStopAt, nReal, true );
     387                 :            :                             return;
     388                 :            :                         }
     389                 :            :                     }
     390                 :            : 
     391         [ #  # ]:          0 :                     pCurrent->SetLLSpaceAdd( nSpaceAdd , nSpaceIdx );
     392                 :          0 :                     pPos->Width( ( (SwGluePortion*)pPos )->GetFixWidth() );
     393                 :            :                 }
     394 [ -  + ][ #  # ]:         20 :                 else if ( IsOneBlock() && nCharCnt > 1 )
                 [ -  + ]
     395                 :            :                 {
     396                 :          0 :                     const long nSpaceAdd = - nGluePortionWidth / ( nCharCnt - 1 );
     397         [ #  # ]:          0 :                     pCurrent->SetLLSpaceAdd( nSpaceAdd, nSpaceIdx );
     398                 :          0 :                     pPos->Width( ( (SwGluePortion*)pPos )->GetFixWidth() );
     399                 :            :                 }
     400                 :            : 
     401                 :         20 :                 nSpaceIdx++;
     402                 :         20 :                 nGluePortion = 0;
     403                 :         20 :                 nCharCnt = 0;
     404                 :            :             }
     405                 :            :             else
     406                 :          0 :                 ++nGluePortion;
     407                 :            :         }
     408                 :         40 :         GetInfo().SetIdx( GetInfo().GetIdx() + pPos->GetLen() );
     409         [ -  + ]:         40 :         if ( pPos == pStopAt )
     410                 :            :         {
     411         [ #  # ]:          0 :             pCurrent->SetLLSpaceAdd( 0, nSpaceIdx );
     412                 :          0 :             break;
     413                 :            :         }
     414                 :         40 :         pPos = pPos->GetPortion();
     415 [ +  - ][ -  + ]:         20 :     }
                 [ +  - ]
     416                 :            : }
     417                 :            : 
     418                 :            : /*************************************************************************
     419                 :            :  * SwTxtAdjuster::CalcKanaAdj()
     420                 :            :  *************************************************************************/
     421                 :            : 
     422                 :          0 : SwTwips SwTxtAdjuster::CalcKanaAdj( SwLineLayout* pCurrent )
     423                 :            : {
     424                 :            :     OSL_ENSURE( pCurrent->Height(), "SwTxtAdjuster::CalcBlockAdjust: missing CalcLine()" );
     425                 :            :     OSL_ENSURE( !pCurrent->GetpKanaComp(), "pKanaComp already exists!!" );
     426                 :            : 
     427 [ #  # ][ #  # ]:          0 :     std::deque<sal_uInt16> *pNewKana = new std::deque<sal_uInt16>();
     428                 :          0 :     pCurrent->SetKanaComp( pNewKana );
     429                 :            : 
     430                 :          0 :     const sal_uInt16 nNull = 0;
     431                 :          0 :     MSHORT nKanaIdx = 0;
     432                 :          0 :     long nKanaDiffSum = 0;
     433                 :          0 :     SwTwips nRepaintOfst = 0;
     434                 :          0 :     SwTwips nX = 0;
     435                 :          0 :     sal_Bool bNoCompression = sal_False;
     436                 :            : 
     437                 :            :     // Do not forget: CalcRightMargin() sets pCurrent->Width() to the line width!
     438         [ #  # ]:          0 :     CalcRightMargin( pCurrent, 0 );
     439                 :            : 
     440                 :          0 :     SwLinePortion* pPos = pCurrent->GetPortion();
     441                 :            : 
     442         [ #  # ]:          0 :     while( pPos )
     443                 :            :     {
     444         [ #  # ]:          0 :         if ( pPos->InTxtGrp() )
     445                 :            :         {
     446                 :            :             // get maximum portion width from info structure, calculated
     447                 :            :             // during text formatting
     448         [ #  # ]:          0 :             sal_uInt16 nMaxWidthDiff = GetInfo().GetMaxWidthDiff( (sal_uLong)pPos );
     449                 :            : 
     450                 :            :             // check, if information is stored under other key
     451 [ #  # ][ #  # ]:          0 :             if ( !nMaxWidthDiff && pPos == pCurrent->GetFirstPortion() )
                 [ #  # ]
     452         [ #  # ]:          0 :                 nMaxWidthDiff = GetInfo().GetMaxWidthDiff( (sal_uLong)pCurrent );
     453                 :            : 
     454                 :            :             // calculate difference between portion width and max. width
     455                 :          0 :             nKanaDiffSum += nMaxWidthDiff;
     456                 :            : 
     457                 :            :             // we store the beginning of the first compressable portion
     458                 :            :             // for repaint
     459 [ #  # ][ #  # ]:          0 :             if ( nMaxWidthDiff && !nRepaintOfst )
     460         [ #  # ]:          0 :                 nRepaintOfst = nX + GetLeftMargin();
     461                 :            :         }
     462 [ #  # ][ #  # ]:          0 :         else if( pPos->InGlueGrp() && pPos->InFixMargGrp() )
                 [ #  # ]
     463                 :            :         {
     464         [ #  # ]:          0 :             if ( nKanaIdx == pCurrent->GetKanaComp().size() )
     465         [ #  # ]:          0 :                 pCurrent->GetKanaComp().push_back( nNull );
     466                 :            : 
     467                 :            :             sal_uInt16 nRest;
     468                 :            : 
     469         [ #  # ]:          0 :             if ( pPos->InTabGrp() )
     470                 :            :             {
     471                 :            :                 nRest = ! bNoCompression &&
     472                 :          0 :                         ( pPos->Width() > MIN_TAB_WIDTH ) ?
     473                 :          0 :                         pPos->Width() - MIN_TAB_WIDTH :
     474   [ #  #  #  # ]:          0 :                         0;
     475                 :            : 
     476                 :            :                 // for simplifying the handling of left, right ... tabs,
     477                 :            :                 // we do expand portions, which are lying behind
     478                 :            :                 // those special tabs
     479                 :          0 :                 bNoCompression = !pPos->IsTabLeftPortion();
     480                 :            :             }
     481                 :            :             else
     482                 :            :             {
     483                 :            :                 nRest = ! bNoCompression ?
     484                 :          0 :                         ((SwGluePortion*)pPos)->GetPrtGlue() :
     485         [ #  # ]:          0 :                         0;
     486                 :            : 
     487                 :          0 :                 bNoCompression = sal_False;
     488                 :            :             }
     489                 :            : 
     490         [ #  # ]:          0 :             if( nKanaDiffSum )
     491                 :            :             {
     492                 :          0 :                 sal_uLong nCompress = ( 10000 * nRest ) / nKanaDiffSum;
     493                 :            : 
     494         [ #  # ]:          0 :                 if ( nCompress >= 10000 )
     495                 :            :                     // kanas can be expanded to 100%, and there is still
     496                 :            :                     // some space remaining
     497                 :          0 :                     nCompress = 0;
     498                 :            : 
     499                 :            :                 else
     500                 :          0 :                     nCompress = 10000 - nCompress;
     501                 :            : 
     502         [ #  # ]:          0 :                 ( pCurrent->GetKanaComp() )[ nKanaIdx ] = (sal_uInt16)nCompress;
     503                 :          0 :                 nKanaDiffSum = 0;
     504                 :            :             }
     505                 :            : 
     506                 :          0 :             nKanaIdx++;
     507                 :            :         }
     508                 :            : 
     509                 :          0 :         nX += pPos->Width();
     510                 :          0 :         pPos = pPos->GetPortion();
     511                 :            :     }
     512                 :            : 
     513                 :            :     // set portion width
     514                 :          0 :     nKanaIdx = 0;
     515         [ #  # ]:          0 :     sal_uInt16 nCompress = ( pCurrent->GetKanaComp() )[ nKanaIdx ];
     516                 :          0 :     pPos = pCurrent->GetPortion();
     517                 :          0 :     long nDecompress = 0;
     518                 :          0 :     nKanaDiffSum = 0;
     519                 :            : 
     520         [ #  # ]:          0 :     while( pPos )
     521                 :            :     {
     522         [ #  # ]:          0 :         if ( pPos->InTxtGrp() )
     523                 :            :         {
     524                 :          0 :             const sal_uInt16 nMinWidth = pPos->Width();
     525                 :            : 
     526                 :            :             // get maximum portion width from info structure, calculated
     527                 :            :             // during text formatting
     528         [ #  # ]:          0 :             sal_uInt16 nMaxWidthDiff = GetInfo().GetMaxWidthDiff( (sal_uLong)pPos );
     529                 :            : 
     530                 :            :             // check, if information is stored under other key
     531 [ #  # ][ #  # ]:          0 :             if ( !nMaxWidthDiff && pPos == pCurrent->GetFirstPortion() )
                 [ #  # ]
     532         [ #  # ]:          0 :                 nMaxWidthDiff = GetInfo().GetMaxWidthDiff( (sal_uLong)pCurrent );
     533                 :          0 :             nKanaDiffSum += nMaxWidthDiff;
     534                 :            :             pPos->Width( nMinWidth +
     535                 :          0 :                        ( ( 10000 - nCompress ) * nMaxWidthDiff ) / 10000 );
     536                 :          0 :             nDecompress += pPos->Width() - nMinWidth;
     537                 :            :         }
     538 [ #  # ][ #  # ]:          0 :         else if( pPos->InGlueGrp() && pPos->InFixMargGrp() )
                 [ #  # ]
     539                 :            :         {
     540         [ #  # ]:          0 :             if( nCompress )
     541                 :            :             {
     542                 :          0 :                 nKanaDiffSum *= nCompress;
     543                 :          0 :                 nKanaDiffSum /= 10000;
     544                 :            :             }
     545                 :            : 
     546                 :          0 :             pPos->Width( static_cast<sal_uInt16>(pPos->Width() - nDecompress) );
     547                 :            : 
     548         [ #  # ]:          0 :             if ( pPos->InTabGrp() )
     549                 :            :                 // set fix width to width
     550                 :          0 :                 ((SwTabPortion*)pPos)->SetFixWidth( pPos->Width() );
     551                 :            : 
     552         [ #  # ]:          0 :             if ( ++nKanaIdx < pCurrent->GetKanaComp().size() )
     553         [ #  # ]:          0 :                 nCompress = ( pCurrent->GetKanaComp() )[ nKanaIdx ];
     554                 :            : 
     555                 :          0 :             nKanaDiffSum = 0;
     556                 :          0 :             nDecompress = 0;
     557                 :            :         }
     558                 :          0 :         pPos = pPos->GetPortion();
     559                 :            :     }
     560                 :            : 
     561                 :          0 :     return nRepaintOfst;
     562                 :            : }
     563                 :            : 
     564                 :            : /*************************************************************************
     565                 :            :  * SwTxtAdjuster::CalcRightMargin()
     566                 :            :  *************************************************************************/
     567                 :            : 
     568                 :        905 : SwMarginPortion *SwTxtAdjuster::CalcRightMargin( SwLineLayout *pCurrent,
     569                 :            :     SwTwips nReal )
     570                 :            : {
     571                 :            :     long nRealWidth;
     572                 :        905 :     const sal_uInt16 nRealHeight = GetLineHeight();
     573                 :        905 :     const sal_uInt16 nLineHeight = pCurrent->Height();
     574                 :            : 
     575                 :        905 :     KSHORT nPrtWidth = pCurrent->PrtWidth();
     576                 :        905 :     SwLinePortion *pLast = pCurrent->FindLastPortion();
     577                 :            : 
     578         [ +  + ]:        905 :     if( GetInfo().IsMulti() )
     579                 :         20 :         nRealWidth = nReal;
     580                 :            :     else
     581                 :            :     {
     582         [ +  - ]:        885 :         nRealWidth = GetLineWidth();
     583                 :            :         // For each FlyFrm extending into the right margin, we create a FlyPortion.
     584         [ +  - ]:        885 :         const long nLeftMar = GetLeftMargin();
     585                 :        885 :         SwRect aCurrRect( nLeftMar + nPrtWidth, Y() + nRealHeight - nLineHeight,
     586                 :        885 :                           nRealWidth - nPrtWidth, nLineHeight );
     587                 :            : 
     588         [ +  - ]:        885 :         SwFlyPortion *pFly = CalcFlyPortion( nRealWidth, aCurrRect );
     589 [ -  + ][ #  # ]:        885 :         while( pFly && long( nPrtWidth )< nRealWidth )
                 [ -  + ]
     590                 :            :         {
     591         [ #  # ]:          0 :             pLast->Append( pFly );
     592                 :          0 :             pLast = pFly;
     593         [ #  # ]:          0 :             if( pFly->Fix() > nPrtWidth )
     594                 :          0 :                 pFly->Width( ( pFly->Fix() - nPrtWidth) + pFly->Width() + 1);
     595                 :          0 :             nPrtWidth += pFly->Width() + 1;
     596                 :          0 :             aCurrRect.Left( nLeftMar + nPrtWidth );
     597         [ #  # ]:          0 :             pFly = CalcFlyPortion( nRealWidth, aCurrRect );
     598                 :            :         }
     599 [ -  + ][ #  # ]:        885 :         delete pFly;
     600                 :            :     }
     601                 :            : 
     602         [ +  - ]:        905 :     SwMarginPortion *pRight = new SwMarginPortion( 0 );
     603                 :        905 :     pLast->Append( pRight );
     604                 :            : 
     605         [ +  - ]:        905 :     if( long( nPrtWidth )< nRealWidth )
     606                 :        905 :         pRight->PrtWidth( KSHORT( nRealWidth - nPrtWidth ) );
     607                 :            : 
     608                 :            :     // pCurrent->Width() is set to the real size, because we attach the
     609                 :            :     // MarginPortions.
     610                 :            :     // This trick gives miraculous results:
     611                 :            :     // If pCurrent->Width() == nRealWidth, then the adjustment gets overruled
     612                 :            :     // implicitly. GetLeftMarginAdjust() and IsJustified() think they have a
     613                 :            :     // line filled with chars.
     614                 :            : 
     615                 :        905 :     pCurrent->PrtWidth( KSHORT( nRealWidth ) );
     616                 :        905 :     return pRight;
     617                 :            : }
     618                 :            : 
     619                 :            : /*************************************************************************
     620                 :            :  * SwTxtAdjuster::CalcFlyAdjust()
     621                 :            :  *************************************************************************/
     622                 :            : 
     623                 :        885 : void SwTxtAdjuster::CalcFlyAdjust( SwLineLayout *pCurrent )
     624                 :            : {
     625                 :            :     // 1) We insert a left margin:
     626                 :        885 :     SwMarginPortion *pLeft = pCurrent->CalcLeftMargin();
     627                 :        885 :     SwGluePortion *pGlue = pLeft; // the last GluePortion
     628                 :            : 
     629                 :            : 
     630                 :            :     // 2) We attach a right margin:
     631                 :            :     // CalcRightMargin also calculates a possible overlap with FlyFrms.
     632                 :        885 :     CalcRightMargin( pCurrent );
     633                 :            : 
     634                 :        885 :     SwLinePortion *pPos = pLeft->GetPortion();
     635                 :        885 :     xub_StrLen nLen = 0;
     636                 :            : 
     637                 :            :     // If we only have one line, the text portion is consecutive and we center, then ...
     638                 :        885 :     sal_Bool bComplete = 0 == nStart;
     639                 :        885 :     const sal_Bool bTabCompat = GetTxtFrm()->GetNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
     640                 :        885 :     sal_Bool bMultiTab = sal_False;
     641                 :            : 
     642         [ +  + ]:       2652 :     while( pPos )
     643                 :            :     {
     644 [ -  + ][ #  # ]:       1767 :         if ( pPos->IsMultiPortion() && ((SwMultiPortion*)pPos)->HasTabulator() )
                 [ -  + ]
     645                 :          0 :             bMultiTab = sal_True;
     646         [ +  + ]:       2652 :         else if( pPos->InFixMargGrp() &&
           [ +  -  +  - ]
         [ #  # ][ +  + ]
     647                 :        885 :                ( bTabCompat ? ! pPos->InTabGrp() : ! bMultiTab ) )
     648                 :            :         {
     649                 :            :             // in tab compat mode we do not want to change tab portions
     650                 :            :             // in non tab compat mode we do not want to change margins if we
     651                 :            :             // found a multi portion with tabs
     652         [ +  + ]:        885 :             if( SVX_ADJUST_RIGHT == GetAdjust() )
     653                 :          3 :                 ((SwGluePortion*)pPos)->MoveAllGlue( pGlue );
     654                 :            :             else
     655                 :            :             {
     656                 :            :                 // We set the first text portion to right-aligned and the last one
     657                 :            :                 // to left-aligned.
     658                 :            :                 // The first text portion gets the whole Glue, but only if we have
     659                 :            :                 // more than one line.
     660 [ +  + ][ +  + ]:        882 :                 if( bComplete && GetInfo().GetTxt().Len() == nLen )
                 [ +  + ]
     661                 :        858 :                     ((SwGluePortion*)pPos)->MoveHalfGlue( pGlue );
     662                 :            :                 else
     663                 :            :                 {
     664         [ -  + ]:         24 :                     if ( ! bTabCompat )
     665                 :            :                     {
     666         [ #  # ]:          0 :                         if( pLeft == pGlue )
     667                 :            :                         {
     668                 :            :                             // If we only have a left and right margin, the
     669                 :            :                             // margins share the Glue.
     670         [ #  # ]:          0 :                             if( nLen + pPos->GetLen() >= pCurrent->GetLen() )
     671                 :          0 :                                 ((SwGluePortion*)pPos)->MoveHalfGlue( pGlue );
     672                 :            :                             else
     673                 :          0 :                                 ((SwGluePortion*)pPos)->MoveAllGlue( pGlue );
     674                 :            :                         }
     675                 :            :                         else
     676                 :            :                         {
     677                 :            :                          // The last text portion retains its Glue.
     678         [ #  # ]:          0 :                          if( !pPos->IsMarginPortion() )
     679                 :          0 :                               ((SwGluePortion*)pPos)->MoveHalfGlue( pGlue );
     680                 :            :                          }
     681                 :            :                      }
     682                 :            :                      else
     683                 :         24 :                         ((SwGluePortion*)pPos)->MoveHalfGlue( pGlue );
     684                 :            :                 }
     685                 :            :             }
     686                 :            : 
     687                 :        885 :             pGlue = (SwFlyPortion*)pPos;
     688                 :        885 :             bComplete = sal_False;
     689                 :            :         }
     690                 :       1767 :         nLen = nLen + pPos->GetLen();
     691                 :       1767 :         pPos = pPos->GetPortion();
     692                 :            :      }
     693                 :            : 
     694 [ -  + ][ #  # ]:        885 :      if( ! bTabCompat && ! bMultiTab && SVX_ADJUST_RIGHT == GetAdjust() )
         [ #  # ][ -  + ]
     695                 :            :         // portions are moved to the right if possible
     696                 :          0 :         pLeft->AdjustRight( pCurrent );
     697                 :        885 : }
     698                 :            : 
     699                 :            : /*************************************************************************
     700                 :            :  * SwTxtAdjuster::CalcAdjLine()
     701                 :            :  *************************************************************************/
     702                 :            : 
     703                 :        885 : void SwTxtAdjuster::CalcAdjLine( SwLineLayout *pCurrent )
     704                 :            : {
     705                 :            :     OSL_ENSURE( pCurrent->IsFormatAdj(), "CalcAdjLine: Why?" );
     706                 :            : 
     707                 :        885 :     pCurrent->SetFormatAdj(sal_False);
     708                 :            : 
     709                 :        885 :     SwParaPortion* pPara = GetInfo().GetParaPortion();
     710                 :            : 
     711      [ +  -  - ]:        885 :     switch( GetAdjust() )
     712                 :            :     {
     713                 :            :         case SVX_ADJUST_RIGHT:
     714                 :            :         case SVX_ADJUST_CENTER:
     715                 :            :         {
     716                 :        885 :             CalcFlyAdjust( pCurrent );
     717                 :        885 :             pPara->GetRepaint()->SetOfst( 0 );
     718                 :        885 :             break;
     719                 :            :         }
     720                 :            :         case SVX_ADJUST_BLOCK:
     721                 :            :         {
     722                 :          0 :             FormatBlock();
     723                 :          0 :             break;
     724                 :            :         }
     725                 :        885 :         default : return;
     726                 :            :     }
     727                 :            : }
     728                 :            : 
     729                 :            : /*************************************************************************
     730                 :            :  * SwTxtAdjuster::CalcFlyPortion()
     731                 :            :  *
     732                 :            :  * This is a quite complicated calculation: nCurrWidth is the width _before_
     733                 :            :  * adding the word, that still fits onto the line! For this reason the FlyPortion's
     734                 :            :  * width is still correct if we get a deadlock-situation of:
     735                 :            :  * bFirstWord && !WORDFITS
     736                 :            :  *************************************************************************/
     737                 :            : 
     738                 :        885 : SwFlyPortion *SwTxtAdjuster::CalcFlyPortion( const long nRealWidth,
     739                 :            :                                              const SwRect &rCurrRect )
     740                 :            : {
     741         [ +  - ]:        885 :     SwTxtFly aTxtFly( GetTxtFrm() );
     742                 :            : 
     743                 :        885 :     const KSHORT nCurrWidth = pCurr->PrtWidth();
     744                 :        885 :     SwFlyPortion *pFlyPortion = 0;
     745                 :            : 
     746                 :        885 :     SwRect aLineVert( rCurrRect );
     747 [ -  + ][ +  - ]:        885 :     if ( GetTxtFrm()->IsRightToLeft() )
     748         [ #  # ]:          0 :         GetTxtFrm()->SwitchLTRtoRTL( aLineVert );
     749 [ +  - ][ -  + ]:        885 :     if ( GetTxtFrm()->IsVertical() )
     750         [ #  # ]:          0 :         GetTxtFrm()->SwitchHorizontalToVertical( aLineVert );
     751                 :            : 
     752                 :            :     // aFlyRect is document-global!
     753         [ +  - ]:        885 :     SwRect aFlyRect( aTxtFly.GetFrm( aLineVert ) );
     754                 :            : 
     755 [ +  - ][ -  + ]:        885 :     if ( GetTxtFrm()->IsRightToLeft() )
     756         [ #  # ]:          0 :         GetTxtFrm()->SwitchRTLtoLTR( aFlyRect );
     757 [ +  - ][ -  + ]:        885 :     if ( GetTxtFrm()->IsVertical() )
     758         [ #  # ]:          0 :         GetTxtFrm()->SwitchVerticalToHorizontal( aFlyRect );
     759                 :            : 
     760                 :            :     // If a Frame overlapps we open a Portion
     761 [ +  - ][ -  + ]:        885 :     if( aFlyRect.HasArea() )
     762                 :            :     {
     763                 :            :         // aLocal is frame-local
     764                 :          0 :         SwRect aLocal( aFlyRect );
     765         [ #  # ]:          0 :         aLocal.Pos( aLocal.Left() - GetLeftMargin(), aLocal.Top() );
     766         [ #  # ]:          0 :         if( nCurrWidth > aLocal.Left() )
     767                 :          0 :             aLocal.Left( nCurrWidth );
     768                 :            : 
     769                 :            :         // If the rect is wider than the line, we adjust it to the right size
     770                 :          0 :         KSHORT nLocalWidth = KSHORT( aLocal.Left() + aLocal.Width() );
     771         [ #  # ]:          0 :         if( nRealWidth < long( nLocalWidth ) )
     772                 :          0 :             aLocal.Width( nRealWidth - aLocal.Left() );
     773                 :          0 :         GetInfo().GetParaPortion()->SetFly( sal_True );
     774 [ #  # ][ #  # ]:          0 :         pFlyPortion = new SwFlyPortion( aLocal );
     775                 :          0 :         pFlyPortion->Height( KSHORT( rCurrRect.Height() ) );
     776                 :            :         // The Width could be smaller than the FixWidth, thus:
     777                 :          0 :         pFlyPortion->AdjFixWidth();
     778                 :            :     }
     779         [ +  - ]:        885 :     return pFlyPortion;
     780                 :            : }
     781                 :            : 
     782                 :            : /*************************************************************************
     783                 :            :  * SwTxtPainter::_CalcDropAdjust()
     784                 :            :  * Drops and Adjustment
     785                 :            :  * CalcDropAdjust is called at the end by Format() if needed
     786                 :            :  *************************************************************************/
     787                 :            : 
     788                 :          0 : void SwTxtAdjuster::CalcDropAdjust()
     789                 :            : {
     790                 :            :     OSL_ENSURE( 1<GetDropLines() && SVX_ADJUST_LEFT!=GetAdjust() && SVX_ADJUST_BLOCK!=GetAdjust(),
     791                 :            :             "CalcDropAdjust: No reason for DropAdjustment." );
     792                 :            : 
     793                 :          0 :     const MSHORT nLineNumber = GetLineNr();
     794                 :            : 
     795                 :            :     // 1) Skip dummies
     796                 :          0 :     Top();
     797                 :            : 
     798 [ #  # ][ #  # ]:          0 :     if( !pCurr->IsDummy() || NextLine() )
                 [ #  # ]
     799                 :            :     {
     800                 :            :         // Adjust first
     801                 :          0 :         GetAdjusted();
     802                 :            : 
     803                 :          0 :         SwLinePortion *pPor = pCurr->GetFirstPortion();
     804                 :            : 
     805                 :            :         // 2) Make sure we include the ropPortion
     806                 :            :         // 3) pLeft is the GluePor preceding the DropPor
     807   [ #  #  #  # ]:          0 :         if( pPor->InGlueGrp() && pPor->GetPortion()
         [ #  # ][ #  # ]
     808                 :          0 :               && pPor->GetPortion()->IsDropPortion() )
     809                 :            :         {
     810                 :          0 :             const SwLinePortion *pDropPor = (SwDropPortion*) pPor->GetPortion();
     811                 :          0 :             SwGluePortion *pLeft = (SwGluePortion*) pPor;
     812                 :            : 
     813                 :            :             // 4) pRight: Find the GluePor coming after the DropPor
     814                 :          0 :             pPor = pPor->GetPortion();
     815 [ #  # ][ #  # ]:          0 :             while( pPor && !pPor->InFixMargGrp() )
                 [ #  # ]
     816                 :          0 :                 pPor = pPor->GetPortion();
     817                 :            : 
     818                 :          0 :             SwGluePortion *pRight = ( pPor && pPor->InGlueGrp() ) ?
     819   [ #  #  #  # ]:          0 :                                     (SwGluePortion*) pPor : 0;
     820 [ #  # ][ #  # ]:          0 :             if( pRight && pRight != pLeft )
     821                 :            :             {
     822                 :            :                 // 5) Calculate nMinLeft. Who is the most to left?
     823                 :            :                 const KSHORT nDropLineStart =
     824                 :          0 :                     KSHORT(GetLineStart()) + pLeft->Width() + pDropPor->Width();
     825                 :          0 :                 KSHORT nMinLeft = nDropLineStart;
     826         [ #  # ]:          0 :                 for( MSHORT i = 1; i < GetDropLines(); ++i )
     827                 :            :                 {
     828         [ #  # ]:          0 :                     if( NextLine() )
     829                 :            :                     {
     830                 :            :                         // Adjust first
     831                 :          0 :                         GetAdjusted();
     832                 :            : 
     833                 :          0 :                         pPor = pCurr->GetFirstPortion();
     834                 :          0 :                         const SwMarginPortion *pMar = pPor->IsMarginPortion() ?
     835         [ #  # ]:          0 :                                                       (SwMarginPortion*)pPor : 0;
     836         [ #  # ]:          0 :                         if( !pMar )
     837                 :          0 :                             nMinLeft = 0;
     838                 :            :                         else
     839                 :            :                         {
     840                 :            :                             const KSHORT nLineStart =
     841                 :          0 :                                 KSHORT(GetLineStart()) + pMar->Width();
     842         [ #  # ]:          0 :                             if( nMinLeft > nLineStart )
     843                 :          0 :                                 nMinLeft = nLineStart;
     844                 :            :                         }
     845                 :            :                     }
     846                 :            :                 }
     847                 :            : 
     848                 :            :                 // 6) Distribute the Glue anew between pLeft and pRight
     849         [ #  # ]:          0 :                 if( nMinLeft < nDropLineStart )
     850                 :            :                 {
     851                 :            :                     // The Glue is always passed from pLeft to pRight, so that
     852                 :            :                     // the text moves to the left.
     853                 :          0 :                     const short nGlue = nDropLineStart - nMinLeft;
     854         [ #  # ]:          0 :                     if( !nMinLeft )
     855                 :          0 :                         pLeft->MoveAllGlue( pRight );
     856                 :            :                     else
     857                 :          0 :                         pLeft->MoveGlue( pRight, nGlue );
     858                 :            :                 }
     859                 :            :             }
     860                 :            :         }
     861                 :            :     }
     862                 :            : 
     863         [ #  # ]:          0 :     if( nLineNumber != GetLineNr() )
     864                 :            :     {
     865                 :          0 :         Top();
     866 [ #  # ][ #  # ]:          0 :         while( nLineNumber != GetLineNr() && Next() )
                 [ #  # ]
     867                 :            :             ;
     868                 :            :     }
     869                 :          0 : }
     870                 :            : 
     871                 :            : /*************************************************************************
     872                 :            :  * SwTxtAdjuster::CalcDropRepaint()
     873                 :            :  *************************************************************************/
     874                 :            : 
     875                 :          0 : void SwTxtAdjuster::CalcDropRepaint()
     876                 :            : {
     877                 :          0 :     Top();
     878                 :          0 :     SwRepaint &rRepaint = *GetInfo().GetParaPortion()->GetRepaint();
     879         [ #  # ]:          0 :     if( rRepaint.Top() > Y() )
     880                 :          0 :         rRepaint.Top( Y() );
     881         [ #  # ]:          0 :     for( MSHORT i = 1; i < GetDropLines(); ++i )
     882                 :          0 :         NextLine();
     883                 :          0 :     const SwTwips nBottom = Y() + GetLineHeight() - 1;
     884         [ #  # ]:          0 :     if( rRepaint.Bottom() < nBottom )
     885                 :          0 :         rRepaint.Bottom( nBottom );
     886                 :          0 : }
     887                 :            : 
     888                 :            : 
     889                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10