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