ITEM: Refactor ItemType
[LibreOffice.git] / sw / source / core / doc / docftn.cxx
blobcbce97a20fbb4c6f55bf573a49ddeea98adb5881
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 <ftnidx.hxx>
21 #include <rootfrm.hxx>
22 #include <txtftn.hxx>
23 #include <fmtftn.hxx>
24 #include <pam.hxx>
25 #include <pagedesc.hxx>
26 #include <charfmt.hxx>
27 #include <UndoAttribute.hxx>
28 #include <rolbck.hxx>
29 #include <doc.hxx>
30 #include <IDocumentFieldsAccess.hxx>
31 #include <IDocumentUndoRedo.hxx>
32 #include <IDocumentState.hxx>
33 #include <IDocumentLayoutAccess.hxx>
34 #include <IDocumentStylePoolAccess.hxx>
35 #include <ndtxt.hxx>
36 #include <poolfmt.hxx>
37 #include <ftninfo.hxx>
38 #include <fmtftntx.hxx>
39 #include <unoprnms.hxx>
41 SwEndNoteInfo& SwEndNoteInfo::operator=(const SwEndNoteInfo& rInfo)
43 m_pTextFormatColl = rInfo.m_pTextFormatColl;
44 m_pPageDesc = rInfo.m_pPageDesc;
45 m_pCharFormat = rInfo.m_pCharFormat;
46 m_pAnchorFormat = rInfo.m_pAnchorFormat;
47 m_aDepends.EndListeningAll();
48 m_aDepends.StartListening(m_pTextFormatColl);
49 m_aDepends.StartListening(m_pPageDesc);
50 m_aDepends.StartListening(m_pCharFormat);
51 m_aDepends.StartListening(m_pAnchorFormat);
53 m_aFormat = rInfo.m_aFormat;
54 m_nFootnoteOffset = rInfo.m_nFootnoteOffset;
55 m_bEndNote = rInfo.m_bEndNote;
56 m_sPrefix = rInfo.m_sPrefix;
57 m_sSuffix = rInfo.m_sSuffix;
58 return *this;
61 bool SwEndNoteInfo::operator==( const SwEndNoteInfo& rInfo ) const
63 return
64 m_pTextFormatColl == rInfo.m_pTextFormatColl &&
65 m_pPageDesc == rInfo.m_pPageDesc &&
66 m_pCharFormat == rInfo.m_pCharFormat &&
67 m_pAnchorFormat == rInfo.m_pAnchorFormat &&
68 m_aFormat.GetNumberingType() == rInfo.m_aFormat.GetNumberingType() &&
69 m_nFootnoteOffset == rInfo.m_nFootnoteOffset &&
70 m_bEndNote == rInfo.m_bEndNote &&
71 m_sPrefix == rInfo.m_sPrefix &&
72 m_sSuffix == rInfo.m_sSuffix;
75 SwEndNoteInfo::SwEndNoteInfo(const SwEndNoteInfo& rInfo) :
76 SwClient(nullptr),
77 m_aDepends(*this),
78 m_pTextFormatColl(rInfo.m_pTextFormatColl),
79 m_pPageDesc(rInfo.m_pPageDesc),
80 m_pCharFormat(rInfo.m_pCharFormat),
81 m_pAnchorFormat(rInfo.m_pAnchorFormat),
82 m_sPrefix( rInfo.m_sPrefix ),
83 m_sSuffix( rInfo.m_sSuffix ),
84 m_bEndNote( true ),
85 m_aFormat( rInfo.m_aFormat ),
86 m_nFootnoteOffset( rInfo.m_nFootnoteOffset )
88 m_aDepends.StartListening(m_pTextFormatColl);
89 m_aDepends.StartListening(m_pPageDesc);
90 m_aDepends.StartListening(m_pCharFormat);
91 m_aDepends.StartListening(m_pAnchorFormat);
94 SwEndNoteInfo::SwEndNoteInfo() :
95 SwClient(nullptr),
96 m_aDepends(*this),
97 m_pTextFormatColl(nullptr),
98 m_pPageDesc(nullptr),
99 m_pCharFormat(nullptr),
100 m_pAnchorFormat(nullptr),
101 m_bEndNote( true ),
102 m_nFootnoteOffset( 0 )
104 m_aFormat.SetNumberingType(SVX_NUM_ROMAN_LOWER);
107 SwPageDesc* SwEndNoteInfo::GetPageDesc(SwDoc& rDoc) const
109 if(!m_pPageDesc)
111 m_pPageDesc = rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool( o3tl::narrowing<sal_uInt16>(
112 m_bEndNote ? RES_POOLPAGE_ENDNOTE : RES_POOLPAGE_FOOTNOTE ) );
113 m_aDepends.StartListening(m_pPageDesc);
115 return m_pPageDesc;
118 bool SwEndNoteInfo::KnowsPageDesc() const
120 return m_pPageDesc != nullptr;
123 bool SwEndNoteInfo::DependsOn(const SwPageDesc* pDesc) const
125 return m_pPageDesc == pDesc;
128 void SwEndNoteInfo::ChgPageDesc(SwPageDesc* pDesc)
130 m_aDepends.EndListening(m_pPageDesc);
131 m_pPageDesc = pDesc;
132 m_aDepends.StartListening(m_pPageDesc);
135 SwSection* SwEndNoteInfo::GetSwSection(SwDoc& rDoc) const
137 if (!m_pSwSection)
139 SwSectionFormat* pFormat = rDoc.MakeSectionFormat();
140 pFormat->SetFormatName(UNO_NAME_ENDNOTE);
141 pFormat->SetFormatAttr(SwFormatEndAtTextEnd(FTNEND_ATTXTEND));
142 m_pSwSection.reset(new SwSection(SectionType::Content, pFormat->GetName(), *pFormat));
144 return m_pSwSection.get();
147 void SwEndNoteInfo::ResetSwSection()
149 m_pSwSection.reset();
152 void SwEndNoteInfo::SetFootnoteTextColl(SwTextFormatColl& rFormat)
154 m_aDepends.EndListening(m_pTextFormatColl);
155 m_pTextFormatColl = &rFormat;
156 m_aDepends.StartListening(m_pTextFormatColl);
159 SwCharFormat* SwEndNoteInfo::GetCharFormat(SwDoc& rDoc) const
161 auto pCharFormatFromDoc = rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( o3tl::narrowing<sal_uInt16>(
162 m_bEndNote ? RES_POOLCHR_ENDNOTE : RES_POOLCHR_FOOTNOTE ) );
163 if (m_pCharFormat != pCharFormatFromDoc)
165 m_aDepends.EndListening(m_pCharFormat);
166 m_aDepends.StartListening(pCharFormatFromDoc);
167 m_pCharFormat = pCharFormatFromDoc;
169 return m_pCharFormat;
172 namespace
174 void lcl_ResetPoolIdForDocAndSync(const sal_uInt16 nId, SwCharFormat* pFormat, const SwEndNoteInfo& rInfo)
176 auto pDoc = pFormat->GetDoc();
177 if(!pDoc)
178 return;
179 for(auto pDocFormat : *pDoc->GetCharFormats())
181 if(pDocFormat == pFormat)
182 pDocFormat->SetPoolFormatId(nId);
183 else if(pDocFormat->GetPoolFormatId() == nId)
184 pDocFormat->SetPoolFormatId(0);
186 rInfo.GetCharFormat(*pDoc);
187 rInfo.GetAnchorCharFormat(*pDoc);
191 void SwEndNoteInfo::SetCharFormat(SwCharFormat* pFormat)
193 lcl_ResetPoolIdForDocAndSync(
194 o3tl::narrowing<sal_uInt16>(m_bEndNote
195 ? RES_POOLCHR_ENDNOTE
196 : RES_POOLCHR_FOOTNOTE),
197 pFormat,
198 *this);
201 SwCharFormat* SwEndNoteInfo::GetAnchorCharFormat(SwDoc& rDoc) const
203 auto pAnchorFormatFromDoc = rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool( o3tl::narrowing<sal_uInt16>(
204 m_bEndNote ? RES_POOLCHR_ENDNOTE_ANCHOR : RES_POOLCHR_FOOTNOTE_ANCHOR ) );
205 if(m_pAnchorFormat != pAnchorFormatFromDoc)
207 m_aDepends.EndListening(m_pAnchorFormat);
208 m_aDepends.StartListening(pAnchorFormatFromDoc);
209 m_pAnchorFormat = pAnchorFormatFromDoc;
211 return m_pAnchorFormat;
214 void SwEndNoteInfo::SetAnchorCharFormat(SwCharFormat* pFormat)
216 lcl_ResetPoolIdForDocAndSync(
217 o3tl::narrowing<sal_uInt16>(m_bEndNote
218 ? RES_POOLCHR_ENDNOTE_ANCHOR
219 : RES_POOLCHR_FOOTNOTE_ANCHOR),
220 pFormat,
221 *this);
224 SwCharFormat* SwEndNoteInfo::GetCurrentCharFormat(const bool bAnchor) const
226 return bAnchor
227 ? m_pAnchorFormat
228 : m_pCharFormat;
231 void SwEndNoteInfo::UpdateFormatOrAttr()
233 auto pFormat = GetCurrentCharFormat(m_pCharFormat == nullptr);
234 if (!pFormat || !m_aDepends.IsListeningTo(pFormat) || pFormat->IsFormatInDTOR())
235 return;
236 SwDoc* pDoc = pFormat->GetDoc();
237 SwFootnoteIdxs& rFootnoteIdxs = pDoc->GetFootnoteIdxs();
238 for(auto pTextFootnote : rFootnoteIdxs)
240 const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
241 if(rFootnote.IsEndNote() == m_bEndNote)
242 pTextFootnote->SetNumber(rFootnote.GetNumber(), rFootnote.GetNumberRLHidden(), rFootnote.GetNumStr());
247 void SwEndNoteInfo::SwClientNotify( const SwModify& rModify, const SfxHint& rHint)
249 if (rHint.GetId() == SfxHintId::SwLegacyModify)
251 auto pLegacyHint = static_cast<const sw::LegacyModifyHint*>(&rHint);
252 switch(pLegacyHint->GetWhich())
254 case RES_ATTRSET_CHG:
255 UpdateFormatOrAttr();
256 break;
257 default:
258 CheckRegistration( pLegacyHint->m_pOld );
261 else if (rHint.GetId() == SfxHintId::SwFormatChange)
263 UpdateFormatOrAttr();
265 else if (rHint.GetId() == SfxHintId::SwModifyChanged)
267 auto pModifyChangedHint = static_cast<const sw::ModifyChangedHint*>(&rHint);
268 auto pNew = const_cast<sw::BroadcastingModify*>(static_cast<const sw::BroadcastingModify*>(pModifyChangedHint->m_pNew));
269 if(m_pAnchorFormat == &rModify)
270 m_pAnchorFormat = static_cast<SwCharFormat*>(pNew);
271 else if(m_pCharFormat == &rModify)
272 m_pCharFormat = static_cast<SwCharFormat*>(pNew);
273 else if(m_pPageDesc == &rModify)
274 m_pPageDesc = static_cast<SwPageDesc*>(pNew);
275 else if(m_pTextFormatColl == &rModify)
276 m_pTextFormatColl = static_cast<SwTextFormatColl*>(pNew);
280 SwFootnoteInfo& SwFootnoteInfo::operator=(const SwFootnoteInfo& rInfo)
282 SwEndNoteInfo::operator=(rInfo);
283 m_aQuoVadis = rInfo.m_aQuoVadis;
284 m_aErgoSum = rInfo.m_aErgoSum;
285 m_ePos = rInfo.m_ePos;
286 m_eNum = rInfo.m_eNum;
287 return *this;
290 bool SwFootnoteInfo::operator==( const SwFootnoteInfo& rInfo ) const
292 return m_ePos == rInfo.m_ePos &&
293 m_eNum == rInfo.m_eNum &&
294 SwEndNoteInfo::operator==(rInfo) &&
295 m_aQuoVadis == rInfo.m_aQuoVadis &&
296 m_aErgoSum == rInfo.m_aErgoSum;
299 SwFootnoteInfo::SwFootnoteInfo(const SwFootnoteInfo& rInfo) :
300 SwEndNoteInfo( rInfo ),
301 m_aQuoVadis( rInfo.m_aQuoVadis ),
302 m_aErgoSum( rInfo.m_aErgoSum ),
303 m_ePos( rInfo.m_ePos ),
304 m_eNum( rInfo.m_eNum )
306 m_bEndNote = false;
309 SwFootnoteInfo::SwFootnoteInfo() :
310 m_ePos( FTNPOS_PAGE ),
311 m_eNum( FTNNUM_DOC )
313 m_aFormat.SetNumberingType(SVX_NUM_ARABIC);
314 m_bEndNote = false;
317 SwFootnoteInfo::~SwFootnoteInfo() = default;
319 void SwDoc::SetFootnoteInfo(const SwFootnoteInfo& rInfo)
321 SwRootFrame* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout();
322 if( GetFootnoteInfo() == rInfo )
323 return;
325 const SwFootnoteInfo &rOld = GetFootnoteInfo();
327 if (GetIDocumentUndoRedo().DoesUndo())
329 GetIDocumentUndoRedo().AppendUndo( std::make_unique<SwUndoFootNoteInfo>(rOld, *this) );
332 bool bFootnotePos = rInfo.m_ePos != rOld.m_ePos;
333 bool bFootnoteDesc = rOld.m_ePos == FTNPOS_CHAPTER &&
334 rInfo.GetPageDesc( *this ) != rOld.GetPageDesc( *this );
335 bool bExtra = rInfo.m_aQuoVadis != rOld.m_aQuoVadis ||
336 rInfo.m_aErgoSum != rOld.m_aErgoSum ||
337 rInfo.m_aFormat.GetNumberingType() != rOld.m_aFormat.GetNumberingType() ||
338 rInfo.GetPrefix() != rOld.GetPrefix() ||
339 rInfo.GetSuffix() != rOld.GetSuffix();
340 SwCharFormat *pOldChrFormat = rOld.GetCharFormat( *this ),
341 *pNewChrFormat = rInfo.GetCharFormat( *this );
342 bool bFootnoteChrFormats = pOldChrFormat != pNewChrFormat;
344 *mpFootnoteInfo = rInfo;
346 if (pTmpRoot)
348 o3tl::sorted_vector<SwRootFrame*> aAllLayouts = GetAllLayouts();
349 if ( bFootnotePos )
350 for( auto aLayout : aAllLayouts )
351 aLayout->AllRemoveFootnotes();
352 else
354 for( auto aLayout : aAllLayouts )
355 aLayout->UpdateFootnoteNums();
356 if ( bFootnoteDesc )
357 for( auto aLayout : aAllLayouts )
358 aLayout->CheckFootnotePageDescs(false);
359 if ( bExtra )
361 // For messages regarding ErgoSum etc. we save the extra code and use the
362 // available methods.
363 SwFootnoteIdxs& rFootnoteIdxs = GetFootnoteIdxs();
364 for( size_t nPos = 0; nPos < rFootnoteIdxs.size(); ++nPos )
366 SwTextFootnote *pTextFootnote = rFootnoteIdxs[ nPos ];
367 const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
368 if ( !rFootnote.IsEndNote() )
369 pTextFootnote->SetNumber(rFootnote.GetNumber(), rFootnote.GetNumberRLHidden(), rFootnote.GetNumStr());
374 if( FTNNUM_PAGE != rInfo.m_eNum )
375 GetFootnoteIdxs().UpdateAllFootnote();
376 else if( bFootnoteChrFormats )
378 mpFootnoteInfo->UpdateFormatOrAttr();
381 // #i81002# no update during loading
382 if ( !IsInReading() )
384 getIDocumentFieldsAccess().UpdateRefFields();
386 getIDocumentState().SetModified();
390 void SwDoc::SetEndNoteInfo(const SwEndNoteInfo& rInfo)
392 SwRootFrame* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout();
393 if( GetEndNoteInfo() == rInfo )
394 return;
396 if(GetIDocumentUndoRedo().DoesUndo())
398 GetIDocumentUndoRedo().AppendUndo(
399 std::make_unique<SwUndoEndNoteInfo>( GetEndNoteInfo(), *this ) );
402 bool bNumChg = rInfo.m_nFootnoteOffset != GetEndNoteInfo().m_nFootnoteOffset;
403 // this seems to be an optimization: UpdateAllFootnote() is only called
404 // if the offset changes; if the offset is the same,
405 // but type/prefix/suffix changes, just set new numbers.
406 bool const bExtra = !bNumChg &&
407 ( (rInfo.m_aFormat.GetNumberingType() !=
408 GetEndNoteInfo().m_aFormat.GetNumberingType())
409 || (rInfo.GetPrefix() != GetEndNoteInfo().GetPrefix())
410 || (rInfo.GetSuffix() != GetEndNoteInfo().GetSuffix())
412 bool bFootnoteDesc = rInfo.GetPageDesc( *this ) !=
413 GetEndNoteInfo().GetPageDesc( *this );
414 SwCharFormat *pOldChrFormat = GetEndNoteInfo().GetCharFormat( *this ),
415 *pNewChrFormat = rInfo.GetCharFormat( *this );
416 bool bFootnoteChrFormats = pOldChrFormat != pNewChrFormat;
418 *mpEndNoteInfo = rInfo;
420 if ( pTmpRoot )
422 if ( bFootnoteDesc )
424 for( auto aLayout : GetAllLayouts() )
425 aLayout->CheckFootnotePageDescs(true);
427 if ( bExtra )
429 // For messages regarding ErgoSum etc. we save the extra code and use the
430 // available methods.
431 SwFootnoteIdxs& rFootnoteIdxs = GetFootnoteIdxs();
432 for( size_t nPos = 0; nPos < rFootnoteIdxs.size(); ++nPos )
434 SwTextFootnote *pTextFootnote = rFootnoteIdxs[ nPos ];
435 const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote();
436 if ( rFootnote.IsEndNote() )
437 pTextFootnote->SetNumber(rFootnote.GetNumber(), rFootnote.GetNumberRLHidden(), rFootnote.GetNumStr());
441 if( bNumChg )
442 GetFootnoteIdxs().UpdateAllFootnote();
443 else if( bFootnoteChrFormats )
445 mpEndNoteInfo->UpdateFormatOrAttr();
448 // #i81002# no update during loading
449 if ( !IsInReading() )
451 getIDocumentFieldsAccess().UpdateRefFields();
453 getIDocumentState().SetModified();
457 bool SwDoc::SetCurFootnote( const SwPaM& rPam, const OUString& rNumStr,
458 bool bIsEndNote)
460 SwFootnoteIdxs& rFootnoteArr = GetFootnoteIdxs();
461 SwRootFrame* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout();
463 auto [pStart, pEnd] = rPam.StartEnd(); // SwPosition*
464 const SwNodeOffset nSttNd = pStart->GetNodeIndex();
465 const sal_Int32 nSttCnt = pStart->GetContentIndex();
466 const SwNodeOffset nEndNd = pEnd->GetNodeIndex();
467 const sal_Int32 nEndCnt = pEnd->GetContentIndex();
469 size_t nPos = 0;
470 rFootnoteArr.SeekEntry( pStart->GetNode(), &nPos );
472 std::unique_ptr<SwUndoChangeFootNote> pUndo;
473 if (GetIDocumentUndoRedo().DoesUndo())
475 GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it
476 pUndo.reset(new SwUndoChangeFootNote( rPam, rNumStr, bIsEndNote ));
479 bool bChg = false;
480 bool bTypeChgd = false;
481 const size_t nPosSave = nPos;
482 while( nPos < rFootnoteArr.size() )
484 SwTextFootnote* pTextFootnote = rFootnoteArr[ nPos++ ];
485 SwNodeOffset nIdx = SwTextFootnote_GetIndex(pTextFootnote);
486 if( nIdx >= nEndNd &&
487 ( nIdx != nEndNd || nEndCnt < pTextFootnote->GetStart() ) )
488 continue;
489 if( nIdx > nSttNd || ( nIdx == nSttNd &&
490 nSttCnt <= pTextFootnote->GetStart() ) )
492 const SwFormatFootnote& rFootnote = pTextFootnote->GetFootnote();
493 if( rFootnote.GetNumStr() != rNumStr ||
494 rFootnote.IsEndNote() != bIsEndNote )
496 bChg = true;
497 if ( pUndo )
499 pUndo->GetHistory().AddFootnote(*pTextFootnote);
502 pTextFootnote->SetNumber(rFootnote.GetNumber(), rFootnote.GetNumberRLHidden(), rNumStr);
503 if( rFootnote.IsEndNote() != bIsEndNote )
505 const_cast<SwFormatFootnote&>(rFootnote).SetEndNote( bIsEndNote );
506 bTypeChgd = true;
507 pTextFootnote->CheckCondColl();
508 //#i11339# dispose UNO wrapper when a footnote is changed to an endnote or vice versa
509 const_cast<SwFormatFootnote&>(rFootnote).InvalidateFootnote();
515 nPos = nPosSave; // There are more in the front!
516 while (nPos > 0)
518 SwTextFootnote* pTextFootnote = rFootnoteArr[ --nPos ];
519 SwNodeOffset nIdx = SwTextFootnote_GetIndex(pTextFootnote);
520 if( nIdx <= nSttNd &&
521 ( nIdx != nSttNd || nSttCnt > pTextFootnote->GetStart() ) )
522 continue;
523 if( nIdx < nEndNd || ( nIdx == nEndNd &&
524 nEndCnt >= pTextFootnote->GetStart() ) )
526 const SwFormatFootnote& rFootnote = pTextFootnote->GetFootnote();
527 if( rFootnote.GetNumStr() != rNumStr ||
528 rFootnote.IsEndNote() != bIsEndNote )
530 bChg = true;
531 if ( pUndo )
533 pUndo->GetHistory().AddFootnote(*pTextFootnote);
536 pTextFootnote->SetNumber(rFootnote.GetNumber(), rFootnote.GetNumberRLHidden(), rNumStr);
537 if( rFootnote.IsEndNote() != bIsEndNote )
539 const_cast<SwFormatFootnote&>(rFootnote).SetEndNote( bIsEndNote );
540 bTypeChgd = true;
541 pTextFootnote->CheckCondColl();
547 // Who needs to be triggered?
548 if( bChg )
550 if( pUndo )
552 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
555 if ( bTypeChgd )
556 rFootnoteArr.UpdateAllFootnote();
557 if( FTNNUM_PAGE != GetFootnoteInfo().m_eNum )
559 if ( !bTypeChgd )
560 rFootnoteArr.UpdateAllFootnote();
562 else if( pTmpRoot )
564 for( auto aLayout : GetAllLayouts() )
565 aLayout->UpdateFootnoteNums();
567 getIDocumentState().SetModified();
569 return bChg;
572 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */