merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / rtf / rtffly.cxx
blob706dc39b8179f7692efabdceb0413ce88eabd13d
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: rtffly.cxx,v $
10 * $Revision: 1.35 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
34 #include <hintids.hxx>
35 #include <tools/list.hxx>
36 #include <tools/cachestr.hxx>
37 #include <svtools/rtftoken.h>
38 #include <svtools/itemiter.hxx>
39 #include <svx/prntitem.hxx>
40 #include <svx/opaqitem.hxx>
41 #include <svx/protitem.hxx>
42 #include <svx/ulspitem.hxx>
43 #include <svx/lrspitem.hxx>
44 #include <svx/boxitem.hxx>
45 #include <svx/frmdiritem.hxx>
46 #include <fmtfsize.hxx>
47 #include <fmtanchr.hxx>
48 #include <fmtpdsc.hxx>
49 #include <fmtsrnd.hxx>
50 #include <fmtclds.hxx>
51 #include <fmtcntnt.hxx>
52 #include <frmatr.hxx>
53 #include <doc.hxx>
54 #include <pam.hxx>
55 #include <ndtxt.hxx>
56 #include <shellio.hxx>
57 #include <swparrtf.hxx>
58 #include <grfatr.hxx>
59 #include <paratr.hxx>
60 #include <rtf.hxx>
61 #include <ndgrf.hxx>
62 #include <pagedesc.hxx>
63 #include <swtable.hxx>
64 #include <txtflcnt.hxx>
65 #include <fmtflcnt.hxx>
66 #include <fltini.hxx>
67 #ifndef __SGI_STL_DEQUE
68 #include <deque>
69 #endif
70 #ifndef __SGI_STL_MAP
71 #include <map>
72 #endif
73 #ifndef __SGI_STL_UTILITY
74 #include <utility>
75 #endif
76 // --> OD 2004-06-30 #i27767#
77 #include <fmtwrapinfluenceonobjpos.hxx>
78 // <--
79 #include <svx/brshitem.hxx>
80 #include <fmtfollowtextflow.hxx>
81 // --> OD, FLR 2006-02-16 #131205#
82 #include "dcontact.hxx"
83 // <--
85 using namespace ::com::sun::star;
87 #define ANCHOR(p) ((SwFmtAnchor*)p)
89 // steht in shellio.hxx
90 extern SwCntntNode* GoNextNds( SwNodeIndex * pIdx, BOOL bChk );
92 SV_IMPL_PTRARR( SwFlySaveArr, SwFlySave* )
94 inline const SwFmtFrmSize GetFrmSize(const SfxItemSet& rSet, BOOL bInP=TRUE)
96 return (const SwFmtFrmSize&)rSet.Get(RES_FRM_SIZE,bInP);
99 SwFlySave::SwFlySave(const SwPaM& rPam, SfxItemSet& rSet)
100 : aFlySet(rSet), nSttNd(rPam.GetPoint()->nNode), nEndNd(nSttNd), nEndCnt(0),
101 nPageWidth(ATT_MIN_SIZE), nDropLines(0), nDropAnchor(0)
105 int SwFlySave::IsEqualFly( const SwPaM& rPos, SfxItemSet& rSet )
107 if( rSet.Count() != aFlySet.Count() || nDropAnchor )
108 return FALSE;
110 // nur TextNodes zusammenfassen
111 if( nSttNd == nEndNd && nEndNd.GetNode().IsNoTxtNode() )
112 return FALSE;
114 // teste auf gleiche / naechste Position
115 if( rPos.GetPoint()->nNode.GetIndex() == nEndNd.GetIndex() )
117 if( 1 < (rPos.GetPoint()->nContent.GetIndex() - nEndCnt) )
118 return FALSE;
120 else if( rPos.GetPoint()->nContent.GetIndex() )
121 return FALSE;
122 else
124 SwNodeIndex aIdx( nEndNd );
125 SwCntntNode* pCNd = rPos.GetDoc()->GetNodes()[ aIdx ]->GetCntntNode();
126 if( !GoNextNds( &aIdx, TRUE ) ||
127 aIdx.GetIndex() != rPos.GetPoint()->nNode.GetIndex() ||
128 ( pCNd && pCNd->Len() != nEndCnt ))
130 return FALSE;
134 if( rSet.Count() )
136 SfxItemIter aIter( rSet );
137 const SfxPoolItem *pItem, *pCurr = aIter.GetCurItem();
138 while( TRUE )
140 if( SFX_ITEM_SET != aFlySet.GetItemState( pCurr->Which(),
141 FALSE, &pItem ) ||
142 // Ankerattribute gesondert behandeln
143 ( RES_ANCHOR == pCurr->Which()
144 ? (ANCHOR(pCurr)->GetAnchorId() != ANCHOR(pItem)->GetAnchorId() ||
145 ANCHOR(pCurr)->GetPageNum() != ANCHOR(pItem)->GetPageNum())
146 : *pItem != *pCurr ))
147 return FALSE;
149 if( aIter.IsAtEnd() )
150 break;
151 pCurr = aIter.NextItem();
154 return TRUE;
157 void SwFlySave::SetFlySize( const SwTableNode& rTblNd )
159 // sollte der Fly kleiner als diese Tabelle sein, dann
160 // korrigiere diesen (nur bei abs. Angaben!)
161 SwTwips nWidth = rTblNd.GetTable().GetFrmFmt()->GetFrmSize().GetWidth();
162 const SwFmtFrmSize& rSz = GetFrmSize( aFlySet );
163 if( nWidth > rSz.GetWidth() )
164 aFlySet.Put( SwFmtFrmSize( rSz.GetHeightSizeType(), nWidth, rSz.GetHeight() ));
167 BOOL lcl_HasBreakAttrs( const SwCntntNode& rNd )
169 BOOL bRet = FALSE;
170 const SfxItemSet& rSet = rNd.GetSwAttrSet();
171 const SfxPoolItem* pItem;
172 if( SFX_ITEM_SET == rSet.GetItemState( RES_BREAK, TRUE, &pItem ) &&
173 SVX_BREAK_NONE != ((SvxFmtBreakItem*)pItem)->GetBreak() )
174 bRet = TRUE;
175 else if( SFX_ITEM_SET == rSet.GetItemState( RES_PAGEDESC, TRUE, &pItem )&&
176 0 != ((SwFmtPageDesc*)pItem)->GetPageDesc() )
177 bRet = TRUE;
178 return bRet;
182 void lcl_CpyBreakAttrs( SwCntntNode* pSrcNd, SwCntntNode* pDstNd,
183 SwNodeIndex* pNewIdx )
185 const SfxItemSet* pSet;
186 if( pSrcNd && pDstNd && 0 != ( pSet = pSrcNd->GetpSwAttrSet() ) )
188 const SfxPoolItem *pDescItem, *pBreakItem;
190 if( SFX_ITEM_SET != pSet->GetItemState( RES_BREAK,
191 FALSE, &pBreakItem ) )
192 pBreakItem = 0;
194 if( SFX_ITEM_SET != pSet->GetItemState( RES_PAGEDESC,
195 FALSE, &pDescItem ) )
196 pDescItem = 0;
198 if( pDescItem || pBreakItem )
200 if( lcl_HasBreakAttrs( *pDstNd ))
202 SwPosition aPos( *pDstNd, SwIndex( pDstNd ));
203 aPos.nNode--;
204 pDstNd->GetDoc()->AppendTxtNode( aPos );
205 if( pNewIdx )
206 *pNewIdx = aPos.nNode;
208 SwCntntNode* pOldNd = pDstNd;
209 pDstNd = aPos.nNode.GetNode().GetCntntNode();
210 pDstNd->ChgFmtColl( pOldNd->GetFmtColl() );
211 if( pDstNd->HasSwAttrSet() )
213 SfxItemSet aSet( *pDstNd->GetpSwAttrSet() );
214 aSet.ClearItem( RES_BREAK );
215 aSet.ClearItem( RES_PAGEDESC );
216 pDstNd->SetAttr( aSet );
219 if( pBreakItem )
221 pDstNd->SetAttr( *pBreakItem );
222 pSrcNd->ResetAttr( RES_BREAK );
224 if( pDescItem )
226 pDstNd->SetAttr( *pDescItem );
227 pSrcNd->ResetAttr( RES_PAGEDESC );
233 void SwRTFParser::SetFlysInDoc()
235 // !! von Oben abarbeiten, CntntPos ist kein Index !
236 SwNodes & rNds = pDoc->GetNodes();
237 typedef std::pair<SwFlyFrmFmt*, SwFmtAnchor> frameEntry;
238 typedef std::deque<frameEntry> rtfframesAtIndex;
239 typedef std::map<const SwNode*, rtfframesAtIndex> rtfFmtMap;
240 rtfFmtMap aPrevFmts;
242 SwFrmFmt* pParent = pDoc->GetFrmFmtFromPool( RES_POOLFRM_FRAME );
243 for( USHORT n = 0; n < aFlyArr.Count(); ++n )
245 SwFlySave* pFlySave = aFlyArr[ n ];
247 ASSERT( !pFlySave->nSttNd.GetNode().FindFlyStartNode(),
248 "Content vom Fly steht in einem Fly" );
249 ASSERT( pFlySave->nSttNd.GetIndex() <= pFlySave->nEndNd.GetIndex(),
250 "Fly hat falschen Bereich" );
254 //JP 21.09.98: wenn ein DropCap ist, dann Text im Node belassen, am
255 // Absatz das Absatz Attribut setzen. Ggfs noch die
256 // FontSize zuruecksetzen, damit das DropCap nicht zu
257 // gro? wird.
258 if( pFlySave->nDropAnchor )
260 SwTxtNode* pSttNd = pFlySave->nSttNd.GetNode().GetTxtNode();
261 SwTxtNode* pEndNd = pFlySave->nEndNd.GetNode().GetTxtNode();
262 if( pSttNd && pEndNd &&
263 pSttNd->GetIndex() + 1 == pEndNd->GetIndex()
264 && pSttNd->GetTxt().Len()>0 /* #i38227# leave drop caps with no content as fly frames */ )
266 ULONG nPos = pSttNd->GetIndex();
267 SwDoc * pDoc1 = pSttNd->GetDoc();
269 BOOL bJoined;
271 SwPaM aTmp( *pSttNd, pSttNd->GetTxt().Len(), *pEndNd, 0 );
272 bJoined = pDoc1->DeleteAndJoin( aTmp );
275 SwTxtNode * pNd = (pDoc1->GetNodes()[nPos])->GetTxtNode();
277 if( bJoined && pNd != NULL)
279 SwFmtDrop aDropCap;
280 aDropCap.GetLines() = (BYTE)pFlySave->nDropLines;
281 aDropCap.GetChars() = 1;
283 SwIndex aIdx( pEndNd );
284 pNd->RstAttr( aIdx, 1, RES_CHRATR_FONTSIZE );
285 pNd->SetAttr( aDropCap );
287 delete pFlySave;
288 continue;
292 // liegt Ende und Start vom Naechsten im gleichen Node, dann muss
293 // gesplittet werden
294 if( n + 1 < aFlyArr.Count() && pFlySave->nEndCnt &&
295 pFlySave->nEndNd == aFlyArr[ n + 1 ]->nSttNd )
297 SwCntntNode* pCNd = rNds[ pFlySave->nEndNd ]->GetCntntNode();
298 if( pCNd )
300 SwPosition aPos( pFlySave->nEndNd,
301 SwIndex( pCNd, pFlySave->nEndCnt ));
302 pDoc->SplitNode( aPos, false );
303 pFlySave->nEndNd--;
305 else
306 pFlySave->nEndCnt = 0;
309 // verschiebe den Inhalt von diesem Anchor in den Auto-TextBereich
310 // und erzeuge dadurch den richtigen SwG-Rahmen
311 SwNodeRange aRg(pFlySave->nSttNd, 0, pFlySave->nEndNd, 0);
312 //Make a new section, unless there is no content at all
313 const bool bMakeEmptySection = aRg.aStart < aRg.aEnd || ((aRg.aStart == aRg.aEnd) && pFlySave->nEndCnt);
316 // Nur TextNodes koennen in Tabellen stehen !!
317 const SwNode* pNd = &pFlySave->nSttNd.GetNode();
318 if( pNd->IsNoTxtNode() )
320 // die Size muss noch korrigiert werden!
321 nAktPageDesc = 0; // Standart PageDesc
322 if( SFX_ITEM_SET != pFlySave->aFlySet.GetItemState(
323 RES_FRM_SIZE, FALSE ) )
324 _SetPictureSize( *(SwNoTxtNode*)pNd, aRg.aStart,
325 pFlySave->aFlySet );
326 if( 0 != ( pNd = pNd->FindTableNode() ) )
327 pFlySave->SetFlySize( *(SwTableNode*)pNd );
329 else
331 // Take care for table nodes
332 pNd = pNd->GetNodes()[ pNd->GetIndex() - 2 ]->GetTableNode();
333 if( pNd ) // if the table starts imediately before aRg -> expand aRg
334 aRg.aStart = *pNd;
336 if( bMakeEmptySection )
338 pNd = &aRg.aEnd.GetNode();
339 ULONG nSectEnd = pNd->EndOfSectionIndex()+1;
341 if (!pNd->IsTableNode() && 0 !=(pNd = pNd->FindTableNode())
342 && (pNd->GetIndex() >= aRg.aStart.GetNode().GetIndex()) )
344 const SwNode* pTblBxNd;
346 // Ende der Tabelle ist hinter dieser Box ??
347 if( pNd->EndOfSectionIndex() == nSectEnd )
348 aRg.aEnd = nSectEnd+1;
349 // is the end in the first box of the table, then
350 // move before the table (Bug 67663)
351 // but the range must not become emtpy, i.e. aStart==aEnd
352 // because otherwise we will get a crash (126506) later on
353 else if( 0 != ( pTblBxNd = aRg.aEnd.GetNode().
354 FindTableBoxStartNode()) &&
355 pTblBxNd->GetIndex() - 1 == pNd->GetIndex() &&
356 &aRg.aStart.GetNode() != pNd )
357 aRg.aEnd = *pNd;
358 else
360 // Tabelle ist noch groesser, also splitte sie hier.
361 rNds.SplitTable( aRg.aEnd, TRUE );
362 aRg.aEnd = pNd->EndOfSectionIndex() + 1;
369 // vorm verschieben muss sich der Index auf die alte Position
370 // gemerkt werden, der Index wird mit verschoben !!!
372 SwNodeIndex aTmpIdx( rNds.GetEndOfAutotext() );
373 SwStartNode* pSttNd = bMakeEmptySection
374 ? rNds.MakeEmptySection( aTmpIdx, SwFlyStartNode )
375 : rNds.MakeTextSection( aTmpIdx, SwFlyStartNode,
376 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
378 // das ist die Verankerungs-Position (fuers Layout!)
379 pFlySave->nSttNd = aRg.aStart.GetIndex()-1;
380 if( bMakeEmptySection )
382 // check: the move does not clear the surrounded section. If all
383 // nodes moved away, then create a new TxtNode
385 // i76403: an empty selection is not a good idea
386 if( aRg.aStart == aRg.aEnd && aRg.aStart.GetNode().GetTxtNode() )
387 aRg.aEnd++;
388 SwNodeIndex aPrev( aRg.aStart, -1 );
389 if( aPrev.GetNode().IsStartNode() &&
390 aPrev.GetNode().EndOfSectionNode() == &aRg.aEnd.GetNode())
392 // create new txtnode, because the section does never be empty
393 pDoc->GetNodes().MakeTxtNode( aRg.aEnd,
394 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
395 aRg.aEnd--;
398 aTmpIdx = *pSttNd->EndOfSectionNode();
399 pDoc->MoveNodeRange( aRg, aTmpIdx,
400 IDocumentContentOperations::DOC_MOVEDEFAULT );
403 // patch from cmc for #i52542#
404 if (pSttNd->GetIndex() + 1 == pSttNd->EndOfSectionIndex())
406 ASSERT(!this, "nothing in this frame, not legal");
407 delete pFlySave;
408 continue;
411 pFlySave->aFlySet.Put( SwFmtCntnt( pSttNd ));
413 CalculateFlySize( pFlySave->aFlySet, pFlySave->nSttNd,
414 pFlySave->nPageWidth );
416 // THIS >>>>>
417 // if the section only contains one Node and this has a
418 // border or backgorund, then put it to the frame
419 // Not in our own RTF-Format!
420 // <<<<< DOES NOT MAKE SENSE TO ME (flr)
421 // #102781#. Added support for transparent frames.
422 if( pSttNd->GetIndex() + 1 != pSttNd->EndOfSectionIndex() &&
423 !bSwPageDesc )
425 SwCntntNode* pSrcNd = pDoc->GetNodes()[ pSttNd->GetIndex() + 1 ]->GetCntntNode();
426 SfxItemSet aTmpSet( pDoc->GetAttrPool(),
427 RES_BACKGROUND, RES_BOX );
428 const SvxBrushItem* pBackgroundBrush = (const SvxBrushItem*)pFlySave->aFlySet.GetItem(RES_BACKGROUND, FALSE);
429 if( pSrcNd && pSrcNd->HasSwAttrSet() )
430 aTmpSet.Put( *pSrcNd->GetpSwAttrSet() );
431 if (pBackgroundBrush)
433 aTmpSet.Put(*pBackgroundBrush, RES_BACKGROUND);
435 else
437 pBackgroundBrush = (const SvxBrushItem*)aTmpSet.GetItem(RES_BACKGROUND, FALSE);
438 if (pBackgroundBrush)
440 Color& rBackgroundColor = const_cast<SvxBrushItem*>(pBackgroundBrush)->GetColor();
441 rBackgroundColor.SetTransparency(0xFE);
443 else
445 Color aColor = Color(0xff, 0xff, 0xff);
446 aColor.SetTransparency( 0xFE);
447 SvxBrushItem aBrush(aColor, RES_BACKGROUND);
448 aTmpSet.Put(aBrush, RES_BACKGROUND);
451 // #117914# Topic 6.
452 pFlySave->aFlySet.Put( aTmpSet );
453 if( pSrcNd && pSrcNd->HasSwAttrSet() )
455 pSrcNd->ResetAttr( RES_BACKGROUND, RES_BOX );
459 SwFlyFrmFmt* pFmt = pDoc->MakeFlyFrmFmt( aEmptyStr, pParent );
460 pFmt->SetFmtAttr( pFlySave->aFlySet );
461 const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
462 if( FLY_IN_CNTNT != rAnchor.GetAnchorId() )
464 // korrigiere noch den Absatz, ist immer der vorhergehende !
465 // JP 20.09.95: wenn es diesen gibt! (DocAnfang!)
467 //JP 02.08.99: that is wrong. The anchor is ever the NEXT!
468 //JP 05.08.99: there are an Bug in the ExportFilter which will
469 // be fixed in the Version 517 - by SWG-Export
470 // the fly will be after the paragraph - but in RTF
471 // the flys will be before the paragraph.
472 if( !bSwPageDesc || 5430 < GetVersionNo() )
473 pFlySave->nSttNd++;
475 // if( !pFlySave->nSttNd.GetNode().IsCntntNode() )
477 // Seitenumbrueche in den Bodybereich verschieben!
478 SwCntntNode* pSrcNd = aRg.aStart.GetNode().GetCntntNode();
479 SwCntntNode* pDstNd = pFlySave->nSttNd.GetNode().GetCntntNode();
480 if( !pDstNd )
481 pDstNd = pDoc->GetNodes().GoNext( &pFlySave->nSttNd );
483 ::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nSttNd );
486 const SwNodeIndex aSttNd(*pSttNd);
487 SwNodeIndex aEndNd(*pSttNd->EndOfSectionNode());
488 aEndNd--;
490 SwPosition aPos( pFlySave->nSttNd );
491 SwFmtAnchor aAnchor(rAnchor);
492 aAnchor.SetAnchor(&aPos);
494 const SwNode *pCurrentAnchor = &(pFlySave->nSttNd.GetNode());
495 aPrevFmts[pCurrentAnchor].push_back(frameEntry(pFmt, aAnchor));
497 while (aEndNd > aSttNd)
499 typedef rtfframesAtIndex::iterator myIter;
500 rtfframesAtIndex &rDeque = aPrevFmts[&(aEndNd.GetNode())];
501 myIter aEnd = rDeque.end();
502 for (myIter aIter = rDeque.begin(); aIter != aEnd; ++aIter)
504 aIter->second.SetAnchor(&aPos);
505 // --> OD 2004-06-30 #i27767# - push on front to keep order
506 // of objects for the correct object positioning
507 //aPrevFmts[pCurrentAnchor].push_back(*aIter);
508 aPrevFmts[pCurrentAnchor].push_front(*aIter);
510 rDeque.clear();
511 aEndNd--;
515 // --> OD, FLR 2006-02-16 #131205#
516 // Create draw contact object, which also creates a <SdrObject> instance,
517 // in order to set the order number.
518 // The order number is assumed to be the order of the text flow.
519 SwFlyDrawContact* pContact =
520 new SwFlyDrawContact( pFmt,
521 pFmt->GetDoc()->GetOrCreateDrawModel() );
522 pContact->GetMaster()->SetOrdNum( n );
523 // <--
525 delete pFlySave;
528 typedef rtfFmtMap::reverse_iterator myriter;
529 myriter aEnd = aPrevFmts.rend();
530 for(myriter aIter = aPrevFmts.rbegin(); aIter != aEnd; ++aIter)
532 rtfframesAtIndex &rDeque = aIter->second;
533 typedef rtfframesAtIndex::iterator myIter;
534 myIter aQEnd = rDeque.end();
535 for (myIter aQIter = rDeque.begin(); aQIter != aQEnd; ++aQIter)
537 frameEntry &rEntry = *aQIter;
538 SwFlyFrmFmt *pFrm = rEntry.first;
539 SwFmtAnchor &rAnchor = rEntry.second;
540 pFrm->SetFmtAttr(rAnchor);
544 aFlyArr.Remove(0, aFlyArr.Count());
547 // clips the text box to the min or max position if it is outside our min or max boundry
548 long SwRTFParser::GetSafePos(long nPos)
550 if(nPos > SHRT_MAX)
551 nPos = SHRT_MAX;
552 else if(nPos < SHRT_MIN)
553 nPos = SHRT_MIN;
555 return nPos;
558 void SwRTFParser::ReadFly( int nToken, SfxItemSet* pSet )
560 // ein Set fuer die FrmFmt-Attribute
561 SfxItemSet aSet( pDoc->GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
562 if( !IsNewDoc() )
563 Reader::ResetFrmFmtAttrs( aSet );
565 // der Fly beginnt immer in einem neuen Absatz
566 if( pPam->GetPoint()->nContent.GetIndex() )
567 InsertPara();
569 // RTF-Defaults setzen:
570 // --> OD 2004-06-24 #i27767#
571 SwFmtAnchor aAnchor( FLY_AT_CNTNT );
573 SwFmtHoriOrient aHori( 0, text::HoriOrientation::LEFT, text::RelOrientation::FRAME );
574 SwFmtVertOrient aVert( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME );
575 // <--
576 SvxFrameDirectionItem aFrmDir( FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR );
578 USHORT nCols = USHRT_MAX, nColSpace = USHRT_MAX, nAktCol = 0;
579 SvUShorts aColumns;
581 BOOL bChkDropCap = 0 == pSet;
582 USHORT nDropCapLines = 0, nDropCapAnchor = 0;
583 int nNumOpenBrakets = GetOpenBrakets();
585 if( !pSet )
587 pSet = &aSet;
589 else
591 // die Werte aus dem uebergebenen!
592 aAnchor = (SwFmtAnchor&)pSet->Get( RES_ANCHOR );
593 aHori = (SwFmtHoriOrient&)pSet->Get( RES_HORI_ORIENT );
594 aVert = (SwFmtVertOrient&)pSet->Get( RES_VERT_ORIENT );
597 // dann sammel mal alle Attribute zusammen
598 int bWeiter = TRUE;
599 int nAppliedProps=0;
600 do {
601 USHORT nVal = USHORT(nTokenValue);
603 #i5263#
604 Assume that a property genuinely contributes towards creating a frame,
605 and if turns out to be a non contributing one reduce the count.
607 ++nAppliedProps;
608 switch( nToken )
610 case RTF_ABSW:
612 SwFmtFrmSize aSz( ATT_MIN_SIZE, nTokenValue, 0 );
613 const SfxPoolItem* pItem;
614 if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, TRUE,
615 &pItem ))
617 aSz.SetHeightSizeType( ((SwFmtFrmSize*)pItem)->GetHeightSizeType() );
618 aSz.SetHeight( ((SwFmtFrmSize*)pItem)->GetHeight() );
620 if( MINFLY > nTokenValue ) nTokenValue = MINFLY;
621 aSet.Put( aSz );
623 break;
624 case RTF_ABSH:
626 SwFmtFrmSize aSz( ATT_MIN_SIZE, 0, MINFLY );
627 const SfxPoolItem* pItem;
628 if( SFX_ITEM_SET == pSet->GetItemState( RES_FRM_SIZE, TRUE,
629 &pItem ))
631 aSz.SetWidth( ((SwFmtFrmSize*)pItem)->GetWidth() );
634 if( 0 > nTokenValue )
636 nTokenValue = -nTokenValue;
637 aSz.SetHeightSizeType( ATT_FIX_SIZE );
639 if( MINFLY > nTokenValue ) nTokenValue = MINFLY;
640 aSz.SetHeight( nTokenValue );
641 aSet.Put( aSz );
643 break;
645 case RTF_NOWRAP:
647 pSet->Put( SwFmtSurround( SURROUND_NONE ));
649 break;
650 case RTF_DXFRTEXT:
652 SvxULSpaceItem aUL( RES_UL_SPACE );
653 SvxLRSpaceItem aLR( RES_LR_SPACE );
654 aUL.SetUpper( nVal ); aUL.SetLower( nVal );
655 aLR.SetLeft( nVal ); aLR.SetRight( nVal );
656 pSet->Put( aUL );
657 pSet->Put( aLR );
659 break;
661 case RTF_DFRMTXTX:
663 SvxLRSpaceItem aLR( RES_LR_SPACE );
664 aLR.SetLeft( nVal ); aLR.SetRight( nVal );
665 pSet->Put( aLR );
667 break;
668 case RTF_DFRMTXTY:
670 SvxULSpaceItem aUL( RES_UL_SPACE );
671 aUL.SetUpper( nVal ); aUL.SetLower( nVal );
672 pSet->Put( aUL );
674 break;
676 case RTF_POSNEGX:
677 case RTF_POSX: aHori.SetHoriOrient( text::HoriOrientation::NONE );
678 aHori.SetPos( GetSafePos((long)nTokenValue) );
679 break;
680 case RTF_POSXC: aHori.SetHoriOrient( text::HoriOrientation::CENTER ); break;
681 case RTF_POSXI: aHori.SetHoriOrient( text::HoriOrientation::LEFT );
682 aHori.SetPosToggle( TRUE );
683 break;
684 case RTF_POSXO: aHori.SetHoriOrient( text::HoriOrientation::RIGHT );
685 aHori.SetPosToggle( TRUE );
686 break;
687 case RTF_POSXL: aHori.SetHoriOrient( text::HoriOrientation::LEFT ); break;
688 case RTF_POSXR: aHori.SetHoriOrient( text::HoriOrientation::RIGHT ); break;
690 case RTF_POSNEGY:
691 case RTF_POSY: aVert.SetVertOrient( text::VertOrientation::NONE );
692 aVert.SetPos( GetSafePos((long)nTokenValue) );
693 break;
694 case RTF_POSYT: aVert.SetVertOrient( text::VertOrientation::TOP ); break;
695 case RTF_POSYB: aVert.SetVertOrient( text::VertOrientation::BOTTOM ); break;
696 case RTF_POSYC: aVert.SetVertOrient( text::VertOrientation::CENTER ); break;
698 case RTF_PHMRG: aHori.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break;
699 case RTF_PVMRG: aVert.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA ); break;
700 case RTF_PHPG: aHori.SetRelationOrient( text::RelOrientation::PAGE_FRAME ); break;
701 case RTF_PVPG: aVert.SetRelationOrient( text::RelOrientation::PAGE_FRAME );break;
702 case RTF_PHCOL: aHori.SetRelationOrient( text::RelOrientation::FRAME ); break;
703 case RTF_PVPARA: aVert.SetRelationOrient( text::RelOrientation::FRAME ); break;
705 case RTF_POSYIL:
706 break;
707 case RTF_ABSLOCK:
709 #i5263#
710 Not sufficient to make a frame at least word won't do it with just
711 an abslock
713 --nAppliedProps;
714 break;
715 case RTF_FRMTXLRTB:
716 aFrmDir.SetValue( FRMDIR_HORI_LEFT_TOP );
717 break;
718 case RTF_FRMTXTBRL:
719 aFrmDir.SetValue( FRMDIR_HORI_RIGHT_TOP );
720 break;
721 case RTF_FRMTXLRTBV:
722 aFrmDir.SetValue( FRMDIR_VERT_TOP_LEFT );
723 break;
724 case RTF_FRMTXTBRLV:
725 aFrmDir.SetValue( FRMDIR_VERT_TOP_RIGHT );
726 break;
728 case RTF_DROPCAPLI: // Dropcaps !!
729 if( bChkDropCap )
731 nDropCapLines = USHORT( nTokenValue );
732 if( !nDropCapAnchor )
733 nDropCapAnchor = 1;
735 break;
736 case RTF_DROPCAPT:
737 if( bChkDropCap )
739 nDropCapAnchor = USHORT( nTokenValue );
740 if( !nDropCapLines )
741 nDropCapLines = 3;
743 break;
746 // fuer die "alten" Writer - haben die Spaltigkeit falsch heraus-
747 // geschrieben
748 case RTF_COLS: nCols = USHORT( nTokenValue ); break;
749 case RTF_COLSX: nColSpace = USHORT( nTokenValue ); break;
750 case RTF_COLNO:
751 nAktCol = USHORT( nTokenValue );
752 if( RTF_COLW == GetNextToken() )
754 USHORT nWidth = USHORT( nTokenValue ), nSpace = 0;
755 if( RTF_COLSR == GetNextToken() )
756 nSpace = USHORT( nTokenValue );
757 else
758 SkipToken( -1 ); // wieder zurueck
760 if( --nAktCol == ( aColumns.Count() / 2 ) )
762 aColumns.Insert( nWidth + nSpace, aColumns.Count() );
763 aColumns.Insert( nSpace, aColumns.Count() );
766 break;
768 case '{':
770 short nSkip = 0;
771 if( RTF_IGNOREFLAG != ( nToken = GetNextToken() ))
773 if( RTF_SHADINGDEF == (nToken & ~0xff) )
775 ReadBackgroundAttr( nToken, aSet );
776 GetNextToken(); // Klammer ueberlesen
778 else
779 nSkip = -1;
781 else if( RTF_APOCTL ==
782 ((nToken = GetNextToken() ) & ~(0xff | RTF_SWGDEFS)) )
784 bReadSwFly = true; // alles kommt in den akt. Fly
785 SvxLRSpaceItem aLR( RES_LR_SPACE );
786 SvxULSpaceItem aUL( RES_UL_SPACE );
787 nCols = USHRT_MAX; // neu aufsetzen
788 nColSpace = USHRT_MAX;
789 do {
790 nVal = USHORT(nTokenValue);
791 switch( nToken )
793 // Swg-Frame-Tokens
794 case RTF_FLYPRINT:
796 pSet->Put( SvxPrintItem( RES_PRINT, FALSE ));
798 break;
799 case RTF_FLYOPAQUE:
801 pSet->Put( SvxOpaqueItem( RES_OPAQUE, FALSE ));
803 break;
805 case RTF_FLYPRTCTD:
807 RTFProtect aP( (BYTE)nTokenValue );
808 SvxProtectItem aProtectItem( RES_PROTECT );
809 aProtectItem.SetCntntProtect( aP.GetCntnt() );
810 aProtectItem.SetSizeProtect( aP.GetSize() );
811 aProtectItem.SetPosProtect( aP.GetPos() );
812 pSet->Put( aProtectItem );
814 break;
816 case RTF_FLYMAINCNT:
818 RTFSurround aMC( (BYTE)nTokenValue );
819 SwFmtSurround aSurr( (SwSurround)aMC.GetOrder());
820 if( aMC.GetGoldCut() )
821 aSurr.SetSurround( SURROUND_IDEAL );
822 pSet->Put( aSurr );
824 break;
825 case RTF_FLYVERT:
827 RTFVertOrient aVO( nVal );
828 aVert.SetVertOrient( aVO.GetOrient() );
829 aVert.SetRelationOrient( aVO.GetRelation() );
831 break;
832 case RTF_FLYHORZ:
834 RTFHoriOrient aHO( nVal );
835 aHori.SetHoriOrient( aHO.GetOrient() );
836 aHori.SetRelationOrient( aHO.GetRelation() );
838 break;
839 case RTF_FLYOUTLEFT: aLR.SetLeft( nVal ); break;
840 case RTF_FLYOUTRIGHT: aLR.SetRight( nVal ); break;
841 case RTF_FLYOUTUPPER: aUL.SetUpper( nVal ); break;
842 case RTF_FLYOUTLOWER: aUL.SetLower( nVal ); break;
843 case RTF_FLYANCHOR:
844 switch( GetNextToken() )
846 case RTF_FLY_PAGE:
847 aAnchor.SetType( FLY_PAGE );
848 aAnchor.SetPageNum( USHORT(nTokenValue));
849 aAnchor.SetAnchor( 0 );
850 break;
852 case RTF_FLY_CNTNT:
854 SwNodeIndex aIdx( pPam->GetPoint()->nNode );
855 pDoc->GetNodes().GoPrevious( &aIdx );
856 SwPosition aPos( aIdx );
857 aAnchor.SetType( FLY_AT_CNTNT );
858 aAnchor.SetAnchor( &aPos );
860 break;
862 // JP 26.09.94: die Bindung an die Spalte gibt es nicht mehr !!
863 // case RTF_FLY_COLUMN:
865 break;
866 case RTF_COLS: nCols = USHORT( nTokenValue ); break;
867 case RTF_COLSX: nColSpace = USHORT( nTokenValue ); break;
868 case RTF_COLNO:
869 nAktCol = USHORT( nTokenValue );
870 if( RTF_COLW == GetNextToken() )
872 USHORT nWidth = USHORT( nTokenValue ), nSpace = 0;
873 if( RTF_COLSR == GetNextToken() )
874 nSpace = USHORT( nTokenValue );
875 else
876 SkipToken( -1 ); // wieder zurueck
878 if( --nAktCol == ( aColumns.Count() / 2 ) )
880 aColumns.Insert( nWidth + nSpace, aColumns.Count() );
881 aColumns.Insert( nSpace, aColumns.Count() );
884 break;
886 case '{':
887 if( RTF_BRDBOX == ( nToken = GetNextToken() ) )
888 ReadBorderAttr( nToken, aSet );
889 else if( RTF_SHADINGDEF == (nToken & ~0xff ) )
890 ReadBackgroundAttr( nToken, aSet );
891 else if( RTF_IGNOREFLAG == nToken )
893 int bSkipGrp = TRUE;
894 switch( nToken = GetNextToken() )
896 case RTF_SHADOW:
897 case RTF_BRDBOX:
898 ReadAttr( SkipToken( -2 ), &aSet );
899 bSkipGrp = FALSE;
900 break;
902 case RTF_BRDRT:
903 case RTF_BRDRB:
904 case RTF_BRDRR:
905 case RTF_BRDRL:
906 bSkipGrp = FALSE;
907 ReadBorderAttr( SkipToken( -2 ), aSet );
908 break;
911 // keine weitere Klammer mehr ueberlesen!!!
912 if( !bSkipGrp )
913 break;
915 SkipGroup();
917 else
918 SkipGroup();
919 GetNextToken(); // Klammer ueberlesen
920 break;
922 } while( IsParserWorking() &&
923 '}' != ( nToken = GetNextToken() ));
925 if( aUL.GetUpper() || aUL.GetLower() )
926 pSet->Put( aUL );
927 if( aLR.GetLeft() || aLR.GetRight() )
928 pSet->Put( aLR );
930 else if( RTF_BRDBOX == nToken )
931 ReadBorderAttr( nToken, aSet );
932 else if( RTF_SHADOW == nToken )
933 ReadAttr( SkipToken( -2 ), &aSet );
934 else if( RTF_SHADINGDEF == (nToken & ~0xff ) )
935 ReadBackgroundAttr( nToken, aSet );
936 else if( RTF_UNKNOWNCONTROL == nToken )
937 SkipGroup();
938 else
939 nSkip = -2;
941 if( nSkip )
943 nToken = SkipToken( nSkip );
944 bWeiter = FALSE;
947 break;
949 default:
950 --nAppliedProps; //Not sufficient to make a frame
951 bWeiter = FALSE;
954 if( bWeiter )
955 nToken = GetNextToken();
956 } while( bWeiter && IsParserWorking() );
958 pSet->Put( aAnchor );
959 pSet->Put( aHori );
960 pSet->Put( aVert );
962 // --> OD 2004-06-30 #i27767# - set wrapping style influence
963 // --> OD 2004-10-18 #i35017# - constant name has changed
964 pSet->Put( SwFmtWrapInfluenceOnObjPos(
965 text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ));
966 // <--
968 SwFmtFollowTextFlow aFollowTextFlow( FALSE );
969 pSet->Put( aFollowTextFlow );
971 if( !( aFrmDir == pSet->Get( RES_FRAMEDIR )) )
972 pSet->Put( aFrmDir );
974 if( nCols && USHRT_MAX != nCols )
976 SwFmtCol aCol;
977 if( USHRT_MAX == nColSpace )
978 nColSpace = 720;
980 ULONG nWidth = USHRT_MAX;
981 aCol.Init( nCols, nColSpace, USHORT( nWidth ) );
982 if( nCols == ( aColumns.Count() / 2 ) )
984 for( USHORT n = 0, i = 0; n < aColumns.Count(); n += 2, ++i )
986 SwColumn* pCol = aCol.GetColumns()[ i ];
987 ULONG nTmp = aColumns[ n ];
988 nTmp *= USHRT_MAX;
989 nTmp /= nWidth;
990 pCol->SetWishWidth( USHORT(nTmp) );
992 JP 07.07.95: der Dialog kennt nur eine Breite fuer alle Spalten
993 darum hier nicht weiter beachten
994 nTmp = aColumns[ n+1 ];
995 if( nTmp )
996 pCol->SetRight( USHORT(nTmp) );
997 else
998 pCol->SetRight( 0 );
999 pCol->SetLeft( 0 );
1003 pSet->Put( aCol );
1006 if( pSet != &aSet ) // wurde der Set uebergeben, dann wars das
1007 return ;
1009 // ein neues FlyFormat anlegen oder das alte benutzen ?
1010 // (teste ob es die selben Attribute besitzt!)
1011 SwFlySave* pFlySave = 0;
1012 USHORT nFlyArrCnt = aFlyArr.Count();
1014 #i5263#
1015 There were not enough frame properties found to actually justify creating
1016 an absolutely positioned frame.
1018 if (nAppliedProps)
1020 if( !nFlyArrCnt ||
1021 !( pFlySave = aFlyArr[ nFlyArrCnt-1 ])->IsEqualFly( *pPam, aSet ))
1023 pFlySave = new SwFlySave( *pPam, aSet );
1024 Size aPgSize;
1025 GetPageSize( aPgSize );
1026 pFlySave->nPageWidth = aPgSize.Width();
1028 if( nDropCapAnchor )
1030 pFlySave->nDropAnchor = nDropCapAnchor;
1031 pFlySave->nDropLines = nDropCapLines;
1033 if (nFlyArrCnt >0){
1034 SwFlySave* pFlySavePrev = aFlyArr[nFlyArrCnt-1];
1035 if (pFlySave->nSttNd.GetIndex() < pFlySavePrev->nEndNd.GetIndex())
1037 pFlySavePrev->nEndNd=pFlySave->nSttNd;
1040 aFlyArr.Insert( pFlySave, nFlyArrCnt++ );
1041 // --> OD 2008-12-22 #i83368# - reset
1042 mbReadCellWhileReadSwFly = false;
1043 // <--
1047 SetPardTokenRead( FALSE );
1048 const SwTableNode* pTblNd = pPam->GetNode()->FindTableNode();
1050 while( !IsPardTokenRead() && IsParserWorking() )
1052 if( RTF_PARD == nToken || nNumOpenBrakets > GetOpenBrakets() )
1053 break;
1055 NextToken( nToken );
1057 if( !IsPardTokenRead() )
1059 // #102781#. Added support for transparent frames.
1060 if (nToken == RTF_CBPAT && nFlyArrCnt > 0)
1062 USHORT _index=USHORT(nTokenValue);
1063 const Color& rColor = GetColor(_index);
1064 SvxBrushItem aBrush(rColor, RES_BACKGROUND);
1065 SwFlySave* pFS = aFlyArr[nFlyArrCnt-1];
1066 pFS->aFlySet.Put(aBrush, RES_BACKGROUND);
1069 nToken = GetNextToken();
1071 // BUG 22036: kommt zwischen Fly-Attributen ein unbekanntes,
1072 // dann erzeuge nie 2 FlyFrames, sondern fasse
1073 // beide zusammen !!!
1074 while( RTF_APOCTL == ( nToken & ~(0xff | RTF_SWGDEFS) ))
1076 if( RTF_FLY_INPARA == nToken )
1077 break;
1079 if( RTF_IGNOREFLAG == SkipToken( -1 ) )
1081 if( '{' == SkipToken( -1 ) )
1082 nToken = '{';
1083 else
1084 SkipToken( 2 );
1086 else
1087 SkipToken( 1 );
1089 ReadFly( nToken, pFlySave ? &pFlySave->aFlySet : 0);
1090 nToken = GetNextToken();
1096 #i5263#
1097 There were enough frame properties found to actually justify creating
1098 an absolutely positioned frame.
1100 if (!nAppliedProps)
1102 bReadSwFly = false;
1103 SkipToken( -1 );
1104 return;
1107 if( pTblNd && !pPam->GetPoint()->nContent.GetIndex() &&
1108 pTblNd->EndOfSectionIndex() + 1 ==
1109 pPam->GetPoint()->nNode.GetIndex() )
1111 // nicht mehr in der Tabelle, sondern dahinter ?
1112 // Dann aber wieder zurueck in die Tabelle
1113 pPam->Move( fnMoveBackward );
1115 else
1116 pTblNd = 0;
1118 // wurde garnichts eingefuegt?
1119 if( !pTblNd &&
1120 pPam->GetPoint()->nNode == pFlySave->nSttNd &&
1121 !pPam->GetPoint()->nContent.GetIndex() )
1123 // // dann erzeuge mindestens einen leeren TextNode
1124 // pDoc->AppendTxtNode(*pPam);
1125 // dann zerstoere den FlySave wieder.
1126 aFlyArr.DeleteAndDestroy( --nFlyArrCnt );
1129 else
1131 BOOL bMovePaM = 0 != pTblNd;
1133 pFlySave->nEndNd = pPam->GetPoint()->nNode;
1134 pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex();
1136 if( bMovePaM )
1137 pPam->Move( fnMoveForward );
1139 pTblNd = pFlySave->nSttNd.GetNode().FindTableNode();
1140 if( pTblNd && !pFlySave->nEndCnt &&
1141 pTblNd == pFlySave->nEndNd.GetNode().FindTableNode() )
1143 // dann teste mal, ob das \pard nicht zu spaet kam und
1144 // eigentlich in die vorherige Zelle gehoert
1145 const SwStartNode* pSttBoxNd = pFlySave->nSttNd.GetNode().
1146 FindTableBoxStartNode(),
1147 * pEndBoxNd = pFlySave->nEndNd.GetNode().
1148 FindTableBoxStartNode();
1149 if( pSttBoxNd && pEndBoxNd &&
1150 bMovePaM ? ( pSttBoxNd == pEndBoxNd )
1151 : ( pSttBoxNd->EndOfSectionIndex() + 1 ==
1152 pEndBoxNd->GetIndex() &&
1153 pEndBoxNd->GetIndex() + 1 ==
1154 pFlySave->nEndNd.GetIndex() ))
1156 // dann gehoert das Ende in die vorherige Box!
1157 SwPosition aPos( *pPam->GetPoint() );
1158 pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode();
1159 pPam->Move( fnMoveBackward, fnGoNode );
1161 DelLastNode();
1163 pPam->GetPoint()->nNode = *pSttBoxNd->EndOfSectionNode();
1164 pPam->Move( fnMoveBackward, fnGoNode );
1166 pFlySave->nEndNd = pPam->GetPoint()->nNode;
1167 pFlySave->nEndCnt = pPam->GetPoint()->nContent.GetIndex();
1169 *pPam->GetPoint() = aPos;
1172 else if( !bReadSwFly && !pFlySave->nEndCnt &&
1173 pFlySave->nSttNd.GetIndex() + 1 == pFlySave->nEndNd.GetIndex() &&
1174 pFlySave->nSttNd.GetNode().IsTxtNode() )
1177 SwTxtNode* pTxtNd = pFlySave->nSttNd.GetNode().GetTxtNode();
1178 SwTxtFlyCnt* pFlyCnt = 0;
1179 if( 1 == pTxtNd->GetTxt().Len() &&
1180 0 != ( pFlyCnt = (SwTxtFlyCnt*)pTxtNd->GetTxtAttr(
1181 0, RES_TXTATR_FLYCNT )) &&
1182 pFlyCnt->GetFlyCnt().GetFrmFmt() )
1184 // then move the content into the surrounded fly
1185 SwFrmFmt* pFlyFmt = pFlyCnt->GetFlyCnt().GetFrmFmt();
1186 const SwNodeIndex* pFlySNd = pFlyFmt->GetCntnt().GetCntntIdx();
1187 SwNodeRange aRg( *pFlySNd, 1,
1188 *pFlySNd->GetNode().EndOfSectionNode(), 0 );
1190 // merge the itemsets
1191 SwFmtFrmSize aSz1( (SwFmtFrmSize&)pFlyFmt->GetAttrSet().
1192 Get( RES_FRM_SIZE ));
1193 SwFmtFrmSize aSz2( (SwFmtFrmSize&)pFlySave->aFlySet.
1194 Get( RES_FRM_SIZE ));
1195 // if
1196 if( !aRg.aStart.GetNode().IsNoTxtNode() ||
1197 !aSz1.GetHeight() || !aSz1.GetWidth() ||
1198 !aSz2.GetHeight() || !aSz2.GetWidth() ||
1199 ( aSz1.GetHeight() == aSz2.GetHeight() &&
1200 aSz1.GetWidth() == aSz2.GetWidth() ) )
1202 SfxItemSet aDiffs( pFlyFmt->GetAttrSet() );
1203 aDiffs.ClearItem( RES_ANCHOR );
1204 aDiffs.ClearItem( RES_FRM_SIZE );
1205 aDiffs.ClearItem( RES_CNTNT );
1206 aDiffs.Differentiate( pFlySave->aFlySet );
1207 pFlySave->aFlySet.Put( aDiffs );
1209 BOOL bSet = FALSE;
1210 if( aSz1.GetHeight() && !aSz2.GetHeight() )
1212 bSet = TRUE;
1213 aSz2.SetHeight( aSz1.GetHeight() );
1215 if( aSz1.GetWidth() && !aSz2.GetWidth() )
1217 bSet = TRUE;
1218 aSz2.SetWidth( aSz1.GetWidth() );
1220 if( bSet )
1221 pFlySave->aFlySet.Put( aSz2 );
1223 // move any PageBreak/Desc Attr to the next Para
1225 SwCntntNode* pSrcNd = pFlySave->nSttNd.GetNode().GetCntntNode();
1226 SwCntntNode* pDstNd = pFlySave->nEndNd.GetNode().GetCntntNode();
1228 ::lcl_CpyBreakAttrs( pSrcNd, pDstNd, &pFlySave->nEndNd );
1231 // create new txtnode, because the section does never be empty
1232 pDoc->GetNodes().MakeTxtNode( aRg.aStart,
1233 (SwTxtFmtColl*)pDoc->GetDfltTxtFmtColl() );
1235 SwNodeIndex aTmp( pFlySave->nSttNd, +1 );
1236 pDoc->MoveNodeRange( aRg, aTmp,
1237 IDocumentContentOperations::DOC_MOVEDEFAULT );
1239 // now delete the redundant txtnode
1240 pDoc->GetNodes().Delete( pFlySave->nSttNd, 1 );
1246 bReadSwFly = false;
1247 SkipToken( -1 );
1251 void SwRTFParser::InsPicture( const String& rGrfNm, const Graphic* pGrf,
1252 const SvxRTFPictureType* pPicType )
1254 // kennzeichen fuer Swg-Dokumente:
1255 // (dann ist das FlyFmt fuer die Grafik!)
1256 SwGrfNode * pGrfNd;
1257 // --> OD 2008-12-22 #i83368#
1258 // Assure that graphic node is enclosed by fly frame node.
1259 // if( bReadSwFly )
1260 if ( bReadSwFly && !mbReadCellWhileReadSwFly )
1261 // <--
1263 // erzeuge nur einen normalen GrafikNode und ersetze diesen gegen
1264 // den vorhandenen Textnode
1265 SwNodeIndex& rIdx = pPam->GetPoint()->nNode;
1266 pGrfNd = pDoc->GetNodes().MakeGrfNode( rIdx,
1267 rGrfNm, aEmptyStr, // Name der Graphic !!
1268 pGrf,
1269 (SwGrfFmtColl*)pDoc->GetDfltGrfFmtColl() );
1271 if( pGrfAttrSet )
1272 pGrfNd->SetAttr( *pGrfAttrSet );
1274 SwFlySave* pFlySave = aFlyArr[ aFlyArr.Count()-1 ];
1275 pFlySave->nSttNd = rIdx.GetIndex() - 1;
1277 if( 1 < aFlyArr.Count() )
1279 pFlySave = aFlyArr[ aFlyArr.Count() - 2 ];
1280 if( pFlySave->nEndNd == rIdx )
1281 pFlySave->nEndNd = rIdx.GetIndex() - 1;
1284 else
1286 // wenn normale RTF-Grafik, dann steht diese im Textfluss !
1287 SwAttrSet aFlySet( pDoc->GetAttrPool(), RES_OPAQUE, /*RES_OPAQUE,
1288 RES_VERT_ORIENT,*/ RES_ANCHOR );
1289 const SwPosition* pPos = pPam->GetPoint();
1291 SwFmtAnchor aAnchor( FLY_IN_CNTNT );
1292 aAnchor.SetAnchor( pPos );
1293 aFlySet.Put( aAnchor );
1294 aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP ));
1296 if (pDoc->IsInHeaderFooter(pPos->nNode))
1298 SvxOpaqueItem aOpaqueItem(RES_OPAQUE, FALSE);
1299 SwFmtSurround aSurroundItem(SURROUND_THROUGHT);
1300 aFlySet.Put(aOpaqueItem);
1301 aFlySet.Put(aSurroundItem);
1304 SwFrmFmt* pFlyFmt = pDoc->Insert( *pPam,
1305 rGrfNm, aEmptyStr, // Name der Graphic !!
1306 pGrf,
1307 &aFlySet, // Attribute fuer den FlyFrm
1308 pGrfAttrSet, NULL ); // Attribute fuer die Grafik
1310 pGrfNd = pDoc->GetNodes()[ pFlyFmt->GetCntnt().GetCntntIdx()->
1311 GetIndex()+1 ]->GetGrfNode();
1313 _SetPictureSize( *pGrfNd, pPos->nNode,
1314 (SfxItemSet&)pFlyFmt->GetAttrSet(),
1315 pPicType );
1318 if( pGrfAttrSet )
1319 DELETEZ( pGrfAttrSet );
1322 void SwRTFParser::_SetPictureSize( const SwNoTxtNode& rNd,
1323 const SwNodeIndex& rAnchor,
1324 SfxItemSet& rSet,
1325 const SvxRTFPictureType* pPicType )
1327 Size aSize( ((SwNoTxtNode&)rNd).GetTwipSize() );
1328 if( pPicType )
1330 if( rNd.IsGrfNode() )
1332 if( SvxRTFPictureType::WIN_METAFILE != pPicType->eStyle &&
1333 pPicType->nGoalWidth && pPicType->nGoalHeight )
1335 aSize.Width() = pPicType->nGoalWidth;
1336 aSize.Height() =pPicType->nGoalHeight;
1338 else if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle )
1340 // IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !!
1341 aSize.Width() = pPicType->nWidth * 20;
1342 aSize.Height() = pPicType->nHeight * 20;
1344 else
1346 // von 100TH_MM nach TWIP umrechenen!
1347 // #117879# when \picwgoal resp \pichgoal are present, then use them.
1348 // The values of \picwgoal and \picwgoal are already given in twips.
1349 aSize.Width() = (pPicType->nGoalWidth?pPicType->nGoalWidth:(pPicType->nWidth*144)/254);
1350 aSize.Height() = (pPicType->nGoalHeight?pPicType->nGoalHeight:(pPicType->nHeight*144)/254);
1352 ((SwGrfNode&)rNd).SetTwipSize( aSize );
1355 if( 100 != pPicType->nScalX )
1356 aSize.Width() = (((long)pPicType->nScalX) * ( aSize.Width() -
1357 ( pPicType->nCropL + pPicType->nCropR ))) / 100L;
1359 if( 100 != pPicType->nScalY )
1360 aSize.Height() = (((long)pPicType->nScalY) * ( aSize.Height() -
1361 ( pPicType->nCropT + pPicType->nCropB ))) / 100L;
1364 //steht der Fly etwa in einer Tabelle ?
1365 const SwNode* pAnchorNd = pDoc->GetNodes()[ rAnchor ];
1366 const SwTableNode* pTblNd = pAnchorNd->FindTableNode();
1367 if( pTblNd )
1369 // Box feststellen:
1370 const SwTableBox* pBox = pTblNd->GetTable().GetTblBox(
1371 pAnchorNd->StartOfSectionIndex() );
1372 if( pBox )
1374 long nBoxWidth = pBox->GetFrmFmt()->GetFrmSize().GetWidth();
1375 if( aSize.Width() > nBoxWidth )
1376 aSize.Width() = nBoxWidth;
1380 //JP 8.11.2001: bug 94450 - if no size exist, then the size is set by
1381 // the swapin of the graphic.
1382 SwGrfNode* pGrfNd;
1383 if( !aSize.Width() && !aSize.Height() &&
1384 0 != (pGrfNd = (SwGrfNode*)rNd.GetGrfNode() ) && pGrfNd->IsGrfLink() )
1385 pGrfNd->SetChgTwipSize( TRUE );
1387 // min. Werte einhalten !!
1388 if( aSize.Width() < MINFLY )
1389 aSize.Width() = MINFLY;
1390 if( aSize.Height() < MINFLY)
1391 aSize.Height() = MINFLY;
1393 if( pPicType )
1395 BOOL bChg = FALSE;
1396 SwCropGrf aCrop;
1399 JP 28.07.99: Bug 67800 - no crop by MAC_QUICKDRAW. At time i dont know why
1400 it has been coded. But this has used for any
1401 RTF-File, but i dont found them.
1402 if( SvxRTFPictureType::MAC_QUICKDRAW == pPicType->eStyle )
1404 // evt. ein wenig Croppen ??
1405 // IMMER auf 72 DPI bezogen, also 1pt == 20 Twip !!
1406 long nTmp = pPicType->nWidth * 20;
1407 if( nTmp != aSize.Width() )
1409 // in der Breite (also rechts) croppen
1410 aCrop.Right() = nTmp - aSize.Width();
1411 aSize.Width() = nTmp;
1412 bChg = TRUE;
1415 nTmp = pPicType->nHeight * 20;
1416 if( nTmp != aSize.Height() )
1418 // in der Hoehe (also unten) croppen
1419 aCrop.Bottom() = nTmp - aSize.Height();
1420 aSize.Height() = nTmp;
1421 bChg = TRUE;
1425 if( pPicType->nCropT )
1427 aCrop.SetTop( pPicType->nCropT );
1428 bChg = TRUE;
1430 if( pPicType->nCropB )
1432 aCrop.SetBottom( pPicType->nCropB );
1433 bChg = TRUE;
1435 if( pPicType->nCropL )
1437 aCrop.SetLeft( pPicType->nCropL );
1438 bChg = TRUE;
1440 if( pPicType->nCropR )
1442 aCrop.SetRight( pPicType->nCropR );
1443 bChg = TRUE;
1446 if( bChg )
1448 // dann mal an die CropWerte an die GrafikSize anpassen.
1449 ((SwNoTxtNode&)rNd).SetAttr( aCrop );
1452 rSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aSize.Width(), aSize.Height() ));
1455 void SwRTFParser::GetPageSize( Size& rSize )
1457 ASSERT(!maSegments.empty(), "not possible");
1458 if (maSegments.empty())
1460 rSize.Width() = 12240 - 1800 - 1800;
1461 rSize.Height() = 15840 - 1440 - 1440;
1462 return;
1465 const rtfSection &rSect = maSegments.back();
1467 rSize.Width() = rSect.maPageInfo.mnPgwsxn - rSect.maPageInfo.mnMarglsxn - rSect.maPageInfo.mnMargrsxn;
1468 rSize.Height() = rSect.maPageInfo.mnPghsxn - rSect.maPageInfo.mnMargtsxn - rSect.maPageInfo.mnMargbsxn;
1470 long nCols = rSect.NoCols();
1471 if (1 < nCols)
1473 rSize.Width() /= nCols;
1474 rSize.Height() /= nCols;
1478 void SwRTFParser::ReadBitmapData()
1480 Graphic aGrf;
1481 SvxRTFPictureType aPicType;
1482 if( ReadBmpData( aGrf, aPicType ) )
1483 InsPicture( aEmptyStr, &aGrf, &aPicType );
1486 #ifdef READ_OLE_OBJECT
1487 void SwRTFParser::ReadOLEData()
1489 SvCacheStream aTmpFile( 0xA000 );
1490 Graphic aGrf;
1491 SvxRTFPictureType aPicType, aOleType;
1493 int nToken, bValidOle = TRUE, bWeiter = TRUE;
1494 int nOpenBrakets = 1; // die erste wurde schon vorher erkannt !!
1496 String* pStr = 0;
1497 String sObjClass, sObjName, sObjData;
1499 while( nOpenBrakets && IsParserWorking() && bWeiter && bValidOle )
1501 nToken = GetNextToken();
1502 USHORT nVal = USHORT( nTokenValue );
1503 switch( nToken )
1505 case '}': --nOpenBrakets; pStr = 0; break;
1506 case '{':
1508 if( RTF_IGNOREFLAG != GetNextToken() )
1509 nToken = SkipToken( -1 );
1510 else if( RTF_UNKNOWNCONTROL != GetNextToken() )
1511 nToken = SkipToken( -2 );
1512 else
1514 // gleich herausfiltern
1515 ReadUnknownData();
1516 nToken = GetNextToken();
1517 if( '}' != nToken )
1518 eState = SVPAR_ERROR;
1519 break;
1521 ++nOpenBrakets;
1523 break;
1525 case RTF_OBJECT:
1526 case RTF_OBJEMB: // default ist embedded
1527 case RTF_LINKSELF: // ??
1528 case RTF_OBJLOCK: // ??
1529 case RTF_OBJUPDATE: // ??
1530 case RTF_OBJTIME: // ??
1531 case RTF_OBJSETSIZE:
1532 case RTF_OBJALIGN:
1533 case RTF_OBJTRANSY:
1534 case RTF_OBJATTPH:
1535 break;
1537 case RTF_OBJLINK: // ?? welche Daten sind das ??
1538 case RTF_OBJAUTLINK: // ?? -""- ??
1539 case RTF_OBJSUB:
1540 case RTF_OBJPUB:
1541 case RTF_OBJICEMB:
1542 case RTF_OBJOCX:
1543 case RTF_OBJHTML:
1544 case RTF_OBJALIAS:
1545 case RTF_OBJSECT:
1546 bValidOle = FALSE; // diese Typen koennen wir nicht
1547 break;
1549 case RTF_OBJCLASS:
1550 // Daten lesen
1551 pStr = &sObjClass;
1552 break;
1554 case RTF_OBJNAME:
1555 // Daten lesen
1556 pStr = &sObjName;
1557 break;
1559 case RTF_OBJDATA:
1560 pStr = &sObjData;
1561 break;
1563 case RTF_RESULT:
1565 // hier weitermachen, wenn das OLE-Object ungueltig ist
1566 bWeiter = FALSE;
1568 break;
1569 case RTF_RSLTBMP: // diese sollten wir ignorieren
1570 case RTF_RSLTMERGE:
1571 case RTF_RSLTPICT:
1572 case RTF_RSLTRTF:
1573 case RTF_RSLTTXT:
1574 break;
1576 case RTF_OBJW: aOleType.nWidth = nVal; break;
1577 case RTF_OBJH: aOleType.nHeight = nVal; break;
1578 case RTF_OBJCROPT: aOleType.nCropT = (short)nTokenValue; break;
1579 case RTF_OBJCROPB: aOleType.nCropB = (short)nTokenValue; break;
1580 case RTF_OBJCROPL: aOleType.nCropL = (short)nTokenValue; break;
1581 case RTF_OBJCROPR: aOleType.nCropR = (short)nTokenValue; break;
1582 case RTF_OBJSCALEX: aOleType.nScalX = nVal; break;
1583 case RTF_OBJSCALEY: aOleType.nScalY = nVal; break;
1585 case RTF_TEXTTOKEN:
1586 if( 1 < nOpenBrakets && pStr )
1588 if( pStr == &sObjData )
1590 xub_StrLen nHexLen = HexToBin( aToken );
1591 if( STRING_NOTFOUND != nHexLen )
1592 bValidOle = FALSE;
1593 else
1595 aTmpFile.Write( (sal_Char*)aToken.GetBuffer(), nHexLen );
1596 bValidOle = 0 == aTmpFile.GetError();
1599 else
1600 *pStr += aToken;
1602 break;
1606 if( bValidOle )
1608 bValidOle = FALSE; // erstmal
1611 if( !bWeiter ) // dann stehen wir noch im Result
1613 // ist das Ole-Object Ok?
1614 // -> dann solange SkipGroup rufen, bis zur letzten
1615 // schliessenden Klammer
1616 // ansonsten alle Token verarbeiten, bis zur letzten
1617 // schliessenden Klammer
1619 bWeiter = TRUE;
1620 while( nOpenBrakets && IsParserWorking() && bWeiter )
1622 switch( nToken = GetNextToken() )
1624 case '}': --nOpenBrakets; break;
1625 case '{': ++nOpenBrakets; break;
1627 if( nOpenBrakets && !bValidOle )
1628 NextToken( nToken );
1632 if( !bValidOle && '}' != nToken )
1633 SkipGroup();
1635 SkipToken( -1 ); // die schliesende Klammer wird "oben" ausgewertet
1637 #endif
1639 /* vi:set tabstop=4 shiftwidth=4 expandtab: */