fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / xmloff / source / text / XMLTextMarkImportContext.cxx
blobae89ab099658e719b0bddaa66645971a90e423e8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "XMLTextMarkImportContext.hxx"
23 #include <rtl/ustring.hxx>
24 #include <tools/debug.hxx>
25 #include <xmloff/xmluconv.hxx>
26 #include <xmloff/xmltoken.hxx>
27 #include <xmloff/xmlimp.hxx>
28 #include <xmloff/nmspmap.hxx>
29 #include "xmloff/xmlnmspe.hxx"
30 #include <xmloff/odffields.hxx>
31 #include <com/sun/star/xml/sax/XAttributeList.hpp>
32 #include <com/sun/star/text/XTextContent.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
35 #include <com/sun/star/container/XNamed.hpp>
36 #include <com/sun/star/rdf/XMetadatable.hpp>
38 #include <com/sun/star/text/XFormField.hpp>
40 #include "RDFaImportHelper.hxx"
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::text;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::lang;
49 using namespace ::com::sun::star::container;
50 using namespace ::com::sun::star::xml::sax;
51 using namespace ::xmloff::token;
55 XMLFieldParamImportContext::XMLFieldParamImportContext(
56 SvXMLImport& rImport,
57 XMLTextImportHelper& rHlp,
58 sal_uInt16 nPrefix,
59 const OUString& rLocalName ) :
60 SvXMLImportContext(rImport, nPrefix, rLocalName),
61 rHelper(rHlp)
66 void XMLFieldParamImportContext::StartElement(const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList> & xAttrList)
68 SvXMLImport& rImport = GetImport();
69 OUString sName;
70 OUString sValue;
72 sal_Int16 nLength = xAttrList->getLength();
73 for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
75 OUString sLocalName;
76 sal_uInt16 nPrefix = rImport.GetNamespaceMap().
77 GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
78 &sLocalName );
80 if ( (XML_NAMESPACE_FIELD == nPrefix) &&
81 IsXMLToken(sLocalName, XML_NAME) )
83 sName = xAttrList->getValueByIndex(nAttr);
85 if ( (XML_NAMESPACE_FIELD == nPrefix) &&
86 IsXMLToken(sLocalName, XML_VALUE) )
88 sValue = xAttrList->getValueByIndex(nAttr);
91 if (rHelper.hasCurrentFieldCtx() && !sName.isEmpty()) {
92 rHelper.addFieldParam(sName, sValue);
97 TYPEINIT1( XMLTextMarkImportContext, SvXMLImportContext);
99 XMLTextMarkImportContext::XMLTextMarkImportContext(
100 SvXMLImport& rImport,
101 XMLTextImportHelper& rHlp,
102 sal_uInt16 nPrefix,
103 const OUString& rLocalName )
104 : SvXMLImportContext(rImport, nPrefix, rLocalName)
105 , m_rHelper(rHlp)
106 , m_bHaveAbout(false)
110 enum lcl_MarkType { TypeReference, TypeReferenceStart, TypeReferenceEnd,
111 TypeBookmark, TypeBookmarkStart, TypeBookmarkEnd,
112 TypeFieldmark, TypeFieldmarkStart, TypeFieldmarkEnd
115 static SvXMLEnumMapEntry const lcl_aMarkTypeMap[] =
117 { XML_REFERENCE_MARK, TypeReference },
118 { XML_REFERENCE_MARK_START, TypeReferenceStart },
119 { XML_REFERENCE_MARK_END, TypeReferenceEnd },
120 { XML_BOOKMARK, TypeBookmark },
121 { XML_BOOKMARK_START, TypeBookmarkStart },
122 { XML_BOOKMARK_END, TypeBookmarkEnd },
123 { XML_FIELDMARK, TypeFieldmark },
124 { XML_FIELDMARK_START, TypeFieldmarkStart },
125 { XML_FIELDMARK_END, TypeFieldmarkEnd },
126 { XML_TOKEN_INVALID, 0 },
130 static const char *lcl_getFormFieldmarkName(OUString &name)
132 static const char sCheckbox[]=ODF_FORMCHECKBOX;
133 static const char sFormDropDown[]=ODF_FORMDROPDOWN;
134 if (name.compareToAscii("msoffice.field.FORMCHECKBOX")==0 ||
135 name.compareToAscii("ecma.office-open-xml.field.FORMCHECKBOX")==0)
136 return sCheckbox;
137 else if (name.compareToAscii(ODF_FORMCHECKBOX)==0)
138 return sCheckbox;
139 if (name.compareToAscii(ODF_FORMDROPDOWN)==0 ||
140 name.compareToAscii("ecma.office-open-xml.field.FORMDROPDOWN")==0)
141 return sFormDropDown;
142 else
143 return NULL;
146 static OUString lcl_getFieldmarkName(OUString &name)
148 static const char sFormtext[]=ODF_FORMTEXT;
149 if (name.compareToAscii("msoffice.field.FORMTEXT")==0 ||
150 name.compareToAscii("ecma.office-open-xml.field.FORMTEXT")==0)
151 return OUString::createFromAscii(sFormtext);
152 else if (name.compareToAscii(ODF_FORMTEXT)==0)
153 return OUString::createFromAscii(sFormtext);
154 else
155 return name;
159 void XMLTextMarkImportContext::StartElement(
160 const Reference<XAttributeList> & xAttrList)
162 if (!FindName(GetImport(), xAttrList))
164 m_sBookmarkName = OUString();
167 if (IsXMLToken(GetLocalName(), XML_FIELDMARK_END))
169 m_sBookmarkName = m_rHelper.FindActiveBookmarkName();
172 if (IsXMLToken(GetLocalName(), XML_FIELDMARK_START) || IsXMLToken(GetLocalName(), XML_FIELDMARK))
174 if (m_sBookmarkName.isEmpty())
176 m_sBookmarkName = "Unknown";
178 m_rHelper.pushFieldCtx( m_sBookmarkName, m_sFieldName );
182 void XMLTextMarkImportContext::EndElement()
184 SvXMLImportContext::EndElement();
186 static const OUString sAPI_reference_mark( "com.sun.star.text.ReferenceMark");
187 static const OUString sAPI_bookmark( "com.sun.star.text.Bookmark");
188 static const OUString sAPI_fieldmark( "com.sun.star.text.Fieldmark");
189 static const OUString sAPI_formfieldmark( "com.sun.star.text.FormFieldmark");
191 if (!m_sBookmarkName.isEmpty())
193 sal_uInt16 nTmp;
194 if (SvXMLUnitConverter::convertEnum(nTmp, GetLocalName(),
195 lcl_aMarkTypeMap))
197 switch ((lcl_MarkType)nTmp)
199 case TypeReference:
200 // export point reference mark
201 CreateAndInsertMark(GetImport(),
202 sAPI_reference_mark,
203 m_sBookmarkName,
204 m_rHelper.GetCursorAsRange()->getStart(),
205 OUString());
206 break;
208 case TypeFieldmark:
209 case TypeBookmark:
211 const char *formFieldmarkName=lcl_getFormFieldmarkName(m_sFieldName);
212 bool bImportAsField=((lcl_MarkType)nTmp==TypeFieldmark && formFieldmarkName!=NULL); //@TODO handle abbreviation cases..
213 // export point bookmark
214 const Reference<XInterface> xContent(
215 CreateAndInsertMark(GetImport(),
216 (bImportAsField?sAPI_formfieldmark:sAPI_bookmark),
217 m_sBookmarkName,
218 m_rHelper.GetCursorAsRange()->getStart(),
219 m_sXmlId) );
220 if ((lcl_MarkType)nTmp==TypeFieldmark) {
221 if (xContent.is() && bImportAsField) {
222 // setup fieldmark...
223 Reference< ::com::sun::star::text::XFormField> xFormField(xContent, UNO_QUERY);
224 xFormField->setFieldType(OUString::createFromAscii(formFieldmarkName));
225 if (xFormField.is() && m_rHelper.hasCurrentFieldCtx()) {
226 m_rHelper.setCurrentFieldParamsTo(xFormField);
229 m_rHelper.popFieldCtx();
232 break;
234 case TypeFieldmarkStart:
235 case TypeBookmarkStart:
236 // save XTextRange for later construction of bookmark
238 ::boost::shared_ptr< ::xmloff::ParsedRDFaAttributes >
239 pRDFaAttributes;
240 if (m_bHaveAbout && (TypeBookmarkStart
241 == static_cast<lcl_MarkType>(nTmp)))
243 pRDFaAttributes =
244 GetImport().GetRDFaImportHelper().ParseRDFa(
245 m_sAbout, m_sProperty,
246 m_sContent, m_sDatatype);
248 m_rHelper.InsertBookmarkStartRange(
249 m_sBookmarkName,
250 m_rHelper.GetCursorAsRange()->getStart(),
251 m_sXmlId, pRDFaAttributes);
253 break;
255 case TypeFieldmarkEnd:
256 case TypeBookmarkEnd:
258 // get old range, and construct
259 Reference<XTextRange> xStartRange;
260 ::boost::shared_ptr< ::xmloff::ParsedRDFaAttributes >
261 pRDFaAttributes;
262 if (m_rHelper.FindAndRemoveBookmarkStartRange(
263 m_sBookmarkName, xStartRange,
264 m_sXmlId, pRDFaAttributes))
266 Reference<XTextRange> xEndRange(
267 m_rHelper.GetCursorAsRange()->getStart());
269 // check if beginning and end are in same XText
270 if (xStartRange->getText() == xEndRange->getText())
272 // create range for insertion
273 Reference<XTextCursor> xInsertionCursor =
274 m_rHelper.GetText()->createTextCursorByRange(
275 xEndRange);
276 try {
277 xInsertionCursor->gotoRange(xStartRange, sal_True);
278 } catch (uno::Exception&) {
279 OSL_ENSURE(false,
280 "cannot go to end position of bookmark");
283 //DBG_ASSERT(! xInsertionCursor->isCollapsed(),
284 // "we want no point mark");
285 // can't assert, because someone could
286 // create a file with subsequence
287 // start/end elements
289 Reference<XTextRange> xInsertionRange(
290 xInsertionCursor, UNO_QUERY);
292 bool bImportAsField=((lcl_MarkType)nTmp==TypeFieldmarkEnd && m_rHelper.hasCurrentFieldCtx());
294 // insert reference
295 const Reference<XInterface> xContent(
296 CreateAndInsertMark(GetImport(),
297 (bImportAsField?sAPI_fieldmark:sAPI_bookmark),
298 m_sBookmarkName,
299 xInsertionRange,
300 m_sXmlId) );
301 if (pRDFaAttributes)
303 const Reference<rdf::XMetadatable>
304 xMeta(xContent, UNO_QUERY);
305 GetImport().GetRDFaImportHelper().AddRDFa(
306 xMeta, pRDFaAttributes);
309 if ((lcl_MarkType)nTmp==TypeFieldmarkEnd) {
310 if (xContent.is() && bImportAsField) {
311 // setup fieldmark...
312 Reference< ::com::sun::star::text::XFormField> xFormField(xContent, UNO_QUERY);
313 if (xFormField.is() && m_rHelper.hasCurrentFieldCtx()) {
314 OUString givenTypeName=m_rHelper.getCurrentFieldType();
315 OUString fieldmarkTypeName=lcl_getFieldmarkName(givenTypeName);
317 xFormField->setFieldType(fieldmarkTypeName);
318 m_rHelper.setCurrentFieldParamsTo(xFormField);
321 m_rHelper.popFieldCtx();
324 // else: beginning/end in different XText -> ignore!
326 // else: no start found -> ignore!
327 break;
330 case TypeReferenceStart:
331 case TypeReferenceEnd:
332 OSL_FAIL("reference start/end are handled in txtparai !");
333 break;
335 default:
336 OSL_FAIL("unknown mark type");
337 break;
343 SvXMLImportContext *XMLTextMarkImportContext::CreateChildContext( sal_uInt16 nPrefix,
344 const OUString& rLocalName,
345 const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& )
347 return new XMLFieldParamImportContext(GetImport(), m_rHelper,
348 nPrefix, rLocalName);
352 Reference<XTextContent> XMLTextMarkImportContext::CreateAndInsertMark(
353 SvXMLImport& rImport,
354 const OUString& sServiceName,
355 const OUString& sMarkName,
356 const Reference<XTextRange> & rRange,
357 const OUString& i_rXmlId)
359 // create mark
360 const Reference<XMultiServiceFactory> xFactory(rImport.GetModel(),
361 UNO_QUERY);
362 Reference<XInterface> xIfc;
364 if (xFactory.is())
366 xIfc = xFactory->createInstance(sServiceName);
368 if (!xIfc.is())
370 OSL_FAIL("CreateAndInsertMark: cannot create service?");
371 return 0;
374 // set name (unless there is no name (text:meta))
375 const Reference<XNamed> xNamed(xIfc, UNO_QUERY);
376 if (xNamed.is())
378 xNamed->setName(sMarkName);
380 else
382 if (!sMarkName.isEmpty())
384 OSL_FAIL("name given, but XNamed not supported?");
385 return 0;
389 // cast to XTextContent and attach to document
390 const Reference<XTextContent> xTextContent(xIfc, UNO_QUERY);
391 if (xTextContent.is())
395 // if inserting marks, bAbsorb==sal_False will cause
396 // collapsing of the given XTextRange.
397 rImport.GetTextImport()->GetText()->insertTextContent(rRange,
398 xTextContent, sal_True);
400 // xml:id for RDF metadata -- after insertion!
401 rImport.SetXmlId(xIfc, i_rXmlId);
403 return xTextContent;
405 catch (com::sun::star::lang::IllegalArgumentException &)
407 OSL_FAIL("CreateAndInsertMark: cannot insert?");
408 return 0;
412 return 0;
415 sal_Bool XMLTextMarkImportContext::FindName(
416 SvXMLImport& rImport,
417 const Reference<XAttributeList> & xAttrList)
419 sal_Bool bNameOK = sal_False;
421 // find name attribute first
422 const sal_Int16 nLength = xAttrList->getLength();
423 for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++)
425 OUString sLocalName;
426 const sal_uInt16 nPrefix = rImport.GetNamespaceMap().
427 GetKeyByAttrName( xAttrList->getNameByIndex(nAttr),
428 &sLocalName );
430 if ( (XML_NAMESPACE_TEXT == nPrefix) &&
431 IsXMLToken(sLocalName, XML_NAME) )
433 m_sBookmarkName = xAttrList->getValueByIndex(nAttr);
434 bNameOK = sal_True;
436 else if ( (XML_NAMESPACE_XML == nPrefix) &&
437 IsXMLToken(sLocalName, XML_ID) )
439 m_sXmlId = xAttrList->getValueByIndex(nAttr);
441 else if ( XML_NAMESPACE_XHTML == nPrefix )
443 // RDFa
444 if ( IsXMLToken( sLocalName, XML_ABOUT) )
446 m_sAbout = xAttrList->getValueByIndex(nAttr);
447 m_bHaveAbout = true;
449 else if ( IsXMLToken( sLocalName, XML_PROPERTY) )
451 m_sProperty = xAttrList->getValueByIndex(nAttr);
453 else if ( IsXMLToken( sLocalName, XML_CONTENT) )
455 m_sContent = xAttrList->getValueByIndex(nAttr);
457 else if ( IsXMLToken( sLocalName, XML_DATATYPE) )
459 m_sDatatype = xAttrList->getValueByIndex(nAttr);
462 else if ( (XML_NAMESPACE_FIELD == nPrefix) &&
463 IsXMLToken(sLocalName, XML_TYPE) )
465 m_sFieldName = xAttrList->getValueByIndex(nAttr);
469 return bNameOK;
472 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */