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