summaryrefslogtreecommitdiff
path: root/sw/source/core/undo/untbl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/undo/untbl.cxx')
-rw-r--r--sw/source/core/undo/untbl.cxx3269
1 files changed, 3269 insertions, 0 deletions
diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
new file mode 100644
index 000000000000..ee16891ab5e1
--- /dev/null
+++ b/sw/source/core/undo/untbl.cxx
@@ -0,0 +1,3269 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <UndoTable.hxx>
+
+#include <UndoRedline.hxx>
+#include <UndoDelete.hxx>
+#include <UndoSplitMove.hxx>
+#include <UndoCore.hxx>
+#include <hintids.hxx>
+#include <hints.hxx>
+#include <editeng/brkitem.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <editsh.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx>
+#include <swtable.hxx>
+#include <pam.hxx>
+#include <cntfrm.hxx>
+#include <tblsel.hxx>
+#include <swundo.hxx> // fuer die UndoIds
+#include <rolbck.hxx>
+#include <ddefld.hxx>
+#include <tabcol.hxx>
+#include <tabfrm.hxx>
+#include <rowfrm.hxx>
+#include <cellfrm.hxx>
+#include <swcache.hxx>
+#include <tblafmt.hxx>
+#include <poolfmt.hxx>
+#include <mvsave.hxx>
+#include <cellatr.hxx>
+#include <swtblfmt.hxx>
+#include <swddetbl.hxx>
+#include <redline.hxx>
+#include <node2lay.hxx>
+#include <tblrwcl.hxx>
+#include <fmtanchr.hxx>
+#include <comcore.hrc>
+#include <unochart.hxx>
+#include <switerator.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#define CHECK_TABLE(t) (t).CheckConsistency();
+#else
+#define CHECK_TABLE(t)
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+ void lcl_DebugRedline( const SwDoc* pDoc );
+ #define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
+#else
+ #define _DEBUG_REDLINE( pDoc )
+#endif
+
+extern void ClearFEShellTabCols();
+
+typedef SfxItemSet* SfxItemSetPtr;
+SV_DECL_PTRARR_DEL( SfxItemSets, SfxItemSetPtr, 10, 5 )
+
+typedef SwUndoSaveSection* SwUndoSaveSectionPtr;
+SV_DECL_PTRARR_DEL( SwUndoSaveSections, SwUndoSaveSectionPtr, 0, 10 )
+
+typedef SwUndoMove* SwUndoMovePtr;
+SV_DECL_PTRARR_DEL( SwUndoMoves, SwUndoMovePtr, 0, 10 )
+
+struct SwTblToTxtSave;
+typedef SwTblToTxtSave* SwTblToTxtSavePtr;
+SV_DECL_PTRARR_DEL( SwTblToTxtSaves, SwTblToTxtSavePtr, 0, 10 )
+
+struct _UndoTblCpyTbl_Entry
+{
+ sal_uLong nBoxIdx, nOffset;
+ SfxItemSet* pBoxNumAttr;
+ SwUndo* pUndo;
+
+ // Was the last paragraph of the new and the first paragraph of the old content joined?
+ bool bJoin; // For redlining only
+
+ _UndoTblCpyTbl_Entry( const SwTableBox& rBox );
+ ~_UndoTblCpyTbl_Entry();
+};
+typedef _UndoTblCpyTbl_Entry* _UndoTblCpyTbl_EntryPtr;
+SV_DECL_PTRARR_DEL( _UndoTblCpyTbl_Entries, _UndoTblCpyTbl_EntryPtr, 0, 10 )
+
+class _SaveBox;
+class _SaveLine;
+
+class _SaveTable
+{
+ friend class _SaveBox;
+ friend class _SaveLine;
+ SfxItemSet aTblSet;
+ _SaveLine* pLine;
+ const SwTable* pSwTable;
+ SfxItemSets aSets;
+ SwFrmFmts aFrmFmts;
+ sal_uInt16 nLineCount;
+ sal_Bool bModifyBox : 1;
+ sal_Bool bSaveFormula : 1;
+ sal_Bool bNewModel : 1;
+
+public:
+ _SaveTable( const SwTable& rTbl, sal_uInt16 nLnCnt = USHRT_MAX,
+ sal_Bool bSaveFml = sal_True );
+ ~_SaveTable();
+
+ sal_uInt16 AddFmt( SwFrmFmt* pFmt, bool bIsLine );
+ void NewFrmFmt( const SwTableLine* , const SwTableBox*, sal_uInt16 nFmtPos,
+ SwFrmFmt* pOldFmt );
+
+ void RestoreAttr( SwTable& rTbl, sal_Bool bModifyBox = sal_False );
+ void SaveCntntAttrs( SwDoc* pDoc );
+ void CreateNew( SwTable& rTbl, sal_Bool bCreateFrms = sal_True,
+ sal_Bool bRestoreChart = sal_True );
+ sal_Bool IsNewModel() const { return bNewModel; }
+};
+
+class _SaveLine
+{
+ friend class _SaveTable;
+ friend class _SaveBox;
+
+ _SaveLine* pNext;
+ _SaveBox* pBox;
+ sal_uInt16 nItemSet;
+
+public:
+
+ _SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl );
+ ~_SaveLine();
+
+ void RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl );
+ void SaveCntntAttrs( SwDoc* pDoc );
+
+ void CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl );
+};
+
+class _SaveBox
+{
+ friend class _SaveLine;
+
+ _SaveBox* pNext;
+ sal_uLong nSttNode;
+ long nRowSpan;
+ sal_uInt16 nItemSet;
+ union
+ {
+ SfxItemSets* pCntntAttrs;
+ _SaveLine* pLine;
+ } Ptrs;
+
+public:
+ _SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl );
+ ~_SaveBox();
+
+ void RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl );
+ void SaveCntntAttrs( SwDoc* pDoc );
+
+ void CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl );
+};
+
+void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 );
+void InsertSort( SvULongs& rArr, sal_uLong nIdx, sal_uInt16* pInsPos = 0 );
+
+#if OSL_DEBUG_LEVEL > 1
+#include "shellio.hxx"
+void CheckTable( const SwTable& );
+#define CHECKTABLE(t) CheckTable( t );
+#else
+#define CHECKTABLE(t)
+#endif
+
+/* #130880: Crash in undo of table to text when the table has (freshly) merged cells
+The order of cell content nodes in the nodes array is not given by the recursive table structure.
+The algorithmn must not rely on this even it holds for a fresh loaded table in odt file format.
+So we need to remember not only the start node position but the end node position as well.
+*/
+
+struct SwTblToTxtSave
+{
+ sal_uLong m_nSttNd;
+ sal_uLong m_nEndNd;
+ xub_StrLen m_nCntnt;
+ SwHistory* m_pHstry;
+ // metadata references for first and last paragraph in cell
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoStart;
+ ::boost::shared_ptr< ::sfx2::MetadatableUndo > m_pMetadataUndoEnd;
+
+ SwTblToTxtSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, xub_StrLen nCntnt );
+ ~SwTblToTxtSave() { delete m_pHstry; }
+};
+
+SV_IMPL_PTRARR( SfxItemSets, SfxItemSetPtr )
+SV_IMPL_PTRARR( SwUndoSaveSections, SwUndoSaveSectionPtr )
+SV_IMPL_PTRARR( SwUndoMoves, SwUndoMovePtr )
+SV_IMPL_PTRARR( SwTblToTxtSaves, SwTblToTxtSavePtr )
+SV_IMPL_PTRARR( _UndoTblCpyTbl_Entries, _UndoTblCpyTbl_EntryPtr )
+
+sal_uInt16 aSave_BoxCntntSet[] = {
+ RES_CHRATR_COLOR, RES_CHRATR_CROSSEDOUT,
+ RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
+ RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
+ RES_CHRATR_SHADOWED, RES_CHRATR_WEIGHT,
+ RES_PARATR_ADJUST, RES_PARATR_ADJUST,
+ 0 };
+
+
+
+SwUndoInsTbl::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)
+ : SwUndo( UNDO_INSTABLE ),
+ aInsTblOpts( rInsTblOpts ), pDDEFldType( 0 ), pColWidth( 0 ), pRedlData( 0 ), pAutoFmt( 0 ),
+ nSttNode( rPos.nNode.GetIndex() ), nRows( nRw ), nCols( nCl ), nAdjust( nAdj )
+{
+ if( pColArr )
+ {
+ pColWidth = new SvUShorts( 0, 1 );
+ pColWidth->Insert( pColArr, 0 );
+ }
+ if( pTAFmt )
+ pAutoFmt = new SwTableAutoFmt( *pTAFmt );
+
+ // Redline beachten
+ SwDoc& rDoc = *rPos.nNode.GetNode().GetDoc();
+ if( rDoc.IsRedlineOn() )
+ {
+ pRedlData = new SwRedlineData( nsRedlineType_t::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
+ SetRedlineMode( rDoc.GetRedlineMode() );
+ }
+
+ sTblNm = rName;
+}
+
+
+SwUndoInsTbl::~SwUndoInsTbl()
+{
+ delete pDDEFldType;
+ delete pColWidth;
+ delete pRedlData;
+ delete pAutoFmt;
+}
+
+void SwUndoInsTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
+
+ SwTableNode* pTblNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+ pTblNd->DelFrms();
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
+ rDoc.DeleteRedline( *pTblNd, true, USHRT_MAX );
+ RemoveIdxFromSection( rDoc, nSttNode );
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ SwCntntNode* pNextNd = rDoc.GetNodes()[ pTblNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTblNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+
+
+ sTblNm = pTblNd->GetTable().GetFrmFmt()->GetName();
+ if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()).
+ GetDDEFldType()->Copy();
+
+ rDoc.GetNodes().Delete( aIdx, pTblNd->EndOfSectionIndex() -
+ aIdx.GetIndex() + 1 );
+
+ SwPaM & rPam( rContext.GetCursorSupplier().CreateNewShellCursor() );
+ rPam.DeleteMark();
+ rPam.GetPoint()->nNode = aIdx;
+ rPam.GetPoint()->nContent.Assign( rPam.GetCntntNode(), 0 );
+}
+
+
+void SwUndoInsTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ SwPosition const aPos(SwNodeIndex(rDoc.GetNodes(), nSttNode));
+ const SwTable* pTbl = rDoc.InsertTable( aInsTblOpts, aPos, nRows, nCols,
+ nAdjust,
+ pAutoFmt, pColWidth );
+ ((SwFrmFmt*)pTbl->GetFrmFmt())->SetName( sTblNm );
+ SwTableNode* pTblNode = (SwTableNode*)rDoc.GetNodes()[nSttNode]->GetTableNode();
+
+ if( pDDEFldType )
+ {
+ SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
+ *pDDEFldType);
+ SwDDETable* pDDETbl = new SwDDETable( pTblNode->GetTable(), pNewType );
+ pTblNode->SetNewTable( pDDETbl ); // setze die DDE-Tabelle
+ delete pDDEFldType, pDDEFldType = 0;
+ }
+
+ if( (pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() )) ||
+ ( !( nsRedlineMode_t::REDLINE_IGNORE & GetRedlineMode() ) &&
+ rDoc.GetRedlineTbl().Count() ))
+ {
+ SwPaM aPam( *pTblNode->EndOfSectionNode(), *pTblNode, 1 );
+ SwCntntNode* pCNd = aPam.GetCntntNode( sal_False );
+ if( pCNd )
+ aPam.GetMark()->nContent.Assign( pCNd, 0 );
+
+ if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ RedlineMode_t eOld = rDoc.GetRedlineMode();
+ rDoc.SetRedlineMode_intern((RedlineMode_t)(eOld & ~nsRedlineMode_t::REDLINE_IGNORE));
+
+ rDoc.AppendRedline( new SwRedline( *pRedlData, aPam ), true);
+ rDoc.SetRedlineMode_intern( eOld );
+ }
+ else
+ rDoc.SplitRedline( aPam );
+ }
+}
+
+
+void SwUndoInsTbl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ rContext.GetDoc().InsertTable(
+ aInsTblOpts, *rContext.GetRepeatPaM().GetPoint(),
+ nRows, nCols, nAdjust, pAutoFmt, pColWidth );
+}
+
+SwRewriter SwUndoInsTbl::GetRewriter() const
+{
+ SwRewriter aRewriter;
+
+ aRewriter.AddRule(UNDO_ARG1, SW_RES(STR_START_QUOTE));
+ aRewriter.AddRule(UNDO_ARG2, sTblNm);
+ aRewriter.AddRule(UNDO_ARG3, SW_RES(STR_END_QUOTE));
+
+ return aRewriter;
+}
+
+// -----------------------------------------------------
+
+SwTblToTxtSave::SwTblToTxtSave( SwDoc& rDoc, sal_uLong nNd, sal_uLong nEndIdx, xub_StrLen nCnt )
+ : m_nSttNd( nNd ), m_nEndNd( nEndIdx), m_nCntnt( nCnt ), m_pHstry( 0 )
+{
+ // Attributierung des gejointen Node merken.
+ SwTxtNode* pNd = rDoc.GetNodes()[ nNd ]->GetTxtNode();
+ if( pNd )
+ {
+ m_pHstry = new SwHistory;
+
+ m_pHstry->Add( pNd->GetTxtColl(), nNd, ND_TEXTNODE );
+ if ( pNd->GetpSwpHints() )
+ {
+ m_pHstry->CopyAttr( pNd->GetpSwpHints(), nNd, 0,
+ pNd->GetTxt().Len(), false );
+ }
+ if( pNd->HasSwAttrSet() )
+ m_pHstry->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNd );
+
+ if( !m_pHstry->Count() )
+ delete m_pHstry, m_pHstry = 0;
+
+ // METADATA: store
+ m_pMetadataUndoStart = pNd->CreateUndo();
+ }
+
+ // we also need to store the metadata reference of the _last_ paragraph
+ // we subtract 1 to account for the removed cell start/end node pair
+ // (after SectionUp, the end of the range points to the node after the cell)
+ if ( nEndIdx - 1 > nNd )
+ {
+ SwTxtNode* pLastNode( rDoc.GetNodes()[ nEndIdx - 1 ]->GetTxtNode() );
+ if( pLastNode )
+ {
+ // METADATA: store
+ m_pMetadataUndoEnd = pLastNode->CreateUndo();
+ }
+ }
+}
+
+SwUndoTblToTxt::SwUndoTblToTxt( const SwTable& rTbl, sal_Unicode cCh )
+ : SwUndo( UNDO_TABLETOTEXT ),
+ sTblNm( rTbl.GetFrmFmt()->GetName() ), pDDEFldType( 0 ), pHistory( 0 ),
+ nSttNd( 0 ), nEndNd( 0 ),
+ nAdjust( static_cast<sal_uInt16>(rTbl.GetFrmFmt()->GetHoriOrient().GetHoriOrient()) ),
+ cTrenner( cCh ), nHdlnRpt( rTbl.GetRowsToRepeat() )
+{
+ pTblSave = new _SaveTable( rTbl );
+ pBoxSaves = new SwTblToTxtSaves( (sal_uInt8)rTbl.GetTabSortBoxes().Count() );
+
+ if( rTbl.IsA( TYPE( SwDDETable ) ) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)rTbl).GetDDEFldType()->Copy();
+
+ bCheckNumFmt = rTbl.GetFrmFmt()->GetDoc()->IsInsTblFormatNum();
+
+ pHistory = new SwHistory;
+ const SwTableNode* pTblNd = rTbl.GetTableNode();
+ sal_uLong nTblStt = pTblNd->GetIndex(), nTblEnd = pTblNd->EndOfSectionIndex();
+
+ const SwSpzFrmFmts& rFrmFmtTbl = *pTblNd->GetDoc()->GetSpzFrmFmts();
+ for( sal_uInt16 n = 0; n < rFrmFmtTbl.Count(); ++n )
+ {
+ SwFrmFmt* pFmt = rFrmFmtTbl[ n ];
+ SwFmtAnchor const*const pAnchor = &pFmt->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_CHAR == pAnchor->GetAnchorId()) ||
+ (FLY_AT_PARA == pAnchor->GetAnchorId())) &&
+ nTblStt <= pAPos->nNode.GetIndex() &&
+ pAPos->nNode.GetIndex() < nTblEnd )
+ {
+ pHistory->Add( *pFmt );
+ }
+ }
+
+ if( !pHistory->Count() )
+ delete pHistory, pHistory = 0;
+}
+
+
+SwUndoTblToTxt::~SwUndoTblToTxt()
+{
+ delete pDDEFldType;
+ delete pTblSave;
+ delete pBoxSaves;
+ delete pHistory;
+}
+
+
+
+void SwUndoTblToTxt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ SwNodeIndex aFrmIdx( rDoc.GetNodes(), nSttNd );
+ SwNodeIndex aEndIdx( rDoc.GetNodes(), nEndNd );
+
+ pPam->GetPoint()->nNode = aFrmIdx;
+ pPam->SetMark();
+ pPam->GetPoint()->nNode = aEndIdx;
+ rDoc.DelNumRules( *pPam );
+ pPam->DeleteMark();
+
+ // dann sammel mal alle Uppers ein
+ SwNode2Layout aNode2Layout( aFrmIdx.GetNode() );
+
+ // erzeuge die TabelleNode Structur
+ SwTableNode* pTblNd = rDoc.GetNodes().UndoTableToText( nSttNd, nEndNd, *pBoxSaves );
+ pTblNd->GetTable().SetTableModel( pTblSave->IsNewModel() );
+ SwTableFmt* pTableFmt = rDoc.MakeTblFrmFmt( sTblNm, rDoc.GetDfltFrmFmt() );
+ pTblNd->GetTable().RegisterToFormat( *pTableFmt );
+ pTblNd->GetTable().SetRowsToRepeat( nHdlnRpt );
+
+ // erzeuge die alte Tabellen Struktur
+ pTblSave->CreateNew( pTblNd->GetTable() );
+
+ if( pDDEFldType )
+ {
+ SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
+ *pDDEFldType);
+ SwDDETable* pDDETbl = new SwDDETable( pTblNd->GetTable(), pNewType );
+ pTblNd->SetNewTable( pDDETbl, sal_False ); // setze die DDE-Tabelle
+ delete pDDEFldType, pDDEFldType = 0;
+ }
+
+ if( bCheckNumFmt )
+ {
+ SwTableSortBoxes& rBxs = pTblNd->GetTable().GetTabSortBoxes();
+ for( sal_uInt16 nBoxes = rBxs.Count(); nBoxes; )
+ rDoc.ChkBoxNumFmt( *rBxs[ --nBoxes ], sal_False );
+ }
+
+ if( pHistory )
+ {
+ sal_uInt16 nTmpEnd = pHistory->GetTmpEnd();
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( nTmpEnd );
+ }
+
+ aNode2Layout.RestoreUpperFrms( rDoc.GetNodes(),
+ pTblNd->GetIndex(), pTblNd->GetIndex()+1 );
+
+ // will man eine TabellenSelektion ??
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pPam->SetMark();
+ pPam->GetPoint()->nNode = *pPam->GetNode()->StartOfSectionNode();
+ pPam->Move( fnMoveForward, fnGoCntnt );
+ pPam->Exchange();
+ pPam->Move( fnMoveBackward, fnGoCntnt );
+
+ ClearFEShellTabCols();
+}
+
+ // steht im untbl.cxx und darf nur vom Undoobject gerufen werden
+SwTableNode* SwNodes::UndoTableToText( sal_uLong nSttNd, sal_uLong nEndNd,
+ const SwTblToTxtSaves& rSavedData )
+{
+ SwNodeIndex aSttIdx( *this, nSttNd );
+ SwNodeIndex aEndIdx( *this, nEndNd+1 );
+
+ SwTableNode * pTblNd = new SwTableNode( aSttIdx );
+ SwEndNode* pEndNd = new SwEndNode( aEndIdx, *pTblNd );
+
+ aEndIdx = *pEndNd;
+
+ /* Set pTblNd as start of section for all nodes in [nSttNd, nEndNd].
+ Delete all Frames attached to the nodes in that range. */
+ SwNode* pNd;
+ {
+ sal_uLong n, nTmpEnd = aEndIdx.GetIndex();
+ for( n = pTblNd->GetIndex() + 1; n < nTmpEnd; ++n )
+ {
+ if( ( pNd = (*this)[ n ] )->IsCntntNode() )
+ ((SwCntntNode*)pNd)->DelFrms();
+ pNd->pStartOfSection = pTblNd;
+ }
+ }
+
+ // dann die Tabellen Struktur teilweise aufbauen. Erstmal eine Line
+ // in der alle Boxen stehen! Die korrekte Struktur kommt dann aus der
+ // SaveStruct
+ SwTableBoxFmt* pBoxFmt = GetDoc()->MakeTableBoxFmt();
+ SwTableLineFmt* pLineFmt = GetDoc()->MakeTableLineFmt();
+ SwTableLine* pLine = new SwTableLine( pLineFmt, rSavedData.Count(), 0 );
+ pTblNd->GetTable().GetTabLines().C40_INSERT( SwTableLine, pLine, 0 );
+
+ SvULongs aBkmkArr( 0, 4 );
+ for( sal_uInt16 n = rSavedData.Count(); n; )
+ {
+ SwTblToTxtSave* pSave = rSavedData[ --n ];
+ // if the start node was merged with last from prev. cell,
+ // subtract 1 from index to get the merged paragraph, and split that
+ aSttIdx = pSave->m_nSttNd - ( ( USHRT_MAX != pSave->m_nCntnt ) ? 1 : 0);
+ SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
+
+ if( USHRT_MAX != pSave->m_nCntnt )
+ {
+ // an der ContentPosition splitten, das vorherige Zeichen
+ // loeschen (ist der Trenner!)
+ OSL_ENSURE( pTxtNd, "Wo ist der TextNode geblieben?" );
+ SwIndex aCntPos( pTxtNd, pSave->m_nCntnt - 1 );
+
+ pTxtNd->EraseText( aCntPos, 1 );
+ SwCntntNode* pNewNd = pTxtNd->SplitCntntNode(
+ SwPosition( aSttIdx, aCntPos ));
+ if( aBkmkArr.Count() )
+ _RestoreCntntIdx( aBkmkArr, *pNewNd, pSave->m_nCntnt,
+ pSave->m_nCntnt + 1 );
+ }
+ else
+ {
+ if( aBkmkArr.Count() )
+ aBkmkArr.Remove( 0, aBkmkArr.Count() );
+ if( pTxtNd )
+ _SaveCntntIdx( GetDoc(), aSttIdx.GetIndex(),
+ pTxtNd->GetTxt().Len(), aBkmkArr );
+ }
+
+ if( pTxtNd )
+ {
+ // METADATA: restore
+ pTxtNd->GetTxtNode()->RestoreMetadata(pSave->m_pMetadataUndoStart);
+ if( pTxtNd->HasSwAttrSet() )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd->GetpSwpHints() )
+ pTxtNd->ClearSwpHintsArr( false );
+ }
+
+ if( pSave->m_pHstry )
+ {
+ sal_uInt16 nTmpEnd = pSave->m_pHstry->GetTmpEnd();
+ pSave->m_pHstry->TmpRollback( GetDoc(), 0 );
+ pSave->m_pHstry->SetTmpEnd( nTmpEnd );
+ }
+
+ // METADATA: restore
+ // end points to node after cell
+ if ( pSave->m_nEndNd - 1 > pSave->m_nSttNd )
+ {
+ SwTxtNode* pLastNode = (*this)[ pSave->m_nEndNd - 1 ]->GetTxtNode();
+ if (pLastNode)
+ {
+ pLastNode->RestoreMetadata(pSave->m_pMetadataUndoEnd);
+ }
+ }
+
+ aEndIdx = pSave->m_nEndNd;
+ SwStartNode* pSttNd = new SwStartNode( aSttIdx, ND_STARTNODE,
+ SwTableBoxStartNode );
+ pSttNd->pStartOfSection = pTblNd;
+ new SwEndNode( aEndIdx, *pSttNd );
+
+ for( sal_uLong i = aSttIdx.GetIndex(); i < aEndIdx.GetIndex()-1; ++i )
+ {
+ pNd = (*this)[ i ];
+ pNd->pStartOfSection = pSttNd;
+ if( pNd->IsStartNode() )
+ i = pNd->EndOfSectionIndex();
+ }
+
+ SwTableBox* pBox = new SwTableBox( pBoxFmt, *pSttNd, pLine );
+ pLine->GetTabBoxes().C40_INSERT( SwTableBox, pBox, 0 );
+ }
+ return pTblNd;
+}
+
+
+void SwUndoTblToTxt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->GetPoint()->nNode = nSttNd;
+ pPam->GetPoint()->nContent.Assign( 0, 0 );
+ SwNodeIndex aSaveIdx( pPam->GetPoint()->nNode, -1 );
+
+ pPam->SetMark(); // alle Indizies abmelden
+ pPam->DeleteMark();
+
+ SwTableNode* pTblNd = pPam->GetNode()->GetTableNode();
+ OSL_ENSURE( pTblNd, "keinen TableNode gefunden" );
+
+ if( pTblNd->GetTable().IsA( TYPE( SwDDETable )) )
+ pDDEFldType = (SwDDEFieldType*)((SwDDETable&)pTblNd->GetTable()).
+ GetDDEFldType()->Copy();
+
+ rDoc.TableToText( pTblNd, cTrenner );
+
+ aSaveIdx++;
+ SwCntntNode* pCNd = aSaveIdx.GetNode().GetCntntNode();
+ if( !pCNd && 0 == ( pCNd = rDoc.GetNodes().GoNext( &aSaveIdx ) ) &&
+ 0 == ( pCNd = rDoc.GetNodes().GoPrevious( &aSaveIdx )) )
+ {
+ OSL_FAIL( "wo steht denn nun der TextNode" );
+ }
+
+ pPam->GetPoint()->nNode = aSaveIdx;
+ pPam->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ pPam->SetMark(); // alle Indizies abmelden
+ pPam->DeleteMark();
+}
+
+
+void SwUndoTblToTxt::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwPaM *const pPam = & rContext.GetRepeatPaM();
+ SwTableNode *const pTblNd = pPam->GetNode()->FindTableNode();
+ if( pTblNd )
+ {
+ // move cursor out of table
+ pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
+ pPam->Move( fnMoveForward, fnGoCntnt );
+ pPam->SetMark();
+ pPam->DeleteMark();
+
+ rContext.GetDoc().TableToText( pTblNd, cTrenner );
+ }
+}
+
+void SwUndoTblToTxt::SetRange( const SwNodeRange& rRg )
+{
+ nSttNd = rRg.aStart.GetIndex();
+ nEndNd = rRg.aEnd.GetIndex();
+}
+
+void SwUndoTblToTxt::AddBoxPos( SwDoc& rDoc, sal_uLong nNdIdx, sal_uLong nEndIdx, xub_StrLen nCntntIdx )
+{
+ SwTblToTxtSave* pNew = new SwTblToTxtSave( rDoc, nNdIdx, nEndIdx, nCntntIdx );
+ pBoxSaves->Insert( pNew, pBoxSaves->Count() );
+}
+
+// -----------------------------------------------------
+
+SwUndoTxtToTbl::SwUndoTxtToTbl( const SwPaM& rRg,
+ const SwInsertTableOptions& rInsTblOpts,
+ sal_Unicode cCh, sal_uInt16 nAdj,
+ const SwTableAutoFmt* pAFmt )
+ : SwUndo( UNDO_TEXTTOTABLE ), SwUndRng( rRg ), aInsTblOpts( rInsTblOpts ),
+ pDelBoxes( 0 ), pAutoFmt( 0 ),
+ pHistory( 0 ), cTrenner( cCh ), nAdjust( nAdj )
+{
+ if( pAFmt )
+ pAutoFmt = new SwTableAutoFmt( *pAFmt );
+
+ const SwPosition* pEnd = rRg.End();
+ SwNodes& rNds = rRg.GetDoc()->GetNodes();
+ bSplitEnd = pEnd->nContent.GetIndex() && ( pEnd->nContent.GetIndex()
+ != pEnd->nNode.GetNode().GetCntntNode()->Len() ||
+ pEnd->nNode.GetIndex() >= rNds.GetEndOfContent().GetIndex()-1 );
+}
+
+SwUndoTxtToTbl::~SwUndoTxtToTbl()
+{
+ delete pDelBoxes;
+ delete pAutoFmt;
+}
+
+void SwUndoTxtToTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ sal_uLong nTblNd = nSttNode;
+ if( nSttCntnt )
+ ++nTblNd; // Node wurde vorher gesplittet
+ SwNodeIndex aIdx( rDoc.GetNodes(), nTblNd );
+ SwTableNode *const pTNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ RemoveIdxFromSection( rDoc, nTblNd );
+
+ sTblNm = pTNd->GetTable().GetFrmFmt()->GetName();
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ if( pDelBoxes )
+ {
+ SwTable& rTbl = pTNd->GetTable();
+ for( sal_uInt16 n = pDelBoxes->Count(); n; )
+ {
+ SwTableBox* pBox = rTbl.GetTblBox( (*pDelBoxes)[ --n ] );
+ if( pBox )
+ ::_DeleteBox( rTbl, pBox, 0, sal_False, sal_False );
+ else {
+ OSL_ENSURE( !this, "Wo ist die Box geblieben?" );
+ }
+ }
+ }
+
+ SwNodeIndex aEndIdx( *pTNd->EndOfSectionNode() );
+ rDoc.TableToText( pTNd, 0x0b == cTrenner ? 0x09 : cTrenner );
+
+ // join again at start?
+ SwPaM aPam(rDoc.GetNodes().GetEndOfContent());
+ SwPosition *const pPos = aPam.GetPoint();
+ if( nSttCntnt )
+ {
+ pPos->nNode = nTblNd;
+ pPos->nContent.Assign(pPos->nNode.GetNode().GetCntntNode(), 0);
+ if (aPam.Move(fnMoveBackward, fnGoCntnt))
+ {
+ SwNodeIndex & rIdx = aPam.GetPoint()->nNode;
+
+ // dann die Crsr/etc. nochmal relativ verschieben
+ RemoveIdxRel( rIdx.GetIndex()+1, *pPos );
+
+ rIdx.GetNode().GetCntntNode()->JoinNext();
+ }
+ }
+
+ // join again at end?
+ if( bSplitEnd )
+ {
+ SwNodeIndex& rIdx = pPos->nNode;
+ rIdx = nEndNode;
+ SwTxtNode* pTxtNd = rIdx.GetNode().GetTxtNode();
+ if( pTxtNd && pTxtNd->CanJoinNext() )
+ {
+ aPam.GetMark()->nContent.Assign( 0, 0 );
+ aPam.GetPoint()->nContent.Assign( 0, 0 );
+
+ // dann die Crsr/etc. nochmal relativ verschieben
+ pPos->nContent.Assign( pTxtNd, pTxtNd->GetTxt().Len() );
+ RemoveIdxRel( nEndNode + 1, *pPos );
+
+ pTxtNd->JoinNext();
+ }
+ }
+
+ AddUndoRedoPaM(rContext);
+}
+
+
+void SwUndoTxtToTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ RemoveIdxFromRange(rPam, false);
+ SetPaM(rPam);
+
+ SwTable const*const pTable = rContext.GetDoc().TextToTable(
+ aInsTblOpts, rPam, cTrenner, nAdjust, pAutoFmt );
+ ((SwFrmFmt*)pTable->GetFrmFmt())->SetName( sTblNm );
+}
+
+
+void SwUndoTxtToTbl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ // no Table In Table
+ if (!rContext.GetRepeatPaM().GetNode()->FindTableNode())
+ {
+ rContext.GetDoc().TextToTable( aInsTblOpts, rContext.GetRepeatPaM(),
+ cTrenner, nAdjust,
+ pAutoFmt );
+ }
+}
+
+void SwUndoTxtToTbl::AddFillBox( const SwTableBox& rBox )
+{
+ if( !pDelBoxes )
+ pDelBoxes = new SvULongs;
+ pDelBoxes->Insert( rBox.GetSttIdx(), pDelBoxes->Count() );
+}
+
+SwHistory& SwUndoTxtToTbl::GetHistory()
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+ return *pHistory;
+}
+
+// -----------------------------------------------------
+
+SwUndoTblHeadline::SwUndoTblHeadline( const SwTable& rTbl, sal_uInt16 nOldHdl,
+ sal_uInt16 nNewHdl )
+ : SwUndo( UNDO_TABLEHEADLINE ),
+ nOldHeadline( nOldHdl ),
+ nNewHeadline( nNewHdl )
+{
+ OSL_ENSURE( rTbl.GetTabSortBoxes().Count(), "Tabelle ohne Inhalt" );
+ const SwStartNode *pSttNd = rTbl.GetTabSortBoxes()[ 0 ]->GetSttNd();
+ OSL_ENSURE( pSttNd, "Box ohne Inhalt" );
+
+ nTblNd = pSttNd->StartOfSectionIndex();
+}
+
+void SwUndoTblHeadline::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ rDoc.SetRowsToRepeat( pTNd->GetTable(), nOldHeadline );
+}
+
+void SwUndoTblHeadline::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
+ OSL_ENSURE( pTNd, "keinen Tabellen-Node gefunden" );
+
+ rDoc.SetRowsToRepeat( pTNd->GetTable(), nNewHeadline );
+}
+
+void SwUndoTblHeadline::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwTableNode *const pTblNd =
+ rContext.GetRepeatPaM().GetNode()->FindTableNode();
+ if( pTblNd )
+ {
+ rContext.GetDoc().SetRowsToRepeat( pTblNd->GetTable(), nNewHeadline );
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+
+_SaveTable::_SaveTable( const SwTable& rTbl, sal_uInt16 nLnCnt, sal_Bool bSaveFml )
+ : aTblSet( *rTbl.GetFrmFmt()->GetAttrSet().GetPool(), aTableSetRange ),
+ pSwTable( &rTbl ), nLineCount( nLnCnt ), bSaveFormula( bSaveFml )
+{
+ bModifyBox = sal_False;
+ bNewModel = rTbl.IsNewModel();
+ aTblSet.Put( rTbl.GetFrmFmt()->GetAttrSet() );
+ pLine = new _SaveLine( 0, *rTbl.GetTabLines()[ 0 ], *this );
+
+ _SaveLine* pLn = pLine;
+ if( USHRT_MAX == nLnCnt )
+ nLnCnt = rTbl.GetTabLines().Count();
+ for( sal_uInt16 n = 1; n < nLnCnt; ++n )
+ pLn = new _SaveLine( pLn, *rTbl.GetTabLines()[ n ], *this );
+
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+ pSwTable = 0;
+}
+
+
+_SaveTable::~_SaveTable()
+{
+ delete pLine;
+}
+
+
+sal_uInt16 _SaveTable::AddFmt( SwFrmFmt* pFmt, bool bIsLine )
+{
+ sal_uInt16 nRet = aFrmFmts.GetPos( pFmt );
+ if( USHRT_MAX == nRet )
+ {
+ // Kopie vom ItemSet anlegen
+ SfxItemSet* pSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
+ bIsLine ? aTableLineSetRange : aTableBoxSetRange );
+ pSet->Put( pFmt->GetAttrSet() );
+ //JP 20.04.98: Bug 49502 - wenn eine Formel gesetzt ist, nie den
+ // Value mit sichern. Der muss gegebenfalls neu
+ // errechnet werden!
+ //JP 30.07.98: Bug 54295 - Formeln immer im Klartext speichern
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pSet->GetItemState( RES_BOXATR_FORMULA, sal_True, &pItem ))
+ {
+ pSet->ClearItem( RES_BOXATR_VALUE );
+ if( pSwTable && bSaveFormula )
+ {
+ SwTableFmlUpdate aMsgHnt( pSwTable );
+ aMsgHnt.eFlags = TBL_BOXNAME;
+ ((SwTblBoxFormula*)pItem)->ChgDefinedIn( pFmt );
+ ((SwTblBoxFormula*)pItem)->ChangeState( &aMsgHnt );
+ ((SwTblBoxFormula*)pItem)->ChgDefinedIn( 0 );
+ }
+ }
+ aSets.Insert( pSet, (nRet = aSets.Count() ) );
+ aFrmFmts.Insert( pFmt, nRet );
+ }
+ return nRet;
+}
+
+
+void _SaveTable::RestoreAttr( SwTable& rTbl, sal_Bool bMdfyBox )
+{
+ sal_uInt16 n;
+
+ bModifyBox = bMdfyBox;
+
+ // zuerst die Attribute des TabellenFrmFormates zurueck holen
+ SwFrmFmt* pFmt = rTbl.GetFrmFmt();
+ SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet();
+ rFmtSet.ClearItem();
+ rFmtSet.Put( aTblSet );
+
+ if( pFmt->IsInCache() )
+ {
+ SwFrm::GetCache().Delete( pFmt );
+ pFmt->SetInCache( sal_False );
+ }
+
+ // zur Sicherheit alle Tableframes invalidieren
+ SwIterator<SwTabFrm,SwFmt> aIter( *pFmt );
+ for( SwTabFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ if( pLast->GetTable() == &rTbl )
+ {
+ pLast->InvalidateAll();
+ pLast->SetCompletePaint();
+ }
+
+ // FrmFmts mit Defaults (0) fuellen
+ pFmt = 0;
+ for( n = aSets.Count(); n; --n )
+ aFrmFmts.Insert( pFmt, aFrmFmts.Count() );
+
+ sal_uInt16 nLnCnt = nLineCount;
+ if( USHRT_MAX == nLnCnt )
+ nLnCnt = rTbl.GetTabLines().Count();
+
+ _SaveLine* pLn = pLine;
+ for( n = 0; n < nLnCnt; ++n, pLn = pLn->pNext )
+ {
+ if( !pLn )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ break;
+ }
+
+ pLn->RestoreAttr( *rTbl.GetTabLines()[ n ], *this );
+ }
+
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+ bModifyBox = sal_False;
+}
+
+
+void _SaveTable::SaveCntntAttrs( SwDoc* pDoc )
+{
+ pLine->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveTable::CreateNew( SwTable& rTbl, sal_Bool bCreateFrms,
+ sal_Bool bRestoreChart )
+{
+ sal_uInt16 n;
+
+ _FndBox aTmpBox( 0, 0 );
+ //if( bRestoreChart )
+ // // ? TL_CHART2: notification or locking of controller required ?
+ aTmpBox.DelFrms( rTbl );
+
+ // zuerst die Attribute des TabellenFrmFormates zurueck holen
+ SwFrmFmt* pFmt = rTbl.GetFrmFmt();
+ SfxItemSet& rFmtSet = (SfxItemSet&)pFmt->GetAttrSet();
+ rFmtSet.ClearItem();
+ rFmtSet.Put( aTblSet );
+
+ if( pFmt->IsInCache() )
+ {
+ SwFrm::GetCache().Delete( pFmt );
+ pFmt->SetInCache( sal_False );
+ }
+
+ // SwTableBox muss ein Format haben!!
+ SwTableBox aParent( (SwTableBoxFmt*)pFmt, rTbl.GetTabLines().Count(), 0 );
+
+ // FrmFmts mit Defaults (0) fuellen
+ pFmt = 0;
+ for( n = aSets.Count(); n; --n )
+ aFrmFmts.Insert( pFmt, aFrmFmts.Count() );
+
+ pLine->CreateNew( rTbl, aParent, *this );
+ aFrmFmts.Remove( 0, aFrmFmts.Count() );
+
+ // die neuen Lines eintragen, die alten loeschen
+ sal_uInt16 nOldLines = nLineCount;
+ if( USHRT_MAX == nLineCount )
+ nOldLines = rTbl.GetTabLines().Count();
+
+ SwDoc *pDoc = rTbl.GetFrmFmt()->GetDoc();
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ for( n = 0; n < aParent.GetTabLines().Count(); ++n )
+ {
+ SwTableLine* pLn = aParent.GetTabLines()[ n ];
+ pLn->SetUpper( 0 );
+ if( n < nOldLines )
+ {
+ SwTableLine* pOld = rTbl.GetTabLines()[ n ];
+
+ // TL_CHART2: notify chart about boxes to be removed
+ const SwTableBoxes &rBoxes = pOld->GetTabBoxes();
+ sal_uInt16 nBoxes = rBoxes.Count();
+ for (sal_uInt16 k = 0; k < nBoxes; ++k)
+ {
+ SwTableBox *pBox = rBoxes[k];
+ if (pPCD)
+ pPCD->DeleteBox( &rTbl, *pBox );
+ }
+
+ rTbl.GetTabLines().C40_REPLACE( SwTableLine, pLn, n );
+ delete pOld;
+ }
+ else
+ rTbl.GetTabLines().C40_INSERT( SwTableLine, pLn, n );
+ }
+
+ if( n < nOldLines )
+ {
+ // remove remaining lines...
+
+ for (sal_uInt16 k1 = 0; k1 < nOldLines - n; ++k1)
+ {
+ const SwTableBoxes &rBoxes = rTbl.GetTabLines()[n + k1]->GetTabBoxes();
+ sal_uInt16 nBoxes = rBoxes.Count();
+ for (sal_uInt16 k2 = 0; k2 < nBoxes; ++k2)
+ {
+ SwTableBox *pBox = rBoxes[k2];
+ // TL_CHART2: notify chart about boxes to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &rTbl, *pBox );
+ }
+ }
+
+ rTbl.GetTabLines().DeleteAndDestroy( n, nOldLines - n );
+ }
+
+ aParent.GetTabLines().Remove( 0, n );
+
+ if( bCreateFrms )
+ aTmpBox.MakeFrms( rTbl );
+ if( bRestoreChart )
+ {
+ // TL_CHART2: need to inform chart of probably changed cell names
+ pDoc->UpdateCharts( rTbl.GetFrmFmt()->GetName() );
+ }
+}
+
+
+void _SaveTable::NewFrmFmt( const SwTableLine* pTblLn, const SwTableBox* pTblBx,
+ sal_uInt16 nFmtPos, SwFrmFmt* pOldFmt )
+{
+ SwDoc* pDoc = pOldFmt->GetDoc();
+
+ SwFrmFmt* pFmt = aFrmFmts[ nFmtPos ];
+ if( !pFmt )
+ {
+ if( pTblLn )
+ pFmt = pDoc->MakeTableLineFmt();
+ else
+ pFmt = pDoc->MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *aSets[ nFmtPos ] );
+ aFrmFmts.Replace( pFmt, nFmtPos );
+ }
+
+ //Erstmal die Frms ummelden.
+ SwIterator<SwTabFrm,SwFmt> aIter( *pOldFmt );
+ for( SwFrm* pLast = aIter.First(); pLast; pLast = aIter.Next() )
+ {
+ if( pTblLn ? ((SwRowFrm*)pLast)->GetTabLine() == pTblLn
+ : ((SwCellFrm*)pLast)->GetTabBox() == pTblBx )
+ {
+ pLast->RegisterToFormat(*pFmt);
+ pLast->InvalidateAll();
+ pLast->ReinitializeFrmSizeAttrFlags();
+ if ( !pTblLn )
+ {
+ ((SwCellFrm*)pLast)->SetDerivedVert( sal_False );
+ ((SwCellFrm*)pLast)->CheckDirChange();
+ }
+ }
+ }
+
+ //Jetzt noch mich selbst ummelden.
+ if ( pTblLn )
+ const_cast<SwTableLine*>(pTblLn)->RegisterToFormat( *pFmt );
+ else if ( pTblBx )
+ const_cast<SwTableBox*>(pTblBx)->RegisterToFormat( *pFmt );
+
+ if( bModifyBox && !pTblLn )
+ {
+ const SfxPoolItem& rOld = pOldFmt->GetFmtAttr( RES_BOXATR_FORMAT ),
+ & rNew = pFmt->GetFmtAttr( RES_BOXATR_FORMAT );
+ if( rOld != rNew )
+ pFmt->ModifyNotification( (SfxPoolItem*)&rOld, (SfxPoolItem*)&rNew );
+ }
+
+ if( !pOldFmt->GetDepends() )
+ delete pOldFmt;
+
+}
+
+
+_SaveLine::_SaveLine( _SaveLine* pPrev, const SwTableLine& rLine, _SaveTable& rSTbl )
+ : pNext( 0 )
+{
+ if( pPrev )
+ pPrev->pNext = this;
+
+ nItemSet = rSTbl.AddFmt( rLine.GetFrmFmt(), true );
+
+ pBox = new _SaveBox( 0, *rLine.GetTabBoxes()[ 0 ], rSTbl );
+ _SaveBox* pBx = pBox;
+ for( sal_uInt16 n = 1; n < rLine.GetTabBoxes().Count(); ++n )
+ pBx = new _SaveBox( pBx, *rLine.GetTabBoxes()[ n ], rSTbl );
+}
+
+
+_SaveLine::~_SaveLine()
+{
+ delete pBox;
+ delete pNext;
+}
+
+
+void _SaveLine::RestoreAttr( SwTableLine& rLine, _SaveTable& rSTbl )
+{
+ rSTbl.NewFrmFmt( &rLine, 0, nItemSet, rLine.GetFrmFmt() );
+
+ _SaveBox* pBx = pBox;
+ for( sal_uInt16 n = 0; n < rLine.GetTabBoxes().Count(); ++n, pBx = pBx->pNext )
+ {
+ if( !pBx )
+ {
+ OSL_ENSURE( !this, "Anzahl der Boxen hat sich veraendert" );
+ break;
+ }
+ pBx->RestoreAttr( *rLine.GetTabBoxes()[ n ], rSTbl );
+ }
+}
+
+
+void _SaveLine::SaveCntntAttrs( SwDoc* pDoc )
+{
+ pBox->SaveCntntAttrs( pDoc );
+ if( pNext )
+ pNext->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveLine::CreateNew( SwTable& rTbl, SwTableBox& rParent, _SaveTable& rSTbl )
+{
+ SwTableLineFmt* pFmt = (SwTableLineFmt*)rSTbl.aFrmFmts[ nItemSet ];
+ if( !pFmt )
+ {
+ SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc();
+ pFmt = pDoc->MakeTableLineFmt();
+ pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] );
+ rSTbl.aFrmFmts.Replace( pFmt, nItemSet );
+ }
+ SwTableLine* pNew = new SwTableLine( pFmt, 1, &rParent );
+
+ rParent.GetTabLines().C40_INSERT( SwTableLine, pNew, rParent.GetTabLines().Count() );
+
+ // HB, #127868# robustness: in some cases - which I
+ // cannot reproduce nor see from the code - pNew seems
+ // to be set to NULL in C40_INSERT.
+ OSL_ENSURE(pNew, "Table line just created set to NULL in C40_INSERT");
+
+ if (pNew)
+ {
+ pBox->CreateNew( rTbl, *pNew, rSTbl );
+ }
+
+ if( pNext )
+ pNext->CreateNew( rTbl, rParent, rSTbl );
+}
+
+
+_SaveBox::_SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl )
+ : pNext( 0 ), nSttNode( ULONG_MAX ), nRowSpan(0)
+{
+ Ptrs.pLine = 0;
+
+ if( pPrev )
+ pPrev->pNext = this;
+
+ nItemSet = rSTbl.AddFmt( rBox.GetFrmFmt(), false );
+
+ if( rBox.GetSttNd() )
+ {
+ nSttNode = rBox.GetSttIdx();
+ nRowSpan = rBox.getRowSpan();
+ }
+ else
+ {
+ Ptrs.pLine = new _SaveLine( 0, *rBox.GetTabLines()[ 0 ], rSTbl );
+
+ _SaveLine* pLn = Ptrs.pLine;
+ for( sal_uInt16 n = 1; n < rBox.GetTabLines().Count(); ++n )
+ pLn = new _SaveLine( pLn, *rBox.GetTabLines()[ n ], rSTbl );
+ }
+}
+
+
+_SaveBox::~_SaveBox()
+{
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ delete Ptrs.pLine;
+ else
+ delete Ptrs.pCntntAttrs;
+ delete pNext;
+}
+
+
+void _SaveBox::RestoreAttr( SwTableBox& rBox, _SaveTable& rSTbl )
+{
+ rSTbl.NewFrmFmt( 0, &rBox, nItemSet, rBox.GetFrmFmt() );
+
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ if( !rBox.GetTabLines().Count() )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ }
+ else
+ {
+ _SaveLine* pLn = Ptrs.pLine;
+ for( sal_uInt16 n = 0; n < rBox.GetTabLines().Count(); ++n, pLn = pLn->pNext )
+ {
+ if( !pLn )
+ {
+ OSL_ENSURE( !this, "Anzahl der Lines hat sich veraendert" );
+ break;
+ }
+
+ pLn->RestoreAttr( *rBox.GetTabLines()[ n ], rSTbl );
+ }
+ }
+ }
+ else if( rBox.GetSttNd() && rBox.GetSttIdx() == nSttNode )
+ {
+ if( Ptrs.pCntntAttrs )
+ {
+ SwNodes& rNds = rBox.GetFrmFmt()->GetDoc()->GetNodes();
+ sal_uInt16 nSet = 0;
+ sal_uLong nEnd = rBox.GetSttNd()->EndOfSectionIndex();
+ for( sal_uLong n = nSttNode + 1; n < nEnd; ++n )
+ {
+ SwCntntNode* pCNd = rNds[ n ]->GetCntntNode();
+ if( pCNd )
+ {
+ SfxItemSet* pSet = (*Ptrs.pCntntAttrs)[ nSet++ ];
+ if( pSet )
+ {
+ sal_uInt16 *pRstAttr = aSave_BoxCntntSet;
+ while( *pRstAttr )
+ {
+ pCNd->ResetAttr( *pRstAttr, *(pRstAttr+1) );
+ pRstAttr += 2;
+ }
+ pCNd->SetAttr( *pSet );
+ }
+ else
+ pCNd->ResetAllAttr();
+ }
+ }
+ }
+ }
+ else
+ {
+ OSL_ENSURE( !this, "Box nicht mehr am gleichen Node" );
+ }
+}
+
+
+void _SaveBox::SaveCntntAttrs( SwDoc* pDoc )
+{
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ // weiter in der Line
+ Ptrs.pLine->SaveCntntAttrs( pDoc );
+ }
+ else
+ {
+ sal_uLong nEnd = pDoc->GetNodes()[ nSttNode ]->EndOfSectionIndex();
+ Ptrs.pCntntAttrs = new SfxItemSets( (sal_uInt8)(nEnd - nSttNode - 1 ), 5 );
+ for( sal_uLong n = nSttNode + 1; n < nEnd; ++n )
+ {
+ SwCntntNode* pCNd = pDoc->GetNodes()[ n ]->GetCntntNode();
+ if( pCNd )
+ {
+ SfxItemSet* pSet = 0;
+ if( pCNd->HasSwAttrSet() )
+ {
+ pSet = new SfxItemSet( pDoc->GetAttrPool(),
+ aSave_BoxCntntSet );
+ pSet->Put( *pCNd->GetpSwAttrSet() );
+ }
+
+ Ptrs.pCntntAttrs->Insert( pSet, Ptrs.pCntntAttrs->Count() );
+ }
+ }
+ }
+ if( pNext )
+ pNext->SaveCntntAttrs( pDoc );
+}
+
+
+void _SaveBox::CreateNew( SwTable& rTbl, SwTableLine& rParent, _SaveTable& rSTbl )
+{
+ SwTableBoxFmt* pFmt = (SwTableBoxFmt*)rSTbl.aFrmFmts[ nItemSet ];
+ if( !pFmt )
+ {
+ SwDoc* pDoc = rTbl.GetFrmFmt()->GetDoc();
+ pFmt = pDoc->MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *rSTbl.aSets[ nItemSet ] );
+ rSTbl.aFrmFmts.Replace( pFmt, nItemSet );
+ }
+
+ if( ULONG_MAX == nSttNode ) // keine EndBox
+ {
+ SwTableBox* pNew = new SwTableBox( pFmt, 1, &rParent );
+ rParent.GetTabBoxes().C40_INSERT( SwTableBox, pNew, rParent.GetTabBoxes().Count() );
+
+ Ptrs.pLine->CreateNew( rTbl, *pNew, rSTbl );
+ }
+ else
+ {
+ // Box zum StartNode in der alten Tabelle suchen
+ SwTableBox* pBox = rTbl.GetTblBox( nSttNode );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ SwFrmFmt* pOld = pBox->GetFrmFmt();
+ pBox->RegisterToFormat( *pFmt );
+ if( !pOld->GetDepends() )
+ delete pOld;
+
+ pBox->setRowSpan( nRowSpan );
+
+ SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) );
+
+ pBox->SetUpper( &rParent );
+ pTBoxes = &rParent.GetTabBoxes();
+ pTBoxes->C40_INSERT( SwTableBox, pBox, pTBoxes->Count() );
+ }
+
+ if( pNext )
+ pNext->CreateNew( rTbl, rParent, rSTbl );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+// UndoObject fuer Attribut Aenderung an der Tabelle
+
+
+SwUndoAttrTbl::SwUndoAttrTbl( const SwTableNode& rTblNd, sal_Bool bClearTabCols )
+ : SwUndo( UNDO_TABLE_ATTR ),
+ nSttNode( rTblNd.GetIndex() )
+{
+ bClearTabCol = bClearTabCols;
+ pSaveTbl = new _SaveTable( rTblNd.GetTable() );
+}
+
+SwUndoAttrTbl::~SwUndoAttrTbl()
+{
+ delete pSaveTbl;
+}
+
+void SwUndoAttrTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ if (pTblNd)
+ {
+ _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() );
+ pSaveTbl->RestoreAttr( pTblNd->GetTable() );
+ delete pSaveTbl;
+ pSaveTbl = pOrig;
+ }
+
+ if( bClearTabCol )
+ ClearFEShellTabCols();
+}
+
+void SwUndoAttrTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ UndoImpl(rContext);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+// UndoObject fuer AutoFormat an der Tabelle
+
+
+SwUndoTblAutoFmt::SwUndoTblAutoFmt( const SwTableNode& rTblNd,
+ const SwTableAutoFmt& rAFmt )
+ : SwUndo( UNDO_TABLE_AUTOFMT ),
+ nSttNode( rTblNd.GetIndex() ),
+ bSaveCntntAttr( sal_False )
+{
+ pSaveTbl = new _SaveTable( rTblNd.GetTable() );
+
+ if( rAFmt.IsFont() || rAFmt.IsJustify() )
+ {
+ // dann auch noch ueber die ContentNodes der EndBoxen und
+ // und alle Absatz-Attribute zusammen sammeln
+ pSaveTbl->SaveCntntAttrs( (SwDoc*)rTblNd.GetDoc() );
+ bSaveCntntAttr = sal_True;
+ }
+}
+
+SwUndoTblAutoFmt::~SwUndoTblAutoFmt()
+{
+ delete pSaveTbl;
+}
+
+void SwUndoTblAutoFmt::SaveBoxCntnt( const SwTableBox& rBox )
+{
+ ::boost::shared_ptr<SwUndoTblNumFmt> const p(new SwUndoTblNumFmt(rBox));
+ m_Undos.push_back(p);
+}
+
+
+void
+SwUndoTblAutoFmt::UndoRedo(bool const bUndo, ::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() );
+ // dann auch noch ueber die ContentNodes der EndBoxen und
+ // und alle Absatz-Attribute zusammen sammeln
+ if( bSaveCntntAttr )
+ pOrig->SaveCntntAttrs( &rDoc );
+
+ if (bUndo)
+ {
+ for (size_t n = m_Undos.size(); 0 < n; --n)
+ {
+ m_Undos.at(n-1)->UndoImpl(rContext);
+ }
+ }
+
+ pSaveTbl->RestoreAttr( pTblNd->GetTable(), !bUndo );
+ delete pSaveTbl;
+ pSaveTbl = pOrig;
+}
+
+void SwUndoTblAutoFmt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ UndoRedo(true, rContext);
+}
+
+void SwUndoTblAutoFmt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ UndoRedo(false, rContext);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction,
+ const SwSelBoxes& rBoxes,
+ const SwTableNode& rTblNd,
+ long nMn, long nMx,
+ sal_uInt16 nCnt, sal_Bool bFlg, sal_Bool bSmHght )
+ : SwUndo( nAction ),
+ aBoxes( rBoxes.Count() < 255 ? (sal_uInt8)rBoxes.Count() : 255, 10 ),
+ nMin( nMn ), nMax( nMx ),
+ nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ),
+ nCount( nCnt ), nRelDiff( 0 ), nAbsDiff( 0 ),
+ nSetColType( USHRT_MAX ),
+ bFlag( bFlg ),
+ bSameHeight( bSmHght )
+{
+ Ptrs.pNewSttNds = 0;
+
+ const SwTable& rTbl = rTblNd.GetTable();
+ pSaveTbl = new _SaveTable( rTbl );
+
+ // und die Selektion merken
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+}
+
+
+SwUndoTblNdsChg::SwUndoTblNdsChg( SwUndoId nAction,
+ const SwSelBoxes& rBoxes,
+ const SwTableNode& rTblNd )
+ : SwUndo( nAction ),
+ aBoxes( rBoxes.Count() < 255 ? (sal_uInt8)rBoxes.Count() : 255, 10 ),
+ nMin( 0 ), nMax( 0 ),
+ nSttNode( rTblNd.GetIndex() ), nCurrBox( 0 ),
+ nCount( 0 ), nRelDiff( 0 ), nAbsDiff( 0 ),
+ nSetColType( USHRT_MAX ),
+ bFlag( sal_False ),
+ bSameHeight( sal_False )
+{
+ Ptrs.pNewSttNds = 0;
+
+ const SwTable& rTbl = rTblNd.GetTable();
+ pSaveTbl = new _SaveTable( rTbl );
+
+ // und die Selektion merken
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+}
+
+void SwUndoTblNdsChg::ReNewBoxes( const SwSelBoxes& rBoxes )
+{
+ if( rBoxes.Count() != aBoxes.Count() )
+ {
+ aBoxes.Remove( 0, aBoxes.Count() );
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
+ }
+}
+
+SwUndoTblNdsChg::~SwUndoTblNdsChg()
+{
+ delete pSaveTbl;
+
+ if( IsDelBox() )
+ delete Ptrs.pDelSects;
+ else
+ delete Ptrs.pNewSttNds;
+}
+
+void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd,
+ const SwTableSortBoxes& rOld )
+{
+ const SwTable& rTbl = rTblNd.GetTable();
+ const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes();
+ sal_uInt16 n;
+ sal_uInt16 i;
+
+ OSL_ENSURE( ! IsDelBox(), "falsche Action" );
+ Ptrs.pNewSttNds = new SvULongs( (sal_uInt8)(rTblBoxes.Count() - rOld.Count()), 5 );
+
+ for( n = 0, i = 0; n < rOld.Count(); ++i )
+ {
+ if( rOld[ n ] == rTblBoxes[ i ] )
+ ++n;
+ else
+ // neue Box: sortiert einfuegen!!
+ InsertSort( *Ptrs.pNewSttNds, rTblBoxes[ i ]->GetSttIdx() );
+ }
+
+ for( ; i < rTblBoxes.Count(); ++i )
+ // neue Box: sortiert einfuegen!!
+ InsertSort( *Ptrs.pNewSttNds, rTblBoxes[ i ]->GetSttIdx() );
+}
+
+
+SwTableLine* lcl_FindTableLine( const SwTable& rTable,
+ const SwTableBox& rBox )
+{
+ SwTableLine* pRet = NULL;
+ // i63949: For nested cells we have to take nLineNo - 1, too, not 0!
+ const SwTableLines &rTableLines = ( rBox.GetUpper()->GetUpper() != NULL ) ?
+ rBox.GetUpper()->GetUpper()->GetTabLines()
+ : rTable.GetTabLines();
+ const SwTableLine* pLine = rBox.GetUpper();
+ sal_uInt16 nLineNo = rTableLines.C40_GETPOS( SwTableLine, pLine );
+ pRet = rTableLines[nLineNo - 1];
+
+ return pRet;
+}
+
+const SwTableLines& lcl_FindParentLines( const SwTable& rTable,
+ const SwTableBox& rBox )
+{
+ const SwTableLines& rRet =
+ ( rBox.GetUpper()->GetUpper() != NULL ) ?
+ rBox.GetUpper()->GetUpper()->GetTabLines() :
+ rTable.GetTabLines();
+
+ return rRet;
+}
+
+
+void SwUndoTblNdsChg::SaveNewBoxes( const SwTableNode& rTblNd,
+ const SwTableSortBoxes& rOld,
+ const SwSelBoxes& rBoxes,
+ const SvULongs& rNodeCnts )
+{
+ const SwTable& rTbl = rTblNd.GetTable();
+ const SwTableSortBoxes& rTblBoxes = rTbl.GetTabSortBoxes();
+
+ OSL_ENSURE( ! IsDelBox(), "falsche Action" );
+ Ptrs.pNewSttNds = new SvULongs( (sal_uInt8)(rTblBoxes.Count() - rOld.Count()), 5 );
+
+ OSL_ENSURE( rTbl.IsNewModel() || rOld.Count() + nCount * rBoxes.Count() == rTblBoxes.Count(),
+ "unexpected boxes" );
+ OSL_ENSURE( rOld.Count() <= rTblBoxes.Count(), "more unexpected boxes" );
+ for( sal_uInt16 n = 0, i = 0; i < rTblBoxes.Count(); ++i )
+ {
+ if( ( n < rOld.Count() ) &&
+ ( rOld[ n ] == rTblBoxes[ i ] ) )
+ {
+ // box already known? Then nothing to be done.
+ ++n;
+ }
+ else
+ {
+ // new box found: insert (obey sort order)
+ sal_uInt16 nInsPos;
+ const SwTableBox* pBox = rTblBoxes[ i ];
+ InsertSort( *Ptrs.pNewSttNds, pBox->GetSttIdx(), &nInsPos );
+
+ // find the source box. It must be one in rBoxes.
+ // We found the right one if it's in the same column as pBox.
+ // No, if more than one selected cell in the same column has been splitted,
+ // we have to look for the nearest one (i65201)!
+ const SwTableBox* pSourceBox = NULL;
+ const SwTableBox* pCheckBox = NULL;
+ const SwTableLine* pBoxLine = pBox->GetUpper();
+ sal_uInt16 nLineDiff = lcl_FindParentLines(rTbl,*pBox).C40_GETPOS(SwTableLine,pBoxLine);
+ sal_uInt16 nLineNo = 0;
+ for( sal_uInt16 j = 0; j < rBoxes.Count(); ++j )
+ {
+ pCheckBox = rBoxes[j];
+ if( pCheckBox->GetUpper()->GetUpper() == pBox->GetUpper()->GetUpper() )
+ {
+ const SwTableLine* pCheckLine = pCheckBox->GetUpper();
+ sal_uInt16 nCheckLine = lcl_FindParentLines( rTbl, *pCheckBox ).
+ C40_GETPOS( SwTableLine, pCheckLine );
+ if( ( !pSourceBox || nCheckLine > nLineNo ) && nCheckLine < nLineDiff )
+ {
+ nLineNo = nCheckLine;
+ pSourceBox = pCheckBox;
+ }
+ }
+ }
+
+ // find the line number difference
+ // (to help determine bNodesMoved flag below)
+ nLineDiff = nLineDiff - nLineNo;
+ OSL_ENSURE( pSourceBox, "Splitted source box not found!" );
+ // find out how many nodes the source box used to have
+ // (to help determine bNodesMoved flag below)
+ sal_uInt16 nNdsPos = 0;
+ while( rBoxes[ nNdsPos ] != pSourceBox )
+ ++nNdsPos;
+ sal_uLong nNodes = rNodeCnts[ nNdsPos ];
+
+ // When a new table cell is created, it either gets a new
+ // node, or it gets node(s) from elsewhere. The undo must
+ // know, of course, and thus we must determine here just
+ // where pBox's nodes are from:
+ // If 1) the source box has lost nodes, and
+ // 2) we're in the node range that got nodes
+ // then pBox received nodes from elsewhere.
+ // If bNodesMoved is set for pBox the undo must move the
+ // boxes back, otherwise it must delete them.
+ // The bNodesMoved flag is stored in a seperate array
+ // which mirrors Ptrs.pNewSttNds, i.e. Ptrs.pNewSttNds[i]
+ // and aMvBoxes[i] belong together.
+ sal_Bool bNodesMoved =
+ ( nNodes != ( pSourceBox->GetSttNd()->EndOfSectionIndex() -
+ pSourceBox->GetSttIdx() ) )
+ && ( nNodes - 1 > nLineDiff );
+ aMvBoxes.insert( aMvBoxes.begin() + nInsPos, bNodesMoved );
+ }
+ }
+}
+
+
+void SwUndoTblNdsChg::SaveSection( SwStartNode* pSttNd )
+{
+ OSL_ENSURE( IsDelBox(), "falsche Action" );
+ if( !Ptrs.pDelSects )
+ Ptrs.pDelSects = new SwUndoSaveSections( 10, 5 );
+
+ SwTableNode* pTblNd = pSttNd->FindTableNode();
+ SwUndoSaveSection* pSave = new SwUndoSaveSection;
+ pSave->SaveSection( pSttNd->GetDoc(), SwNodeIndex( *pSttNd ));
+
+ Ptrs.pDelSects->Insert( pSave, Ptrs.pDelSects->Count() );
+ nSttNode = pTblNd->GetIndex();
+}
+
+
+void SwUndoTblNdsChg::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
+
+ SwTableNode *const pTblNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ CHECK_TABLE( pTblNd->GetTable() )
+
+ _FndBox aTmpBox( 0, 0 );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
+ std::vector< SwTableBox* > aDelBoxes;
+ if( IsDelBox() )
+ {
+ // Trick: die fehlenden Boxen in irgendeine Line einfuegen, beim
+ // CreateNew werden sie korrekt verbunden.
+ SwTableBox* pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0];
+ SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
+
+ // die Sections wieder herstellen
+ for( sal_uInt16 n = Ptrs.pDelSects->Count(); n; )
+ {
+ SwUndoSaveSection* pSave = (*Ptrs.pDelSects)[ --n ];
+ pSave->RestoreSection( &rDoc, &aIdx, SwTableBoxStartNode );
+ if( pSave->GetHistory() )
+ pSave->GetHistory()->Rollback( &rDoc );
+ SwTableBox* pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), aIdx,
+ pCpyBox->GetUpper() );
+ rLnBoxes.C40_INSERT( SwTableBox, pBox, rLnBoxes.Count() );
+ }
+ Ptrs.pDelSects->DeleteAndDestroy( 0, Ptrs.pDelSects->Count() );
+ }
+ else if( !aMvBoxes.empty() )
+ {
+ // dann muessen Nodes verschoben und nicht geloescht werden!
+ // Dafuer brauchen wir aber ein temp Array
+ SvULongs aTmp( 0, 5);
+ aTmp.Insert( Ptrs.pNewSttNds, 0 );
+
+ // von hinten anfangen
+ for( sal_uInt16 n = aTmp.Count(); n; )
+ {
+ // Box aus der Tabellen-Struktur entfernen
+ sal_uLong nIdx = aTmp[ --n ];
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+
+ if( aMvBoxes[ n ] )
+ {
+ SwNodeRange aRg( *pBox->GetSttNd(), 1,
+ *pBox->GetSttNd()->EndOfSectionNode() );
+
+ SwTableLine* pLine = lcl_FindTableLine( pTblNd->GetTable(), *pBox );
+ SwNodeIndex aInsPos( *(pLine->GetTabBoxes()[0]->GetSttNd()), 2 );
+
+ // alle StartNode Indizies anpassen
+ sal_uInt16 i = n;
+ sal_uLong nSttIdx = aInsPos.GetIndex() - 2,
+ nNdCnt = aRg.aEnd.GetIndex() - aRg.aStart.GetIndex();
+ while( i && aTmp[ --i ] > nSttIdx )
+ aTmp[ i ] += nNdCnt;
+
+ // erst die Box loeschen
+ delete pBox;
+ // dann die Nodes verschieben,
+ rDoc.GetNodes()._MoveNodes( aRg, rDoc.GetNodes(), aInsPos, sal_False );
+ }
+ else
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ aDelBoxes.insert( aDelBoxes.end(), pBox );
+ }
+ }
+ else
+ {
+ // Remove nodes from nodes array (backwards!)
+ for( sal_uInt16 n = Ptrs.pNewSttNds->Count(); n; )
+ {
+ sal_uLong nIdx = (*Ptrs.pNewSttNds)[ --n ];
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Where's my table box?" );
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+ aDelBoxes.insert( aDelBoxes.end(), pBox );
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ }
+ }
+ // Remove boxes from table structure
+ for( sal_uInt16 n = 0; n < aDelBoxes.size(); ++n )
+ {
+ SwTableBox* pCurrBox = aDelBoxes[n];
+ SwTableBoxes* pTBoxes = &pCurrBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pCurrBox ) );
+ delete pCurrBox;
+ }
+
+ pSaveTbl->CreateNew( pTblNd->GetTable(), sal_True, sal_False );
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
+
+ if( IsDelBox() )
+ nSttNode = pTblNd->GetIndex();
+ ClearFEShellTabCols();
+ CHECK_TABLE( pTblNd->GetTable() )
+}
+
+
+void SwUndoTblNdsChg::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+
+ SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+ CHECK_TABLE( pTblNd->GetTable() )
+
+ SwSelBoxes aSelBoxes;
+ for( sal_uInt16 n = 0; n < aBoxes.Count(); ++n )
+ {
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( aBoxes[ n ] );
+ aSelBoxes.Insert( pBox );
+ }
+
+ // SelBoxes erzeugen und InsertCell/-Row/SplitTbl aufrufen
+ switch( GetId() )
+ {
+ case UNDO_TABLE_INSCOL:
+ if( USHRT_MAX == nSetColType )
+ rDoc.InsertCol( aSelBoxes, nCount, bFlag );
+ else
+ {
+ SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nCurrBox );
+ rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff,
+ nRelDiff );
+ }
+ break;
+
+ case UNDO_TABLE_INSROW:
+ if( USHRT_MAX == nSetColType )
+ rDoc.InsertRow( aSelBoxes, nCount, bFlag );
+ else
+ {
+ SwTable& rTbl = pTblNd->GetTable();
+ SwTableBox* pBox = rTbl.GetTblBox( nCurrBox );
+ TblChgMode eOldMode = rTbl.GetTblChgMode();
+ rTbl.SetTblChgMode( (TblChgMode)nCount );
+ rDoc.SetColRowWidthHeight( *pBox, nSetColType, nAbsDiff, nRelDiff );
+ rTbl.SetTblChgMode( eOldMode );
+ }
+ break;
+
+ case UNDO_TABLE_SPLIT:
+ rDoc.SplitTbl( aSelBoxes, bFlag, nCount, bSameHeight );
+ break;
+ case UNDO_TABLE_DELBOX:
+ case UNDO_ROW_DELETE:
+ case UNDO_COL_DELETE:
+ if( USHRT_MAX == nSetColType )
+ {
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+ SwTable &rTable = pTblNd->GetTable();
+ if( nMax > nMin && rTable.IsNewModel() )
+ rTable.PrepareDeleteCol( nMin, nMax );
+ rTable.DeleteSel( &rDoc, aSelBoxes, 0, this, sal_True, sal_True );
+ }
+ else
+ {
+ SwTable& rTbl = pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ SwTableBox* pBox = rTbl.GetTblBox( nCurrBox );
+ TblChgMode eOldMode = rTbl.GetTblChgMode();
+ rTbl.SetTblChgMode( (TblChgMode)nCount );
+
+ // need the SaveSections!
+ rDoc.GetIDocumentUndoRedo().DoUndo( true );
+ SwUndoTblNdsChg* pUndo = 0;
+
+ switch( nSetColType & 0xff )
+ {
+ case nsTblChgWidthHeightType::WH_COL_LEFT:
+ case nsTblChgWidthHeightType::WH_COL_RIGHT:
+ case nsTblChgWidthHeightType::WH_CELL_LEFT:
+ case nsTblChgWidthHeightType::WH_CELL_RIGHT:
+ rTbl.SetColWidth( *pBox, nSetColType, nAbsDiff,
+ nRelDiff, (SwUndo**)&pUndo );
+ break;
+ case nsTblChgWidthHeightType::WH_ROW_TOP:
+ case nsTblChgWidthHeightType::WH_ROW_BOTTOM:
+ case nsTblChgWidthHeightType::WH_CELL_TOP:
+ case nsTblChgWidthHeightType::WH_CELL_BOTTOM:
+ rTbl.SetRowHeight( *pBox, nSetColType, nAbsDiff,
+ nRelDiff, (SwUndo**)&pUndo );
+ break;
+ }
+
+ if( pUndo )
+ {
+ Ptrs.pDelSects->Insert( pUndo->Ptrs.pDelSects, 0 );
+ pUndo->Ptrs.pDelSects->Remove( 0, pUndo->Ptrs.pDelSects->Count() );
+
+ delete pUndo;
+ }
+ rDoc.GetIDocumentUndoRedo().DoUndo( false );
+
+ rTbl.SetTblChgMode( eOldMode );
+ }
+ nSttNode = pTblNd->GetIndex();
+ break;
+ default:
+ ;
+ }
+ ClearFEShellTabCols();
+ CHECK_TABLE( pTblNd->GetTable() )
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoTblMerge::SwUndoTblMerge( const SwPaM& rTblSel )
+ : SwUndo( UNDO_TABLE_MERGE ), SwUndRng( rTblSel ), pHistory( 0 )
+{
+ const SwTableNode* pTblNd = rTblSel.GetNode()->FindTableNode();
+ OSL_ENSURE( pTblNd, "Wo ist TabllenNode" );
+ pSaveTbl = new _SaveTable( pTblNd->GetTable() );
+ pMoves = new SwUndoMoves;
+ nTblNode = pTblNd->GetIndex();
+}
+
+SwUndoTblMerge::~SwUndoTblMerge()
+{
+ delete pSaveTbl;
+ delete pMoves;
+ delete pHistory;
+}
+
+void SwUndoTblMerge::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwNodeIndex aIdx( rDoc.GetNodes(), nTblNode );
+
+ SwTableNode *const pTblNd = aIdx.GetNode().GetTableNode();
+ OSL_ENSURE( pTblNd, "kein TabellenNode" );
+
+ SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ rDoc.UpdateTblFlds( &aMsgHnt );
+
+ _FndBox aTmpBox( 0, 0 );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+
+ // 1. die geloeschten Boxen wiederherstellen:
+
+ // Trick: die fehlenden Boxen in irgendeine Line einfuegen, beim
+ // CreateNew werden sie korrekt verbunden.
+ SwTableBox *pBox, *pCpyBox = pTblNd->GetTable().GetTabSortBoxes()[0];
+ SwTableBoxes& rLnBoxes = pCpyBox->GetUpper()->GetTabBoxes();
+
+CHECKTABLE(pTblNd->GetTable())
+
+ SwSelBoxes aSelBoxes;
+ SwTxtFmtColl* pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
+ sal_uInt16 n;
+
+ for( n = 0; n < aBoxes.Count(); ++n )
+ {
+ aIdx = aBoxes[ n ];
+ SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection( aIdx,
+ SwTableBoxStartNode, pColl );
+ pBox = new SwTableBox( (SwTableBoxFmt*)pCpyBox->GetFrmFmt(), *pSttNd,
+ pCpyBox->GetUpper() );
+ rLnBoxes.C40_INSERT( SwTableBox, pBox, rLnBoxes.Count() );
+
+ aSelBoxes.Insert( pBox );
+ }
+
+CHECKTABLE(pTblNd->GetTable())
+
+ SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
+ // 2. die eingefuegten Boxen loeschen
+ // die Nodes loeschen (von Hinten!!)
+ for( n = aNewSttNds.Count(); n; )
+ {
+ // Box aus der Tabellen-Struktur entfernen
+ sal_uLong nIdx = aNewSttNds[ --n ];
+
+ if( !nIdx && n )
+ {
+ nIdx = aNewSttNds[ --n ];
+ pBox = pTblNd->GetTable().GetTblBox( nIdx );
+ OSL_ENSURE( pBox, "Wo ist meine TabellenBox geblieben?" );
+
+ if( !pSaveTbl->IsNewModel() )
+ rDoc.GetNodes().MakeTxtNode( SwNodeIndex(
+ *pBox->GetSttNd()->EndOfSectionNode() ), pColl );
+
+ // das war der Trenner, -> die verschobenen herstellen
+ for( sal_uInt16 i = pMoves->Count(); i; )
+ {
+ SwTxtNode* pTxtNd = 0;
+ sal_uInt16 nDelPos = 0;
+ SwUndoMove* pUndo = (*pMoves)[ --i ];
+ if( !pUndo->IsMoveRange() )
+ {
+ pTxtNd = rDoc.GetNodes()[ pUndo->GetDestSttNode() ]->GetTxtNode();
+ nDelPos = pUndo->GetDestSttCntnt() - 1;
+ }
+ pUndo->UndoImpl(rContext);
+ if( pUndo->IsMoveRange() )
+ {
+ // den ueberfluessigen Node loeschen
+ aIdx = pUndo->GetEndNode();
+ SwCntntNode *pCNd = aIdx.GetNode().GetCntntNode();
+ if( pCNd )
+ {
+ SwNodeIndex aTmp( aIdx, -1 );
+ SwCntntNode *pMove = aTmp.GetNode().GetCntntNode();
+ if( pMove )
+ pCNd->MoveTo( *pMove );
+ }
+ rDoc.GetNodes().Delete( aIdx, 1 );
+ }
+ else if( pTxtNd )
+ {
+ // evt. noch ueberflussige Attribute loeschen
+ SwIndex aTmpIdx( pTxtNd, nDelPos );
+ if( pTxtNd->GetpSwpHints() && pTxtNd->GetpSwpHints()->Count() )
+ pTxtNd->RstAttr( aTmpIdx, pTxtNd->GetTxt().Len() -
+ nDelPos + 1 );
+ // das Trennzeichen loeschen
+ pTxtNd->EraseText( aTmpIdx, 1 );
+ }
+ }
+ nIdx = pBox->GetSttIdx();
+ }
+ else
+ pBox = pTblNd->GetTable().GetTblBox( nIdx );
+
+ if( !pSaveTbl->IsNewModel() )
+ {
+ // TL_CHART2: notify chart about box to be removed
+ if (pPCD)
+ pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
+
+ SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
+ pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) );
+
+
+ // Indizies aus dem Bereich loeschen
+ {
+ SwNodeIndex aTmpIdx( *pBox->GetSttNd() );
+ rDoc.CorrAbs( SwNodeIndex( aTmpIdx, 1 ),
+ SwNodeIndex( *aTmpIdx.GetNode().EndOfSectionNode() ),
+ SwPosition( aTmpIdx, SwIndex( 0, 0 )), sal_True );
+ }
+
+ delete pBox;
+ rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+ }
+ }
+CHECKTABLE(pTblNd->GetTable())
+
+
+ pSaveTbl->CreateNew( pTblNd->GetTable(), sal_True, sal_False );
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ rDoc.UpdateCharts( pTblNd->GetTable().GetFrmFmt()->GetName() );
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+// nTblNode = pTblNd->GetIndex();
+
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nSttNode;
+ pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), nSttCntnt );
+ pPam->SetMark();
+ pPam->DeleteMark();
+
+CHECKTABLE(pTblNd->GetTable())
+ ClearFEShellTabCols();
+}
+
+void SwUndoTblMerge::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM & rPam( AddUndoRedoPaM(rContext) );
+ rDoc.MergeTbl(rPam);
+}
+
+void SwUndoTblMerge::MoveBoxCntnt( SwDoc* pDoc, SwNodeRange& rRg, SwNodeIndex& rPos )
+{
+ SwNodeIndex aTmp( rRg.aStart, -1 ), aTmp2( rPos, -1 );
+ SwUndoMove* pUndo = new SwUndoMove( pDoc, rRg, rPos );
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+ pDoc->MoveNodeRange( rRg, rPos, (pSaveTbl->IsNewModel()) ?
+ IDocumentContentOperations::DOC_NO_DELFRMS :
+ IDocumentContentOperations::DOC_MOVEDEFAULT );
+ aTmp++;
+ aTmp2++;
+ pUndo->SetDestRange( aTmp2, rPos, aTmp );
+
+ pMoves->Insert( pUndo, pMoves->Count() );
+}
+
+void SwUndoTblMerge::SetSelBoxes( const SwSelBoxes& rBoxes )
+{
+ // die Selektion merken
+ for( sal_uInt16 n = 0; n < rBoxes.Count(); ++n )
+ InsertSort( aBoxes, rBoxes[n]->GetSttIdx() );
+
+ // als Trennung fuers einfuegen neuer Boxen nach dem Verschieben!
+ aNewSttNds.Insert( (sal_uLong)0, aNewSttNds.Count() );
+
+ // The new table model does not delete overlapped cells (by row span),
+ // so the rBoxes array might be empty even some cells have been merged.
+ if( rBoxes.Count() )
+ nTblNode = rBoxes[ 0 ]->GetSttNd()->FindTableNode()->GetIndex();
+}
+
+void SwUndoTblMerge::SaveCollection( const SwTableBox& rBox )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ SwNodeIndex aIdx( *rBox.GetSttNd(), 1 );
+ SwCntntNode* pCNd = aIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ pCNd = aIdx.GetNodes().GoNext( &aIdx );
+
+ pHistory->Add( pCNd->GetFmtColl(), aIdx.GetIndex(), pCNd->GetNodeType());
+ if( pCNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pCNd->GetpSwAttrSet(), aIdx.GetIndex() );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoTblNumFmt::SwUndoTblNumFmt( const SwTableBox& rBox,
+ const SfxItemSet* pNewSet )
+ : SwUndo( UNDO_TBLNUMFMT ),
+ pBoxSet( 0 ), pHistory( 0 ), nFmtIdx( NUMBERFORMAT_TEXT )
+{
+ bNewFmt = bNewFml = bNewValue = sal_False;
+ nNode = rBox.GetSttIdx();
+
+ nNdPos = rBox.IsValidNumTxtNd( 0 == pNewSet );
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+
+ if( ULONG_MAX != nNdPos )
+ {
+ SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
+
+ pHistory = new SwHistory;
+ SwRegHistory aRHst( *rBox.GetSttNd(), pHistory );
+ // always save all text atttibutes because of possibly overlapping
+ // areas of on/off
+ pHistory->CopyAttr( pTNd->GetpSwpHints(), nNdPos, 0,
+ pTNd->GetTxt().Len(), true );
+
+ if( pTNd->HasSwAttrSet() )
+ pHistory->CopyFmtAttr( *pTNd->GetpSwAttrSet(), nNdPos );
+
+ aStr = pTNd->GetTxt();
+ if( pTNd->GetpSwpHints() )
+ pTNd->GetpSwpHints()->DeRegister();
+ }
+
+ pBoxSet = new SfxItemSet( pDoc->GetAttrPool(), aTableBoxSetRange );
+ pBoxSet->Put( rBox.GetFrmFmt()->GetAttrSet() );
+
+ if( pNewSet )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMAT,
+ sal_False, &pItem ))
+ {
+ bNewFmt = sal_True;
+ nNewFmtIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ }
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMULA,
+ sal_False, &pItem ))
+ {
+ bNewFml = sal_True;
+ aNewFml = ((SwTblBoxFormula*)pItem)->GetFormula();
+ }
+ if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_VALUE,
+ sal_False, &pItem ))
+ {
+ bNewValue = sal_True;
+ fNewNum = ((SwTblBoxValue*)pItem)->GetValue();
+ }
+ }
+
+ // wird die History ueberhaupt benoetigt ??
+ if( pHistory && !pHistory->Count() )
+ DELETEZ( pHistory );
+}
+
+SwUndoTblNumFmt::~SwUndoTblNumFmt()
+{
+ delete pHistory;
+ delete pBoxSet;
+}
+
+void SwUndoTblNumFmt::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ OSL_ENSURE( pBoxSet, "Where's the stored item set?" );
+
+ SwDoc & rDoc = rContext.GetDoc();
+ SwStartNode* pSttNd = rDoc.GetNodes()[ nNode ]->
+ FindSttNodeByType( SwTableBoxStartNode );
+ OSL_ENSURE( pSttNd, "ohne StartNode kein TabellenBox" );
+ SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ OSL_ENSURE( pBox, "keine TabellenBox gefunden" );
+
+ SwTableBoxFmt* pFmt = rDoc.MakeTableBoxFmt();
+ pFmt->SetFmtAttr( *pBoxSet );
+ pBox->ChgFrmFmt( pFmt );
+
+ if( ULONG_MAX == nNdPos )
+ return;
+
+ SwTxtNode* pTxtNd = rDoc.GetNodes()[ nNdPos ]->GetTxtNode();
+ // wenn mehr als ein Node geloescht wurde, dann wurden auch
+ // alle "Node"-Attribute gespeichert
+ if( pTxtNd->HasSwAttrSet() )
+ pTxtNd->ResetAllAttr();
+
+ if( pTxtNd->GetpSwpHints() && aStr.Len() )
+ pTxtNd->ClearSwpHintsArr( true );
+
+ // ChgTextToNum(..) only acts when the strings are different. We
+ // need to do the same here.
+ if( pTxtNd->GetTxt() != aStr )
+ {
+ rDoc.DeleteRedline( *( pBox->GetSttNd() ), false, USHRT_MAX );
+
+ SwIndex aIdx( pTxtNd, 0 );
+ if( aStr.Len() )
+ {
+ pTxtNd->EraseText( aIdx );
+ pTxtNd->InsertText( aStr, aIdx,
+ IDocumentContentOperations::INS_NOHINTEXPAND );
+ }
+ }
+
+ if( pHistory )
+ {
+ sal_uInt16 nTmpEnd = pHistory->GetTmpEnd();
+ pHistory->TmpRollback( &rDoc, 0 );
+ pHistory->SetTmpEnd( nTmpEnd );
+ }
+
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nNode + 1;
+ pPam->GetPoint()->nContent.Assign( pTxtNd, 0 );
+}
+
+/** switch the RedlineMode on the given document, using
+ * SetRedlineMode_intern. This class set the mode in the constructor,
+ * and changes it back in the destructor, i.e. it uses the
+ * initialization-is-resource-acquisition idiom.
+ */
+class RedlineModeInternGuard
+{
+ SwDoc& mrDoc;
+ RedlineMode_t meOldRedlineMode;
+
+public:
+ RedlineModeInternGuard(
+ SwDoc& rDoc, /// change mode of this document
+ RedlineMode_t eNewRedlineMode, /// new redline mode
+ RedlineMode_t eRedlineModeMask = (RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_IGNORE /*change only bits set in this mask*/));
+
+ ~RedlineModeInternGuard();
+};
+
+RedlineModeInternGuard::RedlineModeInternGuard(
+ SwDoc& rDoc,
+ RedlineMode_t eNewRedlineMode,
+ RedlineMode_t eRedlineModeMask )
+ : mrDoc( rDoc ),
+ meOldRedlineMode( rDoc.GetRedlineMode() )
+{
+ mrDoc.SetRedlineMode_intern((RedlineMode_t)( ( meOldRedlineMode & ~eRedlineModeMask ) |
+ ( eNewRedlineMode & eRedlineModeMask ) ));
+}
+
+RedlineModeInternGuard::~RedlineModeInternGuard()
+{
+ mrDoc.SetRedlineMode_intern( meOldRedlineMode );
+}
+
+
+
+void SwUndoTblNumFmt::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ // konnte die Box veraendert werden ?
+ if( !pBoxSet )
+ return ;
+
+ SwDoc & rDoc = rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nNode;
+
+ SwNode * pNd = & pPam->GetPoint()->nNode.GetNode();
+ SwStartNode* pSttNd = pNd->FindSttNodeByType( SwTableBoxStartNode );
+ OSL_ENSURE( pSttNd, "ohne StartNode kein TabellenBox" );
+ SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
+ pSttNd->GetIndex() );
+ OSL_ENSURE( pBox, "keine TabellenBox gefunden" );
+
+ SwFrmFmt* pBoxFmt = pBox->ClaimFrmFmt();
+ if( bNewFmt || bNewFml || bNewValue )
+ {
+ SfxItemSet aBoxSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->LockModify();
+
+ if( bNewFml )
+ aBoxSet.Put( SwTblBoxFormula( aNewFml ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
+ if( bNewFmt )
+ aBoxSet.Put( SwTblBoxNumFormat( nNewFmtIdx ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT );
+ if( bNewValue )
+ aBoxSet.Put( SwTblBoxValue( fNewNum ));
+ else
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_VALUE );
+ pBoxFmt->UnlockModify();
+
+ // dvo: When redlining is (was) enabled, setting the attribute
+ // will also change the cell content. To allow this, the
+ // REDLINE_IGNORE flag must be removed during Redo. #108450#
+ RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE );
+ pBoxFmt->SetFmtAttr( aBoxSet );
+ }
+ else if( NUMBERFORMAT_TEXT != nFmtIdx )
+ {
+ SfxItemSet aBoxSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+
+ aBoxSet.Put( SwTblBoxNumFormat( nFmtIdx ));
+ aBoxSet.Put( SwTblBoxValue( fNum ));
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->LockModify();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMULA );
+ pBoxFmt->UnlockModify();
+
+ // dvo: When redlining is (was) enabled, setting the attribute
+ // will also change the cell content. To allow this, the
+ // REDLINE_IGNORE flag must be removed during Redo. #108450#
+ RedlineModeInternGuard aGuard( rDoc, nsRedlineMode_t::REDLINE_NONE, nsRedlineMode_t::REDLINE_IGNORE );
+ pBoxFmt->SetFmtAttr( aBoxSet );
+ }
+ else
+ {
+ // es ist keine Zahl
+
+ // JP 15.01.99: Nur Attribute zuruecksetzen reicht nicht.
+ // Sorge dafuer, das der Text auch entsprechend
+ // formatiert wird!
+ pBoxFmt->SetFmtAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
+
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ }
+
+ if( bNewFml )
+ {
+ // egal was gesetzt wurde, ein Update der Tabelle macht sich immer gut
+ SwTableFmlUpdate aTblUpdate( &pSttNd->FindTableNode()->GetTable() );
+ rDoc.UpdateTblFlds( &aTblUpdate );
+ }
+
+ if( !pNd->IsCntntNode() )
+ pNd = rDoc.GetNodes().GoNext( &pPam->GetPoint()->nNode );
+ pPam->GetPoint()->nContent.Assign( (SwCntntNode*)pNd, 0 );
+}
+
+void SwUndoTblNumFmt::SetBox( const SwTableBox& rBox )
+{
+ nNode = rBox.GetSttIdx();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+_UndoTblCpyTbl_Entry::_UndoTblCpyTbl_Entry( const SwTableBox& rBox )
+ : nBoxIdx( rBox.GetSttIdx() ), nOffset( 0 ),
+ pBoxNumAttr( 0 ), pUndo( 0 ), bJoin( false )
+{
+}
+
+_UndoTblCpyTbl_Entry::~_UndoTblCpyTbl_Entry()
+{
+ delete pUndo;
+ delete pBoxNumAttr;
+}
+
+
+SwUndoTblCpyTbl::SwUndoTblCpyTbl()
+ : SwUndo( UNDO_TBLCPYTBL ), pInsRowUndo( 0 )
+{
+ pArr = new _UndoTblCpyTbl_Entries;
+}
+
+SwUndoTblCpyTbl::~SwUndoTblCpyTbl()
+{
+ delete pArr;
+ delete pInsRowUndo;
+}
+
+void SwUndoTblCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ _DEBUG_REDLINE( &rDoc )
+
+ SwTableNode* pTblNd = 0;
+ for( sal_uInt16 n = pArr->Count(); n; )
+ {
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ --n ];
+ sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
+ SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
+ if( !pTblNd )
+ pTblNd = pSNd->FindTableNode();
+
+ SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
+
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+ rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() );
+
+ // b62341295: Redline for copying tables
+ const SwNode *pEndNode = rBox.GetSttNd()->EndOfSectionNode();
+ SwPaM aPam( aInsIdx.GetNode(), *pEndNode );
+ SwUndoDelete* pUndo = 0;
+
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ bool bDeleteCompleteParagraph = false;
+ bool bShiftPam = false;
+ // There are a couple of different situations to consider during redlining
+ if( pEntry->pUndo )
+ {
+ SwUndoDelete *const pUndoDelete =
+ dynamic_cast<SwUndoDelete*>(pEntry->pUndo);
+ SwUndoRedlineDelete *const pUndoRedlineDelete =
+ dynamic_cast<SwUndoRedlineDelete*>(pEntry->pUndo);
+ OSL_ASSERT(pUndoDelete || pUndoRedlineDelete);
+ if (pUndoRedlineDelete)
+ {
+ // The old content was not empty or he has been merged with the new content
+ bDeleteCompleteParagraph = !pEntry->bJoin; // bJoin is set when merged
+ // Set aTmpIdx to the beginning fo the old content
+ SwNodeIndex aTmpIdx( *pEndNode,
+ pUndoRedlineDelete->NodeDiff()-1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt,
+ pUndoRedlineDelete->ContentStart() );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ else if (pUndoDelete && pUndoDelete->IsDelFullPara())
+ {
+ // When the old content was an empty paragraph, but could not be joined
+ // with the new content (e.g. because of a section or table)
+ // We "save" the aPam.Point, we go one step backwards (because later on the
+ // empty paragraph will be inserted by the undo) and set the "ShiftPam-flag
+ // for step forward later on.
+ bDeleteCompleteParagraph = true;
+ bShiftPam = true;
+ SwNodeIndex aTmpIdx( *pEndNode, -1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt, 0 );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ }
+ rDoc.DeleteRedline( aPam, true, USHRT_MAX );
+
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->UndoImpl(rContext);
+ delete pEntry->pUndo;
+ pEntry->pUndo = 0;
+ }
+ if( bShiftPam )
+ {
+ // The aPam.Point is at the moment at the last position of the new content and has to be
+ // moved to the first postion of the old content for the SwUndoDelete operation
+ SwNodeIndex aTmpIdx( aPam.GetPoint()->nNode, 1 );
+ SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aPam.GetPoint()->nNode = *pTxt;
+ aPam.GetPoint()->nContent.Assign( pTxt, 0 );
+ }
+ else
+ *aPam.GetPoint() = SwPosition( aTmpIdx );
+ }
+ pUndo = new SwUndoDelete( aPam, bDeleteCompleteParagraph, sal_True );
+ }
+ else
+ {
+ pUndo = new SwUndoDelete( aPam, true );
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->UndoImpl(rContext);
+ delete pEntry->pUndo;
+ pEntry->pUndo = 0;
+ }
+ }
+ pEntry->pUndo = pUndo;
+
+ aInsIdx = rBox.GetSttIdx() + 1;
+ rDoc.GetNodes().Delete( aInsIdx, 1 );
+
+ SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( aTmpSet.Count() )
+ {
+ SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT );
+ }
+
+ if( pEntry->pBoxNumAttr )
+ {
+ rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr );
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ }
+
+ if( aTmpSet.Count() )
+ {
+ pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( aTmpSet );
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+ }
+
+ if( pInsRowUndo )
+ {
+ pInsRowUndo->UndoImpl(rContext);
+ }
+ _DEBUG_REDLINE( &rDoc )
+}
+
+void SwUndoTblCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ _DEBUG_REDLINE( &rDoc )
+
+ if( pInsRowUndo )
+ {
+ pInsRowUndo->RedoImpl(rContext);
+ }
+
+ SwTableNode* pTblNd = 0;
+ for( sal_uInt16 n = 0; n < pArr->Count(); ++n )
+ {
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ n ];
+ sal_uLong nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
+ SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
+ if( !pTblNd )
+ pTblNd = pSNd->FindTableNode();
+
+ SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
+
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+
+ // b62341295: Redline for copying tables - Start.
+ rDoc.GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl() );
+ SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode());
+ SwUndo* pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ? 0 : new SwUndoDelete( aPam, sal_True );
+ if( pEntry->pUndo )
+ {
+ pEntry->pUndo->UndoImpl(rContext);
+ if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
+ {
+ // PrepareRedline has to be called with the beginning of the old content
+ // When new and old content has been joined, the rIter.pAktPam has been set
+ // by the Undo operation to this point.
+ // Otherwise aInsIdx has been moved during the Undo operation
+ if( pEntry->bJoin )
+ {
+ SwPaM const& rLastPam =
+ rContext.GetCursorSupplier().GetCurrentShellCursor();
+ pUndo = PrepareRedline( &rDoc, rBox, *rLastPam.GetPoint(),
+ pEntry->bJoin, true );
+ }
+ else
+ {
+ SwPosition aTmpPos( aInsIdx );
+ pUndo = PrepareRedline( &rDoc, rBox, aTmpPos, pEntry->bJoin, true );
+ }
+ }
+ delete pEntry->pUndo;
+ pEntry->pUndo = 0;
+ }
+ pEntry->pUndo = pUndo;
+ // b62341295: Redline for copying tables - End.
+
+ aInsIdx = rBox.GetSttIdx() + 1;
+ rDoc.GetNodes().Delete( aInsIdx, 1 );
+
+ SfxItemSet aTmpSet( rDoc.GetAttrPool(), RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ aTmpSet.Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( aTmpSet.Count() )
+ {
+ SwFrmFmt* pBoxFmt = rBox.ClaimFrmFmt();
+ pBoxFmt->ResetFmtAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
+ pBoxFmt->ResetFmtAttr( RES_VERT_ORIENT );
+ }
+ if( pEntry->pBoxNumAttr )
+ {
+ rBox.ClaimFrmFmt()->SetFmtAttr( *pEntry->pBoxNumAttr );
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ }
+
+ if( aTmpSet.Count() )
+ {
+ pEntry->pBoxNumAttr = new SfxItemSet( rDoc.GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( aTmpSet );
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+ }
+ _DEBUG_REDLINE( &rDoc )
+}
+
+void SwUndoTblCpyTbl::AddBoxBefore( const SwTableBox& rBox, sal_Bool bDelCntnt )
+{
+ if( pArr->Count() && !bDelCntnt )
+ return;
+
+ _UndoTblCpyTbl_Entry* pEntry = new _UndoTblCpyTbl_Entry( rBox );
+ pArr->Insert( pEntry, pArr->Count() );
+
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+ _DEBUG_REDLINE( pDoc )
+ if( bDelCntnt )
+ {
+ SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
+ pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );
+
+ if( !pDoc->IsRedlineOn() )
+ pEntry->pUndo = new SwUndoDelete( aPam, sal_True );
+ }
+
+ pEntry->pBoxNumAttr = new SfxItemSet( pDoc->GetAttrPool(),
+ RES_BOXATR_FORMAT, RES_BOXATR_VALUE,
+ RES_VERT_ORIENT, RES_VERT_ORIENT, 0 );
+ pEntry->pBoxNumAttr->Put( rBox.GetFrmFmt()->GetAttrSet() );
+ if( !pEntry->pBoxNumAttr->Count() )
+ delete pEntry->pBoxNumAttr, pEntry->pBoxNumAttr = 0;
+ _DEBUG_REDLINE( pDoc )
+}
+
+void SwUndoTblCpyTbl::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx, sal_Bool bDelCntnt )
+{
+ _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ pArr->Count() - 1 ];
+
+ // wurde der Inhalt geloescht, so loesche jetzt auch noch den temp.
+ // erzeugten Node
+ if( bDelCntnt )
+ {
+ SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
+ _DEBUG_REDLINE( pDoc )
+
+ if( pDoc->IsRedlineOn() )
+ {
+ SwPosition aTmpPos( rIdx );
+ pEntry->pUndo = PrepareRedline( pDoc, rBox, aTmpPos, pEntry->bJoin, false );
+ }
+ SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 );
+ rBox.GetFrmFmt()->GetDoc()->GetNodes().Delete( aDelIdx, 1 );
+ _DEBUG_REDLINE( pDoc )
+ }
+
+ pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx;
+}
+
+// PrepareRedline is called from AddBoxAfter() and from Redo() in slightly different situations.
+// bRedo is set by calling from Redo()
+// rJoin is false by calling from AddBoxAfter() and will be set if the old and new content has
+// been merged.
+// rJoin is true if Redo() is calling and the content has already been merged
+
+SwUndo* SwUndoTblCpyTbl::PrepareRedline( SwDoc* pDoc, const SwTableBox& rBox,
+ const SwPosition& rPos, bool& rJoin, bool bRedo )
+{
+ SwUndo *pUndo = 0;
+ // b62341295: Redline for copying tables
+ // What's to do?
+ // Mark the cell content before rIdx as insertion,
+ // mark the cell content behind rIdx as deletion
+ // merge text nodes at rIdx if possible
+ RedlineMode_t eOld = pDoc->GetRedlineMode();
+ pDoc->SetRedlineMode_intern((RedlineMode_t)( ( eOld | nsRedlineMode_t::REDLINE_DONTCOMBINE_REDLINES ) &
+ ~nsRedlineMode_t::REDLINE_IGNORE ));
+ SwPosition aInsertEnd( rPos );
+ SwTxtNode* pTxt;
+ if( !rJoin )
+ {
+ // If the content is not merged, the end of the insertion is at the end of the node
+ // _before_ the given position rPos
+ --aInsertEnd.nNode;
+ pTxt = aInsertEnd.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ {
+ aInsertEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() );
+ if( !bRedo && rPos.nNode.GetNode().GetTxtNode() )
+ { // Try to merge, if not called by Redo()
+ rJoin = true;
+ pTxt->JoinNext();
+ }
+ }
+ else
+ aInsertEnd.nContent = SwIndex( 0 );
+ }
+ // For joined (merged) contents the start of deletionm and end of insertion are identical
+ // otherwise adjacent nodes.
+ SwPosition aDeleteStart( rJoin ? aInsertEnd : rPos );
+ if( !rJoin )
+ {
+ pTxt = aDeleteStart.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aDeleteStart.nContent.Assign( pTxt, 0 );
+ }
+ SwPosition aCellEnd( SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode(), -1 ) );
+ pTxt = aCellEnd.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aCellEnd.nContent.Assign( pTxt, pTxt->GetTxt().Len() );
+ if( aDeleteStart != aCellEnd )
+ { // If the old (deleted) part is not empty, here we are...
+ SwPaM aDeletePam( aDeleteStart, aCellEnd );
+ pUndo = new SwUndoRedlineDelete( aDeletePam, UNDO_DELETE );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_DELETE, aDeletePam ), true );
+ }
+ else if( !rJoin ) // If the old part is empty and joined, we are finished
+ { // if it is not joined, we have to delete this empty paragraph
+ aCellEnd = SwPosition(
+ SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() ));
+ SwPaM aTmpPam( aDeleteStart, aCellEnd );
+ pUndo = new SwUndoDelete( aTmpPam, sal_True );
+ }
+ SwPosition aCellStart( SwNodeIndex( *rBox.GetSttNd(), 2 ) );
+ pTxt = aCellStart.nNode.GetNode().GetTxtNode();
+ if( pTxt )
+ aCellStart.nContent.Assign( pTxt, 0 );
+ if( aCellStart != aInsertEnd ) // An empty insertion will not been marked
+ {
+ SwPaM aTmpPam( aCellStart, aInsertEnd );
+ pDoc->AppendRedline( new SwRedline( nsRedlineType_t::REDLINE_INSERT, aTmpPam ), true );
+ }
+
+ pDoc->SetRedlineMode_intern( eOld );
+ return pUndo;
+}
+
+
+sal_Bool SwUndoTblCpyTbl::InsertRow( SwTable& rTbl, const SwSelBoxes& rBoxes,
+ sal_uInt16 nCnt )
+{
+ SwTableNode* pTblNd = (SwTableNode*)rTbl.GetTabSortBoxes()[0]->
+ GetSttNd()->FindTableNode();
+
+ SwTableSortBoxes aTmpLst( 0, 5 );
+ pInsRowUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW, rBoxes, *pTblNd,
+ 0, 0, nCnt, sal_True, sal_False );
+ aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
+
+ sal_Bool bRet = rTbl.InsertRow( rTbl.GetFrmFmt()->GetDoc(), rBoxes, nCnt, sal_True );
+ if( bRet )
+ pInsRowUndo->SaveNewBoxes( *pTblNd, aTmpLst );
+ else
+ delete pInsRowUndo, pInsRowUndo = 0;
+ return bRet;
+}
+
+sal_Bool SwUndoTblCpyTbl::IsEmpty() const
+{
+ return !pInsRowUndo && !pArr->Count();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoCpyTbl::SwUndoCpyTbl()
+ : SwUndo( UNDO_CPYTBL ), pDel( 0 ), nTblNode( 0 )
+{
+}
+
+SwUndoCpyTbl::~SwUndoCpyTbl()
+{
+ delete pDel;
+}
+
+void SwUndoCpyTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc & rDoc = rContext.GetDoc();
+ SwTableNode* pTNd = rDoc.GetNodes()[ nTblNode ]->GetTableNode();
+
+ // harte SeitenUmbrueche am nachfolgenden Node verschieben
+ SwCntntNode* pNextNd = rDoc.GetNodes()[ pTNd->EndOfSectionIndex()+1 ]->GetCntntNode();
+ if( pNextNd )
+ {
+ SwFrmFmt* pTableFmt = pTNd->GetTable().GetFrmFmt();
+ const SfxPoolItem *pItem;
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_PAGEDESC,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+
+ if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
+ sal_False, &pItem ) )
+ pNextNd->SetAttr( *pItem );
+ }
+
+ SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 );
+ pDel = new SwUndoDelete( aPam, sal_True );
+}
+
+void SwUndoCpyTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ pDel->UndoImpl(rContext);
+ delete pDel, pDel = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoSplitTbl::SwUndoSplitTbl( const SwTableNode& rTblNd,
+ SwSaveRowSpan* pRowSp, sal_uInt16 eMode, sal_Bool bNewSize )
+ : SwUndo( UNDO_SPLIT_TABLE ),
+ nTblNode( rTblNd.GetIndex() ), nOffset( 0 ), mpSaveRowSpan( pRowSp ), pSavTbl( 0 ),
+ pHistory( 0 ), nMode( eMode ), nFmlEnd( 0 ), bCalcNewSize( bNewSize )
+{
+ switch( nMode )
+ {
+ case HEADLINE_BOXATRCOLLCOPY:
+ pHistory = new SwHistory;
+ // kein break;
+ case HEADLINE_BORDERCOPY:
+ case HEADLINE_BOXATTRCOPY:
+ pSavTbl = new _SaveTable( rTblNd.GetTable(), 1, sal_False );
+ break;
+ }
+}
+
+SwUndoSplitTbl::~SwUndoSplitTbl()
+{
+ delete pSavTbl;
+ delete pHistory;
+ delete mpSaveRowSpan;
+}
+
+void SwUndoSplitTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
+ rIdx = nTblNode + nOffset;
+
+ //Den implizit erzeugten Absatz wieder entfernen.
+ pDoc->GetNodes().Delete( rIdx, 1 );
+
+ rIdx = nTblNode + nOffset;
+ SwTableNode* pTblNd = rIdx.GetNode().GetTableNode();
+ SwTable& rTbl = pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( &rTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ pDoc->UpdateTblFlds( &aMsgHnt );
+
+ switch( nMode )
+ {
+ case HEADLINE_BOXATRCOLLCOPY:
+ if( pHistory )
+ pHistory->TmpRollback( pDoc, nFmlEnd );
+
+ // kein break
+ case HEADLINE_BOXATTRCOPY:
+ case HEADLINE_BORDERCOPY:
+ {
+ pSavTbl->CreateNew( rTbl, sal_False );
+ pSavTbl->RestoreAttr( rTbl );
+ }
+ break;
+
+ case HEADLINE_CNTNTCOPY:
+ // die erzeugte 1. Line muss wieder entfernt werden
+ {
+ SwSelBoxes aSelBoxes;
+ SwTableBox* pBox = rTbl.GetTblBox( nTblNode + nOffset + 1 );
+ rTbl.SelLineFromBox( pBox, aSelBoxes, sal_True );
+ _FndBox aTmpBox( 0, 0 );
+ aTmpBox.SetTableLines( aSelBoxes, rTbl );
+ aTmpBox.DelFrms( rTbl );
+ rTbl.DeleteSel( pDoc, aSelBoxes, 0, 0, sal_False, sal_False );
+ }
+ break;
+ }
+
+ pDoc->GetNodes().MergeTable( rIdx );
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( pDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+ if( mpSaveRowSpan )
+ {
+ pTblNd = rIdx.GetNode().FindTableNode();
+ if( pTblNd )
+ pTblNd->GetTable().RestoreRowSpan( *mpSaveRowSpan );
+ }
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nTblNode;
+ pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
+
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwPaM *const pPam = & rContext.GetRepeatPaM();
+ SwDoc *const pDoc = & rContext.GetDoc();
+
+ pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
+ ClearFEShellTabCols();
+}
+
+void SwUndoSplitTbl::SaveFormula( SwHistory& rHistory )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+
+ nFmlEnd = rHistory.Count();
+ pHistory->Move( 0, &rHistory );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SwUndoMergeTbl::SwUndoMergeTbl( const SwTableNode& rTblNd,
+ const SwTableNode& rDelTblNd,
+ sal_Bool bWithPrv, sal_uInt16 nMd )
+ : SwUndo( UNDO_MERGE_TABLE ), pSavTbl( 0 ),
+ pHistory( 0 ), nMode( nMd ), bWithPrev( bWithPrv )
+{
+ // Endnode der letzen Tabellenzelle merken, die auf der Position verbleibt
+ if( bWithPrev )
+ nTblNode = rDelTblNd.EndOfSectionIndex() - 1;
+ else
+ nTblNode = rTblNd.EndOfSectionIndex() - 1;
+
+ aName = rDelTblNd.GetTable().GetFrmFmt()->GetName();
+ pSavTbl = new _SaveTable( rDelTblNd.GetTable() );
+
+ pSavHdl = bWithPrev ? new _SaveTable( rTblNd.GetTable(), 1 ) : 0;
+}
+
+SwUndoMergeTbl::~SwUndoMergeTbl()
+{
+ delete pSavTbl;
+ delete pSavHdl;
+ delete pHistory;
+}
+
+void SwUndoMergeTbl::UndoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
+ rIdx = nTblNode;
+
+ SwTableNode* pTblNd = rIdx.GetNode().FindTableNode();
+ SwTable* pTbl = &pTblNd->GetTable();
+
+ SwTableFmlUpdate aMsgHnt( pTbl );
+ aMsgHnt.eFlags = TBL_BOXPTR;
+ pDoc->UpdateTblFlds( &aMsgHnt );
+
+ //Lines fuer das Layout-Update herausuchen.
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.SetTableLines( *pTbl );
+ aFndBox.DelFrms( *pTbl );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ SwTableNode* pNew = pDoc->GetNodes().SplitTable( rIdx, sal_True, sal_False );
+
+ //Layout updaten
+ aFndBox.MakeFrms( *pTbl );
+ // ? TL_CHART2: notification or locking of controller required ?
+
+ if( bWithPrev )
+ {
+ // den Namen umsetzen
+ pNew->GetTable().GetFrmFmt()->SetName( pTbl->GetFrmFmt()->GetName() );
+ pSavHdl->RestoreAttr( pNew->GetTable() );
+ }
+ else
+ pTbl = &pNew->GetTable();
+ pTbl->GetFrmFmt()->SetName( aName );
+
+// pSavTbl->CreateNew( *pTbl, sal_False );
+ pSavTbl->RestoreAttr( *pTbl );
+
+
+ if( pHistory )
+ {
+ pHistory->TmpRollback( pDoc, 0 );
+ pHistory->SetTmpEnd( pHistory->Count() );
+ }
+
+ // fuer die neue Tabelle die Frames anlegen
+ SwNodeIndex aTmpIdx( *pNew );
+ pNew->MakeFrms( &aTmpIdx );
+
+ // Cursor irgendwo in den Content stellen
+ SwCntntNode* pCNd = pDoc->GetNodes().GoNext( &rIdx );
+ pPam->GetPoint()->nContent.Assign( pCNd, 0 );
+
+ ClearFEShellTabCols();
+
+ // TL_CHART2: need to inform chart of probably changed cell names
+ SwChartDataProvider *pPCD = pDoc->GetChartDataProvider();
+ if (pPCD)
+ {
+ pDoc->UpdateCharts( pTbl->GetFrmFmt()->GetName() );
+ pDoc->UpdateCharts( pNew->GetTable().GetFrmFmt()->GetName() );
+ }
+}
+
+void SwUndoMergeTbl::RedoImpl(::sw::UndoRedoContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam(& rContext.GetCursorSupplier().CreateNewShellCursor());
+
+ pPam->DeleteMark();
+ pPam->GetPoint()->nNode = nTblNode;
+ if( bWithPrev )
+ pPam->GetPoint()->nNode = nTblNode + 3;
+ else
+ pPam->GetPoint()->nNode = nTblNode;
+
+ pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode );
+
+ ClearFEShellTabCols();
+}
+
+void SwUndoMergeTbl::RepeatImpl(::sw::RepeatContext & rContext)
+{
+ SwDoc *const pDoc = & rContext.GetDoc();
+ SwPaM *const pPam = & rContext.GetRepeatPaM();
+
+ pDoc->MergeTable( *pPam->GetPoint(), bWithPrev, nMode );
+ ClearFEShellTabCols();
+}
+
+void SwUndoMergeTbl::SaveFormula( SwHistory& rHistory )
+{
+ if( !pHistory )
+ pHistory = new SwHistory;
+ pHistory->Move( 0, &rHistory );
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos )
+{
+ sal_uInt16 nO = rArr.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( *(rArr.GetData() + nM) == nIdx )
+ {
+ OSL_FAIL( "Index already exists. This should never happen." );
+ return;
+ }
+ if( *(rArr.GetData() + nM) < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ break;
+ else
+ nO = nM - 1;
+ }
+ }
+ rArr.Insert( nIdx, nU );
+ if( pInsPos )
+ *pInsPos = nU;
+}
+
+void InsertSort( SvULongs& rArr, sal_uLong nIdx, sal_uInt16* pInsPos )
+{
+ sal_uInt16 nO = rArr.Count(), nM, nU = 0;
+ if( nO > 0 )
+ {
+ nO--;
+ while( nU <= nO )
+ {
+ nM = nU + ( nO - nU ) / 2;
+ if( *(rArr.GetData() + nM) == nIdx )
+ {
+ OSL_FAIL( "Index ist schon vorhanden, darf nie sein!" );
+ return;
+ }
+ if( *(rArr.GetData() + nM) < nIdx )
+ nU = nM + 1;
+ else if( nM == 0 )
+ break;
+ else
+ nO = nM - 1;
+ }
+ }
+ rArr.Insert( nIdx, nU );
+ if( pInsPos )
+ *pInsPos = nU;
+}
+
+#if OSL_DEBUG_LEVEL > 1
+
+
+void CheckTable( const SwTable& rTbl )
+{
+ const SwNodes& rNds = rTbl.GetFrmFmt()->GetDoc()->GetNodes();
+ const SwTableSortBoxes& rSrtArr = rTbl.GetTabSortBoxes();
+ for( sal_uInt16 n = 0; n < rSrtArr.Count(); ++n )
+ {
+ const SwTableBox* pBox = rSrtArr[ n ];
+ const SwNode* pNd = pBox->GetSttNd();
+ OSL_ENSURE( rNds[ pBox->GetSttIdx() ] == pNd, "Box mit falchem StartNode" );
+ }
+}
+#endif
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */