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