xref: /trunk/main/xmloff/source/style/styleexp.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
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 <tools/debug.hxx>
31 #ifndef _SVSTDARR_STRINGSSORTDTOR_DECL
32 #define _SVSTDARR_STRINGSSORTDTOR
33 #include <svl/svstdarr.hxx>
34 #endif
35 #include <xmloff/nmspmap.hxx>
36 #include "xmloff/xmlnmspe.hxx"
37 #include <xmloff/xmltoken.hxx>
38 #ifndef _XMLOFF_XMLITMAP_HXX
39 //#include "xmlitmap.hxx"
40 #endif
41 #include <xmloff/xmluconv.hxx>
42 #include <xmloff/attrlist.hxx>
43 #include <xmloff/xmlprmap.hxx>
44 #include <xmloff/xmlexppr.hxx>
45 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
46 #include <com/sun/star/frame/XModel.hpp>
47 #include <com/sun/star/style/XStyleFamiliesSupplier.hpp>
48 #include <com/sun/star/style/XStyle.hpp>
49 #include <com/sun/star/container/XNameContainer.hpp>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <com/sun/star/beans/XPropertyState.hpp>
52 #ifndef _COM_SUN_STAR_DOCUMENT_XEVENTSSUPPLIER_HPP
53 #include <com/sun/star/document/XEventsSupplier.hpp>
54 #endif
55 #include <com/sun/star/text/XChapterNumberingSupplier.hpp>
56 #include <xmloff/xmlaustp.hxx>
57 #ifndef _XMLOFF_STYLEEXP_HXX
58 #include <xmloff/styleexp.hxx>
59 #endif
60 #include <xmloff/xmlexp.hxx>
61 #include <xmloff/XMLEventExport.hxx>
62 
63 using ::rtl::OUString;
64 using ::rtl::OUStringBuffer;
65 
66 using namespace ::com::sun::star;
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::style;
69 using namespace ::com::sun::star::container;
70 using namespace ::com::sun::star::beans;
71 using namespace ::com::sun::star::text;
72 using namespace ::xmloff::token;
73 
74 using ::com::sun::star::document::XEventsSupplier;
75 
76 XMLStyleExport::XMLStyleExport(
77         SvXMLExport& rExp,
78         const ::rtl::OUString& rPoolStyleName,
79         SvXMLAutoStylePoolP *pAutoStyleP ) :
80     rExport( rExp ),
81     sIsPhysical( RTL_CONSTASCII_USTRINGPARAM( "IsPhysical" ) ),
82     sIsAutoUpdate( RTL_CONSTASCII_USTRINGPARAM( "IsAutoUpdate" ) ),
83     sFollowStyle( RTL_CONSTASCII_USTRINGPARAM( "FollowStyle" ) ),
84     sNumberingStyleName( RTL_CONSTASCII_USTRINGPARAM( "NumberingStyleName" ) ),
85     sOutlineLevel( RTL_CONSTASCII_USTRINGPARAM( "OutlineLevel" ) ),//#outline level,add by zhaojianwei
86     sPoolStyleName( rPoolStyleName ),
87     pAutoStylePool( pAutoStyleP  )
88 {
89 }
90 
91 XMLStyleExport::~XMLStyleExport()
92 {
93 }
94 
95 void XMLStyleExport::exportStyleAttributes( const Reference< XStyle >& )
96 {
97 }
98 
99 void XMLStyleExport::exportStyleContent( const Reference< XStyle >& )
100 {
101 }
102 
103 sal_Bool XMLStyleExport::exportStyle(
104         const Reference< XStyle >& rStyle,
105         const OUString& rXMLFamily,
106         const UniReference < SvXMLExportPropertyMapper >& rPropMapper,
107         const Reference< XNameAccess >& xStyles,        //#outline level,add by zhaojianwei
108         const OUString* pPrefix )
109 {
110     Reference< XPropertySet > xPropSet( rStyle, UNO_QUERY );
111     Reference< XPropertySetInfo > xPropSetInfo =
112             xPropSet->getPropertySetInfo();
113     Any aAny;
114 
115     // Don't export styles that aren't existing really. This may be the
116     // case for StarOffice Writer's pool styles.
117     if( xPropSetInfo->hasPropertyByName( sIsPhysical ) )
118     {
119         aAny = xPropSet->getPropertyValue( sIsPhysical );
120         if( !*(sal_Bool *)aAny.getValue() )
121             return sal_False;
122     }
123 
124     // <style:style ...>
125     GetExport().CheckAttrList();
126 
127     // style:name="..."
128     OUString sName;
129 
130     if(pPrefix)
131         sName = *pPrefix;
132     sName += rStyle->getName();
133 
134     sal_Bool bEncoded = sal_False;
135     const OUString sEncodedStyleName(GetExport().EncodeStyleName( sName, &bEncoded ));
136     GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NAME, sEncodedStyleName );
137 
138     if( bEncoded )
139         GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_DISPLAY_NAME,
140                                  sName);
141 
142     // style:family="..."
143     if( rXMLFamily.getLength() > 0 )
144         GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY, rXMLFamily);
145 
146     // style:parent-style-name="..."
147     OUString sParentString(rStyle->getParentStyle());
148     OUString sParent;
149 
150     if(sParentString.getLength())
151     {
152         if(pPrefix)
153             sParent = *pPrefix;
154         sParent += sParentString;
155     }
156     else
157         sParent = sPoolStyleName;
158 
159     if( sParent.getLength() )
160         GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_PARENT_STYLE_NAME,
161                                   GetExport().EncodeStyleName( sParent ) );
162 
163     // style:next-style-name="..." (paragraph styles only)
164     if( xPropSetInfo->hasPropertyByName( sFollowStyle ) )
165     {
166         aAny = xPropSet->getPropertyValue( sFollowStyle );
167         OUString sNextName;
168         aAny >>= sNextName;
169         if( sName != sNextName )
170         {
171             GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_NEXT_STYLE_NAME,
172                           GetExport().EncodeStyleName( sNextName ) );
173         }
174     }
175 
176     // style:auto-update="..." (SW only)
177     if( xPropSetInfo->hasPropertyByName( sIsAutoUpdate ) )
178     {
179         aAny = xPropSet->getPropertyValue( sIsAutoUpdate );
180         if( *(sal_Bool *)aAny.getValue() )
181             GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_AUTO_UPDATE,
182                                       XML_TRUE );
183     }
184 
185     // style:default-outline-level"..." //#outline level, add by zhaojianwei.0802
186     sal_Int32 nOutlineLevel = 0;
187     if( xPropSetInfo->hasPropertyByName( sOutlineLevel ) )
188     {
189         Reference< XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
190         if( PropertyState_DIRECT_VALUE == xPropState->getPropertyState( sOutlineLevel ) )
191         {
192             aAny = xPropSet->getPropertyValue( sOutlineLevel );
193             aAny >>= nOutlineLevel;
194             if( nOutlineLevel > 0 )
195             {
196                 OUStringBuffer sTmp;
197                 sTmp.append( static_cast<sal_Int32>(nOutlineLevel));
198                 GetExport().AddAttribute( XML_NAMESPACE_STYLE,
199                                           XML_DEFAULT_OUTLINE_LEVEL,
200                                           sTmp.makeStringAndClear() );
201             }
202             else
203             {
204                 // --> OD 2009-12-29 #i104889#
205                 // empty value for style:default-outline-level does exist
206                 // since ODF 1.2. Thus, suppress its export for former versions.
207                 if ( ( GetExport().getExportFlags() & EXPORT_OASIS ) != 0 &&
208                      GetExport().getDefaultVersion() >= SvtSaveOptions::ODFVER_012 )
209                 // <--
210                 {
211                     GetExport().AddAttribute( XML_NAMESPACE_STYLE,
212                                               XML_DEFAULT_OUTLINE_LEVEL,
213                                               OUString( RTL_CONSTASCII_USTRINGPARAM( "" )));
214                 }
215             }
216         }
217     }//<-end,zhaojianwei
218 
219     // style:list-style-name="..." (SW paragarph styles only)
220     if( xPropSetInfo->hasPropertyByName( sNumberingStyleName ) )
221     {
222         Reference< XPropertyState > xPropState( xPropSet, uno::UNO_QUERY );
223         if( PropertyState_DIRECT_VALUE ==
224                 xPropState->getPropertyState( sNumberingStyleName  ) )
225         {
226             aAny = xPropSet->getPropertyValue( sNumberingStyleName );
227             if( aAny.hasValue() )
228             {
229                 OUString sListName;
230                 aAny >>= sListName;
231 
232                 // --> OD 2006-09-21 #i69523#
233                 // An direct set empty list style has to be written. Otherwise,
234                 // this information is lost and causes an error, if the parent
235                 // style has a list style set.
236                 if ( !sListName.getLength() )
237                 {
238                     GetExport().AddAttribute( XML_NAMESPACE_STYLE,
239                                               XML_LIST_STYLE_NAME,
240                                               sListName /* empty string */);
241                 }
242                 else
243                 {
244                     // --> OD 2006-09-27 #i69627#
245                     bool bSuppressListStyle( false );
246                     {
247                         if ( !GetExport().writeOutlineStyleAsNormalListStyle() )
248                         {
249                             Reference< XChapterNumberingSupplier > xCNSupplier
250                                 (GetExport().GetModel(), UNO_QUERY);
251 
252                             OUString sOutlineName;
253                             if (xCNSupplier.is())
254                             {
255                                 Reference< XIndexReplace > xNumRule
256                                     ( xCNSupplier->getChapterNumberingRules() );
257                                 DBG_ASSERT( xNumRule.is(), "no chapter numbering rules" );
258 
259                                 if (xNumRule.is())
260                                 {
261                                     Reference< XPropertySet > xNumRulePropSet
262                                         (xNumRule, UNO_QUERY);
263                                     xNumRulePropSet->getPropertyValue(
264                                         OUString(RTL_CONSTASCII_USTRINGPARAM("Name")) )
265                                         >>= sOutlineName;
266                                     bSuppressListStyle = ( sListName == sOutlineName );
267                                 }
268                             }
269                         }
270                     }
271 
272                     if ( sListName.getLength() && !bSuppressListStyle )
273                     // <--
274                     {
275                         GetExport().AddAttribute( XML_NAMESPACE_STYLE,
276                                                   XML_LIST_STYLE_NAME,
277                                   GetExport().EncodeStyleName( sListName ) );
278                     }
279                 }
280                 // <--
281             }
282         }
283         //#outline level, add by zhaojianwei.0802
284         else if( nOutlineLevel > 0 )
285         {
286 
287             bool bNoInheritedListStyle( true );
288 
289             /////////////////////////////////////////////////
290             Reference<XStyle> xStyle( xPropState, UNO_QUERY );
291             while ( xStyle.is() )
292             {
293                 OUString aParentStyle( xStyle->getParentStyle() );
294                 if ( aParentStyle.getLength() == 0 ||
295                     !xStyles->hasByName( aParentStyle ) )
296                 {
297                     break;
298                 }
299                 else
300                 {
301                     xPropState = Reference< XPropertyState >( xStyles->getByName( aParentStyle ), UNO_QUERY );
302                     if ( !xPropState.is() )
303                     {
304                         break;
305                     }
306                     if ( xPropState->getPropertyState( sNumberingStyleName ) == PropertyState_DIRECT_VALUE )
307                     {
308                         bNoInheritedListStyle = false;
309                         break;
310                     }
311                     else
312                     {
313                         xStyle = Reference<XStyle>( xPropState, UNO_QUERY );
314                     }
315                 }
316             }
317             /////////////////////////////////////////////////
318             if ( bNoInheritedListStyle )
319                 GetExport().AddAttribute( XML_NAMESPACE_STYLE,
320                                           XML_LIST_STYLE_NAME,
321                                           OUString( RTL_CONSTASCII_USTRINGPARAM( "" )));
322         }
323         //<-end,zhaojianwei
324     }
325 
326 
327     // style:pool-id="..." is not required any longer since we use
328     // english style names only
329     exportStyleAttributes( rStyle );
330 
331     // TODO: style:help-file-name="..." and style:help-id="..." can neither
332     // be modified by UI nor by API and that for, have not to be exported
333     // currently.
334 
335     {
336         // <style:style>
337         SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE, XML_STYLE,
338                                   sal_True, sal_True );
339 
340         rPropMapper->SetStyleName( sName );
341 
342         // <style:properties>
343         ::std::vector< XMLPropertyState > xPropStates =
344             rPropMapper->Filter( xPropSet );
345         rPropMapper->exportXML( GetExport(), xPropStates,
346                                 XML_EXPORT_FLAG_IGN_WS );
347 
348         rPropMapper->SetStyleName( OUString() );
349 
350         exportStyleContent( rStyle );
351 
352         // <script:events>, if they are supported by this style
353         Reference<XEventsSupplier> xEventsSupp(rStyle, UNO_QUERY);
354         GetExport().GetEventExport().Export(xEventsSupp);
355     }
356     return sal_True;
357 }
358 
359 sal_Bool XMLStyleExport::exportDefaultStyle(
360         const Reference< XPropertySet >& xPropSet,
361         const OUString& rXMLFamily,
362         const UniReference < SvXMLExportPropertyMapper >& rPropMapper )
363 {
364     Reference< XPropertySetInfo > xPropSetInfo =
365             xPropSet->getPropertySetInfo();
366 
367     Any aAny;
368 
369     // <style:default-style ...>
370     GetExport().CheckAttrList();
371 
372     {
373         // style:family="..."
374         if( rXMLFamily.getLength() > 0 )
375             GetExport().AddAttribute( XML_NAMESPACE_STYLE, XML_FAMILY,
376                                       rXMLFamily );
377         // <style:style>
378         SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_STYLE,
379                                   XML_DEFAULT_STYLE,
380                                   sal_True, sal_True );
381         // <style:properties>
382         //::std::vector< XMLPropertyState > xPropStates =
383         //  rPropMapper->FilterDefaults( xPropSet );
384         ::std::vector< XMLPropertyState > xPropStates =
385             rPropMapper->FilterDefaults( xPropSet );
386         rPropMapper->exportXML( GetExport(), xPropStates,
387                                   XML_EXPORT_FLAG_IGN_WS );
388 //      exportStyleContent( rStyle );
389     }
390     return sal_True;
391 }
392 
393 #if 0
394 void XMLStyleExport::exportStyleFamily(
395     const sal_Char *pFamily,
396     const OUString& rXMLFamily,
397     const UniReference < XMLPropertySetMapper >& rPropMapper,
398     sal_Bool bUsed, sal_uInt16 nFamily, const OUString* pPrefix)
399 {
400     const OUString sFamily(OUString::createFromAscii(pFamily ));
401     UniReference < SvXMLExportPropertyMapper > xExpPropMapper =
402         new SvXMLExportPropertyMapper( rPropMapper );
403     exportStyleFamily( sFamily, rXMLFamily, xExpPropMapper, bUsed, nFamily,
404                        pPrefix);
405 }
406 
407 void XMLStyleExport::exportStyleFamily(
408     const OUString& rFamily, const OUString& rXMLFamily,
409     const UniReference < XMLPropertySetMapper >& rPropMapper,
410     sal_Bool bUsed, sal_uInt16 nFamily, const OUString* pPrefix)
411 {
412     UniReference < SvXMLExportPropertyMapper > xExpPropMapper =
413         new SvXMLExportPropertyMapper( rPropMapper );
414     exportStyleFamily( rFamily, rXMLFamily, xExpPropMapper, bUsed, nFamily,
415                        pPrefix);
416 }
417 #endif
418 
419 void XMLStyleExport::exportStyleFamily(
420     const sal_Char *pFamily,
421     const OUString& rXMLFamily,
422     const UniReference < SvXMLExportPropertyMapper >& rPropMapper,
423     sal_Bool bUsed, sal_uInt16 nFamily, const OUString* pPrefix)
424 {
425     const OUString sFamily(OUString::createFromAscii(pFamily ));
426     exportStyleFamily( sFamily, rXMLFamily, rPropMapper, bUsed, nFamily,
427                        pPrefix);
428 }
429 
430 void XMLStyleExport::exportStyleFamily(
431     const OUString& rFamily, const OUString& rXMLFamily,
432     const UniReference < SvXMLExportPropertyMapper >& rPropMapper,
433     sal_Bool bUsed, sal_uInt16 nFamily, const OUString* pPrefix)
434 {
435     DBG_ASSERT( GetExport().GetModel().is(), "There is the model?" );
436     Reference< XStyleFamiliesSupplier > xFamiliesSupp( GetExport().GetModel(), UNO_QUERY );
437     if( !xFamiliesSupp.is() )
438         return; // family not available in current model
439 
440     Reference< XNameAccess > xStyleCont;
441 
442     Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() );
443     if( xFamilies->hasByName( rFamily ) )
444         xFamilies->getByName( rFamily ) >>= xStyleCont;
445 
446     if( !xStyleCont.is() )
447         return;
448 
449     Reference< XNameAccess > xStyles( xStyleCont, UNO_QUERY );
450     // If next styles are supported and used styles should be exported only,
451     // the next style may be unused but has to be exported, too. In this case
452     // the names of all exported styles are remembered.
453     SvStringsSortDtor *pExportedStyles = 0;
454     sal_Bool bFirstStyle = sal_True;
455 
456     const uno::Sequence< ::rtl::OUString> aSeq = xStyles->getElementNames();
457     const ::rtl::OUString* pIter = aSeq.getConstArray();
458     const ::rtl::OUString* pEnd   = pIter + aSeq.getLength();
459     for(;pIter != pEnd;++pIter)
460     {
461         Reference< XStyle > xStyle;
462         try
463         {
464             xStyles->getByName( *pIter ) >>= xStyle;
465         }
466         catch( lang::IndexOutOfBoundsException )
467         {
468             // due to bugs in prior versions it is possible that
469             // a binary file is missing some critical styles.
470             // The only possible way to deal with this is to
471             // not export them here and remain silent.
472             continue;
473         }
474 
475         DBG_ASSERT( xStyle.is(), "Style not found for export!" );
476         if( xStyle.is() )
477         {
478             if( !bUsed || xStyle->isInUse() )
479             {
480                 sal_Bool bExported = exportStyle( xStyle, rXMLFamily, rPropMapper,
481                                               xStyles,pPrefix );
482                 if( bUsed && bFirstStyle && bExported  )
483                 {
484                     // If this is the first style, find out wether next styles
485                     // are supported.
486                     Reference< XPropertySet > xPropSet( xStyle, UNO_QUERY );
487                     Reference< XPropertySetInfo > xPropSetInfo =
488                         xPropSet->getPropertySetInfo();
489 
490                     if( xPropSetInfo->hasPropertyByName( sFollowStyle ) )
491                         pExportedStyles = new SvStringsSortDtor;
492                     bFirstStyle = sal_False;
493                 }
494 
495                 if( pExportedStyles && bExported )
496                 {
497                     // If next styles are supported, remember this style's name.
498                     String *pTmp = new String( xStyle->getName() );
499                     if( !pExportedStyles->Insert( pTmp ) )
500                         delete pTmp;
501                 }
502             }
503 
504             // if an auto style pool is given, remember this style's name as a
505             // style name that must not be used by automatic styles.
506             if( pAutoStylePool )
507                 pAutoStylePool->RegisterName( nFamily, xStyle->getName() );
508         }
509     }
510 
511     if( pExportedStyles )
512     {
513         // if next styles are supported, export all next styles that are
514         // unused and that for, haven't been exported in the first loop.
515         pIter = aSeq.getConstArray();
516         for(;pIter != pEnd;++pIter)
517         {
518             Reference< XStyle > xStyle;
519             xStyles->getByName( *pIter ) >>= xStyle;
520 
521             DBG_ASSERT( xStyle.is(), "Style not found for export!" );
522             if( xStyle.is() )
523             {
524                 Reference< XPropertySet > xPropSet( xStyle, UNO_QUERY );
525                 Reference< XPropertySetInfo > xPropSetInfo( xPropSet->getPropertySetInfo() );
526 
527                 // styles that aren't existing realy are ignored.
528                 if( xPropSetInfo->hasPropertyByName( sIsPhysical ) )
529                 {
530                     Any aAny( xPropSet->getPropertyValue( sIsPhysical ) );
531                     if( !*(sal_Bool *)aAny.getValue() )
532                         continue;
533                 }
534 
535                 if( !xStyle->isInUse() )
536                     continue;
537 
538                 if( !xPropSetInfo->hasPropertyByName( sFollowStyle ) )
539                 {
540                     DBG_ASSERT( 0==sFollowStyle.getLength(),
541                                 "no follow style???" );
542                     continue;
543                 }
544 
545                 OUString sNextName;
546                 xPropSet->getPropertyValue( sFollowStyle ) >>= sNextName;
547                 String sTmp( sNextName );
548                 // if the next style hasn't been exported by now, export it now
549                 // and remember its name.
550                 if( xStyle->getName() != sNextName &&
551                     !pExportedStyles->Seek_Entry( &sTmp ) )
552                 {
553                     xStyleCont->getByName( sNextName ) >>= xStyle;
554                     DBG_ASSERT( xStyle.is(), "Style not found for export!" );
555 
556                     if( xStyle.is() && exportStyle( xStyle, rXMLFamily, rPropMapper, xStyles,pPrefix ) )
557                         pExportedStyles->Insert( new String( sTmp ) );
558                 }
559             }
560         }
561     }
562 
563     delete pExportedStyles;
564 }
565 
566 
567