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 
28 #include <sax/tools/converter.hxx>
29 
30 #include <xmloff/xmltoken.hxx>
31 #include <xmloff/xmlimp.hxx>
32 #include <xmloff/xmlnamespace.hxx>
33 #include <xmloff/xmluconv.hxx>
34 #include <xmloff/namespacemap.hxx>
35 #include "eventimp.hxx"
36 
37 using namespace ::std;
38 using namespace ::cppu;
39 using namespace ::com::sun::star;
40 using namespace ::com::sun::star::xml;
41 using namespace ::com::sun::star::xml::sax;
42 using namespace ::com::sun::star::uno;
43 using namespace ::com::sun::star::drawing;
44 using namespace ::com::sun::star::beans;
45 using namespace ::com::sun::star::lang;
46 using namespace ::com::sun::star::document;
47 using namespace ::com::sun::star::container;
48 using namespace ::com::sun::star::presentation;
49 using 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 
70 SdXMLEventContextData::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 
78 namespace {
79 
80 class SdXMLEventContext : public SvXMLImportContext
81 {
82 public:
84 
85 public:
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 
95 class XMLEventSoundContext : public SvXMLImportContext
96 {
97 public:
98 
99  XMLEventSoundContext( SvXMLImport& rImport, const Reference< XFastAttributeList >& xAttrList, SdXMLEventContext* pParent );
100 };
101 
102 }
103 
104 XMLEventSoundContext::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 
123 SdXMLEventContext::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):
156  SvXMLUnitConverter::convertEnum( maData.meDirection, aIter.toView(), aXML_AnimationDirection_EnumMap );
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());
203  INetURLObject::translateToInternal( rTmp, maData.msBookmark,
205  }
206  }
207  break;
208  }
209  }
210 
211  if( maData.mbValid )
212  maData.mbValid = !sEventName.isEmpty();
213 }
214 
215 css::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 
226 void 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  msMacroName.copy(0,rApp.getLength()).equalsIgnoreAsciiCase( 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  msMacroName.copy(0,rDoc.getLength()).equalsIgnoreAsciiCase( 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 
437 SdXMLEventsContext::SdXMLEventsContext( SvXMLImport& rImport, const Reference< XShape >& rxShape)
438 : SvXMLImportContext(rImport), mxShape( rxShape )
439 {
440 }
441 
443 {
444 }
445 
446 css::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: */
css::uno::Reference< css::drawing::XShape > mxShape
Definition: eventimp.hxx:34
css::uno::Reference< css::drawing::XShape > mxShape
Definition: eventimp.hxx:52
the SvXMLTypeConverter converts values of various types from their internal representation to the tex...
Definition: xmluconv.hxx:80
SdXMLEventContextData(const css::uno::Reference< css::drawing::XShape > &rxShape)
Definition: eventimp.cxx:70
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:56
constexpr sal_uInt16 XML_NAMESPACE_OOO
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:393
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3462
FastAttributeList & castToFastAttributeList(const css::uno::Reference< css::xml::sax::XFastAttributeList > &xAttrList)
const SvXMLEnumMapEntry< XMLEffectDirection > aXML_AnimationDirection_EnumMap[]
Definition: animimp.cxx:78
const SvXMLEnumMapEntry< XMLEffect > aXML_AnimationEffect_EnumMap[]
Definition: animimp.cxx:56
constexpr sal_uInt16 XML_NAMESPACE_DOM
std::vector< sal_Int8 > maData
uno::Reference< drawing::XShape > const mxShape
PropertiesInfo aProperties
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:110
static void convertNumber(OUStringBuffer &b, sal_Int32 n)
const char sLibrary[]
css::presentation::AnimationSpeed meSpeed
Definition: eventimp.hxx:60
sal_Int16 mnStartScale
Definition: eventimp.hxx:59
virtual ~SdXMLEventsContext() override
Definition: eventimp.cxx:442
SvXMLEnumMapEntry< ClickAction > const aXML_EventActions_EnumMap[]
Definition: eventimp.cxx:51
static bool convertPercent(sal_Int32 &rValue, std::u16string_view rString)
This class deliberately does not support XWeak, to improve performance when loading large documents...
Definition: xmlictxt.hxx:45
Map an XMLTokenEnum to an enum value.
Definition: ximpshap.hxx:40
SdXMLEventsContext(SvXMLImport &rImport, const css::uno::Reference< css::drawing::XShape > &rxShape)
Definition: eventimp.cxx:437
const SvXMLEnumMapEntry< AnimationSpeed > aXML_AnimationSpeed_EnumMap[]
Definition: animimp.cxx:111
static bool translateToInternal(OUString const &rTheExtURIRef, OUString &rTheIntURIRef, DecodeMechanism eDecodeMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
OUString GetAbsoluteReference(const OUString &rValue) const
Definition: xmlimp.cxx:1589
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
#define SAL_WARN_IF(condition, area, stream)
Definition: anim.hxx:52
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3406
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
Handling of tokens in XML:
XMLEffectDirection meDirection
Definition: eventimp.hxx:58
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
Definition: anim.hxx:29
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:96
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
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:116
AnimationEffect ImplSdXMLgetEffect(XMLEffect eKind, XMLEffectDirection eDirection, sal_Int16 nStartScale, bool)
Definition: animimp.cxx:119
css::presentation::ClickAction meClickAction
Definition: eventimp.hxx:56
bool mbValid
OUString toString(OptionInfo const *info)