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