/* -*- 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 <hintids.hxx>
#include <vcl/font.hxx>
#include <editeng/langitem.hxx>
#include <doc.hxx>
#include <docary.hxx>
#include <numrule.hxx>
#include <charfmt.hxx>
#include <com/sun/star/i18n/ScriptType.hpp>
 
#include "sprmids.hxx"
 
#include "ww8attributeoutput.hxx"
#include "writerhelper.hxx"
#include "writerwordglue.hxx"
#include "wrtww8.hxx"
#include "ww8par.hxx"
 
using namespace ::com::sun::star;
 
SwNumRule* MSWordExportBase::DuplicateNumRuleImpl(const SwNumRule *pRule)
{
    const OUString sPrefix("WW8TempExport" + OUString::number( m_nUniqueList++ ));
    SwNumRule* pMyNumRule =
            new SwNumRule( m_rDoc.GetUniqueNumRuleName( &sPrefix ),
                           SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
    m_pUsedNumTable->push_back( pMyNumRule );
 
    for ( sal_uInt16 i = 0; i < MAXLEVEL; i++ )
    {
        const SwNumFormat& rSubRule = pRule->Get(i);
        pMyNumRule->Set( i, rSubRule );
    }
    return pMyNumRule;
}
 
sal_uInt16 MSWordExportBase::DuplicateNumRule(const SwNumRule* pRule, sal_uInt8 nLevel, sal_uInt16 nVal)
{
    SwNumRule* const pMyNumRule = DuplicateNumRuleImpl(pRule);
 
    SwNumFormat aNumFormat(pMyNumRule->Get(nLevel));
    aNumFormat.SetStart(nVal);
    pMyNumRule->Set(nLevel, aNumFormat);
 
    return GetNumberingId(*pMyNumRule);
}
 
// multiple SwList can be based on the same SwNumRule; ensure one w:abstractNum
// per SwList
sal_uInt16 MSWordExportBase::DuplicateAbsNum(OUString const& rListId,
        SwNumRule const& rAbstractRule)
{
    auto const it(m_Lists.find(rListId));
    if (it != m_Lists.end())
    {
        return it->second;
    }
    else
    {
        auto const pNewAbstractRule = DuplicateNumRuleImpl(&rAbstractRule);
        assert(GetNumberingId(*pNewAbstractRule) == m_pUsedNumTable->size() - 1);
        (void) pNewAbstractRule;
        m_Lists.insert(std::make_pair(rListId, m_pUsedNumTable->size() - 1));
        return m_pUsedNumTable->size() - 1;
    }
}
 
// Ideally we want to map SwList to w:abstractNum and SwNumRule to w:num
// The current approach is to keep exporting every SwNumRule to
// 1 w:abstractNum and 1 w:num, and then add extra w:num via this function
// that reference an existing w:abstractNum and may override its formatting;
// of course this will end up exporting some w:num that aren't actually used.
sal_uInt16 MSWordExportBase::OverrideNumRule(
        SwNumRule const& rExistingRule,
        OUString const& rListId,
        SwNumRule const& rAbstractRule)
{
    const sal_uInt16 numdef = GetNumberingId(rExistingRule);
 
    const sal_uInt16 absnumdef = rListId == rAbstractRule.GetDefaultListId()
        ? GetNumberingId(rAbstractRule)
        : DuplicateAbsNum(rListId, rAbstractRule);
    assert(numdef != USHRT_MAX);
    assert(absnumdef != USHRT_MAX);
    auto const mapping = std::make_pair(numdef, absnumdef);
 
    auto it = m_OverridingNums.insert(std::make_pair(m_pUsedNumTable->size(), mapping));
 
    m_pUsedNumTable->push_back(nullptr); // dummy, it's unique_ptr...
    ++m_nUniqueList; // counter for DuplicateNumRule...
 
    return it.first->first;
}
 
void MSWordExportBase::AddListLevelOverride(sal_uInt16 nListId,
    sal_uInt16 nLevelNum,
    sal_uInt16 nStartAt)
{
    m_ListLevelOverrides[nListId][nLevelNum] = nStartAt;
}
 
sal_uInt16 MSWordExportBase::GetNumberingId( const SwNumRule& rNumRule )
{
    if ( !m_pUsedNumTable )
    {
        m_pUsedNumTable.reset(new SwNumRuleTable);
        m_pUsedNumTable->insert( m_pUsedNumTable->begin(), m_rDoc.GetNumRuleTable().begin(), m_rDoc.GetNumRuleTable().end() );
        // Check, if the outline rule is already inserted into <pUsedNumTable>.
        // If yes, do not insert it again.
        bool bOutlineRuleAdded( false );
        for ( sal_uInt16 n = m_pUsedNumTable->size(); n; )
        {
            const SwNumRule& rRule = *(*m_pUsedNumTable)[ --n ];
            if (!m_rDoc.IsUsed(rRule))
            {
                m_pUsedNumTable->erase( m_pUsedNumTable->begin() + n );
            }
            else if ( &rRule == m_rDoc.GetOutlineNumRule() )
            {
                bOutlineRuleAdded = true;
            }
        }
 
        if ( !bOutlineRuleAdded )
        {
            // still need to paste the OutlineRule
            SwNumRule* pR = m_rDoc.GetOutlineNumRule();
            m_pUsedNumTable->push_back( pR );
        }
    }
    SwNumRule* p = const_cast<SwNumRule*>(&rNumRule);
    sal_uInt16 nRet = o3tl::narrowing<sal_uInt16>(m_pUsedNumTable->GetPos(p));
 
    return nRet;
}
 
// GetFirstLineOffset should problem never appear unadorned apart from
// here in the ww export filter
sal_Int16 GetWordFirstLineOffset(const SwNumFormat &rFormat)
{
    OSL_ENSURE( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
            "<GetWordFirstLineOffset> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
 
    short nFirstLineOffset;
    if (rFormat.GetNumAdjust() == SvxAdjust::Right)
        nFirstLineOffset = -rFormat.GetCharTextDistance();
    else
        nFirstLineOffset = rFormat.GetFirstLineOffset(); //TODO: overflow
    return nFirstLineOffset;
}
 
void WW8Export::WriteNumbering()
{
    if ( !m_pUsedNumTable )
        return; // no numbering is used
 
    // list formats - LSTF
    m_pFib->m_fcPlcfLst = m_pTableStrm->Tell();
    m_pTableStrm->WriteUInt16( m_pUsedNumTable->size() );
    NumberingDefinitions();
    // set len to FIB
    m_pFib->m_lcbPlcfLst = m_pTableStrm->Tell() - m_pFib->m_fcPlcfLst;
 
    // list formats - LVLF
    AbstractNumberingDefinitions();
 
    // list formats - LFO
    OutOverrideListTab();
 
    // list formats - ListNames
    OutListNamesTab();
}
 
void WW8AttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
{
    m_rWW8Export.m_pTableStrm->WriteUInt32( nId );
    m_rWW8Export.m_pTableStrm->WriteUInt32( nId );
 
    // not associated with a Style
    for ( int i = 0; i < WW8ListManager::nMaxLevel; ++i )
        m_rWW8Export.m_pTableStrm->WriteUInt16( 0xFFF );
 
    sal_uInt8 nFlags = 0;
    if ( rRule.IsContinusNum() )
        nFlags |= 0x1;
 
    m_rWW8Export.m_pTableStrm->WriteUChar( nFlags ).WriteUChar( 0/*nDummy*/ );
}
 
