Kaydet (Commit) 8f7c7a57 authored tarafından Jian Hong Cheng's avatar Jian Hong Cheng

Fix issue #120927: Import/Export Hyperlink Info of Graphic with Anchor Type…

Fix issue #120927: Import/Export Hyperlink Info of Graphic with Anchor Type Except “As Character” to MS Word Binary File

* sw/source/filter/ww8/escher.hxx
* sw/source/filter/ww8/wrtw8esh.cxx
* sw/source/filter/ww8/wrtww8.hxx
* sw/source/filter/ww8/ww8graf.cxx
* sw/source/filter/ww8/ww8par.cxx
* sw/source/filter/ww8/ww8par.hxx
Interoperability of Hyperlink within Flying object

Patch by: Jane Kang,<kangjane2012@gmail.com>
Found by: Yan Ji,<yanji.yj@gmail.com>
Review by: Jian Hong Cheng,<chengjh@apache.org>           
üst 9f69b963
...@@ -134,6 +134,13 @@ public: ...@@ -134,6 +134,13 @@ public:
virtual void WriteFrmExtraData(const SwFrmFmt&); virtual void WriteFrmExtraData(const SwFrmFmt&);
virtual void WritePictures(); virtual void WritePictures();
virtual ~SwBasicEscherEx(); virtual ~SwBasicEscherEx();
//i120927,this function is added to export hyperlink info,such as graphic/frame/OLE
bool IsRelUrl();
String GetBasePath();
String BuildFileName(sal_uInt16& rnLevel, bool& rbRel, const String& rUrl );
void WriteHyperlinkWithinFly( SvMemoryStream& rStrm, const SwFmtURL* pINetFmtArg);
void PreWriteHyperlinkWithinFly(const SwFrmFmt& rFmt,EscherPropertyContainer& rPropOpt);
private: private:
//No copying //No copying
SwBasicEscherEx(const SwBasicEscherEx&); SwBasicEscherEx(const SwBasicEscherEx&);
......
...@@ -103,11 +103,232 @@ ...@@ -103,11 +103,232 @@
// <-- // <--
#include "WW8FFData.hxx" #include "WW8FFData.hxx"
#include <editeng/shaditem.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 com::sun::star;
using namespace sw::util; using namespace sw::util;
using namespace sw::types; using namespace sw::types;
using namespace nsFieldFlags; 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 //#110185# get a part fix for this type of element
bool WW8Export::MiserableFormFieldExportHack(const SwFrmFmt& rFrmFmt) bool WW8Export::MiserableFormFieldExportHack(const SwFrmFmt& rFrmFmt)
...@@ -1843,6 +2064,8 @@ sal_Int32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, ...@@ -1843,6 +2064,8 @@ sal_Int32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt,
rPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 ); rPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
} }
PreWriteHyperlinkWithinFly(rFmt,rPropOpt);
return nLineWidth; return nLineWidth;
} }
...@@ -1936,6 +2159,8 @@ sal_Int32 SwEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType ...@@ -1936,6 +2159,8 @@ sal_Int32 SwEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType
} }
} }
PreWriteHyperlinkWithinFly(rFmt,rPropOpt);
return nLineWidth; return nLineWidth;
} }
......
...@@ -901,6 +901,8 @@ public: ...@@ -901,6 +901,8 @@ public:
using StgWriter::Write; using StgWriter::Write;
virtual sal_uLong Write( SwPaM&, SfxMedium&, const String* = 0 ); virtual sal_uLong Write( SwPaM&, SfxMedium&, const String* = 0 );
//Seems not an expected to provide method to access the private member
SfxMedium* GetMedia(){ return mpMedium;};
private: private:
/// No copying. /// No copying.
......
...@@ -99,6 +99,11 @@ ...@@ -99,6 +99,11 @@
#include <math.h> #include <math.h>
#include <fmturl.hxx>
#include <svx/hlnkitem.hxx>
#include <svl/whiter.hxx>
#include "ww8par2.hxx"
using namespace ::com::sun::star; using namespace ::com::sun::star;
using namespace sw::types; using namespace sw::types;
using namespace sw::util; using namespace sw::util;
...@@ -2728,6 +2733,39 @@ SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp ) ...@@ -2728,6 +2733,39 @@ SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp )
if (pRecord->bHidden) if (pRecord->bHidden)
return 0; return 0;
if(pObject)
{
sal_uInt16 nCount = pObject ? pObject->GetUserDataCount() : 0;
if(nCount)
{
String lnName, aObjName, aTarFrm;
for (sal_uInt16 i = 0; i < nCount; i++ )
{
SdrObjUserData* pData = pObject->GetUserData( i );
if( pData && pData->GetInventor() == SW_DRAWLAYER
&& pData->GetId() == SW_UD_IMAPDATA)
{
SwMacroInfo* macInf = dynamic_cast<SwMacroInfo*>(pData);
if( macInf->GetShapeId() == pF->nSpId)
{
lnName = macInf->GetHlink();
aObjName = macInf->GetName();
aTarFrm = macInf->GetTarFrm();
break;
}
}
}
SwFmtURL* pFmtURL = new SwFmtURL();
pFmtURL->SetURL( lnName, false );
if(aObjName.Len() > 0)
pFmtURL->SetName(aObjName);
if(aTarFrm.Len()>0)
pFmtURL->SetTargetFrameName(aTarFrm);
pFmtURL->SetMap(0);
aFlySet.Put(*pFmtURL);
}
}
// If we are to be "below text" then we are not to be opaque // If we are to be "below text" then we are not to be opaque
// #i14045# MM If we are in a header or footer then make the object transparent // #i14045# MM If we are in a header or footer then make the object transparent
// Not exactly like word but close enough for now // Not exactly like word but close enough for now
......
This diff is collapsed.
...@@ -31,6 +31,10 @@ ...@@ -31,6 +31,10 @@
#include <editeng/frmdir.hxx> #include <editeng/frmdir.hxx>
#include <fltshell.hxx> // fuer den Attribut Stack #include <fltshell.hxx> // fuer den Attribut Stack
#include <svx/svdobj.hxx>
#define SW_DRAWLAYER 0x30334353
#define SW_UD_IMAPDATA 2
#include <vector> #include <vector>
#include <stack> #include <stack>
#include <deque> #include <deque>
...@@ -365,6 +369,48 @@ private: ...@@ -365,6 +369,48 @@ private:
SwWW8FltRefStack& operator=(const SwWW8FltRefStack&); SwWW8FltRefStack& operator=(const SwWW8FltRefStack&);
}; };
template< typename Type >
inline bool get_flag( Type nBitField, Type nMask )
{ return (nBitField & nMask) != 0; }
template< typename ReturnType, typename Type >
inline ReturnType ulimit_cast( Type nValue, ReturnType nMax )
{ return static_cast< ReturnType >( ::std::min< Type >( nValue, nMax ) ); }
template< typename ReturnType, typename Type >
inline ReturnType ulimit_cast( Type nValue )
{ return ulimit_cast( nValue, ::std::numeric_limits< ReturnType >::max() ); }
class SwMacroInfo : public SdrObjUserData
{
public:
SwMacroInfo();
virtual ~SwMacroInfo();
virtual SdrObjUserData* Clone( SdrObject* pObj ) const;
void SetHlink( const rtl::OUString& rHlink ) { maHlink = rHlink; }
const rtl::OUString& GetHlink() const { return maHlink; }
void SetTarFrm( const rtl::OUString& rTarFrm ) { maTarFrm = rTarFrm; }
const rtl::OUString& GetTarFrm() const { return maTarFrm; }
void SetShapeId( const sal_uInt32& rShapeId ) { maShapeId = rShapeId; }
const sal_uInt32& GetShapeId() const { return maShapeId; }
void SetName( const rtl::OUString& rName ) { maNameStr = rName; }
const rtl::OUString& GetName() const { return maNameStr; }
private:
sal_uInt32 maShapeId;
rtl::OUString maHlink;
rtl::OUString maNameStr;
rtl::OUString maTarFrm;
};
struct HyperLinksTable
{
String hLinkAddr;
String tarFrm;
};
namespace sw namespace sw
{ {
...@@ -1667,6 +1713,8 @@ public: // eigentlich private, geht aber leider nur public ...@@ -1667,6 +1713,8 @@ public: // eigentlich private, geht aber leider nur public
CharSet GetCurrentCJKCharSet(); CharSet GetCurrentCJKCharSet();
void PostProcessAttrs(); void PostProcessAttrs();
static void ReadEmbeddedData(SvMemoryStream& rStrm, SwDocShell* pDocShell ,struct HyperLinksTable& hlStr);
static String ReadRawUniString( SvMemoryStream& rStrm,sal_uInt16 nChars, bool b16Bit );
}; };
bool CanUseRemoteLink(const String &rGrfName); bool CanUseRemoteLink(const String &rGrfName);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment