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 : SwFormatHeader& rHead = (SwFormatHeader&)rPageDesc.GetMaster().GetHeader();
46 : SwFormatFooter& rFoot = (SwFormatFooter&)rPageDesc.GetMaster().GetFooter();
47 : SwFormatHeader& rLeftHead = (SwFormatHeader&)rPageDesc.GetLeft().GetHeader();
48 : SwFormatFooter& rLeftFoot = (SwFormatFooter&)rPageDesc.GetLeft().GetFooter();
49 : if( rHead.IsActive() )
50 : {
51 : SwFrameFormat* pHeaderFormat = rHead.GetHeaderFormat();
52 : if( pHeaderFormat )
53 : {
54 : const SwFormatContent* pContent = &pHeaderFormat->GetContent();
55 : if( pContent->GetContentIdx() )
56 : nHeaderMaster = pContent->GetContentIdx()->GetIndex();
57 : else
58 : nHeaderMaster = 0;
59 : }
60 : SwFrameFormat* pLeftHeaderFormat = rLeftHead.GetHeaderFormat();
61 : if( pLeftHeaderFormat )
62 : {
63 : const SwFormatContent* pLeftContent = &pLeftHeaderFormat->GetContent();
64 : if( pLeftContent->GetContentIdx() )
65 : nHeaderLeft = pLeftContent->GetContentIdx()->GetIndex();
66 : else
67 : nHeaderLeft = 0;
68 : }
69 : }
70 : if( rFoot.IsActive() )
71 : {
72 : SwFrameFormat* pFooterFormat = rFoot.GetFooterFormat();
73 : if( pFooterFormat )
74 : {
75 : const SwFormatContent* pContent = &pFooterFormat->GetContent();
76 : if( pContent->GetContentIdx() )
77 : nFooterMaster = pContent->GetContentIdx()->GetIndex();
78 : else
79 : nFooterMaster = 0;
80 : }
81 : SwFrameFormat* pLeftFooterFormat = rLeftFoot.GetFooterFormat();
82 : if( pLeftFooterFormat )
83 : {
84 : const SwFormatContent* pLeftContent = &pLeftFooterFormat->GetContent();
85 : if( pLeftContent->GetContentIdx() )
86 : nFooterLeft = pLeftContent->GetContentIdx()->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 117 : SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc & _aOld,
100 : const SwPageDesc & _aNew,
101 : SwDoc * _pDoc)
102 234 : : SwUndo( _aOld.GetName() != _aNew.GetName() ?
103 : UNDO_RENAME_PAGEDESC :
104 : UNDO_CHANGE_PAGEDESC ),
105 234 : 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( aOld.m_PageDesc );
111 : DebugHeaderFooterContent( aNew.m_PageDesc );
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 117 : SwPageDesc &rOldDesc = aOld.m_PageDesc;
122 117 : SwPageDesc &rNewDesc = aNew.m_PageDesc;
123 117 : const SwFormatHeader& rOldHead = rOldDesc.GetMaster().GetHeader();
124 117 : const SwFormatHeader& rNewHead = rNewDesc.GetMaster().GetHeader();
125 117 : const SwFormatFooter& rOldFoot = rOldDesc.GetMaster().GetFooter();
126 117 : const SwFormatFooter& 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 700 : bExchange = ( aOld.GetName() == aNew.GetName() ) &&
134 229 : ( _aOld.GetFollow() == _aNew.GetFollow() ) &&
135 696 : ( rOldHead.IsActive() == rNewHead.IsActive() ) &&
136 231 : ( rOldFoot.IsActive() == rNewFoot.IsActive() );
137 117 : if( rOldHead.IsActive() && ( rOldDesc.IsHeaderShared() != rNewDesc.IsHeaderShared() ) )
138 0 : bExchange = false;
139 117 : if( rOldFoot.IsActive() && ( rOldDesc.IsFooterShared() != rNewDesc.IsFooterShared() ) )
140 0 : bExchange = false;
141 117 : if( ( rOldHead.IsActive() || rOldFoot.IsActive() ) && ( rOldDesc.IsFirstShared() != rNewDesc.IsFirstShared() ) )
142 0 : bExchange = false;
143 117 : if( bExchange )
144 : {
145 114 : if( rNewHead.IsActive() )
146 : {
147 0 : SwFrameFormat* pFormat = new SwFrameFormat( *rNewHead.GetHeaderFormat() );
148 : // The Ctor of this object will remove the duplicate!
149 0 : SwFormatHeader aFormatHeader(pFormat);
150 0 : if (!rNewDesc.IsHeaderShared())
151 : {
152 0 : pFormat = new SwFrameFormat( *rNewDesc.GetLeft().GetHeader().GetHeaderFormat() );
153 : // The Ctor of this object will remove the duplicate!
154 0 : SwFormatHeader aLeftHeader(pFormat);
155 : }
156 0 : if (!rNewDesc.IsFirstShared())
157 : {
158 0 : pFormat = new SwFrameFormat( *rNewDesc.GetFirstMaster().GetHeader().GetHeaderFormat() );
159 : // The Ctor of this object will remove the duplicate!
160 0 : SwFormatHeader aFirstHeader(pFormat);
161 0 : }
162 : }
163 : // Same procedure for footers...
164 114 : if( rNewFoot.IsActive() )
165 : {
166 0 : SwFrameFormat* pFormat = new SwFrameFormat( *rNewFoot.GetFooterFormat() );
167 : // The Ctor of this object will remove the duplicate!
168 0 : SwFormatFooter aFormatFooter(pFormat);
169 0 : if (!rNewDesc.IsFooterShared())
170 : {
171 0 : pFormat = new SwFrameFormat( *rNewDesc.GetLeft().GetFooter().GetFooterFormat() );
172 : // The Ctor of this object will remove the duplicate!
173 0 : SwFormatFooter aLeftFooter(pFormat);
174 : }
175 0 : if (!rNewDesc.IsFirstShared())
176 : {
177 0 : pFormat = new SwFrameFormat( *rNewDesc.GetFirstMaster().GetFooter().GetFooterFormat() );
178 : // The Ctor of this object will remove the duplicate!
179 0 : SwFormatFooter aFirstFooter(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 114 : ExchangeContentNodes( aOld.m_PageDesc, aNew.m_PageDesc );
186 : #if OSL_DEBUG_LEVEL > 1
187 : DebugHeaderFooterContent( aOld.m_PageDesc );
188 : DebugHeaderFooterContent( aNew.m_PageDesc );
189 : #endif
190 : }
191 117 : }
192 :
193 234 : SwUndoPageDesc::~SwUndoPageDesc()
194 : {
195 234 : }
196 :
197 114 : void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc& rSource, SwPageDesc &rDest )
198 : {
199 : OSL_ENSURE( bExchange, "You shouldn't do that." );
200 114 : const SwFormatHeader& rDestHead = rDest.GetMaster().GetHeader();
201 114 : const SwFormatHeader& rSourceHead = rSource.GetMaster().GetHeader();
202 114 : if( rDestHead.IsActive() )
203 : {
204 : // Let the destination page description 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 : SwFrameFormat* pNewFormat = static_cast<SwFormatHeader*>(pNewItem)->GetHeaderFormat();
210 : #if OSL_DEBUG_LEVEL > 1
211 : const SwFormatContent& rSourceContent = rSourceHead.GetHeaderFormat()->GetContent();
212 : (void)rSourceContent;
213 : const SwFormatContent& rDestContent = rDestHead.GetHeaderFormat()->GetContent();
214 : (void)rDestContent;
215 : #endif
216 0 : pNewFormat->SetFormatAttr( rSourceHead.GetHeaderFormat()->GetContent() );
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 : pNewFormat = static_cast<SwFormatHeader*>(pNewItem)->GetHeaderFormat();
224 0 : pNewFormat->SetFormatAttr( SwFormatContent() );
225 0 : delete pNewItem;
226 :
227 0 : if( !rDest.IsHeaderShared() )
228 : {
229 : // Same procedure for unshared header..
230 0 : const SwFormatHeader& rSourceLeftHead = rSource.GetLeft().GetHeader();
231 0 : rDest.GetLeft().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
232 0 : pNewItem = pItem->Clone();
233 0 : pNewFormat = static_cast<SwFormatHeader*>(pNewItem)->GetHeaderFormat();
234 : #if OSL_DEBUG_LEVEL > 1
235 : const SwFormatContent& rSourceContent1 = rSourceLeftHead.GetHeaderFormat()->GetContent();
236 : (void)rSourceContent1;
237 : const SwFormatContent& rDestContent1 = rDest.GetLeft().GetHeader().GetHeaderFormat()->GetContent();
238 : (void)rDestContent1;
239 : #endif
240 0 : pNewFormat->SetFormatAttr( rSourceLeftHead.GetHeaderFormat()->GetContent() );
241 0 : delete pNewItem;
242 0 : rSource.GetLeft().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
243 0 : pNewItem = pItem->Clone();
244 0 : pNewFormat = static_cast<SwFormatHeader*>(pNewItem)->GetHeaderFormat();
245 0 : pNewFormat->SetFormatAttr( SwFormatContent() );
246 0 : delete pNewItem;
247 : }
248 0 : if (!rDest.IsFirstShared())
249 : {
250 : // Same procedure for unshared header..
251 0 : const SwFormatHeader& rSourceFirstMasterHead = rSource.GetFirstMaster().GetHeader();
252 0 : rDest.GetFirstMaster().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
253 0 : pNewItem = pItem->Clone();
254 0 : pNewFormat = static_cast<SwFormatHeader*>(pNewItem)->GetHeaderFormat();
255 : #if OSL_DEBUG_LEVEL > 1
256 : const SwFormatContent& rSourceContent1 = rSourceFirstMasterHead.GetHeaderFormat()->GetContent();
257 : (void)rSourceContent1;
258 : const SwFormatContent& rDestContent1 = rDest.GetFirstMaster().GetHeader().GetHeaderFormat()->GetContent();
259 : (void)rDestContent1;
260 : #endif
261 0 : pNewFormat->SetFormatAttr( rSourceFirstMasterHead.GetHeaderFormat()->GetContent() );
262 0 : delete pNewItem;
263 0 : rSource.GetFirstMaster().GetAttrSet().GetItemState( RES_HEADER, false, &pItem );
264 0 : pNewItem = pItem->Clone();
265 0 : pNewFormat = static_cast<SwFormatHeader*>(pNewItem)->GetHeaderFormat();
266 0 : pNewFormat->SetFormatAttr( SwFormatContent() );
267 0 : delete pNewItem;
268 : }
269 : }
270 : // Same procedure for footers...
271 114 : const SwFormatFooter& rDestFoot = rDest.GetMaster().GetFooter();
272 114 : const SwFormatFooter& rSourceFoot = rSource.GetMaster().GetFooter();
273 114 : 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 : SwFrameFormat *pNewFormat = static_cast<SwFormatFooter*>(pNewItem)->GetFooterFormat();
279 0 : pNewFormat->SetFormatAttr( rSourceFoot.GetFooterFormat()->GetContent() );
280 0 : delete pNewItem;
281 :
282 : #if OSL_DEBUG_LEVEL > 1
283 : const SwFormatContent& rFooterSourceContent = rSourceFoot.GetFooterFormat()->GetContent();
284 : (void)rFooterSourceContent;
285 : const SwFormatContent& rFooterDestContent = rDestFoot.GetFooterFormat()->GetContent();
286 : (void)rFooterDestContent;
287 : #endif
288 0 : rSource.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
289 0 : pNewItem = pItem->Clone();
290 0 : pNewFormat = static_cast<SwFormatFooter*>(pNewItem)->GetFooterFormat();
291 0 : pNewFormat->SetFormatAttr( SwFormatContent() );
292 0 : delete pNewItem;
293 :
294 0 : if( !rDest.IsFooterShared() )
295 : {
296 0 : const SwFormatFooter& rSourceLeftFoot = rSource.GetLeft().GetFooter();
297 : #if OSL_DEBUG_LEVEL > 1
298 : const SwFormatContent& rFooterSourceContent2 = rSourceLeftFoot.GetFooterFormat()->GetContent();
299 : const SwFormatContent& rFooterDestContent2 =
300 : rDest.GetLeft().GetFooter().GetFooterFormat()->GetContent();
301 : (void)rFooterSourceContent2;
302 : (void)rFooterDestContent2;
303 : #endif
304 0 : rDest.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
305 0 : pNewItem = pItem->Clone();
306 0 : pNewFormat = static_cast<SwFormatFooter*>(pNewItem)->GetFooterFormat();
307 0 : pNewFormat->SetFormatAttr( rSourceLeftFoot.GetFooterFormat()->GetContent() );
308 0 : delete pNewItem;
309 0 : rSource.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
310 0 : pNewItem = pItem->Clone();
311 0 : pNewFormat = static_cast<SwFormatFooter*>(pNewItem)->GetFooterFormat();
312 0 : pNewFormat->SetFormatAttr( SwFormatContent() );
313 0 : delete pNewItem;
314 : }
315 0 : if (!rDest.IsFirstShared())
316 : {
317 0 : const SwFormatFooter& rSourceFirstMasterFoot = rSource.GetFirstMaster().GetFooter();
318 : #if OSL_DEBUG_LEVEL > 1
319 : const SwFormatContent& rFooterSourceContent2 = rSourceFirstMasterFoot.GetFooterFormat()->GetContent();
320 : const SwFormatContent& rFooterDestContent2 =
321 : rDest.GetFirstMaster().GetFooter().GetFooterFormat()->GetContent();
322 : (void)rFooterSourceContent2;
323 : (void)rFooterDestContent2;
324 : #endif
325 0 : rDest.GetFirstMaster().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
326 0 : pNewItem = pItem->Clone();
327 0 : pNewFormat = static_cast<SwFormatFooter*>(pNewItem)->GetFooterFormat();
328 0 : pNewFormat->SetFormatAttr( rSourceFirstMasterFoot.GetFooterFormat()->GetContent() );
329 0 : delete pNewItem;
330 0 : rSource.GetFirstMaster().GetAttrSet().GetItemState( RES_FOOTER, false, &pItem );
331 0 : pNewItem = pItem->Clone();
332 0 : pNewFormat = static_cast<SwFormatFooter*>(pNewItem)->GetFooterFormat();
333 0 : pNewFormat->SetFormatAttr( SwFormatContent() );
334 0 : delete pNewItem;
335 : }
336 : }
337 114 : }
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( aNew.m_PageDesc, aOld.m_PageDesc );
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( aOld.m_PageDesc, aNew.m_PageDesc );
352 0 : pDoc->ChgPageDesc(aNew.GetName(), aNew);
353 0 : }
354 :
355 117 : SwRewriter SwUndoPageDesc::GetRewriter() const
356 : {
357 117 : SwRewriter aResult;
358 :
359 117 : aResult.AddRule(UndoArg1, aOld.GetName());
360 117 : aResult.AddRule(UndoArg2, SW_RESSTR(STR_YIELDS));
361 117 : aResult.AddRule(UndoArg3, aNew.GetName());
362 :
363 117 : return aResult;
364 : }
365 :
366 : // #116530#
367 115 : SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc * pNew,
368 : SwDoc * _pDoc)
369 : : SwUndo(UNDO_CREATE_PAGEDESC), pDesc(pNew), aNew(*pNew, _pDoc),
370 115 : pDoc(_pDoc)
371 : {
372 : OSL_ENSURE(0 != pDoc, "no document?");
373 115 : }
374 :
375 230 : SwUndoPageDescCreate::~SwUndoPageDescCreate()
376 : {
377 230 : }
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 115 : SwRewriter SwUndoPageDescCreate::GetRewriter() const
410 : {
411 115 : SwRewriter aResult;
412 :
413 115 : if (pDesc)
414 115 : aResult.AddRule(UndoArg1, pDesc->GetName());
415 : else
416 0 : aResult.AddRule(UndoArg1, aNew.GetName());
417 :
418 115 : 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 177 : }
462 :
463 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|