/* -*- 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 . */ #include "XMLSectionExport.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::text; using namespace ::com::sun::star::uno; using namespace ::std; using namespace ::xmloff::token; 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; XMLSectionExport::XMLSectionExport( SvXMLExport& rExp, XMLTextParagraphExport& rParaExp) : rExport(rExp) , rParaExport(rParaExp) , bHeadingDummiesExported( false ) { } void XMLSectionExport::ExportSectionStart( const Reference & rSection, bool bAutoStyles) { Reference xPropertySet(rSection, UNO_QUERY); // always export section (auto) style if (bAutoStyles) { // get PropertySet and add section style GetParaExport().Add( XmlStyleFamily::TEXT_SECTION, xPropertySet ); } else { // always export section style GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetParaExport().Find( XmlStyleFamily::TEXT_SECTION, xPropertySet, "" ) ); // xml:id for RDF metadata GetExport().AddAttributeXmlId(rSection); // export index or regular section Reference 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); } } } bool XMLSectionExport::GetIndex( const Reference & rSection, Reference & rIndex) { // first, reset result bool bRet = false; rIndex = nullptr; // get section Properties Reference xSectionPropSet(rSection, UNO_QUERY); // then check if this section happens to be inside an index if (xSectionPropSet->getPropertySetInfo()-> hasPropertyByName("DocumentIndex")) { Any aAny = xSectionPropSet->getPropertyValue("DocumentIndex"); Reference xDocumentIndex; aAny >>= xDocumentIndex; // OK, are we inside of an index if (xDocumentIndex.is()) { // is the enclosing index identical with "our" section? Reference xIndexPropSet(xDocumentIndex, UNO_QUERY); aAny = xIndexPropSet->getPropertyValue("ContentSection"); Reference xEnclosingSection; aAny >>= xEnclosingSection; // if the enclosing section is "our" section, then we are an index! if (rSection == xEnclosingSection) { rIndex = xDocumentIndex; bRet = true; } // else: index header or regular section // is the enclosing index identical with the header section? aAny = xIndexPropSet->getPropertyValue("HeaderSection"); // 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 & rSection, bool bAutoStyles) { // no end section for styles if (bAutoStyles) return; enum XMLTokenEnum eElement = XML_TOKEN_INVALID; // export index or regular section end Reference 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; default: OSL_FAIL("unknown index type"); // default: skip index! break; } } else { eElement = XML_INDEX_TITLE; } } else { eElement = XML_SECTION; } if (XML_TOKEN_INVALID != eElement) { // any old attributes? GetExport().CheckAttrList(); // element surrounded by whitespace GetExport().EndElement( XML_NAMESPACE_TEXT, eElement, true); GetExport().IgnorableWhitespace(); } else { OSL_FAIL("Need element name!"); } // else: autostyles -> ignore } void XMLSectionExport::ExportIndexStart( const Reference & rIndex) { // get PropertySet Reference xPropertySet(rIndex, UNO_QUERY); switch (MapSectionType(rIndex->getServiceName())) { case TEXT_SECTION_TYPE_TOC: ExportTableOfContentStart(xPropertySet); break; case TEXT_SECTION_TYPE_ILLUSTRATION: ExportIllustrationIndexStart(xPropertySet); break; case TEXT_SECTION_TYPE_ALPHABETICAL: ExportAlphabeticalIndexStart(xPropertySet); break; case TEXT_SECTION_TYPE_TABLE: ExportTableIndexStart(xPropertySet); break; case TEXT_SECTION_TYPE_OBJECT: ExportObjectIndexStart(xPropertySet); break; case TEXT_SECTION_TYPE_USER: ExportUserIndexStart(xPropertySet); break; case TEXT_SECTION_TYPE_BIBLIOGRAPHY: ExportBibliographyStart(xPropertySet); break; default: // skip index OSL_FAIL("unknown index type"); break; } } void XMLSectionExport::ExportIndexHeaderStart( const Reference & rSection) { // export name, dammit! Reference xName(rSection, UNO_QUERY); GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName()); // format already handled -> export only start element GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_TITLE, true ); GetExport().IgnorableWhitespace(); } SvXMLEnumStringMapEntry const aIndexTypeMap[] = { ENUM_STRING_MAP_ENTRY( "com.sun.star.text.ContentIndex", TEXT_SECTION_TYPE_TOC ), ENUM_STRING_MAP_ENTRY( "com.sun.star.text.DocumentIndex", TEXT_SECTION_TYPE_ALPHABETICAL ), ENUM_STRING_MAP_ENTRY( "com.sun.star.text.TableIndex", TEXT_SECTION_TYPE_TABLE ), ENUM_STRING_MAP_ENTRY( "com.sun.star.text.ObjectIndex", TEXT_SECTION_TYPE_OBJECT ), ENUM_STRING_MAP_ENTRY( "com.sun.star.text.Bibliography", TEXT_SECTION_TYPE_BIBLIOGRAPHY ), ENUM_STRING_MAP_ENTRY( "com.sun.star.text.UserIndex", TEXT_SECTION_TYPE_USER ), ENUM_STRING_MAP_ENTRY( "com.sun.star.text.IllustrationsIndex", TEXT_SECTION_TYPE_ILLUSTRATION ), { nullptr, 0, SectionTypeEnum(0) } }; enum SectionTypeEnum XMLSectionExport::MapSectionType( std::u16string_view rServiceName) { enum SectionTypeEnum eType = TEXT_SECTION_TYPE_UNKNOWN; SvXMLUnitConverter::convertEnum(eType, rServiceName, aIndexTypeMap); // TODO: index header section types, etc. return eType; } void XMLSectionExport::ExportRegularSectionStart( const Reference & rSection) { // style name already handled in ExportSectionStart(...) Reference xName(rSection, UNO_QUERY); GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_NAME, xName->getName()); // get XPropertySet for other values Reference xPropSet(rSection, UNO_QUERY); // condition and display Any aAny = xPropSet->getPropertyValue("Condition"); OUString sCond; aAny >>= sCond; enum XMLTokenEnum eDisplay = XML_TOKEN_INVALID; if (!sCond.isEmpty()) { OUString sQValue = GetExport().GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_OOOW, sCond, false ); GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_CONDITION, sQValue); eDisplay = XML_CONDITION; // #97450# store hidden-status (of conditional sections only) aAny = xPropSet->getPropertyValue("IsCurrentlyVisible"); if (! *o3tl::doAccess(aAny)) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_IS_HIDDEN, XML_TRUE); } } else { eDisplay = XML_NONE; } aAny = xPropSet->getPropertyValue("IsVisible"); if (! *o3tl::doAccess(aAny)) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_DISPLAY, eDisplay); } // protect + protection key aAny = xPropSet->getPropertyValue("IsProtected"); if (*o3tl::doAccess(aAny)) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE); } Sequence aPassword; xPropSet->getPropertyValue("ProtectionKey") >>= 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 "http://www.w3.org/2000/09/xmldsig#sha256"); } } // 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("FileLink"); SectionFileLink aFileLink; aAny >>= aFileLink; aAny = xPropSet->getPropertyValue("LinkRegion"); OUString sRegionName; aAny >>= sRegionName; if ( !aFileLink.FileURL.isEmpty() || !aFileLink.FilterName.isEmpty() || !sRegionName.isEmpty()) { if (!aFileLink.FileURL.isEmpty()) { GetExport().AddAttribute(XML_NAMESPACE_XLINK, XML_HREF, GetExport().GetRelativeReference( aFileLink.FileURL) ); } if (!aFileLink.FilterName.isEmpty()) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_FILTER_NAME, aFileLink.FilterName); } if (!sRegionName.isEmpty()) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_SECTION_NAME, sRegionName); } SvXMLElementExport aElem(GetExport(), XML_NAMESPACE_TEXT, XML_SECTION_SOURCE, true, true); } else { // check for DDE first if (xPropSet->getPropertySetInfo()->hasPropertyByName("DDECommandFile")) { // data source DDE // unfortunately, we have to test all relevant strings for // non-zero length aAny = xPropSet->getPropertyValue("DDECommandFile"); OUString sApplication; aAny >>= sApplication; aAny = xPropSet->getPropertyValue("DDECommandType"); OUString sTopic; aAny >>= sTopic; aAny = xPropSet->getPropertyValue("DDECommandElement"); OUString sItem; aAny >>= sItem; if ( !sApplication.isEmpty() || !sTopic.isEmpty() || !sItem.isEmpty()) { GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_APPLICATION, sApplication); GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_TOPIC, sTopic); GetExport().AddAttribute(XML_NAMESPACE_OFFICE, XML_DDE_ITEM, sItem); aAny = xPropSet->getPropertyValue("IsAutomaticUpdate"); if (*o3tl::doAccess(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 } } void XMLSectionExport::ExportTableOfContentStart( const Reference & rPropertySet) { // export TOC element start ExportBaseIndexStart(XML_TABLE_OF_CONTENT, rPropertySet); // scope for table-of-content-source element { // TOC specific index source attributes: // outline-level: 1..10 sal_Int16 nLevel = sal_Int16(); if( rPropertySet->getPropertyValue("Level") >>= nLevel ) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL, OUString::number(nLevel)); } // use outline level ExportBoolean(rPropertySet, "CreateFromOutline", XML_USE_OUTLINE_LEVEL, true); // use index marks ExportBoolean(rPropertySet, "CreateFromMarks", XML_USE_INDEX_MARKS, true); // use level styles ExportBoolean(rPropertySet, "CreateFromLevelParagraphStyles", XML_USE_INDEX_SOURCE_STYLES, false); ExportBaseIndexSource(TEXT_SECTION_TYPE_TOC, rPropertySet); } ExportBaseIndexBody(TEXT_SECTION_TYPE_TOC, rPropertySet); } void XMLSectionExport::ExportObjectIndexStart( const Reference & rPropertySet) { // export index start ExportBaseIndexStart(XML_OBJECT_INDEX, rPropertySet); // scope for index source element { ExportBoolean(rPropertySet, "CreateFromOtherEmbeddedObjects", XML_USE_OTHER_OBJECTS, false); ExportBoolean(rPropertySet, "CreateFromStarCalc", XML_USE_SPREADSHEET_OBJECTS, false); ExportBoolean(rPropertySet, "CreateFromStarChart", XML_USE_CHART_OBJECTS, false); ExportBoolean(rPropertySet, "CreateFromStarDraw", XML_USE_DRAW_OBJECTS, false); ExportBoolean(rPropertySet, "CreateFromStarMath", XML_USE_MATH_OBJECTS, false); ExportBaseIndexSource(TEXT_SECTION_TYPE_OBJECT, rPropertySet); } ExportBaseIndexBody(TEXT_SECTION_TYPE_OBJECT, rPropertySet); } void XMLSectionExport::ExportIllustrationIndexStart( const Reference & rPropertySet) { // export index start ExportBaseIndexStart(XML_ILLUSTRATION_INDEX, rPropertySet); // scope for index source element { // export common attributes for illustration and table indices ExportTableAndIllustrationIndexSourceAttributes(rPropertySet); ExportBaseIndexSource(TEXT_SECTION_TYPE_ILLUSTRATION, rPropertySet); } ExportBaseIndexBody(TEXT_SECTION_TYPE_ILLUSTRATION, rPropertySet); } void XMLSectionExport::ExportTableIndexStart( const Reference & rPropertySet) { // export index start ExportBaseIndexStart(XML_TABLE_INDEX, rPropertySet); // scope for index source element { // export common attributes for illustration and table indices ExportTableAndIllustrationIndexSourceAttributes(rPropertySet); ExportBaseIndexSource(TEXT_SECTION_TYPE_TABLE, rPropertySet); } ExportBaseIndexBody(TEXT_SECTION_TYPE_TABLE, rPropertySet); } void XMLSectionExport::ExportAlphabeticalIndexStart( const Reference & rPropertySet) { // export TOC element start ExportBaseIndexStart(XML_ALPHABETICAL_INDEX, rPropertySet); // scope for table-of-content-source element { // style name (if present) Any aAny = rPropertySet->getPropertyValue("MainEntryCharacterStyleName"); OUString sStyleName; aAny >>= sStyleName; if (!sStyleName.isEmpty()) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_MAIN_ENTRY_STYLE_NAME, GetExport().EncodeStyleName( sStyleName )); } // other (boolean) attributes ExportBoolean(rPropertySet, "IsCaseSensitive", XML_IGNORE_CASE, false, true); ExportBoolean(rPropertySet, "UseAlphabeticalSeparators", XML_ALPHABETICAL_SEPARATORS, false); ExportBoolean(rPropertySet, "UseCombinedEntries", XML_COMBINE_ENTRIES, true); ExportBoolean(rPropertySet, "UseDash", XML_COMBINE_ENTRIES_WITH_DASH, false); ExportBoolean(rPropertySet, "UseKeyAsEntry", XML_USE_KEYS_AS_ENTRIES, false); ExportBoolean(rPropertySet, "UsePP", XML_COMBINE_ENTRIES_WITH_PP, true); ExportBoolean(rPropertySet, "UseUpperCase", XML_CAPITALIZE_ENTRIES, false); ExportBoolean(rPropertySet, "IsCommaSeparated", XML_COMMA_SEPARATED, false); // sort algorithm aAny = rPropertySet->getPropertyValue("SortAlgorithm"); OUString sAlgorithm; aAny >>= sAlgorithm; if (!sAlgorithm.isEmpty()) { GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_SORT_ALGORITHM, sAlgorithm ); } // locale aAny = rPropertySet->getPropertyValue("Locale"); Locale aLocale; aAny >>= aLocale; GetExport().AddLanguageTagAttributes( XML_NAMESPACE_FO, XML_NAMESPACE_STYLE, aLocale, true); ExportBaseIndexSource(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet); } ExportBaseIndexBody(TEXT_SECTION_TYPE_ALPHABETICAL, rPropertySet); } void XMLSectionExport::ExportUserIndexStart( const Reference & rPropertySet) { // export TOC element start ExportBaseIndexStart(XML_USER_INDEX, rPropertySet); // scope for table-of-content-source element { // bool attributes ExportBoolean(rPropertySet, "CreateFromEmbeddedObjects", XML_USE_OBJECTS, false); ExportBoolean(rPropertySet, "CreateFromGraphicObjects", XML_USE_GRAPHICS, false); ExportBoolean(rPropertySet, "CreateFromMarks", XML_USE_INDEX_MARKS, false); ExportBoolean(rPropertySet, "CreateFromTables", XML_USE_TABLES, false); ExportBoolean(rPropertySet, "CreateFromTextFrames", XML_USE_FLOATING_FRAMES, false); ExportBoolean(rPropertySet, "UseLevelFromSource", XML_COPY_OUTLINE_LEVELS, false); ExportBoolean(rPropertySet, "CreateFromLevelParagraphStyles", XML_USE_INDEX_SOURCE_STYLES, false); Any aAny = rPropertySet->getPropertyValue( "UserIndexName" ); OUString sIndexName; aAny >>= sIndexName; GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_INDEX_NAME, sIndexName); ExportBaseIndexSource(TEXT_SECTION_TYPE_USER, rPropertySet); } ExportBaseIndexBody(TEXT_SECTION_TYPE_USER, rPropertySet); } void XMLSectionExport::ExportBibliographyStart( const Reference & rPropertySet) { // export TOC element start ExportBaseIndexStart(XML_BIBLIOGRAPHY, rPropertySet); // scope for table-of-content-source element { // No attributes. Fine. ExportBaseIndexSource(TEXT_SECTION_TYPE_BIBLIOGRAPHY, rPropertySet); } ExportBaseIndexBody(TEXT_SECTION_TYPE_BIBLIOGRAPHY, rPropertySet); } void XMLSectionExport::ExportBaseIndexStart( XMLTokenEnum eElement, const Reference & rPropertySet) { // protect + protection key Any aAny = rPropertySet->getPropertyValue("IsProtected"); if (*o3tl::doAccess(aAny)) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_PROTECTED, XML_TRUE); } // index name OUString sIndexName; rPropertySet->getPropertyValue("Name") >>= 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 & 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("CreateFromChapter"); if (*o3tl::doAccess(aAny)) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_INDEX_SCOPE, XML_CHAPTER); } // tab-stops relative to margin? aAny = rPropertySet->getPropertyValue("IsRelativeTabstops"); if (! *o3tl::doAccess(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("ParaStyleHeading"); 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("Title"); OUString sTitleString; aAny >>= sTitleString; GetExport().Characters(sTitleString); } // export level templates (all indices) aAny = rPropertySet->getPropertyValue("LevelFormat"); Reference xLevelTemplates; aAny >>= xLevelTemplates; // iterate over level formats; // skip element 0 (empty template for title) sal_Int32 nLevelCount = xLevelTemplates->getCount(); for(sal_Int32 i = 1; i 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("LevelParagraphStyles"); Reference xLevelParagraphStyles; aAny >>= xLevelParagraphStyles; ExportLevelParagraphStyles(xLevelParagraphStyles); } } void XMLSectionExport::ExportBaseIndexBody( SectionTypeEnum eType, const Reference &) { // type not used; checked anyway. OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type"); OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type"); // export start only // any old attributes? GetExport().CheckAttrList(); // start surrounded by whitespace GetExport().IgnorableWhitespace(); GetExport().StartElement( XML_NAMESPACE_TEXT, XML_INDEX_BODY, true ); } void XMLSectionExport::ExportTableAndIllustrationIndexSourceAttributes( const Reference & rPropertySet) { // use caption Any aAny = rPropertySet->getPropertyValue("CreateFromLabels"); if (! *o3tl::doAccess(aAny)) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_USE_CAPTION, XML_FALSE); } // sequence name aAny = rPropertySet->getPropertyValue("LabelCategory"); OUString sSequenceName; aAny >>= sSequenceName; GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_CAPTION_SEQUENCE_NAME, sSequenceName); // caption format aAny = rPropertySet->getPropertyValue("LabelDisplayType"); sal_Int16 nType = 0; aAny >>= nType; GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_CAPTION_SEQUENCE_FORMAT, XMLTextFieldExport::MapReferenceType(nType)); } // map index of LevelFormats to attribute value; // level 0 is always the header const XMLTokenEnum aLevelNameTOCMap[] = { XML_TOKEN_INVALID, XML_1, XML_2, XML_3, XML_4, XML_5, XML_6, XML_7, XML_8, XML_9, XML_10, XML_TOKEN_INVALID }; const XMLTokenEnum aLevelNameTableMap[] = { XML_TOKEN_INVALID, XML__EMPTY, XML_TOKEN_INVALID }; const XMLTokenEnum aLevelNameAlphaMap[] = { XML_TOKEN_INVALID, XML_SEPARATOR, XML_1, XML_2, XML_3, XML_TOKEN_INVALID }; const XMLTokenEnum aLevelNameBibliographyMap[] = { XML_TOKEN_INVALID, XML_ARTICLE, XML_BOOK, XML_BOOKLET, XML_CONFERENCE, XML_CUSTOM1, XML_CUSTOM2, XML_CUSTOM3, XML_CUSTOM4, XML_CUSTOM5, XML_EMAIL, XML_INBOOK, XML_INCOLLECTION, XML_INPROCEEDINGS, XML_JOURNAL, XML_MANUAL, XML_MASTERSTHESIS, XML_MISC, XML_PHDTHESIS, XML_PROCEEDINGS, XML_TECHREPORT, XML_UNPUBLISHED, XML_WWW, XML_TOKEN_INVALID }; static const XMLTokenEnum* aTypeLevelNameMap[] = { aLevelNameTOCMap, // TOC aLevelNameTableMap, // table index aLevelNameTableMap, // illustration index aLevelNameTableMap, // object index aLevelNameTOCMap, // user index aLevelNameAlphaMap, // alphabetical index aLevelNameBibliographyMap // bibliography }; static const char* aLevelStylePropNameTOCMap[] = { nullptr, "ParaStyleLevel1", "ParaStyleLevel2", "ParaStyleLevel3", "ParaStyleLevel4", "ParaStyleLevel5", "ParaStyleLevel6", "ParaStyleLevel7", "ParaStyleLevel8", "ParaStyleLevel9", "ParaStyleLevel10", nullptr }; static const char* aLevelStylePropNameTableMap[] = { nullptr, "ParaStyleLevel1", nullptr }; static const char* aLevelStylePropNameAlphaMap[] = { nullptr, "ParaStyleSeparator", "ParaStyleLevel1", "ParaStyleLevel2", "ParaStyleLevel3", nullptr }; static const char* aLevelStylePropNameBibliographyMap[] = // TODO: replace with real property names, when available { nullptr, "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", "ParaStyleLevel1", nullptr }; static const char** aTypeLevelStylePropNameMap[] = { aLevelStylePropNameTOCMap, // TOC aLevelStylePropNameTableMap, // table index aLevelStylePropNameTableMap, // illustration index aLevelStylePropNameTableMap, // object index aLevelStylePropNameTOCMap, // user index aLevelStylePropNameAlphaMap, // alphabetical index aLevelStylePropNameBibliographyMap // bibliography }; const XMLTokenEnum aTypeLevelAttrMap[] = { XML_OUTLINE_LEVEL, // TOC XML_TOKEN_INVALID, // table index XML_TOKEN_INVALID, // illustration index XML_TOKEN_INVALID, // object index XML_OUTLINE_LEVEL, // user index XML_OUTLINE_LEVEL, // alphabetical index XML_BIBLIOGRAPHY_TYPE // bibliography }; const XMLTokenEnum aTypeElementNameMap[] = { XML_TABLE_OF_CONTENT_ENTRY_TEMPLATE, // TOC XML_TABLE_INDEX_ENTRY_TEMPLATE, // table index XML_ILLUSTRATION_INDEX_ENTRY_TEMPLATE, // illustration index XML_OBJECT_INDEX_ENTRY_TEMPLATE, // object index XML_USER_INDEX_ENTRY_TEMPLATE, // user index XML_ALPHABETICAL_INDEX_ENTRY_TEMPLATE, // alphabetical index XML_BIBLIOGRAPHY_ENTRY_TEMPLATE // bibliography }; bool XMLSectionExport::ExportIndexTemplate( SectionTypeEnum eType, sal_Int32 nOutlineLevel, const Reference & rPropertySet, const Sequence > & rValues) { OSL_ENSURE(eType >= TEXT_SECTION_TYPE_TOC, "illegal index type"); OSL_ENSURE(eType <= TEXT_SECTION_TYPE_BIBLIOGRAPHY, "illegal index type"); OSL_ENSURE(nOutlineLevel >= 0, "illegal outline level"); 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# return false; } // output level name if ((XML_TOKEN_INVALID != eLevelName) && (XML_TOKEN_INVALID != eLevelAttrName)) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, GetXMLToken(eLevelAttrName), GetXMLToken(eLevelName)); } // paragraph level style name const char* pPropName( aTypeLevelStylePropNameMap[eType-TEXT_SECTION_TYPE_TOC][nOutlineLevel]); OSL_ENSURE(nullptr != pPropName, "can't find property name"); if (nullptr != pPropName) { Any aAny = rPropertySet->getPropertyValue( OUString::createFromAscii(pPropName)); OUString sParaStyleName; aAny >>= sParaStyleName; GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sParaStyleName )); } // template element const XMLTokenEnum eElementName( aTypeElementNameMap[eType - TEXT_SECTION_TYPE_TOC]); SvXMLElementExport aLevelTemplate(GetExport(), XML_NAMESPACE_TEXT, GetXMLToken(eElementName), true, true); // export sequence for(auto& rValue : rValues) { ExportIndexTemplateElement( eType, //i90246 rValue); } } return true; } namespace { enum TemplateTypeEnum { TOK_TTYPE_ENTRY_NUMBER, TOK_TTYPE_ENTRY_TEXT, TOK_TTYPE_TAB_STOP, TOK_TTYPE_TEXT, TOK_TTYPE_PAGE_NUMBER, TOK_TTYPE_CHAPTER_INFO, TOK_TTYPE_HYPERLINK_START, TOK_TTYPE_HYPERLINK_END, TOK_TTYPE_BIBLIOGRAPHY, TOK_TTYPE_INVALID }; enum TemplateParamEnum { TOK_TPARAM_TOKEN_TYPE, TOK_TPARAM_CHAR_STYLE, TOK_TPARAM_TAB_RIGHT_ALIGNED, TOK_TPARAM_TAB_POSITION, TOK_TPARAM_TAB_WITH_TAB, // #i21237# TOK_TPARAM_TAB_FILL_CHAR, TOK_TPARAM_TEXT, TOK_TPARAM_CHAPTER_FORMAT, TOK_TPARAM_CHAPTER_LEVEL,//i53420 TOK_TPARAM_BIBLIOGRAPHY_DATA }; } SvXMLEnumStringMapEntry const aTemplateTypeMap[] = { ENUM_STRING_MAP_ENTRY( "TokenEntryNumber", TOK_TTYPE_ENTRY_NUMBER ), ENUM_STRING_MAP_ENTRY( "TokenEntryText", TOK_TTYPE_ENTRY_TEXT ), ENUM_STRING_MAP_ENTRY( "TokenTabStop", TOK_TTYPE_TAB_STOP ), ENUM_STRING_MAP_ENTRY( "TokenText", TOK_TTYPE_TEXT ), ENUM_STRING_MAP_ENTRY( "TokenPageNumber", TOK_TTYPE_PAGE_NUMBER ), ENUM_STRING_MAP_ENTRY( "TokenChapterInfo", TOK_TTYPE_CHAPTER_INFO ), ENUM_STRING_MAP_ENTRY( "TokenHyperlinkStart", TOK_TTYPE_HYPERLINK_START ), ENUM_STRING_MAP_ENTRY( "TokenHyperlinkEnd", TOK_TTYPE_HYPERLINK_END ), ENUM_STRING_MAP_ENTRY( "TokenBibliographyDataField", TOK_TTYPE_BIBLIOGRAPHY ), { nullptr, 0, TemplateTypeEnum(0)} }; SvXMLEnumStringMapEntry const aTemplateParamMap[] = { ENUM_STRING_MAP_ENTRY( "TokenType", TOK_TPARAM_TOKEN_TYPE ), ENUM_STRING_MAP_ENTRY( "CharacterStyleName", TOK_TPARAM_CHAR_STYLE ), ENUM_STRING_MAP_ENTRY( "TabStopRightAligned", TOK_TPARAM_TAB_RIGHT_ALIGNED ), ENUM_STRING_MAP_ENTRY( "TabStopPosition", TOK_TPARAM_TAB_POSITION ), ENUM_STRING_MAP_ENTRY( "TabStopFillCharacter", TOK_TPARAM_TAB_FILL_CHAR ), // #i21237# ENUM_STRING_MAP_ENTRY( "WithTab", TOK_TPARAM_TAB_WITH_TAB ), ENUM_STRING_MAP_ENTRY( "Text", TOK_TPARAM_TEXT ), ENUM_STRING_MAP_ENTRY( "ChapterFormat", TOK_TPARAM_CHAPTER_FORMAT ), ENUM_STRING_MAP_ENTRY( "ChapterLevel", TOK_TPARAM_CHAPTER_LEVEL ),//i53420 ENUM_STRING_MAP_ENTRY( "BibliographyDataField", TOK_TPARAM_BIBLIOGRAPHY_DATA ), { nullptr, 0, TemplateParamEnum(0)} }; SvXMLEnumMapEntry const aBibliographyDataFieldMap[] = { { XML_ADDRESS, BibliographyDataField::ADDRESS }, { XML_ANNOTE, BibliographyDataField::ANNOTE }, { XML_AUTHOR, BibliographyDataField::AUTHOR }, { XML_BIBLIOGRAPHY_TYPE, BibliographyDataField::BIBILIOGRAPHIC_TYPE }, { XML_BOOKTITLE, BibliographyDataField::BOOKTITLE }, { XML_CHAPTER, BibliographyDataField::CHAPTER }, { XML_CUSTOM1, BibliographyDataField::CUSTOM1 }, { XML_CUSTOM2, BibliographyDataField::CUSTOM2 }, { XML_CUSTOM3, BibliographyDataField::CUSTOM3 }, { XML_CUSTOM4, BibliographyDataField::CUSTOM4 }, { XML_CUSTOM5, BibliographyDataField::CUSTOM5 }, { XML_EDITION, BibliographyDataField::EDITION }, { XML_EDITOR, BibliographyDataField::EDITOR }, { XML_HOWPUBLISHED, BibliographyDataField::HOWPUBLISHED }, { XML_IDENTIFIER, BibliographyDataField::IDENTIFIER }, { XML_INSTITUTION, BibliographyDataField::INSTITUTION }, { XML_ISBN, BibliographyDataField::ISBN }, { XML_JOURNAL, BibliographyDataField::JOURNAL }, { XML_MONTH, BibliographyDataField::MONTH }, { XML_NOTE, BibliographyDataField::NOTE }, { XML_NUMBER, BibliographyDataField::NUMBER }, { XML_ORGANIZATIONS, BibliographyDataField::ORGANIZATIONS }, { XML_PAGES, BibliographyDataField::PAGES }, { XML_PUBLISHER, BibliographyDataField::PUBLISHER }, { XML_REPORT_TYPE, BibliographyDataField::REPORT_TYPE }, { XML_SCHOOL, BibliographyDataField::SCHOOL }, { XML_SERIES, BibliographyDataField::SERIES }, { XML_TITLE, BibliographyDataField::TITLE }, { XML_URL, BibliographyDataField::URL }, { XML_VOLUME, BibliographyDataField::VOLUME }, { XML_YEAR, BibliographyDataField::YEAR }, { XML_TOKEN_INVALID, 0 } }; void XMLSectionExport::ExportIndexTemplateElement( SectionTypeEnum eType, //i90246 const Sequence & rValues) { // variables for template values // char style OUString sCharStyle; bool bCharStyleOK = false; // text OUString sText; bool bTextOK = false; // tab position bool bRightAligned = false; // tab position sal_Int32 nTabPosition = 0; bool bTabPositionOK = false; // fill character OUString sFillChar; bool bFillCharOK = false; // chapter format sal_Int16 nChapterFormat = 0; bool bChapterFormatOK = false; // outline max level sal_Int16 nLevel = 0; bool bLevelOK = false; // Bibliography Data sal_Int16 nBibliographyData = 0; bool bBibliographyDataOK = false; // With Tab Stop #i21237# bool bWithTabStop = false; bool bWithTabStopOK = false; //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(const auto& 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) ) switch (nToken) { case TOK_TPARAM_TOKEN_TYPE: { OUString sVal; rValue.Value >>= sVal; SvXMLUnitConverter::convertEnum( nTokenType, sVal, aTemplateTypeMap); break; } case TOK_TPARAM_CHAR_STYLE: // only valid, if not empty rValue.Value >>= sCharStyle; bCharStyleOK = !sCharStyle.isEmpty(); break; case TOK_TPARAM_TEXT: rValue.Value >>= sText; bTextOK = true; break; case TOK_TPARAM_TAB_RIGHT_ALIGNED: bRightAligned = *o3tl::doAccess(rValue.Value); break; case TOK_TPARAM_TAB_POSITION: rValue.Value >>= nTabPosition; bTabPositionOK = true; break; // #i21237# case TOK_TPARAM_TAB_WITH_TAB: bWithTabStop = *o3tl::doAccess(rValue.Value); bWithTabStopOK = true; break; case TOK_TPARAM_TAB_FILL_CHAR: rValue.Value >>= sFillChar; bFillCharOK = true; break; case TOK_TPARAM_CHAPTER_FORMAT: rValue.Value >>= nChapterFormat; bChapterFormatOK = true; break; //---> i53420 case TOK_TPARAM_CHAPTER_LEVEL: rValue.Value >>= nLevel; bLevelOK = true; break; case TOK_TPARAM_BIBLIOGRAPHY_DATA: rValue.Value >>= nBibliographyData; bBibliographyDataOK = true; break; } } } // convert type to token (and check validity) ... XMLTokenEnum eElement(XML_TOKEN_INVALID); sal_uInt16 nNamespace(XML_NAMESPACE_TEXT); switch(nTokenType) { case TOK_TTYPE_ENTRY_TEXT: eElement = XML_INDEX_ENTRY_TEXT; break; case TOK_TTYPE_TAB_STOP: // test validity if ( bRightAligned || bTabPositionOK || bFillCharOK ) { eElement = XML_INDEX_ENTRY_TAB_STOP; } break; case TOK_TTYPE_TEXT: // test validity if (bTextOK) { eElement = XML_INDEX_ENTRY_SPAN; } break; case TOK_TTYPE_PAGE_NUMBER: eElement = XML_INDEX_ENTRY_PAGE_NUMBER; break; case TOK_TTYPE_CHAPTER_INFO: // keyword index eElement = XML_INDEX_ENTRY_CHAPTER; break; case TOK_TTYPE_ENTRY_NUMBER: // table of content eElement = XML_INDEX_ENTRY_CHAPTER; break; case TOK_TTYPE_HYPERLINK_START: eElement = XML_INDEX_ENTRY_LINK_START; break; case TOK_TTYPE_HYPERLINK_END: eElement = XML_INDEX_ENTRY_LINK_END; break; case TOK_TTYPE_BIBLIOGRAPHY: if (bBibliographyDataOK) { eElement = XML_INDEX_ENTRY_BIBLIOGRAPHY; } break; default: ; // unknown/unimplemented template break; } if (eType != TEXT_SECTION_TYPE_TOC) { switch (nTokenType) { case TOK_TTYPE_HYPERLINK_START: case TOK_TTYPE_HYPERLINK_END: if (SvtSaveOptions::ODFSVER_012 < aODFVersion) { assert(eType == TEXT_SECTION_TYPE_ILLUSTRATION || eType == TEXT_SECTION_TYPE_OBJECT || eType == TEXT_SECTION_TYPE_TABLE || eType == TEXT_SECTION_TYPE_USER); // ODF 1.3 OFFICE-3941 nNamespace = (SvtSaveOptions::ODFSVER_013 <= aODFVersion) ? XML_NAMESPACE_TEXT : XML_NAMESPACE_LO_EXT; } else { eElement = XML_TOKEN_INVALID; // not allowed in ODF <= 1.2 } break; default: break; } } //--->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; } } } else if (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); } // #i21237# if (bWithTabStopOK && ! bWithTabStop) { GetExport().AddAttribute(XML_NAMESPACE_STYLE, XML_WITH_TAB, XML_FALSE); } } // bibliography data if (TOK_TTYPE_BIBLIOGRAPHY == nTokenType) { OSL_ENSURE(bBibliographyDataOK, "need bibl data"); OUStringBuffer sBuf; if (SvXMLUnitConverter::convertEnum( sBuf, nBibliographyData, aBibliographyDataFieldMap ) ) { GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_BIBLIOGRAPHY_DATA_FIELD, sBuf.makeStringAndClear()); } } // chapter info if (TOK_TTYPE_CHAPTER_INFO == nTokenType) { OSL_ENSURE(bChapterFormatOK, "need chapter info"); GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_DISPLAY, XMLTextFieldExport::MapChapterDisplayFormat(nChapterFormat)); //---> i53420 if (bLevelOK) GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL, OUString::number(nLevel)); } //--->i53420 if (TOK_TTYPE_ENTRY_NUMBER == nTokenType) { if (bChapterFormatOK) GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_DISPLAY, XMLTextFieldExport::MapChapterDisplayFormat(nChapterFormat)); if (bLevelOK) GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_OUTLINE_LEVEL, OUString::number(nLevel)); } // export template SvXMLElementExport aTemplateElement(GetExport(), nNamespace, GetXMLToken(eElement), true, false) ; // entry text or span element: write text if (TOK_TTYPE_TEXT == nTokenType) { GetExport().Characters(sText); } } void XMLSectionExport::ExportLevelParagraphStyles( Reference const & xLevelParagraphStyles) { // iterate over levels sal_Int32 nPLevelCount = xLevelParagraphStyles->getCount(); for(sal_Int32 nLevel = 0; nLevel < nPLevelCount; nLevel++) { Any aAny = xLevelParagraphStyles->getByIndex(nLevel); Sequence aStyleNames; aAny >>= aStyleNames; // 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(const auto& rStyleName : std::as_const(aStyleNames)) { // stylename attribute GetExport().AddAttribute(XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName(rStyleName) ); // element SvXMLElementExport aParaStyle(GetExport(), XML_NAMESPACE_TEXT, XML_INDEX_SOURCE_STYLE, true, false); } } } } void XMLSectionExport::ExportBoolean( const Reference & rPropSet, const OUString& sPropertyName, enum XMLTokenEnum eAttributeName, bool bDefault, bool bInvert) { OSL_ENSURE(eAttributeName != XML_TOKEN_INVALID, "Need attribute name"); Any aAny = rPropSet->getPropertyValue(sPropertyName); bool bTmp = *o3tl::doAccess(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 xTextFieldsSupp( rExport.GetModel(), UNO_QUERY ); if ( !xTextFieldsSupp.is() ) return; static const OUStringLiteral sFieldMaster_Bibliography(u"com.sun.star.text.FieldMaster.Bibliography"); // get bibliography field master Reference xMasters = xTextFieldsSupp->getTextFieldMasters(); if ( !xMasters->hasByName(sFieldMaster_Bibliography) ) return; Any aAny = xMasters->getByName(sFieldMaster_Bibliography); Reference xPropSet; aAny >>= xPropSet; OSL_ENSURE( xPropSet.is(), "field master must have XPropSet" ); OUString sTmp; aAny = xPropSet->getPropertyValue("BracketBefore"); aAny >>= sTmp; rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_PREFIX, sTmp); aAny = xPropSet->getPropertyValue("BracketAfter"); aAny >>= sTmp; rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_SUFFIX, sTmp); aAny = xPropSet->getPropertyValue("IsNumberEntries"); if (*o3tl::doAccess(aAny)) { rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_NUMBERED_ENTRIES, XML_TRUE); } aAny = xPropSet->getPropertyValue("IsSortByPosition"); if (! *o3tl::doAccess(aAny)) { rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_SORT_BY_POSITION, XML_FALSE); } // sort algorithm aAny = xPropSet->getPropertyValue("SortAlgorithm"); OUString sAlgorithm; aAny >>= sAlgorithm; if( !sAlgorithm.isEmpty() ) { rExport.AddAttribute( XML_NAMESPACE_TEXT, XML_SORT_ALGORITHM, sAlgorithm ); } // locale aAny = xPropSet->getPropertyValue("Locale"); Locale aLocale; aAny >>= aLocale; rExport.AddLanguageTagAttributes( XML_NAMESPACE_FO, XML_NAMESPACE_STYLE, aLocale, true); // configuration element SvXMLElementExport aElement(rExport, XML_NAMESPACE_TEXT, XML_BIBLIOGRAPHY_CONFIGURATION, true, true); // sort keys aAny = xPropSet->getPropertyValue("SortKeys"); Sequence > aKeys; aAny >>= aKeys; for(const Sequence & rKey : std::as_const(aKeys)) { for(const PropertyValue& rValue : rKey) { if (rValue.Name == "SortKey") { sal_Int16 nKey = 0; rValue.Value >>= nKey; OUStringBuffer sBuf; if (SvXMLUnitConverter::convertEnum( sBuf, nKey, aBibliographyDataFieldMap ) ) { rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_KEY, sBuf.makeStringAndClear()); } } else if (rValue.Name == "IsSortAscending") { bool bTmp = *o3tl::doAccess(rValue.Value); rExport.AddAttribute(XML_NAMESPACE_TEXT, XML_SORT_ASCENDING, bTmp ? XML_TRUE : XML_FALSE); } } SvXMLElementExport aKeyElem(rExport, XML_NAMESPACE_TEXT, XML_SORT_KEY, true, true); } } bool XMLSectionExport::IsMuteSection( const Reference & rSection) const { bool bRet = false; // 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 aSection(rSection); aSection.is(); aSection = aSection->getParentSection()) { // check if it is a global document section (linked or index) Reference xPropSet(aSection, UNO_QUERY); if (xPropSet.is()) { Any aAny = xPropSet->getPropertyValue("IsGlobalDocumentSection"); if ( *o3tl::doAccess(aAny) ) { Reference 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) return bRet; } bool XMLSectionExport::IsMuteSection( const Reference & rSection, bool bDefault) const { // default: like default argument bool bRet = bDefault; Reference xPropSet(rSection->getAnchor(), UNO_QUERY); if (xPropSet.is()) { if (xPropSet->getPropertySetInfo()->hasPropertyByName("TextSection")) { Any aAny = xPropSet->getPropertyValue("TextSection"); Reference xSection; aAny >>= xSection; bRet = IsMuteSection(xSection); } // else: return default } // else: return default return bRet; } bool XMLSectionExport::IsInSection( const Reference & rEnclosingSection, const Reference & rContent, bool bDefault) { // default: like default argument bool bRet = bDefault; OSL_ENSURE(rEnclosingSection.is(), "enclosing section expected"); Reference xPropSet(rContent, UNO_QUERY); if (xPropSet.is()) { if (xPropSet->getPropertySetInfo()->hasPropertyByName("TextSection")) { Any aAny = xPropSet->getPropertyValue("TextSection"); Reference 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 return bRet; } void XMLSectionExport::ExportMasterDocHeadingDummies() { if( bHeadingDummiesExported ) return; Reference< XChapterNumberingSupplier > xCNSupplier( rExport.GetModel(), UNO_QUERY ); Reference< XIndexReplace > xChapterNumbering; if( xCNSupplier.is() ) xChapterNumbering = xCNSupplier->getChapterNumberingRules(); if( !xChapterNumbering.is() ) return; sal_Int32 nCount = xChapterNumbering->getCount(); for( sal_Int32 nLevel = 0; nLevel < nCount; nLevel++ ) { OUString sStyle; Sequence aProperties; xChapterNumbering->getByIndex( nLevel ) >>= aProperties; auto pProp = std::find_if(std::cbegin(aProperties), std::cend(aProperties), [](const PropertyValue& rProp) { return rProp.Name == "HeadingStyleName"; }); if (pProp != std::cend(aProperties)) pProp->Value >>= sStyle; if( !sStyle.isEmpty() ) { GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_STYLE_NAME, GetExport().EncodeStyleName( sStyle ) ); GetExport().AddAttribute( XML_NAMESPACE_TEXT, XML_LEVEL, OUString::number( nLevel + 1 ) ); SvXMLElementExport aElem( GetExport(), XML_NAMESPACE_TEXT, XML_H, true, false ); } } bHeadingDummiesExported = true; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */