/* -*- 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 .
*/
// 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: returnnew SwPostItsPortion(SwFieldIds::Script == pField->GetTyp()->Which()); case SwFieldIds::CombinedChars: if (!bName) returnnew SwCombinedPortion(ExpandField(*pField, *this, rInf)); break; case SwFieldIds::HiddenText: returnnew 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());
/** * 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;
}
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.
*/ staticvoid checkApplyParagraphMarkFormatToNumbering(SwFont* pNumFnt, SwTextFormatInfo& rInf, const IDocumentSettingAccess* pIDSA, const SwAttrSet* pFormat)
{ if( !pIDSA->get(DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING )) return;
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()); elseif (pFormat && pFormat->HasItem(pItem->Which()))
pCleanedSet->ClearItem(pItem->Which()); elseif (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());
}
} elseif (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);
}
// 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); returntrue;
}
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();
// 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 );
// 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", " ");
} elseif (!aTextNow.isEmpty())
aTextNow += pTextNd->GetLabelFollowedBy();
}
} elseif (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 );
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.