sw/qa/extras/ooxmlexport/data/tdf148380_printField.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlexport17.cxx              |   17 ++++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx       |   64 +++++++++++-----
 writerfilter/source/dmapper/DomainMapper_Impl.hxx       |    1 
 4 files changed, 61 insertions(+), 21 deletions(-)

New commits:
commit 115599cc3478e37879cd2fa0b6c6c9dabde7dfd1
Author:     Justin Luth <justin_l...@sil.org>
AuthorDate: Sat Apr 9 18:06:24 2022 +0200
Commit:     Justin Luth <jl...@mail.com>
CommitDate: Mon Apr 25 18:57:45 2022 +0200

    tdf#132475 writerfilter: use proper date-field defaults
    
    When a field doesn't specify the format for a date,
    the system is free to implement it as it chooses.
    However, the user tends to disagree with that,
    so lets try to create a MS-similar default for
    these dates - since LO defaults to only displaying
    a date without any time component.
    
    For example: PRINTDATE \* MERGEFORMAT
    doesn't tell us how to display the date.
    
    MS Word uses different defaults depending on
    the language of the document. And that only make sense.
    For example, I noticed that of course en-GB's format
    is dd/MM/yyyy instead of en-US's M/d/yyyy.
    
    As a documentation example: 17.16.5.47 PRINTDATE
    Syntax: PRINTDATE [ switches ]
    Description: Retrieves the date and time on which the
    document was last printed, as recorded in the
    LastPrinted element of the Core File Properties part.
    
    Switches: Zero or one date-and-time-formatting-switch
    and zero or one of the following field-specific-switches.
    
    PRINTDATE (without any formatting switches)
       the results are:
    1/6/2006 2:58:00 PM
    
    Change-Id: I41f3bdc155bd8cdc74177e4626b31ece9b47e16b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133208
    Tested-by: Justin Luth <jl...@mail.com>
    Tested-by: Jenkins
    Reviewed-by: Justin Luth <jl...@mail.com>

diff --git a/sw/qa/extras/ooxmlexport/data/tdf148380_printField.docx 
b/sw/qa/extras/ooxmlexport/data/tdf148380_printField.docx
new file mode 100644
index 000000000000..44145748c6ed
Binary files /dev/null and 
b/sw/qa/extras/ooxmlexport/data/tdf148380_printField.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx 
b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index 9347a8abfb54..464c0b22d6c4 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -100,6 +100,23 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148380_modifiedField, 
"tdf148380_modifiedField.d
                                  OUString("Charles Brown"), 
xField->getPresentation(false));
 }
 
+DECLARE_OOXMLEXPORT_TEST(testTdf148380_printField, "tdf148380_printField.docx")
+{
+    // Verify that these are fields, and not just plain text
+    uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, 
uno::UNO_QUERY);
+    auto xFieldsAccess(xTextFieldsSupplier->getTextFields());
+    uno::Reference<container::XEnumeration> 
xFields(xFieldsAccess->createEnumeration());
+    uno::Reference<text::XTextField> xField(xFields->nextElement(), 
uno::UNO_QUERY);
+    // unspecified SAVEDATE gets default GB formatting because stylele.xml has 
w:lang w:val="en-GB"
+    //CPPUNIT_ASSERT_EQUAL(OUString("08/04/2022 07:10:00 AM"), 
xField->getPresentation(false));
+    //CPPUNIT_ASSERT_EQUAL(OUString("DocInformation:Modified"), 
xField->getPresentation(true));
+    //xField.set(xFields->nextElement(), uno::UNO_QUERY);
+    // MS Word actually shows "8 o'clock-ish" until the document is reprinted,
+    // but it seems best to actually show the real last-printed date since it 
can't be FIXEDFLD
+    CPPUNIT_ASSERT_EQUAL(OUString("08/04/2022 06:47:00 AM"), 
xField->getPresentation(false));
+    CPPUNIT_ASSERT_EQUAL(OUString("DocInformation:Last printed"), 
xField->getPresentation(true));
+}
+
 DECLARE_OOXMLEXPORT_TEST(testTdf132475_printField, "tdf132475_printField.docx")
 {
     // The last printed date field: formatted two different ways
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 6206a9386edb..d8327fa8d248 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -35,6 +35,8 @@
 #include <com/sun/star/document/IndexedPropertyValues.hpp>
 #include <com/sun/star/drawing/XDrawPageSupplier.hpp>
 #include <com/sun/star/embed/XEmbeddedObject.hpp>
+#include <com/sun/star/i18n/NumberFormatMapper.hpp>
+#include <com/sun/star/i18n/NumberFormatIndex.hpp>
 #include <com/sun/star/lang/XServiceInfo.hpp>
 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
 #include <com/sun/star/style/LineNumberPosition.hpp>
@@ -1187,6 +1189,15 @@ uno::Any DomainMapper_Impl::GetAnyProperty(PropertyIds 
eId, const PropertyMapPtr
             return aProperty->second;
     }
 
+    // then look whether it was directly applied as a paragraph property
+    PropertyMapPtr pParaContext = GetTopContextOfType(CONTEXT_PARAGRAPH);
+    if (pParaContext && rContext != pParaContext)
+    {
+        std::optional<PropertyMap::Property> aProperty = 
pParaContext->getProperty(eId);
+        if (aProperty)
+            return aProperty->second;
+    }
+
     // then look whether it was inherited from a directly applied character 
style
     if ( eId != PROP_CHAR_STYLE_NAME && isCharacterProperty(eId) )
     {
@@ -4429,23 +4440,6 @@ static OUString lcl_trim(std::u16string_view sValue)
     return OUString(o3tl::trim(sValue)).replaceAll("\"","").replaceAll(u"“", 
"").replaceAll(u"”", "");
 }
 
-void DomainMapper_Impl::GetCurrentLocale(lang::Locale& rLocale)
-{
-    PropertyMapPtr pTopContext = GetTopContext();
-    std::optional<PropertyMap::Property> pLocale = 
pTopContext->getProperty(PROP_CHAR_LOCALE);
-    if( pLocale )
-        pLocale->second >>= rLocale;
-    else
-    {
-        PropertyMapPtr pParaContext = GetTopContextOfType(CONTEXT_PARAGRAPH);
-        pLocale = pParaContext->getProperty(PROP_CHAR_LOCALE);
-        if( pLocale )
-        {
-            pLocale->second >>= rLocale;
-        }
-    }
-}
-
 /*-------------------------------------------------------------------------
     extract the number format from the command and apply the resulting number
     format to the XPropertySet
@@ -4461,9 +4455,39 @@ void DomainMapper_Impl::SetNumberFormat( const OUString& 
rCommand,
     aUSLocale.Language = "en";
     aUSLocale.Country = "US";
 
-    //determine current locale - todo: is it necessary to initialize this 
locale?
-    lang::Locale aCurrentLocale = aUSLocale;
-    GetCurrentLocale( aCurrentLocale );
+    lang::Locale aCurrentLocale;
+    GetAnyProperty(PROP_CHAR_LOCALE, GetTopContext()) >>= aCurrentLocale;
+
+    if (sFormatString.isEmpty())
+    {
+        // No format specified. MS Word uses different formats depending on 
w:lang,
+        // "M/d/yyyy h:mm:ss AM/PM" for en-US, and "dd/MM/yyyy hh:mm:ss AM/PM" 
for en-GB.
+        // ALSO SEE: ww8par5's GetWordDefaultDateStringAsUS.
+        sal_Int32 nPos = rCommand.indexOf(" \\");
+        OUString sCommand = nPos == -1 ? rCommand.trim()
+                                       : 
OUString(o3tl::trim(rCommand.subView(0, nPos)));
+        if (sCommand == "CREATEDATE" || sCommand == "PRINTDATE" || sCommand == 
"SAVEDATE")
+        {
+            try
+            {
+                css::uno::Reference<css::i18n::XNumberFormatCode> const& 
xNumberFormatCode =
+                    i18n::NumberFormatMapper::create(m_xComponentContext);
+                sFormatString = xNumberFormatCode->getFormatCode(
+                    css::i18n::NumberFormatIndex::DATE_SYSTEM_SHORT, 
aCurrentLocale).Code;
+                nPos = sFormatString.indexOf("YYYY");
+                if (nPos == -1)
+                    sFormatString = sFormatString.replaceFirst("YY", "YYYY");
+                if (aCurrentLocale == aUSLocale)
+                    sFormatString += " h:mm:ss AM/PM";
+                else
+                    sFormatString += " hh:mm:ss AM/PM";
+            }
+            catch(const uno::Exception&)
+            {
+                DBG_UNHANDLED_EXCEPTION("writerfilter.dmapper");
+            }
+        }
+    }
     OUString sFormat = ConversionHelper::ConvertMSFormatStringToSO( 
sFormatString, aCurrentLocale, bHijri);
     //get the number formatter and convert the string to a format value
     try
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.hxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
index a8355e17a4c9..32721e170c38 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.hxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.hxx
@@ -614,7 +614,6 @@ private:
     bool m_bAnnotationResolved = false;
     std::unordered_map< sal_Int32, AnnotationPosition > m_aAnnotationPositions;
 
-    void GetCurrentLocale(css::lang::Locale& rLocale);
     void SetNumberFormat(const OUString& rCommand, 
css::uno::Reference<css::beans::XPropertySet> const& xPropertySet, bool 
bDetectFormat = false);
     /// @throws css::uno::Exception
     css::uno::Reference<css::beans::XPropertySet> 
FindOrCreateFieldMaster(const char* pFieldMasterService, const OUString& 
rFieldMasterName);

Reply via email to