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/scoped_ptr.hpp>
23 #include <boost/shared_ptr.hpp>
25 #include <com/sun/star/table/XTable.hpp>
27 #include <tools/stream.hxx>
28 #include <svtools/rtftoken.h>
30 #include <editeng/eeitem.hxx>
31 #include <svx/svdetc.hxx>
32 #include <editeng/fhgtitem.hxx>
33 #include <editeng/outlobj.hxx>
36 #include "celltypes.hxx"
37 #include "svx/svdotable.hxx"
38 #include "svx/svdoutl.hxx"
39 #include "editeng/editeng.hxx"
40 #include "editeng/editdata.hxx"
41 #include "svx/svdmodel.hxx"
42 #include "editeng/svxrtf.hxx"
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
;
49 namespace sdr
{ namespace table
{
55 sal_uInt16 mnTwips
; // right border of the cell
56 sal_Int32 mnColSpan
; // MergeCell if >1, merged cells if 0
58 RTFCellDefault( SfxItemPool
* pPool
) : maItemSet( *pPool
), mnCol(0), mnTwips(0 ), mnColSpan(1) {}
61 typedef std::vector
< boost::shared_ptr
< RTFCellDefault
> > RTFCellDefaultVector
;
66 sal_Int32 mnStartPara
;
67 sal_Int32 mnParaCount
;
70 RTFCellInfo( SfxItemPool
& rPool
) : maItemSet( rPool
), mnStartPara(0), mnParaCount(0), mnColSpan(0) {}
73 typedef boost::shared_ptr
< RTFCellInfo
> RTFCellInfoPtr
;
74 typedef std::vector
< RTFCellInfoPtr
> RTFColumnVector
;
76 typedef boost::shared_ptr
< RTFColumnVector
> RTFColumnVectorPtr
;
78 typedef std::vector
< RTFColumnVectorPtr
> RTFRowVector
;
80 class SdrTableRTFParser
83 SdrTableRTFParser( SdrTableObj
& rTableObj
);
86 void Read( SvStream
& rStream
);
88 void ProcToken( ImportInfo
* pInfo
);
94 void InsertCell( ImportInfo
* pInfo
);
98 DECL_LINK( RTFImportHdl
, ImportInfo
* );
101 SdrTableObj
& mrTableObj
;
102 SdrOutliner
* mpOutliner
;
103 SfxItemPool
& mrItemPool
;
105 RTFCellDefaultVector maDefaultList
;
106 RTFCellDefaultVector::iterator maDefaultIterator
;
111 sal_Int32 mnStartPara
;
117 std::vector
< sal_Int32
> maColumnEdges
;
121 RTFCellDefault
* mpInsDefault
;
122 RTFCellDefault
* mpActDefault
;
123 RTFCellDefault
* mpDefMerge
;
125 Reference
< XTable
> mxTable
;
128 SdrTableRTFParser::SdrTableRTFParser( SdrTableObj
& rTableObj
)
129 : mrTableObj( rTableObj
)
130 , mpOutliner( SdrMakeOutliner( OUTLINERMODE_TEXTOBJECT
, *rTableObj
.GetModel() ) )
131 , mrItemPool( rTableObj
.GetModel()->GetItemPool() )
140 , mxTable( rTableObj
.getTable() )
142 mpOutliner
->SetUpdateMode(true);
143 mpOutliner
->SetStyleSheet( 0, mrTableObj
.GetStyleSheet() );
144 mpInsDefault
= new RTFCellDefault( &mrItemPool
);
147 SdrTableRTFParser::~SdrTableRTFParser()
153 void SdrTableRTFParser::Read( SvStream
& rStream
)
155 EditEngine
& rEdit
= const_cast< EditEngine
& >( mpOutliner
->GetEditEngine() );
157 Link
<> aOldLink( rEdit
.GetImportHdl() );
158 rEdit
.SetImportHdl( LINK( this, SdrTableRTFParser
, RTFImportHdl
) );
159 mpOutliner
->Read( rStream
, OUString(), EE_FORMAT_RTF
);
160 rEdit
.SetImportHdl( aOldLink
);
165 IMPL_LINK( SdrTableRTFParser
, RTFImportHdl
, ImportInfo
*, pInfo
)
167 switch ( pInfo
->eState
)
169 case RTFIMP_NEXTTOKEN
:
172 case RTFIMP_UNKNOWNATTR
:
177 SvxRTFParser
* pParser
= static_cast<SvxRTFParser
*>(pInfo
->pParser
);
178 pParser
->SetAttrPool( &mrItemPool
);
179 RTFPardAttrMapIds
& rMap
= pParser
->GetPardMap();
180 rMap
.nBox
= SDRATTR_TABLE_BORDER
;
184 if ( pInfo
->aSelection
.nEndPos
)
187 pInfo
->nToken
= RTF_PAR
;
188 pInfo
->aSelection
.nEndPara
++;
194 case RTFIMP_INSERTTEXT
:
196 case RTFIMP_INSERTPARA
:
199 SAL_WARN( "svx.table","unknown ImportInfo.eState");
204 void SdrTableRTFParser::NextRow()
209 void SdrTableRTFParser::InsertCell( ImportInfo
* pInfo
)
211 sal_Int32 nCol
= mpActDefault
->mnCol
;
213 RTFCellInfoPtr
xCellInfo( new RTFCellInfo(mrItemPool
) );
215 xCellInfo
->mnStartPara
= mnStartPara
;
216 xCellInfo
->mnParaCount
= pInfo
->aSelection
.nEndPara
- 1 - mnStartPara
;
218 if( !maRows
.empty() )
220 RTFColumnVectorPtr
xColumn( maRows
.back() );
222 if( xColumn
->size() <= (size_t)nCol
)
223 xColumn
->resize( nCol
+1 );
225 (*xColumn
)[nCol
] = xCellInfo
;
228 mnStartPara
= pInfo
->aSelection
.nEndPara
- 1;
231 void SdrTableRTFParser::FillTable()
235 sal_Int32 nColCount
= mxTable
->getColumnCount();
236 Reference
< XTableColumns
> xCols( mxTable
->getColumns(), UNO_QUERY_THROW
);
238 if( nColCount
< mnColMax
)
240 xCols
->insertByIndex( nColCount
, mnColMax
- nColCount
);
241 nColCount
= mxTable
->getColumnCount();
244 const OUString
sWidth("Width");
245 sal_Int32 nCol
, nLastEdge
= 0;
246 for( nCol
= 0; nCol
< nColCount
; nCol
++ )
248 Reference
< XPropertySet
> xSet( xCols
->getByIndex( nCol
), UNO_QUERY_THROW
);
249 sal_Int32 nWidth
= maColumnEdges
[nCol
] - nLastEdge
;
251 xSet
->setPropertyValue( sWidth
, Any( nWidth
) );
255 const sal_Int32 nRowCount
= mxTable
->getRowCount();
256 if( nRowCount
< mnRowCnt
)
258 Reference
< XTableRows
> xRows( mxTable
->getRows(), UNO_QUERY_THROW
);
259 xRows
->insertByIndex( nRowCount
, mnRowCnt
- nRowCount
);
262 for( sal_Int32 nRow
= 0; nRow
< (sal_Int32
)maRows
.size(); nRow
++ )
264 RTFColumnVectorPtr
xColumn( maRows
[nRow
] );
265 for( nCol
= 0; nCol
< (sal_Int32
)xColumn
->size(); nCol
++ )
267 RTFCellInfoPtr
xCellInfo( (*xColumn
)[nCol
] );
269 CellRef
xCell( dynamic_cast< Cell
* >( mxTable
->getCellByPosition( nCol
, nRow
).get() ) );
270 if( xCell
.is() && xCellInfo
.get() )
272 const SfxPoolItem
*pPoolItem
= 0;
273 if( xCellInfo
->maItemSet
.GetItemState(SDRATTR_TABLE_BORDER
,false,&pPoolItem
)==SfxItemState::SET
)
274 xCell
->SetMergedItem( *pPoolItem
);
276 boost::scoped_ptr
<OutlinerParaObject
> pTextObject(mpOutliner
->CreateParaObject( xCellInfo
->mnStartPara
, xCellInfo
->mnParaCount
));
279 SdrOutliner
& rOutliner
=mrTableObj
.ImpGetDrawOutliner();
280 rOutliner
.SetUpdateMode(true);
281 rOutliner
.SetText( *pTextObject
);
282 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()
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 static_cast<SvxRTFParser
*>(pInfo
->pParser
)->ReadBorderAttr(pInfo
->nToken
, mpInsDefault
->maItemSet
, 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: */