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