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