xref: /AOO41X/main/xmloff/source/script/XMLEventExport.cxx (revision 63bba73cc51e0afb45f8a8d578158724bb5afee8)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 #include <xmloff/XMLEventExport.hxx>
27 
28 #ifndef _COM_SUN_STAR_BEANS_PROPERTYVALUE_HPP
29 #include <com/sun/star/beans/PropertyValue.hpp>
30 #endif
31 
32 #ifndef _COM_SUN_STAR_DOCUMENT_XEVENTSSUPPLIER_HPP
33 #include <com/sun/star/document/XEventsSupplier.hpp>
34 #endif
35 
36 #ifndef _COM_SUN_STAR_CONTAINER_XNAMEREPLACE_HPP
37 #include <com/sun/star/container/XNameReplace.hpp>
38 #endif
39 #include <tools/debug.hxx>
40 #include <xmloff/xmlexp.hxx>
41 #include <xmloff/xmltoken.hxx>
42 #include "xmloff/xmlnmspe.hxx"
43 #include <xmloff/nmspmap.hxx>
44 
45 
46 using namespace ::com::sun::star::uno;
47 
48 using std::map;
49 using ::rtl::OUString;
50 using ::com::sun::star::beans::PropertyValue;
51 using ::com::sun::star::document::XEventsSupplier;
52 using ::com::sun::star::container::XNameReplace;
53 using ::com::sun::star::container::XNameAccess;
54 using ::xmloff::token::GetXMLToken;
55 using ::xmloff::token::XML_EVENT_LISTENERS;
56 
57 
XMLEventExport(SvXMLExport & rExp,const XMLEventNameTranslation * pTranslationTable)58 XMLEventExport::XMLEventExport(SvXMLExport& rExp,
59                          const XMLEventNameTranslation* pTranslationTable) :
60     sEventType(RTL_CONSTASCII_USTRINGPARAM("EventType")),
61     rExport(rExp),
62     bExtNamespace(false)
63 {
64     AddTranslationTable(pTranslationTable);
65 }
66 
~XMLEventExport()67 XMLEventExport::~XMLEventExport()
68 {
69     // delete all handlers
70     HandlerMap::iterator aEnd = aHandlerMap.end();
71     for( HandlerMap::iterator aIter =
72              aHandlerMap.begin();
73          aIter != aEnd;
74          aIter++ )
75     {
76         delete aIter->second;
77     }
78     aHandlerMap.clear();
79 }
80 
AddHandler(const OUString & rName,XMLEventExportHandler * pHandler)81 void XMLEventExport::AddHandler( const OUString& rName,
82                                  XMLEventExportHandler* pHandler )
83 {
84     DBG_ASSERT(pHandler != NULL, "Need EventExportHandler");
85     if (pHandler != NULL)
86     {
87         aHandlerMap[rName] = pHandler;
88     }
89 }
90 
AddTranslationTable(const XMLEventNameTranslation * pTransTable)91 void XMLEventExport::AddTranslationTable(
92     const XMLEventNameTranslation* pTransTable )
93 {
94     if (NULL != pTransTable)
95     {
96         // put translation table into map
97         for(const XMLEventNameTranslation* pTrans = pTransTable;
98             pTrans->sAPIName != NULL;
99             pTrans++)
100         {
101             aNameTranslationMap[OUString::createFromAscii(pTrans->sAPIName)] =
102                 XMLEventName(pTrans->nPrefix, pTrans->sXMLName);
103         }
104     }
105     // else? ignore!
106 }
107 
Export(Reference<XEventsSupplier> & rSupplier,sal_Bool bWhitespace)108 void XMLEventExport::Export( Reference<XEventsSupplier> & rSupplier,
109                              sal_Bool bWhitespace)
110 {
111     if (rSupplier.is())
112     {
113         Reference<XNameAccess> xAccess(rSupplier->getEvents(), UNO_QUERY);
114         Export(xAccess, bWhitespace);
115     }
116     // else: no supplier, no export -> ignore!
117 }
118 
Export(Reference<XNameReplace> & rReplace,sal_Bool bWhitespace)119 void XMLEventExport::Export( Reference<XNameReplace> & rReplace,
120                              sal_Bool bWhitespace)
121 {
122     Reference<XNameAccess> xAccess(rReplace, UNO_QUERY);
123     Export(xAccess, bWhitespace);
124 }
125 
Export(Reference<XNameAccess> & rAccess,sal_Bool bWhitespace)126 void XMLEventExport::Export( Reference<XNameAccess> & rAccess,
127                              sal_Bool bWhitespace)
128 {
129     // early out if we don't actually get any events
130     if (!rAccess.is())
131     {
132         return;
133     }
134 
135     // have we already processed an element?
136     sal_Bool bStarted = sal_False;
137 
138     // iterate over all event types
139     Sequence<OUString> aNames = rAccess->getElementNames();
140     sal_Int32 nCount = aNames.getLength();
141     for(sal_Int32 i = 0; i < nCount; i++)
142     {
143         // translate name
144         NameMap::iterator aIter = aNameTranslationMap.find(aNames[i]);
145         if (aIter != aNameTranslationMap.end())
146         {
147             const XMLEventName& rXmlName = aIter->second;
148 
149             // get PropertyValues for this event
150             Any aAny = rAccess->getByName( aNames[i] );
151             Sequence<PropertyValue> aValues;
152             aAny >>= aValues;
153 
154             // now export the current event
155             ExportEvent( aValues, rXmlName, bWhitespace, bStarted );
156         }
157 #ifdef DBG_UTIL
158         else
159         {
160             // don't proceed further
161             ::rtl::OString aStr("Unknown event name:" );
162             aStr += ::rtl::OUStringToOString( aNames[i], RTL_TEXTENCODING_UTF8 );
163             DBG_ERROR( aStr.getStr() );
164         }
165 #endif
166     }
167 
168     // close <script:events> element (if it was opened before)
169     if (bStarted)
170     {
171         EndElement(bWhitespace);
172     }
173 }
174 
ExportExt(Reference<XNameAccess> & rAccess,sal_Bool bWhitespace)175 void XMLEventExport::ExportExt( Reference<XNameAccess> & rAccess,
176                                 sal_Bool bWhitespace )
177 {
178     // set bExtNamespace flag to use XML_NAMESPACE_OFFICE_EXT namespace
179     // for events element (not for child elements)
180     bExtNamespace = true;
181     Export(rAccess, bWhitespace);
182     bExtNamespace = false;          // reset for future Export calls
183 }
184 
185 /// export a singular event and wirte <office:events> container
ExportSingleEvent(Sequence<PropertyValue> & rEventValues,const OUString & rApiEventName,sal_Bool bUseWhitespace)186 void XMLEventExport::ExportSingleEvent(
187     Sequence<PropertyValue>& rEventValues,
188     const OUString& rApiEventName,
189     sal_Bool bUseWhitespace )
190 {
191     // translate the name
192     NameMap::iterator aIter = aNameTranslationMap.find(rApiEventName);
193     if (aIter != aNameTranslationMap.end())
194     {
195         const XMLEventName& rXmlName = aIter->second;
196 
197         // export the event ...
198         sal_Bool bStarted = sal_False;
199         ExportEvent( rEventValues, rXmlName, bUseWhitespace, bStarted );
200 
201         // ... and close the container element (if necessary)
202         if (bStarted)
203         {
204             EndElement(bUseWhitespace);
205         }
206     }
207 #ifdef DBG_UTIL
208     else
209     {
210         // don't proceed further
211         ::rtl::OString aStr("Unknown event name:" );
212         aStr += ::rtl::OUStringToOString( rApiEventName, RTL_TEXTENCODING_UTF8 );
213         DBG_ERROR( aStr.getStr() );
214     }
215 #endif
216 }
217 
218 
219 /// export a single event
ExportEvent(Sequence<PropertyValue> & rEventValues,const XMLEventName & rXmlEventName,sal_Bool bUseWhitespace,sal_Bool & rExported)220 void XMLEventExport::ExportEvent(
221     Sequence<PropertyValue>& rEventValues,
222     const XMLEventName& rXmlEventName,
223     sal_Bool bUseWhitespace,
224     sal_Bool& rExported )
225 {
226     // search for EventType value and then delegate to EventHandler
227     sal_Int32 nValues = rEventValues.getLength();
228     const PropertyValue* pValues = rEventValues.getConstArray();
229 
230     for(sal_Int32 nVal = 0; nVal < nValues; nVal++)
231     {
232         if (sEventType.equals(pValues[nVal].Name))
233         {
234             // found! Now find handler and delegate
235             OUString sType;
236             pValues[nVal].Value >>= sType;
237 
238             if (aHandlerMap.count(sType))
239             {
240                 if (! rExported)
241                 {
242                     // OK, we have't yet exported the enclosing
243                     // element. So we do that now.
244                     rExported = sal_True;
245                     StartElement(bUseWhitespace);
246                 }
247 
248                 OUString aEventQName(
249                     rExport.GetNamespaceMap().GetQNameByKey(
250                             rXmlEventName.m_nPrefix, rXmlEventName.m_aName ) );
251 
252                 // delegate to proper ExportEventHandler
253                 aHandlerMap[sType]->Export(rExport, aEventQName,
254                                            rEventValues, bUseWhitespace);
255             }
256             else
257             {
258                 if (! sType.equalsAsciiL("None", sizeof("None")-1))
259                 {
260                     DBG_ERROR("unknown event type returned by API");
261                     // unknown type -> error (ignore)
262                 }
263                 // else: we ignore None fields
264             }
265 
266             // early out: we don't need to look for another type
267             break;
268         }
269         // else: we only care for EventType -> ignore
270     }
271 }
272 
273 
StartElement(sal_Bool bWhitespace)274 void XMLEventExport::StartElement(sal_Bool bWhitespace)
275 {
276     if (bWhitespace)
277     {
278         rExport.IgnorableWhitespace();
279     }
280     sal_uInt16 nNamespace = bExtNamespace ? XML_NAMESPACE_OFFICE_EXT
281                                           : XML_NAMESPACE_OFFICE;
282     rExport.StartElement( nNamespace, XML_EVENT_LISTENERS,
283                           bWhitespace);
284 }
285 
EndElement(sal_Bool bWhitespace)286 void XMLEventExport::EndElement(sal_Bool bWhitespace)
287 {
288     sal_uInt16 nNamespace = bExtNamespace ? XML_NAMESPACE_OFFICE_EXT
289                                           : XML_NAMESPACE_OFFICE;
290     rExport.EndElement(nNamespace, XML_EVENT_LISTENERS, bWhitespace);
291     if (bWhitespace)
292     {
293         rExport.IgnorableWhitespace();
294     }
295 }
296 
297 
298 // implement aStandardEventTable (defined in xmlevent.hxx)
299 const XMLEventNameTranslation aStandardEventTable[] =
300 {
301     { "OnSelect",           XML_NAMESPACE_DOM, "select" }, // "on-select"
302     { "OnInsertStart",      XML_NAMESPACE_OFFICE, "insert-start" }, // "on-insert-start"
303     { "OnInsertDone",       XML_NAMESPACE_OFFICE, "insert-done" }, // "on-insert-done"
304     { "OnMailMerge",        XML_NAMESPACE_OFFICE, "mail-merge" }, // "on-mail-merge"
305     { "OnAlphaCharInput",   XML_NAMESPACE_OFFICE, "alpha-char-input" }, // "on-alpha-char-input"
306     { "OnNonAlphaCharInput",    XML_NAMESPACE_OFFICE, "non-alpha-char-input" }, // "on-non-alpha-char-input"
307     { "OnResize",           XML_NAMESPACE_DOM, "resize" }, // "on-resize"
308     { "OnMove",             XML_NAMESPACE_OFFICE, "move" }, // "on-move"
309     { "OnPageCountChange",  XML_NAMESPACE_OFFICE, "page-count-change" }, // "on-page-count-change"
310     { "OnMouseOver",        XML_NAMESPACE_DOM, "mouseover" }, // "on-mouse-over"
311     { "OnClick",            XML_NAMESPACE_DOM, "click" }, // "on-click"
312     { "OnMouseOut",         XML_NAMESPACE_DOM, "mouseout" }, // "on-mouse-out"
313     { "OnLoadError",        XML_NAMESPACE_OFFICE, "load-error" }, // "on-load-error"
314     { "OnLoadCancel",       XML_NAMESPACE_OFFICE, "load-cancel" }, // "on-load-cancel"
315     { "OnLoadDone",         XML_NAMESPACE_OFFICE, "load-done" }, // "on-load-done"
316     { "OnLoad",             XML_NAMESPACE_DOM, "load" }, // "on-load"
317     { "OnUnload",           XML_NAMESPACE_DOM, "unload" }, // "on-unload"
318     { "OnStartApp",         XML_NAMESPACE_OFFICE, "start-app" }, // "on-start-app"
319     { "OnCloseApp",         XML_NAMESPACE_OFFICE, "close-app" }, // "on-close-app"
320     { "OnNew",              XML_NAMESPACE_OFFICE, "new" }, // "on-new"
321     { "OnSave",             XML_NAMESPACE_OFFICE, "save" }, // "on-save"
322     { "OnSaveAs",           XML_NAMESPACE_OFFICE, "save-as" }, // "on-save-as"
323     { "OnFocus",            XML_NAMESPACE_DOM, "DOMFocusIn" }, // "on-focus"
324     { "OnUnfocus",          XML_NAMESPACE_DOM, "DOMFocusOut" }, // "on-unfocus"
325     { "OnPrint",            XML_NAMESPACE_OFFICE, "print" }, // "on-print"
326     { "OnError",            XML_NAMESPACE_DOM, "error" }, // "on-error"
327     { "OnLoadFinished",     XML_NAMESPACE_OFFICE, "load-finished" }, // "on-load-finished"
328     { "OnSaveFinished",     XML_NAMESPACE_OFFICE, "save-finished" }, // "on-save-finished"
329     { "OnModifyChanged",    XML_NAMESPACE_OFFICE, "modify-changed" }, // "on-modify-changed"
330     { "OnPrepareUnload",    XML_NAMESPACE_OFFICE, "prepare-unload" }, // "on-prepare-unload"
331     { "OnNewMail",          XML_NAMESPACE_OFFICE, "new-mail" }, // "on-new-mail"
332     { "OnToggleFullscreen", XML_NAMESPACE_OFFICE, "toggle-fullscreen" }, // "on-toggle-fullscreen"
333     { "OnSaveDone",         XML_NAMESPACE_OFFICE, "save-done" }, // "on-save-done"
334     { "OnSaveAsDone",       XML_NAMESPACE_OFFICE, "save-as-done" }, // "on-save-as-done"
335     { "OnCopyTo",           XML_NAMESPACE_OFFICE, "copy-to" },
336     { "OnCopyToDone",       XML_NAMESPACE_OFFICE, "copy-to-done" },
337     { "OnViewCreated",      XML_NAMESPACE_OFFICE, "view-created" },
338     { "OnPrepareViewClosing", XML_NAMESPACE_OFFICE, "prepare-view-closing" },
339     { "OnViewClosed",       XML_NAMESPACE_OFFICE, "view-close" },
340     { "OnVisAreaChanged",   XML_NAMESPACE_OFFICE, "visarea-changed" }, // "on-visarea-changed"
341     { "OnCreate",           XML_NAMESPACE_OFFICE, "create" },
342     { "OnSaveAsFailed",     XML_NAMESPACE_OFFICE, "save-as-failed" },
343     { "OnSaveFailed",       XML_NAMESPACE_OFFICE, "save-failed" },
344     { "OnCopyToFailed",     XML_NAMESPACE_OFFICE, "copy-to-failed" },
345     { "OnTitleChanged",     XML_NAMESPACE_OFFICE, "title-changed" },
346     { "OnModeChanged",      XML_NAMESPACE_OFFICE, "mode-changed" },
347     { "OnSaveTo",           XML_NAMESPACE_OFFICE, "save-to" },
348     { "OnSaveToDone",       XML_NAMESPACE_OFFICE, "save-to-done" },
349     { "OnSaveToFailed",     XML_NAMESPACE_OFFICE, "save-to-failed" },
350     { "OnSubComponentOpened",   XML_NAMESPACE_OFFICE, "subcomponent-opened" },
351     { "OnSubComponentClosed",   XML_NAMESPACE_OFFICE, "subcomponent-closed" },
352     { "OnStorageChanged",       XML_NAMESPACE_OFFICE, "storage-changed" },
353     { "OnMailMergeFinished",    XML_NAMESPACE_OFFICE, "mail-merge-finished" },
354     { "OnFieldMerge",           XML_NAMESPACE_OFFICE, "field-merge" },
355     { "OnFieldMergeFinished",   XML_NAMESPACE_OFFICE, "field-merge-finished" },
356     { "OnLayoutFinished",       XML_NAMESPACE_OFFICE, "layout-finished" },
357     { "OnDoubleClick",      XML_NAMESPACE_OFFICE, "dblclick" },
358     { "OnRightClick",       XML_NAMESPACE_OFFICE, "contextmenu" },
359     { "OnChange",           XML_NAMESPACE_OFFICE, "content-changed" },
360     { "OnCalculate",        XML_NAMESPACE_OFFICE, "calculated" },
361 
362     { NULL, 0, 0 }
363 };
364