LCOV - code coverage report
Current view: top level - sw/source/core/text - portxt.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 289 425 68.0 %
Date: 2014-11-03 Functions: 29 33 87.9 %
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 <ctype.h>
      21             : 
      22             : #include <com/sun/star/i18n/ScriptType.hpp>
      23             : #include <i18nlangtag/mslangid.hxx>
      24             : #include <hintids.hxx>
      25             : #include <EnhancedPDFExportHelper.hxx>
      26             : #include <SwPortionHandler.hxx>
      27             : #include <porlay.hxx>
      28             : #include <inftxt.hxx>
      29             : #include <guess.hxx>
      30             : #include <porglue.hxx>
      31             : #include <portab.hxx>
      32             : #include <porfld.hxx>
      33             : #include <wrong.hxx>
      34             : #include <viewsh.hxx>
      35             : #include <IDocumentSettingAccess.hxx>
      36             : #include <viewopt.hxx>
      37             : #include <editeng/borderline.hxx>
      38             : 
      39             : #include <IMark.hxx>
      40             : #include <pam.hxx>
      41             : #include <doc.hxx>
      42             : #include <xmloff/odffields.hxx>
      43             : 
      44             : using namespace ::sw::mark;
      45             : using namespace ::com::sun::star;
      46             : using namespace ::com::sun::star::i18n::ScriptType;
      47             : 
      48             : // Returns for how many characters an extra space has to be added
      49             : // (for justified alignment).
      50        9392 : static sal_Int32 lcl_AddSpace( const SwTxtSizeInfo &rInf, const OUString* pStr,
      51             :                                const SwLinePortion& rPor )
      52             : {
      53             :     sal_Int32 nPos, nEnd;
      54        9392 :     const SwScriptInfo* pSI = 0;
      55             : 
      56        9392 :     if ( pStr )
      57             :     {
      58             :         // passing a string means we are inside a field
      59           0 :         nPos = 0;
      60           0 :         nEnd = pStr->getLength();
      61             :     }
      62             :     else
      63             :     {
      64        9392 :         nPos = rInf.GetIdx();
      65        9392 :         nEnd = rInf.GetIdx() + rPor.GetLen();
      66        9392 :         pStr = &rInf.GetTxt();
      67        9392 :         pSI = &((SwParaPortion*)rInf.GetParaPortion())->GetScriptInfo();
      68             :     }
      69             : 
      70        9392 :     sal_Int32 nCnt = 0;
      71        9392 :     sal_uInt8 nScript = 0;
      72             : 
      73             :     // If portion consists of Asian characters and language is not
      74             :     // Korean, we add extra space to each character.
      75             :     // first we get the script type
      76        9392 :     if ( pSI )
      77        9392 :         nScript = pSI->ScriptType( nPos );
      78           0 :     else if ( g_pBreakIt->GetBreakIter().is() )
      79           0 :         nScript = (sal_uInt8)g_pBreakIt->GetBreakIter()->getScriptType( *pStr, nPos );
      80             : 
      81             :     // Note: rInf.GetIdx() can differ from nPos,
      82             :     // e.g., when rPor is a field portion. nPos referes to the string passed
      83             :     // to the function, rInf.GetIdx() referes to the original string.
      84             : 
      85             :     // We try to find out which justification mode is required. This is done by
      86             :     // evaluating the script type and the language attribute set for this portion
      87             : 
      88             :     // Asian Justification: Each character get some extra space
      89        9392 :     if ( nEnd > nPos && ASIAN == nScript )
      90             :     {
      91             :         LanguageType aLang =
      92           0 :             rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
      93             : 
      94           0 :         if (!MsLangId::isKorean(aLang))
      95             :         {
      96           0 :             const SwLinePortion* pPor = rPor.GetPortion();
      97           0 :             if ( pPor && ( pPor->IsKernPortion() ||
      98           0 :                            pPor->IsControlCharPortion() ||
      99           0 :                            pPor->IsPostItsPortion() ) )
     100           0 :                 pPor = pPor->GetPortion();
     101             : 
     102           0 :             nCnt += nEnd - nPos;
     103             : 
     104           0 :             if ( !pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ||
     105           0 :                   pPor->IsBreakPortion() )
     106           0 :                 --nCnt;
     107             : 
     108           0 :             return nCnt;
     109             :         }
     110             :     }
     111             : 
     112             :     // Kashida Justification: Insert Kashidas
     113        9392 :     if ( nEnd > nPos && pSI && COMPLEX == nScript )
     114             :     {
     115           6 :         if ( SwScriptInfo::IsArabicText( *pStr, nPos, nEnd - nPos ) && pSI->CountKashida() )
     116             :         {
     117           0 :             const sal_Int32 nKashRes = pSI->KashidaJustify( 0, 0, nPos, nEnd - nPos );
     118             :             // i60591: need to check result of KashidaJustify
     119             :             // determine if kashida justification is applicable
     120           0 :             if (nKashRes != -1)
     121           0 :                 return nKashRes;
     122             :         }
     123             :     }
     124             : 
     125             :     // Thai Justification: Each character cell gets some extra space
     126        9392 :     if ( nEnd > nPos && COMPLEX == nScript )
     127             :     {
     128             :         LanguageType aLang =
     129           6 :             rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
     130             : 
     131           6 :         if ( LANGUAGE_THAI == aLang )
     132             :         {
     133           0 :             nCnt = SwScriptInfo::ThaiJustify( *pStr, 0, 0, nPos, nEnd - nPos );
     134             : 
     135           0 :             const SwLinePortion* pPor = rPor.GetPortion();
     136           0 :             if ( pPor && ( pPor->IsKernPortion() ||
     137           0 :                            pPor->IsControlCharPortion() ||
     138           0 :                            pPor->IsPostItsPortion() ) )
     139           0 :                 pPor = pPor->GetPortion();
     140             : 
     141           0 :             if ( nCnt && ( ! pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ) )
     142           0 :                 --nCnt;
     143             : 
     144           0 :             return nCnt;
     145             :         }
     146             :     }
     147             : 
     148             :     // Here starts the good old "Look for blanks and add space to them" part.
     149             :     // Note: We do not want to add space to an isolated latin blank in front
     150             :     // of some complex characters in RTL environment
     151             :     const bool bDoNotAddSpace =
     152        9788 :             LATIN == nScript && ( nEnd == nPos + 1 ) && pSI &&
     153             :             ( i18n::ScriptType::COMPLEX ==
     154         402 :               pSI->ScriptType( nPos + 1 ) ) &&
     155        9392 :             rInf.GetTxtFrm() && rInf.GetTxtFrm()->IsRightToLeft();
     156             : 
     157        9392 :     if ( bDoNotAddSpace )
     158           0 :         return nCnt;
     159             : 
     160        9392 :     sal_Int32 nTxtEnd = std::min(nEnd, pStr->getLength());
     161      556014 :     for ( ; nPos < nTxtEnd; ++nPos )
     162             :     {
     163      546622 :         if( CH_BLANK == (*pStr)[ nPos ] )
     164       81552 :             ++nCnt;
     165             :     }
     166             : 
     167             :     // We still have to examine the next character:
     168             :     // If the next character is ASIAN and not KOREAN we have
     169             :     // to add an extra space
     170             :     // nPos referes to the original string, even if a field string has
     171             :     // been passed to this function
     172        9392 :     nPos = rInf.GetIdx() + rPor.GetLen();
     173        9392 :     if ( nPos < rInf.GetTxt().getLength() )
     174             :     {
     175        9328 :         sal_uInt8 nNextScript = 0;
     176        9328 :         const SwLinePortion* pPor = rPor.GetPortion();
     177        9328 :         if ( pPor && pPor->IsKernPortion() )
     178           0 :             pPor = pPor->GetPortion();
     179             : 
     180        9328 :         if ( ! g_pBreakIt->GetBreakIter().is() || ! pPor || pPor->InFixMargGrp() )
     181         234 :             return nCnt;
     182             : 
     183             :         // next character is inside a field?
     184        9094 :         if ( CH_TXTATR_BREAKWORD == rInf.GetChar( nPos ) && pPor->InExpGrp() )
     185             :         {
     186           0 :             bool bOldOnWin = rInf.OnWin();
     187           0 :             ((SwTxtSizeInfo &)rInf).SetOnWin( false );
     188             : 
     189           0 :             OUString aStr;
     190           0 :             pPor->GetExpTxt( rInf, aStr );
     191           0 :             ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
     192             : 
     193           0 :             nNextScript = (sal_uInt8)g_pBreakIt->GetBreakIter()->getScriptType( aStr, 0 );
     194             :         }
     195             :         else
     196        9094 :             nNextScript = (sal_uInt8)g_pBreakIt->GetBreakIter()->getScriptType( rInf.GetTxt(), nPos );
     197             : 
     198        9094 :         if( ASIAN == nNextScript )
     199             :         {
     200             :             LanguageType aLang =
     201           0 :                 rInf.GetTxtFrm()->GetTxtNode()->GetLang( nPos, 1, nNextScript );
     202             : 
     203           0 :             if (!MsLangId::isKorean(aLang))
     204           0 :                 ++nCnt;
     205             :         }
     206             :     }
     207             : 
     208        9158 :     return nCnt;
     209             : }
     210             : 
     211       25080 : SwTxtPortion::SwTxtPortion( const SwLinePortion &rPortion )
     212       25080 :   : SwLinePortion( rPortion )
     213             : {
     214       25080 :     SetWhichPor( POR_TXT );
     215       25080 : }
     216             : 
     217        5016 : void SwTxtPortion::BreakCut( SwTxtFormatInfo &rInf, const SwTxtGuess &rGuess )
     218             : {
     219             :     // The word/char is larger than the line
     220             :     // Special case 1: The word is larger than the line
     221             :     // We truncate ...
     222        5016 :     const sal_uInt16 nLineWidth = (sal_uInt16)(rInf.Width() - rInf.X());
     223        5016 :     sal_Int32 nLen = rGuess.CutPos() - rInf.GetIdx();
     224        5016 :     if( nLen )
     225             :     {
     226             :         // special case: guess does not always provide the correct
     227             :         // width, only in common cases.
     228        3264 :         if ( !rGuess.BreakWidth() )
     229             :         {
     230        2476 :             rInf.SetLen( nLen );
     231        2476 :             SetLen( nLen );
     232        2476 :             CalcTxtSize( rInf );
     233             : 
     234             :             // changing these values requires also changing them in
     235             :             // guess.cxx
     236        2476 :             sal_uInt16 nItalic = 0;
     237        2476 :             if( ITALIC_NONE != rInf.GetFont()->GetItalic() && !rInf.NotEOL() )
     238             :             {
     239           0 :                 nItalic = Height() / 12;
     240             :             }
     241        2476 :             Width( Width() + nItalic );
     242             :         }
     243             :         else
     244             :         {
     245         788 :             Width( rGuess.BreakWidth() );
     246         788 :             SetLen( nLen );
     247             :         }
     248             :     }
     249             :     // special case: first character does not fit to line
     250        1752 :     else if ( rGuess.CutPos() == rInf.GetLineStart() )
     251             :     {
     252        1742 :         SetLen( 1 );
     253        1742 :         Width( nLineWidth );
     254             :     }
     255             :     else
     256             :     {
     257          10 :         SetLen( 0 );
     258          10 :         Width( 0 );
     259             :     }
     260        5016 : }
     261             : 
     262         224 : void SwTxtPortion::BreakUnderflow( SwTxtFormatInfo &rInf )
     263             : {
     264         224 :     Truncate();
     265         224 :     Height( 0 );
     266         224 :     Width( 0 );
     267         224 :     SetLen( 0 );
     268         224 :     SetAscent( 0 );
     269         224 :     rInf.SetUnderflow( this );
     270         224 : }
     271             : 
     272           0 : static bool lcl_HasContent( const SwFldPortion& rFld, SwTxtFormatInfo &rInf )
     273             : {
     274           0 :     OUString aTxt;
     275           0 :     return rFld.GetExpTxt( rInf, aTxt ) && !aTxt.isEmpty();
     276             : }
     277             : 
     278      161843 : bool SwTxtPortion::_Format( SwTxtFormatInfo &rInf )
     279             : {
     280             :     // 5744: If only the hypen does not fit anymore, we still need to wrap
     281             :     // the word, or else return true!
     282      161843 :     if( rInf.IsUnderflow() && rInf.GetSoftHyphPos() )
     283             :     {
     284             :         // soft hyphen portion has triggered an underflow event because
     285             :         // of an alternative spelling position
     286           0 :         bool bFull = false;
     287           0 :         const bool bHyph = rInf.ChgHyph( true );
     288           0 :         if( rInf.IsHyphenate() )
     289             :         {
     290           0 :             SwTxtGuess aGuess;
     291             :             // check for alternative spelling left from the soft hyphen
     292             :             // this should usually be true but
     293           0 :             aGuess.AlternativeSpelling( rInf, rInf.GetSoftHyphPos() - 1 );
     294           0 :             bFull = CreateHyphen( rInf, aGuess );
     295           0 :             OSL_ENSURE( bFull, "Problem with hyphenation!!!" );
     296             :         }
     297           0 :         rInf.ChgHyph( bHyph );
     298           0 :         rInf.SetSoftHyphPos( 0 );
     299           0 :         return bFull;
     300             :     }
     301             : 
     302      161843 :     SwTxtGuess aGuess;
     303      161843 :     const bool bFull = !aGuess.Guess( *this, rInf, Height() );
     304             : 
     305             :     // these are the possible cases:
     306             :     // A Portion fits to current line
     307             :     // B Portion does not fit to current line but a possible line break
     308             :     //   within the portion has been found by the break iterator, 2 subcases
     309             :     //   B1 break is hyphen
     310             :     //   B2 break is word end
     311             :     // C Portion does not fit to current line and no possible line break
     312             :     //   has been found by break iterator, 2 subcases:
     313             :     //   C1 break iterator found a possible line break in portion before us
     314             :     //      ==> this break is used (underflow)
     315             :     //   C2 break iterator does not found a possible line break at all:
     316             :     //      ==> line break
     317             : 
     318             :     // case A: line not yet full
     319      161843 :     if ( !bFull )
     320             :     {
     321      105395 :         Width( aGuess.BreakWidth() );
     322             :         // Vorsicht !
     323      105395 :         if( !InExpGrp() || InFldGrp() )
     324      104027 :             SetLen( rInf.GetLen() );
     325             : 
     326      105395 :         short nKern = rInf.GetFont()->CheckKerning();
     327      105395 :         if( nKern > 0 && rInf.Width() < rInf.X() + Width() + nKern )
     328             :         {
     329           0 :             nKern = (short)(rInf.Width() - rInf.X() - Width() - 1);
     330           0 :             if( nKern < 0 )
     331           0 :                 nKern = 0;
     332             :         }
     333      105395 :         if( nKern )
     334         656 :             new SwKernPortion( *this, nKern );
     335             :     }
     336             :     // special case: hanging portion
     337       56448 :     else if( bFull && aGuess.GetHangingPortion() )
     338             :     {
     339           0 :         Width( aGuess.BreakWidth() );
     340           0 :         SetLen( aGuess.BreakPos() - rInf.GetIdx() );
     341           0 :         Insert( aGuess.GetHangingPortion() );
     342           0 :         aGuess.GetHangingPortion()->SetAscent( GetAscent() );
     343           0 :         aGuess.ClearHangingPortion();
     344             :     }
     345             :     // breakPos >= index
     346       56448 :     else if ( aGuess.BreakPos() >= rInf.GetIdx() && aGuess.BreakPos() != COMPLETE_STRING )
     347             :     {
     348             :         // case B1
     349      162192 :         if( aGuess.HyphWord().is() && aGuess.BreakPos() > rInf.GetLineStart()
     350      162192 :             && ( aGuess.BreakPos() > rInf.GetIdx() ||
     351           0 :                ( rInf.GetLast() && ! rInf.GetLast()->IsFlyPortion() ) ) )
     352             :         {
     353           0 :             CreateHyphen( rInf, aGuess );
     354           0 :             if ( rInf.GetFly() )
     355           0 :                 rInf.GetRoot()->SetMidHyph( true );
     356             :             else
     357           0 :                 rInf.GetRoot()->SetEndHyph( true );
     358             :         }
     359             :         // case C1
     360             :         // - Footnote portions with fake line start (i.e., not at beginning of line)
     361             :         //   should keep together with the text portion. (Note: no keep together
     362             :         //   with only footnote portions.
     363             :         // - TabPortions not at beginning of line should keep together with the
     364             :         //   text portion, if they are not followed by a blank
     365             :         //   (work around different definition of tab stop character - breaking or
     366             :         //   non breaking character - in compatibility mode)
     367      108128 :         else if ( ( IsFtnPortion() && rInf.IsFakeLineStart() &&
     368             : 
     369      108134 :                     rInf.IsOtherThanFtnInside() ) ||
     370      108128 :                   ( rInf.GetLast() &&
     371      108128 :                     rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) &&
     372       54090 :                     rInf.GetLast()->InTabGrp() &&
     373          40 :                     rInf.GetLineStart() + rInf.GetLast()->GetLen() < rInf.GetIdx() &&
     374          20 :                     aGuess.BreakPos() == rInf.GetIdx()  &&
     375          12 :                     CH_BLANK != rInf.GetChar( rInf.GetIdx() ) &&
     376           6 :                     0x3000 != rInf.GetChar( rInf.GetIdx() ) ) )
     377           6 :             BreakUnderflow( rInf );
     378             :         // case B2
     379      155238 :         else if( rInf.GetIdx() > rInf.GetLineStart() ||
     380       50132 :                  aGuess.BreakPos() > rInf.GetIdx() ||
     381             :                  // this is weird: during formatting the follow of a field
     382             :                  // the values rInf.GetIdx and rInf.GetLineStart are replaced
     383             :                  // IsFakeLineStart indicates GetIdx > GetLineStart
     384        6020 :                  rInf.IsFakeLineStart() ||
     385        6020 :                  rInf.GetFly() ||
     386      111126 :                  rInf.IsFirstMulti() ||
     387        5700 :                  ( rInf.GetLast() &&
     388        5700 :                     ( rInf.GetLast()->IsFlyPortion() ||
     389        2850 :                         ( rInf.GetLast()->InFldGrp() &&
     390           0 :                           ! rInf.GetLast()->InNumberGrp() &&
     391           0 :                           ! rInf.GetLast()->IsErgoSumPortion() &&
     392           0 :                           lcl_HasContent(*((SwFldPortion*)rInf.GetLast()),rInf ) ) ) ) )
     393             :         {
     394       51208 :             if ( rInf.X() + aGuess.BreakWidth() <= rInf.Width() )
     395       51208 :                 Width( aGuess.BreakWidth() );
     396             :             else
     397             :                 // this actually should not happen
     398           0 :                 Width( sal_uInt16(rInf.Width() - rInf.X()) );
     399             : 
     400       51208 :             SetLen( aGuess.BreakPos() - rInf.GetIdx() );
     401             : 
     402             :             OSL_ENSURE( aGuess.BreakStart() >= aGuess.FieldDiff(),
     403             :                     "Trouble with expanded field portions during line break" );
     404       51208 :             const sal_Int32 nRealStart = aGuess.BreakStart() - aGuess.FieldDiff();
     405       51208 :             if( aGuess.BreakPos() < nRealStart && !InExpGrp() )
     406             :             {
     407        7025 :                 SwHolePortion *pNew = new SwHolePortion( *this );
     408        7025 :                 pNew->SetLen( nRealStart - aGuess.BreakPos() );
     409        7025 :                 Insert( pNew );
     410             :             }
     411             :         }
     412             :         else    // case C2, last exit
     413        2850 :             BreakCut( rInf, aGuess );
     414             :     }
     415             :     // breakPos < index or no breakpos at all
     416             :     else
     417             :     {
     418        2384 :         bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
     419        5024 :         if( aGuess.BreakPos() != COMPLETE_STRING &&
     420         474 :             aGuess.BreakPos() != rInf.GetLineStart() &&
     421         218 :             ( !bFirstPor || rInf.GetFly() || rInf.GetLast()->IsFlyPortion() ||
     422        2820 :               rInf.IsFirstMulti() ) &&
     423         248 :             ( !rInf.GetLast()->IsBlankPortion() ||  ((SwBlankPortion*)
     424          30 :               rInf.GetLast())->MayUnderflow( rInf, rInf.GetIdx()-1, true )))
     425             :         {       // case C1 (former BreakUnderflow())
     426         218 :             BreakUnderflow( rInf );
     427             :         }
     428             :         else
     429             :              // case C2, last exit
     430        2166 :             BreakCut( rInf, aGuess );
     431             :     }
     432             : 
     433      161843 :     return bFull;
     434             : }
     435             : 
     436      161843 : bool SwTxtPortion::Format( SwTxtFormatInfo &rInf )
     437             : {
     438      161843 :     if( rInf.X() > rInf.Width() || (!GetLen() && !InExpGrp()) )
     439             :     {
     440           0 :         Height( 0 );
     441           0 :         Width( 0 );
     442           0 :         SetLen( 0 );
     443           0 :         SetAscent( 0 );
     444           0 :         SetPortion( NULL );  // ????
     445           0 :         return true;
     446             :     }
     447             : 
     448             :     OSL_ENSURE( rInf.RealWidth() || (rInf.X() == rInf.Width()),
     449             :         "SwTxtPortion::Format: missing real width" );
     450             :     OSL_ENSURE( Height(), "SwTxtPortion::Format: missing height" );
     451             : 
     452      161843 :     return _Format( rInf );
     453             : }
     454             : 
     455             : // Format end of line
     456             : // 5083: We can have awkward cases e.g.:
     457             : // "from {Santa}"
     458             : // Santa wraps, "from " turns into "from" and " " in a justified
     459             : // paragraph, in which the glue gets expanded instead of merged
     460             : // with the MarginPortion.
     461             : 
     462             : // rInf.nIdx points to the next word, nIdx-1 is the portion's last char
     463        1340 : void SwTxtPortion::FormatEOL( SwTxtFormatInfo &rInf )
     464             : {
     465        3704 :     if( ( !GetPortion() || ( GetPortion()->IsKernPortion() &&
     466        2540 :         !GetPortion()->GetPortion() ) ) && GetLen() &&
     467         968 :         rInf.GetIdx() < rInf.GetTxt().getLength() &&
     468         536 :         1 < rInf.GetIdx() && ' ' == rInf.GetChar( rInf.GetIdx() - 1 )
     469        1574 :         && !rInf.GetLast()->IsHolePortion() )
     470             :     {
     471             :         // calculate number of blanks
     472         234 :         sal_Int32 nX = rInf.GetIdx() - 1;
     473         234 :         sal_Int32 nHoleLen = 1;
     474         468 :         while( nX && nHoleLen < GetLen() && CH_BLANK == rInf.GetChar( --nX ) )
     475           0 :             nHoleLen++;
     476             : 
     477             :         // First set ourselves and the insert, because there could be
     478             :         // a SwLineLayout
     479             :         sal_uInt16 nBlankSize;
     480         234 :         if( nHoleLen == GetLen() )
     481           2 :             nBlankSize = Width();
     482             :         else
     483         232 :             nBlankSize = nHoleLen * rInf.GetTxtSize(OUString(' ')).Width();
     484         234 :         Width( Width() - nBlankSize );
     485         234 :         rInf.X( rInf.X() - nBlankSize );
     486         234 :         SetLen( GetLen() - nHoleLen );
     487         234 :         SwLinePortion *pHole = new SwHolePortion( *this );
     488         234 :         ( (SwHolePortion *)pHole )->SetBlankWidth( nBlankSize );
     489         234 :         ( (SwHolePortion *)pHole )->SetLen( nHoleLen );
     490         234 :         Insert( pHole );
     491             :     }
     492        1340 : }
     493             : 
     494           0 : sal_Int32 SwTxtPortion::GetCrsrOfst( const sal_uInt16 nOfst ) const
     495             : {
     496             :     OSL_ENSURE( false, "SwTxtPortion::GetCrsrOfst: don't use this method!" );
     497           0 :     return SwLinePortion::GetCrsrOfst( nOfst );
     498             : }
     499             : 
     500             : // The GetTxtSize() assumes that the own length is correct
     501        6383 : SwPosSize SwTxtPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
     502             : {
     503        6383 :     SwPosSize aSize = rInf.GetTxtSize();
     504        6383 :     if( !GetJoinBorderWithPrev() )
     505        6383 :         aSize.Width(aSize.Width() + rInf.GetFont()->GetLeftBorderSpace() );
     506        6383 :     if( !GetJoinBorderWithNext() )
     507        6383 :         aSize.Width(aSize.Width() + rInf.GetFont()->GetRightBorderSpace() );
     508             : 
     509        6383 :     aSize.Height(aSize.Height() +
     510        6383 :         rInf.GetFont()->GetTopBorderSpace() +
     511        6383 :         rInf.GetFont()->GetBottomBorderSpace() );
     512             : 
     513        6383 :     return aSize;
     514             : }
     515             : 
     516       43422 : void SwTxtPortion::Paint( const SwTxtPaintInfo &rInf ) const
     517             : {
     518       43422 :     if (rInf.OnWin() && 1==rInf.GetLen() && CH_TXT_ATR_FIELDEND==rInf.GetTxt()[rInf.GetIdx()])
     519             :     {
     520             :         assert(false); // this is some debugging only code
     521           0 :         rInf.DrawBackBrush( *this );
     522           0 :         const OUString aTxt(CH_TXT_ATR_SUBST_FIELDEND);
     523           0 :         rInf.DrawText( aTxt, *this, 0, aTxt.getLength(), false );
     524             :     }
     525       43422 :     else if (rInf.OnWin() && 1==rInf.GetLen() && CH_TXT_ATR_FIELDSTART==rInf.GetTxt()[rInf.GetIdx()])
     526             :     {
     527             :         assert(false); // this is some debugging only code
     528           0 :         rInf.DrawBackBrush( *this );
     529           0 :         const OUString aTxt(CH_TXT_ATR_SUBST_FIELDSTART);
     530           0 :         rInf.DrawText( aTxt, *this, 0, aTxt.getLength(), false );
     531             :     }
     532       43422 :     else if( GetLen() )
     533             :     {
     534       40937 :         rInf.DrawBackBrush( *this );
     535       40937 :         rInf.DrawBorder( *this );
     536             : 
     537             :         // do we have to repaint a post it portion?
     538       40937 :         if( rInf.OnWin() && pPortion && !pPortion->Width() )
     539        3074 :             pPortion->PrePaint( rInf, this );
     540             : 
     541       40937 :         const SwWrongList *pWrongList = rInf.GetpWrongList();
     542       40937 :         const SwWrongList *pGrammarCheckList = rInf.GetGrammarCheckList();
     543       40937 :         const SwWrongList *pSmarttags = rInf.GetSmartTags();
     544             : 
     545       40937 :         const bool bWrong = 0 != pWrongList;
     546       40937 :         const bool bGrammarCheck = 0 != pGrammarCheckList;
     547       40937 :         const bool bSmartTags = 0 != pSmarttags;
     548             : 
     549       40937 :         if ( bWrong || bSmartTags || bGrammarCheck )
     550        7838 :             rInf.DrawMarkedText( *this, rInf.GetLen(), false, bWrong, bSmartTags, bGrammarCheck );
     551             :         else
     552       33099 :             rInf.DrawText( *this, rInf.GetLen(), false );
     553             :     }
     554       43422 : }
     555             : 
     556           4 : bool SwTxtPortion::GetExpTxt( const SwTxtSizeInfo &, OUString & ) const
     557             : {
     558           4 :     return false;
     559             : }
     560             : 
     561             : // Responsible for the justified paragraph. They calculate the blank
     562             : // count and the resulting added space.
     563        2780 : sal_Int32 SwTxtPortion::GetSpaceCnt( const SwTxtSizeInfo &rInf,
     564             :                                       sal_Int32& rCharCnt ) const
     565             : {
     566        2780 :     sal_Int32 nCnt = 0;
     567        2780 :     sal_Int32 nPos = 0;
     568        2780 :     if ( InExpGrp() )
     569             :     {
     570          20 :         if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
     571             :         {
     572             :             // OnWin() likes to return a blank instead of an empty string from
     573             :             // time to time. We cannot use that here at all, however.
     574           0 :             bool bOldOnWin = rInf.OnWin();
     575           0 :             ((SwTxtSizeInfo &)rInf).SetOnWin( false );
     576             : 
     577           0 :             OUString aStr;
     578           0 :             GetExpTxt( rInf, aStr );
     579           0 :             ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
     580             : 
     581           0 :             nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
     582           0 :             nPos = aStr.getLength();
     583             :         }
     584             :     }
     585        2760 :     else if( !IsDropPortion() )
     586             :     {
     587        2760 :         nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
     588        2760 :         nPos = GetLen();
     589             :     }
     590        2780 :     rCharCnt = rCharCnt + nPos;
     591        2780 :     return nCnt;
     592             : }
     593             : 
     594        6662 : long SwTxtPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const
     595             : {
     596        6662 :     sal_Int32 nCnt = 0;
     597             : 
     598        6662 :     if ( InExpGrp() )
     599             :     {
     600          30 :         if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
     601             :         {
     602             :             // OnWin() likes to return a blank instead of an empty string from
     603             :             // time to time. We cannot use that here at all, however.
     604           0 :             bool bOldOnWin = rInf.OnWin();
     605           0 :             ((SwTxtSizeInfo &)rInf).SetOnWin( false );
     606             : 
     607           0 :             OUString aStr;
     608           0 :             GetExpTxt( rInf, aStr );
     609           0 :             ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
     610           0 :             if( nSpaceAdd > 0 )
     611           0 :                 nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
     612             :             else
     613             :             {
     614           0 :                 nSpaceAdd = -nSpaceAdd;
     615           0 :                 nCnt = aStr.getLength();
     616           0 :             }
     617             :         }
     618             :     }
     619        6632 :     else if( !IsDropPortion() )
     620             :     {
     621        6632 :         if( nSpaceAdd > 0 )
     622        6632 :             nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
     623             :         else
     624             :         {
     625           0 :             nSpaceAdd = -nSpaceAdd;
     626           0 :             nCnt = GetLen();
     627           0 :             SwLinePortion* pPor = GetPortion();
     628             : 
     629             :             // we do not want an extra space in front of margin portions
     630           0 :             if ( nCnt )
     631             :             {
     632           0 :                 while ( pPor && !pPor->Width() && ! pPor->IsHolePortion() )
     633           0 :                     pPor = pPor->GetPortion();
     634             : 
     635           0 :                 if ( !pPor || pPor->InFixMargGrp() || pPor->IsHolePortion() )
     636           0 :                     --nCnt;
     637             :             }
     638             :         }
     639             :     }
     640             : 
     641        6662 :     return nCnt * nSpaceAdd / SPACING_PRECISION_FACTOR;
     642             : }
     643             : 
     644        1082 : void SwTxtPortion::HandlePortion( SwPortionHandler& rPH ) const
     645             : {
     646        1082 :     rPH.Text( GetLen(), GetWhichPor(), Height(), Width() );
     647        1082 : }
     648             : 
     649          32 : SwTxtInputFldPortion::SwTxtInputFldPortion()
     650             :     : SwTxtPortion()
     651             :     , mbContainsInputFieldStart( false )
     652          32 :     , mbContainsInputFieldEnd( false )
     653             : {
     654          32 :     SetWhichPor( POR_INPUTFLD );
     655          32 : }
     656             : 
     657          32 : bool SwTxtInputFldPortion::Format( SwTxtFormatInfo &rInf )
     658             : {
     659             :     mbContainsInputFieldStart =
     660          32 :         rInf.GetChar( rInf.GetIdx() ) == CH_TXT_ATR_INPUTFIELDSTART;
     661             :     mbContainsInputFieldEnd =
     662          32 :         rInf.GetChar( rInf.GetIdx() + rInf.GetLen() - 1 ) == CH_TXT_ATR_INPUTFIELDEND;
     663             : 
     664          32 :     bool bRet = false;
     665          64 :     if ( rInf.GetLen() == 1
     666          32 :          && ( mbContainsInputFieldStart || mbContainsInputFieldEnd ) )
     667             :     {
     668           0 :         Width( 0 );
     669             :     }
     670             :     else
     671             :     {
     672          32 :         SwTxtSlot aFormatTxt( &rInf, this, true, true );
     673          32 :         if ( rInf.GetLen() == 0 )
     674             :         {
     675           6 :             Width( 0 );
     676             :         }
     677             :         else
     678             :         {
     679          26 :             const sal_Int32 nFormerLineStart = rInf.GetLineStart();
     680          26 :             if ( !mbContainsInputFieldStart )
     681             :             {
     682           0 :                 rInf.SetLineStart( 0 );
     683             :             }
     684             : 
     685          26 :             bRet = SwTxtPortion::Format( rInf );
     686             : 
     687          26 :             if ( mbContainsInputFieldEnd )
     688             :             {
     689             :                 // adjust portion length accordingly, if complete text fits into the portion
     690          26 :                 if ( GetLen() == rInf.GetLen() )
     691             :                 {
     692          26 :                     SetLen( GetLen() + 1 );
     693             :                 }
     694             :             }
     695             : 
     696          26 :             if ( mbContainsInputFieldStart )
     697             :             {
     698             :                 // adjust portion length accordingly
     699          26 :                 SetLen( GetLen() + 1 );
     700             :             }
     701             :             else
     702             :             {
     703           0 :                 rInf.SetLineStart( nFormerLineStart );
     704             :             }
     705          32 :         }
     706             :     }
     707             : 
     708          32 :     return bRet;
     709             : }
     710             : 
     711          28 : void SwTxtInputFldPortion::Paint( const SwTxtPaintInfo &rInf ) const
     712             : {
     713          28 :     if ( Width() )
     714             :     {
     715          24 :         rInf.DrawViewOpt( *this, POR_INPUTFLD );
     716             :         SwTxtSlot aPaintTxt( &rInf, this, true, true,
     717          24 :                              ContainsOnlyDummyChars() ? OUString(" ") : OUString() );
     718          24 :         SwTxtPortion::Paint( rInf );
     719             :     }
     720          28 : }
     721             : 
     722          52 : bool SwTxtInputFldPortion::GetExpTxt( const SwTxtSizeInfo &rInf, OUString &rTxt ) const
     723             : {
     724          52 :     sal_Int32 nIdx = rInf.GetIdx();
     725          52 :     sal_Int32 nLen = rInf.GetLen();
     726          52 :     if ( rInf.GetChar( rInf.GetIdx() ) == CH_TXT_ATR_INPUTFIELDSTART )
     727             :     {
     728          52 :         ++nIdx;
     729          52 :         --nLen;
     730             :     }
     731          52 :     if ( rInf.GetChar( rInf.GetIdx() + rInf.GetLen() - 1 ) == CH_TXT_ATR_INPUTFIELDEND )
     732             :     {
     733          52 :         --nLen;
     734             :     }
     735          52 :     rTxt = rInf.GetTxt().copy( nIdx, std::min( nLen, rInf.GetTxt().getLength() - nIdx ) );
     736             : 
     737          52 :     return true;
     738             : }
     739             : 
     740           0 : SwPosSize SwTxtInputFldPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
     741             : {
     742           0 :     SwTxtSlot aFormatTxt( &rInf, this, true, false );
     743           0 :     if ( rInf.GetLen() == 0 )
     744             :     {
     745           0 :         return SwPosSize( 0, 0 );
     746             :     }
     747             : 
     748           0 :     return rInf.GetTxtSize();
     749             : }
     750             : 
     751           4 : sal_uInt16 SwTxtInputFldPortion::GetViewWidth( const SwTxtSizeInfo &rInf ) const
     752             : {
     753           8 :     if( !Width()
     754           4 :         && ContainsOnlyDummyChars()
     755           4 :         && !rInf.GetOpt().IsPagePreview()
     756           4 :         && !rInf.GetOpt().IsReadonly()
     757           8 :         && SwViewOption::IsFieldShadings() )
     758             :     {
     759           4 :         return rInf.GetTxtSize( " " ).Width();
     760             :     }
     761             : 
     762           0 :     return SwTxtPortion::GetViewWidth( rInf );
     763             : }
     764             : 
     765          28 : bool SwTxtInputFldPortion::ContainsOnlyDummyChars() const
     766             : {
     767          28 :     return GetLen() <= 2
     768           8 :            && mbContainsInputFieldStart
     769          36 :            && mbContainsInputFieldEnd;
     770             : }
     771             : 
     772        7259 : SwHolePortion::SwHolePortion( const SwTxtPortion &rPor )
     773        7259 :     : nBlankWidth( 0 )
     774             : {
     775        7259 :     SetLen( 1 );
     776        7259 :     Height( rPor.Height() );
     777        7259 :     SetAscent( rPor.GetAscent() );
     778        7259 :     SetWhichPor( POR_HOLE );
     779        7259 : }
     780             : 
     781        7345 : SwLinePortion *SwHolePortion::Compress() { return this; }
     782             : 
     783        2216 : void SwHolePortion::Paint( const SwTxtPaintInfo &rInf ) const
     784             : {
     785        2216 :     if( !rInf.GetOut() )
     786        2216 :         return;
     787             : 
     788             :     // #i16816# export stuff only needed for tagged pdf support
     789        2216 :     if (!SwTaggedPDFHelper::IsExportTaggedPDF( *rInf.GetOut()) )
     790        2216 :         return;
     791             : 
     792             :     // #i68503# the hole must have no decoration for a consistent visual appearance
     793           0 :     const SwFont* pOrigFont = rInf.GetFont();
     794           0 :     SwFont* pHoleFont = NULL;
     795           0 :     SwFontSave* pFontSave = NULL;
     796           0 :     if( pOrigFont->GetUnderline() != UNDERLINE_NONE
     797           0 :     ||  pOrigFont->GetOverline() != UNDERLINE_NONE
     798           0 :     ||  pOrigFont->GetStrikeout() != STRIKEOUT_NONE )
     799             :     {
     800           0 :         pHoleFont = new SwFont( *pOrigFont );
     801           0 :         pHoleFont->SetUnderline( UNDERLINE_NONE );
     802           0 :         pHoleFont->SetOverline( UNDERLINE_NONE );
     803           0 :         pHoleFont->SetStrikeout( STRIKEOUT_NONE );
     804           0 :         pFontSave = new SwFontSave( rInf, pHoleFont );
     805             :     }
     806             : 
     807           0 :     const OUString aTxt( ' ' );
     808           0 :     rInf.DrawText( aTxt, *this, 0, 1, false );
     809             : 
     810           0 :     delete pFontSave;
     811           0 :     delete pHoleFont;
     812             : }
     813             : 
     814           0 : bool SwHolePortion::Format( SwTxtFormatInfo &rInf )
     815             : {
     816           0 :     return rInf.IsFull() || rInf.X() >= rInf.Width();
     817             : }
     818             : 
     819           6 : void SwHolePortion::HandlePortion( SwPortionHandler& rPH ) const
     820             : {
     821           6 :     rPH.Text( GetLen(), GetWhichPor() );
     822           6 : }
     823             : 
     824          28 : void SwFieldMarkPortion::Paint( const SwTxtPaintInfo & /*rInf*/) const
     825             : {
     826             :     // These shouldn't be painted!
     827             :     //SwTxtPortion::Paint(rInf);
     828          28 : }
     829             : 
     830         412 : bool SwFieldMarkPortion::Format( SwTxtFormatInfo & )
     831             : {
     832         412 :     Width(0);
     833         412 :     return false;
     834             : }
     835             : 
     836           4 : void SwFieldFormCheckboxPortion::Paint( const SwTxtPaintInfo& rInf ) const
     837             : {
     838           4 :     SwTxtNode* pNd = const_cast<SwTxtNode*>(rInf.GetTxtFrm()->GetTxtNode());
     839           4 :     const SwDoc *doc=pNd->GetDoc();
     840           4 :     SwIndex aIndex( pNd, rInf.GetIdx() );
     841           8 :     SwPosition aPosition(*pNd, aIndex);
     842             : 
     843           4 :     IFieldmark* pBM = doc->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition );
     844             : 
     845             :     OSL_ENSURE(pBM && pBM->GetFieldname( ) == ODF_FORMCHECKBOX,
     846             :         "Where is my form field bookmark???");
     847             : 
     848           4 :     if (pBM && pBM->GetFieldname( ) == ODF_FORMCHECKBOX)
     849             :     {
     850           4 :         const ICheckboxFieldmark* pCheckboxFm = dynamic_cast< ICheckboxFieldmark* >(pBM);
     851           4 :         bool bChecked = pCheckboxFm && pCheckboxFm->IsChecked();
     852           4 :         rInf.DrawCheckBox(*this, bChecked);
     853           4 :     }
     854           4 : }
     855             : 
     856          18 : bool SwFieldFormCheckboxPortion::Format( SwTxtFormatInfo & rInf )
     857             : {
     858          18 :     SwTxtNode *pNd = const_cast < SwTxtNode * >( rInf.GetTxtFrm(  )->GetTxtNode(  ) );
     859          18 :     const SwDoc *doc = pNd->GetDoc(  );
     860          18 :     SwIndex aIndex( pNd, rInf.GetIdx(  ) );
     861          36 :     SwPosition aPosition( *pNd, aIndex );
     862          18 :     IFieldmark *pBM = doc->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition );
     863             :     OSL_ENSURE(pBM && pBM->GetFieldname( ) == ODF_FORMCHECKBOX, "Where is my form field bookmark???");
     864          18 :     if (pBM && pBM->GetFieldname( ) == ODF_FORMCHECKBOX)
     865             :     {
     866          18 :         Width( rInf.GetTxtHeight(  ) );
     867          18 :         Height( rInf.GetTxtHeight(  ) );
     868          18 :         SetAscent( rInf.GetAscent(  ) );
     869             :     }
     870          36 :     return false;
     871         270 : }
     872             : 
     873             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10