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

Quelle  sbxvar.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 <config_features.h>

#include <tools/stream.hxx>
#include <svl/SfxBroadcaster.hxx>

#include <basic/sbx.hxx>
#include <runtime.hxx>
#include "sbxres.hxx"
#include "sbxconv.hxx"
#include <sbunoobj.hxx>
#include <rtl/ustrbuf.hxx>
#include <sal/log.hxx>
#include <global.hxx>
#include <unotools/transliterationwrapper.hxx>

#include <com/sun/star/uno/XInterface.hpp>
#include <utility>
#include <filefmt.hxx>
using namespace com::sun::star::uno;

// SbxVariable

SbxVariable::SbxVariable()
{
}

SbxVariable::SbxVariable( const SbxVariable& r )
    : SvRefBase( r ),
      SbxValue( r ),
      m_aDeclareClassName( r.m_aDeclareClassName ),
      m_xComListener( r.m_xComListener),
      mpPar( r.mpPar ),
      pInfo( r.pInfo )
{
#if HAVE_FEATURE_SCRIPTING
    if( r.m_xComListener.is() )
    {
        registerComListenerVariableForBasic( this, r.m_pComListenerParentBasic );
    }
#endif
    if( r.CanRead() )
    {
        pParent = r.pParent;
        nUserData = r.nUserData;
        maName = r.maName;
        nHash = r.nHash;
    }
}

SbxEnsureParentVariable::SbxEnsureParentVariable(const SbxVariable& r)
    : SbxVariable(r)
    , xParent(const_cast<SbxVariable&>(r).GetParent())
{
    assert(GetParent() == xParent.get());
}

void SbxEnsureParentVariable::SetParent(SbxObject* p)
{
    assert(GetParent() == xParent.get());
    SbxVariable::SetParent(p);
    xParent = SbxObjectRef(p);
    assert(GetParent() == xParent.get());
}

SbxVariable::SbxVariable( SbxDataType t ) : SbxValue( t )
{
}

SbxVariable::~SbxVariable()
{
#if HAVE_FEATURE_SCRIPTING
    if( IsSet( SbxFlagBits::DimAsNew ))
    {
        removeDimAsNewRecoverItem( this );
    }
#endif
    mpBroadcaster.reset();
}

// Broadcasting

SfxBroadcaster& SbxVariable::GetBroadcaster()
{
    if( !mpBroadcaster )
    {
        mpBroadcaster.reset( new SfxBroadcaster );
    }
    return *mpBroadcaster;
}

SbxArray* SbxVariable::GetParameters() const
{
    return mpPar.get();
}


// Perhaps some day one could cut the parameter 0.
// Then the copying will be dropped...

void SbxVariable::Broadcast( SfxHintId nHintId )
{
    if( !mpBroadcaster || IsSet( SbxFlagBits::NoBroadcast ) )
        return;

    // Because the method could be called from outside, check the
    // rights here again
    if( nHintId == SfxHintId::BasicDataWanted )
    {
        if( !CanRead() )
        {
            return;
        }
    }
    if( nHintId == SfxHintId::BasicDataChanged )
    {
        if( !CanWrite() )
        {
            return;
        }
    }

    //fdo#86843 Add a ref during the following block to guard against
    //getting deleted before completing this method
    SbxVariableRef aBroadcastGuard(this);

    // Avoid further broadcasting
    std::unique_ptr<SfxBroadcaster> pSave = std::move(mpBroadcaster);
    SbxFlagBits nSaveFlags = GetFlags();
    SetFlag( SbxFlagBits::ReadWrite );
    if( mpPar.is() )
    {
        // Register this as element 0, but don't change over the parent!
        mpPar->GetRef(0) = this;
    }
    pSave->Broadcast( SbxHint( nHintId, this ) );
    mpBroadcaster = std::move(pSave);
    SetFlags( nSaveFlags );
}

SbxInfo* SbxVariable::GetInfo()
{
    if( !pInfo.is() )
    {
        Broadcast( SfxHintId::BasicInfoWanted );
        if( pInfo.is() )
        {
            SetModified( true );
        }
    }
    return pInfo.get();
}

void SbxVariable::SetInfo( SbxInfo* p )
{
    pInfo = p;
}

void SbxVariable::SetParameters( SbxArray* p )
{
    mpPar = p;
}


// Name of the variables

// static
OUString SbxVariable::NameToCaseInsensitiveName(const OUString& rName)
{
    return SbGlobal::GetTransliteration().transliterate(rName, 0, rName.getLength());
}

void SbxVariable::SetName( const OUString& rName )
{
    maName = rName;
    nHash = MakeHashCode( rName );
    maNameCI.clear();
}

const OUString& SbxVariable::GetName( SbxNameType t ) const
{
    static const char cSuffixes[] = " %&!#@ $";
    if( t == SbxNameType::NONE )
    {
        return maName;
    }
    if (t == SbxNameType::CaseInsensitive)
    {
        if (maNameCI.isEmpty() && !maName.isEmpty())
            maNameCI = NameToCaseInsensitiveName(maName);
        return maNameCI;
    }
    // Request parameter-information (not for objects)
    const_cast<SbxVariable*>(this)->GetInfo();
    // Append nothing, if it is a simple property (no empty brackets)
    if (!pInfo.is() || (pInfo->m_Params.empty() && GetClass() == SbxClassType::Property))
    {
        return maName;
    }
    OUStringBuffer aTmp( maName );
    if( t == SbxNameType::ShortTypes )
    {
        sal_Unicode cType = ' ';
        // short type? Then fetch it, possible this is 0.
        SbxDataType et = GetType();
        if( et <= SbxSTRING )
        {
            assert(et >= 0 && size_t(et) < std::size(cSuffixes) - 1);
            cType = cSuffixes[ et ];
        }
        if( cType != ' ' )
        {
            aTmp.append(cType);
        }
    }
    aTmp.append("(");

    for (SbxParams::const_iterator iter = pInfo->m_Params.begin(); iter != pInfo->m_Params.end(); ++iter)
    {
        auto const& i = *iter;
        int nt = i->eType & 0x0FFF;
        if (iter != pInfo->m_Params.begin())
        {
            aTmp.append(",");
        }
        if( i->nFlags & SbxFlagBits::Optional )
        {
            aTmp.append( GetSbxRes( StringId::Optional ) );
        }
        if( i->eType & SbxBYREF )
        {
            aTmp.append( GetSbxRes( StringId::ByRef ) );
        }
        aTmp.append( i->aName );
        sal_Unicode cType = ' ';
        // short type? Then fetch it, possible this is 0.
        if( t == SbxNameType::ShortTypes )
        {
            if( nt <= SbxSTRING )
            {
                cType = cSuffixes[ nt ];
            }
        }
        if( cType != ' ' )
        {
            aTmp.append(cType);
            if( i->eType & SbxARRAY )
            {
                aTmp.append("()");
            }
        }
        else
        {
            if( i->eType & SbxARRAY )
            {
                aTmp.append("()");
            }
            // long type?
            aTmp.append(GetSbxRes( StringId::As ));
            if( nt < 32 )
            {
                aTmp.append(GetSbxRes( static_cast<StringId>( static_cast<int>( StringId::Types ) + nt ) ));
            }
            else
            {
                aTmp.append(GetSbxRes( StringId::Any ));
            }
        }
    }
    aTmp.append(")");
    const_cast<SbxVariable*>(this)->aToolString = aTmp.makeStringAndClear();
    return aToolString;
}

// Operators

SbxVariable& SbxVariable::operator=( const SbxVariable& r )
{
    if (this != &r)
    {
        SbxValue::operator=( r );
        // tdf#144353 - copy information about a missing parameter. See SbiRuntime::SetIsMissing.
        // We cannot unconditionally assign the data about a variable because we would overwrite
        // the information about parameters (name, type, flags, and ids). For instance, in the case
        // where a method will be initialized with a literal.
        if (!pInfo)
            pInfo = r.pInfo;
        m_aDeclareClassName = r.m_aDeclareClassName;
        m_xComListener = r.m_xComListener;
        m_pComListenerParentBasic = r.m_pComListenerParentBasic;
#if HAVE_FEATURE_SCRIPTING
        if( m_xComListener.is() )
        {
            registerComListenerVariableForBasic( this, m_pComListenerParentBasic );
        }
#endif
    }
    return *this;
}

// Conversion

SbxDataType SbxVariable::GetType() const
{
    if( aData.eType == SbxOBJECT )
    {
        return aData.pObj ? aData.pObj->GetType() : SbxOBJECT;
    }
    else if( aData.eType == SbxVARIANT )
    {
        return aData.pObj ? aData.pObj->GetType() : SbxVARIANT;
    }
    else
    {
        return aData.eType;
    }
}

SbxClassType SbxVariable::GetClass() const
{
    return SbxClassType::Variable;
}

void SbxVariable::SetModified( bool b )
{
    if( IsSet( SbxFlagBits::NoModify ) )
    {
        return;
    }
    SbxBase::SetModified( b );
    if( pParent && pParent != this ) //??? HotFix: Recursion out here MM
    {
        pParent->SetModified( b );
    }
}

void SbxVariable::SetParent( SbxObject* p )
{
#ifdef DBG_UTIL
    // Will the parent of a SbxObject be set?
    if (p && dynamic_cast<SbxObject*>(this))
    {
        // then this had to be a child of the new parent
        bool bFound = false;
        SbxArray *pChildren = p->GetObjects();
        if ( pChildren )
        {
            for (sal_uInt32 nIdx = 0; !bFound && nIdx < pChildren->Count(); ++nIdx)
            {
                bFound = (this == pChildren->Get(nIdx));
            }
        }
        SAL_INFO_IF(
            !bFound, "basic.sbx",
            "dangling: [" << GetName() << "].SetParent([" << p->GetName()
                << "])");
    }
#endif

    pParent = p;
}

const OUString& SbxVariable::GetDeclareClassName() const
{
    return m_aDeclareClassName;
}

void SbxVariable::SetDeclareClassName( const OUString& rDeclareClassName )
{
    m_aDeclareClassName = rDeclareClassName;
}

void SbxVariable::SetComListener( const css::uno::Reference< css::uno::XInterface >& ;xComListener,
                                  StarBASIC* pParentBasic )
{
    m_xComListener = xComListener;
    m_pComListenerParentBasic = pParentBasic;
#if HAVE_FEATURE_SCRIPTING
    registerComListenerVariableForBasic( this, pParentBasic );
#endif
}

void SbxVariable::ClearComListener()
{
    m_xComListener.clear();
}


// Loading/Saving

bool SbxVariable::LoadData( SvStream& rStrm, sal_uInt16 nVer )
{
    sal_uInt8 cMark;
    rStrm.ReadUChar( cMark );
    if( cMark == 0xFF )
    {
        if( !SbxValue::LoadData( rStrm, nVer ) )
        {
            return false;
        }
        maName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
                                                                RTL_TEXTENCODING_ASCII_US);
        sal_uInt32 nTemp;
        rStrm.ReadUInt32( nTemp );
        nUserData = nTemp;
    }
    else
    {
        sal_uInt16 nType;
        rStrm.SeekRel( -1 );
        rStrm.ReadUInt16( nType );
        maName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
                                                                RTL_TEXTENCODING_ASCII_US);
        sal_uInt32 nTemp;
        rStrm.ReadUInt32( nTemp );
        nUserData = nTemp;
        // correction: old methods have instead of SbxNULL now SbxEMPTY
        if( nType == SbxNULL && GetClass() == SbxClassType::Method )
        {
            nType = SbxEMPTY;
        }
        SbxValues aTmp;
        OUString aTmpString;
        OUString aVal;
        aTmp.eType = aData.eType = static_cast<SbxDataType>(nType);
        aTmp.pOUString = &aVal;
        switch( nType )
        {
        case SbxBOOL:
        case SbxERROR:
        case SbxINTEGER:
            rStrm.ReadInt16( aTmp.nInteger ); break;
        case SbxLONG:
            rStrm.ReadInt32( aTmp.nLong ); break;
        case SbxSINGLE:
        {
            // Floats as ASCII
            aTmpString = read_uInt16_lenPrefixed_uInt8s_ToOUString(
                    rStrm, RTL_TEXTENCODING_ASCII_US);
            double d;
            SbxDataType t;
            if( ImpScan( aTmpString, d, t, nullptr ) != ERRCODE_NONE || t == SbxDOUBLE )
            {
                aTmp.nSingle = 0;
                return false;
            }
            aTmp.nSingle = static_cast<float>(d);
            break;
        }
        case SbxDATE:
        case SbxDOUBLE:
        {
            // Floats as ASCII
            aTmpString = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
                                                                        RTL_TEXTENCODING_ASCII_US);
            SbxDataType t;
            if( ImpScan( aTmpString, aTmp.nDouble, t, nullptr ) != ERRCODE_NONE )
            {
                aTmp.nDouble = 0;
                return false;
            }
            break;
        }
        case SbxSTRING:
            aVal = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
                                                                  RTL_TEXTENCODING_ASCII_US);
            break;
        case SbxEMPTY:
        case SbxNULL:
            break;
        default:
            aData.eType = SbxNULL;
            SAL_WARN( "basic.sbx""Loaded a non-supported data type" );
            return false;
        }
        // putt value
        if( nType != SbxNULL && nType != SbxEMPTY && !Put( aTmp ) )
        {
            return false;
        }
    }
    rStrm.ReadUChar( cMark );
    // cMark is also a version number!
    // 1: initial version
    // 2: with nUserData
    if( cMark )
    {
        if( cMark > 2 )
        {
            return false;
        }
        pInfo = new SbxInfo;
        pInfo->LoadData( rStrm, static_cast<sal_uInt16>(cMark) );
    }
    Broadcast( SfxHintId::BasicDataChanged );
    nHash =  MakeHashCode( maName );
    SetModified( true );
    return true;
}

std::pair<bool, sal_uInt32> SbxVariable::StoreData( SvStream& rStrm ) const
{
    rStrm.WriteUChar( 0xFF );      // Marker
    bool bValStore;
    ifdynamic_cast<const SbxMethod *>(this) != nullptr )
    {
        // #50200 Avoid that objects , which during the runtime
        // as return-value are saved in the method as a value were saved
        SbxVariable* pThis = const_cast<SbxVariable*>(this);
        SbxFlagBits nSaveFlags = GetFlags();
        pThis->SetFlag( SbxFlagBits::Write );
        pThis->SbxValue::Clear();
        pThis->SetFlags( nSaveFlags );

        // So that the method will not be executed in any case!
        // CAST, to avoid const!
        pThis->SetFlag( SbxFlagBits::NoBroadcast );
        bValStore = SbxValue::StoreData( rStrm ).first;
        pThis->ResetFlag( SbxFlagBits::NoBroadcast );
    }
    else
    {
        bValStore = SbxValue::StoreData( rStrm ).first;
    }
    if( !bValStore )
    {
        return { false, 0 };
    }
    write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, maName,
                                                      RTL_TEXTENCODING_ASCII_US);
    rStrm.WriteUInt32( nUserData );
    if( pInfo.is() )
    {
        rStrm.WriteUChar( 2 );     // Version 2: with UserData!
        pInfo->StoreData( rStrm );
    }
    else
    {
        rStrm.WriteUChar( 0 );
    }
    return { true, B_IMG_VERSION_12 };
}

// SbxInfo

SbxInfo::SbxInfo()
        :  nHelpId(0)
{}

SbxInfo::SbxInfo( OUString a, sal_uInt32 n )
       : aHelpFile(std::move( a )), nHelpId( n )
{}

SbxHint::~SbxHint() = default;

void SbxVariable::Dump( SvStream& rStrm, bool bFill )
{
    OString aBNameStr(OUStringToOString(GetName( SbxNameType::ShortTypes ), RTL_TEXTENCODING_ASCII_US));
    rStrm.WriteOString( "Variable( " )
         .WriteOString( OString::number(reinterpret_cast<sal_IntPtr>(this)) ).WriteOString( "==" )
         .WriteOString( aBNameStr );
    OString aBParentNameStr(OUStringToOString(GetParent()->GetName(), RTL_TEXTENCODING_ASCII_US));
    if ( GetParent() )
    {
        rStrm.WriteOString( " in parent '" ).WriteOString( aBParentNameStr ).WriteOString( "'" );
    }
    else
    {
        rStrm.WriteOString( " no parent" );
    }
    rStrm.WriteOString( " ) " );

    // output also the object at object-vars
    if ( GetValues_Impl().eType == SbxOBJECT &&
            GetValues_Impl().pObj &&
            GetValues_Impl().pObj != this &&
            GetValues_Impl().pObj != GetParent() )
    {
        rStrm.WriteOString( " contains " );
        static_cast<SbxObject*>(GetValues_Impl().pObj)->Dump( rStrm, bFill );
    }
    else
    {
        rStrm << endl;
    }
}

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

Messung V0.5
C=93 H=97 G=94

¤ Dauer der Verarbeitung: 0.15 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.