Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <tools/resid.hxx>
21 : #include <doc.hxx>
22 : #include <IDocumentUndoRedo.hxx>
23 : #include <swundo.hxx>
24 : #include <pagedesc.hxx>
25 : #include <SwUndoPageDesc.hxx>
26 : #include <SwRewriter.hxx>
27 : #include <undobj.hxx>
28 : #include <comcore.hrc>
29 : #include <fmtcntnt.hxx>
30 : #include <fmthdft.hxx>
31 :
32 : #if OSL_DEBUG_LEVEL > 1
33 : #include <ndindex.hxx>
34 : #endif
35 :
36 : #if OSL_DEBUG_LEVEL > 1
37 : // Pure debug help function to have a quick look at the header/footer attributes.
38 : void DebugHeaderFooterContent( const SwPageDesc& rPageDesc )
39 : {
40 : sal_uLong nHeaderMaster = ULONG_MAX;
41 : sal_uLong nHeaderLeft = ULONG_MAX;
42 : sal_uLong nFooterMaster = ULONG_MAX;
43 : sal_uLong nFooterLeft = ULONG_MAX;
44 :
45 : SwFmtHeader& rHead = (SwFmtHeader&)rPageDesc.GetMaster().GetHeader();
46 : SwFmtFooter& rFoot = (SwFmtFooter&)rPageDesc.GetMaster().GetFooter();
47 : SwFmtHeader& rLeftHead = (SwFmtHeader&)rPageDesc.GetLeft().GetHeader();
48 : SwFmtFooter& rLeftFoot = (SwFmtFooter&)rPageDesc.GetLeft().GetFooter();
49 : if( rHead.IsActive() )
50 : {
51 : SwFrmFmt* pHeaderFmt = rHead.GetHeaderFmt();
52 : if( pHeaderFmt )
53 : {
54 : const SwFmtCntnt* pCntnt = &pHeaderFmt->GetCntnt();
55 : if( pCntnt->GetCntntIdx() )
56 : nHeaderMaster = pCntnt->GetCntntIdx()->GetIndex();
57 : else
58 : nHeaderMaster = 0;
59 : }
60 : SwFrmFmt* pLeftHeaderFmt = rLeftHead.GetHeaderFmt();
61 : if( pLeftHeaderFmt )
62 : {
63 : const SwFmtCntnt* pLeftCntnt = &pLeftHeaderFmt->GetCntnt();
64 : if( pLeftCntnt->GetCntntIdx() )
65 : nHeaderLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
66 : else
67 : nHeaderLeft = 0;
68 : }
69 : }
70 : if( rFoot.IsActive() )
71 : {
72 : SwFrmFmt* pFooterFmt = rFoot.GetFooterFmt();
73 : if( pFooterFmt )
74 : {
75 : const SwFmtCntnt* pCntnt = &pFooterFmt->GetCntnt();
76 : if( pCntnt->GetCntntIdx() )
77 : nFooterMaster = pCntnt->GetCntntIdx()->GetIndex();
78 : else
79 : nFooterMaster = 0;
80 : }
81 : SwFrmFmt* pLeftFooterFmt = rLeftFoot.GetFooterFmt();
82 : if( pLeftFooterFmt )
83 : {
84 : const SwFmtCntnt* pLeftCntnt = &pLeftFooterFmt->GetCntnt();
85 : if( pLeftCntnt->GetCntntIdx() )
86 : nFooterLeft = pLeftCntnt->GetCntntIdx()->GetIndex();
87 : else
88 : nFooterLeft = 0;
89 : }
90 : }
91 :
92 : (void)nHeaderMaster;
93 : (void)nHeaderLeft;
94 : (void)nFooterMaster;
95 : (void)nFooterLeft;
96 : }
97 : #endif
98 :
99 0 : SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc & _aOld,
100 : const SwPageDesc & _aNew,
101 : SwDoc * _pDoc)
102 0 : : SwUndo( _aOld.GetName() != _aNew.GetName() ?
103 : UNDO_RENAME_PAGEDESC :
104 : UNDO_CHANGE_PAGEDESC ),
105 0 : aOld(_aOld, _pDoc), aNew(_aNew, _pDoc), pDoc(_pDoc), bExchange( false )
106 : {
107 : OSL_ENSURE(0 != pDoc, "no document?");
108 :
109 : #if OSL_DEBUG_LEVEL > 1
110 : DebugHeaderFooterContent( (SwPageDesc&)aOld );
111 : DebugHeaderFooterContent( (SwPageDesc&)aNew );
112 : #endif
113 :
114 : /*
115 : The page description changes.
116 : If there are no header/footer content changes like header on/off or change from shared content
117 : to unshared etc., there is no reason to duplicate the content nodes (Crash i55547)
118 : But this happens, this Undo Ctor will destroy the unnecessary duplicate and manipulate the
119 : content pointer of the both page descriptions.
120 : */
121 0 : SwPageDesc &rOldDesc = (SwPageDesc&)aOld;
122 0 : SwPageDesc &rNewDesc = (SwPageDesc&)aNew;
123 0 : const SwFmtHeader& rOldHead = rOldDesc.GetMaster().GetHeader();
124 0 : const SwFmtHeader& rNewHead = rNewDesc.GetMaster().GetHeader();
125 0 : const SwFmtFooter& rOldFoot = rOldDesc.GetMaster().GetFooter();
126 0 : const SwFmtFooter& rNewFoot = rNewDesc.GetMaster().GetFooter();
127 : /* bExchange must not be set, if the old page descriptor will stay active.
128 : Two known situations:
129 : #i67735#: renaming a page descriptor
130 : #i67334#: changing the follow style
131 : If header/footer will be activated or deactivated, this undo will not work.
132 : */
133 0 : bExchange = ( aOld.GetName() == aNew.GetName() ) &&
134 0 : ( _aOld.GetFollow() == _aNew.GetFollow() ) &&
135 0 : ( rOldHead.IsActive() == rNewHead.IsActive() ) &&
136 0 : ( rOldFoot.IsActive() == rNewFoot.IsActive() );
137 0 : if( rOldHead.IsActive() && ( rOldDesc.IsHeaderShared() != rNewDesc.IsHeaderShared() ) )
138 0 : bExchange = false;
139 0 : if( rOldFoot.IsActive() && ( rOldDesc.IsFooterShared() != rNewDesc.IsFooterShared() ) )
140 0 : bExchange = false;
141 0 : if( ( rOldHead.IsActive() || rOldFoot.IsActive() ) && ( rOldDesc.IsFirstShared() != rNewDesc.IsFirstShared() ) )
142 0 : bExchange = false;
143 0 : if( bExchange )
144 : {
145 0 : if( rNewHead.IsActive() )
146 : {
147 0 : SwFrmFmt* pFormat = new SwFrmFmt( *rNewHead.GetHeaderFmt() );
148 : // The Ctor of this object will remove the duplicate!
149 0 : SwFmtHeader aFmtHeader( pFormat );
150 0 : if( !rNewDesc.IsHeaderShared() )
151 : {
152 0 : pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetHeader().GetHeaderFmt() );
153 : // The Ctor of this object will remove the duplicate!
154 0 : SwFmtHeader aFormatHeader( pFormat );
155 : }
156 0 : if( !rNewDesc.IsFirstShared() )
157 : {
158 0 : pFormat = new SwFrmFmt( *rNewDesc.GetFirstMaster().GetHeader().GetHeaderFmt() );
159 : // The Ctor of this object will remove the duplicate!
160 0 : SwFmtHeader aFormatHeader( pFormat );
161 0 : }
162 : }
163 : // Same procedure for footers...
164 0 : if( rNewFoot.IsActive() )
165 : {
166 0 : SwFrmFmt* pFormat = new SwFrmFmt( *rNewFoot.GetFooterFmt() );
167 : // The Ctor of this object will remove the duplicate!
168 0 : SwFmtFooter aFmtFooter( pFormat );
169 0 : if( !rNewDesc.IsFooterShared() )
170 : {
171 0 : pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetFooter().GetFooterFmt() );
172 : // The Ctor of this object will remove the duplicate!
173 0 : SwFmtFooter aFormatFooter( pFormat );
174 : }
175 0 : if( !rNewDesc.IsFirstShared() )
176 : {
177 0 : pFormat = new SwFrmFmt( *rNewDesc.GetFirstMaster().GetFooter().GetFooterFmt() );
178 : // The Ctor of this object will remove the duplicate!
179 0 : SwFmtFooter aFormatFooter( pFormat );
180 0 : }
181 : }
182 :
183 : // After this exchange method the old page description will point to zero,
184 : // the new one will point to the node position of the original content nodes.
185 0 : ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
186 : #if OSL_DEBUG_LEVEL > 1
187 : DebugHeaderFooterContent( (SwPageDesc&)aOld );
188 : DebugHeaderFooterContent( (SwPageDesc&)aNew );
189 : #endif
190 : }
191 0 : }
192 :
193 0 : SwUndoPageDesc::~SwUndoPageDesc()
194 : {
195 0 : }
196 :
197 0 : void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc& rSource, SwPageDesc &rDest )
198 : {
199 : OSL_ENSURE( bExchange, "You shouldn't do that." );
200 0 : const SwFmtHeader& rDestHead = rDest.GetMaster().GetHeader();
201 0 : const SwFmtHeader& rSourceHead = rSource.GetMaster().GetHeader();
202 0 : if( rDestHead.IsActive() )
203 : {
204 : // Let the destination page descrition point to the source node position,
205 : // from now on this descriptor is responsible for the content nodes!
206 : const SfxPoolItem* pItem;
207 0 : rDest.GetMaster().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
208 0 : SfxPoolItem *pNewItem = pItem->Clone();
209 0 : SwFrmFmt* pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
210 : #if OSL_DEBUG_LEVEL > 1
211 : const SwFmtCntnt& rSourceCntnt = rSourceHead.GetHeaderFmt()->GetCntnt();
212 : (void)rSourceCntnt;
213 : const SwFmtCntnt& rDestCntnt = rDestHead.GetHeaderFmt()->GetCntnt();
214 : (void)rDestCntnt;
215 : #endif
216 0 : pNewFmt->SetFmtAttr( rSourceHead.GetHeaderFmt()->GetCntnt() );
217 0 : delete pNewItem;
218 :
219 : // Let the source page description point to zero node position,
220 : // it loses the responsible and can be destroyed without removing the content nodes.
221 0 : rSource.GetMaster().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
222 0 : pNewItem = pItem->Clone();
223 0 : pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
224 0 : pNewFmt->SetFmtAttr( SwFmtCntnt() );
225 0 : delete pNewItem;
226 :
227 0 : if( !rDest.IsHeaderShared() )
228 : {
229 : // Same procedure for unshared header..
230 0 : const SwFmtHeader& rSourceLeftHead = rSource.GetLeft().GetHeader();
231 0 : rDest.GetLeft().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
232 0 : pNewItem = pItem->Clone();
233 0 : pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
234 : #if OSL_DEBUG_LEVEL > 1
235 : const SwFmtCntnt& rSourceCntnt1 = rSourceLeftHead.GetHeaderFmt()->GetCntnt();
236 : (void)rSourceCntnt1;
237 : const SwFmtCntnt& rDestCntnt1 = rDest.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt();
238 : (void)rDestCntnt1;
239 : #endif
240 0 : pNewFmt->SetFmtAttr( rSourceLeftHead.GetHeaderFmt()->GetCntnt() );
241 0 : delete pNewItem;
242 0 : rSource.GetLeft().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
243 0 : pNewItem = pItem->Clone();
244 0 : pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
245 0 : pNewFmt->SetFmtAttr( SwFmtCntnt() );
246 0 : delete pNewItem;
247 : }
248 0 : if (!rDest.IsFirstShared())
249 : {
250 : // Same procedure for unshared header..
251 0 : const SwFmtHeader& rSourceFirstMasterHead = rSource.GetFirstMaster().GetHeader();
252 0 : rDest.GetFirstMaster().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
253 0 : pNewItem = pItem->Clone();
254 0 : pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
255 : #if OSL_DEBUG_LEVEL > 1
256 : const SwFmtCntnt& rSourceCntnt1 = rSourceFirstMasterHead.GetHeaderFmt()->GetCntnt();
257 : (void)rSourceCntnt1;
258 : const SwFmtCntnt& rDestCntnt1 = rDest.GetFirstMaster().GetHeader().GetHeaderFmt()->GetCntnt();
259 : (void)rDestCntnt1;
260 : #endif
261 0 : pNewFmt->SetFmtAttr( rSourceFirstMasterHead.GetHeaderFmt()->GetCntnt() );
262 0 : delete pNewItem;
263 0 : rSource.GetFirstMaster().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
264 0 : pNewItem = pItem->Clone();
265 0 : pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt();
266 0 : pNewFmt->SetFmtAttr( SwFmtCntnt() );
267 0 : delete pNewItem;
268 : }
269 : }
270 : // Same procedure for footers...
271 0 : const SwFmtFooter& rDestFoot = rDest.GetMaster().GetFooter();
272 0 : const SwFmtFooter& rSourceFoot = rSource.GetMaster().GetFooter();
273 0 : if( rDestFoot.IsActive() )
274 : {
275 : const SfxPoolItem* pItem;
276 0 : rDest.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
277 0 : SfxPoolItem *pNewItem = pItem->Clone();
278 0 : SwFrmFmt *pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
279 0 : pNewFmt->SetFmtAttr( rSourceFoot.GetFooterFmt()->GetCntnt() );
280 0 : delete pNewItem;
281 :
282 : #if OSL_DEBUG_LEVEL > 1
283 : const SwFmtCntnt& rFooterSourceCntnt = rSourceFoot.GetFooterFmt()->GetCntnt();
284 : (void)rFooterSourceCntnt;
285 : const SwFmtCntnt& rFooterDestCntnt = rDestFoot.GetFooterFmt()->GetCntnt();
286 : (void)rFooterDestCntnt;
287 : #endif
288 0 : rSource.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
289 0 : pNewItem = pItem->Clone();
290 0 : pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
291 0 : pNewFmt->SetFmtAttr( SwFmtCntnt() );
292 0 : delete pNewItem;
293 :
294 0 : if( !rDest.IsFooterShared() )
295 : {
296 0 : const SwFmtFooter& rSourceLeftFoot = rSource.GetLeft().GetFooter();
297 : #if OSL_DEBUG_LEVEL > 1
298 : const SwFmtCntnt& rFooterSourceCntnt2 = rSourceLeftFoot.GetFooterFmt()->GetCntnt();
299 : const SwFmtCntnt& rFooterDestCntnt2 =
300 : rDest.GetLeft().GetFooter().GetFooterFmt()->GetCntnt();
301 : (void)rFooterSourceCntnt2;
302 : (void)rFooterDestCntnt2;
303 : #endif
304 0 : rDest.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
305 0 : pNewItem = pItem->Clone();
306 0 : pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
307 0 : pNewFmt->SetFmtAttr( rSourceLeftFoot.GetFooterFmt()->GetCntnt() );
308 0 : delete pNewItem;
309 0 : rSource.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
310 0 : pNewItem = pItem->Clone();
311 0 : pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
312 0 : pNewFmt->SetFmtAttr( SwFmtCntnt() );
313 0 : delete pNewItem;
314 : }
315 0 : if (!rDest.IsFirstShared())
316 : {
317 0 : const SwFmtFooter& rSourceFirstMasterFoot = rSource.GetFirstMaster().GetFooter();
318 : #if OSL_DEBUG_LEVEL > 1
319 : const SwFmtCntnt& rFooterSourceCntnt2 = rSourceFirstMasterFoot.GetFooterFmt()->GetCntnt();
320 : const SwFmtCntnt& rFooterDestCntnt2 =
321 : rDest.GetFirstMaster().GetFooter().GetFooterFmt()->GetCntnt();
322 : (void)rFooterSourceCntnt2;
323 : (void)rFooterDestCntnt2;
324 : #endif
325 0 : rDest.GetFirstMaster().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
326 0 : pNewItem = pItem->Clone();
327 0 : pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
328 0 : pNewFmt->SetFmtAttr( rSourceFirstMasterFoot.GetFooterFmt()->GetCntnt() );
329 0 : delete pNewItem;
330 0 : rSource.GetFirstMaster().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
331 0 : pNewItem = pItem->Clone();
332 0 : pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt();
333 0 : pNewFmt->SetFmtAttr( SwFmtCntnt() );
334 0 : delete pNewItem;
335 : }
336 : }
337 0 : }
338 :
339 0 : void SwUndoPageDesc::UndoImpl(::sw::UndoRedoContext &)
340 : {
341 : // Move (header/footer)content node responsibility from new page descriptor to old one again.
342 0 : if( bExchange )
343 0 : ExchangeContentNodes( (SwPageDesc&)aNew, (SwPageDesc&)aOld );
344 0 : pDoc->ChgPageDesc(aOld.GetName(), aOld);
345 0 : }
346 :
347 0 : void SwUndoPageDesc::RedoImpl(::sw::UndoRedoContext &)
348 : {
349 : // Move (header/footer)content node responsibility from old page descriptor to new one again.
350 0 : if( bExchange )
351 0 : ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew );
352 0 : pDoc->ChgPageDesc(aNew.GetName(), aNew);
353 0 : }
354 :
355 0 : SwRewriter SwUndoPageDesc::GetRewriter() const
356 : {
357 0 : SwRewriter aResult;
358 :
359 0 : aResult.AddRule(UndoArg1, aOld.GetName());
360 0 : aResult.AddRule(UndoArg2, SW_RESSTR(STR_YIELDS));
361 0 : aResult.AddRule(UndoArg3, aNew.GetName());
362 :
363 0 : return aResult;
364 : }
365 :
366 : // #116530#
367 0 : SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc * pNew,
368 : SwDoc * _pDoc)
369 : : SwUndo(UNDO_CREATE_PAGEDESC), pDesc(pNew), aNew(*pNew, _pDoc),
370 0 : pDoc(_pDoc)
371 : {
372 : OSL_ENSURE(0 != pDoc, "no document?");
373 0 : }
374 :
375 0 : SwUndoPageDescCreate::~SwUndoPageDescCreate()
376 : {
377 0 : }
378 :
379 0 : void SwUndoPageDescCreate::UndoImpl(::sw::UndoRedoContext &)
380 : {
381 : // -> #116530#
382 0 : if (pDesc)
383 : {
384 0 : aNew = *pDesc;
385 0 : pDesc = NULL;
386 : }
387 : // <- #116530#
388 :
389 0 : pDoc->DelPageDesc(aNew.GetName(), true);
390 0 : }
391 :
392 0 : void SwUndoPageDescCreate::DoImpl()
393 : {
394 0 : SwPageDesc aPageDesc = aNew;
395 0 : pDoc->MakePageDesc(aNew.GetName(), &aPageDesc, false, true); // #116530#
396 0 : }
397 :
398 0 : void SwUndoPageDescCreate::RedoImpl(::sw::UndoRedoContext &)
399 : {
400 0 : DoImpl();
401 0 : }
402 :
403 0 : void SwUndoPageDescCreate::RepeatImpl(::sw::RepeatContext &)
404 : {
405 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
406 0 : DoImpl();
407 0 : }
408 :
409 0 : SwRewriter SwUndoPageDescCreate::GetRewriter() const
410 : {
411 0 : SwRewriter aResult;
412 :
413 0 : if (pDesc)
414 0 : aResult.AddRule(UndoArg1, pDesc->GetName());
415 : else
416 0 : aResult.AddRule(UndoArg1, aNew.GetName());
417 :
418 0 : return aResult;
419 : }
420 :
421 0 : SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc & _aOld,
422 : SwDoc * _pDoc)
423 0 : : SwUndo(UNDO_DELETE_PAGEDESC), aOld(_aOld, _pDoc), pDoc(_pDoc)
424 : {
425 : OSL_ENSURE(0 != pDoc, "no document?");
426 0 : }
427 :
428 0 : SwUndoPageDescDelete::~SwUndoPageDescDelete()
429 : {
430 0 : }
431 :
432 0 : void SwUndoPageDescDelete::UndoImpl(::sw::UndoRedoContext &)
433 : {
434 0 : SwPageDesc aPageDesc = aOld;
435 0 : pDoc->MakePageDesc(aOld.GetName(), &aPageDesc, false, true); // #116530#
436 0 : }
437 :
438 0 : void SwUndoPageDescDelete::DoImpl()
439 : {
440 0 : pDoc->DelPageDesc(aOld.GetName(), true); // #116530#
441 0 : }
442 :
443 0 : void SwUndoPageDescDelete::RedoImpl(::sw::UndoRedoContext &)
444 : {
445 0 : DoImpl();
446 0 : }
447 :
448 0 : void SwUndoPageDescDelete::RepeatImpl(::sw::RepeatContext &)
449 : {
450 0 : ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
451 0 : DoImpl();
452 0 : }
453 :
454 0 : SwRewriter SwUndoPageDescDelete::GetRewriter() const
455 : {
456 0 : SwRewriter aResult;
457 :
458 0 : aResult.AddRule(UndoArg1, aOld.GetName());
459 :
460 0 : return aResult;
461 : }
462 :
463 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|