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