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