1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svx.hxx"
26 
27 #include <vector>
28 #include <boost/shared_ptr.hpp>
29 
30 #include <com/sun/star/table/XTable.hpp>
31 
32 #include <tools/stream.hxx>
33 #include <svtools/rtftoken.h>
34 
35 #include <editeng/eeitem.hxx>
36 #include <svx/svdetc.hxx>
37 #include <editeng/fhgtitem.hxx>
38 #include <editeng/outlobj.hxx>
39 
40 #include "cell.hxx"
41 #include "celltypes.hxx"
42 #include "svx/svdotable.hxx"
43 #include "svx/svdoutl.hxx"
44 #include "editeng/editeng.hxx"
45 #include "editeng/editdata.hxx"
46 #include "svx/svdmodel.hxx"
47 #include "editeng/svxrtf.hxx"
48 
49 using ::rtl::OUString;
50 using namespace ::com::sun::star::uno;
51 using namespace ::com::sun::star::table;
52 using namespace ::com::sun::star::container;
53 using namespace ::com::sun::star::beans;
54 
55 namespace sdr { namespace table {
56 
57 struct RTFCellDefault
58 {
59 	SfxItemSet			maItemSet;
60 	sal_Int32			mnCol;
61 	sal_uInt16				mnTwips;         // right border of the cell
62 	sal_Int32			mnColSpan;	 // MergeCell if >1, merged cells if 0
63 
RTFCellDefaultsdr::table::RTFCellDefault64 	RTFCellDefault( SfxItemPool* pPool ) : maItemSet( *pPool ), mnCol(0), mnTwips(0 ), mnColSpan(1) {}
65 };
66 
67 typedef std::vector< boost::shared_ptr< RTFCellDefault > > RTFCellDefaultVector;
68 
69 struct RTFCellInfo
70 {
71 	SfxItemSet			maItemSet;
72 	sal_Int32			mnStartPara;
73 	sal_Int32			mnParaCount;
74 	sal_Int32			mnColSpan;
75 
RTFCellInfosdr::table::RTFCellInfo76 	RTFCellInfo( SfxItemPool& rPool ) : maItemSet(  rPool ), mnStartPara(0), mnParaCount(0), mnColSpan(0) {}
77 };
78 
79 typedef boost::shared_ptr< RTFCellInfo > RTFCellInfoPtr;
80 typedef std::vector< RTFCellInfoPtr > RTFColumnVector;
81 
82 typedef boost::shared_ptr< RTFColumnVector > RTFColumnVectorPtr;
83 
84 typedef std::vector< RTFColumnVectorPtr > RTFRowVector;
85 
86 class SdrTableRTFParser
87 {
88 public:
89 	SdrTableRTFParser( SdrTableObj& rTableObj );
90 	~SdrTableRTFParser();
91 
92 	void Read( SvStream& rStream );
93 
94 	void ProcToken( ImportInfo* pInfo );
95 
96 	void NextRow();
97 	void NextColumn();
98 	void NewCellRow();
99 
100 	void InsertCell( ImportInfo* pInfo );
101 
102 	void FillTable();
103 
104 	DECL_LINK( RTFImportHdl, ImportInfo* );
105 
106 private:
107 	SdrTableObj&	mrTableObj;
108 	SdrOutliner*	mpOutliner;
109 	SfxItemPool&	mrItemPool;
110 
111 	RTFCellDefaultVector maDefaultList;
112 	RTFCellDefaultVector::iterator maDefaultIterator;
113 
114 	int				mnLastToken;
115 	sal_Int32		mnLastWidth;
116 	bool			mbNewDef;
117 
118 	sal_uInt16			mnStartPara;
119 
120 	sal_Int32		mnColCnt;
121 	sal_Int32		mnRowCnt;
122 	sal_Int32		mnColMax;
123 
124 	std::vector< sal_Int32 > maColumnEdges;
125 
126 	RTFRowVector	maRows;
127 
128 	RTFCellDefault*	mpInsDefault;
129 	RTFCellDefault*	mpActDefault;
130 	RTFCellDefault*	mpDefMerge;
131 
132 	Reference< XTable > mxTable;
133 };
134 
SdrTableRTFParser(SdrTableObj & rTableObj)135 SdrTableRTFParser::SdrTableRTFParser( SdrTableObj& rTableObj )
136 : mrTableObj( rTableObj )
137 , mpOutliner( SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT, rTableObj.GetModel() ) )
138 , mrItemPool( rTableObj.GetModel()->GetItemPool() )
139 , mnLastToken( 0 )
140 , mnLastWidth( 0 )
141 , mbNewDef( false )
142 , mnStartPara( 0 )
143 , mnColCnt( 0 )
144 , mnRowCnt( 0 )
145 , mnColMax( 0 )
146 , mpActDefault( 0 )
147 , mpDefMerge( 0 )
148 , mxTable( rTableObj.getTable() )
149 {
150 	mpOutliner->SetUpdateMode(sal_True);
151 	mpOutliner->SetStyleSheet( 0, mrTableObj.GetStyleSheet() );
152 	mpInsDefault = new RTFCellDefault( &mrItemPool );
153 }
154 
~SdrTableRTFParser()155 SdrTableRTFParser::~SdrTableRTFParser()
156 {
157 	delete mpOutliner;
158 	delete mpInsDefault;
159 }
160 
Read(SvStream & rStream)161 void SdrTableRTFParser::Read( SvStream& rStream )
162 {
163 	EditEngine& rEdit = const_cast< EditEngine& >( mpOutliner->GetEditEngine() );
164 
165 	Link aOldLink( rEdit.GetImportHdl() );
166 	rEdit.SetImportHdl( LINK( this, SdrTableRTFParser, RTFImportHdl ) );
167 	mpOutliner->Read( rStream, String(), EE_FORMAT_RTF );
168 	rEdit.SetImportHdl( aOldLink );
169 
170 	FillTable();
171 }
172 
IMPL_LINK(SdrTableRTFParser,RTFImportHdl,ImportInfo *,pInfo)173 IMPL_LINK( SdrTableRTFParser, RTFImportHdl, ImportInfo*, pInfo )
174 {
175 	switch ( pInfo->eState )
176 	{
177 		case RTFIMP_NEXTTOKEN:
178 			ProcToken( pInfo );
179 			break;
180 		case RTFIMP_UNKNOWNATTR:
181 			ProcToken( pInfo );
182 			break;
183 		case RTFIMP_START:
184 		{
185 			SvxRTFParser* pParser = (SvxRTFParser*) pInfo->pParser;
186 			pParser->SetAttrPool( &mrItemPool );
187 			RTFPardAttrMapIds& rMap = pParser->GetPardMap();
188 			rMap.nBox = SDRATTR_TABLE_BORDER;
189 		}
190 			break;
191 		case RTFIMP_END:
192 			if ( pInfo->aSelection.nEndPos )
193 			{
194 				mpActDefault = NULL;
195 				pInfo->nToken = RTF_PAR;
196 				pInfo->aSelection.nEndPara++;
197 				ProcToken( pInfo );
198 			}
199 			break;
200 		case RTFIMP_SETATTR:
201 			break;
202 		case RTFIMP_INSERTTEXT:
203 			break;
204 		case RTFIMP_INSERTPARA:
205 			break;
206 		default:
207 			DBG_ERRORFILE("unknown ImportInfo.eState");
208 	}
209 	return 0;
210 }
211 
NextRow()212 void SdrTableRTFParser::NextRow()
213 {
214 	++mnRowCnt;
215 }
216 
InsertCell(ImportInfo * pInfo)217 void SdrTableRTFParser::InsertCell( ImportInfo* pInfo )
218 {
219 	sal_Int32 nCol = mpActDefault->mnCol;
220 
221 	RTFCellInfoPtr xCellInfo( new RTFCellInfo(mrItemPool) );
222 
223 	xCellInfo->mnStartPara = mnStartPara;
224 	xCellInfo->mnParaCount = pInfo->aSelection.nEndPara - 1 - mnStartPara;
225 
226 	if( !maRows.empty() )
227 	{
228 		RTFColumnVectorPtr xColumn( maRows.back() );
229 
230 		if( xColumn->size() <= (size_t)nCol )
231 			xColumn->resize( nCol+1 );
232 
233 		(*xColumn)[nCol] = xCellInfo;
234 	}
235 
236 	mnStartPara = pInfo->aSelection.nEndPara - 1;
237 }
238 
FillTable()239 void SdrTableRTFParser::FillTable()
240 {
241 	try
242 	{
243 		sal_Int32 nColCount = mxTable->getColumnCount();
244 		Reference< XTableColumns > xCols( mxTable->getColumns(), UNO_QUERY_THROW );
245 
246 		if( nColCount < mnColMax )
247 		{
248 			xCols->insertByIndex( nColCount, mnColMax - nColCount );
249 			nColCount = mxTable->getColumnCount();
250 		}
251 
252 		const OUString sWidth( RTL_CONSTASCII_USTRINGPARAM("Width") );
253 		sal_Int32 nCol, nLastEdge = 0;
254 		for( nCol = 0; nCol < nColCount; nCol++ )
255 		{
256 			Reference< XPropertySet > xSet( xCols->getByIndex( nCol ), UNO_QUERY_THROW );
257 			sal_Int32 nWidth = maColumnEdges[nCol] - nLastEdge;
258 
259 			xSet->setPropertyValue( sWidth, Any( nWidth ) );
260 			nLastEdge += nWidth;
261 		}
262 
263 		const sal_Int32 nRowCount = mxTable->getRowCount();
264 		if( nRowCount < mnRowCnt )
265 		{
266 			Reference< XTableRows > xRows( mxTable->getRows(), UNO_QUERY_THROW );
267 			xRows->insertByIndex( nRowCount, mnRowCnt - nRowCount );
268 		}
269 
270 		for( sal_Int32 nRow = 0; nRow < (sal_Int32)maRows.size(); nRow++ )
271 		{
272 			RTFColumnVectorPtr xColumn( maRows[nRow] );
273 			for( nCol = 0; nCol < (sal_Int32)xColumn->size(); nCol++ )
274 			{
275 				RTFCellInfoPtr xCellInfo( (*xColumn)[nCol] );
276 
277 				CellRef xCell( dynamic_cast< Cell* >( mxTable->getCellByPosition( nCol, nRow ).get() ) );
278 				if( xCell.is() && xCellInfo.get() )
279 				{
280 					const SfxPoolItem *pPoolItem = 0;
281 					if( xCellInfo->maItemSet.GetItemState(SDRATTR_TABLE_BORDER,sal_False,&pPoolItem)==SFX_ITEM_SET)
282 						xCell->SetMergedItem( *pPoolItem );
283 
284 					String sDebug = mpOutliner->GetText( mpOutliner->GetParagraph( xCellInfo->mnStartPara ), xCellInfo->mnParaCount );
285 
286 					OutlinerParaObject* pTextObject = mpOutliner->CreateParaObject( (sal_uInt16)xCellInfo->mnStartPara, (sal_uInt16)xCellInfo->mnParaCount );
287 					if( pTextObject )
288 					{
289 						SdrOutliner& rOutliner=mrTableObj.ImpGetDrawOutliner();
290 						rOutliner.SetUpdateMode(sal_True);
291 						rOutliner.SetText( *pTextObject );
292 						mrTableObj.NbcSetOutlinerParaObjectForText( rOutliner.CreateParaObject(), xCell.get() );
293 						delete pTextObject;
294 					}
295 				}
296 			}
297 		}
298 
299 		Rectangle aRect( mrTableObj.GetSnapRect() );
300 		aRect.nRight = aRect.nLeft + nLastEdge;
301 		mrTableObj.NbcSetSnapRect( aRect );
302 
303 	}
304 	catch( Exception& e )
305 	{
306 		(void)e;
307 		DBG_ERROR("sdr::table::SdrTableRTFParser::InsertCell(), exception caught!" );
308 	}
309 }
310 
NewCellRow()311 void SdrTableRTFParser::NewCellRow()
312 {
313 	if( mbNewDef )
314 	{
315 		mbNewDef = sal_False;
316 
317 		maRows.push_back( RTFColumnVectorPtr( new RTFColumnVector() ) );
318 	}
319 	mpDefMerge = NULL;
320 	maDefaultIterator = maDefaultList.begin();
321 
322 	NextColumn();
323 
324 	DBG_ASSERT( mpActDefault, "NewCellRow: pActDefault==0" );
325 }
326 
NextColumn()327 void SdrTableRTFParser::NextColumn()
328 {
329 	if( maDefaultIterator != maDefaultList.end() )
330 		mpActDefault = (*maDefaultIterator++).get();
331 	else
332 		mpActDefault = 0;
333 }
334 
TwipsToHundMM(long nIn)335 long TwipsToHundMM( long nIn )
336 {
337 	long nRet = OutputDevice::LogicToLogic( nIn, MAP_TWIP, MAP_100TH_MM );
338 	return nRet;
339 }
340 
ProcToken(ImportInfo * pInfo)341 void SdrTableRTFParser::ProcToken( ImportInfo* pInfo )
342 {
343 	switch ( pInfo->nToken )
344 	{
345 		case RTF_TROWD:			// denotes table row defauls, before RTF_CELLX
346 		{
347 			mnColCnt = 0;
348 			maDefaultList.clear();
349 			mpDefMerge = NULL;
350 			mnLastToken = pInfo->nToken;
351 		}
352 		break;
353 		case RTF_CLMGF:			// The first cell of cells to be merged
354 		{
355 			mpDefMerge = mpInsDefault;
356 			mnLastToken = pInfo->nToken;
357 		}
358 		break;
359 		case RTF_CLMRG:			// A cell to be merged with the preceding cell
360 		{
361 			if ( !mpDefMerge )
362 				mpDefMerge = maDefaultList.back().get();
363 			DBG_ASSERT( mpDefMerge, "RTF_CLMRG: pDefMerge==0" );
364 			if( mpDefMerge )
365 				mpDefMerge->mnColSpan++;
366 			mpInsDefault->mnColSpan = 0;
367 			mnLastToken = pInfo->nToken;
368 		}
369 		break;
370 		case RTF_CELLX:			// closes cell default
371 		{
372 			mbNewDef = sal_True;
373 			mpInsDefault->mnCol = mnColCnt;
374 			maDefaultList.push_back( boost::shared_ptr< RTFCellDefault >( mpInsDefault ) );
375 
376 			if( (sal_Int32)maColumnEdges.size() <= mnColCnt )
377 				maColumnEdges.resize( mnColCnt + 1 );
378 
379 			const sal_Int32 nSize = TwipsToHundMM( pInfo->nTokenValue );
380 			maColumnEdges[mnColCnt] = std::max( maColumnEdges[mnColCnt], nSize );
381 
382 			mpInsDefault = new RTFCellDefault( &mrItemPool );
383 			if ( ++mnColCnt > mnColMax )
384 				mnColMax = mnColCnt;
385 			mnLastToken = pInfo->nToken;
386 		}
387 		break;
388 		case RTF_INTBL:			// before the first RTF_CELL
389 		{
390 			if ( mnLastToken != RTF_INTBL && mnLastToken != RTF_CELL && mnLastToken != RTF_PAR )
391 			{
392 				NewCellRow();
393 				mnLastToken = pInfo->nToken;
394 			}
395 		}
396 		break;
397 		case RTF_CELL:			// denotes the end of a cell.
398 		{
399 			DBG_ASSERT( mpActDefault, "RTF_CELL: pActDefault==0" );
400 			if ( mbNewDef || !mpActDefault )
401 				NewCellRow();
402 			if ( !mpActDefault )
403 				mpActDefault = mpInsDefault;
404 			if ( mpActDefault->mnColSpan > 0 )
405 			{
406 				InsertCell(pInfo);
407 			}
408 			NextColumn();
409 			mnLastToken = pInfo->nToken;
410 		}
411 		break;
412 		case RTF_ROW:			// means the end of a row
413 		{
414 			NextRow();
415 			mnLastToken = pInfo->nToken;
416 		}
417 		break;
418 		case RTF_PAR:			// Paragraph
419 			mnLastToken = pInfo->nToken;
420 			break;
421 		default:
422 		{	// do not set nLastToken
423 			switch ( pInfo->nToken & ~(0xff | RTF_TABLEDEF) )
424 			{
425 				case RTF_SHADINGDEF:
426 //					((SvxRTFParser*)pInfo->pParser)->ReadBackgroundAttr(pInfo->nToken, mpInsDefault->maItemSet, sal_True );
427 				break;
428 				case RTF_BRDRDEF:
429 					((SvxRTFParser*)pInfo->pParser)->ReadBorderAttr(pInfo->nToken, mpInsDefault->maItemSet, sal_True );
430 				break;
431 			}
432 		}
433 	}
434 }
435 
ImportAsRTF(SvStream & rStream,SdrTableObj & rObj)436 void SdrTableObj::ImportAsRTF( SvStream& rStream, SdrTableObj& rObj )
437 {
438 	SdrTableRTFParser aParser( rObj );
439 	aParser.Read( rStream );
440 }
441 
442 } }
443 
444