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