summaryrefslogtreecommitdiffstats
path: root/editeng
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 09:29:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 09:29:03 +0000
commit5a7157d319477830426797532e02ac39d3b859f4 (patch)
tree3773f5ce209bee14a5643e98672e0f3828c71434 /editeng
parentReleasing progress-linux version 4:24.2.0-3~progress7.99u1. (diff)
downloadlibreoffice-5a7157d319477830426797532e02ac39d3b859f4.tar.xz
libreoffice-5a7157d319477830426797532e02ac39d3b859f4.zip
Merging upstream version 4:24.2.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'editeng')
-rw-r--r--editeng/qa/unit/core-test.cxx92
-rw-r--r--editeng/source/editeng/editeng.cxx7
-rw-r--r--editeng/source/editeng/impedit2.cxx26
-rw-r--r--editeng/source/editeng/impedit4.cxx2
-rw-r--r--editeng/source/misc/acorrcfg.cxx7
5 files changed, 128 insertions, 6 deletions
diff --git a/editeng/qa/unit/core-test.cxx b/editeng/qa/unit/core-test.cxx
index b5320f90e4..8d2a6c11d4 100644
--- a/editeng/qa/unit/core-test.cxx
+++ b/editeng/qa/unit/core-test.cxx
@@ -34,6 +34,7 @@
#include <editeng/fhgtitem.hxx>
#include <com/sun/star/text/textfield/Type.hpp>
+#include <com/sun/star/datatransfer/XTransferable.hpp>
#include <memory>
#include <editeng/outliner.hxx>
@@ -79,6 +80,12 @@ public:
/// Test Copy/Paste using Legacy Format
void testCopyPaste();
+ /// Test Paste using HTML
+ void testHTMLPaste();
+
+ /// Test Paste using an HTML fragment
+ void testHTMLFragmentPaste();
+
/// Test Copy/Paste with selective selection over multiple paragraphs
void testMultiParaSelCopyPaste();
@@ -125,6 +132,8 @@ public:
CPPUNIT_TEST(testAutocorrect);
CPPUNIT_TEST(testHyperlinkCopyPaste);
CPPUNIT_TEST(testCopyPaste);
+ CPPUNIT_TEST(testHTMLPaste);
+ CPPUNIT_TEST(testHTMLFragmentPaste);
CPPUNIT_TEST(testMultiParaSelCopyPaste);
CPPUNIT_TEST(testTabsCopyPaste);
CPPUNIT_TEST(testHyperlinkSearch);
@@ -708,6 +717,89 @@ void Test::testCopyPaste()
CPPUNIT_ASSERT_EQUAL( OUString(aText + aText), rDoc.GetParaAsString(sal_Int32(0)) );
}
+/// XTransferable implementation that provides simple HTML content.
+class TestHTMLTransferable : public cppu::WeakImplHelper<datatransfer::XTransferable>
+{
+ OString m_aHTML;
+public:
+ TestHTMLTransferable(const OString& rHTML);
+ uno::Any SAL_CALL getTransferData(const datatransfer::DataFlavor& rFlavor) override;
+ uno::Sequence<datatransfer::DataFlavor> SAL_CALL getTransferDataFlavors() override;
+ sal_Bool SAL_CALL isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor) override;
+};
+
+TestHTMLTransferable::TestHTMLTransferable(const OString& rHTML)
+ : m_aHTML(rHTML)
+{
+}
+
+uno::Any TestHTMLTransferable::getTransferData(const datatransfer::DataFlavor& rFlavor)
+{
+ if (rFlavor.MimeType != "text/html")
+ {
+ return {};
+ }
+
+ uno::Any aRet;
+ SvMemoryStream aStream;
+ aStream.WriteOString(m_aHTML);
+ aRet <<= uno::Sequence<sal_Int8>(static_cast<const sal_Int8*>(aStream.GetData()), aStream.GetSize());
+ return aRet;
+}
+
+uno::Sequence<datatransfer::DataFlavor> TestHTMLTransferable::getTransferDataFlavors()
+{
+ datatransfer::DataFlavor aFlavor;
+ aFlavor.DataType = cppu::UnoType<uno::Sequence<sal_Int8>>::get();
+ aFlavor.MimeType = "text/html";
+ aFlavor.HumanPresentableName = aFlavor.MimeType;
+ return { aFlavor };
+}
+
+sal_Bool TestHTMLTransferable::isDataFlavorSupported(const datatransfer::DataFlavor& rFlavor)
+{
+ return rFlavor.MimeType == "text/html"
+ && rFlavor.DataType == cppu::UnoType<uno::Sequence<sal_Int8>>::get();
+}
+
+void Test::testHTMLPaste()
+{
+ // Given an empty editeng document:
+ EditEngine aEditEngine(mpItemPool.get());
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+ OString aHTML("<!DOCTYPE html>\n<html><body>test</body></html>"_ostr);
+ uno::Reference< datatransfer::XTransferable > xData(new TestHTMLTransferable(aHTML));
+
+ // When trying to paste HTML:
+ aEditEngine.InsertText(xData, OUString(), rDoc.GetEndPaM(), true);
+
+ // Then make sure the text gets pasted:
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: test
+ // - Actual :
+ // i.e. RTF and plain text paste worked, but not HTML.
+ CPPUNIT_ASSERT_EQUAL(OUString("test"), rDoc.GetParaAsString(static_cast<sal_Int32>(0)));
+}
+
+void Test::testHTMLFragmentPaste()
+{
+ // Given an empty editeng document:
+ EditEngine aEditEngine(mpItemPool.get());
+ EditDoc &rDoc = aEditEngine.GetEditDoc();
+ OString aHTML("a<b>b</b>c"_ostr);
+ uno::Reference< datatransfer::XTransferable > xData(new TestHTMLTransferable(aHTML));
+
+ // When trying to paste an HTML fragment:
+ aEditEngine.InsertText(xData, OUString(), rDoc.GetEndPaM(), true);
+
+ // Then make sure the text gets pasted:
+ // Without the accompanying fix in place, this test would have failed with:
+ // - Expected: abc
+ // - Actual :
+ // i.e. a HTML fragment without a proper header was ignored on paste.
+ CPPUNIT_ASSERT_EQUAL(OUString("abc"), rDoc.GetParaAsString(static_cast<sal_Int32>(0)));
+}
+
void Test::testMultiParaSelCopyPaste()
{
// Create EditEngine's instance
diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx
index 4dbb93ce2c..260e8dfb50 100644
--- a/editeng/source/editeng/editeng.cxx
+++ b/editeng/source/editeng/editeng.cxx
@@ -2795,6 +2795,13 @@ bool EditEngine::HasValidData( const css::uno::Reference< css::datatransfer::XTr
datatransfer::DataFlavor aFlavor;
SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor );
bValidData = rTransferable->isDataFlavorSupported( aFlavor );
+
+ if (!bValidData)
+ {
+ // Allow HTML-only clipboard, i.e. without plain text.
+ SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML, aFlavor);
+ bValidData = rTransferable->isDataFlavorSupported(aFlavor);
+ }
}
return bValidData;
diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx
index 4b8f0a6379..40f111b72e 100644
--- a/editeng/source/editeng/impedit2.cxx
+++ b/editeng/source/editeng/impedit2.cxx
@@ -3939,7 +3939,7 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera
}
}
if (!bDone) {
- // HTML
+ // HTML_SIMPLE
SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML_SIMPLE, aFlavor);
bool bHtmlSupported = rxDataObj->isDataFlavorSupported(aFlavor);
if (bHtmlSupported && (SotClipboardFormatId::NONE == format || SotClipboardFormatId::HTML_SIMPLE == format)) {
@@ -3963,6 +3963,30 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera
}
}
}
+
+ if (!bDone)
+ {
+ // HTML
+ SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML, aFlavor);
+ bool bHtmlSupported = rxDataObj->isDataFlavorSupported(aFlavor);
+ if (bHtmlSupported
+ && (format == SotClipboardFormatId::NONE || format == SotClipboardFormatId::HTML))
+ {
+ try
+ {
+ uno::Any aData = rxDataObj->getTransferData(aFlavor);
+ uno::Sequence<sal_Int8> aSeq;
+ aData >>= aSeq;
+ SvMemoryStream aHtmlStream(aSeq.getArray(), aSeq.getLength(), StreamMode::READ);
+ aNewSelection = Read(aHtmlStream, rBaseURL, EETextFormat::Html, rPaM);
+ bDone = true;
+ }
+ catch (const css::uno::Exception&)
+ {
+ TOOLS_WARN_EXCEPTION("editeng", "HTML paste failed");
+ }
+ }
+ }
}
if ( !bDone )
{
diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx
index 57b3d65c54..3bf44cdb91 100644
--- a/editeng/source/editeng/impedit4.cxx
+++ b/editeng/source/editeng/impedit4.cxx
@@ -905,7 +905,7 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput,
break;
case EE_FEATURE_LINEBR:
{
- rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SL );
+ rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_LINE );
}
break;
case EE_CHAR_KERNING:
diff --git a/editeng/source/misc/acorrcfg.cxx b/editeng/source/misc/acorrcfg.cxx
index 616d75c696..49e48bb48b 100644
--- a/editeng/source/misc/acorrcfg.cxx
+++ b/editeng/source/misc/acorrcfg.cxx
@@ -65,13 +65,12 @@ static void scanAutoCorrectDirForLanguageTags( const OUString& rURL )
continue;
const OUString aBcp47( aTitle.copy( 5, aTitle.getLength() - 9));
- OUString aCanonicalized;
// Ignore invalid langtags and canonicalize for good,
// allow private-use tags.
- if (!LanguageTag::isValidBcp47( aBcp47, &aCanonicalized))
+ const LanguageTag aLanguageTag (aBcp47, true);
+ if (!aLanguageTag.isValidBcp47())
continue;
- const LanguageTag aLanguageTag( aCanonicalized);
if (SvtLanguageTable::HasLanguageType( aLanguageTag.getLanguageType()))
continue;
@@ -83,7 +82,7 @@ static void scanAutoCorrectDirForLanguageTags( const OUString& rURL )
// other private-use tag (which should not fallback,
// but avoid).
if (aLanguageTag.getCountry().isEmpty()
- && LanguageTag::isValidBcp47( aCanonicalized, nullptr,
+ && LanguageTag::isValidBcp47( aLanguageTag.getBcp47(), nullptr,
LanguageTag::PrivateUse::DISALLOW))
{
LanguageTag aFallback( aLanguageTag);