/* -*- 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 .
*/
using ::com::sun::star::beans::XPropertySet; using ::com::sun::star::beans::PropertyValue; using ::com::sun::star::beans::PropertyValues; using ::com::sun::star::container::XIndexReplace; using ::com::sun::star::container::XNameAccess; using ::com::sun::star::container::XNamed; using ::com::sun::star::lang::Locale;
// xml:id for RDF metadata
GetExport().AddAttributeXmlId(rSection);
// export index or regular section
Reference<XDocumentIndex> xIndex; if (GetIndex(rSection, xIndex))
{ if (xIndex.is())
{ // we are an index
ExportIndexStart(xIndex);
} else
{ // we are an index header
ExportIndexHeaderStart(rSection);
}
} else
{ // we are not an index
ExportRegularSectionStart(rSection);
}
}
}
// get section Properties
Reference<XPropertySet> xSectionPropSet(rSection, UNO_QUERY);
// then check if this section happens to be inside an index if (xSectionPropSet->getPropertySetInfo()->
hasPropertyByName(u"DocumentIndex"_ustr))
{
Any aAny = xSectionPropSet->getPropertyValue(u"DocumentIndex"_ustr);
Reference<XDocumentIndex> xDocumentIndex;
aAny >>= xDocumentIndex;
// OK, are we inside of an index if (xDocumentIndex.is())
{ // is the enclosing index identical with "our" section?
Reference<XPropertySet> xIndexPropSet(xDocumentIndex, UNO_QUERY);
aAny = xIndexPropSet->getPropertyValue(u"ContentSection"_ustr);
Reference<XTextSection> xEnclosingSection;
aAny >>= xEnclosingSection;
// if the enclosing section is "our" section, then we are an index! if (rSection == xEnclosingSection)
{
rIndex = std::move(xDocumentIndex);
bRet = true;
} // else: index header or regular section
// is the enclosing index identical with the header section?
aAny = xIndexPropSet->getPropertyValue(u"HeaderSection"_ustr); // now mis-named: contains header section
aAny >>= xEnclosingSection;
// if the enclosing section is "our" section, then we are an index! if (rSection == xEnclosingSection)
{
bRet = true;
} // else: regular section
} // else: we aren't even inside of an index
} // else: we don't even know what an index is.
return bRet;
}
void XMLSectionExport::ExportSectionEnd( const Reference<XTextSection> & rSection, bool bAutoStyles)
{ // no end section for styles if (bAutoStyles) return;
enum XMLTokenEnum eElement = XML_TOKEN_INVALID;
// export index or regular section end
Reference<XDocumentIndex> xIndex; if (GetIndex(rSection, xIndex))
{ if (xIndex.is())
{ // index end: close index body element
GetExport().EndElement( XML_NAMESPACE_TEXT, XML_INDEX_BODY, true );
GetExport().IgnorableWhitespace();
switch (MapSectionType(xIndex->getServiceName()))
{ case TEXT_SECTION_TYPE_TOC:
eElement = XML_TABLE_OF_CONTENT; break;
case TEXT_SECTION_TYPE_ILLUSTRATION:
eElement = XML_ILLUSTRATION_INDEX; break;
case TEXT_SECTION_TYPE_ALPHABETICAL:
eElement = XML_ALPHABETICAL_INDEX; break;
case TEXT_SECTION_TYPE_TABLE:
eElement = XML_TABLE_INDEX; break;
case TEXT_SECTION_TYPE_OBJECT:
eElement = XML_OBJECT_INDEX; break;
case TEXT_SECTION_TYPE_USER:
eElement = XML_USER_INDEX; break;
case TEXT_SECTION_TYPE_BIBLIOGRAPHY:
eElement = XML_BIBLIOGRAPHY; break;
// protect + protection key
aAny = xPropSet->getPropertyValue(u"IsProtected"_ustr); if (*o3tl::doAccess<bool>(aAny))
{
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE);
}
Sequence<sal_Int8> aPassword;
xPropSet->getPropertyValue(u"ProtectionKey"_ustr) >>= aPassword; if (aPassword.hasElements())
{
OUStringBuffer aBuffer;
::comphelper::Base64::encode(aBuffer, aPassword); // in ODF 1.0/1.1 the algorithm was left unspecified so we can write anything
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTION_KEY,
aBuffer.makeStringAndClear()); if (aPassword.getLength() == 32 && GetExport().getSaneDefaultVersion() >= SvtSaveOptions::ODFSVER_012)
{ // attribute exists in ODF 1.2 or later; default is SHA1 so no need to write that
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM, // write the URL from ODF 1.2, not the W3C one
u"http://www.w3.org/2000/09/xmldsig#sha256"_ustr);
}
}
// export element
GetExport().IgnorableWhitespace();
GetExport().StartElement( XML_NAMESPACE_TEXT, XML_SECTION, true );
// data source // unfortunately, we have to test all relevant strings for non-zero length
aAny = xPropSet->getPropertyValue(u"FileLink"_ustr);
SectionFileLink aFileLink;
aAny >>= aFileLink;
aAny = xPropSet->getPropertyValue(u"IsAutomaticUpdate"_ustr); if (*o3tl::doAccess<bool>(aAny))
{
GetExport().AddAttribute(XML_NAMESPACE_OFFICE,
XML_AUTOMATIC_UPDATE, XML_TRUE);
}
SvXMLElementExport aElem(GetExport(),
XML_NAMESPACE_OFFICE,
XML_DDE_SOURCE, true, true);
} // else: no DDE data source
} // else: no DDE on this system
}
}
// scope for index source element
{ // export common attributes for illustration and table indices
ExportTableAndIllustrationIndexSourceAttributes(rPropertySet);
// scope for index source element
{ // export common attributes for illustration and table indices
ExportTableAndIllustrationIndexSourceAttributes(rPropertySet);
// index name
OUString sIndexName;
rPropertySet->getPropertyValue(u"Name"_ustr) >>= sIndexName; if ( !sIndexName.isEmpty() )
{
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, sIndexName);
}
// index Element start
GetExport().IgnorableWhitespace();
GetExport().StartElement( XML_NAMESPACE_TEXT, eElement, false );
}
const XMLTokenEnum aTypeSourceElementNameMap[] =
{
XML_TABLE_OF_CONTENT_SOURCE, // TOC
XML_TABLE_INDEX_SOURCE, // table index
XML_ILLUSTRATION_INDEX_SOURCE, // illustration index
XML_OBJECT_INDEX_SOURCE, // object index
XML_USER_INDEX_SOURCE, // user index
XML_ALPHABETICAL_INDEX_SOURCE, // alphabetical index
XML_BIBLIOGRAPHY_SOURCE // bibliography
};
void XMLSectionExport::ExportBaseIndexSource(
SectionTypeEnum eType, const Reference<XPropertySet> & rPropertySet)
{ // check type
OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type");
OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type");
Any aAny;
// common attributes; not supported by bibliography if (eType != TEXT_SECTION_TYPE_BIBLIOGRAPHY)
{ // document or chapter index?
aAny = rPropertySet->getPropertyValue(u"CreateFromChapter"_ustr); if (*o3tl::doAccess<bool>(aAny))
{
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
XML_INDEX_SCOPE, XML_CHAPTER);
}
// tab-stops relative to margin?
aAny = rPropertySet->getPropertyValue(u"IsRelativeTabstops"_ustr); if (! *o3tl::doAccess<bool>(aAny))
{
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
XML_RELATIVE_TAB_STOP_POSITION,
XML_FALSE);
}
}
// the index source element (all indices)
SvXMLElementExport aElem(GetExport(),
XML_NAMESPACE_TEXT,
GetXMLToken(
aTypeSourceElementNameMap[
eType - TEXT_SECTION_TYPE_TOC]), true, true);
// scope for title template (all indices)
{ // header style name
aAny = rPropertySet->getPropertyValue(u"ParaStyleHeading"_ustr);
OUString sStyleName;
aAny >>= sStyleName;
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
XML_STYLE_NAME,
GetExport().EncodeStyleName( sStyleName ));
// title template
SvXMLElementExport aHeaderTemplate(GetExport(),
XML_NAMESPACE_TEXT,
XML_INDEX_TITLE_TEMPLATE, true, false);
// title as element content
aAny = rPropertySet->getPropertyValue(u"Title"_ustr);
OUString sTitleString;
aAny >>= sTitleString;
GetExport().Characters(sTitleString);
}
// iterate over level formats; // skip element 0 (empty template for title)
sal_Int32 nLevelCount = xLevelTemplates->getCount(); for(sal_Int32 i = 1; i<nLevelCount; i++)
{ // get sequence
Sequence<PropertyValues> aTemplateSequence;
aAny = xLevelTemplates->getByIndex(i);
aAny >>= aTemplateSequence;
// export the sequence (abort export if an error occurred; #91214#) bool bResult =
ExportIndexTemplate(eType, i, rPropertySet, aTemplateSequence); if ( !bResult ) break;
}
// only TOC and user index: // styles from which to build the index (LevelParagraphStyles) if ( (TEXT_SECTION_TYPE_TOC == eType) ||
(TEXT_SECTION_TYPE_USER == eType) )
{
aAny = rPropertySet->getPropertyValue(u"LevelParagraphStyles"_ustr);
Reference<XIndexReplace> xLevelParagraphStyles;
aAny >>= xLevelParagraphStyles;
ExportLevelParagraphStyles(xLevelParagraphStyles);
} elseif (TEXT_SECTION_TYPE_ILLUSTRATION == eType
|| TEXT_SECTION_TYPE_OBJECT == eType
|| TEXT_SECTION_TYPE_TABLE == eType)
{
Any const any(rPropertySet->getPropertyValue(u"CreateFromParagraphStyle"_ustr)); if (any.hasValue() &&
(rExport.getSaneDefaultVersion() & SvtSaveOptions::ODFSVER_EXTENDED))
{
OUString const styleName(any.get<OUString>());
GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME,
GetExport().EncodeStyleName(styleName));
if ( (eType >= TEXT_SECTION_TYPE_TOC) &&
(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY) &&
(nOutlineLevel >= 0) )
{ // get level name and level attribute name from aLevelNameMap; const XMLTokenEnum eLevelAttrName(
aTypeLevelAttrMap[eType-TEXT_SECTION_TYPE_TOC]); const XMLTokenEnum eLevelName(
aTypeLevelNameMap[eType-TEXT_SECTION_TYPE_TOC][nOutlineLevel]);
// #92124#: some old documents may be broken, then they have // too many template levels; we need to recognize this and // export only as many as is legal for the respective index // type. To do this, we simply return an error flag, which // will then abort further template level exports.
OSL_ENSURE(XML_TOKEN_INVALID != eLevelName, "can't find level name"); if ( XML_TOKEN_INVALID == eLevelName )
{ // output level not found? Then end of templates! #91214# returnfalse;
}
// output level name if ((XML_TOKEN_INVALID != eLevelName) && (XML_TOKEN_INVALID != eLevelAttrName))
{
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
GetXMLToken(eLevelAttrName),
GetXMLToken(eLevelName));
}
//i90246, the ODF version being written to is: const SvtSaveOptions::ODFSaneDefaultVersion aODFVersion = rExport.getSaneDefaultVersion(); //the above version cannot be used for old OOo (OOo 1.0) formats!
// token type enum TemplateTypeEnum nTokenType = TOK_TTYPE_INVALID;
for(constauto& rValue : rValues)
{
TemplateParamEnum nToken; if ( SvXMLUnitConverter::convertEnum( nToken, rValue.Name,
aTemplateParamMap ) )
{ // Only use direct and default values. // Wrong. no property states, so ignore. // if ( (beans::PropertyState_DIRECT_VALUE == rValues[i].State) || // (beans::PropertyState_DEFAULT_VALUE == rValues[i].State) )
//--->i90246 //check the ODF version being exported if (aODFVersion == SvtSaveOptions::ODFSVER_011
|| aODFVersion == SvtSaveOptions::ODFSVER_010)
{
bLevelOK = false; if (TOK_TTYPE_CHAPTER_INFO == nTokenType)
{ //if we are emitting for ODF 1.1 or 1.0, this information can be used for alphabetical index only //it's not permitted in other indexes if (eType != TEXT_SECTION_TYPE_ALPHABETICAL)
{
eElement = XML_TOKEN_INVALID; //not permitted, invalidate the element
} else//maps format for 1.1 & 1.0
{ // a few word here: OOo up to 2.4 uses the field chapter info in Alphabetical index // in a way different from the ODF 1.1/1.0 specification:
// ODF1.1/1.0 OOo display in chapter info ODF1.2 // (used in alphabetical index only
// number chapter number without pre/postfix plain-number // number-and-name chapter number without pre/postfix plus title plain-number-and-name
// with issue i89791 the reading of ODF 1.1 and 1.0 was corrected // this one corrects the writing back from ODF 1.2 to ODF 1.1/1.0 // unfortunately if there is another application which interprets correctly ODF1.1/1.0, // the resulting alphabetical index will be rendered wrong by OOo 2.4 version
switch( nChapterFormat )
{ case ChapterFormat::DIGIT:
nChapterFormat = ChapterFormat::NUMBER; break; case ChapterFormat::NO_PREFIX_SUFFIX:
nChapterFormat = ChapterFormat::NAME_NUMBER; break;
}
}
} elseif (TOK_TTYPE_ENTRY_NUMBER == nTokenType)
{ //in case of ODF 1.1 or 1.0 the only allowed number format is "number" //so, force it... // The only expected 'foreign' nChapterFormat is // ' ChapterFormat::DIGIT', forced to 'none, since the // 'value allowed in ODF 1.1 and 1.0 is 'number' the default // this can be obtained by simply disabling the chapter format
bChapterFormatOK = false;
}
}
// ... and write Element if (eElement == XML_TOKEN_INVALID) return;
// character style (for most templates) if (bCharStyleOK)
{ switch (nTokenType)
{ case TOK_TTYPE_ENTRY_TEXT: case TOK_TTYPE_TEXT: case TOK_TTYPE_PAGE_NUMBER: case TOK_TTYPE_ENTRY_NUMBER: case TOK_TTYPE_HYPERLINK_START: case TOK_TTYPE_HYPERLINK_END: case TOK_TTYPE_BIBLIOGRAPHY: case TOK_TTYPE_CHAPTER_INFO: case TOK_TTYPE_TAB_STOP:
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
XML_STYLE_NAME,
GetExport().EncodeStyleName( sCharStyle) ); break; default:
; // nothing: no character style break;
}
}
// tab properties if (TOK_TTYPE_TAB_STOP == nTokenType)
{ // tab type
GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_TYPE,
bRightAligned ? XML_RIGHT : XML_LEFT);
if (bTabPositionOK && (! bRightAligned))
{ // position for left tabs (convert to measure)
OUStringBuffer sBuf;
GetExport().GetMM100UnitConverter().convertMeasureToXML(sBuf,
nTabPosition);
GetExport().AddAttribute(XML_NAMESPACE_STYLE,
XML_POSITION,
sBuf.makeStringAndClear());
}
// fill char ("leader char") if (bFillCharOK && !sFillChar.isEmpty())
{
GetExport().AddAttribute(XML_NAMESPACE_STYLE,
XML_LEADER_CHAR, sFillChar);
}
// export only if at least one style is contained if (aStyleNames.hasElements())
{ // level attribute; we count 1..10; API 0..9
sal_Int32 nLevelPlusOne = nLevel + 1;
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
XML_OUTLINE_LEVEL,
OUString::number(nLevelPlusOne));
// source styles element
SvXMLElementExport aParaStyles(GetExport(),
XML_NAMESPACE_TEXT,
XML_INDEX_SOURCE_STYLES, true, true);
// iterate over styles in this level for (constauto& rStyleName : aStyleNames)
{ // stylename attribute
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
XML_STYLE_NAME,
GetExport().EncodeStyleName(rStyleName) );
Any aAny = rPropSet->getPropertyValue(sPropertyName); bool bTmp = *o3tl::doAccess<bool>(aAny);
// value = value ^ bInvert // omit if value == default if ( (bTmp != bInvert) != bDefault )
{ // export non-default value (since default is omitted)
GetExport().AddAttribute(XML_NAMESPACE_TEXT,
eAttributeName,
bDefault ? XML_FALSE : XML_TRUE);
}
}
void XMLSectionExport::ExportBibliographyConfiguration(SvXMLExport& rExport)
{ // first: get field master (via text field supplier)
Reference<XTextFieldsSupplier> xTextFieldsSupp( rExport.GetModel(),
UNO_QUERY ); if ( !xTextFieldsSupp.is() ) return;
// get bibliography field master
Reference<XNameAccess> xMasters =
xTextFieldsSupp->getTextFieldMasters(); if ( !xMasters->hasByName(sFieldMaster_Bibliography) ) return;
Any aAny =
xMasters->getByName(sFieldMaster_Bibliography);
Reference<XPropertySet> xPropSet;
aAny >>= xPropSet;
OSL_ENSURE( xPropSet.is(), "field master must have XPropSet" );
// a section is mute if // 1) it exists // 2) the SaveLinkedSections flag (at the export) is false // 3) the IsGlobalDocumentSection property is true // 4) it is not an Index
if ( (!rExport.IsSaveLinkedSections()) && rSection.is() )
{ // walk the section chain and set bRet if any is linked for(Reference<XTextSection> aSection(rSection);
aSection.is();
aSection = aSection->getParentSection())
{ // check if it is a global document section (linked or index)
Reference<XPropertySet> xPropSet(aSection, UNO_QUERY); if (xPropSet.is())
{
Any aAny = xPropSet->getPropertyValue(u"IsGlobalDocumentSection"_ustr);
if ( *o3tl::doAccess<bool>(aAny) )
{
Reference<XDocumentIndex> xIndex; if (! GetIndex(rSection, xIndex))
{
bRet = true;
// early out if result is known break;
}
}
} // section has no properties: ignore
}
} // else: no section, or always save sections: default (false)
Reference<XPropertySet> xPropSet(rContent, UNO_QUERY); if (xPropSet.is())
{ if (xPropSet->getPropertySetInfo()->hasPropertyByName(u"TextSection"_ustr))
{
Any aAny = xPropSet->getPropertyValue(u"TextSection"_ustr);
Reference<XTextSection> xSection;
aAny >>= xSection;
// now walk chain of text sections (if we have one) if (xSection.is())
{ do
{
bRet = (rEnclosingSection == xSection);
xSection = xSection->getParentSection();
} while (!bRet && xSection.is());
} else
bRet = false; // no section -> can't be inside
} // else: no TextSection property -> return default
} // else: no XPropertySet -> return default
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.