1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_sw.hxx" 26 27 #include <UndoSection.hxx> 28 29 #include <sfx2/linkmgr.hxx> 30 #include <fmtcntnt.hxx> 31 #include <doc.hxx> 32 #include <docary.hxx> 33 #include <swundo.hxx> // fuer die UndoIds 34 #include <pam.hxx> 35 #include <ndtxt.hxx> 36 #include <UndoCore.hxx> 37 #include <section.hxx> 38 #include <rolbck.hxx> 39 #include <redline.hxx> 40 #include <doctxm.hxx> 41 #include <ftnidx.hxx> 42 #include <editsh.hxx> 43 /// OD 04.10.2002 #102894# 44 /// class Calc needed for calculation of the hidden condition of a section. 45 #include <calc.hxx> 46 47 48 SfxItemSet* lcl_GetAttrSet( const SwSection& rSect ) 49 { 50 // Attribute des Formate sichern (Spalten, Farbe, ... ) 51 // Cntnt- und Protect- Items interessieren nicht (stehen schon in der 52 // Section), muessen also entfernen werden 53 SfxItemSet* pAttr = 0; 54 if( rSect.GetFmt() ) 55 { 56 sal_uInt16 nCnt = 1; 57 if( rSect.IsProtect() ) 58 ++nCnt; 59 60 if( nCnt < rSect.GetFmt()->GetAttrSet().Count() ) 61 { 62 pAttr = new SfxItemSet( rSect.GetFmt()->GetAttrSet() ); 63 pAttr->ClearItem( RES_PROTECT ); 64 pAttr->ClearItem( RES_CNTNT ); 65 if( !pAttr->Count() ) 66 delete pAttr, pAttr = 0; 67 } 68 } 69 return pAttr; 70 } 71 72 73 //////////////////////////////////////////////////////////////////////////// 74 75 SwUndoInsSection::SwUndoInsSection( 76 SwPaM const& rPam, SwSectionData const& rNewData, 77 SfxItemSet const*const pSet, SwTOXBase const*const pTOXBase) 78 : SwUndo( UNDO_INSSECTION ), SwUndRng( rPam ) 79 , m_pSectionData(new SwSectionData(rNewData)) 80 , m_pTOXBase( (pTOXBase) ? new SwTOXBase(*pTOXBase) : 0 ) 81 , m_pAttrSet( (pSet && pSet->Count()) ? new SfxItemSet( *pSet ) : 0 ) 82 , m_pHistory(0) 83 , m_pRedlData(0) 84 , m_nSectionNodePos(0) 85 , m_bSplitAtStart(false) 86 , m_bSplitAtEnd(false) 87 , m_bUpdateFtn(false) 88 { 89 SwDoc& rDoc = *(SwDoc*)rPam.GetDoc(); 90 if( rDoc.IsRedlineOn() ) 91 { 92 m_pRedlData.reset(new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, 93 rDoc.GetRedlineAuthor() )); 94 SetRedlineMode( rDoc.GetRedlineMode() ); 95 } 96 97 98 if( !rPam.HasMark() ) 99 { 100 const SwCntntNode* pCNd = rPam.GetPoint()->nNode.GetNode().GetCntntNode(); 101 if( pCNd && pCNd->HasSwAttrSet() && ( 102 !rPam.GetPoint()->nContent.GetIndex() || 103 rPam.GetPoint()->nContent.GetIndex() == pCNd->Len() )) 104 { 105 SfxItemSet aBrkSet( rDoc.GetAttrPool(), aBreakSetRange ); 106 aBrkSet.Put( *pCNd->GetpSwAttrSet() ); 107 if( aBrkSet.Count() ) 108 { 109 m_pHistory.reset( new SwHistory ); 110 m_pHistory->CopyFmtAttr( aBrkSet, pCNd->GetIndex() ); 111 } 112 } 113 } 114 } 115 116 SwUndoInsSection::~SwUndoInsSection() 117 { 118 } 119 120 void SwUndoInsSection::UndoImpl(::sw::UndoRedoContext & rContext) 121 { 122 SwDoc & rDoc = rContext.GetDoc(); 123 124 RemoveIdxFromSection( rDoc, m_nSectionNodePos ); 125 126 SwSectionNode *const pNd = 127 rDoc.GetNodes()[ m_nSectionNodePos ]->GetSectionNode(); 128 ASSERT( pNd, "wo ist mein SectionNode?" ); 129 130 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) 131 rDoc.DeleteRedline( *pNd, true, USHRT_MAX ); 132 133 // lag keine Selektion vor ?? 134 SwNodeIndex aIdx( *pNd ); 135 if( ( !nEndNode && STRING_MAXLEN == nEndCntnt ) || 136 ( nSttNode == nEndNode && nSttCntnt == nEndCntnt )) 137 // loesche einfach alle Nodes 138 rDoc.GetNodes().Delete( aIdx, pNd->EndOfSectionIndex() - 139 aIdx.GetIndex() ); 140 else 141 // einfach das Format loeschen, der Rest erfolgt automatisch 142 rDoc.DelSectionFmt( pNd->GetSection().GetFmt() ); 143 144 // muessen wir noch zusammenfassen ? 145 if (m_bSplitAtStart) 146 { 147 Join( rDoc, nSttNode ); 148 } 149 150 if (m_bSplitAtEnd) 151 { 152 Join( rDoc, nEndNode ); 153 } 154 155 if (m_pHistory.get()) 156 { 157 m_pHistory->TmpRollback( &rDoc, 0, false ); 158 } 159 160 if (m_bUpdateFtn) 161 { 162 rDoc.GetFtnIdxs().UpdateFtn( aIdx ); 163 } 164 165 AddUndoRedoPaM(rContext); 166 } 167 168 void SwUndoInsSection::RedoImpl(::sw::UndoRedoContext & rContext) 169 { 170 SwDoc & rDoc = rContext.GetDoc(); 171 SwPaM & rPam( AddUndoRedoPaM(rContext) ); 172 173 const SwTOXBaseSection* pUpdateTOX = 0; 174 if (m_pTOXBase.get()) 175 { 176 pUpdateTOX = rDoc.InsertTableOf( *rPam.GetPoint(), 177 *m_pTOXBase, m_pAttrSet.get(), true); 178 } 179 else 180 { 181 rDoc.InsertSwSection(rPam, *m_pSectionData, 0, m_pAttrSet.get(), true); 182 } 183 184 if (m_pHistory.get()) 185 { 186 m_pHistory->SetTmpEnd( m_pHistory->Count() ); 187 } 188 189 SwSectionNode *const pSectNd = 190 rDoc.GetNodes()[ m_nSectionNodePos ]->GetSectionNode(); 191 if (m_pRedlData.get() && 192 IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode())) 193 { 194 RedlineMode_t eOld = rDoc.GetRedlineMode(); 195 rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE)); 196 197 SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 ); 198 rDoc.AppendRedline( new SwRedline( *m_pRedlData, aPam ), true); 199 rDoc.SetRedlineMode_intern( eOld ); 200 } 201 else if( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) && 202 rDoc.GetRedlineTbl().Count() ) 203 { 204 SwPaM aPam( *pSectNd->EndOfSectionNode(), *pSectNd, 1 ); 205 rDoc.SplitRedline( aPam ); 206 } 207 208 if( pUpdateTOX ) 209 { 210 // Formatierung anstossen 211 SwEditShell* pESh = rDoc.GetEditShell(); 212 if( pESh ) 213 pESh->CalcLayout(); 214 215 // Seitennummern eintragen 216 ((SwTOXBaseSection*)pUpdateTOX)->UpdatePageNum(); 217 } 218 } 219 220 void SwUndoInsSection::RepeatImpl(::sw::RepeatContext & rContext) 221 { 222 SwDoc & rDoc = rContext.GetDoc(); 223 if (m_pTOXBase.get()) 224 { 225 rDoc.InsertTableOf(*rContext.GetRepeatPaM().GetPoint(), 226 *m_pTOXBase, m_pAttrSet.get(), true); 227 } 228 else 229 { 230 rDoc.InsertSwSection(rContext.GetRepeatPaM(), 231 *m_pSectionData, 0, m_pAttrSet.get()); 232 } 233 } 234 235 void SwUndoInsSection::Join( SwDoc& rDoc, sal_uLong nNode ) 236 { 237 SwNodeIndex aIdx( rDoc.GetNodes(), nNode ); 238 SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode(); 239 ASSERT( pTxtNd, "wo ist mein TextNode?" ); 240 241 { 242 RemoveIdxRel( nNode + 1, SwPosition( aIdx, 243 SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ))); 244 } 245 pTxtNd->JoinNext(); 246 247 if (m_pHistory.get()) 248 { 249 SwIndex aCntIdx( pTxtNd, 0 ); 250 pTxtNd->RstAttr( aCntIdx, pTxtNd->Len(), 0, 0, true ); 251 } 252 } 253 254 255 void 256 SwUndoInsSection::SaveSplitNode(SwTxtNode *const pTxtNd, bool const bAtStart) 257 { 258 if( pTxtNd->GetpSwpHints() ) 259 { 260 if (!m_pHistory.get()) 261 { 262 m_pHistory.reset( new SwHistory ); 263 } 264 m_pHistory->CopyAttr( pTxtNd->GetpSwpHints(), pTxtNd->GetIndex(), 0, 265 pTxtNd->GetTxt().Len(), false ); 266 } 267 268 if (bAtStart) 269 { 270 m_bSplitAtStart = true; 271 } 272 else 273 { 274 m_bSplitAtEnd = true; 275 } 276 } 277 278 279 //////////////////////////////////////////////////////////////////////////// 280 281 class SwUndoDelSection 282 : public SwUndo 283 { 284 private: 285 ::std::auto_ptr<SwSectionData> const m_pSectionData; /// section not TOX 286 ::std::auto_ptr<SwTOXBase> const m_pTOXBase; /// set iff section is TOX 287 ::std::auto_ptr<SfxItemSet> const m_pAttrSet; 288 ::boost::shared_ptr< ::sfx2::MetadatableUndo > const m_pMetadataUndo; 289 sal_uLong const m_nStartNode; 290 sal_uLong const m_nEndNode; 291 292 public: 293 SwUndoDelSection( 294 SwSectionFmt const&, SwSection const&, SwNodeIndex const*const); 295 296 virtual ~SwUndoDelSection(); 297 298 virtual void UndoImpl( ::sw::UndoRedoContext & ); 299 virtual void RedoImpl( ::sw::UndoRedoContext & ); 300 }; 301 302 SW_DLLPRIVATE SwUndo * MakeUndoDelSection(SwSectionFmt const& rFormat) 303 { 304 return new SwUndoDelSection(rFormat, *rFormat.GetSection(), 305 rFormat.GetCntnt().GetCntntIdx()); 306 } 307 308 SwUndoDelSection::SwUndoDelSection( 309 SwSectionFmt const& rSectionFmt, SwSection const& rSection, 310 SwNodeIndex const*const pIndex) 311 : SwUndo( UNDO_DELSECTION ) 312 , m_pSectionData( new SwSectionData(rSection) ) 313 , m_pTOXBase( rSection.ISA( SwTOXBaseSection ) 314 ? new SwTOXBase(static_cast<SwTOXBaseSection const&>(rSection)) 315 : 0 ) 316 , m_pAttrSet( ::lcl_GetAttrSet(rSection) ) 317 , m_pMetadataUndo( rSectionFmt.CreateUndo() ) 318 , m_nStartNode( pIndex->GetIndex() ) 319 , m_nEndNode( pIndex->GetNode().EndOfSectionIndex() ) 320 { 321 } 322 323 SwUndoDelSection::~SwUndoDelSection() 324 { 325 } 326 327 void SwUndoDelSection::UndoImpl(::sw::UndoRedoContext & rContext) 328 { 329 SwDoc & rDoc = rContext.GetDoc(); 330 331 if (m_pTOXBase.get()) 332 { 333 rDoc.InsertTableOf(m_nStartNode, m_nEndNode-2, *m_pTOXBase, 334 m_pAttrSet.get()); 335 } 336 else 337 { 338 SwNodeIndex aStt( rDoc.GetNodes(), m_nStartNode ); 339 SwNodeIndex aEnd( rDoc.GetNodes(), m_nEndNode-2 ); 340 SwSectionFmt* pFmt = rDoc.MakeSectionFmt( 0 ); 341 if (m_pAttrSet.get()) 342 { 343 pFmt->SetFmtAttr( *m_pAttrSet ); 344 } 345 346 /// OD 04.10.2002 #102894# 347 /// remember inserted section node for further calculations 348 SwSectionNode* pInsertedSectNd = rDoc.GetNodes().InsertTextSection( 349 aStt, *pFmt, *m_pSectionData, 0, & aEnd); 350 351 if( SFX_ITEM_SET == pFmt->GetItemState( RES_FTN_AT_TXTEND ) || 352 SFX_ITEM_SET == pFmt->GetItemState( RES_END_AT_TXTEND )) 353 { 354 rDoc.GetFtnIdxs().UpdateFtn( aStt ); 355 } 356 357 /// OD 04.10.2002 #102894# 358 /// consider that section is hidden by condition. 359 /// If section is hidden by condition, 360 /// recalculate condition and update hidden condition flag. 361 /// Recalculation is necessary, because fields, on which the hide 362 /// condition depends, can be changed - fields changes aren't undoable. 363 /// NOTE: setting hidden condition flag also creates/deletes corresponding 364 /// frames, if the hidden condition flag changes. 365 SwSection& aInsertedSect = pInsertedSectNd->GetSection(); 366 if ( aInsertedSect.IsHidden() && 367 aInsertedSect.GetCondition().Len() > 0 ) 368 { 369 SwCalc aCalc( rDoc ); 370 rDoc.FldsToCalc(aCalc, pInsertedSectNd->GetIndex(), USHRT_MAX); 371 bool bRecalcCondHidden = 372 aCalc.Calculate( aInsertedSect.GetCondition() ).GetBool() ? true : false; 373 aInsertedSect.SetCondHidden( bRecalcCondHidden ); 374 } 375 376 pFmt->RestoreMetadata(m_pMetadataUndo); 377 } 378 } 379 380 void SwUndoDelSection::RedoImpl(::sw::UndoRedoContext & rContext) 381 { 382 SwDoc & rDoc = rContext.GetDoc(); 383 384 SwSectionNode *const pNd = 385 rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode(); 386 OSL_ENSURE(pNd, "SwUndoDelSection::RedoImpl(): no SectionNode?"); 387 // einfach das Format loeschen, der Rest erfolgt automatisch 388 rDoc.DelSectionFmt( pNd->GetSection().GetFmt() ); 389 } 390 391 392 //////////////////////////////////////////////////////////////////////////// 393 394 class SwUndoUpdateSection 395 : public SwUndo 396 { 397 private: 398 ::std::auto_ptr<SwSectionData> m_pSectionData; 399 ::std::auto_ptr<SfxItemSet> m_pAttrSet; 400 sal_uLong const m_nStartNode; 401 bool const m_bOnlyAttrChanged; 402 403 public: 404 SwUndoUpdateSection( 405 SwSection const&, SwNodeIndex const*const, bool const bOnlyAttr); 406 407 virtual ~SwUndoUpdateSection(); 408 409 virtual void UndoImpl( ::sw::UndoRedoContext & ); 410 virtual void RedoImpl( ::sw::UndoRedoContext & ); 411 }; 412 413 SW_DLLPRIVATE SwUndo * 414 MakeUndoUpdateSection(SwSectionFmt const& rFormat, bool const bOnlyAttr) 415 { 416 return new SwUndoUpdateSection(*rFormat.GetSection(), 417 rFormat.GetCntnt().GetCntntIdx(), bOnlyAttr); 418 } 419 420 SwUndoUpdateSection::SwUndoUpdateSection( 421 SwSection const& rSection, SwNodeIndex const*const pIndex, 422 bool const bOnlyAttr) 423 : SwUndo( UNDO_CHGSECTION ) 424 , m_pSectionData( new SwSectionData(rSection) ) 425 , m_pAttrSet( ::lcl_GetAttrSet(rSection) ) 426 , m_nStartNode( pIndex->GetIndex() ) 427 , m_bOnlyAttrChanged( bOnlyAttr ) 428 { 429 } 430 431 SwUndoUpdateSection::~SwUndoUpdateSection() 432 { 433 } 434 435 void SwUndoUpdateSection::UndoImpl(::sw::UndoRedoContext & rContext) 436 { 437 SwDoc & rDoc = rContext.GetDoc(); 438 SwSectionNode *const pSectNd = 439 rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode(); 440 ASSERT( pSectNd, "wo ist mein SectionNode?" ); 441 442 SwSection& rNdSect = pSectNd->GetSection(); 443 SwFmt* pFmt = rNdSect.GetFmt(); 444 445 SfxItemSet* pCur = ::lcl_GetAttrSet( rNdSect ); 446 if (m_pAttrSet.get()) 447 { 448 // das Content- und Protect-Item muss bestehen bleiben 449 const SfxPoolItem* pItem; 450 m_pAttrSet->Put( pFmt->GetFmtAttr( RES_CNTNT )); 451 if( SFX_ITEM_SET == pFmt->GetItemState( RES_PROTECT, sal_True, &pItem )) 452 { 453 m_pAttrSet->Put( *pItem ); 454 } 455 pFmt->DelDiffs( *m_pAttrSet ); 456 m_pAttrSet->ClearItem( RES_CNTNT ); 457 pFmt->SetFmtAttr( *m_pAttrSet ); 458 } 459 else 460 { 461 // dann muessen die alten entfernt werden 462 pFmt->ResetFmtAttr( RES_FRMATR_BEGIN, RES_BREAK ); 463 pFmt->ResetFmtAttr( RES_HEADER, RES_OPAQUE ); 464 pFmt->ResetFmtAttr( RES_SURROUND, RES_FRMATR_END-1 ); 465 } 466 m_pAttrSet.reset(pCur); 467 468 if (!m_bOnlyAttrChanged) 469 { 470 const bool bUpdate = 471 (!rNdSect.IsLinkType() && m_pSectionData->IsLinkType()) 472 || ( m_pSectionData->GetLinkFileName().Len() 473 && (m_pSectionData->GetLinkFileName() != 474 rNdSect.GetLinkFileName())); 475 476 // swap stored section data with live section data 477 SwSectionData *const pOld( new SwSectionData(rNdSect) ); 478 rNdSect.SetSectionData(*m_pSectionData); 479 m_pSectionData.reset(pOld); 480 481 if( bUpdate ) 482 rNdSect.CreateLink( CREATE_UPDATE ); 483 else if( CONTENT_SECTION == rNdSect.GetType() && rNdSect.IsConnected() ) 484 { 485 rNdSect.Disconnect(); 486 rDoc.GetLinkManager().Remove( &rNdSect.GetBaseLink() ); 487 } 488 } 489 } 490 491 void SwUndoUpdateSection::RedoImpl(::sw::UndoRedoContext & rContext) 492 { 493 UndoImpl(rContext); 494 } 495 496