LCOV - code coverage report
Current view: top level - sw/source/core/text - pormulti.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 659 1205 54.7 %
Date: 2012-08-25 Functions: 24 42 57.1 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 523 1561 33.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 <com/sun/star/i18n/ScriptType.hpp>
      32                 :            : #include <editeng/twolinesitem.hxx>
      33                 :            : #include <editeng/charrotateitem.hxx>
      34                 :            : #include <vcl/outdev.hxx>
      35                 :            : #include <fmtfld.hxx>
      36                 :            : #include <fldbas.hxx>      // SwField
      37                 :            : #include <txatbase.hxx>
      38                 :            : #include <fmtruby.hxx>  // SwFmtRuby
      39                 :            : #include <txtatr.hxx>   // SwTxtRuby
      40                 :            : #include <charfmt.hxx>
      41                 :            : #include <txtinet.hxx>
      42                 :            : #include <fchrfmt.hxx>
      43                 :            : #include <layfrm.hxx>       // GetUpper()
      44                 :            : #include <SwPortionHandler.hxx>
      45                 :            : #include <pormulti.hxx>     // SwMultiPortion
      46                 :            : #include <inftxt.hxx>       // SwTxtSizeInfo
      47                 :            : #include <itrpaint.hxx>     // SwTxtPainter
      48                 :            : #include <viewopt.hxx>      // SwViewOptions
      49                 :            : #include <itrform2.hxx>     // SwTxtFormatter
      50                 :            : #include <porfld.hxx>       // SwFldPortion
      51                 :            : #include <porglue.hxx>
      52                 :            : #include <breakit.hxx>
      53                 :            : #include <pagefrm.hxx>
      54                 :            : #include <rowfrm.hxx>
      55                 :            : #include <pagedesc.hxx> // SwPageDesc
      56                 :            : #include <tgrditem.hxx>
      57                 :            : #include <swtable.hxx>
      58                 :            : #include <fmtfsize.hxx>
      59                 :            : 
      60                 :            : using namespace ::com::sun::star;
      61                 :            : extern sal_Bool IsUnderlineBreak( const SwLinePortion& rPor, const SwFont& rFnt );
      62                 :            : 
      63                 :            : /*--------------------------------------------------
      64                 :            :  *  class SwMultiPortion
      65                 :            :  *
      66                 :            :  * A SwMultiPortion is not a simple portion,
      67                 :            :  * it's a container, which contains almost a SwLineLayoutPortion.
      68                 :            :  * This SwLineLayout could be followed by other textportions via pPortion
      69                 :            :  * and by another SwLineLayout via pNext to realize a doubleline portion.
      70                 :            :  * --------------------------------------------------*/
      71                 :            : 
      72         [ +  - ]:        356 : SwMultiPortion::~SwMultiPortion()
      73                 :            : {
      74 [ -  + ][ #  # ]:        356 :     delete pFldRest;
      75         [ -  + ]:        356 : }
      76                 :            : 
      77                 :          0 : void SwMultiPortion::Paint( const SwTxtPaintInfo & ) const
      78                 :            : {
      79                 :            :     OSL_FAIL( "Don't try SwMultiPortion::Paint, try SwTxtPainter::PaintMultiPortion" );
      80                 :          0 : }
      81                 :            : 
      82                 :            : /*--------------------------------------------------
      83                 :            :  * Summarize the internal lines to calculate the (external) size.
      84                 :            :  * The internal line has to calculate first.
      85                 :            :  * --------------------------------------------------*/
      86                 :            : 
      87                 :        932 : void SwMultiPortion::CalcSize( SwTxtFormatter& rLine, SwTxtFormatInfo &rInf )
      88                 :            : {
      89                 :        932 :     Width( 0 );
      90                 :        932 :     Height( 0 );
      91                 :        932 :     SetAscent( 0 );
      92                 :        932 :     SetFlyInCntnt( sal_False );
      93                 :        932 :     SwLineLayout *pLay = &GetRoot();
      94         [ +  + ]:       1544 :     do
      95                 :            :     {
      96                 :       1544 :         pLay->CalcLine( rLine, rInf );
      97         [ -  + ]:       1544 :         if( rLine.IsFlyInCntBase() )
      98                 :          0 :             SetFlyInCntnt( sal_True );
      99 [ +  + ][ +  + ]:       1544 :         if( IsRuby() && ( OnTop() == ( pLay == &GetRoot() ) ) )
                 [ +  + ]
     100                 :            :         {
     101                 :            :             // An empty phonetic line don't need an ascent or a height.
     102         [ +  + ]:        672 :             if( !pLay->Width() )
     103                 :            :             {
     104                 :         56 :                 pLay->SetAscent( 0 );
     105                 :         56 :                 pLay->Height( 0 );
     106                 :            :             }
     107         [ +  + ]:        672 :             if( OnTop() )
     108                 :        560 :                 SetAscent( GetAscent() + pLay->Height() );
     109                 :            :         }
     110                 :            :         else
     111                 :        872 :             SetAscent( GetAscent() + pLay->GetAscent() );
     112                 :       1544 :         Height( Height() + pLay->Height() );
     113         [ +  + ]:       1544 :         if( Width() < pLay->Width() )
     114                 :        864 :             Width( pLay->Width() );
     115                 :       1544 :         pLay = pLay->GetNext();
     116                 :            :     } while ( pLay );
     117         [ +  + ]:        932 :     if( HasBrackets() )
     118                 :            :     {
     119                 :        208 :         KSHORT nTmp = ((SwDoubleLinePortion*)this)->GetBrackets()->nHeight;
     120         [ +  + ]:        208 :         if( nTmp > Height() )
     121                 :            :         {
     122                 :         32 :             KSHORT nAdd = ( nTmp - Height() ) / 2;
     123                 :         32 :             GetRoot().SetAscent( GetRoot().GetAscent() + nAdd );
     124                 :         32 :             GetRoot().Height( GetRoot().Height() + nAdd );
     125                 :         32 :             Height( nTmp );
     126                 :            :         }
     127                 :        208 :         nTmp = ((SwDoubleLinePortion*)this)->GetBrackets()->nAscent;
     128         [ +  + ]:        208 :         if( nTmp > GetAscent() )
     129                 :         32 :             SetAscent( nTmp );
     130                 :            :     }
     131                 :        932 : }
     132                 :            : 
     133                 :          0 : long SwMultiPortion::CalcSpacing( long , const SwTxtSizeInfo & ) const
     134                 :            : {
     135                 :          0 :     return 0;
     136                 :            : }
     137                 :            : 
     138                 :        354 : sal_Bool SwMultiPortion::ChgSpaceAdd( SwLineLayout*, long ) const
     139                 :            : {
     140                 :        354 :     return sal_False;
     141                 :            : }
     142                 :            : 
     143                 :            : /*************************************************************************
     144                 :            :  *              virtual SwMultiPortion::HandlePortion()
     145                 :            :  *************************************************************************/
     146                 :            : 
     147                 :          0 : void SwMultiPortion::HandlePortion( SwPortionHandler& rPH ) const
     148                 :            : {
     149                 :          0 :     rPH.Text( GetLen(), GetWhichPor() );
     150                 :          0 : }
     151                 :            : 
     152                 :            : /*--------------------------------------------------
     153                 :            :  * SwMultiPortion::ActualizeTabulator()
     154                 :            :  * sets the tabulator-flag, if there's any tabulator-portion inside.
     155                 :            :  * --------------------------------------------------*/
     156                 :            : 
     157                 :        336 : void SwMultiPortion::ActualizeTabulator()
     158                 :            : {
     159                 :        336 :     SwLinePortion* pPor = GetRoot().GetFirstPortion();
     160                 :            :     // First line
     161         [ +  + ]:        672 :     for( bTab1 = bTab2 = sal_False; pPor; pPor = pPor->GetPortion() )
     162         [ -  + ]:        336 :         if( pPor->InTabGrp() )
     163                 :          0 :             SetTab1( sal_True );
     164         [ +  - ]:        336 :     if( GetRoot().GetNext() )
     165                 :            :     {
     166                 :            :         // Second line
     167                 :        336 :         pPor = GetRoot().GetNext()->GetFirstPortion();
     168         [ +  + ]:        510 :         do
     169                 :            :         {
     170         [ -  + ]:        510 :             if( pPor->InTabGrp() )
     171                 :          0 :                 SetTab2( sal_True );
     172                 :        510 :             pPor = pPor->GetPortion();
     173                 :            :         } while ( pPor );
     174                 :            :     }
     175                 :        336 : }
     176                 :            : 
     177                 :            : /*--------------------------------------------------
     178                 :            :  * SwRotatedPortion::SwRotatedPortion(..)
     179                 :            :  * --------------------------------------------------*/
     180                 :            : 
     181                 :          0 : SwRotatedPortion::SwRotatedPortion( const SwMultiCreator& rCreate,
     182                 :          0 :     xub_StrLen nEnd, sal_Bool bRTL ) : SwMultiPortion( nEnd )
     183                 :            : {
     184                 :          0 :     const SvxCharRotateItem* pRot = (SvxCharRotateItem*)rCreate.pItem;
     185         [ #  # ]:          0 :     if( !pRot )
     186                 :            :     {
     187                 :          0 :         const SwTxtAttr& rAttr = *rCreate.pAttr;
     188                 :            :         const SfxPoolItem *const pItem =
     189         [ #  # ]:          0 :                 CharFmt::GetItem(rAttr, RES_CHRATR_ROTATE);
     190         [ #  # ]:          0 :         if ( pItem )
     191                 :            :         {
     192                 :          0 :             pRot = static_cast<const SvxCharRotateItem*>(pItem);
     193                 :            :         }
     194                 :            :     }
     195         [ #  # ]:          0 :     if( pRot )
     196                 :            :     {
     197                 :            :         sal_uInt8 nDir;
     198         [ #  # ]:          0 :         if ( bRTL )
     199         [ #  # ]:          0 :             nDir = pRot->IsBottomToTop() ? 3 : 1;
     200                 :            :         else
     201         [ #  # ]:          0 :             nDir = pRot->IsBottomToTop() ? 1 : 3;
     202                 :            : 
     203                 :          0 :         SetDirection( nDir );
     204                 :            :     }
     205                 :          0 : }
     206                 :            : 
     207                 :            : /*---------------------------------------------------
     208                 :            :  * SwBidiPortion::SwBidiPortion(..)
     209                 :            :  * --------------------------------------------------*/
     210                 :            : 
     211                 :          0 : SwBidiPortion::SwBidiPortion( xub_StrLen nEnd, sal_uInt8 nLv )
     212                 :          0 :     : SwMultiPortion( nEnd ), nLevel( nLv )
     213                 :            : {
     214                 :          0 :     SetBidi();
     215                 :            : 
     216         [ #  # ]:          0 :     if ( nLevel % 2 )
     217                 :          0 :         SetDirection( DIR_RIGHT2LEFT );
     218                 :            :     else
     219                 :          0 :         SetDirection( DIR_LEFT2RIGHT );
     220                 :          0 : }
     221                 :            : 
     222                 :            : 
     223                 :          0 : long SwBidiPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo& rInf ) const
     224                 :            : {
     225         [ #  # ]:          0 :     return HasTabulator() ? 0 : GetSpaceCnt(rInf) * nSpaceAdd / SPACING_PRECISION_FACTOR;
     226                 :            : }
     227                 :            : 
     228                 :          0 : sal_Bool SwBidiPortion::ChgSpaceAdd( SwLineLayout* pCurr, long nSpaceAdd ) const
     229                 :            : {
     230                 :          0 :     sal_Bool bRet = sal_False;
     231 [ #  # ][ #  # ]:          0 :     if( !HasTabulator() && nSpaceAdd > 0 && !pCurr->IsSpaceAdd() )
         [ #  # ][ #  # ]
     232                 :            :     {
     233                 :          0 :         pCurr->CreateSpaceAdd();
     234                 :          0 :         pCurr->SetLLSpaceAdd( nSpaceAdd, 0 );
     235                 :          0 :         bRet = sal_True;
     236                 :            :     }
     237                 :            : 
     238                 :          0 :     return bRet;
     239                 :            : }
     240                 :            : 
     241                 :          0 : xub_StrLen SwBidiPortion::GetSpaceCnt( const SwTxtSizeInfo &rInf ) const
     242                 :            : {
     243                 :            :     // Calculate number of blanks for justified alignment
     244                 :          0 :     SwLinePortion* pPor = GetRoot().GetFirstPortion();
     245                 :          0 :     xub_StrLen nTmpStart = rInf.GetIdx();
     246                 :          0 :     xub_StrLen nNull = 0;
     247                 :            :     xub_StrLen nBlanks;
     248                 :            : 
     249         [ #  # ]:          0 :     for( nBlanks = 0; pPor; pPor = pPor->GetPortion() )
     250                 :            :     {
     251         [ #  # ]:          0 :         if( pPor->InTxtGrp() )
     252         [ #  # ]:          0 :             nBlanks = nBlanks + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
     253   [ #  #  #  # ]:          0 :         else if ( pPor->IsMultiPortion() &&
                 [ #  # ]
     254                 :          0 :                  ((SwMultiPortion*)pPor)->IsBidi() )
     255         [ #  # ]:          0 :             nBlanks = nBlanks + ((SwBidiPortion*)pPor)->GetSpaceCnt( rInf );
     256                 :            : 
     257                 :          0 :         ((SwTxtSizeInfo &)rInf).SetIdx( rInf.GetIdx() + pPor->GetLen() );
     258                 :            :     }
     259                 :          0 :     ((SwTxtSizeInfo &)rInf).SetIdx( nTmpStart );
     260                 :          0 :     return nBlanks;
     261                 :            : }
     262                 :            : 
     263                 :            : /*--------------------------------------------------
     264                 :            :  * SwDoubleLinePortion::SwDoubleLinePortion(..)
     265                 :            :  * This constructor is for the continuation of a doubleline portion
     266                 :            :  * in the next line.
     267                 :            :  * It takes the same brackets and if the original has no content except
     268                 :            :  * brackets, these will be deleted.
     269                 :            :  * --------------------------------------------------*/
     270                 :            : 
     271                 :          0 : SwDoubleLinePortion::SwDoubleLinePortion( SwDoubleLinePortion& rDouble,
     272                 :            :                                           xub_StrLen nEnd ) :
     273                 :            :     SwMultiPortion( nEnd ),
     274                 :          0 :     pBracket( 0 )
     275                 :            : {
     276                 :          0 :     SetDirection( rDouble.GetDirection() );
     277                 :          0 :     SetDouble();
     278         [ #  # ]:          0 :     if( rDouble.GetBrackets() )
     279                 :            :     {
     280         [ #  # ]:          0 :         SetBrackets( rDouble );
     281                 :            :         // An empty multiportion needs no brackets.
     282                 :            :         // Notice: GetLen() might be zero, if the multiportion contains
     283                 :            :         // the second part of a field and the width might be zero, if
     284                 :            :         // it contains a note only. In this cases the brackets are okay.
     285                 :            :         // But if the length and the width are both zero, the portion
     286                 :            :         // is really empty.
     287         [ #  # ]:          0 :         if( rDouble.Width() ==  rDouble.BracketWidth() )
     288                 :          0 :             rDouble.ClearBrackets();
     289                 :            :     }
     290                 :          0 : }
     291                 :            : 
     292                 :            : /*--------------------------------------------------
     293                 :            :  * SwDoubleLinePortion::SwDoubleLinePortion(..)
     294                 :            :  * This constructor uses the textattribut to get the right brackets.
     295                 :            :  * The textattribut could be a 2-line-attribute or a character- or
     296                 :            :  * internetstyle, which contains the 2-line-attribute.
     297                 :            :  * --------------------------------------------------*/
     298                 :            : 
     299                 :         20 : SwDoubleLinePortion::SwDoubleLinePortion( const SwMultiCreator& rCreate,
     300         [ +  - ]:         20 :     xub_StrLen nEnd ) : SwMultiPortion( nEnd ), pBracket( new SwBracket() )
     301                 :            : {
     302                 :         20 :     SetDouble();
     303                 :         20 :     const SvxTwoLinesItem* pTwo = (SvxTwoLinesItem*)rCreate.pItem;
     304         [ -  + ]:         20 :     if( pTwo )
     305                 :          0 :         pBracket->nStart = 0;
     306                 :            :     else
     307                 :            :     {
     308                 :         20 :         const SwTxtAttr& rAttr = *rCreate.pAttr;
     309                 :         20 :         pBracket->nStart = *rAttr.GetStart();
     310                 :            : 
     311                 :            :         const SfxPoolItem * const pItem =
     312         [ +  - ]:         20 :             CharFmt::GetItem( rAttr, RES_CHRATR_TWO_LINES );
     313         [ +  - ]:         20 :         if ( pItem )
     314                 :            :         {
     315                 :         20 :             pTwo = static_cast<const SvxTwoLinesItem*>(pItem);
     316                 :            :         }
     317                 :            :     }
     318         [ +  - ]:         20 :     if( pTwo )
     319                 :            :     {
     320                 :         20 :         pBracket->cPre = pTwo->GetStartBracket();
     321                 :         20 :         pBracket->cPost = pTwo->GetEndBracket();
     322                 :            :     }
     323                 :            :     else
     324                 :            :     {
     325                 :          0 :         pBracket->cPre = 0;
     326                 :          0 :         pBracket->cPost = 0;
     327                 :            :     }
     328                 :         20 :     sal_uInt8 nTmp = SW_SCRIPTS;
     329         [ -  + ]:         20 :     if( pBracket->cPre > 255 )
     330                 :            :     {
     331         [ #  # ]:          0 :         String aTxt = rtl::OUString(pBracket->cPre);
     332 [ #  # ][ #  # ]:          0 :         nTmp = SwScriptInfo::WhichFont( 0, &aTxt, 0 );
     333                 :            :     }
     334                 :         20 :     pBracket->nPreScript = nTmp;
     335                 :         20 :     nTmp = SW_SCRIPTS;
     336         [ -  + ]:         20 :     if( pBracket->cPost > 255 )
     337                 :            :     {
     338         [ #  # ]:          0 :         String aTxt = rtl::OUString(pBracket->cPost);
     339 [ #  # ][ #  # ]:          0 :         nTmp = SwScriptInfo::WhichFont( 0, &aTxt, 0 );
     340                 :            :     }
     341                 :         20 :     pBracket->nPostScript = nTmp;
     342                 :            : 
     343 [ +  + ][ +  - ]:         20 :     if( !pBracket->cPre && !pBracket->cPost )
     344                 :            :     {
     345                 :          4 :         delete pBracket;
     346                 :          4 :         pBracket = 0;
     347                 :            :     }
     348                 :            : 
     349                 :            :     // double line portions have the same direction as the frame directions
     350         [ -  + ]:         20 :     if ( rCreate.nLevel % 2 )
     351                 :          0 :         SetDirection( DIR_RIGHT2LEFT );
     352                 :            :     else
     353                 :         20 :         SetDirection( DIR_LEFT2RIGHT );
     354                 :         20 : }
     355                 :            : 
     356                 :            : 
     357                 :            : /*--------------------------------------------------
     358                 :            :  * SwMultiPortion::PaintBracket paints the wished bracket,
     359                 :            :  * if the multiportion has surrounding brackets.
     360                 :            :  * The X-position of the SwTxtPaintInfo will be modified:
     361                 :            :  * the open bracket sets position behind itself,
     362                 :            :  * the close bracket in front of itself.
     363                 :            :  * --------------------------------------------------*/
     364                 :            : 
     365                 :         40 : void SwDoubleLinePortion::PaintBracket( SwTxtPaintInfo &rInf,
     366                 :            :                                         long nSpaceAdd,
     367                 :            :                                         sal_Bool bOpen ) const
     368                 :            : {
     369         [ +  + ]:         40 :     sal_Unicode cCh = bOpen ? pBracket->cPre : pBracket->cPost;
     370         [ +  + ]:         40 :     if( !cCh )
     371                 :            :         return;
     372         [ +  + ]:         36 :     KSHORT nChWidth = bOpen ? PreWidth() : PostWidth();
     373         [ +  - ]:         36 :     if( !nChWidth )
     374                 :            :         return;
     375         [ +  + ]:         36 :     if( !bOpen )
     376                 :         16 :         rInf.X( rInf.X() + Width() - PostWidth() +
     377 [ #  # ][ -  + ]:         16 :             ( nSpaceAdd > 0 ? CalcSpacing( nSpaceAdd, rInf ) : 0 ) );
     378                 :            : 
     379         [ +  - ]:         36 :     SwBlankPortion aBlank( cCh, sal_True );
     380                 :         36 :     aBlank.SetAscent( pBracket->nAscent );
     381                 :         36 :     aBlank.Width( nChWidth );
     382                 :         36 :     aBlank.Height( pBracket->nHeight );
     383                 :            :     {
     384 [ +  - ][ +  - ]:         36 :         SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
     385         [ +  + ]:         36 :         sal_uInt8 nAct = bOpen ? pBracket->nPreScript : pBracket->nPostScript;
     386         [ -  + ]:         36 :         if( SW_SCRIPTS > nAct )
     387                 :          0 :             pTmpFnt->SetActual( nAct );
     388         [ +  - ]:         36 :         pTmpFnt->SetProportion( 100 );
     389         [ +  - ]:         36 :         SwFontSave aSave( rInf, pTmpFnt );
     390         [ +  - ]:         36 :         aBlank.Paint( rInf );
     391 [ +  - ][ +  - ]:         36 :         delete pTmpFnt;
                 [ +  - ]
     392                 :            :     }
     393         [ +  + ]:         36 :     if( bOpen )
     394         [ +  - ]:         40 :         rInf.X( rInf.X() + PreWidth() );
     395                 :            : }
     396                 :            : 
     397                 :            : /*--------------------------------------------------
     398                 :            :  * SwDoubleLinePortion::SetBrackets creates the bracket-structur
     399                 :            :  * and fills it, if not both characters are 0x00.
     400                 :            :  * --------------------------------------------------*/
     401                 :            : 
     402                 :          0 : void SwDoubleLinePortion::SetBrackets( const SwDoubleLinePortion& rDouble )
     403                 :            : {
     404         [ #  # ]:          0 :     if( rDouble.pBracket )
     405                 :            :     {
     406                 :          0 :         pBracket = new SwBracket;
     407                 :          0 :         pBracket->cPre = rDouble.pBracket->cPre;
     408                 :          0 :         pBracket->cPost = rDouble.pBracket->cPost;
     409                 :          0 :         pBracket->nPreScript = rDouble.pBracket->nPreScript;
     410                 :          0 :         pBracket->nPostScript = rDouble.pBracket->nPostScript;
     411                 :          0 :         pBracket->nStart = rDouble.pBracket->nStart;
     412                 :            :     }
     413                 :          0 : }
     414                 :            : 
     415                 :            : /*--------------------------------------------------
     416                 :            :  * SwDoubleLinePortion::FormatBrackets
     417                 :            :  * calculates the size of the brackets => pBracket,
     418                 :            :  * reduces the nMaxWidth-parameter ( minus bracket-width )
     419                 :            :  * and moves the rInf-x-position behind the opening bracket.
     420                 :            :  * --------------------------------------------------*/
     421                 :            : 
     422                 :         16 : void SwDoubleLinePortion::FormatBrackets( SwTxtFormatInfo &rInf, SwTwips& nMaxWidth )
     423                 :            : {
     424                 :         16 :     nMaxWidth -= rInf.X();
     425         [ +  - ]:         16 :     SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
     426                 :         16 :     pTmpFnt->SetProportion( 100 );
     427                 :         16 :     pBracket->nAscent = 0;
     428                 :         16 :     pBracket->nHeight = 0;
     429         [ +  - ]:         16 :     if( pBracket->cPre )
     430                 :            :     {
     431                 :         16 :         rtl::OUString aStr( pBracket->cPre );
     432                 :         16 :         sal_uInt8 nActualScr = pTmpFnt->GetActual();
     433         [ -  + ]:         16 :         if( SW_SCRIPTS > pBracket->nPreScript )
     434                 :          0 :             pTmpFnt->SetActual( pBracket->nPreScript );
     435         [ +  - ]:         16 :         SwFontSave aSave( rInf, pTmpFnt );
     436 [ +  - ][ +  - ]:         16 :         SwPosSize aSize = rInf.GetTxtSize( aStr );
                 [ +  - ]
     437         [ +  - ]:         16 :         pBracket->nAscent = rInf.GetAscent();
     438                 :         16 :         pBracket->nHeight = aSize.Height();
     439                 :         16 :         pTmpFnt->SetActual( nActualScr );
     440         [ +  - ]:         16 :         if( nMaxWidth > aSize.Width() )
     441                 :            :         {
     442                 :         16 :             pBracket->nPreWidth = aSize.Width();
     443                 :         16 :             nMaxWidth -= aSize.Width();
     444                 :         16 :             rInf.X( rInf.X() + aSize.Width() );
     445                 :            :         }
     446                 :            :         else
     447                 :            :         {
     448                 :          0 :             pBracket->nPreWidth = 0;
     449                 :          0 :             nMaxWidth = 0;
     450         [ +  - ]:         16 :         }
     451                 :            :     }
     452                 :            :     else
     453                 :          0 :         pBracket->nPreWidth = 0;
     454         [ +  + ]:         16 :     if( pBracket->cPost )
     455                 :            :     {
     456                 :         12 :         rtl::OUString aStr( pBracket->cPost );
     457         [ -  + ]:         12 :         if( SW_SCRIPTS > pBracket->nPostScript )
     458                 :          0 :             pTmpFnt->SetActual( pBracket->nPostScript );
     459         [ +  - ]:         12 :         SwFontSave aSave( rInf, pTmpFnt );
     460 [ +  - ][ +  - ]:         12 :         SwPosSize aSize = rInf.GetTxtSize( aStr );
                 [ +  - ]
     461         [ +  - ]:         12 :         KSHORT nTmpAsc = rInf.GetAscent();
     462         [ -  + ]:         12 :         if( nTmpAsc > pBracket->nAscent )
     463                 :            :         {
     464                 :          0 :             pBracket->nHeight += nTmpAsc - pBracket->nAscent;
     465                 :          0 :             pBracket->nAscent = nTmpAsc;
     466                 :            :         }
     467         [ -  + ]:         12 :         if( aSize.Height() > pBracket->nHeight )
     468                 :          0 :             pBracket->nHeight = aSize.Height();
     469         [ +  - ]:         12 :         if( nMaxWidth > aSize.Width() )
     470                 :            :         {
     471                 :         12 :             pBracket->nPostWidth = aSize.Width();
     472                 :         12 :             nMaxWidth -= aSize.Width();
     473                 :            :         }
     474                 :            :         else
     475                 :            :         {
     476                 :          0 :             pBracket->nPostWidth = 0;
     477                 :          0 :             nMaxWidth = 0;
     478         [ +  - ]:         12 :         }
     479                 :            :     }
     480                 :            :     else
     481                 :          4 :         pBracket->nPostWidth = 0;
     482                 :         16 :     nMaxWidth += rInf.X();
     483                 :         16 : }
     484                 :            : 
     485                 :            : /*--------------------------------------------------
     486                 :            :  * SwDoubleLinePortion::CalcBlanks
     487                 :            :  * calculates the number of blanks in each line and
     488                 :            :  * the difference of the width of the two lines.
     489                 :            :  * These results are used from the text adjustment.
     490                 :            :  * --------------------------------------------------*/
     491                 :            : 
     492                 :         20 : void SwDoubleLinePortion::CalcBlanks( SwTxtFormatInfo &rInf )
     493                 :            : {
     494                 :         20 :     SwLinePortion* pPor = GetRoot().GetFirstPortion();
     495                 :         20 :     xub_StrLen nNull = 0;
     496                 :         20 :     xub_StrLen nStart = rInf.GetIdx();
     497                 :         20 :     SetTab1( sal_False );
     498                 :         20 :     SetTab2( sal_False );
     499         [ +  + ]:         40 :     for( nBlank1 = 0; pPor; pPor = pPor->GetPortion() )
     500                 :            :     {
     501         [ +  - ]:         20 :         if( pPor->InTxtGrp() )
     502         [ +  - ]:         20 :             nBlank1 = nBlank1 + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
     503                 :         20 :         rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
     504         [ -  + ]:         20 :         if( pPor->InTabGrp() )
     505                 :          0 :             SetTab1( sal_True );
     506                 :            :     }
     507                 :         20 :     nLineDiff = GetRoot().Width();
     508         [ +  - ]:         20 :     if( GetRoot().GetNext() )
     509                 :            :     {
     510                 :         20 :         pPor = GetRoot().GetNext()->GetFirstPortion();
     511                 :         20 :         nLineDiff -= GetRoot().GetNext()->Width();
     512                 :            :     }
     513         [ +  + ]:         40 :     for( nBlank2 = 0; pPor; pPor = pPor->GetPortion() )
     514                 :            :     {
     515         [ +  - ]:         20 :         if( pPor->InTxtGrp() )
     516         [ +  - ]:         20 :             nBlank2 = nBlank2 + ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nNull );
     517                 :         20 :         rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
     518         [ -  + ]:         20 :         if( pPor->InTabGrp() )
     519                 :          0 :             SetTab2( sal_True );
     520                 :            :     }
     521                 :         20 :     rInf.SetIdx( nStart );
     522                 :         20 : }
     523                 :            : 
     524                 :          0 : long SwDoubleLinePortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo & ) const
     525                 :            : {
     526         [ #  # ]:          0 :     return HasTabulator() ? 0 : GetSpaceCnt() * nSpaceAdd / SPACING_PRECISION_FACTOR;
     527                 :            : }
     528                 :            : 
     529                 :            : /*--------------------------------------------------
     530                 :            :  * SwDoubleLinePortion::ChangeSpaceAdd(..)
     531                 :            :  * merges the spaces for text adjustment from the inner and outer part.
     532                 :            :  * Inside the doubleline portion the wider line has no spaceadd-array, the
     533                 :            :  * smaller line has such an array to reach width of the wider line.
     534                 :            :  * If the surrounding line has text adjustment and the doubleline portion
     535                 :            :  * contains no tabulator, it is necessary to create/manipulate the inner
     536                 :            :  * space arrays.
     537                 :            :  * --------------------------------------------------*/
     538                 :            : 
     539                 :         78 : sal_Bool SwDoubleLinePortion::ChgSpaceAdd( SwLineLayout* pCurr,
     540                 :            :                                            long nSpaceAdd ) const
     541                 :            : {
     542                 :         78 :     sal_Bool bRet = sal_False;
     543 [ +  - ][ -  + ]:         78 :     if( !HasTabulator() && nSpaceAdd > 0 )
                 [ -  + ]
     544                 :            :     {
     545         [ #  # ]:          0 :         if( !pCurr->IsSpaceAdd() )
     546                 :            :         {
     547                 :            :             // The wider line gets the spaceadd from the surrounding line direct
     548                 :          0 :             pCurr->CreateSpaceAdd();
     549                 :          0 :             pCurr->SetLLSpaceAdd( nSpaceAdd, 0 );
     550                 :          0 :             bRet = sal_True;
     551                 :            :         }
     552                 :            :         else
     553                 :            :         {
     554                 :          0 :             xub_StrLen nMyBlank = GetSmallerSpaceCnt();
     555                 :          0 :             xub_StrLen nOther = GetSpaceCnt();
     556         [ #  # ]:          0 :             SwTwips nMultiSpace = pCurr->GetLLSpaceAdd( 0 ) * nMyBlank + nOther * nSpaceAdd;
     557                 :            : 
     558         [ #  # ]:          0 :             if( nMyBlank )
     559                 :          0 :                 nMultiSpace /= nMyBlank;
     560                 :            : 
     561         [ #  # ]:          0 :             if( nMultiSpace < KSHRT_MAX * SPACING_PRECISION_FACTOR )
     562                 :            :             {
     563                 :            : //                pCurr->SetLLSpaceAdd( nMultiSpace, 0 );
     564                 :            :                 // #i65711# SetLLSpaceAdd replaces the first value,
     565                 :            :                 // instead we want to insert a new first value:
     566                 :          0 :                 std::vector<long>* pVec = pCurr->GetpLLSpaceAdd();
     567         [ #  # ]:          0 :                 pVec->insert( pVec->begin(), nMultiSpace );
     568                 :          0 :                 bRet = sal_True;
     569                 :            :             }
     570                 :            :         }
     571                 :            :     }
     572                 :         78 :     return bRet;
     573                 :            : }
     574                 :            : /*--------------------------------------------------
     575                 :            :  * SwDoubleLinePortion::ResetSpaceAdd(..)
     576                 :            :  * cancels the manipulation from SwDoubleLinePortion::ChangeSpaceAdd(..)
     577                 :            :  * --------------------------------------------------*/
     578                 :            : 
     579                 :          0 : void SwDoubleLinePortion::ResetSpaceAdd( SwLineLayout* pCurr )
     580                 :            : {
     581                 :          0 :     pCurr->RemoveFirstLLSpaceAdd();;
     582         [ #  # ]:          0 :     if( !pCurr->GetLLSpaceAddCount() )
     583                 :          0 :         pCurr->FinishSpaceAdd();
     584                 :          0 : }
     585                 :            : 
     586                 :         20 : SwDoubleLinePortion::~SwDoubleLinePortion()
     587                 :            : {
     588                 :         20 :     delete pBracket;
     589         [ -  + ]:         40 : }
     590                 :            : 
     591                 :            : /*--------------------------------------------------
     592                 :            :  * SwRubyPortion::SwRubyPortion(..)
     593                 :            :  * constructs a ruby portion, i.e. an additional text is displayed
     594                 :            :  * beside the main text, e.g. phonetic characters.
     595                 :            :  * --------------------------------------------------*/
     596                 :            : 
     597                 :            : 
     598                 :          0 : SwRubyPortion::SwRubyPortion( const SwRubyPortion& rRuby, xub_StrLen nEnd ) :
     599                 :            :     SwMultiPortion( nEnd ),
     600                 :          0 :     nRubyOffset( rRuby.GetRubyOffset() ),
     601                 :          0 :     nAdjustment( rRuby.GetAdjustment() )
     602                 :            : {
     603                 :          0 :     SetDirection( rRuby.GetDirection() ),
     604                 :          0 :     SetTop( rRuby.OnTop() );
     605                 :          0 :     SetRuby();
     606                 :          0 : }
     607                 :            : 
     608                 :            : /*--------------------------------------------------
     609                 :            :  * SwRubyPortion::SwRubyPortion(..)
     610                 :            :  * constructs a ruby portion, i.e. an additional text is displayed
     611                 :            :  * beside the main text, e.g. phonetic characters.
     612                 :            :  * --------------------------------------------------*/
     613                 :            : 
     614                 :        336 : SwRubyPortion::SwRubyPortion( const SwMultiCreator& rCreate, const SwFont& rFnt,
     615                 :            :                               const IDocumentSettingAccess& rIDocumentSettingAccess,
     616                 :            :                               xub_StrLen nEnd, xub_StrLen nOffs,
     617                 :            :                               const sal_Bool* pForceRubyPos )
     618                 :        336 :      : SwMultiPortion( nEnd )
     619                 :            : {
     620                 :        336 :     SetRuby();
     621                 :            :     OSL_ENSURE( SW_MC_RUBY == rCreate.nId, "Ruby expected" );
     622                 :            :     OSL_ENSURE( RES_TXTATR_CJK_RUBY == rCreate.pAttr->Which(), "Wrong attribute" );
     623                 :        336 :     const SwFmtRuby& rRuby = rCreate.pAttr->GetRuby();
     624                 :        336 :     nAdjustment = rRuby.GetAdjustment();
     625                 :        336 :     nRubyOffset = nOffs;
     626                 :            : 
     627                 :            :     // in grid mode we force the ruby text to the upper or lower line
     628         [ -  + ]:        336 :     if ( pForceRubyPos )
     629                 :          0 :         SetTop( *pForceRubyPos );
     630                 :            :     else
     631                 :        336 :         SetTop( ! rRuby.GetPosition() );
     632                 :            : 
     633         [ +  - ]:        336 :     const SwCharFmt* pFmt = ((SwTxtRuby*)rCreate.pAttr)->GetCharFmt();
     634                 :            :     SwFont *pRubyFont;
     635         [ +  - ]:        336 :     if( pFmt )
     636                 :            :     {
     637                 :        336 :         const SwAttrSet& rSet = pFmt->GetAttrSet();
     638 [ +  - ][ +  - ]:        336 :          pRubyFont = new SwFont( rFnt );
     639         [ +  - ]:        336 :         pRubyFont->SetDiffFnt( &rSet, &rIDocumentSettingAccess );
     640                 :            : 
     641                 :            :         // we do not allow a vertical font for the ruby text
     642 [ +  - ][ +  - ]:        336 :         pRubyFont->SetVertical( rFnt.GetOrientation() );
     643                 :            :     }
     644                 :            :     else
     645                 :          0 :         pRubyFont = NULL;
     646                 :            : 
     647         [ +  - ]:        336 :     String aStr( rRuby.GetText(), nOffs, STRING_LEN );
     648 [ +  - ][ +  - ]:        336 :     SwFldPortion *pFld = new SwFldPortion( aStr, pRubyFont );
     649                 :        336 :     pFld->SetNextOffset( nOffs );
     650                 :        336 :     pFld->SetFollow( sal_True );
     651                 :            : 
     652         [ +  + ]:        336 :     if( OnTop() )
     653                 :        280 :         GetRoot().SetPortion( pFld );
     654                 :            :     else
     655                 :            :     {
     656 [ +  - ][ +  - ]:         56 :         GetRoot().SetNext( new SwLineLayout() );
     657                 :         56 :         GetRoot().GetNext()->SetPortion( pFld );
     658                 :            :     }
     659                 :            : 
     660                 :            :     // ruby portions have the same direction as the frame directions
     661         [ -  + ]:        336 :     if ( rCreate.nLevel % 2 )
     662                 :            :     {
     663                 :            :         // switch right and left ruby adjustment in rtl environment
     664         [ #  # ]:          0 :         if ( 0 == nAdjustment )
     665                 :          0 :             nAdjustment = 2;
     666         [ #  # ]:          0 :         else if ( 2 == nAdjustment )
     667                 :          0 :             nAdjustment = 0;
     668                 :            : 
     669                 :          0 :         SetDirection( DIR_RIGHT2LEFT );
     670                 :            :     }
     671                 :            :     else
     672         [ +  - ]:        336 :         SetDirection( DIR_LEFT2RIGHT );
     673                 :        336 : }
     674                 :            : 
     675                 :            : /*--------------------------------------------------
     676                 :            :  * SwRubyPortion::_Adjust(..)
     677                 :            :  * In ruby portion there are different alignments for
     678                 :            :  * the ruby text and the main text.
     679                 :            :  * Left, right, centered and two possibilities of block adjustment
     680                 :            :  * The block adjustment is realized by spacing between the characteres,
     681                 :            :  * either with a half space or no space in front of the first letter and
     682                 :            :  * a half space at the end of the last letter.
     683                 :            :  * Notice: the smaller line will be manipulated, normally it's the ruby line,
     684                 :            :  * but it could be the main text, too.
     685                 :            :  * If there is a tabulator in smaller line, no adjustment is possible.
     686                 :            :  * --------------------------------------------------*/
     687                 :            : 
     688                 :         64 : void SwRubyPortion::_Adjust( SwTxtFormatInfo &rInf )
     689                 :            : {
     690                 :         64 :     SwTwips nLineDiff = GetRoot().Width() - GetRoot().GetNext()->Width();
     691                 :         64 :     xub_StrLen nOldIdx = rInf.GetIdx();
     692         [ -  + ]:         64 :     if( !nLineDiff )
     693                 :          0 :         return;
     694                 :            :     SwLineLayout *pCurr;
     695         [ +  + ]:         64 :     if( nLineDiff < 0 )
     696                 :            :     {   // The first line has to be adjusted.
     697         [ -  + ]:          8 :         if( GetTab1() )
     698                 :          0 :             return;
     699                 :          8 :         pCurr = &GetRoot();
     700                 :          8 :         nLineDiff = -nLineDiff;
     701                 :            :     }
     702                 :            :     else
     703                 :            :     {   // The second line has to be adjusted.
     704         [ -  + ]:         56 :         if( GetTab2() )
     705                 :          0 :             return;
     706                 :         56 :         pCurr = GetRoot().GetNext();
     707                 :         56 :         rInf.SetIdx( nOldIdx + GetRoot().GetLen() );
     708                 :            :     }
     709                 :         64 :     KSHORT nLeft = 0;   // the space in front of the first letter
     710                 :         64 :     KSHORT nRight = 0;  // the space at the end of the last letter
     711                 :         64 :     sal_uInt16 nSub = 0;
     712   [ +  -  -  -  :         64 :     switch ( nAdjustment )
                      - ]
     713                 :            :     {
     714                 :         64 :         case 1: nRight = static_cast<sal_uInt16>(nLineDiff / 2);    // no break
     715                 :         64 :         case 2: nLeft  = static_cast<sal_uInt16>(nLineDiff - nRight); break;
     716                 :          0 :         case 3: nSub   = 1; // no break
     717                 :            :         case 4:
     718                 :            :         {
     719                 :          0 :             xub_StrLen nCharCnt = 0;
     720                 :            :             SwLinePortion *pPor;
     721         [ #  # ]:          0 :             for( pPor = pCurr->GetFirstPortion(); pPor; pPor = pPor->GetPortion() )
     722                 :            :             {
     723         [ #  # ]:          0 :                 if( pPor->InTxtGrp() )
     724         [ #  # ]:          0 :                     ((SwTxtPortion*)pPor)->GetSpaceCnt( rInf, nCharCnt );
     725                 :          0 :                 rInf.SetIdx( rInf.GetIdx() + pPor->GetLen() );
     726                 :            :             }
     727         [ #  # ]:          0 :             if( nCharCnt > nSub )
     728                 :            :             {
     729                 :          0 :                 SwTwips nCalc = nLineDiff / ( nCharCnt - nSub );
     730                 :            :                 short nTmp;
     731         [ #  # ]:          0 :                 if( nCalc < SHRT_MAX )
     732                 :          0 :                     nTmp = -short(nCalc);
     733                 :            :                 else
     734                 :          0 :                     nTmp = SHRT_MIN;
     735                 :            : 
     736         [ #  # ]:          0 :                 pCurr->CreateSpaceAdd( SPACING_PRECISION_FACTOR * nTmp );
     737                 :          0 :                 nLineDiff -= nCalc * ( nCharCnt - 1 );
     738                 :            :             }
     739         [ #  # ]:          0 :             if( nLineDiff > 1 )
     740                 :            :             {
     741                 :          0 :                 nRight = static_cast<sal_uInt16>(nLineDiff / 2);
     742                 :          0 :                 nLeft  = static_cast<sal_uInt16>(nLineDiff - nRight);
     743                 :            :             }
     744                 :            :             break;
     745                 :            :         }
     746                 :            :         default: OSL_FAIL( "New ruby adjustment" );
     747                 :            :     }
     748 [ -  + ][ #  # ]:         64 :     if( nLeft || nRight )
     749                 :            :     {
     750         [ -  + ]:         64 :         if( !pCurr->GetPortion() )
     751         [ #  # ]:          0 :             pCurr->SetPortion( new SwTxtPortion( *pCurr ) );
     752         [ +  - ]:         64 :         SwMarginPortion *pMarg = new SwMarginPortion( 0 );
     753         [ +  - ]:         64 :         if( nLeft )
     754                 :            :         {
     755                 :         64 :             pMarg->AddPrtWidth( nLeft );
     756                 :         64 :             pMarg->SetPortion( pCurr->GetPortion() );
     757                 :         64 :             pCurr->SetPortion( pMarg );
     758                 :            :         }
     759         [ +  - ]:         64 :         if( nRight )
     760                 :            :         {
     761         [ +  - ]:         64 :             pMarg = new SwMarginPortion( 0 );
     762                 :         64 :             pMarg->AddPrtWidth( nRight );
     763                 :         64 :             pCurr->FindLastPortion()->Append( pMarg );
     764                 :            :         }
     765                 :            :     }
     766                 :            : 
     767                 :         64 :     pCurr->Width( Width() );
     768                 :         64 :     rInf.SetIdx( nOldIdx );
     769                 :            : }
     770                 :            : 
     771                 :            : /*--------------------------------------------------
     772                 :            :  * CalcRubyOffset()
     773                 :            :  * has to change the nRubyOffset, if there's a fieldportion
     774                 :            :  * in the phonetic line.
     775                 :            :  * The nRubyOffset is the position in the rubystring, where the
     776                 :            :  * next SwRubyPortion has start the displaying of the phonetics.
     777                 :            :  * --------------------------------------------------*/
     778                 :            : 
     779                 :        336 : void SwRubyPortion::CalcRubyOffset()
     780                 :            : {
     781                 :        336 :     const SwLineLayout *pCurr = &GetRoot();
     782         [ +  + ]:        336 :     if( !OnTop() )
     783                 :            :     {
     784                 :         56 :         pCurr = pCurr->GetNext();
     785         [ -  + ]:         56 :         if( !pCurr )
     786                 :        336 :             return;
     787                 :            :     }
     788                 :        336 :     const SwLinePortion *pPor = pCurr->GetFirstPortion();
     789                 :        336 :     const SwFldPortion *pFld = NULL;
     790         [ +  + ]:        800 :     while( pPor )
     791                 :            :     {
     792         [ +  + ]:        464 :         if( pPor->InFldGrp() )
     793                 :        336 :             pFld = (SwFldPortion*)pPor;
     794                 :        464 :         pPor = pPor->GetPortion();
     795                 :            :     }
     796         [ +  - ]:        336 :     if( pFld )
     797                 :            :     {
     798         [ -  + ]:        336 :         if( pFld->HasFollow() )
     799                 :          0 :             nRubyOffset = pFld->GetNextOffset();
     800                 :            :         else
     801                 :        336 :             nRubyOffset = STRING_LEN;
     802                 :            :     }
     803                 :            : }
     804                 :            : 
     805                 :            : /*--------------------------------------------------
     806                 :            :  * SwTxtSizeInfo::GetMultiCreator(..)
     807                 :            :  * If we (e.g. the position rPos) are inside a two-line-attribute or
     808                 :            :  * a ruby-attribute, the attribute will be returned in a SwMultiCreator-struct,
     809                 :            :  * otherwise the function returns zero.
     810                 :            :  * The rPos parameter is set to the end of the multiportion,
     811                 :            :  * normally this is the end of the attribute,
     812                 :            :  * but sometimes it is the start of another attribute, which finished or
     813                 :            :  * interrupts the first attribute.
     814                 :            :  * E.g. a ruby portion interrupts a 2-line-attribute, a 2-line-attribute
     815                 :            :  * with different brackets interrupts another 2-line-attribute.
     816                 :            :  * --------------------------------------------------*/
     817                 :            : 
     818                 :            : /*--------------------------------------------------
     819                 :            :  * lcl_Has2Lines(..)
     820                 :            :  * is a little help function for GetMultiCreator(..)
     821                 :            :  * It extracts the 2-line-format from a 2-line-attribute or a character style.
     822                 :            :  * The rValue is set to sal_True, if the 2-line-attribute's value is set and
     823                 :            :  * no 2-line-format reference is passed. If there is a 2-line-format reference,
     824                 :            :  * then the rValue is set only, if the 2-line-attribute's value is set _and_
     825                 :            :  * the 2-line-formats has the same brackets.
     826                 :            :  * --------------------------------------------------*/
     827                 :            : 
     828                 :       2764 : sal_Bool lcl_Has2Lines( const SwTxtAttr& rAttr, const SvxTwoLinesItem* &rpRef,
     829                 :            :     sal_Bool &rValue )
     830                 :            : {
     831                 :       2764 :     const SfxPoolItem* pItem = CharFmt::GetItem( rAttr, RES_CHRATR_TWO_LINES );
     832         [ +  + ]:       2764 :     if( pItem )
     833                 :            :     {
     834                 :        108 :         rValue = ((SvxTwoLinesItem*)pItem)->GetValue();
     835         [ +  + ]:        108 :         if( !rpRef )
     836                 :         88 :             rpRef = (SvxTwoLinesItem*)pItem;
     837   [ +  -  -  + ]:         60 :         else if( ((SvxTwoLinesItem*)pItem)->GetEndBracket() !=
                 [ -  + ]
     838                 :         20 :                     rpRef->GetEndBracket() ||
     839                 :         20 :                     ((SvxTwoLinesItem*)pItem)->GetStartBracket() !=
     840                 :         20 :                     rpRef->GetStartBracket() )
     841                 :          0 :             rValue = sal_False;
     842                 :        108 :         return sal_True;
     843                 :            :     }
     844                 :       2764 :     return sal_False;
     845                 :            : }
     846                 :            : 
     847                 :            : /*--------------------------------------------------
     848                 :            :  * lcl_HasRotation(..)
     849                 :            :  * is a little help function for GetMultiCreator(..)
     850                 :            :  * It extracts the charrotation from a charrotate-attribute or a character style.
     851                 :            :  * The rValue is set to sal_True, if the charrotate-attribute's value is set and
     852                 :            :  * no charrotate-format reference is passed.
     853                 :            :  * If there is a charrotate-format reference, then the rValue is set only,
     854                 :            :  * if the charrotate-attribute's value is set _and_ identical
     855                 :            :  * to the charrotate-format's value.
     856                 :            :  * --------------------------------------------------*/
     857                 :            : 
     858                 :       2724 : sal_Bool lcl_HasRotation( const SwTxtAttr& rAttr,
     859                 :            :     const SvxCharRotateItem* &rpRef, sal_Bool &rValue )
     860                 :            : {
     861                 :       2724 :     const SfxPoolItem* pItem = CharFmt::GetItem( rAttr, RES_CHRATR_ROTATE );
     862         [ +  + ]:       2724 :     if ( pItem )
     863                 :            :     {
     864                 :         52 :         rValue = 0 != ((SvxCharRotateItem*)pItem)->GetValue();
     865         [ +  - ]:         52 :         if( !rpRef )
     866                 :         52 :             rpRef = (SvxCharRotateItem*)pItem;
     867         [ #  # ]:          0 :         else if( ((SvxCharRotateItem*)pItem)->GetValue() !=
     868                 :          0 :                     rpRef->GetValue() )
     869                 :          0 :             rValue = sal_False;
     870                 :         52 :         return sal_True;
     871                 :            :     }
     872                 :            : 
     873                 :       2724 :     return sal_False;
     874                 :            : }
     875                 :            : 
     876                 :      65441 : SwMultiCreator* SwTxtSizeInfo::GetMultiCreator( xub_StrLen &rPos,
     877                 :            :                                                 SwMultiPortion* pMulti ) const
     878                 :            : {
     879                 :      65441 :     SwScriptInfo& rSI = ((SwParaPortion*)GetParaPortion())->GetScriptInfo();
     880                 :            : 
     881                 :            :     // get the last embedding level
     882                 :            :     sal_uInt8 nCurrLevel;
     883         [ -  + ]:      65441 :     if ( pMulti )
     884                 :            :     {
     885                 :            :         OSL_ENSURE( pMulti->IsBidi(), "Nested MultiPortion is not BidiPortion" );
     886                 :            :         // level associated with bidi-portion;
     887                 :          0 :         nCurrLevel = ((SwBidiPortion*)pMulti)->GetLevel();
     888                 :            :     }
     889                 :            :     else
     890                 :            :         // no nested bidi portion required
     891 [ +  - ][ -  + ]:      65441 :         nCurrLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
     892                 :            : 
     893                 :            :     // check if there is a field at rPos:
     894                 :      65441 :     sal_uInt8 nNextLevel = nCurrLevel;
     895                 :      65441 :     sal_Bool bFldBidi = sal_False;
     896                 :            : 
     897         [ +  + ]:      65441 :     if ( CH_TXTATR_BREAKWORD == GetChar( rPos ) )
     898                 :            :     {
     899                 :       2089 :         bFldBidi = sal_True;
     900                 :            : /*
     901                 :            :         // examining the script of the field text should be sufficient
     902                 :            :         // for 99% of all cases
     903                 :            :         XubString aTxt = GetTxtFrm()->GetTxtNode()->GetExpandTxt( rPos, 1 );
     904                 :            : 
     905                 :            :         if ( pBreakIt->GetBreakIter().is() && aTxt.Len() )
     906                 :            :         {
     907                 :            :             sal_Bool bFldDir = ( i18n::ScriptType::COMPLEX ==
     908                 :            :                                  pBreakIt->GetRealScriptOfText( aTxt, 0 ) );
     909                 :            :             sal_Bool bCurrDir = ( 0 != ( nCurrLevel % 2 ) );
     910                 :            :             if ( bFldDir != bCurrDir )
     911                 :            :             {
     912                 :            :                 nNextLevel = nCurrLevel + 1;
     913                 :            :                 bFldBidi = sal_True;
     914                 :            :             }
     915                 :            :         }*/
     916                 :            :     }
     917                 :            :     else
     918         [ +  - ]:      63352 :         nNextLevel = rSI.DirType( rPos );
     919                 :            : 
     920 [ +  + ][ -  + ]:      65441 :     if ( GetTxt().Len() != rPos && nNextLevel > nCurrLevel )
                 [ -  + ]
     921                 :            :     {
     922 [ #  # ][ #  # ]:          0 :         rPos = bFldBidi ? rPos + 1 : rSI.NextDirChg( rPos, &nCurrLevel );
     923         [ #  # ]:          0 :         if ( STRING_LEN == rPos )
     924                 :          0 :             return NULL;
     925         [ #  # ]:          0 :         SwMultiCreator *pRet = new SwMultiCreator;
     926                 :          0 :         pRet->pItem = NULL;
     927                 :          0 :         pRet->pAttr = NULL;
     928                 :          0 :         pRet->nId = SW_MC_BIDI;
     929                 :          0 :         pRet->nLevel = nCurrLevel + 1;
     930                 :          0 :         return pRet;
     931                 :            :     }
     932                 :            : 
     933                 :            :     // a bidi portion can only contain other bidi portions
     934         [ -  + ]:      65441 :     if ( pMulti )
     935                 :          0 :         return NULL;
     936                 :            : 
     937                 :      65441 :     const SvxCharRotateItem* pRotate = NULL;
     938                 :            :     const SfxPoolItem* pRotItem;
     939         [ +  - ]:     131176 :     if( SFX_ITEM_SET == pFrm->GetTxtNode()->GetSwAttrSet().
           [ +  +  +  - ]
                 [ +  + ]
     940         [ +  - ]:      65441 :         GetItemState( RES_CHRATR_ROTATE, sal_True, &pRotItem ) &&
     941                 :        294 :         ((SvxCharRotateItem*)pRotItem)->GetValue() )
     942                 :        294 :         pRotate = (SvxCharRotateItem*)pRotItem;
     943                 :            :     else
     944                 :      65147 :         pRotItem = NULL;
     945                 :      65441 :     const SvxTwoLinesItem* p2Lines = NULL;
     946                 :      65441 :     const SwTxtNode *pLclTxtNode = pFrm->GetTxtNode();
     947         [ -  + ]:      65441 :     if( !pLclTxtNode )
     948                 :          0 :         return NULL;
     949                 :            :     const SfxPoolItem* pItem;
     950         [ +  - ]:     131394 :     if( SFX_ITEM_SET == pLclTxtNode->GetSwAttrSet().
           [ +  +  +  - ]
                 [ +  + ]
     951         [ +  - ]:      65441 :         GetItemState( RES_CHRATR_TWO_LINES, sal_True, &pItem ) &&
     952                 :        512 :         ((SvxTwoLinesItem*)pItem)->GetValue() )
     953                 :        512 :         p2Lines = (SvxTwoLinesItem*)pItem;
     954                 :            :     else
     955                 :      64929 :         pItem = NULL;
     956                 :            : 
     957                 :      65441 :     const SwpHints *pHints = pLclTxtNode->GetpSwpHints();
     958 [ +  + ][ +  - ]:      65441 :     if( !pHints && !p2Lines && !pRotate )
                 [ +  + ]
     959                 :      57379 :         return NULL;
     960                 :       8062 :     const SwTxtAttr *pRuby = NULL;
     961                 :       8062 :     sal_Bool bTwo = sal_False;
     962                 :       8062 :     sal_Bool bRot = sal_False;
     963                 :       8062 :     sal_uInt16 n2Lines = USHRT_MAX;
     964                 :       8062 :     sal_uInt16 nRotate = USHRT_MAX;
     965         [ +  + ]:       8062 :     sal_uInt16 nCount = pHints ? pHints->Count() : 0;
     966                 :            :     sal_uInt16 i;
     967         [ +  + ]:      21876 :     for( i = 0; i < nCount; ++i )
     968                 :            :     {
     969         [ +  - ]:      16072 :         const SwTxtAttr *pTmp = (*pHints)[i];
     970                 :      16072 :         xub_StrLen nStart = *pTmp->GetStart();
     971         [ +  + ]:      16072 :         if( rPos < nStart )
     972                 :       2258 :             break;
     973 [ +  - ][ +  + ]:      13814 :         if( *pTmp->GetAnyEnd() > rPos )
     974                 :            :         {
     975 [ +  - ][ +  + ]:       3060 :             if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
     976                 :        336 :                 pRuby = pTmp;
     977                 :            :             else
     978                 :            :             {
     979                 :       2724 :                 const SvxCharRotateItem* pRoTmp = NULL;
     980 [ +  - ][ +  + ]:       2724 :                 if( lcl_HasRotation( *pTmp, pRoTmp, bRot ) )
     981                 :            :                 {
     982         [ +  - ]:         52 :                     nRotate = bRot ? i : nCount;
     983                 :         52 :                     pRotate = pRoTmp;
     984                 :            :                 }
     985                 :       2724 :                 const SvxTwoLinesItem* p2Tmp = NULL;
     986 [ +  - ][ +  + ]:       2724 :                 if( lcl_Has2Lines( *pTmp, p2Tmp, bTwo ) )
     987                 :            :                 {
     988         [ +  - ]:         88 :                     n2Lines = bTwo ? i : nCount;
     989                 :       2724 :                     p2Lines = p2Tmp;
     990                 :            :                 }
     991                 :            :             }
     992                 :            :         }
     993                 :            :     }
     994         [ +  + ]:       8062 :     if( pRuby )
     995                 :            :     {   // The winner is ... a ruby attribute and so
     996                 :            :         // the end of the multiportion is the end of the ruby attribute.
     997         [ +  - ]:        336 :         rPos = *pRuby->GetEnd();
     998         [ +  - ]:        336 :         SwMultiCreator *pRet = new SwMultiCreator;
     999                 :        336 :         pRet->pItem = NULL;
    1000                 :        336 :         pRet->pAttr = pRuby;
    1001                 :        336 :         pRet->nId = SW_MC_RUBY;
    1002 [ +  - ][ -  + ]:        336 :         pRet->nLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
    1003                 :        336 :         return pRet;
    1004                 :            :     }
    1005 [ +  + ][ +  + ]:       8238 :     if( n2Lines < nCount || ( pItem && pItem == p2Lines &&
           [ +  -  -  + ]
                 [ +  + ]
    1006                 :        512 :         rPos < GetTxt().Len() ) )
    1007                 :            :     {   // The winner is a 2-line-attribute,
    1008                 :            :         // the end of the multiportion depends on the following attributes...
    1009         [ +  - ]:         20 :         SwMultiCreator *pRet = new SwMultiCreator;
    1010                 :            : 
    1011                 :            :         // We note the endpositions of the 2-line attributes in aEnd as stack
    1012         [ +  - ]:         20 :         SvXub_StrLens aEnd;
    1013                 :            : 
    1014                 :            :         // The bOn flag signs the state of the last 2-line attribute in the
    1015                 :            :         // aEnd-stack, it is compatible with the winner-attribute or
    1016                 :            :         // it interrupts the other attribute.
    1017                 :         20 :         sal_Bool bOn = sal_True;
    1018                 :            : 
    1019         [ +  - ]:         20 :         if( n2Lines < nCount )
    1020                 :            :         {
    1021                 :         20 :             pRet->pItem = NULL;
    1022         [ +  - ]:         20 :             pRet->pAttr = (*pHints)[n2Lines];
    1023 [ +  - ][ +  - ]:         20 :             aEnd.push_front( *pRet->pAttr->GetEnd() );
    1024         [ -  + ]:         20 :             if( pItem )
    1025                 :            :             {
    1026         [ #  # ]:          0 :                 aEnd.front() = GetTxt().Len();
    1027                 :          0 :                 bOn = ((SvxTwoLinesItem*)pItem)->GetEndBracket() ==
    1028                 :          0 :                         p2Lines->GetEndBracket() &&
    1029                 :          0 :                       ((SvxTwoLinesItem*)pItem)->GetStartBracket() ==
    1030   [ #  #  #  # ]:          0 :                         p2Lines->GetStartBracket();
    1031                 :            :             }
    1032                 :            :         }
    1033                 :            :         else
    1034                 :            :         {
    1035                 :          0 :             pRet->pItem = pItem;
    1036                 :          0 :             pRet->pAttr = NULL;
    1037         [ #  # ]:          0 :             aEnd.push_front( GetTxt().Len() );
    1038                 :            :         }
    1039                 :         20 :         pRet->nId = SW_MC_DOUBLE;
    1040 [ +  - ][ -  + ]:         20 :         pRet->nLevel = GetTxtFrm()->IsRightToLeft() ? 1 : 0;
    1041                 :            : 
    1042                 :            :         // n2Lines is the index of the last 2-line-attribute, which contains
    1043                 :            :         // the actual position.
    1044                 :         20 :         i = 0;
    1045                 :            :         // At this moment we know that at position rPos the "winner"-attribute
    1046                 :            :         // causes a 2-line-portion. The end of the attribute is the end of the
    1047                 :            :         // portion, if there's no interrupting attribute.
    1048                 :            :         // There are two kinds of interruptors:
    1049                 :            :         // - ruby attributes stops the 2-line-attribute, the end of the
    1050                 :            :         //   multiline is the start of the ruby attribute
    1051                 :            :         // - 2-line-attributes with value "Off" or with different brackets,
    1052                 :            :         //   these attributes may interrupt the winner, but they could be
    1053                 :            :         //   neutralized by another 2-line-attribute starting at the same
    1054                 :            :         //   position with the same brackets as the winner-attribute.
    1055                 :            : 
    1056                 :            :         // In the following loop rPos is the critical position and it will be
    1057                 :            :         // evaluated, if at rPos starts a interrupting or a maintaining
    1058                 :            :         // continuity attribute.
    1059         [ +  + ]:         60 :         while( i < nCount )
    1060                 :            :         {
    1061         [ +  - ]:         40 :             const SwTxtAttr *pTmp = (*pHints)[i++];
    1062 [ +  - ][ -  + ]:         40 :             if( *pTmp->GetAnyEnd() <= rPos )
    1063                 :          0 :                 continue;
    1064         [ -  + ]:         40 :             if( rPos < *pTmp->GetStart() )
    1065                 :            :             {
    1066                 :            :                 // If bOn is sal_False and the next attribute starts later than rPos
    1067                 :            :                 // the winner attribute is interrupted at rPos.
    1068                 :            :                 // If the start of the next atribute is behind the end of
    1069                 :            :                 // the last attribute on the aEnd-stack, this is the endposition
    1070                 :            :                 // on the stack is the end of the 2-line portion.
    1071 [ #  # ][ #  # ]:          0 :                 if( !bOn || aEnd.back() < *pTmp->GetStart() )
         [ #  # ][ #  # ]
    1072                 :          0 :                     break;
    1073                 :            :                 // At this moment, bOn is sal_True and the next attribute starts
    1074                 :            :                 // behind rPos, so we could move rPos to the next startpoint
    1075                 :          0 :                 rPos = *pTmp->GetStart();
    1076                 :            :                 // We clean up the aEnd-stack, endpositions equal to rPos are
    1077                 :            :                 // superfluous.
    1078 [ #  # ][ #  # ]:          0 :                 while( !aEnd.empty() && aEnd.back() <= rPos )
         [ #  # ][ #  # ]
    1079                 :            :                 {
    1080                 :          0 :                     bOn = !bOn;
    1081         [ #  # ]:          0 :                     aEnd.pop_back();
    1082                 :            :                 }
    1083                 :            :                 // If the endstack is empty, we simulate an attribute with
    1084                 :            :                 // state sal_True and endposition rPos
    1085         [ #  # ]:          0 :                 if( aEnd.empty() )
    1086                 :            :                 {
    1087         [ #  # ]:          0 :                     aEnd.push_front( rPos );
    1088                 :          0 :                     bOn = sal_True;
    1089                 :            :                 }
    1090                 :            :             }
    1091                 :            :             // A ruby attribute stops the 2-line immediately
    1092 [ +  - ][ -  + ]:         40 :             if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
    1093                 :          0 :                 return pRet;
    1094 [ +  - ][ +  + ]:         40 :             if( lcl_Has2Lines( *pTmp, p2Lines, bTwo ) )
    1095                 :            :             {   // We have an interesting attribute..
    1096         [ +  - ]:         20 :                 if( bTwo == bOn )
    1097                 :            :                 {   // .. with the same state, so the last attribute could
    1098                 :            :                     // be continued.
    1099 [ +  - ][ +  - ]:         20 :                     if( aEnd.back() < *pTmp->GetEnd() )
                 [ -  + ]
    1100 [ #  # ][ #  # ]:          0 :                         aEnd.back() = *pTmp->GetEnd();
    1101                 :            :                 }
    1102                 :            :                 else
    1103                 :            :                 {   // .. with a different state.
    1104                 :          0 :                     bOn = bTwo;
    1105                 :            :                     // If this is smaller than the last on the stack, we put
    1106                 :            :                     // it on the stack. If it has the same endposition, the last
    1107                 :            :                     // could be removed.
    1108 [ #  # ][ #  # ]:          0 :                     if( aEnd.back() > *pTmp->GetEnd() )
                 [ #  # ]
    1109 [ #  # ][ #  # ]:          0 :                         aEnd.push_back( *pTmp->GetEnd() );
    1110         [ #  # ]:          0 :                     else if( aEnd.size() > 1 )
    1111         [ #  # ]:          0 :                         aEnd.pop_back();
    1112                 :            :                     else
    1113 [ #  # ][ #  # ]:          0 :                         aEnd.back() = *pTmp->GetEnd();
    1114                 :            :                 }
    1115                 :            :             }
    1116                 :            :         }
    1117 [ +  - ][ +  - ]:         20 :         if( bOn && !aEnd.empty() )
                 [ +  - ]
    1118         [ +  - ]:         20 :             rPos = aEnd.back();
    1119                 :         20 :         return pRet;
    1120                 :            :     }
    1121 [ +  - ][ +  + ]:       8000 :     if( nRotate < nCount || ( pRotItem && pRotItem == pRotate &&
           [ +  -  -  + ]
                 [ -  + ]
    1122                 :        294 :         rPos < GetTxt().Len() ) )
    1123                 :            :     {   // The winner is a rotate-attribute,
    1124                 :            :         // the end of the multiportion depends on the following attributes...
    1125         [ #  # ]:          0 :         SwMultiCreator *pRet = new SwMultiCreator;
    1126                 :          0 :         pRet->nId = SW_MC_ROTATE;
    1127                 :            : 
    1128                 :            :         // We note the endpositions of the 2-line attributes in aEnd as stack
    1129         [ #  # ]:          0 :         SvXub_StrLens aEnd;
    1130                 :            : 
    1131                 :            :         // The bOn flag signs the state of the last 2-line attribute in the
    1132                 :            :         // aEnd-stack, which could interrupts the winning rotation attribute.
    1133         [ #  # ]:          0 :         sal_Bool bOn = pItem ? sal_True : sal_False;
    1134         [ #  # ]:          0 :         aEnd.push_front( GetTxt().Len() );
    1135                 :            :         // n2Lines is the index of the last 2-line-attribute, which contains
    1136                 :            :         // the actual position.
    1137                 :          0 :         i = 0;
    1138                 :          0 :         xub_StrLen n2Start = rPos;
    1139         [ #  # ]:          0 :         while( i < nCount )
    1140                 :            :         {
    1141         [ #  # ]:          0 :             const SwTxtAttr *pTmp = (*pHints)[i++];
    1142 [ #  # ][ #  # ]:          0 :             if( *pTmp->GetAnyEnd() <= n2Start )
    1143                 :          0 :                 continue;
    1144         [ #  # ]:          0 :             if( n2Start < *pTmp->GetStart() )
    1145                 :            :             {
    1146 [ #  # ][ #  # ]:          0 :                 if( bOn || aEnd.back() < *pTmp->GetStart() )
         [ #  # ][ #  # ]
    1147                 :          0 :                     break;
    1148                 :          0 :                 n2Start = *pTmp->GetStart();
    1149 [ #  # ][ #  # ]:          0 :                 while( !aEnd.empty() && aEnd.back() <= n2Start )
         [ #  # ][ #  # ]
    1150                 :            :                 {
    1151                 :          0 :                     bOn = !bOn;
    1152         [ #  # ]:          0 :                     aEnd.pop_back();
    1153                 :            :                 }
    1154         [ #  # ]:          0 :                 if( aEnd.empty() )
    1155                 :            :                 {
    1156         [ #  # ]:          0 :                     aEnd.push_front( n2Start );
    1157                 :          0 :                     bOn = sal_False;
    1158                 :            :                 }
    1159                 :            :             }
    1160                 :            :             // A ruby attribute stops immediately
    1161 [ #  # ][ #  # ]:          0 :             if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
    1162                 :            :             {
    1163                 :          0 :                 bOn = sal_True;
    1164                 :          0 :                 break;
    1165                 :            :             }
    1166                 :          0 :             p2Lines = NULL;
    1167 [ #  # ][ #  # ]:          0 :             if( lcl_Has2Lines( *pTmp, p2Lines, bTwo ) )
    1168                 :            :             {
    1169         [ #  # ]:          0 :                 if( bTwo == bOn )
    1170                 :            :                 {
    1171 [ #  # ][ #  # ]:          0 :                     if( aEnd.back() < *pTmp->GetEnd() )
                 [ #  # ]
    1172 [ #  # ][ #  # ]:          0 :                         aEnd.back() = *pTmp->GetEnd();
    1173                 :            :                 }
    1174                 :            :                 else
    1175                 :            :                 {
    1176                 :          0 :                     bOn = bTwo;
    1177 [ #  # ][ #  # ]:          0 :                     if( aEnd.back() > *pTmp->GetEnd() )
                 [ #  # ]
    1178 [ #  # ][ #  # ]:          0 :                         aEnd.push_back( *pTmp->GetEnd() );
    1179         [ #  # ]:          0 :                     else if( aEnd.size() > 1 )
    1180         [ #  # ]:          0 :                         aEnd.pop_back();
    1181                 :            :                     else
    1182 [ #  # ][ #  # ]:          0 :                         aEnd.back() = *pTmp->GetEnd();
    1183                 :            :                 }
    1184                 :            :             }
    1185                 :            :         }
    1186 [ #  # ][ #  # ]:          0 :         if( !bOn && !aEnd.empty() )
                 [ #  # ]
    1187         [ #  # ]:          0 :             n2Start = aEnd.back();
    1188                 :            : 
    1189         [ #  # ]:          0 :         if( !aEnd.empty() )
    1190                 :          0 :             aEnd.clear();
    1191                 :            : 
    1192                 :          0 :         bOn = sal_True;
    1193         [ #  # ]:          0 :         if( nRotate < nCount )
    1194                 :            :         {
    1195                 :          0 :             pRet->pItem = NULL;
    1196         [ #  # ]:          0 :             pRet->pAttr = (*pHints)[nRotate];
    1197 [ #  # ][ #  # ]:          0 :             aEnd.push_front( *pRet->pAttr->GetEnd() );
    1198         [ #  # ]:          0 :             if( pRotItem )
    1199                 :            :             {
    1200         [ #  # ]:          0 :                 aEnd.front() = GetTxt().Len();
    1201                 :          0 :                 bOn = ((SvxCharRotateItem*)pRotItem)->GetValue() ==
    1202                 :          0 :                         pRotate->GetValue();
    1203                 :            :             }
    1204                 :            :         }
    1205                 :            :         else
    1206                 :            :         {
    1207                 :          0 :             pRet->pItem = pRotItem;
    1208                 :          0 :             pRet->pAttr = NULL;
    1209         [ #  # ]:          0 :             aEnd.push_front( GetTxt().Len() );
    1210                 :            :         }
    1211                 :          0 :         i = 0;
    1212         [ #  # ]:          0 :         while( i < nCount )
    1213                 :            :         {
    1214         [ #  # ]:          0 :             const SwTxtAttr *pTmp = (*pHints)[i++];
    1215 [ #  # ][ #  # ]:          0 :             if( *pTmp->GetAnyEnd() <= rPos )
    1216                 :          0 :                 continue;
    1217         [ #  # ]:          0 :             if( rPos < *pTmp->GetStart() )
    1218                 :            :             {
    1219 [ #  # ][ #  # ]:          0 :                 if( !bOn || aEnd.back() < *pTmp->GetStart() )
         [ #  # ][ #  # ]
    1220                 :          0 :                     break;
    1221                 :          0 :                 rPos = *pTmp->GetStart();
    1222 [ #  # ][ #  # ]:          0 :                 while( !aEnd.empty() && aEnd.back() <= rPos )
         [ #  # ][ #  # ]
    1223                 :            :                 {
    1224                 :          0 :                     bOn = !bOn;
    1225         [ #  # ]:          0 :                     aEnd.pop_back();
    1226                 :            :                 }
    1227         [ #  # ]:          0 :                 if( aEnd.empty() )
    1228                 :            :                 {
    1229         [ #  # ]:          0 :                     aEnd.push_front( rPos );
    1230                 :          0 :                     bOn = sal_True;
    1231                 :            :                 }
    1232                 :            :             }
    1233 [ #  # ][ #  # ]:          0 :             if( RES_TXTATR_CJK_RUBY == pTmp->Which() )
    1234                 :            :             {
    1235                 :          0 :                 bOn = sal_False;
    1236                 :          0 :                 break;
    1237                 :            :             }
    1238 [ #  # ][ #  # ]:          0 :             if( lcl_HasRotation( *pTmp, pRotate, bTwo ) )
    1239                 :            :             {
    1240         [ #  # ]:          0 :                 if( bTwo == bOn )
    1241                 :            :                 {
    1242 [ #  # ][ #  # ]:          0 :                     if( aEnd.back() < *pTmp->GetEnd() )
                 [ #  # ]
    1243 [ #  # ][ #  # ]:          0 :                         aEnd.back() = *pTmp->GetEnd();
    1244                 :            :                 }
    1245                 :            :                 else
    1246                 :            :                 {
    1247                 :          0 :                     bOn = bTwo;
    1248 [ #  # ][ #  # ]:          0 :                     if( aEnd.back() > *pTmp->GetEnd() )
                 [ #  # ]
    1249 [ #  # ][ #  # ]:          0 :                         aEnd.push_back( *pTmp->GetEnd() );
    1250         [ #  # ]:          0 :                     else if( aEnd.size() > 1 )
    1251         [ #  # ]:          0 :                         aEnd.pop_back();
    1252                 :            :                     else
    1253 [ #  # ][ #  # ]:          0 :                         aEnd.back() = *pTmp->GetEnd();
    1254                 :            :                 }
    1255                 :            :             }
    1256                 :            :         }
    1257 [ #  # ][ #  # ]:          0 :         if( bOn && !aEnd.empty() )
                 [ #  # ]
    1258         [ #  # ]:          0 :             rPos = aEnd.back();
    1259         [ #  # ]:          0 :         if( rPos > n2Start )
    1260                 :          0 :             rPos = n2Start;
    1261                 :          0 :         return pRet;
    1262                 :            :     }
    1263                 :      65441 :     return NULL;
    1264                 :            : }
    1265                 :            : 
    1266                 :            : /*--------------------------------------------------
    1267                 :            :  * SwSpaceManipulator
    1268                 :            :  * is a little helper class to manage the spaceadd-arrays of the text adjustment
    1269                 :            :  * during a PaintMultiPortion.
    1270                 :            :  * The constructor prepares the array for the first line of multiportion,
    1271                 :            :  * the SecondLine-function restores the values for the first line and prepares
    1272                 :            :  * the second line.
    1273                 :            :  * The destructor restores the values of the last manipulation.
    1274                 :            :  * --------------------------------------------------*/
    1275                 :            : 
    1276                 :            : class SwSpaceManipulator
    1277                 :            : {
    1278                 :            :     SwTxtPaintInfo& rInfo;
    1279                 :            :     SwMultiPortion& rMulti;
    1280                 :            :     std::vector<long>* pOldSpaceAdd;
    1281                 :            :     MSHORT nOldSpIdx;
    1282                 :            :     long nSpaceAdd;
    1283                 :            :     sal_Bool bSpaceChg  : 1;
    1284                 :            :     sal_uInt8 nOldDir   : 2;
    1285                 :            : public:
    1286                 :            :     SwSpaceManipulator( SwTxtPaintInfo& rInf, SwMultiPortion& rMult );
    1287                 :            :     ~SwSpaceManipulator();
    1288                 :            :     void SecondLine();
    1289                 :         20 :     inline long GetSpaceAdd() const { return nSpaceAdd; }
    1290                 :            : };
    1291                 :            : 
    1292                 :        392 : SwSpaceManipulator::SwSpaceManipulator( SwTxtPaintInfo& rInf,
    1293                 :            :                                         SwMultiPortion& rMult ) :
    1294                 :        392 :          rInfo( rInf ), rMulti( rMult )
    1295                 :            : {
    1296                 :        392 :     pOldSpaceAdd = rInfo.GetpSpaceAdd();
    1297                 :        392 :     nOldSpIdx = rInfo.GetSpaceIdx();
    1298                 :        392 :     nOldDir = rInfo.GetDirection();
    1299                 :        392 :     rInfo.SetDirection( rMulti.GetDirection() );
    1300                 :        392 :     bSpaceChg = sal_False;
    1301                 :            : 
    1302         [ +  + ]:        392 :     if( rMulti.IsDouble() )
    1303                 :            :     {
    1304                 :          0 :         nSpaceAdd = ( pOldSpaceAdd && !rMulti.HasTabulator() ) ?
    1305   [ -  +  #  # ]:         28 :                       rInfo.GetSpaceAdd() : 0;
    1306         [ -  + ]:         28 :         if( rMulti.GetRoot().IsSpaceAdd() )
    1307                 :            :         {
    1308                 :          0 :             rInfo.SetpSpaceAdd( rMulti.GetRoot().GetpLLSpaceAdd() );
    1309                 :          0 :             rInfo.ResetSpaceIdx();
    1310                 :          0 :             bSpaceChg = rMulti.ChgSpaceAdd( &rMulti.GetRoot(), nSpaceAdd );
    1311                 :            :         }
    1312         [ -  + ]:         28 :         else if( rMulti.HasTabulator() )
    1313                 :          0 :             rInfo.SetpSpaceAdd( NULL );
    1314                 :            :     }
    1315         [ +  - ]:        364 :     else if ( ! rMulti.IsBidi() )
    1316                 :            :     {
    1317                 :        364 :         rInfo.SetpSpaceAdd( rMulti.GetRoot().GetpLLSpaceAdd() );
    1318                 :        364 :         rInfo.ResetSpaceIdx();
    1319                 :            :     }
    1320                 :        392 : }
    1321                 :            : 
    1322                 :        392 : void SwSpaceManipulator::SecondLine()
    1323                 :            : {
    1324         [ -  + ]:        392 :     if( bSpaceChg )
    1325                 :            :     {
    1326                 :          0 :         rInfo.RemoveFirstSpaceAdd();
    1327                 :          0 :         bSpaceChg = sal_False;
    1328                 :            :     }
    1329                 :        392 :     SwLineLayout *pLay = rMulti.GetRoot().GetNext();
    1330         [ +  + ]:        392 :     if( pLay->IsSpaceAdd() )
    1331                 :            :     {
    1332                 :         28 :         rInfo.SetpSpaceAdd( pLay->GetpLLSpaceAdd() );
    1333                 :         28 :         rInfo.ResetSpaceIdx();
    1334                 :         28 :         bSpaceChg = rMulti.ChgSpaceAdd( pLay, nSpaceAdd );
    1335                 :            :     }
    1336                 :            :     else
    1337                 :            :     {
    1338                 :        364 :         rInfo.SetpSpaceAdd( (!rMulti.IsDouble() || rMulti.HasTabulator() ) ?
    1339   [ -  +  #  # ]:        364 :                                 0 : pOldSpaceAdd );
    1340                 :        364 :         rInfo.SetSpaceIdx( nOldSpIdx);
    1341                 :            :     }
    1342                 :        392 : }
    1343                 :            : 
    1344                 :        392 : SwSpaceManipulator::~SwSpaceManipulator()
    1345                 :            : {
    1346         [ -  + ]:        392 :     if( bSpaceChg )
    1347                 :            :     {
    1348                 :          0 :         rInfo.RemoveFirstSpaceAdd();
    1349                 :          0 :         bSpaceChg = sal_False;
    1350                 :            :     }
    1351                 :        392 :     rInfo.SetpSpaceAdd( pOldSpaceAdd );
    1352                 :        392 :     rInfo.SetSpaceIdx( nOldSpIdx);
    1353                 :        392 :     rInfo.SetDirection( nOldDir );
    1354                 :        392 : }
    1355                 :            : 
    1356                 :            : /*--------------------------------------------------
    1357                 :            :  * SwTxtPainter::PaintMultiPortion manages the paint for a SwMultiPortion.
    1358                 :            :  * External, for the calling function, it seems to be a normal Paint-function,
    1359                 :            :  * internal it is like a SwTxtFrm::Paint with multiple DrawTextLines
    1360                 :            :  * --------------------------------------------------*/
    1361                 :            : 
    1362                 :        392 : void SwTxtPainter::PaintMultiPortion( const SwRect &rPaint,
    1363                 :            :     SwMultiPortion& rMulti, const SwMultiPortion* pEnvPor )
    1364                 :            : {
    1365 [ +  - ][ +  - ]:        392 :     GETGRID( pFrm->FindPageFrm() )
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ -  + ]
    1366 [ -  + ][ #  # ]:        392 :     const sal_Bool bHasGrid = pGrid && GetInfo().SnapToGrid();
    1367                 :        392 :     sal_uInt16 nRubyHeight = 0;
    1368                 :        392 :     sal_Bool bRubyTop = sal_False;
    1369                 :            : 
    1370         [ -  + ]:        392 :     if ( bHasGrid )
    1371                 :            :     {
    1372                 :          0 :         nRubyHeight = pGrid->GetRubyHeight();
    1373                 :          0 :         bRubyTop = ! pGrid->GetRubyTextBelow();
    1374                 :            :     }
    1375                 :            : 
    1376                 :            :     // do not allow grid mode for first line in ruby portion
    1377 [ -  + ][ #  # ]:        392 :     const sal_Bool bRubyInGrid = bHasGrid && rMulti.IsRuby();
    1378                 :            : 
    1379                 :        392 :     const sal_uInt16 nOldHeight = rMulti.Height();
    1380                 :        392 :     const sal_Bool bOldGridModeAllowed = GetInfo().SnapToGrid();
    1381                 :            : 
    1382         [ -  + ]:        392 :     if ( bRubyInGrid )
    1383                 :            :     {
    1384                 :          0 :         GetInfo().SetSnapToGrid( ! bRubyTop );
    1385                 :          0 :         rMulti.Height( pCurr->Height() );
    1386                 :            :     }
    1387                 :            : 
    1388         [ +  - ]:        392 :     SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
    1389                 :        392 :     sal_uInt8 nEnvDir = 0;
    1390                 :        392 :     sal_uInt8 nThisDir = 0;
    1391                 :        392 :     sal_uInt8 nFrmDir = 0;
    1392         [ -  + ]:        392 :     if ( rMulti.IsBidi() )
    1393                 :            :     {
    1394                 :            :         // these values are needed for the calculation of the x coordinate
    1395                 :            :         // and the layout mode
    1396                 :            :         OSL_ENSURE( ! pEnvPor || pEnvPor->IsBidi(),
    1397                 :            :                 "Oh no, I expected a BidiPortion" );
    1398 [ #  # ][ #  # ]:          0 :         nFrmDir = GetInfo().GetTxtFrm()->IsRightToLeft() ? 1 : 0;
    1399         [ #  # ]:          0 :         nEnvDir = pEnvPor ? ((SwBidiPortion*)pEnvPor)->GetLevel() % 2 : nFrmDir;
    1400                 :          0 :         nThisDir = ((SwBidiPortion&)rMulti).GetLevel() % 2;
    1401                 :            :     }
    1402                 :            : 
    1403                 :            : #if OSL_DEBUG_LEVEL > 1
    1404                 :            :     // only paint first level bidi portions
    1405                 :            :     if( rMulti.Width() > 1 && ! pEnvPor )
    1406                 :            :         GetInfo().DrawViewOpt( rMulti, POR_FLD );
    1407                 :            : #endif
    1408                 :            : 
    1409         [ -  + ]:        392 :     if ( bRubyInGrid )
    1410                 :          0 :         rMulti.Height( nOldHeight );
    1411                 :            : 
    1412                 :            :     // do we have to repaint a post it portion?
    1413         [ +  + ]:        625 :     if( GetInfo().OnWin() && rMulti.GetPortion() &&
           [ +  +  +  + ]
                 [ +  + ]
    1414                 :        233 :         ! rMulti.GetPortion()->Width() )
    1415         [ +  - ]:         47 :         rMulti.GetPortion()->PrePaint( GetInfo(), &rMulti );
    1416                 :            : 
    1417                 :            :     // old values must be saved and restored at the end
    1418                 :        392 :     xub_StrLen nOldLen = GetInfo().GetLen();
    1419                 :        392 :     KSHORT nOldX = KSHORT(GetInfo().X());
    1420                 :        392 :     long nOldY = GetInfo().Y();
    1421                 :        392 :     xub_StrLen nOldIdx = GetInfo().GetIdx();
    1422                 :            : 
    1423         [ +  - ]:        392 :     SwSpaceManipulator aManip( GetInfo(), rMulti );
    1424                 :            : 
    1425                 :            :     SwFontSave *pFontSave;
    1426                 :            :     SwFont* pTmpFnt;
    1427                 :            : 
    1428         [ +  + ]:        392 :     if( rMulti.IsDouble() )
    1429                 :            :     {
    1430 [ +  - ][ +  - ]:         28 :         pTmpFnt = new SwFont( *GetInfo().GetFont() );
    1431         [ +  - ]:         28 :         if( rMulti.IsDouble() )
    1432                 :            :         {
    1433                 :         28 :             SetPropFont( 50 );
    1434         [ +  - ]:         28 :             pTmpFnt->SetProportion( GetPropFont() );
    1435                 :            :         }
    1436 [ +  - ][ +  - ]:         28 :         pFontSave = new SwFontSave( GetInfo(), pTmpFnt, this );
    1437                 :            :     }
    1438                 :            :     else
    1439                 :            :     {
    1440                 :        364 :         pFontSave = NULL;
    1441                 :        364 :         pTmpFnt = NULL;
    1442                 :            :     }
    1443                 :            : 
    1444 [ +  - ][ +  + ]:        392 :     if( rMulti.HasBrackets() )
    1445                 :            :     {
    1446                 :         20 :         xub_StrLen nTmpOldIdx = GetInfo().GetIdx();
    1447                 :         20 :         GetInfo().SetIdx(((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart);
    1448         [ +  - ]:         20 :         SeekAndChg( GetInfo() );
    1449         [ +  - ]:         20 :         ((SwDoubleLinePortion&)rMulti).PaintBracket( GetInfo(), 0, sal_True );
    1450                 :         20 :         GetInfo().SetIdx( nTmpOldIdx );
    1451                 :            :     }
    1452                 :            : 
    1453                 :        392 :     KSHORT nTmpX = KSHORT(GetInfo().X());
    1454                 :            : 
    1455                 :        392 :     SwLineLayout* pLay = &rMulti.GetRoot();// the first line of the multiportion
    1456                 :        392 :     SwLinePortion* pPor = pLay->GetFirstPortion();//first portion of these line
    1457                 :        392 :     SwTwips nOfst = 0;
    1458                 :            : 
    1459                 :            :     // GetInfo().Y() is the baseline from the surrounding line. We must switch
    1460                 :            :     // this temporary to the baseline of the inner lines of the multiportion.
    1461         [ -  + ]:        392 :     if( rMulti.HasRotation() )
    1462                 :            :     {
    1463         [ #  # ]:          0 :         if( rMulti.IsRevers() )
    1464                 :            :         {
    1465                 :          0 :             GetInfo().Y( nOldY - rMulti.GetAscent() );
    1466                 :          0 :             nOfst = nTmpX + rMulti.Width();
    1467                 :            :         }
    1468                 :            :         else
    1469                 :            :         {
    1470                 :          0 :             GetInfo().Y( nOldY - rMulti.GetAscent() + rMulti.Height() );
    1471                 :          0 :             nOfst = nTmpX;
    1472                 :            :         }
    1473                 :            :     }
    1474         [ -  + ]:        392 :     else if ( rMulti.IsBidi() )
    1475                 :            :     {
    1476                 :            :         // does the current bidi portion has the same direction
    1477                 :            :         // as its environment?
    1478         [ #  # ]:          0 :         if ( nEnvDir != nThisDir )
    1479                 :            :         {
    1480                 :            :             // different directions, we have to adjust the x coordinate
    1481                 :          0 :             SwTwips nMultiWidth = rMulti.Width() +
    1482 [ #  # ][ #  # ]:          0 :                     rMulti.CalcSpacing( GetInfo().GetSpaceAdd(), GetInfo() );
    1483                 :            : 
    1484         [ #  # ]:          0 :             if ( nFrmDir == nThisDir )
    1485                 :          0 :                 GetInfo().X( GetInfo().X() - nMultiWidth );
    1486                 :            :             else
    1487                 :          0 :                 GetInfo().X( GetInfo().X() + nMultiWidth );
    1488                 :            :         }
    1489                 :            : 
    1490                 :          0 :         nOfst = nOldY - rMulti.GetAscent();
    1491                 :            : 
    1492                 :            :         // set layout mode
    1493         [ #  # ]:          0 :         aLayoutModeModifier.Modify( nThisDir );
    1494                 :            :     }
    1495                 :            :     else
    1496                 :        392 :         nOfst = nOldY - rMulti.GetAscent();
    1497                 :            : 
    1498                 :        392 :     sal_Bool bRest = pLay->IsRest();
    1499                 :        392 :     sal_Bool bFirst = sal_True;
    1500                 :            : 
    1501                 :            :     OSL_ENSURE( 0 == GetInfo().GetUnderFnt() || rMulti.IsBidi(),
    1502                 :            :             " Only BiDi portions are allowed to use the common underlining font" );
    1503                 :            : 
    1504         [ +  + ]:       1126 :     do
    1505                 :            :     {
    1506         [ -  + ]:       1126 :         if ( bHasGrid )
    1507                 :            :         {
    1508         [ #  # ]:          0 :             if( rMulti.HasRotation() )
    1509                 :            :             {
    1510                 :          0 :                 const sal_uInt16 nAdjustment = ( pLay->Height() - pPor->Height() ) / 2 +
    1511                 :          0 :                                             pPor->GetAscent();
    1512         [ #  # ]:          0 :                 if( rMulti.IsRevers() )
    1513                 :          0 :                     GetInfo().X( nOfst - nAdjustment );
    1514                 :            :                 else
    1515                 :          0 :                     GetInfo().X( nOfst + nAdjustment );
    1516                 :            :             }
    1517                 :            :             else
    1518                 :            :             {
    1519                 :            :                 // special treatment for ruby portions in grid mode
    1520                 :          0 :                 SwTwips nAdjustment = 0;
    1521         [ #  # ]:          0 :                 if ( rMulti.IsRuby() )
    1522                 :            :                 {
    1523         [ #  # ]:          0 :                     if ( bRubyTop != ( pLay == &rMulti.GetRoot() ) )
    1524                 :            :                         // adjust base text
    1525                 :          0 :                         nAdjustment = ( pCurr->Height() - nRubyHeight - pPor->Height() ) / 2;
    1526         [ #  # ]:          0 :                     else if ( bRubyTop )
    1527                 :            :                         // adjust upper ruby text
    1528                 :          0 :                         nAdjustment = nRubyHeight - pPor->Height();
    1529                 :            :                     // else adjust lower ruby text
    1530                 :            :                 }
    1531                 :            : 
    1532                 :          0 :                 GetInfo().Y( nOfst + nAdjustment + pPor->GetAscent() );
    1533                 :            :             }
    1534                 :            :         }
    1535         [ -  + ]:       1126 :         else if( rMulti.HasRotation() )
    1536                 :            :         {
    1537         [ #  # ]:          0 :             if( rMulti.IsRevers() )
    1538         [ #  # ]:          0 :                 GetInfo().X( nOfst - AdjustBaseLine( *pLay, pPor, 0, 0, sal_True ) );
    1539                 :            :             else
    1540         [ #  # ]:          0 :                 GetInfo().X( nOfst + AdjustBaseLine( *pLay, pPor ) );
    1541                 :            :         }
    1542                 :            :         else
    1543         [ +  - ]:       1126 :             GetInfo().Y( nOfst + AdjustBaseLine( *pLay, pPor ) );
    1544                 :            : 
    1545                 :       1126 :         sal_Bool bSeeked = sal_True;
    1546                 :       1126 :         GetInfo().SetLen( pPor->GetLen() );
    1547                 :            : 
    1548 [ +  + ][ +  - ]:       1126 :         if( bRest && pPor->InFldGrp() && !pPor->GetLen() )
         [ +  + ][ +  + ]
    1549                 :            :         {
    1550         [ +  - ]:        364 :             if( ((SwFldPortion*)pPor)->HasFont() )
    1551                 :        364 :                  bSeeked = sal_False;
    1552                 :            :             else
    1553         [ #  # ]:          0 :                 SeekAndChgBefore( GetInfo() );
    1554                 :            :         }
    1555 [ +  + ][ +  - ]:        762 :         else if( pPor->InTxtGrp() || pPor->InFldGrp() || pPor->InTabGrp() )
         [ -  + ][ +  + ]
    1556         [ +  - ]:        598 :             SeekAndChg( GetInfo() );
    1557 [ +  + ][ -  + ]:        164 :         else if ( !bFirst && pPor->IsBreakPortion() && GetInfo().GetOpt().IsParagraph() )
         [ #  # ][ -  + ]
    1558                 :            :         {
    1559         [ #  # ]:          0 :             if( GetRedln() )
    1560         [ #  # ]:          0 :                 SeekAndChg( GetInfo() );
    1561                 :            :             else
    1562         [ #  # ]:          0 :                 SeekAndChgBefore( GetInfo() );
    1563                 :            :         }
    1564                 :            :         else
    1565                 :        164 :             bSeeked = sal_False;
    1566                 :            : 
    1567                 :       1126 :         SwLinePortion *pNext = pPor->GetPortion();
    1568 [ +  + ][ +  + ]:       1126 :         if(GetInfo().OnWin() && pNext && !pNext->Width() )
         [ +  + ][ +  + ]
    1569                 :            :         {
    1570         [ -  + ]:         30 :             if ( !bSeeked )
    1571         [ #  # ]:          0 :                 SeekAndChg( GetInfo() );
    1572         [ +  - ]:         30 :             pNext->PrePaint( GetInfo(), pPor );
    1573                 :            :         }
    1574                 :            : 
    1575         [ +  - ]:       1126 :         CheckSpecialUnderline( pPor );
    1576                 :       1126 :         SwUnderlineFont* pUnderLineFnt = GetInfo().GetUnderFnt();
    1577         [ +  + ]:       1126 :         if ( pUnderLineFnt )
    1578                 :            :         {
    1579         [ -  + ]:          6 :             if ( rMulti.IsDouble() )
    1580         [ #  # ]:          0 :                 pUnderLineFnt->GetFont().SetProportion( 50 );
    1581                 :          6 :             pUnderLineFnt->SetPos( GetInfo().GetPos() );
    1582                 :            :         }
    1583                 :            : 
    1584         [ -  + ]:       1126 :         if ( rMulti.IsBidi() )
    1585                 :            :         {
    1586                 :            :             // we do not allow any rotation inside a bidi portion
    1587                 :          0 :             SwFont* pTmpFont = GetInfo().GetFont();
    1588 [ #  # ][ #  # ]:          0 :             pTmpFont->SetVertical( 0, GetInfo().GetTxtFrm()->IsVertical() );
    1589                 :            :         }
    1590                 :            : 
    1591 [ -  + ][ #  # ]:       1126 :         if( pPor->IsMultiPortion() && ((SwMultiPortion*)pPor)->IsBidi() )
                 [ -  + ]
    1592                 :            :         {
    1593                 :            :             // but we do allow nested bidi portions
    1594                 :            :             OSL_ENSURE( rMulti.IsBidi(), "Only nesting of bidi portions is allowed" );
    1595         [ #  # ]:          0 :             PaintMultiPortion( rPaint, (SwMultiPortion&)*pPor, &rMulti );
    1596                 :            :         }
    1597                 :            :         else
    1598         [ +  - ]:       1126 :             pPor->Paint( GetInfo() );
    1599                 :            : 
    1600 [ -  + ][ #  # ]:       1126 :         if( GetFnt()->IsURL() && pPor->InTxtGrp() )
                 [ -  + ]
    1601         [ #  # ]:          0 :             GetInfo().NotifyURL( *pPor );
    1602                 :            : 
    1603                 :       1126 :         bFirst &= !pPor->GetLen();
    1604 [ +  + ][ +  + ]:       1126 :         if( pNext || !pPor->IsMarginPortion() )
                 [ +  + ]
    1605         [ +  - ]:       1030 :             pPor->Move( GetInfo() );
    1606                 :            : 
    1607                 :       1126 :         pPor = pNext;
    1608                 :            : 
    1609                 :            :         // If there's no portion left, we go to the next line
    1610 [ +  + ][ +  + ]:       1126 :         if( !pPor && pLay->GetNext() )
                 [ +  + ]
    1611                 :            :         {
    1612                 :        392 :             pLay = pLay->GetNext();
    1613                 :        392 :             pPor = pLay->GetFirstPortion();
    1614                 :        392 :             bRest = pLay->IsRest();
    1615         [ +  - ]:        392 :             aManip.SecondLine();
    1616                 :            : 
    1617                 :            :             // delete underline font
    1618 [ -  + ][ #  # ]:        392 :             delete GetInfo().GetUnderFnt();
    1619                 :        392 :             GetInfo().SetUnderFnt( 0 );
    1620                 :            : 
    1621         [ -  + ]:        392 :             if( rMulti.HasRotation() )
    1622                 :            :             {
    1623         [ #  # ]:          0 :                 if( rMulti.IsRevers() )
    1624                 :            :                 {
    1625                 :          0 :                     nOfst += pLay->Height();
    1626                 :          0 :                     GetInfo().Y( nOldY - rMulti.GetAscent() );
    1627                 :            :                 }
    1628                 :            :                 else
    1629                 :            :                 {
    1630                 :          0 :                     nOfst -= pLay->Height();
    1631                 :          0 :                     GetInfo().Y( nOldY - rMulti.GetAscent() + rMulti.Height() );
    1632                 :            :                 }
    1633                 :            :             }
    1634 [ -  + ][ #  # ]:        392 :             else if ( bHasGrid && rMulti.IsRuby() )
                 [ -  + ]
    1635                 :            :             {
    1636                 :          0 :                 GetInfo().X( nTmpX );
    1637         [ #  # ]:          0 :                 if ( bRubyTop )
    1638                 :            :                 {
    1639                 :          0 :                     nOfst += nRubyHeight;
    1640                 :          0 :                     GetInfo().SetSnapToGrid( sal_True );
    1641                 :            :                 }
    1642                 :            :                 else
    1643                 :            :                 {
    1644                 :          0 :                     nOfst += pCurr->Height() - nRubyHeight;
    1645                 :          0 :                     GetInfo().SetSnapToGrid( sal_False );
    1646                 :            :                 }
    1647                 :            :             } else
    1648                 :            :             {
    1649                 :        392 :                 GetInfo().X( nTmpX );
    1650                 :            :                 // We switch to the baseline of the next inner line
    1651                 :        392 :                 nOfst += rMulti.GetRoot().Height();
    1652                 :            :             }
    1653                 :            :         }
    1654                 :            :     } while( pPor );
    1655                 :            : 
    1656         [ -  + ]:        392 :     if ( bRubyInGrid )
    1657                 :          0 :         GetInfo().SetSnapToGrid( bOldGridModeAllowed );
    1658                 :            : 
    1659                 :            :     // delete underline font
    1660         [ +  - ]:        392 :     if ( ! rMulti.IsBidi() )
    1661                 :            :     {
    1662 [ +  + ][ +  - ]:        392 :         delete GetInfo().GetUnderFnt();
    1663                 :        392 :         GetInfo().SetUnderFnt( 0 );
    1664                 :            :     }
    1665                 :            : 
    1666                 :        392 :     GetInfo().SetIdx( nOldIdx );
    1667                 :        392 :     GetInfo().Y( nOldY );
    1668                 :            : 
    1669 [ +  + ][ +  - ]:        392 :     if( rMulti.HasBrackets() )
    1670                 :            :     {
    1671                 :         20 :         xub_StrLen nTmpOldIdx = GetInfo().GetIdx();
    1672                 :         20 :         GetInfo().SetIdx(((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart);
    1673         [ +  - ]:         20 :         SeekAndChg( GetInfo() );
    1674                 :         20 :         GetInfo().X( nOldX );
    1675                 :         20 :         ((SwDoubleLinePortion&)rMulti).PaintBracket( GetInfo(),
    1676         [ +  - ]:         40 :             aManip.GetSpaceAdd(), sal_False );
    1677                 :         20 :         GetInfo().SetIdx( nTmpOldIdx );
    1678                 :            :     }
    1679                 :            :     // Restore the saved values
    1680                 :        392 :     GetInfo().X( nOldX );
    1681                 :        392 :     GetInfo().SetLen( nOldLen );
    1682 [ +  - ][ +  + ]:        392 :     delete pFontSave;
    1683 [ +  + ][ +  - ]:        392 :     delete pTmpFnt;
    1684 [ +  - ][ +  - ]:        392 :     SetPropFont( 0 );
    1685                 :        392 : }
    1686                 :            : 
    1687                 :          0 : sal_Bool lcl_ExtractFieldFollow( SwLineLayout* pLine, SwLinePortion* &rpFld )
    1688                 :            : {
    1689                 :          0 :     SwLinePortion* pLast = pLine;
    1690                 :          0 :     rpFld = pLine->GetPortion();
    1691 [ #  # ][ #  # ]:          0 :     while( rpFld && !rpFld->InFldGrp() )
                 [ #  # ]
    1692                 :            :     {
    1693                 :          0 :         pLast = rpFld;
    1694                 :          0 :         rpFld = rpFld->GetPortion();
    1695                 :            :     }
    1696                 :          0 :     sal_Bool bRet = rpFld != 0;
    1697         [ #  # ]:          0 :     if( bRet )
    1698                 :            :     {
    1699         [ #  # ]:          0 :         if( ((SwFldPortion*)rpFld)->IsFollow() )
    1700                 :            :         {
    1701                 :          0 :             rpFld->Truncate();
    1702                 :          0 :             pLast->SetPortion( NULL );
    1703                 :            :         }
    1704                 :            :         else
    1705                 :          0 :             rpFld = NULL;
    1706                 :            :     }
    1707                 :          0 :     pLine->Truncate();
    1708                 :          0 :     return bRet;
    1709                 :            : }
    1710                 :            : 
    1711                 :            : /*----------------------------------------------------
    1712                 :            :  *              lcl_TruncateMultiPortion
    1713                 :            :  * If a multi portion completely has to go to the
    1714                 :            :  * next line, this function is called to trunctate
    1715                 :            :  * the rest of the remaining multi portion
    1716                 :            :  * --------------------------------------------------*/
    1717                 :            : 
    1718                 :          0 : void lcl_TruncateMultiPortion( SwMultiPortion& rMulti, SwTxtFormatInfo& rInf,
    1719                 :            :                                xub_StrLen nStartIdx )
    1720                 :            : {
    1721                 :          0 :     rMulti.GetRoot().Truncate();
    1722                 :          0 :     rMulti.GetRoot().SetLen(0);
    1723                 :          0 :     rMulti.GetRoot().Width(0);
    1724                 :            : //  rMulti.CalcSize( *this, aInf );
    1725         [ #  # ]:          0 :     if ( rMulti.GetRoot().GetNext() )
    1726                 :            :     {
    1727                 :          0 :         rMulti.GetRoot().GetNext()->Truncate();
    1728                 :          0 :         rMulti.GetRoot().GetNext()->SetLen( 0 );
    1729                 :          0 :         rMulti.GetRoot().GetNext()->Width( 0 );
    1730                 :            :     }
    1731                 :          0 :     rMulti.Width( 0 );
    1732                 :          0 :     rMulti.SetLen(0);
    1733                 :          0 :     rInf.SetIdx( nStartIdx );
    1734                 :          0 : }
    1735                 :            : 
    1736                 :            : /*-----------------------------------------------------------------------------
    1737                 :            :  *              SwTxtFormatter::BuildMultiPortion
    1738                 :            :  * manages the formatting of a SwMultiPortion. External, for the calling
    1739                 :            :  * function, it seems to be a normal Format-function, internal it is like a
    1740                 :            :  * SwTxtFrm::_Format with multiple BuildPortions
    1741                 :            :  *---------------------------------------------------------------------------*/
    1742                 :            : 
    1743                 :        356 : sal_Bool SwTxtFormatter::BuildMultiPortion( SwTxtFormatInfo &rInf,
    1744                 :            :     SwMultiPortion& rMulti )
    1745                 :            : {
    1746                 :        356 :     SwTwips nMaxWidth = rInf.Width();
    1747                 :        356 :     KSHORT nOldX = 0;
    1748                 :            : 
    1749 [ +  + ][ +  - ]:        356 :     if( rMulti.HasBrackets() )
    1750                 :            :     {
    1751                 :         16 :         xub_StrLen nOldIdx = rInf.GetIdx();
    1752                 :         16 :         rInf.SetIdx( ((SwDoubleLinePortion&)rMulti).GetBrackets()->nStart );
    1753         [ +  - ]:         16 :         SeekAndChg( rInf );
    1754                 :         16 :         nOldX = KSHORT(GetInfo().X());
    1755         [ +  - ]:         16 :         ((SwDoubleLinePortion&)rMulti).FormatBrackets( rInf, nMaxWidth );
    1756                 :         16 :         rInf.SetIdx( nOldIdx );
    1757                 :            :     }
    1758                 :            : 
    1759         [ +  - ]:        356 :     SeekAndChg( rInf );
    1760                 :            :     SwFontSave *pFontSave;
    1761         [ +  + ]:        356 :     if( rMulti.IsDouble() )
    1762                 :            :     {
    1763 [ +  - ][ +  - ]:         20 :         SwFont* pTmpFnt = new SwFont( *rInf.GetFont() );
    1764         [ +  - ]:         20 :         if( rMulti.IsDouble() )
    1765                 :            :         {
    1766                 :         20 :             SetPropFont( 50 );
    1767         [ +  - ]:         20 :             pTmpFnt->SetProportion( GetPropFont() );
    1768                 :            :         }
    1769 [ +  - ][ +  - ]:         20 :         pFontSave = new SwFontSave( rInf, pTmpFnt, this );
    1770                 :            :     }
    1771                 :            :     else
    1772                 :        336 :         pFontSave = NULL;
    1773                 :            : 
    1774         [ +  - ]:        356 :     SwLayoutModeModifier aLayoutModeModifier( *GetInfo().GetOut() );
    1775         [ -  + ]:        356 :     if ( rMulti.IsBidi() )
    1776                 :            :     {
    1777                 :            :         // set layout mode
    1778 [ #  # ][ #  # ]:          0 :         aLayoutModeModifier.Modify( ! rInf.GetTxtFrm()->IsRightToLeft() );
    1779                 :            :     }
    1780                 :            : 
    1781                 :        356 :     SwTwips nTmpX = 0;
    1782                 :            : 
    1783         [ -  + ]:        356 :     if( rMulti.HasRotation() )
    1784                 :            :     {
    1785                 :            :         // For nMaxWidth we take the height of the body frame.
    1786                 :            :         // #i25067#: If the current frame is inside a table, we restrict
    1787                 :            :         // nMaxWidth to the current frame height, unless the frame size
    1788                 :            :         // attribute is set to variable size:
    1789                 :            : 
    1790                 :            :         // We set nTmpX (which is used for portion calculating) to the
    1791                 :            :         // current Y value
    1792         [ #  # ]:          0 :         const SwPageFrm* pPage = pFrm->FindPageFrm();
    1793                 :            :         OSL_ENSURE( pPage, "No page in frame!");
    1794                 :          0 :         const SwLayoutFrm* pUpperFrm = pPage;
    1795                 :            : 
    1796 [ #  # ][ #  # ]:          0 :         if ( pFrm->IsInTab() )
    1797                 :            :         {
    1798                 :          0 :             pUpperFrm = pFrm->GetUpper();
    1799 [ #  # ][ #  # ]:          0 :             while ( pUpperFrm && !pUpperFrm->IsCellFrm() )
                 [ #  # ]
    1800                 :          0 :                 pUpperFrm = pUpperFrm->GetUpper();
    1801                 :            :             OSL_ENSURE( pUpperFrm, "pFrm is in table but does not have an upper cell frame" );
    1802                 :          0 :             const SwTableLine* pLine = ((SwRowFrm*)pUpperFrm->GetUpper())->GetTabLine();
    1803         [ #  # ]:          0 :             const SwFmtFrmSize& rFrmFmtSize = pLine->GetFrmFmt()->GetFrmSize();
    1804         [ #  # ]:          0 :             if ( ATT_VAR_SIZE == rFrmFmtSize.GetHeightSizeType() )
    1805                 :          0 :                 pUpperFrm = pPage;
    1806                 :            :         }
    1807 [ #  # ][ #  # ]:          0 :         if ( pUpperFrm == pPage && !pFrm->IsInFtn() )
         [ #  # ][ #  # ]
    1808         [ #  # ]:          0 :             pUpperFrm = pPage->FindBodyCont();
    1809                 :            : 
    1810                 :            :         nMaxWidth = pUpperFrm ?
    1811         [ #  # ]:          0 :                     ( rInf.GetTxtFrm()->IsVertical() ?
    1812                 :          0 :                       pUpperFrm->Prt().Width() :
    1813                 :          0 :                       pUpperFrm->Prt().Height() ) :
    1814 [ #  # ][ #  # ]:          0 :                     USHRT_MAX;
    1815                 :            :     }
    1816                 :            :     else
    1817                 :        356 :         nTmpX = rInf.X();
    1818                 :            : 
    1819                 :        356 :     SwMultiPortion* pOldMulti = pMulti;
    1820                 :            : 
    1821                 :        356 :     pMulti = &rMulti;
    1822                 :        356 :     SwLineLayout *pOldCurr = pCurr;
    1823                 :        356 :     xub_StrLen nOldStart = GetStart();
    1824                 :        356 :     SwTwips nMinWidth = nTmpX + 1;
    1825                 :        356 :     SwTwips nActWidth = nMaxWidth;
    1826                 :        356 :     const xub_StrLen nStartIdx = rInf.GetIdx();
    1827                 :        356 :     xub_StrLen nMultiLen = rMulti.GetLen();
    1828                 :            : 
    1829                 :            :     SwLinePortion *pFirstRest;
    1830                 :            :     SwLinePortion *pSecondRest;
    1831         [ -  + ]:        356 :     if( rMulti.IsFormatted() )
    1832                 :            :     {
    1833 [ #  # ][ #  #  :          0 :         if( !lcl_ExtractFieldFollow( &rMulti.GetRoot(), pFirstRest )
             #  #  #  # ]
                 [ #  # ]
    1834                 :          0 :             && rMulti.IsDouble() && rMulti.GetRoot().GetNext() )
    1835         [ #  # ]:          0 :             lcl_ExtractFieldFollow( rMulti.GetRoot().GetNext(), pFirstRest );
    1836 [ #  # ][ #  # ]:          0 :         if( !rMulti.IsDouble() && rMulti.GetRoot().GetNext() )
                 [ #  # ]
    1837         [ #  # ]:          0 :             lcl_ExtractFieldFollow( rMulti.GetRoot().GetNext(), pSecondRest );
    1838                 :            :         else
    1839                 :          0 :             pSecondRest = NULL;
    1840                 :            :     }
    1841                 :            :     else
    1842                 :            :     {
    1843                 :        356 :         pFirstRest = rMulti.GetRoot().GetPortion();
    1844                 :        356 :         pSecondRest = rMulti.GetRoot().GetNext() ?
    1845         [ +  + ]:        356 :                       rMulti.GetRoot().GetNext()->GetPortion() : NULL;
    1846         [ +  + ]:        356 :         if( pFirstRest )
    1847                 :        280 :             rMulti.GetRoot().SetPortion( NULL );
    1848         [ +  + ]:        356 :         if( pSecondRest )
    1849                 :         56 :             rMulti.GetRoot().GetNext()->SetPortion( NULL );
    1850                 :        356 :         rMulti.SetFormatted();
    1851                 :        356 :         nMultiLen = nMultiLen - rInf.GetIdx();
    1852                 :            :     }
    1853                 :            : 
    1854                 :            :     // save some values
    1855                 :        356 :     const XubString* pOldTxt = &(rInf.GetTxt());
    1856                 :        356 :     const SwTwips nOldPaintOfst = rInf.GetPaintOfst();
    1857                 :            : 
    1858         [ +  - ]:        356 :     XubString aMultiStr( rInf.GetTxt(), 0, nMultiLen + rInf.GetIdx() );
    1859                 :        356 :     rInf.SetTxt( aMultiStr );
    1860         [ +  - ]:        356 :     SwTxtFormatInfo aInf( rInf, rMulti.GetRoot(), nActWidth );
    1861                 :            :     // Do we allow break cuts? The FirstMulti-Flag is evaluated during
    1862                 :            :     // line break determination.
    1863                 :        356 :     sal_Bool bFirstMulti = rInf.GetIdx() != rInf.GetLineStart();
    1864                 :            : 
    1865                 :        356 :     SwLinePortion *pNextFirst = NULL;
    1866                 :        356 :     SwLinePortion *pNextSecond = NULL;
    1867                 :        356 :     sal_Bool bRet = sal_False;
    1868                 :            : 
    1869 [ +  - ][ +  - ]:        356 :     GETGRID( pFrm->FindPageFrm() )
         [ -  + ][ #  # ]
         [ #  # ][ #  # ]
         [ -  + ][ +  - ]
    1870 [ -  + ][ #  # ]:        356 :     const sal_Bool bHasGrid = pGrid && GRID_LINES_CHARS == pGrid->GetGridType();
    1871                 :            : 
    1872                 :        356 :     sal_Bool bRubyTop = sal_False;
    1873                 :            : 
    1874         [ -  + ]:        356 :     if ( bHasGrid )
    1875                 :          0 :         bRubyTop = ! pGrid->GetRubyTextBelow();
    1876                 :            : 
    1877                 :        160 :     do
    1878                 :            :     {
    1879                 :        516 :         pCurr = &rMulti.GetRoot();
    1880                 :        516 :         nStart = nStartIdx;
    1881                 :        516 :         bRet = sal_False;
    1882         [ +  - ]:        516 :         FormatReset( aInf );
    1883                 :        516 :         aInf.X( nTmpX );
    1884                 :        516 :         aInf.Width( KSHORT(nActWidth) );
    1885                 :        516 :         aInf.RealWidth( KSHORT(nActWidth) );
    1886                 :        516 :         aInf.SetFirstMulti( bFirstMulti );
    1887                 :        516 :         aInf.SetNumDone( rInf.IsNumDone() );
    1888                 :        516 :         aInf.SetFtnDone( rInf.IsFtnDone() );
    1889                 :            : 
    1890         [ +  + ]:        516 :         if( pFirstRest )
    1891                 :            :         {
    1892                 :            :             OSL_ENSURE( pFirstRest->InFldGrp(), "BuildMulti: Fieldrest expected");
    1893                 :            :             SwFldPortion *pFld =
    1894                 :            :                 ((SwFldPortion*)pFirstRest)->Clone(
    1895         [ +  - ]:        280 :                     ((SwFldPortion*)pFirstRest)->GetExp() );
    1896                 :        280 :             pFld->SetFollow( sal_True );
    1897                 :        280 :             aInf.SetRest( pFld );
    1898                 :            :         }
    1899 [ +  + ][ +  + ]:        516 :         aInf.SetRuby( rMulti.IsRuby() && rMulti.OnTop() );
    1900                 :            : 
    1901                 :            :         // in grid mode we temporarily have to disable the grid for the ruby line
    1902                 :        516 :         const sal_Bool bOldGridModeAllowed = GetInfo().SnapToGrid();
    1903 [ #  # ][ #  # ]:        516 :         if ( bHasGrid && aInf.IsRuby() && bRubyTop )
         [ -  + ][ -  + ]
    1904                 :          0 :             aInf.SetSnapToGrid( sal_False );
    1905                 :            : 
    1906                 :            :         // If there's no more rubytext, then buildportion is forbidden
    1907 [ +  + ][ +  - ]:        516 :         if( pFirstRest || !aInf.IsRuby() )
                 [ +  - ]
    1908         [ +  - ]:        516 :             BuildPortions( aInf );
    1909                 :            : 
    1910                 :        516 :         aInf.SetSnapToGrid( bOldGridModeAllowed );
    1911                 :            : 
    1912         [ +  - ]:        516 :         rMulti.CalcSize( *this, aInf );
    1913                 :        516 :         pCurr->SetRealHeight( pCurr->Height() );
    1914                 :            : 
    1915         [ -  + ]:        516 :         if( rMulti.IsBidi() )
    1916                 :            :         {
    1917                 :          0 :             pNextFirst = aInf.GetRest();
    1918                 :          0 :             break;
    1919                 :            :         }
    1920                 :            : 
    1921 [ -  + ][ #  # ]:        516 :         if( rMulti.HasRotation() && !rMulti.IsDouble() )
                 [ -  + ]
    1922                 :          0 :             break;
    1923                 :            :         // second line has to be formatted
    1924 [ +  + ][ +  + ]:        516 :         else if( pCurr->GetLen()<nMultiLen || rMulti.IsRuby() || aInf.GetRest())
         [ -  + ][ +  + ]
    1925                 :            :         {
    1926                 :        416 :             xub_StrLen nFirstLen = pCurr->GetLen();
    1927 [ +  - ][ +  + ]:        416 :             delete pCurr->GetNext();
    1928 [ +  - ][ +  - ]:        416 :             pCurr->SetNext( new SwLineLayout() );
    1929                 :        416 :             pCurr = pCurr->GetNext();
    1930                 :        416 :             nStart = aInf.GetIdx();
    1931                 :        416 :             aInf.X( nTmpX );
    1932         [ +  - ]:        416 :             SwTxtFormatInfo aTmp( aInf, *pCurr, nActWidth );
    1933         [ +  + ]:        416 :             if( rMulti.IsRuby() )
    1934                 :            :             {
    1935                 :        336 :                 aTmp.SetRuby( !rMulti.OnTop() );
    1936                 :        336 :                 pNextFirst = aInf.GetRest();
    1937         [ +  + ]:        336 :                 if( pSecondRest )
    1938                 :            :                 {
    1939                 :            :                     OSL_ENSURE( pSecondRest->InFldGrp(), "Fieldrest expected");
    1940                 :            :                     SwFldPortion *pFld = ((SwFldPortion*)pSecondRest)->Clone(
    1941         [ +  - ]:         56 :                                     ((SwFldPortion*)pSecondRest)->GetExp() );
    1942                 :         56 :                     pFld->SetFollow( sal_True );
    1943                 :         56 :                     aTmp.SetRest( pFld );
    1944                 :            :                 }
    1945 [ +  + ][ -  + ]:        336 :                 if( !rMulti.OnTop() && nFirstLen < nMultiLen )
                 [ -  + ]
    1946                 :          0 :                     bRet = sal_True;
    1947                 :            :             }
    1948                 :            :             else
    1949                 :         80 :                 aTmp.SetRest( aInf.GetRest() );
    1950                 :        416 :             aInf.SetRest( NULL );
    1951                 :            : 
    1952                 :            :             // in grid mode we temporarily have to disable the grid for the ruby line
    1953 [ #  # ][ #  # ]:        416 :             if ( bHasGrid && aTmp.IsRuby() && ! bRubyTop )
         [ -  + ][ -  + ]
    1954                 :          0 :                 aTmp.SetSnapToGrid( sal_False );
    1955                 :            : 
    1956         [ +  - ]:        416 :             BuildPortions( aTmp );
    1957                 :            : 
    1958                 :        416 :             aTmp.SetSnapToGrid( bOldGridModeAllowed );
    1959                 :            : 
    1960         [ +  - ]:        416 :             rMulti.CalcSize( *this, aInf );
    1961                 :        416 :             rMulti.GetRoot().SetRealHeight( rMulti.GetRoot().Height() );
    1962                 :        416 :             pCurr->SetRealHeight( pCurr->Height() );
    1963         [ +  + ]:        416 :             if( rMulti.IsRuby() )
    1964                 :            :             {
    1965                 :        336 :                 pNextSecond = aTmp.GetRest();
    1966         [ -  + ]:        336 :                 if( pNextFirst )
    1967                 :          0 :                     bRet = sal_True;
    1968                 :            :             }
    1969                 :            :             else
    1970                 :         80 :                 pNextFirst = aTmp.GetRest();
    1971         [ +  + ]:        752 :             if( ( !aTmp.IsRuby() && nFirstLen + pCurr->GetLen() < nMultiLen )
           [ +  +  -  + ]
                 [ +  + ]
    1972                 :        336 :                 || aTmp.GetRest() )
    1973                 :            :                 // our guess for width of multiportion was too small,
    1974                 :            :                 // text did not fit into multiportion
    1975         [ +  - ]:        416 :                 bRet = sal_True;
    1976                 :            :         }
    1977         [ +  + ]:        516 :         if( rMulti.IsRuby() )
    1978                 :        336 :             break;
    1979         [ +  + ]:        180 :         if( bRet )
    1980                 :            :         {
    1981                 :            :             // our guess for multiportion width was too small,
    1982                 :            :             // we set min to act
    1983                 :         80 :             nMinWidth = nActWidth;
    1984                 :         80 :             nActWidth = ( 3 * nMaxWidth + nMinWidth + 3 ) / 4;
    1985 [ -  + ][ #  # ]:         80 :             if ( nActWidth == nMaxWidth && rInf.GetLineStart() == rInf.GetIdx() )
                 [ -  + ]
    1986                 :            :             // we have too less space, we must allow break cuts
    1987                 :            :             // ( the first multi flag is considered during TxtPortion::_Format() )
    1988                 :          0 :                 bFirstMulti = sal_False;
    1989         [ -  + ]:         80 :             if( nActWidth <= nMinWidth )
    1990                 :          0 :                 break;
    1991                 :            :         }
    1992                 :            :         else
    1993                 :            :         {
    1994                 :            :             // For Solaris, this optimisation can causes trouble:
    1995                 :            :             // Setting this to the portion width ( = rMulti.Width() )
    1996                 :            :             // can make GetTextBreak inside SwTxtGuess::Guess return to small
    1997                 :            :             // values. Therefore we add some extra twips.
    1998         [ +  + ]:        100 :             if( nActWidth > nTmpX + rMulti.Width() + 6 )
    1999                 :         20 :                 nActWidth = nTmpX + rMulti.Width() + 6;
    2000                 :        100 :             nMaxWidth = nActWidth;
    2001                 :        100 :             nActWidth = ( 3 * nMaxWidth + nMinWidth + 3 ) / 4;
    2002         [ +  + ]:        100 :             if( nActWidth >= nMaxWidth )
    2003                 :         20 :                 break;
    2004                 :            :             // we do not allow break cuts during formatting
    2005                 :         80 :             bFirstMulti = sal_True;
    2006                 :            :         }
    2007 [ -  + ][ #  # ]:        160 :         delete pNextFirst;
    2008                 :        160 :         pNextFirst = NULL;
    2009                 :            :     } while ( sal_True );
    2010                 :            : 
    2011                 :        356 :     pMulti = pOldMulti;
    2012                 :            : 
    2013                 :        356 :     pCurr = pOldCurr;
    2014                 :        356 :     nStart = nOldStart;
    2015                 :        356 :       SetPropFont( 0 );
    2016                 :            : 
    2017                 :        356 :     rMulti.SetLen( rMulti.GetRoot().GetLen() + ( rMulti.GetRoot().GetNext() ?
    2018         [ +  - ]:        356 :         rMulti.GetRoot().GetNext()->GetLen() : 0 ) );
    2019                 :            : 
    2020         [ +  + ]:        356 :     if( rMulti.IsDouble() )
    2021                 :            :     {
    2022         [ +  - ]:         20 :         ((SwDoubleLinePortion&)rMulti).CalcBlanks( rInf );
    2023         [ +  - ]:         20 :         if( ((SwDoubleLinePortion&)rMulti).GetLineDiff() )
    2024                 :            :         {
    2025                 :         20 :             SwLineLayout* pLine = &rMulti.GetRoot();
    2026         [ +  - ]:         20 :             if( ((SwDoubleLinePortion&)rMulti).GetLineDiff() > 0 )
    2027                 :            :             {
    2028                 :         20 :                 rInf.SetIdx( nStartIdx + pLine->GetLen() );
    2029                 :         20 :                 pLine = pLine->GetNext();
    2030                 :            :             }
    2031         [ +  - ]:         20 :             if( pLine )
    2032                 :            :             {
    2033                 :         20 :                 GetInfo().SetMulti( sal_True );
    2034         [ +  - ]:         20 :                 CalcNewBlock( pLine, NULL, rMulti.Width() );
    2035                 :         20 :                 GetInfo().SetMulti( sal_False );
    2036                 :            :             }
    2037                 :         20 :             rInf.SetIdx( nStartIdx );
    2038                 :            :         }
    2039         [ +  + ]:         20 :         if( ((SwDoubleLinePortion&)rMulti).GetBrackets() )
    2040                 :            :         {
    2041                 :         16 :             rMulti.Width( rMulti.Width() +
    2042                 :         16 :                     ((SwDoubleLinePortion&)rMulti).BracketWidth() );
    2043                 :         16 :             GetInfo().X( nOldX );
    2044                 :            :         }
    2045                 :            :     }
    2046                 :            :     else
    2047                 :            :     {
    2048                 :        336 :         rMulti.ActualizeTabulator();
    2049         [ +  - ]:        336 :         if( rMulti.IsRuby() )
    2050                 :            :         {
    2051         [ +  - ]:        336 :             ((SwRubyPortion&)rMulti).Adjust( rInf );
    2052                 :        336 :             ((SwRubyPortion&)rMulti).CalcRubyOffset();
    2053                 :            :         }
    2054                 :            :     }
    2055         [ -  + ]:        356 :     if( rMulti.HasRotation() )
    2056                 :            :     {
    2057                 :          0 :         SwTwips nH = rMulti.Width();
    2058                 :          0 :         SwTwips nAsc = rMulti.GetAscent() + ( nH - rMulti.Height() )/2;
    2059         [ #  # ]:          0 :         if( nAsc > nH )
    2060                 :          0 :             nAsc = nH;
    2061         [ #  # ]:          0 :         else if( nAsc < 0 )
    2062                 :          0 :             nAsc = 0;
    2063                 :          0 :         rMulti.Width( rMulti.Height() );
    2064                 :          0 :         rMulti.Height( KSHORT(nH) );
    2065                 :          0 :         rMulti.SetAscent( KSHORT(nAsc) );
    2066                 :          0 :         bRet = ( rInf.GetPos().X() + rMulti.Width() > rInf.Width() ) &&
    2067 [ #  # ][ #  # ]:          0 :                  nStartIdx != rInf.GetLineStart();
    2068                 :            :     }
    2069         [ -  + ]:        356 :     else if ( rMulti.IsBidi() )
    2070                 :            :     {
    2071 [ #  # ][ #  # ]:          0 :         bRet = rMulti.GetLen() < nMultiLen || pNextFirst;
    2072                 :            :     }
    2073                 :            : 
    2074                 :            :     // line break has to be performed!
    2075         [ -  + ]:        356 :     if( bRet )
    2076                 :            :     {
    2077                 :            :         OSL_ENSURE( !pNextFirst || pNextFirst->InFldGrp(),
    2078                 :            :             "BuildMultiPortion: Surprising restportion, field expected" );
    2079                 :            :         SwMultiPortion *pTmp;
    2080         [ #  # ]:          0 :         if( rMulti.IsDouble() )
    2081                 :            :             pTmp = new SwDoubleLinePortion( ((SwDoubleLinePortion&)rMulti),
    2082 [ #  # ][ #  # ]:          0 :                                             nMultiLen + rInf.GetIdx() );
    2083         [ #  # ]:          0 :         else if( rMulti.IsRuby() )
    2084                 :            :         {
    2085                 :            :             OSL_ENSURE( !pNextSecond || pNextSecond->InFldGrp(),
    2086                 :            :                 "BuildMultiPortion: Surprising restportion, field expected" );
    2087                 :            : 
    2088         [ #  # ]:          0 :             if ( rInf.GetIdx() == rInf.GetLineStart() )
    2089                 :            :             {
    2090                 :            :                 // the ruby portion has to be split in two portions
    2091                 :            :                 pTmp = new SwRubyPortion( ((SwRubyPortion&)rMulti),
    2092 [ #  # ][ #  # ]:          0 :                                           nMultiLen + rInf.GetIdx() );
    2093                 :            : 
    2094         [ #  # ]:          0 :                 if( pNextSecond )
    2095                 :            :                 {
    2096 [ #  # ][ #  # ]:          0 :                     pTmp->GetRoot().SetNext( new SwLineLayout() );
    2097                 :          0 :                     pTmp->GetRoot().GetNext()->SetPortion( pNextSecond );
    2098                 :            :                 }
    2099                 :          0 :                 pTmp->SetFollowFld();
    2100                 :            :             }
    2101                 :            :             else
    2102                 :            :             {
    2103                 :            :                 // we try to keep our ruby portion together
    2104         [ #  # ]:          0 :                 lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
    2105                 :          0 :                 pTmp = 0;
    2106                 :            :             }
    2107                 :            :         }
    2108         [ #  # ]:          0 :         else if( rMulti.HasRotation() )
    2109                 :            :         {
    2110                 :            :             // we try to keep our rotated portion together
    2111         [ #  # ]:          0 :             lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
    2112                 :          0 :             pTmp = new SwRotatedPortion( nMultiLen + rInf.GetIdx(),
    2113 [ #  # ][ #  # ]:          0 :                                          rMulti.GetDirection() );
    2114                 :            :         }
    2115                 :            :         // during a recursion of BuildMultiPortions we may not build
    2116                 :            :         // a new SwBidiPortion, this would cause a memory leak
    2117 [ #  # ][ #  # ]:          0 :         else if( rMulti.IsBidi() && ! pMulti )
                 [ #  # ]
    2118                 :            :         {
    2119         [ #  # ]:          0 :             if ( ! rMulti.GetLen() )
    2120         [ #  # ]:          0 :                 lcl_TruncateMultiPortion( rMulti, rInf, nStartIdx );
    2121                 :            : 
    2122                 :            :             // If there is a HolePortion at the end of the bidi portion,
    2123                 :            :             // it has to be moved behind the bidi portion. Otherwise
    2124                 :            :             // the visual cursor travelling gets into trouble.
    2125                 :          0 :             SwLineLayout& aRoot = rMulti.GetRoot();
    2126                 :          0 :             SwLinePortion* pPor = aRoot.GetFirstPortion();
    2127         [ #  # ]:          0 :             while ( pPor )
    2128                 :            :             {
    2129 [ #  # ][ #  # ]:          0 :                 if ( pPor->GetPortion() && pPor->GetPortion()->IsHolePortion() )
                 [ #  # ]
    2130                 :            :                 {
    2131                 :          0 :                     SwLinePortion* pHolePor = pPor->GetPortion();
    2132                 :          0 :                     pPor->SetPortion( NULL );
    2133                 :          0 :                     aRoot.SetLen( aRoot.GetLen() - pHolePor->GetLen() );
    2134                 :          0 :                     rMulti.SetLen( rMulti.GetLen() - pHolePor->GetLen() );
    2135                 :          0 :                     rMulti.SetPortion( pHolePor );
    2136                 :          0 :                     break;
    2137                 :            :                 }
    2138                 :          0 :                 pPor = pPor->GetPortion();
    2139                 :            :             }
    2140                 :            : 
    2141                 :          0 :             pTmp = new SwBidiPortion( nMultiLen + rInf.GetIdx(),
    2142 [ #  # ][ #  # ]:          0 :                                     ((SwBidiPortion&)rMulti).GetLevel() );
    2143                 :            :         }
    2144                 :            :         else
    2145                 :          0 :             pTmp = NULL;
    2146                 :            : 
    2147 [ #  # ][ #  # ]:          0 :         if ( ! rMulti.GetLen() && rInf.GetLast() )
                 [ #  # ]
    2148                 :            :         {
    2149         [ #  # ]:          0 :             SeekAndChgBefore( rInf );
    2150         [ #  # ]:          0 :             rInf.GetLast()->FormatEOL( rInf );
    2151                 :            :         }
    2152                 :            : 
    2153 [ #  # ][ #  # ]:          0 :         if( pNextFirst && pTmp )
    2154                 :            :         {
    2155                 :          0 :             pTmp->SetFollowFld();
    2156                 :          0 :             pTmp->GetRoot().SetPortion( pNextFirst );
    2157                 :            :         }
    2158                 :            :         else
    2159                 :            :             // A follow field portion is still waiting. If nobody wants it,
    2160                 :            :             // we delete it.
    2161 [ #  # ][ #  # ]:          0 :             delete pNextFirst;
    2162                 :            : 
    2163                 :          0 :         rInf.SetRest( pTmp );
    2164                 :            :     }
    2165                 :            : 
    2166                 :        356 :     rInf.SetTxt( *pOldTxt );
    2167                 :        356 :     rInf.SetPaintOfst( nOldPaintOfst );
    2168                 :        356 :     rInf.SetStop( aInf.IsStop() );
    2169                 :        356 :     rInf.SetNumDone( sal_True );
    2170                 :        356 :     rInf.SetFtnDone( sal_True );
    2171         [ +  - ]:        356 :     SeekAndChg( rInf );
    2172 [ +  + ][ +  - ]:        356 :     delete pFirstRest;
    2173 [ +  + ][ +  - ]:        356 :     delete pSecondRest;
    2174 [ +  + ][ +  - ]:        356 :     delete pFontSave;
    2175 [ +  - ][ +  - ]:        356 :     return bRet;
                 [ +  - ]
    2176                 :            : }
    2177                 :            : 
    2178                 :            : /*--------------------------------------------------
    2179                 :            :  * SwTxtFormatter::MakeRestPortion(..)
    2180                 :            :  * When a fieldportion at the end of line breaks and needs a following
    2181                 :            :  * fieldportion in the next line, then the "restportion" of the formatinfo
    2182                 :            :  * has to be set. Normally this happens during the formatting of the first
    2183                 :            :  * part of the fieldportion.
    2184                 :            :  * But sometimes the formatting starts at the line with the following part,
    2185                 :            :  * especially when the following part is on the next page.
    2186                 :            :  * In this case the MakeRestPortion-function has to create the following part.
    2187                 :            :  * The first parameter is the line that contains possibly a first part
    2188                 :            :  * of a field. When the function finds such field part, it creates the right
    2189                 :            :  * restportion. This may be a multiportion, e.g. if the field is surrounded by
    2190                 :            :  * a doubleline- or ruby-portion.
    2191                 :            :  * The second parameter is the start index of the line.
    2192                 :            :  * --------------------------------------------------*/
    2193                 :            : 
    2194                 :         70 : SwLinePortion* SwTxtFormatter::MakeRestPortion( const SwLineLayout* pLine,
    2195                 :            :     xub_StrLen nPosition )
    2196                 :            : {
    2197         [ -  + ]:         70 :     if( !nPosition )
    2198                 :          0 :         return NULL;
    2199                 :         70 :     xub_StrLen nMultiPos = nPosition - pLine->GetLen();
    2200                 :         70 :     const SwMultiPortion *pTmpMulti = NULL;
    2201                 :         70 :     const SwMultiPortion *pHelpMulti = NULL;
    2202                 :         70 :     const SwLinePortion* pPor = pLine->GetFirstPortion();
    2203                 :         70 :     SwFldPortion *pFld = NULL;
    2204         [ +  + ]:        148 :     while( pPor )
    2205                 :            :     {
    2206         [ +  - ]:         78 :         if( pPor->GetLen() )
    2207                 :            :         {
    2208         [ +  - ]:         78 :             if( !pHelpMulti )
    2209                 :            :             {
    2210                 :         78 :                 nMultiPos = nMultiPos + pPor->GetLen();
    2211                 :         78 :                 pTmpMulti = NULL;
    2212                 :            :             }
    2213                 :            :         }
    2214         [ -  + ]:         78 :         if( pPor->InFldGrp() )
    2215                 :            :         {
    2216         [ #  # ]:          0 :             if( !pHelpMulti )
    2217                 :          0 :                 pTmpMulti = NULL;
    2218                 :          0 :             pFld = (SwFldPortion*)pPor;
    2219                 :            :         }
    2220         [ -  + ]:         78 :         else if( pPor->IsMultiPortion() )
    2221                 :            :         {
    2222                 :            :             OSL_ENSURE( !pHelpMulti || pHelpMulti->IsBidi(),
    2223                 :            :                     "Nested multiportions are forbidden." );
    2224                 :            : 
    2225                 :          0 :             pFld = NULL;
    2226                 :          0 :             pTmpMulti = (SwMultiPortion*)pPor;
    2227                 :            :         }
    2228                 :         78 :         pPor = pPor->GetPortion();
    2229                 :            :         // If the last portion is a multi-portion, we enter it
    2230                 :            :         // and look for a field portion inside.
    2231                 :            :         // If we are already in a multiportion, we could change to the
    2232                 :            :         // next line
    2233 [ -  + ][ +  + ]:         78 :         if( !pPor && pTmpMulti )
    2234                 :            :         {
    2235         [ #  # ]:          0 :             if( pHelpMulti )
    2236                 :            :             {   // We're already inside the multiportion, let's take the second
    2237                 :            :                 // line, if we are in a double line portion
    2238         [ #  # ]:          0 :                 if( !pHelpMulti->IsRuby() )
    2239                 :          0 :                     pPor = pHelpMulti->GetRoot().GetNext();
    2240                 :          0 :                 pTmpMulti = NULL;
    2241                 :            :             }
    2242                 :            :             else
    2243                 :            :             {   // Now we enter a multiportion, in a ruby portion we take the
    2244                 :            :                 // main line, not the phonetic line, in a doublelineportion we
    2245                 :            :                 // starts with the first line.
    2246                 :          0 :                 pHelpMulti = pTmpMulti;
    2247                 :          0 :                 nMultiPos = nMultiPos - pHelpMulti->GetLen();
    2248 [ #  # ][ #  # ]:          0 :                 if( pHelpMulti->IsRuby() && pHelpMulti->OnTop() )
                 [ #  # ]
    2249                 :          0 :                     pPor = pHelpMulti->GetRoot().GetNext();
    2250                 :            :                 else
    2251                 :          0 :                     pPor = pHelpMulti->GetRoot().GetFirstPortion();
    2252                 :            :             }
    2253                 :            :         }
    2254                 :            :     }
    2255 [ -  + ][ #  # ]:         70 :     if( pFld && !pFld->HasFollow() )
                 [ -  + ]
    2256                 :          0 :         pFld = NULL;
    2257                 :            : 
    2258                 :         70 :     SwLinePortion *pRest = NULL;
    2259         [ -  + ]:         70 :     if( pFld )
    2260                 :            :     {
    2261         [ #  # ]:          0 :         const SwTxtAttr *pHint = GetAttr( nPosition - 1 );
    2262 [ #  # ][ #  # ]:          0 :         if( pHint && pHint->Which() == RES_TXTATR_FIELD )
         [ #  # ][ #  # ]
    2263                 :            :         {
    2264         [ #  # ]:          0 :             pRest = NewFldPortion( GetInfo(), pHint );
    2265         [ #  # ]:          0 :             if( pRest->InFldGrp() )
    2266         [ #  # ]:          0 :                 ((SwFldPortion*)pRest)->TakeNextOffset( pFld );
    2267                 :            :             else
    2268                 :            :             {
    2269 [ #  # ][ #  # ]:          0 :                 delete pRest;
    2270                 :          0 :                 pRest = NULL;
    2271                 :            :             }
    2272                 :            :         }
    2273                 :            :     }
    2274         [ +  - ]:         70 :     if( !pHelpMulti )
    2275                 :         70 :         return pRest;
    2276                 :            : 
    2277                 :          0 :     nPosition = nMultiPos + pHelpMulti->GetLen();
    2278         [ #  # ]:          0 :     SwMultiCreator* pCreate = GetInfo().GetMultiCreator( nMultiPos, 0 );
    2279                 :            : 
    2280         [ #  # ]:          0 :     if ( !pCreate )
    2281                 :            :     {
    2282                 :            :         OSL_ENSURE( !pHelpMulti->GetLen(), "Multiportion without attribut?" );
    2283         [ #  # ]:          0 :         if ( nMultiPos )
    2284                 :          0 :             --nMultiPos;
    2285         [ #  # ]:          0 :         pCreate = GetInfo().GetMultiCreator( --nMultiPos, 0 );
    2286                 :            :     }
    2287                 :            : 
    2288         [ #  # ]:          0 :     if (!pCreate)
    2289                 :          0 :         return pRest;
    2290                 :            : 
    2291 [ #  # ][ #  # ]:          0 :     if( pRest || nMultiPos > nPosition || ( pHelpMulti->IsRuby() &&
           [ #  #  #  # ]
                 [ #  # ]
    2292                 :          0 :         ((SwRubyPortion*)pHelpMulti)->GetRubyOffset() < STRING_LEN ) )
    2293                 :            :     {
    2294                 :            :         SwMultiPortion* pTmp;
    2295         [ #  # ]:          0 :         if( pHelpMulti->IsDouble() )
    2296 [ #  # ][ #  # ]:          0 :             pTmp = new SwDoubleLinePortion( *pCreate, nMultiPos );
    2297         [ #  # ]:          0 :         else if( pHelpMulti->IsBidi() )
    2298 [ #  # ][ #  # ]:          0 :             pTmp = new SwBidiPortion( nMultiPos, pCreate->nLevel );
    2299         [ #  # ]:          0 :         else if( pHelpMulti->IsRuby() )
    2300                 :            :         {
    2301                 :            :             sal_Bool bRubyTop;
    2302                 :          0 :             sal_Bool* pRubyPos = 0;
    2303                 :            : 
    2304         [ #  # ]:          0 :             if ( GetInfo().SnapToGrid() )
    2305                 :            :             {
    2306 [ #  # ][ #  # ]:          0 :                 GETGRID( pFrm->FindPageFrm() )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    2307         [ #  # ]:          0 :                 if ( pGrid )
    2308                 :            :                 {
    2309                 :          0 :                     bRubyTop = ! pGrid->GetRubyTextBelow();
    2310                 :          0 :                     pRubyPos = &bRubyTop;
    2311                 :            :                 }
    2312                 :            :             }
    2313                 :            : 
    2314                 :          0 :             pTmp = new SwRubyPortion( *pCreate, *GetInfo().GetFont(),
    2315                 :          0 :                                       *pFrm->GetTxtNode()->getIDocumentSettingAccess(),
    2316                 :          0 :                                        nMultiPos, ((SwRubyPortion*)pHelpMulti)->GetRubyOffset(),
    2317         [ #  # ]:          0 :                                        pRubyPos );
           [ #  #  #  # ]
    2318                 :            :         }
    2319         [ #  # ]:          0 :         else if( pHelpMulti->HasRotation() )
    2320 [ #  # ][ #  # ]:          0 :             pTmp = new SwRotatedPortion( nMultiPos, pHelpMulti->GetDirection() );
    2321                 :            :         else
    2322                 :            :         {
    2323                 :          0 :             delete pCreate;
    2324                 :          0 :             return pRest;
    2325                 :            :         }
    2326                 :          0 :         delete pCreate;
    2327                 :          0 :         pTmp->SetFollowFld();
    2328         [ #  # ]:          0 :         if( pRest )
    2329                 :            :         {
    2330                 :          0 :             SwLineLayout *pLay = &pTmp->GetRoot();
    2331 [ #  # ][ #  # ]:          0 :             if( pTmp->IsRuby() && pTmp->OnTop() )
                 [ #  # ]
    2332                 :            :             {
    2333 [ #  # ][ #  # ]:          0 :                 pLay->SetNext( new SwLineLayout() );
    2334                 :          0 :                 pLay = pLay->GetNext();
    2335                 :            :             }
    2336                 :          0 :             pLay->SetPortion( pRest );
    2337                 :            :         }
    2338                 :          0 :         return pTmp;
    2339                 :            :     }
    2340                 :         70 :     return pRest;
    2341                 :            : }
    2342                 :            : 
    2343                 :            : 
    2344                 :            : 
    2345                 :            : /*--------------------------------------------------
    2346                 :            :  * SwTxtCursorSave notes the start and current line of a SwTxtCursor,
    2347                 :            :  * sets them to the values for GetCrsrOfst inside a multiportion
    2348                 :            :  * and restores them in the destructor.
    2349                 :            :  * --------------------------------------------------*/
    2350                 :            : 
    2351                 :          0 : SwTxtCursorSave::SwTxtCursorSave( SwTxtCursor* pTxtCursor,
    2352                 :            :                                   SwMultiPortion* pMulti,
    2353                 :            :                                   SwTwips nY,
    2354                 :            :                                   sal_uInt16& nX,
    2355                 :            :                                   xub_StrLen nCurrStart,
    2356                 :            :                                   long nSpaceAdd )
    2357                 :            : {
    2358                 :          0 :     pTxtCrsr = pTxtCursor;
    2359                 :          0 :     nStart = pTxtCursor->nStart;
    2360                 :          0 :     pTxtCursor->nStart = nCurrStart;
    2361                 :          0 :     pCurr = pTxtCursor->pCurr;
    2362                 :          0 :     pTxtCursor->pCurr = &pMulti->GetRoot();
    2363   [ #  #  #  # ]:          0 :     while( pTxtCursor->Y() + pTxtCursor->GetLineHeight() < nY &&
                 [ #  # ]
    2364                 :          0 :         pTxtCursor->Next() )
    2365                 :            :         ; // nothing
    2366                 :          0 :     nWidth = pTxtCursor->pCurr->Width();
    2367                 :          0 :     nOldProp = pTxtCursor->GetPropFont();
    2368                 :            : 
    2369 [ #  # ][ #  # ]:          0 :     if ( pMulti->IsDouble() || pMulti->IsBidi() )
                 [ #  # ]
    2370                 :            :     {
    2371                 :          0 :         bSpaceChg = pMulti->ChgSpaceAdd( pTxtCursor->pCurr, nSpaceAdd );
    2372                 :            : 
    2373                 :            :         sal_uInt16 nSpaceCnt;
    2374         [ #  # ]:          0 :         if ( pMulti->IsDouble() )
    2375                 :            :         {
    2376                 :          0 :             pTxtCursor->SetPropFont( 50 );
    2377                 :          0 :             nSpaceCnt = ((SwDoubleLinePortion*)pMulti)->GetSpaceCnt();
    2378                 :            :         }
    2379                 :            :         else
    2380                 :            :         {
    2381                 :          0 :             const xub_StrLen nOldIdx = pTxtCursor->GetInfo().GetIdx();
    2382                 :          0 :             pTxtCursor->GetInfo().SetIdx ( nCurrStart );
    2383                 :          0 :             nSpaceCnt = ((SwBidiPortion*)pMulti)->GetSpaceCnt(pTxtCursor->GetInfo());
    2384                 :          0 :             pTxtCursor->GetInfo().SetIdx ( nOldIdx );
    2385                 :            :         }
    2386                 :            : 
    2387 [ #  # ][ #  # ]:          0 :         if( nSpaceAdd > 0 && !pMulti->HasTabulator() )
                 [ #  # ]
    2388                 :          0 :             pTxtCursor->pCurr->Width( static_cast<sal_uInt16>(nWidth + nSpaceAdd * nSpaceCnt / SPACING_PRECISION_FACTOR ) );
    2389                 :            : 
    2390                 :            :         // For a BidiPortion we have to calculate the offset from the
    2391                 :            :         // end of the portion
    2392 [ #  # ][ #  # ]:          0 :         if ( nX && pMulti->IsBidi() )
                 [ #  # ]
    2393                 :          0 :             nX = pTxtCursor->pCurr->Width() - nX;
    2394                 :            :     }
    2395                 :            :     else
    2396                 :          0 :         bSpaceChg = sal_False;
    2397                 :          0 : }
    2398                 :            : 
    2399                 :          0 : SwTxtCursorSave::~SwTxtCursorSave()
    2400                 :            : {
    2401         [ #  # ]:          0 :     if( bSpaceChg )
    2402                 :          0 :         SwDoubleLinePortion::ResetSpaceAdd( pTxtCrsr->pCurr );
    2403                 :          0 :     pTxtCrsr->pCurr->Width( KSHORT(nWidth) );
    2404                 :          0 :     pTxtCrsr->pCurr = pCurr;
    2405                 :          0 :     pTxtCrsr->nStart = nStart;
    2406                 :          0 :     pTxtCrsr->SetPropFont( nOldProp );
    2407                 :          0 : }
    2408                 :            : 
    2409                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10