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