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