[Libreoffice-commits] core.git: Branch 'libreoffice-7-2' - sw/qa writerfilter/source
Mike Kaganski (via logerrit)
logerrit at kemper.freedesktop.org
Tue Jul 6 09:32:47 UTC 2021
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.kaganski at collabora.com>
AuthorDate: Sun Jul 4 12:29:08 2021 +0300
Commit: Xisco Fauli <xiscofauli at 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.kaganski at collabora.com>
(cherry picked from commit cd0ab69d4afee0c77884ae17ab9410216695b58b)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118413
Reviewed-by: Xisco Fauli <xiscofauli at 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;
More information about the Libreoffice-commits
mailing list