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( 243 nNode + 1, 244 SwPosition( aIdx, SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) ); 245 } 246 pTxtNd->JoinNext(); 247 248 if (m_pHistory.get()) 249 { 250 SwIndex aCntIdx( pTxtNd, 0 ); 251 pTxtNd->RstTxtAttr( aCntIdx, pTxtNd->Len(), 0, 0, true ); 252 } 253 } 254 255 256 void 257 SwUndoInsSection::SaveSplitNode(SwTxtNode *const pTxtNd, bool const bAtStart) 258 { 259 if( pTxtNd->GetpSwpHints() ) 260 { 261 if (!m_pHistory.get()) 262 { 263 m_pHistory.reset( new SwHistory ); 264 } 265 m_pHistory->CopyAttr( pTxtNd->GetpSwpHints(), pTxtNd->GetIndex(), 0, 266 pTxtNd->GetTxt().Len(), false ); 267 } 268 269 if (bAtStart) 270 { 271 m_bSplitAtStart = true; 272 } 273 else 274 { 275 m_bSplitAtEnd = true; 276 } 277 } 278 279 280 //////////////////////////////////////////////////////////////////////////// 281 282 class SwUndoDelSection 283 : public SwUndo 284 { 285 private: 286 ::std::auto_ptr<SwSectionData> const m_pSectionData; /// section not TOX 287 ::std::auto_ptr<SwTOXBase> const m_pTOXBase; /// set iff section is TOX 288 ::std::auto_ptr<SfxItemSet> const m_pAttrSet; 289 ::boost::shared_ptr< ::sfx2::MetadatableUndo > const m_pMetadataUndo; 290 sal_uLong const m_nStartNode; 291 sal_uLong const m_nEndNode; 292 293 public: 294 SwUndoDelSection( 295 SwSectionFmt const&, SwSection const&, SwNodeIndex const*const); 296 297 virtual ~SwUndoDelSection(); 298 299 virtual void UndoImpl( ::sw::UndoRedoContext & ); 300 virtual void RedoImpl( ::sw::UndoRedoContext & ); 301 }; 302 303 SW_DLLPRIVATE SwUndo * MakeUndoDelSection(SwSectionFmt const& rFormat) 304 { 305 return new SwUndoDelSection(rFormat, *rFormat.GetSection(), 306 rFormat.GetCntnt().GetCntntIdx()); 307 } 308 309 SwUndoDelSection::SwUndoDelSection( 310 SwSectionFmt const& rSectionFmt, SwSection const& rSection, 311 SwNodeIndex const*const pIndex) 312 : SwUndo( UNDO_DELSECTION ) 313 , m_pSectionData( new SwSectionData(rSection) ) 314 , m_pTOXBase( rSection.ISA( SwTOXBaseSection ) 315 ? new SwTOXBase(static_cast<SwTOXBaseSection const&>(rSection)) 316 : 0 ) 317 , m_pAttrSet( ::lcl_GetAttrSet(rSection) ) 318 , m_pMetadataUndo( rSectionFmt.CreateUndo() ) 319 , m_nStartNode( pIndex->GetIndex() ) 320 , m_nEndNode( pIndex->GetNode().EndOfSectionIndex() ) 321 { 322 } 323 324 SwUndoDelSection::~SwUndoDelSection() 325 { 326 } 327 328 void SwUndoDelSection::UndoImpl(::sw::UndoRedoContext & rContext) 329 { 330 SwDoc & rDoc = rContext.GetDoc(); 331 332 if (m_pTOXBase.get()) 333 { 334 rDoc.InsertTableOf(m_nStartNode, m_nEndNode-2, *m_pTOXBase, 335 m_pAttrSet.get()); 336 } 337 else 338 { 339 SwNodeIndex aStt( rDoc.GetNodes(), m_nStartNode ); 340 SwNodeIndex aEnd( rDoc.GetNodes(), m_nEndNode-2 ); 341 SwSectionFmt* pFmt = rDoc.MakeSectionFmt( 0 ); 342 if (m_pAttrSet.get()) 343 { 344 pFmt->SetFmtAttr( *m_pAttrSet ); 345 } 346 347 /// OD 04.10.2002 #102894# 348 /// remember inserted section node for further calculations 349 SwSectionNode* pInsertedSectNd = rDoc.GetNodes().InsertTextSection( 350 aStt, *pFmt, *m_pSectionData, 0, & aEnd); 351 352 if( SFX_ITEM_SET == pFmt->GetItemState( RES_FTN_AT_TXTEND ) || 353 SFX_ITEM_SET == pFmt->GetItemState( RES_END_AT_TXTEND )) 354 { 355 rDoc.GetFtnIdxs().UpdateFtn( aStt ); 356 } 357 358 /// OD 04.10.2002 #102894# 359 /// consider that section is hidden by condition. 360 /// If section is hidden by condition, 361 /// recalculate condition and update hidden condition flag. 362 /// Recalculation is necessary, because fields, on which the hide 363 /// condition depends, can be changed - fields changes aren't undoable. 364 /// NOTE: setting hidden condition flag also creates/deletes corresponding 365 /// frames, if the hidden condition flag changes. 366 SwSection& aInsertedSect = pInsertedSectNd->GetSection(); 367 if ( aInsertedSect.IsHidden() && 368 aInsertedSect.GetCondition().Len() > 0 ) 369 { 370 SwCalc aCalc( rDoc ); 371 rDoc.FldsToCalc(aCalc, pInsertedSectNd->GetIndex(), USHRT_MAX); 372 bool bRecalcCondHidden = 373 aCalc.Calculate( aInsertedSect.GetCondition() ).GetBool() ? true : false; 374 aInsertedSect.SetCondHidden( bRecalcCondHidden ); 375 } 376 377 pFmt->RestoreMetadata(m_pMetadataUndo); 378 } 379 } 380 381 void SwUndoDelSection::RedoImpl(::sw::UndoRedoContext & rContext) 382 { 383 SwDoc & rDoc = rContext.GetDoc(); 384 385 SwSectionNode *const pNd = 386 rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode(); 387 OSL_ENSURE(pNd, "SwUndoDelSection::RedoImpl(): no SectionNode?"); 388 // einfach das Format loeschen, der Rest erfolgt automatisch 389 rDoc.DelSectionFmt( pNd->GetSection().GetFmt() ); 390 } 391 392 393 //////////////////////////////////////////////////////////////////////////// 394 395 class SwUndoUpdateSection 396 : public SwUndo 397 { 398 private: 399 ::std::auto_ptr<SwSectionData> m_pSectionData; 400 ::std::auto_ptr<SfxItemSet> m_pAttrSet; 401 sal_uLong const m_nStartNode; 402 bool const m_bOnlyAttrChanged; 403 404 public: 405 SwUndoUpdateSection( 406 SwSection const&, SwNodeIndex const*const, bool const bOnlyAttr); 407 408 virtual ~SwUndoUpdateSection(); 409 410 virtual void UndoImpl( ::sw::UndoRedoContext & ); 411 virtual void RedoImpl( ::sw::UndoRedoContext & ); 412 }; 413 414 SW_DLLPRIVATE SwUndo * 415 MakeUndoUpdateSection(SwSectionFmt const& rFormat, bool const bOnlyAttr) 416 { 417 return new SwUndoUpdateSection(*rFormat.GetSection(), 418 rFormat.GetCntnt().GetCntntIdx(), bOnlyAttr); 419 } 420 421 SwUndoUpdateSection::SwUndoUpdateSection( 422 SwSection const& rSection, SwNodeIndex const*const pIndex, 423 bool const bOnlyAttr) 424 : SwUndo( UNDO_CHGSECTION ) 425 , m_pSectionData( new SwSectionData(rSection) ) 426 , m_pAttrSet( ::lcl_GetAttrSet(rSection) ) 427 , m_nStartNode( pIndex->GetIndex() ) 428 , m_bOnlyAttrChanged( bOnlyAttr ) 429 { 430 } 431 432 SwUndoUpdateSection::~SwUndoUpdateSection() 433 { 434 } 435 436 void SwUndoUpdateSection::UndoImpl(::sw::UndoRedoContext & rContext) 437 { 438 SwDoc & rDoc = rContext.GetDoc(); 439 SwSectionNode *const pSectNd = 440 rDoc.GetNodes()[ m_nStartNode ]->GetSectionNode(); 441 ASSERT( pSectNd, "wo ist mein SectionNode?" ); 442 443 SwSection& rNdSect = pSectNd->GetSection(); 444 SwFmt* pFmt = rNdSect.GetFmt(); 445 446 SfxItemSet* pCur = ::lcl_GetAttrSet( rNdSect ); 447 if (m_pAttrSet.get()) 448 { 449 // das Content- und Protect-Item muss bestehen bleiben 450 const SfxPoolItem* pItem; 451 m_pAttrSet->Put( pFmt->GetFmtAttr( RES_CNTNT )); 452 if( SFX_ITEM_SET == pFmt->GetItemState( RES_PROTECT, sal_True, &pItem )) 453 { 454 m_pAttrSet->Put( *pItem ); 455 } 456 pFmt->DelDiffs( *m_pAttrSet ); 457 m_pAttrSet->ClearItem( RES_CNTNT ); 458 pFmt->SetFmtAttr( *m_pAttrSet ); 459 } 460 else 461 { 462 // dann muessen die alten entfernt werden 463 pFmt->ResetFmtAttr( RES_FRMATR_BEGIN, RES_BREAK ); 464 pFmt->ResetFmtAttr( RES_HEADER, RES_OPAQUE ); 465 pFmt->ResetFmtAttr( RES_SURROUND, RES_FRMATR_END-1 ); 466 } 467 m_pAttrSet.reset(pCur); 468 469 if (!m_bOnlyAttrChanged) 470 { 471 const bool bUpdate = 472 (!rNdSect.IsLinkType() && m_pSectionData->IsLinkType()) 473 || ( m_pSectionData->GetLinkFileName().Len() 474 && (m_pSectionData->GetLinkFileName() != 475 rNdSect.GetLinkFileName())); 476 477 // swap stored section data with live section data 478 SwSectionData *const pOld( new SwSectionData(rNdSect) ); 479 rNdSect.SetSectionData(*m_pSectionData); 480 m_pSectionData.reset(pOld); 481 482 if( bUpdate ) 483 rNdSect.CreateLink( CREATE_UPDATE ); 484 else if( CONTENT_SECTION == rNdSect.GetType() && rNdSect.IsConnected() ) 485 { 486 rNdSect.Disconnect(); 487 rDoc.GetLinkManager().Remove( &rNdSect.GetBaseLink() ); 488 } 489 } 490 } 491 492 void SwUndoUpdateSection::RedoImpl(::sw::UndoRedoContext & rContext) 493 { 494 UndoImpl(rContext); 495 } 496 497