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