android: Update app-specific/MIME type icons
[LibreOffice.git] / sw / source / core / doc / docftn.cxx
blob61dbe5071cd293f79dc74e5277bd32f561e59523
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>
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;
56 return *this;
59 bool SwEndNoteInfo::operator==( const SwEndNoteInfo& rInfo ) const
61 return
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) :
74 SwClient(nullptr),
75 m_aDepends(*this),
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 ),
82 m_bEndNote( true ),
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() :
93 SwClient(nullptr),
94 m_aDepends(*this),
95 m_pTextFormatColl(nullptr),
96 m_pPageDesc(nullptr),
97 m_pCharFormat(nullptr),
98 m_pAnchorFormat(nullptr),
99 m_bEndNote( true ),
100 m_nFootnoteOffset( 0 )
102 m_aFormat.SetNumberingType(SVX_NUM_ROMAN_LOWER);
105 SwPageDesc* SwEndNoteInfo::GetPageDesc(SwDoc& rDoc) const
107 if(!m_pPageDesc)
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);
113 return 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);
129 m_pPageDesc = pDesc;
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;
153 namespace
155 void lcl_ResetPoolIdForDocAndSync(const sal_uInt16 nId, SwCharFormat* pFormat, const SwEndNoteInfo& rInfo)
157 auto pDoc = pFormat->GetDoc();
158 if(!pDoc)
159 return;
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),
178 pFormat,
179 *this);
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),
201 pFormat,
202 *this);
205 SwCharFormat* SwEndNoteInfo::GetCurrentCharFormat(const bool bAnchor) const
207 return bAnchor
208 ? m_pAnchorFormat
209 : m_pCharFormat;
212 void SwEndNoteInfo::UpdateFormatOrAttr()
214 auto pFormat = GetCurrentCharFormat(m_pCharFormat == nullptr);
215 if (!pFormat || !m_aDepends.IsListeningTo(pFormat) || pFormat->IsFormatInDTOR())
216 return;
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:
236 case RES_FMT_CHG:
237 UpdateFormatOrAttr();
238 break;
239 default:
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;
264 return *this;
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 )
283 m_bEndNote = false;
286 SwFootnoteInfo::SwFootnoteInfo() :
287 m_ePos( FTNPOS_PAGE ),
288 m_eNum( FTNNUM_DOC )
290 m_aFormat.SetNumberingType(SVX_NUM_ARABIC);
291 m_bEndNote = false;
294 void SwDoc::SetFootnoteInfo(const SwFootnoteInfo& rInfo)
296 SwRootFrame* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout();
297 if( GetFootnoteInfo() == rInfo )
298 return;
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;
321 if (pTmpRoot)
323 o3tl::sorted_vector<SwRootFrame*> aAllLayouts = GetAllLayouts();
324 if ( bFootnotePos )
325 for( auto aLayout : aAllLayouts )
326 aLayout->AllRemoveFootnotes();
327 else
329 for( auto aLayout : aAllLayouts )
330 aLayout->UpdateFootnoteNums();
331 if ( bFootnoteDesc )
332 for( auto aLayout : aAllLayouts )
333 aLayout->CheckFootnotePageDescs(false);
334 if ( bExtra )
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 )
369 return;
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;
395 if ( pTmpRoot )
397 if ( bFootnoteDesc )
399 for( auto aLayout : GetAllLayouts() )
400 aLayout->CheckFootnotePageDescs(true);
402 if ( bExtra )
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());
416 if( bNumChg )
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,
433 bool bIsEndNote)
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();
444 size_t nPos = 0;
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 ));
454 bool bChg = false;
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() ) )
463 continue;
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 )
471 bChg = true;
472 if ( pUndo )
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 );
481 bTypeChgd = true;
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!
491 while( nPos )
493 SwTextFootnote* pTextFootnote = rFootnoteArr[ --nPos ];
494 SwNodeOffset nIdx = SwTextFootnote_GetIndex(pTextFootnote);
495 if( nIdx <= nSttNd &&
496 ( nIdx != nSttNd || nSttCnt > pTextFootnote->GetStart() ) )
497 continue;
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 )
505 bChg = true;
506 if ( pUndo )
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 );
515 bTypeChgd = true;
516 pTextFootnote->CheckCondColl();
522 // Who needs to be triggered?
523 if( bChg )
525 if( pUndo )
527 GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
530 if ( bTypeChgd )
531 rFootnoteArr.UpdateAllFootnote();
532 if( FTNNUM_PAGE != GetFootnoteInfo().m_eNum )
534 if ( !bTypeChgd )
535 rFootnoteArr.UpdateAllFootnote();
537 else if( pTmpRoot )
539 for( auto aLayout : GetAllLayouts() )
540 aLayout->UpdateFootnoteNums();
542 getIDocumentState().SetModified();
544 return bChg;
547 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */