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>
39 SwEndNoteInfo
& SwEndNoteInfo::operator=(const SwEndNoteInfo
& rInfo
)
41 m_pTextFormatColl
= rInfo
.m_pTextFormatColl
;
42 m_pPageDesc
= rInfo
.m_pPageDesc
;
43 m_pCharFormat
= rInfo
.m_pCharFormat
;
44 m_pAnchorFormat
= rInfo
.m_pAnchorFormat
;
45 m_aDepends
.EndListeningAll();
46 m_aDepends
.StartListening(m_pTextFormatColl
);
47 m_aDepends
.StartListening(m_pPageDesc
);
48 m_aDepends
.StartListening(m_pCharFormat
);
49 m_aDepends
.StartListening(m_pAnchorFormat
);
51 m_aFormat
= rInfo
.m_aFormat
;
52 m_nFootnoteOffset
= rInfo
.m_nFootnoteOffset
;
53 m_bEndNote
= rInfo
.m_bEndNote
;
54 m_sPrefix
= rInfo
.m_sPrefix
;
55 m_sSuffix
= rInfo
.m_sSuffix
;
59 bool SwEndNoteInfo::operator==( const SwEndNoteInfo
& rInfo
) const
62 m_pTextFormatColl
== rInfo
.m_pTextFormatColl
&&
63 m_pPageDesc
== rInfo
.m_pPageDesc
&&
64 m_pCharFormat
== rInfo
.m_pCharFormat
&&
65 m_pAnchorFormat
== rInfo
.m_pAnchorFormat
&&
66 m_aFormat
.GetNumberingType() == rInfo
.m_aFormat
.GetNumberingType() &&
67 m_nFootnoteOffset
== rInfo
.m_nFootnoteOffset
&&
68 m_bEndNote
== rInfo
.m_bEndNote
&&
69 m_sPrefix
== rInfo
.m_sPrefix
&&
70 m_sSuffix
== rInfo
.m_sSuffix
;
73 SwEndNoteInfo::SwEndNoteInfo(const SwEndNoteInfo
& rInfo
) :
76 m_pTextFormatColl(rInfo
.m_pTextFormatColl
),
77 m_pPageDesc(rInfo
.m_pPageDesc
),
78 m_pCharFormat(rInfo
.m_pCharFormat
),
79 m_pAnchorFormat(rInfo
.m_pAnchorFormat
),
80 m_sPrefix( rInfo
.m_sPrefix
),
81 m_sSuffix( rInfo
.m_sSuffix
),
83 m_aFormat( rInfo
.m_aFormat
),
84 m_nFootnoteOffset( rInfo
.m_nFootnoteOffset
)
86 m_aDepends
.StartListening(m_pTextFormatColl
);
87 m_aDepends
.StartListening(m_pPageDesc
);
88 m_aDepends
.StartListening(m_pCharFormat
);
89 m_aDepends
.StartListening(m_pAnchorFormat
);
92 SwEndNoteInfo::SwEndNoteInfo() :
95 m_pTextFormatColl(nullptr),
97 m_pCharFormat(nullptr),
98 m_pAnchorFormat(nullptr),
100 m_nFootnoteOffset( 0 )
102 m_aFormat
.SetNumberingType(SVX_NUM_ROMAN_LOWER
);
105 SwPageDesc
* SwEndNoteInfo::GetPageDesc(SwDoc
& rDoc
) const
109 m_pPageDesc
= rDoc
.getIDocumentStylePoolAccess().GetPageDescFromPool( o3tl::narrowing
<sal_uInt16
>(
110 m_bEndNote
? RES_POOLPAGE_ENDNOTE
: RES_POOLPAGE_FOOTNOTE
) );
111 m_aDepends
.StartListening(m_pPageDesc
);
116 bool SwEndNoteInfo::KnowsPageDesc() const
118 return m_pPageDesc
!= nullptr;
121 bool SwEndNoteInfo::DependsOn(const SwPageDesc
* pDesc
) const
123 return m_pPageDesc
== pDesc
;
126 void SwEndNoteInfo::ChgPageDesc(SwPageDesc
* pDesc
)
128 m_aDepends
.EndListening(m_pPageDesc
);
130 m_aDepends
.StartListening(m_pPageDesc
);
133 void SwEndNoteInfo::SetFootnoteTextColl(SwTextFormatColl
& rFormat
)
135 m_aDepends
.EndListening(m_pTextFormatColl
);
136 m_pTextFormatColl
= &rFormat
;
137 m_aDepends
.StartListening(m_pTextFormatColl
);
140 SwCharFormat
* SwEndNoteInfo::GetCharFormat(SwDoc
& rDoc
) const
142 auto pCharFormatFromDoc
= rDoc
.getIDocumentStylePoolAccess().GetCharFormatFromPool( o3tl::narrowing
<sal_uInt16
>(
143 m_bEndNote
? RES_POOLCHR_ENDNOTE
: RES_POOLCHR_FOOTNOTE
) );
144 if (m_pCharFormat
!= pCharFormatFromDoc
)
146 m_aDepends
.EndListening(m_pCharFormat
);
147 m_aDepends
.StartListening(pCharFormatFromDoc
);
148 m_pCharFormat
= pCharFormatFromDoc
;
150 return m_pCharFormat
;
155 void lcl_ResetPoolIdForDocAndSync(const sal_uInt16 nId
, SwCharFormat
* pFormat
, const SwEndNoteInfo
& rInfo
)
157 auto pDoc
= pFormat
->GetDoc();
160 for(auto pDocFormat
: *pDoc
->GetCharFormats())
162 if(pDocFormat
== pFormat
)
163 pDocFormat
->SetPoolFormatId(nId
);
164 else if(pDocFormat
->GetPoolFormatId() == nId
)
165 pDocFormat
->SetPoolFormatId(0);
167 rInfo
.GetCharFormat(*pDoc
);
168 rInfo
.GetAnchorCharFormat(*pDoc
);
172 void SwEndNoteInfo::SetCharFormat(SwCharFormat
* pFormat
)
174 lcl_ResetPoolIdForDocAndSync(
175 o3tl::narrowing
<sal_uInt16
>(m_bEndNote
176 ? RES_POOLCHR_ENDNOTE
177 : RES_POOLCHR_FOOTNOTE
),
182 SwCharFormat
* SwEndNoteInfo::GetAnchorCharFormat(SwDoc
& rDoc
) const
184 auto pAnchorFormatFromDoc
= rDoc
.getIDocumentStylePoolAccess().GetCharFormatFromPool( o3tl::narrowing
<sal_uInt16
>(
185 m_bEndNote
? RES_POOLCHR_ENDNOTE_ANCHOR
: RES_POOLCHR_FOOTNOTE_ANCHOR
) );
186 if(m_pAnchorFormat
!= pAnchorFormatFromDoc
)
188 m_aDepends
.EndListening(m_pAnchorFormat
);
189 m_aDepends
.StartListening(pAnchorFormatFromDoc
);
190 m_pAnchorFormat
= pAnchorFormatFromDoc
;
192 return m_pAnchorFormat
;
195 void SwEndNoteInfo::SetAnchorCharFormat(SwCharFormat
* pFormat
)
197 lcl_ResetPoolIdForDocAndSync(
198 o3tl::narrowing
<sal_uInt16
>(m_bEndNote
199 ? RES_POOLCHR_ENDNOTE_ANCHOR
200 : RES_POOLCHR_FOOTNOTE_ANCHOR
),
205 SwCharFormat
* SwEndNoteInfo::GetCurrentCharFormat(const bool bAnchor
) const
212 void SwEndNoteInfo::UpdateFormatOrAttr()
214 auto pFormat
= GetCurrentCharFormat(m_pCharFormat
== nullptr);
215 if (!pFormat
|| !m_aDepends
.IsListeningTo(pFormat
) || pFormat
->IsFormatInDTOR())
217 SwDoc
* pDoc
= pFormat
->GetDoc();
218 SwFootnoteIdxs
& rFootnoteIdxs
= pDoc
->GetFootnoteIdxs();
219 for(auto pTextFootnote
: rFootnoteIdxs
)
221 const SwFormatFootnote
&rFootnote
= pTextFootnote
->GetFootnote();
222 if(rFootnote
.IsEndNote() == m_bEndNote
)
223 pTextFootnote
->SetNumber(rFootnote
.GetNumber(), rFootnote
.GetNumberRLHidden(), rFootnote
.GetNumStr());
228 void SwEndNoteInfo::SwClientNotify( const SwModify
& rModify
, const SfxHint
& rHint
)
230 if (rHint
.GetId() == SfxHintId::SwLegacyModify
)
232 auto pLegacyHint
= static_cast<const sw::LegacyModifyHint
*>(&rHint
);
233 switch(pLegacyHint
->GetWhich())
235 case RES_ATTRSET_CHG
:
237 UpdateFormatOrAttr();
240 CheckRegistration( pLegacyHint
->m_pOld
);
243 else if (auto pModifyChangedHint
= dynamic_cast<const sw::ModifyChangedHint
*>(&rHint
))
245 auto pNew
= const_cast<sw::BroadcastingModify
*>(static_cast<const sw::BroadcastingModify
*>(pModifyChangedHint
->m_pNew
));
246 if(m_pAnchorFormat
== &rModify
)
247 m_pAnchorFormat
= static_cast<SwCharFormat
*>(pNew
);
248 else if(m_pCharFormat
== &rModify
)
249 m_pCharFormat
= static_cast<SwCharFormat
*>(pNew
);
250 else if(m_pPageDesc
== &rModify
)
251 m_pPageDesc
= static_cast<SwPageDesc
*>(pNew
);
252 else if(m_pTextFormatColl
== &rModify
)
253 m_pTextFormatColl
= static_cast<SwTextFormatColl
*>(pNew
);
257 SwFootnoteInfo
& SwFootnoteInfo::operator=(const SwFootnoteInfo
& rInfo
)
259 SwEndNoteInfo::operator=(rInfo
);
260 m_aQuoVadis
= rInfo
.m_aQuoVadis
;
261 m_aErgoSum
= rInfo
.m_aErgoSum
;
262 m_ePos
= rInfo
.m_ePos
;
263 m_eNum
= rInfo
.m_eNum
;
267 bool SwFootnoteInfo::operator==( const SwFootnoteInfo
& rInfo
) const
269 return m_ePos
== rInfo
.m_ePos
&&
270 m_eNum
== rInfo
.m_eNum
&&
271 SwEndNoteInfo::operator==(rInfo
) &&
272 m_aQuoVadis
== rInfo
.m_aQuoVadis
&&
273 m_aErgoSum
== rInfo
.m_aErgoSum
;
276 SwFootnoteInfo::SwFootnoteInfo(const SwFootnoteInfo
& rInfo
) :
277 SwEndNoteInfo( rInfo
),
278 m_aQuoVadis( rInfo
.m_aQuoVadis
),
279 m_aErgoSum( rInfo
.m_aErgoSum
),
280 m_ePos( rInfo
.m_ePos
),
281 m_eNum( rInfo
.m_eNum
)
286 SwFootnoteInfo::SwFootnoteInfo() :
287 m_ePos( FTNPOS_PAGE
),
290 m_aFormat
.SetNumberingType(SVX_NUM_ARABIC
);
294 void SwDoc::SetFootnoteInfo(const SwFootnoteInfo
& rInfo
)
296 SwRootFrame
* pTmpRoot
= getIDocumentLayoutAccess().GetCurrentLayout();
297 if( GetFootnoteInfo() == rInfo
)
300 const SwFootnoteInfo
&rOld
= GetFootnoteInfo();
302 if (GetIDocumentUndoRedo().DoesUndo())
304 GetIDocumentUndoRedo().AppendUndo( std::make_unique
<SwUndoFootNoteInfo
>(rOld
, *this) );
307 bool bFootnotePos
= rInfo
.m_ePos
!= rOld
.m_ePos
;
308 bool bFootnoteDesc
= rOld
.m_ePos
== FTNPOS_CHAPTER
&&
309 rInfo
.GetPageDesc( *this ) != rOld
.GetPageDesc( *this );
310 bool bExtra
= rInfo
.m_aQuoVadis
!= rOld
.m_aQuoVadis
||
311 rInfo
.m_aErgoSum
!= rOld
.m_aErgoSum
||
312 rInfo
.m_aFormat
.GetNumberingType() != rOld
.m_aFormat
.GetNumberingType() ||
313 rInfo
.GetPrefix() != rOld
.GetPrefix() ||
314 rInfo
.GetSuffix() != rOld
.GetSuffix();
315 SwCharFormat
*pOldChrFormat
= rOld
.GetCharFormat( *this ),
316 *pNewChrFormat
= rInfo
.GetCharFormat( *this );
317 bool bFootnoteChrFormats
= pOldChrFormat
!= pNewChrFormat
;
319 *mpFootnoteInfo
= rInfo
;
323 o3tl::sorted_vector
<SwRootFrame
*> aAllLayouts
= GetAllLayouts();
325 for( auto aLayout
: aAllLayouts
)
326 aLayout
->AllRemoveFootnotes();
329 for( auto aLayout
: aAllLayouts
)
330 aLayout
->UpdateFootnoteNums();
332 for( auto aLayout
: aAllLayouts
)
333 aLayout
->CheckFootnotePageDescs(false);
336 // For messages regarding ErgoSum etc. we save the extra code and use the
337 // available methods.
338 SwFootnoteIdxs
& rFootnoteIdxs
= GetFootnoteIdxs();
339 for( size_t nPos
= 0; nPos
< rFootnoteIdxs
.size(); ++nPos
)
341 SwTextFootnote
*pTextFootnote
= rFootnoteIdxs
[ nPos
];
342 const SwFormatFootnote
&rFootnote
= pTextFootnote
->GetFootnote();
343 if ( !rFootnote
.IsEndNote() )
344 pTextFootnote
->SetNumber(rFootnote
.GetNumber(), rFootnote
.GetNumberRLHidden(), rFootnote
.GetNumStr());
349 if( FTNNUM_PAGE
!= rInfo
.m_eNum
)
350 GetFootnoteIdxs().UpdateAllFootnote();
351 else if( bFootnoteChrFormats
)
353 mpFootnoteInfo
->UpdateFormatOrAttr();
356 // #i81002# no update during loading
357 if ( !IsInReading() )
359 getIDocumentFieldsAccess().UpdateRefFields();
361 getIDocumentState().SetModified();
365 void SwDoc::SetEndNoteInfo(const SwEndNoteInfo
& rInfo
)
367 SwRootFrame
* pTmpRoot
= getIDocumentLayoutAccess().GetCurrentLayout();
368 if( GetEndNoteInfo() == rInfo
)
371 if(GetIDocumentUndoRedo().DoesUndo())
373 GetIDocumentUndoRedo().AppendUndo(
374 std::make_unique
<SwUndoEndNoteInfo
>( GetEndNoteInfo(), *this ) );
377 bool bNumChg
= rInfo
.m_nFootnoteOffset
!= GetEndNoteInfo().m_nFootnoteOffset
;
378 // this seems to be an optimization: UpdateAllFootnote() is only called
379 // if the offset changes; if the offset is the same,
380 // but type/prefix/suffix changes, just set new numbers.
381 bool const bExtra
= !bNumChg
&&
382 ( (rInfo
.m_aFormat
.GetNumberingType() !=
383 GetEndNoteInfo().m_aFormat
.GetNumberingType())
384 || (rInfo
.GetPrefix() != GetEndNoteInfo().GetPrefix())
385 || (rInfo
.GetSuffix() != GetEndNoteInfo().GetSuffix())
387 bool bFootnoteDesc
= rInfo
.GetPageDesc( *this ) !=
388 GetEndNoteInfo().GetPageDesc( *this );
389 SwCharFormat
*pOldChrFormat
= GetEndNoteInfo().GetCharFormat( *this ),
390 *pNewChrFormat
= rInfo
.GetCharFormat( *this );
391 bool bFootnoteChrFormats
= pOldChrFormat
!= pNewChrFormat
;
393 *mpEndNoteInfo
= rInfo
;
399 for( auto aLayout
: GetAllLayouts() )
400 aLayout
->CheckFootnotePageDescs(true);
404 // For messages regarding ErgoSum etc. we save the extra code and use the
405 // available methods.
406 SwFootnoteIdxs
& rFootnoteIdxs
= GetFootnoteIdxs();
407 for( size_t nPos
= 0; nPos
< rFootnoteIdxs
.size(); ++nPos
)
409 SwTextFootnote
*pTextFootnote
= rFootnoteIdxs
[ nPos
];
410 const SwFormatFootnote
&rFootnote
= pTextFootnote
->GetFootnote();
411 if ( rFootnote
.IsEndNote() )
412 pTextFootnote
->SetNumber(rFootnote
.GetNumber(), rFootnote
.GetNumberRLHidden(), rFootnote
.GetNumStr());
417 GetFootnoteIdxs().UpdateAllFootnote();
418 else if( bFootnoteChrFormats
)
420 mpEndNoteInfo
->UpdateFormatOrAttr();
423 // #i81002# no update during loading
424 if ( !IsInReading() )
426 getIDocumentFieldsAccess().UpdateRefFields();
428 getIDocumentState().SetModified();
432 bool SwDoc::SetCurFootnote( const SwPaM
& rPam
, const OUString
& rNumStr
,
435 SwFootnoteIdxs
& rFootnoteArr
= GetFootnoteIdxs();
436 SwRootFrame
* pTmpRoot
= getIDocumentLayoutAccess().GetCurrentLayout();
438 auto [pStt
, pEnd
] = rPam
.StartEnd(); // SwPosition*
439 const SwNodeOffset nSttNd
= pStt
->GetNodeIndex();
440 const sal_Int32 nSttCnt
= pStt
->GetContentIndex();
441 const SwNodeOffset nEndNd
= pEnd
->GetNodeIndex();
442 const sal_Int32 nEndCnt
= pEnd
->GetContentIndex();
445 rFootnoteArr
.SeekEntry( pStt
->GetNode(), &nPos
);
447 std::unique_ptr
<SwUndoChangeFootNote
> pUndo
;
448 if (GetIDocumentUndoRedo().DoesUndo())
450 GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it
451 pUndo
.reset(new SwUndoChangeFootNote( rPam
, rNumStr
, bIsEndNote
));
455 bool bTypeChgd
= false;
456 const size_t nPosSave
= nPos
;
457 while( nPos
< rFootnoteArr
.size() )
459 SwTextFootnote
* pTextFootnote
= rFootnoteArr
[ nPos
++ ];
460 SwNodeOffset nIdx
= SwTextFootnote_GetIndex(pTextFootnote
);
461 if( nIdx
>= nEndNd
&&
462 ( nIdx
!= nEndNd
|| nEndCnt
< pTextFootnote
->GetStart() ) )
464 if( nIdx
> nSttNd
|| ( nIdx
== nSttNd
&&
465 nSttCnt
<= pTextFootnote
->GetStart() ) )
467 const SwFormatFootnote
& rFootnote
= pTextFootnote
->GetFootnote();
468 if( rFootnote
.GetNumStr() != rNumStr
||
469 rFootnote
.IsEndNote() != bIsEndNote
)
474 pUndo
->GetHistory().Add( *pTextFootnote
);
477 pTextFootnote
->SetNumber(rFootnote
.GetNumber(), rFootnote
.GetNumberRLHidden(), rNumStr
);
478 if( rFootnote
.IsEndNote() != bIsEndNote
)
480 const_cast<SwFormatFootnote
&>(rFootnote
).SetEndNote( bIsEndNote
);
482 pTextFootnote
->CheckCondColl();
483 //#i11339# dispose UNO wrapper when a footnote is changed to an endnote or vice versa
484 const_cast<SwFormatFootnote
&>(rFootnote
).InvalidateFootnote();
490 nPos
= nPosSave
; // There are more in the front!
493 SwTextFootnote
* pTextFootnote
= rFootnoteArr
[ --nPos
];
494 SwNodeOffset nIdx
= SwTextFootnote_GetIndex(pTextFootnote
);
495 if( nIdx
<= nSttNd
&&
496 ( nIdx
!= nSttNd
|| nSttCnt
> pTextFootnote
->GetStart() ) )
498 if( nIdx
< nEndNd
|| ( nIdx
== nEndNd
&&
499 nEndCnt
>= pTextFootnote
->GetStart() ) )
501 const SwFormatFootnote
& rFootnote
= pTextFootnote
->GetFootnote();
502 if( rFootnote
.GetNumStr() != rNumStr
||
503 rFootnote
.IsEndNote() != bIsEndNote
)
508 pUndo
->GetHistory().Add( *pTextFootnote
);
511 pTextFootnote
->SetNumber(rFootnote
.GetNumber(), rFootnote
.GetNumberRLHidden(), rNumStr
);
512 if( rFootnote
.IsEndNote() != bIsEndNote
)
514 const_cast<SwFormatFootnote
&>(rFootnote
).SetEndNote( bIsEndNote
);
516 pTextFootnote
->CheckCondColl();
522 // Who needs to be triggered?
527 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo
));
531 rFootnoteArr
.UpdateAllFootnote();
532 if( FTNNUM_PAGE
!= GetFootnoteInfo().m_eNum
)
535 rFootnoteArr
.UpdateAllFootnote();
539 for( auto aLayout
: GetAllLayouts() )
540 aLayout
->UpdateFootnoteNums();
542 getIDocumentState().SetModified();
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */