LibreOffice Module xmloff (master) 1
eventimp.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <com/sun/star/document/XEventsSupplier.hpp>
21#include <com/sun/star/container/XNameReplace.hpp>
22#include <com/sun/star/presentation/AnimationSpeed.hpp>
23#include <com/sun/star/beans/XPropertySet.hpp>
24#include <tools/urlobj.hxx>
25#include <osl/diagnose.h>
26#include <sal/log.hxx>
27#include <o3tl/string_view.hxx>
28
30
31#include <xmloff/xmltoken.hxx>
32#include <xmloff/xmlimp.hxx>
34#include <xmloff/xmluconv.hxx>
36#include "eventimp.hxx"
37
38using namespace ::std;
39using namespace ::cppu;
40using namespace ::com::sun::star;
41using namespace ::com::sun::star::xml;
42using namespace ::com::sun::star::xml::sax;
43using namespace ::com::sun::star::uno;
44using namespace ::com::sun::star::drawing;
45using namespace ::com::sun::star::beans;
46using namespace ::com::sun::star::lang;
47using namespace ::com::sun::star::document;
48using namespace ::com::sun::star::container;
49using namespace ::com::sun::star::presentation;
50using namespace ::xmloff::token;
51
53{
54 { XML_NONE, ClickAction_NONE },
55 { XML_PREVIOUS_PAGE, ClickAction_PREVPAGE },
56 { XML_NEXT_PAGE, ClickAction_NEXTPAGE },
57 { XML_FIRST_PAGE, ClickAction_FIRSTPAGE },
58 { XML_LAST_PAGE, ClickAction_LASTPAGE },
59 { XML_HIDE, ClickAction_INVISIBLE },
60 { XML_STOP, ClickAction_STOPPRESENTATION },
61 { XML_EXECUTE, ClickAction_PROGRAM },
62 { XML_SHOW, ClickAction_BOOKMARK },
63 { XML_SHOW, ClickAction_DOCUMENT },
64 { XML_EXECUTE_MACRO, ClickAction_MACRO },
65 { XML_VERB, ClickAction_VERB },
66 { XML_FADE_OUT, ClickAction_VANISH },
67 { XML_SOUND, ClickAction_SOUND },
68 { XML_TOKEN_INVALID, ClickAction(0) }
69};
70
71SdXMLEventContextData::SdXMLEventContextData(const Reference< XShape >& rxShape)
72 : mxShape(rxShape), mbValid(false), mbScript(false)
73 , meClickAction(ClickAction_NONE), meEffect(EK_none)
74 , meDirection(ED_none), mnStartScale(100), meSpeed(AnimationSpeed_MEDIUM)
75 , mnVerb(0), mbPlayFull(false)
76{
77}
78
79namespace {
80
81class SdXMLEventContext : public SvXMLImportContext
82{
83public:
85
86public:
87
88 SdXMLEventContext( SvXMLImport& rImport, sal_Int32 nElement, const Reference< XFastAttributeList>& xAttrList, const Reference< XShape >& rxShape );
89
90 virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
91 sal_Int32 nElement,
92 const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override;
93 virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
94};
95
96class XMLEventSoundContext : public SvXMLImportContext
97{
98public:
99
100 XMLEventSoundContext( SvXMLImport& rImport, const Reference< XFastAttributeList >& xAttrList, SdXMLEventContext* pParent );
101};
102
103}
104
105XMLEventSoundContext::XMLEventSoundContext( SvXMLImport& rImp, const Reference< XFastAttributeList >& xAttrList, SdXMLEventContext* pParent )
106: SvXMLImportContext( rImp )
107{
108 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
109 {
110 switch( aIter.getToken() )
111 {
112 case XML_ELEMENT(XLINK, XML_HREF):
113 pParent->maData.msSoundURL = rImp.GetAbsoluteReference(aIter.toString());
114 break;
115 case XML_ELEMENT(PRESENTATION, XML_PLAY_FULL):
116 pParent->maData.mbPlayFull = IsXMLToken( aIter, XML_TRUE );
117 break;
118 default:
119 XMLOFF_WARN_UNKNOWN("xmloff", aIter);
120 }
121 }
122}
123
124SdXMLEventContext::SdXMLEventContext( SvXMLImport& rImp,
125 sal_Int32 nElement,
126 const Reference< XFastAttributeList >& xAttrList, const Reference< XShape >& rxShape )
127 : SvXMLImportContext(rImp)
128 , maData(rxShape)
129{
130 if( nElement == XML_ELEMENT(PRESENTATION, XML_EVENT_LISTENER) )
131 {
132 maData.mbValid = true;
133 }
134 else if( nElement == XML_ELEMENT(SCRIPT, XML_EVENT_LISTENER) )
135 {
136 maData.mbScript = true;
137 maData.mbValid = true;
138 }
139 else
140 {
141 return;
142 }
143
144 // read attributes
145 OUString sEventName;
146 for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) )
147 {
148 switch( aIter.getToken() )
149 {
150 case XML_ELEMENT(PRESENTATION, XML_ACTION):
151 SvXMLUnitConverter::convertEnum( maData.meClickAction, aIter.toView(), aXML_EventActions_EnumMap );
152 break;
153 case XML_ELEMENT(PRESENTATION, XML_EFFECT):
154 SvXMLUnitConverter::convertEnum( maData.meEffect, aIter.toView(), aXML_AnimationEffect_EnumMap );
155 break;
156 case XML_ELEMENT(PRESENTATION, XML_DIRECTION):
158 break;
159 case XML_ELEMENT(PRESENTATION, XML_START_SCALE):
160 {
161 sal_Int32 nScale;
162 if (::sax::Converter::convertPercent( nScale, aIter.toView() ))
163 maData.mnStartScale = static_cast<sal_Int16>(nScale);
164 }
165 break;
166 case XML_ELEMENT(PRESENTATION, XML_SPEED):
167 SvXMLUnitConverter::convertEnum( maData.meSpeed, aIter.toView(), aXML_AnimationSpeed_EnumMap );
168 break;
169 case XML_ELEMENT(PRESENTATION, XML_VERB):
170 ::sax::Converter::convertNumber( maData.mnVerb, aIter.toView() );
171 break;
172 case XML_ELEMENT(SCRIPT, XML_EVENT_NAME):
173 {
174 sEventName = aIter.toString();
175 sal_uInt16 nScriptPrefix =
176 GetImport().GetNamespaceMap().GetKeyByAttrValueQName(sEventName, &sEventName);
177 maData.mbValid = XML_NAMESPACE_DOM == nScriptPrefix && sEventName == "click";
178 }
179 break;
180 case XML_ELEMENT(SCRIPT, XML_LANGUAGE):
181 {
182 // language is not evaluated!
183 OUString aScriptLanguage;
184 maData.msLanguage = aIter.toString();
185 sal_uInt16 nScriptPrefix = rImp.GetNamespaceMap().
186 GetKeyByAttrValueQName(maData.msLanguage, &aScriptLanguage);
187 if( XML_NAMESPACE_OOO == nScriptPrefix )
188 maData.msLanguage = aScriptLanguage;
189 }
190 break;
191 case XML_ELEMENT(SCRIPT, XML_MACRO_NAME):
192 maData.msMacroName = aIter.toString();
193 break;
194 case XML_ELEMENT(XLINK, XML_HREF):
195 {
196 if ( maData.mbScript )
197 {
198 maData.msMacroName = aIter.toString();
199 }
200 else
201 {
202 const OUString &rTmp =
203 rImp.GetAbsoluteReference(aIter.toString());
206 }
207 }
208 break;
209 }
210 }
211
212 if( maData.mbValid )
213 maData.mbValid = !sEventName.isEmpty();
214}
215
216css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLEventContext::createFastChildContext(
217 sal_Int32 nElement,
218 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
219{
220 if( nElement == XML_ELEMENT(PRESENTATION, XML_SOUND) )
221 return new XMLEventSoundContext( GetImport(), xAttrList, this );
222 else
223 XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement);
224 return nullptr;
225}
226
227void SdXMLEventContext::endFastElement(sal_Int32 )
228{
229 GetImport().GetShapeImport()->addShapeEvents(maData);
230}
231
233{
234 if( !mbValid )
235 return;
236
237 do
238 {
239 Reference< XEventsSupplier > xEventsSupplier( mxShape, UNO_QUERY );
240 if( !xEventsSupplier.is() )
241 break;
242
243 Reference< XNameReplace > xEvents( xEventsSupplier->getEvents() );
244 SAL_WARN_IF( !xEvents.is(), "xmloff", "XEventsSupplier::getEvents() returned NULL" );
245 if( !xEvents.is() )
246 break;
247
248 OUString sAPIEventName;
249 uno::Sequence< beans::PropertyValue > aProperties;
250
251 sAPIEventName = "OnClick";
252
253 if( mbScript )
254 meClickAction = ClickAction_MACRO;
255
256 sal_Int32 nPropertyCount = 2;
257 switch( meClickAction )
258 {
259 case ClickAction_NONE:
260 case ClickAction_PREVPAGE:
261 case ClickAction_NEXTPAGE:
262 case ClickAction_FIRSTPAGE:
263 case ClickAction_LASTPAGE:
264 case ClickAction_INVISIBLE:
265 case ClickAction_STOPPRESENTATION:
266 break;
267 case ClickAction_PROGRAM:
268 case ClickAction_VERB:
269 case ClickAction_BOOKMARK:
270 case ClickAction_DOCUMENT:
271 nPropertyCount += 1;
272 break;
273 case ClickAction_MACRO:
274 if ( msLanguage.equalsIgnoreAsciiCase("starbasic") )
275 nPropertyCount += 1;
276 break;
277
278 case ClickAction_SOUND:
279 nPropertyCount += 2;
280 break;
281
282 case ClickAction_VANISH:
283 nPropertyCount += 4;
284 break;
285 default:
286 break;
287 }
288
289 aProperties.realloc( nPropertyCount );
290 beans::PropertyValue* pProperties = aProperties.getArray();
291
292 if( ClickAction_MACRO == meClickAction )
293 {
294 if ( msLanguage.equalsIgnoreAsciiCase("starbasic") )
295 {
296 OUString sLibrary;
297 const OUString& rApp = GetXMLToken( XML_APPLICATION );
298 const OUString& rDoc = GetXMLToken( XML_DOCUMENT );
299 if( msMacroName.getLength() > rApp.getLength()+1 &&
300 o3tl::equalsIgnoreAsciiCase(msMacroName.subView(0,rApp.getLength()), rApp) &&
301 ':' == msMacroName[rApp.getLength()] )
302 {
303 sLibrary = "StarOffice";
304 msMacroName = msMacroName.copy( rApp.getLength()+1 );
305 }
306 else if( msMacroName.getLength() > rDoc.getLength()+1 &&
307 o3tl::equalsIgnoreAsciiCase(msMacroName.subView(0,rDoc.getLength()), rDoc) &&
308 ':' == msMacroName[rDoc.getLength()] )
309 {
310 sLibrary = rDoc;
311 msMacroName = msMacroName.copy( rDoc.getLength()+1 );
312 }
313
314 pProperties->Name = "EventType";
315 pProperties->Handle = -1;
316 pProperties->Value <<= OUString( "StarBasic" );
317 pProperties->State = beans::PropertyState_DIRECT_VALUE;
318 pProperties++;
319
320 pProperties->Name = "MacroName";
321 pProperties->Handle = -1;
322 pProperties->Value <<= msMacroName;
323 pProperties->State = beans::PropertyState_DIRECT_VALUE;
324 pProperties++;
325
326 pProperties->Name = "Library";
327 pProperties->Handle = -1;
328 pProperties->Value <<= sLibrary;
329 pProperties->State = beans::PropertyState_DIRECT_VALUE;
330 }
331 else
332 {
333 pProperties->Name = "EventType";
334 pProperties->Handle = -1;
335 pProperties->Value <<= OUString( "Script" );
336 pProperties->State = beans::PropertyState_DIRECT_VALUE;
337 pProperties++;
338
339 pProperties->Name = "Script";
340 pProperties->Handle = -1;
341 pProperties->Value <<= msMacroName;
342 pProperties->State = beans::PropertyState_DIRECT_VALUE;
343 }
344 }
345 else
346 {
347 pProperties->Name = "EventType";
348 pProperties->Handle = -1;
349 pProperties->Value <<= OUString( "Presentation" );
350 pProperties->State = beans::PropertyState_DIRECT_VALUE;
351 pProperties++;
352
353 // ClickAction_BOOKMARK and ClickAction_DOCUMENT share the same xml event
354 // so check here if it's really a bookmark or maybe a document
355 if( meClickAction == ClickAction_BOOKMARK )
356 {
357 if( !msBookmark.startsWith( "#" ) )
358 meClickAction = ClickAction_DOCUMENT;
359 }
360
361 pProperties->Name = "ClickAction";
362 pProperties->Handle = -1;
363 pProperties->Value <<= meClickAction;
364 pProperties->State = beans::PropertyState_DIRECT_VALUE;
365 pProperties++;
366
367 switch( meClickAction )
368 {
369 case ClickAction_NONE:
370 case ClickAction_PREVPAGE:
371 case ClickAction_NEXTPAGE:
372 case ClickAction_FIRSTPAGE:
373 case ClickAction_LASTPAGE:
374 case ClickAction_INVISIBLE:
375 case ClickAction_STOPPRESENTATION:
376 break;
377
378 case ClickAction_BOOKMARK:
379 msBookmark = msBookmark.copy(1);
380
381 [[fallthrough]];
382
383 case ClickAction_DOCUMENT:
384 case ClickAction_PROGRAM:
385 pProperties->Name = "Bookmark";
386 pProperties->Handle = -1;
387 pProperties->Value <<= msBookmark;
388 pProperties->State = beans::PropertyState_DIRECT_VALUE;
389 break;
390
391 case ClickAction_VANISH:
392 pProperties->Name = "Effect";
393 pProperties->Handle = -1;
394 pProperties->Value <<= ImplSdXMLgetEffect( meEffect, meDirection, mnStartScale, true );
395 pProperties->State = beans::PropertyState_DIRECT_VALUE;
396 pProperties++;
397
398 pProperties->Name = "Speed";
399 pProperties->Handle = -1;
400 pProperties->Value <<= meSpeed;
401 pProperties->State = beans::PropertyState_DIRECT_VALUE;
402 pProperties++;
403
404 [[fallthrough]];
405
406 case ClickAction_SOUND:
407 pProperties->Name = "SoundURL";
408 pProperties->Handle = -1;
409 pProperties->Value <<= msSoundURL;
410 pProperties->State = beans::PropertyState_DIRECT_VALUE;
411 pProperties++;
412
413 pProperties->Name = "PlayFull";
414 pProperties->Handle = -1;
415 pProperties->Value <<= mbPlayFull;
416 pProperties->State = beans::PropertyState_DIRECT_VALUE;
417 break;
418
419 case ClickAction_VERB:
420 pProperties->Name = "Verb";
421 pProperties->Handle = -1;
422 pProperties->Value <<= mnVerb;
423 pProperties->State = beans::PropertyState_DIRECT_VALUE;
424 break;
425 case ClickAction_MACRO:
426 OSL_FAIL("xmloff::SdXMLEventContext::EndElement(), ClickAction_MACRO must be handled in different if case");
427 break;
428 default:
429 break;
430 }
431 }
432 xEvents->replaceByName( sAPIEventName, uno::Any( aProperties ) );
433
434 } while(false);
435}
436
437
438SdXMLEventsContext::SdXMLEventsContext( SvXMLImport& rImport, const Reference< XShape >& rxShape)
439: SvXMLImportContext(rImport), mxShape( rxShape )
440{
441}
442
444{
445}
446
447css::uno::Reference< css::xml::sax::XFastContextHandler > SdXMLEventsContext::createFastChildContext(
448 sal_Int32 nElement,
449 const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList )
450{
451 return new SdXMLEventContext( GetImport(), nElement, xAttrList, mxShape );
452}
453
454/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
@ ED_none
Definition: anim.hxx:51
@ EK_none
Definition: anim.hxx:28
AnimationEffect ImplSdXMLgetEffect(XMLEffect eKind, XMLEffectDirection eDirection, sal_Int16 nStartScale, bool)
Definition: animimp.cxx:119
const SvXMLEnumMapEntry< XMLEffectDirection > aXML_AnimationDirection_EnumMap[]
Definition: animimp.cxx:78
const SvXMLEnumMapEntry< AnimationSpeed > aXML_AnimationSpeed_EnumMap[]
Definition: animimp.cxx:111
const SvXMLEnumMapEntry< XMLEffect > aXML_AnimationEffect_EnumMap[]
Definition: animimp.cxx:56
static bool translateToInternal(std::u16string_view rTheExtURIRef, OUString &rTheIntURIRef, DecodeMechanism eDecodeMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
SdXMLEventsContext(SvXMLImport &rImport, const css::uno::Reference< css::drawing::XShape > &rxShape)
Definition: eventimp.cxx:438
virtual ~SdXMLEventsContext() override
Definition: eventimp.cxx:443
css::uno::Reference< css::drawing::XShape > mxShape
Definition: eventimp.hxx:33
virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList > &AttrList) override
Definition: eventimp.cxx:447
This class deliberately does not support XWeak, to improve performance when loading large documents.
Definition: xmlictxt.hxx:48
virtual void SAL_CALL endFastElement(sal_Int32 Element) override
endFastElement is called before a context will be destructed, but after an elements context has been ...
Definition: xmlictxt.cxx:40
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:60
virtual css::uno::Reference< XFastContextHandler > SAL_CALL createFastChildContext(sal_Int32 Element, const css::uno::Reference< css::xml::sax::XFastAttributeList > &Attribs) override
Definition: xmlictxt.cxx:59
OUString GetAbsoluteReference(const OUString &rValue) const
Definition: xmlimp.cxx:1620
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:399
the SvXMLTypeConverter converts values of various types from their internal representation to the tex...
Definition: xmluconv.hxx:83
static bool convertPercent(sal_Int32 &rValue, std::u16string_view rString)
SvXMLEnumMapEntry< ClickAction > const aXML_EventActions_EnumMap[]
Definition: eventimp.cxx:52
#define SAL_WARN_IF(condition, area, stream)
std::vector< sal_Int8, boost::noinit_adaptor< std::allocator< sal_Int8 > > > maData
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
OUString toString(OptionInfo const *info)
Handling of tokens in XML:
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3581
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3525
bool mbValid
uno::Reference< drawing::XShape > const mxShape
css::presentation::AnimationSpeed meSpeed
Definition: eventimp.hxx:59
SdXMLEventContextData(const css::uno::Reference< css::drawing::XShape > &rxShape)
Definition: eventimp.cxx:71
XMLEffectDirection meDirection
Definition: eventimp.hxx:57
css::presentation::ClickAction meClickAction
Definition: eventimp.hxx:55
sal_Int16 mnStartScale
Definition: eventimp.hxx:58
css::uno::Reference< css::drawing::XShape > mxShape
Definition: eventimp.hxx:51
constexpr OUStringLiteral sLibrary
static void convertNumber(OUStringBuffer &b, sal_Int32 n)
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:120
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:114
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:98
constexpr sal_uInt16 XML_NAMESPACE_DOM
constexpr sal_uInt16 XML_NAMESPACE_OOO