Update ooo320-m1
[ooovba.git] / sw / source / core / undo / SwUndoPageDesc.cxx
blobd7ee78b0701af7b34d021eedf3034671930fff68
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SwUndoPageDesc.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include <tools/resid.hxx>
35 #include <doc.hxx>
36 #include <swundo.hxx>
37 #include <pagedesc.hxx>
38 #include <SwUndoPageDesc.hxx>
39 #include <SwRewriter.hxx>
40 #include <undobj.hxx>
41 #include <comcore.hrc>
42 #include <fmtcntnt.hxx>
43 #include <fmthdft.hxx>
45 #ifdef DEBUG
46 #include <ndindex.hxx>
47 #endif
50 #ifdef DEBUG
51 // Pure debug help function to have a quick look at the header/footer attributes.
52 void DebugHeaderFooterContent( const SwPageDesc& rPageDesc )
54 ULONG nHeaderMaster = ULONG_MAX;
55 ULONG nHeaderLeft = ULONG_MAX;
56 ULONG nFooterMaster = ULONG_MAX;
57 ULONG nFooterLeft = ULONG_MAX;
58 int nHeaderCount = 0;
59 int nLeftHeaderCount = 0;
60 int nFooterCount = 0;
61 int nLeftFooterCount = 0;
62 bool bSharedHeader = false;
63 bool bSharedFooter = false;
65 SwFmtHeader& rHead = (SwFmtHeader&)rPageDesc.GetMaster().GetHeader();
66 SwFmtFooter& rFoot = (SwFmtFooter&)rPageDesc.GetMaster().GetFooter();
67 SwFmtHeader& rLeftHead = (SwFmtHeader&)rPageDesc.GetLeft().GetHeader();
68 SwFmtFooter& rLeftFoot = (SwFmtFooter&)rPageDesc.GetLeft().GetFooter();
69 if( rHead.IsActive() )
71 SwFrmFmt* pHeaderFmt = rHead.GetHeaderFmt();
72 if( pHeaderFmt )
74 SwClientIter aIter( *pHeaderFmt );
75 SwClient *pLast = aIter.GoStart();
76 if( pLast )
79 ++nHeaderCount;
80 } while( 0 != ( pLast = aIter++ ));
81 const SwFmtCntnt* pCntnt = &pHeaderFmt->GetCntnt();
82 if( pCntnt->GetCntntIdx() )
83 nHeaderMaster = pCntnt->GetCntntIdx()->GetIndex();
84 else
85 nHeaderMaster = 0;
87 bSharedHeader = rPageDesc.IsHeaderShared();
88 SwFrmFmt* pLeftHeaderFmt = rLeftHead.GetHeaderFmt();
89 if( pLeftHeaderFmt )
91 SwClientIter aIter( *pLeftHeaderFmt );
92 SwClient *pLast = aIter.GoStart();
93 if( pLast )
96 ++nLeftHeaderCount;
97 } while( 0 != ( pLast = aIter++ ));
98 const SwFmtCntnt* pLeftCntnt = &pLeftHeaderFmt->GetCntnt();
99 if( pLeftCntnt->GetCntntIdx() )
100 nHeaderLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
101 else
102 nHeaderLeft = 0;
105 if( rFoot.IsActive() )
107 SwFrmFmt* pFooterFmt = rFoot.GetFooterFmt();
108 if( pFooterFmt )
110 SwClientIter aIter( *pFooterFmt );
111 SwClient *pLast = aIter.GoStart();
112 if( pLast )
115 ++nFooterCount;
116 } while( 0 != ( pLast = aIter++ ));
117 const SwFmtCntnt* pCntnt = &pFooterFmt->GetCntnt();
118 if( pCntnt->GetCntntIdx() )
119 nFooterMaster = pCntnt->GetCntntIdx()->GetIndex();
120 else
121 nFooterMaster = 0;
123 bSharedFooter = rPageDesc.IsFooterShared();
124 SwFrmFmt* pLeftFooterFmt = rLeftFoot.GetFooterFmt();
125 if( pLeftFooterFmt )
127 SwClientIter aIter( *pLeftFooterFmt );
128 SwClient *pLast = aIter.GoStart();
129 if( pLast )
132 ++nLeftFooterCount;
133 } while( 0 != ( pLast = aIter++ ));
134 const SwFmtCntnt* pLeftCntnt = &pLeftFooterFmt->GetCntnt();
135 if( pLeftCntnt->GetCntntIdx() )
136 nFooterLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
137 else
138 nFooterLeft = 0;
141 int i = 0;
142 ++i; // To set a breakpoint
144 #endif
146 SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc & _aOld,
147 const SwPageDesc & _aNew,
148 SwDoc * _pDoc)
149 : SwUndo( _aOld.GetName() != _aNew.GetName() ?
150 UNDO_RENAME_PAGEDESC :
151 UNDO_CHANGE_PAGEDESC ),
152 aOld(_aOld, _pDoc), aNew(_aNew, _pDoc), pDoc(_pDoc), bExchange( false )
154 ASSERT(0 != pDoc, "no document?");
156 #ifdef DEBUG
157 DebugHeaderFooterContent( (SwPageDesc&)aOld );
158 DebugHeaderFooterContent( (SwPageDesc&)aNew );
159 #endif
162 The page description changes.
163 If there are no header/footer content changes like header on/off or change from shared content
164 to unshared etc., there is no reason to duplicate the content nodes (Crash i55547)
165 But this happens, this Undo Ctor will destroy the unnecessary duplicate and manipulate the
166 content pointer of the both page descriptions.
168 SwPageDesc &rOldDesc = (SwPageDesc&)aOld;
169 SwPageDesc &rNewDesc = (SwPageDesc&)aNew;
170 const SwFmtHeader& rOldHead = rOldDesc.GetMaster().GetHeader();
171 const SwFmtHeader& rNewHead = rNewDesc.GetMaster().GetHeader();
172 const SwFmtFooter& rOldFoot = rOldDesc.GetMaster().GetFooter();
173 const SwFmtFooter& rNewFoot = rNewDesc.GetMaster().GetFooter();
174 /* bExchange must not be set, if the old page descriptor will stay active.
175 Two known situations:
176 #i67735#: renaming a page descriptor
177 #i67334#: changing the follow style
178 If header/footer will be activated or deactivated, this undo will not work.
180 bExchange = ( aOld.GetName() == aNew.GetName() ) &&
181 ( _aOld.GetFollow() == _aNew.GetFollow() ) &&
182 ( rOldHead.IsActive() == rNewHead.IsActive() ) &&
183 ( rOldFoot.IsActive() == rNewFoot.IsActive() );
184 if( rOldHead.IsActive() && ( rOldDesc.IsHeaderShared() != rNewDesc.IsHeaderShared() ) )
185 bExchange = false;
186 if( rOldFoot.IsActive() && ( rOldDesc.IsFooterShared() != rNewDesc.IsFooterShared() ) )
187 bExchange = false;
188 if( bExchange )
190 if( rNewHead.IsActive() )
192 SwFrmFmt* pFormat = new SwFrmFmt( *rNewHead.GetHeaderFmt() );
193 // The Ctor of this object will remove the duplicate!
194 SwFmtHeader aFmtHeader( pFormat );
195 if( !rNewDesc.IsHeaderShared() )
197 pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetHeader().GetHeaderFmt() );
198 // The Ctor of this object will remove the duplicate!
199 SwFmtHeader aFormatHeader( pFormat );
202 // Same procedure for footers...
203 if( rNewFoot.IsActive() )
205 SwFrmFmt* pFormat = new SwFrmFmt( *rNewFoot.GetFooterFmt() );
206 // The Ctor of this object will remove the duplicate!
207 SwFmtFooter aFmtFooter( pFormat );
208 if( !rNewDesc.IsFooterShared() )
210 pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetFooter().GetFooterFmt() );
211 // The Ctor of this object will remove the duplicate!
212 SwFmtFooter aFormatFooter( pFormat );
216 // After this exchange method the old page description will point to zero,
217 // the new one will point to the node position of the original content nodes.
218 ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
219 #ifdef DEBUG
220 DebugHeaderFooterContent( (SwPageDesc&)aOld );
221 DebugHeaderFooterContent( (SwPageDesc&)aNew );
222 #endif
226 SwUndoPageDesc::~SwUndoPageDesc()
231 void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc& rSource, SwPageDesc &rDest )
233 ASSERT( bExchange, "You shouldn't do that." );
234 const SwFmtHeader& rDestHead = rDest.GetMaster().GetHeader();
235 const SwFmtHeader& rSourceHead = rSource.GetMaster().GetHeader();
236 if( rDestHead.IsActive() )
238 // Let the destination page descrition point to the source node position,
239 // from now on this descriptor is responsible for the content nodes!
240 const SfxPoolItem* pItem;
241 rDest.GetMaster().GetAttrSet().GetItemState( RES_HEADER, FALSE, &pItem );
242 SfxPoolItem *pNewItem = pItem->Clone();
243 SwFrmFmt* pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
244 #ifdef DEBUG
245 const SwFmtCntnt& rSourceCntnt = rSourceHead.GetHeaderFmt()->GetCntnt();
246 (void)rSourceCntnt;
247 const SwFmtCntnt& rDestCntnt = rDestHead.GetHeaderFmt()->GetCntnt();
248 (void)rDestCntnt;
249 #endif
250 pNewFmt->SetFmtAttr( rSourceHead.GetHeaderFmt()->GetCntnt() );
251 delete pNewItem;
253 // Let the source page description point to zero node position,
254 // it loses the responsible and can be destroyed without removing the content nodes.
255 rSource.GetMaster().GetAttrSet().GetItemState( RES_HEADER, FALSE, &pItem );
256 pNewItem = pItem->Clone();
257 pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
258 pNewFmt->SetFmtAttr( SwFmtCntnt() );
259 delete pNewItem;
261 if( !rDest.IsHeaderShared() )
263 // Same procedure for unshared header..
264 const SwFmtHeader& rSourceLeftHead = rSource.GetLeft().GetHeader();
265 rDest.GetLeft().GetAttrSet().GetItemState( RES_HEADER, FALSE, &pItem );
266 pNewItem = pItem->Clone();
267 pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
268 #ifdef DEBUG
269 const SwFmtCntnt& rSourceCntnt1 = rSourceLeftHead.GetHeaderFmt()->GetCntnt();
270 (void)rSourceCntnt1;
271 const SwFmtCntnt& rDestCntnt1 = rDest.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt();
272 (void)rDestCntnt1;
273 #endif
274 pNewFmt->SetFmtAttr( rSourceLeftHead.GetHeaderFmt()->GetCntnt() );
275 delete pNewItem;
276 rSource.GetLeft().GetAttrSet().GetItemState( RES_HEADER, FALSE, &pItem );
277 pNewItem = pItem->Clone();
278 pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
279 pNewFmt->SetFmtAttr( SwFmtCntnt() );
280 delete pNewItem;
283 // Same procedure for footers...
284 const SwFmtFooter& rDestFoot = rDest.GetMaster().GetFooter();
285 const SwFmtFooter& rSourceFoot = rSource.GetMaster().GetFooter();
286 if( rDestFoot.IsActive() )
288 const SfxPoolItem* pItem;
289 rDest.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, FALSE, &pItem );
290 SfxPoolItem *pNewItem = pItem->Clone();
291 SwFrmFmt *pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
292 pNewFmt->SetFmtAttr( rSourceFoot.GetFooterFmt()->GetCntnt() );
293 delete pNewItem;
295 #ifdef DEBUG
296 const SwFmtCntnt& rFooterSourceCntnt = rSourceFoot.GetFooterFmt()->GetCntnt();
297 (void)rFooterSourceCntnt;
298 const SwFmtCntnt& rFooterDestCntnt = rDestFoot.GetFooterFmt()->GetCntnt();
299 (void)rFooterDestCntnt;
300 #endif
301 rSource.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, FALSE, &pItem );
302 pNewItem = pItem->Clone();
303 pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
304 pNewFmt->SetFmtAttr( SwFmtCntnt() );
305 delete pNewItem;
307 if( !rDest.IsFooterShared() )
309 const SwFmtFooter& rSourceLeftFoot = rSource.GetLeft().GetFooter();
310 #ifdef DEBUG
311 const SwFmtCntnt& rFooterSourceCntnt2 = rSourceLeftFoot.GetFooterFmt()->GetCntnt();
312 const SwFmtCntnt& rFooterDestCntnt2 =
313 rDest.GetLeft().GetFooter().GetFooterFmt()->GetCntnt();
314 (void)rFooterSourceCntnt2;
315 (void)rFooterDestCntnt2;
316 #endif
317 rDest.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, FALSE, &pItem );
318 pNewItem = pItem->Clone();
319 pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
320 pNewFmt->SetFmtAttr( rSourceLeftFoot.GetFooterFmt()->GetCntnt() );
321 delete pNewItem;
322 rSource.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, FALSE, &pItem );
323 pNewItem = pItem->Clone();
324 pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
325 pNewFmt->SetFmtAttr( SwFmtCntnt() );
326 delete pNewItem;
331 void SwUndoPageDesc::Undo(SwUndoIter &)
333 BOOL bUndo = pDoc->DoesUndo();
335 pDoc->DoUndo(FALSE);
337 // Move (header/footer)content node responsibility from new page descriptor to old one again.
338 if( bExchange )
339 ExchangeContentNodes( (SwPageDesc&)aNew, (SwPageDesc&)aOld );
340 pDoc->ChgPageDesc(aOld.GetName(), aOld);
341 pDoc->DoUndo(bUndo);
344 void SwUndoPageDesc::Redo(SwUndoIter &)
346 BOOL bUndo = pDoc->DoesUndo();
348 pDoc->DoUndo(FALSE);
350 // Move (header/footer)content node responsibility from old page descriptor to new one again.
351 if( bExchange )
352 ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
353 pDoc->ChgPageDesc(aNew.GetName(), aNew);
354 pDoc->DoUndo(bUndo);
357 void SwUndoPageDesc::Repeat(SwUndoIter &)
361 SwRewriter SwUndoPageDesc::GetRewriter() const
363 SwRewriter aResult;
365 aResult.AddRule(UNDO_ARG1, aOld.GetName());
366 aResult.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS));
367 aResult.AddRule(UNDO_ARG3, aNew.GetName());
369 return aResult;
372 // #116530#
373 SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc * pNew,
374 SwDoc * _pDoc)
375 : SwUndo(UNDO_CREATE_PAGEDESC), pDesc(pNew), aNew(*pNew, _pDoc),
376 pDoc(_pDoc)
378 ASSERT(0 != pDoc, "no document?");
381 SwUndoPageDescCreate::~SwUndoPageDescCreate()
385 void SwUndoPageDescCreate::Undo(SwUndoIter &)
387 BOOL bUndo = pDoc->DoesUndo();
389 pDoc->DoUndo(FALSE);
391 // -> #116530#
392 if (pDesc)
394 aNew = *pDesc;
395 pDesc = NULL;
397 // <- #116530#
399 pDoc->DelPageDesc(aNew.GetName(), TRUE);
400 pDoc->DoUndo(bUndo);
404 void SwUndoPageDescCreate::Redo(SwUndoIter &)
406 BOOL bUndo = pDoc->DoesUndo();
408 pDoc->DoUndo(FALSE);
410 SwPageDesc aPageDesc = aNew;
411 pDoc->MakePageDesc(aNew.GetName(), &aPageDesc, FALSE, TRUE); // #116530#
413 pDoc->DoUndo(bUndo);
416 void SwUndoPageDescCreate::Repeat(SwUndoIter & rIt)
418 Redo(rIt);
421 SwRewriter SwUndoPageDescCreate::GetRewriter() const
423 SwRewriter aResult;
425 if (pDesc)
426 aResult.AddRule(UNDO_ARG1, pDesc->GetName());
427 else
428 aResult.AddRule(UNDO_ARG1, aNew.GetName());
431 return aResult;
434 SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc & _aOld,
435 SwDoc * _pDoc)
436 : SwUndo(UNDO_DELETE_PAGEDESC), aOld(_aOld, _pDoc), pDoc(_pDoc)
438 ASSERT(0 != pDoc, "no document?");
441 SwUndoPageDescDelete::~SwUndoPageDescDelete()
445 void SwUndoPageDescDelete::Undo(SwUndoIter &)
447 BOOL bUndo = pDoc->DoesUndo();
449 pDoc->DoUndo(FALSE);
451 SwPageDesc aPageDesc = aOld;
452 pDoc->MakePageDesc(aOld.GetName(), &aPageDesc, FALSE, TRUE); // #116530#
453 pDoc->DoUndo(bUndo);
456 void SwUndoPageDescDelete::Redo(SwUndoIter &)
458 BOOL bUndo = pDoc->DoesUndo();
460 pDoc->DoUndo(FALSE);
461 pDoc->DelPageDesc(aOld.GetName(), TRUE); // #116530#
462 pDoc->DoUndo(bUndo);
465 void SwUndoPageDescDelete::Repeat(SwUndoIter & rIt)
467 Redo(rIt);
470 SwRewriter SwUndoPageDescDelete::GetRewriter() const
472 SwRewriter aResult;
474 aResult.AddRule(UNDO_ARG1, aOld.GetName());
476 return aResult;