Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  docufld.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <config_features.h>
#include <config_fuzzers.h>

#include <textapi.hxx>

#include <hintids.hxx>
#include <com/sun/star/frame/XModel.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/script/Converter.hpp>
#include <com/sun/star/text/PlaceholderType.hpp>
#include <com/sun/star/text/TemplateDisplayFormat.hpp>
#include <com/sun/star/text/PageNumberType.hpp>
#include <com/sun/star/text/FilenameDisplayFormat.hpp>
#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
#include <com/sun/star/document/XDocumentProperties.hpp>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/Duration.hpp>
#include <o3tl/any.hxx>
#include <o3tl/string_view.hxx>
#include <unotools/localedatawrapper.hxx>
#include <comphelper/processfactory.hxx>
#include <comphelper/string.hxx>
#include <tools/urlobj.hxx>
#include <svl/numformat.hxx>
#include <svl/urihelper.hxx>
#include <unotools/useroptions.hxx>
#include <unotools/syslocale.hxx>
#include <libxml/xmlstring.h>
#include <libxml/xmlwriter.h>

#include <tools/time.hxx>
#include <tools/datetime.hxx>

#include <com/sun/star/util/DateTime.hpp>

#include <swmodule.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/doctempl.hxx>
#include <fmtfld.hxx>
#include <txtfld.hxx>
#include <charfmt.hxx>
#include <docstat.hxx>
#include <pagedesc.hxx>
#include <fmtpdsc.hxx>
#include <doc.hxx>
#include <IDocumentFieldsAccess.hxx>
#include <IDocumentStatistics.hxx>
#include <IDocumentStylePoolAccess.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <cntfrm.hxx>
#include <pam.hxx>
#include <utility>
#include <viewsh.hxx>
#include <dbmgr.hxx>
#include <shellres.hxx>
#include <docufld.hxx>
#include <flddat.hxx>
#include <docfld.hxx>
#include <ndtxt.hxx>
#include <expfld.hxx>
#include <poolfmt.hxx>
#include <docsh.hxx>
#include <unofldmid.h>
#include <swunohelper.hxx>
#include <strings.hrc>

#include <editeng/outlobj.hxx>
#include <calbck.hxx>
#include <hints.hxx>

#define URL_DECODE  INetURLObject::DecodeMechanism::Unambiguous

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace nsSwDocInfoSubType;

SwPageNumberFieldType::SwPageNumberFieldType()
    : SwFieldType( SwFieldIds::PageNumber ),
    m_nNumberingType( SVX_NUM_ARABIC ),
    m_bVirtual( false )
{
}

OUString SwPageNumberFieldType::Expand( SvxNumType nFormat, short nOff,
         sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage,
         const OUString& rUserStr, LanguageType nLang ) const
{
    SvxNumType nTmpFormat = (SVX_NUM_PAGEDESC == nFormat) ? m_nNumberingType : nFormat;
    int const nTmp = nPageNumber + nOff;

    if (0 > nTmp || SVX_NUM_NUMBER_NONE == nTmpFormat || (!m_bVirtual && nTmp > nMaxPage))
        return OUString();

    if( SVX_NUM_CHAR_SPECIAL == nTmpFormat )
        return rUserStr;

    return FormatNumber( nTmp, nTmpFormat, nLang );
}

std::unique_ptr<SwFieldType> SwPageNumberFieldType::Copy() const
{
    std::unique_ptr<SwPageNumberFieldType> pTmp(new SwPageNumberFieldType());

    pTmp->m_nNumberingType = m_nNumberingType;
    pTmp->m_bVirtual  = m_bVirtual;

    return pTmp;
}

void SwPageNumberFieldType::ChangeExpansion( SwDoc* pDoc,
                                            bool bVirt,
                                            const SvxNumType* pNumFormat )
{
    if( pNumFormat )
        m_nNumberingType = *pNumFormat;

    m_bVirtual = false;
    if (!(bVirt && pDoc))
        return;

    // check the flag since the layout NEVER sets it back
    for (SwRootFrame* pRootFrame : pDoc->GetAllLayouts())
    {
        const SwPageFrame* pPageFrameIter = pRootFrame->GetLastPage();
        while (pPageFrameIter)
        {
            const SwContentFrame* pContentFrame = pPageFrameIter->FindFirstBodyContent();
            if (pContentFrame)
            {
                const SwFormatPageDesc& rFormatPageDesc = pContentFrame->GetPageDescItem();
                if ( rFormatPageDesc.GetNumOffset() && rFormatPageDesc.GetDefinedIn() )
                {
                    const SwContentNode* pNd = dynamic_cast<const SwContentNode*>( rFormatPageDesc.GetDefinedIn()  );
                    if( pNd )
                    {
                        if (SwIterator<SwFrame, SwContentNode, sw::IteratorMode::UnwrapMulti>(*pNd).First())
                        // sw_redlinehide: not sure if this should happen only if
                        // it's the first node, because that's where RES_PAGEDESC
                        // is effective?
                            m_bVirtual = true;
                    }
                    else ifdynamic_castconst SwFormat* >(rFormatPageDesc.GetDefinedIn()) !=  nullptr)
                    {
                        m_bVirtual = false;
                        sw::AutoFormatUsedHint aHint(m_bVirtual, pDoc->GetNodes());
                        rFormatPageDesc.GetDefinedIn()->CallSwClientNotify(aHint);
                        break;
                    }
                }
            }
            pPageFrameIter = static_cast<const SwPageFrame*>(pPageFrameIter->GetPrev());
        }
    }
}

SwPageNumberField::SwPageNumberField(SwPageNumberFieldType* pTyp,
          sal_uInt16 nSub, sal_uInt32 nFormat, short nOff,
          sal_uInt16 const nPageNumber, sal_uInt16 const nMaxPage)
    : SwField(pTyp, nFormat), m_nSubType(nSub), m_nOffset(nOff)
    , m_nPageNumber(nPageNumber)
    , m_nMaxPage(nMaxPage)
{
}

void SwPageNumberField::ChangeExpansion(sal_uInt16 const nPageNumber,
        sal_uInt16 const nMaxPage)
{
    m_nPageNumber = nPageNumber;
    m_nMaxPage = nMaxPage;
}

OUString SwPageNumberField::ExpandImpl(SwRootFrame const*constconst
{
    OUString sRet;
    SwPageNumberFieldType* pFieldType = static_cast<SwPageNumberFieldType*>(GetTyp());

    if( PG_NEXT == m_nSubType && 1 != m_nOffset )
    {
        sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), 1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
        if (!sRet.isEmpty())
        {
            sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
        }
    }
    else if( PG_PREV == m_nSubType && -1 != m_nOffset )
    {
        sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), -1, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
        if (!sRet.isEmpty())
        {
            sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
        }
    }
    else
        sRet = pFieldType->Expand(static_cast<SvxNumType>(GetFormat()), m_nOffset, m_nPageNumber, m_nMaxPage, m_sUserStr, GetLanguage());
    return sRet;
}

std::unique_ptr<SwField> SwPageNumberField::Copy() const
{
    std::unique_ptr<SwPageNumberField> pTmp(new SwPageNumberField(
                static_cast<SwPageNumberFieldType*>(GetTyp()), m_nSubType,
                GetFormat(), m_nOffset, m_nPageNumber, m_nMaxPage));
    pTmp->SetLanguage( GetLanguage() );
    pTmp->SetUserString( m_sUserStr );
    return std::unique_ptr<SwField>(pTmp.release());
}

OUString SwPageNumberField::GetPar2() const
{
    return OUString::number(m_nOffset);
}

void SwPageNumberField::SetPar2(const OUString& rStr)
{
    m_nOffset = static_cast<short>(rStr.toInt32());
}

sal_uInt16 SwPageNumberField::GetSubType() const
{
    return m_nSubType;
}

bool SwPageNumberField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch( nWhichId )
    {
    case FIELD_PROP_FORMAT:
        rAny <<= static_cast<sal_Int16>(GetFormat());
        break;
    case FIELD_PROP_USHORT1:
        rAny <<= m_nOffset;
        break;
    case FIELD_PROP_SUBTYPE:
        {
            text::PageNumberType eType;
            eType = text::PageNumberType_CURRENT;
            if(m_nSubType == PG_PREV)
                eType = text::PageNumberType_PREV;
            else if(m_nSubType == PG_NEXT)
                eType = text::PageNumberType_NEXT;
            rAny <<= eType;
        }
        break;
    case FIELD_PROP_PAR1:
        rAny <<= m_sUserStr;
        break;

    default:
        assert(false);
    }
    return true;
}

bool SwPageNumberField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    bool bRet = true;
    sal_Int16 nSet = 0;
    switch( nWhichId )
    {
    case FIELD_PROP_FORMAT:
        rAny >>= nSet;

        // TODO: where do the defines come from?
        if(nSet <= SVX_NUM_PAGEDESC )
            SetFormat(nSet);
        break;
    case FIELD_PROP_USHORT1:
        rAny >>= nSet;
        m_nOffset = nSet;
        break;
    case FIELD_PROP_SUBTYPE:
        switchstatic_cast<text::PageNumberType>(SWUnoHelper::GetEnumAsInt32( rAny )) )
        {
            case text::PageNumberType_CURRENT:
                m_nSubType = PG_RANDOM;
            break;
            case text::PageNumberType_PREV:
                m_nSubType = PG_PREV;
            break;
            case text::PageNumberType_NEXT:
                m_nSubType = PG_NEXT;
            break;
            default:
                bRet = false;
        }
        break;
    case FIELD_PROP_PAR1:
        rAny >>= m_sUserStr;
        break;

    default:
        assert(false);
    }
    return bRet;
}

SwAuthorFieldType::SwAuthorFieldType()
    : SwFieldType( SwFieldIds::Author )
{
}

OUString SwAuthorFieldType::Expand(sal_uLong nFormat)
{
    SwModule* mod = SwModule::get();
    SvtUserOptions&  rOpt = mod->GetUserOptions();
    if((nFormat & 0xff) == AF_NAME)
    {
        // Prefer the view's redline author name.
        // (set in SwXTextDocument::initializeForTiledRendering)
        std::size_t nAuthor = mod->GetRedlineAuthor();
        OUString sAuthor = mod->GetRedlineAuthor(nAuthor);
        if (sAuthor.isEmpty())
            return rOpt.GetFullName();

        return sAuthor;
    }

    return rOpt.GetID();
}

std::unique_ptr<SwFieldType> SwAuthorFieldType::Copy() const
{
    return std::make_unique<SwAuthorFieldType>();
}

SwAuthorField::SwAuthorField(SwAuthorFieldType* pTyp, sal_uInt32 nFormat)
    : SwField(pTyp, nFormat)
{
    m_aContent = SwAuthorFieldType::Expand(GetFormat());
}

OUString SwAuthorField::ExpandImpl(SwRootFrame const*constconst
{
    if (!IsFixed())
        const_cast<SwAuthorField*>(this)->m_aContent =
                    SwAuthorFieldType::Expand(GetFormat());

    return m_aContent;
}

std::unique_ptr<SwField> SwAuthorField::Copy() const
{
    std::unique_ptr<SwAuthorField> pTmp(new SwAuthorField( static_cast<SwAuthorFieldType*>(GetTyp()),
                                                GetFormat()));
    pTmp->SetExpansion(m_aContent);
    return std::unique_ptr<SwField>(pTmp.release());
}

bool SwAuthorField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch( nWhichId )
    {
    case FIELD_PROP_BOOL1:
        rAny <<= (GetFormat() & 0xff) == AF_NAME;
        break;

    case FIELD_PROP_BOOL2:
        rAny <<= IsFixed();
        break;

    case FIELD_PROP_PAR1:
        rAny <<= m_aContent;
        break;

    case FIELD_PROP_TITLE:
        break;

    default:
        assert(false);
    }
    return true;
}

bool SwAuthorField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    switch( nWhichId )
    {
    case FIELD_PROP_BOOL1:
        SetFormat( *o3tl::doAccess<bool>(rAny) ? AF_NAME : AF_SHORTCUT );
        break;

    case FIELD_PROP_BOOL2:
        if( *o3tl::doAccess<bool>(rAny) )
            SetFormat( GetFormat() | AF_FIXED);
        else
            SetFormat( GetFormat() & ~AF_FIXED);
        break;

    case FIELD_PROP_PAR1:
        rAny >>= m_aContent;
        break;

    case FIELD_PROP_TITLE:
        break;

    default:
        assert(false);
    }
    return true;
}

SwFileNameFieldType::SwFileNameFieldType(SwDoc& rDocument)
    : SwFieldType( SwFieldIds::Filename )
    , m_rDoc(rDocument)
{
}

OUString SwFileNameFieldType::Expand(sal_uLong nFormat) const
{
    OUString aRet;
    const SwDocShell* pDShell = m_rDoc.GetDocShell();
    if( pDShell && pDShell->HasName() )
    {
        const INetURLObject& rURLObj = pDShell->GetMedium()->GetURLObject();
        switch( nFormat & ~FF_FIXED )
        {
            case FF_PATH:
                {
                    if( INetProtocol::File == rURLObj.GetProtocol() )
                    {
                        INetURLObject aTemp(rURLObj);
                        aTemp.removeSegment();
                        // last slash should belong to the pathname
                        aRet = aTemp.PathToFileName();
                    }
                    else
                    {
                        aRet = URIHelper::removePassword(
                                    rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
                                    INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
                        const sal_Int32 nPos = aRet.indexOf(rURLObj.GetLastName( URL_DECODE ));
                        if (nPos>=0)
                        {
                            aRet = aRet.copy(0, nPos);
                        }
                    }
                }
                break;

            case FF_NAME:
                aRet = rURLObj.GetLastName( INetURLObject::DecodeMechanism::WithCharset );
                break;

            case FF_NAME_NOEXT:
                aRet = rURLObj.GetBase();
                break;

            default:
                if( INetProtocol::File == rURLObj.GetProtocol() )
                    aRet = rURLObj.GetFull();
                else
                    aRet = URIHelper::removePassword(
                                    rURLObj.GetMainURL( INetURLObject::DecodeMechanism::NONE ),
                                    INetURLObject::EncodeMechanism::WasEncoded, URL_DECODE );
        }
    }
    return aRet;
}

std::unique_ptr<SwFieldType> SwFileNameFieldType::Copy() const
{
    return std::make_unique<SwFileNameFieldType>(m_rDoc);
}

SwFileNameField::SwFileNameField(SwFileNameFieldType* pTyp, sal_uInt32 nFormat)
    : SwField(pTyp, nFormat)
{
    m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());
}

OUString SwFileNameField::ExpandImpl(SwRootFrame const*constconst
{
    if (!IsFixed())
        const_cast<SwFileNameField*>(this)->m_aContent = static_cast<SwFileNameFieldType*>(GetTyp())->Expand(GetFormat());

    return m_aContent;
}

std::unique_ptr<SwField> SwFileNameField::Copy() const
{
    std::unique_ptr<SwFileNameField> pTmp(
        new SwFileNameField(static_cast<SwFileNameFieldType*>(GetTyp()), GetFormat()));
    pTmp->SetExpansion(m_aContent);

    return std::unique_ptr<SwField>(pTmp.release());
}

bool SwFileNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch( nWhichId )
    {
    case FIELD_PROP_FORMAT:
        {
            sal_Int16 nRet;
            switch( GetFormat() &(~FF_FIXED) )
            {
                case FF_PATH:
                    nRet = text::FilenameDisplayFormat::PATH;
                break;
                case FF_NAME_NOEXT:
                    nRet = text::FilenameDisplayFormat::NAME;
                break;
                case FF_NAME:
                    nRet = text::FilenameDisplayFormat::NAME_AND_EXT;
                break;
                default:    nRet = text::FilenameDisplayFormat::FULL;
            }
            rAny <<= nRet;
        }
        break;

    case FIELD_PROP_BOOL2:
        rAny <<= IsFixed();
        break;

    case FIELD_PROP_PAR3:
        rAny <<= m_aContent;
        break;

    default:
        assert(false);
    }
    return true;
}

bool SwFileNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    switch( nWhichId )
    {
    case FIELD_PROP_FORMAT:
        {
            //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
            //              called with a int32 value! But normally we need
            //              here only a int16
            sal_Int32 nType = 0;
            rAny >>= nType;
            bool bFixed = IsFixed();
            switch( nType )
            {
                case text::FilenameDisplayFormat::PATH:
                    nType = FF_PATH;
                break;
                case text::FilenameDisplayFormat::NAME:
                    nType = FF_NAME_NOEXT;
                break;
                case text::FilenameDisplayFormat::NAME_AND_EXT:
                    nType = FF_NAME;
                break;
                default:    nType = FF_PATHNAME;
            }
            if(bFixed)
                nType |= FF_FIXED;
            SetFormat(nType);
        }
        break;

    case FIELD_PROP_BOOL2:
        if( *o3tl::doAccess<bool>(rAny) )
            SetFormat( GetFormat() | FF_FIXED);
        else
            SetFormat( GetFormat() & ~FF_FIXED);
        break;

    case FIELD_PROP_PAR3:
        rAny >>= m_aContent;
        break;

    default:
        assert(false);
    }
    return true;
}

