summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBartosz Kosiorek <gang65@poczta.onet.pl>2019-06-26 16:19:18 +0200
committerMiklos Vajna <vmiklos@collabora.com>2019-07-03 16:40:21 +0200
commitd410b9bd6c763ec0037031b6b5913f754264beca (patch)
tree1b2aac47b949ef7ffef9fa73e4b218205c519c2f
parentc5a43cf0bb3d002cc4ff396ffbf85ebe9dd0da29 (diff)
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 <vmiklos@collabora.com> Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
-rw-r--r--src/lib/VSDDocumentStructure.h4
-rw-r--r--src/lib/VSDFieldList.cpp169
-rw-r--r--src/test/data/tdf76829-datetime-format.vsdbin0 -> 161280 bytes
-rw-r--r--src/test/data/tdf76829-numeric-format.vsdbin0 -> 77312 bytes
-rw-r--r--src/test/importtest.cpp20
5 files changed, 160 insertions, 33 deletions
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
--- /dev/null
+++ b/src/test/data/tdf76829-datetime-format.vsd
Binary files 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
--- /dev/null
+++ b/src/test/data/tdf76829-numeric-format.vsd
Binary files 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);