Related: tdf#124601 DOC import: improve fLayoutInCell handling

There were 3 problems here:

First, SwWW8ImplReader::IsObjectLayoutInTableCell() should not use
m_nProduct to determine the Word version. It depends on an undocumented
field of the [MS-DOC] format and the bugdoc shows how it interprets a
Word 2007-produced document as a Word 97 one. Instead, parse the cswNew
field of the file header, which is a more or less documented way to find
out if this file was produced by >=2000 or 97.

See e.g.
<https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-doc/841b5f72-487e-4fe7-8657-ec90d5af8750>
where the Dop structure maps cswNew values to Word versions.

Second, parse the fLayoutInCell correctly: it's part of a bitfield, with
two variables: a bool and an other one which decides if the bool should
be read at all. The bugdoc's case was evaluated as false, so do the
proper parsing in that case and leave the existing logic as-is for now.

Third, there doesn't seem to be a reason to exclude the wrap-through
case for the fLayoutInCell -> follows-text-flow mapping. The bugdoc
shows that Word interprects fLayoutInCell the same way for wrap-though
objects, too.

Change-Id: Iaddd5e522e0380b731899f32a17c14ce4442ac35
Reviewed-on: https://gerrit.libreoffice.org/79629
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Jenkins
diff --git a/sw/qa/extras/ww8import/data/tdf124601.doc b/sw/qa/extras/ww8import/data/tdf124601.doc
new file mode 100644
index 0000000..f617d4b
--- /dev/null
+++ b/sw/qa/extras/ww8import/data/tdf124601.doc
Binary files differ
diff --git a/sw/qa/extras/ww8import/ww8import.cxx b/sw/qa/extras/ww8import/ww8import.cxx
index 41b97b0..363d6b7 100644
--- a/sw/qa/extras/ww8import/ww8import.cxx
+++ b/sw/qa/extras/ww8import/ww8import.cxx
@@ -86,6 +86,14 @@ DECLARE_WW8IMPORT_TEST(testTdf107773, "tdf107773.doc")
    CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), xDrawPage->getCount());
}

DECLARE_WW8IMPORT_TEST(testTdf124601, "tdf124601.doc")
{
    // Without the accompanying fix in place, this test would have failed, as the importer lost the
    // fLayoutInCell shape property for wrap-though shapes.
    CPPUNIT_ASSERT(getProperty<bool>(getShapeByName("Grafik 18"), "IsFollowingTextFlow"));
    CPPUNIT_ASSERT(getProperty<bool>(getShapeByName("Grafik 19"), "IsFollowingTextFlow"));
}

DECLARE_WW8IMPORT_TEST(testTdf112535, "tdf112535.doc")
{
    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
diff --git a/sw/source/filter/ww8/ww8graf.cxx b/sw/source/filter/ww8/ww8graf.cxx
index d3c4a10..a49d9de 100644
--- a/sw/source/filter/ww8/ww8graf.cxx
+++ b/sw/source/filter/ww8/ww8graf.cxx
@@ -2466,7 +2466,17 @@ bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTable

    if ( m_bVer8 )
    {
        const sal_uInt16 nWWVersion = m_xWwFib->m_nProduct & 0xE000;
        sal_uInt16 nWWVersion = m_xWwFib->m_nProduct & 0xE000;
        if (nWWVersion == 0)
        {
            // 0 nProduct can happen for Word >97 as well, check cswNew in this case instead.
            if (m_xWwFib->m_cswNew > 0)
            {
                // This is Word >=2000.
                nWWVersion = 0x2000;
            }
        }

        switch ( nWWVersion )
        {
            case 0x0000: // version 8 aka Microsoft Word 97
@@ -2494,7 +2504,10 @@ bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTable
                }
                else
                {
                    bIsObjectLayoutInTableCell = false;
                    // Documented in [MS-ODRAW], 2.3.4.44 "Group Shape Boolean Properties".
                    bool fUsefLayoutInCell = (nLayoutInTableCell & 0x80000000) >> 31;
                    bool fLayoutInCell = (nLayoutInTableCell & 0x8000) >> 15;
                    bIsObjectLayoutInTableCell = fUsefLayoutInCell && fLayoutInCell;
                }
            }
            break;
@@ -2695,8 +2708,8 @@ SwFrameFormat* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp )
        m_nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell );

    // #i18732# - Switch on 'follow text flow', if object is laid out
    // inside table cell and its wrapping isn't 'SURROUND_THROUGH'
    if (bLayoutInTableCell && eSurround != css::text::WrapTextMode_THROUGH)
    // inside table cell
    if (bLayoutInTableCell)
    {
        SwFormatFollowTextFlow aFollowTextFlow( true );
        aFlySet.Put( aFollowTextFlow );
diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx
index 4a79345..80a7bf8 100644
--- a/sw/source/filter/ww8/ww8scan.cxx
+++ b/sw/source/filter/ww8/ww8scan.cxx
@@ -5779,6 +5779,7 @@ WW8Fib::WW8Fib(SvStream& rSt, sal_uInt8 nWantedVersion, sal_uInt32 nOffset):
        // in C++20 with P06831R1 "Default member initializers for bit-fields (revision 1)", the
        // above bit-field member initializations can be moved to the class definition
{
    // See [MS-DOC] 2.5.15 "How to read the FIB".
    sal_uInt8 aBits1;
    sal_uInt8 aBits2;
    sal_uInt8 aVer8Bits1;    // only used starting with WinWord 8
@@ -5929,6 +5930,15 @@ WW8Fib::WW8Fib(SvStream& rSt, sal_uInt8 nWantedVersion, sal_uInt32 nOffset):
        rSt.ReadInt32( m_fcIslandFirst );
        rSt.ReadInt32( m_fcIslandLim );
        rSt.ReadUInt16( m_cfclcb );

        // Read cswNew to find out if nFib should be ignored.
        sal_uInt32 nPos = rSt.Tell();
        rSt.SeekRel(m_cfclcb * 8);
        if (rSt.good())
        {
            rSt.ReadUInt16(m_cswNew);
        }
        rSt.Seek(nPos);
    }

// end of the insertion for WW8
diff --git a/sw/source/filter/ww8/ww8scan.hxx b/sw/source/filter/ww8/ww8scan.hxx
index 807d4e6..a2dbffa 100644
--- a/sw/source/filter/ww8/ww8scan.hxx
+++ b/sw/source/filter/ww8/ww8scan.hxx
@@ -1232,6 +1232,8 @@ public:
    sal_Int32  m_fcIslandFirst = 0;   // ?
    sal_Int32  m_fcIslandLim = 0;     // ?
    sal_uInt16 m_cfclcb = 0; // Number of fields in the array of FC/LCB pairs.
    /// Specifies the count of 16-bit values corresponding to fibRgCswNew that follow.
    sal_uInt16 m_cswNew = 0;

    // end of WW8 section