tdf#132766: DOCX export: always try to set bullet font for list

There are some problems with bullet if we use MS Wingdigs bullets
and do not specify Symbol font for it. It shiuld be either UTF-8
or Symbol, but not mixture of both.

Change-Id: Ie4a6f7e8fee6cfab21a18fc080f33d1bff455dd9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93846
Tested-by: Jenkins
Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de>
diff --git a/sw/qa/extras/ooxmlexport/data/tdf132766.docx b/sw/qa/extras/ooxmlexport/data/tdf132766.docx
new file mode 100644
index 0000000..aba5e82
--- /dev/null
+++ b/sw/qa/extras/ooxmlexport/data/tdf132766.docx
Binary files differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
index e9fbd794..7fd2ec0 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport12.cxx
@@ -955,19 +955,14 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf94628, "tdf94628.docx")
    uno::Sequence<beans::PropertyValue> aProps;
    xLevels->getByIndex(0) >>= aProps; // 1st level

    for (int i = 0; i < aProps.getLength(); ++i)
    {
        const beans::PropertyValue& rProp = aProps[i];
        if (rProp.Name == "BulletChar")
        {
            // Check for 'BLACK UPPER RIGHT TRIANGLE' (U+25E5) as a bullet
            CPPUNIT_ASSERT_EQUAL(OUString(u"\u25E5"), rProp.Value.get<OUString>());
            return;
        }
    }

    // Shouldn't reach here
    CPPUNIT_FAIL("Did not find bullet with level 0");
    OUString sBulletChar = std::find_if(aProps.begin(), aProps.end(),
                                        [](const beans::PropertyValue& rValue) {
                                            return rValue.Name == "BulletChar";
                                        })
                               ->Value.get<OUString>();
    // Actually for 'BLACK UPPER RIGHT TRIANGLE' is \u25E5
    // But we use Wingdings 3 font here, so code is different
    CPPUNIT_ASSERT_EQUAL(OUString(u"\uF07B"), sBulletChar);
}

DECLARE_OOXMLEXPORT_TEST(testTdf122594, "tdf122594.docx")
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
index 3f26169d..fb1519d 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport14.cxx
@@ -680,6 +680,22 @@ CPPUNIT_TEST_FIXTURE(SwModelTestBase, testUserField)
    assertXPath(pXmlDoc, "//w:docVars/w:docVar", "val", "bar");
}

DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testTdf132766, "tdf132766.docx")
{
    xmlDocUniquePtr pXmlDoc = parseExport("word/numbering.xml");
    CPPUNIT_ASSERT(pXmlDoc);

    // Ensure that for list=1 and level=0 we wrote correct bullet char and correct font
    assertXPath(pXmlDoc, "//w:numbering/w:abstractNum[@w:abstractNumId='1']/w:lvl[@w:ilvl='0']/w:lvlText",
                "val", u"\uF0B7");
    assertXPath(pXmlDoc, "//w:numbering/w:abstractNum[@w:abstractNumId='1']/w:lvl[@w:ilvl='0']/w:rPr/w:rFonts",
                "ascii", "Symbol");
    assertXPath(pXmlDoc, "//w:numbering/w:abstractNum[@w:abstractNumId='1']/w:lvl[@w:ilvl='0']/w:rPr/w:rFonts",
                "hAnsi", "Symbol");
    assertXPath(pXmlDoc, "//w:numbering/w:abstractNum[@w:abstractNumId='1']/w:lvl[@w:ilvl='0']/w:rPr/w:rFonts",
                "cs", "Symbol");
}

DECLARE_OOXMLEXPORT_TEST(testTdf124367, "tdf124367.docx")
{
    CPPUNIT_ASSERT_EQUAL(1, getPages());
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
index 22cad9d..7c576e2 100644
--- a/sw/source/filter/ww8/docxattributeoutput.cxx
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -6988,7 +6988,10 @@ void DocxAttributeOutput::NumberingLevel( sal_uInt8 nLevel,
                    FSNS( XML_w, XML_cs ), aFamilyName,
                    FSNS( XML_w, XML_hint ), "default" );
        }
        m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.m_bExportModeRTF );
        else
        {
            m_rExport.OutputItemSet(*pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.m_bExportModeRTF);
        }

        WriteCollectedRunProperties();

diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx
index cc6795a..ca3a026 100644
--- a/sw/source/filter/ww8/wrtw8num.cxx
+++ b/sw/source/filter/ww8/wrtw8num.cxx
@@ -452,7 +452,11 @@ void MSWordExportBase::NumberingLevel(
    // #i86652#
    if (rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION)
    {
        nFollow = 2;     // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
        // <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)
    {
@@ -490,44 +494,20 @@ void MSWordExportBase::NumberingLevel(
    const vcl::Font* pBulletFont=nullptr;
    rtl_TextEncoding eChrSet=0;
    FontFamily eFamily=FAMILY_DECORATIVE;

    if (!rRule.Get(nLvl).GetListFormat().isEmpty())
    {
        // We have stored list format, use it
        // Nothing to construct: we have it already
        sNumStr = rRule.Get(nLvl).GetListFormat();
    }
    else if (SVX_NUM_CHAR_SPECIAL == rFormat.GetNumberingType() ||
        SVX_NUM_BITMAP == rFormat.GetNumberingType())
    {
        // Use bullet
        sNumStr = OUString(rFormat.GetBulletChar());
        bWriteBullet = true;

        pBulletFont = rFormat.GetBulletFont();
        if (!pBulletFont)
        {
            pBulletFont = &numfunc::GetDefBulletFont();
        }

        eChrSet = pBulletFont->GetCharSet();
        sFontName = pBulletFont->GetFamilyName();
        eFamily = pBulletFont->GetFamilyType();

        if (IsStarSymbol(sFontName))
            SubstituteBullet( sNumStr, eChrSet, sFontName );

        // #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
    {
        // Construct list format string from prefix, level numbers and suffix
        if (SVX_NUM_NUMBER_NONE != rFormat.GetNumberingType())
        {
            sal_uInt8* pLvlPos = aNumLvlPos;
@@ -547,16 +527,6 @@ void MSWordExportBase::NumberingLevel(
                    sNumStr = sNumStr.replaceAt( nFnd, 1, OUString(static_cast<char>(i)) );
                }
            }
            // #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
            }
        }

        if (!rFormat.GetPrefix().isEmpty())
@@ -564,6 +534,25 @@ void MSWordExportBase::NumberingLevel(
        sNumStr += rFormat.GetSuffix();
    }

    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 (IsStarSymbol(sFontName))
            SubstituteBullet(sNumStr, eChrSet, sFontName);
    }

    // Attributes of the numbering
    std::unique_ptr<wwFont> pPseudoFont;
    const SfxItemSet* pOutSet = nullptr;