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