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