xref: /aoo41x/main/sw/source/filter/ww8/ww8graf.cxx (revision 70d3707a)
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 || nPat > sizeof(nPatA))
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             rBox.SetLine(new SvxBorderLine( aLine ), nLine);
1669     }
1670 
1671     return nOutsideThick;
1672 }
1673 
1674 #define WW8ITEMVALUE(ItemSet,Id,Cast)  ((const Cast&)(ItemSet).Get(Id)).GetValue()
1675 
1676 void SwWW8ImplReader::MatchSdrItemsIntoFlySet( SdrObject* pSdrObj,
1677     SfxItemSet& rFlySet, MSO_LineStyle eLineStyle, MSO_SPT eShapeType,
1678     Rectangle& rInnerDist )
1679 {
1680 /*
1681     am Rahmen zu setzende Frame-Attribute
1682     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1683     SwFmtFrmSize            falls noch nicht gesetzt, hier setzen
1684     SvxLRSpaceItem          hier setzen
1685     SvxULSpaceItem          hier setzen
1686     SvxOpaqueItem           (Derzeit bei Rahmen nicht moeglich! khz 10.2.1999)
1687     SwFmtSurround           bereits gesetzt
1688     SwFmtVertOrient         bereits gesetzt
1689     SwFmtHoriOrient         bereits gesetzt
1690     SwFmtAnchor             bereits gesetzt
1691     SvxBoxItem              hier setzen
1692     SvxBrushItem            hier setzen
1693     SvxShadowItem           hier setzen
1694 */
1695 
1696     // 1. GrafikObjekt des Docs?
1697     GrafikCtor();
1698 
1699     const SfxItemSet& rOldSet = pSdrObj->GetMergedItemSet();
1700 
1701     // einige Items koennen direkt so uebernommen werden
1702     const sal_uInt16 nDirectMatch = 2;
1703     static RES_FRMATR __READONLY_DATA aDirectMatch[ nDirectMatch ] =
1704     {
1705         RES_LR_SPACE,   // Aussenabstand links/rechts: SvxLRSpaceItem
1706         RES_UL_SPACE    // Aussenabstand Oben/unten:   SvxULSpaceItem
1707     };
1708     const SfxPoolItem* pPoolItem;
1709     for(sal_uInt16 nItem = 0; nItem < nDirectMatch; ++nItem)
1710         if( SFX_ITEM_SET == rOldSet.GetItemState(
1711                     static_cast< sal_uInt16 >(aDirectMatch[ nItem ]), false, &pPoolItem) )
1712         {
1713             rFlySet.Put( *pPoolItem );
1714         }
1715 
1716 
1717     // jetzt die Umrandung berechnen und die Box bauen: Das Mass wird fuer die
1718     // Rahmen-GROESSE benoetigt!
1719     SvxBoxItem aBox(sw::util::ItemGet<SvxBoxItem>(rFlySet, RES_BOX));
1720     // dashed oder solid wird zu solid
1721     sal_Int32 nLineThick = 0, nOutside=0;
1722 
1723     // check if LineStyle is *really* set!
1724     const SfxPoolItem* pItem;
1725 
1726     SfxItemState eState = rOldSet.GetItemState(XATTR_LINESTYLE,true,&pItem);
1727     if( eState == SFX_ITEM_SET )
1728     {
1729         // Now, that we know there is a line style we will make use the
1730         // parameter given to us when calling the method...  :-)
1731         const Color aLineColor = static_cast< XLineColorItem const & >(
1732             rOldSet.Get(XATTR_LINECOLOR)).GetColorValue();
1733         nLineThick = WW8ITEMVALUE(rOldSet, XATTR_LINEWIDTH, XLineWidthItem);
1734 
1735         if( !nLineThick )
1736             nLineThick = 15; // WW-default: 0.75 pt
1737 
1738         nOutside = MatchSdrBoxIntoFlyBoxItem(aLineColor, eLineStyle,
1739             eShapeType, nLineThick, aBox);
1740     }
1741 
1742     rInnerDist.Left()+=nLineThick;
1743     rInnerDist.Top()+=nLineThick;
1744     rInnerDist.Right()+=nLineThick;
1745     rInnerDist.Bottom()+=nLineThick;
1746 
1747     const SvxBorderLine *pLine;
1748     if (0 != (pLine = aBox.GetLine(BOX_LINE_LEFT)))
1749     {
1750         rInnerDist.Left() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
1751             pLine->GetDistance());
1752     }
1753 
1754     if (0 != (pLine = aBox.GetLine(BOX_LINE_TOP)))
1755     {
1756         rInnerDist.Top() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
1757             pLine->GetDistance());
1758     }
1759 
1760     if (0 != (pLine = aBox.GetLine(BOX_LINE_RIGHT)))
1761     {
1762         rInnerDist.Right() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
1763             pLine->GetDistance());
1764     }
1765 
1766     if (0 != (pLine = aBox.GetLine(BOX_LINE_BOTTOM)))
1767     {
1768         rInnerDist.Bottom() -= (pLine->GetOutWidth() + pLine->GetInWidth() +
1769             pLine->GetDistance());
1770     }
1771 
1772     // set distances from box's border to text contained within the box
1773     if( 0 < rInnerDist.Left() )
1774         aBox.SetDistance( (sal_uInt16)rInnerDist.Left(), BOX_LINE_LEFT );
1775     if( 0 < rInnerDist.Top() )
1776         aBox.SetDistance( (sal_uInt16)rInnerDist.Top(), BOX_LINE_TOP );
1777     if( 0 < rInnerDist.Right() )
1778         aBox.SetDistance( (sal_uInt16)rInnerDist.Right(), BOX_LINE_RIGHT );
1779     if( 0 < rInnerDist.Bottom() )
1780         aBox.SetDistance( (sal_uInt16)rInnerDist.Bottom(), BOX_LINE_BOTTOM );
1781 
1782     bool bFixSize = !(WW8ITEMVALUE(rOldSet, SDRATTR_TEXT_AUTOGROWHEIGHT,
1783         SdrTextAutoGrowHeightItem));
1784 
1785     // Size: SwFmtFrmSize
1786     if( SFX_ITEM_SET != rFlySet.GetItemState(RES_FRM_SIZE, false) )
1787     {
1788         const Rectangle& rSnapRect = pSdrObj->GetSnapRect();
1789         // if necessary adapt width and position of the framework: The
1790         // recorded interior is to remain equally large despite thick edges.
1791         rFlySet.Put( SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
1792             rSnapRect.GetWidth()  + 2*nOutside,
1793             rSnapRect.GetHeight() + 2*nOutside) );
1794     }
1795     else //If a size is set, adjust it to consider border thickness
1796     {
1797         SwFmtFrmSize aSize = (const SwFmtFrmSize &)(rFlySet.Get(RES_FRM_SIZE));
1798 
1799         SwFmtFrmSize aNewSize = SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
1800             aSize.GetWidth()  + 2*nOutside,
1801             aSize.GetHeight() + 2*nOutside);
1802         aNewSize.SetWidthSizeType(aSize.GetWidthSizeType());
1803         rFlySet.Put( aNewSize );
1804     }
1805 
1806     //Sadly word puts escher borders outside the graphic, but orients the
1807     //graphic in relation to the top left inside the border. We don't
1808     if (nOutside)
1809     {
1810         SwFmtHoriOrient aHori = (const SwFmtHoriOrient &)(rFlySet.Get(
1811             RES_HORI_ORIENT));
1812         aHori.SetPos(MakeSafePositioningValue(aHori.GetPos()-nOutside));
1813         rFlySet.Put(aHori);
1814 
1815         SwFmtVertOrient aVert = (const SwFmtVertOrient &)(rFlySet.Get(
1816             RES_VERT_ORIENT));
1817         aVert.SetPos(aVert.GetPos()-nOutside);
1818         rFlySet.Put(aVert);
1819     }
1820 
1821     // jetzt die Umrandung setzen
1822     rFlySet.Put( aBox );
1823 
1824     // Schattenwurf der Box: SvxShadowItem
1825     if( WW8ITEMVALUE(rOldSet, SDRATTR_SHADOW, SdrShadowItem) )
1826     {
1827         SvxShadowItem aShadow( RES_SHADOW );
1828 
1829         const Color aShdColor = static_cast< SdrShadowColorItem const & >(
1830             rOldSet.Get(SDRATTR_SHADOWCOLOR)).GetColorValue();
1831         const sal_Int32 nShdDistX = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWXDIST,
1832             SdrShadowXDistItem);
1833         const sal_Int32 nShdDistY = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWYDIST,
1834             SdrShadowYDistItem);
1835         //const sal_uInt16 nShdTrans= WW8ITEMVALUE(rOldSet,
1836         //   SDRATTR_SHADOWTRANSPARENCE, SdrShadowTransparenceItem);
1837 
1838         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1839         //
1840         // SfxVoidItem( SDRATTR_SHADOW3D    )
1841         // SfxVoidItem( SDRATTR_SHADOWPERSP )
1842 
1843         aShadow.SetColor( Color( aShdColor ) );
1844 
1845         aShadow.SetWidth(writer_cast<sal_uInt16>((Abs( nShdDistX) +
1846             Abs( nShdDistY )) / 2 ));
1847 
1848         SvxShadowLocation eShdPosi;
1849         if( 0 <= nShdDistX )
1850         {
1851             if( 0 <= nShdDistY )
1852                 eShdPosi = SVX_SHADOW_BOTTOMRIGHT;
1853             else
1854                 eShdPosi = SVX_SHADOW_TOPRIGHT;
1855         }
1856         else
1857         {
1858             if( 0 <= nShdDistY )
1859                 eShdPosi = SVX_SHADOW_BOTTOMLEFT;
1860             else
1861                 eShdPosi = SVX_SHADOW_TOPLEFT;
1862         }
1863         aShadow.SetLocation( eShdPosi );
1864 
1865         rFlySet.Put( aShadow );
1866     }
1867     Color Temp(COL_WHITE);
1868     SvxBrushItem aBrushItem(Temp, RES_BACKGROUND);
1869     bool bBrushItemOk = false;
1870     sal_uInt8 nTrans = 0;
1871 
1872     //Seperate transparency
1873     eState = rOldSet.GetItemState(XATTR_FILLTRANSPARENCE, true, &pItem);
1874     if (eState == SFX_ITEM_SET)
1875     {
1876         sal_uInt16 nRes = WW8ITEMVALUE(rOldSet, XATTR_FILLTRANSPARENCE,
1877             XFillTransparenceItem);
1878         nTrans = sal_uInt8((nRes * 0xFE) / 100);
1879         aBrushItem.GetColor().SetTransparency(nTrans);
1880         bBrushItemOk = true;
1881     }
1882 
1883     // Hintergrund: SvxBrushItem
1884     eState = rOldSet.GetItemState(XATTR_FILLSTYLE, true, &pItem);
1885     if (eState == SFX_ITEM_SET)
1886     {
1887         const XFillStyle eFill = ((const XFillStyleItem*)pItem)->GetValue();
1888 
1889         switch (eFill)
1890         {
1891             case XFILL_NONE:
1892                 //Writer graphics don't have it yet
1893                 if (eShapeType != mso_sptPictureFrame)
1894                 {
1895                     aBrushItem.GetColor().SetTransparency(0xFE);
1896                     bBrushItemOk = true;
1897                 }
1898             break;
1899             case XFILL_SOLID:
1900                 {
1901                     const Color aColor = static_cast< XFillColorItem const & >(
1902                         rOldSet.Get(XATTR_FILLCOLOR)).GetColorValue();
1903                     aBrushItem.SetColor(aColor);
1904 
1905                     if (bBrushItemOk) //has trans
1906                         aBrushItem.GetColor().SetTransparency(nTrans);
1907 
1908                     bBrushItemOk = true;
1909                 }
1910             break;
1911             case XFILL_GRADIENT:
1912             break;
1913             case XFILL_HATCH:
1914             break;
1915             case XFILL_BITMAP:
1916                 {
1917                     GraphicObject aGrfObj(static_cast< XFillBitmapItem const & >(rOldSet.Get(XATTR_FILLBITMAP)).GetGraphicObject());
1918                     const bool bTile(WW8ITEMVALUE(rOldSet, XATTR_FILLBMP_TILE, SfxBoolItem) ? true: false);
1919 
1920                     if(bBrushItemOk) //has trans
1921                     {
1922                         GraphicAttr aAttr(aGrfObj.GetAttr());
1923 
1924                         aAttr.SetTransparency(nTrans);
1925                         aGrfObj.SetAttr(aAttr);
1926                     }
1927 
1928                     aBrushItem.SetGraphicObject(aGrfObj);
1929                     aBrushItem.SetGraphicPos(bTile ? GPOS_TILED : GPOS_AREA);
1930                     bBrushItemOk = true;
1931                 }
1932             break;
1933         }
1934     }
1935 
1936     if (bBrushItemOk)
1937         rFlySet.Put(aBrushItem, RES_BACKGROUND);
1938 }
1939 
1940 void SwWW8ImplReader::AdjustLRWrapForWordMargins(
1941     const SvxMSDffImportRec &rRecord, SvxLRSpaceItem &rLR)
1942 {
1943     // Left adjustments - if horizontally aligned to left of
1944     // margin or column then remove the left wrapping
1945     if (rRecord.nXAlign == 1)
1946     {
1947         if ((rRecord.nXRelTo == 0) || (rRecord.nXRelTo == 2))
1948             rLR.SetLeft((sal_uInt16)0);
1949     }
1950 
1951     // Right adjustments - if horizontally aligned to right of
1952     // margin or column then remove the right wrapping
1953     if (rRecord.nXAlign == 3)
1954     {
1955         if ((rRecord.nXRelTo == 0) || (rRecord.nXRelTo == 2))
1956             rLR.SetRight((sal_uInt16)0);
1957     }
1958 
1959     //Inside margin, remove left wrapping
1960     if ((rRecord.nXAlign == 4) && (rRecord.nXRelTo == 0))
1961     {
1962         rLR.SetLeft((sal_uInt16)0);
1963     }
1964 
1965     //Outside margin, remove left wrapping
1966     if ((rRecord.nXAlign == 5) && (rRecord.nXRelTo == 0))
1967     {
1968         rLR.SetRight((sal_uInt16)0);
1969     }
1970 }
1971 
1972 
1973 void SwWW8ImplReader::AdjustULWrapForWordMargins(
1974     const SvxMSDffImportRec &rRecord, SvxULSpaceItem &rUL)
1975 {
1976     // Top adjustment - remove upper wrapping if aligned to page
1977     // printable area or to page
1978     if (rRecord.nYAlign == 1)
1979     {
1980         if ((rRecord.nYRelTo == 0) || (rRecord.nYRelTo == 1))
1981             rUL.SetUpper((sal_uInt16)0);
1982     }
1983 
1984     // Bottom adjustment - remove bottom wrapping if aligned to page or
1985     // printable area or to page
1986     if (rRecord.nYAlign == 3)
1987     {
1988         if ((rRecord.nYRelTo == 0) || (rRecord.nYRelTo == 1))
1989             rUL.SetLower((sal_uInt16)0);
1990     }
1991 
1992     //Remove top margin if aligned vertically inside margin
1993     if ((rRecord.nYAlign == 4) && (rRecord.nYRelTo == 0))
1994         rUL.SetUpper((sal_uInt16)0);
1995 
1996     /*
1997     // Something like this needs to be done once inside and outside are
1998     // fixed
1999     if (rRecord.nYAlign == 4)
2000     {
2001         if (rRecord.nYRelTo == 0)
2002             rUL.SetUpper((sal_uInt16)0);
2003     }
2004     */
2005 }
2006 
2007 void SwWW8ImplReader::MapWrapIntoFlyFmt(SvxMSDffImportRec* pRecord,
2008     SwFrmFmt* pFlyFmt)
2009 {
2010     if (!pRecord || !pFlyFmt)
2011         return;
2012 
2013     if (pRecord->nDxWrapDistLeft || pRecord->nDxWrapDistRight)
2014     {
2015         SvxLRSpaceItem aLR(writer_cast<sal_uInt16>(pRecord->nDxWrapDistLeft),
2016             writer_cast<sal_uInt16>(pRecord->nDxWrapDistRight), 0, 0, RES_LR_SPACE);
2017         AdjustLRWrapForWordMargins(*pRecord, aLR);
2018         pFlyFmt->SetFmtAttr(aLR);
2019     }
2020     if (pRecord->nDyWrapDistTop || pRecord->nDyWrapDistBottom)
2021     {
2022         SvxULSpaceItem aUL(writer_cast<sal_uInt16>(pRecord->nDyWrapDistTop),
2023             writer_cast<sal_uInt16>(pRecord->nDyWrapDistBottom), RES_UL_SPACE);
2024         AdjustULWrapForWordMargins(*pRecord, aUL);
2025         pFlyFmt->SetFmtAttr(aUL);
2026     }
2027 
2028     //If we are contoured and have a custom polygon...
2029     if (pRecord->pWrapPolygon && pFlyFmt->GetSurround().IsContour())
2030     {
2031         if (SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(*pFlyFmt))
2032         {
2033 
2034             /*
2035              Gather round children and hear of a tale that will raise the
2036              hairs on the back of your neck this dark halloween night.
2037 
2038              There is a polygon in word that describes the wraping around
2039              the graphic.
2040 
2041              Here are some sample values for the simplest case of a square
2042              around some solid coloured graphics
2043 
2044                                 X       Y       Pixel size of graphic
2045                 TopLeft         -54     21600   400x400
2046                 Bottom Right    0       21546
2047 
2048                 TopLeft         -108    21600   200x200
2049                 Bottom Right    0       21492
2050 
2051                 TopLeft         -216    21600   100x100
2052                 Bottom Right    0       21384
2053 
2054                 TopLeft         -432    21600   50x50
2055                 Bottom Right    0       21168
2056 
2057                 TopLeft         -76     21600   283x212
2058                 Bottom Right    0       21498
2059 
2060              So given that the size of the values remains pretty much the
2061              same despite the size of the graphic, we can tell that the
2062              polygon is measured in units that are independant of the
2063              graphic. But why does the left corner move a different value
2064              to the left each time, and why does the bottom move upwards
2065              each time, when the right and top remain at the same value ?
2066 
2067              I have no idea, but clearly once we calculate the values out
2068              we see that the left margin is always a fixed realworld
2069              distance from the true left and the polygon bottom is the same
2070              fixed value from the bottom. i.e. 15twips.
2071 
2072              So here we take our word provided polygon, shift it to the
2073              right by 15twips and rescale it widthwise to shrink the width
2074              a little to fit the now moved right margin back to where it
2075              was, and stretch the height a little to make the bottom move
2076              down the missing 15twips then we get a polygon that matches
2077              what I actually see in word
2078             */
2079 
2080             PolyPolygon aPoly(*pRecord->pWrapPolygon);
2081             const Size &rSize = pNd->GetTwipSize();
2082             /*
2083              Move to the left by 15twips, and rescale to
2084              a) shrink right bound back to orig position
2085              b) stretch bottom bound to where I think it should have been
2086              in the first place
2087             */
2088             Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
2089             aMoveHack *= Fraction(15, 1);
2090             long nMove(aMoveHack);
2091             aPoly.Move(nMove, 0);
2092 
2093             Fraction aHackX(ww::nWrap100Percent, ww::nWrap100Percent + nMove);
2094             Fraction aHackY(ww::nWrap100Percent, ww::nWrap100Percent - nMove);
2095             aPoly.Scale(aHackX, aHackY);
2096 
2097             //Turn polygon back into units that match the graphic's
2098             const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
2099             Fraction aMapPolyX(rOrigSize.Width(), ww::nWrap100Percent);
2100             Fraction aMapPolyY(rOrigSize.Height(), ww::nWrap100Percent);
2101             aPoly.Scale(aMapPolyX, aMapPolyY);
2102 
2103             // --> OD 2005-05-19 #i47277# - contour is already in unit of the
2104             // graphic prefered unit. Thus, call method <SetContour(..)>
2105             pNd->SetContour(&aPoly);
2106             // <--
2107         }
2108     }
2109 }
2110 
2111 void SwWW8ImplReader::SetAttributesAtGrfNode( SvxMSDffImportRec* pRecord,
2112     SwFrmFmt *pFlyFmt, WW8_FSPA *pF )
2113 {
2114     const SwNodeIndex* pIdx = pFlyFmt->GetCntnt(false).GetCntntIdx();
2115     SwGrfNode* pGrfNd;
2116     if( pIdx && 0 != (pGrfNd = rDoc.GetNodes()[pIdx->GetIndex() + 1]->GetGrfNode() ))
2117     {
2118         Size aSz(pGrfNd->GetTwipSize());
2119         // --> OD 2005-08-01 #124722# - use type <sal_uInt64> instead of <sal_uLong>
2120         // to get correct results in the following calculations.
2121         sal_uInt64 rHeight = aSz.Height();
2122         sal_uInt64 rWidth  = aSz.Width();
2123         // <--
2124         if( !rWidth && pF)
2125             rWidth  = pF->nXaRight  - pF->nXaLeft;
2126         else if( !rHeight && pF)
2127             rHeight = pF->nYaBottom - pF->nYaTop;
2128 
2129         if( pRecord->nCropFromTop || pRecord->nCropFromBottom ||
2130             pRecord->nCropFromLeft || pRecord->nCropFromRight )
2131         {
2132             SwCropGrf aCrop;            // Cropping is stored in 'fixed floats'
2133                                         // 16.16 (it est fraction times total
2134             if( pRecord->nCropFromTop ) //        image width or height resp.)
2135                 aCrop.SetTop( static_cast< sal_Int32 >(
2136                 (   ( (pRecord->nCropFromTop    >> 16   ) * rHeight )
2137                   + (((pRecord->nCropFromTop    & 0xffff) * rHeight ) >> 16) )));
2138             if( pRecord->nCropFromBottom )
2139                 aCrop.SetBottom( static_cast< sal_Int32 >(
2140                 (   ( (pRecord->nCropFromBottom >> 16   ) * rHeight )
2141                   + (((pRecord->nCropFromBottom & 0xffff) * rHeight ) >> 16) )));
2142             if( pRecord->nCropFromLeft )
2143                 aCrop.SetLeft( static_cast< sal_Int32 >(
2144                 (   ( (pRecord->nCropFromLeft   >> 16   ) * rWidth  )
2145                   + (((pRecord->nCropFromLeft   & 0xffff) * rWidth  ) >> 16) )));
2146             if( pRecord->nCropFromRight )
2147                 aCrop.SetRight( static_cast< sal_Int32 >(
2148                 (   ( (pRecord->nCropFromRight  >> 16   ) * rWidth  )
2149                   + (((pRecord->nCropFromRight  & 0xffff) * rWidth  ) >> 16) )));
2150 
2151             pGrfNd->SetAttr( aCrop );
2152         }
2153 
2154         if (pRecord && pRecord->pObj)
2155         {
2156             const SfxItemSet& rOldSet = pRecord->pObj->GetMergedItemSet();
2157             //contrast
2158             if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFCONTRAST,
2159                 SdrGrafContrastItem))
2160             {
2161                 SwContrastGrf aContrast(
2162                     WW8ITEMVALUE(rOldSet,
2163                     SDRATTR_GRAFCONTRAST, SdrGrafContrastItem));
2164                 pGrfNd->SetAttr( aContrast );
2165             }
2166 
2167             //luminance
2168             if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFLUMINANCE,
2169                 SdrGrafLuminanceItem))
2170             {
2171                 SwLuminanceGrf aLuminance(WW8ITEMVALUE(rOldSet,
2172                     SDRATTR_GRAFLUMINANCE, SdrGrafLuminanceItem));
2173                 pGrfNd->SetAttr( aLuminance );
2174             }
2175             //gamma
2176             if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA, SdrGrafGamma100Item))
2177             {
2178                 double fVal = WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA,
2179                     SdrGrafGamma100Item);
2180                 pGrfNd->SetAttr(SwGammaGrf(fVal/100.));
2181             }
2182 
2183             //drawmode
2184             if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFMODE, SdrGrafModeItem))
2185             {
2186                 SwDrawModeGrf aDrawMode( static_cast< sal_uInt16 >(WW8ITEMVALUE(rOldSet,
2187                     SDRATTR_GRAFMODE, SdrGrafModeItem)) );
2188                 pGrfNd->SetAttr( aDrawMode );
2189             }
2190         }
2191     }
2192 }
2193 
2194 SdrObject* SwWW8ImplReader::CreateContactObject(SwFrmFmt* pFlyFmt)
2195 {
2196     if (pFlyFmt)
2197     {
2198         //JP 11.1.2002: task 96329
2199         SdrObject* pNewObject = mbNewDoc ? 0 : pFlyFmt->FindRealSdrObject();
2200         if (!pNewObject)
2201             pNewObject = pFlyFmt->FindSdrObject();
2202         if (!pNewObject && pFlyFmt->ISA(SwFlyFrmFmt))
2203         {
2204             SwFlyDrawContact* pContactObject
2205                 = new SwFlyDrawContact(static_cast<SwFlyFrmFmt*>(pFlyFmt),
2206                 pDrawModel);
2207             pNewObject = pContactObject->GetMaster();
2208         }
2209         return pNewObject;
2210     }
2211     return 0;
2212 }
2213 
2214 //#109311# Miserable miserable hack to fudge word's graphic layout in
2215 //RTL mode to ours.
2216 bool SwWW8ImplReader::MiserableRTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
2217     sal_Int16 eHoriOri, sal_Int16 eHoriRel)
2218 {
2219     if (!IsRightToLeft())
2220         return false;
2221     return RTLGraphicsHack(rLeft, nWidth, eHoriOri, eHoriRel,
2222             maSectionManager.GetPageLeft(),
2223             maSectionManager.GetPageRight(),
2224             maSectionManager.GetPageWidth());
2225 }
2226 
2227 RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec* pRecord,
2228     WW8_FSPA *pFSPA, SfxItemSet &rFlySet, bool /*bOrgObjectWasReplace*/)
2229 {
2230     ASSERT(pRecord || pFSPA, "give me something! to work with for anchoring");
2231     if (!pRecord && !pFSPA)
2232         return FLY_AT_PAGE;
2233 
2234     SvxMSDffImportRec aRecordFromFSPA;
2235     if (!pRecord)
2236     {
2237         pRecord = &aRecordFromFSPA;
2238         pRecord->nXRelTo = pFSPA->nbx;
2239         pRecord->nYRelTo = pFSPA->nby;
2240     }
2241 
2242     // nXAlign - abs. Position, Left,  Centered,  Right,  Inside, Outside
2243     // nYAlign - abs. Position, Top,   Centered,  Bottom, Inside, Outside
2244 
2245     // nXRelTo - Page printable area, Page,  Column,    Character
2246     // nYRelTo - Page printable area, Page,  Paragraph, Line
2247 
2248     const sal_uInt32 nCntXAlign = 6;
2249     const sal_uInt32 nCntYAlign = 6;
2250 
2251     const sal_uInt32 nCntRelTo  = 4;
2252 
2253 	sal_uInt32 nXAlign = nCntXAlign > pRecord->nXAlign ? pRecord->nXAlign : 1;
2254 	sal_uInt32 nYAlign = nCntYAlign > pRecord->nYAlign ? pRecord->nYAlign : 1;
2255 
2256 	if (pFSPA)
2257 	{
2258 		/*
2259 		#74188# #i15718# #i19008#
2260 		Strangely in this case the FSPA value seems to be considered before
2261 		the newer escher nXRelTo record.
2262 		*/
2263         // --> OD 2005-08-04 #i52565# - correct condition checking:
2264         // first check, if <nXRelTo> and <nYRelTo> have default values.  This
2265         // is a hint that these values aren't set by the escher import - see
2266         // method <SwMSDffManager::ProcessObj(..)>. Then, check if for each
2267         // values, if it differs from the one in the FSPA.
2268         if ( pRecord->nXRelTo == 2 && pRecord->nYRelTo == 2 )
2269         {
2270             // if <nYRelTo> differs from <FSPA.nby> overwrite <nYRelTo>
2271             if ( pFSPA->nby != pRecord->nYRelTo )
2272             {
2273                 pRecord->nYRelTo = pFSPA->nby;
2274             }
2275         }
2276         // <--
2277 	}
2278 
2279     sal_uInt32 nXRelTo = nCntRelTo > pRecord->nXRelTo ? pRecord->nXRelTo : 1;
2280     sal_uInt32 nYRelTo = nCntRelTo > pRecord->nYRelTo ? pRecord->nYRelTo : 1;
2281 
2282     // --> OD 2005-03-03 #i43718#
2283     RndStdIds eAnchor = IsInlineEscherHack() ? FLY_AS_CHAR : FLY_AT_CHAR;
2284     // <--
2285 
2286     SwFmtAnchor aAnchor( eAnchor );
2287 	aAnchor.SetAnchor( pPaM->GetPoint() );
2288 	rFlySet.Put( aAnchor );
2289 
2290     if (pFSPA)
2291 	{
2292         // OD 14.10.2003 #i18732#
2293         //Given new layout where everything is changed to be anchored to
2294         //character the following 4 tables may need to be changed.
2295 
2296         // horizontal Adjustment
2297         static const sal_Int16 aHoriOriTab[ nCntXAlign ] =
2298         {
2299             text::HoriOrientation::NONE,     // From left position
2300             text::HoriOrientation::LEFT,     // left
2301             text::HoriOrientation::CENTER,   // centered
2302             text::HoriOrientation::RIGHT,    // right
2303             // --> OD 2004-12-06 #i36649#
2304             // - inside -> text::HoriOrientation::LEFT and outside -> text::HoriOrientation::RIGHT
2305             text::HoriOrientation::LEFT,   // inside
2306             text::HoriOrientation::RIGHT   // outside
2307             // <--
2308         };
2309 
2310 
2311         // generic vertical Adjustment
2312         static const sal_Int16 aVertOriTab[ nCntYAlign ] =
2313         {
2314             text::VertOrientation::NONE,         // From Top position
2315             text::VertOrientation::TOP,          // top
2316             text::VertOrientation::CENTER,       // centered
2317             text::VertOrientation::BOTTOM,       // bottom
2318             text::VertOrientation::LINE_TOP,     // inside (obscure)
2319             text::VertOrientation::LINE_BOTTOM   // outside (obscure)
2320         };
2321 
2322         // CMC,OD 24.11.2003 #i22673# - to-line vertical alignment
2323         static const sal_Int16 aToLineVertOriTab[ nCntYAlign ] =
2324         {
2325             text::VertOrientation::NONE,         // below
2326             text::VertOrientation::LINE_BOTTOM,  // top
2327             text::VertOrientation::LINE_CENTER,  // centered
2328             text::VertOrientation::LINE_TOP,     // bottom
2329             text::VertOrientation::LINE_BOTTOM,  // inside (obscure)
2330             text::VertOrientation::LINE_TOP      // outside (obscure)
2331         };
2332 
2333         // Adjustment is horizontally relative to...
2334         static const sal_Int16 aHoriRelOriTab[nCntRelTo] =
2335         {
2336             text::RelOrientation::PAGE_PRINT_AREA,    // 0 is page textarea margin
2337             text::RelOrientation::PAGE_FRAME,  // 1 is page margin
2338             text::RelOrientation::FRAME,         // 2 is relative to column
2339             text::RelOrientation::CHAR       // 3 is relative to character
2340         };
2341 
2342         // Adjustment is vertically relative to...
2343         // CMC, OD 24.11.2003 #i22673# - adjustment for new vertical alignment
2344         // at top of line.
2345         static const sal_Int16 aVertRelOriTab[nCntRelTo] =
2346         {
2347             text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
2348             text::RelOrientation::PAGE_FRAME,   // 1 is page margin
2349             text::RelOrientation::FRAME,          // 2 is relative to paragraph
2350             text::RelOrientation::TEXT_LINE   // 3 is relative to line
2351         };
2352 
2353         sal_Int16 eHoriOri = aHoriOriTab[ nXAlign ];
2354         sal_Int16 eHoriRel = aHoriRelOriTab[  nXRelTo ];
2355 
2356         // --> OD 2004-12-06 #i36649# - adjustments for certain alignments
2357         if ( eHoriOri == text::HoriOrientation::LEFT && eHoriRel == text::RelOrientation::PAGE_FRAME )
2358         {
2359             // convert 'left to page' to 'from left -<width> to page text area'
2360             eHoriOri = text::HoriOrientation::NONE;
2361             eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
2362             const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
2363             pFSPA->nXaLeft = -nWidth;
2364             pFSPA->nXaRight = 0;
2365         }
2366         else if ( eHoriOri == text::HoriOrientation::RIGHT && eHoriRel == text::RelOrientation::PAGE_FRAME )
2367         {
2368             // convert 'right to page' to 'from left 0 to right page border'
2369             eHoriOri = text::HoriOrientation::NONE;
2370             eHoriRel = text::RelOrientation::PAGE_RIGHT;
2371             const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
2372             pFSPA->nXaLeft = 0;
2373             pFSPA->nXaRight = nWidth;
2374         }
2375         // <--
2376 
2377         // --> OD 2005-02-07 #i24255# - position of floating screen objects in
2378         // R2L layout are given in L2R layout, thus convert them of all
2379         // floating screen objects, which are imported.
2380         {
2381             //#109311# Miserable miserable hack.
2382             SwTwips nWidth = (pFSPA->nXaRight - pFSPA->nXaLeft);
2383             SwTwips nLeft = pFSPA->nXaLeft;
2384             if (MiserableRTLGraphicsHack(nLeft, nWidth, eHoriOri,
2385                 eHoriRel))
2386             {
2387                 pFSPA->nXaLeft = nLeft;
2388                 pFSPA->nXaRight = pFSPA->nXaLeft + nWidth;
2389             }
2390         }
2391         // <--
2392 
2393         // --> OD 2005-01-20 #118546# - if the object is anchored inside
2394         // a table cell, is horizontal aligned at frame|character and
2395         // has wrap through, but its attribute 'layout in table cell' isn't set,
2396         // convert its horizontal alignment to page text area.
2397         // --> OD 2008-04-10 #i84783# - use new method <IsObjectLayoutInTableCell()>
2398         if ( nInTable &&
2399              ( eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR ) &&
2400              pFSPA->nwr == 3 &&
2401 //             pRecord->nLayoutInTableCell == 0x80000000 )
2402              !IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ) )
2403         {
2404             eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
2405         }
2406         // <--
2407 
2408         SwFmtHoriOrient aHoriOri(MakeSafePositioningValue(pFSPA->nXaLeft),
2409             eHoriOri, eHoriRel);
2410         if( 4 <= nXAlign )
2411             aHoriOri.SetPosToggle(true);
2412         rFlySet.Put( aHoriOri );
2413 
2414         //Writer honours this wrap distance when aligned as "left" or "right",
2415         //Word doesn't. Writer doesn't honour it when its "from left".
2416         if (eHoriOri == text::HoriOrientation::LEFT)
2417             pRecord->nDxWrapDistLeft=0;
2418         else if (eHoriOri == text::HoriOrientation::RIGHT)
2419             pRecord->nDxWrapDistRight=0;
2420 
2421         sal_Int16 eVertRel;
2422         // OD 14.10.2003 #i18732#
2423         eVertRel = aVertRelOriTab[  nYRelTo ];
2424         // CMC, OD 24.11.2003 #i22673# - fill <eVertOri> in dependence of <eVertRel>
2425         sal_Int16 eVertOri;
2426         if ( eVertRel == text::RelOrientation::TEXT_LINE )
2427         {
2428             eVertOri = aToLineVertOriTab[ nYAlign ];
2429         }
2430         else
2431         {
2432             eVertOri = aVertOriTab[ nYAlign ];
2433         }
2434 
2435         //Below line in word is a positive value, while in writer its
2436         //negative
2437         long nYPos = pFSPA->nYaTop;
2438         // CMC, OD 24.11.2003 #i22673#
2439         if ((eVertRel == text::RelOrientation::TEXT_LINE) && (eVertOri == text::VertOrientation::NONE))
2440             nYPos = -nYPos;
2441 
2442         rFlySet.Put(SwFmtVertOrient(MakeSafePositioningValue(nYPos),
2443             eVertOri, eVertRel));
2444 
2445         if (
2446             (pFSPA->nYaTop < 0) && (eVertOri == text::VertOrientation::NONE) &&
2447             ((eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR))
2448            )
2449         {
2450             maTracer.Log(sw::log::eNegativeVertPlacement);
2451         }
2452     }
2453 
2454     return eAnchor;
2455 }
2456 
2457 // --> OD 2008-04-10 #i84783#
2458 bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const
2459 {
2460     bool bIsObjectLayoutInTableCell = false;
2461 
2462     if ( bVer8 )
2463     {
2464         const sal_uInt16 nWWVersion = pWwFib->nProduct & 0xE000;
2465         switch ( nWWVersion )
2466         {
2467             case 0x0000: // version 8 aka Microsoft Word 97
2468             {
2469                 bIsObjectLayoutInTableCell = false;
2470                 ASSERT( nLayoutInTableCell == 0xFFFFFFFF,
2471                         "no explicit object attribute layout in table cell excepted." );
2472             }
2473             break;
2474             case 0x2000: // version 9 aka Microsoft Word 2000
2475             case 0x4000: // version 10 aka Microsoft Word 2002
2476             case 0x6000: // version 11 aka Microsoft Word 2003
2477             case 0x8000: // version 12 aka Microsoft Word 2007
2478             {
2479                 // --> OD 2009-01-13 #i98037#
2480                 // adjustment of conditions needed after deeper analysis of
2481                 // certain test cases.
2482                 if ( nLayoutInTableCell == 0xFFFFFFFF || // no explicit attribute value given
2483                      nLayoutInTableCell & 0x80008000 ||
2484                      ( nLayoutInTableCell & 0x02000000 &&
2485                        !(nLayoutInTableCell & 0x80000000 ) ) )
2486                 // <--
2487                 {
2488                     bIsObjectLayoutInTableCell = true;
2489                 }
2490                 else
2491                 {
2492                     bIsObjectLayoutInTableCell = false;
2493                 }
2494             }
2495             break;
2496             default:
2497             {
2498                 ASSERT( false,
2499                         "unknown version." );
2500             }
2501         }
2502     }
2503 
2504     return bIsObjectLayoutInTableCell;
2505 }
2506 // <--
2507 
2508 SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp )
2509 {
2510     if( nIniFlags & WW8FL_NO_GRAFLAYER )
2511         return 0;
2512 
2513     ::SetProgressState(nProgress, mpDocShell);     // Update
2514 
2515     nDrawCpO = pWwFib->GetBaseCp(pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX);
2516 
2517     GrafikCtor();
2518 
2519     WW8PLCFspecial* pPF = pPlcxMan->GetFdoa();
2520     if( !pPF )
2521     {
2522         ASSERT( !this, "Where is the grapic (1) ?" );
2523         return 0;
2524     }
2525 
2526     if( bVer67 )
2527     {
2528         long nOldPos = pStrm->Tell();
2529 
2530         nDrawXOfs = nDrawYOfs = 0;
2531         ReadGrafLayer1( pPF, nGrafAnchorCp );
2532 
2533         pStrm->Seek( nOldPos );
2534         return 0;
2535     }
2536 
2537     //Normal case of Word 8+ version stuff
2538     pPF->SeekPos( nGrafAnchorCp );
2539 
2540     WW8_FC nStartFc;
2541     void* pF0;
2542     if( !pPF->Get( nStartFc, pF0 ) ){
2543         ASSERT( !this, "+Wo ist die Grafik (2) ?" );
2544         return 0;
2545     }
2546 
2547     WW8_FSPA_SHADOW* pFS = (WW8_FSPA_SHADOW*)pF0;
2548     WW8_FSPA*        pF;
2549 #ifdef __WW8_NEEDS_COPY
2550     WW8_FSPA aFSFA;
2551     pF = &aFSFA;
2552     WW8FSPAShadowToReal( pFS, pF );
2553 #else
2554     pF = (WW8_FSPA*)pFS;
2555 #endif // defined __WW8_NEEDS_COPY
2556     if( !pF->nSpId )
2557     {
2558         ASSERT( !this, "+Wo ist die Grafik (3) ?" );
2559         return 0;
2560     }
2561 
2562     if (!pMSDffManager->GetModel())
2563          pMSDffManager->SetModel(pDrawModel, 1440);
2564 
2565 
2566     Rectangle aRect(pF->nXaLeft,  pF->nYaTop, pF->nXaRight, pF->nYaBottom);
2567     SvxMSDffImportData aData( aRect );
2568 
2569     /*
2570     #i20540#
2571     The SdrOle2Obj will try and manage any ole objects it finds, causing all
2572     sorts of trouble later on
2573     */
2574     SwDocShell* pPersist = rDoc.GetDocShell();
2575     rDoc.SetDocShell(0);         //#i20540# Persist guard
2576 
2577     SdrObject* pObject = 0;
2578     bool bOk = (pMSDffManager->GetShape(pF->nSpId, pObject, aData) && pObject);
2579 
2580     rDoc.SetDocShell(pPersist);  //#i20540# Persist guard
2581 
2582     if (!bOk)
2583     {
2584         ASSERT( !this, "Where is the Shape ?" );
2585         return 0;
2586     }
2587 
2588     bool bDone = false;
2589     SdrObject* pOurNewObject = 0;
2590     bool bReplaceable = false;
2591 
2592     switch (SdrObjKind(pObject->GetObjIdentifier()))
2593     {
2594         case OBJ_GRAF:
2595             bReplaceable = true;
2596             bDone = true;
2597             break;
2598         case OBJ_OLE2:
2599             bReplaceable = true;
2600             break;
2601         default:
2602             break;
2603 
2604     }
2605 
2606     // OD 14.10.2003 - keep wrapping of objects in page header/footer.
2607     /*
2608     //#108778# when in a header or footer word appears to treat all elements
2609     //are wrap through
2610     if (bIsHeader || bIsFooter)
2611         pF->nwr = 3;
2612     */
2613 
2614     // Umfluss-Modus ermitteln
2615     SfxItemSet aFlySet(rDoc.GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
2616     SwSurround eSurround = SURROUND_PARALLEL;
2617     bool bContour = false;
2618     switch (pF->nwr)
2619     {
2620         case 0: //0 like 2, but doesn't require absolute object
2621         case 2: //2 wrap around absolute object
2622             eSurround = SURROUND_PARALLEL;
2623             break;
2624         case 1: //1 no text next to shape
2625             eSurround = SURROUND_NONE;
2626             break;
2627         case 3: //3 wrap as if no object present
2628             eSurround = SURROUND_THROUGHT;
2629             break;
2630         case 4: //4 wrap tightly around object
2631         case 5: //5 wrap tightly, but allow holes
2632             eSurround = SURROUND_PARALLEL;
2633             bContour = true;
2634             break;
2635     }
2636 
2637     // bei Modus 2 oder 4 auch den Zusatzparameter beruecksichtigen
2638     if ( (2 == pF->nwr) || (4 == pF->nwr) )
2639     {
2640         switch( pF->nwrk )
2641         {
2642             //0 wrap both sides
2643             case 0:
2644                 eSurround = SURROUND_PARALLEL;
2645                 break;
2646             //1 wrap only on left
2647             case 1:
2648                 eSurround = SURROUND_LEFT;
2649                 break;
2650             //2 wrap only on right
2651             case 2:
2652                 eSurround = SURROUND_RIGHT;
2653                 break;
2654             //3 wrap only on largest side
2655             case 3:
2656                 eSurround = SURROUND_IDEAL;
2657                 break;
2658         }
2659     }
2660 
2661     SwFmtSurround aSur( eSurround );
2662     aSur.SetContour( bContour );
2663     aSur.SetOutside(true); // Winword kann nur Aussen-Konturen
2664     aFlySet.Put( aSur );
2665 
2666     // eingelesenes Objekt (kann eine ganze Gruppe sein) jetzt korrekt
2667     // positionieren usw.
2668 
2669     ASSERT(!((aData.GetRecCount() != 1) && bReplaceable),
2670         "Replaceable drawing with > 1 entries ?");
2671 
2672     if (aData.GetRecCount() != 1)
2673         bReplaceable = false;
2674 
2675     SvxMSDffImportRec* pRecord = 0;
2676     /*
2677         Get the record for top level object, so we can get the word anchoring
2678         and wrapping information for it.
2679     */
2680     sal_uInt16 nRecCount = aData.GetRecCount();
2681     for (sal_uInt16 nTxbx=0; nTxbx < nRecCount; ++nTxbx )
2682     {
2683         pRecord = aData.GetRecord( nTxbx );
2684         if (pRecord && pRecord->pObj == pObject)
2685             break;
2686         else
2687             pRecord = 0;
2688     }
2689 
2690     ASSERT(pRecord, "how did that happen?");
2691     if (!pRecord)
2692         return 0;
2693 
2694     // --> OD 2008-04-10 #i84783#
2695 //    //cmc: We're in a table, and the element has the magic Word XP bit set
2696 //    //to enable layout inside a cell
2697 //    // --> OD 2005-08-10 #124714# - undo change made for issue #i33442#
2698 //    bool bLayoutInTableCell = ( nInTable &&
2699 //                                pRecord->nLayoutInTableCell & 0x00008000 );
2700 //    // <--
2701     const bool bLayoutInTableCell =
2702         nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell );
2703     // <--
2704 
2705     // OD 14.10.2003 #i18732#
2706     // Switch on 'follow text flow',
2707     // if object is laid out inside table cell and
2708     // its wrapping isn't 'SURROUND_THROUGH'
2709     if (bLayoutInTableCell && eSurround != SURROUND_THROUGHT)
2710     {
2711         SwFmtFollowTextFlow aFollowTextFlow( sal_True );
2712         aFlySet.Put( aFollowTextFlow );
2713     }
2714 
2715 
2716     //#i21847#
2717     //Some shapes are set to *hidden*, don't import those ones.
2718     if (pRecord->bHidden)
2719         return 0;
2720 
2721     // If we are to be "below text" then we are not to be opaque
2722     // #i14045# MM If we are in a header or footer then make the object transparent
2723     // Not exactly like word but close enough for now
2724 
2725     // --> OD 2005-03-07 #b6234902# - both flags <bBelowText> and <bDrawHell>
2726     // have to be set to move object into the background.
2727     // --> OD 2005-04-11 #i46794# - it reveals that value of flag <bBelowText>
2728     // can be neglected.
2729     const bool bMoveToBackgrd = pRecord->bDrawHell ||
2730                                 ( ( bIsHeader || bIsFooter ) && pF->nwr == 3 );
2731     if ( bMoveToBackgrd )
2732         aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false));
2733 
2734     String aObjName = pObject->GetName();
2735 
2736     SwFrmFmt* pRetFrmFmt = 0;
2737     if (bReplaceable)
2738     {
2739         //Single graphics or ole objects
2740         pRetFrmFmt = ImportReplaceableDrawables(pObject, pOurNewObject, pRecord,
2741             pF, aFlySet);
2742     }
2743     else
2744     {
2745         //Drawing objects, (e.g. ovals or drawing groups)
2746         if (pF->bRcaSimple)
2747         {
2748             pF->nbx = WW8_FSPA::RelPageBorder;
2749             pF->nby = WW8_FSPA::RelPageBorder;
2750         }
2751 
2752         RndStdIds eAnchor = ProcessEscherAlign(pRecord, pF, aFlySet,
2753             bReplaceable);
2754 
2755         // Should we, and is it possible to make this into a writer textbox
2756         if ((!(nIniFlags1 & WW8FL_NO_FLY_FOR_TXBX)) && pRecord->bReplaceByFly)
2757         {
2758             pRetFrmFmt = ConvertDrawTextToFly(pObject, pOurNewObject, pRecord,
2759                 eAnchor, pF, aFlySet);
2760             if (pRetFrmFmt)
2761                 bDone = true;
2762         }
2763 
2764         if (!bDone)
2765         {
2766             sw::util::SetLayer aSetLayer(rDoc);
2767             if ( bMoveToBackgrd )
2768                 aSetLayer.SendObjectToHell(*pObject);
2769             else
2770                 aSetLayer.SendObjectToHeaven(*pObject);
2771 
2772             if (!IsInlineEscherHack())
2773             {
2774                 /*
2775                 #97824#  Need to make sure that the correct layer ordering is
2776                 applied.
2777                 */
2778                 // --> OD 2004-12-13 #117915# - pass information, if object
2779                 // is in page header|footer to method.
2780                 pWWZOrder->InsertEscherObject( pObject, pF->nSpId,
2781                                                bIsHeader || bIsFooter );
2782                 // <--
2783             }
2784             else
2785             {
2786                 pWWZOrder->InsertTextLayerObject(pObject);
2787             }
2788 
2789             pRetFrmFmt = rDoc.Insert(*pPaM, *pObject, &aFlySet, NULL);
2790 
2791             ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() ==
2792                 eAnchor, "Not the anchor type requested!");
2793 
2794             /*
2795                 Insert text if necessary into textboxes contained in groups.
2796             */
2797             if (aData.HasRecords())
2798             {
2799                 sal_uInt16 nCount = aData.GetRecCount();
2800                 for (sal_uInt16 nTxbx=0; nTxbx < nCount; ++nTxbx)
2801                 {
2802                     pRecord = aData.GetRecord(nTxbx);
2803                     if (pRecord && pRecord->pObj && pRecord->aTextId.nTxBxS)
2804                     { // #i52825# pRetFrmFmt can be NULL
2805                         pRetFrmFmt = MungeTextIntoDrawBox(pRecord->pObj,
2806                             pRecord, nGrafAnchorCp, pRetFrmFmt);
2807                     }
2808                 }
2809             }
2810         }
2811     }
2812 
2813     // --> OD 2005-03-11 #i44344#, #i44681# - positioning attributes already set
2814     if ( pRetFrmFmt /*#i52825# */ && pRetFrmFmt->ISA(SwDrawFrmFmt) )
2815     {
2816         static_cast<SwDrawFrmFmt*>(pRetFrmFmt)->PosAttrSet();
2817     }
2818     // <--
2819     if (!IsInlineEscherHack())
2820         MapWrapIntoFlyFmt(pRecord, pRetFrmFmt);
2821 
2822     // Set frame name with object name
2823     if( aObjName.Len() )
2824         pRetFrmFmt->SetName( aObjName );
2825     return AddAutoAnchor(pRetFrmFmt);
2826 }
2827 
2828 SwFrmFmt *SwWW8ImplReader::AddAutoAnchor(SwFrmFmt *pFmt)
2829 {
2830     if (pFmt && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
2831     {
2832         sal_uInt16 nTextAreaWidth = static_cast< sal_uInt16 >( maSectionManager.GetPageWidth() -
2833             maSectionManager.GetPageRight() - maSectionManager.GetPageLeft());
2834 
2835         if (pFmt->GetFrmSize().GetSize().Width() > nTextAreaWidth)
2836             maTracer.Log(sw::log::eTooWideAsChar);
2837     }
2838 
2839     /*
2840      * anchored to character at the current position will move along the
2841      * paragraph as text is added because we are at the insertion point.
2842      *
2843      * Leave to later and set the correct location then.
2844      */
2845     if ((pFmt) && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
2846     {
2847         pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFmt);
2848     }
2849     return pFmt;
2850 }
2851 
2852 SwFrmFmt* SwWW8ImplReader::MungeTextIntoDrawBox(SdrObject* pTrueObject,
2853     SvxMSDffImportRec *pRecord, long nGrafAnchorCp, SwFrmFmt* pRetFrmFmt)
2854 {
2855     SdrTextObj* pSdrTextObj;
2856 
2857     // Pruefen, ob Gruppenobjekt (z.B. zwei Klammern) vorliegt
2858     if (SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pRecord->pObj))
2859     {
2860         // Gruppenobjekte haben keinen Text. Fuege ein Textobjekt in die
2861         // Gruppe ein, um den Text zu halten.
2862         pSdrTextObj = new SdrRectObj( OBJ_TEXT, pThisGroup->GetCurrentBoundRect());
2863 
2864         SfxItemSet aSet(pDrawModel->GetItemPool());
2865         aSet.Put(XFillStyleItem(XFILL_NONE));
2866         aSet.Put(XLineStyleItem(XLINE_NONE));
2867         aSet.Put(SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ));
2868         aSet.Put(SdrTextAutoGrowHeightItem(false));
2869         aSet.Put(SdrTextAutoGrowWidthItem(false));
2870         pSdrTextObj->SetMergedItemSet(aSet);
2871 
2872         long nAngle = pRecord->nTextRotationAngle;
2873         if ( nAngle )
2874         {
2875             double a = nAngle*nPi180;
2876             pSdrTextObj->NbcRotate(pSdrTextObj->GetCurrentBoundRect().Center(), nAngle,
2877                 sin(a), cos(a) );
2878         }
2879 
2880         pSdrTextObj->NbcSetLayer( pThisGroup->GetLayer() );
2881         pThisGroup->GetSubList()->NbcInsertObject(pSdrTextObj);
2882     }
2883     else
2884         pSdrTextObj = PTR_CAST(SdrTextObj, pRecord->pObj);
2885 
2886     if( pSdrTextObj )
2887     {
2888         Size aObjSize(pSdrTextObj->GetSnapRect().GetWidth(),
2889             pSdrTextObj->GetSnapRect().GetHeight());
2890 
2891         // Objekt ist Bestandteil einer Gruppe?
2892         SdrObject* pGroupObject = pSdrTextObj->GetUpGroup();
2893 
2894         sal_uInt32 nOrdNum = pSdrTextObj->GetOrdNum();
2895         bool bEraseThisObject;
2896         InsertTxbxText( pSdrTextObj, &aObjSize, pRecord->aTextId.nTxBxS,
2897             pRecord->aTextId.nSequence, nGrafAnchorCp, pRetFrmFmt,
2898             (pSdrTextObj != pTrueObject) || (0 != pGroupObject),
2899             bEraseThisObject, 0, 0, 0, 0, pRecord);
2900 
2901         // wurde dieses Objekt ersetzt ??
2902         if (bEraseThisObject)
2903         {
2904             if( pGroupObject || (pSdrTextObj != pTrueObject) )
2905             {
2906                 // Objekt wurde bereits (in der Gruppe und) der Drawing-Page
2907                 // durch ein neues SdrGrafObj ersetzt.
2908 
2909                 SdrObject* pNewObj = pGroupObject ?
2910                     pGroupObject->GetSubList()->GetObj(nOrdNum) : pTrueObject;
2911                 if (pSdrTextObj != pNewObj)
2912                 {
2913                     // Objekt in der Z-Order-Liste ersetzen
2914                     pMSDffManager->ExchangeInShapeOrder(pSdrTextObj, 0,0, pNewObj);
2915                     // Objekt jetzt noch loeschen
2916                     SdrObject::Free( pRecord->pObj );
2917                     // und das neue Objekt merken.
2918                     pRecord->pObj = pNewObj;
2919                 }
2920             }
2921             else
2922             {
2923                 // Objekt aus der Z-Order-Liste loeschen
2924                 pMSDffManager->RemoveFromShapeOrder( pSdrTextObj );
2925                 // Objekt aus der Drawing-Page rausnehmen
2926                 if( pSdrTextObj->GetPage() )
2927                     pDrawPg->RemoveObject( pSdrTextObj->GetOrdNum() );
2928                 // und FrameFormat entfernen, da durch Grafik ersetzt (dies
2929                 // loescht auch das Objekt)
2930                 rDoc.DelFrmFmt( pRetFrmFmt );
2931                 pRetFrmFmt = 0;
2932                 // auch den Objektmerker loeschen
2933                 pRecord->pObj = 0;
2934             }
2935         }
2936         else
2937         {
2938             // ww8-default Randabstand einsetzen
2939             SfxItemSet aItemSet(pDrawModel->GetItemPool(),
2940                 SDRATTR_TEXT_LEFTDIST, SDRATTR_TEXT_LOWERDIST);
2941             aItemSet.Put( SdrTextLeftDistItem( pRecord->nDxTextLeft ) );
2942             aItemSet.Put( SdrTextRightDistItem( pRecord->nDxTextRight  ) );
2943             aItemSet.Put( SdrTextUpperDistItem( pRecord->nDyTextTop    ) );
2944             aItemSet.Put( SdrTextLowerDistItem( pRecord->nDyTextBottom ) );
2945             pSdrTextObj->SetMergedItemSetAndBroadcast(aItemSet);
2946         }
2947     }
2948     return pRetFrmFmt;
2949 }
2950 
2951 SwFlyFrmFmt* SwWW8ImplReader::ConvertDrawTextToFly(SdrObject* &rpObject,
2952     SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, RndStdIds eAnchor,
2953     WW8_FSPA *pF, SfxItemSet &rFlySet)
2954 {
2955     SwFlyFrmFmt* pRetFrmFmt = 0;
2956     long nStartCp;
2957     long nEndCp;
2958 
2959     // Pruefen, ob in dieser Textbox-Kette denn Text enthalten ist.  (
2960     // Umwandeln einer leeren Kette in Rahmen waere Unsinn. )
2961     if ( TxbxChainContainsRealText(pRecord->aTextId.nTxBxS,nStartCp,nEndCp) )
2962     {
2963         // Der Text wird nicht in das SdrTextObj eingelesen!  Stattdessen wird
2964         // ein Rahmen eingefuegt und der Text von nStartCp bis nEndCp dort
2965         // hinein gelesen.
2966         //
2967         // Vorteil: im Rahmen sind viel mehr Attribute moeglich als in der
2968         // Edit-Enging, und es koennen auch Felder, OLEs oder Grafiken darin
2969         // sein...
2970 
2971         Rectangle aInnerDist(pRecord->nDxTextLeft, pRecord->nDyTextTop,
2972             pRecord->nDxTextRight, pRecord->nDyTextBottom);
2973 
2974         SwFmtFrmSize aFrmSize(ATT_FIX_SIZE, pF->nXaRight - pF->nXaLeft, pF->nYaBottom - pF->nYaTop);
2975         aFrmSize.SetWidthSizeType(pRecord->bAutoWidth ? ATT_VAR_SIZE : ATT_FIX_SIZE);
2976         rFlySet.Put(aFrmSize);
2977 
2978         MatchSdrItemsIntoFlySet( rpObject, rFlySet, pRecord->eLineStyle,
2979             pRecord->eShapeType, aInnerDist );
2980 
2981 
2982         SdrTextObj *pSdrTextObj = PTR_CAST(SdrTextObj, rpObject);
2983         if (pSdrTextObj && pSdrTextObj->IsVerticalWriting())
2984             rFlySet.Put(SvxFrameDirectionItem(FRMDIR_VERT_TOP_RIGHT, RES_FRAMEDIR));
2985 
2986         pRetFrmFmt = rDoc.MakeFlySection(eAnchor, pPaM->GetPoint(), &rFlySet);
2987         ASSERT(pRetFrmFmt->GetAnchor().GetAnchorId() == eAnchor,
2988             "Not the anchor type requested!");
2989 
2990         // falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste
2991         // entsprechend korrigieren (oder Eintrag loeschen)
2992         rpOurNewObject = CreateContactObject(pRetFrmFmt);
2993 
2994         // altes Objekt aus der Z-Order-Liste entfernen
2995         pMSDffManager->RemoveFromShapeOrder( rpObject );
2996 
2997         // und das Objekt loeschen
2998         SdrObject::Free( rpObject );
2999         /*
3000             Achtung: ab jetzt nur noch pOrgShapeObject
3001             abfragen!
3002         */
3003 
3004         if (rpOurNewObject)
3005         {
3006             /*
3007             #96375#
3008             We do not store our rpOutNewObject in the ShapeOrder because we
3009             have a FrmFmt from which we can regenerate the contact object when
3010             we need it. Because, we can have frames anchored to paragraphs in
3011             header/footers and we can copy header/footers, if we do copy a
3012             header/footer with a nonpage anchored frame in it then the contact
3013             objects are invalidated. Under this condition the FrmFmt will be
3014             updated to reflect this change and can be used to get a new
3015             contact object, while a raw rpOutNewObject stored here becomes
3016             deleted and useless.
3017             */
3018             pMSDffManager->StoreShapeOrder(pF->nSpId,
3019                 (((sal_uLong)pRecord->aTextId.nTxBxS) << 16) +
3020                 pRecord->aTextId.nSequence, 0, pRetFrmFmt);
3021 
3022             // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit
3023             // in SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden
3024             // kann !!!
3025             if (!rpOurNewObject->IsInserted())
3026             {
3027                 // --> OD 2004-12-13 #117915# - pass information, if object
3028                 // is in page header|footer to method.
3029                 pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
3030                                                bIsHeader || bIsFooter );
3031                 // <--
3032             }
3033         }
3034 
3035         // Box-0 erhaelt den Text fuer die ganze Kette!
3036         if( !pRecord->aTextId.nSequence )
3037         {
3038             // rette Flags u.ae. und setze sie zurueck
3039             WW8ReaderSave aSave( this );
3040 
3041             MoveInsideFly(pRetFrmFmt);
3042 
3043             SwNodeIndex aStart(pPaM->GetPoint()->nNode);
3044 
3045             pWWZOrder->InsideEscher(pF->nSpId);
3046 
3047             // lies den Text ein
3048             bTxbxFlySection = true;
3049             bool bJoined = ReadText(nStartCp, (nEndCp-nStartCp),
3050                 MAN_MAINTEXT == pPlcxMan->GetManType() ?
3051                         MAN_TXBX : MAN_TXBX_HDFT);
3052 
3053             pWWZOrder->OutsideEscher();
3054 
3055             MoveOutsideFly(pRetFrmFmt, aSave.GetStartPos(),!bJoined);
3056 
3057             aSave.Restore( this );
3058         }
3059     }
3060     return pRetFrmFmt;
3061 }
3062 
3063 void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord,
3064     SfxItemSet &rFlySet)
3065 {
3066     if (rRecord.bVFlip || rRecord.bHFlip)
3067     {
3068         MirrorGraph eType(RES_MIRROR_GRAPH_DONT);
3069         if (rRecord.bVFlip && rRecord.bHFlip)
3070             eType = RES_MIRROR_GRAPH_BOTH;
3071         else if (rRecord.bVFlip)
3072             eType = RES_MIRROR_GRAPH_HOR;
3073         else
3074             eType = RES_MIRROR_GRAPH_VERT;
3075         rFlySet.Put( SwMirrorGrf(eType) );
3076     }
3077 }
3078 
3079 SwFlyFrmFmt* SwWW8ImplReader::ImportReplaceableDrawables( SdrObject* &rpObject,
3080     SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF,
3081     SfxItemSet &rFlySet )
3082 {
3083     SwFlyFrmFmt* pRetFrmFmt = 0;
3084     long nWidthTw  = pF->nXaRight - pF->nXaLeft;
3085     if (0 > nWidthTw)
3086         nWidthTw = 0;
3087     long nHeightTw = pF->nYaBottom - pF->nYaTop;
3088     if (0 > nHeightTw)
3089         nHeightTw = 0;
3090 
3091     ProcessEscherAlign(pRecord, pF, rFlySet, true);
3092 
3093     rFlySet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nWidthTw, nHeightTw));
3094 
3095     SfxItemSet aGrSet(rDoc.GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1);
3096 
3097     if (pRecord)
3098     {
3099         //Note that the escher inner distance only seems to be honoured in
3100         //word for textboxes, not for graphics and ole objects.
3101         Rectangle aInnerDist(0, 0, 0, 0);
3102 
3103         MatchSdrItemsIntoFlySet(rpObject, rFlySet, pRecord->eLineStyle,
3104             pRecord->eShapeType, aInnerDist);
3105 
3106         MatchEscherMirrorIntoFlySet(*pRecord, aGrSet);
3107     }
3108 
3109     String aObjectName(rpObject->GetName());
3110     if (OBJ_OLE2 == SdrObjKind(rpObject->GetObjIdentifier()))
3111         pRetFrmFmt = InsertOle(*((SdrOle2Obj*)rpObject), rFlySet, aGrSet);
3112     else
3113     {
3114         const SdrGrafObj *pGrf= (const SdrGrafObj*)rpObject;
3115         bool bDone = false;
3116         if (pGrf->IsLinkedGraphic() && pGrf->GetFileName().Len())
3117         {
3118             GraphicType eType = pGrf->GetGraphicType();
3119             String aGrfName(
3120                 URIHelper::SmartRel2Abs(
3121                     INetURLObject(sBaseURL), pGrf->GetFileName(),
3122                     URIHelper::GetMaybeFileHdl()));
3123             // --> OD 2005-07-04 #124117# - correction of fix for issue #i10939#:
3124             // One of the two conditions have to be true to insert the graphic
3125             // as a linked graphic -
3126             if (GRAPHIC_NONE == eType || CanUseRemoteLink(aGrfName))
3127             // <--
3128             {
3129                 pRetFrmFmt = rDoc.Insert(*pPaM, aGrfName, aEmptyStr, 0,
3130                     &rFlySet, &aGrSet, NULL);
3131                 bDone = true;
3132             }
3133         }
3134         if (!bDone)
3135         {
3136             const Graphic& rGraph = pGrf->GetGraphic();
3137             pRetFrmFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &rGraph,
3138                 &rFlySet, &aGrSet, NULL);
3139         }
3140     }
3141 
3142     if (pRetFrmFmt)
3143     {
3144         if( pRecord )
3145         {
3146             if( OBJ_OLE2 != SdrObjKind(rpObject->GetObjIdentifier()) )
3147                 SetAttributesAtGrfNode( pRecord, pRetFrmFmt, pF );
3148         }
3149         // mehrfaches Auftreten gleicher Grafik-Namen vermeiden
3150         maGrfNameGenerator.SetUniqueGraphName(pRetFrmFmt, aObjectName);
3151     }
3152     //falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste
3153     //entsprechend korrigieren (oder Eintrag loeschen)
3154     rpOurNewObject = CreateContactObject(pRetFrmFmt);
3155 
3156     // altes Objekt aus der Z-Order-Liste entfernen
3157     pMSDffManager->RemoveFromShapeOrder( rpObject );
3158     // aus der Drawing-Page rausnehmen
3159     if( rpObject->GetPage() )
3160         pDrawPg->RemoveObject( rpObject->GetOrdNum() );
3161 
3162     // und das Objekt loeschen
3163     SdrObject::Free( rpObject );
3164     /*
3165         Achtung: ab jetzt nur noch pOrgShapeObject abfragen!
3166     */
3167 
3168     // Kontakt-Objekt in die Z-Order-Liste und die Page aufnehmen
3169     if (rpOurNewObject)
3170     {
3171         if (!bHdFtFtnEdn)
3172             pMSDffManager->StoreShapeOrder(pF->nSpId, 0, rpOurNewObject, 0 );
3173 
3174         // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit in
3175         // SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden kann !!!
3176         if (!rpOurNewObject->IsInserted())
3177         {
3178             // --> OD 2004-12-13 #117915# - pass information, if object
3179             // is in page header|footer to method.
3180             pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
3181                                            bIsHeader || bIsFooter );
3182             // <--
3183         }
3184     }
3185     return pRetFrmFmt;
3186 }
3187 
3188 void SwWW8ImplReader::GrafikCtor()  // Fuer SVDraw und VCControls und Escher
3189 {
3190     if (!pDrawModel)
3191     {
3192         // --> OD 2005-08-08 #i52858# - method name changed
3193         rDoc.GetOrCreateDrawModel();
3194         // <--
3195         pDrawModel  = rDoc.GetDrawModel();
3196         ASSERT(pDrawModel, "Kann DrawModel nicht anlegen");
3197         pDrawPg = pDrawModel->GetPage(0);
3198 
3199         pMSDffManager = new SwMSDffManager(*this);
3200         pMSDffManager->SetModel(pDrawModel, 1440);
3201         /*
3202          #79055#
3203          Now the dff manager always needs a controls //converter as well, but a
3204          control converter may still exist //without a dffmanager. cmc
3205         */
3206         pFormImpl = new SwMSConvertControls(mpDocShell, pPaM);
3207 
3208         pWWZOrder = new wwZOrderer(sw::util::SetLayer(rDoc), pDrawPg,
3209             pMSDffManager ? pMSDffManager->GetShapeOrders() : 0);
3210     }
3211 }
3212 
3213 void SwWW8ImplReader::GrafikDtor()
3214 {
3215     DELETEZ(mpDrawEditEngine); // evtl. von Grafik angelegt
3216     DELETEZ(pWWZOrder);       // dito
3217 }
3218 
3219 void SwWW8FltAnchorStack::AddAnchor(const SwPosition& rPos, SwFrmFmt *pFmt)
3220 {
3221     ASSERT(pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR,
3222         "Don't use fltanchors with inline frames, slap!");
3223     NewAttr(rPos, SwFltAnchor(pFmt));
3224 }
3225 
3226 void SwWW8FltAnchorStack::Flush()
3227 {
3228     sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count());
3229     for (sal_uInt16 i=0; i < nCnt; ++i)
3230     {
3231         SwFltStackEntry *pEntry = (*this)[i];
3232         SwPosition aDummy(pEntry->nMkNode);
3233         SetAttrInDoc(aDummy,pEntry);
3234         DeleteAndDestroy(i--);
3235         --nCnt;
3236     }
3237 }
3238 
3239 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
3240