1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_xmloff.hxx"
30 #include "XMLSectionExport.hxx"
31 #include <rtl/ustring.hxx>
32 #include <rtl/ustrbuf.hxx>
33 
34 #include <vector>
35 
36 
37 #include <com/sun/star/lang/XServiceInfo.hpp>
38 #include <com/sun/star/lang/Locale.hpp>
39 #include <com/sun/star/container/XIndexReplace.hpp>
40 #include <com/sun/star/beans/XPropertySet.hpp>
41 #include <com/sun/star/beans/PropertyValue.hpp>
42 #include <com/sun/star/beans/PropertyValues.hpp>
43 #include <com/sun/star/beans/PropertyState.hpp>
44 #include <com/sun/star/text/XText.hpp>
45 #include <com/sun/star/text/XTextSection.hpp>
46 #include <com/sun/star/text/SectionFileLink.hpp>
47 #include <com/sun/star/container/XNamed.hpp>
48 #include <com/sun/star/container/XNameAccess.hpp>
49 #include <com/sun/star/text/XDocumentIndex.hpp>
50 #include <com/sun/star/uno/XInterface.hpp>
51 #include <com/sun/star/text/BibliographyDataField.hpp>
52 #include <com/sun/star/text/XTextFieldsSupplier.hpp>
53 #include <com/sun/star/text/XChapterNumberingSupplier.hpp>
54 #include <com/sun/star/text/ChapterFormat.hpp> //i90246
55 #include <xmloff/xmltoken.hxx>
56 #include "xmloff/xmlnmspe.hxx"
57 #include <xmloff/families.hxx>
58 #include <xmloff/xmluconv.hxx>
59 #include <xmloff/nmspmap.hxx>
60 #include <xmloff/xmlexp.hxx>
61 #include <xmloff/xmltkmap.hxx>
62 #include "txtflde.hxx"
63 
64 
65 
66 using namespace ::com::sun::star;
67 using namespace ::com::sun::star::text;
68 using namespace ::com::sun::star::uno;
69 using namespace ::std;
70 using namespace ::xmloff::token;
71 
72 using ::rtl::OUString;
73 using ::rtl::OUStringBuffer;
74 using ::com::sun::star::beans::XPropertySet;
75 using ::com::sun::star::beans::PropertyValue;
76 using ::com::sun::star::beans::PropertyValues;
77 using ::com::sun::star::beans::PropertyState;
78 using ::com::sun::star::container::XIndexReplace;
79 using ::com::sun::star::container::XNameAccess;
80 using ::com::sun::star::container::XNamed;
81 using ::com::sun::star::lang::XServiceInfo;
82 using ::com::sun::star::lang::Locale;
83 using ::com::sun::star::uno::XInterface;
84 
85 
86 XMLSectionExport::XMLSectionExport(
87 	SvXMLExport& rExp,
88 	XMLTextParagraphExport& rParaExp)
89 :	sCondition(RTL_CONSTASCII_USTRINGPARAM("Condition"))
90 ,	sCreateFromChapter(RTL_CONSTASCII_USTRINGPARAM("CreateFromChapter"))
91 ,	sCreateFromEmbeddedObjects(RTL_CONSTASCII_USTRINGPARAM("CreateFromEmbeddedObjects"))
92 ,	sCreateFromGraphicObjects(RTL_CONSTASCII_USTRINGPARAM("CreateFromGraphicObjects"))
93 ,	sCreateFromLabels(RTL_CONSTASCII_USTRINGPARAM("CreateFromLabels"))
94 ,	sCreateFromMarks(RTL_CONSTASCII_USTRINGPARAM("CreateFromMarks"))
95 ,	sCreateFromOtherEmbeddedObjects(RTL_CONSTASCII_USTRINGPARAM("CreateFromOtherEmbeddedObjects"))
96 ,	sCreateFromOutline(RTL_CONSTASCII_USTRINGPARAM("CreateFromOutline"))
97 ,	sCreateFromStarCalc(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarCalc"))
98 ,	sCreateFromStarChart(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarChart"))
99 ,	sCreateFromStarDraw(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarDraw"))
100 ,	sCreateFromStarImage(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarImage"))
101 ,	sCreateFromStarMath(RTL_CONSTASCII_USTRINGPARAM("CreateFromStarMath"))
102 ,	sCreateFromTables(RTL_CONSTASCII_USTRINGPARAM("CreateFromTables"))
103 ,	sCreateFromTextFrames(RTL_CONSTASCII_USTRINGPARAM("CreateFromTextFrames"))
104 ,	sDdeCommandElement(RTL_CONSTASCII_USTRINGPARAM("DDECommandElement"))
105 ,	sDdeCommandFile(RTL_CONSTASCII_USTRINGPARAM("DDECommandFile"))
106 ,	sDdeCommandType(RTL_CONSTASCII_USTRINGPARAM("DDECommandType"))
107 ,	sFileLink(RTL_CONSTASCII_USTRINGPARAM("FileLink"))
108 ,	sIsCaseSensitive(RTL_CONSTASCII_USTRINGPARAM("IsCaseSensitive"))
109 ,	sIsProtected(RTL_CONSTASCII_USTRINGPARAM("IsProtected"))
110 ,	sIsVisible(RTL_CONSTASCII_USTRINGPARAM("IsVisible"))
111 ,	sLabelCategory(RTL_CONSTASCII_USTRINGPARAM("LabelCategory"))
112 ,	sLabelDisplayType(RTL_CONSTASCII_USTRINGPARAM("LabelDisplayType"))
113 ,	sLevel(RTL_CONSTASCII_USTRINGPARAM("Level"))
114 ,	sLevelFormat(RTL_CONSTASCII_USTRINGPARAM("LevelFormat"))
115 ,	sLevelParagraphStyles(RTL_CONSTASCII_USTRINGPARAM("LevelParagraphStyles"))
116 ,	sLinkRegion(RTL_CONSTASCII_USTRINGPARAM("LinkRegion"))
117 ,	sMainEntryCharacterStyleName(RTL_CONSTASCII_USTRINGPARAM("MainEntryCharacterStyleName"))
118 ,	sParaStyleHeading(RTL_CONSTASCII_USTRINGPARAM("ParaStyleHeading"))
119 ,	sParaStyleLevel(RTL_CONSTASCII_USTRINGPARAM("ParaStyleLevel"))
120 ,	sTitle(RTL_CONSTASCII_USTRINGPARAM("Title"))
121 ,	sName(RTL_CONSTASCII_USTRINGPARAM("Name"))
122 ,	sUseAlphabeticalSeparators(RTL_CONSTASCII_USTRINGPARAM("UseAlphabeticalSeparators"))
123 ,	sUseCombinedEntries(RTL_CONSTASCII_USTRINGPARAM("UseCombinedEntries"))
124 ,	sUseDash(RTL_CONSTASCII_USTRINGPARAM("UseDash"))
125 ,	sUseKeyAsEntry(RTL_CONSTASCII_USTRINGPARAM("UseKeyAsEntry"))
126 ,	sUseLevelFromSource(RTL_CONSTASCII_USTRINGPARAM("UseLevelFromSource"))
127 ,	sUsePP(RTL_CONSTASCII_USTRINGPARAM("UsePP"))
128 ,	sUseUpperCase(RTL_CONSTASCII_USTRINGPARAM("UseUpperCase"))
129 ,	sIsCommaSeparated(RTL_CONSTASCII_USTRINGPARAM("IsCommaSeparated"))
130 ,	sIsAutomaticUpdate(RTL_CONSTASCII_USTRINGPARAM("IsAutomaticUpdate"))
131 ,	sIsRelativeTabstops(RTL_CONSTASCII_USTRINGPARAM("IsRelativeTabstops"))
132 ,	sCreateFromLevelParagraphStyles(RTL_CONSTASCII_USTRINGPARAM("CreateFromLevelParagraphStyles"))
133 ,	sDocumentIndex(RTL_CONSTASCII_USTRINGPARAM("DocumentIndex"))
134 ,	sContentSection(RTL_CONSTASCII_USTRINGPARAM("ContentSection"))
135 ,	sHeaderSection(RTL_CONSTASCII_USTRINGPARAM("HeaderSection"))
136 
137 ,	sTextSection(RTL_CONSTASCII_USTRINGPARAM("TextSection"))
138 ,	sIsGlobalDocumentSection(RTL_CONSTASCII_USTRINGPARAM("IsGlobalDocumentSection"))
139 ,	sProtectionKey(RTL_CONSTASCII_USTRINGPARAM("ProtectionKey"))
140 ,	sSortAlgorithm(RTL_CONSTASCII_USTRINGPARAM("SortAlgorithm"))
141 ,	sLocale(RTL_CONSTASCII_USTRINGPARAM("Locale"))
142 ,	sUserIndexName(RTL_CONSTASCII_USTRINGPARAM("UserIndexName"))
143 
144 ,	sIsCurrentlyVisible(RTL_CONSTASCII_USTRINGPARAM("IsCurrentlyVisible"))
145 ,	sHeadingStyleName(RTL_CONSTASCII_USTRINGPARAM("HeadingStyleName"))
146 
147 ,	rExport(rExp)
148 ,	rParaExport(rParaExp)
149 ,	bHeadingDummiesExported( sal_False )
150 {
151 }
152 
153 
154 void XMLSectionExport::ExportSectionStart(
155 	const Reference<XTextSection> & rSection,
156 	sal_Bool bAutoStyles)
157 {
158 	Reference<XPropertySet> xPropertySet(rSection, UNO_QUERY);
159 
160 	// always export section (auto) style
161 	if (bAutoStyles)
162 	{
163 		// get PropertySet and add section style
164 		GetParaExport().Add( XML_STYLE_FAMILY_TEXT_SECTION, xPropertySet );
165 	}
166 	else
167 	{
168 		// always export section style
169 		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
170 									 GetParaExport().Find(
171 									 XML_STYLE_FAMILY_TEXT_SECTION,
172 									 xPropertySet, sEmpty ) );
173 
174         // xml:id for RDF metadata
175         GetExport().AddAttributeXmlId(rSection);
176 
177 		// export index or regular section
178 		Reference<XDocumentIndex> xIndex;
179 		if (GetIndex(rSection, xIndex))
180 		{
181 			if (xIndex.is())
182 			{
183 				// we are an index
184 				ExportIndexStart(xIndex);
185 			}
186 			else
187 			{
188 				// we are an index header
189 				ExportIndexHeaderStart(rSection);
190 			}
191 		}
192 		else
193 		{
194 			// we are not an index
195 			ExportRegularSectionStart(rSection);
196 		}
197 	}
198 }
199 
200 sal_Bool XMLSectionExport::GetIndex(
201 	const Reference<XTextSection> & rSection,
202 	Reference<XDocumentIndex> & rIndex) const
203 {
204 	// first, reset result
205 	sal_Bool bRet = sal_False;
206 	rIndex = NULL;
207 
208 	// get section Properties
209 	Reference<XPropertySet> xSectionPropSet(rSection, UNO_QUERY);
210 
211 	// then check if this section happens to be inside an index
212 	if (xSectionPropSet->getPropertySetInfo()->
213 									hasPropertyByName(sDocumentIndex))
214 	{
215 		Any aAny = xSectionPropSet->getPropertyValue(sDocumentIndex);
216 		Reference<XDocumentIndex> xDocumentIndex;
217 		aAny >>= xDocumentIndex;
218 
219 		// OK, are we inside of an index
220 		if (xDocumentIndex.is())
221 		{
222 			// is the enclosing index identical with "our" section?
223 			Reference<XPropertySet> xIndexPropSet(xDocumentIndex, UNO_QUERY);
224 			aAny = xIndexPropSet->getPropertyValue(sContentSection);
225 			Reference<XTextSection> xEnclosingSection;
226 			aAny >>= xEnclosingSection;
227 
228 			// if the enclosing section is "our" section, then we are an index!
229 			if (rSection == xEnclosingSection)
230 			{
231 				rIndex = xDocumentIndex;
232 				bRet = sal_True;
233 			}
234 			// else: index header or regular section
235 
236 			// is the enclosing index identical with the header section?
237 			aAny = xIndexPropSet->getPropertyValue(sHeaderSection);
238 			// now mis-named: contains header section
239 			aAny >>= xEnclosingSection;
240 
241 			// if the enclosing section is "our" section, then we are an index!
242 			if (rSection == xEnclosingSection)
243 			{
244 				bRet = sal_True;
245 			}
246 			// else: regular section
247 		}
248 		// else: we aren't even inside of an index
249 	}
250 	// else: we don't even know what an index is.
251 
252 	return bRet;
253 }
254 
255 
256 void XMLSectionExport::ExportSectionEnd(
257 	const Reference<XTextSection> & rSection,
258 	sal_Bool bAutoStyles)
259 {
260 	// no end section for styles
261 	if (!bAutoStyles)
262 	{
263 		enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
264 
265 		// export index or regular section end
266 		Reference<XDocumentIndex> xIndex;
267 		if (GetIndex(rSection, xIndex))
268 		{
269 			if (xIndex.is())
270 			{
271 				// index end: close index body element
272 				GetExport().EndElement( XML_NAMESPACE_TEXT,	XML_INDEX_BODY,
273                                         sal_True );
274 				GetExport().IgnorableWhitespace();
275 
276 				switch (MapSectionType(xIndex->getServiceName()))
277 				{
278 					case TEXT_SECTION_TYPE_TOC:
279 						eElement = XML_TABLE_OF_CONTENT;
280 						break;
281 
282 					case TEXT_SECTION_TYPE_ILLUSTRATION:
283 						eElement = XML_ILLUSTRATION_INDEX;
284 						break;
285 
286 					case TEXT_SECTION_TYPE_ALPHABETICAL:
287 						eElement = XML_ALPHABETICAL_INDEX;
288 						break;
289 
290 					case TEXT_SECTION_TYPE_TABLE:
291 						eElement = XML_TABLE_INDEX;
292 						break;
293 
294 					case TEXT_SECTION_TYPE_OBJECT:
295 						eElement = XML_OBJECT_INDEX;
296 						break;
297 
298 					case TEXT_SECTION_TYPE_USER:
299 						eElement = XML_USER_INDEX;
300 						break;
301 
302 					case TEXT_SECTION_TYPE_BIBLIOGRAPHY:
303 						eElement = XML_BIBLIOGRAPHY;
304 						break;
305 
306 					default:
307 						OSL_ENSURE(false, "unknown index type");
308 						// default: skip index!
309 						break;
310 				}
311 			}
312 			else
313 			{
314 				eElement = XML_INDEX_TITLE;
315 			}
316 		}
317 		else
318 		{
319 			eElement = XML_SECTION;
320 		}
321 
322 		if (XML_TOKEN_INVALID != eElement)
323 		{
324 			// any old attributes?
325 			GetExport().CheckAttrList();
326 
327 			// element surrounded by whitespace
328 			GetExport().EndElement( XML_NAMESPACE_TEXT,	eElement, sal_True);
329 			GetExport().IgnorableWhitespace();
330 		}
331 		else
332 		{
333 			OSL_ENSURE(false, "Need element name!");
334 		}
335 	}
336 	// else: autostyles -> ignore
337 }
338 
339 void XMLSectionExport::ExportIndexStart(
340 	const Reference<XDocumentIndex> & rIndex)
341 {
342 	// get PropertySet
343 	Reference<XPropertySet> xPropertySet(rIndex, UNO_QUERY);
344 
345 	switch (MapSectionType(rIndex->getServiceName()))
346 	{
347 		case TEXT_SECTION_TYPE_TOC:
348 			ExportTableOfContentStart(xPropertySet);
349 			break;
350 
351 		case TEXT_SECTION_TYPE_ILLUSTRATION:
352 			ExportIllustrationIndexStart(xPropertySet);
353 			break;
354 
355 		case TEXT_SECTION_TYPE_ALPHABETICAL:
356 			ExportAlphabeticalIndexStart(xPropertySet);
357 			break;
358 
359 		case TEXT_SECTION_TYPE_TABLE:
360 			ExportTableIndexStart(xPropertySet);
361 			break;
362 
363 		case TEXT_SECTION_TYPE_OBJECT:
364 			ExportObjectIndexStart(xPropertySet);
365 			break;
366 
367 		case TEXT_SECTION_TYPE_USER:
368 			ExportUserIndexStart(xPropertySet);
369 			break;
370 
371 		case TEXT_SECTION_TYPE_BIBLIOGRAPHY:
372 			ExportBibliographyStart(xPropertySet);
373 			break;
374 
375 		default:
376 			// skip index
377 			OSL_ENSURE(false, "unknown index type");
378 			break;
379 	}
380 }
381 
382 void XMLSectionExport::ExportIndexHeaderStart(
383 	const Reference<XTextSection> & rSection)
384 {
385 	// export name, dammit!
386 	Reference<XNamed> xName(rSection, UNO_QUERY);
387 	GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName());
388 
389 	// format already handled -> export only start element
390 	GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_TITLE, sal_True );
391 	GetExport().IgnorableWhitespace();
392 }
393 
394 
395 SvXMLEnumStringMapEntry __READONLY_DATA aIndexTypeMap[] =
396 {
397 	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.ContentIndex", TEXT_SECTION_TYPE_TOC ),
398 	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.DocumentIndex", TEXT_SECTION_TYPE_ALPHABETICAL ),
399 	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.TableIndex", TEXT_SECTION_TYPE_TABLE ),
400 	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.ObjectIndex", TEXT_SECTION_TYPE_OBJECT ),
401 	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.Bibliography", TEXT_SECTION_TYPE_BIBLIOGRAPHY ),
402 	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.UserIndex", TEXT_SECTION_TYPE_USER ),
403 	ENUM_STRING_MAP_ENTRY( "com.sun.star.text.IllustrationsIndex", TEXT_SECTION_TYPE_ILLUSTRATION ),
404     ENUM_STRING_MAP_END()
405 };
406 
407 enum SectionTypeEnum XMLSectionExport::MapSectionType(
408 	const OUString& rServiceName)
409 {
410 	enum SectionTypeEnum eType = TEXT_SECTION_TYPE_UNKNOWN;
411 
412 	sal_uInt16 nTmp;
413 	if (SvXMLUnitConverter::convertEnum(nTmp, rServiceName, aIndexTypeMap))
414 	{
415 		eType = (enum SectionTypeEnum)nTmp;
416 	}
417 
418 	// TODO: index header section types, etc.
419 
420 	return eType;
421 }
422 
423 void XMLSectionExport::ExportRegularSectionStart(
424 	const Reference<XTextSection> & rSection)
425 {
426 	// style name already handled in ExportSectionStart(...)
427 
428 	Reference<XNamed> xName(rSection, UNO_QUERY);
429 	GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName());
430 
431 	// get XPropertySet for other values
432 	Reference<XPropertySet> xPropSet(rSection, UNO_QUERY);
433 	Any aAny;
434 
435 	// condition and display
436 	aAny = xPropSet->getPropertyValue(sCondition);
437 	OUString sCond;
438 	aAny >>= sCond;
439 	enum XMLTokenEnum eDisplay = XML_TOKEN_INVALID;
440 	if (sCond.getLength() > 0)
441 	{
442 		OUString sQValue =
443 			GetExport().GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OOOW,
444 														 sCond, sal_False );
445 		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_CONDITION, sQValue);
446 		eDisplay = XML_CONDITION;
447 
448         // #97450# store hidden-status (of conditional sections only)
449         aAny = xPropSet->getPropertyValue(sIsCurrentlyVisible);
450         if (! *(sal_Bool*)aAny.getValue())
451         {
452             GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_IS_HIDDEN,
453                                      XML_TRUE);
454         }
455 	}
456 	else
457 	{
458 		eDisplay = XML_NONE;
459 	}
460 	aAny = xPropSet->getPropertyValue(sIsVisible);
461 	if (! *(sal_Bool*)aAny.getValue())
462 	{
463 		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_DISPLAY, eDisplay);
464 	}
465 
466 	// protect + protection key
467 	aAny = xPropSet->getPropertyValue(sIsProtected);
468 	if (*(sal_Bool*)aAny.getValue())
469 	{
470 		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE);
471 	}
472 	Sequence<sal_Int8> aPassword;
473 	xPropSet->getPropertyValue(sProtectionKey) >>= aPassword;
474 	if (aPassword.getLength() > 0)
475 	{
476 		OUStringBuffer aBuffer;
477 		SvXMLUnitConverter::encodeBase64(aBuffer, aPassword);
478 		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTION_KEY,
479 								 aBuffer.makeStringAndClear());
480 	}
481 
482 	// export element
483 	GetExport().IgnorableWhitespace();
484 	GetExport().StartElement( XML_NAMESPACE_TEXT, XML_SECTION, sal_True );
485 
486 	// data source
487 	// unfortunately, we have to test all relevant strings for non-zero length
488 	aAny = xPropSet->getPropertyValue(sFileLink);
489 	SectionFileLink aFileLink;
490 	aAny >>= aFileLink;
491 
492 	aAny = xPropSet->getPropertyValue(sLinkRegion);
493 	OUString sRegionName;
494 	aAny >>= sRegionName;
495 
496 	if ( (aFileLink.FileURL.getLength() > 0) ||
497 		 (aFileLink.FilterName.getLength() > 0) ||
498 		 (sRegionName.getLength() > 0) )
499 	{
500 		if (aFileLink.FileURL.getLength() > 0)
501 		{
502 			GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF,
503 									 GetExport().GetRelativeReference( aFileLink.FileURL) );
504 		}
505 
506 		if (aFileLink.FilterName.getLength() > 0)
507 		{
508 			GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_FILTER_NAME,
509 									 aFileLink.FilterName);
510 		}
511 
512 		if (sRegionName.getLength() > 0)
513 		{
514 			GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_SECTION_NAME,
515 									 sRegionName);
516 		}
517 
518 		SvXMLElementExport aElem(GetExport(),
519 								 XML_NAMESPACE_TEXT, XML_SECTION_SOURCE,
520 								 sal_True, sal_True);
521 	}
522 	else
523 	{
524 		// check for DDE first
525 		if (xPropSet->getPropertySetInfo()->hasPropertyByName(sDdeCommandFile))
526 		{
527 			// data source DDE
528 			// unfortunately, we have to test all relevant strings for
529 			// non-zero length
530 			aAny = xPropSet->getPropertyValue(sDdeCommandFile);
531 			OUString sApplication;
532 			aAny >>= sApplication;
533 			aAny = xPropSet->getPropertyValue(sDdeCommandType);
534 			OUString sTopic;
535 			aAny >>= sTopic;
536 			aAny = xPropSet->getPropertyValue(sDdeCommandElement);
537 			OUString sItem;
538 			aAny >>= sItem;
539 
540 			if ( (sApplication.getLength() > 0) ||
541 				 (sTopic.getLength() > 0) ||
542 				 (sItem.getLength() > 0 )   )
543 			{
544 				GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
545 										 XML_DDE_APPLICATION, sApplication);
546 				GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_TOPIC,
547 										 sTopic);
548 				GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_ITEM,
549 										 sItem);
550 
551 				aAny = xPropSet->getPropertyValue(sIsAutomaticUpdate);
552 				if (*(sal_Bool*)aAny.getValue())
553 				{
554 					GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
555                                              XML_AUTOMATIC_UPDATE, XML_TRUE);
556 				}
557 
558 				SvXMLElementExport aElem(GetExport(),
559 										 XML_NAMESPACE_OFFICE,
560 										 XML_DDE_SOURCE, sal_True, sal_True);
561 			}
562 			// else: no DDE data source
563 		}
564 		// else: no DDE on this system
565 	}
566 }
567 
568 void XMLSectionExport::ExportTableOfContentStart(
569 	const Reference<XPropertySet> & rPropertySet)
570 {
571 	// export TOC element start
572 	ExportBaseIndexStart(XML_TABLE_OF_CONTENT, rPropertySet);
573 
574 	// scope for table-of-content-source element
575 	{
576 
577 		Any aAny;
578 
579 		// TOC specific index source attributes:
580 
581         // outline-level: 1..10
582         sal_Int16 nLevel = sal_Int16();
583         if( rPropertySet->getPropertyValue(sLevel) >>= nLevel )
584         {
585             OUStringBuffer sBuffer;
586             SvXMLUnitConverter::convertNumber(sBuffer, (sal_Int32)nLevel);
587             GetExport().AddAttribute(XML_NAMESPACE_TEXT,
588                                      XML_OUTLINE_LEVEL,
589                                      sBuffer.makeStringAndClear());
590         }
591 
592         // use outline level
593         ExportBoolean(rPropertySet, sCreateFromOutline,
594                           XML_USE_OUTLINE_LEVEL, sal_True);
595 
596 		// use index marks
597 		ExportBoolean(rPropertySet, sCreateFromMarks,
598 					  XML_USE_INDEX_MARKS, sal_True);
599 
600 		// use level styles
601 		ExportBoolean(rPropertySet, sCreateFromLevelParagraphStyles,
602 					  XML_USE_INDEX_SOURCE_STYLES, sal_False);
603 
604 		ExportBaseIndexSource(TEXT_SECTION_TYPE_TOC, rPropertySet);
605 	}
606 
607 	ExportBaseIndexBody(TEXT_SECTION_TYPE_TOC, rPropertySet);
608 }
609 
610 void XMLSectionExport::ExportObjectIndexStart(
611 	const Reference<XPropertySet> & rPropertySet)
612 {
613 	// export index start
614 	ExportBaseIndexStart(XML_OBJECT_INDEX, rPropertySet);
615 
616 	// scope for index source element
617 	{
618 		ExportBoolean(rPropertySet, sCreateFromOtherEmbeddedObjects,
619 					  XML_USE_OTHER_OBJECTS, sal_False);
620 		ExportBoolean(rPropertySet, sCreateFromStarCalc,
621 					  XML_USE_SPREADSHEET_OBJECTS, sal_False);
622 		ExportBoolean(rPropertySet, sCreateFromStarChart,
623 					  XML_USE_CHART_OBJECTS, sal_False);
624 		ExportBoolean(rPropertySet, sCreateFromStarDraw,
625 					  XML_USE_DRAW_OBJECTS, sal_False);
626 		ExportBoolean(rPropertySet, sCreateFromStarMath,
627 					  XML_USE_MATH_OBJECTS, sal_False);
628 
629 		ExportBaseIndexSource(TEXT_SECTION_TYPE_OBJECT, rPropertySet);
630 	}
631 
632 	ExportBaseIndexBody(TEXT_SECTION_TYPE_OBJECT, rPropertySet);
633 }
634 
635 void XMLSectionExport::ExportIllustrationIndexStart(
636 	const Reference<XPropertySet> & rPropertySet)
637 {
638 	// export index start
639 	ExportBaseIndexStart(XML_ILLUSTRATION_INDEX, rPropertySet);
640 
641 	// scope for index source element
642 	{
643 		// export common attributes for illustration and table indices
644 		ExportTableAndIllustrationIndexSourceAttributes(rPropertySet);
645 
646 		ExportBaseIndexSource(TEXT_SECTION_TYPE_ILLUSTRATION, rPropertySet);
647 	}
648 
649 	ExportBaseIndexBody(TEXT_SECTION_TYPE_ILLUSTRATION, rPropertySet);
650 }
651 
652 void XMLSectionExport::ExportTableIndexStart(
653 	const Reference<XPropertySet> & rPropertySet)
654 {
655 	// export index start
656 	ExportBaseIndexStart(XML_TABLE_INDEX, rPropertySet);
657 
658 	// scope for index source element
659 	{
660 		// export common attributes for illustration and table indices
661 		ExportTableAndIllustrationIndexSourceAttributes(rPropertySet);
662 
663 		ExportBaseIndexSource(TEXT_SECTION_TYPE_TABLE, rPropertySet);
664 	}
665 
666 	ExportBaseIndexBody(TEXT_SECTION_TYPE_TABLE, rPropertySet);
667 }
668 
669 void XMLSectionExport::ExportAlphabeticalIndexStart(
670 	const Reference<XPropertySet> & rPropertySet)
671 {
672 	// export TOC element start
673 	ExportBaseIndexStart(XML_ALPHABETICAL_INDEX, rPropertySet);
674 
675 	// scope for table-of-content-source element
676 	{
677 
678 		// style name (if present)
679 		Any aAny;
680 		aAny = rPropertySet->getPropertyValue(sMainEntryCharacterStyleName);
681 		OUString sStyleName;
682 		aAny >>= sStyleName;
683 		if (sStyleName.getLength())
684 		{
685 			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
686 									 XML_MAIN_ENTRY_STYLE_NAME,
687 									 GetExport().EncodeStyleName( sStyleName ));
688 		}
689 
690 		// other (boolean) attributes
691 		ExportBoolean(rPropertySet, sIsCaseSensitive, XML_IGNORE_CASE,
692 					  sal_False, sal_True);
693 		ExportBoolean(rPropertySet, sUseAlphabeticalSeparators,
694 					  XML_ALPHABETICAL_SEPARATORS, sal_False);
695 		ExportBoolean(rPropertySet, sUseCombinedEntries, XML_COMBINE_ENTRIES,
696 					  sal_True);
697 		ExportBoolean(rPropertySet, sUseDash, XML_COMBINE_ENTRIES_WITH_DASH,
698 					  sal_False);
699 		ExportBoolean(rPropertySet, sUseKeyAsEntry, XML_USE_KEYS_AS_ENTRIES,
700 					  sal_False);
701 		ExportBoolean(rPropertySet, sUsePP, XML_COMBINE_ENTRIES_WITH_PP,
702 					  sal_True);
703 		ExportBoolean(rPropertySet, sUseUpperCase, XML_CAPITALIZE_ENTRIES,
704 					  sal_False);
705 		ExportBoolean(rPropertySet, sIsCommaSeparated, XML_COMMA_SEPARATED,
706 					  sal_False);
707 
708         // sort algorithm
709         aAny = rPropertySet->getPropertyValue(sSortAlgorithm);
710         OUString sAlgorithm;
711         aAny >>= sAlgorithm;
712         if (sAlgorithm.getLength() > 0)
713         {
714             GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_SORT_ALGORITHM,
715                                       sAlgorithm );
716         }
717 
718         // locale
719         aAny = rPropertySet->getPropertyValue(sLocale);
720         Locale aLocale;
721         aAny >>= aLocale;
722         GetExport().AddAttribute(XML_NAMESPACE_FO, XML_LANGUAGE,
723                                  aLocale.Language);
724         GetExport().AddAttribute(XML_NAMESPACE_FO, XML_COUNTRY,
725                                  aLocale.Country);
726 
727 		ExportBaseIndexSource(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet);
728 	}
729 
730 	ExportBaseIndexBody(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet);
731 }
732 
733 void XMLSectionExport::ExportUserIndexStart(
734 	const Reference<XPropertySet> & rPropertySet)
735 {
736 	// export TOC element start
737 	ExportBaseIndexStart(XML_USER_INDEX, rPropertySet);
738 
739 	// scope for table-of-content-source element
740 	{
741 		// bool attributes
742 		ExportBoolean(rPropertySet, sCreateFromEmbeddedObjects,
743 					  XML_USE_OBJECTS, sal_False);
744 		ExportBoolean(rPropertySet, sCreateFromGraphicObjects,
745 					  XML_USE_GRAPHICS, sal_False);
746 		ExportBoolean(rPropertySet, sCreateFromMarks,
747 					  XML_USE_INDEX_MARKS, sal_False);
748 		ExportBoolean(rPropertySet, sCreateFromTables,
749 					  XML_USE_TABLES, sal_False);
750 		ExportBoolean(rPropertySet, sCreateFromTextFrames,
751 					  XML_USE_FLOATING_FRAMES, sal_False);
752 		ExportBoolean(rPropertySet, sUseLevelFromSource,
753 					  XML_COPY_OUTLINE_LEVELS, sal_False);
754 		ExportBoolean(rPropertySet, sCreateFromLevelParagraphStyles,
755 					  XML_USE_INDEX_SOURCE_STYLES, sal_False);
756 
757         Any aAny = rPropertySet->getPropertyValue( sUserIndexName );
758         OUString sIndexName;
759         aAny >>= sIndexName;
760         GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_INDEX_NAME,
761                                  sIndexName);
762 
763 		ExportBaseIndexSource(TEXT_SECTION_TYPE_USER, rPropertySet);
764 	}
765 
766 	ExportBaseIndexBody(TEXT_SECTION_TYPE_USER, rPropertySet);
767 }
768 
769 void XMLSectionExport::ExportBibliographyStart(
770 	const Reference<XPropertySet> & rPropertySet)
771 {
772 	// export TOC element start
773 	ExportBaseIndexStart(XML_BIBLIOGRAPHY, rPropertySet);
774 
775 	// scope for table-of-content-source element
776 	{
777 		// No attributes. Fine.
778 
779 		ExportBaseIndexSource(TEXT_SECTION_TYPE_BIBLIOGRAPHY, rPropertySet);
780 	}
781 
782 	ExportBaseIndexBody(TEXT_SECTION_TYPE_BIBLIOGRAPHY, rPropertySet);
783 }
784 
785 
786 void XMLSectionExport::ExportBaseIndexStart(
787     XMLTokenEnum eElement,
788 	const Reference<XPropertySet> & rPropertySet)
789 {
790 	// protect + protection key
791 	Any aAny = rPropertySet->getPropertyValue(sIsProtected);
792 	if (*(sal_Bool*)aAny.getValue())
793 	{
794 		GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE);
795 	}
796 
797     // index name
798     OUString sIndexName;
799     rPropertySet->getPropertyValue(sName) >>= sIndexName;
800     if ( sIndexName.getLength() > 0 )
801     {
802         GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, sIndexName);
803     }
804 
805 	// index  Element start
806 	GetExport().IgnorableWhitespace();
807 	GetExport().StartElement( XML_NAMESPACE_TEXT, eElement, sal_False );
808 }
809 
810 static const XMLTokenEnum aTypeSourceElementNameMap[] =
811 {
812 	XML_TABLE_OF_CONTENT_SOURCE,		// TOC
813 	XML_TABLE_INDEX_SOURCE,			// table index
814 	XML_ILLUSTRATION_INDEX_SOURCE,		// illustration index
815 	XML_OBJECT_INDEX_SOURCE,			// object index
816 	XML_USER_INDEX_SOURCE,				// user index
817 	XML_ALPHABETICAL_INDEX_SOURCE,		// alphabetical index
818 	XML_BIBLIOGRAPHY_SOURCE			// bibliography
819 };
820 
821 void XMLSectionExport::ExportBaseIndexSource(
822 	SectionTypeEnum eType,
823 	const Reference<XPropertySet> & rPropertySet)
824 {
825 	// check type
826 	OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
827 	OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");
828 
829 	Any aAny;
830 
831 	// common attributes; not supported by bibliography
832 	if (eType != TEXT_SECTION_TYPE_BIBLIOGRAPHY)
833 	{
834 		// document or chapter index?
835 		aAny = rPropertySet->getPropertyValue(sCreateFromChapter);
836 		if (*(sal_Bool*)aAny.getValue())
837 		{
838 			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
839                                      XML_INDEX_SCOPE, XML_CHAPTER);
840 		}
841 
842 		// tab-stops relative to margin?
843 		aAny = rPropertySet->getPropertyValue(sIsRelativeTabstops);
844 		if (! *(sal_Bool*)aAny.getValue())
845 		{
846 			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
847                                      XML_RELATIVE_TAB_STOP_POSITION,
848                                      XML_FALSE);
849 		}
850     }
851 
852 	// the index source element (all indices)
853 	SvXMLElementExport aElem(GetExport(),
854 							 XML_NAMESPACE_TEXT,
855 							 GetXMLToken(
856                                  aTypeSourceElementNameMap[
857                                     eType - TEXT_SECTION_TYPE_TOC]),
858 							 sal_True, sal_True);
859 
860 	// scope for title template (all indices)
861 	{
862 		// header style name
863 		aAny = rPropertySet->getPropertyValue(sParaStyleHeading);
864 		OUString sStyleName;
865 		aAny >>= sStyleName;
866 		GetExport().AddAttribute(XML_NAMESPACE_TEXT,
867 								 XML_STYLE_NAME,
868 								 GetExport().EncodeStyleName( sStyleName ));
869 
870 		// title template
871 		SvXMLElementExport aHeaderTemplate(GetExport(),
872 										   XML_NAMESPACE_TEXT,
873 										   XML_INDEX_TITLE_TEMPLATE,
874 										   sal_True, sal_False);
875 
876 		// title as element content
877 		aAny = rPropertySet->getPropertyValue(sTitle);
878 		OUString sTitleString;
879 		aAny >>= sTitleString;
880 		GetExport().Characters(sTitleString);
881 	}
882 
883 	// export level templates (all indices)
884 	aAny = rPropertySet->getPropertyValue(sLevelFormat);
885 	Reference<XIndexReplace> xLevelTemplates;
886 	aAny >>= xLevelTemplates;
887 
888 	// iterate over level formats;
889 	// skip element 0 (empty template for title)
890 	sal_Int32 nLevelCount = xLevelTemplates->getCount();
891 	for(sal_Int32 i = 1; i<nLevelCount; i++)
892 	{
893 		// get sequence
894 		Sequence<PropertyValues> aTemplateSequence;
895 		aAny = xLevelTemplates->getByIndex(i);
896 		aAny >>= aTemplateSequence;
897 
898 		// export the sequence (abort export if an error occured; #91214#)
899 		sal_Bool bResult =
900             ExportIndexTemplate(eType, i, rPropertySet, aTemplateSequence);
901         if ( !bResult )
902             break;
903 	}
904 
905 	// only TOC and user index:
906 	// styles from which to build the index (LevelParagraphStyles)
907 	if ( (TEXT_SECTION_TYPE_TOC == eType) ||
908 		 (TEXT_SECTION_TYPE_USER == eType)   )
909 	{
910 		aAny = rPropertySet->getPropertyValue(sLevelParagraphStyles);
911 		Reference<XIndexReplace> xLevelParagraphStyles;
912 		aAny >>= xLevelParagraphStyles;
913 		ExportLevelParagraphStyles(xLevelParagraphStyles);
914 	}
915 }
916 
917 
918 void XMLSectionExport::ExportBaseIndexBody(
919 	SectionTypeEnum
920     #if OSL_DEBUG_LEVEL > 0
921     eType
922     #endif
923     ,
924 	const Reference<XPropertySet> &)
925 {
926 	// type not used; checked anyway.
927 	OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
928 	OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");
929 
930 	// export start only
931 
932 	// any old attributes?
933 	GetExport().CheckAttrList();
934 
935 	// start surrounded by whitespace
936 	GetExport().IgnorableWhitespace();
937 	GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_BODY, sal_True );
938 }
939 
940 void XMLSectionExport::ExportTableAndIllustrationIndexSourceAttributes(
941 	const Reference<XPropertySet> & rPropertySet)
942 {
943 	// use caption
944 	Any aAny = rPropertySet->getPropertyValue(sCreateFromLabels);
945 	if (! *(sal_Bool*)aAny.getValue())
946 	{
947 		GetExport().AddAttribute(XML_NAMESPACE_TEXT,
948                                  XML_USE_CAPTION, XML_FALSE);
949 	}
950 
951 	// sequence name
952 	aAny = rPropertySet->getPropertyValue(sLabelCategory);
953 	OUString sSequenceName;
954 	aAny >>= sSequenceName;
955 	GetExport().AddAttribute(XML_NAMESPACE_TEXT,
956 							 XML_CAPTION_SEQUENCE_NAME,
957 							 sSequenceName);
958 
959 	// caption format
960 	aAny = rPropertySet->getPropertyValue(sLabelDisplayType);
961 	sal_Int16 nType = 0;
962 	aAny >>= nType;
963 	GetExport().AddAttribute(XML_NAMESPACE_TEXT,
964                              XML_CAPTION_SEQUENCE_FORMAT,
965                              XMLTextFieldExport::MapReferenceType(nType));
966 }
967 
968 
969 // map index of LevelFormats to attribute value;
970 // level 0 is always the header
971 static const XMLTokenEnum aLevelNameTOCMap[] =
972 	{ XML_TOKEN_INVALID, XML_1, XML_2, XML_3, XML_4, XML_5, XML_6, XML_7,
973 		  XML_8, XML_9, XML_10, XML_TOKEN_INVALID };
974 static const XMLTokenEnum aLevelNameTableMap[] =
975 	{ XML_TOKEN_INVALID, XML__EMPTY, XML_TOKEN_INVALID };
976 static const XMLTokenEnum aLevelNameAlphaMap[] =
977 	{ XML_TOKEN_INVALID, XML_SEPARATOR, XML_1, XML_2, XML_3, XML_TOKEN_INVALID };
978 static const XMLTokenEnum aLevelNameBibliographyMap[] =
979 	{ XML_TOKEN_INVALID, XML_ARTICLE, XML_BOOK, XML_BOOKLET, XML_CONFERENCE,
980 		  XML_CUSTOM1, XML_CUSTOM2, XML_CUSTOM3, XML_CUSTOM4,
981 		  XML_CUSTOM5, XML_EMAIL, XML_INBOOK, XML_INCOLLECTION,
982 		  XML_INPROCEEDINGS, XML_JOURNAL,
983 		  XML_MANUAL, XML_MASTERSTHESIS, XML_MISC, XML_PHDTHESIS,
984 		  XML_PROCEEDINGS, XML_TECHREPORT, XML_UNPUBLISHED, XML_WWW,
985 		  XML_TOKEN_INVALID };
986 
987 static const XMLTokenEnum* aTypeLevelNameMap[] =
988 {
989 	aLevelNameTOCMap,			// TOC
990 	aLevelNameTableMap,			// table index
991 	aLevelNameTableMap,			// illustration index
992 	aLevelNameTableMap,			// object index
993 	aLevelNameTOCMap,			// user index
994 	aLevelNameAlphaMap,			// alphabetical index
995 	aLevelNameBibliographyMap	// bibliography
996 };
997 
998 static const sal_Char* aLevelStylePropNameTOCMap[] =
999 	{ NULL, "ParaStyleLevel1", "ParaStyleLevel2", "ParaStyleLevel3",
1000 		  "ParaStyleLevel4", "ParaStyleLevel5", "ParaStyleLevel6",
1001 		  "ParaStyleLevel7", "ParaStyleLevel8", "ParaStyleLevel9",
1002 		  "ParaStyleLevel10", NULL };
1003 static const sal_Char* aLevelStylePropNameTableMap[] =
1004 	{ NULL, "ParaStyleLevel1", NULL };
1005 static const sal_Char* aLevelStylePropNameAlphaMap[] =
1006 	{ NULL, "ParaStyleSeparator", "ParaStyleLevel1", "ParaStyleLevel2",
1007 		  "ParaStyleLevel3", NULL };
1008 static const sal_Char* aLevelStylePropNameBibliographyMap[] =
1009 		  // TODO: replace with real property names, when available
1010 	{ NULL, "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
1011 		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
1012 		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
1013 		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
1014 		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
1015 		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
1016 		  "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1",
1017 		  "ParaStyleLevel1",
1018 		  NULL };
1019 
1020 static const sal_Char** aTypeLevelStylePropNameMap[] =
1021 {
1022 	aLevelStylePropNameTOCMap,			// TOC
1023 	aLevelStylePropNameTableMap,		// table index
1024 	aLevelStylePropNameTableMap,		// illustration index
1025 	aLevelStylePropNameTableMap,		// object index
1026 	aLevelStylePropNameTOCMap,			// user index
1027 	aLevelStylePropNameAlphaMap,		// alphabetical index
1028 	aLevelStylePropNameBibliographyMap	// bibliography
1029 };
1030 
1031 static const XMLTokenEnum aTypeLevelAttrMap[] =
1032 {
1033 	XML_OUTLINE_LEVEL,		// TOC
1034 	XML_TOKEN_INVALID,		// table index
1035 	XML_TOKEN_INVALID,		// illustration index
1036 	XML_TOKEN_INVALID,		// object index
1037 	XML_OUTLINE_LEVEL,		// user index
1038 	XML_OUTLINE_LEVEL,		// alphabetical index
1039 	XML_BIBLIOGRAPHY_TYPE	// bibliography
1040 };
1041 
1042 static const XMLTokenEnum aTypeElementNameMap[] =
1043 {
1044 	XML_TABLE_OF_CONTENT_ENTRY_TEMPLATE,	// TOC
1045 	XML_TABLE_INDEX_ENTRY_TEMPLATE,		// table index
1046 	XML_ILLUSTRATION_INDEX_ENTRY_TEMPLATE,	// illustration index
1047 	XML_OBJECT_INDEX_ENTRY_TEMPLATE,		// object index
1048 	XML_USER_INDEX_ENTRY_TEMPLATE,			// user index
1049 	XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE,	// alphabetical index
1050 	XML_BIBLIOGRAPHY_ENTRY_TEMPLATE		// bibliography
1051 };
1052 
1053 
1054 sal_Bool XMLSectionExport::ExportIndexTemplate(
1055 	SectionTypeEnum eType,
1056 	sal_Int32 nOutlineLevel,
1057 	const Reference<XPropertySet> & rPropertySet,
1058 	Sequence<Sequence<PropertyValue> > & rValues)
1059 {
1060 	OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
1061 	OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");
1062 	OSL_ENSURE(nOutlineLevel >= 0, "illegal outline level");
1063 
1064 	if ( (eType >= TEXT_SECTION_TYPE_TOC) &&
1065 		 (eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY) &&
1066 		 (nOutlineLevel >= 0) )
1067 	{
1068 		// get level name and level attribute name from aLevelNameMap;
1069 		const XMLTokenEnum eLevelAttrName(
1070 			aTypeLevelAttrMap[eType-TEXT_SECTION_TYPE_TOC]);
1071 		const XMLTokenEnum eLevelName(
1072 			aTypeLevelNameMap[eType-TEXT_SECTION_TYPE_TOC][nOutlineLevel]);
1073 
1074         // #92124#: some old documents may be broken, then they have
1075         // too many template levels; we need to recognize this and
1076         // export only as many as is legal for the respective index
1077         // type. To do this, we simply return an error flag, which
1078         // will then abort further template level exports.
1079 		OSL_ENSURE(XML_TOKEN_INVALID != eLevelName, "can't find level name");
1080         if ( XML_TOKEN_INVALID == eLevelName )
1081         {
1082             // output level not found? Then end of templates! #91214#
1083             return sal_False;
1084         }
1085 
1086 		// output level name
1087 		if ((XML_TOKEN_INVALID != eLevelName) && (XML_TOKEN_INVALID != eLevelAttrName))
1088 		{
1089 			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
1090 										  GetXMLToken(eLevelAttrName),
1091 										  GetXMLToken(eLevelName));
1092 		}
1093 
1094 		// paragraph level style name
1095 		const sal_Char* pPropName(
1096 			aTypeLevelStylePropNameMap[eType-TEXT_SECTION_TYPE_TOC][nOutlineLevel]);
1097 		OSL_ENSURE(NULL != pPropName, "can't find property name");
1098 		if (NULL != pPropName)
1099 		{
1100 			Any aAny = rPropertySet->getPropertyValue(
1101 				OUString::createFromAscii(pPropName));
1102 			OUString sParaStyleName;
1103 			aAny >>= sParaStyleName;
1104 			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
1105 									 XML_STYLE_NAME,
1106 									 GetExport().EncodeStyleName( sParaStyleName ));
1107 		}
1108 
1109 		// template element
1110 		const XMLTokenEnum eElementName(
1111 			aTypeElementNameMap[eType - TEXT_SECTION_TYPE_TOC]);
1112 		SvXMLElementExport aLevelTemplate(GetExport(),
1113 										  XML_NAMESPACE_TEXT,
1114 										  GetXMLToken(eElementName),
1115 										  sal_True, sal_True);
1116 
1117 		// export sequence
1118 		sal_Int32 nTemplateCount = rValues.getLength();
1119 		for(sal_Int32 nTemplateNo = 0;
1120 			nTemplateNo < nTemplateCount;
1121 			nTemplateNo++)
1122 		{
1123 			ExportIndexTemplateElement(
1124                 eType,  //i90246
1125 				rValues[nTemplateNo]);
1126 		}
1127 	}
1128 
1129     return sal_True;
1130 }
1131 
1132 
1133 enum TemplateTypeEnum
1134 {
1135 	TOK_TTYPE_ENTRY_NUMBER,
1136 	TOK_TTYPE_ENTRY_TEXT,
1137 	TOK_TTYPE_TAB_STOP,
1138 	TOK_TTYPE_TEXT,
1139 	TOK_TTYPE_PAGE_NUMBER,
1140 	TOK_TTYPE_CHAPTER_INFO,
1141 	TOK_TTYPE_HYPERLINK_START,
1142 	TOK_TTYPE_HYPERLINK_END,
1143 	TOK_TTYPE_BIBLIOGRAPHY,
1144 	TOK_TTYPE_INVALID
1145 };
1146 
1147 enum TemplateParamEnum
1148 {
1149 	TOK_TPARAM_TOKEN_TYPE,
1150 	TOK_TPARAM_CHAR_STYLE,
1151 	TOK_TPARAM_TAB_RIGHT_ALIGNED,
1152 	TOK_TPARAM_TAB_POSITION,
1153 	TOK_TPARAM_TAB_WITH_TAB, // #i21237#
1154 	TOK_TPARAM_TAB_FILL_CHAR,
1155 	TOK_TPARAM_TEXT,
1156 	TOK_TPARAM_CHAPTER_FORMAT,
1157 	TOK_TPARAM_CHAPTER_LEVEL,//i53420
1158 	TOK_TPARAM_BIBLIOGRAPHY_DATA
1159 };
1160 
1161 SvXMLEnumStringMapEntry __READONLY_DATA aTemplateTypeMap[] =
1162 {
1163 	ENUM_STRING_MAP_ENTRY( "TokenEntryNumber",  TOK_TTYPE_ENTRY_NUMBER ),
1164     ENUM_STRING_MAP_ENTRY( "TokenEntryText",    TOK_TTYPE_ENTRY_TEXT ),
1165     ENUM_STRING_MAP_ENTRY( "TokenTabStop",      TOK_TTYPE_TAB_STOP ),
1166     ENUM_STRING_MAP_ENTRY( "TokenText",         TOK_TTYPE_TEXT ),
1167 	ENUM_STRING_MAP_ENTRY( "TokenPageNumber",   TOK_TTYPE_PAGE_NUMBER ),
1168 	ENUM_STRING_MAP_ENTRY( "TokenChapterInfo",  TOK_TTYPE_CHAPTER_INFO ),
1169     ENUM_STRING_MAP_ENTRY( "TokenHyperlinkStart", TOK_TTYPE_HYPERLINK_START ),
1170 	ENUM_STRING_MAP_ENTRY( "TokenHyperlinkEnd",	TOK_TTYPE_HYPERLINK_END ),
1171 	ENUM_STRING_MAP_ENTRY( "TokenBibliographyDataField", TOK_TTYPE_BIBLIOGRAPHY ),
1172     ENUM_STRING_MAP_END()
1173 };
1174 
1175 SvXMLEnumStringMapEntry __READONLY_DATA aTemplateParamMap[] =
1176 {
1177 	ENUM_STRING_MAP_ENTRY( "TokenType",             TOK_TPARAM_TOKEN_TYPE ),
1178 	ENUM_STRING_MAP_ENTRY( "CharacterStyleName",    TOK_TPARAM_CHAR_STYLE ),
1179 	ENUM_STRING_MAP_ENTRY( "TabStopRightAligned",   TOK_TPARAM_TAB_RIGHT_ALIGNED ),
1180 	ENUM_STRING_MAP_ENTRY( "TabStopPosition",       TOK_TPARAM_TAB_POSITION ),
1181 	ENUM_STRING_MAP_ENTRY( "TabStopFillCharacter",  TOK_TPARAM_TAB_FILL_CHAR ),
1182     // #i21237#
1183 	ENUM_STRING_MAP_ENTRY( "WithTab",               TOK_TPARAM_TAB_WITH_TAB ),
1184 	ENUM_STRING_MAP_ENTRY( "Text",                  TOK_TPARAM_TEXT ),
1185 	ENUM_STRING_MAP_ENTRY( "ChapterFormat",         TOK_TPARAM_CHAPTER_FORMAT ),
1186 	ENUM_STRING_MAP_ENTRY( "ChapterLevel",          TOK_TPARAM_CHAPTER_LEVEL ),//i53420
1187 	ENUM_STRING_MAP_ENTRY( "BibliographyDataField", TOK_TPARAM_BIBLIOGRAPHY_DATA ),
1188     ENUM_STRING_MAP_END()
1189 };
1190 
1191 SvXMLEnumMapEntry __READONLY_DATA aBibliographyDataFieldMap[] =
1192 {
1193 	{ XML_ADDRESS,				BibliographyDataField::ADDRESS },
1194 	{ XML_ANNOTE,				BibliographyDataField::ANNOTE },
1195 	{ XML_AUTHOR,				BibliographyDataField::AUTHOR },
1196 	{ XML_BIBLIOGRAPHY_TYPE,    BibliographyDataField::BIBILIOGRAPHIC_TYPE },
1197 	{ XML_BOOKTITLE,			BibliographyDataField::BOOKTITLE },
1198 	{ XML_CHAPTER,				BibliographyDataField::CHAPTER },
1199 	{ XML_CUSTOM1,				BibliographyDataField::CUSTOM1 },
1200 	{ XML_CUSTOM2,				BibliographyDataField::CUSTOM2 },
1201 	{ XML_CUSTOM3,				BibliographyDataField::CUSTOM3 },
1202 	{ XML_CUSTOM4,				BibliographyDataField::CUSTOM4 },
1203 	{ XML_CUSTOM5,				BibliographyDataField::CUSTOM5 },
1204 	{ XML_EDITION,				BibliographyDataField::EDITION },
1205 	{ XML_EDITOR,				BibliographyDataField::EDITOR },
1206 	{ XML_HOWPUBLISHED,		    BibliographyDataField::HOWPUBLISHED },
1207 	{ XML_IDENTIFIER,			BibliographyDataField::IDENTIFIER },
1208 	{ XML_INSTITUTION,			BibliographyDataField::INSTITUTION },
1209 	{ XML_ISBN,				    BibliographyDataField::ISBN },
1210 	{ XML_JOURNAL,				BibliographyDataField::JOURNAL },
1211 	{ XML_MONTH,				BibliographyDataField::MONTH },
1212 	{ XML_NOTE,				    BibliographyDataField::NOTE },
1213 	{ XML_NUMBER,				BibliographyDataField::NUMBER },
1214 	{ XML_ORGANIZATIONS,		BibliographyDataField::ORGANIZATIONS },
1215 	{ XML_PAGES,				BibliographyDataField::PAGES },
1216 	{ XML_PUBLISHER,			BibliographyDataField::PUBLISHER },
1217 	{ XML_REPORT_TYPE,			BibliographyDataField::REPORT_TYPE },
1218 	{ XML_SCHOOL,				BibliographyDataField::SCHOOL },
1219     { XML_SERIES,				BibliographyDataField::SERIES },
1220 	{ XML_TITLE,				BibliographyDataField::TITLE },
1221 	{ XML_URL,					BibliographyDataField::URL },
1222 	{ XML_VOLUME,				BibliographyDataField::VOLUME },
1223 	{ XML_YEAR,				    BibliographyDataField::YEAR },
1224 	{ XML_TOKEN_INVALID, 0 }
1225 };
1226 
1227 void XMLSectionExport::ExportIndexTemplateElement(
1228     SectionTypeEnum eType,  //i90246
1229     Sequence<PropertyValue> & rValues)
1230 {
1231 	// variables for template values
1232 
1233 	// char style
1234 	OUString sCharStyle;
1235 	sal_Bool bCharStyleOK = sal_False;
1236 
1237 	// text
1238 	OUString sText;
1239 	sal_Bool bTextOK = sal_False;
1240 
1241 	// tab position
1242 	sal_Bool bRightAligned = sal_False;
1243 	sal_Bool bRightAlignedOK = sal_False;
1244 
1245 	// tab position
1246 	sal_Int32 nTabPosition = 0;
1247 	sal_Bool bTabPositionOK = sal_False;
1248 
1249 	// fill character
1250 	OUString sFillChar;
1251 	sal_Bool bFillCharOK = sal_False;
1252 
1253 	// chapter format
1254 	sal_Int16 nChapterFormat = 0;
1255 	sal_Bool bChapterFormatOK = sal_False;
1256 
1257     // outline max level
1258 	sal_Int16 nLevel = 0;
1259 	sal_Bool bLevelOK = sal_False;
1260 
1261 	// Bibliography Data
1262 	sal_Int16 nBibliographyData = 0;
1263 	sal_Bool bBibliographyDataOK = sal_False;
1264 
1265     // With Tab Stop #i21237#
1266     sal_Bool bWithTabStop = sal_False;
1267     sal_Bool bWithTabStopOK = sal_False;
1268 
1269     //i90246, the ODF version being written to is:
1270     const SvtSaveOptions::ODFDefaultVersion aODFVersion = rExport.getDefaultVersion();
1271     //the above version cannot be used for old OOo (OOo 1.0) formats!
1272 
1273     // token type
1274 	enum TemplateTypeEnum nTokenType = TOK_TTYPE_INVALID;
1275 
1276 	sal_Int32 nCount = rValues.getLength();
1277 	for(sal_Int32 i = 0; i<nCount; i++)
1278 	{
1279 		sal_uInt16 nToken;
1280 		if ( SvXMLUnitConverter::convertEnum( nToken, rValues[i].Name,
1281 											  aTemplateParamMap ) )
1282 		{
1283 			// Only use direct and default values.
1284 			// Wrong. no property states, so ignore.
1285 			// if ( (beans::PropertyState_DIRECT_VALUE == rValues[i].State) ||
1286 			//      (beans::PropertyState_DEFAULT_VALUE == rValues[i].State)  )
1287 
1288 			switch (nToken)
1289 			{
1290 				case TOK_TPARAM_TOKEN_TYPE:
1291 				{
1292 					sal_uInt16 nTmp;
1293 					OUString sVal;
1294 					rValues[i].Value >>= sVal;
1295 					if (SvXMLUnitConverter::convertEnum( nTmp, sVal,
1296 														 aTemplateTypeMap))
1297 					{
1298 						nTokenType = (enum TemplateTypeEnum)nTmp;
1299 					}
1300 					break;
1301 				}
1302 
1303 				case TOK_TPARAM_CHAR_STYLE:
1304 					// only valid, if not empty
1305 					rValues[i].Value >>= sCharStyle;
1306 					bCharStyleOK = sCharStyle.getLength() > 0;
1307 					break;
1308 
1309 				case TOK_TPARAM_TEXT:
1310 					rValues[i].Value >>= sText;
1311 					bTextOK = sal_True;
1312 					break;
1313 
1314 				case TOK_TPARAM_TAB_RIGHT_ALIGNED:
1315 					bRightAligned =
1316 						*(sal_Bool *)rValues[i].Value.getValue();
1317 					bRightAlignedOK = sal_True;
1318 					break;
1319 
1320 				case TOK_TPARAM_TAB_POSITION:
1321 					rValues[i].Value >>= nTabPosition;
1322 					bTabPositionOK = sal_True;
1323 					break;
1324 
1325                 // #i21237#
1326                 case TOK_TPARAM_TAB_WITH_TAB:
1327 					bWithTabStop = *(sal_Bool *)rValues[i].Value.getValue();
1328 					bWithTabStopOK = sal_True;
1329 					break;
1330 
1331 				case TOK_TPARAM_TAB_FILL_CHAR:
1332 					rValues[i].Value >>= sFillChar;
1333 					bFillCharOK = sal_True;
1334 					break;
1335 
1336 				case TOK_TPARAM_CHAPTER_FORMAT:
1337 					rValues[i].Value >>= nChapterFormat;
1338 					bChapterFormatOK = sal_True;
1339 					break;
1340 //---> i53420
1341                 case TOK_TPARAM_CHAPTER_LEVEL:
1342                     rValues[i].Value >>= nLevel;
1343                     bLevelOK = sal_True;
1344                     break;
1345 //<---
1346 				case TOK_TPARAM_BIBLIOGRAPHY_DATA:
1347 					rValues[i].Value >>= nBibliographyData;
1348 					bBibliographyDataOK = sal_True;
1349 					break;
1350 			}
1351 		}
1352 	}
1353 
1354 	// convert type to token (and check validity) ...
1355 	XMLTokenEnum eElement(XML_TOKEN_INVALID);
1356 	switch(nTokenType)
1357 	{
1358 		case TOK_TTYPE_ENTRY_TEXT:
1359 			eElement = XML_INDEX_ENTRY_TEXT;
1360 			break;
1361 		case TOK_TTYPE_TAB_STOP:
1362 			// test validity
1363 			if ( bRightAligned || bTabPositionOK || bFillCharOK )
1364             {
1365 				eElement = XML_INDEX_ENTRY_TAB_STOP;
1366             }
1367 			break;
1368 		case TOK_TTYPE_TEXT:
1369 			// test validity
1370 			if (bTextOK)
1371             {
1372                 eElement = XML_INDEX_ENTRY_SPAN;
1373             }
1374 			break;
1375 		case TOK_TTYPE_PAGE_NUMBER:
1376 			eElement = XML_INDEX_ENTRY_PAGE_NUMBER;
1377 			break;
1378 		case TOK_TTYPE_CHAPTER_INFO:	// keyword index
1379 			eElement = XML_INDEX_ENTRY_CHAPTER;
1380 			break;
1381 		case TOK_TTYPE_ENTRY_NUMBER:	// table of content
1382 			eElement = XML_INDEX_ENTRY_CHAPTER;
1383 			break;
1384 		case TOK_TTYPE_HYPERLINK_START:
1385 			eElement = XML_INDEX_ENTRY_LINK_START;
1386 			break;
1387 		case TOK_TTYPE_HYPERLINK_END:
1388 			eElement = XML_INDEX_ENTRY_LINK_END;
1389 			break;
1390 		case TOK_TTYPE_BIBLIOGRAPHY:
1391 			if (bBibliographyDataOK)
1392             {
1393 				eElement = XML_INDEX_ENTRY_BIBLIOGRAPHY;
1394             }
1395 			break;
1396 		default:
1397 			; // unknown/unimplemented template
1398 			break;
1399 	}
1400 
1401     //--->i90246
1402     //check the ODF version being exported
1403     if( aODFVersion == SvtSaveOptions::ODFVER_011
1404         || aODFVersion == SvtSaveOptions::ODFVER_010)
1405     {
1406         bLevelOK = sal_False;
1407         if (TOK_TTYPE_CHAPTER_INFO == nTokenType)
1408         {
1409             //if we are emitting for ODF 1.1 or 1.0, this information can be used for alphabetical index only
1410             //it's not permitted in other indexes
1411             if (eType != TEXT_SECTION_TYPE_ALPHABETICAL)
1412             {
1413                 eElement = XML_TOKEN_INVALID; //not permitted, invalidate the element
1414             }
1415             else //maps format for 1.1 & 1.0
1416             {
1417                 // a few word here: OOo up to 2.4 uses the field chapter info in Alphabetical index
1418                 // in a way different from the ODF 1.1/1.0 specification:
1419                 //
1420                 // ODF1.1/1.0         OOo display in chapter info                       ODF1.2
1421                 //                    (used in alphabetical index only
1422                 //
1423                 // number             chapter number without pre/postfix                plain-number
1424                 // number-and-name    chapter number without pre/postfix plus title     plain-number-and-name
1425                 //
1426                 // with issue i89791 the reading of ODF 1.1 and 1.0 was corrected
1427                 // this one corrects the writing back from ODF 1.2 to ODF 1.1/1.0
1428                 // unfortunately if there is another application which interprets correctly ODF1.1/1.0,
1429                 // the resulting alphabetical index will be rendered wrong by OOo 2.4 version
1430                 //
1431                 switch( nChapterFormat )
1432                 {
1433                 case ChapterFormat::DIGIT:
1434                     nChapterFormat = ChapterFormat::NUMBER;
1435                     break;
1436                 case ChapterFormat::NO_PREFIX_SUFFIX:
1437                     nChapterFormat = ChapterFormat::NAME_NUMBER;
1438                     break;
1439                 }
1440             }
1441         }
1442         else if (TOK_TTYPE_ENTRY_NUMBER == nTokenType)
1443         {
1444             //in case of ODF 1.1 or 1.0 the only allowed number format is "number"
1445             //so, force it...
1446             // The only expected 'foreign' nChapterFormat is
1447             // ' ChapterFormat::DIGIT', forced to 'none, since the
1448             // 'value allowed in ODF 1.1 and 1.0 is 'number' the default
1449             // this can be obtained by simply disabling the chapter format
1450             bChapterFormatOK = sal_False;
1451         }
1452     }
1453 //<---
1454 
1455     // ... and write Element
1456 	if (eElement != XML_TOKEN_INVALID)
1457 	{
1458 		// character style (for most templates)
1459 		if (bCharStyleOK)
1460 		{
1461 			switch (nTokenType)
1462 			{
1463 				case TOK_TTYPE_ENTRY_TEXT:
1464 				case TOK_TTYPE_TEXT:
1465 				case TOK_TTYPE_PAGE_NUMBER:
1466 				case TOK_TTYPE_ENTRY_NUMBER:
1467 				case TOK_TTYPE_HYPERLINK_START:
1468 				case TOK_TTYPE_HYPERLINK_END:
1469 				case TOK_TTYPE_BIBLIOGRAPHY:
1470                 case TOK_TTYPE_CHAPTER_INFO:
1471                 case TOK_TTYPE_TAB_STOP:
1472 					GetExport().AddAttribute(XML_NAMESPACE_TEXT,
1473 											 XML_STYLE_NAME,
1474 								 GetExport().EncodeStyleName( sCharStyle) );
1475 					break;
1476 				default:
1477 					; // nothing: no character style
1478 					break;
1479 			}
1480 		}
1481 
1482 		// tab properties
1483 		if (TOK_TTYPE_TAB_STOP == nTokenType)
1484 		{
1485 			// tab type
1486 			GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_TYPE,
1487                                      bRightAligned ? XML_RIGHT : XML_LEFT);
1488 
1489 			if (bTabPositionOK && (! bRightAligned))
1490 			{
1491 				// position for left tabs (convert to measure)
1492 				OUStringBuffer sBuf;
1493 				GetExport().GetMM100UnitConverter().convertMeasure(sBuf,
1494 																 nTabPosition);
1495 				GetExport().AddAttribute(XML_NAMESPACE_STYLE,
1496 										 XML_POSITION,
1497 										 sBuf.makeStringAndClear());
1498 			}
1499 
1500 			// fill char ("leader char")
1501 			if (bFillCharOK && (sFillChar.getLength() > 0))
1502 			{
1503 				GetExport().AddAttribute(XML_NAMESPACE_STYLE,
1504 										 XML_LEADER_CHAR, sFillChar);
1505 			}
1506 
1507             // #i21237#
1508             if (bWithTabStopOK && ! bWithTabStop)
1509             {
1510                	GetExport().AddAttribute(XML_NAMESPACE_STYLE,
1511 										 XML_WITH_TAB,
1512 										 XML_FALSE);
1513             }
1514 		}
1515 
1516 		// bibliography data
1517 		if (TOK_TTYPE_BIBLIOGRAPHY == nTokenType)
1518 		{
1519 			OSL_ENSURE(bBibliographyDataOK, "need bibl data");
1520 			OUStringBuffer sBuf;
1521 			if (SvXMLUnitConverter::convertEnum( sBuf, nBibliographyData,
1522 												 aBibliographyDataFieldMap ) )
1523 			{
1524 				GetExport().AddAttribute(XML_NAMESPACE_TEXT,
1525 										 XML_BIBLIOGRAPHY_DATA_FIELD,
1526 										 sBuf.makeStringAndClear());
1527 			}
1528 		}
1529 
1530 		// chapter info
1531 		if (TOK_TTYPE_CHAPTER_INFO == nTokenType)
1532 		{
1533 			OSL_ENSURE(bChapterFormatOK, "need chapter info");
1534 			GetExport().AddAttribute(
1535 				XML_NAMESPACE_TEXT, XML_DISPLAY,
1536 				XMLTextFieldExport::MapChapterDisplayFormat(nChapterFormat));
1537 //---> i53420
1538             if (bLevelOK)
1539                 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
1540                                      OUString::valueOf((sal_Int32)nLevel));
1541 //<---
1542 		}
1543 
1544 //--->i53420
1545         if (TOK_TTYPE_ENTRY_NUMBER == nTokenType)
1546         {
1547             if (bChapterFormatOK)
1548                 GetExport().AddAttribute(
1549                     XML_NAMESPACE_TEXT, XML_DISPLAY,
1550                     XMLTextFieldExport::MapChapterDisplayFormat(nChapterFormat));
1551 
1552             if (bLevelOK)
1553                 GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL,
1554                                      OUString::valueOf((sal_Int32)nLevel));
1555         }
1556 //<---
1557 		// export template
1558 		SvXMLElementExport aTemplateElement(GetExport(), XML_NAMESPACE_TEXT,
1559 											GetXMLToken(eElement),
1560                                             sal_True, sal_False)
1561             ;
1562 
1563 		// entry text or span element: write text
1564 		if (TOK_TTYPE_TEXT == nTokenType)
1565 		{
1566 			GetExport().Characters(sText);
1567 		}
1568 	}
1569 }
1570 
1571 void XMLSectionExport::ExportLevelParagraphStyles(
1572 	Reference<XIndexReplace> & xLevelParagraphStyles)
1573 {
1574 	// iterate over levels
1575 	sal_Int32 nPLevelCount = xLevelParagraphStyles->getCount();
1576 	for(sal_Int32 nLevel = 0; nLevel < nPLevelCount; nLevel++)
1577 	{
1578 		Any aAny = xLevelParagraphStyles->getByIndex(nLevel);
1579 		Sequence<OUString> aStyleNames;
1580 		aAny >>= aStyleNames;
1581 
1582 		// export only if at least one style is contained
1583 		sal_Int32 nNamesCount = aStyleNames.getLength();
1584 		if (nNamesCount > 0)
1585 		{
1586 			// level attribute; we count 1..10; API 0..9
1587 			OUStringBuffer sBuf;
1588 			sal_Int32 nLevelPlusOne = nLevel + 1;
1589 			SvXMLUnitConverter::convertNumber(sBuf, nLevelPlusOne);
1590 			GetExport().AddAttribute(XML_NAMESPACE_TEXT,
1591 									 XML_OUTLINE_LEVEL,
1592 									 sBuf.makeStringAndClear());
1593 
1594 			// source styles element
1595 			SvXMLElementExport aParaStyles(GetExport(),
1596 										   XML_NAMESPACE_TEXT,
1597 										   XML_INDEX_SOURCE_STYLES,
1598 										   sal_True, sal_True);
1599 
1600 			// iterate over styles in this level
1601 			for(sal_Int32 nName = 0; nName < nNamesCount; nName++)
1602 			{
1603 				// stylename attribute
1604 				GetExport().AddAttribute(XML_NAMESPACE_TEXT,
1605 										 XML_STYLE_NAME,
1606 							 GetExport().EncodeStyleName( aStyleNames[nName]) );
1607 
1608 				// element
1609 				SvXMLElementExport aParaStyle(GetExport(),
1610 											  XML_NAMESPACE_TEXT,
1611 											  XML_INDEX_SOURCE_STYLE,
1612 											  sal_True, sal_False);
1613 			}
1614 		}
1615 	}
1616 }
1617 
1618 void XMLSectionExport::ExportBoolean(
1619 	const Reference<XPropertySet> & rPropSet,
1620 	const OUString& sPropertyName,
1621 	enum XMLTokenEnum eAttributeName,
1622 	sal_Bool bDefault,
1623 	sal_Bool bInvert)
1624 {
1625 	OSL_ENSURE(eAttributeName != XML_TOKEN_INVALID, "Need attribute name");
1626 
1627 	Any aAny = rPropSet->getPropertyValue(sPropertyName);
1628 	sal_Bool bTmp = *(sal_Bool*)aAny.getValue();
1629 
1630 	// value = value ^ bInvert
1631 	// omit if value == default
1632 	// negate forces sal_Bool to 0/1, making them comparable
1633 	if ((!(bTmp ^ bInvert)) != (!bDefault))
1634 	{
1635 		// export non-default value (since default is omitted)
1636 		GetExport().AddAttribute(XML_NAMESPACE_TEXT,
1637                                  eAttributeName,
1638                                  bDefault ? XML_FALSE : XML_TRUE);
1639 	}
1640 }
1641 
1642 const sal_Char sAPI_FieldMaster_Bibliography[] =
1643 								"com.sun.star.text.FieldMaster.Bibliography";
1644 const sal_Char sAPI_SortKey[] = "SortKey";
1645 const sal_Char sAPI_IsSortAscending[] = "IsSortAscending";
1646 
1647 void XMLSectionExport::ExportBibliographyConfiguration(SvXMLExport& rExport)
1648 {
1649 	// first: get field master (via text field supplier)
1650 	Reference<XTextFieldsSupplier> xTextFieldsSupp( rExport.GetModel(),
1651                                                     UNO_QUERY );
1652     if ( xTextFieldsSupp.is() )
1653     {
1654 		const OUString sFieldMaster_Bibliography(
1655 			RTL_CONSTASCII_USTRINGPARAM(sAPI_FieldMaster_Bibliography));
1656 
1657         // get bibliography field master
1658         Reference<XNameAccess> xMasters =
1659             xTextFieldsSupp->getTextFieldMasters();
1660         if ( xMasters->hasByName(sFieldMaster_Bibliography) )
1661         {
1662             Any aAny =
1663                 xMasters->getByName(sFieldMaster_Bibliography);
1664             Reference<XPropertySet> xPropSet;
1665             aAny >>= xPropSet;
1666 
1667             OSL_ENSURE( xPropSet.is(), "field master must have XPropSet" );
1668 
1669             const OUString sBracketBefore(
1670                 RTL_CONSTASCII_USTRINGPARAM("BracketBefore"));
1671             const OUString sBracketAfter(
1672                 RTL_CONSTASCII_USTRINGPARAM("BracketAfter"));
1673             const OUString sIsNumberEntries(
1674                 RTL_CONSTASCII_USTRINGPARAM("IsNumberEntries"));
1675             const OUString sIsSortByPosition(
1676                 RTL_CONSTASCII_USTRINGPARAM("IsSortByPosition"));
1677             const OUString sSortKeys(
1678                 RTL_CONSTASCII_USTRINGPARAM("SortKeys"));
1679             const OUString sSortAlgorithm(
1680                 RTL_CONSTASCII_USTRINGPARAM("SortAlgorithm"));
1681             const OUString sLocale(
1682                 RTL_CONSTASCII_USTRINGPARAM("Locale"));
1683 
1684 			OUString sTmp;
1685 
1686 			aAny = xPropSet->getPropertyValue(sBracketBefore);
1687 			aAny >>= sTmp;
1688 			rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_PREFIX, sTmp);
1689 
1690 			aAny = xPropSet->getPropertyValue(sBracketAfter);
1691 			aAny >>= sTmp;
1692 			rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_SUFFIX, sTmp);
1693 
1694 			aAny = xPropSet->getPropertyValue(sIsNumberEntries);
1695 			if (*(sal_Bool*)aAny.getValue())
1696 			{
1697 				rExport.AddAttribute(XML_NAMESPACE_TEXT,
1698                                      XML_NUMBERED_ENTRIES, XML_TRUE);
1699 			}
1700 
1701 			aAny = xPropSet->getPropertyValue(sIsSortByPosition);
1702 			if (! *(sal_Bool*)aAny.getValue())
1703 			{
1704 				rExport.AddAttribute(XML_NAMESPACE_TEXT,
1705                                      XML_SORT_BY_POSITION, XML_FALSE);
1706 			}
1707 
1708             // sort algorithm
1709             aAny = xPropSet->getPropertyValue(sSortAlgorithm);
1710             OUString sAlgorithm;
1711             aAny >>= sAlgorithm;
1712             if( sAlgorithm.getLength() > 0 )
1713             {
1714                 rExport.AddAttribute( XML_NAMESPACE_TEXT,
1715                                       XML_SORT_ALGORITHM, sAlgorithm );
1716             }
1717 
1718             // locale
1719             aAny = xPropSet->getPropertyValue(sLocale);
1720             Locale aLocale;
1721             aAny >>= aLocale;
1722             rExport.AddAttribute(XML_NAMESPACE_FO, XML_LANGUAGE,
1723                                      aLocale.Language);
1724             rExport.AddAttribute(XML_NAMESPACE_FO, XML_COUNTRY,
1725                                      aLocale.Country);
1726 
1727 			// configuration element
1728 			SvXMLElementExport aElement(rExport, XML_NAMESPACE_TEXT,
1729 										XML_BIBLIOGRAPHY_CONFIGURATION,
1730 										sal_True, sal_True);
1731 
1732 			// sort keys
1733 			aAny = xPropSet->getPropertyValue(sSortKeys);
1734 			Sequence<Sequence<PropertyValue> > aKeys;
1735 			aAny >>= aKeys;
1736 			sal_Int32 nKeysCount = aKeys.getLength();
1737 			for(sal_Int32 nKeys = 0; nKeys < nKeysCount; nKeys++)
1738 			{
1739 				Sequence<PropertyValue> & rKey = aKeys[nKeys];
1740 
1741 				sal_Int32 nKeyCount = rKey.getLength();
1742 				for(sal_Int32 nPropertyKey = 0; nPropertyKey < nKeyCount; nPropertyKey++)
1743 				{
1744 					PropertyValue& rValue = rKey[nPropertyKey];
1745 
1746 					if (rValue.Name.equalsAsciiL(sAPI_SortKey,
1747 												 sizeof(sAPI_SortKey)-1))
1748 					{
1749 						sal_Int16 nKey = 0;
1750 						rValue.Value >>= nKey;
1751 						OUStringBuffer sBuf;
1752 						if (SvXMLUnitConverter::convertEnum( sBuf, nKey,
1753 												 aBibliographyDataFieldMap ) )
1754 						{
1755 							rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_KEY,
1756 												 sBuf.makeStringAndClear());
1757 						}
1758 					}
1759 					else if (rValue.Name.equalsAsciiL(sAPI_IsSortAscending,
1760 											sizeof(sAPI_IsSortAscending)-1))
1761 					{
1762 						sal_Bool bTmp = *(sal_Bool*)rValue.Value.getValue();
1763 						rExport.AddAttribute(XML_NAMESPACE_TEXT,
1764                                              XML_SORT_ASCENDING,
1765                                              bTmp ? XML_TRUE : XML_FALSE);
1766 					}
1767 				}
1768 
1769 				SvXMLElementExport aKeyElem(rExport,
1770 											XML_NAMESPACE_TEXT, XML_SORT_KEY,
1771 											sal_True, sal_True);
1772 			}
1773 		}
1774 	}
1775 }
1776 
1777 
1778 sal_Bool XMLSectionExport::IsMuteSection(
1779 	const Reference<XTextSection> & rSection) const
1780 {
1781 	sal_Bool bRet = sal_False;
1782 
1783 	// a section is mute if
1784 	// 1) it exists
1785 	// 2) the SaveLinkedSections flag (at the export) is false
1786 	// 3) the IsGlobalDocumentSection property is true
1787     // 4) it is not an Index
1788 
1789 	if ( (!rExport.IsSaveLinkedSections()) && rSection.is() )
1790 	{
1791 		// walk the section chain and set bRet if any is linked
1792 		for(Reference<XTextSection> aSection(rSection);
1793 			aSection.is();
1794 			aSection = aSection->getParentSection())
1795 		{
1796 			// check if it is a global document section (linked or index)
1797 			Reference<XPropertySet> xPropSet(aSection, UNO_QUERY);
1798 			if (xPropSet.is())
1799 			{
1800 				Any aAny = xPropSet->getPropertyValue(sIsGlobalDocumentSection);
1801 
1802                 if ( *(sal_Bool*)aAny.getValue() )
1803                 {
1804                     Reference<XDocumentIndex> xIndex;
1805                     if (! GetIndex(rSection, xIndex))
1806                     {
1807                         bRet = sal_True;
1808 
1809                         // early out if result is known
1810                         break;
1811                     }
1812                 }
1813 			}
1814 			// section has no properties: ignore
1815 		}
1816 	}
1817 	// else: no section, or always save sections: default (false)
1818 
1819 	return bRet;
1820 }
1821 
1822 sal_Bool XMLSectionExport::IsMuteSection(
1823 	const Reference<XTextContent> & rSection,
1824 	sal_Bool bDefault) const
1825 {
1826 	// default: like default argument
1827 	sal_Bool bRet = bDefault;
1828 
1829 	Reference<XPropertySet> xPropSet(rSection->getAnchor(), UNO_QUERY);
1830 	if (xPropSet.is())
1831 	{
1832 		if (xPropSet->getPropertySetInfo()->hasPropertyByName(sTextSection))
1833 		{
1834 			Any aAny = xPropSet->getPropertyValue(sTextSection);
1835 			Reference<XTextSection> xSection;
1836 			aAny >>= xSection;
1837 
1838 			bRet = IsMuteSection(xSection);
1839 		}
1840 		// else: return default
1841 	}
1842 	// else: return default
1843 
1844 	return bRet;
1845 }
1846 
1847 sal_Bool XMLSectionExport::IsInSection(
1848 	const Reference<XTextSection> & rEnclosingSection,
1849 	const Reference<XTextContent> & rContent,
1850 	sal_Bool bDefault)
1851 {
1852 	// default: like default argument
1853 	sal_Bool bRet = bDefault;
1854 	OSL_ENSURE(rEnclosingSection.is(), "enclosing section expected");
1855 
1856 	Reference<XPropertySet> xPropSet(rContent, UNO_QUERY);
1857 	if (xPropSet.is())
1858 	{
1859 		if (xPropSet->getPropertySetInfo()->hasPropertyByName(sTextSection))
1860 		{
1861 			Any aAny = xPropSet->getPropertyValue(sTextSection);
1862 			Reference<XTextSection> xSection;
1863 			aAny >>= xSection;
1864 
1865 			// now walk chain of text sections (if we have one)
1866 			if (xSection.is())
1867 			{
1868 				do
1869 				{
1870 					bRet = (rEnclosingSection == xSection);
1871 					xSection = xSection->getParentSection();
1872 				}
1873 				while (!bRet && xSection.is());
1874 			}
1875 			else
1876 				bRet = sal_False;	// no section -> can't be inside
1877 		}
1878 		// else: no TextSection property -> return default
1879 	}
1880 	// else: no XPropertySet -> return default
1881 
1882 	return bRet;
1883 }
1884 
1885 
1886 void XMLSectionExport::ExportMasterDocHeadingDummies()
1887 {
1888 	if( bHeadingDummiesExported )
1889 		return;
1890 
1891 	Reference< XChapterNumberingSupplier > xCNSupplier( rExport.GetModel(),
1892 														UNO_QUERY );
1893 
1894 	Reference< XIndexReplace > xChapterNumbering;
1895 	if( xCNSupplier.is() )
1896 		xChapterNumbering = xCNSupplier->getChapterNumberingRules();
1897 
1898 	if( !xChapterNumbering.is() )
1899 		return;
1900 
1901 	sal_Int32 nCount = xChapterNumbering->getCount();
1902 	for( sal_Int32 nLevel = 0; nLevel < nCount; nLevel++ )
1903 	{
1904 		OUString sStyle;
1905 		Sequence<PropertyValue> aProperties;
1906 		xChapterNumbering->getByIndex( nLevel ) >>= aProperties;
1907 		for( sal_Int32 i = 0; i < aProperties.getLength(); i++ )
1908 		{
1909 			if( aProperties[i].Name == sHeadingStyleName )
1910 			{
1911 				aProperties[i].Value >>= sStyle;
1912 				break;
1913 			}
1914 		}
1915 		if( sStyle.getLength() > 0 )
1916 		{
1917 			GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME,
1918 									  GetExport().EncodeStyleName( sStyle ) );
1919 
1920 			OUStringBuffer sTmp;
1921 			sTmp.append( nLevel + 1 );
1922 			GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_LEVEL,
1923 								  	  sTmp.makeStringAndClear() );
1924 			SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_H,
1925 								  	  sal_True, sal_False );
1926 		}
1927 	}
1928 
1929 	bHeadingDummiesExported  = sal_True;
1930 }
1931