cmcfixes76: #i113073# redundant dereferences
[LibreOffice.git] / sw / source / filter / rtf / rtffly.cxx
blob76adc11973055ed5c9fe3bd30e8bf46aa2d32183
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
31 #include <hintids.hxx>
32 #include <tools/list.hxx>
33 #include <tools/cachestr.hxx>
34 #include <svtools/rtftoken.h>
35 #include <svl/itemiter.hxx>
36 #include <editeng/prntitem.hxx>
37 #include <editeng/opaqitem.hxx>
38 #include <editeng/protitem.hxx>
39 #include <editeng/ulspitem.hxx>
40 #include <editeng/lrspitem.hxx>
41 #include <editeng/boxitem.hxx>
42 #include <editeng/frmdiritem.hxx>
43 #include <fmtfsize.hxx>
44 #include <fmtanchr.hxx>
45 #include <fmtpdsc.hxx>
46 #include <fmtsrnd.hxx>
47 #include <fmtclds.hxx>
48 #include <fmtcntnt.hxx>
49 #include <frmatr.hxx>
50 #include <doc.hxx>
51 #include <pam.hxx>
52 #include <ndtxt.hxx>
53 #include <shellio.hxx>
54 #include <swparrtf.hxx>
55 #include <grfatr.hxx>
56 #include <paratr.hxx>
57 #include <rtf.hxx>
58 #include <ndgrf.hxx>
59 #include <pagedesc.hxx>
60 #include <swtable.hxx>
61 #include <txtflcnt.hxx>
62 #include <fmtflcnt.hxx>
63 #include <fltini.hxx>
64 #include <deque>
65 #include <map>
66 #include <utility>
67 // --> OD 2004-06-30 #i27767#
68 #include <fmtwrapinfluenceonobjpos.hxx>
69 // <--
70 #include <editeng/brshitem.hxx>
71 #include <fmtfollowtextflow.hxx>
72 // --> OD, FLR 2006-02-16 #131205#
73 #include "dcontact.hxx"
74 // <--
77 using namespace ::com::sun::star;
79 #define ANCHOR(p) ((SwFmtAnchor*)p)
81 // steht in shellio.hxx
82 extern SwCntntNode* GoNextNds( SwNodeIndex * pIdx, BOOL bChk );
84 SV_IMPL_PTRARR( SwFlySaveArr, SwFlySave* )
86 inline const SwFmtFrmSize GetFrmSize(const SfxItemSet& rSet, BOOL bInP=TRUE)
88 return (const SwFmtFrmSize&)rSet.Get(RES_FRM_SIZE,bInP);
91 SwFlySave::SwFlySave(const SwPaM& rPam, SfxItemSet& rSet)
92 : aFlySet(rSet), nSttNd(rPam.GetPoint()->nNode), nEndNd(nSttNd), nEndCnt(0),
93 nPageWidth(ATT_MIN_SIZE), nDropLines(0), nDropAnchor(0)
97 int SwFlySave::IsEqualFly( const SwPaM& rPos, SfxItemSet& rSet )
99 if( rSet.Count() != aFlySet.Count() || nDropAnchor )
100 return FALSE;
102 // nur TextNodes zusammenfassen
103 if( nSttNd == nEndNd && nEndNd.GetNode().IsNoTxtNode() )
104 return FALSE;
106 // teste auf gleiche / naechste Position
107 if( rPos.GetPoint()->nNode.GetIndex() == nEndNd.GetIndex() )
109 if( 1 < (rPos.GetPoint()->nContent.GetIndex() - nEndCnt) )
110 return FALSE;
112 else if( rPos.GetPoint()->nContent.GetIndex() )
113 return FALSE;
114 else
116 SwNodeIndex aIdx( nEndNd );
117 SwCntntNode* pCNd = rPos.GetDoc()->GetNodes()[ aIdx ]->GetCntntNode();
118 if( !GoNextNds( &aIdx, TRUE ) ||
119 aIdx.GetIndex() != rPos.GetPoint()->nNode.GetIndex() ||
120 ( pCNd && pCNd->Len() != nEndCnt ))
122 return FALSE;
126 if( rSet.Count() )
128 SfxItemIter aIter( rSet );
129 const SfxPoolItem *pItem, *pCurr = aIter.GetCurItem();
130 while( TRUE )
132 if( SFX_ITEM_SET != aFlySet.GetItemState( pCurr->Which(),
133 FALSE, &pItem ) ||
134 // Ankerattribute gesondert behandeln
135 ( RES_ANCHOR == pCurr->Which()
136 ? (ANCHOR(pCurr)->GetAnchorId() != ANCHOR(pItem)->GetAnchorId() ||
137 ANCHOR(pCurr)->GetPageNum() != ANCHOR(pItem)->GetPageNum())
138 : *pItem != *pCurr ))
139 return FALSE;
141 if( aIter.IsAtEnd() )
142 break;
143 pCurr = aIter.NextItem();
146 return TRUE;
149 void SwFlySave::SetFlySize( const SwTableNode& rTblNd )
151 // sollte der Fly kleiner als diese Tabelle sein, dann
152 // korrigiere diesen (nur bei abs. Angaben!)
153 SwTwips nWidth = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth();
154 const SwFmtFrmSize& rSz = GetFrmSize( aFlySet );
155 if( nWidth > rSz.GetWidth() )
156 aFlySet.Put( SwFmtFrmSize( rSz.GetHeightSizeType(), nWidth, rSz.GetHeight() ));
159 BOOL lcl_HasBreakAttrs( const SwCntntNode& rNd )
161 BOOL bRet = FALSE;
162 const SfxItemSet& rSet = rNd.GetSwAttrSet();
163 const SfxPoolItem* pItem;
164 if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK, TRUE, &pItem ) &&
165 SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() )
166 bRet = TRUE;
167 else if( SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC, TRUE, &pItem )&&
168 0 != ((SwFmtPageDesc*)pItem)->GetPageDesc() )
169 bRet = TRUE;
170 return bRet;
174 void lcl_CpyBreakAttrs( SwCntntNode* pSrcNd, SwCntntNode* pDstNd,
175 SwNodeIndex* pNewIdx )
177 const SfxItemSet* pSet;
178 if( pSrcNd && pDstNd && 0 != ( pSet = pSrcNd->GetpSwAttrSet() ) )
180 const SfxPoolItem *pDescItem, *pBreakItem;
182 if( SFX_ITEM_SET != pSet->GetItemState( RES_BREAK,
183 FALSE, &pBreakItem ) )
184 pBreakItem = 0;
186 if( SFX_ITEM_SET != pSet->GetItemState( RES_PAGEDESC,
187 FALSE, &pDescItem ) )
188 pDescItem = 0;
190 if( pDescItem || pBreakItem )
192 if( lcl_HasBreakAttrs( *pDstNd ))
194 SwPosition aPos( *pDstNd, SwIndex( pDstNd ));
195 aPos.nNode--;
196 pDstNd->GetDoc()->AppendTxtNode( aPos );
197 if( pNewIdx )
198 *pNewIdx = aPos.nNode;
200 SwCntntNode* pOldNd = pDstNd;
201 pDstNd = aPos.nNode.GetNode().GetCntntNode();
202 pDstNd->ChgFmtColl( pOldNd->GetFmtColl() );
203 if( pDstNd->HasSwAttrSet() )
205 SfxItemSet aSet( *pDstNd->GetpSwAttrSet() );
206 aSet.ClearItem( RES_BREAK );
207 aSet.ClearItem( RES_PAGEDESC );
208 pDstNd->SetAttr( aSet );
211 if( pBreakItem )
213 pDstNd->SetAttr( *pBreakItem );
214 pSrcNd->ResetAttr( RES_BREAK );
216 if( pDescItem )
218 pDstNd->SetAttr( *pDescItem );
219 pSrcNd->ResetAttr( RES_PAGEDESC );
225 void SwRTFParser::SetFlysInDoc()
227 // !! von Oben abarbeiten, CntntPos ist kein Index !
228 SwNodes & rNds = pDoc->GetNodes();
229 typedef std::pair<SwFlyFrmFmt*, SwFmtAnchor> frameEntry;
230 typedef std::deque<frameEntry> rtfframesAtIndex;
231 typedef std::map<const SwNode*, rtfframesAtIndex> rtfFmtMap;
232 rtfFmtMap aPrevFmts;
234 SwFrmFmt* pParent = pDoc->GetFrmFmtFromPool( RES_POOLFRM_FRAME );
235 for( USHORT n = 0; n < aFlyArr.Count(); ++n )
237 SwFlySave* pFlySave = aFlyArr[ n ];
239 ASSERT( !pFlySave->nSttNd.GetNode().FindFlyStartNode(),
240 "Content vom Fly steht in einem Fly" );
241 ASSERT( pFlySave->nSttNd.GetIndex() <= pFlySave->nEndNd.GetIndex(),
242 "Fly hat falschen Bereich" );
246 //JP 21.09.98: wenn ein DropCap ist, dann Text im Node belassen, am
247 // Absatz das Absatz Attribut setzen. Ggfs noch die
248 // FontSize zuruecksetzen, damit das DropCap nicht zu
249 // gro? wird.
250 if( pFlySave->nDropAnchor )
252 SwTxtNode* pSttNd = pFlySave->nSttNd.GetNode().GetTxtNode();
253 SwTxtNode* pEndNd = pFlySave->nEndNd.GetNode().GetTxtNode();
254 if( pSttNd && pEndNd &&
255 pSttNd->GetIndex() + 1 == pEndNd->GetIndex()
256 && pSttNd->GetTxt().Len()>0 /* #i38227# leave drop caps with no content as fly frames */ )
258 ULONG nPos = pSttNd->GetIndex();
259 SwDoc * pDoc1 = pSttNd->GetDoc();
261 BOOL bJoined;
263 SwPaM aTmp( *pSttNd, pSttNd->GetTxt().Len(), *pEndNd, 0 );
264 bJoined = pDoc1->DeleteAndJoin( aTmp );
267 SwTxtNode * pNd = (pDoc1->GetNodes()[nPos])->GetTxtNode();
269 if( bJoined && pNd != NULL)
271 SwFmtDrop aDropCap;
272 aDropCap.GetLines() = (BYTE)pFlySave->nDropLines;
273 aDropCap.GetChars() = 1;
275 SwIndex aIdx( pEndNd );
276 pNd->RstAttr( aIdx, 1, RES_CHRATR_FONTSIZE );
277 pNd->SetAttr( aDropCap );
279 delete pFlySave;
280 continue;
284 // liegt Ende und Start vom Naechsten im gleichen Node, dann muss
285 // gesplittet werden
286 if( n + 1 < aFlyArr.Count() && pFlySave->nEndCnt &&
287 pFlySave->nEndNd == aFlyArr[ n + 1 ]->nSttNd )
289 SwCntntNode* pCNd = rNds[ pFlySave->nEndNd ]->GetCntntNode();
290 if( pCNd )
292 SwPosition aPos( pFlySave->nEndNd,
293 SwIndex( pCNd, pFlySave->nEndCnt ));
294 pDoc->SplitNode( aPos, false );
295 pFlySave->nEndNd--;
297 else
298 pFlySave->nEndCnt = 0;
301 // verschiebe den Inhalt von diesem Anchor in den Auto-TextBereich
302 // und erzeuge dadurch den richtigen SwG-Rahmen
303 SwNodeRange aRg(pFlySave->nSttNd, 0, pFlySave->nEndNd, 0);
304 //Make a new section, unless there is no content at all
305 const bool bMakeEmptySection = aRg.aStart < aRg.aEnd || ((aRg.aStart == aRg.aEnd) && pFlySave->nEndCnt);
308 // Nur TextNodes koennen in Tabellen stehen !!
309 const SwNode* pNd = &pFlySave->nSttNd.GetNode();
310 if( pNd->IsNoTxtNode() )
312 // die Size muss noch korrigiert werden!
313 nAktPageDesc = 0; // Standart PageDesc
314 if( SFX_ITEM_SET != pFlySave->aFlySet.GetItemState(
315 RES_FRM_SIZE, FALSE ) )
316 _SetPictureSize( *(SwNoTxtNode*)pNd, aRg.aStart,
317 pFlySave->aFlySet );
318 if( 0 != ( pNd = pNd->FindTableNode() ) )
319 pFlySave->SetFlySize( *(SwTableNode*)pNd );
321 else
323 // Take care for table nodes
324 pNd = pNd->GetNodes()[ pNd->GetIndex() - 2 ]->GetTableNode();
325 if( pNd ) // if the table starts imediately before aRg -> expand aRg
326 aRg.aStart = *pNd;
328 if( bMakeEmptySection )
330 pNd = &aRg.aEnd.GetNode();
331 ULONG nSectEnd = pNd->EndOfSectionIndex()+1;
333 if (!pNd->IsTableNode() && 0 !=(pNd = pNd->FindTableNode())
334 && (pNd->GetIndex() >= aRg.aStart.GetNode().GetIndex()) )
336 const SwNode* pTblBxNd;
338 // Ende der Tabelle ist hinter dieser Box ??
339 if( pNd->EndOfSectionIndex() == nSectEnd )
340 aRg.aEnd = nSectEnd+1;
341 // is the end in the first box of the table, then
342 // move before the table (Bug 67663)
343 // but the range must not become emtpy, i.e. aStart==aEnd
344 // because otherwise we will get a crash (126506) later on
345 else if( 0 != ( pTblBxNd = aRg.aEnd.GetNode().
346 FindTableBoxStartNode()) &&
347 pTblBxNd->GetIndex() - 1 == pNd->GetIndex() &&
348 &aRg.aStart.GetNode() != pNd )
349 aRg.aEnd = *pNd;
350 else
352 // Tabelle ist noch groesser, also splitte sie hier.
353 rNds.SplitTable( aRg.aEnd, TRUE );
354 aRg.aEnd = pNd->EndOfSectionIndex() + 1;
361 // vorm verschieben muss sich der Index auf die alte Position
362 // gemerkt werden, der Index wird mit verschoben !!!
364 SwNodeIndex aTmpIdx( rNds.GetEndOfAutotext() );
365 SwStartNode* pSttNd = bMakeEmptySection
366 ? rNds.MakeEmptySection( aTmpIdx, SwFlyStartNode )
367 : rNds.MakeTextSection( aTmpIdx, SwFlyStartNode,
368 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
370 // das ist die Verankerungs-Position (fuers Layout!)
371 pFlySave->nSttNd = aRg.aStart.GetIndex()-1;
372 if( bMakeEmptySection )
374 // check: the move does not clear the surrounded section. If all
375 // nodes moved away, then create a new TxtNode
377 // i76403: an empty selection is not a good idea
378 if( aRg.aStart == aRg.aEnd && aRg.aStart.GetNode().GetTxtNode() )
379 aRg.aEnd++;
380 SwNodeIndex aPrev( aRg.aStart, -1 );
381 if( aPrev.GetNode().IsStartNode() &&
382 aPrev.GetNode().EndOfSectionNode() == &aRg.aEnd.GetNode())
384 // create new txtnode, because the section does never be empty
385 pDoc->GetNodes().MakeTxtNode( aRg.aEnd,
386 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
387 aRg.aEnd--;
390 aTmpIdx = *pSttNd->EndOfSectionNode();
391 pDoc->MoveNodeRange( aRg, aTmpIdx,
392 IDocumentContentOperations::DOC_MOVEDEFAULT );
395 // patch from cmc for #i52542#
396 if (pSttNd->GetIndex() + 1 == pSttNd->EndOfSectionIndex())
398 ASSERT(!this, "nothing in this frame, not legal");
399 delete pFlySave;
400 continue;
403 pFlySave->aFlySet.Put( SwFmtCntnt( pSttNd ));
405 CalculateFlySize( pFlySave->aFlySet, pFlySave->nSttNd,
406 pFlySave->nPageWidth );
408 // THIS >>>>>
409 // if the section only contains one Node and this has a
410 // border or backgorund, then put it to the frame
411 // Not in our own RTF-Format!
412 // <<<<< DOES NOT MAKE SENSE TO ME (flr)
413 // #102781#. Added support for transparent frames.
414 if( pSttNd->GetIndex() + 1 != pSttNd->EndOfSectionIndex() &&
415 !bSwPageDesc )
417 SwCntntNode* pSrcNd = pDoc->GetNodes()[ pSttNd->GetIndex() + 1 ]->GetCntntNode();
418 SfxItemSet aTmpSet( pDoc->GetAttrPool(),
419 RES_BACKGROUND, RES_BOX );
420 const SvxBrushItem* pBackgroundBrush = (const SvxBrushItem*)pFlySave->aFlySet.GetItem(RES_BACKGROUND, FALSE);
421 if( pSrcNd && pSrcNd->HasSwAttrSet() )
422 aTmpSet.Put( *pSrcNd->GetpSwAttrSet() );
423 if (pBackgroundBrush)
425 aTmpSet.Put(*pBackgroundBrush, RES_BACKGROUND);
427 else
429 pBackgroundBrush = (const SvxBrushItem*)aTmpSet.GetItem(RES_BACKGROUND, FALSE);
430 if (pBackgroundBrush)
432 Color& rBackgroundColor = const_cast<SvxBrushItem*>(pBackgroundBrush)->GetColor();
433 rBackgroundColor.SetTransparency(0xFE);
435 else
437 Color aColor = Color(0xff, 0xff, 0xff);
438 aColor.SetTransparency( 0xFE);
439 SvxBrushItem aBrush(aColor, RES_BACKGROUND);
440 aTmpSet.Put(aBrush, RES_BACKGROUND);
443 // #117914# Topic 6.
444 pFlySave->aFlySet.Put( aTmpSet );
445 if( pSrcNd && pSrcNd->HasSwAttrSet() )
447 pSrcNd->ResetAttr( RES_BACKGROUND, RES_BOX );
451 SwFlyFrmFmt* pFmt = pDoc->MakeFlyFrmFmt( aEmptyStr, pParent );
452 pFmt->SetFmtAttr( pFlySave->aFlySet );
453 const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
454 if (FLY_AS_CHAR != rAnchor.GetAnchorId())
456 // korrigiere noch den Absatz, ist immer der vorhergehende !
457 // JP 20.09.95: wenn es diesen gibt! (DocAnfang!)
459 //JP 02.08.99: that is wrong. The anchor is ever the NEXT!
460 //JP 05.08.99: there are an Bug in the ExportFilter which will
461 // be fixed in the Version 517 - by SWG-Export
462 // the fly will be after the paragraph - but in RTF
463 // the flys will be before the paragraph.
464 if( !bSwPageDesc || 5430 < GetVersionNo() )
465 pFlySave->nSttNd++;
467 // if( !pFlySave->nSttNd.GetNode().IsCntntNode() )
469 // Seitenumbrueche in den Bodybereich verschieben!
470 SwCntntNode* pSrcNd = aRg.aStart.GetNode().GetCntntNode();
471 SwCntntNode* pDstNd = pFlySave->nSttNd.GetNode().GetCntntNode();
472 if( !pDstNd )
473 pDstNd = pDoc->GetNodes().GoNext( &pFlySave->nSttNd );
475 ::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nSttNd );
478 const SwNodeIndex aSttNd(*pSttNd);
479 SwNodeIndex aEndNd(*pSttNd->EndOfSectionNode());
480 aEndNd--;
482 SwPosition aPos( pFlySave->nSttNd );
483 SwFmtAnchor aAnchor(rAnchor);
484 aAnchor.SetAnchor(&aPos);
486 const SwNode *pCurrentAnchor = &(pFlySave->nSttNd.GetNode());
487 aPrevFmts[pCurrentAnchor].push_back(frameEntry(pFmt, aAnchor));
489 while (aEndNd > aSttNd)
491 typedef rtfframesAtIndex::iterator myIter;
492 rtfframesAtIndex &rDeque = aPrevFmts[&(aEndNd.GetNode())];
493 myIter aEnd = rDeque.end();
494 for (myIter aIter = rDeque.begin(); aIter != aEnd; ++aIter)
496 aIter->second.SetAnchor(&aPos);
497 // --> OD 2004-06-30 #i27767# - push on front to keep order
498 // of objects for the correct object positioning
499 //aPrevFmts[pCurrentAnchor].push_back(*aIter);
500 aPrevFmts[pCurrentAnchor].push_front(*aIter);
502 rDeque.clear();
503 aEndNd--;
507 // --> OD, FLR 2006-02-16 #131205#
508 // Create draw contact object, which also creates a <SdrObject> instance,
509 // in order to set the order number.
510 // The order number is assumed to be the order of the text flow.
511 SwFlyDrawContact* pContact =
512 new SwFlyDrawContact( pFmt,
513 pFmt->GetDoc()->GetOrCreateDrawModel() );
514 pContact->GetMaster()->SetOrdNum( n );
515 // <--
517 delete pFlySave;
520 typedef rtfFmtMap::reverse_iterator myriter;
521 myriter aEnd = aPrevFmts.rend();
522 for(myriter aIter = aPrevFmts.rbegin(); aIter != aEnd; ++aIter)
524 rtfframesAtIndex &rDeque = aIter->second;
525 typedef rtfframesAtIndex::iterator myIter;
526 myIter aQEnd = rDeque.end();
527 for (myIter aQIter = rDeque.begin(); aQIter != aQEnd; ++aQIter)
529 frameEntry &rEntry = *aQIter;
530 SwFlyFrmFmt *pFrm = rEntry.first;
531 SwFmtAnchor &rAnchor = rEntry.second;
532 pFrm->SetFmtAttr(rAnchor);
536 aFlyArr.Remove(0, aFlyArr.Count());
539 // clips the text box to the min or max position if it is outside our min or max boundry
540 long SwRTFParser::GetSafePos(long nPos)
542 if(nPos > SHRT_MAX)
543 nPos = SHRT_MAX;
544 else if(nPos < SHRT_MIN)
545 nPos = SHRT_MIN;
547 return nPos;
550 void SwRTFParser::ReadFly( int nToken, SfxItemSet* pSet )
552 // ein Set fuer die FrmFmt-Attribute
553 SfxItemSet aSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
554 if( !IsNewDoc() )
555 Reader::ResetFrmFmtAttrs( aSet );
557 // der Fly beginnt immer in einem neuen Absatz
558 if( pPam->GetPoint()->nContent.GetIndex() )
559 InsertPara();
561 // RTF-Defaults setzen:
562 // --> OD 2004-06-24 #i27767#
563 SwFmtAnchor aAnchor( FLY_AT_PARA );
565 SwFmtHoriOrient aHori( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME );
566 SwFmtVertOrient aVert( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME );
567 // <--
568 SvxFrameDirectionItem aFrmDir( FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR );
570 USHORT nCols = USHRT_MAX, nColSpace = USHRT_MAX, nAktCol = 0;
571 SvUShorts aColumns;
573 BOOL bChkDropCap = 0 == pSet;
574 USHORT nDropCapLines = 0, nDropCapAnchor = 0;
575 int nNumOpenBrakets = GetOpenBrakets();
577 if( !pSet )
579 pSet = &aSet;
581 else
583 // die Werte aus dem uebergebenen!
584 aAnchor = (SwFmtAnchor&)pSet->Get( RES_ANCHOR );
585 aHori = (SwFmtHoriOrient&)pSet->Get( RES_HORI_ORIENT );
586 aVert = (SwFmtVertOrient&)pSet->Get( RES_VERT_ORIENT );
589 // dann sammel mal alle Attribute zusammen
590 int bWeiter = TRUE;
591 int nAppliedProps=0;
592 do {
593 USHORT nVal = USHORT(nTokenValue);
595 #i5263#
596 Assume that a property genuinely contributes towards creating a frame,
597 and if turns out to be a non contributing one reduce the count.
599 ++nAppliedProps;
600 switch( nToken )
602 case RTF_ABSW:
604 SwFmtFrmSize aSz( ATT_MIN_SIZE, nTokenValue, 0 );
605 const SfxPoolItem* pItem;
606 if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, TRUE,
607 &pItem ))
609 aSz.SetHeightSizeType( ((SwFmtFrmSize*)pItem)->GetHeightSizeType() );
610 aSz.SetHeight( ((SwFmtFrmSize*)pItem)->GetHeight() );
612 if( MINFLY > nTokenValue ) nTokenValue = MINFLY;
613 aSet.Put( aSz );
615 break;
616 case RTF_ABSH:
618 SwFmtFrmSize aSz( ATT_MIN_SIZE, 0, MINFLY );
619 const SfxPoolItem* pItem;
620 if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, TRUE,
621 &pItem ))
623 aSz.SetWidth( ((SwFmtFrmSize*)pItem)->GetWidth() );
626 if( 0 > nTokenValue )
628 nTokenValue = -nTokenValue;
629 aSz.SetHeightSizeType( ATT_FIX_SIZE );
631 if( MINFLY > nTokenValue ) nTokenValue = MINFLY;
632 aSz.SetHeight( nTokenValue );
633 aSet.Put( aSz );
635 break;
637 case RTF_NOWRAP:
639 pSet->Put( SwFmtSurround( SURROUND_NONE ));
641 break;
642 case RTF_DXFRTEXT:
644 SvxULSpaceItem aUL( RES_UL_SPACE );
645 SvxLRSpaceItem aLR( RES_LR_SPACE );
646 aUL.SetUpper( nVal ); aUL.SetLower( nVal );
647 aLR.SetLeft( nVal ); aLR.SetRight( nVal );
648 pSet->Put( aUL );
649 pSet->Put( aLR );
651 break;
653 case RTF_DFRMTXTX:
655 SvxLRSpaceItem aLR( RES_LR_SPACE );
656 aLR.SetLeft( nVal ); aLR.SetRight( nVal );
657 pSet->Put( aLR );
659 break;
660 case RTF_DFRMTXTY:
662 SvxULSpaceItem aUL( RES_UL_SPACE );
663 aUL.SetUpper( nVal ); aUL.SetLower( nVal );
664 pSet->Put( aUL );
666 break;
668 case RTF_POSNEGX:
669 case RTF_POSX: aHori.SetHoriOrient( text::HoriOrientation::NONE );
670 aHori.SetPos( GetSafePos((long)nTokenValue) );
671 break;
672 case RTF_POSXC: aHori.SetHoriOrient( text::HoriOrientation::CENTER ); break;
673 case RTF_POSXI: aHori.SetHoriOrient( text::HoriOrientation::LEFT );
674 aHori.SetPosToggle( TRUE );
675 break;
676 case RTF_POSXO: aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
677 aHori.SetPosToggle( TRUE );
678 break;
679 case RTF_POSXL: aHori.SetHoriOrient( text::HoriOrientation::LEFT ); break;
680 case RTF_POSXR: aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); break;
682 case RTF_POSNEGY:
683 case RTF_POSY: aVert.SetVertOrient( text::VertOrientation::NONE );
684 aVert.SetPos( GetSafePos((long)nTokenValue) );
685 break;
686 case RTF_POSYT: aVert.SetVertOrient( text::VertOrientation::TOP ); break;
687 case RTF_POSYB: aVert.SetVertOrient( text::VertOrientation::BOTTOM ); break;
688 case RTF_POSYC: aVert.SetVertOrient( text::VertOrientation::CENTER ); break;
690 case RTF_PHMRG: aHori.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break;
691 case RTF_PVMRG: aVert.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break;
692 case RTF_PHPG: aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME ); break;
693 case RTF_PVPG: aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );break;
694 case RTF_PHCOL: aHori.SetRelationOrient( text::RelOrientation::FRAME ); break;
695 case RTF_PVPARA: aVert.SetRelationOrient( text::RelOrientation::FRAME ); break;
697 case RTF_POSYIL:
698 break;
699 case RTF_ABSLOCK:
701 #i5263#
702 Not sufficient to make a frame at least word won't do it with just
703 an abslock
705 --nAppliedProps;
706 break;
707 case RTF_FRMTXLRTB:
708 aFrmDir.SetValue( FRMDIR_HORI_LEFT_TOP );
709 break;
710 case RTF_FRMTXTBRL:
711 aFrmDir.SetValue( FRMDIR_HORI_RIGHT_TOP );
712 break;
713 case RTF_FRMTXLRTBV:
714 aFrmDir.SetValue( FRMDIR_VERT_TOP_LEFT );
715 break;
716 case RTF_FRMTXTBRLV:
717 aFrmDir.SetValue( FRMDIR_VERT_TOP_RIGHT );
718 break;
720 case RTF_DROPCAPLI: // Dropcaps !!
721 if( bChkDropCap )
723 nDropCapLines = USHORT( nTokenValue );
724 if( !nDropCapAnchor )
725 nDropCapAnchor = 1;
727 break;
728 case RTF_DROPCAPT:
729 if( bChkDropCap )
731 nDropCapAnchor = USHORT( nTokenValue );
732 if( !nDropCapLines )
733 nDropCapLines = 3;
735 break;
738 // fuer die "alten" Writer - haben die Spaltigkeit falsch heraus-
739 // geschrieben
740 case RTF_COLS: nCols = USHORT( nTokenValue ); break;
741 case RTF_COLSX: nColSpace = USHORT( nTokenValue ); break;
742 case RTF_COLNO:
743 nAktCol = USHORT( nTokenValue );
744 if( RTF_COLW == GetNextToken() )
746 USHORT nWidth = USHORT( nTokenValue ), nSpace = 0;
747 if( RTF_COLSR == GetNextToken() )
748 nSpace = USHORT( nTokenValue );
749 else
750 SkipToken( -1 ); // wieder zurueck
752 if( --nAktCol == ( aColumns.Count() / 2 ) )
754 aColumns.Insert( nWidth + nSpace, aColumns.Count() );
755 aColumns.Insert( nSpace, aColumns.Count() );
758 break;
760 case '{':
762 short nSkip = 0;
763 if( RTF_IGNOREFLAG != ( nToken = GetNextToken() ))
765 if( RTF_SHADINGDEF == (nToken & ~0xff) )
767 ReadBackgroundAttr( nToken, aSet );
768 GetNextToken(); // Klammer ueberlesen
770 else
771 nSkip = -1;
773 else if( RTF_APOCTL ==
774 ((nToken = GetNextToken() ) & ~(0xff | RTF_SWGDEFS)) )
776 bReadSwFly = true; // alles kommt in den akt. Fly
777 SvxLRSpaceItem aLR( RES_LR_SPACE );
778 SvxULSpaceItem aUL( RES_UL_SPACE );
779 nCols = USHRT_MAX; // neu aufsetzen
780 nColSpace = USHRT_MAX;
781 do {
782 nVal = USHORT(nTokenValue);
783 switch( nToken )
785 // Swg-Frame-Tokens
786 case RTF_FLYPRINT:
788 pSet->Put( SvxPrintItem( RES_PRINT, FALSE ));
790 break;
791 case RTF_FLYOPAQUE:
793 pSet->Put( SvxOpaqueItem( RES_OPAQUE, FALSE ));
795 break;
797 case RTF_FLYPRTCTD:
799 RTFProtect aP( (BYTE)nTokenValue );
800 SvxProtectItem aProtectItem( RES_PROTECT );
801 aProtectItem.SetCntntProtect( aP.GetCntnt() );
802 aProtectItem.SetSizeProtect( aP.GetSize() );
803 aProtectItem.SetPosProtect( aP.GetPos() );
804 pSet->Put( aProtectItem );
806 break;
808 case RTF_FLYMAINCNT:
810 RTFSurround aMC( (BYTE)nTokenValue );
811 SwFmtSurround aSurr( (SwSurround)aMC.GetOrder());
812 if( aMC.GetGoldCut() )
813 aSurr.SetSurround( SURROUND_IDEAL );
814 pSet->Put( aSurr );
816 break;
817 case RTF_FLYVERT:
819 RTFVertOrient aVO( nVal );
820 aVert.SetVertOrient( aVO.GetOrient() );
821 aVert.SetRelationOrient( aVO.GetRelation() );
823 break;
824 case RTF_FLYHORZ:
826 RTFHoriOrient aHO( nVal );
827 aHori.SetHoriOrient( aHO.GetOrient() );
828 aHori.SetRelationOrient( aHO.GetRelation() );
830 break;
831 case RTF_FLYOUTLEFT: aLR.SetLeft( nVal ); break;
832 case RTF_FLYOUTRIGHT: aLR.SetRight( nVal ); break;
833 case RTF_FLYOUTUPPER: aUL.SetUpper( nVal ); break;
834 case RTF_FLYOUTLOWER: aUL.SetLower( nVal ); break;
835 case RTF_FLYANCHOR:
836 switch( GetNextToken() )
838 case RTF_FLY_PAGE:
839 aAnchor.SetType( FLY_AT_PAGE );
840 aAnchor.SetPageNum( USHORT(nTokenValue));
841 aAnchor.SetAnchor( 0 );
842 break;
844 case RTF_FLY_CNTNT:
846 SwNodeIndex aIdx( pPam->GetPoint()->nNode );
847 pDoc->GetNodes().GoPrevious( &aIdx );
848 SwPosition aPos( aIdx );
849 aAnchor.SetType( FLY_AT_PARA );
850 aAnchor.SetAnchor( &aPos );
852 break;
854 // JP 26.09.94: die Bindung an die Spalte gibt es nicht mehr !!
855 // case RTF_FLY_COLUMN:
857 break;
858 case RTF_COLS: nCols = USHORT( nTokenValue ); break;
859 case RTF_COLSX: nColSpace = USHORT( nTokenValue ); break;
860 case RTF_COLNO:
861 nAktCol = USHORT( nTokenValue );
862 if( RTF_COLW == GetNextToken() )
864 USHORT nWidth = USHORT( nTokenValue ), nSpace = 0;
865 if( RTF_COLSR == GetNextToken() )
866 nSpace = USHORT( nTokenValue );
867 else
868 SkipToken( -1 ); // wieder zurueck
870 if( --nAktCol == ( aColumns.Count() / 2 ) )
872 aColumns.Insert( nWidth + nSpace, aColumns.Count() );
873 aColumns.Insert( nSpace, aColumns.Count() );
876 break;
878 case '{':
879 if( RTF_BRDBOX == ( nToken = GetNextToken() ) )
880 ReadBorderAttr( nToken, aSet );
881 else if( RTF_SHADINGDEF == (nToken & ~0xff ) )
882 ReadBackgroundAttr( nToken, aSet );
883 else if( RTF_IGNOREFLAG == nToken )
885 int bSkipGrp = TRUE;
886 switch( nToken = GetNextToken() )
888 case RTF_SHADOW:
889 case RTF_BRDBOX:
890 ReadAttr( SkipToken( -2 ), &aSet );
891 bSkipGrp = FALSE;
892 break;
894 case RTF_BRDRT:
895 case RTF_BRDRB:
896 case RTF_BRDRR:
897 case RTF_BRDRL:
898 bSkipGrp = FALSE;
899 ReadBorderAttr( SkipToken( -2 ), aSet );
900 break;
903 // keine weitere Klammer mehr ueberlesen!!!
904 if( !bSkipGrp )
905 break;
907 SkipGroup();
909 else
910 SkipGroup();
911 GetNextToken(); // Klammer ueberlesen
912 break;
914 } while( IsParserWorking() &&
915 '}' != ( nToken = GetNextToken() ));
917 if( aUL.GetUpper() || aUL.GetLower() )
918 pSet->Put( aUL );
919 if( aLR.GetLeft() || aLR.GetRight() )
920 pSet->Put( aLR );
922 else if( RTF_BRDBOX == nToken )
923 ReadBorderAttr( nToken, aSet );
924 else if( RTF_SHADOW == nToken )
925 ReadAttr( SkipToken( -2 ), &aSet );
926 else if( RTF_SHADINGDEF == (nToken & ~0xff ) )
927 ReadBackgroundAttr( nToken, aSet );
928 else if( RTF_UNKNOWNCONTROL == nToken )
929 SkipGroup();
930 else
931 nSkip = -2;
933 if( nSkip )
935 nToken = SkipToken( nSkip );
936 bWeiter = FALSE;
939 break;
941 default:
942 --nAppliedProps; //Not sufficient to make a frame
943 bWeiter = FALSE;
946 if( bWeiter )
947 nToken = GetNextToken();
948 } while( bWeiter && IsParserWorking() );
950 pSet->Put( aAnchor );
951 pSet->Put( aHori );
952 pSet->Put( aVert );
954 // --> OD 2004-06-30 #i27767# - set wrapping style influence
955 // --> OD 2004-10-18 #i35017# - constant name has changed
956 pSet->Put( SwFmtWrapInfluenceOnObjPos(
957 text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ));
958 // <--
960 SwFmtFollowTextFlow aFollowTextFlow( FALSE );
961 pSet->Put( aFollowTextFlow );
963 if( !( aFrmDir == pSet->Get( RES_FRAMEDIR )) )
964 pSet->Put( aFrmDir );
966 if( nCols && USHRT_MAX != nCols )
968 SwFmtCol aCol;
969 if( USHRT_MAX == nColSpace )
970 nColSpace = 720;
972 ULONG nWidth = USHRT_MAX;
973 aCol.Init( nCols, nColSpace, USHORT( nWidth ) );
974 if( nCols == ( aColumns.Count() / 2 ) )
976 for( USHORT n = 0, i = 0; n < aColumns.Count(); n += 2, ++i )
978 SwColumn* pCol = aCol.GetColumns()[ i ];
979 ULONG nTmp = aColumns[ n ];
980 nTmp *= USHRT_MAX;
981 nTmp /= nWidth;
982 pCol->SetWishWidth( USHORT(nTmp) );
984 JP 07.07.95: der Dialog kennt nur eine Breite fuer alle Spalten
985 darum hier nicht weiter beachten
986 nTmp = aColumns[ n+1 ];
987 if( nTmp )
988 pCol->SetRight( USHORT(nTmp) );
989 else
990 pCol->SetRight( 0 );
991 pCol->SetLeft( 0 );
995 pSet->Put( aCol );
998 if( pSet != &aSet ) // wurde der Set uebergeben, dann wars das
999 return ;
1001 // ein neues FlyFormat anlegen oder das alte benutzen ?
1002 // (teste ob es die selben Attribute besitzt!)
1003 SwFlySave* pFlySave = 0;
1004 USHORT nFlyArrCnt = aFlyArr.Count();
1006 #i5263#
1007 There were not enough frame properties found to actually justify creating
1008 an absolutely positioned frame.
1010 if (nAppliedProps)
1012 if( !nFlyArrCnt ||
1013 !( pFlySave = aFlyArr[ nFlyArrCnt-1 ])->IsEqualFly( *pPam, aSet ))
1015 pFlySave = new SwFlySave( *pPam, aSet );
1016 Size aPgSize;
1017 GetPageSize( aPgSize );
1018 pFlySave->nPageWidth = aPgSize.Width();
1020 if( nDropCapAnchor )
1022 pFlySave->nDropAnchor = nDropCapAnchor;
1023 pFlySave->nDropLines = nDropCapLines;
1025 if (nFlyArrCnt >0){
1026 SwFlySave* pFlySavePrev = aFlyArr[nFlyArrCnt-1];
1027 if (pFlySave->nSttNd.GetIndex() < pFlySavePrev->nEndNd.GetIndex())
1029 pFlySavePrev->nEndNd=pFlySave->nSttNd;
1032 aFlyArr.Insert( pFlySave, nFlyArrCnt++ );
1033 // --> OD 2008-12-22 #i83368# - reset
1034 mbReadCellWhileReadSwFly = false;
1035 // <--
1039 SetPardTokenRead( FALSE );
1040 const SwTableNode* pTblNd = pPam->GetNode()->FindTableNode();
1042 while( !IsPardTokenRead() && IsParserWorking() )
1044 if( RTF_PARD == nToken || nNumOpenBrakets > GetOpenBrakets() )
1045 break;
1047 NextToken( nToken );
1049 if( !IsPardTokenRead() )
1051 // #102781#. Added support for transparent frames.
1052 if (nToken == RTF_CBPAT && nFlyArrCnt > 0)
1054 USHORT _index=USHORT(nTokenValue);
1055 const Color& rColor = GetColor(_index);
1056 SvxBrushItem aBrush(rColor, RES_BACKGROUND);
1057 SwFlySave* pFS = aFlyArr[nFlyArrCnt-1];
1058 pFS->aFlySet.Put(aBrush, RES_BACKGROUND);
1061 nToken = GetNextToken();
1063 // BUG 22036: kommt zwischen Fly-Attributen ein unbekanntes,
1064 // dann erzeuge nie 2 FlyFrames, sondern fasse
1065 // beide zusammen !!!
1066 while( RTF_APOCTL == ( nToken & ~(0xff | RTF_SWGDEFS) ))
1068 if( RTF_FLY_INPARA == nToken )
1069 break;
1071 if( RTF_IGNOREFLAG == SkipToken( -1 ) )
1073 if( '{' == SkipToken( -1 ) )
1074 nToken = '{';
1075 else
1076 SkipToken( 2 );
1078 else
1079 SkipToken( 1 );
1081 ReadFly( nToken, pFlySave ? &pFlySave->aFlySet : 0);
1082 nToken = GetNextToken();
1088 #i5263#
1089 There were enough frame properties found to actually justify creating
1090 an absolutely positioned frame.
1092 if (!nAppliedProps)
1094 bReadSwFly = false;
1095 SkipToken( -1 );
1096 return;
1099 if( pTblNd && !pPam->GetPoint()->nContent.GetIndex() &&
1100 pTblNd->EndOfSectionIndex() + 1 ==
1101 pPam->GetPoint()->nNode.GetIndex() )
1103 // nicht mehr in der Tabelle, sondern dahinter ?
1104 // Dann aber wieder zurueck in die Tabelle
1105 pPam->Move( fnMoveBackward );
1107 else
1108 pTblNd = 0;
1110 // wurde garnichts eingefuegt?
1111 if( !pTblNd &&
1112 pPam->GetPoint()->nNode == pFlySave->nSttNd &&
1113 !pPam->GetPoint()->nContent.GetIndex() )
1115 // // dann erzeuge mindestens einen leeren TextNode
1116 // pDoc->AppendTxtNode(*pPam);
1117 // dann zerstoere den FlySave wieder.
1118 aFlyArr.DeleteAndDestroy( --nFlyArrCnt );
1121 else
1123 BOOL bMovePaM = 0 != pTblNd;
1125 pFlySave->nEndNd = pPam->GetPoint()->nNode;
1126 pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex();
1128 if( bMovePaM )
1129 pPam->Move( fnMoveForward );
1131 pTblNd = pFlySave->nSttNd.GetNode().FindTableNode();
1132 if( pTblNd && !pFlySave->nEndCnt &&
1133 pTblNd == pFlySave->nEndNd.GetNode().FindTableNode() )
1135 // dann teste mal, ob das \pard nicht zu spaet kam und
1136 // eigentlich in die vorherige Zelle gehoert
1137 const SwStartNode* pSttBoxNd = pFlySave->nSttNd.GetNode().
1138 FindTableBoxStartNode(),
1139 * pEndBoxNd = pFlySave->nEndNd.GetNode().
1140 FindTableBoxStartNode();
1141 if( pSttBoxNd && pEndBoxNd &&
1142 bMovePaM ? ( pSttBoxNd == pEndBoxNd )
1143 : ( pSttBoxNd->EndOfSectionIndex() + 1 ==
1144 pEndBoxNd->GetIndex() &&
1145 pEndBoxNd->GetIndex() + 1 ==
1146 pFlySave->nEndNd.GetIndex() ))
1148 // dann gehoert das Ende in die vorherige Box!
1149 SwPosition aPos( *pPam->GetPoint() );
1150 pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode();
1151 pPam->Move( fnMoveBackward, fnGoNode );
1153 DelLastNode();
1155 pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode();
1156 pPam->Move( fnMoveBackward, fnGoNode );
1158 pFlySave->nEndNd = pPam->GetPoint()->nNode;
1159 pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex();
1161 *pPam->GetPoint() = aPos;
1164 else if( !bReadSwFly && !pFlySave->nEndCnt &&
1165 pFlySave->nSttNd.GetIndex() + 1 == pFlySave->nEndNd.GetIndex() &&
1166 pFlySave->nSttNd.GetNode().IsTxtNode() )
1169 SwTxtNode* pTxtNd = pFlySave->nSttNd.GetNode().GetTxtNode();
1170 SwTxtFlyCnt* pFlyCnt = 0;
1171 if( 1 == pTxtNd->GetTxt().Len() &&
1172 0 != (pFlyCnt = static_cast<SwTxtFlyCnt*>(
1173 pTxtNd->GetTxtAttrForCharAt(0, RES_TXTATR_FLYCNT))) &&
1174 pFlyCnt->GetFlyCnt().GetFrmFmt() )
1176 // then move the content into the surrounded fly
1177 SwFrmFmt* pFlyFmt = pFlyCnt->GetFlyCnt().GetFrmFmt();
1178 const SwNodeIndex* pFlySNd = pFlyFmt->GetCntnt().GetCntntIdx();
1179 SwNodeRange aRg( *pFlySNd, 1,
1180 *pFlySNd->GetNode().EndOfSectionNode(), 0 );
1182 // merge the itemsets
1183 SwFmtFrmSize aSz1( (SwFmtFrmSize&)pFlyFmt->GetAttrSet().
1184 Get( RES_FRM_SIZE ));
1185 SwFmtFrmSize aSz2( (SwFmtFrmSize&)pFlySave->aFlySet.
1186 Get( RES_FRM_SIZE ));
1187 // if
1188 if( !aRg.aStart.GetNode().IsNoTxtNode() ||
1189 !aSz1.GetHeight() || !aSz1.GetWidth() ||
1190 !aSz2.GetHeight() || !aSz2.GetWidth() ||
1191 ( aSz1.GetHeight() == aSz2.GetHeight() &&
1192 aSz1.GetWidth() == aSz2.GetWidth() ) )
1194 SfxItemSet aDiffs( pFlyFmt->GetAttrSet() );
1195 aDiffs.ClearItem( RES_ANCHOR );
1196 aDiffs.ClearItem( RES_FRM_SIZE );
1197 aDiffs.ClearItem( RES_CNTNT );
1198 aDiffs.Differentiate( pFlySave->aFlySet );
1199 pFlySave->aFlySet.Put( aDiffs );
1201 BOOL bSet = FALSE;
1202 if( aSz1.GetHeight() && !aSz2.GetHeight() )
1204 bSet = TRUE;
1205 aSz2.SetHeight( aSz1.GetHeight() );
1207 if( aSz1.GetWidth() && !aSz2.GetWidth() )
1209 bSet = TRUE;
1210 aSz2.SetWidth( aSz1.GetWidth() );
1212 if( bSet )
1213 pFlySave->aFlySet.Put( aSz2 );
1215 // move any PageBreak/Desc Attr to the next Para
1217 SwCntntNode* pSrcNd = pFlySave->nSttNd.GetNode().GetCntntNode();
1218 SwCntntNode* pDstNd = pFlySave->nEndNd.GetNode().GetCntntNode();
1220 ::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nEndNd );
1223 // create new txtnode, because the section does never be empty
1224 pDoc->GetNodes().MakeTxtNode( aRg.aStart,
1225 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
1227 SwNodeIndex aTmp( pFlySave->nSttNd, +1 );
1228 pDoc->MoveNodeRange( aRg, aTmp,
1229 IDocumentContentOperations::DOC_MOVEDEFAULT );
1231 // now delete the redundant txtnode
1232 pDoc->GetNodes().Delete( pFlySave->nSttNd, 1 );
1238 bReadSwFly = false;
1239 SkipToken( -1 );
1243 void SwRTFParser::InsPicture( const String& rGrfNm, const Graphic* pGrf,
1244 const SvxRTFPictureType* pPicType )
1246 // kennzeichen fuer Swg-Dokumente:
1247 // (dann ist das FlyFmt fuer die Grafik!)
1248 SwGrfNode * pGrfNd;
1249 // --> OD 2008-12-22 #i83368#
1250 // Assure that graphic node is enclosed by fly frame node.
1251 // if( bReadSwFly )
1252 if ( bReadSwFly && !mbReadCellWhileReadSwFly )
1253 // <--
1255 // erzeuge nur einen normalen GrafikNode und ersetze diesen gegen
1256 // den vorhandenen Textnode
1257 SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
1258 pGrfNd = pDoc->GetNodes().MakeGrfNode( rIdx,
1259 rGrfNm, aEmptyStr, // Name der Graphic !!
1260 pGrf,
1261 (SwGrfFmtColl*)pDoc->GetDfltGrfFmtColl() );
1263 if( pGrfAttrSet )
1264 pGrfNd->SetAttr( *pGrfAttrSet );
1266 SwFlySave* pFlySave = aFlyArr[ aFlyArr.Count()-1 ];
1267 pFlySave->nSttNd = rIdx.GetIndex() - 1;
1269 if( 1 < aFlyArr.Count() )
1271 pFlySave = aFlyArr[ aFlyArr.Count() - 2 ];
1272 if( pFlySave->nEndNd == rIdx )
1273 pFlySave->nEndNd = rIdx.GetIndex() - 1;
1276 else
1278 // wenn normale RTF-Grafik, dann steht diese im Textfluss !
1279 SwAttrSet aFlySet( pDoc->GetAttrPool(), RES_OPAQUE, /*RES_OPAQUE,
1280 RES_VERT_ORIENT,*/ RES_ANCHOR );
1281 const SwPosition* pPos = pPam->GetPoint();
1283 SwFmtAnchor aAnchor( FLY_AS_CHAR );
1284 aAnchor.SetAnchor( pPos );
1285 aFlySet.Put( aAnchor );
1286 aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP ));
1288 if (pDoc->IsInHeaderFooter(pPos->nNode))
1290 SvxOpaqueItem aOpaqueItem(RES_OPAQUE, FALSE);
1291 SwFmtSurround aSurroundItem(SURROUND_THROUGHT);
1292 aFlySet.Put(aOpaqueItem);
1293 aFlySet.Put(aSurroundItem);
1296 SwFrmFmt* pFlyFmt = pDoc->Insert( *pPam,
1297 rGrfNm, aEmptyStr, // Name der Graphic !!
1298 pGrf,
1299 &aFlySet, // Attribute fuer den FlyFrm
1300 pGrfAttrSet, NULL ); // Attribute fuer die Grafik
1302 pGrfNd = pDoc->GetNodes()[ pFlyFmt->GetCntnt().GetCntntIdx()->
1303 GetIndex()+1 ]->GetGrfNode();
1305 _SetPictureSize( *pGrfNd, pPos->nNode,
1306 (SfxItemSet&)pFlyFmt->GetAttrSet(),
1307 pPicType );
1310 if( pGrfAttrSet )
1311 DELETEZ( pGrfAttrSet );
1314 void SwRTFParser::_SetPictureSize( const SwNoTxtNode& rNd,
1315 const SwNodeIndex& rAnchor,
1316 SfxItemSet& rSet,
1317 const SvxRTFPictureType* pPicType )
1319 Size aSize( ((SwNoTxtNode&)rNd).GetTwipSize() );
1320 if( pPicType )
1322 if( rNd.IsGrfNode() )
1324 if( SvxRTFPictureType::WIN_METAFILE != pPicType->eStyle &&
1325 pPicType->nGoalWidth && pPicType->nGoalHeight )
1327 aSize.Width() = pPicType->nGoalWidth;
1328 aSize.Height() =pPicType->nGoalHeight;
1330 else if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle )
1332 // IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !!
1333 aSize.Width() = pPicType->nWidth * 20;
1334 aSize.Height() = pPicType->nHeight * 20;
1336 else
1338 // von 100TH_MM nach TWIP umrechenen!
1339 // #117879# when \picwgoal resp \pichgoal are present, then use them.
1340 // The values of \picwgoal and \picwgoal are already given in twips.
1341 aSize.Width() = (pPicType->nGoalWidth?pPicType->nGoalWidth:(pPicType->nWidth*144)/254);
1342 aSize.Height() = (pPicType->nGoalHeight?pPicType->nGoalHeight:(pPicType->nHeight*144)/254);
1344 ((SwGrfNode&)rNd).SetTwipSize( aSize );
1347 if( 100 != pPicType->nScalX )
1348 aSize.Width() = (((long)pPicType->nScalX) * ( aSize.Width() -
1349 ( pPicType->nCropL + pPicType->nCropR ))) / 100L;
1351 if( 100 != pPicType->nScalY )
1352 aSize.Height() = (((long)pPicType->nScalY) * ( aSize.Height() -
1353 ( pPicType->nCropT + pPicType->nCropB ))) / 100L;
1356 //steht der Fly etwa in einer Tabelle ?
1357 const SwNode* pAnchorNd = pDoc->GetNodes()[ rAnchor ];
1358 const SwTableNode* pTblNd = pAnchorNd->FindTableNode();
1359 if( pTblNd )
1361 // Box feststellen:
1362 const SwTableBox* pBox = pTblNd->GetTable().GetTblBox(
1363 pAnchorNd->StartOfSectionIndex() );
1364 if( pBox )
1366 long nBoxWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1367 if( aSize.Width() > nBoxWidth )
1368 aSize.Width() = nBoxWidth;
1372 //JP 8.11.2001: bug 94450 - if no size exist, then the size is set by
1373 // the swapin of the graphic.
1374 SwGrfNode* pGrfNd;
1375 if( !aSize.Width() && !aSize.Height() &&
1376 0 != (pGrfNd = (SwGrfNode*)rNd.GetGrfNode() ) && pGrfNd->IsGrfLink() )
1377 pGrfNd->SetChgTwipSize( TRUE );
1379 // min. Werte einhalten !!
1380 if( aSize.Width() < MINFLY )
1381 aSize.Width() = MINFLY;
1382 if( aSize.Height() < MINFLY)
1383 aSize.Height() = MINFLY;
1385 if( pPicType )
1387 BOOL bChg = FALSE;
1388 SwCropGrf aCrop;
1391 JP 28.07.99: Bug 67800 - no crop by MAC_QUICKDRAW. At time i dont know why
1392 it has been coded. But this has used for any
1393 RTF-File, but i dont found them.
1394 if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle )
1396 // evt. ein wenig Croppen ??
1397 // IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !!
1398 long nTmp = pPicType->nWidth * 20;
1399 if( nTmp != aSize.Width() )
1401 // in der Breite (also rechts) croppen
1402 aCrop.Right() = nTmp - aSize.Width();
1403 aSize.Width() = nTmp;
1404 bChg = TRUE;
1407 nTmp = pPicType->nHeight * 20;
1408 if( nTmp != aSize.Height() )
1410 // in der Hoehe (also unten) croppen
1411 aCrop.Bottom() = nTmp - aSize.Height();
1412 aSize.Height() = nTmp;
1413 bChg = TRUE;
1417 if( pPicType->nCropT )
1419 aCrop.SetTop( pPicType->nCropT );
1420 bChg = TRUE;
1422 if( pPicType->nCropB )
1424 aCrop.SetBottom( pPicType->nCropB );
1425 bChg = TRUE;
1427 if( pPicType->nCropL )
1429 aCrop.SetLeft( pPicType->nCropL );
1430 bChg = TRUE;
1432 if( pPicType->nCropR )
1434 aCrop.SetRight( pPicType->nCropR );
1435 bChg = TRUE;
1438 if( bChg )
1440 // dann mal an die CropWerte an die GrafikSize anpassen.
1441 ((SwNoTxtNode&)rNd).SetAttr( aCrop );
1444 rSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aSize.Width(), aSize.Height() ));
1447 void SwRTFParser::GetPageSize( Size& rSize )
1449 ASSERT(!maSegments.empty(), "not possible");
1450 if (maSegments.empty())
1452 rSize.Width() = 12240 - 1800 - 1800;
1453 rSize.Height() = 15840 - 1440 - 1440;
1454 return;
1457 const rtfSection &rSect = maSegments.back();
1459 rSize.Width() = rSect.maPageInfo.mnPgwsxn - rSect.maPageInfo.mnMarglsxn - rSect.maPageInfo.mnMargrsxn;
1460 rSize.Height() = rSect.maPageInfo.mnPghsxn - rSect.maPageInfo.mnMargtsxn - rSect.maPageInfo.mnMargbsxn;
1462 long nCols = rSect.NoCols();
1463 if (1 < nCols)
1465 rSize.Width() /= nCols;
1466 rSize.Height() /= nCols;
1470 void SwRTFParser::ReadBitmapData()
1472 Graphic aGrf;
1473 SvxRTFPictureType aPicType;
1474 if( ReadBmpData( aGrf, aPicType ) )
1475 InsPicture( aEmptyStr, &aGrf, &aPicType );
1478 #ifdef READ_OLE_OBJECT
1479 void SwRTFParser::ReadOLEData()
1481 SvCacheStream aTmpFile( 0xA000 );
1482 Graphic aGrf;
1483 SvxRTFPictureType aPicType, aOleType;
1485 int nToken, bValidOle = TRUE, bWeiter = TRUE;
1486 int nOpenBrakets = 1; // die erste wurde schon vorher erkannt !!
1488 String* pStr = 0;
1489 String sObjClass, sObjName, sObjData;
1491 while( nOpenBrakets && IsParserWorking() && bWeiter && bValidOle )
1493 nToken = GetNextToken();
1494 USHORT nVal = USHORT( nTokenValue );
1495 switch( nToken )
1497 case '}': --nOpenBrakets; pStr = 0; break;
1498 case '{':
1500 if( RTF_IGNOREFLAG != GetNextToken() )
1501 nToken = SkipToken( -1 );
1502 else if( RTF_UNKNOWNCONTROL != GetNextToken() )
1503 nToken = SkipToken( -2 );
1504 else
1506 // gleich herausfiltern
1507 ReadUnknownData();
1508 nToken = GetNextToken();
1509 if( '}' != nToken )
1510 eState = SVPAR_ERROR;
1511 break;
1513 ++nOpenBrakets;
1515 break;
1517 case RTF_OBJECT:
1518 case RTF_OBJEMB: // default ist embedded
1519 case RTF_LINKSELF: // ??
1520 case RTF_OBJLOCK: // ??
1521 case RTF_OBJUPDATE: // ??
1522 case RTF_OBJTIME: // ??
1523 case RTF_OBJSETSIZE:
1524 case RTF_OBJALIGN:
1525 case RTF_OBJTRANSY:
1526 case RTF_OBJATTPH:
1527 break;
1529 case RTF_OBJLINK: // ?? welche Daten sind das ??
1530 case RTF_OBJAUTLINK: // ?? -""- ??
1531 case RTF_OBJSUB:
1532 case RTF_OBJPUB:
1533 case RTF_OBJICEMB:
1534 case RTF_OBJOCX:
1535 case RTF_OBJHTML:
1536 case RTF_OBJALIAS:
1537 case RTF_OBJSECT:
1538 bValidOle = FALSE; // diese Typen koennen wir nicht
1539 break;
1541 case RTF_OBJCLASS:
1542 // Daten lesen
1543 pStr = &sObjClass;
1544 break;
1546 case RTF_OBJNAME:
1547 // Daten lesen
1548 pStr = &sObjName;
1549 break;
1551 case RTF_OBJDATA:
1552 pStr = &sObjData;
1553 break;
1555 case RTF_RESULT:
1557 // hier weitermachen, wenn das OLE-Object ungueltig ist
1558 bWeiter = FALSE;
1560 break;
1561 case RTF_RSLTBMP: // diese sollten wir ignorieren
1562 case RTF_RSLTMERGE:
1563 case RTF_RSLTPICT:
1564 case RTF_RSLTRTF:
1565 case RTF_RSLTTXT:
1566 break;
1568 case RTF_OBJW: aOleType.nWidth = nVal; break;
1569 case RTF_OBJH: aOleType.nHeight = nVal; break;
1570 case RTF_OBJCROPT: aOleType.nCropT = (short)nTokenValue; break;
1571 case RTF_OBJCROPB: aOleType.nCropB = (short)nTokenValue; break;
1572 case RTF_OBJCROPL: aOleType.nCropL = (short)nTokenValue; break;
1573 case RTF_OBJCROPR: aOleType.nCropR = (short)nTokenValue; break;
1574 case RTF_OBJSCALEX: aOleType.nScalX = nVal; break;
1575 case RTF_OBJSCALEY: aOleType.nScalY = nVal; break;
1577 case RTF_TEXTTOKEN:
1578 if( 1 < nOpenBrakets && pStr )
1580 if( pStr == &sObjData )
1582 xub_StrLen nHexLen = HexToBin( aToken );
1583 if( STRING_NOTFOUND != nHexLen )
1584 bValidOle = FALSE;
1585 else
1587 aTmpFile.Write( (sal_Char*)aToken.GetBuffer(), nHexLen );
1588 bValidOle = 0 == aTmpFile.GetError();
1591 else
1592 *pStr += aToken;
1594 break;
1598 if( bValidOle )
1600 bValidOle = FALSE; // erstmal
1603 if( !bWeiter ) // dann stehen wir noch im Result
1605 // ist das Ole-Object Ok?
1606 // -> dann solange SkipGroup rufen, bis zur letzten
1607 // schliessenden Klammer
1608 // ansonsten alle Token verarbeiten, bis zur letzten
1609 // schliessenden Klammer
1611 bWeiter = TRUE;
1612 while( nOpenBrakets && IsParserWorking() && bWeiter )
1614 switch( nToken = GetNextToken() )
1616 case '}': --nOpenBrakets; break;
1617 case '{': ++nOpenBrakets; break;
1619 if( nOpenBrakets && !bValidOle )
1620 NextToken( nToken );
1624 if( !bValidOle && '}' != nToken )
1625 SkipGroup();
1627 SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
1629 #endif
1631 /* vi:set tabstop=4 shiftwidth=4 expandtab: */