/**************************************************************
 * 
 * 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
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include "XMLSectionExport.hxx"
#include <rtl/ustring.hxx>
#include <rtl/ustrbuf.hxx>

#include <vector>


#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/container/XIndexReplace.hpp>
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/PropertyValues.hpp>
#include <com/sun/star/beans/PropertyState.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/text/XTextSection.hpp>
#include <com/sun/star/text/SectionFileLink.hpp>
#include <com/sun/star/container/XNamed.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/text/XDocumentIndex.hpp>
#include <com/sun/star/uno/XInterface.hpp>
#include <com/sun/star/text/BibliographyDataField.hpp>
#include <com/sun/star/text/XTextFieldsSupplier.hpp>
#include <com/sun/star/text/XChapterNumberingSupplier.hpp>
#include <com/sun/star/text/ChapterFormat.hpp> //i90246
#include <xmloff/xmltoken.hxx>
#include "xmloff/xmlnmspe.hxx"
#include <xmloff/families.hxx>
#include <xmloff/xmluconv.hxx>
#include <xmloff/nmspmap.hxx>
#include <xmloff/xmlexp.hxx>
#include <xmloff/xmltkmap.hxx>
#include "txtflde.hxx"



using namespace ::com::sun::star;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::uno;
using namespace ::std;
using namespace ::xmloff::token;

using ::rtl::OUString;
using ::rtl::OUStringBuffer;
using ::com::sun::star::beans::XPropertySet;
using ::com::sun::star::beans::PropertyValue;
using ::com::sun::star::beans::PropertyValues;
using ::com::sun::star::beans::PropertyState;
using ::com::sun::star::container::XIndexReplace;
using ::com::sun::star::container::XNameAccess;
using ::com::sun::star::container::XNamed;
using ::com::sun::star::lang::XServiceInfo;
using ::com::sun::star::lang::Locale;
using ::com::sun::star::uno::XInterface;


XMLSectionExport::XMLSectionExport(
	SvXMLExport& rExp,
	XMLTextParagraphExport& rParaExp)
:	sCondition(RTL_CONSTASCII_USTRINGPARAM("Condition"))
,	sCreateFromChapter(RTL_CONSTASCII_USTRINGPARAM("CreateFromChapter"))
,	sCreateFromEmbeddedObjects(RTL_CONSTASCII_USTRINGPARAM("CreateFromEmbeddedObjects"))
,	sCreateFromGraphicObjects(RTL_CONSTASCII_USTRINGPARAM("CreateFromGraphicObjects"))
,	sCreateFromLabels(RTL_CONSTASCII_USTRINGPARAM("CreateFromLabels"))
,	sCreateFromMarks(RTL_CONSTASCII_USTRINGPARAM("CreateFromMarks"))
,	sCreateFromOtherEmbeddedObjects(RTL_CONSTASCII_USTRINGPARAM("CreateFromOtherEmbeddedObjects"))
,	sCreateFromOutline(RTL_CONSTASCII_USTRINGPARAM("CreateFromOutline"))
,	sCreateFromStarCalc(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarCalc"))
,	sCreateFromStarChart(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarChart"))
,	sCreateFromStarDraw(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarDraw"))
,	sCreateFromStarImage(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarImage"))
,	sCreateFromStarMath(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarMath"))
,	sCreateFromTables(RTL_CONSTASCII_USTRINGPARAM("CreateFromTables"))
,	sCreateFromTextFrames(RTL_CONSTASCII_USTRINGPARAM("CreateFromTextFrames"))
,	sDdeCommandElement(RTL_CONSTASCII_USTRINGPARAM("DDECommandElement"))
,	sDdeCommandFile(RTL_CONSTASCII_USTRINGPARAM("DDECommandFile"))
,	sDdeCommandType(RTL_CONSTASCII_USTRINGPARAM("DDECommandType"))
,	sFileLink(RTL_CONSTASCII_USTRINGPARAM("FileLink"))
,	sIsCaseSensitive(RTL_CONSTASCII_USTRINGPARAM("IsCaseSensitive"))
,	sIsProtected(RTL_CONSTASCII_USTRINGPARAM("IsProtected"))
,	sIsVisible(RTL_CONSTASCII_USTRINGPARAM("IsVisible"))
,	sLabelCategory(RTL_CONSTASCII_USTRINGPARAM("LabelCategory"))
,	sLabelDisplayType(RTL_CONSTASCII_USTRINGPARAM("LabelDisplayType"))
,	sLevel(RTL_CONSTASCII_USTRINGPARAM("Level"))
,	sLevelFormat(RTL_CONSTASCII_USTRINGPARAM("LevelFormat"))
,	sLevelParagraphStyles(RTL_CONSTASCII_USTRINGPARAM("LevelParagraphStyles"))
,	sLinkRegion(RTL_CONSTASCII_USTRINGPARAM("LinkRegion"))
,	sMainEntryCharacterStyleName(RTL_CONSTASCII_USTRINGPARAM("MainEntryCharacterStyleName"))
,	sParaStyleHeading(RTL_CONSTASCII_USTRINGPARAM("ParaStyleHeading"))
,	sParaStyleLevel(RTL_CONSTASCII_USTRINGPARAM("ParaStyleLevel"))
,	sTitle(RTL_CONSTASCII_USTRINGPARAM("Title"))
,	sName(RTL_CONSTASCII_USTRINGPARAM("Name"))
,	sUseAlphabeticalSeparators(RTL_CONSTASCII_USTRINGPARAM("UseAlphabeticalSeparators"))
,	sUseCombinedEntries(RTL_CONSTASCII_USTRINGPARAM("UseCombinedEntries"))
,	sUseDash(RTL_CONSTASCII_USTRINGPARAM("UseDash"))
,	sUseKeyAsEntry(RTL_CONSTASCII_USTRINGPARAM("UseKeyAsEntry"))
,	sUseLevelFromSource(RTL_CONSTASCII_USTRINGPARAM("UseLevelFromSource"))
,	sUsePP(RTL_CONSTASCII_USTRINGPARAM("UsePP"))
,	sUseUpperCase(RTL_CONSTASCII_USTRINGPARAM("UseUpperCase"))
,	sIsCommaSeparated(RTL_CONSTASCII_USTRINGPARAM("IsCommaSeparated"))
,	sIsAutomaticUpdate(RTL_CONSTASCII_USTRINGPARAM("IsAutomaticUpdate"))
,	sIsRelativeTabstops(RTL_CONSTASCII_USTRINGPARAM("IsRelativeTabstops"))
,	sCreateFromLevelParagraphStyles(RTL_CONSTASCII_USTRINGPARAM("CreateFromLevelParagraphStyles"))
,	sDocumentIndex(RTL_CONSTASCII_USTRINGPARAM("DocumentIndex"))
,	sContentSection(RTL_CONSTASCII_USTRINGPARAM("ContentSection"))
,	sHeaderSection(RTL_CONSTASCII_USTRINGPARAM("HeaderSection"))

,	sTextSection(RTL_CONSTASCII_USTRINGPARAM("TextSection"))
,	sIsGlobalDocumentSection(RTL_CONSTASCII_USTRINGPARAM("IsGlobalDocumentSection"))
,	sProtectionKey(RTL_CONSTASCII_USTRINGPARAM("ProtectionKey"))
,	sSortAlgorithm(RTL_CONSTASCII_USTRINGPARAM("SortAlgorithm"))
,	sLocale(RTL_CONSTASCII_USTRINGPARAM("Locale"))
,	sUserIndexName(RTL_CONSTASCII_USTRINGPARAM("UserIndexName"))

,	sIsCurrentlyVisible(RTL_CONSTASCII_USTRINGPARAM("IsCurrentlyVisible"))
,	sHeadingStyleName(RTL_CONSTASCII_USTRINGPARAM("HeadingStyleName"))

,	rExport(rExp)
,	rParaExport(rParaExp)
,	bHeadingDummiesExported( sal_False )
{
}


void XMLSectionExport::ExportSectionStart(
	const Reference<XTextSection> & rSection,
	sal_Bool bAutoStyles)
{
	Reference<XPropertySet> xPropertySet(rSection, UNO_QUERY);

	// always export section (auto) style
	if (bAutoStyles)
	{
		// get PropertySet and add section style
		GetParaExport().Add( XML_STYLE_FAMILY_TEXT_SECTION, xPropertySet );
	}
	else
	{
		// always export section style
		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
									 GetParaExport().Find(
									 XML_STYLE_FAMILY_TEXT_SECTION,
									 xPropertySet, sEmpty ) );

        // xml:id for RDF metadata
        GetExport().AddAttributeXmlId(rSection);

		// export index or regular section
		Reference<XDocumentIndex> xIndex;
		if (GetIndex(rSection, xIndex))
		{
			if (xIndex.is())
			{
				// we are an index
				ExportIndexStart(xIndex);
			}
			else
			{
				// we are an index header
				ExportIndexHeaderStart(rSection);
			}
		}
		else
		{
			// we are not an index
			ExportRegularSectionStart(rSection);
		}
	}
}

sal_Bool XMLSectionExport::GetIndex(
	const Reference<XTextSection> & rSection,
	Reference<XDocumentIndex> & rIndex) const
{
	// first, reset result
	sal_Bool bRet = sal_False;
	rIndex = NULL;

	// get section Properties
	Reference<XPropertySet> xSectionPropSet(rSection, UNO_QUERY);

	// then check if this section happens to be inside an index
	if (xSectionPropSet->getPropertySetInfo()->
									hasPropertyByName(sDocumentIndex))
	{
		Any aAny = xSectionPropSet->getPropertyValue(sDocumentIndex);
		Reference<XDocumentIndex> xDocumentIndex;
		aAny >>= xDocumentIndex;

		// OK, are we inside of an index
		if (xDocumentIndex.is())
		{
			// is the enclosing index identical with "our" section?
			Reference<XPropertySet> xIndexPropSet(xDocumentIndex, UNO_QUERY);
			aAny = xIndexPropSet->getPropertyValue(sContentSection);
			Reference<XTextSection> xEnclosingSection;
			aAny >>= xEnclosingSection;

			// if the enclosing section is "our" section, then we are an index!
			if (rSection == xEnclosingSection)
			{
				rIndex = xDocumentIndex;
				bRet = sal_True;
			}
			// else: index header or regular section

			// is the enclosing index identical with the header section?
			aAny = xIndexPropSet->getPropertyValue(sHeaderSection);
			// now mis-named: contains header section
			aAny >>= xEnclosingSection;

			// if the enclosing section is "our" section, then we are an index!
			if (rSection == xEnclosingSection)
			{
				bRet = sal_True;
			}
			// else: regular section
		}
		// else: we aren't even inside of an index
	}
	// else: we don't even know what an index is.

	return bRet;
}


void XMLSectionExport::ExportSectionEnd(
	const Reference<XTextSection> & rSection,
	sal_Bool bAutoStyles)
{
	// no end section for styles
	if (!bAutoStyles)
	{
		enum XMLTokenEnum eElement = XML_TOKEN_INVALID;

		// export index or regular section end
		Reference<XDocumentIndex> xIndex;
		if (GetIndex(rSection, xIndex))
		{
			if (xIndex.is())
			{
				// index end: close index body element
				GetExport().EndElement( XML_NAMESPACE_TEXT,	XML_INDEX_BODY,
                                        sal_True );
				GetExport().IgnorableWhitespace();

				switch (MapSectionType(xIndex->getServiceName()))
				{
					case TEXT_SECTION_TYPE_TOC:
						eElement = XML_TABLE_OF_CONTENT;
						break;

					case TEXT_SECTION_TYPE_ILLUSTRATION:
						eElement = XML_ILLUSTRATION_INDEX;
						break;

					case TEXT_SECTION_TYPE_ALPHABETICAL:
						eElement = XML_ALPHABETICAL_INDEX;
						break;

					case TEXT_SECTION_TYPE_TABLE:
						eElement = XML_TABLE_INDEX;
						break;

					case TEXT_SECTION_TYPE_OBJECT:
						eElement = XML_OBJECT_INDEX;
						break;

					case TEXT_SECTION_TYPE_USER:
						eElement = XML_USER_INDEX;
						break;

					case TEXT_SECTION_TYPE_BIBLIOGRAPHY:
						eElement = XML_BIBLIOGRAPHY;
						break;

					default:
						OSL_ENSURE(false, "unknown index type");
						// default: skip index!
						break;
				}
			}
			else
			{
				eElement = XML_INDEX_TITLE;
			}
		}
		else
		{
			eElement = XML_SECTION;
		}

		if (XML_TOKEN_INVALID != eElement)
		{
			// any old attributes?
			GetExport().CheckAttrList();

			// element surrounded by whitespace
			GetExport().EndElement( XML_NAMESPACE_TEXT,	eElement, sal_True);
			GetExport().IgnorableWhitespace();
		}
		else
		{
			OSL_ENSURE(false, "Need element name!");
		}
	}
	// else: autostyles -> ignore
}

void XMLSectionExport::ExportIndexStart(
	const Reference<XDocumentIndex> & rIndex)
{
	// get PropertySet
	Reference<XPropertySet> xPropertySet(rIndex, UNO_QUERY);

	switch (MapSectionType(rIndex->getServiceName()))
	{
		case TEXT_SECTION_TYPE_TOC:
			ExportTableOfContentStart(xPropertySet);
			break;

		case TEXT_SECTION_TYPE_ILLUSTRATION:
			ExportIllustrationIndexStart(xPropertySet);
			break;

		case TEXT_SECTION_TYPE_ALPHABETICAL:
			ExportAlphabeticalIndexStart(xPropertySet);
			break;

		case TEXT_SECTION_TYPE_TABLE:
			ExportTableIndexStart(xPropertySet);
			break;

		case TEXT_SECTION_TYPE_OBJECT:
			ExportObjectIndexStart(xPropertySet);
			break;

		case TEXT_SECTION_TYPE_USER:
			ExportUserIndexStart(xPropertySet);
			break;

		case TEXT_SECTION_TYPE_BIBLIOGRAPHY:
			ExportBibliographyStart(xPropertySet);
			break;

		default:
			// skip index
			OSL_ENSURE(false, "unknown index type");
			break;
	}
}

void XMLSectionExport::ExportIndexHeaderStart(
	const Reference<XTextSection> & rSection)
{
	// export name, dammit!
	Reference<XNamed> xName(rSection, UNO_QUERY);
	GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName());

	// format already handled -> export only start element
	GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_TITLE, sal_True );
	GetExport().IgnorableWhitespace();
}


SvXMLEnumStringMapEntry __READONLY_DATA aIndexTypeMap[] =
{
	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.ContentIndex", TEXT_SECTION_TYPE_TOC ),
	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.DocumentIndex", TEXT_SECTION_TYPE_ALPHABETICAL ),
	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.TableIndex", TEXT_SECTION_TYPE_TABLE ),
	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.ObjectIndex", TEXT_SECTION_TYPE_OBJECT ),
	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.Bibliography", TEXT_SECTION_TYPE_BIBLIOGRAPHY ),
	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.UserIndex", TEXT_SECTION_TYPE_USER ),
	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.IllustrationsIndex", TEXT_SECTION_TYPE_ILLUSTRATION ),
    ENUM_STRING_MAP_END()
};

enum SectionTypeEnum XMLSectionExport::MapSectionType(
	const OUString& rServiceName)
{
	enum SectionTypeEnum eType = TEXT_SECTION_TYPE_UNKNOWN;

	sal_uInt16 nTmp;
	if (SvXMLUnitConverter::convertEnum(nTmp, rServiceName, aIndexTypeMap))
	{
		eType = (enum SectionTypeEnum)nTmp;
	}

	// TODO: index header section types, etc.

	return eType;
}

void XMLSectionExport::ExportRegularSectionStart(
	const Reference<XTextSection> & rSection)
{
	// style name already handled in ExportSectionStart(...)

	Reference<XNamed> xName(rSection, UNO_QUERY);
	GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName());

	// get XPropertySet for other values
	Reference<XPropertySet> xPropSet(rSection, UNO_QUERY);
	Any aAny;

	// condition and display
	aAny = xPropSet->getPropertyValue(sCondition);
	OUString sCond;
	aAny >>= sCond;
	enum XMLTokenEnum eDisplay = XML_TOKEN_INVALID;
	if (sCond.getLength() > 0)
	{
		OUString sQValue =
			GetExport().GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OOOW,
														 sCond, sal_False );
		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_CONDITION, sQValue);
		eDisplay = XML_CONDITION;

        // #97450# store hidden-status (of conditional sections only)
        aAny = xPropSet->getPropertyValue(sIsCurrentlyVisible);
        if (! *(sal_Bool*)aAny.getValue())
        {
            GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_IS_HIDDEN,
                                     XML_TRUE);
        }
	}
	else
	{
		eDisplay = XML_NONE;
	}
	aAny = xPropSet->getPropertyValue(sIsVisible);
	if (! *(sal_Bool*)aAny.getValue())
	{
		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_DISPLAY, eDisplay);
	}

	// protect + protection key
	aAny = xPropSet->getPropertyValue(sIsProtected);
	if (*(sal_Bool*)aAny.getValue())
	{
		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE);
	}
	Sequence<sal_Int8> aPassword;
	xPropSet->getPropertyValue(sProtectionKey) >>= aPassword;
	if (aPassword.getLength() > 0)
	{
		OUStringBuffer aBuffer;
		SvXMLUnitConverter::encodeBase64(aBuffer, aPassword);
		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTION_KEY,
								 aBuffer.makeStringAndClear());
	}

	// export element
	GetExport().IgnorableWhitespace();
	GetExport().StartElement( XML_NAMESPACE_TEXT, XML_SECTION, sal_True );

	// data source
	// unfortunately, we have to test all relevant strings for non-zero length
	aAny = xPropSet->getPropertyValue(sFileLink);
	SectionFileLink aFileLink;
	aAny >>= aFileLink;

	aAny = xPropSet->getPropertyValue(sLinkRegion);
	OUString sRegionName;
	aAny >>= sRegionName;

	if ( (aFileLink.FileURL.getLength() > 0) ||
		 (aFileLink.FilterName.getLength() > 0) ||
		 (sRegionName.getLength() > 0) )
	{
		if (aFileLink.FileURL.getLength() > 0)
		{
			GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF,
									 GetExport().GetRelativeReference( aFileLink.FileURL) );
		}

		if (aFileLink.FilterName.getLength() > 0)
		{
			GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_FILTER_NAME,
									 aFileLink.FilterName);
		}

		if (sRegionName.getLength() > 0)
		{
			GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_SECTION_NAME,
									 sRegionName);
		}

		SvXMLElementExport aElem(GetExport(),
								 XML_NAMESPACE_TEXT, XML_SECTION_SOURCE,
								 sal_True, sal_True);
	}
	else
	{
		// check for DDE first
		if (xPropSet->getPropertySetInfo()->hasPropertyByName(sDdeCommandFile))
		{
			// data source DDE
			// unfortunately, we have to test all relevant strings for
			// non-zero length
			aAny = xPropSet->getPropertyValue(sDdeCommandFile);
			OUString sApplication;
			aAny >>= sApplication;
			aAny = xPropSet->getPropertyValue(sDdeCommandType);
			OUString sTopic;
			aAny >>= sTopic;
			aAny = xPropSet->getPropertyValue(sDdeCommandElement);
			OUString sItem;
			aAny >>= sItem;

			if ( (sApplication.getLength() > 0) ||
				 (sTopic.getLength() > 0) ||
				 (sItem.getLength() > 0 )   )
			{
				GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
										 XML_DDE_APPLICATION, sApplication);
				GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_TOPIC,
										 sTopic);
				GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_ITEM,
										 sItem);

				aAny = xPropSet->getPropertyValue(sIsAutomaticUpdate);
				if (*(sal_Bool*)aAny.getValue())
				{
					GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
                                             XML_AUTOMATIC_UPDATE, XML_TRUE);
				}

				SvXMLElementExport aElem(GetExport(),
										 XML_NAMESPACE_OFFICE,
										 XML_DDE_SOURCE, sal_True, sal_True);
			}
			// else: no DDE data source
		}
		// else: no DDE on this system
	}
}

void XMLSectionExport::ExportTableOfContentStart(
	const Reference<XPropertySet> & rPropertySet)
{
	// export TOC element start
	ExportBaseIndexStart(XML_TABLE_OF_CONTENT, rPropertySet);

	// scope for table-of-content-source element
	{

		Any aAny;

		// TOC specific index source attributes:

        // outline-level: 1..10
        sal_Int16 nLevel = sal_Int16();
        if( rPropertySet->getPropertyValue(sLevel) >>= nLevel )
        {
            OUStringBuffer sBuffer;
            SvXMLUnitConverter::convertNumber(sBuffer, (sal_Int32)nLevel);
            GetExport().AddAttribute(XML_NAMESPACE_TEXT,
                                     XML_OUTLINE_LEVEL,
                                     sBuffer.makeStringAndClear());
        }

        // use outline level
        ExportBoolean(rPropertySet, sCreateFromOutline,
                          XML_USE_OUTLINE_LEVEL, sal_True);

		// use index marks
		ExportBoolean(rPropertySet, sCreateFromMarks,
					  XML_USE_INDEX_MARKS, sal_True);

		// use level styles
		ExportBoolean(rPropertySet, sCreateFromLevelParagraphStyles,
					  XML_USE_INDEX_SOURCE_STYLES, sal_False);

		ExportBaseIndexSource(TEXT_SECTION_TYPE_TOC, rPropertySet);
	}

	ExportBaseIndexBody(TEXT_SECTION_TYPE_TOC, rPropertySet);
}

void XMLSectionExport::ExportObjectIndexStart(
	const Reference<XPropertySet> & rPropertySet)
{
	// export index start
	ExportBaseIndexStart(XML_OBJECT_INDEX, rPropertySet);

	// scope for index source element
	{
		ExportBoolean(rPropertySet, sCreateFromOtherEmbeddedObjects,
					  XML_USE_OTHER_OBJECTS, sal_False);
		ExportBoolean(rPropertySet, sCreateFromStarCalc,
					  XML_USE_SPREADSHEET_OBJECTS, sal_False);
		ExportBoolean(rPropertySet, sCreateFromStarChart,
					  XML_USE_CHART_OBJECTS, sal_False);
		ExportBoolean(rPropertySet, sCreateFromStarDraw,
					  XML_USE_DRAW_OBJECTS, sal_False);
		ExportBoolean(rPropertySet, sCreateFromStarMath,
					  XML_USE_MATH_OBJECTS, sal_False);

		ExportBaseIndexSource(TEXT_SECTION_TYPE_OBJECT, rPropertySet);
	}

	ExportBaseIndexBody(TEXT_SECTION_TYPE_OBJECT, rPropertySet);
}

void XMLSectionExport::ExportIllustrationIndexStart(
	const Reference<XPropertySet> & rPropertySet)
{
	// export index start
	ExportBaseIndexStart(XML_ILLUSTRATION_INDEX, rPropertySet);

	// scope for index source element
	{
		// export common attributes for illustration and table indices
		ExportTableAndIllustrationIndexSourceAttributes(rPropertySet);

		ExportBaseIndexSource(TEXT_SECTION_TYPE_ILLUSTRATION, rPropertySet);
	}

	ExportBaseIndexBody(TEXT_SECTION_TYPE_ILLUSTRATION, rPropertySet);
}

void XMLSectionExport::ExportTableIndexStart(
	const Reference<XPropertySet> & rPropertySet)
{
	// export index start
	ExportBaseIndexStart(XML_TABLE_INDEX, rPropertySet);

	// scope for index source element
	{
		// export common attributes for illustration and table indices
		ExportTableAndIllustrationIndexSourceAttributes(rPropertySet);

		ExportBaseIndexSource(TEXT_SECTION_TYPE_TABLE, rPropertySet);
	}

	ExportBaseIndexBody(TEXT_SECTION_TYPE_TABLE, rPropertySet);
}

void XMLSectionExport::ExportAlphabeticalIndexStart(
	const Reference<XPropertySet> & rPropertySet)
{
	// export TOC element start
	ExportBaseIndexStart(XML_ALPHABETICAL_INDEX, rPropertySet);

	// scope for table-of-content-source element
	{

		// style name (if present)
		Any aAny;
		aAny = rPropertySet->getPropertyValue(sMainEntryCharacterStyleName);
		OUString sStyleName;
		aAny >>= sStyleName;
		if (sStyleName.getLength())
		{
			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
									 XML_MAIN_ENTRY_STYLE_NAME,
									 GetExport().EncodeStyleName( sStyleName ));
		}

		// other (boolean) attributes
		ExportBoolean(rPropertySet, sIsCaseSensitive, XML_IGNORE_CASE,
					  sal_False, sal_True);
		ExportBoolean(rPropertySet, sUseAlphabeticalSeparators,
					  XML_ALPHABETICAL_SEPARATORS, sal_False);
		ExportBoolean(rPropertySet, sUseCombinedEntries, XML_COMBINE_ENTRIES,
					  sal_True);
		ExportBoolean(rPropertySet, sUseDash, XML_COMBINE_ENTRIES_WITH_DASH,
					  sal_False);
		ExportBoolean(rPropertySet, sUseKeyAsEntry, XML_USE_KEYS_AS_ENTRIES,
					  sal_False);
		ExportBoolean(rPropertySet, sUsePP, XML_COMBINE_ENTRIES_WITH_PP,
					  sal_True);
		ExportBoolean(rPropertySet, sUseUpperCase, XML_CAPITALIZE_ENTRIES,
					  sal_False);
		ExportBoolean(rPropertySet, sIsCommaSeparated, XML_COMMA_SEPARATED,
					  sal_False);

        // sort algorithm
        aAny = rPropertySet->getPropertyValue(sSortAlgorithm);
        OUString sAlgorithm;
        aAny >>= sAlgorithm;
        if (sAlgorithm.getLength() > 0)
        {
            GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_SORT_ALGORITHM,
                                      sAlgorithm );
        }

        // locale
        aAny = rPropertySet->getPropertyValue(sLocale);
        Locale aLocale;
        aAny >>= aLocale;
        GetExport().AddAttribute(XML_NAMESPACE_FO, XML_LANGUAGE,
                                 aLocale.Language);
        GetExport().AddAttribute(XML_NAMESPACE_FO, XML_COUNTRY,
                                 aLocale.Country);

		ExportBaseIndexSource(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet);
	}

	ExportBaseIndexBody(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet);
}

void XMLSectionExport::ExportUserIndexStart(
	const Reference<XPropertySet> & rPropertySet)
{
	// export TOC element start
	ExportBaseIndexStart(XML_USER_INDEX, rPropertySet);

	// scope for table-of-content-source element
	{
		// bool attributes
		ExportBoolean(rPropertySet, sCreateFromEmbeddedObjects,
					  XML_USE_OBJECTS, sal_False);
		ExportBoolean(rPropertySet, sCreateFromGraphicObjects,
					  XML_USE_GRAPHICS, sal_False);
		ExportBoolean(rPropertySet, sCreateFromMarks,
					  XML_USE_INDEX_MARKS, sal_False);
		ExportBoolean(rPropertySet, sCreateFromTables,
					  XML_USE_TABLES, sal_False);
		ExportBoolean(rPropertySet, sCreateFromTextFrames,
					  XML_USE_FLOATING_FRAMES, sal_False);
		ExportBoolean(rPropertySet, sUseLevelFromSource,
					  XML_COPY_OUTLINE_LEVELS, sal_False);
		ExportBoolean(rPropertySet, sCreateFromLevelParagraphStyles,
					  XML_USE_INDEX_SOURCE_STYLES, sal_False);

        Any aAny = rPropertySet->getPropertyValue( sUserIndexName );
        OUString sIndexName;
        aAny >>= sIndexName;
        GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_INDEX_NAME,
                                 sIndexName);

		ExportBaseIndexSource(TEXT_SECTION_TYPE_USER, rPropertySet);
	}

	ExportBaseIndexBody(TEXT_SECTION_TYPE_USER, rPropertySet);
}

void XMLSectionExport::ExportBibliographyStart(
	const Reference<XPropertySet> & rPropertySet)
{
	// export TOC element start
	ExportBaseIndexStart(XML_BIBLIOGRAPHY, rPropertySet);

	// scope for table-of-content-source element
	{
		// No attributes. Fine.

		ExportBaseIndexSource(TEXT_SECTION_TYPE_BIBLIOGRAPHY, rPropertySet);
	}

	ExportBaseIndexBody(TEXT_SECTION_TYPE_BIBLIOGRAPHY, rPropertySet);
}


void XMLSectionExport::ExportBaseIndexStart(
    XMLTokenEnum eElement,
	const Reference<XPropertySet> & rPropertySet)
{
	// protect + protection key
	Any aAny = rPropertySet->getPropertyValue(sIsProtected);
	if (*(sal_Bool*)aAny.getValue())
	{
		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE);
	}

    // index name
    OUString sIndexName;
    rPropertySet->getPropertyValue(sName) >>= sIndexName;
    if ( sIndexName.getLength() > 0 )
    {
        GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, sIndexName);
    }

	// index  Element start
	GetExport().IgnorableWhitespace();
	GetExport().StartElement( XML_NAMESPACE_TEXT, eElement, sal_False );
}

static const XMLTokenEnum aTypeSourceElementNameMap[] =
{
	XML_TABLE_OF_CONTENT_SOURCE,		// TOC
	XML_TABLE_INDEX_SOURCE,			// table index
	XML_ILLUSTRATION_INDEX_SOURCE,		// illustration index
	XML_OBJECT_INDEX_SOURCE,			// object index
	XML_USER_INDEX_SOURCE,				// user index
	XML_ALPHABETICAL_INDEX_SOURCE,		// alphabetical index
	XML_BIBLIOGRAPHY_SOURCE			// bibliography
};

void XMLSectionExport::ExportBaseIndexSource(
	SectionTypeEnum eType,
	const Reference<XPropertySet> & rPropertySet)
{
	// check type
	OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
	OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");

	Any aAny;

	// common attributes; not supported by bibliography
	if (eType != TEXT_SECTION_TYPE_BIBLIOGRAPHY)
	{
		// document or chapter index?
		aAny = rPropertySet->getPropertyValue(sCreateFromChapter);
		if (*(sal_Bool*)aAny.getValue())
		{
			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
                                     XML_INDEX_SCOPE, XML_CHAPTER);
		}

		// tab-stops relative to margin?
		aAny = rPropertySet->getPropertyValue(sIsRelativeTabstops);
		if (! *(sal_Bool*)aAny.getValue())
		{
			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
                                     XML_RELATIVE_TAB_STOP_POSITION,
                                     XML_FALSE);
		}
    }

	// the index source element (all indices)
	SvXMLElementExport aElem(GetExport(),
							 XML_NAMESPACE_TEXT,
							 GetXMLToken(
                                 aTypeSourceElementNameMap[
                                    eType - TEXT_SECTION_TYPE_TOC]),
							 sal_True, sal_True);

	// scope for title template (all indices)
	{
		// header style name
		aAny = rPropertySet->getPropertyValue(sParaStyleHeading);
		OUString sStyleName;
		aAny >>= sStyleName;
		GetExport().AddAttribute(XML_NAMESPACE_TEXT,
								 XML_STYLE_NAME,
								 GetExport().EncodeStyleName( sStyleName ));

		// title template
		SvXMLElementExport aHeaderTemplate(GetExport(),
										   XML_NAMESPACE_TEXT,
										   XML_INDEX_TITLE_TEMPLATE,
										   sal_True, sal_False);

		// title as element content
		aAny = rPropertySet->getPropertyValue(sTitle);
		OUString sTitleString;
		aAny >>= sTitleString;
		GetExport().Characters(sTitleString);
	}

	// export level templates (all indices)
	aAny = rPropertySet->getPropertyValue(sLevelFormat);
	Reference<XIndexReplace> xLevelTemplates;
	aAny >>= xLevelTemplates;

	// iterate over level formats;
	// skip element 0 (empty template for title)
	sal_Int32 nLevelCount = xLevelTemplates->getCount();
	for(sal_Int32 i = 1; i<nLevelCount; i++)
	{
		// get sequence
		Sequence<PropertyValues> aTemplateSequence;
		aAny = xLevelTemplates->getByIndex(i);
		aAny >>= aTemplateSequence;

		// export the sequence (abort export if an error occurred; #91214#)
		sal_Bool bResult =
            ExportIndexTemplate(eType, i, rPropertySet, aTemplateSequence);
        if ( !bResult )
            break;
	}

	// only TOC and user index:
	// styles from which to build the index (LevelParagraphStyles)
	if ( (TEXT_SECTION_TYPE_TOC == eType) ||
		 (TEXT_SECTION_TYPE_USER == eType)   )
	{
		aAny = rPropertySet->getPropertyValue(sLevelParagraphStyles);
		Reference<XIndexReplace> xLevelParagraphStyles;
		aAny >>= xLevelParagraphStyles;
		ExportLevelParagraphStyles(xLevelParagraphStyles);
	}
}


void XMLSectionExport::ExportBaseIndexBody(
	SectionTypeEnum
    #if OSL_DEBUG_LEVEL > 0
    eType
    #endif
    ,
	const Reference<XPropertySet> &)
{
	// type not used; checked anyway.
	OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
	OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");

	// export start only

	// any old attributes?
	GetExport().CheckAttrList();

	// start surrounded by whitespace
	GetExport().IgnorableWhitespace();
	GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_BODY, sal_True );
}

void XMLSectionExport::ExportTableAndIllustrationIndexSourceAttributes(
	const Reference<XPropertySet> & rPropertySet)
{
	// use caption
	Any aAny = rPropertySet->getPropertyValue(sCreateFromLabels);
	if (! *(sal_Bool*)aAny.getValue())
	{
		GetExport().AddAttribute(XML_NAMESPACE_TEXT,
                                 XML_USE_CAPTION, XML_FALSE);
	}

	// sequence name
	aAny = rPropertySet->getPropertyValue(sLabelCategory);
	OUString sSequenceName;
	aAny >>= sSequenceName;
	GetExport().AddAttribute(XML_NAMESPACE_TEXT,
							 XML_CAPTION_SEQUENCE_NAME,
							 sSequenceName);

	// caption format
	aAny = rPropertySet->getPropertyValue(sLabelDisplayType);
	sal_Int16 nType = 0;
	aAny >>= nType;
	GetExport().AddAttribute(XML_NAMESPACE_TEXT,
                             XML_CAPTION_SEQUENCE_FORMAT,
                             XMLTextFieldExport::MapReferenceType(nType));
}


// map index of LevelFormats to attribute value;
// level 0 is always the header
static const XMLTokenEnum aLevelNameTOCMap[] =
	{ XML_TOKEN_INVALID, XML_1, XML_2, XML_3, XML_4, XML_5, XML_6, XML_7,
		  XML_8, XML_9, XML_10, XML_TOKEN_INVALID };
static const XMLTokenEnum aLevelNameTableMap[] =
	{ XML_TOKEN_INVALID, XML__EMPTY, XML_TOKEN_INVALID };
static const XMLTokenEnum aLevelNameAlphaMap[] =
	{ XML_TOKEN_INVALID, XML_SEPARATOR, XML_1, XML_2, XML_3, XML_TOKEN_INVALID };
static const XMLTokenEnum aLevelNameBibliographyMap[] =
	{ XML_TOKEN_INVALID, XML_ARTICLE, XML_BOOK, XML_BOOKLET, XML_CONFERENCE,
		  XML_CUSTOM1, XML_CUSTOM2, XML_CUSTOM3, XML_CUSTOM4,
		  XML_CUSTOM5, XML_EMAIL, XML_INBOOK, XML_INCOLLECTION,
		  XML_INPROCEEDINGS, XML_JOURNAL,
		  XML_MANUAL, XML_MASTERSTHESIS, XML_MISC, XML_PHDTHESIS,
		  XML_PROCEEDINGS, XML_TECHREPORT, XML_UNPUBLISHED, XML_WWW,
		  XML_TOKEN_INVALID };

static const XMLTokenEnum* aTypeLevelNameMap[] =
{
	aLevelNameTOCMap,			// TOC
	aLevelNameTableMap,			// table index
	aLevelNameTableMap,			// illustration index
	aLevelNameTableMap,			// object index
	aLevelNameTOCMap,			// user index
	aLevelNameAlphaMap,			// alphabetical index
	aLevelNameBibliographyMap	// bibliography
};

static const sal_Char* aLevelStylePropNameTOCMap[] =
	{ NULL, "ParaStyleLevel1", "ParaStyleLevel2", "ParaStyleLevel3",
		  "ParaStyleLevel4", "ParaStyleLevel5", "ParaStyleLevel6",
		  "ParaStyleLevel7", "ParaStyleLevel8", "ParaStyleLevel9",
		  "ParaStyleLevel10", NULL };
static const sal_Char* aLevelStylePropNameTableMap[] =
	{ NULL, "ParaStyleLevel1", NULL };
static const sal_Char* aLevelStylePropNameAlphaMap[] =
	{ NULL, "ParaStyleSeparator", "ParaStyleLevel1", "ParaStyleLevel2",
		  "ParaStyleLevel3", NULL };
static const sal_Char* aLevelStylePropNameBibliographyMap[] =
		  // TODO: replace with real property names, when available
	{ NULL, "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
		  "ParaStyleLevel1",
		  NULL };

static const sal_Char** aTypeLevelStylePropNameMap[] =
{
	aLevelStylePropNameTOCMap,			// TOC
	aLevelStylePropNameTableMap,		// table index
	aLevelStylePropNameTableMap,		// illustration index
	aLevelStylePropNameTableMap,		// object index
	aLevelStylePropNameTOCMap,			// user index
	aLevelStylePropNameAlphaMap,		// alphabetical index
	aLevelStylePropNameBibliographyMap	// bibliography
};

static const XMLTokenEnum aTypeLevelAttrMap[] =
{
	XML_OUTLINE_LEVEL,		// TOC
	XML_TOKEN_INVALID,		// table index
	XML_TOKEN_INVALID,		// illustration index
	XML_TOKEN_INVALID,		// object index
	XML_OUTLINE_LEVEL,		// user index
	XML_OUTLINE_LEVEL,		// alphabetical index
	XML_BIBLIOGRAPHY_TYPE	// bibliography
};

static const XMLTokenEnum aTypeElementNameMap[] =
{
	XML_TABLE_OF_CONTENT_ENTRY_TEMPLATE,	// TOC
	XML_TABLE_INDEX_ENTRY_TEMPLATE,		// table index
	XML_ILLUSTRATION_INDEX_ENTRY_TEMPLATE,	// illustration index
	XML_OBJECT_INDEX_ENTRY_TEMPLATE,		// object index
	XML_USER_INDEX_ENTRY_TEMPLATE,			// user index
	XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE,	// alphabetical index
	XML_BIBLIOGRAPHY_ENTRY_TEMPLATE		// bibliography
};


sal_Bool XMLSectionExport::ExportIndexTemplate(
	SectionTypeEnum eType,
	sal_Int32 nOutlineLevel,
	const Reference<XPropertySet> & rPropertySet,
	Sequence<Sequence<PropertyValue> > & rValues)
{
	OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
	OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");
	OSL_ENSURE(nOutlineLevel >= 0, "illegal outline level");

	if ( (eType >= TEXT_SECTION_TYPE_TOC) &&
		 (eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY) &&
		 (nOutlineLevel >= 0) )
	{
		// get level name and level attribute name from aLevelNameMap;
		const XMLTokenEnum eLevelAttrName(
			aTypeLevelAttrMap[eType-TEXT_SECTION_TYPE_TOC]);
		const XMLTokenEnum eLevelName(
			aTypeLevelNameMap[eType-TEXT_SECTION_TYPE_TOC][nOutlineLevel]);

        // #92124#: some old documents may be broken, then they have
        // too many template levels; we need to recognize this and
        // export only as many as is legal for the respective index
        // type. To do this, we simply return an error flag, which
        // will then abort further template level exports.
		OSL_ENSURE(XML_TOKEN_INVALID != eLevelName, "can't find level name");
        if ( XML_TOKEN_INVALID == eLevelName )
        {
            // output level not found? Then end of templates! #91214#
            return sal_False;
        }

		// output level name
		if ((XML_TOKEN_INVALID != eLevelName) && (XML_TOKEN_INVALID != eLevelAttrName))
		{
			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
										  GetXMLToken(eLevelAttrName),
										  GetXMLToken(eLevelName));
		}

		// paragraph level style name
		const sal_Char* pPropName( 
			aTypeLevelStylePropNameMap[eType-TEXT_SECTION_TYPE_TOC][nOutlineLevel]);
		OSL_ENSURE(NULL != pPropName, "can't find property name");
		if (NULL != pPropName)
		{
			Any aAny = rPropertySet->getPropertyValue(
				OUString::createFromAscii(pPropName));
			OUString sParaStyleName;
			aAny >>= sParaStyleName;
			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
									 XML_STYLE_NAME,
									 GetExport().EncodeStyleName( sParaStyleName ));
		}

		// template element
		const XMLTokenEnum eElementName(
			aTypeElementNameMap[eType - TEXT_SECTION_TYPE_TOC]);
		SvXMLElementExport aLevelTemplate(GetExport(),
										  XML_NAMESPACE_TEXT,
										  GetXMLToken(eElementName),
										  sal_True, sal_True);

		// export sequence
		sal_Int32 nTemplateCount = rValues.getLength();
		for(sal_Int32 nTemplateNo = 0;
			nTemplateNo < nTemplateCount;
			nTemplateNo++)
		{
			ExportIndexTemplateElement(
                eType,  //i90246
				rValues[nTemplateNo]);
		}
	}

    return sal_True;
}


enum TemplateTypeEnum
{
	TOK_TTYPE_ENTRY_NUMBER,
	TOK_TTYPE_ENTRY_TEXT,
	TOK_TTYPE_TAB_STOP,
	TOK_TTYPE_TEXT,
	TOK_TTYPE_PAGE_NUMBER,
	TOK_TTYPE_CHAPTER_INFO,
	TOK_TTYPE_HYPERLINK_START,
	TOK_TTYPE_HYPERLINK_END,
	TOK_TTYPE_BIBLIOGRAPHY,
	TOK_TTYPE_INVALID
};

enum TemplateParamEnum
{
	TOK_TPARAM_TOKEN_TYPE,
	TOK_TPARAM_CHAR_STYLE,
	TOK_TPARAM_TAB_RIGHT_ALIGNED,
	TOK_TPARAM_TAB_POSITION,
	TOK_TPARAM_TAB_WITH_TAB, // #i21237#
	TOK_TPARAM_TAB_FILL_CHAR,
	TOK_TPARAM_TEXT,
	TOK_TPARAM_CHAPTER_FORMAT,
	TOK_TPARAM_CHAPTER_LEVEL,//i53420
	TOK_TPARAM_BIBLIOGRAPHY_DATA
};

SvXMLEnumStringMapEntry __READONLY_DATA aTemplateTypeMap[] =
{
	ENUM_STRING_MAP_ENTRY( "TokenEntryNumber",  TOK_TTYPE_ENTRY_NUMBER ),
    ENUM_STRING_MAP_ENTRY( "TokenEntryText",    TOK_TTYPE_ENTRY_TEXT ),
    ENUM_STRING_MAP_ENTRY( "TokenTabStop",      TOK_TTYPE_TAB_STOP ),
    ENUM_STRING_MAP_ENTRY( "TokenText",         TOK_TTYPE_TEXT ),
	ENUM_STRING_MAP_ENTRY( "TokenPageNumber",   TOK_TTYPE_PAGE_NUMBER ),
	ENUM_STRING_MAP_ENTRY( "TokenChapterInfo",  TOK_TTYPE_CHAPTER_INFO ),
    ENUM_STRING_MAP_ENTRY( "TokenHyperlinkStart", TOK_TTYPE_HYPERLINK_START ),
	ENUM_STRING_MAP_ENTRY( "TokenHyperlinkEnd",	TOK_TTYPE_HYPERLINK_END ),
	ENUM_STRING_MAP_ENTRY( "TokenBibliographyDataField", TOK_TTYPE_BIBLIOGRAPHY ),
    ENUM_STRING_MAP_END()
};

SvXMLEnumStringMapEntry __READONLY_DATA aTemplateParamMap[] =
{
	ENUM_STRING_MAP_ENTRY( "TokenType",             TOK_TPARAM_TOKEN_TYPE ),
	ENUM_STRING_MAP_ENTRY( "CharacterStyleName",    TOK_TPARAM_CHAR_STYLE ),
	ENUM_STRING_MAP_ENTRY( "TabStopRightAligned",   TOK_TPARAM_TAB_RIGHT_ALIGNED ),
	ENUM_STRING_MAP_ENTRY( "TabStopPosition",       TOK_TPARAM_TAB_POSITION ),
	ENUM_STRING_MAP_ENTRY( "TabStopFillCharacter",  TOK_TPARAM_TAB_FILL_CHAR ),
    // #i21237#
	ENUM_STRING_MAP_ENTRY( "WithTab",               TOK_TPARAM_TAB_WITH_TAB ),
	ENUM_STRING_MAP_ENTRY( "Text",                  TOK_TPARAM_TEXT ),
	ENUM_STRING_MAP_ENTRY( "ChapterFormat",         TOK_TPARAM_CHAPTER_FORMAT ),
	ENUM_STRING_MAP_ENTRY( "ChapterLevel",          TOK_TPARAM_CHAPTER_LEVEL ),//i53420
	ENUM_STRING_MAP_ENTRY( "BibliographyDataField", TOK_TPARAM_BIBLIOGRAPHY_DATA ),
    ENUM_STRING_MAP_END()
};

SvXMLEnumMapEntry __READONLY_DATA aBibliographyDataFieldMap[] =
{
	{ XML_ADDRESS,				BibliographyDataField::ADDRESS },
	{ XML_ANNOTE,				BibliographyDataField::ANNOTE },
	{ XML_AUTHOR,				BibliographyDataField::AUTHOR },
	{ XML_BIBLIOGRAPHY_TYPE,    BibliographyDataField::BIBILIOGRAPHIC_TYPE },
	{ XML_BOOKTITLE,			BibliographyDataField::BOOKTITLE },
	{ XML_CHAPTER,				BibliographyDataField::CHAPTER },
	{ XML_CUSTOM1,				BibliographyDataField::CUSTOM1 },
	{ XML_CUSTOM2,				BibliographyDataField::CUSTOM2 },
	{ XML_CUSTOM3,				BibliographyDataField::CUSTOM3 },
	{ XML_CUSTOM4,				BibliographyDataField::CUSTOM4 },
	{ XML_CUSTOM5,				BibliographyDataField::CUSTOM5 },
	{ XML_EDITION,				BibliographyDataField::EDITION },
	{ XML_EDITOR,				BibliographyDataField::EDITOR },
	{ XML_HOWPUBLISHED,		    BibliographyDataField::HOWPUBLISHED },
	{ XML_IDENTIFIER,			BibliographyDataField::IDENTIFIER },
	{ XML_INSTITUTION,			BibliographyDataField::INSTITUTION },
	{ XML_ISBN,				    BibliographyDataField::ISBN },
	{ XML_JOURNAL,				BibliographyDataField::JOURNAL },
	{ XML_MONTH,				BibliographyDataField::MONTH },
	{ XML_NOTE,				    BibliographyDataField::NOTE },
	{ XML_NUMBER,				BibliographyDataField::NUMBER },
	{ XML_ORGANIZATIONS,		BibliographyDataField::ORGANIZATIONS },
	{ XML_PAGES,				BibliographyDataField::PAGES },
	{ XML_PUBLISHER,			BibliographyDataField::PUBLISHER },
	{ XML_REPORT_TYPE,			BibliographyDataField::REPORT_TYPE },
	{ XML_SCHOOL,				BibliographyDataField::SCHOOL },
    { XML_SERIES,				BibliographyDataField::SERIES },
	{ XML_TITLE,				BibliographyDataField::TITLE },
	{ XML_URL,					BibliographyDataField::URL },
	{ XML_VOLUME,				BibliographyDataField::VOLUME },
	{ XML_YEAR,				    BibliographyDataField::YEAR },
	{ XML_TOKEN_INVALID, 0 }
};

void XMLSectionExport::ExportIndexTemplateElement(
    SectionTypeEnum eType,  //i90246
    Sequence<PropertyValue> & rValues)
{
	// variables for template values

	// char style
	OUString sCharStyle;
	sal_Bool bCharStyleOK = sal_False;

	// text
	OUString sText;
	sal_Bool bTextOK = sal_False;

	// tab position
	sal_Bool bRightAligned = sal_False;
	sal_Bool bRightAlignedOK = sal_False;

	// tab position
	sal_Int32 nTabPosition = 0;
	sal_Bool bTabPositionOK = sal_False;

	// fill character
	OUString sFillChar;
	sal_Bool bFillCharOK = sal_False;

	// chapter format
	sal_Int16 nChapterFormat = 0;
	sal_Bool bChapterFormatOK = sal_False;

    // outline max level
	sal_Int16 nLevel = 0;
	sal_Bool bLevelOK = sal_False;

	// Bibliography Data
	sal_Int16 nBibliographyData = 0;
	sal_Bool bBibliographyDataOK = sal_False;

    // With Tab Stop #i21237#
    sal_Bool bWithTabStop = sal_False;
    sal_Bool bWithTabStopOK = sal_False;

    //i90246, the ODF version being written to is:
    const SvtSaveOptions::ODFDefaultVersion aODFVersion = rExport.getDefaultVersion();
    //the above version cannot be used for old OOo (OOo 1.0) formats!

    // token type
	enum TemplateTypeEnum nTokenType = TOK_TTYPE_INVALID;

	sal_Int32 nCount = rValues.getLength();
	for(sal_Int32 i = 0; i<nCount; i++)
	{
		sal_uInt16 nToken;
		if ( SvXMLUnitConverter::convertEnum( nToken, rValues[i].Name,
											  aTemplateParamMap ) )
		{
			// Only use direct and default values.
			// Wrong. no property states, so ignore.
			// if ( (beans::PropertyState_DIRECT_VALUE == rValues[i].State) ||
			//      (beans::PropertyState_DEFAULT_VALUE == rValues[i].State)  )

			switch (nToken)
			{
				case TOK_TPARAM_TOKEN_TYPE:
				{
					sal_uInt16 nTmp;
					OUString sVal;
					rValues[i].Value >>= sVal;
					if (SvXMLUnitConverter::convertEnum( nTmp, sVal,
														 aTemplateTypeMap))
					{
						nTokenType = (enum TemplateTypeEnum)nTmp;
					}
					break;
				}

				case TOK_TPARAM_CHAR_STYLE:
					// only valid, if not empty
					rValues[i].Value >>= sCharStyle;
					bCharStyleOK = sCharStyle.getLength() > 0;
					break;

				case TOK_TPARAM_TEXT:
					rValues[i].Value >>= sText;
					bTextOK = sal_True;
					break;

				case TOK_TPARAM_TAB_RIGHT_ALIGNED:
					bRightAligned =
						*(sal_Bool *)rValues[i].Value.getValue();
					bRightAlignedOK = sal_True;
					break;

				case TOK_TPARAM_TAB_POSITION:
					rValues[i].Value >>= nTabPosition;
					bTabPositionOK = sal_True;
					break;

                // #i21237#
                case TOK_TPARAM_TAB_WITH_TAB:
					bWithTabStop = *(sal_Bool *)rValues[i].Value.getValue();
					bWithTabStopOK = sal_True;
					break;

				case TOK_TPARAM_TAB_FILL_CHAR:
					rValues[i].Value >>= sFillChar;
					bFillCharOK = sal_True;
					break;

				case TOK_TPARAM_CHAPTER_FORMAT:
					rValues[i].Value >>= nChapterFormat;
					bChapterFormatOK = sal_True;
					break;
//---> i53420
                case TOK_TPARAM_CHAPTER_LEVEL:
                    rValues[i].Value >>= nLevel;
                    bLevelOK = sal_True;
                    break;
//<---
				case TOK_TPARAM_BIBLIOGRAPHY_DATA:
					rValues[i].Value >>= nBibliographyData;
					bBibliographyDataOK = sal_True;
					break;
			}
		}
	}

	// convert type to token (and check validity) ...
	XMLTokenEnum eElement(XML_TOKEN_INVALID);
	switch(nTokenType)
	{
		case TOK_TTYPE_ENTRY_TEXT:
			eElement = XML_INDEX_ENTRY_TEXT;
			break;
		case TOK_TTYPE_TAB_STOP:
			// test validity
			if ( bRightAligned || bTabPositionOK || bFillCharOK )
            {
				eElement = XML_INDEX_ENTRY_TAB_STOP;
            }
			break;
		case TOK_TTYPE_TEXT:
			// test validity
			if (bTextOK)
            {
                eElement = XML_INDEX_ENTRY_SPAN;
            }
			break;
		case TOK_TTYPE_PAGE_NUMBER:
			eElement = XML_INDEX_ENTRY_PAGE_NUMBER;
			break;
		case TOK_TTYPE_CHAPTER_INFO:	// keyword index
			eElement = XML_INDEX_ENTRY_CHAPTER;
			break;
		case TOK_TTYPE_ENTRY_NUMBER:	// table of content
			eElement = XML_INDEX_ENTRY_CHAPTER;
			break;
		case TOK_TTYPE_HYPERLINK_START:
			eElement = XML_INDEX_ENTRY_LINK_START;
			break;
		case TOK_TTYPE_HYPERLINK_END:
			eElement = XML_INDEX_ENTRY_LINK_END;
			break;
		case TOK_TTYPE_BIBLIOGRAPHY:
			if (bBibliographyDataOK)
            {
				eElement = XML_INDEX_ENTRY_BIBLIOGRAPHY;
            }
			break;
		default:
			; // unknown/unimplemented template
			break;
	}

    //--->i90246
    //check the ODF version being exported
    if( aODFVersion == SvtSaveOptions::ODFVER_011
        || aODFVersion == SvtSaveOptions::ODFVER_010)
    {
        bLevelOK = sal_False;
        if (TOK_TTYPE_CHAPTER_INFO == nTokenType)
        {
            //if we are emitting for ODF 1.1 or 1.0, this information can be used for alphabetical index only
            //it's not permitted in other indexes
            if (eType != TEXT_SECTION_TYPE_ALPHABETICAL)
            {
                eElement = XML_TOKEN_INVALID; //not permitted, invalidate the element
            }
            else //maps format for 1.1 & 1.0
            {
                // a few word here: OOo up to 2.4 uses the field chapter info in Alphabetical index
                // in a way different from the ODF 1.1/1.0 specification:
                //
                // ODF1.1/1.0         OOo display in chapter info                       ODF1.2
                //                    (used in alphabetical index only
                //
                // number             chapter number without pre/postfix                plain-number
                // number-and-name    chapter number without pre/postfix plus title     plain-number-and-name
                //
                // with issue i89791 the reading of ODF 1.1 and 1.0 was corrected
                // this one corrects the writing back from ODF 1.2 to ODF 1.1/1.0
                // unfortunately if there is another application which interprets correctly ODF1.1/1.0,
                // the resulting alphabetical index will be rendered wrong by OOo 2.4 version
                //
                switch( nChapterFormat )
                {
                case ChapterFormat::DIGIT:
                    nChapterFormat = ChapterFormat::NUMBER;
                    break;
                case ChapterFormat::NO_PREFIX_SUFFIX:
                    nChapterFormat = ChapterFormat::NAME_NUMBER;
                    break;
                }
            }
        }
        else if (TOK_TTYPE_ENTRY_NUMBER == nTokenType)
        {
            //in case of ODF 1.1 or 1.0 the only allowed number format is "number"
            //so, force it...
            // The only expected 'foreign' nChapterFormat is
            // ' ChapterFormat::DIGIT', forced to 'none, since the
            // 'value allowed in ODF 1.1 and 1.0 is 'number' the default
            // this can be obtained by simply disabling the chapter format
            bChapterFormatOK = sal_False;
        }
    }
//<---

    // ... and write Element
	if (eElement != XML_TOKEN_INVALID)
	{
		// character style (for most templates)
		if (bCharStyleOK)
		{
			switch (nTokenType)
			{
				case TOK_TTYPE_ENTRY_TEXT:
				case TOK_TTYPE_TEXT:
				case TOK_TTYPE_PAGE_NUMBER:
				case TOK_TTYPE_ENTRY_NUMBER:
				case TOK_TTYPE_HYPERLINK_START:
				case TOK_TTYPE_HYPERLINK_END:
				case TOK_TTYPE_BIBLIOGRAPHY:
                case TOK_TTYPE_CHAPTER_INFO:
                case TOK_TTYPE_TAB_STOP:
					GetExport().AddAttribute(XML_NAMESPACE_TEXT,
											 XML_STYLE_NAME,
								 GetExport().EncodeStyleName( sCharStyle) );
					break;
				default:
					; // nothing: no character style
					break;
			}
		}

		// tab properties
		if (TOK_TTYPE_TAB_STOP == nTokenType)
		{
			// tab type
			GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_TYPE,
                                     bRightAligned ? XML_RIGHT : XML_LEFT);

			if (bTabPositionOK && (! bRightAligned))
			{
				// position for left tabs (convert to measure)
				OUStringBuffer sBuf;
				GetExport().GetMM100UnitConverter().convertMeasure(sBuf,
																 nTabPosition);
				GetExport().AddAttribute(XML_NAMESPACE_STYLE,
										 XML_POSITION,
										 sBuf.makeStringAndClear());
			}

			// fill char ("leader char")
			if (bFillCharOK && (sFillChar.getLength() > 0))
			{
				GetExport().AddAttribute(XML_NAMESPACE_STYLE,
										 XML_LEADER_CHAR, sFillChar);
			}

            // #i21237#
            if (bWithTabStopOK && ! bWithTabStop)
            {
               	GetExport().AddAttribute(XML_NAMESPACE_STYLE,
										 XML_WITH_TAB,
										 XML_FALSE);
            }
		}

		// bibliography data
		if (TOK_TTYPE_BIBLIOGRAPHY == nTokenType)
		{
			OSL_ENSURE(bBibliographyDataOK, "need bibl data");
			OUStringBuffer sBuf;
			if (SvXMLUnitConverter::convertEnum( sBuf, nBibliographyData,
												 aBibliographyDataFieldMap ) )
			{
				GetExport().AddAttribute(XML_NAMESPACE_TEXT,
										 XML_BIBLIOGRAPHY_DATA_FIELD,
										 sBuf.makeStringAndClear());
			}
		}

		// chapter info
		if (TOK_TTYPE_CHAPTER_INFO == nTokenType)
		{
			OSL_ENSURE(bChapterFormatOK, "need chapter info");
			GetExport().AddAttribute(
				XML_NAMESPACE_TEXT, XML_DISPLAY,
				XMLTextFieldExport::MapChapterDisplayFormat(nChapterFormat));
//---> i53420
            if (bLevelOK)
                GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
                                     OUString::valueOf((sal_Int32)nLevel));
//<---
		}

//--->i53420
        if (TOK_TTYPE_ENTRY_NUMBER == nTokenType)
        {
            if (bChapterFormatOK)
                GetExport().AddAttribute(
                    XML_NAMESPACE_TEXT, XML_DISPLAY,
                    XMLTextFieldExport::MapChapterDisplayFormat(nChapterFormat));

            if (bLevelOK)
                GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
                                     OUString::valueOf((sal_Int32)nLevel));
        }
//<---
		// export template
		SvXMLElementExport aTemplateElement(GetExport(), XML_NAMESPACE_TEXT,
											GetXMLToken(eElement),
                                            sal_True, sal_False)
            ;

		// entry text or span element: write text
		if (TOK_TTYPE_TEXT == nTokenType)
		{
			GetExport().Characters(sText);
		}
	}
}

void XMLSectionExport::ExportLevelParagraphStyles(
	Reference<XIndexReplace> & xLevelParagraphStyles)
{
	// iterate over levels
	sal_Int32 nPLevelCount = xLevelParagraphStyles->getCount();
	for(sal_Int32 nLevel = 0; nLevel < nPLevelCount; nLevel++)
	{
		Any aAny = xLevelParagraphStyles->getByIndex(nLevel);
		Sequence<OUString> aStyleNames;
		aAny >>= aStyleNames;

		// export only if at least one style is contained
		sal_Int32 nNamesCount = aStyleNames.getLength();
		if (nNamesCount > 0)
		{
			// level attribute; we count 1..10; API 0..9
			OUStringBuffer sBuf;
			sal_Int32 nLevelPlusOne = nLevel + 1;
			SvXMLUnitConverter::convertNumber(sBuf, nLevelPlusOne);
			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
									 XML_OUTLINE_LEVEL,
									 sBuf.makeStringAndClear());

			// source styles element
			SvXMLElementExport aParaStyles(GetExport(),
										   XML_NAMESPACE_TEXT,
										   XML_INDEX_SOURCE_STYLES,
										   sal_True, sal_True);

			// iterate over styles in this level
			for(sal_Int32 nName = 0; nName < nNamesCount; nName++)
			{
				// stylename attribute
				GetExport().AddAttribute(XML_NAMESPACE_TEXT,
										 XML_STYLE_NAME,
							 GetExport().EncodeStyleName( aStyleNames[nName]) );

				// element
				SvXMLElementExport aParaStyle(GetExport(),
											  XML_NAMESPACE_TEXT,
											  XML_INDEX_SOURCE_STYLE,
											  sal_True, sal_False);
			}
		}
	}
}

void XMLSectionExport::ExportBoolean(
	const Reference<XPropertySet> & rPropSet,
	const OUString& sPropertyName,
	enum XMLTokenEnum eAttributeName,
	sal_Bool bDefault,
	sal_Bool bInvert)
{
	OSL_ENSURE(eAttributeName != XML_TOKEN_INVALID, "Need attribute name");

	Any aAny = rPropSet->getPropertyValue(sPropertyName);
	sal_Bool bTmp = *(sal_Bool*)aAny.getValue();

	// value = value ^ bInvert
	// omit if value == default
	// negate forces sal_Bool to 0/1, making them comparable
	if ((!(bTmp ^ bInvert)) != (!bDefault))
	{
		// export non-default value (since default is omitted)
		GetExport().AddAttribute(XML_NAMESPACE_TEXT,
                                 eAttributeName,
                                 bDefault ? XML_FALSE : XML_TRUE);
	}
}

const sal_Char sAPI_FieldMaster_Bibliography[] =
								"com.sun.star.text.FieldMaster.Bibliography";
const sal_Char sAPI_SortKey[] = "SortKey";
const sal_Char sAPI_IsSortAscending[] = "IsSortAscending";

void XMLSectionExport::ExportBibliographyConfiguration(SvXMLExport& rExport)
{
	// first: get field master (via text field supplier)
	Reference<XTextFieldsSupplier> xTextFieldsSupp( rExport.GetModel(),
                                                    UNO_QUERY );
    if ( xTextFieldsSupp.is() )
    {
		const OUString sFieldMaster_Bibliography(
			RTL_CONSTASCII_USTRINGPARAM(sAPI_FieldMaster_Bibliography));

        // get bibliography field master
        Reference<XNameAccess> xMasters =
            xTextFieldsSupp->getTextFieldMasters();
        if ( xMasters->hasByName(sFieldMaster_Bibliography) )
        {
            Any aAny =
                xMasters->getByName(sFieldMaster_Bibliography);
            Reference<XPropertySet> xPropSet;
            aAny >>= xPropSet;

            OSL_ENSURE( xPropSet.is(), "field master must have XPropSet" );

            const OUString sBracketBefore(
                RTL_CONSTASCII_USTRINGPARAM("BracketBefore"));
            const OUString sBracketAfter(
                RTL_CONSTASCII_USTRINGPARAM("BracketAfter"));
            const OUString sIsNumberEntries(
                RTL_CONSTASCII_USTRINGPARAM("IsNumberEntries"));
            const OUString sIsSortByPosition(
                RTL_CONSTASCII_USTRINGPARAM("IsSortByPosition"));
            const OUString sSortKeys(
                RTL_CONSTASCII_USTRINGPARAM("SortKeys"));
            const OUString sSortAlgorithm(
                RTL_CONSTASCII_USTRINGPARAM("SortAlgorithm"));
            const OUString sLocale(
                RTL_CONSTASCII_USTRINGPARAM("Locale"));

			OUString sTmp;

			aAny = xPropSet->getPropertyValue(sBracketBefore);
			aAny >>= sTmp;
			rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_PREFIX, sTmp);

			aAny = xPropSet->getPropertyValue(sBracketAfter);
			aAny >>= sTmp;
			rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_SUFFIX, sTmp);

			aAny = xPropSet->getPropertyValue(sIsNumberEntries);
			if (*(sal_Bool*)aAny.getValue())
			{
				rExport.AddAttribute(XML_NAMESPACE_TEXT,
                                     XML_NUMBERED_ENTRIES, XML_TRUE);
			}

			aAny = xPropSet->getPropertyValue(sIsSortByPosition);
			if (! *(sal_Bool*)aAny.getValue())
			{
				rExport.AddAttribute(XML_NAMESPACE_TEXT,
                                     XML_SORT_BY_POSITION, XML_FALSE);
			}

            // sort algorithm
            aAny = xPropSet->getPropertyValue(sSortAlgorithm);
            OUString sAlgorithm;
            aAny >>= sAlgorithm;
            if( sAlgorithm.getLength() > 0 )
            {
                rExport.AddAttribute( XML_NAMESPACE_TEXT,
                                      XML_SORT_ALGORITHM, sAlgorithm );
            }

            // locale
            aAny = xPropSet->getPropertyValue(sLocale);
            Locale aLocale;
            aAny >>= aLocale;
            rExport.AddAttribute(XML_NAMESPACE_FO, XML_LANGUAGE,
                                     aLocale.Language);
            rExport.AddAttribute(XML_NAMESPACE_FO, XML_COUNTRY,
                                     aLocale.Country);

			// configuration element
			SvXMLElementExport aElement(rExport, XML_NAMESPACE_TEXT,
										XML_BIBLIOGRAPHY_CONFIGURATION,
										sal_True, sal_True);

			// sort keys
			aAny = xPropSet->getPropertyValue(sSortKeys);
			Sequence<Sequence<PropertyValue> > aKeys;
			aAny >>= aKeys;
			sal_Int32 nKeysCount = aKeys.getLength();
			for(sal_Int32 nKeys = 0; nKeys < nKeysCount; nKeys++)
			{
				Sequence<PropertyValue> & rKey = aKeys[nKeys];

				sal_Int32 nKeyCount = rKey.getLength();
				for(sal_Int32 nPropertyKey = 0; nPropertyKey < nKeyCount; nPropertyKey++)
				{
					PropertyValue& rValue = rKey[nPropertyKey];

					if (rValue.Name.equalsAsciiL(sAPI_SortKey,
												 sizeof(sAPI_SortKey)-1))
					{
						sal_Int16 nKey = 0;
						rValue.Value >>= nKey;
						OUStringBuffer sBuf;
						if (SvXMLUnitConverter::convertEnum( sBuf, nKey,
												 aBibliographyDataFieldMap ) )
						{
							rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_KEY,
												 sBuf.makeStringAndClear());
						}
					}
					else if (rValue.Name.equalsAsciiL(sAPI_IsSortAscending,
											sizeof(sAPI_IsSortAscending)-1))
					{
						sal_Bool bTmp = *(sal_Bool*)rValue.Value.getValue();
						rExport.AddAttribute(XML_NAMESPACE_TEXT,
                                             XML_SORT_ASCENDING,
                                             bTmp ? XML_TRUE : XML_FALSE);
					}
				}

				SvXMLElementExport aKeyElem(rExport,
											XML_NAMESPACE_TEXT, XML_SORT_KEY,
											sal_True, sal_True);
			}
		}
	}
}


sal_Bool XMLSectionExport::IsMuteSection(
	const Reference<XTextSection> & rSection) const
{
	sal_Bool bRet = sal_False;

	// a section is mute if
	// 1) it exists
	// 2) the SaveLinkedSections flag (at the export) is false
	// 3) the IsGlobalDocumentSection property is true
    // 4) it is not an Index

	if ( (!rExport.IsSaveLinkedSections()) && rSection.is() )
	{
		// walk the section chain and set bRet if any is linked
		for(Reference<XTextSection> aSection(rSection);
			aSection.is();
			aSection = aSection->getParentSection())
		{
			// check if it is a global document section (linked or index)
			Reference<XPropertySet> xPropSet(aSection, UNO_QUERY);
			if (xPropSet.is())
			{
				Any aAny = xPropSet->getPropertyValue(sIsGlobalDocumentSection);

                if ( *(sal_Bool*)aAny.getValue() )
                {
                    Reference<XDocumentIndex> xIndex;
                    if (! GetIndex(rSection, xIndex))
                    {
                        bRet = sal_True;

                        // early out if result is known
                        break;
                    }
                }
			}
			// section has no properties: ignore
		}
	}
	// else: no section, or always save sections: default (false)

	return bRet;
}

sal_Bool XMLSectionExport::IsMuteSection(
	const Reference<XTextContent> & rSection,
	sal_Bool bDefault) const
{
	// default: like default argument
	sal_Bool bRet = bDefault;

	Reference<XPropertySet> xPropSet(rSection->getAnchor(), UNO_QUERY);
	if (xPropSet.is())
	{
		if (xPropSet->getPropertySetInfo()->hasPropertyByName(sTextSection))
		{
			Any aAny = xPropSet->getPropertyValue(sTextSection);
			Reference<XTextSection> xSection;
			aAny >>= xSection;

			bRet = IsMuteSection(xSection);
		}
		// else: return default
	}
	// else: return default

	return bRet;
}

sal_Bool XMLSectionExport::IsInSection(
	const Reference<XTextSection> & rEnclosingSection,
	const Reference<XTextContent> & rContent,
	sal_Bool bDefault)
{
	// default: like default argument
	sal_Bool bRet = bDefault;
	OSL_ENSURE(rEnclosingSection.is(), "enclosing section expected");

	Reference<XPropertySet> xPropSet(rContent, UNO_QUERY);
	if (xPropSet.is())
	{
		if (xPropSet->getPropertySetInfo()->hasPropertyByName(sTextSection))
		{
			Any aAny = xPropSet->getPropertyValue(sTextSection);
			Reference<XTextSection> xSection;
			aAny >>= xSection;

			// now walk chain of text sections (if we have one)
			if (xSection.is())
			{
				do
				{
					bRet = (rEnclosingSection == xSection);
					xSection = xSection->getParentSection();
				}
				while (!bRet && xSection.is());
			}
			else
				bRet = sal_False;	// no section -> can't be inside
		}
		// else: no TextSection property -> return default
	}
	// else: no XPropertySet -> return default

	return bRet;
}


void XMLSectionExport::ExportMasterDocHeadingDummies()
{
	if( bHeadingDummiesExported )
		return;

	Reference< XChapterNumberingSupplier > xCNSupplier( rExport.GetModel(),
														UNO_QUERY );

	Reference< XIndexReplace > xChapterNumbering;
	if( xCNSupplier.is() )
		xChapterNumbering = xCNSupplier->getChapterNumberingRules();

	if( !xChapterNumbering.is() )
		return;

	sal_Int32 nCount = xChapterNumbering->getCount();
	for( sal_Int32 nLevel = 0; nLevel < nCount; nLevel++ )
	{
		OUString sStyle;
		Sequence<PropertyValue> aProperties;
		xChapterNumbering->getByIndex( nLevel ) >>= aProperties;
		for( sal_Int32 i = 0; i < aProperties.getLength(); i++ )
		{
			if( aProperties[i].Name == sHeadingStyleName )
			{
				aProperties[i].Value >>= sStyle;
				break;
			}
		}
		if( sStyle.getLength() > 0 )
		{
			GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
									  GetExport().EncodeStyleName( sStyle ) );

			OUStringBuffer sTmp;
			sTmp.append( nLevel + 1 );
			GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_LEVEL,
								  	  sTmp.makeStringAndClear() );
			SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_H,
								  	  sal_True, sal_False );
		}
	}

	bHeadingDummiesExported  = sal_True;
}
