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 10 kB image not shown  

Quelle  porlin.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 <vcl/outdev.hxx>
#include <SwPortionHandler.hxx>

#include "porlin.hxx"
#include "portxt.hxx"
#include "inftxt.hxx"
#include "pormulti.hxx"
#if OSL_DEBUG_LEVEL > 0

static bool ChkChain( SwLinePortion *pStart )
{
    SwLinePortion *pPor = pStart->GetNextPortion();
    sal_uInt16 nCount = 0;
    while( pPor )
    {
        ++nCount;
        OSL_ENSURE( nCount < 200 && pPor != pStart,
                "ChkChain(): lost in chains" );
        if( nCount >= 200 || pPor == pStart )
        {
            // the lifesaver
            pPor = pStart->GetNextPortion();
            pStart->SetNextPortion(nullptr);
            pPor->Truncate();
            pStart->SetNextPortion( pPor );
            return false;
        }
        pPor = pPor->GetNextPortion();
    }
    return true;
}
#endif

SwLinePortion::~SwLinePortion()
{
}

SwLinePortion *SwLinePortion::Compress()
{
    return GetLen() || Width() ? this : nullptr;
}

SwTwips SwLinePortion::GetViewWidth(const SwTextSizeInfo&) const { return 0; }

SwLinePortion::SwLinePortion( ) :
    mpNextPortion( nullptr ),
    mnLineLength( 0 ),
    mnAscent( 0 ),
    mnHangingBaseline( 0 ),
    mnWhichPor( PortionType::NONE ),
    m_bJoinBorderWithPrev(false),
    m_bJoinBorderWithNext(false),
    m_bIsFieldmarkText(false)
{
}

void SwLinePortion::PrePaint( const SwTextPaintInfo& rInf,
                              const SwLinePortion* pLast ) const
{
    OSL_ENSURE( rInf.OnWin(), "SwLinePortion::PrePaint: don't prepaint on a printer");
    OSL_ENSURE( !Width(), "SwLinePortion::PrePaint: For Width()==0 only!");

    const SwTwips nViewWidth = GetViewWidth(rInf);

    if( ! nViewWidth )
        return;

    const SwTwips nHalfView = nViewWidth / 2;
    SwTwips nLastWidth = pLast->Width() + pLast->ExtraBlankWidth();

    if ( pLast->InSpaceGrp() && rInf.GetSpaceAdd(/*bShrink=*/true) )
        nLastWidth += pLast->CalcSpacing( rInf.GetSpaceAdd(/*bShrink=*/true), rInf );

    SwTwips nPos;
    SwTextPaintInfo aInf( rInf );

    const bool bBidiPor = rInf.GetTextFrame()->IsRightToLeft() !=
                          bool( vcl::text::ComplexTextLayoutFlags::BiDiRtl & rInf.GetOut()->GetLayoutMode() );

    Degree10 nDir = bBidiPor ?
                  1800_deg10 :
                  rInf.GetFont()->GetOrientation( rInf.GetTextFrame()->IsVertical() );

    // pLast == this *only* for the 1st portion in the line so nLastWidth is 0;
    // allow this too, will paint outside the frame but might look better...
    if (nLastWidth > nHalfView || pLast == this)
    {
        switch (nDir.get())
        {
        case 0:
            nPos = rInf.X();
            nPos += nLastWidth - nHalfView;
            aInf.X( nPos );
            break;
        case 900:
            nPos = rInf.Y();
            nPos -= nLastWidth - nHalfView;
            aInf.Y( nPos );
            break;
        case 1800:
            nPos = rInf.X();
            nPos -= nLastWidth - nHalfView;
            aInf.X( nPos );
            break;
        case 2700:
            nPos = rInf.Y();
            nPos += nLastWidth - nHalfView;
            aInf.Y( nPos );
            break;
        }
    }

    SwLinePortion *pThis = const_cast<SwLinePortion*>(this);
    pThis->Width( nViewWidth );
    Paint( aInf );
    pThis->Width(0);
}

void SwLinePortion::CalcTextSize( const SwTextSizeInfo &rInf )
{
    if( GetLen() == rInf.GetLen()  )
        *static_cast<SwPositiveSize*>(this) = GetTextSize( rInf );
    else
    {
        SwTextSizeInfo aInf( rInf );
        aInf.SetLen( GetLen() );
        *static_cast<SwPositiveSize*>(this) = GetTextSize( aInf );
    }
}

// all following portions will be deleted
void SwLinePortion::Truncate_()
{
    SwLinePortion *pPos = mpNextPortion;
    do
    {
        OSL_ENSURE( pPos != this"SwLinePortion::Truncate: loop" );
        SwLinePortion *pLast = pPos;
        pPos = pPos->GetNextPortion();
        pLast->SetNextPortion( nullptr );
        delete pLast;

    } while( pPos );

    mpNextPortion = nullptr;
}

// It always will be inserted after us.
SwLinePortion *SwLinePortion::Insert( SwLinePortion *pIns )
{
    pIns->FindLastPortion()->SetNextPortion( mpNextPortion );
    SetNextPortion( pIns );
#if OSL_DEBUG_LEVEL > 0
    ChkChain( this );
#endif
    return pIns;
}

SwLinePortion *SwLinePortion::FindLastPortion()
{
    SwLinePortion *pPos = this;
    // Find the end and link pLinPortion to the last one...
    while( pPos->GetNextPortion() )
    {
        pPos = pPos->GetNextPortion();
    }
    return pPos;
}

SwLinePortion *SwLinePortion::Append( SwLinePortion *pIns )
{
    SwLinePortion *pPos = FindLastPortion();
    pPos->SetNextPortion( pIns );
    pIns->SetNextPortion( nullptr );
#if OSL_DEBUG_LEVEL > 0
    ChkChain( this );
#endif
    return pIns;
}

SwLinePortion *SwLinePortion::Cut( SwLinePortion *pVictim )
{
    SwLinePortion *pPrev = pVictim->FindPrevPortion( this );
    OSL_ENSURE( pPrev, "SwLinePortion::Cut(): can't cut" );
    // note: if pVictim is a follow then clearing pPrev's m_bHasFollow here is
    // tricky because it could be that the HookChar inserted a tab portion
    // between 2 field portions
    pPrev->SetNextPortion( pVictim->GetNextPortion() );
    pVictim->SetNextPortion(nullptr);
    return pVictim;
}

SwLinePortion *SwLinePortion::FindPrevPortion( const SwLinePortion *pRoot )
{
    OSL_ENSURE( pRoot != this"SwLinePortion::FindPrevPortion(): invalid root" );
    SwLinePortion *pPos = const_cast<SwLinePortion*>(pRoot);
    while( pPos->GetNextPortion() && pPos->GetNextPortion() != this )
    {
        pPos = pPos->GetNextPortion();
    }
    OSL_ENSURE( pPos->GetNextPortion(),
            "SwLinePortion::FindPrevPortion: blowing in the wind");
    return pPos;
}

TextFrameIndex SwLinePortion::GetModelPositionForViewPoint(const SwTwips nOfst) const
{
    if( nOfst > ( PrtWidth() / 2 ) )
        return GetLen();
    else
        return TextFrameIndex(0);
}

SwPositiveSize SwLinePortion::GetTextSize( const SwTextSizeInfo & ) const
{
    OSL_ENSURE( false"SwLinePortion::GetTextSize: don't ask me about sizes, "
                   "I'm only a stupid SwLinePortion" );
    return SwPositiveSize();
}

bool SwLinePortion::Format( SwTextFormatInfo &rInf )
{
    if( rInf.X() > rInf.Width() )
    {
        Truncate();
        rInf.SetUnderflow( this );
        return true;
    }

    const SwLinePortion *pLast = rInf.GetLast();
    Height( pLast->Height() );
    SetAscent( pLast->GetAscent() );
    const SwTwips nNewWidth = rInf.X() + PrtWidth();
    // Only portions with true width can return true
    // Notes for example never set bFull==true
    if( rInf.Width() <= nNewWidth && PrtWidth() && ! IsKernPortion() )
    {
        Truncate();
        if( nNewWidth > rInf.Width() )
            PrtWidth( nNewWidth - rInf.Width() );
        rInf.GetLast()->FormatEOL( rInf );
        return true;
    }
    return false;
}

// Format end of line

void SwLinePortion::FormatEOL( SwTextFormatInfo & )
{ }

void SwLinePortion::Move(SwTextPaintInfo & rInf) const
{
    bool bB2T = rInf.GetDirection() == DIR_BOTTOM2TOP;
    const bool bFrameDir = rInf.GetTextFrame()->IsRightToLeft();
    bool bCounterDir = ( ! bFrameDir && DIR_RIGHT2LEFT == rInf.GetDirection() ) ||
                       (   bFrameDir && DIR_LEFT2RIGHT == rInf.GetDirection() );

    SwTwips nTmp = PrtWidth() + ExtraBlankWidth();
    if ( InSpaceGrp() && rInf.GetSpaceAdd(/*bShrink=*/true) )
    {
        nTmp += CalcSpacing( rInf.GetSpaceAdd(/*bShrink=*/true), rInf );
        if( rInf.IsRotated() )
            rInf.Y( rInf.Y() + ( bB2T ? -nTmp : nTmp ) );
        else if ( bCounterDir )
            rInf.X( rInf.X() - nTmp );
        else
            rInf.X( rInf.X() + nTmp );
    }
    else
    {
        if( InFixMargGrp() && !IsMarginPortion() )
        {
            rInf.IncSpaceIdx();
            rInf.IncKanaIdx();
        }
        if( rInf.IsRotated() )
            rInf.Y(rInf.Y() + (bB2T ? -nTmp : nTmp));
        else if ( bCounterDir )
            rInf.X(rInf.X() - nTmp);
        else
            rInf.X(rInf.X() + nTmp);
    }
    if (IsMultiPortion() && static_cast<SwMultiPortion const*>(this)->HasTabulator())
        rInf.IncSpaceIdx();

    rInf.SetIdx( rInf.GetIdx() + GetLen() );
}

SwTwips SwLinePortion::CalcSpacing( tools::Long , const SwTextSizeInfo & ) const
{
    return 0;
}

bool SwLinePortion::GetExpText( const SwTextSizeInfo &, OUString & ) const
{
    return false;
}

void SwLinePortion::HandlePortion( SwPortionHandler& rPH ) const
{
    rPH.Special( GetLen(), OUString(), GetWhichPor() );
}

void SwLinePortion::dumpAsXml(xmlTextWriterPtr pWriter, const OUString& rText, TextFrameIndex& nOffset) const
{
    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwLinePortion"));
    dumpAsXmlAttributes(pWriter, rText, nOffset);
    nOffset += GetLen();

    (void)xmlTextWriterEndElement(pWriter);
}

void SwLinePortion::dumpAsXmlAttributes(xmlTextWriterPtr pWriter, std::u16string_view rText, TextFrameIndex nOffset) const
{
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p"this);
    (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("symbol"), BAD_CAST(typeid(*this).name()));
    (void)xmlTextWriterWriteAttribute(
        pWriter, BAD_CAST("width"),
        BAD_CAST(OString::number(Width()).getStr()));
    (void)xmlTextWriterWriteAttribute(
        pWriter, BAD_CAST("height"),
        BAD_CAST(OString::number(Height()).getStr()));
    (void)xmlTextWriterWriteAttribute(
        pWriter, BAD_CAST("length"),
        BAD_CAST(OString::number(static_cast<sal_Int32>(mnLineLength)).getStr()));
    (void)xmlTextWriterWriteAttribute(
        pWriter, BAD_CAST("type"),
        BAD_CAST(sw::PortionTypeToString(GetWhichPor())));
    OUString aText( rText.substr(sal_Int32(nOffset), sal_Int32(GetLen())) );
    for (int i = 0; i < 32; ++i)
        aText = aText.replace(i, '*');
    (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("portion"),
                                      BAD_CAST(aText.toUtf8().getStr()));
}

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

Messung V0.5
C=95 H=98 G=96

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© 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.