blob: 5d4f589b7340314d6781857967dfcc9fb19bcce7 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the 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 <svl/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 <svl/itemiter.hxx>
#include <svx/svdobj.hxx>
#include <svx/svdotext.hxx>
#include <svx/svdmodel.hxx>
#include <svx/svdpage.hxx>
#include <editeng/outlobj.hxx>
#include <editeng/editobj.hxx>
#include <svx/unoshape.hxx>
#include <editeng/brshitem.hxx>
#include <editeng/boxitem.hxx>
#include <editeng/lrspitem.hxx>
#include <editeng/ulspitem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/frmdiritem.hxx>
#include <svx/svdoole2.hxx>
#include <editeng/editeng.hxx>
#ifndef _SVX_FLDITEM_HXX
//miserable hack to get around #98519#
#include <editeng/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"
#include <editeng/shaditem.hxx>
#include <svx/unoapi.hxx>
#include <escher.hxx>
#include <fmtinfmt.hxx>
#include <fmturl.hxx>
#include "sfx2/sfxsids.hrc"
#include <svl/urihelper.hxx>
#include <unotools/saveopt.hxx>
using namespace com::sun::star;
using namespace sw::util;
using namespace sw::types;
using namespace nsFieldFlags;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::UNO_QUERY;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::drawing::XShape;
bool SwBasicEscherEx::IsRelUrl()
{
SvtSaveOptions aSaveOpt;
bool bRelUrl = false;
SfxMedium * pMedium = rWrt.GetWriter().GetMedia();
if ( pMedium )
bRelUrl = pMedium->IsRemote() ? aSaveOpt.IsSaveRelINet() : aSaveOpt.IsSaveRelFSys();
return bRelUrl;
}
String SwBasicEscherEx::GetBasePath()
{
String sDocUrl;
String sBasePath;
SfxMedium * pMedium = rWrt.GetWriter().GetMedia();
if ( pMedium )
{
const SfxItemSet* pPItemSet = pMedium->GetItemSet();
if( pPItemSet )
{
const SfxStringItem* pPItem = dynamic_cast< const SfxStringItem* >( pPItemSet->GetItem( SID_FILE_NAME ) );
if ( pPItem )
sDocUrl = pPItem->GetValue();
}
}
sBasePath = sDocUrl.Copy( 0, sDocUrl.SearchBackward( '/' ) + 1 );
return sBasePath;
}
String SwBasicEscherEx::BuildFileName(sal_uInt16& rnLevel, bool& rbRel, const String& rUrl )
{
String aDosName( INetURLObject( rUrl ).getFSysPath( INetURLObject::FSYS_DOS ) );
rnLevel = 0;
rbRel = IsRelUrl();
if( rbRel )
{
// try to convert to relative file name
String aTmpName( aDosName );
aDosName = INetURLObject::GetRelURL( GetBasePath(), rUrl,
INetURLObject::WAS_ENCODED, INetURLObject::DECODE_WITH_CHARSET );
if( aDosName.SearchAscii( INET_FILE_SCHEME ) == 0 )
{
// not converted to rel -> back to old, return absolute flag
aDosName = aTmpName;
rbRel = false;
}
else if( aDosName.SearchAscii( "./" ) == 0 )
{
aDosName.Erase( 0, 2 );
}
else
{
while( aDosName.SearchAndReplaceAscii( "../", String::EmptyString() ) == 0 )
++rnLevel;
}
}
return aDosName;
}
void SwBasicEscherEx::WriteHyperlinkWithinFly( SvMemoryStream& rStrm, const SwFmtURL* pINetFmtArg)
{
if ( !pINetFmtArg ) return;
sal_uInt8 maGuidStdLink[ 16 ] ={
0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
sal_uInt8 maGuidUrlMoniker[ 16 ] = {
0xE0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
sal_uInt8 maGuidFileMoniker[ 16 ] = {
0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
sal_uInt8 maGuidFileTail[] = {
0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//const sal_uInt16 WW8_ID_HLINK = 0x01B8;
const sal_uInt32 WW8_HLINK_BODY = 0x00000001; /// Contains file link or URL.
const sal_uInt32 WW8_HLINK_ABS = 0x00000002; /// Absolute path.
//const sal_uInt32 WW8_HLINK_DESCR = 0x00000014; /// Description.
const sal_uInt32 WW8_HLINK_MARK = 0x00000008; /// Text mark.
const sal_uInt32 WW8_HLINK_FRAME = 0x00000080; /// Target frame.
//const sal_uInt32 WW8_HLINK_UNC = 0x00000100; /// UNC path.
SvMemoryStream tmpStrm;
String tmpTextMark;
String rUrl = pINetFmtArg->GetURL();
String rTarFrm = pINetFmtArg->GetTargetFrameName();
sal_uInt32 mnFlags = 0;
INetURLObject aUrlObj( rUrl );
const INetProtocol eProtocol = aUrlObj.GetProtocol();
//Target Frame
if( rTarFrm.Len() > 0 )
{
SwWW8Writer::WriteLong( tmpStrm, rTarFrm.Len()+1 );
SwWW8Writer::WriteString16( tmpStrm, rTarFrm, false);
tmpStrm << sal_uInt16( 0 );
mnFlags |= WW8_HLINK_FRAME;
}
// file link or URL
if( eProtocol == INET_PROT_FILE || (eProtocol == INET_PROT_NOT_VALID && rUrl.GetChar( 0 ) != '#') )
{
sal_uInt16 nLevel;
bool bRel;
String aFileName( BuildFileName( nLevel, bRel, rUrl ));
if( !bRel )
mnFlags |= WW8_HLINK_ABS;
mnFlags |= WW8_HLINK_BODY;
tmpStrm.Write( maGuidFileMoniker,sizeof(maGuidFileMoniker) );
tmpStrm << nLevel;
SwWW8Writer::WriteLong( tmpStrm, aFileName.Len()+1);
SwWW8Writer::WriteString8( tmpStrm, aFileName, true, RTL_TEXTENCODING_MS_1252 );
tmpStrm.Write( maGuidFileTail,sizeof(maGuidFileTail) );
//For UNICODE
SwWW8Writer::WriteLong( tmpStrm, 2*aFileName.Len()+6);
SwWW8Writer::WriteLong( tmpStrm, 2*aFileName.Len());
tmpStrm << sal_uInt16(0x0003);
SwWW8Writer::WriteString16(tmpStrm, aFileName, false);
}
else if( eProtocol != INET_PROT_NOT_VALID )
{
tmpStrm.Write( maGuidUrlMoniker,sizeof(maGuidUrlMoniker) );
SwWW8Writer::WriteLong( tmpStrm, 2*(rUrl.Len()+1));
SwWW8Writer::WriteString16(tmpStrm, rUrl, true);
mnFlags |= WW8_HLINK_BODY | WW8_HLINK_ABS;
}
else if( rUrl.GetChar( 0 ) == '#' )
{
String aTextMark( rUrl.Copy( 1 ) );
aTextMark.SearchAndReplace( '.', '!' );
//sal_uInt8 tmpLen = aTextMark.Len();
tmpTextMark = aTextMark;
}
if( tmpTextMark.Len() == 0 && aUrlObj.HasMark() )
{
tmpTextMark = aUrlObj.GetMark();
}
if( tmpTextMark.Len()>0 )
{
SwWW8Writer::WriteLong( tmpStrm, tmpTextMark.Len()+1);
SwWW8Writer::WriteString16(tmpStrm, tmpTextMark, true);
mnFlags |= WW8_HLINK_MARK;
}
rStrm.Write( maGuidStdLink,16 );
rStrm << sal_uInt32( 2 )
<< mnFlags;
tmpStrm.Seek( STREAM_SEEK_TO_BEGIN );
sal_uInt32 nStrmPos = tmpStrm.Tell();
tmpStrm.Seek( STREAM_SEEK_TO_END );
sal_uInt32 nStrmSize = tmpStrm.Tell();
tmpStrm.Seek( nStrmPos );
sal_uInt32 nLen;
nLen = nStrmSize - nStrmPos;
if(nLen >0)
{
sal_uInt8* pBuffer = new sal_uInt8[ nLen ];
tmpStrm.Read(pBuffer, nLen);
rStrm.Write( pBuffer, nLen );
delete[] pBuffer;
}
}
void SwBasicEscherEx::PreWriteHyperlinkWithinFly(const SwFrmFmt& rFmt,EscherPropertyContainer& rPropOpt)
{
const SfxPoolItem* pItem;
const SwAttrSet& rAttrSet = rFmt.GetAttrSet();
if (SFX_ITEM_SET == rAttrSet.GetItemState(RES_URL, true, &pItem))
{
const SwFmtURL *pINetFmt = dynamic_cast<const SwFmtURL*>(pItem);
if(pINetFmt && pINetFmt->GetURL().Len()>0)
{
SvMemoryStream *rStrm = new SvMemoryStream ;
String tmpstr=pINetFmt->GetURL();
WriteHyperlinkWithinFly( *rStrm, pINetFmt );
sal_uInt8* pBuf = (sal_uInt8*) rStrm->GetData();
sal_uInt32 nSize = rStrm->Seek( STREAM_SEEK_TO_END );
rPropOpt.AddOpt( ESCHER_Prop_pihlShape, sal_True, nSize, pBuf, nSize );
sal_uInt32 nValue;
String aNamestr = pINetFmt->GetName();
if(aNamestr.Len()>0)
{
rPropOpt.AddOpt(ESCHER_Prop_wzName, aNamestr );
}
if(rPropOpt.GetOpt( ESCHER_Prop_fPrint, nValue))
{
nValue|=0x03080008;
rPropOpt.AddOpt(ESCHER_Prop_fPrint, nValue );
}
else
rPropOpt.AddOpt(ESCHER_Prop_fPrint, 0x03080008 );
}
}
}
//#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;
{
// --> OD 2010-05-14 #160026#
// property "Help" does not exist and due to the no-existence an exception is thrown.
// uno::Any aTmp = xPropSet->getPropertyValue(C2U("Help"));
try
{
uno::Any aTmp = xPropSet->getPropertyValue(C2U("HelpText"));
// <--
const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
if (pStr)
sHelp = *pStr;
}
catch( uno::Exception& )
{}
// <--
}
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
sal_uLong nDataStt = pDataStrm->Tell();
pChpPlc->AppendFkpEntry( Strm().Tell() );
WriteChar( 0x01 );
static sal_uInt8 aArr1[] =
{
0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
0x06, 0x08, 0x01, // sprmCFData
0x55, 0x08, 0x01, // sprmCFSpec
0x02, 0x08, 0x01 // sprmCFFldVanish
};
sal_uInt8* 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
sal_uLong nDataStt = pDataStrm->Tell();
pChpPlc->AppendFkpEntry( Strm().Tell() );
WriteChar( 0x01 );
static sal_uInt8 aArr1[] = {
0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
0x06, 0x08, 0x01, // sprmCFData
0x55, 0x08, 0x01, // sprmCFSpec
0x02, 0x08, 0x01 // sprmCFFldVanish
};
sal_uInt8* 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;
aFFData.setDefaultResult(nTemp);
xPropSet->getPropertyValue(C2U("State")) >>= nTemp;
aFFData.setResult(nTemp);
::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
sal_uLong nDataStt = pDataStrm->Tell();
pChpPlc->AppendFkpEntry( Strm().Tell() );
WriteChar( 0x01 );
static sal_uInt8 aArr1[] = {
0x02, 0x08, 0x81, // sprmCFFldVanish
0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
0x06, 0x08, 0x01, // sprmCFData
0x55, 0x08, 0x01 // sprmCFSpec
};
sal_uInt8* 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);
const String fieldStr( pFld->ExpandField(true) );
SwWW8Writer::WriteString16(Strm(), fieldStr, false);
static sal_uInt8 aArr2[] = {
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 );
}
// <--
sal_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
sal_uInt16 nFlags=0;
//If nFlags isn't 0x14 its overridden by the escher properties
if (FLY_AT_PAGE == rFmt.GetAnchor().GetAnchorId())
nFlags = 0x0000;
else
nFlags = 0x0014; // x-rel to text, y-rel to text
const SwFmtSurround& rSurr = rFmt.GetSurround();
sal_uInt16 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(sal_uInt32 nId, sal_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, sal_uInt32 nShapeId )
{
void* p = (void*)&rObj;
aCntnt.Insert( p, aCntnt.Count() );
aShapeIds.Insert( nShapeId, aShapeIds.Count() );
//save NULL, if we have an actual SdrObject
aSpareFmts.Insert( (void*)NULL, aSpareFmts.Count() );
}
void WW8_WrPlcTxtBoxes::Append( const SwFrmFmt* pFmt, sal_uInt32 nShapeId )
{
//no sdr object, we insert a NULL in the aCntnt and save the real fmt in aSpareFmts.
aCntnt.Insert( (void*)NULL, aCntnt.Count() );
aShapeIds.Insert( nShapeId, aShapeIds.Count() );
aSpareFmts.Insert( (void*)pFmt, aSpareFmts.Count() );
}
const SvULongs* WW8_WrPlcTxtBoxes::GetShapeIdArr() const
{
return &aShapeIds;
}
/* */
sal_uInt32 WW8Export::GetSdrOrdNum( const SwFrmFmt& rFmt ) const
{
sal_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);
}
MSWord_SdrAttrIter::MSWord_SdrAttrIter( MSWordExportBase& rWr,
const EditTextObject& rEditObj, sal_uInt8 nTyp )
: MSWordAttrIter( rWr ), pEditObj(&rEditObj), pEditPool(0),
aTxtAtrArr( 0, 4 ), aChrTxtAtrArr( 0, 4 ), aChrSetArr( 0, 4 ),
mnTyp(nTyp)
{
NextPara( 0 );
}
void MSWord_SdrAttrIter::NextPara( sal_uInt16 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 MSWord_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 MSWord_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 MSWord_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 )
{
sal_uInt16 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 MSWord_SdrAttrIter::OutEEField(const SfxPoolItem& rHt)
{
const SvxFieldItem &rField = (const SvxFieldItem &)rHt;
const SvxFieldData *pFld = rField.GetField();
if (pFld && pFld->ISA(SvxURLField))
{
sal_uInt8 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 MSWord_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;
sal_uInt16 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 MSWord_SdrAttrIter::IsTxtAttr(xub_StrLen nSwPos)
{
for (sal_uInt16 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* MSWord_SdrAttrIter::HasTextItem(sal_uInt16 nWhich) const
{
const SfxPoolItem* pRet = 0;
nWhich = sw::hack::TransformWhichBetweenPools(*pEditPool,
m_rExport.pDoc->GetAttrPool(), nWhich);
if (nWhich)
{
for (sal_uInt16 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& MSWord_SdrAttrIter::GetItem( sal_uInt16 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 MSWord_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 {
sal_uInt16 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, sal_uInt8 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, sal_uInt8 nTyp)
{
bool bAnyWrite = false;
const EditTextObject& rEditObj = rParaObj.GetTextObject();
MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
sal_uInt16 nPara = rEditObj.GetParagraphCount();
sal_uInt8 bNul = 0;
for( sal_uInt16 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);
sal_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 << (sal_uInt16)0x0390 << sal_uInt32(3);
rSt << (sal_uInt16)0x0392 << sal_uInt32(3);
//This sub property is required to be in the dummy inline frame as
//well
rSt << (sal_uInt16)0x053F << nInlineHack;
}
else
{
rEx.AddAtom(24, DFF_msofbtUDefProp, 3, 4 ); //Prop id is 0xF122
rSt << (sal_uInt16)0x038F << mnXAlign;
rSt << (sal_uInt16)0x0390 << mnXRelTo;
rSt << (sal_uInt16)0x0391 << mnYAlign;
rSt << (sal_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)
{
sal_uLong nStart = pTableStrm->Tell();
pEscher->WritePictures();
pEscher->FinishEscher();
pFib->fcDggInfo = nStart;
pFib->lcbDggInfo = pTableStrm->Tell() - nStart;
delete pEscher, pEscher = 0;
}
}
void SwEscherEx::WritePictures()
{
if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
{
// set the blip - entries to the correct stream pos
sal_Int32 nEndPos = rWrt.Strm().Tell();
mxGlobal->SetNewBlipStreamOffset( nEndPos );
pPicStrm->Seek( 0 );
rWrt.Strm() << *pPicStrm;
}
Flush();
}
/* */
// Output- Routines for Escher Export
SwEscherExGlobal::SwEscherExGlobal()
{
}
SwEscherExGlobal::~SwEscherExGlobal()
{
}
SvStream* SwEscherExGlobal::ImplQueryPictureStream()
{
// this function will be called exactly once
mxPicStrm.reset( new SvMemoryStream );
mxPicStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
return mxPicStrm.get();
}
SwBasicEscherEx::SwBasicEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
: EscherEx( EscherExGlobalRef( new SwEscherExGlobal ), *pStrm), rWrt(rWW8Wrt), pEscherStrm(pStrm)
{
Init();
}
SwBasicEscherEx::~SwBasicEscherEx()
{
}
void SwBasicEscherEx::WriteFrmExtraData(const SwFrmFmt&)
{
AddAtom(4, ESCHER_ClientAnchor);
GetStream() << (sal_uInt32)0x80000000;
}
void SwBasicEscherEx::WriteEmptyFlyFrame(const SwFrmFmt& rFmt, sal_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() << (sal_uInt16)0x053F << nInlineHack;
CloseContainer(); // ESCHER_SpContainer
}
sal_uInt32 AddMirrorFlags(sal_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;
}
//For i120928,this function is added to export graphic of bullet
sal_Int32 SwBasicEscherEx::WriteGrfBullet(const Graphic& rGrf)
{
OpenContainer( ESCHER_SpContainer );
AddShape(ESCHER_ShpInst_PictureFrame, 0xa00,0x401);
EscherPropertyContainer aPropOpt;
GraphicObject aGraphicObject( rGrf );
ByteString aUniqueId = aGraphicObject.GetUniqueID();
if ( aUniqueId.Len() )
{
const MapMode aMap100mm( MAP_100TH_MM );
Size aSize( rGrf.GetPrefSize() );
if ( MAP_PIXEL == rGrf.GetPrefMapMode().GetMapUnit() )
{
aSize = Application::GetDefaultDevice()->PixelToLogic(aSize, aMap100mm );
}
else
{
aSize = OutputDevice::LogicToLogic( aSize,rGrf.GetPrefMapMode(), aMap100mm );
}
Point aEmptyPoint = Point();
Rectangle aRect( aEmptyPoint, aSize );
sal_uInt32 nBlibId = mxGlobal->GetBlibID( *(mxGlobal->QueryPictureStream()), aUniqueId,aRect, NULL, 0 );
if (nBlibId)
aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
}
aPropOpt.AddOpt( ESCHER_Prop_pibFlags, ESCHER_BlipFlagDefault );
aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, DrawModelToEmu(0));
aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, DrawModelToEmu(0));
aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, DrawModelToEmu(0));
aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, DrawModelToEmu(0));
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
aPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
aPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
aPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
aPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
const Color aTmpColor( COL_WHITE );
SvxBrushItem aBrush( aTmpColor, RES_BACKGROUND );
const SvxBrushItem *pRet = rWrt.GetCurrentPageBgBrush();
if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
aBrush = *pRet;
WriteBrushAttr(aBrush, aPropOpt);
aPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0 );
aPropOpt.Commit( GetStream() );
AddAtom(4, ESCHER_ClientAnchor);
GetStream() << (sal_uInt32)0x80000000;
CloseContainer();
return 0;
}
sal_Int32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
{
sal_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;
sal_uInt32 nFlags = ESCHER_BlipFlagDefault;
if (pGrfNd->IsLinkedFile())
{
String sURL;
pGrfNd->GetFileFilterNms( &sURL, 0 );
WW8Bytes aBuf;
SwWW8Writer::InsAsString16( aBuf, sURL );
SwWW8Writer::InsUInt16( aBuf, 0 );
sal_uInt16 nArrLen = aBuf.Count();
sal_uInt8* pArr = new sal_uInt8[ 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 = mxGlobal->GetBlibID( *QueryPictureStream(),
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() );
sal_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 &, sal_uInt32,
EscherPropertyContainer &)
{
}
void SwEscherEx::SetPicId(const SdrObject &rSdrObj, sal_uInt32 nShapeId,
EscherPropertyContainer &rPropOpt)
{
pTxtBxs->Append(rSdrObj, nShapeId);
sal_uInt32 nPicId = pTxtBxs->Count();
nPicId *= 0x10000;
rPropOpt.AddOpt( ESCHER_Prop_pictureId, nPicId );
}
sal_Int32 SwBasicEscherEx::WriteOLEFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
{
sal_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 = mxGlobal->GetBlibID( *QueryPictureStream(),
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
{
sal_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);
}
}
sal_Int32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt,
MSO_SPT eShapeType, EscherPropertyContainer& rPropOpt)
{
sal_Int32 nLineWidth=0;
const SfxPoolItem* pItem;
bool bFirstLine = true;
if (SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem))
{
static const sal_uInt16 aExhperProp[4] =
{
ESCHER_Prop_dyTextTop, ESCHER_Prop_dyTextBottom,
ESCHER_Prop_dxTextLeft, ESCHER_Prop_dxTextRight
};
const SvxBorderLine* pLine;
for( sal_uInt16 n = 0; n < 4; ++n )
if( 0 != ( pLine = ((SvxBoxItem*)pItem)->GetLine( n )) )
{
if( bFirstLine )
{
sal_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 );
}
const SwAttrSet& rAttrSet = rFmt.GetAttrSet();
if (SFX_ITEM_ON == rAttrSet.GetItemState(RES_BOX, false, &pItem))
{
const SvxBoxItem* pBox = (const SvxBoxItem*)pItem;
if( pBox )
{
const SfxPoolItem* pShadItem;
if (SFX_ITEM_ON
== rAttrSet.GetItemState(RES_SHADOW, true, &pShadItem))
{
const SvxShadowItem* pSI = (const SvxShadowItem*)pShadItem;
const sal_uInt16 nCstScale = 635; // unit scale between AOO and MS Word
const sal_uInt32 nShadowType = 131074; // shadow type of ms word. need to set the default value.
sal_uInt32 nColor = (sal_uInt32)(pSI->GetColor().GetColor()) ;
sal_uInt32 nOffX = pSI->GetWidth() * nCstScale;
sal_uInt32 nOffY = pSI->GetWidth() * nCstScale;
sal_uInt32 nShadow = nShadowType;
SvxShadowLocation eLocation = pSI->GetLocation();
if( (eLocation!=SVX_SHADOW_NONE) && (pSI->GetWidth()!=0) )
{
switch( eLocation )
{
case SVX_SHADOW_TOPLEFT:
{
nOffX = -nOffX;
nOffY = -nOffY;
}
break;
case SVX_SHADOW_TOPRIGHT:
{
nOffY = -nOffY;
}
break;
case SVX_SHADOW_BOTTOMLEFT:
{
nOffX = -nOffX;
}
break;
case SVX_SHADOW_BOTTOMRIGHT:
break;
default:
break;
}
rPropOpt.AddOpt( DFF_Prop_shadowColor, wwUtility::RGBToBGR((nColor)));
rPropOpt.AddOpt( DFF_Prop_shadowOffsetX, nOffX );
rPropOpt.AddOpt( DFF_Prop_shadowOffsetY, nOffY );
rPropOpt.AddOpt( DFF_Prop_fshadowObscured, nShadow );
}
}
}
}
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 );
}
PreWriteHyperlinkWithinFly(rFmt,rPropOpt);
return nLineWidth;
}
sal_Int32 SwEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType,
EscherPropertyContainer& rPropOpt)
{
sal_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<sal_uInt8 *>(pArr), nArrLen);
}
}
}
PreWriteHyperlinkWithinFly(rFmt,rPropOpt);
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());
}
sal_Int32 SwBasicEscherEx::ToFract16(sal_Int32 nVal, sal_uInt32 nMax) const
{
if (nMax)
{
sal_Int32 nMSVal = (nVal / 65536) * nMax;
nMSVal += (nVal * 65536 ) / nMax;
return nMSVal;
}
return 0;
}
SdrLayerID SwBasicEscherEx::GetInvisibleHellId() const
{
return rWrt.pDoc->GetInvisibleHellId();
}
void SwBasicEscherEx::WritePictures()
{
if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
{
// set the blip - entries to the correct stream pos
sal_Int32 nEndPos = pPicStrm->Tell();
mxGlobal->WriteBlibStoreEntry(*pEscherStrm, 1, sal_True, nEndPos);
pPicStrm->Seek(0);
*pEscherStrm << *pPicStrm;
}
}
SwEscherEx::SwEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
: SwBasicEscherEx(pStrm, rWW8Wrt),
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
sal_uInt8 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 );
sal_uLong nSecondShapeId = pSdrObjs == rWrt.pSdrObjs ? GenerateShapeId() : 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)
{
sal_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 = GenerateShapeId());
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);
}
#ifdef DBG_UTIL
else
ASSERT( !this, "Where is the SDR-Object?" );
#endif
}
break;
default:
break;
}
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);
SvxGraphicPosition ePos = pBrush->GetGraphicPos();
if( ePos != GPOS_NONE && ePos != GPOS_AREA )
{
/* #i56806# 0x033F parameter specifies a 32-bit field of shape boolean properties.
0x10001 means fBackground and fUsefBackground flag are true thus background
picture will be shown as "tiled" fill.*/
aPropOpt.AddOpt( ESCHER_Prop_fBackground, 0x10001 );
}
}
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_AS_CHAR == 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::list<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_PARA) || (eAnchor == FLY_AT_CHAR) ) &&
_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 if ( _iorHoriOri.IsPosToggle()
&& _iorHoriOri.GetHoriOrient() == text::HoriOrientation::RIGHT )
{
eHoriConv = NO_CONV;
_iorHoriOri.SetHoriOrient( text::HoriOrientation::OUTSIDE );
}
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_AS_CHAR);
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_AT_PAGE)
mnXRelTo = 1;
else
mnXRelTo = 2;
break;
case text::RelOrientation::PRINT_AREA:
if (eAnchor == FLY_AT_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_AT_PAGE)
mnYRelTo = 0;
else
mnYRelTo = 2;
break;
case text::RelOrientation::FRAME:
if (eAnchor == FLY_AT_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;
}
sal_Int32 SwEscherEx::WriteFlyFrm(const DrawObj &rObj, sal_uInt32 &rShapeId,
DrawObjPointerVector &rPVec)
{
const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
// check for textflyframe and if it is the first in a Chain
sal_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 = GenerateShapeId() );
break;
case ND_OLENODE:
nBorderThick = WriteOLEFlyFrame( rFmt, rShapeId = GenerateShapeId() );
break;
default:
if (const SdrObject* pObj = rFmt.FindRealSdrObject())
{
// check for the first in a Chain
sal_uInt32 nTxtId;
sal_uInt16 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 )
{
sal_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);
}
//In browse mode the sdr object doesn't always exist. For example, the
//object is in the hidden header/footer. We save the fmt directly
//in such cases; we copy most of the logic from the block above
const bool bBrowseMode = (rFmt.getIDocumentSettingAccess())->get(IDocumentSettingAccess::BROWSE_MODE);
if( bBrowseMode && rFmt.GetDoc())
{
if( !rFmt.GetChain().GetPrev() )//obj in header/footer?
{
rShapeId = GetFlyShapeId(rFmt, rObj.mnHdFtIndex, rPVec);
pTxtBxs->Append( &rFmt, rShapeId );
sal_uInt32 nTxtId = pTxtBxs->Count();
nTxtId *= 0x10000;
nBorderThick = WriteTxtFlyFrame(rObj, rShapeId, nTxtId, rPVec);
}
}
}
}
return nBorderThick;
}
sal_uInt16 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< sal_uInt16 >(aIter - rPVec.begin());
}
}
return USHRT_MAX;
}
sal_Int32 SwEscherEx::WriteTxtFlyFrame(const DrawObj &rObj, sal_uInt32 nShapeId,
sal_uInt32 nTxtBox, DrawObjPointerVector &rPVec)
{
const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
short nDirection = rObj.mnDirection;
sal_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())
{
sal_uInt16 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 = mxGlobal->GetBlibID( *QueryPictureStream(),
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, sal_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)
{
sal_uInt16 n, nCnt = static_cast< sal_uInt16 >(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();
sal_uLong nOrdNum = rWrt.GetSdrOrdNum(rFmt);
sal_uInt16 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;
}
sal_uLong nShapeId = bNeedsShapeId ? GenerateShapeId() : 0;
aFollowShpIds.Insert(nShapeId, n);
}
}
sal_uInt32 SwEscherEx::GetFlyShapeId(const SwFrmFmt& rFmt,
unsigned int nHdFtIndex, DrawObjPointerVector &rpVec)
{
sal_uInt16 nPos = FindPos(rFmt, nHdFtIndex, rpVec);
sal_uInt32 nShapeId;
if (USHRT_MAX != nPos)
{
if (0 == (nShapeId = aFollowShpIds[nPos]))
{
nShapeId = GenerateShapeId();
aFollowShpIds[ nPos ] = nShapeId;
}
}
else
nShapeId = GenerateShapeId();
return nShapeId;
}
sal_uInt32 SwEscherEx::QueryTextID(
const uno::Reference< drawing::XShape>& xXShapeRef, sal_uInt32 nShapeId )
{
sal_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;
sal_uInt8 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
sal_uInt8 *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: */