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 <UndoTable.hxx> 28 29 #include <UndoRedline.hxx> 30 #include <UndoDelete.hxx> 31 #include <UndoSplitMove.hxx> 32 #include <UndoCore.hxx> 33 #include <hintids.hxx> 34 #include <hints.hxx> 35 #include <editeng/brkitem.hxx> 36 #include <fmtornt.hxx> 37 #include <fmtpdsc.hxx> 38 #include <doc.hxx> 39 #include <IDocumentUndoRedo.hxx> 40 #include <editsh.hxx> 41 #include <docary.hxx> 42 #include <ndtxt.hxx> 43 #include <swtable.hxx> 44 #include <pam.hxx> 45 #include <cntfrm.hxx> 46 #include <tblsel.hxx> 47 #include <swundo.hxx> // fuer die UndoIds 48 #include <rolbck.hxx> 49 #include <ddefld.hxx> 50 #include <tabcol.hxx> 51 #include <tabfrm.hxx> 52 #include <rowfrm.hxx> 53 #include <cellfrm.hxx> 54 #include <swcache.hxx> 55 #include <tblafmt.hxx> 56 #include <poolfmt.hxx> 57 #include <mvsave.hxx> 58 #include <cellatr.hxx> 59 #include <swtblfmt.hxx> 60 #include <swddetbl.hxx> 61 #include <redline.hxx> 62 #include <node2lay.hxx> 63 #include <tblrwcl.hxx> 64 #include <fmtanchr.hxx> 65 #include <comcore.hrc> 66 #include <unochart.hxx> 67 #include <switerator.hxx> 68 69 #ifndef DBG_UTIL 70 #define CHECK_TABLE(t) 71 #else 72 #ifdef DEBUG 73 #define CHECK_TABLE(t) (t).CheckConsistency(); 74 #else 75 #define CHECK_TABLE(t) 76 #endif 77 #endif 78 79 #ifndef DBG_UTIL 80 #define _DEBUG_REDLINE( pDoc ) 81 #else 82 void lcl_DebugRedline( const SwDoc* pDoc ); 83 #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc ); 84 #endif 85 86 extern void ClearFEShellTabCols(); 87 88 typedef SfxItemSet* SfxItemSetPtr; 89 SV_DECL_PTRARR_DEL( SfxItemSets, SfxItemSetPtr, 10, 5 ) 90 91 typedef SwUndoSaveSection* SwUndoSaveSectionPtr; 92 SV_DECL_PTRARR_DEL( SwUndoSaveSections, SwUndoSaveSectionPtr, 0, 10 ) 93 94 typedef SwUndoMove* SwUndoMovePtr; 95 SV_DECL_PTRARR_DEL( SwUndoMoves, SwUndoMovePtr, 0, 10 ) 96 97 struct SwTblToTxtSave; 98 typedef SwTblToTxtSave* SwTblToTxtSavePtr; 99 SV_DECL_PTRARR_DEL( SwTblToTxtSaves, SwTblToTxtSavePtr, 0, 10 ) 100 101 struct _UndoTblCpyTbl_Entry 102 { 103 sal_uLong nBoxIdx, nOffset; 104 SfxItemSet* pBoxNumAttr; 105 SwUndo* pUndo; 106 107 // Was the last paragraph of the new and the first paragraph of the old content joined? 108 bool bJoin; // For redlining only 109 110 _UndoTblCpyTbl_Entry( const SwTableBox& rBox ); 111 ~_UndoTblCpyTbl_Entry(); 112 }; 113 typedef _UndoTblCpyTbl_Entry* _UndoTblCpyTbl_EntryPtr; 114 SV_DECL_PTRARR_DEL( _UndoTblCpyTbl_Entries, _UndoTblCpyTbl_EntryPtr, 0, 10 ) 115 116 class _SaveBox; 117 class _SaveLine; 118 119 class _SaveTable 120 { 121 friend class _SaveBox; 122 friend class _SaveLine; 123 SfxItemSet aTblSet; 124 _SaveLine* pLine; 125 const SwTable* pSwTable; 126 SfxItemSets aSets; 127 SwFrmFmts aFrmFmts; 128 sal_uInt16 nLineCount; 129 sal_Bool bModifyBox : 1; 130 sal_Bool bSaveFormula : 1; 131 sal_Bool bNewModel : 1; 132 133 public: 134 _SaveTable( const SwTable& rTbl, sal_uInt16 nLnCnt = USHRT_MAX, 135 sal_Bool bSaveFml = sal_True ); 136 ~_SaveTable(); 137 138 sal_uInt16 AddFmt( SwFrmFmt* pFmt, bool bIsLine ); 139 void NewFrmFmt( const SwTableLine* , const SwTableBox*, sal_uInt16 nFmtPos, 140 SwFrmFmt* pOldFmt ); 141 142 void RestoreAttr( SwTable& rTbl, sal_Bool bModifyBox = sal_False ); 143 void SaveCntntAttrs( SwDoc* pDoc ); 144 void CreateNew( SwTable& rTbl, sal_Bool bCreateFrms = sal_True, 145 sal_Bool bRestoreChart = sal_True ); 146 sal_Bool IsNewModel() const { return bNewModel; } 147 }; 148 149 class _SaveLine 150 { 151 friend class _SaveTable; 152 friend class _SaveBox; 153 154 _SaveLine* pNext; 155 _SaveBox* pBox; 156 sal_uInt16 nItemSet; 157 158 public: 159 160 _SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl ); 161 ~_SaveLine(); 162 163 void RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl ); 164 void SaveCntntAttrs( SwDoc* pDoc ); 165 166 void CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl ); 167 }; 168 169 class _SaveBox 170 { 171 friend class _SaveLine; 172 173 _SaveBox* pNext; 174 sal_uLong nSttNode; 175 long nRowSpan; 176 sal_uInt16 nItemSet; 177 union 178 { 179 SfxItemSets* pCntntAttrs; 180 _SaveLine* pLine; 181 } Ptrs; 182 183 public: 184 _SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl ); 185 ~_SaveBox(); 186 187 void RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl ); 188 void SaveCntntAttrs( SwDoc* pDoc ); 189 190 void CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl ); 191 }; 192 193 void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 ); 194 void InsertSort( SvULongs& rArr, sal_uLong nIdx, sal_uInt16* pInsPos = 0 ); 195 196 #if defined( JP_DEBUG ) && defined(DBG_UTIL) 197 #include "shellio.hxx" 198 void DumpDoc( SwDoc* pDoc, const String& rFileNm ); 199 void CheckTable( const SwTable& ); 200 #define DUMPDOC(p,s) DumpDoc( p, s); 201 #define CHECKTABLE(t) CheckTable( t ); 202 #else 203 #define DUMPDOC(p,s) 204 #define CHECKTABLE(t) 205 #endif 206 207 /* #130880: Crash in undo of table to text when the table has (freshly) merged cells 208 The order of cell content nodes in the nodes array is not given by the recursive table structure. 209 The algorithmn must not rely on this even it holds for a fresh loaded table in odt file format. 210 So we need to remember not only the start node position but the end node position as well. 211 */ 212 213 struct SwTblToTxtSave 214 { 215 sal_uLong m_nSttNd; 216 sal_uLong m_nEndNd; 217 xub_StrLen m_nCntnt; 218 SwHistory* m_pHstry; 219 // metadata references for first and last paragraph in cell 220 ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart; 221 ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd; 222 223 SwTblToTxtSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, xub_StrLen nCntnt ); 224 ~SwTblToTxtSave() { delete m_pHstry; } 225 }; 226 227 SV_IMPL_PTRARR( SfxItemSets, SfxItemSetPtr ) 228 SV_IMPL_PTRARR( SwUndoSaveSections, SwUndoSaveSectionPtr ) 229 SV_IMPL_PTRARR( SwUndoMoves, SwUndoMovePtr ) 230 SV_IMPL_PTRARR( SwTblToTxtSaves, SwTblToTxtSavePtr ) 231 SV_IMPL_PTRARR( _UndoTblCpyTbl_Entries, _UndoTblCpyTbl_EntryPtr ) 232 233 sal_uInt16 __FAR_DATA aSave_BoxCntntSet[] = { 234 RES_CHRATR_COLOR, RES_CHRATR_CROSSEDOUT, 235 RES_CHRATR_FONT, RES_CHRATR_FONTSIZE, 236 RES_CHRATR_POSTURE, RES_CHRATR_POSTURE, 237 RES_CHRATR_SHADOWED, RES_CHRATR_WEIGHT, 238 RES_PARATR_ADJUST, RES_PARATR_ADJUST, 239 0 }; 240 241 242 243 SwUndoInsTbl::SwUndoInsTbl( const SwPosition& rPos, sal_uInt16 nCl, sal_uInt16 nRw, 244 sal_uInt16 nAdj, const SwInsertTableOptions& rInsTblOpts, 245 const SwTableAutoFmt* pTAFmt, 246 const SvUShorts* pColArr, 247 const String & rName) 248 : SwUndo( UNDO_INSTABLE ), 249 aInsTblOpts( rInsTblOpts ), pDDEFldType( 0 ), pColWidth( 0 ), pRedlData( 0 ), pAutoFmt( 0 ), 250 nSttNode( rPos.nNode.GetIndex() ), nRows( nRw ), nCols( nCl ), nAdjust( nAdj ) 251 { 252 if( pColArr ) 253 { 254 pColWidth = new SvUShorts( 0, 1 ); 255 pColWidth->Insert( pColArr, 0 ); 256 } 257 if( pTAFmt ) 258 pAutoFmt = new SwTableAutoFmt( *pTAFmt ); 259 260 // Redline beachten 261 SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc(); 262 if( rDoc.IsRedlineOn() ) 263 { 264 pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() ); 265 SetRedlineMode( rDoc.GetRedlineMode() ); 266 } 267 268 sTblNm = rName; 269 } 270 271 272 SwUndoInsTbl::~SwUndoInsTbl() 273 { 274 delete pDDEFldType; 275 delete pColWidth; 276 delete pRedlData; 277 delete pAutoFmt; 278 } 279 280 void SwUndoInsTbl::UndoImpl(::sw::UndoRedoContext & rContext) 281 { 282 SwDoc & rDoc = rContext.GetDoc(); 283 SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode ); 284 285 SwTableNode* pTblNd = aIdx.GetNode().GetTableNode(); 286 ASSERT( pTblNd, "kein TabellenNode" ); 287 pTblNd->DelFrms(); 288 289 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) 290 rDoc.DeleteRedline( *pTblNd, true, USHRT_MAX ); 291 RemoveIdxFromSection( rDoc, nSttNode ); 292 293 // harte SeitenUmbrueche am nachfolgenden Node verschieben 294 SwCntntNode* pNextNd = rDoc.GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode(); 295 if( pNextNd ) 296 { 297 SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt(); 298 const SfxPoolItem *pItem; 299 300 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC, 301 sal_False, &pItem ) ) 302 pNextNd->SetAttr( *pItem ); 303 304 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK, 305 sal_False, &pItem ) ) 306 pNextNd->SetAttr( *pItem ); 307 } 308 309 310 sTblNm = pTblNd->GetTable().GetFrmFmt()->GetName(); 311 if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) ) 312 pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()). 313 GetDDEFldType()->Copy(); 314 315 rDoc.GetNodes().Delete( aIdx, pTblNd->EndOfSectionIndex() - 316 aIdx.GetIndex() + 1 ); 317 318 SwPaM & rPam( rContext.GetCursorSupplier().CreateNewShellCursor() ); 319 rPam.DeleteMark(); 320 rPam.GetPoint()->nNode = aIdx; 321 rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 ); 322 } 323 324 325 void SwUndoInsTbl::RedoImpl(::sw::UndoRedoContext & rContext) 326 { 327 SwDoc & rDoc = rContext.GetDoc(); 328 329 SwPosition const aPos(SwNodeIndex(rDoc.GetNodes(), nSttNode)); 330 const SwTable* pTbl = rDoc.InsertTable( aInsTblOpts, aPos, nRows, nCols, 331 nAdjust, 332 pAutoFmt, pColWidth ); 333 ((SwFrmFmt*)pTbl->GetFrmFmt())->SetName( sTblNm ); 334 SwTableNode* pTblNode = (SwTableNode*)rDoc.GetNodes()[nSttNode]->GetTableNode(); 335 336 if( pDDEFldType ) 337 { 338 SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType( 339 *pDDEFldType); 340 SwDDETable* pDDETbl = new SwDDETable( pTblNode->GetTable(), pNewType ); 341 pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle 342 delete pDDEFldType, pDDEFldType = 0; 343 } 344 345 if( (pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) || 346 ( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) && 347 rDoc.GetRedlineTbl().Count() )) 348 { 349 SwPaM aPam( *pTblNode->EndOfSectionNode(), *pTblNode, 1 ); 350 SwCntntNode* pCNd = aPam.GetCntntNode( sal_False ); 351 if( pCNd ) 352 aPam.GetMark()->nContent.Assign( pCNd, 0 ); 353 354 if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ) 355 { 356 RedlineMode_t eOld = rDoc.GetRedlineMode(); 357 rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE)); 358 359 rDoc.AppendRedline( new SwRedline( *pRedlData, aPam ), true); 360 rDoc.SetRedlineMode_intern( eOld ); 361 } 362 else 363 rDoc.SplitRedline( aPam ); 364 } 365 } 366 367 368 void SwUndoInsTbl::RepeatImpl(::sw::RepeatContext & rContext) 369 { 370 rContext.GetDoc().InsertTable( 371 aInsTblOpts, *rContext.GetRepeatPaM().GetPoint(), 372 nRows, nCols, nAdjust, pAutoFmt, pColWidth ); 373 } 374 375 SwRewriter SwUndoInsTbl::GetRewriter() const 376 { 377 SwRewriter aRewriter; 378 379 aRewriter.AddRule(UNDO_ARG1, SW_RES(STR_START_QUOTE)); 380 aRewriter.AddRule(UNDO_ARG2, sTblNm); 381 aRewriter.AddRule(UNDO_ARG3, SW_RES(STR_END_QUOTE)); 382 383 return aRewriter; 384 } 385 386 // ----------------------------------------------------- 387 388 SwTblToTxtSave::SwTblToTxtSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, xub_StrLen nCnt ) 389 : m_nSttNd( nNd ), m_nEndNd( nEndIdx), m_nCntnt( nCnt ), m_pHstry( 0 ) 390 { 391 // Attributierung des gejointen Node merken. 392 SwTxtNode* pNd = rDoc.GetNodes()[ nNd ]->GetTxtNode(); 393 if( pNd ) 394 { 395 m_pHstry = new SwHistory; 396 397 m_pHstry->Add( pNd->GetTxtColl(), nNd, ND_TEXTNODE ); 398 if ( pNd->GetpSwpHints() ) 399 { 400 m_pHstry->CopyAttr( pNd->GetpSwpHints(), nNd, 0, 401 pNd->GetTxt().Len(), false ); 402 } 403 if( pNd->HasSwAttrSet() ) 404 m_pHstry->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNd ); 405 406 if( !m_pHstry->Count() ) 407 delete m_pHstry, m_pHstry = 0; 408 409 // METADATA: store 410 m_pMetadataUndoStart = pNd->CreateUndo(); 411 } 412 413 // we also need to store the metadata reference of the _last_ paragraph 414 // we subtract 1 to account for the removed cell start/end node pair 415 // (after SectionUp, the end of the range points to the node after the cell) 416 if ( nEndIdx - 1 > nNd ) 417 { 418 SwTxtNode* pLastNode( rDoc.GetNodes()[ nEndIdx - 1 ]->GetTxtNode() ); 419 if( pLastNode ) 420 { 421 // METADATA: store 422 m_pMetadataUndoEnd = pLastNode->CreateUndo(); 423 } 424 } 425 } 426 427 SwUndoTblToTxt::SwUndoTblToTxt( const SwTable& rTbl, sal_Unicode cCh ) 428 : SwUndo( UNDO_TABLETOTEXT ), 429 sTblNm( rTbl.GetFrmFmt()->GetName() ), pDDEFldType( 0 ), pHistory( 0 ), 430 nSttNd( 0 ), nEndNd( 0 ), 431 nAdjust( static_cast<sal_uInt16>(rTbl.GetFrmFmt()->GetHoriOrient().GetHoriOrient()) ), 432 cTrenner( cCh ), nHdlnRpt( rTbl.GetRowsToRepeat() ) 433 { 434 pTblSave = new _SaveTable( rTbl ); 435 pBoxSaves = new SwTblToTxtSaves( (sal_uInt8)rTbl.GetTabSortBoxes().Count() ); 436 437 if( rTbl.IsA( TYPE( SwDDETable ) ) ) 438 pDDEFldType = (SwDDEFieldType*)((SwDDETable&)rTbl).GetDDEFldType()->Copy(); 439 440 bCheckNumFmt = rTbl.GetFrmFmt()->GetDoc()->IsInsTblFormatNum(); 441 442 pHistory = new SwHistory; 443 const SwTableNode* pTblNd = rTbl.GetTableNode(); 444 sal_uLong nTblStt = pTblNd->GetIndex(), nTblEnd = pTblNd->EndOfSectionIndex(); 445 446 const SwSpzFrmFmts& rFrmFmtTbl = *pTblNd->GetDoc()->GetSpzFrmFmts(); 447 for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n ) 448 { 449 SwFrmFmt* pFmt = rFrmFmtTbl[ n ]; 450 SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor(); 451 SwPosition const*const pAPos = pAnchor->GetCntntAnchor(); 452 if (pAPos && 453 ((FLY_AT_CHAR == pAnchor->GetAnchorId()) || 454 (FLY_AT_PARA == pAnchor->GetAnchorId())) && 455 nTblStt <= pAPos->nNode.GetIndex() && 456 pAPos->nNode.GetIndex() < nTblEnd ) 457 { 458 pHistory->Add( *pFmt ); 459 } 460 } 461 462 if( !pHistory->Count() ) 463 delete pHistory, pHistory = 0; 464 } 465 466 467 SwUndoTblToTxt::~SwUndoTblToTxt() 468 { 469 delete pDDEFldType; 470 delete pTblSave; 471 delete pBoxSaves; 472 delete pHistory; 473 } 474 475 476 477 void SwUndoTblToTxt::UndoImpl(::sw::UndoRedoContext & rContext) 478 { 479 SwDoc & rDoc = rContext.GetDoc(); 480 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 481 482 SwNodeIndex aFrmIdx( rDoc.GetNodes(), nSttNd ); 483 SwNodeIndex aEndIdx( rDoc.GetNodes(), nEndNd ); 484 485 pPam->GetPoint()->nNode = aFrmIdx; 486 pPam->SetMark(); 487 pPam->GetPoint()->nNode = aEndIdx; 488 rDoc.DelNumRules( *pPam ); 489 pPam->DeleteMark(); 490 491 // dann sammel mal alle Uppers ein 492 SwNode2Layout aNode2Layout( aFrmIdx.GetNode() ); 493 494 // erzeuge die TabelleNode Structur 495 SwTableNode* pTblNd = rDoc.GetNodes().UndoTableToText( nSttNd, nEndNd, *pBoxSaves ); 496 pTblNd->GetTable().SetTableModel( pTblSave->IsNewModel() ); 497 SwTableFmt* pTableFmt = rDoc.MakeTblFrmFmt( sTblNm, rDoc.GetDfltFrmFmt() ); 498 pTblNd->GetTable().RegisterToFormat( *pTableFmt ); 499 pTblNd->GetTable().SetRowsToRepeat( nHdlnRpt ); 500 501 // erzeuge die alte Tabellen Struktur 502 pTblSave->CreateNew( pTblNd->GetTable() ); 503 504 if( pDDEFldType ) 505 { 506 SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType( 507 *pDDEFldType); 508 SwDDETable* pDDETbl = new SwDDETable( pTblNd->GetTable(), pNewType ); 509 pTblNd->SetNewTable( pDDETbl, sal_False ); // setze die DDE-Tabelle 510 delete pDDEFldType, pDDEFldType = 0; 511 } 512 513 if( bCheckNumFmt ) 514 { 515 SwTableSortBoxes& rBxs = pTblNd->GetTable().GetTabSortBoxes(); 516 for( sal_uInt16 nBoxes = rBxs.Count(); nBoxes; ) 517 rDoc.ChkBoxNumFmt( *rBxs[ --nBoxes ], sal_False ); 518 } 519 520 if( pHistory ) 521 { 522 sal_uInt16 nTmpEnd = pHistory->GetTmpEnd(); 523 pHistory->TmpRollback( &rDoc, 0 ); 524 pHistory->SetTmpEnd( nTmpEnd ); 525 } 526 527 aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(), 528 pTblNd->GetIndex(), pTblNd->GetIndex()+1 ); 529 530 // will man eine TabellenSelektion ?? 531 pPam->DeleteMark(); 532 pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode(); 533 pPam->SetMark(); 534 pPam->GetPoint()->nNode = *pPam->GetNode()->StartOfSectionNode(); 535 pPam->Move( fnMoveForward, fnGoCntnt ); 536 pPam->Exchange(); 537 pPam->Move( fnMoveBackward, fnGoCntnt ); 538 539 ClearFEShellTabCols(); 540 } 541 542 // steht im untbl.cxx und darf nur vom Undoobject gerufen werden 543 SwTableNode* SwNodes::UndoTableToText( sal_uLong nSttNd, sal_uLong nEndNd, 544 const SwTblToTxtSaves& rSavedData ) 545 { 546 SwNodeIndex aSttIdx( *this, nSttNd ); 547 SwNodeIndex aEndIdx( *this, nEndNd+1 ); 548 549 SwTableNode * pTblNd = new SwTableNode( aSttIdx ); 550 SwEndNode* pEndNd = new SwEndNode( aEndIdx, *pTblNd ); 551 552 aEndIdx = *pEndNd; 553 554 /* Set pTblNd as start of section for all nodes in [nSttNd, nEndNd]. 555 Delete all Frames attached to the nodes in that range. */ 556 SwNode* pNd; 557 { 558 sal_uLong n, nTmpEnd = aEndIdx.GetIndex(); 559 for( n = pTblNd->GetIndex() + 1; n < nTmpEnd; ++n ) 560 { 561 if( ( pNd = (*this)[ n ] )->IsCntntNode() ) 562 ((SwCntntNode*)pNd)->DelFrms(); 563 pNd->pStartOfSection = pTblNd; 564 } 565 } 566 567 // dann die Tabellen Struktur teilweise aufbauen. Erstmal eine Line 568 // in der alle Boxen stehen! Die korrekte Struktur kommt dann aus der 569 // SaveStruct 570 SwTableBoxFmt* pBoxFmt = GetDoc()->MakeTableBoxFmt(); 571 SwTableLineFmt* pLineFmt = GetDoc()->MakeTableLineFmt(); 572 SwTableLine* pLine = new SwTableLine( pLineFmt, rSavedData.Count(), 0 ); 573 pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pLine, 0 ); 574 575 SvULongs aBkmkArr( 0, 4 ); 576 for( sal_uInt16 n = rSavedData.Count(); n; ) 577 { 578 SwTblToTxtSave* pSave = rSavedData[ --n ]; 579 // if the start node was merged with last from prev. cell, 580 // subtract 1 from index to get the merged paragraph, and split that 581 aSttIdx = pSave->m_nSttNd - ( ( USHRT_MAX != pSave->m_nCntnt ) ? 1 : 0); 582 SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode(); 583 584 if( USHRT_MAX != pSave->m_nCntnt ) 585 { 586 // an der ContentPosition splitten, das vorherige Zeichen 587 // loeschen (ist der Trenner!) 588 ASSERT( pTxtNd, "Wo ist der TextNode geblieben?" ); 589 SwIndex aCntPos( pTxtNd, pSave->m_nCntnt - 1 ); 590 591 pTxtNd->EraseText( aCntPos, 1 ); 592 SwCntntNode* pNewNd = pTxtNd->SplitCntntNode( 593 SwPosition( aSttIdx, aCntPos )); 594 if( aBkmkArr.Count() ) 595 _RestoreCntntIdx( aBkmkArr, *pNewNd, pSave->m_nCntnt, 596 pSave->m_nCntnt + 1 ); 597 } 598 else 599 { 600 if( aBkmkArr.Count() ) 601 aBkmkArr.Remove( 0, aBkmkArr.Count() ); 602 if( pTxtNd ) 603 _SaveCntntIdx( GetDoc(), aSttIdx.GetIndex(), 604 pTxtNd->GetTxt().Len(), aBkmkArr ); 605 } 606 607 if( pTxtNd ) 608 { 609 // METADATA: restore 610 pTxtNd->GetTxtNode()->RestoreMetadata(pSave->m_pMetadataUndoStart); 611 if( pTxtNd->HasSwAttrSet() ) 612 pTxtNd->ResetAllAttr(); 613 614 if( pTxtNd->GetpSwpHints() ) 615 pTxtNd->ClearSwpHintsArr( false ); 616 } 617 618 if( pSave->m_pHstry ) 619 { 620 sal_uInt16 nTmpEnd = pSave->m_pHstry->GetTmpEnd(); 621 pSave->m_pHstry->TmpRollback( GetDoc(), 0 ); 622 pSave->m_pHstry->SetTmpEnd( nTmpEnd ); 623 } 624 625 // METADATA: restore 626 // end points to node after cell 627 if ( pSave->m_nEndNd - 1 > pSave->m_nSttNd ) 628 { 629 SwTxtNode* pLastNode = (*this)[ pSave->m_nEndNd - 1 ]->GetTxtNode(); 630 if (pLastNode) 631 { 632 pLastNode->RestoreMetadata(pSave->m_pMetadataUndoEnd); 633 } 634 } 635 636 aEndIdx = pSave->m_nEndNd; 637 SwStartNode* pSttNd = new SwStartNode( aSttIdx, ND_STARTNODE, 638 SwTableBoxStartNode ); 639 pSttNd->pStartOfSection = pTblNd; 640 new SwEndNode( aEndIdx, *pSttNd ); 641 642 for( sal_uLong i = aSttIdx.GetIndex(); i < aEndIdx.GetIndex()-1; ++i ) 643 { 644 pNd = (*this)[ i ]; 645 pNd->pStartOfSection = pSttNd; 646 if( pNd->IsStartNode() ) 647 i = pNd->EndOfSectionIndex(); 648 } 649 650 SwTableBox* pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine ); 651 pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, 0 ); 652 } 653 return pTblNd; 654 } 655 656 657 void SwUndoTblToTxt::RedoImpl(::sw::UndoRedoContext & rContext) 658 { 659 SwDoc & rDoc = rContext.GetDoc(); 660 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 661 662 pPam->GetPoint()->nNode = nSttNd; 663 pPam->GetPoint()->nContent.Assign( 0, 0 ); 664 SwNodeIndex aSaveIdx( pPam->GetPoint()->nNode, -1 ); 665 666 pPam->SetMark(); // alle Indizies abmelden 667 pPam->DeleteMark(); 668 669 SwTableNode* pTblNd = pPam->GetNode()->GetTableNode(); 670 ASSERT( pTblNd, "keinen TableNode gefunden" ); 671 672 if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) ) 673 pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()). 674 GetDDEFldType()->Copy(); 675 676 rDoc.TableToText( pTblNd, cTrenner ); 677 678 aSaveIdx++; 679 SwCntntNode* pCNd = aSaveIdx.GetNode().GetCntntNode(); 680 if( !pCNd && 0 == ( pCNd = rDoc.GetNodes().GoNext( &aSaveIdx ) ) && 681 0 == ( pCNd = rDoc.GetNodes().GoPrevious( &aSaveIdx )) ) 682 { 683 ASSERT( sal_False, "wo steht denn nun der TextNode" ); 684 } 685 686 pPam->GetPoint()->nNode = aSaveIdx; 687 pPam->GetPoint()->nContent.Assign( pCNd, 0 ); 688 689 pPam->SetMark(); // alle Indizies abmelden 690 pPam->DeleteMark(); 691 } 692 693 694 void SwUndoTblToTxt::RepeatImpl(::sw::RepeatContext & rContext) 695 { 696 SwPaM *const pPam = & rContext.GetRepeatPaM(); 697 SwTableNode *const pTblNd = pPam->GetNode()->FindTableNode(); 698 if( pTblNd ) 699 { 700 // move cursor out of table 701 pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode(); 702 pPam->Move( fnMoveForward, fnGoCntnt ); 703 pPam->SetMark(); 704 pPam->DeleteMark(); 705 706 rContext.GetDoc().TableToText( pTblNd, cTrenner ); 707 } 708 } 709 710 void SwUndoTblToTxt::SetRange( const SwNodeRange& rRg ) 711 { 712 nSttNd = rRg.aStart.GetIndex(); 713 nEndNd = rRg.aEnd.GetIndex(); 714 } 715 716 void SwUndoTblToTxt::AddBoxPos( SwDoc& rDoc, sal_uLong nNdIdx, sal_uLong nEndIdx, xub_StrLen nCntntIdx ) 717 { 718 SwTblToTxtSave* pNew = new SwTblToTxtSave( rDoc, nNdIdx, nEndIdx, nCntntIdx ); 719 pBoxSaves->Insert( pNew, pBoxSaves->Count() ); 720 } 721 722 // ----------------------------------------------------- 723 724 SwUndoTxtToTbl::SwUndoTxtToTbl( const SwPaM& rRg, 725 const SwInsertTableOptions& rInsTblOpts, 726 sal_Unicode cCh, sal_uInt16 nAdj, 727 const SwTableAutoFmt* pAFmt ) 728 : SwUndo( UNDO_TEXTTOTABLE ), SwUndRng( rRg ), aInsTblOpts( rInsTblOpts ), 729 pDelBoxes( 0 ), pAutoFmt( 0 ), 730 pHistory( 0 ), cTrenner( cCh ), nAdjust( nAdj ) 731 { 732 if( pAFmt ) 733 pAutoFmt = new SwTableAutoFmt( *pAFmt ); 734 735 const SwPosition* pEnd = rRg.End(); 736 SwNodes& rNds = rRg.GetDoc()->GetNodes(); 737 bSplitEnd = pEnd->nContent.GetIndex() && ( pEnd->nContent.GetIndex() 738 != pEnd->nNode.GetNode().GetCntntNode()->Len() || 739 pEnd->nNode.GetIndex() >= rNds.GetEndOfContent().GetIndex()-1 ); 740 } 741 742 SwUndoTxtToTbl::~SwUndoTxtToTbl() 743 { 744 delete pDelBoxes; 745 delete pAutoFmt; 746 } 747 748 void SwUndoTxtToTbl::UndoImpl(::sw::UndoRedoContext & rContext) 749 { 750 SwDoc & rDoc = rContext.GetDoc(); 751 752 sal_uLong nTblNd = nSttNode; 753 if( nSttCntnt ) 754 ++nTblNd; // Node wurde vorher gesplittet 755 SwNodeIndex aIdx( rDoc.GetNodes(), nTblNd ); 756 SwTableNode *const pTNd = aIdx.GetNode().GetTableNode(); 757 OSL_ENSURE( pTNd, "SwUndoTxtToTbl: no TableNode" ); 758 759 RemoveIdxFromSection( rDoc, nTblNd ); 760 761 sTblNm = pTNd->GetTable().GetFrmFmt()->GetName(); 762 763 if( pHistory ) 764 { 765 pHistory->TmpRollback( &rDoc, 0 ); 766 pHistory->SetTmpEnd( pHistory->Count() ); 767 } 768 769 if( pDelBoxes ) 770 { 771 SwTable& rTbl = pTNd->GetTable(); 772 for( sal_uInt16 n = pDelBoxes->Count(); n; ) 773 { 774 SwTableBox* pBox = rTbl.GetTblBox( (*pDelBoxes)[ --n ] ); 775 if( pBox ) 776 ::_DeleteBox( rTbl, pBox, 0, sal_False, sal_False ); 777 else { 778 ASSERT( !this, "Wo ist die Box geblieben?" ); 779 } 780 } 781 } 782 783 SwNodeIndex aEndIdx( *pTNd->EndOfSectionNode() ); 784 rDoc.TableToText( pTNd, 0x0b == cTrenner ? 0x09 : cTrenner ); 785 786 // join again at start? 787 SwPaM aPam(rDoc.GetNodes().GetEndOfContent()); 788 SwPosition *const pPos = aPam.GetPoint(); 789 if( nSttCntnt ) 790 { 791 pPos->nNode = nTblNd; 792 pPos->nContent.Assign(pPos->nNode.GetNode().GetCntntNode(), 0); 793 if (aPam.Move(fnMoveBackward, fnGoCntnt)) 794 { 795 SwNodeIndex & rIdx = aPam.GetPoint()->nNode; 796 797 // dann die Crsr/etc. nochmal relativ verschieben 798 RemoveIdxRel( rIdx.GetIndex()+1, *pPos ); 799 800 rIdx.GetNode().GetCntntNode()->JoinNext(); 801 } 802 } 803 804 // join again at end? 805 if( bSplitEnd ) 806 { 807 SwNodeIndex& rIdx = pPos->nNode; 808 rIdx = nEndNode; 809 SwTxtNode* pTxtNd = rIdx.GetNode().GetTxtNode(); 810 if( pTxtNd && pTxtNd->CanJoinNext() ) 811 { 812 aPam.GetMark()->nContent.Assign( 0, 0 ); 813 aPam.GetPoint()->nContent.Assign( 0, 0 ); 814 815 // dann die Crsr/etc. nochmal relativ verschieben 816 pPos->nContent.Assign( pTxtNd, pTxtNd->GetTxt().Len() ); 817 RemoveIdxRel( nEndNode + 1, *pPos ); 818 819 pTxtNd->JoinNext(); 820 } 821 } 822 823 AddUndoRedoPaM(rContext); 824 } 825 826 827 void SwUndoTxtToTbl::RedoImpl(::sw::UndoRedoContext & rContext) 828 { 829 SwPaM & rPam( AddUndoRedoPaM(rContext) ); 830 RemoveIdxFromRange(rPam, false); 831 SetPaM(rPam); 832 833 SwTable const*const pTable = rContext.GetDoc().TextToTable( 834 aInsTblOpts, rPam, cTrenner, nAdjust, pAutoFmt ); 835 ((SwFrmFmt*)pTable->GetFrmFmt())->SetName( sTblNm ); 836 } 837 838 839 void SwUndoTxtToTbl::RepeatImpl(::sw::RepeatContext & rContext) 840 { 841 // no Table In Table 842 if (!rContext.GetRepeatPaM().GetNode()->FindTableNode()) 843 { 844 rContext.GetDoc().TextToTable( aInsTblOpts, rContext.GetRepeatPaM(), 845 cTrenner, nAdjust, 846 pAutoFmt ); 847 } 848 } 849 850 void SwUndoTxtToTbl::AddFillBox( const SwTableBox& rBox ) 851 { 852 if( !pDelBoxes ) 853 pDelBoxes = new SvULongs; 854 pDelBoxes->Insert( rBox.GetSttIdx(), pDelBoxes->Count() ); 855 } 856 857 SwHistory& SwUndoTxtToTbl::GetHistory() 858 { 859 if( !pHistory ) 860 pHistory = new SwHistory; 861 return *pHistory; 862 } 863 864 // ----------------------------------------------------- 865 866 SwUndoTblHeadline::SwUndoTblHeadline( const SwTable& rTbl, sal_uInt16 nOldHdl, 867 sal_uInt16 nNewHdl ) 868 : SwUndo( UNDO_TABLEHEADLINE ), 869 nOldHeadline( nOldHdl ), 870 nNewHeadline( nNewHdl ) 871 { 872 ASSERT( rTbl.GetTabSortBoxes().Count(), "Tabelle ohne Inhalt" ); 873 const SwStartNode *pSttNd = rTbl.GetTabSortBoxes()[ 0 ]->GetSttNd(); 874 ASSERT( pSttNd, "Box ohne Inhalt" ); 875 876 nTblNd = pSttNd->StartOfSectionIndex(); 877 } 878 879 void SwUndoTblHeadline::UndoImpl(::sw::UndoRedoContext & rContext) 880 { 881 SwDoc & rDoc = rContext.GetDoc(); 882 SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode(); 883 ASSERT( pTNd, "keinen Tabellen-Node gefunden" ); 884 885 rDoc.SetRowsToRepeat( pTNd->GetTable(), nOldHeadline ); 886 } 887 888 void SwUndoTblHeadline::RedoImpl(::sw::UndoRedoContext & rContext) 889 { 890 SwDoc & rDoc = rContext.GetDoc(); 891 892 SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode(); 893 ASSERT( pTNd, "keinen Tabellen-Node gefunden" ); 894 895 rDoc.SetRowsToRepeat( pTNd->GetTable(), nNewHeadline ); 896 } 897 898 void SwUndoTblHeadline::RepeatImpl(::sw::RepeatContext & rContext) 899 { 900 SwTableNode *const pTblNd = 901 rContext.GetRepeatPaM().GetNode()->FindTableNode(); 902 if( pTblNd ) 903 { 904 rContext.GetDoc().SetRowsToRepeat( pTblNd->GetTable(), nNewHeadline ); 905 } 906 } 907 908 909 ////////////////////////////////////////////////////////////////////////// 910 911 912 _SaveTable::_SaveTable( const SwTable& rTbl, sal_uInt16 nLnCnt, sal_Bool bSaveFml ) 913 : aTblSet( *rTbl.GetFrmFmt()->GetAttrSet().GetPool(), aTableSetRange ), 914 pSwTable( &rTbl ), nLineCount( nLnCnt ), bSaveFormula( bSaveFml ) 915 { 916 bModifyBox = sal_False; 917 bNewModel = rTbl.IsNewModel(); 918 aTblSet.Put( rTbl.GetFrmFmt()->GetAttrSet() ); 919 pLine = new _SaveLine( 0, *rTbl.GetTabLines()[ 0 ], *this ); 920 921 _SaveLine* pLn = pLine; 922 if( USHRT_MAX == nLnCnt ) 923 nLnCnt = rTbl.GetTabLines().Count(); 924 for( sal_uInt16 n = 1; n < nLnCnt; ++n ) 925 pLn = new _SaveLine( pLn, *rTbl.GetTabLines()[ n ], *this ); 926 927 aFrmFmts.Remove( 0, aFrmFmts.Count() ); 928 pSwTable = 0; 929 } 930 931 932 _SaveTable::~_SaveTable() 933 { 934 delete pLine; 935 } 936 937 938 sal_uInt16 _SaveTable::AddFmt( SwFrmFmt* pFmt, bool bIsLine ) 939 { 940 sal_uInt16 nRet = aFrmFmts.GetPos( pFmt ); 941 if( USHRT_MAX == nRet ) 942 { 943 // Kopie vom ItemSet anlegen 944 SfxItemSet* pSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(), 945 bIsLine ? aTableLineSetRange : aTableBoxSetRange ); 946 pSet->Put( pFmt->GetAttrSet() ); 947 //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den 948 // Value mit sichern. Der muss gegebenfalls neu 949 // errechnet werden! 950 //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern 951 const SfxPoolItem* pItem; 952 if( SFX_ITEM_SET == pSet->GetItemState( RES_BOXATR_FORMULA, sal_True, &pItem )) 953 { 954 pSet->ClearItem( RES_BOXATR_VALUE ); 955 if( pSwTable && bSaveFormula ) 956 { 957 SwTableFmlUpdate aMsgHnt( pSwTable ); 958 aMsgHnt.eFlags = TBL_BOXNAME; 959 ((SwTblBoxFormula*)pItem)->ChgDefinedIn( pFmt ); 960 ((SwTblBoxFormula*)pItem)->ChangeState( &aMsgHnt ); 961 ((SwTblBoxFormula*)pItem)->ChgDefinedIn( 0 ); 962 } 963 } 964 aSets.Insert( pSet, (nRet = aSets.Count() ) ); 965 aFrmFmts.Insert( pFmt, nRet ); 966 } 967 return nRet; 968 } 969 970 971 void _SaveTable::RestoreAttr( SwTable& rTbl, sal_Bool bMdfyBox ) 972 { 973 sal_uInt16 n; 974 975 bModifyBox = bMdfyBox; 976 977 // zuerst die Attribute des TabellenFrmFormates zurueck holen 978 SwFrmFmt* pFmt = rTbl.GetFrmFmt(); 979 SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet(); 980 rFmtSet.ClearItem(); 981 rFmtSet.Put( aTblSet ); 982 983 if( pFmt->IsInCache() ) 984 { 985 SwFrm::GetCache().Delete( pFmt ); 986 pFmt->SetInCache( sal_False ); 987 } 988 989 // zur Sicherheit alle Tableframes invalidieren 990 SwIterator<SwTabFrm,SwFmt> aIter( *pFmt ); 991 for( SwTabFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() ) 992 if( pLast->GetTable() == &rTbl ) 993 { 994 pLast->InvalidateAll(); 995 pLast->SetCompletePaint(); 996 } 997 998 // FrmFmts mit Defaults (0) fuellen 999 pFmt = 0; 1000 for( n = aSets.Count(); n; --n ) 1001 aFrmFmts.Insert( pFmt, aFrmFmts.Count() ); 1002 1003 sal_uInt16 nLnCnt = nLineCount; 1004 if( USHRT_MAX == nLnCnt ) 1005 nLnCnt = rTbl.GetTabLines().Count(); 1006 1007 _SaveLine* pLn = pLine; 1008 for( n = 0; n < nLnCnt; ++n, pLn = pLn->pNext ) 1009 { 1010 if( !pLn ) 1011 { 1012 ASSERT( !this, "Anzahl der Lines hat sich veraendert" ); 1013 break; 1014 } 1015 1016 pLn->RestoreAttr( *rTbl.GetTabLines()[ n ], *this ); 1017 } 1018 1019 aFrmFmts.Remove( 0, aFrmFmts.Count() ); 1020 bModifyBox = sal_False; 1021 } 1022 1023 1024 void _SaveTable::SaveCntntAttrs( SwDoc* pDoc ) 1025 { 1026 pLine->SaveCntntAttrs( pDoc ); 1027 } 1028 1029 1030 void _SaveTable::CreateNew( SwTable& rTbl, sal_Bool bCreateFrms, 1031 sal_Bool bRestoreChart ) 1032 { 1033 sal_uInt16 n; 1034 1035 _FndBox aTmpBox( 0, 0 ); 1036 //if( bRestoreChart ) 1037 // // ? TL_CHART2: notification or locking of controller required ? 1038 aTmpBox.DelFrms( rTbl ); 1039 1040 // zuerst die Attribute des TabellenFrmFormates zurueck holen 1041 SwFrmFmt* pFmt = rTbl.GetFrmFmt(); 1042 SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet(); 1043 rFmtSet.ClearItem(); 1044 rFmtSet.Put( aTblSet ); 1045 1046 if( pFmt->IsInCache() ) 1047 { 1048 SwFrm::GetCache().Delete( pFmt ); 1049 pFmt->SetInCache( sal_False ); 1050 } 1051 1052 // SwTableBox muss ein Format haben!! 1053 SwTableBox aParent( (SwTableBoxFmt*)pFmt, rTbl.GetTabLines().Count(), 0 ); 1054 1055 // FrmFmts mit Defaults (0) fuellen 1056 pFmt = 0; 1057 for( n = aSets.Count(); n; --n ) 1058 aFrmFmts.Insert( pFmt, aFrmFmts.Count() ); 1059 1060 pLine->CreateNew( rTbl, aParent, *this ); 1061 aFrmFmts.Remove( 0, aFrmFmts.Count() ); 1062 1063 // die neuen Lines eintragen, die alten loeschen 1064 sal_uInt16 nOldLines = nLineCount; 1065 if( USHRT_MAX == nLineCount ) 1066 nOldLines = rTbl.GetTabLines().Count(); 1067 1068 SwDoc *pDoc = rTbl.GetFrmFmt()->GetDoc(); 1069 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); 1070 for( n = 0; n < aParent.GetTabLines().Count(); ++n ) 1071 { 1072 SwTableLine* pLn = aParent.GetTabLines()[ n ]; 1073 pLn->SetUpper( 0 ); 1074 if( n < nOldLines ) 1075 { 1076 SwTableLine* pOld = rTbl.GetTabLines()[ n ]; 1077 1078 // TL_CHART2: notify chart about boxes to be removed 1079 const SwTableBoxes &rBoxes = pOld->GetTabBoxes(); 1080 sal_uInt16 nBoxes = rBoxes.Count(); 1081 for (sal_uInt16 k = 0; k < nBoxes; ++k) 1082 { 1083 SwTableBox *pBox = rBoxes[k]; 1084 if (pPCD) 1085 pPCD->DeleteBox( &rTbl, *pBox ); 1086 } 1087 1088 rTbl.GetTabLines().C40_REPLACE( SwTableLine, pLn, n ); 1089 delete pOld; 1090 } 1091 else 1092 rTbl.GetTabLines().C40_INSERT( SwTableLine, pLn, n ); 1093 } 1094 1095 if( n < nOldLines ) 1096 { 1097 // remove remaining lines... 1098 1099 for (sal_uInt16 k1 = 0; k1 < nOldLines - n; ++k1) 1100 { 1101 const SwTableBoxes &rBoxes = rTbl.GetTabLines()[n + k1]->GetTabBoxes(); 1102 sal_uInt16 nBoxes = rBoxes.Count(); 1103 for (sal_uInt16 k2 = 0; k2 < nBoxes; ++k2) 1104 { 1105 SwTableBox *pBox = rBoxes[k2]; 1106 // TL_CHART2: notify chart about boxes to be removed 1107 if (pPCD) 1108 pPCD->DeleteBox( &rTbl, *pBox ); 1109 } 1110 } 1111 1112 rTbl.GetTabLines().DeleteAndDestroy( n, nOldLines - n ); 1113 } 1114 1115 aParent.GetTabLines().Remove( 0, n ); 1116 1117 if( bCreateFrms ) 1118 aTmpBox.MakeFrms( rTbl ); 1119 if( bRestoreChart ) 1120 { 1121 // TL_CHART2: need to inform chart of probably changed cell names 1122 pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() ); 1123 } 1124 } 1125 1126 1127 void _SaveTable::NewFrmFmt( const SwTableLine* pTblLn, const SwTableBox* pTblBx, 1128 sal_uInt16 nFmtPos, SwFrmFmt* pOldFmt ) 1129 { 1130 SwDoc* pDoc = pOldFmt->GetDoc(); 1131 1132 SwFrmFmt* pFmt = aFrmFmts[ nFmtPos ]; 1133 if( !pFmt ) 1134 { 1135 if( pTblLn ) 1136 pFmt = pDoc->MakeTableLineFmt(); 1137 else 1138 pFmt = pDoc->MakeTableBoxFmt(); 1139 pFmt->SetFmtAttr( *aSets[ nFmtPos ] ); 1140 aFrmFmts.Replace( pFmt, nFmtPos ); 1141 } 1142 1143 //Erstmal die Frms ummelden. 1144 SwIterator<SwTabFrm,SwFmt> aIter( *pOldFmt ); 1145 for( SwFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() ) 1146 { 1147 if( pTblLn ? ((SwRowFrm*)pLast)->GetTabLine() == pTblLn 1148 : ((SwCellFrm*)pLast)->GetTabBox() == pTblBx ) 1149 { 1150 pLast->RegisterToFormat(*pFmt); 1151 pLast->InvalidateAll(); 1152 pLast->ReinitializeFrmSizeAttrFlags(); 1153 if ( !pTblLn ) 1154 { 1155 ((SwCellFrm*)pLast)->SetDerivedVert( sal_False ); 1156 ((SwCellFrm*)pLast)->CheckDirChange(); 1157 } 1158 } 1159 } 1160 1161 //Jetzt noch mich selbst ummelden. 1162 if ( pTblLn ) 1163 const_cast<SwTableLine*>(pTblLn)->RegisterToFormat( *pFmt ); 1164 else if ( pTblBx ) 1165 const_cast<SwTableBox*>(pTblBx)->RegisterToFormat( *pFmt ); 1166 1167 if( bModifyBox && !pTblLn ) 1168 { 1169 const SfxPoolItem& rOld = pOldFmt->GetFmtAttr( RES_BOXATR_FORMAT ), 1170 & rNew = pFmt->GetFmtAttr( RES_BOXATR_FORMAT ); 1171 if( rOld != rNew ) 1172 pFmt->ModifyNotification( (SfxPoolItem*)&rOld, (SfxPoolItem*)&rNew ); 1173 } 1174 1175 if( !pOldFmt->GetDepends() ) 1176 delete pOldFmt; 1177 1178 } 1179 1180 1181 _SaveLine::_SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl ) 1182 : pNext( 0 ) 1183 { 1184 if( pPrev ) 1185 pPrev->pNext = this; 1186 1187 nItemSet = rSTbl.AddFmt( rLine.GetFrmFmt(), true ); 1188 1189 pBox = new _SaveBox( 0, *rLine.GetTabBoxes()[ 0 ], rSTbl ); 1190 _SaveBox* pBx = pBox; 1191 for( sal_uInt16 n = 1; n < rLine.GetTabBoxes().Count(); ++n ) 1192 pBx = new _SaveBox( pBx, *rLine.GetTabBoxes()[ n ], rSTbl ); 1193 } 1194 1195 1196 _SaveLine::~_SaveLine() 1197 { 1198 delete pBox; 1199 delete pNext; 1200 } 1201 1202 1203 void _SaveLine::RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl ) 1204 { 1205 rSTbl.NewFrmFmt( &rLine, 0, nItemSet, rLine.GetFrmFmt() ); 1206 1207 _SaveBox* pBx = pBox; 1208 for( sal_uInt16 n = 0; n < rLine.GetTabBoxes().Count(); ++n, pBx = pBx->pNext ) 1209 { 1210 if( !pBx ) 1211 { 1212 ASSERT( !this, "Anzahl der Boxen hat sich veraendert" ); 1213 break; 1214 } 1215 pBx->RestoreAttr( *rLine.GetTabBoxes()[ n ], rSTbl ); 1216 } 1217 } 1218 1219 1220 void _SaveLine::SaveCntntAttrs( SwDoc* pDoc ) 1221 { 1222 pBox->SaveCntntAttrs( pDoc ); 1223 if( pNext ) 1224 pNext->SaveCntntAttrs( pDoc ); 1225 } 1226 1227 1228 void _SaveLine::CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl ) 1229 { 1230 SwTableLineFmt* pFmt = (SwTableLineFmt*)rSTbl.aFrmFmts[ nItemSet ]; 1231 if( !pFmt ) 1232 { 1233 SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc(); 1234 pFmt = pDoc->MakeTableLineFmt(); 1235 pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] ); 1236 rSTbl.aFrmFmts.Replace( pFmt, nItemSet ); 1237 } 1238 SwTableLine* pNew = new SwTableLine( pFmt, 1, &rParent ); 1239 1240 rParent.GetTabLines().C40_INSERT( SwTableLine, pNew, rParent.GetTabLines().Count() ); 1241 1242 // HB, #127868# robustness: in some cases - which I 1243 // cannot reproduce nor see from the code - pNew seems 1244 // to be set to NULL in C40_INSERT. 1245 ASSERT(pNew, "Table line just created set to NULL in C40_INSERT"); 1246 1247 if (pNew) 1248 { 1249 pBox->CreateNew( rTbl, *pNew, rSTbl ); 1250 } 1251 1252 if( pNext ) 1253 pNext->CreateNew( rTbl, rParent, rSTbl ); 1254 } 1255 1256 1257 _SaveBox::_SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl ) 1258 : pNext( 0 ), nSttNode( ULONG_MAX ), nRowSpan(0) 1259 { 1260 Ptrs.pLine = 0; 1261 1262 if( pPrev ) 1263 pPrev->pNext = this; 1264 1265 nItemSet = rSTbl.AddFmt( rBox.GetFrmFmt(), false ); 1266 1267 if( rBox.GetSttNd() ) 1268 { 1269 nSttNode = rBox.GetSttIdx(); 1270 nRowSpan = rBox.getRowSpan(); 1271 } 1272 else 1273 { 1274 Ptrs.pLine = new _SaveLine( 0, *rBox.GetTabLines()[ 0 ], rSTbl ); 1275 1276 _SaveLine* pLn = Ptrs.pLine; 1277 for( sal_uInt16 n = 1; n < rBox.GetTabLines().Count(); ++n ) 1278 pLn = new _SaveLine( pLn, *rBox.GetTabLines()[ n ], rSTbl ); 1279 } 1280 } 1281 1282 1283 _SaveBox::~_SaveBox() 1284 { 1285 if( ULONG_MAX == nSttNode ) // keine EndBox 1286 delete Ptrs.pLine; 1287 else 1288 delete Ptrs.pCntntAttrs; 1289 delete pNext; 1290 } 1291 1292 1293 void _SaveBox::RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl ) 1294 { 1295 rSTbl.NewFrmFmt( 0, &rBox, nItemSet, rBox.GetFrmFmt() ); 1296 1297 if( ULONG_MAX == nSttNode ) // keine EndBox 1298 { 1299 if( !rBox.GetTabLines().Count() ) 1300 { 1301 ASSERT( !this, "Anzahl der Lines hat sich veraendert" ); 1302 } 1303 else 1304 { 1305 _SaveLine* pLn = Ptrs.pLine; 1306 for( sal_uInt16 n = 0; n < rBox.GetTabLines().Count(); ++n, pLn = pLn->pNext ) 1307 { 1308 if( !pLn ) 1309 { 1310 ASSERT( !this, "Anzahl der Lines hat sich veraendert" ); 1311 break; 1312 } 1313 1314 pLn->RestoreAttr( *rBox.GetTabLines()[ n ], rSTbl ); 1315 } 1316 } 1317 } 1318 else if( rBox.GetSttNd() && rBox.GetSttIdx() == nSttNode ) 1319 { 1320 if( Ptrs.pCntntAttrs ) 1321 { 1322 SwNodes& rNds = rBox.GetFrmFmt()->GetDoc()->GetNodes(); 1323 sal_uInt16 nSet = 0; 1324 sal_uLong nEnd = rBox.GetSttNd()->EndOfSectionIndex(); 1325 for( sal_uLong n = nSttNode + 1; n < nEnd; ++n ) 1326 { 1327 SwCntntNode* pCNd = rNds[ n ]->GetCntntNode(); 1328 if( pCNd ) 1329 { 1330 SfxItemSet* pSet = (*Ptrs.pCntntAttrs)[ nSet++ ]; 1331 if( pSet ) 1332 { 1333 sal_uInt16 *pRstAttr = aSave_BoxCntntSet; 1334 while( *pRstAttr ) 1335 { 1336 pCNd->ResetAttr( *pRstAttr, *(pRstAttr+1) ); 1337 pRstAttr += 2; 1338 } 1339 pCNd->SetAttr( *pSet ); 1340 } 1341 else 1342 pCNd->ResetAllAttr(); 1343 } 1344 } 1345 } 1346 } 1347 else 1348 { 1349 ASSERT( !this, "Box nicht mehr am gleichen Node" ); 1350 } 1351 } 1352 1353 1354 void _SaveBox::SaveCntntAttrs( SwDoc* pDoc ) 1355 { 1356 if( ULONG_MAX == nSttNode ) // keine EndBox 1357 { 1358 // weiter in der Line 1359 Ptrs.pLine->SaveCntntAttrs( pDoc ); 1360 } 1361 else 1362 { 1363 sal_uLong nEnd = pDoc->GetNodes()[ nSttNode ]->EndOfSectionIndex(); 1364 Ptrs.pCntntAttrs = new SfxItemSets( (sal_uInt8)(nEnd - nSttNode - 1 ), 5 ); 1365 for( sal_uLong n = nSttNode + 1; n < nEnd; ++n ) 1366 { 1367 SwCntntNode* pCNd = pDoc->GetNodes()[ n ]->GetCntntNode(); 1368 if( pCNd ) 1369 { 1370 SfxItemSet* pSet = 0; 1371 if( pCNd->HasSwAttrSet() ) 1372 { 1373 pSet = new SfxItemSet( pDoc->GetAttrPool(), 1374 aSave_BoxCntntSet ); 1375 pSet->Put( *pCNd->GetpSwAttrSet() ); 1376 } 1377 1378 Ptrs.pCntntAttrs->Insert( pSet, Ptrs.pCntntAttrs->Count() ); 1379 } 1380 } 1381 } 1382 if( pNext ) 1383 pNext->SaveCntntAttrs( pDoc ); 1384 } 1385 1386 1387 void _SaveBox::CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl ) 1388 { 1389 SwTableBoxFmt* pFmt = (SwTableBoxFmt*)rSTbl.aFrmFmts[ nItemSet ]; 1390 if( !pFmt ) 1391 { 1392 SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc(); 1393 pFmt = pDoc->MakeTableBoxFmt(); 1394 pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] ); 1395 rSTbl.aFrmFmts.Replace( pFmt, nItemSet ); 1396 } 1397 1398 if( ULONG_MAX == nSttNode ) // keine EndBox 1399 { 1400 SwTableBox* pNew = new SwTableBox( pFmt, 1, &rParent ); 1401 rParent.GetTabBoxes().C40_INSERT( SwTableBox, pNew, rParent.GetTabBoxes().Count() ); 1402 1403 Ptrs.pLine->CreateNew( rTbl, *pNew, rSTbl ); 1404 } 1405 else 1406 { 1407 // Box zum StartNode in der alten Tabelle suchen 1408 SwTableBox* pBox = rTbl.GetTblBox( nSttNode ); 1409 ASSERT( pBox, "Wo ist meine TabellenBox geblieben?" ); 1410 1411 SwFrmFmt* pOld = pBox->GetFrmFmt(); 1412 pBox->RegisterToFormat( *pFmt ); 1413 if( !pOld->GetDepends() ) 1414 delete pOld; 1415 1416 pBox->setRowSpan( nRowSpan ); 1417 1418 SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes(); 1419 pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) ); 1420 1421 pBox->SetUpper( &rParent ); 1422 pTBoxes = &rParent.GetTabBoxes(); 1423 pTBoxes->C40_INSERT( SwTableBox, pBox, pTBoxes->Count() ); 1424 } 1425 1426 if( pNext ) 1427 pNext->CreateNew( rTbl, rParent, rSTbl ); 1428 } 1429 1430 1431 ////////////////////////////////////////////////////////////////////////// 1432 1433 // UndoObject fuer Attribut Aenderung an der Tabelle 1434 1435 1436 SwUndoAttrTbl::SwUndoAttrTbl( const SwTableNode& rTblNd, sal_Bool bClearTabCols ) 1437 : SwUndo( UNDO_TABLE_ATTR ), 1438 nSttNode( rTblNd.GetIndex() ) 1439 { 1440 bClearTabCol = bClearTabCols; 1441 pSaveTbl = new _SaveTable( rTblNd.GetTable() ); 1442 } 1443 1444 SwUndoAttrTbl::~SwUndoAttrTbl() 1445 { 1446 delete pSaveTbl; 1447 } 1448 1449 void SwUndoAttrTbl::UndoImpl(::sw::UndoRedoContext & rContext) 1450 { 1451 SwDoc & rDoc = rContext.GetDoc(); 1452 SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode(); 1453 ASSERT( pTblNd, "kein TabellenNode" ); 1454 1455 if (pTblNd) 1456 { 1457 _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() ); 1458 pSaveTbl->RestoreAttr( pTblNd->GetTable() ); 1459 delete pSaveTbl; 1460 pSaveTbl = pOrig; 1461 } 1462 1463 if( bClearTabCol ) 1464 ClearFEShellTabCols(); 1465 } 1466 1467 void SwUndoAttrTbl::RedoImpl(::sw::UndoRedoContext & rContext) 1468 { 1469 UndoImpl(rContext); 1470 } 1471 1472 1473 ////////////////////////////////////////////////////////////////////////// 1474 1475 // UndoObject fuer AutoFormat an der Tabelle 1476 1477 1478 SwUndoTblAutoFmt::SwUndoTblAutoFmt( const SwTableNode& rTblNd, 1479 const SwTableAutoFmt& rAFmt ) 1480 : SwUndo( UNDO_TABLE_AUTOFMT ), 1481 nSttNode( rTblNd.GetIndex() ), 1482 bSaveCntntAttr( sal_False ) 1483 { 1484 pSaveTbl = new _SaveTable( rTblNd.GetTable() ); 1485 1486 if( rAFmt.IsFont() || rAFmt.IsJustify() ) 1487 { 1488 // dann auch noch ueber die ContentNodes der EndBoxen und 1489 // und alle Absatz-Attribute zusammen sammeln 1490 pSaveTbl->SaveCntntAttrs( (SwDoc*)rTblNd.GetDoc() ); 1491 bSaveCntntAttr = sal_True; 1492 } 1493 } 1494 1495 SwUndoTblAutoFmt::~SwUndoTblAutoFmt() 1496 { 1497 delete pSaveTbl; 1498 } 1499 1500 void SwUndoTblAutoFmt::SaveBoxCntnt( const SwTableBox& rBox ) 1501 { 1502 ::boost::shared_ptr<SwUndoTblNumFmt> const p(new SwUndoTblNumFmt(rBox)); 1503 m_Undos.push_back(p); 1504 } 1505 1506 1507 void 1508 SwUndoTblAutoFmt::UndoRedo(bool const bUndo, ::sw::UndoRedoContext & rContext) 1509 { 1510 SwDoc & rDoc = rContext.GetDoc(); 1511 SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode(); 1512 ASSERT( pTblNd, "kein TabellenNode" ); 1513 1514 _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() ); 1515 // dann auch noch ueber die ContentNodes der EndBoxen und 1516 // und alle Absatz-Attribute zusammen sammeln 1517 if( bSaveCntntAttr ) 1518 pOrig->SaveCntntAttrs( &rDoc ); 1519 1520 if (bUndo) 1521 { 1522 for (size_t n = m_Undos.size(); 0 < n; --n) 1523 { 1524 m_Undos.at(n-1)->UndoImpl(rContext); 1525 } 1526 } 1527 1528 pSaveTbl->RestoreAttr( pTblNd->GetTable(), !bUndo ); 1529 delete pSaveTbl; 1530 pSaveTbl = pOrig; 1531 } 1532 1533 void SwUndoTblAutoFmt::UndoImpl(::sw::UndoRedoContext & rContext) 1534 { 1535 UndoRedo(true, rContext); 1536 } 1537 1538 void SwUndoTblAutoFmt::RedoImpl(::sw::UndoRedoContext & rContext) 1539 { 1540 UndoRedo(false, rContext); 1541 } 1542 1543 1544 ////////////////////////////////////////////////////////////////////////// 1545 1546 SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction, 1547 const SwSelBoxes& rBoxes, 1548 const SwTableNode& rTblNd, 1549 long nMn, long nMx, 1550 sal_uInt16 nCnt, sal_Bool bFlg, sal_Bool bSmHght ) 1551 : SwUndo( nAction ), 1552 aBoxes( rBoxes.Count() < 255 ? (sal_uInt8)rBoxes.Count() : 255, 10 ), 1553 nMin( nMn ), nMax( nMx ), 1554 nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ), 1555 nCount( nCnt ), nRelDiff( 0 ), nAbsDiff( 0 ), 1556 nSetColType( USHRT_MAX ), 1557 bFlag( bFlg ), 1558 bSameHeight( bSmHght ) 1559 { 1560 Ptrs.pNewSttNds = 0; 1561 1562 const SwTable& rTbl = rTblNd.GetTable(); 1563 pSaveTbl = new _SaveTable( rTbl ); 1564 1565 // und die Selektion merken 1566 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 1567 aBoxes.Insert( rBoxes[n]->GetSttIdx(), n ); 1568 } 1569 1570 1571 SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction, 1572 const SwSelBoxes& rBoxes, 1573 const SwTableNode& rTblNd ) 1574 : SwUndo( nAction ), 1575 aBoxes( rBoxes.Count() < 255 ? (sal_uInt8)rBoxes.Count() : 255, 10 ), 1576 nMin( 0 ), nMax( 0 ), 1577 nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ), 1578 nCount( 0 ), nRelDiff( 0 ), nAbsDiff( 0 ), 1579 nSetColType( USHRT_MAX ), 1580 bFlag( sal_False ), 1581 bSameHeight( sal_False ) 1582 { 1583 Ptrs.pNewSttNds = 0; 1584 1585 const SwTable& rTbl = rTblNd.GetTable(); 1586 pSaveTbl = new _SaveTable( rTbl ); 1587 1588 // und die Selektion merken 1589 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 1590 aBoxes.Insert( rBoxes[n]->GetSttIdx(), n ); 1591 } 1592 1593 void SwUndoTblNdsChg::ReNewBoxes( const SwSelBoxes& rBoxes ) 1594 { 1595 if( rBoxes.Count() != aBoxes.Count() ) 1596 { 1597 aBoxes.Remove( 0, aBoxes.Count() ); 1598 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 1599 aBoxes.Insert( rBoxes[n]->GetSttIdx(), n ); 1600 } 1601 } 1602 1603 SwUndoTblNdsChg::~SwUndoTblNdsChg() 1604 { 1605 delete pSaveTbl; 1606 1607 if( IsDelBox() ) 1608 delete Ptrs.pDelSects; 1609 else 1610 delete Ptrs.pNewSttNds; 1611 } 1612 1613 void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd, 1614 const SwTableSortBoxes& rOld ) 1615 { 1616 const SwTable& rTbl = rTblNd.GetTable(); 1617 const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes(); 1618 sal_uInt16 n; 1619 sal_uInt16 i; 1620 1621 ASSERT( ! IsDelBox(), "falsche Action" ); 1622 Ptrs.pNewSttNds = new SvULongs( (sal_uInt8)(rTblBoxes.Count() - rOld.Count()), 5 ); 1623 1624 for( n = 0, i = 0; n < rOld.Count(); ++i ) 1625 { 1626 if( rOld[ n ] == rTblBoxes[ i ] ) 1627 ++n; 1628 else 1629 // neue Box: sortiert einfuegen!! 1630 InsertSort( *Ptrs.pNewSttNds, rTblBoxes[ i ]->GetSttIdx() ); 1631 } 1632 1633 for( ; i < rTblBoxes.Count(); ++i ) 1634 // neue Box: sortiert einfuegen!! 1635 InsertSort( *Ptrs.pNewSttNds, rTblBoxes[ i ]->GetSttIdx() ); 1636 } 1637 1638 1639 SwTableLine* lcl_FindTableLine( const SwTable& rTable, 1640 const SwTableBox& rBox ) 1641 { 1642 SwTableLine* pRet = NULL; 1643 // i63949: For nested cells we have to take nLineNo - 1, too, not 0! 1644 const SwTableLines &rTableLines = ( rBox.GetUpper()->GetUpper() != NULL ) ? 1645 rBox.GetUpper()->GetUpper()->GetTabLines() 1646 : rTable.GetTabLines(); 1647 const SwTableLine* pLine = rBox.GetUpper(); 1648 sal_uInt16 nLineNo = rTableLines.C40_GETPOS( SwTableLine, pLine ); 1649 pRet = rTableLines[nLineNo - 1]; 1650 1651 return pRet; 1652 } 1653 1654 const SwTableLines& lcl_FindParentLines( const SwTable& rTable, 1655 const SwTableBox& rBox ) 1656 { 1657 const SwTableLines& rRet = 1658 ( rBox.GetUpper()->GetUpper() != NULL ) ? 1659 rBox.GetUpper()->GetUpper()->GetTabLines() : 1660 rTable.GetTabLines(); 1661 1662 return rRet; 1663 } 1664 1665 1666 void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd, 1667 const SwTableSortBoxes& rOld, 1668 const SwSelBoxes& rBoxes, 1669 const SvULongs& rNodeCnts ) 1670 { 1671 const SwTable& rTbl = rTblNd.GetTable(); 1672 const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes(); 1673 1674 ASSERT( ! IsDelBox(), "falsche Action" ); 1675 Ptrs.pNewSttNds = new SvULongs( (sal_uInt8)(rTblBoxes.Count() - rOld.Count()), 5 ); 1676 1677 ASSERT( rTbl.IsNewModel() || rOld.Count() + nCount * rBoxes.Count() == rTblBoxes.Count(), 1678 "unexpected boxes" ); 1679 ASSERT( rOld.Count() <= rTblBoxes.Count(), "more unexpected boxes" ); 1680 for( sal_uInt16 n = 0, i = 0; i < rTblBoxes.Count(); ++i ) 1681 { 1682 if( ( n < rOld.Count() ) && 1683 ( rOld[ n ] == rTblBoxes[ i ] ) ) 1684 { 1685 // box already known? Then nothing to be done. 1686 ++n; 1687 } 1688 else 1689 { 1690 // new box found: insert (obey sort order) 1691 sal_uInt16 nInsPos; 1692 const SwTableBox* pBox = rTblBoxes[ i ]; 1693 InsertSort( *Ptrs.pNewSttNds, pBox->GetSttIdx(), &nInsPos ); 1694 1695 // find the source box. It must be one in rBoxes. 1696 // We found the right one if it's in the same column as pBox. 1697 // No, if more than one selected cell in the same column has been splitted, 1698 // we have to look for the nearest one (i65201)! 1699 const SwTableBox* pSourceBox = NULL; 1700 const SwTableBox* pCheckBox = NULL; 1701 const SwTableLine* pBoxLine = pBox->GetUpper(); 1702 sal_uInt16 nLineDiff = lcl_FindParentLines(rTbl,*pBox).C40_GETPOS(SwTableLine,pBoxLine); 1703 sal_uInt16 nLineNo = 0; 1704 for( sal_uInt16 j = 0; j < rBoxes.Count(); ++j ) 1705 { 1706 pCheckBox = rBoxes[j]; 1707 if( pCheckBox->GetUpper()->GetUpper() == pBox->GetUpper()->GetUpper() ) 1708 { 1709 const SwTableLine* pCheckLine = pCheckBox->GetUpper(); 1710 sal_uInt16 nCheckLine = lcl_FindParentLines( rTbl, *pCheckBox ). 1711 C40_GETPOS( SwTableLine, pCheckLine ); 1712 if( ( !pSourceBox || nCheckLine > nLineNo ) && nCheckLine < nLineDiff ) 1713 { 1714 nLineNo = nCheckLine; 1715 pSourceBox = pCheckBox; 1716 } 1717 } 1718 } 1719 1720 // find the line number difference 1721 // (to help determine bNodesMoved flag below) 1722 nLineDiff = nLineDiff - nLineNo; 1723 ASSERT( pSourceBox, "Splitted source box not found!" ); 1724 // find out how many nodes the source box used to have 1725 // (to help determine bNodesMoved flag below) 1726 sal_uInt16 nNdsPos = 0; 1727 while( rBoxes[ nNdsPos ] != pSourceBox ) 1728 ++nNdsPos; 1729 sal_uLong nNodes = rNodeCnts[ nNdsPos ]; 1730 1731 // When a new table cell is created, it either gets a new 1732 // node, or it gets node(s) from elsewhere. The undo must 1733 // know, of course, and thus we must determine here just 1734 // where pBox's nodes are from: 1735 // If 1) the source box has lost nodes, and 1736 // 2) we're in the node range that got nodes 1737 // then pBox received nodes from elsewhere. 1738 // If bNodesMoved is set for pBox the undo must move the 1739 // boxes back, otherwise it must delete them. 1740 // The bNodesMoved flag is stored in a seperate array 1741 // which mirrors Ptrs.pNewSttNds, i.e. Ptrs.pNewSttNds[i] 1742 // and aMvBoxes[i] belong together. 1743 sal_Bool bNodesMoved = 1744 ( nNodes != ( pSourceBox->GetSttNd()->EndOfSectionIndex() - 1745 pSourceBox->GetSttIdx() ) ) 1746 && ( nNodes - 1 > nLineDiff ); 1747 aMvBoxes.insert( aMvBoxes.begin() + nInsPos, bNodesMoved ); 1748 } 1749 } 1750 } 1751 1752 1753 void SwUndoTblNdsChg::SaveSection( SwStartNode* pSttNd ) 1754 { 1755 ASSERT( IsDelBox(), "falsche Action" ); 1756 if( !Ptrs.pDelSects ) 1757 Ptrs.pDelSects = new SwUndoSaveSections( 10, 5 ); 1758 1759 SwTableNode* pTblNd = pSttNd->FindTableNode(); 1760 SwUndoSaveSection* pSave = new SwUndoSaveSection; 1761 pSave->SaveSection( pSttNd->GetDoc(), SwNodeIndex( *pSttNd )); 1762 1763 Ptrs.pDelSects->Insert( pSave, Ptrs.pDelSects->Count() ); 1764 nSttNode = pTblNd->GetIndex(); 1765 } 1766 1767 1768 void SwUndoTblNdsChg::UndoImpl(::sw::UndoRedoContext & rContext) 1769 { 1770 SwDoc & rDoc = rContext.GetDoc(); 1771 SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode ); 1772 1773 SwTableNode *const pTblNd = aIdx.GetNode().GetTableNode(); 1774 OSL_ENSURE( pTblNd, "SwUndoTblNdsChg: no TableNode" ); 1775 1776 SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() ); 1777 aMsgHnt.eFlags = TBL_BOXPTR; 1778 rDoc.UpdateTblFlds( &aMsgHnt ); 1779 1780 CHECK_TABLE( pTblNd->GetTable() ) 1781 1782 _FndBox aTmpBox( 0, 0 ); 1783 // ? TL_CHART2: notification or locking of controller required ? 1784 1785 SwChartDataProvider *pPCD = rDoc.GetChartDataProvider(); 1786 std::vector< SwTableBox* > aDelBoxes; 1787 if( IsDelBox() ) 1788 { 1789 // Trick: die fehlenden Boxen in irgendeine Line einfuegen, beim 1790 // CreateNew werden sie korrekt verbunden. 1791 SwTableBox* pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0]; 1792 SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes(); 1793 1794 // die Sections wieder herstellen 1795 for( sal_uInt16 n = Ptrs.pDelSects->Count(); n; ) 1796 { 1797 SwUndoSaveSection* pSave = (*Ptrs.pDelSects)[ --n ]; 1798 pSave->RestoreSection( &rDoc, &aIdx, SwTableBoxStartNode ); 1799 if( pSave->GetHistory() ) 1800 pSave->GetHistory()->Rollback( &rDoc ); 1801 SwTableBox* pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), aIdx, 1802 pCpyBox->GetUpper() ); 1803 rLnBoxes.C40_INSERT( SwTableBox, pBox, rLnBoxes.Count() ); 1804 } 1805 Ptrs.pDelSects->DeleteAndDestroy( 0, Ptrs.pDelSects->Count() ); 1806 } 1807 else if( !aMvBoxes.empty() ) 1808 { 1809 // dann muessen Nodes verschoben und nicht geloescht werden! 1810 // Dafuer brauchen wir aber ein temp Array 1811 SvULongs aTmp( 0, 5); 1812 aTmp.Insert( Ptrs.pNewSttNds, 0 ); 1813 1814 // von hinten anfangen 1815 for( sal_uInt16 n = aTmp.Count(); n; ) 1816 { 1817 // Box aus der Tabellen-Struktur entfernen 1818 sal_uLong nIdx = aTmp[ --n ]; 1819 SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx ); 1820 ASSERT( pBox, "Wo ist meine TabellenBox geblieben?" ); 1821 1822 // TL_CHART2: notify chart about box to be removed 1823 if (pPCD) 1824 pPCD->DeleteBox( &pTblNd->GetTable(), *pBox ); 1825 1826 if( aMvBoxes[ n ] ) 1827 { 1828 SwNodeRange aRg( *pBox->GetSttNd(), 1, 1829 *pBox->GetSttNd()->EndOfSectionNode() ); 1830 1831 SwTableLine* pLine = lcl_FindTableLine( pTblNd->GetTable(), *pBox ); 1832 SwNodeIndex aInsPos( *(pLine->GetTabBoxes()[0]->GetSttNd()), 2 ); 1833 1834 // alle StartNode Indizies anpassen 1835 sal_uInt16 i = n; 1836 sal_uLong nSttIdx = aInsPos.GetIndex() - 2, 1837 nNdCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex(); 1838 while( i && aTmp[ --i ] > nSttIdx ) 1839 aTmp[ i ] += nNdCnt; 1840 1841 // erst die Box loeschen 1842 delete pBox; 1843 // dann die Nodes verschieben, 1844 rDoc.GetNodes()._MoveNodes( aRg, rDoc.GetNodes(), aInsPos, sal_False ); 1845 } 1846 else 1847 rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] ); 1848 aDelBoxes.insert( aDelBoxes.end(), pBox ); 1849 } 1850 } 1851 else 1852 { 1853 // Remove nodes from nodes array (backwards!) 1854 for( sal_uInt16 n = Ptrs.pNewSttNds->Count(); n; ) 1855 { 1856 sal_uLong nIdx = (*Ptrs.pNewSttNds)[ --n ]; 1857 SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx ); 1858 ASSERT( pBox, "Where's my table box?" ); 1859 // TL_CHART2: notify chart about box to be removed 1860 if (pPCD) 1861 pPCD->DeleteBox( &pTblNd->GetTable(), *pBox ); 1862 aDelBoxes.insert( aDelBoxes.end(), pBox ); 1863 rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] ); 1864 } 1865 } 1866 // Remove boxes from table structure 1867 for( sal_uInt16 n = 0; n < aDelBoxes.size(); ++n ) 1868 { 1869 SwTableBox* pCurrBox = aDelBoxes[n]; 1870 SwTableBoxes* pTBoxes = &pCurrBox->GetUpper()->GetTabBoxes(); 1871 pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pCurrBox ) ); 1872 delete pCurrBox; 1873 } 1874 1875 pSaveTbl->CreateNew( pTblNd->GetTable(), sal_True, sal_False ); 1876 1877 // TL_CHART2: need to inform chart of probably changed cell names 1878 rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() ); 1879 1880 if( IsDelBox() ) 1881 nSttNode = pTblNd->GetIndex(); 1882 ClearFEShellTabCols(); 1883 CHECK_TABLE( pTblNd->GetTable() ) 1884 } 1885 1886 1887 void SwUndoTblNdsChg::RedoImpl(::sw::UndoRedoContext & rContext) 1888 { 1889 SwDoc & rDoc = rContext.GetDoc(); 1890 1891 SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode(); 1892 ASSERT( pTblNd, "kein TabellenNode" ); 1893 CHECK_TABLE( pTblNd->GetTable() ) 1894 1895 SwSelBoxes aSelBoxes; 1896 for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n ) 1897 { 1898 SwTableBox* pBox = pTblNd->GetTable().GetTblBox( aBoxes[ n ] ); 1899 aSelBoxes.Insert( pBox ); 1900 } 1901 1902 // SelBoxes erzeugen und InsertCell/-Row/SplitTbl aufrufen 1903 switch( GetId() ) 1904 { 1905 case UNDO_TABLE_INSCOL: 1906 if( USHRT_MAX == nSetColType ) 1907 rDoc.InsertCol( aSelBoxes, nCount, bFlag ); 1908 else 1909 { 1910 SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nCurrBox ); 1911 rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff, 1912 nRelDiff ); 1913 } 1914 break; 1915 1916 case UNDO_TABLE_INSROW: 1917 if( USHRT_MAX == nSetColType ) 1918 rDoc.InsertRow( aSelBoxes, nCount, bFlag ); 1919 else 1920 { 1921 SwTable& rTbl = pTblNd->GetTable(); 1922 SwTableBox* pBox = rTbl.GetTblBox( nCurrBox ); 1923 TblChgMode eOldMode = rTbl.GetTblChgMode(); 1924 rTbl.SetTblChgMode( (TblChgMode)nCount ); 1925 rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff, nRelDiff ); 1926 rTbl.SetTblChgMode( eOldMode ); 1927 } 1928 break; 1929 1930 case UNDO_TABLE_SPLIT: 1931 rDoc.SplitTbl( aSelBoxes, bFlag, nCount, bSameHeight ); 1932 break; 1933 case UNDO_TABLE_DELBOX: 1934 case UNDO_ROW_DELETE: 1935 case UNDO_COL_DELETE: 1936 if( USHRT_MAX == nSetColType ) 1937 { 1938 SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() ); 1939 aMsgHnt.eFlags = TBL_BOXPTR; 1940 rDoc.UpdateTblFlds( &aMsgHnt ); 1941 SwTable &rTable = pTblNd->GetTable(); 1942 if( nMax > nMin && rTable.IsNewModel() ) 1943 rTable.PrepareDeleteCol( nMin, nMax ); 1944 rTable.DeleteSel( &rDoc, aSelBoxes, 0, this, sal_True, sal_True ); 1945 } 1946 else 1947 { 1948 SwTable& rTbl = pTblNd->GetTable(); 1949 1950 SwTableFmlUpdate aMsgHnt( &rTbl ); 1951 aMsgHnt.eFlags = TBL_BOXPTR; 1952 rDoc.UpdateTblFlds( &aMsgHnt ); 1953 1954 SwTableBox* pBox = rTbl.GetTblBox( nCurrBox ); 1955 TblChgMode eOldMode = rTbl.GetTblChgMode(); 1956 rTbl.SetTblChgMode( (TblChgMode)nCount ); 1957 1958 // need the SaveSections! 1959 rDoc.GetIDocumentUndoRedo().DoUndo( true ); 1960 SwUndoTblNdsChg* pUndo = 0; 1961 1962 switch( nSetColType & 0xff ) 1963 { 1964 case nsTblChgWidthHeightType::WH_COL_LEFT: 1965 case nsTblChgWidthHeightType::WH_COL_RIGHT: 1966 case nsTblChgWidthHeightType::WH_CELL_LEFT: 1967 case nsTblChgWidthHeightType::WH_CELL_RIGHT: 1968 rTbl.SetColWidth( *pBox, nSetColType, nAbsDiff, 1969 nRelDiff, (SwUndo**)&pUndo ); 1970 break; 1971 case nsTblChgWidthHeightType::WH_ROW_TOP: 1972 case nsTblChgWidthHeightType::WH_ROW_BOTTOM: 1973 case nsTblChgWidthHeightType::WH_CELL_TOP: 1974 case nsTblChgWidthHeightType::WH_CELL_BOTTOM: 1975 rTbl.SetRowHeight( *pBox, nSetColType, nAbsDiff, 1976 nRelDiff, (SwUndo**)&pUndo ); 1977 break; 1978 } 1979 1980 if( pUndo ) 1981 { 1982 Ptrs.pDelSects->Insert( pUndo->Ptrs.pDelSects, 0 ); 1983 pUndo->Ptrs.pDelSects->Remove( 0, pUndo->Ptrs.pDelSects->Count() ); 1984 1985 delete pUndo; 1986 } 1987 rDoc.GetIDocumentUndoRedo().DoUndo( false ); 1988 1989 rTbl.SetTblChgMode( eOldMode ); 1990 } 1991 nSttNode = pTblNd->GetIndex(); 1992 break; 1993 default: 1994 ; 1995 } 1996 ClearFEShellTabCols(); 1997 CHECK_TABLE( pTblNd->GetTable() ) 1998 } 1999 2000 2001 ////////////////////////////////////////////////////////////////////////// 2002 2003 SwUndoTblMerge::SwUndoTblMerge( const SwPaM& rTblSel ) 2004 : SwUndo( UNDO_TABLE_MERGE ), SwUndRng( rTblSel ), pHistory( 0 ) 2005 { 2006 const SwTableNode* pTblNd = rTblSel.GetNode()->FindTableNode(); 2007 ASSERT( pTblNd, "Wo ist TabllenNode" ) 2008 pSaveTbl = new _SaveTable( pTblNd->GetTable() ); 2009 pMoves = new SwUndoMoves; 2010 nTblNode = pTblNd->GetIndex(); 2011 } 2012 2013 SwUndoTblMerge::~SwUndoTblMerge() 2014 { 2015 delete pSaveTbl; 2016 delete pMoves; 2017 delete pHistory; 2018 } 2019 2020 void SwUndoTblMerge::UndoImpl(::sw::UndoRedoContext & rContext) 2021 { 2022 SwDoc & rDoc = rContext.GetDoc(); 2023 SwNodeIndex aIdx( rDoc.GetNodes(), nTblNode ); 2024 2025 SwTableNode *const pTblNd = aIdx.GetNode().GetTableNode(); 2026 OSL_ENSURE( pTblNd, "SwUndoTblMerge: no TableNode" ); 2027 2028 SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() ); 2029 aMsgHnt.eFlags = TBL_BOXPTR; 2030 rDoc.UpdateTblFlds( &aMsgHnt ); 2031 2032 _FndBox aTmpBox( 0, 0 ); 2033 // ? TL_CHART2: notification or locking of controller required ? 2034 2035 2036 // 1. die geloeschten Boxen wiederherstellen: 2037 2038 // Trick: die fehlenden Boxen in irgendeine Line einfuegen, beim 2039 // CreateNew werden sie korrekt verbunden. 2040 SwTableBox *pBox, *pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0]; 2041 SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes(); 2042 2043 DUMPDOC( &rDoc, "d:\\tmp\\tab_a.db" ) 2044 CHECKTABLE(pTblNd->GetTable()) 2045 2046 SwSelBoxes aSelBoxes; 2047 SwTxtFmtColl* pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD ); 2048 sal_uInt16 n; 2049 2050 for( n = 0; n < aBoxes.Count(); ++n ) 2051 { 2052 aIdx = aBoxes[ n ]; 2053 SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection( aIdx, 2054 SwTableBoxStartNode, pColl ); 2055 pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), *pSttNd, 2056 pCpyBox->GetUpper() ); 2057 rLnBoxes.C40_INSERT( SwTableBox, pBox, rLnBoxes.Count() ); 2058 2059 aSelBoxes.Insert( pBox ); 2060 } 2061 2062 DUMPDOC( &rDoc, "d:\\tmp\\tab_b.db" ) 2063 CHECKTABLE(pTblNd->GetTable()) 2064 2065 SwChartDataProvider *pPCD = rDoc.GetChartDataProvider(); 2066 // 2. die eingefuegten Boxen loeschen 2067 // die Nodes loeschen (von Hinten!!) 2068 for( n = aNewSttNds.Count(); n; ) 2069 { 2070 // Box aus der Tabellen-Struktur entfernen 2071 sal_uLong nIdx = aNewSttNds[ --n ]; 2072 2073 if( !nIdx && n ) 2074 { 2075 nIdx = aNewSttNds[ --n ]; 2076 pBox = pTblNd->GetTable().GetTblBox( nIdx ); 2077 ASSERT( pBox, "Wo ist meine TabellenBox geblieben?" ); 2078 2079 if( !pSaveTbl->IsNewModel() ) 2080 rDoc.GetNodes().MakeTxtNode( SwNodeIndex( 2081 *pBox->GetSttNd()->EndOfSectionNode() ), pColl ); 2082 2083 // das war der Trenner, -> die verschobenen herstellen 2084 for( sal_uInt16 i = pMoves->Count(); i; ) 2085 { 2086 SwTxtNode* pTxtNd = 0; 2087 sal_uInt16 nDelPos = 0; 2088 SwUndoMove* pUndo = (*pMoves)[ --i ]; 2089 if( !pUndo->IsMoveRange() ) 2090 { 2091 pTxtNd = rDoc.GetNodes()[ pUndo->GetDestSttNode() ]->GetTxtNode(); 2092 nDelPos = pUndo->GetDestSttCntnt() - 1; 2093 } 2094 pUndo->UndoImpl(rContext); 2095 if( pUndo->IsMoveRange() ) 2096 { 2097 // den ueberfluessigen Node loeschen 2098 aIdx = pUndo->GetEndNode(); 2099 SwCntntNode *pCNd = aIdx.GetNode().GetCntntNode(); 2100 if( pCNd ) 2101 { 2102 SwNodeIndex aTmp( aIdx, -1 ); 2103 SwCntntNode *pMove = aTmp.GetNode().GetCntntNode(); 2104 if( pMove ) 2105 pCNd->MoveTo( *pMove ); 2106 } 2107 rDoc.GetNodes().Delete( aIdx, 1 ); 2108 } 2109 else if( pTxtNd ) 2110 { 2111 // evt. noch ueberflussige Attribute loeschen 2112 SwIndex aTmpIdx( pTxtNd, nDelPos ); 2113 if( pTxtNd->GetpSwpHints() && pTxtNd->GetpSwpHints()->Count() ) 2114 pTxtNd->RstAttr( aTmpIdx, pTxtNd->GetTxt().Len() - 2115 nDelPos + 1 ); 2116 // das Trennzeichen loeschen 2117 pTxtNd->EraseText( aTmpIdx, 1 ); 2118 } 2119 // delete pUndo; 2120 DUMPDOC( &rDoc, String( "d:\\tmp\\tab_") + String( aNewSttNds.Count() - i ) + 2121 String(".db") ) 2122 } 2123 // pMoves->Remove( 0, pMoves->Count() ); 2124 nIdx = pBox->GetSttIdx(); 2125 } 2126 else 2127 pBox = pTblNd->GetTable().GetTblBox( nIdx ); 2128 2129 if( !pSaveTbl->IsNewModel() ) 2130 { 2131 // TL_CHART2: notify chart about box to be removed 2132 if (pPCD) 2133 pPCD->DeleteBox( &pTblNd->GetTable(), *pBox ); 2134 2135 SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes(); 2136 pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) ); 2137 2138 2139 // Indizies aus dem Bereich loeschen 2140 { 2141 SwNodeIndex aTmpIdx( *pBox->GetSttNd() ); 2142 rDoc.CorrAbs( SwNodeIndex( aTmpIdx, 1 ), 2143 SwNodeIndex( *aTmpIdx.GetNode().EndOfSectionNode() ), 2144 SwPosition( aTmpIdx, SwIndex( 0, 0 )), sal_True ); 2145 } 2146 2147 delete pBox; 2148 rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] ); 2149 } 2150 } 2151 DUMPDOC( &rDoc, "d:\\tmp\\tab_z.db" ) 2152 CHECKTABLE(pTblNd->GetTable()) 2153 2154 2155 pSaveTbl->CreateNew( pTblNd->GetTable(), sal_True, sal_False ); 2156 2157 // TL_CHART2: need to inform chart of probably changed cell names 2158 rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() ); 2159 2160 if( pHistory ) 2161 { 2162 pHistory->TmpRollback( &rDoc, 0 ); 2163 pHistory->SetTmpEnd( pHistory->Count() ); 2164 } 2165 // nTblNode = pTblNd->GetIndex(); 2166 2167 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 2168 pPam->DeleteMark(); 2169 pPam->GetPoint()->nNode = nSttNode; 2170 pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), nSttCntnt ); 2171 pPam->SetMark(); 2172 pPam->DeleteMark(); 2173 2174 CHECKTABLE(pTblNd->GetTable()) 2175 ClearFEShellTabCols(); 2176 } 2177 2178 void SwUndoTblMerge::RedoImpl(::sw::UndoRedoContext & rContext) 2179 { 2180 SwDoc & rDoc = rContext.GetDoc(); 2181 SwPaM & rPam( AddUndoRedoPaM(rContext) ); 2182 rDoc.MergeTbl(rPam); 2183 } 2184 2185 void SwUndoTblMerge::MoveBoxCntnt( SwDoc* pDoc, SwNodeRange& rRg, SwNodeIndex& rPos ) 2186 { 2187 SwNodeIndex aTmp( rRg.aStart, -1 ), aTmp2( rPos, -1 ); 2188 SwUndoMove* pUndo = new SwUndoMove( pDoc, rRg, rPos ); 2189 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 2190 pDoc->MoveNodeRange( rRg, rPos, (pSaveTbl->IsNewModel()) ? 2191 IDocumentContentOperations::DOC_NO_DELFRMS : 2192 IDocumentContentOperations::DOC_MOVEDEFAULT ); 2193 aTmp++; 2194 aTmp2++; 2195 pUndo->SetDestRange( aTmp2, rPos, aTmp ); 2196 2197 pMoves->Insert( pUndo, pMoves->Count() ); 2198 } 2199 2200 void SwUndoTblMerge::SetSelBoxes( const SwSelBoxes& rBoxes ) 2201 { 2202 // die Selektion merken 2203 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 2204 InsertSort( aBoxes, rBoxes[n]->GetSttIdx() ); 2205 2206 // als Trennung fuers einfuegen neuer Boxen nach dem Verschieben! 2207 aNewSttNds.Insert( (sal_uLong)0, aNewSttNds.Count() ); 2208 2209 // The new table model does not delete overlapped cells (by row span), 2210 // so the rBoxes array might be empty even some cells have been merged. 2211 if( rBoxes.Count() ) 2212 nTblNode = rBoxes[ 0 ]->GetSttNd()->FindTableNode()->GetIndex(); 2213 } 2214 2215 void SwUndoTblMerge::SaveCollection( const SwTableBox& rBox ) 2216 { 2217 if( !pHistory ) 2218 pHistory = new SwHistory; 2219 2220 SwNodeIndex aIdx( *rBox.GetSttNd(), 1 ); 2221 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); 2222 if( !pCNd ) 2223 pCNd = aIdx.GetNodes().GoNext( &aIdx ); 2224 2225 pHistory->Add( pCNd->GetFmtColl(), aIdx.GetIndex(), pCNd->GetNodeType()); 2226 if( pCNd->HasSwAttrSet() ) 2227 pHistory->CopyFmtAttr( *pCNd->GetpSwAttrSet(), aIdx.GetIndex() ); 2228 } 2229 2230 2231 ////////////////////////////////////////////////////////////////////////// 2232 2233 SwUndoTblNumFmt::SwUndoTblNumFmt( const SwTableBox& rBox, 2234 const SfxItemSet* pNewSet ) 2235 : SwUndo( UNDO_TBLNUMFMT ), 2236 pBoxSet( 0 ), pHistory( 0 ), nFmtIdx( NUMBERFORMAT_TEXT ) 2237 { 2238 bNewFmt = bNewFml = bNewValue = sal_False; 2239 nNode = rBox.GetSttIdx(); 2240 2241 nNdPos = rBox.IsValidNumTxtNd( 0 == pNewSet ); 2242 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc(); 2243 2244 if( ULONG_MAX != nNdPos ) 2245 { 2246 SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode(); 2247 2248 pHistory = new SwHistory; 2249 SwRegHistory aRHst( *rBox.GetSttNd(), pHistory ); 2250 // always save all text atttibutes because of possibly overlapping 2251 // areas of on/off 2252 pHistory->CopyAttr( pTNd->GetpSwpHints(), nNdPos, 0, 2253 pTNd->GetTxt().Len(), true ); 2254 2255 if( pTNd->HasSwAttrSet() ) 2256 pHistory->CopyFmtAttr( *pTNd->GetpSwAttrSet(), nNdPos ); 2257 2258 aStr = pTNd->GetTxt(); 2259 if( pTNd->GetpSwpHints() ) 2260 pTNd->GetpSwpHints()->DeRegister(); 2261 } 2262 2263 pBoxSet = new SfxItemSet( pDoc->GetAttrPool(), aTableBoxSetRange ); 2264 pBoxSet->Put( rBox.GetFrmFmt()->GetAttrSet() ); 2265 2266 if( pNewSet ) 2267 { 2268 const SfxPoolItem* pItem; 2269 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMAT, 2270 sal_False, &pItem )) 2271 { 2272 bNewFmt = sal_True; 2273 nNewFmtIdx = ((SwTblBoxNumFormat*)pItem)->GetValue(); 2274 } 2275 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMULA, 2276 sal_False, &pItem )) 2277 { 2278 bNewFml = sal_True; 2279 aNewFml = ((SwTblBoxFormula*)pItem)->GetFormula(); 2280 } 2281 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_VALUE, 2282 sal_False, &pItem )) 2283 { 2284 bNewValue = sal_True; 2285 fNewNum = ((SwTblBoxValue*)pItem)->GetValue(); 2286 } 2287 } 2288 2289 // wird die History ueberhaupt benoetigt ?? 2290 if( pHistory && !pHistory->Count() ) 2291 DELETEZ( pHistory ); 2292 } 2293 2294 SwUndoTblNumFmt::~SwUndoTblNumFmt() 2295 { 2296 delete pHistory; 2297 delete pBoxSet; 2298 } 2299 2300 void SwUndoTblNumFmt::UndoImpl(::sw::UndoRedoContext & rContext) 2301 { 2302 ASSERT( pBoxSet, "Where's the stored item set?" ) 2303 2304 SwDoc & rDoc = rContext.GetDoc(); 2305 SwStartNode* pSttNd = rDoc.GetNodes()[ nNode ]-> 2306 FindSttNodeByType( SwTableBoxStartNode ); 2307 ASSERT( pSttNd, "ohne StartNode kein TabellenBox" ); 2308 SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox( 2309 pSttNd->GetIndex() ); 2310 ASSERT( pBox, "keine TabellenBox gefunden" ); 2311 2312 SwTableBoxFmt* pFmt = rDoc.MakeTableBoxFmt(); 2313 pFmt->SetFmtAttr( *pBoxSet ); 2314 pBox->ChgFrmFmt( pFmt ); 2315 2316 if( ULONG_MAX == nNdPos ) 2317 return; 2318 2319 SwTxtNode* pTxtNd = rDoc.GetNodes()[ nNdPos ]->GetTxtNode(); 2320 // wenn mehr als ein Node geloescht wurde, dann wurden auch 2321 // alle "Node"-Attribute gespeichert 2322 if( pTxtNd->HasSwAttrSet() ) 2323 pTxtNd->ResetAllAttr(); 2324 2325 if( pTxtNd->GetpSwpHints() && aStr.Len() ) 2326 pTxtNd->ClearSwpHintsArr( true ); 2327 2328 // ChgTextToNum(..) only acts when the strings are different. We 2329 // need to do the same here. 2330 if( pTxtNd->GetTxt() != aStr ) 2331 { 2332 rDoc.DeleteRedline( *( pBox->GetSttNd() ), false, USHRT_MAX ); 2333 2334 SwIndex aIdx( pTxtNd, 0 ); 2335 if( aStr.Len() ) 2336 { 2337 pTxtNd->EraseText( aIdx ); 2338 pTxtNd->InsertText( aStr, aIdx, 2339 IDocumentContentOperations::INS_NOHINTEXPAND ); 2340 } 2341 } 2342 2343 if( pHistory ) 2344 { 2345 sal_uInt16 nTmpEnd = pHistory->GetTmpEnd(); 2346 pHistory->TmpRollback( &rDoc, 0 ); 2347 pHistory->SetTmpEnd( nTmpEnd ); 2348 } 2349 2350 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 2351 pPam->DeleteMark(); 2352 pPam->GetPoint()->nNode = nNode + 1; 2353 pPam->GetPoint()->nContent.Assign( pTxtNd, 0 ); 2354 } 2355 2356 /** switch the RedlineMode on the given document, using 2357 * SetRedlineMode_intern. This class set the mode in the constructor, 2358 * and changes it back in the destructor, i.e. it uses the 2359 * initialization-is-resource-acquisition idiom. 2360 */ 2361 class RedlineModeInternGuard 2362 { 2363 SwDoc& mrDoc; 2364 RedlineMode_t meOldRedlineMode; 2365 2366 public: 2367 RedlineModeInternGuard( 2368 SwDoc& rDoc, /// change mode of this document 2369 RedlineMode_t eNewRedlineMode, /// new redline mode 2370 RedlineMode_t eRedlineModeMask = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE /*change only bits set in this mask*/)); 2371 2372 ~RedlineModeInternGuard(); 2373 }; 2374 2375 RedlineModeInternGuard::RedlineModeInternGuard( 2376 SwDoc& rDoc, 2377 RedlineMode_t eNewRedlineMode, 2378 RedlineMode_t eRedlineModeMask ) 2379 : mrDoc( rDoc ), 2380 meOldRedlineMode( rDoc.GetRedlineMode() ) 2381 { 2382 mrDoc.SetRedlineMode_intern((RedlineMode_t)( ( meOldRedlineMode & ~eRedlineModeMask ) | 2383 ( eNewRedlineMode & eRedlineModeMask ) )); 2384 } 2385 2386 RedlineModeInternGuard::~RedlineModeInternGuard() 2387 { 2388 mrDoc.SetRedlineMode_intern( meOldRedlineMode ); 2389 } 2390 2391 2392 2393 void SwUndoTblNumFmt::RedoImpl(::sw::UndoRedoContext & rContext) 2394 { 2395 // konnte die Box veraendert werden ? 2396 if( !pBoxSet ) 2397 return ; 2398 2399 SwDoc & rDoc = rContext.GetDoc(); 2400 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 2401 2402 pPam->DeleteMark(); 2403 pPam->GetPoint()->nNode = nNode; 2404 2405 SwNode * pNd = & pPam->GetPoint()->nNode.GetNode(); 2406 SwStartNode* pSttNd = pNd->FindSttNodeByType( SwTableBoxStartNode ); 2407 ASSERT( pSttNd, "ohne StartNode kein TabellenBox" ); 2408 SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox( 2409 pSttNd->GetIndex() ); 2410 ASSERT( pBox, "keine TabellenBox gefunden" ); 2411 2412 SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt(); 2413 if( bNewFmt || bNewFml || bNewValue ) 2414 { 2415 SfxItemSet aBoxSet( rDoc.GetAttrPool(), 2416 RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2417 2418 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht. 2419 // Sorge dafuer, das der Text auch entsprechend 2420 // formatiert wird! 2421 pBoxFmt->LockModify(); 2422 2423 if( bNewFml ) 2424 aBoxSet.Put( SwTblBoxFormula( aNewFml )); 2425 else 2426 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA ); 2427 if( bNewFmt ) 2428 aBoxSet.Put( SwTblBoxNumFormat( nNewFmtIdx )); 2429 else 2430 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT ); 2431 if( bNewValue ) 2432 aBoxSet.Put( SwTblBoxValue( fNewNum )); 2433 else 2434 pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE ); 2435 pBoxFmt->UnlockModify(); 2436 2437 // dvo: When redlining is (was) enabled, setting the attribute 2438 // will also change the cell content. To allow this, the 2439 // REDLINE_IGNORE flag must be removed during Redo. #108450# 2440 RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE ); 2441 pBoxFmt->SetFmtAttr( aBoxSet ); 2442 } 2443 else if( NUMBERFORMAT_TEXT != nFmtIdx ) 2444 { 2445 SfxItemSet aBoxSet( rDoc.GetAttrPool(), 2446 RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2447 2448 aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx )); 2449 aBoxSet.Put( SwTblBoxValue( fNum )); 2450 2451 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht. 2452 // Sorge dafuer, das der Text auch entsprechend 2453 // formatiert wird! 2454 pBoxFmt->LockModify(); 2455 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA ); 2456 pBoxFmt->UnlockModify(); 2457 2458 // dvo: When redlining is (was) enabled, setting the attribute 2459 // will also change the cell content. To allow this, the 2460 // REDLINE_IGNORE flag must be removed during Redo. #108450# 2461 RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE ); 2462 pBoxFmt->SetFmtAttr( aBoxSet ); 2463 } 2464 else 2465 { 2466 // es ist keine Zahl 2467 2468 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht. 2469 // Sorge dafuer, das der Text auch entsprechend 2470 // formatiert wird! 2471 pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT )); 2472 2473 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2474 } 2475 2476 if( bNewFml ) 2477 { 2478 // egal was gesetzt wurde, ein Update der Tabelle macht sich immer gut 2479 SwTableFmlUpdate aTblUpdate( &pSttNd->FindTableNode()->GetTable() ); 2480 rDoc.UpdateTblFlds( &aTblUpdate ); 2481 } 2482 2483 if( !pNd->IsCntntNode() ) 2484 pNd = rDoc.GetNodes().GoNext( &pPam->GetPoint()->nNode ); 2485 pPam->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 ); 2486 } 2487 2488 void SwUndoTblNumFmt::SetBox( const SwTableBox& rBox ) 2489 { 2490 nNode = rBox.GetSttIdx(); 2491 } 2492 2493 2494 ////////////////////////////////////////////////////////////////////////// 2495 2496 _UndoTblCpyTbl_Entry::_UndoTblCpyTbl_Entry( const SwTableBox& rBox ) 2497 : nBoxIdx( rBox.GetSttIdx() ), nOffset( 0 ), 2498 pBoxNumAttr( 0 ), pUndo( 0 ), bJoin( false ) 2499 { 2500 } 2501 2502 _UndoTblCpyTbl_Entry::~_UndoTblCpyTbl_Entry() 2503 { 2504 delete pUndo; 2505 delete pBoxNumAttr; 2506 } 2507 2508 2509 SwUndoTblCpyTbl::SwUndoTblCpyTbl() 2510 : SwUndo( UNDO_TBLCPYTBL ), pInsRowUndo( 0 ) 2511 { 2512 pArr = new _UndoTblCpyTbl_Entries; 2513 } 2514 2515 SwUndoTblCpyTbl::~SwUndoTblCpyTbl() 2516 { 2517 delete pArr; 2518 delete pInsRowUndo; 2519 } 2520 2521 void SwUndoTblCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext) 2522 { 2523 SwDoc & rDoc = rContext.GetDoc(); 2524 _DEBUG_REDLINE( &rDoc ) 2525 2526 SwTableNode* pTblNd = 0; 2527 for( sal_uInt16 n = pArr->Count(); n; ) 2528 { 2529 _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ --n ]; 2530 sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset; 2531 SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode(); 2532 if( !pTblNd ) 2533 pTblNd = pSNd->FindTableNode(); 2534 2535 SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos ); 2536 2537 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 ); 2538 rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() ); 2539 2540 // b62341295: Redline for copying tables 2541 const SwNode *pEndNode = rBox.GetSttNd()->EndOfSectionNode(); 2542 SwPaM aPam( aInsIdx.GetNode(), *pEndNode ); 2543 SwUndoDelete* pUndo = 0; 2544 2545 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ) 2546 { 2547 bool bDeleteCompleteParagraph = false; 2548 bool bShiftPam = false; 2549 // There are a couple of different situations to consider during redlining 2550 if( pEntry->pUndo ) 2551 { 2552 SwUndoDelete *const pUndoDelete = 2553 dynamic_cast<SwUndoDelete*>(pEntry->pUndo); 2554 SwUndoRedlineDelete *const pUndoRedlineDelete = 2555 dynamic_cast<SwUndoRedlineDelete*>(pEntry->pUndo); 2556 OSL_ASSERT(pUndoDelete || pUndoRedlineDelete); 2557 if (pUndoRedlineDelete) 2558 { 2559 // The old content was not empty or he has been merged with the new content 2560 bDeleteCompleteParagraph = !pEntry->bJoin; // bJoin is set when merged 2561 // Set aTmpIdx to the beginning fo the old content 2562 SwNodeIndex aTmpIdx( *pEndNode, 2563 pUndoRedlineDelete->NodeDiff()-1 ); 2564 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode(); 2565 if( pTxt ) 2566 { 2567 aPam.GetPoint()->nNode = *pTxt; 2568 aPam.GetPoint()->nContent.Assign( pTxt, 2569 pUndoRedlineDelete->ContentStart() ); 2570 } 2571 else 2572 *aPam.GetPoint() = SwPosition( aTmpIdx ); 2573 } 2574 else if (pUndoDelete && pUndoDelete->IsDelFullPara()) 2575 { 2576 // When the old content was an empty paragraph, but could not be joined 2577 // with the new content (e.g. because of a section or table) 2578 // We "save" the aPam.Point, we go one step backwards (because later on the 2579 // empty paragraph will be inserted by the undo) and set the "ShiftPam-flag 2580 // for step forward later on. 2581 bDeleteCompleteParagraph = true; 2582 bShiftPam = true; 2583 SwNodeIndex aTmpIdx( *pEndNode, -1 ); 2584 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode(); 2585 if( pTxt ) 2586 { 2587 aPam.GetPoint()->nNode = *pTxt; 2588 aPam.GetPoint()->nContent.Assign( pTxt, 0 ); 2589 } 2590 else 2591 *aPam.GetPoint() = SwPosition( aTmpIdx ); 2592 } 2593 } 2594 rDoc.DeleteRedline( aPam, true, USHRT_MAX ); 2595 2596 if( pEntry->pUndo ) 2597 { 2598 pEntry->pUndo->UndoImpl(rContext); 2599 delete pEntry->pUndo; 2600 pEntry->pUndo = 0; 2601 } 2602 if( bShiftPam ) 2603 { 2604 // The aPam.Point is at the moment at the last position of the new content and has to be 2605 // moved to the first postion of the old content for the SwUndoDelete operation 2606 SwNodeIndex aTmpIdx( aPam.GetPoint()->nNode, 1 ); 2607 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode(); 2608 if( pTxt ) 2609 { 2610 aPam.GetPoint()->nNode = *pTxt; 2611 aPam.GetPoint()->nContent.Assign( pTxt, 0 ); 2612 } 2613 else 2614 *aPam.GetPoint() = SwPosition( aTmpIdx ); 2615 } 2616 pUndo = new SwUndoDelete( aPam, bDeleteCompleteParagraph, sal_True ); 2617 } 2618 else 2619 { 2620 pUndo = new SwUndoDelete( aPam, true ); 2621 if( pEntry->pUndo ) 2622 { 2623 pEntry->pUndo->UndoImpl(rContext); 2624 delete pEntry->pUndo; 2625 pEntry->pUndo = 0; 2626 } 2627 } 2628 pEntry->pUndo = pUndo; 2629 2630 aInsIdx = rBox.GetSttIdx() + 1; 2631 rDoc.GetNodes().Delete( aInsIdx, 1 ); 2632 2633 SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2634 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2635 aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() ); 2636 if( aTmpSet.Count() ) 2637 { 2638 SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt(); 2639 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2640 pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT ); 2641 } 2642 2643 if( pEntry->pBoxNumAttr ) 2644 { 2645 rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr ); 2646 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0; 2647 } 2648 2649 if( aTmpSet.Count() ) 2650 { 2651 pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(), 2652 RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2653 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2654 pEntry->pBoxNumAttr->Put( aTmpSet ); 2655 } 2656 2657 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx; 2658 } 2659 2660 if( pInsRowUndo ) 2661 { 2662 pInsRowUndo->UndoImpl(rContext); 2663 } 2664 _DEBUG_REDLINE( &rDoc ) 2665 } 2666 2667 void SwUndoTblCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext) 2668 { 2669 SwDoc & rDoc = rContext.GetDoc(); 2670 _DEBUG_REDLINE( &rDoc ) 2671 2672 if( pInsRowUndo ) 2673 { 2674 pInsRowUndo->RedoImpl(rContext); 2675 } 2676 2677 SwTableNode* pTblNd = 0; 2678 for( sal_uInt16 n = 0; n < pArr->Count(); ++n ) 2679 { 2680 _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ n ]; 2681 sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset; 2682 SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode(); 2683 if( !pTblNd ) 2684 pTblNd = pSNd->FindTableNode(); 2685 2686 SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos ); 2687 2688 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 ); 2689 2690 // b62341295: Redline for copying tables - Start. 2691 rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() ); 2692 SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode()); 2693 SwUndo* pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ? 0 : new SwUndoDelete( aPam, sal_True ); 2694 if( pEntry->pUndo ) 2695 { 2696 pEntry->pUndo->UndoImpl(rContext); 2697 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ) 2698 { 2699 // PrepareRedline has to be called with the beginning of the old content 2700 // When new and old content has been joined, the rIter.pAktPam has been set 2701 // by the Undo operation to this point. 2702 // Otherwise aInsIdx has been moved during the Undo operation 2703 if( pEntry->bJoin ) 2704 { 2705 SwPaM const& rLastPam = 2706 rContext.GetCursorSupplier().GetCurrentShellCursor(); 2707 pUndo = PrepareRedline( &rDoc, rBox, *rLastPam.GetPoint(), 2708 pEntry->bJoin, true ); 2709 } 2710 else 2711 { 2712 SwPosition aTmpPos( aInsIdx ); 2713 pUndo = PrepareRedline( &rDoc, rBox, aTmpPos, pEntry->bJoin, true ); 2714 } 2715 } 2716 delete pEntry->pUndo; 2717 pEntry->pUndo = 0; 2718 } 2719 pEntry->pUndo = pUndo; 2720 // b62341295: Redline for copying tables - End. 2721 2722 aInsIdx = rBox.GetSttIdx() + 1; 2723 rDoc.GetNodes().Delete( aInsIdx, 1 ); 2724 2725 SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2726 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2727 aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() ); 2728 if( aTmpSet.Count() ) 2729 { 2730 SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt(); 2731 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2732 pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT ); 2733 } 2734 if( pEntry->pBoxNumAttr ) 2735 { 2736 rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr ); 2737 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0; 2738 } 2739 2740 if( aTmpSet.Count() ) 2741 { 2742 pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(), 2743 RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2744 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2745 pEntry->pBoxNumAttr->Put( aTmpSet ); 2746 } 2747 2748 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx; 2749 } 2750 _DEBUG_REDLINE( &rDoc ) 2751 } 2752 2753 void SwUndoTblCpyTbl::AddBoxBefore( const SwTableBox& rBox, sal_Bool bDelCntnt ) 2754 { 2755 if( pArr->Count() && !bDelCntnt ) 2756 return; 2757 2758 _UndoTblCpyTbl_Entry* pEntry = new _UndoTblCpyTbl_Entry( rBox ); 2759 pArr->Insert( pEntry, pArr->Count() ); 2760 2761 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc(); 2762 _DEBUG_REDLINE( pDoc ) 2763 if( bDelCntnt ) 2764 { 2765 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 ); 2766 pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() ); 2767 SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() ); 2768 2769 if( !pDoc->IsRedlineOn() ) 2770 pEntry->pUndo = new SwUndoDelete( aPam, sal_True ); 2771 } 2772 2773 pEntry->pBoxNumAttr = new SfxItemSet( pDoc->GetAttrPool(), 2774 RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2775 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2776 pEntry->pBoxNumAttr->Put( rBox.GetFrmFmt()->GetAttrSet() ); 2777 if( !pEntry->pBoxNumAttr->Count() ) 2778 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0; 2779 _DEBUG_REDLINE( pDoc ) 2780 } 2781 2782 void SwUndoTblCpyTbl::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx, sal_Bool bDelCntnt ) 2783 { 2784 _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ pArr->Count() - 1 ]; 2785 2786 // wurde der Inhalt geloescht, so loesche jetzt auch noch den temp. 2787 // erzeugten Node 2788 if( bDelCntnt ) 2789 { 2790 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc(); 2791 _DEBUG_REDLINE( pDoc ) 2792 2793 if( pDoc->IsRedlineOn() ) 2794 { 2795 SwPosition aTmpPos( rIdx ); 2796 pEntry->pUndo = PrepareRedline( pDoc, rBox, aTmpPos, pEntry->bJoin, false ); 2797 } 2798 SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 ); 2799 rBox.GetFrmFmt()->GetDoc()->GetNodes().Delete( aDelIdx, 1 ); 2800 _DEBUG_REDLINE( pDoc ) 2801 } 2802 2803 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx; 2804 } 2805 2806 // PrepareRedline is called from AddBoxAfter() and from Redo() in slightly different situations. 2807 // bRedo is set by calling from Redo() 2808 // rJoin is false by calling from AddBoxAfter() and will be set if the old and new content has 2809 // been merged. 2810 // rJoin is true if Redo() is calling and the content has already been merged 2811 2812 SwUndo* SwUndoTblCpyTbl::PrepareRedline( SwDoc* pDoc, const SwTableBox& rBox, 2813 const SwPosition& rPos, bool& rJoin, bool bRedo ) 2814 { 2815 SwUndo *pUndo = 0; 2816 // b62341295: Redline for copying tables 2817 // What's to do? 2818 // Mark the cell content before rIdx as insertion, 2819 // mark the cell content behind rIdx as deletion 2820 // merge text nodes at rIdx if possible 2821 RedlineMode_t eOld = pDoc->GetRedlineMode(); 2822 pDoc->SetRedlineMode_intern((RedlineMode_t)( ( eOld | nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) & 2823 ~nsRedlineMode_t::REDLINE_IGNORE )); 2824 SwPosition aInsertEnd( rPos ); 2825 SwTxtNode* pTxt; 2826 if( !rJoin ) 2827 { 2828 // If the content is not merged, the end of the insertion is at the end of the node 2829 // _before_ the given position rPos 2830 --aInsertEnd.nNode; 2831 pTxt = aInsertEnd.nNode.GetNode().GetTxtNode(); 2832 if( pTxt ) 2833 { 2834 aInsertEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() ); 2835 if( !bRedo && rPos.nNode.GetNode().GetTxtNode() ) 2836 { // Try to merge, if not called by Redo() 2837 rJoin = true; 2838 pTxt->JoinNext(); 2839 } 2840 } 2841 else 2842 aInsertEnd.nContent = SwIndex( 0 ); 2843 } 2844 // For joined (merged) contents the start of deletionm and end of insertion are identical 2845 // otherwise adjacent nodes. 2846 SwPosition aDeleteStart( rJoin ? aInsertEnd : rPos ); 2847 if( !rJoin ) 2848 { 2849 pTxt = aDeleteStart.nNode.GetNode().GetTxtNode(); 2850 if( pTxt ) 2851 aDeleteStart.nContent.Assign( pTxt, 0 ); 2852 } 2853 SwPosition aCellEnd( SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode(), -1 ) ); 2854 pTxt = aCellEnd.nNode.GetNode().GetTxtNode(); 2855 if( pTxt ) 2856 aCellEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() ); 2857 if( aDeleteStart != aCellEnd ) 2858 { // If the old (deleted) part is not empty, here we are... 2859 SwPaM aDeletePam( aDeleteStart, aCellEnd ); 2860 pUndo = new SwUndoRedlineDelete( aDeletePam, UNDO_DELETE ); 2861 pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDeletePam ), true ); 2862 } 2863 else if( !rJoin ) // If the old part is empty and joined, we are finished 2864 { // if it is not joined, we have to delete this empty paragraph 2865 aCellEnd = SwPosition( 2866 SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() )); 2867 SwPaM aTmpPam( aDeleteStart, aCellEnd ); 2868 pUndo = new SwUndoDelete( aTmpPam, sal_True ); 2869 } 2870 SwPosition aCellStart( SwNodeIndex( *rBox.GetSttNd(), 2 ) ); 2871 pTxt = aCellStart.nNode.GetNode().GetTxtNode(); 2872 if( pTxt ) 2873 aCellStart.nContent.Assign( pTxt, 0 ); 2874 if( aCellStart != aInsertEnd ) // An empty insertion will not been marked 2875 { 2876 SwPaM aTmpPam( aCellStart, aInsertEnd ); 2877 pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aTmpPam ), true ); 2878 } 2879 2880 pDoc->SetRedlineMode_intern( eOld ); 2881 return pUndo; 2882 } 2883 2884 2885 sal_Bool SwUndoTblCpyTbl::InsertRow( SwTable& rTbl, const SwSelBoxes& rBoxes, 2886 sal_uInt16 nCnt ) 2887 { 2888 SwTableNode* pTblNd = (SwTableNode*)rTbl.GetTabSortBoxes()[0]-> 2889 GetSttNd()->FindTableNode(); 2890 2891 SwTableSortBoxes aTmpLst( 0, 5 ); 2892 pInsRowUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW, rBoxes, *pTblNd, 2893 0, 0, nCnt, sal_True, sal_False ); 2894 aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); 2895 2896 sal_Bool bRet = rTbl.InsertRow( rTbl.GetFrmFmt()->GetDoc(), rBoxes, nCnt, sal_True ); 2897 if( bRet ) 2898 pInsRowUndo->SaveNewBoxes( *pTblNd, aTmpLst ); 2899 else 2900 delete pInsRowUndo, pInsRowUndo = 0; 2901 return bRet; 2902 } 2903 2904 sal_Bool SwUndoTblCpyTbl::IsEmpty() const 2905 { 2906 return !pInsRowUndo && !pArr->Count(); 2907 } 2908 2909 2910 ////////////////////////////////////////////////////////////////////////// 2911 2912 SwUndoCpyTbl::SwUndoCpyTbl() 2913 : SwUndo( UNDO_CPYTBL ), pDel( 0 ), nTblNode( 0 ) 2914 { 2915 } 2916 2917 SwUndoCpyTbl::~SwUndoCpyTbl() 2918 { 2919 delete pDel; 2920 } 2921 2922 void SwUndoCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext) 2923 { 2924 SwDoc & rDoc = rContext.GetDoc(); 2925 SwTableNode* pTNd = rDoc.GetNodes()[ nTblNode ]->GetTableNode(); 2926 2927 // harte SeitenUmbrueche am nachfolgenden Node verschieben 2928 SwCntntNode* pNextNd = rDoc.GetNodes()[ pTNd->EndOfSectionIndex()+1 ]->GetCntntNode(); 2929 if( pNextNd ) 2930 { 2931 SwFrmFmt* pTableFmt = pTNd->GetTable().GetFrmFmt(); 2932 const SfxPoolItem *pItem; 2933 2934 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC, 2935 sal_False, &pItem ) ) 2936 pNextNd->SetAttr( *pItem ); 2937 2938 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK, 2939 sal_False, &pItem ) ) 2940 pNextNd->SetAttr( *pItem ); 2941 } 2942 2943 SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 ); 2944 pDel = new SwUndoDelete( aPam, sal_True ); 2945 } 2946 2947 void SwUndoCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext) 2948 { 2949 pDel->UndoImpl(rContext); 2950 delete pDel, pDel = 0; 2951 } 2952 2953 2954 ////////////////////////////////////////////////////////////////////////// 2955 2956 SwUndoSplitTbl::SwUndoSplitTbl( const SwTableNode& rTblNd, 2957 SwSaveRowSpan* pRowSp, sal_uInt16 eMode, sal_Bool bNewSize ) 2958 : SwUndo( UNDO_SPLIT_TABLE ), 2959 nTblNode( rTblNd.GetIndex() ), nOffset( 0 ), mpSaveRowSpan( pRowSp ), pSavTbl( 0 ), 2960 pHistory( 0 ), nMode( eMode ), nFmlEnd( 0 ), bCalcNewSize( bNewSize ) 2961 { 2962 switch( nMode ) 2963 { 2964 case HEADLINE_BOXATRCOLLCOPY: 2965 pHistory = new SwHistory; 2966 // kein break; 2967 case HEADLINE_BORDERCOPY: 2968 case HEADLINE_BOXATTRCOPY: 2969 pSavTbl = new _SaveTable( rTblNd.GetTable(), 1, sal_False ); 2970 break; 2971 } 2972 } 2973 2974 SwUndoSplitTbl::~SwUndoSplitTbl() 2975 { 2976 delete pSavTbl; 2977 delete pHistory; 2978 delete mpSaveRowSpan; 2979 } 2980 2981 void SwUndoSplitTbl::UndoImpl(::sw::UndoRedoContext & rContext) 2982 { 2983 SwDoc *const pDoc = & rContext.GetDoc(); 2984 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 2985 2986 pPam->DeleteMark(); 2987 SwNodeIndex& rIdx = pPam->GetPoint()->nNode; 2988 rIdx = nTblNode + nOffset; 2989 2990 //Den implizit erzeugten Absatz wieder entfernen. 2991 pDoc->GetNodes().Delete( rIdx, 1 ); 2992 2993 rIdx = nTblNode + nOffset; 2994 SwTableNode* pTblNd = rIdx.GetNode().GetTableNode(); 2995 SwTable& rTbl = pTblNd->GetTable(); 2996 2997 SwTableFmlUpdate aMsgHnt( &rTbl ); 2998 aMsgHnt.eFlags = TBL_BOXPTR; 2999 pDoc->UpdateTblFlds( &aMsgHnt ); 3000 3001 switch( nMode ) 3002 { 3003 case HEADLINE_BOXATRCOLLCOPY: 3004 if( pHistory ) 3005 pHistory->TmpRollback( pDoc, nFmlEnd ); 3006 3007 // kein break 3008 case HEADLINE_BOXATTRCOPY: 3009 case HEADLINE_BORDERCOPY: 3010 { 3011 pSavTbl->CreateNew( rTbl, sal_False ); 3012 pSavTbl->RestoreAttr( rTbl ); 3013 } 3014 break; 3015 3016 case HEADLINE_CNTNTCOPY: 3017 // die erzeugte 1. Line muss wieder entfernt werden 3018 { 3019 SwSelBoxes aSelBoxes; 3020 SwTableBox* pBox = rTbl.GetTblBox( nTblNode + nOffset + 1 ); 3021 rTbl.SelLineFromBox( pBox, aSelBoxes, sal_True ); 3022 _FndBox aTmpBox( 0, 0 ); 3023 aTmpBox.SetTableLines( aSelBoxes, rTbl ); 3024 aTmpBox.DelFrms( rTbl ); 3025 rTbl.DeleteSel( pDoc, aSelBoxes, 0, 0, sal_False, sal_False ); 3026 } 3027 break; 3028 } 3029 3030 pDoc->GetNodes().MergeTable( rIdx ); 3031 3032 if( pHistory ) 3033 { 3034 pHistory->TmpRollback( pDoc, 0 ); 3035 pHistory->SetTmpEnd( pHistory->Count() ); 3036 } 3037 if( mpSaveRowSpan ) 3038 { 3039 pTblNd = rIdx.GetNode().FindTableNode(); 3040 if( pTblNd ) 3041 pTblNd->GetTable().RestoreRowSpan( *mpSaveRowSpan ); 3042 } 3043 ClearFEShellTabCols(); 3044 } 3045 3046 void SwUndoSplitTbl::RedoImpl(::sw::UndoRedoContext & rContext) 3047 { 3048 SwDoc *const pDoc = & rContext.GetDoc(); 3049 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 3050 3051 pPam->DeleteMark(); 3052 pPam->GetPoint()->nNode = nTblNode; 3053 pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize ); 3054 3055 ClearFEShellTabCols(); 3056 } 3057 3058 void SwUndoSplitTbl::RepeatImpl(::sw::RepeatContext & rContext) 3059 { 3060 SwPaM *const pPam = & rContext.GetRepeatPaM(); 3061 SwDoc *const pDoc = & rContext.GetDoc(); 3062 3063 pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize ); 3064 ClearFEShellTabCols(); 3065 } 3066 3067 void SwUndoSplitTbl::SaveFormula( SwHistory& rHistory ) 3068 { 3069 if( !pHistory ) 3070 pHistory = new SwHistory; 3071 3072 nFmlEnd = rHistory.Count(); 3073 pHistory->Move( 0, &rHistory ); 3074 } 3075 3076 3077 ////////////////////////////////////////////////////////////////////////// 3078 3079 SwUndoMergeTbl::SwUndoMergeTbl( const SwTableNode& rTblNd, 3080 const SwTableNode& rDelTblNd, 3081 sal_Bool bWithPrv, sal_uInt16 nMd ) 3082 : SwUndo( UNDO_MERGE_TABLE ), pSavTbl( 0 ), 3083 pHistory( 0 ), nMode( nMd ), bWithPrev( bWithPrv ) 3084 { 3085 // Endnode der letzen Tabellenzelle merken, die auf der Position verbleibt 3086 if( bWithPrev ) 3087 nTblNode = rDelTblNd.EndOfSectionIndex() - 1; 3088 else 3089 nTblNode = rTblNd.EndOfSectionIndex() - 1; 3090 3091 aName = rDelTblNd.GetTable().GetFrmFmt()->GetName(); 3092 pSavTbl = new _SaveTable( rDelTblNd.GetTable() ); 3093 3094 pSavHdl = bWithPrev ? new _SaveTable( rTblNd.GetTable(), 1 ) : 0; 3095 } 3096 3097 SwUndoMergeTbl::~SwUndoMergeTbl() 3098 { 3099 delete pSavTbl; 3100 delete pSavHdl; 3101 delete pHistory; 3102 } 3103 3104 void SwUndoMergeTbl::UndoImpl(::sw::UndoRedoContext & rContext) 3105 { 3106 SwDoc *const pDoc = & rContext.GetDoc(); 3107 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 3108 3109 pPam->DeleteMark(); 3110 SwNodeIndex& rIdx = pPam->GetPoint()->nNode; 3111 rIdx = nTblNode; 3112 3113 SwTableNode* pTblNd = rIdx.GetNode().FindTableNode(); 3114 SwTable* pTbl = &pTblNd->GetTable(); 3115 3116 SwTableFmlUpdate aMsgHnt( pTbl ); 3117 aMsgHnt.eFlags = TBL_BOXPTR; 3118 pDoc->UpdateTblFlds( &aMsgHnt ); 3119 3120 //Lines fuer das Layout-Update herausuchen. 3121 _FndBox aFndBox( 0, 0 ); 3122 aFndBox.SetTableLines( *pTbl ); 3123 aFndBox.DelFrms( *pTbl ); 3124 // ? TL_CHART2: notification or locking of controller required ? 3125 3126 SwTableNode* pNew = pDoc->GetNodes().SplitTable( rIdx, sal_True, sal_False ); 3127 3128 //Layout updaten 3129 aFndBox.MakeFrms( *pTbl ); 3130 // ? TL_CHART2: notification or locking of controller required ? 3131 3132 if( bWithPrev ) 3133 { 3134 // den Namen umsetzen 3135 pNew->GetTable().GetFrmFmt()->SetName( pTbl->GetFrmFmt()->GetName() ); 3136 pSavHdl->RestoreAttr( pNew->GetTable() ); 3137 } 3138 else 3139 pTbl = &pNew->GetTable(); 3140 pTbl->GetFrmFmt()->SetName( aName ); 3141 3142 // pSavTbl->CreateNew( *pTbl, sal_False ); 3143 pSavTbl->RestoreAttr( *pTbl ); 3144 3145 3146 if( pHistory ) 3147 { 3148 pHistory->TmpRollback( pDoc, 0 ); 3149 pHistory->SetTmpEnd( pHistory->Count() ); 3150 } 3151 3152 // fuer die neue Tabelle die Frames anlegen 3153 SwNodeIndex aTmpIdx( *pNew ); 3154 pNew->MakeFrms( &aTmpIdx ); 3155 3156 // Cursor irgendwo in den Content stellen 3157 SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &rIdx ); 3158 pPam->GetPoint()->nContent.Assign( pCNd, 0 ); 3159 3160 ClearFEShellTabCols(); 3161 3162 // TL_CHART2: need to inform chart of probably changed cell names 3163 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); 3164 if (pPCD) 3165 { 3166 pDoc->UpdateCharts( pTbl->GetFrmFmt()->GetName() ); 3167 pDoc->UpdateCharts( pNew->GetTable().GetFrmFmt()->GetName() ); 3168 } 3169 } 3170 3171 void SwUndoMergeTbl::RedoImpl(::sw::UndoRedoContext & rContext) 3172 { 3173 SwDoc *const pDoc = & rContext.GetDoc(); 3174 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 3175 3176 pPam->DeleteMark(); 3177 pPam->GetPoint()->nNode = nTblNode; 3178 if( bWithPrev ) 3179 pPam->GetPoint()->nNode = nTblNode + 3; 3180 else 3181 pPam->GetPoint()->nNode = nTblNode; 3182 3183 pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode ); 3184 3185 ClearFEShellTabCols(); 3186 } 3187 3188 void SwUndoMergeTbl::RepeatImpl(::sw::RepeatContext & rContext) 3189 { 3190 SwDoc *const pDoc = & rContext.GetDoc(); 3191 SwPaM *const pPam = & rContext.GetRepeatPaM(); 3192 3193 pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode ); 3194 ClearFEShellTabCols(); 3195 } 3196 3197 void SwUndoMergeTbl::SaveFormula( SwHistory& rHistory ) 3198 { 3199 if( !pHistory ) 3200 pHistory = new SwHistory; 3201 pHistory->Move( 0, &rHistory ); 3202 } 3203 3204 3205 ////////////////////////////////////////////////////////////////////////// 3206 3207 void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos ) 3208 { 3209 sal_uInt16 nO = rArr.Count(), nM, nU = 0; 3210 if( nO > 0 ) 3211 { 3212 nO--; 3213 while( nU <= nO ) 3214 { 3215 nM = nU + ( nO - nU ) / 2; 3216 if( *(rArr.GetData() + nM) == nIdx ) 3217 { 3218 ASSERT( sal_False, "Index ist schon vorhanden, darf nie sein!" ); 3219 return; 3220 } 3221 if( *(rArr.GetData() + nM) < nIdx ) 3222 nU = nM + 1; 3223 else if( nM == 0 ) 3224 break; 3225 else 3226 nO = nM - 1; 3227 } 3228 } 3229 rArr.Insert( nIdx, nU ); 3230 if( pInsPos ) 3231 *pInsPos = nU; 3232 } 3233 3234 void InsertSort( SvULongs& rArr, sal_uLong nIdx, sal_uInt16* pInsPos ) 3235 { 3236 sal_uInt16 nO = rArr.Count(), nM, nU = 0; 3237 if( nO > 0 ) 3238 { 3239 nO--; 3240 while( nU <= nO ) 3241 { 3242 nM = nU + ( nO - nU ) / 2; 3243 if( *(rArr.GetData() + nM) == nIdx ) 3244 { 3245 ASSERT( sal_False, "Index ist schon vorhanden, darf nie sein!" ); 3246 return; 3247 } 3248 if( *(rArr.GetData() + nM) < nIdx ) 3249 nU = nM + 1; 3250 else if( nM == 0 ) 3251 break; 3252 else 3253 nO = nM - 1; 3254 } 3255 } 3256 rArr.Insert( nIdx, nU ); 3257 if( pInsPos ) 3258 *pInsPos = nU; 3259 } 3260 3261 #if defined( JP_DEBUG ) && defined(DBG_UTIL) 3262 3263 3264 void DumpDoc( SwDoc* pDoc, const String& rFileNm ) 3265 { 3266 Writer* pWrt = SwIoSystem::GetWriter( "DEBUG" ); 3267 if( pWrt ) 3268 { 3269 SvFileStream aStream( rFileNm, STREAM_STD_WRITE ); 3270 SwPaM* pPam = new SwPaM( pDoc, SwPosition( pDoc->GetNodes().EndOfContent , 3271 pDoc->GetNodes().EndOfContent )); 3272 pPam->Move( fnMoveBackward, fnGoDoc ); 3273 pPam->SetMark(); 3274 pPam->Move( fnMoveForward, fnGoDoc ); 3275 3276 pWrt->Write( pPam, *pDoc, aStream, rFileNm.GetStr() ); 3277 3278 delete pPam; 3279 } 3280 } 3281 void CheckTable( const SwTable& rTbl ) 3282 { 3283 const SwNodes& rNds = rTbl.GetFrmFmt()->GetDoc()->GetNodes(); 3284 const SwTableSortBoxes& rSrtArr = pTblNd->GetTable().GetTabSortBoxes(); 3285 for( sal_uInt16 n = 0; n < rSrtArr.Count(); ++n ) 3286 { 3287 const SwTableBox* pBox = rSrtArr[ n ]; 3288 const SwNode* pNd = pBox->GetSttNd(); 3289 ASSERT( rNds[ *pBox->GetSttIdx() ] == pNd, "Box mit falchem StartNode" ); 3290 } 3291 } 3292 #endif 3293 3294 3295