xref: /trunk/main/sw/source/filter/xml/xmlexpit.cxx (revision c9a23c92)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 #include "xmlexpit.hxx"
27 
28 #include <xmloff/xmluconv.hxx>
29 #include <rtl/ustrbuf.hxx>
30 #include <svl/itempool.hxx>
31 #include <svl/poolitem.hxx>
32 #include <svl/itemset.hxx>
33 #include <xmloff/attrlist.hxx>
34 #include <xmloff/nmspmap.hxx>
35 #include <xmloff/xmlnmspe.hxx>
36 #include <editeng/xmlcnitm.hxx>
37 #include <xmloff/xmlexp.hxx>
38 #include <editeng/memberids.hrc>
39 
40 #ifndef _SVSTDARR_USHORTS
41 #define _SVSTDARR_USHORTS
42 #include <svl/svstdarr.hxx>
43 #endif
44 
45 
46 #include "hintids.hxx"
47 #include "unomid.h"
48 #include <svx/unomid.hxx>
49 #include <editeng/lrspitem.hxx>
50 #include <editeng/ulspitem.hxx>
51 #include <editeng/shaditem.hxx>
52 #include <editeng/boxitem.hxx>
53 #include <editeng/brkitem.hxx>
54 #include <editeng/keepitem.hxx>
55 #include <editeng/brshitem.hxx>
56 #include "fmtpdsc.hxx"
57 #include "fmtornt.hxx"
58 #include "fmtfsize.hxx"
59 
60 #ifndef _FMTLSPLT_HXX
61 #include "fmtlsplt.hxx"
62 #endif
63 #include "xmlithlp.hxx"
64 
65 #include "fmtrowsplt.hxx"
66 
67 
68 using ::rtl::OUString;
69 using ::rtl::OUStringBuffer;
70 using namespace ::com::sun::star;
71 using namespace ::xmloff::token;
72 using uno::Any;
73 
74 /** fills the given attribute list with the items in the given set */
exportXML(const SvXMLExport & rExport,SvXMLAttributeList & rAttrList,const SfxItemSet & rSet,const SvXMLUnitConverter & rUnitConverter,const SvXMLNamespaceMap & rNamespaceMap,sal_uInt16 nFlags,SvUShorts * pIndexArray) const75 void SvXMLExportItemMapper::exportXML( const SvXMLExport& rExport,
76 								SvXMLAttributeList& rAttrList,
77 								const SfxItemSet& rSet,
78 								const SvXMLUnitConverter& rUnitConverter,
79 								const SvXMLNamespaceMap& rNamespaceMap,
80 								sal_uInt16 nFlags,
81 								SvUShorts* pIndexArray ) const
82 {
83 	const sal_uInt16 nCount = mrMapEntries->getCount();
84 	sal_uInt16 nIndex = 0;
85 
86 	while( nIndex < nCount )
87 	{
88 		SvXMLItemMapEntry* pEntry = mrMapEntries->getByIndex( nIndex );
89 
90 		// we have a valid map entry here, so lets use it...
91 		if( 0 == (pEntry->nMemberId & MID_SW_FLAG_NO_ITEM_EXPORT) )
92 		{
93 			const SfxPoolItem* pItem = GetItem( rSet, pEntry->nWhichId,
94 												nFlags );
95 			// do we have an item?
96 			if(pItem)
97 			{
98 				if( 0 != (pEntry->nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT) )
99 				{
100 					// element items do not add any properties,
101 					// we export it later
102 					if( pIndexArray )
103 						pIndexArray->Insert( nIndex, pIndexArray->Count() );
104 
105 				}
106 				else
107 				{
108 					exportXML( rExport, rAttrList, *pItem, *pEntry, rUnitConverter,
109 						   	   rNamespaceMap, nFlags, &rSet );
110 				}
111 			}
112 		}
113 		else
114 		{
115 			handleNoItem( rAttrList, *pEntry, rUnitConverter, rNamespaceMap,
116 						  rSet );
117 		}
118 		nIndex++;
119 	}
120 }
121 
exportXML(const SvXMLExport & rExport,SvXMLAttributeList & rAttrList,const SfxPoolItem & rItem,const SvXMLItemMapEntry & rEntry,const SvXMLUnitConverter & rUnitConverter,const SvXMLNamespaceMap & rNamespaceMap,sal_uInt16,const SfxItemSet * pSet) const122 void SvXMLExportItemMapper::exportXML( const SvXMLExport& rExport,
123 								 SvXMLAttributeList& rAttrList,
124 								 const SfxPoolItem& rItem,
125 								 const SvXMLItemMapEntry& rEntry,
126 								 const SvXMLUnitConverter& rUnitConverter,
127 								 const SvXMLNamespaceMap& rNamespaceMap,
128 								 sal_uInt16 /*nFlags*/,
129 								 const SfxItemSet *pSet ) const
130 {
131 	if( 0 != (rEntry.nMemberId & MID_SW_FLAG_SPECIAL_ITEM_EXPORT) )
132 	{
133 		if( rItem.ISA( SwFmtRowSplit ) )
134 		{
135 			OUString aValue;
136 			bool bAddAttribute = true;
137 			if( rEntry.nNameSpace == XML_NAMESPACE_STYLE )
138 			{
139 				if( (rExport.getExportFlags() & EXPORT_SAVEBACKWARDCOMPATIBLE ) == 0 ||
140 					!QueryXMLValue(rItem, aValue,
141 					static_cast< sal_uInt16 >( rEntry.nMemberId & MID_SW_FLAG_MASK ),
142 					rUnitConverter ) )
143 				{
144 					bAddAttribute = false;
145 				}
146 			}
147 			else
148 			{
149 				OUStringBuffer aOut;
150 				const SfxBoolItem* pSplit = PTR_CAST(SfxBoolItem, &rItem);
151 				DBG_ASSERT( pSplit != NULL, "Wrong Which-ID" );
152 				sal_uInt16 eEnum = pSplit->GetValue() ? 1 : 0;
153 				rUnitConverter.convertEnum( aOut, eEnum, aXML_KeepTogetherType );
154 				aValue = aOut.makeStringAndClear();
155 			}
156 			if( bAddAttribute )
157 			{
158 				OUString sName( rNamespaceMap.GetQNameByKey( rEntry.nNameSpace,
159                             	GetXMLToken(rEntry.eLocalName) ) );
160 				rAttrList.AddAttribute( sName, aValue );
161 			}
162         }
163 		if( rItem.ISA( SvXMLAttrContainerItem ) )
164 		{
165 			SvXMLNamespaceMap *pNewNamespaceMap = 0;
166 			const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
167 
168 			const SvXMLAttrContainerItem *pUnknown =
169 				PTR_CAST( SvXMLAttrContainerItem, &rItem );
170 
171 			sal_uInt16 nCount = pUnknown->GetAttrCount();
172 			OUStringBuffer sName;
173 			for( sal_uInt16 i=0; i < nCount; i++ )
174 			{
175 				OUString sPrefix( pUnknown->GetAttrPrefix( i ) );
176 				if( sPrefix.getLength() )
177 				{
178 					OUString sNamespace( pUnknown->GetAttrNamespace( i ) );
179 
180 					// if the prefix isn't defined yet or has another meaning,
181 					// we have to redefine it now.
182 					sal_uInt16 nIdx =   pNamespaceMap->GetIndexByPrefix( sPrefix );
183 					if( USHRT_MAX == nIdx ||
184 						pNamespaceMap->GetNameByIndex( nIdx ) != sNamespace )
185 					{
186 						if( !pNewNamespaceMap )
187 						{
188 							pNewNamespaceMap =
189 										new SvXMLNamespaceMap( rNamespaceMap );
190 							pNamespaceMap = pNewNamespaceMap;
191 						}
192 						pNewNamespaceMap->Add( sPrefix, sNamespace );
193 
194 						sName.append( GetXMLToken(XML_XMLNS) );
195 						sName.append( sal_Unicode(':') );
196 						sName.append( sPrefix );
197 						rAttrList.AddAttribute( sName.makeStringAndClear(),
198 												sNamespace );
199 					}
200 
201 					sName.append( sPrefix );
202 					sName.append( sal_Unicode(':') );
203 				}
204 
205 				sName.append( pUnknown->GetAttrLName( i ) );
206 				rAttrList.AddAttribute( sName.makeStringAndClear(),
207 										pUnknown->GetAttrValue(i) );
208 			}
209 
210 			delete pNewNamespaceMap;
211 		}
212 		else
213 		{
214 			handleSpecialItem( rAttrList, rEntry, rItem, rUnitConverter,
215 						   	   rNamespaceMap, pSet );
216 		}
217 	}
218 	else if( 0 == (rEntry.nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT) )
219 	{
220 		OUString aValue;
221 		if( QueryXMLValue(rItem, aValue,
222 						  static_cast< sal_uInt16 >(
223 							  			rEntry.nMemberId & MID_SW_FLAG_MASK ),
224 							 rUnitConverter ) )
225 		{
226 			OUString sName(
227 				rNamespaceMap.GetQNameByKey( rEntry.nNameSpace,
228 											 GetXMLToken(rEntry.eLocalName)));
229 			rAttrList.AddAttribute( sName, aValue );
230 		}
231 	}
232 }
233 
exportElementItems(SvXMLExport & rExport,const SvXMLUnitConverter & rUnitConverter,const SfxItemSet & rSet,sal_uInt16 nFlags,const SvUShorts & rIndexArray) const234 void SvXMLExportItemMapper::exportElementItems(
235 						  SvXMLExport& rExport,
236 						  const SvXMLUnitConverter& rUnitConverter,
237 						  const SfxItemSet &rSet,
238 						  sal_uInt16 nFlags,
239 						  const SvUShorts& rIndexArray ) const
240 {
241 	const sal_uInt16 nCount = rIndexArray.Count();
242 
243 	sal_Bool bItemsExported = sal_False;
244 	for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
245 	{
246 		const sal_uInt16 nElement = rIndexArray.GetObject( nIndex );
247 		SvXMLItemMapEntry* pEntry = mrMapEntries->getByIndex( nElement );
248 		DBG_ASSERT( 0 != (pEntry->nMemberId & MID_SW_FLAG_ELEMENT_ITEM_EXPORT),
249 					"wrong mid flag!" );
250 
251 		const SfxPoolItem* pItem = GetItem( rSet, pEntry->nWhichId, nFlags );
252 		// do we have an item?
253 		if(pItem)
254 		{
255             rExport.IgnorableWhitespace();
256 			handleElementItem( rExport, *pEntry, *pItem, rUnitConverter,
257 							   rSet, nFlags);
258 			bItemsExported = sal_True;
259 		}
260 	}
261 
262 	if( bItemsExported )
263 		rExport.IgnorableWhitespace();
264 }
265 
266 /** returns the item with the givin WhichId from the given ItemSet if its
267     set or its default item if its not set and the XML_EXPORT_FLAG_DEEP
268 	is set in the flags
269 */
GetItem(const SfxItemSet & rSet,sal_uInt16 nWhichId,sal_uInt16 nFlags)270 const SfxPoolItem* SvXMLExportItemMapper::GetItem( const SfxItemSet& rSet,
271 												   sal_uInt16 nWhichId,
272 												   sal_uInt16 nFlags )
273 {
274 	// first get item from itemset
275 	const SfxPoolItem* pItem;
276 	SfxItemState eState =
277 		rSet.GetItemState( nWhichId,
278 						   ( nFlags & XML_EXPORT_FLAG_DEEP ) != 0,
279 						   &pItem );
280 
281 	if( SFX_ITEM_SET == eState )
282 	{
283 		return pItem;
284 	}
285 	else if( (nFlags & XML_EXPORT_FLAG_DEFAULTS) != 0 &&
286 			  SFX_WHICH_MAX > nWhichId )
287 	{
288 		// if its not set, try the pool if we export defaults
289 		return &rSet.GetPool()->GetDefaultItem(nWhichId);
290 	}
291 	else
292 	{
293 		return NULL;
294 	}
295 }
296 
SvXMLExportItemMapper(SvXMLItemMapEntriesRef rMapEntries)297 SvXMLExportItemMapper::SvXMLExportItemMapper( SvXMLItemMapEntriesRef rMapEntries )
298 {
299 	mrMapEntries = rMapEntries;
300 }
301 
~SvXMLExportItemMapper()302 SvXMLExportItemMapper::~SvXMLExportItemMapper()
303 {
304 }
305 
exportXML(SvXMLExport & rExport,const SfxItemSet & rSet,const SvXMLUnitConverter & rUnitConverter,XMLTokenEnum ePropToken,sal_uInt16 nFlags) const306 void SvXMLExportItemMapper::exportXML( SvXMLExport& rExport,
307 					const SfxItemSet& rSet,
308 					const SvXMLUnitConverter& rUnitConverter,
309 					XMLTokenEnum ePropToken,
310 					sal_uInt16 nFlags ) const
311 {
312 	SvUShorts aIndexArray;
313 
314 	exportXML( rExport, rExport.GetAttrList(), rSet, rUnitConverter,
315                rExport.GetNamespaceMap(), nFlags, &aIndexArray );
316 
317 	if( rExport.GetAttrList().getLength() > 0L ||
318 	    (nFlags & XML_EXPORT_FLAG_EMPTY) != 0 ||
319 	    aIndexArray.Count() != 0 )
320 	{
321 		if( (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0 )
322 		{
323 			rExport.IgnorableWhitespace();
324 		}
325 
326         SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, ePropToken,
327                                   sal_False, sal_False );
328 		exportElementItems( rExport, rUnitConverter,
329                             rSet, nFlags, aIndexArray );
330 	}
331 }
332 
333 /** this method is called for every item that has the
334 	MID_SW_FLAG_SPECIAL_ITEM_EXPORT flag set */
handleSpecialItem(SvXMLAttributeList &,const SvXMLItemMapEntry &,const SfxPoolItem &,const SvXMLUnitConverter &,const SvXMLNamespaceMap &,const SfxItemSet *) const335 void SvXMLExportItemMapper::handleSpecialItem( SvXMLAttributeList& /*rAttrList*/,
336 									const SvXMLItemMapEntry& /*rEntry*/,
337 									const SfxPoolItem& /*rItem*/,
338 									const SvXMLUnitConverter& /*rUnitConverter*/,
339 									const SvXMLNamespaceMap& /*rNamespaceMap*/,
340 									const SfxItemSet* /*pSet*/ /* = NULL */ ) const
341 {
342 	DBG_ERROR( "special item not handled in xml export" );
343 }
344 
345 /** this method is called for every item that has the
346 	MID_SW_FLAG_NO_ITEM_EXPORT flag set */
handleNoItem(SvXMLAttributeList &,const SvXMLItemMapEntry &,const SvXMLUnitConverter &,const SvXMLNamespaceMap &,const SfxItemSet &) const347 void SvXMLExportItemMapper::handleNoItem( SvXMLAttributeList& /*rAttrList*/,
348 							   const SvXMLItemMapEntry& /*rEntry*/,
349 							   const SvXMLUnitConverter& /*rUnitConverter*/,
350 							   const SvXMLNamespaceMap& /*rNamespaceMap*/,
351 							   const SfxItemSet& /*rSet*/ ) const
352 {
353 	DBG_ERROR( "no item not handled in xml export" );
354 }
355 
356 /** this method is called for every item that has the
357 	MID_SW_FLAG_ELEMENT_EXPORT flag set */
handleElementItem(SvXMLExport &,const SvXMLItemMapEntry &,const SfxPoolItem &,const SvXMLUnitConverter &,const SfxItemSet &,sal_uInt16) const358 void SvXMLExportItemMapper::handleElementItem(
359                         SvXMLExport& /*rExport*/,
360 						const SvXMLItemMapEntry& /*rEntry*/,
361 						const SfxPoolItem& /*rItem*/,
362 						const SvXMLUnitConverter& /*rUnitConverter*/,
363 						const SfxItemSet& /*rSet*/,
364 						sal_uInt16 /*nFlags*/ ) const
365 {
366 	DBG_ERROR( "element item not handled in xml export" );
367 }
368 
369 
QueryXMLValue(const SfxPoolItem & rItem,OUString & rValue,sal_uInt16 nMemberId,const SvXMLUnitConverter & rUnitConverter)370 sal_Bool SvXMLExportItemMapper::QueryXMLValue(
371     const SfxPoolItem& rItem,
372     OUString& rValue,
373     sal_uInt16 nMemberId,
374     const SvXMLUnitConverter& rUnitConverter )
375 {
376     sal_Bool bOk = sal_False;
377     OUStringBuffer aOut;
378 
379     switch ( rItem.Which() )
380     {
381 
382         case RES_LR_SPACE:
383         {
384             const SvxLRSpaceItem* pLRSpace = PTR_CAST(SvxLRSpaceItem, &rItem);
385             DBG_ASSERT( pLRSpace != NULL, "Wrong Which-ID!" );
386 
387             bOk = sal_True;
388             switch( nMemberId )
389             {
390                 case  MID_L_MARGIN:
391                     if(pLRSpace->GetPropLeft() != 100)
392                         rUnitConverter.convertPercent( aOut, pLRSpace->GetPropLeft() );
393                     else
394                         rUnitConverter.convertMeasure( aOut, pLRSpace->GetLeft() );
395                     break;
396 
397                 case  MID_R_MARGIN:
398                     if(pLRSpace->GetPropRight() != 100)
399                         rUnitConverter.convertPercent( aOut, pLRSpace->GetPropRight() );
400                     else
401                         rUnitConverter.convertMeasure( aOut, pLRSpace->GetRight() );
402                     break;
403 
404                 case MID_FIRST_AUTO:
405                     if( pLRSpace->IsAutoFirst() )
406                         rUnitConverter.convertBool( aOut, pLRSpace->IsAutoFirst() );
407                     else
408                         bOk = sal_False;
409                     break;
410 
411                 case  MID_FIRST_LINE_INDENT:
412                     if( !pLRSpace->IsAutoFirst() )
413                     {
414                         if(pLRSpace->GetPropTxtFirstLineOfst() != 100)
415                             rUnitConverter.convertPercent(
416                                 aOut, pLRSpace->GetPropTxtFirstLineOfst() );
417                         else
418                             rUnitConverter.convertMeasure( aOut, pLRSpace->GetTxtFirstLineOfst() );
419                     }
420                     else
421                         bOk = sal_False;
422                     break;
423 
424                 default:
425                     DBG_ERROR( "unknown member id!");
426                     bOk = sal_False;
427                     break;
428             }
429         }
430         break;
431 
432         case RES_UL_SPACE:
433         {
434             const SvxULSpaceItem* pULSpace = PTR_CAST(SvxULSpaceItem, &rItem);
435             DBG_ASSERT( pULSpace != NULL, "Wrong Which-ID!" );
436 
437             switch( nMemberId )
438             {
439                 case MID_UP_MARGIN:
440                     if( pULSpace->GetPropUpper() != 100 )
441                         rUnitConverter.convertPercent( aOut, pULSpace->GetPropUpper() );
442                     else
443                         rUnitConverter.convertMeasure( aOut, pULSpace->GetUpper() );
444                     break;
445 
446                 case MID_LO_MARGIN:
447                     if( pULSpace->GetPropLower() != 100 )
448                         rUnitConverter.convertPercent( aOut, pULSpace->GetPropLower() );
449                     else
450                         rUnitConverter.convertMeasure( aOut, pULSpace->GetLower() );
451                     break;
452 
453                 default:
454                     DBG_ERROR("unknown MemberId");
455             };
456 
457             bOk = sal_True;
458         }
459         break;
460 
461         case RES_SHADOW:
462         {
463             const SvxShadowItem* pShadow = PTR_CAST(SvxShadowItem, &rItem);
464             DBG_ASSERT( pShadow != NULL, "Wrong Which-ID" );
465 
466             sal_Int32 nX = 1, nY = 1;
467             switch( pShadow->GetLocation() )
468                 {
469                 case SVX_SHADOW_TOPLEFT:
470                     nX = -1;
471                     nY = -1;
472                     break;
473                 case SVX_SHADOW_TOPRIGHT:
474                     nY = -1;
475                     break;
476                 case SVX_SHADOW_BOTTOMLEFT:
477                     nX = -1;
478                     break;
479                 case SVX_SHADOW_BOTTOMRIGHT:
480                     break;
481                 case SVX_SHADOW_NONE:
482                 default:
483                     rValue = GetXMLToken(XML_NONE);
484                     return sal_True;
485                 }
486 
487             nX *= pShadow->GetWidth();
488             nY *= pShadow->GetWidth();
489 
490             rUnitConverter.convertColor( aOut, pShadow->GetColor() );
491             aOut.append( sal_Unicode(' ') );
492             rUnitConverter.convertMeasure( aOut, nX );
493             aOut.append( sal_Unicode(' ') );
494             rUnitConverter.convertMeasure( aOut, nY );
495 
496             bOk = sal_True;
497         }
498         break;
499 
500         case RES_BOX:
501         {
502             SvxBoxItem* pBox = PTR_CAST(SvxBoxItem, &rItem);
503             DBG_ASSERT( pBox != NULL, "Wrong WHich-ID" );
504 
505             /**
506                xml -> MemberId
507 
508                border-padding			ALL_BORDER_PADDING
509                border-padding-before	LEFT_BORDER_PADDING
510                border-padding-after	RIGHT_BORDER_PADDING
511                border-padding-start	TOP_BORDER_PADDING
512                border-padding-end		BOTTOM_BORDER_PADDING
513 
514                border					ALL_BORDER
515                border-before			LEFT_BORDER
516                border-after			RIGHT_BORDER
517                border-start			TOP_BORDER
518                border-end				BOTTOM_BORDER
519 
520                border-line-width			ALL_BORDER_LINE_WIDTH
521                border-line-width-before	LEFT_BORDER_LINE_WIDTH
522                border-line-width-after		RIGHT_BORDER_LINE_WIDTH
523                border-line-width-start		TOP_BORDER_LINE_WIDTH
524                border-line-width-end		BOTTOM_BORDER_LINE_WIDTH
525             */
526 
527             const SvxBorderLine* pLeft    = pBox->GetLeft();
528             const SvxBorderLine* pRight   = pBox->GetRight();
529             const SvxBorderLine* pTop     = pBox->GetTop();
530             const SvxBorderLine* pBottom  = pBox->GetBottom();
531             sal_uInt16 nTopDist     = pBox->GetDistance( BOX_LINE_TOP );
532             sal_uInt16 nBottomDist  = pBox->GetDistance( BOX_LINE_BOTTOM );
533             sal_uInt16 nLeftDist    = pBox->GetDistance( BOX_LINE_LEFT );
534             sal_uInt16 nRightDist   = pBox->GetDistance( BOX_LINE_RIGHT );
535 
536 
537             // check if we need to export it
538             switch( nMemberId )
539             {
540                 case ALL_BORDER_PADDING:
541                 case LEFT_BORDER_PADDING:
542                 case RIGHT_BORDER_PADDING:
543                 case TOP_BORDER_PADDING:
544                 case BOTTOM_BORDER_PADDING:
545                 {
546                     sal_Bool bEqual = nLeftDist == nRightDist &&
547                                       nLeftDist == nTopDist &&
548                                       nLeftDist == nBottomDist;
549                     // don't export individual paddings if all paddings are equal and
550                     // don't export all padding if some paddings are not equal
551                     if( (bEqual && ALL_BORDER_PADDING != nMemberId) ||
552                         (!bEqual && ALL_BORDER_PADDING == nMemberId) )
553                         return sal_False;
554                 }
555                 break;
556                 case ALL_BORDER:
557                 case LEFT_BORDER:
558                 case RIGHT_BORDER:
559                 case TOP_BORDER:
560                 case BOTTOM_BORDER:
561                 {
562                     sal_Bool bEqual = ( NULL == pTop && NULL == pBottom &&
563                                         NULL == pLeft && NULL == pRight ) ||
564                                       ( pTop && pBottom && pLeft && pRight &&
565                                        *pTop == *pBottom  && *pTop == *pLeft &&
566                                         *pTop == *pRight );
567 
568                     // don't export individual borders if all are the same and
569                     // don't export all borders if some are not equal
570                     if( (bEqual && ALL_BORDER != nMemberId) ||
571                         (!bEqual && ALL_BORDER == nMemberId) )
572                         return sal_False;
573                 }
574                 break;
575                 case ALL_BORDER_LINE_WIDTH:
576                 case LEFT_BORDER_LINE_WIDTH:
577                 case RIGHT_BORDER_LINE_WIDTH:
578                 case TOP_BORDER_LINE_WIDTH:
579                 case BOTTOM_BORDER_LINE_WIDTH:
580                 {
581                     // if no line is set, there is nothing to export
582                     if( !pTop && !pBottom && !pLeft && !pRight )
583                         return sal_False;
584 
585                     sal_Bool bEqual = NULL != pTop &&
586                                       NULL != pBottom &&
587                                       NULL != pLeft &&
588                                       NULL != pRight;
589 
590                     if( bEqual )
591                     {
592                         const sal_uInt16 nDistance = pTop->GetDistance();
593                         const sal_uInt16 nInWidth  = pTop->GetInWidth();
594                         const sal_uInt16 nOutWidth = pTop->GetOutWidth();
595 
596                         bEqual = nDistance == pLeft->GetDistance() &&
597                                  nInWidth  == pLeft->GetInWidth()  &&
598                                  nOutWidth == pLeft->GetOutWidth() &&
599                                  nDistance == pRight->GetDistance()  &&
600                                  nInWidth  == pRight->GetInWidth()   &&
601                                  nOutWidth == pRight->GetOutWidth()  &&
602                                  nDistance == pBottom->GetDistance()  &&
603                                  nInWidth  == pBottom->GetInWidth()   &&
604                                  nOutWidth == pBottom->GetOutWidth();
605                     }
606 
607                     switch( nMemberId )
608                     {
609                         case ALL_BORDER_LINE_WIDTH:
610                             if( !bEqual || pTop->GetDistance() == 0 )
611                                 return sal_False;
612                             break;
613                         case LEFT_BORDER_LINE_WIDTH:
614                             if( bEqual || NULL == pLeft ||
615                                 0 == pLeft->GetDistance() )
616                                 return sal_False;
617                             break;
618                         case RIGHT_BORDER_LINE_WIDTH:
619                             if( bEqual || NULL == pRight ||
620                                 0 == pRight->GetDistance() )
621                                 return sal_False;
622                             break;
623                         case TOP_BORDER_LINE_WIDTH:
624                             if( bEqual || NULL == pTop ||
625                                 0 == pTop->GetDistance() )
626                                 return sal_False;
627                             break;
628                         case BOTTOM_BORDER_LINE_WIDTH:
629                             if( bEqual || NULL == pBottom ||
630                                 0 == pBottom->GetDistance() )
631                                 return sal_False;
632                             break;
633                     }
634                 }
635                 break;
636             }
637 
638             // now export it export
639             switch( nMemberId )
640                 {
641                     // padding
642                 case ALL_BORDER_PADDING:
643                 case LEFT_BORDER_PADDING:
644                     rUnitConverter.convertMeasure( aOut, nLeftDist );
645                     break;
646                 case RIGHT_BORDER_PADDING:
647                     rUnitConverter.convertMeasure( aOut, nRightDist );
648                     break;
649                 case TOP_BORDER_PADDING:
650                     rUnitConverter.convertMeasure( aOut, nTopDist );
651                     break;
652                 case BOTTOM_BORDER_PADDING:
653                     rUnitConverter.convertMeasure( aOut, nBottomDist );
654                     break;
655 
656                     // border
657                 case ALL_BORDER:
658                 case LEFT_BORDER:
659                 case RIGHT_BORDER:
660                 case TOP_BORDER:
661                 case BOTTOM_BORDER:
662                 {
663                     const SvxBorderLine* pLine;
664                     switch( nMemberId )
665                     {
666                     case ALL_BORDER:
667                     case LEFT_BORDER:
668                         pLine = pLeft;
669                         break;
670                     case RIGHT_BORDER:
671                         pLine = pRight;
672                         break;
673                     case TOP_BORDER:
674                         pLine = pTop;
675                         break;
676                     case BOTTOM_BORDER:
677                         pLine = pBottom;
678                         break;
679                     default:
680                         pLine = NULL;
681                         break;
682                     }
683 
684                     if( NULL != pLine )
685                     {
686                         sal_Int32 nWidth = pLine->GetOutWidth();
687                         const sal_uInt16 nDistance = pLine->GetDistance();
688                         if( 0 != nDistance )
689                         {
690                             nWidth += nDistance;
691                             nWidth += pLine->GetInWidth();
692                         }
693 
694                         enum XMLTokenEnum eStyle =
695                             (0 == nDistance) ? XML_SOLID : XML_DOUBLE;
696 
697                         rUnitConverter.convertMeasure( aOut, nWidth );
698                         aOut.append( sal_Unicode( ' ' ) );
699                         aOut.append( GetXMLToken( eStyle ) );
700                         aOut.append( sal_Unicode( ' ' ) );
701                         rUnitConverter.convertColor( aOut, pLine->GetColor() );
702 
703                     }
704                     else
705                     {
706                         aOut.append( GetXMLToken(XML_NONE) );
707                     }
708                 }
709                 break;
710 
711                 // width
712                 case ALL_BORDER_LINE_WIDTH:
713                 case LEFT_BORDER_LINE_WIDTH:
714                 case RIGHT_BORDER_LINE_WIDTH:
715                 case TOP_BORDER_LINE_WIDTH:
716                 case BOTTOM_BORDER_LINE_WIDTH:
717                     const SvxBorderLine* pLine;
718                     switch( nMemberId )
719                     {
720                     case ALL_BORDER_LINE_WIDTH:
721                     case LEFT_BORDER_LINE_WIDTH:
722                         pLine = pLeft;
723                         break;
724                     case RIGHT_BORDER_LINE_WIDTH:
725                         pLine = pRight;
726                         break;
727                     case TOP_BORDER_LINE_WIDTH:
728                         pLine = pTop;
729                         break;
730                     case BOTTOM_BORDER_LINE_WIDTH:
731                         pLine = pBottom;
732                         break;
733                     default:
734                         return sal_False;
735                     }
736                     rUnitConverter.convertMeasure( aOut, pLine->GetInWidth() );
737                     aOut.append( sal_Unicode( ' ' ) );
738                     rUnitConverter.convertMeasure( aOut, pLine->GetDistance() );
739                     aOut.append( sal_Unicode( ' ' ) );
740                     rUnitConverter.convertMeasure( aOut, pLine->GetOutWidth() );
741                     break;
742                 }
743 
744             bOk = sal_True;
745         }
746         break;
747 
748         case RES_BREAK:
749         {
750             const SvxFmtBreakItem* pFmtBreak = PTR_CAST(SvxFmtBreakItem, &rItem);
751             DBG_ASSERT( pFmtBreak != NULL, "Wrong Which-ID" );
752 
753             sal_uInt16 eEnum = 0;
754 
755             switch( nMemberId )
756             {
757             case MID_BREAK_BEFORE:
758                 switch( pFmtBreak->GetValue() )
759                 {
760                     case SVX_BREAK_COLUMN_BEFORE:
761                         eEnum = 1;
762                         break;
763                     case SVX_BREAK_PAGE_BEFORE:
764                         eEnum = 2;
765                         break;
766                     case SVX_BREAK_NONE:
767                         eEnum = 0;
768                         break;
769                     default:
770                         return sal_False;
771                 }
772                 break;
773             case MID_BREAK_AFTER:
774                 switch( pFmtBreak->GetValue() )
775                 {
776                     case SVX_BREAK_COLUMN_AFTER:
777                         eEnum = 1;
778                         break;
779                     case SVX_BREAK_PAGE_AFTER:
780                         eEnum = 2;
781                         break;
782                     case SVX_BREAK_NONE:
783                         eEnum = 0;
784                         break;
785                     default:
786                         return sal_False;
787                 }
788                 break;
789             }
790 
791             bOk = rUnitConverter.convertEnum( aOut, eEnum, psXML_BreakType );
792         }
793         break;
794 
795         case RES_KEEP:
796         {
797             SvxFmtKeepItem* pFmtKeep = PTR_CAST(SvxFmtKeepItem, &rItem);
798             DBG_ASSERT( pFmtKeep != NULL, "Wrong Which-ID" );
799 
800             aOut.append( pFmtKeep->GetValue()
801                          ? GetXMLToken( XML_ALWAYS )
802                          : GetXMLToken( XML_AUTO ) );
803             bOk = sal_True;
804         }
805         break;
806 
807         case RES_BACKGROUND:
808         {
809             SvxBrushItem* pBrush = PTR_CAST(SvxBrushItem, &rItem);
810             DBG_ASSERT( pBrush != NULL, "Wrong Which-ID" );
811 
812             // note: the graphic is only exported if nMemberId equals
813             //       MID_GRAPHIC..
814             //       If not, only the color or transparency is exported
815 
816             switch( nMemberId )
817             {
818                 case MID_BACK_COLOR:
819                     if ( pBrush->GetColor().GetTransparency() )
820                         aOut.append( GetXMLToken(XML_TRANSPARENT) );
821                     else
822                         rUnitConverter.convertColor( aOut, pBrush->GetColor());
823                     bOk = sal_True;
824                     break;
825 
826                 case MID_GRAPHIC_LINK:
827                     if( pBrush->GetGraphicPos() != GPOS_NONE )
828                     {
829                         uno::Any aAny;
830                         pBrush->QueryValue( aAny, MID_GRAPHIC_URL );
831                         OUString sTmp;
832                         aAny >>= sTmp;
833                         aOut.append( sTmp );
834                         bOk = sal_True;
835                     }
836                     break;
837 
838                 case MID_GRAPHIC_POSITION:
839                     switch( pBrush->GetGraphicPos() )
840                     {
841                     case GPOS_LT:
842                     case GPOS_MT:
843                     case GPOS_RT:
844                         aOut.append( GetXMLToken(XML_TOP) );
845                         bOk = sal_True;
846                         break;
847                     case GPOS_LM:
848                     case GPOS_MM:
849                     case GPOS_RM:
850                         aOut.append( GetXMLToken(XML_CENTER) );
851                         bOk = sal_True;
852                         break;
853                     case GPOS_LB:
854                     case GPOS_MB:
855                     case GPOS_RB:
856                         aOut.append( GetXMLToken(XML_BOTTOM) );
857                         bOk = sal_True;
858                         break;
859 					default:
860 						;
861                     }
862 
863                     if( bOk )
864                     {
865                         aOut.append( sal_Unicode( ' ' ) );
866 
867                         switch( pBrush->GetGraphicPos() )
868                         {
869                         case GPOS_LT:
870                         case GPOS_LB:
871                         case GPOS_LM:
872                             aOut.append( GetXMLToken(XML_LEFT) );
873                             break;
874                         case GPOS_MT:
875                         case GPOS_MM:
876                         case GPOS_MB:
877                             aOut.append( GetXMLToken(XML_CENTER) );
878                             break;
879                         case GPOS_RM:
880                         case GPOS_RT:
881                         case GPOS_RB:
882                             aOut.append( GetXMLToken(XML_RIGHT) );
883                             break;
884 						default:
885 							;
886                         }
887                     }
888                     break;
889 
890                 case MID_GRAPHIC_REPEAT:
891                 {
892                     SvxGraphicPosition eGraphicPos = pBrush->GetGraphicPos();
893                     if( GPOS_AREA == eGraphicPos )
894                     {
895                         aOut.append( GetXMLToken(XML_BACKGROUND_STRETCH)  );
896                         bOk = sal_True;
897                     }
898                     else if( GPOS_NONE != eGraphicPos && GPOS_TILED != eGraphicPos  )
899                     {
900                         aOut.append( GetXMLToken(XML_BACKGROUND_NO_REPEAT) );
901                         bOk = sal_True;
902                     }
903                 }
904                 break;
905 
906                 case MID_GRAPHIC_FILTER:
907                     if( pBrush->GetGraphicPos() != GPOS_NONE &&
908                         pBrush->GetGraphicFilter() )
909                     {
910                         aOut.append( pBrush->GetGraphicFilter()->GetBuffer() );
911                         bOk = sal_True;
912                     }
913                     break;
914             }
915         }
916         break;
917 
918         case RES_PAGEDESC:
919         {
920             const SwFmtPageDesc* pPageDesc = PTR_CAST(SwFmtPageDesc, &rItem);
921             DBG_ASSERT( pPageDesc != NULL, "Wrong Which-ID" );
922 
923             if( MID_PAGEDESC_PAGENUMOFFSET==nMemberId )
924             {
925                 sal_Int32 const number(pPageDesc->GetNumOffset());
926                 if (0 >= number)
927                 {
928                     aOut.append(GetXMLToken(XML_AUTO));
929                 }
930                 else // #i114163# positiveInteger only!
931                 {
932                     rUnitConverter.convertNumber(aOut, number);
933                 }
934                 bOk = sal_True;
935             }
936         }
937         break;
938 
939         case RES_LAYOUT_SPLIT:
940         case RES_ROW_SPLIT:
941         {
942             const SfxBoolItem* pSplit = PTR_CAST(SfxBoolItem, &rItem);
943             DBG_ASSERT( pSplit != NULL, "Wrong Which-ID" );
944 
945             rUnitConverter.convertBool( aOut, pSplit->GetValue() );
946             bOk = sal_True;
947         }
948         break;
949 
950         case RES_HORI_ORIENT:
951         {
952             SwFmtHoriOrient* pHoriOrient = PTR_CAST(SwFmtHoriOrient, &rItem);
953             DBG_ASSERT( pHoriOrient != NULL, "Wrong Which-ID" );
954 
955             rUnitConverter.convertEnum( aOut, pHoriOrient->GetHoriOrient(),
956                                         aXMLTableAlignMap );
957             bOk = sal_True;
958         }
959         break;
960 
961         case RES_VERT_ORIENT:
962         {
963             SwFmtVertOrient* pVertOrient = PTR_CAST(SwFmtVertOrient, &rItem);
964             DBG_ASSERT( pVertOrient != NULL, "Wrong Which-ID" );
965 
966             rUnitConverter.convertEnum( aOut, pVertOrient->GetVertOrient(),
967                                         aXMLTableVAlignMap );
968             bOk = sal_True;
969         }
970         break;
971 
972         case RES_FRM_SIZE:
973         {
974             SwFmtFrmSize* pFrmSize = PTR_CAST(SwFmtFrmSize, &rItem);
975             DBG_ASSERT( pFrmSize != NULL, "Wrong Which-ID" );
976 
977             sal_Bool bOutHeight = sal_False;
978             switch( nMemberId )
979             {
980                 case MID_FRMSIZE_REL_WIDTH:
981                     if( pFrmSize->GetWidthPercent() )
982                     {
983                         rUnitConverter.convertPercent( aOut, pFrmSize->GetWidthPercent() );
984                         bOk = sal_True;
985                     }
986                     break;
987                 case MID_FRMSIZE_MIN_HEIGHT:
988                     if( ATT_MIN_SIZE == pFrmSize->GetHeightSizeType() )
989                         bOutHeight = sal_True;
990                     break;
991                 case MID_FRMSIZE_FIX_HEIGHT:
992                     if( ATT_FIX_SIZE == pFrmSize->GetHeightSizeType() )
993                         bOutHeight = sal_True;
994                     break;
995             }
996 
997             if( bOutHeight )
998             {
999                 rUnitConverter.convertMeasure( aOut, pFrmSize->GetHeight() );
1000                 bOk = sal_True;
1001             }
1002         }
1003         break;
1004 
1005         case RES_FRAMEDIR:
1006         {
1007             Any aAny;
1008             bOk = rItem.QueryValue( aAny );
1009             if( bOk )
1010             {
1011                 const XMLPropertyHandler* pWritingModeHandler =
1012                     XMLPropertyHandlerFactory::CreatePropertyHandler(
1013                         XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT );
1014                 OUString sValue;
1015                 bOk = pWritingModeHandler->exportXML( sValue, aAny,
1016                                                       rUnitConverter );
1017                 if( bOk )
1018                     aOut.append( sValue );
1019 
1020                 delete pWritingModeHandler;  // memory leak #i120072#
1021             }
1022         }
1023         break;
1024 
1025         case RES_COLLAPSING_BORDERS:
1026         {
1027             const SfxBoolItem* pBorders = PTR_CAST(SfxBoolItem, &rItem);
1028             DBG_ASSERT( pBorders != NULL, "Wrong RES-ID" );
1029 
1030             aOut.append( pBorders->GetValue()
1031                          ? GetXMLToken( XML_COLLAPSING )
1032                          : GetXMLToken( XML_SEPARATING ) );
1033             bOk = sal_True;
1034         }
1035         break;
1036 
1037         default:
1038             DBG_ERROR("GetXMLValue not implemented for this item.");
1039             break;
1040     }
1041 
1042     if ( bOk )
1043         rValue = aOut.makeStringAndClear();
1044 
1045     return bOk;
1046 }
1047