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