/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * 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 .
*/
if ( mpHint->GetHRef().isEmpty() )
{ // hyperlink without a URL is not imported. delete mpHint;
mpHint = nullptr;
} else
{
m_rHints.push_back(std::unique_ptr<XMLHyperlinkHint_Impl>(mpHint));
}
}
XMLImpHyperlinkContext_Impl::~XMLImpHyperlinkContext_Impl()
{ if (mpHint)
mpHint->SetEnd( GetImport().GetTextImport()
->GetCursorAsRange()->getStart() );
}
/** * Process index marks. * * All *-mark-end index marks should instantiate *this* class (because * it doesn't process attributes other than ID), while the *-mark and * *-mark-start classes should instantiate the appropriate subclasses.
*/ class XMLIndexMarkImportContext_Impl : public SvXMLImportContext
{
XMLHints_Impl& m_rHints;
OUString sID;
/// process all attributes void ProcessAttributes(sal_Int32 nElement, const Reference<xml::sax::XFastAttributeList> & xAttrList,
Reference<beans::XPropertySet>& rPropSet);
/** * All marks can be created immediately. Since we don't care about * the element content, ProcessAttribute should set the properties * immediately. * * This method tolerates an empty PropertySet; subclasses however * are not expected to.
*/ virtualvoid ProcessAttribute(sal_Int32 nElement, const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
Reference<beans::XPropertySet>& rPropSet);
void XMLIndexMarkImportContext_Impl::startFastElement(
sal_Int32 nElement, const Reference<xml::sax::XFastAttributeList> & xAttrList)
{ // get Cursor position (needed for all cases)
Reference<XTextRange> xPos(
GetImport().GetTextImport()->GetCursor()->getStart());
Reference<beans::XPropertySet> xMark;
switch (nElement)
{ case XML_ELEMENT(TEXT, XML_TOC_MARK): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK):
{ // single mark: create mark and insert
OUString sService;
GetServiceName(sService, nElement); if (CreateMark(xMark, sService))
{
ProcessAttributes(nElement, xAttrList, xMark);
m_rHints.push_back(
std::make_unique<XMLIndexMarkHint_Impl>(xMark, xPos));
} // else: can't create mark -> ignore break;
}
case XML_ELEMENT(TEXT, XML_TOC_MARK_START): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
{ // start: create mark and insert (if ID is found)
OUString sService;
GetServiceName(sService, nElement); if (CreateMark(xMark, sService))
{
ProcessAttributes(nElement, xAttrList, xMark); if (!sID.isEmpty())
{ // process only if we find an ID
m_rHints.push_back(
std::make_unique<XMLIndexMarkHint_Impl>(xMark, xPos, sID));
} // else: no ID -> we'll never find the end -> ignore
} // else: can't create mark -> ignore break;
}
case XML_ELEMENT(TEXT, XML_TOC_MARK_END): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
{ // end: search for ID and set end of mark
// call process attributes with empty XPropertySet:
ProcessAttributes(nElement, xAttrList, xMark); if (!sID.isEmpty())
{ // if we have an ID, find the hint and set the end position
XMLIndexMarkHint_Impl *const pHint = m_rHints.GetIndexHintById(sID); if (pHint) // set end and stop searching
pHint->SetEnd(xPos);
} // else: no ID -> ignore break;
}
default:
SAL_WARN("xmloff.text", "unknown index mark type!"); break;
}
}
void XMLIndexMarkImportContext_Impl::ProcessAttribute(
sal_Int32 nElement, const sax_fastparser::FastAttributeList::FastAttributeIter & aIter,
Reference<beans::XPropertySet>& rPropSet)
{ // we only know ID + string-value attribute; // (former: marks, latter: -start + -end-marks) // the remainder is handled in sub-classes switch (nElement)
{ case XML_ELEMENT(TEXT, XML_TOC_MARK): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK): if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_STRING_VALUE) )
{
rPropSet->setPropertyValue(u"AlternativeText"_ustr, uno::Any(aIter.toString()));
} // else: ignore! break;
case XML_ELEMENT(TEXT, XML_TOC_MARK_START): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START): case XML_ELEMENT(TEXT, XML_TOC_MARK_END): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END): if ( aIter.getToken() == XML_ELEMENT(TEXT, XML_ID) )
{
sID = aIter.toString();
} // else: ignore break;
void XMLIndexMarkImportContext_Impl::GetServiceName(
OUString& sServiceName,
sal_Int32 nElement)
{ switch (nElement)
{ case XML_ELEMENT(TEXT, XML_TOC_MARK): case XML_ELEMENT(TEXT, XML_TOC_MARK_START): case XML_ELEMENT(TEXT, XML_TOC_MARK_END):
{
sServiceName = "com.sun.star.text.ContentIndexMark"; break;
}
case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END):
{
sServiceName = "com.sun.star.text.UserIndexMark"; break;
}
case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
{
sServiceName = "com.sun.star.text.DocumentIndexMark"; break;
}
switch( nElement )
{ case XML_ELEMENT(TEXT, XML_SPAN):
pContext = new XMLImpSpanContext_Impl( rImport, nElement,
xAttrList,
rHints,
rIgnoreLeadingSpace
,nStarFontsConvFlags
); break;
case XML_ELEMENT(TEXT, XML_TAB):
pContext = new XMLCharContext( rImport, xAttrList,
0x0009, false );
rIgnoreLeadingSpace = false; break;
case XML_ELEMENT(TEXT, XML_LINE_BREAK): if (xAttrList->hasAttribute(XML_ELEMENT(LO_EXT, XML_CLEAR)))
{
pContext = new SvXMLLineBreakContext(rImport, *rImport.GetTextImport());
} else
{
pContext = new XMLCharContext(rImport, ControlCharacter::LINE_BREAK);
}
rIgnoreLeadingSpace = false; break;
case XML_ELEMENT(TEXT, XML_S):
pContext = new XMLCharContext( rImport, xAttrList, 0x0020, true );
rIgnoreLeadingSpace = false; break;
case XML_ELEMENT(TEXT, XML_A):
{ // test for HyperLinkURL property. If present, insert link as // text property (StarWriter), else try to insert as text // field (StarCalc, StarDraw, ...)
Reference< beans::XPropertySet > xPropSet( rImport.GetTextImport()->GetCursor(), UNO_QUERY );
if ( xPropSet->getPropertySetInfo()->hasPropertyByName( u"HyperLinkURL"_ustr ) )
{
pContext = new XMLImpHyperlinkContext_Impl(
rImport,
nElement,
xAttrList,
rHints,
rIgnoreLeadingSpace );
} else
{
pContext = new XMLUrlFieldImportContext(rImport, *rImport.GetTextImport()); //whitespace handling like other fields
rIgnoreLeadingSpace = false;
} break;
}
case XML_ELEMENT(TEXT, XML_RUBY):
pContext = new XMLImpRubyContext_Impl( rImport, nElement,
xAttrList,
rHints,
rIgnoreLeadingSpace ); break;
case XML_ELEMENT(TEXT, XML_NOTE): if (rImport.GetTextImport()->IsInFrame())
{ // we must not insert footnotes into text frames
pContext = new SvXMLImportContext( rImport );
} else
{
pContext = new XMLFootnoteImportContext(rImport, *rImport.GetTextImport());
}
rIgnoreLeadingSpace = false; break;
case XML_ELEMENT(TEXT, XML_REFERENCE_MARK): case XML_ELEMENT(TEXT, XML_BOOKMARK): case XML_ELEMENT(TEXT, XML_BOOKMARK_START): case XML_ELEMENT(TEXT, XML_BOOKMARK_END):
pContext = new XMLTextMarkImportContext(rImport, *rImport.GetTextImport(),
rHints.GetCrossRefHeadingBookmark()); break;
case XML_ELEMENT(FIELD, XML_FIELDMARK): case XML_ELEMENT(FIELD, XML_FIELDMARK_START): case XML_ELEMENT(FIELD, XML_FIELDMARK_SEPARATOR): case XML_ELEMENT(FIELD, XML_FIELDMARK_END):
pContext = new XMLTextMarkImportContext(rImport, *rImport.GetTextImport(),
rHints.GetCrossRefHeadingBookmark()); break;
case XML_ELEMENT(TEXT, XML_REFERENCE_MARK_START):
pContext = new XMLStartReferenceContext_Impl( rImport,
rHints, xAttrList ); break;
case XML_ELEMENT(TEXT, XML_REFERENCE_MARK_END):
pContext = new XMLEndReferenceContext_Impl( rImport,
rHints, xAttrList ); break;
case XML_ELEMENT(DRAW, XML_FRAME):
{
Reference < XTextRange > xAnchorPos =
rImport.GetTextImport()->GetCursor()->getStart();
XMLTextFrameContext *pTextFrameContext = new XMLTextFrameContext(rImport,
xAttrList,
TextContentAnchorType_AS_CHARACTER ); // Remove check for text content. (#i33242#) // Check for text content is done on the processing of the hint if( TextContentAnchorType_AT_CHARACTER ==
pTextFrameContext->GetAnchorType() )
{
rHints.push_back(std::make_unique<XMLTextFrameHint_Impl>(
pTextFrameContext, xAnchorPos));
}
pContext = pTextFrameContext;
rIgnoreLeadingSpace = false;
} break; case XML_ELEMENT(DRAW, XML_A):
{
Reference < XTextRange > xAnchorPos(rImport.GetTextImport()->GetCursor()->getStart());
pContext = new XMLTextFrameHyperlinkContext( rImport, nElement,
xAttrList,
TextContentAnchorType_AS_CHARACTER );
rHints.push_back(
std::make_unique<XMLTextFrameHint_Impl>(pContext, xAnchorPos));
} break;
case XML_ELEMENT(TEXT, XML_TOC_MARK): case XML_ELEMENT(TEXT, XML_TOC_MARK_START):
pContext = new XMLTOCMarkImportContext_Impl(
rImport, rHints); break;
case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_START):
pContext = new XMLUserIndexMarkImportContext_Impl(
rImport, rHints); break;
case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_START):
pContext = new XMLAlphaIndexMarkImportContext_Impl(
rImport, rHints); break;
case XML_ELEMENT(TEXT, XML_TOC_MARK_END): case XML_ELEMENT(TEXT, XML_USER_INDEX_MARK_END): case XML_ELEMENT(TEXT, XML_ALPHABETICAL_INDEX_MARK_END):
pContext = new XMLIndexMarkImportContext_Impl(
rImport, rHints); break;
case XML_ELEMENT(TEXT, XML_CHANGE_START): case XML_ELEMENT(TEXT, XML_CHANGE_END): case XML_ELEMENT(TEXT, XML_CHANGE):
pContext = new XMLChangeImportContext(
rImport,
((nElement == XML_ELEMENT(TEXT, XML_CHANGE_END))
? XMLChangeImportContext::Element::END
: (nElement == XML_ELEMENT(TEXT, XML_CHANGE_START))
? XMLChangeImportContext::Element::START
: XMLChangeImportContext::Element::POINT), false); break;
case XML_ELEMENT(TEXT, XML_META):
pContext = new XMLMetaImportContext(rImport, nElement,
rHints, rIgnoreLeadingSpace ); break;
case XML_ELEMENT(TEXT, XML_META_FIELD):
pContext = new XMLMetaFieldImportContext(rImport, nElement,
rHints, rIgnoreLeadingSpace ); break;
case XML_ELEMENT(LO_EXT, XML_CONTENT_CONTROL):
pContext = new XMLContentControlContext(rImport, nElement, rHints, rIgnoreLeadingSpace); break;
default: // none of the above? then it's probably a text field!
pContext = XMLTextFieldImportContext::CreateTextFieldImportContext(
rImport, *rImport.GetTextImport(), nElement); // #108784# import draw elements (except control shapes in headers) if( pContext == nullptr &&
!( rImport.GetTextImport()->IsInHeaderFooter() &&
nElement == XML_ELEMENT(DRAW, XML_CONTROL ) ) )
{
Reference < XShapes > xShapes;
SvXMLShapeContext* pShapeContext = XMLShapeImportHelper::CreateGroupChildContext(
rImport, nElement, xAttrList, xShapes );
pContext = pShapeContext; // OD 2004-04-20 #i26791# - keep shape in a text frame hint to // adjust its anchor position, if it's at-character anchored
Reference < XTextRange > xAnchorPos =
rImport.GetTextImport()->GetCursor()->getStart();
rHints.push_back(
std::make_unique<XMLDrawHint_Impl>(pShapeContext, xAnchorPos));
} // Behind fields, shapes and any unknown content blanks aren't ignored
rIgnoreLeadingSpace = false;
}
if (!pContext)
XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); return pContext;
}
// if we have an id set for this paragraph, get a cursor for this // paragraph and register it with the given identifier // FIXME: this is just temporary, and should be removed when // EditEngine paragraphs implement XMetadatable! if (!m_sXmlId.isEmpty())
{
Reference < XTextCursor > xIdCursor( xTxtImport->GetText()->createTextCursorByRange( xStart ) ); if( xIdCursor.is() )
{
xIdCursor->gotoRange( xEnd, true );
GetImport().getInterfaceToIdentifierMapper().registerReference(
m_sXmlId, Reference<XInterface>( xIdCursor, UNO_QUERY ));
}
}
// insert a paragraph break
xTxtImport->InsertControlCharacter( ControlCharacter::APPEND_PARAGRAPH );
// create a cursor that select the whole last paragraph
Reference < XTextCursor > xAttrCursor; try {
xAttrCursor = xTxtImport->GetText()->createTextCursorByRange( xStart ); if( !xAttrCursor.is() ) return; // Robust (defective file)
} catch (const uno::Exception &) { // createTextCursorByRange() likes to throw runtime exception, even // though it just means 'we were unable to create the cursor' return;
}
xAttrCursor->gotoRange( xEnd, true );
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.