Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <UndoSection.hxx>
21 :
22 : #include <sfx2/linkmgr.hxx>
23 : #include <fmtcntnt.hxx>
24 : #include <doc.hxx>
25 : #include <IDocumentLinksAdministration.hxx>
26 : #include <IDocumentRedlineAccess.hxx>
27 : #include <IDocumentFieldsAccess.hxx>
28 : #include <docary.hxx>
29 : #include <swundo.hxx>
30 : #include <pam.hxx>
31 : #include <ndtxt.hxx>
32 : #include <UndoCore.hxx>
33 : #include <section.hxx>
34 : #include <rolbck.hxx>
35 : #include <redline.hxx>
36 : #include <doctxm.hxx>
37 : #include <ftnidx.hxx>
38 : #include <editsh.hxx>
39 : /// OD 04.10.2002 #102894#
40 : /// class Calc needed for calculation of the hidden condition of a section.
41 : #include <calc.hxx>
42 :
43 8 : static SfxItemSet* lcl_GetAttrSet( const SwSection& rSect )
44 : {
45 : // save attributes of the format (columns, color, ...)
46 : // Content and Protect items are not interesting since they are already
47 : // stored in Section, thus delete them.
48 8 : SfxItemSet* pAttr = 0;
49 8 : if( rSect.GetFormat() )
50 : {
51 8 : sal_uInt16 nCnt = 1;
52 8 : if( rSect.IsProtect() )
53 0 : ++nCnt;
54 :
55 8 : if( nCnt < rSect.GetFormat()->GetAttrSet().Count() )
56 : {
57 8 : pAttr = new SfxItemSet( rSect.GetFormat()->GetAttrSet() );
58 8 : pAttr->ClearItem( RES_PROTECT );
59 8 : pAttr->ClearItem( RES_CNTNT );
60 8 : if( !pAttr->Count() )
61 0 : delete pAttr, pAttr = 0;
62 : }
63 : }
64 8 : return pAttr;
65 : }
66 :
67 21 : SwUndoInsSection::SwUndoInsSection(
68 : SwPaM const& rPam, SwSectionData const& rNewData,
69 : SfxItemSet const*const pSet, SwTOXBase const*const pTOXBase)
70 : : SwUndo( UNDO_INSSECTION ), SwUndRng( rPam )
71 21 : , m_pSectionData(new SwSectionData(rNewData))
72 4 : , m_pTOXBase( (pTOXBase) ? new SwTOXBase(*pTOXBase) : 0 )
73 22 : , m_pAttrSet( (pSet && pSet->Count()) ? new SfxItemSet( *pSet ) : 0 )
74 : , m_nSectionNodePos(0)
75 : , m_bSplitAtStart(false)
76 : , m_bSplitAtEnd(false)
77 66 : , m_bUpdateFootnote(false)
78 : {
79 21 : SwDoc& rDoc = *rPam.GetDoc();
80 21 : if( rDoc.getIDocumentRedlineAccess().IsRedlineOn() )
81 : {
82 : m_pRedlData.reset(new SwRedlineData( nsRedlineType_t::REDLINE_INSERT,
83 0 : rDoc.getIDocumentRedlineAccess().GetRedlineAuthor() ));
84 0 : SetRedlineMode( rDoc.getIDocumentRedlineAccess().GetRedlineMode() );
85 : }
86 21 : m_pRedlineSaveData.reset( new SwRedlineSaveDatas );
87 21 : if( !FillSaveData( rPam, *m_pRedlineSaveData, false ))
88 20 : m_pRedlineSaveData.reset( NULL );
89 :
90 21 : if( !rPam.HasMark() )
91 : {
92 10 : const SwContentNode* pCNd = rPam.GetPoint()->nNode.GetNode().GetContentNode();
93 22 : if( pCNd && pCNd->HasSwAttrSet() && (
94 6 : !rPam.GetPoint()->nContent.GetIndex() ||
95 0 : rPam.GetPoint()->nContent.GetIndex() == pCNd->Len() ))
96 : {
97 6 : SfxItemSet aBrkSet( rDoc.GetAttrPool(), aBreakSetRange );
98 6 : aBrkSet.Put( *pCNd->GetpSwAttrSet() );
99 6 : if( aBrkSet.Count() )
100 : {
101 0 : m_pHistory.reset( new SwHistory );
102 0 : m_pHistory->CopyFormatAttr( aBrkSet, pCNd->GetIndex() );
103 6 : }
104 : }
105 : }
106 21 : }
107 :
108 42 : SwUndoInsSection::~SwUndoInsSection()
109 : {
110 42 : }
111 :
112 1 : void SwUndoInsSection::UndoImpl(::sw::UndoRedoContext & rContext)
113 : {
114 1 : SwDoc & rDoc = rContext.GetDoc();
115 :
116 1 : RemoveIdxFromSection( rDoc, m_nSectionNodePos );
117 :
118 : SwSectionNode *const pNd =
119 1 : rDoc.GetNodes()[ m_nSectionNodePos ]->GetSectionNode();
120 : OSL_ENSURE( pNd, "wo ist mein SectionNode?" );
121 :
122 1 : if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
123 0 : rDoc.getIDocumentRedlineAccess().DeleteRedline( *pNd, true, USHRT_MAX );
124 :
125 : // no selection?
126 1 : SwNodeIndex aIdx( *pNd );
127 2 : if( ( !nEndNode && COMPLETE_STRING == nEndContent ) ||
128 1 : ( nSttNode == nEndNode && nSttContent == nEndContent ))
129 : // delete simply all nodes
130 0 : rDoc.GetNodes().Delete( aIdx, pNd->EndOfSectionIndex() -
131 0 : aIdx.GetIndex() );
132 : else
133 : // just delete format, rest happens automatically
134 1 : rDoc.DelSectionFormat( pNd->GetSection().GetFormat() );
135 :
136 : // do we need to consolidate?
137 1 : if (m_bSplitAtStart)
138 : {
139 0 : Join( rDoc, nSttNode );
140 : }
141 :
142 1 : if (m_bSplitAtEnd)
143 : {
144 0 : Join( rDoc, nEndNode );
145 : }
146 :
147 1 : if (m_pHistory.get())
148 : {
149 0 : m_pHistory->TmpRollback( &rDoc, 0, false );
150 : }
151 :
152 1 : if (m_bUpdateFootnote)
153 : {
154 0 : rDoc.GetFootnoteIdxs().UpdateFootnote( aIdx );
155 : }
156 :
157 1 : AddUndoRedoPaM(rContext);
158 :
159 1 : if( m_pRedlineSaveData.get())
160 1 : SetSaveData( rDoc, *m_pRedlineSaveData );
161 1 : }
162 :
163 0 : void SwUndoInsSection::RedoImpl(::sw::UndoRedoContext & rContext)
164 : {
165 0 : SwDoc & rDoc = rContext.GetDoc();
166 0 : SwPaM & rPam( AddUndoRedoPaM(rContext) );
167 :
168 0 : const SwTOXBaseSection* pUpdateTOX = 0;
169 0 : if (m_pTOXBase.get())
170 : {
171 0 : pUpdateTOX = rDoc.InsertTableOf( *rPam.GetPoint(),
172 0 : *m_pTOXBase, m_pAttrSet.get(), true);
173 : }
174 : else
175 : {
176 0 : rDoc.InsertSwSection(rPam, *m_pSectionData, 0, m_pAttrSet.get(), true);
177 : }
178 :
179 0 : if (m_pHistory.get())
180 : {
181 0 : m_pHistory->SetTmpEnd( m_pHistory->Count() );
182 : }
183 :
184 : SwSectionNode *const pSectNd =
185 0 : rDoc.GetNodes()[ m_nSectionNodePos ]->GetSectionNode();
186 0 : if (m_pRedlData.get() &&
187 0 : IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode()))
188 : {
189 0 : RedlineMode_t eOld = rDoc.getIDocumentRedlineAccess().GetRedlineMode();
190 0 : rDoc.getIDocumentRedlineAccess().SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
191 :
192 0 : SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 );
193 0 : rDoc.getIDocumentRedlineAccess().AppendRedline( new SwRangeRedline( *m_pRedlData, aPam ), true);
194 0 : rDoc.getIDocumentRedlineAccess().SetRedlineMode_intern( eOld );
195 : }
196 0 : else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
197 0 : !rDoc.getIDocumentRedlineAccess().GetRedlineTable().empty() )
198 : {
199 0 : SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 );
200 0 : rDoc.getIDocumentRedlineAccess().SplitRedline( aPam );
201 : }
202 :
203 0 : if( pUpdateTOX )
204 : {
205 : // initiate formatting
206 0 : SwEditShell* pESh = rDoc.GetEditShell();
207 0 : if( pESh )
208 0 : pESh->CalcLayout();
209 :
210 : // insert page numbers
211 0 : const_cast<SwTOXBaseSection*>(pUpdateTOX)->UpdatePageNum();
212 : }
213 0 : }
214 :
215 0 : void SwUndoInsSection::RepeatImpl(::sw::RepeatContext & rContext)
216 : {
217 0 : SwDoc & rDoc = rContext.GetDoc();
218 0 : if (m_pTOXBase.get())
219 : {
220 0 : rDoc.InsertTableOf(*rContext.GetRepeatPaM().GetPoint(),
221 0 : *m_pTOXBase, m_pAttrSet.get(), true);
222 : }
223 : else
224 : {
225 0 : rDoc.InsertSwSection(rContext.GetRepeatPaM(),
226 0 : *m_pSectionData, 0, m_pAttrSet.get());
227 : }
228 0 : }
229 :
230 0 : void SwUndoInsSection::Join( SwDoc& rDoc, sal_uLong nNode )
231 : {
232 0 : SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
233 0 : SwTextNode* pTextNd = aIdx.GetNode().GetTextNode();
234 : OSL_ENSURE( pTextNd, "Where is my TextNode?" );
235 :
236 : {
237 : RemoveIdxRel(
238 : nNode + 1,
239 0 : SwPosition( aIdx, SwIndex( pTextNd, pTextNd->GetText().getLength() ) ) );
240 : }
241 0 : pTextNd->JoinNext();
242 :
243 0 : if (m_pHistory.get())
244 : {
245 0 : SwIndex aCntIdx( pTextNd, 0 );
246 0 : pTextNd->RstTextAttr( aCntIdx, pTextNd->Len(), 0, 0, true );
247 0 : }
248 0 : }
249 :
250 : void
251 0 : SwUndoInsSection::SaveSplitNode(SwTextNode *const pTextNd, bool const bAtStart)
252 : {
253 0 : if( pTextNd->GetpSwpHints() )
254 : {
255 0 : if (!m_pHistory.get())
256 : {
257 0 : m_pHistory.reset( new SwHistory );
258 : }
259 : m_pHistory->CopyAttr( pTextNd->GetpSwpHints(), pTextNd->GetIndex(), 0,
260 0 : pTextNd->GetText().getLength(), false );
261 : }
262 :
263 0 : if (bAtStart)
264 : {
265 0 : m_bSplitAtStart = true;
266 : }
267 : else
268 : {
269 0 : m_bSplitAtEnd = true;
270 : }
271 0 : }
272 :
273 : class SwUndoDelSection
274 : : public SwUndo
275 : {
276 : private:
277 : ::std::unique_ptr<SwSectionData> const m_pSectionData; /// section not TOX
278 : ::std::unique_ptr<SwTOXBase> const m_pTOXBase; /// set iff section is TOX
279 : ::std::unique_ptr<SfxItemSet> const m_pAttrSet;
280 : std::shared_ptr< ::sfx2::MetadatableUndo > const m_pMetadataUndo;
281 : sal_uLong const m_nStartNode;
282 : sal_uLong const m_nEndNode;
283 :
284 : public:
285 : SwUndoDelSection(
286 : SwSectionFormat const&, SwSection const&, SwNodeIndex const*const);
287 :
288 : virtual ~SwUndoDelSection();
289 :
290 : virtual void UndoImpl( ::sw::UndoRedoContext & ) SAL_OVERRIDE;
291 : virtual void RedoImpl( ::sw::UndoRedoContext & ) SAL_OVERRIDE;
292 : };
293 :
294 2 : SwUndo * MakeUndoDelSection(SwSectionFormat const& rFormat)
295 : {
296 : return new SwUndoDelSection(rFormat, *rFormat.GetSection(),
297 2 : rFormat.GetContent().GetContentIdx());
298 : }
299 :
300 2 : SwUndoDelSection::SwUndoDelSection(
301 : SwSectionFormat const& rSectionFormat, SwSection const& rSection,
302 : SwNodeIndex const*const pIndex)
303 : : SwUndo( UNDO_DELSECTION )
304 2 : , m_pSectionData( new SwSectionData(rSection) )
305 2 : , m_pTOXBase( rSection.ISA( SwTOXBaseSection )
306 0 : ? new SwTOXBase(static_cast<SwTOXBaseSection const&>(rSection))
307 : : 0 )
308 : , m_pAttrSet( ::lcl_GetAttrSet(rSection) )
309 : , m_pMetadataUndo( rSectionFormat.CreateUndo() )
310 2 : , m_nStartNode( pIndex->GetIndex() )
311 8 : , m_nEndNode( pIndex->GetNode().EndOfSectionIndex() )
312 : {
313 2 : }
314 :
315 4 : SwUndoDelSection::~SwUndoDelSection()
316 : {
317 4 : }
318 :
319 0 : void SwUndoDelSection::UndoImpl(::sw::UndoRedoContext & rContext)
320 : {
321 0 : SwDoc & rDoc = rContext.GetDoc();
322 :
323 0 : if (m_pTOXBase.get())
324 : {
325 0 : rDoc.InsertTableOf(m_nStartNode, m_nEndNode-2, *m_pTOXBase,
326 0 : m_pAttrSet.get());
327 : }
328 : else
329 : {
330 0 : SwNodeIndex aStt( rDoc.GetNodes(), m_nStartNode );
331 0 : SwNodeIndex aEnd( rDoc.GetNodes(), m_nEndNode-2 );
332 0 : SwSectionFormat* pFormat = rDoc.MakeSectionFormat( 0 );
333 0 : if (m_pAttrSet.get())
334 : {
335 0 : pFormat->SetFormatAttr( *m_pAttrSet );
336 : }
337 :
338 : /// OD 04.10.2002 #102894#
339 : /// remember inserted section node for further calculations
340 0 : SwSectionNode* pInsertedSectNd = rDoc.GetNodes().InsertTextSection(
341 0 : aStt, *pFormat, *m_pSectionData, 0, & aEnd);
342 :
343 0 : if( SfxItemState::SET == pFormat->GetItemState( RES_FTN_AT_TXTEND ) ||
344 0 : SfxItemState::SET == pFormat->GetItemState( RES_END_AT_TXTEND ))
345 : {
346 0 : rDoc.GetFootnoteIdxs().UpdateFootnote( aStt );
347 : }
348 :
349 : /// OD 04.10.2002 #102894#
350 : /// consider that section is hidden by condition.
351 : /// If section is hidden by condition,
352 : /// recalculate condition and update hidden condition flag.
353 : /// Recalculation is necessary, because fields, on which the hide
354 : /// condition depends, can be changed - fields changes aren't undoable.
355 : /// NOTE: setting hidden condition flag also creates/deletes corresponding
356 : /// frames, if the hidden condition flag changes.
357 0 : SwSection& aInsertedSect = pInsertedSectNd->GetSection();
358 0 : if ( aInsertedSect.IsHidden() &&
359 0 : !aInsertedSect.GetCondition().isEmpty() )
360 : {
361 0 : SwCalc aCalc( rDoc );
362 0 : rDoc.getIDocumentFieldsAccess().FieldsToCalc(aCalc, pInsertedSectNd->GetIndex(), USHRT_MAX);
363 : bool bRecalcCondHidden =
364 0 : aCalc.Calculate( aInsertedSect.GetCondition() ).GetBool();
365 0 : aInsertedSect.SetCondHidden( bRecalcCondHidden );
366 : }
367 :
368 0 : pFormat->RestoreMetadata(m_pMetadataUndo);
369 : }
370 0 : }
371 :
372 0 : void SwUndoDelSection::RedoImpl(::sw::UndoRedoContext & rContext)
373 : {
374 0 : SwDoc & rDoc = rContext.GetDoc();
375 :
376 : SwSectionNode *const pNd =
377 0 : rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode();
378 : OSL_ENSURE( pNd, "Where is my SectionNode?" );
379 : // just delete format, rest happens automatically
380 0 : rDoc.DelSectionFormat( pNd->GetSection().GetFormat() );
381 0 : }
382 :
383 : class SwUndoUpdateSection
384 : : public SwUndo
385 : {
386 : private:
387 : ::std::unique_ptr<SwSectionData> m_pSectionData;
388 : ::std::unique_ptr<SfxItemSet> m_pAttrSet;
389 : sal_uLong const m_nStartNode;
390 : bool const m_bOnlyAttrChanged;
391 :
392 : public:
393 : SwUndoUpdateSection(
394 : SwSection const&, SwNodeIndex const*const, bool const bOnlyAttr);
395 :
396 : virtual ~SwUndoUpdateSection();
397 :
398 : virtual void UndoImpl( ::sw::UndoRedoContext & ) SAL_OVERRIDE;
399 : virtual void RedoImpl( ::sw::UndoRedoContext & ) SAL_OVERRIDE;
400 : };
401 :
402 : SwUndo *
403 6 : MakeUndoUpdateSection(SwSectionFormat const& rFormat, bool const bOnlyAttr)
404 : {
405 : return new SwUndoUpdateSection(*rFormat.GetSection(),
406 6 : rFormat.GetContent().GetContentIdx(), bOnlyAttr);
407 : }
408 :
409 6 : SwUndoUpdateSection::SwUndoUpdateSection(
410 : SwSection const& rSection, SwNodeIndex const*const pIndex,
411 : bool const bOnlyAttr)
412 : : SwUndo( UNDO_CHGSECTION )
413 6 : , m_pSectionData( new SwSectionData(rSection) )
414 : , m_pAttrSet( ::lcl_GetAttrSet(rSection) )
415 6 : , m_nStartNode( pIndex->GetIndex() )
416 18 : , m_bOnlyAttrChanged( bOnlyAttr )
417 : {
418 6 : }
419 :
420 12 : SwUndoUpdateSection::~SwUndoUpdateSection()
421 : {
422 12 : }
423 :
424 0 : void SwUndoUpdateSection::UndoImpl(::sw::UndoRedoContext & rContext)
425 : {
426 0 : SwDoc & rDoc = rContext.GetDoc();
427 : SwSectionNode *const pSectNd =
428 0 : rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode();
429 : OSL_ENSURE( pSectNd, "Where is my SectionNode?" );
430 :
431 0 : SwSection& rNdSect = pSectNd->GetSection();
432 0 : SwFormat* pFormat = rNdSect.GetFormat();
433 :
434 0 : SfxItemSet* pCur = ::lcl_GetAttrSet( rNdSect );
435 0 : if (m_pAttrSet.get())
436 : {
437 : // The Content and Protect items must persist
438 : const SfxPoolItem* pItem;
439 0 : m_pAttrSet->Put( pFormat->GetFormatAttr( RES_CNTNT ));
440 0 : if( SfxItemState::SET == pFormat->GetItemState( RES_PROTECT, true, &pItem ))
441 : {
442 0 : m_pAttrSet->Put( *pItem );
443 : }
444 0 : pFormat->DelDiffs( *m_pAttrSet );
445 0 : m_pAttrSet->ClearItem( RES_CNTNT );
446 0 : pFormat->SetFormatAttr( *m_pAttrSet );
447 : }
448 : else
449 : {
450 : // than the old ones need to be deleted
451 0 : pFormat->ResetFormatAttr( RES_FRMATR_BEGIN, RES_BREAK );
452 0 : pFormat->ResetFormatAttr( RES_HEADER, RES_OPAQUE );
453 0 : pFormat->ResetFormatAttr( RES_SURROUND, RES_FRMATR_END-1 );
454 : }
455 0 : m_pAttrSet.reset(pCur);
456 :
457 0 : if (!m_bOnlyAttrChanged)
458 : {
459 : const bool bUpdate =
460 0 : (!rNdSect.IsLinkType() && m_pSectionData->IsLinkType())
461 0 : || ( !m_pSectionData->GetLinkFileName().isEmpty()
462 0 : && (m_pSectionData->GetLinkFileName() !=
463 0 : rNdSect.GetLinkFileName()));
464 :
465 : // swap stored section data with live section data
466 0 : SwSectionData *const pOld( new SwSectionData(rNdSect) );
467 0 : rNdSect.SetSectionData(*m_pSectionData);
468 0 : m_pSectionData.reset(pOld);
469 :
470 0 : if( bUpdate )
471 0 : rNdSect.CreateLink( CREATE_UPDATE );
472 0 : else if( CONTENT_SECTION == rNdSect.GetType() && rNdSect.IsConnected() )
473 : {
474 0 : rNdSect.Disconnect();
475 0 : rDoc.getIDocumentLinksAdministration().GetLinkManager().Remove( &rNdSect.GetBaseLink() );
476 : }
477 : }
478 0 : }
479 :
480 0 : void SwUndoUpdateSection::RedoImpl(::sw::UndoRedoContext & rContext)
481 : {
482 0 : UndoImpl(rContext);
483 177 : }
484 :
485 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|