1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sw.hxx"
24
25 #include <com/sun/star/embed/Aspects.hpp>
26 #include <hintids.hxx>
27 #define _SVSTDARR_ULONGSSORT
28 #define _SVSTDARR_USHORTS
29 #include <svl/svstdarr.hxx>
30 #include <vcl/cvtgrf.hxx>
31 #include <vcl/virdev.hxx>
32 #include <com/sun/star/drawing/XShape.hpp>
33 #include <vcl/svapp.hxx>
34 #include <sot/storage.hxx>
35 #include <svtools/filter.hxx>
36 #include <svl/itemiter.hxx>
37 #include <svx/svdobj.hxx>
38 #include <svx/svdotext.hxx>
39 #include <svx/svdmodel.hxx>
40 #include <svx/svdpage.hxx>
41 #include <editeng/outlobj.hxx>
42 #include <editeng/editobj.hxx>
43 #include <svx/unoshape.hxx>
44 #include <editeng/brshitem.hxx>
45 #include <editeng/boxitem.hxx>
46 #include <editeng/lrspitem.hxx>
47 #include <editeng/ulspitem.hxx>
48 #include <editeng/fontitem.hxx>
49 #include <editeng/frmdiritem.hxx>
50 #include <svx/svdoole2.hxx>
51 #include <editeng/editeng.hxx>
52 #ifndef _SVX_FLDITEM_HXX
53 //miserable hack to get around #98519#
54 #include <editeng/flditem.hxx>
55 #endif
56 #include <comphelper/seqstream.hxx>
57 #include <unotools/ucbstreamhelper.hxx>
58 #include <svtools/filter.hxx>
59 #include <svx/fmglob.hxx>
60 #include <svx/svdouno.hxx>
61 #include <svx/unoapi.hxx>
62 #include <svx/svdview.hxx>
63 #include <fmtcnct.hxx>
64 #include <fmtanchr.hxx>
65 #include <fmtsrnd.hxx>
66 #include <fmtornt.hxx>
67 #include <fmtfsize.hxx>
68 #include <fmtfollowtextflow.hxx>
69 #include <dcontact.hxx>
70 #include <frmfmt.hxx>
71 #include <fmtcntnt.hxx>
72 #include <ndindex.hxx>
73 #include <doc.hxx>
74 #include <docary.hxx>
75 #include <pam.hxx>
76 #include <swrect.hxx>
77 #include <ndgrf.hxx>
78 #include <grfatr.hxx>
79 #include <ndole.hxx>
80 #include <unodraw.hxx>
81 #include <pagedesc.hxx>
82 #include <ww8par.hxx>
83 #include <breakit.hxx>
84 #include <com/sun/star/i18n/ScriptType.hdl>
85 #include "ww8attributeoutput.hxx"
86 #include "writerhelper.hxx"
87 #include "writerwordglue.hxx"
88 #include "wrtww8.hxx"
89 #include "escher.hxx"
90 #include <ndtxt.hxx>
91 #include "WW8FFData.hxx"
92 #include <editeng/shaditem.hxx>
93 #include <svx/unoapi.hxx>
94 #include <escher.hxx>
95 #include <fmtinfmt.hxx>
96 #include <fmturl.hxx>
97 #include "sfx2/sfxsids.hrc"
98 #include <svl/urihelper.hxx>
99 #include <unotools/saveopt.hxx>
100 #include <drawdoc.hxx>
101
102 using namespace com::sun::star;
103 using namespace sw::util;
104 using namespace sw::types;
105 using namespace nsFieldFlags;
106 using ::com::sun::star::uno::Reference;
107 using ::com::sun::star::uno::UNO_QUERY;
108 using ::com::sun::star::beans::XPropertySet;
109 using ::com::sun::star::drawing::XShape;
110
IsRelUrl()111 bool SwBasicEscherEx::IsRelUrl()
112 {
113 SvtSaveOptions aSaveOpt;
114 bool bRelUrl = false;
115 SfxMedium * pMedium = rWrt.GetWriter().GetMedia();
116 if ( pMedium )
117 bRelUrl = pMedium->IsRemote() ? aSaveOpt.IsSaveRelINet() : aSaveOpt.IsSaveRelFSys();
118 return bRelUrl;
119 }
120
GetBasePath()121 String SwBasicEscherEx::GetBasePath()
122 {
123 String sDocUrl;
124 String sBasePath;
125 SfxMedium * pMedium = rWrt.GetWriter().GetMedia();
126 if ( pMedium )
127 {
128 const SfxItemSet* pPItemSet = pMedium->GetItemSet();
129 if( pPItemSet )
130 {
131 const SfxStringItem* pPItem = dynamic_cast< const SfxStringItem* >( pPItemSet->GetItem( SID_FILE_NAME ) );
132 if ( pPItem )
133 sDocUrl = pPItem->GetValue();
134 }
135 }
136
137 sBasePath = sDocUrl.Copy( 0, sDocUrl.SearchBackward( '/' ) + 1 );
138 return sBasePath;
139
140 }
141
BuildFileName(sal_uInt16 & rnLevel,bool & rbRel,const String & rUrl)142 String SwBasicEscherEx::BuildFileName(sal_uInt16& rnLevel, bool& rbRel, const String& rUrl )
143 {
144 String aDosName( INetURLObject( rUrl ).getFSysPath( INetURLObject::FSYS_DOS ) );
145 rnLevel = 0;
146 rbRel = IsRelUrl();
147
148 if( rbRel )
149 {
150 // try to convert to relative file name
151 String aTmpName( aDosName );
152 aDosName = INetURLObject::GetRelURL( GetBasePath(), rUrl,
153 INetURLObject::WAS_ENCODED, INetURLObject::DECODE_WITH_CHARSET );
154
155 if( aDosName.SearchAscii( INET_FILE_SCHEME ) == 0 )
156 {
157 // not converted to rel -> back to old, return absolute flag
158 aDosName = aTmpName;
159 rbRel = false;
160 }
161 else if( aDosName.SearchAscii( "./" ) == 0 )
162 {
163 aDosName.Erase( 0, 2 );
164 }
165 else
166 {
167 while( aDosName.SearchAndReplaceAscii( "../", String::EmptyString() ) == 0 )
168 ++rnLevel;
169 }
170 }
171 return aDosName;
172 }
173
WriteHyperlinkWithinFly(SvMemoryStream & rStrm,const SwFmtURL * pINetFmtArg)174 void SwBasicEscherEx::WriteHyperlinkWithinFly( SvMemoryStream& rStrm, const SwFmtURL* pINetFmtArg)
175 {
176 if ( !pINetFmtArg ) return;
177
178 sal_uInt8 maGuidStdLink[ 16 ] ={
179 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
180 sal_uInt8 maGuidUrlMoniker[ 16 ] = {
181 0xE0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
182
183 sal_uInt8 maGuidFileMoniker[ 16 ] = {
184 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
185 sal_uInt8 maGuidFileTail[] = {
186 0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
187 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
189 };
190 //const sal_uInt16 WW8_ID_HLINK = 0x01B8;
191 const sal_uInt32 WW8_HLINK_BODY = 0x00000001; /// Contains file link or URL.
192 const sal_uInt32 WW8_HLINK_ABS = 0x00000002; /// Absolute path.
193 //const sal_uInt32 WW8_HLINK_DESCR = 0x00000014; /// Description.
194 const sal_uInt32 WW8_HLINK_MARK = 0x00000008; /// Text mark.
195 const sal_uInt32 WW8_HLINK_FRAME = 0x00000080; /// Target frame.
196 //const sal_uInt32 WW8_HLINK_UNC = 0x00000100; /// UNC path.
197 SvMemoryStream tmpStrm;
198 String tmpTextMark;
199
200 String rUrl = pINetFmtArg->GetURL();
201 String rTarFrm = pINetFmtArg->GetTargetFrameName();
202 sal_uInt32 mnFlags = 0;
203
204 INetURLObject aUrlObj( rUrl );
205 const INetProtocol eProtocol = aUrlObj.GetProtocol();
206
207 //Target Frame
208 if( rTarFrm.Len() > 0 )
209 {
210 SwWW8Writer::WriteLong( tmpStrm, rTarFrm.Len()+1 );
211 SwWW8Writer::WriteString16( tmpStrm, rTarFrm, false);
212
213 tmpStrm << sal_uInt16( 0 );
214
215 mnFlags |= WW8_HLINK_FRAME;
216 }
217
218 // file link or URL
219 if( eProtocol == INET_PROT_FILE || (eProtocol == INET_PROT_NOT_VALID && rUrl.GetChar( 0 ) != '#') )
220 {
221 sal_uInt16 nLevel;
222 bool bRel;
223 String aFileName( BuildFileName( nLevel, bRel, rUrl ));
224
225 if( !bRel )
226 mnFlags |= WW8_HLINK_ABS;
227
228 mnFlags |= WW8_HLINK_BODY;
229
230 tmpStrm.Write( maGuidFileMoniker,sizeof(maGuidFileMoniker) );
231 tmpStrm << nLevel;
232 SwWW8Writer::WriteLong( tmpStrm, aFileName.Len()+1);
233 SwWW8Writer::WriteString8( tmpStrm, aFileName, true, RTL_TEXTENCODING_MS_1252 );
234 tmpStrm.Write( maGuidFileTail,sizeof(maGuidFileTail) );
235
236 //For UNICODE
237 SwWW8Writer::WriteLong( tmpStrm, 2*aFileName.Len()+6);
238 SwWW8Writer::WriteLong( tmpStrm, 2*aFileName.Len());
239 tmpStrm << sal_uInt16(0x0003);
240 SwWW8Writer::WriteString16(tmpStrm, aFileName, false);
241 }
242 else if( eProtocol != INET_PROT_NOT_VALID )
243 {
244 tmpStrm.Write( maGuidUrlMoniker,sizeof(maGuidUrlMoniker) );
245 SwWW8Writer::WriteLong( tmpStrm, 2*(rUrl.Len()+1));
246
247 SwWW8Writer::WriteString16(tmpStrm, rUrl, true);
248 mnFlags |= WW8_HLINK_BODY | WW8_HLINK_ABS;
249 }
250 else if( rUrl.GetChar( 0 ) == '#' )
251 {
252 String aTextMark( rUrl.Copy( 1 ) );
253 aTextMark.SearchAndReplace( '.', '!' );
254 //sal_uInt8 tmpLen = aTextMark.Len();
255 tmpTextMark = aTextMark;
256 }
257
258 if( tmpTextMark.Len() == 0 && aUrlObj.HasMark() )
259 {
260 tmpTextMark = aUrlObj.GetMark();
261 }
262
263 if( tmpTextMark.Len()>0 )
264 {
265 SwWW8Writer::WriteLong( tmpStrm, tmpTextMark.Len()+1);
266 SwWW8Writer::WriteString16(tmpStrm, tmpTextMark, true);
267
268 mnFlags |= WW8_HLINK_MARK;
269 }
270
271 rStrm.Write( maGuidStdLink,16 );
272 rStrm << sal_uInt32( 2 )
273 << mnFlags;
274 tmpStrm.Seek( STREAM_SEEK_TO_BEGIN );
275 sal_uInt32 nStrmPos = tmpStrm.Tell();
276 tmpStrm.Seek( STREAM_SEEK_TO_END );
277 sal_uInt32 nStrmSize = tmpStrm.Tell();
278 tmpStrm.Seek( nStrmPos );
279 sal_uInt32 nLen;
280 nLen = nStrmSize - nStrmPos;
281 if(nLen >0)
282 {
283 sal_uInt8* pBuffer = new sal_uInt8[ nLen ];
284 tmpStrm.Read(pBuffer, nLen);
285 rStrm.Write( pBuffer, nLen );
286 delete[] pBuffer;
287 }
288 }
PreWriteHyperlinkWithinFly(const SwFrmFmt & rFmt,EscherPropertyContainer & rPropOpt)289 void SwBasicEscherEx::PreWriteHyperlinkWithinFly(const SwFrmFmt& rFmt,EscherPropertyContainer& rPropOpt)
290 {
291 const SfxPoolItem* pItem;
292 const SwAttrSet& rAttrSet = rFmt.GetAttrSet();
293 if (SFX_ITEM_SET == rAttrSet.GetItemState(RES_URL, true, &pItem))
294 {
295 const SwFmtURL *pINetFmt = dynamic_cast<const SwFmtURL*>(pItem);
296 if(pINetFmt && pINetFmt->GetURL().Len()>0)
297 {
298 SvMemoryStream *rStrm = new SvMemoryStream ;
299 String tmpstr=pINetFmt->GetURL();
300 WriteHyperlinkWithinFly( *rStrm, pINetFmt );
301 sal_uInt8* pBuf = (sal_uInt8*) rStrm->GetData();
302 sal_uInt32 nSize = rStrm->Seek( STREAM_SEEK_TO_END );
303 rPropOpt.AddOpt( ESCHER_Prop_pihlShape, sal_True, nSize, pBuf, nSize );
304 sal_uInt32 nValue;
305 String aNamestr = pINetFmt->GetName();
306 if(aNamestr.Len()>0)
307 {
308 rPropOpt.AddOpt(ESCHER_Prop_wzName, aNamestr );
309 }
310 if(rPropOpt.GetOpt( ESCHER_Prop_fPrint, nValue))
311 {
312 nValue|=0x03080008;
313 rPropOpt.AddOpt(ESCHER_Prop_fPrint, nValue );
314 }
315 else
316 rPropOpt.AddOpt(ESCHER_Prop_fPrint, 0x03080008 );
317 }
318 }
319 }
320
321 //#110185# get a part fix for this type of element
MiserableFormFieldExportHack(const SwFrmFmt & rFrmFmt)322 bool WW8Export::MiserableFormFieldExportHack(const SwFrmFmt& rFrmFmt)
323 {
324 ASSERT(bWrtWW8, "Not allowed");
325 if (!bWrtWW8)
326 return false;
327 bool bHack = false;
328 const SdrObject *pObject = rFrmFmt.FindRealSdrObject();
329 if (pObject && pObject->GetObjInventor() == FmFormInventor)
330 {
331 if (SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObject))
332 {
333 uno::Reference< awt::XControlModel > xControlModel =
334 pFormObj->GetUnoControlModel();
335 uno::Reference< lang::XServiceInfo > xInfo(xControlModel,
336 uno::UNO_QUERY);
337 uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
338 if (xInfo->supportsService(C2U("com.sun.star.form.component.ComboBox")))
339 {
340 DoComboBox(xPropSet);
341 bHack = true;
342 }
343 else if (xInfo->supportsService(C2U("com.sun.star.form.component.CheckBox")))
344 {
345 DoCheckBox(xPropSet);
346 bHack = true;
347 }
348 }
349 }
350 return bHack;
351 }
352
353
DoComboBox(uno::Reference<beans::XPropertySet> xPropSet)354 void WW8Export::DoComboBox(uno::Reference<beans::XPropertySet> xPropSet)
355 {
356 rtl::OUString sSelected;
357 uno::Sequence<rtl::OUString> aListItems;
358 xPropSet->getPropertyValue(C2U("StringItemList")) >>= aListItems;
359 sal_Int32 nNoStrings = aListItems.getLength();
360 if (nNoStrings)
361 {
362 uno::Any aTmp = xPropSet->getPropertyValue(C2U("DefaultText"));
363 const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
364 if (pStr)
365 sSelected = *pStr;
366 }
367
368 rtl::OUString sName;
369 {
370 uno::Any aTmp = xPropSet->getPropertyValue(C2U("Name"));
371 const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
372 if (pStr)
373 sName = *pStr;
374 }
375
376
377 rtl::OUString sHelp;
378 {
379 // --> OD 2010-05-14 #160026#
380 // property "Help" does not exist and due to the no-existence an exception is thrown.
381 // uno::Any aTmp = xPropSet->getPropertyValue(C2U("Help"));
382 try
383 {
384 uno::Any aTmp = xPropSet->getPropertyValue(C2U("HelpText"));
385 // <--
386 const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
387 if (pStr)
388 sHelp = *pStr;
389 }
390 catch( uno::Exception& )
391 {}
392 // <--
393 }
394
395 rtl::OUString sToolTip;
396 {
397 uno::Any aTmp = xPropSet->getPropertyValue(C2U("Name"));
398 const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
399 if (pStr)
400 sToolTip = *pStr;
401 }
402
403 DoComboBox(sName, sHelp, sToolTip, sSelected, aListItems);
404 }
405
DoComboBox(const rtl::OUString & rName,const rtl::OUString & rHelp,const rtl::OUString & rToolTip,const rtl::OUString & rSelected,uno::Sequence<rtl::OUString> & rListItems)406 void WW8Export::DoComboBox(const rtl::OUString &rName,
407 const rtl::OUString &rHelp,
408 const rtl::OUString &rToolTip,
409 const rtl::OUString &rSelected,
410 uno::Sequence<rtl::OUString> &rListItems)
411 {
412 ASSERT(bWrtWW8, "Not allowed");
413 if (!bWrtWW8)
414 return;
415 OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
416 WRITEFIELD_START | WRITEFIELD_CMD_START);
417 // write the refence to the "picture" structure
418 sal_uLong nDataStt = pDataStrm->Tell();
419 pChpPlc->AppendFkpEntry( Strm().Tell() );
420
421 WriteChar( 0x01 );
422
423 static sal_uInt8 aArr1[] =
424 {
425 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
426 0x06, 0x08, 0x01, // sprmCFData
427 0x55, 0x08, 0x01, // sprmCFSpec
428 0x02, 0x08, 0x01 // sprmCFFldVanish
429 };
430 sal_uInt8* pDataAdr = aArr1 + 2;
431 Set_UInt32( pDataAdr, nDataStt );
432
433 pChpPlc->AppendFkpEntry(Strm().Tell(), sizeof(aArr1), aArr1);
434
435 OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
436 WRITEFIELD_CLOSE);
437
438 ::sw::WW8FFData aFFData;
439
440 aFFData.setType(2);
441 aFFData.setName(rName);
442 aFFData.setHelp(rHelp);
443 aFFData.setStatus(rToolTip);
444
445 sal_uInt32 nListItems = rListItems.getLength();
446
447 for (sal_uInt32 i = 0; i < nListItems; i++)
448 {
449 if (i < 0x20 && rSelected == rListItems[i])
450 aFFData.setResult(::sal::static_int_cast<sal_uInt8>(i));
451 aFFData.addListboxEntry(rListItems[i]);
452 }
453
454 aFFData.Write(pDataStrm);
455 }
456
DoCheckBox(uno::Reference<beans::XPropertySet> xPropSet)457 void WW8Export::DoCheckBox(uno::Reference<beans::XPropertySet> xPropSet)
458 {
459 uno::Reference<beans::XPropertySetInfo> xPropSetInfo =
460 xPropSet->getPropertySetInfo();
461
462 OutputField(0, ww::eFORMCHECKBOX, FieldString(ww::eFORMCHECKBOX),
463 WRITEFIELD_START | WRITEFIELD_CMD_START);
464 // write the refence to the "picture" structure
465 sal_uLong nDataStt = pDataStrm->Tell();
466 pChpPlc->AppendFkpEntry( Strm().Tell() );
467
468 WriteChar( 0x01 );
469 static sal_uInt8 aArr1[] = {
470 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
471
472 0x06, 0x08, 0x01, // sprmCFData
473 0x55, 0x08, 0x01, // sprmCFSpec
474 0x02, 0x08, 0x01 // sprmCFFldVanish
475 };
476 sal_uInt8* pDataAdr = aArr1 + 2;
477 Set_UInt32( pDataAdr, nDataStt );
478
479 pChpPlc->AppendFkpEntry(Strm().Tell(),
480 sizeof( aArr1 ), aArr1 );
481
482 ::sw::WW8FFData aFFData;
483
484 aFFData.setType(1);
485 aFFData.setCheckboxHeight(0x14);
486
487 sal_Int16 nTemp = 0;
488 xPropSet->getPropertyValue(C2U("DefaultState")) >>= nTemp;
489 aFFData.setDefaultResult(nTemp);
490
491 xPropSet->getPropertyValue(C2U("State")) >>= nTemp;
492 aFFData.setResult(nTemp);
493
494 ::rtl::OUString aStr;
495 static ::rtl::OUString sName(C2U("Name"));
496 if (xPropSetInfo->hasPropertyByName(sName))
497 {
498 xPropSet->getPropertyValue(sName) >>= aStr;
499 aFFData.setName(aStr);
500 }
501
502 static ::rtl::OUString sHelpText(C2U("HelpText"));
503 if (xPropSetInfo->hasPropertyByName(sHelpText))
504 {
505 xPropSet->getPropertyValue(sHelpText) >>= aStr;
506 aFFData.setHelp(aStr);
507 }
508 static ::rtl::OUString sHelpF1Text(C2U("HelpF1Text"));
509 if (xPropSetInfo->hasPropertyByName(sHelpF1Text))
510 {
511 xPropSet->getPropertyValue(sHelpF1Text) >>= aStr;
512 aFFData.setStatus(aStr);
513 }
514
515 aFFData.Write(pDataStrm);
516
517 OutputField(0, ww::eFORMCHECKBOX, aEmptyStr, WRITEFIELD_CLOSE);
518 }
519
DoFormText(const SwInputField * pFld)520 void WW8Export::DoFormText(const SwInputField * pFld)
521 {
522 OutputField(0, ww::eFORMTEXT, FieldString(ww::eFORMTEXT),
523 WRITEFIELD_START | WRITEFIELD_CMD_START);
524 // write the refence to the "picture" structure
525 sal_uLong nDataStt = pDataStrm->Tell();
526 pChpPlc->AppendFkpEntry( Strm().Tell() );
527
528 WriteChar( 0x01 );
529 static sal_uInt8 aArr1[] = {
530 0x02, 0x08, 0x81, // sprmCFFldVanish
531 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
532
533 0x06, 0x08, 0x01, // sprmCFData
534 0x55, 0x08, 0x01 // sprmCFSpec
535 };
536 sal_uInt8* pDataAdr = aArr1 + 5;
537 Set_UInt32( pDataAdr, nDataStt );
538
539 pChpPlc->AppendFkpEntry(Strm().Tell(),
540 sizeof( aArr1 ), aArr1 );
541
542 ::sw::WW8FFData aFFData;
543
544 aFFData.setType(0);
545 aFFData.setName(pFld->GetPar2());
546 aFFData.setHelp(pFld->GetHelp());
547 aFFData.setStatus(pFld->GetToolTip());
548 aFFData.Write(pDataStrm);
549
550 OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CMD_END);
551
552 const String fieldStr( pFld->ExpandField(true) );
553 SwWW8Writer::WriteString16(Strm(), fieldStr, false);
554
555 static sal_uInt8 aArr2[] = {
556 0x55, 0x08, 0x01, // sprmCFSpec
557 0x75, 0x08, 0x01 // ???
558 };
559
560 pDataAdr = aArr2 + 2;
561 Set_UInt32( pDataAdr, nDataStt );
562 pChpPlc->AppendFkpEntry(Strm().Tell(),
563 sizeof( aArr2 ), aArr2 );
564
565 OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CLOSE);
566 }
567
~PlcDrawObj()568 PlcDrawObj::~PlcDrawObj()
569 {
570 }
571
572 //Its irritating to have to change the RTL frames position into LTR ones
573 //so that word will have to place them in the right place. Doubly so that
574 //the SO drawings and writer frames have different ideas themselves as to
575 //how to be positioned when in RTL mode!
RTLGraphicsHack(SwTwips & rLeft,SwTwips nWidth,sal_Int16 eHoriOri,sal_Int16 eHoriRel,SwTwips nPageLeft,SwTwips nPageRight,SwTwips nPageSize)576 bool RTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
577 sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
578 SwTwips nPageRight, SwTwips nPageSize)
579 {
580 bool bRet = false;
581 if (eHoriOri == text::HoriOrientation::NONE)
582 {
583 if (eHoriRel == text::RelOrientation::PAGE_FRAME)
584 {
585 rLeft = nPageSize - rLeft;
586 bRet = true;
587 }
588 else if (
589 (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
590 (eHoriRel == text::RelOrientation::FRAME) ||
591 (eHoriRel == text::RelOrientation::PRINT_AREA)
592 )
593 {
594 rLeft = nPageSize - nPageLeft - nPageRight - rLeft;
595 bRet = true;
596 }
597 }
598 if (bRet)
599 rLeft -= nWidth;
600 return bRet;
601 }
602
RTLDrawingsHack(long & rLeft,long,sal_Int16 eHoriOri,sal_Int16 eHoriRel,SwTwips nPageLeft,SwTwips nPageRight,SwTwips nPageSize)603 bool RTLDrawingsHack(long &rLeft, long /*nWidth*/,
604 sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
605 SwTwips nPageRight, SwTwips nPageSize)
606 {
607 bool bRet = false;
608 if (eHoriOri == text::HoriOrientation::NONE)
609 {
610 if (eHoriRel == text::RelOrientation::PAGE_FRAME)
611 {
612 rLeft = nPageSize + rLeft;
613 bRet = true;
614 }
615 else if (
616 (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
617 (eHoriRel == text::RelOrientation::FRAME) ||
618 (eHoriRel == text::RelOrientation::PRINT_AREA)
619 )
620 {
621 rLeft = nPageSize - nPageLeft - nPageRight + rLeft;
622 bRet = true;
623 }
624 }
625 return bRet;
626 }
627
MiserableRTLFrmFmtHack(SwTwips & rLeft,SwTwips & rRight,const sw::Frame & rFrmFmt)628 bool WW8Export::MiserableRTLFrmFmtHack(SwTwips &rLeft, SwTwips &rRight,
629 const sw::Frame &rFrmFmt)
630 {
631 //Require nasty bidi swap
632 if (FRMDIR_HORI_RIGHT_TOP != pDoc->GetTextDirection(rFrmFmt.GetPosition()))
633 return false;
634
635 SwTwips nWidth = rRight - rLeft;
636 SwTwips nPageLeft, nPageRight;
637 SwTwips nPageSize = CurrentPageWidth(nPageLeft, nPageRight);
638
639 const SwFmtHoriOrient& rHOr = rFrmFmt.GetFrmFmt().GetHoriOrient();
640
641 bool bRet = false;
642 sw::Frame::WriterSource eSource = rFrmFmt.GetWriterType();
643 if (eSource == sw::Frame::eDrawing || eSource == sw::Frame::eFormControl)
644 {
645 if (RTLDrawingsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
646 rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
647 {
648 bRet = true;
649 }
650 }
651 else
652 {
653 if (RTLGraphicsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
654 rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
655 {
656 bRet = true;
657 }
658 }
659 if (bRet)
660 rRight = rLeft + nWidth;
661 return bRet;
662 }
663
WritePlc(WW8Export & rWrt) const664 void PlcDrawObj::WritePlc( WW8Export& rWrt ) const
665 {
666 if (8 > rWrt.pFib->nVersion) // Cannot export drawobject in vers 7-
667 return;
668
669 sal_uInt32 nFcStart = rWrt.pTableStrm->Tell();
670
671 if (!maDrawObjs.empty())
672 {
673 // write CPs
674 WW8Fib& rFib = *rWrt.pFib;
675 WW8_CP nCpOffs = GetCpOffset(rFib);
676
677 cDrawObjIter aEnd = maDrawObjs.end();
678 cDrawObjIter aIter;
679
680 for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
681 SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnCp - nCpOffs);
682
683 SwWW8Writer::WriteLong(*rWrt.pTableStrm, rFib.ccpText + rFib.ccpFtn +
684 rFib.ccpHdr + rFib.ccpEdn + rFib.ccpTxbx + rFib.ccpHdrTxbx + 1);
685
686 for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
687 {
688 // write the fspa-struct
689 const sw::Frame &rFrmFmt = aIter->maCntnt;
690 const SwFrmFmt &rFmt = rFrmFmt.GetFrmFmt();
691 const SdrObject* pObj = rFmt.FindRealSdrObject();
692
693 Rectangle aRect;
694 SwFmtVertOrient rVOr = rFmt.GetVertOrient();
695 SwFmtHoriOrient rHOr = rFmt.GetHoriOrient();
696 // --> OD 2005-01-06 #i30669# - convert the positioning attributes.
697 // Most positions are converted, if layout information exists.
698 const bool bPosConverted =
699 WinwordAnchoring::ConvertPosition( rHOr, rVOr, rFmt );
700 // <--
701
702 Point aObjPos;
703 if (RES_FLYFRMFMT == rFmt.Which())
704 {
705 SwRect aLayRect(rFmt.FindLayoutRect(false, &aObjPos));
706 // the Object is not visible - so get the values from
707 // the format. The Position may not be correct.
708 if( aLayRect.IsEmpty() )
709 aRect.SetSize( rFmt.GetFrmSize().GetSize() );
710 else
711 {
712 // --> FME 2007-06-20 #i56090# Do not only consider the first client
713 // Note that we actually would have to find the maximum size of the
714 // frame format clients. However, this already should work in most cases.
715 const SwRect aSizeRect(rFmt.FindLayoutRect());
716 if ( aSizeRect.Width() > aLayRect.Width() )
717 aLayRect.Width( aSizeRect.Width() );
718 // <--
719
720 aRect = aLayRect.SVRect();
721 }
722 }
723 else
724 {
725 ASSERT(pObj, "wo ist das SDR-Object?");
726 if (pObj)
727 {
728 aRect = pObj->GetSnapRect();
729 }
730 }
731
732 // --> OD 2005-01-06 #i30669# - use converted position, if conversion
733 // is performed. Unify position determination of Writer fly frames
734 // and drawing objects.
735 if ( bPosConverted )
736 {
737 aRect.SetPos( Point( rHOr.GetPos(), rVOr.GetPos() ) );
738 }
739 else
740 {
741 aRect -= aIter->maParentPos;
742 aObjPos = aRect.TopLeft();
743 if (text::VertOrientation::NONE == rVOr.GetVertOrient())
744 {
745 // CMC, OD 24.11.2003 #i22673#
746 sal_Int16 eOri = rVOr.GetRelationOrient();
747 if (eOri == text::RelOrientation::CHAR || eOri == text::RelOrientation::TEXT_LINE)
748 aObjPos.Y() = -rVOr.GetPos();
749 else
750 aObjPos.Y() = rVOr.GetPos();
751 }
752 if (text::HoriOrientation::NONE == rHOr.GetHoriOrient())
753 aObjPos.X() = rHOr.GetPos();
754 aRect.SetPos( aObjPos );
755 }
756 // <--
757
758 sal_Int32 nThick = aIter->mnThick;
759
760 //If we are being exported as an inline hack, set
761 //corner to 0 and forget about border thickness for positioning
762 if (rFrmFmt.IsInline())
763 {
764 aRect.SetPos(Point(0,0));
765 nThick = 0;
766 }
767
768 // spid
769 SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnShapeId);
770
771 SwTwips nLeft = aRect.Left() + nThick;
772 SwTwips nRight = aRect.Right() - nThick;
773
774 //Nasty swap for bidi if necessary
775 rWrt.MiserableRTLFrmFmtHack(nLeft, nRight, rFrmFmt);
776
777 //xaLeft/yaTop/xaRight/yaBottom - rel. to anchor
778 //(most of) the border is outside the graphic is word, so
779 //change dimensions to fit
780 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nLeft);
781 SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Top() + nThick);
782 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nRight);
783 SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Bottom() - nThick);
784
785 //fHdr/bx/by/wr/wrk/fRcaSimple/fBelowText/fAnchorLock
786 sal_uInt16 nFlags=0;
787 //If nFlags isn't 0x14 its overridden by the escher properties
788 if (FLY_AT_PAGE == rFmt.GetAnchor().GetAnchorId())
789 nFlags = 0x0000;
790 else
791 nFlags = 0x0014; // x-rel to text, y-rel to text
792
793 const SwFmtSurround& rSurr = rFmt.GetSurround();
794 sal_uInt16 nContour = rSurr.IsContour() ? 0x0080 : 0x0040;
795 SwSurround eSurround = rSurr.GetSurround();
796
797 /*
798 #i3958#
799 The inline elements being export as anchored to character inside
800 the shape field hack are required to be wrap through so as to flow
801 over the following dummy 0x01 graphic
802 */
803 if (rFrmFmt.IsInline())
804 eSurround = SURROUND_THROUGHT;
805
806 switch (eSurround)
807 {
808 case SURROUND_NONE:
809 nFlags |= 0x0020;
810 break;
811 case SURROUND_THROUGHT:
812 nFlags |= 0x0060;
813 break;
814 case SURROUND_PARALLEL:
815 nFlags |= 0x0000 | nContour;
816 break;
817 case SURROUND_IDEAL:
818 nFlags |= 0x0600 | nContour;
819 break;
820 case SURROUND_LEFT:
821 nFlags |= 0x0200 | nContour;
822 break;
823 case SURROUND_RIGHT:
824 nFlags |= 0x0400 | nContour;
825 break;
826 default:
827 ASSERT(sal_False, "Unsupported surround type for export");
828 break;
829 }
830 if (pObj && (pObj->GetLayer() == rWrt.pDoc->GetHellId() ||
831 pObj->GetLayer() == rWrt.pDoc->GetInvisibleHellId()))
832 {
833 nFlags |= 0x4000;
834 }
835
836 /*
837 #i3958# Required to make this inline stuff work in WordXP, not
838 needed for 2003 interestingly
839 */
840 if (rFrmFmt.IsInline())
841 nFlags |= 0x8000;
842
843 SwWW8Writer::WriteShort(*rWrt.pTableStrm, nFlags);
844
845 // cTxbx
846 SwWW8Writer::WriteLong(*rWrt.pTableStrm, 0);
847 }
848
849 RegisterWithFib(rFib, nFcStart, rWrt.pTableStrm->Tell() - nFcStart);
850 }
851 }
852
RegisterWithFib(WW8Fib & rFib,sal_uInt32 nStart,sal_uInt32 nLen) const853 void MainTxtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
854 sal_uInt32 nLen) const
855 {
856 rFib.fcPlcfspaMom = nStart;
857 rFib.lcbPlcfspaMom = nLen;
858 }
859
GetCpOffset(const WW8Fib &) const860 WW8_CP MainTxtPlcDrawObj::GetCpOffset(const WW8Fib &) const
861 {
862 return 0;
863 }
864
RegisterWithFib(WW8Fib & rFib,sal_uInt32 nStart,sal_uInt32 nLen) const865 void HdFtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
866 sal_uInt32 nLen) const
867 {
868 rFib.fcPlcfspaHdr = nStart;
869 rFib.lcbPlcfspaHdr = nLen;
870 }
871
GetCpOffset(const WW8Fib & rFib) const872 WW8_CP HdFtPlcDrawObj::GetCpOffset(const WW8Fib &rFib) const
873 {
874 return rFib.ccpText + rFib.ccpFtn;
875 }
876
operator =(const DrawObj & rOther)877 DrawObj& DrawObj::operator=(const DrawObj& rOther)
878 {
879 mnCp = rOther.mnCp;
880 mnShapeId = rOther.mnShapeId;
881 maCntnt = rOther.maCntnt;
882 maParentPos = rOther.maParentPos;
883 mnThick = rOther.mnThick;
884 mnDirection = rOther.mnDirection;
885 mnHdFtIndex = rOther.mnHdFtIndex;
886 return *this;
887 }
888
Append(WW8Export & rWrt,WW8_CP nCp,const sw::Frame & rFmt,const Point & rNdTopLeft)889 bool PlcDrawObj::Append( WW8Export& rWrt, WW8_CP nCp, const sw::Frame& rFmt,
890 const Point& rNdTopLeft )
891 {
892 bool bRet = false;
893 const SwFrmFmt &rFormat = rFmt.GetFrmFmt();
894 if (TXT_HDFT == rWrt.nTxtTyp || TXT_MAINTEXT == rWrt.nTxtTyp)
895 {
896 if (RES_FLYFRMFMT == rFormat.Which())
897 {
898 // check for textflyframe and if it is the first in a Chain
899 if (rFormat.GetCntnt().GetCntntIdx())
900 bRet = true;
901 }
902 else
903 bRet = true;
904 }
905
906 if (bRet)
907 {
908 DrawObj aObj(rFmt, nCp, rNdTopLeft, rWrt.TrueFrameDirection(rFormat),
909 rWrt.GetHdFtIndex());
910 maDrawObjs.push_back(aObj);
911 }
912 return bRet;
913 }
914
SetShapeDetails(sal_uInt32 nId,sal_Int32 nThick)915 void DrawObj::SetShapeDetails(sal_uInt32 nId, sal_Int32 nThick)
916 {
917 mnShapeId = nId;
918 mnThick = nThick;
919 }
920
WriteTxt(WW8Export & rWrt)921 bool WW8_WrPlcTxtBoxes::WriteTxt( WW8Export& rWrt )
922 {
923 bool bRet = false;
924 rWrt.bInWriteEscher = true;
925 WW8_CP& rccp=TXT_TXTBOX == nTyp ? rWrt.pFib->ccpTxbx : rWrt.pFib->ccpHdrTxbx;
926
927 bRet = WriteGenericTxt( rWrt, nTyp, rccp );
928
929 WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
930 WW8Fib& rFib = *rWrt.pFib;
931 WW8_CP nMyOffset = rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpAtn
932 + rFib.ccpEdn;
933 if( TXT_TXTBOX == nTyp )
934 rWrt.pFldTxtBxs->Finish( nCP, nMyOffset );
935 else
936 rWrt.pFldHFTxtBxs->Finish( nCP, nMyOffset + rFib.ccpTxbx );
937 rWrt.bInWriteEscher = false;
938 return bRet;
939 }
940
Append(const SdrObject & rObj,sal_uInt32 nShapeId)941 void WW8_WrPlcTxtBoxes::Append( const SdrObject& rObj, sal_uInt32 nShapeId )
942 {
943 void* p = (void*)&rObj;
944 aCntnt.Insert( p, aCntnt.Count() );
945 aShapeIds.Insert( nShapeId, aShapeIds.Count() );
946 //save NULL, if we have an actual SdrObject
947 aSpareFmts.Insert( (void*)NULL, aSpareFmts.Count() );
948 }
949
Append(const SwFrmFmt * pFmt,sal_uInt32 nShapeId)950 void WW8_WrPlcTxtBoxes::Append( const SwFrmFmt* pFmt, sal_uInt32 nShapeId )
951 {
952 //no sdr object, we insert a NULL in the aCntnt and save the real fmt in aSpareFmts.
953 aCntnt.Insert( (void*)NULL, aCntnt.Count() );
954 aShapeIds.Insert( nShapeId, aShapeIds.Count() );
955 aSpareFmts.Insert( (void*)pFmt, aSpareFmts.Count() );
956 }
957
GetShapeIdArr() const958 const SvULongs* WW8_WrPlcTxtBoxes::GetShapeIdArr() const
959 {
960 return &aShapeIds;
961 }
962
963 /* */
964
GetSdrOrdNum(const SwFrmFmt & rFmt) const965 sal_uInt32 WW8Export::GetSdrOrdNum( const SwFrmFmt& rFmt ) const
966 {
967 sal_uInt32 nOrdNum;
968 const SdrObject* pObj = rFmt.FindRealSdrObject();
969 if( pObj )
970 nOrdNum = pObj->GetOrdNum();
971 else
972 {
973 // no Layout for this format, then recalc the ordnum
974 SwFrmFmt* pFmt = (SwFrmFmt*)&rFmt;
975 nOrdNum = pDoc->GetSpzFrmFmts()->GetPos( pFmt );
976
977 const SwDrawModel* pModel = pDoc->GetDrawModel();
978 if( pModel )
979 nOrdNum += pModel->GetPage( 0 )->GetObjCount();
980 }
981 return nOrdNum;
982 }
983
AppendFlyInFlys(const sw::Frame & rFrmFmt,const Point & rNdTopLeft)984 void WW8Export::AppendFlyInFlys(const sw::Frame& rFrmFmt,
985 const Point& rNdTopLeft)
986 {
987 ASSERT(bWrtWW8, "this has gone horribly wrong");
988 ASSERT(!pEscher, "der EscherStream wurde schon geschrieben!");
989 if (pEscher)
990 return ;
991 PlcDrawObj *pDrwO;
992 if (TXT_HDFT == nTxtTyp)
993 pDrwO = pHFSdrObjs;
994 else
995 pDrwO = pSdrObjs;
996
997 if (rFrmFmt.IsInline())
998 {
999 OutputField(0, ww::eSHAPE, FieldString(ww::eSHAPE),
1000 WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
1001 }
1002
1003 WW8_CP nCP = Fc2Cp(Strm().Tell());
1004 bool bSuccess = pDrwO->Append(*this, nCP, rFrmFmt, rNdTopLeft);
1005 ASSERT(bSuccess, "Couldn't export a graphical element!");
1006
1007 if (bSuccess)
1008 {
1009 static const sal_uInt8 aSpec8[] =
1010 {
1011 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
1012 0x55, 0x08, 1 // sprmCFSpec
1013 };
1014 // fSpec-Attribut true
1015 // Fuer DrawObjets muss ein Spezial-Zeichen
1016 // in den Text und darum ein fSpec-Attribut
1017 pChpPlc->AppendFkpEntry( Strm().Tell() );
1018 WriteChar( 0x8 );
1019 pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec8 ), aSpec8 );
1020
1021 //Need dummy picture frame
1022 if (rFrmFmt.IsInline())
1023 OutGrf(rFrmFmt);
1024 }
1025
1026 if (rFrmFmt.IsInline())
1027 OutputField(0, ww::eSHAPE, aEmptyStr, WRITEFIELD_CLOSE);
1028 }
1029
MSWord_SdrAttrIter(MSWordExportBase & rWr,const EditTextObject & rEditObj,sal_uInt8 nTyp)1030 MSWord_SdrAttrIter::MSWord_SdrAttrIter( MSWordExportBase& rWr,
1031 const EditTextObject& rEditObj, sal_uInt8 nTyp )
1032 : MSWordAttrIter( rWr ), pEditObj(&rEditObj), pEditPool(0),
1033 aTxtAtrArr( 0, 4 ), aChrTxtAtrArr( 0, 4 ), aChrSetArr( 0, 4 ),
1034 mnTyp(nTyp)
1035 {
1036 NextPara( 0 );
1037 }
1038
NextPara(sal_uInt16 nPar)1039 void MSWord_SdrAttrIter::NextPara( sal_uInt16 nPar )
1040 {
1041 nPara = nPar;
1042 // Attributwechsel an Pos 0 wird ignoriert, da davon ausgegangen
1043 // wird, dass am Absatzanfang sowieso die Attribute neu ausgegeben
1044 // werden.
1045 aChrTxtAtrArr.Remove( 0, aChrTxtAtrArr.Count() );
1046 aChrSetArr.Remove( 0, aChrSetArr.Count() );
1047 nAktSwPos = nTmpSwPos = 0;
1048
1049 SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
1050 pEditPool = aSet.GetPool();
1051 eNdChrSet = ItemGet<SvxFontItem>(aSet,EE_CHAR_FONTINFO).GetCharSet();
1052
1053 if( pBreakIt->GetBreakIter().is() )
1054 nScript = pBreakIt->GetBreakIter()->getScriptType( pEditObj->GetText(nPara), 0);
1055 else
1056 nScript = i18n::ScriptType::LATIN;
1057
1058 pEditObj->GetCharAttribs( nPara, aTxtAtrArr );
1059 nAktSwPos = SearchNext( 1 );
1060 }
1061
GetNextCharSet() const1062 rtl_TextEncoding MSWord_SdrAttrIter::GetNextCharSet() const
1063 {
1064 if( aChrSetArr.Count() )
1065 return (rtl_TextEncoding)aChrSetArr[ aChrSetArr.Count() - 1 ];
1066 return eNdChrSet;
1067 }
1068
1069 // der erste Parameter in SearchNext() liefert zurueck, ob es ein TxtAtr ist.
SearchNext(xub_StrLen nStartPos)1070 xub_StrLen MSWord_SdrAttrIter::SearchNext( xub_StrLen nStartPos )
1071 {
1072 xub_StrLen nPos;
1073 xub_StrLen nMinPos = STRING_MAXLEN;
1074 xub_StrLen i;
1075
1076 for( i = 0; i < aTxtAtrArr.Count(); i++ )
1077 {
1078 const EECharAttrib& rHt = aTxtAtrArr[ i ];
1079 nPos = rHt.nStart; // gibt erstes Attr-Zeichen
1080 if( nPos >= nStartPos && nPos <= nMinPos )
1081 {
1082 nMinPos = nPos;
1083 SetCharSet(rHt, true);
1084 }
1085
1086 //?? if( pHt->GetEnd() ) // Attr mit Ende
1087 {
1088 nPos = rHt.nEnd; // gibt letztes Attr-Zeichen + 1
1089 if( nPos >= nStartPos && nPos < nMinPos )
1090 {
1091 nMinPos = nPos;
1092 SetCharSet(rHt, false);
1093 }
1094 }
1095 /* else
1096 { // Attr ohne Ende
1097 nPos = rHt.nStart + 1; // Laenge 1 wegen CH_TXTATR im Text
1098 if( nPos >= nStartPos && nPos < nMinPos )
1099 {
1100 nMinPos = nPos;
1101 SetCharSet(rHt, false);
1102 }
1103 }
1104 */
1105 }
1106 return nMinPos;
1107 }
1108
SetCharSet(const EECharAttrib & rAttr,bool bStart)1109 void MSWord_SdrAttrIter::SetCharSet(const EECharAttrib& rAttr, bool bStart)
1110 {
1111 void* p = 0;
1112 rtl_TextEncoding eChrSet;
1113 const SfxPoolItem& rItem = *rAttr.pAttr;
1114 switch( rItem.Which() )
1115 {
1116 case EE_CHAR_FONTINFO:
1117 p = (void*)&rAttr;
1118 eChrSet = ((SvxFontItem&)rItem).GetCharSet();
1119 break;
1120 }
1121
1122 if( p )
1123 {
1124 sal_uInt16 nPos;
1125 if( bStart )
1126 {
1127 nPos = aChrSetArr.Count();
1128 aChrSetArr.Insert( eChrSet, nPos );
1129 aChrTxtAtrArr.Insert( p, nPos );
1130 }
1131 else if( USHRT_MAX != ( nPos = aChrTxtAtrArr.GetPos( p )) )
1132 {
1133 aChrTxtAtrArr.Remove( nPos );
1134 aChrSetArr.Remove( nPos );
1135 }
1136 }
1137 }
1138
OutEEField(const SfxPoolItem & rHt)1139 void MSWord_SdrAttrIter::OutEEField(const SfxPoolItem& rHt)
1140 {
1141 const SvxFieldItem &rField = (const SvxFieldItem &)rHt;
1142 const SvxFieldData *pFld = rField.GetField();
1143 if (pFld && pFld->ISA(SvxURLField))
1144 {
1145 sal_uInt8 nOldTxtTyp = m_rExport.nTxtTyp;
1146 m_rExport.nTxtTyp = mnTyp;
1147 const SvxURLField *pURL = (const SvxURLField *)pFld;
1148 m_rExport.AttrOutput().StartURL( pURL->GetURL(), pURL->GetTargetFrame() );
1149
1150 const String &rStr = pURL->GetRepresentation();
1151 m_rExport.AttrOutput().RawText( rStr, true, GetNodeCharSet() ); // FIXME kendy: is the 'true' actually correct here? It was here before, but... ;-)
1152
1153 m_rExport.AttrOutput().EndURL();
1154 m_rExport.nTxtTyp = nOldTxtTyp;
1155 }
1156 }
1157
OutAttr(xub_StrLen nSwPos)1158 void MSWord_SdrAttrIter::OutAttr( xub_StrLen nSwPos )
1159 {
1160 OutParaAttr(true);
1161
1162 if( aTxtAtrArr.Count() )
1163 {
1164 const SwModify* pOldMod = m_rExport.pOutFmtNode;
1165 m_rExport.pOutFmtNode = 0;
1166
1167 const SfxItemPool* pSrcPool = pEditPool;
1168 const SfxItemPool& rDstPool = m_rExport.pDoc->GetAttrPool();
1169
1170 nTmpSwPos = nSwPos;
1171 sal_uInt16 i, nWhich, nSlotId;
1172 for( i = 0; i < aTxtAtrArr.Count(); i++ )
1173 {
1174 const EECharAttrib& rHt = aTxtAtrArr[ i ];
1175 if (nSwPos >= rHt.nStart && nSwPos < rHt.nEnd)
1176 {
1177 nWhich = rHt.pAttr->Which();
1178 if (nWhich == EE_FEATURE_FIELD)
1179 {
1180 OutEEField(*rHt.pAttr);
1181 continue;
1182 }
1183 else if (nWhich == EE_FEATURE_TAB)
1184 {
1185 m_rExport.WriteChar(0x9);
1186 continue;
1187 }
1188 nSlotId = pSrcPool->GetSlotId(nWhich);
1189
1190 if (nSlotId && nWhich != nSlotId)
1191 {
1192 nWhich = rDstPool.GetWhich(nSlotId);
1193 if (nWhich && nWhich != nSlotId &&
1194 nWhich < RES_UNKNOWNATR_BEGIN &&
1195 m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
1196 {
1197 // use always the SW-Which Id !
1198 SfxPoolItem* pI = rHt.pAttr->Clone();
1199 pI->SetWhich( nWhich );
1200 m_rExport.AttrOutput().OutputItem( *pI );
1201 delete pI;
1202 }
1203 }
1204 }
1205
1206 if( nSwPos < rHt.nStart )
1207 break;
1208 }
1209
1210 nTmpSwPos = 0; // HasTextItem nur in dem obigen Bereich erlaubt
1211 m_rExport.pOutFmtNode = pOldMod;
1212 }
1213 }
1214
IsTxtAttr(xub_StrLen nSwPos)1215 bool MSWord_SdrAttrIter::IsTxtAttr(xub_StrLen nSwPos)
1216 {
1217 for (sal_uInt16 i = 0; i < aTxtAtrArr.Count(); ++i)
1218 {
1219 const EECharAttrib& rHt = aTxtAtrArr[ i ];
1220 if (nSwPos >= rHt.nStart && nSwPos < rHt.nEnd)
1221 {
1222 if (
1223 (rHt.pAttr->Which() == EE_FEATURE_FIELD) ||
1224 (rHt.pAttr->Which() == EE_FEATURE_TAB)
1225 )
1226 {
1227 return true;
1228 }
1229 }
1230 }
1231 return false;
1232 }
1233
1234 // HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
1235 // und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
1236 // die dann ueber HasItem() nach anderen Items an der
1237 // Attribut-Anfangposition fragen kann.
1238 // Es koennen nur Attribute mit Ende abgefragt werden.
1239 // Es wird mit bDeep gesucht
HasTextItem(sal_uInt16 nWhich) const1240 const SfxPoolItem* MSWord_SdrAttrIter::HasTextItem(sal_uInt16 nWhich) const
1241 {
1242 const SfxPoolItem* pRet = 0;
1243 nWhich = sw::hack::TransformWhichBetweenPools(*pEditPool,
1244 m_rExport.pDoc->GetAttrPool(), nWhich);
1245 if (nWhich)
1246 {
1247 for (sal_uInt16 i = 0; i < aTxtAtrArr.Count(); ++i)
1248 {
1249 const EECharAttrib& rHt = aTxtAtrArr[i];
1250 if (
1251 nWhich == rHt.pAttr->Which() && nTmpSwPos >= rHt.nStart &&
1252 nTmpSwPos < rHt.nEnd
1253 )
1254 {
1255 pRet = rHt.pAttr; // Found
1256 break;
1257 }
1258 else if (nTmpSwPos < rHt.nStart)
1259 break; // dann kommt da nichts mehr
1260 }
1261 }
1262 return pRet;
1263 }
1264
GetItem(sal_uInt16 nWhich) const1265 const SfxPoolItem& MSWord_SdrAttrIter::GetItem( sal_uInt16 nWhich ) const
1266 {
1267 using sw::hack::GetSetWhichFromSwDocWhich;
1268 const SfxPoolItem* pRet = HasTextItem(nWhich);
1269 if (!pRet)
1270 {
1271 SfxItemSet aSet(pEditObj->GetParaAttribs(nPara));
1272 nWhich = GetSetWhichFromSwDocWhich(aSet, *m_rExport.pDoc, nWhich);
1273 ASSERT(nWhich, "Impossible, catastrophic failure imminent");
1274 pRet = &aSet.Get(nWhich);
1275 }
1276 return *pRet;
1277 }
1278
OutParaAttr(bool bCharAttr)1279 void MSWord_SdrAttrIter::OutParaAttr(bool bCharAttr)
1280 {
1281 SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
1282 if( aSet.Count() )
1283 {
1284 const SfxItemSet* pOldSet = m_rExport.GetCurItemSet();
1285 m_rExport.SetCurItemSet( &aSet );
1286
1287 SfxItemIter aIter( aSet );
1288 const SfxPoolItem* pItem = aIter.GetCurItem();
1289
1290 const SfxItemPool* pSrcPool = pEditPool,
1291 * pDstPool = &m_rExport.pDoc->GetAttrPool();
1292
1293 do {
1294 sal_uInt16 nWhich = pItem->Which(),
1295 nSlotId = pSrcPool->GetSlotId( nWhich );
1296
1297 if ( nSlotId && nWhich != nSlotId &&
1298 0 != ( nWhich = pDstPool->GetWhich( nSlotId ) ) &&
1299 nWhich != nSlotId &&
1300 ( bCharAttr ? ( nWhich >= RES_CHRATR_BEGIN && nWhich < RES_TXTATR_END )
1301 : ( nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END ) ) )
1302 {
1303 // use always the SW-Which Id !
1304 SfxPoolItem* pI = pItem->Clone();
1305 pI->SetWhich( nWhich );
1306 if (m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
1307 m_rExport.AttrOutput().OutputItem( *pI );
1308 delete pI;
1309 }
1310 } while( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
1311 m_rExport.SetCurItemSet( pOldSet );
1312 }
1313 }
1314
WriteSdrTextObj(const SdrObject & rObj,sal_uInt8 nTyp)1315 void WW8Export::WriteSdrTextObj(const SdrObject& rObj, sal_uInt8 nTyp)
1316 {
1317 const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, &rObj);
1318 ASSERT(pTxtObj, "That is no SdrTextObj!");
1319 if (!pTxtObj)
1320 return;
1321
1322 const OutlinerParaObject* pParaObj = 0;
1323 bool bOwnParaObj = false;
1324
1325 /*
1326 #i13885#
1327 When the object is actively being edited, that text is not set into
1328 the objects normal text object, but lives in a separate object.
1329 */
1330 if (pTxtObj->IsTextEditActive())
1331 {
1332 pParaObj = pTxtObj->GetEditOutlinerParaObject();
1333 bOwnParaObj = true;
1334 }
1335 else
1336 {
1337 pParaObj = pTxtObj->GetOutlinerParaObject();
1338 }
1339
1340 if( pParaObj )
1341 {
1342 WriteOutliner(*pParaObj, nTyp);
1343 if( bOwnParaObj )
1344 delete pParaObj;
1345 }
1346 }
1347
WriteOutliner(const OutlinerParaObject & rParaObj,sal_uInt8 nTyp)1348 void WW8Export::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTyp)
1349 {
1350 bool bAnyWrite = false;
1351 const EditTextObject& rEditObj = rParaObj.GetTextObject();
1352 MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
1353
1354 sal_uInt32 nPara = rEditObj.GetParagraphCount();
1355 sal_uInt8 bNul = 0;
1356 for( sal_uInt32 n = 0; n < nPara; ++n )
1357 {
1358 if( n )
1359 aAttrIter.NextPara( n );
1360
1361 rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
1362
1363 ASSERT( !pO->Count(), " pO ist am Zeilenanfang nicht leer" );
1364
1365 String aStr( rEditObj.GetText( n ));
1366 xub_StrLen nAktPos = 0;
1367 xub_StrLen nEnd = aStr.Len();
1368 do {
1369 xub_StrLen nNextAttr = aAttrIter.WhereNext();
1370 rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
1371
1372 if( nNextAttr > nEnd )
1373 nNextAttr = nEnd;
1374
1375 bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
1376 if( !bTxtAtr )
1377 OutSwString( aStr, nAktPos, nNextAttr - nAktPos,
1378 true, eChrSet );
1379
1380 // Am Zeilenende werden die Attribute bis ueber das CR
1381 // aufgezogen. Ausnahme: Fussnoten am Zeilenende
1382 if( nNextAttr == nEnd && !bTxtAtr )
1383 WriteCR(); // CR danach
1384
1385 // Ausgabe der Zeichenattribute
1386 aAttrIter.OutAttr( nAktPos ); // nAktPos - 1 ??
1387 pChpPlc->AppendFkpEntry( Strm().Tell(),
1388 pO->Count(), pO->GetData() );
1389 pO->Remove( 0, pO->Count() ); // leeren
1390
1391 // Ausnahme: Fussnoten am Zeilenende
1392 if( nNextAttr == nEnd && bTxtAtr )
1393 WriteCR(); // CR danach
1394 nAktPos = nNextAttr;
1395 eChrSet = eNextChrSet;
1396 aAttrIter.NextPos();
1397 }
1398 while( nAktPos < nEnd );
1399
1400 ASSERT( !pO->Count(), " pO ist am ZeilenEnde nicht leer" );
1401
1402 pO->Insert( bNul, pO->Count() ); // Style # as short
1403 pO->Insert( bNul, pO->Count() );
1404
1405 aAttrIter.OutParaAttr(false);
1406
1407 sal_uLong nPos = Strm().Tell();
1408 pPapPlc->AppendFkpEntry( Strm().Tell(),
1409 pO->Count(), pO->GetData() );
1410 pO->Remove( 0, pO->Count() ); // leeren
1411 pChpPlc->AppendFkpEntry( nPos );
1412 }
1413
1414 bAnyWrite = 0 != nPara;
1415 if( !bAnyWrite )
1416 WriteStringAsPara( aEmptyStr );
1417 }
1418
WriteData(EscherEx & rEx) const1419 void WinwordAnchoring::WriteData( EscherEx& rEx ) const
1420 {
1421 //Toplevel groups get their winword extra data attached, and sub elements
1422 //use the defaults
1423 if (rEx.GetGroupLevel() <= 1)
1424 {
1425 SvStream& rSt = rEx.GetStream();
1426 //The last argument denotes the number of sub properties in this atom
1427 if (mbInline)
1428 {
1429 rEx.AddAtom(18, DFF_msofbtUDefProp, 3, 3); //Prop id is 0xF122
1430 rSt << (sal_uInt16)0x0390 << sal_uInt32(3);
1431 rSt << (sal_uInt16)0x0392 << sal_uInt32(3);
1432 //This sub property is required to be in the dummy inline frame as
1433 //well
1434 rSt << (sal_uInt16)0x053F << nInlineHack;
1435 }
1436 else
1437 {
1438 rEx.AddAtom(24, DFF_msofbtUDefProp, 3, 4 ); //Prop id is 0xF122
1439 rSt << (sal_uInt16)0x038F << mnXAlign;
1440 rSt << (sal_uInt16)0x0390 << mnXRelTo;
1441 rSt << (sal_uInt16)0x0391 << mnYAlign;
1442 rSt << (sal_uInt16)0x0392 << mnYRelTo;
1443 }
1444 }
1445 }
1446
1447 /* */
1448
CreateEscher()1449 void WW8Export::CreateEscher()
1450 {
1451 SfxItemState eBackSet =
1452 (const_cast<const SwDoc*>(pDoc))->GetPageDesc(0).GetMaster().
1453 GetItemState(RES_BACKGROUND);
1454 if (pHFSdrObjs->size() || pSdrObjs->size() || SFX_ITEM_SET == eBackSet)
1455 {
1456 ASSERT( !pEscher, "wer hat den Pointer nicht geloescht?" );
1457 SvMemoryStream* pEscherStrm = new SvMemoryStream;
1458 pEscherStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1459 pEscher = new SwEscherEx(pEscherStrm, *this);
1460 }
1461 }
1462
WriteEscher()1463 void WW8Export::WriteEscher()
1464 {
1465 if (pEscher)
1466 {
1467 sal_uLong nStart = pTableStrm->Tell();
1468
1469 pEscher->WritePictures();
1470 pEscher->FinishEscher();
1471
1472 pFib->fcDggInfo = nStart;
1473 pFib->lcbDggInfo = pTableStrm->Tell() - nStart;
1474 delete pEscher, pEscher = 0;
1475 }
1476 }
1477
WritePictures()1478 void SwEscherEx::WritePictures()
1479 {
1480 if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
1481 {
1482 // set the blip - entries to the correct stream pos
1483 sal_Int32 nEndPos = rWrt.Strm().Tell();
1484 mxGlobal->SetNewBlipStreamOffset( nEndPos );
1485
1486 pPicStrm->Seek( 0 );
1487 rWrt.Strm() << *pPicStrm;
1488 }
1489 Flush();
1490 }
1491
1492 /* */
1493
1494 // Output- Routines for Escher Export
1495
SwEscherExGlobal()1496 SwEscherExGlobal::SwEscherExGlobal()
1497 {
1498 }
1499
~SwEscherExGlobal()1500 SwEscherExGlobal::~SwEscherExGlobal()
1501 {
1502 }
1503
ImplQueryPictureStream()1504 SvStream* SwEscherExGlobal::ImplQueryPictureStream()
1505 {
1506 // this function will be called exactly once
1507 mxPicStrm.reset( new SvMemoryStream );
1508 mxPicStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1509 return mxPicStrm.get();
1510 }
1511
SwBasicEscherEx(SvStream * pStrm,WW8Export & rWW8Wrt)1512 SwBasicEscherEx::SwBasicEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
1513 : EscherEx( EscherExGlobalRef( new SwEscherExGlobal ), *pStrm), rWrt(rWW8Wrt), pEscherStrm(pStrm)
1514 {
1515 Init();
1516 }
1517
~SwBasicEscherEx()1518 SwBasicEscherEx::~SwBasicEscherEx()
1519 {
1520 }
1521
WriteFrmExtraData(const SwFrmFmt &)1522 void SwBasicEscherEx::WriteFrmExtraData(const SwFrmFmt&)
1523 {
1524 AddAtom(4, ESCHER_ClientAnchor);
1525 GetStream() << (sal_uInt32)0x80000000;
1526 }
1527
WriteEmptyFlyFrame(const SwFrmFmt & rFmt,sal_uInt32 nShapeId)1528 void SwBasicEscherEx::WriteEmptyFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
1529 {
1530 OpenContainer(ESCHER_SpContainer);
1531 AddShape(ESCHER_ShpInst_PictureFrame, 0xa00, nShapeId);
1532 // store anchor attribute
1533 WriteFrmExtraData(rFmt);
1534
1535 AddAtom(6, DFF_msofbtUDefProp, 3, 1); //Prop id is 0xF122
1536 GetStream() << (sal_uInt16)0x053F << nInlineHack;
1537
1538 CloseContainer(); // ESCHER_SpContainer
1539 }
1540
AddMirrorFlags(sal_uInt32 nFlags,const SwMirrorGrf & rMirror)1541 sal_uInt32 AddMirrorFlags(sal_uInt32 nFlags, const SwMirrorGrf &rMirror)
1542 {
1543 switch (rMirror.GetValue())
1544 {
1545 default:
1546 case RES_MIRROR_GRAPH_DONT:
1547 break;
1548 case RES_MIRROR_GRAPH_VERT:
1549 nFlags |= SHAPEFLAG_FLIPH;
1550 break;
1551 case RES_MIRROR_GRAPH_HOR:
1552 nFlags |= SHAPEFLAG_FLIPV;
1553 break;
1554 case RES_MIRROR_GRAPH_BOTH:
1555 nFlags |= SHAPEFLAG_FLIPH;
1556 nFlags |= SHAPEFLAG_FLIPV;
1557 break;
1558
1559 }
1560 return nFlags;
1561 }
1562 //For i120928,this function is added to export graphic of bullet
WriteGrfBullet(const Graphic & rGrf)1563 sal_Int32 SwBasicEscherEx::WriteGrfBullet(const Graphic& rGrf)
1564 {
1565 OpenContainer( ESCHER_SpContainer );
1566 AddShape(ESCHER_ShpInst_PictureFrame, 0xa00,0x401);
1567 EscherPropertyContainer aPropOpt;
1568 GraphicObject aGraphicObject( rGrf );
1569 ByteString aUniqueId = aGraphicObject.GetUniqueID();
1570 if ( aUniqueId.Len() )
1571 {
1572 const MapMode aMap100mm( MAP_100TH_MM );
1573 Size aSize( rGrf.GetPrefSize() );
1574 if ( MAP_PIXEL == rGrf.GetPrefMapMode().GetMapUnit() )
1575 {
1576 aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
1577 }
1578 else
1579 {
1580 aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
1581 }
1582 Point aEmptyPoint = Point();
1583 Rectangle aRect( aEmptyPoint, aSize );
1584 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *(mxGlobal->QueryPictureStream()), aUniqueId,aRect, NULL, 0 );
1585 if (nBlibId)
1586 aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
1587 }
1588 aPropOpt.AddOpt( ESCHER_Prop_pibFlags, ESCHER_BlipFlagDefault );
1589 aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, DrawModelToEmu(0));
1590 aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, DrawModelToEmu(0));
1591 aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, DrawModelToEmu(0));
1592 aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, DrawModelToEmu(0));
1593 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1594 aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
1595 aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
1596 aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
1597 aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
1598 const Color aTmpColor( COL_WHITE );
1599 SvxBrushItem aBrush( aTmpColor, RES_BACKGROUND );
1600 const SvxBrushItem *pRet = rWrt.GetCurrentPageBgBrush();
1601 if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
1602 aBrush = *pRet;
1603 WriteBrushAttr(aBrush, aPropOpt);
1604
1605 aPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0 );
1606 aPropOpt.Commit( GetStream() );
1607 AddAtom(4, ESCHER_ClientAnchor);
1608 GetStream() << (sal_uInt32)0x80000000;
1609 CloseContainer();
1610
1611 return 0;
1612 }
1613
WriteGrfFlyFrame(const SwFrmFmt & rFmt,sal_uInt32 nShapeId)1614 sal_Int32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
1615 {
1616 sal_Int32 nBorderThick=0;
1617 SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt);
1618 SwGrfNode *pGrfNd = pNd ? pNd->GetGrfNode() : 0;
1619 ASSERT(pGrfNd, "No SwGrfNode ?, suspicious");
1620 if (!pGrfNd)
1621 return nBorderThick;
1622
1623 OpenContainer( ESCHER_SpContainer );
1624
1625 const SwMirrorGrf &rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
1626 AddShape(ESCHER_ShpInst_PictureFrame, AddMirrorFlags(0xa00, rMirror),
1627 nShapeId);
1628
1629 EscherPropertyContainer aPropOpt;
1630
1631 sal_uInt32 nFlags = ESCHER_BlipFlagDefault;
1632
1633 if (pGrfNd->IsLinkedFile())
1634 {
1635 String sURL;
1636 pGrfNd->GetFileFilterNms( &sURL, 0 );
1637
1638 WW8Bytes aBuf;
1639 SwWW8Writer::InsAsString16( aBuf, sURL );
1640 SwWW8Writer::InsUInt16( aBuf, 0 );
1641
1642 sal_uInt16 nArrLen = aBuf.Count();
1643 sal_uInt8* pArr = new sal_uInt8[ nArrLen ];
1644 memcpy( pArr, aBuf.GetData(), nArrLen );
1645
1646 aPropOpt.AddOpt(ESCHER_Prop_pibName, true, nArrLen, pArr, nArrLen);
1647 nFlags = ESCHER_BlipFlagLinkToFile | ESCHER_BlipFlagURL |
1648 ESCHER_BlipFlagDoNotSave;
1649 }
1650 else
1651 {
1652 pGrfNd->SwapIn(true);
1653
1654 Graphic aGraphic(pGrfNd->GetGrf());
1655 GraphicObject aGraphicObject( aGraphic );
1656 ByteString aUniqueId = aGraphicObject.GetUniqueID();
1657
1658 if ( aUniqueId.Len() )
1659 {
1660 const MapMode aMap100mm( MAP_100TH_MM );
1661 Size aSize( aGraphic.GetPrefSize() );
1662
1663 if ( MAP_PIXEL == aGraphic.GetPrefMapMode().GetMapUnit() )
1664 {
1665 aSize = Application::GetDefaultDevice()->PixelToLogic(
1666 aSize, aMap100mm );
1667 }
1668 else
1669 {
1670 aSize = OutputDevice::LogicToLogic( aSize,
1671 aGraphic.GetPrefMapMode(), aMap100mm );
1672 }
1673
1674 Point aEmptyPoint = Point();
1675 Rectangle aRect( aEmptyPoint, aSize );
1676
1677 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
1678 aUniqueId, aRect, NULL, 0 );
1679 if (nBlibId)
1680 aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
1681 }
1682 }
1683
1684 aPropOpt.AddOpt( ESCHER_Prop_pibFlags, nFlags );
1685 nBorderThick = WriteFlyFrameAttr(rFmt,mso_sptPictureFrame,aPropOpt);
1686 WriteGrfAttr(*pGrfNd, aPropOpt);
1687
1688 aPropOpt.Commit( GetStream() );
1689
1690 // store anchor attribute
1691 WriteFrmExtraData( rFmt );
1692
1693 CloseContainer(); // ESCHER_SpContainer
1694 return nBorderThick;
1695 }
1696
WriteGrfAttr(const SwNoTxtNode & rNd,EscherPropertyContainer & rPropOpt)1697 void SwBasicEscherEx::WriteGrfAttr(const SwNoTxtNode& rNd,
1698 EscherPropertyContainer& rPropOpt)
1699 {
1700 const SfxPoolItem* pItem;
1701 sal_uInt32 nMode = GRAPHICDRAWMODE_STANDARD;
1702 sal_Int32 nContrast = 0;
1703 sal_Int16 nBrightness = 0;
1704
1705 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CONTRAST,
1706 true, &pItem))
1707 {
1708 nContrast = ((SfxInt16Item*)pItem)->GetValue();
1709 }
1710
1711 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_LUMINANCE,
1712 true, &pItem))
1713 {
1714 nBrightness = ((SfxInt16Item*)pItem)->GetValue();
1715 }
1716
1717
1718 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_DRAWMODE,
1719 true, &pItem))
1720 {
1721 nMode = ((SfxEnumItem*)pItem)->GetValue();
1722 if (nMode == GRAPHICDRAWMODE_WATERMARK)
1723 {
1724 /*
1725 There is no real watermark mode in word, we must use standard
1726 mode and modify our ones by 70% extra brightness and 70% less
1727 contrast. This means that unmodified default OOo watermark
1728 will turn back into watermark, and modified OOo watermark will
1729 change into a close visual representation in standardmode
1730 */
1731 nBrightness += 70;
1732 if (nBrightness > 100)
1733 nBrightness = 100;
1734 nContrast -= 70;
1735 if (nContrast < -100)
1736 nContrast = -100;
1737 nMode = GRAPHICDRAWMODE_STANDARD;
1738 }
1739 }
1740
1741 if (nMode == GRAPHICDRAWMODE_GREYS)
1742 nMode = 0x40004;
1743 else if (nMode == GRAPHICDRAWMODE_MONO)
1744 nMode = 0x60006;
1745 else
1746 nMode = 0;
1747 rPropOpt.AddOpt( ESCHER_Prop_pictureActive, nMode );
1748
1749 if (nContrast != 0)
1750 {
1751 nContrast+=100;
1752 if (nContrast == 100)
1753 nContrast = 0x10000;
1754 else if (nContrast < 100)
1755 {
1756 nContrast *= 0x10000;
1757 nContrast /= 100;
1758 }
1759 else if (nContrast < 200)
1760 nContrast = (100 * 0x10000) / (200-nContrast);
1761 else
1762 nContrast = 0x7fffffff;
1763 rPropOpt.AddOpt( ESCHER_Prop_pictureContrast, nContrast);
1764 }
1765
1766 if (nBrightness != 0)
1767 rPropOpt.AddOpt( ESCHER_Prop_pictureBrightness, nBrightness * 327 );
1768
1769 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CROPGRF,
1770 true, &pItem))
1771 {
1772 const Size aSz( rNd.GetTwipSize() );
1773 sal_Int32 nVal;
1774 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetLeft() ) )
1775 rPropOpt.AddOpt( ESCHER_Prop_cropFromLeft, ToFract16( nVal, aSz.Width()) );
1776 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetRight() ) )
1777 rPropOpt.AddOpt( ESCHER_Prop_cropFromRight, ToFract16( nVal, aSz.Width()));
1778 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetTop() ) )
1779 rPropOpt.AddOpt( ESCHER_Prop_cropFromTop, ToFract16( nVal, aSz.Height()));
1780 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetBottom() ) )
1781 rPropOpt.AddOpt( ESCHER_Prop_cropFromBottom, ToFract16( nVal, aSz.Height()));
1782 }
1783 }
1784
SetPicId(const SdrObject &,sal_uInt32,EscherPropertyContainer &)1785 void SwBasicEscherEx::SetPicId(const SdrObject &, sal_uInt32,
1786 EscherPropertyContainer &)
1787 {
1788 }
1789
SetPicId(const SdrObject & rSdrObj,sal_uInt32 nShapeId,EscherPropertyContainer & rPropOpt)1790 void SwEscherEx::SetPicId(const SdrObject &rSdrObj, sal_uInt32 nShapeId,
1791 EscherPropertyContainer &rPropOpt)
1792 {
1793 pTxtBxs->Append(rSdrObj, nShapeId);
1794 sal_uInt32 nPicId = pTxtBxs->Count();
1795 nPicId *= 0x10000;
1796 rPropOpt.AddOpt( ESCHER_Prop_pictureId, nPicId );
1797 }
1798
WriteOLEFlyFrame(const SwFrmFmt & rFmt,sal_uInt32 nShapeId)1799 sal_Int32 SwBasicEscherEx::WriteOLEFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
1800 {
1801 sal_Int32 nBorderThick = 0;
1802 if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
1803 {
1804 SwNodeIndex aIdx(*rFmt.GetCntnt().GetCntntIdx(), 1);
1805 SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
1806 sal_Int64 nAspect = rOLENd.GetAspect();
1807
1808 uno::Reference < embed::XEmbeddedObject > xObj(rOLENd.GetOLEObj().GetOleRef());
1809
1810 // the rectangle is used to transport the size of the object
1811 // the left, top corner is set to ( 0, 0 ) by default constructor,
1812 // if the width and height are set correctly bRectIsSet should be set to true
1813 awt::Rectangle aRect;
1814 sal_Bool bRectIsSet = sal_False;
1815
1816
1817 // TODO/LATER: should the icon size be stored in case of iconified object?
1818 if ( xObj.is() && nAspect != embed::Aspects::MSOLE_ICON )
1819 {
1820 try
1821 {
1822 awt::Size aSize = xObj->getVisualAreaSize( nAspect );
1823 aRect.Width = aSize.Width;
1824 aRect.Height = aSize.Height;
1825 bRectIsSet = sal_True;
1826 }
1827 catch( uno::Exception& )
1828 {}
1829 }
1830
1831 /*
1832 #i5970#
1833 Export floating ole2 .doc ver 8+ wmf ole2 previews as emf previews
1834 instead ==> allows unicode text to be preserved
1835 */
1836 #ifdef OLE_PREVIEW_AS_EMF
1837 //Graphic aGraphic = wwUtility::MakeSafeGDIMetaFile(xObj);
1838 Graphic* pGraphic = rOLENd.GetGraphic();
1839 #endif
1840 OpenContainer(ESCHER_SpContainer);
1841
1842 EscherPropertyContainer aPropOpt;
1843 const SwMirrorGrf &rMirror = rOLENd.GetSwAttrSet().GetMirrorGrf();
1844 WriteOLEPicture(aPropOpt, AddMirrorFlags(0xa00 | SHAPEFLAG_OLESHAPE,
1845 rMirror), pGraphic ? *pGraphic : Graphic(), *pSdrObj, nShapeId, bRectIsSet ? &aRect : NULL );
1846
1847 nBorderThick = WriteFlyFrameAttr(rFmt, mso_sptPictureFrame, aPropOpt);
1848 WriteGrfAttr(rOLENd, aPropOpt);
1849 aPropOpt.Commit(GetStream());
1850
1851 // store anchor attribute
1852 WriteFrmExtraData( rFmt );
1853
1854 CloseContainer(); // ESCHER_SpContainer
1855 }
1856 return nBorderThick;
1857 }
1858
WriteBrushAttr(const SvxBrushItem & rBrush,EscherPropertyContainer & rPropOpt)1859 void SwBasicEscherEx::WriteBrushAttr(const SvxBrushItem &rBrush,
1860 EscherPropertyContainer& rPropOpt)
1861 {
1862 bool bSetOpacity = false;
1863 sal_uInt32 nOpaque = 0;
1864 if (const GraphicObject *pGraphicObject = rBrush.GetGraphicObject())
1865 {
1866 ByteString aUniqueId = pGraphicObject->GetUniqueID();
1867 if (aUniqueId.Len())
1868 {
1869 const Graphic &rGraphic = pGraphicObject->GetGraphic();
1870 Size aSize(rGraphic.GetPrefSize());
1871 const MapMode aMap100mm(MAP_100TH_MM);
1872 if (MAP_PIXEL == rGraphic.GetPrefMapMode().GetMapUnit())
1873 {
1874 aSize = Application::GetDefaultDevice()->PixelToLogic(
1875 aSize, aMap100mm);
1876 }
1877 else
1878 {
1879 aSize = OutputDevice::LogicToLogic(aSize,
1880 rGraphic.GetPrefMapMode(), aMap100mm);
1881 }
1882
1883 Point aEmptyPoint = Point();
1884 Rectangle aRect(aEmptyPoint, aSize);
1885
1886 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
1887 aUniqueId, aRect, NULL, 0);
1888 if (nBlibId)
1889 rPropOpt.AddOpt(ESCHER_Prop_fillBlip,nBlibId,sal_True);
1890 }
1891
1892 if (0 != (nOpaque = pGraphicObject->GetAttr().GetTransparency()))
1893 bSetOpacity = true;
1894
1895 rPropOpt.AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
1896 rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
1897 rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
1898 }
1899 else
1900 {
1901 sal_uInt32 nFillColor = GetColor(rBrush.GetColor(), false);
1902 rPropOpt.AddOpt( ESCHER_Prop_fillColor, nFillColor );
1903 rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, nFillColor ^ 0xffffff );
1904 rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
1905
1906 if (0 != (nOpaque = rBrush.GetColor().GetTransparency()))
1907 bSetOpacity = true;
1908 }
1909
1910 if (bSetOpacity)
1911 {
1912 nOpaque = (nOpaque * 100) / 0xFE;
1913 nOpaque = ((100 - nOpaque) << 16) / 100;
1914 rPropOpt.AddOpt(ESCHER_Prop_fillOpacity, nOpaque);
1915 }
1916 }
1917
WriteFlyFrameAttr(const SwFrmFmt & rFmt,MSO_SPT eShapeType,EscherPropertyContainer & rPropOpt)1918 sal_Int32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt,
1919 MSO_SPT eShapeType, EscherPropertyContainer& rPropOpt)
1920 {
1921 sal_Int32 nLineWidth=0;
1922 const SfxPoolItem* pItem;
1923 bool bFirstLine = true;
1924 if (SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem))
1925 {
1926 static const sal_uInt16 aExhperProp[4] =
1927 {
1928 ESCHER_Prop_dyTextTop, ESCHER_Prop_dyTextBottom,
1929 ESCHER_Prop_dxTextLeft, ESCHER_Prop_dxTextRight
1930 };
1931 const SvxBorderLine* pLine;
1932
1933 for( sal_uInt16 n = 0; n < 4; ++n )
1934 if( 0 != ( pLine = ((SvxBoxItem*)pItem)->GetLine( n )) )
1935 {
1936 if( bFirstLine )
1937 {
1938 sal_uInt32 nLineColor = GetColor(pLine->GetColor(), false);
1939 rPropOpt.AddOpt( ESCHER_Prop_lineColor, nLineColor );
1940 rPropOpt.AddOpt( ESCHER_Prop_lineBackColor,
1941 nLineColor ^ 0xffffff );
1942
1943 MSO_LineStyle eStyle;
1944 if( pLine->GetInWidth() )
1945 {
1946 // double line
1947 nLineWidth = pLine->GetInWidth() + pLine->GetOutWidth()
1948 + pLine->GetDistance();
1949 if( pLine->GetInWidth() == pLine->GetOutWidth() )
1950 eStyle = mso_lineDouble;
1951 else if( pLine->GetInWidth() < pLine->GetOutWidth() )
1952 eStyle = mso_lineThickThin;
1953 else
1954 eStyle = mso_lineThinThick;
1955 }
1956 else
1957 {
1958 // simple line
1959 eStyle = mso_lineSimple;
1960 nLineWidth = pLine->GetOutWidth();
1961 }
1962
1963 rPropOpt.AddOpt( ESCHER_Prop_lineStyle, eStyle );
1964 rPropOpt.AddOpt( ESCHER_Prop_lineWidth,
1965 DrawModelToEmu( nLineWidth ));
1966 rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x8000E );
1967
1968 //Use import logic to determine how much of border will go
1969 //outside graphic
1970 nLineWidth = SwMSDffManager::GetEscherLineMatch(
1971 eStyle,eShapeType,nLineWidth);
1972 bFirstLine = false;
1973 }
1974 rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(
1975 ((SvxBoxItem*)pItem)->GetDistance( n ) ));
1976 }
1977 else
1978 // MM If there is no line the distance should be set to 0
1979 rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(0));
1980 }
1981 if( bFirstLine ) // no valid line found
1982 {
1983 rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1984 rPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
1985 rPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
1986 rPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
1987 rPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
1988 }
1989 const SwAttrSet& rAttrSet = rFmt.GetAttrSet();
1990 if (SFX_ITEM_ON == rAttrSet.GetItemState(RES_BOX, false, &pItem))
1991 {
1992 const SvxBoxItem* pBox = (const SvxBoxItem*)pItem;
1993 if( pBox )
1994 {
1995 const SfxPoolItem* pShadItem;
1996 if (SFX_ITEM_ON
1997 == rAttrSet.GetItemState(RES_SHADOW, true, &pShadItem))
1998 {
1999 const SvxShadowItem* pSI = (const SvxShadowItem*)pShadItem;
2000
2001 const sal_uInt16 nCstScale = 635; // unit scale between AOO and MS Word
2002 const sal_uInt32 nShadowType = 131074; // shadow type of ms word. need to set the default value.
2003
2004 sal_uInt32 nColor = (sal_uInt32)(pSI->GetColor().GetColor()) ;
2005 sal_uInt32 nOffX = pSI->GetWidth() * nCstScale;
2006 sal_uInt32 nOffY = pSI->GetWidth() * nCstScale;
2007 sal_uInt32 nShadow = nShadowType;
2008
2009 SvxShadowLocation eLocation = pSI->GetLocation();
2010 if( (eLocation!=SVX_SHADOW_NONE) && (pSI->GetWidth()!=0) )
2011 {
2012 switch( eLocation )
2013 {
2014 case SVX_SHADOW_TOPLEFT:
2015 {
2016 nOffX = -nOffX;
2017 nOffY = -nOffY;
2018 }
2019 break;
2020 case SVX_SHADOW_TOPRIGHT:
2021 {
2022 nOffY = -nOffY;
2023 }
2024 break;
2025 case SVX_SHADOW_BOTTOMLEFT:
2026 {
2027 nOffX = -nOffX;
2028 }
2029 break;
2030 case SVX_SHADOW_BOTTOMRIGHT:
2031 break;
2032 default:
2033 break;
2034 }
2035
2036 rPropOpt.AddOpt( DFF_Prop_shadowColor, wwUtility::RGBToBGR((nColor)));
2037 rPropOpt.AddOpt( DFF_Prop_shadowOffsetX, nOffX );
2038 rPropOpt.AddOpt( DFF_Prop_shadowOffsetY, nOffY );
2039 rPropOpt.AddOpt( DFF_Prop_fshadowObscured, nShadow );
2040 }
2041 }
2042 }
2043 }
2044 SvxBrushItem aBrush(rWrt.TrueFrameBgBrush(rFmt));
2045 WriteBrushAttr(aBrush, rPropOpt);
2046
2047 const SdrObject* pObj = rFmt.FindRealSdrObject();
2048 if( pObj && (pObj->GetLayer() == GetHellLayerId() ||
2049 pObj->GetLayer() == GetInvisibleHellId() ))
2050 {
2051 rPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
2052 }
2053
2054 PreWriteHyperlinkWithinFly(rFmt,rPropOpt);
2055
2056 return nLineWidth;
2057 }
2058
WriteFlyFrameAttr(const SwFrmFmt & rFmt,MSO_SPT eShapeType,EscherPropertyContainer & rPropOpt)2059 sal_Int32 SwEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType,
2060 EscherPropertyContainer& rPropOpt)
2061 {
2062 sal_Int32 nLineWidth = SwBasicEscherEx::WriteFlyFrameAttr(rFmt, eShapeType,
2063 rPropOpt);
2064
2065 /*
2066 These are not in SwBasicEscherEx::WriteFlyFrameAttr because inline objs
2067 can't do it in word and it hacks it in by stretching the graphic that
2068 way, perhaps we should actually draw in this space into the graphic we
2069 are exporting!
2070 */
2071 const SfxPoolItem* pItem;
2072 if (SFX_ITEM_SET == rFmt.GetItemState(RES_LR_SPACE, true, &pItem))
2073 {
2074 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft,
2075 DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetLeft() ) );
2076 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight,
2077 DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetRight() ) );
2078 }
2079 else
2080 {
2081 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
2082 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
2083 }
2084
2085 if (SFX_ITEM_SET == rFmt.GetItemState(RES_UL_SPACE, true, &pItem))
2086 {
2087 rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistTop,
2088 DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetUpper() ) );
2089 rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistBottom,
2090 DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetLower() ) );
2091 }
2092
2093 if (rFmt.GetSurround().IsContour())
2094 {
2095 if (const SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt))
2096 {
2097 const PolyPolygon *pPolyPoly = pNd->HasContour();
2098 if (pPolyPoly && pPolyPoly->Count())
2099 {
2100 Polygon aPoly(PolygonFromPolyPolygon(*pPolyPoly));
2101 const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
2102 Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
2103 Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
2104 aPoly.Scale(aMapPolyX, aMapPolyY);
2105
2106 /*
2107 a) stretch right bound by 15twips
2108 b) shrink bottom bound to where it would have been in word
2109 c) Move it to the left by 15twips
2110
2111 See the import for details
2112 */
2113 const Size &rSize = pNd->GetTwipSize();
2114 Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
2115 aMoveHack *= Fraction(15, 1);
2116 long nMove(aMoveHack);
2117
2118 Fraction aHackX(ww::nWrap100Percent + nMove,
2119 ww::nWrap100Percent);
2120 Fraction aHackY(ww::nWrap100Percent - nMove,
2121 ww::nWrap100Percent);
2122 aPoly.Scale(aHackX, aHackY);
2123
2124 aPoly.Move(-nMove, 0);
2125
2126 SvMemoryStream aPolyDump;
2127 aPolyDump.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
2128
2129 sal_uInt16 nLen = aPoly.GetSize();
2130 aPolyDump << nLen;
2131 aPolyDump << nLen;
2132 aPolyDump << sal_uInt16(8);
2133 for (sal_uInt16 nI = 0; nI < nLen; ++nI)
2134 {
2135 aPolyDump << sal_uInt32(aPoly[nI].X());
2136 aPolyDump << sal_uInt32(aPoly[nI].Y());
2137 }
2138
2139 sal_uInt16 nArrLen = msword_cast<sal_uInt16>(aPolyDump.Tell());
2140 void *pArr = const_cast<void *>(aPolyDump.GetData());
2141 //PropOpt wants to own the buffer
2142 aPolyDump.ObjectOwnsMemory(false);
2143 rPropOpt.AddOpt(DFF_Prop_pWrapPolygonVertices, false,
2144 nArrLen, static_cast<sal_uInt8 *>(pArr), nArrLen);
2145 }
2146 }
2147 }
2148
2149 PreWriteHyperlinkWithinFly(rFmt,rPropOpt);
2150
2151 return nLineWidth;
2152 }
2153
Init()2154 void SwBasicEscherEx::Init()
2155 {
2156 MapUnit eMap = MAP_TWIP;
2157 if (SwDrawModel* pModel = rWrt.pDoc->GetDrawModel())
2158 {
2159 // PPT arbeitet nur mit Einheiten zu 576DPI
2160 // WW hingegen verwendet twips, dh. 1440DPI.
2161 eMap = pModel->GetScaleUnit();
2162 }
2163
2164 // MS-DFF-Properties sind grossteils in EMU (English Metric Units) angegeben
2165 // 1mm=36000emu, 1twip=635emu
2166 Fraction aFact(360, 1);
2167 aFact /= GetMapFactor(MAP_100TH_MM, eMap).X();
2168 // create little values
2169 aFact = Fraction(aFact.GetNumerator(), aFact.GetDenominator());
2170 mnEmuMul = aFact.GetNumerator();
2171 mnEmuDiv = aFact.GetDenominator();
2172
2173 SetHellLayerId(rWrt.pDoc->GetHellId());
2174 }
2175
ToFract16(sal_Int32 nVal,sal_uInt32 nMax) const2176 sal_Int32 SwBasicEscherEx::ToFract16(sal_Int32 nVal, sal_uInt32 nMax) const
2177 {
2178 if (nMax)
2179 {
2180 sal_Int32 nMSVal = (nVal / 65536) * nMax;
2181 nMSVal += (nVal * 65536 ) / nMax;
2182 return nMSVal;
2183 }
2184 return 0;
2185 }
2186
GetInvisibleHellId() const2187 SdrLayerID SwBasicEscherEx::GetInvisibleHellId() const
2188 {
2189 return rWrt.pDoc->GetInvisibleHellId();
2190 }
2191
WritePictures()2192 void SwBasicEscherEx::WritePictures()
2193 {
2194 if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
2195 {
2196 // set the blip - entries to the correct stream pos
2197 sal_Int32 nEndPos = pPicStrm->Tell();
2198 mxGlobal->WriteBlibStoreEntry(*pEscherStrm, 1, sal_True, nEndPos);
2199
2200 pPicStrm->Seek(0);
2201 *pEscherStrm << *pPicStrm;
2202 }
2203 }
2204
SwEscherEx(SvStream * pStrm,WW8Export & rWW8Wrt)2205 SwEscherEx::SwEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
2206 : SwBasicEscherEx(pStrm, rWW8Wrt),
2207 pTxtBxs(0)
2208 {
2209 aHostData.SetClientData(&aWinwordAnchoring);
2210 OpenContainer( ESCHER_DggContainer );
2211
2212 sal_uInt16 nColorCount = 4;
2213 *pStrm << (sal_uInt16)( nColorCount << 4 ) // instance
2214 << (sal_uInt16)ESCHER_SplitMenuColors // record type
2215 << (sal_uInt32)( nColorCount * 4 ) // size
2216 << (sal_uInt32)0x08000004
2217 << (sal_uInt32)0x08000001
2218 << (sal_uInt32)0x08000002
2219 << (sal_uInt32)0x100000f7;
2220
2221 CloseContainer(); // ESCHER_DggContainer
2222
2223 sal_uInt8 i = 2; // for header/footer and the other
2224 PlcDrawObj *pSdrObjs = rWrt.pHFSdrObjs;
2225 pTxtBxs = rWrt.pHFTxtBxs;
2226
2227 // if no header/footer -> skip over
2228 if (!pSdrObjs->size())
2229 {
2230 --i;
2231 pSdrObjs = rWrt.pSdrObjs;
2232 pTxtBxs = rWrt.pTxtBxs;
2233 }
2234
2235 for( ; i--; pSdrObjs = rWrt.pSdrObjs, pTxtBxs = rWrt.pTxtBxs )
2236 {
2237 // "dummy char" (or any Count ?) - why? This knows only M$
2238 GetStream() << (sal_Char)i;
2239
2240 OpenContainer( ESCHER_DgContainer );
2241
2242 EnterGroup( 0 );
2243
2244 sal_uLong nSecondShapeId = pSdrObjs == rWrt.pSdrObjs ? GenerateShapeId() : 0;
2245
2246 // write now all Writer-/DrawObjects
2247 DrawObjPointerVector aSorted;
2248 MakeZOrderArrAndFollowIds(pSdrObjs->GetObjArr(), aSorted);
2249
2250 sal_uInt32 nShapeId=0;
2251 DrawObjPointerIter aEnd = aSorted.end();
2252 for (DrawObjPointerIter aIter = aSorted.begin(); aIter != aEnd; ++aIter)
2253 {
2254 sal_Int32 nBorderThick=0;
2255 DrawObj *pObj = (*aIter);
2256 ASSERT(pObj, "impossible");
2257 if (!pObj)
2258 continue;
2259 const sw::Frame &rFrame = pObj->maCntnt;
2260 const SwFrmFmt& rFmt = rFrame.GetFrmFmt();
2261
2262 switch (rFrame.GetWriterType())
2263 {
2264 case sw::Frame::eTxtBox:
2265 case sw::Frame::eOle:
2266 case sw::Frame::eGraphic:
2267 nBorderThick = WriteFlyFrm(*pObj, nShapeId, aSorted);
2268 break;
2269 case sw::Frame::eFormControl:
2270 WriteOCXControl(rFmt, nShapeId = GenerateShapeId());
2271 break;
2272 case sw::Frame::eDrawing: {
2273 aWinwordAnchoring.SetAnchoring(rFmt);
2274 const SdrObject* pSdrObj = rFmt.FindRealSdrObject();
2275 if (pSdrObj)
2276 {
2277 bool bSwapInPage = false;
2278 if (!pSdrObj->GetPage())
2279 {
2280 if (SwDrawModel* pModel = rWrt.pDoc->GetDrawModel())
2281 {
2282 if (SdrPage *pPage = pModel->GetPage(0))
2283 {
2284 bSwapInPage = true;
2285 (const_cast<SdrObject*>(pSdrObj))->SetPage(pPage);
2286 }
2287 }
2288 }
2289
2290 nShapeId = AddSdrObject(*pSdrObj);
2291
2292 if (bSwapInPage)
2293 (const_cast<SdrObject*>(pSdrObj))->SetPage(0);
2294 }
2295 #ifdef DBG_UTIL
2296 else
2297 ASSERT( sal_False, "Where is the SDR-Object?" );
2298 #endif
2299 }
2300 break;
2301 default:
2302 break;
2303 }
2304
2305 if( !nShapeId )
2306 {
2307 nShapeId = AddDummyShape();
2308 }
2309
2310 pObj->SetShapeDetails(nShapeId, nBorderThick);
2311 }
2312
2313 EndSdrObjectPage(); // ???? Bugfix for 74724
2314
2315 if( nSecondShapeId )
2316 {
2317 OpenContainer( ESCHER_SpContainer );
2318
2319 AddShape( ESCHER_ShpInst_Rectangle, 0xe00, nSecondShapeId );
2320
2321 EscherPropertyContainer aPropOpt;
2322 const SwFrmFmt &rFmt = const_cast<const SwDoc *>(rWrt.pDoc)->GetPageDesc(0).GetMaster();
2323 const SfxPoolItem* pItem = 0;
2324 SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true,
2325 &pItem);
2326 if (SFX_ITEM_SET == eState && pItem)
2327 {
2328 const SvxBrushItem* pBrush = (const SvxBrushItem*)pItem;
2329 WriteBrushAttr(*pBrush, aPropOpt);
2330
2331 SvxGraphicPosition ePos = pBrush->GetGraphicPos();
2332 if( ePos != GPOS_NONE && ePos != GPOS_AREA )
2333 {
2334 /* #i56806# 0x033F parameter specifies a 32-bit field of shape boolean properties.
2335 0x10001 means fBackground and fUsefBackground flag are true thus background
2336 picture will be shown as "tiled" fill.*/
2337 aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
2338 }
2339 }
2340 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x8000001 );
2341 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
2342 aPropOpt.AddOpt( ESCHER_Prop_shadowColor, 0x8000002 );
2343 aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
2344
2345 // winword defaults!
2346 // aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
2347 // aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
2348 // aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
2349 // aPropOpt.AddOpt( ESCHER_Prop_bWMode, 0x9 );
2350 // aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
2351
2352 aPropOpt.Commit( *pStrm );
2353
2354 AddAtom( 4, ESCHER_ClientData );
2355 GetStream() << 1L;
2356
2357 CloseContainer(); // ESCHER_SpContainer
2358 }
2359 CloseContainer(); // ESCHER_DgContainer
2360 }
2361 }
2362
~SwEscherEx()2363 SwEscherEx::~SwEscherEx()
2364 {
2365 }
2366
FinishEscher()2367 void SwEscherEx::FinishEscher()
2368 {
2369 pEscherStrm->Seek(0);
2370 *rWrt.pTableStrm << *pEscherStrm;
2371 delete pEscherStrm, pEscherStrm = 0;
2372 }
2373
2374 /** method to perform conversion of positioning attributes with the help
2375 of corresponding layout information
2376
2377 OD 2005-01-06 #i30669#
2378 Because most of the Writer object positions doesn't correspond to the
2379 object positions in WW8, this method converts the positioning
2380 attributes. For this conversion the corresponding layout information
2381 is needed. If no layout information exists - e.g. no layout exists - no
2382 conversion is performed.
2383 No conversion is performed for as-character anchored objects. Whose
2384 object positions are already treated special in method <WriteData(..)>.
2385
2386 @author OD
2387
2388 @param _iorHoriOri
2389 input/output parameter - containing the current horizontal position
2390 attributes, which are converted by this method.
2391
2392 @param _iorVertOri
2393 input/output parameter - containing the current vertical position
2394 attributes, which are converted by this method.
2395
2396 @param _rFrmFmt
2397 input parameter - frame format of the anchored object
2398
2399 @return boolean, indicating, if a conversion has been performed.
2400 */
ConvertPosition(SwFmtHoriOrient & _iorHoriOri,SwFmtVertOrient & _iorVertOri,const SwFrmFmt & _rFrmFmt)2401 bool WinwordAnchoring::ConvertPosition( SwFmtHoriOrient& _iorHoriOri,
2402 SwFmtVertOrient& _iorVertOri,
2403 const SwFrmFmt& _rFrmFmt )
2404 {
2405 const RndStdIds eAnchor = _rFrmFmt.GetAnchor().GetAnchorId();
2406
2407 if ( (FLY_AS_CHAR == eAnchor) || (FLY_AT_FLY == eAnchor) )
2408 {
2409 // no conversion for as-character or at frame anchored objects
2410 return false;
2411 }
2412
2413 // determine anchored object
2414 SwAnchoredObject* pAnchoredObj( 0L );
2415 {
2416 const SwContact* pContact = _rFrmFmt.FindContactObj();
2417 if ( pContact )
2418 {
2419 std::list<SwAnchoredObject*> aAnchoredObjs;
2420 pContact->GetAnchoredObjs( aAnchoredObjs );
2421 if ( !aAnchoredObjs.empty() )
2422 {
2423 pAnchoredObj = aAnchoredObjs.front();
2424 }
2425 }
2426 }
2427 if ( !pAnchoredObj )
2428 {
2429 // no anchored object found. Thus, the needed layout information can't
2430 // be determined. --> no conversion
2431 return false;
2432 }
2433 // --> OD 2006-09-26 #141404#
2434 // no conversion for anchored drawing object, which aren't attached to an
2435 // anchor frame.
2436 // This is the case for drawing objects, which are anchored inside a page
2437 // header/footer of an *unused* page style.
2438 if ( dynamic_cast<SwAnchoredDrawObject*>(pAnchoredObj) &&
2439 !pAnchoredObj->GetAnchorFrm() )
2440 {
2441 return false;
2442 }
2443 // <--
2444
2445 bool bConverted( false );
2446
2447 // determine value of attribute 'Follow text flow', because positions aligned
2448 // at page areas have to be converted, if it's set.
2449 const bool bFollowTextFlow = _rFrmFmt.GetFollowTextFlow().GetValue();
2450
2451 // --> OD 2007-07-24 #148096#
2452 // check, if horizontal and vertical position have to be converted due to
2453 // the fact, that the object is anchored at a paragraph, which has a "column
2454 // break before" attribute
2455 bool bConvDueToAnchoredAtColBreakPara( false );
2456 if ( ( (eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR) ) &&
2457 _rFrmFmt.GetAnchor().GetCntntAnchor() &&
2458 _rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode().IsTxtNode() )
2459 {
2460 SwTxtNode& rAnchorTxtNode =
2461 dynamic_cast<SwTxtNode&>(_rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode());
2462 const SvxFmtBreakItem* pBreak = &(ItemGet<SvxFmtBreakItem>(rAnchorTxtNode, RES_BREAK));
2463 if ( pBreak &&
2464 pBreak->GetBreak() == SVX_BREAK_COLUMN_BEFORE )
2465 {
2466 bConvDueToAnchoredAtColBreakPara = true;
2467 }
2468 }
2469 // <--
2470
2471 // convert horizontal position, if needed
2472 {
2473 enum HoriConv { NO_CONV, CONV2PG, CONV2COL, CONV2CHAR };
2474 HoriConv eHoriConv( NO_CONV );
2475
2476 // determine, if conversion has to be performed due to the position orientation
2477 bool bConvDueToOrientation( false );
2478 {
2479 const sal_Int16 eHOri = _iorHoriOri.GetHoriOrient();
2480 bConvDueToOrientation = eHOri == text::HoriOrientation::LEFT || eHOri == text::HoriOrientation::RIGHT ||
2481 eHOri == text::HoriOrientation::INSIDE || eHOri == text::HoriOrientation::OUTSIDE ||
2482 ( eHOri != text::HoriOrientation::CENTER && _iorHoriOri.IsPosToggle() );
2483 }
2484
2485 // determine conversion type due to the position relation
2486 // --> OD 2007-07-24 #148096#
2487 if ( bConvDueToAnchoredAtColBreakPara )
2488 {
2489 eHoriConv = CONV2PG;
2490 }
2491 else if ( _iorHoriOri.IsPosToggle()
2492 && _iorHoriOri.GetHoriOrient() == text::HoriOrientation::RIGHT )
2493 {
2494 eHoriConv = NO_CONV;
2495 _iorHoriOri.SetHoriOrient( text::HoriOrientation::OUTSIDE );
2496 }
2497 else
2498 {
2499 switch ( _iorHoriOri.GetRelationOrient() )
2500 {
2501 case text::RelOrientation::PAGE_FRAME:
2502 case text::RelOrientation::PAGE_PRINT_AREA:
2503 {
2504 if ( bConvDueToOrientation || bFollowTextFlow )
2505 eHoriConv = CONV2PG;
2506 }
2507 break;
2508 case text::RelOrientation::PAGE_LEFT:
2509 case text::RelOrientation::PAGE_RIGHT:
2510 {
2511 // relation not supported by WW8. Thus, conversion always needed.
2512 eHoriConv = CONV2PG;
2513 }
2514 break;
2515 case text::RelOrientation::FRAME:
2516 {
2517 if ( bConvDueToOrientation )
2518 eHoriConv = CONV2COL;
2519 }
2520 break;
2521 case text::RelOrientation::PRINT_AREA:
2522 case text::RelOrientation::FRAME_LEFT:
2523 case text::RelOrientation::FRAME_RIGHT:
2524 {
2525 // relation not supported by WW8. Thus, conversion always needed.
2526 eHoriConv = CONV2COL;
2527 }
2528 break;
2529 case text::RelOrientation::CHAR:
2530 {
2531 if ( bConvDueToOrientation )
2532 eHoriConv = CONV2CHAR;
2533 }
2534 break;
2535 default:
2536 ASSERT( false,
2537 "<WinwordAnchoring::ConvertPosition(..)> - unknown horizontal relation" );
2538 }
2539 }
2540 // <--
2541 if ( eHoriConv != NO_CONV )
2542 {
2543 _iorHoriOri.SetHoriOrient( text::HoriOrientation::NONE );
2544 SwTwips nPosX( 0L );
2545 {
2546 Point aPos;
2547 if ( eHoriConv == CONV2PG )
2548 {
2549 _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
2550 // --> OD 2005-01-27 #i33818#
2551 bool bRelToTableCell( false );
2552 aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
2553 bRelToTableCell );
2554 if ( bRelToTableCell )
2555 {
2556 _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
2557 }
2558 // <--
2559 }
2560 else if ( eHoriConv == CONV2COL )
2561 {
2562 _iorHoriOri.SetRelationOrient( text::RelOrientation::FRAME );
2563 aPos = pAnchoredObj->GetRelPosToAnchorFrm();
2564 }
2565 else if ( eHoriConv == CONV2CHAR )
2566 {
2567 _iorHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
2568 aPos = pAnchoredObj->GetRelPosToChar();
2569 }
2570 // No distinction between layout directions, because of missing
2571 // information about WW8 in vertical layout.
2572 nPosX = aPos.X();
2573 }
2574 _iorHoriOri.SetPos( nPosX );
2575 bConverted = true;
2576 }
2577 }
2578
2579 // convert vertical position, if needed
2580 {
2581 enum VertConv { NO_CONV, CONV2PG, CONV2PARA, CONV2LINE };
2582 VertConv eVertConv( NO_CONV );
2583
2584 // determine, if conversion has to be performed due to the position orientation
2585 bool bConvDueToOrientation( false );
2586 {
2587 const sal_Int16 eVOri = _iorVertOri.GetVertOrient();
2588 bConvDueToOrientation = ( eVOri == text::VertOrientation::TOP ||
2589 eVOri == text::VertOrientation::BOTTOM ||
2590 eVOri == text::VertOrientation::CHAR_TOP ||
2591 eVOri == text::VertOrientation::CHAR_BOTTOM ||
2592 eVOri == text::VertOrientation::CHAR_CENTER ||
2593 eVOri == text::VertOrientation::LINE_TOP ||
2594 eVOri == text::VertOrientation::LINE_BOTTOM ||
2595 eVOri == text::VertOrientation::LINE_CENTER );
2596 }
2597
2598 // determine conversion type due to the position relation
2599 // --> OD 2007-07-24 #148096#
2600 if ( bConvDueToAnchoredAtColBreakPara )
2601 {
2602 eVertConv = CONV2PG;
2603 }
2604 else
2605 {
2606 switch ( _iorVertOri.GetRelationOrient() )
2607 {
2608 case text::RelOrientation::PAGE_FRAME:
2609 case text::RelOrientation::PAGE_PRINT_AREA:
2610 {
2611 if ( bConvDueToOrientation || bFollowTextFlow )
2612 eVertConv = CONV2PG;
2613 }
2614 break;
2615 case text::RelOrientation::FRAME:
2616 {
2617 if ( bConvDueToOrientation ||
2618 _iorVertOri.GetVertOrient() == text::VertOrientation::CENTER )
2619 {
2620 eVertConv = CONV2PARA;
2621 }
2622 }
2623 break;
2624 case text::RelOrientation::PRINT_AREA:
2625 {
2626 // relation not supported by WW8. Thus, conversion always needed.
2627 eVertConv = CONV2PARA;
2628 }
2629 break;
2630 case text::RelOrientation::CHAR:
2631 {
2632 // relation not supported by WW8. Thus, conversion always needed.
2633 eVertConv = CONV2PARA;
2634 }
2635 break;
2636 case text::RelOrientation::TEXT_LINE:
2637 {
2638 if ( bConvDueToOrientation ||
2639 _iorVertOri.GetVertOrient() == text::VertOrientation::NONE )
2640 {
2641 eVertConv = CONV2LINE;
2642 }
2643 }
2644 break;
2645 case text::RelOrientation::PAGE_LEFT:
2646 case text::RelOrientation::PAGE_RIGHT:
2647 case text::RelOrientation::FRAME_LEFT:
2648 case text::RelOrientation::FRAME_RIGHT:
2649 default:
2650 ASSERT( false,
2651 "<WinwordAnchoring::ConvertPosition(..)> - unknown vertical relation" );
2652 }
2653 }
2654 // <--
2655 if ( eVertConv != NO_CONV )
2656 {
2657 _iorVertOri.SetVertOrient( text::VertOrientation::NONE );
2658 SwTwips nPosY( 0L );
2659 {
2660 Point aPos;
2661 if ( eVertConv == CONV2PG )
2662 {
2663 _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
2664 // --> OD 2005-01-27 #i33818#
2665 bool bRelToTableCell( false );
2666 aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
2667 bRelToTableCell );
2668 if ( bRelToTableCell )
2669 {
2670 _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
2671 }
2672 // <--
2673 }
2674 else if ( eVertConv == CONV2PARA )
2675 {
2676 _iorVertOri.SetRelationOrient( text::RelOrientation::FRAME );
2677 aPos = pAnchoredObj->GetRelPosToAnchorFrm();
2678 }
2679 else if ( eVertConv == CONV2LINE )
2680 {
2681 _iorVertOri.SetRelationOrient( text::RelOrientation::TEXT_LINE );
2682 aPos = pAnchoredObj->GetRelPosToLine();
2683 }
2684 // No distinction between layout directions, because of missing
2685 // information about WW8 in vertical layout.
2686 nPosY = aPos.Y();
2687 }
2688 _iorVertOri.SetPos( nPosY );
2689 bConverted = true;
2690 }
2691 }
2692
2693 return bConverted;
2694 }
2695
SetAnchoring(const SwFrmFmt & rFmt)2696 void WinwordAnchoring::SetAnchoring(const SwFrmFmt& rFmt)
2697 {
2698 const RndStdIds eAnchor = rFmt.GetAnchor().GetAnchorId();
2699 mbInline = (eAnchor == FLY_AS_CHAR);
2700
2701 SwFmtHoriOrient rHoriOri = rFmt.GetHoriOrient();
2702 SwFmtVertOrient rVertOri = rFmt.GetVertOrient();
2703
2704 // --> OD 2005-01-06 #i30669# - convert the positioning attributes.
2705 // Most positions are converted, if layout information exists.
2706 const bool bPosConverted = ConvertPosition( rHoriOri, rVertOri, rFmt );
2707 // <--
2708
2709 const sal_Int16 eHOri = rHoriOri.GetHoriOrient();
2710 // CMC, OD 24.11.2003 #i22673#
2711 const sal_Int16 eVOri = rVertOri.GetVertOrient();
2712
2713 const sal_Int16 eHRel = rHoriOri.GetRelationOrient();
2714 const sal_Int16 eVRel = rVertOri.GetRelationOrient();
2715
2716 // horizontal Adjustment
2717 switch (eHOri)
2718 {
2719 default:
2720 case text::HoriOrientation::NONE:
2721 mnXAlign = 0;
2722 break;
2723 case text::HoriOrientation::LEFT:
2724 mnXAlign = 1;
2725 break;
2726 case text::HoriOrientation::CENTER:
2727 mnXAlign = 2;
2728 break;
2729 case text::HoriOrientation::RIGHT:
2730 mnXAlign = 3;
2731 break;
2732 case text::HoriOrientation::INSIDE:
2733 mnXAlign = 4;
2734 break;
2735 case text::HoriOrientation::OUTSIDE:
2736 mnXAlign = 5;
2737 break;
2738 }
2739
2740 // vertical Adjustment
2741 // CMC, OD 24.11.2003 #i22673#
2742 // When adjustment is vertically relative to line or to char
2743 // bottom becomes top and vice versa
2744 const bool bVertSwap = !bPosConverted &&
2745 ( (eVRel == text::RelOrientation::CHAR) ||
2746 (eVRel == text::RelOrientation::TEXT_LINE) );
2747 switch (eVOri)
2748 {
2749 default:
2750 case text::VertOrientation::NONE:
2751 mnYAlign = 0;
2752 break;
2753 case text::VertOrientation::TOP:
2754 case text::VertOrientation::LINE_TOP:
2755 case text::VertOrientation::CHAR_TOP:
2756 mnYAlign = bVertSwap ? 3 : 1;
2757 break;
2758 case text::VertOrientation::CENTER:
2759 case text::VertOrientation::LINE_CENTER:
2760 mnYAlign = 2;
2761 break;
2762 case text::VertOrientation::BOTTOM:
2763 case text::VertOrientation::LINE_BOTTOM:
2764 case text::VertOrientation::CHAR_BOTTOM:
2765 mnYAlign = bVertSwap ? 1 : 3;
2766 break;
2767 }
2768
2769 // Adjustment is horizontally relative to...
2770 switch (eHRel)
2771 {
2772 case text::RelOrientation::PAGE_PRINT_AREA:
2773 mnXRelTo = 0;
2774 break;
2775 case text::RelOrientation::PAGE_FRAME:
2776 case text::RelOrientation::PAGE_LEFT: //:-(
2777 case text::RelOrientation::PAGE_RIGHT: //:-(
2778 mnXRelTo = 1;
2779 break;
2780 case text::RelOrientation::FRAME:
2781 case text::RelOrientation::FRAME_LEFT: //:-(
2782 case text::RelOrientation::FRAME_RIGHT: //:-(
2783 if (eAnchor == FLY_AT_PAGE)
2784 mnXRelTo = 1;
2785 else
2786 mnXRelTo = 2;
2787 break;
2788 case text::RelOrientation::PRINT_AREA:
2789 if (eAnchor == FLY_AT_PAGE)
2790 mnXRelTo = 0;
2791 else
2792 mnXRelTo = 2;
2793 break;
2794 case text::RelOrientation::CHAR:
2795 mnXRelTo = 3;
2796 break;
2797 case text::RelOrientation::TEXT_LINE:
2798 break;
2799 }
2800
2801 // Adjustment is vertically relative to...
2802 switch (eVRel)
2803 {
2804 case text::RelOrientation::PAGE_PRINT_AREA:
2805 mnYRelTo = 0;
2806 break;
2807 case text::RelOrientation::PAGE_FRAME:
2808 mnYRelTo = 1;
2809 break;
2810 case text::RelOrientation::PRINT_AREA:
2811 if (eAnchor == FLY_AT_PAGE)
2812 mnYRelTo = 0;
2813 else
2814 mnYRelTo = 2;
2815 break;
2816 case text::RelOrientation::FRAME:
2817 if (eAnchor == FLY_AT_PAGE)
2818 mnYRelTo = 1;
2819 else
2820 mnYRelTo = 2;
2821 break;
2822 case text::RelOrientation::CHAR:
2823 case text::RelOrientation::TEXT_LINE: // CMC, OD 24.11.2003 #i22673# - vertical alignment at top of line
2824 case text::RelOrientation::PAGE_LEFT: //nonsense
2825 case text::RelOrientation::PAGE_RIGHT: //nonsense
2826 case text::RelOrientation::FRAME_LEFT: //nonsense
2827 case text::RelOrientation::FRAME_RIGHT: //nonsense
2828 mnYRelTo = 3;
2829 break;
2830 }
2831 }
2832
WriteFrmExtraData(const SwFrmFmt & rFmt)2833 void SwEscherEx::WriteFrmExtraData( const SwFrmFmt& rFmt )
2834 {
2835 aWinwordAnchoring.SetAnchoring(rFmt);
2836 aWinwordAnchoring.WriteData(*this);
2837
2838 AddAtom(4, ESCHER_ClientAnchor);
2839 GetStream() << 0L;
2840
2841 AddAtom(4, ESCHER_ClientData);
2842 GetStream() << 1L;
2843 }
2844
WriteFlyFrm(const DrawObj & rObj,sal_uInt32 & rShapeId,DrawObjPointerVector & rPVec)2845 sal_Int32 SwEscherEx::WriteFlyFrm(const DrawObj &rObj, sal_uInt32 &rShapeId,
2846 DrawObjPointerVector &rPVec)
2847 {
2848 const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
2849
2850 // check for textflyframe and if it is the first in a Chain
2851 sal_Int32 nBorderThick = 0;
2852 const SwNodeIndex* pNdIdx = rFmt.GetCntnt().GetCntntIdx();
2853 if( pNdIdx )
2854 {
2855 SwNodeIndex aIdx( *pNdIdx, 1 );
2856 switch( aIdx.GetNode().GetNodeType() )
2857 {
2858 case ND_GRFNODE:
2859 nBorderThick = WriteGrfFlyFrame( rFmt, rShapeId = GenerateShapeId() );
2860 break;
2861 case ND_OLENODE:
2862 nBorderThick = WriteOLEFlyFrame( rFmt, rShapeId = GenerateShapeId() );
2863 break;
2864 default:
2865 if (const SdrObject* pObj = rFmt.FindRealSdrObject())
2866 {
2867 // check for the first in a Chain
2868 sal_uInt32 nTxtId;
2869 sal_uInt16 nOff = 0;
2870 const SwFrmFmt* pFmt = &rFmt, *pPrev;
2871 while( 0 != ( pPrev = pFmt->GetChain().GetPrev() ))
2872 {
2873 ++nOff;
2874 pFmt = pPrev;
2875 }
2876
2877 rShapeId = GetFlyShapeId(rFmt, rObj.mnHdFtIndex, rPVec);
2878 if( !nOff )
2879 {
2880 void* p = (void*)pObj;
2881 nTxtId = pTxtBxs->GetPos( p );
2882 if( USHRT_MAX == nTxtId )
2883 {
2884 pTxtBxs->Append( *pObj, rShapeId );
2885 nTxtId = pTxtBxs->Count();
2886 }
2887 else
2888 ++nTxtId;
2889 }
2890 else
2891 {
2892 const SdrObject* pPrevObj = pFmt->FindRealSdrObject();
2893 void* p = (void*)pPrevObj;
2894 nTxtId = pTxtBxs->GetPos( p );
2895 if( USHRT_MAX == nTxtId )
2896 {
2897 sal_uInt32 nPrevShapeId =
2898 GetFlyShapeId(*pFmt, rObj.mnHdFtIndex, rPVec);
2899 pTxtBxs->Append( *pPrevObj, nPrevShapeId );
2900 nTxtId = pTxtBxs->Count();
2901 }
2902 else
2903 ++nTxtId;
2904 }
2905 nTxtId *= 0x10000;
2906 nTxtId += nOff;
2907
2908 nBorderThick = WriteTxtFlyFrame(rObj, rShapeId, nTxtId, rPVec);
2909 }
2910
2911 //In browse mode the sdr object doesn't always exist. For example, the
2912 //object is in the hidden header/footer. We save the fmt directly
2913 //in such cases; we copy most of the logic from the block above
2914 const bool bBrowseMode = (rFmt.getIDocumentSettingAccess())->get(IDocumentSettingAccess::BROWSE_MODE);
2915 if( bBrowseMode && rFmt.GetDoc())
2916 {
2917 if( !rFmt.GetChain().GetPrev() )//obj in header/footer?
2918 {
2919 rShapeId = GetFlyShapeId(rFmt, rObj.mnHdFtIndex, rPVec);
2920 pTxtBxs->Append( &rFmt, rShapeId );
2921 sal_uInt32 nTxtId = pTxtBxs->Count();
2922
2923 nTxtId *= 0x10000;
2924 nBorderThick = WriteTxtFlyFrame(rObj, rShapeId, nTxtId, rPVec);
2925 }
2926 }
2927
2928 }
2929 }
2930 return nBorderThick;
2931 }
2932
FindPos(const SwFrmFmt & rFmt,unsigned int nHdFtIndex,DrawObjPointerVector & rPVec)2933 sal_uInt16 FindPos(const SwFrmFmt &rFmt, unsigned int nHdFtIndex,
2934 DrawObjPointerVector &rPVec)
2935 {
2936 DrawObjPointerIter aEnd = rPVec.end();
2937 for (DrawObjPointerIter aIter = rPVec.begin(); aIter != aEnd; ++aIter)
2938 {
2939 const DrawObj *pObj = (*aIter);
2940 ASSERT(pObj, "Impossible");
2941 if (!pObj)
2942 continue;
2943 if (
2944 nHdFtIndex == pObj->mnHdFtIndex &&
2945 &rFmt == (&pObj->maCntnt.GetFrmFmt())
2946 )
2947 {
2948 return static_cast< sal_uInt16 >(aIter - rPVec.begin());
2949 }
2950 }
2951 return USHRT_MAX;
2952 }
2953
WriteTxtFlyFrame(const DrawObj & rObj,sal_uInt32 nShapeId,sal_uInt32 nTxtBox,DrawObjPointerVector & rPVec)2954 sal_Int32 SwEscherEx::WriteTxtFlyFrame(const DrawObj &rObj, sal_uInt32 nShapeId,
2955 sal_uInt32 nTxtBox, DrawObjPointerVector &rPVec)
2956 {
2957 const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
2958 short nDirection = rObj.mnDirection;
2959
2960 sal_Int32 nBorderThick=0;
2961 OpenContainer( ESCHER_SpContainer );
2962
2963 AddShape( ESCHER_ShpInst_TextBox, 0xa00, nShapeId );
2964 EscherPropertyContainer aPropOpt;
2965 aPropOpt.AddOpt(ESCHER_Prop_lTxid, nTxtBox);
2966 if (const SwFrmFmt *pNext = rFmt.GetChain().GetNext())
2967 {
2968 sal_uInt16 nPos = FindPos(*pNext, rObj.mnHdFtIndex, rPVec);
2969 if (USHRT_MAX != nPos && aFollowShpIds[nPos])
2970 aPropOpt.AddOpt(ESCHER_Prop_hspNext, aFollowShpIds[nPos]);
2971 }
2972 nBorderThick = WriteFlyFrameAttr( rFmt, mso_sptTextBox, aPropOpt );
2973
2974 MSO_TextFlow nFlow;
2975
2976 switch (nDirection)
2977 {
2978 default:
2979 ASSERT(sal_False, "unknown direction type");
2980 case FRMDIR_HORI_LEFT_TOP:
2981 nFlow=mso_txflHorzN;
2982 break;
2983 case FRMDIR_HORI_RIGHT_TOP:
2984 nFlow=mso_txflHorzN;
2985 break;
2986 case FRMDIR_VERT_TOP_LEFT: //not really possible in word
2987 case FRMDIR_VERT_TOP_RIGHT:
2988 nFlow=mso_txflTtoBA;
2989 break;
2990 }
2991 aPropOpt.AddOpt( ESCHER_Prop_txflTextFlow, nFlow );
2992
2993 aPropOpt.Commit( GetStream() );
2994
2995 // store anchor attribute
2996 WriteFrmExtraData( rFmt );
2997
2998 AddAtom( 4, ESCHER_ClientTextbox ); GetStream() << nTxtBox;
2999
3000 CloseContainer(); // ESCHER_SpContainer
3001 return nBorderThick;
3002 }
3003
WriteOLEPicture(EscherPropertyContainer & rPropOpt,sal_uInt32 nShapeFlags,const Graphic & rGraphic,const SdrObject & rObj,sal_uInt32 nShapeId,const awt::Rectangle * pVisArea)3004 void SwBasicEscherEx::WriteOLEPicture(EscherPropertyContainer &rPropOpt,
3005 sal_uInt32 nShapeFlags, const Graphic &rGraphic, const SdrObject &rObj,
3006 sal_uInt32 nShapeId, const awt::Rectangle* pVisArea )
3007 {
3008 //nShapeFlags == 0xA00 + flips and ole active
3009 AddShape(ESCHER_ShpInst_PictureFrame, nShapeFlags, nShapeId);
3010
3011 GraphicObject aGraphicObject(rGraphic);
3012 ByteString aId = aGraphicObject.GetUniqueID();
3013 if (aId.Len())
3014 {
3015 Rectangle aRect = rObj.GetLogicRect();
3016 aRect.SetPos(Point(0,0));
3017 aRect.Right() = DrawModelToEmu(aRect.Right());
3018 aRect.Bottom() = DrawModelToEmu(aRect.Bottom());
3019 sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
3020 aId, aRect, pVisArea, 0); // SJ: the fourth parameter (VisArea) should be set..
3021 if (nBlibId)
3022 rPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
3023 }
3024
3025 SetPicId(rObj, nShapeId, rPropOpt);
3026 rPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0x10000 );
3027 }
3028
WriteOCXControl(const SwFrmFmt & rFmt,sal_uInt32 nShapeId)3029 void SwEscherEx::WriteOCXControl( const SwFrmFmt& rFmt, sal_uInt32 nShapeId )
3030 {
3031 if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
3032 {
3033 OpenContainer( ESCHER_SpContainer );
3034
3035 SwDrawModel* pModel = rWrt.pDoc->GetDrawModel();
3036 OutputDevice *pDevice = Application::GetDefaultDevice();
3037 ASSERT(pModel && pDevice, "no model or device");
3038
3039 // #i71538# use complete SdrViews
3040 // SdrExchangeView aExchange(pModel, pDevice);
3041 SdrView aExchange(pModel, pDevice);
3042
3043 Graphic aGraphic(aExchange.GetObjGraphic(pModel, pSdrObj));
3044
3045 EscherPropertyContainer aPropOpt;
3046 WriteOLEPicture(aPropOpt, 0xa00 | SHAPEFLAG_OLESHAPE, aGraphic,
3047 *pSdrObj, nShapeId, NULL );
3048
3049 WriteFlyFrameAttr( rFmt, mso_sptPictureFrame , aPropOpt );
3050 aPropOpt.Commit( GetStream() );
3051
3052 // store anchor attribute
3053 WriteFrmExtraData( rFmt );
3054
3055 CloseContainer(); // ESCHER_SpContainer
3056 }
3057 }
3058
MakeZOrderArrAndFollowIds(std::vector<DrawObj> & rSrcArr,std::vector<DrawObj * > & rDstArr)3059 void SwEscherEx::MakeZOrderArrAndFollowIds(
3060 std::vector<DrawObj>& rSrcArr, std::vector<DrawObj*>&rDstArr)
3061 {
3062 sal_uInt16 n, nCnt = static_cast< sal_uInt16 >(rSrcArr.size());
3063 SvULongsSort aSort( 255 < nCnt ? 255 : nCnt, 255 );
3064 rDstArr.clear();
3065 rDstArr.reserve(nCnt);
3066 for (n = 0; n < nCnt; ++n)
3067 {
3068 const SwFrmFmt &rFmt = rSrcArr[n].maCntnt.GetFrmFmt();
3069 sal_uLong nOrdNum = rWrt.GetSdrOrdNum(rFmt);
3070 sal_uInt16 nPos;
3071 //returns what will be the index in rDstArr of p as nPos
3072 aSort.Insert(nOrdNum, nPos);
3073 DrawObj &rObj = rSrcArr[n];
3074 rDstArr.insert(rDstArr.begin() + nPos, &rObj);
3075 }
3076
3077 if (aFollowShpIds.Count())
3078 aFollowShpIds.Remove(0, aFollowShpIds.Count());
3079
3080 for (n = 0; n < nCnt; ++n)
3081 {
3082 const SwFrmFmt &rFmt = rDstArr[n]->maCntnt.GetFrmFmt();
3083 bool bNeedsShapeId = false;
3084
3085 if (RES_FLYFRMFMT == rFmt.Which())
3086 {
3087 const SwFmtChain &rChain = rFmt.GetChain();
3088 if (rChain.GetPrev() || rChain.GetNext())
3089 bNeedsShapeId = true;
3090 }
3091
3092 sal_uLong nShapeId = bNeedsShapeId ? GenerateShapeId() : 0;
3093
3094 aFollowShpIds.Insert(nShapeId, n);
3095 }
3096 }
3097
GetFlyShapeId(const SwFrmFmt & rFmt,unsigned int nHdFtIndex,DrawObjPointerVector & rpVec)3098 sal_uInt32 SwEscherEx::GetFlyShapeId(const SwFrmFmt& rFmt,
3099 unsigned int nHdFtIndex, DrawObjPointerVector &rpVec)
3100 {
3101 sal_uInt16 nPos = FindPos(rFmt, nHdFtIndex, rpVec);
3102 sal_uInt32 nShapeId;
3103 if (USHRT_MAX != nPos)
3104 {
3105 if (0 == (nShapeId = aFollowShpIds[nPos]))
3106 {
3107 nShapeId = GenerateShapeId();
3108 aFollowShpIds[ nPos ] = nShapeId;
3109 }
3110 }
3111 else
3112 nShapeId = GenerateShapeId();
3113 return nShapeId;
3114 }
3115
QueryTextID(const uno::Reference<drawing::XShape> & xXShapeRef,sal_uInt32 nShapeId)3116 sal_uInt32 SwEscherEx::QueryTextID(
3117 const uno::Reference< drawing::XShape>& xXShapeRef, sal_uInt32 nShapeId )
3118 {
3119 sal_uInt32 nId = 0;
3120 if (SdrObject* pObj = GetSdrObjectFromXShape(xXShapeRef))
3121 {
3122 pTxtBxs->Append( *pObj, nShapeId );
3123 nId = pTxtBxs->Count();
3124 nId *= 0x10000;
3125 }
3126 return nId;
3127 }
3128
ExportControl(WW8Export & rWW8Wrt,const SdrObject * pObj)3129 bool SwMSConvertControls::ExportControl(WW8Export &rWW8Wrt, const SdrObject *pObj)
3130 {
3131 if (!rWW8Wrt.bWrtWW8)
3132 return false;
3133
3134 SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObj);
3135 uno::Reference< awt::XControlModel > xControlModel =
3136 pFormObj->GetUnoControlModel();
3137
3138 //Why oh lord do we use so many different units ?
3139 //I think I painted myself into a little bit of a
3140 //corner by trying to use the uno interface for
3141 //controls export
3142 Rectangle aRect = pFormObj->GetLogicRect();
3143 aRect.SetPos(Point(0,0));
3144 awt::Size aSize;
3145 aSize.Width = TWIPS_TO_MM(aRect.Right());
3146 aSize.Height = TWIPS_TO_MM(aRect.Bottom());
3147
3148 //Open the ObjectPool
3149 SvStorageRef xObjPool = rWW8Wrt.GetWriter().GetStorage().OpenSotStorage(
3150 CREATE_CONST_ASC(SL::aObjectPool), STREAM_READWRITE |
3151 STREAM_SHARE_DENYALL);
3152
3153 //Create a destination storage for the microsoft control
3154 String sStorageName('_');
3155 sStorageName += String::CreateFromInt32((sal_uInt32)(sal_uIntPtr)pObj);
3156 SvStorageRef xOleStg = xObjPool->OpenSotStorage(sStorageName,
3157 STREAM_READWRITE|STREAM_SHARE_DENYALL);
3158
3159 if (!xOleStg.Is())
3160 return false;
3161
3162 String sName;
3163 if (!WriteOCXStream(xOleStg,xControlModel,aSize,sName))
3164 return false;
3165
3166 sal_uInt8 aSpecOLE[] =
3167 {
3168 0x03, 0x6a, 0xFF, 0xFF, 0xFF, 0xFF, // sprmCPicLocation
3169 0x0a, 0x08, 1, // sprmCFOLE2
3170 0x55, 0x08, 1, // sprmCFSpec
3171 0x56, 0x08, 1 // sprmCFObj
3172 };
3173 //Set the obj id into the sprmCPicLocation
3174 sal_uInt8 *pData = aSpecOLE+2;
3175 Set_UInt32(pData,(sal_uInt32)(sal_uIntPtr)pObj);
3176
3177 String sFld(FieldString(ww::eCONTROL));
3178 sFld.APPEND_CONST_ASC("Forms.");
3179 sFld += sName;
3180 sFld.APPEND_CONST_ASC(".1 \\s ");
3181
3182 rWW8Wrt.OutputField(0, ww::eCONTROL, sFld,
3183 WRITEFIELD_START|WRITEFIELD_CMD_START|WRITEFIELD_CMD_END);
3184
3185 rWW8Wrt.pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell(),sizeof(aSpecOLE),
3186 aSpecOLE);
3187 rWW8Wrt.WriteChar( 0x1 );
3188 rWW8Wrt.OutputField(0, ww::eCONTROL, aEmptyStr, WRITEFIELD_END | WRITEFIELD_CLOSE);
3189 return true;
3190 }
3191
3192 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
3193