/*************************************************************************
 *
 *  $RCSfile: txtparae.cxx,v $
 *
 *  $Revision: 1.123 $
 *
 *  last change: $Author: kz $ $Date: 2005-07-14 11:37:34 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef __COMPHELPER_UNOINTERFACETOUNIQUEIDENTIFIERMAPPER__
#include "unointerfacetouniqueidentifiermapper.hxx"
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif
#ifndef _SVSTDARR_LONGS_DECL
#define _SVSTDARR_LONGS
#include <svtools/svstdarr.hxx>
#endif
#ifndef _SVARRAY_HXX
#include <svtools/svarray.hxx>
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#include <vector>


#ifndef _COM_SUN_STAR_LANG_XSERVICEINFO_HPP_
#include <com/sun/star/lang/XServiceInfo.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATIONACCESS_HPP_
#include <com/sun/star/container/XEnumerationAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XENUMERATION_HPP_
#include <com/sun/star/container/XEnumeration.hpp>
#endif

#ifndef _COM_SUN_STAR_CONTAINER_XINDEXREPLACE_HPP_
#include <com/sun/star/container/XIndexReplace.hpp>
#endif

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XMULTIPROPERTYSET_HPP_
#include <com/sun/star/beans/XMultiPropertySet.hpp>
#endif
#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSTATE_HPP_
#include <com/sun/star/beans/XPropertyState.hpp>
#endif

#ifndef _COM_SUN_STAR_TEXT_XTEXTDOCUMENT_HPP_
#include <com/sun/star/text/XTextDocument.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXT_HPP_
#include <com/sun/star/text/XText.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXTCONTENT_HPP_
#include <com/sun/star/text/XTextContent.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXTRANGE_HPP_
#include <com/sun/star/text/XTextRange.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXTFIELD_HPP_
#include <com/sun/star/text/XTextField.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XFOOTNOTE_HPP_
#include <com/sun/star/text/XFootnote.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
#include <com/sun/star/container/XNamed.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XCONTENTENUMERATIONACCESS_HPP_
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXTFRAME_HPP_
#include <com/sun/star/text/XTextFrame.hpp>
#endif
#ifndef _COM_SUN_STAR_CONTAINER_XNAMED_HPP_
#include <com/sun/star/container/XNamed.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_SIZETYPE_HPP_
#include <com/sun/star/text/SizeType.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_HORIORIENTATION_HPP_
#include <com/sun/star/text/HoriOrientation.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_VERTORIENTATION_HPP_
#include <com/sun/star/text/VertOrientation.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_TEXTCONTENTANCHORTYPE_HPP
#include <com/sun/star/text/TextContentAnchorType.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXTFRAMESSUPPLIER_HPP_
#include <com/sun/star/text/XTextFramesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXTGRAPHICOBJECTSSUPPLIER_HPP_
#include <com/sun/star/text/XTextGraphicObjectsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXTEMBEDDEDOBJECTSSUPPLIER_HPP_
#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XDRAWPAGESUPPLIER_HPP_
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XEMBEDDEDOBJECTSUPPLIER_HPP_
#include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XEVENTSSUPPLIER_HPP_
#include <com/sun/star/document/XEventsSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DOCUMENT_XREDLINESSUPPLIER_HPP_
#include <com/sun/star/document/XRedlinesSupplier.hpp>
#endif

#ifndef _COM_SUN_STAR_TEXT_XTEXTSECTION_HPP_
#include <com/sun/star/text/XTextSection.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_SECTIONFILELINK_HPP_
#include <com/sun/star/text/SectionFileLink.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XSHAPE_HPP_
#include <com/sun/star/drawing/XShape.hpp>
#endif
#ifndef _COM_SUN_STAR_TEXT_XTEXTSHAPESSUPPLIER_HPP_
#include <com/sun/star/text/XTextShapesSupplier.hpp>
#endif
#ifndef _COM_SUN_STAR_DRAWING_XCONTROLSHAPE_HPP_
#include <com/sun/star/drawing/XControlShape.hpp>
#endif

#ifndef _COM_SUN_STAR_UTIL_DATETIME_HPP_
#include <com/sun/star/util/DateTime.hpp>
#endif

#ifndef _XMLOFF_XMLKYWD_HXX
#include "xmlkywd.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLASTPLP_HXX
#include "xmlaustp.hxx"
#endif
#ifndef _XMLOFF_FAMILIES_HXX_
#include "families.hxx"
#endif
#ifndef _XMLOFF_TXTEXPPR_HXX
#include "txtexppr.hxx"
#endif
#ifndef _XMLOFF_XMLNUMFE_HXX
#include "xmlnumfe.hxx"
#endif
#ifndef _XMLOFF_XMLNUME_HXX
#include "xmlnume.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif
#ifndef _XMLOFF_XMLANCHORTYPEPROPHDL_HXX
#include "XMLAnchorTypePropHdl.hxx"
#endif
#ifndef _XEXPTRANSFORM_HXX
#include "xexptran.hxx"
#endif
#ifndef _XMLOFF_PROGRESSBARHELPER_HXX
#include "ProgressBarHelper.hxx"
#endif

#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLEXP_HXX
#include "xmlexp.hxx"
#endif
#ifndef _XMLOFF_TXTFLDE_HXX
#include "txtflde.hxx"
#endif
#ifndef _XMLOFF_TXTPRMAP_HXX
#include "txtprmap.hxx"
#endif
#ifndef _XMLOFF_XMLIMAGEMAPEXPORT_HXX_
#include "XMLImageMapExport.hxx"
#endif

#ifndef _XMLOFF_XMLTEXTNUMRULEINFO_HXX
#include "XMLTextNumRuleInfo.hxx"
#endif
#ifndef _XMLOFF_XMLTEXTLISTAUTOSTYLEPOOL_HXX
#include "XMLTextListAutoStylePool.hxx"
#endif
#ifndef _XMLOFF_TXTPARAE_HXX
#include "txtparae.hxx"
#endif
#ifndef _XMLOFF_XMLSECTIONEXPORT_HXX_
#include "XMLSectionExport.hxx"
#endif
#ifndef _XMLOFF_XMLINDEXMARKEXPORT_HXX_
#include "XMLIndexMarkExport.hxx"
#endif
#ifndef _XMLOFF_XMLEVENTEXPORT_HXX
#include "XMLEventExport.hxx"
#endif
#ifndef _XMLOFF_XMLREDLINEEXPORT_HXX
#include "XMLRedlineExport.hxx"
#endif
#ifndef _XMLOFF_MULTIPROPERTYSETHELPER_HXX
#include "MultiPropertySetHelper.hxx"
#endif
#ifndef _XMLOFF_FORMLAYEREXPORT_HXX_
#include "formlayerexport.hxx"
#endif
#ifndef _XMLOFF_XMLTEXTCHARSTYLENAMESELEMENTEXPORT_HXX
#include "XMLTextCharStyleNamesElementExport.hxx"
#endif


using namespace ::rtl;
using namespace ::std;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::util;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::document;
using namespace ::com::sun::star::frame;
using namespace ::xmloff::token;


typedef OUString *OUStringPtr;
SV_DECL_PTRARR_DEL( OUStrings_Impl, OUStringPtr, 20, 10 )
SV_IMPL_PTRARR( OUStrings_Impl, OUStringPtr )

SV_DECL_PTRARR_SORT_DEL( OUStringsSort_Impl, OUStringPtr, 20, 10 )
SV_IMPL_OP_PTRARR_SORT( OUStringsSort_Impl, OUStringPtr )

#ifndef PRODUCT
static int txtparae_bContainsIllegalCharacters = sal_False;
#endif

// The following map shows which property values are required:
//
// property                     auto style pass     export
// --------------------------------------------------------
// ParaStyleName                if style exists     always
// ParaConditionalStyleName     if style exists     always
// NumberingRules               if style exists     always
// TextSection                  always              always
// ParaChapterNumberingLevel    never               always
// NumberingIsNumber            never               always

// The conclusion is that for auto styles the first three properties
// should be queried using a multi property set if, and only if, an
// auto style needs to be exported. TextSection should be queried by
// an individual call to getPropertyvalue, because this seems to be
// less expensive than querying the first three properties if they aren't
// required.

// For the export pass all properties can be queried using a multi property
// set.

static const sal_Char* aParagraphPropertyNamesAuto[] =
{
    "NumberingRules",
    "ParaConditionalStyleName",
    "ParaStyleName",
    NULL
};

enum eParagraphPropertyNamesEnumAuto
{
    NUMBERING_RULES_AUTO = 0,
    PARA_CONDITIONAL_STYLE_NAME_AUTO = 1,
    PARA_STYLE_NAME_AUTO = 2
};

static const sal_Char* aParagraphPropertyNames[] =
{
    "NumberingIsNumber",
    "ParaChapterNumberingLevel",
    "ParaConditionalStyleName",
    "ParaStyleName",
    "TextSection",
    NULL
};

enum eParagraphPropertyNamesEnum
{
    NUMBERING_IS_NUMBER = 0,
    PARA_CHAPTER_NUMERBING_LEVEL = 1,
    PARA_CONDITIONAL_STYLE_NAME = 2,
    PARA_STYLE_NAME = 3,
    TEXT_SECTION = 4
};



void XMLTextParagraphExport::Add( sal_uInt16 nFamily,
                                  const Reference < XPropertySet > & rPropSet,
                                  const XMLPropertyState** ppAddStates)
{
    UniReference < SvXMLExportPropertyMapper > xPropMapper;
    switch( nFamily )
    {
    case XML_STYLE_FAMILY_TEXT_PARAGRAPH:
        xPropMapper = GetParaPropMapper();
        break;
    case XML_STYLE_FAMILY_TEXT_TEXT:
        xPropMapper = GetTextPropMapper();
        break;
    case XML_STYLE_FAMILY_TEXT_FRAME:
        xPropMapper = GetAutoFramePropMapper();
        break;
    case XML_STYLE_FAMILY_TEXT_SECTION:
        xPropMapper = GetSectionPropMapper();
        break;
    case XML_STYLE_FAMILY_TEXT_RUBY:
        xPropMapper = GetRubyPropMapper();
        break;
    }
    DBG_ASSERT( xPropMapper.is(), "There is the property mapper?" );

    vector< XMLPropertyState > xPropStates =
            xPropMapper->Filter( rPropSet );
    if( ppAddStates )
    {
        while( *ppAddStates )
        {
            xPropStates.push_back( **ppAddStates );
            ppAddStates++;
        }
    }

    if( xPropStates.size() > 0L )
    {
        Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());
        OUString sParent, sCondParent;
        sal_uInt16 nIgnoreProps = 0;
        switch( nFamily )
        {
        case XML_STYLE_FAMILY_TEXT_PARAGRAPH:
            if( xPropSetInfo->hasPropertyByName( sParaStyleName ) )
            {
                rPropSet->getPropertyValue( sParaStyleName ) >>= sParent;
            }
            if( xPropSetInfo->hasPropertyByName( sParaConditionalStyleName ) )
            {
                rPropSet->getPropertyValue( sParaConditionalStyleName ) >>= sCondParent;
            }
            if( xPropSetInfo->hasPropertyByName( sNumberingRules ) )
            {
                Reference < XIndexReplace > xNumRule(rPropSet->getPropertyValue( sNumberingRules ), uno::UNO_QUERY);
                if( xNumRule.is() && xNumRule->getCount() )
                {
                    Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
                    OUString sName;
                    if( xNamed.is() )
                        sName = xNamed->getName();
                    sal_Bool bAdd = !sName.getLength();
                    if( !bAdd )
                    {
                        Reference < XPropertySet > xNumPropSet( xNumRule,
                                                                UNO_QUERY );
                        OUString sIsAutomatic( RTL_CONSTASCII_USTRINGPARAM( "IsAutomatic" ) );
                        if( xNumPropSet.is() &&
                            xNumPropSet->getPropertySetInfo()
                                       ->hasPropertyByName( sIsAutomatic ) )
                        {
                            bAdd = *(sal_Bool *)xNumPropSet->getPropertyValue( sIsAutomatic ).getValue();
                        }
                        else
                        {
                            bAdd = sal_True;
                        }
                    }
                    if( bAdd )
                        pListAutoPool->Add( xNumRule );
                }
            }
            break;
        case XML_STYLE_FAMILY_TEXT_TEXT:
            {
                // Get parent and remove hyperlinks (they aren't of interest)
                UniReference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
                for( ::std::vector< XMLPropertyState >::iterator i(xPropStates.begin());
                      nIgnoreProps < 2 && i != xPropStates.end();
                      i++ )
                {
                    if( i->mnIndex == -1 )
                        continue;

                    switch( xPM->GetEntryContextId(i->mnIndex) )
                    {
                    case CTF_CHAR_STYLE_NAME:
                        i->maValue >>= sParent;
                        i->mnIndex = -1;
                        nIgnoreProps++;
                        break;
                    case CTF_HYPERLINK_URL:
                        i->mnIndex = -1;
                        nIgnoreProps++;
                        break;
                    }
                }
            }
            break;
        case XML_STYLE_FAMILY_TEXT_FRAME:
            if( xPropSetInfo->hasPropertyByName( sFrameStyleName ) )
            {
                rPropSet->getPropertyValue( sFrameStyleName ) >>= sParent;
            }
            break;
        case XML_STYLE_FAMILY_TEXT_SECTION:
        case XML_STYLE_FAMILY_TEXT_RUBY:
            ; // section styles have no parents
            break;
        }
        if( (xPropStates.size() - nIgnoreProps) > 0 )
        {
            GetAutoStylePool().Add( nFamily, sParent, xPropStates );
            if( sCondParent.getLength() && sParent != sCondParent )
                GetAutoStylePool().Add( nFamily, sCondParent, xPropStates );
        }
    }
}

bool lcl_validPropState( const XMLPropertyState& rState )
{
    return rState.mnIndex != -1;
}

void XMLTextParagraphExport::Add( sal_uInt16 nFamily,
                                  MultiPropertySetHelper& rPropSetHelper,
                                  const Reference < XPropertySet > & rPropSet,
                                  const XMLPropertyState** ppAddStates)
{
    UniReference < SvXMLExportPropertyMapper > xPropMapper;
    switch( nFamily )
    {
    case XML_STYLE_FAMILY_TEXT_PARAGRAPH:
        xPropMapper = GetParaPropMapper();
        break;
    }
    DBG_ASSERT( xPropMapper.is(), "There is the property mapper?" );

    vector< XMLPropertyState > xPropStates(xPropMapper->Filter( rPropSet ));
    if( ppAddStates )
    {
        while( *ppAddStates )
        {
            xPropStates.push_back( **ppAddStates );
            ++ppAddStates;
        }
    }

    if( xPropStates.size() > 0L )
    {
        OUString sParent, sCondParent;
        switch( nFamily )
        {
        case XML_STYLE_FAMILY_TEXT_PARAGRAPH:
            if( rPropSetHelper.hasProperty( PARA_STYLE_NAME_AUTO ) )
            {
                rPropSetHelper.getValue( PARA_STYLE_NAME_AUTO, rPropSet,
                                                sal_True ) >>= sParent;
            }
            if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME_AUTO ) )
            {
                rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME_AUTO,
                                                 rPropSet, sal_True ) >>= sCondParent;
            }
            if( rPropSetHelper.hasProperty( NUMBERING_RULES_AUTO ) )
            {
                Reference < XIndexReplace > xNumRule(rPropSetHelper.getValue( NUMBERING_RULES_AUTO,
                    rPropSet, sal_True ), uno::UNO_QUERY);
                if( xNumRule.is() && xNumRule->getCount() )
                {
                    Reference < XNamed > xNamed( xNumRule, UNO_QUERY );
                    OUString sName;
                    if( xNamed.is() )
                        sName = xNamed->getName();
                    sal_Bool bAdd = !sName.getLength();
                    if( !bAdd )
                    {
                        Reference < XPropertySet > xNumPropSet( xNumRule,
                                                                UNO_QUERY );
                        OUString sIsAutomatic( RTL_CONSTASCII_USTRINGPARAM( "IsAutomatic" ) );
                        if( xNumPropSet.is() &&
                            xNumPropSet->getPropertySetInfo()
                                       ->hasPropertyByName( sIsAutomatic ) )
                        {
                            bAdd = *(sal_Bool *)xNumPropSet->getPropertyValue( sIsAutomatic ).getValue();
                        }
                        else
                        {
                            bAdd = sal_True;
                        }
                    }
                    if( bAdd )
                        pListAutoPool->Add( xNumRule );
                }
            }
            break;
        }

        if( find_if( xPropStates.begin(), xPropStates.end(), lcl_validPropState ) != xPropStates.end() )
        {
            GetAutoStylePool().Add( nFamily, sParent, xPropStates );
            if( sCondParent.getLength() && sParent != sCondParent )
                GetAutoStylePool().Add( nFamily, sCondParent, xPropStates );
        }
    }
}

OUString XMLTextParagraphExport::Find(
        sal_uInt16 nFamily,
           const Reference < XPropertySet > & rPropSet,
        const OUString& rParent,
        const XMLPropertyState** ppAddStates) const
{
    OUString sName( rParent );
    UniReference < SvXMLExportPropertyMapper > xPropMapper;
    switch( nFamily )
    {
    case XML_STYLE_FAMILY_TEXT_PARAGRAPH:
        xPropMapper = GetParaPropMapper();
        break;
    case XML_STYLE_FAMILY_TEXT_FRAME:
        xPropMapper = GetAutoFramePropMapper();
        break;
    case XML_STYLE_FAMILY_TEXT_SECTION:
        xPropMapper = GetSectionPropMapper();
        break;
    case XML_STYLE_FAMILY_TEXT_RUBY:
        xPropMapper = GetRubyPropMapper();
        break;
    }
    DBG_ASSERT( xPropMapper.is(), "There is the property mapper?" );
    if( !xPropMapper.is() )
        return sName;
    vector< XMLPropertyState > xPropStates(xPropMapper->Filter( rPropSet ));
    if( ppAddStates )
    {
        while( *ppAddStates )
        {
            xPropStates.push_back( **ppAddStates );
            ++ppAddStates;
        }
    }
    if( find_if( xPropStates.begin(), xPropStates.end(), lcl_validPropState ) != xPropStates.end() )
        sName = GetAutoStylePool().Find( nFamily, sName, xPropStates );

    return sName;
}

OUString XMLTextParagraphExport::FindTextStyleAndHyperlink(
           const Reference < XPropertySet > & rPropSet,
        sal_Bool& rHyperlink,
        sal_Bool& rHasCharStyle,
        const XMLPropertyState** ppAddStates ) const
{
    UniReference < SvXMLExportPropertyMapper > xPropMapper(GetTextPropMapper());
    vector< XMLPropertyState > xPropStates(xPropMapper->Filter( rPropSet ));

    // Get parent and remove hyperlinks (they aren't of interest)
    OUString sName;
    rHyperlink = rHasCharStyle = sal_False;
    sal_uInt16 nIgnoreProps = 0;
    UniReference< XMLPropertySetMapper > xPM(xPropMapper->getPropertySetMapper());
    for( ::std::vector< XMLPropertyState >::iterator
            i = xPropStates.begin();
         nIgnoreProps < 2 && i != xPropStates.end();
         i++ )
    {
        if( i->mnIndex == -1 )
            continue;

        switch( xPM->GetEntryContextId(i->mnIndex) )
        {
        case CTF_CHAR_STYLE_NAME:
            i->maValue >>= sName;
            i->mnIndex = -1;
            rHasCharStyle = sName.getLength() > 0;
            nIgnoreProps++;
            break;
        case CTF_HYPERLINK_URL:
            rHyperlink = sal_True;
            i->mnIndex = -1;
            nIgnoreProps++;
            break;
        }
    }
    if( ppAddStates )
    {
        while( *ppAddStates )
        {
            xPropStates.push_back( **ppAddStates );
            ppAddStates++;
        }
    }
    if( (xPropStates.size() - nIgnoreProps) > 0L )
        sName = GetAutoStylePool().Find( XML_STYLE_FAMILY_TEXT_TEXT, sName, xPropStates );

    return sName;
}

OUString XMLTextParagraphExport::FindTextStyle(
           const Reference < XPropertySet > & rPropSet,
        sal_Bool& rHasCharStyle ) const
{
    sal_Bool bDummy;
    return FindTextStyleAndHyperlink( rPropSet, bDummy, rHasCharStyle );
}


void XMLTextParagraphExport::exportListChange(
        const XMLTextNumRuleInfo& rPrevInfo,
        const XMLTextNumRuleInfo& rNextInfo )
{
    // end a list
    if( rPrevInfo.GetLevel() > 0 &&
        ( !rNextInfo.HasSameNumRules( rPrevInfo ) ||
          rNextInfo.GetLevel() < rPrevInfo.GetLevel() ||
             rNextInfo.IsRestart()  ) )
    {
        sal_Int16 nPrevLevel = rPrevInfo.GetLevel();
        sal_Int16 nNextLevel =
            ( !rNextInfo.HasSameNumRules( rPrevInfo ) ||
              rNextInfo.IsRestart() ) ?  0 : rNextInfo.GetLevel();

        DBG_ASSERT( pListElements &&
                pListElements->Count() >= 2*(nNextLevel-nPrevLevel),
                "SwXMLExport::ExportListChange: list elements missing" );

        for( sal_Int16 i=nPrevLevel; i > nNextLevel; i-- )
        {
            for( sal_uInt16 j=0; j<2; j++ )
            {
                OUString *pElem = (*pListElements)[pListElements->Count()-1];
                pListElements->Remove( pListElements->Count()-1 );

                GetExport().EndElement( *pElem, sal_True );

                delete pElem;
            }
        }
    }

    // start a new list
    if( rNextInfo.GetLevel() > 0 &&
        ( !rPrevInfo.HasSameNumRules( rNextInfo ) ||
          rPrevInfo.GetLevel() < rNextInfo.GetLevel() ||
             rNextInfo.IsRestart() ) )
    {
        sal_Int16 nPrevLevel =
            ( !rNextInfo.HasSameNumRules( rPrevInfo ) ||
              rNextInfo.IsRestart() ) ? 0 : rPrevInfo.GetLevel();
        sal_Int16 nNextLevel = rNextInfo.GetLevel();

        // Find out whether this is the first application of the list or not.
        // For named lists, we use the internal name. For unnamed lists, we
        // use the generated name. This works well, because there are either
        // unnamed or either named lists only.
        sal_Bool bListExported = sal_False;
        OUString sName;
        if( rNextInfo.IsNamed() )
            sName = rNextInfo.GetName();
        else
            sName = pListAutoPool->Find( rNextInfo.GetNumRules() );
        DBG_ASSERT( sName.getLength(), "list without a name" );
        if( sName.getLength() )
        {
            bListExported = pExportedLists &&
                             pExportedLists->Seek_Entry( (OUString *)&sName );
            if( !bListExported )
            {
                if( !pExportedLists )
                    pExportedLists = new OUStringsSort_Impl;
                pExportedLists->Insert( new OUString(sName) );
            }
        }
        sal_Bool bContinue = !rNextInfo.IsRestart() && bListExported &&
                             !rPrevInfo.HasSameNumRules( rNextInfo );

        for( sal_Int16 i=nPrevLevel; i < nNextLevel; i++)
        {
            // <text:ordered-list> or <text:unordered-list>
            GetExport().CheckAttrList();
            if( 0 == i )
            {
                // For named list, the name might be the name of an automatic
                // rule, so we have to take a look into the style pool.
                // For unnamed lists, we have done this already.
                if( rNextInfo.IsNamed() )
                {
                    OUString sTmp( pListAutoPool->Find(
                                            rNextInfo.GetNumRules() ) );
                    if( sTmp.getLength() )
                        sName = sTmp;
                }
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                        GetExport().EncodeStyleName( sName ) );
            }
            if( bContinue && rNextInfo.IsOrdered() )
                GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                          XML_CONTINUE_NUMBERING, XML_TRUE );

            enum XMLTokenEnum eLName = XML_LIST;

            OUString *pElem = new OUString(
                    GetExport().GetNamespaceMap().GetQNameByKey(
                                        XML_NAMESPACE_TEXT,
                                        GetXMLToken(eLName) ) );
            GetExport().IgnorableWhitespace();
            GetExport().StartElement( *pElem, sal_False );

            if( !pListElements )
                pListElements = new OUStrings_Impl;
            pListElements->Insert( pElem, pListElements->Count() );

            // <text:list-header> or <text:list-item>
            GetExport().CheckAttrList();
            if( rNextInfo.HasStartValue() )
            {
                OUStringBuffer aBuffer;
                aBuffer.append( (sal_Int32)rNextInfo.GetStartValue() );
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
                              aBuffer.makeStringAndClear() );
            }
            eLName = (rNextInfo.IsNumbered() || i+1 < nNextLevel)
                        ? XML_LIST_ITEM
                        : XML_LIST_HEADER;
            pElem = new OUString(  GetExport().GetNamespaceMap().GetQNameByKey(
                                        XML_NAMESPACE_TEXT,
                                        GetXMLToken(eLName) ) );
            GetExport().IgnorableWhitespace();
            GetExport().StartElement( *pElem, sal_False );

            pListElements->Insert( pElem, pListElements->Count() );
        }
    }

    if( rNextInfo.GetLevel() > 0 && rNextInfo.IsNumbered() &&
        rPrevInfo.HasSameNumRules( rNextInfo ) &&
        rPrevInfo.GetLevel() >= rNextInfo.GetLevel() &&
        !rNextInfo.IsRestart() )
    {
        // </text:list-item> or </text:list-header>
        DBG_ASSERT( pListElements && pListElements->Count() >= 2,
                "SwXMLExport::ExportListChange: list elements missing" );

        OUString *pElem = (*pListElements)[pListElements->Count()-1];
        GetExport().EndElement( *pElem, sal_True );

        pListElements->Remove( pListElements->Count()-1 );
        delete pElem;

        // <text:list-item>
        GetExport().CheckAttrList();
        if( rNextInfo.HasStartValue() )
        {
            OUStringBuffer aBuffer;
            aBuffer.append( (sal_Int32)rNextInfo.GetStartValue() );
            GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_START_VALUE,
                              aBuffer.makeStringAndClear() );
        }
        pElem = new OUString( GetExport().GetNamespaceMap().GetQNameByKey(
                                XML_NAMESPACE_TEXT,
                                GetXMLToken(XML_LIST_ITEM) ) );
        GetExport().IgnorableWhitespace();
        GetExport().StartElement( *pElem, sal_False );

        pListElements->Insert( pElem, pListElements->Count() );
    }
}


XMLTextParagraphExport::XMLTextParagraphExport(
        SvXMLExport& rExp,
        SvXMLAutoStylePoolP & rASP
#if SUPD < 628 && !defined( TEST_MIB )
        , sal_Int32 nProg
#endif
        ) :
    XMLStyleExport( rExp, OUString(), &rASP ),
//  rExport( rExp ),
    rAutoStylePool( rASP ),
    pListElements( 0 ),
    pExportedLists( 0 ),
    pListAutoPool( new XMLTextListAutoStylePool( this->GetExport() ) ),
    pFieldExport( 0 ),
    pPageTextFrameIdxs( 0 ),
    pPageGraphicIdxs( 0 ),
    pPageEmbeddedIdxs( 0 ),
    pPageShapeIdxs( 0 ),
    pFrameTextFrameIdxs( 0 ),
    pFrameGraphicIdxs( 0 ),
    pFrameEmbeddedIdxs( 0 ),
    pSectionExport( NULL ),
    pIndexMarkExport( NULL ),
    pRedlineExport( NULL ),
    pHeadingStyles( NULL ),
    pFrameShapeIdxs( 0 ),
    bBlock( sal_False ),
    bOpenRuby( sal_False ),
    sParagraphService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Paragraph")),
    sTableService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextTable")),
    sTextFieldService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextField")),
    sTextFrameService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextFrame")),
    sTextGraphicService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextGraphicObject")),
    sTextEmbeddedService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextEmbeddedObject")),
    sTextEndnoteService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Endnote")),
    sTextContentService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextContent")),
    sShapeService(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.Shape")),
    sParaStyleName(RTL_CONSTASCII_USTRINGPARAM("ParaStyleName")),
    sParaConditionalStyleName(RTL_CONSTASCII_USTRINGPARAM("ParaConditionalStyleName")),
    sParaChapterNumberingLevel(RTL_CONSTASCII_USTRINGPARAM("ParaChapterNumberingLevel")),
    sCharStyleName(RTL_CONSTASCII_USTRINGPARAM("CharStyleName")),
    sCharStyleNames(RTL_CONSTASCII_USTRINGPARAM("CharStyleNames")),
    sFrameStyleName(RTL_CONSTASCII_USTRINGPARAM("FrameStyleName")),
    sTextField(RTL_CONSTASCII_USTRINGPARAM("TextField")),
    sText(RTL_CONSTASCII_USTRINGPARAM("Text")),
    sFrame(RTL_CONSTASCII_USTRINGPARAM("Frame")),
    sCategory(RTL_CONSTASCII_USTRINGPARAM("Category")),
    sNumberingRules(RTL_CONSTASCII_USTRINGPARAM("NumberingRules")),
    sTextPortionType(RTL_CONSTASCII_USTRINGPARAM("TextPortionType")),
    sFootnote(RTL_CONSTASCII_USTRINGPARAM("Footnote")),
    sBookmark(RTL_CONSTASCII_USTRINGPARAM("Bookmark")),
    sReferenceMark(RTL_CONSTASCII_USTRINGPARAM("ReferenceMark")),
    sIsCollapsed(RTL_CONSTASCII_USTRINGPARAM("IsCollapsed")),
    sIsStart(RTL_CONSTASCII_USTRINGPARAM("IsStart")),
    sReferenceId(RTL_CONSTASCII_USTRINGPARAM("ReferenceId")),
    sNumberingType(RTL_CONSTASCII_USTRINGPARAM("NumberingType")),
    sPageStyleName(RTL_CONSTASCII_USTRINGPARAM("PageStyleName")),
    sPageDescName(RTL_CONSTASCII_USTRINGPARAM("PageDescName")),
    sPrefix(RTL_CONSTASCII_USTRINGPARAM("Prefix")),
    sStartAt(RTL_CONSTASCII_USTRINGPARAM("StartAt")),
    sSuffix(RTL_CONSTASCII_USTRINGPARAM("Suffix")),
    sPositionEndOfDoc(RTL_CONSTASCII_USTRINGPARAM("PositionEndOfDoc")),
    sFootnoteCounting(RTL_CONSTASCII_USTRINGPARAM("FootnoteCounting")),
    sEndNotice(RTL_CONSTASCII_USTRINGPARAM("EndNotice")),
    sBeginNotice(RTL_CONSTASCII_USTRINGPARAM("BeginNotice")),
    sFrameWidthAbsolute(RTL_CONSTASCII_USTRINGPARAM("FrameWidthAbsolute")),
    sFrameWidthPercent(RTL_CONSTASCII_USTRINGPARAM("FrameWidthPercent")),
    sFrameHeightAbsolute(RTL_CONSTASCII_USTRINGPARAM("FrameHeightAbsolute")),
    sFrameHeightPercent(RTL_CONSTASCII_USTRINGPARAM("FrameHeightPercent")),
    sWidth(RTL_CONSTASCII_USTRINGPARAM("Width")),
    sRelativeWidth(RTL_CONSTASCII_USTRINGPARAM("RelativeWidth")),
    sHeight(RTL_CONSTASCII_USTRINGPARAM("Height")),
    sRelativeHeight(RTL_CONSTASCII_USTRINGPARAM("RelativeHeight")),
    sSizeType(RTL_CONSTASCII_USTRINGPARAM("SizeType")),
    sIsSyncWidthToHeight(RTL_CONSTASCII_USTRINGPARAM("IsSyncWidthToHeight")),
    sIsSyncHeightToWidth(RTL_CONSTASCII_USTRINGPARAM("IsSyncHeightToWidth")),
    sHoriOrient(RTL_CONSTASCII_USTRINGPARAM("HoriOrient")),
    sHoriOrientPosition(RTL_CONSTASCII_USTRINGPARAM("HoriOrientPosition")),
    sVertOrient(RTL_CONSTASCII_USTRINGPARAM("VertOrient")),
    sVertOrientPosition(RTL_CONSTASCII_USTRINGPARAM("VertOrientPosition")),
    sChainNextName(RTL_CONSTASCII_USTRINGPARAM("ChainNextName")),
    sAnchorType(RTL_CONSTASCII_USTRINGPARAM("AnchorType")),
    sAnchorPageNo(RTL_CONSTASCII_USTRINGPARAM("AnchorPageNo")),
    sGraphicURL(RTL_CONSTASCII_USTRINGPARAM("GraphicURL")),
    sGraphicFilter(RTL_CONSTASCII_USTRINGPARAM("GraphicFilter")),
    sGraphicRotation(RTL_CONSTASCII_USTRINGPARAM("GraphicRotation")),
    sAlternativeText(RTL_CONSTASCII_USTRINGPARAM("AlternativeText")),
    sHyperLinkURL(RTL_CONSTASCII_USTRINGPARAM("HyperLinkURL")),
    sHyperLinkName(RTL_CONSTASCII_USTRINGPARAM("HyperLinkName")),
    sHyperLinkTarget(RTL_CONSTASCII_USTRINGPARAM("HyperLinkTarget")),
    sUnvisitedCharStyleName(RTL_CONSTASCII_USTRINGPARAM("UnvisitedCharStyleName")),
    sVisitedCharStyleName(RTL_CONSTASCII_USTRINGPARAM("VisitedCharStyleName")),
    sTextSection(RTL_CONSTASCII_USTRINGPARAM("TextSection")),
    sDocumentIndex(RTL_CONSTASCII_USTRINGPARAM("DocumentIndex")),
    sDocumentIndexMark(RTL_CONSTASCII_USTRINGPARAM("DocumentIndexMark")),
    sActualSize(RTL_CONSTASCII_USTRINGPARAM("ActualSize")),
    sContourPolyPolygon(RTL_CONSTASCII_USTRINGPARAM("ContourPolyPolygon")),
    sIsPixelContour(RTL_CONSTASCII_USTRINGPARAM("IsPixelContour")),
    sIsAutomaticContour(RTL_CONSTASCII_USTRINGPARAM("IsAutomaticContour")),
    sAnchorCharStyleName(RTL_CONSTASCII_USTRINGPARAM("AnchorCharStyleName")),
    sServerMap(RTL_CONSTASCII_USTRINGPARAM("ServerMap")),
    sRedline(RTL_CONSTASCII_USTRINGPARAM("Redline")),
    sRuby(RTL_CONSTASCII_USTRINGPARAM("Ruby")),
    sRubyText(RTL_CONSTASCII_USTRINGPARAM("RubyText")),
    sRubyAdjust(RTL_CONSTASCII_USTRINGPARAM("RubyAdjust")),
    sRubyCharStyleName(RTL_CONSTASCII_USTRINGPARAM("RubyCharStyleName")),
    sWidthType( RTL_CONSTASCII_USTRINGPARAM( "WidthType" ) ),
#if SUPD < 628 && !defined( TEST_MIB )
    nProgress( nProg ),
#else
    bProgress( sal_False ),
#endif
    aCharStyleNamesPropInfoCache( sCharStyleNames )
{
    UniReference < XMLPropertySetMapper > xPropMapper(new XMLTextPropertySetMapper( TEXT_PROP_MAP_PARA ));
    xParaPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                             GetExport() );

    OUString sFamily( GetXMLToken(XML_PARAGRAPH) );
    OUString sPrefix( String( 'P' ) );
    rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_PARAGRAPH, sFamily,
                              xParaPropMapper, sPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TEXT_PROP_MAP_TEXT );
    xTextPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                             GetExport() );
    sFamily = OUString( GetXMLToken(XML_TEXT) );
    sPrefix = OUString( String( 'T' ) );
    rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_TEXT, sFamily,
                              xTextPropMapper, sPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TEXT_PROP_MAP_AUTO_FRAME );
    xAutoFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                                  GetExport() );
    sFamily = OUString( RTL_CONSTASCII_USTRINGPARAM(XML_STYLE_FAMILY_SD_GRAPHICS_NAME) );
    sPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM( "fr" ) );
    rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_FRAME, sFamily,
                              xAutoFramePropMapper, sPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TEXT_PROP_MAP_SECTION );
    xSectionPropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                             GetExport() );
    sFamily = OUString( GetXMLToken( XML_SECTION ) );
    sPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM( "Sect" ) );
    rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_SECTION, sFamily,
                              xSectionPropMapper, sPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TEXT_PROP_MAP_RUBY );
    xRubyPropMapper = new SvXMLExportPropertyMapper( xPropMapper );
    sFamily = OUString( GetXMLToken( XML_RUBY ) );
    sPrefix = OUString( RTL_CONSTASCII_USTRINGPARAM( "Ru" ) );
    rAutoStylePool.AddFamily( XML_STYLE_FAMILY_TEXT_RUBY, sFamily,
                              xRubyPropMapper, sPrefix );

    xPropMapper = new XMLTextPropertySetMapper( TEXT_PROP_MAP_FRAME );
    xFramePropMapper = new XMLTextExportPropertySetMapper( xPropMapper,
                                                              GetExport() );

    pSectionExport = new XMLSectionExport( rExp, *this );
    pIndexMarkExport = new XMLIndexMarkExport( rExp, *this );

    if( ! IsBlockMode() &&
        Reference<XRedlinesSupplier>( GetExport().GetModel(), UNO_QUERY ).is())
        pRedlineExport = new XMLRedlineExport( rExp );

    // The text field helper needs a pre-constructed XMLPropertyState
    // to export the combined characters field. We construct that
    // here, because we need the text property mapper to do it.

    // construct Any value, then find index
    sal_Int32 nIndex = xTextPropMapper->getPropertySetMapper()->FindEntryIndex(
                                "", XML_NAMESPACE_STYLE,
                                GetXMLToken(XML_TEXT_COMBINE));
    pFieldExport = new XMLTextFieldExport( rExp, new XMLPropertyState( nIndex, uno::makeAny(sal_True) ) );
}

XMLTextParagraphExport::~XMLTextParagraphExport()
{
    delete pHeadingStyles;
    delete pRedlineExport;
    delete pIndexMarkExport;
    delete pSectionExport;
    delete pFieldExport;
    delete pListElements;
    delete pExportedLists;
    delete pListAutoPool;
    delete pPageTextFrameIdxs;
    delete pPageGraphicIdxs;
    delete pPageEmbeddedIdxs;
    delete pPageShapeIdxs;
    delete pFrameTextFrameIdxs;
    delete pFrameGraphicIdxs;
    delete pFrameEmbeddedIdxs;
    delete pFrameShapeIdxs;
#ifndef PRODUCT
    txtparae_bContainsIllegalCharacters = sal_False;
#endif
}

SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateShapeExtPropMapper(
        SvXMLExport& rExport )
{
    UniReference < XMLPropertySetMapper > xPropMapper =
        new XMLTextPropertySetMapper( TEXT_PROP_MAP_SHAPE );
    return new XMLTextExportPropertySetMapper( xPropMapper, rExport );
}

SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateCharExtPropMapper(
        SvXMLExport& rExport)
{
    XMLPropertySetMapper *pPropMapper =
        new XMLTextPropertySetMapper( TEXT_PROP_MAP_TEXT );
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
}

SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaExtPropMapper(
        SvXMLExport& rExport)
{
    XMLPropertySetMapper *pPropMapper =
        new XMLTextPropertySetMapper( TEXT_PROP_MAP_SHAPE_PARA );
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
}

SvXMLExportPropertyMapper *XMLTextParagraphExport::CreateParaDefaultExtPropMapper(
        SvXMLExport& rExport)
{
    XMLPropertySetMapper *pPropMapper =
        new XMLTextPropertySetMapper( TEXT_PROP_MAP_TEXT_ADDITIONAL_DEFAULTS );
    return new XMLTextExportPropertySetMapper( pPropMapper, rExport );
}

void XMLTextParagraphExport::collectFrames()
{
    collectFrames( sal_False );
}

void XMLTextParagraphExport::collectFrames( sal_Bool bBoundToFrameOnly )
{
    Reference < XTextFramesSupplier > xTFS( GetExport().GetModel(), UNO_QUERY );
    if( xTFS.is() )
    {
        xTextFrames.set( xTFS->getTextFrames(), uno::UNO_QUERY);
        sal_Int32 nCount =  xTextFrames->getCount();
        for( sal_Int32 i = 0; i < nCount; i++ )
        {
            Reference < XPropertySet > xPropSet( xTextFrames->getByIndex( i ), UNO_QUERY );

            TextContentAnchorType eAnchor;
            xPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;

            switch( eAnchor )
            {
            case TextContentAnchorType_AT_PAGE:
                if( !bBoundToFrameOnly )
                {
                    if( !pPageTextFrameIdxs )
                        pPageTextFrameIdxs = new SvLongs;
                    pPageTextFrameIdxs->Insert( i, pPageTextFrameIdxs->Count() );
                }
                break;
            case TextContentAnchorType_AT_FRAME:
                if( !pFrameTextFrameIdxs )
                    pFrameTextFrameIdxs = new SvLongs;
                pFrameTextFrameIdxs->Insert( i, pFrameTextFrameIdxs->Count() );
                break;
            }
        }
    }

    Reference < XTextGraphicObjectsSupplier > xTGOS( GetExport().GetModel(),
                                                    UNO_QUERY );
    if( xTGOS.is() )
    {
        xGraphics.set( xTGOS->getGraphicObjects(),
                                                  UNO_QUERY );
        sal_Int32 nCount =  xGraphics->getCount();
        for( sal_Int32 i = 0; i < nCount; i++ )
        {
            Reference < XPropertySet > xPropSet( xGraphics->getByIndex( i ), UNO_QUERY );

            TextContentAnchorType eAnchor;
            xPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;

            switch( eAnchor )
            {
            case TextContentAnchorType_AT_PAGE:
                if( !bBoundToFrameOnly )
                {
                    if( !pPageGraphicIdxs )
                        pPageGraphicIdxs = new SvLongs;
                    pPageGraphicIdxs->Insert( i, pPageGraphicIdxs->Count() );
                }
                break;
            case TextContentAnchorType_AT_FRAME:
                if( !pFrameGraphicIdxs )
                    pFrameGraphicIdxs = new SvLongs;
                pFrameGraphicIdxs->Insert( i, pFrameGraphicIdxs->Count() );
                break;
            }
        }
    }

    Reference < XTextEmbeddedObjectsSupplier > xTEOS( GetExport().GetModel(),
                                                    UNO_QUERY );
    if( xTEOS.is() )
    {
        xEmbeddeds = Reference < XIndexAccess >( xTEOS->getEmbeddedObjects(),
                                                  UNO_QUERY );
        sal_Int32 nCount =  xEmbeddeds->getCount();
        for( sal_Int32 i = 0; i < nCount; i++ )
        {
            Reference < XPropertySet > xPropSet( xEmbeddeds->getByIndex( i ), UNO_QUERY );

            TextContentAnchorType eAnchor;
            xPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;

            switch( eAnchor )
            {
            case TextContentAnchorType_AT_PAGE:
                if( !bBoundToFrameOnly )
                {
                    if( !pPageEmbeddedIdxs )
                        pPageEmbeddedIdxs = new SvLongs;
                    pPageEmbeddedIdxs->Insert( i, pPageEmbeddedIdxs->Count() );
                }
                break;
            case TextContentAnchorType_AT_FRAME:
                if( !pFrameEmbeddedIdxs )
                    pFrameEmbeddedIdxs = new SvLongs;
                pFrameEmbeddedIdxs->Insert( i, pFrameEmbeddedIdxs->Count() );
                break;
            }
        }
    }

    Reference < XDrawPageSupplier > xDPS( GetExport().GetModel(),
                                                    UNO_QUERY );
    if( xDPS.is() )
    {
        xShapes = Reference < XIndexAccess >( xDPS->getDrawPage(),
                                                  UNO_QUERY );
        sal_Int32 nCount =  xShapes->getCount();
        for( sal_Int32 i = 0; i < nCount; i++ )
        {
            Reference < XShape > xShape(xShapes->getByIndex( i ), uno::UNO_QUERY);
            if( !xShape.is() )
                continue;

            Reference < XPropertySet > xPropSet( xShape, UNO_QUERY );

            TextContentAnchorType eAnchor;
            xPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;

            if( (TextContentAnchorType_AT_PAGE != eAnchor &&
                 TextContentAnchorType_AT_FRAME != eAnchor) ||
                 (TextContentAnchorType_AT_PAGE == eAnchor &&
                 bBoundToFrameOnly ) )
                continue;

            Reference<XServiceInfo> xServiceInfo( xShape,
                                                  UNO_QUERY );
            if( xServiceInfo->supportsService( sTextFrameService ) ||
                  xServiceInfo->supportsService( sTextGraphicService ) ||
                xServiceInfo->supportsService( sTextEmbeddedService ) )
                continue;

            if( TextContentAnchorType_AT_PAGE == eAnchor )
            {
                if( !pPageShapeIdxs )
                    pPageShapeIdxs = new SvLongs;
                pPageShapeIdxs->Insert( i, pPageShapeIdxs->Count() );
            }
            else
            {
                if( !pFrameShapeIdxs )
                    pFrameShapeIdxs = new SvLongs;
                pFrameShapeIdxs->Insert( i, pFrameShapeIdxs->Count() );
            }
        }
    }
}

void XMLTextParagraphExport::exportPageFrames( sal_Bool bAutoStyles,
                                               sal_Bool bProgress )
{
    if( pPageTextFrameIdxs )
    {
        for( sal_uInt16 i = 0; i < pPageTextFrameIdxs->Count(); i++ )
        {
            Reference < XTextContent > xTxtCntnt( xTextFrames->getByIndex( (*pPageTextFrameIdxs)[i] ), UNO_QUERY );
            exportTextFrame( xTxtCntnt, bAutoStyles, bProgress );
        }
    }
    if( pPageGraphicIdxs )
    {
        for( sal_uInt16 i = 0; i < pPageGraphicIdxs->Count(); i++ )
        {
            Reference < XTextContent > xTxtCntnt(xGraphics->getByIndex( (*pPageGraphicIdxs)[i] ), uno::UNO_QUERY);
            exportTextGraphic( xTxtCntnt, bAutoStyles );
        }
    }
    if( pPageEmbeddedIdxs )
    {
        for( sal_uInt16 i = 0; i < pPageEmbeddedIdxs->Count(); i++ )
        {
            Reference < XTextContent > xTxtCntnt(xEmbeddeds->getByIndex( (*pPageEmbeddedIdxs)[i] ), uno::UNO_QUERY);
            exportTextEmbedded( xTxtCntnt, bAutoStyles );
        }
    }
    if( pPageShapeIdxs )
    {
        for( sal_uInt16 i = 0; i < pPageShapeIdxs->Count(); i++ )
        {
            Reference < XTextContent > xTxtCntnt( xShapes->getByIndex( (*pPageShapeIdxs)[i] ), UNO_QUERY );
            exportShape( xTxtCntnt, bAutoStyles );
        }
    }
}

sal_Bool lcl_txtpara_isFrameAnchor(
        const Reference < XPropertySet > rPropSet,
        const Reference < XTextFrame >& rParentTxtFrame )
{
    Reference < XTextFrame > xAnchorTxtFrame(rPropSet->getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM("AnchorFrame") ) ), uno::UNO_QUERY);

    return xAnchorTxtFrame == rParentTxtFrame;
}

void XMLTextParagraphExport::exportFrameFrames(
        sal_Bool bAutoStyles,
        sal_Bool bProgress,
        const Reference < XTextFrame > *pParentTxtFrame )
{
    if( pFrameTextFrameIdxs && pFrameTextFrameIdxs->Count() )
    {
        sal_uInt16 i = 0;
        while( i < pFrameTextFrameIdxs->Count() )
        {
            Reference < XPropertySet > xPropSet( xTextFrames->getByIndex( (*pFrameTextFrameIdxs)[i] ), UNO_QUERY );
            if( lcl_txtpara_isFrameAnchor( xPropSet, *pParentTxtFrame ) )
            {
                if( !bAutoStyles )
                    pFrameTextFrameIdxs->Remove( i );
                sal_uInt16 nOldCount = pFrameTextFrameIdxs->Count();
                Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY );
                exportTextFrame( xTxtCntnt, bAutoStyles, bProgress );
                if( bAutoStyles )
                    i++;
                else if( pFrameTextFrameIdxs->Count() != nOldCount )
                    i = 0;
            }
            else
                i++;
        }
    }
    if( pFrameGraphicIdxs && pFrameGraphicIdxs->Count() )
    {
        Any aAny;
        sal_uInt16 i = 0;
        while( i < pFrameGraphicIdxs->Count() )
        {
            Reference < XPropertySet > xPropSet( xGraphics->getByIndex( (*pFrameGraphicIdxs)[i] ), UNO_QUERY );
            if( lcl_txtpara_isFrameAnchor( xPropSet, *pParentTxtFrame ) )
            {
                if( !bAutoStyles )
                    pFrameGraphicIdxs->Remove( i );
                sal_uInt16 nOldCount = pFrameGraphicIdxs->Count();
                Reference < XTextContent > xTxtCntnt(xPropSet, uno::UNO_QUERY);
                exportTextGraphic( xTxtCntnt, bAutoStyles );
                if( bAutoStyles )
                    i++;
                else if( pFrameGraphicIdxs->Count() != nOldCount )
                    i = 0;
            }
            else
                i++;
        }
    }
    if( pFrameEmbeddedIdxs && pFrameEmbeddedIdxs->Count() )
    {
        Any aAny;
        sal_uInt16 i = 0;
        while( i < pFrameEmbeddedIdxs->Count() )
        {
            Reference < XPropertySet > xPropSet( xEmbeddeds->getByIndex( (*pFrameEmbeddedIdxs)[i] ), UNO_QUERY );
            if( lcl_txtpara_isFrameAnchor( xPropSet, *pParentTxtFrame ) )
            {
                if( !bAutoStyles )
                    pFrameEmbeddedIdxs->Remove( i );
                sal_uInt16 nOldCount = pFrameEmbeddedIdxs->Count();
                Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY );
                exportTextEmbedded( xTxtCntnt, bAutoStyles );
                if( bAutoStyles )
                    i++;
                else if( pFrameEmbeddedIdxs->Count() != nOldCount )
                    i = 0;
            }
            else
                i++;
        }
    }
    if( pFrameShapeIdxs && pFrameShapeIdxs->Count() )
    {
        Any aAny;
        sal_uInt16 i = 0;
        while( i < pFrameShapeIdxs->Count() )
        {
            Reference < XPropertySet > xPropSet( xShapes->getByIndex( (*pFrameShapeIdxs)[i] ), UNO_QUERY );
            if( lcl_txtpara_isFrameAnchor( xPropSet, *pParentTxtFrame ) )
            {
                if( !bAutoStyles )
                    pFrameShapeIdxs->Remove( i );
                sal_uInt16 nOldCount = pFrameShapeIdxs->Count();
                Reference < XTextContent > xTxtCntnt( xPropSet, UNO_QUERY );
                exportShape( xTxtCntnt, bAutoStyles );
                if( bAutoStyles )
                    i++;
                else if( pFrameShapeIdxs->Count() != nOldCount )
                    i = 0;
            }
            else
                i++;
        }
    }
}

void XMLTextParagraphExport::exportText(
        const Reference < XText > & rText,
        sal_Bool bAutoStyles,
        sal_Bool bProgress,
        sal_Bool bExportParagraph )
{
    if( bAutoStyles )
        GetExport().GetShapeExport(); // make sure the graphics styles family
                                      // is added
    Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
    Reference < XEnumeration > xParaEnum(xEA->createEnumeration());
    Reference < XPropertySet > xPropertySet( rText, UNO_QUERY );
    Reference < XTextSection > xBaseSection;

    // #97718# footnotes don't supply paragraph enumerations in some cases
    // This is always a bug, but at least we don't want to crash.
    DBG_ASSERT( xParaEnum.is(), "We need a paragraph enumeration" );
    if( ! xParaEnum.is() )
        return;

    sal_Bool bExportLevels = sal_True;

    if (xPropertySet.is())
    {
        Reference < XPropertySetInfo > xInfo ( xPropertySet->getPropertySetInfo() );

        if( xInfo.is() )
        {
            if (xInfo->hasPropertyByName( sTextSection ))
            {
                xPropertySet->getPropertyValue(sTextSection) >>= xBaseSection ;
            }

            // for applications that use the outliner we need to check if
            // the current text object needs the level information exported
            if( !bAutoStyles )
            {
                // fixme: move string to class member, couldn't do now because
                //        of no incompatible build
                OUString sHasLevels( RTL_CONSTASCII_USTRINGPARAM("HasLevels") );
                if (xInfo->hasPropertyByName( sHasLevels ) )
                {
                    xPropertySet->getPropertyValue(sHasLevels) >>= bExportLevels;
                }
            }
        }
    }

    // #96530# Export redlines at start & end of XText before & after
    // exporting the text content enumeration
    if( !bAutoStyles && (pRedlineExport != NULL) )
        pRedlineExport->ExportStartOrEndRedline( xPropertySet, sal_True );
    exportTextContentEnumeration( xParaEnum, bAutoStyles, xBaseSection,
                                  bProgress, bExportParagraph, 0, bExportLevels );
    if( !bAutoStyles && (pRedlineExport != NULL) )
        pRedlineExport->ExportStartOrEndRedline( xPropertySet, sal_False );
}

void XMLTextParagraphExport::exportText(
        const Reference < XText > & rText,
        const Reference < XTextSection > & rBaseSection,
        sal_Bool bAutoStyles,
        sal_Bool bProgress,
        sal_Bool bExportParagraph )
{
    if( bAutoStyles )
        GetExport().GetShapeExport(); // make sure the graphics styles family
                                      // is added
    Reference < XEnumerationAccess > xEA( rText, UNO_QUERY );
    Reference < XEnumeration > xParaEnum(xEA->createEnumeration());

    // #98165# don't continue without a paragraph enumeration
    if( ! xParaEnum.is() )
        return;

    // #96530# Export redlines at start & end of XText before & after
    // exporting the text content enumeration
    Reference<XPropertySet> xPropertySet;
    if( !bAutoStyles && (pRedlineExport != NULL) )
    {
        xPropertySet.set(rText, uno::UNO_QUERY );
        pRedlineExport->ExportStartOrEndRedline( xPropertySet, sal_True );
    }
    exportTextContentEnumeration( xParaEnum, bAutoStyles, rBaseSection,
                                  bProgress, bExportParagraph );
    if( !bAutoStyles && (pRedlineExport != NULL) )
        pRedlineExport->ExportStartOrEndRedline( xPropertySet, sal_False );
}

sal_Bool XMLTextParagraphExport::exportTextContentEnumeration(
        const Reference < XEnumeration > & rContEnum,
        sal_Bool bAutoStyles,
        const Reference < XTextSection > & rBaseSection,
        sal_Bool bProgress,
        sal_Bool bExportParagraph,
        const Reference < XPropertySet > *pRangePropSet,
        sal_Bool bExportLevels)
{
    DBG_ASSERT( rContEnum.is(), "No enumeration to export!" );
    sal_Bool bHasMoreElements = rContEnum->hasMoreElements();
    if( !bHasMoreElements )
        return sal_False;

    XMLTextNumRuleInfo aPrevNumInfo;
    XMLTextNumRuleInfo aNextNumInfo;

    sal_Bool bHasContent sal_False;
    Reference<XTextSection> xCurrentTextSection(rBaseSection);

    MultiPropertySetHelper aPropSetHelper(
                               bAutoStyles ? aParagraphPropertyNamesAuto :
                                          aParagraphPropertyNames );

    sal_Bool bHoldElement = sal_False;
    Reference < XTextContent > xTxtCntnt;
    while( bHoldElement || bHasMoreElements )
    {
        if (bHoldElement)
        {
            bHoldElement = sal_False;
        }
        else
        {
            xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);

            aPropSetHelper.resetValues();

        }

        Reference<XServiceInfo> xServiceInfo( xTxtCntnt, UNO_QUERY );
        if( xServiceInfo->supportsService( sParagraphService ) )
        {
            if( bExportLevels )
            {
                if( bAutoStyles )
                {
                    exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
                                                aPrevNumInfo, aNextNumInfo,
                                                bAutoStyles );
                }
                else
                {
                    aNextNumInfo.Set( xTxtCntnt );

                    exportListAndSectionChange( xCurrentTextSection, aPropSetHelper,
                                                TEXT_SECTION, xTxtCntnt,
                                                aPrevNumInfo, aNextNumInfo,
                                                bAutoStyles );
                }
            }

            // if we found a mute section: skip all section content
            if (pSectionExport->IsMuteSection(xCurrentTextSection))
            {
                // Make sure headings are exported anyway.
                if( !bAutoStyles )
                    pSectionExport->ExportMasterDocHeadingDummies();

                while (rContEnum->hasMoreElements() &&
                       pSectionExport->IsInSection( xCurrentTextSection,
                                                    xTxtCntnt, sal_True ))
                {
                    xTxtCntnt.set(rContEnum->nextElement(), uno::UNO_QUERY);
                    aPropSetHelper.resetValues();
                    aNextNumInfo.Reset();
                }
                // the first non-mute element still needs to be processed
                bHoldElement =
                    ! pSectionExport->IsInSection( xCurrentTextSection,
                                                   xTxtCntnt, sal_False );
            }
            else
                exportParagraph( xTxtCntnt, bAutoStyles, bProgress,
                                 bExportParagraph, aPropSetHelper );
            bHasContent = sal_True;
        }
        else if( xServiceInfo->supportsService( sTableService ) )
        {
            if( !bAutoStyles )
            {
                aNextNumInfo.Reset();
            }

            exportListAndSectionChange( xCurrentTextSection, xTxtCntnt,
                                        aPrevNumInfo, aNextNumInfo,
                                        bAutoStyles );

            if (! pSectionExport->IsMuteSection(xCurrentTextSection))
            {
                // export start + end redlines (for wholly redlined tables)
                if ((! bAutoStyles) && (NULL != pRedlineExport))
                    pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, sal_True);

                exportTable( xTxtCntnt, bAutoStyles, bProgress  );

                if ((! bAutoStyles) && (NULL != pRedlineExport))
                    pRedlineExport->ExportStartOrEndRedline(xTxtCntnt, sal_False);
            }
            else if( !bAutoStyles )
            {
                // Make sure headings are exported anyway.
                pSectionExport->ExportMasterDocHeadingDummies();
            }

            bHasContent = sal_True;
        }
        else if( xServiceInfo->supportsService( sTextFrameService ) )
        {
            exportTextFrame( xTxtCntnt, bAutoStyles, bProgress, pRangePropSet );
        }
        else if( xServiceInfo->supportsService( sTextGraphicService ) )
        {
            exportTextGraphic( xTxtCntnt, bAutoStyles, pRangePropSet );
        }
        else if( xServiceInfo->supportsService( sTextEmbeddedService ) )
        {
            exportTextEmbedded( xTxtCntnt, bAutoStyles, pRangePropSet );
        }
        else if( xServiceInfo->supportsService( sShapeService ) )
        {
            exportShape( xTxtCntnt, bAutoStyles, pRangePropSet );
        }
        else
        {
            DBG_ASSERT( !xTxtCntnt.is(), "unknown text content" );
        }

        if( !bAutoStyles )
        {
            aPrevNumInfo = aNextNumInfo;
        }

        bHasMoreElements = rContEnum->hasMoreElements();
    }

    if( bExportLevels && bHasContent && !bAutoStyles )
    {
        aNextNumInfo.Reset();

        // close open lists and sections; no new styles
        exportListAndSectionChange( xCurrentTextSection, rBaseSection,
                                    aPrevNumInfo, aNextNumInfo,
                                    bAutoStyles );
    }

    return sal_True;
}

void XMLTextParagraphExport::exportParagraph(
        const Reference < XTextContent > & rTextContent,
        sal_Bool bAutoStyles, sal_Bool bProgress, sal_Bool bExportParagraph,
        MultiPropertySetHelper& rPropSetHelper)
{
    sal_Int8 nOutlineLevel = -1;

    if( bProgress )
    {
        ProgressBarHelper *pProgress = GetExport().GetProgressBarHelper();
            pProgress->SetValue( pProgress->GetValue()+1 );
    }

    // get property set or multi property set and initialize helper
    Reference<XMultiPropertySet> xMultiPropSet( rTextContent, UNO_QUERY );
    Reference<XPropertySet> xPropSet( rTextContent, UNO_QUERY );

    // check for supported properties
    if( !rPropSetHelper.checkedProperties() )
        rPropSetHelper.hasProperties( xPropSet->getPropertySetInfo() );

//  if( xMultiPropSet.is() )
//      rPropSetHelper.getValues( xMultiPropSet );
//  else
//      rPropSetHelper.getValues( xPropSet );

    if( bExportParagraph )
    {
        if( bAutoStyles )
        {
            Add( XML_STYLE_FAMILY_TEXT_PARAGRAPH, rPropSetHelper, xPropSet );
        }
        else
        {
            OUString sStyle;
            if( rPropSetHelper.hasProperty( PARA_STYLE_NAME ) )
            {
                if( xMultiPropSet.is() )
                    rPropSetHelper.getValue( PARA_STYLE_NAME,
                                                    xMultiPropSet ) >>= sStyle;
                else
                    rPropSetHelper.getValue( PARA_STYLE_NAME,
                                                    xPropSet ) >>= sStyle;
            }

            Reference< XInterface > xRef( rTextContent, UNO_QUERY );
            if( xRef.is() )
            {
                const OUString& rIdentifier = GetExport().getInterfaceToIdentifierMapper().getIdentifier( xRef );
                if( rIdentifier.getLength() )
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ID, rIdentifier );
            }

            OUString sAutoStyle( sStyle );
            sAutoStyle = Find( XML_STYLE_FAMILY_TEXT_PARAGRAPH, xPropSet, sStyle );
            if( sAutoStyle.getLength() )
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                              GetExport().EncodeStyleName( sAutoStyle ) );

            if( rPropSetHelper.hasProperty( PARA_CONDITIONAL_STYLE_NAME ) )
            {
                OUString sCondStyle;
                if( xMultiPropSet.is() )
                    rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
                                                     xMultiPropSet ) >>= sCondStyle;
                else
                    rPropSetHelper.getValue( PARA_CONDITIONAL_STYLE_NAME,
                                                     xPropSet ) >>= sCondStyle;
                if( sCondStyle != sStyle )
                {
                    sCondStyle = Find( XML_STYLE_FAMILY_TEXT_PARAGRAPH, xPropSet,
                                          sCondStyle );
                    if( sCondStyle.getLength() )
                        GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                                  XML_COND_STYLE_NAME,
                              GetExport().EncodeStyleName( sCondStyle ) );
                }
            }

            if( rPropSetHelper.hasProperty( PARA_CHAPTER_NUMERBING_LEVEL ) )
            {
                if( xMultiPropSet.is() )
                    rPropSetHelper.getValue( PARA_CHAPTER_NUMERBING_LEVEL,
                                                     xMultiPropSet ) >>= nOutlineLevel;
                else
                    rPropSetHelper.getValue( PARA_CHAPTER_NUMERBING_LEVEL,
                                                     xPropSet ) >>= nOutlineLevel;

                if( -1 != nOutlineLevel )
                {
                    OUStringBuffer sTmp;
                    sTmp.append( (sal_Int32)nOutlineLevel+1L );
                    GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                              XML_OUTLINE_LEVEL,
                                  sTmp.makeStringAndClear() );

                    if( rPropSetHelper.hasProperty( NUMBERING_IS_NUMBER ) )
                    {
                        bool bIsNumber;
                        if( xMultiPropSet.is() )
                            rPropSetHelper.getValue(
                                       NUMBERING_IS_NUMBER, xMultiPropSet ) >>= bIsNumber;
                        else
                            rPropSetHelper.getValue(
                                       NUMBERING_IS_NUMBER, xPropSet ) >>= bIsNumber;

                        if( ! bIsNumber )
                            GetExport().AddAttribute( XML_NAMESPACE_TEXT,
                                                      XML_IS_LIST_HEADER,
                                                      XML_TRUE );
                    }
                }
            }
        }
    }

    Reference < XEnumerationAccess > xEA( rTextContent, UNO_QUERY );
    Reference < XEnumeration > xTextEnum(xEA->createEnumeration());

    Reference < XEnumeration> xContentEnum;
    Reference < XContentEnumerationAccess > xCEA( rTextContent, UNO_QUERY );
    if( xCEA.is() )
        xContentEnum.set(xCEA->createContentEnumeration( sTextContentService ));
    sal_Bool bHasContentEnum = xContentEnum.is() &&
                                  xContentEnum->hasMoreElements();

    Reference < XTextSection > xSection;
    if( bHasContentEnum )
    {
        // For the auto styles, the multi property set helper is only used
        // if hard attributes are existing. Therfor, it seems to be a better
        // strategy to have the TextSection property seperate, because otherwise
        // we always retrieve the style names even if they are not required.
        if( bAutoStyles )
        {
            if( xPropSet->getPropertySetInfo()->hasPropertyByName( sTextSection ) )
            {
                xSection.set(xPropSet->getPropertyValue( sTextSection ), uno::UNO_QUERY);
            }
        }
        else
        {
            if( rPropSetHelper.hasProperty( TEXT_SECTION ) )
            {
                xSection.set(rPropSetHelper.getValue( TEXT_SECTION ), uno::UNO_QUERY);
            }
        }
    }

    if( bAutoStyles )
    {
        sal_Bool bPrevCharIsSpace = sal_True;
        if( bHasContentEnum )
            bPrevCharIsSpace = !exportTextContentEnumeration(
                                    xContentEnum, bAutoStyles, xSection,
                                    bProgress );
        exportTextRangeEnumeration( xTextEnum, bAutoStyles, bProgress );
    }
    else
    {
        sal_Bool bPrevCharIsSpace = sal_True;
        enum XMLTokenEnum eElem =
            -1 == nOutlineLevel ? XML_P : XML_H;
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, eElem,
                                  sal_True, sal_False );
        if( bHasContentEnum )
            bPrevCharIsSpace = !exportTextContentEnumeration(
                                    xContentEnum, bAutoStyles, xSection,
                                    bProgress );
        exportTextRangeEnumeration( xTextEnum, bAutoStyles, bProgress,
                                     bPrevCharIsSpace );
    }
}

// bookmarks, reference marks (and TOC marks) are the same except for the
// element names. We use the same method for export and it an array with
// the proper element names
static const enum XMLTokenEnum lcl_XmlReferenceElements[] = {
    XML_REFERENCE_MARK, XML_REFERENCE_MARK_START, XML_REFERENCE_MARK_END };
static const enum XMLTokenEnum lcl_XmlBookmarkElements[] = {
    XML_BOOKMARK, XML_BOOKMARK_START, XML_BOOKMARK_END };


void XMLTextParagraphExport::exportTextRangeEnumeration(
        const Reference < XEnumeration > & rTextEnum,
        sal_Bool bAutoStyles, sal_Bool bProgress,
        sal_Bool bPrvChrIsSpc )
{
    sal_Bool bPrevCharIsSpace = bPrvChrIsSpc;

    while( rTextEnum->hasMoreElements() )
    {
        Reference<XPropertySet> xPropSet(rTextEnum->nextElement(), UNO_QUERY);
        Reference < XTextRange > xTxtRange(xPropSet, uno::UNO_QUERY);
        Reference<XPropertySetInfo> xPropInfo(xPropSet->getPropertySetInfo());

        if (xPropInfo->hasPropertyByName(sTextPortionType))
        {
            rtl::OUString sType;
            xPropSet->getPropertyValue(sTextPortionType) >>= sType;

            if( sType.equals(sText))
            {
                exportTextRange( xTxtRange, bAutoStyles,
                                 bPrevCharIsSpace );
            }
            else if( sType.equals(sTextField))
            {
                exportTextField( xTxtRange, bAutoStyles );
                bPrevCharIsSpace = sal_False;
            }
            else if( sType.equals( sFrame ) )
            {
                Reference < XEnumeration> xContentEnum;
                Reference < XContentEnumerationAccess > xCEA( xTxtRange,
                                                              UNO_QUERY );
                if( xCEA.is() )
                    xContentEnum.set(xCEA->createContentEnumeration(
                                                    sTextContentService ));
                // frames are never in sections
                Reference<XTextSection> xSection;
                if( xContentEnum.is() )
                    exportTextContentEnumeration( xContentEnum,
                                                    bAutoStyles,
                                                    xSection, bProgress, sal_True,
                                                     &xPropSet  );

                bPrevCharIsSpace = sal_False;
            }
            else if (sType.equals(sFootnote))
            {
                exportTextFootnote(xPropSet,
                                   xTxtRange->getString(),
                                   bAutoStyles, bProgress );
                bPrevCharIsSpace = sal_False;
            }
            else if (sType.equals(sBookmark))
            {
                exportTextMark(xPropSet,
                               sBookmark,
                               lcl_XmlBookmarkElements,
                               bAutoStyles);
            }
            else if (sType.equals(sReferenceMark))
            {
                exportTextMark(xPropSet,
                               sReferenceMark,
                               lcl_XmlReferenceElements,
                               bAutoStyles);
            }
            else if (sType.equals(sDocumentIndexMark))
            {
                pIndexMarkExport->ExportIndexMark(xPropSet, bAutoStyles);
            }
            else if (sType.equals(sRedline))
            {
                if (NULL != pRedlineExport)
                    pRedlineExport->ExportChange(xPropSet, bAutoStyles);
            }
            else if (sType.equals(sRuby))
            {
                exportRuby(xPropSet, bAutoStyles);
            }
            else
                DBG_ERROR("unknown text portion type");
        }
        else
        {
            Reference<XServiceInfo> xServiceInfo( xTxtRange, UNO_QUERY );
            if( xServiceInfo->supportsService( sTextFieldService ) )
            {
                exportTextField( xTxtRange, bAutoStyles );
                bPrevCharIsSpace = sal_False;
            }
            else
            {
                // no TextPortionType property -> non-Writer app -> text
                exportTextRange( xTxtRange, bAutoStyles, bPrevCharIsSpace );
            }
        }
    }

    DBG_ASSERT( !bOpenRuby, "Red Alert: Ruby still open!" );
}

void XMLTextParagraphExport::exportTable(
        const Reference < XTextContent > & rTextContent,
        sal_Bool bAutoStyles, sal_Bool bProgress )
{
}

void XMLTextParagraphExport::exportTextField(
        const Reference < XTextRange > & rTextRange,
        sal_Bool bAutoStyles )
{
    Reference < XPropertySet > xPropSet( rTextRange, UNO_QUERY );
    // non-Writer apps need not support Property TextField, so test first
    if (xPropSet->getPropertySetInfo()->hasPropertyByName( sTextField ))
    {
        Reference < XTextField > xTxtFld(xPropSet->getPropertyValue( sTextField ), uno::UNO_QUERY);
        DBG_ASSERT( xTxtFld.is(), "text field missing" );
        if( xTxtFld.is() )
        {
            if( bAutoStyles )
            {
                pFieldExport->ExportFieldAutoStyle( xTxtFld );
            }
            else
            {
                pFieldExport->ExportField( xTxtFld );
            }
        }
        else
        {
            // write only characters
            GetExport().Characters(rTextRange->getString());
        }

    }
}

void XMLTextParagraphExport::exportTextMark(
    const Reference<XPropertySet> & rPropSet,
    const OUString sProperty,
    const enum XMLTokenEnum pElements[],
    sal_Bool bAutoStyles)
{
    // mib said: "Hau wech!"
    //
    // (Originally, I'd export a span element in case the (book|reference)mark
    //  was formatted. This actually makes a difference in case some pervert
    //  sets a point reference mark in the document and, say, formats it bold.
    //  This basically meaningless formatting will now been thrown away
    //  (aka cleaned up), since mib said: ...                   dvo

     if (!bAutoStyles)
    {
        // name element
        Reference<XNamed> xName(rPropSet->getPropertyValue(sProperty), UNO_QUERY);
        GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME,
                                 xName->getName());

        // start, end, or point-reference?
        sal_Int8 nElement;
        if( *(sal_Bool *)rPropSet->getPropertyValue(sIsCollapsed).getValue() )
        {
            nElement = 0;
        }
        else
        {
            nElement = *(sal_Bool *)rPropSet->getPropertyValue(sIsStart).getValue() ? 1 : 2;
        }

        // export element
        DBG_ASSERT(pElements != NULL, "illegal element array");
        DBG_ASSERT(nElement >= 0, "illegal element number");
        DBG_ASSERT(nElement <= 2, "illegal element number");
        SvXMLElementExport aElem(GetExport(),
                                 XML_NAMESPACE_TEXT, pElements[nElement],
                                 sal_False, sal_False);
    }
    // else: no styles. (see above)
}

sal_Bool lcl_txtpara_isBoundAsChar(
        const Reference < XPropertySet > & rPropSet,
        const Reference < XPropertySetInfo > & rPropSetInfo )
{
    sal_Bool bIsBoundAsChar = sal_False;
    OUString sAnchorType( RTL_CONSTASCII_USTRINGPARAM( "AnchorType" ) );
    if( rPropSetInfo->hasPropertyByName( sAnchorType ) )
    {
        TextContentAnchorType eAnchor;
        rPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;
        bIsBoundAsChar = TextContentAnchorType_AS_CHARACTER == eAnchor;
    }

    return bIsBoundAsChar;
}

sal_Int32 XMLTextParagraphExport::addTextFrameAttributes(
    const Reference < XPropertySet >& rPropSet,
    sal_Bool bShape,
    OUString *pMinHeightValue )
{
    sal_Int32 nShapeFeatures = SEF_DEFAULT;

    // draw:name (#97662#: not for shapes, since those names will be
    // treated in the shape export)
    if( !bShape )
    {
        Reference < XNamed > xNamed( rPropSet, UNO_QUERY );
        if( xNamed.is() )
        {
            OUString sName( xNamed->getName() );
            if( sName.getLength() )
                GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_NAME,
                                          xNamed->getName() );
        }
    }

    OUStringBuffer sValue;

    // text:anchor-type
    TextContentAnchorType eAnchor = TextContentAnchorType_AT_PARAGRAPH;
    rPropSet->getPropertyValue( sAnchorType ) >>= eAnchor;
    {
        XMLAnchorTypePropHdl aAnchorTypeHdl;
        OUString sTmp;
        aAnchorTypeHdl.exportXML( sTmp, uno::makeAny(eAnchor),
                                  GetExport().GetMM100UnitConverter() );
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_TYPE, sTmp );
    }

    // text:anchor-page-number
    if( TextContentAnchorType_AT_PAGE == eAnchor )
    {
        sal_Int16 nPage;
        rPropSet->getPropertyValue( sAnchorPageNo ) >>= nPage;
        GetExport().GetMM100UnitConverter().convertNumber( sValue,
                                                           (sal_Int32)nPage );
        GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_ANCHOR_PAGE_NUMBER,
                                  sValue.makeStringAndClear() );
    }
    else
    {
        // #92210#
        nShapeFeatures |= SEF_EXPORT_NO_WS;
    }

    // OD 2004-06-01 #i27691# - correction: no export of svg:x, if object
    // is anchored as-character.
    if ( !bShape &&
         eAnchor != TextContentAnchorType_AS_CHARACTER )
    {
        // svg:x
        sal_Int16 nHoriOrient =  HoriOrientation::NONE;
        rPropSet->getPropertyValue( sHoriOrient ) >>= nHoriOrient;
        if( HoriOrientation::NONE == nHoriOrient )
        {
            sal_Int32 nPos = 0;
            rPropSet->getPropertyValue( sHoriOrientPosition ) >>= nPos;
            GetExport().GetMM100UnitConverter().convertMeasure( sValue, nPos );
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_X,
                                      sValue.makeStringAndClear() );
        }
    }
    else if( TextContentAnchorType_AS_CHARACTER == eAnchor )
        nShapeFeatures = (nShapeFeatures & ~SEF_EXPORT_X);

    if( !bShape || TextContentAnchorType_AS_CHARACTER == eAnchor  )
    {
        // svg:y
        sal_Int16 nVertOrient =  VertOrientation::NONE;
        rPropSet->getPropertyValue( sVertOrient ) >>= nVertOrient;
        if( VertOrientation::NONE == nVertOrient )
        {
            sal_Int32 nPos = 0;
            rPropSet->getPropertyValue( sVertOrientPosition ) >>= nPos;
            GetExport().GetMM100UnitConverter().convertMeasure( sValue, nPos );
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_Y,
                                      sValue.makeStringAndClear() );
        }
        if( bShape )
            nShapeFeatures = (nShapeFeatures & ~SEF_EXPORT_Y);
    }


    Reference< XPropertySetInfo > xPropSetInfo(rPropSet->getPropertySetInfo());

    // svg:width
    sal_Int16 nWidthType = SizeType::FIX;
    if( xPropSetInfo->hasPropertyByName( sWidthType ) )
    {
        rPropSet->getPropertyValue( sWidthType ) >>= nWidthType;
    }
    if( xPropSetInfo->hasPropertyByName( sWidth ) )
    {
        sal_Int32 nWidth =  0;
        // VAR size will be written as zero min-size
        if( SizeType::VARIABLE != nWidthType )
        {
            rPropSet->getPropertyValue( sWidth ) >>= nWidth;
        }
        GetExport().GetMM100UnitConverter().convertMeasure( sValue, nWidth );
        if( SizeType::FIX != nWidthType )
            GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_WIDTH,
                                      sValue.makeStringAndClear() );
        else
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
                                      sValue.makeStringAndClear() );
    }
    sal_Bool bSyncWidth = sal_False;
    if( xPropSetInfo->hasPropertyByName( sIsSyncWidthToHeight ) )
    {
        bSyncWidth = *(sal_Bool *)rPropSet->getPropertyValue( sIsSyncWidthToHeight ).getValue();
        if( bSyncWidth )
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
                                      XML_SCALE );
    }
    if( !bSyncWidth && xPropSetInfo->hasPropertyByName( sRelativeWidth ) )
    {
        sal_Int16 nRelWidth =  0;
        rPropSet->getPropertyValue( sRelativeWidth ) >>= nRelWidth;
        DBG_ASSERT( nRelWidth >= 0 && nRelWidth <= 254,
                    "Got illegal relative width from API" );
        if( nRelWidth > 0 )
        {
            GetExport().GetMM100UnitConverter().convertPercent( sValue,
                                                                nRelWidth );
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_WIDTH,
                                      sValue.makeStringAndClear() );
        }
    }

    // svg:height, fo:min-height or style:rel-height
    sal_Int16 nSizeType = SizeType::FIX;
    if( xPropSetInfo->hasPropertyByName( sSizeType ) )
    {
        rPropSet->getPropertyValue( sSizeType ) >>= nSizeType;
    }
    sal_Bool bSyncHeight = sal_False;
    if( xPropSetInfo->hasPropertyByName( sIsSyncHeightToWidth ) )
    {
        bSyncHeight = *(sal_Bool *)rPropSet->getPropertyValue( sIsSyncHeightToWidth ).getValue();
    }
    sal_Int16 nRelHeight =  0;
    if( !bSyncHeight && xPropSetInfo->hasPropertyByName( sRelativeHeight ) )
    {
        rPropSet->getPropertyValue( sRelativeHeight ) >>= nRelHeight;
    }
    if( xPropSetInfo->hasPropertyByName( sHeight ) )
    {
        sal_Int32 nHeight =  0;
        if( SizeType::VARIABLE != nSizeType )
        {
            rPropSet->getPropertyValue( sHeight ) >>= nHeight;
        }
        GetExport().GetMM100UnitConverter().convertMeasure( sValue,
                                                            nHeight );
        if( SizeType::FIX != nSizeType && 0==nRelHeight && !bSyncHeight &&
             pMinHeightValue )
            *pMinHeightValue = sValue.makeStringAndClear();
        else
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
                                      sValue.makeStringAndClear() );
    }
    if( bSyncHeight )
    {
        GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
                SizeType::MIN == nSizeType ? XML_SCALE_MIN : XML_SCALE );

    }
    else if( nRelHeight > 0 )
    {
        GetExport().GetMM100UnitConverter().convertPercent( sValue,
                                                            nRelHeight );
        if( SizeType::MIN == nSizeType )
            GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_HEIGHT,
                                      sValue.makeStringAndClear() );
        else
            GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_REL_HEIGHT,
                                      sValue.makeStringAndClear() );
    }

    OUString sZOrder( RTL_CONSTASCII_USTRINGPARAM( "ZOrder" ) );
    if( xPropSetInfo->hasPropertyByName( sZOrder ) )
    {
        sal_Int32 nZIndex;
        rPropSet->getPropertyValue( sZOrder ) >>= nZIndex;
        if( -1 != nZIndex )
        {
            GetExport().GetMM100UnitConverter().convertNumber( sValue,
                                                                nZIndex );
            GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_ZINDEX,
                                      sValue.makeStringAndClear() );
        }
    }

    return nShapeFeatures;
}

void XMLTextParagraphExport::exportAnyTextFrame(
        const Reference < XTextContent > & rTxtCntnt,
        FrameType eType,
        sal_Bool bAutoStyles,
        sal_Bool bProgress,
        const Reference < XPropertySet > *pRangePropSet)
{
    Reference < XPropertySet > xPropSet( rTxtCntnt, UNO_QUERY );

    if( bAutoStyles )
    {
        if( FT_EMBEDDED == eType )
            _collectTextEmbeddedAutoStyles( xPropSet );
        // --> OD 2004-08-09 #i28745# - no text frame style for shapes
        else if ( FT_SHAPE != eType )
            Add( XML_STYLE_FAMILY_TEXT_FRAME, xPropSet );
        // <--

        if( pRangePropSet && lcl_txtpara_isBoundAsChar( xPropSet,
                                            xPropSet->getPropertySetInfo() ) )
            Add( XML_STYLE_FAMILY_TEXT_TEXT, *pRangePropSet );

        switch( eType )
        {
        case FT_TEXT:
            {
                // frame bound frames
                Reference < XTextFrame > xTxtFrame( rTxtCntnt, UNO_QUERY );
                Reference < XText > xTxt(xTxtFrame->getText());
                collectFramesBoundToFrameAutoStyles( xTxtFrame, bProgress );

                exportText( xTxt, bAutoStyles, bProgress, sal_True );
            }
            break;
        case FT_SHAPE:
            {
                Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
                GetExport().GetShapeExport()->collectShapeAutoStyles( xShape );
            }
            break;
        }
    }
    else
    {
        Reference< XPropertySetInfo > xPropSetInfo(xPropSet->getPropertySetInfo());
        Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY );
        {
            sal_Bool bAddCharStyles = pRangePropSet &&
                lcl_txtpara_isBoundAsChar( xPropSet, xPropSetInfo );
            sal_Bool bIsUICharStyle;
            OUString sStyle;
            if( bAddCharStyles )
                   sStyle = FindTextStyle( *pRangePropSet, bIsUICharStyle );
            else
                bIsUICharStyle = sal_False;

            XMLTextCharStyleNamesElementExport aCharStylesExport(
                GetExport(), bIsUICharStyle &&
                             aCharStyleNamesPropInfoCache.hasProperty(
                                            *pRangePropSet ),
                *pRangePropSet, sCharStyleNames );

            if( sStyle.getLength() )
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                                  GetExport().EncodeStyleName( sStyle ) );
            {
                SvXMLElementExport aElem( GetExport(), sStyle.getLength() > 0,
                    XML_NAMESPACE_TEXT, XML_SPAN, sal_False, sal_False );
                {
                    SvXMLElementExport aElem( GetExport(),
                        FT_SHAPE != eType &&
                        addHyperlinkAttributes( xPropSet,
                                                xPropState,xPropSetInfo ),
                        XML_NAMESPACE_DRAW, XML_A, sal_False, sal_False );
                    switch( eType )
                    {
                    case FT_TEXT:
                        _exportTextFrame( xPropSet, xPropSetInfo, bProgress );
                        break;
                    case FT_GRAPHIC:
                        _exportTextGraphic( xPropSet, xPropSetInfo );
                        break;
                    case FT_EMBEDDED:
                        _exportTextEmbedded( xPropSet, xPropSetInfo );
                        break;
                    case FT_SHAPE:
                        {
                            Reference < XShape > xShape( rTxtCntnt, UNO_QUERY );
                            sal_Int32 nFeatures =
                                addTextFrameAttributes( xPropSet, sal_True );
                            GetExport().GetShapeExport()
                                ->exportShape( xShape, nFeatures );
                        }
                        break;
                    }
                }
            }
        }
    }
}

void XMLTextParagraphExport::_exportTextFrame(
        const Reference < XPropertySet > & rPropSet,
        const Reference < XPropertySetInfo > & rPropSetInfo,
        sal_Bool bProgress )
{
    Reference < XTextFrame > xTxtFrame( rPropSet, UNO_QUERY );
    Reference < XText > xTxt(xTxtFrame->getText());

    OUString sStyle;
    if( rPropSetInfo->hasPropertyByName( sFrameStyleName ) )
    {
        rPropSet->getPropertyValue( sFrameStyleName ) >>= sStyle;
    }

    OUString sAutoStyle( sStyle );
    OUString aMinHeightValue;
    sAutoStyle = Find( XML_STYLE_FAMILY_TEXT_FRAME, rPropSet, sStyle );
    if( sAutoStyle.getLength() )
        GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
                              GetExport().EncodeStyleName( sAutoStyle ) );
    addTextFrameAttributes( rPropSet, sal_False, &aMinHeightValue );

    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
                              XML_FRAME, sal_False, sal_True );

    if( aMinHeightValue.getLength() )
        GetExport().AddAttribute( XML_NAMESPACE_FO, XML_MIN_HEIGHT,
                                  aMinHeightValue );

    // draw:chain-next-name
    if( rPropSetInfo->hasPropertyByName( sChainNextName ) )
    {
        OUString sNext;
        if( (rPropSet->getPropertyValue( sChainNextName ) >>= sNext) && sNext.getLength() > 0 )
            GetExport().AddAttribute( XML_NAMESPACE_DRAW,
                                      XML_CHAIN_NEXT_NAME,
                                      sNext );
    }

    {
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
                                  XML_TEXT_BOX, sal_True, sal_True );

        // frame bound frames
        exportFramesBoundToFrame( xTxtFrame, bProgress );

        exportText( xTxt, sal_False, bProgress, sal_True );
    }

    // script:events
    Reference<XEventsSupplier> xEventsSupp( xTxtFrame, UNO_QUERY );
    GetExport().GetEventExport().Export(xEventsSupp);

    // image map
    GetExport().GetImageMapExport().Export( rPropSet );

}

void XMLTextParagraphExport::exportContour(
        const Reference < XPropertySet > & rPropSet,
        const Reference < XPropertySetInfo > & rPropSetInfo )
{
    if( !rPropSetInfo->hasPropertyByName( sContourPolyPolygon ) )
        return;

    PointSequenceSequence aSourcePolyPolygon;
    rPropSet->getPropertyValue( sContourPolyPolygon ) >>= aSourcePolyPolygon;

    if( !aSourcePolyPolygon.getLength() )
        return;

    awt::Point aPoint( 0, 0 );
    awt::Size aSize( 0, 0 );
    sal_Int32 nPolygons = aSourcePolyPolygon.getLength();
    const PointSequence *pPolygons = aSourcePolyPolygon.getConstArray();
    while( nPolygons-- )
    {
        sal_Int32 nPoints = pPolygons->getLength();
        const awt::Point *pPoints = pPolygons->getConstArray();
        while( nPoints-- )
        {
            if( aSize.Width < pPoints->X )
                aSize.Width = pPoints->X;
            if( aSize.Height < pPoints->Y )
                aSize.Height = pPoints->Y;
            pPoints++;
        }
        pPolygons++;
    }

    sal_Bool bPixel = sal_False;
    if( rPropSetInfo->hasPropertyByName( sIsPixelContour ) )
    {
        bPixel = *(sal_Bool *)rPropSet->getPropertyValue( sIsPixelContour ).getValue();
    }

    // svg: width
    OUStringBuffer aStringBuffer( 10 );
    if( bPixel )
        GetExport().GetMM100UnitConverter().convertMeasurePx(aStringBuffer, aSize.Width);
    else
        GetExport().GetMM100UnitConverter().convertMeasure(aStringBuffer, aSize.Width);
    GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_WIDTH,
                              aStringBuffer.makeStringAndClear() );

    // svg: height
    if( bPixel )
        GetExport().GetMM100UnitConverter().convertMeasurePx(aStringBuffer, aSize.Height);
    else
        GetExport().GetMM100UnitConverter().convertMeasure(aStringBuffer, aSize.Height);
    GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_HEIGHT,
                              aStringBuffer.makeStringAndClear() );

    // svg:viewbox
    SdXMLImExViewBox aViewBox(0, 0, aSize.Width, aSize.Height);
    GetExport().AddAttribute(XML_NAMESPACE_SVG, XML_VIEWBOX,
                aViewBox.GetExportString(GetExport().GetMM100UnitConverter()));

    sal_Int32 nOuterCnt( aSourcePolyPolygon.getLength() );

    enum XMLTokenEnum eElem = XML_TOKEN_INVALID;
    if( 1L == nOuterCnt )
    {
        // simple polygon shape, can be written as svg:points sequence
        /*const*/ PointSequence* pSequence =
                            (PointSequence*)aSourcePolyPolygon.getConstArray();

        SdXMLImExPointsElement aPoints( pSequence, aViewBox, aPoint,
                                aSize, GetExport().GetMM100UnitConverter() );

        // write point array
        GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_POINTS,
                                      aPoints.GetExportString());
        eElem = XML_CONTOUR_POLYGON;
    }
    else
    {
        // polypolygon, needs to be written as a svg:path sequence
        /*const*/ PointSequence* pOuterSequence =
                        (PointSequence*)aSourcePolyPolygon.getConstArray();
        if(pOuterSequence)
        {
            // prepare svx:d element export
            SdXMLImExSvgDElement aSvgDElement( aViewBox );

            for(sal_Int32 a(0L); a < nOuterCnt; a++)
            {
                /*const*/ PointSequence* pSequence = pOuterSequence++;
                if(pSequence)
                {
                    aSvgDElement.AddPolygon(pSequence, 0L, aPoint,
                        aSize, GetExport().GetMM100UnitConverter(),
                        sal_True );
                }
            }

            // write point array
            GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_D,
                                      aSvgDElement.GetExportString());
            eElem = XML_CONTOUR_PATH;
        }
    }

    if( rPropSetInfo->hasPropertyByName( sIsAutomaticContour ) )
    {
        if( *(sal_Bool *)rPropSet->getPropertyValue( sIsAutomaticContour ).getValue() )
            GetExport().AddAttribute( XML_NAMESPACE_DRAW,
                                      XML_RECREATE_ON_EDIT, XML_TRUE );
    }

    // write object now
    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW, eElem,
                              sal_True, sal_True );
}

void XMLTextParagraphExport::_exportTextGraphic(
        const Reference < XPropertySet > & rPropSet,
        const Reference < XPropertySetInfo > & rPropSetInfo )
{
    OUString sStyle;
    if( rPropSetInfo->hasPropertyByName( sFrameStyleName ) )
    {
        rPropSet->getPropertyValue( sFrameStyleName ) >>= sStyle;
    }

    OUString sAutoStyle( sStyle );
    sAutoStyle = Find( XML_STYLE_FAMILY_TEXT_FRAME, rPropSet, sStyle );
    if( sAutoStyle.getLength() )
        GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_STYLE_NAME,
                                  GetExport().EncodeStyleName( sAutoStyle ) );
    addTextFrameAttributes( rPropSet, sal_False );

    // svg:transform
    sal_Int16 nVal;
    rPropSet->getPropertyValue( sGraphicRotation ) >>= nVal;
    if( nVal != 0 )
    {
        OUStringBuffer sRet( GetXMLToken(XML_ROTATE).getLength()+4 );
        sRet.append( GetXMLToken(XML_ROTATE));
        sRet.append( (sal_Unicode)'(' );
        GetExport().GetMM100UnitConverter().convertNumber( sRet, (sal_Int32)nVal );
        sRet.append( (sal_Unicode)')' );
        GetExport().AddAttribute( XML_NAMESPACE_SVG, XML_TRANSFORM,
                                  sRet.makeStringAndClear() );
    }


    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
                              XML_FRAME, sal_False, sal_True );

    // xlink:href
    OUString sOrigURL;
    rPropSet->getPropertyValue( sGraphicURL ) >>= sOrigURL;
    OUString sURL(GetExport().AddEmbeddedGraphicObject( sOrigURL ));
    setTextEmbeddedGraphicURL( rPropSet, sURL );

    // If there still is no url, then then graphic is empty
    if( sURL.getLength() )
    {
        GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, sURL );
        GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, XML_EMBED );
        GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_ACTUATE,
                                                       XML_ONLOAD );
    }

    // draw:filter-name
    OUString sGrfFilter;
    rPropSet->getPropertyValue( sGraphicFilter ) >>= sGrfFilter;
    if( sGrfFilter.getLength() )
        GetExport().AddAttribute( XML_NAMESPACE_DRAW, XML_FILTER_NAME,
                                  sGrfFilter );

    {
        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_DRAW,
                                  XML_IMAGE, sal_False, sal_True );

        // optional office:binary-data
        GetExport().AddEmbeddedGraphicObjectAsBase64( sOrigURL );
    }

    // script:events
    Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
    GetExport().GetEventExport().Export(xEventsSupp);

    // image map
    GetExport().GetImageMapExport().Export( rPropSet );

    // svg:desc
    exportAlternativeText( rPropSet, rPropSetInfo );

    // draw:contour
    exportContour( rPropSet, rPropSetInfo );
}

void XMLTextParagraphExport::_collectTextEmbeddedAutoStyles(
        const Reference < XPropertySet > & rPropSet )
{
    DBG_ASSERT( !this, "no API implementation avialable" );
}

void XMLTextParagraphExport::_exportTextEmbedded(
        const Reference < XPropertySet > & rPropSet,
        const Reference < XPropertySetInfo > & rPropSetInfo )
{
    DBG_ASSERT( !this, "no API implementation avialable" );
}

void XMLTextParagraphExport::exportEvents( const Reference < XPropertySet > & rPropSet )
{
    // script:events
    Reference<XEventsSupplier> xEventsSupp( rPropSet, UNO_QUERY );
    GetExport().GetEventExport().Export(xEventsSupp);

    // image map
    OUString sImageMap(RTL_CONSTASCII_USTRINGPARAM("ImageMap"));
    if (rPropSet->getPropertySetInfo()->hasPropertyByName(sImageMap))
        GetExport().GetImageMapExport().Export( rPropSet );
}
void XMLTextParagraphExport::exportAlternativeText(
        const Reference < XPropertySet > & rPropSet,
        const Reference < XPropertySetInfo > & rPropSetInfo )
{
    // svg:desc
    if( rPropSetInfo->hasPropertyByName( sAlternativeText  ) )
    {
        OUString sAltText;
        rPropSet->getPropertyValue( sAlternativeText ) >>= sAltText;
        if( sAltText.getLength() )
        {
            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_SVG,
                                      XML_DESC, sal_True, sal_False );
            GetExport().Characters( sAltText );
        }
    }
}

void XMLTextParagraphExport::setTextEmbeddedGraphicURL(
    const Reference < XPropertySet >& rPropSet,
    OUString& rStreamName ) const
{
}

sal_Bool XMLTextParagraphExport::addHyperlinkAttributes(
        const Reference < XPropertySet > & rPropSet,
        const Reference < XPropertyState > & rPropState,
        const Reference < XPropertySetInfo > & rPropSetInfo )
{
    sal_Bool bExport = sal_False;
    OUString sHRef, sName, sTargetFrame, sUStyleName, sVStyleName;
    sal_Bool bServerMap = sal_False;

    if( rPropSetInfo->hasPropertyByName( sHyperLinkURL ) &&
        ( !rPropState.is() || PropertyState_DIRECT_VALUE ==
                    rPropState->getPropertyState( sHyperLinkURL ) ) )
    {
        rPropSet->getPropertyValue( sHyperLinkURL ) >>= sHRef;

        if( sHRef.getLength() > 0 )
            bExport = sal_True;
    }

    if( rPropSetInfo->hasPropertyByName( sHyperLinkName ) &&
        ( !rPropState.is() || PropertyState_DIRECT_VALUE ==
                    rPropState->getPropertyState( sHyperLinkName ) ) )
    {
        rPropSet->getPropertyValue( sHyperLinkName ) >>= sName;
        if( sName.getLength() > 0 )
            bExport = sal_True;
    }

    if( rPropSetInfo->hasPropertyByName( sHyperLinkTarget ) &&
        ( !rPropState.is() || PropertyState_DIRECT_VALUE ==
                    rPropState->getPropertyState( sHyperLinkTarget ) ) )
    {
        rPropSet->getPropertyValue( sHyperLinkTarget ) >>= sTargetFrame;
        if( sTargetFrame.getLength() )
            bExport = sal_True;
    }

    if( rPropSetInfo->hasPropertyByName( sServerMap ) &&
        ( !rPropState.is() || PropertyState_DIRECT_VALUE ==
                    rPropState->getPropertyState( sServerMap ) ) )
    {
        bServerMap = *(sal_Bool *)rPropSet->getPropertyValue( sServerMap ).getValue();
        if( bServerMap  )
            bExport = sal_True;
    }

    if( rPropSetInfo->hasPropertyByName( sUnvisitedCharStyleName ) &&
        ( !rPropState.is() || PropertyState_DIRECT_VALUE ==
            rPropState->getPropertyState( sUnvisitedCharStyleName ) ) )
    {
        rPropSet->getPropertyValue( sUnvisitedCharStyleName ) >>= sUStyleName;
        if( sUStyleName.getLength() )
            bExport = sal_True;
    }

    if( rPropSetInfo->hasPropertyByName( sVisitedCharStyleName ) &&
        ( !rPropState.is() || PropertyState_DIRECT_VALUE ==
            rPropState->getPropertyState( sVisitedCharStyleName ) ) )
    {
        rPropSet->getPropertyValue( sVisitedCharStyleName ) >>= sVStyleName;
        if( sVStyleName.getLength() )
            bExport = sal_True;
    }

    if( bExport )
    {
        GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_TYPE, XML_SIMPLE );
        GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference( sHRef ) );

        if( sName.getLength() > 0 )
            GetExport().AddAttribute( XML_NAMESPACE_OFFICE, XML_NAME, sName );

        if( sTargetFrame.getLength() )
        {
            GetExport().AddAttribute( XML_NAMESPACE_OFFICE,
                                      XML_TARGET_FRAME_NAME, sTargetFrame );
            enum XMLTokenEnum eTok =
                sTargetFrame.equalsAsciiL( "_blank", sizeof("_blank")-1 )
                    ? XML_NEW : XML_REPLACE;
            GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_SHOW, eTok );
        }

        if( bServerMap  )
            GetExport().AddAttribute( XML_NAMESPACE_OFFICE,
                                      XML_SERVER_MAP, XML_TRUE );

        if( sUStyleName.getLength() )
            GetExport().AddAttribute( XML_NAMESPACE_TEXT,
              XML_STYLE_NAME, GetExport().EncodeStyleName( sUStyleName ) );

        if( sVStyleName.getLength() )
            GetExport().AddAttribute( XML_NAMESPACE_TEXT,
              XML_VISITED_STYLE_NAME, GetExport().EncodeStyleName( sVStyleName ) );
    }

    return bExport;
}

void XMLTextParagraphExport::exportTextRange(
        const Reference < XTextRange > & rTextRange,
        sal_Bool bAutoStyles,
        sal_Bool& rPrevCharIsSpace )
{
    Reference < XPropertySet > xPropSet( rTextRange, UNO_QUERY );
    if( bAutoStyles )
    {
        Add( XML_STYLE_FAMILY_TEXT_TEXT, xPropSet );
    }
    else
    {
        sal_Bool bHyperlink = sal_False, bIsUICharStyle = sal_False;
        OUString sStyle(FindTextStyleAndHyperlink( xPropSet, bHyperlink,
                                                        bIsUICharStyle ));
        Reference < XPropertySetInfo > xPropSetInfo;
        if( bHyperlink )
        {
            Reference< XPropertyState > xPropState( xPropSet, UNO_QUERY );
            xPropSetInfo.set(xPropSet->getPropertySetInfo());
            bHyperlink = addHyperlinkAttributes( xPropSet, xPropState, xPropSetInfo );
        }
        SvXMLElementExport aElem( GetExport(), bHyperlink, XML_NAMESPACE_TEXT,
                                  XML_A, sal_False, sal_False );
        if( bHyperlink )
        {
            // export events (if supported)
            OUString sHyperLinkEvents(RTL_CONSTASCII_USTRINGPARAM(
                "HyperLinkEvents"));
            if (xPropSetInfo->hasPropertyByName(sHyperLinkEvents))
            {
                Reference<XNameReplace> xName(xPropSet->getPropertyValue(sHyperLinkEvents), uno::UNO_QUERY);
                GetExport().GetEventExport().Export(xName, sal_False);
            }
        }

        {
            XMLTextCharStyleNamesElementExport aCharStylesExport(
                GetExport(), bIsUICharStyle &&
                             aCharStyleNamesPropInfoCache.hasProperty(
                                                    xPropSet, xPropSetInfo ),
                xPropSet, sCharStyleNames );

            OUString sText(rTextRange->getString());
            if( sStyle.getLength() )
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                          GetExport().EncodeStyleName( sStyle ) );
            {
                // in a block to make sure it is destroyed before the text:a element
                SvXMLElementExport aElem( GetExport(), sStyle.getLength() > 0,
                                          XML_NAMESPACE_TEXT, XML_SPAN, sal_False,
                                          sal_False );
                exportText( sText, rPrevCharIsSpace );
            }
        }
    }
}

void XMLTextParagraphExport::exportText( const OUString& rText,
                                           sal_Bool& rPrevCharIsSpace )
{
    sal_Int32 nExpStartPos = 0L;
    sal_Int32 nEndPos = rText.getLength();
    sal_Int32 nSpaceChars = 0;
    for( sal_Int32 nPos = 0; nPos < nEndPos; nPos++ )
    {
        sal_Unicode cChar = rText[nPos];
        sal_Bool bExpCharAsText = sal_True;
        sal_Bool bExpCharAsElement = sal_False;
        sal_Bool bCurrCharIsSpace = sal_False;
        switch( cChar )
        {
        case 0x0009:    // Tab
        case 0x000A:    // LF
            // These characters are exported as text.
            bExpCharAsElement = sal_True;
            bExpCharAsText = sal_False;
            break;
        case 0x000D:
            break;  // legal character
        case 0x0020:    // Blank
            if( rPrevCharIsSpace )
            {
                // If the previous character is a space character,
                // too, export a special space element.
                bExpCharAsText = sal_False;
            }
            bCurrCharIsSpace = sal_True;
            break;
        default:
            if( cChar < 0x0020 )
            {
#ifndef PRODUCT
                OSL_ENSURE( txtparae_bContainsIllegalCharacters ||
                            cChar >= 0x0020,
                            "illegal character in text content" );
                txtparae_bContainsIllegalCharacters = sal_True;
#endif
                bExpCharAsText = sal_False;
            }
            break;
        }

        // If the current character is not exported as text
           // the text that has not been exported by now has to be exported now.
        if( nPos > nExpStartPos && !bExpCharAsText )
        {
            DBG_ASSERT( 0==nSpaceChars, "pending spaces" );
            OUString sExp( rText.copy( nExpStartPos, nPos - nExpStartPos ) );
            GetExport().Characters( sExp );
            nExpStartPos = nPos;
        }

        // If there are spaces left that have not been exported and the
        // current chracter is not a space , the pending spaces have to be
        // exported now.
        if( nSpaceChars > 0 && !bCurrCharIsSpace )
        {
            DBG_ASSERT( nExpStartPos == nPos, " pending characters" );

            if( nSpaceChars > 1 )
            {
                OUStringBuffer sTmp;
                sTmp.append( (sal_Int32)nSpaceChars );
                GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
                              sTmp.makeStringAndClear() );
            }

            SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
                                      XML_S, sal_False, sal_False );

            nSpaceChars = 0;
        }

        // If the current character has to be exported as a special
        // element, the elemnt will be exported now.
        if( bExpCharAsElement )
        {
            switch( cChar )
            {
            case 0x0009:    // Tab
                {
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
                                              XML_TAB, sal_False,
                                              sal_False );
                }
                break;
            case 0x000A:    // LF
                {
                    SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT,
                                              XML_LINE_BREAK, sal_False,
                                              sal_False );
                }
                break;
            }
        }

        // If the current character is a space, and the previous one
        // is a space, too, the number of pending spaces is incremented
        // only.
        if( bCurrCharIsSpace && rPrevCharIsSpace )
            nSpaceChars++;
        rPrevCharIsSpace = bCurrCharIsSpace;

        // If the currect character is not exported as text, the start
        // position for text is the position behind the current position.
        if( !bExpCharAsText )
        {
            DBG_ASSERT( nExpStartPos == nPos, "wrong export start pos" );
            nExpStartPos = nPos+1;
        }
    }

    if( nExpStartPos < nEndPos )
    {
        DBG_ASSERT( 0==nSpaceChars, " pending spaces " );
        OUString sExp( rText.copy( nExpStartPos, nEndPos - nExpStartPos ) );
        GetExport().Characters( sExp );
    }

    // If there are some spaces left, they have to be exported now.
    if( nSpaceChars > 0 )
    {
        if( nSpaceChars > 1 )
        {
            OUStringBuffer sTmp;
            sTmp.append( (sal_Int32)nSpaceChars );
            GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_C,
                          sTmp.makeStringAndClear() );
        }

        SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_S,
                                  sal_False, sal_False );
    }
}

void XMLTextParagraphExport::exportTextDeclarations()
{
    pFieldExport->ExportFieldDeclarations();

    // get XPropertySet from the document and ask for AutoMarkFileURL.
    // If it exists, export the auto-mark-file element.
    Reference<XPropertySet> xPropertySet( GetExport().GetModel(), UNO_QUERY );
    if (xPropertySet.is())
    {
        OUString sUrl;
        OUString sIndexAutoMarkFileURL(
            RTL_CONSTASCII_USTRINGPARAM("IndexAutoMarkFileURL"));
        if (xPropertySet->getPropertySetInfo()->hasPropertyByName(
            sIndexAutoMarkFileURL))
        {
            xPropertySet->getPropertyValue(sIndexAutoMarkFileURL) >>= sUrl;
            if (sUrl.getLength() > 0)
            {
                GetExport().AddAttribute( XML_NAMESPACE_XLINK, XML_HREF,
                                          GetExport().GetRelativeReference(sUrl) );
                SvXMLElementExport aAutoMarkElement(
                    GetExport(), XML_NAMESPACE_TEXT,
                    XML_ALPHABETICAL_INDEX_AUTO_MARK_FILE,
                    sal_True, sal_True );
            }
        }
    }
}

void XMLTextParagraphExport::exportTextDeclarations(
    const Reference<XText> & rText )
{
    pFieldExport->ExportFieldDeclarations(rText);
}

