forked from amazingfate/loongoffice
Into the new class DocumentFieldsManager. Removed SwDoc::_MakeFldList because it is not defined anywhere. Also moved a few non interface methods that belong to the manager. Change-Id: Icefd7ca7adcbb05a18d6fae0529fc54150b862fd
350 lines
12 KiB
C++
350 lines
12 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
#include <doc.hxx>
|
|
#include <IDocumentFieldsAccess.hxx>
|
|
#include <node.hxx>
|
|
#include <frmfmt.hxx>
|
|
#include <swtable.hxx>
|
|
#include <ndtxt.hxx>
|
|
#include <swtblfmt.hxx>
|
|
#include <cellatr.hxx>
|
|
#include <docary.hxx>
|
|
#include <ddefld.hxx>
|
|
#include <swddetbl.hxx>
|
|
#include <svtools/fmtfield.hxx>
|
|
#include <boost/foreach.hpp>
|
|
#include <vector>
|
|
|
|
|
|
#ifdef DBG_UTIL
|
|
#define CHECK_TABLE(t) (t).CheckConsistency();
|
|
#else
|
|
#define CHECK_TABLE(t)
|
|
#endif
|
|
|
|
|
|
|
|
// Structure for the mapping from old and new frame formats to the
|
|
// boxes and lines of a table
|
|
struct _MapTblFrmFmt
|
|
{
|
|
const SwFrmFmt *pOld, *pNew;
|
|
_MapTblFrmFmt( const SwFrmFmt *pOldFmt, const SwFrmFmt*pNewFmt )
|
|
: pOld( pOldFmt ), pNew( pNewFmt )
|
|
{}
|
|
};
|
|
|
|
typedef std::vector<_MapTblFrmFmt> _MapTblFrmFmts;
|
|
|
|
SwCntntNode* SwTxtNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
|
|
{
|
|
// the Copy-Textnode is the Node with the Text, the Copy-Attrnode is the
|
|
// node with the collection and hard attributes. Normally is the same
|
|
// node, but if insert a glossary without formatting, then the Attrnode
|
|
// is the prev node of the destionation position in dest. document.
|
|
SwTxtNode* pCpyTxtNd = (SwTxtNode*)this;
|
|
SwTxtNode* pCpyAttrNd = pCpyTxtNd;
|
|
|
|
// Copy the formats to the other document
|
|
SwTxtFmtColl* pColl = 0;
|
|
if( pDoc->IsInsOnlyTextGlossary() )
|
|
{
|
|
SwNodeIndex aIdx( rIdx, -1 );
|
|
if( aIdx.GetNode().IsTxtNode() )
|
|
{
|
|
pCpyAttrNd = aIdx.GetNode().GetTxtNode();
|
|
pColl = &pCpyAttrNd->GetTxtColl()->GetNextTxtFmtColl();
|
|
}
|
|
}
|
|
if( !pColl )
|
|
pColl = pDoc->CopyTxtColl( *GetTxtColl() );
|
|
|
|
SwTxtNode* pTxtNd = pDoc->GetNodes().MakeTxtNode( rIdx, pColl );
|
|
|
|
// METADATA: register copy
|
|
pTxtNd->RegisterAsCopyOf(*pCpyTxtNd);
|
|
|
|
// Copy Attribute/Text
|
|
if( !pCpyAttrNd->HasSwAttrSet() )
|
|
// An AttrSet was added for numbering, so delete it
|
|
pTxtNd->ResetAllAttr();
|
|
|
|
// if Copy-Textnode unequal to Copy-Attrnode, then copy first
|
|
// the attributes into the new Node.
|
|
if( pCpyAttrNd != pCpyTxtNd )
|
|
{
|
|
pCpyAttrNd->CopyAttr( pTxtNd, 0, 0 );
|
|
if( pCpyAttrNd->HasSwAttrSet() )
|
|
{
|
|
SwAttrSet aSet( *pCpyAttrNd->GetpSwAttrSet() );
|
|
aSet.ClearItem( RES_PAGEDESC );
|
|
aSet.ClearItem( RES_BREAK );
|
|
aSet.CopyToModify( *pTxtNd );
|
|
}
|
|
}
|
|
|
|
// Is that enough? What about PostIts/Fields/FieldTypes?
|
|
// #i96213# - force copy of all attributes
|
|
pCpyTxtNd->CopyText( pTxtNd, SwIndex( pCpyTxtNd ),
|
|
pCpyTxtNd->GetTxt().getLength(), true );
|
|
|
|
if( RES_CONDTXTFMTCOLL == pColl->Which() )
|
|
pTxtNd->ChkCondColl();
|
|
|
|
return pTxtNd;
|
|
}
|
|
|
|
static bool lcl_SrchNew( const _MapTblFrmFmt& rMap, const SwFrmFmt** pPara )
|
|
{
|
|
if( rMap.pOld != *pPara )
|
|
return true;
|
|
*pPara = rMap.pNew;
|
|
return false;
|
|
}
|
|
|
|
struct _CopyTable
|
|
{
|
|
SwDoc* pDoc;
|
|
sal_uLong nOldTblSttIdx;
|
|
_MapTblFrmFmts& rMapArr;
|
|
SwTableLine* pInsLine;
|
|
SwTableBox* pInsBox;
|
|
SwTableNode *pTblNd;
|
|
const SwTable *pOldTable;
|
|
|
|
_CopyTable( SwDoc* pDc, _MapTblFrmFmts& rArr, sal_uLong nOldStt,
|
|
SwTableNode& rTblNd, const SwTable* pOldTbl )
|
|
: pDoc(pDc), nOldTblSttIdx(nOldStt), rMapArr(rArr),
|
|
pInsLine(0), pInsBox(0), pTblNd(&rTblNd), pOldTable( pOldTbl )
|
|
{}
|
|
};
|
|
|
|
static void lcl_CopyTblLine( const SwTableLine* pLine, _CopyTable* pCT );
|
|
|
|
static void lcl_CopyTblBox( SwTableBox* pBox, _CopyTable* pCT )
|
|
{
|
|
SwTableBoxFmt* pBoxFmt = (SwTableBoxFmt*)pBox->GetFrmFmt();
|
|
for( _MapTblFrmFmts::const_iterator it = pCT->rMapArr.begin(); it != pCT->rMapArr.end(); ++it )
|
|
if ( !lcl_SrchNew( *it, (const SwFrmFmt**)&pBoxFmt ) )
|
|
break;
|
|
if( pBoxFmt == pBox->GetFrmFmt() ) // Create a new one?
|
|
{
|
|
const SfxPoolItem* pItem;
|
|
if( SFX_ITEM_SET == pBoxFmt->GetItemState( RES_BOXATR_FORMULA, false,
|
|
&pItem ) && ((SwTblBoxFormula*)pItem)->IsIntrnlName() )
|
|
{
|
|
((SwTblBoxFormula*)pItem)->PtrToBoxNm( pCT->pOldTable );
|
|
}
|
|
|
|
pBoxFmt = pCT->pDoc->MakeTableBoxFmt();
|
|
pBoxFmt->CopyAttrs( *pBox->GetFrmFmt() );
|
|
|
|
if( pBox->GetSttIdx() )
|
|
{
|
|
SvNumberFormatter* pN = pCT->pDoc->GetNumberFormatter( false );
|
|
if( pN && pN->HasMergeFmtTbl() && SFX_ITEM_SET == pBoxFmt->
|
|
GetItemState( RES_BOXATR_FORMAT, false, &pItem ) )
|
|
{
|
|
sal_uLong nOldIdx = ((SwTblBoxNumFormat*)pItem)->GetValue();
|
|
sal_uLong nNewIdx = pN->GetMergeFmtIndex( nOldIdx );
|
|
if( nNewIdx != nOldIdx )
|
|
pBoxFmt->SetFmtAttr( SwTblBoxNumFormat( nNewIdx ));
|
|
|
|
}
|
|
}
|
|
|
|
pCT->rMapArr.push_back( _MapTblFrmFmt( pBox->GetFrmFmt(), pBoxFmt ) );
|
|
}
|
|
|
|
sal_uInt16 nLines = pBox->GetTabLines().size();
|
|
SwTableBox* pNewBox;
|
|
if( nLines )
|
|
pNewBox = new SwTableBox( pBoxFmt, nLines, pCT->pInsLine );
|
|
else
|
|
{
|
|
SwNodeIndex aNewIdx( *pCT->pTblNd,
|
|
pBox->GetSttIdx() - pCT->nOldTblSttIdx );
|
|
OSL_ENSURE( aNewIdx.GetNode().IsStartNode(), "Index is not on the start node" );
|
|
pNewBox = new SwTableBox( pBoxFmt, aNewIdx, pCT->pInsLine );
|
|
pNewBox->setRowSpan( pBox->getRowSpan() );
|
|
}
|
|
|
|
pCT->pInsLine->GetTabBoxes().push_back( pNewBox );
|
|
|
|
if( nLines )
|
|
{
|
|
_CopyTable aPara( *pCT );
|
|
aPara.pInsBox = pNewBox;
|
|
BOOST_FOREACH( const SwTableLine* pLine, pBox->GetTabLines() )
|
|
lcl_CopyTblLine( pLine, &aPara );
|
|
}
|
|
else if( pNewBox->IsInHeadline( &pCT->pTblNd->GetTable() ))
|
|
// In the headline, the paragraphs must match conditional styles
|
|
pNewBox->GetSttNd()->CheckSectionCondColl();
|
|
}
|
|
|
|
static void lcl_CopyTblLine( const SwTableLine* pLine, _CopyTable* pCT )
|
|
{
|
|
SwTableLineFmt* pLineFmt = (SwTableLineFmt*)pLine->GetFrmFmt();
|
|
for( _MapTblFrmFmts::const_iterator it = pCT->rMapArr.begin(); it != pCT->rMapArr.end(); ++it )
|
|
if ( !lcl_SrchNew( *it, (const SwFrmFmt**)&pLineFmt ) )
|
|
break;
|
|
if( pLineFmt == pLine->GetFrmFmt() ) // Create a new one?
|
|
{
|
|
pLineFmt = pCT->pDoc->MakeTableLineFmt();
|
|
pLineFmt->CopyAttrs( *pLine->GetFrmFmt() );
|
|
pCT->rMapArr.push_back( _MapTblFrmFmt( pLine->GetFrmFmt(), pLineFmt ) );
|
|
}
|
|
SwTableLine* pNewLine = new SwTableLine( pLineFmt,
|
|
pLine->GetTabBoxes().size(), pCT->pInsBox );
|
|
// Insert the new row into the table
|
|
if( pCT->pInsBox )
|
|
{
|
|
pCT->pInsBox->GetTabLines().push_back( pNewLine );
|
|
}
|
|
else
|
|
{
|
|
pCT->pTblNd->GetTable().GetTabLines().push_back( pNewLine );
|
|
}
|
|
pCT->pInsLine = pNewLine;
|
|
for( SwTableBoxes::iterator it = ((SwTableLine*)pLine)->GetTabBoxes().begin();
|
|
it != ((SwTableLine*)pLine)->GetTabBoxes().end(); ++it)
|
|
lcl_CopyTblBox(*it, pCT );
|
|
}
|
|
|
|
SwTableNode* SwTableNode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const
|
|
{
|
|
// In which array are we? Nodes? UndoNodes?
|
|
SwNodes& rNds = (SwNodes&)GetNodes();
|
|
|
|
{
|
|
if( rIdx < pDoc->GetNodes().GetEndOfInserts().GetIndex() &&
|
|
rIdx >= pDoc->GetNodes().GetEndOfInserts().StartOfSectionIndex() )
|
|
return 0;
|
|
}
|
|
|
|
// Copy the TableFrmFmt
|
|
OUString sTblName( GetTable().GetFrmFmt()->GetName() );
|
|
if( !pDoc->IsCopyIsMove() )
|
|
{
|
|
const SwFrmFmts& rTblFmts = *pDoc->GetTblFrmFmts();
|
|
for( sal_uInt16 n = rTblFmts.size(); n; )
|
|
if( rTblFmts[ --n ]->GetName() == sTblName )
|
|
{
|
|
sTblName = pDoc->GetUniqueTblName();
|
|
break;
|
|
}
|
|
}
|
|
|
|
SwFrmFmt* pTblFmt = pDoc->MakeTblFrmFmt( sTblName, pDoc->GetDfltFrmFmt() );
|
|
pTblFmt->CopyAttrs( *GetTable().GetFrmFmt() );
|
|
SwTableNode* pTblNd = new SwTableNode( rIdx );
|
|
SwEndNode* pEndNd = new SwEndNode( rIdx, *pTblNd );
|
|
SwNodeIndex aInsPos( *pEndNd );
|
|
|
|
SwTable& rTbl = (SwTable&)pTblNd->GetTable();
|
|
rTbl.RegisterToFormat( *pTblFmt );
|
|
|
|
rTbl.SetRowsToRepeat( GetTable().GetRowsToRepeat() );
|
|
rTbl.SetTblChgMode( GetTable().GetTblChgMode() );
|
|
rTbl.SetTableModel( GetTable().IsNewModel() );
|
|
|
|
SwDDEFieldType* pDDEType = 0;
|
|
if( IS_TYPE( SwDDETable, &GetTable() ))
|
|
{
|
|
// We're copying a DDE table
|
|
// Is the field type available in the new document?
|
|
pDDEType = ((SwDDETable&)GetTable()).GetDDEFldType();
|
|
if( pDDEType->IsDeleted() )
|
|
pDoc->getIDocumentFieldsAccess().InsDeletedFldType( *pDDEType );
|
|
else
|
|
pDDEType = (SwDDEFieldType*)pDoc->getIDocumentFieldsAccess().InsertFldType( *pDDEType );
|
|
OSL_ENSURE( pDDEType, "unknown FieldType" );
|
|
|
|
// Swap the table pointers in the node
|
|
SwDDETable* pNewTable = new SwDDETable( pTblNd->GetTable(), pDDEType );
|
|
pTblNd->SetNewTable( pNewTable, false );
|
|
}
|
|
// First copy the content of the tables, we will later assign the
|
|
// boxes/lines and create the frames
|
|
SwNodeRange aRg( *this, +1, *EndOfSectionNode() );
|
|
|
|
// If there is a table in this table, the table format for the outer table
|
|
// does not seem to be used, because the table does not have any contents yet
|
|
// (see IsUsed). Therefore the inner table gets the same name as the outer table.
|
|
// We have to make sure that the table node of the SwTable is accessible, even
|
|
// without any content in m_TabSortContentBoxes. #i26629#
|
|
pTblNd->GetTable().SetTableNode( pTblNd );
|
|
rNds._Copy( aRg, aInsPos, false );
|
|
pTblNd->GetTable().SetTableNode( 0 );
|
|
|
|
// Special case for a single box
|
|
if( 1 == GetTable().GetTabSortBoxes().size() )
|
|
{
|
|
aRg.aStart.Assign( *pTblNd, 1 );
|
|
aRg.aEnd.Assign( *pTblNd->EndOfSectionNode() );
|
|
pDoc->GetNodes().SectionDown( &aRg, SwTableBoxStartNode );
|
|
}
|
|
|
|
// Delete all frames from the copied area, they will be created
|
|
// during the generation of the table frame
|
|
pTblNd->DelFrms();
|
|
|
|
_MapTblFrmFmts aMapArr;
|
|
_CopyTable aPara( pDoc, aMapArr, GetIndex(), *pTblNd, &GetTable() );
|
|
|
|
BOOST_FOREACH(const SwTableLine* pLine, GetTable().GetTabLines() )
|
|
lcl_CopyTblLine( pLine, &aPara );
|
|
|
|
if( pDDEType )
|
|
pDDEType->IncRefCnt();
|
|
|
|
CHECK_TABLE( GetTable() );
|
|
return pTblNd;
|
|
}
|
|
|
|
void SwTxtNode::CopyCollFmt( SwTxtNode& rDestNd )
|
|
{
|
|
// Copy the formats into the other document:
|
|
// Special case for PageBreak/PageDesc/ColBrk
|
|
SwDoc* pDestDoc = rDestNd.GetDoc();
|
|
SwAttrSet aPgBrkSet( pDestDoc->GetAttrPool(), aBreakSetRange );
|
|
const SwAttrSet* pSet;
|
|
|
|
if( 0 != ( pSet = rDestNd.GetpSwAttrSet() ) )
|
|
{
|
|
// Special cases for Break-Attributes
|
|
const SfxPoolItem* pAttr;
|
|
if( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, false, &pAttr ) )
|
|
aPgBrkSet.Put( *pAttr );
|
|
|
|
if( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, false, &pAttr ) )
|
|
aPgBrkSet.Put( *pAttr );
|
|
}
|
|
|
|
rDestNd.ChgFmtColl( pDestDoc->CopyTxtColl( *GetTxtColl() ));
|
|
if( 0 != ( pSet = GetpSwAttrSet() ) )
|
|
pSet->CopyToModify( rDestNd );
|
|
|
|
if( aPgBrkSet.Count() )
|
|
rDestNd.SetAttr( aPgBrkSet );
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|