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