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