xref: /aoo41x/main/sw/source/filter/ww8/ww8graf.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
31 #include <svl/urihelper.hxx>
32 #include <hintids.hxx>
33 #include <osl/endian.h>
34 #include <svx/fmglob.hxx>
35 #include <svx/sdtaitm.hxx>
36 #include <editeng/lrspitem.hxx>
37 #include <editeng/udlnitem.hxx>
38 #include <svx/xlineit.hxx>
39 #include <svx/xfillit.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/sdtaitm.hxx>
42 #include <svx/svdocapt.hxx>
43 #include <svx/sxctitm.hxx>
44 #include <editeng/editeng.hxx>
45 #include <svx/svdpage.hxx>
46 #include <svx/svdopath.hxx>
47 #include <svx/svdocirc.hxx>
48 #include <editeng/outlobj.hxx>
49 #include <svx/svdogrp.hxx>
50 #include <svx/svdograf.hxx>
51 #include <svx/svdoole2.hxx>
52 #include <editeng/colritem.hxx>
53 #include <editeng/fhgtitem.hxx>
54 #include <editeng/postitem.hxx>
55 #include <editeng/adjitem.hxx>
56 #include <editeng/wghtitem.hxx>
57 #include <editeng/crsditem.hxx>
58 #include <editeng/cntritem.hxx>
59 #include <editeng/shdditem.hxx>
60 #include <editeng/fontitem.hxx>
61 #include <editeng/ulspitem.hxx>
62 #include <svx/svdoattr.hxx>
63 #include <editeng/brshitem.hxx>
64 #include <svx/rectenum.hxx>
65 #include <editeng/opaqitem.hxx>
66 #include <editeng/shaditem.hxx>
67 #include <editeng/shaditem.hxx>
68 #include <editeng/boxitem.hxx>
69 #include <editeng/outliner.hxx>         // #79453#
70 #include <editeng/frmdiritem.hxx>
71 #include <svx/xfltrit.hxx>
72 #include <filter/msfilter/msdffimp.hxx>
73 #include <grfatr.hxx>           // class SwCropGrf
74 #include <fmtornt.hxx>
75 #include <fmtcntnt.hxx>
76 #include <frmfmt.hxx>
77 #include <fmtanchr.hxx>
78 #include <pam.hxx>
79 #include <doc.hxx>
80 #include <docary.hxx>
81 #include <ndgrf.hxx>
82 #include <ndtxt.hxx>
83 #include <dcontact.hxx>
84 #include <docsh.hxx>
85 #include <mdiexp.hxx>           // Progress
86 #include <fmtcnct.hxx>
87 #include <swunodef.hxx>
88 #include "ww8struc.hxx"
89 #include "ww8scan.hxx"
90 #include "ww8par.hxx"           // class SwWWImplReader
91 #include "ww8par2.hxx"          // SwWW8StyInf
92 #include "ww8graf.hxx"
93 #include <fmtinfmt.hxx>
94 #include <editeng/eeitem.hxx>
95 #include <editeng/flditem.hxx>
96 // OD 30.09.2003 #i18732#
97 #include <fmtfollowtextflow.hxx>
98 #include "writerhelper.hxx"
99 #include "writerwordglue.hxx"
100 #include <basegfx/point/b2dpoint.hxx>
101 #include <basegfx/polygon/b2dpolygon.hxx>
102 #include <editeng/editobj.hxx>
103 
104 #include <math.h>
105 
106 using namespace ::com::sun::star;
107 using namespace sw::types;
108 using namespace sw::util;
109 
110 // Hilfsroutinen
111 
112 Color WW8TransCol(SVBT32 nWC)
113 {
114 #if 1               // 1 = Vordefinierte Farben benutzen, 0 = ignorieren
115 
116     // Farbtabelle zum Umrechnen RGB-Werte in vordefinierte Farben
117     // ( Damit bei der Writer-UI die Farbnamen stimmen )
118     // Die Tabelle int im *3er-System* aufgeteilt. Die Grauwerte fehlen,
119     // da sie nicht ins 3er-System passen ( 4 Werte: sw, ws, 2 * grau )
120     static ColorData eColA[] = {                    //  B G R  B G R  B G R
121         COL_BLACK, COL_RED, COL_LIGHTRED,           //  0 0 0, 0 0 1, 0 0 2
122         COL_GREEN, COL_BROWN, COL_BLACK,            //  0 1 0, 0 1 1, 0 1 2
123         COL_LIGHTGREEN, COL_BLACK, COL_YELLOW,      //  0 2 0, 0 2 1, 0 2 2
124         COL_BLUE, COL_MAGENTA, COL_BLACK,           //  1 0 0, 1 0 1, 1 0 2
125         COL_CYAN, COL_LIGHTGRAY, COL_BLACK,         //  1 1 0, 1 1 1, 1 1 2
126         COL_BLACK, COL_BLACK, COL_BLACK,            //  1 2 0, 1 2 1, 1 2 2
127         COL_LIGHTBLUE, COL_BLACK, COL_LIGHTMAGENTA, //  2 0 0, 2 0 1, 2 0 2
128         COL_BLACK, COL_BLACK, COL_BLACK,            //  2 1 0, 2 1 1, 2 1 2
129         COL_LIGHTCYAN, COL_BLACK, COL_WHITE };      //  2 2 0, 2 2 1, 2 2 2
130 
131     // In nWC[3] steht ein Byte, dass in der WW-Doku nicht beschrieben ist.
132     // Die Bedeutung ist anscheinend folgende: Bei 0 ist es eine normale
133     // Farbe, dessen RGB-Wert in nWC[0..2] steht. stehen in nWC[3] die
134     // Werte 0x1, 0x7d oder 0x83, dann ist es ein Grauwert, dessen
135     // Schwarzanteil in 1/2 % in nWC[0] steht.
136     // Ich vermute, dass es auf Bit0 in nWV[3] ankommt, ob es RGB oder Grau ist.
137 
138     if( !( nWC[3] & 0x1 ) &&                        // keine Spezial-Farbe (grau)
139         (    ( nWC[0] == 0 ||  nWC[0]== 0x80 || nWC[0] == 0xff )    // R-Anteil
140           && ( nWC[1] == 0 ||  nWC[1]== 0x80 || nWC[1] == 0xff )    // G-Anteil
141           && ( nWC[2] == 0 ||  nWC[2]== 0x80 || nWC[2] == 0xff ) ) ){// B-Anteil
142         int nIdx = 0;       // und nun: Idx-Berechnung im 3er-System
143         for (int i = 2; i >= 0; i--)
144         {
145             nIdx *= 3;
146             if (nWC[i])
147                 nIdx += ((nWC[i] == 0xff) ? 2 : 1);
148         }
149         if (eColA[nIdx] != COL_BLACK)
150             return Color(eColA[nIdx]);  // Standard-Color
151     }
152 #endif
153 
154     if (nWC[3] & 0x1)
155     {
156         //Special colour gray
157         sal_uInt8 u = (sal_uInt8)( (sal_uLong)( 200 - nWC[0] ) * 256 / 200 );
158         return Color(u, u, u);
159     }
160 
161     // User-Color
162     return Color(nWC[0], nWC[1], nWC[2]);
163 }
164 
165 void wwFrameNamer::SetUniqueGraphName(SwFrmFmt *pFrmFmt, const String &rFixed)
166 {
167     if (mbIsDisabled || !rFixed.Len())
168         return;
169     String aName(msSeed);
170     aName += String::CreateFromInt32(++mnImportedGraphicsCount);
171     aName.APPEND_CONST_ASC( ": " );
172     aName += rFixed;
173     pFrmFmt->SetName( aName );
174 }
175 
176 // ReadGrafStart liest die ObjektDaten ein und erzeugt falls noetig einen Anker
177 bool SwWW8ImplReader::ReadGrafStart(void* pData, short nDataSiz,
178     WW8_DPHEAD* pHd, const WW8_DO* pDo, SfxAllItemSet &rSet)
179 {
180     if (SVBT16ToShort(pHd->cb) < sizeof(WW8_DPHEAD) + nDataSiz)
181     {
182         ASSERT( !this, "+Grafik-Element: Size ?" );
183         pStrm->SeekRel(SVBT16ToShort(pHd->cb) - sizeof(WW8_DPHEAD));
184         return false;
185     }
186     pStrm->Read(pData, nDataSiz);
187 
188     RndStdIds eAnchor = (SVBT8ToByte(pDo->by) < 2) ? FLY_AT_PAGE : FLY_AT_PARA;
189     rSet.Put(SwFmtAnchor(eAnchor));
190 
191     nDrawXOfs2 = nDrawXOfs;
192     nDrawYOfs2 = nDrawYOfs;
193 
194     if (eAnchor == FLY_AT_PARA)
195     {
196         if( SVBT8ToByte( pDo->bx ) == 1 )       // Pos: echt links
197             nDrawXOfs2 = static_cast< short >(nDrawXOfs2 - maSectionManager.GetPageLeft());
198         if( nInTable )                          // Obj in Table
199             nDrawXOfs2 = nDrawXOfs2 - GetTableLeft();       // -> siehe Kommentar
200                                                 // bei GetTableLeft()
201     }
202     else
203     {
204         if( SVBT8ToByte( pDo->bx ) != 1 )
205             nDrawXOfs2 = static_cast< short >(nDrawXOfs2 + maSectionManager.GetPageLeft());
206     }
207 
208     return true;
209 }
210 
211 // SetStdAttr() setzt die Attribute, die jedes Objekt hat
212 
213 static void SetStdAttr( SfxItemSet& rSet, WW8_DP_LINETYPE& rL,
214                         WW8_DP_SHADOW& rSh )
215 {
216     if( SVBT16ToShort( rL.lnps ) == 5 ){            // unsichtbar
217         rSet.Put( XLineStyleItem( XLINE_NONE ) );
218     }else{                                          // sichtbar
219         Color aCol( WW8TransCol( rL.lnpc ) );           // LinienFarbe
220         rSet.Put( XLineColorItem( aEmptyStr, aCol ) );
221         rSet.Put( XLineWidthItem( SVBT16ToShort( rL.lnpw ) ) );
222                                                     // LinienDicke
223         if( SVBT16ToShort( rL.lnps ) >= 1
224             && SVBT16ToShort(rL.lnps ) <= 4 ){      // LinienStil
225             rSet.Put( XLineStyleItem( XLINE_DASH ) );
226             sal_Int16 nLen = SVBT16ToShort( rL.lnpw );
227             XDash aD( XDASH_RECT, 1, 2 * nLen, 1, 5 * nLen, 5 * nLen );
228             switch( SVBT16ToShort( rL.lnps ) ){
229             case 1: aD.SetDots( 0 );            // Dash
230                     aD.SetDashLen( 6 * nLen );
231                     aD.SetDistance( 4 * nLen );
232                     break;
233             case 2: aD.SetDashes( 0 ); break;   // Dot
234             case 3: break;                      // Dash Dot
235             case 4: aD.SetDots( 2 ); break;     // Dash Dot Dot
236             }
237             rSet.Put( XLineDashItem( aEmptyStr, aD ) );
238         }else{
239             rSet.Put( XLineStyleItem( XLINE_SOLID ) );  // noetig fuer TextBox
240         }
241     }
242     if( SVBT16ToShort( rSh.shdwpi ) ){                  // Schatten
243         rSet.Put(SdrShadowItem(true));
244         rSet.Put( SdrShadowXDistItem( SVBT16ToShort( rSh.xaOffset ) ) );
245         rSet.Put( SdrShadowYDistItem( SVBT16ToShort( rSh.yaOffset ) ) );
246     }
247 }
248 
249 // SetFill setzt Fuellattribute wie Vordergrund- und Hintergrund-Farbe
250 // und Muster durch Reduktion auf eine Farbe.
251 // SetFill() setzt z.Zt kein Muster, da Sdr das nur sehr umstaendlich kann
252 // und die Sdr-Schraffur ( XDash ) noch nicht fertig ist.
253 // Statt dessen wird eine Mischfarbe gewaehlt, die auf den entsprechenden
254 // Farbton zwischen den Farben liegt.
255 
256 static void SetFill( SfxItemSet& rSet, WW8_DP_FILL& rFill )
257 {
258     static sal_uInt8 nPatA[] =
259     {
260              0,  0,  5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80,
261             90, 50, 50, 50, 50, 50, 50, 33, 33, 33, 33, 33, 33
262     };
263     sal_uInt16 nPat = SVBT16ToShort(rFill.flpp);
264 
265     if (nPat == 0) // transparent
266         rSet.Put(XFillStyleItem(XFILL_NONE));
267     else
268     {
269         rSet.Put(XFillStyleItem(XFILL_SOLID));  // necessary for textbox
270         if (nPat <= 1 || nPat > sizeof(nPatA))
271         {
272             // Solid Background or unknown
273             rSet.Put(XFillColorItem(aEmptyStr, WW8TransCol(rFill.dlpcBg)));
274         }
275         else
276         {                                      // Brush -> Farbmischung
277             Color aB( WW8TransCol( rFill.dlpcBg ) );
278             Color aF( WW8TransCol( rFill.dlpcFg ) );
279             aB.SetRed( (sal_uInt8)( ( (sal_uLong)aF.GetRed() * nPatA[nPat]
280                         + (sal_uLong)aB.GetRed() * ( 100 - nPatA[nPat] ) ) / 100 ) );
281             aB.SetGreen( (sal_uInt8)( ( (sal_uLong)aF.GetGreen() * nPatA[nPat]
282                         + (sal_uLong)aB.GetGreen() * ( 100 - nPatA[nPat] ) ) / 100 ) );
283             aB.SetBlue( (sal_uInt8)( ( (sal_uLong)aF.GetBlue() * nPatA[nPat]
284                         + (sal_uLong)aB.GetBlue() * ( 100 - nPatA[nPat] ) ) / 100 ) );
285             rSet.Put( XFillColorItem( aEmptyStr, aB ) );
286         }
287     }
288 }
289 
290 static void SetLineEndAttr( SfxItemSet& rSet, WW8_DP_LINEEND& rLe,
291                             WW8_DP_LINETYPE& rLt )
292 {
293     sal_uInt16 aSB = SVBT16ToShort( rLe.aStartBits );
294     if( aSB & 0x3 )
295 	{
296 		::basegfx::B2DPolygon aPolygon;
297 		aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
298 		aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
299 		aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
300 		aPolygon.setClosed(true);
301         rSet.Put( XLineEndItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) );
302         sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw )
303                         * ( ( aSB >> 2 & 0x3 ) + ( aSB >> 4 & 0x3 ) );
304         if( nSiz < 220 ) nSiz = 220;
305         rSet.Put(XLineEndWidthItem(nSiz));
306         rSet.Put(XLineEndCenterItem(false));
307     }
308 
309     sal_uInt16 aEB = SVBT16ToShort( rLe.aEndBits );
310     if( aEB & 0x3 ){
311 		::basegfx::B2DPolygon aPolygon;
312 		aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
313 		aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
314 		aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
315 		aPolygon.setClosed(true);
316         rSet.Put( XLineStartItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) );
317         sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw )
318                         * ( ( aEB >> 2 & 0x3 ) + ( aEB >> 4 & 0x3 ) );
319         if( nSiz < 220 ) nSiz = 220;
320         rSet.Put(XLineStartWidthItem(nSiz));
321         rSet.Put(XLineStartCenterItem(false));
322     }
323 }
324 
325 // Ab hier folgen die Routinen fuer die einzelnen Objekte
326 SdrObject* SwWW8ImplReader::ReadLine( WW8_DPHEAD* pHd, const WW8_DO* pDo,
327     SfxAllItemSet &rSet)
328 {
329     WW8_DP_LINE aLine;
330 
331     if( !ReadGrafStart( (void*)&aLine, sizeof( aLine ), pHd, pDo, rSet ) )
332         return 0;
333 
334     Point aP[2];
335     {
336         Point& rP0 = aP[0];
337         Point& rP1 = aP[1];
338 
339         rP0.X() = (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2;
340         rP0.Y() = (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2;
341         rP1 = rP0;
342         rP0.X() += (sal_Int16)SVBT16ToShort( aLine.xaStart );
343         rP0.Y() += (sal_Int16)SVBT16ToShort( aLine.yaStart );
344         rP1.X() += (sal_Int16)SVBT16ToShort( aLine.xaEnd );
345         rP1.Y() += (sal_Int16)SVBT16ToShort( aLine.yaEnd );
346     }
347 
348 	::basegfx::B2DPolygon aPolygon;
349 	aPolygon.append(::basegfx::B2DPoint(aP[0].X(), aP[0].Y()));
350 	aPolygon.append(::basegfx::B2DPoint(aP[1].X(), aP[1].Y()));
351 	SdrObject* pObj = new SdrPathObj(OBJ_LINE, ::basegfx::B2DPolyPolygon(aPolygon));
352 
353     SetStdAttr( rSet, aLine.aLnt, aLine.aShd );
354     SetLineEndAttr( rSet, aLine.aEpp, aLine.aLnt );
355 
356     return pObj;
357 }
358 
359 SdrObject* SwWW8ImplReader::ReadRect( WW8_DPHEAD* pHd, const WW8_DO* pDo,
360     SfxAllItemSet &rSet)
361 {
362     WW8_DP_RECT aRect;
363 
364     if( !ReadGrafStart( (void*)&aRect, sizeof( aRect ), pHd, pDo, rSet ) )
365         return 0;
366 
367     Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
368                (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
369     Point aP1( aP0 );
370     aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
371     aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
372 
373     SdrObject* pObj = new SdrRectObj( Rectangle( aP0, aP1 ) );
374 
375     SetStdAttr( rSet, aRect.aLnt, aRect.aShd );
376     SetFill( rSet, aRect.aFill );
377 
378     return pObj;
379 }
380 
381 SdrObject* SwWW8ImplReader::ReadElipse( WW8_DPHEAD* pHd, const WW8_DO* pDo,
382     SfxAllItemSet &rSet)
383 {
384     WW8_DP_ELIPSE aElipse;
385 
386     if( !ReadGrafStart( (void*)&aElipse, sizeof( aElipse ), pHd, pDo, rSet ) )
387         return 0;
388 
389     Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
390                (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
391     Point aP1( aP0 );
392     aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
393     aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
394 
395     SdrObject* pObj = new SdrCircObj( OBJ_CIRC, Rectangle( aP0, aP1 ) );
396 
397     SetStdAttr( rSet, aElipse.aLnt, aElipse.aShd );
398     SetFill( rSet, aElipse.aFill );
399 
400     return pObj;
401 }
402 
403 SdrObject* SwWW8ImplReader::ReadArc( WW8_DPHEAD* pHd, const WW8_DO* pDo,
404     SfxAllItemSet &rSet)
405 {
406     WW8_DP_ARC aArc;
407 
408     if( !ReadGrafStart( (void*)&aArc, sizeof( aArc ), pHd, pDo, rSet ) )
409         return 0;
410 
411     Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
412                (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
413     Point aP1( aP0 );
414     aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa ) * 2;
415     aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya ) * 2;
416 
417     short nA[] = { 2, 3, 1, 0 };
418     short nW = nA[ ( ( SVBT8ToByte( aArc.fLeft ) & 1 ) << 1 )
419                     + ( SVBT8ToByte( aArc.fUp ) & 1 ) ];
420     if( !SVBT8ToByte( aArc.fLeft ) ){
421         aP0.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya );
422         aP1.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya );
423     }
424     if( SVBT8ToByte( aArc.fUp ) ){
425         aP0.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa );
426         aP1.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa );
427     }
428 
429     SdrObject* pObj = new SdrCircObj( OBJ_SECT, Rectangle( aP0, aP1 ),
430                                nW * 9000, ( ( nW + 1 ) & 3 ) * 9000 );
431 
432     SetStdAttr( rSet, aArc.aLnt, aArc.aShd );
433     SetFill( rSet, aArc.aFill );
434 
435     return pObj;
436 }
437 
438 SdrObject* SwWW8ImplReader::ReadPolyLine( WW8_DPHEAD* pHd, const WW8_DO* pDo,
439     SfxAllItemSet &rSet)
440 {
441     WW8_DP_POLYLINE aPoly;
442 
443     if( !ReadGrafStart( (void*)&aPoly, sizeof( aPoly ), pHd, pDo, rSet ) )
444         return 0;
445 
446     sal_uInt16 nCount = SVBT16ToShort( aPoly.aBits1 ) >> 1 & 0x7fff;
447     SVBT16 *pP = new SVBT16[nCount * 2];
448     pStrm->Read( pP, nCount * 4 );      // Punkte einlesen
449     Polygon aP( nCount );
450     Point aPt;
451     sal_uInt16 i;
452 
453     for( i=0; i<nCount; i++ ){
454         aPt.X() = SVBT16ToShort( pP[i << 1] ) + nDrawXOfs2
455                   + (sal_Int16)SVBT16ToShort( pHd->xa );
456         aPt.Y() = SVBT16ToShort( pP[( i << 1 ) + 1] ) + nDrawYOfs2
457                   + (sal_Int16)SVBT16ToShort( pHd->ya );
458         aP[i] = aPt;
459     }
460     delete[] pP;
461 
462 	SdrObject* pObj = new SdrPathObj(( SVBT16ToShort( aPoly.aBits1 ) & 0x1 ) ? OBJ_POLY : OBJ_PLIN, ::basegfx::B2DPolyPolygon(aP.getB2DPolygon()));
463     SetStdAttr( rSet, aPoly.aLnt, aPoly.aShd );
464     SetFill( rSet, aPoly.aFill );
465 
466     return pObj;
467 }
468 
469 ESelection SwWW8ImplReader::GetESelection( long nCpStart, long nCpEnd )
470 {
471     sal_uInt16 nPCnt = mpDrawEditEngine->GetParagraphCount();
472     sal_uInt16 nSP = 0;
473     sal_uInt16 nEP = 0;
474     while(      (nSP < nPCnt)
475             &&  (nCpStart >= mpDrawEditEngine->GetTextLen( nSP ) + 1) )
476     {
477         nCpStart -= mpDrawEditEngine->GetTextLen( nSP ) + 1;
478         nSP++;
479     }
480         // Beim Ende erst 1 Zeichen spaeter auf naechste Zeile umschalten,
481         // da sonst Zeilenattribute immer eine Zeile zu weit reichen.
482     while(      (nEP < nPCnt)
483             &&  (nCpEnd > mpDrawEditEngine->GetTextLen( nEP ) + 1) )
484     {
485         nCpEnd -= mpDrawEditEngine->GetTextLen( nEP ) + 1;
486         nEP++;
487     }
488     return ESelection( nSP, (sal_uInt16)nCpStart, nEP, (sal_uInt16)nCpEnd );
489 }
490 
491 // InsertTxbxStyAttrs() setzt die Style-Attribute in den uebergebenen ItemSet.
492 // Es werden die SW-Styles genommen, die Import-WW-Styles sind zu diesem
493 // Zeitpunkt schon destruiert.
494 // Die SW-Styles werden per Tiefensuche, d.h. mit Parent-Styles nach den
495 // in aSrcTab angegebenen Attributen untersucht. Diese werden per Clone
496 // dupliziert, bei den Duplikaten werden die Which-IDs
497 // gemaess der Tabelle aDstTab umgesetzt, damit die EditEngine sie nicht
498 // ignoriert.
499 // Es werden hierbei sowohl Para- wie auch Zeichen-Attribute in den
500 // ItemSet gestopft.
501 void SwWW8ImplReader::InsertTxbxStyAttrs( SfxItemSet& rS, sal_uInt16 nColl )
502 {
503     SwWW8StyInf * pStyInf = GetStyle(nColl);
504     if( pStyInf != NULL && pStyInf->pFmt && pStyInf->bColl )
505     {
506         const SfxPoolItem* pItem;
507         for( sal_uInt16 i = POOLATTR_BEGIN; i < POOLATTR_END; i++ )
508         {
509             //If we are set in the source and not set in the destination
510             //then add it in.
511             if ( SFX_ITEM_SET == pStyInf->pFmt->GetItemState(
512                 i, true, &pItem ) )
513             {
514                 SfxItemPool *pEditPool = rS.GetPool();
515                 sal_uInt16 nWhich = i;
516                 sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich);
517                 if (
518                     nSlotId && nWhich != nSlotId &&
519                     0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
520                     nWhich != nSlotId &&
521                     ( SFX_ITEM_SET != rS.GetItemState(nWhich, false) )
522                    )
523                 {
524                     SfxPoolItem* pCopy = pItem->Clone();
525                     pCopy->SetWhich( nWhich );
526                     rS.Put( *pCopy );
527                     delete pCopy;
528                 }
529             }
530         }
531     }
532 
533 }
534 
535 static void lcl_StripFields(String &rString, long &rNewStartCp)
536 {
537     for(sal_uInt16 i=0; i < rString.Len(); i++)
538     {
539         if( 0x13 == rString.GetChar( i ) )
540         {
541             do
542             {
543                 rString.Erase( i, 1 );
544                 rNewStartCp++;
545             }
546             while(              rString.Len()
547                     && (   i  < rString.Len())
548                     && (0x14 != rString.GetChar( i ) )
549                     && (0x15 != rString.GetChar( i ) ) );
550             if( rString.Len() )
551             {
552                 if( 0x14 == rString.GetChar( i ) )
553                 {
554                     rString.Erase( i, 1 );
555                     rNewStartCp++;
556                     do
557                     {
558                         i++;
559                     }
560                     while(              rString.Len()
561                             && (   i  < rString.Len())
562                             && (0x15 != rString.GetChar( i ) ) );
563                     if( i < rString.Len() )
564                         rString.Erase( i, 1 );
565                 }
566                 else if( 0x15 == rString.GetChar( i ) )
567                     rString.Erase( i, 1 );
568             }
569         }
570     }
571 }
572 
573 class Chunk
574 {
575 private:
576     String msURL;
577     long mnStartPos; //0x13
578     long mnEndPos;   //0x15
579 public:
580     explicit Chunk(long nStart, const String &rURL)
581         : msURL(rURL), mnStartPos(nStart) {}
582     Chunk(const Chunk &rChunk)
583         : msURL(rChunk.msURL), mnStartPos(rChunk.mnStartPos),
584         mnEndPos(rChunk.mnEndPos) {}
585     Chunk& operator=(const Chunk &rChunk)
586     {
587         msURL = rChunk.msURL;
588         mnStartPos = rChunk.mnStartPos;
589         mnEndPos = rChunk.mnEndPos;
590         return *this;
591     }
592     void SetEndPos(long nEnd) { mnEndPos = nEnd; }
593     long GetStartPos() const {return mnStartPos;}
594     long GetEndPos() const {return mnEndPos;}
595     const String &GetURL() const {return msURL;}
596     void Adjust(xub_StrLen nAdjust)
597     {
598         mnStartPos-=nAdjust;
599         mnEndPos-=nAdjust;
600     }
601 };
602 
603 // InsertAttrsAsDrawingAttrs() setzt zwischen StartCp und EndCp die Attribute.
604 // Dabei werden Style-Attribute als harte Attribute, Absatz- und Zeichen-
605 // attribute gesetzt.
606 void SwWW8ImplReader::InsertAttrsAsDrawingAttrs(long nStartCp, long nEndCp,
607     ManTypes eType, bool bONLYnPicLocFc)
608 {
609     /*
610      Save and create new plcxman for this drawing object, of the type that
611      will include the para end mark inside a paragraph property range, as
612      drawing boxes have real paragraph marks as part of their text, while
613      normal writer has seperate nodes for each paragraph and so has no actual
614      paragraph mark as part of the paragraph text.
615     */
616     WW8ReaderSave aSave(this);
617     pPlcxMan = new WW8PLCFMan(pSBase, eType, nStartCp, true);
618 
619     WW8_CP nStart = pPlcxMan->Where();
620     WW8_CP nNext, nEnd, nStartReplace=0;
621 
622     bool bDoingSymbol = false;
623     sal_Unicode cReplaceSymbol = cSymbol;
624 
625     SfxItemSet *pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet());
626     WW8PLCFManResult aRes;
627 
628     std::deque<Chunk> aChunks;
629 
630     //Here store stack location
631     sal_uInt16 nCurrentCount = static_cast< sal_uInt16 >(pCtrlStck->Count());
632     while (nStart < nEndCp)
633     {
634         //nStart is the beginning of the attributes for this range, and
635         //may be before the text itself. So watch out for that
636         WW8_CP nTxtStart = nStart;
637         if (nTxtStart < nStartCp)
638             nTxtStart = nStartCp;
639         // get position of next SPRM
640         bool bStartAttr = pPlcxMan->Get(&aRes);
641         nAktColl = pPlcxMan->GetColl();
642         if (aRes.nSprmId)
643         {
644             if( bONLYnPicLocFc )
645             {
646                 if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) )
647                 {
648                     Read_PicLoc(aRes.nSprmId, aRes.pMemPos +
649                         mpSprmParser->DistanceToData(aRes.nSprmId), 4);
650                      // Ok, that's what we were looking for.  Now let's get
651                      // out of here!
652                     break;
653                 }
654             }
655             else if ( aRes.nSprmId && (
656                 (eFTN >  aRes.nSprmId) || (0x0800 <= aRes.nSprmId) ) )
657             {
658                 //Here place them onto our usual stack and we will pop them
659                 //off and convert them later
660                 if (bStartAttr)
661                 {
662                     ImportSprm(aRes.pMemPos, aRes.nSprmId);
663                     if (!bDoingSymbol && bSymbol == true)
664                     {
665                         bDoingSymbol = true;
666                         nStartReplace = nTxtStart;
667                         cReplaceSymbol = cSymbol;
668                     }
669                 }
670                 else
671                 {
672                     EndSprm( aRes.nSprmId );
673                     if (bSymbol == false && bDoingSymbol)
674                     {
675                         bDoingSymbol = false;
676                         String sTemp;
677                         sTemp.Fill(writer_cast<xub_StrLen>(
678                             nTxtStart - nStartReplace), cReplaceSymbol);
679                         mpDrawEditEngine->QuickInsertText(sTemp,
680                             GetESelection(nStartReplace - nStartCp,
681                             nTxtStart - nStartCp ) );
682                     }
683                 }
684             }
685             else if (aRes.nSprmId == eFLD)
686             {
687                 if (bStartAttr)
688                 {
689                     sal_uInt16 nCount = static_cast< sal_uInt16 >(pCtrlStck->Count());
690                     if (maFieldStack.empty() && Read_Field(&aRes))
691                     {
692                         String sURL;
693                         for (sal_uInt16 nI = static_cast< sal_uInt16 >(pCtrlStck->Count()); nI > nCount; --nI)
694                         {
695                             const SfxPoolItem *pItem = ((*pCtrlStck)[nI-1])->pAttr;
696                             sal_uInt16 nWhich = pItem->Which();
697                             if (nWhich == RES_TXTATR_INETFMT)
698                             {
699                                 const SwFmtINetFmt *pURL =
700                                     (const SwFmtINetFmt *)pItem;
701                                 sURL = pURL->GetValue();
702                             }
703                             pCtrlStck->DeleteAndDestroy(nI-1);
704                         }
705                         aChunks.push_back(Chunk(nStart, sURL));
706                     }
707                 }
708                 else
709                 {
710                     if (!maFieldStack.empty() && End_Field())
711                         aChunks.back().SetEndPos(nStart+1);
712                 }
713             }
714         }
715 
716         (*pPlcxMan)++;
717         nNext = pPlcxMan->Where();
718 
719         if( (nNext != nStart) && !bONLYnPicLocFc )
720         {
721             nEnd = ( nNext < nEndCp ) ? nNext : nEndCp;
722             SfxItemPool *pEditPool = pS->GetPool();
723 
724             //Here read current properties and convert them into pS
725             //and put those attrs into the draw box if they can be converted
726             //to draw attributes
727             if (pCtrlStck->Count() - nCurrentCount)
728             {
729                 for (sal_uInt16 i = nCurrentCount; i < pCtrlStck->Count(); i++)
730                 {
731                     const SfxPoolItem *pItem = ((*pCtrlStck)[i])->pAttr;
732                     sal_uInt16 nWhich = pItem->Which();
733                     if( nWhich < RES_FLTRATTR_BEGIN ||
734                         nWhich >= RES_FLTRATTR_END )
735                     {
736                         sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich);
737                         if (
738                             nSlotId && nWhich != nSlotId &&
739                             0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
740                             nWhich != nSlotId
741                         )
742                         {
743                             SfxPoolItem* pCopy = pItem->Clone();
744                             pCopy->SetWhich( nWhich );
745                             pS->Put( *pCopy );
746                             delete pCopy;
747                         }
748                     }
749                 }
750             }
751             //Fill in the remainder from the style
752             InsertTxbxStyAttrs(*pS, nAktColl);
753 
754             if( pS->Count() )
755             {
756                 mpDrawEditEngine->QuickSetAttribs( *pS,
757                     GetESelection( nTxtStart - nStartCp, nEnd - nStartCp ) );
758                 delete pS;
759                 pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet());
760             }
761         }
762         nStart = nNext;
763     }
764     delete pS;
765 
766     //pop off as far as recorded location just in case there were some left
767     //unclosed
768     for (sal_uInt16 nI = static_cast< sal_uInt16 >(pCtrlStck->Count()); nI > nCurrentCount; --nI)
769         pCtrlStck->DeleteAndDestroy(nI-1);
770 
771     typedef std::deque<Chunk>::iterator myIter;
772     myIter aEnd = aChunks.end();
773     for (myIter aIter = aChunks.begin(); aIter != aEnd; ++aIter)
774     {
775         ESelection aSel(GetESelection(aIter->GetStartPos()-nStartCp,
776             aIter->GetEndPos()-nStartCp));
777         String aString(mpDrawEditEngine->GetText(aSel));
778         xub_StrLen nOrigLen = aString.Len();
779         long nDummy(0);
780         lcl_StripFields(aString, nDummy);
781 
782         xub_StrLen nChanged;
783         if (aIter->GetURL().Len())
784         {
785             SvxURLField aURL(aIter->GetURL(), aString,
786                 SVXURLFORMAT_APPDEFAULT);
787             mpDrawEditEngine->QuickInsertField(SvxFieldItem(aURL, EE_FEATURE_FIELD), aSel);
788             nChanged = nOrigLen - 1;
789         }
790         else
791         {
792             mpDrawEditEngine->QuickInsertText(aString, aSel);
793             nChanged = nOrigLen - aString.Len();
794         }
795         for (myIter aIter2 = aIter+1; aIter2 != aEnd; ++aIter2)
796             aIter2->Adjust(nChanged);
797         }
798 
799     /*
800      Don't worry about the new pPlcxMan, the restorer removes it when
801      replacing the current one with the old one.
802     */
803     aSave.Restore(this);
804 }
805 
806 bool SwWW8ImplReader::GetTxbxTextSttEndCp(WW8_CP& rStartCp, WW8_CP& rEndCp,
807     sal_uInt16 nTxBxS, sal_uInt16 nSequence)
808 {
809     // rasch den TextBox-PLCF greifen
810     WW8PLCFspecial* pT = pPlcxMan ? pPlcxMan->GetTxbx() : 0;
811     if( !pT )
812     {
813         ASSERT( !this, "+Wo ist der Grafik-Text (1) ?" );
814         return false;
815     }
816 
817     // ggfs. zuerst die richtige TextBox-Story finden
818     bool bCheckTextBoxStory = ( nTxBxS && pT->GetIMax() >= nTxBxS );
819     if(  bCheckTextBoxStory )
820         pT->SetIdx( nTxBxS-1 );
821 
822     // dann Start und Ende ermitteln
823     void* pT0;
824     if( !pT->Get( rStartCp, pT0 ) )
825     {
826         ASSERT( !this, "+Wo ist der Grafik-Text (2) ?" );
827         return false;
828     }
829 
830     if( bCheckTextBoxStory )
831     {
832         bool bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable ));
833         while( bReusable )
834         {
835             (*pT)++;
836             if( !pT->Get( rStartCp, pT0 ) )
837             {
838                 ASSERT( !this, "+Wo ist der Grafik-Text (2-a) ?" );
839                 return false;
840             }
841             bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable ));
842         }
843     }
844     (*pT)++;
845     if( !pT->Get( rEndCp, pT0 ) )
846     {
847         ASSERT( !this, "+Wo ist der Grafik-Text (3) ?" );
848         return false;
849     }
850 
851     // jetzt ggfs. die passende Page in der Break-Table finden
852     if( bCheckTextBoxStory )
853     {
854         // Sonderfall: gesamte(!) Kette soll ermittelt werden,
855         //             dann sind wir hier schon fertig!
856         if( USHRT_MAX > nSequence )
857         {
858             long nMinStartCp = rStartCp;
859             long nMaxEndCp   = rEndCp;
860             // rasch den TextBox-Break-Deskriptor-PLCF greifen
861             pT = pPlcxMan->GetTxbxBkd();
862             if (!pT) //It can occur on occasion, Caolan
863                 return false;
864 
865             // den ersten Eintrag fuer diese TextBox-Story finden
866             if( !pT->SeekPos( rStartCp ) )
867             {
868                 ASSERT( !this, "+Wo ist der Grafik-Text (4) ?" );
869                 return false;
870             }
871             // ggfs. entsprechende Anzahl Eintraege weitergehen
872             for(sal_uInt16 iSequence = 0; iSequence < nSequence; iSequence++) (*pT)++;
873             // dann die tatsaechlichen Start und Ende ermitteln
874             if(    (!pT->Get( rStartCp, pT0 ))
875                 || ( nMinStartCp > rStartCp  ) )
876             {
877                 ASSERT( !this, "+Wo ist der Grafik-Text (5) ?" );
878                 return false;
879             }
880             if( rStartCp >= nMaxEndCp )
881                 rEndCp = rStartCp;  // kein Error: leerer String!
882             else
883             {
884                 (*pT)++;
885                 if(    (!pT->Get( rEndCp, pT0 ))
886                     || ( nMaxEndCp < rEndCp-1  ) )
887                 {
888                     ASSERT( !this, "+Wo ist der Grafik-Text (6) ?" );
889                     return false;
890                 }
891                 rEndCp -= 1;
892             }
893         }
894         else
895             rEndCp -= 1;
896     }
897     else
898         rEndCp -= 1;
899     return true;
900 }
901 
902 // TxbxText() holt aus WW-File den Text und gibt diesen und den Anfangs- und
903 // den um -2 (bzw. -1 bei Ver8) korrigierten End-Cp zurueck
904 bool SwWW8ImplReader::GetRangeAsDrawingString(String& rString, long nStartCp, long nEndCp, ManTypes eType)
905 {
906     WW8_CP nOffset = pWwFib->GetBaseCp(eType);
907 
908     bool bOk = false;
909     ASSERT(nStartCp <= nEndCp, "+Wo ist der Grafik-Text (7) ?");
910     if (nStartCp == nEndCp)
911         rString.Erase();      // leerer String: durchaus denkbar!
912     else if (nStartCp < nEndCp)
913     {
914         // den Text einlesen: kann sich ueber mehrere Pieces erstrecken!!!
915         sal_uInt16 nLen = pSBase->WW8ReadString(*pStrm, rString,
916             nStartCp + nOffset, nEndCp - nStartCp, GetCurrentCharSet());
917         ASSERT(nLen, "+Wo ist der Grafik-Text (8) ?");
918         if (nLen)
919         {
920             bOk = true;
921             if( 0x0d == rString.GetChar(nLen - 1) )
922                 rString.Erase(nLen - 1);
923 
924             rString.SearchAndReplaceAll( 0xb, 0xa );
925         }
926     }
927     return bOk;
928 }
929 
930 OutlinerParaObject* SwWW8ImplReader::ImportAsOutliner(String &rString, WW8_CP nStartCp, WW8_CP nEndCp, ManTypes eType)
931 {
932     OutlinerParaObject* pRet = 0;
933 
934     if (GetRangeAsDrawingString( rString, nStartCp, nEndCp, eType ))
935     {
936         if (!mpDrawEditEngine)
937             mpDrawEditEngine = new EditEngine(0);
938 
939         mpDrawEditEngine->SetText(rString);
940         InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
941 
942         //Annotations typically begin with a (useless) 0x5
943 	if ((eType == MAN_AND) && mpDrawEditEngine->GetTextLen())
944 	{
945 	    ESelection aFirstChar(0, 0, 0, 1);
946             if (mpDrawEditEngine->GetText( aFirstChar ) == String(sal_Unicode(0x5)))
947 	        mpDrawEditEngine->QuickDelete(aFirstChar);
948         }
949 
950         EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject();
951         pRet = new OutlinerParaObject(*pTemporaryText);
952         pRet->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT );
953         delete pTemporaryText;
954 
955         mpDrawEditEngine->SetText( aEmptyStr );
956         mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet());
957 
958         //Strip out fields, leaving the result
959         long nDummy(0);
960         lcl_StripFields(rString, nDummy);
961         //Strip out word's special characters for the simple string
962         rString.EraseAllChars(0x1);
963         rString.EraseAllChars(0x5);
964         rString.EraseAllChars(0x8);
965         rString.SearchAndReplaceAllAscii("\007\007", String::CreateFromAscii("\007\012"));
966         rString.SearchAndReplaceAll(0x7, ' ');
967 
968     }
969 
970     return pRet;
971 }
972 
973 // InsertTxbxText() fuegt fuer TextBoxen und CaptionBoxen den Text
974 // und die Attribute ein
975 SwFrmFmt* SwWW8ImplReader::InsertTxbxText(SdrTextObj* pTextObj,
976     Size* pObjSiz, sal_uInt16 nTxBxS, sal_uInt16 nSequence, long nPosCp,
977     SwFrmFmt* pOldFlyFmt, bool bMakeSdrGrafObj, bool& rbEraseTextObj,
978     bool* pbTestTxbxContainsText, long* pnStartCp, long* pnEndCp,
979     bool* pbContainsGraphics, SvxMSDffImportRec* pRecord)
980 {
981     SwFrmFmt* pFlyFmt = 0;
982     sal_uLong nOld = pStrm->Tell();
983 
984     ManTypes eType = pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX;
985 
986     rbEraseTextObj = false;
987 
988     String aString;
989     WW8_CP nStartCp, nEndCp;
990     bool bContainsGraphics = false;
991     bool bTextWasRead = GetTxbxTextSttEndCp( nStartCp, nEndCp, nTxBxS,
992         nSequence ) && GetRangeAsDrawingString( aString, nStartCp, nEndCp, eType );
993 
994     if (!mpDrawEditEngine)
995         mpDrawEditEngine = new EditEngine(0);
996     if( pObjSiz )
997         mpDrawEditEngine->SetPaperSize( *pObjSiz );
998 
999     String aOrigString(aString);
1000     if( bTextWasRead )
1001     {
1002         long nNewStartCp = nStartCp;
1003         lcl_StripFields(aString, nNewStartCp);
1004 
1005         if (1 != aString.Len())
1006         {
1007             if ( (STRING_NOTFOUND != aString.Search(0x1)) ||
1008                 (STRING_NOTFOUND != aString.Search(0x8)) )
1009             {
1010                 bContainsGraphics = true;
1011             }
1012         }
1013         else        // May be a single graphic or object
1014         {
1015             bool bDone = true;
1016             switch( aString.GetChar(0) )
1017             {
1018                 case 0x1:
1019                     if (!pbTestTxbxContainsText)
1020                     {
1021                         WW8ReaderSave aSave(this, nNewStartCp -1);
1022                         bool bOldEmbeddObj = bEmbeddObj;
1023                         //bEmbedd Ordinarily would have been set by field
1024                         //parse, but this is impossible here so...
1025                         bEmbeddObj = true;
1026 
1027                         // 1st look for OLE- or Graph-Indicator Sprms
1028                         WW8PLCFx_Cp_FKP* pChp = pPlcxMan->GetChpPLCF();
1029                         WW8PLCFxDesc aDesc;
1030                         pChp->GetSprms( &aDesc );
1031                         WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen,
1032                             *mpSprmParser);
1033 
1034                         const sal_uInt8* pParams = aSprmIter.GetAktParams();
1035                         for( int nLoop = 0; nLoop < 2; ++nLoop )
1036                         {
1037                             while( aSprmIter.GetSprms()
1038                                 && (0 != (pParams = aSprmIter.GetAktParams())) )
1039                             {
1040                                 sal_uInt16 nAktId = aSprmIter.GetAktId();
1041                                 switch( nAktId )
1042                                 {
1043                                     case     75:
1044                                     case    118:
1045                                     case 0x080A:
1046                                     case 0x0856:
1047                                             Read_Obj(nAktId, pParams, 1);
1048                                         break;
1049                                     case     68:  // Read_Pic()
1050                                     case 0x6A03:
1051                                     case 0x680E:
1052                                             Read_PicLoc(nAktId, pParams, 1);
1053                                         break;
1054                                 }
1055                                 aSprmIter++;
1056                             }
1057 
1058                             //if( bRead_Obj || bRead_PicLoc ) break;
1059                             if( !nLoop )
1060                             {
1061                                 pChp->GetPCDSprms(  aDesc );
1062                                 aSprmIter.SetSprms( aDesc.pMemPos,
1063                                     aDesc.nSprmsLen );
1064                             }
1065                             //if( bRead_Obj || bRead_PicLoc ) break;
1066                         }
1067                         aSave.Restore(this);
1068                         bEmbeddObj=bOldEmbeddObj;
1069 
1070                         // then import either an OLE of a Graphic
1071                         if( bObj )
1072                         {
1073                             if( bMakeSdrGrafObj && pTextObj &&
1074                                 pTextObj->GetUpGroup() )
1075                             {
1076                                 // SdrOleObj/SdrGrafObj anstatt des
1077                                 // SdrTextObj in dessen Gruppe einsetzen
1078 
1079                                 Graphic aGraph;
1080                                 SdrObject* pNew = ImportOleBase(aGraph);
1081 
1082                                 if( !pNew )
1083                                 {
1084                                     pNew = new SdrGrafObj;
1085                                     ((SdrGrafObj*)pNew)->SetGraphic(aGraph);
1086                                 }
1087 
1088                                 GrafikCtor();
1089 
1090                                 pNew->SetModel( pDrawModel );
1091                                 pNew->SetLogicRect( pTextObj->GetCurrentBoundRect() );
1092                                 pNew->SetLayer( pTextObj->GetLayer() );
1093 
1094                                 pTextObj->GetUpGroup()->GetSubList()->
1095                                     ReplaceObject(pNew, pTextObj->GetOrdNum());
1096                             }
1097                             else
1098                                 pFlyFmt = ImportOle();
1099                             bObj = false;
1100                         }
1101                         else
1102                         {
1103                             InsertAttrsAsDrawingAttrs(nNewStartCp, nNewStartCp+1,
1104                                 eType, true);
1105                             pFlyFmt = ImportGraf(bMakeSdrGrafObj ? pTextObj : 0,
1106                                 pOldFlyFmt);
1107                         }
1108                     }
1109                     break;
1110                 case 0x8:
1111                     if ( (!pbTestTxbxContainsText) && (!bObj) )
1112                         pFlyFmt = Read_GrafLayer( nPosCp );
1113                     break;
1114                 default:
1115                     bDone = false;
1116                     break;
1117             }
1118 
1119             if( bDone )
1120             {
1121                 if( pFlyFmt )
1122                 {
1123                     if( pRecord )
1124                     {
1125                         SfxItemSet aFlySet( rDoc.GetAttrPool(),
1126                             RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
1127 
1128                         Rectangle aInnerDist(   pRecord->nDxTextLeft,
1129                                                 pRecord->nDyTextTop,
1130                                                 pRecord->nDxTextRight,
1131                                                 pRecord->nDyTextBottom  );
1132                         MatchSdrItemsIntoFlySet( pTextObj,
1133                                                  aFlySet,
1134                                                  pRecord->eLineStyle,
1135                                                  pRecord->eShapeType,
1136                                                  aInnerDist );
1137 
1138                         pFlyFmt->SetFmtAttr( aFlySet );
1139 
1140                         MapWrapIntoFlyFmt(pRecord, pFlyFmt);
1141                     }
1142                 }
1143                 aString.Erase();
1144                 rbEraseTextObj = (0 != pFlyFmt);
1145             }
1146         }
1147     }
1148 
1149     if( pnStartCp )
1150         *pnStartCp = nStartCp;
1151     if( pnEndCp )
1152         *pnEndCp = nEndCp;
1153 
1154     if( pbTestTxbxContainsText )
1155         *pbTestTxbxContainsText = bTextWasRead && ! rbEraseTextObj;
1156     else if( !rbEraseTextObj )
1157     {
1158         if( bTextWasRead )
1159         {
1160             mpDrawEditEngine->SetText(aOrigString);
1161             InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
1162         }
1163 
1164         bool bVertical = pTextObj->IsVerticalWriting() ? true : false;
1165         EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject();
1166         OutlinerParaObject* pOp = new OutlinerParaObject(*pTemporaryText);
1167         pOp->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT );
1168         pOp->SetVertical( bVertical );
1169         delete pTemporaryText;
1170         pTextObj->NbcSetOutlinerParaObject( pOp );
1171         pTextObj->SetVerticalWriting(bVertical);
1172 
1173         // Fuer die naechste Textbox noch die alten Absatz-Attribute
1174         // und Styles entfernen, sonst startet die naechste Box
1175         // mit falschen Attributen.
1176         // Vorgehen: Text loeschen = auf 1 Absatz reduzieren
1177         // und an diesem Absatz die Absatzattribute und Styles loeschen
1178         // (Empfehlung JOE)
1179         mpDrawEditEngine->SetText( aEmptyStr );
1180         mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet());
1181     }
1182 
1183     pStrm->Seek( nOld );
1184     if (pbContainsGraphics)
1185         *pbContainsGraphics = bContainsGraphics;
1186     return pFlyFmt;
1187 }
1188 
1189 
1190 bool SwWW8ImplReader::TxbxChainContainsRealText(sal_uInt16 nTxBxS, long& rStartCp,
1191     long&  rEndCp)
1192 {
1193     bool bErase, bContainsText;
1194     InsertTxbxText( 0,0,nTxBxS,USHRT_MAX,0,0,0, bErase, &bContainsText,
1195         &rStartCp, &rEndCp );
1196     return bContainsText;
1197 }
1198 
1199 
1200 // TextBoxes only for Ver67 !!
1201 SdrObject* SwWW8ImplReader::ReadTxtBox( WW8_DPHEAD* pHd, const WW8_DO* pDo,
1202     SfxAllItemSet &rSet)
1203 {
1204     bool bDummy;
1205     WW8_DP_TXTBOX aTxtB;
1206 
1207     if( !ReadGrafStart( (void*)&aTxtB, sizeof( aTxtB ), pHd, pDo, rSet ) )
1208         return 0;
1209 
1210     Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
1211                (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
1212     Point aP1( aP0 );
1213     aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
1214     aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
1215 
1216     SdrObject* pObj = new SdrRectObj( OBJ_TEXT, Rectangle( aP0, aP1 ) );
1217     pObj->SetModel( pDrawModel );
1218     pObj->NbcSetSnapRect(Rectangle(aP0, aP1));
1219     Size aSize( (sal_Int16)SVBT16ToShort( pHd->dxa ) ,
1220         (sal_Int16)SVBT16ToShort( pHd->dya ) );
1221 
1222     long nStartCpFly,nEndCpFly;
1223     bool bContainsGraphics;
1224     InsertTxbxText(PTR_CAST(SdrTextObj,pObj), &aSize, 0, 0, 0, 0, false,
1225         bDummy,0,&nStartCpFly,&nEndCpFly,&bContainsGraphics);
1226 
1227     SetStdAttr( rSet, aTxtB.aLnt, aTxtB.aShd );
1228     SetFill( rSet, aTxtB.aFill );
1229 
1230     rSet.Put( SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ) );
1231     rSet.Put( SdrTextAutoGrowWidthItem(false));
1232     rSet.Put( SdrTextAutoGrowHeightItem(false));
1233     rSet.Put( SdrTextLeftDistItem(  MIN_BORDER_DIST*2 ) );
1234     rSet.Put( SdrTextRightDistItem( MIN_BORDER_DIST*2 ) );
1235     rSet.Put( SdrTextUpperDistItem( MIN_BORDER_DIST ) );
1236     rSet.Put( SdrTextLowerDistItem( MIN_BORDER_DIST ) );
1237 
1238     return pObj;
1239 }
1240 
1241 SdrObject* SwWW8ImplReader::ReadCaptionBox( WW8_DPHEAD* pHd, const WW8_DO* pDo,
1242     SfxAllItemSet &rSet)
1243 {
1244     static SdrCaptionType aCaptA[] = { SDRCAPT_TYPE1, SDRCAPT_TYPE2,
1245                                        SDRCAPT_TYPE3, SDRCAPT_TYPE4 };
1246 
1247     WW8_DP_CALLOUT_TXTBOX aCallB;
1248 
1249     if( !ReadGrafStart( (void*)&aCallB, sizeof( aCallB ), pHd, pDo, rSet ) )
1250         return 0;
1251 
1252     sal_uInt16 nCount = SVBT16ToShort( aCallB.dpPolyLine.aBits1 ) >> 1 & 0x7fff;
1253     SVBT16 *pP = new SVBT16[nCount * 2];
1254     pStrm->Read( pP, nCount * 4 );      // Punkte einlesen
1255     sal_uInt8 nTyp = (sal_uInt8)nCount - 1;
1256     if( nTyp == 1 && SVBT16ToShort( pP[0] ) == SVBT16ToShort( pP[2] ) )
1257         nTyp = 0;
1258 
1259     Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) +
1260                (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.xa ) + nDrawXOfs2,
1261                (sal_Int16)SVBT16ToShort( pHd->ya )
1262                + (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.ya ) + nDrawYOfs2 );
1263     Point aP1( aP0 );
1264     aP1.X() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa );
1265     aP1.Y() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya );
1266     Point aP2( (sal_Int16)SVBT16ToShort( pHd->xa )
1267                 + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.xa )
1268                 + nDrawXOfs2 + (sal_Int16)SVBT16ToShort( pP[0] ),
1269                (sal_Int16)SVBT16ToShort( pHd->ya )
1270                + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.ya )
1271                + nDrawYOfs2 + (sal_Int16)SVBT16ToShort( pP[1] ) );
1272     delete[] pP;
1273 
1274     SdrCaptionObj* pObj = new SdrCaptionObj( Rectangle( aP0, aP1 ), aP2 );
1275     pObj->SetModel( pDrawModel );
1276     pObj->NbcSetSnapRect(Rectangle(aP0, aP1));
1277     Size aSize( (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa ),
1278                            (sal_Int16)SVBT16ToShort(  aCallB.dpheadTxbx.dya ) );
1279     bool bEraseThisObject;
1280 
1281     InsertTxbxText(pObj, &aSize, 0, 0, 0, 0, false, bEraseThisObject );
1282 
1283     if( SVBT16ToShort( aCallB.dptxbx.aLnt.lnps ) != 5 ) // Umrandung sichtbar ?
1284         SetStdAttr( rSet, aCallB.dptxbx.aLnt, aCallB.dptxbx.aShd );
1285     else                                                // nein -> Nimm Linie
1286         SetStdAttr( rSet, aCallB.dpPolyLine.aLnt, aCallB.dptxbx.aShd );
1287     SetFill( rSet, aCallB.dptxbx.aFill );
1288     rSet.Put( SdrCaptionTypeItem( aCaptA[nTyp] ) );
1289 
1290     return pObj;
1291 }
1292 
1293 
1294 SdrObject *SwWW8ImplReader::ReadGroup( WW8_DPHEAD* pHd, const WW8_DO* pDo,
1295     SfxAllItemSet &rSet)
1296 {
1297     sal_Int16 nGrouped;
1298 
1299     if( !ReadGrafStart( (void*)&nGrouped, sizeof( nGrouped ), pHd, pDo, rSet ) )
1300         return 0;
1301 
1302 #ifdef OSL_BIGENDIAN
1303     nGrouped = (sal_Int16)SWAPSHORT( nGrouped );
1304 #endif
1305 
1306     nDrawXOfs = nDrawXOfs + (sal_Int16)SVBT16ToShort( pHd->xa );
1307     nDrawYOfs = nDrawYOfs + (sal_Int16)SVBT16ToShort( pHd->ya );
1308 
1309     SdrObject* pObj = new SdrObjGroup;
1310 
1311     short nLeft = (sal_Int16)SVBT16ToShort( pHd->cb ) - sizeof( WW8_DPHEAD );
1312     for (int i = 0; i < nGrouped; i++)
1313     {
1314         SfxAllItemSet aSet(pDrawModel->GetItemPool());
1315         if (SdrObject *pObject = ReadGrafPrimitive(nLeft, pDo, aSet))
1316         {
1317 			// #116150#
1318 			// first add and then set ItemSet
1319             SdrObjList *pSubGroup = pObj->GetSubList();
1320             ASSERT(pSubGroup, "Why no sublist available?");
1321             if (pSubGroup)
1322                 pSubGroup->InsertObject(pObject, 0);
1323             pObject->SetMergedItemSetAndBroadcast(aSet);
1324         }
1325     }
1326 
1327     nDrawXOfs = nDrawXOfs - (sal_Int16)SVBT16ToShort( pHd->xa );
1328     nDrawYOfs = nDrawYOfs - (sal_Int16)SVBT16ToShort( pHd->ya );
1329 
1330     return pObj;
1331 }
1332 
1333 SdrObject* SwWW8ImplReader::ReadGrafPrimitive( short& rLeft, const WW8_DO* pDo,
1334     SfxAllItemSet &rSet)
1335 {
1336     //cmc: This whole archaic word 6 graphic import can probably be refactored
1337     //into an object hierarachy with a little effort.
1338     SdrObject *pRet=0;
1339     WW8_DPHEAD aHd;                         // Lese Draw-Primitive-Header
1340     pStrm->Read(&aHd, sizeof(WW8_DPHEAD));
1341 
1342     if( rLeft >= SVBT16ToShort(aHd.cb) )    // Vorsichtsmassmahme
1343     {
1344         rSet.Put(SwFmtSurround(SURROUND_THROUGHT));
1345         switch (SVBT16ToShort(aHd.dpk) & 0xff )
1346         {
1347             case 0:
1348                 pRet = ReadGroup( &aHd, pDo, rSet );
1349                 break;
1350             case 1:
1351                 pRet = ReadLine( &aHd, pDo, rSet );
1352                 break;
1353             case 2:
1354                 pRet = ReadTxtBox( &aHd, pDo, rSet );
1355                 break;
1356             case 3:
1357                 pRet = ReadRect( &aHd, pDo, rSet );
1358                 break;
1359             case 4:
1360                 pRet = ReadElipse( &aHd, pDo, rSet );
1361                 break;
1362             case 5:
1363                 pRet = ReadArc( &aHd, pDo, rSet );
1364                 break;
1365             case 6:
1366                 pRet = ReadPolyLine( &aHd, pDo, rSet );
1367                 break;
1368             case 7:
1369                 pRet = ReadCaptionBox( &aHd, pDo, rSet );
1370                 break;
1371             default:    // unbekannt
1372                 pStrm->SeekRel(SVBT16ToShort(aHd.cb) - sizeof(WW8_DPHEAD));
1373                 break;
1374         }
1375     }
1376     else
1377     {
1378         ASSERT( !this, "+Grafik-Overlap" );
1379     }
1380     rLeft = rLeft - SVBT16ToShort( aHd.cb );
1381     return pRet;
1382 }
1383 
1384 void SwWW8ImplReader::ReadGrafLayer1( WW8PLCFspecial* pPF, long nGrafAnchorCp )
1385 {
1386     pPF->SeekPos( nGrafAnchorCp );
1387     WW8_FC nStartFc;
1388     void* pF0;
1389     if( !pPF->Get( nStartFc, pF0 ) )
1390     {
1391         ASSERT( !this, "+Wo ist die Grafik (2) ?" );
1392         return;
1393     }
1394     WW8_FDOA* pF = (WW8_FDOA*)pF0;
1395     if( !SVBT32ToUInt32( pF->fc ) )
1396     {
1397         ASSERT( !this, "+Wo ist die Grafik (3) ?" );
1398         return;
1399     }
1400     WW8_DO aDo;
1401     pStrm->Seek( SVBT32ToUInt32( pF->fc ) );                  // Lese Draw-Header
1402     pStrm->Read( &aDo, sizeof( WW8_DO ) );
1403 
1404     short nLeft = SVBT16ToShort( aDo.cb ) - sizeof( WW8_DO );
1405     while (nLeft > static_cast<short>(sizeof(WW8_DPHEAD)))
1406     {
1407         SfxAllItemSet aSet( pDrawModel->GetItemPool() );
1408         if (SdrObject *pObject = ReadGrafPrimitive( nLeft, &aDo, aSet ))
1409         {
1410             pWWZOrder->InsertDrawingObject(pObject, SVBT16ToShort(aDo.dhgt));
1411             SwFrmFmt *pFrm = rDoc.Insert( *pPaM, *pObject, &aSet, NULL);
1412             pObject->SetMergedItemSet(aSet);
1413             pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFrm);
1414         }
1415     }
1416 }
1417 
1418 const WW8_BordersSO &WW8_BordersSO::Get0x01LineMatch(eBorderCode eCode)
1419 {
1420     /*
1421     // Linien-Defaults in Twips: fruehere Writer-Defaults,
1422     //                           siehe auch <editeng/boxitem.hxx>
1423     #define DEF_LINE_WIDTH_0        1
1424     #define DEF_LINE_WIDTH_1        20
1425     #define DEF_LINE_WIDTH_2        50
1426     #define DEF_LINE_WIDTH_3        80
1427     #define DEF_LINE_WIDTH_4        100
1428     #define DEF_LINE_WIDTH_5        10
1429 
1430     #define DEF_MAX_LINE_WIDHT      DEF_LINE_WIDTH_4
1431     #define DEF_MAX_LINE_DIST       DEF_LINE_WIDTH_2
1432 
1433     #define DEF_DOUBLE_LINE0_OUT    DEF_LINE_WIDTH_0
1434     #define DEF_DOUBLE_LINE0_IN     DEF_LINE_WIDTH_0
1435     #define DEF_DOUBLE_LINE0_DIST   DEF_LINE_WIDTH_1
1436 
1437     #define DEF_DOUBLE_LINE1_OUT    DEF_LINE_WIDTH_1
1438     #define DEF_DOUBLE_LINE1_IN     DEF_LINE_WIDTH_1
1439     #define DEF_DOUBLE_LINE1_DIST   DEF_LINE_WIDTH_1
1440 
1441     #define DEF_DOUBLE_LINE2_OUT    DEF_LINE_WIDTH_2
1442     #define DEF_DOUBLE_LINE2_IN     DEF_LINE_WIDTH_2
1443     #define DEF_DOUBLE_LINE2_DIST   DEF_LINE_WIDTH_2
1444 
1445     #define DEF_DOUBLE_LINE3_OUT    DEF_LINE_WIDTH_2
1446     #define DEF_DOUBLE_LINE3_IN     DEF_LINE_WIDTH_1
1447     #define DEF_DOUBLE_LINE3_DIST   DEF_LINE_WIDTH_2
1448 
1449     #define DEF_DOUBLE_LINE4_OUT    DEF_LINE_WIDTH_1
1450     #define DEF_DOUBLE_LINE4_IN     DEF_LINE_WIDTH_2
1451     #define DEF_DOUBLE_LINE4_DIST   DEF_LINE_WIDTH_1
1452 
1453     #define DEF_DOUBLE_LINE5_OUT    DEF_LINE_WIDTH_3
1454     #define DEF_DOUBLE_LINE5_IN     DEF_LINE_WIDTH_2
1455     #define DEF_DOUBLE_LINE5_DIST   DEF_LINE_WIDTH_2
1456 
1457     #define DEF_DOUBLE_LINE6_OUT    DEF_LINE_WIDTH_2
1458     #define DEF_DOUBLE_LINE6_IN     DEF_LINE_WIDTH_3
1459     #define DEF_DOUBLE_LINE6_DIST   DEF_LINE_WIDTH_2
1460 
1461     #define DEF_DOUBLE_LINE7_OUT    DEF_LINE_WIDTH_0
1462     #define DEF_DOUBLE_LINE7_IN     DEF_LINE_WIDTH_0
1463     #define DEF_DOUBLE_LINE7_DIST   DEF_LINE_WIDTH_2
1464 
1465     #define DEF_DOUBLE_LINE8_OUT    DEF_LINE_WIDTH_1
1466     #define DEF_DOUBLE_LINE8_IN     DEF_LINE_WIDTH_0
1467     #define DEF_DOUBLE_LINE8_DIST   DEF_LINE_WIDTH_2
1468 
1469     #define DEF_DOUBLE_LINE9_OUT    DEF_LINE_WIDTH_2
1470     #define DEF_DOUBLE_LINE9_IN     DEF_LINE_WIDTH_0
1471     #define DEF_DOUBLE_LINE9_DIST   DEF_LINE_WIDTH_2
1472 
1473     #define DEF_DOUBLE_LINE10_OUT   DEF_LINE_WIDTH_3
1474     #define DEF_DOUBLE_LINE10_IN    DEF_LINE_WIDTH_0
1475     #define DEF_DOUBLE_LINE10_DIST  DEF_LINE_WIDTH_2
1476     */
1477     // Deklarationen gemaess BOXITEM.HXX
1478     static const WW8_BordersSO aLineTabVer8[] =
1479     {
1480 /* 0*/  { DEF_LINE_WIDTH_0, 0, 0 },
1481 /* 1*/  { DEF_LINE_WIDTH_1, 0, 0 },
1482 /* 2*/  { DEF_LINE_WIDTH_2, 0, 0 },
1483 /* 3*/  { DEF_LINE_WIDTH_3, 0, 0 },
1484 /* 4*/  { DEF_LINE_WIDTH_4, 0, 0 },
1485 /* 5*/  { DEF_LINE_WIDTH_5, 0, 0 },
1486 /* 6*/  { DEF_DOUBLE_LINE0_OUT, DEF_DOUBLE_LINE0_IN, DEF_DOUBLE_LINE0_DIST },
1487 /* 7*/  { DEF_DOUBLE_LINE1_OUT, DEF_DOUBLE_LINE1_IN, DEF_DOUBLE_LINE1_DIST },
1488 /* 8*/  { DEF_DOUBLE_LINE2_OUT, DEF_DOUBLE_LINE2_IN, DEF_DOUBLE_LINE2_DIST },
1489 /* 9*/  { DEF_DOUBLE_LINE3_OUT, DEF_DOUBLE_LINE3_IN, DEF_DOUBLE_LINE3_DIST },
1490 /*10*/  { DEF_DOUBLE_LINE4_OUT, DEF_DOUBLE_LINE4_IN, DEF_DOUBLE_LINE4_DIST },
1491 /*11*/  { DEF_DOUBLE_LINE5_OUT, DEF_DOUBLE_LINE5_IN, DEF_DOUBLE_LINE5_DIST },
1492 /*12*/  { DEF_DOUBLE_LINE6_OUT, DEF_DOUBLE_LINE6_IN, DEF_DOUBLE_LINE6_DIST },
1493 /*13*/  { DEF_DOUBLE_LINE7_OUT, DEF_DOUBLE_LINE7_IN, DEF_DOUBLE_LINE7_DIST },
1494 /*14*/  { DEF_DOUBLE_LINE8_OUT, DEF_DOUBLE_LINE8_IN, DEF_DOUBLE_LINE8_DIST },
1495 /*15*/  { DEF_DOUBLE_LINE9_OUT, DEF_DOUBLE_LINE9_IN, DEF_DOUBLE_LINE9_DIST },
1496 /*16*/  { DEF_DOUBLE_LINE10_OUT,DEF_DOUBLE_LINE10_IN,DEF_DOUBLE_LINE10_DIST}
1497     };
1498     size_t nPos = static_cast<size_t>(eCode);
1499     ASSERT(nPos < sizeof(aLineTabVer8), "Impossible");
1500     if (nPos >= sizeof(aLineTabVer8))
1501         eCode = single0;
1502     return aLineTabVer8[eCode];
1503 }
1504 
1505 sal_Int32 SwMSDffManager::GetEscherLineMatch(MSO_LineStyle eStyle,
1506     MSO_SPT eShapeType, sal_Int32 &rThick)
1507 {
1508     sal_Int32 nOutsideThick = 0;
1509     /*
1510     Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und
1511     Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer*
1512     Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER
1513     stammenden Daten bereits als Gesamt-Breite [twips] vor!
1514 
1515     Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie.  (
1516     0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als
1517     etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur
1518     bei Winword-Staerken bis zu maximal 0.5 pt ein.
1519     */
1520     switch( eStyle )
1521     {
1522     case mso_lineTriple:
1523     case mso_lineSimple:
1524         nOutsideThick = eShapeType != mso_sptTextBox ? rThick : rThick/2;
1525         break;
1526     case mso_lineDouble:
1527         if (eShapeType == mso_sptTextBox)
1528         {
1529             nOutsideThick = rThick/6;
1530             rThick = rThick*2/3;
1531         }
1532         else
1533             nOutsideThick = rThick*2/3;
1534         break;
1535     case mso_lineThickThin:
1536         if (eShapeType == mso_sptTextBox)
1537         {
1538             nOutsideThick = rThick*3/10;
1539             rThick = rThick*4/5;
1540         }
1541         else
1542             nOutsideThick = rThick*4/5;
1543         break;
1544     case mso_lineThinThick:
1545         {
1546         if (eShapeType == mso_sptTextBox)
1547         {
1548             nOutsideThick = rThick/10;
1549             rThick = rThick*3/5;
1550         }
1551         else
1552             nOutsideThick = rThick*3/5;
1553         }
1554         break;
1555     default:
1556         break;
1557     }
1558     return nOutsideThick;
1559 }
1560 
1561 //Returns the thickness of the line outside the frame, the logic of
1562 //words positioning of borders around floating objects is that of a
1563 //disturbed mind.
1564 sal_Int32 SwWW8ImplReader::MatchSdrBoxIntoFlyBoxItem(const Color& rLineColor,
1565     MSO_LineStyle eLineStyle, MSO_SPT eShapeType, sal_Int32 &rLineThick,
1566     SvxBoxItem& rBox )
1567 {
1568     sal_Int32 nOutsideThick = 0;
1569     if( !rLineThick )
1570         return nOutsideThick;
1571 
1572     WW8_BordersSO::eBorderCode nIdx = WW8_BordersSO::none;
1573 
1574     sal_Int32 nLineThick=rLineThick;
1575     nOutsideThick = SwMSDffManager::GetEscherLineMatch(eLineStyle,
1576         eShapeType, rLineThick);
1577 
1578     /*
1579     Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und
1580     Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer*
1581     Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER
1582     stammenden Daten bereits als Gesamt-Breite [twips] vor!
1583 
1584     Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie.  (
1585     0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als
1586     etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur
1587     bei Winword-Staerken bis zu maximal 0.5 pt ein.
1588     */
1589     switch( +eLineStyle )
1590     {
1591     // zuerst die Einzel-Linien
1592     case mso_lineSimple:
1593         if (nLineThick < 10)
1594             nIdx = WW8_BordersSO::single0;//   1 Twip bei uns
1595         else if (nLineThick < 20)
1596             nIdx = WW8_BordersSO::single5;//   10 Twips bei uns
1597         else if (nLineThick < 50)
1598             nIdx = WW8_BordersSO::single1;//  20 Twips
1599         else if (nLineThick < 80)
1600             nIdx = WW8_BordersSO::single2;//  50
1601         else if (nLineThick < 100)
1602             nIdx = WW8_BordersSO::single3;//  80
1603         else if (nLineThick <150)
1604             nIdx = WW8_BordersSO::single4;// 100
1605         // Pfusch: fuer die ganz dicken Linien muessen wir doppelte Linien
1606         // malen, weil unsere Einfach-Linie nicht dicker als 5 Punkt wird
1607         else if (nLineThick <180)
1608             nIdx = WW8_BordersSO::double2;// 150
1609         else
1610             nIdx = WW8_BordersSO::double5;// 180
1611     break;
1612     // dann die Doppel-Linien, fuer die wir feine Entsprechungen haben :-)))
1613     case mso_lineDouble:
1614         if (nLineThick <  60)
1615             nIdx = WW8_BordersSO::double0;//  22 Twips bei uns
1616         else if (nLineThick < 135)
1617             nIdx = WW8_BordersSO::double7;// some more space
1618         else if (nLineThick < 180)
1619             nIdx = WW8_BordersSO::double1;//  60
1620         else
1621             nIdx = WW8_BordersSO::double2;// 150
1622     break;
1623     case mso_lineThickThin:
1624         if (nLineThick <  87)
1625             nIdx = WW8_BordersSO::double8;//  71 Twips bei uns
1626         else if (nLineThick < 117)
1627             nIdx = WW8_BordersSO::double9;// 101
1628         else if (nLineThick < 166)
1629             nIdx = WW8_BordersSO::double10;// 131
1630         else
1631             nIdx = WW8_BordersSO::double5;// 180
1632     break;
1633     case mso_lineThinThick:
1634         if (nLineThick < 137)
1635             nIdx = WW8_BordersSO::double4;//  90 Twips bei uns
1636         else
1637             nIdx = WW8_BordersSO::double6;// 180
1638     break;
1639     // zu guter Letzt die Dreifach-Linien, an deren Stelle wir eine
1640     // Doppel-Linie setzen
1641     case mso_lineTriple:
1642         if (nLineThick < 46)
1643             nIdx = WW8_BordersSO::double0;//  22 Twips bei uns
1644         else if (nLineThick < 106)
1645             nIdx = WW8_BordersSO::double1;//  60
1646         else if (nLineThick < 166)
1647             nIdx = WW8_BordersSO::double2;// 150
1648         else
1649             nIdx = WW8_BordersSO::double5;// 180
1650     break;
1651     // no line style is set
1652     case (MSO_LineStyle)USHRT_MAX:
1653         break;
1654     // erroneously not implemented line style is set
1655     default:
1656         ASSERT(!this, "eLineStyle is not (yet) implemented!");
1657         break;
1658     }
1659 
1660     if (WW8_BordersSO::none != nIdx)
1661     {
1662         SvxBorderLine aLine;
1663         aLine.SetColor( rLineColor );
1664 
1665         const WW8_BordersSO& rBorders = WW8_BordersSO::Get0x01LineMatch(nIdx);
1666 
1667         aLine.SetOutWidth(rBorders.mnOut);
1668         aLine.SetInWidth (rBorders.mnIn);
1669         aLine.SetDistance(rBorders.mnDist);
1670 
1671         for(sal_uInt16 nLine = 0; nLine < 4; ++nLine)
1672             rBox.SetLine(new SvxBorderLine( aLine ), nLine);
1673     }
1674 
1675     return nOutsideThick;
1676 }
1677 
1678 #define WW8ITEMVALUE(ItemSet,Id,Cast)  ((const Cast&)(ItemSet).Get(Id)).GetValue()
1679 
1680 void SwWW8ImplReader::MatchSdrItemsIntoFlySet( SdrObject* pSdrObj,
1681     SfxItemSet& rFlySet, MSO_LineStyle eLineStyle, MSO_SPT eShapeType,
1682     Rectangle& rInnerDist )
1683 {
1684 /*
1685     am Rahmen zu setzende Frame-Attribute
1686     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1687     SwFmtFrmSize            falls noch nicht gesetzt, hier setzen
1688     SvxLRSpaceItem          hier setzen
1689     SvxULSpaceItem          hier setzen
1690     SvxOpaqueItem           (Derzeit bei Rahmen nicht moeglich! khz 10.2.1999)
1691     SwFmtSurround           bereits gesetzt
1692     SwFmtVertOrient         bereits gesetzt
1693     SwFmtHoriOrient         bereits gesetzt
1694     SwFmtAnchor             bereits gesetzt
1695     SvxBoxItem              hier setzen
1696     SvxBrushItem            hier setzen
1697     SvxShadowItem           hier setzen
1698 */
1699 
1700     // 1. GrafikObjekt des Docs?
1701     GrafikCtor();
1702 
1703     const SfxItemSet& rOldSet = pSdrObj->GetMergedItemSet();
1704 
1705     // einige Items koennen direkt so uebernommen werden
1706     const sal_uInt16 nDirectMatch = 2;
1707     static RES_FRMATR __READONLY_DATA aDirectMatch[ nDirectMatch ] =
1708     {
1709         RES_LR_SPACE,   // Aussenabstand links/rechts: SvxLRSpaceItem
1710         RES_UL_SPACE    // Aussenabstand Oben/unten:   SvxULSpaceItem
1711     };
1712     const SfxPoolItem* pPoolItem;
1713     for(sal_uInt16 nItem = 0; nItem < nDirectMatch; ++nItem)
1714         if( SFX_ITEM_SET == rOldSet.GetItemState(
1715                     static_cast< sal_uInt16 >(aDirectMatch[ nItem ]), false, &pPoolItem) )
1716         {
1717             rFlySet.Put( *pPoolItem );
1718         }
1719 
1720 
1721     // jetzt die Umrandung berechnen und die Box bauen: Das Mass wird fuer die
1722     // Rahmen-GROESSE benoetigt!
1723     SvxBoxItem aBox(sw::util::ItemGet<SvxBoxItem>(rFlySet, RES_BOX));
1724     // dashed oder solid wird zu solid
1725     sal_Int32 nLineThick = 0, nOutside=0;
1726 
1727     // check if LineStyle is *really* set!
1728     const SfxPoolItem* pItem;
1729 
1730     SfxItemState eState = rOldSet.GetItemState(XATTR_LINESTYLE,true,&pItem);
1731     if( eState == SFX_ITEM_SET )
1732     {
1733         // Now, that we know there is a line style we will make use the
1734         // parameter given to us when calling the method...  :-)
1735         const Color aLineColor = static_cast< XLineColorItem const & >(
1736             rOldSet.Get(XATTR_LINECOLOR)).GetColorValue();
1737         nLineThick = WW8ITEMVALUE(rOldSet, XATTR_LINEWIDTH, XLineWidthItem);
1738 
1739         if( !nLineThick )
1740             nLineThick = 15; // WW-default: 0.75 pt
1741 
1742         nOutside = MatchSdrBoxIntoFlyBoxItem(aLineColor, eLineStyle,
1743             eShapeType, nLineThick, aBox);
1744     }
1745 
1746     rInnerDist.Left()+=nLineThick;
1747     rInnerDist.Top()+=nLineThick;
1748     rInnerDist.Right()+=nLineThick;
1749     rInnerDist.Bottom()+=nLineThick;
1750 
1751     const SvxBorderLine *pLine;
1752     if (0 != (pLine = aBox.GetLine(BOX_LINE_LEFT)))
1753     {
1754         rInnerDist.Left() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
1755             pLine->GetDistance());
1756     }
1757 
1758     if (0 != (pLine = aBox.GetLine(BOX_LINE_TOP)))
1759     {
1760         rInnerDist.Top() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
1761             pLine->GetDistance());
1762     }
1763 
1764     if (0 != (pLine = aBox.GetLine(BOX_LINE_RIGHT)))
1765     {
1766         rInnerDist.Right() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
1767             pLine->GetDistance());
1768     }
1769 
1770     if (0 != (pLine = aBox.GetLine(BOX_LINE_BOTTOM)))
1771     {
1772         rInnerDist.Bottom() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
1773             pLine->GetDistance());
1774     }
1775 
1776     // set distances from box's border to text contained within the box
1777     if( 0 < rInnerDist.Left() )
1778         aBox.SetDistance( (sal_uInt16)rInnerDist.Left(), BOX_LINE_LEFT );
1779     if( 0 < rInnerDist.Top() )
1780         aBox.SetDistance( (sal_uInt16)rInnerDist.Top(), BOX_LINE_TOP );
1781     if( 0 < rInnerDist.Right() )
1782         aBox.SetDistance( (sal_uInt16)rInnerDist.Right(), BOX_LINE_RIGHT );
1783     if( 0 < rInnerDist.Bottom() )
1784         aBox.SetDistance( (sal_uInt16)rInnerDist.Bottom(), BOX_LINE_BOTTOM );
1785 
1786     bool bFixSize = !(WW8ITEMVALUE(rOldSet, SDRATTR_TEXT_AUTOGROWHEIGHT,
1787         SdrTextAutoGrowHeightItem));
1788 
1789     // Size: SwFmtFrmSize
1790     if( SFX_ITEM_SET != rFlySet.GetItemState(RES_FRM_SIZE, false) )
1791     {
1792         const Rectangle& rSnapRect = pSdrObj->GetSnapRect();
1793         // if necessary adapt width and position of the framework: The
1794         // recorded interior is to remain equally large despite thick edges.
1795         rFlySet.Put( SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
1796             rSnapRect.GetWidth()  + 2*nOutside,
1797             rSnapRect.GetHeight() + 2*nOutside) );
1798     }
1799     else //If a size is set, adjust it to consider border thickness
1800     {
1801         SwFmtFrmSize aSize = (const SwFmtFrmSize &)(rFlySet.Get(RES_FRM_SIZE));
1802 
1803         SwFmtFrmSize aNewSize = SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
1804             aSize.GetWidth()  + 2*nOutside,
1805             aSize.GetHeight() + 2*nOutside);
1806         aNewSize.SetWidthSizeType(aSize.GetWidthSizeType());
1807         rFlySet.Put( aNewSize );
1808     }
1809 
1810     //Sadly word puts escher borders outside the graphic, but orients the
1811     //graphic in relation to the top left inside the border. We don't
1812     if (nOutside)
1813     {
1814         SwFmtHoriOrient aHori = (const SwFmtHoriOrient &)(rFlySet.Get(
1815             RES_HORI_ORIENT));
1816         aHori.SetPos(MakeSafePositioningValue(aHori.GetPos()-nOutside));
1817         rFlySet.Put(aHori);
1818 
1819         SwFmtVertOrient aVert = (const SwFmtVertOrient &)(rFlySet.Get(
1820             RES_VERT_ORIENT));
1821         aVert.SetPos(aVert.GetPos()-nOutside);
1822         rFlySet.Put(aVert);
1823     }
1824 
1825     // jetzt die Umrandung setzen
1826     rFlySet.Put( aBox );
1827 
1828     // Schattenwurf der Box: SvxShadowItem
1829     if( WW8ITEMVALUE(rOldSet, SDRATTR_SHADOW, SdrShadowItem) )
1830     {
1831         SvxShadowItem aShadow( RES_SHADOW );
1832 
1833         const Color aShdColor = static_cast< SdrShadowColorItem const & >(
1834             rOldSet.Get(SDRATTR_SHADOWCOLOR)).GetColorValue();
1835         const sal_Int32 nShdDistX = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWXDIST,
1836             SdrShadowXDistItem);
1837         const sal_Int32 nShdDistY = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWYDIST,
1838             SdrShadowYDistItem);
1839         //const sal_uInt16 nShdTrans= WW8ITEMVALUE(rOldSet,
1840         //   SDRATTR_SHADOWTRANSPARENCE, SdrShadowTransparenceItem);
1841 
1842         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1843         //
1844         // SfxVoidItem( SDRATTR_SHADOW3D    )
1845         // SfxVoidItem( SDRATTR_SHADOWPERSP )
1846 
1847         aShadow.SetColor( Color( aShdColor ) );
1848 
1849         aShadow.SetWidth(writer_cast<sal_uInt16>((Abs( nShdDistX) +
1850             Abs( nShdDistY )) / 2 ));
1851 
1852         SvxShadowLocation eShdPosi;
1853         if( 0 <= nShdDistX )
1854         {
1855             if( 0 <= nShdDistY )
1856                 eShdPosi = SVX_SHADOW_BOTTOMRIGHT;
1857             else
1858                 eShdPosi = SVX_SHADOW_TOPRIGHT;
1859         }
1860         else
1861         {
1862             if( 0 <= nShdDistY )
1863                 eShdPosi = SVX_SHADOW_BOTTOMLEFT;
1864             else
1865                 eShdPosi = SVX_SHADOW_TOPLEFT;
1866         }
1867         aShadow.SetLocation( eShdPosi );
1868 
1869         rFlySet.Put( aShadow );
1870     }
1871     Color Temp(COL_WHITE);
1872     SvxBrushItem aBrushItem(Temp, RES_BACKGROUND);
1873     bool bBrushItemOk = false;
1874     sal_uInt8 nTrans = 0;
1875 
1876     //Seperate transparency
1877     eState = rOldSet.GetItemState(XATTR_FILLTRANSPARENCE, true, &pItem);
1878     if (eState == SFX_ITEM_SET)
1879     {
1880         sal_uInt16 nRes = WW8ITEMVALUE(rOldSet, XATTR_FILLTRANSPARENCE,
1881             XFillTransparenceItem);
1882         nTrans = sal_uInt8((nRes * 0xFE) / 100);
1883         aBrushItem.GetColor().SetTransparency(nTrans);
1884         bBrushItemOk = true;
1885     }
1886 
1887     // Hintergrund: SvxBrushItem
1888     eState = rOldSet.GetItemState(XATTR_FILLSTYLE, true, &pItem);
1889     if (eState == SFX_ITEM_SET)
1890     {
1891         const XFillStyle eFill = ((const XFillStyleItem*)pItem)->GetValue();
1892 
1893         switch (eFill)
1894         {
1895             case XFILL_NONE:
1896                 //Writer graphics don't have it yet
1897                 if (eShapeType != mso_sptPictureFrame)
1898                 {
1899                     aBrushItem.GetColor().SetTransparency(0xFE);
1900                     bBrushItemOk = true;
1901                 }
1902             break;
1903             case XFILL_SOLID:
1904                 {
1905                     const Color aColor = static_cast< XFillColorItem const & >(
1906                         rOldSet.Get(XATTR_FILLCOLOR)).GetColorValue();
1907                     aBrushItem.SetColor(aColor);
1908 
1909                     if (bBrushItemOk) //has trans
1910                         aBrushItem.GetColor().SetTransparency(nTrans);
1911 
1912                     bBrushItemOk = true;
1913                 }
1914             break;
1915             case XFILL_GRADIENT:
1916             break;
1917             case XFILL_HATCH:
1918             break;
1919             case XFILL_BITMAP:
1920                 {
1921                     const Graphic aGraphic(
1922                         static_cast< XFillBitmapItem const & >(
1923                             rOldSet.Get(XATTR_FILLBITMAP)).
1924                         GetBitmapValue().GetBitmap());
1925                     bool bTile = WW8ITEMVALUE(rOldSet, XATTR_FILLBMP_TILE,
1926                         SfxBoolItem) ? true: false;
1927                     GraphicObject aGrfObj(aGraphic);
1928 
1929                     aBrushItem.SetGraphicObject(aGrfObj);
1930 
1931                     if (bBrushItemOk) //has trans
1932                     {
1933                         GraphicObject *pGraphicObject =
1934                             const_cast<GraphicObject *>
1935                             (aBrushItem.GetGraphicObject());
1936                         GraphicAttr aAttr(pGraphicObject->GetAttr());
1937                         aAttr.SetTransparency(nTrans);
1938                         pGraphicObject->SetAttr(aAttr);
1939                     }
1940 
1941                     aBrushItem.SetGraphicPos(bTile ? GPOS_TILED : GPOS_AREA);
1942 
1943                     bBrushItemOk = true;
1944                 }
1945             break;
1946         }
1947     }
1948 
1949     if (bBrushItemOk)
1950         rFlySet.Put(aBrushItem, RES_BACKGROUND);
1951 }
1952 
1953 void SwWW8ImplReader::AdjustLRWrapForWordMargins(
1954     const SvxMSDffImportRec &rRecord, SvxLRSpaceItem &rLR)
1955 {
1956     // Left adjustments - if horizontally aligned to left of
1957     // margin or column then remove the left wrapping
1958     if (rRecord.nXAlign == 1)
1959     {
1960         if ((rRecord.nXRelTo == 0) || (rRecord.nXRelTo == 2))
1961             rLR.SetLeft((sal_uInt16)0);
1962     }
1963 
1964     // Right adjustments - if horizontally aligned to right of
1965     // margin or column then remove the right wrapping
1966     if (rRecord.nXAlign == 3)
1967     {
1968         if ((rRecord.nXRelTo == 0) || (rRecord.nXRelTo == 2))
1969             rLR.SetRight((sal_uInt16)0);
1970     }
1971 
1972     //Inside margin, remove left wrapping
1973     if ((rRecord.nXAlign == 4) && (rRecord.nXRelTo == 0))
1974     {
1975         rLR.SetLeft((sal_uInt16)0);
1976     }
1977 
1978     //Outside margin, remove left wrapping
1979     if ((rRecord.nXAlign == 5) && (rRecord.nXRelTo == 0))
1980     {
1981         rLR.SetRight((sal_uInt16)0);
1982     }
1983 }
1984 
1985 
1986 void SwWW8ImplReader::AdjustULWrapForWordMargins(
1987     const SvxMSDffImportRec &rRecord, SvxULSpaceItem &rUL)
1988 {
1989     // Top adjustment - remove upper wrapping if aligned to page
1990     // printable area or to page
1991     if (rRecord.nYAlign == 1)
1992     {
1993         if ((rRecord.nYRelTo == 0) || (rRecord.nYRelTo == 1))
1994             rUL.SetUpper((sal_uInt16)0);
1995     }
1996 
1997     // Bottom adjustment - remove bottom wrapping if aligned to page or
1998     // printable area or to page
1999     if (rRecord.nYAlign == 3)
2000     {
2001         if ((rRecord.nYRelTo == 0) || (rRecord.nYRelTo == 1))
2002             rUL.SetLower((sal_uInt16)0);
2003     }
2004 
2005     //Remove top margin if aligned vertically inside margin
2006     if ((rRecord.nYAlign == 4) && (rRecord.nYRelTo == 0))
2007         rUL.SetUpper((sal_uInt16)0);
2008 
2009     /*
2010     // Something like this needs to be done once inside and outside are
2011     // fixed
2012     if (rRecord.nYAlign == 4)
2013     {
2014         if (rRecord.nYRelTo == 0)
2015             rUL.SetUpper((sal_uInt16)0);
2016     }
2017     */
2018 }
2019 
2020 void SwWW8ImplReader::MapWrapIntoFlyFmt(SvxMSDffImportRec* pRecord,
2021     SwFrmFmt* pFlyFmt)
2022 {
2023     if (!pRecord || !pFlyFmt)
2024         return;
2025 
2026     if (pRecord->nDxWrapDistLeft || pRecord->nDxWrapDistRight)
2027     {
2028         SvxLRSpaceItem aLR(writer_cast<sal_uInt16>(pRecord->nDxWrapDistLeft),
2029             writer_cast<sal_uInt16>(pRecord->nDxWrapDistRight), 0, 0, RES_LR_SPACE);
2030         AdjustLRWrapForWordMargins(*pRecord, aLR);
2031         pFlyFmt->SetFmtAttr(aLR);
2032     }
2033     if (pRecord->nDyWrapDistTop || pRecord->nDyWrapDistBottom)
2034     {
2035         SvxULSpaceItem aUL(writer_cast<sal_uInt16>(pRecord->nDyWrapDistTop),
2036             writer_cast<sal_uInt16>(pRecord->nDyWrapDistBottom), RES_UL_SPACE);
2037         AdjustULWrapForWordMargins(*pRecord, aUL);
2038         pFlyFmt->SetFmtAttr(aUL);
2039     }
2040 
2041     //If we are contoured and have a custom polygon...
2042     if (pRecord->pWrapPolygon && pFlyFmt->GetSurround().IsContour())
2043     {
2044         if (SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(*pFlyFmt))
2045         {
2046 
2047             /*
2048              Gather round children and hear of a tale that will raise the
2049              hairs on the back of your neck this dark halloween night.
2050 
2051              There is a polygon in word that describes the wraping around
2052              the graphic.
2053 
2054              Here are some sample values for the simplest case of a square
2055              around some solid coloured graphics
2056 
2057                                 X       Y       Pixel size of graphic
2058                 TopLeft         -54     21600   400x400
2059                 Bottom Right    0       21546
2060 
2061                 TopLeft         -108    21600   200x200
2062                 Bottom Right    0       21492
2063 
2064                 TopLeft         -216    21600   100x100
2065                 Bottom Right    0       21384
2066 
2067                 TopLeft         -432    21600   50x50
2068                 Bottom Right    0       21168
2069 
2070                 TopLeft         -76     21600   283x212
2071                 Bottom Right    0       21498
2072 
2073              So given that the size of the values remains pretty much the
2074              same despite the size of the graphic, we can tell that the
2075              polygon is measured in units that are independant of the
2076              graphic. But why does the left corner move a different value
2077              to the left each time, and why does the bottom move upwards
2078              each time, when the right and top remain at the same value ?
2079 
2080              I have no idea, but clearly once we calculate the values out
2081              we see that the left margin is always a fixed realworld
2082              distance from the true left and the polygon bottom is the same
2083              fixed value from the bottom. i.e. 15twips.
2084 
2085              So here we take our word provided polygon, shift it to the
2086              right by 15twips and rescale it widthwise to shrink the width
2087              a little to fit the now moved right margin back to where it
2088              was, and stretch the height a little to make the bottom move
2089              down the missing 15twips then we get a polygon that matches
2090              what I actually see in word
2091             */
2092 
2093             PolyPolygon aPoly(*pRecord->pWrapPolygon);
2094             const Size &rSize = pNd->GetTwipSize();
2095             /*
2096              Move to the left by 15twips, and rescale to
2097              a) shrink right bound back to orig position
2098              b) stretch bottom bound to where I think it should have been
2099              in the first place
2100             */
2101             Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
2102             aMoveHack *= Fraction(15, 1);
2103             long nMove(aMoveHack);
2104             aPoly.Move(nMove, 0);
2105 
2106             Fraction aHackX(ww::nWrap100Percent, ww::nWrap100Percent + nMove);
2107             Fraction aHackY(ww::nWrap100Percent, ww::nWrap100Percent - nMove);
2108             aPoly.Scale(aHackX, aHackY);
2109 
2110             //Turn polygon back into units that match the graphic's
2111             const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
2112             Fraction aMapPolyX(rOrigSize.Width(), ww::nWrap100Percent);
2113             Fraction aMapPolyY(rOrigSize.Height(), ww::nWrap100Percent);
2114             aPoly.Scale(aMapPolyX, aMapPolyY);
2115 
2116             // --> OD 2005-05-19 #i47277# - contour is already in unit of the
2117             // graphic prefered unit. Thus, call method <SetContour(..)>
2118             pNd->SetContour(&aPoly);
2119             // <--
2120         }
2121     }
2122 }
2123 
2124 void SwWW8ImplReader::SetAttributesAtGrfNode( SvxMSDffImportRec* pRecord,
2125     SwFrmFmt *pFlyFmt, WW8_FSPA *pF )
2126 {
2127     const SwNodeIndex* pIdx = pFlyFmt->GetCntnt(false).GetCntntIdx();
2128     SwGrfNode* pGrfNd;
2129     if( pIdx && 0 != (pGrfNd = rDoc.GetNodes()[pIdx->GetIndex() + 1]->GetGrfNode() ))
2130     {
2131         Size aSz(pGrfNd->GetTwipSize());
2132         // --> OD 2005-08-01 #124722# - use type <sal_uInt64> instead of <sal_uLong>
2133         // to get correct results in the following calculations.
2134         sal_uInt64 rHeight = aSz.Height();
2135         sal_uInt64 rWidth  = aSz.Width();
2136         // <--
2137         if( !rWidth && pF)
2138             rWidth  = pF->nXaRight  - pF->nXaLeft;
2139         else if( !rHeight && pF)
2140             rHeight = pF->nYaBottom - pF->nYaTop;
2141 
2142         if( pRecord->nCropFromTop || pRecord->nCropFromBottom ||
2143             pRecord->nCropFromLeft || pRecord->nCropFromRight )
2144         {
2145             SwCropGrf aCrop;            // Cropping is stored in 'fixed floats'
2146                                         // 16.16 (it est fraction times total
2147             if( pRecord->nCropFromTop ) //        image width or height resp.)
2148                 aCrop.SetTop( static_cast< sal_Int32 >(
2149                 (   ( (pRecord->nCropFromTop    >> 16   ) * rHeight )
2150                   + (((pRecord->nCropFromTop    & 0xffff) * rHeight ) >> 16) )));
2151             if( pRecord->nCropFromBottom )
2152                 aCrop.SetBottom( static_cast< sal_Int32 >(
2153                 (   ( (pRecord->nCropFromBottom >> 16   ) * rHeight )
2154                   + (((pRecord->nCropFromBottom & 0xffff) * rHeight ) >> 16) )));
2155             if( pRecord->nCropFromLeft )
2156                 aCrop.SetLeft( static_cast< sal_Int32 >(
2157                 (   ( (pRecord->nCropFromLeft   >> 16   ) * rWidth  )
2158                   + (((pRecord->nCropFromLeft   & 0xffff) * rWidth  ) >> 16) )));
2159             if( pRecord->nCropFromRight )
2160                 aCrop.SetRight( static_cast< sal_Int32 >(
2161                 (   ( (pRecord->nCropFromRight  >> 16   ) * rWidth  )
2162                   + (((pRecord->nCropFromRight  & 0xffff) * rWidth  ) >> 16) )));
2163 
2164             pGrfNd->SetAttr( aCrop );
2165         }
2166 
2167         if (pRecord && pRecord->pObj)
2168         {
2169             const SfxItemSet& rOldSet = pRecord->pObj->GetMergedItemSet();
2170             //contrast
2171             if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFCONTRAST,
2172                 SdrGrafContrastItem))
2173             {
2174                 SwContrastGrf aContrast(
2175                     WW8ITEMVALUE(rOldSet,
2176                     SDRATTR_GRAFCONTRAST, SdrGrafContrastItem));
2177                 pGrfNd->SetAttr( aContrast );
2178             }
2179 
2180             //luminance
2181             if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFLUMINANCE,
2182                 SdrGrafLuminanceItem))
2183             {
2184                 SwLuminanceGrf aLuminance(WW8ITEMVALUE(rOldSet,
2185                     SDRATTR_GRAFLUMINANCE, SdrGrafLuminanceItem));
2186                 pGrfNd->SetAttr( aLuminance );
2187             }
2188             //gamma
2189             if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA, SdrGrafGamma100Item))
2190             {
2191                 double fVal = WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA,
2192                     SdrGrafGamma100Item);
2193                 pGrfNd->SetAttr(SwGammaGrf(fVal/100.));
2194             }
2195 
2196             //drawmode
2197             if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFMODE, SdrGrafModeItem))
2198             {
2199                 SwDrawModeGrf aDrawMode( static_cast< sal_uInt16 >(WW8ITEMVALUE(rOldSet,
2200                     SDRATTR_GRAFMODE, SdrGrafModeItem)) );
2201                 pGrfNd->SetAttr( aDrawMode );
2202             }
2203         }
2204     }
2205 }
2206 
2207 SdrObject* SwWW8ImplReader::CreateContactObject(SwFrmFmt* pFlyFmt)
2208 {
2209     if (pFlyFmt)
2210     {
2211         //JP 11.1.2002: task 96329
2212         SdrObject* pNewObject = mbNewDoc ? 0 : pFlyFmt->FindRealSdrObject();
2213         if (!pNewObject)
2214             pNewObject = pFlyFmt->FindSdrObject();
2215         if (!pNewObject && pFlyFmt->ISA(SwFlyFrmFmt))
2216         {
2217             SwFlyDrawContact* pContactObject
2218                 = new SwFlyDrawContact(static_cast<SwFlyFrmFmt*>(pFlyFmt),
2219                 pDrawModel);
2220             pNewObject = pContactObject->GetMaster();
2221         }
2222         return pNewObject;
2223     }
2224     return 0;
2225 }
2226 
2227 //#109311# Miserable miserable hack to fudge word's graphic layout in
2228 //RTL mode to ours.
2229 bool SwWW8ImplReader::MiserableRTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
2230     sal_Int16 eHoriOri, sal_Int16 eHoriRel)
2231 {
2232     if (!IsRightToLeft())
2233         return false;
2234     return RTLGraphicsHack(rLeft, nWidth, eHoriOri, eHoriRel,
2235             maSectionManager.GetPageLeft(),
2236             maSectionManager.GetPageRight(),
2237             maSectionManager.GetPageWidth());
2238 }
2239 
2240 RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec* pRecord,
2241     WW8_FSPA *pFSPA, SfxItemSet &rFlySet, bool /*bOrgObjectWasReplace*/)
2242 {
2243     ASSERT(pRecord || pFSPA, "give me something! to work with for anchoring");
2244     if (!pRecord && !pFSPA)
2245         return FLY_AT_PAGE;
2246 
2247     SvxMSDffImportRec aRecordFromFSPA;
2248     if (!pRecord)
2249     {
2250         pRecord = &aRecordFromFSPA;
2251         pRecord->nXRelTo = pFSPA->nbx;
2252         pRecord->nYRelTo = pFSPA->nby;
2253     }
2254 
2255     // nXAlign - abs. Position, Left,  Centered,  Right,  Inside, Outside
2256     // nYAlign - abs. Position, Top,   Centered,  Bottom, Inside, Outside
2257 
2258     // nXRelTo - Page printable area, Page,  Column,    Character
2259     // nYRelTo - Page printable area, Page,  Paragraph, Line
2260 
2261     const sal_uInt32 nCntXAlign = 6;
2262     const sal_uInt32 nCntYAlign = 6;
2263 
2264     const sal_uInt32 nCntRelTo  = 4;
2265 
2266 	sal_uInt32 nXAlign = nCntXAlign > pRecord->nXAlign ? pRecord->nXAlign : 1;
2267 	sal_uInt32 nYAlign = nCntYAlign > pRecord->nYAlign ? pRecord->nYAlign : 1;
2268 
2269 	if (pFSPA)
2270 	{
2271 		/*
2272 		#74188# #i15718# #i19008#
2273 		Strangely in this case the FSPA value seems to be considered before
2274 		the newer escher nXRelTo record.
2275 		*/
2276         // --> OD 2005-08-04 #i52565# - correct condition checking:
2277         // first check, if <nXRelTo> and <nYRelTo> have default values.  This
2278         // is a hint that these values aren't set by the escher import - see
2279         // method <SwMSDffManager::ProcessObj(..)>. Then, check if for each
2280         // values, if it differs from the one in the FSPA.
2281         if ( pRecord->nXRelTo == 2 && pRecord->nYRelTo == 2 )
2282         {
2283             // if <nYRelTo> differs from <FSPA.nby> overwrite <nYRelTo>
2284             if ( pFSPA->nby != pRecord->nYRelTo )
2285             {
2286                 pRecord->nYRelTo = pFSPA->nby;
2287             }
2288         }
2289         // <--
2290 	}
2291 
2292     sal_uInt32 nXRelTo = nCntRelTo > pRecord->nXRelTo ? pRecord->nXRelTo : 1;
2293     sal_uInt32 nYRelTo = nCntRelTo > pRecord->nYRelTo ? pRecord->nYRelTo : 1;
2294 
2295     // --> OD 2005-03-03 #i43718#
2296     RndStdIds eAnchor = IsInlineEscherHack() ? FLY_AS_CHAR : FLY_AT_CHAR;
2297     // <--
2298 
2299     SwFmtAnchor aAnchor( eAnchor );
2300 	aAnchor.SetAnchor( pPaM->GetPoint() );
2301 	rFlySet.Put( aAnchor );
2302 
2303     if (pFSPA)
2304 	{
2305         // OD 14.10.2003 #i18732#
2306         //Given new layout where everything is changed to be anchored to
2307         //character the following 4 tables may need to be changed.
2308 
2309         // horizontal Adjustment
2310         static const sal_Int16 aHoriOriTab[ nCntXAlign ] =
2311         {
2312             text::HoriOrientation::NONE,     // From left position
2313             text::HoriOrientation::LEFT,     // left
2314             text::HoriOrientation::CENTER,   // centered
2315             text::HoriOrientation::RIGHT,    // right
2316             // --> OD 2004-12-06 #i36649#
2317             // - inside -> text::HoriOrientation::LEFT and outside -> text::HoriOrientation::RIGHT
2318             text::HoriOrientation::LEFT,   // inside
2319             text::HoriOrientation::RIGHT   // outside
2320             // <--
2321         };
2322 
2323 
2324         // generic vertical Adjustment
2325         static const sal_Int16 aVertOriTab[ nCntYAlign ] =
2326         {
2327             text::VertOrientation::NONE,         // From Top position
2328             text::VertOrientation::TOP,          // top
2329             text::VertOrientation::CENTER,       // centered
2330             text::VertOrientation::BOTTOM,       // bottom
2331             text::VertOrientation::LINE_TOP,     // inside (obscure)
2332             text::VertOrientation::LINE_BOTTOM   // outside (obscure)
2333         };
2334 
2335         // CMC,OD 24.11.2003 #i22673# - to-line vertical alignment
2336         static const sal_Int16 aToLineVertOriTab[ nCntYAlign ] =
2337         {
2338             text::VertOrientation::NONE,         // below
2339             text::VertOrientation::LINE_BOTTOM,  // top
2340             text::VertOrientation::LINE_CENTER,  // centered
2341             text::VertOrientation::LINE_TOP,     // bottom
2342             text::VertOrientation::LINE_BOTTOM,  // inside (obscure)
2343             text::VertOrientation::LINE_TOP      // outside (obscure)
2344         };
2345 
2346         // Adjustment is horizontally relative to...
2347         static const sal_Int16 aHoriRelOriTab[nCntRelTo] =
2348         {
2349             text::RelOrientation::PAGE_PRINT_AREA,    // 0 is page textarea margin
2350             text::RelOrientation::PAGE_FRAME,  // 1 is page margin
2351             text::RelOrientation::FRAME,         // 2 is relative to column
2352             text::RelOrientation::CHAR       // 3 is relative to character
2353         };
2354 
2355         // Adjustment is vertically relative to...
2356         // CMC, OD 24.11.2003 #i22673# - adjustment for new vertical alignment
2357         // at top of line.
2358         static const sal_Int16 aVertRelOriTab[nCntRelTo] =
2359         {
2360             text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
2361             text::RelOrientation::PAGE_FRAME,   // 1 is page margin
2362             text::RelOrientation::FRAME,          // 2 is relative to paragraph
2363             text::RelOrientation::TEXT_LINE   // 3 is relative to line
2364         };
2365 
2366         sal_Int16 eHoriOri = aHoriOriTab[ nXAlign ];
2367         sal_Int16 eHoriRel = aHoriRelOriTab[  nXRelTo ];
2368 
2369         // --> OD 2004-12-06 #i36649# - adjustments for certain alignments
2370         if ( eHoriOri == text::HoriOrientation::LEFT && eHoriRel == text::RelOrientation::PAGE_FRAME )
2371         {
2372             // convert 'left to page' to 'from left -<width> to page text area'
2373             eHoriOri = text::HoriOrientation::NONE;
2374             eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
2375             const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
2376             pFSPA->nXaLeft = -nWidth;
2377             pFSPA->nXaRight = 0;
2378         }
2379         else if ( eHoriOri == text::HoriOrientation::RIGHT && eHoriRel == text::RelOrientation::PAGE_FRAME )
2380         {
2381             // convert 'right to page' to 'from left 0 to right page border'
2382             eHoriOri = text::HoriOrientation::NONE;
2383             eHoriRel = text::RelOrientation::PAGE_RIGHT;
2384             const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
2385             pFSPA->nXaLeft = 0;
2386             pFSPA->nXaRight = nWidth;
2387         }
2388         // <--
2389 
2390         // --> OD 2005-02-07 #i24255# - position of floating screen objects in
2391         // R2L layout are given in L2R layout, thus convert them of all
2392         // floating screen objects, which are imported.
2393         {
2394             //#109311# Miserable miserable hack.
2395             SwTwips nWidth = (pFSPA->nXaRight - pFSPA->nXaLeft);
2396             SwTwips nLeft = pFSPA->nXaLeft;
2397             if (MiserableRTLGraphicsHack(nLeft, nWidth, eHoriOri,
2398                 eHoriRel))
2399             {
2400                 pFSPA->nXaLeft = nLeft;
2401                 pFSPA->nXaRight = pFSPA->nXaLeft + nWidth;
2402             }
2403         }
2404         // <--
2405 
2406         // --> OD 2005-01-20 #118546# - if the object is anchored inside
2407         // a table cell, is horizontal aligned at frame|character and
2408         // has wrap through, but its attribute 'layout in table cell' isn't set,
2409         // convert its horizontal alignment to page text area.
2410         // --> OD 2008-04-10 #i84783# - use new method <IsObjectLayoutInTableCell()>
2411         if ( nInTable &&
2412              ( eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR ) &&
2413              pFSPA->nwr == 3 &&
2414 //             pRecord->nLayoutInTableCell == 0x80000000 )
2415              !IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ) )
2416         {
2417             eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
2418         }
2419         // <--
2420 
2421         SwFmtHoriOrient aHoriOri(MakeSafePositioningValue(pFSPA->nXaLeft),
2422             eHoriOri, eHoriRel);
2423         if( 4 <= nXAlign )
2424             aHoriOri.SetPosToggle(true);
2425         rFlySet.Put( aHoriOri );
2426 
2427         //Writer honours this wrap distance when aligned as "left" or "right",
2428         //Word doesn't. Writer doesn't honour it when its "from left".
2429         if (eHoriOri == text::HoriOrientation::LEFT)
2430             pRecord->nDxWrapDistLeft=0;
2431         else if (eHoriOri == text::HoriOrientation::RIGHT)
2432             pRecord->nDxWrapDistRight=0;
2433 
2434         sal_Int16 eVertRel;
2435         // OD 14.10.2003 #i18732#
2436         eVertRel = aVertRelOriTab[  nYRelTo ];
2437         // CMC, OD 24.11.2003 #i22673# - fill <eVertOri> in dependence of <eVertRel>
2438         sal_Int16 eVertOri;
2439         if ( eVertRel == text::RelOrientation::TEXT_LINE )
2440         {
2441             eVertOri = aToLineVertOriTab[ nYAlign ];
2442         }
2443         else
2444         {
2445             eVertOri = aVertOriTab[ nYAlign ];
2446         }
2447 
2448         //Below line in word is a positive value, while in writer its
2449         //negative
2450         long nYPos = pFSPA->nYaTop;
2451         // CMC, OD 24.11.2003 #i22673#
2452         if ((eVertRel == text::RelOrientation::TEXT_LINE) && (eVertOri == text::VertOrientation::NONE))
2453             nYPos = -nYPos;
2454 
2455         rFlySet.Put(SwFmtVertOrient(MakeSafePositioningValue(nYPos),
2456             eVertOri, eVertRel));
2457 
2458         if (
2459             (pFSPA->nYaTop < 0) && (eVertOri == text::VertOrientation::NONE) &&
2460             ((eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR))
2461            )
2462         {
2463             maTracer.Log(sw::log::eNegativeVertPlacement);
2464         }
2465     }
2466 
2467     return eAnchor;
2468 }
2469 
2470 // --> OD 2008-04-10 #i84783#
2471 bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const
2472 {
2473     bool bIsObjectLayoutInTableCell = false;
2474 
2475     if ( bVer8 )
2476     {
2477         const sal_uInt16 nWWVersion = pWwFib->nProduct & 0xE000;
2478         switch ( nWWVersion )
2479         {
2480             case 0x0000: // version 8 aka Microsoft Word 97
2481             {
2482                 bIsObjectLayoutInTableCell = false;
2483                 ASSERT( nLayoutInTableCell == 0xFFFFFFFF,
2484                         "no explicit object attribute layout in table cell excepted." );
2485             }
2486             break;
2487             case 0x2000: // version 9 aka Microsoft Word 2000
2488             case 0x4000: // version 10 aka Microsoft Word 2002
2489             case 0x6000: // version 11 aka Microsoft Word 2003
2490             case 0x8000: // version 12 aka Microsoft Word 2007
2491             {
2492                 // --> OD 2009-01-13 #i98037#
2493                 // adjustment of conditions needed after deeper analysis of
2494                 // certain test cases.
2495                 if ( nLayoutInTableCell == 0xFFFFFFFF || // no explicit attribute value given
2496                      nLayoutInTableCell & 0x80008000 ||
2497                      ( nLayoutInTableCell & 0x02000000 &&
2498                        !(nLayoutInTableCell & 0x80000000 ) ) )
2499                 // <--
2500                 {
2501                     bIsObjectLayoutInTableCell = true;
2502                 }
2503                 else
2504                 {
2505                     bIsObjectLayoutInTableCell = false;
2506                 }
2507             }
2508             break;
2509             default:
2510             {
2511                 ASSERT( false,
2512                         "unknown version." );
2513             }
2514         }
2515     }
2516 
2517     return bIsObjectLayoutInTableCell;
2518 }
2519 // <--
2520 
2521 SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp )
2522 {
2523     if( nIniFlags & WW8FL_NO_GRAFLAYER )
2524         return 0;
2525 
2526     ::SetProgressState(nProgress, mpDocShell);     // Update
2527 
2528     nDrawCpO = pWwFib->GetBaseCp(pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX);
2529 
2530     GrafikCtor();
2531 
2532     WW8PLCFspecial* pPF = pPlcxMan->GetFdoa();
2533     if( !pPF )
2534     {
2535         ASSERT( !this, "Where is the grapic (1) ?" );
2536         return 0;
2537     }
2538 
2539     if( bVer67 )
2540     {
2541         long nOldPos = pStrm->Tell();
2542 
2543         nDrawXOfs = nDrawYOfs = 0;
2544         ReadGrafLayer1( pPF, nGrafAnchorCp );
2545 
2546         pStrm->Seek( nOldPos );
2547         return 0;
2548     }
2549 
2550     //Normal case of Word 8+ version stuff
2551     pPF->SeekPos( nGrafAnchorCp );
2552 
2553     WW8_FC nStartFc;
2554     void* pF0;
2555     if( !pPF->Get( nStartFc, pF0 ) ){
2556         ASSERT( !this, "+Wo ist die Grafik (2) ?" );
2557         return 0;
2558     }
2559 
2560     WW8_FSPA_SHADOW* pFS = (WW8_FSPA_SHADOW*)pF0;
2561     WW8_FSPA*        pF;
2562 #ifdef __WW8_NEEDS_COPY
2563     WW8_FSPA aFSFA;
2564     pF = &aFSFA;
2565     WW8FSPAShadowToReal( pFS, pF );
2566 #else
2567     pF = (WW8_FSPA*)pFS;
2568 #endif // defined __WW8_NEEDS_COPY
2569     if( !pF->nSpId )
2570     {
2571         ASSERT( !this, "+Wo ist die Grafik (3) ?" );
2572         return 0;
2573     }
2574 
2575     if (!pMSDffManager->GetModel())
2576          pMSDffManager->SetModel(pDrawModel, 1440);
2577 
2578 
2579     Rectangle aRect(pF->nXaLeft,  pF->nYaTop, pF->nXaRight, pF->nYaBottom);
2580     SvxMSDffImportData aData( aRect );
2581 
2582     /*
2583     #i20540#
2584     The SdrOle2Obj will try and manage any ole objects it finds, causing all
2585     sorts of trouble later on
2586     */
2587     SwDocShell* pPersist = rDoc.GetDocShell();
2588     rDoc.SetDocShell(0);         //#i20540# Persist guard
2589 
2590     SdrObject* pObject = 0;
2591     bool bOk = (pMSDffManager->GetShape(pF->nSpId, pObject, aData) && pObject);
2592 
2593     rDoc.SetDocShell(pPersist);  //#i20540# Persist guard
2594 
2595     if (!bOk)
2596     {
2597         ASSERT( !this, "Where is the Shape ?" );
2598         return 0;
2599     }
2600 
2601     bool bDone = false;
2602     SdrObject* pOurNewObject = 0;
2603     bool bReplaceable = false;
2604 
2605     switch (SdrObjKind(pObject->GetObjIdentifier()))
2606     {
2607         case OBJ_GRAF:
2608             bReplaceable = true;
2609             bDone = true;
2610             break;
2611         case OBJ_OLE2:
2612             bReplaceable = true;
2613             break;
2614         default:
2615             break;
2616 
2617     }
2618 
2619     // OD 14.10.2003 - keep wrapping of objects in page header/footer.
2620     /*
2621     //#108778# when in a header or footer word appears to treat all elements
2622     //are wrap through
2623     if (bIsHeader || bIsFooter)
2624         pF->nwr = 3;
2625     */
2626 
2627     // Umfluss-Modus ermitteln
2628     SfxItemSet aFlySet(rDoc.GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
2629     SwSurround eSurround = SURROUND_PARALLEL;
2630     bool bContour = false;
2631     switch (pF->nwr)
2632     {
2633         case 0: //0 like 2, but doesn't require absolute object
2634         case 2: //2 wrap around absolute object
2635             eSurround = SURROUND_PARALLEL;
2636             break;
2637         case 1: //1 no text next to shape
2638             eSurround = SURROUND_NONE;
2639             break;
2640         case 3: //3 wrap as if no object present
2641             eSurround = SURROUND_THROUGHT;
2642             break;
2643         case 4: //4 wrap tightly around object
2644         case 5: //5 wrap tightly, but allow holes
2645             eSurround = SURROUND_PARALLEL;
2646             bContour = true;
2647             break;
2648     }
2649 
2650     // bei Modus 2 oder 4 auch den Zusatzparameter beruecksichtigen
2651     if ( (2 == pF->nwr) || (4 == pF->nwr) )
2652     {
2653         switch( pF->nwrk )
2654         {
2655             //0 wrap both sides
2656             case 0:
2657                 eSurround = SURROUND_PARALLEL;
2658                 break;
2659             //1 wrap only on left
2660             case 1:
2661                 eSurround = SURROUND_LEFT;
2662                 break;
2663             //2 wrap only on right
2664             case 2:
2665                 eSurround = SURROUND_RIGHT;
2666                 break;
2667             //3 wrap only on largest side
2668             case 3:
2669                 eSurround = SURROUND_IDEAL;
2670                 break;
2671         }
2672     }
2673 
2674     SwFmtSurround aSur( eSurround );
2675     aSur.SetContour( bContour );
2676     aSur.SetOutside(true); // Winword kann nur Aussen-Konturen
2677     aFlySet.Put( aSur );
2678 
2679     // eingelesenes Objekt (kann eine ganze Gruppe sein) jetzt korrekt
2680     // positionieren usw.
2681 
2682     ASSERT(!((aData.GetRecCount() != 1) && bReplaceable),
2683         "Replaceable drawing with > 1 entries ?");
2684 
2685     if (aData.GetRecCount() != 1)
2686         bReplaceable = false;
2687 
2688     SvxMSDffImportRec* pRecord = 0;
2689     /*
2690         Get the record for top level object, so we can get the word anchoring
2691         and wrapping information for it.
2692     */
2693     sal_uInt16 nRecCount = aData.GetRecCount();
2694     for (sal_uInt16 nTxbx=0; nTxbx < nRecCount; ++nTxbx )
2695     {
2696         pRecord = aData.GetRecord( nTxbx );
2697         if (pRecord && pRecord->pObj == pObject)
2698             break;
2699         else
2700             pRecord = 0;
2701     }
2702 
2703     ASSERT(pRecord, "how did that happen?");
2704     if (!pRecord)
2705         return 0;
2706 
2707     // --> OD 2008-04-10 #i84783#
2708 //    //cmc: We're in a table, and the element has the magic Word XP bit set
2709 //    //to enable layout inside a cell
2710 //    // --> OD 2005-08-10 #124714# - undo change made for issue #i33442#
2711 //    bool bLayoutInTableCell = ( nInTable &&
2712 //                                pRecord->nLayoutInTableCell & 0x00008000 );
2713 //    // <--
2714     const bool bLayoutInTableCell =
2715         nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell );
2716     // <--
2717 
2718     // OD 14.10.2003 #i18732#
2719     // Switch on 'follow text flow',
2720     // if object is laid out inside table cell and
2721     // its wrapping isn't 'SURROUND_THROUGH'
2722     if (bLayoutInTableCell && eSurround != SURROUND_THROUGHT)
2723     {
2724         SwFmtFollowTextFlow aFollowTextFlow( sal_True );
2725         aFlySet.Put( aFollowTextFlow );
2726     }
2727 
2728 
2729     //#i21847#
2730     //Some shapes are set to *hidden*, don't import those ones.
2731     if (pRecord->bHidden)
2732         return 0;
2733 
2734     // If we are to be "below text" then we are not to be opaque
2735     // #i14045# MM If we are in a header or footer then make the object transparent
2736     // Not exactly like word but close enough for now
2737 
2738     // --> OD 2005-03-07 #b6234902# - both flags <bBelowText> and <bDrawHell>
2739     // have to be set to move object into the background.
2740     // --> OD 2005-04-11 #i46794# - it reveals that value of flag <bBelowText>
2741     // can be neglected.
2742     const bool bMoveToBackgrd = pRecord->bDrawHell ||
2743                                 ( ( bIsHeader || bIsFooter ) && pF->nwr == 3 );
2744     if ( bMoveToBackgrd )
2745         aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false));
2746 
2747     String aObjName = pObject->GetName();
2748 
2749     SwFrmFmt* pRetFrmFmt = 0;
2750     if (bReplaceable)
2751     {
2752         //Single graphics or ole objects
2753         pRetFrmFmt = ImportReplaceableDrawables(pObject, pOurNewObject, pRecord,
2754             pF, aFlySet);
2755     }
2756     else
2757     {
2758         //Drawing objects, (e.g. ovals or drawing groups)
2759         if (pF->bRcaSimple)
2760         {
2761             pF->nbx = WW8_FSPA::RelPageBorder;
2762             pF->nby = WW8_FSPA::RelPageBorder;
2763         }
2764 
2765         RndStdIds eAnchor = ProcessEscherAlign(pRecord, pF, aFlySet,
2766             bReplaceable);
2767 
2768         // Should we, and is it possible to make this into a writer textbox
2769         if ((!(nIniFlags1 & WW8FL_NO_FLY_FOR_TXBX)) && pRecord->bReplaceByFly)
2770         {
2771             pRetFrmFmt = ConvertDrawTextToFly(pObject, pOurNewObject, pRecord,
2772                 eAnchor, pF, aFlySet);
2773             if (pRetFrmFmt)
2774                 bDone = true;
2775         }
2776 
2777         if (!bDone)
2778         {
2779             sw::util::SetLayer aSetLayer(rDoc);
2780             if ( bMoveToBackgrd )
2781                 aSetLayer.SendObjectToHell(*pObject);
2782             else
2783                 aSetLayer.SendObjectToHeaven(*pObject);
2784 
2785             if (!IsInlineEscherHack())
2786             {
2787                 /*
2788                 #97824#  Need to make sure that the correct layer ordering is
2789                 applied.
2790                 */
2791                 // --> OD 2004-12-13 #117915# - pass information, if object
2792                 // is in page header|footer to method.
2793                 pWWZOrder->InsertEscherObject( pObject, pF->nSpId,
2794                                                bIsHeader || bIsFooter );
2795                 // <--
2796             }
2797             else
2798             {
2799                 pWWZOrder->InsertTextLayerObject(pObject);
2800             }
2801 
2802             pRetFrmFmt = rDoc.Insert(*pPaM, *pObject, &aFlySet, NULL);
2803 
2804             ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() ==
2805                 eAnchor, "Not the anchor type requested!");
2806 
2807             /*
2808                 Insert text if necessary into textboxes contained in groups.
2809             */
2810             if (aData.HasRecords())
2811             {
2812                 sal_uInt16 nCount = aData.GetRecCount();
2813                 for (sal_uInt16 nTxbx=0; nTxbx < nCount; ++nTxbx)
2814                 {
2815                     pRecord = aData.GetRecord(nTxbx);
2816                     if (pRecord && pRecord->pObj && pRecord->aTextId.nTxBxS)
2817                     { // #i52825# pRetFrmFmt can be NULL
2818                         pRetFrmFmt = MungeTextIntoDrawBox(pRecord->pObj,
2819                             pRecord, nGrafAnchorCp, pRetFrmFmt);
2820                     }
2821                 }
2822             }
2823         }
2824     }
2825 
2826     // --> OD 2005-03-11 #i44344#, #i44681# - positioning attributes already set
2827     if ( pRetFrmFmt /*#i52825# */ && pRetFrmFmt->ISA(SwDrawFrmFmt) )
2828     {
2829         static_cast<SwDrawFrmFmt*>(pRetFrmFmt)->PosAttrSet();
2830     }
2831     // <--
2832     if (!IsInlineEscherHack())
2833         MapWrapIntoFlyFmt(pRecord, pRetFrmFmt);
2834 
2835     // Set frame name with object name
2836     if( aObjName.Len() )
2837         pRetFrmFmt->SetName( aObjName );
2838     return AddAutoAnchor(pRetFrmFmt);
2839 }
2840 
2841 SwFrmFmt *SwWW8ImplReader::AddAutoAnchor(SwFrmFmt *pFmt)
2842 {
2843     if (pFmt && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
2844     {
2845         sal_uInt16 nTextAreaWidth = static_cast< sal_uInt16 >( maSectionManager.GetPageWidth() -
2846             maSectionManager.GetPageRight() - maSectionManager.GetPageLeft());
2847 
2848         if (pFmt->GetFrmSize().GetSize().Width() > nTextAreaWidth)
2849             maTracer.Log(sw::log::eTooWideAsChar);
2850     }
2851 
2852     /*
2853      * anchored to character at the current position will move along the
2854      * paragraph as text is added because we are at the insertion point.
2855      *
2856      * Leave to later and set the correct location then.
2857      */
2858     if ((pFmt) && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
2859     {
2860         pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFmt);
2861     }
2862     return pFmt;
2863 }
2864 
2865 SwFrmFmt* SwWW8ImplReader::MungeTextIntoDrawBox(SdrObject* pTrueObject,
2866     SvxMSDffImportRec *pRecord, long nGrafAnchorCp, SwFrmFmt* pRetFrmFmt)
2867 {
2868     SdrTextObj* pSdrTextObj;
2869 
2870     // Pruefen, ob Gruppenobjekt (z.B. zwei Klammern) vorliegt
2871     if (SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pRecord->pObj))
2872     {
2873         // Gruppenobjekte haben keinen Text. Fuege ein Textobjekt in die
2874         // Gruppe ein, um den Text zu halten.
2875         pSdrTextObj = new SdrRectObj( OBJ_TEXT, pThisGroup->GetCurrentBoundRect());
2876 
2877         SfxItemSet aSet(pDrawModel->GetItemPool());
2878         aSet.Put(XFillStyleItem(XFILL_NONE));
2879         aSet.Put(XLineStyleItem(XLINE_NONE));
2880         aSet.Put(SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ));
2881         aSet.Put(SdrTextAutoGrowHeightItem(false));
2882         aSet.Put(SdrTextAutoGrowWidthItem(false));
2883         pSdrTextObj->SetMergedItemSet(aSet);
2884 
2885         long nAngle = pRecord->nTextRotationAngle;
2886         if ( nAngle )
2887         {
2888             double a = nAngle*nPi180;
2889             pSdrTextObj->NbcRotate(pSdrTextObj->GetCurrentBoundRect().Center(), nAngle,
2890                 sin(a), cos(a) );
2891         }
2892 
2893         pSdrTextObj->NbcSetLayer( pThisGroup->GetLayer() );
2894         pThisGroup->GetSubList()->NbcInsertObject(pSdrTextObj);
2895     }
2896     else
2897         pSdrTextObj = PTR_CAST(SdrTextObj, pRecord->pObj);
2898 
2899     if( pSdrTextObj )
2900     {
2901         Size aObjSize(pSdrTextObj->GetSnapRect().GetWidth(),
2902             pSdrTextObj->GetSnapRect().GetHeight());
2903 
2904         // Objekt ist Bestandteil einer Gruppe?
2905         SdrObject* pGroupObject = pSdrTextObj->GetUpGroup();
2906 
2907         sal_uInt32 nOrdNum = pSdrTextObj->GetOrdNum();
2908         bool bEraseThisObject;
2909         InsertTxbxText( pSdrTextObj, &aObjSize, pRecord->aTextId.nTxBxS,
2910             pRecord->aTextId.nSequence, nGrafAnchorCp, pRetFrmFmt,
2911             (pSdrTextObj != pTrueObject) || (0 != pGroupObject),
2912             bEraseThisObject, 0, 0, 0, 0, pRecord);
2913 
2914         // wurde dieses Objekt ersetzt ??
2915         if (bEraseThisObject)
2916         {
2917             if( pGroupObject || (pSdrTextObj != pTrueObject) )
2918             {
2919                 // Objekt wurde bereits (in der Gruppe und) der Drawing-Page
2920                 // durch ein neues SdrGrafObj ersetzt.
2921 
2922                 SdrObject* pNewObj = pGroupObject ?
2923                     pGroupObject->GetSubList()->GetObj(nOrdNum) : pTrueObject;
2924                 if (pSdrTextObj != pNewObj)
2925                 {
2926                     // Objekt in der Z-Order-Liste ersetzen
2927                     pMSDffManager->ExchangeInShapeOrder(pSdrTextObj, 0,0, pNewObj);
2928                     // Objekt jetzt noch loeschen
2929                     SdrObject::Free( pRecord->pObj );
2930                     // und das neue Objekt merken.
2931                     pRecord->pObj = pNewObj;
2932                 }
2933             }
2934             else
2935             {
2936                 // Objekt aus der Z-Order-Liste loeschen
2937                 pMSDffManager->RemoveFromShapeOrder( pSdrTextObj );
2938                 // Objekt aus der Drawing-Page rausnehmen
2939                 if( pSdrTextObj->GetPage() )
2940                     pDrawPg->RemoveObject( pSdrTextObj->GetOrdNum() );
2941                 // und FrameFormat entfernen, da durch Grafik ersetzt (dies
2942                 // loescht auch das Objekt)
2943                 rDoc.DelFrmFmt( pRetFrmFmt );
2944                 pRetFrmFmt = 0;
2945                 // auch den Objektmerker loeschen
2946                 pRecord->pObj = 0;
2947             }
2948         }
2949         else
2950         {
2951             // ww8-default Randabstand einsetzen
2952             SfxItemSet aItemSet(pDrawModel->GetItemPool(),
2953                 SDRATTR_TEXT_LEFTDIST, SDRATTR_TEXT_LOWERDIST);
2954             aItemSet.Put( SdrTextLeftDistItem( pRecord->nDxTextLeft ) );
2955             aItemSet.Put( SdrTextRightDistItem( pRecord->nDxTextRight  ) );
2956             aItemSet.Put( SdrTextUpperDistItem( pRecord->nDyTextTop    ) );
2957             aItemSet.Put( SdrTextLowerDistItem( pRecord->nDyTextBottom ) );
2958             pSdrTextObj->SetMergedItemSetAndBroadcast(aItemSet);
2959         }
2960     }
2961     return pRetFrmFmt;
2962 }
2963 
2964 SwFlyFrmFmt* SwWW8ImplReader::ConvertDrawTextToFly(SdrObject* &rpObject,
2965     SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, RndStdIds eAnchor,
2966     WW8_FSPA *pF, SfxItemSet &rFlySet)
2967 {
2968     SwFlyFrmFmt* pRetFrmFmt = 0;
2969     long nStartCp;
2970     long nEndCp;
2971 
2972     // Pruefen, ob in dieser Textbox-Kette denn Text enthalten ist.  (
2973     // Umwandeln einer leeren Kette in Rahmen waere Unsinn. )
2974     if ( TxbxChainContainsRealText(pRecord->aTextId.nTxBxS,nStartCp,nEndCp) )
2975     {
2976         // Der Text wird nicht in das SdrTextObj eingelesen!  Stattdessen wird
2977         // ein Rahmen eingefuegt und der Text von nStartCp bis nEndCp dort
2978         // hinein gelesen.
2979         //
2980         // Vorteil: im Rahmen sind viel mehr Attribute moeglich als in der
2981         // Edit-Enging, und es koennen auch Felder, OLEs oder Grafiken darin
2982         // sein...
2983 
2984         Rectangle aInnerDist(pRecord->nDxTextLeft, pRecord->nDyTextTop,
2985             pRecord->nDxTextRight, pRecord->nDyTextBottom);
2986 
2987         SwFmtFrmSize aFrmSize(ATT_FIX_SIZE, pF->nXaRight - pF->nXaLeft, pF->nYaBottom - pF->nYaTop);
2988         aFrmSize.SetWidthSizeType(pRecord->bAutoWidth ? ATT_VAR_SIZE : ATT_FIX_SIZE);
2989         rFlySet.Put(aFrmSize);
2990 
2991         MatchSdrItemsIntoFlySet( rpObject, rFlySet, pRecord->eLineStyle,
2992             pRecord->eShapeType, aInnerDist );
2993 
2994 
2995         SdrTextObj *pSdrTextObj = PTR_CAST(SdrTextObj, rpObject);
2996         if (pSdrTextObj && pSdrTextObj->IsVerticalWriting())
2997             rFlySet.Put(SvxFrameDirectionItem(FRMDIR_VERT_TOP_RIGHT, RES_FRAMEDIR));
2998 
2999         pRetFrmFmt = rDoc.MakeFlySection(eAnchor, pPaM->GetPoint(), &rFlySet);
3000         ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() == eAnchor,
3001             "Not the anchor type requested!");
3002 
3003         // falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste
3004         // entsprechend korrigieren (oder Eintrag loeschen)
3005         rpOurNewObject = CreateContactObject(pRetFrmFmt);
3006 
3007         // altes Objekt aus der Z-Order-Liste entfernen
3008         pMSDffManager->RemoveFromShapeOrder( rpObject );
3009 
3010         // und das Objekt loeschen
3011         SdrObject::Free( rpObject );
3012         /*
3013             Achtung: ab jetzt nur noch pOrgShapeObject
3014             abfragen!
3015         */
3016 
3017         if (rpOurNewObject)
3018         {
3019             /*
3020             #96375#
3021             We do not store our rpOutNewObject in the ShapeOrder because we
3022             have a FrmFmt from which we can regenerate the contact object when
3023             we need it. Because, we can have frames anchored to paragraphs in
3024             header/footers and we can copy header/footers, if we do copy a
3025             header/footer with a nonpage anchored frame in it then the contact
3026             objects are invalidated. Under this condition the FrmFmt will be
3027             updated to reflect this change and can be used to get a new
3028             contact object, while a raw rpOutNewObject stored here becomes
3029             deleted and useless.
3030             */
3031             pMSDffManager->StoreShapeOrder(pF->nSpId,
3032                 (((sal_uLong)pRecord->aTextId.nTxBxS) << 16) +
3033                 pRecord->aTextId.nSequence, 0, pRetFrmFmt);
3034 
3035             // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit
3036             // in SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden
3037             // kann !!!
3038             if (!rpOurNewObject->IsInserted())
3039             {
3040                 // --> OD 2004-12-13 #117915# - pass information, if object
3041                 // is in page header|footer to method.
3042                 pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
3043                                                bIsHeader || bIsFooter );
3044                 // <--
3045             }
3046         }
3047 
3048         // Box-0 erhaelt den Text fuer die ganze Kette!
3049         if( !pRecord->aTextId.nSequence )
3050         {
3051             // rette Flags u.ae. und setze sie zurueck
3052             WW8ReaderSave aSave( this );
3053 
3054             MoveInsideFly(pRetFrmFmt);
3055 
3056             SwNodeIndex aStart(pPaM->GetPoint()->nNode);
3057 
3058             pWWZOrder->InsideEscher(pF->nSpId);
3059 
3060             // lies den Text ein
3061             bTxbxFlySection = true;
3062             bool bJoined = ReadText(nStartCp, (nEndCp-nStartCp),
3063                 MAN_MAINTEXT == pPlcxMan->GetManType() ?
3064                         MAN_TXBX : MAN_TXBX_HDFT);
3065 
3066             pWWZOrder->OutsideEscher();
3067 
3068             MoveOutsideFly(pRetFrmFmt, aSave.GetStartPos(),!bJoined);
3069 
3070             aSave.Restore( this );
3071         }
3072     }
3073     return pRetFrmFmt;
3074 }
3075 
3076 void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord,
3077     SfxItemSet &rFlySet)
3078 {
3079     if (rRecord.bVFlip || rRecord.bHFlip)
3080     {
3081         MirrorGraph eType(RES_MIRROR_GRAPH_DONT);
3082         if (rRecord.bVFlip && rRecord.bHFlip)
3083             eType = RES_MIRROR_GRAPH_BOTH;
3084         else if (rRecord.bVFlip)
3085             eType = RES_MIRROR_GRAPH_HOR;
3086         else
3087             eType = RES_MIRROR_GRAPH_VERT;
3088         rFlySet.Put( SwMirrorGrf(eType) );
3089     }
3090 }
3091 
3092 SwFlyFrmFmt* SwWW8ImplReader::ImportReplaceableDrawables( SdrObject* &rpObject,
3093     SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF,
3094     SfxItemSet &rFlySet )
3095 {
3096     SwFlyFrmFmt* pRetFrmFmt = 0;
3097     long nWidthTw  = pF->nXaRight - pF->nXaLeft;
3098     if (0 > nWidthTw)
3099         nWidthTw = 0;
3100     long nHeightTw = pF->nYaBottom - pF->nYaTop;
3101     if (0 > nHeightTw)
3102         nHeightTw = 0;
3103 
3104     ProcessEscherAlign(pRecord, pF, rFlySet, true);
3105 
3106     rFlySet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nWidthTw, nHeightTw));
3107 
3108     SfxItemSet aGrSet(rDoc.GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1);
3109 
3110     if (pRecord)
3111     {
3112         //Note that the escher inner distance only seems to be honoured in
3113         //word for textboxes, not for graphics and ole objects.
3114         Rectangle aInnerDist(0, 0, 0, 0);
3115 
3116         MatchSdrItemsIntoFlySet(rpObject, rFlySet, pRecord->eLineStyle,
3117             pRecord->eShapeType, aInnerDist);
3118 
3119         MatchEscherMirrorIntoFlySet(*pRecord, aGrSet);
3120     }
3121 
3122     String aObjectName(rpObject->GetName());
3123     if (OBJ_OLE2 == SdrObjKind(rpObject->GetObjIdentifier()))
3124         pRetFrmFmt = InsertOle(*((SdrOle2Obj*)rpObject), rFlySet, aGrSet);
3125     else
3126     {
3127         const SdrGrafObj *pGrf= (const SdrGrafObj*)rpObject;
3128         bool bDone = false;
3129         if (pGrf->IsLinkedGraphic() && pGrf->GetFileName().Len())
3130         {
3131             GraphicType eType = pGrf->GetGraphicType();
3132             String aGrfName(
3133                 URIHelper::SmartRel2Abs(
3134                     INetURLObject(sBaseURL), pGrf->GetFileName(),
3135                     URIHelper::GetMaybeFileHdl()));
3136             // --> OD 2005-07-04 #124117# - correction of fix for issue #i10939#:
3137             // One of the two conditions have to be true to insert the graphic
3138             // as a linked graphic -
3139             if (GRAPHIC_NONE == eType || CanUseRemoteLink(aGrfName))
3140             // <--
3141             {
3142                 pRetFrmFmt = rDoc.Insert(*pPaM, aGrfName, aEmptyStr, 0,
3143                     &rFlySet, &aGrSet, NULL);
3144                 bDone = true;
3145             }
3146         }
3147         if (!bDone)
3148         {
3149             const Graphic& rGraph = pGrf->GetGraphic();
3150             pRetFrmFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &rGraph,
3151                 &rFlySet, &aGrSet, NULL);
3152         }
3153     }
3154 
3155     if (pRetFrmFmt)
3156     {
3157         if( pRecord )
3158         {
3159             if( OBJ_OLE2 != SdrObjKind(rpObject->GetObjIdentifier()) )
3160                 SetAttributesAtGrfNode( pRecord, pRetFrmFmt, pF );
3161         }
3162         // mehrfaches Auftreten gleicher Grafik-Namen vermeiden
3163         maGrfNameGenerator.SetUniqueGraphName(pRetFrmFmt, aObjectName);
3164     }
3165     //falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste
3166     //entsprechend korrigieren (oder Eintrag loeschen)
3167     rpOurNewObject = CreateContactObject(pRetFrmFmt);
3168 
3169     // altes Objekt aus der Z-Order-Liste entfernen
3170     pMSDffManager->RemoveFromShapeOrder( rpObject );
3171     // aus der Drawing-Page rausnehmen
3172     if( rpObject->GetPage() )
3173         pDrawPg->RemoveObject( rpObject->GetOrdNum() );
3174 
3175     // und das Objekt loeschen
3176     SdrObject::Free( rpObject );
3177     /*
3178         Achtung: ab jetzt nur noch pOrgShapeObject abfragen!
3179     */
3180 
3181     // Kontakt-Objekt in die Z-Order-Liste und die Page aufnehmen
3182     if (rpOurNewObject)
3183     {
3184         if (!bHdFtFtnEdn)
3185             pMSDffManager->StoreShapeOrder(pF->nSpId, 0, rpOurNewObject, 0 );
3186 
3187         // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit in
3188         // SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden kann !!!
3189         if (!rpOurNewObject->IsInserted())
3190         {
3191             // --> OD 2004-12-13 #117915# - pass information, if object
3192             // is in page header|footer to method.
3193             pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
3194                                            bIsHeader || bIsFooter );
3195             // <--
3196         }
3197     }
3198     return pRetFrmFmt;
3199 }
3200 
3201 void SwWW8ImplReader::GrafikCtor()  // Fuer SVDraw und VCControls und Escher
3202 {
3203     if (!pDrawModel)
3204     {
3205         // --> OD 2005-08-08 #i52858# - method name changed
3206         rDoc.GetOrCreateDrawModel();
3207         // <--
3208         pDrawModel  = rDoc.GetDrawModel();
3209         ASSERT(pDrawModel, "Kann DrawModel nicht anlegen");
3210         pDrawPg = pDrawModel->GetPage(0);
3211 
3212         pMSDffManager = new SwMSDffManager(*this);
3213         pMSDffManager->SetModel(pDrawModel, 1440);
3214         /*
3215          #79055#
3216          Now the dff manager always needs a controls //converter as well, but a
3217          control converter may still exist //without a dffmanager. cmc
3218         */
3219         pFormImpl = new SwMSConvertControls(mpDocShell, pPaM);
3220 
3221         pWWZOrder = new wwZOrderer(sw::util::SetLayer(rDoc), pDrawPg,
3222             pMSDffManager ? pMSDffManager->GetShapeOrders() : 0);
3223     }
3224 }
3225 
3226 void SwWW8ImplReader::GrafikDtor()
3227 {
3228     DELETEZ(mpDrawEditEngine); // evtl. von Grafik angelegt
3229     DELETEZ(pWWZOrder);       // dito
3230 }
3231 
3232 void SwWW8FltAnchorStack::AddAnchor(const SwPosition& rPos, SwFrmFmt *pFmt)
3233 {
3234     ASSERT(pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR,
3235         "Don't use fltanchors with inline frames, slap!");
3236     NewAttr(rPos, SwFltAnchor(pFmt));
3237 }
3238 
3239 void SwWW8FltAnchorStack::Flush()
3240 {
3241     sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count());
3242     for (sal_uInt16 i=0; i < nCnt; ++i)
3243     {
3244         SwFltStackEntry *pEntry = (*this)[i];
3245         SwPosition aDummy(pEntry->nMkNode);
3246         SetAttrInDoc(aDummy,pEntry);
3247         DeleteAndDestroy(i--);
3248         --nCnt;
3249     }
3250 }
3251 
3252 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
3253