Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sw/source/core/text/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 24 kB image not shown  

Quelle  txttab.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <hintids.hxx>
#include <comphelper/string.hxx>
#include <editeng/tstpitem.hxx>
#include <rtl/ustrbuf.hxx>
#include <IDocumentSettingAccess.hxx>
#include <doc.hxx>
#include <SwPortionHandler.hxx>

#include <viewopt.hxx>
#include "portab.hxx"
#include "inftxt.hxx"
#include "itrform2.hxx"
#include <txtfrm.hxx>
#include "porfld.hxx"
#include <memory>

/**
 * #i24363# tab stops relative to indent
 *
 * Return the first tab stop that is > nSearchPos.
 * If the tab stop is outside the print area, we
 * return 0 if it is not the first tab stop.
 */

const SvxTabStop* SwLineInfo::GetTabStop(const SwTwips nSearchPos, SwTwips& nRightconst
{
    for( sal_uInt16 i = 0; i < m_oRuler->Count(); ++i )
    {
        const SvxTabStop &rTabStop = m_oRuler->operator[](i);
        if (nRight && rTabStop.GetTabPos() > nRight)
        {
            // Consider the first tabstop to always be in-bounds.
            if (!i)
                nRight = rTabStop.GetTabPos();
            return i ? nullptr : &rTabStop;
        }
        if( rTabStop.GetTabPos() > nSearchPos )
        {
            if (!i && !nRight)
                nRight = rTabStop.GetTabPos();
            return &rTabStop;
        }
    }
    return nullptr;
}

sal_uInt16 SwLineInfo::NumberOfTabStops() const
{
    return m_oRuler->Count();
}

SwTabPortion *SwTextFormatter::NewTabPortion( SwTextFormatInfo &rInf, bool bAuto ) const
{
    IDocumentSettingAccess const& rIDSA(rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess());
    const bool bTabOverMargin = rIDSA.get(DocumentSettingId::TAB_OVER_MARGIN);
    const bool bTabOverSpacing = rIDSA.get(DocumentSettingId::TAB_OVER_SPACING);
    const bool bTabsRelativeToIndent = rIDSA.get(DocumentSettingId::TABS_RELATIVE_TO_INDENT);

    // Update search location - since Center/Decimal tabstops' width is dependent on the following text.
    SwTabPortion* pTmpLastTab = rInf.GetLastTab();
    if (pTmpLastTab && (pTmpLastTab->IsTabCenterPortion() || pTmpLastTab->IsTabDecimalPortion()))
        pTmpLastTab->PostFormat(rInf);

    sal_Unicode cFill = 0;
    sal_Unicode cDec = 0;
    SvxTabAdjust eAdj;

    SwTwips nNewTabPos;
    bool bAutoTabStop = true;
    {
        const bool bRTL = m_pFrame->IsRightToLeft();
        // #i24363# tab stops relative to indent
        // nTabLeft: The absolute value, the tab stops are relative to: Tabs origin.

        // #i91133#
        const SwTwips nTabLeft = bRTL
                                 ? m_pFrame->getFrameArea().Right() -
                                   ( bTabsRelativeToIndent ? GetTabLeft() : 0 )
                                 : m_pFrame->getFrameArea().Left() +
                                   ( bTabsRelativeToIndent ? GetTabLeft() : 0 );

        // The absolute position, where we started the line formatting
        SwTwips nLinePos = GetLeftMargin();
        if ( bRTL )
        {
            Point aPoint( nLinePos, 0 );
            m_pFrame->SwitchLTRtoRTL( aPoint );
            nLinePos = aPoint.X();
        }

        // The current position, relative to the line start
        SwTwips nTabPos = rInf.GetLastTab() ? rInf.GetLastTab()->GetTabPos() : 0;
        if( nTabPos < rInf.X() )
        {
            nTabPos = rInf.X();
        }

        // The current position in absolute coordinates
        const SwTwips nCurrentAbsPos = bRTL ?
                                       nLinePos - nTabPos :
                                       nLinePos + nTabPos;

        SwTwips nMyRight;
        if ( m_pFrame->IsVertLR() )
           nMyRight = Left();
        else
           nMyRight = Right();

        if ( m_pFrame->IsVertical() )
        {
            Point aRightTop( nMyRight, m_pFrame->getFrameArea().Top() );
            m_pFrame->SwitchHorizontalToVertical( aRightTop );
            nMyRight = aRightTop.Y();
        }

        SwTwips nNextPos = 0;
        bool bAbsoluteNextPos = false;

        // #i24363# tab stops relative to indent
        // nSearchPos: The current position relative to the tabs origin
        const SwTwips nSearchPos = bRTL ?
                                   nTabLeft - nCurrentAbsPos :
                                   nCurrentAbsPos - nTabLeft;

        // First, we examine the tab stops set at the paragraph style or
        // any hard set tab stops:
        // Note: If there are no user defined tab stops, there is always a
        // default tab stop.
        const SwTwips nOldRight = nMyRight;
        // Accept left-tabstops beyond the paragraph margin for bTabOverSpacing
        if (bTabOverSpacing || bTabOverMargin)
            nMyRight = 0;
        const SvxTabStop* pTabStop = m_aLineInf.GetTabStop( nSearchPos, nMyRight );
        if (!nMyRight)
            nMyRight = nOldRight;
        if (pTabStop)
        {
            cFill = ' ' != pTabStop->GetFill() ? pTabStop->GetFill() : 0;
            cDec = pTabStop->GetDecimal();
            eAdj = pTabStop->GetAdjustment();
            nNextPos = pTabStop->GetTabPos();
            if(!bTabsRelativeToIndent && eAdj == SvxTabAdjust::Default && nSearchPos < 0)
            {
                //calculate default tab position of default tabs in negative indent
                nNextPos = ( nSearchPos / nNextPos ) * nNextPos;
            }
            else if (pTabStop->GetTabPos() > nMyRight
                     && pTabStop->GetAdjustment() != SvxTabAdjust::Left)
            {
                // A rather special situation. The tabstop found is:
                // 1.) in a document compatible with MS formats
                // 2.) not a left tabstop.
                // 3.) not the first tabstop (in that case nMyRight was adjusted to match tabPos).
                // 4.) beyond the end of the text area
                // Therefore, they act like right-tabstops at the edge of the para area.
                // This benefits DOCX 2013+, and doesn't hurt the earlier formats,
                // since up till now these were just treated as automatic tabstops.
                eAdj = SvxTabAdjust::Right;
                bAbsoluteNextPos = true;
                // TODO: unclear if old Word has an upper limit for center/right
                // tabs, UI allows setting 55.87cm max which is still one line
                if (!bTabOverMargin || o3tl::toTwips(558, o3tl::Length::mm) < nNextPos)
                {
                    nNextPos = rInf.Width();
                }
            }
            bAutoTabStop = false;
        }
        else
        {
            SwTwips nDefTabDist = m_aLineInf.GetDefTabStop();
            if (std::numeric_limits<SwTwips>::max() == nDefTabDist)
            {
                const SvxTabStopItem& rTab =
                    m_pFrame->GetAttrSet()->GetPool()->GetUserOrPoolDefaultItem( RES_PARATR_TABSTOP );
                if( rTab.Count() )
                    nDefTabDist = rTab[0].GetTabPos();
                else
                    nDefTabDist = SVX_TAB_DEFDIST;
                m_aLineInf.SetDefTabStop( nDefTabDist );
            }
            SwTwips nCount = nSearchPos;

            // Minimum tab stop width is 1
            if (nDefTabDist <= 0)
                nDefTabDist = 1;

            nCount /= nDefTabDist;
            nNextPos = ( nCount < 0 || ( !nCount && nSearchPos <= 0 ) )
                       ? ( nCount * nDefTabDist )
                       : ( ( nCount + 1 ) * nDefTabDist );

            // --> FME 2004-09-21 #117919 Minimum tab stop width is 1 or 51 twips:
            const SwTwips nMinimumTabWidth = m_pFrame->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT) ? 0 : 50;
            if( (  bRTL && nTabLeft - nNextPos >= nCurrentAbsPos - nMinimumTabWidth ) ||
                 ( !bRTL && nNextPos + nTabLeft <= nCurrentAbsPos + nMinimumTabWidth  ) )
            {
                nNextPos += nDefTabDist;
            }
            cFill = 0;
            eAdj = SvxTabAdjust::Left;
        }

        // #i115705# - correction and refactoring:
        // overrule determined next tab stop position in order to apply
        // a tab stop at the left margin under the following conditions:
        // - the new tab portion is inside the hanging indent
        // - a tab stop at the left margin is allowed
        // - the determined next tab stop is a default tab stop position OR
        //   the determined next tab stop is beyond the left margin
        {
            tools::Long nLeftMarginTabPos = 0;
            {
                if ( !bTabsRelativeToIndent )
                {
                    if ( bRTL )
                    {
                        Point aPoint( Left(), 0 );
                        m_pFrame->SwitchLTRtoRTL( aPoint );
                        nLeftMarginTabPos = m_pFrame->getFrameArea().Right() - aPoint.X();
                    }
                    else
                    {
                        nLeftMarginTabPos = Left() - m_pFrame->getFrameArea().Left();
                    }
                }
                if( m_pCurr->HasForcedLeftMargin() )
                {
                    SwLinePortion* pPor = m_pCurr->GetNextPortion();
                    while( pPor && !pPor->IsFlyPortion() )
                    {
                        pPor = pPor->GetNextPortion();
                    }
                    if ( pPor )
                    {
                        nLeftMarginTabPos += pPor->Width();
                    }
                }
            }
            const bool bNewTabPortionInsideHangingIndent =
                        bRTL ? nCurrentAbsPos > nTabLeft - nLeftMarginTabPos
                             : nCurrentAbsPos < nTabLeft + nLeftMarginTabPos;
            if ( bNewTabPortionInsideHangingIndent )
            {
                // If the paragraph is not inside a list having a list tab stop following
                // the list label or no further tab stop found in such a paragraph or
                // the next tab stop position does not equal the list tab stop,
                // a tab stop at the left margin can be applied. If this condition is
                // not hold, it is overruled by compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST.
                const bool bTabAtLeftMarginAllowed =
                    ( !m_aLineInf.IsListTabStopIncluded() ||
                      !pTabStop ||
                      nNextPos != m_aLineInf.GetListTabStopPosition() ) ||
                    // compatibility option TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST:
                    m_pFrame->GetDoc().getIDocumentSettingAccess().
                        get(DocumentSettingId::TAB_AT_LEFT_INDENT_FOR_PARA_IN_LIST);
                if ( bTabAtLeftMarginAllowed )
                {
                    if ( !pTabStop || eAdj == SvxTabAdjust::Default ||
                         ( nNextPos > nLeftMarginTabPos ) )
                    {
                        eAdj = SvxTabAdjust::Default;
                        cFill = 0;
                        nNextPos = nLeftMarginTabPos;
                    }
                }
            }
        }

        if (!bAbsoluteNextPos)
            nNextPos += bRTL ? nLinePos - nTabLeft : nTabLeft - nLinePos;
        OSL_ENSURE( nNextPos >= 0, "GetTabStop: Don't go back!" );
        nNewTabPos = nNextPos;
    }

    SwTabPortion *pTabPor = nullptr;
    if ( bAuto )
    {
        if ( SvxTabAdjust::Decimal == eAdj &&
             1 == m_aLineInf.NumberOfTabStops() )
            pTabPor = new SwAutoTabDecimalPortion( nNewTabPos, cDec, cFill );
    }
    else
    {
        switch( eAdj )
        {
        case SvxTabAdjust::Right :
            {
                pTabPor = new SwTabRightPortion( nNewTabPos, cFill );
                break;
            }
        case SvxTabAdjust::Center :
            {
                pTabPor = new SwTabCenterPortion( nNewTabPos, cFill );
                break;
            }
        case SvxTabAdjust::Decimal :
            {
                pTabPor = new SwTabDecimalPortion( nNewTabPos, cDec, cFill );
                break;
            }
        default:
            {
                OSL_ENSURE( SvxTabAdjust::Left == eAdj || SvxTabAdjust::Default == eAdj,
                    "+SwTextFormatter::NewTabPortion: unknown adjustment" );
                pTabPor = new SwTabLeftPortion( nNewTabPos, cFill, bAutoTabStop );
                break;
            }
        }
    }
    if (pTabPor)
        rInf.UpdateTabSeen(pTabPor->GetWhichPor());

    return pTabPor;
}

/**
 * The base class is initialized without setting anything
 */

SwTabPortion::SwTabPortion( const SwTwips nTabPosition, const sal_Unicode cFillChar, const bool bAutoTab )
    : m_nTabPos(nTabPosition), m_cFill(cFillChar), m_bAutoTabStop( bAutoTab )
{
    mnLineLength = TextFrameIndex(1);
    OSL_ENSURE(!IsFilled() || ' ' != m_cFill, "SwTabPortion::CTOR: blanks ?!");
    SetWhichPor( PortionType::Tab );
}

bool SwTabPortion::Format( SwTextFormatInfo &rInf )
{
    SwTabPortion *pLastTab = rInf.GetLastTab();
    if( pLastTab == this )
        return PostFormat( rInf );
    if( pLastTab )
        pLastTab->PostFormat( rInf );
    return PreFormat(rInf, pLastTab);
}

void SwTabPortion::FormatEOL( SwTextFormatInfo &rInf )
{
    if( rInf.GetLastTab() == this )
        PostFormat( rInf );
}

bool SwTabPortion::PreFormat(SwTextFormatInfo &rInf, SwTabPortion const*const pLastTab)
{
    OSL_ENSURE( rInf.X() <= GetTabPos(), "SwTabPortion::PreFormat: rush hour" );

    // Here we settle down ...
    SetFix(rInf.X());

    IDocumentSettingAccess const& rIDSA(rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess());
    const bool bTabCompat = rIDSA.get(DocumentSettingId::TAB_COMPAT);
    const bool bTabOverflow = rIDSA.get(DocumentSettingId::TAB_OVERFLOW);
    const bool bTabOverMargin = rIDSA.get(DocumentSettingId::TAB_OVER_MARGIN);
    const bool bTabOverSpacing = rIDSA.get(DocumentSettingId::TAB_OVER_SPACING);
    const tools::Long nTextFrameWidth = rInf.GetTextFrame()->getFrameArea().Width();

    // The minimal width of a tab is one blank at least.
    // #i37686# In compatibility mode, the minimum width
    // should be 1, even for non-left tab stops.
    SwTwips nMinimumTabWidth = 1;
    if ( !bTabCompat )
    {
        // #i89179#
        // tab portion representing the list tab of a list label gets the
        // same font as the corresponding number portion
        std::optional< SwFontSave > oSave;
        if ( GetLen() == TextFrameIndex(0) &&
             rInf.GetLast() && rInf.GetLast()->InNumberGrp() &&
             static_cast<SwNumberPortion*>(rInf.GetLast())->HasFont() )
        {
            const SwFont* pNumberPortionFont =
                    static_cast<SwNumberPortion*>(rInf.GetLast())->GetFont();
            oSave.emplace( rInf, const_cast<SwFont*>(pNumberPortionFont) );
        }
        OUString aTmp( ' ' );
        SwTextSizeInfo aInf( rInf, &aTmp );
        nMinimumTabWidth = aInf.GetTextSize().Width();
    }
    PrtWidth( nMinimumTabWidth );

    // Break tab stop to next line if:
    // 1. Minimal width does not fit to line anymore.
    // 2. An underflow event was called for the tab portion.
    bool bFull = ( bTabCompat && rInf.IsUnderflow() ) ||
             (rInf.Width() <= rInf.X() + PrtWidth() && rInf.X() <= rInf.Width()
              && (!bTabOverMargin || !pLastTab));

    // #95477# Rotated tab stops get the width of one blank
    const Degree10 nDir = rInf.GetFont()->GetOrientation( rInf.GetTextFrame()->IsVertical() );

    if( ! bFull && 0_deg10 == nDir )
    {
        const PortionType nWhich = GetWhichPor();
        switch( nWhich )
        {
            case PortionType::TabRight:
            case PortionType::TabDecimal:
            case PortionType::TabCenter:
            {
                if( PortionType::TabDecimal == nWhich )
                    rInf.SetTabDecimal(
                        static_cast<SwTabDecimalPortion*>(this)->GetTabDecimal());
                rInf.SetLastTab( this );
                break;
            }
            case PortionType::TabLeft:
            {
                if ((bTabOverMargin || bTabOverSpacing) && GetTabPos() > rInf.Width()
                    && (!m_bAutoTabStop || rInf.Width() <= rInf.X()))
                {
                    if (bTabOverMargin || GetTabPos() < nTextFrameWidth)
                    {   // handle this case in PostFormat
                        rInf.SetLastTab(this);
                        break;
                    }
                    else
                    {
                        assert(!bTabOverMargin && bTabOverSpacing && GetTabPos() >= nTextFrameWidth);
                        bFull = true;
                        break;
                    }
                }

                PrtWidth(GetTabPos() - rInf.X());
                bFull = rInf.Width() <= rInf.X() + PrtWidth();

                // In tabulator compatibility mode, we reset the bFull flag
                // if the tabulator is at the end of the paragraph and the
                // tab stop position is outside the frame:
                bool bAtParaEnd = rInf.GetIdx() + GetLen() == TextFrameIndex(rInf.GetText().getLength());
                if ( bFull && bTabCompat &&
                     ( ( bTabOverflow && ( rInf.IsTabOverflow() || !m_bAutoTabStop ) ) || bAtParaEnd ) &&
                     GetTabPos() >= nTextFrameWidth)
                {
                    bFull = false;
                    if ( bTabOverflow && !m_bAutoTabStop )
                        rInf.SetTabOverflow( true );
                }

                break;
            }
            default: OSL_ENSURE( false"SwTabPortion::PreFormat: unknown adjustment" );
        }
    }

    if( bFull )
    {
        // We have to look for endless loops, if the width is smaller than one blank
        if( rInf.GetIdx() == rInf.GetLineStart() &&
            // #119175# TabStop should be forced to current
            // line if there is a fly reducing the line width:
            !rInf.GetFly() )
        {
            PrtWidth(std::max(SwTwips{0}, rInf.Width() - rInf.X()));
            SetFixWidth( PrtWidth() );
        }
        else
        {
            Height( 0 );
            Width( 0 );
            SetLen( TextFrameIndex(0) );
            SetAscent( 0 );
            SetNextPortion( nullptr ); //?????
        }
        return true;
    }
    else
    {
        // A trick with impact: The new Tabportions now behave like
        // FlyFrames, located in the line - including adjustment !
        SetFixWidth( PrtWidth() );
        return false;
    }
}

bool SwTabPortion::PostFormat( SwTextFormatInfo &rInf )
{
    bool bTabOverMargin = rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
        DocumentSettingId::TAB_OVER_MARGIN);
    bool bTabOverSpacing = rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
        DocumentSettingId::TAB_OVER_SPACING);
    if (rInf.GetTextFrame()->IsInSct())
        bTabOverMargin = false;

    // If the tab position is larger than the right margin, it gets scaled down by default.
    // However, if compat mode enabled, we allow tabs to go over the margin: the rest of the paragraph is not broken into lines.
    const SwTwips nRight
        = bTabOverMargin
              ? GetTabPos()
              : bTabOverSpacing
                    ? std::min(GetTabPos(), rInf.GetTextFrame()->getFrameArea().Right())
                    : std::min(GetTabPos(), rInf.Width());
    const SwLinePortion *pPor = GetNextPortion();

    SwTwips nPorWidth = 0;
    while( pPor )
    {
        nPorWidth = nPorWidth + pPor->Width();
        pPor = pPor->GetNextPortion();
    }

    const PortionType nWhich = GetWhichPor();
    const bool bTabCompat = rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT);

    if ((bTabOverMargin || bTabOverSpacing) && PortionType::TabLeft == nWhich)
    {
        nPorWidth = 0;
    }

    // #127428# Abandon dec. tab position if line is full
    if ( bTabCompat && PortionType::TabDecimal == nWhich )
    {
        SwTwips nPrePorWidth = static_cast<const SwTabDecimalPortion*>(this)->GetWidthOfPortionsUpToDecimalPosition();

        // no value was set => no decimal character was found
        if (std::numeric_limits<SwTwips>::max() != nPrePorWidth)
        {
            if ( !bTabOverMargin && nPrePorWidth && nPorWidth - nPrePorWidth > rInf.Width() - nRight )
            {
                nPrePorWidth += nPorWidth - nPrePorWidth - ( rInf.Width() - nRight );
            }

            nPorWidth = nPrePorWidth - 1;
        }
    }

    if( PortionType::TabCenter == nWhich )
    {
        // centered tabs are problematic:
        // We have to detect how much fits into the line.
        SwTwips nNewWidth = nPorWidth / 2;
        if (!bTabOverMargin && !bTabOverSpacing && nNewWidth > rInf.Width() - nRight)
            nNewWidth = nPorWidth - (rInf.Width() - nRight);
        nPorWidth = nNewWidth;
    }

    const SwTwips nDiffWidth = nRight - GetFix();

    if( nDiffWidth > nPorWidth )
    {
        const SwTwips nOldWidth = GetFixWidth();
        const SwTwips nAdjDiff = nDiffWidth - nPorWidth;
        if( nAdjDiff > GetFixWidth() )
            PrtWidth( nAdjDiff );
        // Don't be afraid: we have to move rInf further.
        // The right-tab till now only had the width of one blank.
        // Now that we stretched, the difference had to be added to rInf.X() !
        rInf.X( rInf.X() + PrtWidth() - nOldWidth );
    }
    SetFixWidth( PrtWidth() );
    // reset last values
    rInf.SetLastTab(nullptr);
    if( PortionType::TabDecimal == nWhich )
        rInf.SetTabDecimal(0);

    return rInf.Width() <= rInf.X();
}

/**
 * Ex: LineIter::DrawTab()
 */

void SwTabPortion::Paint( const SwTextPaintInfo &rInf ) const
{
    // #i89179#
    // tab portion representing the list tab of a list label gets the
    // same font as the corresponding number portion
    std::optional< SwFontSave > oSave;
    bool bAfterNumbering = false;
    if (GetLen() == TextFrameIndex(0))
    {
        const SwLinePortion* pPrevPortion =
            const_cast<SwTabPortion*>(this)->FindPrevPortion( rInf.GetParaPortion() );
        if ( pPrevPortion &&
             pPrevPortion->InNumberGrp() &&
             static_cast<const SwNumberPortion*>(pPrevPortion)->HasFont() )
        {
            const SwFont* pNumberPortionFont =
                    static_cast<const SwNumberPortion*>(pPrevPortion)->GetFont();
            oSave.emplace( rInf, const_cast<SwFont*>(pNumberPortionFont) );
            bAfterNumbering = true;
        }
    }
    rInf.DrawBackBrush( *this );
    if( !bAfterNumbering )
        rInf.DrawBorder( *this );

    // do we have to repaint a post it portion?
    if( rInf.OnWin() && mpNextPortion && !mpNextPortion->Width() )
        mpNextPortion->PrePaint( rInf, this );

    // display special characters
    if( rInf.OnWin() && rInf.GetOpt().IsTab() )
    {
        // filled tabs are shaded in gray
        if( IsFilled() )
            rInf.DrawViewOpt( *this, PortionType::Tab );
        else
            rInf.DrawTab( *this );
    }

    // Tabs should be underlined at once
    if( rInf.GetFont()->IsPaintBlank() )
    {
        // Tabs with filling/filled tabs
        const SwTwips nCharWidth = rInf.GetTextSize(OUString(' ')).Width();

        // Robust:
        if( nCharWidth )
        {
            // Always with kerning, also on printer!
            sal_Int32 nChar = Width() / nCharWidth;
            rInf.DrawText(OUString::Concat(RepeatedUChar(' ', nChar)), *this, TextFrameIndex(0),
                            TextFrameIndex(nChar), true);
        }
    }

    // Display fill characters
    if( !IsFilled() )
        return;

    // Tabs with filling/filled tabs
    const SwTwips nCharWidth = rInf.GetTextSize(OUString(m_cFill)).Width();
    OSL_ENSURE( nCharWidth, "!SwTabPortion::Paint: sophisticated tabchar" );

    // Robust:
    if( nCharWidth )
    {
        // Always with kerning, also on printer!
        sal_Int32 nChar = Width() / nCharWidth;
        if ( m_cFill == '_' )
            ++nChar; // to avoid gaps
        rInf.DrawText(OUString::Concat(RepeatedUChar(m_cFill, nChar)), *this, TextFrameIndex(0),
                        TextFrameIndex(nChar), true);
    }
}

void SwAutoTabDecimalPortion::Paint( const SwTextPaintInfo & ) const
{
}

void SwTabPortion::HandlePortion( SwPortionHandler& rPH ) const
{
    rPH.Text( GetLen(), GetWhichPor() );
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=87 H=98 G=92

¤ Dauer der Verarbeitung: 0.36 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.