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

Generated by: LCOV version 1.10