SwTemplNameFieldType::SwTemplNameFieldType(SwDoc& rDocument)
    : SwFieldType( SwFieldIds::TemplateName )
    , m_rDoc(rDocument)
{
}

OUString SwTemplNameFieldType::Expand(sal_uLong nFormat) const
{
    OSL_ENSURE( nFormat < FF_END, "Expand: no valid Format!" );

    OUString aRet;
    SwDocShell *pDocShell(m_rDoc.GetDocShell());
    OSL_ENSURE(pDocShell, "no SwDocShell");
    if (pDocShell) {
        uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
            pDocShell->GetModel(), uno::UNO_QUERY_THROW);
        uno::Reference<document::XDocumentProperties> xDocProps(
            xDPS->getDocumentProperties());
        OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");

        if( FF_UI_NAME == nFormat )
            aRet = xDocProps->getTemplateName();
        else if( !xDocProps->getTemplateURL().isEmpty() )
        {
            if( FF_UI_RANGE == nFormat )
            {
                // for getting region names!
                SfxDocumentTemplates aFac;
                OUString sTmp;
                OUString sRegion;
                aFac.GetLogicNames( xDocProps->getTemplateURL(), sRegion, sTmp );
                aRet = sRegion;
            }
            else
            {
                INetURLObject aPathName( xDocProps->getTemplateURL() );
                if( FF_NAME == nFormat )
                    aRet = aPathName.GetLastName(URL_DECODE);
                else if( FF_NAME_NOEXT == nFormat )
                    aRet = aPathName.GetBase();
                else
                {
                    if( FF_PATH == nFormat )
                    {
                        aPathName.removeSegment();
                        aRet = aPathName.GetFull();
                    }
                    else
                        aRet = aPathName.GetFull();
                }
            }
        }
    }
    return aRet;
}

std::unique_ptr<SwFieldType> SwTemplNameFieldType::Copy() const
{
    return std::make_unique<SwTemplNameFieldType>(m_rDoc);
}

SwTemplNameField::SwTemplNameField(SwTemplNameFieldType* pTyp, sal_uInt32 nFormat)
    : SwField(pTyp, nFormat)
{}

OUString SwTemplNameField::ExpandImpl(SwRootFrame const*constconst
{
    return static_cast<SwTemplNameFieldType*>(GetTyp())->Expand(GetFormat());
}

std::unique_ptr<SwField> SwTemplNameField::Copy() const
{
    return std::make_unique<SwTemplNameField>(static_cast<SwTemplNameFieldType*>(GetTyp()), GetFormat());
}

bool SwTemplNameField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch ( nWhichId )
    {
    case FIELD_PROP_FORMAT:
        {
            sal_Int16 nRet;
            switch( GetFormat() )
            {
                case FF_PATH:       nRet = text::FilenameDisplayFormat::PATH; break;
                case FF_NAME_NOEXT: nRet = text::FilenameDisplayFormat::NAME; break;
                case FF_NAME:       nRet = text::FilenameDisplayFormat::NAME_AND_EXT; break;
                case FF_UI_RANGE:   nRet = text::TemplateDisplayFormat::AREA; break;
                case FF_UI_NAME:    nRet = text::TemplateDisplayFormat::TITLE;  break;
                default:    nRet = text::FilenameDisplayFormat::FULL;

            }
            rAny <<= nRet;
        }
        break;

    default:
        assert(false);
    }
    return true;
}

bool SwTemplNameField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    switch ( nWhichId )
    {
    case FIELD_PROP_FORMAT:
        {
            //JP 24.10.2001: int32 because in UnoField.cxx a putvalue is
            //              called with a int32 value! But normally we need
            //              here only a int16
            sal_Int32 nType = 0;
            rAny >>= nType;
            switch( nType )
            {
            case text::FilenameDisplayFormat::PATH:
                SetFormat(FF_PATH);
            break;
            case text::FilenameDisplayFormat::NAME:
                SetFormat(FF_NAME_NOEXT);
            break;
            case text::FilenameDisplayFormat::NAME_AND_EXT:
                SetFormat(FF_NAME);
            break;
            case text::TemplateDisplayFormat::AREA  :
                SetFormat(FF_UI_RANGE);
            break;
            case text::TemplateDisplayFormat::TITLE  :
                SetFormat(FF_UI_NAME);
            break;
            default:    SetFormat(FF_PATHNAME);
            }
        }
        break;

    default:
        assert(false);
    }
    return true;
}

SwDocStatFieldType::SwDocStatFieldType(SwDoc& rDocument)
    : SwFieldType(SwFieldIds::DocStat)
    , m_rDoc(rDocument)
    , m_nNumberingType(SVX_NUM_ARABIC)
{
}

OUString SwDocStatFieldType::Expand(sal_uInt16 nSubType,
    SvxNumType nFormat, sal_uInt16 nVirtPageCount) const
{
    sal_uInt32 nVal = 0;
    const SwDocStat& rDStat = m_rDoc.getIDocumentStatistics().GetDocStat();
    switch( nSubType )
    {
        case DS_TBL:  nVal = rDStat.nTable;   break;
        case DS_GRF:  nVal = rDStat.nGrf;   break;
        case DS_OLE:  nVal = rDStat.nOLE;   break;
        case DS_PARA: nVal = rDStat.nPara;  break;
        case DS_WORD: nVal = rDStat.nWord;  break;
        case DS_CHAR: nVal = rDStat.nChar;  break;
        case DS_PAGE:
            if( m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout() )
                const_cast<SwDocStat &>(rDStat).nPage = m_rDoc.getIDocumentLayoutAccess().GetCurrentLayout()->GetPageNum();
            nVal = rDStat.nPage;
            if( SVX_NUM_PAGEDESC == nFormat )
                nFormat = m_nNumberingType;
            break;
        case DS_PAGE_RANGE:
            nVal = nVirtPageCount;
            if( SVX_NUM_PAGEDESC == nFormat )
                nFormat = m_nNumberingType;
            break;
        default:
            OSL_FAIL( "SwDocStatFieldType::Expand: unknown SubType" );
    }

    if( nVal <= SHRT_MAX )
        return FormatNumber( nVal, nFormat );

    return OUString::number( nVal );
}

std::unique_ptr<SwFieldType> SwDocStatFieldType::Copy() const
{
    return std::make_unique<SwDocStatFieldType>(m_rDoc);
}
void SwDocStatFieldType::UpdateRangeFields(SwRootFrame const*const pLayout)
{
    std::vector<SwFormatField*> vFields;
    GatherFields(vFields);
    for(auto pFormatField: vFields)
    {
        SwDocStatField* pDocStatField = static_cast<SwDocStatField*>(pFormatField->GetField());
        if (pDocStatField->GetSubType() == DS_PAGE_RANGE)
        {
            SwTextField* pTField = pFormatField->GetTextField();
            const SwTextNode& rTextNd = pTField->GetTextNode();

            // Always the first! (in Tab-Headline, header/footer )
            Point aPt;
            std::pair<Point, boolconst tmp(aPt, false);
            const SwContentFrame *const pFrame = rTextNd.getLayoutFrame(
                pLayout, nullptr, &tmp);

            if (pFrame &&
                pFrame->IsInDocBody() &&
                pFrame->FindPageFrame())
            {
                pDocStatField->ChangeExpansion(pFrame, pFrame->GetVirtPageCount());
            }
        }
    }
}
/**
 * @param pTyp
 * @param nSub SubType
 * @param nFormat
 */

SwDocStatField::SwDocStatField(SwDocStatFieldType* pTyp, sal_uInt16 nSub,
    sal_uInt32 nFormat, sal_uInt16 nVirtPageCount)
    : SwField(pTyp, nFormat),
    m_nSubType(nSub),
    m_nVirtPageCount(nVirtPageCount)
{
}

OUString SwDocStatField::ExpandImpl(SwRootFrame const*constconst
{
    return static_cast<SwDocStatFieldType*>(GetTyp())
        ->Expand(m_nSubType, static_cast<SvxNumType>(GetFormat()), m_nVirtPageCount);
}

std::unique_ptr<SwField> SwDocStatField::Copy() const
{
    return std::make_unique<SwDocStatField>(
        static_cast<SwDocStatFieldType*>(GetTyp()), m_nSubType, GetFormat(), m_nVirtPageCount );
}

sal_uInt16 SwDocStatField::GetSubType() const
{
    return m_nSubType;
}

void SwDocStatField::SetSubType(sal_uInt16 nSub)
{
    m_nSubType = nSub;
}

void SwDocStatField::ChangeExpansion(const SwFrame* pFrame, sal_uInt16 nVirtPageCount)
{
    if( DS_PAGE == m_nSubType && SVX_NUM_PAGEDESC == GetFormat() )
        static_cast<SwDocStatFieldType*>(GetTyp())->SetNumFormat(
                pFrame->FindPageFrame()->GetPageDesc()->GetNumType().GetNumberingType() );
    else if (nVirtPageCount && DS_PAGE_RANGE == m_nSubType)
        m_nVirtPageCount = nVirtPageCount;
}

bool SwDocStatField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch ( nWhichId )
    {
    case FIELD_PROP_USHORT2:
        rAny <<= static_cast<sal_Int16>(GetFormat());
        break;
    case FIELD_PROP_USHORT1:
        rAny <<= static_cast<sal_Int32>(m_nVirtPageCount);
        break;

    default:
        assert(false);
    }
    return true;
}

bool SwDocStatField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    bool bRet = false;
    switch ( nWhichId )
    {
    case FIELD_PROP_USHORT2:
        {
            sal_Int16 nSet = 0;
            rAny >>= nSet;
            if(nSet <= SVX_NUM_CHARS_LOWER_LETTER_N &&
                nSet != SVX_NUM_CHAR_SPECIAL &&
                    nSet != SVX_NUM_BITMAP)
            {
                SetFormat(nSet);
                bRet = true;
            }
        }
        break;
    case FIELD_PROP_USHORT1:
        {
            sal_Int32 nSet = 0;
            rAny >>= nSet;
            if (nSet >= 0 && nSet < USHRT_MAX)
            {
                m_nVirtPageCount = static_cast<sal_uInt16>(nSet);
                bRet = true;
            }
        }
        break;

    default:
        assert(false);
    }
    return bRet;
}

// Document info field type

SwDocInfoFieldType::SwDocInfoFieldType(SwDoc* pDc)
    : SwValueFieldType( pDc, SwFieldIds::DocInfo )
{
}

std::unique_ptr<SwFieldType> SwDocInfoFieldType::Copy() const
{
    return std::make_unique<SwDocInfoFieldType>(GetDoc());
}

static void lcl_GetLocalDataWrapper( LanguageType nLang,
                              const LocaleDataWrapper **ppAppLocalData,
                              const LocaleDataWrapper **ppLocalData )
{
    SvtSysLocale aLocale;
    *ppAppLocalData = &aLocale.GetLocaleData();
    *ppLocalData = *ppAppLocalData;
    if( nLang != (*ppLocalData)->getLanguageTag().getLanguageType() )
        *ppLocalData = new LocaleDataWrapper(LanguageTag( nLang ));
}

OUString SwDocInfoFieldType::Expand( sal_uInt16 nSub, sal_uInt32 nFormat,
                                    LanguageType nLang, const OUString& rName ) const
{
    const LocaleDataWrapper *pAppLocalData = nullptr, *pLocalData = nullptr;
    SwDocShell *pDocShell(GetDoc()->GetDocShell());
    OSL_ENSURE(pDocShell, "no SwDocShell");
    if (!pDocShell) { return OUString(); }

    uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
        pDocShell->GetModel(), uno::UNO_QUERY_THROW);
    uno::Reference<document::XDocumentProperties> xDocProps(
        xDPS->getDocumentProperties());
    OSL_ENSURE(xDocProps.is(), "Doc has no DocumentProperties");

    sal_uInt16 nExtSub = nSub & 0xff00;
    nSub &= 0xff;   // do not consider extended SubTypes

    OUString aStr;
    switch(nSub)
    {
    case DI_TITLE:  aStr = xDocProps->getTitle();       break;
    case DI_SUBJECT:aStr = xDocProps->getSubject();     break;
    case DI_KEYS:   aStr = ::comphelper::string::convertCommaSeparated(
                                xDocProps->getKeywords());
                    break;
    case DI_COMMENT:aStr = xDocProps->getDescription(); break;
    case DI_DOCNO:  aStr = OUString::number(
                                        xDocProps->getEditingCycles() );
                    break;
    case DI_EDIT:
        if ( !nFormat )
        {
            lcl_GetLocalDataWrapper( nLang, &pAppLocalData, &pLocalData );
            sal_Int32 dur = xDocProps->getEditingDuration();
            // If Seconds > 0 then bSec should be TRUE otherwise Seconds
            // information will be lost if file has EditTime in Seconds format.
            aStr = pLocalData->getTime( tools::Time(dur/3600, (dur%3600)/60, dur%60),
                                        dur%60 > 0);
        }
        else
        {
            double fVal = xDocProps->getEditingDuration() / double(tools::Time::secondPerDay);
            aStr = ExpandValue(fVal, nFormat, nLang);
        }
        break;
    case DI_CUSTOM:
        {
            OUString sVal;
            try
            {
                uno::Any aAny;
                uno::Reference < beans::XPropertySet > xSet(
                    xDocProps->getUserDefinedProperties(),
                    uno::UNO_QUERY_THROW);
                aAny = xSet->getPropertyValue( rName );

                uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
                uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
                aNew >>= sVal;
            }
            catch (uno::Exception&) {}
            return sVal;
        }

    default:
        {
            OUString aName( xDocProps->getAuthor() );
            util::DateTime uDT( xDocProps->getCreationDate() );
            DateTime aDate(uDT);
            if( nSub == DI_CREATE )
                ;       // that's it !!
            else if( nSub == DI_CHANGE )
            {
                aName = xDocProps->getModifiedBy();
                uDT = xDocProps->getModificationDate();
                aDate = DateTime(uDT);
            }
            else if( nSub == DI_PRINT )
            {
                aName = xDocProps->getPrintedBy();
                if ( !std::getenv("STABLE_FIELDS_HACK") )
                {
                    uDT = xDocProps->getPrintDate();
                    aDate = DateTime(uDT);
                }
            }
            else
                break;

            if (aDate.IsValidAndGregorian())
            {
                switch (nExtSub & ~DI_SUB_FIXED)
                {
                case DI_SUB_AUTHOR:
                    aStr = aName;
                    break;

                case DI_SUB_TIME:
                    if (!nFormat)
                    {
                        lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
                                                        &pLocalData );
                        aStr = pLocalData->getTime( aDate,
                                                    false);
                    }
                    else
                    {
                        // start the number formatter
                        double fVal = SwDateTimeField::GetDateTime( *GetDoc(),
                                                    aDate);
                        aStr = ExpandValue(fVal, nFormat, nLang);
                    }
                    break;

                case DI_SUB_DATE:
                    if (!nFormat)
                    {
                        lcl_GetLocalDataWrapper( nLang, &pAppLocalData,
                                                 &pLocalData );
                        aStr = pLocalData->getDate( aDate );
                    }
                    else
                    {
                        // start the number formatter
                        double fVal = SwDateTimeField::GetDateTime( *GetDoc(),
                                                    aDate);
                        aStr = ExpandValue(fVal, nFormat, nLang);
                    }
                    break;
                }
            }
        }
        break;
    }

    if( pAppLocalData != pLocalData )
        delete pLocalData;

    return aStr;
}

// document info field

SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, sal_uInt32 nFormat) :
    SwValueField(pTyp, nFormat), m_nSubType(nSub)
{
    m_aName = rName;
    m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, nFormat, GetLanguage(), m_aName);
}

SwDocInfoField::SwDocInfoField(SwDocInfoFieldType* pTyp, sal_uInt16 nSub, const OUString& rName, const OUString& rValue, sal_uInt32 nFormat) :
    SwValueField(pTyp, nFormat), m_nSubType(nSub)
{
    m_aName = rName;
    m_aContent = rValue;
}

template <class T> static double lcl_TimeToDays(const T& rTime)
{
    constexpr double fNanoSecondsPerDay = tools::Time::nanoSecPerDay;
    return (  (rTime.Hours   * tools::Time::nanoSecPerHour)
            + (rTime.Minutes * tools::Time::nanoSecPerMinute)
            + (rTime.Seconds * tools::Time::nanoSecPerSec)
            + (rTime.NanoSeconds))
        / fNanoSecondsPerDay;
}

template<class D> static double lcl_DateToDays(const D& rDate, const SwDocShell* pDocShell)
{
    const SvNumberFormatter* pFormatter = pDocShell->GetDoc()->GetNumberFormatter();
    sal_Int64 nDate = Date::DateToDays(rDate.Day, rDate.Month, rDate.Year);
    sal_Int64 nNullDate = pFormatter->GetNullDate().GetAsNormalizedDays();
    return double( nDate - nNullDate );
}

OUString SwDocInfoField::ExpandImpl(SwRootFrame const*constconst
{
    // if the field is "fixed" we don't update it from the property
    if (!IsFixed())
    {
        if ( ( m_nSubType & 0xFF ) == DI_CUSTOM )
        {
            // custom properties currently need special treatment
            // We don't have a secure way to detect "real" custom properties in Word import of text
            // fields, so we treat *every* unknown property as a custom property, even the "built-in"
            // section in Word's document summary information stream as these properties have not been
            // inserted when the document summary information was imported, we do it here.
            // This approach is still a lot better than the old one to import such fields as
            // "user fields" and simple text
            SwDocShell* pDocShell = GetDoc()->GetDocShell();
            if( !pDocShell )
                return m_aContent;
            try
            {
                uno::Reference<document::XDocumentPropertiesSupplier> xDPS( pDocShell->GetModel(), uno::UNO_QUERY_THROW);
                uno::Reference<document::XDocumentProperties> xDocProps( xDPS->getDocumentProperties());
                uno::Reference < beans::XPropertySet > xSet( xDocProps->getUserDefinedProperties(), uno::UNO_QUERY_THROW);
                uno::Reference < beans::XPropertySetInfo > xSetInfo = xSet->getPropertySetInfo();

                uno::Any aAny;
                if( xSetInfo->hasPropertyByName( m_aName ) )
                    aAny = xSet->getPropertyValue( m_aName );
                if (aAny.hasValue())
                {
                    // "void" type means that the property has not been inserted until now
                    OUString sVal;
                    if (util::Date aDate; aAny >>= aDate)
                    {
                        sVal = ExpandValue(lcl_DateToDays(aDate, pDocShell), GetFormat(), GetLanguage());
                    }
                    else if (util::DateTime aDateTime; aAny >>= aDateTime)
                    {
                        double fDateTime = lcl_TimeToDays(aDateTime) + lcl_DateToDays(aDateTime, pDocShell);
                        sVal = ExpandValue( fDateTime, GetFormat(), GetLanguage());
                    }
                    else if (util::Duration aDuration; aAny >>= aDuration)
                    {
                        sVal = OUStringChar(aDuration.Negative ? '-' : '+')
                             + SwViewShell::GetShellRes()->sDurationFormat;
                        sVal = sVal.replaceFirst("%1", OUString::number( aDuration.Years  ) );
                        sVal = sVal.replaceFirst("%2", OUString::number( aDuration.Months ) );
                        sVal = sVal.replaceFirst("%3", OUString::number( aDuration.Days   ) );
                        sVal = sVal.replaceFirst("%4", OUString::number( aDuration.Hours  ) );
                        sVal = sVal.replaceFirst("%5", OUString::number( aDuration.Minutes) );
                        sVal = sVal.replaceFirst("%6", OUString::number( aDuration.Seconds) );
                    }
                    else
                    {
                        uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(comphelper::getProcessComponentContext()) );
                        uno::Any aNew = xConverter->convertToSimpleType( aAny, uno::TypeClass_STRING );
                        aNew >>= sVal;
                    }
                    const_cast<SwDocInfoField*>(this)->m_aContent = sVal;
                }
            }
            catch (uno::Exception&) {}
        }
        else
            const_cast<SwDocInfoField*>(this)->m_aContent = static_cast<SwDocInfoFieldType*>(GetTyp())->Expand(m_nSubType, GetFormat(), GetLanguage(), m_aName);
    }

    return m_aContent;
}

OUString SwDocInfoField::GetFieldName() const
{
    OUString aStr(SwFieldType::GetTypeStr(GetTypeId()) + ":");

    sal_uInt16 const nSub = m_nSubType & 0xff;

    switch (nSub)
    {
        case DI_CUSTOM:
            aStr += m_aName;
            break;

        default:
            aStr += SwViewShell::GetShellRes()
                     ->aDocInfoLst[ nSub - DI_SUBTYPE_BEGIN ];
            break;
    }
    if (IsFixed())
    {
        aStr += " " + SwViewShell::GetShellRes()->aFixedStr;
    }
    return aStr;
}

std::unique_ptr<SwField> SwDocInfoField::Copy() const
{
    std::unique_ptr<SwDocInfoField> pField(new SwDocInfoField(static_cast<SwDocInfoFieldType*>(GetTyp()), m_nSubType, m_aName, GetFormat()));
    pField->SetAutomaticLanguage(IsAutomaticLanguage());
    pField->m_aContent = m_aContent;

    return std::unique_ptr<SwField>(pField.release());
}

sal_uInt16 SwDocInfoField::GetSubType() const
{
    return m_nSubType;
}

void SwDocInfoField::SetSubType(sal_uInt16 nSub)
{
    m_nSubType = nSub;
}

void SwDocInfoField::SetLanguage(LanguageType nLng)
{
    if (!GetFormat())
        SwField::SetLanguage(nLng);
    else
        SwValueField::SetLanguage(nLng);
}

bool SwDocInfoField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch( nWhichId )
    {
    case FIELD_PROP_PAR1:
        rAny <<= m_aContent;
        break;

    case FIELD_PROP_PAR4:
        rAny <<= m_aName;
        break;

    case FIELD_PROP_USHORT1:
        rAny  <<= static_cast<sal_Int16>(m_aContent.toInt32());
        break;

    case FIELD_PROP_BOOL1:
        rAny <<= 0 != (m_nSubType & DI_SUB_FIXED);
        break;

    case FIELD_PROP_FORMAT:
        rAny  <<= static_cast<sal_Int32>(GetFormat());
        break;

    case FIELD_PROP_DOUBLE:
        {
            double fVal = GetValue();
            rAny <<= fVal;
        }
        break;
    case FIELD_PROP_PAR3:
        rAny <<= ExpandImpl(nullptr);
        break;
    case FIELD_PROP_BOOL2:
        {
            sal_uInt16 nExtSub = (m_nSubType & 0xff00) & ~DI_SUB_FIXED;
            rAny <<= nExtSub == DI_SUB_DATE;
        }
        break;
    default:
        return SwField::QueryValue(rAny, nWhichId);
    }
    return true;
}

bool SwDocInfoField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    sal_Int32 nValue = 0;
    switch( nWhichId )
    {
    case FIELD_PROP_PAR1:
        if( m_nSubType & DI_SUB_FIXED )
            rAny >>= m_aContent;
        break;

    case FIELD_PROP_USHORT1:
        if( m_nSubType & DI_SUB_FIXED )
        {
            rAny >>= nValue;
            m_aContent = OUString::number(nValue);
        }
        break;

    case FIELD_PROP_BOOL1:
        if(*o3tl::doAccess<bool>(rAny))
            m_nSubType |= DI_SUB_FIXED;
        else
            m_nSubType &= ~DI_SUB_FIXED;
        break;
    case FIELD_PROP_FORMAT:
        {
            rAny >>= nValue;
            if( nValue >= 0)
                SetFormat(nValue);
        }
        break;

    case FIELD_PROP_PAR3:
        rAny >>= m_aContent;
        break;
    case FIELD_PROP_BOOL2:
        m_nSubType &= 0xf0ff;
        if(*o3tl::doAccess<bool>(rAny))
            m_nSubType |= DI_SUB_DATE;
        else
            m_nSubType |= DI_SUB_TIME;
        break;
    default:
        return SwField::PutValue(rAny, nWhichId);
    }
    return true;
}

SwHiddenTextFieldType::SwHiddenTextFieldType( bool bSetHidden )
    : SwFieldType( SwFieldIds::HiddenText ), m_bHidden( bSetHidden )
{
}

std::unique_ptr<SwFieldType> SwHiddenTextFieldType::Copy() const
{
    return std::make_unique<SwHiddenTextFieldType>( m_bHidden );
}

void SwHiddenTextFieldType::SetHiddenFlag( bool bSetHidden )
{
    if( m_bHidden != bSetHidden )
    {
        m_bHidden = bSetHidden;
        UpdateFields();       // notify all HiddenTexts
    }
}

SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
                                    bool    bConditional,
                                    OUString aCond,
                                    const OUString& rStr,
                                    bool    bHidden,
                                    SwFieldTypesEnum  nSub) :
    SwField( pFieldType ), m_aCond(std::move(aCond)), m_nSubType(nSub),
    m_bCanToggle(bConditional), m_bIsHidden(bHidden), m_bValid(false)
{
    if(m_nSubType == SwFieldTypesEnum::ConditionalText)
    {
        sal_Int32 nPos = 0;
        m_aTRUEText = rStr.getToken(0, '|', nPos);

        if(nPos != -1)
        {
            m_aFALSEText = rStr.getToken(0, '|', nPos);
            if(nPos != -1)
            {
                m_aContent = rStr.getToken(0, '|', nPos);
                m_bValid = true;
            }
        }
    }
    else
        m_aTRUEText = rStr;
}

SwHiddenTextField::SwHiddenTextField( SwHiddenTextFieldType* pFieldType,
                                    OUString aCond,
                                    OUString aTrue,
                                    OUString aFalse,
                                    SwFieldTypesEnum nSub)
    : SwField( pFieldType ), m_aTRUEText(std::move(aTrue)), m_aFALSEText(std::move(aFalse)), m_aCond(std::move(aCond)), m_nSubType(nSub),
      m_bIsHidden(true), m_bValid(false)
{
    m_bCanToggle = !m_aCond.isEmpty();
}

OUString SwHiddenTextField::ExpandImpl(SwRootFrame const*constconst
{
    // Type: !Hidden  -> show always
    //        Hide    -> evaluate condition

    if( SwFieldTypesEnum::ConditionalText == m_nSubType )
    {
        if( m_bValid )
            return m_aContent;

        if( m_bCanToggle && !m_bIsHidden )
            return m_aTRUEText;
    }
    else if( !static_cast<SwHiddenTextFieldType*>(GetTyp())->GetHiddenFlag() ||
        ( m_bCanToggle && m_bIsHidden ))
        return m_aTRUEText;

    return m_aFALSEText;
}

/// get current field value and cache it
void SwHiddenTextField::Evaluate(SwDoc& rDoc)
{
    if( SwFieldTypesEnum::ConditionalText != m_nSubType )
        return;

#if !HAVE_FEATURE_DBCONNECTIVITY || ENABLE_FUZZERS
    (void) rDoc;
#else
    SwDBManager* pMgr = rDoc.GetDBManager();
#endif
    m_bValid = false;
    OUString sTmpName = (m_bCanToggle && !m_bIsHidden) ? m_aTRUEText : m_aFALSEText;

    // Database expressions need to be different from normal text. Therefore, normal text is set
    // in quotes. If the latter exist they will be removed. If not, check if potential DB name.
    // Only if there are two or more dots and no quotes, we assume a database.
    if (sTmpName.getLength()>1 &&
        sTmpName.startsWith("\"") &&
        sTmpName.endsWith("\""))
    {
        m_aContent = sTmpName.copy(1, sTmpName.getLength() - 2);
        m_bValid = true;
    }
    else if(sTmpName.indexOf('\"')<0 &&
        comphelper::string::getTokenCount(sTmpName, '.') > 2)
    {
        sTmpName = ::ReplacePoint(sTmpName);
        if(sTmpName.startsWith("[") && sTmpName.endsWith("]"))
        {   // remove brackets
            sTmpName = sTmpName.copy(1, sTmpName.getLength() - 2);
        }
#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
        if( pMgr)
        {
            sal_Int32 nIdx{ 0 };
            OUString sDBName( GetDBName( sTmpName, rDoc ));
            OUString sDataSource(sDBName.getToken(0, DB_DELIM, nIdx));
            OUString sDataTableOrQuery(sDBName.getToken(0, DB_DELIM, nIdx));
            if( pMgr->IsInMerge() && !sDBName.isEmpty() &&
                pMgr->IsDataSourceOpen( sDataSource,
                                            sDataTableOrQuery, false))
            {
                double fNumber;
                pMgr->GetMergeColumnCnt(GetColumnName( sTmpName ),
                    GetLanguage(), m_aContent, &fNumber );
                m_bValid = true;
            }
        }
#endif
    }
}

OUString SwHiddenTextField::GetFieldName() const
{
    OUString aStr = SwFieldType::GetTypeStr(m_nSubType) +
        " " + m_aCond + " " + m_aTRUEText;

    if (m_nSubType == SwFieldTypesEnum::ConditionalText)
    {
        aStr += " : " + m_aFALSEText;
    }
    return aStr;
}

std::unique_ptr<SwField> SwHiddenTextField::Copy() const
{
    std::unique_ptr<SwHiddenTextField> pField(
        new SwHiddenTextField(static_cast<SwHiddenTextFieldType*>(GetTyp()), m_aCond,
                              m_aTRUEText, m_aFALSEText));
    pField->m_bIsHidden = m_bIsHidden;
    pField->m_bValid    = m_bValid;
    pField->m_aContent  = m_aContent;
    pField->SetFormat(GetFormat());
    pField->m_nSubType  = m_nSubType;
    return std::unique_ptr<SwField>(pField.release());
}

/// set condition
void SwHiddenTextField::SetPar1(const OUString& rStr)
{
    m_aCond = rStr;
    m_bCanToggle = !m_aCond.isEmpty();
}

OUString SwHiddenTextField::GetPar1() const
{
    return m_aCond;
}

/// set True/False text
void SwHiddenTextField::SetPar2(const OUString& rStr)
{
    if (m_nSubType == SwFieldTypesEnum::ConditionalText)
    {
        sal_Int32 nPos = rStr.indexOf('|');
        if (nPos == -1)
            m_aTRUEText = rStr;
        else
        {
            m_aTRUEText = rStr.copy(0, nPos);
            m_aFALSEText = rStr.copy(nPos + 1);
        }
    }
    else
        m_aTRUEText = rStr;
}

/// get True/False text
OUString SwHiddenTextField::GetPar2() const
{
    if(m_nSubType != SwFieldTypesEnum::ConditionalText)
    {
        return m_aTRUEText;
    }
    return m_aTRUEText + "|" + m_aFALSEText;
}

sal_uInt16 SwHiddenTextField::GetSubType() const
{
    return static_cast<sal_uInt16>(m_nSubType);
}

bool SwHiddenTextField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch( nWhichId )
    {
    case FIELD_PROP_PAR1:
        rAny <<= m_aCond;
        break;
    case FIELD_PROP_PAR2:
        rAny <<= m_aTRUEText;
        break;
    case FIELD_PROP_PAR3:
        rAny <<= m_aFALSEText;
        break;
    case FIELD_PROP_PAR4 :
        rAny <<= m_aContent;
        break;
    case FIELD_PROP_BOOL1:
        rAny <<= m_bIsHidden;
        break;
    default:
        assert(false);
    }
    return true;
}

bool SwHiddenTextField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    switch( nWhichId )
    {
    case FIELD_PROP_PAR1:
        {
            OUString sVal;
            rAny >>= sVal;
            SetPar1(sVal);
        }
        break;
    case FIELD_PROP_PAR2:
        rAny >>= m_aTRUEText;
        break;
    case FIELD_PROP_PAR3:
        rAny >>= m_aFALSEText;
        break;
    case FIELD_PROP_BOOL1:
        m_bIsHidden = *o3tl::doAccess<bool>(rAny);
        break;
    case FIELD_PROP_PAR4:
        rAny >>= m_aContent;
        m_bValid = true;
        break;
    default:
        assert(false);
    }
    return true;
}

OUString SwHiddenTextField::GetColumnName(const OUString& rName)
{
    sal_Int32 nPos = rName.indexOf(DB_DELIM);
    if( nPos>=0 )
    {
        nPos = rName.indexOf(DB_DELIM, nPos + 1);

        if( nPos>=0 )
            return rName.copy(nPos + 1);
    }
    return rName;
}

OUString SwHiddenTextField::GetDBName(std::u16string_view rName, SwDoc& rDoc)
{
    size_t nPos = rName.find(DB_DELIM);
    if( nPos != std::u16string_view::npos )
    {
        nPos = rName.find(DB_DELIM, nPos + 1);

        if( nPos != std::u16string_view::npos )
            return OUString(rName.substr(0, nPos));
    }

    SwDBData aData = rDoc.GetDBData();
    return aData.sDataSource + OUStringChar(DB_DELIM) + aData.sCommand;
}

// [aFieldDefinition] value sample : " IF A == B \"TrueText\" \"FalseText\""
void SwHiddenTextField::ParseIfFieldDefinition(std::u16string_view aFieldDefinition,
                                               OUString& rCondition,
                                               OUString& rTrue,
                                               OUString& rFalse)
{
    // get all positions inside the input string where words are started
    //
    // In: " IF A == B \"TrueText\" \"FalseText\""
    //      0         1           2          3
    //      01234567890 123456789 01 2345678901 2
    //
    // result:
    //      [1, 4, 6, 9, 11, 22]
    std::vector<sal_Int32> wordPosition;
    {
        bool quoted = false;
        bool insideWord = false;
        for (size_t i = 0; i < aFieldDefinition.size(); i++)
        {
            if (quoted)
            {
                if (aFieldDefinition[i] == '\"')
                {
                    quoted = false;
                    insideWord = false;
                }
            }
            else
            {
                if (aFieldDefinition[i] == ' ')
                {
                    // word delimiter
                    insideWord = false;
                }
                else
                {
                    if (insideWord)
                    {
                        quoted = (aFieldDefinition[i] == '\"');
                    }
                    else
                    {
                        insideWord = true;
                        wordPosition.push_back(i);
                        quoted = (aFieldDefinition[i] == '\"');
                    }
                }
            }
        }
    }

    // first word is always "IF"
    // last two words are: true-case and false-case,
    // everything before is treated as condition expression
    // => we need at least 4 words to be inside the input string
    if (wordPosition.size() < 4)
    {
        return;
    }


    const sal_Int32 conditionBegin = wordPosition[1];
    const sal_Int32 trueBegin      = wordPosition[wordPosition.size() - 2];
    const sal_Int32 falseBegin     = wordPosition[wordPosition.size() - 1];

    const sal_Int32 conditionLength = trueBegin - conditionBegin;
    const sal_Int32 trueLength      = falseBegin - trueBegin;

    // Syntax
    // OUString::copy( sal_Int32 beginIndex, sal_Int32 count )
    rCondition = o3tl::trim(aFieldDefinition.substr(conditionBegin, conditionLength));
    rTrue = o3tl::trim(aFieldDefinition.substr(trueBegin, trueLength));
    rFalse = o3tl::trim(aFieldDefinition.substr(falseBegin));

    // remove quotes
    if (rCondition.getLength() >= 2)
    {
        if (rCondition[0] == '\"' && rCondition[rCondition.getLength() - 1] == '\"')
            rCondition = rCondition.copy(1, rCondition.getLength() - 2);
    }
    if (rTrue.getLength() >= 2)
    {
        if (rTrue[0] == '\"' && rTrue[rTrue.getLength() - 1] == '\"')
            rTrue = rTrue.copy(1, rTrue.getLength() - 2);
    }
    if (rFalse.getLength() >= 2)
    {
        if (rFalse[0] == '\"' && rFalse[rFalse.getLength() - 1] == '\"')
            rFalse = rFalse.copy(1, rFalse.getLength() - 2);
    }

    // Note: do not make trim once again, while this is a user defined data
}

// field type for line height 0

SwHiddenParaFieldType::SwHiddenParaFieldType()
    : SwFieldType( SwFieldIds::HiddenPara )
{
}

std::unique_ptr<SwFieldType> SwHiddenParaFieldType::Copy() const
{
    return std::make_unique<SwHiddenParaFieldType>();
}

// field for line height 0

SwHiddenParaField::SwHiddenParaField(SwHiddenParaFieldType* pTyp, OUString aStr)
    : SwField(pTyp), m_aCond(std::move(aStr))
{
    m_bIsHidden = false;
}

OUString SwHiddenParaField::ExpandImpl(SwRootFrame const*constconst
{
    return OUString();
}

std::unique_ptr<SwField> SwHiddenParaField::Copy() const
{
    std::unique_ptr<SwHiddenParaField> pField(new SwHiddenParaField(static_cast<SwHiddenParaFieldType*>(GetTyp()), m_aCond));
    pField->m_bIsHidden = m_bIsHidden;
    return std::unique_ptr<SwField>(pField.release());
}

bool SwHiddenParaField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch ( nWhichId )
    {
    case FIELD_PROP_PAR1:
        rAny <<= m_aCond;
        break;
    case  FIELD_PROP_BOOL1:
        rAny <<= m_bIsHidden;
        break;

    default:
        assert(false);
    }
    return true;
}

bool SwHiddenParaField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    switch ( nWhichId )
    {
    case FIELD_PROP_PAR1:
        rAny >>= m_aCond;
        break;
    case FIELD_PROP_BOOL1:
        m_bIsHidden = *o3tl::doAccess<bool>(rAny);
        break;

    default:
        assert(false);
    }
    return true;
}

/// set condition
void SwHiddenParaField::SetPar1(const OUString& rStr)
{
    m_aCond = rStr;
}

OUString SwHiddenParaField::GetPar1() const
{
    return m_aCond;
}

// PostIt field type

SwPostItFieldType::SwPostItFieldType(SwDoc& rDoc)
    : SwFieldType( SwFieldIds::Postit )
    , mrDoc(rDoc)
{}

std::unique_ptr<SwFieldType> SwPostItFieldType::Copy() const
{
    return std::make_unique<SwPostItFieldType>(mrDoc);
}

// PostIt field

sal_uInt32 SwPostItField::s_nLastPostItId = 1;

SwPostItField::SwPostItField( SwPostItFieldType* pT,
        OUString aAuthor,
        OUString aText,
        OUString aInitials,
        SwMarkName aName,
        const DateTime& rDateTime,
        const bool bResolved,
        const sal_uInt32 nPostItId,
        const sal_uInt32 nParentId,
        const sal_uInt32 nParaId,
        const sal_uInt32 nParentPostItId,
        SwMarkName aParentName
)
    : SwField( pT )
    , m_sText( std::move(aText) )
    , m_sAuthor( std::move(aAuthor) )
    , m_sInitials( std::move(aInitials) )
    , m_sName( std::move(aName) )
    , m_aDateTime( rDateTime )
    , m_bResolved( bResolved )
    , m_nParentId( nParentId )
    , m_nParaId( nParaId )
    , m_nParentPostItId ( nParentPostItId )
    , m_sParentName( std::move(aParentName) )
{
    m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId;
}

SwPostItField::~SwPostItField()
{
    if ( m_xTextObject.is() )
    {
        m_xTextObject->DisposeEditSource();
    }

    mpText.reset();
}

OUString SwPostItField::ExpandImpl(SwRootFrame const*constconst
{
    return OUString();
}

OUString SwPostItField::GetDescription() const
{
    return SwResId(STR_NOTE);
}

void SwPostItField::SetResolved(bool bNewState)
{
    m_bResolved = bNewState;
}

void SwPostItField::ToggleResolved()
{
    m_bResolved = !m_bResolved;
}

bool SwPostItField::GetResolved() const
{
    return m_bResolved;
}

std::unique_ptr<SwField> SwPostItField::Copy() const
{
    std::unique_ptr<SwPostItField> pRet(new SwPostItField( static_cast<SwPostItFieldType*>(GetTyp()), m_sAuthor, m_sText, m_sInitials, m_sName,
                                                           m_aDateTime, m_bResolved, m_nPostItId, m_nParentId, m_nParaId, m_nParentPostItId, m_sParentName));
    if (mpText)
        pRet->SetTextObject( *mpText );

    // Note: member <m_xTextObject> not copied.

    return std::unique_ptr<SwField>(pRet.release());
}

/// set author
void SwPostItField::SetPar1(const OUString& rStr)
{
    m_sAuthor = rStr;
}

/// get author
OUString SwPostItField::GetPar1() const
{
    return m_sAuthor;
}

/// set the PostIt's text
void SwPostItField::SetPar2(const OUString& rStr)
{
    m_sText = rStr;
}

/// get the PostIt's text
OUString SwPostItField::GetPar2() const
{
    return m_sText;
}


void SwPostItField::SetName(const SwMarkName& rName)
{
    m_sName = rName;
}

void SwPostItField::SetParentName(const SwMarkName& rName)
{
    m_sParentName = rName;
}

void SwPostItField::SetTextObject( std::optional<OutlinerParaObject> pText )
{
    mpText = std::move(pText);
}

sal_Int32 SwPostItField::GetNumberOfParagraphs() const
{
    return mpText ? mpText->Count() : 1;
}

void SwPostItField::ChangeStyleSheetName(std::u16string_view rOldName, const SfxStyleSheetBase* pStyleSheet)
{
    if (mpText && pStyleSheet)
        mpText->ChangeStyleSheetName(pStyleSheet->GetFamily(), rOldName, pStyleSheet->GetName());
}

void SwPostItField::SetPostItId(const sal_uInt32 nPostItId)
{
    m_nPostItId = nPostItId == 0 ? s_nLastPostItId++ : nPostItId;
}

void SwPostItField::SetParentPostItId(const sal_uInt32 nParentPostItId)
{
    m_nParentPostItId = nParentPostItId;
}

void SwPostItField::SetParentId(const sal_uInt32 nParentId)
{
    m_nParentId = nParentId;
}

void SwPostItField::SetParaId(const sal_uInt32 nParaId)
{
    m_nParaId = nParaId;
}

bool SwPostItField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
{
    switch( nWhichId )
    {
    case FIELD_PROP_PAR1:
        rAny <<= m_sAuthor;
        break;
    case FIELD_PROP_PAR2:
        {
        rAny <<= m_sText;
        break;
        }
    case FIELD_PROP_PAR3:
        rAny <<= m_sInitials;
        break;
    case FIELD_PROP_PAR4:
        rAny <<= m_sName.toString();
        break;
    case FIELD_PROP_PAR7: // PAR5 (Parent Para Id) and PAR6 (Para Id) are skipped - they are not written into xml. Used for file conversion.
        rAny <<= m_sParentName.toString();
        break;
    case FIELD_PROP_BOOL1:
        rAny <<= m_bResolved;
        break;
    case FIELD_PROP_TEXT:
        {
            if ( !m_xTextObject.is() )
            {
                SwPostItFieldType* pGetType = static_cast<SwPostItFieldType*>(GetTyp());
                SwDoc& rDoc = pGetType->GetDoc();
                auto pObj = std::make_unique<SwTextAPIEditSource>( &rDoc );
                const_cast <SwPostItField*> (this)->m_xTextObject = new SwTextAPIObject( std::move(pObj) );
            }

            if ( mpText )
                m_xTextObject->SetText( *mpText );
            else
                m_xTextObject->SetString( m_sText );

            rAny <<= uno::Reference < text::XText >( m_xTextObject );
            break;
        }
    case FIELD_PROP_DATE:
        {
            rAny <<= m_aDateTime.GetUNODate();
        }
        break;
    case FIELD_PROP_DATE_TIME:
        {
            rAny <<= m_aDateTime.GetUNODateTime();
        }
        break;
    case FIELD_PROP_PAR5:
        {
            rAny <<= OUString(OUString::number(m_nParentId, 16).toAsciiUpperCase());
        }
        break;
    case FIELD_PROP_PAR6:
        {
            rAny <<= OUString(OUString::number(m_nPostItId, 16).toAsciiUpperCase());
        }
        break;
    case FIELD_PROP_TITLE:
        break;
    default:
        assert(false);
    }
    return true;
}

bool SwPostItField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
{
    switch( nWhichId )
    {
    case FIELD_PROP_PAR1:
        rAny >>= m_sAuthor;
        break;
    case FIELD_PROP_PAR2:
        rAny >>= m_sText;
        //#i100374# new string via api, delete complex text object so SwPostItNote picks up the new string
        mpText.reset();
        break;
    case FIELD_PROP_PAR3:
        rAny >>= m_sInitials;
        break;
    case FIELD_PROP_PAR4:
        {
            OUString tmp;
            if (rAny >>= tmp)
                m_sName = SwMarkName(tmp);
        }
        break;
    case FIELD_PROP_PAR7: // PAR5 (Parent Para Id) and PAR6 (Para Id) are skipped - they are not written into xml. Used for file conversion.
        {
            OUString tmp;
            if (rAny >>= tmp)
                m_sParentName = SwMarkName(tmp);
        }
        break;
    case FIELD_PROP_BOOL1:
        rAny >>= m_bResolved;
        break;
    case FIELD_PROP_TEXT:
        OSL_FAIL("Not implemented!");
        break;
    case FIELD_PROP_DATE:
        ifauto aSetDate = o3tl::tryAccess<util::Date>(rAny) )
        {
            m_aDateTime = DateTime( Date(aSetDate->Day, aSetDate->Month, aSetDate->Year) );
        }
        break;
    case FIELD_PROP_DATE_TIME:
    {
        util::DateTime aDateTimeValue;
        if(!(rAny >>= aDateTimeValue))
            return false;
        m_aDateTime = DateTime(aDateTimeValue);
    }
    break;
    case FIELD_PROP_PAR5:
    {
        OUString sTemp;
        rAny >>= sTemp;
        m_nParentId = sTemp.toInt32(16);
    }
    break;
    case FIELD_PROP_PAR6:
    {
        OUString sTemp;
        rAny >>= sTemp;
        m_nPostItId = sTemp.toInt32(16);
    }
    break;
    default:
        assert(false);
    }
    return true;
}

void SwPostItField::dumpAsXml(xmlTextWriterPtr pWriter) const
{
    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SwPostItField"));
    (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("name"), BAD_CAST(GetName().toString().toUtf8().getStr()));

    SwField::dumpAsXml(pWriter);

    (void)xmlTextWriterStartElement(pWriter, BAD_CAST("mpText"));
    (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("ptr"), "%p", mpText ? &*mpText ;: nullptr);
    if (mpText)
        mpText->dumpAsXml(pWriter);
    (void)xmlTextWriterEndElement(pWriter);

    (void)xmlTextWriterEndElement(pWriter);
}

// extended user information field type

SwExtUserFieldType::SwExtUserFieldType()
    : SwFieldType( SwFieldIds::ExtUser )
{
}

std::unique_ptr<SwFieldType> SwExtUserFieldType::Copy() const
{
    return std::make_unique<SwExtUserFieldType>();
}

OUString SwExtUserFieldType::Expand(sal_uInt16 nSub )
{
    UserOptToken nRet = static_cast<UserOptToken>(USHRT_MAX);
    switch(nSub)
    {
    case EU_FIRSTNAME:      nRet = UserOptToken::FirstName; break;
    case EU_NAME:           nRet = UserOptToken::LastName;  break;
    case EU_SHORTCUT:       nRet = UserOptToken::ID; break;

    case EU_COMPANY:        nRet = UserOptToken::Company;        break;
    case EU_STREET:         nRet = UserOptToken::Street;         break;
    case EU_TITLE:          nRet = UserOptToken::Title;          break;
    case EU_POSITION:       nRet = UserOptToken::Position;       break;
    case EU_PHONE_PRIVATE:  nRet = UserOptToken::TelephoneHome;    break;
    case EU_PHONE_COMPANY:  nRet = UserOptToken::TelephoneWork;    break;
    case EU_FAX:            nRet = UserOptToken::Fax;            break;
    case EU_EMAIL:          nRet = UserOptToken::Email;          break;
    case EU_COUNTRY:        nRet = UserOptToken::Country;        break;
    case EU_ZIP:            nRet = UserOptToken::Zip;            break;
    case EU_CITY:           nRet = UserOptToken::City;           break;
    case EU_STATE:          nRet = UserOptToken::State;          break;
    case EU_FATHERSNAME:    nRet = UserOptToken::FathersName;    break;
    case EU_APARTMENT:      nRet = UserOptToken::Apartment;      break;
    default:             OSL_ENSURE( false"Field unknown");
    }
    ifstatic_cast<UserOptToken>(USHRT_MAX) != nRet )
    {
        SvtUserOptions& rUserOpt = SwModule::get()->GetUserOptions();
        return rUserOpt.GetToken( nRet );
    }
    return OUString();
}

// extended user information field

SwExtUserField::SwExtUserField(SwExtUserFieldType* pTyp, sal_uInt16 nSubTyp, sal_uInt32 nFormat) :
    SwField(pTyp, nFormat), m_nType(nSubTyp)
{
    m_aContent = SwExtUserFieldType::Expand(m_nType);
}

OUString SwExtUserField::ExpandImpl(SwRootFrame const*constconst
{
    if (!IsFixed())
        const_cast<SwExtUserField*>(this)->m_aContent = SwExtUserFieldType::Expand(m_nType);

    return m_aContent;
}

std::unique_ptr<SwField> SwExtUserField::Copy() const
{
    std::unique_ptr<SwExtUserField> pField(new SwExtUserField(static_cast<SwExtUserFieldType*>(GetTyp()), m_nType, GetFormat()));
    pField->SetExpansion(m_aContent);

    return std::unique_ptr<SwField>(pField.release());
}

sal_uInt16 SwExtUserField::GetSubType() const
{
    return m_nType;
}

void SwExtUserField::SetSubType(sal_uInt16 nSub)
{
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=96 H=97 G=96

¤ Dauer der Verarbeitung: 0.36 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge