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