1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <hintids.hxx>
21 #include <comphelper/string.hxx>
22 #include <editeng/tstpitem.hxx>
23 #include <rtl/ustrbuf.hxx>
24 #include <IDocumentSettingAccess.hxx>
26 #include <SwPortionHandler.hxx>
28 #include <viewopt.hxx>
31 #include "itrform2.hxx"
37 * #i24363# tab stops relative to indent
39 * Return the first tab stop that is > nSearchPos.
40 * If the tab stop is outside the print area, we
41 * return 0 if it is not the first tab stop.
43 const SvxTabStop
* SwLineInfo::GetTabStop(const SwTwips nSearchPos
, SwTwips
& nRight
) const
45 for( sal_uInt16 i
= 0; i
< m_oRuler
->Count(); ++i
)
47 const SvxTabStop
&rTabStop
= m_oRuler
->operator[](i
);
48 if (nRight
&& rTabStop
.GetTabPos() > nRight
)
50 // Consider the first tabstop to always be in-bounds.
52 nRight
= rTabStop
.GetTabPos();
53 return i
? nullptr : &rTabStop
;
55 if( rTabStop
.GetTabPos() > nSearchPos
)
58 nRight
= rTabStop
.GetTabPos();
65 sal_uInt16
SwLineInfo::NumberOfTabStops() const
67 return m_oRuler
->Count();
70 SwTabPortion
*SwTextFormatter::NewTabPortion( SwTextFormatInfo
&rInf
, bool bAuto
) const
72 IDocumentSettingAccess
const& rIDSA(rInf
.GetTextFrame()->GetDoc().getIDocumentSettingAccess());
73 const bool bTabOverMargin
= rIDSA
.get(DocumentSettingId::TAB_OVER_MARGIN
);
74 const bool bTabOverSpacing
= rIDSA
.get(DocumentSettingId::TAB_OVER_SPACING
);
75 const bool bTabsRelativeToIndent
= rIDSA
.get(DocumentSettingId::TABS_RELATIVE_TO_INDENT
);
77 // Update search location - since Center/Decimal tabstops' width is dependent on the following text.
78 SwTabPortion
* pTmpLastTab
= rInf
.GetLastTab();
79 if (pTmpLastTab
&& (pTmpLastTab
->IsTabCenterPortion() || pTmpLastTab
->IsTabDecimalPortion()))
80 pTmpLastTab
->PostFormat(rInf
);
82 sal_Unicode cFill
= 0;
87 bool bAutoTabStop
= true;
89 const bool bRTL
= m_pFrame
->IsRightToLeft();
90 // #i24363# tab stops relative to indent
91 // nTabLeft: The absolute value, the tab stops are relative to: Tabs origin.
94 const SwTwips nTabLeft
= bRTL
95 ? m_pFrame
->getFrameArea().Right() -
96 ( bTabsRelativeToIndent
? GetTabLeft() : 0 )
97 : m_pFrame
->getFrameArea().Left() +
98 ( bTabsRelativeToIndent
? GetTabLeft() : 0 );
100 // The absolute position, where we started the line formatting
101 SwTwips nLinePos
= GetLeftMargin();
104 Point
aPoint( nLinePos
, 0 );
105 m_pFrame
->SwitchLTRtoRTL( aPoint
);
106 nLinePos
= aPoint
.X();
109 // The current position, relative to the line start
110 SwTwips nTabPos
= rInf
.GetLastTab() ? rInf
.GetLastTab()->GetTabPos() : 0;
111 if( nTabPos
< rInf
.X() )
116 // The current position in absolute coordinates
117 const SwTwips nCurrentAbsPos
= bRTL
?
122 if ( m_pFrame
->IsVertLR() )
127 if ( m_pFrame
->IsVertical() )
129 Point
aRightTop( nMyRight
, m_pFrame
->getFrameArea().Top() );
130 m_pFrame
->SwitchHorizontalToVertical( aRightTop
);
131 nMyRight
= aRightTop
.Y();
134 SwTwips nNextPos
= 0;
135 bool bAbsoluteNextPos
= false;
137 // #i24363# tab stops relative to indent
138 // nSearchPos: The current position relative to the tabs origin
139 const SwTwips nSearchPos
= bRTL
?
140 nTabLeft
- nCurrentAbsPos
:
141 nCurrentAbsPos
- nTabLeft
;
143 // First, we examine the tab stops set at the paragraph style or
144 // any hard set tab stops:
145 // Note: If there are no user defined tab stops, there is always a
147 const SwTwips nOldRight
= nMyRight
;
148 // Accept left-tabstops beyond the paragraph margin for bTabOverSpacing
149 if (bTabOverSpacing
|| bTabOverMargin
)
151 const SvxTabStop
* pTabStop
= m_aLineInf
.GetTabStop( nSearchPos
, nMyRight
);
153 nMyRight
= nOldRight
;
156 cFill
= ' ' != pTabStop
->GetFill() ? pTabStop
->GetFill() : 0;
157 cDec
= pTabStop
->GetDecimal();
158 eAdj
= pTabStop
->GetAdjustment();
159 nNextPos
= pTabStop
->GetTabPos();
160 if(!bTabsRelativeToIndent
&& eAdj
== SvxTabAdjust::Default
&& nSearchPos
< 0)
162 //calculate default tab position of default tabs in negative indent
163 nNextPos
= ( nSearchPos
/ nNextPos
) * nNextPos
;
165 else if (pTabStop
->GetTabPos() > nMyRight
166 && pTabStop
->GetAdjustment() != SvxTabAdjust::Left
)
168 // A rather special situation. The tabstop found is:
169 // 1.) in a document compatible with MS formats
170 // 2.) not a left tabstop.
171 // 3.) not the first tabstop (in that case nMyRight was adjusted to match tabPos).
172 // 4.) beyond the end of the text area
173 // Therefore, they act like right-tabstops at the edge of the para area.
174 // This benefits DOCX 2013+, and doesn't hurt the earlier formats,
175 // since up till now these were just treated as automatic tabstops.
176 eAdj
= SvxTabAdjust::Right
;
177 bAbsoluteNextPos
= true;
178 // TODO: unclear if old Word has an upper limit for center/right
179 // tabs, UI allows setting 55.87cm max which is still one line
180 if (!bTabOverMargin
|| o3tl::toTwips(558, o3tl::Length::mm
) < nNextPos
)
182 nNextPos
= rInf
.Width();
185 bAutoTabStop
= false;
189 SwTwips nDefTabDist
= m_aLineInf
.GetDefTabStop();
190 if (std::numeric_limits
<SwTwips
>::max() == nDefTabDist
)
192 const SvxTabStopItem
& rTab
=
193 m_pFrame
->GetAttrSet()->GetPool()->GetUserOrPoolDefaultItem( RES_PARATR_TABSTOP
);
195 nDefTabDist
= rTab
[0].GetTabPos();
197 nDefTabDist
= SVX_TAB_DEFDIST
;
198 m_aLineInf
.SetDefTabStop( nDefTabDist
);
200 SwTwips nCount
= nSearchPos
;
202 // Minimum tab stop width is 1
203 if (nDefTabDist
<= 0)
206 nCount
/= nDefTabDist
;
207 nNextPos
= ( nCount
< 0 || ( !nCount
&& nSearchPos
<= 0 ) )
208 ? ( nCount
* nDefTabDist
)
209 : ( ( nCount
+ 1 ) * nDefTabDist
);
211 // --> FME 2004-09-21 #117919 Minimum tab stop width is 1 or 51 twips:
212 const SwTwips nMinimumTabWidth
= m_pFrame
->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT
) ? 0 : 50;
213 if( ( bRTL
&& nTabLeft
- nNextPos
>= nCurrentAbsPos
- nMinimumTabWidth
) ||
214 ( !bRTL
&& nNextPos
+ nTabLeft
<= nCurrentAbsPos
+ nMinimumTabWidth
) )
216 nNextPos
+= nDefTabDist
;
219 eAdj
= SvxTabAdjust::Left
;
222 // #i115705# - correction and refactoring:
223 // overrule determined next tab stop position in order to apply
224 // a tab stop at the left margin under the following conditions:
225 // - the new tab portion is inside the hanging indent
226 // - a tab stop at the left margin is allowed
227 // - the determined next tab stop is a default tab stop position OR
228 // the determined next tab stop is beyond the left margin
230 tools::Long nLeftMarginTabPos
= 0;
232 if ( !bTabsRelativeToIndent
)
236 Point
aPoint( Left(), 0 );
237 m_pFrame
->SwitchLTRtoRTL( aPoint
);
238 nLeftMarginTabPos
= m_pFrame
->getFrameArea().Right() - aPoint
.X();
242 nLeftMarginTabPos
= Left() - m_pFrame
->getFrameArea().Left();
245 if( m_pCurr
->HasForcedLeftMargin() )
247 SwLinePortion
* pPor
= m_pCurr
->GetNextPortion();
248 while( pPor
&& !pPor
->IsFlyPortion() )
250 pPor
= pPor
->GetNextPortion();
254 nLeftMarginTabPos
+= pPor
->Width();
258 const bool bNewTabPortionInsideHangingIndent
=
259 bRTL
? nCurrentAbsPos
> nTabLeft
- nLeftMarginTabPos
260 : nCurrentAbsPos
< nTabLeft
+ nLeftMarginTabPos
;
261 if ( bNewTabPortionInsideHangingIndent
)
263 // If the paragraph is not inside a list having a list tab stop following
264 // the list label or no further tab stop found in such a paragraph or
265 // the next tab stop position does not equal the list tab stop,
266 // a tab stop at the left margin can be applied. If this condition is
267 // not hold, it is overruled by compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST.
268 const bool bTabAtLeftMarginAllowed
=
269 ( !m_aLineInf
.IsListTabStopIncluded() ||
271 nNextPos
!= m_aLineInf
.GetListTabStopPosition() ) ||
272 // compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
273 m_pFrame
->GetDoc().getIDocumentSettingAccess().
274 get(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST
);
275 if ( bTabAtLeftMarginAllowed
)
277 if ( !pTabStop
|| eAdj
== SvxTabAdjust::Default
||
278 ( nNextPos
> nLeftMarginTabPos
) )
280 eAdj
= SvxTabAdjust::Default
;
282 nNextPos
= nLeftMarginTabPos
;
288 if (!bAbsoluteNextPos
)
289 nNextPos
+= bRTL
? nLinePos
- nTabLeft
: nTabLeft
- nLinePos
;
290 OSL_ENSURE( nNextPos
>= 0, "GetTabStop: Don't go back!" );
291 nNewTabPos
= nNextPos
;
294 SwTabPortion
*pTabPor
= nullptr;
297 if ( SvxTabAdjust::Decimal
== eAdj
&&
298 1 == m_aLineInf
.NumberOfTabStops() )
299 pTabPor
= new SwAutoTabDecimalPortion( nNewTabPos
, cDec
, cFill
);
305 case SvxTabAdjust::Right
:
307 pTabPor
= new SwTabRightPortion( nNewTabPos
, cFill
);
310 case SvxTabAdjust::Center
:
312 pTabPor
= new SwTabCenterPortion( nNewTabPos
, cFill
);
315 case SvxTabAdjust::Decimal
:
317 pTabPor
= new SwTabDecimalPortion( nNewTabPos
, cDec
, cFill
);
322 OSL_ENSURE( SvxTabAdjust::Left
== eAdj
|| SvxTabAdjust::Default
== eAdj
,
323 "+SwTextFormatter::NewTabPortion: unknown adjustment" );
324 pTabPor
= new SwTabLeftPortion( nNewTabPos
, cFill
, bAutoTabStop
);
330 rInf
.UpdateTabSeen(pTabPor
->GetWhichPor());
336 * The base class is initialized without setting anything
338 SwTabPortion::SwTabPortion( const SwTwips nTabPosition
, const sal_Unicode cFillChar
, const bool bAutoTab
)
339 : m_nTabPos(nTabPosition
), m_cFill(cFillChar
), m_bAutoTabStop( bAutoTab
)
341 mnLineLength
= TextFrameIndex(1);
342 OSL_ENSURE(!IsFilled() || ' ' != m_cFill
, "SwTabPortion::CTOR: blanks ?!");
343 SetWhichPor( PortionType::Tab
);
346 bool SwTabPortion::Format( SwTextFormatInfo
&rInf
)
348 SwTabPortion
*pLastTab
= rInf
.GetLastTab();
349 if( pLastTab
== this )
350 return PostFormat( rInf
);
352 pLastTab
->PostFormat( rInf
);
353 return PreFormat(rInf
, pLastTab
);
356 void SwTabPortion::FormatEOL( SwTextFormatInfo
&rInf
)
358 if( rInf
.GetLastTab() == this )
362 bool SwTabPortion::PreFormat(SwTextFormatInfo
&rInf
, SwTabPortion
const*const pLastTab
)
364 OSL_ENSURE( rInf
.X() <= GetTabPos(), "SwTabPortion::PreFormat: rush hour" );
366 // Here we settle down ...
369 IDocumentSettingAccess
const& rIDSA(rInf
.GetTextFrame()->GetDoc().getIDocumentSettingAccess());
370 const bool bTabCompat
= rIDSA
.get(DocumentSettingId::TAB_COMPAT
);
371 const bool bTabOverflow
= rIDSA
.get(DocumentSettingId::TAB_OVERFLOW
);
372 const bool bTabOverMargin
= rIDSA
.get(DocumentSettingId::TAB_OVER_MARGIN
);
373 const bool bTabOverSpacing
= rIDSA
.get(DocumentSettingId::TAB_OVER_SPACING
);
374 const tools::Long nTextFrameWidth
= rInf
.GetTextFrame()->getFrameArea().Width();
376 // The minimal width of a tab is one blank at least.
377 // #i37686# In compatibility mode, the minimum width
378 // should be 1, even for non-left tab stops.
379 SwTwips nMinimumTabWidth
= 1;
383 // tab portion representing the list tab of a list label gets the
384 // same font as the corresponding number portion
385 std::optional
< SwFontSave
> oSave
;
386 if ( GetLen() == TextFrameIndex(0) &&
387 rInf
.GetLast() && rInf
.GetLast()->InNumberGrp() &&
388 static_cast<SwNumberPortion
*>(rInf
.GetLast())->HasFont() )
390 const SwFont
* pNumberPortionFont
=
391 static_cast<SwNumberPortion
*>(rInf
.GetLast())->GetFont();
392 oSave
.emplace( rInf
, const_cast<SwFont
*>(pNumberPortionFont
) );
394 OUString
aTmp( ' ' );
395 SwTextSizeInfo
aInf( rInf
, &aTmp
);
396 nMinimumTabWidth
= aInf
.GetTextSize().Width();
398 PrtWidth( nMinimumTabWidth
);
400 // Break tab stop to next line if:
401 // 1. Minimal width does not fit to line anymore.
402 // 2. An underflow event was called for the tab portion.
403 bool bFull
= ( bTabCompat
&& rInf
.IsUnderflow() ) ||
404 (rInf
.Width() <= rInf
.X() + PrtWidth() && rInf
.X() <= rInf
.Width()
405 && (!bTabOverMargin
|| !pLastTab
));
407 // #95477# Rotated tab stops get the width of one blank
408 const Degree10 nDir
= rInf
.GetFont()->GetOrientation( rInf
.GetTextFrame()->IsVertical() );
410 if( ! bFull
&& 0_deg10
== nDir
)
412 const PortionType nWhich
= GetWhichPor();
415 case PortionType::TabRight
:
416 case PortionType::TabDecimal
:
417 case PortionType::TabCenter
:
419 if( PortionType::TabDecimal
== nWhich
)
421 static_cast<SwTabDecimalPortion
*>(this)->GetTabDecimal());
422 rInf
.SetLastTab( this );
425 case PortionType::TabLeft
:
427 // handle this case in PostFormat
428 if ((bTabOverMargin
|| bTabOverSpacing
) && GetTabPos() > rInf
.Width()
429 && (!m_bAutoTabStop
|| rInf
.Width() <= rInf
.X()))
431 if (bTabOverMargin
|| GetTabPos() < nTextFrameWidth
)
433 rInf
.SetLastTab(this);
438 assert(!bTabOverMargin
&& bTabOverSpacing
&& GetTabPos() >= nTextFrameWidth
);
444 PrtWidth(GetTabPos() - rInf
.X());
445 bFull
= rInf
.Width() <= rInf
.X() + PrtWidth();
447 // In tabulator compatibility mode, we reset the bFull flag
448 // if the tabulator is at the end of the paragraph and the
449 // tab stop position is outside the frame:
450 bool bAtParaEnd
= rInf
.GetIdx() + GetLen() == TextFrameIndex(rInf
.GetText().getLength());
451 if ( bFull
&& bTabCompat
&&
452 ( ( bTabOverflow
&& ( rInf
.IsTabOverflow() || !m_bAutoTabStop
) ) || bAtParaEnd
) &&
453 GetTabPos() >= nTextFrameWidth
)
456 if ( bTabOverflow
&& !m_bAutoTabStop
)
457 rInf
.SetTabOverflow( true );
462 default: OSL_ENSURE( false, "SwTabPortion::PreFormat: unknown adjustment" );
468 // We have to look for endless loops, if the width is smaller than one blank
469 if( rInf
.GetIdx() == rInf
.GetLineStart() &&
470 // #119175# TabStop should be forced to current
471 // line if there is a fly reducing the line width:
474 PrtWidth(rInf
.Width() - rInf
.X());
475 SetFixWidth( PrtWidth() );
481 SetLen( TextFrameIndex(0) );
483 SetNextPortion( nullptr ); //?????
489 // A trick with impact: The new Tabportions now behave like
490 // FlyFrames, located in the line - including adjustment !
491 SetFixWidth( PrtWidth() );
496 bool SwTabPortion::PostFormat( SwTextFormatInfo
&rInf
)
498 bool bTabOverMargin
= rInf
.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
499 DocumentSettingId::TAB_OVER_MARGIN
);
500 bool bTabOverSpacing
= rInf
.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
501 DocumentSettingId::TAB_OVER_SPACING
);
502 if (rInf
.GetTextFrame()->IsInSct())
503 bTabOverMargin
= false;
505 // If the tab position is larger than the right margin, it gets scaled down by default.
506 // However, if compat mode enabled, we allow tabs to go over the margin: the rest of the paragraph is not broken into lines.
511 ? std::min(GetTabPos(), rInf
.GetTextFrame()->getFrameArea().Right())
512 : std::min(GetTabPos(), rInf
.Width());
513 const SwLinePortion
*pPor
= GetNextPortion();
515 SwTwips nPorWidth
= 0;
518 nPorWidth
= nPorWidth
+ pPor
->Width();
519 pPor
= pPor
->GetNextPortion();
522 const PortionType nWhich
= GetWhichPor();
523 const bool bTabCompat
= rInf
.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT
);
525 if ((bTabOverMargin
|| bTabOverSpacing
) && PortionType::TabLeft
== nWhich
)
530 // #127428# Abandon dec. tab position if line is full
531 if ( bTabCompat
&& PortionType::TabDecimal
== nWhich
)
533 SwTwips nPrePorWidth
= static_cast<const SwTabDecimalPortion
*>(this)->GetWidthOfPortionsUpToDecimalPosition();
535 // no value was set => no decimal character was found
536 if (std::numeric_limits
<SwTwips
>::max() != nPrePorWidth
)
538 if ( !bTabOverMargin
&& nPrePorWidth
&& nPorWidth
- nPrePorWidth
> rInf
.Width() - nRight
)
540 nPrePorWidth
+= nPorWidth
- nPrePorWidth
- ( rInf
.Width() - nRight
);
543 nPorWidth
= nPrePorWidth
- 1;
547 if( PortionType::TabCenter
== nWhich
)
549 // centered tabs are problematic:
550 // We have to detect how much fits into the line.
551 SwTwips nNewWidth
= nPorWidth
/ 2;
552 if (!bTabOverMargin
&& !bTabOverSpacing
&& nNewWidth
> rInf
.Width() - nRight
)
553 nNewWidth
= nPorWidth
- (rInf
.Width() - nRight
);
554 nPorWidth
= nNewWidth
;
557 const SwTwips nDiffWidth
= nRight
- GetFix();
559 if( nDiffWidth
> nPorWidth
)
561 const SwTwips nOldWidth
= GetFixWidth();
562 const SwTwips nAdjDiff
= nDiffWidth
- nPorWidth
;
563 if( nAdjDiff
> GetFixWidth() )
564 PrtWidth( nAdjDiff
);
565 // Don't be afraid: we have to move rInf further.
566 // The right-tab till now only had the width of one blank.
567 // Now that we stretched, the difference had to be added to rInf.X() !
568 rInf
.X( rInf
.X() + PrtWidth() - nOldWidth
);
570 SetFixWidth( PrtWidth() );
572 rInf
.SetLastTab(nullptr);
573 if( PortionType::TabDecimal
== nWhich
)
574 rInf
.SetTabDecimal(0);
576 return rInf
.Width() <= rInf
.X();
580 * Ex: LineIter::DrawTab()
582 void SwTabPortion::Paint( const SwTextPaintInfo
&rInf
) const
585 // tab portion representing the list tab of a list label gets the
586 // same font as the corresponding number portion
587 std::optional
< SwFontSave
> oSave
;
588 bool bAfterNumbering
= false;
589 if (GetLen() == TextFrameIndex(0))
591 const SwLinePortion
* pPrevPortion
=
592 const_cast<SwTabPortion
*>(this)->FindPrevPortion( rInf
.GetParaPortion() );
594 pPrevPortion
->InNumberGrp() &&
595 static_cast<const SwNumberPortion
*>(pPrevPortion
)->HasFont() )
597 const SwFont
* pNumberPortionFont
=
598 static_cast<const SwNumberPortion
*>(pPrevPortion
)->GetFont();
599 oSave
.emplace( rInf
, const_cast<SwFont
*>(pNumberPortionFont
) );
600 bAfterNumbering
= true;
603 rInf
.DrawBackBrush( *this );
604 if( !bAfterNumbering
)
605 rInf
.DrawBorder( *this );
607 // do we have to repaint a post it portion?
608 if( rInf
.OnWin() && mpNextPortion
&& !mpNextPortion
->Width() )
609 mpNextPortion
->PrePaint( rInf
, this );
611 // display special characters
612 if( rInf
.OnWin() && rInf
.GetOpt().IsTab() )
614 // filled tabs are shaded in gray
616 rInf
.DrawViewOpt( *this, PortionType::Tab
);
618 rInf
.DrawTab( *this );
621 // Tabs should be underlined at once
622 if( rInf
.GetFont()->IsPaintBlank() )
624 // Tabs with filling/filled tabs
625 const SwTwips nCharWidth
= rInf
.GetTextSize(OUString(' ')).Width();
630 // Always with kerning, also on printer!
631 sal_Int32 nChar
= Width() / nCharWidth
;
632 OUStringBuffer
aBuf(nChar
);
633 comphelper::string::padToLength(aBuf
, nChar
, ' ');
634 rInf
.DrawText(aBuf
.makeStringAndClear(), *this, TextFrameIndex(0),
635 TextFrameIndex(nChar
), true);
639 // Display fill characters
643 // Tabs with filling/filled tabs
644 const SwTwips nCharWidth
= rInf
.GetTextSize(OUString(m_cFill
)).Width();
645 OSL_ENSURE( nCharWidth
, "!SwTabPortion::Paint: sophisticated tabchar" );
650 // Always with kerning, also on printer!
651 sal_Int32 nChar
= Width() / nCharWidth
;
652 if ( m_cFill
== '_' )
653 ++nChar
; // to avoid gaps
654 OUStringBuffer
aBuf(nChar
);
655 comphelper::string::padToLength(aBuf
, nChar
, m_cFill
);
656 rInf
.DrawText(aBuf
.makeStringAndClear(), *this, TextFrameIndex(0),
657 TextFrameIndex(nChar
), true);
661 void SwAutoTabDecimalPortion::Paint( const SwTextPaintInfo
& ) const
665 void SwTabPortion::HandlePortion( SwPortionHandler
& rPH
) const
667 rPH
.Text( GetLen(), GetWhichPor() );
670 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */