tdf#132475 sw ms: import/export DI_CHANGE as field

and (only) the AUTHOR portion as FIXED for DOC/DOCX/RTF.

The SAVEDATE import was failing as a field because of exception
writerfilter/source/dmapper/DomainMapper_Impl.cxx:6950:
Exception in CloseFieldCommand() com.sun.star.lang.ServiceNotRegisteredException
message: "unknown service: com.sun.star.text.TextField.DocInfo.Change
at /persistent/git/libreoffice2/svx/source/unodraw/unomod.cxx:191"

In terms of marking the field FIXED:
MS Word doesn't update the save date while the document is being edited
(although a user could force an update via F9)
but it does update the field at FILEOPEN!

So, since it updates the date on FILEOPEN, it makes perfect sense
to treat this as a normal SAVEDATE field in LO - not fixed at all.
At opening time, it will ignore the last-displayed-text
and load the values from the field just like Word.
The difference will be that it updates the field immediately
after a while-editing-save, but that's fine, because when Word opens
the same file, that is what it will see.

However, curiously enough, MS Word does NOT update the LASTSAVEBY user,
and thus the modified author can be set as FIXED,
with the normal caveat that a LO user won't be able to update
the field (except by deleting and re-creating it).

Change-Id: I5640432708cf3eebb6a60eaa500fdf0b8f3a6e1b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/133209
Tested-by: Jenkins
Reviewed-by: Justin Luth <jluth@mail.com>
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
index 464c0b2..737dbc0 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport17.cxx
@@ -85,7 +85,7 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148380_createField, "tdf148380_createField.docx"

DECLARE_OOXMLEXPORT_TEST(testTdf148380_modifiedField, "tdf148380_modifiedField.docx")
{
    getParagraph(2, "4/5/2022 4:29:00 PM"); // default (unspecified) date format
    getParagraph(2, "4/5/2022 3:29:00 PM"); // default (unspecified) date format

    // Verify that these are fields, and not just plain text
    uno::Reference<text::XTextFieldsSupplier> xTextFieldsSupplier(mxComponent, uno::UNO_QUERY);
@@ -93,11 +93,10 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148380_modifiedField, "tdf148380_modifiedField.d
    uno::Reference<container::XEnumeration> xFields(xFieldsAccess->createEnumeration());
    uno::Reference<text::XTextField> xField(xFields->nextElement(), uno::UNO_QUERY);
    // unspecified SAVEDATE gets default US formatting because style.xml has w:lang w:val="en-US"
    //CPPUNIT_ASSERT_EQUAL(OUString("4/5/2022 4:29:00 PM"), xField->getPresentation(false));
    //xField.set(xFields->nextElement(), uno::UNO_QUERY);
    // FIXME: This was hand-modified and really should be Charlie Brown
    CPPUNIT_ASSERT_EQUAL_MESSAGE("Did you fix me? I really should be Charlie Brown (or a date)",
                                 OUString("Charles Brown"), xField->getPresentation(false));
    CPPUNIT_ASSERT_EQUAL(OUString("4/5/2022 3:29:00 PM"), xField->getPresentation(false));
    xField.set(xFields->nextElement(), uno::UNO_QUERY);
    // This was hand-modified and really should be Charlie Brown, not Charles ...
    CPPUNIT_ASSERT_EQUAL(OUString("Charlie Brown"), xField->getPresentation(false));
}

DECLARE_OOXMLEXPORT_TEST(testTdf148380_printField, "tdf148380_printField.docx")
@@ -108,9 +107,9 @@ DECLARE_OOXMLEXPORT_TEST(testTdf148380_printField, "tdf148380_printField.docx")
    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);
    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));
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
index a5e650e..c5dd0ad 100644
--- a/sw/source/filter/ww8/ww8atr.cxx
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -2947,7 +2947,10 @@ void AttributeOutputBase::TextField( const SwFormatField& rField )

                case DI_CHANGE:
                    if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK))
                    {
                        eField = ww::eLASTSAVEDBY;
                        bWriteExpand=false;
                    }
                    else if (GetExport().GetNumberFormat(*pField, sStr) || sStr.isEmpty())
                        eField = ww::eSAVEDATE;
                    break;
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
index 1029e98..e6ec235 100644
--- a/sw/source/filter/ww8/ww8par5.cxx
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -1710,10 +1710,12 @@ eF_ResT SwWW8ImplReader::Read_F_DocInfo( WW8FieldDesc* pF, OUString& rStr )
            nSub = DI_COMMENT;
            break;
        case 20:
            nSub = DI_CHANGE;
            // MS Word never updates this automatically, so mark as fixed for best compatibility
            nSub = DI_CHANGE | DI_SUB_FIXED;
            nReg = DI_SUB_AUTHOR;
            break;
        case 21:
            // The real create date can never change, so mark as fixed for best compatibility
            nSub = DI_CREATE | DI_SUB_FIXED;
            nReg = DI_SUB_DATE;
            bDateTime = true;
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index d8327fa..5422d26 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -5192,7 +5192,7 @@ static const FieldConversionMap_t & lcl_GetFieldConversion()
        {"PRINTDATE",       {"DocInfo.PrintDateTime",   FIELD_PRINTDATE     }},
        {"REF",             {"GetReference",            FIELD_REF           }},
        {"REVNUM",          {"DocInfo.Revision",        FIELD_REVNUM        }},
        {"SAVEDATE",        {"DocInfo.Change",          FIELD_SAVEDATE      }},
        {"SAVEDATE",        {"DocInfo.ChangeDateTime",  FIELD_SAVEDATE      }},
//      {"SECTION",         {"",                        FIELD_SECTION       }},
//      {"SECTIONPAGES",    {"",                        FIELD_SECTIONPAGES  }},
        {"SEQ",             {"SetExpression",           FIELD_SEQ           }},
@@ -6393,6 +6393,7 @@ void DomainMapper_Impl::CloseFieldCommand()
                break;
                case FIELD_CREATEDATE  :
                case FIELD_PRINTDATE:
                case FIELD_SAVEDATE:
                {
                    xFieldProperties->setPropertyValue(
                        getPropertyName( PROP_IS_DATE ), uno::makeAny( true ));
@@ -6621,7 +6622,10 @@ void DomainMapper_Impl::CloseFieldCommand()
                    }
                }
                break;
                case FIELD_LASTSAVEDBY  : break;
                case FIELD_LASTSAVEDBY :
                    xFieldProperties->setPropertyValue(
                        getPropertyName(PROP_IS_FIXED), uno::makeAny(true));
                    break;
                case FIELD_MACROBUTTON:
                {
                    //extract macro name
@@ -6727,9 +6731,6 @@ void DomainMapper_Impl::CloseFieldCommand()
                }
                break;
                case FIELD_REVNUM       : break;
                case FIELD_SAVEDATE     :
                    SetNumberFormat( pContext->GetCommand(), xFieldProperties );
                break;
                case FIELD_SECTION      : break;
                case FIELD_SECTIONPAGES : break;
                case FIELD_SEQ          :