1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <hintids.hxx>
21 #include <comphelper/string.hxx>
22 #include <editeng/lrspitem.hxx>
23 #include <editeng/tstpitem.hxx>
24 #include <rtl/ustrbuf.hxx>
25 #include <IDocumentSettingAccess.hxx>
26 #include <doc.hxx>
27 #include <frmatr.hxx>
28 #include <SwPortionHandler.hxx>
29
30 #include <viewopt.hxx>
31 #include "portab.hxx"
32 #include "inftxt.hxx"
33 #include "itrform2.hxx"
34 #include <txtfrm.hxx>
35 #include <numrule.hxx>
36 #include "porfld.hxx"
37 #include <memory>
38
39 /**
40 * #i24363# tab stops relative to indent
41 *
42 * Return the first tab stop that is > nSearchPos.
43 * If the tab stop is outside the print area, we
44 * return 0 if it is not the first tab stop.
45 */
GetTabStop(const SwTwips nSearchPos,const SwTwips nRight) const46 const SvxTabStop *SwLineInfo::GetTabStop( const SwTwips nSearchPos, const SwTwips nRight ) const
47 {
48 for( sal_uInt16 i = 0; i < pRuler->Count(); ++i )
49 {
50 const SvxTabStop &rTabStop = pRuler->operator[](i);
51 if( rTabStop.GetTabPos() > SwTwips(nRight) )
52 return i ? nullptr : &rTabStop;
53
54 if( rTabStop.GetTabPos() > nSearchPos )
55 return &rTabStop;
56 }
57 return nullptr;
58 }
59
NumberOfTabStops() const60 sal_uInt16 SwLineInfo::NumberOfTabStops() const
61 {
62 return pRuler->Count();
63 }
64
NewTabPortion(SwTextFormatInfo & rInf,bool bAuto) const65 SwTabPortion *SwTextFormatter::NewTabPortion( SwTextFormatInfo &rInf, bool bAuto ) const
66 {
67 sal_Unicode cFill = 0;
68 sal_Unicode cDec = 0;
69 SvxTabAdjust eAdj;
70
71 sal_uInt16 nNewTabPos;
72 bool bAutoTabStop = true;
73 {
74 const bool bRTL = m_pFrame->IsRightToLeft();
75 // #i24363# tab stops relative to indent
76 // nTabLeft: The absolute value, the tab stops are relative to: Tabs origin.
77
78 // #i91133#
79 const bool bTabsRelativeToIndent =
80 m_pFrame->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TABS_RELATIVE_TO_INDENT);
81 const SwTwips nTabLeft = bRTL
82 ? m_pFrame->getFrameArea().Right() -
83 ( bTabsRelativeToIndent ? GetTabLeft() : 0 )
84 : m_pFrame->getFrameArea().Left() +
85 ( bTabsRelativeToIndent ? GetTabLeft() : 0 );
86
87 // The absolute position, where we started the line formatting
88 SwTwips nLinePos = GetLeftMargin();
89 if ( bRTL )
90 {
91 Point aPoint( nLinePos, 0 );
92 m_pFrame->SwitchLTRtoRTL( aPoint );
93 nLinePos = aPoint.X();
94 }
95
96 // The current position, relative to the line start
97 SwTwips nTabPos = rInf.GetLastTab() ? rInf.GetLastTab()->GetTabPos() : 0;
98 if( nTabPos < rInf.X() )
99 {
100 nTabPos = rInf.X();
101 }
102
103 // The current position in absolute coordinates
104 const SwTwips nCurrentAbsPos = bRTL ?
105 nLinePos - nTabPos :
106 nLinePos + nTabPos;
107
108 SwTwips nMyRight;
109 if ( m_pFrame->IsVertLR() )
110 nMyRight = Left();
111 else
112 nMyRight = Right();
113
114 if ( m_pFrame->IsVertical() )
115 {
116 Point aRightTop( nMyRight, m_pFrame->getFrameArea().Top() );
117 m_pFrame->SwitchHorizontalToVertical( aRightTop );
118 nMyRight = aRightTop.Y();
119 }
120
121 SwTwips nNextPos = 0;
122
123 // #i24363# tab stops relative to indent
124 // nSearchPos: The current position relative to the tabs origin
125 const SwTwips nSearchPos = bRTL ?
126 nTabLeft - nCurrentAbsPos :
127 nCurrentAbsPos - nTabLeft;
128
129 // First, we examine the tab stops set at the paragraph style or
130 // any hard set tab stops:
131 // Note: If there are no user defined tab stops, there is always a
132 // default tab stop.
133 const SvxTabStop* pTabStop = m_aLineInf.GetTabStop( nSearchPos, nMyRight );
134 if ( pTabStop )
135 {
136 cFill = ' ' != pTabStop->GetFill() ? pTabStop->GetFill() : 0;
137 cDec = pTabStop->GetDecimal();
138 eAdj = pTabStop->GetAdjustment();
139 nNextPos = pTabStop->GetTabPos();
140 if(!bTabsRelativeToIndent && eAdj == SvxTabAdjust::Default && nSearchPos < 0)
141 {
142 //calculate default tab position of default tabs in negative indent
143 nNextPos = ( nSearchPos / nNextPos ) * nNextPos;
144 }
145 bAutoTabStop = false;
146 }
147 else
148 {
149 sal_uInt16 nDefTabDist = m_aLineInf.GetDefTabStop();
150 if( USHRT_MAX == nDefTabDist )
151 {
152 const SvxTabStopItem& rTab =
153 m_pFrame->GetAttrSet()->GetPool()->GetDefaultItem( RES_PARATR_TABSTOP );
154 if( rTab.Count() )
155 nDefTabDist = static_cast<sal_uInt16>(rTab[0].GetTabPos());
156 else
157 nDefTabDist = SVX_TAB_DEFDIST;
158 m_aLineInf.SetDefTabStop( nDefTabDist );
159 }
160 SwTwips nCount = nSearchPos;
161
162 // Minimum tab stop width is 1
163 if (nDefTabDist <= 0)
164 nDefTabDist = 1;
165
166 nCount /= nDefTabDist;
167 nNextPos = ( nCount < 0 || ( !nCount && nSearchPos <= 0 ) )
168 ? ( nCount * nDefTabDist )
169 : ( ( nCount + 1 ) * nDefTabDist );
170
171 // --> FME 2004-09-21 #117919 Minimum tab stop width is 1 or 51 twips:
172 const SwTwips nMinimumTabWidth = m_pFrame->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT) ? 0 : 50;
173 if( ( bRTL && nTabLeft - nNextPos >= nCurrentAbsPos - nMinimumTabWidth ) ||
174 ( !bRTL && nNextPos + nTabLeft <= nCurrentAbsPos + nMinimumTabWidth ) )
175 {
176 nNextPos += nDefTabDist;
177 }
178 cFill = 0;
179 eAdj = SvxTabAdjust::Left;
180 }
181
182 // #i115705# - correction and refactoring:
183 // overrule determined next tab stop position in order to apply
184 // a tab stop at the left margin under the following conditions:
185 // - the new tab portion is inside the hanging indent
186 // - a tab stop at the left margin is allowed
187 // - the determined next tab stop is a default tab stop position OR
188 // the determined next tab stop is beyond the left margin
189 {
190 long nLeftMarginTabPos = 0;
191 {
192 if ( !bTabsRelativeToIndent )
193 {
194 if ( bRTL )
195 {
196 Point aPoint( Left(), 0 );
197 m_pFrame->SwitchLTRtoRTL( aPoint );
198 nLeftMarginTabPos = m_pFrame->getFrameArea().Right() - aPoint.X();
199 }
200 else
201 {
202 nLeftMarginTabPos = Left() - m_pFrame->getFrameArea().Left();
203 }
204 }
205 if( m_pCurr->HasForcedLeftMargin() )
206 {
207 SwLinePortion* pPor = m_pCurr->GetNextPortion();
208 while( pPor && !pPor->IsFlyPortion() )
209 {
210 pPor = pPor->GetNextPortion();
211 }
212 if ( pPor )
213 {
214 nLeftMarginTabPos += pPor->Width();
215 }
216 }
217 }
218 const bool bNewTabPortionInsideHangingIndent =
219 bRTL ? nCurrentAbsPos > nTabLeft - nLeftMarginTabPos
220 : nCurrentAbsPos < nTabLeft + nLeftMarginTabPos;
221 if ( bNewTabPortionInsideHangingIndent )
222 {
223 // If the paragraph is not inside a list having a list tab stop following
224 // the list label or no further tab stop found in such a paragraph or
225 // the next tab stop position does not equal the list tab stop,
226 // a tab stop at the left margin can be applied. If this condition is
227 // not hold, it is overruled by compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST.
228 const bool bTabAtLeftMarginAllowed =
229 ( !m_aLineInf.IsListTabStopIncluded() ||
230 !pTabStop ||
231 nNextPos != m_aLineInf.GetListTabStopPosition() ) ||
232 // compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
233 m_pFrame->GetDoc().getIDocumentSettingAccess().
234 get(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST);
235 if ( bTabAtLeftMarginAllowed )
236 {
237 if ( !pTabStop || eAdj == SvxTabAdjust::Default ||
238 ( nNextPos > nLeftMarginTabPos ) )
239 {
240 eAdj = SvxTabAdjust::Default;
241 cFill = 0;
242 nNextPos = nLeftMarginTabPos;
243 }
244 }
245 }
246 }
247
248 nNextPos += bRTL ? nLinePos - nTabLeft : nTabLeft - nLinePos;
249 OSL_ENSURE( nNextPos >= 0, "GetTabStop: Don't go back!" );
250 nNewTabPos = sal_uInt16(nNextPos);
251 }
252
253 SwTabPortion *pTabPor = nullptr;
254 if ( bAuto )
255 {
256 if ( SvxTabAdjust::Decimal == eAdj &&
257 1 == m_aLineInf.NumberOfTabStops() )
258 pTabPor = new SwAutoTabDecimalPortion( nNewTabPos, cDec, cFill );
259 }
260 else
261 {
262 switch( eAdj )
263 {
264 case SvxTabAdjust::Right :
265 {
266 pTabPor = new SwTabRightPortion( nNewTabPos, cFill );
267 break;
268 }
269 case SvxTabAdjust::Center :
270 {
271 pTabPor = new SwTabCenterPortion( nNewTabPos, cFill );
272 break;
273 }
274 case SvxTabAdjust::Decimal :
275 {
276 pTabPor = new SwTabDecimalPortion( nNewTabPos, cDec, cFill );
277 break;
278 }
279 default:
280 {
281 OSL_ENSURE( SvxTabAdjust::Left == eAdj || SvxTabAdjust::Default == eAdj,
282 "+SwTextFormatter::NewTabPortion: unknown adjustment" );
283 pTabPor = new SwTabLeftPortion( nNewTabPos, cFill, bAutoTabStop );
284 break;
285 }
286 }
287 }
288
289 return pTabPor;
290 }
291
292 /**
293 * The base class is initialized without setting anything
294 */
SwTabPortion(const sal_uInt16 nTabPosition,const sal_Unicode cFillChar,const bool bAutoTab)295 SwTabPortion::SwTabPortion( const sal_uInt16 nTabPosition, const sal_Unicode cFillChar, const bool bAutoTab )
296 : SwFixPortion(), nTabPos(nTabPosition), cFill(cFillChar), bAutoTabStop( bAutoTab )
297 {
298 nLineLength = TextFrameIndex(1);
299 OSL_ENSURE(!IsFilled() || ' ' != cFill, "SwTabPortion::CTOR: blanks ?!");
300 SetWhichPor( PortionType::Table );
301 }
302
Format(SwTextFormatInfo & rInf)303 bool SwTabPortion::Format( SwTextFormatInfo &rInf )
304 {
305 SwTabPortion *pLastTab = rInf.GetLastTab();
306 if( pLastTab == this )
307 return PostFormat( rInf );
308 if( pLastTab )
309 pLastTab->PostFormat( rInf );
310 return PreFormat( rInf );
311 }
312
FormatEOL(SwTextFormatInfo & rInf)313 void SwTabPortion::FormatEOL( SwTextFormatInfo &rInf )
314 {
315 if( rInf.GetLastTab() == this )
316 PostFormat( rInf );
317 }
318
PreFormat(SwTextFormatInfo & rInf)319 bool SwTabPortion::PreFormat( SwTextFormatInfo &rInf )
320 {
321 OSL_ENSURE( rInf.X() <= GetTabPos(), "SwTabPortion::PreFormat: rush hour" );
322
323 // Here we settle down ...
324 SetFix( static_cast<sal_uInt16>(rInf.X()) );
325
326 IDocumentSettingAccess const& rIDSA(rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess());
327 const bool bTabCompat = rIDSA.get(DocumentSettingId::TAB_COMPAT);
328 const bool bTabOverflow = rIDSA.get(DocumentSettingId::TAB_OVERFLOW);
329 const bool bTabOverMargin = rIDSA.get(DocumentSettingId::TAB_OVER_MARGIN);
330
331 // The minimal width of a tab is one blank at least.
332 // #i37686# In compatibility mode, the minimum width
333 // should be 1, even for non-left tab stops.
334 sal_uInt16 nMinimumTabWidth = 1;
335 if ( !bTabCompat )
336 {
337 // #i89179#
338 // tab portion representing the list tab of a list label gets the
339 // same font as the corresponding number portion
340 std::unique_ptr< SwFontSave > pSave;
341 if ( GetLen() == TextFrameIndex(0) &&
342 rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
343 static_cast<SwNumberPortion*>(rInf.GetLast())->HasFont() )
344 {
345 const SwFont* pNumberPortionFont =
346 static_cast<SwNumberPortion*>(rInf.GetLast())->GetFont();
347 pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) );
348 }
349 OUString aTmp( ' ' );
350 SwTextSizeInfo aInf( rInf, &aTmp );
351 nMinimumTabWidth = aInf.GetTextSize().Width();
352 }
353 PrtWidth( nMinimumTabWidth );
354
355 // Break tab stop to next line if:
356 // 1. Minimal width does not fit to line anymore.
357 // 2. An underflow event was called for the tab portion.
358 bool bFull = ( bTabCompat && rInf.IsUnderflow() ) ||
359 ( rInf.Width() <= rInf.X() + PrtWidth() && rInf.X() <= rInf.Width() ) ;
360
361 // #95477# Rotated tab stops get the width of one blank
362 const sal_uInt16 nDir = rInf.GetFont()->GetOrientation( rInf.GetTextFrame()->IsVertical() );
363
364 if( ! bFull && 0 == nDir )
365 {
366 const PortionType nWhich = GetWhichPor();
367 switch( nWhich )
368 {
369 case PortionType::TabRight:
370 case PortionType::TabDecimal:
371 case PortionType::TabCenter:
372 {
373 if( PortionType::TabDecimal == nWhich )
374 rInf.SetTabDecimal(
375 static_cast<SwTabDecimalPortion*>(this)->GetTabDecimal());
376 rInf.SetLastTab( this );
377 break;
378 }
379 case PortionType::TabLeft:
380 {
381 // handle this case in PostFormat
382 if( bTabOverMargin && !bAutoTabStop && GetTabPos() > rInf.Width() )
383 {
384 rInf.SetLastTab( this );
385 break;
386 }
387
388 PrtWidth( static_cast<sal_uInt16>(GetTabPos() - rInf.X()) );
389 bFull = rInf.Width() <= rInf.X() + PrtWidth();
390
391 // In tabulator compatibility mode, we reset the bFull flag
392 // if the tabulator is at the end of the paragraph and the
393 // tab stop position is outside the frame:
394 bool bAtParaEnd = rInf.GetIdx() + GetLen() == TextFrameIndex(rInf.GetText().getLength());
395 if ( bFull && bTabCompat &&
396 ( ( bTabOverflow && ( rInf.IsTabOverflow() || !bAutoTabStop ) ) || bAtParaEnd ) &&
397 GetTabPos() >= rInf.GetTextFrame()->getFrameArea().Width() )
398 {
399 bFull = false;
400 if ( bTabOverflow && !bAutoTabStop )
401 rInf.SetTabOverflow( true );
402 }
403
404 break;
405 }
406 default: OSL_ENSURE( false, "SwTabPortion::PreFormat: unknown adjustment" );
407 }
408 }
409
410 if( bFull )
411 {
412 // We have to look for endless loops, if the width is smaller than one blank
413 if( rInf.GetIdx() == rInf.GetLineStart() &&
414 // #119175# TabStop should be forced to current
415 // line if there is a fly reducing the line width:
416 !rInf.GetFly() )
417 {
418 PrtWidth( static_cast<sal_uInt16>(rInf.Width() - rInf.X()) );
419 SetFixWidth( PrtWidth() );
420 }
421 else
422 {
423 Height( 0 );
424 Width( 0 );
425 SetLen( TextFrameIndex(0) );
426 SetAscent( 0 );
427 SetNextPortion( nullptr ); //?????
428 }
429 return true;
430 }
431 else
432 {
433 // A trick with impact: The new Tabportions now behave like
434 // FlyFrames, located in the line - including adjustment !
435 SetFixWidth( PrtWidth() );
436 return false;
437 }
438 }
439
PostFormat(SwTextFormatInfo & rInf)440 bool SwTabPortion::PostFormat( SwTextFormatInfo &rInf )
441 {
442 const bool bTabOverMargin = rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_OVER_MARGIN);
443 // If the tab position is larger than the right margin, it gets scaled down by default.
444 // However, if compat mode enabled, we allow tabs to go over the margin: the rest of the paragraph is not broken into lines.
445 const sal_uInt16 nRight = bTabOverMargin ? GetTabPos() : std::min(GetTabPos(), rInf.Width());
446 const SwLinePortion *pPor = GetNextPortion();
447
448 sal_uInt16 nPorWidth = 0;
449 while( pPor )
450 {
451 nPorWidth = nPorWidth + pPor->Width();
452 pPor = pPor->GetNextPortion();
453 }
454
455 const PortionType nWhich = GetWhichPor();
456 const bool bTabCompat = rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT);
457
458 if ( bTabOverMargin && PortionType::TabLeft == nWhich )
459 {
460 nPorWidth = 0;
461 }
462
463 // #127428# Abandon dec. tab position if line is full
464 if ( bTabCompat && PortionType::TabDecimal == nWhich )
465 {
466 sal_uInt16 nPrePorWidth = static_cast<const SwTabDecimalPortion*>(this)->GetWidthOfPortionsUpToDecimalPosition();
467
468 // no value was set => no decimal character was found
469 if ( USHRT_MAX != nPrePorWidth )
470 {
471 if ( !bTabOverMargin && nPrePorWidth && nPorWidth - nPrePorWidth > rInf.Width() - nRight )
472 {
473 nPrePorWidth += nPorWidth - nPrePorWidth - ( rInf.Width() - nRight );
474 }
475
476 nPorWidth = nPrePorWidth - 1;
477 }
478 }
479
480 if( PortionType::TabCenter == nWhich )
481 {
482 // centered tabs are problematic:
483 // We have to detect how much fits into the line.
484 sal_uInt16 nNewWidth = nPorWidth /2;
485 if( !bTabOverMargin && nNewWidth > rInf.Width() - nRight )
486 nNewWidth = nPorWidth - (rInf.Width() - nRight);
487 nPorWidth = nNewWidth;
488 }
489
490 const sal_uInt16 nDiffWidth = nRight - GetFix();
491
492 if( nDiffWidth > nPorWidth )
493 {
494 const sal_uInt16 nOldWidth = GetFixWidth();
495 const sal_uInt16 nAdjDiff = nDiffWidth - nPorWidth;
496 if( nAdjDiff > GetFixWidth() )
497 PrtWidth( nAdjDiff );
498 // Don't be afraid: we have to move rInf further.
499 // The right-tab till now only had the width of one blank.
500 // Now that we stretched, the difference had to be added to rInf.X() !
501 rInf.X( rInf.X() + PrtWidth() - nOldWidth );
502 }
503 SetFixWidth( PrtWidth() );
504 // reset last values
505 rInf.SetLastTab(nullptr);
506 if( PortionType::TabDecimal == nWhich )
507 rInf.SetTabDecimal(0);
508
509 return rInf.Width() <= rInf.X();
510 }
511
512 /**
513 * Ex: LineIter::DrawTab()
514 */
Paint(const SwTextPaintInfo & rInf) const515 void SwTabPortion::Paint( const SwTextPaintInfo &rInf ) const
516 {
517 // #i89179#
518 // tab portion representing the list tab of a list label gets the
519 // same font as the corresponding number portion
520 std::unique_ptr< SwFontSave > pSave;
521 bool bAfterNumbering = false;
522 if (GetLen() == TextFrameIndex(0))
523 {
524 const SwLinePortion* pPrevPortion =
525 const_cast<SwTabPortion*>(this)->FindPrevPortion( rInf.GetParaPortion() );
526 if ( pPrevPortion &&
527 pPrevPortion->InNumberGrp() &&
528 static_cast<const SwNumberPortion*>(pPrevPortion)->HasFont() )
529 {
530 const SwFont* pNumberPortionFont =
531 static_cast<const SwNumberPortion*>(pPrevPortion)->GetFont();
532 pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) );
533 bAfterNumbering = true;
534 }
535 }
536 rInf.DrawBackBrush( *this );
537 if( !bAfterNumbering )
538 rInf.DrawBorder( *this );
539
540 // do we have to repaint a post it portion?
541 if( rInf.OnWin() && mpNextPortion && !mpNextPortion->Width() )
542 mpNextPortion->PrePaint( rInf, this );
543
544 // display special characters
545 if( rInf.OnWin() && rInf.GetOpt().IsTab() )
546 {
547 // filled tabs are shaded in gray
548 if( IsFilled() )
549 rInf.DrawViewOpt( *this, PortionType::Table );
550 else
551 rInf.DrawTab( *this );
552 }
553
554 // Tabs should be underlined at once
555 if( rInf.GetFont()->IsPaintBlank() )
556 {
557 // Tabs with filling/filled tabs
558 const sal_uInt16 nCharWidth = rInf.GetTextSize(OUString(' ')).Width();
559
560 // Robust:
561 if( nCharWidth )
562 {
563 // Always with kerning, also on printer!
564 sal_uInt16 nChar = Width() / nCharWidth;
565 OUStringBuffer aBuf;
566 comphelper::string::padToLength(aBuf, nChar, ' ');
567 rInf.DrawText(aBuf.makeStringAndClear(), *this, TextFrameIndex(0),
568 TextFrameIndex(nChar), true);
569 }
570 }
571
572 // Display fill characters
573 if( IsFilled() )
574 {
575 // Tabs with filling/filled tabs
576 const sal_uInt16 nCharWidth = rInf.GetTextSize(OUString(cFill)).Width();
577 OSL_ENSURE( nCharWidth, "!SwTabPortion::Paint: sophisticated tabchar" );
578
579 // Robust:
580 if( nCharWidth )
581 {
582 // Always with kerning, also on printer!
583 sal_uInt16 nChar = Width() / nCharWidth;
584 if ( cFill == '_' )
585 ++nChar; // to avoid gaps
586 OUStringBuffer aBuf;
587 comphelper::string::padToLength(aBuf, nChar, cFill);
588 rInf.DrawText(aBuf.makeStringAndClear(), *this, TextFrameIndex(0),
589 TextFrameIndex(nChar), true);
590 }
591 }
592 }
593
Paint(const SwTextPaintInfo &) const594 void SwAutoTabDecimalPortion::Paint( const SwTextPaintInfo & ) const
595 {
596 }
597
HandlePortion(SwPortionHandler & rPH) const598 void SwTabPortion::HandlePortion( SwPortionHandler& rPH ) const
599 {
600 rPH.Text( GetLen(), GetWhichPor(), Height(), Width() );
601 }
602
603 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
604