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