Files
libreoffice/sw/source/core/undo/untbl.cxx

3257 lines
100 KiB
C++
Raw Normal View History

2000-09-18 23:08:29 +00:00
/*************************************************************************
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 23:08:29 +00:00
*
* $RCSfile: untbl.cxx,v $
2000-09-18 23:08:29 +00:00
*
* $Revision: 1.26 $
2000-09-18 23:08:29 +00:00
*
* last change: $Author: rt $ $Date: 2006-12-01 15:50:30 $
2000-09-18 23:08:29 +00:00
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
2000-09-18 23:08:29 +00:00
*
*
* GNU Lesser General Public License Version 2.1
* =============================================
* Copyright 2005 by Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, CA 94303, USA
2000-09-18 23:08:29 +00:00
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1, as published by the Free Software Foundation.
2000-09-18 23:08:29 +00:00
*
* This library 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 for more details.
2000-09-18 23:08:29 +00:00
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
2000-09-18 23:08:29 +00:00
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
2000-09-18 23:08:29 +00:00
#define ITEMID_BOXINFO SID_ATTR_BORDER_INNER
#ifndef _HINTIDS_HXX
#include <hintids.hxx>
#endif
#ifndef _SVX_BRKITEM_HXX //autogen
#include <svx/brkitem.hxx>
#endif
#ifndef _FMTORNT_HXX //autogen
#include <fmtornt.hxx>
#endif
#ifndef _FMTPDSC_HXX //autogen
#include <fmtpdsc.hxx>
#endif
#ifndef _DOC_HXX
#include <doc.hxx>
#endif
#ifndef _DOCARY_HXX
#include <docary.hxx>
#endif
#ifndef _NDTXT_HXX
#include <ndtxt.hxx>
#endif
#ifndef _SWTABLE_HXX
#include <swtable.hxx>
#endif
#ifndef _PAM_HXX
#include <pam.hxx>
#endif
#ifndef _CNTFRM_HXX
#include <cntfrm.hxx>
#endif
#ifndef _TBLSEL_HXX
#include <tblsel.hxx>
#endif
#ifndef _SWUNDO_HXX
#include <swundo.hxx> // fuer die UndoIds
#endif
#ifndef _UNDOBJ_HXX
#include <undobj.hxx>
#endif
#ifndef _ROLBCK_HXX
#include <rolbck.hxx>
#endif
#ifndef _DDEFLD_HXX
#include <ddefld.hxx>
#endif
#ifndef _TABCOL_HXX
#include <tabcol.hxx>
#endif
#ifndef _TABFRM_HXX
#include <tabfrm.hxx>
#endif
#ifndef _ROWFRM_HXX
#include <rowfrm.hxx>
#endif
#ifndef _CELLFRM_HXX
#include <cellfrm.hxx>
#endif
#ifndef _SWCACHE_HXX
#include <swcache.hxx>
#endif
#ifndef _TBLAFMT_HXX
#include <tblafmt.hxx>
#endif
#ifndef _POOLFMT_HXX
#include <poolfmt.hxx>
#endif
#ifndef _MVSAVE_HXX
#include <mvsave.hxx>
#endif
#ifndef _CELLATR_HXX
#include <cellatr.hxx>
#endif
#ifndef _SWTBLFMT_HXX
#include <swtblfmt.hxx>
#endif
#ifndef _SWDDETBL_HXX
#include <swddetbl.hxx>
#endif
#ifndef _REDLINE_HXX
#include <redline.hxx>
#endif
#ifndef _NODE2LAY_HXX
#include <node2lay.hxx>
#endif
#ifndef _TBLRWCL_HXX
#include <tblrwcl.hxx>
#endif
#ifndef _FMTANCHR_HXX
#include <fmtanchr.hxx>
#endif
#ifndef _COMCORE_HRC
#include <comcore.hrc>
#endif
2000-09-18 23:08:29 +00:00
#ifdef PRODUCT
#define _DEBUG_REDLINE( pDoc )
#else
void lcl_DebugRedline( const SwDoc* pDoc );
#define _DEBUG_REDLINE( pDoc ) lcl_DebugRedline( pDoc );
#endif
2000-09-18 23:08:29 +00:00
inline SwDoc& SwUndoIter::GetDoc() const { return *pAktPam->GetDoc(); }
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
{
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
2000-09-18 23:08:29 +00:00
_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;
_SaveLine* pLine;
const SwTable* pSwTable;
SfxItemSets aSets;
SwFrmFmts aFrmFmts;
SfxItemSet aTblSet;
USHORT nLineCount;
BOOL bModifyBox : 1;
BOOL bSaveFormula : 1;
public:
_SaveTable( const SwTable& rTbl, USHORT nLnCnt = USHRT_MAX,
BOOL bSaveFml = TRUE );
~_SaveTable();
USHORT AddFmt( SwFrmFmt* pFmt );
void NewFrmFmt( const SwClient* pLnBx, BOOL bIsLine, USHORT nFmtPos,
SwFrmFmt* pOldFmt );
void RestoreAttr( SwTable& rTbl, BOOL bModifyBox = FALSE );
void SaveCntntAttrs( SwDoc* pDoc );
void CreateNew( SwTable& rTbl, BOOL bCreateFrms = TRUE,
BOOL bRestoreChart = TRUE );
};
class _SaveLine
{
friend class _SaveTable;
friend class _SaveBox;
_SaveLine* pNext;
_SaveBox* pBox;
USHORT 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;
ULONG nSttNode;
USHORT 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, USHORT nIdx, USHORT* pInsPos = 0 );
void InsertSort( SvULongs& rArr, ULONG nIdx, USHORT* pInsPos = 0 );
#if defined( JP_DEBUG ) && !defined( PRODUCT )
#include "shellio.hxx"
void DumpDoc( SwDoc* pDoc, const String& rFileNm );
void CheckTable( const SwTable& );
#define DUMPDOC(p,s) DumpDoc( p, s);
#define CHECKTABLE(t) CheckTable( t );
#else
#define DUMPDOC(p,s)
#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.
*/
2000-09-18 23:08:29 +00:00
struct SwTblToTxtSave
{
ULONG nNode;
ULONG nEndNd;
2000-09-18 23:08:29 +00:00
xub_StrLen nCntnt;
SwHistory* pHstry;
SwTblToTxtSave( SwDoc& rDoc, ULONG nNd, ULONG nEndIdx, xub_StrLen nCntnt );
2000-09-18 23:08:29 +00:00
~SwTblToTxtSave() { delete 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 )
USHORT __FAR_DATA 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, USHORT nCl, USHORT nRw,
USHORT nAdj, const SwInsertTableOptions& rInsTblOpts,
2000-09-18 23:08:29 +00:00
const SwTableAutoFmt* pTAFmt,
const SvUShorts* pColArr,
const String & rName)
2000-09-18 23:08:29 +00:00
: SwUndo( UNDO_INSTABLE ), nSttNode( rPos.nNode.GetIndex() ),
nRows( nRw ), nCols( nCl ), nAdjust( nAdj ), pDDEFldType( 0 ),
aInsTblOpts( rInsTblOpts ), pColWidth( 0 ), pRedlData( 0 ), pAutoFmt( 0 )
2000-09-18 23:08:29 +00:00
{
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( IDocumentRedlineAccess::REDLINE_INSERT, rDoc.GetRedlineAuthor() );
2000-09-18 23:08:29 +00:00
SetRedlineMode( rDoc.GetRedlineMode() );
}
sTblNm = rName;
2000-09-18 23:08:29 +00:00
}
SwUndoInsTbl::~SwUndoInsTbl()
{
delete pDDEFldType;
delete pColWidth;
delete pRedlData;
delete pAutoFmt;
}
void SwUndoInsTbl::Undo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
SwTableNode* pTblNd = aIdx.GetNode().GetTableNode();
ASSERT( pTblNd, "kein TabellenNode" );
pTblNd->DelFrms();
if( IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ))
rDoc.DeleteRedline( *pTblNd, true, USHRT_MAX );
2000-09-18 23:08:29 +00:00
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,
FALSE, &pItem ) )
pNextNd->SetAttr( *pItem );
if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
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 );
rUndoIter.pAktPam->DeleteMark();
rUndoIter.pAktPam->GetPoint()->nNode = aIdx;
rUndoIter.pAktPam->GetPoint()->nContent.Assign(
rUndoIter.pAktPam->GetCntntNode(), 0 );
}
void SwUndoInsTbl::Redo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwPosition aPos( *rUndoIter.pAktPam->GetPoint() );
aPos.nNode = nSttNode;
const SwTable* pTbl = rDoc.InsertTable( aInsTblOpts, aPos, nRows, nCols,
(SwHoriOrient)nAdjust,
pAutoFmt, pColWidth );
2000-09-18 23:08:29 +00:00
((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() )) ||
( !( IDocumentRedlineAccess::REDLINE_IGNORE & GetRedlineMode() ) &&
2000-09-18 23:08:29 +00:00
rDoc.GetRedlineTbl().Count() ))
{
SwPaM aPam( *pTblNode->EndOfSectionNode(), *pTblNode, 1 );
SwCntntNode* pCNd = aPam.GetCntntNode( FALSE );
if( pCNd )
aPam.GetMark()->nContent.Assign( pCNd, 0 );
if( pRedlData && IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) )
2000-09-18 23:08:29 +00:00
{
IDocumentRedlineAccess::RedlineMode_t eOld = rDoc.GetRedlineMode();
rDoc.SetRedlineMode_intern((IDocumentRedlineAccess::RedlineMode_t)(eOld & ~IDocumentRedlineAccess::REDLINE_IGNORE));
2000-09-18 23:08:29 +00:00
rDoc.AppendRedline( new SwRedline( *pRedlData, aPam ), true);
2000-09-18 23:08:29 +00:00
rDoc.SetRedlineMode_intern( eOld );
}
else
rDoc.SplitRedline( aPam );
}
}
void SwUndoInsTbl::Repeat( SwUndoIter& rUndoIter )
{
rUndoIter.GetDoc().InsertTable( aInsTblOpts, *rUndoIter.pAktPam->GetPoint(),
nRows, nCols, (SwHoriOrient)nAdjust,
pAutoFmt, pColWidth );
2000-09-18 23:08:29 +00:00
}
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;
}
2000-09-18 23:08:29 +00:00
// -----------------------------------------------------
SwTblToTxtSave::SwTblToTxtSave( SwDoc& rDoc, ULONG nNd, ULONG nEndIdx, xub_StrLen nCnt )
: nNode( nNd ), nEndNd( nEndIdx), nCntnt( nCnt ), pHstry( 0 )
2000-09-18 23:08:29 +00:00
{
// Attributierung des gejointen Node merken.
if( USHRT_MAX != nCnt )
++nNd;
SwTxtNode* pNd = rDoc.GetNodes()[ nNd ]->GetTxtNode();
if( pNd )
{
pHstry = new SwHistory;
pHstry->Add( pNd->GetTxtColl(), nNd, ND_TEXTNODE );
if( pNd->GetpSwpHints() )
pHstry->CopyAttr( pNd->GetpSwpHints(), nNd, 0,
pNd->GetTxt().Len(), FALSE );
if( pNd->HasSwAttrSet() )
2000-09-18 23:08:29 +00:00
pHstry->CopyFmtAttr( *pNd->GetpSwAttrSet(), nNd );
if( !pHstry->Count() )
delete pHstry, pHstry = 0;
}
}
SwUndoTblToTxt::SwUndoTblToTxt( const SwTable& rTbl, sal_Unicode cCh )
: SwUndo( UNDO_TABLETOTEXT ),
nSttNd( 0 ), nEndNd( 0 ), cTrenner( cCh ), pDDEFldType( 0 ),
nAdjust( rTbl.GetFrmFmt()->GetHoriOrient().GetHoriOrient() ),
sTblNm( rTbl.GetFrmFmt()->GetName() ),
nHdlnRpt( rTbl.GetRowsToRepeat() ),
2000-09-18 23:08:29 +00:00
pHistory( 0 )
{
pTblSave = new _SaveTable( rTbl );
pBoxSaves = new SwTblToTxtSaves( (BYTE)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();
ULONG nTblStt = pTblNd->GetIndex(), nTblEnd = pTblNd->EndOfSectionIndex();
const SwSpzFrmFmts& rFrmFmtTbl = *pTblNd->GetDoc()->GetSpzFrmFmts();
for( USHORT n = 0; n < rFrmFmtTbl.Count(); ++n )
{
const SwPosition* pAPos;
const SwFrmFmt* pFmt = rFrmFmtTbl[ n ];
const SwFmtAnchor* pAnchor = &pFmt->GetAnchor();
if( 0 != ( pAPos = pAnchor->GetCntntAnchor()) &&
( FLY_AUTO_CNTNT == pAnchor->GetAnchorId() ||
FLY_AT_CNTNT == 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::Undo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwPaM* pPam = rUndoIter.pAktPam;
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();
SwNode2Layout* pNode2Layout = NULL;
// dann sammel mal alle Uppers ein
SwNode2Layout aNode2Layout( aFrmIdx.GetNode() );
// erzeuge die TabelleNode Structur
SwTableNode* pTblNd = rDoc.GetNodes().UndoTableToText( nSttNd, nEndNd,
*pBoxSaves );
SwTableFmt* pTableFmt = rDoc.MakeTblFrmFmt( sTblNm, rDoc.GetDfltFrmFmt() );
pTableFmt->Add( &pTblNd->GetTable() ); // das Frame-Format setzen
pTblNd->GetTable().SetRowsToRepeat( nHdlnRpt );
2000-09-18 23:08:29 +00:00
// erzeuge die alte Tabellen Struktur
pTblSave->CreateNew( pTblNd->GetTable() );
if( pDDEFldType )
{
SwDDEFieldType* pNewType = (SwDDEFieldType*)rDoc.InsertFldType(
*pDDEFldType);
SwDDETable* pDDETbl = new SwDDETable( pTblNd->GetTable(), pNewType );
2002-10-15 13:22:13 +00:00
pTblNd->SetNewTable( pDDETbl, FALSE ); // setze die DDE-Tabelle
2000-09-18 23:08:29 +00:00
delete pDDEFldType, pDDEFldType = 0;
}
if( bCheckNumFmt )
{
SwTableSortBoxes& rBxs = pTblNd->GetTable().GetTabSortBoxes();
for( USHORT nBoxes = rBxs.Count(); nBoxes; )
rDoc.ChkBoxNumFmt( *rBxs[ --nBoxes ], FALSE );
}
if( pHistory )
{
USHORT 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( ULONG nSttNd, 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;
2002-10-15 13:22:13 +00:00
/* Set pTblNd as start of section for all nodes in [nSttNd, nEndNd].
Delete all Frames attached to the nodes in that range. */
2000-09-18 23:08:29 +00:00
SwNode* pNd;
{
ULONG n, nTmpEnd = aEndIdx.GetIndex();
for( n = pTblNd->GetIndex() + 1; n < nTmpEnd; ++n )
2002-10-15 13:22:13 +00:00
{
2000-09-18 23:08:29 +00:00
if( ( pNd = (*this)[ n ] )->IsCntntNode() )
((SwCntntNode*)pNd)->DelFrms();
2002-10-15 13:22:13 +00:00
pNd->pStartOfSection = pTblNd;
}
2000-09-18 23:08:29 +00:00
}
// 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( USHORT n = rSavedData.Count(); n; )
{
SwTblToTxtSave* pSave = rSavedData[ --n ];
aSttIdx = pSave->nNode;
SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode();
2002-10-15 13:22:13 +00:00
2000-09-18 23:08:29 +00:00
if( USHRT_MAX != pSave->nCntnt )
{
// an der ContentPosition splitten, das vorherige Zeichen
// loeschen (ist der Trenner!)
ASSERT( pTxtNd, "Wo ist der TextNode geblieben?" );
SwIndex aCntPos( pTxtNd, pSave->nCntnt - 1 );
pTxtNd->Erase( aCntPos, 1 );
SwCntntNode* pNewNd = pTxtNd->SplitNode(
SwPosition( aSttIdx, aCntPos ));
if( aBkmkArr.Count() )
_RestoreCntntIdx( aBkmkArr, *pNewNd, pSave->nCntnt,
pSave->nCntnt + 1 );
}
else
{
if( aBkmkArr.Count() )
aBkmkArr.Remove( 0, aBkmkArr.Count() );
if( pTxtNd )
_SaveCntntIdx( GetDoc(), aSttIdx.GetIndex(),
pTxtNd->GetTxt().Len(), aBkmkArr );
}
if( pTxtNd )
{
if( pTxtNd->HasSwAttrSet() )
2000-09-18 23:08:29 +00:00
pTxtNd->ResetAllAttr();
if( pTxtNd->GetpSwpHints() )
pTxtNd->ClearSwpHintsArr( false );
2000-09-18 23:08:29 +00:00
}
if( pSave->pHstry )
{
USHORT nTmpEnd = pSave->pHstry->GetTmpEnd();
pSave->pHstry->TmpRollback( GetDoc(), 0 );
pSave->pHstry->SetTmpEnd( nTmpEnd );
}
aEndIdx = pSave->nEndNd;
2000-09-18 23:08:29 +00:00
SwStartNode* pSttNd = new SwStartNode( aSttIdx, ND_STARTNODE,
SwTableBoxStartNode );
pSttNd->pStartOfSection = pTblNd;
new SwEndNode( aEndIdx, *pSttNd );
for( 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::Redo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwPaM* pPam = rUndoIter.pAktPam;
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();
ASSERT( 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 )) )
{
2000-09-18 23:08:29 +00:00
ASSERT( FALSE, "wo steht denn nun der TextNode" );
}
2000-09-18 23:08:29 +00:00
pPam->GetPoint()->nNode = aSaveIdx;
pPam->GetPoint()->nContent.Assign( pCNd, 0 );
pPam->SetMark(); // alle Indizies abmelden
pPam->DeleteMark();
}
void SwUndoTblToTxt::Repeat( SwUndoIter& rUndoIter )
{
SwTableNode* pTblNd = rUndoIter.pAktPam->GetNode()->FindTableNode();
if( pTblNd )
{
// bewege den Cursor aus der Tabelle
SwPaM* pPam = rUndoIter.pAktPam;
pPam->GetPoint()->nNode = *pTblNd->EndOfSectionNode();
pPam->Move( fnMoveForward, fnGoCntnt );
pPam->SetMark();
pPam->DeleteMark();
rUndoIter.GetDoc().TableToText( pTblNd, cTrenner );
}
}
void SwUndoTblToTxt::SetRange( const SwNodeRange& rRg )
{
nSttNd = rRg.aStart.GetIndex();
nEndNd = rRg.aEnd.GetIndex();
}
void SwUndoTblToTxt::AddBoxPos( SwDoc& rDoc, ULONG nNdIdx, ULONG nEndIdx, xub_StrLen nCntntIdx )
2000-09-18 23:08:29 +00:00
{
SwTblToTxtSave* pNew = new SwTblToTxtSave( rDoc, nNdIdx, nEndIdx, nCntntIdx );
2000-09-18 23:08:29 +00:00
pBoxSaves->Insert( pNew, pBoxSaves->Count() );
}
// -----------------------------------------------------
SwUndoTxtToTbl::SwUndoTxtToTbl( const SwPaM& rRg,
const SwInsertTableOptions& rInsTblOpts,
sal_Unicode cCh, USHORT nAdj,
const SwTableAutoFmt* pAFmt )
: SwUndo( UNDO_TEXTTOTABLE ), SwUndRng( rRg ), aInsTblOpts( rInsTblOpts ),
pAutoFmt( 0 ), nAdjust( nAdj ), cTrenner( cCh ), pDelBoxes( 0 ),
pHistory( 0 )
2000-09-18 23:08:29 +00:00
{
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::Undo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
2000-09-18 23:08:29 +00:00
ULONG nTblNd = nSttNode;
if( nSttCntnt )
++nTblNd; // Node wurde vorher gesplittet
SwNodeIndex aIdx( rDoc.GetNodes(), nTblNd );
SwTableNode* pTNd = rDoc.GetNodes()[ aIdx ]->GetTableNode();
ASSERT( 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( USHORT n = pDelBoxes->Count(); n; )
{
SwTableBox* pBox = rTbl.GetTblBox( (*pDelBoxes)[ --n ] );
if( pBox )
::_DeleteBox( rTbl, pBox, 0, FALSE, FALSE );
else
ASSERT( !this, "Wo ist die Box geblieben?" );
}
}
SwNodeIndex aEndIdx( *pTNd->EndOfSectionNode() );
rDoc.TableToText( pTNd, 0x0b == cTrenner ? 0x09 : cTrenner );
// am Start wieder zusammenfuegen ?
SwPosition* pPos = rUndoIter.pAktPam->GetPoint();
if( nSttCntnt )
{
pPos->nNode = nTblNd;
pPos->nContent.Assign( rDoc.GetNodes()[ pPos->nNode ]->GetCntntNode(), 0 );
if( rUndoIter.pAktPam->Move( fnMoveBackward, fnGoCntnt))
{
SwNodeIndex& rIdx = rUndoIter.pAktPam->GetPoint()->nNode;
// dann die Crsr/etc. nochmal relativ verschieben
RemoveIdxRel( rIdx.GetIndex()+1, *pPos );
rIdx.GetNode().GetCntntNode()->JoinNext();
}
}
// am Ende wieder zusammenfuegen ?
if( bSplitEnd )
{
SwNodeIndex& rIdx = pPos->nNode;
rIdx = nEndNode;
SwTxtNode* pTxtNd = rIdx.GetNode().GetTxtNode();
if( pTxtNd && pTxtNd->CanJoinNext() )
{
rUndoIter.pAktPam->GetMark()->nContent.Assign( 0, 0 );
rUndoIter.pAktPam->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();
}
}
SetPaM( rUndoIter ); // manipulierten Bereich selectieren
}
void SwUndoTxtToTbl::Redo( SwUndoIter& rUndoIter )
{
SetPaM( rUndoIter );
RemoveIdxFromRange( *rUndoIter.pAktPam, FALSE );
SetPaM( rUndoIter );
const SwTable* pTable = rUndoIter.GetDoc().TextToTable(
aInsTblOpts, *rUndoIter.pAktPam, cTrenner,
(SwHoriOrient)nAdjust, pAutoFmt );
2000-09-18 23:08:29 +00:00
((SwFrmFmt*)pTable->GetFrmFmt())->SetName( sTblNm );
}
void SwUndoTxtToTbl::Repeat( SwUndoIter& rUndoIter )
{
// keine TABLE IN TABLE
2000-09-18 23:08:29 +00:00
if( !rUndoIter.pAktPam->GetNode()->FindTableNode() )
rUndoIter.GetDoc().TextToTable( aInsTblOpts, *rUndoIter.pAktPam,
cTrenner, (SwHoriOrient)nAdjust,
pAutoFmt );
2000-09-18 23:08:29 +00:00
}
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, USHORT nOldHdl,
USHORT nNewHdl )
2000-09-18 23:08:29 +00:00
: SwUndo( UNDO_TABLEHEADLINE ),
nOldHeadline( nOldHdl ),
nNewHeadline( nNewHdl )
2000-09-18 23:08:29 +00:00
{
ASSERT( rTbl.GetTabSortBoxes().Count(), "Tabelle ohne Inhalt" );
const SwStartNode *pSttNd = rTbl.GetTabSortBoxes()[ 0 ]->GetSttNd();
ASSERT( pSttNd, "Box ohne Inhalt" );
nTblNd = pSttNd->StartOfSectionIndex();
}
void SwUndoTblHeadline::Undo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
ASSERT( pTNd, "keinen Tabellen-Node gefunden" );
rDoc.SetRowsToRepeat( pTNd->GetTable(), nOldHeadline );
2000-09-18 23:08:29 +00:00
}
void SwUndoTblHeadline::Redo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode();
ASSERT( pTNd, "keinen Tabellen-Node gefunden" );
rDoc.SetRowsToRepeat( pTNd->GetTable(), nNewHeadline );
2000-09-18 23:08:29 +00:00
}
void SwUndoTblHeadline::Repeat( SwUndoIter& rUndoIter )
{
SwTableNode* pTblNd = rUndoIter.pAktPam->GetNode()->FindTableNode();
if( pTblNd )
rUndoIter.GetDoc().SetRowsToRepeat( pTblNd->GetTable(), nNewHeadline );
2000-09-18 23:08:29 +00:00
}
/* */
_SaveTable::_SaveTable( const SwTable& rTbl, USHORT nLnCnt, BOOL bSaveFml )
: aTblSet( *rTbl.GetFrmFmt()->GetAttrSet().GetPool(), aTableSetRange ),
nLineCount( nLnCnt ), pSwTable( &rTbl ), bSaveFormula( bSaveFml )
{
bModifyBox = FALSE;
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( USHORT n = 1; n < nLnCnt; ++n )
pLn = new _SaveLine( pLn, *rTbl.GetTabLines()[ n ], *this );
aFrmFmts.Remove( 0, aFrmFmts.Count() );
pSwTable = 0;
}
_SaveTable::~_SaveTable()
{
delete pLine;
}
USHORT _SaveTable::AddFmt( SwFrmFmt* pFmt )
{
USHORT nRet = aFrmFmts.GetPos( pFmt );
if( USHRT_MAX == nRet )
{
// Kopie vom ItemSet anlegen
SfxItemSet* pSet = new SfxItemSet( *pFmt->GetAttrSet().GetPool(),
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, 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, BOOL bMdfyBox )
{
USHORT n;
2000-09-18 23:08:29 +00:00
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( FALSE );
}
// zur Sicherheit alle Tableframes invalidieren
SwClientIter aIter( *pFmt );
for( SwClient* pLast = aIter.First( TYPE( SwFrm ) ); pLast; pLast = aIter.Next() )
if( ((SwTabFrm*)pLast)->GetTable() == &rTbl )
{
((SwTabFrm*)pLast)->InvalidateAll();
((SwTabFrm*)pLast)->SetCompletePaint();
}
// FrmFmts mit Defaults (0) fuellen
pFmt = 0;
for( n = aSets.Count(); n; --n )
2000-09-18 23:08:29 +00:00
aFrmFmts.Insert( pFmt, aFrmFmts.Count() );
USHORT nLnCnt = nLineCount;
if( USHRT_MAX == nLnCnt )
nLnCnt = rTbl.GetTabLines().Count();
_SaveLine* pLn = pLine;
for( n = 0; n < nLnCnt; ++n, pLn = pLn->pNext )
{
if( !pLn )
{
ASSERT( !this, "Anzahl der Lines hat sich veraendert" );
break;
}
pLn->RestoreAttr( *rTbl.GetTabLines()[ n ], *this );
}
aFrmFmts.Remove( 0, aFrmFmts.Count() );
bModifyBox = FALSE;
}
void _SaveTable::SaveCntntAttrs( SwDoc* pDoc )
{
pLine->SaveCntntAttrs( pDoc );
}
void _SaveTable::CreateNew( SwTable& rTbl, BOOL bCreateFrms,
BOOL bRestoreChart )
{
USHORT n;
2000-09-18 23:08:29 +00:00
_FndBox aTmpBox( 0, 0 );
if( bRestoreChart )
aTmpBox.SaveChartData( rTbl );
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( 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 )
2000-09-18 23:08:29 +00:00
aFrmFmts.Insert( pFmt, aFrmFmts.Count() );
pLine->CreateNew( rTbl, aParent, *this );
aFrmFmts.Remove( 0, aFrmFmts.Count() );
// die neuen Lines eintragen, die alten loeschen
USHORT nOldLines = nLineCount;
if( USHRT_MAX == nLineCount )
nOldLines = rTbl.GetTabLines().Count();
for( n = 0; n < aParent.GetTabLines().Count(); ++n )
{
SwTableLine* pLn = aParent.GetTabLines()[ n ];
pLn->SetUpper( 0 );
if( n < nOldLines )
{
SwTableLine* pOld = rTbl.GetTabLines()[ n ];
rTbl.GetTabLines().C40_REPLACE( SwTableLine, pLn, n );
delete pOld;
}
else
rTbl.GetTabLines().C40_INSERT( SwTableLine, pLn, n );
}
if( n < nOldLines )
rTbl.GetTabLines().DeleteAndDestroy( n, nOldLines - n );
aParent.GetTabLines().Remove( 0, n );
if( bCreateFrms )
aTmpBox.MakeFrms( rTbl );
if( bRestoreChart )
aTmpBox.RestoreChartData( rTbl );
}
void _SaveTable::NewFrmFmt( const SwClient* pLnBx, BOOL bIsLine,
USHORT nFmtPos, SwFrmFmt* pOldFmt )
{
SwDoc* pDoc = pOldFmt->GetDoc();
SwFrmFmt* pFmt = aFrmFmts[ nFmtPos ];
if( !pFmt )
{
if( bIsLine )
pFmt = pDoc->MakeTableLineFmt();
else
pFmt = pDoc->MakeTableBoxFmt();
pFmt->SetAttr( *aSets[ nFmtPos ] );
aFrmFmts.Replace( pFmt, nFmtPos );
}
//Erstmal die Frms ummelden.
SwClientIter aIter( *pOldFmt );
for( SwClient* pLast = aIter.First( TYPE( SwFrm ) ); pLast; pLast = aIter.Next() )
{
2000-09-18 23:08:29 +00:00
if( bIsLine ? pLnBx == ((SwRowFrm*)pLast)->GetTabLine()
: pLnBx == ((SwCellFrm*)pLast)->GetTabBox() )
{
pFmt->Add( pLast );
((SwFrm*)pLast)->InvalidateAll();
((SwFrm*)pLast)->ReinitializeFrmSizeAttrFlags();
if ( !bIsLine )
{
((SwCellFrm*)pLast)->SetDerivedVert( FALSE );
((SwCellFrm*)pLast)->CheckDirChange();
}
2000-09-18 23:08:29 +00:00
}
}
2000-09-18 23:08:29 +00:00
//Jetzt noch mich selbst ummelden.
pFmt->Add( (SwClient*)pLnBx );
if( bModifyBox && !bIsLine )
{
const SfxPoolItem& rOld = pOldFmt->GetAttr( RES_BOXATR_FORMAT ),
& rNew = pFmt->GetAttr( RES_BOXATR_FORMAT );
if( rOld != rNew )
pFmt->Modify( (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() );
pBox = new _SaveBox( 0, *rLine.GetTabBoxes()[ 0 ], rSTbl );
_SaveBox* pBx = pBox;
for( USHORT 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, TRUE, nItemSet, rLine.GetFrmFmt() );
_SaveBox* pBx = pBox;
for( USHORT n = 0; n < rLine.GetTabBoxes().Count(); ++n, pBx = pBx->pNext )
{
if( !pBx )
{
ASSERT( !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->SetAttr( *rSTbl.aSets[ nItemSet ] );
rSTbl.aFrmFmts.Replace( pFmt, nItemSet );
}
SwTableLine* pNew = new SwTableLine( pFmt, 1, &rParent );
2000-09-18 23:08:29 +00:00
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.
ASSERT(pNew, "Table line just created set to NULL in C40_INSERT");
if (pNew)
{
pBox->CreateNew( rTbl, *pNew, rSTbl );
}
2000-09-18 23:08:29 +00:00
if( pNext )
pNext->CreateNew( rTbl, rParent, rSTbl );
}
_SaveBox::_SaveBox( _SaveBox* pPrev, const SwTableBox& rBox, _SaveTable& rSTbl )
: nSttNode( ULONG_MAX ), pNext( 0 )
{
Ptrs.pLine = 0;
if( pPrev )
pPrev->pNext = this;
nItemSet = rSTbl.AddFmt( rBox.GetFrmFmt() );
if( rBox.GetSttNd() )
nSttNode = rBox.GetSttIdx();
else
{
Ptrs.pLine = new _SaveLine( 0, *rBox.GetTabLines()[ 0 ], rSTbl );
_SaveLine* pLn = Ptrs.pLine;
for( USHORT 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( &rBox, FALSE, nItemSet, rBox.GetFrmFmt() );
if( ULONG_MAX == nSttNode ) // keine EndBox
{
if( !rBox.GetTabLines().Count() )
{
ASSERT( !this, "Anzahl der Lines hat sich veraendert" );
}
else
{
_SaveLine* pLn = Ptrs.pLine;
for( USHORT n = 0; n < rBox.GetTabLines().Count(); ++n, pLn = pLn->pNext )
{
if( !pLn )
{
ASSERT( !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();
USHORT nSet = 0;
ULONG nEnd = rBox.GetSttNd()->EndOfSectionIndex();
for( ULONG n = nSttNode + 1; n < nEnd; ++n )
{
SwCntntNode* pCNd = rNds[ n ]->GetCntntNode();
if( pCNd )
{
SfxItemSet* pSet = (*Ptrs.pCntntAttrs)[ nSet++ ];
if( pSet )
{
USHORT *pRstAttr = aSave_BoxCntntSet;
while( *pRstAttr )
{
pCNd->ResetAttr( *pRstAttr, *(pRstAttr+1) );
pRstAttr += 2;
}
pCNd->SetAttr( *pSet );
}
else
pCNd->ResetAllAttr();
}
}
}
}
else
{
ASSERT( !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
{
USHORT nSet = 0;
ULONG nEnd = pDoc->GetNodes()[ nSttNode ]->EndOfSectionIndex();
Ptrs.pCntntAttrs = new SfxItemSets( (BYTE)(nEnd - nSttNode - 1 ), 5 );
for( ULONG n = nSttNode + 1; n < nEnd; ++n )
{
SwCntntNode* pCNd = pDoc->GetNodes()[ n ]->GetCntntNode();
if( pCNd )
{
SfxItemSet* pSet = 0;
if( pCNd->HasSwAttrSet() )
2000-09-18 23:08:29 +00:00
{
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->SetAttr( *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 );
ASSERT( pBox, "Wo ist meine TabellenBox geblieben?" );
SwFrmFmt* pOld = pBox->GetFrmFmt();
pFmt->Add( pBox );
if( !pOld->GetDepends() )
delete pOld;
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, BOOL bClearTabCols )
: SwUndo( UNDO_TABLE_ATTR ),
nSttNode( rTblNd.GetIndex() )
{
bClearTabCol = bClearTabCols;
pSaveTbl = new _SaveTable( rTblNd.GetTable() );
}
SwUndoAttrTbl::~SwUndoAttrTbl()
{
delete pSaveTbl;
}
void SwUndoAttrTbl::Undo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
ASSERT( pTblNd, "kein TabellenNode" );
if (pTblNd)
{
_SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() );
pSaveTbl->RestoreAttr( pTblNd->GetTable() );
delete pSaveTbl;
pSaveTbl = pOrig;
}
2000-09-18 23:08:29 +00:00
if( bClearTabCol )
ClearFEShellTabCols();
}
void SwUndoAttrTbl::Redo( SwUndoIter& rUndoIter )
{
Undo( rUndoIter );
}
/* */
// UndoObject fuer AutoFormat an der Tabelle
SwUndoTblAutoFmt::SwUndoTblAutoFmt( const SwTableNode& rTblNd,
const SwTableAutoFmt& rAFmt )
: SwUndo( UNDO_TABLE_AUTOFMT ),
nSttNode( rTblNd.GetIndex() ),
bSaveCntntAttr( FALSE ), pUndos( 0 )
{
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 = TRUE;
}
}
SwUndoTblAutoFmt::~SwUndoTblAutoFmt()
{
delete pUndos;
delete pSaveTbl;
}
void SwUndoTblAutoFmt::SaveBoxCntnt( const SwTableBox& rBox )
{
SwUndoTblNumFmt* p = new SwUndoTblNumFmt( rBox );
if( !pUndos )
pUndos = new SwUndos( 8, 8 );
pUndos->Insert( p, pUndos->Count() );
}
void SwUndoTblAutoFmt::UndoRedo( BOOL bUndo, SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
ASSERT( 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( pUndos && bUndo )
for( USHORT n = pUndos->Count(); n; )
pUndos->GetObject( --n )->Undo( rUndoIter );
pSaveTbl->RestoreAttr( pTblNd->GetTable(), !bUndo );
delete pSaveTbl;
pSaveTbl = pOrig;
}
void SwUndoTblAutoFmt::Undo( SwUndoIter& rUndoIter )
{
UndoRedo( TRUE, rUndoIter );
}
void SwUndoTblAutoFmt::Redo( SwUndoIter& rUndoIter )
{
UndoRedo( FALSE, rUndoIter );
}
/* */
SwUndoTblNdsChg::SwUndoTblNdsChg( USHORT nAction,
const SwSelBoxes& rBoxes,
const SwTableNode& rTblNd,
2002-11-15 08:56:50 +00:00
USHORT nCnt, BOOL bFlg, BOOL bSmHght )
2000-09-18 23:08:29 +00:00
: SwUndo( nAction ),
nSttNode( rTblNd.GetIndex() ),
aBoxes( rBoxes.Count() < 255 ? (BYTE)rBoxes.Count() : 255, 10 ),
nCount( nCnt ), nRelDiff( 0 ), nAbsDiff( 0 ),
nSetColType( USHRT_MAX ), nCurrBox( 0 ),
2002-11-15 08:56:50 +00:00
bFlag( bFlg ),
bSameHeight( bSmHght )
2000-09-18 23:08:29 +00:00
{
Ptrs.pNewSttNds = 0;
const SwTable& rTbl = rTblNd.GetTable();
pSaveTbl = new _SaveTable( rTbl );
// und die Selektion merken
for( USHORT n = 0; n < rBoxes.Count(); ++n )
aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
}
SwUndoTblNdsChg::SwUndoTblNdsChg( USHORT nAction,
const SwSelBoxes& rBoxes,
const SwTableNode& rTblNd )
: SwUndo( nAction ),
nSttNode( rTblNd.GetIndex() ),
aBoxes( rBoxes.Count() < 255 ? (BYTE)rBoxes.Count() : 255, 10 ),
nCount( 0 ), nRelDiff( 0 ), nAbsDiff( 0 ),
nSetColType( USHRT_MAX ), nCurrBox( 0 ),
bFlag( FALSE )
{
Ptrs.pNewSttNds = 0;
const SwTable& rTbl = rTblNd.GetTable();
pSaveTbl = new _SaveTable( rTbl );
// und die Selektion merken
for( USHORT n = 0; n < rBoxes.Count(); ++n )
aBoxes.Insert( rBoxes[n]->GetSttIdx(), n );
}
SwUndoTblNdsChg::~SwUndoTblNdsChg()
{
delete pSaveTbl;
if( IsDelBox() )
2000-09-18 23:08:29 +00:00
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();
USHORT n;
USHORT i;
2000-09-18 23:08:29 +00:00
ASSERT( ! IsDelBox(), "falsche Action" );
2000-09-18 23:08:29 +00:00
Ptrs.pNewSttNds = new SvULongs( (BYTE)(rTblBoxes.Count() - rOld.Count()), 5 );
for( n = 0, i = 0; n < rOld.Count(); ++i )
2000-09-18 23:08:29 +00:00
{
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();
USHORT 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;
}
2000-09-18 23:08:29 +00:00
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();
ASSERT( ! IsDelBox(), "falsche Action" );
2000-09-18 23:08:29 +00:00
Ptrs.pNewSttNds = new SvULongs( (BYTE)(rTblBoxes.Count() - rOld.Count()), 5 );
ASSERT( rOld.Count() + nCount * rBoxes.Count() == rTblBoxes.Count(),
"unexpected boxes" );
ASSERT( rOld.Count() <= rTblBoxes.Count(), "more unexpected boxes" );
for( USHORT n = 0, i = 0; i < rTblBoxes.Count(); ++i )
2000-09-18 23:08:29 +00:00
{
if( ( n < rOld.Count() ) &&
( rOld[ n ] == rTblBoxes[ i ] ) )
{
// box already known? Then nothing to be done.
2000-09-18 23:08:29 +00:00
++n;
}
2000-09-18 23:08:29 +00:00
else
{
// new box found: insert (obey sort order)
2000-09-18 23:08:29 +00:00
USHORT 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();
USHORT nLineDiff = lcl_FindParentLines(rTbl,*pBox).C40_GETPOS(SwTableLine,pBoxLine);
USHORT nLineNo = 0;
for( USHORT j = 0; j < rBoxes.Count(); ++j )
{
pCheckBox = rBoxes[j];
if( pCheckBox->GetUpper()->GetUpper() == pBox->GetUpper()->GetUpper() )
{
const SwTableLine* pCheckLine = pCheckBox->GetUpper();
USHORT 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 -= nLineNo;
ASSERT( pSourceBox, "Splitted source box not found!" );
// find out how many nodes the source box used to have
// (to help determine bNodesMoved flag below)
2000-09-18 23:08:29 +00:00
USHORT nNdsPos = 0;
while( rBoxes[ nNdsPos ] != pSourceBox )
2000-09-18 23:08:29 +00:00
++nNdsPos;
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.
BOOL bNodesMoved =
( nNodes != ( pSourceBox->GetSttNd()->EndOfSectionIndex() -
pSourceBox->GetSttIdx() ) )
&& ( nNodes - 1 > nLineDiff );
aMvBoxes.Insert( bNodesMoved, nInsPos );
}
2000-09-18 23:08:29 +00:00
}
}
void SwUndoTblNdsChg::SaveSection( SwStartNode* pSttNd )
{
ASSERT( IsDelBox(), "falsche Action" );
2000-09-18 23:08:29 +00:00
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::Undo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwNodeIndex aIdx( rDoc.GetNodes(), nSttNode );
SwTableNode* pTblNd = rDoc.GetNodes()[ aIdx ]->GetTableNode();
ASSERT( pTblNd, "kein TabellenNode" );
SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
aMsgHnt.eFlags = TBL_BOXPTR;
rDoc.UpdateTblFlds( &aMsgHnt );
_FndBox aTmpBox( 0, 0 );
aTmpBox.SaveChartData( pTblNd->GetTable() );
if( IsDelBox() )
2000-09-18 23:08:29 +00:00
{
// 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( USHORT 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.Count() )
{
// 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( USHORT n = aTmp.Count(); n; )
{
// Box aus der Tabellen-Struktur entfernen
ULONG nIdx = aTmp[ --n ];
SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
ASSERT( pBox, "Wo ist meine TabellenBox geblieben?" );
SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, 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 );
2000-09-18 23:08:29 +00:00
// alle StartNode Indizies anpassen
USHORT i = n;
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, FALSE );
}
else
{
delete pBox;
rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
}
}
}
else
// die Nodes loeschen (von Hinten!!)
for( USHORT n = Ptrs.pNewSttNds->Count(); n; )
{
// Box aus der Tabellen-Struktur entfernen
ULONG nIdx = (*Ptrs.pNewSttNds)[ --n ];
SwTableBox* pBox = pTblNd->GetTable().GetTblBox( nIdx );
ASSERT( pBox, "Wo ist meine TabellenBox geblieben?" );
SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) );
delete pBox;
rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
}
pSaveTbl->CreateNew( pTblNd->GetTable(), TRUE, FALSE );
aTmpBox.RestoreChartData( pTblNd->GetTable() );
if( IsDelBox() )
2000-09-18 23:08:29 +00:00
nSttNode = pTblNd->GetIndex();
ClearFEShellTabCols();
}
void SwUndoTblNdsChg::Redo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwTableNode* pTblNd = rDoc.GetNodes()[ nSttNode ]->GetTableNode();
ASSERT( pTblNd, "kein TabellenNode" );
SwSelBoxes aSelBoxes;
for( USHORT 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:
2002-11-15 08:56:50 +00:00
rDoc.SplitTbl( aSelBoxes, bFlag, nCount, bSameHeight );
2000-09-18 23:08:29 +00:00
break;
case UNDO_TABLE_DELBOX:
case UNDO_ROW_DELETE:
case UNDO_COL_DELETE:
2000-09-18 23:08:29 +00:00
if( USHRT_MAX == nSetColType )
{
SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
aMsgHnt.eFlags = TBL_BOXPTR;
rDoc.UpdateTblFlds( &aMsgHnt );
pTblNd->GetTable().DeleteSel( &rDoc, aSelBoxes, this, 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 );
rDoc.DoUndo( TRUE ); // wir brauchen die SaveSections!
SwUndoTblNdsChg* pUndo = 0;
switch( nSetColType & 0xff )
{
case WH_COL_LEFT:
case WH_COL_RIGHT:
case WH_CELL_LEFT:
case WH_CELL_RIGHT:
rTbl.SetColWidth( *pBox, nSetColType, nAbsDiff,
nRelDiff, (SwUndo**)&pUndo );
break;
case WH_ROW_TOP:
case WH_ROW_BOTTOM:
case WH_CELL_TOP:
case 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.DoUndo( FALSE );
rTbl.SetTblChgMode( eOldMode );
}
nSttNode = pTblNd->GetIndex();
break;
}
ClearFEShellTabCols();
}
/* */
SwUndoTblMerge::SwUndoTblMerge( const SwPaM& rTblSel )
: SwUndo( UNDO_TABLE_MERGE ), SwUndRng( rTblSel ), pHistory( 0 )
{
const SwTableNode* pTblNd = rTblSel.GetNode()->FindTableNode();
ASSERT( 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::Undo( SwUndoIter& rUndoIter )
{
SwDoc& rDoc = rUndoIter.GetDoc();
SwNodeIndex aIdx( rDoc.GetNodes(), nTblNode );
SwTableNode* pTblNd = rDoc.GetNodes()[ aIdx ]->GetTableNode();
ASSERT( pTblNd, "kein TabellenNode" );
SwTableFmlUpdate aMsgHnt( &pTblNd->GetTable() );
aMsgHnt.eFlags = TBL_BOXPTR;
rDoc.UpdateTblFlds( &aMsgHnt );
_FndBox aTmpBox( 0, 0 );
aTmpBox.SaveChartData( pTblNd->GetTable() );
// 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();
DUMPDOC( &rDoc, "d:\\tmp\\tab_a.db" )
CHECKTABLE(pTblNd->GetTable())
SwSelBoxes aSelBoxes;
SwTxtFmtColl* pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_STANDARD );
USHORT n;
for( n = 0; n < aBoxes.Count(); ++n )
2000-09-18 23:08:29 +00:00
{
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 );
}
DUMPDOC( &rDoc, "d:\\tmp\\tab_b.db" )
CHECKTABLE(pTblNd->GetTable())
// 2. die eingefuegten Boxen loeschen
// die Nodes loeschen (von Hinten!!)
for( n = aNewSttNds.Count(); n; )
{
// Box aus der Tabellen-Struktur entfernen
ULONG nIdx = aNewSttNds[ --n ];
if( !nIdx && n )
{
nIdx = aNewSttNds[ --n ];
pBox = pTblNd->GetTable().GetTblBox( nIdx );
ASSERT( pBox, "Wo ist meine TabellenBox geblieben?" );
rDoc.GetNodes().MakeTxtNode( SwNodeIndex(
*pBox->GetSttNd()->EndOfSectionNode() ), pColl );
// das war der Trenner, -> die verschobenen herstellen
for( USHORT i = pMoves->Count(); i; )
{
SwTxtNode* pTxtNd;
USHORT nDelPos;
SwUndoMove* pUndo = (*pMoves)[ --i ];
if( !pUndo->IsMoveRange() )
{
pTxtNd = rDoc.GetNodes()[ pUndo->GetDestSttNode() ]->GetTxtNode();
nDelPos = pUndo->GetDestSttCntnt() - 1;
}
pUndo->Undo( rUndoIter );
if( pUndo->IsMoveRange() )
{
// den ueberfluessigen Node loeschen
aIdx = pUndo->GetEndNode();
rDoc.GetNodes().Delete( aIdx, 1 );
}
else if( pTxtNd )
{
// evt. noch ueberflussige Attribute loeschen
SwIndex aIdx( pTxtNd, nDelPos );
if( pTxtNd->GetpSwpHints() && pTxtNd->GetpSwpHints()->Count() )
pTxtNd->RstAttr( aIdx, pTxtNd->GetTxt().Len() -
nDelPos + 1 );
// das Trennzeichen loeschen
pTxtNd->Erase( aIdx, 1 );
}
// delete pUndo;
DUMPDOC( &rDoc, String( "d:\\tmp\\tab_") + String( aNewSttNds.Count() - i ) +
String(".db") )
}
// pMoves->Remove( 0, pMoves->Count() );
nIdx = pBox->GetSttIdx();
}
else
pBox = pTblNd->GetTable().GetTblBox( nIdx );
SwTableBoxes* pTBoxes = &pBox->GetUpper()->GetTabBoxes();
pTBoxes->Remove( pTBoxes->C40_GETPOS( SwTableBox, pBox ) );
// Indizies aus dem Bereich loeschen
{
SwNodeIndex aIdx( *pBox->GetSttNd() );
rDoc.CorrAbs( SwNodeIndex( aIdx, 1 ),
SwNodeIndex( *aIdx.GetNode().EndOfSectionNode() ),
SwPosition( aIdx, SwIndex( 0, 0 )), TRUE );
}
delete pBox;
rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
}
DUMPDOC( &rDoc, "d:\\tmp\\tab_z.db" )
CHECKTABLE(pTblNd->GetTable())
pSaveTbl->CreateNew( pTblNd->GetTable(), TRUE, FALSE );
aTmpBox.RestoreChartData( pTblNd->GetTable() );
if( pHistory )
{
pHistory->TmpRollback( &rDoc, 0 );
pHistory->SetTmpEnd( pHistory->Count() );
}
// nTblNode = pTblNd->GetIndex();
SwPaM* pPam = rUndoIter.pAktPam;
pPam->DeleteMark();
pPam->GetPoint()->nNode = nSttNode;
pPam->GetPoint()->nContent.Assign( pPam->GetCntntNode(), nSttCntnt );
pPam->SetMark();
pPam->DeleteMark();
CHECKTABLE(pTblNd->GetTable())
ClearFEShellTabCols();
}
void SwUndoTblMerge::Redo( SwUndoIter& rUndoIter )
{
SwPaM* pPam = rUndoIter.pAktPam;
SwDoc& rDoc = *pPam->GetDoc();
SetPaM( *pPam );
rDoc.MergeTbl( *pPam );
}
void SwUndoTblMerge::MoveBoxCntnt( SwPaM& rPam, SwPosition& rPos,
const _SaveFlyArr& rArr )
{
SwDoc* pDoc = rPam.GetDoc();
SwNodeIndex aIdx( rPam.GetPoint()->nNode );
SwNode* pNd = &aIdx.GetNode();
// alle verschobenen Flys in der History vom Move-Object merken.
// Hier erstmal zwischenspeichern, damit die alten NodeIdx richtig sind
SwHistory aHst;
for( USHORT n = 0; n < rArr.Count(); ++n )
aHst.Add( *rArr[ n ].pFrmFmt );
SwUndoMove* pUndoMove;
if( pDoc->Move( rPam, rPos, IDocumentContentOperations::DOC_MOVEREDLINES ) )
2000-09-18 23:08:29 +00:00
pUndoMove = (SwUndoMove*)pDoc->RemoveLastUndo( UNDO_MOVE );
else
{
// wir muessen das Undo Object haben!
pUndoMove = new SwUndoMove( rPam, rPos );
SwPaM aPam( rPos );
pUndoMove->SetDestRange( aPam, rPos, FALSE, FALSE );
}
ASSERT( pUndoMove, "falsches Undo-Object" );
// alle verschobenen Flys in der History vom Move-Object merken
if( aHst.Count() )
pUndoMove->AddTblMrgFlyHstry( aHst );
pMoves->Insert( pUndoMove, pMoves->Count() );
const SwStartNode* pBoxNd = pNd->FindTableBoxStartNode();
ULONG nDelNds = pBoxNd->EndOfSectionIndex() - pBoxNd->GetIndex();
if( 2 < nDelNds )
{
// es darf nur ein Textnode in der Box verbleiben!
rPam.DeleteMark();
// Indizies aus dem Bereich loeschen
{
pDoc->CorrAbs( SwNodeIndex( *pBoxNd ),
SwNodeIndex( *pBoxNd->EndOfSectionNode() ),
SwPosition( aIdx,
SwIndex( pNd->GetCntntNode(), 0 )), TRUE );
}
// rPam.GetBound1().nNode = rPam.GetBound2().nNode = aIdx;
if( aIdx.GetIndex() - 1 != pBoxNd->GetIndex() )
{
SwNodeIndex aTmp( *pBoxNd, 1 );
pDoc->GetNodes().Delete( aTmp, aIdx.GetIndex() - aTmp.GetIndex() );
}
aIdx++;
pDoc->GetNodes().Delete( aIdx, pBoxNd->EndOfSectionIndex() - aIdx.GetIndex() );
}
}
void SwUndoTblMerge::MoveBoxCntnt( SwDoc* pDoc, SwNodeRange& rRg, SwNodeIndex& rPos )
{
SwNodeIndex aTmp( rRg.aStart, -1 ), aTmp2( rPos, -1 );
SwUndoMove* pUndo = new SwUndoMove( pDoc, rRg, rPos );
pDoc->Move( rRg, rPos, IDocumentContentOperations::DOC_MOVEDEFAULT );
2000-09-18 23:08:29 +00:00
aTmp++;
aTmp2++;
pUndo->SetDestRange( aTmp2, rPos, aTmp );
pMoves->Insert( pUndo, pMoves->Count() );
}
void SwUndoTblMerge::SetSelBoxes( const SwSelBoxes& rBoxes )
{
// die Selektion merken
for( USHORT n = 0; n < rBoxes.Count(); ++n )
InsertSort( aBoxes, rBoxes[n]->GetSttIdx() );
// als Trennung fuers einfuegen neuer Boxen nach dem Verschieben!
aNewSttNds.Insert( (ULONG)0, aNewSttNds.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() )
2000-09-18 23:08:29 +00:00
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 = FALSE;
nNode = rBox.GetSttIdx();
ULONG nNdPos = rBox.IsValidNumTxtNd( 0 == pNewSet );
if( ULONG_MAX != nNdPos )
{
SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
SwTxtNode* pTNd = pDoc->GetNodes()[ nNdPos ]->GetTxtNode();
pHistory = new SwHistory;
SwRegHistory aRHst( *rBox.GetSttNd(), pHistory );
// immer alle TextAttribute sichern; ist fuers Undo mit voll-
// staendiger Attributierung am besten, wegen den evt.
// Ueberlappenden Bereichen von An/Aus.
pHistory->CopyAttr( pTNd->GetpSwpHints(), nNdPos, 0,
pTNd->GetTxt().Len(), TRUE );
if( pTNd->HasSwAttrSet() )
2000-09-18 23:08:29 +00:00
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,
FALSE, &pItem ))
{
bNewFmt = TRUE;
nNewFmtIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
}
if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_FORMULA,
FALSE, &pItem ))
{
bNewFml = TRUE;
aNewFml = ((SwTblBoxFormula*)pItem)->GetFormula();
}
if( SFX_ITEM_SET == pNewSet->GetItemState( RES_BOXATR_VALUE,
FALSE, &pItem ))
{
bNewValue = TRUE;
fNewNum = ((SwTblBoxValue*)pItem)->GetValue();
}
}
}
// wird die History ueberhaupt benoetigt ??
if( pHistory && !pHistory->Count() )
DELETEZ( pHistory );
}
SwUndoTblNumFmt::~SwUndoTblNumFmt()
{
delete pHistory;
delete pBoxSet;
}
void SwUndoTblNumFmt::Undo( SwUndoIter& rIter )
{
// konnte die Box veraendert werden ?
if( !pBoxSet )
return ;
SwDoc& rDoc = rIter.GetDoc();
SwStartNode* pSttNd = rDoc.GetNodes()[ nNode ]->
FindSttNodeByType( SwTableBoxStartNode );
ASSERT( pSttNd, "ohne StartNode kein TabellenBox" );
SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
pSttNd->GetIndex() );
ASSERT( pBox, "keine TabellenBox gefunden" );
SwTableBoxFmt* pFmt = rDoc.MakeTableBoxFmt();
pFmt->SetAttr( *pBoxSet );
pBox->ChgFrmFmt( pFmt );
SwTxtNode* pTxtNd = rDoc.GetNodes()[ nNode + 1 ]->GetTxtNode();
// wenn mehr als ein Node geloescht wurde, dann wurden auch
// alle "Node"-Attribute gespeichert
if( pTxtNd->HasSwAttrSet() )
2000-09-18 23:08:29 +00:00
pTxtNd->ResetAllAttr();
if( pTxtNd->GetpSwpHints() )
pTxtNd->ClearSwpHintsArr( true );
2000-09-18 23:08:29 +00:00
// 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 );
pTxtNd->Erase( aIdx );
if( aStr.Len() )
pTxtNd->Insert( aStr, aIdx, INS_NOHINTEXPAND );
}
2000-09-18 23:08:29 +00:00
if( pHistory )
{
USHORT nTmpEnd = pHistory->GetTmpEnd();
pHistory->TmpRollback( &rDoc, 0 );
pHistory->SetTmpEnd( nTmpEnd );
}
SwPaM* pPam = rIter.pAktPam;
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;
IDocumentRedlineAccess::RedlineMode_t meOldRedlineMode;
public:
RedlineModeInternGuard(
SwDoc& rDoc, /// change mode of this document
IDocumentRedlineAccess::RedlineMode_t eNewRedlineMode, /// new redline mode
IDocumentRedlineAccess::RedlineMode_t eRedlineModeMask = (IDocumentRedlineAccess::RedlineMode_t)(IDocumentRedlineAccess::REDLINE_ON | IDocumentRedlineAccess::REDLINE_IGNORE /*change only bits set in this mask*/));
~RedlineModeInternGuard();
};
RedlineModeInternGuard::RedlineModeInternGuard(
SwDoc& rDoc,
IDocumentRedlineAccess::RedlineMode_t eNewRedlineMode,
IDocumentRedlineAccess::RedlineMode_t eRedlineModeMask )
: mrDoc( rDoc ),
meOldRedlineMode( rDoc.GetRedlineMode() )
{
mrDoc.SetRedlineMode_intern((IDocumentRedlineAccess::RedlineMode_t)( ( meOldRedlineMode & ~eRedlineModeMask ) |
( eNewRedlineMode & eRedlineModeMask ) ));
}
RedlineModeInternGuard::~RedlineModeInternGuard()
{
mrDoc.SetRedlineMode_intern( meOldRedlineMode );
}
2000-09-18 23:08:29 +00:00
void SwUndoTblNumFmt::Redo( SwUndoIter& rIter )
{
// konnte die Box veraendert werden ?
if( !pBoxSet )
return ;
SwDoc& rDoc = rIter.GetDoc();
SwPaM* pPam = rIter.pAktPam;
pPam->DeleteMark();
pPam->GetPoint()->nNode = nNode;
SwNode* pNd = rDoc.GetNodes()[ pPam->GetPoint()->nNode ];
SwStartNode* pSttNd = pNd->FindSttNodeByType( SwTableBoxStartNode );
ASSERT( pSttNd, "ohne StartNode kein TabellenBox" );
SwTableBox* pBox = pSttNd->FindTableNode()->GetTable().GetTblBox(
pSttNd->GetIndex() );
ASSERT( 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->ResetAttr( RES_BOXATR_FORMULA );
if( bNewFmt )
aBoxSet.Put( SwTblBoxNumFormat( nNewFmtIdx ));
else
pBoxFmt->ResetAttr( RES_BOXATR_FORMAT );
if( bNewValue )
aBoxSet.Put( SwTblBoxValue( fNewNum ));
else
pBoxFmt->ResetAttr( 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, IDocumentRedlineAccess::REDLINE_NONE, IDocumentRedlineAccess::REDLINE_IGNORE );
2000-09-18 23:08:29 +00:00
pBoxFmt->SetAttr( 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->ResetAttr( 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, IDocumentRedlineAccess::REDLINE_NONE, IDocumentRedlineAccess::REDLINE_IGNORE );
2000-09-18 23:08:29 +00:00
pBoxFmt->SetAttr( 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->SetAttr( *GetDfltAttr( RES_BOXATR_FORMAT ));
pBoxFmt->ResetAttr( 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 )
2000-09-18 23:08:29 +00:00
{
}
_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::Undo( SwUndoIter& rIter )
{
SwDoc& rDoc = rIter.GetDoc();
_DEBUG_REDLINE( &rDoc )
2000-09-18 23:08:29 +00:00
SwTableNode* pTblNd = 0;
for( USHORT n = pArr->Count(); n; )
{
_UndoTblCpyTbl_Entry* pEntry = (*pArr)[ --n ];
ULONG nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
2000-09-18 23:08:29 +00:00
if( !pTblNd )
pTblNd = pSNd->FindTableNode();
SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
SwTxtNode* pNd = 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 *pUnDel = (SwUndoDelete*)pEntry->pUndo;
if( UNDO_REDLINE == pUnDel->GetId() )
{
// 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, pUnDel->NodeDiff()-1 );
SwTxtNode *pTxt = aTmpIdx.GetNode().GetTxtNode();
if( pTxt )
{
aPam.GetPoint()->nNode = *pTxt;
aPam.GetPoint()->nContent.Assign( pTxt, pUnDel->ContentStart() );
}
else
*aPam.GetPoint() = SwPosition( aTmpIdx );
}
else if( pUnDel->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 );
2000-09-18 23:08:29 +00:00
if( pEntry->pUndo )
{
pEntry->pUndo->Undo( rIter );
delete pEntry->pUndo;
}
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, TRUE );
2000-09-18 23:08:29 +00:00
}
else
{
pUndo = new SwUndoDelete( aPam, true );
if( pEntry->pUndo )
{
pEntry->pUndo->Undo( rIter );
delete pEntry->pUndo;
}
}
2000-09-18 23:08:29 +00:00
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->ResetAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
pBoxFmt->ResetAttr( RES_VERT_ORIENT );
}
if( pEntry->pBoxNumAttr )
{
rBox.ClaimFrmFmt()->SetAttr( *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->Undo( rIter );
_DEBUG_REDLINE( &rDoc )
2000-09-18 23:08:29 +00:00
}
void SwUndoTblCpyTbl::Redo( SwUndoIter& rIter )
{
SwDoc& rDoc = rIter.GetDoc();
_DEBUG_REDLINE( &rDoc )
2000-09-18 23:08:29 +00:00
if( pInsRowUndo )
pInsRowUndo->Redo( rIter );
SwTableNode* pTblNd = 0;
for( USHORT n = 0; n < pArr->Count(); ++n )
{
_UndoTblCpyTbl_Entry* pEntry = (*pArr)[ n ];
ULONG nSttPos = pEntry->nBoxIdx + pEntry->nOffset;
SwStartNode* pSNd = rDoc.GetNodes()[ nSttPos ]->StartOfSectionNode();
2000-09-18 23:08:29 +00:00
if( !pTblNd )
pTblNd = pSNd->FindTableNode();
SwTableBox& rBox = *pTblNd->GetTable().GetTblBox( nSttPos );
SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
// b62341295: Redline for copying tables - Start.
2000-09-18 23:08:29 +00:00
SwTxtNode* pNd = rDoc.GetNodes().MakeTxtNode( aInsIdx,
(SwTxtFmtColl*)rDoc.GetDfltTxtFmtColl());
SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode());
SwUndo* pUndo = IDocumentRedlineAccess::IsRedlineOn( GetRedlineMode() ) ? 0 : new SwUndoDelete( aPam, TRUE );
2000-09-18 23:08:29 +00:00
if( pEntry->pUndo )
{
pEntry->pUndo->Undo( rIter );
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 )
pUndo = PrepareRedline( &rDoc, rBox, *rIter.pAktPam->GetPoint(),
pEntry->bJoin, true );
else
{
SwPosition aTmpPos( aInsIdx );
pUndo = PrepareRedline( &rDoc, rBox, aTmpPos, pEntry->bJoin, true );
}
}
2000-09-18 23:08:29 +00:00
delete pEntry->pUndo;
}
pEntry->pUndo = pUndo;
// b62341295: Redline for copying tables - End.
2000-09-18 23:08:29 +00:00
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->ResetAttr( RES_BOXATR_FORMAT, RES_BOXATR_VALUE );
pBoxFmt->ResetAttr( RES_VERT_ORIENT );
}
if( pEntry->pBoxNumAttr )
{
rBox.ClaimFrmFmt()->SetAttr( *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 )
2000-09-18 23:08:29 +00:00
}
void SwUndoTblCpyTbl::AddBoxBefore( const SwTableBox& rBox, 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 )
2000-09-18 23:08:29 +00:00
if( bDelCntnt )
{
SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 );
SwTxtNode* pNd = pDoc->GetNodes().MakeTxtNode( aInsIdx,
(SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl());
SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() );
if( !pDoc->IsRedlineOn() )
pEntry->pUndo = new SwUndoDelete( aPam, TRUE );
2000-09-18 23:08:29 +00:00
}
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 )
2000-09-18 23:08:29 +00:00
}
void SwUndoTblCpyTbl::AddBoxAfter( const SwTableBox& rBox, const SwNodeIndex& rIdx, BOOL bDelCntnt )
2000-09-18 23:08:29 +00:00
{
_UndoTblCpyTbl_Entry* pEntry = (*pArr)[ pArr->Count() - 1 ];
// wurde der Inhalt geloescht, so loesche jetzt auch noch den temp.
// erzeugten Node
if( bDelCntnt )
2000-09-18 23:08:29 +00:00
{
SwDoc* pDoc = rBox.GetFrmFmt()->GetDoc();
_DEBUG_REDLINE( pDoc )
if( pDoc->IsRedlineOn() )
{
SwPosition aTmpPos( rIdx );
pEntry->pUndo = PrepareRedline( pDoc, rBox, aTmpPos, pEntry->bJoin, false );
}
2000-09-18 23:08:29 +00:00
SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 );
rBox.GetFrmFmt()->GetDoc()->GetNodes().Delete( aDelIdx, 1 );
_DEBUG_REDLINE( pDoc )
2000-09-18 23:08:29 +00:00
}
2000-09-18 23:08:29 +00:00
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
IDocumentRedlineAccess::RedlineMode_t eOld = pDoc->GetRedlineMode();
pDoc->SetRedlineMode_intern((IDocumentRedlineAccess::RedlineMode_t)( ( eOld | IDocumentRedlineAccess::REDLINE_DONTCOMBINE_REDLINES ) &
~IDocumentRedlineAccess::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( IDocumentRedlineAccess::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 = SwNodeIndex( *rBox.GetSttNd()->EndOfSectionNode() );
SwPaM aTmpPam( aDeleteStart, aCellEnd );
pUndo = new SwUndoDelete( aTmpPam, 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( IDocumentRedlineAccess::REDLINE_INSERT, aTmpPam ), true );
}
pDoc->SetRedlineMode_intern( eOld );
return pUndo;
}
2000-09-18 23:08:29 +00:00
BOOL SwUndoTblCpyTbl::InsertRow( SwTable& rTbl, const SwSelBoxes& rBoxes,
USHORT nCnt )
{
SwTableNode* pTblNd = (SwTableNode*)rTbl.GetTabSortBoxes()[0]->
GetSttNd()->FindTableNode();
SwTableSortBoxes aTmpLst( 0, 5 );
pInsRowUndo = new SwUndoTblNdsChg( UNDO_TABLE_INSROW, rBoxes, *pTblNd,
nCnt, TRUE );
aTmpLst.Insert( &rTbl.GetTabSortBoxes(), 0, rTbl.GetTabSortBoxes().Count() );
BOOL bRet = rTbl.InsertRow( rTbl.GetFrmFmt()->GetDoc(), rBoxes, nCnt, TRUE );
if( bRet )
pInsRowUndo->SaveNewBoxes( *pTblNd, aTmpLst );
else
delete pInsRowUndo, pInsRowUndo = 0;
return bRet;
}
BOOL SwUndoTblCpyTbl::IsEmpty() const
{
return !pInsRowUndo && !pArr->Count();
}
/* */
SwUndoCpyTbl::SwUndoCpyTbl()
: SwUndo( UNDO_CPYTBL ), pDel( 0 ), nTblNode( 0 )
{
}
SwUndoCpyTbl::~SwUndoCpyTbl()
{
delete pDel;
}
void SwUndoCpyTbl::Undo( SwUndoIter& rIter )
{
SwDoc& rDoc = rIter.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,
FALSE, &pItem ) )
pNextNd->SetAttr( *pItem );
if( SFX_ITEM_SET == pTableFmt->GetItemState( RES_BREAK,
FALSE, &pItem ) )
pNextNd->SetAttr( *pItem );
}
SwPaM aPam( *pTNd, *pTNd->EndOfSectionNode(), 0 , 1 );
pDel = new SwUndoDelete( aPam, TRUE );
}
void SwUndoCpyTbl::Redo( SwUndoIter& rIter )
{
pDel->Undo( rIter );
delete pDel, pDel = 0;
}
/* */
SwUndoSplitTbl::SwUndoSplitTbl( const SwTableNode& rTblNd, USHORT eMode,
BOOL bNewSize )
: SwUndo( UNDO_SPLIT_TABLE ), pSavTbl( 0 ),
nTblNode( rTblNd.GetIndex() ), nMode( eMode ), nOffset( 0 ), nFmlEnd( 0 ),
pHistory( 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, FALSE );
break;
}
}
SwUndoSplitTbl::~SwUndoSplitTbl()
{
delete pSavTbl;
delete pHistory;
}
void SwUndoSplitTbl::Undo( SwUndoIter& rIter )
{
SwPaM* pPam = rIter.pAktPam;
SwDoc* pDoc = pPam->GetDoc();
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, 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, TRUE );
rTbl.DeleteSel( pDoc, aSelBoxes, 0, FALSE, FALSE );
}
break;
}
pDoc->GetNodes().MergeTable( rIdx );
if( pHistory )
{
pHistory->TmpRollback( pDoc, 0 );
pHistory->SetTmpEnd( pHistory->Count() );
}
ClearFEShellTabCols();
}
void SwUndoSplitTbl::Redo( SwUndoIter& rIter )
{
SwPaM* pPam = rIter.pAktPam;
SwDoc* pDoc = pPam->GetDoc();
pPam->DeleteMark();
pPam->GetPoint()->nNode = nTblNode;
pDoc->SplitTable( *pPam->GetPoint(), nMode, bCalcNewSize );
ClearFEShellTabCols();
}
void SwUndoSplitTbl::Repeat( SwUndoIter& rIter )
{
SwPaM* pPam = rIter.pAktPam;
SwDoc* pDoc = pPam->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,
BOOL bWithPrv, USHORT nMd )
: SwUndo( UNDO_MERGE_TABLE ), pSavTbl( 0 ),
pHistory( 0 ), bWithPrev( bWithPrv ), nMode( nMd )
{
// 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::Undo( SwUndoIter& rIter )
{
SwPaM* pPam = rIter.pAktPam;
SwDoc* pDoc = pPam->GetDoc();
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 );
aFndBox.SaveChartData( *pTbl );
SwTableNode* pNew = pDoc->GetNodes().SplitTable( rIdx, TRUE, FALSE );
//Layout updaten
aFndBox.MakeFrms( *pTbl );
aFndBox.RestoreChartData( *pTbl );
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, 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();
}
void SwUndoMergeTbl::Redo( SwUndoIter& rIter )
{
SwPaM* pPam = rIter.pAktPam;
SwDoc* pDoc = pPam->GetDoc();
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::Repeat( SwUndoIter& rIter )
{
SwPaM* pPam = rIter.pAktPam;
SwDoc* pDoc = pPam->GetDoc();
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, USHORT nIdx, USHORT* pInsPos )
{
register USHORT nO = rArr.Count(), nM, nU = 0;
if( nO > 0 )
{
nO--;
while( nU <= nO )
{
nM = nU + ( nO - nU ) / 2;
if( *(rArr.GetData() + nM) == nIdx )
{
ASSERT( FALSE, "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;
}
void InsertSort( SvULongs& rArr, ULONG nIdx, USHORT* pInsPos )
{
register USHORT nO = rArr.Count(), nM, nU = 0;
if( nO > 0 )
{
nO--;
while( nU <= nO )
{
nM = nU + ( nO - nU ) / 2;
if( *(rArr.GetData() + nM) == nIdx )
{
ASSERT( FALSE, "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 defined( JP_DEBUG ) && !defined( PRODUCT )
void DumpDoc( SwDoc* pDoc, const String& rFileNm )
{
Writer* pWrt = SwIoSystem::GetWriter( "DEBUG" );
if( pWrt )
{
SvFileStream aStream( rFileNm, STREAM_STD_WRITE );
SwPaM* pPam = new SwPaM( pDoc, SwPosition( pDoc->GetNodes().EndOfContent ,
pDoc->GetNodes().EndOfContent ));
pPam->Move( fnMoveBackward, fnGoDoc );
pPam->SetMark();
pPam->Move( fnMoveForward, fnGoDoc );
pWrt->Write( pPam, *pDoc, aStream, rFileNm.GetStr() );
delete pPam;
}
}
void CheckTable( const SwTable& rTbl )
{
const SwNodes& rNds = rTbl.GetFrmFmt()->GetDoc()->GetNodes();
const SwTableSortBoxes& rSrtArr = pTblNd->GetTable().GetTabSortBoxes();
for( USHORT n = 0; n < rSrtArr.Count(); ++n )
{
const SwTableBox* pBox = rSrtArr[ n ];
const SwNode* pNd = pBox->GetSttNd();
ASSERT( rNds[ *pBox->GetSttIdx() ] == pNd, "Box mit falchem StartNode" );
}
}
#endif