src/lib/VSDDocumentStructure.h | 4 src/lib/VSDFieldList.cpp | 169 ++++++++++++++++++++++++----- src/test/data/tdf76829-datetime-format.vsd |binary src/test/data/tdf76829-numeric-format.vsd |binary src/test/importtest.cpp | 20 ++- 5 files changed, 160 insertions(+), 33 deletions(-)
New commits: commit d410b9bd6c763ec0037031b6b5913f754264beca Author: Bartosz Kosiorek <gan...@poczta.onet.pl> AuthorDate: Wed Jun 26 16:19:18 2019 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jul 3 16:40:21 2019 +0200 tdf#76829 tdf#98291 Visio: Fix date and time conversion to string The documentation which implementation was based on was taken from: https://docs.microsoft.com/en-us/openspecs/sharepoint_protocols/ms-vsdx/50c23601-c943-4ff2-b4a1-02445f52daf0 Change-Id: I8a3544d198d0376bdc31b158c073f5340dff7237 Reviewed-on: https://gerrit.libreoffice.org/74743 Tested-by: Miklos Vajna <vmik...@collabora.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/src/lib/VSDDocumentStructure.h b/src/lib/VSDDocumentStructure.h index 1f022b7..4fd8b61 100644 --- a/src/lib/VSDDocumentStructure.h +++ b/src/lib/VSDDocumentStructure.h @@ -152,8 +152,8 @@ #define VSD_FIELD_FORMAT_DateLong 21 #define VSD_FIELD_FORMAT_DateMDYY 22 #define VSD_FIELD_FORMAT_DateMMDDYY 23 -#define VSD_FIELD_FORMAT_DateMmmDYYYY 24 -#define VSD_FIELD_FORMAT_DateMmmmDYYYY 25 +#define VSD_FIELD_FORMAT_DateMMMDYYYY 24 +#define VSD_FIELD_FORMAT_DateMMMMDYYYY 25 #define VSD_FIELD_FORMAT_DateDMYY 26 #define VSD_FIELD_FORMAT_DateDDMMYY 27 #define VSD_FIELD_FORMAT_DateDMMMYYYY 28 diff --git a/src/lib/VSDFieldList.cpp b/src/lib/VSDFieldList.cpp index c4c16ef..05482d0 100644 --- a/src/lib/VSDFieldList.cpp +++ b/src/lib/VSDFieldList.cpp @@ -10,6 +10,7 @@ #include "VSDFieldList.h" #include <time.h> +#include <cmath> #include "VSDCollector.h" #include "libvisio_utils.h" @@ -25,6 +26,9 @@ libvisio::VSDFieldListElement *libvisio::VSDTextField::clone() librevenge::RVNGString libvisio::VSDTextField::getString(const std::map<unsigned, librevenge::RVNGString> &strVec) { + //TODO VSD_FIELD_FORMAT_StrNormal 37 + //TODO VSD_FIELD_FORMAT_StrLower 38 + //TODO VSD_FIELD_FORMAT_StrUpper 39 auto iter = strVec.find(m_nameId); if (iter != strVec.end()) return iter->second; @@ -66,18 +70,111 @@ librevenge::RVNGString libvisio::VSDNumericField::datetimeToString(const char *f librevenge::RVNGString libvisio::VSDNumericField::getString(const std::map<unsigned, librevenge::RVNGString> &) { - if (m_format == 0xffff) + if (m_format == VSD_FIELD_FORMAT_Unknown) return librevenge::RVNGString(); switch (m_format) { + case VSD_FIELD_FORMAT_NumGenNoUnits: + case VSD_FIELD_FORMAT_NumGenDefUnits: + { + // 0 Format string: 0.#### Example: 30060.9167 + // 1 Format string: 0.#### u Example: 30060.9167 cm + //TODO We need to implement number of digits support after decimal separator in librevenge + double intpart; + // If there is no decimal value, then treat number as Integer + if (std::modf(m_number, &intpart) == 0.0) + { + std::unique_ptr<librevenge::RVNGProperty> pProp{librevenge::RVNGPropertyFactory::newIntProp(m_number)}; + return pProp ? pProp->getStr() : librevenge::RVNGString(); + } + std::unique_ptr<librevenge::RVNGProperty> pProp{librevenge::RVNGPropertyFactory::newDoubleProp(m_number)}; + return pProp ? pProp->getStr() : librevenge::RVNGString(); + } + case VSD_FIELD_FORMAT_0PlNoUnits: + case VSD_FIELD_FORMAT_0PlDefUnits: + { + // 2 Format string: 0 Example: 30061 + // 3 Format string: 0 u Example: 30061 cm + std::unique_ptr<librevenge::RVNGProperty> pProp{librevenge::RVNGPropertyFactory::newIntProp(m_number)}; + return pProp ? pProp->getStr() : librevenge::RVNGString(); + } + //TODO VSD_FIELD_FORMAT_1PlNoUnits 4 Format string: 0.0 + //TODO VSD_FIELD_FORMAT_1PlDefUnits 5 Format string: 0.0 u + //TODO VSD_FIELD_FORMAT_2PlNoUnits 6 Format string: 0.00 + //TODO VSD_FIELD_FORMAT_2PlDefUnits 7 Format string: 0.00 u + //TODO VSD_FIELD_FORMAT_3PlNoUnits 8 Format string: 0.000 + //TODO VSD_FIELD_FORMAT_3PlDefUnits 9 Format string: 0.000 u + //TODO VSD_FIELD_FORMAT_FeetAndInches 10 Format string: <,FEET/INCH>0.000 u + //TODO VSD_FIELD_FORMAT_Radians 11 Format string: <,rad>0.#### u + //TODO VSD_FIELD_FORMAT_Degrees 12 Format string: <,deg>0.# u + //TODO VSD_FIELD_FORMAT_FeetAndInches1Pl 13 Format string: <,FEET/INCH># #/# u + //TODO VSD_FIELD_FORMAT_FeetAndInches2Pl 14 Format string: <,FEET/INCH># #/## u + //TODO VSD_FIELD_FORMAT_Fraction1PlNoUnits 15 Format string: 0 #/# + //TODO VSD_FIELD_FORMAT_Fraction1PlDefUnits 16 Format string: 0 #/# u + //TODO VSD_FIELD_FORMAT_Fraction2PlNoUnits 17 Format string: 0 #/## + //TODO VSD_FIELD_FORMAT_Fraction2PlDefUnits 18 Format string: 0 #/## u + case VSD_FIELD_FORMAT_DateShort: + // 20 Format string: ddddd Example: Thu + return datetimeToString("%a", m_number); + case VSD_FIELD_FORMAT_DateLong: + // 21 Format string: dddddd Example: Thursday + return datetimeToString("%A", m_number); case VSD_FIELD_FORMAT_DateMDYY: case VSD_FIELD_FORMAT_DateMMDDYY: - case VSD_FIELD_FORMAT_DateMmmDYYYY: - case VSD_FIELD_FORMAT_DateMmmmDYYYY: + // 22 Format string: M/d/y Example: 4/19/82 + // 23 Format string: MM/d/y Example: 4/19/82 + return datetimeToString("%m/%d/%y", m_number); + case VSD_FIELD_FORMAT_DateMMMDYYYY: + // 24 Format string: MMM d, yyyy Example: Apr 19, 1982 + return datetimeToString("%b %e, %Y", m_number); + case VSD_FIELD_FORMAT_DateMMMMDYYYY: + // 25 Format string: MMMM d, yyyy Example: April 19, 1982 + return datetimeToString("%B %e, %Y", m_number); case VSD_FIELD_FORMAT_DateDMYY: + // 26 Format string: d/M/YY Example: 19/04/82 + return datetimeToString("%e/%m/%y", m_number); case VSD_FIELD_FORMAT_DateDDMMYY: + // 27 Format string: dd/MM/YY Example: 19/04/82 + return datetimeToString("%d/%m/%y", m_number); case VSD_FIELD_FORMAT_DateDMMMYYYY: + // 28 Format string: d MMM, yyyy Example: 19 Apr, 1982 + return datetimeToString("%e %b, %Y", m_number); case VSD_FIELD_FORMAT_DateDMMMMYYYY: + // 29 Format string: d MMMM, yyyy Example: 19 April, 1982 + return datetimeToString("%e %B, %Y", m_number); + case VSD_FIELD_FORMAT_TimeGen: + // The value is formatted using a format string "h:mm:ss tt" and inserted to the result string. + // For example, FORMAT(DATETIME("6/25/07 12:05"), "T") displays 12:05:00 PM. + // 30 Format string: T Example: 10:02:02 PM + return datetimeToString("%r", m_number); + case VSD_FIELD_FORMAT_TimeHMM: + case VSD_FIELD_FORMAT_TimeHHMM: + case VSD_FIELD_FORMAT_TimeHMM24: + case VSD_FIELD_FORMAT_TimeHHMM24: + // 31 Format string: h:mm Example: 10:02 + // 32 Format string: hh:mm Example: 10:02 + // 33 Format string: H:mm Example: 10:02 + // 34 Format string: HH:mm Example: 10:02 + return datetimeToString("%H:%m:%S", m_number); + case VSD_FIELD_FORMAT_TimeHMMAMPM: + case VSD_FIELD_FORMAT_TimeHHMMAMPM: + // 35 Format string: h:mm tt Example: 10:02 PM + // 36 Format string: HH:mm tt Example: 10:02 PM + return datetimeToString("%I:%m %p", m_number); + case VSD_FIELD_FORMAT_TimeAMPMhmm_J: + case VSD_FIELD_FORMAT_TimeAMPMhmm_C: + case VSD_FIELD_FORMAT_TimeAMPMhmm_K: + case VSD_FIELD_FORMAT_TimeAMPM_hmm_J: + case VSD_FIELD_FORMAT_Timehmm_J: + case VSD_FIELD_FORMAT_TimeAMPM_hmm_C: + case VSD_FIELD_FORMAT_Timehmm_C: + case VSD_FIELD_FORMAT_TimeAMPM_hmm_K: + case VSD_FIELD_FORMAT_Timehmm_K: + case VSD_FIELD_FORMAT_TimeHMMAMPM_E: + case VSD_FIELD_FORMAT_TimeHHMMAMPM_E: + case VSD_FIELD_FORMAT_TimeAMPMhmm_S: + case VSD_FIELD_FORMAT_TimeAMPMhhmm_S: + return datetimeToString("%X", m_number); case VSD_FIELD_FORMAT_Dateyyyymd: case VSD_FIELD_FORMAT_Dateyymmdd: case VSD_FIELD_FORMAT_DateTWNfYYYYMMDDD_C: @@ -101,45 +198,61 @@ librevenge::RVNGString libvisio::VSDNumericField::getString(const std::map<unsig case VSD_FIELD_FORMAT_Datewwyyyymmdd_S: case VSD_FIELD_FORMAT_Datewwyyyymd_S: case VSD_FIELD_FORMAT_MsoDateShort: + case VSD_FIELD_FORMAT_MsoFEExtra1: + case VSD_FIELD_FORMAT_MsoFEExtra2: + case VSD_FIELD_FORMAT_MsoFEExtra3: + case VSD_FIELD_FORMAT_MsoFEExtra4: + case VSD_FIELD_FORMAT_MsoFEExtra5: + // 40-81, 200, 217-221 Format string: M/d/yyyy Example: 4/19/1982 + return datetimeToString("%m/%d/%Y", m_number); case VSD_FIELD_FORMAT_MsoDateLongDay: + // 201 Format string: dddd, MMMM dd, yyyy Example: Monday, April 19, 1982 + return datetimeToString("%A, %B %d, %Y", m_number); case VSD_FIELD_FORMAT_MsoDateLong: + // 202 Format string: MMMM d, yyyy Example: April 19, 1982 + return datetimeToString("%B %e, %Y", m_number); case VSD_FIELD_FORMAT_MsoDateShortAlt: + // 203 Format string: M/d/yy Example: 4/19/82 + return datetimeToString("%m/%d/%y", m_number); case VSD_FIELD_FORMAT_MsoDateISO: + // 204 Format string: yyyy-MM-dd Example: 1982-04-19 + return datetimeToString("%Y-%m-%d", m_number); case VSD_FIELD_FORMAT_MsoDateShortMon: + // 205 Format string: d-MMM-yy Example: 19-Apr-1982 + return datetimeToString("%e-%b-%y", m_number); case VSD_FIELD_FORMAT_MsoDateShortSlash: + // 206 Format string: M.d.yyyy Example: 4.19.1982 + return datetimeToString("%m.%d.%Y", m_number); case VSD_FIELD_FORMAT_MsoDateShortAbb: + // 207 Format string: MMM.d, yy Example: Apr.19, 82 + return datetimeToString("%b.%d, %y", m_number); case VSD_FIELD_FORMAT_MsoDateEnglish: + // 208 Format string: D MMMM yyyy Example: 19 April 1982 + return datetimeToString("%e %B %Y", m_number); case VSD_FIELD_FORMAT_MsoDateMonthYr: + // 209 Format string: MMMM yy Example: April 82 + return datetimeToString("%B %y", m_number); case VSD_FIELD_FORMAT_MsoDateMon_Yr: - return datetimeToString("%x", m_number); - case VSD_FIELD_FORMAT_TimeGen: - case VSD_FIELD_FORMAT_TimeHMM: - case VSD_FIELD_FORMAT_TimeHHMM: - case VSD_FIELD_FORMAT_TimeHMM24: - case VSD_FIELD_FORMAT_TimeHHMM24: - case VSD_FIELD_FORMAT_TimeHMMAMPM: - case VSD_FIELD_FORMAT_TimeHHMMAMPM: - case VSD_FIELD_FORMAT_TimeAMPMhmm_J: - case VSD_FIELD_FORMAT_TimeAMPMhmm_C: - case VSD_FIELD_FORMAT_TimeAMPMhmm_K: - case VSD_FIELD_FORMAT_TimeAMPM_hmm_J: - case VSD_FIELD_FORMAT_Timehmm_J: - case VSD_FIELD_FORMAT_TimeAMPM_hmm_C: - case VSD_FIELD_FORMAT_Timehmm_C: - case VSD_FIELD_FORMAT_TimeAMPM_hmm_K: - case VSD_FIELD_FORMAT_Timehmm_K: - case VSD_FIELD_FORMAT_TimeHMMAMPM_E: - case VSD_FIELD_FORMAT_TimeHHMMAMPM_E: - case VSD_FIELD_FORMAT_TimeAMPMhmm_S: - case VSD_FIELD_FORMAT_TimeAMPMhhmm_S: + // 210 Format string: MMM-yy Example: Apr-82 + return datetimeToString("%b-%y", m_number); + case VSD_FIELD_FORMAT_MsoTimeDatePM: + // 211 Format string: M/d/yyyy h:mm am/pm Example: 4/19/1982 10:02 PM + return datetimeToString("%m/%d/%Y %I:%m %p", m_number); + case VSD_FIELD_FORMAT_MsoTimeDateSecPM: + // 212 Format string: M/d/yyyy h:mm:ss am/pm Example: 4/19/1982 10:02:02 PM + return datetimeToString("%m/%d/%Y %I:%m:%S %p", m_number); case VSD_FIELD_FORMAT_MsoTimePM: + // 213 Format string: H:mm am/pm Example: 10:02 PM + return datetimeToString("%I:%m %p", m_number); case VSD_FIELD_FORMAT_MsoTimeSecPM: + // 214 Format string: h:mm:ss am/pm Example: 10:02:02 PM + return datetimeToString("%I:%m:%S %p", m_number); case VSD_FIELD_FORMAT_MsoTime24: + // 215 Format string: HH:mm Example: 10:02 + return datetimeToString("%H:%m", m_number); case VSD_FIELD_FORMAT_MsoTimeSec24: - return datetimeToString("%X", m_number); - case VSD_FIELD_FORMAT_MsoTimeDatePM: - case VSD_FIELD_FORMAT_MsoTimeDateSecPM: - return datetimeToString("%x %X", m_number); + // 216 Format string: HH:mm:ss Example: 10:02:01 + return datetimeToString("%H:%m:%S", m_number); default: { std::unique_ptr<librevenge::RVNGProperty> pProp{librevenge::RVNGPropertyFactory::newDoubleProp(m_number)}; diff --git a/src/test/data/tdf76829-datetime-format.vsd b/src/test/data/tdf76829-datetime-format.vsd new file mode 100644 index 0000000..c9237fe Binary files /dev/null and b/src/test/data/tdf76829-datetime-format.vsd differ diff --git a/src/test/data/tdf76829-numeric-format.vsd b/src/test/data/tdf76829-numeric-format.vsd new file mode 100644 index 0000000..a1c24cc Binary files /dev/null and b/src/test/data/tdf76829-numeric-format.vsd differ diff --git a/src/test/importtest.cpp b/src/test/importtest.cpp index 418551f..13b665f 100644 --- a/src/test/importtest.cpp +++ b/src/test/importtest.cpp @@ -110,7 +110,6 @@ void assertBmpDataOffset(xmlDocPtr doc, const librevenge::RVNGString &xpath, con CPPUNIT_ASSERT_EQUAL_MESSAGE(message.cstr(), expectedValue, actualValue); } -#if 0 // keep for future use /// Same as the assertXPathContent(), but don't assert: return the string instead. librevenge::RVNGString getXPathContent(xmlDocPtr doc, const librevenge::RVNGString &xpath) { @@ -127,7 +126,6 @@ librevenge::RVNGString getXPathContent(xmlDocPtr doc, const librevenge::RVNGStri xmlXPathFreeObject(xpathObject); return s; } - /// Assert that xpath exists, and its content equals to content. void assertXPathContent(xmlDocPtr doc, const librevenge::RVNGString &xpath, const librevenge::RVNGString &content) { @@ -136,7 +134,6 @@ void assertXPathContent(xmlDocPtr doc, const librevenge::RVNGString &xpath, cons message.append("': contents of child does not match."); CPPUNIT_ASSERT_EQUAL_MESSAGE(message.cstr(), content, getXPathContent(doc, xpath)); } -#endif /// Paints an XML representation of filename into buffer, then returns the parsed buffer content. xmlDocPtr parse(const char *filename, xmlBufferPtr buffer) @@ -179,6 +176,8 @@ class ImportTest : public CPPUNIT_NS::TestFixture CPPUNIT_TEST(testVsdxCharBgColor); #endif CPPUNIT_TEST(testVsdTextBlockWithoutBgColor); + CPPUNIT_TEST(testVsdNumericFormat); + CPPUNIT_TEST(testVsdDateTimeFormatting); CPPUNIT_TEST(testBmpFileHeader); CPPUNIT_TEST(testBmpFileHeader2); CPPUNIT_TEST_SUITE_END(); @@ -191,6 +190,8 @@ class ImportTest : public CPPUNIT_NS::TestFixture void testVsdxImportBgColorFromTheme(); void testVsdxCharBgColor(); void testVsdTextBlockWithoutBgColor(); + void testVsdNumericFormat(); + void testVsdDateTimeFormatting(); void testBmpFileHeader(); void testBmpFileHeader2(); @@ -313,6 +314,19 @@ void ImportTest::testVsdTextBlockWithoutBgColor() assertXPathNoAttribute(m_doc, "/document/page/layer[5]/textObject/paragraph[1]/span", "background-color"); } +void ImportTest::testVsdNumericFormat() +{ + m_doc = parse("tdf76829-numeric-format.vsd", m_buffer); + assertXPathContent(m_doc, "/document/page[1]/textObject[1]/paragraph[1]/span/insertText", "Zeichenblatt 1 "); + assertXPathContent(m_doc, "/document/page[2]/textObject[1]/paragraph[1]/span/insertText", "Zeichenblatt 2 "); +} + +void ImportTest::testVsdDateTimeFormatting() +{ + m_doc = parse("tdf76829-datetime-format.vsd", m_buffer); + assertXPathContent(m_doc, "/document/page/textObject/paragraph/span/insertText", "11/30/2005"); +} + void ImportTest::testBmpFileHeader() { m_doc = parse("bitmaps.vsd", m_buffer); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits