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 // MARKER(update_precomp.py): autogen include statement, do not remove 23 #include "precompiled_sw.hxx" 24 25 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */ 26 #include <hintids.hxx> 27 #include <tools/list.hxx> 28 #include <tools/cachestr.hxx> 29 #include <svtools/rtftoken.h> 30 #include <svl/itemiter.hxx> 31 #include <editeng/prntitem.hxx> 32 #include <editeng/opaqitem.hxx> 33 #include <editeng/protitem.hxx> 34 #include <editeng/ulspitem.hxx> 35 #include <editeng/lrspitem.hxx> 36 #include <editeng/boxitem.hxx> 37 #include <editeng/frmdiritem.hxx> 38 #include <fmtfsize.hxx> 39 #include <fmtanchr.hxx> 40 #include <fmtpdsc.hxx> 41 #include <fmtsrnd.hxx> 42 #include <fmtclds.hxx> 43 #include <fmtcntnt.hxx> 44 #include <frmatr.hxx> 45 #include <doc.hxx> 46 #include <pam.hxx> 47 #include <ndtxt.hxx> 48 #include <shellio.hxx> 49 #include <swparrtf.hxx> 50 #include <grfatr.hxx> 51 #include <paratr.hxx> 52 #include <rtf.hxx> 53 #include <ndgrf.hxx> 54 #include <pagedesc.hxx> 55 #include <swtable.hxx> 56 #include <txtflcnt.hxx> 57 #include <fmtflcnt.hxx> 58 #include <fltini.hxx> 59 #include <unoframe.hxx> 60 #include <deque> 61 #include <map> 62 #include <utility> 63 #include <fmtwrapinfluenceonobjpos.hxx> 64 #include <editeng/brshitem.hxx> 65 #include <fmtfollowtextflow.hxx> 66 #include "dcontact.hxx" 67 #include <drawdoc.hxx> 68 69 using namespace ::com::sun::star; 70 71 #define ANCHOR(p) ((SwFmtAnchor*)p) 72 73 // steht in shellio.hxx 74 extern SwCntntNode* GoNextNds( SwNodeIndex * pIdx, sal_Bool bChk ); 75 76 SV_IMPL_PTRARR( SwFlySaveArr, SwFlySave* ) 77 78 inline const SwFmtFrmSize GetFrmSize(const SfxItemSet& rSet, sal_Bool bInP=sal_True) 79 { 80 return (const SwFmtFrmSize&)rSet.Get(RES_FRM_SIZE,bInP); 81 } 82 83 SwFlySave::SwFlySave(const SwPaM& rPam, SfxItemSet& rSet) 84 : aFlySet(rSet), nSttNd(rPam.GetPoint()->nNode), nEndNd(nSttNd), nEndCnt(0), 85 nPageWidth(ATT_MIN_SIZE), nDropLines(0), nDropAnchor(0) 86 { 87 } 88 89 int SwFlySave::IsEqualFly( const SwPaM& rPos, SfxItemSet& rSet ) 90 { 91 if( rSet.Count() != aFlySet.Count() || nDropAnchor ) 92 return sal_False; 93 94 // nur TextNodes zusammenfassen 95 if( nSttNd == nEndNd && nEndNd.GetNode().IsNoTxtNode() ) 96 return sal_False; 97 98 // teste auf gleiche / naechste Position 99 if( rPos.GetPoint()->nNode.GetIndex() == nEndNd.GetIndex() ) 100 { 101 if( 1 < (rPos.GetPoint()->nContent.GetIndex() - nEndCnt) ) 102 return sal_False; 103 } 104 else if( rPos.GetPoint()->nContent.GetIndex() ) 105 return sal_False; 106 else 107 { 108 SwNodeIndex aIdx( nEndNd ); 109 SwCntntNode *const pCNd = aIdx.GetNode().GetCntntNode(); 110 if( !GoNextNds( &aIdx, sal_True ) || 111 aIdx.GetIndex() != rPos.GetPoint()->nNode.GetIndex() || 112 ( pCNd && pCNd->Len() != nEndCnt )) 113 { 114 return sal_False; 115 } 116 } 117 118 if( rSet.Count() ) 119 { 120 SfxItemIter aIter( rSet ); 121 const SfxPoolItem *pItem, *pCurr = aIter.GetCurItem(); 122 while( sal_True ) 123 { 124 if( SFX_ITEM_SET != aFlySet.GetItemState( pCurr->Which(), 125 sal_False, &pItem ) || 126 // Ankerattribute gesondert behandeln 127 ( RES_ANCHOR == pCurr->Which() 128 ? (ANCHOR(pCurr)->GetAnchorId() != ANCHOR(pItem)->GetAnchorId() || 129 ANCHOR(pCurr)->GetPageNum() != ANCHOR(pItem)->GetPageNum()) 130 : *pItem != *pCurr )) 131 return sal_False; 132 133 if( aIter.IsAtEnd() ) 134 break; 135 pCurr = aIter.NextItem(); 136 } 137 } 138 return sal_True; 139 } 140 141 void SwFlySave::SetFlySize( const SwTableNode& rTblNd ) 142 { 143 // sollte der Fly kleiner als diese Tabelle sein, dann 144 // korrigiere diesen (nur bei abs. Angaben!) 145 SwTwips nWidth = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth(); 146 const SwFmtFrmSize& rSz = GetFrmSize( aFlySet ); 147 if( nWidth > rSz.GetWidth() ) 148 aFlySet.Put( SwFmtFrmSize( rSz.GetHeightSizeType(), nWidth, rSz.GetHeight() )); 149 } 150 151 sal_Bool lcl_HasBreakAttrs( const SwCntntNode& rNd ) 152 { 153 sal_Bool bRet = sal_False; 154 const SfxItemSet& rSet = rNd.GetSwAttrSet(); 155 const SfxPoolItem* pItem; 156 if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK, sal_True, &pItem ) && 157 SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() ) 158 bRet = sal_True; 159 else if( SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC, sal_True, &pItem )&& 160 0 != ((SwFmtPageDesc*)pItem)->GetPageDesc() ) 161 bRet = sal_True; 162 return bRet; 163 } 164 165 166 void lcl_CpyBreakAttrs( SwCntntNode* pSrcNd, SwCntntNode* pDstNd, 167 SwNodeIndex* pNewIdx ) 168 { 169 const SfxItemSet* pSet; 170 if( pSrcNd && pDstNd && 0 != ( pSet = pSrcNd->GetpSwAttrSet() ) ) 171 { 172 const SfxPoolItem *pDescItem, *pBreakItem; 173 174 if( SFX_ITEM_SET != pSet->GetItemState( RES_BREAK, 175 sal_False, &pBreakItem ) ) 176 pBreakItem = 0; 177 178 if( SFX_ITEM_SET != pSet->GetItemState( RES_PAGEDESC, 179 sal_False, &pDescItem ) ) 180 pDescItem = 0; 181 182 if( pDescItem || pBreakItem ) 183 { 184 if( lcl_HasBreakAttrs( *pDstNd )) 185 { 186 SwPosition aPos( *pDstNd, SwIndex( pDstNd )); 187 aPos.nNode--; 188 pDstNd->GetDoc()->AppendTxtNode( aPos ); 189 if( pNewIdx ) 190 *pNewIdx = aPos.nNode; 191 192 SwCntntNode* pOldNd = pDstNd; 193 pDstNd = aPos.nNode.GetNode().GetCntntNode(); 194 pDstNd->ChgFmtColl( pOldNd->GetFmtColl() ); 195 if( pDstNd->HasSwAttrSet() ) 196 { 197 SfxItemSet aSet( *pDstNd->GetpSwAttrSet() ); 198 aSet.ClearItem( RES_BREAK ); 199 aSet.ClearItem( RES_PAGEDESC ); 200 pDstNd->SetAttr( aSet ); 201 } 202 } 203 if( pBreakItem ) 204 { 205 pDstNd->SetAttr( *pBreakItem ); 206 pSrcNd->ResetAttr( RES_BREAK ); 207 } 208 if( pDescItem ) 209 { 210 pDstNd->SetAttr( *pDescItem ); 211 pSrcNd->ResetAttr( RES_PAGEDESC ); 212 } 213 } 214 } 215 } 216 217 void SwRTFParser::SetFlysInDoc() 218 { 219 // !! von Oben abarbeiten, CntntPos ist kein Index ! 220 SwNodes & rNds = pDoc->GetNodes(); 221 typedef std::pair<SwFlyFrmFmt*, SwFmtAnchor> frameEntry; 222 typedef std::deque<frameEntry> rtfframesAtIndex; 223 typedef std::map<const SwNode*, rtfframesAtIndex> rtfFmtMap; 224 rtfFmtMap aPrevFmts; 225 226 SwFrmFmt* pParent = pDoc->GetFrmFmtFromPool( RES_POOLFRM_FRAME ); 227 for( sal_uInt16 n = 0; n < aFlyArr.Count(); ++n ) 228 { 229 SwFlySave* pFlySave = aFlyArr[ n ]; 230 231 ASSERT( !pFlySave->nSttNd.GetNode().FindFlyStartNode(), 232 "Content vom Fly steht in einem Fly" ); 233 ASSERT( pFlySave->nSttNd.GetIndex() <= pFlySave->nEndNd.GetIndex(), 234 "Fly hat falschen Bereich" ); 235 236 237 238 //JP 21.09.98: wenn ein DropCap ist, dann Text im Node belassen, am 239 // Absatz das Absatz Attribut setzen. Ggfs noch die 240 // FontSize zuruecksetzen, damit das DropCap nicht zu 241 // gro? wird. 242 if( pFlySave->nDropAnchor ) 243 { 244 SwTxtNode* pSttNd = pFlySave->nSttNd.GetNode().GetTxtNode(); 245 SwTxtNode* pEndNd = pFlySave->nEndNd.GetNode().GetTxtNode(); 246 if( pSttNd && pEndNd && 247 pSttNd->GetIndex() + 1 == pEndNd->GetIndex() 248 && pSttNd->GetTxt().Len()>0 /* #i38227# leave drop caps with no content as fly frames */ ) 249 { 250 sal_uLong nPos = pSttNd->GetIndex(); 251 SwDoc * pDoc1 = pSttNd->GetDoc(); 252 253 sal_Bool bJoined; 254 { 255 SwPaM aTmp( *pSttNd, pSttNd->GetTxt().Len(), *pEndNd, 0 ); 256 bJoined = pDoc1->DeleteAndJoin( aTmp ); 257 } 258 259 SwTxtNode * pNd = (pDoc1->GetNodes()[nPos])->GetTxtNode(); 260 261 if( bJoined && pNd != NULL) 262 { 263 SwFmtDrop aDropCap; 264 aDropCap.GetLines() = (sal_uInt8)pFlySave->nDropLines; 265 aDropCap.GetChars() = 1; 266 267 SwIndex aIdx( pEndNd ); 268 pNd->RstTxtAttr( aIdx, 1, RES_CHRATR_FONTSIZE ); 269 pNd->SetAttr( aDropCap ); 270 } 271 delete pFlySave; 272 continue; 273 } 274 } 275 276 // liegt Ende und Start vom Naechsten im gleichen Node, dann muss 277 // gesplittet werden 278 if (((static_cast<size_t>(n) + 1) < aFlyArr.Count()) && 279 pFlySave->nEndCnt && 280 pFlySave->nEndNd == aFlyArr[ n + 1 ]->nSttNd ) 281 { 282 SwCntntNode *const pCNd = pFlySave->nEndNd.GetNode().GetCntntNode(); 283 if( pCNd ) 284 { 285 SwPosition aPos( pFlySave->nEndNd, 286 SwIndex( pCNd, pFlySave->nEndCnt )); 287 pDoc->SplitNode( aPos, false ); 288 pFlySave->nEndNd--; 289 } 290 else 291 pFlySave->nEndCnt = 0; 292 } 293 294 // verschiebe den Inhalt von diesem Anchor in den Auto-TextBereich 295 // und erzeuge dadurch den richtigen SwG-Rahmen 296 SwNodeRange aRg(pFlySave->nSttNd, 0, pFlySave->nEndNd, 0); 297 //Make a new section, unless there is no content at all 298 const bool bMakeEmptySection = aRg.aStart < aRg.aEnd || ((aRg.aStart == aRg.aEnd) && pFlySave->nEndCnt); 299 300 { 301 // Nur TextNodes koennen in Tabellen stehen !! 302 const SwNode* pNd = &pFlySave->nSttNd.GetNode(); 303 if( pNd->IsNoTxtNode() ) 304 { 305 // die Size muss noch korrigiert werden! 306 nAktPageDesc = 0; // Standart PageDesc 307 if( SFX_ITEM_SET != pFlySave->aFlySet.GetItemState( 308 RES_FRM_SIZE, sal_False ) ) 309 _SetPictureSize( *(SwNoTxtNode*)pNd, aRg.aStart, 310 pFlySave->aFlySet ); 311 if( 0 != ( pNd = pNd->FindTableNode() ) ) 312 pFlySave->SetFlySize( *(SwTableNode*)pNd ); 313 } 314 else 315 { 316 // Take care for table nodes 317 pNd = pNd->GetNodes()[ pNd->GetIndex() - 2 ]->GetTableNode(); 318 if( pNd ) // if the table starts immediately before aRg -> expand aRg 319 aRg.aStart = *pNd; 320 321 if( bMakeEmptySection ) 322 { 323 pNd = &aRg.aEnd.GetNode(); 324 sal_uLong nSectEnd = pNd->EndOfSectionIndex()+1; 325 326 if (!pNd->IsTableNode() && 0 !=(pNd = pNd->FindTableNode()) 327 && (pNd->GetIndex() >= aRg.aStart.GetNode().GetIndex()) ) 328 { 329 const SwNode* pTblBxNd; 330 331 // Ende der Tabelle ist hinter dieser Box ?? 332 if( pNd->EndOfSectionIndex() == nSectEnd ) 333 aRg.aEnd = nSectEnd+1; 334 // is the end in the first box of the table, then 335 // move before the table (Bug 67663) 336 // but the range must not become emtpy, i.e. aStart==aEnd 337 // because otherwise we will get a crash (126506) later on 338 else if( 0 != ( pTblBxNd = aRg.aEnd.GetNode(). 339 FindTableBoxStartNode()) && 340 pTblBxNd->GetIndex() - 1 == pNd->GetIndex() && 341 &aRg.aStart.GetNode() != pNd ) 342 aRg.aEnd = *pNd; 343 else 344 { 345 // Tabelle ist noch groesser, also splitte sie hier. 346 rNds.SplitTable( aRg.aEnd, sal_True ); 347 aRg.aEnd = pNd->EndOfSectionIndex() + 1; 348 } 349 } 350 } 351 } 352 } 353 354 // vorm verschieben muss sich der Index auf die alte Position 355 // gemerkt werden, der Index wird mit verschoben !!! 356 357 SwNodeIndex aTmpIdx( rNds.GetEndOfAutotext() ); 358 SwStartNode* pSttNd = bMakeEmptySection 359 ? rNds.MakeEmptySection( aTmpIdx, SwFlyStartNode ) 360 : rNds.MakeTextSection( aTmpIdx, SwFlyStartNode, 361 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() ); 362 363 // das ist die Verankerungs-Position (fuers Layout!) 364 pFlySave->nSttNd = aRg.aStart.GetIndex()-1; 365 if( bMakeEmptySection ) 366 { 367 // check: the move does not clear the surrounded section. If all 368 // nodes moved away, then create a new TxtNode 369 { 370 // i76403: an empty selection is not a good idea 371 if( aRg.aStart == aRg.aEnd && aRg.aStart.GetNode().GetTxtNode() ) 372 aRg.aEnd++; 373 SwNodeIndex aPrev( aRg.aStart, -1 ); 374 if( aPrev.GetNode().IsStartNode() && 375 aPrev.GetNode().EndOfSectionNode() == &aRg.aEnd.GetNode()) 376 { 377 // create new txtnode, because the section does never be empty 378 pDoc->GetNodes().MakeTxtNode( aRg.aEnd, 379 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() ); 380 aRg.aEnd--; 381 } 382 } 383 aTmpIdx = *pSttNd->EndOfSectionNode(); 384 pDoc->MoveNodeRange( aRg, aTmpIdx, 385 IDocumentContentOperations::DOC_MOVEDEFAULT ); 386 } 387 388 // patch from cmc for #i52542# 389 if (pSttNd->GetIndex() + 1 == pSttNd->EndOfSectionIndex()) 390 { 391 ASSERT(!this, "nothing in this frame, not legal"); 392 delete pFlySave; 393 continue; 394 } 395 396 pFlySave->aFlySet.Put( SwFmtCntnt( pSttNd )); 397 398 CalculateFlySize( pFlySave->aFlySet, pFlySave->nSttNd, 399 pFlySave->nPageWidth ); 400 401 // THIS >>>>> 402 // if the section only contains one Node and this has a 403 // border or background, then put it to the frame 404 // Not in our own RTF-Format! 405 // <<<<< DOES NOT MAKE SENSE TO ME (flr) 406 // #102781#. Added support for transparent frames. 407 if( pSttNd->GetIndex() + 1 != pSttNd->EndOfSectionIndex() && 408 !bSwPageDesc ) 409 { 410 SwCntntNode* pSrcNd = pDoc->GetNodes()[ pSttNd->GetIndex() + 1 ]->GetCntntNode(); 411 SfxItemSet aTmpSet( pDoc->GetAttrPool(), 412 RES_BACKGROUND, RES_BOX ); 413 const SvxBrushItem* pBackgroundBrush = (const SvxBrushItem*)pFlySave->aFlySet.GetItem(RES_BACKGROUND, sal_False); 414 if( pSrcNd && pSrcNd->HasSwAttrSet() ) 415 aTmpSet.Put( *pSrcNd->GetpSwAttrSet() ); 416 if (pBackgroundBrush) 417 { 418 aTmpSet.Put(*pBackgroundBrush, RES_BACKGROUND); 419 } 420 else 421 { 422 pBackgroundBrush = (const SvxBrushItem*)aTmpSet.GetItem(RES_BACKGROUND, sal_False); 423 if (pBackgroundBrush) 424 { 425 Color& rBackgroundColor = const_cast<SvxBrushItem*>(pBackgroundBrush)->GetColor(); 426 rBackgroundColor.SetTransparency(0xFE); 427 } 428 else 429 { 430 Color aColor = Color(0xff, 0xff, 0xff); 431 aColor.SetTransparency( 0xFE); 432 SvxBrushItem aBrush(aColor, RES_BACKGROUND); 433 aTmpSet.Put(aBrush, RES_BACKGROUND); 434 } 435 } 436 // #117914# Topic 6. 437 pFlySave->aFlySet.Put( aTmpSet ); 438 if( pSrcNd && pSrcNd->HasSwAttrSet() ) 439 { 440 pSrcNd->ResetAttr( RES_BACKGROUND, RES_BOX ); 441 } 442 } 443 444 SwFlyFrmFmt* pFmt = pDoc->MakeFlyFrmFmt( aEmptyStr, pParent ); 445 pFmt->SetFmtAttr( pFlySave->aFlySet ); 446 const SwFmtAnchor& rAnchor = pFmt->GetAnchor(); 447 if (FLY_AS_CHAR != rAnchor.GetAnchorId()) 448 { 449 // korrigiere noch den Absatz, ist immer der vorhergehende ! 450 // JP 20.09.95: wenn es diesen gibt! (DocAnfang!) 451 452 //JP 02.08.99: that is wrong. The anchor is ever the NEXT! 453 //JP 05.08.99: there are an Bug in the ExportFilter which will 454 // be fixed in the Version 517 - by SWG-Export 455 // the fly will be after the paragraph - but in RTF 456 // the flys will be before the paragraph. 457 if( !bSwPageDesc || 5430 < GetVersionNo() ) 458 pFlySave->nSttNd++; 459 460 // if( !pFlySave->nSttNd.GetNode().IsCntntNode() ) 461 { 462 // Seitenumbrueche in den Bodybereich verschieben! 463 SwCntntNode* pSrcNd = aRg.aStart.GetNode().GetCntntNode(); 464 SwCntntNode* pDstNd = pFlySave->nSttNd.GetNode().GetCntntNode(); 465 if( !pDstNd ) 466 pDstNd = pDoc->GetNodes().GoNext( &pFlySave->nSttNd ); 467 468 ::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nSttNd ); 469 } 470 471 const SwNodeIndex aSttNd(*pSttNd); 472 SwNodeIndex aEndNd(*pSttNd->EndOfSectionNode()); 473 aEndNd--; 474 475 SwPosition aPos( pFlySave->nSttNd ); 476 SwFmtAnchor aAnchor(rAnchor); 477 aAnchor.SetAnchor(&aPos); 478 479 const SwNode *pCurrentAnchor = &(pFlySave->nSttNd.GetNode()); 480 aPrevFmts[pCurrentAnchor].push_back(frameEntry(pFmt, aAnchor)); 481 482 while (aEndNd > aSttNd) 483 { 484 typedef rtfframesAtIndex::iterator myIter; 485 rtfframesAtIndex &rDeque = aPrevFmts[&(aEndNd.GetNode())]; 486 myIter aEnd = rDeque.end(); 487 for (myIter aIter = rDeque.begin(); aIter != aEnd; ++aIter) 488 { 489 aIter->second.SetAnchor(&aPos); 490 // --> OD 2004-06-30 #i27767# - push on front to keep order 491 // of objects for the correct object positioning 492 //aPrevFmts[pCurrentAnchor].push_back(*aIter); 493 aPrevFmts[pCurrentAnchor].push_front(*aIter); 494 } 495 rDeque.clear(); 496 aEndNd--; 497 } 498 } 499 500 // --> OD, FLR 2006-02-16 #131205# 501 // Create draw contact object, which also creates a <SdrObject> instance, 502 // in order to set the order number. 503 // The order number is assumed to be the order of the text flow. 504 SwFlyDrawContact* pContact = 505 new SwFlyDrawContact( pFmt, 506 pFmt->GetDoc()->GetOrCreateDrawModel() ); 507 pContact->GetMaster()->SetOrdNum( n ); 508 // <-- 509 510 delete pFlySave; 511 } 512 513 typedef rtfFmtMap::reverse_iterator myriter; 514 myriter aEnd = aPrevFmts.rend(); 515 for(myriter aIter = aPrevFmts.rbegin(); aIter != aEnd; ++aIter) 516 { 517 rtfframesAtIndex &rDeque = aIter->second; 518 typedef rtfframesAtIndex::iterator myIter; 519 myIter aQEnd = rDeque.end(); 520 for (myIter aQIter = rDeque.begin(); aQIter != aQEnd; ++aQIter) 521 { 522 frameEntry &rEntry = *aQIter; 523 SwFlyFrmFmt *pFrm = rEntry.first; 524 SwFmtAnchor &rAnchor = rEntry.second; 525 pFrm->SetFmtAttr(rAnchor); 526 } 527 } 528 529 aFlyArr.Remove(0, aFlyArr.Count()); 530 } 531 532 // clips the text box to the min or max position if it is outside our min or max boundary 533 long SwRTFParser::GetSafePos(long nPos) 534 { 535 if(nPos > SHRT_MAX) 536 nPos = SHRT_MAX; 537 else if(nPos < SHRT_MIN) 538 nPos = SHRT_MIN; 539 540 return nPos; 541 } 542 543 void SwRTFParser::ReadFly( int nToken, SfxItemSet* pSet ) 544 { 545 // ein Set fuer die FrmFmt-Attribute 546 SfxItemSet aSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1 ); 547 if( !IsNewDoc() ) 548 Reader::ResetFrmFmtAttrs( aSet ); 549 550 // der Fly beginnt immer in einem neuen Absatz 551 if( pPam->GetPoint()->nContent.GetIndex() ) 552 InsertPara(); 553 554 // RTF-Defaults setzen: 555 // --> OD 2004-06-24 #i27767# 556 SwFmtAnchor aAnchor( FLY_AT_PARA ); 557 558 SwFmtHoriOrient aHori( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME ); 559 SwFmtVertOrient aVert( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ); 560 // <-- 561 SvxFrameDirectionItem aFrmDir( FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR ); 562 563 sal_uInt16 nCols = USHRT_MAX, nColSpace = USHRT_MAX, nAktCol = 0; 564 SvUShorts aColumns; 565 566 sal_Bool bChkDropCap = 0 == pSet; 567 sal_uInt16 nDropCapLines = 0, nDropCapAnchor = 0; 568 int nNumOpenBrakets = GetOpenBrakets(); 569 570 if( !pSet ) 571 { 572 pSet = &aSet; 573 } 574 else 575 { 576 // die Werte aus dem uebergebenen! 577 aAnchor = (SwFmtAnchor&)pSet->Get( RES_ANCHOR ); 578 aHori = (SwFmtHoriOrient&)pSet->Get( RES_HORI_ORIENT ); 579 aVert = (SwFmtVertOrient&)pSet->Get( RES_VERT_ORIENT ); 580 } 581 582 // dann sammel mal alle Attribute zusammen 583 int bWeiter = sal_True; 584 int nAppliedProps=0; 585 do { 586 sal_uInt16 nVal = sal_uInt16(nTokenValue); 587 /* 588 #i5263# 589 Assume that a property genuinely contributes towards creating a frame, 590 and if turns out to be a non contributing one reduce the count. 591 */ 592 ++nAppliedProps; 593 switch( nToken ) 594 { 595 case RTF_ABSW: 596 { 597 SwFmtFrmSize aSz( ATT_MIN_SIZE, nTokenValue, 0 ); 598 const SfxPoolItem* pItem; 599 if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, sal_True, 600 &pItem )) 601 { 602 aSz.SetHeightSizeType( ((SwFmtFrmSize*)pItem)->GetHeightSizeType() ); 603 aSz.SetHeight( ((SwFmtFrmSize*)pItem)->GetHeight() ); 604 } 605 if( MINFLY > nTokenValue ) nTokenValue = MINFLY; 606 aSet.Put( aSz ); 607 } 608 break; 609 case RTF_ABSH: 610 { 611 SwFmtFrmSize aSz( ATT_MIN_SIZE, 0, MINFLY ); 612 const SfxPoolItem* pItem; 613 if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, sal_True, 614 &pItem )) 615 { 616 aSz.SetWidth( ((SwFmtFrmSize*)pItem)->GetWidth() ); 617 } 618 619 if( 0 > nTokenValue ) 620 { 621 nTokenValue = -nTokenValue; 622 aSz.SetHeightSizeType( ATT_FIX_SIZE ); 623 } 624 if( MINFLY > nTokenValue ) nTokenValue = MINFLY; 625 aSz.SetHeight( nTokenValue ); 626 aSet.Put( aSz ); 627 } 628 break; 629 630 case RTF_NOWRAP: 631 { 632 pSet->Put( SwFmtSurround( SURROUND_NONE )); 633 } 634 break; 635 case RTF_DXFRTEXT: 636 { 637 SvxULSpaceItem aUL( RES_UL_SPACE ); 638 SvxLRSpaceItem aLR( RES_LR_SPACE ); 639 aUL.SetUpper( nVal ); aUL.SetLower( nVal ); 640 aLR.SetLeft( nVal ); aLR.SetRight( nVal ); 641 pSet->Put( aUL ); 642 pSet->Put( aLR ); 643 } 644 break; 645 646 case RTF_DFRMTXTX: 647 { 648 SvxLRSpaceItem aLR( RES_LR_SPACE ); 649 aLR.SetLeft( nVal ); aLR.SetRight( nVal ); 650 pSet->Put( aLR ); 651 } 652 break; 653 case RTF_DFRMTXTY: 654 { 655 SvxULSpaceItem aUL( RES_UL_SPACE ); 656 aUL.SetUpper( nVal ); aUL.SetLower( nVal ); 657 pSet->Put( aUL ); 658 } 659 break; 660 661 case RTF_POSNEGX: 662 case RTF_POSX: aHori.SetHoriOrient( text::HoriOrientation::NONE ); 663 aHori.SetPos( GetSafePos((long)nTokenValue) ); 664 break; 665 case RTF_POSXC: aHori.SetHoriOrient( text::HoriOrientation::CENTER ); break; 666 case RTF_POSXI: aHori.SetHoriOrient( text::HoriOrientation::LEFT ); 667 aHori.SetPosToggle( sal_True ); 668 break; 669 case RTF_POSXO: aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); 670 aHori.SetPosToggle( sal_True ); 671 break; 672 case RTF_POSXL: aHori.SetHoriOrient( text::HoriOrientation::LEFT ); break; 673 case RTF_POSXR: aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); break; 674 675 case RTF_POSNEGY: 676 case RTF_POSY: aVert.SetVertOrient( text::VertOrientation::NONE ); 677 aVert.SetPos( GetSafePos((long)nTokenValue) ); 678 break; 679 case RTF_POSYT: aVert.SetVertOrient( text::VertOrientation::TOP ); break; 680 case RTF_POSYB: aVert.SetVertOrient( text::VertOrientation::BOTTOM ); break; 681 case RTF_POSYC: aVert.SetVertOrient( text::VertOrientation::CENTER ); break; 682 683 case RTF_PHMRG: aHori.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break; 684 case RTF_PVMRG: aVert.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break; 685 case RTF_PHPG: aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME ); break; 686 case RTF_PVPG: aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );break; 687 case RTF_PHCOL: aHori.SetRelationOrient( text::RelOrientation::FRAME ); break; 688 case RTF_PVPARA: aVert.SetRelationOrient( text::RelOrientation::FRAME ); break; 689 690 case RTF_POSYIL: 691 break; 692 case RTF_ABSLOCK: 693 /* 694 #i5263# 695 Not sufficient to make a frame at least word won't do it with just 696 an abslock 697 */ 698 --nAppliedProps; 699 break; 700 case RTF_FRMTXLRTB: 701 aFrmDir.SetValue( FRMDIR_HORI_LEFT_TOP ); 702 break; 703 case RTF_FRMTXTBRL: 704 aFrmDir.SetValue( FRMDIR_HORI_RIGHT_TOP ); 705 break; 706 case RTF_FRMTXLRTBV: 707 aFrmDir.SetValue( FRMDIR_VERT_TOP_LEFT ); 708 break; 709 case RTF_FRMTXTBRLV: 710 aFrmDir.SetValue( FRMDIR_VERT_TOP_RIGHT ); 711 break; 712 713 case RTF_DROPCAPLI: // Dropcaps !! 714 if( bChkDropCap ) 715 { 716 nDropCapLines = sal_uInt16( nTokenValue ); 717 if( !nDropCapAnchor ) 718 nDropCapAnchor = 1; 719 } 720 break; 721 case RTF_DROPCAPT: 722 if( bChkDropCap ) 723 { 724 nDropCapAnchor = sal_uInt16( nTokenValue ); 725 if( !nDropCapLines ) 726 nDropCapLines = 3; 727 } 728 break; 729 730 731 // fuer die "alten" Writer - haben die Spaltigkeit falsch heraus- 732 // geschrieben 733 case RTF_COLS: nCols = sal_uInt16( nTokenValue ); break; 734 case RTF_COLSX: nColSpace = sal_uInt16( nTokenValue ); break; 735 case RTF_COLNO: 736 nAktCol = sal_uInt16( nTokenValue ); 737 if( RTF_COLW == GetNextToken() ) 738 { 739 sal_uInt16 nWidth = sal_uInt16( nTokenValue ), nSpace = 0; 740 if( RTF_COLSR == GetNextToken() ) 741 nSpace = sal_uInt16( nTokenValue ); 742 else 743 SkipToken( -1 ); // wieder zurueck 744 745 if( --nAktCol == ( aColumns.Count() / 2 ) ) 746 { 747 aColumns.Insert( nWidth + nSpace, aColumns.Count() ); 748 aColumns.Insert( nSpace, aColumns.Count() ); 749 } 750 } 751 break; 752 753 case '{': 754 { 755 short nSkip = 0; 756 if( RTF_IGNOREFLAG != ( nToken = GetNextToken() )) 757 { 758 if( RTF_SHADINGDEF == (nToken & ~0xff) ) 759 { 760 ReadBackgroundAttr( nToken, aSet ); 761 GetNextToken(); // Klammer ueberlesen 762 } 763 else 764 nSkip = -1; 765 } 766 else if( RTF_APOCTL == 767 ((nToken = GetNextToken() ) & ~(0xff | RTF_SWGDEFS)) ) 768 { 769 bReadSwFly = true; // alles kommt in den akt. Fly 770 SvxLRSpaceItem aLR( RES_LR_SPACE ); 771 SvxULSpaceItem aUL( RES_UL_SPACE ); 772 nCols = USHRT_MAX; // neu aufsetzen 773 nColSpace = USHRT_MAX; 774 do { 775 nVal = sal_uInt16(nTokenValue); 776 switch( nToken ) 777 { 778 // Swg-Frame-Tokens 779 case RTF_FLYPRINT: 780 { 781 pSet->Put( SvxPrintItem( RES_PRINT, sal_False )); 782 } 783 break; 784 case RTF_FLYOPAQUE: 785 { 786 pSet->Put( SvxOpaqueItem( RES_OPAQUE, sal_False )); 787 } 788 break; 789 790 case RTF_FLYPRTCTD: 791 { 792 RTFProtect aP( (sal_uInt8)nTokenValue ); 793 SvxProtectItem aProtectItem( RES_PROTECT ); 794 aProtectItem.SetCntntProtect( aP.GetCntnt() ); 795 aProtectItem.SetSizeProtect( aP.GetSize() ); 796 aProtectItem.SetPosProtect( aP.GetPos() ); 797 pSet->Put( aProtectItem ); 798 } 799 break; 800 801 case RTF_FLYMAINCNT: 802 { 803 RTFSurround aMC( (sal_uInt8)nTokenValue ); 804 SwFmtSurround aSurr( (SwSurround)aMC.GetOrder()); 805 if( aMC.GetGoldCut() ) 806 aSurr.SetSurround( SURROUND_IDEAL ); 807 pSet->Put( aSurr ); 808 } 809 break; 810 case RTF_FLYVERT: 811 { 812 RTFVertOrient aVO( nVal ); 813 aVert.SetVertOrient( aVO.GetOrient() ); 814 aVert.SetRelationOrient( aVO.GetRelation() ); 815 } 816 break; 817 case RTF_FLYHORZ: 818 { 819 RTFHoriOrient aHO( nVal ); 820 aHori.SetHoriOrient( aHO.GetOrient() ); 821 aHori.SetRelationOrient( aHO.GetRelation() ); 822 } 823 break; 824 case RTF_FLYOUTLEFT: aLR.SetLeft( nVal ); break; 825 case RTF_FLYOUTRIGHT: aLR.SetRight( nVal ); break; 826 case RTF_FLYOUTUPPER: aUL.SetUpper( nVal ); break; 827 case RTF_FLYOUTLOWER: aUL.SetLower( nVal ); break; 828 case RTF_FLYANCHOR: 829 switch( GetNextToken() ) 830 { 831 case RTF_FLY_PAGE: 832 aAnchor.SetType( FLY_AT_PAGE ); 833 aAnchor.SetPageNum( sal_uInt16(nTokenValue)); 834 aAnchor.SetAnchor( 0 ); 835 break; 836 837 case RTF_FLY_CNTNT: 838 { 839 SwNodeIndex aIdx( pPam->GetPoint()->nNode ); 840 pDoc->GetNodes().GoPrevious( &aIdx ); 841 SwPosition aPos( aIdx ); 842 aAnchor.SetType( FLY_AT_PARA ); 843 aAnchor.SetAnchor( &aPos ); 844 } 845 break; 846 847 // JP 26.09.94: die Bindung an die Spalte gibt es nicht mehr !! 848 // case RTF_FLY_COLUMN: 849 } 850 break; 851 case RTF_COLS: nCols = sal_uInt16( nTokenValue ); break; 852 case RTF_COLSX: nColSpace = sal_uInt16( nTokenValue ); break; 853 case RTF_COLNO: 854 nAktCol = sal_uInt16( nTokenValue ); 855 if( RTF_COLW == GetNextToken() ) 856 { 857 sal_uInt16 nWidth = sal_uInt16( nTokenValue ), nSpace = 0; 858 if( RTF_COLSR == GetNextToken() ) 859 nSpace = sal_uInt16( nTokenValue ); 860 else 861 SkipToken( -1 ); // wieder zurueck 862 863 if( --nAktCol == ( aColumns.Count() / 2 ) ) 864 { 865 aColumns.Insert( nWidth + nSpace, aColumns.Count() ); 866 aColumns.Insert( nSpace, aColumns.Count() ); 867 } 868 } 869 break; 870 871 case '{': 872 if( RTF_BRDBOX == ( nToken = GetNextToken() ) ) 873 ReadBorderAttr( nToken, aSet ); 874 else if( RTF_SHADINGDEF == (nToken & ~0xff ) ) 875 ReadBackgroundAttr( nToken, aSet ); 876 else if( RTF_IGNOREFLAG == nToken ) 877 { 878 int bSkipGrp = sal_True; 879 switch( nToken = GetNextToken() ) 880 { 881 case RTF_SHADOW: 882 case RTF_BRDBOX: 883 ReadAttr( SkipToken( -2 ), &aSet ); 884 bSkipGrp = sal_False; 885 break; 886 887 case RTF_BRDRT: 888 case RTF_BRDRB: 889 case RTF_BRDRR: 890 case RTF_BRDRL: 891 bSkipGrp = sal_False; 892 ReadBorderAttr( SkipToken( -2 ), aSet ); 893 break; 894 } 895 896 // keine weitere Klammer mehr ueberlesen!!! 897 if( !bSkipGrp ) 898 break; 899 900 SkipGroup(); 901 } 902 else 903 SkipGroup(); 904 GetNextToken(); // Klammer ueberlesen 905 break; 906 } 907 } while( IsParserWorking() && 908 '}' != ( nToken = GetNextToken() )); 909 910 if( aUL.GetUpper() || aUL.GetLower() ) 911 pSet->Put( aUL ); 912 if( aLR.GetLeft() || aLR.GetRight() ) 913 pSet->Put( aLR ); 914 } 915 else if( RTF_BRDBOX == nToken ) 916 ReadBorderAttr( nToken, aSet ); 917 else if( RTF_SHADOW == nToken ) 918 ReadAttr( SkipToken( -2 ), &aSet ); 919 else if( RTF_SHADINGDEF == (nToken & ~0xff ) ) 920 ReadBackgroundAttr( nToken, aSet ); 921 else if( RTF_UNKNOWNCONTROL == nToken ) 922 SkipGroup(); 923 else 924 nSkip = -2; 925 926 if( nSkip ) 927 { 928 nToken = SkipToken( nSkip ); 929 bWeiter = sal_False; 930 } 931 } 932 break; 933 934 default: 935 --nAppliedProps; //Not sufficient to make a frame 936 bWeiter = sal_False; 937 } 938 939 if( bWeiter ) 940 nToken = GetNextToken(); 941 } while( bWeiter && IsParserWorking() ); 942 943 pSet->Put( aAnchor ); 944 pSet->Put( aHori ); 945 pSet->Put( aVert ); 946 947 // --> OD 2004-06-30 #i27767# - set wrapping style influence 948 // --> OD 2004-10-18 #i35017# - constant name has changed 949 pSet->Put( SwFmtWrapInfluenceOnObjPos( 950 text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE )); 951 // <-- 952 953 SwFmtFollowTextFlow aFollowTextFlow( sal_False ); 954 pSet->Put( aFollowTextFlow ); 955 956 if( !( aFrmDir == pSet->Get( RES_FRAMEDIR )) ) 957 pSet->Put( aFrmDir ); 958 959 if( nCols && USHRT_MAX != nCols ) 960 { 961 SwFmtCol aCol; 962 if( USHRT_MAX == nColSpace ) 963 nColSpace = 720; 964 965 sal_uLong nWidth = USHRT_MAX; 966 aCol.Init( nCols, nColSpace, sal_uInt16( nWidth ) ); 967 if( nCols == ( aColumns.Count() / 2 ) ) 968 { 969 for( sal_uInt16 n = 0, i = 0; n < aColumns.Count(); n += 2, ++i ) 970 { 971 SwColumn* pCol = aCol.GetColumns()[ i ]; 972 sal_uLong nTmp = aColumns[ n ]; 973 nTmp *= USHRT_MAX; 974 nTmp /= nWidth; 975 pCol->SetWishWidth( sal_uInt16(nTmp) ); 976 /* 977 JP 07.07.95: der Dialog kennt nur eine Breite fuer alle Spalten 978 darum hier nicht weiter beachten 979 nTmp = aColumns[ n+1 ]; 980 if( nTmp ) 981 pCol->SetRight( sal_uInt16(nTmp) ); 982 else 983 pCol->SetRight( 0 ); 984 pCol->SetLeft( 0 ); 985 */ 986 } 987 } 988 pSet->Put( aCol ); 989 } 990 991 if( pSet != &aSet ) // wurde der Set uebergeben, dann wars das 992 return ; 993 994 // ein neues FlyFormat anlegen oder das alte benutzen ? 995 // (teste ob es die selben Attribute besitzt!) 996 SwFlySave* pFlySave = 0; 997 sal_uInt16 nFlyArrCnt = aFlyArr.Count(); 998 /* 999 #i5263# 1000 There were not enough frame properties found to actually justify creating 1001 an absolutely positioned frame. 1002 */ 1003 if (nAppliedProps) 1004 { 1005 if( !nFlyArrCnt || 1006 !( pFlySave = aFlyArr[ nFlyArrCnt-1 ])->IsEqualFly( *pPam, aSet )) 1007 { 1008 pFlySave = new SwFlySave( *pPam, aSet ); 1009 Size aPgSize; 1010 GetPageSize( aPgSize ); 1011 pFlySave->nPageWidth = aPgSize.Width(); 1012 1013 if( nDropCapAnchor ) 1014 { 1015 pFlySave->nDropAnchor = nDropCapAnchor; 1016 pFlySave->nDropLines = nDropCapLines; 1017 } 1018 if (nFlyArrCnt >0){ 1019 SwFlySave* pFlySavePrev = aFlyArr[nFlyArrCnt-1]; 1020 if (pFlySave->nSttNd.GetIndex() < pFlySavePrev->nEndNd.GetIndex()) 1021 { 1022 pFlySavePrev->nEndNd=pFlySave->nSttNd; 1023 } 1024 } 1025 aFlyArr.Insert( pFlySave, nFlyArrCnt++ ); 1026 // --> OD 2008-12-22 #i83368# - reset 1027 mbReadCellWhileReadSwFly = false; 1028 // <-- 1029 } 1030 } 1031 1032 SetPardTokenRead( sal_False ); 1033 const SwTableNode* pTblNd = pPam->GetNode()->FindTableNode(); 1034 1035 while( !IsPardTokenRead() && IsParserWorking() ) 1036 { 1037 if( RTF_PARD == nToken || nNumOpenBrakets > GetOpenBrakets() ) 1038 break; 1039 1040 NextToken( nToken ); 1041 1042 if( !IsPardTokenRead() ) 1043 { 1044 // #102781#. Added support for transparent frames. 1045 if (nToken == RTF_CBPAT && nFlyArrCnt > 0) 1046 { 1047 sal_uInt16 _index=sal_uInt16(nTokenValue); 1048 const Color& rColor = GetColor(_index); 1049 SvxBrushItem aBrush(rColor, RES_BACKGROUND); 1050 SwFlySave* pFS = aFlyArr[nFlyArrCnt-1]; 1051 pFS->aFlySet.Put(aBrush, RES_BACKGROUND); 1052 } 1053 1054 nToken = GetNextToken(); 1055 1056 // BUG 22036: kommt zwischen Fly-Attributen ein unbekanntes, 1057 // dann erzeuge nie 2 FlyFrames, sondern fasse 1058 // beide zusammen !!! 1059 while( RTF_APOCTL == ( nToken & ~(0xff | RTF_SWGDEFS) )) 1060 { 1061 if( RTF_FLY_INPARA == nToken ) 1062 break; 1063 1064 if( RTF_IGNOREFLAG == SkipToken( -1 ) ) 1065 { 1066 if( '{' == SkipToken( -1 ) ) 1067 nToken = '{'; 1068 else 1069 SkipToken( 2 ); 1070 } 1071 else 1072 SkipToken( 1 ); 1073 1074 ReadFly( nToken, pFlySave ? &pFlySave->aFlySet : 0); 1075 nToken = GetNextToken(); 1076 } 1077 } 1078 } 1079 1080 /* 1081 #i5263# 1082 There were enough frame properties found to actually justify creating 1083 an absolutely positioned frame. 1084 */ 1085 if (!nAppliedProps) 1086 { 1087 bReadSwFly = false; 1088 SkipToken( -1 ); 1089 return; 1090 } 1091 1092 if( pTblNd && !pPam->GetPoint()->nContent.GetIndex() && 1093 pTblNd->EndOfSectionIndex() + 1 == 1094 pPam->GetPoint()->nNode.GetIndex() ) 1095 { 1096 // nicht mehr in der Tabelle, sondern dahinter ? 1097 // Dann aber wieder zurueck in die Tabelle 1098 pPam->Move( fnMoveBackward ); 1099 } 1100 else 1101 pTblNd = 0; 1102 1103 // wurde garnichts eingefuegt? 1104 if( !pTblNd && 1105 pPam->GetPoint()->nNode == pFlySave->nSttNd && 1106 !pPam->GetPoint()->nContent.GetIndex() ) 1107 { 1108 // // dann erzeuge mindestens einen leeren TextNode 1109 // pDoc->AppendTxtNode(*pPam); 1110 // dann zerstoere den FlySave wieder. 1111 aFlyArr.DeleteAndDestroy( --nFlyArrCnt ); 1112 1113 } 1114 else 1115 { 1116 sal_Bool bMovePaM = 0 != pTblNd; 1117 1118 pFlySave->nEndNd = pPam->GetPoint()->nNode; 1119 pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex(); 1120 1121 if( bMovePaM ) 1122 pPam->Move( fnMoveForward ); 1123 1124 pTblNd = pFlySave->nSttNd.GetNode().FindTableNode(); 1125 if( pTblNd && !pFlySave->nEndCnt && 1126 pTblNd == pFlySave->nEndNd.GetNode().FindTableNode() ) 1127 { 1128 // dann teste mal, ob das \pard nicht zu spaet kam und 1129 // eigentlich in die vorherige Zelle gehoert 1130 const SwStartNode* pSttBoxNd = pFlySave->nSttNd.GetNode(). 1131 FindTableBoxStartNode(), 1132 * pEndBoxNd = pFlySave->nEndNd.GetNode(). 1133 FindTableBoxStartNode(); 1134 if( pSttBoxNd && pEndBoxNd && 1135 bMovePaM ? ( pSttBoxNd == pEndBoxNd ) 1136 : ( pSttBoxNd->EndOfSectionIndex() + 1 == 1137 pEndBoxNd->GetIndex() && 1138 pEndBoxNd->GetIndex() + 1 == 1139 pFlySave->nEndNd.GetIndex() )) 1140 { 1141 // dann gehoert das Ende in die vorherige Box! 1142 SwPosition aPos( *pPam->GetPoint() ); 1143 pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode(); 1144 pPam->Move( fnMoveBackward, fnGoNode ); 1145 1146 DelLastNode(); 1147 1148 pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode(); 1149 pPam->Move( fnMoveBackward, fnGoNode ); 1150 1151 pFlySave->nEndNd = pPam->GetPoint()->nNode; 1152 pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex(); 1153 1154 *pPam->GetPoint() = aPos; 1155 } 1156 } 1157 else if( !bReadSwFly && !pFlySave->nEndCnt && 1158 pFlySave->nSttNd.GetIndex() + 1 == pFlySave->nEndNd.GetIndex() && 1159 pFlySave->nSttNd.GetNode().IsTxtNode() ) 1160 { 1161 1162 SwTxtNode* pTxtNd = pFlySave->nSttNd.GetNode().GetTxtNode(); 1163 SwTxtFlyCnt* pFlyCnt = 0; 1164 if( 1 == pTxtNd->GetTxt().Len() && 1165 0 != (pFlyCnt = static_cast<SwTxtFlyCnt*>( 1166 pTxtNd->GetTxtAttrForCharAt(0, RES_TXTATR_FLYCNT))) && 1167 pFlyCnt->GetFlyCnt().GetFrmFmt() ) 1168 { 1169 // then move the content into the surrounded fly 1170 SwFrmFmt* pFlyFmt = pFlyCnt->GetFlyCnt().GetFrmFmt(); 1171 const SwNodeIndex* pFlySNd = pFlyFmt->GetCntnt().GetCntntIdx(); 1172 SwNodeRange aRg( *pFlySNd, 1, 1173 *pFlySNd->GetNode().EndOfSectionNode(), 0 ); 1174 1175 // merge the itemsets 1176 SwFmtFrmSize aSz1( (SwFmtFrmSize&)pFlyFmt->GetAttrSet(). 1177 Get( RES_FRM_SIZE )); 1178 SwFmtFrmSize aSz2( (SwFmtFrmSize&)pFlySave->aFlySet. 1179 Get( RES_FRM_SIZE )); 1180 // if 1181 if( !aRg.aStart.GetNode().IsNoTxtNode() || 1182 !aSz1.GetHeight() || !aSz1.GetWidth() || 1183 !aSz2.GetHeight() || !aSz2.GetWidth() || 1184 ( aSz1.GetHeight() == aSz2.GetHeight() && 1185 aSz1.GetWidth() == aSz2.GetWidth() ) ) 1186 { 1187 SfxItemSet aDiffs( pFlyFmt->GetAttrSet() ); 1188 aDiffs.ClearItem( RES_ANCHOR ); 1189 aDiffs.ClearItem( RES_FRM_SIZE ); 1190 aDiffs.ClearItem( RES_CNTNT ); 1191 aDiffs.Differentiate( pFlySave->aFlySet ); 1192 pFlySave->aFlySet.Put( aDiffs ); 1193 1194 sal_Bool bSet = sal_False; 1195 if( aSz1.GetHeight() && !aSz2.GetHeight() ) 1196 { 1197 bSet = sal_True; 1198 aSz2.SetHeight( aSz1.GetHeight() ); 1199 } 1200 if( aSz1.GetWidth() && !aSz2.GetWidth() ) 1201 { 1202 bSet = sal_True; 1203 aSz2.SetWidth( aSz1.GetWidth() ); 1204 } 1205 if( bSet ) 1206 pFlySave->aFlySet.Put( aSz2 ); 1207 1208 // move any PageBreak/Desc Attr to the next Para 1209 { 1210 SwCntntNode* pSrcNd = pFlySave->nSttNd.GetNode().GetCntntNode(); 1211 SwCntntNode* pDstNd = pFlySave->nEndNd.GetNode().GetCntntNode(); 1212 1213 ::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nEndNd ); 1214 } 1215 1216 // create new txtnode, because the section does never be empty 1217 pDoc->GetNodes().MakeTxtNode( aRg.aStart, 1218 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() ); 1219 1220 SwNodeIndex aTmp( pFlySave->nSttNd, +1 ); 1221 pDoc->MoveNodeRange( aRg, aTmp, 1222 IDocumentContentOperations::DOC_MOVEDEFAULT ); 1223 1224 // now delete the redundant txtnode 1225 pDoc->GetNodes().Delete( pFlySave->nSttNd, 1 ); 1226 } 1227 } 1228 } 1229 } 1230 1231 bReadSwFly = false; 1232 SkipToken( -1 ); 1233 } 1234 1235 1236 void SwRTFParser::InsPicture( const String& rGrfNm, const Graphic* pGrf, 1237 const SvxRTFPictureType* pPicType ) 1238 { 1239 // kennzeichen fuer Swg-Dokumente: 1240 // (dann ist das FlyFmt fuer die Grafik!) 1241 SwGrfNode * pGrfNd; 1242 // --> OD 2008-12-22 #i83368# 1243 // Assure that graphic node is enclosed by fly frame node. 1244 // if( bReadSwFly ) 1245 if ( bReadSwFly && !mbReadCellWhileReadSwFly ) 1246 // <-- 1247 { 1248 OSL_ENSURE(aFlyArr.Count(), 1249 "SwRTFParser::InsPicture: fly array empty."); 1250 if (aFlyArr.Count()) 1251 { 1252 // erzeuge nur einen normalen GrafikNode und ersetze diesen gegen 1253 // den vorhandenen Textnode 1254 SwNodeIndex& rIdx = pPam->GetPoint()->nNode; 1255 pGrfNd = pDoc->GetNodes().MakeGrfNode( rIdx, 1256 rGrfNm, aEmptyStr, // Name der Graphic !! 1257 pGrf, 1258 (SwGrfFmtColl*)pDoc->GetDfltGrfFmtColl() ); 1259 1260 if( pGrfAttrSet ) 1261 pGrfNd->SetAttr( *pGrfAttrSet ); 1262 1263 SwFlySave* pFlySave = aFlyArr[ aFlyArr.Count()-1 ]; 1264 pFlySave->nSttNd = rIdx.GetIndex() - 1; 1265 1266 if( 1 < aFlyArr.Count() ) 1267 { 1268 pFlySave = aFlyArr[ aFlyArr.Count() - 2 ]; 1269 if( pFlySave->nEndNd == rIdx ) 1270 pFlySave->nEndNd = rIdx.GetIndex() - 1; 1271 } 1272 } 1273 } 1274 else 1275 { 1276 // wenn normale RTF-Grafik, dann steht diese im Textfluss ! 1277 SwAttrSet aFlySet( pDoc->GetAttrPool(), RES_OPAQUE, /*RES_OPAQUE, 1278 RES_VERT_ORIENT,*/ RES_ANCHOR ); 1279 const SwPosition* pPos = pPam->GetPoint(); 1280 1281 SwFmtAnchor aAnchor( FLY_AS_CHAR ); 1282 aAnchor.SetAnchor( pPos ); 1283 aFlySet.Put( aAnchor ); 1284 aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP )); 1285 1286 if (pDoc->IsInHeaderFooter(pPos->nNode)) 1287 { 1288 SvxOpaqueItem aOpaqueItem(RES_OPAQUE, sal_False); 1289 SwFmtSurround aSurroundItem(SURROUND_THROUGHT); 1290 aFlySet.Put(aOpaqueItem); 1291 aFlySet.Put(aSurroundItem); 1292 } 1293 1294 SwFlyFrmFmt* pFlyFmt = pDoc->Insert( *pPam, 1295 rGrfNm, aEmptyStr, // Name der Graphic !! 1296 pGrf, 1297 &aFlySet, // Attribute fuer den FlyFrm 1298 pGrfAttrSet, NULL ); // Attribute fuer die Grafik 1299 1300 pGrfNd = pDoc->GetNodes()[ pFlyFmt->GetCntnt().GetCntntIdx()-> 1301 GetIndex()+1 ]->GetGrfNode(); 1302 1303 _SetPictureSize( *pGrfNd, pPos->nNode, 1304 (SfxItemSet&)pFlyFmt->GetAttrSet(), 1305 pPicType ); 1306 if( pPicType ) 1307 { 1308 PictPropertyNameValuePairs::const_iterator aIt = pPicType->aPropertyPairs.begin(); 1309 PictPropertyNameValuePairs::const_iterator aEnd = pPicType->aPropertyPairs.end(); 1310 while( aIt != aEnd) 1311 { 1312 if( aIt->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "wzDescription") )) 1313 { 1314 SwXFrame::GetOrCreateSdrObject( pFlyFmt ); 1315 pDoc->SetFlyFrmDescription( *(pFlyFmt), aIt->second ); 1316 } 1317 else if( aIt->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM( "wzName") )) 1318 { 1319 SwXFrame::GetOrCreateSdrObject( pFlyFmt ); 1320 pDoc->SetFlyFrmTitle( *(pFlyFmt), aIt->second ); 1321 } 1322 ++aIt; 1323 } 1324 } 1325 1326 } 1327 1328 if( pGrfAttrSet ) 1329 DELETEZ( pGrfAttrSet ); 1330 } 1331 1332 void SwRTFParser::_SetPictureSize( const SwNoTxtNode& rNd, 1333 const SwNodeIndex& rAnchor, 1334 SfxItemSet& rSet, 1335 const SvxRTFPictureType* pPicType ) 1336 { 1337 Size aSize( ((SwNoTxtNode&)rNd).GetTwipSize() ); 1338 if( pPicType ) 1339 { 1340 if( rNd.IsGrfNode() ) 1341 { 1342 if( SvxRTFPictureType::WIN_METAFILE != pPicType->eStyle && 1343 pPicType->nGoalWidth && pPicType->nGoalHeight ) 1344 { 1345 aSize.Width() = pPicType->nGoalWidth; 1346 aSize.Height() =pPicType->nGoalHeight; 1347 } 1348 else if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle ) 1349 { 1350 // IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !! 1351 aSize.Width() = pPicType->nWidth * 20; 1352 aSize.Height() = pPicType->nHeight * 20; 1353 } 1354 else 1355 { 1356 // von 100TH_MM nach TWIP umrechenen! 1357 // #117879# when \picwgoal resp \pichgoal are present, then use them. 1358 // The values of \picwgoal and \picwgoal are already given in twips. 1359 aSize.Width() = (pPicType->nGoalWidth?pPicType->nGoalWidth:(pPicType->nWidth*144)/254); 1360 aSize.Height() = (pPicType->nGoalHeight?pPicType->nGoalHeight:(pPicType->nHeight*144)/254); 1361 } 1362 ((SwGrfNode&)rNd).SetTwipSize( aSize ); 1363 } 1364 1365 if( 100 != pPicType->nScalX ) 1366 aSize.Width() = (((long)pPicType->nScalX) * ( aSize.Width() - 1367 ( pPicType->nCropL + pPicType->nCropR ))) / 100L; 1368 1369 if( 100 != pPicType->nScalY ) 1370 aSize.Height() = (((long)pPicType->nScalY) * ( aSize.Height() - 1371 ( pPicType->nCropT + pPicType->nCropB ))) / 100L; 1372 } 1373 1374 //steht der Fly etwa in einer Tabelle ? 1375 const SwNode* pAnchorNd = & rAnchor.GetNode(); 1376 const SwTableNode* pTblNd = pAnchorNd->FindTableNode(); 1377 if( pTblNd ) 1378 { 1379 // Box feststellen: 1380 const SwTableBox* pBox = pTblNd->GetTable().GetTblBox( 1381 pAnchorNd->StartOfSectionIndex() ); 1382 if( pBox ) 1383 { 1384 long nBoxWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth(); 1385 if( aSize.Width() > nBoxWidth ) 1386 aSize.Width() = nBoxWidth; 1387 } 1388 } 1389 1390 //JP 8.11.2001: bug 94450 - if no size exist, then the size is set by 1391 // the swapin of the graphic. 1392 SwGrfNode* pGrfNd; 1393 if( !aSize.Width() && !aSize.Height() && 1394 0 != (pGrfNd = (SwGrfNode*)rNd.GetGrfNode() ) && pGrfNd->IsGrfLink() ) 1395 pGrfNd->SetChgTwipSize( sal_True ); 1396 1397 // min. Werte einhalten !! 1398 if( aSize.Width() < MINFLY ) 1399 aSize.Width() = MINFLY; 1400 if( aSize.Height() < MINFLY) 1401 aSize.Height() = MINFLY; 1402 1403 if( pPicType ) 1404 { 1405 sal_Bool bChg = sal_False; 1406 SwCropGrf aCrop; 1407 1408 /* 1409 JP 28.07.99: Bug 67800 - no crop by MAC_QUICKDRAW. At time i dont know why 1410 it has been coded. But this has used for any 1411 RTF-File, but i dont found them. 1412 if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle ) 1413 { 1414 // evt. ein wenig Croppen ?? 1415 // IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !! 1416 long nTmp = pPicType->nWidth * 20; 1417 if( nTmp != aSize.Width() ) 1418 { 1419 // in der Breite (also rechts) croppen 1420 aCrop.Right() = nTmp - aSize.Width(); 1421 aSize.Width() = nTmp; 1422 bChg = sal_True; 1423 } 1424 1425 nTmp = pPicType->nHeight * 20; 1426 if( nTmp != aSize.Height() ) 1427 { 1428 // in der Hoehe (also unten) croppen 1429 aCrop.Bottom() = nTmp - aSize.Height(); 1430 aSize.Height() = nTmp; 1431 bChg = sal_True; 1432 } 1433 } 1434 */ 1435 if( pPicType->nCropT ) 1436 { 1437 aCrop.SetTop( pPicType->nCropT ); 1438 bChg = sal_True; 1439 } 1440 if( pPicType->nCropB ) 1441 { 1442 aCrop.SetBottom( pPicType->nCropB ); 1443 bChg = sal_True; 1444 } 1445 if( pPicType->nCropL ) 1446 { 1447 aCrop.SetLeft( pPicType->nCropL ); 1448 bChg = sal_True; 1449 } 1450 if( pPicType->nCropR ) 1451 { 1452 aCrop.SetRight( pPicType->nCropR ); 1453 bChg = sal_True; 1454 } 1455 1456 if( bChg ) 1457 { 1458 // dann mal an die CropWerte an die GrafikSize anpassen. 1459 ((SwNoTxtNode&)rNd).SetAttr( aCrop ); 1460 } 1461 } 1462 rSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aSize.Width(), aSize.Height() )); 1463 } 1464 1465 void SwRTFParser::GetPageSize( Size& rSize ) 1466 { 1467 ASSERT(!maSegments.empty(), "not possible"); 1468 if (maSegments.empty()) 1469 { 1470 rSize.Width() = 12240 - 1800 - 1800; 1471 rSize.Height() = 15840 - 1440 - 1440; 1472 return; 1473 } 1474 1475 const rtfSection &rSect = maSegments.back(); 1476 1477 rSize.Width() = rSect.maPageInfo.mnPgwsxn - rSect.maPageInfo.mnMarglsxn - rSect.maPageInfo.mnMargrsxn; 1478 rSize.Height() = rSect.maPageInfo.mnPghsxn - rSect.maPageInfo.mnMargtsxn - rSect.maPageInfo.mnMargbsxn; 1479 1480 long nCols = rSect.NoCols(); 1481 if (1 < nCols) 1482 { 1483 rSize.Width() /= nCols; 1484 rSize.Height() /= nCols; 1485 } 1486 } 1487 1488 void SwRTFParser::ReadBitmapData() 1489 { 1490 Graphic aGrf; 1491 SvxRTFPictureType aPicType; 1492 if( ReadBmpData( aGrf, aPicType ) ) 1493 InsPicture( aEmptyStr, &aGrf, &aPicType ); 1494 } 1495 1496 #ifdef READ_OLE_OBJECT 1497 void SwRTFParser::ReadOLEData() 1498 { 1499 SvCacheStream aTmpFile( 0xA000 ); 1500 Graphic aGrf; 1501 SvxRTFPictureType aPicType, aOleType; 1502 1503 int nToken, bValidOle = sal_True, bWeiter = sal_True; 1504 int nOpenBrakets = 1; // die erste wurde schon vorher erkannt !! 1505 1506 String* pStr = 0; 1507 String sObjClass, sObjName, sObjData; 1508 1509 while( nOpenBrakets && IsParserWorking() && bWeiter && bValidOle ) 1510 { 1511 nToken = GetNextToken(); 1512 sal_uInt16 nVal = sal_uInt16( nTokenValue ); 1513 switch( nToken ) 1514 { 1515 case '}': --nOpenBrakets; pStr = 0; break; 1516 case '{': 1517 { 1518 if( RTF_IGNOREFLAG != GetNextToken() ) 1519 nToken = SkipToken( -1 ); 1520 else if( RTF_UNKNOWNCONTROL != GetNextToken() ) 1521 nToken = SkipToken( -2 ); 1522 else 1523 { 1524 // gleich herausfiltern 1525 ReadUnknownData(); 1526 nToken = GetNextToken(); 1527 if( '}' != nToken ) 1528 eState = SVPAR_ERROR; 1529 break; 1530 } 1531 ++nOpenBrakets; 1532 } 1533 break; 1534 1535 case RTF_OBJECT: 1536 case RTF_OBJEMB: // default ist embedded 1537 case RTF_LINKSELF: // ?? 1538 case RTF_OBJLOCK: // ?? 1539 case RTF_OBJUPDATE: // ?? 1540 case RTF_OBJTIME: // ?? 1541 case RTF_OBJSETSIZE: 1542 case RTF_OBJALIGN: 1543 case RTF_OBJTRANSY: 1544 case RTF_OBJATTPH: 1545 break; 1546 1547 case RTF_OBJLINK: // ?? welche Daten sind das ?? 1548 case RTF_OBJAUTLINK: // ?? -""- ?? 1549 case RTF_OBJSUB: 1550 case RTF_OBJPUB: 1551 case RTF_OBJICEMB: 1552 case RTF_OBJOCX: 1553 case RTF_OBJHTML: 1554 case RTF_OBJALIAS: 1555 case RTF_OBJSECT: 1556 bValidOle = sal_False; // diese Typen koennen wir nicht 1557 break; 1558 1559 case RTF_OBJCLASS: 1560 // Daten lesen 1561 pStr = &sObjClass; 1562 break; 1563 1564 case RTF_OBJNAME: 1565 // Daten lesen 1566 pStr = &sObjName; 1567 break; 1568 1569 case RTF_OBJDATA: 1570 pStr = &sObjData; 1571 break; 1572 1573 case RTF_RESULT: 1574 { 1575 // hier weitermachen, wenn das OLE-Object ungueltig ist 1576 bWeiter = sal_False; 1577 } 1578 break; 1579 case RTF_RSLTBMP: // diese sollten wir ignorieren 1580 case RTF_RSLTMERGE: 1581 case RTF_RSLTPICT: 1582 case RTF_RSLTRTF: 1583 case RTF_RSLTTXT: 1584 break; 1585 1586 case RTF_OBJW: aOleType.nWidth = nVal; break; 1587 case RTF_OBJH: aOleType.nHeight = nVal; break; 1588 case RTF_OBJCROPT: aOleType.nCropT = (short)nTokenValue; break; 1589 case RTF_OBJCROPB: aOleType.nCropB = (short)nTokenValue; break; 1590 case RTF_OBJCROPL: aOleType.nCropL = (short)nTokenValue; break; 1591 case RTF_OBJCROPR: aOleType.nCropR = (short)nTokenValue; break; 1592 case RTF_OBJSCALEX: aOleType.nScalX = nVal; break; 1593 case RTF_OBJSCALEY: aOleType.nScalY = nVal; break; 1594 1595 case RTF_TEXTTOKEN: 1596 if( 1 < nOpenBrakets && pStr ) 1597 { 1598 if( pStr == &sObjData ) 1599 { 1600 xub_StrLen nHexLen = HexToBin( aToken ); 1601 if( STRING_NOTFOUND != nHexLen ) 1602 bValidOle = sal_False; 1603 else 1604 { 1605 aTmpFile.Write( (sal_Char*)aToken.GetBuffer(), nHexLen ); 1606 bValidOle = 0 == aTmpFile.GetError(); 1607 } 1608 } 1609 else 1610 *pStr += aToken; 1611 } 1612 break; 1613 } 1614 } 1615 1616 if( bValidOle ) 1617 { 1618 bValidOle = sal_False; // erstmal 1619 } 1620 1621 if( !bWeiter ) // dann stehen wir noch im Result 1622 { 1623 // ist das Ole-Object Ok? 1624 // -> dann solange SkipGroup rufen, bis zur letzten 1625 // schliessenden Klammer 1626 // ansonsten alle Token verarbeiten, bis zur letzten 1627 // schliessenden Klammer 1628 1629 bWeiter = sal_True; 1630 while( nOpenBrakets && IsParserWorking() && bWeiter ) 1631 { 1632 switch( nToken = GetNextToken() ) 1633 { 1634 case '}': --nOpenBrakets; break; 1635 case '{': ++nOpenBrakets; break; 1636 } 1637 if( nOpenBrakets && !bValidOle ) 1638 NextToken( nToken ); 1639 } 1640 } 1641 1642 if( !bValidOle && '}' != nToken ) 1643 SkipGroup(); 1644 1645 SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet 1646 } 1647 #endif 1648 1649 /* vi:set tabstop=4 shiftwidth=4 expandtab: */ 1650