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