summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/wrtw8esh.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/wrtw8esh.cxx')
-rw-r--r--sw/source/filter/ww8/wrtw8esh.cxx2880
1 files changed, 2880 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/wrtw8esh.cxx b/sw/source/filter/ww8/wrtw8esh.cxx
new file mode 100644
index 000000000000..5bb1ffc557b7
--- /dev/null
+++ b/sw/source/filter/ww8/wrtw8esh.cxx
@@ -0,0 +1,2880 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: wrtw8esh.cxx,v $
+ * $Revision: 1.105.10.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+#include <com/sun/star/embed/Aspects.hpp>
+
+
+#include <hintids.hxx>
+
+#define _SVSTDARR_ULONGSSORT
+#define _SVSTDARR_USHORTS
+#include <svtools/svstdarr.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <vcl/virdev.hxx>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <vcl/svapp.hxx>
+#include <sot/storage.hxx>
+#include <svtools/filter.hxx>
+#include <svtools/itemiter.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/outlobj.hxx>
+#include <svx/editobj.hxx>
+#include <svx/unoshape.hxx>
+#include <svx/brshitem.hxx>
+#include <svx/boxitem.hxx>
+#include <svx/lrspitem.hxx>
+#include <svx/ulspitem.hxx>
+#include <svx/fontitem.hxx>
+#include <svx/frmdiritem.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/editeng.hxx>
+#ifndef _SVX_FLDITEM_HXX
+//miserable hack to get around #98519#
+
+#include <svx/flditem.hxx>
+#endif
+
+#include <comphelper/seqstream.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <svtools/filter.hxx>
+#include <svx/fmglob.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/unoapi.hxx>
+
+// #i71538#
+#include <svx/svdview.hxx>
+#include <fmtcnct.hxx>
+#include <fmtanchr.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+// --> OD 2005-01-06 #i30669#
+#include <fmtfollowtextflow.hxx>
+// <--
+#include <dcontact.hxx>
+#include <frmfmt.hxx>
+#include <fmtcntnt.hxx>
+#include <ndindex.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <swrect.hxx>
+#include <ndgrf.hxx>
+#include <grfatr.hxx>
+#include <ndole.hxx>
+#include <unodraw.hxx>
+#include <pagedesc.hxx>
+#include <ww8par.hxx>
+#include <breakit.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include "ww8attributeoutput.hxx"
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+#include "escher.hxx"
+// --> OD 2007-07-24 #148096#
+#include <ndtxt.hxx>
+// <--
+#include "WW8FFData.hxx"
+
+using namespace com::sun::star;
+using namespace sw::util;
+using namespace sw::types;
+using namespace nsFieldFlags;
+
+//#110185# get a part fix for this type of element
+bool WW8Export::MiserableFormFieldExportHack(const SwFrmFmt& rFrmFmt)
+{
+ ASSERT(bWrtWW8, "Not allowed");
+ if (!bWrtWW8)
+ return false;
+ bool bHack = false;
+ const SdrObject *pObject = rFrmFmt.FindRealSdrObject();
+ if (pObject && pObject->GetObjInventor() == FmFormInventor)
+ {
+ if (SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObject))
+ {
+ uno::Reference< awt::XControlModel > xControlModel =
+ pFormObj->GetUnoControlModel();
+ uno::Reference< lang::XServiceInfo > xInfo(xControlModel,
+ uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
+ if (xInfo->supportsService(C2U("com.sun.star.form.component.ComboBox")))
+ {
+ DoComboBox(xPropSet);
+ bHack = true;
+ }
+ else if (xInfo->supportsService(C2U("com.sun.star.form.component.CheckBox")))
+ {
+ DoCheckBox(xPropSet);
+ bHack = true;
+ }
+ }
+ }
+ return bHack;
+}
+
+
+void WW8Export::DoComboBox(uno::Reference<beans::XPropertySet> xPropSet)
+{
+ rtl::OUString sSelected;
+ uno::Sequence<rtl::OUString> aListItems;
+ xPropSet->getPropertyValue(C2U("StringItemList")) >>= aListItems;
+ sal_Int32 nNoStrings = aListItems.getLength();
+ if (nNoStrings)
+ {
+ uno::Any aTmp = xPropSet->getPropertyValue(C2U("DefaultText"));
+ const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
+ if (pStr)
+ sSelected = *pStr;
+ }
+
+ rtl::OUString sName;
+ {
+ uno::Any aTmp = xPropSet->getPropertyValue(C2U("Name"));
+ const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
+ if (pStr)
+ sName = *pStr;
+ }
+
+
+ rtl::OUString sHelp;
+ {
+ uno::Any aTmp = xPropSet->getPropertyValue(C2U("Help"));
+ const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
+ if (pStr)
+ sHelp = *pStr;
+ }
+
+ rtl::OUString sToolTip;
+ {
+ uno::Any aTmp = xPropSet->getPropertyValue(C2U("Name"));
+ const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
+ if (pStr)
+ sToolTip = *pStr;
+ }
+
+ DoComboBox(sName, sHelp, sToolTip, sSelected, aListItems);
+}
+
+void WW8Export::DoComboBox(const rtl::OUString &rName,
+ const rtl::OUString &rHelp,
+ const rtl::OUString &rToolTip,
+ const rtl::OUString &rSelected,
+ uno::Sequence<rtl::OUString> &rListItems)
+{
+ ASSERT(bWrtWW8, "Not allowed");
+ if (!bWrtWW8)
+ return;
+ OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
+ WRITEFIELD_START | WRITEFIELD_CMD_START);
+ // write the refence to the "picture" structure
+ ULONG nDataStt = pDataStrm->Tell();
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+
+ WriteChar( 0x01 );
+
+ static BYTE aArr1[] =
+ {
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x02, 0x08, 0x01 // sprmCFFldVanish
+ };
+ BYTE* pDataAdr = aArr1 + 2;
+ Set_UInt32( pDataAdr, nDataStt );
+
+ pChpPlc->AppendFkpEntry(Strm().Tell(), sizeof(aArr1), aArr1);
+
+ OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
+ WRITEFIELD_CLOSE);
+
+ ::sw::WW8FFData aFFData;
+
+ aFFData.setType(2);
+ aFFData.setName(rName);
+ aFFData.setHelp(rHelp);
+ aFFData.setStatus(rToolTip);
+
+ sal_uInt32 nListItems = rListItems.getLength();
+
+ for (sal_uInt32 i = 0; i < nListItems; i++)
+ {
+ if (i < 0x20 && rSelected == rListItems[i])
+ aFFData.setResult(::sal::static_int_cast<sal_uInt8>(i));
+ aFFData.addListboxEntry(rListItems[i]);
+ }
+
+ aFFData.Write(pDataStrm);
+}
+
+void WW8Export::DoCheckBox(uno::Reference<beans::XPropertySet> xPropSet)
+{
+ uno::Reference<beans::XPropertySetInfo> xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+
+ OutputField(0, ww::eFORMCHECKBOX, FieldString(ww::eFORMCHECKBOX),
+ WRITEFIELD_START | WRITEFIELD_CMD_START);
+ // write the refence to the "picture" structure
+ ULONG nDataStt = pDataStrm->Tell();
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+
+ WriteChar( 0x01 );
+ static BYTE aArr1[] = {
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x02, 0x08, 0x01 // sprmCFFldVanish
+ };
+ BYTE* pDataAdr = aArr1 + 2;
+ Set_UInt32( pDataAdr, nDataStt );
+
+ pChpPlc->AppendFkpEntry(Strm().Tell(),
+ sizeof( aArr1 ), aArr1 );
+
+ ::sw::WW8FFData aFFData;
+
+ aFFData.setType(1);
+ aFFData.setCheckboxHeight(0x14);
+
+ sal_Int16 nTemp = 0;
+ xPropSet->getPropertyValue(C2U("DefaultState")) >>= nTemp;
+ sal_uInt32 nIsDefaultChecked(nTemp);
+
+ xPropSet->getPropertyValue(C2U("State")) >>= nTemp;
+ sal_uInt32 nIsChecked(nTemp);
+
+ if (nIsDefaultChecked != nIsChecked)
+ {
+ switch (nIsChecked)
+ {
+ case false:
+ aFFData.setResult(0);
+ break;
+ case true:
+ aFFData.setResult(1);
+ break;
+ default:
+ ASSERT(!this, "how did that happen");
+ }
+ }
+
+ ::rtl::OUString aStr;
+ static ::rtl::OUString sName(C2U("Name"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aStr;
+ aFFData.setName(aStr);
+ }
+
+ static ::rtl::OUString sHelpText(C2U("HelpText"));
+ if (xPropSetInfo->hasPropertyByName(sHelpText))
+ {
+ xPropSet->getPropertyValue(sHelpText) >>= aStr;
+ aFFData.setHelp(aStr);
+ }
+ static ::rtl::OUString sHelpF1Text(C2U("HelpF1Text"));
+ if (xPropSetInfo->hasPropertyByName(sHelpF1Text))
+ {
+ xPropSet->getPropertyValue(sHelpF1Text) >>= aStr;
+ aFFData.setStatus(aStr);
+ }
+
+ aFFData.Write(pDataStrm);
+
+ OutputField(0, ww::eFORMCHECKBOX, aEmptyStr, WRITEFIELD_CLOSE);
+}
+
+void WW8Export::DoFormText(const SwInputField * pFld)
+{
+ OutputField(0, ww::eFORMTEXT, FieldString(ww::eFORMTEXT),
+ WRITEFIELD_START | WRITEFIELD_CMD_START);
+ // write the refence to the "picture" structure
+ ULONG nDataStt = pDataStrm->Tell();
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+
+ WriteChar( 0x01 );
+ static BYTE aArr1[] = {
+ 0x02, 0x08, 0x81, // sprmCFFldVanish
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01 // sprmCFSpec
+ };
+ BYTE* pDataAdr = aArr1 + 5;
+ Set_UInt32( pDataAdr, nDataStt );
+
+ pChpPlc->AppendFkpEntry(Strm().Tell(),
+ sizeof( aArr1 ), aArr1 );
+
+ ::sw::WW8FFData aFFData;
+
+ aFFData.setType(0);
+ aFFData.setName(pFld->GetPar2());
+ aFFData.setHelp(pFld->GetHelp());
+ aFFData.setStatus(pFld->GetToolTip());
+ aFFData.Write(pDataStrm);
+
+ OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CMD_END);
+
+ SwWW8Writer::WriteString16(Strm(), pFld->Expand(), false);
+
+ static BYTE aArr2[] = {
+ 0x03, 0x6a, 0x00, 0x00, 0x00, 0x00, // sprmCPicLocation
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x75, 0x08, 0x01 // ???
+ };
+
+ pDataAdr = aArr2 + 2;
+ Set_UInt32( pDataAdr, nDataStt );
+ pChpPlc->AppendFkpEntry(Strm().Tell(),
+ sizeof( aArr2 ), aArr2 );
+
+ OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CLOSE);
+}
+
+PlcDrawObj::~PlcDrawObj()
+{
+}
+
+//Its irritating to have to change the RTL frames position into LTR ones
+//so that word will have to place them in the right place. Doubly so that
+//the SO drawings and writer frames have different ideas themselves as to
+//how to be positioned when in RTL mode!
+bool RTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
+sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
+ SwTwips nPageRight, SwTwips nPageSize)
+{
+ bool bRet = false;
+ if (eHoriOri == text::HoriOrientation::NONE)
+ {
+ if (eHoriRel == text::RelOrientation::PAGE_FRAME)
+ {
+ rLeft = nPageSize - rLeft;
+ bRet = true;
+ }
+ else if (
+ (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
+ (eHoriRel == text::RelOrientation::FRAME) ||
+ (eHoriRel == text::RelOrientation::PRINT_AREA)
+ )
+ {
+ rLeft = nPageSize - nPageLeft - nPageRight - rLeft;
+ bRet = true;
+ }
+ }
+ if (bRet)
+ rLeft -= nWidth;
+ return bRet;
+}
+
+bool RTLDrawingsHack(long &rLeft, long /*nWidth*/,
+ sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
+ SwTwips nPageRight, SwTwips nPageSize)
+{
+ bool bRet = false;
+ if (eHoriOri == text::HoriOrientation::NONE)
+ {
+ if (eHoriRel == text::RelOrientation::PAGE_FRAME)
+ {
+ rLeft = nPageSize + rLeft;
+ bRet = true;
+ }
+ else if (
+ (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
+ (eHoriRel == text::RelOrientation::FRAME) ||
+ (eHoriRel == text::RelOrientation::PRINT_AREA)
+ )
+ {
+ rLeft = nPageSize - nPageLeft - nPageRight + rLeft;
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+bool WW8Export::MiserableRTLFrmFmtHack(SwTwips &rLeft, SwTwips &rRight,
+ const sw::Frame &rFrmFmt)
+{
+ //Require nasty bidi swap
+ if (FRMDIR_HORI_RIGHT_TOP != pDoc->GetTextDirection(rFrmFmt.GetPosition()))
+ return false;
+
+ SwTwips nWidth = rRight - rLeft;
+ SwTwips nPageLeft, nPageRight;
+ SwTwips nPageSize = CurrentPageWidth(nPageLeft, nPageRight);
+
+ const SwFmtHoriOrient& rHOr = rFrmFmt.GetFrmFmt().GetHoriOrient();
+
+ bool bRet = false;
+ sw::Frame::WriterSource eSource = rFrmFmt.GetWriterType();
+ if (eSource == sw::Frame::eDrawing || eSource == sw::Frame::eFormControl)
+ {
+ if (RTLDrawingsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
+ rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
+ {
+ bRet = true;
+ }
+ }
+ else
+ {
+ if (RTLGraphicsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
+ rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
+ {
+ bRet = true;
+ }
+ }
+ if (bRet)
+ rRight = rLeft + nWidth;
+ return bRet;
+}
+
+void PlcDrawObj::WritePlc( WW8Export& rWrt ) const
+{
+ if (8 > rWrt.pFib->nVersion) // Cannot export drawobject in vers 7-
+ return;
+
+ sal_uInt32 nFcStart = rWrt.pTableStrm->Tell();
+
+ if (!maDrawObjs.empty())
+ {
+ // write CPs
+ WW8Fib& rFib = *rWrt.pFib;
+ WW8_CP nCpOffs = GetCpOffset(rFib);
+
+ cDrawObjIter aEnd = maDrawObjs.end();
+ cDrawObjIter aIter;
+
+ for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnCp - nCpOffs);
+
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, rFib.ccpText + rFib.ccpFtn +
+ rFib.ccpHdr + rFib.ccpEdn + rFib.ccpTxbx + rFib.ccpHdrTxbx + 1);
+
+ for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
+ {
+ // write the fspa-struct
+ const sw::Frame &rFrmFmt = aIter->maCntnt;
+ const SwFrmFmt &rFmt = rFrmFmt.GetFrmFmt();
+ const SdrObject* pObj = rFmt.FindRealSdrObject();
+
+ Rectangle aRect;
+ SwFmtVertOrient rVOr = rFmt.GetVertOrient();
+ SwFmtHoriOrient rHOr = rFmt.GetHoriOrient();
+ // --> OD 2005-01-06 #i30669# - convert the positioning attributes.
+ // Most positions are converted, if layout information exists.
+ const bool bPosConverted =
+ WinwordAnchoring::ConvertPosition( rHOr, rVOr, rFmt );
+ // <--
+
+ Point aObjPos;
+ if (RES_FLYFRMFMT == rFmt.Which())
+ {
+ SwRect aLayRect(rFmt.FindLayoutRect(false, &aObjPos));
+ // the Object is not visible - so get the values from
+ // the format. The Position may not be correct.
+ if( aLayRect.IsEmpty() )
+ aRect.SetSize( rFmt.GetFrmSize().GetSize() );
+ else
+ {
+ // --> FME 2007-06-20 #i56090# Do not only consider the first client
+ // Note that we actually would have to find the maximum size of the
+ // frame format clients. However, this already should work in most cases.
+ const SwRect aSizeRect(rFmt.FindLayoutRect());
+ if ( aSizeRect.Width() > aLayRect.Width() )
+ aLayRect.Width( aSizeRect.Width() );
+ // <--
+
+ aRect = aLayRect.SVRect();
+ }
+ }
+ else
+ {
+ ASSERT(pObj, "wo ist das SDR-Object?");
+ if (pObj)
+ {
+ aRect = pObj->GetSnapRect();
+ }
+ }
+
+ // --> OD 2005-01-06 #i30669# - use converted position, if conversion
+ // is performed. Unify position determination of Writer fly frames
+ // and drawing objects.
+ if ( bPosConverted )
+ {
+ aRect.SetPos( Point( rHOr.GetPos(), rVOr.GetPos() ) );
+ }
+ else
+ {
+ aRect -= aIter->maParentPos;
+ aObjPos = aRect.TopLeft();
+ if (text::VertOrientation::NONE == rVOr.GetVertOrient())
+ {
+ // CMC, OD 24.11.2003 #i22673#
+ sal_Int16 eOri = rVOr.GetRelationOrient();
+ if (eOri == text::RelOrientation::CHAR || eOri == text::RelOrientation::TEXT_LINE)
+ aObjPos.Y() = -rVOr.GetPos();
+ else
+ aObjPos.Y() = rVOr.GetPos();
+ }
+ if (text::HoriOrientation::NONE == rHOr.GetHoriOrient())
+ aObjPos.X() = rHOr.GetPos();
+ aRect.SetPos( aObjPos );
+ }
+ // <--
+
+ INT32 nThick = aIter->mnThick;
+
+ //If we are being exported as an inline hack, set
+ //corner to 0 and forget about border thickness for positioning
+ if (rFrmFmt.IsInline())
+ {
+ aRect.SetPos(Point(0,0));
+ nThick = 0;
+ }
+
+ // spid
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnShapeId);
+
+ SwTwips nLeft = aRect.Left() + nThick;
+ SwTwips nRight = aRect.Right() - nThick;
+
+ //Nasty swap for bidi if neccessary
+ rWrt.MiserableRTLFrmFmtHack(nLeft, nRight, rFrmFmt);
+
+ //xaLeft/yaTop/xaRight/yaBottom - rel. to anchor
+ //(most of) the border is outside the graphic is word, so
+ //change dimensions to fit
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, nLeft);
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Top() + nThick);
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, nRight);
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Bottom() - nThick);
+
+ //fHdr/bx/by/wr/wrk/fRcaSimple/fBelowText/fAnchorLock
+ USHORT nFlags=0;
+ //If nFlags isn't 0x14 its overridden by the escher properties
+ if( FLY_PAGE == rFmt.GetAnchor().GetAnchorId())
+ nFlags = 0x0000;
+ else
+ nFlags = 0x0014; // x-rel to text, y-rel to text
+
+ const SwFmtSurround& rSurr = rFmt.GetSurround();
+ USHORT nContour = rSurr.IsContour() ? 0x0080 : 0x0040;
+ SwSurround eSurround = rSurr.GetSurround();
+
+ /*
+ #i3958#
+ The inline elements being export as anchored to character inside
+ the shape field hack are required to be wrap through so as to flow
+ over the following dummy 0x01 graphic
+ */
+ if (rFrmFmt.IsInline())
+ eSurround = SURROUND_THROUGHT;
+
+ switch (eSurround)
+ {
+ case SURROUND_NONE:
+ nFlags |= 0x0020;
+ break;
+ case SURROUND_THROUGHT:
+ nFlags |= 0x0060;
+ break;
+ case SURROUND_PARALLEL:
+ nFlags |= 0x0000 | nContour;
+ break;
+ case SURROUND_IDEAL:
+ nFlags |= 0x0600 | nContour;
+ break;
+ case SURROUND_LEFT:
+ nFlags |= 0x0200 | nContour;
+ break;
+ case SURROUND_RIGHT:
+ nFlags |= 0x0400 | nContour;
+ break;
+ default:
+ ASSERT(!this, "Unsupported surround type for export");
+ break;
+ }
+ if (pObj && (pObj->GetLayer() == rWrt.pDoc->GetHellId() ||
+ pObj->GetLayer() == rWrt.pDoc->GetInvisibleHellId()))
+ {
+ nFlags |= 0x4000;
+ }
+
+ /*
+ #i3958# Required to make this inline stuff work in WordXP, not
+ needed for 2003 interestingly
+ */
+ if (rFrmFmt.IsInline())
+ nFlags |= 0x8000;
+
+ SwWW8Writer::WriteShort(*rWrt.pTableStrm, nFlags);
+
+ // cTxbx
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, 0);
+ }
+
+ RegisterWithFib(rFib, nFcStart, rWrt.pTableStrm->Tell() - nFcStart);
+ }
+}
+
+void MainTxtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
+ sal_uInt32 nLen) const
+{
+ rFib.fcPlcfspaMom = nStart;
+ rFib.lcbPlcfspaMom = nLen;
+}
+
+WW8_CP MainTxtPlcDrawObj::GetCpOffset(const WW8Fib &) const
+{
+ return 0;
+}
+
+void HdFtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
+ sal_uInt32 nLen) const
+{
+ rFib.fcPlcfspaHdr = nStart;
+ rFib.lcbPlcfspaHdr = nLen;
+}
+
+WW8_CP HdFtPlcDrawObj::GetCpOffset(const WW8Fib &rFib) const
+{
+ return rFib.ccpText + rFib.ccpFtn;
+}
+
+DrawObj& DrawObj::operator=(const DrawObj& rOther)
+{
+ mnCp = rOther.mnCp;
+ mnShapeId = rOther.mnShapeId;
+ maCntnt = rOther.maCntnt;
+ maParentPos = rOther.maParentPos;
+ mnThick = rOther.mnThick;
+ mnDirection = rOther.mnDirection;
+ mnHdFtIndex = rOther.mnHdFtIndex;
+ return *this;
+}
+
+bool PlcDrawObj::Append( WW8Export& rWrt, WW8_CP nCp, const sw::Frame& rFmt,
+ const Point& rNdTopLeft )
+{
+ bool bRet = false;
+ const SwFrmFmt &rFormat = rFmt.GetFrmFmt();
+ if (TXT_HDFT == rWrt.nTxtTyp || TXT_MAINTEXT == rWrt.nTxtTyp)
+ {
+ if (RES_FLYFRMFMT == rFormat.Which())
+ {
+ // check for textflyframe and if it is the first in a Chain
+ if (rFormat.GetCntnt().GetCntntIdx())
+ bRet = true;
+ }
+ else
+ bRet = true;
+ }
+
+ if (bRet)
+ {
+ DrawObj aObj(rFmt, nCp, rNdTopLeft, rWrt.TrueFrameDirection(rFormat),
+ rWrt.GetHdFtIndex());
+ maDrawObjs.push_back(aObj);
+ }
+ return bRet;
+}
+
+void DrawObj::SetShapeDetails(UINT32 nId, INT32 nThick)
+{
+ mnShapeId = nId;
+ mnThick = nThick;
+}
+
+bool WW8_WrPlcTxtBoxes::WriteTxt( WW8Export& rWrt )
+{
+ bool bRet = false;
+ rWrt.bInWriteEscher = true;
+ WW8_CP& rccp=TXT_TXTBOX == nTyp ? rWrt.pFib->ccpTxbx : rWrt.pFib->ccpHdrTxbx;
+
+ bRet = WriteGenericTxt( rWrt, nTyp, rccp );
+
+ WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ WW8Fib& rFib = *rWrt.pFib;
+ WW8_CP nMyOffset = rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpAtn
+ + rFib.ccpEdn;
+ if( TXT_TXTBOX == nTyp )
+ rWrt.pFldTxtBxs->Finish( nCP, nMyOffset );
+ else
+ rWrt.pFldHFTxtBxs->Finish( nCP, nMyOffset + rFib.ccpTxbx );
+ rWrt.bInWriteEscher = false;
+ return bRet;
+}
+
+void WW8_WrPlcTxtBoxes::Append( const SdrObject& rObj, UINT32 nShapeId )
+{
+ void* p = (void*)&rObj;
+ aCntnt.Insert( p, aCntnt.Count() );
+ aShapeIds.Insert( nShapeId, aShapeIds.Count() );
+}
+
+const SvULongs* WW8_WrPlcTxtBoxes::GetShapeIdArr() const
+{
+ return &aShapeIds;
+}
+
+/* */
+
+UINT32 WW8Export::GetSdrOrdNum( const SwFrmFmt& rFmt ) const
+{
+ UINT32 nOrdNum;
+ const SdrObject* pObj = rFmt.FindRealSdrObject();
+ if( pObj )
+ nOrdNum = pObj->GetOrdNum();
+ else
+ {
+ // no Layout for this format, then recalc the ordnum
+ SwFrmFmt* pFmt = (SwFrmFmt*)&rFmt;
+ nOrdNum = pDoc->GetSpzFrmFmts()->GetPos( pFmt );
+
+ const SdrModel* pModel = pDoc->GetDrawModel();
+ if( pModel )
+ nOrdNum += pModel->GetPage( 0 )->GetObjCount();
+ }
+ return nOrdNum;
+}
+
+void WW8Export::AppendFlyInFlys(const sw::Frame& rFrmFmt,
+ const Point& rNdTopLeft)
+{
+ ASSERT(bWrtWW8, "this has gone horribly wrong");
+ ASSERT(!pEscher, "der EscherStream wurde schon geschrieben!");
+ if (pEscher)
+ return ;
+ PlcDrawObj *pDrwO;
+ if (TXT_HDFT == nTxtTyp)
+ pDrwO = pHFSdrObjs;
+ else
+ pDrwO = pSdrObjs;
+
+ if (rFrmFmt.IsInline())
+ {
+ OutputField(0, ww::eSHAPE, FieldString(ww::eSHAPE),
+ WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
+ }
+
+ WW8_CP nCP = Fc2Cp(Strm().Tell());
+ bool bSuccess = pDrwO->Append(*this, nCP, rFrmFmt, rNdTopLeft);
+ ASSERT(bSuccess, "Couldn't export a graphical element!");
+
+ if (bSuccess)
+ {
+ static const sal_uInt8 aSpec8[] =
+ {
+ 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
+ 0x55, 0x08, 1 // sprmCFSpec
+ };
+ // fSpec-Attribut true
+ // Fuer DrawObjets muss ein Spezial-Zeichen
+ // in den Text und darum ein fSpec-Attribut
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+ WriteChar( 0x8 );
+ pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec8 ), aSpec8 );
+
+ //Need dummy picture frame
+ if (rFrmFmt.IsInline())
+ OutGrf(rFrmFmt);
+ }
+
+ if (rFrmFmt.IsInline())
+ OutputField(0, ww::eSHAPE, aEmptyStr, WRITEFIELD_CLOSE);
+}
+
+class WW8_SdrAttrIter : public MSWordAttrIter
+{
+private:
+ const EditTextObject* pEditObj;
+ const SfxItemPool* pEditPool;
+ EECharAttribArray aTxtAtrArr;
+ SvPtrarr aChrTxtAtrArr;
+ SvUShorts aChrSetArr;
+ USHORT nPara;
+ xub_StrLen nAktSwPos;
+ xub_StrLen nTmpSwPos; // fuer HasItem()
+ rtl_TextEncoding eNdChrSet;
+ USHORT nScript;
+ BYTE mnTyp;
+
+ xub_StrLen SearchNext( xub_StrLen nStartPos );
+ void SetCharSet(const EECharAttrib& rTxtAttr, bool bStart);
+
+ //No copying
+ WW8_SdrAttrIter(const WW8_SdrAttrIter&);
+ WW8_SdrAttrIter& operator=(const WW8_SdrAttrIter&);
+public:
+ WW8_SdrAttrIter( WW8Export& rWr, const EditTextObject& rEditObj,
+ BYTE nType );
+ void NextPara( USHORT nPar );
+ void OutParaAttr(bool bCharAttr);
+ void OutEEField(const SfxPoolItem& rHt);
+
+ bool IsTxtAttr(xub_StrLen nSwPos);
+
+ void NextPos() { nAktSwPos = SearchNext( nAktSwPos + 1 ); }
+
+ void OutAttr( xub_StrLen nSwPos );
+ virtual const SfxPoolItem* HasTextItem( USHORT nWhich ) const;
+ virtual const SfxPoolItem& GetItem( USHORT nWhich ) const;
+ bool OutAttrWithRange(xub_StrLen nPos);
+ xub_StrLen WhereNext() const { return nAktSwPos; }
+ rtl_TextEncoding GetNextCharSet() const;
+ rtl_TextEncoding GetNodeCharSet() const { return eNdChrSet; }
+};
+
+
+WW8_SdrAttrIter::WW8_SdrAttrIter( WW8Export& rWr,
+ const EditTextObject& rEditObj, BYTE nTyp )
+ : MSWordAttrIter( rWr ), pEditObj(&rEditObj), pEditPool(0),
+ aTxtAtrArr( 0, 4 ), aChrTxtAtrArr( 0, 4 ), aChrSetArr( 0, 4 ),
+ mnTyp(nTyp)
+{
+ NextPara( 0 );
+}
+
+void WW8_SdrAttrIter::NextPara( USHORT nPar )
+{
+ nPara = nPar;
+ // Attributwechsel an Pos 0 wird ignoriert, da davon ausgegangen
+ // wird, dass am Absatzanfang sowieso die Attribute neu ausgegeben
+ // werden.
+ aChrTxtAtrArr.Remove( 0, aChrTxtAtrArr.Count() );
+ aChrSetArr.Remove( 0, aChrSetArr.Count() );
+ nAktSwPos = nTmpSwPos = 0;
+
+ SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
+ pEditPool = aSet.GetPool();
+ eNdChrSet = ItemGet<SvxFontItem>(aSet,EE_CHAR_FONTINFO).GetCharSet();
+
+ if( pBreakIt->GetBreakIter().is() )
+ nScript = pBreakIt->GetBreakIter()->getScriptType( pEditObj->GetText(nPara), 0);
+ else
+ nScript = i18n::ScriptType::LATIN;
+
+ pEditObj->GetCharAttribs( nPara, aTxtAtrArr );
+ nAktSwPos = SearchNext( 1 );
+}
+
+rtl_TextEncoding WW8_SdrAttrIter::GetNextCharSet() const
+{
+ if( aChrSetArr.Count() )
+ return (rtl_TextEncoding)aChrSetArr[ aChrSetArr.Count() - 1 ];
+ return eNdChrSet;
+}
+
+// der erste Parameter in SearchNext() liefert zurueck, ob es ein TxtAtr ist.
+xub_StrLen WW8_SdrAttrIter::SearchNext( xub_StrLen nStartPos )
+{
+ xub_StrLen nPos;
+ xub_StrLen nMinPos = STRING_MAXLEN;
+ xub_StrLen i;
+
+ for( i = 0; i < aTxtAtrArr.Count(); i++ )
+ {
+ const EECharAttrib& rHt = aTxtAtrArr[ i ];
+ nPos = rHt.nStart; // gibt erstes Attr-Zeichen
+ if( nPos >= nStartPos && nPos <= nMinPos )
+ {
+ nMinPos = nPos;
+ SetCharSet(rHt, true);
+ }
+
+//?? if( pHt->GetEnd() ) // Attr mit Ende
+ {
+ nPos = rHt.nEnd; // gibt letztes Attr-Zeichen + 1
+ if( nPos >= nStartPos && nPos < nMinPos )
+ {
+ nMinPos = nPos;
+ SetCharSet(rHt, false);
+ }
+ }
+/* else
+ { // Attr ohne Ende
+ nPos = rHt.nStart + 1; // Laenge 1 wegen CH_TXTATR im Text
+ if( nPos >= nStartPos && nPos < nMinPos )
+ {
+ nMinPos = nPos;
+ SetCharSet(rHt, false);
+ }
+ }
+*/
+ }
+ return nMinPos;
+}
+
+void WW8_SdrAttrIter::SetCharSet(const EECharAttrib& rAttr, bool bStart)
+{
+ void* p = 0;
+ rtl_TextEncoding eChrSet;
+ const SfxPoolItem& rItem = *rAttr.pAttr;
+ switch( rItem.Which() )
+ {
+ case EE_CHAR_FONTINFO:
+ p = (void*)&rAttr;
+ eChrSet = ((SvxFontItem&)rItem).GetCharSet();
+ break;
+ }
+
+ if( p )
+ {
+ USHORT nPos;
+ if( bStart )
+ {
+ nPos = aChrSetArr.Count();
+ aChrSetArr.Insert( eChrSet, nPos );
+ aChrTxtAtrArr.Insert( p, nPos );
+ }
+ else if( USHRT_MAX != ( nPos = aChrTxtAtrArr.GetPos( p )) )
+ {
+ aChrTxtAtrArr.Remove( nPos );
+ aChrSetArr.Remove( nPos );
+ }
+ }
+}
+
+void WW8_SdrAttrIter::OutEEField(const SfxPoolItem& rHt)
+{
+ const SvxFieldItem &rField = (const SvxFieldItem &)rHt;
+ const SvxFieldData *pFld = rField.GetField();
+ if (pFld && pFld->ISA(SvxURLField))
+ {
+ BYTE nOldTxtTyp = m_rExport.nTxtTyp;
+ m_rExport.nTxtTyp = mnTyp;
+ const SvxURLField *pURL = (const SvxURLField *)pFld;
+ m_rExport.AttrOutput().StartURL( pURL->GetURL(), pURL->GetTargetFrame() );
+
+ const String &rStr = pURL->GetRepresentation();
+ m_rExport.AttrOutput().RawText( rStr, true, GetNodeCharSet() ); // FIXME kendy: is the 'true' actually correct here? It was here before, but... ;-)
+
+ m_rExport.AttrOutput().EndURL();
+ m_rExport.nTxtTyp = nOldTxtTyp;
+ }
+}
+
+void WW8_SdrAttrIter::OutAttr( xub_StrLen nSwPos )
+{
+ OutParaAttr(true);
+
+ if( aTxtAtrArr.Count() )
+ {
+ const SwModify* pOldMod = m_rExport.pOutFmtNode;
+ m_rExport.pOutFmtNode = 0;
+
+ const SfxItemPool* pSrcPool = pEditPool;
+ const SfxItemPool& rDstPool = m_rExport.pDoc->GetAttrPool();
+
+ nTmpSwPos = nSwPos;
+ USHORT i, nWhich, nSlotId;
+ for( i = 0; i < aTxtAtrArr.Count(); i++ )
+ {
+ const EECharAttrib& rHt = aTxtAtrArr[ i ];
+ if (nSwPos >= rHt.nStart && nSwPos < rHt.nEnd)
+ {
+ nWhich = rHt.pAttr->Which();
+ if (nWhich == EE_FEATURE_FIELD)
+ {
+ OutEEField(*rHt.pAttr);
+ continue;
+ }
+ else if (nWhich == EE_FEATURE_TAB)
+ {
+ m_rExport.WriteChar(0x9);
+ continue;
+ }
+ nSlotId = pSrcPool->GetSlotId(nWhich);
+
+ if (nSlotId && nWhich != nSlotId)
+ {
+ nWhich = rDstPool.GetWhich(nSlotId);
+ if (nWhich && nWhich != nSlotId &&
+ nWhich < RES_UNKNOWNATR_BEGIN &&
+ m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
+ {
+ // use always the SW-Which Id !
+ SfxPoolItem* pI = rHt.pAttr->Clone();
+ pI->SetWhich( nWhich );
+ m_rExport.AttrOutput().OutputItem( *pI );
+ delete pI;
+ }
+ }
+ }
+
+ if( nSwPos < rHt.nStart )
+ break;
+ }
+
+ nTmpSwPos = 0; // HasTextItem nur in dem obigen Bereich erlaubt
+ m_rExport.pOutFmtNode = pOldMod;
+ }
+}
+
+bool WW8_SdrAttrIter::IsTxtAttr(xub_StrLen nSwPos)
+{
+ for (USHORT i = 0; i < aTxtAtrArr.Count(); ++i)
+ {
+ const EECharAttrib& rHt = aTxtAtrArr[ i ];
+ if (nSwPos >= rHt.nStart && nSwPos < rHt.nEnd)
+ {
+ if (
+ (rHt.pAttr->Which() == EE_FEATURE_FIELD) ||
+ (rHt.pAttr->Which() == EE_FEATURE_TAB)
+ )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
+// und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
+// die dann ueber HasItem() nach anderen Items an der
+// Attribut-Anfangposition fragen kann.
+// Es koennen nur Attribute mit Ende abgefragt werden.
+// Es wird mit bDeep gesucht
+const SfxPoolItem* WW8_SdrAttrIter::HasTextItem(USHORT nWhich) const
+{
+ const SfxPoolItem* pRet = 0;
+ nWhich = sw::hack::TransformWhichBetweenPools(*pEditPool,
+ m_rExport.pDoc->GetAttrPool(), nWhich);
+ if (nWhich)
+ {
+ for (USHORT i = 0; i < aTxtAtrArr.Count(); ++i)
+ {
+ const EECharAttrib& rHt = aTxtAtrArr[i];
+ if (
+ nWhich == rHt.pAttr->Which() && nTmpSwPos >= rHt.nStart &&
+ nTmpSwPos < rHt.nEnd
+ )
+ {
+ pRet = rHt.pAttr; // Found
+ break;
+ }
+ else if (nTmpSwPos < rHt.nStart)
+ break; // dann kommt da nichts mehr
+ }
+ }
+ return pRet;
+}
+
+const SfxPoolItem& WW8_SdrAttrIter::GetItem( USHORT nWhich ) const
+{
+ using sw::hack::GetSetWhichFromSwDocWhich;
+ const SfxPoolItem* pRet = HasTextItem(nWhich);
+ if (!pRet)
+ {
+ SfxItemSet aSet(pEditObj->GetParaAttribs(nPara));
+ nWhich = GetSetWhichFromSwDocWhich(aSet, *m_rExport.pDoc, nWhich);
+ ASSERT(nWhich, "Impossible, catastrophic failure imminent");
+ pRet = &aSet.Get(nWhich);
+ }
+ return *pRet;
+}
+
+void WW8_SdrAttrIter::OutParaAttr(bool bCharAttr)
+{
+ SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
+ if( aSet.Count() )
+ {
+ const SfxItemSet* pOldSet = m_rExport.GetCurItemSet();
+ m_rExport.SetCurItemSet( &aSet );
+
+ SfxItemIter aIter( aSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+
+ const SfxItemPool* pSrcPool = pEditPool,
+ * pDstPool = &m_rExport.pDoc->GetAttrPool();
+
+ do {
+ USHORT nWhich = pItem->Which(),
+ nSlotId = pSrcPool->GetSlotId( nWhich );
+
+ if ( nSlotId && nWhich != nSlotId &&
+ 0 != ( nWhich = pDstPool->GetWhich( nSlotId ) ) &&
+ nWhich != nSlotId &&
+ ( bCharAttr ? ( nWhich >= RES_CHRATR_BEGIN && nWhich < RES_TXTATR_END )
+ : ( nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END ) ) )
+ {
+ // use always the SW-Which Id !
+ SfxPoolItem* pI = pItem->Clone();
+ pI->SetWhich( nWhich );
+ if (m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
+ m_rExport.AttrOutput().OutputItem( *pI );
+ delete pI;
+ }
+ } while( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
+ m_rExport.SetCurItemSet( pOldSet );
+ }
+}
+
+void WW8Export::WriteSdrTextObj(const SdrObject& rObj, BYTE nTyp)
+{
+ const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, &rObj);
+ ASSERT(pTxtObj, "That is no SdrTextObj!");
+ if (!pTxtObj)
+ return;
+
+ const OutlinerParaObject* pParaObj = 0;
+ bool bOwnParaObj = false;
+
+ /*
+ #i13885#
+ When the object is actively being edited, that text is not set into
+ the objects normal text object, but lives in a seperate object.
+ */
+ if (pTxtObj->IsTextEditActive())
+ {
+ pParaObj = pTxtObj->GetEditOutlinerParaObject();
+ bOwnParaObj = true;
+ }
+ else
+ {
+ pParaObj = pTxtObj->GetOutlinerParaObject();
+ }
+
+ if( pParaObj )
+ {
+ WriteOutliner(*pParaObj, nTyp);
+ if( bOwnParaObj )
+ delete pParaObj;
+ }
+}
+
+void WW8Export::WriteOutliner(const OutlinerParaObject& rParaObj, BYTE nTyp)
+{
+ bool bAnyWrite = false;
+ const EditTextObject& rEditObj = rParaObj.GetTextObject();
+ WW8_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
+
+ USHORT nPara = rEditObj.GetParagraphCount();
+ BYTE bNul = 0;
+ for( USHORT n = 0; n < nPara; ++n )
+ {
+ if( n )
+ aAttrIter.NextPara( n );
+
+ rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
+
+ ASSERT( !pO->Count(), " pO ist am Zeilenanfang nicht leer" );
+
+ String aStr( rEditObj.GetText( n ));
+ xub_StrLen nAktPos = 0;
+ xub_StrLen nEnd = aStr.Len();
+ do {
+ xub_StrLen nNextAttr = aAttrIter.WhereNext();
+ rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
+
+ if( nNextAttr > nEnd )
+ nNextAttr = nEnd;
+
+ bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
+ if( !bTxtAtr )
+ OutSwString( aStr, nAktPos, nNextAttr - nAktPos,
+ true, eChrSet );
+
+ // Am Zeilenende werden die Attribute bis ueber das CR
+ // aufgezogen. Ausnahme: Fussnoten am Zeilenende
+ if( nNextAttr == nEnd && !bTxtAtr )
+ WriteCR(); // CR danach
+
+ // Ausgabe der Zeichenattribute
+ aAttrIter.OutAttr( nAktPos ); // nAktPos - 1 ??
+ pChpPlc->AppendFkpEntry( Strm().Tell(),
+ pO->Count(), pO->GetData() );
+ pO->Remove( 0, pO->Count() ); // leeren
+
+ // Ausnahme: Fussnoten am Zeilenende
+ if( nNextAttr == nEnd && bTxtAtr )
+ WriteCR(); // CR danach
+ nAktPos = nNextAttr;
+ eChrSet = eNextChrSet;
+ aAttrIter.NextPos();
+ }
+ while( nAktPos < nEnd );
+
+ ASSERT( !pO->Count(), " pO ist am ZeilenEnde nicht leer" );
+
+ pO->Insert( bNul, pO->Count() ); // Style # as short
+ pO->Insert( bNul, pO->Count() );
+
+ aAttrIter.OutParaAttr(false);
+
+ ULONG nPos = Strm().Tell();
+ pPapPlc->AppendFkpEntry( Strm().Tell(),
+ pO->Count(), pO->GetData() );
+ pO->Remove( 0, pO->Count() ); // leeren
+ pChpPlc->AppendFkpEntry( nPos );
+ }
+
+ bAnyWrite = 0 != nPara;
+ if( !bAnyWrite )
+ WriteStringAsPara( aEmptyStr );
+}
+
+void WinwordAnchoring::WriteData( EscherEx& rEx ) const
+{
+ //Toplevel groups get their winword extra data attached, and sub elements
+ //use the defaults
+ if (rEx.GetGroupLevel() <= 1)
+ {
+ SvStream& rSt = rEx.GetStream();
+ //The last argument denotes the number of sub properties in this atom
+ if (mbInline)
+ {
+ rEx.AddAtom(18, DFF_msofbtUDefProp, 3, 3); //Prop id is 0xF122
+ rSt << (UINT16)0x0390 << sal_uInt32(3);
+ rSt << (UINT16)0x0392 << sal_uInt32(3);
+ //This sub property is required to be in the dummy inline frame as
+ //well
+ rSt << (UINT16)0x053F << nInlineHack;
+ }
+ else
+ {
+ rEx.AddAtom(24, DFF_msofbtUDefProp, 3, 4 ); //Prop id is 0xF122
+ rSt << (UINT16)0x038F << mnXAlign;
+ rSt << (UINT16)0x0390 << mnXRelTo;
+ rSt << (UINT16)0x0391 << mnYAlign;
+ rSt << (UINT16)0x0392 << mnYRelTo;
+ }
+ }
+}
+
+/* */
+
+void WW8Export::CreateEscher()
+{
+ SfxItemState eBackSet =
+ (const_cast<const SwDoc*>(pDoc))->GetPageDesc(0).GetMaster().
+ GetItemState(RES_BACKGROUND);
+ if (pHFSdrObjs->size() || pSdrObjs->size() || SFX_ITEM_SET == eBackSet)
+ {
+ ASSERT( !pEscher, "wer hat den Pointer nicht geloescht?" );
+ SvMemoryStream* pEscherStrm = new SvMemoryStream;
+ pEscherStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ pEscher = new SwEscherEx(pEscherStrm, *this);
+ }
+}
+
+void WW8Export::WriteEscher()
+{
+ if (pEscher)
+ {
+ ULONG nStart = pTableStrm->Tell();
+
+ pEscher->WritePictures();
+ pEscher->FinishEscher();
+
+ pFib->fcDggInfo = nStart;
+ pFib->lcbDggInfo = pTableStrm->Tell() - nStart;
+ delete pEscher, pEscher = 0;
+ }
+}
+
+void SwEscherEx::WritePictures()
+{
+ if (pPictStrm)
+ {
+ // set the blip - entries to the correct stream pos
+ INT32 nEndPos = rWrt.Strm().Tell();
+ SetNewBlipStreamOffset( nEndPos );
+
+ pPictStrm->Seek( 0 );
+ rWrt.Strm() << *pPictStrm;
+
+ delete pPictStrm, pPictStrm = 0;
+ }
+ Flush();
+}
+
+/* */
+
+// Output- Routines for Escher Export
+
+SwBasicEscherEx::SwBasicEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt,
+ UINT32 nDrawings)
+ : EscherEx(*pStrm, nDrawings), rWrt(rWW8Wrt), pEscherStrm(pStrm),
+ pPictStrm(0)
+{
+ Init();
+}
+
+SwBasicEscherEx::~SwBasicEscherEx()
+{
+}
+
+void SwBasicEscherEx::WriteFrmExtraData(const SwFrmFmt&)
+{
+ AddAtom(4, ESCHER_ClientAnchor);
+ GetStream() << (sal_uInt32)0x80000000;
+}
+
+void SwBasicEscherEx::WriteEmptyFlyFrame(const SwFrmFmt& rFmt, UINT32 nShapeId)
+{
+ OpenContainer(ESCHER_SpContainer);
+ AddShape(ESCHER_ShpInst_PictureFrame, 0xa00, nShapeId);
+ // store anchor attribute
+ WriteFrmExtraData(rFmt);
+
+ AddAtom(6, DFF_msofbtUDefProp, 3, 1); //Prop id is 0xF122
+ GetStream() << (UINT16)0x053F << nInlineHack;
+
+ CloseContainer(); // ESCHER_SpContainer
+}
+
+UINT32 AddMirrorFlags(UINT32 nFlags, const SwMirrorGrf &rMirror)
+{
+ switch (rMirror.GetValue())
+ {
+ default:
+ case RES_MIRROR_GRAPH_DONT:
+ break;
+ case RES_MIRROR_GRAPH_VERT:
+ nFlags |= SHAPEFLAG_FLIPH;
+ break;
+ case RES_MIRROR_GRAPH_HOR:
+ nFlags |= SHAPEFLAG_FLIPV;
+ break;
+ case RES_MIRROR_GRAPH_BOTH:
+ nFlags |= SHAPEFLAG_FLIPH;
+ nFlags |= SHAPEFLAG_FLIPV;
+ break;
+
+ }
+ return nFlags;
+}
+
+INT32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrmFmt& rFmt, UINT32 nShapeId)
+{
+ INT32 nBorderThick=0;
+ SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt);
+ SwGrfNode *pGrfNd = pNd ? pNd->GetGrfNode() : 0;
+ ASSERT(pGrfNd, "No SwGrfNode ?, suspicious");
+ if (!pGrfNd)
+ return nBorderThick;
+
+ OpenContainer( ESCHER_SpContainer );
+
+ const SwMirrorGrf &rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
+ AddShape(ESCHER_ShpInst_PictureFrame, AddMirrorFlags(0xa00, rMirror),
+ nShapeId);
+
+ EscherPropertyContainer aPropOpt;
+
+ UINT32 nFlags = ESCHER_BlipFlagDefault;
+
+ if (pGrfNd->IsLinkedFile())
+ {
+ String sURL;
+ pGrfNd->GetFileFilterNms( &sURL, 0 );
+
+ WW8Bytes aBuf;
+ SwWW8Writer::InsAsString16( aBuf, sURL );
+ SwWW8Writer::InsUInt16( aBuf, 0 );
+
+ USHORT nArrLen = aBuf.Count();
+ BYTE* pArr = new BYTE[ nArrLen ];
+ memcpy( pArr, aBuf.GetData(), nArrLen );
+
+ aPropOpt.AddOpt(ESCHER_Prop_pibName, true, nArrLen, pArr, nArrLen);
+ nFlags = ESCHER_BlipFlagLinkToFile | ESCHER_BlipFlagURL |
+ ESCHER_BlipFlagDoNotSave;
+ }
+ else
+ {
+ pGrfNd->SwapIn(true);
+
+ Graphic aGraphic(pGrfNd->GetGrf());
+ GraphicObject aGraphicObject( aGraphic );
+ ByteString aUniqueId = aGraphicObject.GetUniqueID();
+
+ if ( aUniqueId.Len() )
+ {
+ const MapMode aMap100mm( MAP_100TH_MM );
+ Size aSize( aGraphic.GetPrefSize() );
+
+ if ( MAP_PIXEL == aGraphic.GetPrefMapMode().GetMapUnit() )
+ {
+ aSize = Application::GetDefaultDevice()->PixelToLogic(
+ aSize, aMap100mm );
+ }
+ else
+ {
+ aSize = OutputDevice::LogicToLogic( aSize,
+ aGraphic.GetPrefMapMode(), aMap100mm );
+ }
+
+ Point aEmptyPoint = Point();
+ Rectangle aRect( aEmptyPoint, aSize );
+
+ sal_uInt32 nBlibId = GetBlibID( *QueryPicStream(), aUniqueId,
+ aRect, NULL, 0 );
+ if (nBlibId)
+ aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
+ }
+ }
+
+ aPropOpt.AddOpt( ESCHER_Prop_pibFlags, nFlags );
+ nBorderThick = WriteFlyFrameAttr(rFmt,mso_sptPictureFrame,aPropOpt);
+ WriteGrfAttr(*pGrfNd, aPropOpt);
+
+ aPropOpt.Commit( GetStream() );
+
+ // store anchor attribute
+ WriteFrmExtraData( rFmt );
+
+ CloseContainer(); // ESCHER_SpContainer
+ return nBorderThick;
+}
+
+void SwBasicEscherEx::WriteGrfAttr(const SwNoTxtNode& rNd,
+ EscherPropertyContainer& rPropOpt)
+{
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMode = GRAPHICDRAWMODE_STANDARD;
+ sal_Int32 nContrast = 0;
+ sal_Int16 nBrightness = 0;
+
+ if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CONTRAST,
+ true, &pItem))
+ {
+ nContrast = ((SfxInt16Item*)pItem)->GetValue();
+ }
+
+ if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_LUMINANCE,
+ true, &pItem))
+ {
+ nBrightness = ((SfxInt16Item*)pItem)->GetValue();
+ }
+
+
+ if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_DRAWMODE,
+ true, &pItem))
+ {
+ nMode = ((SfxEnumItem*)pItem)->GetValue();
+ if (nMode == GRAPHICDRAWMODE_WATERMARK)
+ {
+ /*
+ There is no real watermark mode in word, we must use standard
+ mode and modify our ones by 70% extra brightness and 70% less
+ contrast. This means that unmodified default OOo watermark
+ will turn back into watermark, and modified OOo watermark will
+ change into a close visual representation in standardmode
+ */
+ nBrightness += 70;
+ if (nBrightness > 100)
+ nBrightness = 100;
+ nContrast -= 70;
+ if (nContrast < -100)
+ nContrast = -100;
+ nMode = GRAPHICDRAWMODE_STANDARD;
+ }
+ }
+
+ if (nMode == GRAPHICDRAWMODE_GREYS)
+ nMode = 0x40004;
+ else if (nMode == GRAPHICDRAWMODE_MONO)
+ nMode = 0x60006;
+ else
+ nMode = 0;
+ rPropOpt.AddOpt( ESCHER_Prop_pictureActive, nMode );
+
+ if (nContrast != 0)
+ {
+ nContrast+=100;
+ if (nContrast == 100)
+ nContrast = 0x10000;
+ else if (nContrast < 100)
+ {
+ nContrast *= 0x10000;
+ nContrast /= 100;
+ }
+ else if (nContrast < 200)
+ nContrast = (100 * 0x10000) / (200-nContrast);
+ else
+ nContrast = 0x7fffffff;
+ rPropOpt.AddOpt( ESCHER_Prop_pictureContrast, nContrast);
+ }
+
+ if (nBrightness != 0)
+ rPropOpt.AddOpt( ESCHER_Prop_pictureBrightness, nBrightness * 327 );
+
+ if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CROPGRF,
+ true, &pItem))
+ {
+ const Size aSz( rNd.GetTwipSize() );
+ INT32 nVal;
+ if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetLeft() ) )
+ rPropOpt.AddOpt( ESCHER_Prop_cropFromLeft, ToFract16( nVal, aSz.Width()) );
+ if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetRight() ) )
+ rPropOpt.AddOpt( ESCHER_Prop_cropFromRight, ToFract16( nVal, aSz.Width()));
+ if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetTop() ) )
+ rPropOpt.AddOpt( ESCHER_Prop_cropFromTop, ToFract16( nVal, aSz.Height()));
+ if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetBottom() ) )
+ rPropOpt.AddOpt( ESCHER_Prop_cropFromBottom, ToFract16( nVal, aSz.Height()));
+ }
+}
+
+void SwBasicEscherEx::SetPicId(const SdrObject &, UINT32,
+ EscherPropertyContainer &)
+{
+}
+
+void SwEscherEx::SetPicId(const SdrObject &rSdrObj, UINT32 nShapeId,
+ EscherPropertyContainer &rPropOpt)
+{
+ pTxtBxs->Append(rSdrObj, nShapeId);
+ UINT32 nPicId = pTxtBxs->Count();
+ nPicId *= 0x10000;
+ rPropOpt.AddOpt( ESCHER_Prop_pictureId, nPicId );
+}
+
+INT32 SwBasicEscherEx::WriteOLEFlyFrame(const SwFrmFmt& rFmt, UINT32 nShapeId)
+{
+ INT32 nBorderThick = 0;
+ if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
+ {
+ SwNodeIndex aIdx(*rFmt.GetCntnt().GetCntntIdx(), 1);
+ SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
+ sal_Int64 nAspect = rOLENd.GetAspect();
+
+ uno::Reference < embed::XEmbeddedObject > xObj(rOLENd.GetOLEObj().GetOleRef());
+
+ // the rectangle is used to transport the size of the object
+ // the left, top corner is set to ( 0, 0 ) by default constructor,
+ // if the width and height are set correctly bRectIsSet should be set to true
+ awt::Rectangle aRect;
+ sal_Bool bRectIsSet = sal_False;
+
+
+ // TODO/LATER: should the icon size be stored in case of iconified object?
+ if ( xObj.is() && nAspect != embed::Aspects::MSOLE_ICON )
+ {
+ try
+ {
+ awt::Size aSize = xObj->getVisualAreaSize( nAspect );
+ aRect.Width = aSize.Width;
+ aRect.Height = aSize.Height;
+ bRectIsSet = sal_True;
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ /*
+ #i5970#
+ Export floating ole2 .doc ver 8+ wmf ole2 previews as emf previews
+ instead ==> allows unicode text to be preserved
+ */
+#ifdef OLE_PREVIEW_AS_EMF
+ //Graphic aGraphic = wwUtility::MakeSafeGDIMetaFile(xObj);
+ Graphic* pGraphic = rOLENd.GetGraphic();
+#endif
+ OpenContainer(ESCHER_SpContainer);
+
+ EscherPropertyContainer aPropOpt;
+ const SwMirrorGrf &rMirror = rOLENd.GetSwAttrSet().GetMirrorGrf();
+ WriteOLEPicture(aPropOpt, AddMirrorFlags(0xa00 | SHAPEFLAG_OLESHAPE,
+ rMirror), pGraphic ? *pGraphic : Graphic(), *pSdrObj, nShapeId, bRectIsSet ? &aRect : NULL );
+
+ nBorderThick = WriteFlyFrameAttr(rFmt, mso_sptPictureFrame, aPropOpt);
+ WriteGrfAttr(rOLENd, aPropOpt);
+ aPropOpt.Commit(GetStream());
+
+ // store anchor attribute
+ WriteFrmExtraData( rFmt );
+
+ CloseContainer(); // ESCHER_SpContainer
+ }
+ return nBorderThick;
+}
+
+void SwBasicEscherEx::WriteBrushAttr(const SvxBrushItem &rBrush,
+ EscherPropertyContainer& rPropOpt)
+{
+ bool bSetOpacity = false;
+ sal_uInt32 nOpaque = 0;
+ if (const GraphicObject *pGraphicObject = rBrush.GetGraphicObject())
+ {
+ ByteString aUniqueId = pGraphicObject->GetUniqueID();
+ if (aUniqueId.Len())
+ {
+ const Graphic &rGraphic = pGraphicObject->GetGraphic();
+ Size aSize(rGraphic.GetPrefSize());
+ const MapMode aMap100mm(MAP_100TH_MM);
+ if (MAP_PIXEL == rGraphic.GetPrefMapMode().GetMapUnit())
+ {
+ aSize = Application::GetDefaultDevice()->PixelToLogic(
+ aSize, aMap100mm);
+ }
+ else
+ {
+ aSize = OutputDevice::LogicToLogic(aSize,
+ rGraphic.GetPrefMapMode(), aMap100mm);
+ }
+
+ Point aEmptyPoint = Point();
+ Rectangle aRect(aEmptyPoint, aSize);
+
+ sal_uInt32 nBlibId = GetBlibID(*QueryPicStream(), aUniqueId,
+ aRect, NULL, 0);
+ if (nBlibId)
+ rPropOpt.AddOpt(ESCHER_Prop_fillBlip,nBlibId,sal_True);
+ }
+
+ if (0 != (nOpaque = pGraphicObject->GetAttr().GetTransparency()))
+ bSetOpacity = true;
+
+ rPropOpt.AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
+ rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
+ rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
+ }
+ else
+ {
+ UINT32 nFillColor = GetColor(rBrush.GetColor(), false);
+ rPropOpt.AddOpt( ESCHER_Prop_fillColor, nFillColor );
+ rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, nFillColor ^ 0xffffff );
+ rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
+
+ if (0 != (nOpaque = rBrush.GetColor().GetTransparency()))
+ bSetOpacity = true;
+ }
+
+ if (bSetOpacity)
+ {
+ nOpaque = (nOpaque * 100) / 0xFE;
+ nOpaque = ((100 - nOpaque) << 16) / 100;
+ rPropOpt.AddOpt(ESCHER_Prop_fillOpacity, nOpaque);
+ }
+}
+
+INT32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt,
+ MSO_SPT eShapeType, EscherPropertyContainer& rPropOpt)
+{
+ INT32 nLineWidth=0;
+ const SfxPoolItem* pItem;
+ bool bFirstLine = true;
+ if (SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem))
+ {
+ static const UINT16 aExhperProp[4] =
+ {
+ ESCHER_Prop_dyTextTop, ESCHER_Prop_dyTextBottom,
+ ESCHER_Prop_dxTextLeft, ESCHER_Prop_dxTextRight
+ };
+ const SvxBorderLine* pLine;
+
+ for( USHORT n = 0; n < 4; ++n )
+ if( 0 != ( pLine = ((SvxBoxItem*)pItem)->GetLine( n )) )
+ {
+ if( bFirstLine )
+ {
+ UINT32 nLineColor = GetColor(pLine->GetColor(), false);
+ rPropOpt.AddOpt( ESCHER_Prop_lineColor, nLineColor );
+ rPropOpt.AddOpt( ESCHER_Prop_lineBackColor,
+ nLineColor ^ 0xffffff );
+
+ MSO_LineStyle eStyle;
+ if( pLine->GetInWidth() )
+ {
+ // double line
+ nLineWidth = pLine->GetInWidth() + pLine->GetOutWidth()
+ + pLine->GetDistance();
+ if( pLine->GetInWidth() == pLine->GetOutWidth() )
+ eStyle = mso_lineDouble;
+ else if( pLine->GetInWidth() < pLine->GetOutWidth() )
+ eStyle = mso_lineThickThin;
+ else
+ eStyle = mso_lineThinThick;
+ }
+ else
+ {
+ // simple line
+ eStyle = mso_lineSimple;
+ nLineWidth = pLine->GetOutWidth();
+ }
+
+ rPropOpt.AddOpt( ESCHER_Prop_lineStyle, eStyle );
+ rPropOpt.AddOpt( ESCHER_Prop_lineWidth,
+ DrawModelToEmu( nLineWidth ));
+ rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x8000E );
+
+ //Use import logic to determine how much of border will go
+ //outside graphic
+ nLineWidth = SwMSDffManager::GetEscherLineMatch(
+ eStyle,eShapeType,nLineWidth);
+ bFirstLine = false;
+ }
+ rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(
+ ((SvxBoxItem*)pItem)->GetDistance( n ) ));
+ }
+ else
+ // MM If there is no line the distance should be set to 0
+ rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(0));
+ }
+ if( bFirstLine ) // no valid line found
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
+ rPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
+ rPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
+ rPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
+ rPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
+ }
+
+ SvxBrushItem aBrush(rWrt.TrueFrameBgBrush(rFmt));
+ WriteBrushAttr(aBrush, rPropOpt);
+
+ const SdrObject* pObj = rFmt.FindRealSdrObject();
+ if( pObj && (pObj->GetLayer() == GetHellLayerId() ||
+ pObj->GetLayer() == GetInvisibleHellId() ))
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
+ }
+
+ return nLineWidth;
+}
+
+INT32 SwEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType,
+ EscherPropertyContainer& rPropOpt)
+{
+ INT32 nLineWidth = SwBasicEscherEx::WriteFlyFrameAttr(rFmt, eShapeType,
+ rPropOpt);
+
+ /*
+ These are not in SwBasicEscherEx::WriteFlyFrameAttr because inline objs
+ can't do it in word and it hacks it in by stretching the graphic that
+ way, perhaps we should actually draw in this space into the graphic we
+ are exporting!
+ */
+ const SfxPoolItem* pItem;
+ if (SFX_ITEM_SET == rFmt.GetItemState(RES_LR_SPACE, true, &pItem))
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft,
+ DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetLeft() ) );
+ rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight,
+ DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetRight() ) );
+ }
+ else
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
+ rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
+ }
+
+ if (SFX_ITEM_SET == rFmt.GetItemState(RES_UL_SPACE, true, &pItem))
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistTop,
+ DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetUpper() ) );
+ rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistBottom,
+ DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetLower() ) );
+ }
+
+ if (rFmt.GetSurround().IsContour())
+ {
+ if (const SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt))
+ {
+ const PolyPolygon *pPolyPoly = pNd->HasContour();
+ if (pPolyPoly && pPolyPoly->Count())
+ {
+ Polygon aPoly(PolygonFromPolyPolygon(*pPolyPoly));
+ const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
+ Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
+ Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
+ aPoly.Scale(aMapPolyX, aMapPolyY);
+
+ /*
+ a) stretch right bound by 15twips
+ b) shrink bottom bound to where it would have been in word
+ c) Move it to the left by 15twips
+
+ See the import for details
+ */
+ const Size &rSize = pNd->GetTwipSize();
+ Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
+ aMoveHack *= Fraction(15, 1);
+ long nMove(aMoveHack);
+
+ Fraction aHackX(ww::nWrap100Percent + nMove,
+ ww::nWrap100Percent);
+ Fraction aHackY(ww::nWrap100Percent - nMove,
+ ww::nWrap100Percent);
+ aPoly.Scale(aHackX, aHackY);
+
+ aPoly.Move(-nMove, 0);
+
+ SvMemoryStream aPolyDump;
+ aPolyDump.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+
+ sal_uInt16 nLen = aPoly.GetSize();
+ aPolyDump << nLen;
+ aPolyDump << nLen;
+ aPolyDump << sal_uInt16(8);
+ for (sal_uInt16 nI = 0; nI < nLen; ++nI)
+ {
+ aPolyDump << sal_uInt32(aPoly[nI].X());
+ aPolyDump << sal_uInt32(aPoly[nI].Y());
+ }
+
+ sal_uInt16 nArrLen = msword_cast<sal_uInt16>(aPolyDump.Tell());
+ void *pArr = const_cast<void *>(aPolyDump.GetData());
+ //PropOpt wants to own the buffer
+ aPolyDump.ObjectOwnsMemory(false);
+ rPropOpt.AddOpt(DFF_Prop_pWrapPolygonVertices, false,
+ nArrLen, static_cast<BYTE *>(pArr), nArrLen);
+ }
+ }
+ }
+
+ return nLineWidth;
+}
+
+void SwBasicEscherEx::Init()
+{
+ MapUnit eMap = MAP_TWIP;
+ if (SdrModel *pModel = rWrt.pDoc->GetDrawModel())
+ {
+ // PPT arbeitet nur mit Einheiten zu 576DPI
+ // WW hingegen verwendet twips, dh. 1440DPI.
+ eMap = pModel->GetScaleUnit();
+ }
+
+ // MS-DFF-Properties sind grossteils in EMU (English Metric Units) angegeben
+ // 1mm=36000emu, 1twip=635emu
+ Fraction aFact(360, 1);
+ aFact /= GetMapFactor(MAP_100TH_MM, eMap).X();
+ // create little values
+ aFact = Fraction(aFact.GetNumerator(), aFact.GetDenominator());
+ mnEmuMul = aFact.GetNumerator();
+ mnEmuDiv = aFact.GetDenominator();
+
+ SetHellLayerId(rWrt.pDoc->GetHellId());
+}
+
+INT32 SwBasicEscherEx::ToFract16(INT32 nVal, UINT32 nMax) const
+{
+ if (nMax)
+ {
+ INT32 nMSVal = (nVal / 65536) * nMax;
+ nMSVal += (nVal * 65536 ) / nMax;
+ return nMSVal;
+ }
+ return 0;
+}
+
+SvStream* SwBasicEscherEx::QueryPicStream()
+{
+ if (!pPictStrm)
+ {
+ pPictStrm = new SvMemoryStream;
+ pPictStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ }
+ return pPictStrm;
+}
+
+SdrLayerID SwBasicEscherEx::GetInvisibleHellId() const
+{
+ return rWrt.pDoc->GetInvisibleHellId();
+}
+
+void SwBasicEscherEx::WritePictures()
+{
+ ASSERT(pPictStrm, "no picture!");
+ if (pPictStrm)
+ {
+ // set the blip - entries to the correct stream pos
+ INT32 nEndPos = pPictStrm->Tell();
+ WriteBlibStoreEntry(*pEscherStrm, 1, sal_True, nEndPos);
+
+ pPictStrm->Seek(0);
+ *pEscherStrm << *pPictStrm;
+
+ delete pPictStrm, pPictStrm = 0;
+ }
+}
+
+SwEscherEx::SwEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
+ : SwBasicEscherEx(pStrm, rWW8Wrt, rWW8Wrt.pHFSdrObjs->size() ? 2 : 1),
+ pTxtBxs(0)
+{
+ aHostData.SetClientData(&aWinwordAnchoring);
+ OpenContainer( ESCHER_DggContainer );
+
+ sal_uInt16 nColorCount = 4;
+ *pStrm << (sal_uInt16)( nColorCount << 4 ) // instance
+ << (sal_uInt16)ESCHER_SplitMenuColors // record type
+ << (sal_uInt32)( nColorCount * 4 ) // size
+ << (sal_uInt32)0x08000004
+ << (sal_uInt32)0x08000001
+ << (sal_uInt32)0x08000002
+ << (sal_uInt32)0x100000f7;
+
+ CloseContainer(); // ESCHER_DggContainer
+
+ BYTE i = 2; // for header/footer and the other
+ PlcDrawObj *pSdrObjs = rWrt.pHFSdrObjs;
+ pTxtBxs = rWrt.pHFTxtBxs;
+
+ // if no header/footer -> skip over
+ if (!pSdrObjs->size())
+ {
+ --i;
+ pSdrObjs = rWrt.pSdrObjs;
+ pTxtBxs = rWrt.pTxtBxs;
+ }
+
+ for( ; i--; pSdrObjs = rWrt.pSdrObjs, pTxtBxs = rWrt.pTxtBxs )
+ {
+ // "dummy char" (or any Count ?) - why? This knows only M$
+ GetStream() << (sal_Char)i;
+
+ OpenContainer( ESCHER_DgContainer );
+
+ EnterGroup( 0 );
+
+ ULONG nSecondShapeId = pSdrObjs == rWrt.pSdrObjs ? GetShapeID() : 0;
+
+ // write now all Writer-/DrawObjects
+ DrawObjPointerVector aSorted;
+ MakeZOrderArrAndFollowIds(pSdrObjs->GetObjArr(), aSorted);
+
+ sal_uInt32 nShapeId=0;
+ DrawObjPointerIter aEnd = aSorted.end();
+ for (DrawObjPointerIter aIter = aSorted.begin(); aIter != aEnd; ++aIter)
+ {
+ INT32 nBorderThick=0;
+ DrawObj *pObj = (*aIter);
+ ASSERT(pObj, "impossible");
+ if (!pObj)
+ continue;
+ const sw::Frame &rFrame = pObj->maCntnt;
+ const SwFrmFmt& rFmt = rFrame.GetFrmFmt();
+
+ switch (rFrame.GetWriterType())
+ {
+ case sw::Frame::eTxtBox:
+ case sw::Frame::eOle:
+ case sw::Frame::eGraphic:
+ nBorderThick = WriteFlyFrm(*pObj, nShapeId, aSorted);
+ break;
+ case sw::Frame::eFormControl:
+ WriteOCXControl(rFmt, nShapeId=GetShapeID());
+ break;
+ case sw::Frame::eDrawing:
+ aWinwordAnchoring.SetAnchoring(rFmt);
+ const SdrObject* pSdrObj = rFmt.FindRealSdrObject();
+ if (pSdrObj)
+ {
+ bool bSwapInPage = false;
+ if (!pSdrObj->GetPage())
+ {
+ if (SdrModel* pModel = rWrt.pDoc->GetDrawModel())
+ {
+ if (SdrPage *pPage = pModel->GetPage(0))
+ {
+ bSwapInPage = true;
+ (const_cast<SdrObject*>(pSdrObj))->SetPage(pPage);
+ }
+ }
+ }
+
+ nShapeId = AddSdrObject(*pSdrObj);
+
+ if (bSwapInPage)
+ (const_cast<SdrObject*>(pSdrObj))->SetPage(0);
+ }
+#ifndef PRODUCT
+ else
+ ASSERT( !this, "Where is the SDR-Object?" );
+#endif
+ }
+
+ if( !nShapeId )
+ {
+ nShapeId = AddDummyShape();
+ }
+
+ pObj->SetShapeDetails(nShapeId, nBorderThick);
+ }
+
+ EndSdrObjectPage(); // ???? Bugfix for 74724
+
+ if( nSecondShapeId )
+ {
+ OpenContainer( ESCHER_SpContainer );
+
+ AddShape( ESCHER_ShpInst_Rectangle, 0xe00, nSecondShapeId );
+
+ EscherPropertyContainer aPropOpt;
+ const SwFrmFmt &rFmt = const_cast<const SwDoc *>(rWrt.pDoc)->GetPageDesc(0).GetMaster();
+ const SfxPoolItem* pItem = 0;
+ SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true,
+ &pItem);
+ if (SFX_ITEM_SET == eState && pItem)
+ {
+ const SvxBrushItem* pBrush = (const SvxBrushItem*)pItem;
+ WriteBrushAttr(*pBrush, aPropOpt);
+ }
+ aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x8000001 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
+ aPropOpt.AddOpt( ESCHER_Prop_shadowColor, 0x8000002 );
+ aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
+
+// winword defaults!
+// aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
+// aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
+// aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
+// aPropOpt.AddOpt( ESCHER_Prop_bWMode, 0x9 );
+// aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
+
+ aPropOpt.Commit( *pStrm );
+
+ AddAtom( 4, ESCHER_ClientData );
+ GetStream() << 1L;
+
+ CloseContainer(); // ESCHER_SpContainer
+ }
+ CloseContainer(); // ESCHER_DgContainer
+ }
+}
+
+SwEscherEx::~SwEscherEx()
+{
+}
+
+void SwEscherEx::FinishEscher()
+{
+ pEscherStrm->Seek(0);
+ *rWrt.pTableStrm << *pEscherStrm;
+ delete pEscherStrm, pEscherStrm = 0;
+}
+
+/** method to perform conversion of positioning attributes with the help
+ of corresponding layout information
+
+ OD 2005-01-06 #i30669#
+ Because most of the Writer object positions doesn't correspond to the
+ object positions in WW8, this method converts the positioning
+ attributes. For this conversion the corresponding layout information
+ is needed. If no layout information exists - e.g. no layout exists - no
+ conversion is performed.
+ No conversion is performed for as-character anchored objects. Whose
+ object positions are already treated special in method <WriteData(..)>.
+
+ @author OD
+
+ @param _iorHoriOri
+ input/output parameter - containing the current horizontal position
+ attributes, which are converted by this method.
+
+ @param _iorVertOri
+ input/output parameter - containing the current vertical position
+ attributes, which are converted by this method.
+
+ @param _rFrmFmt
+ input parameter - frame format of the anchored object
+
+ @return boolean, indicating, if a conversion has been performed.
+*/
+bool WinwordAnchoring::ConvertPosition( SwFmtHoriOrient& _iorHoriOri,
+ SwFmtVertOrient& _iorVertOri,
+ const SwFrmFmt& _rFrmFmt )
+{
+ const RndStdIds eAnchor = _rFrmFmt.GetAnchor().GetAnchorId();
+
+ if ( FLY_IN_CNTNT == eAnchor || FLY_AT_FLY == eAnchor )
+ {
+ // no conversion for as-character or at frame anchored objects
+ return false;
+ }
+
+ // determine anchored object
+ SwAnchoredObject* pAnchoredObj( 0L );
+ {
+ const SwContact* pContact = _rFrmFmt.FindContactObj();
+ if ( pContact )
+ {
+ std::vector<SwAnchoredObject*> aAnchoredObjs;
+ pContact->GetAnchoredObjs( aAnchoredObjs );
+ if ( !aAnchoredObjs.empty() )
+ {
+ pAnchoredObj = aAnchoredObjs.front();
+ }
+ }
+ }
+ if ( !pAnchoredObj )
+ {
+ // no anchored object found. Thus, the needed layout information can't
+ // be determined. --> no conversion
+ return false;
+ }
+ // --> OD 2006-09-26 #141404#
+ // no conversion for anchored drawing object, which aren't attached to an
+ // anchor frame.
+ // This is the case for drawing objects, which are anchored inside a page
+ // header/footer of an *unused* page style.
+ if ( dynamic_cast<SwAnchoredDrawObject*>(pAnchoredObj) &&
+ !pAnchoredObj->GetAnchorFrm() )
+ {
+ return false;
+ }
+ // <--
+
+ bool bConverted( false );
+
+ // determine value of attribute 'Follow text flow', because positions aligned
+ // at page areas have to be converted, if it's set.
+ const bool bFollowTextFlow = _rFrmFmt.GetFollowTextFlow().GetValue();
+
+ // --> OD 2007-07-24 #148096#
+ // check, if horizontal and vertical position have to be converted due to
+ // the fact, that the object is anchored at a paragraph, which has a "column
+ // break before" attribute
+ bool bConvDueToAnchoredAtColBreakPara( false );
+ if ( ( eAnchor == FLY_AT_CNTNT || eAnchor == FLY_AUTO_CNTNT ) &&
+ _rFrmFmt.GetAnchor().GetCntntAnchor() &&
+ _rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode().IsTxtNode() )
+ {
+ SwTxtNode& rAnchorTxtNode =
+ dynamic_cast<SwTxtNode&>(_rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode());
+ const SvxFmtBreakItem* pBreak = &(ItemGet<SvxFmtBreakItem>(rAnchorTxtNode, RES_BREAK));
+ if ( pBreak &&
+ pBreak->GetBreak() == SVX_BREAK_COLUMN_BEFORE )
+ {
+ bConvDueToAnchoredAtColBreakPara = true;
+ }
+ }
+ // <--
+
+ // convert horizontal position, if needed
+ {
+ enum HoriConv { NO_CONV, CONV2PG, CONV2COL, CONV2CHAR };
+ HoriConv eHoriConv( NO_CONV );
+
+ // determine, if conversion has to be performed due to the position orientation
+ bool bConvDueToOrientation( false );
+ {
+ const sal_Int16 eHOri = _iorHoriOri.GetHoriOrient();
+ bConvDueToOrientation = eHOri == text::HoriOrientation::LEFT || eHOri == text::HoriOrientation::RIGHT ||
+ eHOri == text::HoriOrientation::INSIDE || eHOri == text::HoriOrientation::OUTSIDE ||
+ ( eHOri != text::HoriOrientation::CENTER && _iorHoriOri.IsPosToggle() );
+ }
+
+ // determine conversion type due to the position relation
+ // --> OD 2007-07-24 #148096#
+ if ( bConvDueToAnchoredAtColBreakPara )
+ {
+ eHoriConv = CONV2PG;
+ }
+ else
+ {
+ switch ( _iorHoriOri.GetRelationOrient() )
+ {
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ if ( bConvDueToOrientation || bFollowTextFlow )
+ eHoriConv = CONV2PG;
+ }
+ break;
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_RIGHT:
+ {
+ // relation not supported by WW8. Thus, conversion always needed.
+ eHoriConv = CONV2PG;
+ }
+ break;
+ case text::RelOrientation::FRAME:
+ {
+ if ( bConvDueToOrientation )
+ eHoriConv = CONV2COL;
+ }
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::FRAME_LEFT:
+ case text::RelOrientation::FRAME_RIGHT:
+ {
+ // relation not supported by WW8. Thus, conversion always needed.
+ eHoriConv = CONV2COL;
+ }
+ break;
+ case text::RelOrientation::CHAR:
+ {
+ if ( bConvDueToOrientation )
+ eHoriConv = CONV2CHAR;
+ }
+ break;
+ default:
+ ASSERT( false,
+ "<WinwordAnchoring::ConvertPosition(..)> - unknown horizontal relation" );
+ }
+ }
+ // <--
+ if ( eHoriConv != NO_CONV )
+ {
+ _iorHoriOri.SetHoriOrient( text::HoriOrientation::NONE );
+ SwTwips nPosX( 0L );
+ {
+ Point aPos;
+ if ( eHoriConv == CONV2PG )
+ {
+ _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
+ // --> OD 2005-01-27 #i33818#
+ bool bRelToTableCell( false );
+ aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
+ bRelToTableCell );
+ if ( bRelToTableCell )
+ {
+ _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
+ }
+ // <--
+ }
+ else if ( eHoriConv == CONV2COL )
+ {
+ _iorHoriOri.SetRelationOrient( text::RelOrientation::FRAME );
+ aPos = pAnchoredObj->GetRelPosToAnchorFrm();
+ }
+ else if ( eHoriConv == CONV2CHAR )
+ {
+ _iorHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
+ aPos = pAnchoredObj->GetRelPosToChar();
+ }
+ // No distinction between layout directions, because of missing
+ // information about WW8 in vertical layout.
+ nPosX = aPos.X();
+ }
+ _iorHoriOri.SetPos( nPosX );
+ bConverted = true;
+ }
+ }
+
+ // convert vertical position, if needed
+ {
+ enum VertConv { NO_CONV, CONV2PG, CONV2PARA, CONV2LINE };
+ VertConv eVertConv( NO_CONV );
+
+ // determine, if conversion has to be performed due to the position orientation
+ bool bConvDueToOrientation( false );
+ {
+ const sal_Int16 eVOri = _iorVertOri.GetVertOrient();
+ bConvDueToOrientation = ( eVOri == text::VertOrientation::TOP ||
+ eVOri == text::VertOrientation::BOTTOM ||
+ eVOri == text::VertOrientation::CHAR_TOP ||
+ eVOri == text::VertOrientation::CHAR_BOTTOM ||
+ eVOri == text::VertOrientation::CHAR_CENTER ||
+ eVOri == text::VertOrientation::LINE_TOP ||
+ eVOri == text::VertOrientation::LINE_BOTTOM ||
+ eVOri == text::VertOrientation::LINE_CENTER );
+ }
+
+ // determine conversion type due to the position relation
+ // --> OD 2007-07-24 #148096#
+ if ( bConvDueToAnchoredAtColBreakPara )
+ {
+ eVertConv = CONV2PG;
+ }
+ else
+ {
+ switch ( _iorVertOri.GetRelationOrient() )
+ {
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ if ( bConvDueToOrientation || bFollowTextFlow )
+ eVertConv = CONV2PG;
+ }
+ break;
+ case text::RelOrientation::FRAME:
+ {
+ if ( bConvDueToOrientation ||
+ _iorVertOri.GetVertOrient() == text::VertOrientation::CENTER )
+ {
+ eVertConv = CONV2PARA;
+ }
+ }
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ {
+ // relation not supported by WW8. Thus, conversion always needed.
+ eVertConv = CONV2PARA;
+ }
+ break;
+ case text::RelOrientation::CHAR:
+ {
+ // relation not supported by WW8. Thus, conversion always needed.
+ eVertConv = CONV2PARA;
+ }
+ break;
+ case text::RelOrientation::TEXT_LINE:
+ {
+ if ( bConvDueToOrientation ||
+ _iorVertOri.GetVertOrient() == text::VertOrientation::NONE )
+ {
+ eVertConv = CONV2LINE;
+ }
+ }
+ break;
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_LEFT:
+ case text::RelOrientation::FRAME_RIGHT:
+ default:
+ ASSERT( false,
+ "<WinwordAnchoring::ConvertPosition(..)> - unknown vertical relation" );
+ }
+ }
+ // <--
+ if ( eVertConv != NO_CONV )
+ {
+ _iorVertOri.SetVertOrient( text::VertOrientation::NONE );
+ SwTwips nPosY( 0L );
+ {
+ Point aPos;
+ if ( eVertConv == CONV2PG )
+ {
+ _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
+ // --> OD 2005-01-27 #i33818#
+ bool bRelToTableCell( false );
+ aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
+ bRelToTableCell );
+ if ( bRelToTableCell )
+ {
+ _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
+ }
+ // <--
+ }
+ else if ( eVertConv == CONV2PARA )
+ {
+ _iorVertOri.SetRelationOrient( text::RelOrientation::FRAME );
+ aPos = pAnchoredObj->GetRelPosToAnchorFrm();
+ }
+ else if ( eVertConv == CONV2LINE )
+ {
+ _iorVertOri.SetRelationOrient( text::RelOrientation::TEXT_LINE );
+ aPos = pAnchoredObj->GetRelPosToLine();
+ }
+ // No distinction between layout directions, because of missing
+ // information about WW8 in vertical layout.
+ nPosY = aPos.Y();
+ }
+ _iorVertOri.SetPos( nPosY );
+ bConverted = true;
+ }
+ }
+
+ return bConverted;
+}
+
+void WinwordAnchoring::SetAnchoring(const SwFrmFmt& rFmt)
+{
+ const RndStdIds eAnchor = rFmt.GetAnchor().GetAnchorId();
+ mbInline = (eAnchor == FLY_IN_CNTNT);
+
+ SwFmtHoriOrient rHoriOri = rFmt.GetHoriOrient();
+ SwFmtVertOrient rVertOri = rFmt.GetVertOrient();
+
+ // --> OD 2005-01-06 #i30669# - convert the positioning attributes.
+ // Most positions are converted, if layout information exists.
+ const bool bPosConverted = ConvertPosition( rHoriOri, rVertOri, rFmt );
+ // <--
+
+ const sal_Int16 eHOri = rHoriOri.GetHoriOrient();
+ // CMC, OD 24.11.2003 #i22673#
+ const sal_Int16 eVOri = rVertOri.GetVertOrient();
+
+ const sal_Int16 eHRel = rHoriOri.GetRelationOrient();
+ const sal_Int16 eVRel = rVertOri.GetRelationOrient();
+
+ // horizontal Adjustment
+ switch (eHOri)
+ {
+ default:
+ case text::HoriOrientation::NONE:
+ mnXAlign = 0;
+ break;
+ case text::HoriOrientation::LEFT:
+ mnXAlign = 1;
+ break;
+ case text::HoriOrientation::CENTER:
+ mnXAlign = 2;
+ break;
+ case text::HoriOrientation::RIGHT:
+ mnXAlign = 3;
+ break;
+ case text::HoriOrientation::INSIDE:
+ mnXAlign = 4;
+ break;
+ case text::HoriOrientation::OUTSIDE:
+ mnXAlign = 5;
+ break;
+ }
+
+ // vertical Adjustment
+ // CMC, OD 24.11.2003 #i22673#
+ // When adjustment is vertically relative to line or to char
+ // bottom becomes top and vice versa
+ const bool bVertSwap = !bPosConverted &&
+ ( (eVRel == text::RelOrientation::CHAR) ||
+ (eVRel == text::RelOrientation::TEXT_LINE) );
+ switch (eVOri)
+ {
+ default:
+ case text::VertOrientation::NONE:
+ mnYAlign = 0;
+ break;
+ case text::VertOrientation::TOP:
+ case text::VertOrientation::LINE_TOP:
+ case text::VertOrientation::CHAR_TOP:
+ mnYAlign = bVertSwap ? 3 : 1;
+ break;
+ case text::VertOrientation::CENTER:
+ case text::VertOrientation::LINE_CENTER:
+ mnYAlign = 2;
+ break;
+ case text::VertOrientation::BOTTOM:
+ case text::VertOrientation::LINE_BOTTOM:
+ case text::VertOrientation::CHAR_BOTTOM:
+ mnYAlign = bVertSwap ? 1 : 3;
+ break;
+ }
+
+ // Adjustment is horizontally relative to...
+ switch (eHRel)
+ {
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ mnXRelTo = 0;
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_LEFT: //:-(
+ case text::RelOrientation::PAGE_RIGHT: //:-(
+ mnXRelTo = 1;
+ break;
+ case text::RelOrientation::FRAME:
+ case text::RelOrientation::FRAME_LEFT: //:-(
+ case text::RelOrientation::FRAME_RIGHT: //:-(
+ if (eAnchor == FLY_PAGE)
+ mnXRelTo = 1;
+ else
+ mnXRelTo = 2;
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ if (eAnchor == FLY_PAGE)
+ mnXRelTo = 0;
+ else
+ mnXRelTo = 2;
+ break;
+ case text::RelOrientation::CHAR:
+ mnXRelTo = 3;
+ break;
+ case text::RelOrientation::TEXT_LINE:
+ break;
+ }
+
+ // Adjustment is vertically relative to...
+ switch (eVRel)
+ {
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ mnYRelTo = 0;
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ mnYRelTo = 1;
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ if (eAnchor == FLY_PAGE)
+ mnYRelTo = 0;
+ else
+ mnYRelTo = 2;
+ break;
+ case text::RelOrientation::FRAME:
+ if (eAnchor == FLY_PAGE)
+ mnYRelTo = 1;
+ else
+ mnYRelTo = 2;
+ break;
+ case text::RelOrientation::CHAR:
+ case text::RelOrientation::TEXT_LINE: // CMC, OD 24.11.2003 #i22673# - vertical alignment at top of line
+ case text::RelOrientation::PAGE_LEFT: //nonsense
+ case text::RelOrientation::PAGE_RIGHT: //nonsense
+ case text::RelOrientation::FRAME_LEFT: //nonsense
+ case text::RelOrientation::FRAME_RIGHT: //nonsense
+ mnYRelTo = 3;
+ break;
+ }
+}
+
+void SwEscherEx::WriteFrmExtraData( const SwFrmFmt& rFmt )
+{
+ aWinwordAnchoring.SetAnchoring(rFmt);
+ aWinwordAnchoring.WriteData(*this);
+
+ AddAtom(4, ESCHER_ClientAnchor);
+ GetStream() << 0L;
+
+ AddAtom(4, ESCHER_ClientData);
+ GetStream() << 1L;
+}
+
+INT32 SwEscherEx::WriteFlyFrm(const DrawObj &rObj, UINT32 &rShapeId,
+ DrawObjPointerVector &rPVec)
+{
+ const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
+
+ // check for textflyframe and if it is the first in a Chain
+ INT32 nBorderThick = 0;
+ const SwNodeIndex* pNdIdx = rFmt.GetCntnt().GetCntntIdx();
+ if( pNdIdx )
+ {
+ SwNodeIndex aIdx( *pNdIdx, 1 );
+ switch( aIdx.GetNode().GetNodeType() )
+ {
+ case ND_GRFNODE:
+ nBorderThick = WriteGrfFlyFrame( rFmt, rShapeId = GetShapeID() );
+ break;
+ case ND_OLENODE:
+ nBorderThick = WriteOLEFlyFrame( rFmt, rShapeId = GetShapeID() );
+ break;
+ default:
+ if (const SdrObject* pObj = rFmt.FindRealSdrObject())
+ {
+ // check for the first in a Chain
+ UINT32 nTxtId;
+ USHORT nOff = 0;
+ const SwFrmFmt* pFmt = &rFmt, *pPrev;
+ while( 0 != ( pPrev = pFmt->GetChain().GetPrev() ))
+ {
+ ++nOff;
+ pFmt = pPrev;
+ }
+
+ rShapeId = GetFlyShapeId(rFmt, rObj.mnHdFtIndex, rPVec);
+ if( !nOff )
+ {
+ void* p = (void*)pObj;
+ nTxtId = pTxtBxs->GetPos( p );
+ if( USHRT_MAX == nTxtId )
+ {
+ pTxtBxs->Append( *pObj, rShapeId );
+ nTxtId = pTxtBxs->Count();
+ }
+ else
+ ++nTxtId;
+ }
+ else
+ {
+ const SdrObject* pPrevObj = pFmt->FindRealSdrObject();
+ void* p = (void*)pPrevObj;
+ nTxtId = pTxtBxs->GetPos( p );
+ if( USHRT_MAX == nTxtId )
+ {
+ UINT32 nPrevShapeId =
+ GetFlyShapeId(*pFmt, rObj.mnHdFtIndex, rPVec);
+ pTxtBxs->Append( *pPrevObj, nPrevShapeId );
+ nTxtId = pTxtBxs->Count();
+ }
+ else
+ ++nTxtId;
+ }
+ nTxtId *= 0x10000;
+ nTxtId += nOff;
+
+ nBorderThick = WriteTxtFlyFrame(rObj, rShapeId, nTxtId, rPVec);
+ }
+ }
+ }
+ return nBorderThick;
+}
+
+USHORT FindPos(const SwFrmFmt &rFmt, unsigned int nHdFtIndex,
+ DrawObjPointerVector &rPVec)
+{
+ DrawObjPointerIter aEnd = rPVec.end();
+ for (DrawObjPointerIter aIter = rPVec.begin(); aIter != aEnd; ++aIter)
+ {
+ const DrawObj *pObj = (*aIter);
+ ASSERT(pObj, "Impossible");
+ if (!pObj)
+ continue;
+ if (
+ nHdFtIndex == pObj->mnHdFtIndex &&
+ &rFmt == (&pObj->maCntnt.GetFrmFmt())
+ )
+ {
+ return static_cast< USHORT >(aIter - rPVec.begin());
+ }
+ }
+ return USHRT_MAX;
+}
+
+INT32 SwEscherEx::WriteTxtFlyFrame(const DrawObj &rObj, UINT32 nShapeId,
+ UINT32 nTxtBox, DrawObjPointerVector &rPVec)
+{
+ const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
+ short nDirection = rObj.mnDirection;
+
+ INT32 nBorderThick=0;
+ OpenContainer( ESCHER_SpContainer );
+
+ AddShape( ESCHER_ShpInst_TextBox, 0xa00, nShapeId );
+ EscherPropertyContainer aPropOpt;
+ aPropOpt.AddOpt(ESCHER_Prop_lTxid, nTxtBox);
+ if (const SwFrmFmt *pNext = rFmt.GetChain().GetNext())
+ {
+ USHORT nPos = FindPos(*pNext, rObj.mnHdFtIndex, rPVec);
+ if (USHRT_MAX != nPos && aFollowShpIds[nPos])
+ aPropOpt.AddOpt(ESCHER_Prop_hspNext, aFollowShpIds[nPos]);
+ }
+ nBorderThick = WriteFlyFrameAttr( rFmt, mso_sptTextBox, aPropOpt );
+
+ MSO_TextFlow nFlow;
+
+ switch (nDirection)
+ {
+ default:
+ ASSERT(!this, "unknown direction type");
+ case FRMDIR_HORI_LEFT_TOP:
+ nFlow=mso_txflHorzN;
+ break;
+ case FRMDIR_HORI_RIGHT_TOP:
+ nFlow=mso_txflHorzN;
+ break;
+ case FRMDIR_VERT_TOP_LEFT: //not really possible in word
+ case FRMDIR_VERT_TOP_RIGHT:
+ nFlow=mso_txflTtoBA;
+ break;
+ }
+ aPropOpt.AddOpt( ESCHER_Prop_txflTextFlow, nFlow );
+
+ aPropOpt.Commit( GetStream() );
+
+ // store anchor attribute
+ WriteFrmExtraData( rFmt );
+
+ AddAtom( 4, ESCHER_ClientTextbox ); GetStream() << nTxtBox;
+
+ CloseContainer(); // ESCHER_SpContainer
+ return nBorderThick;
+}
+
+void SwBasicEscherEx::WriteOLEPicture(EscherPropertyContainer &rPropOpt,
+ sal_uInt32 nShapeFlags, const Graphic &rGraphic, const SdrObject &rObj,
+ sal_uInt32 nShapeId, const awt::Rectangle* pVisArea )
+{
+ //nShapeFlags == 0xA00 + flips and ole active
+ AddShape(ESCHER_ShpInst_PictureFrame, nShapeFlags, nShapeId);
+
+ GraphicObject aGraphicObject(rGraphic);
+ ByteString aId = aGraphicObject.GetUniqueID();
+ if (aId.Len())
+ {
+ Rectangle aRect = rObj.GetLogicRect();
+ aRect.SetPos(Point(0,0));
+ aRect.Right() = DrawModelToEmu(aRect.Right());
+ aRect.Bottom() = DrawModelToEmu(aRect.Bottom());
+ sal_uInt32 nBlibId = GetBlibID(*QueryPicStream(), aId, aRect, pVisArea, 0); // SJ: the fourth parameter (VisArea) should be set..
+ if (nBlibId)
+ rPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
+ }
+
+ SetPicId(rObj, nShapeId, rPropOpt);
+ rPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0x10000 );
+}
+
+void SwEscherEx::WriteOCXControl( const SwFrmFmt& rFmt, UINT32 nShapeId )
+{
+ if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
+ {
+ OpenContainer( ESCHER_SpContainer );
+
+ SdrModel *pModel = rWrt.pDoc->GetDrawModel();
+ OutputDevice *pDevice = Application::GetDefaultDevice();
+ ASSERT(pModel && pDevice, "no model or device");
+
+ // #i71538# use complete SdrViews
+ // SdrExchangeView aExchange(pModel, pDevice);
+ SdrView aExchange(pModel, pDevice);
+
+ Graphic aGraphic(aExchange.GetObjGraphic(pModel, pSdrObj));
+
+ EscherPropertyContainer aPropOpt;
+ WriteOLEPicture(aPropOpt, 0xa00 | SHAPEFLAG_OLESHAPE, aGraphic,
+ *pSdrObj, nShapeId, NULL );
+
+ WriteFlyFrameAttr( rFmt, mso_sptPictureFrame , aPropOpt );
+ aPropOpt.Commit( GetStream() );
+
+ // store anchor attribute
+ WriteFrmExtraData( rFmt );
+
+ CloseContainer(); // ESCHER_SpContainer
+ }
+}
+
+void SwEscherEx::MakeZOrderArrAndFollowIds(
+ std::vector<DrawObj>& rSrcArr, std::vector<DrawObj*>&rDstArr)
+{
+ USHORT n, nCnt = static_cast< USHORT >(rSrcArr.size());
+ SvULongsSort aSort( 255 < nCnt ? 255 : nCnt, 255 );
+ rDstArr.clear();
+ rDstArr.reserve(nCnt);
+ for (n = 0; n < nCnt; ++n)
+ {
+ const SwFrmFmt &rFmt = rSrcArr[n].maCntnt.GetFrmFmt();
+ ULONG nOrdNum = rWrt.GetSdrOrdNum(rFmt);
+ USHORT nPos;
+ //returns what will be the index in rDstArr of p as nPos
+ aSort.Insert(nOrdNum, nPos);
+ DrawObj &rObj = rSrcArr[n];
+ rDstArr.insert(rDstArr.begin() + nPos, &rObj);
+ }
+
+ if (aFollowShpIds.Count())
+ aFollowShpIds.Remove(0, aFollowShpIds.Count());
+
+ for (n = 0; n < nCnt; ++n)
+ {
+ const SwFrmFmt &rFmt = rDstArr[n]->maCntnt.GetFrmFmt();
+ bool bNeedsShapeId = false;
+
+ if (RES_FLYFRMFMT == rFmt.Which())
+ {
+ const SwFmtChain &rChain = rFmt.GetChain();
+ if (rChain.GetPrev() || rChain.GetNext())
+ bNeedsShapeId = true;
+ }
+
+ ULONG nShapeId = bNeedsShapeId ? GetShapeID() : 0;
+
+ aFollowShpIds.Insert(nShapeId, n);
+ }
+}
+
+UINT32 SwEscherEx::GetFlyShapeId(const SwFrmFmt& rFmt,
+ unsigned int nHdFtIndex, DrawObjPointerVector &rpVec)
+{
+ USHORT nPos = FindPos(rFmt, nHdFtIndex, rpVec);
+ UINT32 nShapeId;
+ if (USHRT_MAX != nPos)
+ {
+ if (0 == (nShapeId = aFollowShpIds[nPos]))
+ {
+ nShapeId = GetShapeID();
+ aFollowShpIds[ nPos ] = nShapeId;
+ }
+ }
+ else
+ nShapeId = GetShapeID();
+ return nShapeId;
+}
+
+UINT32 SwEscherEx::QueryTextID(
+ const uno::Reference< drawing::XShape>& xXShapeRef, UINT32 nShapeId )
+{
+ UINT32 nId = 0;
+ if (SdrObject* pObj = GetSdrObjectFromXShape(xXShapeRef))
+ {
+ pTxtBxs->Append( *pObj, nShapeId );
+ nId = pTxtBxs->Count();
+ nId *= 0x10000;
+ }
+ return nId;
+}
+
+bool SwMSConvertControls::ExportControl(WW8Export &rWW8Wrt, const SdrObject *pObj)
+{
+ if (!rWW8Wrt.bWrtWW8)
+ return false;
+
+ SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObj);
+ uno::Reference< awt::XControlModel > xControlModel =
+ pFormObj->GetUnoControlModel();
+
+ //Why oh lord do we use so many different units ?
+ //I think I painted myself into a little bit of a
+ //corner by trying to use the uno interface for
+ //controls export
+ Rectangle aRect = pFormObj->GetLogicRect();
+ aRect.SetPos(Point(0,0));
+ awt::Size aSize;
+ aSize.Width = TWIPS_TO_MM(aRect.Right());
+ aSize.Height = TWIPS_TO_MM(aRect.Bottom());
+
+ //Open the ObjectPool
+ SvStorageRef xObjPool = rWW8Wrt.GetWriter().GetStorage().OpenSotStorage(
+ CREATE_CONST_ASC(SL::aObjectPool), STREAM_READWRITE |
+ STREAM_SHARE_DENYALL);
+
+ //Create a destination storage for the microsoft control
+ String sStorageName('_');
+ sStorageName += String::CreateFromInt32((sal_uInt32)(sal_uIntPtr)pObj);
+ SvStorageRef xOleStg = xObjPool->OpenSotStorage(sStorageName,
+ STREAM_READWRITE|STREAM_SHARE_DENYALL);
+
+ if (!xOleStg.Is())
+ return false;
+
+ String sName;
+ if (!WriteOCXStream(xOleStg,xControlModel,aSize,sName))
+ return false;
+
+ BYTE aSpecOLE[] =
+ {
+ 0x03, 0x6a, 0xFF, 0xFF, 0xFF, 0xFF, // sprmCPicLocation
+ 0x0a, 0x08, 1, // sprmCFOLE2
+ 0x55, 0x08, 1, // sprmCFSpec
+ 0x56, 0x08, 1 // sprmCFObj
+ };
+ //Set the obj id into the sprmCPicLocation
+ BYTE *pData = aSpecOLE+2;
+ Set_UInt32(pData,(sal_uInt32)(sal_uIntPtr)pObj);
+
+ String sFld(FieldString(ww::eCONTROL));
+ sFld.APPEND_CONST_ASC("Forms.");
+ sFld += sName;
+ sFld.APPEND_CONST_ASC(".1 \\s ");
+
+ rWW8Wrt.OutputField(0, ww::eCONTROL, sFld,
+ WRITEFIELD_START|WRITEFIELD_CMD_START|WRITEFIELD_CMD_END);
+
+ rWW8Wrt.pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell(),sizeof(aSpecOLE),
+ aSpecOLE);
+ rWW8Wrt.WriteChar( 0x1 );
+ rWW8Wrt.OutputField(0, ww::eCONTROL, aEmptyStr, WRITEFIELD_END | WRITEFIELD_CLOSE);
+ return true;
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */