LCOV - code coverage report
Current view: top level - sw/source/core/text - porfld.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 673 0.0 %
Date: 2014-04-14 Functions: 0 39 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10