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