android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / text / txtfld.cxx
blob68c32ee19b32b1294cef3766c8cb1db84a1db1e5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
21 #include <fmtfld.hxx>
22 #include <txtfld.hxx>
23 #include <charfmt.hxx>
24 #include <fmtautofmt.hxx>
26 #include <viewsh.hxx>
27 #include <doc.hxx>
28 #include <rootfrm.hxx>
29 #include <pagefrm.hxx>
30 #include <ndtxt.hxx>
31 #include <fldbas.hxx>
32 #include <viewopt.hxx>
33 #include <flyfrm.hxx>
34 #include <viewimp.hxx>
35 #include <swfont.hxx>
36 #include <swmodule.hxx>
37 #include "porfld.hxx"
38 #include "porftn.hxx"
39 #include "porref.hxx"
40 #include "portox.hxx"
41 #include "porfly.hxx"
42 #include "itrform2.hxx"
43 #include <chpfld.hxx>
44 #include <dbfld.hxx>
45 #include <expfld.hxx>
46 #include <docufld.hxx>
47 #include <pagedesc.hxx>
48 #include <fmtmeta.hxx>
49 #include <reffld.hxx>
50 #include <flddat.hxx>
51 #include <IDocumentSettingAccess.hxx>
52 #include <IDocumentRedlineAccess.hxx>
53 #include <redline.hxx>
54 #include <sfx2/docfile.hxx>
55 #include <svl/grabbagitem.hxx>
56 #include <svl/itemiter.hxx>
57 #include <svl/whiter.hxx>
58 #include <editeng/colritem.hxx>
59 #include <editeng/udlnitem.hxx>
60 #include <editeng/crossedoutitem.hxx>
61 #include <officecfg/Office/Writer.hxx>
63 static bool lcl_IsInBody( SwFrame const *pFrame )
65 if ( pFrame->IsInDocBody() )
66 return true;
68 while (const SwFlyFrame* pFly = pFrame->FindFlyFrame())
69 pFrame = pFly->GetAnchorFrame();
70 return pFrame->IsInDocBody();
73 static OUString ExpandField(const SwField& rField, const SwTextFormatter& rFormatter,
74 const SwTextFormatInfo& rInf)
76 if (rInf.GetOpt().IsFieldName())
77 return rField.GetFieldName();
79 const SwViewShell* pSh = rInf.GetVsh();
80 const SwDoc* pDoc(pSh ? pSh->GetDoc() : nullptr);
81 const bool bInClipboard(!pDoc || pDoc->IsClipBoard());
82 return rField.ExpandField(bInClipboard, rFormatter.GetTextFrame()->getRootFrame());
85 SwExpandPortion *SwTextFormatter::NewFieldPortion( SwTextFormatInfo &rInf,
86 const SwTextAttr *pHint ) const
88 SwField *pField = const_cast<SwField*>(pHint->GetFormatField().GetField());
89 const bool bName = rInf.GetOpt().IsFieldName();
91 // set language
92 const_cast<SwTextFormatter*>(this)->SeekAndChg( rInf );
93 if (pField->GetLanguage() != GetFnt()->GetLanguage())
95 pField->SetLanguage( GetFnt()->GetLanguage() );
96 // let the visual note know about its new language
97 if (pField->GetTyp()->Which()==SwFieldIds::Postit)
98 const_cast<SwFormatField*> (&pHint->GetFormatField())->Broadcast( SwFormatFieldHint( &pHint->GetFormatField(), SwFormatFieldHintWhich::LANGUAGE ) );
101 SwViewShell *pSh = rInf.GetVsh();
103 switch (pField->GetTyp()->Which())
105 case SwFieldIds::Script:
106 case SwFieldIds::Postit:
107 return new SwPostItsPortion(SwFieldIds::Script == pField->GetTyp()->Which());
108 case SwFieldIds::CombinedChars:
109 if (!bName)
110 return new SwCombinedPortion(ExpandField(*pField, *this, rInf));
111 break;
112 case SwFieldIds::HiddenText:
113 return new SwHiddenPortion(ExpandField(*pField, *this, rInf));
114 case SwFieldIds::Chapter:
115 if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
117 static_cast<SwChapterField*>(pField)->ChangeExpansion(
118 *m_pFrame, &static_txtattr_cast<SwTextField const*>(pHint)->GetTextNode());
120 break;
121 case SwFieldIds::DocStat:
122 if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
124 static_cast<SwDocStatField*>(pField)->ChangeExpansion(m_pFrame);
126 break;
127 case SwFieldIds::PageNumber:
128 if (!bName && pSh && pSh->GetLayout() && !pSh->Imp()->IsUpdateExpFields())
130 auto pPageNr = static_cast<SwPageNumberFieldType*>(pField->GetTyp());
132 const SwRootFrame* pTmpRootFrame = pSh->GetLayout();
133 const bool bVirt = pTmpRootFrame->IsVirtPageNum();
135 sal_uInt16 nVirtNum = m_pFrame->GetVirtPageNum();
136 sal_uInt16 nNumPages = pTmpRootFrame->GetPageNum();
137 SvxNumType nNumFormat = SvxNumType(-1);
138 if (SVX_NUM_PAGEDESC == pField->GetFormat())
139 nNumFormat
140 = m_pFrame->FindPageFrame()->GetPageDesc()->GetNumType().GetNumberingType();
141 static_cast<SwPageNumberField*>(pField)->ChangeExpansion(nVirtNum, nNumPages);
142 pPageNr->ChangeExpansion(pSh->GetDoc(), bVirt,
143 nNumFormat != SvxNumType(-1) ? &nNumFormat : nullptr);
145 break;
146 case SwFieldIds::GetExp:
147 if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
149 auto pExpField = static_cast<SwGetExpField*>(pField);
150 if (!::lcl_IsInBody(m_pFrame))
152 pExpField->ChgBodyTextFlag(false);
153 pExpField->ChangeExpansion(*m_pFrame,
154 *static_txtattr_cast<SwTextField const*>(pHint));
156 else if (!pExpField->IsInBodyText())
158 // Was something else previously, thus: expand first, then convert it!
159 pExpField->ChangeExpansion(*m_pFrame,
160 *static_txtattr_cast<SwTextField const*>(pHint));
161 pExpField->ChgBodyTextFlag(true);
164 break;
165 case SwFieldIds::Database:
166 if (!bName)
168 static_cast<SwDBField*>(pField)->ChgBodyTextFlag(::lcl_IsInBody(m_pFrame));
170 break;
171 case SwFieldIds::RefPageGet:
172 if (!bName && pSh && !pSh->Imp()->IsUpdateExpFields())
174 static_cast<SwRefPageGetField*>(pField)->ChangeExpansion(
175 *m_pFrame, static_txtattr_cast<SwTextField const*>(pHint));
177 break;
178 case SwFieldIds::JumpEdit:
180 std::unique_ptr<SwFont> pFont;
181 if (!bName)
183 pFont = std::make_unique<SwFont>(*m_pFont);
184 pFont->SetDiffFnt(
185 &static_cast<SwJumpEditField*>(pField)->GetCharFormat()->GetAttrSet(),
186 &m_pFrame->GetDoc().getIDocumentSettingAccess());
188 return new SwJumpFieldPortion(ExpandField(*pField, *this, rInf), pField->GetPar2(),
189 std::move(pFont), pField->GetFormat());
191 case SwFieldIds::GetRef:
192 break;
193 default:
194 break;
196 return new SwFieldPortion(ExpandField(*pField, *this, rInf));
199 static SwFieldPortion * lcl_NewMetaPortion(SwTextAttr & rHint, const bool bPrefix)
201 ::sw::Meta *const pMeta(
202 static_cast<SwFormatMeta &>(rHint.GetAttr()).GetMeta() );
203 OUString fix;
204 ::sw::MetaField *const pField( dynamic_cast< ::sw::MetaField * >(pMeta) );
205 OSL_ENSURE(pField, "lcl_NewMetaPortion: no meta field?");
206 if (pField)
208 OUString color;
209 pField->GetPrefixAndSuffix(bPrefix ? &fix : nullptr, bPrefix ? nullptr : &fix, &color);
211 return new SwFieldPortion( fix );
215 * Try to create a new portion with zero length, for an end of a hint
216 * (where there is no CH_TXTATR). Because there may be multiple hint ends at a
217 * given index, m_pByEndIter is used to keep track of the already created
218 * portions. But the portions created here may actually be deleted again,
219 * due to Underflow. In that case, m_pByEndIter must be decremented,
220 * so the portion will be created again on the next line.
222 SwExpandPortion * SwTextFormatter::TryNewNoLengthPortion(SwTextFormatInfo const & rInfo)
224 const TextFrameIndex nIdx(rInfo.GetIdx());
226 // sw_redlinehide: because there is a dummy character at the start of these
227 // hints, it's impossible to have ends of hints from different nodes at the
228 // same view position, so it's sufficient to check the hints of the current
229 // node. However, m_pByEndIter exists for the whole text frame, so
230 // it's necessary to iterate all hints for that purpose...
231 if (!m_pByEndIter)
233 m_pByEndIter.reset(new sw::MergedAttrIterByEnd(*rInfo.GetTextFrame()));
235 SwTextNode const* pNode(nullptr);
236 for (SwTextAttr const* pHint = m_pByEndIter->NextAttr(pNode); pHint;
237 pHint = m_pByEndIter->NextAttr(pNode))
239 SwTextAttr & rHint(const_cast<SwTextAttr&>(*pHint));
240 TextFrameIndex const nEnd(
241 rInfo.GetTextFrame()->MapModelToView(pNode, rHint.GetAnyEnd()));
242 if (nEnd > nIdx)
244 m_pByEndIter->PrevAttr();
245 break;
247 if (nEnd == nIdx)
249 if (RES_TXTATR_METAFIELD == rHint.Which())
251 SwFieldPortion *const pPortion(
252 lcl_NewMetaPortion(rHint, false));
253 pPortion->SetNoLength(); // no CH_TXTATR at hint end!
254 return pPortion;
258 return nullptr;
261 SwLinePortion *SwTextFormatter::NewExtraPortion( SwTextFormatInfo &rInf )
263 SwTextAttr *pHint = GetAttr( rInf.GetIdx() );
264 SwLinePortion *pRet = nullptr;
265 if( !pHint )
267 pRet = new SwTextPortion;
268 pRet->SetLen(TextFrameIndex(1));
269 rInf.SetLen(TextFrameIndex(1));
270 return pRet;
273 switch( pHint->Which() )
275 case RES_TXTATR_FLYCNT :
277 pRet = NewFlyCntPortion( rInf, pHint );
278 break;
280 case RES_TXTATR_FTN :
282 pRet = NewFootnotePortion( rInf, pHint );
283 break;
285 case RES_TXTATR_FIELD :
286 case RES_TXTATR_ANNOTATION :
288 pRet = NewFieldPortion( rInf, pHint );
289 break;
291 case RES_TXTATR_REFMARK :
293 pRet = new SwIsoRefPortion;
294 break;
296 case RES_TXTATR_TOXMARK :
298 pRet = new SwIsoToxPortion;
299 break;
301 case RES_TXTATR_METAFIELD:
303 pRet = lcl_NewMetaPortion( *pHint, true );
304 break;
306 default: ;
308 if( !pRet )
310 auto pFieldPortion = new SwFieldPortion( "" );
311 if (pHint->Which() == RES_TXTATR_CONTENTCONTROL)
313 pFieldPortion->SetContentControl(true);
315 pRet = pFieldPortion;
316 rInf.SetLen(TextFrameIndex(1));
318 return pRet;
322 * OOXML spec says that w:rPr inside w:pPr specifies formatting for the paragraph mark symbol (i.e. the control
323 * character than can be configured to be shown). However, in practice MSO also uses it as direct formatting
324 * for numbering in that paragraph. I don't know if the problem is in the spec or in MSWord.
326 static void checkApplyParagraphMarkFormatToNumbering(SwFont* pNumFnt, SwTextFormatInfo& rInf,
327 const IDocumentSettingAccess* pIDSA,
328 const SwAttrSet* pFormat)
330 if( !pIDSA->get(DocumentSettingId::APPLY_PARAGRAPH_MARK_FORMAT_TO_NUMBERING ))
331 return;
333 SwFormatAutoFormat const& rListAutoFormat(rInf.GetTextFrame()->GetTextNodeForParaProps()->GetAttr(RES_PARATR_LIST_AUTOFMT));
334 std::shared_ptr<SfxItemSet> pSet(rListAutoFormat.GetStyleHandle());
336 // Check each item and in case it should be ignored, then clear it.
337 if (!pSet)
338 return;
340 std::unique_ptr<SfxItemSet> const pCleanedSet = pSet->Clone();
342 if (pCleanedSet->HasItem(RES_TXTATR_CHARFMT))
344 // Insert attributes of referenced char format into current set
345 const SwFormatCharFormat& rCharFormat = pCleanedSet->Get(RES_TXTATR_CHARFMT);
346 const SwAttrSet& rStyleAttrs = static_cast<const SwCharFormat *>(rCharFormat.GetRegisteredIn())->GetAttrSet();
347 SfxWhichIter aIter(rStyleAttrs);
348 sal_uInt16 nWhich = aIter.FirstWhich();
349 while (nWhich)
351 if (!SwTextNode::IsIgnoredCharFormatForNumbering(nWhich, /*bIsCharStyle=*/true)
352 && !pCleanedSet->HasItem(nWhich)
353 && !(pFormat && pFormat->HasItem(nWhich)) )
355 // Copy from parent sets only allowed items which will not overwrite
356 // values explicitly defined in current set (pCleanedSet) or in pFormat
357 if (const SfxPoolItem* pItem = rStyleAttrs.GetItem(nWhich, true))
358 pCleanedSet->Put(*pItem);
360 nWhich = aIter.NextWhich();
363 // It is not required here anymore, all referenced items are inserted
364 pCleanedSet->ClearItem(RES_TXTATR_CHARFMT);
367 SfxItemIter aIter(*pSet);
368 const SfxPoolItem* pItem = aIter.GetCurItem();
369 while (pItem)
371 if (SwTextNode::IsIgnoredCharFormatForNumbering(pItem->Which()))
372 pCleanedSet->ClearItem(pItem->Which());
373 else if (pFormat && pFormat->HasItem(pItem->Which()))
374 pCleanedSet->ClearItem(pItem->Which());
375 else if (pItem->Which() == RES_CHRATR_BACKGROUND)
377 bool bShadingWasImported = false;
378 // If Shading was imported, it should not be converted to a Highlight,
379 // but remain as Shading which is ignored for numbering.
380 if (pCleanedSet->HasItem(RES_CHRATR_GRABBAG))
382 SfxGrabBagItem aGrabBag = pCleanedSet->Get(RES_CHRATR_GRABBAG, /*bSrchInParent=*/false);
383 std::map<OUString, css::uno::Any>& rMap = aGrabBag.GetGrabBag();
384 auto aIterator = rMap.find("CharShadingMarker");
385 if (aIterator != rMap.end())
386 aIterator->second >>= bShadingWasImported;
389 // If used, BACKGROUND is converted to HIGHLIGHT. So also ignore if a highlight already exists.
390 if (bShadingWasImported
391 || pCleanedSet->HasItem(RES_CHRATR_HIGHLIGHT)
392 || (pFormat && pFormat->HasItem(RES_CHRATR_HIGHLIGHT)))
394 pCleanedSet->ClearItem(pItem->Which());
397 pItem = aIter.NextItem();
400 // SetDiffFnt resets the background color (why?), so capture it and re-apply if it had a value,
401 // because an existing value should override anything inherited from the paragraph marker.
402 const std::optional<Color> oFontBackColor = pNumFnt->GetBackColor();
403 // The same is true for the highlight color.
404 const Color aHighlight = pNumFnt->GetHighlightColor();
406 pNumFnt->SetDiffFnt(pCleanedSet.get(), pIDSA);
408 if (oFontBackColor)
409 pNumFnt->SetBackColor(oFontBackColor);
410 if (aHighlight != COL_TRANSPARENT)
411 pNumFnt->SetHighlightColor(aHighlight);
414 static const SwRangeRedline* lcl_GetRedlineAtNodeInsertionOrDeletion( const SwTextNode& rTextNode,
415 bool& bIsMoved )
417 const SwDoc& rDoc = rTextNode.GetDoc();
418 SwRedlineTable::size_type nRedlPos = rDoc.getIDocumentRedlineAccess().GetRedlinePos( rTextNode, RedlineType::Any );
420 if( SwRedlineTable::npos != nRedlPos )
422 const SwNodeOffset nNdIdx = rTextNode.GetIndex();
423 const SwRedlineTable& rTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable();
424 for( ; nRedlPos < rTable.size() ; ++nRedlPos )
426 const SwRangeRedline* pTmp = rTable[ nRedlPos ];
427 SwNodeOffset nStart = pTmp->GetPoint()->GetNodeIndex(),
428 nEnd = pTmp->GetMark()->GetNodeIndex();
429 if( nStart > nEnd )
430 std::swap(nStart, nEnd);
431 if( RedlineType::Delete == pTmp->GetType() ||
432 RedlineType::Insert == pTmp->GetType() )
434 if( nStart <= nNdIdx && nEnd > nNdIdx )
436 bIsMoved = pTmp->IsMoved();
437 return pTmp;
440 if( nStart > nNdIdx )
441 break;
444 return nullptr;
447 static bool lcl_setRedlineAttr( SwTextFormatInfo &rInf, const SwTextNode& rTextNode, const std::unique_ptr<SwFont>& pNumFnt )
449 if ( rInf.GetVsh()->GetLayout()->IsHideRedlines() )
450 return false;
452 bool bIsMoved;
453 const SwRangeRedline* pRedlineNum = lcl_GetRedlineAtNodeInsertionOrDeletion( rTextNode, bIsMoved );
454 if (!pRedlineNum)
455 return false;
457 // moved text: dark green with double underline or strikethrough
458 if ( bIsMoved )
460 pNumFnt->SetColor(COL_GREEN);
461 if ( RedlineType::Delete == pRedlineNum->GetType() )
462 pNumFnt->SetStrikeout(STRIKEOUT_DOUBLE);
463 else
464 pNumFnt->SetUnderline(LINESTYLE_DOUBLE);
465 return true;
468 SwAttrPool& rPool = rInf.GetVsh()->GetDoc()->GetAttrPool();
469 SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END-1> aSet(rPool);
471 std::size_t aAuthor = (1 < pRedlineNum->GetStackCount())
472 ? pRedlineNum->GetAuthor( 1 )
473 : pRedlineNum->GetAuthor();
475 if ( RedlineType::Delete == pRedlineNum->GetType() )
476 SW_MOD()->GetDeletedAuthorAttr(aAuthor, aSet);
477 else
478 SW_MOD()->GetInsertAuthorAttr(aAuthor, aSet);
480 if (const SvxColorItem* pItem = aSet.GetItemIfSet(RES_CHRATR_COLOR))
481 pNumFnt->SetColor(pItem->GetValue());
482 if (const SvxUnderlineItem* pItem = aSet.GetItemIfSet(RES_CHRATR_UNDERLINE))
483 pNumFnt->SetUnderline(pItem->GetLineStyle());
484 if (const SvxCrossedOutItem* pItem = aSet.GetItemIfSet(RES_CHRATR_CROSSEDOUT))
485 pNumFnt->SetStrikeout( pItem->GetStrikeout() );
487 return true;
490 SwNumberPortion *SwTextFormatter::NewNumberPortion( SwTextFormatInfo &rInf ) const
492 if( rInf.IsNumDone() || rInf.GetTextStart() != m_nStart
493 || rInf.GetTextStart() != rInf.GetIdx() )
494 return nullptr;
496 SwNumberPortion *pRet = nullptr;
497 // sw_redlinehide: at this point it's certain that pTextNd is the node with
498 // the numbering of the frame; only the actual number-vector (GetNumString)
499 // depends on the hide-mode in the layout so other calls don't need to care
500 const SwTextNode *const pTextNd = GetTextFrame()->GetTextNodeForParaProps();
501 const SwNumRule* pNumRule = pTextNd->GetNumRule();
503 // Has a "valid" number?
504 // sw_redlinehide: check that pParaPropsNode is the correct one
505 assert(pTextNd->IsNumbered(m_pFrame->getRootFrame()) == pTextNd->IsNumbered(nullptr));
506 if (pTextNd->IsNumbered(m_pFrame->getRootFrame()) && pTextNd->IsCountedInList())
508 int nLevel = pTextNd->GetActualListLevel();
510 if (nLevel < 0)
511 nLevel = 0;
513 if (nLevel >= MAXLEVEL)
514 nLevel = MAXLEVEL - 1;
516 const SwNumFormat &rNumFormat = pNumRule->Get( nLevel );
517 const bool bLeft = SvxAdjust::Left == rNumFormat.GetNumAdjust();
518 const bool bCenter = SvxAdjust::Center == rNumFormat.GetNumAdjust();
519 const bool bLabelAlignmentPosAndSpaceModeActive(
520 rNumFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT );
521 const sal_uInt16 nMinDist = bLabelAlignmentPosAndSpaceModeActive
522 ? 0 : rNumFormat.GetCharTextDistance();
524 if( SVX_NUM_BITMAP == rNumFormat.GetNumberingType() )
526 OUString referer;
527 if (auto const sh1 = rInf.GetVsh()) {
528 if (auto const doc = sh1->GetDoc()) {
529 auto const sh2 = doc->GetPersist();
530 if (sh2 != nullptr && sh2->HasName()) {
531 referer = sh2->GetMedium()->GetName();
535 pRet = new SwGrfNumPortion( pTextNd->GetLabelFollowedBy(),
536 rNumFormat.GetBrush(), referer,
537 rNumFormat.GetGraphicOrientation(),
538 rNumFormat.GetGraphicSize(),
539 bLeft, bCenter, nMinDist,
540 bLabelAlignmentPosAndSpaceModeActive );
541 tools::Long nTmpA = rInf.GetLast()->GetAscent();
542 tools::Long nTmpD = rInf.GetLast()->Height() - nTmpA;
543 if( !rInf.IsTest() )
544 static_cast<SwGrfNumPortion*>(pRet)->SetBase( nTmpA, nTmpD, nTmpA, nTmpD );
546 else
548 // The SwFont is created dynamically and passed in the ctor,
549 // as the CharFormat only returns an SV-Font.
550 // In the dtor of SwNumberPortion, the SwFont is deleted.
551 const SwAttrSet* pFormat = rNumFormat.GetCharFormat() ?
552 &rNumFormat.GetCharFormat()->GetAttrSet() :
553 nullptr;
554 const IDocumentSettingAccess* pIDSA = pTextNd->getIDocumentSettingAccess();
556 if( SVX_NUM_CHAR_SPECIAL == rNumFormat.GetNumberingType() )
558 const std::optional<vcl::Font> pFormatFnt = rNumFormat.GetBulletFont();
560 // Build a new bullet font basing on the current paragraph font:
561 std::unique_ptr<SwFont> pNumFnt(new SwFont( &rInf.GetCharAttr(), pIDSA ));
563 // #i53199#
564 if ( !pIDSA->get(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
566 // i18463:
567 // Underline style of paragraph font should not be considered
568 // Overline style of paragraph font should not be considered
569 // Weight style of paragraph font should not be considered
570 // Posture style of paragraph font should not be considered
571 pNumFnt->SetUnderline( LINESTYLE_NONE );
572 pNumFnt->SetOverline( LINESTYLE_NONE );
573 pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::Latin );
574 pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::CJK );
575 pNumFnt->SetItalic( ITALIC_NONE, SwFontScript::CTL );
576 pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::Latin );
577 pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::CJK );
578 pNumFnt->SetWeight( WEIGHT_NORMAL, SwFontScript::CTL );
581 // Apply the explicit attributes from the character style
582 // associated with the numbering to the new bullet font.
583 if( pFormat )
584 pNumFnt->SetDiffFnt( pFormat, pIDSA );
586 checkApplyParagraphMarkFormatToNumbering(pNumFnt.get(), rInf, pIDSA, pFormat);
588 if ( pFormatFnt )
590 const SwFontScript nAct = pNumFnt->GetActual();
591 pNumFnt->SetFamily( pFormatFnt->GetFamilyType(), nAct );
592 pNumFnt->SetName( pFormatFnt->GetFamilyName(), nAct );
593 pNumFnt->SetStyleName( pFormatFnt->GetStyleName(), nAct );
594 pNumFnt->SetCharSet( pFormatFnt->GetCharSet(), nAct );
595 pNumFnt->SetPitch( pFormatFnt->GetPitch(), nAct );
598 // we do not allow a vertical font
599 pNumFnt->SetVertical( pNumFnt->GetOrientation(),
600 m_pFrame->IsVertical() );
602 lcl_setRedlineAttr( rInf, *pTextNd, pNumFnt );
604 // --> OD 2008-01-23 #newlistelevelattrs#
605 if (rNumFormat.GetBulletChar())
607 pRet = new SwBulletPortion(rNumFormat.GetBulletChar(),
608 pTextNd->GetLabelFollowedBy(),
609 std::move(pNumFnt),
610 bLeft, bCenter, nMinDist,
611 bLabelAlignmentPosAndSpaceModeActive);
614 else
616 // Show Changes mode shows the actual numbering (SwListRedlineType::HIDDEN) and
617 // the original one (SwListRedlineType::ORIGTEXT) instead of the fake numbering
618 // (SwListRedlineType::SHOW, which counts removed and inserted numbered paragraphs
619 // in a single list)
620 bool bHasHiddenNum = false;
621 OUString aText( pTextNd->GetNumString(true, MAXLEVEL, m_pFrame->getRootFrame(), SwListRedlineType::HIDDEN) );
622 const SwDoc& rDoc = pTextNd->GetDoc();
623 const SwRedlineTable& rTable = rDoc.getIDocumentRedlineAccess().GetRedlineTable();
624 if ( rTable.size() && !rInf.GetVsh()->GetLayout()->IsHideRedlines() )
626 OUString aHiddenText( pTextNd->GetNumString(true, MAXLEVEL, m_pFrame->getRootFrame(), SwListRedlineType::ORIGTEXT) );
628 if ( !aText.isEmpty() || !aHiddenText.isEmpty() )
630 bool bDisplayChangedParagraphNumbering = officecfg::Office::Writer::Comparison::DisplayChangedParagraphNumbering::get();
631 if (bDisplayChangedParagraphNumbering && aText != aHiddenText && !aHiddenText.isEmpty())
633 bHasHiddenNum = true;
634 // show also original number after the actual one enclosed in [ and ],
635 // and replace tabulator with space to avoid messy indentation
636 // resulted by the longer numbering, e.g. "1.[2.]" instead of "1.".
637 aText = aText + "[" + aHiddenText + "]"
638 + pTextNd->GetLabelFollowedBy().replaceAll("\t", " ");
640 else if (!aText.isEmpty())
641 aText += pTextNd->GetLabelFollowedBy();
644 else if (pTextNd->getIDocumentSettingAccess()->get(DocumentSettingId::NO_NUMBERING_SHOW_FOLLOWBY)
645 || !aText.isEmpty())
646 aText += pTextNd->GetLabelFollowedBy();
648 // Not just an optimization ...
649 // A number portion without text will be assigned a width of 0.
650 // The succeeding text portion will flow into the BreakCut in the BreakLine,
651 // although we have rInf.GetLast()->GetFlyPortion()!
652 if( !aText.isEmpty() )
655 // Build a new numbering font basing on the current paragraph font:
656 std::unique_ptr<SwFont> pNumFnt(new SwFont( &rInf.GetCharAttr(), pIDSA ));
658 const SwTextNode& rTextNode = *rInf.GetTextFrame()->GetTextNodeForParaProps();
659 if (const SwpHints* pHints = rTextNode.GetpSwpHints())
661 // Also look for an empty character hint that sits at the paragraph end:
662 for (size_t i = 0; i < pHints->Count(); ++i)
664 const SwTextAttr* pHint = pHints->GetSortedByEnd(i);
665 if (pHint->Which() == RES_TXTATR_AUTOFMT && pHint->GetEnd()
666 && pHint->GetStart() == *pHint->GetEnd()
667 && pHint->GetStart() == rTextNode.GetText().getLength())
669 std::shared_ptr<SfxItemSet> pSet
670 = pHint->GetAutoFormat().GetStyleHandle();
671 if (pSet)
673 pNumFnt->SetDiffFnt(pSet.get(), pIDSA);
674 break;
680 // #i53199#
681 if ( !pIDSA->get(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT) )
683 // i18463:
684 // Underline style of paragraph font should not be considered
685 pNumFnt->SetUnderline( LINESTYLE_NONE );
686 // Overline style of paragraph font should not be considered
687 pNumFnt->SetOverline( LINESTYLE_NONE );
690 // Apply the explicit attributes from the character style
691 // associated with the numbering to the new bullet font.
692 if( pFormat )
693 pNumFnt->SetDiffFnt( pFormat, pIDSA );
695 checkApplyParagraphMarkFormatToNumbering(pNumFnt.get(), rInf, pIDSA, pFormat);
697 if ( !lcl_setRedlineAttr( rInf, *pTextNd, pNumFnt ) && bHasHiddenNum )
698 pNumFnt->SetColor(NON_PRINTING_CHARACTER_COLOR);
700 // we do not allow a vertical font
701 pNumFnt->SetVertical( pNumFnt->GetOrientation(), m_pFrame->IsVertical() );
703 pRet = new SwNumberPortion( aText, std::move(pNumFnt),
704 bLeft, bCenter, nMinDist,
705 bLabelAlignmentPosAndSpaceModeActive );
710 return pRet;
713 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */