1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: SwUndoPageDesc.cxx,v $
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>
37 #include <pagedesc.hxx>
38 #include <SwUndoPageDesc.hxx>
39 #include <SwRewriter.hxx>
41 #include <comcore.hrc>
42 #include <fmtcntnt.hxx>
43 #include <fmthdft.hxx>
46 #include <ndindex.hxx>
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
;
59 int nLeftHeaderCount
= 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();
74 SwClientIter
aIter( *pHeaderFmt
);
75 SwClient
*pLast
= aIter
.GoStart();
80 } while( 0 != ( pLast
= aIter
++ ));
81 const SwFmtCntnt
* pCntnt
= &pHeaderFmt
->GetCntnt();
82 if( pCntnt
->GetCntntIdx() )
83 nHeaderMaster
= pCntnt
->GetCntntIdx()->GetIndex();
87 bSharedHeader
= rPageDesc
.IsHeaderShared();
88 SwFrmFmt
* pLeftHeaderFmt
= rLeftHead
.GetHeaderFmt();
91 SwClientIter
aIter( *pLeftHeaderFmt
);
92 SwClient
*pLast
= aIter
.GoStart();
97 } while( 0 != ( pLast
= aIter
++ ));
98 const SwFmtCntnt
* pLeftCntnt
= &pLeftHeaderFmt
->GetCntnt();
99 if( pLeftCntnt
->GetCntntIdx() )
100 nHeaderLeft
= pLeftCntnt
->GetCntntIdx()->GetIndex();
105 if( rFoot
.IsActive() )
107 SwFrmFmt
* pFooterFmt
= rFoot
.GetFooterFmt();
110 SwClientIter
aIter( *pFooterFmt
);
111 SwClient
*pLast
= aIter
.GoStart();
116 } while( 0 != ( pLast
= aIter
++ ));
117 const SwFmtCntnt
* pCntnt
= &pFooterFmt
->GetCntnt();
118 if( pCntnt
->GetCntntIdx() )
119 nFooterMaster
= pCntnt
->GetCntntIdx()->GetIndex();
123 bSharedFooter
= rPageDesc
.IsFooterShared();
124 SwFrmFmt
* pLeftFooterFmt
= rLeftFoot
.GetFooterFmt();
127 SwClientIter
aIter( *pLeftFooterFmt
);
128 SwClient
*pLast
= aIter
.GoStart();
133 } while( 0 != ( pLast
= aIter
++ ));
134 const SwFmtCntnt
* pLeftCntnt
= &pLeftFooterFmt
->GetCntnt();
135 if( pLeftCntnt
->GetCntntIdx() )
136 nFooterLeft
= pLeftCntnt
->GetCntntIdx()->GetIndex();
142 ++i
; // To set a breakpoint
146 SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc
& _aOld
,
147 const SwPageDesc
& _aNew
,
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?");
157 DebugHeaderFooterContent( (SwPageDesc
&)aOld
);
158 DebugHeaderFooterContent( (SwPageDesc
&)aNew
);
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() ) )
186 if( rOldFoot
.IsActive() && ( rOldDesc
.IsFooterShared() != rNewDesc
.IsFooterShared() ) )
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
);
220 DebugHeaderFooterContent( (SwPageDesc
&)aOld
);
221 DebugHeaderFooterContent( (SwPageDesc
&)aNew
);
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();
245 const SwFmtCntnt
& rSourceCntnt
= rSourceHead
.GetHeaderFmt()->GetCntnt();
247 const SwFmtCntnt
& rDestCntnt
= rDestHead
.GetHeaderFmt()->GetCntnt();
250 pNewFmt
->SetFmtAttr( rSourceHead
.GetHeaderFmt()->GetCntnt() );
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() );
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();
269 const SwFmtCntnt
& rSourceCntnt1
= rSourceLeftHead
.GetHeaderFmt()->GetCntnt();
271 const SwFmtCntnt
& rDestCntnt1
= rDest
.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt();
274 pNewFmt
->SetFmtAttr( rSourceLeftHead
.GetHeaderFmt()->GetCntnt() );
276 rSource
.GetLeft().GetAttrSet().GetItemState( RES_HEADER
, FALSE
, &pItem
);
277 pNewItem
= pItem
->Clone();
278 pNewFmt
= ((SwFmtHeader
*)pNewItem
)->GetHeaderFmt();
279 pNewFmt
->SetFmtAttr( SwFmtCntnt() );
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() );
296 const SwFmtCntnt
& rFooterSourceCntnt
= rSourceFoot
.GetFooterFmt()->GetCntnt();
297 (void)rFooterSourceCntnt
;
298 const SwFmtCntnt
& rFooterDestCntnt
= rDestFoot
.GetFooterFmt()->GetCntnt();
299 (void)rFooterDestCntnt
;
301 rSource
.GetMaster().GetAttrSet().GetItemState( RES_FOOTER
, FALSE
, &pItem
);
302 pNewItem
= pItem
->Clone();
303 pNewFmt
= ((SwFmtFooter
*)pNewItem
)->GetFooterFmt();
304 pNewFmt
->SetFmtAttr( SwFmtCntnt() );
307 if( !rDest
.IsFooterShared() )
309 const SwFmtFooter
& rSourceLeftFoot
= rSource
.GetLeft().GetFooter();
311 const SwFmtCntnt
& rFooterSourceCntnt2
= rSourceLeftFoot
.GetFooterFmt()->GetCntnt();
312 const SwFmtCntnt
& rFooterDestCntnt2
=
313 rDest
.GetLeft().GetFooter().GetFooterFmt()->GetCntnt();
314 (void)rFooterSourceCntnt2
;
315 (void)rFooterDestCntnt2
;
317 rDest
.GetLeft().GetAttrSet().GetItemState( RES_FOOTER
, FALSE
, &pItem
);
318 pNewItem
= pItem
->Clone();
319 pNewFmt
= ((SwFmtFooter
*)pNewItem
)->GetFooterFmt();
320 pNewFmt
->SetFmtAttr( rSourceLeftFoot
.GetFooterFmt()->GetCntnt() );
322 rSource
.GetLeft().GetAttrSet().GetItemState( RES_FOOTER
, FALSE
, &pItem
);
323 pNewItem
= pItem
->Clone();
324 pNewFmt
= ((SwFmtFooter
*)pNewItem
)->GetFooterFmt();
325 pNewFmt
->SetFmtAttr( SwFmtCntnt() );
331 void SwUndoPageDesc::Undo(SwUndoIter
&)
333 BOOL bUndo
= pDoc
->DoesUndo();
337 // Move (header/footer)content node responsibility from new page descriptor to old one again.
339 ExchangeContentNodes( (SwPageDesc
&)aNew
, (SwPageDesc
&)aOld
);
340 pDoc
->ChgPageDesc(aOld
.GetName(), aOld
);
344 void SwUndoPageDesc::Redo(SwUndoIter
&)
346 BOOL bUndo
= pDoc
->DoesUndo();
350 // Move (header/footer)content node responsibility from old page descriptor to new one again.
352 ExchangeContentNodes( (SwPageDesc
&)aOld
, (SwPageDesc
&)aNew
);
353 pDoc
->ChgPageDesc(aNew
.GetName(), aNew
);
357 void SwUndoPageDesc::Repeat(SwUndoIter
&)
361 SwRewriter
SwUndoPageDesc::GetRewriter() const
365 aResult
.AddRule(UNDO_ARG1
, aOld
.GetName());
366 aResult
.AddRule(UNDO_ARG2
, SW_RES(STR_YIELDS
));
367 aResult
.AddRule(UNDO_ARG3
, aNew
.GetName());
373 SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc
* pNew
,
375 : SwUndo(UNDO_CREATE_PAGEDESC
), pDesc(pNew
), aNew(*pNew
, _pDoc
),
378 ASSERT(0 != pDoc
, "no document?");
381 SwUndoPageDescCreate::~SwUndoPageDescCreate()
385 void SwUndoPageDescCreate::Undo(SwUndoIter
&)
387 BOOL bUndo
= pDoc
->DoesUndo();
399 pDoc
->DelPageDesc(aNew
.GetName(), TRUE
);
404 void SwUndoPageDescCreate::Redo(SwUndoIter
&)
406 BOOL bUndo
= pDoc
->DoesUndo();
410 SwPageDesc aPageDesc
= aNew
;
411 pDoc
->MakePageDesc(aNew
.GetName(), &aPageDesc
, FALSE
, TRUE
); // #116530#
416 void SwUndoPageDescCreate::Repeat(SwUndoIter
& rIt
)
421 SwRewriter
SwUndoPageDescCreate::GetRewriter() const
426 aResult
.AddRule(UNDO_ARG1
, pDesc
->GetName());
428 aResult
.AddRule(UNDO_ARG1
, aNew
.GetName());
434 SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc
& _aOld
,
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();
451 SwPageDesc aPageDesc
= aOld
;
452 pDoc
->MakePageDesc(aOld
.GetName(), &aPageDesc
, FALSE
, TRUE
); // #116530#
456 void SwUndoPageDescDelete::Redo(SwUndoIter
&)
458 BOOL bUndo
= pDoc
->DoesUndo();
461 pDoc
->DelPageDesc(aOld
.GetName(), TRUE
); // #116530#
465 void SwUndoPageDescDelete::Repeat(SwUndoIter
& rIt
)
470 SwRewriter
SwUndoPageDescDelete::GetRewriter() const
474 aResult
.AddRule(UNDO_ARG1
, aOld
.GetName());