void XMLTextParagraphExport::exportUsedDeclarations( sal_Bool bOnlyUsed )
{
    pFieldExport->SetExportOnlyUsedFieldDeclarations( bOnlyUsed );
}


void XMLTextParagraphExport::exportTrackedChanges(sal_Bool bAutoStyles)
{
    if (NULL != pRedlineExport)
        pRedlineExport->ExportChangesList( bAutoStyles );
}

void XMLTextParagraphExport::exportTrackedChanges(
    const Reference<XText> & rText,
    sal_Bool bAutoStyle)
{
    if (NULL != pRedlineExport)
        pRedlineExport->ExportChangesList(rText, bAutoStyle);
}

void XMLTextParagraphExport::recordTrackedChangesForXText(
    const Reference<XText> & rText )
{
    if (NULL != pRedlineExport)
        pRedlineExport->SetCurrentXText(rText);
}

void XMLTextParagraphExport::recordTrackedChangesNoXText()
{
    if (NULL != pRedlineExport)
        pRedlineExport->SetCurrentXText();
}


void XMLTextParagraphExport::exportTextAutoStyles()
{
    GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_PARAGRAPH,
                                   GetExport().GetDocHandler(),
                                   GetExport().GetMM100UnitConverter(),
                                   GetExport().GetNamespaceMap() );

    GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_TEXT,
                                   GetExport().GetDocHandler(),
                                   GetExport().GetMM100UnitConverter(),
                                   GetExport().GetNamespaceMap() );

    GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_FRAME,
                                   GetExport().GetDocHandler(),
                                   GetExport().GetMM100UnitConverter(),
                                   GetExport().GetNamespaceMap() );

    GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_SECTION,
                                  GetExport().GetDocHandler(),
                                  GetExport().GetMM100UnitConverter(),
                                  GetExport().GetNamespaceMap() );

    GetAutoStylePool().exportXML( XML_STYLE_FAMILY_TEXT_RUBY,
                                  GetExport().GetDocHandler(),
                                  GetExport().GetMM100UnitConverter(),
                                  GetExport().GetNamespaceMap() );

    pListAutoPool->exportXML();
}

void XMLTextParagraphExport::exportRuby(
    const Reference<XPropertySet> & rPropSet,
    sal_Bool bAutoStyles )
{
    // early out: a collapsed ruby makes no sense
    if (*(sal_Bool*)rPropSet->getPropertyValue(sIsCollapsed).getValue())
        return;

    // start value ?
    sal_Bool bStart = (*(sal_Bool*)rPropSet->getPropertyValue(sIsStart).getValue());

    if (bAutoStyles)
    {
        // ruby auto styles
        if (bStart)
            Add( XML_STYLE_FAMILY_TEXT_RUBY, rPropSet );
    }
    else
    {
        // prepare element names
        OUString sRuby(GetXMLToken(XML_RUBY));
        OUString sTextRuby(GetExport().GetNamespaceMap().
                           GetQNameByKey(XML_NAMESPACE_TEXT, sRuby));
        OUString sRubyBase(GetXMLToken(XML_RUBY_BASE));
        OUString sTextRubyBase(GetExport().GetNamespaceMap().
                           GetQNameByKey(XML_NAMESPACE_TEXT, sRubyBase));

        if (bStart)
        {
            // ruby start

            // we can only start a ruby if none is open
            DBG_ASSERT(! bOpenRuby, "Can't open a ruby inside of ruby!");
            if( bOpenRuby )
                return;

            // save ruby text + ruby char style
            rPropSet->getPropertyValue(sRubyText) >>= sOpenRubyText;
            rPropSet->getPropertyValue(sRubyCharStyleName) >>= sOpenRubyCharStyle;

            // ruby style
            GetExport().CheckAttrList();
            OUString sEmpty;
            OUString sStyleName(Find( XML_STYLE_FAMILY_TEXT_RUBY, rPropSet,
                                        sEmpty ));
            DBG_ASSERT(sStyleName.getLength() > 0, "I can't find the style!");
            GetExport().AddAttribute(XML_NAMESPACE_TEXT,
                                     XML_STYLE_NAME, sStyleName);

            // export <text:ruby> and <text:ruby-base> start elements
            GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY, sal_False);
            GetExport().ClearAttrList();
            GetExport().StartElement( XML_NAMESPACE_TEXT, XML_RUBY_BASE,
                                      sal_False );
            bOpenRuby = sal_True;
        }
        else
        {
            // ruby end

            // check for an open ruby
            DBG_ASSERT(bOpenRuby, "Can't close a ruby if none is open!");
            if( !bOpenRuby )
                return;

            // close <text:ruby-base>
            GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY_BASE,
                                   sal_False);

            // write the ruby text (with char style)
            {
                if (sOpenRubyCharStyle.getLength() > 0)
                    GetExport().AddAttribute(
                        XML_NAMESPACE_TEXT, XML_STYLE_NAME,
                        GetExport().EncodeStyleName( sOpenRubyCharStyle) );

                SvXMLElementExport aRuby(
                    GetExport(), XML_NAMESPACE_TEXT, XML_RUBY_TEXT,
                    sal_False, sal_False);

                GetExport().Characters(sOpenRubyText);
            }

            // and finally, close the ruby
            GetExport().EndElement(XML_NAMESPACE_TEXT, XML_RUBY, sal_False);
            bOpenRuby = sal_False;
        }
    }
}




void XMLTextParagraphExport::PreventExportOfControlsInMuteSections(
    const Reference<XIndexAccess> & rShapes,
    UniReference<xmloff::OFormLayerXMLExport> xFormExport   )
{
    // check parameters ad pre-conditions
    if( ( ! rShapes.is() ) || ( ! xFormExport.is() ) )
    {
        // if we don't have shapes or a form export, there's nothing to do
        return;
    }
    DBG_ASSERT( pSectionExport != NULL, "We need the section export." );

    sal_Int32 nShapes = xShapes->getCount();
    for( sal_Int32 i = 0; i < nShapes; i++ )
    {
        // now we need to check
        // 1) if this is a control shape, and
        // 2) if it's in a mute section
        // if both answers are 'yes', notify the form layer export

        // we join accessing the shape and testing for control
        Reference<XControlShape> xControlShape(xShapes->getByIndex( i ), uno::UNO_QUERY);
        if( xControlShape.is() )
        {
            //            Reference<XPropertySet> xPropSet( xControlShape, UNO_QUERY );
            //            Reference<XTextContent> xTextContent;
            //            xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "TextRange" ) ) ) >>= xTextContent;

            Reference<XTextContent> xTextContent( xControlShape, UNO_QUERY );
            if( xTextContent.is() )
            {
                if( pSectionExport->IsMuteSection( xTextContent, sal_False ) )
                {
                    // Ah, we've found a shape that
                    // 1) is a control shape
                    // 2) is anchored in a mute section
                    // so: don't export it!
                    xFormExport->excludeFromExport(
                        xControlShape->getControl() );
                }
                // else: not in mute section -> should be exported -> nothing
                // to do
            }
            // else: no anchor -> ignore
        }
        // else: no control shape -> nothing to do
    }
}
sal_Int32 XMLTextParagraphExport::GetHeadingLevel( const OUString& rStyleName )
{
    if( !pHeadingStyles )
    {
        pHeadingStyles = new XMLStringVector;
        SvxXMLNumRuleExport::GetOutlineStyles( *pHeadingStyles,
                                               GetExport().GetModel() );
    }
    for( XMLStringVector::size_type i=0; i < pHeadingStyles->size(); ++i )
    {
        if( (*pHeadingStyles)[i] == rStyleName )
            return static_cast < sal_Int32 >( i );
    }

    return -1;
}

