xref: /aoo41x/main/sw/source/filter/rtf/rtffly.cxx (revision efeef26f)
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