summaryrefslogtreecommitdiffstats
path: root/sw/source/filter/html/css1atr.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 05:54:39 +0000
commit267c6f2ac71f92999e969232431ba04678e7437e (patch)
tree358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/filter/html/css1atr.cxx
parentInitial commit. (diff)
downloadlibreoffice-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/css1atr.cxx')
-rw-r--r--sw/source/filter/html/css1atr.cxx3671
1 files changed, 3671 insertions, 0 deletions
diff --git a/sw/source/filter/html/css1atr.cxx b/sw/source/filter/html/css1atr.cxx
new file mode 100644
index 0000000000..30ba8d3c0a
--- /dev/null
+++ b/sw/source/filter/html/css1atr.cxx
@@ -0,0 +1,3671 @@
+/* -*- 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 <hintids.hxx>
+#include <comphelper/string.hxx>
+#include <comphelper/xmlencode.hxx>
+#include <vcl/svapp.hxx>
+#include <svl/whiter.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/crossedoutitem.hxx>
+#include <editeng/blinkitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/adjustitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brushitem.hxx>
+#include <editeng/formatbreakitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <svx/xoutbmp.hxx>
+#include <svx/svdobj.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svtools/htmlout.hxx>
+#include <svtools/htmlkywd.hxx>
+#include <svl/urihelper.hxx>
+#include <unotools/charclass.hxx>
+#include <i18nlangtag/languagetag.hxx>
+#include <charfmt.hxx>
+#include <fmtclds.hxx>
+#include <fmtcol.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtlsplt.hxx>
+#include <pagedesc.hxx>
+#include <fmtanchr.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <viewsh.hxx>
+#include <viewopt.hxx>
+#include <swtable.hxx>
+// NOTES
+#include <ftninfo.hxx>
+#include <ftnidx.hxx>
+#include <txtftn.hxx>
+#include <fmtftn.hxx>
+// FOOTNOTES
+#include <doc.hxx>
+#include <IDocumentSettingAccess.hxx>
+#include <IDocumentLayoutAccess.hxx>
+#include <swerror.h>
+#include <paratr.hxx>
+#include <frmatr.hxx>
+#include <poolfmt.hxx>
+#include "css1kywd.hxx"
+#include "wrthtml.hxx"
+#include "htmlnum.hxx"
+#include "css1atr.hxx"
+
+#include <IDocumentStylePoolAccess.hxx>
+#include <numrule.hxx>
+#include <o3tl/typed_flags_set.hxx>
+#include <o3tl/unit_conversion.hxx>
+
+#include <rtl/strbuf.hxx>
+#include <osl/diagnose.h>
+
+using namespace css;
+using editeng::SvxBorderLine;
+
+#define HTML_HEADSPACE (12*20)
+
+namespace {
+
+enum class Css1FrameSize {
+ NONE = 0x00,
+ Width = 0x01,
+ MinHeight = 0x02,
+ FixHeight = 0x04,
+ Pixel = 0x10,
+};
+
+}
+
+namespace o3tl {
+ template<> struct typed_flags<Css1FrameSize> : is_typed_flags<Css1FrameSize, 0x17> {};
+}
+
+#define DOT_LEADERS_MAX_WIDTH 18
+
+static SwHTMLWriter& OutCSS1_SwFormat( SwHTMLWriter& rWrt, const SwFormat& rFormat,
+ IDocumentStylePoolAccess /*SwDoc*/ *pDoc, SwDoc *pTemplate );
+static SwHTMLWriter& OutCSS1_SwPageDesc( SwHTMLWriter& rWrt, const SwPageDesc& rFormat,
+ IDocumentStylePoolAccess /*SwDoc*/ *pDoc, SwDoc *pTemplate,
+ sal_uInt16 nRefPoolId, bool bExtRef,
+ bool bPseudo=true );
+static SwHTMLWriter& OutCSS1_SwFootnoteInfo( SwHTMLWriter& rWrt, const SwEndNoteInfo& rInfo,
+ SwDoc *pDoc, bool bHasNotes, bool bEndNote );
+static void OutCSS1_SwFormatDropAttrs( SwHTMLWriter& rHWrt,
+ const SwFormatDrop& rDrop,
+ const SfxItemSet *pCharFormatItemSet=nullptr );
+static SwHTMLWriter& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( SwHTMLWriter& rWrt,
+ const SvxUnderlineItem *pUItem,
+ const SvxOverlineItem *pOItem,
+ const SvxCrossedOutItem *pCOItem,
+ const SvxBlinkItem *pBItem );
+static SwHTMLWriter& OutCSS1_SvxFontWeight( SwHTMLWriter& rWrt, const SfxPoolItem& rHt );
+static SwHTMLWriter& OutCSS1_SvxPosture( SwHTMLWriter& rWrt, const SfxPoolItem& rHt );
+static SwHTMLWriter& OutCSS1_SvxULSpace( SwHTMLWriter& rWrt, const SfxPoolItem& rHt );
+static SwHTMLWriter& OutCSS1_SvxFirstLineIndent(SwHTMLWriter& rWrt, const SfxPoolItem& rHt);
+static SwHTMLWriter& OutCSS1_SvxTextLeftMargin(SwHTMLWriter& rWrt, const SfxPoolItem& rHt);
+static SwHTMLWriter& OutCSS1_SvxRightMargin(SwHTMLWriter& rWrt, const SfxPoolItem& rHt);
+static SwHTMLWriter& OutCSS1_SvxLRSpace( SwHTMLWriter& rWrt, const SfxPoolItem& rHt );
+static SwHTMLWriter& OutCSS1_SvxULSpace_SvxLRSpace( SwHTMLWriter& rWrt,
+ const SvxULSpaceItem *pULSpace,
+ const SvxLRSpaceItem *pLRSpace );
+static SwHTMLWriter& OutCSS1_SvxULSpace_SvxLRSpace( SwHTMLWriter& rWrt,
+ const SfxItemSet& rItemSet );
+static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& rWrt, const SfxPoolItem& rHt,
+ sw::Css1Background nMode,
+ const OUString *pGraphicName );
+static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& rWrt, const SfxPoolItem& rHt );
+static SwHTMLWriter& OutCSS1_SwFormatFrameSize( SwHTMLWriter& rWrt, const SfxPoolItem& rHt,
+ Css1FrameSize nMode );
+static SwHTMLWriter& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( SwHTMLWriter& rWrt,
+ const SfxItemSet& rItemSet,
+ bool bDeep );
+static SwHTMLWriter& OutCSS1_SwFormatLayoutSplit( SwHTMLWriter& rWrt, const SfxPoolItem& rHt );
+
+namespace
+{
+
+const char sCSS1_rule_end[] = " }";
+const char sCSS1_span_tag_end[] = "\">";
+const char cCSS1_style_opt_end = '\"';
+
+const char* const sHTML_FTN_fontheight = "57%";
+
+OString lclConvToHex(sal_uInt16 nHex)
+{
+ char aNToABuf[] = "00";
+
+ // set pointer to end of buffer
+ char *pStr = aNToABuf + (sizeof(aNToABuf)-1);
+ for( sal_uInt8 n = 0; n < 2; ++n )
+ {
+ *(--pStr) = static_cast<char>(nHex & 0xf ) + 48;
+ if( *pStr > '9' )
+ *pStr += 39;
+ nHex >>= 4;
+ }
+
+ return OString(aNToABuf, 2);
+}
+}
+
+bool IgnorePropertyForReqIF(bool bReqIF, std::string_view rProperty, std::string_view rValue,
+ std::optional<sw::Css1Background> oMode)
+{
+ if (!bReqIF)
+ return false;
+
+ if (oMode.has_value() && *oMode != sw::Css1Background::TableCell)
+ {
+ // Table or row.
+ if (rProperty == sCSS1_P_background && rValue == "transparent")
+ {
+ // This is the default already.
+ return true;
+ }
+
+ return false;
+ }
+
+ // Only allow these two keys, nothing else in ReqIF mode.
+ if (rProperty == sCSS1_P_text_decoration)
+ {
+ // Deny other text-decoration values (e.g. "none").
+ if (rValue == "underline" || rValue == "line-through")
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ if (rProperty == sCSS1_P_color)
+ return false;
+
+ return true;
+}
+
+OString GetCSS1_Color(const Color& rColor)
+{
+ return "#" + lclConvToHex(rColor.GetRed()) + lclConvToHex(rColor.GetGreen()) + lclConvToHex(rColor.GetBlue());
+}
+
+namespace {
+
+class SwCSS1OutMode
+{
+ SwHTMLWriter& rWrt;
+ sal_uInt16 nOldMode;
+
+public:
+
+ SwCSS1OutMode( SwHTMLWriter& rHWrt, sal_uInt16 nMode,
+ const OUString *pSelector ) :
+ rWrt( rHWrt ),
+ nOldMode( rHWrt.m_nCSS1OutMode )
+ {
+ rWrt.m_nCSS1OutMode = nMode;
+ rWrt.m_bFirstCSS1Property = true;
+ if( pSelector )
+ rWrt.m_aCSS1Selector = *pSelector;
+ }
+
+ ~SwCSS1OutMode()
+ {
+ rWrt.m_nCSS1OutMode = nOldMode;
+ }
+};
+
+}
+
+void SwHTMLWriter::OutCSS1_Property( std::string_view pProp,
+ std::string_view sVal,
+ const OUString *pSVal,
+ std::optional<sw::Css1Background> oMode )
+{
+ OString aPropertyValue(sVal);
+ if (aPropertyValue.isEmpty() && pSVal)
+ {
+ aPropertyValue = OUStringToOString(*pSVal, RTL_TEXTENCODING_UTF8);
+ }
+ if (IgnorePropertyForReqIF(mbReqIF, pProp, aPropertyValue, oMode))
+ return;
+
+ OStringBuffer sOut;
+
+ if( m_bFirstCSS1Rule && (m_nCSS1OutMode & CSS1_OUTMODE_RULE_ON)!=0 )
+ {
+ m_bFirstCSS1Rule = false;
+ OutNewLine();
+ sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_style " "
+ OOO_STRING_SVTOOLS_HTML_O_type "=\"text/css\">");
+ // Optional CSS2 code for dot leaders (dotted line between the Table of Contents titles and page numbers):
+ // (More information: http://www.w3.org/Style/Examples/007/leaders.en.html)
+ //
+ // p.leaders {
+ // /* FIXME:
+ // (1) dots line up vertically only in the paragraphs with the same alignment/level
+ // (2) max-width = 18 cm instead of 80em; possible improvement with the new CSS3 calc() */
+ // max-width: 18cm; /* note: need to overwrite max-width with max-width - border-left_of_the_actual_paragraph */
+ // padding: 0;
+ // overflow-x: hidden;
+ // line-height: 120%; /* note: avoid HTML scrollbars and missing descenders of the letters */
+ // }
+ // p.leaders:after {
+ // float: left;
+ // width: 0;
+ // white-space: nowrap;
+ // content: ". . . . . . . . . . . . . . . . . . ...";
+ // }
+ // p.leaders span:first-child {
+ // padding-right: 0.33em;
+ // background: white;
+ // }
+ // p.leaders span + span {
+ // float: right;
+ // padding-left: 0.33em;
+ // background: white;
+ // position: relative;
+ // z-index: 1
+ // }
+
+ if (m_bCfgPrintLayout) {
+ sOut.append(
+ "p." sCSS2_P_CLASS_leaders "{max-width:" + OString::number(DOT_LEADERS_MAX_WIDTH) +
+ "cm;padding:0;overflow-x:hidden;line-height:120%}"
+ "p." sCSS2_P_CLASS_leaders ":after{float:left;width:0;white-space:nowrap;content:\"");
+ for (int i = 0; i < 100; i++ )
+ sOut.append(". ");
+ sOut.append(
+ "\"}p." sCSS2_P_CLASS_leaders " span:first-child{padding-right:0.33em;background:white}"
+ "p." sCSS2_P_CLASS_leaders " span+span{float:right;padding-left:0.33em;"
+ "background:white;position:relative;z-index:1}");
+ }
+ Strm().WriteOString( sOut );
+ sOut.setLength(0);
+
+ IncIndentLevel();
+ }
+
+ if( m_bFirstCSS1Property )
+ {
+ switch( m_nCSS1OutMode & CSS1_OUTMODE_ANY_ON )
+ {
+ case CSS1_OUTMODE_SPAN_TAG_ON:
+ case CSS1_OUTMODE_SPAN_TAG1_ON:
+ if( m_bTagOn )
+ {
+ sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_span
+ " " OOO_STRING_SVTOOLS_HTML_O_style "=\"");
+ }
+ else
+ {
+ HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false );
+ return;
+ }
+ break;
+
+ case CSS1_OUTMODE_RULE_ON:
+ {
+ OutNewLine();
+ sOut.append(OUStringToOString(m_aCSS1Selector, RTL_TEXTENCODING_UTF8) + " { ");
+ }
+ break;
+
+ case CSS1_OUTMODE_STYLE_OPT_ON:
+ sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_style "=\"");
+ break;
+ }
+ m_bFirstCSS1Property = false;
+ }
+ else
+ {
+ sOut.append("; ");
+ }
+
+ sOut.append(pProp + OString::Concat(": "));
+ if( m_nCSS1OutMode & CSS1_OUTMODE_ENCODE )
+ {
+ // for STYLE-Option encode string
+ Strm().WriteOString( sOut );
+ sOut.setLength(0);
+ if( !sVal.empty() )
+ HTMLOutFuncs::Out_String( Strm(), OUString::createFromAscii(sVal) );
+ else if( pSVal )
+ HTMLOutFuncs::Out_String( Strm(), *pSVal );
+ }
+ else
+ {
+ // for STYLE-Tag print string directly
+ sOut.append(aPropertyValue);
+ }
+
+ if (!sOut.isEmpty())
+ Strm().WriteOString( sOut );
+}
+
+static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal,
+ FieldUnit eUnit)
+{
+ if( nVal < 0 )
+ {
+ // special-case sign symbol
+ nVal = -nVal;
+ rOut.append('-');
+ }
+
+ o3tl::Length eTo;
+ int nFac; // used to get specific number of decimals
+ std::string_view pUnit;
+ switch( eUnit )
+ {
+ case FieldUnit::MM_100TH:
+ OSL_ENSURE( FieldUnit::MM == eUnit, "Measuring unit not supported" );
+ [[fallthrough]];
+ case FieldUnit::MM:
+ eTo = o3tl::Length::mm;
+ nFac = 100;
+ pUnit = sCSS1_UNIT_mm;
+ break;
+
+ case FieldUnit::M:
+ case FieldUnit::KM:
+ OSL_ENSURE( FieldUnit::CM == eUnit, "Measuring unit not supported" );
+ [[fallthrough]];
+ case FieldUnit::CM:
+ eTo = o3tl::Length::cm;
+ nFac = 100;
+ pUnit = sCSS1_UNIT_cm;
+ break;
+
+ case FieldUnit::TWIP:
+ OSL_ENSURE( FieldUnit::POINT == eUnit, "Measuring unit not supported" );
+ [[fallthrough]];
+ case FieldUnit::POINT:
+ eTo = o3tl::Length::pt;
+ nFac = 10;
+ pUnit = sCSS1_UNIT_pt;
+ break;
+
+ case FieldUnit::PICA:
+ eTo = o3tl::Length::pc;
+ nFac = 100;
+ pUnit = sCSS1_UNIT_pc;
+ break;
+
+ case FieldUnit::NONE:
+ case FieldUnit::FOOT:
+ case FieldUnit::MILE:
+ case FieldUnit::CUSTOM:
+ case FieldUnit::PERCENT:
+ case FieldUnit::INCH:
+ default:
+ OSL_ENSURE( FieldUnit::INCH == eUnit, "Measuring unit not supported" );
+ eTo = o3tl::Length::in;
+ nFac = 100;
+ pUnit = sCSS1_UNIT_inch;
+ break;
+ }
+
+ sal_Int64 nResult = o3tl::convert(nVal * nFac, o3tl::Length::twip, eTo);
+ rOut.append(nResult/nFac);
+ if ((nResult % nFac) != 0)
+ {
+ rOut.append('.');
+ while (nFac > 1 && (nResult % nFac) != 0)
+ {
+ nFac /= 10;
+ rOut.append((nResult / nFac) % 10);
+ }
+ }
+
+ rOut.append(pUnit);
+}
+
+void SwHTMLWriter::OutCSS1_UnitProperty( std::string_view pProp, tools::Long nVal )
+{
+ OStringBuffer sOut;
+ AddUnitPropertyValue(sOut, nVal, m_eCSS1Unit);
+ OutCSS1_PropertyAscii(pProp, sOut);
+}
+
+void SwHTMLWriter::OutCSS1_PixelProperty( std::string_view pProp, tools::Long nTwips )
+{
+ OString sOut(OString::number(ToPixel(nTwips)) + sCSS1_UNIT_px);
+ OutCSS1_PropertyAscii(pProp, sOut);
+}
+
+void SwHTMLWriter::OutStyleSheet( const SwPageDesc& rPageDesc )
+{
+ m_bFirstCSS1Rule = true;
+
+// Feature: PrintExt
+ if( IsHTMLMode(HTMLMODE_PRINT_EXT) )
+ {
+ const SwPageDesc *pFirstPageDesc = nullptr;
+ sal_uInt16 nFirstRefPoolId = RES_POOLPAGE_HTML;
+ m_bCSS1IgnoreFirstPageDesc = true;
+
+ // First we try to guess how the document is constructed.
+ // Allowed are only the templates: HTML, 1st page, left page, and right page.
+ // A first page is only exported, if it matches the template "1st page".
+ // Left and right pages are only exported, if their templates are linked.
+ // If other templates are used, only very simple cases are exported.
+ const SwPageDesc *pPageDesc = &rPageDesc;
+ const SwPageDesc *pFollow = rPageDesc.GetFollow();
+ if( RES_POOLPAGE_FIRST == pPageDesc->GetPoolFormatId() &&
+ pFollow != pPageDesc &&
+ !IsPoolUserFormat( pFollow->GetPoolFormatId() ) )
+ {
+ // the document has a first page
+ pFirstPageDesc = pPageDesc;
+ pPageDesc = pFollow;
+ pFollow = pPageDesc->GetFollow();
+ }
+
+ IDocumentStylePoolAccess* pStylePoolAccess = &getIDocumentStylePoolAccess();
+ if( pPageDesc == pFollow )
+ {
+ // The document is one-sided; no matter what page, we do not create a 2-sided doc.
+ // The attribute is exported relative to the HTML page template.
+ OutCSS1_SwPageDesc( *this, *pPageDesc, pStylePoolAccess, m_xTemplate.get(),
+ RES_POOLPAGE_HTML, true, false );
+ nFirstRefPoolId = pFollow->GetPoolFormatId();
+ }
+ else if( (RES_POOLPAGE_LEFT == pPageDesc->GetPoolFormatId() &&
+ RES_POOLPAGE_RIGHT == pFollow->GetPoolFormatId()) ||
+ (RES_POOLPAGE_RIGHT == pPageDesc->GetPoolFormatId() &&
+ RES_POOLPAGE_LEFT == pFollow->GetPoolFormatId()) )
+ {
+ // the document is double-sided
+ OutCSS1_SwPageDesc( *this, *pPageDesc, pStylePoolAccess, m_xTemplate.get(),
+ RES_POOLPAGE_HTML, true );
+ OutCSS1_SwPageDesc( *this, *pFollow, pStylePoolAccess, m_xTemplate.get(),
+ RES_POOLPAGE_HTML, true );
+ nFirstRefPoolId = RES_POOLPAGE_RIGHT;
+ m_bCSS1IgnoreFirstPageDesc = false;
+ }
+ // other cases we miss
+
+ if( pFirstPageDesc )
+ OutCSS1_SwPageDesc( *this, *pFirstPageDesc, pStylePoolAccess, m_xTemplate.get(),
+ nFirstRefPoolId, false );
+ }
+
+ // The text body style has to be exported always (if it is changed compared
+ // to the template), because it is used as reference for any style
+ // that maps to <P>, and that's especially the standard style
+ getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT, false );
+
+ // the Default-TextStyle is not also exported !!
+ // 0-Style is the Default; is never exported !!
+ const size_t nTextFormats = m_pDoc->GetTextFormatColls()->size();
+ for( size_t i = 1; i < nTextFormats; ++i )
+ {
+ const SwTextFormatColl* pColl = (*m_pDoc->GetTextFormatColls())[i];
+ sal_uInt16 nPoolId = pColl->GetPoolFormatId();
+ if( nPoolId == RES_POOLCOLL_TEXT || m_pDoc->IsUsed( *pColl ) )
+ OutCSS1_SwFormat( *this, *pColl, &m_pDoc->getIDocumentStylePoolAccess(), m_xTemplate.get() );
+ }
+
+ // the Default-TextStyle is not also exported !!
+ const size_t nCharFormats = m_pDoc->GetCharFormats()->size();
+ for( size_t i = 1; i < nCharFormats; ++i )
+ {
+ const SwCharFormat *pCFormat = (*m_pDoc->GetCharFormats())[i];
+ sal_uInt16 nPoolId = pCFormat->GetPoolFormatId();
+ if( nPoolId == RES_POOLCHR_INET_NORMAL ||
+ nPoolId == RES_POOLCHR_INET_VISIT ||
+ m_pDoc->IsUsed( *pCFormat ) )
+ OutCSS1_SwFormat( *this, *pCFormat, &m_pDoc->getIDocumentStylePoolAccess(), m_xTemplate.get() );
+ }
+
+ bool bHasEndNotes {false};
+ bool bHasFootNotes {false};
+ const SwFootnoteIdxs& rIdxs = m_pDoc->GetFootnoteIdxs();
+ for( auto pIdx : rIdxs )
+ {
+ if( pIdx->GetFootnote().IsEndNote() )
+ {
+ bHasEndNotes = true;
+ if (bHasFootNotes)
+ break;
+ }
+ else
+ {
+ bHasFootNotes = true;
+ if (bHasEndNotes)
+ break;
+ }
+ }
+ OutCSS1_SwFootnoteInfo( *this, m_pDoc->GetFootnoteInfo(), m_pDoc, bHasFootNotes, false );
+ OutCSS1_SwFootnoteInfo( *this, m_pDoc->GetEndNoteInfo(), m_pDoc, bHasEndNotes, true );
+
+ if( !m_bFirstCSS1Rule )
+ {
+ DecIndentLevel();
+
+ OutNewLine();
+ HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_style), false );
+ }
+ else
+ {
+ m_bFirstCSS1Rule = false;
+ }
+
+ m_nDfltTopMargin = 0;
+ m_nDfltBottomMargin = 0;
+}
+
+// if pPseudo is set, Styles-Sheets will be exported;
+// otherwise we only search for Token and Class for a Format
+sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rToken,
+ OUString& rClass, sal_uInt16& rRefPoolId,
+ OUString *pPseudo )
+{
+ sal_uInt16 nDeep = 0;
+ rToken.clear();
+ rClass.clear();
+ rRefPoolId = 0;
+ if( pPseudo )
+ pPseudo->clear();
+
+ bool bChrFormat = RES_CHRFMT==pFormat->Which();
+
+ // search formats above for the nearest standard or HTML-Tag template
+ const SwFormat *pPFormat = pFormat;
+ while( pPFormat && !pPFormat->IsDefault() )
+ {
+ bool bStop = false;
+ sal_uInt16 nPoolId = pPFormat->GetPoolFormatId();
+ if( USER_FMT & nPoolId )
+ {
+ // user templates
+ const OUString& aNm(pPFormat->GetName());
+
+ if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_blockquote)
+ {
+ rRefPoolId = RES_POOLCOLL_HTML_BLOCKQUOTE;
+ rToken = OOO_STRING_SVTOOLS_HTML_blockquote ""_ostr;
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_citation)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_CITATION;
+ rToken = OOO_STRING_SVTOOLS_HTML_citation ""_ostr;
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_code)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_CODE;
+ rToken = OOO_STRING_SVTOOLS_HTML_code ""_ostr;
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_definstance)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_DEFINSTANCE;
+ rToken = OOO_STRING_SVTOOLS_HTML_definstance ""_ostr;
+ }
+ else if (!bChrFormat && (aNm == OOO_STRING_SVTOOLS_HTML_dd ||
+ aNm == OOO_STRING_SVTOOLS_HTML_dt))
+ {
+ sal_uInt16 nDefListLvl = GetDefListLvl(aNm, nPoolId);
+ // Export the templates DD 1/DT 1,
+ // but none of their derived templates,
+ // also not DD 2/DT 2 etc.
+ if (nDefListLvl)
+ {
+ if (pPseudo && (nDeep || (nDefListLvl & 0x0fff) > 1))
+ {
+ bStop = true;
+ }
+ else if (nDefListLvl & HTML_DLCOLL_DD)
+ {
+ rRefPoolId = RES_POOLCOLL_HTML_DD;
+ rToken = OOO_STRING_SVTOOLS_HTML_dd ""_ostr;
+ }
+ else
+ {
+ rRefPoolId = RES_POOLCOLL_HTML_DT;
+ rToken = OOO_STRING_SVTOOLS_HTML_dt ""_ostr;
+ }
+ }
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_emphasis)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_EMPHASIS;
+ rToken = OOO_STRING_SVTOOLS_HTML_emphasis ""_ostr;
+ }
+ else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_horzrule)
+ {
+ // do not export HR !
+ bStop = (nDeep==0);
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_keyboard)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_KEYBOARD;
+ rToken = OOO_STRING_SVTOOLS_HTML_keyboard ""_ostr;
+ }
+ else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_listing)
+ {
+ // Export Listings as PRE or PRE-derived template
+ rToken = OOO_STRING_SVTOOLS_HTML_preformtxt ""_ostr;
+ rRefPoolId = RES_POOLCOLL_HTML_PRE;
+ nDeep = CSS1_FMT_CMPREF;
+ }
+ else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_preformtxt)
+ {
+ rRefPoolId = RES_POOLCOLL_HTML_PRE;
+ rToken = OOO_STRING_SVTOOLS_HTML_preformtxt ""_ostr;
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_sample)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_SAMPLE;
+ rToken = OOO_STRING_SVTOOLS_HTML_sample ""_ostr;
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_strong)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_STRONG;
+ rToken = OOO_STRING_SVTOOLS_HTML_strong ""_ostr;
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_teletype)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_TELETYPE;
+ rToken = OOO_STRING_SVTOOLS_HTML_teletype ""_ostr;
+ }
+ else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_variable)
+ {
+ rRefPoolId = RES_POOLCHR_HTML_VARIABLE;
+ rToken = OOO_STRING_SVTOOLS_HTML_variable ""_ostr;
+ }
+ else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_xmp)
+ {
+ // export XMP as PRE (but not the template as Style)
+ rToken = OOO_STRING_SVTOOLS_HTML_preformtxt ""_ostr;
+ rRefPoolId = RES_POOLCOLL_HTML_PRE;
+ nDeep = CSS1_FMT_CMPREF;
+ }
+
+ // if a PoolId is set, the Name of the template is that of the related Token
+ OSL_ENSURE( (rRefPoolId != 0) == (!rToken.isEmpty()),
+ "Token missing" );
+ }
+ else
+ {
+ // Pool templates
+ switch( nPoolId )
+ {
+ // paragraph templates
+ case RES_POOLCOLL_HEADLINE_BASE:
+ case RES_POOLCOLL_STANDARD:
+ // do not export this template
+ bStop = (nDeep==0);
+ break;
+ case RES_POOLCOLL_TEXT:
+ rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr;
+ break;
+ case RES_POOLCOLL_HEADLINE1:
+ rToken = OOO_STRING_SVTOOLS_HTML_head1 ""_ostr;
+ break;
+ case RES_POOLCOLL_HEADLINE2:
+ rToken = OOO_STRING_SVTOOLS_HTML_head2 ""_ostr;
+ break;
+ case RES_POOLCOLL_HEADLINE3:
+ rToken = OOO_STRING_SVTOOLS_HTML_head3 ""_ostr;
+ break;
+ case RES_POOLCOLL_HEADLINE4:
+ rToken = OOO_STRING_SVTOOLS_HTML_head4 ""_ostr;
+ break;
+ case RES_POOLCOLL_HEADLINE5:
+ rToken = OOO_STRING_SVTOOLS_HTML_head5 ""_ostr;
+ break;
+ case RES_POOLCOLL_HEADLINE6:
+ rToken = OOO_STRING_SVTOOLS_HTML_head6 ""_ostr;
+ break;
+ case RES_POOLCOLL_SEND_ADDRESS:
+ rToken = OOO_STRING_SVTOOLS_HTML_address ""_ostr;
+ break;
+ case RES_POOLCOLL_HTML_BLOCKQUOTE:
+ rToken = OOO_STRING_SVTOOLS_HTML_blockquote ""_ostr;
+ break;
+ case RES_POOLCOLL_HTML_PRE:
+ rToken = OOO_STRING_SVTOOLS_HTML_preformtxt ""_ostr;
+ break;
+
+ case RES_POOLCOLL_HTML_DD:
+ rToken = OOO_STRING_SVTOOLS_HTML_dd ""_ostr;
+ break;
+ case RES_POOLCOLL_HTML_DT:
+ rToken = OOO_STRING_SVTOOLS_HTML_dt ""_ostr;
+ break;
+
+ case RES_POOLCOLL_TABLE:
+ if( pPseudo )
+ {
+ rToken = OOO_STRING_SVTOOLS_HTML_tabledata " "
+ OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr;
+ }
+ else
+ rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr;
+ break;
+ case RES_POOLCOLL_TABLE_HDLN:
+ if( pPseudo )
+ {
+ rToken = OOO_STRING_SVTOOLS_HTML_tableheader " "
+ OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr;
+ }
+ else
+ rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr;
+ break;
+ case RES_POOLCOLL_HTML_HR:
+ // do not export HR !
+ bStop = (nDeep==0);
+ break;
+ case RES_POOLCOLL_FOOTNOTE:
+ if( !nDeep )
+ {
+ rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr;
+ rClass = OOO_STRING_SVTOOLS_HTML_sdfootnote;
+ rRefPoolId = RES_POOLCOLL_TEXT;
+ nDeep = CSS1_FMT_CMPREF;
+ }
+ break;
+ case RES_POOLCOLL_ENDNOTE:
+ if( !nDeep )
+ {
+ rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr;
+ rClass = OOO_STRING_SVTOOLS_HTML_sdendnote;
+ rRefPoolId = RES_POOLCOLL_TEXT;
+ nDeep = CSS1_FMT_CMPREF;
+ }
+ break;
+
+ // character templates
+ case RES_POOLCHR_HTML_EMPHASIS:
+ rToken = OOO_STRING_SVTOOLS_HTML_emphasis ""_ostr;
+ break;
+ case RES_POOLCHR_HTML_CITATION:
+ rToken = OOO_STRING_SVTOOLS_HTML_citation ""_ostr;
+ break;
+ case RES_POOLCHR_HTML_STRONG:
+ rToken = OOO_STRING_SVTOOLS_HTML_strong ""_ostr;
+ break;
+ case RES_POOLCHR_HTML_CODE:
+ rToken = OOO_STRING_SVTOOLS_HTML_code ""_ostr;
+ break;
+ case RES_POOLCHR_HTML_SAMPLE:
+ rToken = OOO_STRING_SVTOOLS_HTML_sample ""_ostr;
+ break;
+ case RES_POOLCHR_HTML_KEYBOARD:
+ rToken = OOO_STRING_SVTOOLS_HTML_keyboard ""_ostr;
+ break;
+ case RES_POOLCHR_HTML_VARIABLE:
+ rToken = OOO_STRING_SVTOOLS_HTML_variable ""_ostr;
+ break;
+ case RES_POOLCHR_HTML_DEFINSTANCE:
+ rToken = OOO_STRING_SVTOOLS_HTML_definstance ""_ostr;
+ break;
+ case RES_POOLCHR_HTML_TELETYPE:
+ rToken = OOO_STRING_SVTOOLS_HTML_teletype ""_ostr;
+ break;
+
+ case RES_POOLCHR_INET_NORMAL:
+ if( pPseudo )
+ {
+ rToken = OOO_STRING_SVTOOLS_HTML_anchor ""_ostr;
+ *pPseudo = OStringToOUString( sCSS1_link, RTL_TEXTENCODING_ASCII_US );
+ }
+ break;
+ case RES_POOLCHR_INET_VISIT:
+ if( pPseudo )
+ {
+ rToken = OOO_STRING_SVTOOLS_HTML_anchor ""_ostr;
+ *pPseudo = OStringToOUString( sCSS1_visited, RTL_TEXTENCODING_ASCII_US );
+ }
+ break;
+ }
+
+ // if a token is set, PoolId contains the related template
+ if( !rToken.isEmpty() && !rRefPoolId )
+ rRefPoolId = nPoolId;
+ }
+
+ if( !rToken.isEmpty() || bStop )
+ {
+ // stop if a HTML-Tag template was found
+ break;
+ }
+ else
+ {
+ // continue otherwise
+ nDeep++;
+ pPFormat = pPFormat->DerivedFrom();
+ }
+ }
+
+ if( !rToken.isEmpty() )
+ {
+ // this is a HTML-Tag template
+ if( !nDeep )
+ nDeep = CSS1_FMT_ISTAG;
+ }
+ else
+ {
+ // this is not a HTML-Tag template nor derived from one
+ nDeep = 0;
+ }
+ if( nDeep > 0 && nDeep < CSS1_FMT_SPECIAL )
+ {
+ // If the template is derived from a HTML template,
+ // we export it as <TOKEN>.<CLASS>, otherwise as .<CLASS>.
+ // <CLASS> is the name of the template after removing all characters
+ // before and including the first '.'
+ rClass = pFormat->GetName();
+ sal_Int32 nPos = rClass.indexOf( '.' );
+ if( nPos >= 0 && rClass.getLength() > nPos+1 )
+ {
+ rClass = rClass.replaceAt( 0, nPos+1, u"" );
+ }
+
+ rClass = GetAppCharClass().lowercase( rClass );
+ rClass = rClass.replaceAll( ".", "-" );
+ rClass = rClass.replaceAll( " ", "-" );
+ rClass = rClass.replaceAll( "_", "-" );
+ }
+
+ return nDeep;
+}
+
+static sal_uInt16 GetCSS1Selector( const SwFormat *pFormat, OUString& rSelector,
+ sal_uInt16& rRefPoolId )
+{
+ OString aToken;
+ OUString aClass;
+ OUString aPseudo;
+
+ sal_uInt16 nDeep = SwHTMLWriter::GetCSS1Selector( pFormat, aToken, aClass,
+ rRefPoolId, &aPseudo );
+ if( nDeep )
+ {
+ if( !aToken.isEmpty() )
+ rSelector = OStringToOUString(aToken, RTL_TEXTENCODING_ASCII_US);
+ else
+ rSelector.clear();
+
+ if( !aClass.isEmpty() )
+ rSelector += "." + aClass;
+ if( !aPseudo.isEmpty() )
+ rSelector += ":" + aPseudo;
+ }
+
+ return nDeep;
+}
+
+const SwFormat *SwHTMLWriter::GetTemplateFormat( sal_uInt16 nPoolFormatId,
+ IDocumentStylePoolAccess* pTemplate /*SwDoc *pTemplate*/)
+{
+ const SwFormat *pRefFormat = nullptr;
+
+ if( pTemplate )
+ {
+ OSL_ENSURE( !(USER_FMT & nPoolFormatId),
+ "No user templates found" );
+ if( POOLGRP_NOCOLLID & nPoolFormatId )
+ pRefFormat = pTemplate->GetCharFormatFromPool( nPoolFormatId );
+ else
+ pRefFormat = pTemplate->GetTextCollFromPool( nPoolFormatId, false );
+ }
+
+ return pRefFormat;
+}
+
+const SwFormat *SwHTMLWriter::GetParentFormat( const SwFormat& rFormat, sal_uInt16 nDeep )
+{
+ OSL_ENSURE( nDeep != USHRT_MAX, "Called GetParent for HTML-template!" );
+ const SwFormat *pRefFormat = nullptr;
+
+ if( nDeep > 0 )
+ {
+ // get the pointer for the HTML-Tag template, from which the template is derived
+ pRefFormat = &rFormat;
+ for( sal_uInt16 i=nDeep; i>0; i-- )
+ pRefFormat = pRefFormat->DerivedFrom();
+
+ if( pRefFormat && pRefFormat->IsDefault() )
+ pRefFormat = nullptr;
+ }
+
+ return pRefFormat;
+}
+
+bool swhtml_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 )
+{
+ return static_cast<const SvxFontItem &>(r1).GetFamilyName() ==
+ static_cast<const SvxFontItem &>(r2).GetFamilyName() &&
+ static_cast<const SvxFontItem &>(r1).GetFamily() ==
+ static_cast<const SvxFontItem &>(r2).GetFamily();
+}
+
+void SwHTMLWriter::SubtractItemSet( SfxItemSet& rItemSet,
+ const SfxItemSet& rRefItemSet,
+ bool bSetDefaults,
+ bool bClearSame,
+ const SfxItemSet *pRefScriptItemSet )
+{
+ OSL_ENSURE( bSetDefaults || bClearSame,
+ "SwHTMLWriter::SubtractItemSet: No action for this Flag" );
+ SfxItemSet aRefItemSet( *rRefItemSet.GetPool(), rRefItemSet.GetRanges() );
+ aRefItemSet.Set( rRefItemSet );
+
+ // compare with the Attr-Set of the template
+ SfxWhichIter aIter( rItemSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while( nWhich )
+ {
+ const SfxPoolItem *pRefItem, *pItem;
+ bool bItemSet = ( SfxItemState::SET ==
+ aIter.GetItemState( false, &pItem) );
+ bool bRefItemSet;
+
+ if( pRefScriptItemSet )
+ {
+ switch( nWhich )
+ {
+ case RES_CHRATR_FONT:
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_LANGUAGE:
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_WEIGHT:
+ case RES_CHRATR_CJK_FONT:
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CJK_LANGUAGE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CJK_WEIGHT:
+ case RES_CHRATR_CTL_FONT:
+ case RES_CHRATR_CTL_FONTSIZE:
+ case RES_CHRATR_CTL_LANGUAGE:
+ case RES_CHRATR_CTL_POSTURE:
+ case RES_CHRATR_CTL_WEIGHT:
+ bRefItemSet = ( SfxItemState::SET ==
+ pRefScriptItemSet->GetItemState( nWhich, true, &pRefItem) );
+ break;
+ default:
+ bRefItemSet = ( SfxItemState::SET ==
+ aRefItemSet.GetItemState( nWhich, false, &pRefItem) );
+ break;
+ }
+ }
+ else
+ {
+ bRefItemSet = ( SfxItemState::SET ==
+ aRefItemSet.GetItemState( nWhich, false, &pRefItem) );
+ }
+
+ if( bItemSet )
+ {
+ if( (bClearSame || pRefScriptItemSet) && bRefItemSet &&
+ ( *pItem == *pRefItem ||
+ ((RES_CHRATR_FONT == nWhich ||
+ RES_CHRATR_CJK_FONT == nWhich ||
+ RES_CHRATR_CTL_FONT == nWhich) &&
+ swhtml_css1atr_equalFontItems( *pItem, *pRefItem )) ) )
+ {
+ // the Attribute is in both templates with the same value
+ // and does not need to be exported
+ rItemSet.ClearItem( nWhich );
+ }
+ }
+ else
+ {
+ if( (bSetDefaults || pRefScriptItemSet) && bRefItemSet )
+ {
+ // the Attribute exists only in the reference; the default
+ // might have to be exported
+ rItemSet.Put( rItemSet.GetPool()->GetDefaultItem(nWhich) );
+ }
+ }
+
+ nWhich = aIter.NextWhich();
+ }
+}
+
+void SwHTMLWriter::PrepareFontList( const SvxFontItem& rFontItem,
+ OUString& rNames,
+ sal_Unicode cQuote, bool bGeneric )
+{
+ rNames.clear();
+ const OUString& rName = rFontItem.GetFamilyName();
+ bool bContainsKeyword = false;
+ if( !rName.isEmpty() )
+ {
+ sal_Int32 nStrPos = 0;
+ while( nStrPos != -1 )
+ {
+ OUString aName = rName.getToken( 0, ';', nStrPos );
+ aName = comphelper::string::encodeForXml(comphelper::string::strip(aName, ' '));
+ if( aName.isEmpty() )
+ continue;
+
+ bool bIsKeyword = false;
+ switch( aName[0] )
+ {
+ case 'c':
+ case 'C':
+ bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_cursive );
+ break;
+
+ case 'f':
+ case 'F':
+ bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_fantasy );
+ break;
+
+ case 'm':
+ case 'M':
+ bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_monospace );
+ break;
+
+ case 's':
+ case 'S':
+ bIsKeyword =
+ aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_serif ) ||
+ aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_sans_serif );
+ break;
+ }
+
+ bContainsKeyword |= bIsKeyword;
+
+ if( !rNames.isEmpty() )
+ rNames += ", ";
+ if( cQuote && !bIsKeyword )
+ rNames += OUStringChar( cQuote );
+ rNames += aName;
+ if( cQuote && !bIsKeyword )
+ rNames += OUStringChar( cQuote );
+ }
+ }
+
+ if( bContainsKeyword || !bGeneric )
+ return;
+
+ std::string_view pStr;
+ switch( rFontItem.GetFamily() )
+ {
+ case FAMILY_ROMAN: pStr = sCSS1_PV_serif; break;
+ case FAMILY_SWISS: pStr = sCSS1_PV_sans_serif; break;
+ case FAMILY_SCRIPT: pStr = sCSS1_PV_cursive; break;
+ case FAMILY_DECORATIVE: pStr = sCSS1_PV_fantasy; break;
+ case FAMILY_MODERN: pStr = sCSS1_PV_monospace; break;
+ default:
+ ;
+ }
+
+ if( !pStr.empty() )
+ {
+ if( !rNames.isEmpty() )
+ rNames += ", ";
+ rNames += OStringToOUString( pStr, RTL_TEXTENCODING_ASCII_US );
+ }
+}
+
+bool SwHTMLWriter::HasScriptDependentItems( const SfxItemSet& rItemSet,
+ bool bCheckDropCap )
+{
+ static const sal_uInt16 aWhichIds[] =
+ {
+ RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT,
+ RES_CHRATR_FONTSIZE, RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CTL_FONTSIZE,
+ RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE,
+ RES_CHRATR_POSTURE, RES_CHRATR_CJK_POSTURE, RES_CHRATR_CTL_POSTURE,
+ RES_CHRATR_WEIGHT, RES_CHRATR_CJK_WEIGHT, RES_CHRATR_CTL_WEIGHT,
+ 0, 0, 0
+ };
+
+ for( int i=0; aWhichIds[i]; i += 3 )
+ {
+ const SfxPoolItem *pItem = nullptr, *pItemCJK = nullptr, *pItemCTL = nullptr, *pTmp;
+ int nItemCount = 0;
+ if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i], false,
+ &pTmp ) )
+ {
+ pItem = pTmp;
+ nItemCount++;
+ }
+ if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i+1], false,
+ &pTmp ) )
+ {
+ pItemCJK = pTmp;
+ nItemCount++;
+ }
+ if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i+2], false,
+ &pTmp ) )
+ {
+ pItemCTL = pTmp;
+ nItemCount++;
+ }
+
+ // If some of the items are set, but not all, we need script dependent
+ // styles
+ if( nItemCount > 0 && nItemCount < 3 )
+ return true;
+
+ if( 3 == nItemCount )
+ {
+ // If all items are set, but some of them have different values,
+ // we need script dependent styles, too. For font items, we have
+ // to take care about their special HTML/CSS1 representation.
+ if( RES_CHRATR_FONT == aWhichIds[i] )
+ {
+ if( !swhtml_css1atr_equalFontItems( *pItem, *pItemCJK ) ||
+ !swhtml_css1atr_equalFontItems( *pItem, *pItemCTL ) ||
+ !swhtml_css1atr_equalFontItems( *pItemCJK, *pItemCTL ) )
+ return true;
+ }
+ else
+ {
+ if( *pItem != *pItemCJK ||
+ *pItem != *pItemCTL ||
+ *pItemCJK != *pItemCTL )
+ return true;
+ }
+ }
+ }
+
+ const SwFormatDrop *pDrop;
+ if( bCheckDropCap &&
+ (pDrop = rItemSet.GetItemIfSet( RES_PARATR_DROP )) )
+ {
+ const SwCharFormat *pDCCharFormat = pDrop->GetCharFormat();
+ if( pDCCharFormat )
+ {
+ //sequence of (start, end) property ranges we want to
+ //query
+ SfxItemSetFixed<
+ RES_CHRATR_FONT, RES_CHRATR_FONT,
+ RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
+ RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
+ RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
+ RES_CHRATR_CJK_POSTURE, RES_CHRATR_CTL_FONT,
+ RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT>
+ aTstItemSet(*pDCCharFormat->GetAttrSet().GetPool());
+ aTstItemSet.Set( pDCCharFormat->GetAttrSet() );
+ return HasScriptDependentItems( aTstItemSet, false );
+ }
+ }
+
+ return false;
+}
+
+static bool OutCSS1Rule( SwHTMLWriter& rWrt, const OUString& rSelector,
+ const SfxItemSet& rItemSet, bool bHasClass,
+ bool bCheckForPseudo )
+{
+ bool bScriptDependent = false;
+ if( SwHTMLWriter::HasScriptDependentItems( rItemSet, bHasClass ) )
+ {
+ bScriptDependent = true;
+ std::u16string_view aSelector( rSelector );
+
+ std::u16string_view aPseudo;
+ if( bCheckForPseudo )
+ {
+ size_t nPos = aSelector.rfind( ':' );
+ if( nPos != std::u16string_view::npos )
+ {
+ aPseudo = aSelector.substr( nPos );
+ aSelector =aSelector.substr( 0, nPos );
+ }
+ }
+
+ if( !bHasClass )
+ {
+ // If we are exporting styles for a tag we have to export a tag
+ // rule for all properties that aren't style dependent and
+ // some class rule for the additional style dependen properties
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &rSelector );
+ rWrt.OutCSS1_SfxItemSet( rItemSet, false );
+ }
+
+ //sequence of (start, end) property ranges we want to
+ //query
+ SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
+ RES_CHRATR_LANGUAGE, RES_CHRATR_POSTURE,
+ RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
+ RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT>
+ aScriptItemSet( *rItemSet.GetPool() );
+ aScriptItemSet.Put( rItemSet );
+
+ OUString aNewSelector = OUString::Concat(aSelector) + ".western" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &aNewSelector );
+ rWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
+ }
+
+ aNewSelector = OUString::Concat(aSelector) + ".cjk" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &aNewSelector );
+ rWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
+ }
+
+ aNewSelector = OUString::Concat(aSelector) + ".ctl" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &aNewSelector );
+ rWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
+ }
+ }
+ else
+ {
+ // If there are script dependencies and we are derived from a tag,
+ // when we have to export a style dependent class for all
+ // scripts
+ OUString aNewSelector = OUString::Concat(aSelector) + "-western" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &aNewSelector );
+ rWrt.OutCSS1_SfxItemSet( rItemSet, false );
+ }
+
+ aNewSelector = OUString::Concat(aSelector) + "-cjk" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &aNewSelector );
+ rWrt.OutCSS1_SfxItemSet( rItemSet, false );
+ }
+
+ aNewSelector = OUString::Concat(aSelector) + "-ctl" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &aNewSelector );
+ rWrt.OutCSS1_SfxItemSet( rItemSet, false );
+ }
+ }
+ }
+ else
+ {
+ // If there are no script dependencies, when all items are
+ // exported in one step. For hyperlinks only, a script information
+ // must be there, because these two chr formats don't support
+ // script dependencies by now.
+ SwCSS1OutMode aMode( rWrt,
+ rWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &rSelector );
+ rWrt.OutCSS1_SfxItemSet( rItemSet, false );
+ }
+
+ return bScriptDependent;
+}
+
+static void OutCSS1DropCapRule(
+ SwHTMLWriter& rWrt, const OUString& rSelector,
+ const SwFormatDrop& rDrop, bool bHasClass,
+ bool bHasScriptDependencies )
+{
+ const SwCharFormat *pDCCharFormat = rDrop.GetCharFormat();
+ if( (bHasScriptDependencies && bHasClass) ||
+ (pDCCharFormat && SwHTMLWriter::HasScriptDependentItems( pDCCharFormat->GetAttrSet(), false ) ) )
+ {
+ std::u16string_view aSelector( rSelector );
+
+ std::u16string_view aPseudo;
+ size_t nPos = aSelector.rfind( ':' );
+ if( nPos != std::u16string_view::npos )
+ {
+ aPseudo = aSelector.substr( nPos );
+ aSelector = aSelector.substr( 0, nPos );
+ }
+
+ if( !bHasClass )
+ {
+ // If we are exporting styles for a tag we have to export a tag
+ // rule for all properties that aren't style dependent and
+ // some class rule for the additional style dependen properties
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
+ &rSelector );
+ OutCSS1_SwFormatDropAttrs( rWrt, rDrop );
+ }
+
+ SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
+ RES_CHRATR_LANGUAGE, RES_CHRATR_POSTURE,
+ RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
+ RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT>
+ aScriptItemSet( rWrt.m_pDoc->GetAttrPool() );
+ if( pDCCharFormat )
+ aScriptItemSet.Set( pDCCharFormat->GetAttrSet() );
+
+ OUString aNewSelector = OUString::Concat(aSelector) + ".western" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
+ &aNewSelector );
+ OutCSS1_SwFormatDropAttrs( rWrt, rDrop, &aScriptItemSet );
+ }
+
+ aNewSelector = OUString::Concat(aSelector) + ".cjk" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
+ &aNewSelector );
+ OutCSS1_SwFormatDropAttrs( rWrt, rDrop, &aScriptItemSet );
+ }
+
+ aNewSelector = OUString::Concat(aSelector) + ".ctl" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
+ &aNewSelector );
+ OutCSS1_SwFormatDropAttrs( rWrt, rDrop, &aScriptItemSet );
+ }
+ }
+ else
+ {
+ // If there are script dependencies and we are derived from a tag,
+ // when we have to export a style dependent class for all
+ // scripts
+ OUString aNewSelector = OUString::Concat(aSelector) + "-western" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
+ &aNewSelector );
+ OutCSS1_SwFormatDropAttrs( rWrt, rDrop );
+ }
+
+ aNewSelector = OUString::Concat(aSelector) + "-cjk" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
+ &aNewSelector );
+ OutCSS1_SwFormatDropAttrs( rWrt, rDrop );
+ }
+
+ aNewSelector = OUString::Concat(aSelector) + "-ctl" + aPseudo;
+ {
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
+ &aNewSelector );
+ OutCSS1_SwFormatDropAttrs( rWrt, rDrop );
+ }
+ }
+ }
+ else
+ {
+ // If there are no script dependencies, when all items are
+ // exported in one step. For hyperlinks only, a script information
+ // must be there, because these two chr formats don't support
+ // script dependencies by now.
+ SwCSS1OutMode aMode( rWrt,
+ rWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
+ &rSelector );
+ OutCSS1_SwFormatDropAttrs( rWrt, rDrop );
+ }
+}
+
+static SwHTMLWriter& OutCSS1_SwFormat( SwHTMLWriter& rWrt, const SwFormat& rFormat,
+ IDocumentStylePoolAccess/*SwDoc*/ *pDoc, SwDoc *pTemplate )
+{
+ bool bCharFormat = false;
+ switch( rFormat.Which() )
+ {
+ case RES_CHRFMT:
+ bCharFormat = true;
+ break;
+
+ case RES_TXTFMTCOLL:
+ case RES_CONDTXTFMTCOLL:
+ // these template-types can be exported
+ break;
+
+ default:
+ // but not these
+ return rWrt;
+ }
+
+ // determine Selector and the to-be-exported Attr-Set-depth
+ OUString aSelector;
+ sal_uInt16 nRefPoolId = 0;
+ sal_uInt16 nDeep = GetCSS1Selector( &rFormat, aSelector, nRefPoolId );
+ if( !nDeep )
+ return rWrt; // not derived from a HTML-template
+
+ sal_uInt16 nPoolFormatId = rFormat.GetPoolFormatId();
+
+ // Determine the to-be-exported Attr-Set. We have to distinguish 3 cases:
+ // - HTML-Tag templates (nDeep==USHRT_MAX):
+ // Export Attrs...
+ // - that are set in the template, but not in the original of the HTML template
+ // - the Default-Attrs for the Attrs, that are set in the Original of the
+ // HTML template, but not in the current template.
+ // - templates directly derived from HTML templates (nDeep==1):
+ // Export only Attributes of the template Item-Set w/o its parents.
+ // - templates in-directly derived from HTML templates (nDeep>1):
+ // Export Attributes of the template Item-Set incl. its Parents,
+ // but w/o Attributes that are set in the HTML-Tag template.
+
+ // create Item-Set with all Attributes from the template
+ // (all but for nDeep==1)
+ const SfxItemSet& rFormatItemSet = rFormat.GetAttrSet();
+ SfxItemSet aItemSet( *rFormatItemSet.GetPool(), rFormatItemSet.GetRanges() );
+ aItemSet.Set( rFormatItemSet ); // Was nDeep!=1 that is not working
+ // for script dependent items but should
+ // not make a difference for any other
+
+ bool bSetDefaults = true, bClearSame = true;
+ const SwFormat *pRefFormat = nullptr;
+ const SwFormat *pRefFormatScript = nullptr;
+ switch( nDeep )
+ {
+ case CSS1_FMT_ISTAG:
+ pRefFormat = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
+ break;
+ case CSS1_FMT_CMPREF:
+ pRefFormat = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pDoc );
+ pRefFormatScript = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
+ bClearSame = false;
+ break;
+ default:
+ pRefFormat = SwHTMLWriter::GetParentFormat( rFormat, nDeep );
+ pRefFormatScript = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
+ bSetDefaults = false;
+ break;
+ }
+
+ if( pRefFormat )
+ {
+ // subtract Item-Set of the Reference template (incl. its Parents)
+ SwHTMLWriter::SubtractItemSet( aItemSet, pRefFormat->GetAttrSet(),
+ bSetDefaults, bClearSame,
+ pRefFormatScript
+ ? &pRefFormatScript->GetAttrSet()
+ : nullptr );
+
+ if( !bCharFormat )
+ {
+ const SvxULSpaceItem& rULItem = pRefFormat->GetULSpace();
+ rWrt.m_nDfltTopMargin = rULItem.GetUpper();
+ rWrt.m_nDfltBottomMargin = rULItem.GetLower();
+ }
+ }
+ else if( CSS1_FMT_ISTAG==nDeep && !bCharFormat )
+ {
+ // set Default-distance above and below (for the
+ // case that there is no reference template)
+ rWrt.m_nDfltTopMargin = 0;
+ rWrt.m_nDfltBottomMargin = HTML_PARSPACE;
+ if( USER_FMT & nPoolFormatId )
+ {
+ // user templates
+ const OUString& aNm(rFormat.GetName());
+
+ if (aNm == "DD 1" || aNm == "DT 1")
+ rWrt.m_nDfltBottomMargin = 0;
+ else if (aNm == OOO_STRING_SVTOOLS_HTML_listing)
+ rWrt.m_nDfltBottomMargin = 0;
+ else if (aNm == OOO_STRING_SVTOOLS_HTML_preformtxt)
+ rWrt.m_nDfltBottomMargin = 0;
+ else if (aNm == OOO_STRING_SVTOOLS_HTML_xmp)
+ rWrt.m_nDfltBottomMargin = 0;
+ }
+ else
+ {
+ // Pool templates
+ switch( nPoolFormatId )
+ {
+ case RES_POOLCOLL_HEADLINE1:
+ case RES_POOLCOLL_HEADLINE2:
+ case RES_POOLCOLL_HEADLINE3:
+ case RES_POOLCOLL_HEADLINE4:
+ case RES_POOLCOLL_HEADLINE5:
+ case RES_POOLCOLL_HEADLINE6:
+ rWrt.m_nDfltTopMargin = HTML_HEADSPACE;
+ break;
+ case RES_POOLCOLL_SEND_ADDRESS:
+ case RES_POOLCOLL_HTML_DT:
+ case RES_POOLCOLL_HTML_DD:
+ case RES_POOLCOLL_HTML_PRE:
+ rWrt.m_nDfltBottomMargin = 0;
+ break;
+ }
+ }
+ }
+
+ // if nothing is to be exported ...
+ if( !aItemSet.Count() )
+ return rWrt;
+
+ // There is no support for script dependent hyperlinks by now.
+ bool bCheckForPseudo = false;
+ if( bCharFormat &&
+ (RES_POOLCHR_INET_NORMAL==nRefPoolId ||
+ RES_POOLCHR_INET_VISIT==nRefPoolId) )
+ bCheckForPseudo = true;
+
+ // export now the Attributes (incl. selector)
+ bool bHasScriptDependencies = false;
+ if( OutCSS1Rule( rWrt, aSelector, aItemSet, CSS1_FMT_ISTAG != nDeep,
+ bCheckForPseudo ) )
+ {
+ if( bCharFormat )
+ rWrt.m_aScriptTextStyles.insert( rFormat.GetName() );
+ else
+ {
+ if( nPoolFormatId==RES_POOLCOLL_TEXT )
+ rWrt.m_aScriptParaStyles.insert( pDoc->GetTextCollFromPool( RES_POOLCOLL_STANDARD, false )->GetName() );
+ rWrt.m_aScriptParaStyles.insert( rFormat.GetName() );
+ }
+ bHasScriptDependencies = true;
+ }
+
+ // export Drop-Caps
+ if( const SwFormatDrop *pDrop = aItemSet.GetItemIfSet( RES_PARATR_DROP, false ) )
+ {
+ OUString sOut = aSelector +
+ ":" + OStringToOUString( sCSS1_first_letter, RTL_TEXTENCODING_ASCII_US );
+ OutCSS1DropCapRule( rWrt, sOut, *pDrop, CSS1_FMT_ISTAG != nDeep, bHasScriptDependencies );
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SwPageDesc( SwHTMLWriter& rWrt, const SwPageDesc& rPageDesc,
+ IDocumentStylePoolAccess/*SwDoc*/ *pDoc, SwDoc *pTemplate,
+ sal_uInt16 nRefPoolId, bool bExtRef,
+ bool bPseudo )
+{
+ const SwPageDesc* pRefPageDesc = nullptr;
+ if( !bExtRef )
+ pRefPageDesc = pDoc->GetPageDescFromPool( nRefPoolId, false );
+ else if( pTemplate )
+ pRefPageDesc = pTemplate->getIDocumentStylePoolAccess().GetPageDescFromPool( nRefPoolId, false );
+
+ OUString aSelector = "@" + OStringToOUString( sCSS1_page, RTL_TEXTENCODING_ASCII_US );
+
+ if( bPseudo )
+ {
+ std::string_view pPseudo;
+ switch( rPageDesc.GetPoolFormatId() )
+ {
+ case RES_POOLPAGE_FIRST: pPseudo = sCSS1_first; break;
+ case RES_POOLPAGE_LEFT: pPseudo = sCSS1_left; break;
+ case RES_POOLPAGE_RIGHT: pPseudo = sCSS1_right; break;
+ }
+ if( !pPseudo.empty() )
+ aSelector += ":" + OStringToOUString( pPseudo, RTL_TEXTENCODING_ASCII_US );
+ }
+
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_RULE_ON|CSS1_OUTMODE_TEMPLATE,
+ &aSelector );
+
+ // Size: If the only difference is the Landscape-Flag,
+ // only export Portrait or Landscape. Otherwise export size.
+ bool bRefLandscape = pRefPageDesc && pRefPageDesc->GetLandscape();
+ Size aRefSz;
+ const Size& rSz = rPageDesc.GetMaster().GetFrameSize().GetSize();
+ if( pRefPageDesc )
+ {
+ aRefSz = pRefPageDesc->GetMaster().GetFrameSize().GetSize();
+ if( bRefLandscape != rPageDesc.GetLandscape() )
+ {
+ tools::Long nTmp = aRefSz.Height();
+ aRefSz.setHeight( aRefSz.Width() );
+ aRefSz.setWidth( nTmp );
+ }
+ }
+
+ // TODO: Bad Hack: On the Page-Tabpage there are small rounding errors
+ // for the page size. Partially because of bug 25535, we stupidly still
+ // use the Size-Item from Dialog, even if nothing changed.
+ // Thus: once one visited the Page-Dialog and left it with OK, we get a
+ // new page size that then gets exported here. To avoid that, we allow
+ // here small deviations.
+ if( std::abs( rSz.Width() - aRefSz.Width() ) <= 2 &&
+ std::abs( rSz.Height() - aRefSz.Height() ) <= 2 )
+ {
+ if( bRefLandscape != rPageDesc.GetLandscape() )
+ {
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_size,
+ rPageDesc.GetLandscape() ? sCSS1_PV_landscape
+ : sCSS1_PV_portrait );
+ }
+ }
+ else
+ {
+ OStringBuffer sVal;
+ AddUnitPropertyValue(sVal, rSz.Width(), rWrt.GetCSS1Unit());
+ sVal.append(' ');
+ AddUnitPropertyValue(sVal, rSz.Height(), rWrt.GetCSS1Unit());
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_size, sVal);
+ }
+
+ // Export the distance-Attributes as normally
+ const SwFrameFormat &rMaster = rPageDesc.GetMaster();
+ SfxItemSetFixed<RES_LR_SPACE, RES_UL_SPACE> aItemSet( *rMaster.GetAttrSet().GetPool() );
+ aItemSet.Set( rMaster.GetAttrSet() );
+
+ if( pRefPageDesc )
+ {
+ SwHTMLWriter::SubtractItemSet( aItemSet,
+ pRefPageDesc->GetMaster().GetAttrSet(),
+ true );
+ }
+
+ OutCSS1_SvxULSpace_SvxLRSpace( rWrt, aItemSet );
+
+ // If for a Pseudo-Selector no Property had been set, we still
+ // have to export something, so that the corresponding template is
+ // created on the next import.
+ if( rWrt.m_bFirstCSS1Property && bPseudo )
+ {
+ rWrt.OutNewLine();
+ OString sTmp(OUStringToOString(aSelector, RTL_TEXTENCODING_UTF8));
+ rWrt.Strm().WriteOString( sTmp ).WriteOString( " {" );
+ rWrt.m_bFirstCSS1Property = false;
+ }
+
+ if( !rWrt.m_bFirstCSS1Property )
+ rWrt.Strm().WriteOString( sCSS1_rule_end );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SwFootnoteInfo( SwHTMLWriter& rWrt, const SwEndNoteInfo& rInfo,
+ SwDoc *pDoc, bool bHasNotes, bool bEndNote )
+{
+ OUString aSelector;
+
+ if( bHasNotes )
+ {
+ aSelector = OUString::Concat(OOO_STRING_SVTOOLS_HTML_anchor ".") +
+ ( bEndNote ? std::u16string_view(u"" OOO_STRING_SVTOOLS_HTML_sdendnote_anc)
+ : std::u16string_view(u"" OOO_STRING_SVTOOLS_HTML_sdfootnote_anc) );
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
+ &aSelector );
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_size,
+ sHTML_FTN_fontheight );
+ rWrt.Strm().WriteOString( sCSS1_rule_end );
+ }
+
+ const SwCharFormat *pSymCharFormat = rInfo.GetCharFormat( *pDoc );
+ if( pSymCharFormat )
+ {
+ const SfxItemSet& rFormatItemSet = pSymCharFormat->GetAttrSet();
+ SfxItemSet aItemSet( *rFormatItemSet.GetPool(), rFormatItemSet.GetRanges() );
+ aItemSet.Set( rFormatItemSet );
+
+ // If there are footnotes or endnotes, then all Attributes have to be
+ // exported, so that Netscape displays the document correctly.
+ // Otherwise it is sufficient, to export the differences to the
+ // footnote and endnote template.
+ if( !bHasNotes && rWrt.m_xTemplate.is() )
+ {
+ SwFormat *pRefFormat = rWrt.m_xTemplate->getIDocumentStylePoolAccess().GetCharFormatFromPool(
+ static_cast< sal_uInt16 >(bEndNote ? RES_POOLCHR_ENDNOTE : RES_POOLCHR_FOOTNOTE) );
+ if( pRefFormat )
+ SwHTMLWriter::SubtractItemSet( aItemSet, pRefFormat->GetAttrSet(),
+ true );
+ }
+ if( aItemSet.Count() )
+ {
+ aSelector = OUString::Concat(OOO_STRING_SVTOOLS_HTML_anchor ".") +
+ ( bEndNote ? std::u16string_view(u"" OOO_STRING_SVTOOLS_HTML_sdendnote_sym)
+ : std::u16string_view(
+ u"" OOO_STRING_SVTOOLS_HTML_sdfootnote_sym));
+ if( OutCSS1Rule( rWrt, aSelector, aItemSet, true, false ))
+ rWrt.m_aScriptTextStyles.insert( pSymCharFormat->GetName() );
+ }
+ }
+
+ return rWrt;
+}
+
+SwHTMLWriter& OutCSS1_BodyTagStyleOpt( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet )
+{
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_STYLE_OPT_ON |
+ CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_BODY, nullptr );
+
+ // Only export the attributes of the page template.
+ // The attributes of the default paragraph template were
+ // considered already when exporting the paragraph template.
+
+ const SfxPoolItem *pItem;
+ if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false,
+ &pItem ) )
+ {
+ OUString rEmbeddedGraphicName;
+ OutCSS1_SvxBrush( rWrt, *pItem, sw::Css1Background::Page, &rEmbeddedGraphicName );
+ }
+
+ if( SfxItemState::SET == rItemSet.GetItemState( RES_BOX, false,
+ &pItem ))
+ {
+ OutCSS1_SvxBox( rWrt, *pItem );
+ }
+
+ if( !rWrt.m_bFirstCSS1Property )
+ {
+ // if a Property was exported as part of a Style-Option,
+ // the Option still needs to be finished
+ rWrt.Strm().WriteChar( '\"' );
+ }
+
+ return rWrt;
+}
+
+SwHTMLWriter& OutCSS1_ParaTagStyleOpt( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet, std::string_view rAdd )
+{
+ SwCSS1OutMode aMode( rWrt, rWrt.m_nCSS1Script|CSS1_OUTMODE_STYLE_OPT |
+ CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_PARA, nullptr );
+ rWrt.OutCSS1_SfxItemSet( rItemSet, false, rAdd );
+
+ return rWrt;
+}
+
+SwHTMLWriter& OutCSS1_TableBGStyleOpt( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_STYLE_OPT_ON |
+ CSS1_OUTMODE_ENCODE|
+ CSS1_OUTMODE_TABLEBOX, nullptr );
+ OutCSS1_SvxBrush( rWrt, rHt, sw::Css1Background::TableRow, nullptr );
+
+ if (!rWrt.m_bFirstCSS1Property)
+ rWrt.Strm().WriteChar(cCSS1_style_opt_end);
+
+ return rWrt;
+}
+
+SwHTMLWriter& OutCSS1_NumberBulletListStyleOpt( SwHTMLWriter& rWrt, const SwNumRule& rNumRule,
+ sal_uInt8 nLevel )
+{
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_STYLE_OPT |
+ CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_PARA, nullptr );
+
+ const SwNumFormat& rNumFormat = rNumRule.Get( nLevel );
+
+ tools::Long nLSpace = rNumFormat.GetAbsLSpace();
+ tools::Long nFirstLineOffset = rNumFormat.GetFirstLineOffset();
+ tools::Long nDfltFirstLineOffset = HTML_NUMBER_BULLET_INDENT;
+ if( nLevel > 0 )
+ {
+ const SwNumFormat& rPrevNumFormat = rNumRule.Get( nLevel-1 );
+ nLSpace -= rPrevNumFormat.GetAbsLSpace();
+ nDfltFirstLineOffset = rPrevNumFormat.GetFirstLineOffset();
+ }
+
+ if( rWrt.IsHTMLMode(HTMLMODE_LSPACE_IN_NUMBER_BULLET) &&
+ nLSpace != HTML_NUMBER_BULLET_MARGINLEFT )
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLSpace );
+
+ if( rWrt.IsHTMLMode(HTMLMODE_FRSTLINE_IN_NUMBER_BULLET) &&
+ nFirstLineOffset != nDfltFirstLineOffset )
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent, nFirstLineOffset );
+
+ if( !rWrt.m_bFirstCSS1Property )
+ rWrt.Strm().WriteChar( '\"' );
+
+ return rWrt;
+}
+
+void SwHTMLWriter::OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat,
+ HtmlFrmOpts nFrameOpts,
+ const SdrObject *pSdrObj,
+ const SfxItemSet *pItemSet )
+{
+ SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
+ CSS1_OUTMODE_ENCODE|
+ CSS1_OUTMODE_FRAME, nullptr );
+
+ const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
+ SvxLRSpaceItem aLRItem( rFrameFormat.GetLRSpace() );
+ SvxULSpaceItem aULItem( rFrameFormat.GetULSpace() );
+ if( nFrameOpts & HtmlFrmOpts::SAlign )
+ {
+ const SwFormatAnchor& rAnchor = rFrameFormat.GetAnchor();
+ switch( rAnchor.GetAnchorId() )
+ {
+ case RndStdIds::FLY_AT_PARA:
+ case RndStdIds::FLY_AT_CHAR:
+ if( text::RelOrientation::FRAME == rHoriOri.GetRelationOrient() ||
+ text::RelOrientation::PRINT_AREA == rHoriOri.GetRelationOrient() )
+ {
+ if( !(nFrameOpts & HtmlFrmOpts::Align) )
+ {
+ // float
+ std::string_view pStr = text::HoriOrientation::RIGHT==rHoriOri.GetHoriOrient()
+ ? sCSS1_PV_right
+ : sCSS1_PV_left;
+ OutCSS1_PropertyAscii( sCSS1_P_float, pStr );
+ }
+ break;
+ }
+ [[fallthrough]];
+
+ case RndStdIds::FLY_AT_PAGE:
+ case RndStdIds::FLY_AT_FLY:
+ {
+ // position
+ OutCSS1_PropertyAscii( sCSS1_P_position, sCSS1_PV_absolute );
+
+ // For top/left we need to subtract the distance to the frame
+ // from the position, as in CSS1 it is added to the position.
+ // This works also for automatically aligned frames, even that
+ // in this case Writer also adds the distance; because in this
+ // case the Orient-Attribute contains the correct position.
+
+ // top
+ tools::Long nXPos=0, nYPos=0;
+ bool bOutXPos = false, bOutYPos = false;
+ if( RES_DRAWFRMFMT == rFrameFormat.Which() )
+ {
+ OSL_ENSURE( pSdrObj, "Do not pass a SdrObject. Inefficient" );
+ if( !pSdrObj )
+ pSdrObj = rFrameFormat.FindSdrObject();
+ OSL_ENSURE( pSdrObj, "Where is the SdrObject" );
+ if( pSdrObj )
+ {
+ Point aPos( pSdrObj->GetRelativePos() );
+ nXPos = aPos.X();
+ nYPos = aPos.Y();
+ }
+ bOutXPos = bOutYPos = true;
+ }
+ else
+ {
+ bOutXPos = text::RelOrientation::CHAR != rHoriOri.GetRelationOrient();
+ nXPos = text::HoriOrientation::NONE == rHoriOri.GetHoriOrient()
+ ? rHoriOri.GetPos() : 0;
+
+ const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
+ bOutYPos = text::RelOrientation::CHAR != rVertOri.GetRelationOrient();
+ nYPos = text::VertOrientation::NONE == rVertOri.GetVertOrient()
+ ? rVertOri.GetPos() : 0;
+ }
+
+ if( bOutYPos )
+ {
+ if( IsHTMLMode( HTMLMODE_FLY_MARGINS) )
+ {
+ nYPos -= aULItem.GetUpper();
+ if( nYPos < 0 )
+ {
+ aULItem.SetUpper( o3tl::narrowing<sal_uInt16>(aULItem.GetUpper() + nYPos) );
+ nYPos = 0;
+ }
+ }
+
+ OutCSS1_UnitProperty( sCSS1_P_top, nYPos );
+ }
+
+ if( bOutXPos )
+ {
+ // left
+ if( IsHTMLMode( HTMLMODE_FLY_MARGINS) )
+ {
+ nXPos -= aLRItem.GetLeft();
+ if( nXPos < 0 )
+ {
+ aLRItem.SetLeft( o3tl::narrowing<sal_uInt16>(aLRItem.GetLeft() + nXPos) );
+ nXPos = 0;
+ }
+ }
+
+ OutCSS1_UnitProperty( sCSS1_P_left, nXPos );
+ }
+ }
+ break;
+
+ default:
+ ;
+ }
+ }
+
+ // width/height
+ if( nFrameOpts & HtmlFrmOpts::SSize )
+ {
+ if( RES_DRAWFRMFMT == rFrameFormat.Which() )
+ {
+ OSL_ENSURE( pSdrObj, "Do not pass a SdrObject. Inefficient" );
+ if( !pSdrObj )
+ pSdrObj = rFrameFormat.FindSdrObject();
+ OSL_ENSURE( pSdrObj, "Where is the SdrObject" );
+ if( pSdrObj )
+ {
+ Size aTwipSz( pSdrObj->GetLogicRect().GetSize() );
+ if( nFrameOpts & HtmlFrmOpts::SWidth )
+ {
+ if( nFrameOpts & HtmlFrmOpts::SPixSize )
+ OutCSS1_PixelProperty( sCSS1_P_width, aTwipSz.Width() );
+ else
+ OutCSS1_UnitProperty( sCSS1_P_width, aTwipSz.Width() );
+ }
+ if( nFrameOpts & HtmlFrmOpts::SHeight )
+ {
+ if( nFrameOpts & HtmlFrmOpts::SPixSize )
+ OutCSS1_PixelProperty( sCSS1_P_height, aTwipSz.Height() );
+ else
+ OutCSS1_UnitProperty( sCSS1_P_height, aTwipSz.Height() );
+ }
+ }
+ }
+ else
+ {
+ OSL_ENSURE( HtmlFrmOpts::AbsSize & nFrameOpts,
+ "Export absolute size" );
+ OSL_ENSURE( HtmlFrmOpts::AnySize & nFrameOpts,
+ "Export every size" );
+ Css1FrameSize nMode = Css1FrameSize::NONE;
+ if( nFrameOpts & HtmlFrmOpts::SWidth )
+ nMode |= Css1FrameSize::Width;
+ if( nFrameOpts & HtmlFrmOpts::SHeight )
+ nMode |= Css1FrameSize::MinHeight|Css1FrameSize::FixHeight;
+ if( nFrameOpts & HtmlFrmOpts::SPixSize )
+ nMode |= Css1FrameSize::Pixel;
+
+ OutCSS1_SwFormatFrameSize( *this, rFrameFormat.GetFrameSize(), nMode );
+ }
+ }
+
+ const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
+ // margin-*
+ if( (nFrameOpts & HtmlFrmOpts::SSpace) &&
+ IsHTMLMode( HTMLMODE_FLY_MARGINS) )
+ {
+ const SvxLRSpaceItem *pLRItem = nullptr;
+ const SvxULSpaceItem *pULItem = nullptr;
+ if( SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE ) )
+ pLRItem = &aLRItem;
+ if( SfxItemState::SET == rItemSet.GetItemState( RES_UL_SPACE ) )
+ pULItem = &aULItem;
+ if( pLRItem || pULItem )
+ OutCSS1_SvxULSpace_SvxLRSpace( *this, pULItem, pLRItem );
+ }
+
+ // border
+ if( nFrameOpts & HtmlFrmOpts::SBorder )
+ {
+ const SfxPoolItem* pItem;
+ if( nFrameOpts & HtmlFrmOpts::SNoBorder )
+ OutCSS1_SvxBox( *this, rFrameFormat.GetBox() );
+ else if( SfxItemState::SET==rItemSet.GetItemState( RES_BOX, true, &pItem ) )
+ OutCSS1_SvxBox( *this, *pItem );
+ }
+
+ // background (if, then the color must be set also)
+ if( nFrameOpts & HtmlFrmOpts::SBackground )
+ OutCSS1_FrameFormatBackground( rFrameFormat );
+
+ if( pItemSet )
+ OutCSS1_SfxItemSet( *pItemSet, false );
+
+ if( !m_bFirstCSS1Property )
+ Strm().WriteChar( '\"' );
+}
+
+void SwHTMLWriter::OutCSS1_TableFrameFormatOptions( const SwFrameFormat& rFrameFormat )
+{
+ SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
+ CSS1_OUTMODE_ENCODE|
+ CSS1_OUTMODE_TABLE, nullptr );
+
+ const SfxPoolItem *pItem;
+ const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
+ if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) )
+ OutCSS1_SvxBrush( *this, *pItem, sw::Css1Background::Table, nullptr );
+
+ if( IsHTMLMode( HTMLMODE_PRINT_EXT ) )
+ OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( *this, rItemSet, false );
+
+ if( SfxItemState::SET==rItemSet.GetItemState( RES_LAYOUT_SPLIT, false, &pItem ) )
+ OutCSS1_SwFormatLayoutSplit( *this, *pItem );
+
+ if (mbXHTML)
+ {
+ sal_Int16 eTabHoriOri = rFrameFormat.GetHoriOrient().GetHoriOrient();
+ if (eTabHoriOri == text::HoriOrientation::CENTER)
+ {
+ // Emit XHTML's center using inline CSS.
+ OutCSS1_Property(sCSS1_P_margin_left, "auto", nullptr, sw::Css1Background::Table);
+ OutCSS1_Property(sCSS1_P_margin_right, "auto", nullptr, sw::Css1Background::Table);
+ }
+ }
+
+ if( !m_bFirstCSS1Property )
+ Strm().WriteChar( '\"' );
+}
+
+void SwHTMLWriter::OutCSS1_TableCellBordersAndBG(SwFrameFormat const& rFrameFormat, const SvxBrushItem *pBrushItem)
+{
+ SwCSS1OutMode const aMode( *this,
+ CSS1_OUTMODE_STYLE_OPT_ON|CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_TABLEBOX, nullptr );
+ if (pBrushItem)
+ OutCSS1_SvxBrush(*this, *pBrushItem, sw::Css1Background::TableCell, nullptr);
+ OutCSS1_SvxBox(*this, rFrameFormat.GetBox());
+ if (!m_bFirstCSS1Property)
+ Strm().WriteChar(cCSS1_style_opt_end);
+}
+
+void SwHTMLWriter::OutCSS1_SectionFormatOptions( const SwFrameFormat& rFrameFormat, const SwFormatCol *pCol )
+{
+ SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
+ CSS1_OUTMODE_ENCODE|
+ CSS1_OUTMODE_SECTION, nullptr );
+
+ const SfxPoolItem *pItem;
+ const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
+ if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) )
+ OutCSS1_SvxBrush( *this, *pItem, sw::Css1Background::Section, nullptr );
+
+ if (mbXHTML)
+ {
+ SvxFrameDirection nDir = GetHTMLDirection(rFrameFormat.GetAttrSet());
+ OString sConvertedDirection = convertDirection(nDir);
+ if (!sConvertedDirection.isEmpty())
+ {
+ OutCSS1_Property(sCSS1_P_dir, sConvertedDirection, nullptr,
+ sw::Css1Background::Section);
+ }
+ }
+
+ if (pCol)
+ {
+ OString sColumnCount(OString::number(static_cast<sal_Int32>(pCol->GetNumCols())));
+ OutCSS1_PropertyAscii(sCSS1_P_column_count, sColumnCount);
+ }
+
+ if( !m_bFirstCSS1Property )
+ Strm().WriteChar( '\"' );
+}
+
+static bool OutCSS1_FrameFormatBrush( SwHTMLWriter& rWrt,
+ const SvxBrushItem& rBrushItem )
+{
+ bool bWritten = false;
+ /// output brush of frame format, if its background color is not "no fill"/"auto fill"
+ /// or it has a background graphic.
+ if( rBrushItem.GetColor() != COL_TRANSPARENT ||
+ !rBrushItem.GetGraphicLink().isEmpty() ||
+ 0 != rBrushItem.GetGraphicPos() )
+ {
+ OutCSS1_SvxBrush( rWrt, rBrushItem, sw::Css1Background::Fly, nullptr );
+ bWritten = true;
+ }
+ return bWritten;
+}
+
+void SwHTMLWriter::OutCSS1_FrameFormatBackground( const SwFrameFormat& rFrameFormat )
+{
+ // If the frame itself has a background, then export.
+ if( OutCSS1_FrameFormatBrush( *this, *rFrameFormat.makeBackgroundBrushItem() ) )
+ return;
+
+ // If the frame is not linked to a page, we use the background of the anchor.
+ const SwFormatAnchor& rAnchor = rFrameFormat.GetAnchor();
+ RndStdIds eAnchorId = rAnchor.GetAnchorId();
+ const SwNode *pAnchorNode = rAnchor.GetAnchorNode();
+ if (RndStdIds::FLY_AT_PAGE != eAnchorId && pAnchorNode)
+ {
+ if( pAnchorNode->IsContentNode() )
+ {
+ // If the frame is linked to a content-node,
+ // we take the background of the content-node, if it has one.
+ if( OutCSS1_FrameFormatBrush( *this,
+ pAnchorNode->GetContentNode()->GetSwAttrSet().GetBackground()) )
+ return;
+
+ // Otherwise we also could be in a table
+ const SwTableNode *pTableNd = pAnchorNode->FindTableNode();
+ if( pTableNd )
+ {
+ const SwStartNode *pBoxSttNd = pAnchorNode->FindTableBoxStartNode();
+ const SwTableBox *pBox =
+ pTableNd->GetTable().GetTableBox( pBoxSttNd->GetIndex() );
+
+ // If the box has a background, we take it.
+ if( OutCSS1_FrameFormatBrush( *this,
+ *pBox->GetFrameFormat()->makeBackgroundBrushItem() ) )
+ return;
+
+ // Otherwise we use that of the lines
+ const SwTableLine *pLine = pBox->GetUpper();
+ while( pLine )
+ {
+ if( OutCSS1_FrameFormatBrush( *this,
+ *pLine->GetFrameFormat()->makeBackgroundBrushItem() ) )
+ return;
+ pBox = pLine->GetUpper();
+ pLine = pBox ? pBox->GetUpper() : nullptr;
+ }
+
+ // If there was none either, we use the background of the table.
+ if( OutCSS1_FrameFormatBrush( *this,
+ *pTableNd->GetTable().GetFrameFormat()->makeBackgroundBrushItem() ) )
+ return;
+ }
+
+ }
+
+ // If the anchor is again in a Fly-Frame, use the background of the Fly-Frame.
+ const SwFrameFormat *pFrameFormat = pAnchorNode->GetFlyFormat();
+ if( pFrameFormat )
+ {
+ OutCSS1_FrameFormatBackground( *pFrameFormat );
+ return;
+ }
+ }
+
+ // At last there is the background of the page, and as the final rescue
+ // the value of the Config.
+ OSL_ENSURE( m_pCurrPageDesc, "no page template found" );
+ if( OutCSS1_FrameFormatBrush( *this,
+ *m_pCurrPageDesc->GetMaster().makeBackgroundBrushItem() ) )
+ return;
+
+ Color aColor( COL_WHITE );
+
+ // The background color is normally only used in Browse-Mode.
+ // We always use it for a HTML document, but for a text document
+ // only if viewed in Browse-Mode.
+ if( m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ||
+ m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE))
+ {
+ SwViewShell *pVSh = m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
+ if ( pVSh &&
+ COL_TRANSPARENT != pVSh->GetViewOptions()->GetRetoucheColor())
+ aColor = pVSh->GetViewOptions()->GetRetoucheColor();
+ }
+
+ OutCSS1_PropertyAscii(sCSS1_P_background, GetCSS1_Color(aColor));
+}
+
+static SwHTMLWriter& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( SwHTMLWriter& rWrt,
+ const SvxUnderlineItem *pUItem,
+ const SvxOverlineItem *pOItem,
+ const SvxCrossedOutItem *pCOItem,
+ const SvxBlinkItem *pBItem )
+{
+ bool bNone = false;
+ OStringBuffer sOut;
+
+ if( pUItem )
+ {
+ switch( pUItem->GetLineStyle() )
+ {
+ case LINESTYLE_NONE:
+ bNone = true;
+ break;
+ case LINESTYLE_DONTKNOW:
+ break;
+ default:
+ if( !rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ {
+ // this also works in HTML does not need to be written as
+ // a STYLE-Options, and must not be written as Hint
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rWrt.mbReqIF,
+ "write underline as Hint?" );
+ sOut.append(sCSS1_PV_underline);
+ }
+ break;
+ }
+ }
+
+ if( pOItem )
+ {
+ switch( pOItem->GetLineStyle() )
+ {
+ case LINESTYLE_NONE:
+ bNone = true;
+ break;
+ case LINESTYLE_DONTKNOW:
+ break;
+ default:
+ if( !rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ {
+ // this also works in HTML does not need to be written as
+ // a STYLE-Options, and must not be written as Hint
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
+ "write overline as Hint?" );
+ if (!sOut.isEmpty())
+ sOut.append(' ');
+ sOut.append(sCSS1_PV_overline);
+ }
+ break;
+ }
+ }
+
+ if( pCOItem )
+ {
+ switch( pCOItem->GetStrikeout() )
+ {
+ case STRIKEOUT_NONE:
+ bNone = true;
+ break;
+ case STRIKEOUT_DONTKNOW:
+ break;
+ default:
+ if( !rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ {
+ // this also works in HTML does not need to be written as
+ // a STYLE-Options, and must not be written as Hint
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rWrt.mbReqIF,
+ "write crossedOut as Hint?" );
+ if (!sOut.isEmpty())
+ sOut.append(' ');
+ sOut.append(sCSS1_PV_line_through);
+ }
+ break;
+ }
+ }
+
+ if( pBItem )
+ {
+ if( !pBItem->GetValue() )
+ {
+ bNone = true;
+ }
+ else if( !rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ {
+ // this also works in HTML does not need to be written as
+ // a STYLE-Options, and must not be written as Hint
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
+ "write blink as Hint?" );
+ if (!sOut.isEmpty())
+ sOut.append(' ');
+ sOut.append(sCSS1_PV_blink);
+ }
+ }
+
+ if (!sOut.isEmpty())
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sOut );
+ else if( bNone )
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sCSS1_PV_none );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxCaseMap( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ switch( static_cast<const SvxCaseMapItem&>(rHt).GetCaseMap() )
+ {
+ case SvxCaseMap::NotMapped:
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_normal );
+ break;
+ case SvxCaseMap::SmallCaps:
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_small_caps );
+ break;
+ case SvxCaseMap::Uppercase:
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_uppercase );
+ break;
+ case SvxCaseMap::Lowercase:
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_lowercase );
+ break;
+ case SvxCaseMap::Capitalize:
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_capitalize );
+ break;
+ default:
+ ;
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxColor( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // Colors do not need to be exported for Style-Option.
+ if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) &&
+ !rWrt.m_bCfgPreferStyles )
+ return rWrt;
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
+ "write color as Hint?" );
+
+ Color aColor( static_cast<const SvxColorItem&>(rHt).GetValue() );
+ if( COL_AUTO == aColor )
+ aColor = COL_BLACK;
+
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_color, GetCSS1_Color(aColor));
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxCrossedOut( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // This function only exports Hints!
+ // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
+
+ if( rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) )
+ OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
+ nullptr, nullptr, static_cast<const SvxCrossedOutItem *>(&rHt), nullptr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxFont( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // No need to export Fonts for the Style-Option.
+ if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ return rWrt;
+
+ sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
+ switch( rHt.Which() )
+ {
+ case RES_CHRATR_CJK_FONT: nScript = CSS1_OUTMODE_CJK; break;
+ case RES_CHRATR_CTL_FONT: nScript = CSS1_OUTMODE_CTL; break;
+ }
+ if( !rWrt.IsCSS1Script( nScript ) )
+ return rWrt;
+
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
+ "write Font as Hint?" );
+
+ OUString sOut;
+ // MS IE3b1 has problems with single quotes
+ sal_uInt16 nMode = rWrt.m_nCSS1OutMode & CSS1_OUTMODE_ANY_ON;
+ sal_Unicode cQuote = nMode == CSS1_OUTMODE_RULE_ON ? '\"' : '\'';
+ SwHTMLWriter::PrepareFontList( static_cast<const SvxFontItem&>(rHt), sOut, cQuote,
+ true );
+
+ rWrt.OutCSS1_Property( sCSS1_P_font_family, sOut );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxFontHeight( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // Font-Height need not be exported in the Style-Option.
+ // For Drop-Caps another Font-Size is exported.
+ if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ||
+ rWrt.IsCSS1Source( CSS1_OUTMODE_DROPCAP ) )
+ return rWrt;
+
+ sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
+ switch( rHt.Which() )
+ {
+ case RES_CHRATR_CJK_FONTSIZE: nScript = CSS1_OUTMODE_CJK; break;
+ case RES_CHRATR_CTL_FONTSIZE: nScript = CSS1_OUTMODE_CTL; break;
+ }
+ if( !rWrt.IsCSS1Script( nScript ) )
+ return rWrt;
+
+ sal_uInt32 nHeight = static_cast<const SvxFontHeightItem&>(rHt).GetHeight();
+ OString sHeight(OString::number(nHeight/20) + sCSS1_UNIT_pt);
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_font_size, sHeight);
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxPosture( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
+ switch( rHt.Which() )
+ {
+ case RES_CHRATR_CJK_POSTURE: nScript = CSS1_OUTMODE_CJK; break;
+ case RES_CHRATR_CTL_POSTURE: nScript = CSS1_OUTMODE_CTL; break;
+ }
+ if( !rWrt.IsCSS1Script( nScript ) )
+ return rWrt;
+
+ std::string_view pStr;
+ switch( static_cast<const SvxPostureItem&>(rHt).GetPosture() )
+ {
+ case ITALIC_NONE: pStr = sCSS1_PV_normal; break;
+ case ITALIC_OBLIQUE: pStr = sCSS1_PV_oblique; break;
+ case ITALIC_NORMAL:
+ if( !rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ {
+ // this also works in HTML does not need to be written as
+ // a STYLE-Options, and must not be written as Hint
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
+ "write italic as Hint?" );
+ pStr = sCSS1_PV_italic;
+ }
+ break;
+ default:
+ ;
+ }
+
+ if( !pStr.empty() )
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_style, pStr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxKerning( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ sal_Int16 nValue = static_cast<const SvxKerningItem&>(rHt).GetValue();
+ if( nValue )
+ {
+ OStringBuffer sOut;
+ if( nValue < 0 )
+ {
+ sOut.append('-');
+ nValue = -nValue;
+ }
+
+ // Width as n.n pt
+ nValue = (nValue + 1) / 2; // 1/10pt
+ sOut.append(OString::number(nValue / 10) + "." + OString::number(nValue % 10) +
+ sCSS1_UNIT_pt);
+
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_letter_spacing, sOut);
+ sOut.setLength(0);
+ }
+ else
+ {
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_letter_spacing,
+ sCSS1_PV_normal );
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxLanguage( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // Only export Language rules
+ if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ return rWrt;
+
+ sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
+ switch( rHt.Which() )
+ {
+ case RES_CHRATR_CJK_LANGUAGE: nScript = CSS1_OUTMODE_CJK; break;
+ case RES_CHRATR_CTL_LANGUAGE: nScript = CSS1_OUTMODE_CTL; break;
+ }
+ if( !rWrt.IsCSS1Script( nScript ) )
+ return rWrt;
+
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
+ "write Language as Hint?" );
+
+ LanguageType eLang = static_cast<const SvxLanguageItem &>(rHt).GetLanguage();
+ if( LANGUAGE_DONTKNOW == eLang )
+ return rWrt;
+
+ OUString sOut = LanguageTag::convertToBcp47( eLang );
+
+ rWrt.OutCSS1_Property( sCSS1_P_so_language, sOut );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxUnderline( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // This function only exports Hints!
+ // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
+
+ if( rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) )
+ OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
+ static_cast<const SvxUnderlineItem *>(&rHt), nullptr, nullptr, nullptr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxOverline( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // This function only exports Hints!
+ // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
+
+ if( rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) )
+ OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
+ nullptr, static_cast<const SvxOverlineItem *>(&rHt), nullptr, nullptr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxHidden( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ if ( static_cast<const SvxCharHiddenItem&>(rHt).GetValue() )
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_display, sCSS1_PV_none );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxFontWeight( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
+ switch( rHt.Which() )
+ {
+ case RES_CHRATR_CJK_WEIGHT: nScript = CSS1_OUTMODE_CJK; break;
+ case RES_CHRATR_CTL_WEIGHT: nScript = CSS1_OUTMODE_CTL; break;
+ }
+ if( !rWrt.IsCSS1Script( nScript ) )
+ return rWrt;
+
+ std::string_view pStr;
+ switch( static_cast<const SvxWeightItem&>(rHt).GetWeight() )
+ {
+ case WEIGHT_ULTRALIGHT: pStr = sCSS1_PV_extra_light; break;
+ case WEIGHT_LIGHT: pStr = sCSS1_PV_light; break;
+ case WEIGHT_SEMILIGHT: pStr = sCSS1_PV_demi_light; break;
+ case WEIGHT_NORMAL: pStr = sCSS1_PV_normal; break;
+ case WEIGHT_SEMIBOLD: pStr = sCSS1_PV_demi_bold; break;
+ case WEIGHT_BOLD:
+ if( !rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ {
+ // this also works in HTML does not need to be written as
+ // a STYLE-Options, and must not be written as Hint
+ OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
+ "write bold as Hint?" );
+ pStr = sCSS1_PV_bold;
+ }
+ break;
+ case WEIGHT_ULTRABOLD: pStr = sCSS1_PV_extra_bold; break;
+ default:
+ pStr = sCSS1_PV_normal;
+ }
+
+ if( !pStr.empty() )
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_weight, pStr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxBlink( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // This function only exports Hints!
+ // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
+
+ if( rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) )
+ OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
+ nullptr, nullptr, nullptr, static_cast<const SvxBlinkItem *>(&rHt) );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxLineSpacing( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // Netscape4 has big problems with cell heights if the line spacing is
+ // changed within a table and the width of the table is not calculated
+ // automatically (== if there is a WIDTH-Option)
+ if( rWrt.m_bOutTable && rWrt.m_bCfgNetscape4 )
+ return rWrt;
+
+ const SvxLineSpacingItem& rLSItem = static_cast<const SvxLineSpacingItem&>(rHt);
+
+ sal_uInt16 nHeight = 0;
+ sal_uInt16 nPercentHeight = 0;
+ SvxLineSpaceRule eLineSpace = rLSItem.GetLineSpaceRule();
+ switch( rLSItem.GetInterLineSpaceRule() )
+ {
+ case SvxInterLineSpaceRule::Off:
+ case SvxInterLineSpaceRule::Fix:
+ {
+ switch( eLineSpace )
+ {
+ case SvxLineSpaceRule::Min:
+ case SvxLineSpaceRule::Fix:
+ nHeight = rLSItem.GetLineHeight();
+ break;
+ case SvxLineSpaceRule::Auto:
+ nPercentHeight = 100;
+ break;
+ default:
+ ;
+ }
+ }
+ break;
+ case SvxInterLineSpaceRule::Prop:
+ nPercentHeight = rLSItem.GetPropLineSpace();
+ break;
+
+ default:
+ ;
+ }
+
+ if( nHeight )
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_line_height, static_cast<tools::Long>(nHeight) );
+ else if( nPercentHeight &&
+ !(nPercentHeight < 115 && rWrt.m_bParaDotLeaders )) // avoid HTML scrollbars and missing descenders
+ {
+ OString sHeight(OString::number(nPercentHeight) + "%");
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_line_height, sHeight);
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxAdjust( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // Export Alignment in Style-Option only if the Tag does not allow ALIGN=xxx
+ if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) &&
+ !rWrt.m_bNoAlign)
+ return rWrt;
+
+ std::string_view pStr;
+ switch( static_cast<const SvxAdjustItem&>(rHt).GetAdjust() )
+ {
+ case SvxAdjust::Left: pStr = sCSS1_PV_left; break;
+ case SvxAdjust::Right: pStr = sCSS1_PV_right; break;
+ case SvxAdjust::Block: pStr = sCSS1_PV_justify; break;
+ case SvxAdjust::Center: pStr = sCSS1_PV_center; break;
+ default:
+ ;
+ }
+
+ if( !pStr.empty() )
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_align, pStr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxFormatSplit( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ std::string_view pStr = static_cast<const SvxFormatSplitItem&>(rHt).GetValue()
+ ? sCSS1_PV_auto
+ : sCSS1_PV_avoid;
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SwFormatLayoutSplit( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ std::string_view pStr = static_cast<const SwFormatLayoutSplit&>(rHt).GetValue()
+ ? sCSS1_PV_auto
+ : sCSS1_PV_avoid;
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxWidows( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ OString aStr(OString::number(static_cast<const SvxWidowsItem&>(rHt).GetValue()));
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_widows, aStr );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxOrphans( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ OString aStr(OString::number(static_cast<const SvxOrphansItem&>(rHt).GetValue()));
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_orphans, aStr );
+
+ return rWrt;
+}
+
+static void OutCSS1_SwFormatDropAttrs( SwHTMLWriter& rHWrt,
+ const SwFormatDrop& rDrop,
+ const SfxItemSet *pCharFormatItemSet )
+{
+ // Text flows around on right side
+ rHWrt.OutCSS1_PropertyAscii( sCSS1_P_float, sCSS1_PV_left );
+
+ // number of lines -> use % for Font-Height!
+ OString sOut(OString::number(rDrop.GetLines()*100) + "%");
+ rHWrt.OutCSS1_PropertyAscii(sCSS1_P_font_size, sOut);
+
+ // distance to Text = right margin
+ sal_uInt16 nDistance = rDrop.GetDistance();
+ if( nDistance > 0 )
+ rHWrt.OutCSS1_UnitProperty( sCSS1_P_margin_right, nDistance );
+
+ const SwCharFormat *pDCCharFormat = rDrop.GetCharFormat();
+ if( pCharFormatItemSet )
+ rHWrt.OutCSS1_SfxItemSet( *pCharFormatItemSet );
+ else if( pDCCharFormat )
+ rHWrt.OutCSS1_SfxItemSet( pDCCharFormat->GetAttrSet() );
+ else if( (rHWrt.m_nCSS1OutMode & CSS1_OUTMODE_ANY_OFF) == CSS1_OUTMODE_RULE_OFF )
+ rHWrt.Strm().WriteOString( sCSS1_rule_end );
+
+}
+
+static SwHTMLWriter& OutCSS1_SwFormatDrop( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // never export as an Option of a paragraph, but only as Hints
+ if( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) )
+ return rWrt;
+
+ if( rWrt.m_bTagOn )
+ {
+ SwCSS1OutMode aMode( rWrt,
+ rWrt.m_nCSS1Script|CSS1_OUTMODE_SPAN_TAG1_ON|CSS1_OUTMODE_ENCODE|
+ CSS1_OUTMODE_DROPCAP, nullptr );
+
+ OutCSS1_SwFormatDropAttrs( rWrt, static_cast<const SwFormatDrop&>(rHt) );
+ // A "> is already printed by the calling OutCSS1_HintAsSpanTag.
+ }
+ else
+ {
+ HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false );
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SwFormatFrameSize( SwHTMLWriter& rWrt, const SfxPoolItem& rHt,
+ Css1FrameSize nMode )
+{
+ const SwFormatFrameSize& rFSItem = static_cast<const SwFormatFrameSize&>(rHt);
+
+ if( nMode & Css1FrameSize::Width )
+ {
+ sal_uInt8 nPercentWidth = rFSItem.GetWidthPercent();
+ if( nPercentWidth )
+ {
+ OString sOut(OString::number(nPercentWidth) + "%");
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_width, sOut);
+ }
+ else if( nMode & Css1FrameSize::Pixel )
+ {
+ rWrt.OutCSS1_PixelProperty( sCSS1_P_width,
+ rFSItem.GetSize().Width() );
+ }
+ else
+ {
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_width,
+ rFSItem.GetSize().Width() );
+ }
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxFirstLineIndent(SwHTMLWriter & rWrt, SfxPoolItem const& rHt)
+{
+ const SvxFirstLineIndentItem & rFirstLine(static_cast<const SvxFirstLineIndentItem&>(rHt));
+
+ // No Export of a firm attribute is needed if the new values
+ // match that of the current template
+
+ // The LineIndent of the first line might contain the room for numbering
+ tools::Long nFirstLineIndent = static_cast<tools::Long>(rFirstLine.GetTextFirstLineOffset())
+ - rWrt.m_nFirstLineIndent;
+ if (rWrt.m_nDfltFirstLineIndent != nFirstLineIndent)
+ {
+ rWrt.OutCSS1_UnitProperty(sCSS1_P_text_indent, nFirstLineIndent);
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxTextLeftMargin(SwHTMLWriter & rWrt, SfxPoolItem const& rHt)
+{
+ const SvxTextLeftMarginItem& rLeftMargin(static_cast<const SvxTextLeftMarginItem&>(rHt));
+
+ // No Export of a firm attribute is needed if the new values
+ // match that of the current template
+
+ // A left margin can exist because of a list nearby
+ tools::Long nLeftMargin = rLeftMargin.GetTextLeft() - rWrt.m_nLeftMargin;
+ if (rWrt.m_nDfltLeftMargin != nLeftMargin)
+ {
+ rWrt.OutCSS1_UnitProperty(sCSS1_P_margin_left, nLeftMargin);
+
+ // max-width = max-width - margin-left for TOC paragraphs with dot leaders
+ if (rWrt.m_bParaDotLeaders)
+ rWrt.OutCSS1_UnitProperty(sCSS1_P_max_width, tools::Long(DOT_LEADERS_MAX_WIDTH/2.54*72*20) - nLeftMargin);
+
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxRightMargin(SwHTMLWriter & rWrt, SfxPoolItem const& rHt)
+{
+ const SvxRightMarginItem& rRightMargin(static_cast<const SvxRightMarginItem&>(rHt));
+
+ // No Export of a firm attribute is needed if the new values
+ // match that of the current template
+
+ if (rWrt.m_nDfltRightMargin != rRightMargin.GetRight())
+ {
+ rWrt.OutCSS1_UnitProperty(sCSS1_P_margin_right, rRightMargin.GetRight());
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxLRSpace( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ const SvxLRSpaceItem& rLRItem = static_cast<const SvxLRSpaceItem&>(rHt);
+
+ // No Export of a firm attribute is needed if the new values
+ // match that of the current template
+
+ // A left margin can exist because of a list nearby
+ tools::Long nLeftMargin = rLRItem.GetTextLeft() - rWrt.m_nLeftMargin;
+ if( rWrt.m_nDfltLeftMargin != nLeftMargin )
+ {
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLeftMargin );
+
+ // max-width = max-width - margin-left for TOC paragraphs with dot leaders
+ if( rWrt.m_bParaDotLeaders )
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_max_width, tools::Long(DOT_LEADERS_MAX_WIDTH/2.54*72*20) - nLeftMargin );
+
+ }
+
+ if( rWrt.m_nDfltRightMargin != rLRItem.GetRight() )
+ {
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_right, rLRItem.GetRight() );
+ }
+
+ // The LineIndent of the first line might contain the room for numbering
+ tools::Long nFirstLineIndent = static_cast<tools::Long>(rLRItem.GetTextFirstLineOffset()) -
+ rWrt.m_nFirstLineIndent;
+ if( rWrt.m_nDfltFirstLineIndent != nFirstLineIndent )
+ {
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent,
+ nFirstLineIndent );
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxULSpace( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ const SvxULSpaceItem& rULItem = static_cast<const SvxULSpaceItem&>(rHt);
+
+ if( rWrt.m_nDfltTopMargin != rULItem.GetUpper() )
+ {
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_top,
+ static_cast<tools::Long>(rULItem.GetUpper()) );
+ }
+
+ if( rWrt.m_nDfltBottomMargin != rULItem.GetLower() )
+ {
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_bottom,
+ static_cast<tools::Long>(rULItem.GetLower()) );
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxULSpace_SvxLRSpace( SwHTMLWriter& rWrt,
+ const SvxULSpaceItem *pULItem,
+ const SvxLRSpaceItem *pLRItem )
+{
+ if( pLRItem && pULItem &&
+ pLRItem->GetLeft() == pLRItem->GetRight() &&
+ pLRItem->GetLeft() == pULItem->GetUpper() &&
+ pLRItem->GetLeft() == pULItem->GetLower() &&
+ pLRItem->GetLeft() != rWrt.m_nDfltLeftMargin &&
+ pLRItem->GetRight() != rWrt.m_nDfltRightMargin &&
+ pULItem->GetUpper() != rWrt.m_nDfltTopMargin &&
+ pULItem->GetLower() != rWrt.m_nDfltBottomMargin )
+ {
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_margin, pLRItem->GetLeft() );
+ }
+ else
+ {
+ if( pLRItem )
+ OutCSS1_SvxLRSpace( rWrt, *pLRItem );
+ if( pULItem )
+ OutCSS1_SvxULSpace( rWrt, *pULItem );
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxULSpace_SvxLRSpace( SwHTMLWriter& rWrt,
+ const SfxItemSet& rItemSet )
+{
+ const SvxLRSpaceItem *pLRSpace = rItemSet.GetItemIfSet( RES_LR_SPACE, false/*bDeep*/ );
+ const SvxULSpaceItem *pULSpace = rItemSet.GetItemIfSet( RES_UL_SPACE, false/*bDeep*/ );
+
+ if( pLRSpace || pULSpace )
+ OutCSS1_SvxULSpace_SvxLRSpace( rWrt, pULSpace, pLRSpace );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( SwHTMLWriter& rWrt,
+ const SvxFormatBreakItem *pBreakItem,
+ const SwFormatPageDesc *pPDescItem,
+ const SvxFormatKeepItem *pKeepItem )
+{
+ if( !rWrt.IsHTMLMode(HTMLMODE_PRINT_EXT) )
+ return rWrt;
+
+ std::string_view pBreakBefore;
+ std::string_view pBreakAfter;
+
+ if( pKeepItem )
+ {
+ pBreakAfter = pKeepItem->GetValue() ? sCSS1_PV_avoid : sCSS1_PV_auto;
+ }
+ if( pBreakItem )
+ {
+ switch( pBreakItem->GetBreak() )
+ {
+ case SvxBreak::NONE:
+ pBreakBefore = sCSS1_PV_auto;
+ if( pBreakAfter.empty() )
+ pBreakAfter = sCSS1_PV_auto;
+ break;
+
+ case SvxBreak::PageBefore:
+ pBreakBefore = sCSS1_PV_always;
+ break;
+
+ case SvxBreak::PageAfter:
+ pBreakAfter= sCSS1_PV_always;
+ break;
+
+ default:
+ ;
+ }
+ }
+ if( pPDescItem )
+ {
+ const SwPageDesc *pPDesc = pPDescItem->GetPageDesc();
+ if( pPDesc )
+ {
+ switch( pPDesc->GetPoolFormatId() )
+ {
+ case RES_POOLPAGE_LEFT: pBreakBefore = sCSS1_PV_left; break;
+ case RES_POOLPAGE_RIGHT: pBreakBefore = sCSS1_PV_right; break;
+ default: pBreakBefore = sCSS1_PV_always; break;
+ }
+ }
+ else if( pBreakBefore.empty() )
+ {
+ pBreakBefore = sCSS1_PV_auto;
+ }
+ }
+
+ if (rWrt.mbSkipHeaderFooter)
+ // No page break when writing only a fragment.
+ return rWrt;
+
+ if( !pBreakBefore.empty() )
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_before,
+ pBreakBefore );
+ if( !pBreakAfter.empty() )
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_after,
+ pBreakAfter );
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( SwHTMLWriter& rWrt,
+ const SfxItemSet& rItemSet,
+ bool bDeep )
+{
+ const SvxFormatBreakItem *pBreakItem = rItemSet.GetItemIfSet( RES_BREAK, bDeep );
+
+ const SwFormatPageDesc *pPDescItem = nullptr;
+ if( !rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ||
+ !rWrt.m_bCSS1IgnoreFirstPageDesc ||
+ rWrt.m_pStartNdIdx->GetIndex() !=
+ rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex() )
+ pPDescItem = rItemSet.GetItemIfSet( RES_PAGEDESC, bDeep );
+
+ const SvxFormatKeepItem *pKeepItem = rItemSet.GetItemIfSet( RES_KEEP, bDeep );
+
+ if( pBreakItem || pPDescItem || pKeepItem )
+ OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( rWrt, pBreakItem,
+ pPDescItem, pKeepItem );
+
+ return rWrt;
+}
+
+// Wrapper for OutCSS1_SfxItemSet etc.
+static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ OutCSS1_SvxBrush( rWrt, rHt, sw::Css1Background::Attr, nullptr );
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& rWrt, const SfxPoolItem& rHt,
+ sw::Css1Background nMode,
+ const OUString* pGraphicName)
+{
+ // The Character-Attribute is skipped, if we are about to
+ // exporting options
+ if( rHt.Which() < RES_CHRATR_END &&
+ rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ return rWrt;
+
+ // start getting a few values
+// const Brush &rBrush = static_cast<const SvxBrushItem &>(rHt).GetBrush();
+ const Color & rColor = static_cast<const SvxBrushItem &>(rHt).GetColor();
+ OUString aLink = pGraphicName ? *pGraphicName
+ : static_cast<const SvxBrushItem &>(rHt).GetGraphicLink();
+ SvxGraphicPosition ePos = static_cast<const SvxBrushItem &>(rHt).GetGraphicPos();
+ if( sw::Css1Background::Page == nMode && !rWrt.mbEmbedImages )
+ {
+ // page style images are exported if not tiled
+ if( aLink.isEmpty() || GPOS_TILED==ePos )
+ return rWrt;
+ }
+
+ // get the color
+ bool bColor = false;
+ /// set <bTransparent> to true, if color is "no fill"/"auto fill"
+ bool bTransparent = (rColor == COL_TRANSPARENT);
+ Color aColor;
+ if( !bTransparent )
+ {
+ aColor = rColor;
+ bColor = true;
+ }
+
+ // and now the Graphic
+ OUString aGraphicInBase64;
+
+ // Embedded Graphic -> export WriteEmbedded
+ const Graphic* pGrf = nullptr;
+ if( rWrt.mbEmbedImages || aLink.isEmpty())
+ {
+ pGrf = static_cast<const SvxBrushItem &>(rHt).GetGraphic();
+ if( pGrf )
+ {
+ if( !XOutBitmap::GraphicToBase64(*pGrf, aGraphicInBase64) )
+ {
+ rWrt.m_nWarn = WARN_SWG_POOR_LOAD;
+ }
+ }
+ aLink.clear();
+ }
+ else if( !pGraphicName && rWrt.m_bCfgCpyLinkedGrfs )
+ {
+ OUString aGraphicAsLink = aLink;
+ rWrt.CopyLocalFileToINet( aGraphicAsLink );
+ aLink = aGraphicAsLink;
+ }
+ // In tables we only export something if there is a Graphic
+ if( (nMode == sw::Css1Background::Table || nMode == sw::Css1Background::TableRow) && !pGrf && !aLink.isEmpty())
+ return rWrt;
+
+ // if necessary, add the orientation of the Graphic
+ std::string_view pRepeat, pHori, pVert;
+ if( pGrf || !aLink.isEmpty() )
+ {
+ if( GPOS_TILED==ePos )
+ {
+ pRepeat = sCSS1_PV_repeat;
+ }
+ else
+ {
+ switch( ePos )
+ {
+ case GPOS_LT:
+ case GPOS_MT:
+ case GPOS_RT:
+ pHori = sCSS1_PV_top;
+ break;
+
+ case GPOS_LM:
+ case GPOS_MM:
+ case GPOS_RM:
+ pHori = sCSS1_PV_middle;
+ break;
+
+ case GPOS_LB:
+ case GPOS_MB:
+ case GPOS_RB:
+ pHori = sCSS1_PV_bottom;
+ break;
+
+ default:
+ ;
+ }
+
+ switch( ePos )
+ {
+ case GPOS_LT:
+ case GPOS_LM:
+ case GPOS_LB:
+ pVert = sCSS1_PV_left;
+ break;
+
+ case GPOS_MT:
+ case GPOS_MM:
+ case GPOS_MB:
+ pVert = sCSS1_PV_center;
+ break;
+
+ case GPOS_RT:
+ case GPOS_RM:
+ case GPOS_RB:
+ pVert = sCSS1_PV_right;
+ break;
+
+ default:
+ ;
+ }
+
+ if( !pHori.empty() || !pVert.empty() )
+ pRepeat = sCSS1_PV_no_repeat;
+ }
+ }
+
+ // now build the string
+ OUString sOut;
+ if( !pGrf && aLink.isEmpty() && !bColor )
+ {
+ // no color and no Link, but a transparent Brush
+ if( bTransparent && sw::Css1Background::Fly != nMode )
+ sOut += OStringToOUString(sCSS1_PV_transparent, RTL_TEXTENCODING_ASCII_US);
+ }
+ else
+ {
+ if( bColor )
+ {
+ OString sTmp(GetCSS1_Color(aColor));
+ sOut += OStringToOUString(sTmp, RTL_TEXTENCODING_ASCII_US);
+ }
+
+ if( pGrf || !aLink.isEmpty() )
+ {
+ if( bColor )
+ sOut += " ";
+
+ if(pGrf)
+ {
+ sOut += OStringToOUString(sCSS1_url, RTL_TEXTENCODING_ASCII_US) +
+ "(\'" OOO_STRING_SVTOOLS_HTML_O_data ":" + aGraphicInBase64 + "\')";
+ }
+ else
+ {
+ sOut += OStringToOUString(sCSS1_url, RTL_TEXTENCODING_ASCII_US)+
+ "(" + URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(),
+ aLink) + ")";
+ }
+
+ if( !pRepeat.empty() )
+ {
+ sOut += " " + OStringToOUString(pRepeat, RTL_TEXTENCODING_ASCII_US);
+ }
+
+ if( !pHori.empty() )
+ {
+ sOut += " " + OStringToOUString(pHori, RTL_TEXTENCODING_ASCII_US);
+ }
+ if( !pVert.empty() )
+ {
+ sOut += " " + OStringToOUString(pVert, RTL_TEXTENCODING_ASCII_US);
+ }
+
+ sOut += " " + OStringToOUString(sCSS1_PV_scroll, RTL_TEXTENCODING_ASCII_US) + " ";
+ }
+ }
+
+ if( !sOut.isEmpty() )
+ {
+ rWrt.OutCSS1_Property(sCSS1_P_background, std::string_view(), &sOut,
+ nMode);
+ }
+
+ return rWrt;
+}
+
+static void OutCSS1_SvxBorderLine( SwHTMLWriter& rWrt,
+ std::string_view pProperty,
+ const SvxBorderLine *pLine )
+{
+ if( !pLine || pLine->isEmpty() )
+ {
+ rWrt.OutCSS1_PropertyAscii( pProperty, sCSS1_PV_none );
+ return;
+ }
+
+ sal_Int32 nWidth = pLine->GetWidth();
+
+ OStringBuffer sOut;
+ if( nWidth <= o3tl::convert(1, o3tl::Length::px, o3tl::Length::twip) )
+ {
+ // If the width is smaller than one pixel, then export as 1px
+ // so that Netscape and IE show the line.
+ sOut.append("1px");
+ }
+ else
+ {
+ nWidth *= 5; // 1/100pt
+
+ // width in n.nn pt
+ sOut.append(OString::number(nWidth / 100) + "." + OString::number((nWidth/10) % 10) +
+ OString::number(nWidth % 10) + sCSS1_UNIT_pt);
+ }
+
+ // Line-Style: solid or double
+ sOut.append(' ');
+ switch (pLine->GetBorderLineStyle())
+ {
+ case SvxBorderLineStyle::SOLID:
+ sOut.append(sCSS1_PV_solid);
+ break;
+ case SvxBorderLineStyle::DOTTED:
+ sOut.append(sCSS1_PV_dotted);
+ break;
+ case SvxBorderLineStyle::DASHED:
+ sOut.append(sCSS1_PV_dashed);
+ break;
+ case SvxBorderLineStyle::DOUBLE:
+ case SvxBorderLineStyle::THINTHICK_SMALLGAP:
+ case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
+ case SvxBorderLineStyle::THINTHICK_LARGEGAP:
+ case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
+ case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
+ case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
+ sOut.append(sCSS1_PV_double);
+ break;
+ case SvxBorderLineStyle::EMBOSSED:
+ sOut.append(sCSS1_PV_ridge);
+ break;
+ case SvxBorderLineStyle::ENGRAVED:
+ sOut.append(sCSS1_PV_groove);
+ break;
+ case SvxBorderLineStyle::INSET:
+ sOut.append(sCSS1_PV_inset);
+ break;
+ case SvxBorderLineStyle::OUTSET:
+ sOut.append(sCSS1_PV_outset);
+ break;
+ default:
+ sOut.append(sCSS1_PV_none);
+ }
+ sOut.append(' ');
+
+ // and also the color
+ sOut.append(GetCSS1_Color(pLine->GetColor()));
+
+ rWrt.OutCSS1_PropertyAscii(pProperty, sOut);
+}
+
+SwHTMLWriter& OutCSS1_SvxBox( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // Avoid interference between character and paragraph attributes
+ if( rHt.Which() < RES_CHRATR_END &&
+ rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
+ return rWrt;
+
+ if( rHt.Which() == RES_CHRATR_BOX )
+ {
+ if( rWrt.m_bTagOn )
+ {
+ // Inline-block to make the line height changing correspond to the character border
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_display, "inline-block");
+ }
+ else
+ {
+ HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false );
+ return rWrt;
+ }
+ }
+
+ const SvxBoxItem& rBoxItem = static_cast<const SvxBoxItem&>(rHt);
+ const SvxBorderLine *pTop = rBoxItem.GetTop();
+ const SvxBorderLine *pBottom = rBoxItem.GetBottom();
+ const SvxBorderLine *pLeft = rBoxItem.GetLeft();
+ const SvxBorderLine *pRight = rBoxItem.GetRight();
+
+ if( (pTop && pBottom && pLeft && pRight &&
+ *pTop == *pBottom && *pTop == *pLeft && *pTop == *pRight) ||
+ (!pTop && !pBottom && !pLeft && !pRight) )
+ {
+ // all Lines are set and equal, or all Lines are not set
+ // => border : ...
+ OutCSS1_SvxBorderLine( rWrt, sCSS1_P_border, pTop );
+ }
+ else
+ {
+ // otherwise export all Lines separately
+ OutCSS1_SvxBorderLine( rWrt, sCSS1_P_border_top, pTop );
+ OutCSS1_SvxBorderLine( rWrt, sCSS1_P_border_bottom, pBottom );
+ OutCSS1_SvxBorderLine( rWrt, sCSS1_P_border_left, pLeft );
+ OutCSS1_SvxBorderLine( rWrt, sCSS1_P_border_right, pRight );
+ }
+
+ tools::Long nTopDist = pTop ? rBoxItem.GetDistance( SvxBoxItemLine::TOP ) : 0;
+ tools::Long nBottomDist = pBottom ? rBoxItem.GetDistance( SvxBoxItemLine::BOTTOM ) : 0;
+ tools::Long nLeftDist = pLeft ? rBoxItem.GetDistance( SvxBoxItemLine::LEFT ) : 0;
+ tools::Long nRightDist = pRight ? rBoxItem.GetDistance( SvxBoxItemLine::RIGHT ) : 0;
+
+ if( nTopDist == nBottomDist && nLeftDist == nRightDist )
+ {
+ OStringBuffer sVal;
+ AddUnitPropertyValue(sVal, nTopDist, rWrt.GetCSS1Unit());
+ if( nTopDist != nLeftDist )
+ {
+ sVal.append(' ');
+ AddUnitPropertyValue(sVal, nLeftDist, rWrt.GetCSS1Unit());
+ }
+ rWrt.OutCSS1_PropertyAscii(sCSS1_P_padding, sVal);
+ }
+ else
+ {
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_padding_top, nTopDist );
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_padding_bottom, nBottomDist );
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_padding_left, nLeftDist );
+ rWrt.OutCSS1_UnitProperty( sCSS1_P_padding_right, nRightDist );
+ }
+
+ return rWrt;
+}
+
+static SwHTMLWriter& OutCSS1_SvxFrameDirection( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ // Language will be exported rules only
+ if( !rWrt.IsCSS1Source( CSS1_OUTMODE_TEMPLATE ) )
+ return rWrt;
+
+ SvxFrameDirection nDir =
+ static_cast< const SvxFrameDirectionItem& >( rHt ).GetValue();
+ std::string_view pStr;
+ switch( nDir )
+ {
+ case SvxFrameDirection::Horizontal_LR_TB:
+ case SvxFrameDirection::Vertical_LR_TB:
+ pStr = sCSS1_PV_ltr;
+ break;
+ case SvxFrameDirection::Horizontal_RL_TB:
+ case SvxFrameDirection::Vertical_RL_TB:
+ pStr = sCSS1_PV_rtl;
+ break;
+ case SvxFrameDirection::Environment:
+ pStr = sCSS1_PV_inherit;
+ break;
+ default: break;
+ }
+
+ if( !pStr.empty() )
+ rWrt.OutCSS1_PropertyAscii( sCSS1_P_direction, pStr );
+
+ return rWrt;
+}
+
+/*
+ * Place here the table for the HTML-Function-Pointer to the
+ * Export-Functions.
+ * They are local structures, only needed within the HTML-DLL.
+ */
+
+SwAttrFnTab const aCSS1AttrFnTab = {
+/* RES_CHRATR_CASEMAP */ OutCSS1_SvxCaseMap,
+/* RES_CHRATR_CHARSETCOLOR */ nullptr,
+/* RES_CHRATR_COLOR */ OutCSS1_SvxColor,
+/* RES_CHRATR_CONTOUR */ nullptr,
+/* RES_CHRATR_CROSSEDOUT */ OutCSS1_SvxCrossedOut,
+/* RES_CHRATR_ESCAPEMENT */ nullptr,
+/* RES_CHRATR_FONT */ OutCSS1_SvxFont,
+/* RES_CHRATR_FONTSIZE */ OutCSS1_SvxFontHeight,
+/* RES_CHRATR_KERNING */ OutCSS1_SvxKerning,
+/* RES_CHRATR_LANGUAGE */ OutCSS1_SvxLanguage,
+/* RES_CHRATR_POSTURE */ OutCSS1_SvxPosture,
+/* RES_CHRATR_UNUSED1*/ nullptr,
+/* RES_CHRATR_SHADOWED */ nullptr,
+/* RES_CHRATR_UNDERLINE */ OutCSS1_SvxUnderline,
+/* RES_CHRATR_WEIGHT */ OutCSS1_SvxFontWeight,
+/* RES_CHRATR_WORDLINEMODE */ nullptr,
+/* RES_CHRATR_AUTOKERN */ nullptr,
+/* RES_CHRATR_BLINK */ OutCSS1_SvxBlink,
+/* RES_CHRATR_NOHYPHEN */ nullptr, // new: don't separate
+/* RES_CHRATR_UNUSED2 */ nullptr,
+/* RES_CHRATR_BACKGROUND */ OutCSS1_SvxBrush, // new: character background
+/* RES_CHRATR_CJK_FONT */ OutCSS1_SvxFont,
+/* RES_CHRATR_CJK_FONTSIZE */ OutCSS1_SvxFontHeight,
+/* RES_CHRATR_CJK_LANGUAGE */ OutCSS1_SvxLanguage,
+/* RES_CHRATR_CJK_POSTURE */ OutCSS1_SvxPosture,
+/* RES_CHRATR_CJK_WEIGHT */ OutCSS1_SvxFontWeight,
+/* RES_CHRATR_CTL_FONT */ OutCSS1_SvxFont,
+/* RES_CHRATR_CTL_FONTSIZE */ OutCSS1_SvxFontHeight,
+/* RES_CHRATR_CTL_LANGUAGE */ OutCSS1_SvxLanguage,
+/* RES_CHRATR_CTL_POSTURE */ OutCSS1_SvxPosture,
+/* RES_CHRATR_CTL_WEIGHT */ OutCSS1_SvxFontWeight,
+/* RES_CHRATR_ROTATE */ nullptr,
+/* RES_CHRATR_EMPHASIS_MARK */ nullptr,
+/* RES_CHRATR_TWO_LINES */ nullptr,
+/* RES_CHRATR_SCALEW */ nullptr,
+/* RES_CHRATR_RELIEF */ nullptr,
+/* RES_CHRATR_HIDDEN */ OutCSS1_SvxHidden,
+/* RES_CHRATR_OVERLINE */ OutCSS1_SvxOverline,
+/* RES_CHRATR_RSID */ nullptr,
+/* RES_CHRATR_BOX */ OutCSS1_SvxBox,
+/* RES_CHRATR_SHADOW */ nullptr,
+/* RES_CHRATR_HIGHLIGHT */ nullptr,
+/* RES_CHRATR_GRABBAG */ nullptr,
+/* RES_CHRATR_BIDIRTL */ nullptr,
+/* RES_CHRATR_IDCTHINT */ nullptr,
+
+/* RES_TXTATR_REFMARK */ nullptr,
+/* RES_TXTATR_TOXMARK */ nullptr,
+/* RES_TXTATR_META */ nullptr,
+/* RES_TXTATR_METAFIELD */ nullptr,
+/* RES_TXTATR_AUTOFMT */ nullptr,
+/* RES_TXTATR_INETFMT */ nullptr,
+/* RES_TXTATR_CHARFMT */ nullptr,
+/* RES_TXTATR_CJK_RUBY */ nullptr,
+/* RES_TXTATR_UNKNOWN_CONTAINER */ nullptr,
+/* RES_TXTATR_INPUTFIELD */ nullptr,
+/* RES_TXTATR_CONTENTCONTROL */ nullptr,
+
+/* RES_TXTATR_FIELD */ nullptr,
+/* RES_TXTATR_FLYCNT */ nullptr,
+/* RES_TXTATR_FTN */ nullptr,
+/* RES_TXTATR_ANNOTATION */ nullptr,
+/* RES_TXTATR_LINEBREAK */ nullptr,
+/* RES_TXTATR_DUMMY1 */ nullptr, // Dummy:
+
+/* RES_PARATR_LINESPACING */ OutCSS1_SvxLineSpacing,
+/* RES_PARATR_ADJUST */ OutCSS1_SvxAdjust,
+/* RES_PARATR_SPLIT */ OutCSS1_SvxFormatSplit,
+/* RES_PARATR_ORPHANS */ OutCSS1_SvxOrphans,
+/* RES_PARATR_WIDOWS */ OutCSS1_SvxWidows,
+/* RES_PARATR_TABSTOP */ nullptr,
+/* RES_PARATR_HYPHENZONE*/ nullptr,
+/* RES_PARATR_DROP */ OutCSS1_SwFormatDrop,
+/* RES_PARATR_REGISTER */ nullptr, // new: register-true
+/* RES_PARATR_NUMRULE */ nullptr,
+/* RES_PARATR_SCRIPTSPACE */ nullptr,
+/* RES_PARATR_HANGINGPUNCTUATION */ nullptr,
+/* RES_PARATR_FORBIDDEN_RULES */ nullptr, // new
+/* RES_PARATR_VERTALIGN */ nullptr, // new
+/* RES_PARATR_SNAPTOGRID*/ nullptr, // new
+/* RES_PARATR_CONNECT_TO_BORDER */ nullptr, // new
+/* RES_PARATR_OUTLINELEVEL */ nullptr, // new since cws outlinelevel
+/* RES_PARATR_RSID */ nullptr, // new
+/* RES_PARATR_GRABBAG */ nullptr,
+
+/* RES_PARATR_LIST_ID */ nullptr, // new
+/* RES_PARATR_LIST_LEVEL */ nullptr, // new
+/* RES_PARATR_LIST_ISRESTART */ nullptr, // new
+/* RES_PARATR_LIST_RESTARTVALUE */ nullptr, // new
+/* RES_PARATR_LIST_ISCOUNTED */ nullptr, // new
+/* RES_PARATR_LIST_AUTOFMT */ nullptr, // new
+
+/* RES_FILL_ORDER */ nullptr,
+/* RES_FRM_SIZE */ nullptr,
+/* RES_PAPER_BIN */ nullptr,
+/* RES_MARGIN_FIRSTLINE */ OutCSS1_SvxFirstLineIndent,
+/* RES_MARGIN_TEXTLEFT */ OutCSS1_SvxTextLeftMargin,
+/* RES_MARGIN_RIGHT */ OutCSS1_SvxRightMargin,
+/* RES_MARGIN_LEFT */ nullptr,
+/* RES_MARGIN_GUTTER */ nullptr,
+/* RES_MARGIN_GUTTER_RIGHT */ nullptr,
+/* RES_LR_SPACE */ OutCSS1_SvxLRSpace,
+/* RES_UL_SPACE */ OutCSS1_SvxULSpace,
+/* RES_PAGEDESC */ nullptr,
+/* RES_BREAK */ nullptr,
+/* RES_CNTNT */ nullptr,
+/* RES_HEADER */ nullptr,
+/* RES_FOOTER */ nullptr,
+/* RES_PRINT */ nullptr,
+/* RES_OPAQUE */ nullptr,
+/* RES_PROTECT */ nullptr,
+/* RES_SURROUND */ nullptr,
+/* RES_VERT_ORIENT */ nullptr,
+/* RES_HORI_ORIENT */ nullptr,
+/* RES_ANCHOR */ nullptr,
+/* RES_BACKGROUND */ OutCSS1_SvxBrush,
+/* RES_BOX */ OutCSS1_SvxBox,
+/* RES_SHADOW */ nullptr,
+/* RES_FRMMACRO */ nullptr,
+/* RES_COL */ nullptr,
+/* RES_KEEP */ nullptr,
+/* RES_URL */ nullptr,
+/* RES_EDIT_IN_READONLY */ nullptr,
+/* RES_LAYOUT_SPLIT */ nullptr,
+/* RES_CHAIN */ nullptr,
+/* RES_TEXTGRID */ nullptr,
+/* RES_LINENUMBER */ nullptr,
+/* RES_FTN_AT_TXTEND */ nullptr,
+/* RES_END_AT_TXTEND */ nullptr,
+/* RES_COLUMNBALANCE */ nullptr,
+/* RES_FRAMEDIR */ OutCSS1_SvxFrameDirection,
+/* RES_HEADER_FOOTER_EAT_SPACING */ nullptr,
+/* RES_ROW_SPLIT */ nullptr,
+/* RES_FLY_SPLIT */ nullptr,
+/* RES_FOLLOW_TEXT_FLOW */ nullptr,
+/* RES_COLLAPSING_BORDERS */ nullptr,
+/* RES_WRAP_INFLUENCE_ON_OBJPOS */ nullptr,
+/* RES_AUTO_STYLE */ nullptr,
+/* RES_FRMATR_STYLE_NAME */ nullptr,
+/* RES_FRMATR_CONDITIONAL_STYLE_NAME */ nullptr,
+/* RES_FRMATR_GRABBAG */ nullptr,
+/* RES_TEXT_VERT_ADJUST */ nullptr,
+/* RES_BACKGROUND_FULL_SIZE */ nullptr,
+/* RES_RTL_GUTTER */ nullptr,
+/* RES_DECORATIVE */ nullptr,
+
+/* RES_GRFATR_MIRRORGRF */ nullptr,
+/* RES_GRFATR_CROPGRF */ nullptr,
+/* RES_GRFATR_ROTATION */ nullptr,
+/* RES_GRFATR_LUMINANCE */ nullptr,
+/* RES_GRFATR_CONTRAST */ nullptr,
+/* RES_GRFATR_CHANNELR */ nullptr,
+/* RES_GRFATR_CHANNELG */ nullptr,
+/* RES_GRFATR_CHANNELB */ nullptr,
+/* RES_GRFATR_GAMMA */ nullptr,
+/* RES_GRFATR_INVERT */ nullptr,
+/* RES_GRFATR_TRANSPARENCY */ nullptr,
+/* RES_GRFATR_DRWAMODE */ nullptr,
+/* RES_GRFATR_DUMMY3 */ nullptr,
+/* RES_GRFATR_DUMMY4 */ nullptr,
+/* RES_GRFATR_DUMMY5 */ nullptr,
+
+/* RES_BOXATR_FORMAT */ nullptr,
+/* RES_BOXATR_FORMULA */ nullptr,
+/* RES_BOXATR_VALUE */ nullptr
+};
+
+static_assert(SAL_N_ELEMENTS(aCSS1AttrFnTab) == RES_BOXATR_END);
+
+void SwHTMLWriter::OutCSS1_SfxItemSet( const SfxItemSet& rItemSet,
+ bool bDeep, std::string_view rAdd )
+{
+ // print ItemSet, including all attributes
+ Out_SfxItemSet( aCSS1AttrFnTab, *this, rItemSet, bDeep );
+
+ // some Attributes require special treatment
+
+ // Underline, Overline, CrossedOut and Blink form together a CSS1-Property
+ // (doesn't work of course for Hints)
+ if( !IsCSS1Source(CSS1_OUTMODE_HINT) )
+ {
+ const SvxUnderlineItem *pUnderlineItem =
+ rItemSet.GetItemIfSet( RES_CHRATR_UNDERLINE, bDeep );
+
+ const SvxOverlineItem *pOverlineItem =
+ rItemSet.GetItemIfSet( RES_CHRATR_OVERLINE, bDeep );
+
+ const SvxCrossedOutItem *pCrossedOutItem =
+ rItemSet.GetItemIfSet( RES_CHRATR_CROSSEDOUT, bDeep );
+
+ const SvxBlinkItem *pBlinkItem =
+ rItemSet.GetItemIfSet( RES_CHRATR_BLINK, bDeep );
+
+ if( pUnderlineItem || pOverlineItem || pCrossedOutItem || pBlinkItem )
+ OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( *this, pUnderlineItem,
+ pOverlineItem,
+ pCrossedOutItem,
+ pBlinkItem );
+
+ OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( *this, rItemSet, bDeep );
+ }
+
+ if (!rAdd.empty())
+ {
+ for (std::size_t index = 0; index != std::string_view::npos;)
+ {
+ std::string_view attr = o3tl::trim(o3tl::getToken(rAdd, ':', index));
+ assert(!attr.empty());
+ assert(index != std::string_view::npos);
+
+ std::string_view val = o3tl::trim(o3tl::getToken(rAdd, ':', index));
+ assert(!val.empty());
+ OutCSS1_PropertyAscii(attr, val);
+ }
+ }
+
+ if( m_bFirstCSS1Property )
+ return;
+
+ // if a Property was exported as part of a Style-Option,
+ // the Option still needs to be finished
+ OStringBuffer sOut;
+ switch( m_nCSS1OutMode & CSS1_OUTMODE_ANY_OFF )
+ {
+ case CSS1_OUTMODE_SPAN_TAG_OFF:
+ sOut.append(sCSS1_span_tag_end);
+ break;
+
+ case CSS1_OUTMODE_STYLE_OPT_OFF:
+ sOut.append(cCSS1_style_opt_end);
+ break;
+
+ case CSS1_OUTMODE_RULE_OFF:
+ sOut.append(sCSS1_rule_end);
+ break;
+ }
+ if (!sOut.isEmpty())
+ Strm().WriteOString( sOut );
+}
+
+SwHTMLWriter& OutCSS1_HintSpanTag( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_SPAN_TAG |
+ CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_HINT, nullptr );
+
+ Out( aCSS1AttrFnTab, rHt, rWrt );
+
+ if( !rWrt.m_bFirstCSS1Property && rWrt.m_bTagOn )
+ rWrt.Strm().WriteOString( sCSS1_span_tag_end );
+
+ return rWrt;
+}
+
+SwHTMLWriter& OutCSS1_HintStyleOpt( SwHTMLWriter& rWrt, const SfxPoolItem& rHt )
+{
+ SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_STYLE_OPT_ON |
+ CSS1_OUTMODE_ENCODE|
+ CSS1_OUTMODE_HINT, nullptr );
+
+ Out( aCSS1AttrFnTab, rHt, rWrt );
+
+ if( !rWrt.m_bFirstCSS1Property )
+ rWrt.Strm().WriteChar( '\"' );
+
+ return rWrt;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */