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