bump product version to 5.0.4.1
[LibreOffice.git] / svx / source / table / tablertfimporter.cxx
blobe0c83401f254640fb89e4390a0121ca67e30faa0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vector>
22 #include <boost/scoped_ptr.hpp>
23 #include <boost/shared_ptr.hpp>
25 #include <com/sun/star/table/XTable.hpp>
27 #include <tools/stream.hxx>
28 #include <svtools/rtftoken.h>
30 #include <editeng/eeitem.hxx>
31 #include <svx/svdetc.hxx>
32 #include <editeng/fhgtitem.hxx>
33 #include <editeng/outlobj.hxx>
35 #include "cell.hxx"
36 #include "celltypes.hxx"
37 #include "svx/svdotable.hxx"
38 #include "svx/svdoutl.hxx"
39 #include "editeng/editeng.hxx"
40 #include "editeng/editdata.hxx"
41 #include "svx/svdmodel.hxx"
42 #include "editeng/svxrtf.hxx"
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::table;
46 using namespace ::com::sun::star::container;
47 using namespace ::com::sun::star::beans;
49 namespace sdr { namespace table {
51 struct RTFCellDefault
53 SfxItemSet maItemSet;
54 sal_Int32 mnCol;
55 sal_uInt16 mnTwips; // right border of the cell
56 sal_Int32 mnColSpan; // MergeCell if >1, merged cells if 0
58 RTFCellDefault( SfxItemPool* pPool ) : maItemSet( *pPool ), mnCol(0), mnTwips(0 ), mnColSpan(1) {}
61 typedef std::vector< boost::shared_ptr< RTFCellDefault > > RTFCellDefaultVector;
63 struct RTFCellInfo
65 SfxItemSet maItemSet;
66 sal_Int32 mnStartPara;
67 sal_Int32 mnParaCount;
68 sal_Int32 mnColSpan;
70 RTFCellInfo( SfxItemPool& rPool ) : maItemSet( rPool ), mnStartPara(0), mnParaCount(0), mnColSpan(0) {}
73 typedef boost::shared_ptr< RTFCellInfo > RTFCellInfoPtr;
74 typedef std::vector< RTFCellInfoPtr > RTFColumnVector;
76 typedef boost::shared_ptr< RTFColumnVector > RTFColumnVectorPtr;
78 typedef std::vector< RTFColumnVectorPtr > RTFRowVector;
80 class SdrTableRTFParser
82 public:
83 SdrTableRTFParser( SdrTableObj& rTableObj );
84 ~SdrTableRTFParser();
86 void Read( SvStream& rStream );
88 void ProcToken( ImportInfo* pInfo );
90 void NextRow();
91 void NextColumn();
92 void NewCellRow();
94 void InsertCell( ImportInfo* pInfo );
96 void FillTable();
98 DECL_LINK( RTFImportHdl, ImportInfo* );
100 private:
101 SdrTableObj& mrTableObj;
102 SdrOutliner* mpOutliner;
103 SfxItemPool& mrItemPool;
105 RTFCellDefaultVector maDefaultList;
106 RTFCellDefaultVector::iterator maDefaultIterator;
108 int mnLastToken;
109 bool mbNewDef;
111 sal_Int32 mnStartPara;
113 sal_Int32 mnColCnt;
114 sal_Int32 mnRowCnt;
115 sal_Int32 mnColMax;
117 std::vector< sal_Int32 > maColumnEdges;
119 RTFRowVector maRows;
121 RTFCellDefault* mpInsDefault;
122 RTFCellDefault* mpActDefault;
123 RTFCellDefault* mpDefMerge;
125 Reference< XTable > mxTable;
128 SdrTableRTFParser::SdrTableRTFParser( SdrTableObj& rTableObj )
129 : mrTableObj( rTableObj )
130 , mpOutliner( SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, *rTableObj.GetModel() ) )
131 , mrItemPool( rTableObj.GetModel()->GetItemPool() )
132 , mnLastToken( 0 )
133 , mbNewDef( false )
134 , mnStartPara( 0 )
135 , mnColCnt( 0 )
136 , mnRowCnt( 0 )
137 , mnColMax( 0 )
138 , mpActDefault( 0 )
139 , mpDefMerge( 0 )
140 , mxTable( rTableObj.getTable() )
142 mpOutliner->SetUpdateMode(true);
143 mpOutliner->SetStyleSheet( 0, mrTableObj.GetStyleSheet() );
144 mpInsDefault = new RTFCellDefault( &mrItemPool );
147 SdrTableRTFParser::~SdrTableRTFParser()
149 delete mpOutliner;
150 delete mpInsDefault;
153 void SdrTableRTFParser::Read( SvStream& rStream )
155 EditEngine& rEdit = const_cast< EditEngine& >( mpOutliner->GetEditEngine() );
157 Link<> aOldLink( rEdit.GetImportHdl() );
158 rEdit.SetImportHdl( LINK( this, SdrTableRTFParser, RTFImportHdl ) );
159 mpOutliner->Read( rStream, OUString(), EE_FORMAT_RTF );
160 rEdit.SetImportHdl( aOldLink );
162 FillTable();
165 IMPL_LINK( SdrTableRTFParser, RTFImportHdl, ImportInfo*, pInfo )
167 switch ( pInfo->eState )
169 case RTFIMP_NEXTTOKEN:
170 ProcToken( pInfo );
171 break;
172 case RTFIMP_UNKNOWNATTR:
173 ProcToken( pInfo );
174 break;
175 case RTFIMP_START:
177 SvxRTFParser* pParser = static_cast<SvxRTFParser*>(pInfo->pParser);
178 pParser->SetAttrPool( &mrItemPool );
179 RTFPardAttrMapIds& rMap = pParser->GetPardMap();
180 rMap.nBox = SDRATTR_TABLE_BORDER;
182 break;
183 case RTFIMP_END:
184 if ( pInfo->aSelection.nEndPos )
186 mpActDefault = NULL;
187 pInfo->nToken = RTF_PAR;
188 pInfo->aSelection.nEndPara++;
189 ProcToken( pInfo );
191 break;
192 case RTFIMP_SETATTR:
193 break;
194 case RTFIMP_INSERTTEXT:
195 break;
196 case RTFIMP_INSERTPARA:
197 break;
198 default:
199 SAL_WARN( "svx.table","unknown ImportInfo.eState");
201 return 0;
204 void SdrTableRTFParser::NextRow()
206 ++mnRowCnt;
209 void SdrTableRTFParser::InsertCell( ImportInfo* pInfo )
211 sal_Int32 nCol = mpActDefault->mnCol;
213 RTFCellInfoPtr xCellInfo( new RTFCellInfo(mrItemPool) );
215 xCellInfo->mnStartPara = mnStartPara;
216 xCellInfo->mnParaCount = pInfo->aSelection.nEndPara - 1 - mnStartPara;
218 if( !maRows.empty() )
220 RTFColumnVectorPtr xColumn( maRows.back() );
222 if( xColumn->size() <= (size_t)nCol )
223 xColumn->resize( nCol+1 );
225 (*xColumn)[nCol] = xCellInfo;
228 mnStartPara = pInfo->aSelection.nEndPara - 1;
231 void SdrTableRTFParser::FillTable()
235 sal_Int32 nColCount = mxTable->getColumnCount();
236 Reference< XTableColumns > xCols( mxTable->getColumns(), UNO_QUERY_THROW );
238 if( nColCount < mnColMax )
240 xCols->insertByIndex( nColCount, mnColMax - nColCount );
241 nColCount = mxTable->getColumnCount();
244 const OUString sWidth("Width");
245 sal_Int32 nCol, nLastEdge = 0;
246 for( nCol = 0; nCol < nColCount; nCol++ )
248 Reference< XPropertySet > xSet( xCols->getByIndex( nCol ), UNO_QUERY_THROW );
249 sal_Int32 nWidth = maColumnEdges[nCol] - nLastEdge;
251 xSet->setPropertyValue( sWidth, Any( nWidth ) );
252 nLastEdge += nWidth;
255 const sal_Int32 nRowCount = mxTable->getRowCount();
256 if( nRowCount < mnRowCnt )
258 Reference< XTableRows > xRows( mxTable->getRows(), UNO_QUERY_THROW );
259 xRows->insertByIndex( nRowCount, mnRowCnt - nRowCount );
262 for( sal_Int32 nRow = 0; nRow < (sal_Int32)maRows.size(); nRow++ )
264 RTFColumnVectorPtr xColumn( maRows[nRow] );
265 for( nCol = 0; nCol < (sal_Int32)xColumn->size(); nCol++ )
267 RTFCellInfoPtr xCellInfo( (*xColumn)[nCol] );
269 CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
270 if( xCell.is() && xCellInfo.get() )
272 const SfxPoolItem *pPoolItem = 0;
273 if( xCellInfo->maItemSet.GetItemState(SDRATTR_TABLE_BORDER,false,&pPoolItem)==SfxItemState::SET)
274 xCell->SetMergedItem( *pPoolItem );
276 boost::scoped_ptr<OutlinerParaObject> pTextObject(mpOutliner->CreateParaObject( xCellInfo->mnStartPara, xCellInfo->mnParaCount ));
277 if( pTextObject )
279 SdrOutliner& rOutliner=mrTableObj.ImpGetDrawOutliner();
280 rOutliner.SetUpdateMode(true);
281 rOutliner.SetText( *pTextObject );
282 mrTableObj.NbcSetOutlinerParaObjectForText( rOutliner.CreateParaObject(), xCell.get() );
288 Rectangle aRect( mrTableObj.GetSnapRect() );
289 aRect.Right() = aRect.Left() + nLastEdge;
290 mrTableObj.NbcSetSnapRect( aRect );
293 catch( Exception& e )
295 (void)e;
296 OSL_FAIL("sdr::table::SdrTableRTFParser::InsertCell(), exception caught!" );
300 void SdrTableRTFParser::NewCellRow()
302 if( mbNewDef )
304 mbNewDef = false;
306 maRows.push_back( RTFColumnVectorPtr( new RTFColumnVector() ) );
308 mpDefMerge = NULL;
309 maDefaultIterator = maDefaultList.begin();
311 NextColumn();
313 DBG_ASSERT( mpActDefault, "NewCellRow: pActDefault==0" );
316 void SdrTableRTFParser::NextColumn()
318 if( maDefaultIterator != maDefaultList.end() )
319 mpActDefault = (*maDefaultIterator++).get();
320 else
321 mpActDefault = 0;
324 long TwipsToHundMM( long nIn )
326 long nRet = OutputDevice::LogicToLogic( nIn, MAP_TWIP, MAP_100TH_MM );
327 return nRet;
330 void SdrTableRTFParser::ProcToken( ImportInfo* pInfo )
332 switch ( pInfo->nToken )
334 case RTF_TROWD: // denotes table row defauls, before RTF_CELLX
336 mnColCnt = 0;
337 maDefaultList.clear();
338 mpDefMerge = NULL;
339 mnLastToken = pInfo->nToken;
341 break;
342 case RTF_CLMGF: // The first cell of cells to be merged
344 mpDefMerge = mpInsDefault;
345 mnLastToken = pInfo->nToken;
347 break;
348 case RTF_CLMRG: // A cell to be merged with the preceding cell
350 if ( !mpDefMerge )
351 mpDefMerge = maDefaultList.back().get();
352 DBG_ASSERT( mpDefMerge, "RTF_CLMRG: pDefMerge==0" );
353 if( mpDefMerge )
354 mpDefMerge->mnColSpan++;
355 mpInsDefault->mnColSpan = 0;
356 mnLastToken = pInfo->nToken;
358 break;
359 case RTF_CELLX: // closes cell default
361 mbNewDef = true;
362 mpInsDefault->mnCol = mnColCnt;
363 maDefaultList.push_back( boost::shared_ptr< RTFCellDefault >( mpInsDefault ) );
365 if( (sal_Int32)maColumnEdges.size() <= mnColCnt )
366 maColumnEdges.resize( mnColCnt + 1 );
368 const sal_Int32 nSize = TwipsToHundMM( pInfo->nTokenValue );
369 maColumnEdges[mnColCnt] = std::max( maColumnEdges[mnColCnt], nSize );
371 mpInsDefault = new RTFCellDefault( &mrItemPool );
372 if ( ++mnColCnt > mnColMax )
373 mnColMax = mnColCnt;
374 mnLastToken = pInfo->nToken;
376 break;
377 case RTF_INTBL: // before the first RTF_CELL
379 if ( mnLastToken != RTF_INTBL && mnLastToken != RTF_CELL && mnLastToken != RTF_PAR )
381 NewCellRow();
382 mnLastToken = pInfo->nToken;
385 break;
386 case RTF_CELL: // denotes the end of a cell.
388 DBG_ASSERT( mpActDefault, "RTF_CELL: pActDefault==0" );
389 if ( mbNewDef || !mpActDefault )
390 NewCellRow();
391 if ( !mpActDefault )
392 mpActDefault = mpInsDefault;
393 if ( mpActDefault->mnColSpan > 0 )
395 InsertCell(pInfo);
397 NextColumn();
398 mnLastToken = pInfo->nToken;
400 break;
401 case RTF_ROW: // means the end of a row
403 NextRow();
404 mnLastToken = pInfo->nToken;
406 break;
407 case RTF_PAR: // Paragraph
408 mnLastToken = pInfo->nToken;
409 break;
410 default:
411 { // do not set nLastToken
412 switch ( pInfo->nToken & ~(0xff | RTF_TABLEDEF) )
414 case RTF_SHADINGDEF:
415 // ((SvxRTFParser*)pInfo->pParser)->ReadBackgroundAttr(pInfo->nToken, mpInsDefault->maItemSet, sal_True );
416 break;
417 case RTF_BRDRDEF:
418 static_cast<SvxRTFParser*>(pInfo->pParser)->ReadBorderAttr(pInfo->nToken, mpInsDefault->maItemSet, true );
419 break;
425 void SdrTableObj::ImportAsRTF( SvStream& rStream, SdrTableObj& rObj )
427 SdrTableRTFParser aParser( rObj );
428 aParser.Read( rStream );
433 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */