| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_xmloff.hxx" |
| |
| |
| #include "XMLTextMarkImportContext.hxx" |
| |
| |
| #include <rtl/ustring.hxx> |
| #include <tools/debug.hxx> |
| #include <xmloff/xmluconv.hxx> |
| #include <xmloff/xmltoken.hxx> |
| #include <xmloff/xmlimp.hxx> |
| #include <xmloff/nmspmap.hxx> |
| #include "xmloff/xmlnmspe.hxx" |
| #include <xmloff/odffields.hxx> |
| #include <com/sun/star/xml/sax/XAttributeList.hpp> |
| #include <com/sun/star/text/XTextContent.hpp> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/container/XNamed.hpp> |
| #include <com/sun/star/rdf/XMetadatable.hpp> |
| |
| #include <com/sun/star/text/XFormField.hpp> |
| |
| #include "RDFaImportHelper.hxx" |
| |
| |
| using ::rtl::OUString; |
| using ::rtl::OUStringBuffer; |
| |
| using namespace ::com::sun::star; |
| using namespace ::com::sun::star::text; |
| using namespace ::com::sun::star::uno; |
| using namespace ::com::sun::star::beans; |
| using namespace ::com::sun::star::lang; |
| using namespace ::com::sun::star::container; |
| using namespace ::com::sun::star::xml::sax; |
| using namespace ::xmloff::token; |
| |
| |
| XMLFieldParamImportContext::XMLFieldParamImportContext( |
| SvXMLImport& rImport, |
| XMLTextImportHelper& rHlp, |
| sal_uInt16 nPrefix, |
| const OUString& rLocalName ) : |
| SvXMLImportContext(rImport, nPrefix, rLocalName), |
| rHelper(rHlp) |
| { |
| } |
| |
| |
| void XMLFieldParamImportContext::StartElement(const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList> & xAttrList) |
| { |
| SvXMLImport& rImport = GetImport(); |
| ::rtl::OUString sName; |
| ::rtl::OUString sValue; |
| |
| sal_Int16 nLength = xAttrList->getLength(); |
| for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++) |
| { |
| OUString sLocalName; |
| sal_uInt16 nPrefix = rImport.GetNamespaceMap(). |
| GetKeyByAttrName( xAttrList->getNameByIndex(nAttr), |
| &sLocalName ); |
| |
| if ( (XML_NAMESPACE_FIELD == nPrefix) && |
| IsXMLToken(sLocalName, XML_NAME) ) |
| { |
| sName = xAttrList->getValueByIndex(nAttr); |
| } |
| if ( (XML_NAMESPACE_FIELD == nPrefix) && |
| IsXMLToken(sLocalName, XML_VALUE) ) |
| { |
| sValue = xAttrList->getValueByIndex(nAttr); |
| } |
| } |
| if (rHelper.hasCurrentFieldCtx() && sName.getLength()>0) { |
| rHelper.addFieldParam(sName, sValue); |
| } |
| } |
| |
| |
| TYPEINIT1( XMLTextMarkImportContext, SvXMLImportContext); |
| |
| XMLTextMarkImportContext::XMLTextMarkImportContext( |
| SvXMLImport& rImport, |
| XMLTextImportHelper& rHlp, |
| sal_uInt16 nPrefix, |
| const OUString& rLocalName ) |
| : SvXMLImportContext(rImport, nPrefix, rLocalName) |
| , m_rHelper(rHlp) |
| , m_bHaveAbout(false) |
| { |
| } |
| |
| enum lcl_MarkType { TypeReference, TypeReferenceStart, TypeReferenceEnd, |
| TypeBookmark, TypeBookmarkStart, TypeBookmarkEnd, |
| TypeFieldmark, TypeFieldmarkStart, TypeFieldmarkEnd |
| }; |
| |
| static SvXMLEnumMapEntry __READONLY_DATA lcl_aMarkTypeMap[] = |
| { |
| { XML_REFERENCE_MARK, TypeReference }, |
| { XML_REFERENCE_MARK_START, TypeReferenceStart }, |
| { XML_REFERENCE_MARK_END, TypeReferenceEnd }, |
| { XML_BOOKMARK, TypeBookmark }, |
| { XML_BOOKMARK_START, TypeBookmarkStart }, |
| { XML_BOOKMARK_END, TypeBookmarkEnd }, |
| { XML_FIELDMARK, TypeFieldmark }, |
| { XML_FIELDMARK_START, TypeFieldmarkStart }, |
| { XML_FIELDMARK_END, TypeFieldmarkEnd }, |
| { XML_TOKEN_INVALID, 0 }, |
| }; |
| |
| |
| static const char *lcl_getFormFieldmarkName(rtl::OUString &name) |
| { |
| static const char sCheckbox[]=ODF_FORMCHECKBOX; |
| static const char sFormDropDown[]=ODF_FORMDROPDOWN; |
| if (name.compareToAscii("msoffice.field.FORMCHECKBOX")==0) |
| return sCheckbox; |
| else if (name.compareToAscii(ODF_FORMCHECKBOX)==0) |
| return sCheckbox; |
| if (name.compareToAscii(ODF_FORMDROPDOWN)==0) |
| return sFormDropDown; |
| else |
| return NULL; |
| } |
| |
| static rtl::OUString lcl_getFieldmarkName(rtl::OUString &name) |
| { |
| static const char sFormtext[]=ODF_FORMTEXT; |
| if (name.compareToAscii("msoffice.field.FORMTEXT")==0) |
| return rtl::OUString::createFromAscii(sFormtext); |
| else if (name.compareToAscii(ODF_FORMTEXT)==0) |
| return rtl::OUString::createFromAscii(sFormtext); |
| else |
| return name; |
| } |
| |
| |
| void XMLTextMarkImportContext::StartElement( |
| const Reference<XAttributeList> & xAttrList) |
| { |
| if (!FindName(GetImport(), xAttrList)) |
| { |
| m_sBookmarkName = OUString(); |
| } |
| |
| if (IsXMLToken(GetLocalName(), XML_FIELDMARK_END)) |
| { |
| m_sBookmarkName = m_rHelper.FindActiveBookmarkName(); |
| } |
| |
| if (IsXMLToken(GetLocalName(), XML_FIELDMARK_START) || IsXMLToken(GetLocalName(), XML_FIELDMARK)) |
| { |
| if (m_sBookmarkName.getLength() == 0) |
| { |
| m_sBookmarkName = ::rtl::OUString::createFromAscii("Unknown"); |
| } |
| m_rHelper.pushFieldCtx( m_sBookmarkName, m_sFieldName ); |
| } |
| } |
| |
| void XMLTextMarkImportContext::EndElement() |
| { |
| SvXMLImportContext::EndElement(); |
| |
| static const OUString sAPI_reference_mark( |
| RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.ReferenceMark")); |
| static const OUString sAPI_bookmark( |
| RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Bookmark")); |
| static const OUString sAPI_fieldmark( |
| RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.Fieldmark")); |
| static const OUString sAPI_formfieldmark( |
| RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.FormFieldmark")); |
| |
| if (m_sBookmarkName.getLength() > 0) |
| { |
| sal_uInt16 nTmp; |
| if (SvXMLUnitConverter::convertEnum(nTmp, GetLocalName(), |
| lcl_aMarkTypeMap)) |
| { |
| switch ((lcl_MarkType)nTmp) |
| { |
| case TypeReference: |
| // export point reference mark |
| CreateAndInsertMark(GetImport(), |
| sAPI_reference_mark, |
| m_sBookmarkName, |
| m_rHelper.GetCursorAsRange()->getStart(), |
| ::rtl::OUString()); |
| break; |
| |
| case TypeFieldmark: |
| case TypeBookmark: |
| { |
| const char *formFieldmarkName=lcl_getFormFieldmarkName(m_sFieldName); |
| bool bImportAsField=((lcl_MarkType)nTmp==TypeFieldmark && formFieldmarkName!=NULL); //@TODO handle abbreviation cases.. |
| // export point bookmark |
| const Reference<XInterface> xContent( |
| CreateAndInsertMark(GetImport(), |
| (bImportAsField?sAPI_formfieldmark:sAPI_bookmark), |
| m_sBookmarkName, |
| m_rHelper.GetCursorAsRange()->getStart(), |
| m_sXmlId) ); |
| if ((lcl_MarkType)nTmp==TypeFieldmark) { |
| if (xContent.is() && bImportAsField) { |
| // setup fieldmark... |
| Reference< ::com::sun::star::text::XFormField> xFormField(xContent, UNO_QUERY); |
| xFormField->setFieldType(rtl::OUString::createFromAscii(formFieldmarkName)); |
| if (xFormField.is() && m_rHelper.hasCurrentFieldCtx()) { |
| m_rHelper.setCurrentFieldParamsTo(xFormField); |
| } |
| } |
| m_rHelper.popFieldCtx(); |
| } |
| } |
| break; |
| |
| case TypeFieldmarkStart: |
| case TypeBookmarkStart: |
| // save XTextRange for later construction of bookmark |
| { |
| ::boost::shared_ptr< ::xmloff::ParsedRDFaAttributes > |
| pRDFaAttributes; |
| if (m_bHaveAbout && (TypeBookmarkStart |
| == static_cast<lcl_MarkType>(nTmp))) |
| { |
| pRDFaAttributes = |
| GetImport().GetRDFaImportHelper().ParseRDFa( |
| m_sAbout, m_sProperty, |
| m_sContent, m_sDatatype); |
| } |
| m_rHelper.InsertBookmarkStartRange( |
| m_sBookmarkName, |
| m_rHelper.GetCursorAsRange()->getStart(), |
| m_sXmlId, pRDFaAttributes); |
| } |
| break; |
| |
| case TypeFieldmarkEnd: |
| case TypeBookmarkEnd: |
| { |
| // get old range, and construct |
| Reference<XTextRange> xStartRange; |
| ::boost::shared_ptr< ::xmloff::ParsedRDFaAttributes > |
| pRDFaAttributes; |
| if (m_rHelper.FindAndRemoveBookmarkStartRange( |
| m_sBookmarkName, xStartRange, |
| m_sXmlId, pRDFaAttributes)) |
| { |
| Reference<XTextRange> xEndRange( |
| m_rHelper.GetCursorAsRange()->getStart()); |
| |
| // check if beginning and end are in same XText |
| if (xStartRange->getText() == xEndRange->getText()) |
| { |
| // create range for insertion |
| Reference<XTextCursor> xInsertionCursor = |
| m_rHelper.GetText()->createTextCursorByRange( |
| xEndRange); |
| try { |
| xInsertionCursor->gotoRange(xStartRange, sal_True); |
| } catch (uno::Exception&) { |
| OSL_ENSURE(false, |
| "cannot go to end position of bookmark"); |
| } |
| |
| //DBG_ASSERT(! xInsertionCursor->isCollapsed(), |
| // "we want no point mark"); |
| // can't assert, because someone could |
| // create a file with subsequence |
| // start/end elements |
| |
| Reference<XTextRange> xInsertionRange( |
| xInsertionCursor, UNO_QUERY); |
| |
| bool bImportAsField=((lcl_MarkType)nTmp==TypeFieldmarkEnd && m_rHelper.hasCurrentFieldCtx()); |
| |
| // insert reference |
| const Reference<XInterface> xContent( |
| CreateAndInsertMark(GetImport(), |
| (bImportAsField?sAPI_fieldmark:sAPI_bookmark), |
| m_sBookmarkName, |
| xInsertionRange, |
| m_sXmlId) ); |
| if (pRDFaAttributes) |
| { |
| const Reference<rdf::XMetadatable> |
| xMeta(xContent, UNO_QUERY); |
| GetImport().GetRDFaImportHelper().AddRDFa( |
| xMeta, pRDFaAttributes); |
| } |
| |
| if ((lcl_MarkType)nTmp==TypeFieldmarkEnd) { |
| if (xContent.is() && bImportAsField) { |
| // setup fieldmark... |
| Reference< ::com::sun::star::text::XFormField> xFormField(xContent, UNO_QUERY); |
| if (xFormField.is() && m_rHelper.hasCurrentFieldCtx()) { |
| rtl::OUString givenTypeName=m_rHelper.getCurrentFieldType(); |
| rtl::OUString fieldmarkTypeName=lcl_getFieldmarkName(givenTypeName); |
| |
| xFormField->setFieldType(fieldmarkTypeName); |
| m_rHelper.setCurrentFieldParamsTo(xFormField); |
| } |
| } |
| m_rHelper.popFieldCtx(); |
| } |
| } |
| // else: beginning/end in different XText -> ignore! |
| } |
| // else: no start found -> ignore! |
| break; |
| } |
| |
| case TypeReferenceStart: |
| case TypeReferenceEnd: |
| DBG_ERROR("reference start/end are handled in txtparai !"); |
| break; |
| |
| default: |
| DBG_ERROR("unknown mark type"); |
| break; |
| } |
| } |
| } |
| } |
| |
| SvXMLImportContext *XMLTextMarkImportContext::CreateChildContext( sal_uInt16 nPrefix, |
| const ::rtl::OUString& rLocalName, |
| const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList >& ) |
| { |
| return new XMLFieldParamImportContext(GetImport(), m_rHelper, |
| nPrefix, rLocalName); |
| } |
| |
| |
| Reference<XTextContent> XMLTextMarkImportContext::CreateAndInsertMark( |
| SvXMLImport& rImport, |
| const OUString& sServiceName, |
| const OUString& sMarkName, |
| const Reference<XTextRange> & rRange, |
| const OUString& i_rXmlId) |
| { |
| // create mark |
| const Reference<XMultiServiceFactory> xFactory(rImport.GetModel(), |
| UNO_QUERY); |
| Reference<XInterface> xIfc; |
| |
| if (xFactory.is()) |
| { |
| xIfc = xFactory->createInstance(sServiceName); |
| |
| if (!xIfc.is()) |
| { |
| OSL_ENSURE(false, "CreateAndInsertMark: cannot create service?"); |
| return 0; |
| } |
| |
| // set name (unless there is no name (text:meta)) |
| const Reference<XNamed> xNamed(xIfc, UNO_QUERY); |
| if (xNamed.is()) |
| { |
| xNamed->setName(sMarkName); |
| } |
| else |
| { |
| if (sMarkName.getLength()) |
| { |
| OSL_ENSURE(false, "name given, but XNamed not supported?"); |
| return 0; |
| } |
| } |
| |
| // cast to XTextContent and attach to document |
| const Reference<XTextContent> xTextContent(xIfc, UNO_QUERY); |
| if (xTextContent.is()) |
| { |
| try |
| { |
| // if inserting marks, bAbsorb==sal_False will cause |
| // collapsing of the given XTextRange. |
| rImport.GetTextImport()->GetText()->insertTextContent(rRange, |
| xTextContent, sal_True); |
| |
| // xml:id for RDF metadata -- after insertion! |
| rImport.SetXmlId(xIfc, i_rXmlId); |
| |
| return xTextContent; |
| } |
| catch (com::sun::star::lang::IllegalArgumentException &) |
| { |
| OSL_ENSURE(false, "CreateAndInsertMark: cannot insert?"); |
| return 0; |
| } |
| } |
| } |
| return 0; |
| } |
| |
| sal_Bool XMLTextMarkImportContext::FindName( |
| SvXMLImport& rImport, |
| const Reference<XAttributeList> & xAttrList) |
| { |
| sal_Bool bNameOK = sal_False; |
| |
| // find name attribute first |
| const sal_Int16 nLength = xAttrList->getLength(); |
| for(sal_Int16 nAttr = 0; nAttr < nLength; nAttr++) |
| { |
| OUString sLocalName; |
| const sal_uInt16 nPrefix = rImport.GetNamespaceMap(). |
| GetKeyByAttrName( xAttrList->getNameByIndex(nAttr), |
| &sLocalName ); |
| |
| if ( (XML_NAMESPACE_TEXT == nPrefix) && |
| IsXMLToken(sLocalName, XML_NAME) ) |
| { |
| m_sBookmarkName = xAttrList->getValueByIndex(nAttr); |
| bNameOK = sal_True; |
| } |
| else if ( (XML_NAMESPACE_XML == nPrefix) && |
| IsXMLToken(sLocalName, XML_ID) ) |
| { |
| m_sXmlId = xAttrList->getValueByIndex(nAttr); |
| } |
| else if ( XML_NAMESPACE_XHTML == nPrefix ) |
| { |
| // RDFa |
| if ( IsXMLToken( sLocalName, XML_ABOUT) ) |
| { |
| m_sAbout = xAttrList->getValueByIndex(nAttr); |
| m_bHaveAbout = true; |
| } |
| else if ( IsXMLToken( sLocalName, XML_PROPERTY) ) |
| { |
| m_sProperty = xAttrList->getValueByIndex(nAttr); |
| } |
| else if ( IsXMLToken( sLocalName, XML_CONTENT) ) |
| { |
| m_sContent = xAttrList->getValueByIndex(nAttr); |
| } |
| else if ( IsXMLToken( sLocalName, XML_DATATYPE) ) |
| { |
| m_sDatatype = xAttrList->getValueByIndex(nAttr); |
| } |
| } |
| else if ( (XML_NAMESPACE_FIELD == nPrefix) && |
| IsXMLToken(sLocalName, XML_TYPE) ) |
| { |
| m_sFieldName = xAttrList->getValueByIndex(nAttr); |
| } |
| } |
| |
| return bNameOK; |
| } |
| |