void MSWordExportBase::NumberingDefinitions()
{
    if ( !m_pUsedNumTable )
        return; // no numbering is used
 
    sal_uInt16 nCount = m_pUsedNumTable->size();
 
    // Write static data of SwNumRule - LSTF
    for ( sal_uInt16 n = 0; n < nCount; ++n )
    {
        const SwNumRule * pRule = (*m_pUsedNumTable)[ n ];
        if (pRule)
        {
            AttrOutput().NumberingDefinition(n + 1, *pRule);
        }
        else
        {
            auto it = m_OverridingNums.find(n);
            assert(it != m_OverridingNums.end());
            pRule = (*m_pUsedNumTable)[it->second.first];
            assert(pRule);
            AttrOutput().OverrideNumberingDefinition(*pRule, n + 1, it->second.second + 1, m_ListLevelOverrides[n]);
        }
    }
}
 
/**
 * Converts the SVX numbering type to MSONFC.
 *
 * This is used for special paragraph numbering considerations.
 */
static sal_uInt8 GetLevelNFC(sal_uInt16 eNumType, const SfxItemSet* pOutSet, sal_uInt8 nDefault)
{
    sal_uInt8 nRet = nDefault;
    switch( eNumType )
    {
    case SVX_NUM_NUMBER_LOWER_ZH:
        nRet = 35;
        if ( pOutSet ) {
            const SvxLanguageItem& rLang = pOutSet->Get( RES_CHRATR_CJK_LANGUAGE);
            const LanguageType eLang = rLang.GetLanguage();
            if (LANGUAGE_CHINESE_SIMPLIFIED ==eLang) {
                nRet = 39;
            }
        }
        break;
 
    // LVLF can't contain 0x08, msonfcHex.
    case style::NumberingType::SYMBOL_CHICAGO:
        // No SVX_NUM_SYMBOL_CHICAGO here: LVLF can't contain 0x09, msonfcChiManSty.
        nRet = 0;
        break;
    // LVLF can't contain 0x0F / 15, msonfcSbChar / decimalHalfWidth.
    // LVLF can't contain 0x13 / 19, msonfcDArabic / decimalFullWidth2
    }
    return nRet;
}
 
 
void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/,
        sal_uInt16 nStart,
        sal_uInt16 nNumberingType,
        SvxAdjust eAdjust,
        const sal_uInt8 *pNumLvlPos,
        sal_uInt8 nFollow,
        const wwFont *pFont,
        const SfxItemSet *pOutSet,
        sal_Int16 nIndentAt,
        sal_Int16 nFirstLineIndex,
        sal_Int16 nListTabPos,
        const OUString &rNumberingString,
        const SvxBrushItem* pBrush, //For i120928,to transfer graphic of bullet
        bool isLegal
    )
{
    // Start value
    m_rWW8Export.m_pTableStrm->WriteUInt32( nStart );
 
    // Type
    sal_uInt8 nNumId = GetLevelNFC(nNumberingType, pOutSet, WW8Export::GetNumId(nNumberingType));
    m_rWW8Export.m_pTableStrm->WriteUChar(nNumId);
 
    // Justification
    sal_uInt8 nAlign;
    switch ( eAdjust )
    {
    case SvxAdjust::Center:
        nAlign = 1;
        break;
    case SvxAdjust::Right:
        nAlign = 2;
        break;
    default:
        nAlign = 0;
        break;
    }
 
    if (isLegal)
    {
        // 3rd bit.
        nAlign |= 0x04;
    }
 
    m_rWW8Export.m_pTableStrm->WriteUChar( nAlign );
 
    // Write the rgbxchNums[9], positions of placeholders for paragraph
    // numbers in the text
    m_rWW8Export.m_pTableStrm->WriteBytes(pNumLvlPos, WW8ListManager::nMaxLevel);
 
    // Type of the character between the bullet and the text
    m_rWW8Export.m_pTableStrm->WriteUChar( nFollow );
 
    // dxaSoace/dxaIndent (Word 6 compatibility)
    m_rWW8Export.m_pTableStrm->WriteUInt32( 0 );
    m_rWW8Export.m_pTableStrm->WriteUInt32( 0 );
 
    // cbGrpprlChpx
    std::unique_ptr<ww::bytes> pCharAtrs;
    if ( pOutSet )
    {
        std::unique_ptr<ww::bytes> pOldpO = std::move(m_rWW8Export.m_pO);
        m_rWW8Export.m_pO.reset(new ww::bytes);
        if ( pFont )
        {
            sal_uInt16 nFontID = m_rWW8Export.m_aFontHelper.GetId( *pFont );
 
            m_rWW8Export.InsUInt16( NS_sprm::CRgFtc0::val );
            m_rWW8Export.InsUInt16( nFontID );
            m_rWW8Export.InsUInt16( NS_sprm::CRgFtc2::val );
            m_rWW8Export.InsUInt16( nFontID );
        }
 
        m_rWW8Export.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rWW8Export.m_bExportModeRTF );
        //For i120928,achieve graphic's index of bullet from the bullet bookmark
        if (SVX_NUM_BITMAP == nNumberingType && pBrush)
        {
            int nIndex = m_rWW8Export.GetGrfIndex(*pBrush);
            if ( nIndex != -1 )
            {
                m_rWW8Export.InsUInt16(NS_sprm::CPbiIBullet::val);
                m_rWW8Export.InsUInt32(nIndex);
                m_rWW8Export.InsUInt16(NS_sprm::CPbiGrf::val);
                m_rWW8Export.InsUInt16(1);
            }
        }
 
        pCharAtrs = std::move(m_rWW8Export.m_pO);
        m_rWW8Export.m_pO = std::move(pOldpO);
    }
    m_rWW8Export.m_pTableStrm->WriteUChar(sal_uInt8(pCharAtrs ? pCharAtrs->size() : 0));
 
    // cbGrpprlPapx
    sal_uInt8 aPapSprms [] = {
        0x5e, 0x84, 0, 0,               // sprmPDxaLeft
        0x60, 0x84, 0, 0,               // sprmPDxaLeft1
        0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06
    };
    m_rWW8Export.m_pTableStrm->WriteUChar( sal_uInt8( sizeof( aPapSprms ) ) );
 
    // reserved
    m_rWW8Export.m_pTableStrm->WriteUInt16( 0 );
 
    // pap sprms
    sal_uInt8* pData = aPapSprms + 2;
    Set_UInt16( pData, nIndentAt );
    pData += 2;
    Set_UInt16( pData, nFirstLineIndex );
    pData += 5;
    Set_UInt16( pData, nListTabPos );
 
    m_rWW8Export.m_pTableStrm->WriteBytes(aPapSprms, sizeof(aPapSprms));
 
    // write Chpx
    if (pCharAtrs && !pCharAtrs->empty())
        m_rWW8Export.m_pTableStrm->WriteBytes(pCharAtrs->data(), pCharAtrs->size());
 
    // write the num string
    m_rWW8Export.m_pTableStrm->WriteUInt16( rNumberingString.getLength() );
    SwWW8Writer::WriteString16( *m_rWW8Export.m_pTableStrm, rNumberingString, false );
}
 
