    /* -*- 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 <sal/config.h>

    #include <sal/log.hxx>
    #include <comphelper/fileformat.h>
    #include <tools/stream.hxx>

    #include <svl/macitem.hxx>
    #include <stringio.hxx>

    SvxMacro::SvxMacro( const OUString &rMacName, const OUString &rLanguage)
        : aMacName( rMacName ), aLibName( rLanguage),
          eType( EXTENDED_STYPE)
    {
        if ( rLanguage == SVX_MACRO_LANGUAGE_STARBASIC )
            eType=STARBASIC;
        else if ( rLanguage == SVX_MACRO_LANGUAGE_JAVASCRIPT )
            eType=JAVASCRIPT;
    }

    OUString SvxMacro::GetLanguage()const
    {
        if(eType==STARBASIC)
        {
            return OUString(SVX_MACRO_LANGUAGE_STARBASIC);
        }
        else if(eType==JAVASCRIPT)
        {
            return OUString(SVX_MACRO_LANGUAGE_JAVASCRIPT);
        }
        else if(eType==EXTENDED_STYPE)
        {
            return OUString(SVX_MACRO_LANGUAGE_SF);

        }
        return aLibName;
    }

    SvxMacro& SvxMacro::operator=( const SvxMacro& rBase )
    {
        if( this != &rBase )
        {
            aMacName = rBase.aMacName;
            aLibName = rBase.aLibName;
            eType = rBase.eType;
        }
        return *this;
    }

    SvxMacroTableDtor& SvxMacroTableDtor::operator=( const SvxMacroTableDtor& rTbl )
    {
        aSvxMacroTable.clear();
        aSvxMacroTable.insert(rTbl.aSvxMacroTable.begin(), rTbl.aSvxMacroTable.end());
        return *this;
    }

    bool SvxMacroTableDtor::operator==( const SvxMacroTableDtor& rOther ) const
    {
        // Count different => odd in any case
        if ( aSvxMacroTable.size() != rOther.aSvxMacroTable.size() )
            return false;

        // Compare single ones; the sequence matters due to performance reasons
        SvxMacroTable::const_iterator it1 = aSvxMacroTable.begin();
        SvxMacroTable::const_iterator it2 = rOther.aSvxMacroTable.begin();
        for ( ; it1 != aSvxMacroTable.end(); ++it1, ++it2 )
        {
            const SvxMacro& rOwnMac = it1->second;
            const SvxMacro& rOtherMac = it2->second;
            if (    it1->first != it2->first ||
                    rOwnMac.GetLibName() != rOtherMac.GetLibName() ||
                    rOwnMac.GetMacName() != rOtherMac.GetMacName() )
                return false;
        }

        return true;
    }

    void SvxMacroTableDtor::Read( SvStream& rStrm )
    {
        sal_uInt16 nVersion;
        rStrm.ReadUInt16( nVersion );

        short nMacro(0);
        rStrm.ReadInt16(nMacro);
        if (nMacro < 0)
        {
            SAL_WARN("editeng", "Parsing error: negative value " << nMacro);
            return;
        }

        const size_t nMinStringSize = rStrm.GetStreamCharSet() == RTL_TEXTENCODING_UNICODE ? 4 : 2;
        size_t nMinRecordSize = 2 + 2*nMinStringSize;
        if( SVX_MACROTBL_VERSION40 <= nVersion )
            nMinRecordSize+=2;

        const size_t nMaxRecords = rStrm.remainingSize() / nMinRecordSize;
        if (static_cast<size_t>(nMacro) > nMaxRecords)
        {
            SAL_WARN("editeng", "Parsing error: " << nMaxRecords <<
                     " max possible entries, but " << nMacro<< " claimed, truncating");
            nMacro = nMaxRecords;
        }

        for (short i = 0; i < nMacro; ++i)
        {
            sal_uInt16 nCurKey, eType = STARBASIC;
            OUString aLibName, aMacName;
            rStrm.ReadUInt16( nCurKey );
            aLibName = readByteString(rStrm);
            aMacName = readByteString(rStrm);

            if( SVX_MACROTBL_VERSION40 <= nVersion )
                rStrm.ReadUInt16( eType );

            aSvxMacroTable.emplace( SvMacroItemId(nCurKey), SvxMacro( aMacName, aLibName, static_cast<ScriptType>(eType) ) );
        }
    }

    SvStream& SvxMacroTableDtor::Write( SvStream& rStream ) const
    {
        sal_uInt16 nVersion = SOFFICE_FILEFORMAT_31 == rStream.GetVersion()
                                        ? SVX_MACROTBL_VERSION31
                                        : SVX_MACROTBL_AKTVERSION;

        if( SVX_MACROTBL_VERSION40 <= nVersion )
            rStream.WriteUInt16( nVersion );

        rStream.WriteUInt16( aSvxMacroTable.size() );

        SvxMacroTable::const_iterator it = aSvxMacroTable.begin();
        while( it != aSvxMacroTable.end() && rStream.GetError() == ERRCODE_NONE )
        {
            const SvxMacro& rMac = it->second;
            rStream.WriteUInt16( static_cast<sal_uInt16>(it->first) );
            writeByteString(rStream, rMac.GetLibName());
            writeByteString(rStream, rMac.GetMacName());

            if( SVX_MACROTBL_VERSION40 <= nVersion )
                rStream.WriteUInt16( rMac.GetScriptType() );
            ++it;
        }
        return rStream;
    }

    // returns NULL if no entry exists, or a pointer to the internal value
    const SvxMacro* SvxMacroTableDtor::Get(SvMacroItemId nEvent) const
    {
        SvxMacroTable::const_iterator it = aSvxMacroTable.find(nEvent);
        return it == aSvxMacroTable.end() ? nullptr : &(it->second);
    }

    // returns NULL if no entry exists, or a pointer to the internal value
    SvxMacro* SvxMacroTableDtor::Get(SvMacroItemId nEvent)
    {
        SvxMacroTable::iterator it = aSvxMacroTable.find(nEvent);
        return it == aSvxMacroTable.end() ? nullptr : &(it->second);
    }

    // return true if the key exists
    bool SvxMacroTableDtor::IsKeyValid(SvMacroItemId nEvent) const
    {
        SvxMacroTable::const_iterator it = aSvxMacroTable.find(nEvent);
        return it != aSvxMacroTable.end();
    }

    // This stores a copy of the rMacro parameter
    SvxMacro& SvxMacroTableDtor::Insert(SvMacroItemId nEvent, const SvxMacro& rMacro)
    {
        return aSvxMacroTable.emplace( nEvent, rMacro ).first->second;
    }

    // If the entry exists, remove it from the map and release it's storage
    void SvxMacroTableDtor::Erase(SvMacroItemId nEvent)
    {
        SvxMacroTable::iterator it = aSvxMacroTable.find(nEvent);
        if ( it != aSvxMacroTable.end())
        {
            aSvxMacroTable.erase(it);
        }
    }

    bool SvxMacroItem::operator==( const SfxPoolItem& rAttr ) const
    {
        assert(SfxPoolItem::operator==(rAttr));

        const SvxMacroTableDtor& rOwn = aMacroTable;
        const SvxMacroTableDtor& rOther = static_cast<const SvxMacroItem&>(rAttr).aMacroTable;

        return rOwn == rOther;
    }

    SfxPoolItem* SvxMacroItem::Clone( SfxItemPool* ) const
    {
        return new SvxMacroItem( *this );
    }

    bool SvxMacroItem::GetPresentation
    (
        SfxItemPresentation /*ePres*/,
        MapUnit             /*eCoreUnit*/,
        MapUnit             /*ePresUnit*/,
        OUString&           rText,
        const IntlWrapper&
    )   const
    {
    /*!!!
        SvxMacroTableDtor& rTbl = (SvxMacroTableDtor&)GetMacroTable();
        SvxMacro* pMac = rTbl.First();

        while ( pMac )
        {
            rText += pMac->GetLibName();
            rText += cpDelim;
            rText += pMac->GetMacName();
            pMac = rTbl.Next();
            if ( pMac )
                rText += cpDelim;
        }
    */
        rText.clear();
        return false;
    }

    void SvxMacroItem::SetMacro( SvMacroItemId nEvent, const SvxMacro& rMacro )
    {
        aMacroTable.Insert( nEvent, rMacro);
    }

    sal_uInt16 SvxMacroItem::GetVersion( sal_uInt16 nFileFormatVersion ) const
    {
        return SOFFICE_FILEFORMAT_31 == nFileFormatVersion
                    ? 0 : SvxMacroTableDtor::GetVersion();
    }

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

↑ V794 The assignment operator should be protected from the case of 'this == &rTbl'.