1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
21 #include <rootfrm.hxx>
25 #include <pagedesc.hxx>
26 #include <charfmt.hxx>
27 #include <UndoAttribute.hxx>
30 #include <IDocumentFieldsAccess.hxx>
31 #include <IDocumentUndoRedo.hxx>
32 #include <IDocumentState.hxx>
33 #include <IDocumentLayoutAccess.hxx>
34 #include <IDocumentStylePoolAccess.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
;
61 bool SwEndNoteInfo::operator==( const SwEndNoteInfo
& rInfo
) const
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
) :
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
),
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() :
97 m_pTextFormatColl(nullptr),
99 m_pCharFormat(nullptr),
100 m_pAnchorFormat(nullptr),
102 m_nFootnoteOffset( 0 )
104 m_aFormat
.SetNumberingType(SVX_NUM_ROMAN_LOWER
);
107 SwPageDesc
* SwEndNoteInfo::GetPageDesc(SwDoc
& rDoc
) const
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
);
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
);
132 m_aDepends
.StartListening(m_pPageDesc
);
135 SwSection
* SwEndNoteInfo::GetSwSection(SwDoc
& rDoc
) const
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
;
174 void lcl_ResetPoolIdForDocAndSync(const sal_uInt16 nId
, SwCharFormat
* pFormat
, const SwEndNoteInfo
& rInfo
)
176 auto pDoc
= pFormat
->GetDoc();
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
),
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
),
224 SwCharFormat
* SwEndNoteInfo::GetCurrentCharFormat(const bool bAnchor
) const
231 void SwEndNoteInfo::UpdateFormatOrAttr()
233 auto pFormat
= GetCurrentCharFormat(m_pCharFormat
== nullptr);
234 if (!pFormat
|| !m_aDepends
.IsListeningTo(pFormat
) || pFormat
->IsFormatInDTOR())
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();
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
;
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
)
309 SwFootnoteInfo::SwFootnoteInfo() :
310 m_ePos( FTNPOS_PAGE
),
313 m_aFormat
.SetNumberingType(SVX_NUM_ARABIC
);
317 SwFootnoteInfo::~SwFootnoteInfo() = default;
319 void SwDoc::SetFootnoteInfo(const SwFootnoteInfo
& rInfo
)
321 SwRootFrame
* pTmpRoot
= getIDocumentLayoutAccess().GetCurrentLayout();
322 if( GetFootnoteInfo() == rInfo
)
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
;
348 o3tl::sorted_vector
<SwRootFrame
*> aAllLayouts
= GetAllLayouts();
350 for( auto aLayout
: aAllLayouts
)
351 aLayout
->AllRemoveFootnotes();
354 for( auto aLayout
: aAllLayouts
)
355 aLayout
->UpdateFootnoteNums();
357 for( auto aLayout
: aAllLayouts
)
358 aLayout
->CheckFootnotePageDescs(false);
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
)
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
;
424 for( auto aLayout
: GetAllLayouts() )
425 aLayout
->CheckFootnotePageDescs(true);
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());
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
,
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();
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
));
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() ) )
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
)
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
);
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!
518 SwTextFootnote
* pTextFootnote
= rFootnoteArr
[ --nPos
];
519 SwNodeOffset nIdx
= SwTextFootnote_GetIndex(pTextFootnote
);
520 if( nIdx
<= nSttNd
&&
521 ( nIdx
!= nSttNd
|| nSttCnt
> pTextFootnote
->GetStart() ) )
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
)
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
);
541 pTextFootnote
->CheckCondColl();
547 // Who needs to be triggered?
552 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo
));
556 rFootnoteArr
.UpdateAllFootnote();
557 if( FTNNUM_PAGE
!= GetFootnoteInfo().m_eNum
)
560 rFootnoteArr
.UpdateAllFootnote();
564 for( auto aLayout
: GetAllLayouts() )
565 aLayout
->UpdateFootnoteNums();
567 getIDocumentState().SetModified();
572 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */