114361: provide and accept changed URL of embedded graphic file during save (ODF export)

Notes:

merged as: 192abfb36b8a4859879fcb49326d59ed62083c8d
diff --git a/sw/inc/ndgrf.hxx b/sw/inc/ndgrf.hxx
index f9ee8ac..6d59466 100644
--- a/sw/inc/ndgrf.hxx
+++ b/sw/inc/ndgrf.hxx
@@ -25,22 +25,17 @@
#include <sfx2/lnkbase.hxx>
#include <svtools/grfmgr.hxx>
#include <ndnotxt.hxx>
// --> OD, MAV 2005-08-17 #i53025#
#include <com/sun/star/embed/XStorage.hpp>
// <--
// --> OD 2007-03-28 #i73788#
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
class SwAsyncRetrieveInputStreamThreadConsumer;
// <--

class SwGrfFmtColl;
class SwDoc;
class GraphicAttr;
class SvStorage;
// --------------------
// SwGrfNode
// --------------------


class SW_DLLPUBLIC SwGrfNode: public SwNoTxtNode
{
    friend class SwNodes;
@@ -49,28 +44,19 @@ class SW_DLLPUBLIC SwGrfNode: public SwNoTxtNode
    GraphicObject* mpReplacementGraphic;
    ::sfx2::SvBaseLinkRef refLink;       // falls Grafik nur als Link, dann Pointer gesetzt
    Size nGrfSize;
//  String aStrmName;           // SW3: Name des Storage-Streams fuer Embedded
    String aNewStrmName;        // SW3/XML: new stream name (either SW3 stream
                                // name or package url)
    String aLowResGrf;          // HTML: LowRes Grafik (Ersatzdarstellung bis
                                //      die normale (HighRes) geladen ist.
    sal_Bool bTransparentFlagValid  :1;
    sal_Bool bInSwapIn              :1;
    sal_Bool bInSwapIn :1;

    sal_Bool bGrafikArrived         :1;
    sal_Bool bChgTwipSize           :1;
    sal_Bool bChgTwipSizeFromPixel  :1;
    sal_Bool bLoadLowResGrf         :1;
    sal_Bool bFrameInPaint          :1; //Um Start-/EndActions im Paint (ueber
                                    //SwapIn zu verhindern.
    sal_Bool bScaleImageMap         :1; //Image-Map in SetTwipSize skalieren
    sal_Bool bGrafikArrived :1;
    sal_Bool bChgTwipSize :1;
    sal_Bool bChgTwipSizeFromPixel :1;
    sal_Bool bLoadLowResGrf :1;
    sal_Bool bFrameInPaint :1;  // Um Start-/EndActions im Paint (ueber SwapIn zu verhindern.
    sal_Bool bScaleImageMap :1; // Image-Map in SetTwipSize skalieren

    // --> OD 2007-01-19 #i73788#
    boost::shared_ptr< SwAsyncRetrieveInputStreamThreadConsumer > mpThreadConsumer;
    bool mbLinkedInputStreamReady;
    com::sun::star::uno::Reference<com::sun::star::io::XInputStream> mxInputStream;
    sal_Bool mbIsStreamReadOnly;
    // <--

    SwGrfNode( const SwNodeIndex& rWhere,
               const String& rGrfName, const String& rFltName,
@@ -90,13 +76,7 @@ class SW_DLLPUBLIC SwGrfNode: public SwNoTxtNode
    void InsertLink( const String& rGrfName, const String& rFltName );
    sal_Bool ImportGraphic( SvStream& rStrm );
    sal_Bool HasStreamName() const { return maGrfObj.HasUserData(); }
    // --> OD 2005-05-04 #i48434# - adjust return type and rename method to
    // indicate that its an private one.
    // --> OD 2005-08-17 #i53025#
    // embedded graphic stream couldn't be inside a 3.1 - 5.2 storage any more.
    // Thus, return value isn't needed any more.
    void _GetStreamStorageNames( String& rStrmName, String& rStgName ) const;
    // <--
    void DelStreamName();
    DECL_LINK( SwapGraphic, GraphicObject* );

@@ -194,11 +174,15 @@ public:
                 sal_Bool bModify = sal_True );
    // Laden der Grafik unmittelbar vor der Anzeige
    short SwapIn( sal_Bool bWaitForData = sal_False );
        // Entfernen der Grafik, um Speicher freizugeben
    // Entfernen der Grafik, um Speicher freizugeben
    short SwapOut();
        // Zugriff auf den Storage-Streamnamen
    void SetStreamName( const String& r ) { maGrfObj.SetUserData( r ); }
    void SetNewStreamName( const String& r ) { aNewStrmName = r; }

    // applying new stream name for embedded graphic - needed as saving the document might change this stream name
    void ApplyNewEmbeddedStreamName( const String& r )
    {
        maGrfObj.SetUserData( r );
    }

    // is this node selected by any shell?
    sal_Bool IsSelected() const;
#endif
@@ -224,7 +208,6 @@ public:
    GraphicAttr& GetGraphicAttr( GraphicAttr&, const SwFrm* pFrm ) const;

#endif
    // --> OD 2007-01-18 #i73788#
    boost::weak_ptr< SwAsyncRetrieveInputStreamThreadConsumer > GetThreadConsumer();
    bool IsLinkedInputStreamReady() const;
    void TriggerAsyncRetrieveInputStream();
@@ -232,10 +215,7 @@ public:
        com::sun::star::uno::Reference<com::sun::star::io::XInputStream> xInputStream,
        const sal_Bool bIsStreamReadOnly );
    void UpdateLinkWithInputStream();
    // <--
    // --> OD 2008-07-21 #i90395#
    bool IsAsyncRetrieveInputStreamPossible() const;
    // <--
};


diff --git a/sw/source/core/graphic/ndgrf.cxx b/sw/source/core/graphic/ndgrf.cxx
index 5fa944c..e9c6348 100644
--- a/sw/source/core/graphic/ndgrf.cxx
+++ b/sw/source/core/graphic/ndgrf.cxx
@@ -68,44 +68,41 @@ using namespace com::sun::star;
// SwGrfNode
// --------------------
SwGrfNode::SwGrfNode(
        const SwNodeIndex & rWhere,
        const String& rGrfName, const String& rFltName,
        const Graphic* pGraphic,
        SwGrfFmtColl *pGrfColl,
        SwAttrSet* pAutoAttr ) :
    SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
    maGrfObj(),
    mpReplacementGraphic(0),
    // --> OD 2007-01-23 #i73788#
    mbLinkedInputStreamReady( false ),
    mbIsStreamReadOnly( sal_False )
    // <--
    const SwNodeIndex & rWhere,
    const String& rGrfName,
    const String& rFltName,
    const Graphic* pGraphic,
    SwGrfFmtColl *pGrfColl,
    SwAttrSet* pAutoAttr )
        : SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
          maGrfObj(),
          mpReplacementGraphic( 0 ),
          mbLinkedInputStreamReady( false ),
          mbIsStreamReadOnly( sal_False )
{
    maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ) );
    bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf =
        bFrameInPaint = bScaleImageMap = sal_False;
    bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf = bFrameInPaint = bScaleImageMap = sal_False;

    bGrafikArrived = sal_True;
    ReRead(rGrfName,rFltName, pGraphic, 0, sal_False);
    ReRead( rGrfName, rFltName, pGraphic, 0, sal_False );
}

SwGrfNode::SwGrfNode( const SwNodeIndex & rWhere,
                          const GraphicObject& rGrfObj,
                      SwGrfFmtColl *pGrfColl, SwAttrSet* pAutoAttr ) :
    SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
    maGrfObj(rGrfObj),
    mpReplacementGraphic(0),
    // --> OD 2007-01-23 #i73788#
    mbLinkedInputStreamReady( false ),
    mbIsStreamReadOnly( sal_False )
    // <--
SwGrfNode::SwGrfNode(
    const SwNodeIndex & rWhere,
    const GraphicObject& rGrfObj,
    SwGrfFmtColl *pGrfColl,
    SwAttrSet* pAutoAttr )
        : SwNoTxtNode( rWhere, ND_GRFNODE, pGrfColl, pAutoAttr ),
          maGrfObj( rGrfObj ),
          mpReplacementGraphic( 0 ),
          mbLinkedInputStreamReady( false ),
          mbIsStreamReadOnly( sal_False )
{
    maGrfObj = rGrfObj;
    maGrfObj.SetSwapStreamHdl( LINK( this, SwGrfNode, SwapGraphic ) );
    if( rGrfObj.HasUserData() && rGrfObj.IsSwappedOut() )
    if ( rGrfObj.HasUserData() && rGrfObj.IsSwappedOut() )
        maGrfObj.SetSwapState();
    bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel= bLoadLowResGrf =
        bFrameInPaint = bScaleImageMap = sal_False;
    bInSwapIn = bChgTwipSize = bChgTwipSizeFromPixel = bLoadLowResGrf = bFrameInPaint = bScaleImageMap = sal_False;
    bGrafikArrived = sal_True;
}

diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx
index 7da5f96..741627a 100644
--- a/sw/source/core/unocore/unoframe.cxx
+++ b/sw/source/core/unocore/unoframe.cxx
@@ -2003,26 +2003,25 @@ uno::Any SwXFrame::getPropertyValue(const OUString& rPropertyName)
        {
            String sGrfName;
            const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
            if(pIdx)
            if ( pIdx )
            {
                SwNodeIndex aIdx(*pIdx, 1);
//              SwNoTxtNode* pNoTxt = aIdx.GetNode().GetNoTxtNode();
                SwNodeIndex aIdx( *pIdx, 1 );
                SwGrfNode* pGrfNode = aIdx.GetNode().GetGrfNode();
                if(!pGrfNode)
                if ( !pGrfNode )
                    throw uno::RuntimeException();
                if( pGrfNode->IsGrfLink() )
                if ( pGrfNode->IsGrfLink() )
                {
                    pFmt->GetDoc()->GetGrfNms( *(SwFlyFrmFmt*)pFmt, &sGrfName, 0 );
                    pFmt->GetDoc()->GetGrfNms( *(SwFlyFrmFmt*) pFmt, &sGrfName, 0 );
                }
                else
                {
                    String sPrefix( RTL_CONSTASCII_STRINGPARAM(sGraphicObjectProtocol) );
                    String sPrefix( RTL_CONSTASCII_STRINGPARAM( sGraphicObjectProtocol ) );
                    String sId( pGrfNode->GetGrfObj().GetUniqueID(),
                                RTL_TEXTENCODING_ASCII_US );
                    (sGrfName = sPrefix) += sId;
                    RTL_TEXTENCODING_ASCII_US );
                    ( sGrfName = sPrefix ) += sId;
                }
            }
            aAny <<= OUString(sGrfName);
            aAny <<= OUString( sGrfName );
        }
        else if( FN_UNO_REPLACEMENT_GRAPHIC_U_R_L == pEntry->nWID)
        {
diff --git a/sw/source/filter/xml/xmltexte.cxx b/sw/source/filter/xml/xmltexte.cxx
index 84c980f..5bf90e5 100644
--- a/sw/source/filter/xml/xmltexte.cxx
+++ b/sw/source/filter/xml/xmltexte.cxx
@@ -222,7 +222,7 @@ void SwXMLTextParagraphExport::setTextEmbeddedGraphicURL(
    {
        String aNewURL( RTL_CONSTASCII_STRINGPARAM("vnd.sun.star.Package:") );
        aNewURL += String(rURL);
        pGrfNd->SetNewStreamName( aNewURL );
        pGrfNd->ApplyNewEmbeddedStreamName( aNewURL );

        // #i15411# save-as will swap all graphics in; we need to swap
        // them out again, to prevent excessive memory use
diff --git a/xmloff/source/draw/shapeexport2.cxx b/xmloff/source/draw/shapeexport2.cxx
index e31e59f..0014188 100644
--- a/xmloff/source/draw/shapeexport2.cxx
+++ b/xmloff/source/draw/shapeexport2.cxx
@@ -1090,37 +1090,38 @@ void XMLShapeExport::ImpExportPolygonShape(

void XMLShapeExport::ImpExportGraphicObjectShape(
    const uno::Reference< drawing::XShape >& xShape,
    XmlShapeType eShapeType, sal_Int32 nFeatures, awt::Point* pRefPoint)
    XmlShapeType eShapeType,
    sal_Int32 nFeatures,
    awt::Point* pRefPoint )
{
    const uno::Reference< beans::XPropertySet > xPropSet(xShape, uno::UNO_QUERY);
    if(xPropSet.is())
    const uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
    if ( xPropSet.is() )
    {
        sal_Bool bIsEmptyPresObj = sal_False;
        uno::Reference< beans::XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );

        // Transformation
        ImpExportNewTrans(xPropSet, nFeatures, pRefPoint);
        ImpExportNewTrans( xPropSet, nFeatures, pRefPoint );

        OUString sImageURL;

        if(eShapeType == XmlShapeTypePresGraphicObjectShape)
            bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken(XML_PRESENTATION_GRAPHIC) );
        if ( eShapeType == XmlShapeTypePresGraphicObjectShape )
            bIsEmptyPresObj = ImpExportPresentationAttributes( xPropSet, GetXMLToken( XML_PRESENTATION_GRAPHIC ) );

        sal_Bool bCreateNewline( (nFeatures & SEF_EXPORT_NO_WS) == 0 ); // #86116#/#92210#
        SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW,
                                  XML_FRAME, bCreateNewline, sal_True );
        sal_Bool bCreateNewline( ( nFeatures & SEF_EXPORT_NO_WS ) == 0 ); // #86116#/#92210#
        SvXMLElementExport aElem( mrExport, XML_NAMESPACE_DRAW, XML_FRAME, bCreateNewline, sal_True );

        const bool bSaveBackwardsCompatible = ( mrExport.getExportFlags() & EXPORT_SAVEBACKWARDCOMPATIBLE );

        if( !bIsEmptyPresObj || bSaveBackwardsCompatible )
        if ( !bIsEmptyPresObj || bSaveBackwardsCompatible )
        {
            if( !bIsEmptyPresObj )
            if ( !bIsEmptyPresObj )
            {
                OUString aReplacementUrl;
                xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("ReplacementGraphicURL"))) >>= aReplacementUrl;

                // If there is no url, then then graphic is empty
                if(aReplacementUrl.getLength())
                if ( aReplacementUrl.getLength() )
                {
                    const OUString aStr = mrExport.AddEmbeddedGraphicObject(aReplacementUrl);

@@ -1140,15 +1141,13 @@ void XMLShapeExport::ImpExportGraphicObjectShape(
                }

                OUString aStreamURL;
                OUString aStr;

                xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("GraphicStreamURL"))) >>= aStreamURL;
                xPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("GraphicURL"))) >>= sImageURL;
                xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicStreamURL" ) ) ) >>= aStreamURL;
                xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ) ) >>= sImageURL;

                OUString aResolveURL( sImageURL );
                const rtl::OUString sPackageURL( RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.Package:") );
                const rtl::OUString sPackageURL( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package:" ) );

                    // sj: trying to preserve the filename
                // sj: trying to preserve the filename
                if ( aStreamURL.match( sPackageURL, 0 ) )
                {
                    rtl::OUString sRequestedName( aStreamURL.copy( sPackageURL.getLength(), aStreamURL.getLength() - sPackageURL.getLength() ) );
@@ -1160,50 +1159,54 @@ void XMLShapeExport::ImpExportGraphicObjectShape(
                        sRequestedName = sRequestedName.copy( 0, nLastIndex );
                    if ( sRequestedName.getLength() )
                    {
                        aResolveURL = aResolveURL.concat( OUString(RTL_CONSTASCII_USTRINGPARAM("?requestedName=")));
                        aResolveURL = aResolveURL.concat( OUString( RTL_CONSTASCII_USTRINGPARAM( "?requestedName=" ) ) );
                        aResolveURL = aResolveURL.concat( sRequestedName );
                    }
                }

                aStr = mrExport.AddEmbeddedGraphicObject( aResolveURL );
                mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aStr );
                const OUString aStr = mrExport.AddEmbeddedGraphicObject( aResolveURL );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aStr );

                if( aStr.getLength() )
                if ( !aStr.isEmpty() )
                {
                    if( aStr[ 0 ] == '#' )
                    aStreamURL = sPackageURL;
                    if ( aStr[0] == '#' )
                    {
                        aStreamURL = sPackageURL;
                        aStreamURL = aStreamURL.concat( aStr.copy( 1, aStr.getLength() - 1 ) );
                    }
                    else
                    {
                        aStreamURL = aStreamURL.concat( aStr );
                    }

                    // update stream URL for load on demand
                    uno::Any aAny;
                    aAny <<= aStreamURL;
                    xPropSet->setPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("GraphicStreamURL")), aAny );
                    xPropSet->setPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "GraphicStreamURL" ) ), aAny );

                    mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                    mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
                    mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
                    mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
                }
            }
            else
            {
                OUString aStr;
                mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, aStr );
                mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
                mrExport.AddAttribute(XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, aStr );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
                mrExport.AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE, XML_ONLOAD );
            }

            {
                SvXMLElementExport aOBJ(mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, sal_True, sal_True);
                SvXMLElementExport aOBJ( mrExport, XML_NAMESPACE_DRAW, XML_IMAGE, sal_True, sal_True );

                if( sImageURL.getLength() )
                if ( sImageURL.getLength() )
                {
                    // optional office:binary-data
                    mrExport.AddEmbeddedGraphicObjectAsBase64( sImageURL );
                }
                if( !bIsEmptyPresObj )
                if ( !bIsEmptyPresObj )
                    ImpExportText( xShape );
            }
        }