update credits
[LibreOffice.git] / sw / source / core / undo / untbl.cxx
blob4ed6fa724a0ef01c5bcc1d8f7408f6f51dceb48c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <vector>
22 #include <boost/shared_ptr.hpp>
24 #include <UndoTable.hxx>
25 #include <UndoRedline.hxx>
26 #include <UndoDelete.hxx>
27 #include <UndoSplitMove.hxx>
28 #include <UndoCore.hxx>
29 #include <hintids.hxx>
30 #include <hints.hxx>
31 #include <editeng/formatbreakitem.hxx>
32 #include <fmtornt.hxx>
33 #include <fmtpdsc.hxx>
34 #include <doc.hxx>
35 #include <IDocumentUndoRedo.hxx>
36 #include <editsh.hxx>
37 #include <docary.hxx>
38 #include <ndtxt.hxx>
39 #include <swtable.hxx>
40 #include <pam.hxx>
41 #include <cntfrm.hxx>
42 #include <tblsel.hxx>
43 #include <swundo.hxx>
44 #include <rolbck.hxx>
45 #include <ddefld.hxx>
46 #include <tabcol.hxx>
47 #include <tabfrm.hxx>
48 #include <rowfrm.hxx>
49 #include <cellfrm.hxx>
50 #include <swcache.hxx>
51 #include <tblafmt.hxx>
52 #include <poolfmt.hxx>
53 #include <mvsave.hxx>
54 #include <cellatr.hxx>
55 #include <swtblfmt.hxx>
56 #include <swddetbl.hxx>
57 #include <redline.hxx>
58 #include <node2lay.hxx>
59 #include <tblrwcl.hxx>
60 #include <fmtanchr.hxx>
61 #include <comcore.hrc>
62 #include <unochart.hxx>
63 #include <switerator.hxx>
65 #ifdef DBG_UTIL
66 #define CHECK_TABLE(t) (t).CheckConsistency();
67 #else
68 #define CHECK_TABLE(t)
69 #endif
71 #ifdef DBG_UTIL
72 void sw_DebugRedline( const SwDoc* pDoc ); // docredln.cxx
73 #define _DEBUG_REDLINE( pDoc ) sw_DebugRedline( pDoc );
74 #else
75 #define _DEBUG_REDLINE( pDoc )
76 #endif
78 extern void ClearFEShellTabCols();
80 typedef std::vector<boost::shared_ptr<SfxItemSet> > SfxItemSets;
82 class SwUndoSaveSections : public boost::ptr_vector<SwUndoSaveSection> {
83 public:
84 SwUndoSaveSections(size_type n) : boost::ptr_vector<SwUndoSaveSection>(n) {}
87 class SwUndoMoves : public boost::ptr_vector<SwUndoMove> {};
89 struct SwTblToTxtSave;
90 class SwTblToTxtSaves : public boost::ptr_vector<SwTblToTxtSave> {
91 public:
92 SwTblToTxtSaves(size_type n) : boost::ptr_vector<SwTblToTxtSave>(n) {}
95 struct _UndoTblCpyTbl_Entry
97 sal_uLong nBoxIdx, nOffset;
98 SfxItemSet* pBoxNumAttr;
99 SwUndo* pUndo;
101 // Was the last paragraph of the new and the first paragraph of the old content joined?
102 bool bJoin; // For redlining only
104 _UndoTblCpyTbl_Entry( const SwTableBox& rBox );
105 ~_UndoTblCpyTbl_Entry();
107 class _UndoTblCpyTbl_Entries : public boost::ptr_vector<_UndoTblCpyTbl_Entry> {};
109 class _SaveBox;
110 class _SaveLine;
112 class _SaveTable
114 friend class _SaveBox;
115 friend class _SaveLine;
116 SfxItemSet aTblSet;
117 _SaveLine* pLine;
118 const SwTable* pSwTable;
119 SfxItemSets aSets;
120 SwFrmFmts aFrmFmts;
121 sal_uInt16 nLineCount;
122 bool bModifyBox : 1;
123 bool bSaveFormula : 1;
124 bool bNewModel : 1;
126 public:
127 _SaveTable( const SwTable& rTbl, sal_uInt16 nLnCnt = USHRT_MAX,
128 bool bSaveFml = true );
129 ~_SaveTable();
131 sal_uInt16 AddFmt( SwFrmFmt* pFmt, bool bIsLine );
132 void NewFrmFmt( const SwTableLine* , const SwTableBox*, sal_uInt16 nFmtPos,
133 SwFrmFmt* pOldFmt );
135 void RestoreAttr( SwTable& rTbl, bool bModifyBox = false );
136 void SaveCntntAttrs( SwDoc* pDoc );
137 void CreateNew( SwTable& rTbl, bool bCreateFrms = true,
138 bool bRestoreChart = true );
139 bool IsNewModel() const { return bNewModel; }
142 class _SaveLine
144 friend class _SaveTable;
145 friend class _SaveBox;
147 _SaveLine* pNext;
148 _SaveBox* pBox;
149 sal_uInt16 nItemSet;
151 public:
152 _SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl );
153 ~_SaveLine();
155 void RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl );
156 void SaveCntntAttrs( SwDoc* pDoc );
158 void CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl );
161 class _SaveBox
163 friend class _SaveLine;
165 _SaveBox* pNext;
166 sal_uLong nSttNode;
167 long nRowSpan;
168 sal_uInt16 nItemSet;
169 union
171 SfxItemSets* pCntntAttrs;
172 _SaveLine* pLine;
173 } Ptrs;
175 public:
176 _SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl );
177 ~_SaveBox();
179 void RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl );
180 void SaveCntntAttrs( SwDoc* pDoc );
182 void CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl );
185 void InsertSort( std::vector<sal_uInt16>& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 );
187 #if OSL_DEBUG_LEVEL > 0
188 #include "shellio.hxx"
189 void CheckTable( const SwTable& );
190 #define CHECKTABLE(t) CheckTable( t );
191 #else
192 #define CHECKTABLE(t)
193 #endif
195 /* #130880: Crash in undo of table to text when the table has (freshly) merged cells
196 The order of cell content nodes in the nodes array is not given by the recursive table structure.
197 The algorithmn must not rely on this even it holds for a fresh loaded table in odt file format.
198 So we need to remember not only the start node position but the end node position as well.
201 struct SwTblToTxtSave
203 sal_uLong m_nSttNd;
204 sal_uLong m_nEndNd;
205 xub_StrLen m_nCntnt;
206 SwHistory* m_pHstry;
207 // metadata references for first and last paragraph in cell
208 ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
209 ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
211 SwTblToTxtSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, xub_StrLen nCntnt );
212 ~SwTblToTxtSave() { delete m_pHstry; }
215 sal_uInt16 aSave_BoxCntntSet[] = {
216 RES_CHRATR_COLOR, RES_CHRATR_CROSSEDOUT,
217 RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
218 RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
219 RES_CHRATR_SHADOWED, RES_CHRATR_WEIGHT,
220 RES_PARATR_ADJUST, RES_PARATR_ADJUST,
221 0 };
223 SwUndoInsTbl::SwUndoInsTbl( const SwPosition& rPos, sal_uInt16 nCl, sal_uInt16 nRw,
224 sal_uInt16 nAdj, const SwInsertTableOptions& rInsTblOpts,
225 const SwTableAutoFmt* pTAFmt,
226 const std::vector<sal_uInt16> *pColArr,
227 const String & rName)
228 : SwUndo( UNDO_INSTABLE ),
229 aInsTblOpts( rInsTblOpts ), pDDEFldType( 0 ), pColWidth( 0 ), pRedlData( 0 ), pAutoFmt( 0 ),
230 nSttNode( rPos.nNode.GetIndex() ), nRows( nRw ), nCols( nCl ), nAdjust( nAdj )
232 if( pColArr )
234 pColWidth = new std::vector<sal_uInt16>(*pColArr);
236 if( pTAFmt )
237 pAutoFmt = new SwTableAutoFmt( *pTAFmt );
239 // consider redline
240 SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc();
241 if( rDoc.IsRedlineOn() )
243 pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
244 SetRedlineMode( rDoc.GetRedlineMode() );
247 sTblNm = rName;
250 SwUndoInsTbl::~SwUndoInsTbl()
252 delete pDDEFldType;
253 delete pColWidth;
254 delete pRedlData;
255 delete pAutoFmt;
258 void SwUndoInsTbl::UndoImpl(::sw::UndoRedoContext & rContext)
260 SwDoc & rDoc = rContext.GetDoc();
261 SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
263 SwTableNode* pTblNd = aIdx.GetNode().GetTableNode();
264 OSL_ENSURE( pTblNd, "no TableNode" );
265 pTblNd->DelFrms();
267 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
268 rDoc.DeleteRedline( *pTblNd, true, USHRT_MAX );
269 RemoveIdxFromSection( rDoc, nSttNode );
271 // move hard page breaks into next node
272 SwCntntNode* pNextNd = rDoc.GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
273 if( pNextNd )
275 SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
276 const SfxPoolItem *pItem;
278 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
279 sal_False, &pItem ) )
280 pNextNd->SetAttr( *pItem );
282 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
283 sal_False, &pItem ) )
284 pNextNd->SetAttr( *pItem );
288 sTblNm = pTblNd->GetTable().GetFrmFmt()->GetName();
289 if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) )
290 pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()).
291 GetDDEFldType()->Copy();
293 rDoc.GetNodes().Delete( aIdx, pTblNd->EndOfSectionIndex() -
294 aIdx.GetIndex() + 1 );
296 SwPaM & rPam( rContext.GetCursorSupplier().CreateNewShellCursor() );
297 rPam.DeleteMark();
298 rPam.GetPoint()->nNode = aIdx;
299 rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
302 void SwUndoInsTbl::RedoImpl(::sw::UndoRedoContext & rContext)
304 SwDoc & rDoc = rContext.GetDoc();
306 SwPosition const aPos(SwNodeIndex(rDoc.GetNodes(), nSttNode));
307 const SwTable* pTbl = rDoc.InsertTable( aInsTblOpts, aPos, nRows, nCols,
308 nAdjust,
309 pAutoFmt, pColWidth );
310 ((SwFrmFmt*)pTbl->GetFrmFmt())->SetName( sTblNm );
311 SwTableNode* pTblNode = (SwTableNode*)rDoc.GetNodes()[nSttNode]->GetTableNode();
313 if( pDDEFldType )
315 SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
316 *pDDEFldType);
317 SwDDETable* pDDETbl = new SwDDETable( pTblNode->GetTable(), pNewType );
318 pTblNode->SetNewTable( pDDETbl );
319 delete pDDEFldType, pDDEFldType = 0;
322 if( (pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) ||
323 ( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
324 !rDoc.GetRedlineTbl().empty() ))
326 SwPaM aPam( *pTblNode->EndOfSectionNode(), *pTblNode, 1 );
327 SwCntntNode* pCNd = aPam.GetCntntNode( sal_False );
328 if( pCNd )
329 aPam.GetMark()->nContent.Assign( pCNd, 0 );
331 if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
333 RedlineMode_t eOld = rDoc.GetRedlineMode();
334 rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
336 rDoc.AppendRedline( new SwRedline( *pRedlData, aPam ), true);
337 rDoc.SetRedlineMode_intern( eOld );
339 else
340 rDoc.SplitRedline( aPam );
344 void SwUndoInsTbl::RepeatImpl(::sw::RepeatContext & rContext)
346 rContext.GetDoc().InsertTable(
347 aInsTblOpts, *rContext.GetRepeatPaM().GetPoint(),
348 nRows, nCols, nAdjust, pAutoFmt, pColWidth );
351 SwRewriter SwUndoInsTbl::GetRewriter() const
353 SwRewriter aRewriter;
355 aRewriter.AddRule(UndoArg1, SW_RES(STR_START_QUOTE));
356 aRewriter.AddRule(UndoArg2, sTblNm);
357 aRewriter.AddRule(UndoArg3, SW_RES(STR_END_QUOTE));
359 return aRewriter;
362 SwTblToTxtSave::SwTblToTxtSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, xub_StrLen nCnt )
363 : m_nSttNd( nNd ), m_nEndNd( nEndIdx), m_nCntnt( nCnt ), m_pHstry( 0 )
365 // keep attributes of the joined node
366 SwTxtNode* pNd = rDoc.GetNodes()[ nNd ]->GetTxtNode();
367 if( pNd )
369 m_pHstry = new SwHistory;
371 m_pHstry->Add( pNd->GetTxtColl(), nNd, ND_TEXTNODE );
372 if ( pNd->GetpSwpHints() )
374 m_pHstry->CopyAttr( pNd->GetpSwpHints(), nNd, 0,
375 pNd->GetTxt().getLength(), false );
377 if( pNd->HasSwAttrSet() )
378 m_pHstry->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNd );
380 if( !m_pHstry->Count() )
381 delete m_pHstry, m_pHstry = 0;
383 // METADATA: store
384 m_pMetadataUndoStart = pNd->CreateUndo();
387 // we also need to store the metadata reference of the _last_ paragraph
388 // we subtract 1 to account for the removed cell start/end node pair
389 // (after SectionUp, the end of the range points to the node after the cell)
390 if ( nEndIdx - 1 > nNd )
392 SwTxtNode* pLastNode( rDoc.GetNodes()[ nEndIdx - 1 ]->GetTxtNode() );
393 if( pLastNode )
395 // METADATA: store
396 m_pMetadataUndoEnd = pLastNode->CreateUndo();
401 SwUndoTblToTxt::SwUndoTblToTxt( const SwTable& rTbl, sal_Unicode cCh )
402 : SwUndo( UNDO_TABLETOTEXT ),
403 sTblNm( rTbl.GetFrmFmt()->GetName() ), pDDEFldType( 0 ), pHistory( 0 ),
404 nSttNd( 0 ), nEndNd( 0 ),
405 nAdjust( static_cast<sal_uInt16>(rTbl.GetFrmFmt()->GetHoriOrient().GetHoriOrient()) ),
406 cTrenner( cCh ), nHdlnRpt( rTbl.GetRowsToRepeat() )
408 pTblSave = new _SaveTable( rTbl );
409 pBoxSaves = new SwTblToTxtSaves( (SwTblToTxtSaves::size_type)rTbl.GetTabSortBoxes().size() );
411 if( rTbl.IsA( TYPE( SwDDETable ) ) )
412 pDDEFldType = (SwDDEFieldType*)((SwDDETable&)rTbl).GetDDEFldType()->Copy();
414 bCheckNumFmt = rTbl.GetFrmFmt()->GetDoc()->IsInsTblFormatNum();
416 pHistory = new SwHistory;
417 const SwTableNode* pTblNd = rTbl.GetTableNode();
418 sal_uLong nTblStt = pTblNd->GetIndex(), nTblEnd = pTblNd->EndOfSectionIndex();
420 const SwFrmFmts& rFrmFmtTbl = *pTblNd->GetDoc()->GetSpzFrmFmts();
421 for( sal_uInt16 n = 0; n < rFrmFmtTbl.size(); ++n )
423 SwFrmFmt* pFmt = rFrmFmtTbl[ n ];
424 SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
425 SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
426 if (pAPos &&
427 ((FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
428 (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
429 nTblStt <= pAPos->nNode.GetIndex() &&
430 pAPos->nNode.GetIndex() < nTblEnd )
432 pHistory->Add( *pFmt );
436 if( !pHistory->Count() )
437 delete pHistory, pHistory = 0;
440 SwUndoTblToTxt::~SwUndoTblToTxt()
442 delete pDDEFldType;
443 delete pTblSave;
444 delete pBoxSaves;
445 delete pHistory;
448 void SwUndoTblToTxt::UndoImpl(::sw::UndoRedoContext & rContext)
450 SwDoc & rDoc = rContext.GetDoc();
451 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
453 SwNodeIndex aFrmIdx( rDoc.GetNodes(), nSttNd );
454 SwNodeIndex aEndIdx( rDoc.GetNodes(), nEndNd );
456 pPam->GetPoint()->nNode = aFrmIdx;
457 pPam->SetMark();
458 pPam->GetPoint()->nNode = aEndIdx;
459 rDoc.DelNumRules( *pPam );
460 pPam->DeleteMark();
462 // now collect all Uppers
463 SwNode2Layout aNode2Layout( aFrmIdx.GetNode() );
465 // create TableNode structure
466 SwTableNode* pTblNd = rDoc.GetNodes().UndoTableToText( nSttNd, nEndNd, *pBoxSaves );
467 pTblNd->GetTable().SetTableModel( pTblSave->IsNewModel() );
468 SwTableFmt* pTableFmt = rDoc.MakeTblFrmFmt( sTblNm, rDoc.GetDfltFrmFmt() );
469 pTblNd->GetTable().RegisterToFormat( *pTableFmt );
470 pTblNd->GetTable().SetRowsToRepeat( nHdlnRpt );
472 // create old table structure
473 pTblSave->CreateNew( pTblNd->GetTable() );
475 if( pDDEFldType )
477 SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
478 *pDDEFldType);
479 SwDDETable* pDDETbl = new SwDDETable( pTblNd->GetTable(), pNewType );
480 pTblNd->SetNewTable( pDDETbl, sal_False );
481 delete pDDEFldType, pDDEFldType = 0;
484 if( bCheckNumFmt )
486 SwTableSortBoxes& rBxs = pTblNd->GetTable().GetTabSortBoxes();
487 for (size_t nBoxes = rBxs.size(); nBoxes; )
489 rDoc.ChkBoxNumFmt( *rBxs[ --nBoxes ], sal_False );
493 if( pHistory )
495 sal_uInt16 nTmpEnd = pHistory->GetTmpEnd();
496 pHistory->TmpRollback( &rDoc, 0 );
497 pHistory->SetTmpEnd( nTmpEnd );
500 aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(),
501 pTblNd->GetIndex(), pTblNd->GetIndex()+1 );
503 // Is a table selection requested?
504 pPam->DeleteMark();
505 pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
506 pPam->SetMark();
507 pPam->GetPoint()->nNode = *pPam->GetNode()->StartOfSectionNode();
508 pPam->Move( fnMoveForward, fnGoCntnt );
509 pPam->Exchange();
510 pPam->Move( fnMoveBackward, fnGoCntnt );
512 ClearFEShellTabCols();
515 // located in untbl.cxx and only an Undo object is allowed to call it
516 SwTableNode* SwNodes::UndoTableToText( sal_uLong nSttNd, sal_uLong nEndNd,
517 const SwTblToTxtSaves& rSavedData )
519 SwNodeIndex aSttIdx( *this, nSttNd );
520 SwNodeIndex aEndIdx( *this, nEndNd+1 );
522 SwTableNode * pTblNd = new SwTableNode( aSttIdx );
523 SwEndNode* pEndNd = new SwEndNode( aEndIdx, *pTblNd );
525 aEndIdx = *pEndNd;
527 /* Set pTblNd as start of section for all nodes in [nSttNd, nEndNd].
528 Delete all Frames attached to the nodes in that range. */
529 SwNode* pNd;
531 sal_uLong n, nTmpEnd = aEndIdx.GetIndex();
532 for( n = pTblNd->GetIndex() + 1; n < nTmpEnd; ++n )
534 if( ( pNd = (*this)[ n ] )->IsCntntNode() )
535 ((SwCntntNode*)pNd)->DelFrms();
536 pNd->pStartOfSection = pTblNd;
540 // than create table structure partially. First a single line that contains
541 // all boxes. The correct structure is than taken from SaveStruct.
542 SwTableBoxFmt* pBoxFmt = GetDoc()->MakeTableBoxFmt();
543 SwTableLineFmt* pLineFmt = GetDoc()->MakeTableLineFmt();
544 SwTableLine* pLine = new SwTableLine( pLineFmt, rSavedData.size(), 0 );
545 pTblNd->GetTable().GetTabLines().insert( pTblNd->GetTable().GetTabLines().begin(), pLine );
547 std::vector<sal_uLong> aBkmkArr;
548 for( sal_uInt16 n = rSavedData.size(); n; )
550 const SwTblToTxtSave* pSave = &rSavedData[ --n ];
551 // if the start node was merged with last from prev. cell,
552 // subtract 1 from index to get the merged paragraph, and split that
553 aSttIdx = pSave->m_nSttNd - ( ( USHRT_MAX != pSave->m_nCntnt ) ? 1 : 0);
554 SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
556 if( USHRT_MAX != pSave->m_nCntnt )
558 // split at ContentPosition, delete previous char (= separator)
559 OSL_ENSURE( pTxtNd, "Where is my TextNode?" );
560 SwIndex aCntPos( pTxtNd, pSave->m_nCntnt - 1 );
562 pTxtNd->EraseText( aCntPos, 1 );
563 SwCntntNode* pNewNd = pTxtNd->SplitCntntNode(
564 SwPosition( aSttIdx, aCntPos ));
565 if( !aBkmkArr.empty() )
566 _RestoreCntntIdx( aBkmkArr, *pNewNd, pSave->m_nCntnt,
567 pSave->m_nCntnt + 1 );
569 else
571 aBkmkArr.clear();
572 if( pTxtNd )
573 _SaveCntntIdx( GetDoc(), aSttIdx.GetIndex(),
574 pTxtNd->GetTxt().getLength(), aBkmkArr );
577 if( pTxtNd )
579 // METADATA: restore
580 pTxtNd->GetTxtNode()->RestoreMetadata(pSave->m_pMetadataUndoStart);
581 if( pTxtNd->HasSwAttrSet() )
582 pTxtNd->ResetAllAttr();
584 if( pTxtNd->GetpSwpHints() )
585 pTxtNd->ClearSwpHintsArr( false );
588 if( pSave->m_pHstry )
590 sal_uInt16 nTmpEnd = pSave->m_pHstry->GetTmpEnd();
591 pSave->m_pHstry->TmpRollback( GetDoc(), 0 );
592 pSave->m_pHstry->SetTmpEnd( nTmpEnd );
595 // METADATA: restore
596 // end points to node after cell
597 if ( pSave->m_nEndNd - 1 > pSave->m_nSttNd )
599 SwTxtNode* pLastNode = (*this)[ pSave->m_nEndNd - 1 ]->GetTxtNode();
600 if (pLastNode)
602 pLastNode->RestoreMetadata(pSave->m_pMetadataUndoEnd);
606 aEndIdx = pSave->m_nEndNd;
607 SwStartNode* pSttNd = new SwStartNode( aSttIdx, ND_STARTNODE,
608 SwTableBoxStartNode );
609 pSttNd->pStartOfSection = pTblNd;
610 new SwEndNode( aEndIdx, *pSttNd );
612 for( sal_uLong i = aSttIdx.GetIndex(); i < aEndIdx.GetIndex()-1; ++i )
614 pNd = (*this)[ i ];
615 pNd->pStartOfSection = pSttNd;
616 if( pNd->IsStartNode() )
617 i = pNd->EndOfSectionIndex();
620 SwTableBox* pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
621 pLine->GetTabBoxes().insert( pLine->GetTabBoxes().begin(), pBox );
623 return pTblNd;
626 void SwUndoTblToTxt::RedoImpl(::sw::UndoRedoContext & rContext)
628 SwDoc & rDoc = rContext.GetDoc();
629 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
631 pPam->GetPoint()->nNode = nSttNd;
632 pPam->GetPoint()->nContent.Assign( 0, 0 );
633 SwNodeIndex aSaveIdx( pPam->GetPoint()->nNode, -1 );
635 pPam->SetMark(); // log off all indices
636 pPam->DeleteMark();
638 SwTableNode* pTblNd = pPam->GetNode()->GetTableNode();
639 OSL_ENSURE( pTblNd, "Could not find any TableNode" );
641 if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) )
642 pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()).
643 GetDDEFldType()->Copy();
645 rDoc.TableToText( pTblNd, cTrenner );
647 ++aSaveIdx;
648 SwCntntNode* pCNd = aSaveIdx.GetNode().GetCntntNode();
649 if( !pCNd && 0 == ( pCNd = rDoc.GetNodes().GoNext( &aSaveIdx ) ) &&
650 0 == ( pCNd = rDoc.GetNodes().GoPrevious( &aSaveIdx )) )
652 OSL_FAIL( "Where is the TextNode now?" );
655 pPam->GetPoint()->nNode = aSaveIdx;
656 pPam->GetPoint()->nContent.Assign( pCNd, 0 );
658 pPam->SetMark(); // log off all indices
659 pPam->DeleteMark();
662 void SwUndoTblToTxt::RepeatImpl(::sw::RepeatContext & rContext)
664 SwPaM *const pPam = & rContext.GetRepeatPaM();
665 SwTableNode *const pTblNd = pPam->GetNode()->FindTableNode();
666 if( pTblNd )
668 // move cursor out of table
669 pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
670 pPam->Move( fnMoveForward, fnGoCntnt );
671 pPam->SetMark();
672 pPam->DeleteMark();
674 rContext.GetDoc().TableToText( pTblNd, cTrenner );
678 void SwUndoTblToTxt::SetRange( const SwNodeRange& rRg )
680 nSttNd = rRg.aStart.GetIndex();
681 nEndNd = rRg.aEnd.GetIndex();
684 void SwUndoTblToTxt::AddBoxPos( SwDoc& rDoc, sal_uLong nNdIdx, sal_uLong nEndIdx, xub_StrLen nCntntIdx )
686 SwTblToTxtSave* pNew = new SwTblToTxtSave( rDoc, nNdIdx, nEndIdx, nCntntIdx );
687 pBoxSaves->push_back( pNew );
690 SwUndoTxtToTbl::SwUndoTxtToTbl( const SwPaM& rRg,
691 const SwInsertTableOptions& rInsTblOpts,
692 sal_Unicode cCh, sal_uInt16 nAdj,
693 const SwTableAutoFmt* pAFmt )
694 : SwUndo( UNDO_TEXTTOTABLE ), SwUndRng( rRg ), aInsTblOpts( rInsTblOpts ),
695 pDelBoxes( 0 ), pAutoFmt( 0 ),
696 pHistory( 0 ), cTrenner( cCh ), nAdjust( nAdj )
698 if( pAFmt )
699 pAutoFmt = new SwTableAutoFmt( *pAFmt );
701 const SwPosition* pEnd = rRg.End();
702 SwNodes& rNds = rRg.GetDoc()->GetNodes();
703 bSplitEnd = pEnd->nContent.GetIndex() && ( pEnd->nContent.GetIndex()
704 != pEnd->nNode.GetNode().GetCntntNode()->Len() ||
705 pEnd->nNode.GetIndex() >= rNds.GetEndOfContent().GetIndex()-1 );
708 SwUndoTxtToTbl::~SwUndoTxtToTbl()
710 delete pDelBoxes;
711 delete pAutoFmt;
714 void SwUndoTxtToTbl::UndoImpl(::sw::UndoRedoContext & rContext)
716 SwDoc & rDoc = rContext.GetDoc();
718 sal_uLong nTblNd = nSttNode;
719 if( nSttCntnt )
720 ++nTblNd; // Node was splitted previously
721 SwNodeIndex aIdx( rDoc.GetNodes(), nTblNd );
722 SwTableNode *const pTNd = aIdx.GetNode().GetTableNode();
723 OSL_ENSURE( pTNd, "Could not find a TableNode" );
725 RemoveIdxFromSection( rDoc, nTblNd );
727 sTblNm = pTNd->GetTable().GetFrmFmt()->GetName();
729 if( pHistory )
731 pHistory->TmpRollback( &rDoc, 0 );
732 pHistory->SetTmpEnd( pHistory->Count() );
735 if( pDelBoxes )
737 pTNd->DelFrms();
738 SwTable& rTbl = pTNd->GetTable();
739 for( sal_uInt16 n = pDelBoxes->size(); n; )
741 SwTableBox* pBox = rTbl.GetTblBox( (*pDelBoxes)[ --n ] );
742 if( pBox )
743 ::_DeleteBox( rTbl, pBox, 0, false, false );
744 else {
745 OSL_ENSURE( !this, "Where is my box?" );
750 SwNodeIndex aEndIdx( *pTNd->EndOfSectionNode() );
751 rDoc.TableToText( pTNd, 0x0b == cTrenner ? 0x09 : cTrenner );
753 // join again at start?
754 SwPaM aPam(rDoc.GetNodes().GetEndOfContent());
755 SwPosition *const pPos = aPam.GetPoint();
756 if( nSttCntnt )
758 pPos->nNode = nTblNd;
759 pPos->nContent.Assign(pPos->nNode.GetNode().GetCntntNode(), 0);
760 if (aPam.Move(fnMoveBackward, fnGoCntnt))
762 SwNodeIndex & rIdx = aPam.GetPoint()->nNode;
764 // than move, relatively, the Crsr/etc. again
765 RemoveIdxRel( rIdx.GetIndex()+1, *pPos );
767 rIdx.GetNode().GetCntntNode()->JoinNext();
771 // join again at end?
772 if( bSplitEnd )
774 SwNodeIndex& rIdx = pPos->nNode;
775 rIdx = nEndNode;
776 SwTxtNode* pTxtNd = rIdx.GetNode().GetTxtNode();
777 if( pTxtNd && pTxtNd->CanJoinNext() )
779 aPam.GetMark()->nContent.Assign( 0, 0 );
780 aPam.GetPoint()->nContent.Assign( 0, 0 );
782 // than move, relatively, the Crsr/etc. again
783 pPos->nContent.Assign(pTxtNd, pTxtNd->GetTxt().getLength());
784 RemoveIdxRel( nEndNode + 1, *pPos );
786 pTxtNd->JoinNext();
790 AddUndoRedoPaM(rContext);
793 void SwUndoTxtToTbl::RedoImpl(::sw::UndoRedoContext & rContext)
795 SwPaM & rPam( AddUndoRedoPaM(rContext) );
796 RemoveIdxFromRange(rPam, false);
797 SetPaM(rPam);
799 SwTable const*const pTable = rContext.GetDoc().TextToTable(
800 aInsTblOpts, rPam, cTrenner, nAdjust, pAutoFmt );
801 ((SwFrmFmt*)pTable->GetFrmFmt())->SetName( sTblNm );
804 void SwUndoTxtToTbl::RepeatImpl(::sw::RepeatContext & rContext)
806 // no Table In Table
807 if (!rContext.GetRepeatPaM().GetNode()->FindTableNode())
809 rContext.GetDoc().TextToTable( aInsTblOpts, rContext.GetRepeatPaM(),
810 cTrenner, nAdjust,
811 pAutoFmt );
815 void SwUndoTxtToTbl::AddFillBox( const SwTableBox& rBox )
817 if( !pDelBoxes )
818 pDelBoxes = new std::vector<sal_uLong>;
819 pDelBoxes->push_back( rBox.GetSttIdx() );
822 SwHistory& SwUndoTxtToTbl::GetHistory()
824 if( !pHistory )
825 pHistory = new SwHistory;
826 return *pHistory;
829 SwUndoTblHeadline::SwUndoTblHeadline( const SwTable& rTbl, sal_uInt16 nOldHdl,
830 sal_uInt16 nNewHdl )
831 : SwUndo( UNDO_TABLEHEADLINE ),
832 nOldHeadline( nOldHdl ),
833 nNewHeadline( nNewHdl )
835 OSL_ENSURE( !rTbl.GetTabSortBoxes().empty(), "Table without content" );
836 const SwStartNode *pSttNd = rTbl.GetTabSortBoxes()[ 0 ]->GetSttNd();
837 OSL_ENSURE( pSttNd, "Box without content" );
839 nTblNd = pSttNd->StartOfSectionIndex();
842 void SwUndoTblHeadline::UndoImpl(::sw::UndoRedoContext & rContext)
844 SwDoc & rDoc = rContext.GetDoc();
845 SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
846 OSL_ENSURE( pTNd, "could not find any TableNode" );
848 rDoc.SetRowsToRepeat( pTNd->GetTable(), nOldHeadline );
851 void SwUndoTblHeadline::RedoImpl(::sw::UndoRedoContext & rContext)
853 SwDoc & rDoc = rContext.GetDoc();
855 SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
856 OSL_ENSURE( pTNd, "could not find any TableNode" );
858 rDoc.SetRowsToRepeat( pTNd->GetTable(), nNewHeadline );
861 void SwUndoTblHeadline::RepeatImpl(::sw::RepeatContext & rContext)
863 SwTableNode *const pTblNd =
864 rContext.GetRepeatPaM().GetNode()->FindTableNode();
865 if( pTblNd )
867 rContext.GetDoc().SetRowsToRepeat( pTblNd->GetTable(), nNewHeadline );
871 _SaveTable::_SaveTable( const SwTable& rTbl, sal_uInt16 nLnCnt, bool bSaveFml )
872 : aTblSet( *rTbl.GetFrmFmt()->GetAttrSet().GetPool(), aTableSetRange ),
873 pSwTable( &rTbl ), nLineCount( nLnCnt ), bSaveFormula( bSaveFml )
875 bModifyBox = false;
876 bNewModel = rTbl.IsNewModel();
877 aTblSet.Put( rTbl.GetFrmFmt()->GetAttrSet() );
878 pLine = new _SaveLine( 0, *rTbl.GetTabLines()[ 0 ], *this );
880 _SaveLine* pLn = pLine;
881 if( USHRT_MAX == nLnCnt )
882 nLnCnt = rTbl.GetTabLines().size();
883 for( sal_uInt16 n = 1; n < nLnCnt; ++n )
884 pLn = new _SaveLine( pLn, *rTbl.GetTabLines()[ n ], *this );
886 aFrmFmts.clear();
887 pSwTable = 0;
890 _SaveTable::~_SaveTable()
892 delete pLine;
895 sal_uInt16 _SaveTable::AddFmt( SwFrmFmt* pFmt, bool bIsLine )
897 sal_uInt16 nRet = aFrmFmts.GetPos( pFmt );
898 if( USHRT_MAX == nRet )
900 // Create copy of ItemSet
901 boost::shared_ptr<SfxItemSet> pSet( new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
902 bIsLine ? aTableLineSetRange : aTableBoxSetRange ) );
903 pSet->Put( pFmt->GetAttrSet() );
904 // When a formula is set, never save the value. It possibly must be
905 // recalculated.
906 // Save formulas always in plain text.
907 const SfxPoolItem* pItem;
908 if( SFX_ITEM_SET == pSet->GetItemState( RES_BOXATR_FORMULA, sal_True, &pItem ))
910 pSet->ClearItem( RES_BOXATR_VALUE );
911 if( pSwTable && bSaveFormula )
913 SwTableFmlUpdate aMsgHnt( pSwTable );
914 aMsgHnt.eFlags = TBL_BOXNAME;
915 ((SwTblBoxFormula*)pItem)->ChgDefinedIn( pFmt );
916 ((SwTblBoxFormula*)pItem)->ChangeState( &aMsgHnt );
917 ((SwTblBoxFormula*)pItem)->ChgDefinedIn( 0 );
920 nRet = aSets.size();
921 aSets.push_back( pSet );
922 aFrmFmts.insert( aFrmFmts.begin() + nRet, pFmt );
924 return nRet;
927 void _SaveTable::RestoreAttr( SwTable& rTbl, bool bMdfyBox )
929 sal_uInt16 n;
931 bModifyBox = bMdfyBox;
933 // first, get back attributes of TableFrmFormat
934 SwFrmFmt* pFmt = rTbl.GetFrmFmt();
935 SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet();
936 rFmtSet.ClearItem();
937 rFmtSet.Put( aTblSet );
939 if( pFmt->IsInCache() )
941 SwFrm::GetCache().Delete( pFmt );
942 pFmt->SetInCache( sal_False );
945 // for safety, invalidate all TableFrames
946 SwIterator<SwTabFrm,SwFmt> aIter( *pFmt );
947 for( SwTabFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
948 if( pLast->GetTable() == &rTbl )
950 pLast->InvalidateAll();
951 pLast->SetCompletePaint();
954 // fill FrmFmts with defaults (0)
955 pFmt = 0;
956 for( n = aSets.size(); n; --n )
957 aFrmFmts.push_back( pFmt );
959 sal_uInt16 nLnCnt = nLineCount;
960 if( USHRT_MAX == nLnCnt )
961 nLnCnt = rTbl.GetTabLines().size();
963 _SaveLine* pLn = pLine;
964 for( n = 0; n < nLnCnt; ++n, pLn = pLn->pNext )
966 if( !pLn )
968 OSL_ENSURE( !this, "Number of lines changed" );
969 break;
972 pLn->RestoreAttr( *rTbl.GetTabLines()[ n ], *this );
975 aFrmFmts.clear();
976 bModifyBox = false;
979 void _SaveTable::SaveCntntAttrs( SwDoc* pDoc )
981 pLine->SaveCntntAttrs( pDoc );
984 void _SaveTable::CreateNew( SwTable& rTbl, bool bCreateFrms,
985 bool bRestoreChart )
987 sal_uInt16 n;
989 _FndBox aTmpBox( 0, 0 );
990 aTmpBox.DelFrms( rTbl );
992 // first, get back attributes of TableFrmFormat
993 SwFrmFmt* pFmt = rTbl.GetFrmFmt();
994 SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet();
995 rFmtSet.ClearItem();
996 rFmtSet.Put( aTblSet );
998 if( pFmt->IsInCache() )
1000 SwFrm::GetCache().Delete( pFmt );
1001 pFmt->SetInCache( sal_False );
1004 // SwTableBox must have a format
1005 SwTableBox aParent( (SwTableBoxFmt*)pFmt, rTbl.GetTabLines().size(), 0 );
1007 // fill FrmFmts with defaults (0)
1008 pFmt = 0;
1009 for( n = aSets.size(); n; --n )
1010 aFrmFmts.push_back( pFmt );
1012 pLine->CreateNew( rTbl, aParent, *this );
1013 aFrmFmts.clear();
1015 // add new lines, delete old ones
1016 sal_uInt16 nOldLines = nLineCount;
1017 if( USHRT_MAX == nLineCount )
1018 nOldLines = rTbl.GetTabLines().size();
1020 SwDoc *pDoc = rTbl.GetFrmFmt()->GetDoc();
1021 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
1022 for( n = 0; n < aParent.GetTabLines().size(); ++n )
1024 SwTableLine* pLn = aParent.GetTabLines()[ n ];
1025 pLn->SetUpper( 0 );
1026 if( n < nOldLines )
1028 SwTableLine* pOld = rTbl.GetTabLines()[ n ];
1030 // TL_CHART2: notify chart about boxes to be removed
1031 const SwTableBoxes &rBoxes = pOld->GetTabBoxes();
1032 sal_uInt16 nBoxes = rBoxes.size();
1033 for (sal_uInt16 k = 0; k < nBoxes; ++k)
1035 SwTableBox *pBox = rBoxes[k];
1036 if (pPCD)
1037 pPCD->DeleteBox( &rTbl, *pBox );
1040 rTbl.GetTabLines()[n] = pLn;
1041 delete pOld;
1043 else
1044 rTbl.GetTabLines().insert( rTbl.GetTabLines().begin() + n, pLn );
1047 if( n < nOldLines )
1049 // remove remaining lines...
1050 for (sal_uInt16 k1 = 0; k1 < nOldLines - n; ++k1)
1052 const SwTableBoxes &rBoxes = rTbl.GetTabLines()[n + k1]->GetTabBoxes();
1053 sal_uInt16 nBoxes = rBoxes.size();
1054 for (sal_uInt16 k2 = 0; k2 < nBoxes; ++k2)
1056 SwTableBox *pBox = rBoxes[k2];
1057 // TL_CHART2: notify chart about boxes to be removed
1058 if (pPCD)
1059 pPCD->DeleteBox( &rTbl, *pBox );
1063 for( SwTableLines::const_iterator it = rTbl.GetTabLines().begin() + n;
1064 it != rTbl.GetTabLines().begin() + nOldLines; ++it )
1065 delete *it;
1066 rTbl.GetTabLines().erase( rTbl.GetTabLines().begin() + n, rTbl.GetTabLines().begin() + nOldLines );
1069 aParent.GetTabLines().erase( aParent.GetTabLines().begin(), aParent.GetTabLines().begin() + n );
1071 if( bCreateFrms )
1072 aTmpBox.MakeFrms( rTbl );
1073 if( bRestoreChart )
1075 // TL_CHART2: need to inform chart of probably changed cell names
1076 pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
1080 void _SaveTable::NewFrmFmt( const SwTableLine* pTblLn, const SwTableBox* pTblBx,
1081 sal_uInt16 nFmtPos, SwFrmFmt* pOldFmt )
1083 SwDoc* pDoc = pOldFmt->GetDoc();
1085 SwFrmFmt* pFmt = aFrmFmts[ nFmtPos ];
1086 if( !pFmt )
1088 if( pTblLn )
1089 pFmt = pDoc->MakeTableLineFmt();
1090 else
1091 pFmt = pDoc->MakeTableBoxFmt();
1092 pFmt->SetFmtAttr( *aSets[ nFmtPos ] );
1093 aFrmFmts[nFmtPos] = pFmt;
1096 // first re-assign Frms
1097 SwIterator<SwTabFrm,SwFmt> aIter( *pOldFmt );
1098 for( SwFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
1100 if( pTblLn ? ((SwRowFrm*)pLast)->GetTabLine() == pTblLn
1101 : ((SwCellFrm*)pLast)->GetTabBox() == pTblBx )
1103 pLast->RegisterToFormat(*pFmt);
1104 pLast->InvalidateAll();
1105 pLast->ReinitializeFrmSizeAttrFlags();
1106 if ( !pTblLn )
1108 ((SwCellFrm*)pLast)->SetDerivedVert( sal_False );
1109 ((SwCellFrm*)pLast)->CheckDirChange();
1114 // than re-assign myself
1115 if ( pTblLn )
1116 const_cast<SwTableLine*>(pTblLn)->RegisterToFormat( *pFmt );
1117 else if ( pTblBx )
1118 const_cast<SwTableBox*>(pTblBx)->RegisterToFormat( *pFmt );
1120 if( bModifyBox && !pTblLn )
1122 const SfxPoolItem& rOld = pOldFmt->GetFmtAttr( RES_BOXATR_FORMAT ),
1123 & rNew = pFmt->GetFmtAttr( RES_BOXATR_FORMAT );
1124 if( rOld != rNew )
1125 pFmt->ModifyNotification( (SfxPoolItem*)&rOld, (SfxPoolItem*)&rNew );
1128 if( !pOldFmt->GetDepends() )
1129 delete pOldFmt;
1132 _SaveLine::_SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl )
1133 : pNext( 0 )
1135 if( pPrev )
1136 pPrev->pNext = this;
1138 nItemSet = rSTbl.AddFmt( rLine.GetFrmFmt(), true );
1140 pBox = new _SaveBox( 0, *rLine.GetTabBoxes()[ 0 ], rSTbl );
1141 _SaveBox* pBx = pBox;
1142 for( sal_uInt16 n = 1; n < rLine.GetTabBoxes().size(); ++n )
1143 pBx = new _SaveBox( pBx, *rLine.GetTabBoxes()[ n ], rSTbl );
1146 _SaveLine::~_SaveLine()
1148 delete pBox;
1149 delete pNext;
1152 void _SaveLine::RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl )
1154 rSTbl.NewFrmFmt( &rLine, 0, nItemSet, rLine.GetFrmFmt() );
1156 _SaveBox* pBx = pBox;
1157 for( sal_uInt16 n = 0; n < rLine.GetTabBoxes().size(); ++n, pBx = pBx->pNext )
1159 if( !pBx )
1161 OSL_ENSURE( !this, "Number of boxes changed" );
1162 break;
1164 pBx->RestoreAttr( *rLine.GetTabBoxes()[ n ], rSTbl );
1168 void _SaveLine::SaveCntntAttrs( SwDoc* pDoc )
1170 pBox->SaveCntntAttrs( pDoc );
1171 if( pNext )
1172 pNext->SaveCntntAttrs( pDoc );
1175 void _SaveLine::CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl )
1177 SwTableLineFmt* pFmt = (SwTableLineFmt*)rSTbl.aFrmFmts[ nItemSet ];
1178 if( !pFmt )
1180 SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc();
1181 pFmt = pDoc->MakeTableLineFmt();
1182 pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] );
1183 rSTbl.aFrmFmts[ nItemSet ] = pFmt;
1185 SwTableLine* pNew = new SwTableLine( pFmt, 1, &rParent );
1187 rParent.GetTabLines().push_back( pNew );
1189 // HB, #127868# robustness: in some cases - which I
1190 // cannot reproduce nor see from the code - pNew seems
1191 // to be set to NULL in C40_INSERT.
1192 OSL_ENSURE(pNew, "Table line just created set to NULL in C40_INSERT");
1194 if (pNew)
1196 pBox->CreateNew( rTbl, *pNew, rSTbl );
1199 if( pNext )
1200 pNext->CreateNew( rTbl, rParent, rSTbl );
1203 _SaveBox::_SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl )
1204 : pNext( 0 ), nSttNode( ULONG_MAX ), nRowSpan(0)
1206 Ptrs.pLine = 0;
1208 if( pPrev )
1209 pPrev->pNext = this;
1211 nItemSet = rSTbl.AddFmt( rBox.GetFrmFmt(), false );
1213 if( rBox.GetSttNd() )
1215 nSttNode = rBox.GetSttIdx();
1216 nRowSpan = rBox.getRowSpan();
1218 else
1220 Ptrs.pLine = new _SaveLine( 0, *rBox.GetTabLines()[ 0 ], rSTbl );
1222 _SaveLine* pLn = Ptrs.pLine;
1223 for( sal_uInt16 n = 1; n < rBox.GetTabLines().size(); ++n )
1224 pLn = new _SaveLine( pLn, *rBox.GetTabLines()[ n ], rSTbl );
1228 _SaveBox::~_SaveBox()
1230 if( ULONG_MAX == nSttNode ) // no EndBox
1231 delete Ptrs.pLine;
1232 else
1233 delete Ptrs.pCntntAttrs;
1234 delete pNext;
1237 void _SaveBox::RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl )
1239 rSTbl.NewFrmFmt( 0, &rBox, nItemSet, rBox.GetFrmFmt() );
1241 if( ULONG_MAX == nSttNode ) // no EndBox
1243 if( !rBox.GetTabLines().size() )
1245 OSL_ENSURE( !this, "Number of lines changed" );
1247 else
1249 _SaveLine* pLn = Ptrs.pLine;
1250 for( sal_uInt16 n = 0; n < rBox.GetTabLines().size(); ++n, pLn = pLn->pNext )
1252 if( !pLn )
1254 OSL_ENSURE( !this, "Number of lines changed" );
1255 break;
1258 pLn->RestoreAttr( *rBox.GetTabLines()[ n ], rSTbl );
1262 else if( rBox.GetSttNd() && rBox.GetSttIdx() == nSttNode )
1264 if( Ptrs.pCntntAttrs )
1266 SwNodes& rNds = rBox.GetFrmFmt()->GetDoc()->GetNodes();
1267 sal_uInt16 nSet = 0;
1268 sal_uLong nEnd = rBox.GetSttNd()->EndOfSectionIndex();
1269 for( sal_uLong n = nSttNode + 1; n < nEnd; ++n )
1271 SwCntntNode* pCNd = rNds[ n ]->GetCntntNode();
1272 if( pCNd )
1274 boost::shared_ptr<SfxItemSet> pSet( (*Ptrs.pCntntAttrs)[ nSet++ ] );
1275 if( pSet )
1277 sal_uInt16 *pRstAttr = aSave_BoxCntntSet;
1278 while( *pRstAttr )
1280 pCNd->ResetAttr( *pRstAttr, *(pRstAttr+1) );
1281 pRstAttr += 2;
1283 pCNd->SetAttr( *pSet );
1285 else
1286 pCNd->ResetAllAttr();
1291 else
1293 OSL_ENSURE( !this, "Box not anymore at the same node" );
1297 void _SaveBox::SaveCntntAttrs( SwDoc* pDoc )
1299 if( ULONG_MAX == nSttNode ) // no EndBox
1301 // continue in current line
1302 Ptrs.pLine->SaveCntntAttrs( pDoc );
1304 else
1306 sal_uLong nEnd = pDoc->GetNodes()[ nSttNode ]->EndOfSectionIndex();
1307 Ptrs.pCntntAttrs = new SfxItemSets( (sal_uInt8)(nEnd - nSttNode - 1 ) );
1308 for( sal_uLong n = nSttNode + 1; n < nEnd; ++n )
1310 SwCntntNode* pCNd = pDoc->GetNodes()[ n ]->GetCntntNode();
1311 if( pCNd )
1313 boost::shared_ptr<SfxItemSet> pSet;
1314 if( pCNd->HasSwAttrSet() )
1316 pSet.reset( new SfxItemSet( pDoc->GetAttrPool(),
1317 aSave_BoxCntntSet ) );
1318 pSet->Put( *pCNd->GetpSwAttrSet() );
1321 Ptrs.pCntntAttrs->push_back( pSet );
1325 if( pNext )
1326 pNext->SaveCntntAttrs( pDoc );
1329 void _SaveBox::CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl )
1331 SwTableBoxFmt* pFmt = (SwTableBoxFmt*)rSTbl.aFrmFmts[ nItemSet ];
1332 if( !pFmt )
1334 SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc();
1335 pFmt = pDoc->MakeTableBoxFmt();
1336 pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] );
1337 rSTbl.aFrmFmts[nItemSet] = pFmt;
1340 if( ULONG_MAX == nSttNode ) // no EndBox
1342 SwTableBox* pNew = new SwTableBox( pFmt, 1, &rParent );
1343 rParent.GetTabBoxes().push_back( pNew );
1345 Ptrs.pLine->CreateNew( rTbl, *pNew, rSTbl );
1347 else
1349 // search box for StartNode in old table
1350 SwTableBox* pBox = rTbl.GetTblBox( nSttNode );
1351 OSL_ENSURE( pBox, "Where is my TableBox?" );
1353 SwFrmFmt* pOld = pBox->GetFrmFmt();
1354 pBox->RegisterToFormat( *pFmt );
1355 if( !pOld->GetDepends() )
1356 delete pOld;
1358 pBox->setRowSpan( nRowSpan );
1360 SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
1361 pTBoxes->erase( std::find( pTBoxes->begin(), pTBoxes->end(), pBox ) );
1363 pBox->SetUpper( &rParent );
1364 pTBoxes = &rParent.GetTabBoxes();
1365 pTBoxes->push_back( pBox );
1368 if( pNext )
1369 pNext->CreateNew( rTbl, rParent, rSTbl );
1372 // UndoObject for attribute changes on table
1373 SwUndoAttrTbl::SwUndoAttrTbl( const SwTableNode& rTblNd, sal_Bool bClearTabCols )
1374 : SwUndo( UNDO_TABLE_ATTR ),
1375 nSttNode( rTblNd.GetIndex() )
1377 bClearTabCol = bClearTabCols;
1378 pSaveTbl = new _SaveTable( rTblNd.GetTable() );
1381 SwUndoAttrTbl::~SwUndoAttrTbl()
1383 delete pSaveTbl;
1386 void SwUndoAttrTbl::UndoImpl(::sw::UndoRedoContext & rContext)
1388 SwDoc & rDoc = rContext.GetDoc();
1389 SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
1390 OSL_ENSURE( pTblNd, "no TableNode" );
1392 if (pTblNd)
1394 _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() );
1395 pSaveTbl->RestoreAttr( pTblNd->GetTable() );
1396 delete pSaveTbl;
1397 pSaveTbl = pOrig;
1400 if( bClearTabCol )
1401 ClearFEShellTabCols();
1404 void SwUndoAttrTbl::RedoImpl(::sw::UndoRedoContext & rContext)
1406 UndoImpl(rContext);
1409 // UndoObject for AutoFormat on Table
1410 SwUndoTblAutoFmt::SwUndoTblAutoFmt( const SwTableNode& rTblNd,
1411 const SwTableAutoFmt& rAFmt )
1412 : SwUndo( UNDO_TABLE_AUTOFMT ),
1413 nSttNode( rTblNd.GetIndex() ),
1414 bSaveCntntAttr( sal_False )
1415 , m_nRepeatHeading(rTblNd.GetTable().GetRowsToRepeat())
1417 pSaveTbl = new _SaveTable( rTblNd.GetTable() );
1419 if( rAFmt.IsFont() || rAFmt.IsJustify() )
1421 // than also go over the ContentNodes of the EndBoxes and collect
1422 // all paragraph attributes
1423 pSaveTbl->SaveCntntAttrs( (SwDoc*)rTblNd.GetDoc() );
1424 bSaveCntntAttr = sal_True;
1428 SwUndoTblAutoFmt::~SwUndoTblAutoFmt()
1430 delete pSaveTbl;
1433 void SwUndoTblAutoFmt::SaveBoxCntnt( const SwTableBox& rBox )
1435 ::boost::shared_ptr<SwUndoTblNumFmt> const p(new SwUndoTblNumFmt(rBox));
1436 m_Undos.push_back(p);
1439 void
1440 SwUndoTblAutoFmt::UndoRedo(bool const bUndo, ::sw::UndoRedoContext & rContext)
1442 SwDoc & rDoc = rContext.GetDoc();
1443 SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
1444 OSL_ENSURE( pTblNd, "no TableNode" );
1446 SwTable& table = pTblNd->GetTable();
1447 _SaveTable* pOrig = new _SaveTable( table );
1448 // than go also over the ContentNodes of the EndBoxes and collect
1449 // all paragraph attributes
1450 if( bSaveCntntAttr )
1451 pOrig->SaveCntntAttrs( &rDoc );
1453 if (bUndo)
1455 for (size_t n = m_Undos.size(); 0 < n; --n)
1457 m_Undos.at(n-1)->UndoImpl(rContext);
1460 table.SetRowsToRepeat(m_nRepeatHeading);
1463 pSaveTbl->RestoreAttr( pTblNd->GetTable(), !bUndo );
1464 delete pSaveTbl;
1465 pSaveTbl = pOrig;
1468 void SwUndoTblAutoFmt::UndoImpl(::sw::UndoRedoContext & rContext)
1470 UndoRedo(true, rContext);
1473 void SwUndoTblAutoFmt::RedoImpl(::sw::UndoRedoContext & rContext)
1475 UndoRedo(false, rContext);
1478 SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction,
1479 const SwSelBoxes& rBoxes,
1480 const SwTableNode& rTblNd,
1481 long nMn, long nMx,
1482 sal_uInt16 nCnt, sal_Bool bFlg, sal_Bool bSmHght )
1483 : SwUndo( nAction ),
1484 nMin( nMn ), nMax( nMx ),
1485 nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ),
1486 nCount( nCnt ), nRelDiff( 0 ), nAbsDiff( 0 ),
1487 nSetColType( USHRT_MAX ),
1488 bFlag( bFlg ),
1489 bSameHeight( bSmHght )
1491 const SwTable& rTbl = rTblNd.GetTable();
1492 pSaveTbl = new _SaveTable( rTbl );
1494 // and remember selection
1495 ReNewBoxes( rBoxes );
1498 SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction,
1499 const SwSelBoxes& rBoxes,
1500 const SwTableNode& rTblNd )
1501 : SwUndo( nAction ),
1502 nMin( 0 ), nMax( 0 ),
1503 nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ),
1504 nCount( 0 ), nRelDiff( 0 ), nAbsDiff( 0 ),
1505 nSetColType( USHRT_MAX ),
1506 bFlag( sal_False ),
1507 bSameHeight( sal_False )
1509 const SwTable& rTbl = rTblNd.GetTable();
1510 pSaveTbl = new _SaveTable( rTbl );
1512 // and remember selection
1513 ReNewBoxes( rBoxes );
1516 void SwUndoTblNdsChg::ReNewBoxes( const SwSelBoxes& rBoxes )
1518 if (rBoxes.size() != m_Boxes.size())
1520 m_Boxes.clear();
1521 for (size_t n = 0; n < rBoxes.size(); ++n)
1523 m_Boxes.insert( rBoxes[n]->GetSttIdx() );
1528 SwUndoTblNdsChg::~SwUndoTblNdsChg()
1530 delete pSaveTbl;
1533 void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd,
1534 const SwTableSortBoxes& rOld )
1536 const SwTable& rTbl = rTblNd.GetTable();
1537 const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes();
1539 OSL_ENSURE( ! IsDelBox(), "wrong Action" );
1540 pNewSttNds.reset( new std::set<_BoxMove> );
1542 size_t i = 0;
1543 for (size_t n = 0; n < rOld.size(); ++i)
1545 if( rOld[ n ] == rTblBoxes[ i ] )
1546 ++n;
1547 else
1548 // new box: insert sorted
1549 pNewSttNds->insert( _BoxMove(rTblBoxes[ i ]->GetSttIdx()) );
1552 for( ; i < rTblBoxes.size(); ++i )
1553 // new box: insert sorted
1554 pNewSttNds->insert( _BoxMove(rTblBoxes[ i ]->GetSttIdx()) );
1557 static SwTableLine* lcl_FindTableLine( const SwTable& rTable,
1558 const SwTableBox& rBox )
1560 SwTableLine* pRet = NULL;
1561 // i63949: For nested cells we have to take nLineNo - 1, too, not 0!
1562 const SwTableLines &rTableLines = ( rBox.GetUpper()->GetUpper() != NULL ) ?
1563 rBox.GetUpper()->GetUpper()->GetTabLines()
1564 : rTable.GetTabLines();
1565 const SwTableLine* pLine = rBox.GetUpper();
1566 sal_uInt16 nLineNo = rTableLines.GetPos( pLine );
1567 pRet = rTableLines[nLineNo - 1];
1569 return pRet;
1572 static const SwTableLines& lcl_FindParentLines( const SwTable& rTable,
1573 const SwTableBox& rBox )
1575 const SwTableLines& rRet =
1576 ( rBox.GetUpper()->GetUpper() != NULL ) ?
1577 rBox.GetUpper()->GetUpper()->GetTabLines() :
1578 rTable.GetTabLines();
1580 return rRet;
1583 void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd,
1584 const SwTableSortBoxes& rOld,
1585 const SwSelBoxes& rBoxes,
1586 const std::vector<sal_uLong> &rNodeCnts )
1588 const SwTable& rTbl = rTblNd.GetTable();
1589 const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes();
1591 OSL_ENSURE( ! IsDelBox(), "wrong Action" );
1592 pNewSttNds.reset( new std::set<_BoxMove> );
1594 OSL_ENSURE( rTbl.IsNewModel() || rOld.size() + nCount * rBoxes.size() == rTblBoxes.size(),
1595 "unexpected boxes" );
1596 OSL_ENSURE( rOld.size() <= rTblBoxes.size(), "more unexpected boxes" );
1597 for (size_t n = 0, i = 0; i < rTblBoxes.size(); ++i)
1599 if( ( n < rOld.size() ) &&
1600 ( rOld[ n ] == rTblBoxes[ i ] ) )
1602 // box already known? Then nothing to be done.
1603 ++n;
1605 else
1607 // new box found: insert (obey sort order)
1608 const SwTableBox* pBox = rTblBoxes[ i ];
1610 // find the source box. It must be one in rBoxes.
1611 // We found the right one if it's in the same column as pBox.
1612 // No, if more than one selected cell in the same column has been splitted,
1613 // we have to look for the nearest one (i65201)!
1614 const SwTableBox* pSourceBox = NULL;
1615 const SwTableBox* pCheckBox = NULL;
1616 const SwTableLine* pBoxLine = pBox->GetUpper();
1617 sal_uInt16 nLineDiff = lcl_FindParentLines(rTbl,*pBox).GetPos(pBoxLine);
1618 sal_uInt16 nLineNo = 0;
1619 for (size_t j = 0; j < rBoxes.size(); ++j)
1621 pCheckBox = rBoxes[j];
1622 if( pCheckBox->GetUpper()->GetUpper() == pBox->GetUpper()->GetUpper() )
1624 const SwTableLine* pCheckLine = pCheckBox->GetUpper();
1625 sal_uInt16 nCheckLine = lcl_FindParentLines( rTbl, *pCheckBox ).
1626 GetPos( pCheckLine );
1627 if( ( !pSourceBox || nCheckLine > nLineNo ) && nCheckLine < nLineDiff )
1629 nLineNo = nCheckLine;
1630 pSourceBox = pCheckBox;
1635 // find the line number difference
1636 // (to help determine bNodesMoved flag below)
1637 nLineDiff = nLineDiff - nLineNo;
1638 OSL_ENSURE( pSourceBox, "Splitted source box not found!" );
1639 // find out how many nodes the source box used to have
1640 // (to help determine bNodesMoved flag below)
1641 size_t nNdsPos = 0;
1642 while( rBoxes[ nNdsPos ] != pSourceBox )
1643 ++nNdsPos;
1644 sal_uLong nNodes = rNodeCnts[ nNdsPos ];
1646 // When a new table cell is created, it either gets a new
1647 // node, or it gets node(s) from elsewhere. The undo must
1648 // know, of course, and thus we must determine here just
1649 // where pBox's nodes are from:
1650 // If 1) the source box has lost nodes, and
1651 // 2) we're in the node range that got nodes
1652 // then pBox received nodes from elsewhere.
1653 // If bNodesMoved is set for pBox the undo must move the
1654 // boxes back, otherwise it must delete them.
1655 sal_Bool bNodesMoved =
1656 ( nNodes != ( pSourceBox->GetSttNd()->EndOfSectionIndex() -
1657 pSourceBox->GetSttIdx() ) )
1658 && ( nNodes - 1 > nLineDiff );
1659 pNewSttNds->insert( _BoxMove(pBox->GetSttIdx(), bNodesMoved) );
1664 void SwUndoTblNdsChg::SaveSection( SwStartNode* pSttNd )
1666 OSL_ENSURE( IsDelBox(), "wrong Action" );
1667 if( pDelSects.get() == NULL )
1668 pDelSects.reset( new SwUndoSaveSections( 10 ) );
1670 SwTableNode* pTblNd = pSttNd->FindTableNode();
1671 SwUndoSaveSection* pSave = new SwUndoSaveSection;
1672 pSave->SaveSection( pSttNd->GetDoc(), SwNodeIndex( *pSttNd ));
1674 pDelSects->push_back( pSave );
1675 nSttNode = pTblNd->GetIndex();
1678 void SwUndoTblNdsChg::UndoImpl(::sw::UndoRedoContext & rContext)
1680 SwDoc & rDoc = rContext.GetDoc();
1681 SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
1683 SwTableNode *const pTblNd = aIdx.GetNode().GetTableNode();
1684 OSL_ENSURE( pTblNd, "no TableNode" );
1686 SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
1687 aMsgHnt.eFlags = TBL_BOXPTR;
1688 rDoc.UpdateTblFlds( &aMsgHnt );
1690 CHECK_TABLE( pTblNd->GetTable() )
1692 _FndBox aTmpBox( 0, 0 );
1693 // ? TL_CHART2: notification or locking of controller required ?
1695 SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
1696 std::vector< SwTableBox* > aDelBoxes;
1697 if( IsDelBox() )
1699 // Trick: add missing boxes in any line, they will be connected
1700 // correctly when calling CreateNew
1701 SwTableBox* pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0];
1702 SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
1704 // restore sections
1705 for( sal_uInt16 n = pDelSects->size(); n; )
1707 SwUndoSaveSection* pSave = &(*pDelSects)[ --n ];
1708 pSave->RestoreSection( &rDoc, &aIdx, SwTableBoxStartNode );
1709 if( pSave->GetHistory() )
1710 pSave->GetHistory()->Rollback( &rDoc );
1711 SwTableBox* pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), aIdx,
1712 pCpyBox->GetUpper() );
1713 rLnBoxes.push_back( pBox );
1715 pDelSects->clear();
1717 else if( !pNewSttNds->empty() )
1719 // Than the nodes have be moved and not deleted!
1720 // But for that we need a temp array.
1721 std::vector<_BoxMove> aTmp( pNewSttNds->begin(), pNewSttNds->end() );
1723 // backwards
1724 for (size_t n = aTmp.size(); n > 0 ; )
1726 --n;
1727 // delete box from table structure
1728 sal_uLong nIdx = aTmp[n].index;
1729 SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
1730 OSL_ENSURE( pBox, "Where is my TableBox?" );
1732 // TL_CHART2: notify chart about box to be removed
1733 if (pPCD)
1734 pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
1736 if( aTmp[n].hasMoved )
1738 SwNodeRange aRg( *pBox->GetSttNd(), 1,
1739 *pBox->GetSttNd()->EndOfSectionNode() );
1741 SwTableLine* pLine = lcl_FindTableLine( pTblNd->GetTable(), *pBox );
1742 SwNodeIndex aInsPos( *(pLine->GetTabBoxes()[0]->GetSttNd()), 2 );
1744 // adjust all StartNode indices
1745 size_t i = n;
1746 sal_uLong nSttIdx = aInsPos.GetIndex() - 2,
1747 nNdCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
1748 while( i && aTmp[ --i ].index > nSttIdx )
1749 aTmp[ i ].index += nNdCnt;
1751 // first delete box
1752 delete pBox;
1753 // than move nodes
1754 rDoc.GetNodes()._MoveNodes( aRg, rDoc.GetNodes(), aInsPos, sal_False );
1756 else
1757 { // first disconnect box from node, otherwise ~SwTableBox would
1758 // access pBox->pSttNd, deleted by DeleteSection
1759 pBox->RemoveFromTable();
1760 rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
1762 aDelBoxes.insert( aDelBoxes.end(), pBox );
1765 else
1767 // Remove nodes from nodes array (backwards!)
1768 std::set<_BoxMove>::reverse_iterator it;
1769 for( it = pNewSttNds->rbegin(); it != pNewSttNds->rend(); ++it )
1771 sal_uLong nIdx = (*it).index;
1772 SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
1773 OSL_ENSURE( pBox, "Where's my table box?" );
1774 // TL_CHART2: notify chart about box to be removed
1775 if (pPCD)
1776 pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
1777 pBox->RemoveFromTable(); // ~SwTableBox would access pBox->pSttNd
1778 aDelBoxes.insert( aDelBoxes.end(), pBox );
1779 rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
1782 // Remove boxes from table structure
1783 for( sal_uInt16 n = 0; n < aDelBoxes.size(); ++n )
1785 SwTableBox* pCurrBox = aDelBoxes[n];
1786 SwTableBoxes* pTBoxes = &pCurrBox->GetUpper()->GetTabBoxes();
1787 pTBoxes->erase( std::find( pTBoxes->begin(), pTBoxes->end(), pCurrBox ) );
1788 delete pCurrBox;
1791 pSaveTbl->CreateNew( pTblNd->GetTable(), true, false );
1793 // TL_CHART2: need to inform chart of probably changed cell names
1794 rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
1796 if( IsDelBox() )
1797 nSttNode = pTblNd->GetIndex();
1798 ClearFEShellTabCols();
1799 CHECK_TABLE( pTblNd->GetTable() )
1802 void SwUndoTblNdsChg::RedoImpl(::sw::UndoRedoContext & rContext)
1804 SwDoc & rDoc = rContext.GetDoc();
1806 SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
1807 OSL_ENSURE( pTblNd, "no TableNode" );
1808 CHECK_TABLE( pTblNd->GetTable() )
1810 SwSelBoxes aSelBoxes;
1811 for (std::set<sal_uLong>::iterator it = m_Boxes.begin();
1812 it != m_Boxes.end(); ++it)
1814 SwTableBox* pBox = pTblNd->GetTable().GetTblBox( *it );
1815 aSelBoxes.insert( pBox );
1818 // create SelBoxes and call InsertCell/-Row/SplitTbl
1819 switch( GetId() )
1821 case UNDO_TABLE_INSCOL:
1822 if( USHRT_MAX == nSetColType )
1823 rDoc.InsertCol( aSelBoxes, nCount, bFlag );
1824 else
1826 SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nCurrBox );
1827 rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff,
1828 nRelDiff );
1830 break;
1832 case UNDO_TABLE_INSROW:
1833 if( USHRT_MAX == nSetColType )
1834 rDoc.InsertRow( aSelBoxes, nCount, bFlag );
1835 else
1837 SwTable& rTbl = pTblNd->GetTable();
1838 SwTableBox* pBox = rTbl.GetTblBox( nCurrBox );
1839 TblChgMode eOldMode = rTbl.GetTblChgMode();
1840 rTbl.SetTblChgMode( (TblChgMode)nCount );
1841 rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff, nRelDiff );
1842 rTbl.SetTblChgMode( eOldMode );
1844 break;
1846 case UNDO_TABLE_SPLIT:
1847 rDoc.SplitTbl( aSelBoxes, bFlag, nCount, bSameHeight );
1848 break;
1849 case UNDO_TABLE_DELBOX:
1850 case UNDO_ROW_DELETE:
1851 case UNDO_COL_DELETE:
1852 if( USHRT_MAX == nSetColType )
1854 SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
1855 aMsgHnt.eFlags = TBL_BOXPTR;
1856 rDoc.UpdateTblFlds( &aMsgHnt );
1857 SwTable &rTable = pTblNd->GetTable();
1858 if( nMax > nMin && rTable.IsNewModel() )
1859 rTable.PrepareDeleteCol( nMin, nMax );
1860 rTable.DeleteSel( &rDoc, aSelBoxes, 0, this, true, true );
1862 else
1864 SwTable& rTbl = pTblNd->GetTable();
1866 SwTableFmlUpdate aMsgHnt( &rTbl );
1867 aMsgHnt.eFlags = TBL_BOXPTR;
1868 rDoc.UpdateTblFlds( &aMsgHnt );
1870 SwTableBox* pBox = rTbl.GetTblBox( nCurrBox );
1871 TblChgMode eOldMode = rTbl.GetTblChgMode();
1872 rTbl.SetTblChgMode( (TblChgMode)nCount );
1874 // need the SaveSections!
1875 rDoc.GetIDocumentUndoRedo().DoUndo( true );
1876 SwUndoTblNdsChg* pUndo = 0;
1878 switch( nSetColType & 0xff )
1880 case nsTblChgWidthHeightType::WH_COL_LEFT:
1881 case nsTblChgWidthHeightType::WH_COL_RIGHT:
1882 case nsTblChgWidthHeightType::WH_CELL_LEFT:
1883 case nsTblChgWidthHeightType::WH_CELL_RIGHT:
1884 rTbl.SetColWidth( *pBox, nSetColType, nAbsDiff,
1885 nRelDiff, (SwUndo**)&pUndo );
1886 break;
1887 case nsTblChgWidthHeightType::WH_ROW_TOP:
1888 case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
1889 case nsTblChgWidthHeightType::WH_CELL_TOP:
1890 case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
1891 rTbl.SetRowHeight( *pBox, nSetColType, nAbsDiff,
1892 nRelDiff, (SwUndo**)&pUndo );
1893 break;
1896 if( pUndo )
1898 pDelSects->transfer( pDelSects->begin(), *pUndo->pDelSects.get() );
1899 delete pUndo;
1901 rDoc.GetIDocumentUndoRedo().DoUndo( false );
1903 rTbl.SetTblChgMode( eOldMode );
1905 nSttNode = pTblNd->GetIndex();
1906 break;
1907 default:
1910 ClearFEShellTabCols();
1911 CHECK_TABLE( pTblNd->GetTable() )
1914 SwUndoTblMerge::SwUndoTblMerge( const SwPaM& rTblSel )
1915 : SwUndo( UNDO_TABLE_MERGE ), SwUndRng( rTblSel ), pHistory( 0 )
1917 const SwTableNode* pTblNd = rTblSel.GetNode()->FindTableNode();
1918 OSL_ENSURE( pTblNd, "Where is the TableNode?" );
1919 pSaveTbl = new _SaveTable( pTblNd->GetTable() );
1920 pMoves = new SwUndoMoves;
1921 nTblNode = pTblNd->GetIndex();
1924 SwUndoTblMerge::~SwUndoTblMerge()
1926 delete pSaveTbl;
1927 delete pMoves;
1928 delete pHistory;
1931 void SwUndoTblMerge::UndoImpl(::sw::UndoRedoContext & rContext)
1933 SwDoc & rDoc = rContext.GetDoc();
1934 SwNodeIndex aIdx( rDoc.GetNodes(), nTblNode );
1936 SwTableNode *const pTblNd = aIdx.GetNode().GetTableNode();
1937 OSL_ENSURE( pTblNd, "no TableNode" );
1939 SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
1940 aMsgHnt.eFlags = TBL_BOXPTR;
1941 rDoc.UpdateTblFlds( &aMsgHnt );
1943 _FndBox aTmpBox( 0, 0 );
1944 // ? TL_CHART2: notification or locking of controller required ?
1946 // 1. restore deleted boxes:
1947 // Trick: add missing boxes in any line, they will be connected
1948 // correctly when calling CreateNew
1949 SwTableBox *pBox, *pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0];
1950 SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
1952 CHECKTABLE(pTblNd->GetTable())
1954 SwSelBoxes aSelBoxes;
1955 SwTxtFmtColl* pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
1956 sal_uInt16 n;
1958 std::set<sal_uLong>::iterator it;
1959 for (it = m_Boxes.begin(); it != m_Boxes.end(); ++it)
1961 aIdx = *it;
1962 SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection( aIdx,
1963 SwTableBoxStartNode, pColl );
1964 pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), *pSttNd,
1965 pCpyBox->GetUpper() );
1966 rLnBoxes.push_back( pBox );
1968 aSelBoxes.insert( pBox );
1971 CHECKTABLE(pTblNd->GetTable())
1973 SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
1974 // 2. deleted the inserted boxes
1975 // delete nodes (from last to first)
1976 for( n = aNewSttNds.size(); n; )
1978 // remove box from table structure
1979 sal_uLong nIdx = aNewSttNds[ --n ];
1981 if( !nIdx && n )
1983 nIdx = aNewSttNds[ --n ];
1984 pBox = pTblNd->GetTable().GetTblBox( nIdx );
1985 OSL_ENSURE( pBox, "Where is my TableBox?" );
1987 if( !pSaveTbl->IsNewModel() )
1988 rDoc.GetNodes().MakeTxtNode( SwNodeIndex(
1989 *pBox->GetSttNd()->EndOfSectionNode() ), pColl );
1991 // this was the separator -> restore moved ones
1992 for( sal_uInt16 i = pMoves->size(); i; )
1994 SwTxtNode* pTxtNd = 0;
1995 sal_uInt16 nDelPos = 0;
1996 SwUndoMove* pUndo = &(*pMoves)[ --i ];
1997 if( !pUndo->IsMoveRange() )
1999 pTxtNd = rDoc.GetNodes()[ pUndo->GetDestSttNode() ]->GetTxtNode();
2000 nDelPos = pUndo->GetDestSttCntnt() - 1;
2002 pUndo->UndoImpl(rContext);
2003 if( pUndo->IsMoveRange() )
2005 // delete the unnecessary node
2006 aIdx = pUndo->GetEndNode();
2007 SwCntntNode *pCNd = aIdx.GetNode().GetCntntNode();
2008 if( pCNd )
2010 SwNodeIndex aTmp( aIdx, -1 );
2011 SwCntntNode *pMove = aTmp.GetNode().GetCntntNode();
2012 if( pMove )
2013 pCNd->MoveTo( *pMove );
2015 rDoc.GetNodes().Delete( aIdx, 1 );
2017 else if( pTxtNd )
2019 // also delete not needed attributes
2020 SwIndex aTmpIdx( pTxtNd, nDelPos );
2021 if( pTxtNd->GetpSwpHints() && pTxtNd->GetpSwpHints()->Count() )
2022 pTxtNd->RstAttr(aTmpIdx, pTxtNd->GetTxt().getLength() -
2023 nDelPos + 1 );
2024 // delete separator
2025 pTxtNd->EraseText( aTmpIdx, 1 );
2028 nIdx = pBox->GetSttIdx();
2030 else
2031 pBox = pTblNd->GetTable().GetTblBox( nIdx );
2033 if( !pSaveTbl->IsNewModel() )
2035 // TL_CHART2: notify chart about box to be removed
2036 if (pPCD)
2037 pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
2039 SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
2040 pTBoxes->erase( std::find(pTBoxes->begin(), pTBoxes->end(), pBox ) );
2042 // delete indices from section
2044 SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
2045 rDoc.CorrAbs( SwNodeIndex( aTmpIdx, 1 ),
2046 SwNodeIndex( *aTmpIdx.GetNode().EndOfSectionNode() ),
2047 SwPosition( aTmpIdx, SwIndex( 0, 0 )), sal_True );
2050 delete pBox;
2051 rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
2054 CHECKTABLE(pTblNd->GetTable())
2056 pSaveTbl->CreateNew( pTblNd->GetTable(), true, false );
2058 // TL_CHART2: need to inform chart of probably changed cell names
2059 rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
2061 if( pHistory )
2063 pHistory->TmpRollback( &rDoc, 0 );
2064 pHistory->SetTmpEnd( pHistory->Count() );
2066 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2067 pPam->DeleteMark();
2068 pPam->GetPoint()->nNode = nSttNode;
2069 pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), nSttCntnt );
2070 pPam->SetMark();
2071 pPam->DeleteMark();
2073 CHECKTABLE(pTblNd->GetTable())
2074 ClearFEShellTabCols();
2077 void SwUndoTblMerge::RedoImpl(::sw::UndoRedoContext & rContext)
2079 SwDoc & rDoc = rContext.GetDoc();
2080 SwPaM & rPam( AddUndoRedoPaM(rContext) );
2081 rDoc.MergeTbl(rPam);
2084 void SwUndoTblMerge::MoveBoxCntnt( SwDoc* pDoc, SwNodeRange& rRg, SwNodeIndex& rPos )
2086 SwNodeIndex aTmp( rRg.aStart, -1 ), aTmp2( rPos, -1 );
2087 SwUndoMove* pUndo = new SwUndoMove( pDoc, rRg, rPos );
2088 ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
2089 pDoc->MoveNodeRange( rRg, rPos, (pSaveTbl->IsNewModel()) ?
2090 IDocumentContentOperations::DOC_NO_DELFRMS :
2091 IDocumentContentOperations::DOC_MOVEDEFAULT );
2092 ++aTmp;
2093 ++aTmp2;
2094 pUndo->SetDestRange( aTmp2, rPos, aTmp );
2096 pMoves->push_back( pUndo );
2099 void SwUndoTblMerge::SetSelBoxes( const SwSelBoxes& rBoxes )
2101 // memorize selection
2102 for (size_t n = 0; n < rBoxes.size(); ++n)
2104 m_Boxes.insert(rBoxes[n]->GetSttIdx());
2107 // as separator for inserts of new boxes after shifting
2108 aNewSttNds.push_back( (sal_uLong)0 );
2110 // The new table model does not delete overlapped cells (by row span),
2111 // so the rBoxes array might be empty even some cells have been merged.
2112 if( !rBoxes.empty() )
2113 nTblNode = rBoxes[ 0 ]->GetSttNd()->FindTableNode()->GetIndex();
2116 void SwUndoTblMerge::SaveCollection( const SwTableBox& rBox )
2118 if( !pHistory )
2119 pHistory = new SwHistory;
2121 SwNodeIndex aIdx( *rBox.GetSttNd(), 1 );
2122 SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
2123 if( !pCNd )
2124 pCNd = aIdx.GetNodes().GoNext( &aIdx );
2126 pHistory->Add( pCNd->GetFmtColl(), aIdx.GetIndex(), pCNd->GetNodeType());
2127 if( pCNd->HasSwAttrSet() )
2128 pHistory->CopyFmtAttr( *pCNd->GetpSwAttrSet(), aIdx.GetIndex() );
2131 SwUndoTblNumFmt::SwUndoTblNumFmt( const SwTableBox& rBox,
2132 const SfxItemSet* pNewSet )
2133 : SwUndo( UNDO_TBLNUMFMT ),
2134 pBoxSet( 0 ), pHistory( 0 ), nFmtIdx( NUMBERFORMAT_TEXT )
2136 bNewFmt = bNewFml = bNewValue = sal_False;
2137 nNode = rBox.GetSttIdx();
2139 nNdPos = rBox.IsValidNumTxtNd( 0 == pNewSet );
2140 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
2142 if( ULONG_MAX != nNdPos )
2144 SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
2146 pHistory = new SwHistory;
2147 SwRegHistory aRHst( *rBox.GetSttNd(), pHistory );
2148 // always save all text atttibutes because of possibly overlapping
2149 // areas of on/off
2150 pHistory->CopyAttr( pTNd->GetpSwpHints(), nNdPos, 0,
2151 pTNd->GetTxt().getLength(), true );
2153 if( pTNd->HasSwAttrSet() )
2154 pHistory->CopyFmtAttr( *pTNd->GetpSwAttrSet(), nNdPos );
2156 aStr = pTNd->GetTxt();
2157 if( pTNd->GetpSwpHints() )
2158 pTNd->GetpSwpHints()->DeRegister();
2161 pBoxSet = new SfxItemSet( pDoc->GetAttrPool(), aTableBoxSetRange );
2162 pBoxSet->Put( rBox.GetFrmFmt()->GetAttrSet() );
2164 if( pNewSet )
2166 const SfxPoolItem* pItem;
2167 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMAT,
2168 sal_False, &pItem ))
2170 bNewFmt = sal_True;
2171 nNewFmtIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
2173 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMULA,
2174 sal_False, &pItem ))
2176 bNewFml = sal_True;
2177 aNewFml = ((SwTblBoxFormula*)pItem)->GetFormula();
2179 if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_VALUE,
2180 sal_False, &pItem ))
2182 bNewValue = sal_True;
2183 fNewNum = ((SwTblBoxValue*)pItem)->GetValue();
2187 // is a history needed at all?
2188 if( pHistory && !pHistory->Count() )
2189 DELETEZ( pHistory );
2192 SwUndoTblNumFmt::~SwUndoTblNumFmt()
2194 delete pHistory;
2195 delete pBoxSet;
2198 void SwUndoTblNumFmt::UndoImpl(::sw::UndoRedoContext & rContext)
2200 OSL_ENSURE( pBoxSet, "Where's the stored item set?" );
2202 SwDoc & rDoc = rContext.GetDoc();
2203 SwStartNode* pSttNd = rDoc.GetNodes()[ nNode ]->
2204 FindSttNodeByType( SwTableBoxStartNode );
2205 OSL_ENSURE( pSttNd, "without StartNode no TableBox" );
2206 SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
2207 pSttNd->GetIndex() );
2208 OSL_ENSURE( pBox, "found no TableBox" );
2210 SwTableBoxFmt* pFmt = rDoc.MakeTableBoxFmt();
2211 pFmt->SetFmtAttr( *pBoxSet );
2212 pBox->ChgFrmFmt( pFmt );
2214 if( ULONG_MAX == nNdPos )
2215 return;
2217 SwTxtNode* pTxtNd = rDoc.GetNodes()[ nNdPos ]->GetTxtNode();
2218 // If more than one node was deleted than all "node" attributes were also
2219 // saved
2220 if( pTxtNd->HasSwAttrSet() )
2221 pTxtNd->ResetAllAttr();
2223 if( pTxtNd->GetpSwpHints() && aStr.Len() )
2224 pTxtNd->ClearSwpHintsArr( true );
2226 // ChgTextToNum(..) only acts when the strings are different. We need to do
2227 // the same here.
2228 if( pTxtNd->GetTxt() != aStr )
2230 rDoc.DeleteRedline( *( pBox->GetSttNd() ), false, USHRT_MAX );
2232 SwIndex aIdx( pTxtNd, 0 );
2233 if( aStr.Len() )
2235 pTxtNd->EraseText( aIdx );
2236 pTxtNd->InsertText( aStr, aIdx,
2237 IDocumentContentOperations::INS_NOHINTEXPAND );
2241 if( pHistory )
2243 sal_uInt16 nTmpEnd = pHistory->GetTmpEnd();
2244 pHistory->TmpRollback( &rDoc, 0 );
2245 pHistory->SetTmpEnd( nTmpEnd );
2248 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2249 pPam->DeleteMark();
2250 pPam->GetPoint()->nNode = nNode + 1;
2251 pPam->GetPoint()->nContent.Assign( pTxtNd, 0 );
2254 /** switch the RedlineMode on the given document, using
2255 * SetRedlineMode_intern. This class set the mode in the constructor,
2256 * and changes it back in the destructor, i.e. it uses the
2257 * initialization-is-resource-acquisition idiom.
2259 class RedlineModeInternGuard
2261 SwDoc& mrDoc;
2262 RedlineMode_t meOldRedlineMode;
2264 public:
2265 RedlineModeInternGuard(
2266 SwDoc& rDoc, // change mode of this document
2267 RedlineMode_t eNewRedlineMode, // new redline mode
2268 RedlineMode_t eRedlineModeMask = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE /*change only bits set in this mask*/));
2270 ~RedlineModeInternGuard();
2273 RedlineModeInternGuard::RedlineModeInternGuard(
2274 SwDoc& rDoc,
2275 RedlineMode_t eNewRedlineMode,
2276 RedlineMode_t eRedlineModeMask )
2277 : mrDoc( rDoc ),
2278 meOldRedlineMode( rDoc.GetRedlineMode() )
2280 mrDoc.SetRedlineMode_intern((RedlineMode_t)( ( meOldRedlineMode & ~eRedlineModeMask ) |
2281 ( eNewRedlineMode & eRedlineModeMask ) ));
2284 RedlineModeInternGuard::~RedlineModeInternGuard()
2286 mrDoc.SetRedlineMode_intern( meOldRedlineMode );
2289 void SwUndoTblNumFmt::RedoImpl(::sw::UndoRedoContext & rContext)
2291 // Could the box be changed?
2292 if( !pBoxSet )
2293 return ;
2295 SwDoc & rDoc = rContext.GetDoc();
2296 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2298 pPam->DeleteMark();
2299 pPam->GetPoint()->nNode = nNode;
2301 SwNode * pNd = & pPam->GetPoint()->nNode.GetNode();
2302 SwStartNode* pSttNd = pNd->FindSttNodeByType( SwTableBoxStartNode );
2303 OSL_ENSURE( pSttNd, "without StartNode no TableBox" );
2304 SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
2305 pSttNd->GetIndex() );
2306 OSL_ENSURE( pBox, "found no TableBox" );
2308 SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt();
2309 if( bNewFmt || bNewFml || bNewValue )
2311 SfxItemSet aBoxSet( rDoc.GetAttrPool(),
2312 RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2314 // Resetting attributes is not enough. In addition, take care that the
2315 // text will be also formatted correctly.
2316 pBoxFmt->LockModify();
2318 if( bNewFml )
2319 aBoxSet.Put( SwTblBoxFormula( aNewFml ));
2320 else
2321 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
2322 if( bNewFmt )
2323 aBoxSet.Put( SwTblBoxNumFormat( nNewFmtIdx ));
2324 else
2325 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT );
2326 if( bNewValue )
2327 aBoxSet.Put( SwTblBoxValue( fNewNum ));
2328 else
2329 pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE );
2330 pBoxFmt->UnlockModify();
2332 // dvo: When redlining is (was) enabled, setting the attribute
2333 // will also change the cell content. To allow this, the
2334 // REDLINE_IGNORE flag must be removed during Redo. #108450#
2335 RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE );
2336 pBoxFmt->SetFmtAttr( aBoxSet );
2338 else if( NUMBERFORMAT_TEXT != nFmtIdx )
2340 SfxItemSet aBoxSet( rDoc.GetAttrPool(),
2341 RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2343 aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx ));
2344 aBoxSet.Put( SwTblBoxValue( fNum ));
2346 // Resetting attributes is not enough. In addition, take care that the
2347 // text will be also formatted correctly.
2348 pBoxFmt->LockModify();
2349 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
2350 pBoxFmt->UnlockModify();
2352 // dvo: When redlining is (was) enabled, setting the attribute
2353 // will also change the cell content. To allow this, the
2354 // REDLINE_IGNORE flag must be removed during Redo. #108450#
2355 RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE );
2356 pBoxFmt->SetFmtAttr( aBoxSet );
2358 else
2360 // it's no number
2362 // Resetting attributes is not enough. In addition, take care that the
2363 // text will be also formatted correctly.
2364 pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
2366 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2369 if( bNewFml )
2371 // No matter what was set, an update of the table is always a good idea
2372 SwTableFmlUpdate aTblUpdate( &pSttNd->FindTableNode()->GetTable() );
2373 rDoc.UpdateTblFlds( &aTblUpdate );
2376 if( !pNd->IsCntntNode() )
2377 pNd = rDoc.GetNodes().GoNext( &pPam->GetPoint()->nNode );
2378 pPam->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
2381 void SwUndoTblNumFmt::SetBox( const SwTableBox& rBox )
2383 nNode = rBox.GetSttIdx();
2386 _UndoTblCpyTbl_Entry::_UndoTblCpyTbl_Entry( const SwTableBox& rBox )
2387 : nBoxIdx( rBox.GetSttIdx() ), nOffset( 0 ),
2388 pBoxNumAttr( 0 ), pUndo( 0 ), bJoin( false )
2392 _UndoTblCpyTbl_Entry::~_UndoTblCpyTbl_Entry()
2394 delete pUndo;
2395 delete pBoxNumAttr;
2398 SwUndoTblCpyTbl::SwUndoTblCpyTbl()
2399 : SwUndo( UNDO_TBLCPYTBL ), pInsRowUndo( 0 )
2401 pArr = new _UndoTblCpyTbl_Entries;
2404 SwUndoTblCpyTbl::~SwUndoTblCpyTbl()
2406 delete pArr;
2407 delete pInsRowUndo;
2410 void SwUndoTblCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext)
2412 SwDoc & rDoc = rContext.GetDoc();
2413 _DEBUG_REDLINE( &rDoc )
2415 SwTableNode* pTblNd = 0;
2416 for( sal_uInt16 n = pArr->size(); n; )
2418 _UndoTblCpyTbl_Entry* pEntry = &(*pArr)[ --n ];
2419 sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
2420 SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
2421 if( !pTblNd )
2422 pTblNd = pSNd->FindTableNode();
2424 SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
2426 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
2427 rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() );
2429 // b62341295: Redline for copying tables
2430 const SwNode *pEndNode = rBox.GetSttNd()->EndOfSectionNode();
2431 SwPaM aPam( aInsIdx.GetNode(), *pEndNode );
2432 SwUndoDelete* pUndo = 0;
2434 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
2436 bool bDeleteCompleteParagraph = false;
2437 bool bShiftPam = false;
2438 // There are a couple of different situations to consider during redlining
2439 if( pEntry->pUndo )
2441 SwUndoDelete *const pUndoDelete =
2442 dynamic_cast<SwUndoDelete*>(pEntry->pUndo);
2443 SwUndoRedlineDelete *const pUndoRedlineDelete =
2444 dynamic_cast<SwUndoRedlineDelete*>(pEntry->pUndo);
2445 OSL_ASSERT(pUndoDelete || pUndoRedlineDelete);
2446 if (pUndoRedlineDelete)
2448 // The old content was not empty or he has been merged with the new content
2449 bDeleteCompleteParagraph = !pEntry->bJoin; // bJoin is set when merged
2450 // Set aTmpIdx to the beginning fo the old content
2451 SwNodeIndex aTmpIdx( *pEndNode,
2452 pUndoRedlineDelete->NodeDiff()-1 );
2453 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
2454 if( pTxt )
2456 aPam.GetPoint()->nNode = *pTxt;
2457 aPam.GetPoint()->nContent.Assign( pTxt,
2458 pUndoRedlineDelete->ContentStart() );
2460 else
2461 *aPam.GetPoint() = SwPosition( aTmpIdx );
2463 else if (pUndoDelete && pUndoDelete->IsDelFullPara())
2465 // When the old content was an empty paragraph, but could not be joined
2466 // with the new content (e.g. because of a section or table)
2467 // We "save" the aPam.Point, we go one step backwards (because later on the
2468 // empty paragraph will be inserted by the undo) and set the "ShiftPam-flag
2469 // for step forward later on.
2470 bDeleteCompleteParagraph = true;
2471 bShiftPam = true;
2472 SwNodeIndex aTmpIdx( *pEndNode, -1 );
2473 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
2474 if( pTxt )
2476 aPam.GetPoint()->nNode = *pTxt;
2477 aPam.GetPoint()->nContent.Assign( pTxt, 0 );
2479 else
2480 *aPam.GetPoint() = SwPosition( aTmpIdx );
2483 rDoc.DeleteRedline( aPam, true, USHRT_MAX );
2485 if( pEntry->pUndo )
2487 pEntry->pUndo->UndoImpl(rContext);
2488 delete pEntry->pUndo;
2489 pEntry->pUndo = 0;
2491 if( bShiftPam )
2493 // The aPam.Point is at the moment at the last position of the new content and has to be
2494 // moved to the first postion of the old content for the SwUndoDelete operation
2495 SwNodeIndex aTmpIdx( aPam.GetPoint()->nNode, 1 );
2496 SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
2497 if( pTxt )
2499 aPam.GetPoint()->nNode = *pTxt;
2500 aPam.GetPoint()->nContent.Assign( pTxt, 0 );
2502 else
2503 *aPam.GetPoint() = SwPosition( aTmpIdx );
2505 pUndo = new SwUndoDelete( aPam, bDeleteCompleteParagraph, sal_True );
2507 else
2509 pUndo = new SwUndoDelete( aPam, true );
2510 if( pEntry->pUndo )
2512 pEntry->pUndo->UndoImpl(rContext);
2513 delete pEntry->pUndo;
2514 pEntry->pUndo = 0;
2517 pEntry->pUndo = pUndo;
2519 aInsIdx = rBox.GetSttIdx() + 1;
2520 rDoc.GetNodes().Delete( aInsIdx, 1 );
2522 SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
2523 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
2524 aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() );
2525 if( aTmpSet.Count() )
2527 SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
2528 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2529 pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT );
2532 if( pEntry->pBoxNumAttr )
2534 rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr );
2535 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
2538 if( aTmpSet.Count() )
2540 pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(),
2541 RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
2542 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
2543 pEntry->pBoxNumAttr->Put( aTmpSet );
2546 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
2549 if( pInsRowUndo )
2551 pInsRowUndo->UndoImpl(rContext);
2553 _DEBUG_REDLINE( &rDoc )
2556 void SwUndoTblCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext)
2558 SwDoc & rDoc = rContext.GetDoc();
2559 _DEBUG_REDLINE( &rDoc )
2561 if( pInsRowUndo )
2563 pInsRowUndo->RedoImpl(rContext);
2566 SwTableNode* pTblNd = 0;
2567 for( sal_uInt16 n = 0; n < pArr->size(); ++n )
2569 _UndoTblCpyTbl_Entry* pEntry = &(*pArr)[ n ];
2570 sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
2571 SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
2572 if( !pTblNd )
2573 pTblNd = pSNd->FindTableNode();
2575 SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
2577 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
2579 // b62341295: Redline for copying tables - Start.
2580 rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() );
2581 SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode());
2582 SwUndo* pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ? 0 : new SwUndoDelete( aPam, sal_True );
2583 if( pEntry->pUndo )
2585 pEntry->pUndo->UndoImpl(rContext);
2586 if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
2588 // PrepareRedline has to be called with the beginning of the old content
2589 // When new and old content has been joined, the rIter.pAktPam has been set
2590 // by the Undo operation to this point.
2591 // Otherwise aInsIdx has been moved during the Undo operation
2592 if( pEntry->bJoin )
2594 SwPaM const& rLastPam =
2595 rContext.GetCursorSupplier().GetCurrentShellCursor();
2596 pUndo = PrepareRedline( &rDoc, rBox, *rLastPam.GetPoint(),
2597 pEntry->bJoin, true );
2599 else
2601 SwPosition aTmpPos( aInsIdx );
2602 pUndo = PrepareRedline( &rDoc, rBox, aTmpPos, pEntry->bJoin, true );
2605 delete pEntry->pUndo;
2606 pEntry->pUndo = 0;
2608 pEntry->pUndo = pUndo;
2609 // b62341295: Redline for copying tables - End.
2611 aInsIdx = rBox.GetSttIdx() + 1;
2612 rDoc.GetNodes().Delete( aInsIdx, 1 );
2614 SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
2615 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
2616 aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() );
2617 if( aTmpSet.Count() )
2619 SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
2620 pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
2621 pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT );
2623 if( pEntry->pBoxNumAttr )
2625 rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr );
2626 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
2629 if( aTmpSet.Count() )
2631 pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(),
2632 RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
2633 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
2634 pEntry->pBoxNumAttr->Put( aTmpSet );
2637 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
2639 _DEBUG_REDLINE( &rDoc )
2642 void SwUndoTblCpyTbl::AddBoxBefore( const SwTableBox& rBox, bool bDelCntnt )
2644 if( !pArr->empty() && !bDelCntnt )
2645 return;
2647 _UndoTblCpyTbl_Entry* pEntry = new _UndoTblCpyTbl_Entry( rBox );
2648 pArr->push_back( pEntry );
2650 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
2651 _DEBUG_REDLINE( pDoc )
2652 if( bDelCntnt )
2654 SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
2655 pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
2656 SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );
2658 if( !pDoc->IsRedlineOn() )
2659 pEntry->pUndo = new SwUndoDelete( aPam, sal_True );
2662 pEntry->pBoxNumAttr = new SfxItemSet( pDoc->GetAttrPool(),
2663 RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
2664 RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
2665 pEntry->pBoxNumAttr->Put( rBox.GetFrmFmt()->GetAttrSet() );
2666 if( !pEntry->pBoxNumAttr->Count() )
2667 delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
2668 _DEBUG_REDLINE( pDoc )
2671 void SwUndoTblCpyTbl::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx, bool bDelCntnt )
2673 _UndoTblCpyTbl_Entry* pEntry = &(*pArr).back();
2675 // If the content was deleted than remove also the temporarily created node
2676 if( bDelCntnt )
2678 SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
2679 _DEBUG_REDLINE( pDoc )
2681 if( pDoc->IsRedlineOn() )
2683 SwPosition aTmpPos( rIdx );
2684 pEntry->pUndo = PrepareRedline( pDoc, rBox, aTmpPos, pEntry->bJoin, false );
2686 SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 );
2687 rBox.GetFrmFmt()->GetDoc()->GetNodes().Delete( aDelIdx, 1 );
2688 _DEBUG_REDLINE( pDoc )
2691 pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
2694 // PrepareRedline is called from AddBoxAfter() and from Redo() in slightly different situations.
2695 // bRedo is set by calling from Redo()
2696 // rJoin is false by calling from AddBoxAfter() and will be set if the old and new content has
2697 // been merged.
2698 // rJoin is true if Redo() is calling and the content has already been merged
2700 SwUndo* SwUndoTblCpyTbl::PrepareRedline( SwDoc* pDoc, const SwTableBox& rBox,
2701 const SwPosition& rPos, bool& rJoin, bool bRedo )
2703 SwUndo *pUndo = 0;
2704 // b62341295: Redline for copying tables
2705 // What's to do?
2706 // Mark the cell content before rIdx as insertion,
2707 // mark the cell content behind rIdx as deletion
2708 // merge text nodes at rIdx if possible
2709 RedlineMode_t eOld = pDoc->GetRedlineMode();
2710 pDoc->SetRedlineMode_intern((RedlineMode_t)( ( eOld | nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &
2711 ~nsRedlineMode_t::REDLINE_IGNORE ));
2712 SwPosition aInsertEnd( rPos );
2713 SwTxtNode* pTxt;
2714 if( !rJoin )
2716 // If the content is not merged, the end of the insertion is at the end of the node
2717 // _before_ the given position rPos
2718 --aInsertEnd.nNode;
2719 pTxt = aInsertEnd.nNode.GetNode().GetTxtNode();
2720 if( pTxt )
2722 aInsertEnd.nContent.Assign(pTxt, pTxt->GetTxt().getLength());
2723 if( !bRedo && rPos.nNode.GetNode().GetTxtNode() )
2724 { // Try to merge, if not called by Redo()
2725 rJoin = true;
2726 pTxt->JoinNext();
2729 else
2730 aInsertEnd.nContent = SwIndex( 0 );
2732 // For joined (merged) contents the start of deletion and end of insertion are identical
2733 // otherwise adjacent nodes.
2734 SwPosition aDeleteStart( rJoin ? aInsertEnd : rPos );
2735 if( !rJoin )
2737 pTxt = aDeleteStart.nNode.GetNode().GetTxtNode();
2738 if( pTxt )
2739 aDeleteStart.nContent.Assign( pTxt, 0 );
2741 SwPosition aCellEnd( SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode(), -1 ) );
2742 pTxt = aCellEnd.nNode.GetNode().GetTxtNode();
2743 if( pTxt )
2744 aCellEnd.nContent.Assign(pTxt, pTxt->GetTxt().getLength());
2745 if( aDeleteStart != aCellEnd )
2746 { // If the old (deleted) part is not empty, here we are...
2747 SwPaM aDeletePam( aDeleteStart, aCellEnd );
2748 pUndo = new SwUndoRedlineDelete( aDeletePam, UNDO_DELETE );
2749 pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDeletePam ), true );
2751 else if( !rJoin ) // If the old part is empty and joined, we are finished
2752 { // if it is not joined, we have to delete this empty paragraph
2753 aCellEnd = SwPosition(
2754 SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() ));
2755 SwPaM aTmpPam( aDeleteStart, aCellEnd );
2756 pUndo = new SwUndoDelete( aTmpPam, sal_True );
2758 SwPosition aCellStart( SwNodeIndex( *rBox.GetSttNd(), 2 ) );
2759 pTxt = aCellStart.nNode.GetNode().GetTxtNode();
2760 if( pTxt )
2761 aCellStart.nContent.Assign( pTxt, 0 );
2762 if( aCellStart != aInsertEnd ) // An empty insertion will not been marked
2764 SwPaM aTmpPam( aCellStart, aInsertEnd );
2765 pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aTmpPam ), true );
2768 pDoc->SetRedlineMode_intern( eOld );
2769 return pUndo;
2772 bool SwUndoTblCpyTbl::InsertRow( SwTable& rTbl, const SwSelBoxes& rBoxes,
2773 sal_uInt16 nCnt )
2775 SwTableNode* pTblNd = (SwTableNode*)rTbl.GetTabSortBoxes()[0]->
2776 GetSttNd()->FindTableNode();
2778 pInsRowUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW, rBoxes, *pTblNd,
2779 0, 0, nCnt, sal_True, sal_False );
2780 SwTableSortBoxes aTmpLst( rTbl.GetTabSortBoxes() );
2782 bool bRet = rTbl.InsertRow( rTbl.GetFrmFmt()->GetDoc(), rBoxes, nCnt, true );
2783 if( bRet )
2784 pInsRowUndo->SaveNewBoxes( *pTblNd, aTmpLst );
2785 else
2786 delete pInsRowUndo, pInsRowUndo = 0;
2787 return bRet;
2790 sal_Bool SwUndoTblCpyTbl::IsEmpty() const
2792 return !pInsRowUndo && pArr->empty();
2795 SwUndoCpyTbl::SwUndoCpyTbl()
2796 : SwUndo( UNDO_CPYTBL ), pDel( 0 ), nTblNode( 0 )
2800 SwUndoCpyTbl::~SwUndoCpyTbl()
2802 delete pDel;
2805 void SwUndoCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext)
2807 SwDoc & rDoc = rContext.GetDoc();
2808 SwTableNode* pTNd = rDoc.GetNodes()[ nTblNode ]->GetTableNode();
2810 // move hard page breaks into next node
2811 SwCntntNode* pNextNd = rDoc.GetNodes()[ pTNd->EndOfSectionIndex()+1 ]->GetCntntNode();
2812 if( pNextNd )
2814 SwFrmFmt* pTableFmt = pTNd->GetTable().GetFrmFmt();
2815 const SfxPoolItem *pItem;
2817 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
2818 sal_False, &pItem ) )
2819 pNextNd->SetAttr( *pItem );
2821 if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
2822 sal_False, &pItem ) )
2823 pNextNd->SetAttr( *pItem );
2826 SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 );
2827 pDel = new SwUndoDelete( aPam, sal_True );
2830 void SwUndoCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext)
2832 pDel->UndoImpl(rContext);
2833 delete pDel, pDel = 0;
2836 SwUndoSplitTbl::SwUndoSplitTbl( const SwTableNode& rTblNd,
2837 SwSaveRowSpan* pRowSp, sal_uInt16 eMode, sal_Bool bNewSize )
2838 : SwUndo( UNDO_SPLIT_TABLE ),
2839 nTblNode( rTblNd.GetIndex() ), nOffset( 0 ), mpSaveRowSpan( pRowSp ), pSavTbl( 0 ),
2840 pHistory( 0 ), nMode( eMode ), nFmlEnd( 0 ), bCalcNewSize( bNewSize )
2842 switch( nMode )
2844 case HEADLINE_BOXATRCOLLCOPY:
2845 pHistory = new SwHistory;
2846 // no break
2847 case HEADLINE_BORDERCOPY:
2848 case HEADLINE_BOXATTRCOPY:
2849 pSavTbl = new _SaveTable( rTblNd.GetTable(), 1, false );
2850 break;
2854 SwUndoSplitTbl::~SwUndoSplitTbl()
2856 delete pSavTbl;
2857 delete pHistory;
2858 delete mpSaveRowSpan;
2861 void SwUndoSplitTbl::UndoImpl(::sw::UndoRedoContext & rContext)
2863 SwDoc *const pDoc = & rContext.GetDoc();
2864 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2866 pPam->DeleteMark();
2867 SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
2868 rIdx = nTblNode + nOffset;
2870 // remove implicitly created paragraph again
2871 pDoc->GetNodes().Delete( rIdx, 1 );
2873 rIdx = nTblNode + nOffset;
2874 SwTableNode* pTblNd = rIdx.GetNode().GetTableNode();
2875 SwTable& rTbl = pTblNd->GetTable();
2877 SwTableFmlUpdate aMsgHnt( &rTbl );
2878 aMsgHnt.eFlags = TBL_BOXPTR;
2879 pDoc->UpdateTblFlds( &aMsgHnt );
2881 switch( nMode )
2883 case HEADLINE_BOXATRCOLLCOPY:
2884 if( pHistory )
2885 pHistory->TmpRollback( pDoc, nFmlEnd );
2886 // no break
2887 case HEADLINE_BOXATTRCOPY:
2888 case HEADLINE_BORDERCOPY:
2890 pSavTbl->CreateNew( rTbl, false );
2891 pSavTbl->RestoreAttr( rTbl );
2893 break;
2895 case HEADLINE_CNTNTCOPY:
2896 // the created first line has to be removed again
2898 SwSelBoxes aSelBoxes;
2899 SwTableBox* pBox = rTbl.GetTblBox( nTblNode + nOffset + 1 );
2900 rTbl.SelLineFromBox( pBox, aSelBoxes, true );
2901 _FndBox aTmpBox( 0, 0 );
2902 aTmpBox.SetTableLines( aSelBoxes, rTbl );
2903 aTmpBox.DelFrms( rTbl );
2904 rTbl.DeleteSel( pDoc, aSelBoxes, 0, 0, false, false );
2906 break;
2909 pDoc->GetNodes().MergeTable( rIdx );
2911 if( pHistory )
2913 pHistory->TmpRollback( pDoc, 0 );
2914 pHistory->SetTmpEnd( pHistory->Count() );
2916 if( mpSaveRowSpan )
2918 pTblNd = rIdx.GetNode().FindTableNode();
2919 if( pTblNd )
2920 pTblNd->GetTable().RestoreRowSpan( *mpSaveRowSpan );
2922 ClearFEShellTabCols();
2925 void SwUndoSplitTbl::RedoImpl(::sw::UndoRedoContext & rContext)
2927 SwDoc *const pDoc = & rContext.GetDoc();
2928 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2930 pPam->DeleteMark();
2931 pPam->GetPoint()->nNode = nTblNode;
2932 pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
2934 ClearFEShellTabCols();
2937 void SwUndoSplitTbl::RepeatImpl(::sw::RepeatContext & rContext)
2939 SwPaM *const pPam = & rContext.GetRepeatPaM();
2940 SwDoc *const pDoc = & rContext.GetDoc();
2942 pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
2943 ClearFEShellTabCols();
2946 void SwUndoSplitTbl::SaveFormula( SwHistory& rHistory )
2948 if( !pHistory )
2949 pHistory = new SwHistory;
2951 nFmlEnd = rHistory.Count();
2952 pHistory->Move( 0, &rHistory );
2955 SwUndoMergeTbl::SwUndoMergeTbl( const SwTableNode& rTblNd,
2956 const SwTableNode& rDelTblNd,
2957 sal_Bool bWithPrv, sal_uInt16 nMd )
2958 : SwUndo( UNDO_MERGE_TABLE ), pSavTbl( 0 ),
2959 pHistory( 0 ), nMode( nMd ), bWithPrev( bWithPrv )
2961 // memorize end node of the last table cell that'll stay in position
2962 if( bWithPrev )
2963 nTblNode = rDelTblNd.EndOfSectionIndex() - 1;
2964 else
2965 nTblNode = rTblNd.EndOfSectionIndex() - 1;
2967 aName = rDelTblNd.GetTable().GetFrmFmt()->GetName();
2968 pSavTbl = new _SaveTable( rDelTblNd.GetTable() );
2970 pSavHdl = bWithPrev ? new _SaveTable( rTblNd.GetTable(), 1 ) : 0;
2973 SwUndoMergeTbl::~SwUndoMergeTbl()
2975 delete pSavTbl;
2976 delete pSavHdl;
2977 delete pHistory;
2980 void SwUndoMergeTbl::UndoImpl(::sw::UndoRedoContext & rContext)
2982 SwDoc *const pDoc = & rContext.GetDoc();
2983 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
2985 pPam->DeleteMark();
2986 SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
2987 rIdx = nTblNode;
2989 SwTableNode* pTblNd = rIdx.GetNode().FindTableNode();
2990 SwTable* pTbl = &pTblNd->GetTable();
2992 SwTableFmlUpdate aMsgHnt( pTbl );
2993 aMsgHnt.eFlags = TBL_BOXPTR;
2994 pDoc->UpdateTblFlds( &aMsgHnt );
2996 // get lines for layout update
2997 _FndBox aFndBox( 0, 0 );
2998 aFndBox.SetTableLines( *pTbl );
2999 aFndBox.DelFrms( *pTbl );
3000 // ? TL_CHART2: notification or locking of controller required ?
3002 SwTableNode* pNew = pDoc->GetNodes().SplitTable( rIdx, sal_True, sal_False );
3004 // update layout
3005 aFndBox.MakeFrms( *pTbl );
3006 // ? TL_CHART2: notification or locking of controller required ?
3008 if( bWithPrev )
3010 // move name
3011 pNew->GetTable().GetFrmFmt()->SetName( pTbl->GetFrmFmt()->GetName() );
3012 pSavHdl->RestoreAttr( pNew->GetTable() );
3014 else
3015 pTbl = &pNew->GetTable();
3017 pTbl->GetFrmFmt()->SetName( aName );
3018 pSavTbl->RestoreAttr( *pTbl );
3020 if( pHistory )
3022 pHistory->TmpRollback( pDoc, 0 );
3023 pHistory->SetTmpEnd( pHistory->Count() );
3026 // create frames for the new table
3027 SwNodeIndex aTmpIdx( *pNew );
3028 pNew->MakeFrms( &aTmpIdx );
3030 // position cursor somewhere in content
3031 SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &rIdx );
3032 pPam->GetPoint()->nContent.Assign( pCNd, 0 );
3034 ClearFEShellTabCols();
3036 // TL_CHART2: need to inform chart of probably changed cell names
3037 SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
3038 if (pPCD)
3040 pDoc->UpdateCharts( pTbl->GetFrmFmt()->GetName() );
3041 pDoc->UpdateCharts( pNew->GetTable().GetFrmFmt()->GetName() );
3045 void SwUndoMergeTbl::RedoImpl(::sw::UndoRedoContext & rContext)
3047 SwDoc *const pDoc = & rContext.GetDoc();
3048 SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
3050 pPam->DeleteMark();
3051 pPam->GetPoint()->nNode = nTblNode;
3052 if( bWithPrev )
3053 pPam->GetPoint()->nNode = nTblNode + 3;
3054 else
3055 pPam->GetPoint()->nNode = nTblNode;
3057 pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode );
3059 ClearFEShellTabCols();
3062 void SwUndoMergeTbl::RepeatImpl(::sw::RepeatContext & rContext)
3064 SwDoc *const pDoc = & rContext.GetDoc();
3065 SwPaM *const pPam = & rContext.GetRepeatPaM();
3067 pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode );
3068 ClearFEShellTabCols();
3071 void SwUndoMergeTbl::SaveFormula( SwHistory& rHistory )
3073 if( !pHistory )
3074 pHistory = new SwHistory;
3075 pHistory->Move( 0, &rHistory );
3078 void InsertSort( std::vector<sal_uInt16>& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos )
3080 sal_uInt16 nO = rArr.size(), nM, nU = 0;
3081 if( nO > 0 )
3083 nO--;
3084 while( nU <= nO )
3086 nM = nU + ( nO - nU ) / 2;
3087 if ( rArr[nM] == nIdx )
3089 OSL_FAIL( "Index already exists. This should never happen." );
3090 return;
3092 if( rArr[nM] < nIdx )
3093 nU = nM + 1;
3094 else if( nM == 0 )
3095 break;
3096 else
3097 nO = nM - 1;
3100 rArr.insert( rArr.begin() + nU, nIdx );
3101 if( pInsPos )
3102 *pInsPos = nU;
3105 #if OSL_DEBUG_LEVEL > 0
3106 void CheckTable( const SwTable& rTbl )
3108 const SwNodes& rNds = rTbl.GetFrmFmt()->GetDoc()->GetNodes();
3109 const SwTableSortBoxes& rSrtArr = rTbl.GetTabSortBoxes();
3110 for (size_t n = 0; n < rSrtArr.size(); ++n)
3112 const SwTableBox* pBox = rSrtArr[ n ];
3113 const SwNode* pNd = pBox->GetSttNd();
3114 OSL_ENSURE( rNds[ pBox->GetSttIdx() ] == pNd, "Box with wrong StartNode" );
3117 #endif
3119 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */