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 write <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 haven'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