1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: portxt.cxx,v $
10 * $Revision: 1.51.112.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
37 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
38 #include <com/sun/star/i18n/ScriptType.hdl>
40 #include <hintids.hxx> // CH_TXTATR
41 #include <errhdl.hxx> // ASSERT
42 #include <SwPortionHandler.hxx>
46 #include <guess.hxx> // SwTxtGuess, Zeilenumbruch
47 #include <porglue.hxx>
48 #include <portab.hxx> // pLastTab->
49 #include <porfld.hxx> // SwFldPortion
52 #include <IDocumentSettingAccess.hxx>
53 #include <viewopt.hxx> // SwViewOptions
58 #include <ecmaflds.hxx>
60 #if OSL_DEBUG_LEVEL > 1
61 const sal_Char
*GetLangName( const MSHORT nLang
);
64 using namespace ::sw::mark
;
65 using namespace ::com::sun::star
;
66 using namespace ::com::sun::star::i18n::ScriptType
;
68 /*************************************************************************
70 * Returns for how many characters an extra space has to be added
71 * (for justified alignment).
72 *************************************************************************/
74 USHORT
lcl_AddSpace( const SwTxtSizeInfo
&rInf
, const XubString
* pStr
,
75 const SwLinePortion
& rPor
)
77 xub_StrLen nPos
, nEnd
;
78 const SwScriptInfo
* pSI
= 0;
82 // passing a string means we are inside a field
89 nEnd
= rInf
.GetIdx() + rPor
.GetLen();
90 pStr
= &rInf
.GetTxt();
91 pSI
= &((SwParaPortion
*)rInf
.GetParaPortion())->GetScriptInfo();
97 // If portion consists of Asian characters and language is not
98 // Korean, we add extra space to each character.
99 // first we get the script type
101 nScript
= pSI
->ScriptType( nPos
);
102 else if ( pBreakIt
->GetBreakIter().is() )
103 nScript
= (BYTE
)pBreakIt
->GetBreakIter()->getScriptType( *pStr
, nPos
);
105 // Note: rInf.GetIdx() can differ from nPos,
106 // e.g., when rPor is a field portion. nPos referes to the string passed
107 // to the function, rInf.GetIdx() referes to the original string.
109 // We try to find out which justification mode is required. This is done by
110 // evaluating the script type and the language attribute set for this portion
112 // Asian Justification: Each character get some extra space
113 if ( nEnd
> nPos
&& ASIAN
== nScript
)
116 rInf
.GetTxtFrm()->GetTxtNode()->GetLang( rInf
.GetIdx(), 1, nScript
);
118 if ( LANGUAGE_KOREAN
!= aLang
&& LANGUAGE_KOREAN_JOHAB
!= aLang
)
120 const SwLinePortion
* pPor
= rPor
.GetPortion();
121 if ( pPor
&& ( pPor
->IsKernPortion() ||
122 pPor
->IsControlCharPortion() ||
123 pPor
->IsPostItsPortion() ) )
124 pPor
= pPor
->GetPortion();
128 if ( !pPor
|| pPor
->IsHolePortion() || pPor
->InFixMargGrp() ||
129 pPor
->IsBreakPortion() )
136 // Kashida Justification: Insert Kashidas
137 if ( nEnd
> nPos
&& pSI
&& COMPLEX
== nScript
)
139 if ( SwScriptInfo::IsArabicText( *pStr
, nPos
, nEnd
- nPos
) && pSI
->CountKashida() )
141 const USHORT nKashRes
= pSI
->KashidaJustify( 0, 0, nPos
, nEnd
- nPos
);
142 // i60591: need to check result of KashidaJustify
143 // determine if kashida justification is applicable
144 if( nKashRes
!= STRING_LEN
)
149 // Thai Justification: Each character cell gets some extra space
150 if ( nEnd
> nPos
&& COMPLEX
== nScript
)
153 rInf
.GetTxtFrm()->GetTxtNode()->GetLang( rInf
.GetIdx(), 1, nScript
);
155 if ( LANGUAGE_THAI
== aLang
)
157 nCnt
= SwScriptInfo::ThaiJustify( *pStr
, 0, 0, nPos
, nEnd
- nPos
);
159 const SwLinePortion
* pPor
= rPor
.GetPortion();
160 if ( pPor
&& ( pPor
->IsKernPortion() ||
161 pPor
->IsControlCharPortion() ||
162 pPor
->IsPostItsPortion() ) )
163 pPor
= pPor
->GetPortion();
165 if ( nCnt
&& ( ! pPor
|| pPor
->IsHolePortion() || pPor
->InFixMargGrp() ) )
172 // Here starts the good old "Look for blanks and add space to them" part.
173 // Note: We do not want to add space to an isolated latin blank in front
174 // of some complex characters in RTL environment
175 const sal_Bool bDoNotAddSpace
=
176 LATIN
== nScript
&& ( nEnd
== nPos
+ 1 ) && pSI
&&
177 ( i18n::ScriptType::COMPLEX
==
178 pSI
->ScriptType( nPos
+ 1 ) ) &&
179 rInf
.GetTxtFrm() && rInf
.GetTxtFrm()->IsRightToLeft();
181 if ( bDoNotAddSpace
)
184 for ( ; nPos
< nEnd
; ++nPos
)
186 if( CH_BLANK
== pStr
->GetChar( nPos
) )
190 // We still have to examine the next character:
191 // If the next character is ASIAN and not KOREAN we have
192 // to add an extra space
193 // nPos referes to the original string, even if a field string has
194 // been passed to this function
195 nPos
= rInf
.GetIdx() + rPor
.GetLen();
196 if ( nPos
< rInf
.GetTxt().Len() )
198 BYTE nNextScript
= 0;
199 const SwLinePortion
* pPor
= rPor
.GetPortion();
200 if ( pPor
&& pPor
->IsKernPortion() )
201 pPor
= pPor
->GetPortion();
203 if ( ! pBreakIt
->GetBreakIter().is() || ! pPor
|| pPor
->InFixMargGrp() )
206 // next character is inside a field?
207 if ( CH_TXTATR_BREAKWORD
== rInf
.GetChar( nPos
) && pPor
->InExpGrp() )
209 sal_Bool bOldOnWin
= rInf
.OnWin();
210 ((SwTxtSizeInfo
&)rInf
).SetOnWin( sal_False
);
212 XubString
aStr( aEmptyStr
);
213 pPor
->GetExpTxt( rInf
, aStr
);
214 ((SwTxtSizeInfo
&)rInf
).SetOnWin( bOldOnWin
);
216 nNextScript
= (BYTE
)pBreakIt
->GetBreakIter()->getScriptType( aStr
, 0 );
219 nNextScript
= (BYTE
)pBreakIt
->GetBreakIter()->getScriptType( rInf
.GetTxt(), nPos
);
221 if( ASIAN
== nNextScript
)
224 rInf
.GetTxtFrm()->GetTxtNode()->GetLang( nPos
, 1, nNextScript
);
226 if ( LANGUAGE_KOREAN
!= aLang
&& LANGUAGE_KOREAN_JOHAB
!= aLang
)
234 /*************************************************************************
236 *************************************************************************/
238 SwTxtPortion::SwTxtPortion( const SwLinePortion
&rPortion
)
239 : SwLinePortion( rPortion
)
241 SetWhichPor( POR_TXT
);
244 /*************************************************************************
245 * SwTxtPortion::BreakCut()
246 *************************************************************************/
248 void SwTxtPortion::BreakCut( SwTxtFormatInfo
&rInf
, const SwTxtGuess
&rGuess
)
250 // Das Wort/Zeichen ist groesser als die Zeile
251 // Sonderfall Nr.1: Das Wort ist groesser als die Zeile
253 const KSHORT nLineWidth
= (KSHORT
)(rInf
.Width() - rInf
.X());
254 xub_StrLen nLen
= rGuess
.CutPos() - rInf
.GetIdx();
257 // special case: guess does not always provide the correct
258 // width, only in common cases.
259 if ( !rGuess
.BreakWidth() )
265 // changing these values requires also changing them in
268 if( ITALIC_NONE
!= rInf
.GetFont()->GetItalic() && !rInf
.NotEOL() )
270 nItalic
= Height() / 12;
272 Width( Width() + nItalic
);
276 Width( rGuess
.BreakWidth() );
280 // special case: first character does not fit to line
281 else if ( rGuess
.CutPos() == rInf
.GetLineStart() )
293 /*************************************************************************
294 * SwTxtPortion::BreakUnderflow()
295 *************************************************************************/
297 void SwTxtPortion::BreakUnderflow( SwTxtFormatInfo
&rInf
)
304 rInf
.SetUnderFlow( this );
307 /*************************************************************************
308 * SwTxtPortion::_Format()
309 *************************************************************************/
311 sal_Bool
lcl_HasContent( const SwFldPortion
& rFld
, SwTxtFormatInfo
&rInf
)
314 return rFld
.GetExpTxt( rInf
, aTxt
) && aTxt
.Len();
317 sal_Bool
SwTxtPortion::_Format( SwTxtFormatInfo
&rInf
)
319 // 5744: wenn nur der Trennstrich nicht mehr passt,
320 // muss trotzdem das Wort umgebrochen werden, ansonsten return sal_True!
321 if( rInf
.IsUnderFlow() && rInf
.GetSoftHyphPos() )
323 // soft hyphen portion has triggered an underflow event because
324 // of an alternative spelling position
325 sal_Bool bFull
= sal_False
;
326 const sal_Bool bHyph
= rInf
.ChgHyph( sal_True
);
327 if( rInf
.IsHyphenate() )
330 // check for alternative spelling left from the soft hyphen
331 // this should usually be true but
332 aGuess
.AlternativeSpelling( rInf
, rInf
.GetSoftHyphPos() - 1 );
333 bFull
= CreateHyphen( rInf
, aGuess
);
334 ASSERT( bFull
, "Problem with hyphenation!!!" );
336 rInf
.ChgHyph( bHyph
);
337 rInf
.SetSoftHyphPos( 0 );
342 const sal_Bool bFull
= !aGuess
.Guess( *this, rInf
, Height() );
344 // these are the possible cases:
345 // A Portion fits to current line
346 // B Portion does not fit to current line but a possible line break
347 // within the portion has been found by the break iterator, 2 subcases
348 // B1 break is hyphen
349 // B2 break is word end
350 // C Portion does not fit to current line and no possible line break
351 // has been found by break iterator, 2 subcases:
352 // C1 break iterator found a possible line break in portion before us
353 // ==> this break is used (underflow)
354 // C2 break iterator does not found a possible line break at all:
357 // case A: line not yet full
360 Width( aGuess
.BreakWidth() );
362 if( !InExpGrp() || InFldGrp() )
363 SetLen( rInf
.GetLen() );
365 short nKern
= rInf
.GetFont()->CheckKerning();
366 if( nKern
> 0 && rInf
.Width() < rInf
.X() + Width() + nKern
)
368 nKern
= (short)(rInf
.Width() - rInf
.X() - Width() - 1);
373 new SwKernPortion( *this, nKern
);
375 // special case: hanging portion
376 else if( bFull
&& aGuess
.GetHangingPortion() )
378 Width( aGuess
.BreakWidth() );
379 SetLen( aGuess
.BreakPos() - rInf
.GetIdx() );
380 Insert( aGuess
.GetHangingPortion() );
381 aGuess
.GetHangingPortion()->SetAscent( GetAscent() );
382 aGuess
.ClearHangingPortion();
385 else if ( aGuess
.BreakPos() >= rInf
.GetIdx() && aGuess
.BreakPos() != STRING_LEN
)
388 if( aGuess
.HyphWord().is() && aGuess
.BreakPos() > rInf
.GetLineStart()
389 && ( aGuess
.BreakPos() > rInf
.GetIdx() ||
390 ( rInf
.GetLast() && ! rInf
.GetLast()->IsFlyPortion() ) ) )
392 CreateHyphen( rInf
, aGuess
);
394 rInf
.GetRoot()->SetMidHyph( sal_True
);
396 rInf
.GetRoot()->SetEndHyph( sal_True
);
399 // - Footnote portions with fake line start (i.e., not at beginning of line)
400 // should keep together with the text portion.
401 // - TabPortions not at beginning of line should keep together with the
402 // text portion, if they are not followed by a blank
403 // (work around different definition of tab stop character - breaking or
404 // non breaking character - in compatibility mode)
405 else if ( ( IsFtnPortion() && rInf
.IsFakeLineStart() ) ||
407 rInf
.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT
) &&
408 rInf
.GetLast()->InTabGrp() &&
409 rInf
.GetLineStart() + rInf
.GetLast()->GetLen() < rInf
.GetIdx() &&
410 aGuess
.BreakPos() == rInf
.GetIdx() &&
411 CH_BLANK
!= rInf
.GetChar( rInf
.GetIdx() ) &&
412 0x3000 != rInf
.GetChar( rInf
.GetIdx() ) ) )
413 BreakUnderflow( rInf
);
415 else if( rInf
.GetIdx() > rInf
.GetLineStart() ||
416 aGuess
.BreakPos() > rInf
.GetIdx() ||
417 // this is weird: during formatting the follow of a field
418 // the values rInf.GetIdx and rInf.GetLineStart are replaced
419 // IsFakeLineStart indicates GetIdx > GetLineStart
420 rInf
.IsFakeLineStart() ||
422 rInf
.IsFirstMulti() ||
424 ( rInf
.GetLast()->IsFlyPortion() ||
425 ( rInf
.GetLast()->InFldGrp() &&
426 ! rInf
.GetLast()->InNumberGrp() &&
427 ! rInf
.GetLast()->IsErgoSumPortion() &&
428 lcl_HasContent(*((SwFldPortion
*)rInf
.GetLast()),rInf
) ) ) ) )
430 if ( rInf
.X() + aGuess
.BreakWidth() <= rInf
.Width() )
431 Width( aGuess
.BreakWidth() );
433 // this actually should not happen
434 Width( KSHORT(rInf
.Width() - rInf
.X()) );
436 SetLen( aGuess
.BreakPos() - rInf
.GetIdx() );
438 ASSERT( aGuess
.BreakStart() >= aGuess
.FieldDiff(),
439 "Trouble with expanded field portions during line break" );
440 const xub_StrLen nRealStart
= aGuess
.BreakStart() - aGuess
.FieldDiff();
441 if( aGuess
.BreakPos() < nRealStart
&& !InExpGrp() )
443 SwHolePortion
*pNew
= new SwHolePortion( *this );
444 pNew
->SetLen( nRealStart
- aGuess
.BreakPos() );
448 else // case C2, last exit
449 BreakCut( rInf
, aGuess
);
451 // breakPos < index or no breakpos at all
454 sal_Bool bFirstPor
= rInf
.GetLineStart() == rInf
.GetIdx();
455 if( aGuess
.BreakPos() != STRING_LEN
&&
456 aGuess
.BreakPos() != rInf
.GetLineStart() &&
457 ( !bFirstPor
|| rInf
.GetFly() || rInf
.GetLast()->IsFlyPortion() ||
458 rInf
.IsFirstMulti() ) &&
459 ( !rInf
.GetLast()->IsBlankPortion() || ((SwBlankPortion
*)
460 rInf
.GetLast())->MayUnderFlow( rInf
, rInf
.GetIdx()-1, sal_True
)))
461 { // case C1 (former BreakUnderflow())
462 BreakUnderflow( rInf
);
465 // case C2, last exit
466 BreakCut( rInf
, aGuess
);
472 /*************************************************************************
473 * virtual SwTxtPortion::Format()
474 *************************************************************************/
478 sal_Bool
SwTxtPortion::Format( SwTxtFormatInfo
&rInf
)
480 #if OSL_DEBUG_LEVEL > 1
481 const XubString
aDbgTxt( rInf
.GetTxt().Copy( rInf
.GetIdx(), rInf
.GetLen() ) );
484 if( rInf
.X() > rInf
.Width() || (!GetLen() && !InExpGrp()) )
490 SetPortion( NULL
); // ????
494 ASSERT( rInf
.RealWidth() || (rInf
.X() == rInf
.Width()),
495 "SwTxtPortion::Format: missing real width" );
496 ASSERT( Height(), "SwTxtPortion::Format: missing height" );
498 return _Format( rInf
);
501 /*************************************************************************
502 * virtual SwTxtPortion::FormatEOL()
503 *************************************************************************/
505 // Format end of line
506 // 5083: Es kann schon manchmal unguenstige Faelle geben...
507 // "vom {Nikolaus}", Nikolaus bricht um "vom " wird im Blocksatz
508 // zu "vom" und " ", wobei der Glue expandiert wird, statt in die
509 // MarginPortion aufzugehen.
510 // rInf.nIdx steht auf dem naechsten Wort, nIdx-1 ist der letzte
511 // Buchstabe der Portion.
515 void SwTxtPortion::FormatEOL( SwTxtFormatInfo
&rInf
)
517 if( ( !GetPortion() || ( GetPortion()->IsKernPortion() &&
518 !GetPortion()->GetPortion() ) ) && GetLen() &&
519 rInf
.GetIdx() < rInf
.GetTxt().Len() &&
520 1 < rInf
.GetIdx() && ' ' == rInf
.GetChar( rInf
.GetIdx() - 1 )
521 && !rInf
.GetLast()->IsHolePortion() )
523 // calculate number of blanks
524 xub_StrLen nX
= rInf
.GetIdx() - 1;
526 while( nX
&& nHoleLen
< GetLen() && CH_BLANK
== rInf
.GetChar( --nX
) )
529 // Erst uns einstellen und dann Inserten, weil wir ja auch ein
530 // SwLineLayout sein koennten.
532 if( nHoleLen
== GetLen() )
533 nBlankSize
= Width();
535 nBlankSize
= nHoleLen
* rInf
.GetTxtSize( ' ' ).Width();
536 Width( Width() - nBlankSize
);
537 rInf
.X( rInf
.X() - nBlankSize
);
538 SetLen( GetLen() - nHoleLen
);
539 SwLinePortion
*pHole
= new SwHolePortion( *this );
540 ( (SwHolePortion
*)pHole
)->SetBlankWidth( nBlankSize
);
541 ( (SwHolePortion
*)pHole
)->SetLen( nHoleLen
);
546 /*************************************************************************
547 * virtual SwTxtPortion::GetCrsrOfst()
548 *************************************************************************/
552 xub_StrLen
SwTxtPortion::GetCrsrOfst( const KSHORT nOfst
) const
554 ASSERT( !this, "SwTxtPortion::GetCrsrOfst: don't use this method!" );
555 return SwLinePortion::GetCrsrOfst( nOfst
);
558 /*************************************************************************
559 * virtual SwTxtPortion::GetTxtSize()
560 *************************************************************************/
561 // Das GetTxtSize() geht davon aus, dass die eigene Laenge korrekt ist
563 SwPosSize
SwTxtPortion::GetTxtSize( const SwTxtSizeInfo
&rInf
) const
565 return rInf
.GetTxtSize();
568 /*************************************************************************
569 * virtual SwTxtPortion::Paint()
570 *************************************************************************/
574 void SwTxtPortion::Paint( const SwTxtPaintInfo
&rInf
) const
576 if (rInf
.OnWin() && 1==rInf
.GetLen() && CH_TXT_ATR_FIELDEND
==rInf
.GetTxt().GetChar(rInf
.GetIdx()))
578 rInf
.DrawBackBrush( *this );
579 const XubString aTxt
= XubString::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDEND
);
580 rInf
.DrawText( aTxt
, *this, 0, aTxt
.Len(), false );
582 else if (rInf
.OnWin() && 1==rInf
.GetLen() && CH_TXT_ATR_FIELDSTART
==rInf
.GetTxt().GetChar(rInf
.GetIdx()))
584 rInf
.DrawBackBrush( *this );
585 const XubString aTxt
= XubString::CreateFromAscii(CH_TXT_ATR_SUBST_FIELDSTART
);
586 rInf
.DrawText( aTxt
, *this, 0, aTxt
.Len(), false );
590 rInf
.DrawBackBrush( *this );
592 // do we have to repaint a post it portion?
593 if( rInf
.OnWin() && pPortion
&& !pPortion
->Width() )
594 pPortion
->PrePaint( rInf
, this );
596 const SwWrongList
*pWrongList
= rInf
.GetpWrongList();
597 const SwWrongList
*pGrammarCheckList
= rInf
.GetGrammarCheckList();
599 const SwWrongList
*pSmarttags
= rInf
.GetSmartTags();
601 const bool bWrong
= 0 != pWrongList
;
602 const bool bGrammarCheck
= 0 != pGrammarCheckList
;
603 const bool bSmartTags
= 0 != pSmarttags
;
605 if ( bWrong
|| bSmartTags
|| bGrammarCheck
)
606 rInf
.DrawMarkedText( *this, rInf
.GetLen(), sal_False
, bWrong
, bSmartTags
, bGrammarCheck
);
608 rInf
.DrawText( *this, rInf
.GetLen(), sal_False
);
612 /*************************************************************************
613 * virtual SwTxtPortion::GetExpTxt()
614 *************************************************************************/
618 sal_Bool
SwTxtPortion::GetExpTxt( const SwTxtSizeInfo
&, XubString
& ) const
623 /*************************************************************************
624 * xub_StrLen SwTxtPortion::GetSpaceCnt()
625 * long SwTxtPortion::CalcSpacing()
626 * sind fuer den Blocksatz zustaendig und ermitteln die Anzahl der Blanks
627 * und den daraus resultierenden zusaetzlichen Zwischenraum
628 *************************************************************************/
630 xub_StrLen
SwTxtPortion::GetSpaceCnt( const SwTxtSizeInfo
&rInf
,
631 xub_StrLen
& rCharCnt
) const
637 if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
639 // Bei OnWin() wird anstatt eines Leerstrings gern mal ein Blank
640 // zurueckgeliefert, das koennen wir hier aber gar nicht gebrauchen
641 sal_Bool bOldOnWin
= rInf
.OnWin();
642 ((SwTxtSizeInfo
&)rInf
).SetOnWin( sal_False
);
644 XubString
aStr( aEmptyStr
);
645 GetExpTxt( rInf
, aStr
);
646 ((SwTxtSizeInfo
&)rInf
).SetOnWin( bOldOnWin
);
648 nCnt
= nCnt
+ lcl_AddSpace( rInf
, &aStr
, *this );
652 else if( !IsDropPortion() )
654 nCnt
= nCnt
+ lcl_AddSpace( rInf
, 0, *this );
657 rCharCnt
= rCharCnt
+ nPos
;
661 long SwTxtPortion::CalcSpacing( long nSpaceAdd
, const SwTxtSizeInfo
&rInf
) const
667 if( !IsBlankPortion() && !InNumberGrp() && !IsCombinedPortion() )
669 // Bei OnWin() wird anstatt eines Leerstrings gern mal ein Blank
670 // zurueckgeliefert, das koennen wir hier aber gar nicht gebrauchen
671 sal_Bool bOldOnWin
= rInf
.OnWin();
672 ((SwTxtSizeInfo
&)rInf
).SetOnWin( sal_False
);
674 XubString
aStr( aEmptyStr
);
675 GetExpTxt( rInf
, aStr
);
676 ((SwTxtSizeInfo
&)rInf
).SetOnWin( bOldOnWin
);
678 nCnt
= nCnt
+ lcl_AddSpace( rInf
, &aStr
, *this );
681 nSpaceAdd
= -nSpaceAdd
;
686 else if( !IsDropPortion() )
689 nCnt
= nCnt
+ lcl_AddSpace( rInf
, 0, *this );
692 nSpaceAdd
= -nSpaceAdd
;
694 SwLinePortion
* pPor
= GetPortion();
696 // we do not want an extra space in front of margin portions
699 while ( pPor
&& !pPor
->Width() && ! pPor
->IsHolePortion() )
700 pPor
= pPor
->GetPortion();
702 if ( !pPor
|| pPor
->InFixMargGrp() || pPor
->IsHolePortion() )
708 return nCnt
* nSpaceAdd
/ SPACING_PRECISION_FACTOR
;
711 /*************************************************************************
712 * virtual SwTxtPortion::HandlePortion()
713 *************************************************************************/
715 void SwTxtPortion::HandlePortion( SwPortionHandler
& rPH
) const
717 rPH
.Text( GetLen(), GetWhichPor() );
720 /*************************************************************************
721 * class SwHolePortion
722 *************************************************************************/
726 SwHolePortion::SwHolePortion( const SwTxtPortion
&rPor
)
730 Height( rPor
.Height() );
731 SetAscent( rPor
.GetAscent() );
732 SetWhichPor( POR_HOLE
);
735 SwLinePortion
*SwHolePortion::Compress() { return this; }
737 /*************************************************************************
738 * virtual SwHolePortion::Paint()
739 *************************************************************************/
743 void SwHolePortion::Paint( const SwTxtPaintInfo
&rInf
) const
745 // --> FME 2004-06-24 #i16816# tagged pdf support
746 if( rInf
.GetVsh() && rInf
.GetVsh()->GetViewOptions()->IsPDFExport() )
748 const XubString
aTxt( ' ' );
749 rInf
.DrawText( aTxt
, *this, 0, 1, false );
754 /*************************************************************************
755 * virtual SwHolePortion::Format()
756 *************************************************************************/
760 sal_Bool
SwHolePortion::Format( SwTxtFormatInfo
&rInf
)
762 return rInf
.IsFull() || rInf
.X() >= rInf
.Width();
765 /*************************************************************************
766 * virtual SwHolePortion::HandlePortion()
767 *************************************************************************/
769 void SwHolePortion::HandlePortion( SwPortionHandler
& rPH
) const
771 rPH
.Text( GetLen(), GetWhichPor() );
774 void SwFieldMarkPortion::Paint( const SwTxtPaintInfo
& /*rInf*/) const
776 // These shouldn't be painted!
777 // SwTxtPortion::Paint(rInf);
780 sal_Bool
SwFieldMarkPortion::Format( SwTxtFormatInfo
& )
788 static int getCurrentListIndex( IFieldmark
* pBM
,
789 ::rtl::OUString
*currentText
= NULL
)
791 int currentIndex
= pBM
->getParam( ECMA_FORMDROPDOWN_RESULT
, "0" ).second
.toInt32();
793 for( int i
= 0; i
< pBM
->getNumOfParams(); i
++ )
795 IFieldmark::ParamPair_t p
= pBM
->getParam( i
);
796 if ( p
.first
.compareToAscii( ECMA_FORMDROPDOWN_LISTENTRY
) == 0 )
798 if ( idx
== currentIndex
)
800 if ( currentText
!=NULL
) *currentText
=p
.second
;
812 void SwFieldFormPortion::Paint( const SwTxtPaintInfo
& rInf
) const
814 SwTxtNode
* pNd
= const_cast<SwTxtNode
*>(rInf
.GetTxtFrm()->GetTxtNode());
815 const SwDoc
*doc
=pNd
->GetDoc();
816 SwIndex
aIndex( pNd
, rInf
.GetIdx() );
817 SwPosition
aPosition(*pNd
, aIndex
);
819 IFieldmark
* pBM
= doc
->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition
);
822 "SwFieldFormPortion::Paint(..)"
823 " - Where is my form field bookmark???");
827 if ( pBM
->GetFieldname( ).equalsAscii( ECMA_FORMCHECKBOX
) )
829 bool checked
= pBM
->getParam( ECMA_FORMCHECKBOX_CHECKED
).second
.compareToAscii("on") == 0;
830 rInf
.DrawCheckBox( *this , checked
);
832 else if ( pBM
->GetFieldname( ).equalsAscii( ECMA_FORMDROPDOWN
) )
835 rInf
.DrawViewOpt( *this, POR_FLD
);
836 rInf
.DrawText( aTxt
, *this, 0, aTxt
.getLength(), false );
840 assert(0); // unknown type...
845 sal_Bool
SwFieldFormPortion::Format( SwTxtFormatInfo
& rInf
)
848 SwTxtNode
*pNd
= const_cast < SwTxtNode
* >( rInf
.GetTxtFrm( )->GetTxtNode( ) );
849 const SwDoc
*doc
= pNd
->GetDoc( );
850 SwIndex
aIndex( pNd
, rInf
.GetIdx( ) );
851 SwPosition
aPosition( *pNd
, aIndex
);
852 IFieldmark
*pBM
= doc
->getIDocumentMarkAccess( )->getFieldmarkFor( aPosition
);
853 ASSERT( pBM
!= NULL
, "Where is my form field bookmark???" );
856 if ( pBM
->GetFieldname( ).equalsAscii( ECMA_FORMCHECKBOX
) )
858 Width( rInf
.GetTxtHeight( ) );
859 Height( rInf
.GetTxtHeight( ) );
860 SetAscent( rInf
.GetAscent( ) );
862 else if ( pBM
->GetFieldname( ).equalsAscii( ECMA_FORMDROPDOWN
) )
864 ::rtl::OUString aTxt
;
865 ecma::getCurrentListIndex( pBM
, &aTxt
);
866 SwPosSize aPosSize
= rInf
.GetTxtSize( aTxt
);
867 Width( aPosSize
.Width( ) );
868 Height( aPosSize
.Height( ) );
869 SetAscent( rInf
.GetAscent( ) );
873 assert( 0 ); // unknown type...