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 
29 #include <sax/tools/converter.hxx>
30 
31 #include <xmloff/xmltoken.hxx>
32 #include <xmloff/xmlimp.hxx>
33 #include <xmloff/xmlnamespace.hxx>
34 #include <xmloff/xmluconv.hxx>
35 #include <xmloff/namespacemap.hxx>
36 #include "eventimp.hxx"
37 
38 using namespace ::std;
39 using namespace ::cppu;
40 using namespace ::com::sun::star;
41 using namespace ::com::sun::star::xml;
42 using namespace ::com::sun::star::xml::sax;
43 using namespace ::com::sun::star::uno;
44 using namespace ::com::sun::star::drawing;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::document;
48 using namespace ::com::sun::star::container;
49 using namespace ::com::sun::star::presentation;
50 using 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 
71 SdXMLEventContextData::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 
79 namespace {
80 
81 class SdXMLEventContext : public SvXMLImportContext
82 {
83 public:
85 
86 public:
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 
96 class XMLEventSoundContext : public SvXMLImportContext
97 {
98 public:
99 
100  XMLEventSoundContext( SvXMLImport& rImport, const Reference< XFastAttributeList >& xAttrList, SdXMLEventContext* pParent );
101 };
102 
103 }
104 
105 XMLEventSoundContext::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 
124 SdXMLEventContext::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):
157  SvXMLUnitConverter::convertEnum( maData.meDirection, aIter.toView(), aXML_AnimationDirection_EnumMap );
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());
204  INetURLObject::translateToInternal( rTmp, maData.msBookmark,
206  }
207  }
208  break;
209  }
210  }
211 
212  if( maData.mbValid )
213  maData.mbValid = !sEventName.isEmpty();
214 }
215 
216 css::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 
227 void 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 
438 SdXMLEventsContext::SdXMLEventsContext( SvXMLImport& rImport, const Reference< XShape >& rxShape)
439 : SvXMLImportContext(rImport), mxShape( rxShape )
440 {
441 }
442 
444 {
445 }
446 
447 css::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: */
css::uno::Reference< css::drawing::XShape > mxShape
Definition: eventimp.hxx:33
css::uno::Reference< css::drawing::XShape > mxShape
Definition: eventimp.hxx:51
the SvXMLTypeConverter converts values of various types from their internal representation to the tex...
Definition: xmluconv.hxx:82
SdXMLEventContextData(const css::uno::Reference< css::drawing::XShape > &rxShape)
Definition: eventimp.cxx:71
SvXMLImport & GetImport()
Definition: xmlictxt.hxx:60
constexpr sal_uInt16 XML_NAMESPACE_OOO
SvXMLNamespaceMap & GetNamespaceMap()
Definition: xmlimp.hxx:398
bool IsXMLToken(std::u16string_view rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3566
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
static bool translateToInternal(std::u16string_view rTheExtURIRef, OUString &rTheIntURIRef, DecodeMechanism eDecodeMechanism=DecodeMechanism::ToIUri, rtl_TextEncoding eCharset=RTL_TEXTENCODING_UTF8)
uno::Reference< drawing::XShape > const mxShape
PropertiesInfo aProperties
constexpr OUStringLiteral sLibrary
#define XMLOFF_WARN_UNKNOWN(area, rIter)
Definition: xmlictxt.hxx:114
static void convertNumber(OUStringBuffer &b, sal_Int32 n)
css::presentation::AnimationSpeed meSpeed
Definition: eventimp.hxx:59
sal_Int16 mnStartScale
Definition: eventimp.hxx:58
virtual ~SdXMLEventsContext() override
Definition: eventimp.cxx:443
SvXMLEnumMapEntry< ClickAction > const aXML_EventActions_EnumMap[]
Definition: eventimp.cxx:52
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:39
SdXMLEventsContext(SvXMLImport &rImport, const css::uno::Reference< css::drawing::XShape > &rxShape)
Definition: eventimp.cxx:438
const SvXMLEnumMapEntry< AnimationSpeed > aXML_AnimationSpeed_EnumMap[]
Definition: animimp.cxx:111
OUString GetAbsoluteReference(const OUString &rValue) const
Definition: xmlimp.cxx:1618
bool equalsIgnoreAsciiCase(std::u16string_view s1, std::u16string_view s2)
#define SAL_WARN_IF(condition, area, stream)
Definition: anim.hxx:51
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3510
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:57
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:28
#define XML_ELEMENT(prefix, name)
Definition: xmlimp.hxx:97
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
#define XMLOFF_WARN_UNKNOWN_ELEMENT(area, token)
Definition: xmlictxt.hxx:120
AnimationEffect ImplSdXMLgetEffect(XMLEffect eKind, XMLEffectDirection eDirection, sal_Int16 nStartScale, bool)
Definition: animimp.cxx:119
css::presentation::ClickAction meClickAction
Definition: eventimp.hxx:55
bool mbValid
OUString toString(OptionInfo const *info)
bool m_bDetectedRangeSegmentation false