tdf#100680 sw DOCX compatibility: fix wrap of as_char flys

New DOCX compatibility flag "WordLikeWrapForAsCharFlys"
has been introduced which true in case of importing DOCX
documents. It modifies the wrapping of long words
with as_char anchored flys anchored into the same line,
resulting e.g. correct import of poor man's header lines
drawn by using underline characters under an image.

Note: this example was imported as a broken header line:
half of it was there after the left aligned image in the
same line, and after the line break, only the other half
under the image.

Change-Id: I9474900ef778bcf5ddc9d95f39d536d67015f3b2
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132571
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/inc/IDocumentSettingAccess.hxx b/sw/inc/IDocumentSettingAccess.hxx
index 7de8674..4e434f2 100644
--- a/sw/inc/IDocumentSettingAccess.hxx
+++ b/sw/inc/IDocumentSettingAccess.hxx
@@ -119,6 +119,9 @@ enum class DocumentSettingId
    // footnoteContainer default position is the page end instead of the column end
    // only if "evenly distributed" is set, and "collected at the end" is not set
    FOOTNOTE_IN_COLUMN_TO_PAGEEND,
    // AsChar anchored flys wrapped differently in ooxlm than normally so in case of
    // docx enable this flag. For details see ticket tdf#100680.
    WRAP_AS_CHAR_FLYS_LIKE_IN_OOXML
};

/** Provides access to settings of a document
diff --git a/sw/qa/extras/layout/data/tdf100680.docx b/sw/qa/extras/layout/data/tdf100680.docx
new file mode 100644
index 0000000..c949540
--- /dev/null
+++ b/sw/qa/extras/layout/data/tdf100680.docx
Binary files differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 02b40c2..faf978d 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -93,6 +93,14 @@ void SwLayoutWriter2::CheckRedlineCharAttributesHidden()
    assertXPath(pXmlDoc, "/root/page[1]/body/txt[11]/Text[1]", "Portion", "foobaz");
}

CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf100680_as_char_wrap)
{
    createSwDoc(DATA_DIRECTORY, "tdf100680.docx");
    auto pDump = parseLayoutDump();
    assertXPath(pDump, "/root/page/header/txt/SwParaPortion/SwLineLayout[3]");
    // If the third line missing that assert will fire, as was before the fix.
}

CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineCharAttributes)
{
    createSwDoc(DATA_DIRECTORY, "redline_charatr.fodt");
diff --git a/sw/source/core/doc/DocumentSettingManager.cxx b/sw/source/core/doc/DocumentSettingManager.cxx
index 3e03097..851aec5 100644
--- a/sw/source/core/doc/DocumentSettingManager.cxx
+++ b/sw/source/core/doc/DocumentSettingManager.cxx
@@ -105,7 +105,8 @@ sw::DocumentSettingManager::DocumentSettingManager(SwDoc &rDoc)
    mbGutterAtTop(false),
    mbFootnoteInColumnToPageEnd(false),
    mnImagePreferredDPI(0),
    mbAutoFirstLineIndentDisregardLineSpace(true)
    mbAutoFirstLineIndentDisregardLineSpace(true),
    mbWrapAsCharFlysLikeInOOXML(false)

    // COMPATIBILITY FLAGS END
{
@@ -244,6 +245,7 @@ bool sw::DocumentSettingManager::get(/*[in]*/ DocumentSettingId id) const
        case DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND: return mbFootnoteInColumnToPageEnd;
        case DocumentSettingId::AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE:
            return mbAutoFirstLineIndentDisregardLineSpace;
        case DocumentSettingId::WRAP_AS_CHAR_FLYS_LIKE_IN_OOXML: return mbWrapAsCharFlysLikeInOOXML;
        default:
            OSL_FAIL("Invalid setting id");
    }
@@ -422,6 +424,10 @@ void sw::DocumentSettingManager::set(/*[in]*/ DocumentSettingId id, /*[in]*/ boo
            mbAutoFirstLineIndentDisregardLineSpace = value;
            break;

        case DocumentSettingId::WRAP_AS_CHAR_FLYS_LIKE_IN_OOXML:
            mbWrapAsCharFlysLikeInOOXML = value;
            break;

        // COMPATIBILITY FLAGS END

        case DocumentSettingId::BROWSE_MODE: //can be used temporary (load/save) when no SwViewShell is available
diff --git a/sw/source/core/inc/DocumentSettingManager.hxx b/sw/source/core/inc/DocumentSettingManager.hxx
index c687eb5..b6656a9 100644
--- a/sw/source/core/inc/DocumentSettingManager.hxx
+++ b/sw/source/core/inc/DocumentSettingManager.hxx
@@ -174,6 +174,8 @@ class DocumentSettingManager final :
    bool mbFootnoteInColumnToPageEnd;
    sal_Int32 mnImagePreferredDPI;
    bool mbAutoFirstLineIndentDisregardLineSpace;
    // If this is on as_char flys wrapping will be handled the same like in Word
    bool mbWrapAsCharFlysLikeInOOXML;

public:

diff --git a/sw/source/core/text/portxt.cxx b/sw/source/core/text/portxt.cxx
index cf827ab..140e29c 100644
--- a/sw/source/core/text/portxt.cxx
+++ b/sw/source/core/text/portxt.cxx
@@ -419,8 +419,11 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
    else
    {
        bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx();
        const bool bBreakLineIfHasFly
            = rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
                DocumentSettingId::WRAP_AS_CHAR_FLYS_LIKE_IN_OOXML);
        if (aGuess.BreakPos() != TextFrameIndex(COMPLETE_STRING) &&
            aGuess.BreakPos() != rInf.GetLineStart() &&
            (aGuess.BreakPos() != rInf.GetLineStart() || bBreakLineIfHasFly) &&
            ( !bFirstPor || rInf.GetFly() || rInf.GetLast()->IsFlyPortion() ||
              rInf.IsFirstMulti() ) &&
            ( !rInf.GetLast()->IsBlankPortion() ||
@@ -430,7 +433,7 @@ bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
        }
        else
             // case C2, last exit
            BreakCut( rInf, aGuess );
            BreakCut(rInf, aGuess);
    }

    return bFull;
diff --git a/sw/source/uibase/uno/SwXDocumentSettings.cxx b/sw/source/uibase/uno/SwXDocumentSettings.cxx
index 4cfda7b..49e6bae 100644
--- a/sw/source/uibase/uno/SwXDocumentSettings.cxx
+++ b/sw/source/uibase/uno/SwXDocumentSettings.cxx
@@ -152,6 +152,7 @@ enum SwDocumentSettingsPropertyHandles
    HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND,
    HANDLE_IMAGE_PREFERRED_DPI,
    HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE,
    HANDLE_WORD_LIKE_WRAP_FOR_AS_CHAR_FLYS
};

}
@@ -250,6 +251,7 @@ static rtl::Reference<MasterPropertySetInfo> lcl_createSettingsInfo()
        { OUString("FootnoteInColumnToPageEnd"), HANDLE_FOOTNOTE_IN_COLUMN_TO_PAGEEND, cppu::UnoType<bool>::get(), 0 },
        { OUString("ImagePreferredDPI"), HANDLE_IMAGE_PREFERRED_DPI, cppu::UnoType<sal_Int32>::get(), 0 },
        { OUString("AutoFirstLineIndentDisregardLineSpace"), HANDLE_AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE, cppu::UnoType<bool>::get(), 0 },
        { OUString("WordLikeWrapForAsCharFlys"), HANDLE_WORD_LIKE_WRAP_FOR_AS_CHAR_FLYS, cppu::UnoType<bool>::get(), 0 },

/*
 * As OS said, we don't have a view when we need to set this, so I have to
@@ -1051,6 +1053,14 @@ void SwXDocumentSettings::_setSingleValue( const comphelper::PropertyInfo & rInf
            }
        }
        break;
        case HANDLE_WORD_LIKE_WRAP_FOR_AS_CHAR_FLYS:
        {
            bool bValue = false;
            if (rValue >>= bValue)
                mpDoc->getIDocumentSettingAccess().set(
                    DocumentSettingId::WRAP_AS_CHAR_FLYS_LIKE_IN_OOXML, bValue);
        }
        break;
        default:
            throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
    }
@@ -1574,6 +1584,12 @@ void SwXDocumentSettings::_getSingleValue( const comphelper::PropertyInfo & rInf
                DocumentSettingId::AUTO_FIRST_LINE_INDENT_DISREGARD_LINE_SPACE);
        }
        break;
        case HANDLE_WORD_LIKE_WRAP_FOR_AS_CHAR_FLYS:
        {
            rValue <<= mpDoc->getIDocumentSettingAccess().get(
                DocumentSettingId::WRAP_AS_CHAR_FLYS_LIKE_IN_OOXML);
        }
        break;
        default:
            throw UnknownPropertyException(OUString::number(rInfo.mnHandle));
    }
diff --git a/writerfilter/source/filter/WriterFilter.cxx b/writerfilter/source/filter/WriterFilter.cxx
index 945a00f..5b87cb8 100644
--- a/writerfilter/source/filter/WriterFilter.cxx
+++ b/writerfilter/source/filter/WriterFilter.cxx
@@ -331,6 +331,7 @@ void WriterFilter::setTargetDocument(const uno::Reference<lang::XComponent>& xDo
    xSettings->setPropertyValue("PropLineSpacingShrinksFirstLine", uno::makeAny(true));
    xSettings->setPropertyValue("DoNotCaptureDrawObjsOnPage", uno::makeAny(true));
    xSettings->setPropertyValue("DisableOffPagePositioning", uno::makeAny(true));
    xSettings->setPropertyValue("WordLikeWrapForAsCharFlys", uno::makeAny(true));
}

void WriterFilter::setSourceDocument(const uno::Reference<lang::XComponent>& xDoc)