1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: XMLTextMarkImportContext.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_xmloff.hxx"
35 #include "XMLTextMarkImportContext.hxx"
38 #include <rtl/ustring.hxx>
39 #include <tools/debug.hxx>
40 #include <xmloff/xmluconv.hxx>
41 #include <xmloff/xmltoken.hxx>
42 #include <xmloff/xmlimp.hxx>
43 #include <xmloff/nmspmap.hxx>
44 #include <xmloff/ecmaflds.hxx>
45 #include "xmlnmspe.hxx"
46 #include <com/sun/star/xml/sax/XAttributeList.hpp>
47 #include <com/sun/star/text/XTextContent.hpp>
48 #include <com/sun/star/beans/XPropertySet.hpp>
49 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/container/XNamed.hpp>
51 #include <com/sun/star/rdf/XMetadatable.hpp>
53 #include <com/sun/star/text/XFormField.hpp>
56 using ::rtl::OUString
;
57 using ::rtl::OUStringBuffer
;
59 using namespace ::com::sun::star::text
;
60 using namespace ::com::sun::star::uno
;
61 using namespace ::com::sun::star::beans
;
62 using namespace ::com::sun::star::lang
;
63 using namespace ::com::sun::star::container
;
64 using namespace ::com::sun::star::xml::sax
;
65 using namespace ::xmloff::token
;
68 XMLFieldParamImportContext::XMLFieldParamImportContext(
70 XMLTextImportHelper
& rHlp
,
72 const OUString
& rLocalName
) :
73 SvXMLImportContext(rImport
, nPrefix
, rLocalName
),
79 void XMLFieldParamImportContext::StartElement(const ::com::sun::star::uno::Reference
< ::com::sun::star::xml::sax::XAttributeList
> & xAttrList
)
81 SvXMLImport
& rImport
= GetImport();
82 ::rtl::OUString sName
;
83 ::rtl::OUString sValue
;
85 sal_Int16 nLength
= xAttrList
->getLength();
86 for(sal_Int16 nAttr
= 0; nAttr
< nLength
; nAttr
++)
89 sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().
90 GetKeyByAttrName( xAttrList
->getNameByIndex(nAttr
),
93 if ( (XML_NAMESPACE_FIELD
== nPrefix
) &&
94 IsXMLToken(sLocalName
, XML_NAME
) )
96 sName
= xAttrList
->getValueByIndex(nAttr
);
98 if ( (XML_NAMESPACE_FIELD
== nPrefix
) &&
99 IsXMLToken(sLocalName
, XML_VALUE
) )
101 sValue
= xAttrList
->getValueByIndex(nAttr
);
104 if (rHelper
.hasCurrentFieldCtx() && sName
.getLength()>0) {
105 rHelper
.addFieldParam(sName
, sValue
);
110 TYPEINIT1( XMLTextMarkImportContext
, SvXMLImportContext
);
112 XMLTextMarkImportContext::XMLTextMarkImportContext(
113 SvXMLImport
& rImport
,
114 XMLTextImportHelper
& rHlp
,
116 const OUString
& rLocalName
)
117 : SvXMLImportContext(rImport
, nPrefix
, rLocalName
)
119 , m_bHaveAbout(false)
123 enum lcl_MarkType
{ TypeReference
, TypeReferenceStart
, TypeReferenceEnd
,
124 TypeBookmark
, TypeBookmarkStart
, TypeBookmarkEnd
,
125 TypeFieldmark
, TypeFieldmarkStart
, TypeFieldmarkEnd
128 static SvXMLEnumMapEntry __READONLY_DATA lcl_aMarkTypeMap
[] =
130 { XML_REFERENCE_MARK
, TypeReference
},
131 { XML_REFERENCE_MARK_START
, TypeReferenceStart
},
132 { XML_REFERENCE_MARK_END
, TypeReferenceEnd
},
133 { XML_BOOKMARK
, TypeBookmark
},
134 { XML_BOOKMARK_START
, TypeBookmarkStart
},
135 { XML_BOOKMARK_END
, TypeBookmarkEnd
},
136 { XML_FIELDMARK
, TypeFieldmark
},
137 { XML_FIELDMARK_START
, TypeFieldmarkStart
},
138 { XML_FIELDMARK_END
, TypeFieldmarkEnd
},
139 { XML_TOKEN_INVALID
, 0 },
143 static const char *lcl_getFormFieldmarkName(rtl::OUString
&name
)
145 static const char sCheckbox
[]=ECMA_FORMCHECKBOX
;
146 static const char sFormDropDown
[]=ECMA_FORMDROPDOWN
;
147 if (name
.compareToAscii("msoffice.field.FORMCHECKBOX")==0)
149 else if (name
.compareToAscii(ECMA_FORMCHECKBOX
)==0)
151 if (name
.compareToAscii(ECMA_FORMDROPDOWN
)==0)
152 return sFormDropDown
;
157 static rtl::OUString
lcl_getFieldmarkName(rtl::OUString
&name
)
159 static const char sFormtext
[]=ECMA_FORMTEXT
;
160 if (name
.compareToAscii("msoffice.field.FORMTEXT")==0)
161 return rtl::OUString::createFromAscii(sFormtext
);
162 else if (name
.compareToAscii(ECMA_FORMTEXT
)==0)
163 return rtl::OUString::createFromAscii(sFormtext
);
169 void XMLTextMarkImportContext::StartElement(
170 const Reference
<XAttributeList
> & xAttrList
)
172 if (!FindName(GetImport(), xAttrList
))
174 m_sBookmarkName
= OUString();
177 if (IsXMLToken(GetLocalName(), XML_FIELDMARK_END
))
179 m_sBookmarkName
= m_rHelper
.FindActiveBookmarkName();
182 if (IsXMLToken(GetLocalName(), XML_FIELDMARK_START
) || IsXMLToken(GetLocalName(), XML_FIELDMARK
))
184 if (m_sBookmarkName
.getLength() == 0)
186 m_sBookmarkName
= ::rtl::OUString::createFromAscii("Unknown");
188 m_rHelper
.pushFieldCtx( m_sBookmarkName
, m_sFieldName
);
192 void XMLTextMarkImportContext::EndElement()
194 SvXMLImportContext::EndElement();
196 const OUString
sAPI_reference_mark(
197 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.ReferenceMark"));
198 const OUString
sAPI_bookmark(
199 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Bookmark"));
200 const OUString
sAPI_fieldmark(
201 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Fieldmark"));
202 const OUString
sAPI_formfieldmark(
203 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.FormFieldmark"));
205 if (m_sBookmarkName
.getLength() > 0)
208 if (SvXMLUnitConverter::convertEnum(nTmp
, GetLocalName(),
211 switch ((lcl_MarkType
)nTmp
)
214 // export point reference mark
215 CreateAndInsertMark(GetImport(),
218 m_rHelper
.GetCursorAsRange()->getStart(),
225 const char *formFieldmarkName
=lcl_getFormFieldmarkName(m_sFieldName
);
226 bool bImportAsField
=((lcl_MarkType
)nTmp
==TypeFieldmark
&& formFieldmarkName
!=NULL
); //@TODO handle abbreviation cases..
227 // export point bookmark
228 const Reference
<XInterface
> xContent(
229 CreateAndInsertMark(GetImport(),
230 (bImportAsField
?sAPI_formfieldmark
:sAPI_bookmark
),
232 m_rHelper
.GetCursorAsRange()->getStart(),
236 const Reference
<com::sun::star::rdf::XMetadatable
>
237 xMeta( xContent
, UNO_QUERY
);
238 GetImport().AddRDFa(xMeta
,
239 m_sAbout
, m_sProperty
, m_sContent
, m_sDatatype
);
241 if ((lcl_MarkType
)nTmp
==TypeFieldmark
) {
242 if (xContent
.is() && bImportAsField
) {
243 // setup fieldmark...
244 Reference
< ::com::sun::star::text::XFormField
> xFormField(xContent
, UNO_QUERY
);
245 xFormField
->setFieldType(rtl::OUString::createFromAscii(formFieldmarkName
));
246 if (xFormField
.is() && m_rHelper
.hasCurrentFieldCtx()) {
247 m_rHelper
.setCurrentFieldParamsTo(xFormField
);
250 m_rHelper
.popFieldCtx();
255 case TypeFieldmarkStart
:
256 case TypeBookmarkStart
:
257 // save XTextRange for later construction of bookmark
258 m_rHelper
.InsertBookmarkStartRange(
259 m_sBookmarkName
, m_rHelper
.GetCursorAsRange()->getStart(),
263 case TypeFieldmarkEnd
:
264 case TypeBookmarkEnd
:
266 // get old range, and construct
267 Reference
<XTextRange
> xStartRange
;
268 if (m_rHelper
.FindAndRemoveBookmarkStartRange(m_sBookmarkName
,
269 xStartRange
, m_sXmlId
))
271 Reference
<XTextRange
> xEndRange(
272 m_rHelper
.GetCursorAsRange()->getStart());
274 // check if beginning and end are in same XText
275 if (xStartRange
->getText() == xEndRange
->getText())
277 // create range for insertion
278 Reference
<XTextCursor
> xInsertionCursor
=
279 m_rHelper
.GetText()->createTextCursorByRange(
281 xInsertionCursor
->gotoRange(xStartRange
, sal_True
);
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());
295 const Reference
<XInterface
> xContent(
296 CreateAndInsertMark(GetImport(),
297 (bImportAsField
?sAPI_fieldmark
:sAPI_bookmark
),
303 const Reference
<com::sun::star::rdf::XMetadatable
>
304 xMeta( xContent
, UNO_QUERY
);
305 GetImport().AddRDFa(xMeta
,
306 m_sAbout
, m_sProperty
, m_sContent
, m_sDatatype
);
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 rtl::OUString givenTypeName
=m_rHelper
.getCurrentFieldType();
315 rtl::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!
330 case TypeReferenceStart
:
331 case TypeReferenceEnd
:
332 DBG_ERROR("reference start/end are handled in txtparai !");
336 DBG_ERROR("unknown mark type");
343 SvXMLImportContext
*XMLTextMarkImportContext::CreateChildContext( USHORT nPrefix
,
344 const ::rtl::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
)
360 const Reference
<XMultiServiceFactory
> xFactory(rImport
.GetModel(),
362 Reference
<XInterface
> xIfc
;
366 xIfc
= xFactory
->createInstance(sServiceName
);
370 OSL_ENSURE(false, "CreateAndInsertMark: cannot create service?");
374 // set name (unless there is no name (text:meta))
375 const Reference
<XNamed
> xNamed(xIfc
, UNO_QUERY
);
378 xNamed
->setName(sMarkName
);
382 if (sMarkName
.getLength())
384 OSL_ENSURE(false, "name given, but XNamed not supported?");
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
);
405 catch (com::sun::star::lang::IllegalArgumentException
&)
407 OSL_ENSURE(false, "CreateAndInsertMark: cannot insert?");
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
++)
426 const sal_uInt16 nPrefix
= rImport
.GetNamespaceMap().
427 GetKeyByAttrName( xAttrList
->getNameByIndex(nAttr
),
430 if ( (XML_NAMESPACE_TEXT
== nPrefix
) &&
431 IsXMLToken(sLocalName
, XML_NAME
) )
433 m_sBookmarkName
= xAttrList
->getValueByIndex(nAttr
);
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
)
444 if ( IsXMLToken( sLocalName
, XML_ABOUT
) )
446 m_sAbout
= xAttrList
->getValueByIndex(nAttr
);
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
);