1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/urlobj.hxx>
21 #include <com/sun/star/document/XGraphicObjectResolver.hpp>
22 #include <com/sun/star/embed/ElementModes.hpp>
23 #include <com/sun/star/io/XActiveDataControl.hpp>
24 #include <com/sun/star/io/XActiveDataSource.hpp>
25 #include <com/sun/star/xml/sax/Parser.hpp>
26 #include <com/sun/star/container/XNameContainer.hpp>
27 #include <com/sun/star/xml/sax/XDocumentHandler.hpp>
28 #include <com/sun/star/uno/Sequence.hxx>
29 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
30 #include <com/sun/star/drawing/LineDash.hpp>
31 #include <com/sun/star/awt/Gradient.hpp>
32 #include <com/sun/star/drawing/Hatch.hpp>
33 #include <com/sun/star/io/XOutputStream.hpp>
34 #include <com/sun/star/io/XSeekable.hpp>
35 #include <comphelper/processfactory.hxx>
36 #include <comphelper/storagehelper.hxx>
37 #include <unotools/streamwrap.hxx>
38 #include <rtl/ustrbuf.hxx>
39 #include <sax/tools/converter.hxx>
40 #include <sfx2/docfile.hxx>
41 #include "xmloff/xmlnmspe.hxx"
42 #include "xmloff/nmspmap.hxx"
44 #include "xmloff/xmltoken.hxx"
45 #include "xmloff/xmlmetae.hxx"
46 #include "xmloff/DashStyle.hxx"
47 #include "xmloff/GradientStyle.hxx"
48 #include "xmloff/HatchStyle.hxx"
49 #include "xmloff/ImageStyle.hxx"
50 #include "xmloff/MarkerStyle.hxx"
51 #include <xmloff/xmlictxt.hxx>
52 #include "svx/xmlgrhlp.hxx"
53 #include "xmloff/attrlist.hxx"
55 #include "xmlxtimp.hxx"
59 using namespace com::sun::star
;
60 using namespace com::sun::star::container
;
61 using namespace com::sun::star::document
;
62 using namespace com::sun::star::uno
;
63 using namespace com::sun::star::awt
;
64 using namespace com::sun::star::lang
;
65 using namespace com::sun::star::xml::sax
;
66 using namespace ::xmloff::token
;
69 sal_Char
const sXML_np__office
[] = "__office";
70 sal_Char
const sXML_np__office_ooo
[] = "___office";
71 sal_Char
const sXML_np__draw
[] = "__draw";
72 sal_Char
const sXML_np__draw_ooo
[] = "___draw";
73 sal_Char
const sXML_np__ooo
[] = "__ooo";
74 sal_Char
const sXML_np__xlink
[] = "__xlink";
78 enum SvxXMLTableImportContextEnum
{ stice_unknown
, stice_color
, stice_marker
, stice_dash
, stice_hatch
, stice_gradient
, stice_bitmap
};
82 class SvxXMLTableImportContext
: public SvXMLImportContext
85 SvxXMLTableImportContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
, const uno::Reference
< XAttributeList
>& xAttrList
, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
,
87 virtual ~SvxXMLTableImportContext();
89 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
) SAL_OVERRIDE
;
92 void importColor( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
93 void importMarker( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
94 void importDash( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
95 void importHatch( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
96 void importGradient( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
97 void importBitmap( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
100 uno::Reference
< XNameContainer
> mxTable
;
101 SvxXMLTableImportContextEnum meContext
;
107 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
, const uno::Reference
< XAttributeList
>&, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
, bool bOOoFormat
)
108 : SvXMLImportContext( rImport
, nPrfx
, rLName
), mxTable( xTable
), meContext( eContext
),
109 mbOOoFormat( bOOoFormat
)
113 SvxXMLTableImportContext::~SvxXMLTableImportContext()
117 SvXMLImportContext
*SvxXMLTableImportContext::CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& rAttrList
)
119 if( XML_NAMESPACE_DRAW
== nPrefix
)
121 uno::Reference
< XAttributeList
> xAttrList( rAttrList
);
123 (stice_dash
== meContext
|| stice_hatch
== meContext
||
124 stice_bitmap
== meContext
) )
126 SvXMLAttributeList
*pAttrList
= new SvXMLAttributeList( rAttrList
);
127 xAttrList
= pAttrList
;
128 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
129 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
131 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
133 sal_uInt16 nPrefix_
=
134 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
136 if( XML_NAMESPACE_XLINK
== nPrefix_
&&
137 stice_bitmap
== meContext
&&
138 IsXMLToken( aLocalName
, XML_HREF
) )
140 const OUString rValue
= xAttrList
->getValueByIndex( i
);
141 if( !rValue
.isEmpty() && '#' == rValue
[0] )
142 pAttrList
->SetValueByIndex( i
, rValue
.copy( 1 ) );
144 else if( XML_NAMESPACE_DRAW
== nPrefix_
&&
145 ( ( stice_dash
== meContext
&&
146 (IsXMLToken( aLocalName
, XML_DOTS1_LENGTH
) ||
147 IsXMLToken( aLocalName
, XML_DOTS2_LENGTH
) ||
148 IsXMLToken( aLocalName
, XML_DISTANCE
)) ) ||
149 ( stice_hatch
== meContext
&&
150 IsXMLToken( aLocalName
, XML_HATCH_DISTANCE
) ) ) )
152 const OUString rValue
= xAttrList
->getValueByIndex( i
);
153 sal_Int32 nPos
= rValue
.getLength();
154 while( nPos
&& rValue
[nPos
-1] <= ' ' )
157 ('c'==rValue
[nPos
-2] || 'C'==rValue
[nPos
-2]) &&
158 ('h'==rValue
[nPos
-1] || 'H'==rValue
[nPos
-1]) )
160 pAttrList
->SetValueByIndex( i
, rValue
.copy( 0, nPos
-2 ) );
173 importColor( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
176 importMarker( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
179 importDash( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
182 importHatch( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
185 importGradient( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
188 importBitmap( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
194 if( !aName
.isEmpty() && aAny
.hasValue() )
196 if( mxTable
->hasByName( aName
) )
198 mxTable
->replaceByName( aName
, aAny
);
202 mxTable
->insertByName( aName
, aAny
);
206 catch (const uno::Exception
&)
211 return new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
214 void SvxXMLTableImportContext::importColor( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
219 const sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
220 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
222 const OUString
& rFullAttrName
= xAttrList
->getNameByIndex( i
);
224 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( rFullAttrName
, &aLocalName
);
227 if( XML_NAMESPACE_DRAW
== nPrefix
)
229 if( aLocalName
== GetXMLToken(XML_NAME
) )
231 rName
= xAttrList
->getValueByIndex( i
);
233 else if( aLocalName
== GetXMLToken(XML_COLOR
) )
236 ::sax::Converter::convertColor(nColor
,
237 xAttrList
->getValueByIndex( i
));
244 void SvxXMLTableImportContext::importMarker( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
251 XMLMarkerStyleImport
aMarkerStyle( GetImport() );
252 aMarkerStyle
.importXML( xAttrList
, rAny
, rName
);
254 catch (const Exception
&)
256 OSL_FAIL("SvxXMLTableImportContext::importMarker(), exception caught!");
260 void SvxXMLTableImportContext::importDash( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
267 XMLDashStyleImport
aDashStyle( GetImport() );
268 aDashStyle
.importXML( xAttrList
, rAny
, rName
);
270 catch (const Exception
&)
272 OSL_FAIL("SvxXMLTableImportContext::importDash(), exception caught!");
276 void SvxXMLTableImportContext::importHatch( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
283 XMLHatchStyleImport
aHatchStyle( GetImport() );
284 aHatchStyle
.importXML( xAttrList
, rAny
, rName
);
286 catch (const Exception
&)
288 OSL_FAIL("SvxXMLTableImportContext::importHatch(), exception caught!");
292 void SvxXMLTableImportContext::importGradient( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
299 XMLGradientStyleImport
aGradientStyle( GetImport() );
300 aGradientStyle
.importXML( xAttrList
, rAny
, rName
);
302 catch (const Exception
&)
304 OSL_FAIL("SvxXMLTableImportContext::importGradient(), exception caught!");
308 void SvxXMLTableImportContext::importBitmap( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
315 XMLImageStyle aImageStyle
;
316 aImageStyle
.importXML( xAttrList
, rAny
, rName
, GetImport() );
318 catch (const Exception
&)
320 OSL_FAIL("SvxXMLTableImportContext::importBitmap(), exception caught!");
327 SvxXMLXTableImport::SvxXMLXTableImport(
328 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
>& rContext
,
329 const uno::Reference
< XNameContainer
> & rTable
,
330 uno::Reference
< XGraphicObjectResolver
>& xGrfResolver
)
331 : SvXMLImport(rContext
, "", SvXMLImportFlags::NONE
),
334 SetGraphicResolver( xGrfResolver
);
336 GetNamespaceMap().Add( OUString( sXML_np__ooo
), GetXMLToken(XML_N_OOO
), XML_NAMESPACE_OOO
);
337 GetNamespaceMap().Add( OUString( sXML_np__office
), GetXMLToken(XML_N_OFFICE
), XML_NAMESPACE_OFFICE
);
338 GetNamespaceMap().Add( OUString( sXML_np__draw
), GetXMLToken(XML_N_DRAW
), XML_NAMESPACE_DRAW
);
339 GetNamespaceMap().Add( OUString( sXML_np__xlink
), GetXMLToken(XML_N_XLINK
), XML_NAMESPACE_XLINK
);
341 // OOo namespaces for reading OOo 1.1 files
342 GetNamespaceMap().Add( OUString( sXML_np__office_ooo
),
343 GetXMLToken(XML_N_OFFICE_OOO
),
344 XML_NAMESPACE_OFFICE
);
345 GetNamespaceMap().Add( OUString( sXML_np__draw_ooo
),
346 GetXMLToken(XML_N_DRAW_OOO
),
347 XML_NAMESPACE_DRAW
);
350 SvxXMLXTableImport::~SvxXMLXTableImport() throw ()
354 static void openStorageStream( xml::sax::InputSource
*pParserInput
,
355 SvXMLGraphicHelper
**ppGraphicHelper
,
356 uno::Reference
< embed::XStorage
> xStorage
)
358 uno::Reference
< io::XStream
> xIStm
;
359 xIStm
.set( xStorage
->openStreamElement( "Content.xml", embed::ElementModes::READ
), uno::UNO_QUERY_THROW
);
362 OSL_FAIL( "could not open Content stream" );
365 pParserInput
->aInputStream
= xIStm
->getInputStream();
366 *ppGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, GRAPHICHELPER_MODE_READ
);
369 bool SvxXMLXTableImport::load( const OUString
&rPath
, const OUString
&rReferer
,
370 const uno::Reference
< embed::XStorage
> &xStorage
,
371 const uno::Reference
< XNameContainer
>& xTable
,
372 bool *bOptLoadedFromStorage
) throw()
375 SvXMLGraphicHelper
* pGraphicHelper
= 0;
377 INetURLObject
aURLObj( rPath
);
378 bool bUseStorage
= aURLObj
.GetProtocol() == INetProtocol::NotValid
; // a relative path
382 uno::Reference
<uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
384 uno::Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create( xContext
);
386 xml::sax::InputSource aParserInput
;
387 comphelper::LifecycleProxy aNasty
;
389 if( !bUseStorage
|| !xStorage
.is() )
391 SfxMedium
aMedium( rPath
, rReferer
, StreamMode::READ
| StreamMode::NOCREATE
);
392 aParserInput
.sSystemId
= aMedium
.GetName();
394 if( aMedium
.IsStorage() )
396 uno::Reference
< embed::XStorage
> xMediumStorage( aMedium
.GetStorage( false ), uno::UNO_QUERY_THROW
);
397 openStorageStream( &aParserInput
, &pGraphicHelper
, xMediumStorage
);
400 aParserInput
.aInputStream
= aMedium
.GetInputStream();
402 else // relative URL into a storage
404 uno::Reference
< embed::XStorage
> xSubStorage
;
407 xSubStorage
= comphelper::OStorageHelper::GetStorageAtPath(
408 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
410 catch (const uno::Exception
&)
413 if( xSubStorage
.is() )
414 openStorageStream( &aParserInput
, &pGraphicHelper
, xSubStorage
);
417 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XStream
> xStream
;
418 xStream
= comphelper::OStorageHelper::GetStreamAtPath(
419 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
422 aParserInput
.aInputStream
= xStream
->getInputStream();
424 if( bOptLoadedFromStorage
)
425 *bOptLoadedFromStorage
= true;
428 uno::Reference
< XGraphicObjectResolver
> xGrfResolver
;
430 xGrfResolver
= pGraphicHelper
;
434 uno::Reference
< io::XSeekable
> xSeek( aParserInput
.aInputStream
, uno::UNO_QUERY_THROW
);
437 catch (const uno::Exception
&)
441 uno::Reference
< XDocumentHandler
> xHandler( new SvxXMLXTableImport( xContext
, xTable
, xGrfResolver
) );
442 xParser
->setDocumentHandler( xHandler
);
443 xParser
->parseStream( aParserInput
);
446 SvXMLGraphicHelper::Destroy( pGraphicHelper
);
448 catch (const uno::Exception
&)
450 // thrown each time you load a document with property tables that are not
451 // on the current machine. FIXME: would be better to check a file exists
452 // before importing ...
453 // fprintf (stderr, "parsing etc. exception '%s'\n",
454 // OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
461 SvXMLImportContext
*SvxXMLXTableImport::CreateContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
)
463 if( XML_NAMESPACE_OOO
== nPrefix
||
464 XML_NAMESPACE_OFFICE
== nPrefix
)
466 bool bOOoFormat
= (XML_NAMESPACE_OFFICE
== nPrefix
);
467 Type aType
= mrTable
->getElementType();
469 if ( rLocalName
== "color-table" )
471 if( aType
== ::cppu::UnoType
<sal_Int32
>::get() )
472 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_color
, mrTable
, bOOoFormat
);
474 else if ( rLocalName
== "marker-table" )
476 if( aType
== cppu::UnoType
<drawing::PolyPolygonBezierCoords
>::get())
477 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_marker
, mrTable
, bOOoFormat
);
479 else if ( rLocalName
== "dash-table" )
481 if( aType
== cppu::UnoType
<drawing::LineDash
>::get())
482 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_dash
, mrTable
, bOOoFormat
);
484 else if ( rLocalName
== "hatch-table" )
486 if( aType
== cppu::UnoType
<drawing::Hatch
>::get())
487 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_hatch
, mrTable
, bOOoFormat
);
489 else if ( rLocalName
== "gradient-table" )
491 if( aType
== cppu::UnoType
<awt::Gradient
>::get())
492 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_gradient
, mrTable
, bOOoFormat
);
494 else if ( rLocalName
== "bitmap-table" )
496 if( aType
== ::cppu::UnoType
<OUString
>::get())
497 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_bitmap
, mrTable
, bOOoFormat
);
501 return new SvXMLImportContext( *this, nPrefix
, rLocalName
);
504 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */