/**************************************************************
 * 
 * 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
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"

#include <cmdid.h>
#include <hintids.hxx>
#include <svl/stritem.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/container/XNameAccess.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/XUriReferenceFactory.hpp>
#include <com/sun/star/uri/XVndSunStarScriptUrl.hpp>
#include <comphelper/processfactory.hxx>
#include <editeng/unolingu.hxx>
#include <unotools/localedatawrapper.hxx>
#include <sfx2/dispatch.hxx>
#include <sfx2/objsh.hxx>
#include <sfx2/linkmgr.hxx>
#include <sfx2/app.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>		// Actives Fenster
#include <doc.hxx>		// Actives Fenster
#include <docsh.hxx>		// Actives Fenster
#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 <crsskip.hxx>
#include <flddropdown.hxx>
#include <fldui.hrc>
#include <tox.hxx>

using rtl::OUString;
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;

/*--------------------------------------------------------------------
	Beschreibung: Gruppen der Felder
 --------------------------------------------------------------------*/
enum
{
	GRP_DOC_BEGIN	=  0,
	GRP_DOC_END   	=  GRP_DOC_BEGIN + 11,

	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,	// Die Gruppe ist leer!

	GRP_WEB_REF_BEGIN 	=  GRP_WEB_FKT_END + 6,		// Die Gruppe ist leer!
	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,			// Die Gruppe ist leer!
	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
};

/*--------------------------------------------------------------------
	Beschreibung: Formate in der richtigen Reihenfolge
 --------------------------------------------------------------------*/
static const sal_uInt16 __FAR_DATA aSetFmt[] =
{
// die Reihenfolge muss zu Beginn mit den ResourceIds fuer FMT_SETVAR_???
// uebereinstimmen
	0,
	0
};

static const sal_uInt16 __FAR_DATA aGetFmt[] =
{
// die Reihenfolge muss zu Beginn mit den ResourceIds fuer FMT_GETVAR_???
// uebereinstimmen
	0
};

static const sal_uInt16 __FAR_DATA aUsrFmt[] =
{
// die Reihenfolge muss zu Beginn mit den ResourceIds fuer FMT_SETVAR_???
// uebereinstimmen
	0,
	nsSwExtendedSubType::SUB_CMD
};

static const sal_uInt16 __FAR_DATA aDBFmt[] =
{
// die Reihenfolge muss zu Beginn mit den ResourceIds fuer FMT_DBFLD_???
// uebereinstimmen
	nsSwExtendedSubType::SUB_OWN_FMT
};

static const sal_uInt16 VF_COUNT		= sizeof(aGetFmt) / sizeof(sal_uInt16);
static const sal_uInt16 VF_USR_COUNT	= sizeof(aUsrFmt) / sizeof(sal_uInt16);
static const sal_uInt16 VF_DB_COUNT		= sizeof(aDBFmt)  / sizeof(sal_uInt16);

/*--------------------------------------------------------------------
	Beschreibung: Feldtypen und Subtypes
 --------------------------------------------------------------------*/
struct SwFldPack
{
	sal_uInt16  nTypeId;

	sal_uInt16	nSubTypeStart;
	sal_uInt16  nSubTypeEnd;

	sal_uLong	nFmtBegin;
	sal_uLong	nFmtEnd;
};

/*--------------------------------------------------------------------
	Beschreibung: Strings und Formate
 --------------------------------------------------------------------*/
static const SwFldPack __FAR_DATA aSwFlds[] =
{
	// Dokument
	{ TYP_EXTUSERFLD,	 	FLD_EU_BEGIN,	 	FLD_EU_END,	    0,     				0 },
	{ TYP_AUTHORFLD,	 	0,					0,				FMT_AUTHOR_BEGIN,	FMT_AUTHOR_END },
	{ TYP_DATEFLD,			FLD_DATE_BEGIN,		FLD_DATE_END,	0,					0 },
	{ TYP_TIMEFLD,			FLD_TIME_BEGIN,		FLD_TIME_END,	0,					0 },
	{ TYP_PAGENUMBERFLD,	0,					0,				FMT_NUM_BEGIN,   	FMT_NUM_END-1 },
	{ TYP_NEXTPAGEFLD,		0,					0,				FMT_NUM_BEGIN,		FMT_NUM_END },
	{ TYP_PREVPAGEFLD,		0,					0,				FMT_NUM_BEGIN,		FMT_NUM_END },
	{ TYP_FILENAMEFLD,		0,					0,				FMT_FF_BEGIN,    	FMT_FF_END },
	{ TYP_DOCSTATFLD,	 	FLD_STAT_BEGIN,		FLD_STAT_END,	FMT_NUM_BEGIN,		FMT_NUM_END-1 },

	{ TYP_CHAPTERFLD,	 	0,					0,				FMT_CHAPTER_BEGIN, 	FMT_CHAPTER_END },
	{ TYP_TEMPLNAMEFLD,		0,					0,				FMT_FF_BEGIN,    	FMT_FF_END },

	// Funktion
	{ TYP_CONDTXTFLD,	 	0,					0,				0,					0 },
    { TYP_DROPDOWN,       	0,                  0,              0,                  0 },
	{ TYP_INPUTFLD,			FLD_INPUT_BEGIN,	FLD_INPUT_END,	0,   				0 },
	{ TYP_MACROFLD,			0,					0,				0,					0 },
	{ TYP_JUMPEDITFLD, 		0,					0,				FMT_MARK_BEGIN,		FMT_MARK_END },
	{ TYP_COMBINED_CHARS,	0,					0,				0,					0 },
	{ TYP_HIDDENTXTFLD,		0,					0,				0,					0 },
	{ TYP_HIDDENPARAFLD, 	0,			   		0,				0,					0 },

	// Referenzen
	{ TYP_SETREFFLD,	 	0,					0,				0,					0 },
	{ TYP_GETREFFLD,	 	0,					0,				FMT_REF_BEGIN,		FMT_REF_END },

	// Ablage
	{ TYP_DOCINFOFLD,	 	0,					0,				FMT_REG_BEGIN, 		FMT_REG_END },

	// Datenbank
	{ TYP_DBFLD,		 	0,					0,				FMT_DBFLD_BEGIN,	FMT_DBFLD_END },
	{ TYP_DBNEXTSETFLD,		0,					0,				0,					0 },
	{ TYP_DBNUMSETFLD,		0,					0,				0,					0 },
	{ TYP_DBSETNUMBERFLD, 	0,					0,				FMT_NUM_BEGIN,	    FMT_NUM_END-2 },
	{ TYP_DBNAMEFLD, 	 	0,					0,				0,					0 },

	// Variablen
	{ TYP_SETFLD,		 	0,					0,				FMT_SETVAR_BEGIN,   FMT_SETVAR_END },

	{ TYP_GETFLD,		 	0,					0, 				FMT_GETVAR_BEGIN,	FMT_GETVAR_END },
	{ TYP_DDEFLD,		 	0,					0,				FMT_DDE_BEGIN, 		FMT_DDE_END },
	{ TYP_FORMELFLD,  		0,					0,				FMT_GETVAR_BEGIN,	FMT_GETVAR_END },
	{ TYP_INPUTFLD,			FLD_INPUT_BEGIN,	FLD_INPUT_END,	0,   				0 },
	{ TYP_SEQFLD,		 	0,					0,				FMT_NUM_BEGIN,		FMT_NUM_END-2 },
	{ TYP_SETREFPAGEFLD,	FLD_PAGEREF_BEGIN,	FLD_PAGEREF_END,0,   				0 },
	{ TYP_GETREFPAGEFLD,	0,					0,				FMT_NUM_BEGIN,   	FMT_NUM_END-1 },
	{ TYP_USERFLD,			0,					0,				FMT_USERVAR_BEGIN,	FMT_USERVAR_END }
};

/*--------------------------------------------------------------------
	Beschreibung: Zugriff auf die Shell
 --------------------------------------------------------------------*/

static SwWrtShell* lcl_GetShell()
{
	SwView* pView;
	if ( 0 != (pView = ::GetActiveView()) )
		return pView->GetWrtShellPtr();
	DBG_ERROR("no current shell found!");
	return 0;
}

inline sal_uInt16 GetPackCount() {	return sizeof(aSwFlds) / sizeof(SwFldPack); }

/*--------------------------------------------------------------------
	Beschreibung: FieldManager regelt das Einfuegen und Updaten
				  von Feldern
 --------------------------------------------------------------------*/

SwFldMgr::SwFldMgr(SwWrtShell* pSh ) :
	pModule(0),
	pMacroItem(0),
    pWrtShell(pSh),
    bEvalExp(sal_True)
{
	// aktuelles Feld ermitteln falls vorhanden
	GetCurFld();
}


SwFldMgr::~SwFldMgr()
{
}

/*--------------------------------------------------------------------
	Beschreibung: RefMark ueber Namen organisieren
 --------------------------------------------------------------------*/

sal_Bool  SwFldMgr::CanInsertRefMark( const String& rStr )
{
    sal_Bool bRet = sal_False;
    SwWrtShell *pSh = pWrtShell ? pWrtShell : lcl_GetShell();
    DBG_ASSERT(pSh, "no SwWrtShell found");
    if(pSh)
    {
        sal_uInt16 nCnt = pSh->GetCrsrCnt();

        // der letzte Crsr muss keine aufgespannte Selektion
        if( 1 < nCnt && !pSh->SwCrsrShell::HasSelection() )
            --nCnt;

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

/*--------------------------------------------------------------------
	Beschreibung: Zugriff ueber ResIds
 --------------------------------------------------------------------*/

void SwFldMgr::RemoveFldType(sal_uInt16 nResId, const String& rName )
{
    SwWrtShell * pSh = pWrtShell ? pWrtShell : lcl_GetShell();
    DBG_ASSERT(pSh, "no SwWrtShell found");
    if( pSh )
        pSh->RemoveFldType(nResId, rName);
}

sal_uInt16 SwFldMgr::GetFldTypeCount(sal_uInt16 nResId) const
{
    SwWrtShell * pSh = pWrtShell ? pWrtShell : lcl_GetShell();
    DBG_ASSERT(pSh, "no SwWrtShell found");
    return pSh ? pSh->GetFldTypeCount(nResId) : 0;
}


SwFieldType* SwFldMgr::GetFldType(sal_uInt16 nResId, sal_uInt16 nId) const
{
    SwWrtShell * pSh = pWrtShell ? pWrtShell : lcl_GetShell();
    DBG_ASSERT(pSh, "no SwWrtShell found");
    return pSh ? pSh->GetFldType(nId, nResId) : 0;
}


SwFieldType* SwFldMgr::GetFldType(sal_uInt16 nResId, const String& rName) const
{
    SwWrtShell * pSh = pWrtShell ? pWrtShell : lcl_GetShell();
    DBG_ASSERT(pSh, "no SwWrtShell found");
    return pSh ? pSh->GetFldType(nResId, rName) : 0;
}


/*--------------------------------------------------------------------
	Beschreibung: Aktuelles Feld ermitteln
 --------------------------------------------------------------------*/
SwField* SwFldMgr::GetCurFld()
{
	SwWrtShell *pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
	if ( pSh )
		pCurFld = pSh->GetCurFld( true );
	else
		pCurFld = NULL;

	// Strings und Format initialisieren
	//
	aCurPar1.Erase();
	aCurPar2.Erase();
	sCurFrame.Erase();
	nCurFmt = 0;

	if(!pCurFld)
		return 0;

	// Aktuelle Werte aufbereiten Parameter 1 und Parameter 2
	// als auch das Format ermitteln
	//
	const sal_uInt16 nTypeId = pCurFld->GetTypeId();

	nCurFmt  	= pCurFld->GetFormat();
	aCurPar1 	= pCurFld->GetPar1();
	aCurPar2 	= pCurFld->GetPar2();

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

/*--------------------------------------------------------------------
	Beschreibung: Gruppen-Bereich liefern
 --------------------------------------------------------------------*/


const SwFldGroupRgn& SwFldMgr::GetGroupRange(sal_Bool bHtmlMode, sal_uInt16 nGrpId) const
{
static SwFldGroupRgn __READONLY_DATA aRanges[] =
{
	{ /* Dokument	*/ 	GRP_DOC_BEGIN, 	GRP_DOC_END },
	{ /* Funktionen	*/ 	GRP_FKT_BEGIN,  GRP_FKT_END },
	{ /* Referenzen	*/ 	GRP_REF_BEGIN,  GRP_REF_END },
	{ /* Ablage		*/ 	GRP_REG_BEGIN,  GRP_REG_END },
	{ /* DB			*/	GRP_DB_BEGIN,	GRP_DB_END },
	{ /* User		*/	GRP_VAR_BEGIN,	GRP_VAR_END }
};
static SwFldGroupRgn __READONLY_DATA aWebRanges[] =
{
	{ /* Dokument	*/ 	GRP_WEB_DOC_BEGIN, 	GRP_WEB_DOC_END },
	{ /* Funktionen	*/ 	GRP_WEB_FKT_BEGIN,  GRP_WEB_FKT_END },
	{ /* Referenzen	*/ 	GRP_WEB_REF_BEGIN,  GRP_WEB_REF_END },
	{ /* Ablage		*/ 	GRP_WEB_REG_BEGIN,  GRP_WEB_REG_END },
	{ /* DB			*/	GRP_WEB_DB_BEGIN,	GRP_WEB_DB_END },
	{ /* User		*/	GRP_WEB_VAR_BEGIN,	GRP_WEB_VAR_END }
};

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

/*--------------------------------------------------------------------
	Beschreibung: GroupId bestimmen
 --------------------------------------------------------------------*/

sal_uInt16 SwFldMgr::GetGroup(sal_Bool bHtmlMode, sal_uInt16 nTypeId, sal_uInt16 nSubType) const
{
	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 SwFldGroupRgn& rRange = GetGroupRange(bHtmlMode, i);
		for (sal_uInt16 nPos = rRange.nStart; nPos < rRange.nEnd; nPos++)
		{
			if (aSwFlds[nPos].nTypeId == nTypeId)
				return i;
		}
	}
	return USHRT_MAX;
}

/*--------------------------------------------------------------------
	Beschreibung: Namen zur TypeId ermitteln
				  ZUGRIFF ueber TYP_....
 --------------------------------------------------------------------*/


sal_uInt16 SwFldMgr::GetTypeId(sal_uInt16 nPos)
{
	ASSERT(nPos < ::GetPackCount(), "unzulaessige Pos");
	return aSwFlds[ nPos ].nTypeId;
}


const String& SwFldMgr::GetTypeStr(sal_uInt16 nPos)
{
	ASSERT(nPos < ::GetPackCount(), "unzulaessige TypeId");

	sal_uInt16 nFldWh = aSwFlds[ nPos ].nTypeId;

	// Sonderbehandlung fuer Datum/Zeit Felder (ohne var/fix)
	if( TYP_DATEFLD == nFldWh )
	{
		static String g_aDate( SW_RES( STR_DATEFLD ) );
		return g_aDate;
	}
	if( TYP_TIMEFLD == nFldWh )
	{
		static String g_aTime( SW_RES( STR_TIMEFLD ) );
		return g_aTime;
	}

	return SwFieldType::GetTypeStr( nFldWh );
}

/*--------------------------------------------------------------------
	Beschreibung: Pos in der Liste bestimmen
 --------------------------------------------------------------------*/


sal_uInt16 SwFldMgr::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(aSwFlds[i].nTypeId == nTypeId)
			return i;

	return USHRT_MAX;
}

/*--------------------------------------------------------------------
	Beschreibung: Subtypen eines Feldes lokalisieren
 --------------------------------------------------------------------*/

sal_Bool SwFldMgr::GetSubTypes(sal_uInt16 nTypeId, SvStringsDtor& rToFill)
{
    sal_Bool bRet = sal_False;
    SwWrtShell *pSh = pWrtShell ? pWrtShell : lcl_GetShell();
    DBG_ASSERT(pSh, "no SwWrtShell found");
    if(pSh)
    {
        const sal_uInt16 nPos = GetPos(nTypeId);

        switch(nTypeId)
        {
            case TYP_SETREFFLD:
            case TYP_GETREFFLD:
            {
                // Referenzen sind keine Felder
                pSh->GetRefMarks( &rToFill );
                break;
            }
            case TYP_MACROFLD:
            {
                break;
            }
            case TYP_INPUTFLD:
            {   String* pNew = new SW_RESSTR(aSwFlds[nPos].nSubTypeStart);
                rToFill.Insert(pNew, rToFill.Count());
                // Weiter bei generischen Typen
            }
            case TYP_DDEFLD:
            case TYP_SEQFLD:
            case TYP_FORMELFLD:
            case TYP_GETFLD:
            case TYP_SETFLD:
            case TYP_USERFLD:
            {

                const sal_uInt16 nCount = pSh->GetFldTypeCount();
                for(sal_uInt16 i = 0; i < nCount; ++i)
                {
                    SwFieldType* pFldType = pSh->GetFldType( i );
                    const sal_uInt16 nWhich = pFldType->Which();

                    if((nTypeId == TYP_DDEFLD && pFldType->Which() == RES_DDEFLD) ||

                       (nTypeId == TYP_USERFLD && nWhich == RES_USERFLD) ||

                       (nTypeId == TYP_GETFLD && nWhich == RES_SETEXPFLD &&
                        !(((SwSetExpFieldType*)pFldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||

                       (nTypeId == TYP_SETFLD && nWhich == RES_SETEXPFLD &&
                        !(((SwSetExpFieldType*)pFldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||

                       (nTypeId == TYP_SEQFLD && nWhich == RES_SETEXPFLD  &&
                       (((SwSetExpFieldType*)pFldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||

                       ((nTypeId == TYP_INPUTFLD || nTypeId == TYP_FORMELFLD) &&
                         (nWhich == RES_USERFLD ||
                          (nWhich == RES_SETEXPFLD &&
                          !(((SwSetExpFieldType*)pFldType)->GetType() & nsSwGetSetExpType::GSE_SEQ))) ) )
                    {
                        String* pNew = new String(pFldType->GetName());
                        rToFill.Insert(pNew, rToFill.Count());
                    }
                }
                break;
            }
            case TYP_DBNEXTSETFLD:
            case TYP_DBNUMSETFLD:
            case TYP_DBNAMEFLD:
            case TYP_DBSETNUMBERFLD:
                break;

            default:
            {
                // statische SubTypes
                if(nPos != USHRT_MAX)
                {
                    sal_uInt16 nCount;
                    if (nTypeId == TYP_DOCINFOFLD)
                        nCount = DI_SUBTYPE_END - DI_SUBTYPE_BEGIN;
                    else
                        nCount = aSwFlds[nPos].nSubTypeEnd - aSwFlds[nPos].nSubTypeStart;

                    for(sal_uInt16 i = 0; i < nCount; ++i)
                    {
                        String* pNew;
                        if (nTypeId == TYP_DOCINFOFLD)
                        {
                            if ( i == DI_CUSTOM )
                                pNew = new String( String(SW_RES( STR_CUSTOM )) );
							else
                                pNew = new String(*ViewShell::GetShellRes()->aDocInfoLst[i]);
                        }
                        else
                            pNew = new SW_RESSTR(aSwFlds[nPos].nSubTypeStart + i);

                        rToFill.Insert(pNew, rToFill.Count());
                    }
                }
            }
        }
        bRet = sal_True;
    }
    return bRet;
}

/*--------------------------------------------------------------------
	Beschreibung: Format ermitteln
				  ZUGRIFF ueber TYP_....
 --------------------------------------------------------------------*/


sal_uInt16 SwFldMgr::GetFormatCount(sal_uInt16 nTypeId, sal_Bool bIsText, sal_Bool bHtmlMode) const
{
	ASSERT(nTypeId < TYP_END, "unzulaessige TypeId");

	{
		const sal_uInt16 nPos = GetPos(nTypeId);

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

		sal_uLong nStart = aSwFlds[nPos].nFmtBegin;
		sal_uLong nEnd   = aSwFlds[nPos].nFmtEnd;

		if (bIsText && nEnd - nStart >= 2)
			return 2;

		if (nTypeId == TYP_FILENAMEFLD)
			nEnd -= 2;	// Kein Bereich oder Vorlage

		switch(nStart)
		{
			case FMT_GETVAR_BEGIN:
			case FMT_SETVAR_BEGIN:	return VF_COUNT;
			case FMT_USERVAR_BEGIN:	return VF_USR_COUNT;
			case FMT_DBFLD_BEGIN:	return VF_DB_COUNT;
			case FMT_NUM_BEGIN:
			{
				sal_uInt16 nCount = (sal_uInt16)(nEnd - nStart);
				GetNumberingInfo();
                if(xNumberingInfo.is())
				{
					Sequence<sal_Int16> aTypes = 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 (sal_uInt16)(nEnd - nStart);
	}
}

/*--------------------------------------------------------------------
	Beschreibung:	FormatString zu einem Typ ermitteln
 --------------------------------------------------------------------*/


String SwFldMgr::GetFormatStr(sal_uInt16 nTypeId, sal_uLong nFormatId) const
{
	String aRet;
	ASSERT(nTypeId < TYP_END, "unzulaessige TypeId");

	const sal_uInt16 nPos = GetPos(nTypeId);

	if(nPos == USHRT_MAX)
		return aRet;

	sal_uLong nStart;

	nStart = aSwFlds[nPos].nFmtBegin;

	if (TYP_AUTHORFLD == nTypeId|| TYP_FILENAMEFLD == nTypeId)
		nFormatId &= ~FF_FIXED;		// Fixed-Flag ausmaskieren

	if((nStart + nFormatId) < aSwFlds[nPos].nFmtEnd)
		aRet = SW_RESSTR((sal_uInt16)(nStart + nFormatId));
	else if( FMT_NUM_BEGIN == nStart)
	{
		if(xNumberingInfo.is())
		{
			Sequence<sal_Int16> aTypes = xNumberingInfo->getSupportedNumberingTypes();
			const sal_Int16* pTypes = aTypes.getConstArray();
            sal_Int32 nOffset = aSwFlds[nPos].nFmtEnd - nStart;
            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 == ((sal_Int32)nFormatId) - nOffset)
                    {
                        aRet = xNumberingInfo->getNumberingIdentifier( pTypes[nType] );
                        break;
                    }
                    ++nValidEntry;
				}
			}
		}
	}

	return aRet;
}

/*--------------------------------------------------------------------
	Beschreibung:	FormatId aus Pseudo-ID ermitteln
 --------------------------------------------------------------------*/

sal_uInt16 SwFldMgr::GetFormatId(sal_uInt16 nTypeId, sal_uLong nFormatId) const
{
	sal_uInt16 nId = (sal_uInt16)nFormatId;

	switch( nTypeId )
	{
	case TYP_DOCINFOFLD:
		switch( aSwFlds[ GetPos( nTypeId ) ].nFmtBegin + nFormatId )
		{
		case FMT_REG_AUTHOR:	nId = DI_SUB_AUTHOR;	break;
		case FMT_REG_TIME:		nId = DI_SUB_TIME;		break;
		case FMT_REG_DATE:		nId = DI_SUB_DATE;		break;
		}
		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 );
		sal_uLong nBegin = aSwFlds[ nPos ].nFmtBegin;
		sal_uLong nEnd = aSwFlds[nPos].nFmtEnd;
		if((nBegin + nFormatId) < nEnd)
		{
			switch( nBegin + nFormatId )
			{
			case FMT_NUM_ABC:				nId = SVX_NUM_CHARS_UPPER_LETTER;	break;
			case FMT_NUM_SABC:				nId = SVX_NUM_CHARS_LOWER_LETTER;	break;
			case FMT_NUM_ROMAN:             nId = SVX_NUM_ROMAN_UPPER;			break;
			case FMT_NUM_SROMAN:			nId = SVX_NUM_ROMAN_LOWER;			break;
			case FMT_NUM_ARABIC:            nId = SVX_NUM_ARABIC;				break;
			case FMT_NUM_PAGEDESC: 			nId = SVX_NUM_PAGEDESC; 			break;
			case FMT_NUM_PAGESPECIAL:		nId = SVX_NUM_CHAR_SPECIAL;			break;
			case FMT_NUM_ABC_N:				nId = SVX_NUM_CHARS_UPPER_LETTER_N; break;
			case FMT_NUM_SABC_N:			nId = SVX_NUM_CHARS_LOWER_LETTER_N;	break;
			}
		}
		else if(xNumberingInfo.is())
		{
			Sequence<sal_Int16> aTypes = xNumberingInfo->getSupportedNumberingTypes();
			const sal_Int16* pTypes = aTypes.getConstArray();
            sal_Int32 nOffset = nEnd - nBegin;
            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 == ((sal_Int32)nFormatId) - nOffset)
                    {
                        nId = pTypes[nType];
                        break;
                    }
                    ++nValidEntry;
                }
            }
        }
	}
	break;
	case TYP_DDEFLD:
		switch ( aSwFlds[ GetPos( nTypeId ) ].nFmtBegin + nFormatId )
		{
        case FMT_DDE_NORMAL:    nId = sfx2::LINKUPDATE_ONCALL; break;
        case FMT_DDE_HOT:       nId = sfx2::LINKUPDATE_ALWAYS; break;
		}
		break;
	}

	return nId;

}

/*--------------------------------------------------------------------
	Beschreibung: Traveling
 --------------------------------------------------------------------*/


sal_Bool SwFldMgr::GoNextPrev( sal_Bool bNext, SwFieldType* pTyp )
{
	SwWrtShell* pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
    if(!pSh)
        return sal_False;

	if( !pTyp && pCurFld )
	{
		const sal_uInt16 nTypeId = pCurFld->GetTypeId();
		if( TYP_SETINPFLD == nTypeId || TYP_USRINPFLD == nTypeId )
			pTyp = pSh->GetFldType( 0, RES_INPUTFLD );
		else
			pTyp = pCurFld->GetTyp();
	}

	if (pTyp && pTyp->Which() == RES_DBFLD)
	{
		// Fuer Feldbefehl-bearbeiten (alle DB-Felder anspringen)
		return pSh->MoveFldType( 0, (bNext ? true : false), RES_DBFLD );
	}

    return (pTyp && pSh)
           ? pSh->MoveFldType( pTyp, (bNext ? true : false) )
           : sal_False;
}

/*--------------------------------------------------------------------
	Beschreibung: Feldtypen einfuegen
 --------------------------------------------------------------------*/


void SwFldMgr::InsertFldType(SwFieldType& rType)
{
    SwWrtShell* pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
    DBG_ASSERT(pSh, "no SwWrtShell found");
    if(pSh)
        pSh->InsertFldType(rType);
}

/*--------------------------------------------------------------------
	Beschreibung: Aktuelle TypeId ermitteln
 --------------------------------------------------------------------*/


sal_uInt16 SwFldMgr::GetCurTypeId() const
{
    return pCurFld ? pCurFld->GetTypeId() : USHRT_MAX;
}

/*--------------------------------------------------------------------
	Beschreibung: Ueber String  Feld einfuegen oder Update
 --------------------------------------------------------------------*/


sal_Bool SwFldMgr::InsertFld(
    const SwInsertFld_Data& rData,
    const SwPaM *pPam )
{
    SwField* pFld   = 0;
    sal_Bool bExp = sal_False;
    sal_Bool bTbl = sal_False;
    sal_Bool bPageVar = sal_False;
    sal_uLong nFormatId = rData.nFormatId;
    sal_uInt16 nSubType = rData.nSubType;
    sal_Unicode cSeparator = rData.cSeparator;
    SwWrtShell* pCurShell = rData.pSh;
    if(!pCurShell)
        pCurShell = pWrtShell ? pWrtShell : ::lcl_GetShell();
    DBG_ASSERT(pCurShell, "no SwWrtShell found");
    if(!pCurShell)
        return sal_False;

    switch(rData.nTypeId)
    {
    case TYP_POSTITFLD:
        {
            SwPostItFieldType* pType = (SwPostItFieldType*)pCurShell->GetFldType(0, RES_POSTITFLD);
            pFld = new SwPostItField(
                pType,
                rData.sPar2, // content
                rData.sPar1, // author
                aEmptyStr, // author's initials
                aEmptyStr, // name
                DateTime() );
            break;
        }

		case TYP_SCRIPTFLD:
		{
			SwScriptFieldType* pType =
                (SwScriptFieldType*)pCurShell->GetFldType(0, RES_SCRIPTFLD);
            pFld = new SwScriptField(pType, rData.sPar1, rData.sPar2, (sal_Bool)nFormatId);
			break;
		}
		case TYP_COMBINED_CHARS:
		{
			SwCombinedCharFieldType* pType = (SwCombinedCharFieldType*)
                                pCurShell->GetFldType( 0, RES_COMBINED_CHARS );
            pFld = new SwCombinedCharField( pType, rData.sPar1 );
		}
		break;
		case TYP_AUTHORITY:
		{
			SwAuthorityFieldType* pType =
                (SwAuthorityFieldType*)pCurShell->GetFldType(0, RES_AUTHORITY);
			if(!pType)
			{
				pType =
                    (SwAuthorityFieldType*)pCurShell->InsertFldType(
                                    SwAuthorityFieldType(pCurShell->GetDoc()));
			}
            pFld = new SwAuthorityField(pType, rData.sPar1);
		}
		break;
		case TYP_DATEFLD:
		case TYP_TIMEFLD:
		{
            sal_uInt16 nSub = static_cast< sal_uInt16 >(rData.nTypeId == TYP_DATEFLD ? DATEFLD : TIMEFLD);
            nSub |= nSubType == DATE_VAR ? 0 : FIXEDFLD;

			SwDateTimeFieldType* pTyp =
                (SwDateTimeFieldType*)pCurShell->GetFldType(0, RES_DATETIMEFLD);
            pFld = new SwDateTimeField(pTyp, nSub, nFormatId);
            pFld->SetPar2(rData.sPar2);
			break;
		}
		case TYP_FILENAMEFLD:
		{
			SwFileNameFieldType* pTyp =
                (SwFileNameFieldType*)pCurShell->GetFldType(0, RES_FILENAMEFLD);
            pFld = new SwFileNameField(pTyp, nFormatId);
			break;
		}
		case TYP_TEMPLNAMEFLD:
		{
			SwTemplNameFieldType* pTyp =
                (SwTemplNameFieldType*)pCurShell->GetFldType(0, RES_TEMPLNAMEFLD);
            pFld = new SwTemplNameField(pTyp, nFormatId);
			break;
		}
		case TYP_CHAPTERFLD:
        {
            sal_uInt16 nByte = (sal_uInt16)rData.sPar2.ToInt32();
			SwChapterFieldType* pTyp =
                (SwChapterFieldType*)pCurShell->GetFldType(0, RES_CHAPTERFLD);
            pFld = new SwChapterField(pTyp, nFormatId);
			nByte = Max(sal_uInt16(1), nByte);
			nByte = Min(nByte, sal_uInt16(MAXLEVEL));
			nByte -= 1;
			((SwChapterField*)pFld)->SetLevel((sal_uInt8)nByte);
			break;
		}
		case TYP_NEXTPAGEFLD:
		case TYP_PREVPAGEFLD:
		case TYP_PAGENUMBERFLD:
		{
            short nOff  = (short)rData.sPar2.ToInt32();

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

			SwPageNumberFieldType* pTyp =
                (SwPageNumberFieldType*)pCurShell->GetFldType(0, RES_PAGENUMBERFLD);
            pFld = new SwPageNumberField(pTyp, nSubType, nFormatId, nOff);

            if( SVX_NUM_CHAR_SPECIAL == nFormatId &&
                ( PG_PREV == nSubType || PG_NEXT == nSubType ) )
                ((SwPageNumberField*)pFld)->SetUserString( rData.sPar2 );
			break;
		}
		case TYP_DOCSTATFLD:
		{	SwDocStatFieldType* pTyp =
                (SwDocStatFieldType*)pCurShell->GetFldType(0, RES_DOCSTATFLD);
            pFld = new SwDocStatField(pTyp, nSubType, nFormatId);
			break;
		}
		case TYP_AUTHORFLD:
		{	SwAuthorFieldType* pTyp =
                (SwAuthorFieldType*)pCurShell->GetFldType(0, RES_AUTHORFLD);
            pFld = new SwAuthorField(pTyp, nFormatId);
			break;
		}
		case TYP_CONDTXTFLD:
		case TYP_HIDDENTXTFLD:
		{
			SwHiddenTxtFieldType* pTyp =
                (SwHiddenTxtFieldType*)pCurShell->GetFldType(0, RES_HIDDENTXTFLD);
            pFld = new SwHiddenTxtField(pTyp, sal_True, rData.sPar1, rData.sPar2, sal_False, rData.nTypeId);
			bExp = sal_True;
			break;
		}
		case TYP_HIDDENPARAFLD:
		{
			SwHiddenParaFieldType* pTyp =
                (SwHiddenParaFieldType*)pCurShell->GetFldType(0, RES_HIDDENPARAFLD);
            pFld = new SwHiddenParaField(pTyp, rData.sPar1);
			bExp = sal_True;
			break;
		}
		case TYP_SETREFFLD:
		{
            if( rData.sPar1.Len() > 0 && CanInsertRefMark( rData.sPar1 ) )
			{
                pCurShell->SetAttrItem( SwFmtRefMark( rData.sPar1 ) );
				return sal_True;
			}
			return sal_False;
		}
		case TYP_GETREFFLD:
		{
			SwGetRefFieldType* pTyp =
                (SwGetRefFieldType*)pCurShell->GetFldType(0, RES_GETREFFLD);
            sal_uInt16 nSeqNo = (sal_uInt16)rData.sPar2.ToInt32();
            pFld = new SwGetRefField(pTyp, rData.sPar1, nSubType, nSeqNo, nFormatId);
			bExp = sal_True;
			break;
		}
		case TYP_DDEFLD:
		{
			//JP 28.08.95: DDE-Topics/-Items koennen Blanks in ihren
			//				Namen haben! Wird hier noch nicht beachtet.
            String sCmd( rData.sPar2 );
            sal_uInt16 nTmpPos = sCmd.SearchAndReplace( ' ', sfx2::cTokenSeperator );
            sCmd.SearchAndReplace( ' ', sfx2::cTokenSeperator, nTmpPos );

            SwDDEFieldType aType( rData.sPar1, sCmd, (sal_uInt16) nFormatId );
            SwDDEFieldType* pTyp = (SwDDEFieldType*) pCurShell->InsertFldType( aType );
			pFld = new SwDDEField( pTyp );
			break;
		}
		case TYP_MACROFLD:
		{
			SwMacroFieldType* pTyp =
				(SwMacroFieldType*)pCurShell->GetFldType(0, RES_MACROFLD);

			pFld = new SwMacroField(pTyp, rData.sPar1, rData.sPar2);

			break;
		}
		case TYP_INTERNETFLD:
		{
            SwFmtINetFmt aFmt( rData.sPar1, sCurFrame );
			if( pMacroItem )
				aFmt.SetMacroTbl( &pMacroItem->GetMacroTable() );
            return pCurShell->InsertURL( aFmt, rData.sPar2 );
		}
		case TYP_JUMPEDITFLD:
		{
			SwJumpEditFieldType* pTyp =
                (SwJumpEditFieldType*)pCurShell->GetFldType(0, RES_JUMPEDITFLD);

            pFld = new SwJumpEditField(pTyp, nFormatId, rData.sPar1, rData.sPar2 );
			break;
		}
		case TYP_DOCINFOFLD:
		{
            SwDocInfoFieldType* pTyp = (SwDocInfoFieldType*)pCurShell->GetFldType(
											0, RES_DOCINFOFLD );
            pFld = new SwDocInfoField(pTyp, nSubType, rData.sPar1, nFormatId);
			break;
		}
		case TYP_EXTUSERFLD:
		{
            SwExtUserFieldType* pTyp = (SwExtUserFieldType*)pCurShell->GetFldType(
											0, RES_EXTUSERFLD);
            pFld = new SwExtUserField(pTyp, nSubType, nFormatId);
			break;
		}
		case TYP_DBFLD:
		{
			SwDBData aDBData;
			String sPar1;

            if (rData.sPar1.Search(DB_DELIM) == STRING_NOTFOUND)
			{
                aDBData = pCurShell->GetDBData();
                sPar1 = rData.sPar1;
			}
			else
			{
                aDBData.sDataSource = rData.sPar1.GetToken(0, DB_DELIM);
                aDBData.sCommand = rData.sPar1.GetToken(1, DB_DELIM);
                aDBData.nCommandType = rData.sPar1.GetToken(2, DB_DELIM).ToInt32();
                sPar1 = rData.sPar1.GetToken(3, DB_DELIM);
			}

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

            SwDBFieldType* pTyp = (SwDBFieldType*)pCurShell->InsertFldType(
                    SwDBFieldType(pCurShell->GetDoc(), sPar1, aDBData) );
			pFld = new SwDBField(pTyp);
            pFld->SetSubType(nSubType);

            if( !(nSubType & nsSwExtendedSubType::SUB_OWN_FMT) ) // Datenbankformat ermitteln
			{
                Reference< XDataSource> xSource;
                rData.aDBDataSource >>= xSource;
                Reference<XConnection> xConnection;
                rData.aDBConnection >>= xConnection;
                Reference<XPropertySet> xColumn;
                rData.aDBColumn >>= xColumn;
                if(xColumn.is())
                {
                    nFormatId = pCurShell->GetNewDBMgr()->GetColumnFmt(xSource, xConnection, xColumn,
                                        pCurShell->GetNumberFormatter(), GetCurrLanguage() );
                }
                else
                    nFormatId = pCurShell->GetNewDBMgr()->GetColumnFmt(
                                        aDBData.sDataSource, aDBData.sCommand, sPar1,
                                        pCurShell->GetNumberFormatter(), GetCurrLanguage() );
			}
            pFld->ChangeFormat( nFormatId );

			bExp = sal_True;
			break;
		}
		case TYP_DBSETNUMBERFLD:
		case TYP_DBNUMSETFLD:
		case TYP_DBNEXTSETFLD:
		case TYP_DBNAMEFLD:
		{
			sal_uInt16 nPos, nTablePos, nCmdTypePos, nExpPos;
			String sPar1;
			SwDBData aDBData;

            // DBName aus rData.sPar1 extrahieren. Format: DBName.TableName.CommandType.ExpStrg
            if ((nTablePos = rData.sPar1.Search(DB_DELIM)) != STRING_NOTFOUND)
                aDBData.sDataSource = rData.sPar1.Copy(0, nTablePos++);
            if ((nCmdTypePos = rData.sPar1.Search(DB_DELIM, nTablePos)) != STRING_NOTFOUND)
			{
                aDBData.sCommand = rData.sPar1.Copy(nTablePos, nCmdTypePos++ - nTablePos);
			}
            if ((nExpPos = rData.sPar1.Search(DB_DELIM, nCmdTypePos)) != STRING_NOTFOUND)
			{
                aDBData.nCommandType = rData.sPar1.Copy(nCmdTypePos, nExpPos++ - nCmdTypePos).ToInt32();
			}
			if (nExpPos != STRING_NOTFOUND)
				nPos = nExpPos;
			else if (nTablePos != STRING_NOTFOUND)
				nPos = nTablePos;
			else
				nPos = 0;
            sPar1 = rData.sPar1.Copy(nPos);

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

            switch(rData.nTypeId)
			{
				case TYP_DBNAMEFLD:
				{
					SwDBNameFieldType* pTyp =
                        (SwDBNameFieldType*)pCurShell->GetFldType(0, RES_DBNAMEFLD);
					pFld = new SwDBNameField(pTyp, aDBData);

					break;
				}
				case TYP_DBNEXTSETFLD:
				{
                    SwDBNextSetFieldType* pTyp = (SwDBNextSetFieldType*)pCurShell->GetFldType(
													0, RES_DBNEXTSETFLD);
                    pFld = new SwDBNextSetField(pTyp, sPar1, rData.sPar2, aDBData);
					bExp = sal_True;
					break;
				}
				case TYP_DBNUMSETFLD:
				{
                    SwDBNumSetFieldType* pTyp = (SwDBNumSetFieldType*)pCurShell->GetFldType(
													0, RES_DBNUMSETFLD);
                    pFld = new SwDBNumSetField( pTyp, sPar1, rData.sPar2, aDBData);
					bExp = sal_True;
					break;
				}
				case TYP_DBSETNUMBERFLD:
				{
					SwDBSetNumberFieldType* pTyp = (SwDBSetNumberFieldType*)
                                                pCurShell->GetFldType(0, RES_DBSETNUMBERFLD);
                    pFld = new SwDBSetNumberField( pTyp, aDBData, nFormatId);
					bExp = sal_True;
					break;	
				}
			}
			break;
		}
		case TYP_USERFLD:
		{
			SwUserFieldType* pTyp =
                (SwUserFieldType*)pCurShell->GetFldType(RES_USERFLD, rData.sPar1);

			// nur wenn vorhanden
			if(!pTyp)
			{
                pTyp = (SwUserFieldType*)pCurShell->InsertFldType(
                        SwUserFieldType(pCurShell->GetDoc(), rData.sPar1));
			}
            if (pTyp->GetContent(nFormatId) != rData.sPar2)
                pTyp->SetContent(rData.sPar2, nFormatId);
            pFld = new SwUserField(pTyp, 0, nFormatId);
            if (pFld->GetSubType() != nSubType)
                pFld->SetSubType(nSubType);
			bTbl = sal_True;
			break;
		}
		case TYP_INPUTFLD:
		{
            if ((nSubType & 0x00ff) == INP_VAR)
			{
				SwSetExpFieldType* pTyp = (SwSetExpFieldType*)
                                    pCurShell->GetFldType(RES_SETEXPFLD, rData.sPar1);

				// kein Experssion Type mit dem Namen vorhanden -> anlegen
				if(pTyp)
				{
					SwSetExpField* pExpFld =
                        new SwSetExpField(pTyp, aEmptyStr, nFormatId);

					// Typ vom SwSetExpFieldType nicht veraendern:
					sal_uInt16 nOldSubType = pExpFld->GetSubType();
                    pExpFld->SetSubType(nOldSubType | (nSubType & 0xff00));

                    pExpFld->SetPromptText(rData.sPar2);
					pExpFld->SetInputFlag(sal_True) ;
					bExp = sal_True;
					pFld = pExpFld;
				}
				else
					return sal_False;
			}
			else
			{
                SwInputFieldType* pTyp =
                    (SwInputFieldType*)pCurShell->GetFldType(0, RES_INPUTFLD);

                SwInputField* pInpFld =
                    new SwInputField( pTyp, rData.sPar1, rData.sPar2, nSubType|nsSwExtendedSubType::SUB_INVISIBLE, nFormatId);
                pFld = pInpFld;
            }

			// Dialog starten
			//
            pCurShell->StartInputFldDlg(pFld, sal_False, rData.pParent);
			break;
		}
		case TYP_SETFLD:
		{
            if (!rData.sPar2.Len())   // Leere Variablen sind nicht erlaubt
				return sal_False;

            SwSetExpFieldType* pTyp = (SwSetExpFieldType*)pCurShell->InsertFldType(
                    SwSetExpFieldType(pCurShell->GetDoc(), rData.sPar1) );

            SwSetExpField* pExpFld = new SwSetExpField( pTyp, rData.sPar2, nFormatId);
            pExpFld->SetSubType(nSubType);
            pExpFld->SetPar2(rData.sPar2);
			bExp = sal_True;
			pFld = pExpFld;
			break;
		}
		case TYP_SEQFLD:
		{
            SwSetExpFieldType* pTyp = (SwSetExpFieldType*)pCurShell->InsertFldType(
                    SwSetExpFieldType(pCurShell->GetDoc(), rData.sPar1, nsSwGetSetExpType::GSE_SEQ));

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

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

            pTyp->SetDelimiter(cSeparator);
            SwSetExpField* pExpFld = new SwSetExpField(pTyp, rData.sPar2, nFormatId);
			bExp = sal_True;
			pFld = pExpFld;
            nSubType = nsSwGetSetExpType::GSE_SEQ;
			break;
		}
		case TYP_GETFLD:
		{
			// gibt es ein entprechendes SetField
			SwSetExpFieldType* pSetTyp = (SwSetExpFieldType*)
                                    pCurShell->GetFldType(RES_SETEXPFLD, rData.sPar1);

			if(pSetTyp)
			{
                SwGetExpFieldType* pTyp = (SwGetExpFieldType*)pCurShell->GetFldType(
												0, RES_GETEXPFLD);
                pFld = new SwGetExpField(pTyp, rData.sPar1, pSetTyp->GetType(), nFormatId);
                pFld->SetSubType(nSubType | pSetTyp->GetType());
				bExp = sal_True;
			}
			else
				return sal_False;
			break;
		}
		case TYP_FORMELFLD:
		{
            if(pCurShell->GetFrmType(0,sal_False) & FRMTYPE_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()->
						Execute(FN_NUMBER_FORMAT, SFX_CALLMODE_SYNCHRON, &aFormat, 0L);
				}

                SfxItemSet aBoxSet( pCurShell->GetAttrPool(),
								RES_BOXATR_FORMULA, RES_BOXATR_FORMULA );

                String sFml( rData.sPar2 );
				if( sFml.EraseLeadingChars().Len() &&
					'=' == sFml.GetChar( 0 ) )
					sFml.Erase( 0, 1 );

				aBoxSet.Put( SwTblBoxFormula( sFml ));
                pCurShell->SetTblBoxFormulaAttrs( aBoxSet );
                pCurShell->UpdateTable();

                pCurShell->EndAllAction();
				return sal_True;

/*				// In der Tabelle Tabellenformeln einfuegen
                SwTblFieldType* pTyp = (SwTblFieldType*)pCurShell->GetFldType(
														0, RES_TABLEFLD);
                pFld = new SwTblField(pTyp, rData.sPar2, nsSwGetSetExpType::GSE_EXPR, nFormatId);
				bTbl = sal_True;*/
			}
			else
			{
				SwGetExpFieldType* pTyp = (SwGetExpFieldType*)
                                            pCurShell->GetFldType(0, RES_GETEXPFLD);
                pFld = new SwGetExpField(pTyp, rData.sPar2, nsSwGetSetExpType::GSE_FORMULA, nFormatId);
                pFld->SetSubType(nSubType);
				bExp = sal_True;
			}
			break;
		}
		case TYP_SETREFPAGEFLD:
			pFld = new SwRefPageSetField( (SwRefPageSetFieldType*)
                                pCurShell->GetFldType( 0, RES_REFPAGESETFLD ),
                                (short)rData.sPar2.ToInt32(), 0 != nSubType  );
			bPageVar = sal_True;
			break;

		case TYP_GETREFPAGEFLD:
			pFld = new SwRefPageGetField( (SwRefPageGetFieldType*)
                            pCurShell->GetFldType( 0, RES_REFPAGEGETFLD ), nFormatId );
			bPageVar = sal_True;
			break;
        case TYP_DROPDOWN :
        {
            pFld = new SwDropDownField(pCurShell->GetFldType( 0, RES_DROPDOWN ));
            xub_StrLen nTokenCount = rData.sPar2.Len() ? rData.sPar2.GetTokenCount(DB_DELIM) : 0;
            Sequence<OUString> aEntries(nTokenCount);
            OUString* pArray = aEntries.getArray();
            for(xub_StrLen nToken = 0; nToken < nTokenCount; nToken++)
                pArray[nToken] = rData.sPar2.GetToken(nToken, DB_DELIM);
            ((SwDropDownField*)pFld)->SetItems(aEntries);
            ((SwDropDownField*)pFld)->SetName(rData.sPar1);
        }
        break;
		default:
		{	ASSERT(!this, "Falscher Feldtyp");
			return sal_False;
		}
	}
	ASSERT(pFld, "Feld nicht vorhanden");


     //the auto language flag has to be set prior to the language!
     pFld->SetAutomaticLanguage(rData.bIsAutomaticLanguage);
     sal_uInt16 nLang = GetCurrLanguage();
     pFld->SetLanguage(nLang);

	// Einfuegen
    pCurShell->StartAllAction();

    const SwPaM* pCommentRange = NULL;
    if (pPam && *pPam->GetPoint() != *pPam->GetMark() && rData.nTypeId == TYP_POSTITFLD)
    {
        pCommentRange = pPam;
    }

    pCurShell->Insert( *pFld, pCommentRange );

	if(bExp && bEvalExp)
        pCurShell->UpdateExpFlds(sal_True);

	if(bTbl)
	{
        pCurShell->Left(CRSR_SKIP_CHARS, sal_False, 1, sal_False );
        pCurShell->UpdateFlds(*pFld);
        pCurShell->Right(CRSR_SKIP_CHARS, sal_False, 1, sal_False );
	}
	else if( bPageVar )
        ((SwRefPageGetFieldType*)pCurShell->GetFldType( 0, RES_REFPAGEGETFLD ))->UpdateFlds();
    else if( TYP_GETREFFLD == rData.nTypeId )
		pFld->GetTyp()->ModifyNotification( 0, 0 );

	// temporaeres Feld loeschen
	delete pFld;

    pCurShell->EndAllAction();
	return sal_True;
}

/*--------------------------------------------------------------------
	Beschreibung: Felder Update
 --------------------------------------------------------------------*/


void SwFldMgr::UpdateCurFld(sal_uLong nFormat,
							const String& rPar1,
							const String& rPar2,
                            SwField * _pTmpFld) // #111840#
{
	// Format aendern
	ASSERT(pCurFld, "kein Feld an der CursorPos");

    bool bDelete = false;
    SwField *pTmpFld;		// mb: fixed memory leak
    if (NULL != _pTmpFld)
    {
        pTmpFld = _pTmpFld;
    }
    else
    {
        pTmpFld = pCurFld->CopyField();
        bDelete = true;
    }

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

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

	sal_Bool bSetPar2 = sal_True;
	sal_Bool bSetPar1 = sal_True;
	String sPar1( rPar1 );
	String sPar2( rPar2 );

	// Order to Format
	switch( nTypeId )
	{
		case TYP_DDEFLD:
		{
			//JP 28.08.95: DDE-Topics/-Items koennen Blanks in ihren
			//				Namen haben! Wird hier noch nicht beachtet.
            sal_uInt16 nTmpPos = sPar2.SearchAndReplace( ' ', sfx2::cTokenSeperator );
            sPar2.SearchAndReplace( ' ', sfx2::cTokenSeperator, nTmpPos );
			break;
		}

		case TYP_CHAPTERFLD:
		{
            sal_uInt16 nByte = (sal_uInt16)rPar2.ToInt32();
			nByte = Max(sal_uInt16(1), nByte);
			nByte = Min(nByte, sal_uInt16(MAXLEVEL));
			nByte -= 1;
			((SwChapterField*)pTmpFld)->SetLevel((sal_uInt8)nByte);
			bSetPar2 = sal_False;
			break;
		}

		case TYP_SCRIPTFLD:
			((SwScriptField*)pTmpFld)->SetCodeURL((sal_Bool)nFormat);
			break;

		case TYP_NEXTPAGEFLD:
			if( SVX_NUM_CHAR_SPECIAL == nFormat )
			{
				((SwPageNumberField*)pCurFld)->SetUserString( sPar2 );
				sPar2 = '1';
			}
			else
			{
				if( nFormat + 2 == SVX_NUM_PAGEDESC )
					nFormat = SVX_NUM_PAGEDESC;
                short nOff = (short)sPar2.ToInt32();
				nOff += 1;
				sPar2 = String::CreateFromInt32(nOff);
			}
			break;

		case TYP_PREVPAGEFLD:
			if( SVX_NUM_CHAR_SPECIAL == nFormat )
			{
				((SwPageNumberField*)pCurFld)->SetUserString( sPar2 );
				sPar2 = String::CreateFromAscii(
                    RTL_CONSTASCII_STRINGPARAM("-1"));
			}
			else
			{
				if( nFormat + 2 == SVX_NUM_PAGEDESC )
					nFormat = SVX_NUM_PAGEDESC;
                short nOff = (short)sPar2.ToInt32();
				nOff -= 1;
				sPar2 = String::CreateFromInt32(nOff);
			}
			break;

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

		case TYP_GETREFFLD:
			{
				bSetPar2 = sal_False;
                ((SwGetRefField*)pTmpFld)->SetSubType( (sal_uInt16)rPar2.ToInt32() );
				sal_uInt16 nPos = rPar2.Search( '|' );
				if( STRING_NOTFOUND != nPos )
                    ((SwGetRefField*)pTmpFld)->SetSeqNo( (sal_uInt16)rPar2.Copy( nPos + 1 ).ToInt32());
			}
			break;
		case TYP_DROPDOWN:
		{
            xub_StrLen nTokenCount = sPar2.Len() ? sPar2.GetTokenCount(DB_DELIM) : 0;
            Sequence<OUString> aEntries(nTokenCount);
            OUString* pArray = aEntries.getArray();
            for(xub_StrLen nToken = 0; nToken < nTokenCount; nToken++)
                pArray[nToken] = sPar2.GetToken(nToken, DB_DELIM);
            ((SwDropDownField*)pTmpFld)->SetItems(aEntries);
            ((SwDropDownField*)pTmpFld)->SetName(sPar1);
			bSetPar1 = bSetPar2 = sal_False;
		}
		break;
        case TYP_AUTHORITY :
        {    
            //#i99069# changes to a bibliography field should change the field type
            SwAuthorityField* pAuthorityField = static_cast<SwAuthorityField*>(pTmpFld);
            SwAuthorityFieldType* pAuthorityType = static_cast<SwAuthorityFieldType*>(pType);
            SwAuthEntry aTempEntry;
            for( sal_uInt16 i = 0; i < AUTH_FIELD_END; ++i )
                aTempEntry.SetAuthorField( (ToxAuthorityField)i,
                                rPar1.GetToken( i, TOX_STYLE_DELIMITER ));
            if( pAuthorityType->ChangeEntryContent( &aTempEntry ) )
            {
                pType->UpdateFlds();
                pSh->SetModified();
            }
        
            if( aTempEntry.GetAuthorField( AUTH_FIELD_IDENTIFIER ) == 
                pAuthorityField->GetFieldText( AUTH_FIELD_IDENTIFIER ) ) 
                bSetPar1 = sal_False; //otherwise it's a new or changed entry, the field needs to be updated    
            bSetPar2 = sal_False;
        }
        break;
	}

	// Format setzen
	// Format wegen NumberFormatter vor SetPar2 einstellen!
	pTmpFld->ChangeFormat(nFormat);

	if(bSetPar1)
		pTmpFld->SetPar1( sPar1 );
	if( bSetPar2 )
		pTmpFld->SetPar2( sPar2 );

	// Update anschmeissen
	if(nTypeId == TYP_DDEFLD ||
	   nTypeId == TYP_USERFLD ||
	   nTypeId == TYP_USRINPFLD)
	{
		pType->UpdateFlds();
        pSh->SetModified();
	}
	else {
		// mb: #32157
        pSh->SwEditShell::UpdateFlds(*pTmpFld);
		GetCurFld();
	}

    if (bDelete)
        delete pTmpFld;

    pSh->EndAllAction();
}

/*--------------------------------------------------------------------
	Beschreibung: ExpressionFields explizit evaluieren
 --------------------------------------------------------------------*/
void SwFldMgr::EvalExpFlds(SwWrtShell* pSh)
{
	if (pSh == NULL)
		pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();

	if(pSh)
	{
		pSh->StartAllAction();
		pSh->UpdateExpFlds(sal_True);
		pSh->EndAllAction();
	}
}
sal_uInt16 SwFldMgr::GetCurrLanguage() const
{
	SwWrtShell* pSh = pWrtShell ? pWrtShell : ::lcl_GetShell();
	if( pSh )
		return pSh->GetCurLang();
	return SvxLocaleToLanguage( SvtSysLocale().GetLocaleData().getLocale() );
}

void SwFieldType::_GetFldName()
{
	// mba: this is an awful mess; a fix is available, but too much for 3.4 -> applay plaster
	static const sal_uInt16 coFldCnt = 43;

	static sal_uInt16 __READONLY_DATA coFldNms[ coFldCnt ] = {
		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
	};

	// Infos fuer Felder einfuegen
	SwFieldType::pFldNames = new SvStringsDtor( (sal_uInt8)coFldCnt, 2 );
	for( sal_uInt16 nIdx = 0; nIdx < coFldCnt; ++nIdx )
	{
		String* pTmp = new SW_RESSTR( coFldNms[ nIdx ] );
        pTmp->Assign( MnemonicGenerator::EraseAllMnemonicChars( *pTmp ) );
		SwFieldType::pFldNames->Insert(pTmp, nIdx );
	}
}

/*--------------------------------------------------------------------
	Beschreibung:
 --------------------------------------------------------------------*/

sal_Bool SwFldMgr::ChooseMacro(const String&)
{
    sal_Bool bRet = sal_False;

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

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

    return bRet;
}

void SwFldMgr::SetMacroPath(const String& rPath)
{
    sMacroPath = rPath;
    sMacroName = rPath;

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

    Reference< XMultiServiceFactory > xSMgr =
        ::comphelper::getProcessServiceFactory();

    Reference< uri::XUriReferenceFactory >
        xFactory( xSMgr->createInstance(
            ::rtl::OUString::createFromAscii(
                "com.sun.star.uri.UriReferenceFactory" ) ), UNO_QUERY );

    if ( xFactory.is() )
    {
        Reference< uri::XVndSunStarScriptUrl >
            xUrl( xFactory->parse( sMacroPath ), UNO_QUERY );

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

/*--------------------------------------------------------------------
	Beschreibung:
 --------------------------------------------------------------------*/

sal_uLong SwFldMgr::GetDefaultFormat(sal_uInt16 nTypeId, sal_Bool bIsText, SvNumberFormatter* pFormatter, double* pVal)
{
	double fValue;
	short  nDefFormat;

	switch (nTypeId)
	{
		case TYP_TIMEFLD:
		case TYP_DATEFLD:
		{
			Date aDate;
			Date* pNullDate = pFormatter->GetNullDate();

			fValue = aDate - *pNullDate;

			Time aTime;

			sal_uLong nNumFmtTime = (sal_uLong)aTime.GetSec() + (sal_uLong)aTime.GetMin() * 60L +
						  (sal_uLong)aTime.GetHour() * 3600L;

			fValue += (double)nNumFmtTime / 86400.0;

			nDefFormat = (nTypeId == TYP_DATEFLD) ? NUMBERFORMAT_DATE : NUMBERFORMAT_TIME;
		}
		break;

		default:
			if (bIsText)
			{
				fValue = 0.0;
				nDefFormat = NUMBERFORMAT_TEXT;
			}
			else
			{
				fValue = 0.0;
				nDefFormat = NUMBERFORMAT_ALL;
			}
			break;
	}

	if (pVal)
		*pVal = fValue;

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

/* -----------------------------01.03.01 16:46--------------------------------

 ---------------------------------------------------------------------------*/
Reference<XNumberingTypeInfo> SwFldMgr::GetNumberingInfo() const
{
	if(!xNumberingInfo.is())
	{
		Reference< XMultiServiceFactory > xMSF = ::comphelper::getProcessServiceFactory();
		Reference < XInterface > xI = xMSF->createInstance(
			::rtl::OUString::createFromAscii(
							"com.sun.star.text.DefaultNumberingProvider" ));
		Reference<XDefaultNumberingProvider> xDefNum(xI, UNO_QUERY);
		DBG_ASSERT(xDefNum.is(), "service missing: \"com.sun.star.text.DefaultNumberingProvider\"");
		((SwFldMgr*)this)->xNumberingInfo = Reference<XNumberingTypeInfo>(xDefNum, UNO_QUERY);
	}
	return xNumberingInfo;
}