LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sw/source/core/text - portxt.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 202 386 52.3 %
Date: 2013-07-09 Functions: 20 27 74.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10