staticauto InsertFieldmark(SvXMLImport & rImport,
XMLTextImportHelper & rHelper, boolconst isFieldmarkSeparatorMissing) -> void
{
assert(rHelper.hasCurrentFieldCtx()); // was set up in StartElement()
// fdo#86795 check if it's actually a checkbox first autoconst [ name, type ] = rHelper.getCurrentFieldType();
OUString const fieldmarkTypeName = lcl_getFieldmarkName(type); if (fieldmarkTypeName == ODF_FORMCHECKBOX ||
fieldmarkTypeName == ODF_FORMDROPDOWN)
{ // sw can't handle checkbox with start+end
SAL_INFO("xmloff.text", "invalid fieldmark-start/fieldmark-end ignored"); return;
}
uno::Reference<text::XTextRange> const xStartRange(rHelper.getCurrentFieldStart());
uno::Reference<text::XTextCursor> const xCursor(
rHelper.GetText()->createTextCursorByRange(xStartRange));
uno::Reference<text::XTextRangeCompare> const xCompare(rHelper.GetText(), uno::UNO_QUERY); if (xCompare->compareRegionStarts(xStartRange, rHelper.GetCursorAsRange()) < 0)
{
SAL_WARN("xmloff.text", "invalid field mark positions");
assert(false);
}
xCursor->gotoRange(rHelper.GetCursorAsRange(), true);
// setup fieldmark...
Reference<text::XFormField> const xFormField(xContent, UNO_QUERY);
assert(xFormField.is()); try {
xFormField->setFieldType(fieldmarkTypeName);
} catch (uno::RuntimeException const&) { // tdf#140437 somehow old documents had the field code in the type // attribute instead of field:param
SAL_INFO("xmloff.text", "invalid fieldmark type, converting to param"); // add without checking: FieldParamImporter::Import() catches ElementExistException
rHelper.addFieldParam(ODF_CODE_PARAM, fieldmarkTypeName);
xFormField->setFieldType(ODF_UNHANDLED);
}
rHelper.setCurrentFieldParamsTo(xFormField); // move cursor after setFieldType as that may delete/re-insert
rHelper.GetCursor()->gotoRange(xContent->getAnchor()->getEnd(), false);
rHelper.GetCursor()->goLeft(1, false); // move before CH_TXT_ATR_FIELDEND // tdf#129520: AppendTextNode() ignores the content index! // plan B: insert a spurious paragraph break now and join // it in PopFieldmark()!
rHelper.GetText()->insertControlCharacter(rHelper.GetCursor(),
text::ControlCharacter::PARAGRAPH_BREAK, false);
rHelper.GetCursor()->goLeft(1, false); // back to previous paragraph
}
staticauto PopFieldmark(XMLTextImportHelper & rHelper) -> void
{ // can't verify name because it's not written as an attribute...
uno::Reference<text::XTextContent> const xField(rHelper.popFieldCtx(),
uno::UNO_QUERY); if (!xField.is()) return;
if (rHelper.GetText() == xField->getAnchor()->getText())
{ try
{ // skip CH_TXT_ATR_FIELDEND
rHelper.GetCursor()->goRight(1, true);
rHelper.GetCursor()->setString(OUString()); // undo AppendTextNode from InsertFieldmark
rHelper.GetCursor()->gotoRange(xField->getAnchor()->getEnd(), false);
} catch (uno::Exception const&)
{
assert(false); // must succeed
}
} else
{
SAL_INFO("xmloff.text", "fieldmark has invalid positions"); // could either dispose it or leave it to end at the end of the document?
xField->dispose();
}
}
switch (nTmp)
{ case TypeReference: // export point reference mark
CreateAndInsertMark(GetImport(),
u"com.sun.star.text.ReferenceMark"_ustr,
m_sBookmarkName,
m_rHelper.GetCursorAsRange()->getStart()); break;
// get old range, and construct
Reference<XTextRange> xStartRange;
std::shared_ptr< ::xmloff::ParsedRDFaAttributes >
xRDFaAttributes; if (m_rHelper.FindAndRemoveBookmarkStartRange(
m_sBookmarkName, xStartRange,
m_sXmlId, xRDFaAttributes))
{
Reference<XTextRange> xEndRange(
m_rHelper.GetCursorAsRange()->getStart());
// check if beginning and end are in same XText if (xStartRange.is() && xEndRange.is() && xStartRange->getText() == xEndRange->getText())
{ // create range for insertion
Reference<XTextCursor> xInsertionCursor =
m_rHelper.GetText()->createTextCursorByRange(
xEndRange); try {
xInsertionCursor->gotoRange(xStartRange, true);
} catch (uno::Exception&) {
TOOLS_WARN_EXCEPTION("xmloff.text", "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<XInterface> xContent; // insert reference
xContent = CreateAndInsertMark(GetImport(),
sAPI_bookmark,
m_sBookmarkName,
xInsertionCursor,
m_sXmlId); if (xRDFaAttributes)
{ const Reference<rdf::XMetadatable>
xMeta(xContent, UNO_QUERY);
GetImport().GetRDFaImportHelper().AddRDFa(
xMeta, xRDFaAttributes);
} const Reference<XPropertySet> xPropertySet(xContent, UNO_QUERY); if (xPropertySet.is())
{
xPropertySet->setPropertyValue(u"BookmarkHidden"_ustr, uno::Any(m_rHelper.getBookmarkHidden(m_sBookmarkName)));
xPropertySet->setPropertyValue(u"BookmarkCondition"_ustr, uno::Any(m_rHelper.getBookmarkCondition(m_sBookmarkName)));
} if (m_sBookmarkName.startsWith("__RefHeading__"))
{
assert(xContent.is());
m_rxCrossRefHeadingBookmark = std::move(xContent);
}
} // else: beginning/end in different XText -> ignore!
} // else: no start found -> ignore! break;
} case TypeFieldmarkStart:
{ break;
} case TypeFieldmarkSeparator:
{
InsertFieldmark(GetImport(), m_rHelper, false); break;
} case TypeFieldmarkEnd:
{ if (m_rHelper.hasCurrentFieldCtx() && !m_rHelper.hasCurrentFieldSeparator())
{ // backward compat for old files without separator
InsertFieldmark(GetImport(), m_rHelper, true);
}
PopFieldmark(m_rHelper); break;
} case TypeReferenceStart: case TypeReferenceEnd:
OSL_FAIL("reference start/end are handled in txtparai !"); break;
default:
OSL_FAIL("unknown mark type"); break;
}
}
if (xFactory.is())
{
xIfc = xFactory->createInstance(sServiceName);
if (!xIfc.is())
{
OSL_FAIL("CreateAndInsertMark: cannot create service?"); return nullptr;
}
// 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.isEmpty())
{
OSL_FAIL("name given, but XNamed not supported?"); return nullptr;
}
}
if (isFieldmarkSeparatorMissing)
{
uno::Reference<beans::XPropertySet> const xProps(xIfc, uno::UNO_QUERY_THROW);
xProps->setPropertyValue(u"PrivateSeparatorAtStart"_ustr, uno::Any(true));
}
// 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, true);
// xml:id for RDF metadata -- after insertion!
rImport.SetXmlId(xIfc, i_rXmlId);
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.