Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/LibreOffice/sfx2/source/appl/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 15 kB image not shown  

Quelle  lnkbase2.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   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 .
 */



#include <memory>
#include <sfx2/lnkbase.hxx>
#include <sot/exchange.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/ui/dialogs/TemplateDescription.hpp>
#include <sfx2/linkmgr.hxx>
#include <vcl/svapp.hxx>
#include <vcl/weld.hxx>
#include <sfx2/strings.hrc>
#include <sfx2/sfxresid.hxx>
#include <sfx2/filedlghelper.hxx>
#include <tools/debug.hxx>
#include <svl/svdde.hxx>
#include <osl/diagnose.h>
#include <officecfg/Office/Common.hxx>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace sfx2
{

namespace {
class ImplDdeItem;
}

// only for internal management
struct ImplBaseLinkData
{
    struct tClientType
    {
        // applies for all links
        SotClipboardFormatId nCntntType; // Update Format
        // Not Ole-Links
        bool                 bIntrnlLnk;  // It is an internal link
        SfxLinkUpdateMode    nUpdateMode; // UpdateMode
    };

    struct tDDEType
    {
        ImplDdeItem* pItem;
    };

    union {
        tClientType ClientType;
        tDDEType DDEType;
    };
    ImplBaseLinkData()
    {
        ClientType.nCntntType = SotClipboardFormatId::NONE;
        ClientType.bIntrnlLnk = false;
        ClientType.nUpdateMode = SfxLinkUpdateMode::NONE;
        DDEType.pItem = nullptr;
    }
};

namespace {

class ImplDdeItem : public DdeGetPutItem
{
    SvBaseLink* pLink;
    DdeData aData;
    Sequence< sal_Int8 > aSeq;  // Datacontainer for DdeData !!!
    bool bIsValidData : 1;
    bool bIsInDTOR : 1;
public:
#if defined(_WIN32)
    ImplDdeItem( SvBaseLink& rLink, const OUString& rStr )
        : DdeGetPutItem( rStr ), pLink( &rLink ), bIsValidData( false ),
        bIsInDTOR( false )
    {}
#endif
    virtual ~ImplDdeItem() override;

    virtual DdeData* Get( SotClipboardFormatId ) override;
    virtual bool     Put( const DdeData* ) override;
    virtual void     AdviseLoop( bool ) override;

    void Notify()
    {
        bIsValidData = false;
        DdeGetPutItem::NotifyClient();
    }

    bool IsInDTOR() const { return bIsInDTOR; }
};

}

SvBaseLink::SvBaseLink()
    : m_pLinkMgr( nullptr )
    , m_pParentWin( nullptr )
    , m_bIsConnect( false )
    , m_bIsReadOnly(false)
{
    mnObjType = SvBaseLinkObjectType::ClientSo;
    pImplData.reset( new ImplBaseLinkData );
    bVisible = bSynchron = true;
    bWasLastEditOK = false;
}


SvBaseLink::SvBaseLink( SfxLinkUpdateMode nUpdateMode, SotClipboardFormatId nContentType )
    : m_pLinkMgr( nullptr )
    , m_pParentWin( nullptr )
    , m_bIsConnect( false )
    , m_bIsReadOnly(false)
{
    mnObjType = SvBaseLinkObjectType::ClientSo;
    pImplData.reset( new ImplBaseLinkData );
    bVisible = bSynchron = true;
    bWasLastEditOK = false;

    // It is going to be an OLE-Link,
    pImplData->ClientType.nUpdateMode = nUpdateMode;
    pImplData->ClientType.nCntntType = nContentType;
    pImplData->ClientType.bIntrnlLnk = false;
}

#if defined(_WIN32)

static DdeTopic* FindTopic( const OUString & rLinkName, sal_uInt16* pItemStt )
{
    if( rLinkName.isEmpty() )
        return nullptr;

    OUString sNm( rLinkName );
    sal_Int32 nTokenPos = 0;
    OUString sService( sNm.getToken( 0, cTokenSeparator, nTokenPos ) );

    DdeServices& rSvc = DdeService::GetServices();
    for (auto const& elem : rSvc)
    {
        if(elem->GetName() == sService)
        {
            // then we search for the Topic
            OUString sTopic( sNm.getToken( 0, cTokenSeparator, nTokenPos ) );
            if( pItemStt )
                *pItemStt = nTokenPos;

            std::vector<DdeTopic*>& rTopics = elem->GetTopics();

            auto cfName = [&sTopic](const DdeTopic* p) { return p->GetName() == sTopic; };
            auto it = std::find_if(rTopics.begin(), rTopics.end(), cfName);
            if (it == rTopics.end())
            {
                // Topic not found?
                // then we try once to create it
                if (elem->MakeTopic(sTopic))
                    it = std::find_if(rTopics.begin(), rTopics.end(), cfName);
            }
            if (it != rTopics.end())
                return *it;
            break;
        }
    }
    return nullptr;
}

SvBaseLink::SvBaseLink( const OUString& rLinkName, SvBaseLinkObjectType nObjectType, SvLinkSource* pObj )
    : m_pLinkMgr( nullptr )
    , m_pParentWin( nullptr )
    , m_bIsConnect( false )
    , m_bIsReadOnly(false)
{
    bVisible = bSynchron = true;
    bWasLastEditOK = false;
    aLinkName = rLinkName;
    pImplData.reset( new ImplBaseLinkData );
    mnObjType = nObjectType;

    if( !pObj )
    {
        DBG_ASSERT( pObj, "Where is my left-most object" );
        return;
    }

    if( SvBaseLinkObjectType::DdeExternal == mnObjType )
    {
        sal_uInt16 nItemStt = 0;
        DdeTopic* pTopic = FindTopic( aLinkName, &nItemStt );
        if( pTopic )
        {
            // then we have it all together
            // MM_TODO how do I get the name
            OUString aStr = aLinkName; // xLinkName->GetDisplayName();
            aStr = aStr.copy( nItemStt );
            pImplData->DDEType.pItem = new ImplDdeItem( *this, aStr );
            pTopic->InsertItem( pImplData->DDEType.pItem );

            // store the Advice
            xObj = pObj;
        }
    }
    else if( pObj->Connect( this ) )
        xObj = pObj;
}

#endif

SvBaseLink::~SvBaseLink()
{
    Disconnect();

    if( mnObjType == SvBaseLinkObjectType::DdeExternal )
    {
        if( !pImplData->DDEType.pItem->IsInDTOR() )
            delete pImplData->DDEType.pItem;
    }

    pImplData.reset();
}

IMPL_LINK( SvBaseLink, EndEditHdl, const OUString&, _rNewName, void )
{
    OUString sNewName = _rNewName;
    if ( !ExecuteEdit( sNewName ) )
        sNewName.clear();
    bWasLastEditOK = !sNewName.isEmpty();
    m_aEndEditLink.Call( *this );
}


void SvBaseLink::SetObjType( SvBaseLinkObjectType mnObjTypeP )
{
    DBG_ASSERT( mnObjType != SvBaseLinkObjectType::ClientDde, "type already set" );
    DBG_ASSERT( !xObj.is(), "object exist" );

    mnObjType = mnObjTypeP;
}


void SvBaseLink::SetName( const OUString & rNm )
{
    aLinkName = rNm;
}


void SvBaseLink::SetObj( SvLinkSource * pObj )
{
    DBG_ASSERT( (isClientType(mnObjType) &&
                 pImplData->ClientType.bIntrnlLnk) ||
                mnObjType == SvBaseLinkObjectType::ClientGraphic,
                "no intern link" );
    xObj = pObj;
}


void SvBaseLink::SetLinkSourceName( const OUString & rLnkNm )
{
    if( aLinkName == rLnkNm )
        return;

    AddNextRef(); // should be superfluous
    // remove old connection
    Disconnect();

    aLinkName = rLnkNm;

    // New Connection
    GetRealObject_();
    ReleaseRef(); // should be superfluous
}


void SvBaseLink::SetUpdateMode( SfxLinkUpdateMode nMode )
{
    if( isClientType(mnObjType) &&
        pImplData->ClientType.nUpdateMode != nMode )
    {
        AddNextRef();
        Disconnect();

        pImplData->ClientType.nUpdateMode = nMode;
        GetRealObject_();
        ReleaseRef();
    }
}

// #i88291#
void SvBaseLink::clearStreamToLoadFrom()
{
    m_xInputStreamToLoadFrom.clear();
    if( xObj.is() )
    {
        xObj->clearStreamToLoadFrom();
    }
}

bool SvBaseLink::Update()
{
    if(officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
        return false;

    if( isClientType(mnObjType) )
    {
        AddNextRef();
        Disconnect();

        GetRealObject_();
        ReleaseRef();
        if( xObj.is() )
        {
            xObj->setStreamToLoadFrom(m_xInputStreamToLoadFrom,m_bIsReadOnly);
            OUString sMimeType( SotExchange::GetFormatMimeType(
                            pImplData->ClientType.nCntntType ));
            Any aData;

            if( xObj->GetData( aData, sMimeType ) )
            {
                UpdateResult eRes = DataChanged(sMimeType, aData);
                bool bSuccess = eRes == SUCCESS;
                //for manual Updates there is no need to hold the ServerObject
                if( SvBaseLinkObjectType::ClientDde == mnObjType &&
                    SfxLinkUpdateMode::ONCALL == GetUpdateMode() && xObj.is() )
                    xObj->RemoveAllDataAdvise( this );
                return bSuccess;
            }
            if( xObj.is() )
            {
                // should be asynchronous?
                if( xObj->IsPending() )
                    return true;

                // we do not need the object anymore
                AddNextRef();
                Disconnect();
                ReleaseRef();
            }
        }
    }
    return false;
}


SfxLinkUpdateMode SvBaseLink::GetUpdateMode() const
{
    return isClientType(mnObjType)
            ? pImplData->ClientType.nUpdateMode
            : SfxLinkUpdateMode::ONCALL;
}


void SvBaseLink::GetRealObject_( bool bConnect)
{
    if( !m_pLinkMgr )
        return;

    DBG_ASSERT( !xObj.is(), "object already exist" );

    if( SvBaseLinkObjectType::ClientDde == mnObjType )
    {
        OUString sServer;
        if( sfx2::LinkManager::GetDisplayNames( this, &sServer ) &&
            sServer == Application::GetAppName() )  // internal Link !!!
        {
            // so that the Internal link can be created!
            mnObjType = SvBaseLinkObjectType::Internal;
            xObj = sfx2::LinkManager::CreateObj( this );

            pImplData->ClientType.bIntrnlLnk = true;
            mnObjType = SvBaseLinkObjectType::ClientDde;  // so we know what it once was!
        }
        else
        {
            pImplData->ClientType.bIntrnlLnk = false;
            xObj = sfx2::LinkManager::CreateObj( this );
        }
    }
    else if( isClientType(mnObjType) )
        xObj = sfx2::LinkManager::CreateObj( this );

    if( bConnect && ( !xObj.is() || !xObj->Connect( this ) ) )
        Disconnect();
}

SotClipboardFormatId SvBaseLink::GetContentType() const
{
    if( isClientType(mnObjType) )
        return pImplData->ClientType.nCntntType;

    return SotClipboardFormatId::NONE;  // all Formats ?
}


void SvBaseLink::SetContentType( SotClipboardFormatId nType )
{
    if( isClientType(mnObjType) )
    {
        pImplData->ClientType.nCntntType = nType;
    }
}

LinkManager* SvBaseLink::GetLinkManager()
{
    return m_pLinkMgr;
}

const LinkManager* SvBaseLink::GetLinkManager() const
{
    return m_pLinkMgr;
}

void SvBaseLink::SetLinkManager( LinkManager* _pMgr )
{
    m_pLinkMgr = _pMgr;
}

void SvBaseLink::Disconnect()
{
    if( xObj.is() )
    {
        xObj->RemoveAllDataAdvise( this );
        xObj->RemoveConnectAdvise( this );
        xObj.clear();
    }
}

SvBaseLink::UpdateResult SvBaseLink::DataChanged( const OUString &, const css::uno::Any & )
{
    if ( mnObjType == SvBaseLinkObjectType::DdeExternal )
    {
        if( pImplData->DDEType.pItem )
            pImplData->DDEType.pItem->Notify();
    }
    return SUCCESS;
}

void SvBaseLink::Edit(weld::Window* pParent, const Link<SvBaseLink&,void>& rEndEditHdl )
{
    m_pParentWin = pParent;
    m_aEndEditLink = rEndEditHdl;
    m_bIsConnect = xObj.is();
    if( !m_bIsConnect )
        GetRealObject_( xObj.is() );

    bool bAsync = false;
    Link<const OUString&, void> aLink = LINK( this, SvBaseLink, EndEditHdl );

    if( isClientType(mnObjType) && pImplData->ClientType.bIntrnlLnk )
    {
        if( m_pLinkMgr )
        {
            SvLinkSourceRef ref = sfx2::LinkManager::CreateObj( this );
            if( ref.is() )
            {
                ref->Edit( pParent, this, aLink );
                bAsync = true;
            }
        }
    }
    else
    {
        xObj->Edit( pParent, this, aLink );
        bAsync = true;
    }

    if ( !bAsync )
    {
        ExecuteEdit( OUString() );
        bWasLastEditOK = false;
        m_aEndEditLink.Call( *this );
    }
}

bool SvBaseLink::ExecuteEdit( const OUString& _rNewName )
{
    if( !_rNewName.isEmpty() )
    {
        SetLinkSourceName( _rNewName );
        if( !Update() )
        {
            OUString sApp, sTopic, sItem, sError;
            sfx2::LinkManager::GetDisplayNames( this, &sApp, &sTopic, &sItem );
            if( mnObjType == SvBaseLinkObjectType::ClientDde )
            {
                sError = SfxResId(STR_DDE_ERROR);

                sal_Int32 nFndPos = sError.indexOf( "%1" );
                if( -1 != nFndPos )
                {
                    sError = sError.replaceAt( nFndPos, 2, sApp );
                    nFndPos = nFndPos + sApp.getLength();

                    if( -1 != ( nFndPos = sError.indexOf( "%2", nFndPos )))
                    {
                        sError = sError.replaceAt( nFndPos, 2, sTopic );
                        nFndPos = nFndPos + sTopic.getLength();

                        if( -1 != ( nFndPos = sError.indexOf( "%3", nFndPos )))
                            sError = sError.replaceAt( nFndPos, 2, sItem );
                    }
                }
            }
            else
                return false;

            std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(m_pParentWin,
                                                                     VclMessageType::Warning, VclButtonsType::Ok, sError));
            xBox->run();
        }
    }
    else if( !m_bIsConnect )
        Disconnect();
    m_bIsConnect = false;
    return true;
}

void SvBaseLink::Closed()
{
    if( xObj.is() )
        xObj->RemoveAllDataAdvise( this );
}

FileDialogHelper & SvBaseLink::GetInsertFileDialog(const OUString& rFactory)
{
    m_pFileDlg.reset( new FileDialogHelper(
            ui::dialogs::TemplateDescription::FILEOPEN_SIMPLE,
            FileDialogFlags::Insert, rFactory, SfxFilterFlags::NONE, SfxFilterFlags::NONE, m_pParentWin) );
    return *m_pFileDlg;
}

ImplDdeItem::~ImplDdeItem()
{
    bIsInDTOR = true;
    // So that no-one gets the idea to delete the pointer when Disconnecting!
    tools::SvRef<SvBaseLink> aRef( pLink );
    aRef->Disconnect();
}

DdeData* ImplDdeItem::Get( SotClipboardFormatId nFormat )
{
    if( pLink->GetObj() )
    {
        // is it still valid?
        if( bIsValidData && nFormat == aData.GetFormat() )
            return &aData;

        Any aValue;
        OUString sMimeType( SotExchange::GetFormatMimeType( nFormat ));
        if( pLink->GetObj()->GetData( aValue, sMimeType ) )
        {
            if( aValue >>= aSeq )
            {
                aData = DdeData( aSeq.getConstArray(), aSeq.getLength(), nFormat );

                bIsValidData = true;
                return &aData;
            }
        }
    }
    aSeq.realloc( 0 );
    bIsValidData = false;
    return nullptr;
}


bool ImplDdeItem::Put( const DdeData*  )
{
    OSL_FAIL( "ImplDdeItem::Put not implemented" );
    return false;
}


void ImplDdeItem::AdviseLoop( bool bOpen )
{
    // Connection is closed, so also unsubscribe link
    if( !pLink->GetObj() )
        return;

    if( bOpen )
    {
        // A connection is re-established
        if( SvBaseLinkObjectType::DdeExternal == pLink->GetObjType() )
        {
            pLink->GetObj()->AddDataAdvise( pLink, u"text/plain;charset=utf-16"_ustr,  ADVISEMODE_NODATA );
            pLink->GetObj()->AddConnectAdvise( pLink );
        }
    }
    else
    {
        // So that no-one gets the idea to delete the pointer
        // when Disconnecting!
        tools::SvRef<SvBaseLink> aRef( pLink );
        aRef->Disconnect();
    }
}

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=97 G=96

¤ Dauer der Verarbeitung: 0.17 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.