xref: /trunk/main/svx/source/table/tablertfimporter.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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