1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
22 #include <boost/shared_ptr.hpp>
24 #include <com/sun/star/table/XTable.hpp>
26 #include <tools/stream.hxx>
27 #include <svtools/rtftoken.h>
29 #include <editeng/eeitem.hxx>
30 #include <svx/svdetc.hxx>
31 #include <editeng/fhgtitem.hxx>
32 #include <editeng/outlobj.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"
43 using namespace ::com::sun::star::uno
;
44 using namespace ::com::sun::star::table
;
45 using namespace ::com::sun::star::container
;
46 using namespace ::com::sun::star::beans
;
48 namespace sdr
{ namespace table
{
54 sal_uInt16 mnTwips
; // right border of the cell
55 sal_Int32 mnColSpan
; // MergeCell if >1, merged cells if 0
57 RTFCellDefault( SfxItemPool
* pPool
) : maItemSet( *pPool
), mnCol(0), mnTwips(0 ), mnColSpan(1) {}
60 typedef std::vector
< boost::shared_ptr
< RTFCellDefault
> > RTFCellDefaultVector
;
65 sal_Int32 mnStartPara
;
66 sal_Int32 mnParaCount
;
69 RTFCellInfo( SfxItemPool
& rPool
) : maItemSet( rPool
), mnStartPara(0), mnParaCount(0), mnColSpan(0) {}
72 typedef boost::shared_ptr
< RTFCellInfo
> RTFCellInfoPtr
;
73 typedef std::vector
< RTFCellInfoPtr
> RTFColumnVector
;
75 typedef boost::shared_ptr
< RTFColumnVector
> RTFColumnVectorPtr
;
77 typedef std::vector
< RTFColumnVectorPtr
> RTFRowVector
;
79 class SdrTableRTFParser
82 SdrTableRTFParser( SdrTableObj
& rTableObj
);
85 void Read( SvStream
& rStream
);
87 void ProcToken( ImportInfo
* pInfo
);
93 void InsertCell( ImportInfo
* pInfo
);
97 DECL_LINK( RTFImportHdl
, ImportInfo
* );
100 SdrTableObj
& mrTableObj
;
101 SdrOutliner
* mpOutliner
;
102 SfxItemPool
& mrItemPool
;
104 RTFCellDefaultVector maDefaultList
;
105 RTFCellDefaultVector::iterator maDefaultIterator
;
110 sal_Int32 mnStartPara
;
116 std::vector
< sal_Int32
> maColumnEdges
;
120 RTFCellDefault
* mpInsDefault
;
121 RTFCellDefault
* mpActDefault
;
122 RTFCellDefault
* mpDefMerge
;
124 Reference
< XTable
> mxTable
;
127 SdrTableRTFParser::SdrTableRTFParser( SdrTableObj
& rTableObj
)
128 : mrTableObj( rTableObj
)
129 , mpOutliner( SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT
, rTableObj
.GetModel() ) )
130 , mrItemPool( rTableObj
.GetModel()->GetItemPool() )
139 , mxTable( rTableObj
.getTable() )
141 mpOutliner
->SetUpdateMode(sal_True
);
142 mpOutliner
->SetStyleSheet( 0, mrTableObj
.GetStyleSheet() );
143 mpInsDefault
= new RTFCellDefault( &mrItemPool
);
146 SdrTableRTFParser::~SdrTableRTFParser()
152 void SdrTableRTFParser::Read( SvStream
& rStream
)
154 EditEngine
& rEdit
= const_cast< EditEngine
& >( mpOutliner
->GetEditEngine() );
156 Link
aOldLink( rEdit
.GetImportHdl() );
157 rEdit
.SetImportHdl( LINK( this, SdrTableRTFParser
, RTFImportHdl
) );
158 mpOutliner
->Read( rStream
, String(), EE_FORMAT_RTF
);
159 rEdit
.SetImportHdl( aOldLink
);
164 IMPL_LINK( SdrTableRTFParser
, RTFImportHdl
, ImportInfo
*, pInfo
)
166 switch ( pInfo
->eState
)
168 case RTFIMP_NEXTTOKEN
:
171 case RTFIMP_UNKNOWNATTR
:
176 SvxRTFParser
* pParser
= (SvxRTFParser
*) pInfo
->pParser
;
177 pParser
->SetAttrPool( &mrItemPool
);
178 RTFPardAttrMapIds
& rMap
= pParser
->GetPardMap();
179 rMap
.nBox
= SDRATTR_TABLE_BORDER
;
183 if ( pInfo
->aSelection
.nEndPos
)
186 pInfo
->nToken
= RTF_PAR
;
187 pInfo
->aSelection
.nEndPara
++;
193 case RTFIMP_INSERTTEXT
:
195 case RTFIMP_INSERTPARA
:
198 SAL_WARN( "svx.table","unknown ImportInfo.eState");
203 void SdrTableRTFParser::NextRow()
208 void SdrTableRTFParser::InsertCell( ImportInfo
* pInfo
)
210 sal_Int32 nCol
= mpActDefault
->mnCol
;
212 RTFCellInfoPtr
xCellInfo( new RTFCellInfo(mrItemPool
) );
214 xCellInfo
->mnStartPara
= mnStartPara
;
215 xCellInfo
->mnParaCount
= pInfo
->aSelection
.nEndPara
- 1 - mnStartPara
;
217 if( !maRows
.empty() )
219 RTFColumnVectorPtr
xColumn( maRows
.back() );
221 if( xColumn
->size() <= (size_t)nCol
)
222 xColumn
->resize( nCol
+1 );
224 (*xColumn
)[nCol
] = xCellInfo
;
227 mnStartPara
= pInfo
->aSelection
.nEndPara
- 1;
230 void SdrTableRTFParser::FillTable()
234 sal_Int32 nColCount
= mxTable
->getColumnCount();
235 Reference
< XTableColumns
> xCols( mxTable
->getColumns(), UNO_QUERY_THROW
);
237 if( nColCount
< mnColMax
)
239 xCols
->insertByIndex( nColCount
, mnColMax
- nColCount
);
240 nColCount
= mxTable
->getColumnCount();
243 const OUString
sWidth("Width");
244 sal_Int32 nCol
, nLastEdge
= 0;
245 for( nCol
= 0; nCol
< nColCount
; nCol
++ )
247 Reference
< XPropertySet
> xSet( xCols
->getByIndex( nCol
), UNO_QUERY_THROW
);
248 sal_Int32 nWidth
= maColumnEdges
[nCol
] - nLastEdge
;
250 xSet
->setPropertyValue( sWidth
, Any( nWidth
) );
254 const sal_Int32 nRowCount
= mxTable
->getRowCount();
255 if( nRowCount
< mnRowCnt
)
257 Reference
< XTableRows
> xRows( mxTable
->getRows(), UNO_QUERY_THROW
);
258 xRows
->insertByIndex( nRowCount
, mnRowCnt
- nRowCount
);
261 for( sal_Int32 nRow
= 0; nRow
< (sal_Int32
)maRows
.size(); nRow
++ )
263 RTFColumnVectorPtr
xColumn( maRows
[nRow
] );
264 for( nCol
= 0; nCol
< (sal_Int32
)xColumn
->size(); nCol
++ )
266 RTFCellInfoPtr
xCellInfo( (*xColumn
)[nCol
] );
268 CellRef
xCell( dynamic_cast< Cell
* >( mxTable
->getCellByPosition( nCol
, nRow
).get() ) );
269 if( xCell
.is() && xCellInfo
.get() )
271 const SfxPoolItem
*pPoolItem
= 0;
272 if( xCellInfo
->maItemSet
.GetItemState(SDRATTR_TABLE_BORDER
,sal_False
,&pPoolItem
)==SFX_ITEM_SET
)
273 xCell
->SetMergedItem( *pPoolItem
);
275 OutlinerParaObject
* pTextObject
= mpOutliner
->CreateParaObject( xCellInfo
->mnStartPara
, xCellInfo
->mnParaCount
);
278 SdrOutliner
& rOutliner
=mrTableObj
.ImpGetDrawOutliner();
279 rOutliner
.SetUpdateMode(sal_True
);
280 rOutliner
.SetText( *pTextObject
);
281 mrTableObj
.NbcSetOutlinerParaObjectForText( rOutliner
.CreateParaObject(), xCell
.get() );
288 Rectangle
aRect( mrTableObj
.GetSnapRect() );
289 aRect
.Right() = aRect
.Left() + nLastEdge
;
290 mrTableObj
.NbcSetSnapRect( aRect
);
293 catch( Exception
& e
)
296 OSL_FAIL("sdr::table::SdrTableRTFParser::InsertCell(), exception caught!" );
300 void SdrTableRTFParser::NewCellRow()
304 mbNewDef
= sal_False
;
306 maRows
.push_back( RTFColumnVectorPtr( new RTFColumnVector() ) );
309 maDefaultIterator
= maDefaultList
.begin();
313 DBG_ASSERT( mpActDefault
, "NewCellRow: pActDefault==0" );
316 void SdrTableRTFParser::NextColumn()
318 if( maDefaultIterator
!= maDefaultList
.end() )
319 mpActDefault
= (*maDefaultIterator
++).get();
324 long TwipsToHundMM( long nIn
)
326 long nRet
= OutputDevice::LogicToLogic( nIn
, MAP_TWIP
, MAP_100TH_MM
);
330 void SdrTableRTFParser::ProcToken( ImportInfo
* pInfo
)
332 switch ( pInfo
->nToken
)
334 case RTF_TROWD
: // denotes table row defauls, before RTF_CELLX
337 maDefaultList
.clear();
339 mnLastToken
= pInfo
->nToken
;
342 case RTF_CLMGF
: // The first cell of cells to be merged
344 mpDefMerge
= mpInsDefault
;
345 mnLastToken
= pInfo
->nToken
;
348 case RTF_CLMRG
: // A cell to be merged with the preceding cell
351 mpDefMerge
= maDefaultList
.back().get();
352 DBG_ASSERT( mpDefMerge
, "RTF_CLMRG: pDefMerge==0" );
354 mpDefMerge
->mnColSpan
++;
355 mpInsDefault
->mnColSpan
= 0;
356 mnLastToken
= pInfo
->nToken
;
359 case RTF_CELLX
: // closes cell default
362 mpInsDefault
->mnCol
= mnColCnt
;
363 maDefaultList
.push_back( boost::shared_ptr
< RTFCellDefault
>( mpInsDefault
) );
365 if( (sal_Int32
)maColumnEdges
.size() <= mnColCnt
)
366 maColumnEdges
.resize( mnColCnt
+ 1 );
368 const sal_Int32 nSize
= TwipsToHundMM( pInfo
->nTokenValue
);
369 maColumnEdges
[mnColCnt
] = std::max( maColumnEdges
[mnColCnt
], nSize
);
371 mpInsDefault
= new RTFCellDefault( &mrItemPool
);
372 if ( ++mnColCnt
> mnColMax
)
374 mnLastToken
= pInfo
->nToken
;
377 case RTF_INTBL
: // before the first RTF_CELL
379 if ( mnLastToken
!= RTF_INTBL
&& mnLastToken
!= RTF_CELL
&& mnLastToken
!= RTF_PAR
)
382 mnLastToken
= pInfo
->nToken
;
386 case RTF_CELL
: // denotes the end of a cell.
388 DBG_ASSERT( mpActDefault
, "RTF_CELL: pActDefault==0" );
389 if ( mbNewDef
|| !mpActDefault
)
392 mpActDefault
= mpInsDefault
;
393 if ( mpActDefault
->mnColSpan
> 0 )
398 mnLastToken
= pInfo
->nToken
;
401 case RTF_ROW
: // means the end of a row
404 mnLastToken
= pInfo
->nToken
;
407 case RTF_PAR
: // Paragraph
408 mnLastToken
= pInfo
->nToken
;
411 { // do not set nLastToken
412 switch ( pInfo
->nToken
& ~(0xff | RTF_TABLEDEF
) )
415 // ((SvxRTFParser*)pInfo->pParser)->ReadBackgroundAttr(pInfo->nToken, mpInsDefault->maItemSet, sal_True );
418 ((SvxRTFParser
*)pInfo
->pParser
)->ReadBorderAttr(pInfo
->nToken
, mpInsDefault
->maItemSet
, sal_True
);
425 void SdrTableObj::ImportAsRTF( SvStream
& rStream
, SdrTableObj
& rObj
)
427 SdrTableRTFParser
aParser( rObj
);
428 aParser
.Read( rStream
);
433 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */