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