/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */
 
 
/** @#file
 *
 *  export of all text fields
 */
#include <txtflde.hxx>
#include <xmloff/XMLEventExport.hxx>
#include <xmloff/families.hxx>
#include <xmloff/nmspmap.hxx>
#include <xmloff/numehelp.hxx>
#include <xmloff/xmlement.hxx>
#include <xmloff/xmlexp.hxx>
#include <xmloff/xmlnume.hxx>
#include <xmloff/xmlnumfe.hxx>
#include <xmloff/xmltoken.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/maptype.hxx>
 
#include "XMLTextCharStyleNamesElementExport.hxx"
#include <sax/tools/converter.hxx>
 
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/text/UserDataPart.hpp>
#include <com/sun/star/text/PageNumberType.hpp>
#include <com/sun/star/style/NumberingType.hpp>
#include <com/sun/star/text/ReferenceFieldPart.hpp>
#include <com/sun/star/text/ReferenceFieldSource.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/XPropertyState.hpp>
#include <com/sun/star/text/XTextField.hpp>
#include <com/sun/star/text/XDependentTextField.hpp>
#include <com/sun/star/text/XTextFieldsSupplier.hpp>
 
#include <com/sun/star/text/SetVariableType.hpp>
#include <com/sun/star/text/PlaceholderType.hpp>
#include <com/sun/star/text/FilenameDisplayFormat.hpp>
#include <com/sun/star/text/ChapterFormat.hpp>
#include <com/sun/star/text/TemplateDisplayFormat.hpp>
#include <com/sun/star/container/XNameReplace.hpp>
#include <com/sun/star/uno/Sequence.h>
#include <com/sun/star/util/NumberFormat.hpp>
#include <com/sun/star/text/BibliographyDataType.hpp>
#include <com/sun/star/sdb/CommandType.hpp>
#include <com/sun/star/rdf/XMetadatable.hpp>
#include <o3tl/any.hxx>
#include <rtl/ustrbuf.hxx>
#include <tools/debug.hxx>
#include <rtl/math.hxx>
#include <sal/log.hxx>
 
#include <vector>
 
 
using namespace ::std;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::style;
using namespace ::com::sun::star::document;
using namespace ::com::sun::star::container;
using namespace ::xmloff::token;
 
 
static sal_Char const FIELD_SERVICE_SENDER[] = "ExtendedUser";
static sal_Char const FIELD_SERVICE_AUTHOR[] = "Author";
static sal_Char const FIELD_SERVICE_JUMPEDIT[] = "JumpEdit";
static sal_Char const FIELD_SERVICE_GETEXP[] = "GetExpression";
static sal_Char const FIELD_SERVICE_SETEXP[] = "SetExpression";
static sal_Char const FIELD_SERVICE_USER[] = "User";
static sal_Char const FIELD_SERVICE_INPUT[] = "Input";
static sal_Char const FIELD_SERVICE_USERINPUT[] = "InputUser";
static sal_Char const FIELD_SERVICE_DATETIME[] = "DateTime";
static sal_Char const FIELD_SERVICE_PAGENUMBER[] = "PageNumber";
static sal_Char const FIELD_SERVICE_DB_NEXT[] = "DatabaseNextSet";
static sal_Char const FIELD_SERVICE_DB_SELECT[] = "DatabaseNumberOfSet";
static sal_Char const FIELD_SERVICE_DB_NUMBER[] = "DatabaseSetNumber";
static sal_Char const FIELD_SERVICE_DB_DISPLAY[] = "Database";
static sal_Char const FIELD_SERVICE_DB_NAME[] = "DatabaseName";
static sal_Char const FIELD_SERVICE_CONDITIONAL_TEXT[] = "ConditionalText";
static sal_Char const FIELD_SERVICE_HIDDEN_TEXT[] = "HiddenText";
static sal_Char const FIELD_SERVICE_HIDDEN_PARAGRAPH[] = "HiddenParagraph";
static sal_Char const FIELD_SERVICE_DOC_INFO_CHANGE_AUTHOR[] = "DocInfo.ChangeAuthor";
static sal_Char const FIELD_SERVICE_DOC_INFO_CHANGE_AUTHOR2[] = "docinfo.ChangeAuthor";
static sal_Char const FIELD_SERVICE_DOC_INFO_CHANGE_DATE_TIME[] = "DocInfo.ChangeDateTime";
static sal_Char const FIELD_SERVICE_DOC_INFO_CHANGE_DATE_TIME2[] = "docinfo.ChangeDateTime";
static sal_Char const FIELD_SERVICE_DOC_INFO_EDIT_TIME[] = "DocInfo.EditTime";
static sal_Char const FIELD_SERVICE_DOC_INFO_EDIT_TIME2[] = "docinfo.EditTime";
static sal_Char const FIELD_SERVICE_DOC_INFO_DESCRIPTION[] = "DocInfo.Description";
static sal_Char const FIELD_SERVICE_DOC_INFO_DESCRIPTION2[] = "docinfo.Description";
static sal_Char const FIELD_SERVICE_DOC_INFO_CREATE_AUTHOR[] = "DocInfo.CreateAuthor";
static sal_Char const FIELD_SERVICE_DOC_INFO_CREATE_AUTHOR2[] = "docinfo.CreateAuthor";
static sal_Char const FIELD_SERVICE_DOC_INFO_CREATE_DATE_TIME[] = "DocInfo.CreateDateTime";
static sal_Char const FIELD_SERVICE_DOC_INFO_CREATE_DATE_TIME2[] = "docinfo.CreateDateTime";
static sal_Char const FIELD_SERVICE_DOC_INFO_CUSTOM[] = "DocInfo.Custom";
static sal_Char const FIELD_SERVICE_DOC_INFO_CUSTOM2[] = "docinfo.Custom";
static sal_Char const FIELD_SERVICE_DOC_INFO_PRINT_AUTHOR[] = "DocInfo.PrintAuthor";
static sal_Char const FIELD_SERVICE_DOC_INFO_PRINT_AUTHOR2[] = "docinfo.PrintAuthor";
static sal_Char const FIELD_SERVICE_DOC_INFO_PRINT_DATE_TIME[] = "DocInfo.PrintDateTime";
static sal_Char const FIELD_SERVICE_DOC_INFO_PRINT_DATE_TIME2[] = "docinfo.PrintDateTime";
static sal_Char const FIELD_SERVICE_DOC_INFO_KEY_WORDS[] = "DocInfo.KeyWords";
static sal_Char const FIELD_SERVICE_DOC_INFO_KEY_WORDS2[] = "docinfo.KeyWords";
static sal_Char const FIELD_SERVICE_DOC_INFO_SUBJECT[] = "DocInfo.Subject";
static sal_Char const FIELD_SERVICE_DOC_INFO_SUBJECT2[] = "docinfo.Subject";
static sal_Char const FIELD_SERVICE_DOC_INFO_TITLE[] = "DocInfo.Title";
static sal_Char const FIELD_SERVICE_DOC_INFO_TITLE2[] = "docinfo.Title";
static sal_Char const FIELD_SERVICE_DOC_INFO_REVISION[] = "DocInfo.Revision";
static sal_Char const FIELD_SERVICE_DOC_INFO_REVISION2[] = "docinfo.Revision";
static sal_Char const FIELD_SERVICE_FILE_NAME[] = "FileName";
static sal_Char const FIELD_SERVICE_CHAPTER[] = "Chapter";
static sal_Char const FIELD_SERVICE_TEMPLATE_NAME[] = "TemplateName";
static sal_Char const FIELD_SERVICE_PAGE_COUNT[] = "PageCount";
static sal_Char const FIELD_SERVICE_PARAGRAPH_COUNT[] = "ParagraphCount";
static sal_Char const FIELD_SERVICE_WORD_COUNT[] = "WordCount";
static sal_Char const FIELD_SERVICE_CHARACTER_COUNT[] = "CharacterCount";
static sal_Char const FIELD_SERVICE_TABLE_COUNT[] = "TableCount";
static sal_Char const FIELD_SERVICE_GRAPHIC_COUNT[] = "GraphicObjectCount";
static sal_Char const FIELD_SERVICE_OBJECT_COUNT[] = "EmbeddedObjectCount";
static sal_Char const FIELD_SERVICE_REFERENCE_PAGE_SET[] = "ReferencePageSet";
static sal_Char const FIELD_SERVICE_REFERENCE_PAGE_GET[] = "ReferencePageGet";
static sal_Char const FIELD_SERVICE_SHEET_NAME[] = "SheetName";
static sal_Char const FIELD_SERVICE_PAGE_NAME[] = "PageName";
static sal_Char const FIELD_SERVICE_MACRO[] = "Macro";
static sal_Char const FIELD_SERVICE_GET_REFERENCE[] = "GetReference";
static sal_Char const FIELD_SERVICE_DDE[] = "DDE";
static sal_Char const FIELD_SERVICE_URL[] = "URL";
static sal_Char const FIELD_SERVICE_BIBLIOGRAPHY[] = "Bibliography";
static sal_Char const FIELD_SERVICE_SCRIPT[] = "Script";
static sal_Char const FIELD_SERVICE_ANNOTATION[] = "Annotation";
static sal_Char const FIELD_SERVICE_COMBINED_CHARACTERS[] = "CombinedCharacters";
static sal_Char const FIELD_SERVICE_META[] = "MetadataField";
static sal_Char const FIELD_SERVICE_MEASURE[] = "Measure";
static sal_Char const FIELD_SERVICE_TABLE_FORMULA[] = "TableFormula";
static sal_Char const FIELD_SERVICE_DROP_DOWN[] = "DropDown";
 
SvXMLEnumStringMapEntry<FieldIdEnum> const aFieldServiceNameMapping[] =
{
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SENDER, FIELD_ID_SENDER ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_AUTHOR, FIELD_ID_AUTHOR ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_JUMPEDIT, FIELD_ID_PLACEHOLDER ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_GETEXP, FIELD_ID_VARIABLE_GET ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SETEXP, FIELD_ID_VARIABLE_SET ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_USER, FIELD_ID_USER_GET ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_INPUT, FIELD_ID_TEXT_INPUT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_USERINPUT, FIELD_ID_USER_INPUT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DATETIME, FIELD_ID_TIME ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PAGENUMBER, FIELD_ID_PAGENUMBER ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_REFERENCE_PAGE_SET, FIELD_ID_REFPAGE_SET ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_REFERENCE_PAGE_GET, FIELD_ID_REFPAGE_GET ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_NEXT, FIELD_ID_DATABASE_NEXT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_SELECT, FIELD_ID_DATABASE_SELECT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_NUMBER, FIELD_ID_DATABASE_NUMBER ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_DISPLAY, FIELD_ID_DATABASE_DISPLAY ),
    // workaround for #no-bug#: Database/DataBase
    ENUM_STRING_MAP_ENTRY( "DataBase", FIELD_ID_DATABASE_DISPLAY ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DB_NAME, FIELD_ID_DATABASE_NAME ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CREATE_AUTHOR, FIELD_ID_DOCINFO_CREATION_AUTHOR ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CREATE_AUTHOR2, FIELD_ID_DOCINFO_CREATION_AUTHOR ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CREATE_DATE_TIME, FIELD_ID_DOCINFO_CREATION_TIME),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CREATE_DATE_TIME2, FIELD_ID_DOCINFO_CREATION_TIME),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CHANGE_AUTHOR, FIELD_ID_DOCINFO_SAVE_AUTHOR ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CHANGE_AUTHOR2, FIELD_ID_DOCINFO_SAVE_AUTHOR ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CHANGE_DATE_TIME, FIELD_ID_DOCINFO_SAVE_TIME ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CHANGE_DATE_TIME2, FIELD_ID_DOCINFO_SAVE_TIME ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_EDIT_TIME, FIELD_ID_DOCINFO_EDIT_DURATION ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_EDIT_TIME2, FIELD_ID_DOCINFO_EDIT_DURATION ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_DESCRIPTION, FIELD_ID_DOCINFO_DESCRIPTION ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_DESCRIPTION2, FIELD_ID_DOCINFO_DESCRIPTION ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CUSTOM, FIELD_ID_DOCINFO_CUSTOM ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_CUSTOM2, FIELD_ID_DOCINFO_CUSTOM ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_PRINT_AUTHOR, FIELD_ID_DOCINFO_PRINT_AUTHOR ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_PRINT_AUTHOR2, FIELD_ID_DOCINFO_PRINT_AUTHOR ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_PRINT_DATE_TIME, FIELD_ID_DOCINFO_PRINT_TIME ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_PRINT_DATE_TIME2, FIELD_ID_DOCINFO_PRINT_TIME ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_KEY_WORDS, FIELD_ID_DOCINFO_KEYWORDS ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_KEY_WORDS2, FIELD_ID_DOCINFO_KEYWORDS ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_SUBJECT, FIELD_ID_DOCINFO_SUBJECT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_SUBJECT2, FIELD_ID_DOCINFO_SUBJECT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_TITLE, FIELD_ID_DOCINFO_TITLE ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_TITLE2, FIELD_ID_DOCINFO_TITLE ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_REVISION, FIELD_ID_DOCINFO_REVISION ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DOC_INFO_REVISION2, FIELD_ID_DOCINFO_REVISION ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_CONDITIONAL_TEXT, FIELD_ID_CONDITIONAL_TEXT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_HIDDEN_TEXT, FIELD_ID_HIDDEN_TEXT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_HIDDEN_PARAGRAPH, FIELD_ID_HIDDEN_PARAGRAPH ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_FILE_NAME, FIELD_ID_FILE_NAME ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_CHAPTER, FIELD_ID_CHAPTER ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_TEMPLATE_NAME, FIELD_ID_TEMPLATE_NAME ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PAGE_COUNT, FIELD_ID_COUNT_PAGES ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PARAGRAPH_COUNT, FIELD_ID_COUNT_PARAGRAPHS ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_WORD_COUNT, FIELD_ID_COUNT_WORDS ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_CHARACTER_COUNT, FIELD_ID_COUNT_CHARACTERS ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_TABLE_COUNT, FIELD_ID_COUNT_TABLES ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_GRAPHIC_COUNT, FIELD_ID_COUNT_GRAPHICS ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_OBJECT_COUNT, FIELD_ID_COUNT_OBJECTS ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_MACRO, FIELD_ID_MACRO ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_GET_REFERENCE, FIELD_ID_REF_REFERENCE ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DDE, FIELD_ID_DDE ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_BIBLIOGRAPHY, FIELD_ID_BIBLIOGRAPHY ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SCRIPT, FIELD_ID_SCRIPT ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_ANNOTATION, FIELD_ID_ANNOTATION ),
 
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_COMBINED_CHARACTERS, FIELD_ID_COMBINED_CHARACTERS ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_META, FIELD_ID_META ),
 
    // non-writer fields
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_SHEET_NAME, FIELD_ID_SHEET_NAME ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_PAGE_NAME, FIELD_ID_PAGENAME ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_URL, FIELD_ID_URL ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_MEASURE, FIELD_ID_MEASURE ),
 
    // deprecated fields
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_TABLE_FORMULA, FIELD_ID_TABLE_FORMULA ),
    ENUM_STRING_MAP_ENTRY( FIELD_SERVICE_DROP_DOWN, FIELD_ID_DROP_DOWN ),
 
    { nullptr, 0, FieldIdEnum(0) }
};
 
 
// property accessor helper functions
inline bool GetBoolProperty(const OUString&,
                                      const Reference<XPropertySet> &);
inline bool GetOptionalBoolProperty(const OUString&,
                                              const Reference<XPropertySet> &,
                                              const Reference<XPropertySetInfo> &,
                                              bool bDefault);
inline double GetDoubleProperty(const OUString&,
                                      const Reference<XPropertySet> &);
inline OUString const GetStringProperty(const OUString&,
                                        const Reference<XPropertySet> &);
inline sal_Int32 GetIntProperty(const OUString&,
                                      const Reference<XPropertySet> &);
inline sal_Int16 GetInt16Property(const OUString&,
                                        const Reference<XPropertySet> &);
inline sal_Int8 GetInt8Property(const OUString&,
                                      const Reference<XPropertySet> &);
inline util::DateTime const GetDateTimeProperty( const OUString& sPropName,
                                           const Reference<XPropertySet> & xPropSet);
inline Sequence<OUString> const GetStringSequenceProperty(
                                   const OUString& sPropName,
                                   const Reference<XPropertySet> & xPropSet);
 
 
    // service names
static const OUStringLiteral gsServicePrefix("com.sun.star.text.textfield.");
static const OUStringLiteral gsFieldMasterPrefix("com.sun.star.text.FieldMaster.");
static const OUStringLiteral gsPresentationServicePrefix("com.sun.star.presentation.TextField.");
 
    // property names
static const OUStringLiteral gsPropertyAdjust("Adjust");
static const OUStringLiteral gsPropertyAuthor("Author");
static const OUStringLiteral gsPropertyChapterFormat("ChapterFormat");
static const OUStringLiteral gsPropertyChapterNumberingLevel("ChapterNumberingLevel");
static const OUStringLiteral gsPropertyCharStyleNames("CharStyleNames");
static const OUStringLiteral gsPropertyCondition("Condition");
static const OUStringLiteral gsPropertyContent("Content");
static const OUStringLiteral gsPropertyDataBaseName("DataBaseName");
static const OUStringLiteral gsPropertyDataBaseURL("DataBaseURL");
static const OUStringLiteral gsPropertyDataColumnName("DataColumnName");
static const OUStringLiteral gsPropertyDataCommandType("DataCommandType");
static const OUStringLiteral gsPropertyDataTableName("DataTableName");
static const OUStringLiteral gsPropertyDateTime("DateTime");
static const OUStringLiteral gsPropertyDateTimeValue("DateTimeValue");
static const OUStringLiteral gsPropertyDDECommandElement("DDECommandElement");
static const OUStringLiteral gsPropertyDDECommandFile("DDECommandFile");
static const OUStringLiteral gsPropertyDDECommandType("DDECommandType");
static const OUStringLiteral gsPropertyDependentTextFields("DependentTextFields");
static const OUStringLiteral gsPropertyFalseContent("FalseContent");
static const OUStringLiteral gsPropertyFields("Fields");
static const OUStringLiteral gsPropertyFieldSubType("UserDataType");
static const OUStringLiteral gsPropertyFileFormat("FileFormat");
static const OUStringLiteral gsPropertyFullName("FullName");
static const OUStringLiteral gsPropertyHint("Hint");
static const OUStringLiteral gsPropertyInitials("Initials");
static const OUStringLiteral gsPropertyInstanceName("InstanceName");
static const OUStringLiteral gsPropertyIsAutomaticUpdate("IsAutomaticUpdate");
static const OUStringLiteral gsPropertyIsConditionTrue("IsConditionTrue");
static const OUStringLiteral gsPropertyIsDataBaseFormat("DataBaseFormat");
static const OUStringLiteral gsPropertyIsDate("IsDate");
static const OUStringLiteral gsPropertyIsExpression("IsExpression");
static const OUStringLiteral gsPropertyIsFixed("IsFixed");
static const OUStringLiteral gsPropertyIsFixedLanguage("IsFixedLanguage");
static const OUStringLiteral gsPropertyIsHidden("IsHidden");
static const OUStringLiteral gsPropertyIsInput("Input");
static const OUStringLiteral gsPropertyIsShowFormula("IsShowFormula");
static const OUStringLiteral gsPropertyIsVisible("IsVisible");
static const OUStringLiteral gsPropertyItems("Items");
static const OUStringLiteral gsPropertyLevel("Level");
static const OUStringLiteral gsPropertyMeasureKind("Kind");
static const OUStringLiteral gsPropertyName("Name");
static const OUStringLiteral gsPropertyNumberFormat("NumberFormat");
static const OUStringLiteral gsPropertyNumberingSeparator("NumberingSeparator");
static const OUStringLiteral gsPropertyNumberingType("NumberingType");
static const OUStringLiteral gsPropertyOffset("Offset");
static const OUStringLiteral gsPropertyOn("On");
static const OUStringLiteral gsPropertyPlaceholderType("PlaceHolderType");
static const OUStringLiteral gsPropertyReferenceFieldPart("ReferenceFieldPart");
static const OUStringLiteral gsPropertyReferenceFieldSource("ReferenceFieldSource");
static const OUStringLiteral gsPropertyReferenceFieldLanguage("ReferenceFieldLanguage");
static const OUStringLiteral gsPropertyScriptType("ScriptType");
static const OUStringLiteral gsPropertySelectedItem("SelectedItem");
static const OUStringLiteral gsPropertySequenceNumber("SequenceNumber");
static const OUStringLiteral gsPropertySequenceValue("SequenceValue");
static const OUStringLiteral gsPropertySetNumber("SetNumber");
static const OUStringLiteral gsPropertySourceName("SourceName");
static const OUStringLiteral gsPropertySubType("SubType");
static const OUStringLiteral gsPropertyTargetFrame("TargetFrame");
static const OUStringLiteral gsPropertyTrueContent("TrueContent");
static const OUStringLiteral gsPropertyURL("URL");
static const OUStringLiteral gsPropertyURLContent("URLContent");
static const OUStringLiteral gsPropertyUserText("UserText");
static const OUStringLiteral gsPropertyValue("Value");
static const OUStringLiteral gsPropertyVariableName("VariableName");
static const OUStringLiteral gsPropertyHelp("Help");
static const OUStringLiteral gsPropertyTooltip("Tooltip");
static const OUStringLiteral gsPropertyTextRange("TextRange");
 
XMLTextFieldExport::XMLTextFieldExport( SvXMLExport& rExp,
                                        std::unique_ptr<XMLPropertyState> pCombinedCharState)
    : rExport(rExp),
      pCombinedCharactersPropertyState(std::move(pCombinedCharState))
{
    SetExportOnlyUsedFieldDeclarations();
}
 
XMLTextFieldExport::~XMLTextFieldExport()
{
}
 
/// get the field ID (as in FieldIDEnum) from XTextField
enum FieldIdEnum XMLTextFieldExport::GetFieldID(
    const Reference<XTextField> & rTextField,
    const Reference<XPropertySet> & xPropSet)
{
    // get service names for rTextField (via XServiceInfo service)
    Reference<XServiceInfo> xService(rTextField, UNO_QUERY);
    const Sequence<OUString> aServices = xService->getSupportedServiceNames();
    const OUString* pNames = aServices.getConstArray();
    sal_Int32 nCount = aServices.getLength();
 
    OUString sFieldName;    // service name postfix of current field
 
    // search for TextField service name
    while( nCount-- )
    {
        if (pNames->matchIgnoreAsciiCase(gsServicePrefix))
        {
            // TextField found => postfix is field type!
            sFieldName = pNames->copy(gsServicePrefix.getLength());
            break;
        }
 
        ++pNames;
    }
 
    // if this is not a normal text field, check if it's a presentation text field
    if( sFieldName.isEmpty() )
    {
        const OUString* pNames2 = aServices.getConstArray();
        sal_Int32 nCount2 = aServices.getLength();
        // search for TextField service name
        while( nCount2-- )
        {
            if( pNames2->startsWith(gsPresentationServicePrefix) )
            {
                // TextField found => postfix is field type!
                sFieldName = pNames2->copy(gsPresentationServicePrefix.getLength());
                break;
            }
 
            ++pNames2;
        }
 
        if( !sFieldName.isEmpty() )
        {
            if( sFieldName == "Header" )
            {
                return FIELD_ID_DRAW_HEADER;
            }
            else if( sFieldName == "Footer" )
            {
                return FIELD_ID_DRAW_FOOTER;
            }
            else if( sFieldName == "DateTime" )
            {
                return FIELD_ID_DRAW_DATE_TIME;
            }
        }
    }
 
    // map postfix of service name to field ID
    DBG_ASSERT(!sFieldName.isEmpty(), "no TextField service found!");
    return MapFieldName(sFieldName, xPropSet);
}
 
enum FieldIdEnum XMLTextFieldExport::MapFieldName(
    const OUString& sFieldName,             // field (master) name
    const Reference<XPropertySet> & xPropSet)   // for subtype
{
    // we'll proceed in 2 steps:
    // a) map service name to preliminary FIELD_ID
    // b) map those prelim. FIELD_IDs that correspond to several field types
    //    (in our (XML) world) to final FIELD IDs
 
 
    // a) find prelim. FIELD_ID via aFieldServiceMapping
 
    // check for non-empty service name
    DBG_ASSERT(!sFieldName.isEmpty(), "no valid service name!");
    enum FieldIdEnum nToken = FIELD_ID_UNKNOWN;
    if (!sFieldName.isEmpty())
    {
        // map name to prelim. ID
        bool bRet = SvXMLUnitConverter::convertEnum(
            nToken, sFieldName, aFieldServiceNameMapping);
 
        // check return
        DBG_ASSERT(bRet, "Unknown field service name encountered!");
    }
 
    // b) map prelim. to final FIELD_IDs
    switch (nToken) {
        case FIELD_ID_VARIABLE_SET:
            if (GetBoolProperty(gsPropertyIsInput, xPropSet))
            {
                nToken = FIELD_ID_VARIABLE_INPUT;
            }
            else
            {
                switch (GetIntProperty(gsPropertySubType, xPropSet))
                {
                    case SetVariableType::STRING:   // text field
                    case SetVariableType::VAR:      // num field
                        nToken = FIELD_ID_VARIABLE_SET;
                        break;
                    case SetVariableType::SEQUENCE:
                        nToken = FIELD_ID_SEQUENCE;
                        break;
                    case SetVariableType::FORMULA:
                    default:
                        nToken = FIELD_ID_UNKNOWN;
                        break;
                }
            }
            break;
 
        case FIELD_ID_VARIABLE_GET:
            switch (GetIntProperty(gsPropertySubType, xPropSet))
            {
                case SetVariableType::STRING:   // text field
                case SetVariableType::VAR:      // num field
                    nToken = FIELD_ID_VARIABLE_GET;
                    break;
                case SetVariableType::FORMULA:
                    nToken = FIELD_ID_EXPRESSION;
                    break;
                case SetVariableType::SEQUENCE:
                default:
                    nToken = FIELD_ID_UNKNOWN;
                    break;
            }
            break;
 
        case FIELD_ID_TIME:
            if (GetBoolProperty(gsPropertyIsDate, xPropSet))
            {
                nToken = FIELD_ID_DATE;
            }
            break;
 
        case FIELD_ID_PAGENUMBER:
            // NumberingType not available in non-Writer apps
            if (xPropSet->getPropertySetInfo()->
                hasPropertyByName(gsPropertyNumberingType))
            {
                if (NumberingType::CHAR_SPECIAL == GetIntProperty(
                                            gsPropertyNumberingType, xPropSet))
                {
                    nToken = FIELD_ID_PAGESTRING;
                }
            }
            break;
 
        case FIELD_ID_DOCINFO_CREATION_TIME:
             if (GetBoolProperty(gsPropertyIsDate, xPropSet))
            {
                nToken = FIELD_ID_DOCINFO_CREATION_DATE;
            }
            break;
 
        case FIELD_ID_DOCINFO_PRINT_TIME:
             if (GetBoolProperty(gsPropertyIsDate, xPropSet))
            {
                nToken = FIELD_ID_DOCINFO_PRINT_DATE;
            }
            break;
 
        case FIELD_ID_DOCINFO_SAVE_TIME:
             if (GetBoolProperty(gsPropertyIsDate, xPropSet))
            {
                nToken = FIELD_ID_DOCINFO_SAVE_DATE;
            }
            break;
 
        case FIELD_ID_REF_REFERENCE:
            switch (GetInt16Property(gsPropertyReferenceFieldSource, xPropSet))
            {
                case ReferenceFieldSource::REFERENCE_MARK:
                    nToken = FIELD_ID_REF_REFERENCE;
                    break;
                case ReferenceFieldSource::SEQUENCE_FIELD:
                    nToken = FIELD_ID_REF_SEQUENCE;
                    break;
                case ReferenceFieldSource::BOOKMARK:
                    nToken = FIELD_ID_REF_BOOKMARK;
                    break;
                case ReferenceFieldSource::FOOTNOTE:
                    nToken = FIELD_ID_REF_FOOTNOTE;
                    break;
                case ReferenceFieldSource::ENDNOTE:
                    nToken = FIELD_ID_REF_ENDNOTE;
                    break;
                default:
                    nToken = FIELD_ID_UNKNOWN;
                    break;
            }
            break;
 
        case FIELD_ID_COMBINED_CHARACTERS:
        case FIELD_ID_SCRIPT:
        case FIELD_ID_ANNOTATION:
        case FIELD_ID_BIBLIOGRAPHY:
        case FIELD_ID_DDE:
        case FIELD_ID_MACRO:
        case FIELD_ID_REFPAGE_SET:
        case FIELD_ID_REFPAGE_GET:
        case FIELD_ID_COUNT_PAGES:
        case FIELD_ID_COUNT_PARAGRAPHS:
        case FIELD_ID_COUNT_WORDS:
        case FIELD_ID_COUNT_CHARACTERS:
        case FIELD_ID_COUNT_TABLES:
        case FIELD_ID_COUNT_GRAPHICS:
        case FIELD_ID_COUNT_OBJECTS:
        case FIELD_ID_CONDITIONAL_TEXT:
        case FIELD_ID_HIDDEN_TEXT:
        case FIELD_ID_HIDDEN_PARAGRAPH:
        case FIELD_ID_DOCINFO_CREATION_AUTHOR:
        case FIELD_ID_DOCINFO_DESCRIPTION:
        case FIELD_ID_DOCINFO_CUSTOM:
        case FIELD_ID_DOCINFO_PRINT_AUTHOR:
        case FIELD_ID_DOCINFO_TITLE:
        case FIELD_ID_DOCINFO_SUBJECT:
        case FIELD_ID_DOCINFO_KEYWORDS:
        case FIELD_ID_DOCINFO_REVISION:
        case FIELD_ID_DOCINFO_EDIT_DURATION:
        case FIELD_ID_DOCINFO_SAVE_AUTHOR:
        case FIELD_ID_TEXT_INPUT:
        case FIELD_ID_USER_INPUT:
        case FIELD_ID_AUTHOR:
        case FIELD_ID_SENDER:
        case FIELD_ID_PLACEHOLDER:
        case FIELD_ID_USER_GET:
        case FIELD_ID_DATABASE_NEXT:
        case FIELD_ID_DATABASE_SELECT:
        case FIELD_ID_DATABASE_DISPLAY:
        case FIELD_ID_DATABASE_NAME:
        case FIELD_ID_DATABASE_NUMBER:
        case FIELD_ID_TEMPLATE_NAME:
        case FIELD_ID_CHAPTER:
        case FIELD_ID_FILE_NAME:
        case FIELD_ID_META:
        case FIELD_ID_SHEET_NAME:
        case FIELD_ID_PAGENAME:
        case FIELD_ID_MEASURE:
        case FIELD_ID_URL:
        case FIELD_ID_TABLE_FORMULA:
        case FIELD_ID_DROP_DOWN:
            ; // these field IDs are final
            break;
 
        default:
            nToken = FIELD_ID_UNKNOWN;
    }
 
    // ... and return final FIELD_ID
    return nToken;
}
 
// is string or numeric field?
bool XMLTextFieldExport::IsStringField(
    FieldIdEnum nFieldType,
    const Reference<XPropertySet> & xPropSet)
{
    switch (nFieldType) {
 
    case FIELD_ID_VARIABLE_GET:
    case FIELD_ID_VARIABLE_SET:
    case FIELD_ID_VARIABLE_INPUT:
    {
        // depends on field sub type
        return ( GetIntProperty(gsPropertySubType, xPropSet) ==
                 SetVariableType::STRING                    );
    }
 
    case FIELD_ID_USER_GET:
    case FIELD_ID_USER_INPUT:
    {
        Reference<XTextField> xTextField(xPropSet, UNO_QUERY);
        DBG_ASSERT(xTextField.is(), "field is no XTextField!");
        bool bRet = GetBoolProperty(gsPropertyIsExpression,
                                        GetMasterPropertySet(xTextField));
        return !bRet;
    }
 
    case FIELD_ID_META:
        return 0 > GetIntProperty(gsPropertyNumberFormat, xPropSet);
 
    case FIELD_ID_DATABASE_DISPLAY:
        // TODO: depends on... ???
        // workaround #no-bug#: no data type
        return 5100 == GetIntProperty(gsPropertyNumberFormat, xPropSet);
 
    case FIELD_ID_TABLE_FORMULA:
        // legacy field: always a number field (because it always has
        // a number format)
        return false;
 
    case FIELD_ID_COUNT_PAGES:
    case FIELD_ID_COUNT_PARAGRAPHS:
    case FIELD_ID_COUNT_WORDS:
    case FIELD_ID_COUNT_CHARACTERS:
    case FIELD_ID_COUNT_TABLES:
    case FIELD_ID_COUNT_GRAPHICS:
    case FIELD_ID_COUNT_OBJECTS:
    case FIELD_ID_DOCINFO_SAVE_TIME:
    case FIELD_ID_DOCINFO_SAVE_DATE:
    case FIELD_ID_DOCINFO_CREATION_DATE:
    case FIELD_ID_DOCINFO_CREATION_TIME:
    case FIELD_ID_DOCINFO_PRINT_TIME:
    case FIELD_ID_DOCINFO_PRINT_DATE:
    case FIELD_ID_DOCINFO_EDIT_DURATION:
    case FIELD_ID_DOCINFO_REVISION:
    case FIELD_ID_DATABASE_NUMBER:
    case FIELD_ID_EXPRESSION:
    case FIELD_ID_SEQUENCE:
    case FIELD_ID_DATE:
    case FIELD_ID_TIME:
    case FIELD_ID_PAGENUMBER:
    case FIELD_ID_REFPAGE_SET:
    case FIELD_ID_REFPAGE_GET:
    case FIELD_ID_DOCINFO_CUSTOM:
        // always number
        return false;
 
    case FIELD_ID_COMBINED_CHARACTERS:
    case FIELD_ID_BIBLIOGRAPHY:
    case FIELD_ID_DDE:
    case FIELD_ID_REF_REFERENCE:
    case FIELD_ID_REF_SEQUENCE:
    case FIELD_ID_REF_BOOKMARK:
    case FIELD_ID_REF_FOOTNOTE:
    case FIELD_ID_REF_ENDNOTE:
    case FIELD_ID_MACRO:
    case FIELD_ID_TEMPLATE_NAME:
    case FIELD_ID_CHAPTER:
    case FIELD_ID_FILE_NAME:
    case FIELD_ID_CONDITIONAL_TEXT:
    case FIELD_ID_HIDDEN_TEXT:
    case FIELD_ID_HIDDEN_PARAGRAPH:
    case FIELD_ID_DOCINFO_CREATION_AUTHOR:
    case FIELD_ID_DOCINFO_DESCRIPTION:
    case FIELD_ID_DOCINFO_PRINT_AUTHOR:
    case FIELD_ID_DOCINFO_TITLE:
    case FIELD_ID_DOCINFO_SUBJECT:
    case FIELD_ID_DOCINFO_KEYWORDS:
    case FIELD_ID_DOCINFO_SAVE_AUTHOR:
    case FIELD_ID_DATABASE_NAME:
    case FIELD_ID_TEXT_INPUT:
    case FIELD_ID_SENDER:
    case FIELD_ID_AUTHOR:
    case FIELD_ID_PAGENAME:
    case FIELD_ID_PAGESTRING:
    case FIELD_ID_SHEET_NAME:
    case FIELD_ID_MEASURE:
    case FIELD_ID_URL:
    case FIELD_ID_DROP_DOWN:
        // always string:
        return true;
 
    case FIELD_ID_SCRIPT:
    case FIELD_ID_ANNOTATION:
    case FIELD_ID_DATABASE_NEXT:
    case FIELD_ID_DATABASE_SELECT:
    case FIELD_ID_PLACEHOLDER:
    case FIELD_ID_UNKNOWN:
    case FIELD_ID_DRAW_HEADER:
    case FIELD_ID_DRAW_FOOTER:
    case FIELD_ID_DRAW_DATE_TIME:
    default:
        OSL_FAIL("unknown field type/field has no content");
        return true; // invalid info; string in case of doubt
    }
}
 
/// export the styles needed by the given field. Called on first pass
/// through document
void XMLTextFieldExport::ExportFieldAutoStyle(
    const Reference<XTextField> & rTextField, const bool bProgress,
    const bool bRecursive )
{
    // get property set
    Reference<XPropertySet> xPropSet(rTextField, UNO_QUERY);
 
    // add field master to list of used field masters (if desired)
    if (nullptr != pUsedMasters)
    {
        Reference<XDependentTextField> xDepField(rTextField, UNO_QUERY);
        if (xDepField.is())
        {
            Reference<XText> xOurText = rTextField->getAnchor()->getText();
 
            map<Reference<XText>, set<OUString> >::iterator aMapIter =
                pUsedMasters->find(xOurText);
 
            // insert a list for our XText (if necessary)
            if (aMapIter == pUsedMasters->end())
            {
                set<OUString> aSet;
                (*pUsedMasters)[xOurText] = aSet;
                aMapIter = pUsedMasters->find(xOurText);
            }
 
            // insert this text field master
            OUString sFieldMasterName = GetStringProperty(
                gsPropertyInstanceName, xDepField->getTextFieldMaster());
            if (!sFieldMasterName.isEmpty())
                aMapIter->second.insert( sFieldMasterName );
        }
        // else: no dependent field -> no master -> ignore
    }
 
    // get Field ID
    FieldIdEnum nToken = GetFieldID(rTextField, xPropSet);
 
    // export the character style for all fields
    // with one exception: combined character fields export their own
    //                     text style below
    Reference <XPropertySet> xRangePropSet(rTextField->getAnchor(), UNO_QUERY);
    if (FIELD_ID_COMBINED_CHARACTERS != nToken)
    {
        GetExport().GetTextParagraphExport()->Add(
            XML_STYLE_FAMILY_TEXT_TEXT, xRangePropSet);
    }
 
    // process special styles for each field (e.g. data styles)
    switch (nToken) {
 
    case FIELD_ID_DATABASE_DISPLAY:
    {
        sal_Int32 nFormat = GetIntProperty(gsPropertyNumberFormat, xPropSet);
        // workaround: #no-bug#; see IsStringField(...)
        if ( (5100 != nFormat) &&
             !GetBoolProperty(gsPropertyIsDataBaseFormat, xPropSet) )
        {
                GetExport().addDataStyle(nFormat);
        }
        break;
    }
 
    case FIELD_ID_DATE:
    case FIELD_ID_TIME:
        {
            // date and time fields are always number fields, but the
            // NumberFormat property is optional (e.g. Calc doesn't
            // support it)
            Reference<XPropertySetInfo> xPropSetInfo(
                xPropSet->getPropertySetInfo() );
            if ( xPropSetInfo->hasPropertyByName( gsPropertyNumberFormat ) )
            {
                sal_Int32 nFormat =
                    GetIntProperty(gsPropertyNumberFormat, xPropSet);
 
                // nFormat may be -1 for numeric fields that display their
                //  variable name. (Maybe this should be a field type, then?)
                if (nFormat != -1)
                {
                    if( ! GetOptionalBoolProperty(
                            gsPropertyIsFixedLanguage,
                            xPropSet, xPropSetInfo, false ) )
                    {
                        nFormat =
                            GetExport().dataStyleForceSystemLanguage(nFormat);
                    }
 
                    GetExport().addDataStyle( nFormat,
                                              nToken == FIELD_ID_TIME );
                }
            }
        }
        break;
 
    case FIELD_ID_META:
        // recurse into content (does not export element, so can be done first)
        if (bRecursive)
        {
            bool dummy_for_autostyles(true);
            ExportMetaField(xPropSet, true, bProgress, dummy_for_autostyles);
        }
        SAL_FALLTHROUGH;
    case FIELD_ID_DOCINFO_PRINT_TIME:
    case FIELD_ID_DOCINFO_PRINT_DATE:
    case FIELD_ID_DOCINFO_CREATION_DATE:
    case FIELD_ID_DOCINFO_CREATION_TIME:
    case FIELD_ID_DOCINFO_SAVE_TIME:
    case FIELD_ID_DOCINFO_SAVE_DATE:
    case FIELD_ID_DOCINFO_EDIT_DURATION:
    case FIELD_ID_VARIABLE_SET:
    case FIELD_ID_VARIABLE_GET:
    case FIELD_ID_VARIABLE_INPUT:
    case FIELD_ID_USER_GET:
    case FIELD_ID_EXPRESSION:
    case FIELD_ID_TABLE_FORMULA:
    case FIELD_ID_DOCINFO_CUSTOM:
        // register number format, if this is a numeric field
        if (! IsStringField(nToken, xPropSet)) {
 
            sal_Int32 nFormat =
                GetIntProperty(gsPropertyNumberFormat, xPropSet);
 
            // nFormat may be -1 for numeric fields that display their
            //  variable name. (Maybe this should be a field type, then?)
            if (nFormat != -1)
            {
                // handle formats for fixed language fields
                // for all these fields (except table formula)
                if( ( nToken != FIELD_ID_TABLE_FORMULA ) &&
                    ! GetOptionalBoolProperty(
                          gsPropertyIsFixedLanguage,
                          xPropSet, xPropSet->getPropertySetInfo(),
                          false ) )
                {
                    nFormat =
                        GetExport().dataStyleForceSystemLanguage(nFormat);
                }
 
                GetExport().addDataStyle(nFormat);
            }
        }
        break;
 
    case FIELD_ID_COMBINED_CHARACTERS:
    {
        // export text style with the addition of the combined characters
        DBG_ASSERT(nullptr != pCombinedCharactersPropertyState,
                   "need proper PropertyState for combined characters");
        const XMLPropertyState *aStates[] = { pCombinedCharactersPropertyState.get(), nullptr };
        GetExport().GetTextParagraphExport()->Add(
            XML_STYLE_FAMILY_TEXT_TEXT, xRangePropSet,
            aStates);
        break;
    }
 
    case FIELD_ID_SCRIPT:
    case FIELD_ID_ANNOTATION:
    case FIELD_ID_BIBLIOGRAPHY:
    case FIELD_ID_DDE:
    case FIELD_ID_REF_REFERENCE:
    case FIELD_ID_REF_SEQUENCE:
    case FIELD_ID_REF_BOOKMARK:
    case FIELD_ID_REF_FOOTNOTE:
    case FIELD_ID_REF_ENDNOTE:
    case FIELD_ID_MACRO:
    case FIELD_ID_REFPAGE_SET:
    case FIELD_ID_REFPAGE_GET:
    case FIELD_ID_COUNT_PAGES:
    case FIELD_ID_COUNT_PARAGRAPHS:
    case FIELD_ID_COUNT_WORDS:
    case FIELD_ID_COUNT_CHARACTERS:
    case FIELD_ID_COUNT_TABLES:
    case FIELD_ID_COUNT_GRAPHICS:
    case FIELD_ID_COUNT_OBJECTS:
    case FIELD_ID_CONDITIONAL_TEXT:
    case FIELD_ID_HIDDEN_TEXT:
    case FIELD_ID_HIDDEN_PARAGRAPH:
    case FIELD_ID_DOCINFO_CREATION_AUTHOR:
    case FIELD_ID_DOCINFO_DESCRIPTION:
    case FIELD_ID_DOCINFO_PRINT_AUTHOR:
    case FIELD_ID_DOCINFO_TITLE:
    case FIELD_ID_DOCINFO_SUBJECT:
    case FIELD_ID_DOCINFO_KEYWORDS:
    case FIELD_ID_DOCINFO_REVISION:
    case FIELD_ID_DOCINFO_SAVE_AUTHOR:
    case FIELD_ID_SEQUENCE:
    case FIELD_ID_PAGENAME:
    case FIELD_ID_PAGENUMBER:
    case FIELD_ID_PAGESTRING:
    case FIELD_ID_AUTHOR:
    case FIELD_ID_SENDER:
    case FIELD_ID_PLACEHOLDER:
    case FIELD_ID_USER_INPUT:
    case FIELD_ID_TEXT_INPUT:
    case FIELD_ID_DATABASE_NEXT:
    case FIELD_ID_DATABASE_SELECT:
    case FIELD_ID_DATABASE_NAME:
    case FIELD_ID_DATABASE_NUMBER:
    case FIELD_ID_TEMPLATE_NAME:
    case FIELD_ID_CHAPTER:
    case FIELD_ID_FILE_NAME:
    case FIELD_ID_SHEET_NAME:
    case FIELD_ID_MEASURE:
    case FIELD_ID_URL:
    case FIELD_ID_DROP_DOWN:
    case FIELD_ID_DRAW_DATE_TIME:
    case FIELD_ID_DRAW_FOOTER:
    case FIELD_ID_DRAW_HEADER:
        ; // no formats for these fields!
        break;
 
    case FIELD_ID_UNKNOWN:
    default:
        OSL_FAIL("unknown field type!");
        // ignore -> no format for unknown
        break;
    }
}
 
/// export the given field to XML. Called on second pass through document
void XMLTextFieldExport::ExportField(
    const Reference<XTextField> & rTextField, bool bProgress,
    bool & rPrevCharIsSpace)
{
    // get property set
    Reference<XPropertySet> xPropSet(rTextField, UNO_QUERY);
 
    // get property set of range (for the attributes)
    Reference <XPropertySet> xRangePropSet(rTextField->getAnchor(), UNO_QUERY);
 
    // get Field ID
    enum FieldIdEnum nToken = GetFieldID(rTextField, xPropSet);
 
    // special treatment for combined characters field, because it is
    // exported as a style
    const XMLPropertyState* aStates[] = { pCombinedCharactersPropertyState.get(), nullptr };
    const XMLPropertyState **pStates =
                FIELD_ID_COMBINED_CHARACTERS == nToken
                    ? aStates
                    : nullptr;
 
    // find out whether we need to set the style or hyperlink
    bool bHasHyperlink;
    bool bIsUICharStyle;
    bool bHasAutoStyle;
    OUString sStyle = GetExport().GetTextParagraphExport()->
        FindTextStyleAndHyperlink( xRangePropSet, bHasHyperlink, bIsUICharStyle,
                                   bHasAutoStyle, pStates );
    bool bHasStyle = !sStyle.isEmpty();
 
    // export hyperlink (if we have one)
    Reference < XPropertySetInfo > xRangePropSetInfo;
    if( bHasHyperlink )
    {
        Reference<XPropertyState> xRangePropState( xRangePropSet, UNO_QUERY );
        xRangePropSetInfo = xRangePropSet->getPropertySetInfo();
        bHasHyperlink =
            GetExport().GetTextParagraphExport()->addHyperlinkAttributes(
                xRangePropSet, xRangePropState,
                xRangePropSetInfo );
    }
    SvXMLElementExport aHyperlink( GetExport(), bHasHyperlink,
                                   XML_NAMESPACE_TEXT, XML_A,
                                   false, false );
 
    if( bHasHyperlink )
    {
        // export events (if supported)
        OUString sHyperLinkEvents("HyperLinkEvents");
        if (xRangePropSetInfo->hasPropertyByName(sHyperLinkEvents))
        {
            Any aAny = xRangePropSet->getPropertyValue(sHyperLinkEvents);
            Reference<XNameReplace> xName;
            aAny >>= xName;
            GetExport().GetEventExport().Export(xName, false);
        }
    }
 
    {
        XMLTextCharStyleNamesElementExport aCharStylesExport(
            GetExport(), bIsUICharStyle &&
                         GetExport().GetTextParagraphExport()
                             ->GetCharStyleNamesPropInfoCache().hasProperty(
                                        xRangePropSet, xRangePropSetInfo ), bHasAutoStyle,
            xRangePropSet, gsPropertyCharStyleNames );
 
        // export span with style (if necessary)
        // (except for combined characters field)
        if( bHasStyle )
        {
            // export <text:span> element
            GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                            GetExport().EncodeStyleName( sStyle ) );
        }
        SvXMLElementExport aSpan( GetExport(), bHasStyle,
                                  XML_NAMESPACE_TEXT, XML_SPAN,
                                  false, false);
 
        // finally, export the field itself
        ExportFieldHelper( rTextField, xPropSet, xRangePropSet, nToken,
            bProgress, rPrevCharIsSpace);
    }
}
 
/// export the given field to XML. Called on second pass through document
void XMLTextFieldExport::ExportFieldHelper(
    const Reference<XTextField> & rTextField,
    const Reference<XPropertySet> & rPropSet,
    const Reference<XPropertySet> &,
    enum FieldIdEnum nToken,
    bool bProgress,
    bool & rPrevCharIsSpace)
{
    // get property set info (because some attributes are not support
    // in all implementations)
    Reference<XPropertySetInfo> xPropSetInfo(rPropSet->getPropertySetInfo());
 
    OUString sPresentation = rTextField->getPresentation(false);
 
    // process each field type
    switch (nToken) {
    case FIELD_ID_AUTHOR:
        // author field: fixed, field (sub-)type
        if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
        {
            GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_FIXED,
                                 (GetBoolProperty(gsPropertyIsFixed, rPropSet) ? XML_TRUE : XML_FALSE) );
        }
        ExportElement(MapAuthorFieldName(rPropSet), sPresentation);
        break;
 
    case FIELD_ID_SENDER:
        // sender field: fixed, field (sub-)type
        ProcessBoolean(XML_FIXED,
                       GetBoolProperty(gsPropertyIsFixed, rPropSet), true);
        ExportElement(MapSenderFieldName(rPropSet), sPresentation);
        break;
 
    case FIELD_ID_PLACEHOLDER:
        // placeholder field: type, name, description
        ProcessString(XML_PLACEHOLDER_TYPE,
                      MapPlaceholderType(
                        GetInt16Property(gsPropertyPlaceholderType, rPropSet)));
        ProcessString(XML_DESCRIPTION,
                      GetStringProperty(gsPropertyHint,rPropSet), true);
        ExportElement(XML_PLACEHOLDER, sPresentation);
        break;
 
    case FIELD_ID_VARIABLE_SET:
    {
        // variable set field: name, visible, format&value
        ProcessString(XML_NAME,
                      GetStringProperty(gsPropertyVariableName, rPropSet));
        ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
                       false);
        ProcessString(XML_FORMULA, XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyContent, rPropSet),
                      sPresentation);
        ProcessValueAndType(IsStringField(nToken, rPropSet),
                            GetIntProperty(gsPropertyNumberFormat, rPropSet),
                            GetStringProperty(gsPropertyContent, rPropSet),
                            sPresentation,
                            GetDoubleProperty(gsPropertyValue, rPropSet),
                            true, true, true,
                            ! GetOptionalBoolProperty(
                                 gsPropertyIsFixedLanguage,
                                 rPropSet, xPropSetInfo, false ) );
        ExportElement(XML_VARIABLE_SET, sPresentation);
        break;
    }
    case FIELD_ID_VARIABLE_GET:
    {
        // variable get field: name, format&value
        ProcessString(XML_NAME,
                      GetStringProperty(gsPropertyContent, rPropSet));
        bool bCmd = GetBoolProperty(gsPropertyIsShowFormula, rPropSet);
        ProcessDisplay(true, bCmd);
        // #i81766# for older versions export of the value-type
        bool bExportValueType = !bCmd && ( GetExport().getExportFlags() & SvXMLExportFlags::SAVEBACKWARDCOMPATIBLE );
        // show style, unless name will be shown
        ProcessValueAndType(IsStringField(nToken, rPropSet),
                            GetIntProperty(gsPropertyNumberFormat, rPropSet),
                            "", "", 0.0, // values not used
                            false,
                            bExportValueType,
                            !bCmd,
                            ! GetOptionalBoolProperty(
                                 gsPropertyIsFixedLanguage,
                                 rPropSet, xPropSetInfo, false ) );
        ExportElement(XML_VARIABLE_GET, sPresentation);
        break;
    }
    case FIELD_ID_VARIABLE_INPUT:
        // variable input field: name, description, format&value
        ProcessString(XML_NAME,
                      GetStringProperty(gsPropertyVariableName, rPropSet));
        ProcessString(XML_DESCRIPTION,
                      GetStringProperty(gsPropertyHint , rPropSet));
        ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
                       false);
        ProcessString(XML_FORMULA, XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyContent, rPropSet),
                      sPresentation);
        ProcessValueAndType(IsStringField(nToken, rPropSet),
                            GetIntProperty(gsPropertyNumberFormat, rPropSet),
                            GetStringProperty(gsPropertyContent, rPropSet),
                            sPresentation,
                            GetDoubleProperty(gsPropertyValue, rPropSet),
                            true, true, true,
                            ! GetOptionalBoolProperty(
                                 gsPropertyIsFixedLanguage,
                                 rPropSet, xPropSetInfo, false ) );
        ExportElement(XML_VARIABLE_INPUT, sPresentation);
        break;
 
    case FIELD_ID_USER_GET:
        // user field: name, hidden, style
    {
        bool bCmd = GetBoolProperty(gsPropertyIsShowFormula, rPropSet);
        ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
                       bCmd);
        ProcessValueAndType(IsStringField(nToken, rPropSet),
                            GetIntProperty(gsPropertyNumberFormat, rPropSet),
                            "", "", 0.0, // values not used
                            false, false, !bCmd,
                            ! GetOptionalBoolProperty(
                                 gsPropertyIsFixedLanguage,
                                 rPropSet, xPropSetInfo, false ) );
 
        // name from FieldMaster
        ProcessString(XML_NAME,
                      GetStringProperty(gsPropertyName,
                                        GetMasterPropertySet(rTextField)));
        ExportElement(XML_USER_FIELD_GET, sPresentation);
        break;
    }
 
    case FIELD_ID_USER_INPUT:
        // user input field: name (from FieldMaster), description
//      ProcessString(XML_NAME,
//                    GetStringProperty(sPropertyName,
//                                      GetMasterPropertySet(rTextField)));
        ProcessString(XML_NAME,
                      GetStringProperty(gsPropertyContent, rPropSet));
        ProcessString(XML_DESCRIPTION,
                      GetStringProperty(gsPropertyHint, rPropSet));
        ExportElement(XML_USER_FIELD_INPUT, sPresentation);
        break;
 
    case FIELD_ID_SEQUENCE:
    {
        // sequence field: name, formula, seq-format
        OUString sName = GetStringProperty(gsPropertyVariableName, rPropSet);
        // TODO: use reference name only if actually being referenced.
        ProcessString(XML_REF_NAME,
                      MakeSequenceRefName(
                          GetInt16Property(gsPropertySequenceValue, rPropSet),
                          sName));
        ProcessString(XML_NAME, sName);
        ProcessString(XML_FORMULA,  XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyContent, rPropSet),
                      sPresentation);
        ProcessNumberingType(GetInt16Property(gsPropertyNumberingType,
                                              rPropSet));
        ExportElement(XML_SEQUENCE, sPresentation);
        break;
    }
 
    case FIELD_ID_EXPRESSION:
    {
        // formula field: formula, format&value
        bool bCmd = GetBoolProperty(gsPropertyIsShowFormula, rPropSet);
        ProcessString(XML_FORMULA,  XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyContent, rPropSet),
                      sPresentation);
        ProcessDisplay(true, bCmd);
        ProcessValueAndType(IsStringField(nToken, rPropSet),
                            GetIntProperty(gsPropertyNumberFormat, rPropSet),
                            GetStringProperty(gsPropertyContent, rPropSet),
                            sPresentation,
                            GetDoubleProperty(gsPropertyValue, rPropSet),
                            !bCmd, !bCmd, !bCmd,
                            ! GetOptionalBoolProperty(
                                 gsPropertyIsFixedLanguage,
                                 rPropSet, xPropSetInfo, false ) );
        ExportElement(XML_EXPRESSION, sPresentation);
        break;
    }
 
    case FIELD_ID_TEXT_INPUT:
        // text input field: description and string-value
        ProcessString(XML_DESCRIPTION,
                      GetStringProperty(gsPropertyHint, rPropSet));
        ProcessString(XML_HELP,
                      GetStringProperty(gsPropertyHelp, rPropSet), true);
        ProcessString(XML_HINT,
                      GetStringProperty(gsPropertyTooltip, rPropSet), true);
        ExportElement(XML_TEXT_INPUT, sPresentation);
        break;
 
    case FIELD_ID_TIME:
        // all properties (except IsDate) are optional!
        if (xPropSetInfo->hasPropertyByName(gsPropertyNumberFormat))
        {
            ProcessValueAndType(false,
                                GetIntProperty(gsPropertyNumberFormat,rPropSet),
                                "", "", 0.0, // not used
                                false, false, true,
                                ! GetOptionalBoolProperty(
                                    gsPropertyIsFixedLanguage,
                                    rPropSet, xPropSetInfo, false ),
                                true);
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyDateTimeValue))
        {
            // no value -> current time
            ProcessTimeOrDateTime(XML_TIME_VALUE,
                            GetDateTimeProperty(gsPropertyDateTimeValue,
                                                rPropSet));
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyDateTime))
        {
            // no value -> current time
            ProcessTimeOrDateTime(XML_TIME_VALUE,
                            GetDateTimeProperty(gsPropertyDateTime,rPropSet));
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
        {
            ProcessBoolean(XML_FIXED,
                           GetBoolProperty(gsPropertyIsFixed, rPropSet),
                           false);
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyAdjust))
        {
            // adjust value given as integer in minutes
            ProcessDateTime(XML_TIME_ADJUST,
                            GetIntProperty(gsPropertyAdjust, rPropSet),
                            false, true);
        }
        ExportElement(XML_TIME, sPresentation);
        break;
 
    case FIELD_ID_DATE:
        // all properties (except IsDate) are optional!
        if (xPropSetInfo->hasPropertyByName(gsPropertyNumberFormat))
        {
            ProcessValueAndType(false,
                                GetIntProperty(gsPropertyNumberFormat,rPropSet),
                                "", "", 0.0, // not used
                                false, false, true,
                                ! GetOptionalBoolProperty(
                                    gsPropertyIsFixedLanguage,
                                    rPropSet, xPropSetInfo, false ) );
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyDateTimeValue))
        {
            // no value -> current date
            ProcessDateTime(XML_DATE_VALUE,
                            GetDateTimeProperty(gsPropertyDateTimeValue,
                                                rPropSet));
        }
        // TODO: remove double-handling after SRC614
        else if (xPropSetInfo->hasPropertyByName(gsPropertyDateTime))
        {
            ProcessDateTime(XML_DATE_VALUE,
                            GetDateTimeProperty(gsPropertyDateTime,rPropSet));
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
        {
            ProcessBoolean(XML_FIXED,
                           GetBoolProperty(gsPropertyIsFixed, rPropSet),
                           false);
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyAdjust))
        {
            // adjust value given as number of days
            ProcessDateTime(XML_DATE_ADJUST,
                            GetIntProperty(gsPropertyAdjust, rPropSet),
                            true, true);
        }
        ExportElement(XML_DATE, sPresentation);
        break;
 
    case FIELD_ID_PAGENUMBER:
        // all properties are optional
        if (xPropSetInfo->hasPropertyByName(gsPropertyNumberingType))
        {
            ProcessNumberingType(GetInt16Property(gsPropertyNumberingType,
                                                  rPropSet));
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyOffset))
        {
            sal_Int32 nAdjust = GetIntProperty(gsPropertyOffset, rPropSet);
 
            if (xPropSetInfo->hasPropertyByName(gsPropertySubType))
            {
                // property SubType used in MapPageNumebrName
                ProcessString(XML_SELECT_PAGE,
                              MapPageNumberName(rPropSet, nAdjust));
            }
            ProcessIntegerDef(XML_PAGE_ADJUST, nAdjust, 0);
        }
        ExportElement(XML_PAGE_NUMBER, sPresentation);
        break;
 
    case FIELD_ID_PAGESTRING:
    {
        ProcessString(XML_STRING_VALUE,
                      GetStringProperty(gsPropertyUserText, rPropSet),
                      sPresentation);
        sal_Int32 nDummy = 0; // MapPageNumberName need int
        ProcessString(XML_SELECT_PAGE, MapPageNumberName(rPropSet, nDummy));
        if( !( GetExport().getExportFlags() & SvXMLExportFlags::SAVEBACKWARDCOMPATIBLE ) )
            ExportElement(XML_PAGE_CONTINUATION, sPresentation);
        else
            ExportElement(XML_PAGE_CONTINUATION_STRING, sPresentation);
        break;
    }
 
    case FIELD_ID_DATABASE_NAME:
        ProcessString(XML_TABLE_NAME,
                      GetStringProperty(gsPropertyDataTableName, rPropSet));
        ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, rPropSet));
        ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
                       false);
        ExportDataBaseElement(XML_DATABASE_NAME, sPresentation,
                              rPropSet, xPropSetInfo);
        break;
 
    case FIELD_ID_DATABASE_NUMBER:
        ProcessString(XML_TABLE_NAME,
                      GetStringProperty(gsPropertyDataTableName, rPropSet));
        ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, rPropSet));
        ProcessNumberingType(
            GetInt16Property(gsPropertyNumberingType,rPropSet));
        ProcessInteger(XML_VALUE,
                       GetIntProperty(gsPropertySetNumber, rPropSet));
        ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
                       false);
        ExportDataBaseElement(XML_DATABASE_ROW_NUMBER, sPresentation,
                              rPropSet, xPropSetInfo);
        break;
 
    case FIELD_ID_DATABASE_NEXT:
        ProcessString(XML_TABLE_NAME,
                      GetStringProperty(gsPropertyDataTableName, rPropSet));
        ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, rPropSet));
        ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyCondition, rPropSet));
        DBG_ASSERT(sPresentation.isEmpty(),
                   "Unexpected presentation for database next field");
        ExportDataBaseElement(XML_DATABASE_NEXT, OUString(),
                              rPropSet, xPropSetInfo);
        break;
 
    case FIELD_ID_DATABASE_SELECT:
        ProcessString(XML_TABLE_NAME,
                      GetStringProperty(gsPropertyDataTableName, rPropSet));
        ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, rPropSet));
        ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyCondition, rPropSet));
        ProcessInteger(XML_ROW_NUMBER,
                       GetIntProperty(gsPropertySetNumber, rPropSet));
        DBG_ASSERT(sPresentation.isEmpty(),
                   "Unexpected presentation for database select field");
        ExportDataBaseElement(XML_DATABASE_ROW_SELECT, OUString(),
                              rPropSet, xPropSetInfo);
        break;
 
    case FIELD_ID_DATABASE_DISPLAY:
    {
        // get database, table and column name from field master
        const Reference<XPropertySet> & xMaster = GetMasterPropertySet(rTextField);
        ProcessString(XML_TABLE_NAME,
                      GetStringProperty(gsPropertyDataTableName, xMaster));
        ProcessCommandType(GetIntProperty(gsPropertyDataCommandType, xMaster));
        ProcessString(XML_COLUMN_NAME,
                      GetStringProperty(gsPropertyDataColumnName, xMaster));
        // export number format if available (happens only for numbers!)
        if (!GetBoolProperty(gsPropertyIsDataBaseFormat, rPropSet))
        {
            ProcessValueAndType(false,  // doesn't happen for text
                                GetIntProperty(gsPropertyNumberFormat,rPropSet),
                                "", "", 0.0, // not used
                                false, false, true, false);
        }
        ProcessDisplay(GetBoolProperty(gsPropertyIsVisible, rPropSet),
                       false);
        ExportDataBaseElement(XML_DATABASE_DISPLAY, sPresentation,
                              xMaster, xMaster->getPropertySetInfo());
        break;
    }
 
    case FIELD_ID_DOCINFO_REVISION:
        ProcessBoolean(XML_FIXED,
                       GetBoolProperty(gsPropertyIsFixed, rPropSet), false);
        ExportElement(MapDocInfoFieldName(nToken), sPresentation);
        break;
 
    case FIELD_ID_DOCINFO_EDIT_DURATION:
    case FIELD_ID_DOCINFO_SAVE_TIME:
    case FIELD_ID_DOCINFO_CREATION_TIME:
    case FIELD_ID_DOCINFO_PRINT_TIME:
    case FIELD_ID_DOCINFO_SAVE_DATE:
    case FIELD_ID_DOCINFO_CREATION_DATE:
    case FIELD_ID_DOCINFO_PRINT_DATE:
        ProcessValueAndType(false,
                            GetIntProperty(gsPropertyNumberFormat, rPropSet),
                            "", "", 0.0,
                            false, false, true,
                            ! GetOptionalBoolProperty(
                                    gsPropertyIsFixedLanguage,
                                    rPropSet, xPropSetInfo, false ) );
 
        // todo: export date/time value, but values not available -> core bug
        ProcessBoolean(XML_FIXED,
                       GetBoolProperty(gsPropertyIsFixed, rPropSet), false);
        ExportElement(MapDocInfoFieldName(nToken), sPresentation);
        break;
 
    case FIELD_ID_DOCINFO_CREATION_AUTHOR:
    case FIELD_ID_DOCINFO_DESCRIPTION:
    case FIELD_ID_DOCINFO_PRINT_AUTHOR:
    case FIELD_ID_DOCINFO_TITLE:
    case FIELD_ID_DOCINFO_SUBJECT:
    case FIELD_ID_DOCINFO_KEYWORDS:
    case FIELD_ID_DOCINFO_SAVE_AUTHOR:
        if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
        {
            ProcessBoolean(XML_FIXED,
                           GetBoolProperty(gsPropertyIsFixed, rPropSet), false);
        }
        ExportElement(MapDocInfoFieldName(nToken), sPresentation);
        break;
 
    case FIELD_ID_DOCINFO_CUSTOM:
    {
        ProcessValueAndType(false,  // doesn't happen for text
                                GetIntProperty(gsPropertyNumberFormat,rPropSet),
                                "", "", 0.0, // not used
                                false, false, true,
                                ! GetOptionalBoolProperty(
                                    gsPropertyIsFixedLanguage,
                                    rPropSet, xPropSetInfo, false ));
        uno::Any aAny = rPropSet->getPropertyValue( gsPropertyName );
        OUString sName;
        aAny >>= sName;
        ProcessString(XML_NAME, sName);
        ProcessBoolean(XML_FIXED, GetBoolProperty(gsPropertyIsFixed, rPropSet), false);
        ExportElement(XML_USER_DEFINED, sPresentation);
        break;
    }
 
    case FIELD_ID_COUNT_PAGES:
    case FIELD_ID_COUNT_PARAGRAPHS:
    case FIELD_ID_COUNT_WORDS:
    case FIELD_ID_COUNT_CHARACTERS:
    case FIELD_ID_COUNT_TABLES:
    case FIELD_ID_COUNT_GRAPHICS:
    case FIELD_ID_COUNT_OBJECTS:
        // all properties optional (applies to pages only, but I'll do
        // it for all for sake of common implementation)
        if (xPropSetInfo->hasPropertyByName(gsPropertyNumberingType))
        {
            ProcessNumberingType(GetInt16Property(gsPropertyNumberingType,
                                                  rPropSet));
        }
        ExportElement(MapCountFieldName(nToken), sPresentation);
        break;
 
    case FIELD_ID_CONDITIONAL_TEXT:
        ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyCondition, rPropSet));
        ProcessString(XML_STRING_VALUE_IF_TRUE,
                      GetStringProperty(gsPropertyTrueContent, rPropSet));
        ProcessString(XML_STRING_VALUE_IF_FALSE,
                      GetStringProperty(gsPropertyFalseContent, rPropSet));
        ProcessBoolean(XML_CURRENT_VALUE,
                       GetBoolProperty(gsPropertyIsConditionTrue, rPropSet),
                       false);
        ExportElement(XML_CONDITIONAL_TEXT, sPresentation);
        break;
 
    case FIELD_ID_HIDDEN_TEXT:
        ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyCondition, rPropSet));
        ProcessString(XML_STRING_VALUE,
                      GetStringProperty(gsPropertyContent, rPropSet));
        ProcessBoolean(XML_IS_HIDDEN,
                       GetBoolProperty(gsPropertyIsHidden, rPropSet),
                       false);
        ExportElement(XML_HIDDEN_TEXT, sPresentation);
        break;
 
    case FIELD_ID_HIDDEN_PARAGRAPH:
        ProcessString(XML_CONDITION, XML_NAMESPACE_OOOW,
                      GetStringProperty(gsPropertyCondition, rPropSet));
        ProcessBoolean(XML_IS_HIDDEN,
                       GetBoolProperty(gsPropertyIsHidden, rPropSet),
                       false);
        DBG_ASSERT(sPresentation.isEmpty(),
                   "Unexpected presentation for hidden paragraph field");
        ExportElement(XML_HIDDEN_PARAGRAPH);
        break;
 
    case FIELD_ID_TEMPLATE_NAME:
        ProcessString(XML_DISPLAY,
                      MapTemplateDisplayFormat(
                          GetInt16Property(gsPropertyFileFormat, rPropSet)));
        ExportElement(XML_TEMPLATE_NAME, sPresentation);
        break;
 
    case FIELD_ID_CHAPTER:
        ProcessString(XML_DISPLAY,
                      MapChapterDisplayFormat(
                          GetInt16Property(gsPropertyChapterFormat, rPropSet)));
        // API numbers 0..9, we number 1..10
        ProcessInteger(XML_OUTLINE_LEVEL,
                       GetInt8Property(gsPropertyLevel, rPropSet) + 1);
        ExportElement(XML_CHAPTER, sPresentation);
        break;
 
    case FIELD_ID_FILE_NAME:
        // all properties are optional
        if (xPropSetInfo->hasPropertyByName(gsPropertyFileFormat))
        {
            ProcessString(XML_DISPLAY,
                          MapFilenameDisplayFormat(
                             GetInt16Property(gsPropertyFileFormat, rPropSet)));
        }
        if (xPropSetInfo->hasPropertyByName(gsPropertyIsFixed))
        {
            ProcessBoolean(XML_FIXED,
                           GetBoolProperty(gsPropertyIsFixed, rPropSet),
                           false);
        }
        ExportElement(XML_FILE_NAME, sPresentation);
        break;
 
    case FIELD_ID_REFPAGE_SET:
        ProcessBoolean(XML_ACTIVE,
                       GetBoolProperty(gsPropertyOn, rPropSet), true);
        ProcessIntegerDef(XML_PAGE_ADJUST,
                       GetInt16Property(gsPropertyOffset, rPropSet), 0);
        DBG_ASSERT(sPresentation.isEmpty(),
                   "Unexpected presentation page variable field");
        ExportElement(XML_PAGE_VARIABLE_SET);
        break;
 
    case FIELD_ID_REFPAGE_GET:
        ProcessNumberingType(
            GetInt16Property(gsPropertyNumberingType, rPropSet));
        ExportElement(XML_PAGE_VARIABLE_GET, sPresentation);
        break;
 
    case FIELD_ID_MACRO:
        ExportMacro( rPropSet, sPresentation );
        break;
 
    case FIELD_ID_REF_SEQUENCE:
        // reference to sequence: format, name, find value (and element)
        // was: if (nSeqNumber != -1) ...
        ProcessString(XML_REFERENCE_FORMAT,
                      MapReferenceType(GetInt16Property(
                          gsPropertyReferenceFieldPart, rPropSet)),
                      XML_TEMPLATE);
        ProcessString(XML_REF_NAME,
                      MakeSequenceRefName(
                          GetInt16Property(gsPropertySequenceNumber, rPropSet),
                          GetStringProperty(gsPropertySourceName, rPropSet) ) );
        if (xPropSetInfo->hasPropertyByName(gsPropertyReferenceFieldLanguage) &&
            SvtSaveOptions().GetODFDefaultVersion() > SvtSaveOptions::ODFVER_012)
        {
            // export text:reference-language attribute, if not empty
            ProcessString(XML_REFERENCE_LANGUAGE,
                    GetStringProperty(gsPropertyReferenceFieldLanguage, rPropSet), true, XML_NAMESPACE_LO_EXT);
        }
        ExportElement(
            MapReferenceSource(
                GetInt16Property(gsPropertyReferenceFieldSource, rPropSet)),
            sPresentation);
        break;
 
    case FIELD_ID_REF_REFERENCE:
    case FIELD_ID_REF_BOOKMARK:
        // reference to bookmarks, references: format, name (and element)
        ProcessString(XML_REFERENCE_FORMAT,
                      MapReferenceType(GetInt16Property(
                          gsPropertyReferenceFieldPart, rPropSet)),
                      XML_TEMPLATE);
        ProcessString(XML_REF_NAME,
                      GetStringProperty(gsPropertySourceName, rPropSet));
        if (xPropSetInfo->hasPropertyByName(gsPropertyReferenceFieldLanguage) &&
            SvtSaveOptions().GetODFDefaultVersion() > SvtSaveOptions::ODFVER_012)
        {
            // export text:reference-language attribute, if not empty
            ProcessString(XML_REFERENCE_LANGUAGE,
                      GetStringProperty(gsPropertyReferenceFieldLanguage, rPropSet), true, XML_NAMESPACE_LO_EXT);
        }
        ExportElement(
            MapReferenceSource(GetInt16Property(
                gsPropertyReferenceFieldSource, rPropSet)),
            sPresentation);
        break;
 
    case FIELD_ID_REF_FOOTNOTE:
    case FIELD_ID_REF_ENDNOTE:
        // reference to end-/footnote: format, generate name, (and element)
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_NOTE_CLASS,
            FIELD_ID_REF_ENDNOTE==nToken ? XML_ENDNOTE : XML_FOOTNOTE );
        ProcessString(XML_REFERENCE_FORMAT,
                      MapReferenceType(GetInt16Property(
                          gsPropertyReferenceFieldPart, rPropSet)),
                      XML_TEMPLATE);
        ProcessString(XML_REF_NAME,
                      MakeFootnoteRefName(GetInt16Property(
                          gsPropertySequenceNumber, rPropSet)));
        if (xPropSetInfo->hasPropertyByName(gsPropertyReferenceFieldLanguage) &&
            SvtSaveOptions().GetODFDefaultVersion() > SvtSaveOptions::ODFVER_012)
        {
            // export text:reference-language attribute, if not empty
            ProcessString(XML_REFERENCE_LANGUAGE,
                      GetStringProperty(gsPropertyReferenceFieldLanguage, rPropSet), true, XML_NAMESPACE_LO_EXT);
        }
        ExportElement(
            MapReferenceSource(GetInt16Property(
                gsPropertyReferenceFieldSource, rPropSet)),
            sPresentation);
        break;
 
    case FIELD_ID_DDE:
        // name from field master
         ProcessString(XML_CONNECTION_NAME,
 
                       GetStringProperty(gsPropertyName,
                                         GetMasterPropertySet(rTextField)));
        ExportElement(XML_DDE_CONNECTION, sPresentation);
        break;
 
    case FIELD_ID_SHEET_NAME:
        // name of spreadsheet (Calc only)
        ExportElement(XML_SHEET_NAME, sPresentation);
        break;
 
    case FIELD_ID_PAGENAME:
    {
        if (SvtSaveOptions().GetODFDefaultVersion() > SvtSaveOptions::ODFVER_012)
        {
            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_LO_EXT, XML_PAGE_NAME, false, false );
            GetExport().Characters( sPresentation );
        }
        break;
    }
 
    case FIELD_ID_URL:
    {
        // this field is a special case because it gets mapped onto a
        // hyperlink, rather than one of the regular text field.
        ProcessString(XML_HREF, GetExport().GetRelativeReference(GetStringProperty(gsPropertyURL, rPropSet)),
                      false, XML_NAMESPACE_XLINK);
        ProcessString(XML_TARGET_FRAME_NAME,
                      GetStringProperty(gsPropertyTargetFrame,rPropSet),
                      true, XML_NAMESPACE_OFFICE);
        GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        SvXMLElementExport aUrlField(rExport, XML_NAMESPACE_TEXT, XML_A,
                                     false, false);
        GetExport().Characters(sPresentation);
        break;
    }
 
    case FIELD_ID_BIBLIOGRAPHY:
    {
        ProcessBibliographyData(rPropSet);
        ExportElement(XML_BIBLIOGRAPHY_MARK, sPresentation);
        break;
    }
 
    case FIELD_ID_SCRIPT:
        ProcessString(XML_LANGUAGE,
                      GetStringProperty(gsPropertyScriptType, rPropSet),
                      true, XML_NAMESPACE_SCRIPT);
        DBG_ASSERT(sPresentation.isEmpty(),
                   "Unexpected presentation for script field");
        if (GetBoolProperty(gsPropertyURLContent, rPropSet))
        {
            ProcessString(XML_HREF,
                          GetExport().GetRelativeReference(GetStringProperty(gsPropertyContent, rPropSet)),
                          false, XML_NAMESPACE_XLINK);
            ExportElement(XML_SCRIPT);
        }
        else
        {
            ExportElement(XML_SCRIPT,
                          GetStringProperty(gsPropertyContent, rPropSet));
        }
        break;
 
    case FIELD_ID_ANNOTATION:
    {
        // check for empty presentation (just in case)
        DBG_ASSERT(sPresentation.isEmpty(),
                   "Unexpected presentation for annotation field");
 
        // annotation element + content
        OUString aName;
        rPropSet->getPropertyValue(gsPropertyName) >>= aName;
        if (!aName.isEmpty())
            GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_NAME, aName);
        SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_OFFICE,
                                 XML_ANNOTATION, false, true);
 
        // author
        OUString aAuthor( GetStringProperty(gsPropertyAuthor, rPropSet) );
        if( !aAuthor.isEmpty() )
        {
            SvXMLElementExport aCreatorElem( GetExport(), XML_NAMESPACE_DC,
                                              XML_CREATOR, true,
                                              false );
            GetExport().Characters(aAuthor);
        }
 
        // date time
        util::DateTime aDate( GetDateTimeProperty(gsPropertyDateTimeValue, rPropSet) );
        {
            OUStringBuffer aBuffer;
            ::sax::Converter::convertDateTime(aBuffer, aDate, nullptr, true);
            SvXMLElementExport aDateElem( GetExport(), XML_NAMESPACE_DC,
                                              XML_DATE, true,
                                              false );
            GetExport().Characters(aBuffer.makeStringAndClear());
        }
 
        if (SvtSaveOptions().GetODFDefaultVersion() > SvtSaveOptions::ODFVER_012)
        {
            // initials
            OUString aInitials( GetStringProperty(gsPropertyInitials, rPropSet) );
            if( !aInitials.isEmpty() )
            {
                // TODO: see OFFICE-3776 export meta:creator-initials for ODF 1.3
                SvXMLElementExport aCreatorElem( GetExport(), XML_NAMESPACE_LO_EXT,
                        XML_SENDER_INITIALS, true,
                        false );
                GetExport().Characters(aInitials);
            }
        }
 
        css::uno::Reference < css::text::XText > xText;
        try
        {
            css::uno::Any aRet = rPropSet->getPropertyValue(gsPropertyTextRange);
            aRet >>= xText;
        }
        catch ( css::uno::Exception& )
        {}
 
        if ( xText.is() )
            GetExport().GetTextParagraphExport()->exportText( xText );
        else
            ProcessParagraphSequence(GetStringProperty(gsPropertyContent,rPropSet));
        break;
    }
 
    case FIELD_ID_COMBINED_CHARACTERS:
    {
        // The style with the combined characters attribute has
        // already been handled in the ExportField method. So all that
        // is left to do now is to export the characters.
        GetExport().Characters(sPresentation);
        break;
    }
 
    case FIELD_ID_META:
    {
        ExportMetaField(rPropSet, false, bProgress, rPrevCharIsSpace);
        break;
    }
 
    case FIELD_ID_MEASURE:
    {
        ProcessString(XML_KIND, MapMeasureKind(GetInt16Property(gsPropertyMeasureKind, rPropSet)));
        ExportElement( XML_MEASURE, sPresentation );
        break;
    }
 
    case FIELD_ID_TABLE_FORMULA:
        ProcessString( XML_FORMULA,  XML_NAMESPACE_OOOW,
                       GetStringProperty(gsPropertyContent, rPropSet) );
        ProcessDisplay( true,
                        GetBoolProperty(gsPropertyIsShowFormula, rPropSet) );
        ProcessValueAndType( false,
                             GetIntProperty(gsPropertyNumberFormat, rPropSet),
                             "", "", 0.0f,
                             false, false, true,
                             false );
        ExportElement( XML_TABLE_FORMULA, sPresentation );
        break;
 
    case FIELD_ID_DROP_DOWN:
    {
        ProcessString(XML_NAME, GetStringProperty(gsPropertyName, rPropSet));
        ProcessString(XML_HELP,
                      GetStringProperty(gsPropertyHelp, rPropSet), true);
        ProcessString(XML_HINT,
                      GetStringProperty(gsPropertyTooltip, rPropSet), true);
        SvXMLElementExport aElem( GetExport(),
                                  XML_NAMESPACE_TEXT, XML_DROP_DOWN,
                                  false, false );
        ProcessStringSequence
            (GetStringSequenceProperty( gsPropertyItems, rPropSet ),
             GetStringProperty( gsPropertySelectedItem, rPropSet ) );
 
        GetExport().Characters( sPresentation );
    }
    break;
 
    case FIELD_ID_DRAW_HEADER:
    {
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_PRESENTATION, XML_HEADER, false, false );
    }
    break;
 
    case FIELD_ID_DRAW_FOOTER:
    {
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_PRESENTATION, XML_FOOTER, false, false );
    }
    break;
 
    case FIELD_ID_DRAW_DATE_TIME:
    {
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_PRESENTATION, XML_DATE_TIME, false, false );
    }
    break;
 
 
    case FIELD_ID_UNKNOWN:
    default:
        OSL_FAIL("unknown field type encountered!");
        // always export content
        GetExport().Characters(sPresentation);
    }
}
 
 
/// export field declarations / field masters
void XMLTextFieldExport::ExportFieldDeclarations()
{
    Reference<XText> xEmptyText;
    ExportFieldDeclarations(xEmptyText);
}
 
/// export field declarations / field masters
void XMLTextFieldExport::ExportFieldDeclarations(
    const Reference<XText> & rText )
{
    // store lists for decl elements
    vector<OUString>                    aVarName;
    vector<OUString>                    aUserName;
    vector<OUString>                    aSeqName;
    vector<OUString>                    aDdeName;
 
    // get text fields supplier and field master name access
    Reference<XTextFieldsSupplier> xTextFieldsSupp(GetExport().GetModel(),
                                                   UNO_QUERY);
    if( !xTextFieldsSupp.is() )
        return;
 
    Reference<container::XNameAccess> xFieldMasterNameAccess(
        xTextFieldsSupp->getTextFieldMasters(), UNO_QUERY);
 
    // where to get the text field masters from?
    // a) we get a specific XText: then use pUsedMasters
    // b) the XText is empty: then export all text fields
    Sequence<OUString> aFieldMasters;
    if (rText.is())
    {
        // export only used masters
        DBG_ASSERT(nullptr != pUsedMasters,
                   "field masters must be recorded in order to be "
                   "written out separately" );
        if (nullptr != pUsedMasters)
        {
            map<Reference<XText>, set<OUString> > ::iterator aMapIter =
                pUsedMasters->find(rText);
            if (aMapIter != pUsedMasters->end())
            {
                // found the set of used field masters
                set<OUString> & rOurMasters = aMapIter->second;
 
                // copy set to sequence
                aFieldMasters.realloc( rOurMasters.size() );
                sal_Int32 i = 0;
                for( set<OUString>::iterator aSetIter = rOurMasters.begin();
                     aSetIter != rOurMasters.end();
                     ++aSetIter, ++i )
                {
                    aFieldMasters[i] = *aSetIter;
                }
 
                pUsedMasters->erase(rText);
            }
            // else: XText not found -> ignore
        }
        // else: no field masters have been recorded -> ignore
    }
    else
    {
        // no XText: export all!
        aFieldMasters = xFieldMasterNameAccess->getElementNames();
    }
 
    for(sal_Int32 i=0; i<aFieldMasters.getLength(); i++) {
 
        // get field master name
        OUString sFieldMaster = aFieldMasters[i];
 
        // workaround for #no-bug#
        if ( sFieldMaster.startsWithIgnoreAsciiCase(
                 "com.sun.star.text.FieldMaster.DataBase.") )
        {
            continue;
        }
 
 
        OUString sFieldMasterType;
        OUString sVarName;
        ExplodeFieldMasterName(sFieldMaster, sFieldMasterType, sVarName);
 
        // get XPropertySet of this field master
        Reference<XPropertySet> xPropSet;
        Any aAny = xFieldMasterNameAccess->getByName(sFieldMaster);
        aAny >>= xPropSet;
 
        // save interesting field masters
        if (sFieldMasterType == FIELD_SERVICE_SETEXP)
        {
            sal_Int32 nType = GetIntProperty(gsPropertySubType, xPropSet);
 
            // sequence or variable?
            if ( SetVariableType::SEQUENCE == nType )
            {
                aSeqName.push_back( sFieldMaster );
            }
            else
            {
                aVarName.push_back( sFieldMaster );
            }
        }
        else if (sFieldMasterType == FIELD_SERVICE_USER)
        {
            aUserName.push_back( sFieldMaster );
        }
        else if (sFieldMasterType == FIELD_SERVICE_DDE)
        {
            aDdeName.push_back( sFieldMaster );
        }
        else
        {
            ; // ignore
        }
    }
 
    // now process fields:
 
    // variable field masters:
    if ( !aVarName.empty() )
    {
        SvXMLElementExport aElem( GetExport(),
                                  XML_NAMESPACE_TEXT,
                                  XML_VARIABLE_DECLS,
                                  true, true );
 
        for (vector<OUString>::iterator aVarIter = aVarName.begin();
             aVarIter != aVarName.end();
             ++aVarIter) {
 
            OUString sName = *aVarIter;
 
            // get field master property set
            Reference<XPropertySet> xPropSet;
            Any aAny = xFieldMasterNameAccess->getByName(sName);
            aAny >>= xPropSet;
 
            // field name and type
            OUString sFieldMasterType;
            OUString sVarName;
            ExplodeFieldMasterName(sName, sFieldMasterType, sVarName);
 
            // determine string/numeric field
            bool bIsString = ( GetIntProperty(gsPropertySubType, xPropSet)
                                   == SetVariableType::STRING );
 
            // get dependent field property set
            Reference<XPropertySet> xFieldPropSet;
            if (GetDependentFieldPropertySet(xPropSet, xFieldPropSet))
            {
                // process value and type.
                ProcessValueAndType(
                    bIsString,
                    GetIntProperty(gsPropertyNumberFormat, xFieldPropSet),
                    "", "", 0.0,
                    false, true, false, false);
            }
            else
            {
                // If no dependent field is found, only string and
                // float types can be supported
 
                // number format: 0 is default number format for 1st
                // language. should be: getDefaultNumberFormat(Locale)
                // from NumberFormats
                ProcessValueAndType(
                    bIsString,
                    0, "", "", 0.0,
                    false, true, false, false);
            }
 
            ProcessString(XML_NAME, sVarName);
            ExportElement(XML_VARIABLE_DECL, true);
        }
    }
    // else: no declarations element
 
    // sequence field masters:
    if ( !aSeqName.empty() )
    {
        SvXMLElementExport aElem( GetExport(),
                                  XML_NAMESPACE_TEXT,
                                  XML_SEQUENCE_DECLS,
                                  true, true );
 
        for (vector<OUString>::iterator aSeqIter = aSeqName.begin();
             aSeqIter != aSeqName.end();
             ++aSeqIter) {
 
            OUString sName = *aSeqIter;
 
            // get field master property set
            Reference<XPropertySet> xPropSet;
            Any aAny = xFieldMasterNameAccess->getByName(sName);
            aAny >>= xPropSet;
 
            // field name and type
            OUString sFieldMasterType;
            OUString sVarName;
            ExplodeFieldMasterName(sName, sFieldMasterType, sVarName);
 
            // outline level
            sal_Int32 nLevel = 1 + GetIntProperty(
                gsPropertyChapterNumberingLevel, xPropSet);
            DBG_ASSERT(nLevel >= 0, "illegal outline level");
            DBG_ASSERT(nLevel < 127, "possible illegal outline level");
            ProcessInteger(XML_DISPLAY_OUTLINE_LEVEL, nLevel);
 
            // separation character
            if (nLevel > 0) {
                ProcessString(XML_SEPARATION_CHARACTER, GetStringProperty(
                    gsPropertyNumberingSeparator, xPropSet));
            }
            ProcessString(XML_NAME, sVarName);
            ExportElement(XML_SEQUENCE_DECL, true);
        }
    }
    // else: no declarations element
 
    // user field masters:
    if ( !aUserName.empty() )
    {
        SvXMLElementExport aElem( GetExport(),
                                  XML_NAMESPACE_TEXT,
                                  XML_USER_FIELD_DECLS,
                                  true, true );
 
        for (vector<OUString>::iterator aUserIter = aUserName.begin();
             aUserIter != aUserName.end();
             ++aUserIter) {
 
            OUString sName = *aUserIter;
 
            // get field master property set
            Reference<XPropertySet> xPropSet;
            Any aAny = xFieldMasterNameAccess->getByName(sName);
            aAny >>= xPropSet;
 
            // field name and type
            OUString sFieldMasterType;
            OUString sVarName;
            ExplodeFieldMasterName(sName, sFieldMasterType, sVarName);
 
            if (GetBoolProperty(gsPropertyIsExpression, xPropSet))
            {
                // expression:
                ProcessValueAndType(
                    false,
                    0, "", "",
                    GetDoubleProperty(gsPropertyValue, xPropSet),
                    true,
                    true,
                    false,
                    false);
            }
            else
            {
                // string: write regardless of default
                ProcessString(XML_VALUE_TYPE, XML_STRING,
                              XML_NAMESPACE_OFFICE);
                ProcessString(XML_STRING_VALUE,
                              GetStringProperty(gsPropertyContent, xPropSet),
                              false, XML_NAMESPACE_OFFICE );
            }
            ProcessString(XML_NAME, sVarName);
            ExportElement(XML_USER_FIELD_DECL, true);
        }
    }
    // else: no declarations element
 
    // DDE field masters:
    if ( !aDdeName.empty() )
    {
        SvXMLElementExport aElem( GetExport(),
                                  XML_NAMESPACE_TEXT,
                                  XML_DDE_CONNECTION_DECLS,
                                  true, true );
 
        for (vector<OUString>::iterator aDdeIter = aDdeName.begin();
             aDdeIter != aDdeName.end();
             ++aDdeIter)
        {
            OUString sName = *aDdeIter;
 
            // get field master property set
            Reference<XPropertySet> xPropSet;
            Any aAny = xFieldMasterNameAccess->getByName(sName);
            aAny >>= xPropSet;
 
            // check if this connection is being used by a field
            Reference<XPropertySet> xDummy;
            if (GetDependentFieldPropertySet(xPropSet, xDummy))
            {
 
                ProcessString(XML_NAME,
                              GetStringProperty(gsPropertyName, xPropSet),
                              false, XML_NAMESPACE_OFFICE);
 
                // export elements; can't use ProcessString because
                // elements are in office namespace
                ProcessString(XML_DDE_APPLICATION,
                              GetStringProperty(gsPropertyDDECommandType,
                                                xPropSet),
                              false, XML_NAMESPACE_OFFICE);
                ProcessString(XML_DDE_TOPIC,
                              GetStringProperty(gsPropertyDDECommandFile,
                                                xPropSet),
                              false, XML_NAMESPACE_OFFICE);
                ProcessString(XML_DDE_ITEM,
                              GetStringProperty(gsPropertyDDECommandElement,
                                                xPropSet),
                              false, XML_NAMESPACE_OFFICE);
                bool bIsAutomaticUpdate = GetBoolProperty(
                    gsPropertyIsAutomaticUpdate, xPropSet);
                if (bIsAutomaticUpdate)
                {
                    GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
                                             XML_AUTOMATIC_UPDATE,
                                             XML_TRUE);
                }
 
                ExportElement(XML_DDE_CONNECTION_DECL, true);
            }
            // else: no dependent field -> no export of field declaration
        }
    }
    // else: no declarations element
}
 
void XMLTextFieldExport::SetExportOnlyUsedFieldDeclarations(
    bool bExportOnlyUsed)
{
    pUsedMasters.reset();
 
    // create used masters set (if none is used)
    if (bExportOnlyUsed)
        pUsedMasters.reset( new map<Reference<XText>, set<OUString> > );
}
 
void XMLTextFieldExport::ExportElement(enum XMLTokenEnum eElementName,
                                       bool bAddSpace)
{
    // can't call ExportElement(eElementName, const OUString&) with empty
    // string because xmlprinter only uses empty tags if no content
    // (not even empty content) was written.
 
    DBG_ASSERT(XML_TOKEN_INVALID != eElementName, "invalid element name!");
    if (XML_TOKEN_INVALID != eElementName)
    {
        // Element
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
                                  eElementName, bAddSpace, bAddSpace );
    } // else: ignore
}
 
void XMLTextFieldExport::ExportElement(enum XMLTokenEnum eElementName,
                                       const OUString& sContent)
{
    DBG_ASSERT(eElementName != XML_TOKEN_INVALID, "invalid element name!");
    if (eElementName != XML_TOKEN_INVALID)
    {
        // Element
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
                eElementName, false, false );
        // export content
        GetExport().Characters(sContent);
    } else {
        // always export content
        GetExport().Characters(sContent);
    }
}
 
void XMLTextFieldExport::ExportMacro(
    const Reference<XPropertySet> & rPropSet,
    const OUString& rContent )
{
    // some strings we'll need
    OUString sEventType( "EventType" );
    OUString sScript( "Script" );
    OUString sPropertyScriptURL( "ScriptURL" );
 
 
    // the description attribute
    ProcessString(XML_DESCRIPTION,
                  GetStringProperty(gsPropertyHint, rPropSet),
                  rContent);
 
    // the element
    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
                              XML_EXECUTE_MACRO, false, false );
 
    // the <office:events>-macro:
 
    // 1) build sequence of PropertyValues
    Sequence<PropertyValue> aSeq;
    OUString sName;
    rPropSet->getPropertyValue( sPropertyScriptURL ) >>= sName;
 
    // if the ScriptURL property is not empty then this is a Scripting
    // Framework URL, otherwise treat it as a Basic Macro
    if (!sName.isEmpty())
    {
        aSeq = Sequence<PropertyValue> (2);
        PropertyValue* pArr = aSeq.getArray();
        pArr[0].Name = sEventType;
        pArr[0].Value <<= sScript;
        pArr[1].Name = sScript;
        pArr[1].Value = rPropSet->getPropertyValue( sPropertyScriptURL );
    }
    else
    {
        aSeq = Sequence<PropertyValue> (3);
        PropertyValue* pArr = aSeq.getArray();
        pArr[0].Name = sEventType;
        pArr[0].Value <<= OUString("StarBasic");
        pArr[1].Name = "Library";
        pArr[1].Value = rPropSet->getPropertyValue( "MacroLibrary" );
        pArr[2].Name = "MacroName";
        pArr[2].Value = rPropSet->getPropertyValue( "MacroName" );
    }
 
    // 2) export the sequence
    GetExport().GetEventExport().ExportSingleEvent( aSeq, "OnClick", false );
 
    // and finally, the field presentation
    GetExport().Characters(rContent);
}
 
void XMLTextFieldExport::ExportMetaField(
    const Reference<XPropertySet> & i_xMeta,
    bool i_bAutoStyles, bool i_bProgress,
    bool & rPrevCharIsSpace)
{
    bool doExport(!i_bAutoStyles); // do not export element if autostyles
    // check version >= 1.2
    switch (GetExport().getDefaultVersion()) {
        case SvtSaveOptions::ODFVER_011: // fall through
        case SvtSaveOptions::ODFVER_010: doExport = false; break;
        default: break;
    }
 
    const Reference < XEnumerationAccess > xEA( i_xMeta, UNO_QUERY_THROW );
    const Reference < XEnumeration > xTextEnum( xEA->createEnumeration() );
 
    if (doExport)
    {
        const Reference<rdf::XMetadatable> xMeta( i_xMeta, UNO_QUERY_THROW );
 
        // style:data-style-name
        ProcessValueAndType(false,
            GetIntProperty(gsPropertyNumberFormat, i_xMeta),
            "", "", 0.0, false, false, true,
            false  );
 
        // text:meta-field without xml:id is invalid
        xMeta->ensureMetadataReference();
 
        // xml:id for RDF metadata
        GetExport().AddAttributeXmlId(xMeta);
    }
 
    SvXMLElementExport aElem( GetExport(), doExport,
        XML_NAMESPACE_TEXT, XML_META_FIELD, false, false );
 
    // recurse to export content
    GetExport().GetTextParagraphExport()->
        exportTextRangeEnumeration(xTextEnum, i_bAutoStyles, i_bProgress, rPrevCharIsSpace);
}
 
/// export all data-style related attributes
void XMLTextFieldExport::ProcessValueAndType(
    bool bIsString,     /// do we process a string or a number?
    sal_Int32 nFormatKey,   /// format key for NumberFormatter; inv. if string
    const OUString& sContent,   /// string content; possibly invalid
    const OUString& sDefault,   /// default string
    double fValue,          /// float content; possibly invalid
    bool bExportValue,  /// export value attribute?
    bool bExportValueType,  /// export value-type attribute?
    bool bExportStyle,  /// export style-sttribute?
    bool bForceSystemLanguage, /// export language attributes?
    bool bTimeStyle)    // exporting a time style?
{
    // String or number?
    if (bIsString)
    {
 
        // string: attributes value-type=string, string-value=...
 
        if (bExportValue || bExportValueType)
        {
            XMLNumberFormatAttributesExportHelper::SetNumberFormatAttributes(
                GetExport(), sContent, sDefault, bExportValue);
        }
 
    }
    else
    {
 
        // number: value-type=..., value...=..., data-style-name=...
 
        DBG_ASSERT(bExportValueType || !bExportValue, "value w/o value type not supported!");
 
        // take care of illegal formats
        // (shouldn't happen, but does if document is corrupted)
        if (-1 != nFormatKey)
        {
            if (bExportValue || bExportValueType)
            {
                XMLNumberFormatAttributesExportHelper::
                    SetNumberFormatAttributes(
                        GetExport(), nFormatKey, fValue, bExportValue);
            }
 
            if (bExportStyle)
            {
                // don't export language (if desired)
                if( bForceSystemLanguage )
                    nFormatKey =
                        GetExport().dataStyleForceSystemLanguage( nFormatKey );
 
                OUString sDataStyleName =
                    GetExport().getDataStyleName(nFormatKey, bTimeStyle);
                if( !sDataStyleName.isEmpty() )
                {
                    GetExport().AddAttribute( XML_NAMESPACE_STYLE,
                                              XML_DATA_STYLE_NAME,
                                                sDataStyleName );
                } // else: ignore (no valid number format)
            }  // else: ignore (no number format)
        }
    }
}
 
 
/// process display related properties
void XMLTextFieldExport::ProcessDisplay(bool bIsVisible,
                                        bool bIsCommand)
{
    enum XMLTokenEnum eValue;
 
    if (bIsVisible)
    {
        eValue = bIsCommand ? XML_FORMULA : XML_VALUE;
    }
    else
    {
        eValue = XML_NONE;
    }
 
    // omit attribute if default
    if (eValue != XML_VALUE)
    {
        GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_DISPLAY, eValue);
    }
}
 
 
/// export boolean property
void XMLTextFieldExport::ProcessBoolean(enum XMLTokenEnum eName,
                                        bool bBool, bool bDefault)
{
    SAL_WARN_IF( eName == XML_TOKEN_INVALID, "xmloff.text", "invalid element token");
    if ( XML_TOKEN_INVALID == eName )
        return;
 
    // write attribute (if different than default)
    // negate to force 0/1 values (and make sal_Bool comparable)
    if ((!bBool) != (!bDefault)) {
        GetExport().AddAttribute(XML_NAMESPACE_TEXT, eName,
                                 (bBool ? XML_TRUE : XML_FALSE) );
    }
}
 
 
/// export string attribute
void XMLTextFieldExport::ProcessString(enum XMLTokenEnum eName,
                                       const OUString& sValue,
                                       bool bOmitEmpty,
                                       sal_uInt16 nPrefix)
{
    SAL_WARN_IF( eName == XML_TOKEN_INVALID, "xmloff.text", "invalid element token");
    if ( XML_TOKEN_INVALID == eName )
        return;
 
    // check for empty string, if applicable
    if ( bOmitEmpty && sValue.isEmpty() )
        return;
 
    // write attribute
    GetExport().AddAttribute(nPrefix, eName, sValue);
}
 
void XMLTextFieldExport::ProcessString(enum XMLTokenEnum eName,
                                       sal_uInt16 nValuePrefix,
                                       const OUString& sValue)
{
    OUString sQValue =
        GetExport().GetNamespaceMap().GetQNameByKey( nValuePrefix, sValue, false );
    ProcessString( eName, sQValue );
}
 
/// export a string attribute
void XMLTextFieldExport::ProcessString(enum XMLTokenEnum eName,
                                       const OUString& sValue,
                                       const OUString& sDefault)
{
    if (sValue != sDefault)
    {
        ProcessString(eName, sValue);
    }
}
 
