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 ::rtl
;
67 using namespace ::xmloff::token
;
70 sal_Char
const sXML_np__office
[] = "__office";
71 sal_Char
const sXML_np__office_ooo
[] = "___office";
72 sal_Char
const sXML_np__draw
[] = "__draw";
73 sal_Char
const sXML_np__draw_ooo
[] = "___draw";
74 sal_Char
const sXML_np__ooo
[] = "__ooo";
75 sal_Char
const sXML_np__xlink
[] = "__xlink";
79 enum SvxXMLTableImportContextEnum
{ stice_unknown
, stice_color
, stice_marker
, stice_dash
, stice_hatch
, stice_gradient
, stice_bitmap
};
83 class SvxXMLTableImportContext
: public SvXMLImportContext
86 SvxXMLTableImportContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
, const uno::Reference
< XAttributeList
>& xAttrList
, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
,
88 virtual ~SvxXMLTableImportContext();
90 virtual SvXMLImportContext
*CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
) SAL_OVERRIDE
;
93 void importColor( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
94 void importMarker( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
95 void importDash( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
96 void importHatch( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
97 void importGradient( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
98 void importBitmap( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
101 uno::Reference
< XNameContainer
> mxTable
;
102 SvxXMLTableImportContextEnum meContext
;
108 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
, const uno::Reference
< XAttributeList
>&, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
, bool bOOoFormat
)
109 : SvXMLImportContext( rImport
, nPrfx
, rLName
), mxTable( xTable
), meContext( eContext
),
110 mbOOoFormat( bOOoFormat
)
114 SvxXMLTableImportContext::~SvxXMLTableImportContext()
118 SvXMLImportContext
*SvxXMLTableImportContext::CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& rAttrList
)
120 if( XML_NAMESPACE_DRAW
== nPrefix
)
122 uno::Reference
< XAttributeList
> xAttrList( rAttrList
);
124 (stice_dash
== meContext
|| stice_hatch
== meContext
||
125 stice_bitmap
== meContext
) )
127 SvXMLAttributeList
*pAttrList
= new SvXMLAttributeList( rAttrList
);
128 xAttrList
= pAttrList
;
129 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
130 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
132 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
134 sal_uInt16 nPrefix_
=
135 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
137 if( XML_NAMESPACE_XLINK
== nPrefix_
&&
138 stice_bitmap
== meContext
&&
139 IsXMLToken( aLocalName
, XML_HREF
) )
141 const OUString rValue
= xAttrList
->getValueByIndex( i
);
142 if( !rValue
.isEmpty() && '#' == rValue
[0] )
143 pAttrList
->SetValueByIndex( i
, rValue
.copy( 1 ) );
145 else if( XML_NAMESPACE_DRAW
== nPrefix_
&&
146 ( ( stice_dash
== meContext
&&
147 (IsXMLToken( aLocalName
, XML_DOTS1_LENGTH
) ||
148 IsXMLToken( aLocalName
, XML_DOTS2_LENGTH
) ||
149 IsXMLToken( aLocalName
, XML_DISTANCE
)) ) ||
150 ( stice_hatch
== meContext
&&
151 IsXMLToken( aLocalName
, XML_HATCH_DISTANCE
) ) ) )
153 const OUString rValue
= xAttrList
->getValueByIndex( i
);
154 sal_Int32 nPos
= rValue
.getLength();
155 while( nPos
&& rValue
[nPos
-1] <= ' ' )
158 ('c'==rValue
[nPos
-2] || 'C'==rValue
[nPos
-2]) &&
159 ('h'==rValue
[nPos
-1] || 'H'==rValue
[nPos
-1]) )
161 pAttrList
->SetValueByIndex( i
, rValue
.copy( 0, nPos
-2 ) );
174 importColor( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
177 importMarker( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
180 importDash( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
183 importHatch( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
186 importGradient( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
189 importBitmap( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
195 if( !aName
.isEmpty() && aAny
.hasValue() )
197 if( mxTable
->hasByName( aName
) )
199 mxTable
->replaceByName( aName
, aAny
);
203 mxTable
->insertByName( aName
, aAny
);
207 catch (const uno::Exception
&)
212 return new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
215 void SvxXMLTableImportContext::importColor( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
220 const sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
221 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
223 const OUString
& rFullAttrName
= xAttrList
->getNameByIndex( i
);
225 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( rFullAttrName
, &aLocalName
);
228 if( XML_NAMESPACE_DRAW
== nPrefix
)
230 if( aLocalName
== GetXMLToken(XML_NAME
) )
232 rName
= xAttrList
->getValueByIndex( i
);
234 else if( aLocalName
== GetXMLToken(XML_COLOR
) )
237 ::sax::Converter::convertColor(nColor
,
238 xAttrList
->getValueByIndex( i
));
245 void SvxXMLTableImportContext::importMarker( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
252 XMLMarkerStyleImport
aMarkerStyle( GetImport() );
253 aMarkerStyle
.importXML( xAttrList
, rAny
, rName
);
255 catch (const Exception
&)
257 OSL_FAIL("SvxXMLTableImportContext::importMarker(), exception caught!");
261 void SvxXMLTableImportContext::importDash( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
268 XMLDashStyleImport
aDashStyle( GetImport() );
269 aDashStyle
.importXML( xAttrList
, rAny
, rName
);
271 catch (const Exception
&)
273 OSL_FAIL("SvxXMLTableImportContext::importDash(), exception caught!");
277 void SvxXMLTableImportContext::importHatch( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
284 XMLHatchStyleImport
aHatchStyle( GetImport() );
285 aHatchStyle
.importXML( xAttrList
, rAny
, rName
);
287 catch (const Exception
&)
289 OSL_FAIL("SvxXMLTableImportContext::importHatch(), exception caught!");
293 void SvxXMLTableImportContext::importGradient( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
300 XMLGradientStyleImport
aGradientStyle( GetImport() );
301 aGradientStyle
.importXML( xAttrList
, rAny
, rName
);
303 catch (const Exception
&)
305 OSL_FAIL("SvxXMLTableImportContext::importGradient(), exception caught!");
309 void SvxXMLTableImportContext::importBitmap( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
316 XMLImageStyle aImageStyle
;
317 aImageStyle
.importXML( xAttrList
, rAny
, rName
, GetImport() );
319 catch (const Exception
&)
321 OSL_FAIL("SvxXMLTableImportContext::importBitmap(), exception caught!");
328 SvxXMLXTableImport::SvxXMLXTableImport(
329 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
> xContext
,
330 const uno::Reference
< XNameContainer
> & rTable
,
331 uno::Reference
< XGraphicObjectResolver
>& xGrfResolver
)
332 : SvXMLImport(xContext
, "", 0),
335 SetGraphicResolver( xGrfResolver
);
337 GetNamespaceMap().Add( OUString( sXML_np__ooo
), GetXMLToken(XML_N_OOO
), XML_NAMESPACE_OOO
);
338 GetNamespaceMap().Add( OUString( sXML_np__office
), GetXMLToken(XML_N_OFFICE
), XML_NAMESPACE_OFFICE
);
339 GetNamespaceMap().Add( OUString( sXML_np__draw
), GetXMLToken(XML_N_DRAW
), XML_NAMESPACE_DRAW
);
340 GetNamespaceMap().Add( OUString( sXML_np__xlink
), GetXMLToken(XML_N_XLINK
), XML_NAMESPACE_XLINK
);
342 // OOo namespaces for reading OOo 1.1 files
343 GetNamespaceMap().Add( OUString( sXML_np__office_ooo
),
344 GetXMLToken(XML_N_OFFICE_OOO
),
345 XML_NAMESPACE_OFFICE
);
346 GetNamespaceMap().Add( OUString( sXML_np__draw_ooo
),
347 GetXMLToken(XML_N_DRAW_OOO
),
348 XML_NAMESPACE_DRAW
);
351 SvxXMLXTableImport::~SvxXMLXTableImport() throw ()
355 static void openStorageStream( xml::sax::InputSource
*pParserInput
,
356 SvXMLGraphicHelper
**ppGraphicHelper
,
357 uno::Reference
< embed::XStorage
> xStorage
)
359 uno::Reference
< io::XStream
> xIStm
;
360 xIStm
.set( xStorage
->openStreamElement( "Content.xml", embed::ElementModes::READ
), uno::UNO_QUERY_THROW
);
363 OSL_FAIL( "could not open Content stream" );
366 pParserInput
->aInputStream
= xIStm
->getInputStream();
367 *ppGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, GRAPHICHELPER_MODE_READ
);
370 bool SvxXMLXTableImport::load( const OUString
&rPath
, const OUString
&rReferer
,
371 const uno::Reference
< embed::XStorage
> &xStorage
,
372 const uno::Reference
< XNameContainer
>& xTable
,
373 bool *bOptLoadedFromStorage
) throw()
376 SvXMLGraphicHelper
* pGraphicHelper
= 0;
378 INetURLObject
aURLObj( rPath
);
379 bool bUseStorage
= aURLObj
.GetProtocol() == INET_PROT_NOT_VALID
; // a relative path
383 uno::Reference
<uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
385 uno::Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create( xContext
);
387 xml::sax::InputSource aParserInput
;
388 comphelper::LifecycleProxy aNasty
;
390 if( !bUseStorage
|| !xStorage
.is() )
392 SfxMedium
aMedium( rPath
, rReferer
, STREAM_READ
| STREAM_NOCREATE
);
393 aParserInput
.sSystemId
= aMedium
.GetName();
395 if( aMedium
.IsStorage() )
397 uno::Reference
< embed::XStorage
> xMediumStorage( aMedium
.GetStorage( false ), uno::UNO_QUERY_THROW
);
398 openStorageStream( &aParserInput
, &pGraphicHelper
, xMediumStorage
);
401 aParserInput
.aInputStream
= aMedium
.GetInputStream();
403 else // relative URL into a storage
405 uno::Reference
< embed::XStorage
> xSubStorage
;
408 xSubStorage
= comphelper::OStorageHelper::GetStorageAtPath(
409 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
411 catch (const uno::Exception
&)
414 if( xSubStorage
.is() )
415 openStorageStream( &aParserInput
, &pGraphicHelper
, xSubStorage
);
418 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XStream
> xStream
;
419 xStream
= comphelper::OStorageHelper::GetStreamAtPath(
420 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
423 aParserInput
.aInputStream
= xStream
->getInputStream();
425 if( bOptLoadedFromStorage
)
426 *bOptLoadedFromStorage
= true;
429 uno::Reference
< XGraphicObjectResolver
> xGrfResolver
;
431 xGrfResolver
= pGraphicHelper
;
435 uno::Reference
< io::XSeekable
> xSeek( aParserInput
.aInputStream
, uno::UNO_QUERY_THROW
);
438 catch (const uno::Exception
&)
442 uno::Reference
< XDocumentHandler
> xHandler( new SvxXMLXTableImport( xContext
, xTable
, xGrfResolver
) );
443 xParser
->setDocumentHandler( xHandler
);
444 xParser
->parseStream( aParserInput
);
447 SvXMLGraphicHelper::Destroy( pGraphicHelper
);
449 catch (const uno::Exception
&)
451 // thrown each time you load a document with property tables that are not
452 // on the current machine. FIXME: would be better to check a file exists
453 // before importing ...
454 // fprintf (stderr, "parsing etc. exception '%s'\n",
455 // OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
462 SvXMLImportContext
*SvxXMLXTableImport::CreateContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
)
464 if( XML_NAMESPACE_OOO
== nPrefix
||
465 XML_NAMESPACE_OFFICE
== nPrefix
)
467 bool bOOoFormat
= (XML_NAMESPACE_OFFICE
== nPrefix
);
468 Type aType
= mrTable
->getElementType();
470 if ( rLocalName
== "color-table" )
472 if( aType
== ::cppu::UnoType
<sal_Int32
>::get() )
473 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_color
, mrTable
, bOOoFormat
);
475 else if ( rLocalName
== "marker-table" )
477 if( aType
== cppu::UnoType
<drawing::PolyPolygonBezierCoords
>::get())
478 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_marker
, mrTable
, bOOoFormat
);
480 else if ( rLocalName
== "dash-table" )
482 if( aType
== cppu::UnoType
<drawing::LineDash
>::get())
483 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_dash
, mrTable
, bOOoFormat
);
485 else if ( rLocalName
== "hatch-table" )
487 if( aType
== cppu::UnoType
<drawing::Hatch
>::get())
488 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_hatch
, mrTable
, bOOoFormat
);
490 else if ( rLocalName
== "gradient-table" )
492 if( aType
== cppu::UnoType
<awt::Gradient
>::get())
493 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_gradient
, mrTable
, bOOoFormat
);
495 else if ( rLocalName
== "bitmap-table" )
497 if( aType
== ::cppu::UnoType
<OUString
>::get())
498 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_bitmap
, mrTable
, bOOoFormat
);
502 return new SvXMLImportContext( *this, nPrefix
, rLocalName
);
505 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */