Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  txtfld.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 <fmtfld.hxx>
#include <txtfld.hxx>
#include <charfmt.hxx>
#include <fmtautofmt.hxx>

#include <viewsh.hxx>
#include <doc.hxx>
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <ndtxt.hxx>
#include <fldbas.hxx>
#include <viewopt.hxx>
#include <flyfrm.hxx>
#include <viewimp.hxx>
#include <swfont.hxx>
#include <swmodule.hxx>
#include "porfld.hxx"
#include "porftn.hxx"
#include "porref.hxx"
#include "portox.hxx"
#include "porfly.hxx"
#include "itrform2.hxx"
#include <chpfld.hxx>
#include <dbfld.hxx>
#include <expfld.hxx>
#include <docufld.hxx>
#include <pagedesc.hxx>
#include <fmtmeta.hxx>
#include <reffld.hxx>
#include <flddat.hxx>
#include <IDocumentSettingAccess.hxx>
#include <IDocumentRedlineAccess.hxx>
#include <redline.hxx>
#include <sfx2/docfile.hxx>
#include <svl/grabbagitem.hxx>
#include <svl/itemiter.hxx>
#include <svl/whiter.hxx>
#include <editeng/cmapitem.hxx>
#include <editeng/colritem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/crossedoutitem.hxx>
#include <officecfg/Office/Writer.hxx>

static bool lcl_IsInBody( SwFrame const *pFrame )
{
    if ( pFrame->IsInDocBody() )
        return true;

    while (const SwFlyFrame* pFly = pFrame->FindFlyFrame())
        pFrame = pFly->GetAnchorFrame();
    return pFrame->IsInDocBody();
}

static OUString ExpandField(const SwField& rField, const SwTextFormatter& rFormatter,
                            const SwTextFormatInfo& rInf)
{
    if (rInf.GetOpt().IsFieldName())
        return rField.GetFieldName();

    const SwViewShell* pSh = rInf.GetVsh();
    const SwDoc* pDoc(pSh ? pSh->GetDoc() : nullptr);
    const bool bInClipboard(!pDoc || pDoc->IsClipBoard());
    return rField.ExpandField(bInClipboard, rFormatter.GetTextFrame()->getRootFrame());
}

SwExpandPortion *SwTextFormatter::NewFieldPortion( SwTextFormatInfo &rInf,
                                                const SwTextAttr *pHint ) const
{
    SwField *pField = const_cast<SwField*>(pHint->GetFormatField().GetField());
    const bool bName = rInf.GetOpt().IsFieldName();

    // set language
    const_cast<SwTextFormatter*>(this)->SeekAndChg( rInf );
    if (pField->GetLanguage() != GetFnt()->GetLanguage())
        pField->SetLanguage( GetFnt()->GetLanguage() );

    SwViewShell *pSh = rInf.GetVsh();

    switch (pField->GetTyp()->Which())
    {
        case SwFieldIds::Script:
        case SwFieldIds::Postit:
            return new SwPostItsPortion(SwFieldIds::Script == pField->GetTyp()->Which());
        case SwFieldIds::CombinedChars:
            if (!bName)
                return new SwCombinedPortion(ExpandField(*pField, *this, rInf));
            break;
        case SwFieldIds::HiddenText:
            return new SwHiddenPortion(ExpandField(*pField, *this, rInf));
        case SwFieldIds::Chapter:
            if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
            {
                static_cast<SwChapterField*>(pField)->ChangeExpansion(
                    *m_pFrame, &static_txtattr_cast<SwTextField const*>(pHint)->GetTextNode());
            }
            break;
        case SwFieldIds::DocStat:
            if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
            {
                SwDocStatField* pDocStatField = static_cast<SwDocStatField*>(pField);
                sal_uInt16 nVirtPageCount = 0;
                if (pDocStatField->GetSubType() == SwDocStatSubType::DS_PAGE_RANGE)
                    nVirtPageCount = m_pFrame->GetVirtPageCount();
                pDocStatField->ChangeExpansion(m_pFrame, nVirtPageCount);
            }
            break;
        case SwFieldIds::PageNumber:
            if (!bName && pSh && pSh->GetLayout() && !pSh->Imp()->IsUpdateExpFields())
            {
                auto pPageNr = static_cast<SwPageNumberFieldType*>(pField->GetTyp());

                const SwRootFrame* pTmpRootFrame = pSh->GetLayout();
                const bool bVirt = pTmpRootFrame->IsVirtPageNum();

                sal_uInt16 nVirtNum = m_pFrame->GetVirtPageNum();
                sal_uInt16 nNumPages = pTmpRootFrame->GetPageNum();
                SvxNumType nNumFormat = SvxNumType(-1);
                if (SVX_NUM_PAGEDESC == pField->GetFormat())
                    nNumFormat
                        = m_pFrame->FindPageFrame()->GetPageDesc()->GetNumType().GetNumberingType();
                static_cast<SwPageNumberField*>(pField)->ChangeExpansion(nVirtNum, nNumPages);
                pPageNr->ChangeExpansion(pSh->GetDoc(), bVirt,
                                         nNumFormat != SvxNumType(-1) ? &nNumFormat : nullptr);
            }
            break;
        case SwFieldIds::GetExp:
            if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
            {
                auto pExpField = static_cast<SwGetExpField*>(pField);
                if (!::lcl_IsInBody(m_pFrame))
                {
                    pExpField->ChgBodyTextFlag(false);
                    pExpField->ChangeExpansion(*m_pFrame,
                                               *static_txtattr_cast<SwTextField const*>(pHint));
                }
                else if (!pExpField->IsInBodyText())
                {
                    // Was something else previously, thus: expand first, then convert it!
                    pExpField->ChangeExpansion(*m_pFrame,
                                               *static_txtattr_cast<SwTextField const*>(pHint));
                    pExpField->ChgBodyTextFlag(true);
                }
            }
            break;
        case SwFieldIds::Database:
            if (!bName)
            {
                static_cast<SwDBField*>(pField)->ChgBodyTextFlag(::lcl_IsInBody(m_pFrame));
            }
            break;
        case SwFieldIds::RefPageGet:
            if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
            {
                static_cast<SwRefPageGetField*>(pField)->ChangeExpansion(
                    *m_pFrame, static_txtattr_cast<SwTextField const*>(pHint));
            }
            break;
        case SwFieldIds::JumpEdit:
        {
            std::unique_ptr<SwFont> pFont;
            if (!bName)
            {
                pFont = std::make_unique<SwFont>(*m_pFont);
                pFont->SetDiffFnt(
                    &static_cast<SwJumpEditField*>(pField)->GetCharFormat()->GetAttrSet(),
                    &m_pFrame->GetDoc().getIDocumentSettingAccess());
            }
            return new SwJumpFieldPortion(ExpandField(*pField, *this, rInf), pField->GetPar2(),
                                          std::move(pFont), pField->GetFormat());
        }
        case SwFieldIds::GetRef:
            if (!bName)
            {
                auto pGetRef = static_cast<SwGetRefField*>(pField);
                if (pGetRef->GetSubType() == REF_STYLE)
                    pGetRef->UpdateField(static_txtattr_cast<SwTextField const*>(pHint), m_pFrame);
            }
            break;
        default:
            break;
    }
    return new SwFieldPortion(ExpandField(*pField, *this, rInf));
}

static SwFieldPortion * lcl_NewMetaPortion(SwTextAttr & rHint, const bool bPrefix)
{
    ::sw::Meta *const pMeta(
        static_cast<SwFormatMeta &>(rHint.GetAttr()).GetMeta() );
    OUString fix;
    ::sw::MetaField *const pField( dynamic_cast< ::sw::MetaField * >(pMeta) );
    OSL_ENSURE(pField, "lcl_NewMetaPortion: no meta field?");
    if (pField)
    {
        OUString color;
        pField->GetPrefixAndSuffix(bPrefix ? &fix : nullptr, bPrefix ? nullptr : &fix, &color);
    }
    return new SwFieldPortion( fix );
}

/**
 * Try to create a new portion with zero length, for an end of a hint
 * (where there is no CH_TXTATR). Because there may be multiple hint ends at a
 * given index, m_pByEndIter is used to keep track of the already created
 * portions. But the portions created here may actually be deleted again,
 * due to Underflow. In that case, m_pByEndIter must be decremented,
 * so the portion will be created again on the next line.
 */

SwExpandPortion * SwTextFormatter::TryNewNoLengthPortion(SwTextFormatInfo const & ;rInfo)
{
    const TextFrameIndex nIdx(rInfo.GetIdx());

    // sw_redlinehide: because there is a dummy character at the start of these
    // hints, it's impossible to have ends of hints from different nodes at the
    // same view position, so it's sufficient to check the hints of the current
    // node.  However, m_pByEndIter exists for the whole text frame, so
    // it's necessary to iterate all hints for that purpose...
    if (!m_pByEndIter)
    {
        m_pByEndIter.reset(new sw::MergedAttrIterByEnd(*rInfo.GetTextFrame()));
    }
    SwTextNode const* pNode(nullptr);
    for (SwTextAttr const* pHint = m_pByEndIter->NextAttr(pNode); pHint;
         pHint = m_pByEndIter->NextAttr(pNode))
    {
        SwTextAttr & rHint(const_cast<SwTextAttr&>(*pHint));
        TextFrameIndex const nEnd(
            rInfo.GetTextFrame()->MapModelToView(pNode, rHint.GetAnyEnd()));
        if (nEnd > nIdx)
        {
            m_pByEndIter->PrevAttr();
            break;
        }
        if (nEnd == nIdx)
        {
            if (RES_TXTATR_METAFIELD == rHint.Which())
            {
                SwFieldPortion *const pPortion(
                        lcl_NewMetaPortion(rHint, false));
                pPortion->SetNoLength(); // no CH_TXTATR at hint end!
                return pPortion;
            }
        }
    }
    return nullptr;
}

SwLinePortion *SwTextFormatter::NewExtraPortion( SwTextFormatInfo &rInf )
{
    SwTextAttr *pHint = GetAttr( rInf.GetIdx() );
    SwLinePortion *pRet = nullptr;
    if( !pHint )
    {
        pRet = new SwTextPortion;
        pRet->SetLen(TextFrameIndex(1));
        rInf.SetLen(TextFrameIndex(1));
        return pRet;
    }

    switch( pHint->Which() )
    {
    case RES_TXTATR_FLYCNT :
        {
            pRet = NewFlyCntPortion( rInf, pHint );
            break;
        }
    case RES_TXTATR_FTN :
        {
            pRet = NewFootnotePortion( rInf, pHint );
            break;
        }
    case RES_TXTATR_FIELD :
    case RES_TXTATR_ANNOTATION :
        {
            pRet = NewFieldPortion( rInf, pHint );
            break;
        }
    case RES_TXTATR_REFMARK :
        {
            pRet = new SwIsoRefPortion;
            break;
        }
    case RES_TXTATR_TOXMARK :
        {
            pRet = new SwIsoToxPortion;
            break;
        }
    case RES_TXTATR_METAFIELD:
        {
            pRet = lcl_NewMetaPortion( *pHint, true );
            break;
        }
    default: ;
    }
    if( !pRet )
    {
        auto pFieldPortion = new SwFieldPortion( u""_ustr );
        if (pHint->Which() == RES_TXTATR_CONTENTCONTROL)
        {
            pFieldPortion->SetContentControl(true);
        }
        pRet = pFieldPortion;
        rInf.SetLen(TextFrameIndex(1));
    }
    return pRet;
}

/**
 * OOXML spec says that w:rPr inside w:pPr specifies formatting for the paragraph mark symbol (i.e. the control
 * character than can be configured to be shown). However, in practice MSO also uses it as direct formatting
 * for numbering in that paragraph. I don't know if the problem is in the spec or in MSWord.
 */

static void checkApplyParagraphMarkFormatToNumbering(SwFont* pNumFnt, SwTextFormatInfo& rInf,
                                                     const IDocumentSettingAccess* pIDSA,
                                                     const SwAttrSet* pFormat)
{
    if( !pIDSA->get(DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING ))
        return;

    SwFormatAutoFormat const& rListAutoFormat(rInf.GetTextFrame()->GetTextNodeForParaProps()->GetAttr(RES_PARATR_LIST_AUTOFMT));
    std::shared_ptr<SfxItemSet> pSet(rListAutoFormat.GetStyleHandle());

    // Check each item and in case it should be ignored, then clear it.
    if (!pSet)
        return;

    std::unique_ptr<SfxItemSet> const pCleanedSet = pSet->Clone();

    if (pCleanedSet->HasItem(RES_TXTATR_CHARFMT))
    {
        // Insert attributes of referenced char format into current set
        const SwFormatCharFormat& rCharFormat = pCleanedSet->Get(RES_TXTATR_CHARFMT);
        const SwAttrSet& rStyleAttrs = rCharFormat.GetCharFormat()->GetAttrSet();
        SfxWhichIter aIter(rStyleAttrs);
        sal_uInt16 nWhich = aIter.FirstWhich();
        while (nWhich)
        {
            const SfxPoolItem* pItem = nullptr;
            if (!SwTextNode::IsIgnoredCharFormatForNumbering(nWhich, /*bIsCharStyle=*/true)
                && !pCleanedSet->HasItem(nWhich)
                && !(pFormat && pFormat->HasItem(nWhich))
                && rStyleAttrs.GetItemState(nWhich, true, &pItem) > SfxItemState::DEFAULT)
            {
                // Copy from parent sets only allowed items which will not overwrite
                // values explicitly defined in current set (pCleanedSet) or in pFormat
                if (pItem)
                    pCleanedSet->Put(*pItem);
            }
            nWhich = aIter.NextWhich();
        }

        // It is not required here anymore, all referenced items are inserted
        pCleanedSet->ClearItem(RES_TXTATR_CHARFMT);
    };

    SfxItemIter aIter(*pSet);
    const SfxPoolItem* pItem = aIter.GetCurItem();
    while (pItem)
    {
        if (SwTextNode::IsIgnoredCharFormatForNumbering(pItem->Which()))
            pCleanedSet->ClearItem(pItem->Which());
        else if (pFormat && pFormat->HasItem(pItem->Which()))
            pCleanedSet->ClearItem(pItem->Which());
        else if (pItem->Which() == RES_CHRATR_BACKGROUND)
        {
            bool bShadingWasImported = false;
            // If Shading was imported, it should not be converted to a Highlight,
            // but remain as Shading which is ignored for numbering.
            if (pCleanedSet->HasItem(RES_CHRATR_GRABBAG))
            {
                SfxGrabBagItem aGrabBag = pCleanedSet->Get(RES_CHRATR_GRABBAG, /*bSrchInParent=*/false);
                const std::map<OUString, css::uno::Any>& rMap = aGrabBag.GetGrabBag();
                auto aIterator = rMap.find(u"CharShadingMarker"_ustr);
                if (aIterator != rMap.end())
                    aIterator->second >>= bShadingWasImported;
            }

            // If used, BACKGROUND is converted to HIGHLIGHT. So also ignore if a highlight already exists.
            if (bShadingWasImported
                || pCleanedSet->HasItem(RES_CHRATR_HIGHLIGHT)
                || (pFormat && pFormat->HasItem(RES_CHRATR_HIGHLIGHT)))
            {
                pCleanedSet->ClearItem(pItem->Which());
            }
        }
        else if (pItem->Which() == RES_CHRATR_CASEMAP)
        {
            SvxCaseMap eCaseMap = static_cast<const SvxCaseMapItem*>(pItem)->GetCaseMap();
            // MS only knows about "all caps" and "small caps". Small caps is not set on numbering
            if (eCaseMap == SvxCaseMap::SmallCaps)
                pCleanedSet->ClearItem(pItem->Which());
        }
        pItem = aIter.NextItem();
    };

    // SetDiffFnt resets the background color (why?), so capture it and re-apply if it had a value,
    // because an existing value should override anything inherited from the paragraph marker.
    const std::optional<Color> oFontBackColor = pNumFnt->GetBackColor();
    // The same is true for the highlight color.
    const Color aHighlight = pNumFnt->GetHighlightColor();

    pNumFnt->SetDiffFnt(pCleanedSet.get(), pIDSA);

    if (oFontBackColor)
        pNumFnt->SetBackColor(oFontBackColor);
    if (aHighlight != COL_TRANSPARENT && !pCleanedSet->HasItem(RES_CHRATR_HIGHLIGHT))
        pNumFnt->SetHighlightColor(aHighlight);
}

static const SwRangeRedline* lcl_GetRedlineAtNodeInsertionOrDeletion( const SwTextNode& rTextNode,
        bool& bIsMoved )
{
    const SwDoc& rDoc = rTextNode.GetDoc();
    SwRedlineTable::size_type nRedlPos = rDoc.getIDocumentRedlineAccess().GetRedlinePos( rTextNode, RedlineType::Any );

    if( SwRedlineTable::npos != nRedlPos )
    {
        const SwNodeOffset nNdIdx = rTextNode.GetIndex();
        const SwRedlineTable& rTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable();
        for( ; nRedlPos < rTable.size() ; ++nRedlPos )
        {
            const SwRangeRedline* pTmp = rTable[ nRedlPos ];
            SwNodeOffset nStart = pTmp->GetPoint()->GetNodeIndex(),
                         nEnd = pTmp->GetMark()->GetNodeIndex();
            if( nStart > nEnd )
                std::swap(nStart, nEnd);
            if( RedlineType::Delete == pTmp->GetType() ||
                RedlineType::Insert == pTmp->GetType() )
            {
                if( nStart <= nNdIdx && nEnd > nNdIdx )
                {
                    bIsMoved = pTmp->IsMoved();
                    return pTmp;
                }
            }
            if( nStart > nNdIdx )
                break;
        }
    }
    return nullptr;
}

static bool lcl_setRedlineAttr( SwTextFormatInfo &rInf, const SwTextNode& rTextNode, const std::unique_ptr<SwFont>& pNumFnt )
{
    if ( rInf.GetVsh()->GetLayout()->IsHideRedlines() )
        return false;

    bool bIsMoved;
    const SwRangeRedline* pRedlineNum = lcl_GetRedlineAtNodeInsertionOrDeletion( rTextNode, bIsMoved );
    if (!pRedlineNum)
        return false;

    // moved text: dark green with double underline or strikethrough
    bool bDisplayMovedTextInGreen = officecfg::Office::Writer::Comparison::DisplayMovedTextInGreen::get();
    if ( bDisplayMovedTextInGreen && bIsMoved )
    {
        pNumFnt->SetColor(COL_GREEN);
        if ( RedlineType::Delete == pRedlineNum->GetType() )
            pNumFnt->SetStrikeout(STRIKEOUT_DOUBLE);
        else
            pNumFnt->SetUnderline(LINESTYLE_DOUBLE);
        return true;
    }

    SwAttrPool& rPool = rInf.GetVsh()->GetDoc()->GetAttrPool();
    SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1> aSet(rPool);

    std::size_t aAuthor = (1 < pRedlineNum->GetStackCount())
            ? pRedlineNum->GetAuthor( 1 )
            : pRedlineNum->GetAuthor();

    if ( RedlineType::Delete == pRedlineNum->GetType() )
        SwModule::get()->GetDeletedAuthorAttr(aAuthor, aSet);
    else
        SwModule::get()->GetInsertAuthorAttr(aAuthor, aSet);

    if (const SvxColorItem* pItem = aSet.GetItemIfSet(RES_CHRATR_COLOR))
        pNumFnt->SetColor(pItem->GetValue());
    if (const SvxUnderlineItem* pItem = aSet.GetItemIfSet(RES_CHRATR_UNDERLINE))
        pNumFnt->SetUnderline(pItem->GetLineStyle());
    if (const SvxCrossedOutItem* pItem = aSet.GetItemIfSet(RES_CHRATR_CROSSEDOUT))
        pNumFnt->SetStrikeout( pItem->GetStrikeout() );

    return true;
}

SwNumberPortion *SwTextFormatter::NewNumberPortion( SwTextFormatInfo &rInf ) const
{
    if( rInf.IsNumDone() || rInf.GetTextStart() != m_nStart
                || rInf.GetTextStart() != rInf.GetIdx() )
        return nullptr;

    SwNumberPortion *pRet = nullptr;
    // sw_redlinehide: at this point it's certain that pTextNd is the node with
    // the numbering of the frame; only the actual number-vector (GetNumString)
    // depends on the hide-mode in the layout so other calls don't need to care
    const SwTextNode *const pTextNd = GetTextFrame()->GetTextNodeForParaProps();
    const SwNumRule* pNumRule = pTextNd->GetNumRule();

    // Has a "valid" number?
    // sw_redlinehide: check that pParaPropsNode is the correct one
    assert(pTextNd->IsNumbered(m_pFrame->getRootFrame()) == pTextNd->IsNumbered(nullptr));
    if (pTextNd->IsNumbered(m_pFrame->getRootFrame()) && pTextNd->IsCountedInList())
    {
        int nLevel = pTextNd->GetActualListLevel();

        if (nLevel < 0)
            nLevel = 0;

        if (nLevel >= MAXLEVEL)
            nLevel = MAXLEVEL - 1;

        const SwNumFormat &rNumFormat = pNumRule->Get( nLevel );
        const bool bLeft = SvxAdjust::Left == rNumFormat.GetNumAdjust();
        const bool bCenter = SvxAdjust::Center == rNumFormat.GetNumAdjust();
        const bool bLabelAlignmentPosAndSpaceModeActive(
                rNumFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT );
        const sal_uInt16 nMinDist = bLabelAlignmentPosAndSpaceModeActive
                                ? 0 : rNumFormat.GetCharTextDistance();

        if( SVX_NUM_BITMAP == rNumFormat.GetNumberingType() )
        {
            OUString referer;
            if (auto const sh1 = rInf.GetVsh()) {
                if (auto const doc = sh1->GetDoc()) {
                    auto const sh2 = doc->GetPersist();
                    if (sh2 != nullptr && sh2->HasName()) {
                        referer = sh2->GetMedium()->GetName();
                    }
                }
            }
            pRet = new SwGrfNumPortion( pTextNd->GetLabelFollowedBy(),
                                        rNumFormat.GetBrush(), referer,
                                        rNumFormat.GetGraphicOrientation(),
                                        rNumFormat.GetGraphicSize(),
                                        bLeft, bCenter, nMinDist,
                                        bLabelAlignmentPosAndSpaceModeActive );
            tools::Long nTmpA = rInf.GetLast()->GetAscent();
            tools::Long nTmpD = rInf.GetLast()->Height() - nTmpA;
            if( !rInf.IsTest() )
                static_cast<SwGrfNumPortion*>(pRet)->SetBase( nTmpA, nTmpD, nTmpA, nTmpD );
        }
        else
        {
            // The SwFont is created dynamically and passed in the ctor,
            // as the CharFormat only returns an SV-Font.
            // In the dtor of SwNumberPortion, the SwFont is deleted.
            const SwAttrSet* pFormat = rNumFormat.GetCharFormat() ?
                                    &rNumFormat.GetCharFormat()->GetAttrSet() :
                                    nullptr;
            const IDocumentSettingAccess* pIDSA = pTextNd->getIDocumentSettingAccess();

            if( SVX_NUM_CHAR_SPECIAL == rNumFormat.GetNumberingType() )
            {
                const std::optional<vcl::Font> pFormatFnt = rNumFormat.GetBulletFont();

                // Build a new bullet font basing on the current paragraph font:
                std::unique_ptr<SwFont> pNumFnt(new SwFont( &rInf.GetCharAttr(), pIDSA ));

                // #i53199#
                if ( !pIDSA->get(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
                {
                    // i18463:
                    // Underline style of paragraph font should not be considered
                    // Overline style of paragraph font should not be considered
                    // Weight style of paragraph font should not be considered
                    // Posture style of paragraph font should not be considered
                    pNumFnt->SetUnderline( LINESTYLE_NONE );
                    pNumFnt->SetOverline( LINESTYLE_NONE );
                    pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::Latin );
                    pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::CJK );
                    pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::CTL );
                    pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::Latin );
                    pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::CJK );
                    pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::CTL );
                }

                // Apply the explicit attributes from the character style
                // associated with the numbering to the new bullet font.
                if( pFormat )
                    pNumFnt->SetDiffFnt( pFormat, pIDSA );

                checkApplyParagraphMarkFormatToNumbering(pNumFnt.get(), rInf, pIDSA, pFormat);

                if ( pFormatFnt )
                {
                    const SwFontScript nAct = pNumFnt->GetActual();
                    pNumFnt->SetFamily( pFormatFnt->GetFamilyType(), nAct );
                    pNumFnt->SetName( pFormatFnt->GetFamilyName(), nAct );
                    pNumFnt->SetStyleName( pFormatFnt->GetStyleName(), nAct );
                    pNumFnt->SetCharSet( pFormatFnt->GetCharSet(), nAct );
                    pNumFnt->SetPitch( pFormatFnt->GetPitch(), nAct );
                }

                // we do not allow a vertical font
                pNumFnt->SetVertical( pNumFnt->GetOrientation(),
                                      m_pFrame->IsVertical() );

                lcl_setRedlineAttr( rInf, *pTextNd, pNumFnt );

                // --> OD 2008-01-23 #newlistelevelattrs#
                if (rNumFormat.GetBulletChar())
                {
                    pRet = new SwBulletPortion(rNumFormat.GetBulletChar(),
                        pTextNd->GetLabelFollowedBy(),
                        std::move(pNumFnt),
                        bLeft, bCenter, nMinDist,
                        bLabelAlignmentPosAndSpaceModeActive);
                }
            }
            else
            {
                // Show Changes mode shows the actual numbering (SwListRedlineType::HIDDEN) and
                // the original one (SwListRedlineType::ORIGTEXT) instead of the fake numbering
                // (SwListRedlineType::SHOW, which counts removed and inserted numbered paragraphs
                // in a single list)
                bool bHasHiddenNum = false;
                OUString aTextNow( pTextNd->GetNumString(true, MAXLEVEL, m_pFrame->getRootFrame(), SwListRedlineType::HIDDEN) );
                const SwDoc& rDoc = pTextNd->GetDoc();
                const SwRedlineTable& rTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable();
                if ( rTable.size() && !rInf.GetVsh()->GetLayout()->IsHideRedlines() )
                {
                    // previous (outdated) text
                    OUString aOriginalText( pTextNd->GetNumString(true, MAXLEVEL, m_pFrame->getRootFrame(), SwListRedlineType::ORIGTEXT) );

                    if ( !aTextNow.isEmpty() || !aOriginalText.isEmpty() )
                    {

                        bool bDisplayChangedParagraphNumbering = officecfg::Office::Writer::Comparison::DisplayChangedParagraphNumbering::get();
                        if (bDisplayChangedParagraphNumbering && aTextNow != aOriginalText && !aOriginalText.isEmpty())
                        {
                            bHasHiddenNum = true;
                            // show also original number after the actual one enclosed in [ and ],
                            // and replace tabulator with space to avoid messy indentation
                            // resulted by the longer numbering, e.g. "1.[2.]" instead of "1.".
                            aTextNow = aTextNow +  "[" + aOriginalText + "]"
                                     + pTextNd->GetLabelFollowedBy().replaceAll("\t"" ");
                        }
                        else if (!aTextNow.isEmpty())
                            aTextNow += pTextNd->GetLabelFollowedBy();
                    }
                }
                else if (pTextNd->getIDocumentSettingAccess()->get(DocumentSettingId::NO_NUMBERING_SHOW_FOLLOWBY)
                    || !aTextNow.isEmpty())
                    aTextNow += pTextNd->GetLabelFollowedBy();

                // Not just an optimization ...
                // A number portion without text will be assigned a width of 0.
                // The succeeding text portion will flow into the BreakCut in the BreakLine,
                // although  we have rInf.GetLast()->GetFlyPortion()!
                if( !aTextNow.isEmpty() )
                {

                    // Build a new numbering font basing on the current paragraph font:
                    std::unique_ptr<SwFont> pNumFnt(new SwFont( &rInf.GetCharAttr(), pIDSA ));

                    // #i53199#
                    if ( !pIDSA->get(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
                    {
                        // i18463:
                        // Underline style of paragraph font should not be considered
                        pNumFnt->SetUnderline( LINESTYLE_NONE );
                        // Overline style of paragraph font should not be considered
                        pNumFnt->SetOverline( LINESTYLE_NONE );
                    }

                    // Apply the explicit attributes from the character style
                    // associated with the numbering to the new bullet font.
                    if( pFormat )
                        pNumFnt->SetDiffFnt( pFormat, pIDSA );

                    checkApplyParagraphMarkFormatToNumbering(pNumFnt.get(), rInf, pIDSA, pFormat);

                    if ( !lcl_setRedlineAttr( rInf, *pTextNd, pNumFnt ) && bHasHiddenNum )
                        pNumFnt->SetColor(SwViewOption::GetCurrentViewOptions().GetNonPrintingCharacterColor());

                    // we do not allow a vertical font
                    pNumFnt->SetVertical( pNumFnt->GetOrientation(), m_pFrame->IsVertical() );

                    pRet = new SwNumberPortion( aTextNow, std::move(pNumFnt),
                                                bLeft, bCenter, nMinDist,
                                                bLabelAlignmentPosAndSpaceModeActive );
                }
            }
        }
    }
    return pRet;
}

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

Messung V0.5
C=93 H=96 G=94

¤ Dauer der Verarbeitung: 0.17 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.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge