xref: /aoo41x/main/sw/source/core/text/txttab.cxx (revision 0244f9a7)
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