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