summaryrefslogtreecommitdiff
path: root/sw/source/core/text/portxt.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/text/portxt.cxx')
-rw-r--r--sw/source/core/text/portxt.cxx876
1 files changed, 876 insertions, 0 deletions
diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
new file mode 100644
index 000000000000..a84ccb6b52de
--- /dev/null
+++ b/sw/source/core/text/portxt.cxx
@@ -0,0 +1,876 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <ctype.h>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <hintids.hxx> // CH_TXTATR
+#include <SwPortionHandler.hxx>
+#include <porlay.hxx>
+#include <inftxt.hxx>
+#include <guess.hxx> // SwTxtGuess, Zeilenumbruch
+#include <porglue.hxx>
+#include <portab.hxx> // pLastTab->
+#include <porfld.hxx> // SwFldPortion
+#include <wrong.hxx>
+#include <viewsh.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <viewopt.hxx> // SwViewOptions
+
+#include <IMark.hxx>
+#include <pam.hxx>
+#include <doc.hxx>
+#include <xmloff/odffields.hxx>
+
+using namespace ::sw::mark;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n::ScriptType;
+
+/*************************************************************************
+ * lcl_AddSpace
+ * Returns for how many characters an extra space has to be added
+ * (for justified alignment).
+ *************************************************************************/
+
+sal_uInt16 lcl_AddSpace( const SwTxtSizeInfo &rInf, const XubString* pStr,
+ const SwLinePortion& rPor )
+{
+ xub_StrLen nPos, nEnd;
+ const SwScriptInfo* pSI = 0;
+
+ if ( pStr )
+ {
+ // passing a string means we are inside a field
+ nPos = 0;
+ nEnd = pStr->Len();
+ }
+ else
+ {
+ nPos = rInf.GetIdx();
+ nEnd = rInf.GetIdx() + rPor.GetLen();
+ pStr = &rInf.GetTxt();
+ pSI = &((SwParaPortion*)rInf.GetParaPortion())->GetScriptInfo();
+ }
+
+ sal_uInt16 nCnt = 0;
+ sal_uInt8 nScript = 0;
+
+ // If portion consists of Asian characters and language is not
+ // Korean, we add extra space to each character.
+ // first we get the script type
+ if ( pSI )
+ nScript = pSI->ScriptType( nPos );
+ else if ( pBreakIt->GetBreakIter().is() )
+ nScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( *pStr, nPos );
+
+ // Note: rInf.GetIdx() can differ from nPos,
+ // e.g., when rPor is a field portion. nPos referes to the string passed
+ // to the function, rInf.GetIdx() referes to the original string.
+
+ // We try to find out which justification mode is required. This is done by
+ // evaluating the script type and the language attribute set for this portion
+
+ // Asian Justification: Each character get some extra space
+ if ( nEnd > nPos && ASIAN == nScript )
+ {
+ LanguageType aLang =
+ rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
+
+ if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
+ {
+ const SwLinePortion* pPor = rPor.GetPortion();
+ if ( pPor && ( pPor->IsKernPortion() ||
+ pPor->IsControlCharPortion() ||
+ pPor->IsPostItsPortion() ) )
+ pPor = pPor->GetPortion();
+
+ nCnt += nEnd - nPos;
+
+ if ( !pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ||
+ pPor->IsBreakPortion() )
+ --nCnt;
+
+ return nCnt;
+ }
+ }
+
+ // Kashida Justification: Insert Kashidas
+ if ( nEnd > nPos && pSI && COMPLEX == nScript )
+ {
+ if ( SwScriptInfo::IsArabicText( *pStr, nPos, nEnd - nPos ) && pSI->CountKashida() )
+ {
+ const sal_uInt16 nKashRes = pSI->KashidaJustify( 0, 0, nPos, nEnd - nPos );
+ // i60591: need to check result of KashidaJustify
+ // determine if kashida justification is applicable
+ if( nKashRes != STRING_LEN )
+ return nKashRes;
+ }
+ }
+
+ // Thai Justification: Each character cell gets some extra space
+ if ( nEnd > nPos && COMPLEX == nScript )
+ {
+ LanguageType aLang =
+ rInf.GetTxtFrm()->GetTxtNode()->GetLang( rInf.GetIdx(), 1, nScript );
+
+ if ( LANGUAGE_THAI == aLang )
+ {
+ nCnt = SwScriptInfo::ThaiJustify( *pStr, 0, 0, nPos, nEnd - nPos );
+
+ const SwLinePortion* pPor = rPor.GetPortion();
+ if ( pPor && ( pPor->IsKernPortion() ||
+ pPor->IsControlCharPortion() ||
+ pPor->IsPostItsPortion() ) )
+ pPor = pPor->GetPortion();
+
+ if ( nCnt && ( ! pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ) )
+ --nCnt;
+
+ return nCnt;
+ }
+ }
+
+ // Here starts the good old "Look for blanks and add space to them" part.
+ // Note: We do not want to add space to an isolated latin blank in front
+ // of some complex characters in RTL environment
+ const sal_Bool bDoNotAddSpace =
+ LATIN == nScript && ( nEnd == nPos + 1 ) && pSI &&
+ ( i18n::ScriptType::COMPLEX ==
+ pSI->ScriptType( nPos + 1 ) ) &&
+ rInf.GetTxtFrm() && rInf.GetTxtFrm()->IsRightToLeft();
+
+ if ( bDoNotAddSpace )
+ return nCnt;
+
+ for ( ; nPos < nEnd; ++nPos )
+ {
+ if( CH_BLANK == pStr->GetChar( nPos ) )
+ ++nCnt;
+ }
+
+ // We still have to examine the next character:
+ // If the next character is ASIAN and not KOREAN we have
+ // to add an extra space
+ // nPos referes to the original string, even if a field string has
+ // been passed to this function
+ nPos = rInf.GetIdx() + rPor.GetLen();
+ if ( nPos < rInf.GetTxt().Len() )
+ {
+ sal_uInt8 nNextScript = 0;
+ const SwLinePortion* pPor = rPor.GetPortion();
+ if ( pPor && pPor->IsKernPortion() )
+ pPor = pPor->GetPortion();
+
+ if ( ! pBreakIt->GetBreakIter().is() || ! pPor || pPor->InFixMargGrp() )
+ return nCnt;
+
+ // next character is inside a field?
+ if ( CH_TXTATR_BREAKWORD == rInf.GetChar( nPos ) && pPor->InExpGrp() )
+ {
+ sal_Bool bOldOnWin = rInf.OnWin();
+ ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
+
+ XubString aStr( aEmptyStr );
+ pPor->GetExpTxt( rInf, aStr );
+ ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
+
+ nNextScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( aStr, 0 );
+ }
+ else
+ nNextScript = (sal_uInt8)pBreakIt->GetBreakIter()->getScriptType( rInf.GetTxt(), nPos );
+
+ if( ASIAN == nNextScript )
+ {
+ LanguageType aLang =
+ rInf.GetTxtFrm()->GetTxtNode()->GetLang( nPos, 1, nNextScript );
+
+ if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
+ ++nCnt;
+ }
+ }
+
+ return nCnt;
+}
+
+/*************************************************************************
+ * class SwTxtPortion
+ *************************************************************************/
+
+SwTxtPortion::SwTxtPortion( const SwLinePortion &rPortion )
+ : SwLinePortion( rPortion )
+{
+ SetWhichPor( POR_TXT );
+}
+
+/*************************************************************************
+ * SwTxtPortion::BreakCut()
+ *************************************************************************/
+
+void SwTxtPortion::BreakCut( SwTxtFormatInfo &rInf, const SwTxtGuess &rGuess )
+{
+ // Das Wort/Zeichen ist groesser als die Zeile
+ // Sonderfall Nr.1: Das Wort ist groesser als die Zeile
+ // Wir kappen...
+ const KSHORT nLineWidth = (KSHORT)(rInf.Width() - rInf.X());
+ xub_StrLen nLen = rGuess.CutPos() - rInf.GetIdx();
+ if( nLen )
+ {
+ // special case: guess does not always provide the correct
+ // width, only in common cases.
+ if ( !rGuess.BreakWidth() )
+ {
+ rInf.SetLen( nLen );
+ SetLen( nLen );
+ CalcTxtSize( rInf );
+
+ // changing these values requires also changing them in
+ // guess.cxx
+ KSHORT nItalic = 0;
+ if( ITALIC_NONE != rInf.GetFont()->GetItalic() && !rInf.NotEOL() )
+ {
+ nItalic = Height() / 12;
+ }
+ Width( Width() + nItalic );
+ }
+ else
+ {
+ Width( rGuess.BreakWidth() );
+ SetLen( nLen );
+ }
+ }
+ // special case: first character does not fit to line
+ else if ( rGuess.CutPos() == rInf.GetLineStart() )
+ {
+ SetLen( 1 );
+ Width( nLineWidth );
+ }
+ else
+ {
+ SetLen( 0 );
+ Width( 0 );
+ }
+}
+
+/*************************************************************************
+ * SwTxtPortion::BreakUnderflow()
+ *************************************************************************/
+
+void SwTxtPortion::BreakUnderflow( SwTxtFormatInfo &rInf )
+{
+ Truncate();
+ Height( 0 );
+ Width( 0 );
+ SetLen( 0 );
+ SetAscent( 0 );
+ rInf.SetUnderFlow( this );
+}
+
+ /*************************************************************************
+ * SwTxtPortion::_Format()
+ *************************************************************************/
+
+sal_Bool lcl_HasContent( const SwFldPortion& rFld, SwTxtFormatInfo &rInf )
+{
+ String aTxt;
+ return rFld.GetExpTxt( rInf, aTxt ) && aTxt.Len();
+}
+
+sal_Bool SwTxtPortion::_Format( SwTxtFormatInfo &rInf )
+{
+ // 5744: wenn nur der Trennstrich nicht mehr passt,
+ // muss trotzdem das Wort umgebrochen werden, ansonsten return sal_True!
+ if( rInf.IsUnderFlow() && rInf.GetSoftHyphPos() )
+ {
+ // soft hyphen portion has triggered an underflow event because
+ // of an alternative spelling position
+ sal_Bool bFull = sal_False;
+ const sal_Bool bHyph = rInf.ChgHyph( sal_True );
+ if( rInf.IsHyphenate() )
+ {
+ SwTxtGuess aGuess;
+ // check for alternative spelling left from the soft hyphen
+ // this should usually be true but
+ aGuess.AlternativeSpelling( rInf, rInf.GetSoftHyphPos() - 1 );
+ bFull = CreateHyphen( rInf, aGuess );
+ OSL_ENSURE( bFull, "Problem with hyphenation!!!" );
+ }
+ rInf.ChgHyph( bHyph );
+ rInf.SetSoftHyphPos( 0 );
+ return bFull;
+ }
+
+ SwTxtGuess aGuess;
+ const sal_Bool bFull = !aGuess.Guess( *this, rInf, Height() );
+
+ // these are the possible cases:
+ // A Portion fits to current line
+ // B Portion does not fit to current line but a possible line break
+ // within the portion has been found by the break iterator, 2 subcases
+ // B1 break is hyphen
+ // B2 break is word end
+ // C Portion does not fit to current line and no possible line break
+ // has been found by break iterator, 2 subcases:
+ // C1 break iterator found a possible line break in portion before us
+ // ==> this break is used (underflow)
+ // C2 break iterator does not found a possible line break at all:
+ // ==> line break
+
+ // case A: line not yet full
+ if ( !bFull )
+ {
+ Width( aGuess.BreakWidth() );
+ // Vorsicht !
+ if( !InExpGrp() || InFldGrp() )
+ SetLen( rInf.GetLen() );
+
+ short nKern = rInf.GetFont()->CheckKerning();
+ if( nKern > 0 && rInf.Width() < rInf.X() + Width() + nKern )
+ {
+ nKern = (short)(rInf.Width() - rInf.X() - Width() - 1);
+ if( nKern < 0 )
+ nKern = 0;
+ }
+ if( nKern )
+ new SwKernPortion( *this, nKern );
+ }
+ // special case: hanging portion
+ else if( bFull && aGuess.GetHangingPortion() )
+ {
+ Width( aGuess.BreakWidth() );
+ SetLen( aGuess.BreakPos() - rInf.GetIdx() );
+ Insert( aGuess.GetHangingPortion() );
+ aGuess.GetHangingPortion()->SetAscent( GetAscent() );
+ aGuess.ClearHangingPortion();
+ }
+ // breakPos >= index
+ else if ( aGuess.BreakPos() >= rInf.GetIdx() && aGuess.BreakPos() != STRING_LEN )
+ {
+ // case B1
+ if( aGuess.HyphWord().is() && aGuess.BreakPos() > rInf.GetLineStart()
+ && ( aGuess.BreakPos() > rInf.GetIdx() ||
+ ( rInf.GetLast() && ! rInf.GetLast()->IsFlyPortion() ) ) )
+ {
+ CreateHyphen( rInf, aGuess );
+ if ( rInf.GetFly() )
+ rInf.GetRoot()->SetMidHyph( sal_True );
+ else
+ rInf.GetRoot()->SetEndHyph( sal_True );
+ }
+ // case C1
+ // - Footnote portions with fake line start (i.e., not at beginning of line)
+ // should keep together with the text portion. (Note: no keep together
+ // with only footnote portions.
+ // - TabPortions not at beginning of line should keep together with the
+ // text portion, if they are not followed by a blank
+ // (work around different definition of tab stop character - breaking or
+ // non breaking character - in compatibility mode)
+ else if ( ( IsFtnPortion() && rInf.IsFakeLineStart() &&
+ // --> OD 2010-01-29 #b6921213#
+ rInf.IsOtherThanFtnInside() ) ||
+ // <--
+ ( rInf.GetLast() &&
+ rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) &&
+ rInf.GetLast()->InTabGrp() &&
+ rInf.GetLineStart() + rInf.GetLast()->GetLen() < rInf.GetIdx() &&
+ aGuess.BreakPos() == rInf.GetIdx() &&
+ CH_BLANK != rInf.GetChar( rInf.GetIdx() ) &&
+ 0x3000 != rInf.GetChar( rInf.GetIdx() ) ) )
+ BreakUnderflow( rInf );
+ // case B2
+ else if( rInf.GetIdx() > rInf.GetLineStart() ||
+ aGuess.BreakPos() > rInf.GetIdx() ||
+ // this is weird: during formatting the follow of a field
+ // the values rInf.GetIdx and rInf.GetLineStart are replaced
+ // IsFakeLineStart indicates GetIdx > GetLineStart
+ rInf.IsFakeLineStart() ||
+ rInf.GetFly() ||
+ rInf.IsFirstMulti() ||
+ ( rInf.GetLast() &&
+ ( rInf.GetLast()->IsFlyPortion() ||
+ ( rInf.GetLast()->InFldGrp() &&
+ ! rInf.GetLast()->InNumberGrp() &&
+ ! rInf.GetLast()->IsErgoSumPortion() &&
+ lcl_HasContent(*((SwFldPortion*)rInf.GetLast()),rInf ) ) ) ) )
+ {
+ if ( rInf.X() + aGuess.BreakWidth() <= rInf.Width() )
+ Width( aGuess.BreakWidth() );
+ else
+ // this actually should not happen
+ Width( KSHORT(rInf.Width() - rInf.X()) );
+
+ SetLen( aGuess.BreakPos() - rInf.GetIdx() );
+
+ OSL_ENSURE( aGuess.BreakStart() >= aGuess.FieldDiff(),
+ "Trouble with expanded field portions during line break" );
+ const xub_StrLen nRealStart = aGuess.BreakStart() - aGuess.FieldDiff();
+ if( aGuess.BreakPos() < nRealStart && !InExpGrp() )
+ {
+ SwHolePortion *pNew = new SwHolePortion( *this );
+ pNew->SetLen( nRealStart - aGuess.BreakPos() );
+ Insert( pNew );
+ }
+ }
+ else // case C2, last exit
+ BreakCut( rInf, aGuess );
+ }
+ // breakPos < index or no breakpos at all
+ else
+ {
+ sal_Bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
+ if( aGuess.BreakPos() != STRING_LEN &&
+ aGuess.BreakPos() != rInf.GetLineStart() &&
+ ( !bFirstPor || rInf.GetFly() || rInf.GetLast()->IsFlyPortion() ||
+ rInf.IsFirstMulti() ) &&
+ ( !rInf.GetLast()->IsBlankPortion() || ((SwBlankPortion*)
+ rInf.GetLast())->MayUnderFlow( rInf, rInf.GetIdx()-1, sal_True )))
+ { // case C1 (former BreakUnderflow())
+ BreakUnderflow( rInf );
+ }
+ else
+ // case C2, last exit
+ BreakCut( rInf, aGuess );
+ }
+
+ return bFull;
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::Format()
+ *************************************************************************/
+
+
+
+sal_Bool SwTxtPortion::Format( SwTxtFormatInfo &rInf )
+{
+#if OSL_DEBUG_LEVEL > 1
+ const XubString aDbgTxt( rInf.GetTxt().Copy( rInf.GetIdx(), rInf.GetLen() ) );
+#endif
+
+ if( rInf.X() > rInf.Width() || (!GetLen() && !InExpGrp()) )
+ {
+ Height( 0 );
+ Width( 0 );
+ SetLen( 0 );
+ SetAscent( 0 );
+ SetPortion( NULL ); // ????
+ return sal_True;
+ }
+
+ OSL_ENSURE( rInf.RealWidth() || (rInf.X() == rInf.Width()),
+ "SwTxtPortion::Format: missing real width" );
+ OSL_ENSURE( Height(), "SwTxtPortion::Format: missing height" );
+
+ return _Format( rInf );
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::FormatEOL()
+ *************************************************************************/
+
+// Format end of line
+// 5083: Es kann schon manchmal unguenstige Faelle geben...
+// "vom {Nikolaus}", Nikolaus bricht um "vom " wird im Blocksatz
+// zu "vom" und " ", wobei der Glue expandiert wird, statt in die
+// MarginPortion aufzugehen.
+// rInf.nIdx steht auf dem naechsten Wort, nIdx-1 ist der letzte
+// Buchstabe der Portion.
+
+
+
+void SwTxtPortion::FormatEOL( SwTxtFormatInfo &rInf )
+{
+ if( ( !GetPortion() || ( GetPortion()->IsKernPortion() &&
+ !GetPortion()->GetPortion() ) ) && GetLen() &&
+ rInf.GetIdx() < rInf.GetTxt().Len() &&
+ 1 < rInf.GetIdx() && ' ' == rInf.GetChar( rInf.GetIdx() - 1 )
+ && !rInf.GetLast()->IsHolePortion() )
+ {
+ // calculate number of blanks
+ xub_StrLen nX = rInf.GetIdx() - 1;
+ sal_uInt16 nHoleLen = 1;
+ while( nX && nHoleLen < GetLen() && CH_BLANK == rInf.GetChar( --nX ) )
+ nHoleLen++;
+
+ // Erst uns einstellen und dann Inserten, weil wir ja auch ein
+ // SwLineLayout sein koennten.
+ KSHORT nBlankSize;
+ if( nHoleLen == GetLen() )
+ nBlankSize = Width();
+ else
+ nBlankSize = nHoleLen * rInf.GetTxtSize( ' ' ).Width();
+ Width( Width() - nBlankSize );
+ rInf.X( rInf.X() - nBlankSize );
+ SetLen( GetLen() - nHoleLen );
+ SwLinePortion *pHole = new SwHolePortion( *this );
+ ( (SwHolePortion *)pHole )->SetBlankWidth( nBlankSize );
+ ( (SwHolePortion *)pHole )->SetLen( nHoleLen );
+ Insert( pHole );
+ }
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::GetCrsrOfst()
+ *************************************************************************/
+
+
+
+xub_StrLen SwTxtPortion::GetCrsrOfst( const KSHORT nOfst ) const
+{
+ OSL_ENSURE( !this, "SwTxtPortion::GetCrsrOfst: don't use this method!" );
+ return SwLinePortion::GetCrsrOfst( nOfst );
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::GetTxtSize()
+ *************************************************************************/
+// Das GetTxtSize() geht davon aus, dass die eigene Laenge korrekt ist
+
+SwPosSize SwTxtPortion::GetTxtSize( const SwTxtSizeInfo &rInf ) const
+{
+ return rInf.GetTxtSize();
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::Paint()
+ *************************************************************************/
+
+
+
+void SwTxtPortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ if (rInf.OnWin() && 1==rInf.GetLen() && CH_TXT_ATR_FIELDEND==rInf.GetTxt().GetChar(rInf.GetIdx()))
+ {
+ rInf.DrawBackBrush( *this );
+ const XubString aTxt = XubString::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDEND);
+ rInf.DrawText( aTxt, *this, 0, aTxt.Len(), false );
+ }
+ else if (rInf.OnWin() && 1==rInf.GetLen() && CH_TXT_ATR_FIELDSTART==rInf.GetTxt().GetChar(rInf.GetIdx()))
+ {
+ rInf.DrawBackBrush( *this );
+ const XubString aTxt = XubString::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDSTART);
+ rInf.DrawText( aTxt, *this, 0, aTxt.Len(), false );
+ }
+ else if( GetLen() )
+ {
+ rInf.DrawBackBrush( *this );
+
+ // do we have to repaint a post it portion?
+ if( rInf.OnWin() && pPortion && !pPortion->Width() )
+ pPortion->PrePaint( rInf, this );
+
+ const SwWrongList *pWrongList = rInf.GetpWrongList();
+ const SwWrongList *pGrammarCheckList = rInf.GetGrammarCheckList();
+ // SMARTTAGS
+ const SwWrongList *pSmarttags = rInf.GetSmartTags();
+
+ const bool bWrong = 0 != pWrongList;
+ const bool bGrammarCheck = 0 != pGrammarCheckList;
+ const bool bSmartTags = 0 != pSmarttags;
+
+ if ( bWrong || bSmartTags || bGrammarCheck )
+ rInf.DrawMarkedText( *this, rInf.GetLen(), sal_False, bWrong, bSmartTags, bGrammarCheck );
+ else
+ rInf.DrawText( *this, rInf.GetLen(), sal_False );
+ }
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::GetExpTxt()
+ *************************************************************************/
+
+
+
+sal_Bool SwTxtPortion::GetExpTxt( const SwTxtSizeInfo &, XubString & ) const
+{
+ return sal_False;
+}
+
+/*************************************************************************
+ * xub_StrLen SwTxtPortion::GetSpaceCnt()
+ * long SwTxtPortion::CalcSpacing()
+ * sind fuer den Blocksatz zustaendig und ermitteln die Anzahl der Blanks
+ * und den daraus resultierenden zusaetzlichen Zwischenraum
+ *************************************************************************/
+
+xub_StrLen SwTxtPortion::GetSpaceCnt( const SwTxtSizeInfo &rInf,
+ xub_StrLen& rCharCnt ) const
+{
+ xub_StrLen nCnt = 0;
+ xub_StrLen nPos = 0;
+ if ( InExpGrp() )
+ {
+ if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
+ {
+ // Bei OnWin() wird anstatt eines Leerstrings gern mal ein Blank
+ // zurueckgeliefert, das koennen wir hier aber gar nicht gebrauchen
+ sal_Bool bOldOnWin = rInf.OnWin();
+ ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
+
+ XubString aStr( aEmptyStr );
+ GetExpTxt( rInf, aStr );
+ ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
+
+ nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
+ nPos = aStr.Len();
+ }
+ }
+ else if( !IsDropPortion() )
+ {
+ nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
+ nPos = GetLen();
+ }
+ rCharCnt = rCharCnt + nPos;
+ return nCnt;
+}
+
+long SwTxtPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const
+{
+ xub_StrLen nCnt = 0;
+
+ if ( InExpGrp() )
+ {
+ if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
+ {
+ // Bei OnWin() wird anstatt eines Leerstrings gern mal ein Blank
+ // zurueckgeliefert, das koennen wir hier aber gar nicht gebrauchen
+ sal_Bool bOldOnWin = rInf.OnWin();
+ ((SwTxtSizeInfo &)rInf).SetOnWin( sal_False );
+
+ XubString aStr( aEmptyStr );
+ GetExpTxt( rInf, aStr );
+ ((SwTxtSizeInfo &)rInf).SetOnWin( bOldOnWin );
+ if( nSpaceAdd > 0 )
+ nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
+ else
+ {
+ nSpaceAdd = -nSpaceAdd;
+ nCnt = aStr.Len();
+ }
+ }
+ }
+ else if( !IsDropPortion() )
+ {
+ if( nSpaceAdd > 0 )
+ nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
+ else
+ {
+ nSpaceAdd = -nSpaceAdd;
+ nCnt = GetLen();
+ SwLinePortion* pPor = GetPortion();
+
+ // we do not want an extra space in front of margin portions
+ if ( nCnt )
+ {
+ while ( pPor && !pPor->Width() && ! pPor->IsHolePortion() )
+ pPor = pPor->GetPortion();
+
+ if ( !pPor || pPor->InFixMargGrp() || pPor->IsHolePortion() )
+ --nCnt;
+ }
+ }
+ }
+
+ return nCnt * nSpaceAdd / SPACING_PRECISION_FACTOR;
+}
+
+/*************************************************************************
+ * virtual SwTxtPortion::HandlePortion()
+ *************************************************************************/
+
+void SwTxtPortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Text( GetLen(), GetWhichPor() );
+}
+
+/*************************************************************************
+ * class SwHolePortion
+ *************************************************************************/
+
+
+
+SwHolePortion::SwHolePortion( const SwTxtPortion &rPor )
+ : nBlankWidth( 0 )
+{
+ SetLen( 1 );
+ Height( rPor.Height() );
+ SetAscent( rPor.GetAscent() );
+ SetWhichPor( POR_HOLE );
+}
+
+SwLinePortion *SwHolePortion::Compress() { return this; }
+
+/*************************************************************************
+ * virtual SwHolePortion::Paint()
+ *************************************************************************/
+
+
+
+void SwHolePortion::Paint( const SwTxtPaintInfo &rInf ) const
+{
+ // --> FME 2004-06-24 #i16816# tagged pdf support
+ if( rInf.GetVsh() && rInf.GetVsh()->GetViewOptions()->IsPDFExport() )
+ {
+ const XubString aTxt( ' ' );
+ rInf.DrawText( aTxt, *this, 0, 1, false );
+ }
+ // <--
+}
+
+/*************************************************************************
+ * virtual SwHolePortion::Format()
+ *************************************************************************/
+
+
+
+sal_Bool SwHolePortion::Format( SwTxtFormatInfo &rInf )
+{
+ return rInf.IsFull() || rInf.X() >= rInf.Width();
+}
+
+/*************************************************************************
+ * virtual SwHolePortion::HandlePortion()
+ *************************************************************************/
+
+void SwHolePortion::HandlePortion( SwPortionHandler& rPH ) const
+{
+ rPH.Text( GetLen(), GetWhichPor() );
+}
+
+void SwFieldMarkPortion::Paint( const SwTxtPaintInfo & /*rInf*/) const
+{
+ // These shouldn't be painted!
+ // SwTxtPortion::Paint(rInf);
+}
+
+sal_Bool SwFieldMarkPortion::Format( SwTxtFormatInfo & )
+{
+ sal_Bool ret=0;
+ Width(0);
+ return ret;
+}
+
+namespace {
+ static sal_Int32 getCurrentListIndex( IFieldmark* pBM,
+ ::rtl::OUString* io_pCurrentText = NULL )
+ {
+ const IFieldmark::parameter_map_t* const pParameters = pBM->GetParameters();
+ sal_Int32 nCurrentIdx = 0;
+ const IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_RESULT)));
+ if(pResult != pParameters->end())
+ pResult->second >>= nCurrentIdx;
+ if(io_pCurrentText)
+ {
+ const IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_LISTENTRY)));
+ if(pListEntries != pParameters->end())
+ {
+ uno::Sequence< ::rtl::OUString > vListEntries;
+ pListEntries->second >>= vListEntries;
+ if(nCurrentIdx < vListEntries.getLength())
+ *io_pCurrentText = vListEntries[nCurrentIdx];
+ }
+ }
+ return nCurrentIdx;
+ }
+}
+
+//FIXME Fieldbk
+void SwFieldFormPortion::Paint( const SwTxtPaintInfo& rInf ) const
+{
+ SwTxtNode* pNd = const_cast<SwTxtNode*>(rInf.GetTxtFrm()->GetTxtNode());
+ const SwDoc *doc=pNd->GetDoc();
+ SwIndex aIndex( pNd, rInf.GetIdx() );
+ SwPosition aPosition(*pNd, aIndex);
+
+ IFieldmark* pBM = doc->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition );
+
+ OSL_ENSURE( pBM,
+ "SwFieldFormPortion::Paint(..)"
+ " - Where is my form field bookmark???");
+
+ if ( pBM != NULL )
+ {
+ if ( pBM->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) )
+ { // a checkbox...
+ ICheckboxFieldmark* pCheckboxFm = reinterpret_cast< ICheckboxFieldmark* >(pBM);
+ bool checked = pCheckboxFm->IsChecked();
+ rInf.DrawCheckBox(*this, checked);
+ }
+ else if ( pBM->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) )
+ { // a list...
+ rtl::OUString aTxt;
+ getCurrentListIndex( pBM, &aTxt );
+ rInf.DrawViewOpt( *this, POR_FLD );
+ rInf.DrawText( aTxt, *this, 0, aTxt.getLength(), false );
+ }
+ else
+ {
+ assert(0); // unknown type...
+ }
+ }
+}
+
+sal_Bool SwFieldFormPortion::Format( SwTxtFormatInfo & rInf )
+{
+ sal_Bool ret = 0;
+ SwTxtNode *pNd = const_cast < SwTxtNode * >( rInf.GetTxtFrm( )->GetTxtNode( ) );
+ const SwDoc *doc = pNd->GetDoc( );
+ SwIndex aIndex( pNd, rInf.GetIdx( ) );
+ SwPosition aPosition( *pNd, aIndex );
+ IFieldmark *pBM = doc->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition );
+ OSL_ENSURE( pBM != NULL, "Where is my form field bookmark???" );
+ if ( pBM != NULL )
+ {
+ if ( pBM->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) )
+ {
+ Width( rInf.GetTxtHeight( ) );
+ Height( rInf.GetTxtHeight( ) );
+ SetAscent( rInf.GetAscent( ) );
+ }
+ else if ( pBM->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) )
+ {
+ ::rtl::OUString aTxt;
+ getCurrentListIndex( pBM, &aTxt );
+ SwPosSize aPosSize = rInf.GetTxtSize( aTxt );
+ Width( aPosSize.Width( ) );
+ Height( aPosSize.Height( ) );
+ SetAscent( rInf.GetAscent( ) );
+ }
+ else
+ {
+ assert( 0 ); // unknown type...
+ }
+ }
+ return ret;
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */