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