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 <xmloff/SettingsExportHelper.hxx>
31 #include "xmloff/xmlnmspe.hxx"
32 #include <xmloff/xmltoken.hxx>
33 #include <xmloff/xmluconv.hxx>
34 #include <tools/debug.hxx>
35 #include <tools/diagnose_ex.h>
36 #include <comphelper/extract.hxx>
37 
38 #include <com/sun/star/linguistic2/XSupportedLocales.hpp>
39 #include <com/sun/star/i18n/XForbiddenCharacters.hpp>
40 #include <com/sun/star/container/XNameAccess.hpp>
41 #include <com/sun/star/container/XNameContainer.hpp>
42 #include <com/sun/star/container/XIndexContainer.hpp>
43 #include <com/sun/star/util/DateTime.hpp>
44 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
45 #include <com/sun/star/container/XIndexContainer.hpp>
46 #include <com/sun/star/formula/SymbolDescriptor.hpp>
47 #include <com/sun/star/document/PrinterIndependentLayout.hpp>
48 #include <xmloff/XMLSettingsExportContext.hxx>
49 #include <xmlenums.hxx>
50 
51 using namespace ::com::sun::star;
52 using namespace ::xmloff::token;
53 
54 XMLSettingsExportHelper::XMLSettingsExportHelper( ::xmloff::XMLSettingsExportContext& i_rContext )
55 : m_rContext( i_rContext )
56 , msPrinterIndependentLayout( RTL_CONSTASCII_USTRINGPARAM( "PrinterIndependentLayout" ) )
57 , msColorTableURL( RTL_CONSTASCII_USTRINGPARAM( "ColorTableURL" ) )
58 , msLineEndTableURL( RTL_CONSTASCII_USTRINGPARAM( "LineEndTableURL" ) )
59 , msHatchTableURL( RTL_CONSTASCII_USTRINGPARAM( "HatchTableURL" ) )
60 , msDashTableURL( RTL_CONSTASCII_USTRINGPARAM( "DashTableURL" ) )
61 , msGradientTableURL( RTL_CONSTASCII_USTRINGPARAM( "GradientTableURL" ) )
62 , msBitmapTableURL( RTL_CONSTASCII_USTRINGPARAM( "BitmapTableURL" ) )
63 {
64 }
65 
66 XMLSettingsExportHelper::~XMLSettingsExportHelper()
67 {
68 }
69 
70 void XMLSettingsExportHelper::CallTypeFunction(const uno::Any& rAny,
71 											const rtl::OUString& rName) const
72 {
73     uno::Any aAny( rAny );
74     ManipulateSetting( aAny, rName );
75 
76 	uno::TypeClass eClass = aAny.getValueTypeClass();
77 	switch (eClass)
78 	{
79 		case uno::TypeClass_VOID:
80 		{
81 			/*
82 			 * This assertion pops up when exporting values which are set to:
83 			 * PropertyAttribute::MAYBEVOID, and thus are _supposed_ to have
84 			 * a VOID value...so I'm removing it ...mtg
85 			 * DBG_ERROR("no type");
86 			 */
87 		}
88 		break;
89 		case uno::TypeClass_BOOLEAN:
90 		{
91 			exportBool(::cppu::any2bool(aAny), rName);
92 		}
93 		break;
94 		case uno::TypeClass_BYTE:
95 		{
96 			sal_Int8 nInt8 = 0;
97 			aAny >>= nInt8;
98 			exportByte(nInt8, rName);
99 		}
100 		break;
101 		case uno::TypeClass_SHORT:
102 		{
103 			sal_Int16 nInt16 = 0;
104 			aAny >>= nInt16;
105 			exportShort(nInt16, rName);
106 		}
107 		break;
108 		case uno::TypeClass_LONG:
109 		{
110 			sal_Int32 nInt32 = 0;
111 			aAny >>= nInt32;
112 			exportInt(nInt32, rName);
113 		}
114 		break;
115 		case uno::TypeClass_HYPER:
116 		{
117 			sal_Int64 nInt64 = 0;
118 			aAny >>= nInt64;
119 			exportLong(nInt64, rName);
120 		}
121 		break;
122 		case uno::TypeClass_DOUBLE:
123 		{
124 			double fDouble = 0.0;
125 			aAny >>= fDouble;
126 			exportDouble(fDouble, rName);
127 		}
128 		break;
129 		case uno::TypeClass_STRING:
130 		{
131 			rtl::OUString sString;
132 			aAny >>= sString;
133 			exportString(sString, rName);
134 		}
135 		break;
136 		default:
137 		{
138 			uno::Type aType = aAny.getValueType();
139 			if (aType.equals(getCppuType( (uno::Sequence<beans::PropertyValue> *)0 ) ) )
140 			{
141 				uno::Sequence< beans::PropertyValue> aProps;
142 				aAny >>= aProps;
143 				exportSequencePropertyValue(aProps, rName);
144 			}
145 			else if( aType.equals(getCppuType( (uno::Sequence<sal_Int8> *)0 ) ) )
146 			{
147 				uno::Sequence< sal_Int8 > aProps;
148 				aAny >>= aProps;
149 				exportbase64Binary(aProps, rName);
150 			}
151 			else if (aType.equals(getCppuType( (uno::Reference<container::XNameContainer> *)0 ) ) ||
152 					aType.equals(getCppuType( (uno::Reference<container::XNameAccess> *)0 ) ))
153 			{
154 				uno::Reference< container::XNameAccess> aNamed;
155 				aAny >>= aNamed;
156 				exportNameAccess(aNamed, rName);
157 			}
158 			else if (aType.equals(getCppuType( (uno::Reference<container::XIndexAccess> *)0 ) ) ||
159 					aType.equals(getCppuType( (uno::Reference<container::XIndexContainer> *)0 ) ) )
160 			{
161 				uno::Reference<container::XIndexAccess> aIndexed;
162 				aAny >>= aIndexed;
163 				exportIndexAccess(aIndexed, rName);
164 			}
165 			else if (aType.equals(getCppuType( (util::DateTime *)0 ) ) )
166 			{
167 				util::DateTime aDateTime;
168 				aAny >>= aDateTime;
169 				exportDateTime(aDateTime, rName);
170 			}
171 			else if( aType.equals(getCppuType( (uno::Reference<i18n::XForbiddenCharacters> *)0 ) ) )
172 			{
173 				exportForbiddenCharacters( aAny, rName );
174 			}
175 			else if( aType.equals(getCppuType( (uno::Sequence<formula::SymbolDescriptor> *)0 ) ) )
176 			{
177 				uno::Sequence< formula::SymbolDescriptor > aProps;
178 				aAny >>= aProps;
179 				exportSymbolDescriptors(aProps, rName);
180 			}
181 			else {
182 				DBG_ERROR("this type is not implemented now");
183             }
184 		}
185 		break;
186 	}
187 }
188 
189 void XMLSettingsExportHelper::exportBool(const sal_Bool bValue, const rtl::OUString& rName) const
190 {
191 	DBG_ASSERT(rName.getLength(), "no name");
192 	m_rContext.AddAttribute( XML_NAME, rName );
193 	m_rContext.AddAttribute( XML_TYPE, XML_BOOLEAN );
194     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
195 	rtl::OUString sValue;
196 	if (bValue)
197 		sValue = GetXMLToken(XML_TRUE);
198 	else
199 		sValue = GetXMLToken(XML_FALSE);
200 	m_rContext.Characters( sValue );
201     m_rContext.EndElement( sal_False );
202 }
203 
204 void XMLSettingsExportHelper::exportByte(const sal_Int8 nValue, const rtl::OUString& rName) const
205 {
206 #if 0
207 	DBG_ASSERT(rName.getLength(), "no name");
208 	m_rContext.AddAttribute( XML_NAME, rName );
209 	m_rContext.AddAttribute( XML_TYPE, XML_BYTE );
210     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
211 	rtl::OUStringBuffer sBuffer;
212 	SvXMLUnitConverter::convertNumber(sBuffer, sal_Int32(nValue));
213 	m_rContext.Characters( sBuffer.makeStringAndClear() );
214     m_rContext.EndElement( sal_False );
215 #else
216     (void) nValue; (void) rName;
217     OSL_ENSURE(false, "XMLSettingsExportHelper::exportByte(): #i114162#:\n"
218         "config-items of type \"byte\" are not valid ODF, "
219         "so storing them is disabled!\n"
220         "Use a different type instead (e.g. \"short\").");
221 #endif
222 }
223 void XMLSettingsExportHelper::exportShort(const sal_Int16 nValue, const rtl::OUString& rName) const
224 {
225 	DBG_ASSERT(rName.getLength(), "no name");
226 	m_rContext.AddAttribute( XML_NAME, rName );
227 	m_rContext.AddAttribute( XML_TYPE, XML_SHORT );
228     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
229 	rtl::OUStringBuffer sBuffer;
230 	SvXMLUnitConverter::convertNumber(sBuffer, sal_Int32(nValue));
231 	m_rContext.Characters( sBuffer.makeStringAndClear() );
232     m_rContext.EndElement( sal_False );
233 }
234 
235 void XMLSettingsExportHelper::exportInt(const sal_Int32 nValue, const rtl::OUString& rName) const
236 {
237 	DBG_ASSERT(rName.getLength(), "no name");
238 	m_rContext.AddAttribute( XML_NAME, rName );
239 	m_rContext.AddAttribute( XML_TYPE, XML_INT );
240     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
241 	rtl::OUStringBuffer sBuffer;
242 	SvXMLUnitConverter::convertNumber(sBuffer, nValue);
243 	m_rContext.Characters( sBuffer.makeStringAndClear() );
244     m_rContext.EndElement( sal_False );
245 }
246 
247 void XMLSettingsExportHelper::exportLong(const sal_Int64 nValue, const rtl::OUString& rName) const
248 {
249 	DBG_ASSERT(rName.getLength(), "no name");
250 	m_rContext.AddAttribute( XML_NAME, rName );
251 	m_rContext.AddAttribute( XML_TYPE, XML_LONG );
252     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
253 	rtl::OUString sValue(rtl::OUString::valueOf(nValue));
254 	m_rContext.Characters( sValue );
255     m_rContext.EndElement( sal_False );
256 }
257 
258 void XMLSettingsExportHelper::exportDouble(const double fValue, const rtl::OUString& rName) const
259 {
260 	DBG_ASSERT(rName.getLength(), "no name");
261 	m_rContext.AddAttribute( XML_NAME, rName );
262 	m_rContext.AddAttribute( XML_TYPE, XML_DOUBLE );
263     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
264 	rtl::OUStringBuffer sBuffer;
265 	SvXMLUnitConverter::convertDouble(sBuffer, fValue);
266 	m_rContext.Characters( sBuffer.makeStringAndClear() );
267     m_rContext.EndElement( sal_False );
268 }
269 
270 void XMLSettingsExportHelper::exportString(const rtl::OUString& sValue, const rtl::OUString& rName) const
271 {
272 	DBG_ASSERT(rName.getLength(), "no name");
273 	m_rContext.AddAttribute( XML_NAME, rName );
274 	m_rContext.AddAttribute( XML_TYPE, XML_STRING );
275     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
276 	if (sValue.getLength())
277 		m_rContext.Characters( sValue );
278     m_rContext.EndElement( sal_False );
279 }
280 
281 void XMLSettingsExportHelper::exportDateTime(const util::DateTime& aValue, const rtl::OUString& rName) const
282 {
283 	DBG_ASSERT(rName.getLength(), "no name");
284 	m_rContext.AddAttribute( XML_NAME, rName );
285 	m_rContext.AddAttribute( XML_TYPE, XML_DATETIME );
286 	rtl::OUStringBuffer sBuffer;
287 	SvXMLUnitConverter::convertDateTime(sBuffer, aValue);
288     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
289 	m_rContext.Characters( sBuffer.makeStringAndClear() );
290     m_rContext.EndElement( sal_False );
291 }
292 
293 void XMLSettingsExportHelper::exportSequencePropertyValue(
294 					const uno::Sequence<beans::PropertyValue>& aProps,
295 					const rtl::OUString& rName) const
296 {
297 	DBG_ASSERT(rName.getLength(), "no name");
298 	sal_Int32 nLength(aProps.getLength());
299 	if(nLength)
300 	{
301 		m_rContext.AddAttribute( XML_NAME, rName );
302         m_rContext.StartElement( XML_CONFIG_ITEM_SET, sal_True );
303 		for (sal_Int32 i = 0; i < nLength; i++)
304 			CallTypeFunction(aProps[i].Value, aProps[i].Name);
305         m_rContext.EndElement( sal_True );
306 	}
307 }
308 void XMLSettingsExportHelper::exportSymbolDescriptors(
309 					const uno::Sequence < formula::SymbolDescriptor > &rProps,
310 					const rtl::OUString rName) const
311 {
312 	// #110680#
313 	// uno::Reference< lang::XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() );
314 	uno::Reference< lang::XMultiServiceFactory > xServiceFactory( m_rContext.GetServiceFactory() );
315 	DBG_ASSERT( xServiceFactory.is(), "XMLSettingsExportHelper::exportSymbolDescriptors: got no service manager" );
316 
317 	if( xServiceFactory.is() )
318 	{
319 		uno::Reference< container::XIndexContainer > xBox(xServiceFactory->createInstance(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.document.IndexedPropertyValues") ) ), uno::UNO_QUERY);
320 		DBG_ASSERT( xBox.is(), "could not create service com.sun.star.document.IndexedPropertyValues" );
321 		if (xBox.is() )
322 		{
323 			const rtl::OUString sName     ( RTL_CONSTASCII_USTRINGPARAM ( "Name" ) );
324 			const rtl::OUString sExportName ( RTL_CONSTASCII_USTRINGPARAM ( "ExportName" ) );
325 			const rtl::OUString sSymbolSet ( RTL_CONSTASCII_USTRINGPARAM ( "SymbolSet" ) );
326 			const rtl::OUString sCharacter ( RTL_CONSTASCII_USTRINGPARAM ( "Character" ) );
327 			const rtl::OUString sFontName ( RTL_CONSTASCII_USTRINGPARAM ( "FontName" ) );
328 			const rtl::OUString sCharSet  ( RTL_CONSTASCII_USTRINGPARAM ( "CharSet" ) );
329 			const rtl::OUString sFamily   ( RTL_CONSTASCII_USTRINGPARAM ( "Family" ) );
330 			const rtl::OUString sPitch    ( RTL_CONSTASCII_USTRINGPARAM ( "Pitch" ) );
331 			const rtl::OUString sWeight   ( RTL_CONSTASCII_USTRINGPARAM ( "Weight" ) );
332 			const rtl::OUString sItalic   ( RTL_CONSTASCII_USTRINGPARAM ( "Italic" ) );
333 
334 			sal_Int32 nCount = rProps.getLength();
335 			const formula::SymbolDescriptor *pDescriptor = rProps.getConstArray();
336 
337 			for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++, pDescriptor++ )
338 			{
339 				uno::Sequence < beans::PropertyValue > aSequence ( XML_SYMBOL_DESCRIPTOR_MAX );
340 				beans::PropertyValue *pSymbol = aSequence.getArray();
341 
342 				pSymbol[XML_SYMBOL_DESCRIPTOR_NAME].Name         = sName;
343 				pSymbol[XML_SYMBOL_DESCRIPTOR_NAME].Value	    <<= pDescriptor->sName;
344 				pSymbol[XML_SYMBOL_DESCRIPTOR_EXPORT_NAME].Name  = sExportName;
345 				pSymbol[XML_SYMBOL_DESCRIPTOR_EXPORT_NAME].Value<<= pDescriptor->sExportName;
346 				pSymbol[XML_SYMBOL_DESCRIPTOR_FONT_NAME].Name    = sFontName;
347 				pSymbol[XML_SYMBOL_DESCRIPTOR_FONT_NAME].Value	<<= pDescriptor->sFontName;
348 				pSymbol[XML_SYMBOL_DESCRIPTOR_CHAR_SET].Name      = sCharSet;
349 				pSymbol[XML_SYMBOL_DESCRIPTOR_CHAR_SET].Value	<<= pDescriptor->nCharSet;
350 				pSymbol[XML_SYMBOL_DESCRIPTOR_FAMILY].Name       = sFamily;
351 				pSymbol[XML_SYMBOL_DESCRIPTOR_FAMILY].Value	<<= pDescriptor->nFamily;
352 				pSymbol[XML_SYMBOL_DESCRIPTOR_PITCH].Name        = sPitch;
353 				pSymbol[XML_SYMBOL_DESCRIPTOR_PITCH].Value	    <<= pDescriptor->nPitch;
354 				pSymbol[XML_SYMBOL_DESCRIPTOR_WEIGHT].Name       = sWeight;
355 				pSymbol[XML_SYMBOL_DESCRIPTOR_WEIGHT].Value	<<= pDescriptor->nWeight;
356 				pSymbol[XML_SYMBOL_DESCRIPTOR_ITALIC].Name       = sItalic;
357 				pSymbol[XML_SYMBOL_DESCRIPTOR_ITALIC].Value	<<= pDescriptor->nItalic;
358 				pSymbol[XML_SYMBOL_DESCRIPTOR_SYMBOL_SET].Name       = sSymbolSet;
359 				pSymbol[XML_SYMBOL_DESCRIPTOR_SYMBOL_SET].Value	<<= pDescriptor->sSymbolSet;
360 				pSymbol[XML_SYMBOL_DESCRIPTOR_CHARACTER].Name       = sCharacter;
361 				pSymbol[XML_SYMBOL_DESCRIPTOR_CHARACTER].Value	<<= pDescriptor->nCharacter;
362 
363 				xBox->insertByIndex(nIndex, uno::makeAny( aSequence ));
364 			}
365 
366 			uno::Reference< container::XIndexAccess > xIA( xBox, uno::UNO_QUERY );
367 			exportIndexAccess( xIA, rName );
368 		}
369 	}
370 }
371 void XMLSettingsExportHelper::exportbase64Binary(
372 					const uno::Sequence<sal_Int8>& aProps,
373 					const rtl::OUString& rName) const
374 {
375 	DBG_ASSERT(rName.getLength(), "no name");
376 	sal_Int32 nLength(aProps.getLength());
377 	m_rContext.AddAttribute( XML_NAME, rName );
378 	m_rContext.AddAttribute( XML_TYPE, XML_BASE64BINARY );
379     m_rContext.StartElement( XML_CONFIG_ITEM, sal_True );
380 	if(nLength)
381 	{
382 		rtl::OUStringBuffer sBuffer;
383 		SvXMLUnitConverter::encodeBase64(sBuffer, aProps);
384 		m_rContext.Characters( sBuffer.makeStringAndClear() );
385 	}
386     m_rContext.EndElement( sal_False );
387 }
388 
389 void XMLSettingsExportHelper::exportMapEntry(const uno::Any& rAny,
390 										const rtl::OUString& rName,
391 										const sal_Bool bNameAccess) const
392 {
393 	DBG_ASSERT((bNameAccess && rName.getLength()) || !bNameAccess, "no name");
394 	uno::Sequence<beans::PropertyValue> aProps;
395 	rAny >>= aProps;
396 	sal_Int32 nLength = aProps.getLength();
397 	if (nLength)
398 	{
399 		if (bNameAccess)
400 			m_rContext.AddAttribute( XML_NAME, rName );
401         m_rContext.StartElement( XML_CONFIG_ITEM_MAP_ENTRY, sal_True );
402 		for (sal_Int32 i = 0; i < nLength; i++)
403 			CallTypeFunction(aProps[i].Value, aProps[i].Name);
404         m_rContext.EndElement( sal_True );
405 	}
406 }
407 
408 void XMLSettingsExportHelper::exportNameAccess(
409 					const uno::Reference<container::XNameAccess>& aNamed,
410 					const rtl::OUString& rName) const
411 {
412 	DBG_ASSERT(rName.getLength(), "no name");
413 	DBG_ASSERT(aNamed->getElementType().equals(getCppuType( (uno::Sequence<beans::PropertyValue> *)0 ) ),
414 				"wrong NameAccess" );
415 	if(aNamed->hasElements())
416 	{
417 		m_rContext.AddAttribute( XML_NAME, rName );
418         m_rContext.StartElement( XML_CONFIG_ITEM_MAP_NAMED, sal_True );
419 		uno::Sequence< rtl::OUString > aNames(aNamed->getElementNames());
420 		for (sal_Int32 i = 0; i < aNames.getLength(); i++)
421 			exportMapEntry(aNamed->getByName(aNames[i]), aNames[i], sal_True);
422         m_rContext.EndElement( sal_True );
423 	}
424 }
425 
426 void XMLSettingsExportHelper::exportIndexAccess(
427 					const uno::Reference<container::XIndexAccess> aIndexed,
428 					const rtl::OUString rName) const
429 {
430 	DBG_ASSERT(rName.getLength(), "no name");
431 	DBG_ASSERT(aIndexed->getElementType().equals(getCppuType( (uno::Sequence<beans::PropertyValue> *)0 ) ),
432 				"wrong IndexAccess" );
433 	rtl::OUString sEmpty;// ( RTLCONSTASCII_USTRINGPARAM( "View" ) );
434 	if(aIndexed->hasElements())
435 	{
436 		m_rContext.AddAttribute( XML_NAME, rName );
437         m_rContext.StartElement( XML_CONFIG_ITEM_MAP_INDEXED, sal_True );
438 		sal_Int32 nCount = aIndexed->getCount();
439 		for (sal_Int32 i = 0; i < nCount; i++)
440 		{
441 			exportMapEntry(aIndexed->getByIndex(i), sEmpty, sal_False);
442 		}
443         m_rContext.EndElement( sal_True );
444 	}
445 }
446 
447 void XMLSettingsExportHelper::exportForbiddenCharacters(
448 					const uno::Any &rAny,
449 					const rtl::OUString rName) const
450 {
451 	uno::Reference<i18n::XForbiddenCharacters> xForbChars;
452 	uno::Reference<linguistic2::XSupportedLocales> xLocales;
453 
454 	rAny >>= xForbChars;
455 	rAny >>= xLocales;
456 
457 	DBG_ASSERT( xForbChars.is() && xLocales.is(),"XMLSettingsExportHelper::exportForbiddenCharacters: got illegal forbidden characters!" );
458 
459 	if( !xForbChars.is() || !xLocales.is() )
460 		return;
461 
462 	// #110680#
463 	// uno::Reference< lang::XMultiServiceFactory > xServiceFactory( comphelper::getProcessServiceFactory() );
464 	uno::Reference< lang::XMultiServiceFactory > xServiceFactory( m_rContext.GetServiceFactory() );
465 	DBG_ASSERT( xServiceFactory.is(), "XMLSettingsExportHelper::exportForbiddenCharacters: got no service manager" );
466 
467 	if( xServiceFactory.is() )
468 	{
469 		uno::Reference< container::XIndexContainer > xBox(xServiceFactory->createInstance(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ("com.sun.star.document.IndexedPropertyValues") ) ), uno::UNO_QUERY);
470 		DBG_ASSERT( xBox.is(), "could not create service com.sun.star.document.IndexedPropertyValues" );
471 		if (xBox.is() )
472 		{
473 			const uno::Sequence< lang::Locale > aLocales( xLocales->getLocales() );
474 			const lang::Locale* pLocales = aLocales.getConstArray();
475 
476 			const sal_Int32 nCount = aLocales.getLength();
477 
478 			const rtl::OUString sLanguage  ( RTL_CONSTASCII_USTRINGPARAM ( "Language" ) );
479 			const rtl::OUString sCountry   ( RTL_CONSTASCII_USTRINGPARAM ( "Country" ) );
480 			const rtl::OUString sVariant   ( RTL_CONSTASCII_USTRINGPARAM ( "Variant" ) );
481 			const rtl::OUString sBeginLine ( RTL_CONSTASCII_USTRINGPARAM ( "BeginLine" ) );
482 			const rtl::OUString sEndLine   ( RTL_CONSTASCII_USTRINGPARAM ( "EndLine" ) );
483 
484 			sal_Int32 nPos = 0;
485 			for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++, pLocales++ )
486 			{
487 				if( xForbChars->hasForbiddenCharacters( *pLocales ) )
488 				{
489 					const i18n::ForbiddenCharacters aChars( xForbChars->getForbiddenCharacters( *pLocales ) );
490 
491 
492 					uno::Sequence < beans::PropertyValue > aSequence ( XML_FORBIDDEN_CHARACTER_MAX );
493 					beans::PropertyValue *pForChar = aSequence.getArray();
494 
495 					pForChar[XML_FORBIDDEN_CHARACTER_LANGUAGE].Name    = sLanguage;
496 					pForChar[XML_FORBIDDEN_CHARACTER_LANGUAGE].Value <<= pLocales->Language;
497 					pForChar[XML_FORBIDDEN_CHARACTER_COUNTRY].Name    = sCountry;
498 					pForChar[XML_FORBIDDEN_CHARACTER_COUNTRY].Value <<= pLocales->Country;
499 					pForChar[XML_FORBIDDEN_CHARACTER_VARIANT].Name    = sVariant;
500 					pForChar[XML_FORBIDDEN_CHARACTER_VARIANT].Value <<= pLocales->Variant;
501 					pForChar[XML_FORBIDDEN_CHARACTER_BEGIN_LINE].Name    = sBeginLine;
502 					pForChar[XML_FORBIDDEN_CHARACTER_BEGIN_LINE].Value <<= aChars.beginLine;
503 					pForChar[XML_FORBIDDEN_CHARACTER_END_LINE].Name    = sEndLine;
504 					pForChar[XML_FORBIDDEN_CHARACTER_END_LINE].Value <<= aChars.endLine;
505 					xBox->insertByIndex(nPos++, uno::makeAny( aSequence ));
506 				}
507 			}
508 
509 			uno::Reference< container::XIndexAccess > xIA( xBox, uno::UNO_QUERY );
510 			exportIndexAccess( xIA, rName );
511 		}
512 	}
513 }
514 
515 void XMLSettingsExportHelper::exportAllSettings(
516 					const uno::Sequence<beans::PropertyValue>& aProps,
517 					const rtl::OUString& rName) const
518 {
519 	DBG_ASSERT(rName.getLength(), "no name");
520 	exportSequencePropertyValue(aProps, rName);
521 }
522 
523 
524 /** For some settings we may want to change their API representation
525  * from their XML settings representation. This is your chance to do
526  * so!
527  */
528 void XMLSettingsExportHelper::ManipulateSetting( uno::Any& rAny, const rtl::OUString& rName ) const
529 {
530     if( rName == msPrinterIndependentLayout )
531     {
532         sal_Int16 nTmp = sal_Int16();
533         if( rAny >>= nTmp )
534         {
535             if( nTmp == document::PrinterIndependentLayout::LOW_RESOLUTION )
536                 rAny <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("low-resolution"));
537             else if( nTmp == document::PrinterIndependentLayout::DISABLED )
538                 rAny <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("disabled"));
539             else if( nTmp == document::PrinterIndependentLayout::HIGH_RESOLUTION )
540                 rAny <<= rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("high-resolution"));
541         }
542     }
543 	else if( (rName == msColorTableURL) || (rName == msLineEndTableURL) || (rName == msHatchTableURL) ||
544 			 (rName == msDashTableURL) || (rName == msGradientTableURL) || (rName == msBitmapTableURL ) )
545 	{
546 		if( !mxStringSubsitution.is() )
547 		{
548 			if( m_rContext.GetServiceFactory().is() ) try
549 			{
550 				const_cast< XMLSettingsExportHelper* >(this)->mxStringSubsitution =
551 					uno::Reference< util::XStringSubstitution >::query(
552 						m_rContext.GetServiceFactory()->
553 							createInstance(::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.util.PathSubstitution" ) ) ) );
554 			}
555 			catch( uno::Exception& )
556 			{
557                 DBG_UNHANDLED_EXCEPTION();
558 			}
559 		}
560 
561 		if( mxStringSubsitution.is() )
562 		{
563 			::rtl::OUString aURL;
564 			rAny >>= aURL;
565 			aURL = mxStringSubsitution->reSubstituteVariables( aURL );
566 			rAny <<= aURL;
567 		}
568 	}
569 }
570