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 64 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 76 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 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 155 SdrTableRTFParser::~SdrTableRTFParser() 156 { 157 delete mpOutliner; 158 delete mpInsDefault; 159 } 160 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 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 212 void SdrTableRTFParser::NextRow() 213 { 214 ++mnRowCnt; 215 } 216 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 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 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 327 void SdrTableRTFParser::NextColumn() 328 { 329 if( maDefaultIterator != maDefaultList.end() ) 330 mpActDefault = (*maDefaultIterator++).get(); 331 else 332 mpActDefault = 0; 333 } 334 335 long TwipsToHundMM( long nIn ) 336 { 337 long nRet = OutputDevice::LogicToLogic( nIn, MAP_TWIP, MAP_100TH_MM ); 338 return nRet; 339 } 340 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 436 void SdrTableObj::ImportAsRTF( SvStream& rStream, SdrTableObj& rObj ) 437 { 438 SdrTableRTFParser aParser( rObj ); 439 aParser.Read( rStream ); 440 } 441 442 } } 443 444