/**************************************************************
 * 
 * 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 occured; #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;
}