Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / sw / source / core / docnode / section.cxx
blobbce8f371f9ee3b12048805c242a8a983dd68df84
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 <libxml/xmlstring.h>
21 #include <libxml/xmlwriter.h>
22 #include <stdlib.h>
23 #include <hintids.hxx>
24 #include <osl/diagnose.h>
25 #include <sot/exchange.hxx>
26 #include <svl/stritem.hxx>
27 #include <sfx2/docfile.hxx>
28 #include <editeng/protitem.hxx>
29 #include <sfx2/linkmgr.hxx>
30 #include <sfx2/sfxsids.hrc>
31 #include <docary.hxx>
32 #include <fmtcntnt.hxx>
33 #include <fmtpdsc.hxx>
34 #include <doc.hxx>
35 #include <IDocumentUndoRedo.hxx>
36 #include <DocumentLinksAdministrationManager.hxx>
37 #include <DocumentContentOperationsManager.hxx>
38 #include <IDocumentRedlineAccess.hxx>
39 #include <IDocumentFieldsAccess.hxx>
40 #include <IDocumentStylePoolAccess.hxx>
41 #include <IDocumentState.hxx>
42 #include <IDocumentLayoutAccess.hxx>
43 #include <node.hxx>
44 #include <pam.hxx>
45 #include <frmatr.hxx>
46 #include <frmtool.hxx>
47 #include <editsh.hxx>
48 #include <hints.hxx>
49 #include <docsh.hxx>
50 #include <ndtxt.hxx>
51 #include <section.hxx>
52 #include <swserv.hxx>
53 #include <shellio.hxx>
54 #include <poolfmt.hxx>
55 #include <swbaslnk.hxx>
56 #include <mvsave.hxx>
57 #include <ftnidx.hxx>
58 #include <doctxm.hxx>
59 #include <fmteiro.hxx>
60 #include <unosection.hxx>
61 #include <calbck.hxx>
62 #include <fmtclds.hxx>
63 #include <algorithm>
64 #include <utility>
65 #include "ndsect.hxx"
67 using namespace ::com::sun::star;
69 namespace {
70 class SwIntrnlSectRefLink : public SwBaseLink
72 SwSectionFormat& m_rSectFormat;
74 public:
75 SwIntrnlSectRefLink(SwSectionFormat& rFormat, SfxLinkUpdateMode nUpdateType)
76 : SwBaseLink(nUpdateType, SotClipboardFormatId::RTF)
77 , m_rSectFormat(rFormat)
80 virtual void Closed() override;
81 virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
82 const OUString& rMimeType, const css::uno::Any & rValue ) override;
84 virtual const SwNode* GetAnchor() const override;
85 virtual bool IsInRange( SwNodeOffset nSttNd, SwNodeOffset nEndNd ) const override;
87 SwSectionNode* GetSectNode()
89 const SwNode* pSectNd( GetAnchor() );
90 return const_cast<SwSectionNode*>( pSectNd->GetSectionNode() );
95 SwSectionData::SwSectionData(SectionType const eType, OUString aName)
96 : m_eType(eType)
97 , m_sSectionName(std::move(aName))
98 , m_bHiddenFlag(false)
99 , m_bProtectFlag(false)
100 , m_bEditInReadonlyFlag(false) // edit in readonly sections
101 , m_bHidden(false)
102 , m_bCondHiddenFlag(true)
103 , m_bConnectFlag(true)
107 // this must have the same semantics as operator=()
108 SwSectionData::SwSectionData(SwSection const& rSection)
109 : m_eType(rSection.GetType())
110 , m_sSectionName(rSection.GetSectionName())
111 , m_sCondition(rSection.GetCondition())
112 , m_sLinkFileName(rSection.GetLinkFileName())
113 , m_sLinkFilePassword(rSection.GetLinkFilePassword())
114 , m_Password(rSection.GetPassword())
115 , m_bHiddenFlag(rSection.IsHiddenFlag())
116 , m_bProtectFlag(rSection.IsProtect())
117 // edit in readonly sections
118 , m_bEditInReadonlyFlag(rSection.IsEditInReadonly())
119 , m_bHidden(rSection.IsHidden())
120 , m_bCondHiddenFlag(true)
121 , m_bConnectFlag(rSection.IsConnectFlag())
125 // this must have the same semantics as operator=()
126 SwSectionData::SwSectionData(SwSectionData const& rOther)
127 : m_eType(rOther.m_eType)
128 , m_sSectionName(rOther.m_sSectionName)
129 , m_sCondition(rOther.m_sCondition)
130 , m_sLinkFileName(rOther.m_sLinkFileName)
131 , m_sLinkFilePassword(rOther.m_sLinkFilePassword)
132 , m_Password(rOther.m_Password)
133 , m_bHiddenFlag(rOther.m_bHiddenFlag)
134 , m_bProtectFlag(rOther.m_bProtectFlag)
135 // edit in readonly sections
136 , m_bEditInReadonlyFlag(rOther.m_bEditInReadonlyFlag)
137 , m_bHidden(rOther.m_bHidden)
138 , m_bCondHiddenFlag(true)
139 , m_bConnectFlag(rOther.m_bConnectFlag)
143 // the semantics here are weird for reasons of backward compatibility
144 SwSectionData & SwSectionData::operator= (SwSectionData const& rOther)
146 m_eType = rOther.m_eType;
147 m_sSectionName = rOther.m_sSectionName;
148 m_sCondition = rOther.m_sCondition;
149 m_sLinkFileName = rOther.m_sLinkFileName;
150 m_sLinkFilePassword = rOther.m_sLinkFilePassword;
151 m_bConnectFlag = rOther.m_bConnectFlag;
152 m_Password = rOther.m_Password;
154 m_bEditInReadonlyFlag = rOther.m_bEditInReadonlyFlag;
155 m_bProtectFlag = rOther.m_bProtectFlag;
157 m_bHidden = rOther.m_bHidden;
158 // FIXME: old code did not assign m_bHiddenFlag ?
159 // FIXME: why should m_bCondHiddenFlag always default to true?
160 m_bCondHiddenFlag = true;
162 return *this;
165 // the semantics here are weird for reasons of backward compatibility
166 bool SwSectionData::operator==(SwSectionData const& rOther) const
168 return (m_eType == rOther.m_eType)
169 && (m_sSectionName == rOther.m_sSectionName)
170 && (m_sCondition == rOther.m_sCondition)
171 && (m_bHidden == rOther.m_bHidden)
172 && (m_bProtectFlag == rOther.m_bProtectFlag)
173 && (m_bEditInReadonlyFlag == rOther.m_bEditInReadonlyFlag)
174 && (m_sLinkFileName == rOther.m_sLinkFileName)
175 && (m_sLinkFilePassword == rOther.m_sLinkFilePassword)
176 && (m_Password == rOther.m_Password);
177 // FIXME: old code ignored m_bCondHiddenFlag m_bHiddenFlag m_bConnectFlag
180 void SwSectionData::dumpAsXml(xmlTextWriterPtr pWriter) const
182 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwSectionData"));
183 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
184 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("section-name"), BAD_CAST(m_sSectionName.toUtf8().getStr()));
185 (void)xmlTextWriterEndElement(pWriter);
188 SwSection::SwSection(
189 SectionType const eType, OUString const& rName, SwSectionFormat & rFormat)
190 : SwClient(& rFormat)
191 , m_Data(eType, rName)
193 StartListening(rFormat.GetNotifier());
195 SwSection *const pParentSect = GetParent();
196 if( pParentSect )
198 // edit in readonly sections
199 m_Data.SetEditInReadonlyFlag( pParentSect->IsEditInReadonlyFlag() );
202 m_Data.SetProtectFlag( rFormat.GetProtect().IsContentProtected() );
204 if (!m_Data.IsEditInReadonlyFlag()) // edit in readonly sections
206 m_Data.SetEditInReadonlyFlag( rFormat.GetEditInReadonly().GetValue() );
210 SwSection::~SwSection()
212 SwSectionFormat* pFormat = GetFormat();
213 if( !pFormat )
214 return;
216 SwDoc* pDoc = pFormat->GetDoc();
217 if( pDoc->IsInDtor() )
219 // We reattach our Format to the default FrameFormat
220 // to not get any dependencies
221 if( pFormat->DerivedFrom() != pDoc->GetDfltFrameFormat() )
222 pFormat->RegisterToFormat( *pDoc->GetDfltFrameFormat() );
224 else
226 pFormat->Remove( this ); // remove
227 SvtListener::EndListeningAll();
229 if (SectionType::Content != m_Data.GetType())
231 pDoc->getIDocumentLinksAdministration().GetLinkManager().Remove( m_RefLink.get() );
234 if (m_RefObj.is())
236 pDoc->getIDocumentLinksAdministration().GetLinkManager().RemoveServer( m_RefObj.get() );
239 // If the Section is the last Client in the Format we can delete it
240 pFormat->RemoveAllUnos();
241 if( !pFormat->HasWriterListeners() )
243 // Do not add to the Undo. This should've happened earlier.
244 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
245 pDoc->DelSectionFormat( pFormat );
248 if (m_RefObj.is())
250 m_RefObj->Closed();
254 void SwSection::SetSectionData(SwSectionData const& rData)
256 bool const bOldHidden( m_Data.IsHidden() );
257 m_Data = rData;
258 // The next two may actually overwrite the m_Data.m_bProtect or EditInReadonly Flag
259 // in Modify, which should result in same flag value as the old code!
260 SetProtect(m_Data.IsProtectFlag());
261 SetEditInReadonly(m_Data.IsEditInReadonlyFlag());
262 if (bOldHidden != m_Data.IsHidden()) // check if changed...
264 ImplSetHiddenFlag(m_Data.IsHidden(), m_Data.IsCondHidden());
268 bool SwSection::DataEquals(SwSectionData const& rCmp) const
270 // note that the old code compared the flags of the parameter with the
271 // format attributes of this; the following mess should do the same...
272 (void) GetLinkFileName(); // updates m_sLinkFileName
273 bool const bProtect(m_Data.IsProtectFlag());
274 bool const bEditInReadonly(m_Data.IsEditInReadonlyFlag());
275 m_Data.SetProtectFlag(IsProtect());
276 m_Data.SetEditInReadonlyFlag(IsEditInReadonly());
277 bool const bResult( m_Data == rCmp );
278 m_Data.SetProtectFlag(bProtect);
279 m_Data.SetEditInReadonlyFlag(bEditInReadonly);
280 return bResult;
283 void SwSection::ImplSetHiddenFlag(bool const bTmpHidden, bool const bCondition)
285 SwSectionFormat* pFormat = GetFormat();
286 OSL_ENSURE(pFormat, "ImplSetHiddenFlag: no format?");
287 if( !pFormat )
288 return;
290 const bool bHide = bTmpHidden && bCondition;
292 if (bHide) // should be hidden
294 if (!m_Data.IsHiddenFlag()) // is not hidden
296 // Is the Parent hidden?
297 // This should be shown by the bHiddenFlag.
299 // Tell all Children that they are hidden
300 const sw::SectionHidden aHint;
301 pFormat->CallSwClientNotify(aHint);
303 // Delete all Frames
304 pFormat->DelFrames();
307 else if (m_Data.IsHiddenFlag()) // show Nodes again
309 // Show all Frames (Child Sections are accounted for by MakeFrames)
310 // Only if the Parent Section is not restricting us!
311 SwSection* pParentSect = pFormat->GetParentSection();
312 if( !pParentSect || !pParentSect->IsHiddenFlag() )
314 // Tell all Children that the Parent is not hidden anymore
315 const sw::SectionHidden aHint(false);
316 pFormat->CallSwClientNotify(aHint);
318 pFormat->MakeFrames();
323 bool SwSection::CalcHiddenFlag() const
325 const SwSection* pSect = this;
326 do {
327 if( pSect->IsHidden() && pSect->IsCondHidden() )
328 return true;
329 } while( nullptr != ( pSect = pSect->GetParent()) );
331 return false;
334 bool SwSection::IsProtect() const
336 SwSectionFormat const *const pFormat( GetFormat() );
337 OSL_ENSURE(pFormat, "SwSection::IsProtect: no format?");
338 return pFormat
339 ? pFormat->GetProtect().IsContentProtected()
340 : IsProtectFlag();
343 // edit in readonly sections
344 bool SwSection::IsEditInReadonly() const
346 SwSectionFormat const *const pFormat( GetFormat() );
347 OSL_ENSURE(pFormat, "SwSection::IsEditInReadonly: no format?");
348 return pFormat
349 ? pFormat->GetEditInReadonly().GetValue()
350 : IsEditInReadonlyFlag();
353 void SwSection::SetHidden(bool const bFlag)
355 if (!m_Data.IsHidden() == !bFlag)
356 return;
358 m_Data.SetHidden(bFlag);
359 ImplSetHiddenFlag(bFlag, m_Data.IsCondHidden());
362 void SwSection::SetProtect(bool const bFlag)
364 SwSectionFormat *const pFormat( GetFormat() );
365 OSL_ENSURE(pFormat, "SwSection::SetProtect: no format?");
366 if (pFormat)
368 SvxProtectItem aItem( RES_PROTECT );
369 aItem.SetContentProtect( bFlag );
370 pFormat->SetFormatAttr( aItem );
371 // note: this will call m_Data.SetProtectFlag via Modify!
373 else
375 m_Data.SetProtectFlag(bFlag);
379 // edit in readonly sections
380 void SwSection::SetEditInReadonly(bool const bFlag)
382 SwSectionFormat *const pFormat( GetFormat() );
383 OSL_ENSURE(pFormat, "SwSection::SetEditInReadonly: no format?");
384 if (pFormat)
386 SwFormatEditInReadonly aItem;
387 aItem.SetValue( bFlag );
388 pFormat->SetFormatAttr( aItem );
389 // note: this will call m_Data.SetEditInReadonlyFlag via Modify!
391 else
393 m_Data.SetEditInReadonlyFlag(bFlag);
397 void SwSection::SwClientNotify(const SwModify&, const SfxHint& rHint)
399 Notify(rHint);
402 void SwSection::Notify(SfxHint const& rHint)
404 if (rHint.GetId() == SfxHintId::SwSectionHidden)
406 auto rSectionHidden = static_cast<const sw::SectionHidden&>(rHint);
407 m_Data.SetHiddenFlag(rSectionHidden.m_isHidden || (m_Data.IsHidden() && m_Data.IsCondHidden()));
408 return;
409 } else if (rHint.GetId() != SfxHintId::SwLegacyModify)
410 return;
411 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
412 auto pOld = pLegacy->m_pOld;
413 auto pNew = pLegacy->m_pNew;
414 bool bUpdateFootnote = false;
415 switch(pLegacy->GetWhich())
417 case RES_ATTRSET_CHG:
418 if (pNew && pOld)
420 SfxItemSet* pNewSet = const_cast<SwAttrSetChg*>(static_cast<const SwAttrSetChg*>(pNew))->GetChgSet();
421 SfxItemSet* pOldSet = const_cast<SwAttrSetChg*>(static_cast<const SwAttrSetChg*>(pOld))->GetChgSet();
423 if( const SvxProtectItem* pItem = pNewSet->GetItemIfSet(
424 RES_PROTECT, false ) )
426 m_Data.SetProtectFlag( pItem->IsContentProtected() );
427 pNewSet->ClearItem( RES_PROTECT );
428 pOldSet->ClearItem( RES_PROTECT );
431 // --> edit in readonly sections
432 if( const SwFormatEditInReadonly* pItem = pNewSet->GetItemIfSet(
433 RES_EDIT_IN_READONLY, false ) )
435 m_Data.SetEditInReadonlyFlag(pItem->GetValue());
436 pNewSet->ClearItem( RES_EDIT_IN_READONLY );
437 pOldSet->ClearItem( RES_EDIT_IN_READONLY );
440 if( SfxItemState::SET == pNewSet->GetItemState(
441 RES_FTN_AT_TXTEND, false ) ||
442 SfxItemState::SET == pNewSet->GetItemState(
443 RES_END_AT_TXTEND, false ))
445 bUpdateFootnote = true;
448 if( !pNewSet->Count() )
449 return;
451 break;
453 case RES_PROTECT:
454 if( pNew )
456 bool bNewFlag =
457 static_cast<const SvxProtectItem*>(pNew)->IsContentProtected();
458 // this used to inherit the flag from the parent, but then there is
459 // no way to turn it off in an inner section
460 m_Data.SetProtectFlag( bNewFlag );
462 return;
463 // edit in readonly sections
464 case RES_EDIT_IN_READONLY:
465 if( pNew )
467 const bool bNewFlag =
468 static_cast<const SwFormatEditInReadonly*>(pNew)->GetValue();
469 m_Data.SetEditInReadonlyFlag( bNewFlag );
471 return;
473 case RES_COL:
474 // Is handled by the Layout, if appropriate
475 break;
477 case RES_FTN_AT_TXTEND:
478 if( pNew && pOld )
480 bUpdateFootnote = true;
482 break;
484 case RES_END_AT_TXTEND:
485 if( pNew && pOld )
487 bUpdateFootnote = true;
489 break;
491 default:
492 CheckRegistration( pOld );
493 break;
496 if( bUpdateFootnote )
498 SwSectionNode* pSectNd = GetFormat()->GetSectionNode();
499 if( pSectNd )
500 pSectNd->GetDoc().GetFootnoteIdxs().UpdateFootnote(*pSectNd);
504 void SwSection::SetRefObject( SwServerObject* pObj )
506 m_RefObj = pObj;
509 void SwSection::SetCondHidden(bool const bFlag)
511 if (!m_Data.IsCondHidden() == !bFlag)
512 return;
514 m_Data.SetCondHidden(bFlag);
515 ImplSetHiddenFlag(m_Data.IsHidden(), bFlag);
518 // Set/remove the linked FileName
519 OUString const & SwSection::GetLinkFileName() const
521 if (m_RefLink.is())
523 OUString sTmp;
524 switch (m_Data.GetType())
526 case SectionType::DdeLink:
527 sTmp = m_RefLink->GetLinkSourceName();
528 break;
530 case SectionType::FileLink:
532 OUString sRange;
533 OUString sFilter;
534 if (m_RefLink->GetLinkManager() &&
535 sfx2::LinkManager::GetDisplayNames(
536 m_RefLink.get(), nullptr, &sTmp, &sRange, &sFilter ))
538 sTmp += OUStringChar(sfx2::cTokenSeparator) + sFilter
539 + OUStringChar(sfx2::cTokenSeparator) + sRange;
541 else if( GetFormat() && !GetFormat()->GetSectionNode() )
543 // If the Section is in the UndoNodesArray, the LinkManager
544 // does not contain the Link, thus it cannot be queried for it.
545 // Thus return the current Name.
546 return m_Data.GetLinkFileName();
549 break;
550 default: break;
552 m_Data.SetLinkFileName(sTmp);
554 return m_Data.GetLinkFileName();
557 void SwSection::SetLinkFileName(const OUString& rNew)
559 if (m_RefLink.is())
561 m_RefLink->SetLinkSourceName( rNew );
563 m_Data.SetLinkFileName(rNew);
566 // If it was a Linked Section, we need to make all Child Links visible
567 void SwSection::MakeChildLinksVisible( const SwSectionNode& rSectNd )
569 const SwNode* pNd;
570 const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc().getIDocumentLinksAdministration().GetLinkManager().GetLinks();
571 for( auto n = rLnks.size(); n; )
573 sfx2::SvBaseLink& rBLnk = *rLnks[--n];
574 if (!rBLnk.IsVisible() && dynamic_cast<const SwBaseLink*>(&rBLnk) != nullptr
575 && nullptr != (pNd = static_cast<SwBaseLink&>(rBLnk).GetAnchor()))
577 pNd = pNd->StartOfSectionNode(); // If it's a SectionNode
578 const SwSectionNode* pParent;
579 while( nullptr != ( pParent = pNd->FindSectionNode() ) &&
580 ( SectionType::Content == pParent->GetSection().GetType()
581 || pNd == &rSectNd ))
582 pNd = pParent->StartOfSectionNode();
584 // It's within a normal Section, so show again
585 if( !pParent )
586 rBLnk.SetVisible(true);
591 const SwTOXBase* SwSection::GetTOXBase() const
593 const SwTOXBase* pRet = nullptr;
594 if( SectionType::ToxContent == GetType() )
595 pRet = dynamic_cast<const SwTOXBaseSection*>(this);
596 return pRet;
599 SwSectionFormat::SwSectionFormat( SwFrameFormat* pDrvdFrame, SwDoc *pDoc )
600 : SwFrameFormat( pDoc->GetAttrPool(), OUString(), pDrvdFrame )
602 LockModify();
603 SetFormatAttr( *GetDfltAttr( RES_COL ) );
604 UnlockModify();
607 SwSectionFormat::~SwSectionFormat()
609 if( GetDoc()->IsInDtor() )
610 return;
612 SwSectionNode* pSectNd;
613 const SwNodeIndex* pIdx = GetContent( false ).GetContentIdx();
614 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
615 nullptr != (pSectNd = pIdx->GetNode().GetSectionNode() ))
617 SwSection& rSect = pSectNd->GetSection();
618 // If it was a linked Section, we need to make all Child Links
619 // visible again
620 if( rSect.IsConnected() )
621 SwSection::MakeChildLinksVisible( *pSectNd );
623 // Check whether we need to be visible, before deleting the Nodes
624 if( rSect.IsHiddenFlag() )
626 SwSection* pParentSect = rSect.GetParent();
627 if( !pParentSect || !pParentSect->IsHiddenFlag() )
629 // Make Nodes visible again
630 rSect.SetHidden(false);
633 // mba: test iteration; objects are removed while iterating
634 // use hint which allows to specify, if the content shall be saved or not
635 CallSwClientNotify( SwSectionFrameMoveAndDeleteHint( true ) );
637 // Raise the Section up
638 SwNodeRange aRg( *pSectNd, SwNodeOffset(0), *pSectNd->EndOfSectionNode() );
639 GetDoc()->GetNodes().SectionUp( &aRg );
641 LockModify();
642 ResetFormatAttr( RES_CNTNT );
643 UnlockModify();
646 SwSection * SwSectionFormat::GetSection() const
648 return SwIterator<SwSection,SwSectionFormat>( *this ).First();
651 // Do not destroy all Frames in aDepend (Frames are recognized with a dynamic_cast).
652 void SwSectionFormat::DelFrames()
654 SwSectionNode* pSectNd;
655 const SwNodeIndex* pIdx = GetContent(false).GetContentIdx();
656 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
657 nullptr != (pSectNd = pIdx->GetNode().GetSectionNode() ))
659 // First delete the <SwSectionFrame> of the <SwSectionFormat> instance
660 // mba: test iteration as objects are removed in iteration
661 // use hint which allows to specify, if the content shall be saved or not
662 CallSwClientNotify( SwSectionFrameMoveAndDeleteHint( false ) );
664 // Then delete frames of the nested <SwSectionFormat> instances
665 SwIterator<SwSectionFormat,SwSectionFormat> aIter( *this );
666 SwSectionFormat *pLast = aIter.First();
667 while ( pLast )
669 pLast->DelFrames();
670 pLast = aIter.Next();
673 SwNodeOffset nEnd = pSectNd->EndOfSectionIndex();
674 SwNodeOffset nStart = pSectNd->GetIndex()+1;
675 sw_DeleteFootnote( pSectNd, nStart, nEnd );
677 if( !pIdx )
678 return;
680 // Send Hint for PageDesc. Actually the Layout contained in the
681 // Paste of the Frame itself would need to do this. But that leads
682 // to subsequent errors, which we'd need to solve at run-time.
683 SwNodeIndex aNextNd( *pIdx );
684 SwContentNode* pCNd = GetDoc()->GetNodes().GoNextSection( &aNextNd, true, false );
685 if( pCNd )
687 const SfxPoolItem& rItem = pCNd->GetSwAttrSet().Get(RES_PAGEDESC);
688 pCNd->CallSwClientNotify(sw::LegacyModifyHint(&rItem, &rItem));
692 // Create the Views
693 void SwSectionFormat::MakeFrames()
695 SwSectionNode* pSectNd;
696 const SwNodeIndex* pIdx = GetContent(false).GetContentIdx();
698 if( pIdx && &GetDoc()->GetNodes() == &pIdx->GetNodes() &&
699 nullptr != (pSectNd = pIdx->GetNode().GetSectionNode() ))
701 SwNodeIndex aIdx( *pIdx );
702 pSectNd->MakeOwnFrames( &aIdx );
706 void SwSectionFormat::SwClientNotify(const SwModify& rMod, const SfxHint& rHint)
708 if (rHint.GetId() == SfxHintId::SwSectionHidden)
710 auto rSectionHidden = static_cast<const sw::SectionHidden&>(rHint);
711 auto pSect = GetSection();
712 if(!pSect || rSectionHidden.m_isHidden == pSect->IsHiddenFlag()) // already at target state, skipping.
713 return;
714 GetNotifier().Broadcast(rSectionHidden);
715 return;
716 } else if (rHint.GetId() != SfxHintId::SwLegacyModify)
717 return;
718 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
719 sal_uInt16 nWhich = pLegacy->GetWhich();
720 auto pOld = pLegacy->m_pOld;
721 auto pNew = pLegacy->m_pNew;
722 switch( nWhich )
724 case RES_ATTRSET_CHG:
725 if (HasWriterListeners() && pOld && pNew)
727 SfxItemSet* pNewSet = const_cast<SwAttrSetChg*>(static_cast<const SwAttrSetChg*>(pNew))->GetChgSet();
728 SfxItemSet* pOldSet = const_cast<SwAttrSetChg*>(static_cast<const SwAttrSetChg*>(pOld))->GetChgSet();
729 const SfxPoolItem *pItem;
730 if( SfxItemState::SET == pNewSet->GetItemState(
731 RES_PROTECT, false, &pItem ))
733 GetNotifier().Broadcast(sw::LegacyModifyHint(pItem, pItem));
734 pNewSet->ClearItem( RES_PROTECT );
735 pOldSet->ClearItem( RES_PROTECT );
738 // --> edit in readonly sections
739 if( SfxItemState::SET == pNewSet->GetItemState(
740 RES_EDIT_IN_READONLY, false, &pItem ) )
742 GetNotifier().Broadcast(sw::LegacyModifyHint(pItem, pItem));
743 pNewSet->ClearItem( RES_EDIT_IN_READONLY );
744 pOldSet->ClearItem( RES_EDIT_IN_READONLY );
747 if( SfxItemState::SET == pNewSet->GetItemState(
748 RES_FTN_AT_TXTEND, false, &pItem ))
750 GetNotifier().Broadcast(sw::LegacyModifyHint(pItem, pItem));
751 pNewSet->ClearItem( RES_FTN_AT_TXTEND );
752 pOldSet->ClearItem( RES_FTN_AT_TXTEND );
754 if( SfxItemState::SET == pNewSet->GetItemState(
755 RES_END_AT_TXTEND, false, &pItem ))
757 GetNotifier().Broadcast(sw::LegacyModifyHint(pItem, pItem));
758 pNewSet->ClearItem( RES_END_AT_TXTEND );
759 pOldSet->ClearItem( RES_END_AT_TXTEND );
761 if( !static_cast<const SwAttrSetChg*>(pOld)->GetChgSet()->Count() )
762 return;
764 break;
766 case RES_FTN_AT_TXTEND:
767 case RES_END_AT_TXTEND:
768 GetNotifier().Broadcast(sw::LegacyModifyHint(pOld, pNew));
769 return;
770 case RES_PROTECT:
771 case RES_EDIT_IN_READONLY: // edit in readonly sections
772 // Pass through these Messages until the End of the tree!
773 GetNotifier().Broadcast(sw::LegacyModifyHint(pOld, pNew));
774 return; // That's it!
776 case RES_OBJECTDYING:
777 if( !GetDoc()->IsInDtor() && pOld &&
778 static_cast<const SwPtrMsgPoolItem *>(pOld)->pObject == static_cast<void*>(GetRegisteredIn()) )
780 // My Parents will be destroyed, so get the Parent's Parent
781 // and update
782 SwFrameFormat::SwClientNotify(rMod, rHint);
783 UpdateParent();
784 return;
786 break;
788 case RES_FMT_CHG:
789 if( !GetDoc()->IsInDtor() &&
790 static_cast<const SwFormatChg*>(pNew)->pChangedFormat == static_cast<void*>(GetRegisteredIn()) &&
791 dynamic_cast<const SwSectionFormat*>(static_cast<const SwFormatChg*>(pNew)->pChangedFormat) != nullptr )
793 // My Parent will be changed, thus I need to update
794 SwFrameFormat::SwClientNotify(rMod, rHint);
795 UpdateParent();
796 return;
798 break;
800 SwFrameFormat::SwClientNotify(rMod, rHint);
802 if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which()))
803 { // invalidate cached uno object
804 SetXTextSection(nullptr);
808 void SwSectionFormat::SetXTextSection(rtl::Reference<SwXTextSection> const& xTextSection)
810 m_wXTextSection = xTextSection.get();
813 bool SwSectionFormat::IsVisible() const
815 if(SwFrameFormat::IsVisible())
816 return true;
817 SwIterator<SwSectionFormat,SwSectionFormat> aFormatIter(*this);
818 for(SwSectionFormat* pChild = aFormatIter.First(); pChild; pChild = aFormatIter.Next())
819 if(pChild->IsVisible())
820 return true;
821 return false;
824 // Get info from the Format
825 bool SwSectionFormat::GetInfo(SfxPoolItem& rInfo) const
827 if(rInfo.Which() == RES_FINDNEARESTNODE)
829 if(GetFormatAttr( RES_PAGEDESC ).GetPageDesc())
831 const SwSectionNode* pNd = GetSectionNode();
832 if(pNd)
833 static_cast<SwFindNearestNode&>(rInfo).CheckNode(*pNd);
835 return true;
837 return sw::BroadcastingModify::GetInfo(rInfo);
840 static bool lcl_SectionCmpPos( const SwSection *pFirst, const SwSection *pSecond)
842 const SwSectionFormat* pFSectFormat = pFirst->GetFormat();
843 const SwSectionFormat* pSSectFormat = pSecond->GetFormat();
844 OSL_ENSURE( pFSectFormat && pSSectFormat &&
845 pFSectFormat->GetContent(false).GetContentIdx() &&
846 pSSectFormat->GetContent(false).GetContentIdx(),
847 "Invalid sections" );
848 return pFSectFormat->GetContent(false).GetContentIdx()->GetIndex() <
849 pSSectFormat->GetContent(false).GetContentIdx()->GetIndex();
852 // get all Sections that have been derived from this one
853 void SwSectionFormat::GetChildSections( SwSections& rArr,
854 SectionSort eSort,
855 bool bAllSections ) const
857 rArr.clear();
859 if( !HasWriterListeners() )
860 return;
862 SwIterator<SwSectionFormat,SwSectionFormat> aIter(*this);
863 const SwNodeIndex* pIdx;
864 for( SwSectionFormat* pLast = aIter.First(); pLast; pLast = aIter.Next() )
865 if( bAllSections ||
866 ( nullptr != ( pIdx = pLast->GetContent(false).
867 GetContentIdx()) && &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
869 SwSection* pDummy = pLast->GetSection();
870 rArr.push_back( pDummy );
873 // Do we need any sorting?
874 if( 1 < rArr.size() )
875 switch( eSort )
877 case SectionSort::Pos:
878 std::sort( rArr.begin(), rArr.end(), lcl_SectionCmpPos );
879 break;
880 case SectionSort::Not: break;
884 // See whether the Section is within the Nodes or the UndoNodes array
885 bool SwSectionFormat::IsInNodesArr() const
887 const SwNodeIndex* pIdx = GetContent(false).GetContentIdx();
888 return pIdx && &pIdx->GetNodes() == &GetDoc()->GetNodes();
891 // Parent was changed
892 void SwSectionFormat::UpdateParent()
894 if(!HasWriterListeners())
895 return;
897 const SwSection* pSection = GetSection();
898 const SvxProtectItem* pProtect = &GetProtect();
899 // edit in readonly sections
900 const SwFormatEditInReadonly* pEditInReadonly = &GetEditInReadonly();
901 bool bIsHidden = pSection->IsHidden();
902 if(GetRegisteredIn())
904 const SwSection* pPS = GetParentSection();
905 pProtect = &pPS->GetFormat()->GetProtect();
906 pEditInReadonly = &pPS->GetFormat()->GetEditInReadonly();
907 bIsHidden = pPS->IsHiddenFlag();
909 if(!pProtect->IsContentProtected() != !pSection->IsProtectFlag())
910 CallSwClientNotify(sw::LegacyModifyHint(pProtect, pProtect));
912 // edit in readonly sections
913 if(!pEditInReadonly->GetValue() != !pSection->IsEditInReadonlyFlag())
914 CallSwClientNotify(sw::LegacyModifyHint(pEditInReadonly, pEditInReadonly));
916 if(bIsHidden == pSection->IsHiddenFlag())
918 const sw::SectionHidden aHint(bIsHidden);
919 CallSwClientNotify(aHint);
923 SwSectionNode* SwSectionFormat::GetSectionNode()
925 const SwNodeIndex* pIdx = GetContent(false).GetContentIdx();
926 if( pIdx && ( &pIdx->GetNodes() == &GetDoc()->GetNodes() ))
927 return pIdx->GetNode().GetSectionNode();
928 return nullptr;
931 // Is this Section valid for the GlobalDocument?
932 const SwSection* SwSectionFormat::GetGlobalDocSection() const
934 const SwSectionNode* pNd = GetSectionNode();
935 if( pNd &&
936 ( SectionType::FileLink == pNd->GetSection().GetType() ||
937 SectionType::ToxContent == pNd->GetSection().GetType() ) &&
938 pNd->GetIndex() > pNd->GetNodes().GetEndOfExtras().GetIndex() &&
939 !pNd->StartOfSectionNode()->IsSectionNode() &&
940 !pNd->StartOfSectionNode()->FindSectionNode() )
941 return &pNd->GetSection();
942 return nullptr;
945 // sw::Metadatable
946 ::sfx2::IXmlIdRegistry& SwSectionFormat::GetRegistry()
948 return GetDoc()->GetXmlIdRegistry();
951 bool SwSectionFormat::IsInClipboard() const
953 return GetDoc()->IsClipBoard();
956 bool SwSectionFormat::IsInUndo() const
958 return !IsInNodesArr();
961 bool SwSectionFormat::IsInContent() const
963 SwNodeIndex const*const pIdx = GetContent(false).GetContentIdx();
964 OSL_ENSURE(pIdx, "SwSectionFormat::IsInContent: no index?");
965 return pIdx == nullptr || !GetDoc()->IsInHeaderFooter(pIdx->GetNode());
968 // n.b.: if the section format represents an index, then there is both a
969 // SwXDocumentIndex and a SwXTextSection instance for this single core object.
970 // these two can both implement XMetadatable and forward to the same core
971 // section format. but here only one UNO object can be returned,
972 // so always return the text section.
973 uno::Reference< rdf::XMetadatable >
974 SwSectionFormat::MakeUnoObject()
976 uno::Reference<rdf::XMetadatable> xMeta;
977 SwSection *const pSection( GetSection() );
978 if (pSection)
980 xMeta = SwXTextSection::CreateXTextSection(this,
981 SectionType::ToxHeader == pSection->GetType());
983 return xMeta;
986 bool SwSectionFormat::supportsFullDrawingLayerFillAttributeSet() const
988 return false;
991 void SwSectionFormat::dumpAsXml(xmlTextWriterPtr pWriter) const
993 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwSectionFormat"));
994 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
995 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toUtf8().getStr()));
996 GetAttrSet().dumpAsXml(pWriter);
997 (void)xmlTextWriterEndElement(pWriter);
1000 void SwSectionFormats::dumpAsXml(xmlTextWriterPtr pWriter) const
1002 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwSectionFormats"));
1003 for (size_t i = 0; i < size(); ++i)
1004 GetFormat(i)->dumpAsXml(pWriter);
1005 (void)xmlTextWriterEndElement(pWriter);
1008 // Method to break section links inside a linked section
1009 static void lcl_BreakSectionLinksInSect( const SwSectionNode& rSectNd )
1011 if ( !rSectNd.GetSection().IsConnected() )
1013 OSL_FAIL( "method <lcl_RemoveSectionLinksInSect(..)> - no Link at Section of SectionNode" );
1014 return;
1016 const ::sfx2::SvBaseLink* pOwnLink( &(rSectNd.GetSection().GetBaseLink() ) );
1017 const ::sfx2::SvBaseLinks& rLnks = rSectNd.GetDoc().getIDocumentLinksAdministration().GetLinkManager().GetLinks();
1018 for ( auto n = rLnks.size(); n > 0; )
1020 SwIntrnlSectRefLink* pSectLnk = dynamic_cast<SwIntrnlSectRefLink*>(&(*rLnks[ --n ]));
1021 if ( pSectLnk && pSectLnk != pOwnLink &&
1022 pSectLnk->IsInRange( rSectNd.GetIndex(), rSectNd.EndOfSectionIndex() ) )
1024 // break the link of the corresponding section.
1025 // the link is also removed from the link manager
1026 SwSectionNode* pSectNode = pSectLnk->GetSectNode();
1027 assert(pSectNode);
1028 pSectNode->GetSection().BreakLink();
1030 // for robustness, because link is removed from the link manager
1031 if ( n > rLnks.size() )
1033 n = rLnks.size();
1039 static void lcl_UpdateLinksInSect( const SwBaseLink& rUpdLnk, SwSectionNode& rSectNd )
1041 SwDoc& rDoc = rSectNd.GetDoc();
1042 SwDocShell* pDShell = rDoc.GetDocShell();
1043 if( !pDShell || !pDShell->GetMedium() )
1044 return ;
1046 const OUString sName( pDShell->GetMedium()->GetName() );
1047 const OUString sMimeType( SotExchange::GetFormatMimeType( SotClipboardFormatId::SIMPLE_FILE ));
1048 uno::Any aValue;
1049 aValue <<= sName; // Arbitrary name
1051 const ::sfx2::SvBaseLinks& rLnks = rDoc.getIDocumentLinksAdministration().GetLinkManager().GetLinks();
1052 for( auto n = rLnks.size(); n; )
1054 ::sfx2::SvBaseLink* pLnk = &(*rLnks[ --n ]);
1055 if( pLnk == &rUpdLnk )
1056 continue;
1057 if( sfx2::SvBaseLinkObjectType::ClientFile != pLnk->GetObjType() )
1058 continue;
1059 SwBaseLink* pBLink = dynamic_cast<SwBaseLink*>( pLnk );
1060 if( pBLink && pBLink->IsInRange( rSectNd.GetIndex(),
1061 rSectNd.EndOfSectionIndex() ) )
1063 // It's in the Section, so update. But only if it's not in the same File!
1064 OUString sFName;
1065 sfx2::LinkManager::GetDisplayNames( pBLink, nullptr, &sFName );
1066 if( sFName != sName )
1068 pBLink->DataChanged( sMimeType, aValue );
1070 // If needed find the Link pointer to avoid skipping one or calling one twice
1071 if( n >= rLnks.size() && 0 != ( n = rLnks.size() ))
1072 --n;
1074 if( n && pLnk != &(*rLnks[ n ]) )
1076 // Find - it can only precede it!
1077 while( n )
1078 if( pLnk == &(*rLnks[ --n ] ) )
1079 break;
1086 ::sfx2::SvBaseLink::UpdateResult SwIntrnlSectRefLink::DataChanged(
1087 const OUString& rMimeType, const uno::Any & rValue )
1089 SwSectionNode* pSectNd = m_rSectFormat.GetSectionNode();
1090 SwDoc* pDoc = m_rSectFormat.GetDoc();
1092 SotClipboardFormatId nDataFormat = SotExchange::GetFormatIdFromMimeType( rMimeType );
1094 if( !pSectNd || !pDoc || pDoc->IsInDtor() || ChkNoDataFlag() ||
1095 sfx2::LinkManager::RegisterStatusInfoId() == nDataFormat )
1097 // Should we be in the Undo already?
1098 return SUCCESS;
1101 // #i38810# - Due to possible existing signatures, the
1102 // document has to be modified after updating a link.
1103 pDoc->getIDocumentState().SetModified();
1104 // set additional flag that links have been updated, in order to check this
1105 // during load.
1106 pDoc->getIDocumentLinksAdministration().SetLinksUpdated( true );
1108 // Always switch off Undo
1109 bool const bWasUndo = pDoc->GetIDocumentUndoRedo().DoesUndo();
1110 pDoc->GetIDocumentUndoRedo().DoUndo(false);
1111 bool bWasVisibleLinks = pDoc->getIDocumentLinksAdministration().IsVisibleLinks();
1112 pDoc->getIDocumentLinksAdministration().SetVisibleLinks( false );
1114 SwPaM* pPam;
1115 SwViewShell* pVSh = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
1116 SwEditShell* pESh = pDoc->GetEditShell();
1117 pDoc->getIDocumentFieldsAccess().LockExpFields();
1119 // Insert an empty TextNode at the Section's start
1120 SwNodeIndex aIdx( *pSectNd, +1 );
1121 SwNodeIndex aEndIdx( *pSectNd->EndOfSectionNode() );
1122 pDoc->GetNodes().MakeTextNode( aIdx.GetNode(),
1123 pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT ) );
1125 if( pESh )
1126 pESh->StartAllAction();
1127 else if( pVSh )
1128 pVSh->StartAction();
1130 SwPosition aPos( aIdx, SwNodeOffset(-1) );
1131 SwDoc::CorrAbs( aIdx, aEndIdx, aPos, true );
1133 pPam = new SwPaM( aPos );
1135 // Delete everything succeeding it
1136 --aIdx;
1137 DelFlyInRange( aIdx.GetNode(), aEndIdx.GetNode() );
1138 DelBookmarks(aIdx.GetNode(), aEndIdx.GetNode());
1139 ++aIdx;
1141 pDoc->GetNodes().Delete( aIdx, aEndIdx.GetIndex() - aIdx.GetIndex() );
1144 SwSection& rSection = pSectNd->GetSection();
1145 rSection.SetConnectFlag(false);
1147 Reader* pRead = nullptr;
1148 switch( nDataFormat )
1150 case SotClipboardFormatId::STRING:
1151 pRead = ReadAscii;
1152 break;
1154 case SotClipboardFormatId::RICHTEXT:
1155 case SotClipboardFormatId::RTF:
1156 pRead = SwReaderWriter::GetRtfReader();
1157 break;
1159 case SotClipboardFormatId::SIMPLE_FILE:
1160 if ( rValue.hasValue() )
1162 OUString sFileName;
1163 if ( !(rValue >>= sFileName) )
1164 break;
1165 OUString sFilter;
1166 OUString sRange;
1167 sfx2::LinkManager::GetDisplayNames( this, nullptr, &sFileName,
1168 &sRange, &sFilter );
1170 RedlineFlags eOldRedlineFlags = RedlineFlags::NONE;
1171 SfxObjectShellRef xDocSh;
1172 SfxObjectShellLock xLockRef;
1173 int nRet;
1174 if( sFileName.isEmpty() )
1176 xDocSh = pDoc->GetDocShell();
1177 nRet = 1;
1179 else
1181 nRet = SwFindDocShell( xDocSh, xLockRef, sFileName,
1182 rSection.GetLinkFilePassword(),
1183 sFilter, 0, pDoc->GetDocShell() );
1184 if( nRet )
1186 SwDoc* pSrcDoc = static_cast<SwDocShell*>( xDocSh.get() )->GetDoc();
1187 eOldRedlineFlags = pSrcDoc->getIDocumentRedlineAccess().GetRedlineFlags();
1188 pSrcDoc->getIDocumentRedlineAccess().SetRedlineFlags( RedlineFlags::ShowInsert );
1192 if( nRet )
1194 rSection.SetConnectFlag();
1196 SwNodeIndex aSave( pPam->GetPoint()->GetNode(), -1 );
1197 std::optional<SwNodeRange> oCpyRg;
1199 if( xDocSh->GetMedium() &&
1200 rSection.GetLinkFilePassword().isEmpty() )
1202 if( const SfxStringItem* pItem = xDocSh->GetMedium()->GetItemSet()->
1203 GetItemIfSet( SID_PASSWORD, false ) )
1204 rSection.SetLinkFilePassword( pItem->GetValue() );
1207 SwDoc* pSrcDoc = static_cast<SwDocShell*>( xDocSh.get() )->GetDoc();
1209 if( !sRange.isEmpty() )
1211 // Catch recursion
1212 bool bRecursion = false;
1213 if( pSrcDoc == pDoc )
1215 tools::SvRef<SwServerObject> refObj( static_cast<SwServerObject*>(
1216 pDoc->getIDocumentLinksAdministration().CreateLinkSource( sRange )));
1217 if( refObj.is() )
1219 bRecursion = refObj->IsLinkInServer( this ) ||
1220 ChkNoDataFlag();
1224 SwNode& rInsPos = pPam->GetPoint()->GetNode();
1226 SwPaM* pCpyPam = nullptr;
1227 if( !bRecursion &&
1228 pSrcDoc->GetDocumentLinksAdministrationManager().SelectServerObj( sRange, pCpyPam, oCpyRg )
1229 && pCpyPam )
1231 if( pSrcDoc != pDoc ||
1232 pCpyPam->Start()->GetNode() > rInsPos ||
1233 rInsPos >= pCpyPam->End()->GetNode() )
1235 pSrcDoc->getIDocumentContentOperations().CopyRange(*pCpyPam, *pPam->GetPoint(), SwCopyFlags::CheckPosInFly);
1237 delete pCpyPam;
1239 if( oCpyRg && pSrcDoc == pDoc &&
1240 oCpyRg->aStart < rInsPos && rInsPos < oCpyRg->aEnd.GetNode() )
1242 oCpyRg.reset();
1245 else if( pSrcDoc != pDoc )
1246 oCpyRg.emplace( pSrcDoc->GetNodes().GetEndOfExtras(), SwNodeOffset(2),
1247 pSrcDoc->GetNodes().GetEndOfContent() );
1249 // #i81653#
1250 // Update links of extern linked document or extern linked
1251 // document section, if section is protected.
1252 if ( pSrcDoc != pDoc &&
1253 rSection.IsProtectFlag() )
1255 pSrcDoc->getIDocumentLinksAdministration().GetLinkManager().UpdateAllLinks( false, false, nullptr );
1258 if( oCpyRg )
1260 SwNode& rInsPos = pPam->GetPoint()->GetNode();
1261 bool bCreateFrame = rInsPos <= pDoc->GetNodes().GetEndOfExtras() ||
1262 rInsPos.FindTableNode();
1264 SwTableNumFormatMerge aTNFM( *pSrcDoc, *pDoc );
1266 pSrcDoc->GetDocumentContentOperationsManager().CopyWithFlyInFly(*oCpyRg, rInsPos, nullptr, bCreateFrame);
1267 ++aSave;
1269 if( !bCreateFrame )
1270 ::MakeFrames( pDoc, aSave.GetNode(), rInsPos );
1272 // Delete last Node, only if it was copied successfully
1273 // (the Section contains more than one Node)
1274 if( SwNodeOffset(2) < pSectNd->EndOfSectionIndex() - pSectNd->GetIndex() )
1276 aSave = rInsPos;
1277 pPam->Move( fnMoveBackward, GoInNode );
1278 pPam->SetMark(); // Rewire both SwPositions
1280 pDoc->CorrAbs( aSave.GetNode(), *pPam->GetPoint(), 0, true );
1281 pDoc->GetNodes().Delete( aSave );
1283 oCpyRg.reset();
1286 lcl_BreakSectionLinksInSect( *pSectNd );
1288 // Update all Links in this Section
1289 lcl_UpdateLinksInSect( *this, *pSectNd );
1291 if( xDocSh.is() )
1293 if( 2 == nRet )
1294 xDocSh->DoClose();
1295 else if( static_cast<SwDocShell*>( xDocSh.get() )->GetDoc() )
1296 static_cast<SwDocShell*>( xDocSh.get() )->GetDoc()->getIDocumentRedlineAccess().SetRedlineFlags(
1297 eOldRedlineFlags );
1300 break;
1301 default: break;
1304 // Only create DDE if Shell is available!
1305 uno::Sequence< sal_Int8 > aSeq;
1306 if( pRead && rValue.hasValue() && ( rValue >>= aSeq ) )
1308 if( pESh )
1310 pESh->Push();
1311 SwPaM* pCursor = pESh->GetCursor();
1312 *pCursor->GetPoint() = *pPam->GetPoint();
1313 delete pPam;
1314 pPam = pCursor;
1317 SvMemoryStream aStrm( const_cast<sal_Int8 *>(aSeq.getConstArray()), aSeq.getLength(),
1318 StreamMode::READ );
1319 aStrm.Seek( 0 );
1321 // TODO/MBA: it's impossible to set a BaseURL here!
1322 SwReader aTmpReader( aStrm, OUString(), pDoc->GetDocShell()->GetMedium()->GetBaseURL(), *pPam );
1324 if( ! aTmpReader.Read( *pRead ).IsError() )
1326 rSection.SetConnectFlag();
1329 if( pESh )
1331 pESh->Pop(SwCursorShell::PopMode::DeleteCurrent);
1332 pPam = nullptr; // pam was deleted earlier
1336 // remove all undo actions and turn undo on again
1337 pDoc->GetIDocumentUndoRedo().DelAllUndoObj();
1338 pDoc->GetIDocumentUndoRedo().DoUndo(bWasUndo);
1339 pDoc->getIDocumentLinksAdministration().SetVisibleLinks( bWasVisibleLinks );
1341 pDoc->getIDocumentFieldsAccess().UnlockExpFields();
1342 if( !pDoc->getIDocumentFieldsAccess().IsExpFieldsLocked() )
1343 pDoc->getIDocumentFieldsAccess().UpdateExpFields(nullptr, true);
1345 if( pESh )
1346 pESh->EndAllAction();
1347 else if( pVSh )
1348 pVSh->EndAction();
1349 delete pPam; // Was created at the start
1351 return SUCCESS;
1354 void SwIntrnlSectRefLink::Closed()
1356 SwDoc* pDoc = m_rSectFormat.GetDoc();
1357 if( pDoc && !pDoc->IsInDtor() )
1359 // Advise says goodbye: mark the Section as not protected
1360 // and change the Flag
1361 const SwSectionFormats& rFormats = pDoc->GetSections();
1362 for( auto n = rFormats.size(); n; )
1363 if (rFormats[--n] == &m_rSectFormat)
1365 SwViewShell* pSh = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
1366 SwEditShell* pESh = pDoc->GetEditShell();
1368 if( pESh )
1369 pESh->StartAllAction();
1370 else
1371 pSh->StartAction();
1373 SwSectionData aSectionData(*m_rSectFormat.GetSection());
1374 aSectionData.SetType( SectionType::Content );
1375 aSectionData.SetLinkFileName( OUString() );
1376 aSectionData.SetProtectFlag( false );
1377 // edit in readonly sections
1378 aSectionData.SetEditInReadonlyFlag( false );
1380 aSectionData.SetConnectFlag( false );
1382 pDoc->UpdateSection( n, aSectionData );
1384 // Make all Links within the Section visible again
1385 SwSectionNode* pSectNd = m_rSectFormat.GetSectionNode();
1386 if( pSectNd )
1387 SwSection::MakeChildLinksVisible( *pSectNd );
1389 if( pESh )
1390 pESh->EndAllAction();
1391 else
1392 pSh->EndAction();
1393 break;
1396 SvBaseLink::Closed();
1399 void SwSection::CreateLink( LinkCreateType eCreateType )
1401 SwSectionFormat* pFormat = GetFormat();
1402 OSL_ENSURE(pFormat, "SwSection::CreateLink: no format?");
1403 if (!pFormat || (SectionType::Content == m_Data.GetType()))
1404 return ;
1406 SfxLinkUpdateMode nUpdateType = SfxLinkUpdateMode::ALWAYS;
1408 if (!m_RefLink.is())
1410 // create BaseLink
1411 m_RefLink = new SwIntrnlSectRefLink( *pFormat, nUpdateType );
1413 else
1415 pFormat->GetDoc()->getIDocumentLinksAdministration().GetLinkManager().Remove( m_RefLink.get() );
1418 SwIntrnlSectRefLink *const pLnk =
1419 static_cast<SwIntrnlSectRefLink*>( m_RefLink.get() );
1421 const OUString sCmd(m_Data.GetLinkFileName());
1422 pLnk->SetUpdateMode( nUpdateType );
1423 pLnk->SetVisible( pFormat->GetDoc()->getIDocumentLinksAdministration().IsVisibleLinks() );
1425 switch (m_Data.GetType())
1427 case SectionType::DdeLink:
1428 pLnk->SetLinkSourceName( sCmd );
1429 pFormat->GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertDDELink( pLnk );
1430 break;
1431 case SectionType::FileLink:
1433 pLnk->SetContentType( SotClipboardFormatId::SIMPLE_FILE );
1434 sal_Int32 nIndex = 0;
1435 const OUString sFile(sCmd.getToken( 0, sfx2::cTokenSeparator, nIndex ));
1436 const OUString sFltr(sCmd.getToken( 0, sfx2::cTokenSeparator, nIndex ));
1437 const OUString sRange(sCmd.getToken( 0, sfx2::cTokenSeparator, nIndex ));
1438 pFormat->GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( *pLnk,
1439 static_cast<sfx2::SvBaseLinkObjectType>(m_Data.GetType()),
1440 sFile,
1441 ( !sFltr.isEmpty() ? &sFltr : nullptr ),
1442 ( !sRange.isEmpty() ? &sRange : nullptr ) );
1444 break;
1445 default:
1446 OSL_ENSURE( false, "What kind of Link is this?" );
1449 switch( eCreateType )
1451 case LinkCreateType::Connect: // Connect Link right away
1452 pLnk->Connect();
1453 break;
1455 case LinkCreateType::Update: // Connect Link and update
1456 pLnk->Update();
1457 break;
1458 case LinkCreateType::NONE: break;
1462 void SwSection::BreakLink()
1464 const SectionType eCurrentType( GetType() );
1465 if ( eCurrentType == SectionType::Content ||
1466 eCurrentType == SectionType::ToxHeader ||
1467 eCurrentType == SectionType::ToxContent )
1469 // nothing to do
1470 return;
1473 // Release link, if it exists
1474 if (m_RefLink.is())
1476 SwSectionFormat *const pFormat( GetFormat() );
1477 OSL_ENSURE(pFormat, "SwSection::BreakLink: no format?");
1478 if (pFormat)
1480 pFormat->GetDoc()->getIDocumentLinksAdministration().GetLinkManager().Remove( m_RefLink.get() );
1482 m_RefLink.clear();
1484 // change type
1485 SetType( SectionType::Content );
1486 // reset linked file data
1487 SetLinkFileName( OUString() );
1488 SetLinkFilePassword( OUString() );
1491 void SwSection::dumpAsXml(xmlTextWriterPtr pWriter) const
1493 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwSection"));
1494 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", this);
1495 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("registered-in"), "%p",
1496 GetRegisteredIn());
1497 m_Data.dumpAsXml(pWriter);
1498 (void)xmlTextWriterEndElement(pWriter);
1501 const SwNode* SwIntrnlSectRefLink::GetAnchor() const { return m_rSectFormat.GetSectionNode(); }
1503 bool SwIntrnlSectRefLink::IsInRange( SwNodeOffset nSttNd, SwNodeOffset nEndNd ) const
1505 SwStartNode* pSttNd = m_rSectFormat.GetSectionNode();
1506 return pSttNd &&
1507 nSttNd < pSttNd->GetIndex() &&
1508 pSttNd->EndOfSectionIndex() < nEndNd;
1511 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */