1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sw.hxx" 30 31 #include <tools/resid.hxx> 32 #include <doc.hxx> 33 #include <IDocumentUndoRedo.hxx> 34 #include <swundo.hxx> 35 #include <pagedesc.hxx> 36 #include <SwUndoPageDesc.hxx> 37 #include <SwRewriter.hxx> 38 #include <undobj.hxx> 39 #include <comcore.hrc> 40 #include <fmtcntnt.hxx> 41 #include <fmthdft.hxx> 42 43 #ifdef DEBUG 44 #include <ndindex.hxx> 45 #endif 46 47 48 #ifdef DEBUG 49 // Pure debug help function to have a quick look at the header/footer attributes. 50 void DebugHeaderFooterContent( const SwPageDesc& rPageDesc ) 51 { 52 sal_uLong nHeaderMaster = ULONG_MAX; 53 sal_uLong nHeaderLeft = ULONG_MAX; 54 sal_uLong nFooterMaster = ULONG_MAX; 55 sal_uLong nFooterLeft = ULONG_MAX; 56 int nHeaderCount = 0; 57 int nLeftHeaderCount = 0; 58 int nFooterCount = 0; 59 int nLeftFooterCount = 0; 60 bool bSharedHeader = false; 61 bool bSharedFooter = false; 62 63 SwFmtHeader& rHead = (SwFmtHeader&)rPageDesc.GetMaster().GetHeader(); 64 SwFmtFooter& rFoot = (SwFmtFooter&)rPageDesc.GetMaster().GetFooter(); 65 SwFmtHeader& rLeftHead = (SwFmtHeader&)rPageDesc.GetLeft().GetHeader(); 66 SwFmtFooter& rLeftFoot = (SwFmtFooter&)rPageDesc.GetLeft().GetFooter(); 67 if( rHead.IsActive() ) 68 { 69 SwFrmFmt* pHeaderFmt = rHead.GetHeaderFmt(); 70 if( pHeaderFmt ) 71 { 72 nHeaderCount = pHeaderFmt->GetClientCount(); 73 const SwFmtCntnt* pCntnt = &pHeaderFmt->GetCntnt(); 74 if( pCntnt->GetCntntIdx() ) 75 nHeaderMaster = pCntnt->GetCntntIdx()->GetIndex(); 76 else 77 nHeaderMaster = 0; 78 } 79 bSharedHeader = rPageDesc.IsHeaderShared(); 80 SwFrmFmt* pLeftHeaderFmt = rLeftHead.GetHeaderFmt(); 81 if( pLeftHeaderFmt ) 82 { 83 nLeftHeaderCount = pLeftHeaderFmt->GetClientCount(); 84 const SwFmtCntnt* pLeftCntnt = &pLeftHeaderFmt->GetCntnt(); 85 if( pLeftCntnt->GetCntntIdx() ) 86 nHeaderLeft = pLeftCntnt->GetCntntIdx()->GetIndex(); 87 else 88 nHeaderLeft = 0; 89 } 90 } 91 if( rFoot.IsActive() ) 92 { 93 SwFrmFmt* pFooterFmt = rFoot.GetFooterFmt(); 94 if( pFooterFmt ) 95 { 96 nFooterCount = pFooterFmt->GetClientCount(); 97 const SwFmtCntnt* pCntnt = &pFooterFmt->GetCntnt(); 98 if( pCntnt->GetCntntIdx() ) 99 nFooterMaster = pCntnt->GetCntntIdx()->GetIndex(); 100 else 101 nFooterMaster = 0; 102 } 103 bSharedFooter = rPageDesc.IsFooterShared(); 104 SwFrmFmt* pLeftFooterFmt = rLeftFoot.GetFooterFmt(); 105 if( pLeftFooterFmt ) 106 { 107 nLeftFooterCount = pLeftFooterFmt->GetClientCount(); 108 const SwFmtCntnt* pLeftCntnt = &pLeftFooterFmt->GetCntnt(); 109 if( pLeftCntnt->GetCntntIdx() ) 110 nFooterLeft = pLeftCntnt->GetCntntIdx()->GetIndex(); 111 else 112 nFooterLeft = 0; 113 } 114 } 115 int i = 0; 116 ++i; // To set a breakpoint 117 } 118 #endif 119 120 SwUndoPageDesc::SwUndoPageDesc(const SwPageDesc & _aOld, 121 const SwPageDesc & _aNew, 122 SwDoc * _pDoc) 123 : SwUndo( _aOld.GetName() != _aNew.GetName() ? 124 UNDO_RENAME_PAGEDESC : 125 UNDO_CHANGE_PAGEDESC ), 126 aOld(_aOld, _pDoc), aNew(_aNew, _pDoc), pDoc(_pDoc), bExchange( false ) 127 { 128 ASSERT(0 != pDoc, "no document?"); 129 130 #ifdef DEBUG 131 DebugHeaderFooterContent( (SwPageDesc&)aOld ); 132 DebugHeaderFooterContent( (SwPageDesc&)aNew ); 133 #endif 134 135 /* 136 The page description changes. 137 If there are no header/footer content changes like header on/off or change from shared content 138 to unshared etc., there is no reason to duplicate the content nodes (Crash i55547) 139 But this happens, this Undo Ctor will destroy the unnecessary duplicate and manipulate the 140 content pointer of the both page descriptions. 141 */ 142 SwPageDesc &rOldDesc = (SwPageDesc&)aOld; 143 SwPageDesc &rNewDesc = (SwPageDesc&)aNew; 144 const SwFmtHeader& rOldHead = rOldDesc.GetMaster().GetHeader(); 145 const SwFmtHeader& rNewHead = rNewDesc.GetMaster().GetHeader(); 146 const SwFmtFooter& rOldFoot = rOldDesc.GetMaster().GetFooter(); 147 const SwFmtFooter& rNewFoot = rNewDesc.GetMaster().GetFooter(); 148 /* bExchange must not be set, if the old page descriptor will stay active. 149 Two known situations: 150 #i67735#: renaming a page descriptor 151 #i67334#: changing the follow style 152 If header/footer will be activated or deactivated, this undo will not work. 153 */ 154 bExchange = ( aOld.GetName() == aNew.GetName() ) && 155 ( _aOld.GetFollow() == _aNew.GetFollow() ) && 156 ( rOldHead.IsActive() == rNewHead.IsActive() ) && 157 ( rOldFoot.IsActive() == rNewFoot.IsActive() ); 158 if( rOldHead.IsActive() && ( rOldDesc.IsHeaderShared() != rNewDesc.IsHeaderShared() ) ) 159 bExchange = false; 160 if( rOldFoot.IsActive() && ( rOldDesc.IsFooterShared() != rNewDesc.IsFooterShared() ) ) 161 bExchange = false; 162 if( bExchange ) 163 { 164 if( rNewHead.IsActive() ) 165 { 166 SwFrmFmt* pFormat = new SwFrmFmt( *rNewHead.GetHeaderFmt() ); 167 // The Ctor of this object will remove the duplicate! 168 SwFmtHeader aFmtHeader( pFormat ); 169 if( !rNewDesc.IsHeaderShared() ) 170 { 171 pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetHeader().GetHeaderFmt() ); 172 // The Ctor of this object will remove the duplicate! 173 SwFmtHeader aFormatHeader( pFormat ); 174 } 175 } 176 // Same procedure for footers... 177 if( rNewFoot.IsActive() ) 178 { 179 SwFrmFmt* pFormat = new SwFrmFmt( *rNewFoot.GetFooterFmt() ); 180 // The Ctor of this object will remove the duplicate! 181 SwFmtFooter aFmtFooter( pFormat ); 182 if( !rNewDesc.IsFooterShared() ) 183 { 184 pFormat = new SwFrmFmt( *rNewDesc.GetLeft().GetFooter().GetFooterFmt() ); 185 // The Ctor of this object will remove the duplicate! 186 SwFmtFooter aFormatFooter( pFormat ); 187 } 188 } 189 190 // After this exchange method the old page description will point to zero, 191 // the new one will point to the node position of the original content nodes. 192 ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew ); 193 #ifdef DEBUG 194 DebugHeaderFooterContent( (SwPageDesc&)aOld ); 195 DebugHeaderFooterContent( (SwPageDesc&)aNew ); 196 #endif 197 } 198 } 199 200 SwUndoPageDesc::~SwUndoPageDesc() 201 { 202 } 203 204 205 void SwUndoPageDesc::ExchangeContentNodes( SwPageDesc& rSource, SwPageDesc &rDest ) 206 { 207 ASSERT( bExchange, "You shouldn't do that." ); 208 const SwFmtHeader& rDestHead = rDest.GetMaster().GetHeader(); 209 const SwFmtHeader& rSourceHead = rSource.GetMaster().GetHeader(); 210 if( rDestHead.IsActive() ) 211 { 212 // Let the destination page descrition point to the source node position, 213 // from now on this descriptor is responsible for the content nodes! 214 const SfxPoolItem* pItem; 215 rDest.GetMaster().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem ); 216 SfxPoolItem *pNewItem = pItem->Clone(); 217 SwFrmFmt* pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt(); 218 #ifdef DEBUG 219 const SwFmtCntnt& rSourceCntnt = rSourceHead.GetHeaderFmt()->GetCntnt(); 220 (void)rSourceCntnt; 221 const SwFmtCntnt& rDestCntnt = rDestHead.GetHeaderFmt()->GetCntnt(); 222 (void)rDestCntnt; 223 #endif 224 pNewFmt->SetFmtAttr( rSourceHead.GetHeaderFmt()->GetCntnt() ); 225 delete pNewItem; 226 227 // Let the source page description point to zero node position, 228 // it loses the responsible and can be destroyed without removing the content nodes. 229 rSource.GetMaster().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem ); 230 pNewItem = pItem->Clone(); 231 pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt(); 232 pNewFmt->SetFmtAttr( SwFmtCntnt() ); 233 delete pNewItem; 234 235 if( !rDest.IsHeaderShared() ) 236 { 237 // Same procedure for unshared header.. 238 const SwFmtHeader& rSourceLeftHead = rSource.GetLeft().GetHeader(); 239 rDest.GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem ); 240 pNewItem = pItem->Clone(); 241 pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt(); 242 #ifdef DEBUG 243 const SwFmtCntnt& rSourceCntnt1 = rSourceLeftHead.GetHeaderFmt()->GetCntnt(); 244 (void)rSourceCntnt1; 245 const SwFmtCntnt& rDestCntnt1 = rDest.GetLeft().GetHeader().GetHeaderFmt()->GetCntnt(); 246 (void)rDestCntnt1; 247 #endif 248 pNewFmt->SetFmtAttr( rSourceLeftHead.GetHeaderFmt()->GetCntnt() ); 249 delete pNewItem; 250 rSource.GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False, &pItem ); 251 pNewItem = pItem->Clone(); 252 pNewFmt = ((SwFmtHeader*)pNewItem)->GetHeaderFmt(); 253 pNewFmt->SetFmtAttr( SwFmtCntnt() ); 254 delete pNewItem; 255 } 256 } 257 // Same procedure for footers... 258 const SwFmtFooter& rDestFoot = rDest.GetMaster().GetFooter(); 259 const SwFmtFooter& rSourceFoot = rSource.GetMaster().GetFooter(); 260 if( rDestFoot.IsActive() ) 261 { 262 const SfxPoolItem* pItem; 263 rDest.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem ); 264 SfxPoolItem *pNewItem = pItem->Clone(); 265 SwFrmFmt *pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt(); 266 pNewFmt->SetFmtAttr( rSourceFoot.GetFooterFmt()->GetCntnt() ); 267 delete pNewItem; 268 269 #ifdef DEBUG 270 const SwFmtCntnt& rFooterSourceCntnt = rSourceFoot.GetFooterFmt()->GetCntnt(); 271 (void)rFooterSourceCntnt; 272 const SwFmtCntnt& rFooterDestCntnt = rDestFoot.GetFooterFmt()->GetCntnt(); 273 (void)rFooterDestCntnt; 274 #endif 275 rSource.GetMaster().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem ); 276 pNewItem = pItem->Clone(); 277 pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt(); 278 pNewFmt->SetFmtAttr( SwFmtCntnt() ); 279 delete pNewItem; 280 281 if( !rDest.IsFooterShared() ) 282 { 283 const SwFmtFooter& rSourceLeftFoot = rSource.GetLeft().GetFooter(); 284 #ifdef DEBUG 285 const SwFmtCntnt& rFooterSourceCntnt2 = rSourceLeftFoot.GetFooterFmt()->GetCntnt(); 286 const SwFmtCntnt& rFooterDestCntnt2 = 287 rDest.GetLeft().GetFooter().GetFooterFmt()->GetCntnt(); 288 (void)rFooterSourceCntnt2; 289 (void)rFooterDestCntnt2; 290 #endif 291 rDest.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem ); 292 pNewItem = pItem->Clone(); 293 pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt(); 294 pNewFmt->SetFmtAttr( rSourceLeftFoot.GetFooterFmt()->GetCntnt() ); 295 delete pNewItem; 296 rSource.GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False, &pItem ); 297 pNewItem = pItem->Clone(); 298 pNewFmt = ((SwFmtFooter*)pNewItem)->GetFooterFmt(); 299 pNewFmt->SetFmtAttr( SwFmtCntnt() ); 300 delete pNewItem; 301 } 302 } 303 } 304 305 void SwUndoPageDesc::UndoImpl(::sw::UndoRedoContext &) 306 { 307 // Move (header/footer)content node responsibility from new page descriptor to old one again. 308 if( bExchange ) 309 ExchangeContentNodes( (SwPageDesc&)aNew, (SwPageDesc&)aOld ); 310 pDoc->ChgPageDesc(aOld.GetName(), aOld); 311 } 312 313 void SwUndoPageDesc::RedoImpl(::sw::UndoRedoContext &) 314 { 315 // Move (header/footer)content node responsibility from old page descriptor to new one again. 316 if( bExchange ) 317 ExchangeContentNodes( (SwPageDesc&)aOld, (SwPageDesc&)aNew ); 318 pDoc->ChgPageDesc(aNew.GetName(), aNew); 319 } 320 321 SwRewriter SwUndoPageDesc::GetRewriter() const 322 { 323 SwRewriter aResult; 324 325 aResult.AddRule(UNDO_ARG1, aOld.GetName()); 326 aResult.AddRule(UNDO_ARG2, SW_RES(STR_YIELDS)); 327 aResult.AddRule(UNDO_ARG3, aNew.GetName()); 328 329 return aResult; 330 } 331 332 // #116530# 333 SwUndoPageDescCreate::SwUndoPageDescCreate(const SwPageDesc * pNew, 334 SwDoc * _pDoc) 335 : SwUndo(UNDO_CREATE_PAGEDESC), pDesc(pNew), aNew(*pNew, _pDoc), 336 pDoc(_pDoc) 337 { 338 ASSERT(0 != pDoc, "no document?"); 339 } 340 341 SwUndoPageDescCreate::~SwUndoPageDescCreate() 342 { 343 } 344 345 void SwUndoPageDescCreate::UndoImpl(::sw::UndoRedoContext &) 346 { 347 // -> #116530# 348 if (pDesc) 349 { 350 aNew = *pDesc; 351 pDesc = NULL; 352 } 353 // <- #116530# 354 355 pDoc->DelPageDesc(aNew.GetName(), sal_True); 356 } 357 358 void SwUndoPageDescCreate::DoImpl() 359 { 360 SwPageDesc aPageDesc = aNew; 361 pDoc->MakePageDesc(aNew.GetName(), &aPageDesc, sal_False, sal_True); // #116530# 362 } 363 364 void SwUndoPageDescCreate::RedoImpl(::sw::UndoRedoContext &) 365 { 366 DoImpl(); 367 } 368 369 void SwUndoPageDescCreate::RepeatImpl(::sw::RepeatContext &) 370 { 371 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 372 DoImpl(); 373 } 374 375 SwRewriter SwUndoPageDescCreate::GetRewriter() const 376 { 377 SwRewriter aResult; 378 379 if (pDesc) 380 aResult.AddRule(UNDO_ARG1, pDesc->GetName()); 381 else 382 aResult.AddRule(UNDO_ARG1, aNew.GetName()); 383 384 385 return aResult; 386 } 387 388 SwUndoPageDescDelete::SwUndoPageDescDelete(const SwPageDesc & _aOld, 389 SwDoc * _pDoc) 390 : SwUndo(UNDO_DELETE_PAGEDESC), aOld(_aOld, _pDoc), pDoc(_pDoc) 391 { 392 ASSERT(0 != pDoc, "no document?"); 393 } 394 395 SwUndoPageDescDelete::~SwUndoPageDescDelete() 396 { 397 } 398 399 void SwUndoPageDescDelete::UndoImpl(::sw::UndoRedoContext &) 400 { 401 SwPageDesc aPageDesc = aOld; 402 pDoc->MakePageDesc(aOld.GetName(), &aPageDesc, sal_False, sal_True); // #116530# 403 } 404 405 void SwUndoPageDescDelete::DoImpl() 406 { 407 pDoc->DelPageDesc(aOld.GetName(), sal_True); // #116530# 408 } 409 410 void SwUndoPageDescDelete::RedoImpl(::sw::UndoRedoContext &) 411 { 412 DoImpl(); 413 } 414 415 void SwUndoPageDescDelete::RepeatImpl(::sw::RepeatContext &) 416 { 417 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 418 DoImpl(); 419 } 420 421 SwRewriter SwUndoPageDescDelete::GetRewriter() const 422 { 423 SwRewriter aResult; 424 425 aResult.AddRule(UNDO_ARG1, aOld.GetName()); 426 427 return aResult; 428 } 429