sw/qa/extras/ooxmlexport/data/tdf152425.docx |binary sw/qa/extras/ooxmlexport/ooxmlexport13.cxx | 8 - sw/qa/extras/ooxmlexport/ooxmlexport16.cxx | 2 sw/qa/extras/ooxmlexport/ooxmlexport18.cxx | 19 ++ sw/source/filter/inc/wwstyles.hxx | 1 sw/source/filter/ww8/docxattributeoutput.cxx | 16 +- sw/source/filter/ww8/styles.cxx | 185 +++++++++++++-------------- sw/source/filter/ww8/wrtw8sty.cxx | 140 +++++++++++--------- sw/source/filter/ww8/wrtww8.hxx | 10 + 9 files changed, 208 insertions(+), 173 deletions(-)
New commits: commit a15de4c3a3075aa7ca78c1c19ec480c339531e47 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Sat Dec 10 08:58:10 2022 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Jan 20 11:35:23 2023 +0000 tdf#152425 Make Word names unique, and use them for style ids generation Before, a style id was generated from LibreOffice name, and then the name was replaced with Word name. Given that Writer's List N maps to Word's List Bullet N, and Word's List N doesn't map to anything in Writer, this led to styles.xml having after roundtrip: <w:style w:type="paragraph" w:styleId="List5"> <w:name w:val="List Bullet 5"/> ... <w:style w:type="paragraph" w:styleId="ListBullet5"> <w:name w:val="List Bullet 5"/> So the idea is to do the following steps: 1. Collect all the exported styles (unchanged); 2. Build unique Word names for collected styles (new): a. Process all the styles that map to special Word styles first, so that their Word names don't get changed when made unique; b. Process the rest of the styles, making sure to append a sequential number after the Writer name, if a clash happens. 3. Build Style Ids from the Word names (previously Writer name could be used), also making sure they are unique. Change-Id: I9f8f254aa6ae713671234f0109b94cc72a588150 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143905 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145886 Tested-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx index f42b5e7f9a28..a1610c35dbbb 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport13.cxx @@ -1228,8 +1228,8 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf123628) xmlDocUniquePtr pXmlStyles = parseExport("word/styles.xml"); - assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:hyperlink/w:r/w:rPr/w:rStyle", "val", "InternetLink"); - assertXPath(pXmlStyles, "/w:styles/w:style[@w:styleId='InternetLink']/w:name", "val", "Hyperlink"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:hyperlink/w:r/w:rPr/w:rStyle", "val", "Hyperlink"); + assertXPath(pXmlStyles, "/w:styles/w:style[@w:styleId='Hyperlink']/w:name", "val", "Hyperlink"); } DECLARE_OOXMLEXPORT_TEST(testTdf127741, "tdf127741.docx") @@ -1255,7 +1255,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf127925) loadAndSave("tdf127925.odt"); CPPUNIT_ASSERT_EQUAL(1, getPages()); xmlDocUniquePtr pXmlStyles = parseExport("word/styles.xml"); - assertXPath(pXmlStyles, "/w:styles/w:style[@w:styleId='VisitedInternetLink']/w:name", "val", "FollowedHyperlink"); + assertXPath(pXmlStyles, "/w:styles/w:style[@w:styleId='FollowedHyperlink']/w:name", "val", "FollowedHyperlink"); } CPPUNIT_TEST_FIXTURE(Test, testTdf127579) @@ -1263,7 +1263,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf127579) loadAndSave("tdf127579.odt"); CPPUNIT_ASSERT_EQUAL(1, getPages()); xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml"); - assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:hyperlink/w:r/w:rPr/w:rStyle", "val", "InternetLink"); + assertXPath(pXmlDoc, "/w:document/w:body/w:p/w:hyperlink/w:r/w:rPr/w:rStyle", "val", "Hyperlink"); } CPPUNIT_TEST_FIXTURE(Test, testTdf128304) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx index f5230adb643a..4c27a18101fd 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport16.cxx @@ -1013,7 +1013,7 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf143726) CPPUNIT_ASSERT(pXmlStyles); // Without the fix this was "TOA Heading" which belongs to the "Table of Authorities" index in Word // TOC's heading style should be exported as "TOC Heading" as that's the default Word style name - assertXPath(pXmlStyles, "/w:styles/w:style[@w:styleId='ContentsHeading']/w:name", "val", "TOC Heading"); + assertXPath(pXmlStyles, "/w:styles/w:style[@w:styleId='TOCHeading']/w:name", "val", "TOC Heading"); } CPPUNIT_TEST_FIXTURE(Test, testTdf152153) diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx index 0bb66493c331..f3b63cd3c57f 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx @@ -257,6 +257,11 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf152425) // CPPUNIT_ASSERT_EQUAL(OUString("List 5"), Para4Style); // But for now, just make sure that the style names differ CPPUNIT_ASSERT(Para4Style != Para3Style); + const OUString Para5Style = getProperty<OUString>(getParagraph(5), "ParaStyleName"); + // Eventually, we need to check this: + // CPPUNIT_ASSERT_EQUAL(OUString("List Bullet 5"), Para5Style); + // But for now, just make sure that the style names differ + CPPUNIT_ASSERT(Para5Style != Para4Style); } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx index 80f09a85562f..22349f47dd28 100644 --- a/sw/source/filter/ww8/docxattributeoutput.cxx +++ b/sw/source/filter/ww8/docxattributeoutput.cxx @@ -3822,7 +3822,12 @@ void DocxAttributeOutput::Redline( const SwRedlineData* pRedlineData) m_pSerializer->startElementNS(XML_w, XML_pPr); - OString sStyleName = MSWordStyles::CreateStyleId( sParaStyleName ); + OString sStyleName; + if (auto format = m_rExport.m_rDoc.FindTextFormatCollByName(sParaStyleName)) + if (auto slot = m_rExport.m_pStyles->GetSlot(format); slot != 0xfff) + sStyleName = m_rExport.m_pStyles->GetStyleId(slot); + if (sStyleName.isEmpty()) + sStyleName = MSWordStyles::CreateStyleId(sParaStyleName); if ( !sStyleName.isEmpty() ) m_pSerializer->singleElementNS(XML_w, XML_pStyle, FSNS(XML_w, XML_val), sStyleName); @@ -7115,20 +7120,14 @@ void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType, SAL_WARN("sw.ww8", "Unhandled style property: " << rProp.Name); } - // MSO exports English names and writerfilter only recognize them. - const char *pEnglishName = nullptr; const char* pType = nullptr; switch (eType) { case STYLE_TYPE_PARA: pType = "paragraph"; - if ( nWwId < ww::stiMax) - pEnglishName = ww::GetEnglishNameFromSti( static_cast<ww::sti>(nWwId ) ); break; case STYLE_TYPE_CHAR: pType = "character"; - if (nWwId < ww::stiMax) - pEnglishName = ww::GetEnglishNameFromSti(static_cast<ww::sti>(nWwId)); break; case STYLE_TYPE_LIST: pType = "numbering"; break; } @@ -7139,8 +7138,7 @@ void DocxAttributeOutput::StartStyle( const OUString& rName, StyleType eType, if (bCustomStyle) pStyleAttributeList->add(FSNS(XML_w, XML_customStyle), "1"); m_pSerializer->startElementNS( XML_w, XML_style, pStyleAttributeList); - m_pSerializer->singleElementNS( XML_w, XML_name, - FSNS( XML_w, XML_val ), pEnglishName ? pEnglishName : rName.toUtf8() ); + m_pSerializer->singleElementNS(XML_w, XML_name, FSNS(XML_w, XML_val), rName); if ( nBase != 0x0FFF && eType != STYLE_TYPE_LIST) { diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx index f251f41cff15..8ca2eb1776b8 100644 --- a/sw/source/filter/ww8/wrtw8sty.cxx +++ b/sw/source/filter/ww8/wrtw8sty.cxx @@ -158,6 +158,7 @@ MSWordStyles::MSWordStyles( MSWordExportBase& rExport, bool bListStyles ) memset( m_aHeadingParagraphStyles, -1 , MAXLEVEL * sizeof( sal_uInt16)); BuildStylesTable(); + BuildWwNames(); BuildStyleIds(); } @@ -289,7 +290,7 @@ void MSWordStyles::BuildStylesTable() sal_uInt16 nSlot = BuildGetSlot(*pFormat); if (nSlot != 0xfff) { - m_aStyles[nSlot].format = pFormat; + m_aStyles[nSlot] = { pFormat }; } else { @@ -319,6 +320,59 @@ void MSWordStyles::BuildStylesTable() } } +void MSWordStyles::BuildWwNames() +{ + std::unordered_set<OUString> aUsed; + + auto makeUniqueName = [&aUsed](OUString& name) { + // toAsciiLowerCase rules out e.g. user's "normal"; no problem if there are non-ASCII chars + OUString lower(name.toAsciiLowerCase()); + if (!aUsed.insert(lower).second) + { + int nFree = 1; + while (!aUsed.insert(lower + OUString::number(nFree)).second) + ++nFree; + + name += OUString::number(nFree); + } + }; + + // We want to map LO's default style to Word's "Normal" style. + // Word looks for this specific style name when reading docx files. + // (It must be the English word regardless of language settings) + assert(!m_aStyles.empty()); + assert(!m_aStyles[0].format || m_aStyles[0].ww_id == ww::stiNormal); + m_aStyles[0].ww_name = "Normal"; + aUsed.insert("normal"); + + // 1. Handle styles having special wwIds, and thus pre-defined names + for (auto& entry : m_aStyles) + { + if (!entry.ww_name.isEmpty()) + continue; // "Normal" is already added + if (entry.ww_id >= ww::stiMax) + continue; // Not a format with special name + assert(entry.format); + + entry.ww_name = OUString::createFromAscii(ww::GetEnglishNameFromSti(static_cast<ww::sti>(entry.ww_id))); + makeUniqueName(entry.ww_name); + } + + // 2. Now handle other styles + for (auto& entry : m_aStyles) + { + if (!entry.ww_name.isEmpty()) + continue; + if (entry.format) + entry.ww_name = entry.format->GetName(); + else if (entry.num_rule) + entry.ww_name = entry.num_rule->GetName(); + else + continue; + makeUniqueName(entry.ww_name); + } +} + OString MSWordStyles::CreateStyleId(std::u16string_view aName) { OStringBuffer aStyleIdBuf(aName.size()); @@ -341,23 +395,9 @@ void MSWordStyles::BuildStyleIds() { std::unordered_set<OString> aUsed; - assert(!m_aStyles.empty()); - m_aStyles[0].style_id = "Normal"; - aUsed.insert("normal"); - for (auto& entry : m_aStyles) { - if (!entry.style_id.isEmpty()) - continue; // "Normal" is already added - - assert(entry.style_id.isEmpty()); - OUString name; - if (entry.format) - name = entry.format->GetName(); - else if (entry.num_rule) - name = entry.num_rule->GetName(); - - OString aStyleId = CreateStyleId(name); + OString aStyleId = CreateStyleId(entry.ww_name); if (aStyleId.isEmpty()) aStyleId = "Style"; @@ -590,68 +630,45 @@ void WW8AttributeOutput::DefaultStyle() m_rWW8Export.m_pTableStrm->WriteUInt16(0); // empty Style } -void MSWordStyles::OutputStyle(const SwNumRule* pNumRule, sal_uInt16 nSlot) +void MSWordStyles::OutputStyle(sal_uInt16 nSlot) { - m_rExport.AttrOutput().StartStyle( pNumRule->GetName(), STYLE_TYPE_LIST, + const auto& entry = m_aStyles[nSlot]; + + if (entry.num_rule) + { + m_rExport.AttrOutput().StartStyle( entry.ww_name, STYLE_TYPE_LIST, /*nBase =*/ 0, /*nWwNext =*/ 0, /*nWwLink =*/ 0, /*nWWId =*/ 0, nSlot, /*bAutoUpdateFormat =*/ false ); - m_rExport.AttrOutput().EndStyle(); -} - -// OutputStyle applies for TextFormatColls and CharFormats -void MSWordStyles::OutputStyle( const SwFormat* pFormat, sal_uInt16 nSlot) -{ - if ( !pFormat ) + m_rExport.AttrOutput().EndStyle(); + } + else if (!entry.format) + { m_rExport.AttrOutput().DefaultStyle(); + } else { bool bFormatColl; sal_uInt16 nBase, nWwNext; sal_uInt16 nWwLink = 0x0FFF; - GetStyleData(pFormat, bFormatColl, nBase, nWwNext, nWwLink); + GetStyleData(entry.format, bFormatColl, nBase, nWwNext, nWwLink); - OUString aName = pFormat->GetName(); - // We want to map LO's default style to Word's "Normal" style. - // Word looks for this specific style name when reading docx files. - // (It must be the English word regardless of language settings) - if (nSlot == 0) - { - assert( pFormat->GetPoolFormatId() == RES_POOLCOLL_STANDARD ); - aName = "Normal"; - } - else if (aName.equalsIgnoreAsciiCase("Normal")) - { - // If LO has a style named "Normal"(!) rename it to something unique - const OUString aBaseName = "LO-" + aName; - aName = aBaseName; - // Check if we still have a clash, in which case we add a suffix - for ( int nSuffix = 0; ; ++nSuffix ) { - if (std::none_of(m_aStyles.begin() + 1, m_aStyles.end(), - [&aName](const auto& entry) { - return entry.format - && entry.format->GetName().equalsIgnoreAsciiCase(aName); - })) - break; // Found a unique name - aName = aBaseName + OUString::number(nSuffix); - } - } - else if (!bFormatColl && m_rExport.GetExportFormat() == MSWordExportBase::DOCX && - m_rExport.m_pStyles->GetStyleId(nSlot).startsWith("ListLabel")) + if (!bFormatColl && m_rExport.GetExportFormat() == MSWordExportBase::DOCX && + entry.style_id.startsWith("ListLabel")) { // tdf#92335 don't export redundant DOCX import style "ListLabel" return; } - m_rExport.AttrOutput().StartStyle( aName, (bFormatColl ? STYLE_TYPE_PARA : STYLE_TYPE_CHAR), - nBase, nWwNext, nWwLink, GetWWId( *pFormat ), nSlot, - pFormat->IsAutoUpdateFormat() ); + m_rExport.AttrOutput().StartStyle(entry.ww_name, (bFormatColl ? STYLE_TYPE_PARA : STYLE_TYPE_CHAR), + nBase, nWwNext, nWwLink, m_aStyles[nSlot].ww_id, nSlot, + entry.format->IsAutoUpdateFormat() ); if ( bFormatColl ) - WriteProperties( pFormat, true, nSlot, nBase==0xfff ); // UPX.papx + WriteProperties( entry.format, true, nSlot, nBase==0xfff ); // UPX.papx - WriteProperties( pFormat, false, nSlot, bFormatColl && nBase==0xfff ); // UPX.chpx + WriteProperties( entry.format, false, nSlot, bFormatColl && nBase==0xfff ); // UPX.chpx m_rExport.AttrOutput().EndStyle(); } @@ -700,12 +717,7 @@ void MSWordStyles::OutputStylesTable() // Implementing check for all exports DOCX, DOC, RTF assert(m_aStyles.size() <= MSWORD_MAX_STYLES_LIMIT); for (size_t slot = 0; slot < m_aStyles.size(); ++slot) - { - if (m_aStyles[slot].num_rule) - OutputStyle(m_aStyles[slot].num_rule, slot); - else - OutputStyle(m_aStyles[slot].format, slot); - } + OutputStyle(slot); m_rExport.AttrOutput().EndStyles(m_aStyles.size()); diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx index 5af10e91fdc3..cf5d0bfa104b 100644 --- a/sw/source/filter/ww8/wrtww8.hxx +++ b/sw/source/filter/ww8/wrtww8.hxx @@ -1587,10 +1587,12 @@ class MSWordStyles const SwFormat* format = nullptr; const SwNumRule* num_rule = nullptr; /// We need to build style id's for DOCX export; ideally we should roundtrip that, but this is good enough. + sal_uInt16 ww_id = ww::stiUser; + OUString ww_name; OString style_id; MapEntry() = default; - MapEntry(const SwFormat* f) : format(f) {} + MapEntry(const SwFormat* f) : format(f) { if (f) ww_id = GetWWId(*f); } MapEntry(const SwNumRule* r) : num_rule(r) {} }; std::vector<MapEntry> m_aStyles; ///< Slot <-> Character/paragraph/list style array. @@ -1599,6 +1601,9 @@ class MSWordStyles /// Create the style table, called from the constructor. void BuildStylesTable(); + /// Generate proper Word names, taking mapping between special types into account + void BuildWwNames(); + /// Based on style names, fill in unique, MS-like names. void BuildStyleIds(); @@ -1613,8 +1618,7 @@ class MSWordStyles void SetStyleDefaults( const SwFormat& rFormat, bool bPap ); /// Outputs one style - called (in a loop) from OutputStylesTable(). - void OutputStyle( const SwFormat* pFormat, sal_uInt16 nSlot ); - void OutputStyle( const SwNumRule* pNumRule, sal_uInt16 nSlot); + void OutputStyle( sal_uInt16 nSlot ); MSWordStyles( const MSWordStyles& ) = delete; MSWordStyles& operator=( const MSWordStyles& ) = delete; commit 0879de301ed9e987cdff74911fe53c45ef6a4059 Author: Mike Kaganski <mike.kagan...@collabora.com> AuthorDate: Thu Dec 8 19:13:43 2022 +0300 Commit: Mike Kaganski <mike.kagan...@collabora.com> CommitDate: Fri Jan 20 11:35:12 2023 +0000 tdf#152425 Fix order in stiName array Since their introduction in commit 552d05f57175ecdd0736dc257319bc30aa88d696 (INTEGRATION: CWS portlaoisefilterteam16 (1.1.2); FILE ADDED, 2003-12-09) and commit 9ba054a180fe1fcd410a2887351c2ff1fcb30847 (INTEGRATION: CWS portlaoisefilterteam16 (1.1.2); FILE ADDED, 2003-12-09), the enum sti and GetStiNames were accidentally not matching each other. commit 78284714b73a8307174c596295894e8f3951e09a (tdf#76817: fix missing heading styles assigned to outline levels in ooxml, 2016-02-04) introduced a use of ww::GetEnglishNameFromSti, and since then, the unmatched elements started to get written to DOCX styles with wrong names, like <w:style w:type="paragraph" w:styleId="List5"> <w:name w:val="List Number"/> instead of original name "List 5". Change-Id: I8888b3f117e0b7f57c2dbb90565475d529416c60 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143828 Tested-by: Jenkins Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145885 Tested-by: Mike Kaganski <mike.kagan...@collabora.com> diff --git a/sw/qa/extras/ooxmlexport/data/tdf152425.docx b/sw/qa/extras/ooxmlexport/data/tdf152425.docx new file mode 100644 index 000000000000..53a65cc63438 Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/tdf152425.docx differ diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx index 1524539eb309..0bb66493c331 100644 --- a/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx +++ b/sw/qa/extras/ooxmlexport/ooxmlexport18.cxx @@ -245,6 +245,20 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf126477) CPPUNIT_ASSERT_EQUAL(sal_Int32(1), aSeq2.getLength()); } +CPPUNIT_TEST_FIXTURE(Test, testTdf152425) +{ + loadAndReload("tdf152425.docx"); + + // Check that "List Number" and "List 5" styles don't get merged + const OUString Para3Style = getProperty<OUString>(getParagraph(3), "ParaStyleName"); + CPPUNIT_ASSERT_EQUAL(OUString("List Number"), Para3Style); + const OUString Para4Style = getProperty<OUString>(getParagraph(4), "ParaStyleName"); + // Eventually, we need to check this: + // CPPUNIT_ASSERT_EQUAL(OUString("List 5"), Para4Style); + // But for now, just make sure that the style names differ + CPPUNIT_ASSERT(Para4Style != Para3Style); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/inc/wwstyles.hxx b/sw/source/filter/inc/wwstyles.hxx index 32dce11e3692..7a253d87c508 100644 --- a/sw/source/filter/inc/wwstyles.hxx +++ b/sw/source/filter/inc/wwstyles.hxx @@ -24,6 +24,7 @@ namespace ww { + // When changing, make sure to update GetStiNames in sw/source/filter/ww8/styles.cxx accordingly enum sti : sal_uInt16 { stiNormal = 0, // 0x0000 diff --git a/sw/source/filter/ww8/styles.cxx b/sw/source/filter/ww8/styles.cxx index 86ec89a37798..c7a28e77e60b 100644 --- a/sw/source/filter/ww8/styles.cxx +++ b/sw/source/filter/ww8/styles.cxx @@ -25,102 +25,103 @@ namespace { const char **GetStiNames() noexcept { + // Matches enum ww::sti in sw/source/filter/inc/wwstyles.hxx static const char *stiName[] = { - "Normal", - "Heading 1", - "Heading 2", - "Heading 3", - "Heading 4", - "Heading 5", - "Heading 6", - "Heading 7", - "Heading 8", - "Heading 9", - "Index 1", - "Index 2", - "Index 3", - "Index 4", - "Index 5", - "Index 6", - "Index 7", - "Index 8", - "Index 9", - "TOC 1", - "TOC 2", - "TOC 3", - "TOC 4", - "TOC 5", - "TOC 6", - "TOC 7", - "TOC 8", - "TOC 9", - "Normal Indent", - "Footnote Text", - "Annotation Text", - "Header", - "Footer", - "Index Heading", - "Caption", - "Table of Figures", - "Envelope Address", - "Envelope Return", - "Footnote Reference", - "Annotation Reference", - "Line Number", - "Page Number", - "Endnote Reference", - "Endnote Text", - "Table of Authorities", - "Macro Text", - "TOC Heading", - "List", - "List 2", - "List 3", - "List 4", - "List 5", - "List Bullet", - "List Bullet 2", - "List Bullet 3", - "List Bullet 4", - "List Bullet 5", - "List Number", - "List Number 2", - "List Number 3", - "List Number 4", - "List Number 5", - "Title", - "Closing", - "Signature", - "Default Paragraph Font", - "Body Text", - "Body Text Indent", - "List Continue", - "List Continue 2", - "List Continue 3", - "List Continue 4", - "List Continue 5", - "Message Header", - "Subtitle", - "Salutation", - "Date", - "Body Text First Indent", - "Body Text First Indent 2", - "Note Heading", - "Body Text 2", - "Body Text 3", - "Body Text Indent 2", - "Body Text Indent 3", - "Block Text", - "Hyperlink", - "FollowedHyperlink", - "Strong", - "Emphasis", - "Document Map", - "Plain Text" + "Normal", // stiNormal + "Heading 1", // stiLev1 + "Heading 2", // stiLev2 + "Heading 3", // stiLev3 + "Heading 4", // stiLev4 + "Heading 5", // stiLev5 + "Heading 6", // stiLev6 + "Heading 7", // stiLev7 + "Heading 8", // stiLev8 + "Heading 9", // stiLev9 + "Index 1", // stiIndex1 + "Index 2", // stiIndex2 + "Index 3", // stiIndex3 + "Index 4", // stiIndex4 + "Index 5", // stiIndex5 + "Index 6", // stiIndex6 + "Index 7", // stiIndex7 + "Index 8", // stiIndex8 + "Index 9", // stiIndex9 + "TOC 1", // stiToc1 + "TOC 2", // stiToc2 + "TOC 3", // stiToc3 + "TOC 4", // stiToc4 + "TOC 5", // stiToc5 + "TOC 6", // stiToc6 + "TOC 7", // stiToc7 + "TOC 8", // stiToc8 + "TOC 9", // stiToc9 + "Normal Indent", // stiNormIndent + "Footnote Text", // stiFootnoteText + "Annotation Text", // stiAtnText + "Header", // stiHeader + "Footer", // stiFooter + "Index Heading", // stiIndexHeading + "Caption", // stiCaption + "Table of Figures", // stiToCaption + "Envelope Address", // stiEnvAddr + "Envelope Return", // stiEnvRet + "Footnote Reference", // stiFootnoteRef + "Annotation Reference", // stiAtnRef + "Line Number", // stiLnn + "Page Number", // stiPgn + "Endnote Reference", // stiEdnRef + "Endnote Text", // stiEdnText + "Table of Authorities", // stiToa + "Macro Text", // stiMacro + "TOC Heading", // stiToaHeading - tdf143726 + "List", // stiList + "List Bullet", // stiListBullet + "List Number", // stiListNumber + "List 2", // stiList2 + "List 3", // stiList3 + "List 4", // stiList4 + "List 5", // stiList5 + "List Bullet 2", // stiListBullet2 + "List Bullet 3", // stiListBullet3 + "List Bullet 4", // stiListBullet4 + "List Bullet 5", // stiListBullet5 + "List Number 2", // stiListNumber2 + "List Number 3", // stiListNumber3 + "List Number 4", // stiListNumber4 + "List Number 5", // stiListNumber5 + "Title", // stiTitle + "Closing", // stiClosing + "Signature", // stiSignature + "Default Paragraph Font", // stiNormalChar + "Body Text", // stiBodyText + "Body Text Indent", // stiBodyTextInd1 + "List Continue", // stiListCont + "List Continue 2", // stiListCont2 + "List Continue 3", // stiListCont3 + "List Continue 4", // stiListCont4 + "List Continue 5", // stiListCont5 + "Message Header", // stiMsgHeader + "Subtitle", // stiSubtitle + "Salutation", // stiSalutation + "Date", // stiDate + "Body Text First Indent", // stiBodyText1I + "Body Text First Indent 2", // stiBodyText1I2 + "Note Heading", // stiNoteHeading + "Body Text 2", // stiBodyText2 + "Body Text 3", // stiBodyText3 + "Body Text Indent 2", // stiBodyTextInd2 + "Body Text Indent 3", // stiBodyTextInd3 + "Block Text", // stiBlockQuote + "Hyperlink", // stiHyperlink + "FollowedHyperlink", // stiHyperlinkFollowed + "Strong", // stiStrong + "Emphasis", // stiEmphasis + "Document Map", // stiNavPane + "Plain Text", // stiPlainText }; - OSL_ENSURE( SAL_N_ELEMENTS(stiName) == ww::stiMax, "WrongSizeOfArray" ); + static_assert(SAL_N_ELEMENTS(stiName) == ww::stiMax, "WrongSizeOfArray"); return stiName; }