filter/source/msfilter/rtfutil.cxx | 3 ++- svtools/source/svrtf/rtfout.cxx | 3 ++- sw/qa/extras/rtfexport/rtfexport8.cxx | 21 +++++++++++++++++++++ sw/source/filter/ww8/rtfattributeoutput.cxx | 3 ++- 4 files changed, 27 insertions(+), 3 deletions(-)
New commits: commit 77db5679983cc58603c2001a9b8dfcea7faa8574 Author: Mike Kaganski <[email protected]> AuthorDate: Thu Jul 24 11:10:28 2025 +0500 Commit: Xisco Fauli <[email protected]> CommitDate: Mon Aug 11 12:11:54 2025 +0200 tdf#167660: export \uN as signed 16-bit values This is as specified in Rich Text Format (RTF) Specification, Version 1.9.1, "Unicode RTF"; and this matches what Word outputs. Change-Id: Ia1b7c2dc40d5908a78a30ea249c1ec0a13945b87 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/188257 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> Signed-off-by: Xisco Fauli <[email protected]> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189302 diff --git a/filter/source/msfilter/rtfutil.cxx b/filter/source/msfilter/rtfutil.cxx index bb1b85876bfd..093be55f6ff6 100644 --- a/filter/source/msfilter/rtfutil.cxx +++ b/filter/source/msfilter/rtfutil.cxx @@ -186,7 +186,8 @@ OString OutChar(sal_Unicode c, int* pUCMode, rtl_TextEncoding eDestEnc, bool* pS aBuf.append(' '); *pUCMode = nLen; } - aBuf.append("\u" + OString::number(static_cast<sal_Int32>(c))); + // Rich Text Format (RTF) Specification, Version 1.9.1, "Unicode RTF" + aBuf.append("\u" + OString::number(static_cast<sal_Int16>(c))); // signed! } for (sal_Int32 nI = 0; nI < nLen; ++nI) diff --git a/svtools/source/svrtf/rtfout.cxx b/svtools/source/svrtf/rtfout.cxx index 843256dc2d47..da2bd7b103f8 100644 --- a/svtools/source/svrtf/rtfout.cxx +++ b/svtools/source/svrtf/rtfout.cxx @@ -154,8 +154,9 @@ SvStream& Out_Char(SvStream& rStream, sal_Unicode c, .WriteNumberAsString( nLen ).WriteOString( " " ); *pUCMode = nLen; } + // Rich Text Format (RTF) Specification, Version 1.9.1, "Unicode RTF" rStream.WriteOString( "\u" ) - .WriteNumberAsString(c); + .WriteNumberAsString(static_cast<sal_Int16>(c)); // signed! } for (sal_Int32 nI = 0; nI < nLen; ++nI) diff --git a/sw/qa/extras/rtfexport/rtfexport8.cxx b/sw/qa/extras/rtfexport/rtfexport8.cxx index ff05ce5c4fcd..9c36b8596691 100644 --- a/sw/qa/extras/rtfexport/rtfexport8.cxx +++ b/sw/qa/extras/rtfexport/rtfexport8.cxx @@ -992,6 +992,27 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf167569) } } +CPPUNIT_TEST_FIXTURE(Test, testTdf167660) +{ + // Create a document, add there a character in a range U+8000-U+FFFF, export to RTF + createSwDoc(); + CPPUNIT_ASSERT(getSwDocShell()); + CPPUNIT_ASSERT(getSwDocShell()->GetWrtShell()); + getSwDocShell()->GetWrtShell()->Insert(u"\uFB02"_ustr); + + save(mpFilter); + + // Test that the character is exported as a negative integer + + SvFileStream stream(maTempFile.GetFileName(), StreamMode::READ); + auto size = stream.remainingSize(); + std::vector<char> buffer(size); + CPPUNIT_ASSERT_EQUAL(size_t(size), stream.ReadBytes(buffer.data(), buffer.size())); + std::string_view buffer_view(buffer.data(), buffer.size()); + CPPUNIT_ASSERT_EQUAL(std::string_view::npos, buffer_view.find("\u64258")); + CPPUNIT_ASSERT(buffer_view.find("\u-1278") != std::string_view::npos); +} + } // end of anonymous namespace CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx index 4579ba5e3f75..e2b66f87c278 100644 --- a/sw/source/filter/ww8/rtfattributeoutput.cxx +++ b/sw/source/filter/ww8/rtfattributeoutput.cxx @@ -1867,7 +1867,8 @@ void RtfAttributeOutput::NumberingLevel(sal_uInt8 nLevel, sal_uInt16 nStart, m_rExport.Strm().WriteOString("\'01"); sal_Unicode cChar = rNumberingString[0]; m_rExport.Strm().WriteOString("\u"); - m_rExport.Strm().WriteNumberAsString(cChar); + // Rich Text Format (RTF) Specification, Version 1.9.1, "Unicode RTF" + m_rExport.Strm().WriteNumberAsString(static_cast<sal_Int16>(cChar)); // signed! m_rExport.Strm().WriteOString(" ?"); } else
