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";
77 ///////////////////////////////////////////////////////////////////////
79 enum SvxXMLTableImportContextEnum
{ stice_unknown
, stice_color
, stice_marker
, stice_dash
, stice_hatch
, stice_gradient
, stice_bitmap
};
81 ///////////////////////////////////////////////////////////////////////
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
);
92 SvxXMLXTableImport
& getImport() const { return *(SvxXMLXTableImport
*)&GetImport(); }
95 void importColor( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
96 void importMarker( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
97 void importDash( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
98 void importHatch( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
99 void importGradient( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
100 void importBitmap( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
);
103 uno::Reference
< XNameContainer
> mxTable
;
104 SvxXMLTableImportContextEnum meContext
;
108 ///////////////////////////////////////////////////////////////////////
110 SvxXMLTableImportContext::SvxXMLTableImportContext( SvXMLImport
& rImport
, sal_uInt16 nPrfx
, const OUString
& rLName
, const uno::Reference
< XAttributeList
>&, SvxXMLTableImportContextEnum eContext
, const uno::Reference
< XNameContainer
>& xTable
, bool bOOoFormat
)
111 : SvXMLImportContext( rImport
, nPrfx
, rLName
), mxTable( xTable
), meContext( eContext
),
112 mbOOoFormat( bOOoFormat
)
116 SvxXMLTableImportContext::~SvxXMLTableImportContext()
120 SvXMLImportContext
*SvxXMLTableImportContext::CreateChildContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& rAttrList
)
122 if( XML_NAMESPACE_DRAW
== nPrefix
)
124 uno::Reference
< XAttributeList
> xAttrList( rAttrList
);
126 (stice_dash
== meContext
|| stice_hatch
== meContext
||
127 stice_bitmap
== meContext
) )
129 SvXMLAttributeList
*pAttrList
= new SvXMLAttributeList( rAttrList
);
130 xAttrList
= pAttrList
;
131 sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
132 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
134 const OUString
& rAttrName
= xAttrList
->getNameByIndex( i
);
136 sal_uInt16 nPrefix_
=
137 GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName
,
139 if( XML_NAMESPACE_XLINK
== nPrefix_
&&
140 stice_bitmap
== meContext
&&
141 IsXMLToken( aLocalName
, XML_HREF
) )
143 const OUString rValue
= xAttrList
->getValueByIndex( i
);
144 if( !rValue
.isEmpty() && '#' == rValue
[0] )
145 pAttrList
->SetValueByIndex( i
, rValue
.copy( 1 ) );
147 else if( XML_NAMESPACE_DRAW
== nPrefix_
&&
148 ( ( stice_dash
== meContext
&&
149 (IsXMLToken( aLocalName
, XML_DOTS1_LENGTH
) ||
150 IsXMLToken( aLocalName
, XML_DOTS2_LENGTH
) ||
151 IsXMLToken( aLocalName
, XML_DISTANCE
)) ) ||
152 ( stice_hatch
== meContext
&&
153 IsXMLToken( aLocalName
, XML_HATCH_DISTANCE
) ) ) )
155 const OUString rValue
= xAttrList
->getValueByIndex( i
);
156 sal_Int32 nPos
= rValue
.getLength();
157 while( nPos
&& rValue
[nPos
-1] <= ' ' )
160 ('c'==rValue
[nPos
-2] || 'C'==rValue
[nPos
-2]) &&
161 ('h'==rValue
[nPos
-1] || 'H'==rValue
[nPos
-1]) )
163 pAttrList
->SetValueByIndex( i
, rValue
.copy( 0, nPos
-2 ) );
176 importColor( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
179 importMarker( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
182 importDash( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
185 importHatch( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
188 importGradient( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
191 importBitmap( nPrefix
, rLocalName
, xAttrList
, aAny
, aName
);
197 if( !aName
.isEmpty() && aAny
.hasValue() )
199 if( mxTable
->hasByName( aName
) )
201 mxTable
->replaceByName( aName
, aAny
);
205 mxTable
->insertByName( aName
, aAny
);
209 catch (const uno::Exception
&)
214 return new SvXMLImportContext( GetImport(), nPrefix
, rLocalName
);
217 void SvxXMLTableImportContext::importColor( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
222 const sal_Int16 nAttrCount
= xAttrList
.is() ? xAttrList
->getLength() : 0;
223 for( sal_Int16 i
=0; i
< nAttrCount
; i
++ )
225 const OUString
& rFullAttrName
= xAttrList
->getNameByIndex( i
);
227 sal_uInt16 nPrefix
= GetImport().GetNamespaceMap().GetKeyByAttrName( rFullAttrName
, &aLocalName
);
230 if( XML_NAMESPACE_DRAW
== nPrefix
)
232 if( aLocalName
== GetXMLToken(XML_NAME
) )
234 rName
= xAttrList
->getValueByIndex( i
);
236 else if( aLocalName
== GetXMLToken(XML_COLOR
) )
239 ::sax::Converter::convertColor(nColor
,
240 xAttrList
->getValueByIndex( i
));
247 void SvxXMLTableImportContext::importMarker( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
254 XMLMarkerStyleImport
aMarkerStyle( GetImport() );
255 aMarkerStyle
.importXML( xAttrList
, rAny
, rName
);
257 catch (const Exception
&)
259 OSL_FAIL("SvxXMLTableImportContext::importMarker(), exception caught!");
263 void SvxXMLTableImportContext::importDash( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
270 XMLDashStyleImport
aDashStyle( GetImport() );
271 aDashStyle
.importXML( xAttrList
, rAny
, rName
);
273 catch (const Exception
&)
275 OSL_FAIL("SvxXMLTableImportContext::importDash(), exception caught!");
279 void SvxXMLTableImportContext::importHatch( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
286 XMLHatchStyleImport
aHatchStyle( GetImport() );
287 aHatchStyle
.importXML( xAttrList
, rAny
, rName
);
289 catch (const Exception
&)
291 OSL_FAIL("SvxXMLTableImportContext::importHatch(), exception caught!");
295 void SvxXMLTableImportContext::importGradient( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
302 XMLGradientStyleImport
aGradientStyle( GetImport() );
303 aGradientStyle
.importXML( xAttrList
, rAny
, rName
);
305 catch (const Exception
&)
307 OSL_FAIL("SvxXMLTableImportContext::importGradient(), exception caught!");
311 void SvxXMLTableImportContext::importBitmap( sal_uInt16 nPrfx
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
, Any
& rAny
, OUString
& rName
)
318 XMLImageStyle aImageStyle
;
319 aImageStyle
.importXML( xAttrList
, rAny
, rName
, GetImport() );
321 catch (const Exception
&)
323 OSL_FAIL("SvxXMLTableImportContext::importBitmap(), exception caught!");
327 ///////////////////////////////////////////////////////////////////////
330 SvxXMLXTableImport::SvxXMLXTableImport(
331 const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XComponentContext
> xContext
,
332 const uno::Reference
< XNameContainer
> & rTable
,
333 uno::Reference
< XGraphicObjectResolver
>& xGrfResolver
)
334 : SvXMLImport(xContext
, 0),
337 SetGraphicResolver( xGrfResolver
);
339 GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__ooo
) ), GetXMLToken(XML_N_OOO
), XML_NAMESPACE_OOO
);
340 GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__office
) ), GetXMLToken(XML_N_OFFICE
), XML_NAMESPACE_OFFICE
);
341 GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__draw
) ), GetXMLToken(XML_N_DRAW
), XML_NAMESPACE_DRAW
);
342 GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__xlink
) ), GetXMLToken(XML_N_XLINK
), XML_NAMESPACE_XLINK
);
344 // OOo namespaces for reading OOo 1.1 files
345 GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__office_ooo
) ),
346 GetXMLToken(XML_N_OFFICE_OOO
),
347 XML_NAMESPACE_OFFICE
);
348 GetNamespaceMap().Add( OUString( RTL_CONSTASCII_USTRINGPARAM ( sXML_np__draw_ooo
) ),
349 GetXMLToken(XML_N_DRAW_OOO
),
350 XML_NAMESPACE_DRAW
);
353 SvxXMLXTableImport::~SvxXMLXTableImport() throw ()
357 static void openStorageStream( xml::sax::InputSource
*pParserInput
,
358 SvXMLGraphicHelper
**ppGraphicHelper
,
359 uno::Reference
< embed::XStorage
> xStorage
)
361 uno::Reference
< io::XStream
> xIStm
;
362 const String
aContentStmName( RTL_CONSTASCII_USTRINGPARAM( "Content.xml" ) );
363 xIStm
.set( xStorage
->openStreamElement( aContentStmName
, embed::ElementModes::READ
), uno::UNO_QUERY_THROW
);
366 OSL_FAIL( "could not open Content stream" );
369 pParserInput
->aInputStream
= xIStm
->getInputStream();
370 *ppGraphicHelper
= SvXMLGraphicHelper::Create( xStorage
, GRAPHICHELPER_MODE_READ
);
373 bool SvxXMLXTableImport::load( const OUString
&rPath
,
374 const uno::Reference
< embed::XStorage
> &xStorage
,
375 const uno::Reference
< XNameContainer
>& xTable
,
376 bool *bOptLoadedFromStorage
) throw()
379 SvXMLGraphicHelper
* pGraphicHelper
= 0;
381 INetURLObject
aURLObj( rPath
);
382 bool bUseStorage
= aURLObj
.GetProtocol() == INET_PROT_NOT_VALID
; // a relative path
386 uno::Reference
<uno::XComponentContext
> xContext( ::comphelper::getProcessComponentContext() );
388 uno::Reference
< xml::sax::XParser
> xParser
= xml::sax::Parser::create( xContext
);
390 xml::sax::InputSource aParserInput
;
391 comphelper::LifecycleProxy aNasty
;
393 if( !bUseStorage
|| !xStorage
.is() )
395 SfxMedium
aMedium( rPath
, STREAM_READ
| STREAM_NOCREATE
);
396 aParserInput
.sSystemId
= aMedium
.GetName();
398 if( aMedium
.IsStorage() )
400 uno::Reference
< embed::XStorage
> xMediumStorage( aMedium
.GetStorage( sal_False
), uno::UNO_QUERY_THROW
);
401 openStorageStream( &aParserInput
, &pGraphicHelper
, xMediumStorage
);
404 aParserInput
.aInputStream
= aMedium
.GetInputStream();
406 else // relative URL into a storage
408 uno::Reference
< embed::XStorage
> xSubStorage
;
411 xSubStorage
= comphelper::OStorageHelper::GetStorageAtPath(
412 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
414 catch (const uno::Exception
&)
417 if( xSubStorage
.is() )
418 openStorageStream( &aParserInput
, &pGraphicHelper
, xSubStorage
);
421 ::com::sun::star::uno::Reference
< ::com::sun::star::io::XStream
> xStream
;
422 xStream
= comphelper::OStorageHelper::GetStreamAtPath(
423 xStorage
, rPath
, embed::ElementModes::READ
, aNasty
);
426 aParserInput
.aInputStream
= xStream
->getInputStream();
428 if( bOptLoadedFromStorage
)
429 *bOptLoadedFromStorage
= true;
432 uno::Reference
< XGraphicObjectResolver
> xGrfResolver
;
434 xGrfResolver
= pGraphicHelper
;
438 uno::Reference
< io::XSeekable
> xSeek( aParserInput
.aInputStream
, uno::UNO_QUERY_THROW
);
441 catch (const uno::Exception
&)
445 uno::Reference
< XDocumentHandler
> xHandler( new SvxXMLXTableImport( xContext
, xTable
, xGrfResolver
) );
446 xParser
->setDocumentHandler( xHandler
);
447 xParser
->parseStream( aParserInput
);
450 SvXMLGraphicHelper::Destroy( pGraphicHelper
);
452 catch (const uno::Exception
&)
454 // thrown each time you load a document with property tables that are not
455 // on the current machine. FIXME: would be better to check a file exists
456 // before importing ...
457 // fprintf (stderr, "parsing etc. exception '%s'\n",
458 // OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
465 SvXMLImportContext
*SvxXMLXTableImport::CreateContext( sal_uInt16 nPrefix
, const OUString
& rLocalName
, const uno::Reference
< XAttributeList
>& xAttrList
)
467 if( XML_NAMESPACE_OOO
== nPrefix
||
468 XML_NAMESPACE_OFFICE
== nPrefix
)
470 bool bOOoFormat
= (XML_NAMESPACE_OFFICE
== nPrefix
);
471 Type aType
= mrTable
->getElementType();
473 if ( rLocalName
== "color-table" )
475 if( aType
== ::getCppuType((const sal_Int32
*)0) )
476 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_color
, mrTable
, bOOoFormat
);
478 else if ( rLocalName
== "marker-table" )
480 if( aType
== ::getCppuType((const drawing::PolyPolygonBezierCoords
*)0) )
481 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_marker
, mrTable
, bOOoFormat
);
483 else if ( rLocalName
== "dash-table" )
485 if( aType
== ::getCppuType((const drawing::LineDash
*)0) )
486 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_dash
, mrTable
, bOOoFormat
);
488 else if ( rLocalName
== "hatch-table" )
490 if( aType
== ::getCppuType((const drawing::Hatch
*)0) )
491 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_hatch
, mrTable
, bOOoFormat
);
493 else if ( rLocalName
== "gradient-table" )
495 if( aType
== ::getCppuType((const awt::Gradient
*)0))
496 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_gradient
, mrTable
, bOOoFormat
);
498 else if ( rLocalName
== "bitmap-table" )
500 if( aType
== ::getCppuType((const OUString
*)0))
501 return new SvxXMLTableImportContext( *this, nPrefix
, rLocalName
, xAttrList
, stice_bitmap
, mrTable
, bOOoFormat
);
505 return new SvXMLImportContext( *this, nPrefix
, rLocalName
);
508 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */