1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 #include "hintids.hxx" 32 #include <editeng/lrspitem.hxx> 33 #ifndef _SVX_TSTPITEM_HXX //autogen 34 #include <editeng/tstpitem.hxx> 35 #endif 36 #include <IDocumentSettingAccess.hxx> 37 #include <frmatr.hxx> 38 #include <SwPortionHandler.hxx> 39 40 #include "viewopt.hxx" // SwViewOptions 41 #include "txtcfg.hxx" 42 #include "portab.hxx" 43 #include "inftxt.hxx" 44 #include "itrform2.hxx" 45 #include "txtfrm.hxx" 46 #include <numrule.hxx> 47 // --> OD 2008-06-05 #i89179# 48 #include <porfld.hxx> 49 // <-- 50 51 52 /************************************************************************* 53 * SwLineInfo::GetTabStop() 54 *************************************************************************/ 55 56 //#i24363# tab stops relative to indent 57 /* Return the first tab stop that is > nSearchPos. 58 * If the tab stop is outside the print area, we 59 * return 0 if it is not the first tab stop.*/ 60 const SvxTabStop *SwLineInfo::GetTabStop( const SwTwips nSearchPos, 61 const SwTwips nRight ) const 62 { 63 for( MSHORT i = 0; i < pRuler->Count(); ++i ) 64 { 65 const SvxTabStop &rTabStop = pRuler->operator[](i); 66 if( rTabStop.GetTabPos() > SwTwips(nRight) ) 67 return i ? 0 : &rTabStop; 68 69 if( rTabStop.GetTabPos() > nSearchPos ) 70 return &rTabStop; 71 } 72 return 0; 73 } 74 75 /************************************************************************* 76 * SwLineInfo::NumberOfTabStops() 77 *************************************************************************/ 78 79 sal_uInt16 SwLineInfo::NumberOfTabStops() const 80 { 81 return pRuler->Count(); 82 } 83 84 /************************************************************************* 85 * SwTxtFormatter::NewTabPortion() 86 *************************************************************************/ 87 SwTabPortion *SwTxtFormatter::NewTabPortion( SwTxtFormatInfo &rInf, bool bAuto ) const 88 { 89 SwTabPortion *pTabPor = 0; 90 SwTabPortion *pLastTab = rInf.GetLastTab(); 91 if( pLastTab && ( pLastTab->IsTabCntPortion() || pLastTab->IsTabDecimalPortion() ) ) 92 if( pLastTab->PostFormat( rInf ) ) 93 return 0; 94 95 xub_Unicode cFill = 0; 96 xub_Unicode cDec = 0; 97 SvxTabAdjust eAdj; 98 99 KSHORT nNewTabPos; 100 { 101 const bool bRTL = pFrm->IsRightToLeft(); 102 // #i24363# tab stops relative to indent 103 // nTabLeft: The absolute value, the tab stops are relative to: Tabs origin. 104 // 105 // --> OD 2008-07-01 #i91133# 106 const bool bTabsRelativeToIndent = 107 pFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT); 108 const SwTwips nTabLeft = bRTL 109 ? pFrm->Frm().Right() - 110 ( bTabsRelativeToIndent ? GetTabLeft() : 0 ) 111 : pFrm->Frm().Left() + 112 ( bTabsRelativeToIndent ? GetTabLeft() : 0 ); 113 // <-- 114 115 // 116 // nLinePos: The absolute position, where we started the line formatting. 117 // 118 SwTwips nLinePos = GetLeftMargin(); 119 if ( bRTL ) 120 { 121 Point aPoint( nLinePos, 0 ); 122 pFrm->SwitchLTRtoRTL( aPoint ); 123 nLinePos = aPoint.X(); 124 } 125 126 // 127 // nTabPos: The current position, relative to the line start. 128 // 129 SwTwips nTabPos = rInf.GetLastTab() ? rInf.GetLastTab()->GetTabPos() : 0; 130 if( nTabPos < rInf.X() ) 131 { 132 nTabPos = rInf.X(); 133 } 134 135 // 136 // nCurrentAbsPos: The current position in absolute coordinates. 137 // 138 const SwTwips nCurrentAbsPos = bRTL ? 139 nLinePos - nTabPos : 140 nLinePos + nTabPos; 141 142 //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin 143 SwTwips nMyRight; 144 if ( pFrm->IsVertLR() ) 145 nMyRight = Left(); 146 else 147 nMyRight = Right(); 148 149 if ( pFrm->IsVertical() ) 150 { 151 Point aRightTop( nMyRight, pFrm->Frm().Top() ); 152 pFrm->SwitchHorizontalToVertical( aRightTop ); 153 nMyRight = aRightTop.Y(); 154 } 155 156 SwTwips nNextPos; 157 158 // #i24363# tab stops relative to indent 159 // nSearchPos: The current position relative to the tabs origin. 160 // 161 const SwTwips nSearchPos = bRTL ? 162 nTabLeft - nCurrentAbsPos : 163 nCurrentAbsPos - nTabLeft; 164 165 // 166 // First, we examine the tab stops set at the paragraph style or 167 // any hard set tab stops: 168 // Note: If there are no user defined tab stops, there is always a 169 // default tab stop. 170 // 171 const SvxTabStop* pTabStop = 172 aLineInf.GetTabStop( nSearchPos, nMyRight ); 173 if( pTabStop ) 174 { 175 cFill = ' ' != pTabStop->GetFill() ? pTabStop->GetFill() : 0; 176 cDec = pTabStop->GetDecimal(); 177 eAdj = pTabStop->GetAdjustment(); 178 nNextPos = pTabStop->GetTabPos(); 179 if(!bTabsRelativeToIndent && eAdj == SVX_TAB_ADJUST_DEFAULT && nSearchPos < 0) 180 { 181 //calculate default tab position of default tabs in negative indent 182 nNextPos = ( nSearchPos / nNextPos ) * nNextPos; 183 } 184 } 185 else 186 { 187 KSHORT nDefTabDist = aLineInf.GetDefTabStop(); 188 if( KSHRT_MAX == nDefTabDist ) 189 { 190 const SvxTabStopItem& rTab = 191 (const SvxTabStopItem &)pFrm->GetAttrSet()-> 192 GetPool()->GetDefaultItem( RES_PARATR_TABSTOP ); 193 if( rTab.Count() ) 194 nDefTabDist = (KSHORT)rTab.GetStart()->GetTabPos(); 195 else 196 nDefTabDist = SVX_TAB_DEFDIST; 197 aLineInf.SetDefTabStop( nDefTabDist ); 198 } 199 SwTwips nCount = nSearchPos; 200 201 //Minimum tab stop width is 1 202 if (nDefTabDist <= 0) 203 nDefTabDist = 1; 204 205 nCount /= nDefTabDist; 206 nNextPos = nCount < 0 || (!nCount && nSearchPos <= 0)? nCount * nDefTabDist :( nCount + 1 ) * nDefTabDist ; 207 // --> FME 2004-09-21 #117919 Minimum tab stop width is 1 or 51 twips: 208 const SwTwips nMinimumTabWidth = pFrm->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT) ? 0 : 50; 209 // <-- 210 if( ( bRTL && nTabLeft - nNextPos >= nCurrentAbsPos - nMinimumTabWidth ) || 211 ( !bRTL && nNextPos + nTabLeft <= nCurrentAbsPos + nMinimumTabWidth ) ) 212 { 213 nNextPos += nDefTabDist; 214 } 215 cFill = 0; 216 eAdj = SVX_TAB_ADJUST_LEFT; 217 } 218 219 // --> OD #i115705# - correction and refactoring: 220 // overrule determined next tab stop position in order to apply 221 // a tab stop at the left margin under the following conditions: 222 // - the new tab portion is inside the hanging indent 223 // - a tab stop at the left margin is allowed 224 // - the determined next tab stop is a default tab stop position OR 225 // the determined next tab stop is beyond the left margin 226 { 227 long nLeftMarginTabPos = 0; 228 { 229 if ( !bTabsRelativeToIndent ) 230 { 231 if ( bRTL ) 232 { 233 Point aPoint( Left(), 0 ); 234 pFrm->SwitchLTRtoRTL( aPoint ); 235 nLeftMarginTabPos = pFrm->Frm().Right() - aPoint.X(); 236 } 237 else 238 { 239 nLeftMarginTabPos = Left() - pFrm->Frm().Left(); 240 } 241 } 242 if( pCurr->HasForcedLeftMargin() ) 243 { 244 SwLinePortion* pPor = pCurr->GetPortion(); 245 while( pPor && !pPor->IsFlyPortion() ) 246 { 247 pPor = pPor->GetPortion(); 248 } 249 if ( pPor ) 250 { 251 nLeftMarginTabPos += pPor->Width(); 252 } 253 } 254 } 255 const bool bNewTabPortionInsideHangingIndent = 256 bRTL ? nCurrentAbsPos > nTabLeft - nLeftMarginTabPos 257 : nCurrentAbsPos < nTabLeft + nLeftMarginTabPos; 258 if ( bNewTabPortionInsideHangingIndent ) 259 { 260 // If the paragraph is not inside a list having a list tab stop following 261 // the list label or no further tab stop found in such a paragraph or 262 // the next tab stop position does not equal the list tab stop, 263 // a tab stop at the left margin can be applied. If this condition is 264 // not hold, it is overruled by compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST. 265 const bool bTabAtLeftMarginAllowed = 266 ( !aLineInf.IsListTabStopIncluded() || 267 !pTabStop || 268 nNextPos != aLineInf.GetListTabStopPosition() ) || 269 // compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST: 270 pFrm->GetTxtNode()->getIDocumentSettingAccess()-> 271 get(IDocumentSettingAccess::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST); 272 if ( bTabAtLeftMarginAllowed ) 273 { 274 if ( !pTabStop || eAdj == SVX_TAB_ADJUST_DEFAULT || 275 ( nNextPos > nLeftMarginTabPos ) ) 276 { 277 eAdj = SVX_TAB_ADJUST_DEFAULT; 278 cFill = 0; 279 nNextPos = nLeftMarginTabPos; 280 } 281 } 282 } 283 } 284 // <-- 285 286 nNextPos += bRTL ? nLinePos - nTabLeft : nTabLeft - nLinePos; 287 ASSERT( nNextPos >= 0, "GetTabStop: Don't go back!" ); 288 nNewTabPos = KSHORT(nNextPos); 289 } 290 291 if ( bAuto ) 292 { 293 if ( SVX_TAB_ADJUST_DECIMAL == eAdj && 294 // --> FME 2005-12-19 #127428# 295 1 == aLineInf.NumberOfTabStops() ) 296 // <-- 297 pTabPor = new SwAutoTabDecimalPortion( nNewTabPos, cDec, cFill ); 298 } 299 else 300 { 301 switch( eAdj ) 302 { 303 case SVX_TAB_ADJUST_RIGHT : 304 { 305 pTabPor = new SwTabRightPortion( nNewTabPos, cFill ); 306 break; 307 } 308 case SVX_TAB_ADJUST_CENTER : 309 { 310 pTabPor = new SwTabCenterPortion( nNewTabPos, cFill ); 311 break; 312 } 313 case SVX_TAB_ADJUST_DECIMAL : 314 { 315 pTabPor = new SwTabDecimalPortion( nNewTabPos, cDec, cFill ); 316 break; 317 } 318 default: 319 { 320 ASSERT( SVX_TAB_ADJUST_LEFT == eAdj || SVX_TAB_ADJUST_DEFAULT == eAdj, 321 "+SwTxtFormatter::NewTabPortion: unknown adjustment" ); 322 pTabPor = new SwTabLeftPortion( nNewTabPos, cFill ); 323 break; 324 } 325 } 326 } 327 328 // Vorhandensein von Tabulatoren anzeigen ... ist nicht mehr noetig 329 // pCurr->SetTabulation(); 330 // Aus Sicherheitsgruenden lassen wir uns die Daten errechnen 331 // pTabPor->Height( pLast->Height() ); 332 // pTabPor->SetAscent( pLast->GetAscent() ); 333 return pTabPor; 334 } 335 336 /************************************************************************* 337 * SwTabPortion::SwTabPortion() 338 *************************************************************************/ 339 340 // Die Basisklasse wird erstmal ohne alles initialisiert. 341 342 343 SwTabPortion::SwTabPortion( const KSHORT nTabPosition, const xub_Unicode cFillChar ) 344 : SwFixPortion( 0, 0 ), nTabPos(nTabPosition), cFill(cFillChar) 345 { 346 nLineLength = 1; 347 #ifdef DBG_UTIL 348 if( IsFilled() ) 349 { 350 ASSERT( ' ' != cFill, "SwTabPortion::CTOR: blanks ?!" ); 351 } 352 #endif 353 SetWhichPor( POR_TAB ); 354 } 355 356 /************************************************************************* 357 * virtual SwTabPortion::Format() 358 *************************************************************************/ 359 360 361 362 sal_Bool SwTabPortion::Format( SwTxtFormatInfo &rInf ) 363 { 364 SwTabPortion *pLastTab = rInf.GetLastTab(); 365 if( pLastTab == this ) 366 return PostFormat( rInf ); 367 if( pLastTab ) 368 pLastTab->PostFormat( rInf ); 369 return PreFormat( rInf ); 370 } 371 372 /************************************************************************* 373 * virtual SwTabPortion::FormatEOL() 374 *************************************************************************/ 375 376 377 378 void SwTabPortion::FormatEOL( SwTxtFormatInfo &rInf ) 379 { 380 if( rInf.GetLastTab() == this && !IsTabLeftPortion() ) 381 PostFormat( rInf ); 382 } 383 384 /************************************************************************* 385 * SwTabPortion::PreFormat() 386 *************************************************************************/ 387 388 389 390 sal_Bool SwTabPortion::PreFormat( SwTxtFormatInfo &rInf ) 391 { 392 ASSERT( rInf.X() <= GetTabPos(), "SwTabPortion::PreFormat: rush hour" ); 393 394 // Hier lassen wir uns nieder... 395 Fix( static_cast<sal_uInt16>(rInf.X()) ); 396 397 const bool bTabCompat = rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT); 398 399 // Die Mindestbreite eines Tabs ist immer mindestens ein Blank 400 // --> FME 2004-11-25 #i37686# In compatibility mode, the minimum width 401 // should be 1, even for non-left tab stops. 402 sal_uInt16 nMinimumTabWidth = 1; 403 // <-- 404 if ( !bTabCompat ) 405 { 406 // --> OD 2008-06-05 #i89179# 407 // tab portion representing the list tab of a list label gets the 408 // same font as the corresponding number portion 409 std::auto_ptr< SwFontSave > pSave( 0 ); 410 if ( GetLen() == 0 && 411 rInf.GetLast() && rInf.GetLast()->InNumberGrp() && 412 static_cast<SwNumberPortion*>(rInf.GetLast())->HasFont() ) 413 { 414 const SwFont* pNumberPortionFont = 415 static_cast<SwNumberPortion*>(rInf.GetLast())->GetFont(); 416 pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) ); 417 } 418 // <-- 419 XubString aTmp( ' ' ); 420 SwTxtSizeInfo aInf( rInf, aTmp ); 421 nMinimumTabWidth = aInf.GetTxtSize().Width(); 422 } 423 PrtWidth( nMinimumTabWidth ); 424 425 // Break tab stop to next line if: 426 // 1. Minmal width does not fit to line anymore. 427 // 2. An underflow event was called for the tab portion. 428 sal_Bool bFull = ( bTabCompat && rInf.IsUnderFlow() ) || 429 rInf.Width() <= rInf.X() + PrtWidth(); 430 431 // #95477# Rotated tab stops get the width of one blank 432 const sal_uInt16 nDir = rInf.GetFont()->GetOrientation( rInf.GetTxtFrm()->IsVertical() ); 433 434 if( ! bFull && 0 == nDir ) 435 { 436 const MSHORT nWhich = GetWhichPor(); 437 switch( nWhich ) 438 { 439 case POR_TABRIGHT: 440 case POR_TABDECIMAL: 441 case POR_TABCENTER: 442 { 443 if( POR_TABDECIMAL == nWhich ) 444 rInf.SetTabDecimal( 445 ((SwTabDecimalPortion*)this)->GetTabDecimal()); 446 rInf.SetLastTab( this ); 447 break; 448 } 449 case POR_TABLEFT: 450 { 451 PrtWidth( static_cast<sal_uInt16>(GetTabPos() - rInf.X()) ); 452 bFull = rInf.Width() <= rInf.X() + PrtWidth(); 453 454 // In tabulator compatibility mode, we reset the bFull flag 455 // if the tabulator is at the end of the paragraph and the 456 // tab stop position is outside the frame: 457 if ( bFull && bTabCompat && 458 rInf.GetIdx() + GetLen() == rInf.GetTxt().Len() && 459 GetTabPos() >= rInf.GetTxtFrm()->Frm().Width() ) 460 bFull = sal_False; 461 462 break; 463 } 464 default: ASSERT( !this, "SwTabPortion::PreFormat: unknown adjustment" ); 465 } 466 } 467 468 if( bFull ) 469 { 470 // Wir muessen aufpassen, dass wir nicht endlos schleifen, 471 // wenn die Breite kleiner ist, als ein Blank ... 472 if( rInf.GetIdx() == rInf.GetLineStart() && 473 // --> FME 2005-01-19 #119175# TabStop should be forced to current 474 // line if there is a fly reducing the line width: 475 !rInf.GetFly() ) 476 // <-- 477 { 478 PrtWidth( static_cast<sal_uInt16>(rInf.Width() - rInf.X()) ); 479 SetFixWidth( PrtWidth() ); 480 } 481 else 482 { 483 Height( 0 ); 484 Width( 0 ); 485 SetLen( 0 ); 486 SetAscent( 0 ); 487 SetPortion( NULL ); //????? 488 } 489 return sal_True; 490 } 491 else 492 { 493 // Ein Kunstgriff mit Effekt: Die neuen Tabportions verhalten sich nun 494 // so, wie FlyFrms, die in der Zeile stehen - inklusive Adjustment ! 495 SetFixWidth( PrtWidth() ); 496 return sal_False; 497 } 498 } 499 500 /************************************************************************* 501 * SwTabPortion::PostFormat() 502 *************************************************************************/ 503 504 505 506 sal_Bool SwTabPortion::PostFormat( SwTxtFormatInfo &rInf ) 507 { 508 const KSHORT nRight = Min( GetTabPos(), rInf.Width() ); 509 const SwLinePortion *pPor = GetPortion(); 510 511 KSHORT nPorWidth = 0; 512 while( pPor ) 513 { 514 DBG_LOOP; 515 nPorWidth = nPorWidth + pPor->Width(); 516 pPor = pPor->GetPortion(); 517 } 518 519 const MSHORT nWhich = GetWhichPor(); 520 ASSERT( POR_TABLEFT != nWhich, "SwTabPortion::PostFormat: already formatted" ); 521 const bool bTabCompat = rInf.GetTxtFrm()->GetTxtNode()->getIDocumentSettingAccess()->get(IDocumentSettingAccess::TAB_COMPAT); 522 523 // --> FME 2005-12-19 #127428# Abandon dec. tab position if line is full: 524 if ( bTabCompat && POR_TABDECIMAL == nWhich ) 525 { 526 KSHORT nPrePorWidth = static_cast<const SwTabDecimalPortion*>(this)->GetWidthOfPortionsUpToDecimalPosition(); 527 528 // no value was set => no decimal character was found 529 if ( USHRT_MAX != nPrePorWidth ) 530 { 531 if ( nPrePorWidth && nPorWidth - nPrePorWidth > rInf.Width() - nRight ) 532 { 533 nPrePorWidth += nPorWidth - nPrePorWidth - ( rInf.Width() - nRight ); 534 } 535 536 nPorWidth = nPrePorWidth - 1; 537 } 538 } 539 // <-- 540 541 if( POR_TABCENTER == nWhich ) 542 { 543 // zentrierte Tabs bereiten Probleme: 544 // Wir muessen den Anteil herausfinden, der noch auf die Zeile passt. 545 KSHORT nNewWidth = nPorWidth /2; 546 if( nNewWidth > rInf.Width() - nRight ) 547 nNewWidth = nPorWidth - (rInf.Width() - nRight); 548 nPorWidth = nNewWidth; 549 } 550 551 const KSHORT nDiffWidth = nRight - Fix(); 552 553 if( nDiffWidth > nPorWidth ) 554 { 555 const KSHORT nOldWidth = GetFixWidth(); 556 const KSHORT nAdjDiff = nDiffWidth - nPorWidth; 557 if( nAdjDiff > GetFixWidth() ) 558 PrtWidth( nAdjDiff ); 559 // Nicht erschrecken: wir muessen rInf weiterschieben. 560 // Immerhin waren wir als Rechtstab bislang nur ein Blank breit. 561 // Da wir uns jetzt aufgespannt haben, muss der Differenzbetrag 562 // auf rInf.X() addiert werden ! 563 rInf.X( rInf.X() + PrtWidth() - nOldWidth ); 564 } 565 SetFixWidth( PrtWidth() ); 566 // letzte Werte zuruecksetzen 567 rInf.SetLastTab(0); 568 if( POR_TABDECIMAL == nWhich ) 569 rInf.SetTabDecimal(0); 570 571 return rInf.Width() <= rInf.X(); 572 } 573 574 /************************************************************************* 575 * virtual SwTabPortion::Paint() 576 * 577 * Ex: LineIter::DrawTab() 578 *************************************************************************/ 579 580 void SwTabPortion::Paint( const SwTxtPaintInfo &rInf ) const 581 { 582 #ifdef DBG_UTIL 583 // Wir wollen uns die Fixbreite anzeigen 584 if( rInf.OnWin() && OPTDBG( rInf ) && 585 !rInf.GetOpt().IsPagePreview() && \ 586 !rInf.GetOpt().IsReadonly() && \ 587 SwViewOption::IsFieldShadings() ) 588 { 589 const KSHORT nTmpWidth = PrtWidth(); 590 ((SwTabPortion*)this)->PrtWidth( GetFixWidth() ); 591 rInf.DrawViewOpt( *this, POR_TAB ); 592 ((SwTabPortion*)this)->PrtWidth( nTmpWidth ); 593 } 594 #endif 595 596 // --> OD 2008-06-05 #i89179# 597 // tab portion representing the list tab of a list label gets the 598 // same font as the corresponding number portion 599 std::auto_ptr< SwFontSave > pSave( 0 ); 600 if ( GetLen() == 0 ) 601 { 602 const SwLinePortion* pPrevPortion = 603 const_cast<SwTabPortion*>(this)->FindPrevPortion( rInf.GetParaPortion() ); 604 if ( pPrevPortion && 605 pPrevPortion->InNumberGrp() && 606 static_cast<const SwNumberPortion*>(pPrevPortion)->HasFont() ) 607 { 608 const SwFont* pNumberPortionFont = 609 static_cast<const SwNumberPortion*>(pPrevPortion)->GetFont(); 610 pSave.reset( new SwFontSave( rInf, const_cast<SwFont*>(pNumberPortionFont) ) ); 611 } 612 } 613 // <-- 614 rInf.DrawBackBrush( *this ); 615 616 // do we have to repaint a post it portion? 617 if( rInf.OnWin() && pPortion && !pPortion->Width() ) 618 pPortion->PrePaint( rInf, this ); 619 620 // Darstellung von Sonderzeichen 621 if( rInf.OnWin() && rInf.GetOpt().IsTab() ) 622 { 623 // gefuellte Tabs werden grau hinterlegt. 624 if( IsFilled() ) 625 rInf.DrawViewOpt( *this, POR_TAB ); 626 else 627 rInf.DrawTab( *this ); 628 } 629 630 // 6842: Tabs sollen auf einmal wieder unterstrichen werden. 631 if( rInf.GetFont()->IsPaintBlank() ) 632 { 633 // Tabs mit Fuellung 634 XubString aTxt( ' ' ); 635 const KSHORT nCharWidth = rInf.GetTxtSize( aTxt ).Width(); 636 // robust: 637 if( nCharWidth ) 638 { 639 // 6864: immer mit Kerning, auch auf dem Drucker! 640 KSHORT nChar = Width() / nCharWidth; 641 rInf.DrawText( aTxt.Fill( nChar, ' ' ), *this, 0, nChar, sal_True ); 642 } 643 } 644 645 // Ausgabe von Fuellzeichen 646 if( IsFilled() ) 647 { 648 // Tabs mit Fuellung 649 XubString aTxt( cFill ); 650 const KSHORT nCharWidth = rInf.GetTxtSize( aTxt ).Width(); 651 #if OSL_DEBUG_LEVEL > 1 652 ASSERT( nCharWidth, "!SwTabPortion::Paint: sophisticated tabchar" ); 653 #endif 654 // robust: 655 if( nCharWidth ) 656 { 657 // 6864: immer mit Kerning, auch auf dem Drucker! 658 KSHORT nChar = Width() / nCharWidth; 659 if ( cFill == '_' ) 660 ++nChar; // damit keine Luecken entstehen (Bug 13430) 661 rInf.DrawText( aTxt.Fill( nChar, cFill ), *this, 0, nChar, sal_True ); 662 } 663 } 664 } 665 666 /************************************************************************* 667 * virtual SwAutoTabDecimalPortion::Paint() 668 *************************************************************************/ 669 670 void SwAutoTabDecimalPortion::Paint( const SwTxtPaintInfo & ) const 671 { 672 } 673 674 /************************************************************************* 675 * virtual SwTabPortion::HandlePortion() 676 *************************************************************************/ 677 678 void SwTabPortion::HandlePortion( SwPortionHandler& rPH ) const 679 { 680 rPH.Text( GetLen(), GetWhichPor() ); 681 } 682 683