summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--svx/source/table/tablertfimporter.cxx455
1 files changed, 455 insertions, 0 deletions
diff --git a/svx/source/table/tablertfimporter.cxx b/svx/source/table/tablertfimporter.cxx
new file mode 100644
index 000000000000..7f8b42d95d6b
--- /dev/null
+++ b/svx/source/table/tablertfimporter.cxx
@@ -0,0 +1,455 @@
+/*************************************************************************
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: tablertfimporter.cxx,v $
+ *
+ * $Revision: 1.2 $
+ *
+ * last change: $Author: rt $ $Date: 2008-03-12 10:06:48 $
+ *
+ * The Contents of this file are made available subject to
+ * the terms of GNU Lesser General Public License Version 2.1.
+ *
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2005 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
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_svx.hxx"
+
+#include <vector>
+#include <boost/shared_ptr.hpp>
+
+#include <com/sun/star/table/XTable.hpp>
+
+#include <tools/stream.hxx>
+#include <svtools/rtftoken.h>
+
+#include <svx/eeitem.hxx>
+#include <svx/svdetc.hxx>
+#include <svx/fhgtitem.hxx>
+#include <svx/outlobj.hxx>
+
+#include "cell.hxx"
+#include "celltypes.hxx"
+#include "svx/svdotable.hxx"
+#include "svx/svdoutl.hxx"
+#include "svx/editeng.hxx"
+#include "svx/editdata.hxx"
+#include "svx/svdmodel.hxx"
+#include "svxrtf.hxx"
+
+using ::rtl::OUString;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::table;
+using namespace ::com::sun::star::container;
+using namespace ::com::sun::star::beans;
+
+namespace sdr { namespace table {
+
+struct RTFCellDefault
+{
+ SfxItemSet maItemSet;
+ sal_Int32 mnCol;
+ USHORT mnTwips; // right border of the cell
+ sal_Int32 mnColSpan; // MergeCell if >1, merged cells if 0
+
+ RTFCellDefault( SfxItemPool* pPool ) : maItemSet( *pPool ), mnCol(0), mnTwips(0 ), mnColSpan(1) {}
+};
+
+typedef std::vector< boost::shared_ptr< RTFCellDefault > > RTFCellDefaultVector;
+
+struct RTFCellInfo
+{
+ SfxItemSet maItemSet;
+ sal_Int32 mnStartPara;
+ sal_Int32 mnParaCount;
+ sal_Int32 mnColSpan;
+
+ RTFCellInfo( SfxItemPool& rPool ) : maItemSet( rPool ), mnStartPara(0), mnParaCount(0), mnColSpan(0) {}
+};
+
+typedef boost::shared_ptr< RTFCellInfo > RTFCellInfoPtr;
+typedef std::vector< RTFCellInfoPtr > RTFColumnVector;
+
+typedef boost::shared_ptr< RTFColumnVector > RTFColumnVectorPtr;
+
+typedef std::vector< RTFColumnVectorPtr > RTFRowVector;
+
+class SdrTableRTFParser
+{
+public:
+ SdrTableRTFParser( SdrTableObj& rTableObj );
+ ~SdrTableRTFParser();
+
+ void Read( SvStream& rStream );
+
+ void ProcToken( ImportInfo* pInfo );
+
+ void NextRow();
+ void NextColumn();
+ void NewCellRow();
+
+ void InsertCell( ImportInfo* pInfo );
+
+ void FillTable();
+
+ DECL_LINK( RTFImportHdl, ImportInfo* );
+
+private:
+ SdrTableObj& mrTableObj;
+ SdrOutliner* mpOutliner;
+ SfxItemPool& mrItemPool;
+
+ RTFCellDefaultVector maDefaultList;
+ RTFCellDefaultVector::iterator maDefaultIterator;
+
+ int mnLastToken;
+ sal_Int32 mnLastWidth;
+ bool mbNewDef;
+
+ USHORT mnStartPara;
+
+ sal_Int32 mnColCnt;
+ sal_Int32 mnRowCnt;
+ sal_Int32 mnColMax;
+
+ std::vector< sal_Int32 > maColumnEdges;
+
+ RTFRowVector maRows;
+
+ RTFCellDefault* mpInsDefault;
+ RTFCellDefault* mpActDefault;
+ RTFCellDefault* mpDefMerge;
+
+ Reference< XTable > mxTable;
+};
+
+SdrTableRTFParser::SdrTableRTFParser( SdrTableObj& rTableObj )
+: mrTableObj( rTableObj )
+, mpOutliner( SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, rTableObj.GetModel() ) )
+, mrItemPool( rTableObj.GetModel()->GetItemPool() )
+, mnLastToken( 0 )
+, mnLastWidth( 0 )
+, mbNewDef( false )
+, mnStartPara( 0 )
+, mnColCnt( 0 )
+, mnRowCnt( 0 )
+, mnColMax( 0 )
+, mpActDefault( 0 )
+, mpDefMerge( 0 )
+, mxTable( rTableObj.getTable() )
+{
+ mpOutliner->SetUpdateMode(TRUE);
+ mpOutliner->SetStyleSheet( 0, mrTableObj.GetStyleSheet() );
+ mpInsDefault = new RTFCellDefault( &mrItemPool );
+}
+
+SdrTableRTFParser::~SdrTableRTFParser()
+{
+ delete mpOutliner;
+ delete mpInsDefault;
+}
+
+void SdrTableRTFParser::Read( SvStream& rStream )
+{
+ EditEngine& rEdit = const_cast< EditEngine& >( mpOutliner->GetEditEngine() );
+
+ Link aOldLink( rEdit.GetImportHdl() );
+ rEdit.SetImportHdl( LINK( this, SdrTableRTFParser, RTFImportHdl ) );
+ mpOutliner->Read( rStream, String(), EE_FORMAT_RTF );
+ rEdit.SetImportHdl( aOldLink );
+
+ FillTable();
+}
+
+IMPL_LINK( SdrTableRTFParser, RTFImportHdl, ImportInfo*, pInfo )
+{
+ switch ( pInfo->eState )
+ {
+ case RTFIMP_NEXTTOKEN:
+ ProcToken( pInfo );
+ break;
+ case RTFIMP_UNKNOWNATTR:
+ ProcToken( pInfo );
+ break;
+ case RTFIMP_START:
+ {
+ SvxRTFParser* pParser = (SvxRTFParser*) pInfo->pParser;
+ pParser->SetAttrPool( &mrItemPool );
+ RTFPardAttrMapIds& rMap = pParser->GetPardMap();
+ rMap.nBox = SDRATTR_TABLE_BORDER;
+ }
+ break;
+ case RTFIMP_END:
+ if ( pInfo->aSelection.nEndPos )
+ {
+ mpActDefault = NULL;
+ pInfo->nToken = RTF_PAR;
+ pInfo->aSelection.nEndPara++;
+ ProcToken( pInfo );
+ }
+ break;
+ case RTFIMP_SETATTR:
+ break;
+ case RTFIMP_INSERTTEXT:
+ break;
+ case RTFIMP_INSERTPARA:
+ break;
+ default:
+ DBG_ERRORFILE("unknown ImportInfo.eState");
+ }
+ return 0;
+}
+
+void SdrTableRTFParser::NextRow()
+{
+ ++mnRowCnt;
+}
+
+void SdrTableRTFParser::InsertCell( ImportInfo* pInfo )
+{
+ sal_Int32 nCol = mpActDefault->mnCol;
+
+ RTFCellInfoPtr xCellInfo( new RTFCellInfo(mrItemPool) );
+
+ xCellInfo->mnStartPara = mnStartPara;
+ xCellInfo->mnParaCount = pInfo->aSelection.nEndPara - 1 - mnStartPara;
+
+ if( !maRows.empty() )
+ {
+ RTFColumnVectorPtr xColumn( maRows.back() );
+
+ if( xColumn->size() <= (size_t)nCol )
+ xColumn->resize( nCol+1 );
+
+ (*xColumn)[nCol] = xCellInfo;
+ }
+
+ mnStartPara = pInfo->aSelection.nEndPara - 1;
+}
+
+void SdrTableRTFParser::FillTable()
+{
+ try
+ {
+ sal_Int32 nColCount = mxTable->getColumnCount();
+ Reference< XTableColumns > xCols( mxTable->getColumns(), UNO_QUERY_THROW );
+
+ if( nColCount < mnColMax )
+ {
+ xCols->insertByIndex( nColCount, mnColMax - nColCount );
+ nColCount = mxTable->getColumnCount();
+ }
+
+ const OUString sWidth( RTL_CONSTASCII_USTRINGPARAM("Width") );
+ sal_Int32 nCol, nLastEdge = 0;
+ for( nCol = 0; nCol < nColCount; nCol++ )
+ {
+ Reference< XPropertySet > xSet( xCols->getByIndex( nCol ), UNO_QUERY_THROW );
+ sal_Int32 nWidth = maColumnEdges[nCol] - nLastEdge;
+
+ xSet->setPropertyValue( sWidth, Any( nWidth ) );
+ nLastEdge += nWidth;
+ }
+
+ const sal_Int32 nRowCount = mxTable->getRowCount();
+ if( nRowCount < mnRowCnt )
+ {
+ Reference< XTableRows > xRows( mxTable->getRows(), UNO_QUERY_THROW );
+ xRows->insertByIndex( nRowCount, mnRowCnt - nRowCount );
+ }
+
+ for( sal_Int32 nRow = 0; nRow < (sal_Int32)maRows.size(); nRow++ )
+ {
+ RTFColumnVectorPtr xColumn( maRows[nRow] );
+ for( nCol = 0; nCol < (sal_Int32)xColumn->size(); nCol++ )
+ {
+ RTFCellInfoPtr xCellInfo( (*xColumn)[nCol] );
+
+ CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
+ if( xCell.is() )
+ {
+ const SfxPoolItem *pPoolItem = 0;
+ if( xCellInfo->maItemSet.GetItemState(SDRATTR_TABLE_BORDER,FALSE,&pPoolItem)==SFX_ITEM_SET)
+ xCell->SetMergedItem( *pPoolItem );
+
+ String sDebug = mpOutliner->GetText( mpOutliner->GetParagraph( xCellInfo->mnStartPara ), xCellInfo->mnParaCount );
+
+ OutlinerParaObject* pTextObject = mpOutliner->CreateParaObject( (USHORT)xCellInfo->mnStartPara, (USHORT)xCellInfo->mnParaCount );
+ if( pTextObject )
+ {
+ SdrOutliner& rOutliner=mrTableObj.ImpGetDrawOutliner();
+ rOutliner.SetUpdateMode(TRUE);
+ rOutliner.SetText( *pTextObject );
+ mrTableObj.NbcSetOutlinerParaObjectForText( rOutliner.CreateParaObject(), xCell.get() );
+ delete pTextObject;
+ }
+ }
+ }
+ }
+
+ Rectangle aRect( mrTableObj.GetSnapRect() );
+ aRect.nRight = aRect.nLeft + nLastEdge;
+ mrTableObj.NbcSetSnapRect( aRect );
+
+ }
+ catch( Exception& e )
+ {
+ (void)e;
+ DBG_ERROR("sdr::table::SdrTableRTFParser::InsertCell(), exception caught!" );
+ }
+}
+
+void SdrTableRTFParser::NewCellRow()
+{
+ if( mbNewDef )
+ {
+ mbNewDef = FALSE;
+
+ maRows.push_back( RTFColumnVectorPtr( new RTFColumnVector() ) );
+ }
+ mpDefMerge = NULL;
+ maDefaultIterator = maDefaultList.begin();
+
+ NextColumn();
+
+ DBG_ASSERT( mpActDefault, "NewCellRow: pActDefault==0" );
+}
+
+void SdrTableRTFParser::NextColumn()
+{
+ if( maDefaultIterator != maDefaultList.end() )
+ mpActDefault = (*maDefaultIterator++).get();
+ else
+ mpActDefault = 0;
+}
+
+long TwipsToHundMM( long nIn )
+{
+ long nRet = OutputDevice::LogicToLogic( nIn, MAP_TWIP, MAP_100TH_MM );
+ return nRet;
+}
+
+void SdrTableRTFParser::ProcToken( ImportInfo* pInfo )
+{
+ switch ( pInfo->nToken )
+ {
+ case RTF_TROWD: // denotes table row defauls, before RTF_CELLX
+ {
+ mnColCnt = 0;
+ maDefaultList.clear();
+ mpDefMerge = NULL;
+ mnLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_CLMGF: // The first cell of cells to be merged
+ {
+ mpDefMerge = mpInsDefault;
+ mnLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_CLMRG: // A cell to be merged with the preceding cell
+ {
+ if ( !mpDefMerge )
+ mpDefMerge = maDefaultList.back().get();
+ DBG_ASSERT( mpDefMerge, "RTF_CLMRG: pDefMerge==0" );
+ if( mpDefMerge )
+ mpDefMerge->mnColSpan++;
+ mpInsDefault->mnColSpan = 0;
+ mnLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_CELLX: // closes cell default
+ {
+ mbNewDef = TRUE;
+ mpInsDefault->mnCol = mnColCnt;
+ maDefaultList.push_back( boost::shared_ptr< RTFCellDefault >( mpInsDefault ) );
+
+ if( (sal_Int32)maColumnEdges.size() <= mnColCnt )
+ maColumnEdges.resize( mnColCnt + 1 );
+
+ const sal_Int32 nSize = TwipsToHundMM( pInfo->nTokenValue );
+ maColumnEdges[mnColCnt] = std::max( maColumnEdges[mnColCnt], nSize );
+
+ mpInsDefault = new RTFCellDefault( &mrItemPool );
+ if ( ++mnColCnt > mnColMax )
+ mnColMax = mnColCnt;
+ mnLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_INTBL: // before the first RTF_CELL
+ {
+ if ( mnLastToken != RTF_INTBL && mnLastToken != RTF_CELL && mnLastToken != RTF_PAR )
+ {
+ NewCellRow();
+ mnLastToken = pInfo->nToken;
+ }
+ }
+ break;
+ case RTF_CELL: // denotes the end of a cell.
+ {
+ DBG_ASSERT( mpActDefault, "RTF_CELL: pActDefault==0" );
+ if ( mbNewDef || !mpActDefault )
+ NewCellRow();
+ if ( !mpActDefault )
+ mpActDefault = mpInsDefault;
+ if ( mpActDefault->mnColSpan > 0 )
+ {
+ InsertCell(pInfo);
+ }
+ NextColumn();
+ mnLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_ROW: // means the end of a row
+ {
+ NextRow();
+ mnLastToken = pInfo->nToken;
+ }
+ break;
+ case RTF_PAR: // Paragraph
+ mnLastToken = pInfo->nToken;
+ break;
+ default:
+ { // do not set nLastToken
+ switch ( pInfo->nToken & ~(0xff | RTF_TABLEDEF) )
+ {
+ case RTF_SHADINGDEF:
+// ((SvxRTFParser*)pInfo->pParser)->ReadBackgroundAttr(pInfo->nToken, mpInsDefault->maItemSet, TRUE );
+ break;
+ case RTF_BRDRDEF:
+ ((SvxRTFParser*)pInfo->pParser)->ReadBorderAttr(pInfo->nToken, mpInsDefault->maItemSet, TRUE );
+ break;
+ }
+ }
+ }
+}
+
+void SdrTableObj::ImportAsRTF( SvStream& rStream, SdrTableObj& rObj )
+{
+ SdrTableRTFParser aParser( rObj );
+ aParser.Read( rStream );
+}
+
+} }
+