diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/filter/html/htmlftn.cxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/filter/html/htmlftn.cxx')
-rw-r--r-- | sw/source/filter/html/htmlftn.cxx | 598 |
1 files changed, 598 insertions, 0 deletions
diff --git a/sw/source/filter/html/htmlftn.cxx b/sw/source/filter/html/htmlftn.cxx new file mode 100644 index 0000000000..db24a32bb7 --- /dev/null +++ b/sw/source/filter/html/htmlftn.cxx @@ -0,0 +1,598 @@ +/* -*- 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 <sal/config.h> + +#include <string_view> + +#include <osl/diagnose.h> +#include <svtools/htmlout.hxx> +#include <svtools/htmlkywd.hxx> +#include <svtools/HtmlWriter.hxx> +#include <rtl/strbuf.hxx> +#include <ndindex.hxx> +#include <fmtftn.hxx> +#include <txtftn.hxx> +#include <ftninfo.hxx> +#include <doc.hxx> +#include <ndtxt.hxx> +#include <charfmt.hxx> + +#include "swhtml.hxx" +#include "wrthtml.hxx" + +static sal_Int32 lcl_html_getNextPart( OUString& rPart, std::u16string_view aContent, + sal_Int32 nPos ) +{ + rPart.clear(); + sal_Int32 nLen = aContent.size(); + if( nPos >= nLen ) + { + nPos = -1; + } + else + { + bool bQuoted = false, bDone = false; + for( ; nPos < nLen && !bDone; nPos++ ) + { + sal_Unicode c = aContent[nPos]; + switch( c ) + { + case '\\': + if( bQuoted ) + rPart += OUStringChar( c ); + bQuoted = !bQuoted; + break; + + case ';': + if( bQuoted ) + rPart += OUStringChar( c ); + else + bDone = true; + bQuoted = false; + break; + + default: + rPart += OUStringChar( c ); + bQuoted = false; + break; + } + } + } + + return nPos; +} + +static sal_Int32 lcl_html_getEndNoteInfo( SwEndNoteInfo& rInfo, + std::u16string_view aContent, + bool bEndNote ) +{ + sal_Int32 nStrPos = 0; + for( int nPart = 0; nPart < 4; ++nPart ) + { + OUString aPart; + if( -1 != nStrPos ) + nStrPos = lcl_html_getNextPart( aPart, aContent, nStrPos ); + + switch( nPart ) + { + case 0: + rInfo.m_aFormat.SetNumberingType( bEndNote ? SVX_NUM_ROMAN_LOWER : SVX_NUM_ARABIC ); + if( !aPart.isEmpty() ) + rInfo.m_aFormat.SetNumberingType(SwHTMLParser::GetNumType( aPart, + rInfo.m_aFormat.GetNumberingType() )); + break; + + case 1: + rInfo.m_nFootnoteOffset = aPart.isEmpty() ? 0 : o3tl::narrowing<sal_uInt16>(aPart.toInt32()); + break; + + case 2: + rInfo.SetPrefix( aPart ); + break; + + case 3: + rInfo.SetSuffix( aPart ); + break; + } + } + + return nStrPos; +} + +void SwHTMLParser::FillEndNoteInfo( std::u16string_view aContent ) +{ + SwEndNoteInfo aInfo( m_xDoc->GetEndNoteInfo() ); + lcl_html_getEndNoteInfo( aInfo, aContent, true ); + m_xDoc->SetEndNoteInfo( aInfo ); +} + +void SwHTMLParser::FillFootNoteInfo( std::u16string_view aContent ) +{ + SwFootnoteInfo aInfo( m_xDoc->GetFootnoteInfo() ); + + sal_Int32 nStrPos = lcl_html_getEndNoteInfo( aInfo, aContent, false ); + + for( int nPart = 4; nPart < 8; ++nPart ) + { + OUString aPart; + if( -1 != nStrPos ) + nStrPos = lcl_html_getNextPart( aPart, aContent, nStrPos ); + + switch( nPart ) + { + case 4: + aInfo.m_eNum = FTNNUM_DOC; + if( !aPart.isEmpty() ) + { + switch( aPart[0] ) + { + case 'D': aInfo.m_eNum = FTNNUM_DOC; break; + case 'C': aInfo.m_eNum = FTNNUM_CHAPTER; break; + case 'P': aInfo.m_eNum = FTNNUM_PAGE; break; + } + } + break; + + case 5: + aInfo.m_ePos = FTNPOS_PAGE; + if( !aPart.isEmpty() ) + { + switch( aPart[0] ) + { + case 'C': aInfo.m_ePos = FTNPOS_CHAPTER; break; + case 'P': aInfo.m_ePos = FTNPOS_PAGE; break; + } + } + break; + + case 6: + aInfo.m_aQuoVadis = aPart; + break; + + case 7: + aInfo.m_aErgoSum = aPart; + break; + } + } + + m_xDoc->SetFootnoteInfo( aInfo ); +} + +void SwHTMLParser::InsertFootEndNote( const OUString& rName, bool bEndNote, + bool bFixed ) +{ + if( !m_pFootEndNoteImpl ) + m_pFootEndNoteImpl.reset(new SwHTMLFootEndNote_Impl); + + m_pFootEndNoteImpl->sName = rName; + if( m_pFootEndNoteImpl->sName.getLength() > 3 ) + m_pFootEndNoteImpl->sName = m_pFootEndNoteImpl->sName.copy( 0, m_pFootEndNoteImpl->sName.getLength() - 3 ); + m_pFootEndNoteImpl->sName = m_pFootEndNoteImpl->sName.toAsciiUpperCase(); + m_pFootEndNoteImpl->bEndNote = bEndNote; + m_pFootEndNoteImpl->bFixed = bFixed; + m_pFootEndNoteImpl->sContent.clear(); +} + +void SwHTMLParser::FinishFootEndNote() +{ + if( !m_pFootEndNoteImpl ) + return; + + SwFormatFootnote aFootnote( m_pFootEndNoteImpl->bEndNote ); + if( m_pFootEndNoteImpl->bFixed ) + aFootnote.SetNumStr( m_pFootEndNoteImpl->sContent ); + + m_xDoc->getIDocumentContentOperations().InsertPoolItem( *m_pPam, aFootnote ); + SwTextFootnote * const pTextFootnote = static_cast<SwTextFootnote *>( + m_pPam->GetPointNode().GetTextNode()->GetTextAttrForCharAt( + m_pPam->GetPoint()->GetContentIndex() - 1, RES_TXTATR_FTN ) ); + // In header and footer no footnotes can be inserted. + if (pTextFootnote) + m_pFootEndNoteImpl->aTextFootnotes.push_back(SwHTMLTextFootnote(m_pFootEndNoteImpl->sName,pTextFootnote)); + m_pFootEndNoteImpl->sName.clear(); + m_pFootEndNoteImpl->sContent.clear(); + m_pFootEndNoteImpl->bFixed = false; +} + +void SwHTMLParser::InsertFootEndNoteText() +{ + if( m_pFootEndNoteImpl && m_pFootEndNoteImpl->bFixed ) + m_pFootEndNoteImpl->sContent += aToken; +} + +SwNodeIndex *SwHTMLParser::GetFootEndNoteSection( const OUString& rName ) +{ + SwNodeIndex *pStartNodeIdx = nullptr; + + if (m_pFootEndNoteImpl) + { + OUString aName(rName.toAsciiUpperCase()); + + size_t nCount = m_pFootEndNoteImpl->aTextFootnotes.size(); + for(size_t i = 0; i < nCount; ++i) + { + if (m_pFootEndNoteImpl->aTextFootnotes[i].GetName() == aName) + { + pStartNodeIdx = const_cast<SwNodeIndex*>(m_pFootEndNoteImpl->aTextFootnotes[i].GetStartNode()); + m_pFootEndNoteImpl->aTextFootnotes.erase( m_pFootEndNoteImpl->aTextFootnotes.begin() + i ); + if (m_pFootEndNoteImpl->aTextFootnotes.empty()) + { + m_pFootEndNoteImpl.reset(); + } + + break; + } + } + } + + return pStartNodeIdx; +} + +SwHTMLWriter& OutHTML_SwFormatLineBreak(SwHTMLWriter& rWrt, const SfxPoolItem& rHt) +{ + const auto& rLineBreak = static_cast<const SwFormatLineBreak&>(rHt); + + HtmlWriter aWriter(rWrt.Strm(), rWrt.maNamespace); + aWriter.start(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr); + switch (rLineBreak.GetValue()) + { + case SwLineBreakClear::NONE: + aWriter.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, "none"); + break; + case SwLineBreakClear::LEFT: + aWriter.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, "left"); + break; + case SwLineBreakClear::RIGHT: + aWriter.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, "right"); + break; + case SwLineBreakClear::ALL: + aWriter.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, "all"); + break; + } + aWriter.end(); + return rWrt; +} + +SwHTMLWriter& OutHTML_SwFormatFootnote( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) +{ + SwFormatFootnote& rFormatFootnote = const_cast<SwFormatFootnote&>(static_cast<const SwFormatFootnote&>(rHt)); + SwTextFootnote *pTextFootnote = rFormatFootnote.GetTextFootnote(); + if( !pTextFootnote ) + return rWrt; + + OUString sFootnoteName, sClass; + size_t nPos; + if( rFormatFootnote.IsEndNote() ) + { + nPos = rWrt.m_xFootEndNotes ? rWrt.m_xFootEndNotes->size() : 0; + OSL_ENSURE( nPos == static_cast<size_t>(rWrt.m_nFootNote + rWrt.m_nEndNote), + "OutHTML_SwFormatFootnote: wrong position" ); + sClass = OOO_STRING_SVTOOLS_HTML_sdendnote_anc; + sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdendnote + OUString::number( static_cast<sal_Int32>(++rWrt.m_nEndNote) ); + } + else + { + nPos = rWrt.m_nFootNote; + sClass = OOO_STRING_SVTOOLS_HTML_sdfootnote_anc; + sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote + OUString::number( static_cast<sal_Int32>(++rWrt.m_nFootNote)); + } + + if( !rWrt.m_xFootEndNotes ) + rWrt.m_xFootEndNotes.emplace(); + rWrt.m_xFootEndNotes->insert( rWrt.m_xFootEndNotes->begin() + nPos, pTextFootnote ); + + OStringBuffer sOut; + OString aTag = rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor; + sOut.append("<" + aTag + " " OOO_STRING_SVTOOLS_HTML_O_class "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), sClass ); + sOut.append("\" " OOO_STRING_SVTOOLS_HTML_O_name "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), sFootnoteName ); + sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_anchor "\" " + OOO_STRING_SVTOOLS_HTML_O_href "=\"#"); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), sFootnoteName ); + sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_symbol "\""); + if( !rFormatFootnote.GetNumStr().isEmpty() ) + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_sdfixed); + sOut.append(">"); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_superscript )); + + HTMLOutFuncs::Out_String( rWrt.Strm(), rFormatFootnote.GetViewNumStr(*rWrt.m_pDoc, nullptr) ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_superscript), false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor), false ); + + return rWrt; +} + +void SwHTMLWriter::OutFootEndNotes() +{ + OSL_ENSURE( m_xFootEndNotes, + "SwHTMLWriter::OutFootEndNotes(): unnecessary call" ); + if( !m_xFootEndNotes ) + return; + +#if OSL_DEBUG_LEVEL > 0 + sal_uInt16 nFootnote = m_nFootNote, nEn = m_nEndNote; +#endif + m_nFootNote = 0; + m_nEndNote = 0; + + for( auto *pTextFootnote : *m_xFootEndNotes ) + { + m_pFormatFootnote = &pTextFootnote->GetFootnote(); + + OUString sFootnoteName; + if( m_pFormatFootnote->IsEndNote() ) + { + sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdendnote + OUString::number(static_cast<sal_Int32>(++m_nEndNote)); + } + else + { + sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote + OUString::number(static_cast<sal_Int32>(++m_nFootNote)); + } + + if (IsLFPossible()) + OutNewLine(); + OString sOut = + "<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_division + " " OOO_STRING_SVTOOLS_HTML_O_id "=\""; + Strm().WriteOString( sOut ); + HTMLOutFuncs::Out_String( Strm(), sFootnoteName ); + Strm().WriteOString( "\">" ); + + SetLFPossible(true); + IncIndentLevel(); // indent content of <DIV> + + OSL_ENSURE( pTextFootnote, "SwHTMLWriter::OutFootEndNotes: SwTextFootnote is missing" ); + const SwNodeIndex *pSttNdIdx = pTextFootnote->GetStartNode(); + OSL_ENSURE( pSttNdIdx, + "SwHTMLWriter::OutFootEndNotes: StartNode-Index is missing" ); + if( pSttNdIdx ) + { + HTMLSaveData aSaveData( *this, pSttNdIdx->GetIndex()+1, + pSttNdIdx->GetNode().EndOfSectionIndex(), false ); + Out_SwDoc( m_pCurrentPam.get() ); + } + + DecIndentLevel(); // indent content of <DIV> + if (IsLFPossible()) + OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false ); + SetLFPossible(true); + + OSL_ENSURE( !m_pFormatFootnote, + "SwHTMLWriter::OutFootEndNotes: Footnote was not output" ); + if( m_pFormatFootnote ) + { + if( m_pFormatFootnote->IsEndNote() ) + m_nEndNote++; + else + m_nFootNote++; + + m_pFormatFootnote = nullptr; + } + } + +#if OSL_DEBUG_LEVEL > 0 + OSL_ENSURE( nFootnote == m_nFootNote, + "SwHTMLWriter::OutFootEndNotes: Number of footnotes does not match" ); + OSL_ENSURE( nEn == m_nEndNote, + "SwHTMLWriter::OutFootEndNotes: Number of endnotes does not match" ); +#endif + + m_xFootEndNotes.reset(); + m_nFootNote = m_nEndNote = 0; +} + +OUString SwHTMLWriter::GetFootEndNoteSym( const SwFormatFootnote& rFormatFootnote ) +{ + const SwEndNoteInfo * pInfo = nullptr; + if( rFormatFootnote.GetNumStr().isEmpty() ) + pInfo = rFormatFootnote.IsEndNote() ? &m_pDoc->GetEndNoteInfo() + : &m_pDoc->GetFootnoteInfo(); + + OUString sRet; + if( pInfo ) + sRet = pInfo->GetPrefix(); + sRet += rFormatFootnote.GetViewNumStr(*m_pDoc, nullptr); + if( pInfo ) + sRet += pInfo->GetSuffix(); + + return sRet; +} + +void SwHTMLWriter::OutFootEndNoteSym( const SwFormatFootnote& rFormatFootnote, + const OUString& rNum, + sal_uInt16 nScript ) +{ + const SwEndNoteInfo *pInfo; + + OUString sFootnoteName, sClass; + if( rFormatFootnote.IsEndNote() ) + { + sClass = OOO_STRING_SVTOOLS_HTML_sdendnote_sym; + sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdendnote + + OUString::number(static_cast<sal_Int32>(m_nEndNote)); + pInfo = &m_pDoc->GetEndNoteInfo(); + } + else + { + sClass = OOO_STRING_SVTOOLS_HTML_sdfootnote_sym; + sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote + + OUString::number(static_cast<sal_Int32>(m_nFootNote)); + pInfo = &m_pDoc->GetFootnoteInfo(); + } + + const SwCharFormat *pSymCharFormat = pInfo->GetCharFormat( *m_pDoc ); + if( pSymCharFormat && 0 != m_aScriptTextStyles.count( pSymCharFormat->GetName() ) ) + { + switch( nScript ) + { + case CSS1_OUTMODE_WESTERN: + sClass += "-western"; + break; + case CSS1_OUTMODE_CJK: + sClass += "-cjk"; + break; + case CSS1_OUTMODE_CTL: + sClass += "-ctl"; + break; + } + } + + OStringBuffer sOut("<" + + GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor " " + OOO_STRING_SVTOOLS_HTML_O_class "=\""); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), sClass ); + sOut.append("\" " OOO_STRING_SVTOOLS_HTML_O_name "=\""); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), sFootnoteName ); + sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_symbol "\" " + OOO_STRING_SVTOOLS_HTML_O_href "=\"#"); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), sFootnoteName ); + sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_anchor "\">"); + Strm().WriteOString( sOut ); + sOut.setLength(0); + + HTMLOutFuncs::Out_String( Strm(), rNum ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor), false ); +} + +static int lcl_html_fillEndNoteInfo( const SwEndNoteInfo& rInfo, + OUString *pParts, + bool bEndNote ) +{ + int nParts = 0; + sal_Int16 eFormat = rInfo.m_aFormat.GetNumberingType(); + if( (bEndNote ? SVX_NUM_ROMAN_LOWER : SVX_NUM_ARABIC) != eFormat ) + { + const char *pStr = SwHTMLWriter::GetNumFormat( eFormat ); + if( pStr ) + { + pParts[0] = OUString::createFromAscii( pStr ); + nParts = 1; + } + } + if( rInfo.m_nFootnoteOffset > 0 ) + { + pParts[1] = OUString::number(rInfo.m_nFootnoteOffset); + nParts = 2; + } + if( !rInfo.GetPrefix().isEmpty() ) + { + pParts[2] = rInfo.GetPrefix(); + nParts = 3; + } + if( !rInfo.GetSuffix().isEmpty() ) + { + pParts[3] = rInfo.GetSuffix(); + nParts = 4; + } + + return nParts; +} + +static void lcl_html_outFootEndNoteInfo( SwHTMLWriter& rWrt, OUString const *pParts, + int nParts, const char *pName ) +{ + OUStringBuffer aContent; + for( int i=0; i<nParts; ++i ) + { + OUString aTmp( pParts[i] ); + aTmp = aTmp.replaceAll( "\\", "\\\\" ); + aTmp = aTmp.replaceAll( ";", "\\;" ); + if( i > 0 ) + aContent.append(";"); + aContent.append(aTmp); + } + + rWrt.OutNewLine(); + OString sOut = + "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_meta " " + OOO_STRING_SVTOOLS_HTML_O_name "=\"" + pName + + "\" " OOO_STRING_SVTOOLS_HTML_O_content "=\""; + rWrt.Strm().WriteOString( sOut ); + HTMLOutFuncs::Out_String( rWrt.Strm(), aContent.makeStringAndClear() ); + rWrt.Strm().WriteOString( "\">" ); +} + +void SwHTMLWriter::OutFootEndNoteInfo() +{ + // Number type (1 or i) + // Offset (0) + // Before it + // Behind it + // Doc/Page/Chap (D) + // Position (S) + // Next page + // Beginning + + { + const SwFootnoteInfo& rInfo = m_pDoc->GetFootnoteInfo(); + OUString aParts[8]; + int nParts = lcl_html_fillEndNoteInfo( rInfo, aParts, false ); + if( rInfo.m_eNum != FTNNUM_DOC ) + { + aParts[4] = rInfo.m_eNum == FTNNUM_CHAPTER ? std::u16string_view( u"C" ) : std::u16string_view( u"P" ); + nParts = 5; + } + if( rInfo.m_ePos != FTNPOS_PAGE) + { + aParts[5] = "C"; + nParts = 6; + } + if( !rInfo.m_aQuoVadis.isEmpty() ) + { + aParts[6] = rInfo.m_aQuoVadis; + nParts = 7; + } + if( !rInfo.m_aErgoSum.isEmpty() ) + { + aParts[7] = rInfo.m_aErgoSum; + nParts = 8; + } + if( nParts > 0 ) + lcl_html_outFootEndNoteInfo( *this, aParts, nParts, + OOO_STRING_SVTOOLS_HTML_META_sdfootnote ); + } + + { + const SwEndNoteInfo& rInfo = m_pDoc->GetEndNoteInfo(); + OUString aParts[4]; + const int nParts = lcl_html_fillEndNoteInfo( rInfo, aParts, true ); + if( nParts > 0 ) + lcl_html_outFootEndNoteInfo( *this, aParts, nParts, + OOO_STRING_SVTOOLS_HTML_META_sdendnote ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |