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