1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include "hintids.hxx"
28 #include <editeng/lrspitem.hxx>
29 #ifndef _SVX_TSTPITEM_HXX //autogen
30 #include <editeng/tstpitem.hxx>
31 #endif
32 #include <IDocumentSettingAccess.hxx>
33 #include <frmatr.hxx>
34 #include <SwPortionHandler.hxx>
35
36 #include "viewopt.hxx" // SwViewOptions
37 #include "txtcfg.hxx"
38 #include "portab.hxx"
39 #include "inftxt.hxx"
40 #include "itrform2.hxx"
41 #include "txtfrm.hxx"
42 #include <numrule.hxx>
43 // --> OD 2008-06-05 #i89179#
44 #include <porfld.hxx>
45 // <--
46
47
48 /*************************************************************************
49 * SwLineInfo::GetTabStop()
50 *************************************************************************/
51
52 //#i24363# tab stops relative to indent
53 /* Return the first tab stop that is > nSearchPos.
54 * If the tab stop is outside the print area, we
55 * return 0 if it is not the first tab stop.*/
GetTabStop(const SwTwips nSearchPos,const SwTwips nRight) const56 const SvxTabStop *SwLineInfo::GetTabStop( const SwTwips nSearchPos,
57 const SwTwips nRight ) const
58 {
59 for( MSHORT i = 0; i < pRuler->Count(); ++i )
60 {
61 const SvxTabStop &rTabStop = pRuler->operator[](i);
62 if( rTabStop.GetTabPos() > SwTwips(nRight) )
63 return i ? 0 : &rTabStop;
64
65 if( rTabStop.GetTabPos() > nSearchPos )
66 return &rTabStop;
67 }
68 return 0;
69 }
70
71 /*************************************************************************
72 * SwLineInfo::NumberOfTabStops()
73 *************************************************************************/
74
NumberOfTabStops() const75 sal_uInt16 SwLineInfo::NumberOfTabStops() const
76 {
77 return pRuler->Count();
78 }
79
80 /*************************************************************************
81 * SwTxtFormatter::NewTabPortion()
82 *************************************************************************/
NewTabPortion(SwTxtFormatInfo & rInf,bool bAuto) const83 SwTabPortion *SwTxtFormatter::NewTabPortion( SwTxtFormatInfo &rInf, bool bAuto ) const
84 {
85 {
86 SwTabPortion *pLastTab = rInf.GetLastTab();
87 if( pLastTab && ( pLastTab->IsTabCntPortion() || pLastTab->IsTabDecimalPortion() ) )
88 if( pLastTab->PostFormat( rInf ) )
89 return 0;
90 }
91
92 xub_Unicode cFill = 0;
93 xub_Unicode cDec = 0;
94 SvxTabAdjust eAdj;
95
96 KSHORT nNewTabPos;
97 {
98 const bool bRTL = pFrm->IsRightToLeft();
99 // #i24363# tab stops relative to indent
100 // nTabLeft: The absolute value, the tab stops are relative to: Tabs origin.
101 //
102 // --> OD 2008-07-01 #i91133#
103 const bool bTabsRelativeToIndent =
104 pFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT);
105 const SwTwips nTabLeft = bRTL
106 ? pFrm->Frm().Right() -
107 ( bTabsRelativeToIndent ? GetTabLeft() : 0 )
108 : pFrm->Frm().Left() +
109 ( bTabsRelativeToIndent ? GetTabLeft() : 0 );
110 // <--
111
112 //
113 // nLinePos: The absolute position, where we started the line formatting.
114 //
115 SwTwips nLinePos = GetLeftMargin();
116 if ( bRTL )
117 {
118 Point aPoint( nLinePos, 0 );
119 pFrm->SwitchLTRtoRTL( aPoint );
120 nLinePos = aPoint.X();
121 }
122
123 //
124 // nTabPos: The current position, relative to the line start.
125 //
126 SwTwips nTabPos = rInf.GetLastTab() ? rInf.GetLastTab()->GetTabPos() : 0;
127 if( nTabPos < rInf.X() )
128 {
129 nTabPos = rInf.X();
130 }
131
132 //
133 // nCurrentAbsPos: The current position in absolute coordinates.
134 //
135 const SwTwips nCurrentAbsPos = bRTL ?
136 nLinePos - nTabPos :
137 nLinePos + nTabPos;
138
139 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
140 SwTwips nMyRight;
141 if ( pFrm->IsVertLR() )
142 nMyRight = Left();
143 else
144 nMyRight = Right();
145
146 if ( pFrm->IsVertical() )
147 {
148 Point aRightTop( nMyRight, pFrm->Frm().Top() );
149 pFrm->SwitchHorizontalToVertical( aRightTop );
150 nMyRight = aRightTop.Y();
151 }
152
153 SwTwips nNextPos = 0;
154
155 // #i24363# tab stops relative to indent
156 // nSearchPos: The current position relative to the tabs origin.
157 //
158 const SwTwips nSearchPos = bRTL ?
159 nTabLeft - nCurrentAbsPos :
160 nCurrentAbsPos - nTabLeft;
161
162 //
163 // First, we examine the tab stops set at the paragraph style or
164 // any hard set tab stops:
165 // Note: If there are no user defined tab stops, there is always a
166 // default tab stop.
167 //
168 const SvxTabStop* pTabStop = aLineInf.GetTabStop( nSearchPos, nMyRight );
169 if ( pTabStop )
170 {
171 cFill = ' ' != pTabStop->GetFill() ? pTabStop->GetFill() : 0;
172 cDec = pTabStop->GetDecimal();
173 eAdj = pTabStop->GetAdjustment();
174 nNextPos = pTabStop->GetTabPos();
175 if(!bTabsRelativeToIndent && eAdj == SVX_TAB_ADJUST_DEFAULT && nSearchPos < 0)
176 {
177 //calculate default tab position of default tabs in negative indent
178 nNextPos = ( nSearchPos / nNextPos ) * nNextPos;
179 }
180 }
181 else
182 {
183 KSHORT nDefTabDist = aLineInf.GetDefTabStop();
184 if( KSHRT_MAX == nDefTabDist )
185 {
186 const SvxTabStopItem& rTab =
187 (const SvxTabStopItem &)pFrm->GetAttrSet()->
188 GetPool()->GetDefaultItem( RES_PARATR_TABSTOP );
189 if( rTab.Count() )
190 nDefTabDist = (KSHORT)rTab.GetStart()->GetTabPos();
191 else
192 nDefTabDist = SVX_TAB_DEFDIST;
193 aLineInf.SetDefTabStop( nDefTabDist );
194 }
195 SwTwips nCount = nSearchPos;
196
197 // Minimum tab stop width is 1
198 if (nDefTabDist <= 0)
199 nDefTabDist = 1;
200
201 nCount /= nDefTabDist;
202 nNextPos = ( nCount < 0 || ( !nCount && nSearchPos <= 0 ) )
203 ? ( nCount * nDefTabDist )
204 : ( ( nCount + 1 ) * nDefTabDist );
205 // --> FME 2004-09-21 #117919 Minimum tab stop width is 1 or 51 twips:
206 const SwTwips nMinimumTabWidth = pFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) ? 0 : 50;
207 // <--
208 if ( ( bRTL && nTabLeft - nNextPos >= nCurrentAbsPos - nMinimumTabWidth ) ||
209 ( !bRTL && nNextPos + nTabLeft <= nCurrentAbsPos + nMinimumTabWidth ) )
210 {
211 nNextPos += nDefTabDist;
212 }
213 cFill = 0;
214 eAdj = SVX_TAB_ADJUST_LEFT;
215 }
216
217 // --> OD #i115705# - correction and refactoring:
218 // overrule determined next tab stop position in order to apply
219 // a tab stop at the left margin under the following conditions:
220 // - the new tab portion is inside the hanging indent
221 // - a tab stop at the left margin is allowed
222 // - the determined next tab stop is a default tab stop position OR
223 // the determined next tab stop is beyond the left margin
224 {
225 long nLeftMarginTabPos = 0;
226 {
227 if ( !bTabsRelativeToIndent )
228 {
229 if ( bRTL )
230 {
231 Point aPoint( Left(), 0 );
232 pFrm->SwitchLTRtoRTL( aPoint );
233 nLeftMarginTabPos = pFrm->Frm().Right() - aPoint.X();
234 }
235 else
236 {
237 nLeftMarginTabPos = Left() - pFrm->Frm().Left();
238 }
239 }
240 if( pCurr->HasForcedLeftMargin() )
241 {
242 SwLinePortion* pPor = pCurr->GetPortion();
243 while( pPor && !pPor->IsFlyPortion() )
244 {
245 pPor = pPor->GetPortion();
246 }
247 if ( pPor )
248 {
249 nLeftMarginTabPos += pPor->Width();
250 }
251 }
252 }
253 const bool bNewTabPortionInsideHangingIndent =
254 bRTL ? nCurrentAbsPos > nTabLeft - nLeftMarginTabPos
255 : nCurrentAbsPos < nTabLeft + nLeftMarginTabPos;
256 if ( bNewTabPortionInsideHangingIndent )
257 {
258 // If the paragraph is not inside a list having a list tab stop following
259 // the list label or no further tab stop found in such a paragraph or
260 // the next tab stop position does not equal the list tab stop,
261 // a tab stop at the left margin can be applied. If this condition is
262 // not hold, it is overruled by compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST.
263 const bool bTabAtLeftMarginAllowed =
264 ( !aLineInf.IsListTabStopIncluded() ||
265 !pTabStop ||
266 nNextPos != aLineInf.GetListTabStopPosition() ) ||
267 // compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
268 pFrm->GetTxtNode()->getIDocumentSettingAccess()->
269 get(IDocumentSettingAccess::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST);
270 if ( bTabAtLeftMarginAllowed )
271 {
272 if ( !pTabStop || eAdj == SVX_TAB_ADJUST_DEFAULT ||
273 ( nNextPos > nLeftMarginTabPos ) )
274 {
275 eAdj = SVX_TAB_ADJUST_DEFAULT;
276 cFill = 0;
277 nNextPos = nLeftMarginTabPos;
278 }
279 }
280 }
281 }
282 // <--
283
284 nNextPos += bRTL ? nLinePos - nTabLeft : nTabLeft - nLinePos;
285 ASSERT( nNextPos >= 0, "GetTabStop: Don't go back!" );
286 nNewTabPos = KSHORT(nNextPos);
287 }
288
289 SwTabPortion *pTabPor = 0;
290 if ( bAuto )
291 {
292 if ( SVX_TAB_ADJUST_DECIMAL == eAdj &&
293 // --> FME 2005-12-19 #127428#
294 1 == aLineInf.NumberOfTabStops() )
295 // <--
296 pTabPor = new SwAutoTabDecimalPortion( nNewTabPos, cDec, cFill );
297 }
298 else
299 {
300 switch( eAdj )
301 {
302 case SVX_TAB_ADJUST_RIGHT :
303 {
304 pTabPor = new SwTabRightPortion( nNewTabPos, cFill );
305 break;
306 }
307 case SVX_TAB_ADJUST_CENTER :
308 {
309 pTabPor = new SwTabCenterPortion( nNewTabPos, cFill );
310 break;
311 }
312 case SVX_TAB_ADJUST_DECIMAL :
313 {
314 pTabPor = new SwTabDecimalPortion( nNewTabPos, cDec, cFill );
315 break;
316 }
317 default:
318 {
319 ASSERT( SVX_TAB_ADJUST_LEFT == eAdj || SVX_TAB_ADJUST_DEFAULT == eAdj,
320 "+SwTxtFormatter::NewTabPortion: unknown adjustment" );
321 pTabPor = new SwTabLeftPortion( nNewTabPos, cFill );
322 break;
323 }
324 }
325 }
326
327 return pTabPor;
328 }
329
330 /*************************************************************************
331 * SwTabPortion::SwTabPortion()
332 *************************************************************************/
333
334 // Die Basisklasse wird erstmal ohne alles initialisiert.
335
336
SwTabPortion(const KSHORT nTabPosition,const xub_Unicode cFillChar)337 SwTabPortion::SwTabPortion( const KSHORT nTabPosition, const xub_Unicode cFillChar )
338 : SwFixPortion( 0, 0 ), nTabPos(nTabPosition), cFill(cFillChar)
339 {
340 nLineLength = 1;
341 #ifdef DBG_UTIL
342 if( IsFilled() )
343 {
344 ASSERT( ' ' != cFill, "SwTabPortion::CTOR: blanks ?!" );
345 }
346 #endif
347 SetWhichPor( POR_TAB );
348 }
349
350 /*************************************************************************
351 * virtual SwTabPortion::Format()
352 *************************************************************************/
353
354
355
Format(SwTxtFormatInfo & rInf)356 sal_Bool SwTabPortion::Format( SwTxtFormatInfo &rInf )
357 {
358 SwTabPortion *pLastTab = rInf.GetLastTab();
359 if( pLastTab == this )
360 return PostFormat( rInf );
361 if( pLastTab )
362 pLastTab->PostFormat( rInf );
363 return PreFormat( rInf );
364 }
365
366 /*************************************************************************
367 * virtual SwTabPortion::FormatEOL()
368 *************************************************************************/
369
370
371
FormatEOL(SwTxtFormatInfo & rInf)372 void SwTabPortion::FormatEOL( SwTxtFormatInfo &rInf )
373 {
374 if( rInf.GetLastTab() == this && !IsTabLeftPortion() )
375 PostFormat( rInf );
376 }
377
378 /*************************************************************************
379 * SwTabPortion::PreFormat()
380 *************************************************************************/
381
382
383
PreFormat(SwTxtFormatInfo & rInf)384 sal_Bool SwTabPortion::PreFormat( SwTxtFormatInfo &rInf )
385 {
386 ASSERT( rInf.X() <= GetTabPos(), "SwTabPortion::PreFormat: rush hour" );
387
388 // Hier lassen wir uns nieder...
389 Fix( static_cast<sal_uInt16>(rInf.X()) );
390
391 const bool bTabCompat = rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
392
393 // Die Mindestbreite eines Tabs ist immer mindestens ein Blank
394 // --> FME 2004-11-25 #i37686# In compatibility mode, the minimum width
395 // should be 1, even for non-left tab stops.
396 sal_uInt16 nMinimumTabWidth = 1;
397 // <--
398 if ( !bTabCompat )
399 {
400 // --> OD 2008-06-05 #i89179#
401 // tab portion representing the list tab of a list label gets the
402 // same font as the corresponding number portion
403 std::auto_ptr< SwFontSave > pSave( 0 );
404 if ( GetLen() == 0 &&
405 rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
406 static_cast<SwNumberPortion*>(rInf.GetLast())->HasFont() )
407 {
408 const SwFont* pNumberPortionFont =
409 static_cast<SwNumberPortion*>(rInf.GetLast())->GetFont();
410 pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) );
411 }
412 // <--
413 XubString aTmp( ' ' );
414 SwTxtSizeInfo aInf( rInf, aTmp );
415 nMinimumTabWidth = aInf.GetTxtSize().Width();
416 }
417 PrtWidth( nMinimumTabWidth );
418
419 // Break tab stop to next line if:
420 // 1. Minmal width does not fit to line anymore.
421 // 2. An underflow event was called for the tab portion.
422 sal_Bool bFull = ( bTabCompat && rInf.IsUnderFlow() ) ||
423 rInf.Width() <= rInf.X() + PrtWidth();
424
425 // #95477# Rotated tab stops get the width of one blank
426 const sal_uInt16 nDir = rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() );
427
428 if( ! bFull && 0 == nDir )
429 {
430 const MSHORT nWhich = GetWhichPor();
431 switch( nWhich )
432 {
433 case POR_TABRIGHT:
434 case POR_TABDECIMAL:
435 case POR_TABCENTER:
436 {
437 if( POR_TABDECIMAL == nWhich )
438 rInf.SetTabDecimal(
439 ((SwTabDecimalPortion*)this)->GetTabDecimal());
440 rInf.SetLastTab( this );
441 break;
442 }
443 case POR_TABLEFT:
444 {
445 PrtWidth( static_cast<sal_uInt16>(GetTabPos() - rInf.X()) );
446 bFull = rInf.Width() <= rInf.X() + PrtWidth();
447
448 // In tabulator compatibility mode, we reset the bFull flag
449 // if the tabulator is at the end of the paragraph and the
450 // tab stop position is outside the frame:
451 if ( bFull && bTabCompat &&
452 rInf.GetIdx() + GetLen() == rInf.GetTxt().Len() &&
453 GetTabPos() >= rInf.GetTxtFrm()->Frm().Width() )
454 bFull = sal_False;
455
456 break;
457 }
458 default: ASSERT( !this, "SwTabPortion::PreFormat: unknown adjustment" );
459 }
460 }
461
462 if( bFull )
463 {
464 // Wir muessen aufpassen, dass wir nicht endlos schleifen,
465 // wenn die Breite kleiner ist, als ein Blank ...
466 if( rInf.GetIdx() == rInf.GetLineStart() &&
467 // --> FME 2005-01-19 #119175# TabStop should be forced to current
468 // line if there is a fly reducing the line width:
469 !rInf.GetFly() )
470 // <--
471 {
472 PrtWidth( static_cast<sal_uInt16>(rInf.Width() - rInf.X()) );
473 SetFixWidth( PrtWidth() );
474 }
475 else
476 {
477 Height( 0 );
478 Width( 0 );
479 SetLen( 0 );
480 SetAscent( 0 );
481 SetPortion( NULL ); //?????
482 }
483 return sal_True;
484 }
485 else
486 {
487 // Ein Kunstgriff mit Effekt: Die neuen Tabportions verhalten sich nun
488 // so, wie FlyFrms, die in der Zeile stehen - inklusive Adjustment !
489 SetFixWidth( PrtWidth() );
490 return sal_False;
491 }
492 }
493
494 /*************************************************************************
495 * SwTabPortion::PostFormat()
496 *************************************************************************/
497
498
499
PostFormat(SwTxtFormatInfo & rInf)500 sal_Bool SwTabPortion::PostFormat( SwTxtFormatInfo &rInf )
501 {
502 const KSHORT nRight = Min( GetTabPos(), rInf.Width() );
503 const SwLinePortion *pPor = GetPortion();
504
505 KSHORT nPorWidth = 0;
506 while( pPor )
507 {
508 DBG_LOOP;
509 nPorWidth = nPorWidth + pPor->Width();
510 pPor = pPor->GetPortion();
511 }
512
513 const MSHORT nWhich = GetWhichPor();
514 ASSERT( POR_TABLEFT != nWhich, "SwTabPortion::PostFormat: already formatted" );
515 const bool bTabCompat = rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT);
516
517 // --> FME 2005-12-19 #127428# Abandon dec. tab position if line is full:
518 if ( bTabCompat && POR_TABDECIMAL == nWhich )
519 {
520 KSHORT nPrePorWidth = static_cast<const SwTabDecimalPortion*>(this)->GetWidthOfPortionsUpToDecimalPosition();
521
522 // no value was set => no decimal character was found
523 if ( USHRT_MAX != nPrePorWidth )
524 {
525 if ( nPrePorWidth && nPorWidth - nPrePorWidth > rInf.Width() - nRight )
526 {
527 nPrePorWidth += nPorWidth - nPrePorWidth - ( rInf.Width() - nRight );
528 }
529
530 nPorWidth = nPrePorWidth - 1;
531 }
532 }
533 // <--
534
535 if( POR_TABCENTER == nWhich )
536 {
537 // zentrierte Tabs bereiten Probleme:
538 // Wir muessen den Anteil herausfinden, der noch auf die Zeile passt.
539 KSHORT nNewWidth = nPorWidth /2;
540 if( nNewWidth > rInf.Width() - nRight )
541 nNewWidth = nPorWidth - (rInf.Width() - nRight);
542 nPorWidth = nNewWidth;
543 }
544
545 const KSHORT nDiffWidth = nRight - Fix();
546
547 if( nDiffWidth > nPorWidth )
548 {
549 const KSHORT nOldWidth = GetFixWidth();
550 const KSHORT nAdjDiff = nDiffWidth - nPorWidth;
551 if( nAdjDiff > GetFixWidth() )
552 PrtWidth( nAdjDiff );
553 // Nicht erschrecken: wir muessen rInf weiterschieben.
554 // Immerhin waren wir als Rechtstab bislang nur ein Blank breit.
555 // Da wir uns jetzt aufgespannt haben, muss der Differenzbetrag
556 // auf rInf.X() addiert werden !
557 rInf.X( rInf.X() + PrtWidth() - nOldWidth );
558 }
559 SetFixWidth( PrtWidth() );
560 // letzte Werte zuruecksetzen
561 rInf.SetLastTab(0);
562 if( POR_TABDECIMAL == nWhich )
563 rInf.SetTabDecimal(0);
564
565 return rInf.Width() <= rInf.X();
566 }
567
568 /*************************************************************************
569 * virtual SwTabPortion::Paint()
570 *
571 * Ex: LineIter::DrawTab()
572 *************************************************************************/
573
Paint(const SwTxtPaintInfo & rInf) const574 void SwTabPortion::Paint( const SwTxtPaintInfo &rInf ) const
575 {
576 #ifdef DBG_UTIL
577 // Wir wollen uns die Fixbreite anzeigen
578 if( rInf.OnWin() && OPTDBG( rInf ) &&
579 !rInf.GetOpt().IsPagePreview() && \
580 !rInf.GetOpt().IsReadonly() && \
581 SwViewOption::IsFieldShadings() )
582 {
583 const KSHORT nTmpWidth = PrtWidth();
584 ((SwTabPortion*)this)->PrtWidth( GetFixWidth() );
585 rInf.DrawViewOpt( *this, POR_TAB );
586 ((SwTabPortion*)this)->PrtWidth( nTmpWidth );
587 }
588 #endif
589
590 // --> OD 2008-06-05 #i89179#
591 // tab portion representing the list tab of a list label gets the
592 // same font as the corresponding number portion
593 std::auto_ptr< SwFontSave > pSave( 0 );
594 if ( GetLen() == 0 )
595 {
596 const SwLinePortion* pPrevPortion =
597 const_cast<SwTabPortion*>(this)->FindPrevPortion( rInf.GetParaPortion() );
598 if ( pPrevPortion &&
599 pPrevPortion->InNumberGrp() &&
600 static_cast<const SwNumberPortion*>(pPrevPortion)->HasFont() )
601 {
602 const SwFont* pNumberPortionFont =
603 static_cast<const SwNumberPortion*>(pPrevPortion)->GetFont();
604 pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) );
605 }
606 }
607 // <--
608 rInf.DrawBackBrush( *this );
609
610 // do we have to repaint a post it portion?
611 if( rInf.OnWin() && pPortion && !pPortion->Width() )
612 pPortion->PrePaint( rInf, this );
613
614 // Darstellung von Sonderzeichen
615 if( rInf.OnWin() && rInf.GetOpt().IsTab() )
616 {
617 // gefuellte Tabs werden grau hinterlegt.
618 if( IsFilled() )
619 rInf.DrawViewOpt( *this, POR_TAB );
620 else
621 rInf.DrawTab( *this );
622 }
623
624 // 6842: Tabs sollen auf einmal wieder unterstrichen werden.
625 if( rInf.GetFont()->IsPaintBlank() )
626 {
627 // Tabs mit Fuellung
628 XubString aTxt( ' ' );
629 const KSHORT nCharWidth = rInf.GetTxtSize( aTxt ).Width();
630 // robust:
631 if( nCharWidth )
632 {
633 // 6864: immer mit Kerning, auch auf dem Drucker!
634 KSHORT nChar = Width() / nCharWidth;
635 rInf.DrawText( aTxt.Fill( nChar, ' ' ), *this, 0, nChar, sal_True );
636 }
637 }
638
639 // Ausgabe von Fuellzeichen
640 if( IsFilled() )
641 {
642 // Tabs mit Fuellung
643 XubString aTxt( cFill );
644 const KSHORT nCharWidth = rInf.GetTxtSize( aTxt ).Width();
645 #if OSL_DEBUG_LEVEL > 1
646 ASSERT( nCharWidth, "!SwTabPortion::Paint: sophisticated tabchar" );
647 #endif
648 // robust:
649 if( nCharWidth )
650 {
651 // 6864: immer mit Kerning, auch auf dem Drucker!
652 KSHORT nChar = Width() / nCharWidth;
653 if ( cFill == '_' )
654 ++nChar; // damit keine Luecken entstehen (Bug 13430)
655 rInf.DrawText( aTxt.Fill( nChar, cFill ), *this, 0, nChar, sal_True );
656 }
657 }
658 }
659
660 /*************************************************************************
661 * virtual SwAutoTabDecimalPortion::Paint()
662 *************************************************************************/
663
Paint(const SwTxtPaintInfo &) const664 void SwAutoTabDecimalPortion::Paint( const SwTxtPaintInfo & ) const
665 {
666 }
667
668 /*************************************************************************
669 * virtual SwTabPortion::HandlePortion()
670 *************************************************************************/
671
HandlePortion(SwPortionHandler & rPH) const672 void SwTabPortion::HandlePortion( SwPortionHandler& rPH ) const
673 {
674 rPH.Text( GetLen(), GetWhichPor() );
675 }
676
677