sw/qa/extras/uiwriter/data/placeholder-bold.fodt |  114 +++++++++++++++++++++++
 sw/qa/extras/uiwriter/uiwriter3.cxx              |   49 +++++++++
 sw/source/filter/html/swhtml.cxx                 |   14 ++
 sw/source/filter/html/swhtml.hxx                 |    2 
 4 files changed, 179 insertions(+)

New commits:
commit f45d2fa85ba89eb7d71b51c3324f5938509b3201
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Thu Aug 8 17:41:05 2024 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Fri Aug 9 13:57:07 2024 +0200

    sw: HTML import: apply existing hard formatting at insert position
    
    When selecting a placeholder field and pasting some HTML over it, the
    existing formatting of the placeholder field is inconsistently retained
    on the first paragraph of the pasted text, but not on subsequent ones.
    
    Fix this by retaining it on all of the pasted text; copy it after doing
    the 2 SplitNode() calls in SwHTMLParser::CallParser() and apply it
    directly to new paragraphs in SwHTMLParser::SetTextCollAttrs() after
    applying the paragraph style (which resets hard formatting).
    
    Change-Id: I8c3596372b415fece46f6bb018cb8c26ff89c5ad
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171648
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/qa/extras/uiwriter/data/placeholder-bold.fodt 
b/sw/qa/extras/uiwriter/data/placeholder-bold.fodt
new file mode 100644
index 000000000000..55ecf66df714
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data/placeholder-bold.fodt
@@ -0,0 +1,114 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<office:document xmlns:css3t="http://www.w3.org/TR/css3-text/"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; xmlns:c
 alcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:
 meta:1.0" 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text">
+ 
<office:meta><meta:creation-date>2024-08-08T18:32:28.420082817</meta:creation-date><dc:date>2024-08-08T18:33:51.021911316</dc:date><meta:editing-duration>PT1M27S</meta:editing-duration><meta:editing-cycles>1</meta:editing-cycles><meta:document-statistic
 meta:table-count="0" meta:image-count="0" meta:object-count="0" 
meta:page-count="1" meta:paragraph-count="1" meta:word-count="3" 
meta:character-count="21" 
meta:non-whitespace-character-count="19"/><meta:generator>ZetaOffice/7.4.8.0.0$Linux_X86_64
 
