    /* -*- 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 <cmdid.h>
    #include <hintids.hxx>
    #include <svl/stritem.hxx>
    #include <com/sun/star/text/DefaultNumberingProvider.hpp>
    #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
    #include <com/sun/star/text/XNumberingTypeInfo.hpp>
    #include <com/sun/star/style/NumberingType.hpp>
    #include <com/sun/star/beans/XPropertySet.hpp>
    #include <com/sun/star/sdbc/XConnection.hpp>
    #include <com/sun/star/sdbc/XDataSource.hpp>
    #include <com/sun/star/uri/UriReferenceFactory.hpp>
    #include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
    #include <comphelper/processfactory.hxx>
    #include <comphelper/string.hxx>
    #include <editeng/unolingu.hxx>
    #include <unotools/localedatawrapper.hxx>
    #include <tools/resary.hxx>
    #include <sfx2/dispatch.hxx>
    #include <sfx2/objsh.hxx>
    #include <sfx2/linkmgr.hxx>
    #include <sfx2/app.hxx>
    #include <svx/dialogs.hrc>
    #include <svx/strarray.hxx>
    #include <basic/basmgr.hxx>
    #include <editeng/langitem.hxx>
    #include <svl/macitem.hxx>
    #include <basic/sbmod.hxx>
    #include <fmtrfmrk.hxx>
    #include <basic/sbmeth.hxx>
    #include <basic/sbx.hxx>
    #include <svl/zforlist.hxx>
    #include <svl/zformat.hxx>
    #include <vcl/mnemonic.hxx>
    #include <view.hxx>
    #include <wrtsh.hxx>
    #include <doc.hxx>
    #include <docsh.hxx>
    #include <swmodule.hxx>
    #include <charatr.hxx>
    #include <fmtinfmt.hxx>
    #include <cellatr.hxx>
    #include <dbmgr.hxx>
    #include <shellres.hxx>
    #include <fldbas.hxx>
    #include <docufld.hxx>
    #include <chpfld.hxx>
    #include <ddefld.hxx>
    #include <expfld.hxx>
    #include <reffld.hxx>
    #include <usrfld.hxx>
    #include <dbfld.hxx>
    #include <authfld.hxx>
    #include <flddat.hxx>
    #include <fldmgr.hxx>
    #include <flddropdown.hxx>
    #include <strings.hrc>
    #include <tox.hxx>
    #include <cnttab.hxx>
    #include <unotools/useroptions.hxx>

    using namespace com::sun::star::uno;
    using namespace com::sun::star::container;
    using namespace com::sun::star::lang;
    using namespace com::sun::star::beans;
    using namespace com::sun::star::text;
    using namespace com::sun::star::style;
    using namespace com::sun::star::sdbc;
    using namespace ::com::sun::star;
    using namespace nsSwDocInfoSubType;

    // groups of fields
    enum
    {
        GRP_DOC_BEGIN   =  0,
        GRP_DOC_END     =  GRP_DOC_BEGIN + 12,

        GRP_FKT_BEGIN   =  GRP_DOC_END,
        GRP_FKT_END     =  GRP_FKT_BEGIN + 8,

        GRP_REF_BEGIN   =  GRP_FKT_END,
        GRP_REF_END     =  GRP_REF_BEGIN + 2,

        GRP_REG_BEGIN   =  GRP_REF_END,
        GRP_REG_END     =  GRP_REG_BEGIN + 1,

        GRP_DB_BEGIN    =  GRP_REG_END,
        GRP_DB_END      =  GRP_DB_BEGIN  + 5,

        GRP_VAR_BEGIN   =  GRP_DB_END,
        GRP_VAR_END     =  GRP_VAR_BEGIN + 9
    };

    enum
    {
        GRP_WEB_DOC_BEGIN   =  0,
        GRP_WEB_DOC_END     =  GRP_WEB_DOC_BEGIN + 9,

        GRP_WEB_FKT_BEGIN   =  GRP_WEB_DOC_END + 2,
        GRP_WEB_FKT_END     =  GRP_WEB_FKT_BEGIN + 0,   // the group is empty!

        GRP_WEB_REF_BEGIN   =  GRP_WEB_FKT_END + 6,     // the group is empty!
        GRP_WEB_REF_END     =  GRP_WEB_REF_BEGIN + 0,

        GRP_WEB_REG_BEGIN   =  GRP_WEB_REF_END + 2,
        GRP_WEB_REG_END     =  GRP_WEB_REG_BEGIN + 1,

        GRP_WEB_DB_BEGIN    =  GRP_WEB_REG_END,         // the group is empty!
        GRP_WEB_DB_END      =  GRP_WEB_DB_BEGIN  + 0,

        GRP_WEB_VAR_BEGIN   =  GRP_WEB_DB_END + 5,
        GRP_WEB_VAR_END     =  GRP_WEB_VAR_BEGIN + 1
    };

    static const sal_uInt16 VF_COUNT = 1; // { 0 }
    static const sal_uInt16 VF_USR_COUNT = 2; // { 0, nsSwExtendedSubType::SUB_CMD }
    static const sal_uInt16 VF_DB_COUNT = 1; // { nsSwExtendedSubType::SUB_OWN_FMT }

    static const char* FLD_EU_ARY[] =
    {
        FLD_EU_FIRMA,
        FLD_EU_VORNAME,
        FLD_EU_NAME,
        FLD_EU_ABK,
        FLD_EU_STRASSE,
        FLD_EU_LAND,
        FLD_EU_PLZ,
        FLD_EU_ORT,
        FLD_EU_TITEL,
        FLD_EU_POS,
        FLD_EU_TELPRIV,
        FLD_EU_TELFIRMA,
        FLD_EU_FAX,
        FLD_EU_EMAIL,
        FLD_EU_STATE
    };

    static const char* FMT_AUTHOR_ARY[] =
    {
        FMT_AUTHOR_NAME,
        FMT_AUTHOR_SCUT
    };

    static const char* FLD_DATE_ARY[] =
    {
        FLD_DATE_FIX,
        FLD_DATE_STD,
    };

    static const char* FLD_TIME_ARY[] =
    {
        FLD_TIME_FIX,
        FLD_TIME_STD
    };

    static const char* FMT_NUM_ARY[] =
    {
        FMT_NUM_ABC,
        FMT_NUM_SABC,
        FMT_NUM_ABC_N,
        FMT_NUM_SABC_N,
        FMT_NUM_ROMAN,
        FMT_NUM_SROMAN,
        FMT_NUM_ARABIC,
        FMT_NUM_PAGEDESC,
        FMT_NUM_PAGESPECIAL
    };

    static const char* FMT_FF_ARY[] =
    {
        FMT_FF_NAME,
        FMT_FF_PATHNAME,
        FMT_FF_PATH,
        FMT_FF_NAME_NOEXT,
        FMT_FF_UI_NAME,
        FMT_FF_UI_RANGE
    };

    static const char* FLD_STAT_ARY[] =
    {
        FLD_STAT_PAGE,
        FLD_STAT_PARA,
        FLD_STAT_WORD,
        FLD_STAT_CHAR,
        FLD_STAT_TABLE,
        FLD_STAT_GRF,
        FLD_STAT_OBJ
    };

    static const char* FMT_CHAPTER_ARY[] =
    {
        FMT_CHAPTER_NO,
        FMT_CHAPTER_NAME,
        FMT_CHAPTER_NAMENO,
        FMT_CHAPTER_NO_NOSEPARATOR
    };

    static const char* FLD_INPUT_ARY[] =
    {
        FLD_INPUT_TEXT
    };

    static const char* FMT_MARK_ARY[] =
    {
        FMT_MARK_TEXT,
        FMT_MARK_TABLE,
        FMT_MARK_FRAME,
        FMT_MARK_GRAFIC,
        FMT_MARK_OLE
    };

    static const char* FMT_REF_ARY[] =
    {
        FMT_REF_PAGE,
        FMT_REF_CHAPTER,
        FMT_REF_TEXT,
        FMT_REF_UPDOWN,
        FMT_REF_PAGE_PGDSC,
        FMT_REF_ONLYNUMBER,
        FMT_REF_ONLYCAPTION,
        FMT_REF_ONLYSEQNO,
        FMT_REF_NUMBER,
        FMT_REF_NUMBER_NO_CONTEXT,
        FMT_REF_NUMBER_FULL_CONTEXT
    };

    static const char* FMT_REG_ARY[] =
    {
        FMT_REG_AUTHOR,
        FMT_REG_TIME,
        FMT_REG_DATE
    };

    static const char* FMT_DBFLD_ARY[] =
    {
        FMT_DBFLD_DB,
        FMT_DBFLD_SYS
    };

    static const char* FMT_SETVAR_ARY[] =
    {
        FMT_SETVAR_SYS,
        FMT_SETVAR_TEXT
    };

    static const char* FMT_GETVAR_ARY[] =
    {
        FMT_GETVAR_TEXT,
        FMT_GETVAR_NAME
    };

    static const char* FMT_DDE_ARY[] =
    {
        FMT_DDE_NORMAL,
        FMT_DDE_HOT
    };

    static const char* FLD_PAGEREF_ARY[] =
    {
        FLD_PAGEREF_OFF,
        FLD_PAGEREF_ON
    };

    static const char* FMT_USERVAR_ARY[] =
    {
        FMT_USERVAR_TEXT,
        FMT_USERVAR_CMD
    };

    // field types and subtypes
    struct SwFieldPack
    {
        sal_uInt16   nTypeId;

        const char** pSubTypeResIds;
        size_t       nSubTypeLength;

        const char** pFormatResIds;
        size_t       nFormatLength;
    };

    // strings and formats
    static const SwFieldPack aSwFields[] =
    {
        // Document
        { TYP_EXTUSERFLD,       FLD_EU_ARY,         SAL_N_ELEMENTS(FLD_EU_ARY),     nullptr,          0 },
        { TYP_AUTHORFLD,        nullptr,            0,                              FMT_AUTHOR_ARY,   SAL_N_ELEMENTS(FMT_AUTHOR_ARY) },
        { TYP_DATEFLD,          FLD_DATE_ARY,       SAL_N_ELEMENTS(FLD_DATE_ARY),   nullptr,          0 },
        { TYP_TIMEFLD,          FLD_TIME_ARY,       SAL_N_ELEMENTS(FLD_TIME_ARY),   nullptr,          0 },
        { TYP_PAGENUMBERFLD,    nullptr,            0,                              FMT_NUM_ARY,      SAL_N_ELEMENTS(FMT_NUM_ARY) -1 },
        { TYP_NEXTPAGEFLD,      nullptr,            0,                              FMT_NUM_ARY,      SAL_N_ELEMENTS(FMT_NUM_ARY) },
        { TYP_PREVPAGEFLD,      nullptr,            0,                              FMT_NUM_ARY,      SAL_N_ELEMENTS(FMT_NUM_ARY) },
        { TYP_FILENAMEFLD,      nullptr,            0,                              FMT_FF_ARY,       SAL_N_ELEMENTS(FMT_FF_ARY) },
        { TYP_DOCSTATFLD,       FLD_STAT_ARY,       SAL_N_ELEMENTS(FLD_STAT_ARY),   FMT_NUM_ARY,      SAL_N_ELEMENTS(FMT_NUM_ARY) -1 },

        { TYP_CHAPTERFLD,       nullptr,            0,                              FMT_CHAPTER_ARY,  SAL_N_ELEMENTS(FMT_CHAPTER_ARY) },
        { TYP_TEMPLNAMEFLD,     nullptr,            0,                              FMT_FF_ARY,       SAL_N_ELEMENTS(FMT_FF_ARY) },
        { TYP_PARAGRAPHSIGFLD,  nullptr,            0,                              nullptr,          0 },

        // Functions
        { TYP_CONDTXTFLD,       nullptr,            0,                              nullptr,          0 },
        { TYP_DROPDOWN,         nullptr,            0,                              nullptr,          0 },
        { TYP_INPUTFLD,         FLD_INPUT_ARY,      SAL_N_ELEMENTS(FLD_INPUT_ARY),  nullptr,          0 },
        { TYP_MACROFLD,         nullptr,            0,                              nullptr,          0 },
        { TYP_JUMPEDITFLD,      nullptr,            0,                              FMT_MARK_ARY,     SAL_N_ELEMENTS(FMT_MARK_ARY) },
        { TYP_COMBINED_CHARS,   nullptr,            0,                              nullptr,          0 },
        { TYP_HIDDENTXTFLD,     nullptr,            0,                              nullptr,          0 },
        { TYP_HIDDENPARAFLD,    nullptr,            0,                              nullptr,          0 },

        // Cross-References
        { TYP_SETREFFLD,        nullptr,            0,                              nullptr,          0 },
        { TYP_GETREFFLD,        nullptr,            0,                              FMT_REF_ARY,      SAL_N_ELEMENTS(FMT_REF_ARY) },

        // DocInformation
        { TYP_DOCINFOFLD,       nullptr,            0,                              FMT_REG_ARY,      SAL_N_ELEMENTS(FMT_REG_ARY) },

        // Database
        { TYP_DBFLD,            nullptr,            0,                              FMT_DBFLD_ARY,    SAL_N_ELEMENTS(FMT_DBFLD_ARY) },
        { TYP_DBNEXTSETFLD,     nullptr,            0,                              nullptr,          0 },
        { TYP_DBNUMSETFLD,      nullptr,            0,                              nullptr,          0 },
        { TYP_DBSETNUMBERFLD,   nullptr,            0,                              FMT_NUM_ARY,      SAL_N_ELEMENTS(FMT_NUM_ARY) - 2 },
        { TYP_DBNAMEFLD,        nullptr,            0,                              nullptr,          0 },

        // Variables
        { TYP_SETFLD,           nullptr,            0,                              FMT_SETVAR_ARY,   SAL_N_ELEMENTS(FMT_SETVAR_ARY) },

        { TYP_GETFLD,           nullptr,            0,                              FMT_GETVAR_ARY,   SAL_N_ELEMENTS(FMT_GETVAR_ARY) },
        { TYP_DDEFLD,           nullptr,            0,                              FMT_DDE_ARY,      SAL_N_ELEMENTS(FMT_DDE_ARY) },
        { TYP_FORMELFLD,        nullptr,            0,                              FMT_GETVAR_ARY,   SAL_N_ELEMENTS(FMT_GETVAR_ARY) },
        { TYP_INPUTFLD,         FLD_INPUT_ARY,      SAL_N_ELEMENTS(FLD_INPUT_ARY),  nullptr,          0 },
        { TYP_SEQFLD,           nullptr,            0,                              FMT_NUM_ARY,      SAL_N_ELEMENTS(FMT_NUM_ARY) - 2 },
        { TYP_SETREFPAGEFLD,    FLD_PAGEREF_ARY,    SAL_N_ELEMENTS(FLD_PAGEREF_ARY),nullptr,          0 },
        { TYP_GETREFPAGEFLD,    nullptr,            0,                              FMT_NUM_ARY,      SAL_N_ELEMENTS(FMT_NUM_ARY) - 1 },
        { TYP_USERFLD,          nullptr,            0,                              FMT_USERVAR_ARY,  SAL_N_ELEMENTS(FMT_USERVAR_ARY) }
    };

    // access to the shell
    static SwWrtShell* lcl_GetShell()
    {
        SwView* pView;
        if ( nullptr != (pView = ::GetActiveView()) )
            return pView->GetWrtShellPtr();
        OSL_FAIL("no current shell found!");
        return nullptr;
    }

    inline sal_uInt16 GetPackCount() {  return SAL_N_ELEMENTS(aSwFields); }

    // FieldManager controls inserting and updating of fields
    SwFieldMgr::SwFieldMgr(SwWrtShell* pSh ) :
        m_pWrtShell(pSh),
        m_bEvalExp(true)
    {
        // determine current field if existing
        GetCurField();
    }

    SwFieldMgr::~SwFieldMgr()
    {
    }

    // organise RefMark by names
    bool  SwFieldMgr::CanInsertRefMark( const OUString& rStr )
    {
        bool bRet = false;
        SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
        OSL_ENSURE(pSh, "no SwWrtShell found");
        if(pSh)
        {
            sal_uInt16 nCnt = pSh->GetCursorCnt();

            // the last Cursor doesn't have to be a spanned selection
            if( 1 < nCnt && !pSh->SwCursorShell::HasSelection() )
                --nCnt;

            bRet =  2 > nCnt && nullptr == pSh->GetRefMark( rStr );
        }
        return bRet;
    }

    // access over ResIds
    void SwFieldMgr::RemoveFieldType(SwFieldIds nResId, const OUString& rName )
    {
        SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
        OSL_ENSURE(pSh, "no SwWrtShell found");
        if( pSh )
            pSh->RemoveFieldType(nResId, rName);
    }

    size_t SwFieldMgr::GetFieldTypeCount() const
    {
        SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
        OSL_ENSURE(pSh, "no SwWrtShell found");
        return pSh ? pSh->GetFieldTypeCount() : 0;
    }

    SwFieldType* SwFieldMgr::GetFieldType(SwFieldIds nResId, size_t nField) const
    {
        SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
        OSL_ENSURE(pSh, "no SwWrtShell found");
        return pSh ? pSh->GetFieldType(nField, nResId) : nullptr;
    }

    SwFieldType* SwFieldMgr::GetFieldType(SwFieldIds nResId, const OUString& rName) const
    {
        SwWrtShell * pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
        OSL_ENSURE(pSh, "no SwWrtShell found");
        return pSh ? pSh->GetFieldType(nResId, rName) : nullptr;
    }

    // determine current field
    SwField* SwFieldMgr::GetCurField()
    {
        SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
        if ( pSh )
            m_pCurField = pSh->GetCurField( true );
        else
            m_pCurField = nullptr;

        // initialise strings and format
        m_aCurPar1.clear();
        m_aCurPar2.clear();
        m_sCurFrame.clear();
        m_nCurFormat = 0;

        if(!m_pCurField)
            return nullptr;

        // preprocess current values; determine parameter 1 and parameter 2
        // as well as the format
        const sal_uInt16 nTypeId = m_pCurField->GetTypeId();

        m_nCurFormat     = m_pCurField->GetFormat();
        m_aCurPar1    = m_pCurField->GetPar1();
        m_aCurPar2    = m_pCurField->GetPar2();

        switch( nTypeId )
        {
            case TYP_PAGENUMBERFLD:
            case TYP_NEXTPAGEFLD:
            case TYP_PREVPAGEFLD:
            case TYP_GETREFPAGEFLD:
                if( m_nCurFormat == SVX_NUM_PAGEDESC )
                    m_nCurFormat -= 2;
                break;
        }
        return m_pCurField;
    }

    // provide group range
    const SwFieldGroupRgn& SwFieldMgr::GetGroupRange(bool bHtmlMode, sal_uInt16 nGrpId)
    {
    static SwFieldGroupRgn const aRanges[] =
    {
        { /* Document   */  GRP_DOC_BEGIN,  GRP_DOC_END },
        { /* Functions  */  GRP_FKT_BEGIN,  GRP_FKT_END },
        { /* Cross-Refs */  GRP_REF_BEGIN,  GRP_REF_END },
        { /* DocInfos   */  GRP_REG_BEGIN,  GRP_REG_END },
        { /* Database   */  GRP_DB_BEGIN,   GRP_DB_END  },
        { /* User       */  GRP_VAR_BEGIN,  GRP_VAR_END }
    };
    static SwFieldGroupRgn const aWebRanges[] =
    {
        { /* Document    */  GRP_WEB_DOC_BEGIN,  GRP_WEB_DOC_END },
        { /* Functions   */  GRP_WEB_FKT_BEGIN,  GRP_WEB_FKT_END },
        { /* Cross-Refs  */  GRP_WEB_REF_BEGIN,  GRP_WEB_REF_END },
        { /* DocInfos    */  GRP_WEB_REG_BEGIN,  GRP_WEB_REG_END },
        { /* Database    */  GRP_WEB_DB_BEGIN,   GRP_WEB_DB_END  },
        { /* User        */  GRP_WEB_VAR_BEGIN,  GRP_WEB_VAR_END }
    };

        if (bHtmlMode)
            return aWebRanges[nGrpId];
        else
            return aRanges[nGrpId];
    }

    // determine GroupId
    sal_uInt16 SwFieldMgr::GetGroup(sal_uInt16 nTypeId, sal_uInt16 nSubType)
    {
        if (nTypeId == TYP_SETINPFLD)
            nTypeId = TYP_SETFLD;

        if (nTypeId == TYP_INPUTFLD && (nSubType & INP_USR))
            nTypeId = TYP_USERFLD;

        if (nTypeId == TYP_FIXDATEFLD)
            nTypeId = TYP_DATEFLD;

        if (nTypeId == TYP_FIXTIMEFLD)
            nTypeId = TYP_TIMEFLD;

        for (sal_uInt16 i = GRP_DOC; i <= GRP_VAR; i++)
        {
            const SwFieldGroupRgn& rRange = GetGroupRange(false/*bHtmlMode*/, i);
            for (sal_uInt16 nPos = rRange.nStart; nPos < rRange.nEnd; nPos++)
            {
                if (aSwFields[nPos].nTypeId == nTypeId)
                    return i;
            }
        }
        return USHRT_MAX;
    }

    // determine names to TypeId
    //  ACCESS over TYP_....
    sal_uInt16 SwFieldMgr::GetTypeId(sal_uInt16 nPos)
    {
        OSL_ENSURE(nPos < ::GetPackCount(), "forbidden Pos");
        return aSwFields[ nPos ].nTypeId;
    }

    OUString SwFieldMgr::GetTypeStr(sal_uInt16 nPos)
    {
        OSL_ENSURE(nPos < ::GetPackCount(), "forbidden TypeId");

        sal_uInt16 nFieldWh = aSwFields[ nPos ].nTypeId;

        // special treatment for date/time fields (without var/fix)
        if( TYP_DATEFLD == nFieldWh )
        {
            static OUString g_aDate( SwResId( STR_DATEFLD ) );
            return g_aDate;
        }
        if( TYP_TIMEFLD == nFieldWh )
        {
            static OUString g_aTime( SwResId( STR_TIMEFLD ) );
            return g_aTime;
        }

        return SwFieldType::GetTypeStr( nFieldWh );
    }

    // determine Pos in the list
    sal_uInt16 SwFieldMgr::GetPos(sal_uInt16 nTypeId)
    {
        switch( nTypeId )
        {
            case TYP_FIXDATEFLD:        nTypeId = TYP_DATEFLD;      break;
            case TYP_FIXTIMEFLD:        nTypeId = TYP_TIMEFLD;      break;
            case TYP_SETINPFLD:         nTypeId = TYP_SETFLD;       break;
            case TYP_USRINPFLD:         nTypeId = TYP_USERFLD;      break;
        }

        for(sal_uInt16 i = 0; i < GetPackCount(); i++)
            if(aSwFields[i].nTypeId == nTypeId)
                return i;

        return USHRT_MAX;
    }

    // localise subtypes of a field
    void SwFieldMgr::GetSubTypes(sal_uInt16 nTypeId, std::vector<OUString>& rToFill)
    {
        SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
        OSL_ENSURE(pSh, "no SwWrtShell found");
        if(pSh)
        {
            const sal_uInt16 nPos = GetPos(nTypeId);

            switch(nTypeId)
            {
                case TYP_SETREFFLD:
                case TYP_GETREFFLD:
                {
                    // references are no fields
                    pSh->GetRefMarks( &rToFill );
                    break;
                }
                case TYP_MACROFLD:
                {
                    break;
                }
                case TYP_INPUTFLD:
                {
                    rToFill.push_back(SwResId(aSwFields[nPos].pSubTypeResIds[0]));
                    SAL_FALLTHROUGH; // move on at generic types
                }
                case TYP_DDEFLD:
                case TYP_SEQFLD:
                case TYP_FORMELFLD:
                case TYP_GETFLD:
                case TYP_SETFLD:
                case TYP_USERFLD:
                {

                    const size_t nCount = pSh->GetFieldTypeCount();
                    for(size_t i = 0; i < nCount; ++i)
                    {
                        SwFieldType* pFieldType = pSh->GetFieldType( i );
                        const SwFieldIds nWhich = pFieldType->Which();

                        if((nTypeId == TYP_DDEFLD && pFieldType->Which() == SwFieldIds::Dde) ||

                           (nTypeId == TYP_USERFLD && nWhich == SwFieldIds::User) ||

                           (nTypeId == TYP_GETFLD && nWhich == SwFieldIds::SetExp &&
                            !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||

                           (nTypeId == TYP_SETFLD && nWhich == SwFieldIds::SetExp &&
                            !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||

                           (nTypeId == TYP_SEQFLD && nWhich == SwFieldIds::SetExp  &&
                           (static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||

                           ((nTypeId == TYP_INPUTFLD || nTypeId == TYP_FORMELFLD) &&
                             (nWhich == SwFieldIds::User ||
                              (nWhich == SwFieldIds::SetExp &&
                              !(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ))) ) )
                        {
                            rToFill.push_back(pFieldType->GetName());
                        }
                    }
                    break;
                }
                case TYP_DBNEXTSETFLD:
                case TYP_DBNUMSETFLD:
                case TYP_DBNAMEFLD:
                case TYP_DBSETNUMBERFLD:
                    break;

                default:
                {
                    // static SubTypes
                    if(nPos != USHRT_MAX)
                    {
                        sal_uInt16 nCount;
                        if (nTypeId == TYP_DOCINFOFLD)
                            nCount = DI_SUBTYPE_END - DI_SUBTYPE_BEGIN;
                        else
                            nCount = aSwFields[nPos].nSubTypeLength;

                        for(sal_uInt16 i = 0; i < nCount; ++i)
                        {
                            OUString sNew;
                            if (nTypeId == TYP_DOCINFOFLD)
                            {
                                if ( i == DI_CUSTOM )
                                    sNew = SwResId(STR_CUSTOM_FIELD);
                                else
                                    sNew = SwViewShell::GetShellRes()->aDocInfoLst[i];
                            }
                            else
                                sNew = SwResId(aSwFields[nPos].pSubTypeResIds[i]);

                            rToFill.push_back(sNew);
                        }
                    }
                }
            }
        }
    }

    // determine format
    //  ACCESS over TYP_....
    sal_uInt16 SwFieldMgr::GetFormatCount(sal_uInt16 nTypeId, bool bHtmlMode) const
    {
        OSL_ENSURE(nTypeId < TYP_END, "forbidden TypeId");
        {
            const sal_uInt16 nPos = GetPos(nTypeId);

            if (nPos == USHRT_MAX || (bHtmlMode && nTypeId == TYP_SETFLD))
                return 0;

            sal_uInt16 nCount = aSwFields[nPos].nFormatLength;

            if (nTypeId == TYP_FILENAMEFLD)
                nCount -= 2;  // no range or template

            const char** pStart = aSwFields[nPos].pFormatResIds;
            if (!pStart)
                return nCount;

            if (strcmp(*pStart, FMT_GETVAR_ARY[0]) == 0 || strcmp(*pStart, FMT_SETVAR_ARY[0]) == 0)
                return VF_COUNT;
            else if (strcmp(*pStart, FMT_USERVAR_ARY[0]) == 0)
                return VF_USR_COUNT;
            else if (strcmp(*pStart, FMT_DBFLD_ARY[0]) == 0)
                return VF_DB_COUNT;
            else if (strcmp(*pStart, FMT_NUM_ARY[0]) == 0)
            {
                GetNumberingInfo();
                if(m_xNumberingInfo.is())
                {
                    Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
                    const sal_Int16* pTypes = aTypes.getConstArray();
                    for(sal_Int32 nType = 0; nType < aTypes.getLength(); nType++)
                    {
                        sal_Int16 nCurrent = pTypes[nType];
                        //skip all values below or equal to CHARS_LOWER_LETTER_N
                        if(nCurrent > NumberingType::CHARS_LOWER_LETTER_N)
                        {
                            // #i28073# it's not necessarily a sorted sequence
                            ++nCount;
                        }
                    }
                }
                return nCount;
            }

            return nCount;
        }
    }

    // determine FormatString to a type
    OUString SwFieldMgr::GetFormatStr(sal_uInt16 nTypeId, sal_uInt32 nFormatId) const
    {
        OSL_ENSURE(nTypeId < TYP_END, "forbidden TypeId");
        const sal_uInt16 nPos = GetPos(nTypeId);

        if (nPos == USHRT_MAX)
            return OUString();

        const char** pStart = aSwFields[nPos].pFormatResIds;
        if (!pStart)
            return OUString();

        if (TYP_AUTHORFLD == nTypeId|| TYP_FILENAMEFLD == nTypeId)
            nFormatId &= ~static_cast<sal_uInt32>(FF_FIXED); // mask out Fixed-Flag

        if (nFormatId < aSwFields[nPos].nFormatLength)
            return SwResId(pStart[nFormatId]);

        OUString aRet;
        if (*pStart == FMT_NUM_ARY[0])
        {
            if (m_xNumberingInfo.is())
            {
                Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
                const sal_Int16* pTypes = aTypes.getConstArray();
                sal_Int32 nOffset = aSwFields[nPos].nFormatLength;
                sal_uInt32 nValidEntry = 0;
                for (sal_Int32 nType = 0; nType < aTypes.getLength(); nType++)
                {
                    sal_Int16 nCurrent = pTypes[nType];
                    if(nCurrent > NumberingType::CHARS_LOWER_LETTER_N &&
                            (nCurrent != (NumberingType::BITMAP | LINK_TOKEN)))
                    {
                        if (nValidEntry == nFormatId - nOffset)
                        {
                            sal_uInt32 n = SvxNumberingTypeTable::FindIndex(pTypes[nType]);
                            if (n != RESARRAY_INDEX_NOTFOUND)
                            {
                                aRet = SvxNumberingTypeTable::GetString(n);
                            }
                            else
                            {
                                aRet = m_xNumberingInfo->getNumberingIdentifier( pTypes[nType] );
                            }
                            break;
                        }
                        ++nValidEntry;
                    }
                }
            }
        }

        return aRet;
    }

    // determine FormatId from Pseudo-ID
    sal_uInt16 SwFieldMgr::GetFormatId(sal_uInt16 nTypeId, sal_uInt32 nFormatId) const
    {
        sal_uInt16 nId = static_cast<sal_uInt16>(nFormatId);
        switch( nTypeId )
        {
            case TYP_DOCINFOFLD:
            {
                const OString sId(aSwFields[GetPos(nTypeId)].pFormatResIds[nFormatId]);
                if (sId == FMT_REG_AUTHOR)
                    nId = DI_SUB_AUTHOR;
                else if (sId == FMT_REG_TIME)
                    nId = DI_SUB_TIME;
                else if (sId == FMT_REG_DATE)
                    nId = DI_SUB_DATE;
                break;
            }
            case TYP_PAGENUMBERFLD:
            case TYP_NEXTPAGEFLD:
            case TYP_PREVPAGEFLD:
            case TYP_DOCSTATFLD:
            case TYP_DBSETNUMBERFLD:
            case TYP_SEQFLD:
            case TYP_GETREFPAGEFLD:
            {
                sal_uInt16 nPos = GetPos(nTypeId);
                if (nFormatId < aSwFields[nPos].nFormatLength)
                {
                    const OString sId(aSwFields[nPos].pFormatResIds[nFormatId]);
                    if (sId == FMT_NUM_ABC)
                        nId = SVX_NUM_CHARS_UPPER_LETTER;
                    else if (sId == FMT_NUM_SABC)
                        nId = SVX_NUM_CHARS_LOWER_LETTER;
                    else if (sId == FMT_NUM_ROMAN)
                        nId = SVX_NUM_ROMAN_UPPER;
                    else if (sId == FMT_NUM_SROMAN)
                        nId = SVX_NUM_ROMAN_LOWER;
                    else if (sId == FMT_NUM_ARABIC)
                        nId = SVX_NUM_ARABIC;
                    else if (sId == FMT_NUM_PAGEDESC)
                        nId = SVX_NUM_PAGEDESC;
                    else if (sId == FMT_NUM_PAGESPECIAL)
                        nId = SVX_NUM_CHAR_SPECIAL;
                    else if (sId == FMT_NUM_ABC_N)
                        nId = SVX_NUM_CHARS_UPPER_LETTER_N;
                    else if (sId == FMT_NUM_SABC_N)
                        nId = SVX_NUM_CHARS_LOWER_LETTER_N;
                }
                else if (m_xNumberingInfo.is())
                {
                    Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
                    const sal_Int16* pTypes = aTypes.getConstArray();
                    sal_Int32 nOffset = aSwFields[nPos].nFormatLength;
                    sal_Int32 nValidEntry = 0;
                    for (sal_Int32 nType = 0; nType < aTypes.getLength(); nType++)
                    {
                        sal_Int16 nCurrent = pTypes[nType];
                        if (nCurrent > NumberingType::CHARS_LOWER_LETTER_N)
                        {
                            if (nValidEntry == static_cast<sal_Int32>(nFormatId) - nOffset)
                            {
                                nId = pTypes[nType];
                                break;
                            }
                            ++nValidEntry;
                        }
                    }
                }
                break;
            }
            case TYP_DDEFLD:
            {
                const OString sId(aSwFields[GetPos(nTypeId)].pFormatResIds[nFormatId]);
                if (sId == FMT_DDE_NORMAL)
                    nId = static_cast<sal_uInt16>(SfxLinkUpdateMode::ONCALL);
                else if (sId == FMT_DDE_HOT)
                    nId = static_cast<sal_uInt16>(SfxLinkUpdateMode::ALWAYS);
                break;
            }
        }
        return nId;
    }

    // Traveling
    bool SwFieldMgr::GoNextPrev( bool bNext, SwFieldType* pTyp )
    {
        SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
        if(!pSh)
            return false;

        if( !pTyp && m_pCurField )
        {
            const sal_uInt16 nTypeId = m_pCurField->GetTypeId();
            if( TYP_SETINPFLD == nTypeId || TYP_USRINPFLD == nTypeId )
                pTyp = pSh->GetFieldType( 0, SwFieldIds::Input );
            else
                pTyp = m_pCurField->GetTyp();
        }

        if (pTyp && pTyp->Which() == SwFieldIds::Database)
        {
            // for fieldcommand-edit (hop to all DB fields)
            return pSh->MoveFieldType( nullptr, bNext, SwFieldIds::Database );
        }

        return pTyp && pSh && pSh->MoveFieldType( pTyp, bNext );
    }

    // insert field types
    void SwFieldMgr::InsertFieldType(SwFieldType const & rType)
    {
        SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
        OSL_ENSURE(pSh, "no SwWrtShell found");
        if(pSh)
            pSh->InsertFieldType(rType);
    }

    // determine current TypeId
    sal_uInt16 SwFieldMgr::GetCurTypeId() const
    {
        return m_pCurField ? m_pCurField->GetTypeId() : USHRT_MAX;
    }

    // Over string  insert field or update
    bool SwFieldMgr::InsertField(
        const SwInsertField_Data& rData)
    {
        SwField* pField   = nullptr;
        bool bExp = false;
        bool bTable = false;
        bool bPageVar = false;
        sal_uInt32 nFormatId = rData.m_nFormatId;
        sal_uInt16 nSubType = rData.m_nSubType;
        sal_Unicode cSeparator = rData.m_cSeparator;
        SwWrtShell* pCurShell = rData.m_pSh;
        if(!pCurShell)
            pCurShell = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
        OSL_ENSURE(pCurShell, "no SwWrtShell found");
        if(!pCurShell)
            return false;

        switch (rData.m_nTypeId)
        {   // ATTENTION this field is inserted by a separate dialog
            case TYP_POSTITFLD:
            {
                SvtUserOptions aUserOpt;
                SwPostItFieldType* pType = static_cast<SwPostItFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Postit));
                SwPostItField* pPostItField =
                    new SwPostItField(
                        pType,
                        rData.m_sPar1, // author
                        rData.m_sPar2, // content
                        aUserOpt.GetID(), // author's initials
                        OUString(), // name
                        DateTime(DateTime::SYSTEM) );
                pField = pPostItField;
            }
            break;
            case TYP_SCRIPTFLD:
            {
                SwScriptFieldType* pType =
                    static_cast<SwScriptFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Script));
                pField = new SwScriptField(pType, rData.m_sPar1, rData.m_sPar2, static_cast<bool>(nFormatId));
                break;
            }

        case TYP_COMBINED_CHARS:
            {
                SwCombinedCharFieldType* pType = static_cast<SwCombinedCharFieldType*>(
                    pCurShell->GetFieldType( 0, SwFieldIds::CombinedChars ));
                pField = new SwCombinedCharField( pType, rData.m_sPar1 );
            }
            break;

        case TYP_AUTHORITY:
            {
                SwAuthorityFieldType* pType =
                    static_cast<SwAuthorityFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::TableOfAuthorities));
                if (!pType)
                {
                    SwAuthorityFieldType const type(pCurShell->GetDoc());
                    pType = static_cast<SwAuthorityFieldType*>(
                                pCurShell->InsertFieldType(type));
                }
                pField = new SwAuthorityField(pType, rData.m_sPar1);
            }
            break;

        case TYP_DATEFLD:
        case TYP_TIMEFLD:
            {
                sal_uInt16 nSub = static_cast< sal_uInt16 >(rData.m_nTypeId == TYP_DATEFLD ? DATEFLD : TIMEFLD);
                nSub |= nSubType == DATE_VAR ? 0 : FIXEDFLD;

                SwDateTimeFieldType* pTyp =
                    static_cast<SwDateTimeFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::DateTime) );
                pField = new SwDateTimeField(pTyp, nSub, nFormatId);
                pField->SetPar2(rData.m_sPar2);
                break;
            }

        case TYP_FILENAMEFLD:
            {
                SwFileNameFieldType* pTyp =
                    static_cast<SwFileNameFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Filename) );
                pField = new SwFileNameField(pTyp, nFormatId);
                break;
            }

        case TYP_TEMPLNAMEFLD:
            {
                SwTemplNameFieldType* pTyp =
                    static_cast<SwTemplNameFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::TemplateName) );
                pField = new SwTemplNameField(pTyp, nFormatId);
                break;
            }

        case TYP_CHAPTERFLD:
            {
                sal_uInt16 nByte = static_cast<sal_uInt16>(rData.m_sPar2.toInt32());
                SwChapterFieldType* pTyp =
                    static_cast<SwChapterFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Chapter) );
                pField = new SwChapterField(pTyp, nFormatId);
                nByte = std::max(sal_uInt16(1), nByte);
                nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
                nByte -= 1;
                static_cast<SwChapterField*>(pField)->SetLevel(static_cast<sal_uInt8>(nByte));
                break;
            }

        case TYP_NEXTPAGEFLD:
        case TYP_PREVPAGEFLD:
        case TYP_PAGENUMBERFLD:
            {
                short nOff = static_cast<short>(rData.m_sPar2.toInt32());

                if(rData.m_nTypeId == TYP_NEXTPAGEFLD)
                {
                    if( SVX_NUM_CHAR_SPECIAL == nFormatId )
                        nOff = 1;
                    else
                        nOff += 1;
                    nSubType = PG_NEXT;
                }
                else if(rData.m_nTypeId == TYP_PREVPAGEFLD)
                {
                    if( SVX_NUM_CHAR_SPECIAL == nFormatId )
                        nOff = -1;
                    else
                        nOff -= 1;
                    nSubType =  PG_PREV;
                }
                else
                    nSubType = PG_RANDOM;

                SwPageNumberFieldType* pTyp =
                    static_cast<SwPageNumberFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::PageNumber) );
                pField = new SwPageNumberField(pTyp, nSubType, nFormatId, nOff);

                if( SVX_NUM_CHAR_SPECIAL == nFormatId &&
                    ( PG_PREV == nSubType || PG_NEXT == nSubType ) )
                    static_cast<SwPageNumberField*>(pField)->SetUserString( rData.m_sPar2 );
                break;
            }

        case TYP_DOCSTATFLD:
            {
                SwDocStatFieldType* pTyp =
                    static_cast<SwDocStatFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::DocStat) );
                pField = new SwDocStatField(pTyp, nSubType, nFormatId);
                break;
            }

        case TYP_AUTHORFLD:
            {
                SwAuthorFieldType* pTyp =
                    static_cast<SwAuthorFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Author) );
                pField = new SwAuthorField(pTyp, nFormatId);
                break;
            }

        case TYP_CONDTXTFLD:
        case TYP_HIDDENTXTFLD:
            {
                SwHiddenTextFieldType* pTyp =
                    static_cast<SwHiddenTextFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::HiddenText) );
                pField = new SwHiddenTextField(pTyp, true, rData.m_sPar1, rData.m_sPar2, false, rData.m_nTypeId);
                bExp = true;
                break;
            }

        case TYP_HIDDENPARAFLD:
            {
                SwHiddenParaFieldType* pTyp =
                    static_cast<SwHiddenParaFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::HiddenPara) );
                pField = new SwHiddenParaField(pTyp, rData.m_sPar1);
                bExp = true;
                break;
            }

        case TYP_SETREFFLD:
            {
                if( !rData.m_sPar1.isEmpty() && CanInsertRefMark( rData.m_sPar1 ) )
                {
                    pCurShell->SetAttrItem( SwFormatRefMark( rData.m_sPar1 ) );
                    return true;
                }
                return false;
            }

        case TYP_GETREFFLD:
            {
                SwGetRefFieldType* pTyp =
                    static_cast<SwGetRefFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::GetRef) );
                sal_uInt16 nSeqNo = static_cast<sal_uInt16>(rData.m_sPar2.toInt32());
                OUString sReferenceLanguage;
                // handle language-variant formats
                if (nFormatId >= SAL_N_ELEMENTS(FMT_REF_ARY))
                {
                    LanguageType nLang = GetCurrLanguage();
                    if (nLang == LANGUAGE_HUNGARIAN)
                    {
                        if (nFormatId >= SAL_N_ELEMENTS(FMT_REF_ARY) * 2)
                            sReferenceLanguage = "Hu";
                        else
                            sReferenceLanguage = "hu";
                    }
                    nFormatId %= SAL_N_ELEMENTS(FMT_REF_ARY);
                }
                pField = new SwGetRefField(pTyp, rData.m_sPar1, sReferenceLanguage, nSubType, nSeqNo, nFormatId);
                bExp = true;
                break;
            }

        case TYP_DDEFLD:
            {
                //JP 28.08.95: DDE-Topics/-Items can have blanks in their names!
                //              That's not yet considered here.
                sal_Int32 nIndex = 0;
                OUString sCmd = rData.m_sPar2.replaceFirst(" ", OUStringLiteral1(sfx2::cTokenSeparator), &nIndex);
                if (nIndex>=0 && ++nIndex<sCmd.getLength())
                {
                    sCmd = sCmd.replaceFirst(" ", OUStringLiteral1(sfx2::cTokenSeparator), &nIndex);
                }

                SwDDEFieldType aType( rData.m_sPar1, sCmd, static_cast<SfxLinkUpdateMode>(nFormatId) );
                SwDDEFieldType* pTyp = static_cast<SwDDEFieldType*>( pCurShell->InsertFieldType( aType ) );
                pField = new SwDDEField( pTyp );
                break;
            }

        case TYP_MACROFLD:
            {
                SwMacroFieldType* pTyp =
                    static_cast<SwMacroFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Macro));

                pField = new SwMacroField(pTyp, rData.m_sPar1, rData.m_sPar2);

                break;
            }

        case TYP_INTERNETFLD:
            {
                SwFormatINetFormat aFormat( rData.m_sPar1, m_sCurFrame );
                return pCurShell->InsertURL( aFormat, rData.m_sPar2 );
            }

        case TYP_JUMPEDITFLD:
            {
                SwJumpEditFieldType* pTyp =
                    static_cast<SwJumpEditFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::JumpEdit));

                pField = new SwJumpEditField(pTyp, nFormatId, rData.m_sPar1, rData.m_sPar2);
                break;
            }

        case TYP_DOCINFOFLD:
            {
                SwDocInfoFieldType* pTyp = static_cast<SwDocInfoFieldType*>( pCurShell->GetFieldType(
                    0, SwFieldIds::DocInfo ) );
                pField = new SwDocInfoField(pTyp, nSubType, rData.m_sPar1, nFormatId);
                break;
            }

        case TYP_EXTUSERFLD:
            {
                SwExtUserFieldType* pTyp = static_cast<SwExtUserFieldType*>( pCurShell->GetFieldType(
                    0, SwFieldIds::ExtUser) );
                pField = new SwExtUserField(pTyp, nSubType, nFormatId);
                break;
            }

        case TYP_DBFLD:
            {
    #if HAVE_FEATURE_DBCONNECTIVITY
                SwDBData aDBData;
                OUString sPar1;

                if (rData.m_sPar1.indexOf(DB_DELIM)<0)
                {
                    aDBData = pCurShell->GetDBData();
                    sPar1 = rData.m_sPar1;
                }
                else
                {
                    aDBData.sDataSource = rData.m_sPar1.getToken(0, DB_DELIM);
                    aDBData.sCommand = rData.m_sPar1.getToken(1, DB_DELIM);
                    aDBData.nCommandType = rData.m_sPar1.getToken(2, DB_DELIM).toInt32();
                    sPar1 = rData.m_sPar1.getToken(3, DB_DELIM);
                }

                if(!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
                    pCurShell->ChgDBData(aDBData);

                SwDBFieldType* pTyp = static_cast<SwDBFieldType*>(pCurShell->InsertFieldType(
                    SwDBFieldType(pCurShell->GetDoc(), sPar1, aDBData) ) );
                pField = new SwDBField(pTyp);
                pField->SetSubType(nSubType);

                if( !(nSubType & nsSwExtendedSubType::SUB_OWN_FMT) ) // determine database format
                {
                    Reference< XDataSource> xSource;
                    rData.m_aDBDataSource >>= xSource;
                    Reference<XConnection> xConnection;
                    rData.m_aDBConnection >>= xConnection;
                    Reference<XPropertySet> xColumn;
                    rData.m_aDBColumn >>= xColumn;
                    if(xColumn.is())
                    {
                        nFormatId = SwDBManager::GetColumnFormat(xSource, xConnection, xColumn,
                            pCurShell->GetNumberFormatter(), GetCurrLanguage() );
                    }
                    else
                        nFormatId = pCurShell->GetDBManager()->GetColumnFormat(
                        aDBData.sDataSource, aDBData.sCommand, sPar1,
                        pCurShell->GetNumberFormatter(), GetCurrLanguage() );
                }
                pField->ChangeFormat( nFormatId );

                bExp = true;
    #endif
                break;
            }

        case TYP_DBSETNUMBERFLD:
        case TYP_DBNUMSETFLD:
        case TYP_DBNEXTSETFLD:
        case TYP_DBNAMEFLD:
            {
    #if HAVE_FEATURE_DBCONNECTIVITY
                SwDBData aDBData;

                // extract DBName from rData.m_sPar1. Format: DBName.TableName.CommandType.ExpStrg
                sal_Int32 nTablePos = rData.m_sPar1.indexOf(DB_DELIM);
                sal_Int32 nCmdTypePos = -1;
                sal_Int32 nExpPos = -1;

                if (nTablePos>=0)
                {
                    aDBData.sDataSource = rData.m_sPar1.copy(0, nTablePos++);
                    nCmdTypePos = rData.m_sPar1.indexOf(DB_DELIM, nTablePos);
                    if (nCmdTypePos>=0)
                    {
                        aDBData.sCommand = rData.m_sPar1.copy(nTablePos, nCmdTypePos++ - nTablePos);
                        nExpPos = rData.m_sPar1.indexOf(DB_DELIM, nCmdTypePos);
                        if (nExpPos>=0)
                        {
                            aDBData.nCommandType = rData.m_sPar1.copy(nCmdTypePos, nExpPos++ - nCmdTypePos).toInt32();
                        }
                    }
                }

                sal_Int32 nPos = 0;
                if (nExpPos>=0)
                    nPos = nExpPos;
                else if (nTablePos>=0)
                    nPos = nTablePos;

                OUString sPar1 = rData.m_sPar1.copy(nPos);

                if (!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
                    pCurShell->ChgDBData(aDBData);

                switch(rData.m_nTypeId)
                {
                case TYP_DBNAMEFLD:
                    {
                        SwDBNameFieldType* pTyp =
                            static_cast<SwDBNameFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::DatabaseName));
                        pField = new SwDBNameField(pTyp, aDBData);

                        break;
                    }
                case TYP_DBNEXTSETFLD:
                    {
                        SwDBNextSetFieldType* pTyp = static_cast<SwDBNextSetFieldType*>(pCurShell->GetFieldType(
                            0, SwFieldIds::DbNextSet) );
                        pField = new SwDBNextSetField(pTyp, sPar1, aDBData);
                        bExp = true;
                        break;
                    }
                case TYP_DBNUMSETFLD:
                    {
                        SwDBNumSetFieldType* pTyp = static_cast<SwDBNumSetFieldType*>( pCurShell->GetFieldType(
                            0, SwFieldIds::DbNumSet) );
                        pField = new SwDBNumSetField( pTyp, sPar1, rData.m_sPar2, aDBData);
                        bExp = true;
                        break;
                    }
                case TYP_DBSETNUMBERFLD:
                    {
                        SwDBSetNumberFieldType* pTyp = static_cast<SwDBSetNumberFieldType*>(
                            pCurShell->GetFieldType(0, SwFieldIds::DbSetNumber) );
                        pField = new SwDBSetNumberField( pTyp, aDBData, nFormatId);
                        bExp = true;
                        break;
                    }
                }
    #endif
                break;
            }

        case TYP_USERFLD:
            {
                SwUserFieldType* pTyp =
                    static_cast<SwUserFieldType*>( pCurShell->GetFieldType(SwFieldIds::User, rData.m_sPar1) );

                // only if existing
                if(!pTyp)
                {
                    pTyp = static_cast<SwUserFieldType*>( pCurShell->InsertFieldType(
                        SwUserFieldType(pCurShell->GetDoc(), rData.m_sPar1)) );
                }
                if (pTyp->GetContent(nFormatId) != rData.m_sPar2)
                    pTyp->SetContent(rData.m_sPar2, nFormatId);
                pField = new SwUserField(pTyp, 0, nFormatId);
                if (pField->GetSubType() != nSubType)
                    pField->SetSubType(nSubType);
                bTable = true;
                break;
            }

        case TYP_INPUTFLD:
            {
                if ((nSubType & 0x00ff) == INP_VAR)
                {
                    SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>(
                        pCurShell->GetFieldType(SwFieldIds::SetExp, rData.m_sPar1) );

                    // no Expression Type with this name existing -> create
                    if(pTyp)
                    {
                        SwSetExpField* pExpField =
                            new SwSetExpField(pTyp, OUString(), nFormatId);

                        // Don't change type of SwSetExpFieldType:
                        sal_uInt16 nOldSubType = pExpField->GetSubType();
                        pExpField->SetSubType(nOldSubType | (nSubType & 0xff00));

                        pExpField->SetPromptText(rData.m_sPar2);
                        pExpField->SetInputFlag(true) ;
                        bExp = true;
                        pField = pExpField;
                    }
                    else
                        return false;
                }
                else
                {
                    SwInputFieldType* pTyp =
                        static_cast<SwInputFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Input) );

                    SwInputField* pInpField =
                        new SwInputField( pTyp, rData.m_sPar1, rData.m_sPar2, nSubType|nsSwExtendedSubType::SUB_INVISIBLE, nFormatId);
                    pField = pInpField;
                }
                break;
            }

        case TYP_SETFLD:
            {
                if (rData.m_sPar2.isEmpty())   // empty variables are not allowed
                    return false;

                SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>( pCurShell->InsertFieldType(
                    SwSetExpFieldType(pCurShell->GetDoc(), rData.m_sPar1) ) );

                SwSetExpField* pExpField = new SwSetExpField( pTyp, rData.m_sPar2, nFormatId);
                pExpField->SetSubType(nSubType);
                pExpField->SetPar2(rData.m_sPar2);
                bExp = true;
                pField = pExpField;
                break;
            }

        case TYP_SEQFLD:
            {
                SwSetExpFieldType* pTyp = static_cast<SwSetExpFieldType*>( pCurShell->InsertFieldType(
                    SwSetExpFieldType(pCurShell->GetDoc(), rData.m_sPar1, nsSwGetSetExpType::GSE_SEQ)));

                sal_uInt8 nLevel = static_cast< sal_uInt8 >(nSubType & 0xff);

                pTyp->SetOutlineLvl(nLevel);
                if (nLevel != 0x7f && cSeparator == 0)
                    cSeparator = '.';

                pTyp->SetDelimiter(OUString(cSeparator));
                SwSetExpField* pExpField = new SwSetExpField(pTyp, rData.m_sPar2, nFormatId);
                bExp = true;
                pField = pExpField;
                break;
            }

        case TYP_GETFLD:
            {
                // is there a corresponding SetField
                SwSetExpFieldType* pSetTyp = static_cast<SwSetExpFieldType*>(
                    pCurShell->GetFieldType(SwFieldIds::SetExp, rData.m_sPar1));

                if(pSetTyp)
                {
                    SwGetExpFieldType* pTyp = static_cast<SwGetExpFieldType*>( pCurShell->GetFieldType(
                        0, SwFieldIds::GetExp) );
                    pField = new SwGetExpField(pTyp, rData.m_sPar1, pSetTyp->GetType(), nFormatId);
                    pField->SetSubType(nSubType | pSetTyp->GetType());
                    bExp = true;
                }
                else
                    return false;
                break;
            }

        case TYP_FORMELFLD:
            {
                if(pCurShell->GetFrameType(nullptr,false) & FrameTypeFlags::TABLE)
                {
                    pCurShell->StartAllAction();

                    SvNumberFormatter* pFormatter = pCurShell->GetDoc()->GetNumberFormatter();
                    const SvNumberformat* pEntry = pFormatter->GetEntry(nFormatId);

                    if (pEntry)
                    {
                        SfxStringItem aFormat(FN_NUMBER_FORMAT, pEntry->GetFormatstring());
                        pCurShell->GetView().GetViewFrame()->GetDispatcher()->
                            ExecuteList(FN_NUMBER_FORMAT, SfxCallMode::SYNCHRON,
                                    { &aFormat });
                    }

                    SfxItemSet aBoxSet( pCurShell->GetAttrPool(),
                        svl::Items<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA>{} );

                    OUString sFormula(comphelper::string::stripStart(rData.m_sPar2, ' '));
                    if ( sFormula.startsWith("=") )
                    {
                        sFormula = sFormula.copy(1);
                    }

                    aBoxSet.Put( SwTableBoxFormula( sFormula ));
                    pCurShell->SetTableBoxFormulaAttrs( aBoxSet );
                    pCurShell->UpdateTable();

                    pCurShell->EndAllAction();
                    return true;

                }
                else
                {
                    SwGetExpFieldType* pTyp = static_cast<SwGetExpFieldType*>(
                        pCurShell->GetFieldType(0, SwFieldIds::GetExp) );
                    pField = new SwGetExpField(pTyp, rData.m_sPar2, nsSwGetSetExpType::GSE_FORMULA, nFormatId);
                    pField->SetSubType(nSubType);
                    bExp = true;
                }
                break;
            }
            case TYP_SETREFPAGEFLD:
                pField = new SwRefPageSetField( static_cast<SwRefPageSetFieldType*>(
                                    pCurShell->GetFieldType( 0, SwFieldIds::RefPageSet ) ),
                                    static_cast<short>(rData.m_sPar2.toInt32()), 0 != nSubType  );
                bPageVar = true;
                break;

            case TYP_GETREFPAGEFLD:
                pField = new SwRefPageGetField( static_cast<SwRefPageGetFieldType*>(
                                pCurShell->GetFieldType( 0, SwFieldIds::RefPageGet ) ), nFormatId );
                bPageVar = true;
                break;
            case TYP_DROPDOWN :
            {
                pField = new SwDropDownField(pCurShell->GetFieldType( 0, SwFieldIds::Dropdown ));
                const sal_Int32 nTokenCount = comphelper::string::getTokenCount(rData.m_sPar2, DB_DELIM);
                Sequence<OUString> aEntries(nTokenCount);
                OUString* pArray = aEntries.getArray();
                for(sal_Int32 nToken = 0; nToken < nTokenCount; nToken++)
                    pArray[nToken] = rData.m_sPar2.getToken(nToken, DB_DELIM);
                static_cast<SwDropDownField*>(pField)->SetItems(aEntries);
                static_cast<SwDropDownField*>(pField)->SetName(rData.m_sPar1);
            }
            break;

            // Insert Paragraph Signature field by signing the paragraph.
            // The resulting field is really a metadata field, created and added via signing.
            case TYP_PARAGRAPHSIGFLD:
                pCurShell->SignParagraph();
                return true;
            break;

            default:
            {   OSL_ENSURE(false, "wrong field type");
                return false;
            }
        }
        OSL_ENSURE(pField, "field not available");

        //the auto language flag has to be set prior to the language!
        pField->SetAutomaticLanguage(rData.m_bIsAutomaticLanguage);
        LanguageType nLang = GetCurrLanguage();
        pField->SetLanguage(nLang);

        // insert
        pCurShell->StartAllAction();

        pCurShell->Insert( *pField );

        if (TYP_INPUTFLD == rData.m_nTypeId)
        {
            pCurShell->Push();

            // start dialog, not before the field is inserted tdf#99529
            pCurShell->Left(CRSR_SKIP_CHARS,
                    false, (INP_VAR == (nSubType & 0xff)) ? 1 : 2, false );
            pCurShell->StartInputFieldDlg(pField, false, true, rData.m_pParent ? rData.m_pParent->GetFrameWeld() : nullptr);

            pCurShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
        }

        if(bExp && m_bEvalExp)
            pCurShell->UpdateExpFields(true);

        if(bTable)
        {
            pCurShell->Left(CRSR_SKIP_CHARS, false, 1, false );
            pCurShell->UpdateFields(*pField);
            pCurShell->Right(CRSR_SKIP_CHARS, false, 1, false );
        }
        else if( bPageVar )
            static_cast<SwRefPageGetFieldType*>(pCurShell->GetFieldType( 0, SwFieldIds::RefPageGet ))->UpdateFields();
        else if( TYP_GETREFFLD == rData.m_nTypeId )
            pField->GetTyp()->ModifyNotification( nullptr, nullptr );

        // delete temporary field
        delete pField;

        pCurShell->EndAllAction();
        return true;
    }

    // fields update
    void SwFieldMgr::UpdateCurField(sal_uInt32 nFormat,
                                const OUString& rPar1,
                                const OUString& rPar2,
                                std::unique_ptr<SwField> pTmpField)
    {
        // change format
        OSL_ENSURE(m_pCurField, "no field at CursorPos");

        if (!pTmpField)
            pTmpField = m_pCurField->CopyField();

        SwFieldType* pType   = pTmpField->GetTyp();
        const sal_uInt16 nTypeId = pTmpField->GetTypeId();

        SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
        OSL_ENSURE(pSh, "no SwWrtShell found");
        if(!pSh)
            return;
        pSh->StartAllAction();

        bool bSetPar2 = true;
        bool bSetPar1 = true;
        OUString sPar2( rPar2 );

        // Order to Format
        switch( nTypeId )
        {
            case TYP_DDEFLD:
            {
                // DDE-Topics/-Items can have blanks in their names!
                //  That's not yet considered here!
                sal_Int32 nIndex = 0;
                sPar2 = sPar2.replaceFirst(" ", OUStringLiteral1(sfx2::cTokenSeparator), &nIndex );
                if (nIndex>=0 && ++nIndex<sPar2.getLength())
                {
                    sPar2 = sPar2.replaceFirst(" ", OUStringLiteral1(sfx2::cTokenSeparator), &nIndex);
                }
                break;
            }

            case TYP_CHAPTERFLD:
            {
                sal_uInt16 nByte = static_cast<sal_uInt16>(rPar2.toInt32());
                nByte = std::max(sal_uInt16(1), nByte);
                nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
                nByte -= 1;
                static_cast<SwChapterField*>(pTmpField.get())->SetLevel(static_cast<sal_uInt8>(nByte));
                bSetPar2 = false;
                break;
            }

            case TYP_SCRIPTFLD:
                static_cast<SwScriptField*>(pTmpField.get())->SetCodeURL(static_cast<bool>(nFormat));
                break;

            case TYP_NEXTPAGEFLD:
                if( SVX_NUM_CHAR_SPECIAL == nFormat )
                {
                    static_cast<SwPageNumberField*>(m_pCurField)->SetUserString( sPar2 );
                    sPar2 = "1";
                }
                else
                {
                    if( nFormat + 2 == SVX_NUM_PAGEDESC )
                        nFormat = SVX_NUM_PAGEDESC;
                    short nOff = static_cast<short>(sPar2.toInt32());
                    nOff += 1;
                    sPar2 = OUString::number(nOff);
                }
                break;

            case TYP_PREVPAGEFLD:
                if( SVX_NUM_CHAR_SPECIAL == nFormat )
                {
                    static_cast<SwPageNumberField*>(m_pCurField)->SetUserString( sPar2 );
                    sPar2 = "-1";
                }
                else
                {
                    if( nFormat + 2 == SVX_NUM_PAGEDESC )
                        nFormat = SVX_NUM_PAGEDESC;
                    short nOff = static_cast<short>(sPar2.toInt32());
                    nOff -= 1;
                    sPar2 = OUString::number(nOff);
                }
                break;

            case TYP_PAGENUMBERFLD:
            case TYP_GETREFPAGEFLD:
                if( nFormat + 2 == SVX_NUM_PAGEDESC )
                    nFormat = SVX_NUM_PAGEDESC;
                break;

            case TYP_GETREFFLD:
                {
                    bSetPar2 = false;
                    static_cast<SwGetRefField*>(pTmpField.get())->SetSubType( static_cast<sal_uInt16>(rPar2.toInt32()) );
                    const sal_Int32 nPos = rPar2.indexOf( '|' );
                    if( nPos>=0 )
                        static_cast<SwGetRefField*>(pTmpField.get())->SetSeqNo( static_cast<sal_uInt16>(rPar2.copy( nPos + 1 ).toInt32()));
                }
                break;
            case TYP_DROPDOWN:
            {
                sal_Int32 nTokenCount = comphelper::string::getTokenCount(sPar2, DB_DELIM);
                Sequence<OUString> aEntries(nTokenCount);
                OUString* pArray = aEntries.getArray();
                for(sal_Int32 nToken = 0; nToken < nTokenCount; nToken++)
                    pArray[nToken] = sPar2.getToken(nToken, DB_DELIM);
                static_cast<SwDropDownField*>(pTmpField.get())->SetItems(aEntries);
                static_cast<SwDropDownField*>(pTmpField.get())->SetName(rPar1);
                bSetPar1 = bSetPar2 = false;
            }
            break;
            case TYP_AUTHORITY :
            {
                //#i99069# changes to a bibliography field should change the field type
                SwAuthorityField* pAuthorityField = static_cast<SwAuthorityField*>(pTmpField.get());
                SwAuthorityFieldType* pAuthorityType = static_cast<SwAuthorityFieldType*>(pType);
                SwAuthEntry aTempEntry;
                for( sal_uInt16 i = 0; i < AUTH_FIELD_END; ++i )
                    aTempEntry.SetAuthorField( static_cast<ToxAuthorityField>(i),
                                    rPar1.getToken( i, TOX_STYLE_DELIMITER ));
                if( pAuthorityType->ChangeEntryContent( &aTempEntry ) )
                {
                    pType->UpdateFields();
                    pSh->SetModified();
                }

                if( aTempEntry.GetAuthorField( AUTH_FIELD_IDENTIFIER ) ==
                    pAuthorityField->GetFieldText( AUTH_FIELD_IDENTIFIER ) )
                    bSetPar1 = false; //otherwise it's a new or changed entry, the field needs to be updated
                bSetPar2 = false;
            }
            break;
        }

        // set format
        // setup format before SetPar2 because of NumberFormatter!
        pTmpField->ChangeFormat(nFormat);

        if( bSetPar1 )
            pTmpField->SetPar1( rPar1 );
        if( bSetPar2 )
            pTmpField->SetPar2( sPar2 );

        // kick off update
        if(nTypeId == TYP_DDEFLD ||
           nTypeId == TYP_USERFLD ||
           nTypeId == TYP_USRINPFLD)
        {
            pType->UpdateFields();
            pSh->SetModified();
        }
        else {
            // mb: #32157
            pSh->SwEditShell::UpdateFields(*pTmpField);
            GetCurField();
        }

        pTmpField.reset();

        pSh->EndAllAction();
    }

    // explicitly evaluate ExpressionFields
    void SwFieldMgr::EvalExpFields(SwWrtShell* pSh)
    {
        if (pSh == nullptr)
            pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();

        if(pSh)
        {
            pSh->StartAllAction();
            pSh->UpdateExpFields(true);
            pSh->EndAllAction();
        }
    }
    LanguageType SwFieldMgr::GetCurrLanguage() const
    {
        SwWrtShell* pSh = m_pWrtShell ? m_pWrtShell : ::lcl_GetShell();
        if( pSh )
            return pSh->GetCurLang();
        return SvtSysLocale().GetLanguageTag().getLanguageType();
    }

    void SwFieldType::GetFieldName_()
    {
        static const char* coFieldNms[] =
        {
            FLD_DATE_STD,
            FLD_TIME_STD,
            STR_FILENAMEFLD,
            STR_DBNAMEFLD,
            STR_CHAPTERFLD,
            STR_PAGENUMBERFLD,
            STR_DOCSTATFLD,
            STR_AUTHORFLD,
            STR_SETFLD,
            STR_GETFLD,
            STR_FORMELFLD,
            STR_HIDDENTXTFLD,
            STR_SETREFFLD,
            STR_GETREFFLD,
            STR_DDEFLD,
            STR_MACROFLD,
            STR_INPUTFLD,
            STR_HIDDENPARAFLD,
            STR_DOCINFOFLD,
            STR_DBFLD,
            STR_USERFLD,
            STR_POSTITFLD,
            STR_TEMPLNAMEFLD,
            STR_SEQFLD,
            STR_DBNEXTSETFLD,
            STR_DBNUMSETFLD,
            STR_DBSETNUMBERFLD,
            STR_CONDTXTFLD,
            STR_NEXTPAGEFLD,
            STR_PREVPAGEFLD,
            STR_EXTUSERFLD,
            FLD_DATE_FIX,
            FLD_TIME_FIX,
            STR_SETINPUTFLD,
            STR_USRINPUTFLD,
            STR_SETREFPAGEFLD,
            STR_GETREFPAGEFLD,
            STR_INTERNETFLD,
            STR_JUMPEDITFLD,
            STR_SCRIPTFLD,
            STR_AUTHORITY,
            STR_COMBINED_CHARS,
            STR_DROPDOWN,
            STR_CUSTOM_FIELD,
            STR_PARAGRAPH_SIGNATURE
        };

        // insert infos for fields
        SwFieldType::s_pFieldNames = new std::vector<OUString>;
        SwFieldType::s_pFieldNames->reserve(SAL_N_ELEMENTS(coFieldNms));
        for (const char* id : coFieldNms)
        {
            const OUString aTmp(SwResId(id));
            SwFieldType::s_pFieldNames->push_back(MnemonicGenerator::EraseAllMnemonicChars( aTmp ));
        }
    }

    bool SwFieldMgr::ChooseMacro()
    {
        bool bRet = false;

        // choose script dialog
        OUString aScriptURL = SfxApplication::ChooseScript();

        // the script selector dialog returns a valid script URL
        if ( !aScriptURL.isEmpty() )
        {
            SetMacroPath( aScriptURL );
            bRet = true;
        }

        return bRet;
    }

    void SwFieldMgr::SetMacroPath(const OUString& rPath)
    {
        m_sMacroPath = rPath;
        m_sMacroName = rPath;

        // try to set sMacroName member variable by parsing the macro path
        // using the new URI parsing services

        Reference< XComponentContext > xContext =
            ::comphelper::getProcessComponentContext();

        Reference< uri::XUriReferenceFactory >
            xFactory = uri::UriReferenceFactory::create( xContext );

        Reference< uri::XVndSunStarScriptUrl >
            xUrl( xFactory->parse( m_sMacroPath ), UNO_QUERY );

        if ( xUrl.is() )
        {
            m_sMacroName = xUrl->getName();
        }
    }

    sal_uInt32 SwFieldMgr::GetDefaultFormat(sal_uInt16 nTypeId, bool bIsText, SvNumberFormatter* pFormatter)
    {
        SvNumFormatType  nDefFormat;

        switch (nTypeId)
        {
            case TYP_TIMEFLD:
            case TYP_DATEFLD:
            {
                nDefFormat = (nTypeId == TYP_DATEFLD) ? SvNumFormatType::DATE : SvNumFormatType::TIME;
            }
            break;

            default:
                if (bIsText)
                {
                    nDefFormat = SvNumFormatType::TEXT;
                }
                else
                {
                    nDefFormat = SvNumFormatType::ALL;
                }
                break;
        }

        return pFormatter->GetStandardFormat(nDefFormat, GetCurrLanguage());
    }

    Reference<XNumberingTypeInfo> const & SwFieldMgr::GetNumberingInfo() const
    {
        if(!m_xNumberingInfo.is())
        {
            Reference<XComponentContext>         xContext( ::comphelper::getProcessComponentContext() );
            Reference<XDefaultNumberingProvider> xDefNum = text::DefaultNumberingProvider::create(xContext);
            const_cast<SwFieldMgr*>(this)->m_xNumberingInfo.set(xDefNum, UNO_QUERY);
        }
        return m_xNumberingInfo;
    }

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

↑ V557 Array overrun is possible. The value of 'nPos' index could reach 65535.

↑ V557 Array overrun is possible. The value of 'GetPos(nTypeId)' index could reach 65535.

↑ V560 A part of conditional expression is always true: pSh.

↑ V557 Array overrun is possible. The value of 'nPos' index could reach 65535.

↑ V557 Array overrun is possible. The value of 'GetPos(nTypeId)' index could reach 65535.

↑ V557 Array overrun is possible. The value of 'nPos' index could reach 65535.

↑ V557 Array overrun is possible. The value of 'nPos' index could reach 65535.