/// export a string attribute
void XMLTextFieldExport::ProcessString(enum XMLTokenEnum eName,
                                       sal_uInt16 nValuePrefix,
                                       const OUString& sValue,
                                       const OUString& sDefault)
{
    if (sValue != sDefault)
    {
        ProcessString(eName, nValuePrefix, sValue);
    }
}
 
 
/// export string attribute
void XMLTextFieldExport::ProcessString(
    enum XMLTokenEnum eName,
    enum XMLTokenEnum eValue,
    sal_uInt16 nPrefix)
{
    SAL_WARN_IF( eName == XML_TOKEN_INVALID, "xmloff.text", "invalid element token" );
    SAL_WARN_IF( eValue == XML_TOKEN_INVALID, "xmloff.text", "invalid value token" );
    if ( XML_TOKEN_INVALID == eName )
        return;
 
    GetExport().AddAttribute(nPrefix, eName, eValue);
}
 
/// export a string attribute
void XMLTextFieldExport::ProcessString(
    enum XMLTokenEnum eName,
    enum XMLTokenEnum eValue,
    enum XMLTokenEnum eDefault)
{
    if ( eValue != eDefault )
        ProcessString( eName, eValue);
}
 
 
/// export a string as a sequence of paragraphs
void XMLTextFieldExport::ProcessParagraphSequence(
    const OUString& sParagraphSequence)
{
    // iterate over all string-pieces separated by return (0x0a) and
    // put each inside a paragraph element.
    SvXMLTokenEnumerator aEnumerator(sParagraphSequence, sal_Char(0x0a));
    OUString aSubString;
    while (aEnumerator.getNextToken(aSubString))
    {
        SvXMLElementExport aParagraph(
            GetExport(), XML_NAMESPACE_TEXT, XML_P, true, false);
        GetExport().Characters(aSubString);
    }
}
 
// export an integer attribute
void XMLTextFieldExport::ProcessInteger(enum XMLTokenEnum eName,
                                        sal_Int32 nNum)
{
    SAL_WARN_IF( eName == XML_TOKEN_INVALID, "xmloff.text", "invalid element token");
    if ( XML_TOKEN_INVALID == eName )
        return;
 
    GetExport().AddAttribute(XML_NAMESPACE_TEXT, eName,
                             OUString::number(nNum));
}
 
/// export an integer attribute, omit if default
void XMLTextFieldExport::ProcessIntegerDef(enum XMLTokenEnum eName,
                                        sal_Int32 nNum, sal_Int32 nDefault)
{
    if (nNum != nDefault)
        ProcessInteger(eName, nNum);
}
 
 
/// export a numbering type
void XMLTextFieldExport::ProcessNumberingType(sal_Int16 nNumberingType)
{
    // process only if real format (not: like page descriptor)
    if (NumberingType::PAGE_DESCRIPTOR != nNumberingType)
    {
        OUStringBuffer sTmp( 10 );
        // number type: num format
        GetExport().GetMM100UnitConverter().convertNumFormat( sTmp,
                                                              nNumberingType );
        GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_FORMAT,
                                      sTmp.makeStringAndClear() );
        // and letter sync, if applicable
        SvXMLUnitConverter::convertNumLetterSync( sTmp, nNumberingType );
 
        if (!sTmp.isEmpty())
        {
            GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_NUM_LETTER_SYNC,
                                     sTmp.makeStringAndClear() );
        }
    }
    // else: like page descriptor => ignore
}
 
 
/// export a date, time, or duration
void XMLTextFieldExport::ProcessDateTime(enum XMLTokenEnum eName,
                                         double dValue,
                                         bool bIsDate,
                                         bool bIsDuration,
                                         bool bOmitDurationIfZero,
                                         sal_uInt16 nPrefix)
{
    // truncate for date granularity
    if (bIsDate)
    {
        dValue = ::rtl::math::approxFloor(dValue);
    }
 
    OUStringBuffer aBuffer;
    if (bIsDuration)
    {
        // date/time duration handle bOmitDurationIfZero
        if (!bOmitDurationIfZero || dValue != 0.0)
        {
            ::sax::Converter::convertDuration(aBuffer, dValue);
        }
    }
    else
    {
        // date/time value
        rExport.GetMM100UnitConverter().convertDateTime(aBuffer, dValue);
    }
 
    // output attribute
    ProcessString(eName, aBuffer.makeStringAndClear(), true, nPrefix);
}
 
/// export a date or time
void XMLTextFieldExport::ProcessDateTime(enum XMLTokenEnum eName,
                                         const util::DateTime& rTime)
{
    OUStringBuffer aBuffer;
 
    util::DateTime aDateTime(rTime);
 
    // date/time value
    ::sax::Converter::convertDateTime(aBuffer, aDateTime, nullptr);
 
    // output attribute
    ProcessString(eName, aBuffer.makeStringAndClear(), true);
}
 
/// export a date, time, or duration
void XMLTextFieldExport::ProcessDateTime(enum XMLTokenEnum eName,
                                         sal_Int32 nMinutes,
                                         bool bIsDate,
                                         bool bIsDuration)
{
    // handle bOmitDurationIfZero here, because we can precisely compare ints
    if (!(bIsDuration && (nMinutes==0)))
    {
        ProcessDateTime(eName, static_cast<double>(nMinutes) / double(24*60),
                        bIsDate, bIsDuration);
    }
}
 
/// export a time or dateTime
void XMLTextFieldExport::ProcessTimeOrDateTime(enum XMLTokenEnum eName,
                                         const util::DateTime& rTime)
{
    OUStringBuffer aBuffer;
 
    // date/time value
    ::sax::Converter::convertTimeOrDateTime(aBuffer, rTime);
 
    // output attribute
    ProcessString(eName, aBuffer.makeStringAndClear(), true);
}
 
 
SvXMLEnumMapEntry<sal_Int16> const aBibliographyDataTypeMap[] =
{
    { XML_ARTICLE,          BibliographyDataType::ARTICLE },
    { XML_BOOK,             BibliographyDataType::BOOK },
    { XML_BOOKLET,          BibliographyDataType::BOOKLET },
    { XML_CONFERENCE,       BibliographyDataType::CONFERENCE },
    { XML_CUSTOM1,          BibliographyDataType::CUSTOM1 },
    { XML_CUSTOM2,          BibliographyDataType::CUSTOM2 },
    { XML_CUSTOM3,          BibliographyDataType::CUSTOM3 },
    { XML_CUSTOM4,          BibliographyDataType::CUSTOM4 },
    { XML_CUSTOM5,          BibliographyDataType::CUSTOM5 },
    { XML_EMAIL,            BibliographyDataType::EMAIL },
    { XML_INBOOK,           BibliographyDataType::INBOOK },
    { XML_INCOLLECTION,     BibliographyDataType::INCOLLECTION },
    { XML_INPROCEEDINGS,    BibliographyDataType::INPROCEEDINGS },
    { XML_JOURNAL,          BibliographyDataType::JOURNAL },
    { XML_MANUAL,           BibliographyDataType::MANUAL },
    { XML_MASTERSTHESIS,    BibliographyDataType::MASTERSTHESIS },
    { XML_MISC,             BibliographyDataType::MISC },
    { XML_PHDTHESIS,        BibliographyDataType::PHDTHESIS },
    { XML_PROCEEDINGS,      BibliographyDataType::PROCEEDINGS },
    { XML_TECHREPORT,       BibliographyDataType::TECHREPORT },
    { XML_UNPUBLISHED,      BibliographyDataType::UNPUBLISHED },
    { XML_WWW,              BibliographyDataType::WWW },
    { XML_TOKEN_INVALID, 0 }
};
 
 
void XMLTextFieldExport::ProcessBibliographyData(
    const Reference<XPropertySet>& rPropSet)
{
    // get the values
    Any aAny = rPropSet->getPropertyValue(gsPropertyFields);
    Sequence<PropertyValue> aValues;
    aAny >>= aValues;
 
    // one attribute per value (unless empty)
    sal_Int32 nLength = aValues.getLength();
    for (sal_Int32 i = 0; i < nLength; i++)
    {
        if( aValues[i].Name == "BibiliographicType" )
        {
            sal_Int16 nTypeId = 0;
            aValues[i].Value >>= nTypeId;
            OUStringBuffer sBuf;
 
            if (SvXMLUnitConverter::convertEnum(sBuf, nTypeId,
                                                aBibliographyDataTypeMap))
            {
                rExport.AddAttribute(XML_NAMESPACE_TEXT,
                                     XML_BIBLIOGRAPHY_TYPE,
                                     sBuf.makeStringAndClear());
            }
            // else: ignore this argument
        }
        else
        {
            OUString sStr;
            aValues[i].Value >>= sStr;
 
            if (!sStr.isEmpty())
            {
                rExport.AddAttribute(XML_NAMESPACE_TEXT,
                                     MapBibliographyFieldName(aValues[i].Name),
                                     sStr);
            }
        }
    }
}
 
/// export CommandTypeAttribute
void XMLTextFieldExport::ProcessCommandType(
    sal_Int32 nCommandType)
{
    enum XMLTokenEnum eToken = XML_TOKEN_INVALID;
    switch( nCommandType )
    {
        case sdb::CommandType::TABLE:   eToken = XML_TABLE; break;
        case sdb::CommandType::QUERY:   eToken = XML_QUERY; break;
        case sdb::CommandType::COMMAND: eToken = XML_COMMAND; break;
    }
 
    if( eToken != XML_TOKEN_INVALID )
        rExport.AddAttribute( XML_NAMESPACE_TEXT, XML_TABLE_TYPE, eToken );
}
 
 
void XMLTextFieldExport::ProcessStringSequence(
    const Sequence<OUString>& rSequence,
    const OUString& sSelected )
{
    // find selected element
    sal_Int32 nSelected = -1;
    sal_Int32 nLength = rSequence.getLength();
    const OUString* pSequence = rSequence.getConstArray();
    for( sal_Int32 i = 0; i < nLength; i++ )
    {
        if( pSequence[i] == sSelected )
            nSelected = i;
    }
 
    // delegate to ProcessStringSequence(OUString,sal_Int32)
    ProcessStringSequence( rSequence, nSelected );
}
 
void XMLTextFieldExport::ProcessStringSequence(
    const Sequence<OUString>& rSequence,
    sal_Int32 nSelected )
{
    sal_Int32 nLength = rSequence.getLength();
    const OUString* pSequence = rSequence.getConstArray();
    for( sal_Int32 i = 0; i < nLength; i++ )
    {
        if( i == nSelected )
            rExport.AddAttribute( XML_NAMESPACE_TEXT,
                                  XML_CURRENT_SELECTED, XML_TRUE );
        rExport.AddAttribute( XML_NAMESPACE_TEXT, XML_VALUE, pSequence[i] );
        SvXMLElementExport aElement( rExport, XML_NAMESPACE_TEXT, XML_LABEL,
                                     false, false );
    }
}
 
void XMLTextFieldExport::ExportDataBaseElement(
    enum XMLTokenEnum eElementName,
    const OUString& sPresentation,
    const Reference<XPropertySet>& rPropertySet,
    const Reference<XPropertySetInfo>& rPropertySetInfo )
{
    SAL_WARN_IF( eElementName == XML_TOKEN_INVALID, "xmloff.text", "need token" );
    SAL_WARN_IF( !rPropertySet.is(), "xmloff.text", "need property set" );
    SAL_WARN_IF( !rPropertySetInfo.is(), "xmloff.text", "need property set info" );
 
    // get database properties
    OUString sDataBaseName;
    OUString sDataBaseURL;
    OUString sStr;
    if( ( rPropertySet->getPropertyValue( gsPropertyDataBaseName ) >>= sStr )
        && !sStr.isEmpty() )
    {
        sDataBaseName = sStr;
    }
    else if( rPropertySetInfo->hasPropertyByName( gsPropertyDataBaseURL ) &&
             (rPropertySet->getPropertyValue( gsPropertyDataBaseURL ) >>= sStr) &&
             !sStr.isEmpty() )
    {
        sDataBaseURL = sStr;
    }
 
    // add database name property (if present)
    if( !sDataBaseName.isEmpty() )
        rExport.AddAttribute( XML_NAMESPACE_TEXT, XML_DATABASE_NAME,
                              sDataBaseName );
    SvXMLElementExport aDataBaseElement( GetExport(),
                                         XML_NAMESPACE_TEXT, eElementName,
                                         false, false );
 
    // write URL as children
    if( !sDataBaseURL.isEmpty() )
    {
        rExport.AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, sDataBaseURL );
        SvXMLElementExport aDataSourceElement(
            GetExport(), XML_NAMESPACE_FORM, XML_CONNECTION_RESOURCE,
            false, false );
    }
 
    // write presentation
    rExport.Characters( sPresentation );
}
 
 
// explode a field master name into field type and field name
void XMLTextFieldExport::ExplodeFieldMasterName(
    const OUString& sMasterName, OUString& sFieldType, OUString& sVarName)
{
    sal_Int32 nLength = gsFieldMasterPrefix.getLength();
    sal_Int32 nSeparator = sMasterName.indexOf('.', nLength);
 
    // '.' found?
    if (nSeparator <= nLength) {
        SAL_WARN("xmloff.text", "no field var name!");
    }
    else
    {
        sFieldType = sMasterName.copy(nLength, nSeparator-nLength);
        sVarName = sMasterName.copy(nSeparator+1);
    }
}
 
 
// for XDependentTextFields, get PropertySet of FieldMaster
Reference<XPropertySet> XMLTextFieldExport::GetMasterPropertySet(
    const Reference<XTextField> & rTextField)
{
    // name, value => get Property set of TextFieldMaster
    Reference<XDependentTextField> xDep(rTextField, UNO_QUERY);
    return xDep->getTextFieldMaster();
}
 
// get PropertySet of (any; the first) dependent field
bool XMLTextFieldExport::GetDependentFieldPropertySet(
    const Reference<XPropertySet> & xMaster,
    Reference<XPropertySet> & xField)
{
    Any aAny;
    Sequence<Reference<XDependentTextField> > aFields;
    aAny = xMaster->getPropertyValue(gsPropertyDependentTextFields);
    aAny >>= aFields;
 
    // any fields?
    if (aFields.getLength() > 0)
    {
        // get first one and return
        Reference<XDependentTextField> xTField = aFields[0];
        xField.set(xTField, UNO_QUERY);
        DBG_ASSERT(xField.is(),
                  "Surprisingly, this TextField refuses to be a PropertySet!");
        return true;
    }
    else
    {
        return false;
    }
}
 
 
/// map placeholder type
enum XMLTokenEnum XMLTextFieldExport::MapPlaceholderType(sal_uInt16 nType)
{
    enum XMLTokenEnum eType = XML_TEXT;
 
    switch (nType)
    {
        case PlaceholderType::TEXT:
            eType = XML_TEXT;
            break;
 
        case PlaceholderType::TABLE:
            eType = XML_TABLE;
            break;
 
        case PlaceholderType::TEXTFRAME:
            eType = XML_TEXT_BOX;
            break;
 
        case PlaceholderType::GRAPHIC:
            eType = XML_IMAGE;
            break;
 
        case PlaceholderType::OBJECT:
            eType = XML_OBJECT;
            break;
 
        default:
            // unknown placeholder: XML_TEXT
            OSL_FAIL("unknown placeholder type");
    }
 
    return eType;
}
 
 
/// element name for author fields
enum XMLTokenEnum XMLTextFieldExport::MapAuthorFieldName(
    const Reference<XPropertySet> & xPropSet)
{
    // Initials or full name?
    return GetBoolProperty(gsPropertyFullName, xPropSet)
        ? XML_AUTHOR_NAME : XML_AUTHOR_INITIALS;
}
 
enum XMLTokenEnum XMLTextFieldExport::MapPageNumberName(
    const Reference<XPropertySet> & xPropSet,
    sal_Int32& nOffset)
{
    enum XMLTokenEnum eName = XML_TOKEN_INVALID;
    PageNumberType ePage;
    Any aAny = xPropSet->getPropertyValue(gsPropertySubType);
    ePage = *o3tl::doAccess<PageNumberType>(aAny);
 
    switch (ePage)
    {
        case PageNumberType_PREV:
            eName = XML_PREVIOUS;
            nOffset += 1;
            break;
        case PageNumberType_CURRENT:
            eName = XML_CURRENT;
            break;
        case PageNumberType_NEXT:
            eName = XML_NEXT;
            nOffset -= 1;
            break;
        default:
            OSL_FAIL("unknown page number type");
            eName = XML_TOKEN_INVALID;
            break;
    }
 
    return eName;
}
 
/// map TemplateDisplayFormat to XML
enum XMLTokenEnum XMLTextFieldExport::MapTemplateDisplayFormat(sal_Int16 nFormat)
{
    enum XMLTokenEnum eName = XML_TOKEN_INVALID;
 
    switch (nFormat)
    {
        case TemplateDisplayFormat::FULL:
            eName = XML_FULL;
            break;
        case TemplateDisplayFormat::PATH:
            eName = XML_PATH;
            break;
        case TemplateDisplayFormat::NAME:
            eName = XML_NAME;
            break;
        case TemplateDisplayFormat::NAME_AND_EXT:
            eName = XML_NAME_AND_EXTENSION;
            break;
        case TemplateDisplayFormat::AREA:
            eName = XML_AREA;
            break;
        case TemplateDisplayFormat::TITLE:
            eName = XML_TITLE;
            break;
        default:
            OSL_FAIL("unknown template display format");
            eName = XML_TOKEN_INVALID;
            break;
    }
 
    return eName;
}
 
/// map count/statistics field token to XML name
enum XMLTokenEnum XMLTextFieldExport::MapCountFieldName(FieldIdEnum nToken)
{
    enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
 
    switch (nToken)
    {
        case FIELD_ID_COUNT_PAGES:
            eElement = XML_PAGE_COUNT;
            break;
        case FIELD_ID_COUNT_PARAGRAPHS:
            eElement = XML_PARAGRAPH_COUNT;
            break;
        case FIELD_ID_COUNT_WORDS:
            eElement = XML_WORD_COUNT;
            break;
        case FIELD_ID_COUNT_CHARACTERS:
            eElement = XML_CHARACTER_COUNT;
            break;
        case FIELD_ID_COUNT_TABLES:
            eElement = XML_TABLE_COUNT;
            break;
        case FIELD_ID_COUNT_GRAPHICS:
            eElement = XML_IMAGE_COUNT;
            break;
        case FIELD_ID_COUNT_OBJECTS:
            eElement = XML_OBJECT_COUNT;
            break;
        default:
            OSL_FAIL("no count field token");
            eElement = XML_TOKEN_INVALID;
            break;
    }
 
    return eElement;
}
 
/// map ChapterDisplayFormat to XML string
enum XMLTokenEnum XMLTextFieldExport::MapChapterDisplayFormat(sal_Int16 nFormat)
{
    enum XMLTokenEnum eName = XML_TOKEN_INVALID;
 
    switch (nFormat)
    {
        case ChapterFormat::NAME:
            eName = XML_NAME;
            break;
        case ChapterFormat::NUMBER:
            eName = XML_NUMBER;
            break;
        case ChapterFormat::NAME_NUMBER:
            eName = XML_NUMBER_AND_NAME;
            break;
        case ChapterFormat::NO_PREFIX_SUFFIX:
            eName = XML_PLAIN_NUMBER_AND_NAME;
            break;
        case ChapterFormat::DIGIT:
            eName = XML_PLAIN_NUMBER;
            break;
        default:
            OSL_FAIL("unknown chapter display format");
            eName = XML_TOKEN_INVALID;
            break;
    }
 
    return eName;
}
 
 
/// map FilenameDisplayFormat to XML attribute names
enum XMLTokenEnum XMLTextFieldExport::MapFilenameDisplayFormat(sal_Int16 nFormat)
{
    enum XMLTokenEnum eName = XML_TOKEN_INVALID;
 
    switch (nFormat)
    {
        case FilenameDisplayFormat::FULL:
            eName = XML_FULL;
            break;
        case FilenameDisplayFormat::PATH:
            eName = XML_PATH;
            break;
        case FilenameDisplayFormat::NAME:
            eName = XML_NAME;
            break;
        case FilenameDisplayFormat::NAME_AND_EXT:
            eName = XML_NAME_AND_EXTENSION;
            break;
        default:
            OSL_FAIL("unknown filename display format");
    }
 
    return eName;
}
 
 
/// map ReferenceFieldPart to XML string
enum XMLTokenEnum XMLTextFieldExport::MapReferenceType(sal_Int16 nType)
{
    enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
 
    switch (nType)
    {
        case ReferenceFieldPart::PAGE:
            eElement = XML_PAGE;
            break;
        case ReferenceFieldPart::CHAPTER:
            eElement = XML_CHAPTER;
            break;
        case ReferenceFieldPart::TEXT:
            eElement = XML_TEXT;
            break;
        case ReferenceFieldPart::UP_DOWN:
            eElement = XML_DIRECTION;
            break;
        case ReferenceFieldPart::CATEGORY_AND_NUMBER:
            eElement = XML_CATEGORY_AND_VALUE;
            break;
        case ReferenceFieldPart::ONLY_CAPTION:
            eElement = XML_CAPTION;
            break;
        case ReferenceFieldPart::ONLY_SEQUENCE_NUMBER:
            eElement = XML_VALUE;
            break;
        case ReferenceFieldPart::PAGE_DESC:
            // small hack: this value never gets written, because
            // XML_TEMPLATE is default
            eElement = XML_TEMPLATE;
            break;
        // Core implementation for direct cross-references (#i81002#)
        case ReferenceFieldPart::NUMBER:
            eElement = XML_NUMBER;
            break;
        case ReferenceFieldPart::NUMBER_NO_CONTEXT:
            eElement = XML_NUMBER_NO_SUPERIOR;
            break;
        case ReferenceFieldPart::NUMBER_FULL_CONTEXT:
            eElement = XML_NUMBER_ALL_SUPERIOR;
            break;
        default:
            OSL_FAIL("unknown reference type");
            eElement = XML_TEMPLATE;
            break;
    }
 
    return eElement;
}
 
/// map ReferenceFieldPart to XML string
enum XMLTokenEnum XMLTextFieldExport::MapReferenceSource(sal_Int16 nType)
{
    enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
 
    switch (nType)
    {
        case ReferenceFieldSource::REFERENCE_MARK:
            eElement = XML_REFERENCE_REF;
            break;
        case ReferenceFieldSource::SEQUENCE_FIELD:
            eElement = XML_SEQUENCE_REF;
            break;
        case ReferenceFieldSource::BOOKMARK:
            eElement = XML_BOOKMARK_REF;
            break;
        case ReferenceFieldSource::FOOTNOTE:
        case ReferenceFieldSource::ENDNOTE:
            eElement = XML_NOTE_REF;
            break;
        default:
            OSL_FAIL("unknown reference source");
            break;
    }
 
    return eElement;
}
 
 
/// element name for sender fields
enum XMLTokenEnum XMLTextFieldExport::MapSenderFieldName(
    const Reference<XPropertySet> & xPropSet)
{
    enum XMLTokenEnum eName = XML_TOKEN_INVALID;
 
    // sub-field type
    switch (GetInt16Property(gsPropertyFieldSubType, xPropSet))
    {
        case UserDataPart::COMPANY :
            eName = XML_SENDER_COMPANY;
            break;
        case UserDataPart::FIRSTNAME :
            eName = XML_SENDER_FIRSTNAME;
            break;
        case UserDataPart::NAME :
            eName = XML_SENDER_LASTNAME;
            break;
        case UserDataPart::SHORTCUT :
            eName = XML_SENDER_INITIALS;
            break;
        case UserDataPart::STREET :
            eName = XML_SENDER_STREET;
            break;
        case UserDataPart::COUNTRY :
            eName = XML_SENDER_COUNTRY;
            break;
        case UserDataPart::ZIP :
            eName = XML_SENDER_POSTAL_CODE;
            break;
        case UserDataPart::CITY :
            eName = XML_SENDER_CITY;
            break;
        case UserDataPart::TITLE :
            eName = XML_SENDER_TITLE;
            break;
        case UserDataPart::POSITION :
            eName = XML_SENDER_POSITION;
            break;
        case UserDataPart::PHONE_PRIVATE :
            eName = XML_SENDER_PHONE_PRIVATE;
            break;
        case UserDataPart::PHONE_COMPANY :
            eName = XML_SENDER_PHONE_WORK;
            break;
        case UserDataPart::FAX :
            eName = XML_SENDER_FAX;
            break;
        case UserDataPart::EMAIL :
            eName = XML_SENDER_EMAIL;
            break;
        case UserDataPart::STATE :
            eName = XML_SENDER_STATE_OR_PROVINCE;
            break;
        default:
            SAL_WARN("xmloff.text", "unknown sender type");
            eName = XML_TOKEN_INVALID;
            break;
    }
 
    return eName;
}
 
enum XMLTokenEnum XMLTextFieldExport::MapDocInfoFieldName(
    enum FieldIdEnum nToken)
{
    enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
 
    switch (nToken)
    {
        case FIELD_ID_DOCINFO_CREATION_AUTHOR:
            eElement = XML_INITIAL_CREATOR;
            break;
        case FIELD_ID_DOCINFO_CREATION_DATE:
            eElement = XML_CREATION_DATE;
            break;
        case FIELD_ID_DOCINFO_CREATION_TIME:
            eElement = XML_CREATION_TIME;
            break;
        case FIELD_ID_DOCINFO_DESCRIPTION:
            eElement = XML_DESCRIPTION;
            break;
        case FIELD_ID_DOCINFO_PRINT_TIME:
            eElement = XML_PRINT_TIME;
            break;
        case FIELD_ID_DOCINFO_PRINT_DATE:
            eElement = XML_PRINT_DATE;
            break;
        case FIELD_ID_DOCINFO_PRINT_AUTHOR:
            eElement = XML_PRINTED_BY;
            break;
        case FIELD_ID_DOCINFO_TITLE:
            eElement = XML_TITLE;
            break;
        case FIELD_ID_DOCINFO_SUBJECT:
            eElement = XML_SUBJECT;
            break;
        case FIELD_ID_DOCINFO_KEYWORDS:
            eElement = XML_KEYWORDS;
            break;
        case FIELD_ID_DOCINFO_REVISION:
            eElement = XML_EDITING_CYCLES;
            break;
        case FIELD_ID_DOCINFO_EDIT_DURATION:
            eElement = XML_EDITING_DURATION;
            break;
        case FIELD_ID_DOCINFO_SAVE_TIME:
            eElement = XML_MODIFICATION_TIME;
            break;
        case FIELD_ID_DOCINFO_SAVE_DATE:
            eElement = XML_MODIFICATION_DATE;
            break;
        case FIELD_ID_DOCINFO_SAVE_AUTHOR:
            eElement = XML_CREATOR;
            break;
        default:
            SAL_WARN("xmloff.text", "unknown docinfo field type!");
            eElement = XML_TOKEN_INVALID;
            break;
    }
 
    return eElement;
}
 
enum XMLTokenEnum XMLTextFieldExport::MapBibliographyFieldName(const OUString& sName)
{
    enum XMLTokenEnum eName = XML_TOKEN_INVALID;
 
    if( sName == "Identifier" )
    {
        eName = XML_IDENTIFIER;
    }
    else if( sName == "BibiliographicType" )
    {
        eName = XML_BIBLIOGRAPHY_TYPE;
    }
    else if( sName == "Address" )
    {
        eName = XML_ADDRESS;
    }
    else if( sName == "Annote" )
    {
        eName = XML_ANNOTE;
    }
    else if( sName == "Author" )
    {
        eName = XML_AUTHOR;
    }
    else if( sName == "Booktitle" )
    {
        eName = XML_BOOKTITLE;
    }
    else if( sName == "Chapter" )
    {
        eName = XML_CHAPTER;
    }
    else if( sName == "Edition" )
    {
        eName = XML_EDITION;
    }
    else if( sName == "Editor" )
    {
        eName = XML_EDITOR;
    }
    else if( sName == "Howpublished" )
    {
        eName = XML_HOWPUBLISHED;
    }
    else if( sName == "Institution" )
    {
        eName = XML_INSTITUTION;
    }
    else if( sName == "Journal" )
    {
        eName = XML_JOURNAL;
    }
    else if( sName =="Month" )
    {
        eName = XML_MONTH;
    }
    else if( sName == "Note" )
    {
        eName = XML_NOTE;
    }
    else if( sName == "Number" )
    {
        eName = XML_NUMBER;
    }
    else if( sName == "Organizations" )
    {
        eName = XML_ORGANIZATIONS;
    }
    else if( sName == "Pages" )
    {
        eName = XML_PAGES;
    }
    else if( sName == "Publisher" )
    {
        eName = XML_PUBLISHER;
    }
    else if( sName == "School" )
    {
        eName = XML_SCHOOL;
    }
    else if( sName == "Series" )
    {
        eName = XML_SERIES;
    }
    else if( sName == "Title" )
    {
        eName = XML_TITLE;
    }
    else if( sName == "Report_Type" )
    {
        eName = XML_REPORT_TYPE;
    }
    else if( sName == "Volume" )
    {
        eName = XML_VOLUME;
    }
    else if( sName == "Year" )
    {
        eName = XML_YEAR;
    }
    else if( sName == "URL" )
    {
        eName = XML_URL;
    }
    else if( sName == "Custom1" )
    {
        eName = XML_CUSTOM1;
    }
    else if( sName == "Custom2" )
    {
        eName = XML_CUSTOM2;
    }
    else if( sName == "Custom3" )
    {
        eName = XML_CUSTOM3;
    }
    else if( sName == "Custom4" )
    {
        eName = XML_CUSTOM4;
    }
    else if( sName == "Custom5" )
    {
        eName = XML_CUSTOM5;
    }
    else if( sName == "ISBN" )
    {
        eName = XML_ISBN;
    }
    else
    {
        OSL_FAIL("Unknown bibliography info data");
        eName = XML_TOKEN_INVALID;
    }
 
    return eName;
}
 
enum XMLTokenEnum XMLTextFieldExport::MapMeasureKind(sal_Int16 nKind)
{
    switch( nKind )
    {
    case 0:
        return XML_VALUE;
    case 1:
        return XML_UNIT;
    }
    return XML_GAP;
}
 
OUString XMLTextFieldExport::MakeFootnoteRefName(
    sal_Int16 nSeqNo)
{
    // generate foot-/endnote ID
    OUStringBuffer aBuf;
    aBuf.append("ftn");
    aBuf.append(static_cast<sal_Int32>(nSeqNo));
    return aBuf.makeStringAndClear();
}
 
OUString XMLTextFieldExport::MakeSequenceRefName(
    sal_Int16 nSeqNo,
    const OUString& rSeqName)
{
    // generate foot-/endnote ID
    OUStringBuffer aBuf;
    aBuf.append("ref");
    aBuf.append(rSeqName);
    aBuf.append(static_cast<sal_Int32>(nSeqNo));
    return aBuf.makeStringAndClear();
}
 
 
// Property accessor helper functions
 
 
// to be relegated (does that word exist?) to a more appropriate place
 
 
inline bool GetBoolProperty(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet)
{
    Any aAny = xPropSet->getPropertyValue(sPropName);
    bool bBool = *o3tl::doAccess<bool>(aAny);
    return bBool;
}
 
inline bool GetOptionalBoolProperty(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet,
    const Reference<XPropertySetInfo> & xPropSetInfo,
    bool bDefault)
{
    return xPropSetInfo->hasPropertyByName( sPropName )
        ? GetBoolProperty( sPropName, xPropSet ) : bDefault;
}
 
inline double GetDoubleProperty(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet)
{
    Any aAny = xPropSet->getPropertyValue(sPropName);
    double fDouble = 0.0;
    aAny >>= fDouble;
    return fDouble;
}
 
inline OUString const GetStringProperty(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet)
{
    Any aAny = xPropSet->getPropertyValue(sPropName);
    OUString sString;
    aAny >>= sString;
    return sString;
}
 
inline sal_Int32 GetIntProperty(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet)
{
    Any aAny = xPropSet->getPropertyValue(sPropName);
    sal_Int32 nInt = 0;
    aAny >>= nInt;
    return nInt;
}
 
inline sal_Int16 GetInt16Property(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet)
{
    Any aAny = xPropSet->getPropertyValue(sPropName);
    sal_Int16 nInt = 0;
    aAny >>= nInt;
    return nInt;
}
 
inline sal_Int8 GetInt8Property(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet)
{
    Any aAny = xPropSet->getPropertyValue(sPropName);
    sal_Int8 nInt = 0;
    aAny >>= nInt;
    return nInt;
}
 
inline util::DateTime const GetDateTimeProperty(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet)
{
    Any aAny = xPropSet->getPropertyValue(sPropName);
    util::DateTime aTime;
    aAny >>= aTime;
    return aTime;
}
 
inline Sequence<OUString> const GetStringSequenceProperty(
    const OUString& sPropName,
    const Reference<XPropertySet> & xPropSet)
{
    Any aAny = xPropSet->getPropertyValue(sPropName);
    Sequence<OUString> aSequence;
    aAny >>= aSequence;
    return aSequence;
}
 
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

V1001 The 'aAny' variable is assigned but is not used by the end of the function.

V1001 The 'aAny' variable is assigned but is not used by the end of the function.

V1001 The 'aAny' variable is assigned but is not used by the end of the function.

V1001 The 'aAny' variable is assigned but is not used by the end of the function.

V1019 Compound assignment expression is used inside condition.

V1001 The 'aAny' variable is assigned but is not used by the end of the function.

V1001 The 'aAny' variable is assigned but is not used by the end of the function.

V1001 The 'aAny' variable is assigned but is not used by the end of the function.