sw/qa/extras/ooxmlexport/data/tdf142464_ampm.docx |binary sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx | 26 +++++++++ writerfilter/source/dmapper/ConversionHelper.cxx | 62 ++++++++++++---------- 3 files changed, 62 insertions(+), 26 deletions(-)
New commits: commit f51f0c023dc163e348e784fc1f846a76afb9bf80 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sun Jul 4 12:29:08 2021 +0300 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Jul 6 11:32:11 2021 +0200 tdf#142464: do not escape '/' is AM/PM when importing DOCX. See also commit a2e964afc5187fc1e3b38720ec10ad9856b87020, doing the same for DOC. Change-Id: Ib0ddb36de8589f9264fe857b20a6ef2aa2607c52 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118369 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> (cherry picked from commit cd0ab69d4afee0c77884ae17ab9410216695b58b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118413 Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org> diff --git a/sw/qa/extras/ooxmlexport/data/tdf142464_ampm.docx b/sw/qa/extras/ooxmlexport/data/tdf142464_ampm.docx new file mode 100644 index 000000000000..d63398488858 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf142464_ampm.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx index e828519ed4cf..d92c29fefbe7 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlfieldexport.cxx @@ -10,6 +10,7 @@ #include <swmodeltestbase.hxx> #include <com/sun/star/text/XTextFieldsSupplier.hpp> +#include <com/sun/star/text/XTextField.hpp> #include <xmloff/odffields.hxx> @@ -688,6 +689,31 @@ DECLARE_OOXMLEXPORT_EXPORTONLY_TEST(testConditionalText, "conditional-text.fodt" assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:r[2]/w:instrText", OUString(aExpected)); } +DECLARE_OOXMLEXPORT_TEST(testTdf142464_ampm, "tdf142464_ampm.docx") +{ + css::uno::Reference<css::text::XTextFieldsSupplier> xTextFieldsSupplier( + mxComponent, css::uno::UNO_QUERY_THROW); + auto xFieldsAccess(xTextFieldsSupplier->getTextFields()); + auto xFields(xFieldsAccess->createEnumeration()); + css::uno::Reference<css::text::XTextField> xField(xFields->nextElement(), + css::uno::UNO_QUERY_THROW); + + // Without the fix in place, this would have failed with: + // - Expected: 12:32 PM + // - Actual : 12:32 a12/p12 + CPPUNIT_ASSERT_EQUAL(OUString("12:32 PM"), xField->getPresentation(false)); + + if (xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml")) + { + // Without the fix in place, this would have failed with: + // - Expected: DATE \@"H:mm\ AM/PM" + // - Actual : DATE \@"H:mm' a'M'/p'M" + // i.e., the AM/PM would be treated as literal 'a' and 'p' followed by a month code + assertXPathContent(pXmlDoc, "/w:document/w:body/w:p/w:r[2]/w:instrText", + " DATE \\@\"H:mm\\ AM/PM\" "); + } +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/writerfilter/source/dmapper/ConversionHelper.cxx b/writerfilter/source/dmapper/ConversionHelper.cxx index ac877c5d723a..12cac7c8f1b3 100644 --- a/writerfilter/source/dmapper/ConversionHelper.cxx +++ b/writerfilter/source/dmapper/ConversionHelper.cxx @@ -295,8 +295,17 @@ bool lcl_IsNotAM(OUString const & rFmt, sal_Int32 nPos) ) ); } +bool IsPreviousAM(OUString const& rParams, sal_Int32 nPos) +{ + return nPos >= 2 && rParams.matchIgnoreAsciiCase("am", nPos - 2); +} +bool IsNextPM(OUString const& rParams, sal_Int32 nPos) +{ + return nPos + 2 < rParams.getLength() && rParams.matchIgnoreAsciiCase("pm", nPos + 1); +} } +// See also sw::ms::MSDateTimeFormatToSwFormat OUString ConvertMSFormatStringToSO( const OUString& rFormat, lang::Locale& rLocale, bool bHijri) { @@ -306,37 +315,38 @@ OUString ConvertMSFormatStringToSO( //#102782#, #102815#, #108341# & #111944# have to work at the same time :-) bool bForceJapanese(false); bool bForceNatNum(false); - sal_Int32 nLen = sFormat.getLength(); + const sal_Int32 nLen = sFormat.getLength(); sal_Int32 nI = 0; + sal_Int32 nAddedChars = 0; // const sal_Unicode* pFormat = sFormat.getStr(); OUStringBuffer aNewFormat( sFormat ); while (nI < nLen) { - if (aNewFormat[nI] == '\\') - nI++; - else if (aNewFormat[nI] == '\"') + if (sFormat[nI] == '\\') + ++nI; + else if (sFormat[nI] == '\"') { ++nI; //While not at the end and not at an unescaped end quote - while ((nI < nLen) && ((aNewFormat[nI] != '\"') && (aNewFormat[nI-1] != '\\'))) + while ((nI < nLen) && ((sFormat[nI] != '\"') && (sFormat[nI-1] != '\\'))) ++nI; } else //normal unquoted section { - sal_Unicode nChar = aNewFormat[nI]; + sal_Unicode nChar = sFormat[nI]; if (nChar == 'O') { - aNewFormat[nI] = 'M'; + aNewFormat[nI + nAddedChars] = 'M'; bForceNatNum = true; } else if (nChar == 'o') { - aNewFormat[nI] = 'm'; + aNewFormat[nI + nAddedChars] = 'm'; bForceNatNum = true; } else if ((nChar == 'A') && lcl_IsNotAM(sFormat, nI)) { - aNewFormat[nI] = 'D'; + aNewFormat[nI + nAddedChars] = 'D'; bForceNatNum = true; } else if ((nChar == 'g') || (nChar == 'G')) @@ -345,38 +355,38 @@ OUString ConvertMSFormatStringToSO( bForceJapanese = true; else if (nChar == 'E') { - if ((nI != nLen-1) && (aNewFormat[nI+1] == 'E')) + if ((nI != nLen-1) && (sFormat[nI+1] == 'E')) { //todo: this cannot be the right way to replace a part of the string! - aNewFormat[nI] = 'Y'; - aNewFormat[nI + 1] = 'Y'; - aNewFormat.insert(nI + 2, "YY"); - nLen+=2; - nI+=3; + aNewFormat[nI + nAddedChars] = 'Y'; + aNewFormat[nI + nAddedChars + 1] = 'Y'; + aNewFormat.insert(nI + nAddedChars + 2, "YY"); + nAddedChars += 2; + ++nI; } bForceJapanese = true; } else if (nChar == 'e') { - if ((nI != nLen-1) && (aNewFormat[nI+1] == 'e')) + if ((nI != nLen-1) && (sFormat[nI+1] == 'e')) { //todo: this cannot be the right way to replace a part of the string! - aNewFormat[nI] = 'y'; - aNewFormat[nI + 1] = 'y'; - aNewFormat.insert(nI + 2, "yy"); - nLen+=2; - nI+=3; + aNewFormat[nI + nAddedChars] = 'y'; + aNewFormat[nI + nAddedChars + 1] = 'y'; + aNewFormat.insert(nI + nAddedChars + 2, "yy"); + nAddedChars += 2; + ++nI; } bForceJapanese = true; } - else if (nChar == '/') + else if (nChar == '/' && !(IsPreviousAM(sFormat, nI) && IsNextPM(sFormat, nI))) { // MM We have to escape '/' in case it's used as a char //todo: this cannot be the right way to replace a part of the string! - aNewFormat[nI] = '\\'; - aNewFormat.insert(nI + 1, "/"); - nI++; - nLen++; + aNewFormat[nI + nAddedChars] = '\\'; + aNewFormat.insert(nI + nAddedChars + 1, "/"); + ++nAddedChars; + ++nI; } } ++nI; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits