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

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

Generated by: LCOV version 1.10