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