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

Generated by: LCOV version 1.10