1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <tools/resid.hxx>
23 #include <IDocumentUndoRedo.hxx>
25 #include <pagedesc.hxx>
26 #include <SwUndoPageDesc.hxx>
27 #include <SwRewriter.hxx>
29 #include <comcore.hrc>
30 #include <fmtcntnt.hxx>
31 #include <fmthdft.hxx>
33 #if OSL_DEBUG_LEVEL > 1
34 #include <ndindex.hxx>
38 #if OSL_DEBUG_LEVEL > 1
39 // Pure debug help function to have a quick look at the header/footer attributes.
40 void DebugHeaderFooterContent( const SwPageDesc
& rPageDesc
)
42 sal_uLong nHeaderMaster
= ULONG_MAX
;
43 sal_uLong nHeaderLeft
= ULONG_MAX
;
44 sal_uLong nFooterMaster
= ULONG_MAX
;
45 sal_uLong nFooterLeft
= ULONG_MAX
;
47 SwFmtHeader
& rHead
= (SwFmtHeader
&)rPageDesc
.GetMaster().GetHeader();
48 SwFmtFooter
& rFoot
= (SwFmtFooter
&)rPageDesc
.GetMaster().GetFooter();
49 SwFmtHeader
& rLeftHead
= (SwFmtHeader
&)rPageDesc
.GetLeft().GetHeader();
50 SwFmtFooter
& rLeftFoot
= (SwFmtFooter
&)rPageDesc
.GetLeft().GetFooter();
51 if( rHead
.IsActive() )
53 SwFrmFmt
* pHeaderFmt
= rHead
.GetHeaderFmt();
56 const SwFmtCntnt
* pCntnt
= &pHeaderFmt
->GetCntnt();
57 if( pCntnt
->GetCntntIdx() )
58 nHeaderMaster
= pCntnt
->GetCntntIdx()->GetIndex();
62 SwFrmFmt
* pLeftHeaderFmt
= rLeftHead
.GetHeaderFmt();
65 const SwFmtCntnt
* pLeftCntnt
= &pLeftHeaderFmt
->GetCntnt();
66 if( pLeftCntnt
->GetCntntIdx() )
67 nHeaderLeft
= pLeftCntnt
->GetCntntIdx()->GetIndex();
72 if( rFoot
.IsActive() )
74 SwFrmFmt
* pFooterFmt
= rFoot
.GetFooterFmt();
77 const SwFmtCntnt
* pCntnt
= &pFooterFmt
->GetCntnt();
78 if( pCntnt
->GetCntntIdx() )
79 nFooterMaster
= pCntnt
->GetCntntIdx()->GetIndex();
83 SwFrmFmt
* pLeftFooterFmt
= rLeftFoot
.GetFooterFmt();
86 const SwFmtCntnt
* pLeftCntnt
= &pLeftFooterFmt
->GetCntnt();
87 if( pLeftCntnt
->GetCntntIdx() )
88 nFooterLeft
= pLeftCntnt
->GetCntntIdx()->GetIndex();
101 SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc
& _aOld
,
102 const SwPageDesc
& _aNew
,
104 : SwUndo( _aOld
.GetName() != _aNew
.GetName() ?
105 UNDO_RENAME_PAGEDESC
:
106 UNDO_CHANGE_PAGEDESC
),
107 aOld(_aOld
, _pDoc
), aNew(_aNew
, _pDoc
), pDoc(_pDoc
), bExchange( false )
109 OSL_ENSURE(0 != pDoc
, "no document?");
111 #if OSL_DEBUG_LEVEL > 1
112 DebugHeaderFooterContent( (SwPageDesc
&)aOld
);
113 DebugHeaderFooterContent( (SwPageDesc
&)aNew
);
117 The page description changes.
118 If there are no header/footer content changes like header on/off or change from shared content
119 to unshared etc., there is no reason to duplicate the content nodes (Crash i55547)
120 But this happens, this Undo Ctor will destroy the unnecessary duplicate and manipulate the
121 content pointer of the both page descriptions.
123 SwPageDesc
&rOldDesc
= (SwPageDesc
&)aOld
;
124 SwPageDesc
&rNewDesc
= (SwPageDesc
&)aNew
;
125 const SwFmtHeader
& rOldHead
= rOldDesc
.GetMaster().GetHeader();
126 const SwFmtHeader
& rNewHead
= rNewDesc
.GetMaster().GetHeader();
127 const SwFmtFooter
& rOldFoot
= rOldDesc
.GetMaster().GetFooter();
128 const SwFmtFooter
& rNewFoot
= rNewDesc
.GetMaster().GetFooter();
129 /* bExchange must not be set, if the old page descriptor will stay active.
130 Two known situations:
131 #i67735#: renaming a page descriptor
132 #i67334#: changing the follow style
133 If header/footer will be activated or deactivated, this undo will not work.
135 bExchange
= ( aOld
.GetName() == aNew
.GetName() ) &&
136 ( _aOld
.GetFollow() == _aNew
.GetFollow() ) &&
137 ( rOldHead
.IsActive() == rNewHead
.IsActive() ) &&
138 ( rOldFoot
.IsActive() == rNewFoot
.IsActive() );
139 if( rOldHead
.IsActive() && ( rOldDesc
.IsHeaderShared() != rNewDesc
.IsHeaderShared() ) )
141 if( rOldFoot
.IsActive() && ( rOldDesc
.IsFooterShared() != rNewDesc
.IsFooterShared() ) )
143 if( ( rOldHead
.IsActive() || rOldFoot
.IsActive() ) && ( rOldDesc
.IsFirstShared() != rNewDesc
.IsFirstShared() ) )
147 if( rNewHead
.IsActive() )
149 SwFrmFmt
* pFormat
= new SwFrmFmt( *rNewHead
.GetHeaderFmt() );
150 // The Ctor of this object will remove the duplicate!
151 SwFmtHeader
aFmtHeader( pFormat
);
152 if( !rNewDesc
.IsHeaderShared() )
154 pFormat
= new SwFrmFmt( *rNewDesc
.GetLeft().GetHeader().GetHeaderFmt() );
155 // The Ctor of this object will remove the duplicate!
156 SwFmtHeader
aFormatHeader( pFormat
);
158 if( !rNewDesc
.IsFirstShared() )
160 pFormat
= new SwFrmFmt( *rNewDesc
.GetFirst().GetHeader().GetHeaderFmt() );
161 // The Ctor of this object will remove the duplicate!
162 SwFmtHeader
aFormatHeader( pFormat
);
165 // Same procedure for footers...
166 if( rNewFoot
.IsActive() )
168 SwFrmFmt
* pFormat
= new SwFrmFmt( *rNewFoot
.GetFooterFmt() );
169 // The Ctor of this object will remove the duplicate!
170 SwFmtFooter
aFmtFooter( pFormat
);
171 if( !rNewDesc
.IsFooterShared() )
173 pFormat
= new SwFrmFmt( *rNewDesc
.GetLeft().GetFooter().GetFooterFmt() );
174 // The Ctor of this object will remove the duplicate!
175 SwFmtFooter
aFormatFooter( pFormat
);
177 if( !rNewDesc
.IsFirstShared() )
179 pFormat
= new SwFrmFmt( *rNewDesc
.GetFirst().GetFooter().GetFooterFmt() );
180 // The Ctor of this object will remove the duplicate!
181 SwFmtFooter
aFormatFooter( pFormat
);
185 // After this exchange method the old page description will point to zero,
186 // the new one will point to the node position of the original content nodes.
187 ExchangeContentNodes( (SwPageDesc
&)aOld
, (SwPageDesc
&)aNew
);
188 #if OSL_DEBUG_LEVEL > 1
189 DebugHeaderFooterContent( (SwPageDesc
&)aOld
);
190 DebugHeaderFooterContent( (SwPageDesc
&)aNew
);
195 SwUndoPageDesc::~SwUndoPageDesc()
200 void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc
& rSource
, SwPageDesc
&rDest
)
202 OSL_ENSURE( bExchange
, "You shouldn't do that." );
203 const SwFmtHeader
& rDestHead
= rDest
.GetMaster().GetHeader();
204 const SwFmtHeader
& rSourceHead
= rSource
.GetMaster().GetHeader();
205 if( rDestHead
.IsActive() )
207 // Let the destination page descrition point to the source node position,
208 // from now on this descriptor is responsible for the content nodes!
209 const SfxPoolItem
* pItem
;
210 rDest
.GetMaster().GetAttrSet().GetItemState( RES_HEADER
, sal_False
, &pItem
);
211 SfxPoolItem
*pNewItem
= pItem
->Clone();
212 SwFrmFmt
* pNewFmt
= ((SwFmtHeader
*)pNewItem
)->GetHeaderFmt();
213 #if OSL_DEBUG_LEVEL > 1
214 const SwFmtCntnt
& rSourceCntnt
= rSourceHead
.GetHeaderFmt()->GetCntnt();
216 const SwFmtCntnt
& rDestCntnt
= rDestHead
.GetHeaderFmt()->GetCntnt();
219 pNewFmt
->SetFmtAttr( rSourceHead
.GetHeaderFmt()->GetCntnt() );
222 // Let the source page description point to zero node position,
223 // it loses the responsible and can be destroyed without removing the content nodes.
224 rSource
.GetMaster().GetAttrSet().GetItemState( RES_HEADER
, sal_False
, &pItem
);
225 pNewItem
= pItem
->Clone();
226 pNewFmt
= ((SwFmtHeader
*)pNewItem
)->GetHeaderFmt();
227 pNewFmt
->SetFmtAttr( SwFmtCntnt() );
230 if( !rDest
.IsHeaderShared() )
232 // Same procedure for unshared header..
233 const SwFmtHeader
& rSourceLeftHead
= rSource
.GetLeft().GetHeader();
234 rDest
.GetLeft().GetAttrSet().GetItemState( RES_HEADER
, sal_False
, &pItem
);
235 pNewItem
= pItem
->Clone();
236 pNewFmt
= ((SwFmtHeader
*)pNewItem
)->GetHeaderFmt();
237 #if OSL_DEBUG_LEVEL > 1
238 const SwFmtCntnt
& rSourceCntnt1
= rSourceLeftHead
.GetHeaderFmt()->GetCntnt();
240 const SwFmtCntnt
& rDestCntnt1
= rDest
.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt();
243 pNewFmt
->SetFmtAttr( rSourceLeftHead
.GetHeaderFmt()->GetCntnt() );
245 rSource
.GetLeft().GetAttrSet().GetItemState( RES_HEADER
, sal_False
, &pItem
);
246 pNewItem
= pItem
->Clone();
247 pNewFmt
= ((SwFmtHeader
*)pNewItem
)->GetHeaderFmt();
248 pNewFmt
->SetFmtAttr( SwFmtCntnt() );
252 // Same procedure for footers...
253 const SwFmtFooter
& rDestFoot
= rDest
.GetMaster().GetFooter();
254 const SwFmtFooter
& rSourceFoot
= rSource
.GetMaster().GetFooter();
255 if( rDestFoot
.IsActive() )
257 const SfxPoolItem
* pItem
;
258 rDest
.GetMaster().GetAttrSet().GetItemState( RES_FOOTER
, sal_False
, &pItem
);
259 SfxPoolItem
*pNewItem
= pItem
->Clone();
260 SwFrmFmt
*pNewFmt
= ((SwFmtFooter
*)pNewItem
)->GetFooterFmt();
261 pNewFmt
->SetFmtAttr( rSourceFoot
.GetFooterFmt()->GetCntnt() );
264 #if OSL_DEBUG_LEVEL > 1
265 const SwFmtCntnt
& rFooterSourceCntnt
= rSourceFoot
.GetFooterFmt()->GetCntnt();
266 (void)rFooterSourceCntnt
;
267 const SwFmtCntnt
& rFooterDestCntnt
= rDestFoot
.GetFooterFmt()->GetCntnt();
268 (void)rFooterDestCntnt
;
270 rSource
.GetMaster().GetAttrSet().GetItemState( RES_FOOTER
, sal_False
, &pItem
);
271 pNewItem
= pItem
->Clone();
272 pNewFmt
= ((SwFmtFooter
*)pNewItem
)->GetFooterFmt();
273 pNewFmt
->SetFmtAttr( SwFmtCntnt() );
276 if( !rDest
.IsFooterShared() )
278 const SwFmtFooter
& rSourceLeftFoot
= rSource
.GetLeft().GetFooter();
279 #if OSL_DEBUG_LEVEL > 1
280 const SwFmtCntnt
& rFooterSourceCntnt2
= rSourceLeftFoot
.GetFooterFmt()->GetCntnt();
281 const SwFmtCntnt
& rFooterDestCntnt2
=
282 rDest
.GetLeft().GetFooter().GetFooterFmt()->GetCntnt();
283 (void)rFooterSourceCntnt2
;
284 (void)rFooterDestCntnt2
;
286 rDest
.GetLeft().GetAttrSet().GetItemState( RES_FOOTER
, sal_False
, &pItem
);
287 pNewItem
= pItem
->Clone();
288 pNewFmt
= ((SwFmtFooter
*)pNewItem
)->GetFooterFmt();
289 pNewFmt
->SetFmtAttr( rSourceLeftFoot
.GetFooterFmt()->GetCntnt() );
291 rSource
.GetLeft().GetAttrSet().GetItemState( RES_FOOTER
, sal_False
, &pItem
);
292 pNewItem
= pItem
->Clone();
293 pNewFmt
= ((SwFmtFooter
*)pNewItem
)->GetFooterFmt();
294 pNewFmt
->SetFmtAttr( SwFmtCntnt() );
300 void SwUndoPageDesc::UndoImpl(::sw::UndoRedoContext
&)
302 // Move (header/footer)content node responsibility from new page descriptor to old one again.
304 ExchangeContentNodes( (SwPageDesc
&)aNew
, (SwPageDesc
&)aOld
);
305 pDoc
->ChgPageDesc(aOld
.GetName(), aOld
);
308 void SwUndoPageDesc::RedoImpl(::sw::UndoRedoContext
&)
310 // Move (header/footer)content node responsibility from old page descriptor to new one again.
312 ExchangeContentNodes( (SwPageDesc
&)aOld
, (SwPageDesc
&)aNew
);
313 pDoc
->ChgPageDesc(aNew
.GetName(), aNew
);
316 SwRewriter
SwUndoPageDesc::GetRewriter() const
320 aResult
.AddRule(UndoArg1
, aOld
.GetName());
321 aResult
.AddRule(UndoArg2
, SW_RESSTR(STR_YIELDS
));
322 aResult
.AddRule(UndoArg3
, aNew
.GetName());
328 SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc
* pNew
,
330 : SwUndo(UNDO_CREATE_PAGEDESC
), pDesc(pNew
), aNew(*pNew
, _pDoc
),
333 OSL_ENSURE(0 != pDoc
, "no document?");
336 SwUndoPageDescCreate::~SwUndoPageDescCreate()
340 void SwUndoPageDescCreate::UndoImpl(::sw::UndoRedoContext
&)
350 pDoc
->DelPageDesc(aNew
.GetName(), true);
353 void SwUndoPageDescCreate::DoImpl()
355 SwPageDesc aPageDesc
= aNew
;
356 pDoc
->MakePageDesc(aNew
.GetName(), &aPageDesc
, false, true); // #116530#
359 void SwUndoPageDescCreate::RedoImpl(::sw::UndoRedoContext
&)
364 void SwUndoPageDescCreate::RepeatImpl(::sw::RepeatContext
&)
366 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
370 SwRewriter
SwUndoPageDescCreate::GetRewriter() const
375 aResult
.AddRule(UndoArg1
, pDesc
->GetName());
377 aResult
.AddRule(UndoArg1
, aNew
.GetName());
383 SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc
& _aOld
,
385 : SwUndo(UNDO_DELETE_PAGEDESC
), aOld(_aOld
, _pDoc
), pDoc(_pDoc
)
387 OSL_ENSURE(0 != pDoc
, "no document?");
390 SwUndoPageDescDelete::~SwUndoPageDescDelete()
394 void SwUndoPageDescDelete::UndoImpl(::sw::UndoRedoContext
&)
396 SwPageDesc aPageDesc
= aOld
;
397 pDoc
->MakePageDesc(aOld
.GetName(), &aPageDesc
, false, true); // #116530#
400 void SwUndoPageDescDelete::DoImpl()
402 pDoc
->DelPageDesc(aOld
.GetName(), true); // #116530#
405 void SwUndoPageDescDelete::RedoImpl(::sw::UndoRedoContext
&)
410 void SwUndoPageDescDelete::RepeatImpl(::sw::RepeatContext
&)
412 ::sw::UndoGuard
const undoGuard(pDoc
->GetIDocumentUndoRedo());
416 SwRewriter
SwUndoPageDescDelete::GetRewriter() const
420 aResult
.AddRule(UndoArg1
, aOld
.GetName());
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */