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