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