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