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