update dev300-m58
[ooovba.git] / sw / source / core / text / portxt.cxx
blob9b24e31381a715e06010d7b9a3cf8dbdd3547cf2
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"
35 #include <ctype.h>
37 #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
38 #include <com/sun/star/i18n/ScriptType.hdl>
39 #endif
40 #include <hintids.hxx> // CH_TXTATR
41 #include <errhdl.hxx> // ASSERT
42 #include <SwPortionHandler.hxx>
43 #include <txtcfg.hxx>
44 #include <porlay.hxx>
45 #include <inftxt.hxx>
46 #include <guess.hxx> // SwTxtGuess, Zeilenumbruch
47 #include <porglue.hxx>
48 #include <portab.hxx> // pLastTab->
49 #include <porfld.hxx> // SwFldPortion
50 #include <wrong.hxx>
51 #include <viewsh.hxx>
52 #include <IDocumentSettingAccess.hxx>
53 #include <viewopt.hxx> // SwViewOptions
55 #include <IMark.hxx>
56 #include <pam.hxx>
57 #include <doc.hxx>
58 #include <ecmaflds.hxx>
60 #if OSL_DEBUG_LEVEL > 1
61 const sal_Char *GetLangName( const MSHORT nLang );
62 #endif
64 using namespace ::sw::mark;
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::i18n::ScriptType;
68 /*************************************************************************
69 * lcl_AddSpace
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;
80 if ( pStr )
82 // passing a string means we are inside a field
83 nPos = 0;
84 nEnd = pStr->Len();
86 else
88 nPos = rInf.GetIdx();
89 nEnd = rInf.GetIdx() + rPor.GetLen();
90 pStr = &rInf.GetTxt();
91 pSI = &((SwParaPortion*)rInf.GetParaPortion())->GetScriptInfo();
94 USHORT nCnt = 0;
95 BYTE nScript = 0;
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
100 if ( pSI )
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 )
115 LanguageType aLang =
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();
126 nCnt += nEnd - nPos;
128 if ( !pPor || pPor->IsHolePortion() || pPor->InFixMargGrp() ||
129 pPor->IsBreakPortion() )
130 --nCnt;
132 return nCnt;
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 )
145 return nKashRes;
149 // Thai Justification: Each character cell gets some extra space
150 if ( nEnd > nPos && COMPLEX == nScript )
152 LanguageType aLang =
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() ) )
166 --nCnt;
168 return nCnt;
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 )
182 return nCnt;
184 for ( ; nPos < nEnd; ++nPos )
186 if( CH_BLANK == pStr->GetChar( nPos ) )
187 ++nCnt;
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() )
204 return nCnt;
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 );
218 else
219 nNextScript = (BYTE)pBreakIt->GetBreakIter()->getScriptType( rInf.GetTxt(), nPos );
221 if( ASIAN == nNextScript )
223 LanguageType aLang =
224 rInf.GetTxtFrm()->GetTxtNode()->GetLang( nPos, 1, nNextScript );
226 if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
227 ++nCnt;
231 return nCnt;
234 /*************************************************************************
235 * class SwTxtPortion
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
252 // Wir kappen...
253 const KSHORT nLineWidth = (KSHORT)(rInf.Width() - rInf.X());
254 xub_StrLen nLen = rGuess.CutPos() - rInf.GetIdx();
255 if( nLen )
257 // special case: guess does not always provide the correct
258 // width, only in common cases.
259 if ( !rGuess.BreakWidth() )
261 rInf.SetLen( nLen );
262 SetLen( nLen );
263 CalcTxtSize( rInf );
265 // changing these values requires also changing them in
266 // guess.cxx
267 KSHORT nItalic = 0;
268 if( ITALIC_NONE != rInf.GetFont()->GetItalic() && !rInf.NotEOL() )
270 nItalic = Height() / 12;
272 Width( Width() + nItalic );
274 else
276 Width( rGuess.BreakWidth() );
277 SetLen( nLen );
280 // special case: first character does not fit to line
281 else if ( rGuess.CutPos() == rInf.GetLineStart() )
283 SetLen( 1 );
284 Width( nLineWidth );
286 else
288 SetLen( 0 );
289 Width( 0 );
293 /*************************************************************************
294 * SwTxtPortion::BreakUnderflow()
295 *************************************************************************/
297 void SwTxtPortion::BreakUnderflow( SwTxtFormatInfo &rInf )
299 Truncate();
300 Height( 0 );
301 Width( 0 );
302 SetLen( 0 );
303 SetAscent( 0 );
304 rInf.SetUnderFlow( this );
307 /*************************************************************************
308 * SwTxtPortion::_Format()
309 *************************************************************************/
311 sal_Bool lcl_HasContent( const SwFldPortion& rFld, SwTxtFormatInfo &rInf )
313 String aTxt;
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() )
329 SwTxtGuess aGuess;
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 );
338 return bFull;
341 SwTxtGuess aGuess;
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:
355 // ==> line break
357 // case A: line not yet full
358 if ( !bFull )
360 Width( aGuess.BreakWidth() );
361 // Vorsicht !
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);
369 if( nKern < 0 )
370 nKern = 0;
372 if( nKern )
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();
384 // breakPos >= index
385 else if ( aGuess.BreakPos() >= rInf.GetIdx() && aGuess.BreakPos() != STRING_LEN )
387 // case B1
388 if( aGuess.HyphWord().is() && aGuess.BreakPos() > rInf.GetLineStart()
389 && ( aGuess.BreakPos() > rInf.GetIdx() ||
390 ( rInf.GetLast() && ! rInf.GetLast()->IsFlyPortion() ) ) )
392 CreateHyphen( rInf, aGuess );
393 if ( rInf.GetFly() )
394 rInf.GetRoot()->SetMidHyph( sal_True );
395 else
396 rInf.GetRoot()->SetEndHyph( sal_True );
398 // case C1
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() ) ||
406 ( rInf.GetLast() &&
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 );
414 // case B2
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() ||
421 rInf.GetFly() ||
422 rInf.IsFirstMulti() ||
423 ( rInf.GetLast() &&
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() );
432 else
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() );
445 Insert( pNew );
448 else // case C2, last exit
449 BreakCut( rInf, aGuess );
451 // breakPos < index or no breakpos at all
452 else
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 );
464 else
465 // case C2, last exit
466 BreakCut( rInf, aGuess );
469 return bFull;
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() ) );
482 #endif
484 if( rInf.X() > rInf.Width() || (!GetLen() && !InExpGrp()) )
486 Height( 0 );
487 Width( 0 );
488 SetLen( 0 );
489 SetAscent( 0 );
490 SetPortion( NULL ); // ????
491 return sal_True;
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;
525 USHORT nHoleLen = 1;
526 while( nX && nHoleLen < GetLen() && CH_BLANK == rInf.GetChar( --nX ) )
527 nHoleLen++;
529 // Erst uns einstellen und dann Inserten, weil wir ja auch ein
530 // SwLineLayout sein koennten.
531 KSHORT nBlankSize;
532 if( nHoleLen == GetLen() )
533 nBlankSize = Width();
534 else
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 );
542 Insert( pHole );
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 );
588 else if( GetLen() )
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();
598 // SMARTTAGS
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 );
607 else
608 rInf.DrawText( *this, rInf.GetLen(), sal_False );
612 /*************************************************************************
613 * virtual SwTxtPortion::GetExpTxt()
614 *************************************************************************/
618 sal_Bool SwTxtPortion::GetExpTxt( const SwTxtSizeInfo &, XubString & ) const
620 return sal_False;
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
633 xub_StrLen nCnt = 0;
634 xub_StrLen nPos = 0;
635 if ( InExpGrp() )
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 );
649 nPos = aStr.Len();
652 else if( !IsDropPortion() )
654 nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
655 nPos = GetLen();
657 rCharCnt = rCharCnt + nPos;
658 return nCnt;
661 long SwTxtPortion::CalcSpacing( long nSpaceAdd, const SwTxtSizeInfo &rInf ) const
663 xub_StrLen nCnt = 0;
665 if ( InExpGrp() )
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 );
677 if( nSpaceAdd > 0 )
678 nCnt = nCnt + lcl_AddSpace( rInf, &aStr, *this );
679 else
681 nSpaceAdd = -nSpaceAdd;
682 nCnt = aStr.Len();
686 else if( !IsDropPortion() )
688 if( nSpaceAdd > 0 )
689 nCnt = nCnt + lcl_AddSpace( rInf, 0, *this );
690 else
692 nSpaceAdd = -nSpaceAdd;
693 nCnt = GetLen();
694 SwLinePortion* pPor = GetPortion();
696 // we do not want an extra space in front of margin portions
697 if ( nCnt )
699 while ( pPor && !pPor->Width() && ! pPor->IsHolePortion() )
700 pPor = pPor->GetPortion();
702 if ( !pPor || pPor->InFixMargGrp() || pPor->IsHolePortion() )
703 --nCnt;
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 )
727 : nBlankWidth( 0 )
729 SetLen( 1 );
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 );
751 // <--
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 & )
782 sal_Bool ret=0;
783 Width(0);
784 return ret;
787 namespace ecma {
788 static int getCurrentListIndex( IFieldmark* pBM,
789 ::rtl::OUString *currentText = NULL )
791 int currentIndex = pBM->getParam( ECMA_FORMDROPDOWN_RESULT, "0" ).second.toInt32();
792 int idx = 0;
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;
801 break;
803 else
804 idx++;
807 return idx;
809 } /* ecma */
811 //FIXME Fieldbk
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 );
821 OSL_ENSURE( pBM,
822 "SwFieldFormPortion::Paint(..)"
823 " - Where is my form field bookmark???");
825 if ( pBM != NULL )
827 if ( pBM->GetFieldname( ).equalsAscii( ECMA_FORMCHECKBOX ) )
828 { // a checkbox...
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 ) )
833 { // a list...
834 rtl::OUString aTxt;
835 rInf.DrawViewOpt( *this, POR_FLD );
836 rInf.DrawText( aTxt, *this, 0, aTxt.getLength(), false );
838 else
840 assert(0); // unknown type...
845 sal_Bool SwFieldFormPortion::Format( SwTxtFormatInfo & rInf )
847 sal_Bool ret = 0;
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???" );
854 if ( pBM != NULL )
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( ) );
871 else
873 assert( 0 ); // unknown type...
876 return ret;