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