Impress Remote 1.0.5, tag sdremote-1.0.5
[LibreOffice.git] / sw / source / core / undo / SwUndoPageDesc.cxx
blob6962684ed8827aea07996b9c4545e945e8288833
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
22 #include <doc.hxx>
23 #include <IDocumentUndoRedo.hxx>
24 #include <swundo.hxx>
25 #include <pagedesc.hxx>
26 #include <SwUndoPageDesc.hxx>
27 #include <SwRewriter.hxx>
28 #include <undobj.hxx>
29 #include <comcore.hrc>
30 #include <fmtcntnt.hxx>
31 #include <fmthdft.hxx>
33 #if OSL_DEBUG_LEVEL > 1
34 #include <ndindex.hxx>
35 #endif
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();
54 if( pHeaderFmt )
56 const SwFmtCntnt* pCntnt = &pHeaderFmt->GetCntnt();
57 if( pCntnt->GetCntntIdx() )
58 nHeaderMaster = pCntnt->GetCntntIdx()->GetIndex();
59 else
60 nHeaderMaster = 0;
62 SwFrmFmt* pLeftHeaderFmt = rLeftHead.GetHeaderFmt();
63 if( pLeftHeaderFmt )
65 const SwFmtCntnt* pLeftCntnt = &pLeftHeaderFmt->GetCntnt();
66 if( pLeftCntnt->GetCntntIdx() )
67 nHeaderLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
68 else
69 nHeaderLeft = 0;
72 if( rFoot.IsActive() )
74 SwFrmFmt* pFooterFmt = rFoot.GetFooterFmt();
75 if( pFooterFmt )
77 const SwFmtCntnt* pCntnt = &pFooterFmt->GetCntnt();
78 if( pCntnt->GetCntntIdx() )
79 nFooterMaster = pCntnt->GetCntntIdx()->GetIndex();
80 else
81 nFooterMaster = 0;
83 SwFrmFmt* pLeftFooterFmt = rLeftFoot.GetFooterFmt();
84 if( pLeftFooterFmt )
86 const SwFmtCntnt* pLeftCntnt = &pLeftFooterFmt->GetCntnt();
87 if( pLeftCntnt->GetCntntIdx() )
88 nFooterLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
89 else
90 nFooterLeft = 0;
94 (void)nHeaderMaster;
95 (void)nHeaderLeft;
96 (void)nFooterMaster;
97 (void)nFooterLeft;
99 #endif
101 SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc & _aOld,
102 const SwPageDesc & _aNew,
103 SwDoc * _pDoc)
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 );
114 #endif
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() ) )
140 bExchange = false;
141 if( rOldFoot.IsActive() && ( rOldDesc.IsFooterShared() != rNewDesc.IsFooterShared() ) )
142 bExchange = false;
143 if( ( rOldHead.IsActive() || rOldFoot.IsActive() ) && ( rOldDesc.IsFirstShared() != rNewDesc.IsFirstShared() ) )
144 bExchange = false;
145 if( bExchange )
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 );
191 #endif
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();
215 (void)rSourceCntnt;
216 const SwFmtCntnt& rDestCntnt = rDestHead.GetHeaderFmt()->GetCntnt();
217 (void)rDestCntnt;
218 #endif
219 pNewFmt->SetFmtAttr( rSourceHead.GetHeaderFmt()->GetCntnt() );
220 delete pNewItem;
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() );
228 delete pNewItem;
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();
239 (void)rSourceCntnt1;
240 const SwFmtCntnt& rDestCntnt1 = rDest.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt();
241 (void)rDestCntnt1;
242 #endif
243 pNewFmt->SetFmtAttr( rSourceLeftHead.GetHeaderFmt()->GetCntnt() );
244 delete pNewItem;
245 rSource.GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem );
246 pNewItem = pItem->Clone();
247 pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
248 pNewFmt->SetFmtAttr( SwFmtCntnt() );
249 delete pNewItem;
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() );
262 delete pNewItem;
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;
269 #endif
270 rSource.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem );
271 pNewItem = pItem->Clone();
272 pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
273 pNewFmt->SetFmtAttr( SwFmtCntnt() );
274 delete pNewItem;
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;
285 #endif
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() );
290 delete pNewItem;
291 rSource.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem );
292 pNewItem = pItem->Clone();
293 pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
294 pNewFmt->SetFmtAttr( SwFmtCntnt() );
295 delete pNewItem;
300 void SwUndoPageDesc::UndoImpl(::sw::UndoRedoContext &)
302 // Move (header/footer)content node responsibility from new page descriptor to old one again.
303 if( bExchange )
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.
311 if( bExchange )
312 ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
313 pDoc->ChgPageDesc(aNew.GetName(), aNew);
316 SwRewriter SwUndoPageDesc::GetRewriter() const
318 SwRewriter aResult;
320 aResult.AddRule(UndoArg1, aOld.GetName());
321 aResult.AddRule(UndoArg2, SW_RESSTR(STR_YIELDS));
322 aResult.AddRule(UndoArg3, aNew.GetName());
324 return aResult;
327 // #116530#
328 SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc * pNew,
329 SwDoc * _pDoc)
330 : SwUndo(UNDO_CREATE_PAGEDESC), pDesc(pNew), aNew(*pNew, _pDoc),
331 pDoc(_pDoc)
333 OSL_ENSURE(0 != pDoc, "no document?");
336 SwUndoPageDescCreate::~SwUndoPageDescCreate()
340 void SwUndoPageDescCreate::UndoImpl(::sw::UndoRedoContext &)
342 // -> #116530#
343 if (pDesc)
345 aNew = *pDesc;
346 pDesc = NULL;
348 // <- #116530#
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 &)
361 DoImpl();
364 void SwUndoPageDescCreate::RepeatImpl(::sw::RepeatContext &)
366 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
367 DoImpl();
370 SwRewriter SwUndoPageDescCreate::GetRewriter() const
372 SwRewriter aResult;
374 if (pDesc)
375 aResult.AddRule(UndoArg1, pDesc->GetName());
376 else
377 aResult.AddRule(UndoArg1, aNew.GetName());
380 return aResult;
383 SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc & _aOld,
384 SwDoc * _pDoc)
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 &)
407 DoImpl();
410 void SwUndoPageDescDelete::RepeatImpl(::sw::RepeatContext &)
412 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
413 DoImpl();
416 SwRewriter SwUndoPageDescDelete::GetRewriter() const
418 SwRewriter aResult;
420 aResult.AddRule(UndoArg1, aOld.GetName());
422 return aResult;
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */