LCOV - code coverage report
Current view: top level - sw/source/core/text - txttab.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 220 251 87.6 %
Date: 2014-11-03 Functions: 11 13 84.6 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10