LCOV - code coverage report
Current view: top level - sw/source/core/text - porfld.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 321 667 48.1 %
Date: 2014-11-03 Functions: 26 41 63.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <hintids.hxx>
      21             : 
      22             : #include <com/sun/star/i18n/ScriptType.hpp>
      23             : #include <vcl/graph.hxx>
      24             : #include <editeng/brushitem.hxx>
      25             : #include <vcl/metric.hxx>
      26             : #include <vcl/outdev.hxx>
      27             : #include <viewopt.hxx>
      28             : #include <SwPortionHandler.hxx>
      29             : #include <porlay.hxx>
      30             : #include <porfld.hxx>
      31             : #include <inftxt.hxx>
      32             : #include <blink.hxx>
      33             : #include <frmtool.hxx>
      34             : #include <viewsh.hxx>
      35             : #include <docsh.hxx>
      36             : #include <doc.hxx>
      37             : #include <IDocumentSettingAccess.hxx>
      38             : #include "rootfrm.hxx"
      39             : #include <breakit.hxx>
      40             : #include <porrst.hxx>
      41             : #include <porftn.hxx>
      42             : #include <accessibilityoptions.hxx>
      43             : #include <editeng/lrspitem.hxx>
      44             : #include <unicode/ubidi.h>
      45             : 
      46             : using namespace ::com::sun::star;
      47             : 
      48       23234 : SwLinePortion *SwFldPortion::Compress()
      49       23234 : { return (GetLen() || !aExpand.isEmpty() || SwLinePortion::Compress()) ? this : 0; }
      50             : 
      51         364 : SwFldPortion *SwFldPortion::Clone( const OUString &rExpand ) const
      52             : {
      53             :     SwFont *pNewFnt;
      54         364 :     if( 0 != ( pNewFnt = pFnt ) )
      55             :     {
      56         336 :         pNewFnt = new SwFont( *pFnt );
      57             :     }
      58             :     // #i107143#
      59             :     // pass placeholder property to created <SwFldPortion> instance.
      60         364 :     SwFldPortion* pClone = new SwFldPortion( rExpand, pNewFnt, bPlaceHolder );
      61         364 :     pClone->SetNextOffset( nNextOffset );
      62         364 :     pClone->m_bNoLength = this->m_bNoLength;
      63         364 :     return pClone;
      64             : }
      65             : 
      66           0 : void SwFldPortion::TakeNextOffset( const SwFldPortion* pFld )
      67             : {
      68             :     OSL_ENSURE( pFld, "TakeNextOffset: Missing Source" );
      69           0 :     nNextOffset = pFld->GetNextOffset();
      70           0 :     aExpand = aExpand.replaceAt( 0, nNextOffset, "" );
      71           0 :     bFollow = true;
      72           0 : }
      73             : 
      74       23286 : SwFldPortion::SwFldPortion( const OUString &rExpand, SwFont *pFont, bool bPlaceHold )
      75             :     : aExpand(rExpand), pFnt(pFont), nNextOffset(0), nNextScriptChg(COMPLETE_STRING), nViewWidth(0)
      76             :     , bFollow( false ), bLeft( false), bHide( false)
      77             :     , bCenter (false), bHasFollow( false )
      78             :     , bAnimated( false), bNoPaint( false)
      79             :     , bReplace( false), bPlaceHolder( bPlaceHold )
      80             :     , m_bNoLength( false )
      81       23286 :     , m_nAttrFldType(0)
      82             : {
      83       23286 :     SetWhichPor( POR_FLD );
      84       23286 : }
      85             : 
      86          10 : SwFldPortion::SwFldPortion( const SwFldPortion& rFld )
      87             :     : SwExpandPortion( rFld )
      88             :     , aExpand( rFld.GetExp() )
      89          10 :     , nNextOffset( rFld.GetNextOffset() )
      90          10 :     , nNextScriptChg( rFld.GetNextScriptChg() )
      91             :     , nViewWidth( rFld.nViewWidth )
      92          10 :     , bFollow( rFld.IsFollow() )
      93          10 :     , bLeft( rFld.IsLeft() )
      94          10 :     , bHide( rFld.IsHide() )
      95          10 :     , bCenter( rFld.IsCenter() )
      96          10 :     , bHasFollow( rFld.HasFollow() )
      97             :     , bAnimated ( rFld.bAnimated )
      98             :     , bNoPaint( rFld.bNoPaint)
      99             :     , bReplace( rFld.bReplace )
     100             :     , bPlaceHolder( rFld.bPlaceHolder )
     101             :     , m_bNoLength( rFld.m_bNoLength )
     102          80 :     , m_nAttrFldType( rFld.m_nAttrFldType)
     103             : {
     104          10 :     if ( rFld.HasFont() )
     105          10 :         pFnt = new SwFont( *rFld.GetFont() );
     106             :     else
     107           0 :         pFnt = 0;
     108             : 
     109          10 :     SetWhichPor( POR_FLD );
     110          10 : }
     111             : 
     112       52800 : SwFldPortion::~SwFldPortion()
     113             : {
     114       23296 :     delete pFnt;
     115       23296 :     if( pBlink )
     116         136 :         pBlink->Delete( this );
     117       29504 : }
     118             : 
     119        1028 : sal_uInt16 SwFldPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
     120             : {
     121             :     // even though this is const, nViewWidth should be computed at the very end:
     122        1028 :     SwFldPortion* pThis = (SwFldPortion*)this;
     123        4112 :     if( !Width() && rInf.OnWin() && !rInf.GetOpt().IsPagePreview() &&
     124        3084 :             !rInf.GetOpt().IsReadonly() && SwViewOption::IsFieldShadings() )
     125             :     {
     126        1028 :         if( !nViewWidth )
     127         474 :             pThis->nViewWidth = rInf.GetTxtSize(OUString(' ')).Width();
     128             :     }
     129             :     else
     130           0 :         pThis->nViewWidth = 0;
     131        1028 :     return nViewWidth;
     132             : }
     133             : 
     134             : // 8653: in keinem Fall nur SetLen(0);
     135             : 
     136             : class SwFldSlot
     137             : {
     138             :     const OUString *pOldTxt;
     139             :     OUString aTxt;
     140             :     sal_Int32 nIdx;
     141             :     sal_Int32 nLen;
     142             :     SwTxtFormatInfo *pInf;
     143             :     bool bOn;
     144             : public:
     145             :     SwFldSlot( const SwTxtFormatInfo* pNew, const SwFldPortion *pPor );
     146             :     ~SwFldSlot();
     147             : };
     148             : 
     149       22944 : SwFldSlot::SwFldSlot( const SwTxtFormatInfo* pNew, const SwFldPortion *pPor )
     150             :     : pOldTxt(NULL)
     151             :     , nIdx(0)
     152             :     , nLen(0)
     153       22944 :     , pInf(NULL)
     154             : {
     155       22944 :     bOn = pPor->GetExpTxt( *pNew, aTxt );
     156             : 
     157             :     // Der Text wird ausgetauscht...
     158       22944 :     if( bOn )
     159             :     {
     160       22944 :         pInf = (SwTxtFormatInfo*)pNew;
     161       22944 :         nIdx = pInf->GetIdx();
     162       22944 :         nLen = pInf->GetLen();
     163       22944 :         pOldTxt = &(pInf->GetTxt());
     164       22944 :         pInf->SetLen( aTxt.getLength() );
     165       22944 :         if( pPor->IsFollow() )
     166             :         {
     167        8366 :             pInf->SetFakeLineStart( nIdx > pInf->GetLineStart() );
     168        8366 :             pInf->SetIdx( 0 );
     169             :         }
     170             :         else
     171             :         {
     172       14578 :             aTxt = (*pOldTxt).replaceAt(nIdx, 1, aTxt);
     173             :         }
     174       22944 :         pInf->SetTxt( aTxt );
     175             :     }
     176       22944 : }
     177             : 
     178       45888 : SwFldSlot::~SwFldSlot()
     179             : {
     180       22944 :     if( bOn )
     181             :     {
     182       22944 :         pInf->SetTxt( *pOldTxt );
     183       22944 :         pInf->SetIdx( nIdx );
     184       22944 :         pInf->SetLen( nLen );
     185       22944 :         pInf->SetFakeLineStart( false );
     186             :     }
     187       22944 : }
     188             : 
     189       22944 : void SwFldPortion::CheckScript( const SwTxtSizeInfo &rInf )
     190             : {
     191       22944 :     OUString aTxt;
     192       22944 :     if( GetExpTxt( rInf, aTxt ) && !aTxt.isEmpty() && g_pBreakIt->GetBreakIter().is() )
     193             :     {
     194       14402 :         sal_uInt8 nActual = pFnt ? pFnt->GetActual() : rInf.GetFont()->GetActual();
     195       14402 :         sal_uInt16 nScript = g_pBreakIt->GetBreakIter()->getScriptType( aTxt, 0 );
     196       14402 :         sal_Int32 nChg = 0;
     197       14402 :         if( i18n::ScriptType::WEAK == nScript )
     198             :         {
     199        6148 :             nChg = g_pBreakIt->GetBreakIter()->endOfScript(aTxt,0,nScript);
     200        6148 :             if (nChg < aTxt.getLength() && nChg >= 0)
     201        6030 :                 nScript = g_pBreakIt->GetBreakIter()->getScriptType( aTxt, nChg );
     202             :         }
     203             : 
     204             :         // nNextScriptChg will be evaluated during SwFldPortion::Format()
     205             : 
     206       14402 :         if (nChg < aTxt.getLength() && nChg >= 0)
     207       14284 :             nNextScriptChg = g_pBreakIt->GetBreakIter()->endOfScript( aTxt, nChg, nScript );
     208             :         else
     209         118 :             nNextScriptChg = aTxt.getLength();
     210             : 
     211             :         sal_uInt8 nTmp;
     212       14402 :         switch ( nScript ) {
     213       14248 :             case i18n::ScriptType::LATIN : nTmp = SW_LATIN; break;
     214           0 :             case i18n::ScriptType::ASIAN : nTmp = SW_CJK; break;
     215          36 :             case i18n::ScriptType::COMPLEX : nTmp = SW_CTL; break;
     216         118 :             default: nTmp = nActual;
     217             :         }
     218             : 
     219             :         // #i16354# Change script type for RTL text to CTL.
     220       14402 :         const SwScriptInfo& rSI = rInf.GetParaPortion()->GetScriptInfo();
     221             :         // #i98418#
     222       26454 :         const sal_uInt8 nFldDir = ( IsNumberPortion() || IsFtnNumPortion() ) ?
     223             :                              rSI.GetDefaultDir() :
     224       16988 :                              rSI.DirType( IsFollow() ? rInf.GetIdx() - 1 : rInf.GetIdx() );
     225             : 
     226       14402 :         bool bPerformUBA = UBIDI_LTR != nFldDir || i18n::ScriptType::COMPLEX == nScript;
     227       14402 :         if (bPerformUBA)
     228             :         {
     229          36 :             UErrorCode nError = U_ZERO_ERROR;
     230          36 :             UBiDi* pBidi = ubidi_openSized( aTxt.getLength(), 0, &nError );
     231          36 :             ubidi_setPara( pBidi, reinterpret_cast<const UChar *>(aTxt.getStr()), aTxt.getLength(), nFldDir, NULL, &nError );
     232             :             int32_t nEnd;
     233             :             UBiDiLevel nCurrDir;
     234          36 :             ubidi_getLogicalRun( pBidi, 0, &nEnd, &nCurrDir );
     235          36 :             ubidi_close( pBidi );
     236          36 :             const sal_Int32 nNextDirChg = nEnd;
     237          36 :             nNextScriptChg = std::min( nNextScriptChg, nNextDirChg );
     238             : 
     239             :             // #i89825# change the script type also to CTL
     240             :             // if there is no strong LTR char in the LTR run (numbers)
     241          36 :             if ( nCurrDir != UBIDI_RTL )
     242             :             {
     243           0 :                 nCurrDir = UBIDI_RTL;
     244           0 :                 for( sal_Int32 nCharIdx = 0; nCharIdx < nEnd; ++nCharIdx )
     245             :                 {
     246           0 :                     UCharDirection nCharDir = u_charDirection ( aTxt[ nCharIdx ]);
     247           0 :                     if ( nCharDir == U_LEFT_TO_RIGHT ||
     248           0 :                          nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
     249             :                          nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
     250             :                     {
     251           0 :                         nCurrDir = UBIDI_LTR;
     252           0 :                         break;
     253             :                     }
     254             :                 }
     255             :             }
     256             : 
     257          36 :             if (nCurrDir == UBIDI_RTL)
     258             :             {
     259          36 :                 nTmp = SW_CTL;
     260             :                 //If we decided that this range was RTL after all and the
     261             :                 //previous range was complex but clipped to the start of this
     262             :                 //range, then extend it to be complex over the additional RTL
     263             :                 //range
     264          36 :                 if (nScript == i18n::ScriptType::COMPLEX)
     265          36 :                     nNextScriptChg = nNextDirChg;
     266             :             }
     267             :         }
     268             : 
     269             :         // #i98418#
     270             :         // keep determined script type for footnote portions as preferred script type.
     271             :         // For footnote portions a font can not be created directly - see footnote
     272             :         // portion format method.
     273       14402 :         if ( IsFtnPortion() )
     274             :         {
     275         278 :             static_cast<SwFtnPortion*>(this)->SetPreferredScriptType( nTmp );
     276             :         }
     277       14124 :         else if ( nTmp != nActual )
     278             :         {
     279          72 :             if( !pFnt )
     280           0 :                 pFnt = new SwFont( *rInf.GetFont() );
     281          72 :             pFnt->SetActual( nTmp );
     282             :         }
     283       22944 :     }
     284       22944 : }
     285             : 
     286       22944 : bool SwFldPortion::Format( SwTxtFormatInfo &rInf )
     287             : {
     288             :     // Scope wegen aDiffTxt::DTOR!
     289             :     sal_Int32 nRest;
     290       22944 :     bool bFull = false;
     291       22944 :     bool bEOL = false;
     292       22944 :     const sal_Int32 nTxtRest = rInf.GetTxt().getLength() - rInf.GetIdx();
     293             :     {
     294       22944 :         SwFldSlot aDiffTxt( &rInf, this );
     295       45888 :         SwLayoutModeModifier aLayoutModeModifier( *rInf.GetOut() );
     296       22944 :         aLayoutModeModifier.SetAuto();
     297             : 
     298             :         // Field portion has to be split in several parts if
     299             :         // 1. There are script/direction changes inside the field
     300             :         // 2. There are portion breaks (tab, break) inside the field:
     301       22944 :         const sal_Int32 nOldFullLen = rInf.GetLen();
     302       22944 :         sal_Int32 nFullLen = rInf.ScanPortionEnd( rInf.GetIdx(), rInf.GetIdx() + nOldFullLen ) - rInf.GetIdx();
     303       22944 :         if ( nNextScriptChg < nFullLen )
     304             :         {
     305          36 :             nFullLen = nNextScriptChg;
     306          36 :             rInf.SetHookChar( 0 );
     307             :         }
     308       22944 :         rInf.SetLen( nFullLen );
     309             : 
     310       22944 :         if ( COMPLETE_STRING != rInf.GetUnderScorePos() &&
     311           0 :              rInf.GetUnderScorePos() > rInf.GetIdx() )
     312           0 :              rInf.SetUnderScorePos( rInf.GetIdx() );
     313             : 
     314       22944 :         if( pFnt )
     315       16878 :             pFnt->GoMagic( rInf.GetVsh(), pFnt->GetActual() );
     316             : 
     317       45888 :         SwFontSave aSave( rInf, pFnt );
     318             : 
     319             :         // 8674: Laenge muss 0 sein, bei bFull nach Format ist die Laenge
     320             :         // gesetzt und wird in nRest uebertragen. Ansonsten bleibt die
     321             :         // Laenge erhalten und wuerde auch in nRest einfliessen!
     322       22944 :         SetLen(0);
     323       22944 :         const sal_Int32 nFollow = IsFollow() ? 0 : 1;
     324             : 
     325             :         // So komisch es aussieht, die Abfrage auf GetLen() muss wegen der
     326             :         // ExpandPortions _hinter_ aDiffTxt (vgl. SoftHyphs)
     327             :         // false returnen wegen SetFull ...
     328       22944 :         if( !nFullLen )
     329             :         {
     330             :             // nicht Init(), weil wir Hoehe und Ascent brauchen
     331        8682 :             Width(0);
     332        8682 :             bFull = rInf.Width() <= rInf.GetPos().X();
     333             :         }
     334             :         else
     335             :         {
     336       14262 :             sal_Int32 nOldLineStart = rInf.GetLineStart();
     337       14262 :             if( IsFollow() )
     338         382 :                 rInf.SetLineStart( 0 );
     339       14262 :             rInf.SetNotEOL( nFullLen == nOldFullLen && nTxtRest > nFollow );
     340             : 
     341             :             // the height depending on the fields font is set,
     342             :             // this is required for SwTxtGuess::Guess
     343       14262 :             Height( rInf.GetTxtHeight() + rInf.GetFont()->GetTopBorderSpace() +
     344       14262 :                     rInf.GetFont()->GetBottomBorderSpace() );
     345             :             // If a kerning portion is inserted after our field portion,
     346             :             // the ascent and height must be known
     347       14262 :             SetAscent( rInf.GetAscent() + rInf.GetFont()->GetTopBorderSpace() );
     348       14262 :             bFull = SwTxtPortion::Format( rInf );
     349       14262 :             rInf.SetNotEOL( false );
     350       14262 :             rInf.SetLineStart( nOldLineStart );
     351             :         }
     352       22944 :         sal_Int32 nTmpLen = GetLen();
     353       22944 :         bEOL = !nTmpLen && nFollow && bFull;
     354       22944 :         nRest = nOldFullLen - nTmpLen;
     355             : 
     356             :         // Das Zeichen wird in der ersten Portion gehalten.
     357             :         // Unbedingt nach Format!
     358       22944 :         SetLen( (m_bNoLength) ? 0 : nFollow );
     359             : 
     360       22944 :         if( nRest )
     361             :         {
     362             :             // aExpand ist noch nicht gekuerzt worden, der neue Ofst
     363             :             // ergibt sich durch nRest.
     364        8048 :             sal_Int32 nNextOfst = aExpand.getLength() - nRest;
     365             : 
     366        8048 :             if ( IsQuoVadisPortion() )
     367           0 :                 nNextOfst = nNextOfst + ((SwQuoVadisPortion*)this)->GetContTxt().getLength();
     368             : 
     369        8048 :             OUString aNew( aExpand.copy( nNextOfst ) );
     370        8048 :             aExpand = aExpand.copy( 0, nNextOfst );
     371             : 
     372             :             // These characters should not be contained in the follow
     373             :             // field portion. They are handled via the HookChar mechanism.
     374        8048 :             switch( aNew[0] )
     375             :             {
     376           0 :                 case CH_BREAK  : bFull = true;
     377             :                             // no break
     378             :                 case ' ' :
     379             :                 case CH_TAB    :
     380             :                 case CHAR_HARDHYPHEN:               // non-breaking hyphen
     381             :                 case CHAR_SOFTHYPHEN:
     382             :                 case CHAR_HARDBLANK:
     383             :                 case CHAR_ZWSP :
     384             :                 case CHAR_ZWNBSP :
     385             :                 case CH_TXTATR_BREAKWORD:
     386             :                 case CH_TXTATR_INWORD:
     387             :                 {
     388        7986 :                     aNew = aNew.copy( 1 );
     389        7986 :                     ++nNextOfst;
     390        7986 :                     break;
     391             :                 }
     392             :                 default: ;
     393             :             }
     394             : 
     395             :             // Even if there is no more text left for a follow field,
     396             :             // we have to build a follow field portion (without font),
     397             :             // otherwise the HookChar mechanism would not work.
     398        8048 :             SwFldPortion *pFld = Clone( aNew );
     399        8048 :             if( !aNew.isEmpty() && !pFld->GetFont() )
     400             :             {
     401          28 :                 SwFont *pNewFnt = new SwFont( *rInf.GetFont() );
     402          28 :                 pFld->SetFont( pNewFnt );
     403             :             }
     404        8048 :             pFld->SetFollow( true );
     405        8048 :             SetHasFollow( true );
     406             :             // In nNextOffset steht bei einem neuangelegten Feld zunaechst
     407             :             // der Offset, an dem es selbst im Originalstring beginnt.
     408             :             // Wenn beim Formatieren ein FollowFeld angelegt wird, wird
     409             :             // der Offset dieses FollowFelds in nNextOffset festgehalten.
     410        8048 :             nNextOffset = nNextOffset + nNextOfst;
     411        8048 :             pFld->SetNextOffset( nNextOffset );
     412        8048 :             rInf.SetRest( pFld );
     413       22944 :         }
     414             :     }
     415             : 
     416       22944 :     if( bEOL && rInf.GetLast() && !rInf.GetUnderflow() )
     417           8 :         rInf.GetLast()->FormatEOL( rInf );
     418       22944 :     return bFull;
     419             : }
     420             : 
     421        2408 : void SwFldPortion::Paint( const SwTxtPaintInfo &rInf ) const
     422             : {
     423        2408 :     SwFontSave aSave( rInf, pFnt );
     424             : 
     425             :     OSL_ENSURE( GetLen() <= 1, "SwFldPortion::Paint: rest-portion polution?" );
     426        2408 :     if( Width() && ( !bPlaceHolder || rInf.GetOpt().IsShowPlaceHolderFields() ) )
     427             :     {
     428             :         // Dies ist eine freizuegige Auslegung der Hintergrundbelegung ...
     429        1840 :         rInf.DrawViewOpt( *this, POR_FLD );
     430        1840 :         SwExpandPortion::Paint( rInf );
     431        2408 :     }
     432        2408 : }
     433             : 
     434       54012 : bool SwFldPortion::GetExpTxt( const SwTxtSizeInfo &rInf, OUString &rTxt ) const
     435             : {
     436       54012 :     rTxt = aExpand;
     437      127654 :     if( rTxt.isEmpty() && rInf.OnWin() &&
     438        3084 :         !rInf.GetOpt().IsPagePreview() && !rInf.GetOpt().IsReadonly() &&
     439       56068 :             SwViewOption::IsFieldShadings() &&
     440        1028 :             !HasFollow() )
     441        1028 :         rTxt = OUString(' ');
     442       54012 :     return true;
     443             : }
     444             : 
     445         112 : void SwFldPortion::HandlePortion( SwPortionHandler& rPH ) const
     446             : {
     447         112 :     sal_Int32 nH = 0;
     448         112 :     if (pFnt)
     449          92 :         nH = pFnt->GetSize(pFnt->GetActual()).Height();
     450         112 :     rPH.Special( GetLen(), aExpand, GetWhichPor(), nH );
     451         112 :     if( GetWhichPor() == POR_FLD )
     452             :     {
     453           2 :         rPH.SetAttrFieldType(m_nAttrFldType);
     454             :     }
     455         112 : }
     456             : 
     457           0 : SwPosSize SwFldPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
     458             : {
     459           0 :     SwFontSave aSave( rInf, pFnt );
     460           0 :     SwPosSize aSize( SwExpandPortion::GetTxtSize( rInf ) );
     461           0 :     return aSize;
     462             : }
     463             : 
     464           0 : SwFldPortion *SwHiddenPortion::Clone(const OUString &rExpand ) const
     465             : {
     466             :     SwFont *pNewFnt;
     467           0 :     if( 0 != ( pNewFnt = pFnt ) )
     468           0 :         pNewFnt = new SwFont( *pFnt );
     469           0 :     return new SwHiddenPortion( rExpand, pNewFnt );
     470             : }
     471             : 
     472           0 : void SwHiddenPortion::Paint( const SwTxtPaintInfo &rInf ) const
     473             : {
     474           0 :     if( Width() )
     475             :     {
     476           0 :         SwFontSave aSave( rInf, pFnt );
     477           0 :         rInf.DrawViewOpt( *this, POR_HIDDEN );
     478           0 :         SwExpandPortion::Paint( rInf );
     479             :     }
     480           0 : }
     481             : 
     482           0 : bool SwHiddenPortion::GetExpTxt( const SwTxtSizeInfo &rInf, OUString &rTxt ) const
     483             : {
     484             :     // Nicht auf IsHidden() abfragen !
     485           0 :     return SwFldPortion::GetExpTxt( rInf, rTxt );
     486             : }
     487             : 
     488       16810 : SwNumberPortion::SwNumberPortion( const OUString &rExpand,
     489             :                                   SwFont *pFont,
     490             :                                   const bool bLft,
     491             :                                   const bool bCntr,
     492             :                                   const sal_uInt16 nMinDst,
     493             :                                   const bool bLabelAlignmentPosAndSpaceModeActive )
     494             :         : SwFldPortion( rExpand, pFont ),
     495             :           nFixWidth(0),
     496             :           nMinDist( nMinDst ),
     497       16810 :           mbLabelAlignmentPosAndSpaceModeActive( bLabelAlignmentPosAndSpaceModeActive )
     498             : {
     499       16810 :     SetWhichPor( POR_NUMBER );
     500       16810 :     SetLeft( bLft );
     501       16810 :     SetHide( false );
     502       16810 :     SetCenter( bCntr );
     503       16810 : }
     504             : 
     505           0 : sal_Int32 SwNumberPortion::GetCrsrOfst( const sal_uInt16 ) const
     506             : {
     507           0 :     return 0;
     508             : }
     509             : 
     510        8020 : SwFldPortion *SwNumberPortion::Clone( const OUString &rExpand ) const
     511             : {
     512             :     SwFont *pNewFnt;
     513        8020 :     if( 0 != ( pNewFnt = pFnt ) )
     514        7880 :         pNewFnt = new SwFont( *pFnt );
     515             : 
     516       16040 :     return new SwNumberPortion( rExpand, pNewFnt, IsLeft(), IsCenter(),
     517       16040 :                                 nMinDist, mbLabelAlignmentPosAndSpaceModeActive );
     518             : }
     519             : 
     520             : // 5010: Wir sind in der Lage, mehrzeilige NumFelder anzulegen!
     521             : // 3689: Fies ist, wenn man in der Dialogbox soviel Davor-Text
     522             : // eingibt, bis die Zeile ueberlaeuft.
     523             : // Man muss die Fly-Ausweichmanoever beachten!
     524             : 
     525       16670 : bool SwNumberPortion::Format( SwTxtFormatInfo &rInf )
     526             : {
     527       16670 :     SetHide( false );
     528       16670 :     const bool bFull = SwFldPortion::Format( rInf );
     529       16670 :     SetLen( 0 );
     530             :     // a numbering portion can be contained in a rotated portion!!!
     531       16670 :     nFixWidth = rInf.IsMulti() ? Height() : Width();
     532       16670 :     rInf.SetNumDone( !rInf.GetRest() );
     533       16670 :     if( rInf.IsNumDone() )
     534             :     {
     535             : //        SetAscent( rInf.GetAscent() );
     536             :         OSL_ENSURE( Height() && nAscent, "NumberPortions without Height | Ascent" );
     537             : 
     538        8790 :         long nDiff( 0 );
     539             : 
     540        8790 :         if ( !mbLabelAlignmentPosAndSpaceModeActive )
     541             :         {
     542        1368 :             if ( !rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING) &&
     543             :                  // #i32902#
     544         684 :                  !IsFtnNumPortion() )
     545             :             {
     546         448 :                 nDiff = rInf.Left()
     547         896 :                     + rInf.GetTxtFrm()->GetTxtNode()->
     548         448 :                     GetSwAttrSet().GetLRSpace().GetTxtFirstLineOfst()
     549         448 :                     - rInf.First()
     550         448 :                     + rInf.ForcedLeftMargin();
     551             :             }
     552             :             else
     553             :             {
     554         236 :                 nDiff = rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
     555             :             }
     556             :         }
     557             :         // proposal from Juergen and Volkmar:
     558             :         // Der Textteil hinter der Numerierung sollte immer
     559             :         // mindestens beim linken Rand beginnen.
     560        8790 :         if( nDiff < 0 )
     561           6 :             nDiff = 0;
     562        8784 :         else if ( nDiff > rInf.X() )
     563         586 :             nDiff -= rInf.X();
     564             :         else
     565        8198 :             nDiff = 0;
     566             : 
     567        8790 :         if( nDiff < nFixWidth + nMinDist )
     568         286 :             nDiff = nFixWidth + nMinDist;
     569             :         // 2739: Numerierung weicht Fly aus, kein nDiff in der zweiten Runde
     570             :         // fieser Sonderfall: FlyFrm liegt in dem Bereich,
     571             :         // den wir uns gerade unter den Nagel reissen wollen.
     572             :         // Die NumberPortion wird als verborgen markiert.
     573       17580 :         const bool bFly = rInf.GetFly() ||
     574       26370 :             ( rInf.GetLast() && rInf.GetLast()->IsFlyPortion() );
     575        8790 :         if( nDiff > rInf.Width() )
     576             :         {
     577           0 :             nDiff = rInf.Width();
     578           0 :             if ( bFly )
     579           0 :                 SetHide( true );
     580             :         }
     581             : 
     582             :         // A numbering portion can be inside a SwRotatedPortion. Then the
     583             :         // Height has to be changed
     584        8790 :         if ( rInf.IsMulti() )
     585             :         {
     586           0 :             if ( Height() < nDiff )
     587           0 :                 Height( sal_uInt16( nDiff ) );
     588             :         }
     589        8790 :         else if( Width() < nDiff )
     590         520 :             Width( sal_uInt16(nDiff) );
     591             :     }
     592       16670 :     return bFull;
     593             : }
     594             : 
     595           0 : void SwNumberPortion::FormatEOL( SwTxtFormatInfo& )
     596             : {
     597             : /*  Ein FormatEOL deutet daraufhin, dass der folgende Text
     598             :  *  nicht mit auf die Zeile passte. Damit die Numerierung mitwandert,
     599             :  *  wird diese NumberPortion verborgen.
     600             :  */
     601             : 
     602             :     // This caused trouble with flys anchored as characters.
     603             :     // If one of these is numbered but does not fit to the line,
     604             :     // it calls this function, causing a loop because both the number
     605             :     // portion and the fly portion go to the next line
     606             : //    SetHide( true );
     607           0 : }
     608             : 
     609         654 : void SwNumberPortion::Paint( const SwTxtPaintInfo &rInf ) const
     610             : {
     611             : /*  Eine verborgene NumberPortion wird nicht angezeigt, es sei denn, es gibt
     612             :  *  Textportions in dieser Zeile oder es gibt ueberhaupt nur eine einzige Zeile.
     613             :  */
     614             : 
     615         654 :     if ( IsHide() && rInf.GetParaPortion() && rInf.GetParaPortion()->GetNext() )
     616             :     {
     617           0 :         SwLinePortion *pTmp = GetPortion();
     618           0 :         while ( pTmp && !pTmp->InTxtGrp() )
     619           0 :             pTmp = pTmp->GetPortion();
     620           0 :         if ( !pTmp )
     621         654 :             return;
     622             :     }
     623             : 
     624             :     // calculate the width of the number portion, including follows
     625         654 :     const sal_uInt16 nOldWidth = Width();
     626         654 :     sal_uInt16 nSumWidth = 0;
     627         654 :     sal_uInt16 nOffset = 0;
     628             : 
     629         654 :     const SwLinePortion* pTmp = this;
     630        1452 :     while ( pTmp && pTmp->InNumberGrp() )
     631             :     {
     632         654 :         nSumWidth = nSumWidth + pTmp->Width();
     633         654 :         if ( ((SwNumberPortion*)pTmp)->HasFollow() )
     634         144 :             pTmp = pTmp->GetPortion();
     635             :         else
     636             :         {
     637         510 :             nOffset = pTmp->Width() - ((SwNumberPortion*)pTmp)->nFixWidth;
     638         510 :             break;
     639             :         }
     640             :     }
     641             : 
     642             :     // The master portion takes care for painting the background of the
     643             :     // follow field portions
     644         654 :     if ( ! IsFollow() )
     645             :     {
     646         654 :         SwLinePortion *pThis = (SwLinePortion*)this;
     647         654 :         pThis->Width( nSumWidth );
     648         654 :         rInf.DrawViewOpt( *this, POR_NUMBER );
     649         654 :         pThis->Width( nOldWidth );
     650             :     }
     651             : 
     652         654 :     if( !aExpand.isEmpty() )
     653             :     {
     654         654 :         const SwFont *pTmpFnt = rInf.GetFont();
     655        1308 :         bool bPaintSpace = ( UNDERLINE_NONE != pTmpFnt->GetUnderline() ||
     656        1308 :                                  UNDERLINE_NONE != pTmpFnt->GetOverline()  ||
     657        1308 :                                  STRIKEOUT_NONE != pTmpFnt->GetStrikeout() ) &&
     658         654 :                                  !pTmpFnt->IsWordLineMode();
     659         654 :         if( bPaintSpace && pFnt )
     660           0 :             bPaintSpace = ( UNDERLINE_NONE != pFnt->GetUnderline() ||
     661           0 :                             UNDERLINE_NONE != pFnt->GetOverline()  ||
     662           0 :                             STRIKEOUT_NONE != pFnt->GetStrikeout() ) &&
     663           0 :                             !pFnt->IsWordLineMode();
     664             : 
     665         654 :         SwFontSave aSave( rInf, pFnt );
     666             : 
     667         654 :         if( nFixWidth == Width() && ! HasFollow() )
     668          90 :             SwExpandPortion::Paint( rInf );
     669             :         else
     670             :         {
     671             :             // logical const: reset width
     672         564 :             SwLinePortion *pThis = (SwLinePortion*)this;
     673         564 :             bPaintSpace = bPaintSpace && nFixWidth < nOldWidth;
     674         564 :             sal_uInt16 nSpaceOffs = nFixWidth;
     675         564 :             pThis->Width( nFixWidth );
     676             : 
     677        1128 :             if( ( IsLeft() && ! rInf.GetTxtFrm()->IsRightToLeft() ) ||
     678           0 :                 ( ! IsLeft() && ! IsCenter() && rInf.GetTxtFrm()->IsRightToLeft() ) )
     679         564 :                 SwExpandPortion::Paint( rInf );
     680             :             else
     681             :             {
     682           0 :                 SwTxtPaintInfo aInf( rInf );
     683           0 :                 if( nOffset < nMinDist )
     684           0 :                     nOffset = 0;
     685             :                 else
     686             :                 {
     687           0 :                     if( IsCenter() )
     688             :                     {
     689             :                         /* #110778# a / 2 * 2 == a is not a tautology */
     690           0 :                         sal_uInt16 nTmpOffset = nOffset;
     691           0 :                         nOffset /= 2;
     692           0 :                         if( nOffset < nMinDist )
     693           0 :                             nOffset = nTmpOffset - nMinDist;
     694             :                     }
     695             :                     else
     696           0 :                         nOffset = nOffset - nMinDist;
     697             :                 }
     698           0 :                 aInf.X( aInf.X() + nOffset );
     699           0 :                 SwExpandPortion::Paint( aInf );
     700           0 :                 if( bPaintSpace )
     701           0 :                     nSpaceOffs = nSpaceOffs + nOffset;
     702             :             }
     703         564 :             if( bPaintSpace && nOldWidth > nSpaceOffs )
     704             :             {
     705           0 :                 SwTxtPaintInfo aInf( rInf );
     706           0 :                 aInf.X( aInf.X() + nSpaceOffs );
     707             : 
     708             :                 // #i53199# Adjust position of underline:
     709           0 :                 if ( rInf.GetUnderFnt() )
     710             :                 {
     711           0 :                     const Point aNewPos( aInf.GetPos().X(), rInf.GetUnderFnt()->GetPos().Y() );
     712           0 :                     rInf.GetUnderFnt()->SetPos( aNewPos );
     713             :                 }
     714             : 
     715           0 :                 pThis->Width( nOldWidth - nSpaceOffs + 12 );
     716             :                 {
     717           0 :                     SwTxtSlot aDiffTxt( &aInf, this, true, false, "  " );
     718           0 :                     aInf.DrawText( *this, aInf.GetLen(), true );
     719           0 :                 }
     720             :             }
     721         564 :             pThis->Width( nOldWidth );
     722         654 :         }
     723             :     }
     724             : }
     725             : 
     726        6100 : SwBulletPortion::SwBulletPortion( const sal_Unicode cBullet,
     727             :                                   const OUString& rBulletFollowedBy,
     728             :                                   SwFont *pFont,
     729             :                                   const bool bLft,
     730             :                                   const bool bCntr,
     731             :                                   const sal_uInt16 nMinDst,
     732             :                                   const bool bLabelAlignmentPosAndSpaceModeActive )
     733       12200 :     : SwNumberPortion( OUString(cBullet) + rBulletFollowedBy,
     734             :                        pFont, bLft, bCntr, nMinDst,
     735       18300 :                        bLabelAlignmentPosAndSpaceModeActive )
     736             : {
     737        6100 :     SetWhichPor( POR_BULLET );
     738        6100 : }
     739             : 
     740             : #define GRFNUM_SECURE 10
     741             : 
     742         140 : SwGrfNumPortion::SwGrfNumPortion(
     743             :         SwFrm*,
     744             :         const OUString& rGraphicFollowedBy,
     745             :         const SvxBrushItem* pGrfBrush,
     746             :         const SwFmtVertOrient* pGrfOrient, const Size& rGrfSize,
     747             :         const bool bLft, const bool bCntr, const sal_uInt16 nMinDst,
     748             :         const bool bLabelAlignmentPosAndSpaceModeActive ) :
     749             :     SwNumberPortion( rGraphicFollowedBy, NULL, bLft, bCntr, nMinDst,
     750             :                      bLabelAlignmentPosAndSpaceModeActive ),
     751         140 :     pBrush( new SvxBrushItem(RES_BACKGROUND) ), nId( 0 )
     752             : {
     753         140 :     SetWhichPor( POR_GRFNUM );
     754         140 :     SetAnimated( false );
     755         140 :     bReplace = false;
     756         140 :     if( pGrfBrush )
     757             :     {
     758         140 :         *pBrush = *pGrfBrush;
     759         140 :         const Graphic* pGraph = pGrfBrush->GetGraphic();
     760         140 :         if( pGraph )
     761         140 :             SetAnimated( pGraph->IsAnimated() );
     762             :         else
     763           0 :             bReplace = true;
     764             :     }
     765         140 :     if( pGrfOrient )
     766             :     {
     767           0 :         nYPos = pGrfOrient->GetPos();
     768           0 :         eOrient = pGrfOrient->GetVertOrient();
     769             :     }
     770             :     else
     771             :     {
     772         140 :         nYPos = 0;
     773         140 :         eOrient = text::VertOrientation::TOP;
     774             :     }
     775         140 :     Width( static_cast<sal_uInt16>(rGrfSize.Width() + 2 * GRFNUM_SECURE) );
     776         140 :     nFixWidth = Width();
     777         140 :     nGrfHeight = rGrfSize.Height() + 2 * GRFNUM_SECURE;
     778         140 :     Height( sal_uInt16(nGrfHeight) );
     779         140 :     bNoPaint = false;
     780         140 : }
     781             : 
     782         420 : SwGrfNumPortion::~SwGrfNumPortion()
     783             : {
     784         140 :     if ( IsAnimated() )
     785             :     {
     786           0 :         Graphic* pGraph = ( (Graphic*) pBrush->GetGraphic() );
     787           0 :         if (pGraph)
     788           0 :             pGraph->StopAnimation( 0, nId );
     789             :     }
     790         140 :     delete pBrush;
     791         280 : }
     792             : 
     793           0 : void SwGrfNumPortion::StopAnimation( OutputDevice* pOut )
     794             : {
     795           0 :     if ( IsAnimated() )
     796             :     {
     797           0 :         Graphic* pGraph = ( (Graphic*) pBrush->GetGraphic() );
     798           0 :         if (pGraph)
     799           0 :             pGraph->StopAnimation( pOut, nId );
     800             :     }
     801           0 : }
     802             : 
     803         140 : bool SwGrfNumPortion::Format( SwTxtFormatInfo &rInf )
     804             : {
     805         140 :     SetHide( false );
     806             : //    Width( nFixWidth );
     807         140 :     sal_uInt16 nFollowedByWidth( 0 );
     808         140 :     if ( mbLabelAlignmentPosAndSpaceModeActive )
     809             :     {
     810         140 :         SwFldPortion::Format( rInf );
     811         140 :         nFollowedByWidth = Width();
     812         140 :         SetLen( 0 );
     813             :     }
     814         140 :     Width( nFixWidth + nFollowedByWidth );
     815         140 :     const bool bFull = rInf.Width() < rInf.X() + Width();
     816         280 :     const bool bFly = rInf.GetFly() ||
     817         420 :         ( rInf.GetLast() && rInf.GetLast()->IsFlyPortion() );
     818         140 :     SetAscent( static_cast<sal_uInt16>(GetRelPos() > 0 ? GetRelPos() : 0) );
     819         140 :     if( GetAscent() > Height() )
     820           0 :         Height( GetAscent() );
     821             : 
     822         140 :     if( bFull )
     823             :     {
     824           0 :         Width( rInf.Width() - (sal_uInt16)rInf.X() );
     825           0 :         if( bFly )
     826             :         {
     827           0 :             SetLen( 0 );
     828           0 :             SetNoPaint( true );
     829           0 :             rInf.SetNumDone( false );
     830           0 :             return true;
     831             :         }
     832             :     }
     833         140 :     rInf.SetNumDone( true );
     834             : //    long nDiff = rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
     835             :     long nDiff = mbLabelAlignmentPosAndSpaceModeActive
     836             :                  ? 0
     837         140 :                  : rInf.Left() - rInf.First() + rInf.ForcedLeftMargin();
     838             :     // proposal by Juergen and Volkmar:
     839             :     // Der Textteil hinter der Numerierung sollte immer
     840             :     // mindestens beim linken Rand beginnen.
     841         140 :     if( nDiff < 0 )
     842           0 :         nDiff = 0;
     843         140 :     else if ( nDiff > rInf.X() )
     844           0 :         nDiff -= rInf.X();
     845         140 :     if( nDiff < nFixWidth + nMinDist )
     846         140 :         nDiff = nFixWidth + nMinDist;
     847             :     // 2739: Numerierung weicht Fly aus, kein nDiff in der zweiten Runde
     848             :     // fieser Sonderfall: FlyFrm liegt in dem Bereich,
     849             :     // den wir uns gerade unter den Nagel reissen wollen.
     850             :     // Die NumberPortion wird als verborgen markiert.
     851         140 :     if( nDiff > rInf.Width() )
     852             :     {
     853           0 :         nDiff = rInf.Width();
     854           0 :         if( bFly )
     855           0 :             SetHide( true );
     856             :     }
     857             : 
     858         140 :     if( Width() < nDiff )
     859           0 :         Width( sal_uInt16(nDiff) );
     860         140 :     return bFull;
     861             : }
     862             : 
     863           0 : void SwGrfNumPortion::Paint( const SwTxtPaintInfo &rInf ) const
     864             : {
     865           0 :     if( DontPaint() )
     866           0 :         return;
     867             : /*  Eine verborgene NumberPortion wird nicht angezeigt, es sei denn, es gibt
     868             :  *  Textportions in dieser Zeile oder es gibt ueberhaupt nur eine einzige Zeile.
     869             :  */
     870           0 :     if ( IsHide() && rInf.GetParaPortion() && rInf.GetParaPortion()->GetNext() )
     871             :     {
     872           0 :         SwLinePortion *pTmp = GetPortion();
     873           0 :         while ( pTmp && !pTmp->InTxtGrp() )
     874           0 :             pTmp = pTmp->GetPortion();
     875           0 :         if ( !pTmp )
     876           0 :             return;
     877             :     }
     878           0 :     Point aPos( rInf.X() + GRFNUM_SECURE, rInf.Y() - GetRelPos() + GRFNUM_SECURE );
     879           0 :     long nTmpWidth = std::max( (long)0, (long)(nFixWidth - 2 * GRFNUM_SECURE) );
     880           0 :     Size aSize( nTmpWidth, GetGrfHeight() - 2 * GRFNUM_SECURE );
     881             : 
     882           0 :     const bool bTmpLeft = mbLabelAlignmentPosAndSpaceModeActive ||
     883           0 :                               ( IsLeft() && ! rInf.GetTxtFrm()->IsRightToLeft() ) ||
     884           0 :                               ( ! IsLeft() && ! IsCenter() && rInf.GetTxtFrm()->IsRightToLeft() );
     885             : 
     886           0 :     if( nFixWidth < Width() && !bTmpLeft )
     887             :     {
     888           0 :         sal_uInt16 nOffset = Width() - nFixWidth;
     889           0 :         if( nOffset < nMinDist )
     890           0 :             nOffset = 0;
     891             :         else
     892             :         {
     893           0 :             if( IsCenter() )
     894             :             {
     895           0 :                 nOffset /= 2;
     896           0 :                 if( nOffset < nMinDist )
     897           0 :                     nOffset = Width() - nFixWidth - nMinDist;
     898             :             }
     899             :             else
     900           0 :                 nOffset = nOffset - nMinDist;
     901             :         }
     902           0 :         aPos.X() += nOffset;
     903             :     }
     904             : 
     905           0 :     if( bReplace )
     906             :     {
     907           0 :         const long nTmpH = GetPortion() ? GetPortion()->GetAscent() : 120;
     908           0 :         aSize = Size( nTmpH, nTmpH );
     909           0 :         aPos.Y() = rInf.Y() - nTmpH;
     910             :     }
     911           0 :     SwRect aTmp( aPos, aSize );
     912             : 
     913           0 :     bool bDraw = true;
     914             : 
     915           0 :     if ( IsAnimated() )
     916             :     {
     917           0 :         bDraw = !rInf.GetOpt().IsGraphic();
     918           0 :         if( !nId )
     919             :         {
     920           0 :             SetId( sal_IntPtr( rInf.GetTxtFrm() ) );
     921           0 :             rInf.GetTxtFrm()->SetAnimation();
     922             :         }
     923           0 :         if( aTmp.IsOver( rInf.GetPaintRect() ) && !bDraw )
     924             :         {
     925           0 :             rInf.NoteAnimation();
     926           0 :             const SwViewShell* pViewShell = rInf.GetVsh();
     927             : 
     928             :             // virtual device, not pdf export
     929           0 :             if( OUTDEV_VIRDEV == rInf.GetOut()->GetOutDevType() &&
     930           0 :                 pViewShell && pViewShell->GetWin()  )
     931             :             {
     932           0 :                 Graphic* pGraph = (Graphic*)pBrush->GetGraphic();
     933           0 :                 if (pGraph)
     934           0 :                     pGraph->StopAnimation(0,nId);
     935           0 :                 rInf.GetTxtFrm()->getRootFrm()->GetCurrShell()->InvalidateWindows( aTmp );
     936             :             }
     937             : 
     938           0 :             else if ( pViewShell &&
     939           0 :                      !pViewShell->GetAccessibilityOptions()->IsStopAnimatedGraphics() &&
     940           0 :                      !pViewShell->IsPreview() &&
     941             :                       // #i9684# Stop animation during printing/pdf export.
     942           0 :                       pViewShell->GetWin() )
     943             :             {
     944           0 :                 Graphic* pGraph = (Graphic*)pBrush->GetGraphic();
     945           0 :                 if (pGraph)
     946             :                 {
     947             :                     pGraph->StartAnimation(
     948           0 :                         (OutputDevice*)rInf.GetOut(), aPos, aSize, nId );
     949             :                 }
     950             :             }
     951             : 
     952             :             // pdf export, printing, preview, stop animations...
     953             :             else
     954           0 :                 bDraw = true;
     955             :         }
     956           0 :         if( bDraw )
     957             :         {
     958             : 
     959           0 :             Graphic* pGraph = (Graphic*)pBrush->GetGraphic();
     960           0 :             if (pGraph)
     961           0 :                 pGraph->StopAnimation( 0, nId );
     962             :         }
     963             :     }
     964             : 
     965           0 :     SwRect aRepaint( rInf.GetPaintRect() );
     966           0 :     const SwTxtFrm& rFrm = *rInf.GetTxtFrm();
     967           0 :     if( rFrm.IsVertical() )
     968             :     {
     969           0 :         rFrm.SwitchHorizontalToVertical( aTmp );
     970           0 :         rFrm.SwitchHorizontalToVertical( aRepaint );
     971             :     }
     972             : 
     973           0 :     if( rFrm.IsRightToLeft() )
     974             :     {
     975           0 :         rFrm.SwitchLTRtoRTL( aTmp );
     976           0 :         rFrm.SwitchLTRtoRTL( aRepaint );
     977             :     }
     978             : 
     979           0 :     if( bDraw && aTmp.HasArea() )
     980             :     {
     981           0 :         DrawGraphic( pBrush, (OutputDevice*)rInf.GetOut(),
     982           0 :             aTmp, aRepaint, bReplace ? GRFNUM_REPLACE : GRFNUM_YES );
     983             :     }
     984             : }
     985             : 
     986         140 : void SwGrfNumPortion::SetBase( long nLnAscent, long nLnDescent,
     987             :                                long nFlyAsc, long nFlyDesc )
     988             : {
     989         140 :     if ( GetOrient() != text::VertOrientation::NONE )
     990             :     {
     991         140 :         SetRelPos( 0 );
     992         140 :         if ( GetOrient() == text::VertOrientation::CENTER )
     993           0 :             SetRelPos( GetGrfHeight() / 2 );
     994         140 :         else if ( GetOrient() == text::VertOrientation::TOP )
     995         140 :             SetRelPos( GetGrfHeight() - GRFNUM_SECURE );
     996           0 :         else if ( GetOrient() == text::VertOrientation::BOTTOM )
     997             :             ;
     998           0 :         else if ( GetOrient() == text::VertOrientation::CHAR_CENTER )
     999           0 :             SetRelPos( ( GetGrfHeight() + nLnAscent - nLnDescent ) / 2 );
    1000           0 :         else if ( GetOrient() == text::VertOrientation::CHAR_TOP )
    1001           0 :             SetRelPos( nLnAscent );
    1002           0 :         else if ( GetOrient() == text::VertOrientation::CHAR_BOTTOM )
    1003           0 :             SetRelPos( GetGrfHeight() - nLnDescent );
    1004             :         else
    1005             :         {
    1006           0 :             if( GetGrfHeight() >= nFlyAsc + nFlyDesc )
    1007             :             {
    1008             :                 // wenn ich genauso gross bin wie die Zeile, brauche ich mich
    1009             :                 // nicht an der Zeile nicht weiter ausrichten, ich lasse
    1010             :                 // dann auch den max. Ascent der Zeile unveraendert
    1011             : 
    1012           0 :                 SetRelPos( nFlyAsc );
    1013             :             }
    1014           0 :             else if ( GetOrient() == text::VertOrientation::LINE_CENTER )
    1015           0 :                 SetRelPos( ( GetGrfHeight() + nFlyAsc - nFlyDesc ) / 2 );
    1016           0 :             else if ( GetOrient() == text::VertOrientation::LINE_TOP )
    1017           0 :                 SetRelPos( nFlyAsc );
    1018           0 :             else if ( GetOrient() == text::VertOrientation::LINE_BOTTOM )
    1019           0 :                 SetRelPos( GetGrfHeight() - nFlyDesc );
    1020             :         }
    1021             :     }
    1022         140 : }
    1023             : 
    1024           0 : void SwTxtFrm::StopAnimation( OutputDevice* pOut )
    1025             : {
    1026             :     OSL_ENSURE( HasAnimation(), "SwTxtFrm::StopAnimation: Which Animation?" );
    1027           0 :     if( HasPara() )
    1028             :     {
    1029           0 :         SwLineLayout *pLine = GetPara();
    1030           0 :         while( pLine )
    1031             :         {
    1032           0 :             SwLinePortion *pPor = pLine->GetPortion();
    1033           0 :             while( pPor )
    1034             :             {
    1035           0 :                 if( pPor->IsGrfNumPortion() )
    1036           0 :                     ((SwGrfNumPortion*)pPor)->StopAnimation( pOut );
    1037             :                 // Die Numerierungsportion sitzt immer vor dem ersten Zeichen,
    1038             :                 // deshalb koennen wir abbrechen, sobald wir eine Portion mit
    1039             :                 // einer Laenge > 0 erreicht haben.
    1040           0 :                 pPor = pPor->GetLen() ? 0 : pPor->GetPortion();
    1041             :             }
    1042           0 :             pLine = pLine->GetLen() ? 0 : pLine->GetNext();
    1043             :         }
    1044             :     }
    1045           0 : }
    1046             : 
    1047             : // initializes the script array and clears the width array
    1048           0 : SwCombinedPortion::SwCombinedPortion( const OUString &rTxt )
    1049             :     : SwFldPortion( rTxt )
    1050             :     , nUpPos(0)
    1051             :     , nLowPos(0)
    1052           0 :     , nProportion(55)
    1053             : {
    1054           0 :     SetLen(1);
    1055           0 :     SetWhichPor( POR_COMBINED );
    1056           0 :     if( aExpand.getLength() > 6 )
    1057           0 :         aExpand = aExpand.copy( 0, 6 );
    1058             :     // Initialization of the scripttype array,
    1059             :     // the arrays of width and position are filled by the format function
    1060           0 :     if( g_pBreakIt->GetBreakIter().is() )
    1061             :     {
    1062           0 :         sal_uInt8 nScr = SW_SCRIPTS;
    1063           0 :         for( sal_Int32 i = 0; i < rTxt.getLength(); ++i )
    1064             :         {
    1065           0 :             switch ( g_pBreakIt->GetBreakIter()->getScriptType( rTxt, i ) ) {
    1066           0 :                 case i18n::ScriptType::LATIN : nScr = SW_LATIN; break;
    1067           0 :                 case i18n::ScriptType::ASIAN : nScr = SW_CJK; break;
    1068           0 :                 case i18n::ScriptType::COMPLEX : nScr = SW_CTL; break;
    1069             :             }
    1070           0 :             aScrType[i] = nScr;
    1071             :         }
    1072             :     }
    1073             :     else
    1074             :     {
    1075           0 :         for( int i = 0; i < 6; ++i )
    1076           0 :             aScrType[i] = 0;
    1077             :     }
    1078           0 :     memset( &aWidth, 0, sizeof(aWidth) );
    1079           0 : }
    1080             : 
    1081           0 : void SwCombinedPortion::Paint( const SwTxtPaintInfo &rInf ) const
    1082             : {
    1083             :     OSL_ENSURE( GetLen() <= 1, "SwFldPortion::Paint: rest-portion polution?" );
    1084           0 :     if( Width() )
    1085             :     {
    1086           0 :         rInf.DrawBackBrush( *this );
    1087           0 :         rInf.DrawViewOpt( *this, POR_FLD );
    1088             : 
    1089             :         // do we have to repaint a post it portion?
    1090           0 :         if( rInf.OnWin() && pPortion && !pPortion->Width() )
    1091           0 :             pPortion->PrePaint( rInf, this );
    1092             : 
    1093           0 :         const sal_Int32 nCount = aExpand.getLength();
    1094           0 :         if( !nCount )
    1095           0 :             return;
    1096             :         OSL_ENSURE( nCount < 7, "Too much combined characters" );
    1097             : 
    1098             :         // the first character of the second row
    1099           0 :         const sal_Int32 nTop = ( nCount + 1 ) / 2;
    1100             : 
    1101           0 :         SwFont aTmpFont( *rInf.GetFont() );
    1102           0 :         aTmpFont.SetProportion( nProportion );  // a smaller font
    1103           0 :         SwFontSave aFontSave( rInf, &aTmpFont );
    1104             : 
    1105           0 :         Point aOldPos = rInf.GetPos();
    1106           0 :         Point aOutPos( aOldPos.X(), aOldPos.Y() - nUpPos );// Y of the first row
    1107           0 :         for( sal_Int32 i = 0 ; i < nCount; ++i )
    1108             :         {
    1109           0 :             if( i == nTop ) // change the row
    1110           0 :                 aOutPos.Y() = aOldPos.Y() + nLowPos;    // Y of the second row
    1111           0 :             aOutPos.X() = aOldPos.X() + aPos[i];        // X position
    1112           0 :             const sal_uInt8 nAct = aScrType[i];             // script type
    1113           0 :             aTmpFont.SetActual( nAct );
    1114             :             // if there're more than 4 characters to display, we choose fonts
    1115             :             // with 2/3 of the original font width.
    1116           0 :             if( aWidth[ nAct ] )
    1117             :             {
    1118           0 :                 Size aTmpSz = aTmpFont.GetSize( nAct );
    1119           0 :                 if( aTmpSz.Width() != aWidth[ nAct ] )
    1120             :                 {
    1121           0 :                     aTmpSz.Width() = aWidth[ nAct ];
    1122           0 :                     aTmpFont.SetSize( aTmpSz, nAct );
    1123             :                 }
    1124             :             }
    1125           0 :             ((SwTxtPaintInfo&)rInf).SetPos( aOutPos );
    1126           0 :             rInf.DrawText( aExpand, *this, i, 1 );
    1127             :         }
    1128             :         // rInf is const, so we have to take back our manipulations
    1129           0 :         ((SwTxtPaintInfo&)rInf).SetPos( aOldPos );
    1130             :     }
    1131             : }
    1132             : 
    1133           0 : bool SwCombinedPortion::Format( SwTxtFormatInfo &rInf )
    1134             : {
    1135           0 :     const sal_Int32 nCount = aExpand.getLength();
    1136           0 :     if( !nCount )
    1137             :     {
    1138           0 :         Width( 0 );
    1139           0 :         return false;
    1140             :     }
    1141             : 
    1142             :     OSL_ENSURE( nCount < 7, "Too much combined characters" );
    1143             :     // If there are leading "weak"-scripttyped characters in this portion,
    1144             :     // they get the actual scripttype.
    1145           0 :     for( sal_Int32 i = 0; i < nCount && SW_SCRIPTS == aScrType[i]; ++i )
    1146           0 :         aScrType[i] = rInf.GetFont()->GetActual();
    1147           0 :     if( nCount > 4 )
    1148             :     {
    1149             :         // more than four? Ok, then we need the 2/3 font width
    1150           0 :         for( sal_Int32 i = 0; i < aExpand.getLength(); ++i )
    1151             :         {
    1152             :             OSL_ENSURE( aScrType[i] < SW_SCRIPTS, "Combined: Script fault" );
    1153           0 :             if( !aWidth[ aScrType[i] ] )
    1154             :             {
    1155           0 :                 rInf.GetOut()->SetFont( rInf.GetFont()->GetFnt( aScrType[i] ) );
    1156           0 :                 aWidth[ aScrType[i] ] =
    1157           0 :                         static_cast<sal_uInt16>(2 * rInf.GetOut()->GetFontMetric().GetSize().Width() / 3);
    1158             :             }
    1159             :         }
    1160             :     }
    1161             : 
    1162           0 :     const sal_Int32 nTop = ( nCount + 1 ) / 2; // the first character of the second line
    1163           0 :     SwViewShell *pSh = rInf.GetTxtFrm()->getRootFrm()->GetCurrShell();
    1164           0 :     SwFont aTmpFont( *rInf.GetFont() );
    1165           0 :     SwFontSave aFontSave( rInf, &aTmpFont );
    1166           0 :     nProportion = 55;
    1167             :     // In nMainAscent/Descent we store the ascent and descent
    1168             :     // of the original surrounding font
    1169             :     sal_uInt16 nMaxDescent, nMaxAscent, nMaxWidth;
    1170           0 :     sal_uInt16 nMainDescent = rInf.GetFont()->GetHeight( pSh, *rInf.GetOut() );
    1171           0 :     const sal_uInt16 nMainAscent = rInf.GetFont()->GetAscent( pSh, *rInf.GetOut() );
    1172           0 :     nMainDescent = nMainDescent - nMainAscent;
    1173             :     // we start with a 50% font, but if we notice that the combined portion
    1174             :     // becomes bigger than the surrounding font, we check 45% and maybe 40%.
    1175           0 :     do
    1176             :     {
    1177           0 :         nProportion -= 5;
    1178           0 :         aTmpFont.SetProportion( nProportion );
    1179           0 :         memset( &aPos, 0, sizeof(aPos) );
    1180           0 :         nMaxDescent = 0;
    1181           0 :         nMaxAscent = 0;
    1182           0 :         nMaxWidth = 0;
    1183           0 :         nUpPos = nLowPos = 0;
    1184             : 
    1185             :         // Now we get the width of all characters.
    1186             :         // The ascent and the width of the first line are stored in the
    1187             :         // ascent member of the portion, the descent in nLowPos.
    1188             :         // The ascent, descent and width of the second line are stored in the
    1189             :         // local nMaxAscent, nMaxDescent and nMaxWidth variables.
    1190           0 :         for( sal_Int32 i = 0; i < nCount; ++i )
    1191             :         {
    1192           0 :             sal_uInt8 nScrp = aScrType[i];
    1193           0 :             aTmpFont.SetActual( nScrp );
    1194           0 :             if( aWidth[ nScrp ] )
    1195             :             {
    1196           0 :                 Size aFontSize( aTmpFont.GetSize( nScrp ) );
    1197           0 :                 aFontSize.Width() = aWidth[ nScrp ];
    1198           0 :                 aTmpFont.SetSize( aFontSize, nScrp );
    1199             :             }
    1200             : 
    1201           0 :             SwDrawTextInfo aDrawInf( pSh, *rInf.GetOut(), 0, aExpand, i, 1 );
    1202           0 :             Size aSize = aTmpFont._GetTxtSize( aDrawInf );
    1203           0 :             const sal_uInt16 nAsc = aTmpFont.GetAscent( pSh, *rInf.GetOut() );
    1204           0 :             aPos[ i ] = (sal_uInt16)aSize.Width();
    1205           0 :             if( i == nTop ) // enter the second line
    1206             :             {
    1207           0 :                 nLowPos = nMaxDescent;
    1208           0 :                 Height( nMaxDescent + nMaxAscent );
    1209           0 :                 Width( nMaxWidth );
    1210           0 :                 SetAscent( nMaxAscent );
    1211           0 :                 nMaxAscent = 0;
    1212           0 :                 nMaxDescent = 0;
    1213           0 :                 nMaxWidth = 0;
    1214             :             }
    1215           0 :             nMaxWidth = nMaxWidth + aPos[ i ];
    1216           0 :             if( nAsc > nMaxAscent )
    1217           0 :                 nMaxAscent = nAsc;
    1218           0 :             if( aSize.Height() - nAsc > nMaxDescent )
    1219           0 :                 nMaxDescent = static_cast<sal_uInt16>(aSize.Height() - nAsc);
    1220           0 :         }
    1221             :         // for one or two characters we double the width of the portion
    1222           0 :         if( nCount < 3 )
    1223             :         {
    1224           0 :             nMaxWidth *= 2;
    1225           0 :             Width( 2*Width() );
    1226           0 :             if( nCount < 2 )
    1227             :             {
    1228           0 :                 Height( nMaxAscent + nMaxDescent );
    1229           0 :                 nLowPos = nMaxDescent;
    1230             :             }
    1231             :         }
    1232           0 :         Height( Height() + nMaxDescent + nMaxAscent );
    1233           0 :         nUpPos = nMaxAscent;
    1234           0 :         SetAscent( Height() - nMaxDescent - nLowPos );
    1235           0 :     } while( nProportion > 40 && ( GetAscent() > nMainAscent ||
    1236           0 :                                     Height() - GetAscent() > nMainDescent ) );
    1237             :     // if the combined portion is smaller than the surrounding text,
    1238             :     // the portion grows. This looks better, if there's a character background.
    1239           0 :     if( GetAscent() < nMainAscent )
    1240             :     {
    1241           0 :         Height( Height() + nMainAscent - GetAscent() );
    1242           0 :         SetAscent( nMainAscent );
    1243             :     }
    1244           0 :     if( Height() < nMainAscent + nMainDescent )
    1245           0 :         Height( nMainAscent + nMainDescent );
    1246             : 
    1247             :     // We calculate the x positions of the characters in both lines..
    1248           0 :     sal_uInt16 nTopDiff = 0;
    1249           0 :     sal_uInt16 nBotDiff = 0;
    1250           0 :     if( nMaxWidth > Width() )
    1251             :     {
    1252           0 :         nTopDiff = ( nMaxWidth - Width() ) / 2;
    1253           0 :         Width( nMaxWidth );
    1254             :     }
    1255             :     else
    1256           0 :         nBotDiff = ( Width() - nMaxWidth ) / 2;
    1257           0 :     switch( nTop)
    1258             :     {
    1259           0 :         case 3: aPos[1] = aPos[0] + nTopDiff;  // no break
    1260           0 :         case 2: aPos[nTop-1] = Width() - aPos[nTop-1];
    1261             :     }
    1262           0 :     aPos[0] = 0;
    1263           0 :     switch( nCount )
    1264             :     {
    1265           0 :         case 5: aPos[4] = aPos[3] + nBotDiff;   // no break
    1266           0 :         case 3: aPos[nTop] = nBotDiff;          break;
    1267           0 :         case 6: aPos[4] = aPos[3] + nBotDiff;   // no break
    1268           0 :         case 4: aPos[nTop] = 0;                 // no break
    1269           0 :         case 2: aPos[nCount-1] = Width() - aPos[nCount-1];
    1270             :     }
    1271             : 
    1272             :     // Does the combined portion fit the line?
    1273           0 :     const bool bFull = rInf.Width() < rInf.X() + Width();
    1274           0 :     if( bFull )
    1275             :     {
    1276           0 :         if( rInf.GetLineStart() == rInf.GetIdx() && (!rInf.GetLast()->InFldGrp()
    1277           0 :             || !((SwFldPortion*)rInf.GetLast())->IsFollow() ) )
    1278           0 :             Width( (sal_uInt16)( rInf.Width() - rInf.X() ) );
    1279             :         else
    1280             :         {
    1281           0 :             Truncate();
    1282           0 :             Width( 0 );
    1283           0 :             SetLen( 0 );
    1284           0 :             if( rInf.GetLast() )
    1285           0 :                 rInf.GetLast()->FormatEOL( rInf );
    1286             :         }
    1287             :     }
    1288           0 :     return bFull;
    1289             : }
    1290             : 
    1291           0 : sal_uInt16 SwCombinedPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
    1292             : {
    1293           0 :     if( !GetLen() ) // for the dummy part at the end of the line, where
    1294           0 :         return 0;   // the combined portion doesn't fit.
    1295           0 :     return SwFldPortion::GetViewWidth( rInf );
    1296             : }
    1297             : 
    1298           0 : SwFldPortion *SwFieldFormDropDownPortion::Clone(const OUString &rExpand) const
    1299             : {
    1300           0 :     return new SwFieldFormDropDownPortion(rExpand);
    1301         270 : }
    1302             : 
    1303             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10