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