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


Quelle  tox.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 <calbck.hxx>
#include <doc.hxx>
#include <docary.hxx>
#include <editeng/tstpitem.hxx>
#include <hintids.hxx>
#include <hints.hxx>
#include <ndtxt.hxx>
#include <paratr.hxx>
#include <rootfrm.hxx>
#include <scriptinfo.hxx>
#include <strings.hrc>
#include <swtypes.hxx>
#include <tox.hxx>
#include <txtfrm.hxx>
#include <txttxmrk.hxx>
#include <unoidx.hxx>

#include <optional>
#include <sal/log.hxx>
#include <o3tl/string_view.hxx>
#include <osl/diagnose.h>

#include <algorithm>
#include <string_view>
#include <utility>


const sal_Unicode C_NUM_REPL      = '@';
const sal_Unicode C_END_PAGE_NUM   = '~';

namespace
{
void lcl_FillAuthPattern(SwFormTokens &rAuthTokens, sal_uInt16 nTypeId)
{
    rAuthTokens.reserve(9); // Worst case: Start+Sep1+Auth+3*(Sep2+Auth)

    SwFormToken aStartToken( TOKEN_AUTHORITY );
    aStartToken.nAuthorityField = AUTH_FIELD_IDENTIFIER;
    rAuthTokens.push_back( aStartToken );
    SwFormToken aSeparatorToken( TOKEN_TEXT );
    aSeparatorToken.sText = ": ";
    rAuthTokens.push_back( aSeparatorToken );

    --nTypeId; // compensate +1 offset introduced by caller

    SwFormToken aTextToken( TOKEN_TEXT );
    aTextToken.sText = ", ";

    const ToxAuthorityField nVals[4] = {
        AUTH_FIELD_AUTHOR,
        AUTH_FIELD_TITLE,
        AUTH_FIELD_YEAR,
        nTypeId == AUTH_TYPE_WWW ? AUTH_FIELD_URL : AUTH_FIELD_END
    };

    for(size_t i = 0; i < SAL_N_ELEMENTS(nVals); ++i)
    {
        if(nVals[i] == AUTH_FIELD_END)
            break;
        if( i > 0 )
            rAuthTokens.push_back( aTextToken );

        // -> #i21237#
        SwFormToken aToken(TOKEN_AUTHORITY);

        aToken.nAuthorityField = nVals[i];
        rAuthTokens.push_back(aToken);
        // <- #i21237#
    }
}
}

/// pool default constructor
SwTOXMark::SwTOXMark()
    : SfxPoolItem(RES_TXTATR_TOXMARK)
    , m_pType(nullptr)
    , m_pTextAttr(nullptr)
    , m_nLevel(0)
    , m_bAutoGenerated(false)
    , m_bMainEntry(false)
{
    setNonShareable();
}

SwTOXMark::SwTOXMark(const SwTOXType* pType)
    : SfxPoolItem(RES_TXTATR_TOXMARK)
    , m_pType(pType)
    , m_pTextAttr(nullptr)
    , m_nLevel(0)
    , m_bAutoGenerated(false)
    , m_bMainEntry(false)
{
    setNonShareable();
    StartListening(const_cast<SwTOXType*>(m_pType)->GetNotifier());
}

SwTOXMark::SwTOXMark(const SwTOXMark& rCopy)
    : SfxPoolItem(RES_TXTATR_TOXMARK)
    , SvtListener()
    , m_pType(rCopy.m_pType)
    , m_aPrimaryKey(rCopy.m_aPrimaryKey)
    , m_aSecondaryKey(rCopy.m_aSecondaryKey)
    , m_aTextReading(rCopy.m_aTextReading)
    , m_aPrimaryKeyReading(rCopy.m_aPrimaryKeyReading)
    , m_aSecondaryKeyReading(rCopy.m_aSecondaryKeyReading)
    , m_pTextAttr(nullptr)
    , m_nLevel(rCopy.m_nLevel)
    , m_bAutoGenerated(rCopy.m_bAutoGenerated)
    , m_bMainEntry(rCopy.m_bMainEntry)
{
    setNonShareable();
    if(m_pType)
        StartListening(const_cast<SwTOXType*>(m_pType)->GetNotifier());
    // Copy AlternativString
    m_aAltText = rCopy.m_aAltText;
}

SwTOXMark::~SwTOXMark()
{
}

void SwTOXMark::SetXTOXMark(rtl::Reference<SwXDocumentIndexMark> const& xMark)
{ m_wXDocumentIndexMark = xMark.get(); }

void SwTOXMark::RegisterToTOXType(SwTOXType& rType)
{
    SvtListener::EndListeningAll();
    m_pType = &rType;
    StartListening(rType.GetNotifier());
}

bool SwTOXMark::operator==( const SfxPoolItem& rAttr ) const
{
    assert(SfxPoolItem::operator==(rAttr));
    // tdf#158783 this item was never 'pooled', so operator== was not really
    // ever used. We discussed to implement it (there is quite some
    // content), but we came to the point that it's only safe to say
    // instances are equal when same instance -> fallback to ptr compare.
    // NOTE: Do *not* use areSfxPoolItemPtrsEqual here, with DBG_UTIL
    //   active the control/test code there would again call operator==
    return this == &rAttr;
}

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

void SwTOXMark::Notify(const SfxHint& rHint)
{
    if (rHint.GetId() == SfxHintId::SwCollectTextMarks)
    {
        auto pCollectHint = static_cast<const sw::CollectTextMarksHint*>(&rHint);
        if(GetTextTOXMark())
            pCollectHint->m_rMarks.push_back(this);
    }
    else if (rHint.GetId() == SfxHintId::SwCollectTextTOXMarksForLayout)
    {
        auto pCollectLayoutHint = static_cast<const sw::CollectTextTOXMarksForLayoutHint*>(&rHint);
        if(!GetTextTOXMark())
            return;
        auto& rTextMark = *GetTextTOXMark();
        auto& rNode = rTextMark.GetTextNode();
        auto pLayout = pCollectLayoutHint->m_pLayout;
        // Check basic sanity and that it is part of our layout and not in undo
        if(!rNode.GetNodes().IsDocNodes() || !rNode.GetText().getLength() || !rNode.HasWriterListeners() || !rNode.getLayoutFrame(pLayout))
            return;
        // Check for being hidden
        if(rNode.IsHiddenByParaField() || SwScriptInfo::IsInHiddenRange(rNode, rTextMark.GetStart()))
            return;
        // Check for being hidden by hidden redlines
        if (pLayout && pLayout->HasMergedParas() && sw::IsMarkHintHidden(*pLayout, rNode, rTextMark))
            return;
        // Check for being hidden by hidden sections
        if (auto pFrame(rNode.getLayoutFrame(pLayout)); !pFrame || pFrame->IsHiddenNow())
            return;
        pCollectLayoutHint->m_rMarks.push_back(rTextMark);
    }
}

void SwTOXMark::InvalidateTOXMark()
{
    if (auto xUnoIndexMark = m_wXDocumentIndexMark.get())
    {
        xUnoIndexMark->OnSwTOXMarkDeleted();
        m_wXDocumentIndexMark.clear();
    }
}

OUString SwTOXMark::GetText(SwRootFrame const*const pLayout) const
{
    if( !m_aAltText.isEmpty() )
        return m_aAltText;

    if( m_pTextAttr && m_pTextAttr->GetpTextNd() )
    {
        const sal_Int32* pEndIdx = m_pTextAttr->GetEnd();
        OSL_ENSURE( pEndIdx, "TOXMark without mark!");
        if( pEndIdx )
        {
            const sal_Int32 nStt = m_pTextAttr->GetStart();
            return m_pTextAttr->GetpTextNd()->GetExpandText(pLayout, nStt, *pEndIdx-nStt);
        }
    }

    return OUString();
}

// Manage types of TOX
SwTOXType::SwTOXType(SwDoc& rDoc, TOXTypes eTyp, OUString aName)
    : m_rDoc(rDoc)
    , m_aName(std::move(aName))
    , m_eType(eTyp)
{
}

SwTOXType::SwTOXType(const SwTOXType& rCopy)
    : m_rDoc(rCopy.m_rDoc)
    , m_aName(rCopy.m_aName)
    , m_eType(rCopy.m_eType)
{
    if (auto pRegisteredIn = const_cast<SwTOXType&>(rCopy).GetRegisteredIn())
        pRegisteredIn->Add(*this);
}

const TranslateId STR_POOLCOLL_TOX_ARY[] =
{
    // Subcategory Index-Directories
    STR_POOLCOLL_TOX_IDXH,
    STR_POOLCOLL_TOX_IDX1,
    STR_POOLCOLL_TOX_IDX2,
    STR_POOLCOLL_TOX_IDX3,
    STR_POOLCOLL_TOX_IDXBREAK
};

const TranslateId STR_POOLCOLL_TOX_CNTNT_ARY[] =
{
    // Subcategory Tables of Contents
    STR_POOLCOLL_TOX_CNTNTH,
    STR_POOLCOLL_TOX_CNTNT1,
    STR_POOLCOLL_TOX_CNTNT2,
    STR_POOLCOLL_TOX_CNTNT3,
    STR_POOLCOLL_TOX_CNTNT4,
    STR_POOLCOLL_TOX_CNTNT5
};

const TranslateId STR_POOLCOLL_TOX_CNTNT_EXTRA_ARY[] =
{
    // Subcategory Table of Contents more Levels 5 - 10
    STR_POOLCOLL_TOX_CNTNT6,
    STR_POOLCOLL_TOX_CNTNT7,
    STR_POOLCOLL_TOX_CNTNT8,
    STR_POOLCOLL_TOX_CNTNT9,
    STR_POOLCOLL_TOX_CNTNT10
};

const TranslateId STR_POOLCOLL_TOX_USER_ARY[] =
{
    // Subcategory User-Directories:
    STR_POOLCOLL_TOX_USERH,
    STR_POOLCOLL_TOX_USER1,
    STR_POOLCOLL_TOX_USER2,
    STR_POOLCOLL_TOX_USER3,
    STR_POOLCOLL_TOX_USER4,
    STR_POOLCOLL_TOX_USER5
};

const TranslateId STR_POOLCOLL_TOX_USER_EXTRA_ARY[] =
{
    // Subcategory User-Directories more Levels 5 - 10
    STR_POOLCOLL_TOX_USER6,
    STR_POOLCOLL_TOX_USER7,
    STR_POOLCOLL_TOX_USER8,
    STR_POOLCOLL_TOX_USER9,
    STR_POOLCOLL_TOX_USER10
};

const TranslateId STR_POOLCOLL_TOX_ILLUS_ARY[] =
{
    // Illustrations Index
    STR_POOLCOLL_TOX_ILLUSH,
    STR_POOLCOLL_TOX_ILLUS1
};

const TranslateId STR_POOLCOLL_TOX_OBJECT_ARY[] =
{
    //  Object Index
    STR_POOLCOLL_TOX_OBJECTH,
    STR_POOLCOLL_TOX_OBJECT1
};

const TranslateId STR_POOLCOLL_TOX_TABLES_ARY[] =
{
    //  Tables Index
    STR_POOLCOLL_TOX_TABLESH,
    STR_POOLCOLL_TOX_TABLES1
};

const TranslateId STR_POOLCOLL_TOX_AUTHORITIES_ARY[] =
{
    //  Index of Authorities
    STR_POOLCOLL_TOX_AUTHORITIESH,
    STR_POOLCOLL_TOX_AUTHORITIES1
};

const TranslateId STR_POOLCOLL_TOX_CITATION_ARY[] =
{
    STR_POOLCOLL_TOX_CITATION
};

// Edit forms
SwForm::SwForm( TOXTypes eTyp ) // #i21237#
    : m_eType( eTyp ), m_nFormMaxLevel( SwForm::GetFormMaxLevel( eTyp )),
//  nFirstTabPos( lNumberIndent ),
    m_bCommaSeparated(false)
{
    //bHasFirstTabPos =
    m_bIsRelTabPos = true;

    // The table of contents has a certain number of headlines + headings
    // The user has 10 levels + headings
    // Keyword has 3 levels + headings+ separator
    // Indexes of tables, object illustrations and authorities consist of a heading and one level

    const TranslateId* pPoolId;
    switch( m_eType )
    {
    case TOX_INDEX:         pPoolId = STR_POOLCOLL_TOX_ARY;    break;
    case TOX_USER:          pPoolId = STR_POOLCOLL_TOX_USER_ARY;   break;
    case TOX_CONTENT:       pPoolId = STR_POOLCOLL_TOX_CNTNT_ARY;  break;
    case TOX_ILLUSTRATIONS: pPoolId = STR_POOLCOLL_TOX_ILLUS_ARY;  break;
    case TOX_OBJECTS      : pPoolId = STR_POOLCOLL_TOX_OBJECT_ARY; break;
    case TOX_TABLES       : pPoolId = STR_POOLCOLL_TOX_TABLES_ARY; break;
    case TOX_AUTHORITIES  : pPoolId = STR_POOLCOLL_TOX_AUTHORITIES_ARY;    break;
    case TOX_CITATION  : pPoolId = STR_POOLCOLL_TOX_CITATION_ARY; break;
    default:
        OSL_ENSURE( false"invalid TOXTyp");
        return ;
    }

    SwFormTokens aTokens;
    const bool bNeedsLink
        = TOX_CONTENT == m_eType || TOX_ILLUSTRATIONS == m_eType || TOX_TABLES == m_eType;
    if (bNeedsLink)
    {
        SwFormToken aLinkStt (TOKEN_LINK_START);
        aLinkStt.sCharStyleName = UIName(SwResId(STR_POOLCHR_TOXJUMP));
        aTokens.push_back(aLinkStt);
    }

    if (TOX_CONTENT == m_eType)
    {
        aTokens.emplace_back(TOKEN_ENTRY_NO);
        aTokens.emplace_back(TOKEN_ENTRY_TEXT);
    }
    else
        aTokens.emplace_back(TOKEN_ENTRY);

    if (TOX_AUTHORITIES != m_eType)
    {
        SwFormToken aToken(TOKEN_TAB_STOP);
        aToken.nTabStopPosition = 0;

        // #i36870# right aligned tab for all
        aToken.cTabFillChar = '.';
        aToken.eTabAlign = SvxTabAdjust::End;

        aTokens.push_back(aToken);
        aTokens.emplace_back(TOKEN_PAGE_NUMS);
    }

    if (bNeedsLink)
        aTokens.emplace_back(TOKEN_LINK_END);

    SetTemplate(0, UIName(SwResId(*pPoolId++)));

    if(TOX_INDEX == m_eType)
    {
        for( sal_uInt16 i = 1; i < 5; ++i  )
        {
            if(1 == i)
            {
                SwFormTokens aTmpTokens;
                SwFormToken aTmpToken(TOKEN_ENTRY);
                aTmpTokens.push_back(aTmpToken);

                SetPattern( i, std::move(aTmpTokens) );
                SetTemplate(i, UIName(SwResId(STR_POOLCOLL_TOX_IDXBREAK)));
            }
            else
            {
                SetPattern( i, std::vector(aTokens) );
                SetTemplate(i, UIName(SwResId(STR_POOLCOLL_TOX_ARY[i - 1])));
            }
        }
    }
    else
    {
        for (sal_uInt16 i = 1; i < GetFormMax(); ++i, ++pPoolId)    // Number 0 is the title
        {
            if (TOX_AUTHORITIES == m_eType)
            {
                SwFormTokens aAuthTokens;
                lcl_FillAuthPattern(aAuthTokens, i);
                SetPattern(i, std::move(aAuthTokens));
            }
            else
                SetPattern( i, std::vector(aTokens) );

            if( TOX_CONTENT == m_eType && 6 == i )
                pPoolId = STR_POOLCOLL_TOX_CNTNT_EXTRA_ARY;
            else if( TOX_USER == m_eType && 6 == i )
                pPoolId = STR_POOLCOLL_TOX_USER_EXTRA_ARY;
            else if( TOX_AUTHORITIES == m_eType ) //reuse the same STR_POOLCOLL_TOX_AUTHORITIES1 id each time
                pPoolId = STR_POOLCOLL_TOX_AUTHORITIES_ARY + 1;
            SetTemplate(i, UIName(SwResId(*pPoolId)));
        }
    }
}

SwForm::SwForm(const SwForm& rForm)
    : m_eType( rForm.m_eType )
{
    *this = rForm;
}

SwForm& SwForm::operator=(const SwForm& rForm)
{
    m_eType = rForm.m_eType;
    m_nFormMaxLevel = rForm.m_nFormMaxLevel;
//  nFirstTabPos = rForm.nFirstTabPos;
//  bHasFirstTabPos = rForm.bHasFirstTabPos;
    m_bIsRelTabPos = rForm.m_bIsRelTabPos;
    m_bCommaSeparated = rForm.m_bCommaSeparated;
    for(sal_uInt16 i=0; i < m_nFormMaxLevel; ++i)
    {
        m_aPattern[i] = rForm.m_aPattern[i];
        m_aTemplate[i] = rForm.m_aTemplate[i];
    }
    return *this;
}

sal_uInt16 SwForm::GetFormMaxLevel( TOXTypes eTOXType )
{
    switch( eTOXType )
    {
        case TOX_INDEX:
            return 5;
        case TOX_USER:
        case TOX_CONTENT:
            return MAXLEVEL + 1;
        case TOX_ILLUSTRATIONS:
        case TOX_OBJECTS:
        case TOX_TABLES:
            return 2;
        case TOX_BIBLIOGRAPHY:
        case TOX_CITATION:
        case TOX_AUTHORITIES:
            return AUTH_TYPE_END + 1;
    }
    return 0;
}

void SwForm::AdjustTabStops( SwDoc const & rDoc ) // #i21237#
{
    const sal_uInt16 nFormMax = GetFormMax();
    for ( sal_uInt16 nLevel = 1; nLevel < nFormMax; ++nLevel )
    {
        SwTextFormatColl* pColl = rDoc.FindTextFormatCollByName( GetTemplate(nLevel) );
        if( pColl == nullptr )
        {
            // Paragraph Style for this level has not been created.
            // --> No need to propagate default values
            continue;
        }

        const SvxTabStopItem& rTabStops = pColl->GetTabStops(false);
        const sal_uInt16 nTabCount = rTabStops.Count();
        if (nTabCount != 0)
        {
            SwFormTokens aCurrentPattern = GetPattern(nLevel);
            SwFormTokens::iterator aIt = aCurrentPattern.begin();

            bool bChanged = false;
            for(sal_uInt16 nTab = 0; nTab < nTabCount; ++nTab)
            {
                const SvxTabStop& rTab = rTabStops[nTab];

                if ( rTab.GetAdjustment() == SvxTabAdjust::Default )
                    continue// ignore the default tab stop

                aIt = find_if( aIt, aCurrentPattern.end(), SwFormTokenEqualToFormTokenType(TOKEN_TAB_STOP) );
                if ( aIt != aCurrentPattern.end() )
                {
                    bChanged = true;
                    aIt->nTabStopPosition = rTab.GetTabPos();
                    aIt->eTabAlign =
                        ( nTab == nTabCount - 1
                          && rTab.GetAdjustment() == SvxTabAdjust::Right )
                        ? SvxTabAdjust::End
                        : rTab.GetAdjustment();
                    aIt->cTabFillChar = rTab.GetFill();
                    ++aIt;
                }
                else
                    break// no more tokens to replace
            }

            if ( bChanged )
                SetPattern( nLevel, std::move(aCurrentPattern) );
        }
    }
}

OUString SwForm::GetFormEntry()       {return u""_ustr;}
OUString SwForm::GetFormTab()         {return u""_ustr;}
OUString SwForm::GetFormPageNums()    {return u"<#>"_ustr;}
OUString SwForm::GetFormLinkStt()     {return u""_ustr;}
OUString SwForm::GetFormLinkEnd()     {return u""_ustr;}
OUString SwForm::GetFormEntryNum()    {return u""_ustr;}
OUString SwForm::GetFormEntryText()    {return u""_ustr;}
OUString SwForm::GetFormChapterMark() {return u""_ustr;}
OUString SwForm::GetFormText()        {return u""_ustr;}
OUString SwForm::GetFormAuth()        {return u""_ustr;}

SwTOXBase::SwTOXBase(const SwTOXType* pTyp, const SwForm& rForm,
                     SwTOXElement nCreaType, OUString aTitle )
    : SwClient(const_cast<sw::BroadcastingModify*>(static_cast<sw::BroadcastingModify const *>(pTyp)))
    , m_aForm(rForm)
    , m_aTitle(std::move(aTitle))
    , m_eLanguage(::GetAppLanguage())
    , m_nCreateType(nCreaType)
    , m_nOLEOptions(SwTOOElements::NONE)
    , m_eCaptionDisplay(CAPTION_COMPLETE)
    , m_bProtected( true )
    , m_bFromChapter(false)
    , m_bFromObjectNames(false)
    , m_bLevelFromChapter(false)
    , maMSTOCExpression()
    , mbKeepExpression(true)
{
    m_aData.nOptions = SwTOIOptions::NONE;
}

SwTOXBase::SwTOXBase( const SwTOXBase& rSource, SwDoc* pDoc )
    : SwClient( rSource.GetRegisteredInNonConst() )
    , mbKeepExpression(true)
{
    CopyTOXBase( pDoc, rSource );
}

void SwTOXBase::RegisterToTOXType( SwTOXType& rType )
{
    rType.Add(*this);
}

void SwTOXBase::CopyTOXBase( SwDoc* pDoc, const SwTOXBase& rSource )
{
    maMSTOCExpression = rSource.maMSTOCExpression;
    SwTOXType* pType = const_cast<SwTOXType*>(rSource.GetTOXType());
    if( pDoc &&
        std::find_if(pDoc->GetTOXTypes().begin(), pDoc->GetTOXTypes().end(),
                     [=](const std::unique_ptr<SwTOXType> & p) { return p.get() == pType; })
            == pDoc->GetTOXTypes().end())
    {
        // type not in pDoc, so create it now
        const SwTOXTypes& rTypes = pDoc->GetTOXTypes();
        bool bFound = false;
        for( size_t n = rTypes.size(); n; )
        {
            const SwTOXType* pCmp = rTypes[ --n ].get();
            if( pCmp->GetType() == pType->GetType() &&
                pCmp->GetTypeName() == pType->GetTypeName() )
            {
                pType = const_cast<SwTOXType*>(pCmp);
                bFound = true;
                break;
            }
        }

        if( !bFound )
            pType = const_cast<SwTOXType*>(pDoc->InsertTOXType( *pType ));
    }
    pType->Add(*this);

    m_nCreateType = rSource.m_nCreateType;
    m_aTitle      = rSource.m_aTitle;
    m_aForm       = rSource.m_aForm;
    m_aBookmarkName = rSource.m_aBookmarkName;
    m_bProtected  = rSource.m_bProtected;
    m_bFromChapter = rSource.m_bFromChapter;
    m_bFromObjectNames = rSource.m_bFromObjectNames;
    m_sMainEntryCharStyle = rSource.m_sMainEntryCharStyle;
    m_sSequenceName = rSource.m_sSequenceName;
    m_eCaptionDisplay = rSource.m_eCaptionDisplay;
    m_nOLEOptions = rSource.m_nOLEOptions;
    m_eLanguage = rSource.m_eLanguage;
    m_sSortAlgorithm = rSource.m_sSortAlgorithm;
    m_bLevelFromChapter = rSource.m_bLevelFromChapter;

    for( sal_uInt16 i = 0; i < MAXLEVEL; ++i )
        m_aStyleNames[i] = rSource.m_aStyleNames[i];

    // it's the same data type!
    m_aData.nOptions =  rSource.m_aData.nOptions;

    if( !pDoc || pDoc->IsCopyIsMove() )
        m_aName = rSource.GetTOXName();
    else
        m_aName = UIName(pDoc->GetUniqueTOXBaseName( *pType, rSource.GetTOXName().toString() ));
}

// TOX specific functions
SwTOXBase::~SwTOXBase()
{
//    if( GetTOXType()->GetType() == TOX_USER  )
//        delete aData.pTemplateName;
}

void SwTOXBase::SetTitle(const OUString& rTitle)
    {   m_aTitle = rTitle; }

void SwTOXBase::SetBookmarkName(const OUString& bName)
{
     m_aBookmarkName = bName;
}

SwTOXBase & SwTOXBase::operator = (const SwTOXBase & rSource)
{
    m_aForm = rSource.m_aForm;
    m_aName = rSource.m_aName;
    m_aTitle = rSource.m_aTitle;
    m_aBookmarkName = rSource.m_aBookmarkName;
    m_sMainEntryCharStyle = rSource.m_sMainEntryCharStyle;
    for(sal_uInt16 nLevel = 0; nLevel < MAXLEVEL; nLevel++)
        m_aStyleNames[nLevel] = rSource.m_aStyleNames[nLevel];
    m_sSequenceName = rSource.m_sSequenceName;
    m_eLanguage = rSource.m_eLanguage;
    m_sSortAlgorithm = rSource.m_sSortAlgorithm;
    m_aData = rSource.m_aData;
    m_nCreateType = rSource.m_nCreateType;
    m_nOLEOptions = rSource.m_nOLEOptions;
    m_eCaptionDisplay = rSource.m_eCaptionDisplay;
    m_bProtected = rSource.m_bProtected;
    m_bFromChapter = rSource.m_bFromChapter;
    m_bFromObjectNames = rSource.m_bFromObjectNames;
    m_bLevelFromChapter = rSource.m_bLevelFromChapter;

    if (rSource.GetAttrSet())
        SetAttrSet(*rSource.GetAttrSet());

    return *this;
}

OUString SwFormToken::GetString() const
{
    OUString sToken;

    switch( eTokenType )
    {
        case TOKEN_ENTRY_NO:
            sToken = SwForm::GetFormEntryNum();
        break;
        case TOKEN_ENTRY_TEXT:
            sToken = SwForm::GetFormEntryText();
        break;
        case TOKEN_ENTRY:
            sToken = SwForm::GetFormEntry();
        break;
        case TOKEN_TAB_STOP:
            sToken = SwForm::GetFormTab();
        break;
        case TOKEN_TEXT:
            // Return a Token only if Text is not empty!
            if( sText.isEmpty() )
            {
                return OUString();
            }
            sToken = SwForm::GetFormText();
        break;
        case TOKEN_PAGE_NUMS:
            sToken = SwForm::GetFormPageNums();
        break;
        case TOKEN_CHAPTER_INFO:
            sToken = SwForm::GetFormChapterMark();
        break;
        case TOKEN_LINK_START:
            sToken = SwForm::GetFormLinkStt();
        break;
        case TOKEN_LINK_END:
            sToken = SwForm::GetFormLinkEnd();
        break;
        case TOKEN_AUTHORITY:
        {
            sToken = SwForm::GetFormAuth();
        }
        break;
        case TOKEN_END:
        break;
    }

    OUString sData = " " + sCharStyleName.toString() + "," + OUString::number( nPoolId ) + ",";

    // TabStopPosition and TabAlign or ChapterInfoFormat
    switch (eTokenType)
    {
        case TOKEN_TAB_STOP:
            sData += OUString::number( nTabStopPosition ) + ","
                  +  OUString::number( static_cast< sal_Int32 >(eTabAlign) ) + ","
                  +  OUStringChar(cTabFillChar) + ","
                  +  OUString::number( bWithTab ? 1 : 0 );
            break;
        case TOKEN_CHAPTER_INFO:
        case TOKEN_ENTRY_NO:
            // add also maximum permitted level
            sData += OUString::number( nChapterFormat ) + ","
                  +  OUString::number( nOutlineLevel );
            break;
        case TOKEN_TEXT:
            sData += OUStringChar(TOX_STYLE_DELIMITER)
                  +  sText.replaceAll(OUStringChar(TOX_STYLE_DELIMITER), "")
                  +  OUStringChar(TOX_STYLE_DELIMITER);
            break;
        case TOKEN_AUTHORITY:
            if (nAuthorityField<10)
            {
                 sData = "0" + OUString::number( nAuthorityField ) + sData;
            }
            else
            {
                 sData = OUString::number( nAuthorityField ) + sData;
            }
            break;
        default:
            break;
    }

    return sToken.subView(0, sToken.getLength()-1) + sData + sToken.subView(sToken.getLength()-1);
}

// -> #i21237#

/**
   Returns the type of a token.

   @param sToken     the string representation of the token
   @param rTokenLen  return parameter the length of the head of the token

   @return the type of the token
*/

static FormTokenType lcl_GetTokenType(std::u16string_view sToken,
                                      sal_Int32 & rTokenLen)
{
    static struct
    {
        OUString sTokenStart;
        sal_Int16 nTokenLength;
        FormTokenType eTokenType;
    } const aTokenArr[] = {
        { SwForm::GetFormTab().copy(0, 2),         3, TOKEN_TAB_STOP },
        { SwForm::GetFormPageNums().copy(0, 2),    3, TOKEN_PAGE_NUMS },
        { SwForm::GetFormLinkStt().copy(0, 3),     4, TOKEN_LINK_START },
        { SwForm::GetFormLinkEnd().copy(0, 3),     4, TOKEN_LINK_END },
        { SwForm::GetFormEntryNum().copy(0, 3),    4, TOKEN_ENTRY_NO },
        { SwForm::GetFormEntryText().copy(0, 3),   4, TOKEN_ENTRY_TEXT },
        { SwForm::GetFormChapterMark().copy(0, 2), 3, TOKEN_CHAPTER_INFO },
        { SwForm::GetFormText().copy(0, 2),        3, TOKEN_TEXT },
        { SwForm::GetFormEntry().copy(0, 2),       3, TOKEN_ENTRY },
        { SwForm::GetFormAuth().copy(0, 2),        5, TOKEN_AUTHORITY }
    };

    for(const auto & i : aTokenArr)
    {
        if( o3tl::starts_with( sToken, i.sTokenStart ) )
        {
            rTokenLen = i.nTokenLength;
            return i.eTokenType;
        }
    }

    SAL_WARN("sw.core""SwFormTokensHelper: invalid token");
    return TOKEN_END;
}

/**
   Returns the string of a token.

   @param sPattern    the whole pattern
   @param nStt        starting position of the token

   @return   the string representation of the token
*/

static std::u16string_view
lcl_SearchNextToken(std::u16string_view sPattern, sal_Int32 const nStt)
{
    size_t nEnd = sPattern.find( u'>', nStt );
    if (nEnd != std::u16string_view::npos)
    {
        // apparently the TOX_STYLE_DELIMITER act as a bracketing for
        // TOKEN_TEXT tokens so that the user can have '>' inside the text...
        const size_t nTextSeparatorFirst = sPattern.find( TOX_STYLE_DELIMITER, nStt );
        if (    nTextSeparatorFirst != std::u16string_view::npos
            &&  nTextSeparatorFirst + 1 < sPattern.size()
            &&  nTextSeparatorFirst < nEnd)
        {
            const size_t nTextSeparatorSecond = sPattern.find( TOX_STYLE_DELIMITER,
                                                                     nTextSeparatorFirst + 1 );
            // Since nEnd>=0 we don't need to check if nTextSeparatorSecond==std::u16string_view::npos!
            if( nEnd < nTextSeparatorSecond )
                nEnd = sPattern.find( '>', nTextSeparatorSecond );
            // FIXME: No check to verify that nEnd is still >=0?
            assert(nEnd != std::u16string_view::npos);
        }

        ++nEnd;

        return sPattern.substr( nStt, nEnd - nStt );
    }

    return std::u16string_view();
}

/**
   Builds a token from its string representation.

   @sPattern          the whole pattern
   @nCurPatternPos    starting position of the token

   @return the token
 */

static std::optional<SwFormToken>
lcl_BuildToken(std::u16string_view sPattern, size_t & nCurPatternPos)
{
    std::u16string_view sToken( lcl_SearchNextToken(sPattern, nCurPatternPos) );
    nCurPatternPos += sToken.size();
    sal_Int32 nTokenLen = 0;
    FormTokenType const eTokenType = lcl_GetTokenType(sToken, nTokenLen);
    if (TOKEN_END == eTokenType) // invalid input? skip it
    {
        nCurPatternPos = sPattern.size();
        return std::optional<SwFormToken>();
    }

    // at this point sPattern contains the
    // character style name, the PoolId, tab stop position, tab stop alignment, chapter info format
    // the form is: CharStyleName, PoolId[, TabStopPosition|ChapterInfoFormat[, TabStopAlignment[, TabFillChar]]]
    // in text tokens the form differs from the others: CharStyleName, PoolId[,\0xffinserted text\0xff]
    SwFormToken eRet( eTokenType );
    const std::u16string_view sAuthFieldEnum = sToken.substr( 2, 2 );
    sToken = sToken.substr( nTokenLen, sToken.size() - nTokenLen - 1);

    sal_Int32 nIdx{ 0 };
    eRet.sCharStyleName = UIName(OUString(o3tl::getToken(sToken, 0, ',', nIdx )));
    std::u16string_view sTmp( o3tl::getToken(sToken, 0, ',', nIdx ));
    if( !sTmp.empty() )
        eRet.nPoolId = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sTmp));

    switch( eTokenType )
    {
//i53420
    case TOKEN_CHAPTER_INFO:
//i53420
    case TOKEN_ENTRY_NO:
        sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 2
        if( !sTmp.empty() )
            eRet.nChapterFormat = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sTmp));
        sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 3
        if( !sTmp.empty() )
            eRet.nOutlineLevel = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sTmp)); //the maximum outline level to examine
        break;

    case TOKEN_TEXT:
        {
            const size_t nStartText = sToken.find( TOX_STYLE_DELIMITER );
            if( nStartText != std::u16string_view::npos && nStartText+1<sToken.size())
            {
                const size_t nEndText = sToken.find( TOX_STYLE_DELIMITER,
                                                           nStartText + 1);
                if( nEndText != std::u16string_view::npos )
                {
                    eRet.sText = sToken.substr( nStartText + 1,
                                                nEndText - nStartText - 1);
                }
            }
        }
        break;

    case TOKEN_TAB_STOP:
        sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 2
        if( !sTmp.empty() )
            eRet.nTabStopPosition = o3tl::toInt32(sTmp);

        sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 3
        if( !sTmp.empty() )
            eRet.eTabAlign = static_cast<SvxTabAdjust>(o3tl::toInt32(sTmp));

        sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 4
        if( !sTmp.empty() )
            eRet.cTabFillChar = sTmp[0];

        sTmp = o3tl::getToken(sToken, 0, ',', nIdx ); // token 5
        if( !sTmp.empty() )
            eRet.bWithTab = 0 != o3tl::toInt32(sTmp);
        break;

    case TOKEN_AUTHORITY:
        eRet.nAuthorityField = o3tl::narrowing<sal_uInt16>(o3tl::toInt32(sAuthFieldEnum));
        break;
    defaultbreak;
    }
    return eRet;
}

SwFormTokensHelper::SwFormTokensHelper(std::u16string_view aPattern)
{
    size_t nCurPatternPos = 0;

    while (nCurPatternPos < aPattern.size())
    {
        std::optional<SwFormToken> const oToken(
                lcl_BuildToken(aPattern, nCurPatternPos));
        if (oToken)
            m_Tokens.push_back(*oToken);
    }
}

// <- #i21237#

void SwForm::SetPattern(sal_uInt16 nLevel, SwFormTokens&& rTokens)
{
    OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
    m_aPattern[nLevel] = std::move(rTokens);
}

void SwForm::SetPattern(sal_uInt16 nLevel, std::u16string_view aStr)
{
    OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");

    SwFormTokensHelper aHelper(aStr);
    m_aPattern[nLevel] = aHelper.GetTokens();
}

const SwFormTokens& SwForm::GetPattern(sal_uInt16 nLevel) const
{
    OSL_ENSURE(nLevel < GetFormMax(), "Index >= FORM_MAX");
    return m_aPattern[nLevel];
}

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

¤ Dauer der Verarbeitung: 0.27 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