/************************************************************************* * * $RCSfile: untbl.cxx,v $ * * $Revision: 1.3 $ * * last change: $Author: hbrinkm $ $Date: 2002-10-15 14:22:13 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses * * - GNU Lesser General Public License Version 2.1 * - Sun Industry Standards Source License Version 1.1 * * Sun Microsystems Inc., October, 2000 * * GNU Lesser General Public License Version 2.1 * ============================================= * Copyright 2000 by Sun Microsystems, Inc. * 901 San Antonio Road, Palo Alto, CA 94303, USA * * 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. * * 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. * * 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 * * * Sun Industry Standards Source License Version 1.1 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.1 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://www.openoffice.org/license.html. * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2000 by Sun Microsystems, Inc. * * All Rights Reserved. * * Contributor(s): _______________________________________ * * ************************************************************************/ #ifdef PRECOMPILED #include "core_pch.hxx" #endif #pragma hdrstop #define ITEMID_BOXINFO SID_ATTR_BORDER_INNER #ifndef _HINTIDS_HXX #include #endif #ifndef _SVX_BRKITEM_HXX //autogen #include #endif #ifndef _FMTORNT_HXX //autogen #include #endif #ifndef _FMTPDSC_HXX //autogen #include #endif #ifndef _DOC_HXX #include #endif #ifndef _DOCARY_HXX #include #endif #ifndef _NDARR_HXX #include #endif #ifndef _NDTXT_HXX #include #endif #ifndef _SWTABLE_HXX #include #endif #ifndef _PAM_HXX #include #endif #ifndef _CNTFRM_HXX #include #endif #ifndef _TBLSEL_HXX #include #endif #ifndef _HINTS_HXX #include #endif #ifndef _SWUNDO_HXX #include // fuer die UndoIds #endif #ifndef _UNDOBJ_HXX #include #endif #ifndef _ROLBCK_HXX #include #endif #ifndef _DDEFLD_HXX #include #endif #ifndef _TABCOL_HXX #include #endif #ifndef _TABFRM_HXX #include #endif #ifndef _ROWFRM_HXX #include #endif #ifndef _CELLFRM_HXX #include #endif #ifndef _SWCACHE_HXX #include #endif #ifndef _TBLAFMT_HXX #include #endif #ifndef _POOLFMT_HXX #include #endif #ifndef _MVSAVE_HXX #include #endif #ifndef _CELLATR_HXX #include #endif #ifndef _SWTBLFMT_HXX #include #endif #ifndef _SWDDETBL_HXX #include #endif #ifndef _REDLINE_HXX #include #endif #ifndef _NODE2LAY_HXX #include #endif #ifndef _TBLRWCL_HXX #include #endif #ifndef _FMTANCHR_HXX #include #endif 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; SwUndoDelete* pUndo; _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 struct SwTblToTxtSave { ULONG nNode; xub_StrLen nCntnt; SwHistory* pHstry; SwTblToTxtSave( SwDoc& rDoc, ULONG nNd, xub_StrLen nCntnt = STRING_MAXLEN ); ~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, USHORT nInsert, const SwTableAutoFmt* pTAFmt, const SvUShorts* pColArr ) : SwUndo( UNDO_INSTABLE ), nSttNode( rPos.nNode.GetIndex() ), nRows( nRw ), nCols( nCl ), nAdjust( nAdj ), pDDEFldType( 0 ), nInsTblFlags( nInsert ), pColWidth( 0 ), pRedlData( 0 ), pAutoFmt( 0 ) { 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( REDLINE_INSERT, rDoc.GetRedlineAuthor() ); SetRedlineMode( rDoc.GetRedlineMode() ); } } 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( IsRedlineOn( GetRedlineMode() )) rDoc.DeleteRedline( *pTblNd ); 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( aPos, nRows, nCols, (SwHoriOrient)nAdjust, nInsTblFlags, 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 && IsRedlineOn( GetRedlineMode() )) || ( !( REDLINE_IGNORE & GetRedlineMode() ) && rDoc.GetRedlineTbl().Count() )) { SwPaM aPam( *pTblNode->EndOfSectionNode(), *pTblNode, 1 ); SwCntntNode* pCNd = aPam.GetCntntNode( FALSE ); if( pCNd ) aPam.GetMark()->nContent.Assign( pCNd, 0 ); if( pRedlData && IsRedlineOn( GetRedlineMode() ) ) { SwRedlineMode eOld = rDoc.GetRedlineMode(); rDoc.SetRedlineMode_intern( eOld & ~REDLINE_IGNORE ); rDoc.AppendRedline( new SwRedline( *pRedlData, aPam )); rDoc.SetRedlineMode_intern( eOld ); } else rDoc.SplitRedline( aPam ); } } void SwUndoInsTbl::Repeat( SwUndoIter& rUndoIter ) { // keine Tabelle in Tabelle if( !rUndoIter.pAktPam->GetNode()->FindTableNode() ) rUndoIter.GetDoc().InsertTable( *rUndoIter.pAktPam->GetPoint(), nRows, nCols, (SwHoriOrient)nAdjust, nInsTblFlags, pAutoFmt, pColWidth ); } // ----------------------------------------------------- SwTblToTxtSave::SwTblToTxtSave( SwDoc& rDoc, ULONG nNd, xub_StrLen nCnt ) : nNode( nNd ), nCntnt( nCnt ), pHstry( 0 ) { // 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->GetpSwAttrSet() ) 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() ), bHdlnRpt( rTbl.IsHeadlineRepeat() ), 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().SetHeadlineRepeat( bHdlnRpt ); // 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, FALSE ); // setze die DDE-Tabelle 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; /* Set pTblNd as start of section for all nodes in [nSttNd, nEndNd]. Delete all Frames attached to the nodes in that range. */ SwNode* pNd; { 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( USHORT n = rSavedData.Count(); n; ) { SwTblToTxtSave* pSave = rSavedData[ --n ]; aSttIdx = pSave->nNode; SwTxtNode* pTxtNd = aSttIdx.GetNode().GetTxtNode(); 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->GetpSwAttrSet() ) pTxtNd->ResetAllAttr(); if( pTxtNd->GetpSwpHints() ) pTxtNd->ClearSwpHintsArr( FALSE, FALSE ); } if( pSave->pHstry ) { USHORT nTmpEnd = pSave->pHstry->GetTmpEnd(); pSave->pHstry->TmpRollback( GetDoc(), 0 ); pSave->pHstry->SetTmpEnd( nTmpEnd ); } 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 ); aEndIdx = *pSttNd; } 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 )) ) ASSERT( FALSE, "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::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, xub_StrLen nCntntIdx ) { SwTblToTxtSave* pNew = new SwTblToTxtSave( rDoc, nNdIdx, nCntntIdx ); pBoxSaves->Insert( pNew, pBoxSaves->Count() ); } // ----------------------------------------------------- SwUndoTxtToTbl::SwUndoTxtToTbl( const SwPaM& rRg, sal_Unicode cCh, USHORT nAdj, USHORT nInsert, const SwTableAutoFmt* pAFmt ) : SwUndo( UNDO_TEXTTOTABLE ), SwUndRng( rRg ), pAutoFmt( 0 ), nAdjust( nAdj ), cTrenner( cCh ), pDelBoxes( 0 ), nInsTblFlags( nInsert ), pHistory( 0 ) { 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(); 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( *rUndoIter.pAktPam, cTrenner, (SwHoriOrient)nAdjust, nInsTblFlags, pAutoFmt ); ((SwFrmFmt*)pTable->GetFrmFmt())->SetName( sTblNm ); } void SwUndoTxtToTbl::Repeat( SwUndoIter& rUndoIter ) { // keine Tabelle in Tabelle if( !rUndoIter.pAktPam->GetNode()->FindTableNode() ) rUndoIter.GetDoc().TextToTable( *rUndoIter.pAktPam, cTrenner, (SwHoriOrient)nAdjust, nInsTblFlags, 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, BOOL bOldHdl ) : SwUndo( UNDO_TABLEHEADLINE ), bOldHeadline( bOldHdl ) { 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.SetHeadlineRepeat( pTNd->GetTable(), bOldHeadline ); } void SwUndoTblHeadline::Redo( SwUndoIter& rUndoIter ) { SwDoc& rDoc = rUndoIter.GetDoc(); SwTableNode* pTNd = rDoc.GetNodes()[ nTblNd ]->GetTableNode(); ASSERT( pTNd, "keinen Tabellen-Node gefunden" ); rDoc.SetHeadlineRepeat( pTNd->GetTable(), !bOldHeadline ); } void SwUndoTblHeadline::Repeat( SwUndoIter& rUndoIter ) { SwTableNode* pTblNd = rUndoIter.pAktPam->GetNode()->FindTableNode(); if( pTblNd ) rUndoIter.GetDoc().SetHeadlineRepeat( pTblNd->GetTable(), !bOldHeadline ); } /* */ _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 ) { 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( USHORT n = aSets.Count(); n; --n ) 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 ) { _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( USHORT 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 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() ) if( bIsLine ? pLnBx == ((SwRowFrm*)pLast)->GetTabLine() : pLnBx == ((SwCellFrm*)pLast)->GetTabBox() ) { pFmt->Add( pLast ); ((SwFrm*)pLast)->InvalidateAll(); ((SwFrm*)pLast)->ReinitializeFrmSizeAttrFlags(); } //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 ); rParent.GetTabLines().C40_INSERT( SwTableLine, pNew, rParent.GetTabLines().Count() ); pBox->CreateNew( rTbl, *pNew, rSTbl ); 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->GetpSwAttrSet() ) { 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" ); _SaveTable* pOrig = new _SaveTable( pTblNd->GetTable() ); pSaveTbl->RestoreAttr( pTblNd->GetTable() ); delete pSaveTbl; pSaveTbl = pOrig; 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, USHORT nCnt, BOOL bFlg ) : 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 ), bFlag( bFlg ) { 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( UNDO_TABLE_DELBOX == GetId() ) 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(); ASSERT( UNDO_TABLE_DELBOX != GetId(), "falsche Action" ); Ptrs.pNewSttNds = new SvULongs( (BYTE)(rTblBoxes.Count() - rOld.Count()), 5 ); for( USHORT 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() ); } 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( UNDO_TABLE_DELBOX != GetId(), "falsche Action" ); Ptrs.pNewSttNds = new SvULongs( (BYTE)(rTblBoxes.Count() - rOld.Count()), 5 ); for( USHORT n = 0, i = 0; n < rOld.Count(); ++i ) { if( rOld[ n ] == rTblBoxes[ i ] ) ++n; else { // neue Box: sortiert einfuegen!! USHORT nInsPos; const SwTableBox* pBox = rTblBoxes[ i ]; InsertSort( *Ptrs.pNewSttNds, pBox->GetSttIdx(), &nInsPos ); // feststellen, an welcher Position die Line in der Box steht const SwTableLine* pLn = pBox->GetUpper(); USHORT nLinePos = pLn->GetUpper()->GetTabLines().GetPos( pLn ); // 1. Box der 1. Line besorgen, ist die selektierte Box! pBox = pBox->GetUpper()->GetUpper()->GetTabLines()[ 0 ] ->GetTabBoxes()[0]; // stelle fest, wieviele Nodes die Box hatte und ob // die aktuelle davon einen bekommen hat USHORT nNdsPos = 0; while( rBoxes[ nNdsPos ] != pBox ) ++nNdsPos; ULONG nNodes = rNodeCnts[ nNdsPos ]; // wurden Nodes verschoben und hat die akt. Box davon einen // bekommen. Wenn ja, setze das Flag -> beim Undo darf der Inhalt // dann nicht geloscht sondern muss verschoben werden! BOOL bFlag = nNodes != pBox->GetSttNd()->EndOfSectionIndex() - pBox->GetSttIdx() && nNodes - 1 > nLinePos; aMvBoxes.Insert( bFlag, nInsPos ); } } for( ; i < rTblBoxes.Count(); ++i ) { // neue Box: sortiert einfuegen!! USHORT nInsPos; const SwTableBox* pBox = rTblBoxes[ i ]; InsertSort( *Ptrs.pNewSttNds, pBox->GetSttIdx(), &nInsPos ); // feststellen, an welcher Position die Line in der Box steht const SwTableLine* pLn = pBox->GetUpper(); USHORT nLinePos = pLn->GetUpper()->GetTabLines().GetPos( pLn ); // 1. Box der 1. Line besorgen, ist die selektierte Box! pBox = pBox->GetUpper()->GetUpper()->GetTabLines()[ 0 ] ->GetTabBoxes()[0]; // stelle fest, wieviele Nodes die Box hatte und ob // die aktuelle davon einen bekommen hat USHORT nNdsPos = 0; while( rBoxes[ nNdsPos ] != pBox ) ++nNdsPos; ULONG nNodes = rNodeCnts[ nNdsPos ]; // wurden Nodes verschoben und hat die akt. Box davon einen // bekommen. Wenn ja, setze das Flag -> beim Undo darf der Inhalt // dann nicht geloscht sondern muss verschoben werden! BOOL bFlag = nNodes != pBox->GetSttNd()->EndOfSectionIndex() - pBox->GetSttIdx() && nNodes - 1 > nLinePos; aMvBoxes.Insert( bFlag, nInsPos ); } } void SwUndoTblNdsChg::SaveSection( SwStartNode* pSttNd ) { ASSERT( UNDO_TABLE_DELBOX == GetId(), "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::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( UNDO_TABLE_DELBOX == GetId() ) { // 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() ); SwNodeIndex aInsPos( *pBox->GetUpper()->GetUpper()->GetTabLines()[0] ->GetTabBoxes()[ 0 ]->GetSttNd(), 2 ); // 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( UNDO_TABLE_DELBOX == GetId() ) 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: rDoc.SplitTbl( aSelBoxes, bFlag, nCount ); break; case UNDO_TABLE_DELBOX: 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 ); for( USHORT 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 ); } 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 ) ) 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 ); 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->GetpSwAttrSet() ) 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->GetpSwAttrSet() ) 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->GetpSwAttrSet() ) pTxtNd->ResetAllAttr(); if( pTxtNd->GetpSwpHints() ) pTxtNd->ClearSwpHintsArr( FALSE ); SwIndex aIdx( pTxtNd, 0 ); pTxtNd->Erase( aIdx ); if( aStr.Len() ) pTxtNd->Insert( aStr, aIdx, INS_NOHINTEXPAND ); 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 ); } 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(); 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(); 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 ) { } _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(); 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 ]->FindStartNode(); 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()); SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() ); SwUndoDelete* pUndo = new SwUndoDelete( aPam, TRUE ); if( pEntry->pUndo ) { pEntry->pUndo->Undo( rIter ); delete pEntry->pUndo; } 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 ); } void SwUndoTblCpyTbl::Redo( SwUndoIter& rIter ) { SwDoc& rDoc = rIter.GetDoc(); 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 ]->FindStartNode(); 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()); SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode()); SwUndoDelete* pUndo = new SwUndoDelete( aPam, TRUE ); if( pEntry->pUndo ) { pEntry->pUndo->Undo( rIter ); delete pEntry->pUndo; } 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; } } 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(); if( bDelCntnt ) { SwNodeIndex aInsIdx( *rBox.GetSttNd(), 1 ); SwTxtNode* pNd = pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl()); SwPaM aPam( aInsIdx.GetNode(), *rBox.GetSttNd()->EndOfSectionNode() ); pEntry->pUndo = new SwUndoDelete( aPam, 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; } void SwUndoTblCpyTbl::AddBoxAfter( const SwTableBox& rBox, BOOL bDelCntnt ) { _UndoTblCpyTbl_Entry* pEntry = (*pArr)[ pArr->Count() - 1 ]; // wurde der Inhalt geloescht, so loesche jetzt auch noch den temp. // erzeugten Node if( bDelCntnt && pEntry->pUndo ) { SwNodeIndex aDelIdx( *rBox.GetSttNd(), 1 ); rBox.GetFrmFmt()->GetDoc()->GetNodes().Delete( aDelIdx, 1 ); } pEntry->nOffset = rBox.GetSttIdx() - pEntry->nBoxIdx; } 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