LibreOffice_project/ab7057b1137e2241f51e62b58a0c605ec9a4b29c</meta:generator></office:meta>
+ <office:font-face-decls>
+  <style:font-face style:name="Arial Unicode MS1" svg:font-family="'Arial 
Unicode MS'" style:font-family-generic="system" style:font-pitch="variable"/>
+  <style:font-face style:name="Liberation Serif" svg:font-family="'Liberation 
Serif'" style:font-family-generic="roman" style:font-pitch="variable"/>
+  <style:font-face style:name="Noto Serif CJK SC" svg:font-family="'Noto Serif 
CJK SC'" style:font-family-generic="system" style:font-pitch="variable"/>
+ </office:font-face-decls>
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" 
draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" 
draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" 
draw:start-line-spacing-vertical="0.283cm" 
draw:end-line-spacing-horizontal="0.283cm" 
draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" 
style:line-break="strict" style:writing-mode="lr-tb" 
style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" loext:color-lum-mod="100%" loext:color-lum-off="0%" 
style:font-name="Liberation Serif" fo:font-size="12pt" fo:language="de" 
fo:country="DE" style:letter-kerning="true" style:font-name-asian="Noto Serif 
CJK SC" style:font-size-asian="10.5pt" style:language-asian="zh" 
style:country-asian="CN" style:font-name-complex="Arial Unicode MS1" 
style:font-size-complex="12pt" style:language-complex="hi" 
style:country-complex="IN"/>
+  </style:default-style>
+  <style:default-style style:family="paragraph">
+   <style:paragraph-properties fo:orphans="2" fo:widows="2" 
fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" 
style:punctuation-wrap="hanging" style:line-break="strict" 
style:tab-stop-distance="1.251cm" style:writing-mode="page"/>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="de" fo:country="DE" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="Arial Unicode MS1" style:font-size-complex="12pt" 
style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" 
fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" 
loext:hyphenation-no-caps="false" loext:hyphenation-no-last-word="false" 
loext:hyphenation-word-char-count="5" loext:hyphenation-zone="no-limit"/>
+  </style:default-style>
+  <style:default-style style:family="table">
+   <style:table-properties table:border-model="collapsing"/>
+  </style:default-style>
+  <style:default-style style:family="table-row">
+   <style:table-row-properties fo:keep-together="auto"/>
+  </style:default-style>
+  <style:style style:name="Standard" style:family="paragraph" 
style:class="text"/>
+  <text:outline-style style:name="Outline">
+   <text:outline-level-style text:level="1" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="2" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="3" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="4" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="5" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="6" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="7" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="8" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="9" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+   <text:outline-level-style text:level="10" style:num-format="">
+    <style:list-level-properties 
text:list-level-position-and-space-mode="label-alignment">
+     <style:list-level-label-alignment text:label-followed-by="listtab"/>
+    </style:list-level-properties>
+   </text:outline-level-style>
+  </text:outline-style>
+  <text:notes-configuration text:note-class="footnote" style:num-format="1" 
text:start-value="0" text:footnotes-position="page" 
text:start-numbering-at="document"/>
+  <text:notes-configuration text:note-class="endnote" style:num-format="i" 
text:start-value="0"/>
+  <text:linenumbering-configuration text:number-lines="false" 
text:offset="0.499cm" style:num-format="1" text:number-position="left" 
text:increment="5"/>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="P1" style:family="paragraph" 
style:parent-style-name="Standard">
+   <style:text-properties/>
+  </style:style>
+  <style:style style:name="T1" style:family="text">
+   <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" 
style:font-weight-complex="bold"/>
+  </style:style>
+  <style:page-layout style:name="pm1">
+   <style:page-layout-properties fo:page-width="21.001cm" 
fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" 
fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" 
fo:margin-right="2cm" style:writing-mode="lr-tb" 
style:footnote-max-height="0cm" loext:margin-gutter="0cm">
+    <style:footnote-sep style:width="0.018cm" 
style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" 
style:line-style="solid" style:adjustment="left" style:rel-width="25%" 
style:color="#000000"/>
+   </style:page-layout-properties>
+   <style:header-style/>
+   <style:footer-style/>
+  </style:page-layout>
+ </office:automatic-styles>
+ <office:master-styles>
+  <style:master-page style:name="Standard" style:page-layout-name="pm1"/>
+ </office:master-styles>
+ <office:body>
+  <office:text>
+   <text:sequence-decls>
+    <text:sequence-decl text:display-outline-level="0" 
text:name="Illustration"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
+   </text:sequence-decls>
+   <text:p text:style-name="P1">Test <text:span 
text:style-name="T1"><text:placeholder text:placeholder-type="text" 
text:description="to be 
replaced">&lt;replaceme&gt;</text:placeholder></text:span><text:s/>test</text:p>
+  </office:text>
+ </office:body>
+</office:document>
\ No newline at end of file
diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx 
b/sw/qa/extras/uiwriter/uiwriter3.cxx
index ecd1f07a7d99..870b0fb80800 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -10,6 +10,7 @@
 #include <swmodeltestbase.hxx>
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <vcl/scheduler.hxx>
+#include <com/sun/star/awt/FontWeight.hpp>
 #include <com/sun/star/table/TableBorder2.hpp>
 #include <com/sun/star/text/XDocumentIndex.hpp>
 #include <com/sun/star/text/XTextFrame.hpp>
@@ -39,6 +40,54 @@ public:
     }
 };
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testPlaceholderHTMLPaste)
+{
+    {
+        createSwDoc();
+
+        SwDoc* const pDoc = getSwDoc();
+        SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+        pWrtShell->Insert(u"AAA"_ustr);
+        pWrtShell->SplitNode();
+        pWrtShell->Insert(u"BBB"_ustr);
+        pWrtShell->SplitNode();
+        pWrtShell->Insert(u"CCC"_ustr);
+
+        dispatchCommand(mxComponent, u".uno:SelectAll"_ustr, {});
+        dispatchCommand(mxComponent, u".uno:Copy"_ustr, {});
+    }
+
+    createSwDoc("placeholder-bold.fodt");
+
+    // select placeholder field
+    SwDoc* const pDoc = getSwDoc();
+    SwWrtShell* const pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/false, 5, 
/*bBasicCall=*/false);
+    pWrtShell->Right(SwCursorSkipMode::Chars, /*bSelect=*/true, 1, 
/*bBasicCall=*/false);
+
+    // Paste special as HTML
+    uno::Sequence<beans::PropertyValue> aPropertyValues = 
comphelper::InitPropertySequence(
+        { { "SelectedFormat", 
uno::Any(static_cast<sal_uInt32>(SotClipboardFormatId::HTML)) } });
+
+    dispatchCommand(mxComponent, u".uno:ClipboardFormatItems"_ustr, 
aPropertyValues);
+
+    CPPUNIT_ASSERT_EQUAL(int(4), getParagraphs());
+
+    CPPUNIT_ASSERT_EQUAL(
+        awt::FontWeight::NORMAL,
+        getProperty<float>(getRun(getParagraph(1), 1, u"Test "_ustr), 
u"CharWeight"_ustr));
+    CPPUNIT_ASSERT_EQUAL(
+        awt::FontWeight::BOLD,
+        getProperty<float>(getRun(getParagraph(1), 2, u"AAA"_ustr), 
u"CharWeight"_ustr));
+    CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
+                         getProperty<float>(getParagraph(2), 
u"CharWeight"_ustr));
+    CPPUNIT_ASSERT_EQUAL(awt::FontWeight::BOLD,
+                         getProperty<float>(getParagraph(3), 
u"CharWeight"_ustr));
+    CPPUNIT_ASSERT_EQUAL(
+        awt::FontWeight::NORMAL,
+        getProperty<float>(getRun(getParagraph(4), 1, u" test"_ustr), 
u"CharWeight"_ustr));
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf151974)
 {
     createSwDoc("tdf151974.odt");
diff --git a/sw/source/filter/html/swhtml.cxx b/sw/source/filter/html/swhtml.cxx
index 767ce605fbf7..3ce6c858d3ab 100644
--- a/sw/source/filter/html/swhtml.cxx
+++ b/sw/source/filter/html/swhtml.cxx
@@ -578,6 +578,13 @@ SvParserState SwHTMLParser::CallParser()
         aInsertionRangePam.Move( fnMoveBackward );
         m_xDoc->getIDocumentRedlineAccess().SplitRedline( aInsertionRangePam );
 
+        if (SwAttrSet const*const pAttrs = 
pPos->GetNode().GetTextNode()->GetpSwAttrSet())
+        {
+            m_pTargetCharAttrs.reset(new SfxItemSet(*pAttrs->GetPool(),
+                        svl::Items<RES_CHRATR_BEGIN, RES_CHRATR_END-1>));
+            m_pTargetCharAttrs->Put(*pAttrs);
+        }
+
         m_xDoc->SetTextFormatColl( *m_pPam,
                 m_pCSS1Parser->GetTextCollFromPool( RES_POOLCOLL_STANDARD ));
     }
@@ -4812,6 +4819,13 @@ void SwHTMLParser::SetTextCollAttrs( HTMLAttrContext 
*pContext )
     // set the style
     m_xDoc->SetTextFormatColl( *m_pPam, pCollToSet );
 
+    if (m_pTargetCharAttrs)
+    {
+        std::unique_ptr<SfxItemSet> const pCharSet(new 
SfxItemSet(*m_pTargetCharAttrs));
+        pCharSet->Differentiate(pCollToSet->GetAttrSet());
+        m_xDoc->getIDocumentContentOperations().InsertItemSet(*m_pPam, 
*pCharSet);
+    }
+
     // if applicable correct the paragraph indent
     const SvxFirstLineIndentItem & rFirstLine = 
pCollToSet->GetFirstLineIndent();
     const SvxTextLeftMarginItem & rTextLeftMargin = 
pCollToSet->GetTextLeftMargin();
diff --git a/sw/source/filter/html/swhtml.hxx b/sw/source/filter/html/swhtml.hxx
index 33f03ecf3fc3..1f50803633dc 100644
--- a/sw/source/filter/html/swhtml.hxx
+++ b/sw/source/filter/html/swhtml.hxx
@@ -500,6 +500,8 @@ class SwHTMLParser : public SfxHTMLParser, public 
SvtListener
     /// This is the URL of the outer <object> data if it's not OLE2 or an 
image.
     OUString m_aEmbedURL;
 
+    std::unique_ptr<SfxItemSet> m_pTargetCharAttrs;
+
     void DeleteFormImpl();
 
     void DocumentDetected();

Reply via email to