/************************************************************************* * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2008 by Sun Microsystems, Inc. * * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: tablertfimporter.cxx,v $ * $Revision: 1.4 $ * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_svx.hxx" #include #include #include #include #include #include #include #include #include #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() && xCellInfo.get() ) { 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 ); } } }