merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / ww8 / wrtw8esh.cxx
bloba23f68f813d5fb5b98f0ac80e0cc2a64b58b5519
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: wrtw8esh.cxx,v $
10 * $Revision: 1.105.10.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
34 #include <com/sun/star/embed/Aspects.hpp>
37 #include <hintids.hxx>
39 #define _SVSTDARR_ULONGSSORT
40 #define _SVSTDARR_USHORTS
41 #include <svtools/svstdarr.hxx>
42 #include <vcl/cvtgrf.hxx>
43 #include <vcl/virdev.hxx>
44 #include <com/sun/star/drawing/XShape.hpp>
45 #include <vcl/svapp.hxx>
46 #include <sot/storage.hxx>
47 #include <svtools/filter.hxx>
48 #include <svtools/itemiter.hxx>
49 #include <svx/svdobj.hxx>
50 #include <svx/svdotext.hxx>
51 #include <svx/svdmodel.hxx>
52 #include <svx/svdpage.hxx>
53 #include <svx/outlobj.hxx>
54 #include <svx/editobj.hxx>
55 #include <svx/unoshape.hxx>
56 #include <svx/brshitem.hxx>
57 #include <svx/boxitem.hxx>
58 #include <svx/lrspitem.hxx>
59 #include <svx/ulspitem.hxx>
60 #include <svx/fontitem.hxx>
61 #include <svx/frmdiritem.hxx>
62 #include <svx/svdoole2.hxx>
63 #include <svx/editeng.hxx>
64 #ifndef _SVX_FLDITEM_HXX
65 //miserable hack to get around #98519#
67 #include <svx/flditem.hxx>
68 #endif
70 #include <comphelper/seqstream.hxx>
71 #include <unotools/ucbstreamhelper.hxx>
72 #include <svtools/filter.hxx>
73 #include <svx/fmglob.hxx>
74 #include <svx/svdouno.hxx>
75 #include <svx/unoapi.hxx>
77 // #i71538#
78 #include <svx/svdview.hxx>
79 #include <fmtcnct.hxx>
80 #include <fmtanchr.hxx>
81 #include <fmtsrnd.hxx>
82 #include <fmtornt.hxx>
83 #include <fmtfsize.hxx>
84 // --> OD 2005-01-06 #i30669#
85 #include <fmtfollowtextflow.hxx>
86 // <--
87 #include <dcontact.hxx>
88 #include <frmfmt.hxx>
89 #include <fmtcntnt.hxx>
90 #include <ndindex.hxx>
91 #include <doc.hxx>
92 #include <docary.hxx>
93 #include <pam.hxx>
94 #include <swrect.hxx>
95 #include <ndgrf.hxx>
96 #include <grfatr.hxx>
97 #include <ndole.hxx>
98 #include <unodraw.hxx>
99 #include <pagedesc.hxx>
100 #include <ww8par.hxx>
101 #include <breakit.hxx>
102 #include <com/sun/star/i18n/ScriptType.hdl>
103 #include "ww8attributeoutput.hxx"
104 #include "writerhelper.hxx"
105 #include "writerwordglue.hxx"
106 #include "wrtww8.hxx"
107 #include "escher.hxx"
108 // --> OD 2007-07-24 #148096#
109 #include <ndtxt.hxx>
110 // <--
111 #include "WW8FFData.hxx"
113 using namespace com::sun::star;
114 using namespace sw::util;
115 using namespace sw::types;
116 using namespace nsFieldFlags;
118 //#110185# get a part fix for this type of element
119 bool WW8Export::MiserableFormFieldExportHack(const SwFrmFmt& rFrmFmt)
121 ASSERT(bWrtWW8, "Not allowed");
122 if (!bWrtWW8)
123 return false;
124 bool bHack = false;
125 const SdrObject *pObject = rFrmFmt.FindRealSdrObject();
126 if (pObject && pObject->GetObjInventor() == FmFormInventor)
128 if (SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObject))
130 uno::Reference< awt::XControlModel > xControlModel =
131 pFormObj->GetUnoControlModel();
132 uno::Reference< lang::XServiceInfo > xInfo(xControlModel,
133 uno::UNO_QUERY);
134 uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
135 if (xInfo->supportsService(C2U("com.sun.star.form.component.ComboBox")))
137 DoComboBox(xPropSet);
138 bHack = true;
140 else if (xInfo->supportsService(C2U("com.sun.star.form.component.CheckBox")))
142 DoCheckBox(xPropSet);
143 bHack = true;
147 return bHack;
151 void WW8Export::DoComboBox(uno::Reference<beans::XPropertySet> xPropSet)
153 rtl::OUString sSelected;
154 uno::Sequence<rtl::OUString> aListItems;
155 xPropSet->getPropertyValue(C2U("StringItemList")) >>= aListItems;
156 sal_Int32 nNoStrings = aListItems.getLength();
157 if (nNoStrings)
159 uno::Any aTmp = xPropSet->getPropertyValue(C2U("DefaultText"));
160 const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
161 if (pStr)
162 sSelected = *pStr;
165 rtl::OUString sName;
167 uno::Any aTmp = xPropSet->getPropertyValue(C2U("Name"));
168 const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
169 if (pStr)
170 sName = *pStr;
174 rtl::OUString sHelp;
176 uno::Any aTmp = xPropSet->getPropertyValue(C2U("Help"));
177 const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
178 if (pStr)
179 sHelp = *pStr;
182 rtl::OUString sToolTip;
184 uno::Any aTmp = xPropSet->getPropertyValue(C2U("Name"));
185 const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
186 if (pStr)
187 sToolTip = *pStr;
190 DoComboBox(sName, sHelp, sToolTip, sSelected, aListItems);
193 void WW8Export::DoComboBox(const rtl::OUString &rName,
194 const rtl::OUString &rHelp,
195 const rtl::OUString &rToolTip,
196 const rtl::OUString &rSelected,
197 uno::Sequence<rtl::OUString> &rListItems)
199 ASSERT(bWrtWW8, "Not allowed");
200 if (!bWrtWW8)
201 return;
202 OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
203 WRITEFIELD_START | WRITEFIELD_CMD_START);
204 // write the refence to the "picture" structure
205 ULONG nDataStt = pDataStrm->Tell();
206 pChpPlc->AppendFkpEntry( Strm().Tell() );
208 WriteChar( 0x01 );
210 static BYTE aArr1[] =
212 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
213 0x06, 0x08, 0x01, // sprmCFData
214 0x55, 0x08, 0x01, // sprmCFSpec
215 0x02, 0x08, 0x01 // sprmCFFldVanish
217 BYTE* pDataAdr = aArr1 + 2;
218 Set_UInt32( pDataAdr, nDataStt );
220 pChpPlc->AppendFkpEntry(Strm().Tell(), sizeof(aArr1), aArr1);
222 OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
223 WRITEFIELD_CLOSE);
225 ::sw::WW8FFData aFFData;
227 aFFData.setType(2);
228 aFFData.setName(rName);
229 aFFData.setHelp(rHelp);
230 aFFData.setStatus(rToolTip);
232 sal_uInt32 nListItems = rListItems.getLength();
234 for (sal_uInt32 i = 0; i < nListItems; i++)
236 if (i < 0x20 && rSelected == rListItems[i])
237 aFFData.setResult(::sal::static_int_cast<sal_uInt8>(i));
238 aFFData.addListboxEntry(rListItems[i]);
241 aFFData.Write(pDataStrm);
244 void WW8Export::DoCheckBox(uno::Reference<beans::XPropertySet> xPropSet)
246 uno::Reference<beans::XPropertySetInfo> xPropSetInfo =
247 xPropSet->getPropertySetInfo();
249 OutputField(0, ww::eFORMCHECKBOX, FieldString(ww::eFORMCHECKBOX),
250 WRITEFIELD_START | WRITEFIELD_CMD_START);
251 // write the refence to the "picture" structure
252 ULONG nDataStt = pDataStrm->Tell();
253 pChpPlc->AppendFkpEntry( Strm().Tell() );
255 WriteChar( 0x01 );
256 static BYTE aArr1[] = {
257 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
259 0x06, 0x08, 0x01, // sprmCFData
260 0x55, 0x08, 0x01, // sprmCFSpec
261 0x02, 0x08, 0x01 // sprmCFFldVanish
263 BYTE* pDataAdr = aArr1 + 2;
264 Set_UInt32( pDataAdr, nDataStt );
266 pChpPlc->AppendFkpEntry(Strm().Tell(),
267 sizeof( aArr1 ), aArr1 );
269 ::sw::WW8FFData aFFData;
271 aFFData.setType(1);
272 aFFData.setCheckboxHeight(0x14);
274 sal_Int16 nTemp = 0;
275 xPropSet->getPropertyValue(C2U("DefaultState")) >>= nTemp;
276 sal_uInt32 nIsDefaultChecked(nTemp);
278 xPropSet->getPropertyValue(C2U("State")) >>= nTemp;
279 sal_uInt32 nIsChecked(nTemp);
281 if (nIsDefaultChecked != nIsChecked)
283 switch (nIsChecked)
285 case false:
286 aFFData.setResult(0);
287 break;
288 case true:
289 aFFData.setResult(1);
290 break;
291 default:
292 ASSERT(!this, "how did that happen");
296 ::rtl::OUString aStr;
297 static ::rtl::OUString sName(C2U("Name"));
298 if (xPropSetInfo->hasPropertyByName(sName))
300 xPropSet->getPropertyValue(sName) >>= aStr;
301 aFFData.setName(aStr);
304 static ::rtl::OUString sHelpText(C2U("HelpText"));
305 if (xPropSetInfo->hasPropertyByName(sHelpText))
307 xPropSet->getPropertyValue(sHelpText) >>= aStr;
308 aFFData.setHelp(aStr);
310 static ::rtl::OUString sHelpF1Text(C2U("HelpF1Text"));
311 if (xPropSetInfo->hasPropertyByName(sHelpF1Text))
313 xPropSet->getPropertyValue(sHelpF1Text) >>= aStr;
314 aFFData.setStatus(aStr);
317 aFFData.Write(pDataStrm);
319 OutputField(0, ww::eFORMCHECKBOX, aEmptyStr, WRITEFIELD_CLOSE);
322 void WW8Export::DoFormText(const SwInputField * pFld)
324 OutputField(0, ww::eFORMTEXT, FieldString(ww::eFORMTEXT),
325 WRITEFIELD_START | WRITEFIELD_CMD_START);
326 // write the refence to the "picture" structure
327 ULONG nDataStt = pDataStrm->Tell();
328 pChpPlc->AppendFkpEntry( Strm().Tell() );
330 WriteChar( 0x01 );
331 static BYTE aArr1[] = {
332 0x02, 0x08, 0x81, // sprmCFFldVanish
333 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
335 0x06, 0x08, 0x01, // sprmCFData
336 0x55, 0x08, 0x01 // sprmCFSpec
338 BYTE* pDataAdr = aArr1 + 5;
339 Set_UInt32( pDataAdr, nDataStt );
341 pChpPlc->AppendFkpEntry(Strm().Tell(),
342 sizeof( aArr1 ), aArr1 );
344 ::sw::WW8FFData aFFData;
346 aFFData.setType(0);
347 aFFData.setName(pFld->GetPar2());
348 aFFData.setHelp(pFld->GetHelp());
349 aFFData.setStatus(pFld->GetToolTip());
350 aFFData.Write(pDataStrm);
352 OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CMD_END);
354 SwWW8Writer::WriteString16(Strm(), pFld->Expand(), false);
356 static BYTE aArr2[] = {
357 0x03, 0x6a, 0x00, 0x00, 0x00, 0x00, // sprmCPicLocation
358 0x55, 0x08, 0x01, // sprmCFSpec
359 0x75, 0x08, 0x01 // ???
362 pDataAdr = aArr2 + 2;
363 Set_UInt32( pDataAdr, nDataStt );
364 pChpPlc->AppendFkpEntry(Strm().Tell(),
365 sizeof( aArr2 ), aArr2 );
367 OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CLOSE);
370 PlcDrawObj::~PlcDrawObj()
374 //Its irritating to have to change the RTL frames position into LTR ones
375 //so that word will have to place them in the right place. Doubly so that
376 //the SO drawings and writer frames have different ideas themselves as to
377 //how to be positioned when in RTL mode!
378 bool RTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
379 sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
380 SwTwips nPageRight, SwTwips nPageSize)
382 bool bRet = false;
383 if (eHoriOri == text::HoriOrientation::NONE)
385 if (eHoriRel == text::RelOrientation::PAGE_FRAME)
387 rLeft = nPageSize - rLeft;
388 bRet = true;
390 else if (
391 (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
392 (eHoriRel == text::RelOrientation::FRAME) ||
393 (eHoriRel == text::RelOrientation::PRINT_AREA)
396 rLeft = nPageSize - nPageLeft - nPageRight - rLeft;
397 bRet = true;
400 if (bRet)
401 rLeft -= nWidth;
402 return bRet;
405 bool RTLDrawingsHack(long &rLeft, long /*nWidth*/,
406 sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
407 SwTwips nPageRight, SwTwips nPageSize)
409 bool bRet = false;
410 if (eHoriOri == text::HoriOrientation::NONE)
412 if (eHoriRel == text::RelOrientation::PAGE_FRAME)
414 rLeft = nPageSize + rLeft;
415 bRet = true;
417 else if (
418 (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
419 (eHoriRel == text::RelOrientation::FRAME) ||
420 (eHoriRel == text::RelOrientation::PRINT_AREA)
423 rLeft = nPageSize - nPageLeft - nPageRight + rLeft;
424 bRet = true;
427 return bRet;
430 bool WW8Export::MiserableRTLFrmFmtHack(SwTwips &rLeft, SwTwips &rRight,
431 const sw::Frame &rFrmFmt)
433 //Require nasty bidi swap
434 if (FRMDIR_HORI_RIGHT_TOP != pDoc->GetTextDirection(rFrmFmt.GetPosition()))
435 return false;
437 SwTwips nWidth = rRight - rLeft;
438 SwTwips nPageLeft, nPageRight;
439 SwTwips nPageSize = CurrentPageWidth(nPageLeft, nPageRight);
441 const SwFmtHoriOrient& rHOr = rFrmFmt.GetFrmFmt().GetHoriOrient();
443 bool bRet = false;
444 sw::Frame::WriterSource eSource = rFrmFmt.GetWriterType();
445 if (eSource == sw::Frame::eDrawing || eSource == sw::Frame::eFormControl)
447 if (RTLDrawingsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
448 rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
450 bRet = true;
453 else
455 if (RTLGraphicsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
456 rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
458 bRet = true;
461 if (bRet)
462 rRight = rLeft + nWidth;
463 return bRet;
466 void PlcDrawObj::WritePlc( WW8Export& rWrt ) const
468 if (8 > rWrt.pFib->nVersion) // Cannot export drawobject in vers 7-
469 return;
471 sal_uInt32 nFcStart = rWrt.pTableStrm->Tell();
473 if (!maDrawObjs.empty())
475 // write CPs
476 WW8Fib& rFib = *rWrt.pFib;
477 WW8_CP nCpOffs = GetCpOffset(rFib);
479 cDrawObjIter aEnd = maDrawObjs.end();
480 cDrawObjIter aIter;
482 for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
483 SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnCp - nCpOffs);
485 SwWW8Writer::WriteLong(*rWrt.pTableStrm, rFib.ccpText + rFib.ccpFtn +
486 rFib.ccpHdr + rFib.ccpEdn + rFib.ccpTxbx + rFib.ccpHdrTxbx + 1);
488 for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
490 // write the fspa-struct
491 const sw::Frame &rFrmFmt = aIter->maCntnt;
492 const SwFrmFmt &rFmt = rFrmFmt.GetFrmFmt();
493 const SdrObject* pObj = rFmt.FindRealSdrObject();
495 Rectangle aRect;
496 SwFmtVertOrient rVOr = rFmt.GetVertOrient();
497 SwFmtHoriOrient rHOr = rFmt.GetHoriOrient();
498 // --> OD 2005-01-06 #i30669# - convert the positioning attributes.
499 // Most positions are converted, if layout information exists.
500 const bool bPosConverted =
501 WinwordAnchoring::ConvertPosition( rHOr, rVOr, rFmt );
502 // <--
504 Point aObjPos;
505 if (RES_FLYFRMFMT == rFmt.Which())
507 SwRect aLayRect(rFmt.FindLayoutRect(false, &aObjPos));
508 // the Object is not visible - so get the values from
509 // the format. The Position may not be correct.
510 if( aLayRect.IsEmpty() )
511 aRect.SetSize( rFmt.GetFrmSize().GetSize() );
512 else
514 // --> FME 2007-06-20 #i56090# Do not only consider the first client
515 // Note that we actually would have to find the maximum size of the
516 // frame format clients. However, this already should work in most cases.
517 const SwRect aSizeRect(rFmt.FindLayoutRect());
518 if ( aSizeRect.Width() > aLayRect.Width() )
519 aLayRect.Width( aSizeRect.Width() );
520 // <--
522 aRect = aLayRect.SVRect();
525 else
527 ASSERT(pObj, "wo ist das SDR-Object?");
528 if (pObj)
530 aRect = pObj->GetSnapRect();
534 // --> OD 2005-01-06 #i30669# - use converted position, if conversion
535 // is performed. Unify position determination of Writer fly frames
536 // and drawing objects.
537 if ( bPosConverted )
539 aRect.SetPos( Point( rHOr.GetPos(), rVOr.GetPos() ) );
541 else
543 aRect -= aIter->maParentPos;
544 aObjPos = aRect.TopLeft();
545 if (text::VertOrientation::NONE == rVOr.GetVertOrient())
547 // CMC, OD 24.11.2003 #i22673#
548 sal_Int16 eOri = rVOr.GetRelationOrient();
549 if (eOri == text::RelOrientation::CHAR || eOri == text::RelOrientation::TEXT_LINE)
550 aObjPos.Y() = -rVOr.GetPos();
551 else
552 aObjPos.Y() = rVOr.GetPos();
554 if (text::HoriOrientation::NONE == rHOr.GetHoriOrient())
555 aObjPos.X() = rHOr.GetPos();
556 aRect.SetPos( aObjPos );
558 // <--
560 INT32 nThick = aIter->mnThick;
562 //If we are being exported as an inline hack, set
563 //corner to 0 and forget about border thickness for positioning
564 if (rFrmFmt.IsInline())
566 aRect.SetPos(Point(0,0));
567 nThick = 0;
570 // spid
571 SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnShapeId);
573 SwTwips nLeft = aRect.Left() + nThick;
574 SwTwips nRight = aRect.Right() - nThick;
576 //Nasty swap for bidi if neccessary
577 rWrt.MiserableRTLFrmFmtHack(nLeft, nRight, rFrmFmt);
579 //xaLeft/yaTop/xaRight/yaBottom - rel. to anchor
580 //(most of) the border is outside the graphic is word, so
581 //change dimensions to fit
582 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nLeft);
583 SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Top() + nThick);
584 SwWW8Writer::WriteLong(*rWrt.pTableStrm, nRight);
585 SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Bottom() - nThick);
587 //fHdr/bx/by/wr/wrk/fRcaSimple/fBelowText/fAnchorLock
588 USHORT nFlags=0;
589 //If nFlags isn't 0x14 its overridden by the escher properties
590 if( FLY_PAGE == rFmt.GetAnchor().GetAnchorId())
591 nFlags = 0x0000;
592 else
593 nFlags = 0x0014; // x-rel to text, y-rel to text
595 const SwFmtSurround& rSurr = rFmt.GetSurround();
596 USHORT nContour = rSurr.IsContour() ? 0x0080 : 0x0040;
597 SwSurround eSurround = rSurr.GetSurround();
600 #i3958#
601 The inline elements being export as anchored to character inside
602 the shape field hack are required to be wrap through so as to flow
603 over the following dummy 0x01 graphic
605 if (rFrmFmt.IsInline())
606 eSurround = SURROUND_THROUGHT;
608 switch (eSurround)
610 case SURROUND_NONE:
611 nFlags |= 0x0020;
612 break;
613 case SURROUND_THROUGHT:
614 nFlags |= 0x0060;
615 break;
616 case SURROUND_PARALLEL:
617 nFlags |= 0x0000 | nContour;
618 break;
619 case SURROUND_IDEAL:
620 nFlags |= 0x0600 | nContour;
621 break;
622 case SURROUND_LEFT:
623 nFlags |= 0x0200 | nContour;
624 break;
625 case SURROUND_RIGHT:
626 nFlags |= 0x0400 | nContour;
627 break;
628 default:
629 ASSERT(!this, "Unsupported surround type for export");
630 break;
632 if (pObj && (pObj->GetLayer() == rWrt.pDoc->GetHellId() ||
633 pObj->GetLayer() == rWrt.pDoc->GetInvisibleHellId()))
635 nFlags |= 0x4000;
639 #i3958# Required to make this inline stuff work in WordXP, not
640 needed for 2003 interestingly
642 if (rFrmFmt.IsInline())
643 nFlags |= 0x8000;
645 SwWW8Writer::WriteShort(*rWrt.pTableStrm, nFlags);
647 // cTxbx
648 SwWW8Writer::WriteLong(*rWrt.pTableStrm, 0);
651 RegisterWithFib(rFib, nFcStart, rWrt.pTableStrm->Tell() - nFcStart);
655 void MainTxtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
656 sal_uInt32 nLen) const
658 rFib.fcPlcfspaMom = nStart;
659 rFib.lcbPlcfspaMom = nLen;
662 WW8_CP MainTxtPlcDrawObj::GetCpOffset(const WW8Fib &) const
664 return 0;
667 void HdFtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
668 sal_uInt32 nLen) const
670 rFib.fcPlcfspaHdr = nStart;
671 rFib.lcbPlcfspaHdr = nLen;
674 WW8_CP HdFtPlcDrawObj::GetCpOffset(const WW8Fib &rFib) const
676 return rFib.ccpText + rFib.ccpFtn;
679 DrawObj& DrawObj::operator=(const DrawObj& rOther)
681 mnCp = rOther.mnCp;
682 mnShapeId = rOther.mnShapeId;
683 maCntnt = rOther.maCntnt;
684 maParentPos = rOther.maParentPos;
685 mnThick = rOther.mnThick;
686 mnDirection = rOther.mnDirection;
687 mnHdFtIndex = rOther.mnHdFtIndex;
688 return *this;
691 bool PlcDrawObj::Append( WW8Export& rWrt, WW8_CP nCp, const sw::Frame& rFmt,
692 const Point& rNdTopLeft )
694 bool bRet = false;
695 const SwFrmFmt &rFormat = rFmt.GetFrmFmt();
696 if (TXT_HDFT == rWrt.nTxtTyp || TXT_MAINTEXT == rWrt.nTxtTyp)
698 if (RES_FLYFRMFMT == rFormat.Which())
700 // check for textflyframe and if it is the first in a Chain
701 if (rFormat.GetCntnt().GetCntntIdx())
702 bRet = true;
704 else
705 bRet = true;
708 if (bRet)
710 DrawObj aObj(rFmt, nCp, rNdTopLeft, rWrt.TrueFrameDirection(rFormat),
711 rWrt.GetHdFtIndex());
712 maDrawObjs.push_back(aObj);
714 return bRet;
717 void DrawObj::SetShapeDetails(UINT32 nId, INT32 nThick)
719 mnShapeId = nId;
720 mnThick = nThick;
723 bool WW8_WrPlcTxtBoxes::WriteTxt( WW8Export& rWrt )
725 bool bRet = false;
726 rWrt.bInWriteEscher = true;
727 WW8_CP& rccp=TXT_TXTBOX == nTyp ? rWrt.pFib->ccpTxbx : rWrt.pFib->ccpHdrTxbx;
729 bRet = WriteGenericTxt( rWrt, nTyp, rccp );
731 WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
732 WW8Fib& rFib = *rWrt.pFib;
733 WW8_CP nMyOffset = rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpAtn
734 + rFib.ccpEdn;
735 if( TXT_TXTBOX == nTyp )
736 rWrt.pFldTxtBxs->Finish( nCP, nMyOffset );
737 else
738 rWrt.pFldHFTxtBxs->Finish( nCP, nMyOffset + rFib.ccpTxbx );
739 rWrt.bInWriteEscher = false;
740 return bRet;
743 void WW8_WrPlcTxtBoxes::Append( const SdrObject& rObj, UINT32 nShapeId )
745 void* p = (void*)&rObj;
746 aCntnt.Insert( p, aCntnt.Count() );
747 aShapeIds.Insert( nShapeId, aShapeIds.Count() );
750 const SvULongs* WW8_WrPlcTxtBoxes::GetShapeIdArr() const
752 return &aShapeIds;
755 /* \f */
757 UINT32 WW8Export::GetSdrOrdNum( const SwFrmFmt& rFmt ) const
759 UINT32 nOrdNum;
760 const SdrObject* pObj = rFmt.FindRealSdrObject();
761 if( pObj )
762 nOrdNum = pObj->GetOrdNum();
763 else
765 // no Layout for this format, then recalc the ordnum
766 SwFrmFmt* pFmt = (SwFrmFmt*)&rFmt;
767 nOrdNum = pDoc->GetSpzFrmFmts()->GetPos( pFmt );
769 const SdrModel* pModel = pDoc->GetDrawModel();
770 if( pModel )
771 nOrdNum += pModel->GetPage( 0 )->GetObjCount();
773 return nOrdNum;
776 void WW8Export::AppendFlyInFlys(const sw::Frame& rFrmFmt,
777 const Point& rNdTopLeft)
779 ASSERT(bWrtWW8, "this has gone horribly wrong");
780 ASSERT(!pEscher, "der EscherStream wurde schon geschrieben!");
781 if (pEscher)
782 return ;
783 PlcDrawObj *pDrwO;
784 if (TXT_HDFT == nTxtTyp)
785 pDrwO = pHFSdrObjs;
786 else
787 pDrwO = pSdrObjs;
789 if (rFrmFmt.IsInline())
791 OutputField(0, ww::eSHAPE, FieldString(ww::eSHAPE),
792 WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
795 WW8_CP nCP = Fc2Cp(Strm().Tell());
796 bool bSuccess = pDrwO->Append(*this, nCP, rFrmFmt, rNdTopLeft);
797 ASSERT(bSuccess, "Couldn't export a graphical element!");
799 if (bSuccess)
801 static const sal_uInt8 aSpec8[] =
803 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
804 0x55, 0x08, 1 // sprmCFSpec
806 // fSpec-Attribut true
807 // Fuer DrawObjets muss ein Spezial-Zeichen
808 // in den Text und darum ein fSpec-Attribut
809 pChpPlc->AppendFkpEntry( Strm().Tell() );
810 WriteChar( 0x8 );
811 pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec8 ), aSpec8 );
813 //Need dummy picture frame
814 if (rFrmFmt.IsInline())
815 OutGrf(rFrmFmt);
818 if (rFrmFmt.IsInline())
819 OutputField(0, ww::eSHAPE, aEmptyStr, WRITEFIELD_CLOSE);
822 class WW8_SdrAttrIter : public MSWordAttrIter
824 private:
825 const EditTextObject* pEditObj;
826 const SfxItemPool* pEditPool;
827 EECharAttribArray aTxtAtrArr;
828 SvPtrarr aChrTxtAtrArr;
829 SvUShorts aChrSetArr;
830 USHORT nPara;
831 xub_StrLen nAktSwPos;
832 xub_StrLen nTmpSwPos; // fuer HasItem()
833 rtl_TextEncoding eNdChrSet;
834 USHORT nScript;
835 BYTE mnTyp;
837 xub_StrLen SearchNext( xub_StrLen nStartPos );
838 void SetCharSet(const EECharAttrib& rTxtAttr, bool bStart);
840 //No copying
841 WW8_SdrAttrIter(const WW8_SdrAttrIter&);
842 WW8_SdrAttrIter& operator=(const WW8_SdrAttrIter&);
843 public:
844 WW8_SdrAttrIter( WW8Export& rWr, const EditTextObject& rEditObj,
845 BYTE nType );
846 void NextPara( USHORT nPar );
847 void OutParaAttr(bool bCharAttr);
848 void OutEEField(const SfxPoolItem& rHt);
850 bool IsTxtAttr(xub_StrLen nSwPos);
852 void NextPos() { nAktSwPos = SearchNext( nAktSwPos + 1 ); }
854 void OutAttr( xub_StrLen nSwPos );
855 virtual const SfxPoolItem* HasTextItem( USHORT nWhich ) const;
856 virtual const SfxPoolItem& GetItem( USHORT nWhich ) const;
857 bool OutAttrWithRange(xub_StrLen nPos);
858 xub_StrLen WhereNext() const { return nAktSwPos; }
859 rtl_TextEncoding GetNextCharSet() const;
860 rtl_TextEncoding GetNodeCharSet() const { return eNdChrSet; }
864 WW8_SdrAttrIter::WW8_SdrAttrIter( WW8Export& rWr,
865 const EditTextObject& rEditObj, BYTE nTyp )
866 : MSWordAttrIter( rWr ), pEditObj(&rEditObj), pEditPool(0),
867 aTxtAtrArr( 0, 4 ), aChrTxtAtrArr( 0, 4 ), aChrSetArr( 0, 4 ),
868 mnTyp(nTyp)
870 NextPara( 0 );
873 void WW8_SdrAttrIter::NextPara( USHORT nPar )
875 nPara = nPar;
876 // Attributwechsel an Pos 0 wird ignoriert, da davon ausgegangen
877 // wird, dass am Absatzanfang sowieso die Attribute neu ausgegeben
878 // werden.
879 aChrTxtAtrArr.Remove( 0, aChrTxtAtrArr.Count() );
880 aChrSetArr.Remove( 0, aChrSetArr.Count() );
881 nAktSwPos = nTmpSwPos = 0;
883 SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
884 pEditPool = aSet.GetPool();
885 eNdChrSet = ItemGet<SvxFontItem>(aSet,EE_CHAR_FONTINFO).GetCharSet();
887 if( pBreakIt->GetBreakIter().is() )
888 nScript = pBreakIt->GetBreakIter()->getScriptType( pEditObj->GetText(nPara), 0);
889 else
890 nScript = i18n::ScriptType::LATIN;
892 pEditObj->GetCharAttribs( nPara, aTxtAtrArr );
893 nAktSwPos = SearchNext( 1 );
896 rtl_TextEncoding WW8_SdrAttrIter::GetNextCharSet() const
898 if( aChrSetArr.Count() )
899 return (rtl_TextEncoding)aChrSetArr[ aChrSetArr.Count() - 1 ];
900 return eNdChrSet;
903 // der erste Parameter in SearchNext() liefert zurueck, ob es ein TxtAtr ist.
904 xub_StrLen WW8_SdrAttrIter::SearchNext( xub_StrLen nStartPos )
906 xub_StrLen nPos;
907 xub_StrLen nMinPos = STRING_MAXLEN;
908 xub_StrLen i;
910 for( i = 0; i < aTxtAtrArr.Count(); i++ )
912 const EECharAttrib& rHt = aTxtAtrArr[ i ];
913 nPos = rHt.nStart; // gibt erstes Attr-Zeichen
914 if( nPos >= nStartPos && nPos <= nMinPos )
916 nMinPos = nPos;
917 SetCharSet(rHt, true);
920 //?? if( pHt->GetEnd() ) // Attr mit Ende
922 nPos = rHt.nEnd; // gibt letztes Attr-Zeichen + 1
923 if( nPos >= nStartPos && nPos < nMinPos )
925 nMinPos = nPos;
926 SetCharSet(rHt, false);
929 /* else
930 { // Attr ohne Ende
931 nPos = rHt.nStart + 1; // Laenge 1 wegen CH_TXTATR im Text
932 if( nPos >= nStartPos && nPos < nMinPos )
934 nMinPos = nPos;
935 SetCharSet(rHt, false);
940 return nMinPos;
943 void WW8_SdrAttrIter::SetCharSet(const EECharAttrib& rAttr, bool bStart)
945 void* p = 0;
946 rtl_TextEncoding eChrSet;
947 const SfxPoolItem& rItem = *rAttr.pAttr;
948 switch( rItem.Which() )
950 case EE_CHAR_FONTINFO:
951 p = (void*)&rAttr;
952 eChrSet = ((SvxFontItem&)rItem).GetCharSet();
953 break;
956 if( p )
958 USHORT nPos;
959 if( bStart )
961 nPos = aChrSetArr.Count();
962 aChrSetArr.Insert( eChrSet, nPos );
963 aChrTxtAtrArr.Insert( p, nPos );
965 else if( USHRT_MAX != ( nPos = aChrTxtAtrArr.GetPos( p )) )
967 aChrTxtAtrArr.Remove( nPos );
968 aChrSetArr.Remove( nPos );
973 void WW8_SdrAttrIter::OutEEField(const SfxPoolItem& rHt)
975 const SvxFieldItem &rField = (const SvxFieldItem &)rHt;
976 const SvxFieldData *pFld = rField.GetField();
977 if (pFld && pFld->ISA(SvxURLField))
979 BYTE nOldTxtTyp = m_rExport.nTxtTyp;
980 m_rExport.nTxtTyp = mnTyp;
981 const SvxURLField *pURL = (const SvxURLField *)pFld;
982 m_rExport.AttrOutput().StartURL( pURL->GetURL(), pURL->GetTargetFrame() );
984 const String &rStr = pURL->GetRepresentation();
985 m_rExport.AttrOutput().RawText( rStr, true, GetNodeCharSet() ); // FIXME kendy: is the 'true' actually correct here? It was here before, but... ;-)
987 m_rExport.AttrOutput().EndURL();
988 m_rExport.nTxtTyp = nOldTxtTyp;
992 void WW8_SdrAttrIter::OutAttr( xub_StrLen nSwPos )
994 OutParaAttr(true);
996 if( aTxtAtrArr.Count() )
998 const SwModify* pOldMod = m_rExport.pOutFmtNode;
999 m_rExport.pOutFmtNode = 0;
1001 const SfxItemPool* pSrcPool = pEditPool;
1002 const SfxItemPool& rDstPool = m_rExport.pDoc->GetAttrPool();
1004 nTmpSwPos = nSwPos;
1005 USHORT i, nWhich, nSlotId;
1006 for( i = 0; i < aTxtAtrArr.Count(); i++ )
1008 const EECharAttrib& rHt = aTxtAtrArr[ i ];
1009 if (nSwPos >= rHt.nStart && nSwPos < rHt.nEnd)
1011 nWhich = rHt.pAttr->Which();
1012 if (nWhich == EE_FEATURE_FIELD)
1014 OutEEField(*rHt.pAttr);
1015 continue;
1017 else if (nWhich == EE_FEATURE_TAB)
1019 m_rExport.WriteChar(0x9);
1020 continue;
1022 nSlotId = pSrcPool->GetSlotId(nWhich);
1024 if (nSlotId && nWhich != nSlotId)
1026 nWhich = rDstPool.GetWhich(nSlotId);
1027 if (nWhich && nWhich != nSlotId &&
1028 nWhich < RES_UNKNOWNATR_BEGIN &&
1029 m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
1031 // use always the SW-Which Id !
1032 SfxPoolItem* pI = rHt.pAttr->Clone();
1033 pI->SetWhich( nWhich );
1034 m_rExport.AttrOutput().OutputItem( *pI );
1035 delete pI;
1040 if( nSwPos < rHt.nStart )
1041 break;
1044 nTmpSwPos = 0; // HasTextItem nur in dem obigen Bereich erlaubt
1045 m_rExport.pOutFmtNode = pOldMod;
1049 bool WW8_SdrAttrIter::IsTxtAttr(xub_StrLen nSwPos)
1051 for (USHORT i = 0; i < aTxtAtrArr.Count(); ++i)
1053 const EECharAttrib& rHt = aTxtAtrArr[ i ];
1054 if (nSwPos >= rHt.nStart && nSwPos < rHt.nEnd)
1056 if (
1057 (rHt.pAttr->Which() == EE_FEATURE_FIELD) ||
1058 (rHt.pAttr->Which() == EE_FEATURE_TAB)
1061 return true;
1065 return false;
1068 // HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
1069 // und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
1070 // die dann ueber HasItem() nach anderen Items an der
1071 // Attribut-Anfangposition fragen kann.
1072 // Es koennen nur Attribute mit Ende abgefragt werden.
1073 // Es wird mit bDeep gesucht
1074 const SfxPoolItem* WW8_SdrAttrIter::HasTextItem(USHORT nWhich) const
1076 const SfxPoolItem* pRet = 0;
1077 nWhich = sw::hack::TransformWhichBetweenPools(*pEditPool,
1078 m_rExport.pDoc->GetAttrPool(), nWhich);
1079 if (nWhich)
1081 for (USHORT i = 0; i < aTxtAtrArr.Count(); ++i)
1083 const EECharAttrib& rHt = aTxtAtrArr[i];
1084 if (
1085 nWhich == rHt.pAttr->Which() && nTmpSwPos >= rHt.nStart &&
1086 nTmpSwPos < rHt.nEnd
1089 pRet = rHt.pAttr; // Found
1090 break;
1092 else if (nTmpSwPos < rHt.nStart)
1093 break; // dann kommt da nichts mehr
1096 return pRet;
1099 const SfxPoolItem& WW8_SdrAttrIter::GetItem( USHORT nWhich ) const
1101 using sw::hack::GetSetWhichFromSwDocWhich;
1102 const SfxPoolItem* pRet = HasTextItem(nWhich);
1103 if (!pRet)
1105 SfxItemSet aSet(pEditObj->GetParaAttribs(nPara));
1106 nWhich = GetSetWhichFromSwDocWhich(aSet, *m_rExport.pDoc, nWhich);
1107 ASSERT(nWhich, "Impossible, catastrophic failure imminent");
1108 pRet = &aSet.Get(nWhich);
1110 return *pRet;
1113 void WW8_SdrAttrIter::OutParaAttr(bool bCharAttr)
1115 SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
1116 if( aSet.Count() )
1118 const SfxItemSet* pOldSet = m_rExport.GetCurItemSet();
1119 m_rExport.SetCurItemSet( &aSet );
1121 SfxItemIter aIter( aSet );
1122 const SfxPoolItem* pItem = aIter.GetCurItem();
1124 const SfxItemPool* pSrcPool = pEditPool,
1125 * pDstPool = &m_rExport.pDoc->GetAttrPool();
1127 do {
1128 USHORT nWhich = pItem->Which(),
1129 nSlotId = pSrcPool->GetSlotId( nWhich );
1131 if ( nSlotId && nWhich != nSlotId &&
1132 0 != ( nWhich = pDstPool->GetWhich( nSlotId ) ) &&
1133 nWhich != nSlotId &&
1134 ( bCharAttr ? ( nWhich >= RES_CHRATR_BEGIN && nWhich < RES_TXTATR_END )
1135 : ( nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END ) ) )
1137 // use always the SW-Which Id !
1138 SfxPoolItem* pI = pItem->Clone();
1139 pI->SetWhich( nWhich );
1140 if (m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
1141 m_rExport.AttrOutput().OutputItem( *pI );
1142 delete pI;
1144 } while( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
1145 m_rExport.SetCurItemSet( pOldSet );
1149 void WW8Export::WriteSdrTextObj(const SdrObject& rObj, BYTE nTyp)
1151 const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, &rObj);
1152 ASSERT(pTxtObj, "That is no SdrTextObj!");
1153 if (!pTxtObj)
1154 return;
1156 const OutlinerParaObject* pParaObj = 0;
1157 bool bOwnParaObj = false;
1160 #i13885#
1161 When the object is actively being edited, that text is not set into
1162 the objects normal text object, but lives in a seperate object.
1164 if (pTxtObj->IsTextEditActive())
1166 pParaObj = pTxtObj->GetEditOutlinerParaObject();
1167 bOwnParaObj = true;
1169 else
1171 pParaObj = pTxtObj->GetOutlinerParaObject();
1174 if( pParaObj )
1176 WriteOutliner(*pParaObj, nTyp);
1177 if( bOwnParaObj )
1178 delete pParaObj;
1182 void WW8Export::WriteOutliner(const OutlinerParaObject& rParaObj, BYTE nTyp)
1184 bool bAnyWrite = false;
1185 const EditTextObject& rEditObj = rParaObj.GetTextObject();
1186 WW8_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
1188 USHORT nPara = rEditObj.GetParagraphCount();
1189 BYTE bNul = 0;
1190 for( USHORT n = 0; n < nPara; ++n )
1192 if( n )
1193 aAttrIter.NextPara( n );
1195 rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
1197 ASSERT( !pO->Count(), " pO ist am Zeilenanfang nicht leer" );
1199 String aStr( rEditObj.GetText( n ));
1200 xub_StrLen nAktPos = 0;
1201 xub_StrLen nEnd = aStr.Len();
1202 do {
1203 xub_StrLen nNextAttr = aAttrIter.WhereNext();
1204 rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
1206 if( nNextAttr > nEnd )
1207 nNextAttr = nEnd;
1209 bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
1210 if( !bTxtAtr )
1211 OutSwString( aStr, nAktPos, nNextAttr - nAktPos,
1212 true, eChrSet );
1214 // Am Zeilenende werden die Attribute bis ueber das CR
1215 // aufgezogen. Ausnahme: Fussnoten am Zeilenende
1216 if( nNextAttr == nEnd && !bTxtAtr )
1217 WriteCR(); // CR danach
1219 // Ausgabe der Zeichenattribute
1220 aAttrIter.OutAttr( nAktPos ); // nAktPos - 1 ??
1221 pChpPlc->AppendFkpEntry( Strm().Tell(),
1222 pO->Count(), pO->GetData() );
1223 pO->Remove( 0, pO->Count() ); // leeren
1225 // Ausnahme: Fussnoten am Zeilenende
1226 if( nNextAttr == nEnd && bTxtAtr )
1227 WriteCR(); // CR danach
1228 nAktPos = nNextAttr;
1229 eChrSet = eNextChrSet;
1230 aAttrIter.NextPos();
1232 while( nAktPos < nEnd );
1234 ASSERT( !pO->Count(), " pO ist am ZeilenEnde nicht leer" );
1236 pO->Insert( bNul, pO->Count() ); // Style # as short
1237 pO->Insert( bNul, pO->Count() );
1239 aAttrIter.OutParaAttr(false);
1241 ULONG nPos = Strm().Tell();
1242 pPapPlc->AppendFkpEntry( Strm().Tell(),
1243 pO->Count(), pO->GetData() );
1244 pO->Remove( 0, pO->Count() ); // leeren
1245 pChpPlc->AppendFkpEntry( nPos );
1248 bAnyWrite = 0 != nPara;
1249 if( !bAnyWrite )
1250 WriteStringAsPara( aEmptyStr );
1253 void WinwordAnchoring::WriteData( EscherEx& rEx ) const
1255 //Toplevel groups get their winword extra data attached, and sub elements
1256 //use the defaults
1257 if (rEx.GetGroupLevel() <= 1)
1259 SvStream& rSt = rEx.GetStream();
1260 //The last argument denotes the number of sub properties in this atom
1261 if (mbInline)
1263 rEx.AddAtom(18, DFF_msofbtUDefProp, 3, 3); //Prop id is 0xF122
1264 rSt << (UINT16)0x0390 << sal_uInt32(3);
1265 rSt << (UINT16)0x0392 << sal_uInt32(3);
1266 //This sub property is required to be in the dummy inline frame as
1267 //well
1268 rSt << (UINT16)0x053F << nInlineHack;
1270 else
1272 rEx.AddAtom(24, DFF_msofbtUDefProp, 3, 4 ); //Prop id is 0xF122
1273 rSt << (UINT16)0x038F << mnXAlign;
1274 rSt << (UINT16)0x0390 << mnXRelTo;
1275 rSt << (UINT16)0x0391 << mnYAlign;
1276 rSt << (UINT16)0x0392 << mnYRelTo;
1281 /* \f */
1283 void WW8Export::CreateEscher()
1285 SfxItemState eBackSet =
1286 (const_cast<const SwDoc*>(pDoc))->GetPageDesc(0).GetMaster().
1287 GetItemState(RES_BACKGROUND);
1288 if (pHFSdrObjs->size() || pSdrObjs->size() || SFX_ITEM_SET == eBackSet)
1290 ASSERT( !pEscher, "wer hat den Pointer nicht geloescht?" );
1291 SvMemoryStream* pEscherStrm = new SvMemoryStream;
1292 pEscherStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1293 pEscher = new SwEscherEx(pEscherStrm, *this);
1297 void WW8Export::WriteEscher()
1299 if (pEscher)
1301 ULONG nStart = pTableStrm->Tell();
1303 pEscher->WritePictures();
1304 pEscher->FinishEscher();
1306 pFib->fcDggInfo = nStart;
1307 pFib->lcbDggInfo = pTableStrm->Tell() - nStart;
1308 delete pEscher, pEscher = 0;
1312 void SwEscherEx::WritePictures()
1314 if (pPictStrm)
1316 // set the blip - entries to the correct stream pos
1317 INT32 nEndPos = rWrt.Strm().Tell();
1318 SetNewBlipStreamOffset( nEndPos );
1320 pPictStrm->Seek( 0 );
1321 rWrt.Strm() << *pPictStrm;
1323 delete pPictStrm, pPictStrm = 0;
1325 Flush();
1328 /* \f */
1330 // Output- Routines for Escher Export
1332 SwBasicEscherEx::SwBasicEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt,
1333 UINT32 nDrawings)
1334 : EscherEx(*pStrm, nDrawings), rWrt(rWW8Wrt), pEscherStrm(pStrm),
1335 pPictStrm(0)
1337 Init();
1340 SwBasicEscherEx::~SwBasicEscherEx()
1344 void SwBasicEscherEx::WriteFrmExtraData(const SwFrmFmt&)
1346 AddAtom(4, ESCHER_ClientAnchor);
1347 GetStream() << (sal_uInt32)0x80000000;
1350 void SwBasicEscherEx::WriteEmptyFlyFrame(const SwFrmFmt& rFmt, UINT32 nShapeId)
1352 OpenContainer(ESCHER_SpContainer);
1353 AddShape(ESCHER_ShpInst_PictureFrame, 0xa00, nShapeId);
1354 // store anchor attribute
1355 WriteFrmExtraData(rFmt);
1357 AddAtom(6, DFF_msofbtUDefProp, 3, 1); //Prop id is 0xF122
1358 GetStream() << (UINT16)0x053F << nInlineHack;
1360 CloseContainer(); // ESCHER_SpContainer
1363 UINT32 AddMirrorFlags(UINT32 nFlags, const SwMirrorGrf &rMirror)
1365 switch (rMirror.GetValue())
1367 default:
1368 case RES_MIRROR_GRAPH_DONT:
1369 break;
1370 case RES_MIRROR_GRAPH_VERT:
1371 nFlags |= SHAPEFLAG_FLIPH;
1372 break;
1373 case RES_MIRROR_GRAPH_HOR:
1374 nFlags |= SHAPEFLAG_FLIPV;
1375 break;
1376 case RES_MIRROR_GRAPH_BOTH:
1377 nFlags |= SHAPEFLAG_FLIPH;
1378 nFlags |= SHAPEFLAG_FLIPV;
1379 break;
1382 return nFlags;
1385 INT32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrmFmt& rFmt, UINT32 nShapeId)
1387 INT32 nBorderThick=0;
1388 SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt);
1389 SwGrfNode *pGrfNd = pNd ? pNd->GetGrfNode() : 0;
1390 ASSERT(pGrfNd, "No SwGrfNode ?, suspicious");
1391 if (!pGrfNd)
1392 return nBorderThick;
1394 OpenContainer( ESCHER_SpContainer );
1396 const SwMirrorGrf &rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
1397 AddShape(ESCHER_ShpInst_PictureFrame, AddMirrorFlags(0xa00, rMirror),
1398 nShapeId);
1400 EscherPropertyContainer aPropOpt;
1402 UINT32 nFlags = ESCHER_BlipFlagDefault;
1404 if (pGrfNd->IsLinkedFile())
1406 String sURL;
1407 pGrfNd->GetFileFilterNms( &sURL, 0 );
1409 WW8Bytes aBuf;
1410 SwWW8Writer::InsAsString16( aBuf, sURL );
1411 SwWW8Writer::InsUInt16( aBuf, 0 );
1413 USHORT nArrLen = aBuf.Count();
1414 BYTE* pArr = new BYTE[ nArrLen ];
1415 memcpy( pArr, aBuf.GetData(), nArrLen );
1417 aPropOpt.AddOpt(ESCHER_Prop_pibName, true, nArrLen, pArr, nArrLen);
1418 nFlags = ESCHER_BlipFlagLinkToFile | ESCHER_BlipFlagURL |
1419 ESCHER_BlipFlagDoNotSave;
1421 else
1423 pGrfNd->SwapIn(true);
1425 Graphic aGraphic(pGrfNd->GetGrf());
1426 GraphicObject aGraphicObject( aGraphic );
1427 ByteString aUniqueId = aGraphicObject.GetUniqueID();
1429 if ( aUniqueId.Len() )
1431 const MapMode aMap100mm( MAP_100TH_MM );
1432 Size aSize( aGraphic.GetPrefSize() );
1434 if ( MAP_PIXEL == aGraphic.GetPrefMapMode().GetMapUnit() )
1436 aSize = Application::GetDefaultDevice()->PixelToLogic(
1437 aSize, aMap100mm );
1439 else
1441 aSize = OutputDevice::LogicToLogic( aSize,
1442 aGraphic.GetPrefMapMode(), aMap100mm );
1445 Point aEmptyPoint = Point();
1446 Rectangle aRect( aEmptyPoint, aSize );
1448 sal_uInt32 nBlibId = GetBlibID( *QueryPicStream(), aUniqueId,
1449 aRect, NULL, 0 );
1450 if (nBlibId)
1451 aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
1455 aPropOpt.AddOpt( ESCHER_Prop_pibFlags, nFlags );
1456 nBorderThick = WriteFlyFrameAttr(rFmt,mso_sptPictureFrame,aPropOpt);
1457 WriteGrfAttr(*pGrfNd, aPropOpt);
1459 aPropOpt.Commit( GetStream() );
1461 // store anchor attribute
1462 WriteFrmExtraData( rFmt );
1464 CloseContainer(); // ESCHER_SpContainer
1465 return nBorderThick;
1468 void SwBasicEscherEx::WriteGrfAttr(const SwNoTxtNode& rNd,
1469 EscherPropertyContainer& rPropOpt)
1471 const SfxPoolItem* pItem;
1472 sal_uInt32 nMode = GRAPHICDRAWMODE_STANDARD;
1473 sal_Int32 nContrast = 0;
1474 sal_Int16 nBrightness = 0;
1476 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CONTRAST,
1477 true, &pItem))
1479 nContrast = ((SfxInt16Item*)pItem)->GetValue();
1482 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_LUMINANCE,
1483 true, &pItem))
1485 nBrightness = ((SfxInt16Item*)pItem)->GetValue();
1489 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_DRAWMODE,
1490 true, &pItem))
1492 nMode = ((SfxEnumItem*)pItem)->GetValue();
1493 if (nMode == GRAPHICDRAWMODE_WATERMARK)
1496 There is no real watermark mode in word, we must use standard
1497 mode and modify our ones by 70% extra brightness and 70% less
1498 contrast. This means that unmodified default OOo watermark
1499 will turn back into watermark, and modified OOo watermark will
1500 change into a close visual representation in standardmode
1502 nBrightness += 70;
1503 if (nBrightness > 100)
1504 nBrightness = 100;
1505 nContrast -= 70;
1506 if (nContrast < -100)
1507 nContrast = -100;
1508 nMode = GRAPHICDRAWMODE_STANDARD;
1512 if (nMode == GRAPHICDRAWMODE_GREYS)
1513 nMode = 0x40004;
1514 else if (nMode == GRAPHICDRAWMODE_MONO)
1515 nMode = 0x60006;
1516 else
1517 nMode = 0;
1518 rPropOpt.AddOpt( ESCHER_Prop_pictureActive, nMode );
1520 if (nContrast != 0)
1522 nContrast+=100;
1523 if (nContrast == 100)
1524 nContrast = 0x10000;
1525 else if (nContrast < 100)
1527 nContrast *= 0x10000;
1528 nContrast /= 100;
1530 else if (nContrast < 200)
1531 nContrast = (100 * 0x10000) / (200-nContrast);
1532 else
1533 nContrast = 0x7fffffff;
1534 rPropOpt.AddOpt( ESCHER_Prop_pictureContrast, nContrast);
1537 if (nBrightness != 0)
1538 rPropOpt.AddOpt( ESCHER_Prop_pictureBrightness, nBrightness * 327 );
1540 if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CROPGRF,
1541 true, &pItem))
1543 const Size aSz( rNd.GetTwipSize() );
1544 INT32 nVal;
1545 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetLeft() ) )
1546 rPropOpt.AddOpt( ESCHER_Prop_cropFromLeft, ToFract16( nVal, aSz.Width()) );
1547 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetRight() ) )
1548 rPropOpt.AddOpt( ESCHER_Prop_cropFromRight, ToFract16( nVal, aSz.Width()));
1549 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetTop() ) )
1550 rPropOpt.AddOpt( ESCHER_Prop_cropFromTop, ToFract16( nVal, aSz.Height()));
1551 if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetBottom() ) )
1552 rPropOpt.AddOpt( ESCHER_Prop_cropFromBottom, ToFract16( nVal, aSz.Height()));
1556 void SwBasicEscherEx::SetPicId(const SdrObject &, UINT32,
1557 EscherPropertyContainer &)
1561 void SwEscherEx::SetPicId(const SdrObject &rSdrObj, UINT32 nShapeId,
1562 EscherPropertyContainer &rPropOpt)
1564 pTxtBxs->Append(rSdrObj, nShapeId);
1565 UINT32 nPicId = pTxtBxs->Count();
1566 nPicId *= 0x10000;
1567 rPropOpt.AddOpt( ESCHER_Prop_pictureId, nPicId );
1570 INT32 SwBasicEscherEx::WriteOLEFlyFrame(const SwFrmFmt& rFmt, UINT32 nShapeId)
1572 INT32 nBorderThick = 0;
1573 if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
1575 SwNodeIndex aIdx(*rFmt.GetCntnt().GetCntntIdx(), 1);
1576 SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
1577 sal_Int64 nAspect = rOLENd.GetAspect();
1579 uno::Reference < embed::XEmbeddedObject > xObj(rOLENd.GetOLEObj().GetOleRef());
1581 // the rectangle is used to transport the size of the object
1582 // the left, top corner is set to ( 0, 0 ) by default constructor,
1583 // if the width and height are set correctly bRectIsSet should be set to true
1584 awt::Rectangle aRect;
1585 sal_Bool bRectIsSet = sal_False;
1588 // TODO/LATER: should the icon size be stored in case of iconified object?
1589 if ( xObj.is() && nAspect != embed::Aspects::MSOLE_ICON )
1593 awt::Size aSize = xObj->getVisualAreaSize( nAspect );
1594 aRect.Width = aSize.Width;
1595 aRect.Height = aSize.Height;
1596 bRectIsSet = sal_True;
1598 catch( uno::Exception& )
1603 #i5970#
1604 Export floating ole2 .doc ver 8+ wmf ole2 previews as emf previews
1605 instead ==> allows unicode text to be preserved
1607 #ifdef OLE_PREVIEW_AS_EMF
1608 //Graphic aGraphic = wwUtility::MakeSafeGDIMetaFile(xObj);
1609 Graphic* pGraphic = rOLENd.GetGraphic();
1610 #endif
1611 OpenContainer(ESCHER_SpContainer);
1613 EscherPropertyContainer aPropOpt;
1614 const SwMirrorGrf &rMirror = rOLENd.GetSwAttrSet().GetMirrorGrf();
1615 WriteOLEPicture(aPropOpt, AddMirrorFlags(0xa00 | SHAPEFLAG_OLESHAPE,
1616 rMirror), pGraphic ? *pGraphic : Graphic(), *pSdrObj, nShapeId, bRectIsSet ? &aRect : NULL );
1618 nBorderThick = WriteFlyFrameAttr(rFmt, mso_sptPictureFrame, aPropOpt);
1619 WriteGrfAttr(rOLENd, aPropOpt);
1620 aPropOpt.Commit(GetStream());
1622 // store anchor attribute
1623 WriteFrmExtraData( rFmt );
1625 CloseContainer(); // ESCHER_SpContainer
1627 return nBorderThick;
1630 void SwBasicEscherEx::WriteBrushAttr(const SvxBrushItem &rBrush,
1631 EscherPropertyContainer& rPropOpt)
1633 bool bSetOpacity = false;
1634 sal_uInt32 nOpaque = 0;
1635 if (const GraphicObject *pGraphicObject = rBrush.GetGraphicObject())
1637 ByteString aUniqueId = pGraphicObject->GetUniqueID();
1638 if (aUniqueId.Len())
1640 const Graphic &rGraphic = pGraphicObject->GetGraphic();
1641 Size aSize(rGraphic.GetPrefSize());
1642 const MapMode aMap100mm(MAP_100TH_MM);
1643 if (MAP_PIXEL == rGraphic.GetPrefMapMode().GetMapUnit())
1645 aSize = Application::GetDefaultDevice()->PixelToLogic(
1646 aSize, aMap100mm);
1648 else
1650 aSize = OutputDevice::LogicToLogic(aSize,
1651 rGraphic.GetPrefMapMode(), aMap100mm);
1654 Point aEmptyPoint = Point();
1655 Rectangle aRect(aEmptyPoint, aSize);
1657 sal_uInt32 nBlibId = GetBlibID(*QueryPicStream(), aUniqueId,
1658 aRect, NULL, 0);
1659 if (nBlibId)
1660 rPropOpt.AddOpt(ESCHER_Prop_fillBlip,nBlibId,sal_True);
1663 if (0 != (nOpaque = pGraphicObject->GetAttr().GetTransparency()))
1664 bSetOpacity = true;
1666 rPropOpt.AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
1667 rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
1668 rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
1670 else
1672 UINT32 nFillColor = GetColor(rBrush.GetColor(), false);
1673 rPropOpt.AddOpt( ESCHER_Prop_fillColor, nFillColor );
1674 rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, nFillColor ^ 0xffffff );
1675 rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
1677 if (0 != (nOpaque = rBrush.GetColor().GetTransparency()))
1678 bSetOpacity = true;
1681 if (bSetOpacity)
1683 nOpaque = (nOpaque * 100) / 0xFE;
1684 nOpaque = ((100 - nOpaque) << 16) / 100;
1685 rPropOpt.AddOpt(ESCHER_Prop_fillOpacity, nOpaque);
1689 INT32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt,
1690 MSO_SPT eShapeType, EscherPropertyContainer& rPropOpt)
1692 INT32 nLineWidth=0;
1693 const SfxPoolItem* pItem;
1694 bool bFirstLine = true;
1695 if (SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem))
1697 static const UINT16 aExhperProp[4] =
1699 ESCHER_Prop_dyTextTop, ESCHER_Prop_dyTextBottom,
1700 ESCHER_Prop_dxTextLeft, ESCHER_Prop_dxTextRight
1702 const SvxBorderLine* pLine;
1704 for( USHORT n = 0; n < 4; ++n )
1705 if( 0 != ( pLine = ((SvxBoxItem*)pItem)->GetLine( n )) )
1707 if( bFirstLine )
1709 UINT32 nLineColor = GetColor(pLine->GetColor(), false);
1710 rPropOpt.AddOpt( ESCHER_Prop_lineColor, nLineColor );
1711 rPropOpt.AddOpt( ESCHER_Prop_lineBackColor,
1712 nLineColor ^ 0xffffff );
1714 MSO_LineStyle eStyle;
1715 if( pLine->GetInWidth() )
1717 // double line
1718 nLineWidth = pLine->GetInWidth() + pLine->GetOutWidth()
1719 + pLine->GetDistance();
1720 if( pLine->GetInWidth() == pLine->GetOutWidth() )
1721 eStyle = mso_lineDouble;
1722 else if( pLine->GetInWidth() < pLine->GetOutWidth() )
1723 eStyle = mso_lineThickThin;
1724 else
1725 eStyle = mso_lineThinThick;
1727 else
1729 // simple line
1730 eStyle = mso_lineSimple;
1731 nLineWidth = pLine->GetOutWidth();
1734 rPropOpt.AddOpt( ESCHER_Prop_lineStyle, eStyle );
1735 rPropOpt.AddOpt( ESCHER_Prop_lineWidth,
1736 DrawModelToEmu( nLineWidth ));
1737 rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x8000E );
1739 //Use import logic to determine how much of border will go
1740 //outside graphic
1741 nLineWidth = SwMSDffManager::GetEscherLineMatch(
1742 eStyle,eShapeType,nLineWidth);
1743 bFirstLine = false;
1745 rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(
1746 ((SvxBoxItem*)pItem)->GetDistance( n ) ));
1748 else
1749 // MM If there is no line the distance should be set to 0
1750 rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(0));
1752 if( bFirstLine ) // no valid line found
1754 rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
1755 rPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
1756 rPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
1757 rPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
1758 rPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
1761 SvxBrushItem aBrush(rWrt.TrueFrameBgBrush(rFmt));
1762 WriteBrushAttr(aBrush, rPropOpt);
1764 const SdrObject* pObj = rFmt.FindRealSdrObject();
1765 if( pObj && (pObj->GetLayer() == GetHellLayerId() ||
1766 pObj->GetLayer() == GetInvisibleHellId() ))
1768 rPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
1771 return nLineWidth;
1774 INT32 SwEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType,
1775 EscherPropertyContainer& rPropOpt)
1777 INT32 nLineWidth = SwBasicEscherEx::WriteFlyFrameAttr(rFmt, eShapeType,
1778 rPropOpt);
1781 These are not in SwBasicEscherEx::WriteFlyFrameAttr because inline objs
1782 can't do it in word and it hacks it in by stretching the graphic that
1783 way, perhaps we should actually draw in this space into the graphic we
1784 are exporting!
1786 const SfxPoolItem* pItem;
1787 if (SFX_ITEM_SET == rFmt.GetItemState(RES_LR_SPACE, true, &pItem))
1789 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft,
1790 DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetLeft() ) );
1791 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight,
1792 DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetRight() ) );
1794 else
1796 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
1797 rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
1800 if (SFX_ITEM_SET == rFmt.GetItemState(RES_UL_SPACE, true, &pItem))
1802 rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistTop,
1803 DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetUpper() ) );
1804 rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistBottom,
1805 DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetLower() ) );
1808 if (rFmt.GetSurround().IsContour())
1810 if (const SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt))
1812 const PolyPolygon *pPolyPoly = pNd->HasContour();
1813 if (pPolyPoly && pPolyPoly->Count())
1815 Polygon aPoly(PolygonFromPolyPolygon(*pPolyPoly));
1816 const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
1817 Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
1818 Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
1819 aPoly.Scale(aMapPolyX, aMapPolyY);
1822 a) stretch right bound by 15twips
1823 b) shrink bottom bound to where it would have been in word
1824 c) Move it to the left by 15twips
1826 See the import for details
1828 const Size &rSize = pNd->GetTwipSize();
1829 Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
1830 aMoveHack *= Fraction(15, 1);
1831 long nMove(aMoveHack);
1833 Fraction aHackX(ww::nWrap100Percent + nMove,
1834 ww::nWrap100Percent);
1835 Fraction aHackY(ww::nWrap100Percent - nMove,
1836 ww::nWrap100Percent);
1837 aPoly.Scale(aHackX, aHackY);
1839 aPoly.Move(-nMove, 0);
1841 SvMemoryStream aPolyDump;
1842 aPolyDump.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1844 sal_uInt16 nLen = aPoly.GetSize();
1845 aPolyDump << nLen;
1846 aPolyDump << nLen;
1847 aPolyDump << sal_uInt16(8);
1848 for (sal_uInt16 nI = 0; nI < nLen; ++nI)
1850 aPolyDump << sal_uInt32(aPoly[nI].X());
1851 aPolyDump << sal_uInt32(aPoly[nI].Y());
1854 sal_uInt16 nArrLen = msword_cast<sal_uInt16>(aPolyDump.Tell());
1855 void *pArr = const_cast<void *>(aPolyDump.GetData());
1856 //PropOpt wants to own the buffer
1857 aPolyDump.ObjectOwnsMemory(false);
1858 rPropOpt.AddOpt(DFF_Prop_pWrapPolygonVertices, false,
1859 nArrLen, static_cast<BYTE *>(pArr), nArrLen);
1864 return nLineWidth;
1867 void SwBasicEscherEx::Init()
1869 MapUnit eMap = MAP_TWIP;
1870 if (SdrModel *pModel = rWrt.pDoc->GetDrawModel())
1872 // PPT arbeitet nur mit Einheiten zu 576DPI
1873 // WW hingegen verwendet twips, dh. 1440DPI.
1874 eMap = pModel->GetScaleUnit();
1877 // MS-DFF-Properties sind grossteils in EMU (English Metric Units) angegeben
1878 // 1mm=36000emu, 1twip=635emu
1879 Fraction aFact(360, 1);
1880 aFact /= GetMapFactor(MAP_100TH_MM, eMap).X();
1881 // create little values
1882 aFact = Fraction(aFact.GetNumerator(), aFact.GetDenominator());
1883 mnEmuMul = aFact.GetNumerator();
1884 mnEmuDiv = aFact.GetDenominator();
1886 SetHellLayerId(rWrt.pDoc->GetHellId());
1889 INT32 SwBasicEscherEx::ToFract16(INT32 nVal, UINT32 nMax) const
1891 if (nMax)
1893 INT32 nMSVal = (nVal / 65536) * nMax;
1894 nMSVal += (nVal * 65536 ) / nMax;
1895 return nMSVal;
1897 return 0;
1900 SvStream* SwBasicEscherEx::QueryPicStream()
1902 if (!pPictStrm)
1904 pPictStrm = new SvMemoryStream;
1905 pPictStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
1907 return pPictStrm;
1910 SdrLayerID SwBasicEscherEx::GetInvisibleHellId() const
1912 return rWrt.pDoc->GetInvisibleHellId();
1915 void SwBasicEscherEx::WritePictures()
1917 ASSERT(pPictStrm, "no picture!");
1918 if (pPictStrm)
1920 // set the blip - entries to the correct stream pos
1921 INT32 nEndPos = pPictStrm->Tell();
1922 WriteBlibStoreEntry(*pEscherStrm, 1, sal_True, nEndPos);
1924 pPictStrm->Seek(0);
1925 *pEscherStrm << *pPictStrm;
1927 delete pPictStrm, pPictStrm = 0;
1931 SwEscherEx::SwEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
1932 : SwBasicEscherEx(pStrm, rWW8Wrt, rWW8Wrt.pHFSdrObjs->size() ? 2 : 1),
1933 pTxtBxs(0)
1935 aHostData.SetClientData(&aWinwordAnchoring);
1936 OpenContainer( ESCHER_DggContainer );
1938 sal_uInt16 nColorCount = 4;
1939 *pStrm << (sal_uInt16)( nColorCount << 4 ) // instance
1940 << (sal_uInt16)ESCHER_SplitMenuColors // record type
1941 << (sal_uInt32)( nColorCount * 4 ) // size
1942 << (sal_uInt32)0x08000004
1943 << (sal_uInt32)0x08000001
1944 << (sal_uInt32)0x08000002
1945 << (sal_uInt32)0x100000f7;
1947 CloseContainer(); // ESCHER_DggContainer
1949 BYTE i = 2; // for header/footer and the other
1950 PlcDrawObj *pSdrObjs = rWrt.pHFSdrObjs;
1951 pTxtBxs = rWrt.pHFTxtBxs;
1953 // if no header/footer -> skip over
1954 if (!pSdrObjs->size())
1956 --i;
1957 pSdrObjs = rWrt.pSdrObjs;
1958 pTxtBxs = rWrt.pTxtBxs;
1961 for( ; i--; pSdrObjs = rWrt.pSdrObjs, pTxtBxs = rWrt.pTxtBxs )
1963 // "dummy char" (or any Count ?) - why? This knows only M$
1964 GetStream() << (sal_Char)i;
1966 OpenContainer( ESCHER_DgContainer );
1968 EnterGroup( 0 );
1970 ULONG nSecondShapeId = pSdrObjs == rWrt.pSdrObjs ? GetShapeID() : 0;
1972 // write now all Writer-/DrawObjects
1973 DrawObjPointerVector aSorted;
1974 MakeZOrderArrAndFollowIds(pSdrObjs->GetObjArr(), aSorted);
1976 sal_uInt32 nShapeId=0;
1977 DrawObjPointerIter aEnd = aSorted.end();
1978 for (DrawObjPointerIter aIter = aSorted.begin(); aIter != aEnd; ++aIter)
1980 INT32 nBorderThick=0;
1981 DrawObj *pObj = (*aIter);
1982 ASSERT(pObj, "impossible");
1983 if (!pObj)
1984 continue;
1985 const sw::Frame &rFrame = pObj->maCntnt;
1986 const SwFrmFmt& rFmt = rFrame.GetFrmFmt();
1988 switch (rFrame.GetWriterType())
1990 case sw::Frame::eTxtBox:
1991 case sw::Frame::eOle:
1992 case sw::Frame::eGraphic:
1993 nBorderThick = WriteFlyFrm(*pObj, nShapeId, aSorted);
1994 break;
1995 case sw::Frame::eFormControl:
1996 WriteOCXControl(rFmt, nShapeId=GetShapeID());
1997 break;
1998 case sw::Frame::eDrawing:
1999 aWinwordAnchoring.SetAnchoring(rFmt);
2000 const SdrObject* pSdrObj = rFmt.FindRealSdrObject();
2001 if (pSdrObj)
2003 bool bSwapInPage = false;
2004 if (!pSdrObj->GetPage())
2006 if (SdrModel* pModel = rWrt.pDoc->GetDrawModel())
2008 if (SdrPage *pPage = pModel->GetPage(0))
2010 bSwapInPage = true;
2011 (const_cast<SdrObject*>(pSdrObj))->SetPage(pPage);
2016 nShapeId = AddSdrObject(*pSdrObj);
2018 if (bSwapInPage)
2019 (const_cast<SdrObject*>(pSdrObj))->SetPage(0);
2021 #ifndef PRODUCT
2022 else
2023 ASSERT( !this, "Where is the SDR-Object?" );
2024 #endif
2027 if( !nShapeId )
2029 nShapeId = AddDummyShape();
2032 pObj->SetShapeDetails(nShapeId, nBorderThick);
2035 EndSdrObjectPage(); // ???? Bugfix for 74724
2037 if( nSecondShapeId )
2039 OpenContainer( ESCHER_SpContainer );
2041 AddShape( ESCHER_ShpInst_Rectangle, 0xe00, nSecondShapeId );
2043 EscherPropertyContainer aPropOpt;
2044 const SwFrmFmt &rFmt = const_cast<const SwDoc *>(rWrt.pDoc)->GetPageDesc(0).GetMaster();
2045 const SfxPoolItem* pItem = 0;
2046 SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true,
2047 &pItem);
2048 if (SFX_ITEM_SET == eState && pItem)
2050 const SvxBrushItem* pBrush = (const SvxBrushItem*)pItem;
2051 WriteBrushAttr(*pBrush, aPropOpt);
2053 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x8000001 );
2054 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
2055 aPropOpt.AddOpt( ESCHER_Prop_shadowColor, 0x8000002 );
2056 aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
2058 // winword defaults!
2059 // aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
2060 // aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
2061 // aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
2062 // aPropOpt.AddOpt( ESCHER_Prop_bWMode, 0x9 );
2063 // aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
2065 aPropOpt.Commit( *pStrm );
2067 AddAtom( 4, ESCHER_ClientData );
2068 GetStream() << 1L;
2070 CloseContainer(); // ESCHER_SpContainer
2072 CloseContainer(); // ESCHER_DgContainer
2076 SwEscherEx::~SwEscherEx()
2080 void SwEscherEx::FinishEscher()
2082 pEscherStrm->Seek(0);
2083 *rWrt.pTableStrm << *pEscherStrm;
2084 delete pEscherStrm, pEscherStrm = 0;
2087 /** method to perform conversion of positioning attributes with the help
2088 of corresponding layout information
2090 OD 2005-01-06 #i30669#
2091 Because most of the Writer object positions doesn't correspond to the
2092 object positions in WW8, this method converts the positioning
2093 attributes. For this conversion the corresponding layout information
2094 is needed. If no layout information exists - e.g. no layout exists - no
2095 conversion is performed.
2096 No conversion is performed for as-character anchored objects. Whose
2097 object positions are already treated special in method <WriteData(..)>.
2099 @author OD
2101 @param _iorHoriOri
2102 input/output parameter - containing the current horizontal position
2103 attributes, which are converted by this method.
2105 @param _iorVertOri
2106 input/output parameter - containing the current vertical position
2107 attributes, which are converted by this method.
2109 @param _rFrmFmt
2110 input parameter - frame format of the anchored object
2112 @return boolean, indicating, if a conversion has been performed.
2114 bool WinwordAnchoring::ConvertPosition( SwFmtHoriOrient& _iorHoriOri,
2115 SwFmtVertOrient& _iorVertOri,
2116 const SwFrmFmt& _rFrmFmt )
2118 const RndStdIds eAnchor = _rFrmFmt.GetAnchor().GetAnchorId();
2120 if ( FLY_IN_CNTNT == eAnchor || FLY_AT_FLY == eAnchor )
2122 // no conversion for as-character or at frame anchored objects
2123 return false;
2126 // determine anchored object
2127 SwAnchoredObject* pAnchoredObj( 0L );
2129 const SwContact* pContact = _rFrmFmt.FindContactObj();
2130 if ( pContact )
2132 std::vector<SwAnchoredObject*> aAnchoredObjs;
2133 pContact->GetAnchoredObjs( aAnchoredObjs );
2134 if ( !aAnchoredObjs.empty() )
2136 pAnchoredObj = aAnchoredObjs.front();
2140 if ( !pAnchoredObj )
2142 // no anchored object found. Thus, the needed layout information can't
2143 // be determined. --> no conversion
2144 return false;
2146 // --> OD 2006-09-26 #141404#
2147 // no conversion for anchored drawing object, which aren't attached to an
2148 // anchor frame.
2149 // This is the case for drawing objects, which are anchored inside a page
2150 // header/footer of an *unused* page style.
2151 if ( dynamic_cast<SwAnchoredDrawObject*>(pAnchoredObj) &&
2152 !pAnchoredObj->GetAnchorFrm() )
2154 return false;
2156 // <--
2158 bool bConverted( false );
2160 // determine value of attribute 'Follow text flow', because positions aligned
2161 // at page areas have to be converted, if it's set.
2162 const bool bFollowTextFlow = _rFrmFmt.GetFollowTextFlow().GetValue();
2164 // --> OD 2007-07-24 #148096#
2165 // check, if horizontal and vertical position have to be converted due to
2166 // the fact, that the object is anchored at a paragraph, which has a "column
2167 // break before" attribute
2168 bool bConvDueToAnchoredAtColBreakPara( false );
2169 if ( ( eAnchor == FLY_AT_CNTNT || eAnchor == FLY_AUTO_CNTNT ) &&
2170 _rFrmFmt.GetAnchor().GetCntntAnchor() &&
2171 _rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode().IsTxtNode() )
2173 SwTxtNode& rAnchorTxtNode =
2174 dynamic_cast<SwTxtNode&>(_rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode());
2175 const SvxFmtBreakItem* pBreak = &(ItemGet<SvxFmtBreakItem>(rAnchorTxtNode, RES_BREAK));
2176 if ( pBreak &&
2177 pBreak->GetBreak() == SVX_BREAK_COLUMN_BEFORE )
2179 bConvDueToAnchoredAtColBreakPara = true;
2182 // <--
2184 // convert horizontal position, if needed
2186 enum HoriConv { NO_CONV, CONV2PG, CONV2COL, CONV2CHAR };
2187 HoriConv eHoriConv( NO_CONV );
2189 // determine, if conversion has to be performed due to the position orientation
2190 bool bConvDueToOrientation( false );
2192 const sal_Int16 eHOri = _iorHoriOri.GetHoriOrient();
2193 bConvDueToOrientation = eHOri == text::HoriOrientation::LEFT || eHOri == text::HoriOrientation::RIGHT ||
2194 eHOri == text::HoriOrientation::INSIDE || eHOri == text::HoriOrientation::OUTSIDE ||
2195 ( eHOri != text::HoriOrientation::CENTER && _iorHoriOri.IsPosToggle() );
2198 // determine conversion type due to the position relation
2199 // --> OD 2007-07-24 #148096#
2200 if ( bConvDueToAnchoredAtColBreakPara )
2202 eHoriConv = CONV2PG;
2204 else
2206 switch ( _iorHoriOri.GetRelationOrient() )
2208 case text::RelOrientation::PAGE_FRAME:
2209 case text::RelOrientation::PAGE_PRINT_AREA:
2211 if ( bConvDueToOrientation || bFollowTextFlow )
2212 eHoriConv = CONV2PG;
2214 break;
2215 case text::RelOrientation::PAGE_LEFT:
2216 case text::RelOrientation::PAGE_RIGHT:
2218 // relation not supported by WW8. Thus, conversion always needed.
2219 eHoriConv = CONV2PG;
2221 break;
2222 case text::RelOrientation::FRAME:
2224 if ( bConvDueToOrientation )
2225 eHoriConv = CONV2COL;
2227 break;
2228 case text::RelOrientation::PRINT_AREA:
2229 case text::RelOrientation::FRAME_LEFT:
2230 case text::RelOrientation::FRAME_RIGHT:
2232 // relation not supported by WW8. Thus, conversion always needed.
2233 eHoriConv = CONV2COL;
2235 break;
2236 case text::RelOrientation::CHAR:
2238 if ( bConvDueToOrientation )
2239 eHoriConv = CONV2CHAR;
2241 break;
2242 default:
2243 ASSERT( false,
2244 "<WinwordAnchoring::ConvertPosition(..)> - unknown horizontal relation" );
2247 // <--
2248 if ( eHoriConv != NO_CONV )
2250 _iorHoriOri.SetHoriOrient( text::HoriOrientation::NONE );
2251 SwTwips nPosX( 0L );
2253 Point aPos;
2254 if ( eHoriConv == CONV2PG )
2256 _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
2257 // --> OD 2005-01-27 #i33818#
2258 bool bRelToTableCell( false );
2259 aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
2260 bRelToTableCell );
2261 if ( bRelToTableCell )
2263 _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
2265 // <--
2267 else if ( eHoriConv == CONV2COL )
2269 _iorHoriOri.SetRelationOrient( text::RelOrientation::FRAME );
2270 aPos = pAnchoredObj->GetRelPosToAnchorFrm();
2272 else if ( eHoriConv == CONV2CHAR )
2274 _iorHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
2275 aPos = pAnchoredObj->GetRelPosToChar();
2277 // No distinction between layout directions, because of missing
2278 // information about WW8 in vertical layout.
2279 nPosX = aPos.X();
2281 _iorHoriOri.SetPos( nPosX );
2282 bConverted = true;
2286 // convert vertical position, if needed
2288 enum VertConv { NO_CONV, CONV2PG, CONV2PARA, CONV2LINE };
2289 VertConv eVertConv( NO_CONV );
2291 // determine, if conversion has to be performed due to the position orientation
2292 bool bConvDueToOrientation( false );
2294 const sal_Int16 eVOri = _iorVertOri.GetVertOrient();
2295 bConvDueToOrientation = ( eVOri == text::VertOrientation::TOP ||
2296 eVOri == text::VertOrientation::BOTTOM ||
2297 eVOri == text::VertOrientation::CHAR_TOP ||
2298 eVOri == text::VertOrientation::CHAR_BOTTOM ||
2299 eVOri == text::VertOrientation::CHAR_CENTER ||
2300 eVOri == text::VertOrientation::LINE_TOP ||
2301 eVOri == text::VertOrientation::LINE_BOTTOM ||
2302 eVOri == text::VertOrientation::LINE_CENTER );
2305 // determine conversion type due to the position relation
2306 // --> OD 2007-07-24 #148096#
2307 if ( bConvDueToAnchoredAtColBreakPara )
2309 eVertConv = CONV2PG;
2311 else
2313 switch ( _iorVertOri.GetRelationOrient() )
2315 case text::RelOrientation::PAGE_FRAME:
2316 case text::RelOrientation::PAGE_PRINT_AREA:
2318 if ( bConvDueToOrientation || bFollowTextFlow )
2319 eVertConv = CONV2PG;
2321 break;
2322 case text::RelOrientation::FRAME:
2324 if ( bConvDueToOrientation ||
2325 _iorVertOri.GetVertOrient() == text::VertOrientation::CENTER )
2327 eVertConv = CONV2PARA;
2330 break;
2331 case text::RelOrientation::PRINT_AREA:
2333 // relation not supported by WW8. Thus, conversion always needed.
2334 eVertConv = CONV2PARA;
2336 break;
2337 case text::RelOrientation::CHAR:
2339 // relation not supported by WW8. Thus, conversion always needed.
2340 eVertConv = CONV2PARA;
2342 break;
2343 case text::RelOrientation::TEXT_LINE:
2345 if ( bConvDueToOrientation ||
2346 _iorVertOri.GetVertOrient() == text::VertOrientation::NONE )
2348 eVertConv = CONV2LINE;
2351 break;
2352 case text::RelOrientation::PAGE_LEFT:
2353 case text::RelOrientation::PAGE_RIGHT:
2354 case text::RelOrientation::FRAME_LEFT:
2355 case text::RelOrientation::FRAME_RIGHT:
2356 default:
2357 ASSERT( false,
2358 "<WinwordAnchoring::ConvertPosition(..)> - unknown vertical relation" );
2361 // <--
2362 if ( eVertConv != NO_CONV )
2364 _iorVertOri.SetVertOrient( text::VertOrientation::NONE );
2365 SwTwips nPosY( 0L );
2367 Point aPos;
2368 if ( eVertConv == CONV2PG )
2370 _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
2371 // --> OD 2005-01-27 #i33818#
2372 bool bRelToTableCell( false );
2373 aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
2374 bRelToTableCell );
2375 if ( bRelToTableCell )
2377 _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
2379 // <--
2381 else if ( eVertConv == CONV2PARA )
2383 _iorVertOri.SetRelationOrient( text::RelOrientation::FRAME );
2384 aPos = pAnchoredObj->GetRelPosToAnchorFrm();
2386 else if ( eVertConv == CONV2LINE )
2388 _iorVertOri.SetRelationOrient( text::RelOrientation::TEXT_LINE );
2389 aPos = pAnchoredObj->GetRelPosToLine();
2391 // No distinction between layout directions, because of missing
2392 // information about WW8 in vertical layout.
2393 nPosY = aPos.Y();
2395 _iorVertOri.SetPos( nPosY );
2396 bConverted = true;
2400 return bConverted;
2403 void WinwordAnchoring::SetAnchoring(const SwFrmFmt& rFmt)
2405 const RndStdIds eAnchor = rFmt.GetAnchor().GetAnchorId();
2406 mbInline = (eAnchor == FLY_IN_CNTNT);
2408 SwFmtHoriOrient rHoriOri = rFmt.GetHoriOrient();
2409 SwFmtVertOrient rVertOri = rFmt.GetVertOrient();
2411 // --> OD 2005-01-06 #i30669# - convert the positioning attributes.
2412 // Most positions are converted, if layout information exists.
2413 const bool bPosConverted = ConvertPosition( rHoriOri, rVertOri, rFmt );
2414 // <--
2416 const sal_Int16 eHOri = rHoriOri.GetHoriOrient();
2417 // CMC, OD 24.11.2003 #i22673#
2418 const sal_Int16 eVOri = rVertOri.GetVertOrient();
2420 const sal_Int16 eHRel = rHoriOri.GetRelationOrient();
2421 const sal_Int16 eVRel = rVertOri.GetRelationOrient();
2423 // horizontal Adjustment
2424 switch (eHOri)
2426 default:
2427 case text::HoriOrientation::NONE:
2428 mnXAlign = 0;
2429 break;
2430 case text::HoriOrientation::LEFT:
2431 mnXAlign = 1;
2432 break;
2433 case text::HoriOrientation::CENTER:
2434 mnXAlign = 2;
2435 break;
2436 case text::HoriOrientation::RIGHT:
2437 mnXAlign = 3;
2438 break;
2439 case text::HoriOrientation::INSIDE:
2440 mnXAlign = 4;
2441 break;
2442 case text::HoriOrientation::OUTSIDE:
2443 mnXAlign = 5;
2444 break;
2447 // vertical Adjustment
2448 // CMC, OD 24.11.2003 #i22673#
2449 // When adjustment is vertically relative to line or to char
2450 // bottom becomes top and vice versa
2451 const bool bVertSwap = !bPosConverted &&
2452 ( (eVRel == text::RelOrientation::CHAR) ||
2453 (eVRel == text::RelOrientation::TEXT_LINE) );
2454 switch (eVOri)
2456 default:
2457 case text::VertOrientation::NONE:
2458 mnYAlign = 0;
2459 break;
2460 case text::VertOrientation::TOP:
2461 case text::VertOrientation::LINE_TOP:
2462 case text::VertOrientation::CHAR_TOP:
2463 mnYAlign = bVertSwap ? 3 : 1;
2464 break;
2465 case text::VertOrientation::CENTER:
2466 case text::VertOrientation::LINE_CENTER:
2467 mnYAlign = 2;
2468 break;
2469 case text::VertOrientation::BOTTOM:
2470 case text::VertOrientation::LINE_BOTTOM:
2471 case text::VertOrientation::CHAR_BOTTOM:
2472 mnYAlign = bVertSwap ? 1 : 3;
2473 break;
2476 // Adjustment is horizontally relative to...
2477 switch (eHRel)
2479 case text::RelOrientation::PAGE_PRINT_AREA:
2480 mnXRelTo = 0;
2481 break;
2482 case text::RelOrientation::PAGE_FRAME:
2483 case text::RelOrientation::PAGE_LEFT: //:-(
2484 case text::RelOrientation::PAGE_RIGHT: //:-(
2485 mnXRelTo = 1;
2486 break;
2487 case text::RelOrientation::FRAME:
2488 case text::RelOrientation::FRAME_LEFT: //:-(
2489 case text::RelOrientation::FRAME_RIGHT: //:-(
2490 if (eAnchor == FLY_PAGE)
2491 mnXRelTo = 1;
2492 else
2493 mnXRelTo = 2;
2494 break;
2495 case text::RelOrientation::PRINT_AREA:
2496 if (eAnchor == FLY_PAGE)
2497 mnXRelTo = 0;
2498 else
2499 mnXRelTo = 2;
2500 break;
2501 case text::RelOrientation::CHAR:
2502 mnXRelTo = 3;
2503 break;
2504 case text::RelOrientation::TEXT_LINE:
2505 break;
2508 // Adjustment is vertically relative to...
2509 switch (eVRel)
2511 case text::RelOrientation::PAGE_PRINT_AREA:
2512 mnYRelTo = 0;
2513 break;
2514 case text::RelOrientation::PAGE_FRAME:
2515 mnYRelTo = 1;
2516 break;
2517 case text::RelOrientation::PRINT_AREA:
2518 if (eAnchor == FLY_PAGE)
2519 mnYRelTo = 0;
2520 else
2521 mnYRelTo = 2;
2522 break;
2523 case text::RelOrientation::FRAME:
2524 if (eAnchor == FLY_PAGE)
2525 mnYRelTo = 1;
2526 else
2527 mnYRelTo = 2;
2528 break;
2529 case text::RelOrientation::CHAR:
2530 case text::RelOrientation::TEXT_LINE: // CMC, OD 24.11.2003 #i22673# - vertical alignment at top of line
2531 case text::RelOrientation::PAGE_LEFT: //nonsense
2532 case text::RelOrientation::PAGE_RIGHT: //nonsense
2533 case text::RelOrientation::FRAME_LEFT: //nonsense
2534 case text::RelOrientation::FRAME_RIGHT: //nonsense
2535 mnYRelTo = 3;
2536 break;
2540 void SwEscherEx::WriteFrmExtraData( const SwFrmFmt& rFmt )
2542 aWinwordAnchoring.SetAnchoring(rFmt);
2543 aWinwordAnchoring.WriteData(*this);
2545 AddAtom(4, ESCHER_ClientAnchor);
2546 GetStream() << 0L;
2548 AddAtom(4, ESCHER_ClientData);
2549 GetStream() << 1L;
2552 INT32 SwEscherEx::WriteFlyFrm(const DrawObj &rObj, UINT32 &rShapeId,
2553 DrawObjPointerVector &rPVec)
2555 const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
2557 // check for textflyframe and if it is the first in a Chain
2558 INT32 nBorderThick = 0;
2559 const SwNodeIndex* pNdIdx = rFmt.GetCntnt().GetCntntIdx();
2560 if( pNdIdx )
2562 SwNodeIndex aIdx( *pNdIdx, 1 );
2563 switch( aIdx.GetNode().GetNodeType() )
2565 case ND_GRFNODE:
2566 nBorderThick = WriteGrfFlyFrame( rFmt, rShapeId = GetShapeID() );
2567 break;
2568 case ND_OLENODE:
2569 nBorderThick = WriteOLEFlyFrame( rFmt, rShapeId = GetShapeID() );
2570 break;
2571 default:
2572 if (const SdrObject* pObj = rFmt.FindRealSdrObject())
2574 // check for the first in a Chain
2575 UINT32 nTxtId;
2576 USHORT nOff = 0;
2577 const SwFrmFmt* pFmt = &rFmt, *pPrev;
2578 while( 0 != ( pPrev = pFmt->GetChain().GetPrev() ))
2580 ++nOff;
2581 pFmt = pPrev;
2584 rShapeId = GetFlyShapeId(rFmt, rObj.mnHdFtIndex, rPVec);
2585 if( !nOff )
2587 void* p = (void*)pObj;
2588 nTxtId = pTxtBxs->GetPos( p );
2589 if( USHRT_MAX == nTxtId )
2591 pTxtBxs->Append( *pObj, rShapeId );
2592 nTxtId = pTxtBxs->Count();
2594 else
2595 ++nTxtId;
2597 else
2599 const SdrObject* pPrevObj = pFmt->FindRealSdrObject();
2600 void* p = (void*)pPrevObj;
2601 nTxtId = pTxtBxs->GetPos( p );
2602 if( USHRT_MAX == nTxtId )
2604 UINT32 nPrevShapeId =
2605 GetFlyShapeId(*pFmt, rObj.mnHdFtIndex, rPVec);
2606 pTxtBxs->Append( *pPrevObj, nPrevShapeId );
2607 nTxtId = pTxtBxs->Count();
2609 else
2610 ++nTxtId;
2612 nTxtId *= 0x10000;
2613 nTxtId += nOff;
2615 nBorderThick = WriteTxtFlyFrame(rObj, rShapeId, nTxtId, rPVec);
2619 return nBorderThick;
2622 USHORT FindPos(const SwFrmFmt &rFmt, unsigned int nHdFtIndex,
2623 DrawObjPointerVector &rPVec)
2625 DrawObjPointerIter aEnd = rPVec.end();
2626 for (DrawObjPointerIter aIter = rPVec.begin(); aIter != aEnd; ++aIter)
2628 const DrawObj *pObj = (*aIter);
2629 ASSERT(pObj, "Impossible");
2630 if (!pObj)
2631 continue;
2632 if (
2633 nHdFtIndex == pObj->mnHdFtIndex &&
2634 &rFmt == (&pObj->maCntnt.GetFrmFmt())
2637 return static_cast< USHORT >(aIter - rPVec.begin());
2640 return USHRT_MAX;
2643 INT32 SwEscherEx::WriteTxtFlyFrame(const DrawObj &rObj, UINT32 nShapeId,
2644 UINT32 nTxtBox, DrawObjPointerVector &rPVec)
2646 const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
2647 short nDirection = rObj.mnDirection;
2649 INT32 nBorderThick=0;
2650 OpenContainer( ESCHER_SpContainer );
2652 AddShape( ESCHER_ShpInst_TextBox, 0xa00, nShapeId );
2653 EscherPropertyContainer aPropOpt;
2654 aPropOpt.AddOpt(ESCHER_Prop_lTxid, nTxtBox);
2655 if (const SwFrmFmt *pNext = rFmt.GetChain().GetNext())
2657 USHORT nPos = FindPos(*pNext, rObj.mnHdFtIndex, rPVec);
2658 if (USHRT_MAX != nPos && aFollowShpIds[nPos])
2659 aPropOpt.AddOpt(ESCHER_Prop_hspNext, aFollowShpIds[nPos]);
2661 nBorderThick = WriteFlyFrameAttr( rFmt, mso_sptTextBox, aPropOpt );
2663 MSO_TextFlow nFlow;
2665 switch (nDirection)
2667 default:
2668 ASSERT(!this, "unknown direction type");
2669 case FRMDIR_HORI_LEFT_TOP:
2670 nFlow=mso_txflHorzN;
2671 break;
2672 case FRMDIR_HORI_RIGHT_TOP:
2673 nFlow=mso_txflHorzN;
2674 break;
2675 case FRMDIR_VERT_TOP_LEFT: //not really possible in word
2676 case FRMDIR_VERT_TOP_RIGHT:
2677 nFlow=mso_txflTtoBA;
2678 break;
2680 aPropOpt.AddOpt( ESCHER_Prop_txflTextFlow, nFlow );
2682 aPropOpt.Commit( GetStream() );
2684 // store anchor attribute
2685 WriteFrmExtraData( rFmt );
2687 AddAtom( 4, ESCHER_ClientTextbox ); GetStream() << nTxtBox;
2689 CloseContainer(); // ESCHER_SpContainer
2690 return nBorderThick;
2693 void SwBasicEscherEx::WriteOLEPicture(EscherPropertyContainer &rPropOpt,
2694 sal_uInt32 nShapeFlags, const Graphic &rGraphic, const SdrObject &rObj,
2695 sal_uInt32 nShapeId, const awt::Rectangle* pVisArea )
2697 //nShapeFlags == 0xA00 + flips and ole active
2698 AddShape(ESCHER_ShpInst_PictureFrame, nShapeFlags, nShapeId);
2700 GraphicObject aGraphicObject(rGraphic);
2701 ByteString aId = aGraphicObject.GetUniqueID();
2702 if (aId.Len())
2704 Rectangle aRect = rObj.GetLogicRect();
2705 aRect.SetPos(Point(0,0));
2706 aRect.Right() = DrawModelToEmu(aRect.Right());
2707 aRect.Bottom() = DrawModelToEmu(aRect.Bottom());
2708 sal_uInt32 nBlibId = GetBlibID(*QueryPicStream(), aId, aRect, pVisArea, 0); // SJ: the fourth parameter (VisArea) should be set..
2709 if (nBlibId)
2710 rPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
2713 SetPicId(rObj, nShapeId, rPropOpt);
2714 rPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0x10000 );
2717 void SwEscherEx::WriteOCXControl( const SwFrmFmt& rFmt, UINT32 nShapeId )
2719 if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
2721 OpenContainer( ESCHER_SpContainer );
2723 SdrModel *pModel = rWrt.pDoc->GetDrawModel();
2724 OutputDevice *pDevice = Application::GetDefaultDevice();
2725 ASSERT(pModel && pDevice, "no model or device");
2727 // #i71538# use complete SdrViews
2728 // SdrExchangeView aExchange(pModel, pDevice);
2729 SdrView aExchange(pModel, pDevice);
2731 Graphic aGraphic(aExchange.GetObjGraphic(pModel, pSdrObj));
2733 EscherPropertyContainer aPropOpt;
2734 WriteOLEPicture(aPropOpt, 0xa00 | SHAPEFLAG_OLESHAPE, aGraphic,
2735 *pSdrObj, nShapeId, NULL );
2737 WriteFlyFrameAttr( rFmt, mso_sptPictureFrame , aPropOpt );
2738 aPropOpt.Commit( GetStream() );
2740 // store anchor attribute
2741 WriteFrmExtraData( rFmt );
2743 CloseContainer(); // ESCHER_SpContainer
2747 void SwEscherEx::MakeZOrderArrAndFollowIds(
2748 std::vector<DrawObj>& rSrcArr, std::vector<DrawObj*>&rDstArr)
2750 USHORT n, nCnt = static_cast< USHORT >(rSrcArr.size());
2751 SvULongsSort aSort( 255 < nCnt ? 255 : nCnt, 255 );
2752 rDstArr.clear();
2753 rDstArr.reserve(nCnt);
2754 for (n = 0; n < nCnt; ++n)
2756 const SwFrmFmt &rFmt = rSrcArr[n].maCntnt.GetFrmFmt();
2757 ULONG nOrdNum = rWrt.GetSdrOrdNum(rFmt);
2758 USHORT nPos;
2759 //returns what will be the index in rDstArr of p as nPos
2760 aSort.Insert(nOrdNum, nPos);
2761 DrawObj &rObj = rSrcArr[n];
2762 rDstArr.insert(rDstArr.begin() + nPos, &rObj);
2765 if (aFollowShpIds.Count())
2766 aFollowShpIds.Remove(0, aFollowShpIds.Count());
2768 for (n = 0; n < nCnt; ++n)
2770 const SwFrmFmt &rFmt = rDstArr[n]->maCntnt.GetFrmFmt();
2771 bool bNeedsShapeId = false;
2773 if (RES_FLYFRMFMT == rFmt.Which())
2775 const SwFmtChain &rChain = rFmt.GetChain();
2776 if (rChain.GetPrev() || rChain.GetNext())
2777 bNeedsShapeId = true;
2780 ULONG nShapeId = bNeedsShapeId ? GetShapeID() : 0;
2782 aFollowShpIds.Insert(nShapeId, n);
2786 UINT32 SwEscherEx::GetFlyShapeId(const SwFrmFmt& rFmt,
2787 unsigned int nHdFtIndex, DrawObjPointerVector &rpVec)
2789 USHORT nPos = FindPos(rFmt, nHdFtIndex, rpVec);
2790 UINT32 nShapeId;
2791 if (USHRT_MAX != nPos)
2793 if (0 == (nShapeId = aFollowShpIds[nPos]))
2795 nShapeId = GetShapeID();
2796 aFollowShpIds[ nPos ] = nShapeId;
2799 else
2800 nShapeId = GetShapeID();
2801 return nShapeId;
2804 UINT32 SwEscherEx::QueryTextID(
2805 const uno::Reference< drawing::XShape>& xXShapeRef, UINT32 nShapeId )
2807 UINT32 nId = 0;
2808 if (SdrObject* pObj = GetSdrObjectFromXShape(xXShapeRef))
2810 pTxtBxs->Append( *pObj, nShapeId );
2811 nId = pTxtBxs->Count();
2812 nId *= 0x10000;
2814 return nId;
2817 bool SwMSConvertControls::ExportControl(WW8Export &rWW8Wrt, const SdrObject *pObj)
2819 if (!rWW8Wrt.bWrtWW8)
2820 return false;
2822 SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObj);
2823 uno::Reference< awt::XControlModel > xControlModel =
2824 pFormObj->GetUnoControlModel();
2826 //Why oh lord do we use so many different units ?
2827 //I think I painted myself into a little bit of a
2828 //corner by trying to use the uno interface for
2829 //controls export
2830 Rectangle aRect = pFormObj->GetLogicRect();
2831 aRect.SetPos(Point(0,0));
2832 awt::Size aSize;
2833 aSize.Width = TWIPS_TO_MM(aRect.Right());
2834 aSize.Height = TWIPS_TO_MM(aRect.Bottom());
2836 //Open the ObjectPool
2837 SvStorageRef xObjPool = rWW8Wrt.GetWriter().GetStorage().OpenSotStorage(
2838 CREATE_CONST_ASC(SL::aObjectPool), STREAM_READWRITE |
2839 STREAM_SHARE_DENYALL);
2841 //Create a destination storage for the microsoft control
2842 String sStorageName('_');
2843 sStorageName += String::CreateFromInt32((sal_uInt32)(sal_uIntPtr)pObj);
2844 SvStorageRef xOleStg = xObjPool->OpenSotStorage(sStorageName,
2845 STREAM_READWRITE|STREAM_SHARE_DENYALL);
2847 if (!xOleStg.Is())
2848 return false;
2850 String sName;
2851 if (!WriteOCXStream(xOleStg,xControlModel,aSize,sName))
2852 return false;
2854 BYTE aSpecOLE[] =
2856 0x03, 0x6a, 0xFF, 0xFF, 0xFF, 0xFF, // sprmCPicLocation
2857 0x0a, 0x08, 1, // sprmCFOLE2
2858 0x55, 0x08, 1, // sprmCFSpec
2859 0x56, 0x08, 1 // sprmCFObj
2861 //Set the obj id into the sprmCPicLocation
2862 BYTE *pData = aSpecOLE+2;
2863 Set_UInt32(pData,(sal_uInt32)(sal_uIntPtr)pObj);
2865 String sFld(FieldString(ww::eCONTROL));
2866 sFld.APPEND_CONST_ASC("Forms.");
2867 sFld += sName;
2868 sFld.APPEND_CONST_ASC(".1 \\s ");
2870 rWW8Wrt.OutputField(0, ww::eCONTROL, sFld,
2871 WRITEFIELD_START|WRITEFIELD_CMD_START|WRITEFIELD_CMD_END);
2873 rWW8Wrt.pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell(),sizeof(aSpecOLE),
2874 aSpecOLE);
2875 rWW8Wrt.WriteChar( 0x1 );
2876 rWW8Wrt.OutputField(0, ww::eCONTROL, aEmptyStr, WRITEFIELD_END | WRITEFIELD_CLOSE);
2877 return true;
2880 /* vi:set tabstop=4 shiftwidth=4 expandtab: */