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