/* -*- 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 <config_fuzzers.h>
#include <cmdid.h>
#include <hintids.hxx>
#include <svl/numformat.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 <o3tl/string_view.hxx>
#include <tools/resary.hxx>
#include <osl/diagnose.h>
#include <sfx2/dispatch.hxx>
#include <sfx2/linkmgr.hxx>
#include <sfx2/app.hxx>
#include <sfx2/viewfrm.hxx>
#include <svx/strarray.hxx>
#include <fmtrfmrk.hxx>
#include <svl/zforlist.hxx>
#include <svl/zformat.hxx>
#include <vcl/mnemonic.hxx>
#include <view.hxx>
#include <wrtsh.hxx>
#include <doc.hxx>
#include <swmodule.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 <ndtxt.hxx>
#include <cntfrm.hxx>
#include <flddropdown.hxx>
#include <strings.hrc>
#include <tox.hxx>
#include <viewopt.hxx>
#include <txmsrt.hxx>
#include <unotools/useroptions.hxx>
#include <IDocumentContentOperations.hxx>
#include <translatehelper.hxx>
using namespace com::sun::star::uno;
using namespace com::sun::star::container;
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
};
const sal_uInt16 VF_COUNT = 1; // { 0 }
const sal_uInt16 VF_USR_COUNT = 2; // { 0, nsSwExtendedSubType::SUB_CMD }
const sal_uInt16 VF_DB_COUNT = 1; // { nsSwExtendedSubType::SUB_OWN_FMT }
const TranslateId FLD_EU_ARY[] =
{
FLD_EU_COMPANY,
FLD_EU_GIVENNAME,
FLD_EU_SURNAME,
FLD_EU_INITIALS,
FLD_EU_STREET,
FLD_EU_COUNTRY,
FLD_EU_POSTCODE,
FLD_EU_TOWN,
FLD_EU_TITLE,
FLD_EU_POS,
FLD_EU_TELPERSONAL,
FLD_EU_TELWORK,
FLD_EU_FAX,
FLD_EU_EMAIL,
FLD_EU_REGION
};
const TranslateId FMT_AUTHOR_ARY[] =
{
FMT_AUTHOR_NAME,
FMT_AUTHOR_SCUT
};
const TranslateId FLD_DATE_ARY[] =
{
FLD_DATE_FIX,
FLD_DATE_STD,
};
const TranslateId FLD_TIME_ARY[] =
{
FLD_TIME_FIX,
FLD_TIME_STD
};
const TranslateId 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
};
const TranslateId FMT_FF_ARY[] =
{
FMT_FF_NAME,
FMT_FF_PATHNAME,
FMT_FF_PATH,
FMT_FF_NAME_NOEXT,
FMT_FF_UI_NAME,
FMT_FF_UI_RANGE
};
const TranslateId FLD_STAT_ARY[] =
{
FLD_STAT_PAGE,
FLD_STAT_PARA,
FLD_STAT_WORD,
FLD_STAT_CHAR,
FLD_STAT_TABLE,
FLD_STAT_GRF,
FLD_STAT_OBJ
};
const TranslateId FMT_CHAPTER_ARY[] =
{
FMT_CHAPTER_NO,
FMT_CHAPTER_NAME,
FMT_CHAPTER_NAMENO,
FMT_CHAPTER_NO_NOSEPARATOR
};
const TranslateId FLD_INPUT_ARY[] =
{
FLD_INPUT_TEXT
};
const TranslateId FMT_MARK_ARY[] =
{
FMT_MARK_TEXT,
FMT_MARK_TABLE,
FMT_MARK_FRAME,
FMT_MARK_GRAFIC,
FMT_MARK_OLE
};
const TranslateId 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
};
const TranslateId FMT_REG_ARY[] =
{
FMT_REG_AUTHOR,
FMT_REG_TIME,
FMT_REG_DATE
};
const TranslateId FMT_DBFLD_ARY[] =
{
FMT_DBFLD_DB,
FMT_DBFLD_SYS
};
const TranslateId FMT_SETVAR_ARY[] =
{
FMT_SETVAR_SYS,
FMT_SETVAR_TEXT
};
const TranslateId FMT_GETVAR_ARY[] =
{
FMT_GETVAR_TEXT,
FMT_GETVAR_NAME
};
const TranslateId FMT_DDE_ARY[] =
{
FMT_DDE_NORMAL,
FMT_DDE_HOT
};
const TranslateId FLD_PAGEREF_ARY[] =
{
FLD_PAGEREF_OFF,
FLD_PAGEREF_ON
};
const TranslateId FMT_USERVAR_ARY[] =
{
FMT_USERVAR_TEXT,
FMT_USERVAR_CMD
};
namespace {
// field types and subtypes
struct SwFieldPack
{
SwFieldTypesEnum nTypeId;
const TranslateId* pSubTypeResIds;
size_t nSubTypeLength;
const TranslateId* pFormatResIds;
size_t nFormatLength;
};
}
// strings and formats
const SwFieldPack aSwFields[] =
{
// Document
{ SwFieldTypesEnum::ExtendedUser, FLD_EU_ARY, std::size(FLD_EU_ARY), nullptr, 0 },
{ SwFieldTypesEnum::Author, nullptr, 0, FMT_AUTHOR_ARY, std::size(FMT_AUTHOR_ARY) },
{ SwFieldTypesEnum::Date, FLD_DATE_ARY, std::size(FLD_DATE_ARY), nullptr, 0 },
{ SwFieldTypesEnum::Time, FLD_TIME_ARY, std::size(FLD_TIME_ARY), nullptr, 0 },
{ SwFieldTypesEnum::PageNumber, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) -1 },
{ SwFieldTypesEnum::NextPage, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) },
{ SwFieldTypesEnum::PreviousPage, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) },
{ SwFieldTypesEnum::Filename, nullptr, 0, FMT_FF_ARY, std::size(FMT_FF_ARY) },
{ SwFieldTypesEnum::DocumentStatistics, FLD_STAT_ARY, std::size(FLD_STAT_ARY), FMT_NUM_ARY, std::size(FMT_NUM_ARY) -1 },
{ SwFieldTypesEnum::Chapter, nullptr, 0, FMT_CHAPTER_ARY, std::size(FMT_CHAPTER_ARY) },
{ SwFieldTypesEnum::TemplateName, nullptr, 0, FMT_FF_ARY, std::size(FMT_FF_ARY) },
{ SwFieldTypesEnum::ParagraphSignature, nullptr, 0, nullptr, 0 },
// Functions
{ SwFieldTypesEnum::ConditionalText, nullptr, 0, nullptr, 0 },
{ SwFieldTypesEnum::Dropdown, nullptr, 0, nullptr, 0 },
{ SwFieldTypesEnum::Input, FLD_INPUT_ARY, std::size(FLD_INPUT_ARY), nullptr, 0 },
{ SwFieldTypesEnum::Macro, nullptr, 0, nullptr, 0 },
{ SwFieldTypesEnum::JumpEdit, nullptr, 0, FMT_MARK_ARY, std::size(FMT_MARK_ARY) },
{ SwFieldTypesEnum::CombinedChars, nullptr, 0, nullptr, 0 },
{ SwFieldTypesEnum::HiddenText, nullptr, 0, nullptr, 0 },
{ SwFieldTypesEnum::HiddenParagraph, nullptr, 0, nullptr, 0 },
// Cross-References
{ SwFieldTypesEnum::SetRef, nullptr, 0, nullptr, 0 },
{ SwFieldTypesEnum::GetRef, nullptr, 0, FMT_REF_ARY, std::size(FMT_REF_ARY) },
// DocInformation
{ SwFieldTypesEnum::DocumentInfo, nullptr, 0, FMT_REG_ARY, std::size(FMT_REG_ARY) },
// Database
{ SwFieldTypesEnum::Database, nullptr, 0, FMT_DBFLD_ARY, std::size(FMT_DBFLD_ARY) },
{ SwFieldTypesEnum::DatabaseNextSet, nullptr, 0, nullptr, 0 },
{ SwFieldTypesEnum::DatabaseNumberSet, nullptr, 0, nullptr, 0 },
{ SwFieldTypesEnum::DatabaseSetNumber, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) - 2 },
{ SwFieldTypesEnum::DatabaseName, nullptr, 0, nullptr, 0 },
// Variables
{ SwFieldTypesEnum::Set, nullptr, 0, FMT_SETVAR_ARY, std::size(FMT_SETVAR_ARY) },
{ SwFieldTypesEnum::Get, nullptr, 0, FMT_GETVAR_ARY, std::size(FMT_GETVAR_ARY) },
{ SwFieldTypesEnum::DDE, nullptr, 0, FMT_DDE_ARY, std::size(FMT_DDE_ARY) },
{ SwFieldTypesEnum::Formel, nullptr, 0, FMT_GETVAR_ARY, std::size(FMT_GETVAR_ARY) },
{ SwFieldTypesEnum::Input, FLD_INPUT_ARY, std::size(FLD_INPUT_ARY), nullptr, 0 },
{ SwFieldTypesEnum::Sequence, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) - 2 },
{ SwFieldTypesEnum::SetRefPage, FLD_PAGEREF_ARY, std::size(FLD_PAGEREF_ARY),nullptr, 0 },
{ SwFieldTypesEnum::GetRefPage, nullptr, 0, FMT_NUM_ARY, std::size(FMT_NUM_ARY) - 1 },
{ SwFieldTypesEnum::User, nullptr, 0, FMT_USERVAR_ARY, std::size(FMT_USERVAR_ARY) }
};
// access to the shell
static SwWrtShell* lcl_GetShell()
{
if (SwView* pView = GetActiveView())
return pView->GetWrtShellPtr();
return nullptr;
}
static 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( std::u16string_view 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();
if(!m_pCurField)
return nullptr;
// preprocess current values; determine parameter 1 and parameter 2
m_aCurPar1 = m_pCurField->GetPar1();
m_aCurPar2 = m_pCurField->GetPar2();
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(SwFieldTypesEnum nTypeId, sal_uInt16 nSubType)
{
if (nTypeId == SwFieldTypesEnum::SetInput)
nTypeId = SwFieldTypesEnum::Set;
if (nTypeId == SwFieldTypesEnum::Input && (nSubType & INP_USR))
nTypeId = SwFieldTypesEnum::User;
if (nTypeId == SwFieldTypesEnum::FixedDate)
nTypeId = SwFieldTypesEnum::Date;
if (nTypeId == SwFieldTypesEnum::FixedTime)
nTypeId = SwFieldTypesEnum::Time;
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_...
SwFieldTypesEnum SwFieldMgr::GetTypeId(sal_uInt16 nPos)
{
OSL_ENSURE(nPos < ::GetPackCount(), "forbidden Pos");
return aSwFields[ nPos ].nTypeId;
}
const OUString & SwFieldMgr::GetTypeStr(sal_uInt16 nPos)
{
OSL_ENSURE(nPos < ::GetPackCount(), "forbidden TypeId");
SwFieldTypesEnum nFieldWh = aSwFields[ nPos ].nTypeId;
// special treatment for date/time fields (without var/fix)
if( SwFieldTypesEnum::Date == nFieldWh )
{
static OUString g_aDate( SwResId( STR_DATEFLD ) );
return g_aDate;
}
if( SwFieldTypesEnum::Time == nFieldWh )
{
static OUString g_aTime( SwResId( STR_TIMEFLD ) );
return g_aTime;
}
return SwFieldType::GetTypeStr( nFieldWh );
}
// determine Pos in the list
sal_uInt16 SwFieldMgr::GetPos(SwFieldTypesEnum nTypeId)
{
switch( nTypeId )
{
case SwFieldTypesEnum::FixedDate: nTypeId = SwFieldTypesEnum::Date; break;
case SwFieldTypesEnum::FixedTime: nTypeId = SwFieldTypesEnum::Time; break;
case SwFieldTypesEnum::SetInput: nTypeId = SwFieldTypesEnum::Set; break;
case SwFieldTypesEnum::UserInput: nTypeId = SwFieldTypesEnum::User; break;
default: 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(SwFieldTypesEnum nTypeId, std::vector<OUString>& rToFill)
{
SwWrtShell *pSh = m_pWrtShell ? m_pWrtShell : lcl_GetShell();
OSL_ENSURE(pSh, "no SwWrtShell found");
if(!pSh)
return;
const sal_uInt16 nPos = GetPos(nTypeId);
switch(nTypeId)
{
case SwFieldTypesEnum::SetRef:
case SwFieldTypesEnum::GetRef:
{
// references are no fields
pSh->GetRefMarks( &rToFill );
break;
}
case SwFieldTypesEnum::Macro:
{
break;
}
case SwFieldTypesEnum::Input:
{
rToFill.push_back(SwResId(aSwFields[nPos].pSubTypeResIds[0]));
[[fallthrough]]; // move on at generic types
}
case SwFieldTypesEnum::DDE:
case SwFieldTypesEnum::Sequence:
case SwFieldTypesEnum::Formel:
case SwFieldTypesEnum::Get:
case SwFieldTypesEnum::Set:
case SwFieldTypesEnum::User:
{
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 == SwFieldTypesEnum::DDE && pFieldType->Which() == SwFieldIds::Dde) ||
(nTypeId == SwFieldTypesEnum::User && nWhich == SwFieldIds::User) ||
(nTypeId == SwFieldTypesEnum::Get && nWhich == SwFieldIds::SetExp &&
!(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
(nTypeId == SwFieldTypesEnum::Set && nWhich == SwFieldIds::SetExp &&
!(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
(nTypeId == SwFieldTypesEnum::Sequence && nWhich == SwFieldIds::SetExp &&
(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ)) ||
((nTypeId == SwFieldTypesEnum::Input || nTypeId == SwFieldTypesEnum::Formel) &&
(nWhich == SwFieldIds::User ||
(nWhich == SwFieldIds::SetExp &&
!(static_cast<SwSetExpFieldType*>(pFieldType)->GetType() & nsSwGetSetExpType::GSE_SEQ))) ) )
{
rToFill.push_back(pFieldType->GetName());
}
}
break;
}
case SwFieldTypesEnum::DatabaseNextSet:
case SwFieldTypesEnum::DatabaseNumberSet:
case SwFieldTypesEnum::DatabaseName:
case SwFieldTypesEnum::DatabaseSetNumber:
break;
default:
{
// static SubTypes
if(nPos != USHRT_MAX)
{
sal_uInt16 nCount;
if (nTypeId == SwFieldTypesEnum::DocumentInfo)
nCount = DI_SUBTYPE_END - DI_SUBTYPE_BEGIN;
else
nCount = aSwFields[nPos].nSubTypeLength;
for(sal_uInt16 i = 0; i < nCount; ++i)
{
OUString sNew;
if (nTypeId == SwFieldTypesEnum::DocumentInfo)
{
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(SwFieldTypesEnum nTypeId, bool bHtmlMode) const
{
assert(nTypeId < SwFieldTypesEnum::LAST && "forbidden TypeId");
{
const sal_uInt16 nPos = GetPos(nTypeId);
if (nPos == USHRT_MAX || (bHtmlMode && nTypeId == SwFieldTypesEnum::Set))
return 0;
sal_uInt16 nCount = aSwFields[nPos].nFormatLength;
if (nTypeId == SwFieldTypesEnum::Filename)
nCount -= 2; // no range or template
const TranslateId* pStart = aSwFields[nPos].pFormatResIds;
if (!pStart)
return nCount;
if (*pStart == FMT_GETVAR_ARY[0] || *pStart == FMT_SETVAR_ARY[0])
return VF_COUNT;
else if (*pStart == FMT_USERVAR_ARY[0])
return VF_USR_COUNT;
else if (*pStart == FMT_DBFLD_ARY[0])
return VF_DB_COUNT;
else if (*pStart == FMT_NUM_ARY[0])
{
GetNumberingInfo();
if(m_xNumberingInfo.is())
{
const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
// #i28073# it's not necessarily a sorted sequence
//skip all values below or equal to CHARS_LOWER_LETTER_N
nCount += std::count_if(aTypes.begin(), aTypes.end(),
[](sal_Int16 nCurrent) { return nCurrent > NumberingType::CHARS_LOWER_LETTER_N; });
}
return nCount;
}
return nCount;
}
}
// determine FormatString to a type
OUString SwFieldMgr::GetFormatStr(SwFieldTypesEnum nTypeId, sal_uInt32 nFormatId) const
{
assert(nTypeId < SwFieldTypesEnum::LAST && "forbidden TypeId");
const sal_uInt16 nPos = GetPos(nTypeId);
if (nPos == USHRT_MAX)
return OUString();
const TranslateId* pStart = aSwFields[nPos].pFormatResIds;
if (!pStart)
return OUString();
if (SwFieldTypesEnum::Author == nTypeId || SwFieldTypesEnum::Filename == 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())
{
const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
sal_Int32 nOffset = aSwFields[nPos].nFormatLength;
sal_uInt32 nValidEntry = 0;
for (const sal_Int16 nCurrent : aTypes)
{
if(nCurrent > NumberingType::CHARS_LOWER_LETTER_N &&
(nCurrent != (NumberingType::BITMAP | LINK_TOKEN)))
{
if (nValidEntry == nFormatId - nOffset)
{
sal_uInt32 n = SvxNumberingTypeTable::FindIndex(nCurrent);
if (n != RESARRAY_INDEX_NOTFOUND)
{
aRet = SvxNumberingTypeTable::GetString(n);
}
else
{
aRet = m_xNumberingInfo->getNumberingIdentifier( nCurrent );
}
break;
}
++nValidEntry;
}
}
}
}
return aRet;
}
// determine FormatId from Pseudo-ID
sal_uInt16 SwFieldMgr::GetFormatId(SwFieldTypesEnum nTypeId, sal_uInt32 nFormatId) const
{
sal_uInt16 nId = o3tl::narrowing<sal_uInt16>(nFormatId);
switch( nTypeId )
{
case SwFieldTypesEnum::DocumentInfo:
{
TranslateId 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 SwFieldTypesEnum::PageNumber:
case SwFieldTypesEnum::NextPage:
case SwFieldTypesEnum::PreviousPage:
case SwFieldTypesEnum::DocumentStatistics:
case SwFieldTypesEnum::DatabaseSetNumber:
case SwFieldTypesEnum::Sequence:
case SwFieldTypesEnum::GetRefPage:
{
sal_uInt16 nPos = GetPos(nTypeId);
if (nFormatId < aSwFields[nPos].nFormatLength)
{
const TranslateId 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())
{
const Sequence<sal_Int16> aTypes = m_xNumberingInfo->getSupportedNumberingTypes();
sal_Int32 nOffset = aSwFields[nPos].nFormatLength;
sal_Int32 nValidEntry = 0;
for (const sal_Int16 nCurrent : aTypes)
{
if (nCurrent > NumberingType::CHARS_LOWER_LETTER_N)
{
if (nValidEntry == static_cast<sal_Int32>(nFormatId) - nOffset)
{
nId = nCurrent;
break;
}
++nValidEntry;
}
}
}
break;
}
case SwFieldTypesEnum::DDE:
{
const TranslateId 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;
}
default: 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 SwFieldTypesEnum nTypeId = m_pCurField->GetTypeId();
if( SwFieldTypesEnum::SetInput == nTypeId || SwFieldTypesEnum::UserInput == 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->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
SwFieldTypesEnum SwFieldMgr::GetCurTypeId() const
{
return m_pCurField ? m_pCurField->GetTypeId() : SwFieldTypesEnum::Unknown;
}
// Over string insert field or update
bool SwFieldMgr::InsertField(
SwInsertField_Data& rData)
{
std::unique_ptr<SwField> pField;
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 SwFieldTypesEnum::Postit:
{
SvtUserOptions aUserOpt;
SwPostItFieldType* pType = static_cast<SwPostItFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Postit));
pField.reset(
new SwPostItField(
pType,
rData.m_sPar1, // author
rData.m_sPar2, // content
aUserOpt.GetID(), // author's initials
OUString(), // name
DateTime(DateTime::SYSTEM) ));
}
break;
case SwFieldTypesEnum::Script:
{
SwScriptFieldType* pType =
static_cast<SwScriptFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Script));
pField.reset(new SwScriptField(pType, rData.m_sPar1, rData.m_sPar2, static_cast<bool>(nFormatId)));
break;
}
case SwFieldTypesEnum::CombinedChars:
{
SwCombinedCharFieldType* pType = static_cast<SwCombinedCharFieldType*>(
pCurShell->GetFieldType( 0, SwFieldIds::CombinedChars ));
pField.reset(new SwCombinedCharField( pType, rData.m_sPar1 ));
}
break;
case SwFieldTypesEnum::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.reset(new SwAuthorityField(pType, rData.m_sPar1));
}
break;
case SwFieldTypesEnum::Date:
case SwFieldTypesEnum::Time:
{
sal_uInt16 nSub = static_cast< sal_uInt16 >(rData.m_nTypeId == SwFieldTypesEnum::Date ? DATEFLD : TIMEFLD);
nSub |= nSubType == DATE_VAR ? 0 : FIXEDFLD;
SwDateTimeFieldType* pTyp =
static_cast<SwDateTimeFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::DateTime) );
pField.reset(new SwDateTimeField(pTyp, nSub, nFormatId));
pField->SetPar2(rData.m_sPar2);
break;
}
case SwFieldTypesEnum::Filename:
{
SwFileNameFieldType* pTyp =
static_cast<SwFileNameFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Filename) );
pField.reset(new SwFileNameField(pTyp, nFormatId));
break;
}
case SwFieldTypesEnum::TemplateName:
{
SwTemplNameFieldType* pTyp =
static_cast<SwTemplNameFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::TemplateName) );
pField.reset(new SwTemplNameField(pTyp, nFormatId));
break;
}
case SwFieldTypesEnum::Chapter:
{
sal_uInt16 nByte = o3tl::narrowing<sal_uInt16>(rData.m_sPar2.toInt32());
SwChapterFieldType* pTyp =
static_cast<SwChapterFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Chapter) );
pField.reset(new SwChapterField(pTyp, nFormatId));
nByte = std::max(sal_uInt16(1), nByte);
nByte = std::min(nByte, sal_uInt16(MAXLEVEL));
nByte -= 1;
static_cast<SwChapterField*>(pField.get())->SetLevel(static_cast<sal_uInt8>(nByte));
break;
}
case SwFieldTypesEnum::NextPage:
case SwFieldTypesEnum::PreviousPage:
case SwFieldTypesEnum::PageNumber:
{
short nOff = static_cast<short>(rData.m_sPar2.toInt32());
if(rData.m_nTypeId == SwFieldTypesEnum::NextPage)
{
if( SVX_NUM_CHAR_SPECIAL == nFormatId )
nOff = 1;
else
nOff += 1;
nSubType = PG_NEXT;
}
else if(rData.m_nTypeId == SwFieldTypesEnum::PreviousPage)
{
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.reset(new SwPageNumberField(pTyp, nSubType, nFormatId, nOff));
if( SVX_NUM_CHAR_SPECIAL == nFormatId &&
( PG_PREV == nSubType || PG_NEXT == nSubType ) )
static_cast<SwPageNumberField*>(pField.get())->SetUserString( rData.m_sPar2 );
break;
}
case SwFieldTypesEnum::DocumentStatistics:
{
SwDocStatFieldType* pTyp =
static_cast<SwDocStatFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::DocStat) );
pField.reset(new SwDocStatField(pTyp, nSubType, nFormatId));
break;
}
case SwFieldTypesEnum::Author:
{
SwAuthorFieldType* pTyp =
static_cast<SwAuthorFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Author) );
pField.reset(new SwAuthorField(pTyp, nFormatId));
break;
}
case SwFieldTypesEnum::ConditionalText:
case SwFieldTypesEnum::HiddenText:
{
SwHiddenTextFieldType* pTyp =
static_cast<SwHiddenTextFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::HiddenText) );
pField.reset(new SwHiddenTextField(pTyp, true, rData.m_sPar1, rData.m_sPar2, false, rData.m_nTypeId));
bExp = true;
break;
}
case SwFieldTypesEnum::HiddenParagraph:
{
SwHiddenParaFieldType* pTyp =
static_cast<SwHiddenParaFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::HiddenPara) );
pField.reset(new SwHiddenParaField(pTyp, rData.m_sPar1));
bExp = true;
break;
}
case SwFieldTypesEnum::SetRef:
{
if( !rData.m_sPar1.isEmpty() && CanInsertRefMark( rData.m_sPar1 ) )
{
const OUString& rRefmarkText = rData.m_sPar2;
SwPaM* pCursorPos = pCurShell->GetCursor();
pCurShell->StartAction();
bool bHadMark = pCursorPos->HasMark();
// If we have no selection and the refmark text is provided, then the text is
// expected to be HTML.
if (!bHadMark && !rRefmarkText.isEmpty())
{
// Split node to remember where the start position is.
bool bSuccess = pCurShell->GetDoc()->getIDocumentContentOperations().SplitNode(
*pCursorPos->GetPoint(), /*bChkTableStart=*/false);
if (bSuccess)
{
SwPaM aRefmarkPam(*pCursorPos->GetPoint());
aRefmarkPam.Move(fnMoveBackward, GoInContent);
// Paste HTML content.
SwTranslateHelper::PasteHTMLToPaM(
*pCurShell, pCursorPos, rRefmarkText.toUtf8());
// Undo the above SplitNode().
aRefmarkPam.SetMark();
aRefmarkPam.Move(fnMoveForward, GoInContent);
pCurShell->GetDoc()->getIDocumentContentOperations().DeleteAndJoin(
aRefmarkPam);
*aRefmarkPam.GetMark() = *pCursorPos->GetPoint();
*pCursorPos = aRefmarkPam;
}
}
pCurShell->SetAttrItem( SwFormatRefMark( rData.m_sPar1 ) );
if (!bHadMark && !rRefmarkText.isEmpty())
{
pCursorPos->DeleteMark();
}
pCurShell->EndAction();
return true;
}
return false;
}
case SwFieldTypesEnum::GetRef:
{
SwGetRefFieldType* pTyp =
static_cast<SwGetRefFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::GetRef) );
sal_uInt16 nSeqNo = 0;
sal_uInt16 nFlags = 0;
if (nSubType == REF_STYLE) nFlags = o3tl::narrowing<sal_uInt16>(rData.m_sPar2.toInt32());
else nSeqNo = o3tl::narrowing<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.reset(new SwGetRefField(pTyp, rData.m_sPar1, sReferenceLanguage, nSubType, nSeqNo, nFlags, nFormatId));
bExp = true;
break;
}
case SwFieldTypesEnum::DDE:
{
//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(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
if (nIndex>=0 && ++nIndex<sCmd.getLength())
{
sCmd = sCmd.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
}
SwDDEFieldType aType( rData.m_sPar1, sCmd, static_cast<SfxLinkUpdateMode>(nFormatId) );
SwDDEFieldType* pTyp = static_cast<SwDDEFieldType*>( pCurShell->InsertFieldType( aType ) );
pField.reset(new SwDDEField( pTyp ));
break;
}
case SwFieldTypesEnum::Macro:
{
SwMacroFieldType* pTyp =
static_cast<SwMacroFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::Macro));
pField.reset(new SwMacroField(pTyp, rData.m_sPar1, rData.m_sPar2));
break;
}
case SwFieldTypesEnum::Internet:
{
SwFormatINetFormat aFormat( rData.m_sPar1, m_sCurFrame );
return pCurShell->InsertURL( aFormat, rData.m_sPar2 );
}
case SwFieldTypesEnum::JumpEdit:
{
SwJumpEditFieldType* pTyp =
static_cast<SwJumpEditFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::JumpEdit));
pField.reset(new SwJumpEditField(pTyp, nFormatId, rData.m_sPar1, rData.m_sPar2));
break;
}
case SwFieldTypesEnum::DocumentInfo:
{
SwDocInfoFieldType* pTyp = static_cast<SwDocInfoFieldType*>( pCurShell->GetFieldType(
0, SwFieldIds::DocInfo ) );
pField.reset(new SwDocInfoField(pTyp, nSubType, rData.m_sPar1, nFormatId));
break;
}
case SwFieldTypesEnum::ExtendedUser:
{
SwExtUserFieldType* pTyp = static_cast<SwExtUserFieldType*>( pCurShell->GetFieldType(
0, SwFieldIds::ExtUser) );
pField.reset(new SwExtUserField(pTyp, nSubType, nFormatId));
break;
}
case SwFieldTypesEnum::Database:
{
#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
SwDBData aDBData;
OUString sPar1;
if (rData.m_sPar1.indexOf(DB_DELIM)<0)
{
aDBData = pCurShell->GetDBData();
sPar1 = rData.m_sPar1;
}
else
{
sal_Int32 nIdx{ 0 };
aDBData.sDataSource = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
aDBData.sCommand = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
aDBData.nCommandType = o3tl::toInt32(o3tl::getToken(rData.m_sPar1, 0, DB_DELIM, nIdx));
sPar1 = rData.m_sPar1.getToken(0, DB_DELIM, nIdx);
}
if(!aDBData.sDataSource.isEmpty() && pCurShell->GetDBData() != aDBData)
pCurShell->ChgDBData(aDBData);
SwDBFieldType* pTyp = static_cast<SwDBFieldType*>(pCurShell->InsertFieldType(
SwDBFieldType(pCurShell->GetDoc(), sPar1, aDBData) ) );
pField.reset(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 SwFieldTypesEnum::DatabaseSetNumber:
case SwFieldTypesEnum::DatabaseNumberSet:
case SwFieldTypesEnum::DatabaseNextSet:
case SwFieldTypesEnum::DatabaseName:
{
#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
SwDBData aDBData;
// extract DBName from rData.m_sPar1. Format: DBName.TableName.CommandType.ExpStrg
sal_Int32 nTablePos = rData.m_sPar1.indexOf(DB_DELIM);
sal_Int32 nExpPos = -1;
if (nTablePos>=0)
{
aDBData.sDataSource = rData.m_sPar1.copy(0, nTablePos++);
sal_Int32 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 = o3tl::toInt32(rData.m_sPar1.subView(nCmdTypePos, nExpPos++ - nCmdTypePos));
}
}
}
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 SwFieldTypesEnum::DatabaseName:
{
SwDBNameFieldType* pTyp =
static_cast<SwDBNameFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::DatabaseName));
pField.reset(new SwDBNameField(pTyp, aDBData));
break;
}
case SwFieldTypesEnum::DatabaseNextSet:
{
SwDBNextSetFieldType* pTyp = static_cast<SwDBNextSetFieldType*>(pCurShell->GetFieldType(
0, SwFieldIds::DbNextSet) );
pField.reset(new SwDBNextSetField(pTyp, sPar1, aDBData));
bExp = true;
break;
}
case SwFieldTypesEnum::DatabaseNumberSet:
{
SwDBNumSetFieldType* pTyp = static_cast<SwDBNumSetFieldType*>( pCurShell->GetFieldType(
0, SwFieldIds::DbNumSet) );
pField.reset(new SwDBNumSetField( pTyp, sPar1, rData.m_sPar2, aDBData));
bExp = true;
break;
}
case SwFieldTypesEnum::DatabaseSetNumber:
{
SwDBSetNumberFieldType* pTyp = static_cast<SwDBSetNumberFieldType*>(
pCurShell->GetFieldType(0, SwFieldIds::DbSetNumber) );
pField.reset(new SwDBSetNumberField( pTyp, aDBData, nFormatId));
bExp = true;
break;
}
default: break;
}
#endif
break;
}
case SwFieldTypesEnum::User:
{
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.reset(new SwUserField(pTyp, 0, nFormatId));
if (pField->GetSubType() != nSubType)
pField->SetSubType(nSubType);
bTable = true;
break;
}
case SwFieldTypesEnum::Input:
{
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)
{
std::unique_ptr<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 = std::move(pExpField);
}
else
return false;
}
else
{
SwInputFieldType* pTyp =
static_cast<SwInputFieldType*>( pCurShell->GetFieldType(0, SwFieldIds::Input) );
pField.reset(
new SwInputField( pTyp, rData.m_sPar1, rData.m_sPar2, nSubType|nsSwExtendedSubType::SUB_INVISIBLE, nFormatId));
}
break;
}
case SwFieldTypesEnum::Set:
{
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) ) );
std::unique_ptr<SwSetExpField> pExpField(new SwSetExpField( pTyp, rData.m_sPar2, nFormatId));
pExpField->SetSubType(nSubType);
pExpField->SetPar2(rData.m_sPar2);
bExp = true;
pField = std::move(pExpField);
break;
}
case SwFieldTypesEnum::Sequence:
{
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));
pField.reset(new SwSetExpField(pTyp, rData.m_sPar2, nFormatId));
bExp = true;
break;
}
case SwFieldTypesEnum::Get:
{
// 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.reset( new SwGetExpField(pTyp, rData.m_sPar1, pSetTyp->GetType(), nFormatId) );
pField->SetSubType(nSubType | pSetTyp->GetType());
bExp = true;
}
else
return false;
break;
}
case SwFieldTypesEnum::Formel:
{
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 });
}
SfxItemSetFixed<RES_BOXATR_FORMULA, RES_BOXATR_FORMULA> aBoxSet( pCurShell->GetAttrPool() );
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.reset( new SwGetExpField(pTyp, rData.m_sPar2, nsSwGetSetExpType::GSE_FORMULA, nFormatId) );
pField->SetSubType(nSubType);
bExp = true;
}
break;
}
case SwFieldTypesEnum::SetRefPage:
pField.reset( new SwRefPageSetField( static_cast<SwRefPageSetFieldType*>(
pCurShell->GetFieldType( 0, SwFieldIds::RefPageSet ) ),
static_cast<short>(rData.m_sPar2.toInt32()), 0 != nSubType ) );
bPageVar = true;
break;
case SwFieldTypesEnum::GetRefPage:
pField.reset( new SwRefPageGetField( static_cast<SwRefPageGetFieldType*>(
pCurShell->GetFieldType( 0, SwFieldIds::RefPageGet ) ), nFormatId ) );
bPageVar = true;
break;
case SwFieldTypesEnum::Dropdown :
{
pField.reset( 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, nIdx = 0; nToken < nTokenCount; nToken++)
pArray[nToken] = rData.m_sPar2.getToken(0, DB_DELIM, nIdx);
static_cast<SwDropDownField*>(pField.get())->SetItems(aEntries);
static_cast<SwDropDownField*>(pField.get())->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 SwFieldTypesEnum::ParagraphSignature:
pCurShell->SignParagraph();
return true;
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();
bool const isSuccess = pCurShell->InsertField2(*pField, rData.m_oAnnotationRange ? &*rData.m_oAnnotationRange : nullptr);
if (isSuccess)
{
if (SwFieldTypesEnum::Input == rData.m_nTypeId)
{
pCurShell->Push();
// start dialog, not before the field is inserted tdf#99529
pCurShell->Left(SwCursorSkipMode::Chars, false,
(INP_VAR == (nSubType & 0xff) || pCurShell->GetViewOptions()->IsFieldName()) ? 1 : 2,
false);
pCurShell->StartInputFieldDlg(pField.get(), false, true, rData.m_pParent);
pCurShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
}
if (bExp && m_bEvalExp)
{
pCurShell->UpdateExpFields(true);
}
if (bTable)
{
pCurShell->Left(SwCursorSkipMode::Chars, false, 1, false );
pCurShell->UpdateOneField(*pField);
pCurShell->Right(SwCursorSkipMode::Chars, false, 1, false );
}
else if (bPageVar)
{
static_cast<SwRefPageGetFieldType*>(pCurShell->GetFieldType(0, SwFieldIds::RefPageGet))->UpdateFields();
}
else if (SwFieldTypesEnum::GetRef == rData.m_nTypeId)
{
pField->GetTyp()->UpdateFields();
}
}
// delete temporary field
pField.reset();
pCurShell->EndAllAction();
return isSuccess;
}
// 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 SwFieldTypesEnum 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 SwFieldTypesEnum::DDE:
{
// DDE-Topics/-Items can have blanks in their names!
// That's not yet considered here!
sal_Int32 nIndex = 0;
sPar2 = sPar2.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex );
if (nIndex>=0 && ++nIndex<sPar2.getLength())
{
sPar2 = sPar2.replaceFirst(" ", OUStringChar(sfx2::cTokenSeparator), &nIndex);
}
break;
}
case SwFieldTypesEnum::Chapter:
{
sal_uInt16 nByte = o3tl::narrowing<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 SwFieldTypesEnum::Script:
static_cast<SwScriptField*>(pTmpField.get())->SetCodeURL(static_cast<bool>(nFormat));
break;
case SwFieldTypesEnum::NextPage:
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 SwFieldTypesEnum::PreviousPage:
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 SwFieldTypesEnum::PageNumber:
case SwFieldTypesEnum::GetRefPage:
if( nFormat + 2 == SVX_NUM_PAGEDESC )
nFormat = SVX_NUM_PAGEDESC;
break;
case SwFieldTypesEnum::GetRef:
{
bSetPar2 = false;
sal_Int16 nSubType = o3tl::narrowing<sal_uInt16>(rPar2.toInt32());
static_cast<SwGetRefField*>(pTmpField.get())->SetSubType( nSubType );
const sal_Int32 nPos = rPar2.indexOf( '|' );
if( nPos>=0 )
switch (nSubType) {
case REF_STYLE:
static_cast<SwGetRefField*>(pTmpField.get())->SetFlags( o3tl::narrowing<sal_uInt16>(o3tl::toInt32(rPar2.subView( nPos + 1 ))));
break;
default:
static_cast<SwGetRefField*>(pTmpField.get())->SetSeqNo( o3tl::narrowing<sal_uInt16>(o3tl::toInt32(rPar2.subView( nPos + 1 ))));
}
}
break;
case SwFieldTypesEnum::Dropdown:
{
sal_Int32 nTokenCount = comphelper::string::getTokenCount(sPar2, DB_DELIM);
Sequence<OUString> aEntries(nTokenCount);
OUString* pArray = aEntries.getArray();
for(sal_Int32 nToken = 0, nIdx = 0; nToken < nTokenCount; nToken++)
pArray[nToken] = sPar2.getToken(0, DB_DELIM, nIdx);
static_cast<SwDropDownField*>(pTmpField.get())->SetItems(aEntries);
static_cast<SwDropDownField*>(pTmpField.get())->SetName(rPar1);
bSetPar1 = bSetPar2 = false;
}
break;
case SwFieldTypesEnum::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);
rtl::Reference<SwAuthEntry> xTempEntry(new SwAuthEntry);
for( sal_Int32 i = 0, nIdx = 0; i < AUTH_FIELD_END; ++i )
xTempEntry->SetAuthorField( static_cast<ToxAuthorityField>(i),
rPar1.getToken( 0, TOX_STYLE_DELIMITER, nIdx ));
// If just the page number of the URL changed, then update the current field and not
// others.
bool bEquivalent = true;
for (int i = 0; i < AUTH_FIELD_END; ++i)
{
auto eField = static_cast<ToxAuthorityField>(i);
if (eField == AUTH_FIELD_URL)
{
if (SwTOXAuthority::GetSourceURL(xTempEntry->GetAuthorField(AUTH_FIELD_URL))
!= SwTOXAuthority::GetSourceURL(
pAuthorityField->GetFieldText(AUTH_FIELD_URL)))
{
bEquivalent = false;
break;
}
}
else
{
if (xTempEntry->GetAuthorField(eField) != pAuthorityField->GetFieldText(eField))
{
bEquivalent = false;
break;
}
}
}
if (bEquivalent)
{
break;
}
if( pAuthorityType->ChangeEntryContent( xTempEntry.get() ) )
{
pType->UpdateFields();
pSh->SetModified();
}
if( xTempEntry->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;
default: 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 == SwFieldTypesEnum::DDE ||
nTypeId == SwFieldTypesEnum::User ||
nTypeId == SwFieldTypesEnum::UserInput)
{
pType->UpdateFields();
pSh->SetModified();
}
else {
// mb: #32157
pSh->SwEditShell::UpdateOneField(*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 TranslateId 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 TranslateId & id : coFieldNms)
{
const OUString aTmp(SwResId(id));
SwFieldType::s_pFieldNames->push_back(MnemonicGenerator::EraseAllMnemonicChars( aTmp ));
}
}
bool SwFieldMgr::ChooseMacro(weld::Window* pDialogParent)
{
bool bRet = false;
// choose script dialog
OUString aScriptURL = SfxApplication::ChooseScript(pDialogParent);
// 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
const 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(SwFieldTypesEnum nTypeId, bool bIsText, SvNumberFormatter* pFormatter)
{
SvNumFormatType nDefFormat;
switch (nTypeId)
{
case SwFieldTypesEnum::Time:
case SwFieldTypesEnum::Date:
{
nDefFormat = (nTypeId == SwFieldTypesEnum::Date) ? 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())
{
const 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: */
↑ V614 Potentially null smart pointer 'pField' used.