summaryrefslogtreecommitdiff
path: root/sw/source/core/doc/tblcpy.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/core/doc/tblcpy.cxx')
-rw-r--r--sw/source/core/doc/tblcpy.cxx1077
1 files changed, 1077 insertions, 0 deletions
diff --git a/sw/source/core/doc/tblcpy.cxx b/sw/source/core/doc/tblcpy.cxx
new file mode 100644
index 000000000000..d83bf854c645
--- /dev/null
+++ b/sw/source/core/doc/tblcpy.cxx
@@ -0,0 +1,1077 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+
+#include <hintids.hxx>
+
+#define _ZFORLIST_DECLARE_TABLE
+#include <svl/zforlist.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <IDocumentUndoRedo.hxx>
+#include <cntfrm.hxx>
+#include <pam.hxx>
+#include <swtable.hxx>
+#include <ndtxt.hxx>
+#include <fldbas.hxx>
+#include <tblsel.hxx>
+#include <tabfrm.hxx>
+#include <poolfmt.hxx>
+#include <cellatr.hxx>
+#include <mvsave.hxx>
+#include <docary.hxx>
+#include <fmtanchr.hxx>
+#include <hints.hxx>
+#include <UndoTable.hxx>
+#include <redline.hxx>
+#include <fmtfsize.hxx>
+#include <list>
+
+sal_Bool _FndCntntLine( const SwTableLine*& rpLine, void* pPara );
+sal_Bool _FndCntntBox( const SwTableBox*& rpBox, void* pPara );
+void lcl_CpyBox( const SwTable& rCpyTbl, const SwTableBox* pCpyBox,
+ SwTable& rDstTbl, SwTableBox* pDstBox,
+ sal_Bool bDelCntnt, SwUndoTblCpyTbl* pUndo );
+
+// The following type will be used by table copy functions to describe
+// the structure of tables (or parts of tables).
+// It's for new table model only.
+
+namespace
+{
+ struct BoxSpanInfo
+ {
+ SwTableBox* mpBox;
+ SwTableBox* mpCopy;
+ sal_uInt16 mnColSpan;
+ bool mbSelected;
+ };
+
+ typedef std::vector< BoxSpanInfo > BoxStructure;
+ typedef std::vector< BoxStructure > LineStructure;
+ typedef std::list< sal_uLong > ColumnStructure;
+
+ struct SubBox
+ {
+ SwTableBox *mpBox;
+ bool mbCovered;
+ };
+
+ typedef std::list< SubBox > SubLine;
+ typedef std::list< SubLine > SubTable;
+
+ class TableStructure
+ {
+ public:
+ LineStructure maLines;
+ ColumnStructure maCols;
+ sal_uInt16 mnStartCol;
+ sal_uInt16 mnAddLine;
+ void addLine( sal_uInt16 &rLine, const SwTableBoxes&, const SwSelBoxes*,
+ bool bNewModel );
+ void addBox( sal_uInt16 nLine, const SwSelBoxes*, SwTableBox *pBox,
+ sal_uLong &rnB, sal_uInt16 &rnC, ColumnStructure::iterator& rpCl,
+ BoxStructure::iterator& rpSel, bool &rbSel, bool bCover );
+ void incColSpan( sal_uInt16 nLine, sal_uInt16 nCol );
+ TableStructure( const SwTable& rTable );
+ TableStructure( const SwTable& rTable, _FndBox &rFndBox,
+ const SwSelBoxes& rSelBoxes,
+ LineStructure::size_type nMinSize );
+ LineStructure::size_type getLineCount() const
+ { return maLines.size(); }
+ void moreLines( const SwTable& rTable );
+ void assignBoxes( const TableStructure &rSource );
+ void copyBoxes( const SwTable& rSource, SwTable& rDstTbl,
+ SwUndoTblCpyTbl* pUndo ) const;
+ };
+
+ SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
+ SubTable::iterator pStartLn );
+
+ SubTable::iterator insertSubBox( SubTable& rSubTable, SwTableBox& rBox,
+ SubTable::iterator pStartLn, SubTable::iterator pEndLn )
+ {
+ if( rBox.GetTabLines().Count() )
+ {
+ SubTable::difference_type nSize = std::distance( pStartLn, pEndLn );
+ if( nSize < rBox.GetTabLines().Count() )
+ {
+ SubLine aSubLine;
+ SubLine::iterator pBox = pStartLn->begin();
+ SubLine::iterator pEnd = pStartLn->end();
+ while( pBox != pEnd )
+ {
+ SubBox aSub;
+ aSub.mpBox = pBox->mpBox;
+ aSub.mbCovered = true;
+ aSubLine.push_back( aSub );
+ ++pBox;
+ }
+ do
+ {
+ rSubTable.insert( pEndLn, aSubLine );
+ } while( ++nSize < rBox.GetTabLines().Count() );
+ }
+ for( sal_uInt16 nLine = 0; nLine < rBox.GetTabLines().Count(); ++nLine )
+ pStartLn = insertSubLine( rSubTable, *rBox.GetTabLines()[nLine],
+ pStartLn );
+ OSL_ENSURE( pStartLn == pEndLn, "Sub line confusion" );
+ }
+ else
+ {
+ SubBox aSub;
+ aSub.mpBox = &rBox;
+ aSub.mbCovered = false;
+ while( pStartLn != pEndLn )
+ {
+ pStartLn->push_back( aSub );
+ aSub.mbCovered = true;
+ ++pStartLn;
+ }
+ }
+ return pStartLn;
+ }
+
+ SubTable::iterator insertSubLine( SubTable& rSubTable, SwTableLine& rLine,
+ SubTable::iterator pStartLn )
+ {
+ SubTable::iterator pMax = pStartLn;
+ ++pMax;
+ SubTable::difference_type nMax = 1;
+ for( sal_uInt16 nBox = 0; nBox < rLine.GetTabBoxes().Count(); ++nBox )
+ {
+ SubTable::iterator pTmp = insertSubBox( rSubTable,
+ *rLine.GetTabBoxes()[nBox], pStartLn, pMax );
+ SubTable::difference_type nTmp = std::distance( pStartLn, pTmp );
+ if( nTmp > nMax )
+ {
+ pMax = pTmp;
+ nMax = nTmp;
+ }
+ }
+ return pMax;
+ }
+
+ TableStructure::TableStructure( const SwTable& rTable ) :
+ maLines( rTable.GetTabLines().Count() ), mnStartCol(USHRT_MAX),
+ mnAddLine(0)
+ {
+ maCols.push_front(0);
+ const SwTableLines &rLines = rTable.GetTabLines();
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 nLine = 0; nLine < rLines.Count(); ++nLine )
+ addLine( nCnt, rLines[nLine]->GetTabBoxes(), 0, rTable.IsNewModel() );
+ }
+
+ TableStructure::TableStructure( const SwTable& rTable,
+ _FndBox &rFndBox, const SwSelBoxes& rSelBoxes,
+ LineStructure::size_type nMinSize )
+ : mnStartCol(USHRT_MAX), mnAddLine(0)
+ {
+ if( rFndBox.GetLines().Count() )
+ {
+ bool bNoSelection = rSelBoxes.Count() < 2;
+ _FndLines &rFndLines = rFndBox.GetLines();
+ maCols.push_front(0);
+ const SwTableLine* pLine = rFndLines[0]->GetLine();
+ sal_uInt16 nStartLn = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ sal_uInt16 nEndLn = nStartLn;
+ if( rFndLines.Count() > 1 )
+ {
+ pLine = rFndLines[ rFndLines.Count()-1 ]->GetLine();
+ nEndLn = rTable.GetTabLines().C40_GETPOS( SwTableLine, pLine );
+ }
+ if( nStartLn < USHRT_MAX && nEndLn < USHRT_MAX )
+ {
+ const SwTableLines &rLines = rTable.GetTabLines();
+ if( bNoSelection &&
+ (sal_uInt16)nMinSize > nEndLn - nStartLn + 1 )
+ {
+ sal_uInt16 nNewEndLn = nStartLn + (sal_uInt16)nMinSize - 1;
+ if( nNewEndLn >= rLines.Count() )
+ {
+ mnAddLine = nNewEndLn - rLines.Count() + 1;
+ nNewEndLn = rLines.Count() - 1;
+ }
+ while( nEndLn < nNewEndLn )
+ {
+ SwTableLine *pLine2 = rLines[ ++nEndLn ];
+ SwTableBox *pTmpBox = pLine2->GetTabBoxes()[0];
+ _FndLine *pInsLine = new _FndLine( pLine2, &rFndBox );
+ _FndBox *pFndBox = new _FndBox( pTmpBox, pInsLine );
+ pInsLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, 0 );
+ rFndLines.C40_INSERT( _FndLine, pInsLine, rFndLines.Count() );
+ }
+ }
+ maLines.resize( nEndLn - nStartLn + 1 );
+ const SwSelBoxes* pSelBoxes = &rSelBoxes;
+ sal_uInt16 nCnt = 0;
+ for( sal_uInt16 nLine = nStartLn; nLine <= nEndLn; ++nLine )
+ {
+ addLine( nCnt, rLines[nLine]->GetTabBoxes(),
+ pSelBoxes, rTable.IsNewModel() );
+ if( bNoSelection )
+ pSelBoxes = 0;
+ }
+ }
+ if( bNoSelection && mnStartCol < USHRT_MAX )
+ {
+ BoxStructure::iterator pC = maLines[0].begin();
+ BoxStructure::iterator pEnd = maLines[0].end();
+ sal_uInt16 nIdx = mnStartCol;
+ mnStartCol = 0;
+ while( nIdx && pC != pEnd )
+ {
+ mnStartCol = mnStartCol + pC->mnColSpan;
+ --nIdx;
+ ++pC;
+ }
+ }
+ else
+ mnStartCol = USHRT_MAX;
+ }
+ }
+
+ void TableStructure::addLine( sal_uInt16 &rLine, const SwTableBoxes& rBoxes,
+ const SwSelBoxes* pSelBoxes, bool bNewModel )
+ {
+ bool bComplex = false;
+ if( !bNewModel )
+ for( sal_uInt16 nBox = 0; !bComplex && nBox < rBoxes.Count(); ++nBox )
+ bComplex = rBoxes[nBox]->GetTabLines().Count() > 0;
+ if( bComplex )
+ {
+ SubTable aSubTable;
+ SubLine aSubLine;
+ aSubTable.push_back( aSubLine );
+ SubTable::iterator pStartLn = aSubTable.begin();
+ SubTable::iterator pEndLn = aSubTable.end();
+ for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
+ insertSubBox( aSubTable, *rBoxes[nBox], pStartLn, pEndLn );
+ SubTable::size_type nSize = aSubTable.size();
+ if( nSize )
+ {
+ maLines.resize( maLines.size() + nSize - 1 );
+ while( pStartLn != pEndLn )
+ {
+ bool bSelected = false;
+ sal_uLong nBorder = 0;
+ sal_uInt16 nCol = 0;
+ maLines[rLine].reserve( pStartLn->size() );
+ BoxStructure::iterator pSel = maLines[rLine].end();
+ ColumnStructure::iterator pCol = maCols.begin();
+ SubLine::iterator pBox = pStartLn->begin();
+ SubLine::iterator pEnd = pStartLn->end();
+ while( pBox != pEnd )
+ {
+ addBox( rLine, pSelBoxes, pBox->mpBox, nBorder, nCol,
+ pCol, pSel, bSelected, pBox->mbCovered );
+ ++pBox;
+ }
+ ++rLine;
+ ++pStartLn;
+ }
+ }
+ }
+ else
+ {
+ bool bSelected = false;
+ sal_uLong nBorder = 0;
+ sal_uInt16 nCol = 0;
+ maLines[rLine].reserve( rBoxes.Count() );
+ ColumnStructure::iterator pCol = maCols.begin();
+ BoxStructure::iterator pSel = maLines[rLine].end();
+ for( sal_uInt16 nBox = 0; nBox < rBoxes.Count(); ++nBox )
+ addBox( rLine, pSelBoxes, rBoxes[nBox], nBorder, nCol,
+ pCol, pSel, bSelected, false );
+ ++rLine;
+ }
+ }
+
+ void TableStructure::addBox( sal_uInt16 nLine, const SwSelBoxes* pSelBoxes,
+ SwTableBox *pBox, sal_uLong &rnBorder, sal_uInt16 &rnCol,
+ ColumnStructure::iterator& rpCol, BoxStructure::iterator& rpSel,
+ bool &rbSelected, bool bCovered )
+ {
+ BoxSpanInfo aInfo;
+ if( pSelBoxes &&
+ USHRT_MAX != pSelBoxes->GetPos( pBox ) )
+ {
+ aInfo.mbSelected = true;
+ if( mnStartCol == USHRT_MAX )
+ {
+ mnStartCol = (sal_uInt16)maLines[nLine].size();
+ if( pSelBoxes->Count() < 2 )
+ {
+ pSelBoxes = 0;
+ aInfo.mbSelected = false;
+ }
+ }
+ }
+ else
+ aInfo.mbSelected = false;
+ rnBorder += pBox->GetFrmFmt()->GetFrmSize().GetWidth();
+ sal_uInt16 nLeftCol = rnCol;
+ while( rpCol != maCols.end() && *rpCol < rnBorder )
+ {
+ ++rnCol;
+ ++rpCol;
+ }
+ if( rpCol == maCols.end() || *rpCol > rnBorder )
+ {
+ maCols.insert( rpCol, rnBorder );
+ --rpCol;
+ incColSpan( nLine, rnCol );
+ }
+ aInfo.mnColSpan = rnCol - nLeftCol;
+ aInfo.mpCopy = 0;
+ aInfo.mpBox = bCovered ? 0 : pBox;
+ maLines[nLine].push_back( aInfo );
+ if( aInfo.mbSelected )
+ {
+ if( rbSelected )
+ {
+ while( rpSel != maLines[nLine].end() )
+ {
+ rpSel->mbSelected = true;
+ ++rpSel;
+ }
+ }
+ else
+ {
+ rpSel = maLines[nLine].end();
+ rbSelected = true;
+ }
+ --rpSel;
+ }
+ }
+
+ void TableStructure::moreLines( const SwTable& rTable )
+ {
+ if( mnAddLine )
+ {
+ const SwTableLines &rLines = rTable.GetTabLines();
+ sal_uInt16 nLineCount = rLines.Count();
+ if( nLineCount < mnAddLine )
+ mnAddLine = nLineCount;
+ sal_uInt16 nLine = (sal_uInt16)maLines.size();
+ maLines.resize( nLine + mnAddLine );
+ while( mnAddLine )
+ {
+ SwTableLine *pLine = rLines[ nLineCount - mnAddLine ];
+ addLine( nLine, pLine->GetTabBoxes(), 0, rTable.IsNewModel() );
+ --mnAddLine;
+ }
+ }
+ }
+
+ void TableStructure::incColSpan( sal_uInt16 nLineMax, sal_uInt16 nNewCol )
+ {
+ for( sal_uInt16 nLine = 0; nLine < nLineMax; ++nLine )
+ {
+ BoxStructure::iterator pInfo = maLines[nLine].begin();
+ BoxStructure::iterator pEnd = maLines[nLine].end();
+ long nCol = pInfo->mnColSpan;
+ while( nNewCol > nCol && ++pInfo != pEnd )
+ nCol += pInfo->mnColSpan;
+ if( pInfo != pEnd )
+ ++(pInfo->mnColSpan);
+ }
+ }
+
+ void TableStructure::assignBoxes( const TableStructure &rSource )
+ {
+ LineStructure::const_iterator pFirstLine = rSource.maLines.begin();
+ LineStructure::const_iterator pLastLine = rSource.maLines.end();
+ if( pFirstLine == pLastLine )
+ return;
+ LineStructure::const_iterator pCurrLine = pFirstLine;
+ LineStructure::size_type nLineCount = maLines.size();
+ sal_uInt16 nFirstStartCol = 0;
+ {
+ BoxStructure::const_iterator pFirstBox = pFirstLine->begin();
+ if( pFirstBox != pFirstLine->end() && pFirstBox->mpBox &&
+ pFirstBox->mpBox->getDummyFlag() )
+ nFirstStartCol = pFirstBox->mnColSpan;
+ }
+ for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ BoxStructure::const_iterator pFirstBox = pCurrLine->begin();
+ BoxStructure::const_iterator pLastBox = pCurrLine->end();
+ sal_uInt16 nCurrStartCol = mnStartCol;
+ if( pFirstBox != pLastBox )
+ {
+ BoxStructure::const_iterator pTmpBox = pLastBox;
+ --pTmpBox;
+ if( pTmpBox->mpBox && pTmpBox->mpBox->getDummyFlag() )
+ --pLastBox;
+ if( pFirstBox != pLastBox && pFirstBox->mpBox &&
+ pFirstBox->mpBox->getDummyFlag() )
+ {
+ if( nCurrStartCol < USHRT_MAX )
+ {
+ if( pFirstBox->mnColSpan > nFirstStartCol )
+ nCurrStartCol = pFirstBox->mnColSpan - nFirstStartCol
+ + nCurrStartCol;
+ }
+ ++pFirstBox;
+ }
+ }
+ if( pFirstBox != pLastBox )
+ {
+ BoxStructure::const_iterator pCurrBox = pFirstBox;
+ BoxStructure &rBox = maLines[nLine];
+ BoxStructure::size_type nBoxCount = rBox.size();
+ sal_uInt16 nCol = 0;
+ for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
+ {
+ BoxSpanInfo& rInfo = rBox[nBox];
+ nCol = nCol + rInfo.mnColSpan;
+ if( rInfo.mbSelected || nCol > nCurrStartCol )
+ {
+ rInfo.mpCopy = pCurrBox->mpBox;
+ if( rInfo.mbSelected && rInfo.mpCopy->getDummyFlag() )
+ {
+ ++pCurrBox;
+ if( pCurrBox == pLastBox )
+ {
+ pCurrBox = pFirstBox;
+ if( pCurrBox->mpBox->getDummyFlag() )
+ ++pCurrBox;
+ }
+ rInfo.mpCopy = pCurrBox->mpBox;
+ }
+ ++pCurrBox;
+ if( pCurrBox == pLastBox )
+ {
+ if( rInfo.mbSelected )
+ pCurrBox = pFirstBox;
+ else
+ {
+ rInfo.mbSelected = rInfo.mpCopy == 0;
+ break;
+ }
+ }
+ rInfo.mbSelected = rInfo.mpCopy == 0;
+ }
+ }
+ }
+ ++pCurrLine;
+ if( pCurrLine == pLastLine )
+ pCurrLine = pFirstLine;
+ }
+ }
+
+ void TableStructure::copyBoxes( const SwTable& rSource, SwTable& rDstTbl,
+ SwUndoTblCpyTbl* pUndo ) const
+ {
+ LineStructure::size_type nLineCount = maLines.size();
+ for( LineStructure::size_type nLine = 0; nLine < nLineCount; ++nLine )
+ {
+ const BoxStructure &rBox = maLines[nLine];
+ BoxStructure::size_type nBoxCount = rBox.size();
+ for( BoxStructure::size_type nBox = 0; nBox < nBoxCount; ++nBox )
+ {
+ const BoxSpanInfo& rInfo = rBox[nBox];
+ if( ( rInfo.mpCopy && !rInfo.mpCopy->getDummyFlag() )
+ || rInfo.mbSelected )
+ {
+ SwTableBox *pBox = rInfo.mpBox;
+ if( pBox && pBox->getRowSpan() > 0 )
+ lcl_CpyBox( rSource, rInfo.mpCopy, rDstTbl, pBox,
+ sal_True, pUndo );
+ }
+ }
+ }
+ }
+}
+
+// ---------------------------------------------------------------
+
+// kopiere die Tabelle in diese.
+// Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
+// wird dabei geloescht.
+// Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
+// Box einer "GrundLine".
+// Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
+// einer "GrundLine"
+
+
+void lcl_CpyBox( const SwTable& rCpyTbl, const SwTableBox* pCpyBox,
+ SwTable& rDstTbl, SwTableBox* pDstBox,
+ sal_Bool bDelCntnt, SwUndoTblCpyTbl* pUndo )
+{
+ OSL_ENSURE( ( !pCpyBox || pCpyBox->GetSttNd() ) && pDstBox->GetSttNd(),
+ "Keine inhaltstragende Box" );
+
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+ SwDoc* pDoc = rDstTbl.GetFrmFmt()->GetDoc();
+
+ // kopiere erst den neuen und loeschen dann den alten Inhalt
+ // (keine leeren Section erzeugen; werden sonst geloescht!)
+ std::auto_ptr< SwNodeRange > pRg( pCpyBox ?
+ new SwNodeRange ( *pCpyBox->GetSttNd(), 1,
+ *pCpyBox->GetSttNd()->EndOfSectionNode() ) : 0 );
+
+ SwNodeIndex aInsIdx( *pDstBox->GetSttNd(), bDelCntnt ? 1 :
+ pDstBox->GetSttNd()->EndOfSectionIndex() -
+ pDstBox->GetSttIdx() );
+
+ if( pUndo )
+ pUndo->AddBoxBefore( *pDstBox, bDelCntnt );
+
+ bool bUndoRedline = pUndo && pDoc->IsRedlineOn();
+ ::sw::UndoGuard const undoGuard(pDoc->GetIDocumentUndoRedo());
+
+ SwNodeIndex aSavePos( aInsIdx, -1 );
+ if( pRg.get() )
+ pCpyDoc->CopyWithFlyInFly( *pRg, 0, aInsIdx, sal_False );
+ else
+ pDoc->GetNodes().MakeTxtNode( aInsIdx, (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
+ aSavePos++;
+
+ SwTableLine* pLine = pDstBox->GetUpper();
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ sal_Bool bReplaceColl = sal_True;
+ if( bDelCntnt && !bUndoRedline )
+ {
+ // zuerst die Fly loeschen, dann die entsprechenden Nodes
+ SwNodeIndex aEndNdIdx( *aInsIdx.GetNode().EndOfSectionNode() );
+
+ // Bookmarks usw. verschieben
+ {
+ SwPosition aMvPos( aInsIdx );
+ SwCntntNode* pCNd = pDoc->GetNodes().GoPrevious( &aMvPos.nNode );
+ aMvPos.nContent.Assign( pCNd, pCNd->Len() );
+ pDoc->CorrAbs( aInsIdx, aEndNdIdx, aMvPos, /*sal_True*/sal_False );
+ }
+
+ // stehen noch FlyFrames rum, loesche auch diese
+ for( sal_uInt16 n = 0; n < pDoc->GetSpzFrmFmts()->Count(); ++n )
+ {
+ SwFrmFmt *const pFly = (*pDoc->GetSpzFrmFmts())[n];
+ SwFmtAnchor const*const pAnchor = &pFly->GetAnchor();
+ SwPosition const*const pAPos = pAnchor->GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == pAnchor->GetAnchorId()) ||
+ (FLY_AT_CHAR == pAnchor->GetAnchorId())) &&
+ aInsIdx <= pAPos->nNode && pAPos->nNode <= aEndNdIdx )
+ {
+ pDoc->DelLayoutFmt( pFly );
+ }
+ }
+
+ // ist DestBox eine Headline-Box und hat Tabellen-Vorlage gesetzt,
+ // dann NICHT die TabellenHeadline-Vorlage automatisch setzen
+ if( 1 < rDstTbl.GetTabLines().Count() &&
+ pLine == rDstTbl.GetTabLines()[0] )
+ {
+ SwCntntNode* pCNd = aInsIdx.GetNode().GetCntntNode();
+ if( !pCNd )
+ {
+ SwNodeIndex aTmp( aInsIdx );
+ pCNd = pDoc->GetNodes().GoNext( &aTmp );
+ }
+
+ if( pCNd &&
+ RES_POOLCOLL_TABLE_HDLN !=
+ pCNd->GetFmtColl()->GetPoolFmtId() )
+ bReplaceColl = sal_False;
+ }
+
+ pDoc->GetNodes().Delete( aInsIdx, aEndNdIdx.GetIndex() - aInsIdx.GetIndex() );
+ }
+
+ //b6341295: Table copy redlining will be managed by AddBoxAfter()
+ if( pUndo )
+ pUndo->AddBoxAfter( *pDstBox, aInsIdx, bDelCntnt );
+
+ // heading
+ SwTxtNode *const pTxtNd = aSavePos.GetNode().GetTxtNode();
+ if( pTxtNd )
+ {
+ sal_uInt16 nPoolId = pTxtNd->GetTxtColl()->GetPoolFmtId();
+ if( bReplaceColl &&
+ (( 1 < rDstTbl.GetTabLines().Count() &&
+ pLine == rDstTbl.GetTabLines()[0] )
+ // gilt noch die Tabellen-Inhalt ??
+ ? RES_POOLCOLL_TABLE == nPoolId
+ : RES_POOLCOLL_TABLE_HDLN == nPoolId ) )
+ {
+ SwTxtFmtColl* pColl = pDoc->GetTxtCollFromPool(
+ static_cast<sal_uInt16>(
+ RES_POOLCOLL_TABLE == nPoolId
+ ? RES_POOLCOLL_TABLE_HDLN
+ : RES_POOLCOLL_TABLE ) );
+ if( pColl ) // Vorlage umsetzen
+ {
+ SwPaM aPam( aSavePos );
+ aPam.SetMark();
+ aPam.Move( fnMoveForward, fnGoSection );
+ pDoc->SetTxtFmtColl( aPam, pColl );
+ }
+ }
+
+ // loesche die akt. Formel/Format/Value Werte
+ if( SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_FORMAT ) ||
+ SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_FORMULA ) ||
+ SFX_ITEM_SET == pDstBox->GetFrmFmt()->GetItemState( RES_BOXATR_VALUE ) )
+ {
+ pDstBox->ClaimFrmFmt()->ResetFmtAttr( RES_BOXATR_FORMAT,
+ RES_BOXATR_VALUE );
+ }
+
+ // kopiere die TabellenBoxAttribute - Formel/Format/Value
+ if( pCpyBox )
+ {
+ SfxItemSet aBoxAttrSet( pCpyDoc->GetAttrPool(), RES_BOXATR_FORMAT,
+ RES_BOXATR_VALUE );
+ aBoxAttrSet.Put( pCpyBox->GetFrmFmt()->GetAttrSet() );
+ if( aBoxAttrSet.Count() )
+ {
+ const SfxPoolItem* pItem;
+ SvNumberFormatter* pN = pDoc->GetNumberFormatter( sal_False );
+ if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == aBoxAttrSet.
+ GetItemState( RES_BOXATR_FORMAT, sal_False, &pItem ) )
+ {
+ sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
+ sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
+ if( nNewIdx != nOldIdx )
+ aBoxAttrSet.Put( SwTblBoxNumFormat( nNewIdx ));
+ }
+ pDstBox->ClaimFrmFmt()->SetFmtAttr( aBoxAttrSet );
+ }
+ }
+ }
+}
+
+sal_Bool SwTable::InsNewTable( const SwTable& rCpyTbl, const SwSelBoxes& rSelBoxes,
+ SwUndoTblCpyTbl* pUndo )
+{
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ // analyse source structure
+ TableStructure aCopyStruct( rCpyTbl );
+
+ // analyse target structure (from start box) and selected substructure
+ _FndBox aFndBox( 0, 0 );
+ { // get all boxes/lines
+ _FndPara aPara( rSelBoxes, &aFndBox );
+ GetTabLines().ForEach( &_FndLineCopyCol, &aPara );
+ }
+ TableStructure aTarget( *this, aFndBox, rSelBoxes, aCopyStruct.getLineCount() );
+
+ bool bClear = false;
+ if( aTarget.mnAddLine && IsNewModel() )
+ {
+ SwSelBoxes aBoxes;
+ aBoxes.Insert( GetTabLines()[ GetTabLines().Count()-1 ]->GetTabBoxes()[0] );
+ if( pUndo )
+ pUndo->InsertRow( *this, aBoxes, aTarget.mnAddLine );
+ else
+ InsertRow( pDoc, aBoxes, aTarget.mnAddLine, sal_True );
+
+ aTarget.moreLines( *this );
+ bClear = true;
+ }
+
+ // find mapping, if needed extend target table and/or selection
+ aTarget.assignBoxes( aCopyStruct );
+
+ {
+ // Change table formulas into relative representation
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ // delete frames
+ aFndBox.SetTableLines( *this );
+ if( bClear )
+ aFndBox.ClearLineBehind();
+ aFndBox.DelFrms( *this );
+
+ // copy boxes
+ aTarget.copyBoxes( rCpyTbl, *this, pUndo );
+
+ // adjust row span attributes accordingly
+
+ // make frames
+ aFndBox.MakeFrms( *this );
+
+ return sal_True;
+}
+
+// kopiere die Tabelle in diese.
+// Kopiere alle Boxen einer Line in entsprechenden Boxen. Der alte Inhalt
+// wird dabei geloescht.
+// Ist keine mehr vorhanden, kommt der restliche Inhalt in die letzte
+// Box einer "GrundLine".
+// Ist auch keine Line mehr vorhanden, -> auch in die letzte Box
+// einer "GrundLine"
+sal_Bool SwTable::InsTable( const SwTable& rCpyTbl, const SwNodeIndex& rSttBox,
+ SwUndoTblCpyTbl* pUndo )
+{
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+
+ SwTableNode* pTblNd = pDoc->IsIdxInTbl( rSttBox );
+
+ // suche erstmal die Box, in die kopiert werden soll:
+ SwTableBox* pMyBox = (SwTableBox*)GetTblBox(
+ rSttBox.GetNode().FindTableBoxStartNode()->GetIndex() );
+
+ OSL_ENSURE( pMyBox, "Index steht nicht in dieser Tabelle in einer Box" );
+
+ // loesche erstmal die Frames der Tabelle
+ _FndBox aFndBox( 0, 0 );
+ aFndBox.DelFrms( pTblNd->GetTable() );
+
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ sal_Bool bDelCntnt = sal_True;
+ const SwTableBox* pTmp;
+
+ for( sal_uInt16 nLines = 0; nLines < rCpyTbl.GetTabLines().Count(); ++nLines )
+ {
+ // hole die erste Box von der Copy-Line
+ const SwTableBox* pCpyBox = rCpyTbl.GetTabLines()[nLines]
+ ->GetTabBoxes()[0];
+ while( pCpyBox->GetTabLines().Count() )
+ pCpyBox = pCpyBox->GetTabLines()[0]->GetTabBoxes()[0];
+
+ do {
+ // kopiere erst den neuen und loeschen dann den alten Inhalt
+ // (keine leeren Section erzeugen, werden sonst geloescht!)
+ lcl_CpyBox( rCpyTbl, pCpyBox, *this, pMyBox, bDelCntnt, pUndo );
+
+ if( 0 == (pTmp = pCpyBox->FindNextBox( rCpyTbl, pCpyBox, sal_False )))
+ break; // es folgt keine weitere Box mehr
+ pCpyBox = pTmp;
+
+ if( 0 == ( pTmp = pMyBox->FindNextBox( *this, pMyBox, sal_False )))
+ bDelCntnt = sal_False; // kein Platz mehr ??
+ else
+ pMyBox = (SwTableBox*)pTmp;
+
+ } while( sal_True );
+
+ // suche die oberste Line
+ SwTableLine* pNxtLine = pMyBox->GetUpper();
+ while( pNxtLine->GetUpper() )
+ pNxtLine = pNxtLine->GetUpper()->GetUpper();
+ sal_uInt16 nPos = GetTabLines().C40_GETPOS( SwTableLine, pNxtLine );
+ // gibt es eine naechste ??
+ if( nPos + 1 >= GetTabLines().Count() )
+ bDelCntnt = sal_False; // es gibt keine, alles in die letzte Box
+ else
+ {
+ // suche die naechste "Inhaltstragende Box"
+ pNxtLine = GetTabLines()[ nPos+1 ];
+ pMyBox = pNxtLine->GetTabBoxes()[0];
+ while( pMyBox->GetTabLines().Count() )
+ pMyBox = pMyBox->GetTabLines()[0]->GetTabBoxes()[0];
+ bDelCntnt = sal_True;
+ }
+ }
+
+ aFndBox.MakeFrms( pTblNd->GetTable() ); // erzeuge die Frames neu
+ return sal_True;
+}
+
+sal_Bool SwTable::InsTable( const SwTable& rCpyTbl, const SwSelBoxes& rSelBoxes,
+ SwUndoTblCpyTbl* pUndo )
+{
+ OSL_ENSURE( rSelBoxes.Count(), "Missing selection" );
+
+ SetHTMLTableLayout( 0 ); // MIB 9.7.97: HTML-Layout loeschen
+
+ if( IsNewModel() || rCpyTbl.IsNewModel() )
+ return InsNewTable( rCpyTbl, rSelBoxes, pUndo );
+
+ OSL_ENSURE( !rCpyTbl.IsTblComplex(), "Table too complex" );
+
+ SwDoc* pDoc = GetFrmFmt()->GetDoc();
+ SwDoc* pCpyDoc = rCpyTbl.GetFrmFmt()->GetDoc();
+
+ SwTblNumFmtMerge aTNFM( *pCpyDoc, *pDoc );
+
+ SwTableBox *pTmpBox, *pSttBox = (SwTableBox*)rSelBoxes[0];
+
+ sal_uInt16 nLn, nBx;
+ _FndLine *pFLine, *pInsFLine = 0;
+ _FndBox aFndBox( 0, 0 );
+ // suche alle Boxen / Lines
+ {
+ _FndPara aPara( rSelBoxes, &aFndBox );
+ ((SwTableLines&)GetTabLines()).ForEach( &_FndLineCopyCol, &aPara );
+ }
+
+ // JP 06.09.96: Sonderfall - eine Box in der Tabelle -> in alle
+ // selektierten Boxen kopieren!
+ if( 1 != rCpyTbl.GetTabSortBoxes().Count() )
+ {
+ SwTableLine* pSttLine = pSttBox->GetUpper();
+ sal_uInt16 nSttBox = pSttLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ sal_uInt16 nSttLine = GetTabLines().C40_GETPOS( SwTableLine, pSttLine );
+ _FndBox* pFndBox;
+
+ sal_uInt16 nFndCnt = aFndBox.GetLines().Count();
+ if( !nFndCnt )
+ return sal_False;
+
+ // teste ob genug Platz fuer die einzelnen Lines und Boxen ist:
+ sal_uInt16 nTstLns = 0;
+ pFLine = aFndBox.GetLines()[ 0 ];
+ pSttLine = pFLine->GetLine();
+ nSttLine = GetTabLines().C40_GETPOS( SwTableLine, pSttLine );
+ // sind ueberhaupt soviele Zeilen vorhanden
+ if( 1 == nFndCnt )
+ {
+ // in der Tabelle noch genug Platz ??
+ if( (GetTabLines().Count() - nSttLine ) <
+ rCpyTbl.GetTabLines().Count() )
+ {
+ // sollte nicht mehr soviele Lines vorhanden sein, dann
+ // teste, ob man durch einfuegen neuer zum Ziel kommt. Aber
+ // nur wenn die SSelection eine Box umfasst !!
+ if( 1 < rSelBoxes.Count() )
+ return sal_False;
+
+ sal_uInt16 nNewLns = rCpyTbl.GetTabLines().Count() -
+ (GetTabLines().Count() - nSttLine );
+
+ // Dann teste mal ob die Anzahl der Boxen fuer die Lines reicht
+ SwTableLine* pLastLn = GetTabLines()[ GetTabLines().Count()-1 ];
+
+ pSttBox = pFLine->GetBoxes()[0]->GetBox();
+ nSttBox = pFLine->GetLine()->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ for( sal_uInt16 n = rCpyTbl.GetTabLines().Count() - nNewLns;
+ n < rCpyTbl.GetTabLines().Count(); ++n )
+ {
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[ n ];
+
+ if( pLastLn->GetTabBoxes().Count() < nSttBox ||
+ ( pLastLn->GetTabBoxes().Count() - nSttBox ) <
+ pCpyLn->GetTabBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pCpyLn->GetTabBoxes().Count(); ++nBx )
+ if( !( pTmpBox = pLastLn->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ }
+ // es ist also Platz fuer das zu kopierende vorhanden, also
+ // fuege entsprechend neue Zeilen ein.
+ SwTableBox* pInsBox = pLastLn->GetTabBoxes()[ nSttBox ];
+ OSL_ENSURE( pInsBox && pInsBox->GetSttNd(),
+ "kein CntntBox oder steht nicht in dieser Tabelle" );
+ SwSelBoxes aBoxes;
+
+ if( pUndo
+ ? !pUndo->InsertRow( *this, SelLineFromBox( pInsBox,
+ aBoxes, sal_True ), nNewLns )
+ : !InsertRow( pDoc, SelLineFromBox( pInsBox,
+ aBoxes, sal_True ), nNewLns, sal_True ) )
+ return sal_False;
+ }
+
+ nTstLns = rCpyTbl.GetTabLines().Count(); // soviele Kopieren
+ }
+ else if( 0 == (nFndCnt % rCpyTbl.GetTabLines().Count()) )
+ nTstLns = nFndCnt;
+ else
+ return sal_False; // kein Platz fuer die Zeilen
+
+ for( nLn = 0; nLn < nTstLns; ++nLn )
+ {
+ // Zeilen sind genug vorhanden, dann ueberpruefe die Boxen
+ // je Zeile
+ pFLine = aFndBox.GetLines()[ nLn % nFndCnt ];
+ SwTableLine* pLine = pFLine->GetLine();
+ pSttBox = pFLine->GetBoxes()[0]->GetBox();
+ nSttBox = pLine->GetTabBoxes().C40_GETPOS( SwTableBox, pSttBox );
+ if( nLn >= nFndCnt )
+ {
+ // es sind im ClipBoard mehr Zeilen als selectiert wurden
+ pInsFLine = new _FndLine( GetTabLines()[ nSttLine + nLn ],
+ &aFndBox );
+ pLine = pInsFLine->GetLine();
+ }
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[ nLn %
+ rCpyTbl.GetTabLines().Count() ];
+
+ // zu wenig Zeilen selektiert ?
+ if( pInsFLine )
+ {
+ // eine neue Zeile wird in die FndBox eingefuegt,
+ if( pLine->GetTabBoxes().Count() < nSttBox ||
+ ( pLine->GetTabBoxes().Count() - nSttBox ) <
+ pFLine->GetBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ {
+ if( !( pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ // wenn Ok, fuege die Box in die FndLine zu
+ pFndBox = new _FndBox( pTmpBox, pInsFLine );
+ pInsFLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, nBx );
+ }
+ aFndBox.GetLines().C40_INSERT( _FndLine, pInsFLine, nLn );
+ }
+ else if( pFLine->GetBoxes().Count() == 1 )
+ {
+ if( pLine->GetTabBoxes().Count() < nSttBox ||
+ ( pLine->GetTabBoxes().Count() - nSttBox ) <
+ pCpyLn->GetTabBoxes().Count() )
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pCpyLn->GetTabBoxes().Count(); ++nBx )
+ {
+ if( !( pTmpBox = pLine->GetTabBoxes()[ nSttBox + nBx ])
+ ->GetSttNd() )
+ return sal_False;
+ // wenn Ok, fuege die Box in die FndLine zu
+ if( nBx == pFLine->GetBoxes().Count() )
+ {
+ pFndBox = new _FndBox( pTmpBox, pFLine );
+ pFLine->GetBoxes().C40_INSERT( _FndBox, pFndBox, nBx );
+ }
+ }
+ }
+ else
+ {
+ // ueberpruefe die selektierten Boxen mit denen im Clipboard
+ // (n-Fach)
+ if( 0 != ( pFLine->GetBoxes().Count() %
+ pCpyLn->GetTabBoxes().Count() ))
+ return sal_False;
+
+ // Test auf Verschachtelungen
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ if( !pFLine->GetBoxes()[ nBx ]->GetBox()->GetSttNd() )
+ return sal_False;
+ }
+ }
+
+ if( !aFndBox.GetLines().Count() )
+ return sal_False;
+ }
+
+ {
+ // Tabellen-Formeln in die relative Darstellung umwandeln
+ SwTableFmlUpdate aMsgHnt( &rCpyTbl );
+ aMsgHnt.eFlags = TBL_RELBOXNAME;
+ pCpyDoc->UpdateTblFlds( &aMsgHnt );
+ }
+
+ // loesche die Frames
+ aFndBox.SetTableLines( *this );
+ aFndBox.DelFrms( *this );
+
+ if( 1 == rCpyTbl.GetTabSortBoxes().Count() )
+ {
+ SwTableBox *pTmpBx = rCpyTbl.GetTabSortBoxes()[0];
+ for( sal_uInt16 n = 0; n < rSelBoxes.Count(); ++n )
+ lcl_CpyBox( rCpyTbl, pTmpBx, *this,
+ (SwTableBox*)rSelBoxes[n], sal_True, pUndo );
+ }
+ else
+ for( nLn = 0; nLn < aFndBox.GetLines().Count(); ++nLn )
+ {
+ pFLine = aFndBox.GetLines()[ nLn ];
+ SwTableLine* pCpyLn = rCpyTbl.GetTabLines()[
+ nLn % rCpyTbl.GetTabLines().Count() ];
+ for( nBx = 0; nBx < pFLine->GetBoxes().Count(); ++nBx )
+ {
+ // Kopiere in pMyBox die pCpyBox
+ lcl_CpyBox( rCpyTbl, pCpyLn->GetTabBoxes()[
+ nBx % pCpyLn->GetTabBoxes().Count() ],
+ *this, pFLine->GetBoxes()[ nBx ]->GetBox(), sal_True, pUndo );
+ }
+ }
+
+ aFndBox.MakeFrms( *this );
+ return sal_True;
+}
+
+sal_Bool _FndCntntBox( const SwTableBox*& rpBox, void* pPara )
+{
+ SwTableBox* pBox = (SwTableBox*)rpBox;
+ if( rpBox->GetTabLines().Count() )
+ pBox->GetTabLines().ForEach( &_FndCntntLine, pPara );
+ else
+ ((SwSelBoxes*)pPara)->Insert( pBox );
+ return sal_True;
+}
+
+sal_Bool _FndCntntLine( const SwTableLine*& rpLine, void* pPara )
+{
+ ((SwTableLine*)rpLine)->GetTabBoxes().ForEach( &_FndCntntBox, pPara );
+ return sal_True;
+}
+
+// suche alle Inhaltstragenden-Boxen dieser Box
+SwSelBoxes& SwTable::SelLineFromBox( const SwTableBox* pBox,
+ SwSelBoxes& rBoxes, sal_Bool bToTop ) const
+{
+ SwTableLine* pLine = (SwTableLine*)pBox->GetUpper();
+ if( bToTop )
+ while( pLine->GetUpper() )
+ pLine = pLine->GetUpper()->GetUpper();
+
+ // alle alten loeschen
+ rBoxes.Remove( sal_uInt16(0), rBoxes.Count() );
+ pLine->GetTabBoxes().ForEach( &_FndCntntBox, &rBoxes );
+ return rBoxes;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */