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->RstTxtAttr( aTmpIdx, pTxtNd->GetTxt().Len() - nDelPos + 1 ); 2115 // das Trennzeichen loeschen 2116 pTxtNd->EraseText( aTmpIdx, 1 ); 2117 } 2118 DUMPDOC( &rDoc, String( "d:\\tmp\\tab_") + String( aNewSttNds.Count() - i ) + 2119 String(".db") ) 2120 } 2121 nIdx = pBox->GetSttIdx(); 2122 } 2123 else 2124 pBox = pTblNd->GetTable().GetTblBox( nIdx ); 2125 2126 if( !pSaveTbl->IsNewModel() ) 2127 { 2128 // TL_CHART2: notify chart about box to be removed 2129 if (pPCD) 2130 pPCD->DeleteBox( &pTblNd->GetTable(), *pBox ); 2131 2132 SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes(); 2133 pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) ); 2134 2135 2136 // Indizies aus dem Bereich loeschen 2137 { 2138 SwNodeIndex aTmpIdx( *pBox->GetSttNd() ); 2139 rDoc.CorrAbs( SwNodeIndex( aTmpIdx, 1 ), 2140 SwNodeIndex( *aTmpIdx.GetNode().EndOfSectionNode() ), 2141 SwPosition( aTmpIdx, SwIndex( 0, 0 )), sal_True ); 2142 } 2143 2144 delete pBox; 2145 rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] ); 2146 } 2147 } 2148 DUMPDOC( &rDoc, "d:\\tmp\\tab_z.db" ) 2149 CHECKTABLE(pTblNd->GetTable()) 2150 2151 2152 pSaveTbl->CreateNew( pTblNd->GetTable(), sal_True, sal_False ); 2153 2154 // TL_CHART2: need to inform chart of probably changed cell names 2155 rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() ); 2156 2157 if( pHistory ) 2158 { 2159 pHistory->TmpRollback( &rDoc, 0 ); 2160 pHistory->SetTmpEnd( pHistory->Count() ); 2161 } 2162 // nTblNode = pTblNd->GetIndex(); 2163 2164 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 2165 pPam->DeleteMark(); 2166 pPam->GetPoint()->nNode = nSttNode; 2167 pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), nSttCntnt ); 2168 pPam->SetMark(); 2169 pPam->DeleteMark(); 2170 2171 CHECKTABLE(pTblNd->GetTable()) 2172 ClearFEShellTabCols(); 2173 } 2174 2175 void SwUndoTblMerge::RedoImpl(::sw::UndoRedoContext & rContext) 2176 { 2177 SwDoc & rDoc = rContext.GetDoc(); 2178 SwPaM & rPam( AddUndoRedoPaM(rContext) ); 2179 rDoc.MergeTbl(rPam); 2180 } 2181 2182 void SwUndoTblMerge::MoveBoxCntnt( SwDoc* pDoc, SwNodeRange& rRg, SwNodeIndex& rPos ) 2183 { 2184 SwNodeIndex aTmp( rRg.aStart, -1 ), aTmp2( rPos, -1 ); 2185 SwUndoMove* pUndo = new SwUndoMove( pDoc, rRg, rPos ); 2186 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo()); 2187 pDoc->MoveNodeRange( rRg, rPos, (pSaveTbl->IsNewModel()) ? 2188 IDocumentContentOperations::DOC_NO_DELFRMS : 2189 IDocumentContentOperations::DOC_MOVEDEFAULT ); 2190 aTmp++; 2191 aTmp2++; 2192 pUndo->SetDestRange( aTmp2, rPos, aTmp ); 2193 2194 pMoves->Insert( pUndo, pMoves->Count() ); 2195 } 2196 2197 void SwUndoTblMerge::SetSelBoxes( const SwSelBoxes& rBoxes ) 2198 { 2199 // die Selektion merken 2200 for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n ) 2201 InsertSort( aBoxes, rBoxes[n]->GetSttIdx() ); 2202 2203 // als Trennung fuers einfuegen neuer Boxen nach dem Verschieben! 2204 aNewSttNds.Insert( (sal_uLong)0, aNewSttNds.Count() ); 2205 2206 // The new table model does not delete overlapped cells (by row span), 2207 // so the rBoxes array might be empty even some cells have been merged. 2208 if( rBoxes.Count() ) 2209 nTblNode = rBoxes[ 0 ]->GetSttNd()->FindTableNode()->GetIndex(); 2210 } 2211 2212 void SwUndoTblMerge::SaveCollection( const SwTableBox& rBox ) 2213 { 2214 if( !pHistory ) 2215 pHistory = new SwHistory; 2216 2217 SwNodeIndex aIdx( *rBox.GetSttNd(), 1 ); 2218 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode(); 2219 if( !pCNd ) 2220 pCNd = aIdx.GetNodes().GoNext( &aIdx ); 2221 2222 pHistory->Add( pCNd->GetFmtColl(), aIdx.GetIndex(), pCNd->GetNodeType()); 2223 if( pCNd->HasSwAttrSet() ) 2224 pHistory->CopyFmtAttr( *pCNd->GetpSwAttrSet(), aIdx.GetIndex() ); 2225 } 2226 2227 2228 ////////////////////////////////////////////////////////////////////////// 2229 2230 SwUndoTblNumFmt::SwUndoTblNumFmt( const SwTableBox& rBox, 2231 const SfxItemSet* pNewSet ) 2232 : SwUndo( UNDO_TBLNUMFMT ), 2233 pBoxSet( 0 ), pHistory( 0 ), nFmtIdx( NUMBERFORMAT_TEXT ) 2234 { 2235 bNewFmt = bNewFml = bNewValue = sal_False; 2236 nNode = rBox.GetSttIdx(); 2237 2238 nNdPos = rBox.IsValidNumTxtNd( 0 == pNewSet ); 2239 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc(); 2240 2241 if( ULONG_MAX != nNdPos ) 2242 { 2243 SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode(); 2244 2245 pHistory = new SwHistory; 2246 SwRegHistory aRHst( *rBox.GetSttNd(), pHistory ); 2247 // always save all text atttibutes because of possibly overlapping 2248 // areas of on/off 2249 pHistory->CopyAttr( pTNd->GetpSwpHints(), nNdPos, 0, 2250 pTNd->GetTxt().Len(), true ); 2251 2252 if( pTNd->HasSwAttrSet() ) 2253 pHistory->CopyFmtAttr( *pTNd->GetpSwAttrSet(), nNdPos ); 2254 2255 aStr = pTNd->GetTxt(); 2256 if( pTNd->GetpSwpHints() ) 2257 pTNd->GetpSwpHints()->DeRegister(); 2258 } 2259 2260 pBoxSet = new SfxItemSet( pDoc->GetAttrPool(), aTableBoxSetRange ); 2261 pBoxSet->Put( rBox.GetFrmFmt()->GetAttrSet() ); 2262 2263 if( pNewSet ) 2264 { 2265 const SfxPoolItem* pItem; 2266 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMAT, 2267 sal_False, &pItem )) 2268 { 2269 bNewFmt = sal_True; 2270 nNewFmtIdx = ((SwTblBoxNumFormat*)pItem)->GetValue(); 2271 } 2272 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMULA, 2273 sal_False, &pItem )) 2274 { 2275 bNewFml = sal_True; 2276 aNewFml = ((SwTblBoxFormula*)pItem)->GetFormula(); 2277 } 2278 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_VALUE, 2279 sal_False, &pItem )) 2280 { 2281 bNewValue = sal_True; 2282 fNewNum = ((SwTblBoxValue*)pItem)->GetValue(); 2283 } 2284 } 2285 2286 // wird die History ueberhaupt benoetigt ?? 2287 if( pHistory && !pHistory->Count() ) 2288 DELETEZ( pHistory ); 2289 } 2290 2291 SwUndoTblNumFmt::~SwUndoTblNumFmt() 2292 { 2293 delete pHistory; 2294 delete pBoxSet; 2295 } 2296 2297 void SwUndoTblNumFmt::UndoImpl(::sw::UndoRedoContext & rContext) 2298 { 2299 ASSERT( pBoxSet, "Where's the stored item set?" ) 2300 2301 SwDoc & rDoc = rContext.GetDoc(); 2302 SwStartNode* pSttNd = rDoc.GetNodes()[ nNode ]-> 2303 FindSttNodeByType( SwTableBoxStartNode ); 2304 ASSERT( pSttNd, "ohne StartNode kein TabellenBox" ); 2305 SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox( 2306 pSttNd->GetIndex() ); 2307 ASSERT( pBox, "keine TabellenBox gefunden" ); 2308 2309 SwTableBoxFmt* pFmt = rDoc.MakeTableBoxFmt(); 2310 pFmt->SetFmtAttr( *pBoxSet ); 2311 pBox->ChgFrmFmt( pFmt ); 2312 2313 if( ULONG_MAX == nNdPos ) 2314 return; 2315 2316 SwTxtNode* pTxtNd = rDoc.GetNodes()[ nNdPos ]->GetTxtNode(); 2317 // wenn mehr als ein Node geloescht wurde, dann wurden auch 2318 // alle "Node"-Attribute gespeichert 2319 if( pTxtNd->HasSwAttrSet() ) 2320 pTxtNd->ResetAllAttr(); 2321 2322 if( pTxtNd->GetpSwpHints() && aStr.Len() ) 2323 pTxtNd->ClearSwpHintsArr( true ); 2324 2325 // ChgTextToNum(..) only acts when the strings are different. We 2326 // need to do the same here. 2327 if( pTxtNd->GetTxt() != aStr ) 2328 { 2329 rDoc.DeleteRedline( *( pBox->GetSttNd() ), false, USHRT_MAX ); 2330 2331 SwIndex aIdx( pTxtNd, 0 ); 2332 if( aStr.Len() ) 2333 { 2334 pTxtNd->EraseText( aIdx ); 2335 pTxtNd->InsertText( aStr, aIdx, 2336 IDocumentContentOperations::INS_NOHINTEXPAND ); 2337 } 2338 } 2339 2340 if( pHistory ) 2341 { 2342 sal_uInt16 nTmpEnd = pHistory->GetTmpEnd(); 2343 pHistory->TmpRollback( &rDoc, 0 ); 2344 pHistory->SetTmpEnd( nTmpEnd ); 2345 } 2346 2347 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 2348 pPam->DeleteMark(); 2349 pPam->GetPoint()->nNode = nNode + 1; 2350 pPam->GetPoint()->nContent.Assign( pTxtNd, 0 ); 2351 } 2352 2353 /** switch the RedlineMode on the given document, using 2354 * SetRedlineMode_intern. This class set the mode in the constructor, 2355 * and changes it back in the destructor, i.e. it uses the 2356 * initialization-is-resource-acquisition idiom. 2357 */ 2358 class RedlineModeInternGuard 2359 { 2360 SwDoc& mrDoc; 2361 RedlineMode_t meOldRedlineMode; 2362 2363 public: 2364 RedlineModeInternGuard( 2365 SwDoc& rDoc, /// change mode of this document 2366 RedlineMode_t eNewRedlineMode, /// new redline mode 2367 RedlineMode_t eRedlineModeMask = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE /*change only bits set in this mask*/)); 2368 2369 ~RedlineModeInternGuard(); 2370 }; 2371 2372 RedlineModeInternGuard::RedlineModeInternGuard( 2373 SwDoc& rDoc, 2374 RedlineMode_t eNewRedlineMode, 2375 RedlineMode_t eRedlineModeMask ) 2376 : mrDoc( rDoc ), 2377 meOldRedlineMode( rDoc.GetRedlineMode() ) 2378 { 2379 mrDoc.SetRedlineMode_intern((RedlineMode_t)( ( meOldRedlineMode & ~eRedlineModeMask ) | 2380 ( eNewRedlineMode & eRedlineModeMask ) )); 2381 } 2382 2383 RedlineModeInternGuard::~RedlineModeInternGuard() 2384 { 2385 mrDoc.SetRedlineMode_intern( meOldRedlineMode ); 2386 } 2387 2388 2389 2390 void SwUndoTblNumFmt::RedoImpl(::sw::UndoRedoContext & rContext) 2391 { 2392 // konnte die Box veraendert werden ? 2393 if( !pBoxSet ) 2394 return ; 2395 2396 SwDoc & rDoc = rContext.GetDoc(); 2397 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 2398 2399 pPam->DeleteMark(); 2400 pPam->GetPoint()->nNode = nNode; 2401 2402 SwNode * pNd = & pPam->GetPoint()->nNode.GetNode(); 2403 SwStartNode* pSttNd = pNd->FindSttNodeByType( SwTableBoxStartNode ); 2404 ASSERT( pSttNd, "ohne StartNode kein TabellenBox" ); 2405 SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox( 2406 pSttNd->GetIndex() ); 2407 ASSERT( pBox, "keine TabellenBox gefunden" ); 2408 2409 SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt(); 2410 if( bNewFmt || bNewFml || bNewValue ) 2411 { 2412 SfxItemSet aBoxSet( rDoc.GetAttrPool(), 2413 RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2414 2415 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht. 2416 // Sorge dafuer, das der Text auch entsprechend 2417 // formatiert wird! 2418 pBoxFmt->LockModify(); 2419 2420 if( bNewFml ) 2421 aBoxSet.Put( SwTblBoxFormula( aNewFml )); 2422 else 2423 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA ); 2424 if( bNewFmt ) 2425 aBoxSet.Put( SwTblBoxNumFormat( nNewFmtIdx )); 2426 else 2427 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT ); 2428 if( bNewValue ) 2429 aBoxSet.Put( SwTblBoxValue( fNewNum )); 2430 else 2431 pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE ); 2432 pBoxFmt->UnlockModify(); 2433 2434 // dvo: When redlining is (was) enabled, setting the attribute 2435 // will also change the cell content. To allow this, the 2436 // REDLINE_IGNORE flag must be removed during Redo. #108450# 2437 RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE ); 2438 pBoxFmt->SetFmtAttr( aBoxSet ); 2439 } 2440 else if( NUMBERFORMAT_TEXT != nFmtIdx ) 2441 { 2442 SfxItemSet aBoxSet( rDoc.GetAttrPool(), 2443 RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2444 2445 aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx )); 2446 aBoxSet.Put( SwTblBoxValue( fNum )); 2447 2448 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht. 2449 // Sorge dafuer, das der Text auch entsprechend 2450 // formatiert wird! 2451 pBoxFmt->LockModify(); 2452 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA ); 2453 pBoxFmt->UnlockModify(); 2454 2455 // dvo: When redlining is (was) enabled, setting the attribute 2456 // will also change the cell content. To allow this, the 2457 // REDLINE_IGNORE flag must be removed during Redo. #108450# 2458 RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE ); 2459 pBoxFmt->SetFmtAttr( aBoxSet ); 2460 } 2461 else 2462 { 2463 // es ist keine Zahl 2464 2465 // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht. 2466 // Sorge dafuer, das der Text auch entsprechend 2467 // formatiert wird! 2468 pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT )); 2469 2470 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2471 } 2472 2473 if( bNewFml ) 2474 { 2475 // egal was gesetzt wurde, ein Update der Tabelle macht sich immer gut 2476 SwTableFmlUpdate aTblUpdate( &pSttNd->FindTableNode()->GetTable() ); 2477 rDoc.UpdateTblFlds( &aTblUpdate ); 2478 } 2479 2480 if( !pNd->IsCntntNode() ) 2481 pNd = rDoc.GetNodes().GoNext( &pPam->GetPoint()->nNode ); 2482 pPam->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 ); 2483 } 2484 2485 void SwUndoTblNumFmt::SetBox( const SwTableBox& rBox ) 2486 { 2487 nNode = rBox.GetSttIdx(); 2488 } 2489 2490 2491 ////////////////////////////////////////////////////////////////////////// 2492 2493 _UndoTblCpyTbl_Entry::_UndoTblCpyTbl_Entry( const SwTableBox& rBox ) 2494 : nBoxIdx( rBox.GetSttIdx() ), nOffset( 0 ), 2495 pBoxNumAttr( 0 ), pUndo( 0 ), bJoin( false ) 2496 { 2497 } 2498 2499 _UndoTblCpyTbl_Entry::~_UndoTblCpyTbl_Entry() 2500 { 2501 delete pUndo; 2502 delete pBoxNumAttr; 2503 } 2504 2505 2506 SwUndoTblCpyTbl::SwUndoTblCpyTbl() 2507 : SwUndo( UNDO_TBLCPYTBL ), pInsRowUndo( 0 ) 2508 { 2509 pArr = new _UndoTblCpyTbl_Entries; 2510 } 2511 2512 SwUndoTblCpyTbl::~SwUndoTblCpyTbl() 2513 { 2514 delete pArr; 2515 delete pInsRowUndo; 2516 } 2517 2518 void SwUndoTblCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext) 2519 { 2520 SwDoc & rDoc = rContext.GetDoc(); 2521 _DEBUG_REDLINE( &rDoc ) 2522 2523 SwTableNode* pTblNd = 0; 2524 for( sal_uInt16 n = pArr->Count(); n; ) 2525 { 2526 _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ --n ]; 2527 sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset; 2528 SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode(); 2529 if( !pTblNd ) 2530 pTblNd = pSNd->FindTableNode(); 2531 2532 SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos ); 2533 2534 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 ); 2535 rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() ); 2536 2537 // b62341295: Redline for copying tables 2538 const SwNode *pEndNode = rBox.GetSttNd()->EndOfSectionNode(); 2539 SwPaM aPam( aInsIdx.GetNode(), *pEndNode ); 2540 SwUndoDelete* pUndo = 0; 2541 2542 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ) 2543 { 2544 bool bDeleteCompleteParagraph = false; 2545 bool bShiftPam = false; 2546 // There are a couple of different situations to consider during redlining 2547 if( pEntry->pUndo ) 2548 { 2549 SwUndoDelete *const pUndoDelete = 2550 dynamic_cast<SwUndoDelete*>(pEntry->pUndo); 2551 SwUndoRedlineDelete *const pUndoRedlineDelete = 2552 dynamic_cast<SwUndoRedlineDelete*>(pEntry->pUndo); 2553 OSL_ASSERT(pUndoDelete || pUndoRedlineDelete); 2554 if (pUndoRedlineDelete) 2555 { 2556 // The old content was not empty or he has been merged with the new content 2557 bDeleteCompleteParagraph = !pEntry->bJoin; // bJoin is set when merged 2558 // Set aTmpIdx to the beginning fo the old content 2559 SwNodeIndex aTmpIdx( *pEndNode, 2560 pUndoRedlineDelete->NodeDiff()-1 ); 2561 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode(); 2562 if( pTxt ) 2563 { 2564 aPam.GetPoint()->nNode = *pTxt; 2565 aPam.GetPoint()->nContent.Assign( pTxt, 2566 pUndoRedlineDelete->ContentStart() ); 2567 } 2568 else 2569 *aPam.GetPoint() = SwPosition( aTmpIdx ); 2570 } 2571 else if (pUndoDelete && pUndoDelete->IsDelFullPara()) 2572 { 2573 // When the old content was an empty paragraph, but could not be joined 2574 // with the new content (e.g. because of a section or table) 2575 // We "save" the aPam.Point, we go one step backwards (because later on the 2576 // empty paragraph will be inserted by the undo) and set the "ShiftPam-flag 2577 // for step forward later on. 2578 bDeleteCompleteParagraph = true; 2579 bShiftPam = true; 2580 SwNodeIndex aTmpIdx( *pEndNode, -1 ); 2581 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode(); 2582 if( pTxt ) 2583 { 2584 aPam.GetPoint()->nNode = *pTxt; 2585 aPam.GetPoint()->nContent.Assign( pTxt, 0 ); 2586 } 2587 else 2588 *aPam.GetPoint() = SwPosition( aTmpIdx ); 2589 } 2590 } 2591 rDoc.DeleteRedline( aPam, true, USHRT_MAX ); 2592 2593 if( pEntry->pUndo ) 2594 { 2595 pEntry->pUndo->UndoImpl(rContext); 2596 delete pEntry->pUndo; 2597 pEntry->pUndo = 0; 2598 } 2599 if( bShiftPam ) 2600 { 2601 // The aPam.Point is at the moment at the last position of the new content and has to be 2602 // moved to the first postion of the old content for the SwUndoDelete operation 2603 SwNodeIndex aTmpIdx( aPam.GetPoint()->nNode, 1 ); 2604 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode(); 2605 if( pTxt ) 2606 { 2607 aPam.GetPoint()->nNode = *pTxt; 2608 aPam.GetPoint()->nContent.Assign( pTxt, 0 ); 2609 } 2610 else 2611 *aPam.GetPoint() = SwPosition( aTmpIdx ); 2612 } 2613 pUndo = new SwUndoDelete( aPam, bDeleteCompleteParagraph, sal_True ); 2614 } 2615 else 2616 { 2617 pUndo = new SwUndoDelete( aPam, true ); 2618 if( pEntry->pUndo ) 2619 { 2620 pEntry->pUndo->UndoImpl(rContext); 2621 delete pEntry->pUndo; 2622 pEntry->pUndo = 0; 2623 } 2624 } 2625 pEntry->pUndo = pUndo; 2626 2627 aInsIdx = rBox.GetSttIdx() + 1; 2628 rDoc.GetNodes().Delete( aInsIdx, 1 ); 2629 2630 SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2631 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2632 aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() ); 2633 if( aTmpSet.Count() ) 2634 { 2635 SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt(); 2636 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2637 pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT ); 2638 } 2639 2640 if( pEntry->pBoxNumAttr ) 2641 { 2642 rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr ); 2643 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0; 2644 } 2645 2646 if( aTmpSet.Count() ) 2647 { 2648 pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(), 2649 RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2650 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2651 pEntry->pBoxNumAttr->Put( aTmpSet ); 2652 } 2653 2654 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx; 2655 } 2656 2657 if( pInsRowUndo ) 2658 { 2659 pInsRowUndo->UndoImpl(rContext); 2660 } 2661 _DEBUG_REDLINE( &rDoc ) 2662 } 2663 2664 void SwUndoTblCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext) 2665 { 2666 SwDoc & rDoc = rContext.GetDoc(); 2667 _DEBUG_REDLINE( &rDoc ) 2668 2669 if( pInsRowUndo ) 2670 { 2671 pInsRowUndo->RedoImpl(rContext); 2672 } 2673 2674 SwTableNode* pTblNd = 0; 2675 for( sal_uInt16 n = 0; n < pArr->Count(); ++n ) 2676 { 2677 _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ n ]; 2678 sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset; 2679 SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode(); 2680 if( !pTblNd ) 2681 pTblNd = pSNd->FindTableNode(); 2682 2683 SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos ); 2684 2685 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 ); 2686 2687 // b62341295: Redline for copying tables - Start. 2688 rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() ); 2689 SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode()); 2690 SwUndo* pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ? 0 : new SwUndoDelete( aPam, sal_True ); 2691 if( pEntry->pUndo ) 2692 { 2693 pEntry->pUndo->UndoImpl(rContext); 2694 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ) 2695 { 2696 // PrepareRedline has to be called with the beginning of the old content 2697 // When new and old content has been joined, the rIter.pAktPam has been set 2698 // by the Undo operation to this point. 2699 // Otherwise aInsIdx has been moved during the Undo operation 2700 if( pEntry->bJoin ) 2701 { 2702 SwPaM const& rLastPam = 2703 rContext.GetCursorSupplier().GetCurrentShellCursor(); 2704 pUndo = PrepareRedline( &rDoc, rBox, *rLastPam.GetPoint(), 2705 pEntry->bJoin, true ); 2706 } 2707 else 2708 { 2709 SwPosition aTmpPos( aInsIdx ); 2710 pUndo = PrepareRedline( &rDoc, rBox, aTmpPos, pEntry->bJoin, true ); 2711 } 2712 } 2713 delete pEntry->pUndo; 2714 pEntry->pUndo = 0; 2715 } 2716 pEntry->pUndo = pUndo; 2717 // b62341295: Redline for copying tables - End. 2718 2719 aInsIdx = rBox.GetSttIdx() + 1; 2720 rDoc.GetNodes().Delete( aInsIdx, 1 ); 2721 2722 SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2723 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2724 aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() ); 2725 if( aTmpSet.Count() ) 2726 { 2727 SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt(); 2728 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE ); 2729 pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT ); 2730 } 2731 if( pEntry->pBoxNumAttr ) 2732 { 2733 rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr ); 2734 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0; 2735 } 2736 2737 if( aTmpSet.Count() ) 2738 { 2739 pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(), 2740 RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2741 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2742 pEntry->pBoxNumAttr->Put( aTmpSet ); 2743 } 2744 2745 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx; 2746 } 2747 _DEBUG_REDLINE( &rDoc ) 2748 } 2749 2750 void SwUndoTblCpyTbl::AddBoxBefore( const SwTableBox& rBox, sal_Bool bDelCntnt ) 2751 { 2752 if( pArr->Count() && !bDelCntnt ) 2753 return; 2754 2755 _UndoTblCpyTbl_Entry* pEntry = new _UndoTblCpyTbl_Entry( rBox ); 2756 pArr->Insert( pEntry, pArr->Count() ); 2757 2758 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc(); 2759 _DEBUG_REDLINE( pDoc ) 2760 if( bDelCntnt ) 2761 { 2762 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 ); 2763 pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() ); 2764 SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() ); 2765 2766 if( !pDoc->IsRedlineOn() ) 2767 pEntry->pUndo = new SwUndoDelete( aPam, sal_True ); 2768 } 2769 2770 pEntry->pBoxNumAttr = new SfxItemSet( pDoc->GetAttrPool(), 2771 RES_BOXATR_FORMAT, RES_BOXATR_VALUE, 2772 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 ); 2773 pEntry->pBoxNumAttr->Put( rBox.GetFrmFmt()->GetAttrSet() ); 2774 if( !pEntry->pBoxNumAttr->Count() ) 2775 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0; 2776 _DEBUG_REDLINE( pDoc ) 2777 } 2778 2779 void SwUndoTblCpyTbl::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx, sal_Bool bDelCntnt ) 2780 { 2781 _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ pArr->Count() - 1 ]; 2782 2783 // wurde der Inhalt geloescht, so loesche jetzt auch noch den temp. 2784 // erzeugten Node 2785 if( bDelCntnt ) 2786 { 2787 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc(); 2788 _DEBUG_REDLINE( pDoc ) 2789 2790 if( pDoc->IsRedlineOn() ) 2791 { 2792 SwPosition aTmpPos( rIdx ); 2793 pEntry->pUndo = PrepareRedline( pDoc, rBox, aTmpPos, pEntry->bJoin, false ); 2794 } 2795 SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 ); 2796 rBox.GetFrmFmt()->GetDoc()->GetNodes().Delete( aDelIdx, 1 ); 2797 _DEBUG_REDLINE( pDoc ) 2798 } 2799 2800 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx; 2801 } 2802 2803 // PrepareRedline is called from AddBoxAfter() and from Redo() in slightly different situations. 2804 // bRedo is set by calling from Redo() 2805 // rJoin is false by calling from AddBoxAfter() and will be set if the old and new content has 2806 // been merged. 2807 // rJoin is true if Redo() is calling and the content has already been merged 2808 2809 SwUndo* SwUndoTblCpyTbl::PrepareRedline( SwDoc* pDoc, const SwTableBox& rBox, 2810 const SwPosition& rPos, bool& rJoin, bool bRedo ) 2811 { 2812 SwUndo *pUndo = 0; 2813 // b62341295: Redline for copying tables 2814 // What's to do? 2815 // Mark the cell content before rIdx as insertion, 2816 // mark the cell content behind rIdx as deletion 2817 // merge text nodes at rIdx if possible 2818 RedlineMode_t eOld = pDoc->GetRedlineMode(); 2819 pDoc->SetRedlineMode_intern((RedlineMode_t)( ( eOld | nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) & 2820 ~nsRedlineMode_t::REDLINE_IGNORE )); 2821 SwPosition aInsertEnd( rPos ); 2822 SwTxtNode* pTxt; 2823 if( !rJoin ) 2824 { 2825 // If the content is not merged, the end of the insertion is at the end of the node 2826 // _before_ the given position rPos 2827 --aInsertEnd.nNode; 2828 pTxt = aInsertEnd.nNode.GetNode().GetTxtNode(); 2829 if( pTxt ) 2830 { 2831 aInsertEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() ); 2832 if( !bRedo && rPos.nNode.GetNode().GetTxtNode() ) 2833 { // Try to merge, if not called by Redo() 2834 rJoin = true; 2835 pTxt->JoinNext(); 2836 } 2837 } 2838 else 2839 aInsertEnd.nContent = SwIndex( 0 ); 2840 } 2841 // For joined (merged) contents the start of deletionm and end of insertion are identical 2842 // otherwise adjacent nodes. 2843 SwPosition aDeleteStart( rJoin ? aInsertEnd : rPos ); 2844 if( !rJoin ) 2845 { 2846 pTxt = aDeleteStart.nNode.GetNode().GetTxtNode(); 2847 if( pTxt ) 2848 aDeleteStart.nContent.Assign( pTxt, 0 ); 2849 } 2850 SwPosition aCellEnd( SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode(), -1 ) ); 2851 pTxt = aCellEnd.nNode.GetNode().GetTxtNode(); 2852 if( pTxt ) 2853 aCellEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() ); 2854 if( aDeleteStart != aCellEnd ) 2855 { // If the old (deleted) part is not empty, here we are... 2856 SwPaM aDeletePam( aDeleteStart, aCellEnd ); 2857 pUndo = new SwUndoRedlineDelete( aDeletePam, UNDO_DELETE ); 2858 pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDeletePam ), true ); 2859 } 2860 else if( !rJoin ) // If the old part is empty and joined, we are finished 2861 { // if it is not joined, we have to delete this empty paragraph 2862 aCellEnd = SwPosition( 2863 SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() )); 2864 SwPaM aTmpPam( aDeleteStart, aCellEnd ); 2865 pUndo = new SwUndoDelete( aTmpPam, sal_True ); 2866 } 2867 SwPosition aCellStart( SwNodeIndex( *rBox.GetSttNd(), 2 ) ); 2868 pTxt = aCellStart.nNode.GetNode().GetTxtNode(); 2869 if( pTxt ) 2870 aCellStart.nContent.Assign( pTxt, 0 ); 2871 if( aCellStart != aInsertEnd ) // An empty insertion will not been marked 2872 { 2873 SwPaM aTmpPam( aCellStart, aInsertEnd ); 2874 pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aTmpPam ), true ); 2875 } 2876 2877 pDoc->SetRedlineMode_intern( eOld ); 2878 return pUndo; 2879 } 2880 2881 2882 sal_Bool SwUndoTblCpyTbl::InsertRow( SwTable& rTbl, const SwSelBoxes& rBoxes, 2883 sal_uInt16 nCnt ) 2884 { 2885 SwTableNode* pTblNd = (SwTableNode*)rTbl.GetTabSortBoxes()[0]-> 2886 GetSttNd()->FindTableNode(); 2887 2888 SwTableSortBoxes aTmpLst( 0, 5 ); 2889 pInsRowUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW, rBoxes, *pTblNd, 2890 0, 0, nCnt, sal_True, sal_False ); 2891 aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() ); 2892 2893 sal_Bool bRet = rTbl.InsertRow( rTbl.GetFrmFmt()->GetDoc(), rBoxes, nCnt, sal_True ); 2894 if( bRet ) 2895 pInsRowUndo->SaveNewBoxes( *pTblNd, aTmpLst ); 2896 else 2897 delete pInsRowUndo, pInsRowUndo = 0; 2898 return bRet; 2899 } 2900 2901 sal_Bool SwUndoTblCpyTbl::IsEmpty() const 2902 { 2903 return !pInsRowUndo && !pArr->Count(); 2904 } 2905 2906 2907 ////////////////////////////////////////////////////////////////////////// 2908 2909 SwUndoCpyTbl::SwUndoCpyTbl() 2910 : SwUndo( UNDO_CPYTBL ), pDel( 0 ), nTblNode( 0 ) 2911 { 2912 } 2913 2914 SwUndoCpyTbl::~SwUndoCpyTbl() 2915 { 2916 delete pDel; 2917 } 2918 2919 void SwUndoCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext) 2920 { 2921 SwDoc & rDoc = rContext.GetDoc(); 2922 SwTableNode* pTNd = rDoc.GetNodes()[ nTblNode ]->GetTableNode(); 2923 2924 // harte SeitenUmbrueche am nachfolgenden Node verschieben 2925 SwCntntNode* pNextNd = rDoc.GetNodes()[ pTNd->EndOfSectionIndex()+1 ]->GetCntntNode(); 2926 if( pNextNd ) 2927 { 2928 SwFrmFmt* pTableFmt = pTNd->GetTable().GetFrmFmt(); 2929 const SfxPoolItem *pItem; 2930 2931 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC, 2932 sal_False, &pItem ) ) 2933 pNextNd->SetAttr( *pItem ); 2934 2935 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK, 2936 sal_False, &pItem ) ) 2937 pNextNd->SetAttr( *pItem ); 2938 } 2939 2940 SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 ); 2941 pDel = new SwUndoDelete( aPam, sal_True ); 2942 } 2943 2944 void SwUndoCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext) 2945 { 2946 pDel->UndoImpl(rContext); 2947 delete pDel, pDel = 0; 2948 } 2949 2950 2951 ////////////////////////////////////////////////////////////////////////// 2952 2953 SwUndoSplitTbl::SwUndoSplitTbl( const SwTableNode& rTblNd, 2954 SwSaveRowSpan* pRowSp, sal_uInt16 eMode, sal_Bool bNewSize ) 2955 : SwUndo( UNDO_SPLIT_TABLE ), 2956 nTblNode( rTblNd.GetIndex() ), nOffset( 0 ), mpSaveRowSpan( pRowSp ), pSavTbl( 0 ), 2957 pHistory( 0 ), nMode( eMode ), nFmlEnd( 0 ), bCalcNewSize( bNewSize ) 2958 { 2959 switch( nMode ) 2960 { 2961 case HEADLINE_BOXATRCOLLCOPY: 2962 pHistory = new SwHistory; 2963 // kein break; 2964 case HEADLINE_BORDERCOPY: 2965 case HEADLINE_BOXATTRCOPY: 2966 pSavTbl = new _SaveTable( rTblNd.GetTable(), 1, sal_False ); 2967 break; 2968 } 2969 } 2970 2971 SwUndoSplitTbl::~SwUndoSplitTbl() 2972 { 2973 delete pSavTbl; 2974 delete pHistory; 2975 delete mpSaveRowSpan; 2976 } 2977 2978 void SwUndoSplitTbl::UndoImpl(::sw::UndoRedoContext & rContext) 2979 { 2980 SwDoc *const pDoc = & rContext.GetDoc(); 2981 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 2982 2983 pPam->DeleteMark(); 2984 SwNodeIndex& rIdx = pPam->GetPoint()->nNode; 2985 rIdx = nTblNode + nOffset; 2986 2987 //Den implizit erzeugten Absatz wieder entfernen. 2988 pDoc->GetNodes().Delete( rIdx, 1 ); 2989 2990 rIdx = nTblNode + nOffset; 2991 SwTableNode* pTblNd = rIdx.GetNode().GetTableNode(); 2992 SwTable& rTbl = pTblNd->GetTable(); 2993 2994 SwTableFmlUpdate aMsgHnt( &rTbl ); 2995 aMsgHnt.eFlags = TBL_BOXPTR; 2996 pDoc->UpdateTblFlds( &aMsgHnt ); 2997 2998 switch( nMode ) 2999 { 3000 case HEADLINE_BOXATRCOLLCOPY: 3001 if( pHistory ) 3002 pHistory->TmpRollback( pDoc, nFmlEnd ); 3003 3004 // kein break 3005 case HEADLINE_BOXATTRCOPY: 3006 case HEADLINE_BORDERCOPY: 3007 { 3008 pSavTbl->CreateNew( rTbl, sal_False ); 3009 pSavTbl->RestoreAttr( rTbl ); 3010 } 3011 break; 3012 3013 case HEADLINE_CNTNTCOPY: 3014 // die erzeugte 1. Line muss wieder entfernt werden 3015 { 3016 SwSelBoxes aSelBoxes; 3017 SwTableBox* pBox = rTbl.GetTblBox( nTblNode + nOffset + 1 ); 3018 rTbl.SelLineFromBox( pBox, aSelBoxes, sal_True ); 3019 _FndBox aTmpBox( 0, 0 ); 3020 aTmpBox.SetTableLines( aSelBoxes, rTbl ); 3021 aTmpBox.DelFrms( rTbl ); 3022 rTbl.DeleteSel( pDoc, aSelBoxes, 0, 0, sal_False, sal_False ); 3023 } 3024 break; 3025 } 3026 3027 pDoc->GetNodes().MergeTable( rIdx ); 3028 3029 if( pHistory ) 3030 { 3031 pHistory->TmpRollback( pDoc, 0 ); 3032 pHistory->SetTmpEnd( pHistory->Count() ); 3033 } 3034 if( mpSaveRowSpan ) 3035 { 3036 pTblNd = rIdx.GetNode().FindTableNode(); 3037 if( pTblNd ) 3038 pTblNd->GetTable().RestoreRowSpan( *mpSaveRowSpan ); 3039 } 3040 ClearFEShellTabCols(); 3041 } 3042 3043 void SwUndoSplitTbl::RedoImpl(::sw::UndoRedoContext & rContext) 3044 { 3045 SwDoc *const pDoc = & rContext.GetDoc(); 3046 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 3047 3048 pPam->DeleteMark(); 3049 pPam->GetPoint()->nNode = nTblNode; 3050 pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize ); 3051 3052 ClearFEShellTabCols(); 3053 } 3054 3055 void SwUndoSplitTbl::RepeatImpl(::sw::RepeatContext & rContext) 3056 { 3057 SwPaM *const pPam = & rContext.GetRepeatPaM(); 3058 SwDoc *const pDoc = & rContext.GetDoc(); 3059 3060 pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize ); 3061 ClearFEShellTabCols(); 3062 } 3063 3064 void SwUndoSplitTbl::SaveFormula( SwHistory& rHistory ) 3065 { 3066 if( !pHistory ) 3067 pHistory = new SwHistory; 3068 3069 nFmlEnd = rHistory.Count(); 3070 pHistory->Move( 0, &rHistory ); 3071 } 3072 3073 3074 ////////////////////////////////////////////////////////////////////////// 3075 3076 SwUndoMergeTbl::SwUndoMergeTbl( const SwTableNode& rTblNd, 3077 const SwTableNode& rDelTblNd, 3078 sal_Bool bWithPrv, sal_uInt16 nMd ) 3079 : SwUndo( UNDO_MERGE_TABLE ), pSavTbl( 0 ), 3080 pHistory( 0 ), nMode( nMd ), bWithPrev( bWithPrv ) 3081 { 3082 // Endnode der letzen Tabellenzelle merken, die auf der Position verbleibt 3083 if( bWithPrev ) 3084 nTblNode = rDelTblNd.EndOfSectionIndex() - 1; 3085 else 3086 nTblNode = rTblNd.EndOfSectionIndex() - 1; 3087 3088 aName = rDelTblNd.GetTable().GetFrmFmt()->GetName(); 3089 pSavTbl = new _SaveTable( rDelTblNd.GetTable() ); 3090 3091 pSavHdl = bWithPrev ? new _SaveTable( rTblNd.GetTable(), 1 ) : 0; 3092 } 3093 3094 SwUndoMergeTbl::~SwUndoMergeTbl() 3095 { 3096 delete pSavTbl; 3097 delete pSavHdl; 3098 delete pHistory; 3099 } 3100 3101 void SwUndoMergeTbl::UndoImpl(::sw::UndoRedoContext & rContext) 3102 { 3103 SwDoc *const pDoc = & rContext.GetDoc(); 3104 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 3105 3106 pPam->DeleteMark(); 3107 SwNodeIndex& rIdx = pPam->GetPoint()->nNode; 3108 rIdx = nTblNode; 3109 3110 SwTableNode* pTblNd = rIdx.GetNode().FindTableNode(); 3111 SwTable* pTbl = &pTblNd->GetTable(); 3112 3113 SwTableFmlUpdate aMsgHnt( pTbl ); 3114 aMsgHnt.eFlags = TBL_BOXPTR; 3115 pDoc->UpdateTblFlds( &aMsgHnt ); 3116 3117 //Lines fuer das Layout-Update herausuchen. 3118 _FndBox aFndBox( 0, 0 ); 3119 aFndBox.SetTableLines( *pTbl ); 3120 aFndBox.DelFrms( *pTbl ); 3121 // ? TL_CHART2: notification or locking of controller required ? 3122 3123 SwTableNode* pNew = pDoc->GetNodes().SplitTable( rIdx, sal_True, sal_False ); 3124 3125 //Layout updaten 3126 aFndBox.MakeFrms( *pTbl ); 3127 // ? TL_CHART2: notification or locking of controller required ? 3128 3129 if( bWithPrev ) 3130 { 3131 // den Namen umsetzen 3132 pNew->GetTable().GetFrmFmt()->SetName( pTbl->GetFrmFmt()->GetName() ); 3133 pSavHdl->RestoreAttr( pNew->GetTable() ); 3134 } 3135 else 3136 pTbl = &pNew->GetTable(); 3137 pTbl->GetFrmFmt()->SetName( aName ); 3138 3139 // pSavTbl->CreateNew( *pTbl, sal_False ); 3140 pSavTbl->RestoreAttr( *pTbl ); 3141 3142 3143 if( pHistory ) 3144 { 3145 pHistory->TmpRollback( pDoc, 0 ); 3146 pHistory->SetTmpEnd( pHistory->Count() ); 3147 } 3148 3149 // fuer die neue Tabelle die Frames anlegen 3150 SwNodeIndex aTmpIdx( *pNew ); 3151 pNew->MakeFrms( &aTmpIdx ); 3152 3153 // Cursor irgendwo in den Content stellen 3154 SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &rIdx ); 3155 pPam->GetPoint()->nContent.Assign( pCNd, 0 ); 3156 3157 ClearFEShellTabCols(); 3158 3159 // TL_CHART2: need to inform chart of probably changed cell names 3160 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider(); 3161 if (pPCD) 3162 { 3163 pDoc->UpdateCharts( pTbl->GetFrmFmt()->GetName() ); 3164 pDoc->UpdateCharts( pNew->GetTable().GetFrmFmt()->GetName() ); 3165 } 3166 } 3167 3168 void SwUndoMergeTbl::RedoImpl(::sw::UndoRedoContext & rContext) 3169 { 3170 SwDoc *const pDoc = & rContext.GetDoc(); 3171 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor()); 3172 3173 pPam->DeleteMark(); 3174 pPam->GetPoint()->nNode = nTblNode; 3175 if( bWithPrev ) 3176 pPam->GetPoint()->nNode = nTblNode + 3; 3177 else 3178 pPam->GetPoint()->nNode = nTblNode; 3179 3180 pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode ); 3181 3182 ClearFEShellTabCols(); 3183 } 3184 3185 void SwUndoMergeTbl::RepeatImpl(::sw::RepeatContext & rContext) 3186 { 3187 SwDoc *const pDoc = & rContext.GetDoc(); 3188 SwPaM *const pPam = & rContext.GetRepeatPaM(); 3189 3190 pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode ); 3191 ClearFEShellTabCols(); 3192 } 3193 3194 void SwUndoMergeTbl::SaveFormula( SwHistory& rHistory ) 3195 { 3196 if( !pHistory ) 3197 pHistory = new SwHistory; 3198 pHistory->Move( 0, &rHistory ); 3199 } 3200 3201 3202 ////////////////////////////////////////////////////////////////////////// 3203 3204 void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos ) 3205 { 3206 sal_uInt16 nO = rArr.Count(), nM, nU = 0; 3207 if( nO > 0 ) 3208 { 3209 nO--; 3210 while( nU <= nO ) 3211 { 3212 nM = nU + ( nO - nU ) / 2; 3213 if( *(rArr.GetData() + nM) == nIdx ) 3214 { 3215 ASSERT( sal_False, "Index ist schon vorhanden, darf nie sein!" ); 3216 return; 3217 } 3218 if( *(rArr.GetData() + nM) < nIdx ) 3219 nU = nM + 1; 3220 else if( nM == 0 ) 3221 break; 3222 else 3223 nO = nM - 1; 3224 } 3225 } 3226 rArr.Insert( nIdx, nU ); 3227 if( pInsPos ) 3228 *pInsPos = nU; 3229 } 3230 3231 void InsertSort( SvULongs& rArr, sal_uLong nIdx, sal_uInt16* pInsPos ) 3232 { 3233 sal_uInt16 nO = rArr.Count(), nM, nU = 0; 3234 if( nO > 0 ) 3235 { 3236 nO--; 3237 while( nU <= nO ) 3238 { 3239 nM = nU + ( nO - nU ) / 2; 3240 if( *(rArr.GetData() + nM) == nIdx ) 3241 { 3242 ASSERT( sal_False, "Index ist schon vorhanden, darf nie sein!" ); 3243 return; 3244 } 3245 if( *(rArr.GetData() + nM) < nIdx ) 3246 nU = nM + 1; 3247 else if( nM == 0 ) 3248 break; 3249 else 3250 nO = nM - 1; 3251 } 3252 } 3253 rArr.Insert( nIdx, nU ); 3254 if( pInsPos ) 3255 *pInsPos = nU; 3256 } 3257 3258 #if defined( JP_DEBUG ) && defined(DBG_UTIL) 3259 3260 3261 void DumpDoc( SwDoc* pDoc, const String& rFileNm ) 3262 { 3263 Writer* pWrt = SwIoSystem::GetWriter( "DEBUG" ); 3264 if( pWrt ) 3265 { 3266 SvFileStream aStream( rFileNm, STREAM_STD_WRITE ); 3267 SwPaM* pPam = new SwPaM( pDoc, SwPosition( pDoc->GetNodes().EndOfContent , 3268 pDoc->GetNodes().EndOfContent )); 3269 pPam->Move( fnMoveBackward, fnGoDoc ); 3270 pPam->SetMark(); 3271 pPam->Move( fnMoveForward, fnGoDoc ); 3272 3273 pWrt->Write( pPam, *pDoc, aStream, rFileNm.GetStr() ); 3274 3275 delete pPam; 3276 } 3277 } 3278 void CheckTable( const SwTable& rTbl ) 3279 { 3280 const SwNodes& rNds = rTbl.GetFrmFmt()->GetDoc()->GetNodes(); 3281 const SwTableSortBoxes& rSrtArr = pTblNd->GetTable().GetTabSortBoxes(); 3282 for( sal_uInt16 n = 0; n < rSrtArr.Count(); ++n ) 3283 { 3284 const SwTableBox* pBox = rSrtArr[ n ]; 3285 const SwNode* pNd = pBox->GetSttNd(); 3286 ASSERT( rNds[ *pBox->GetSttIdx() ] == pNd, "Box mit falchem StartNode" ); 3287 } 3288 } 3289 #endif 3290 3291 3292