void MSWordExportBase::AbstractNumberingDefinitions()
{
    sal_uInt16 nCount = m_pUsedNumTable->size();
    sal_uInt16 n;
 
    for( n = 0; n < nCount; ++n )
    {
        if (nullptr == (*m_pUsedNumTable)[ n ])
        {
            continue;
        }
 
        AttrOutput().StartAbstractNumbering( n + 1 );
 
        const SwNumRule& rRule = *(*m_pUsedNumTable)[ n ];
        sal_uInt8 nLvl;
        sal_uInt8 nLevels = static_cast< sal_uInt8 >(rRule.IsContinusNum() ?
            WW8ListManager::nMinLevel : WW8ListManager::nMaxLevel);
        for( nLvl = 0; nLvl < nLevels; ++nLvl )
        {
            NumberingLevel(rRule, nLvl);
        }
 
        AttrOutput().EndAbstractNumbering();
    }
}
 
void MSWordExportBase::NumberingLevel(
        SwNumRule const& rRule, sal_uInt8 const nLvl)
{
    // write the static data of the SwNumFormat of this level
    sal_uInt8 aNumLvlPos[WW8ListManager::nMaxLevel] = { 0,0,0,0,0,0,0,0,0 };
 
    const SwNumFormat& rFormat = rRule.Get( nLvl );
 
    sal_uInt8 nFollow = 0;
    // #i86652#
    if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
    {
        // <nFollow = 2>, if minimum label width equals 0 and
        // minimum distance between label and text equals 0
        nFollow = (rFormat.GetFirstLineOffset() == 0 &&
            rFormat.GetCharTextDistance() == 0)
            ? 2 : 0;     // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
    }
    else if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
    {
        switch (rFormat.GetLabelFollowedBy())
        {
            case SvxNumberFormat::LISTTAB:
            {
                // 0 (tab) unless there would be no content before the tab, in which case 2 (nothing)
                nFollow = (SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType()) ? 0 : 2;
            }
            break;
            case SvxNumberFormat::SPACE:
            {
                // 1 (space) unless there would be no content before the space in which case 2 (nothing)
                nFollow = (SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType()) ? 1 : 2;
            }
            break;
            case SvxNumberFormat::NOTHING:
            {
                nFollow = 2;
            }
            break;
            default:
            {
                nFollow = 0;
                OSL_FAIL( "unknown GetLabelFollowedBy() return value" );
            }
        }
    }
 
    // Build the NumString for this Level
    OUString sNumStr;
    OUString sFontName;
    bool bWriteBullet = false;
    std::optional<vcl::Font> pBulletFont;
    rtl_TextEncoding eChrSet=0;
    FontFamily eFamily=FAMILY_DECORATIVE;
    if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType() ||
        SVX_NUM_BITMAP == rFormat.GetNumberingType())
    {
        // Use bullet
        sal_UCS4 cBullet = rFormat.GetBulletChar();
        sNumStr = OUString(&cBullet, 1);
    }
    else
    {
        // Create level string
        if (rFormat.HasListFormat())
        {
            sal_uInt8* pLvlPos = aNumLvlPos;
            sNumStr = rFormat.GetListFormat();
 
            // now search the nums in the string
            for (sal_uInt8 i = 0; i <= nLvl; ++i)
            {
                OUString sSrch("%" + OUString::number(i+1) + "%");
                sal_Int32 nFnd = sNumStr.indexOf(sSrch);
                if (-1 != nFnd)
                {
                    sal_Int32 nLen = sSrch.getLength();
                    if (i < nLvl && rRule.Get(i).GetNumberingType() == SVX_NUM_NUMBER_NONE)
                    {
                        // LO doesn't show this level, so don't export its separator
                        const OUString sSrch2("%" + OUString::number(i + 2) + "%");
                        const sal_Int32 nFnd2 = sNumStr.indexOf(sSrch2, nFnd);
                        if (-1 != nFnd2)
                            nLen = nFnd2 - nFnd;
                    }
                    *pLvlPos = static_cast<sal_uInt8>(nFnd + 1);
                    ++pLvlPos;
                    sNumStr = sNumStr.replaceAt(nFnd, nLen, OUStringChar(static_cast<char>(i)));
                }
            }
        }
        else if (rFormat.GetNumberingType() != SVX_NUM_NUMBER_NONE)
            assert(false && "deprecated format still exists and is unhandled. Inform Vasily or Justin");
    }
 
    if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType() ||
        SVX_NUM_BITMAP == rFormat.GetNumberingType())
    {
        bWriteBullet = true;
 
        pBulletFont = rFormat.GetBulletFont();
        if (!pBulletFont)
        {
            pBulletFont = numfunc::GetDefBulletFont();
        }
 
        eChrSet = pBulletFont->GetCharSet();
        sFontName = pBulletFont->GetFamilyName();
        eFamily = pBulletFont->GetFamilyType();
 
        if (IsOpenSymbol(sFontName))
            SubstituteBullet(sNumStr, eChrSet, sFontName);
    }
 
    // Attributes of the numbering
    std::unique_ptr<wwFont> pPseudoFont;
    const SfxItemSet* pOutSet = nullptr;
 
    // cbGrpprlChpx
    SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END> aSet( m_rDoc.GetAttrPool() );
    if (rFormat.GetCharFormat() || bWriteBullet)
    {
        if (bWriteBullet)
        {
            pOutSet = &aSet;
 
            if (rFormat.GetCharFormat())
                aSet.Put( rFormat.GetCharFormat()->GetAttrSet() );
            aSet.ClearItem( RES_CHRATR_CJK_FONT );
            aSet.ClearItem( RES_CHRATR_FONT );
 
            if (sFontName.isEmpty())
                sFontName = pBulletFont->GetFamilyName();
 
            pPseudoFont.reset(new wwFont( sFontName, pBulletFont->GetPitch(),
                eFamily, eChrSet));
        }
        else
            pOutSet = &rFormat.GetCharFormat()->GetAttrSet();
    }
 
    sal_Int16 nIndentAt = 0;
    sal_Int16 nFirstLineIndex = 0;
    sal_Int16 nListTabPos = -1;
 
    // #i86652#
    if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
    {
        nIndentAt = nListTabPos = rFormat.GetAbsLSpace(); //TODO: overflow
        nFirstLineIndex = GetWordFirstLineOffset(rFormat);
    }
    else if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT)
    {
        nIndentAt = static_cast<sal_Int16>(rFormat.GetIndentAt());
        nFirstLineIndex = static_cast<sal_Int16>(rFormat.GetFirstLineIndent());
        nListTabPos = rFormat.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB?
                      static_cast<sal_Int16>( rFormat.GetListtabPos() ) : 0;
    }
 
    AttrOutput().NumberingLevel( nLvl,
            rFormat.GetStart(),
            rFormat.GetNumberingType(),
            rFormat.GetNumAdjust(),
            aNumLvlPos,
            nFollow,
            pPseudoFont.get(), pOutSet,
            nIndentAt, nFirstLineIndex, nListTabPos,
            sNumStr,
            rFormat.GetNumberingType()==SVX_NUM_BITMAP ? rFormat.GetBrush() : nullptr, rFormat.GetIsLegal());
}
 
void WW8Export::OutOverrideListTab()
{
    if( !m_pUsedNumTable )
        return ;            // no numbering is used
 
    // write the "list format override" - LFO
    sal_uInt16 nCount = m_pUsedNumTable->size();
    sal_uInt16 n;
 
    m_pFib->m_fcPlfLfo = m_pTableStrm->Tell();
    m_pTableStrm->WriteUInt32( nCount );
 
    // LFO ([MS-DOC] 2.9.131)
    for( n = 0; n < nCount; ++n )
    {
        m_pTableStrm->WriteUInt32( n + 1 );
        SwWW8Writer::FillCount( *m_pTableStrm, 12 );
    }
    // LFOData ([MS-DOC] 2.9.132)
    for( n = 0; n < nCount; ++n )
        m_pTableStrm->WriteInt32( -1 );  // no overwrite
 
    // set len to FIB
    m_pFib->m_lcbPlfLfo = m_pTableStrm->Tell() - m_pFib->m_fcPlfLfo;
}
 
void WW8Export::OutListNamesTab()
{
    if( !m_pUsedNumTable )
        return ;            // no numbering is used
 
    // write the "list format override" - LFO
    sal_uInt16 nNms = 0, nCount = m_pUsedNumTable->size();
 
    m_pFib->m_fcSttbListNames = m_pTableStrm->Tell();
    m_pTableStrm->WriteInt16( -1 );
    m_pTableStrm->WriteUInt32( nCount );
 
    for( ; nNms < nCount; ++nNms )
    {
        const SwNumRule& rRule = *(*m_pUsedNumTable)[ nNms ];
        OUString sNm;
        if( !rRule.IsAutoRule() )
            sNm = rRule.GetName();
 
        m_pTableStrm->WriteUInt16( sNm.getLength() );
        if (!sNm.isEmpty())
            SwWW8Writer::WriteString16(*m_pTableStrm, sNm, false);
    }
 
    SwWW8Writer::WriteLong( *m_pTableStrm, m_pFib->m_fcSttbListNames + 2, nNms );
    // set len to FIB
    m_pFib->m_lcbSttbListNames = m_pTableStrm->Tell() - m_pFib->m_fcSttbListNames;
}
 
void MSWordExportBase::SubstituteBullet( OUString& rNumStr,
    rtl_TextEncoding& rChrSet, OUString& rFontName ) const
{
    if (!m_bSubstituteBullets)
        return;
    OUString sFontName = rFontName;
 
    // If Bullet char is "", don't change
    if (rNumStr[0] != u'\0')
    {
        rNumStr = rNumStr.replaceAt(0, 1, rtl::OUStringChar(
            msfilter::util::bestFitOpenSymbolToMSFont(rNumStr[0], rChrSet, sFontName)));
    }
 
    rFontName = sFontName;
}
 
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

V1007 The value from the potentially uninitialized optional 'pBulletFont' is used. Probably it is a mistake.

V1007 The value from the potentially uninitialized optional 'pBulletFont' is used. Probably it is a mistake.

V1029 Numeric Truncation Error. Return value of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Return value of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Return value of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Return value of the 'size' function is written to the 16-bit variable.

V1029 Numeric Truncation Error. Return value of the 'size' function is written to the 16-bit variable.