diff options
Diffstat (limited to 'sw/source/filter/html')
40 files changed, 6373 insertions, 6044 deletions
diff --git a/sw/source/filter/html/README b/sw/source/filter/html/README new file mode 100644 index 000000000000..7b16fb0838a3 --- /dev/null +++ b/sw/source/filter/html/README @@ -0,0 +1,42 @@ +This filter is used when the "HTML (StarWriter)" filter is invoked. + +Import options: + +- FilterOptions: string + + - xhtmlns=reqif-xhtml: actives the ReqIF mode + +- AllowedRTFOLEMimeTypes: sequence<string> + + In case an (UNO) client wants to limit the accepted set of MIME types for + OLE objects in ReqIF mode, that's possible via this parameter. + + Any MIME type is accepted by default. + +Export options: + +- FilterOptions: string + + - SkipImages: skips images + + - SkipHeaderFooter: skips the header and footer + + - EmbedImages: inlines images + + - XHTML: activates the XHTML mode + + - xhtmlns=reqif-xhtml: actives the ReqIF mode + +- RTFOLEMimeType: string + + Defines what MIME type to use for OLE objects in ReqIF mode, defaults to text/rtf. + +- ExportImagesAsOLE: boolean + + Defines if images should be exported as OLE objects or bitmaps, defaults to + false. + +- ShapeDPI: long (32bit signed int) + + Defines a custom DPI when converting vector shapes to bitmaps, defaults to + the system DPI (96 when not on HiDPI). diff --git a/sw/source/filter/html/SwAppletImpl.cxx b/sw/source/filter/html/SwAppletImpl.cxx index fe79b0d26753..9dbca2748305 100644 --- a/sw/source/filter/html/SwAppletImpl.cxx +++ b/sw/source/filter/html/SwAppletImpl.cxx @@ -26,6 +26,7 @@ #include <comphelper/embeddedobjectcontainer.hxx> #include <comphelper/classids.hxx> #include <com/sun/star/uno/Any.hxx> +#include <o3tl/string_view.hxx> #include <svtools/embedhlp.hxx> #include <tools/globname.hxx> #include <tools/urlobj.hxx> @@ -33,75 +34,75 @@ using namespace com::sun::star; -SwHtmlOptType SwApplet_Impl::GetOptionType( const OUString& rName, bool bApplet ) +SwHtmlOptType SwApplet_Impl::GetOptionType( std::u16string_view rName, bool bApplet ) { SwHtmlOptType nType = bApplet ? SwHtmlOptType::PARAM : SwHtmlOptType::TAG; - switch( rName.toChar() ) + switch( rName[0] ) { case 'A': case 'a': - if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_align ) || - rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_alt ) ) + if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_align ) || + o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_alt ) ) nType = SwHtmlOptType::IGNORE; else if( bApplet && - (rName == "ARCHIVE" || rName == "ARCHIVES" ) ) + (rName == u"ARCHIVE" || rName == u"ARCHIVES" ) ) nType = SwHtmlOptType::TAG; break; case 'C': case 'c': - if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_class ) || - (bApplet && (rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_code ) || - rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_codebase ))) ) + if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_class ) || + (bApplet && (o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_code ) || + o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_codebase ))) ) nType = SwHtmlOptType::IGNORE; break; case 'H': case 'h': - if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_height ) ) + if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_height ) ) nType = SwHtmlOptType::SIZE; - else if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_hspace ) || - (!bApplet && rName.equalsIgnoreAsciiCase( OOO_STRING_SW_HTML_O_Hidden )) ) + else if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_hspace ) || + (!bApplet && o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SW_HTML_O_Hidden )) ) nType = SwHtmlOptType::IGNORE; break; case 'I': case 'i': - if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_id ) ) + if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_id ) ) nType = SwHtmlOptType::IGNORE; break; case 'M': case 'm': - if( bApplet && rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_mayscript ) ) + if( bApplet && o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_mayscript ) ) nType = SwHtmlOptType::IGNORE; break; case 'N': case 'n': - if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_name ) ) + if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_name ) ) nType = SwHtmlOptType::IGNORE; break; case 'O': case 'o': - if( bApplet && rName == "OBJECT" ) + if( bApplet && rName == u"OBJECT" ) nType = SwHtmlOptType::TAG; break; case 'S': case 's': - if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_style ) || - (!bApplet && rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_src )) ) + if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_style ) || + (!bApplet && o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_src )) ) nType = SwHtmlOptType::IGNORE; break; case 'T': case 't': - if( !bApplet && rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_type ) ) + if( !bApplet && o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_type ) ) nType = SwHtmlOptType::IGNORE; break; case 'V': case 'v': - if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_vspace ) ) + if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_vspace ) ) nType = SwHtmlOptType::IGNORE; break; case 'W': case 'w': - if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_width ) ) + if( o3tl::equalsIgnoreAsciiCase( rName, OOO_STRING_SVTOOLS_HTML_O_width ) ) nType = SwHtmlOptType::SIZE; break; } @@ -109,48 +110,48 @@ SwHtmlOptType SwApplet_Impl::GetOptionType( const OUString& rName, bool bApplet return nType; } SwApplet_Impl::SwApplet_Impl( SfxItemPool& rPool ) : - aItemSet( rPool, svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ) + m_aItemSet( rPool, svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1> ) { } void SwApplet_Impl::CreateApplet( const OUString& rCode, const OUString& rName, bool bMayScript, const OUString& rCodeBase, - const OUString& rDocumentBaseURL ) + std::u16string_view rDocumentBaseURL ) { comphelper::EmbeddedObjectContainer aCnt; OUString aName; // create Applet; it will be in running state - xApplet = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_APPLET_CLASSID ).GetByteSequence(), aName ); - ::svt::EmbeddedObjectRef::TryRunningState( xApplet ); + m_xApplet = aCnt.CreateEmbeddedObject( SvGlobalName( SO3_APPLET_CLASSID ).GetByteSequence(), aName ); + (void)::svt::EmbeddedObjectRef::TryRunningState( m_xApplet ); INetURLObject aUrlBase(rDocumentBaseURL); aUrlBase.removeSegment(); OUString sDocBase = aUrlBase.GetMainURL(INetURLObject::DecodeMechanism::NONE); - uno::Reference < beans::XPropertySet > xSet( xApplet->getComponent(), uno::UNO_QUERY ); + uno::Reference < beans::XPropertySet > xSet( m_xApplet->getComponent(), uno::UNO_QUERY ); if ( xSet.is() ) { - xSet->setPropertyValue("AppletCode", uno::makeAny( rCode ) ); - xSet->setPropertyValue("AppletName", uno::makeAny( rName ) ); - xSet->setPropertyValue("AppletIsScript", uno::makeAny( bMayScript ) ); - xSet->setPropertyValue("AppletDocBase", uno::makeAny( sDocBase ) ); + xSet->setPropertyValue("AppletCode", uno::Any( rCode ) ); + xSet->setPropertyValue("AppletName", uno::Any( rName ) ); + xSet->setPropertyValue("AppletIsScript", uno::Any( bMayScript ) ); + xSet->setPropertyValue("AppletDocBase", uno::Any( sDocBase ) ); if ( !rCodeBase.isEmpty() ) - xSet->setPropertyValue("AppletCodeBase", uno::makeAny( rCodeBase ) ); + xSet->setPropertyValue("AppletCodeBase", uno::Any( rCodeBase ) ); else - xSet->setPropertyValue("AppletCodeBase", uno::makeAny( sDocBase ) ); + xSet->setPropertyValue("AppletCodeBase", uno::Any( sDocBase ) ); } } #if HAVE_FEATURE_JAVA -bool SwApplet_Impl::CreateApplet( const OUString& rBaseURL ) +bool SwApplet_Impl::CreateApplet( std::u16string_view rBaseURL ) { OUString aCode, aName, aCodeBase; bool bMayScript = false; - size_t nArgCount = aCommandList.size(); + size_t nArgCount = m_aCommandList.size(); for( size_t i = 0; i < nArgCount; i++ ) { - const SvCommand& rArg = aCommandList[i]; + const SvCommand& rArg = m_aCommandList[i]; const OUString& rName = rArg.GetCommand(); if( rName.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_code ) ) aCode = rArg.GetArgument(); @@ -174,19 +175,19 @@ SwApplet_Impl::~SwApplet_Impl() } void SwApplet_Impl::FinishApplet() { - uno::Reference < beans::XPropertySet > xSet( xApplet->getComponent(), uno::UNO_QUERY ); + uno::Reference < beans::XPropertySet > xSet( m_xApplet->getComponent(), uno::UNO_QUERY ); if ( xSet.is() ) { uno::Sequence < beans::PropertyValue > aProps; - aCommandList.FillSequence( aProps ); - xSet->setPropertyValue("AppletCommands", uno::makeAny( aProps ) ); + m_aCommandList.FillSequence( aProps ); + xSet->setPropertyValue("AppletCommands", uno::Any( aProps ) ); } } #if HAVE_FEATURE_JAVA void SwApplet_Impl::AppendParam( const OUString& rName, const OUString& rValue ) { - aCommandList.Append( rName, rValue ); + m_aCommandList.Append( rName, rValue ); } #endif diff --git a/sw/source/filter/html/css1atr.cxx b/sw/source/filter/html/css1atr.cxx index e0c2f9fb8021..0cbf5b36da86 100644 --- a/sw/source/filter/html/css1atr.cxx +++ b/sw/source/filter/html/css1atr.cxx @@ -23,6 +23,7 @@ #include <hintids.hxx> #include <comphelper/string.hxx> +#include <comphelper/xmlencode.hxx> #include <vcl/svapp.hxx> #include <svl/whiter.hxx> #include <editeng/boxitem.hxx> @@ -91,8 +92,10 @@ #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; @@ -101,14 +104,6 @@ using editeng::SvxBorderLine; namespace { -enum class Css1Background { - Attr = 1, - Page = 2, - Table = 3, - Fly = 4, - Section = 5 -}; - enum class Css1FrameSize { NONE = 0x00, Width = 0x01, @@ -123,43 +118,46 @@ namespace o3tl { template<> struct typed_flags<Css1FrameSize> : is_typed_flags<Css1FrameSize, 0x17> {}; } -#define DOT_LEADERS_MAX_WIDTH 18 +constexpr int DOT_LEADERS_MAX_WIDTH = 18; // cm -static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat, +static SwHTMLWriter& OutCSS1_SwFormat( SwHTMLWriter& rWrt, const SwFormat& rFormat, IDocumentStylePoolAccess /*SwDoc*/ *pDoc, SwDoc *pTemplate ); -static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rFormat, +static SwHTMLWriter& OutCSS1_SwPageDesc( SwHTMLWriter& rWrt, const SwPageDesc& rFormat, IDocumentStylePoolAccess /*SwDoc*/ *pDoc, SwDoc *pTemplate, sal_uInt16 nRefPoolId, bool bExtRef, bool bPseudo=true ); -static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo, +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 Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt, +static SwHTMLWriter& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( SwHTMLWriter& rWrt, const SvxUnderlineItem *pUItem, const SvxOverlineItem *pOItem, const SvxCrossedOutItem *pCOItem, const SvxBlinkItem *pBItem ); -static Writer& OutCSS1_SvxFontWeight( Writer& rWrt, const SfxPoolItem& rHt ); -static Writer& OutCSS1_SvxPosture( Writer& rWrt, const SfxPoolItem& rHt ); -static Writer& OutCSS1_SvxULSpace( Writer& rWrt, const SfxPoolItem& rHt ); -static Writer& OutCSS1_SvxLRSpace( Writer& rWrt, const SfxPoolItem& rHt ); -static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt, +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 Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt, +static SwHTMLWriter& OutCSS1_SvxULSpace_SvxLRSpace( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet ); -static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt, - Css1Background nMode, +static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& rWrt, const SfxPoolItem& rHt, + sw::Css1Background nMode, const OUString *pGraphicName ); -static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt ); -static Writer& OutCSS1_SwFormatFrameSize( Writer& rWrt, const SfxPoolItem& rHt, +static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); +static SwHTMLWriter& OutCSS1_SwFormatFrameSize( SwHTMLWriter& rWrt, const SfxPoolItem& rHt, Css1FrameSize nMode ); -static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt, +static SwHTMLWriter& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet, bool bDeep ); -static Writer& OutCSS1_SwFormatLayoutSplit( Writer& rWrt, const SfxPoolItem& rHt ); +static SwHTMLWriter& OutCSS1_SwFormatLayoutSplit( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); namespace { @@ -188,11 +186,24 @@ OString lclConvToHex(sal_uInt16 nHex) } } -bool IgnorePropertyForReqIF(bool bReqIF, std::string_view rProperty, std::string_view rValue) +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) { @@ -244,11 +255,17 @@ public: } -void SwHTMLWriter::OutCSS1_Property( const char *pProp, +void SwHTMLWriter::OutCSS1_Property( std::string_view pProp, std::string_view sVal, - const OUString *pSVal ) + const OUString *pSVal, + std::optional<sw::Css1Background> oMode ) { - if (IgnorePropertyForReqIF(mbReqIF, pProp, sVal)) + OString aPropertyValue(sVal); + if (aPropertyValue.isEmpty() && pSVal) + { + aPropertyValue = OUStringToOString(*pSVal, RTL_TEXTENCODING_UTF8); + } + if (IgnorePropertyForReqIF(mbReqIF, pProp, aPropertyValue, oMode)) return; OStringBuffer sOut; @@ -301,7 +318,8 @@ void SwHTMLWriter::OutCSS1_Property( const char *pProp, "p." sCSS2_P_CLASS_leaders " span+span{float:right;padding-left:0.33em;" "background:white;position:relative;z-index:1}"); } - Strm().WriteOString( sOut.makeStringAndClear() ); + Strm().WriteOString( sOut ); + sOut.setLength(0); IncIndentLevel(); } @@ -319,7 +337,7 @@ void SwHTMLWriter::OutCSS1_Property( const char *pProp, } else { - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false ); return; } break; @@ -327,7 +345,7 @@ void SwHTMLWriter::OutCSS1_Property( const char *pProp, case CSS1_OUTMODE_RULE_ON: { OutNewLine(); - sOut.append(OUStringToOString(m_aCSS1Selector, m_eDestEnc) + " { "); + sOut.append(OUStringToOString(m_aCSS1Selector, RTL_TEXTENCODING_UTF8) + " { "); } break; @@ -342,28 +360,25 @@ void SwHTMLWriter::OutCSS1_Property( const char *pProp, sOut.append("; "); } - sOut.append(pProp + OStringLiteral(": ")); + sOut.append(pProp + OString::Concat(": ")); if( m_nCSS1OutMode & CSS1_OUTMODE_ENCODE ) { // for STYLE-Option encode string - Strm().WriteOString( sOut.makeStringAndClear() ); + Strm().WriteOString( sOut ); + sOut.setLength(0); if( !sVal.empty() ) - HTMLOutFuncs::Out_String( Strm(), OUString::createFromAscii(sVal), - m_eDestEnc, &m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( Strm(), OUString::createFromAscii(sVal) ); else if( pSVal ) - HTMLOutFuncs::Out_String( Strm(), *pSVal, m_eDestEnc, &m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( Strm(), *pSVal ); } else { // for STYLE-Tag print string directly - if( !sVal.empty() ) - sOut.append(sVal); - else if( pSVal ) - sOut.append(OUStringToOString(*pSVal, m_eDestEnc)); + sOut.append(aPropertyValue); } if (!sOut.isEmpty()) - Strm().WriteOString( sOut.makeStringAndClear() ); + Strm().WriteOString( sOut ); } static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, @@ -376,20 +391,16 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, rOut.append('-'); } - // the recalculated unit results from (x * nMul)/(nDiv*nFac*10) - tools::Long nMul = 1000; - tools::Long nDiv = 1; - tools::Long nFac = 100; - const char *pUnit; + 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: - // 0.01mm = 0.57twip - nMul = 25400; // 25.4 * 1000 - nDiv = 1440; // 72 * 20; + eTo = o3tl::Length::mm; nFac = 100; pUnit = sCSS1_UNIT_mm; break; @@ -399,9 +410,7 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, OSL_ENSURE( FieldUnit::CM == eUnit, "Measuring unit not supported" ); [[fallthrough]]; case FieldUnit::CM: - // 0.01cm = 5.7twip (not exact, but the UI is also not exact) - nMul = 2540; // 2.54 * 1000 - nDiv = 1440; // 72 * 20; + eTo = o3tl::Length::cm; nFac = 100; pUnit = sCSS1_UNIT_cm; break; @@ -410,17 +419,13 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, OSL_ENSURE( FieldUnit::POINT == eUnit, "Measuring unit not supported" ); [[fallthrough]]; case FieldUnit::POINT: - // 0.1pt = 2.0twip (not exact, but the UI is also not exact) - nMul = 100; - nDiv = 20; + eTo = o3tl::Length::pt; nFac = 10; pUnit = sCSS1_UNIT_pt; break; case FieldUnit::PICA: - // 0.01pc = 2.40twip (not exact, but the UI is also not exact) - nMul = 1000; - nDiv = 240; // 12 * 20; + eTo = o3tl::Length::pc; nFac = 100; pUnit = sCSS1_UNIT_pc; break; @@ -433,80 +438,37 @@ static void AddUnitPropertyValue(OStringBuffer &rOut, tools::Long nVal, case FieldUnit::INCH: default: OSL_ENSURE( FieldUnit::INCH == eUnit, "Measuring unit not supported" ); - // 0.01in = 14.4twip (not exact, but the UI is also not exact) - nMul = 1000; - nDiv = 1440; // 72 * 20; + eTo = o3tl::Length::in; nFac = 100; pUnit = sCSS1_UNIT_inch; break; } - tools::Long nLongVal = 0; - bool bOutLongVal = true; - if( nVal > LONG_MAX / nMul ) - { - sal_Int64 nBigVal( nVal ); - nBigVal *= nMul; - nBigVal /= nDiv; - nBigVal += 5; - nBigVal /= 10; - - if( nBigVal <= LONG_MAX ) - { - // a long is sufficient - nLongVal = static_cast<tools::Long>(nBigVal); - } - else - { - rOut.append(nBigVal / static_cast<sal_Int64>(nFac)); - if( (nBigVal % static_cast<sal_Int64>(nFac)) != 0 ) - { - rOut.append('.'); - while( nFac > 1 && (nBigVal % static_cast<sal_Int64>(nFac)) != 0 ) - { - nFac /= 10; - rOut.append((nBigVal / static_cast<sal_Int64>(nFac)) % sal_Int64(10)); - } - } - bOutLongVal = false; - } - } - else - { - nLongVal = nVal * nMul; - nLongVal /= nDiv; - nLongVal += 5; - nLongVal /= 10; - } - - if( bOutLongVal ) + sal_Int64 nResult = o3tl::convert(nVal * nFac, o3tl::Length::twip, eTo); + rOut.append(nResult/nFac); + if ((nResult % nFac) != 0) { - rOut.append(OString::number(nLongVal/nFac)); - if( (nLongVal % nFac) != 0 ) + rOut.append('.'); + while (nFac > 1 && (nResult % nFac) != 0) { - rOut.append('.'); - while( nFac > 1 && (nLongVal % nFac) != 0 ) - { - nFac /= 10; - rOut.append(OString::number((nLongVal / nFac) % 10)); - } + nFac /= 10; + rOut.append((nResult / nFac) % 10); } } rOut.append(pUnit); } -void SwHTMLWriter::OutCSS1_UnitProperty( const char *pProp, tools::Long nVal ) +void SwHTMLWriter::OutCSS1_UnitProperty( std::string_view pProp, tools::Long nVal ) { OStringBuffer sOut; AddUnitPropertyValue(sOut, nVal, m_eCSS1Unit); - OutCSS1_PropertyAscii(pProp, sOut.makeStringAndClear()); + OutCSS1_PropertyAscii(pProp, sOut); } -void SwHTMLWriter::OutCSS1_PixelProperty( const char *pProp, tools::Long nVal, - bool bVert ) +void SwHTMLWriter::OutCSS1_PixelProperty( std::string_view pProp, tools::Long nTwips ) { - OString sOut(OString::number(ToPixel(nVal,bVert)) + sCSS1_UNIT_px); + OString sOut(OString::number(ToPixel(nTwips)) + sCSS1_UNIT_px); OutCSS1_PropertyAscii(pProp, sOut); } @@ -621,7 +583,7 @@ void SwHTMLWriter::OutStyleSheet( const SwPageDesc& rPageDesc ) DecIndentLevel(); OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_style, false ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_style), false ); } else { @@ -661,22 +623,22 @@ sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rTok if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_blockquote) { rRefPoolId = RES_POOLCOLL_HTML_BLOCKQUOTE; - rToken = OString(OOO_STRING_SVTOOLS_HTML_blockquote); + rToken = OOO_STRING_SVTOOLS_HTML_blockquote ""_ostr; } - else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_citiation) + else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_citation) { - rRefPoolId = RES_POOLCHR_HTML_CITIATION; - rToken = OString(OOO_STRING_SVTOOLS_HTML_citiation); + 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 = OString(OOO_STRING_SVTOOLS_HTML_code); + rToken = OOO_STRING_SVTOOLS_HTML_code ""_ostr; } else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_definstance) { rRefPoolId = RES_POOLCHR_HTML_DEFINSTANCE; - rToken = OString(OOO_STRING_SVTOOLS_HTML_definstance); + rToken = OOO_STRING_SVTOOLS_HTML_definstance ""_ostr; } else if (!bChrFormat && (aNm == OOO_STRING_SVTOOLS_HTML_dd || aNm == OOO_STRING_SVTOOLS_HTML_dt)) @@ -694,19 +656,19 @@ sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rTok else if (nDefListLvl & HTML_DLCOLL_DD) { rRefPoolId = RES_POOLCOLL_HTML_DD; - rToken = OString(OOO_STRING_SVTOOLS_HTML_dd); + rToken = OOO_STRING_SVTOOLS_HTML_dd ""_ostr; } else { rRefPoolId = RES_POOLCOLL_HTML_DT; - rToken = OString(OOO_STRING_SVTOOLS_HTML_dt); + rToken = OOO_STRING_SVTOOLS_HTML_dt ""_ostr; } } } else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_emphasis) { rRefPoolId = RES_POOLCHR_HTML_EMPHASIS; - rToken = OString(OOO_STRING_SVTOOLS_HTML_emphasis); + rToken = OOO_STRING_SVTOOLS_HTML_emphasis ""_ostr; } else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_horzrule) { @@ -716,44 +678,44 @@ sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rTok else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_keyboard) { rRefPoolId = RES_POOLCHR_HTML_KEYBOARD; - rToken = OString(OOO_STRING_SVTOOLS_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 = OString(OOO_STRING_SVTOOLS_HTML_preformtxt); + 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 = OString(OOO_STRING_SVTOOLS_HTML_preformtxt); + rToken = OOO_STRING_SVTOOLS_HTML_preformtxt ""_ostr; } else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_sample) { rRefPoolId = RES_POOLCHR_HTML_SAMPLE; - rToken = OString(OOO_STRING_SVTOOLS_HTML_sample); + rToken = OOO_STRING_SVTOOLS_HTML_sample ""_ostr; } else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_strong) { rRefPoolId = RES_POOLCHR_HTML_STRONG; - rToken = OString(OOO_STRING_SVTOOLS_HTML_strong); + rToken = OOO_STRING_SVTOOLS_HTML_strong ""_ostr; } else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_teletype) { rRefPoolId = RES_POOLCHR_HTML_TELETYPE; - rToken = OString(OOO_STRING_SVTOOLS_HTML_teletype); + rToken = OOO_STRING_SVTOOLS_HTML_teletype ""_ostr; } else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_variable) { rRefPoolId = RES_POOLCHR_HTML_VARIABLE; - rToken = OString(OOO_STRING_SVTOOLS_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 = OString(OOO_STRING_SVTOOLS_HTML_preformtxt); + rToken = OOO_STRING_SVTOOLS_HTML_preformtxt ""_ostr; rRefPoolId = RES_POOLCOLL_HTML_PRE; nDeep = CSS1_FMT_CMPREF; } @@ -774,60 +736,60 @@ sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rTok bStop = (nDeep==0); break; case RES_POOLCOLL_TEXT: - rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak); + rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr; break; case RES_POOLCOLL_HEADLINE1: - rToken = OString(OOO_STRING_SVTOOLS_HTML_head1); + rToken = OOO_STRING_SVTOOLS_HTML_head1 ""_ostr; break; case RES_POOLCOLL_HEADLINE2: - rToken = OString(OOO_STRING_SVTOOLS_HTML_head2); + rToken = OOO_STRING_SVTOOLS_HTML_head2 ""_ostr; break; case RES_POOLCOLL_HEADLINE3: - rToken = OString(OOO_STRING_SVTOOLS_HTML_head3); + rToken = OOO_STRING_SVTOOLS_HTML_head3 ""_ostr; break; case RES_POOLCOLL_HEADLINE4: - rToken = OString(OOO_STRING_SVTOOLS_HTML_head4); + rToken = OOO_STRING_SVTOOLS_HTML_head4 ""_ostr; break; case RES_POOLCOLL_HEADLINE5: - rToken = OString(OOO_STRING_SVTOOLS_HTML_head5); + rToken = OOO_STRING_SVTOOLS_HTML_head5 ""_ostr; break; case RES_POOLCOLL_HEADLINE6: - rToken = OString(OOO_STRING_SVTOOLS_HTML_head6); + rToken = OOO_STRING_SVTOOLS_HTML_head6 ""_ostr; break; case RES_POOLCOLL_SEND_ADDRESS: - rToken = OString(OOO_STRING_SVTOOLS_HTML_address); + rToken = OOO_STRING_SVTOOLS_HTML_address ""_ostr; break; case RES_POOLCOLL_HTML_BLOCKQUOTE: - rToken = OString(OOO_STRING_SVTOOLS_HTML_blockquote); + rToken = OOO_STRING_SVTOOLS_HTML_blockquote ""_ostr; break; case RES_POOLCOLL_HTML_PRE: - rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt); + rToken = OOO_STRING_SVTOOLS_HTML_preformtxt ""_ostr; break; case RES_POOLCOLL_HTML_DD: - rToken = OString(OOO_STRING_SVTOOLS_HTML_dd); + rToken = OOO_STRING_SVTOOLS_HTML_dd ""_ostr; break; case RES_POOLCOLL_HTML_DT: - rToken = OString(OOO_STRING_SVTOOLS_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; + OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr; } else - rToken = OOO_STRING_SVTOOLS_HTML_parabreak; + 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; + OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr; } else - rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak); + rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr; break; case RES_POOLCOLL_HTML_HR: // do not export HR ! @@ -836,7 +798,7 @@ sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rTok case RES_POOLCOLL_FOOTNOTE: if( !nDeep ) { - rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak); + rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr; rClass = OOO_STRING_SVTOOLS_HTML_sdfootnote; rRefPoolId = RES_POOLCOLL_TEXT; nDeep = CSS1_FMT_CMPREF; @@ -845,7 +807,7 @@ sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rTok case RES_POOLCOLL_ENDNOTE: if( !nDeep ) { - rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak); + rToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr; rClass = OOO_STRING_SVTOOLS_HTML_sdendnote; rRefPoolId = RES_POOLCOLL_TEXT; nDeep = CSS1_FMT_CMPREF; @@ -854,44 +816,44 @@ sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rTok // character templates case RES_POOLCHR_HTML_EMPHASIS: - rToken = OString(OOO_STRING_SVTOOLS_HTML_emphasis); + rToken = OOO_STRING_SVTOOLS_HTML_emphasis ""_ostr; break; - case RES_POOLCHR_HTML_CITIATION: - rToken = OString(OOO_STRING_SVTOOLS_HTML_citiation); + case RES_POOLCHR_HTML_CITATION: + rToken = OOO_STRING_SVTOOLS_HTML_citation ""_ostr; break; case RES_POOLCHR_HTML_STRONG: - rToken = OString(OOO_STRING_SVTOOLS_HTML_strong); + rToken = OOO_STRING_SVTOOLS_HTML_strong ""_ostr; break; case RES_POOLCHR_HTML_CODE: - rToken = OString(OOO_STRING_SVTOOLS_HTML_code); + rToken = OOO_STRING_SVTOOLS_HTML_code ""_ostr; break; case RES_POOLCHR_HTML_SAMPLE: - rToken = OString(OOO_STRING_SVTOOLS_HTML_sample); + rToken = OOO_STRING_SVTOOLS_HTML_sample ""_ostr; break; case RES_POOLCHR_HTML_KEYBOARD: - rToken = OString(OOO_STRING_SVTOOLS_HTML_keyboard); + rToken = OOO_STRING_SVTOOLS_HTML_keyboard ""_ostr; break; case RES_POOLCHR_HTML_VARIABLE: - rToken = OString(OOO_STRING_SVTOOLS_HTML_variable); + rToken = OOO_STRING_SVTOOLS_HTML_variable ""_ostr; break; case RES_POOLCHR_HTML_DEFINSTANCE: - rToken = OString(OOO_STRING_SVTOOLS_HTML_definstance); + rToken = OOO_STRING_SVTOOLS_HTML_definstance ""_ostr; break; case RES_POOLCHR_HTML_TELETYPE: - rToken = OString(OOO_STRING_SVTOOLS_HTML_teletype); + rToken = OOO_STRING_SVTOOLS_HTML_teletype ""_ostr; break; case RES_POOLCHR_INET_NORMAL: if( pPseudo ) { - rToken = OString(OOO_STRING_SVTOOLS_HTML_anchor); + rToken = OOO_STRING_SVTOOLS_HTML_anchor ""_ostr; *pPseudo = OStringToOUString( sCSS1_link, RTL_TEXTENCODING_ASCII_US ); } break; case RES_POOLCHR_INET_VISIT: if( pPseudo ) { - rToken = OString(OOO_STRING_SVTOOLS_HTML_anchor); + rToken = OOO_STRING_SVTOOLS_HTML_anchor ""_ostr; *pPseudo = OStringToOUString( sCSS1_visited, RTL_TEXTENCODING_ASCII_US ); } break; @@ -936,7 +898,7 @@ sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rTok sal_Int32 nPos = rClass.indexOf( '.' ); if( nPos >= 0 && rClass.getLength() > nPos+1 ) { - rClass = rClass.replaceAt( 0, nPos+1, "" ); + rClass = rClass.replaceAt( 0, nPos+1, u"" ); } rClass = GetAppCharClass().lowercase( rClass ); @@ -1036,7 +998,7 @@ void SwHTMLWriter::SubtractItemSet( SfxItemSet& rItemSet, { const SfxPoolItem *pRefItem, *pItem; bool bItemSet = ( SfxItemState::SET == - rItemSet.GetItemState( nWhich, false, &pItem) ); + aIter.GetItemState( false, &pItem) ); bool bRefItemSet; if( pRefScriptItemSet ) @@ -1093,7 +1055,7 @@ void SwHTMLWriter::SubtractItemSet( SfxItemSet& rItemSet, { // the Attribute exists only in the reference; the default // might have to be exported - rItemSet.Put( rItemSet.GetPool()->GetDefaultItem(nWhich) ); + rItemSet.Put( rItemSet.GetPool()->GetUserOrPoolDefaultItem(nWhich) ); } } @@ -1114,7 +1076,7 @@ void SwHTMLWriter::PrepareFontList( const SvxFontItem& rFontItem, while( nStrPos != -1 ) { OUString aName = rName.getToken( 0, ';', nStrPos ); - aName = comphelper::string::strip(aName, ' '); + aName = comphelper::string::encodeForXml(comphelper::string::strip(aName, ' ')); if( aName.isEmpty() ) continue; @@ -1159,7 +1121,7 @@ void SwHTMLWriter::PrepareFontList( const SvxFontItem& rFontItem, if( bContainsKeyword || !bGeneric ) return; - const char *pStr = nullptr; + std::string_view pStr; switch( rFontItem.GetFamily() ) { case FAMILY_ROMAN: pStr = sCSS1_PV_serif; break; @@ -1171,7 +1133,7 @@ void SwHTMLWriter::PrepareFontList( const SvxFontItem& rFontItem, ; } - if( pStr ) + if( !pStr.empty() ) { if( !rNames.isEmpty() ) rNames += ", "; @@ -1242,26 +1204,23 @@ bool SwHTMLWriter::HasScriptDependentItems( const SfxItemSet& rItemSet, } } - const SfxPoolItem *pItem; + const SwFormatDrop *pDrop; if( bCheckDropCap && - SfxItemState::SET == rItemSet.GetItemState( RES_PARATR_DROP, true, - &pItem ) ) + (pDrop = rItemSet.GetItemIfSet( RES_PARATR_DROP )) ) { - const SwFormatDrop *pDrop = static_cast<const SwFormatDrop *>(pItem); const SwCharFormat *pDCCharFormat = pDrop->GetCharFormat(); if( pDCCharFormat ) { //sequence of (start, end) property ranges we want to //query - SfxItemSet aTstItemSet( - *pDCCharFormat->GetAttrSet().GetPool(), - svl::Items< + 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>{}); + RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT> + aTstItemSet(*pDCCharFormat->GetAttrSet().GetPool()); aTstItemSet.Set( pDCCharFormat->GetAttrSet() ); return HasScriptDependentItems( aTstItemSet, false ); } @@ -1270,7 +1229,7 @@ bool SwHTMLWriter::HasScriptDependentItems( const SfxItemSet& rItemSet, return false; } -static bool OutCSS1Rule( SwHTMLWriter& rHTMLWrt, const OUString& rSelector, +static bool OutCSS1Rule( SwHTMLWriter& rWrt, const OUString& rSelector, const SfxItemSet& rItemSet, bool bHasClass, bool bCheckForPseudo ) { @@ -1278,16 +1237,16 @@ static bool OutCSS1Rule( SwHTMLWriter& rHTMLWrt, const OUString& rSelector, if( SwHTMLWriter::HasScriptDependentItems( rItemSet, bHasClass ) ) { bScriptDependent = true; - OUString aSelector( rSelector ); + std::u16string_view aSelector( rSelector ); - OUString aPseudo; + std::u16string_view aPseudo; if( bCheckForPseudo ) { - sal_Int32 nPos = aSelector.lastIndexOf( ':' ); - if( nPos >= 0 ) + size_t nPos = aSelector.rfind( ':' ); + if( nPos != std::u16string_view::npos ) { - aPseudo = aSelector.copy( nPos ); - aSelector =aSelector.copy( 0, nPos ); + aPseudo = aSelector.substr( nPos ); + aSelector =aSelector.substr( 0, nPos ); } } @@ -1297,39 +1256,39 @@ static bool OutCSS1Rule( SwHTMLWriter& rHTMLWrt, const OUString& rSelector, // rule for all properties that aren't style dependent and // some class rule for the additional style dependen properties { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &rSelector ); - rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false ); + rWrt.OutCSS1_SfxItemSet( rItemSet, false ); } //sequence of (start, end) property ranges we want to //query - SfxItemSet aScriptItemSet( *rItemSet.GetPool(), - svl::Items<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE, + 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>{} ); + RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT> + aScriptItemSet( *rItemSet.GetPool() ); aScriptItemSet.Put( rItemSet ); - OUString aNewSelector = aSelector + ".western" + aPseudo; + OUString aNewSelector = OUString::Concat(aSelector) + ".western" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &aNewSelector ); - rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false ); + rWrt.OutCSS1_SfxItemSet( aScriptItemSet, false ); } - aNewSelector = aSelector + ".cjk" + aPseudo; + aNewSelector = OUString::Concat(aSelector) + ".cjk" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &aNewSelector ); - rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false ); + rWrt.OutCSS1_SfxItemSet( aScriptItemSet, false ); } - aNewSelector = aSelector + ".ctl" + aPseudo; + aNewSelector = OUString::Concat(aSelector) + ".ctl" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &aNewSelector ); - rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false ); + rWrt.OutCSS1_SfxItemSet( aScriptItemSet, false ); } } else @@ -1337,25 +1296,25 @@ static bool OutCSS1Rule( SwHTMLWriter& rHTMLWrt, const OUString& rSelector, // 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 = aSelector + "-western" + aPseudo; + OUString aNewSelector = OUString::Concat(aSelector) + "-western" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &aNewSelector ); - rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false ); + rWrt.OutCSS1_SfxItemSet( rItemSet, false ); } - aNewSelector = aSelector + "-cjk" + aPseudo; + aNewSelector = OUString::Concat(aSelector) + "-cjk" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &aNewSelector ); - rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false ); + rWrt.OutCSS1_SfxItemSet( rItemSet, false ); } - aNewSelector = aSelector + "-ctl" + aPseudo; + aNewSelector = OUString::Concat(aSelector) + "-ctl" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &aNewSelector ); - rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false ); + rWrt.OutCSS1_SfxItemSet( rItemSet, false ); } } } @@ -1365,17 +1324,17 @@ static bool OutCSS1Rule( SwHTMLWriter& rHTMLWrt, const OUString& rSelector, // 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( rHTMLWrt, - rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, + rWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &rSelector ); - rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false ); + rWrt.OutCSS1_SfxItemSet( rItemSet, false ); } return bScriptDependent; } static void OutCSS1DropCapRule( - SwHTMLWriter& rHTMLWrt, const OUString& rSelector, + SwHTMLWriter& rWrt, const OUString& rSelector, const SwFormatDrop& rDrop, bool bHasClass, bool bHasScriptDependencies ) { @@ -1383,14 +1342,14 @@ static void OutCSS1DropCapRule( if( (bHasScriptDependencies && bHasClass) || (pDCCharFormat && SwHTMLWriter::HasScriptDependentItems( pDCCharFormat->GetAttrSet(), false ) ) ) { - OUString aSelector( rSelector ); + std::u16string_view aSelector( rSelector ); - OUString aPseudo; - sal_Int32 nPos = aSelector.lastIndexOf( ':' ); - if( nPos >= 0 ) + std::u16string_view aPseudo; + size_t nPos = aSelector.rfind( ':' ); + if( nPos != std::u16string_view::npos ) { - aPseudo = aSelector.copy( nPos ); - aSelector = aSelector.copy( 0, nPos ); + aPseudo = aSelector.substr( nPos ); + aSelector = aSelector.substr( 0, nPos ); } if( !bHasClass ) @@ -1399,38 +1358,38 @@ static void OutCSS1DropCapRule( // rule for all properties that aren't style dependent and // some class rule for the additional style dependen properties { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, &rSelector ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop ); + OutCSS1_SwFormatDropAttrs( rWrt, rDrop ); } - SfxItemSet aScriptItemSet( rHTMLWrt.m_pDoc->GetAttrPool(), - svl::Items<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>{} ); + 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 = aSelector + ".western" + aPseudo; + OUString aNewSelector = OUString::Concat(aSelector) + ".western" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, &aNewSelector ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop, &aScriptItemSet ); + OutCSS1_SwFormatDropAttrs( rWrt, rDrop, &aScriptItemSet ); } - aNewSelector = aSelector + ".cjk" + aPseudo; + aNewSelector = OUString::Concat(aSelector) + ".cjk" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, &aNewSelector ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop, &aScriptItemSet ); + OutCSS1_SwFormatDropAttrs( rWrt, rDrop, &aScriptItemSet ); } - aNewSelector = aSelector + ".ctl" + aPseudo; + aNewSelector = OUString::Concat(aSelector) + ".ctl" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, &aNewSelector ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop, &aScriptItemSet ); + OutCSS1_SwFormatDropAttrs( rWrt, rDrop, &aScriptItemSet ); } } else @@ -1438,25 +1397,25 @@ static void OutCSS1DropCapRule( // 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 = aSelector + "-western" + aPseudo; + OUString aNewSelector = OUString::Concat(aSelector) + "-western" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, &aNewSelector ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop ); + OutCSS1_SwFormatDropAttrs( rWrt, rDrop ); } - aNewSelector = aSelector + "-cjk" + aPseudo; + aNewSelector = OUString::Concat(aSelector) + "-cjk" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, &aNewSelector ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop ); + OutCSS1_SwFormatDropAttrs( rWrt, rDrop ); } - aNewSelector = aSelector + "-ctl" + aPseudo; + aNewSelector = OUString::Concat(aSelector) + "-ctl" + aPseudo; { - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, &aNewSelector ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop ); + OutCSS1_SwFormatDropAttrs( rWrt, rDrop ); } } } @@ -1466,18 +1425,16 @@ static void OutCSS1DropCapRule( // 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( rHTMLWrt, - rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, + SwCSS1OutMode aMode( rWrt, + rWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP, &rSelector ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop ); + OutCSS1_SwFormatDropAttrs( rWrt, rDrop ); } } -static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat, +static SwHTMLWriter& OutCSS1_SwFormat( SwHTMLWriter& rWrt, const SwFormat& rFormat, IDocumentStylePoolAccess/*SwDoc*/ *pDoc, SwDoc *pTemplate ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - bool bCharFormat = false; switch( rFormat.Which() ) { @@ -1556,29 +1513,29 @@ static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat, if( !bCharFormat ) { const SvxULSpaceItem& rULItem = pRefFormat->GetULSpace(); - rHTMLWrt.m_nDfltTopMargin = rULItem.GetUpper(); - rHTMLWrt.m_nDfltBottomMargin = rULItem.GetLower(); + 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) - rHTMLWrt.m_nDfltTopMargin = 0; - rHTMLWrt.m_nDfltBottomMargin = HTML_PARSPACE; + 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") - rHTMLWrt.m_nDfltBottomMargin = 0; + rWrt.m_nDfltBottomMargin = 0; else if (aNm == OOO_STRING_SVTOOLS_HTML_listing) - rHTMLWrt.m_nDfltBottomMargin = 0; + rWrt.m_nDfltBottomMargin = 0; else if (aNm == OOO_STRING_SVTOOLS_HTML_preformtxt) - rHTMLWrt.m_nDfltBottomMargin = 0; + rWrt.m_nDfltBottomMargin = 0; else if (aNm == OOO_STRING_SVTOOLS_HTML_xmp) - rHTMLWrt.m_nDfltBottomMargin = 0; + rWrt.m_nDfltBottomMargin = 0; } else { @@ -1591,13 +1548,13 @@ static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat, case RES_POOLCOLL_HEADLINE4: case RES_POOLCOLL_HEADLINE5: case RES_POOLCOLL_HEADLINE6: - rHTMLWrt.m_nDfltTopMargin = HTML_HEADSPACE; + 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: - rHTMLWrt.m_nDfltBottomMargin = 0; + rWrt.m_nDfltBottomMargin = 0; break; } } @@ -1616,40 +1573,36 @@ static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat, // export now the Attributes (incl. selector) bool bHasScriptDependencies = false; - if( OutCSS1Rule( rHTMLWrt, aSelector, aItemSet, CSS1_FMT_ISTAG != nDeep, + if( OutCSS1Rule( rWrt, aSelector, aItemSet, CSS1_FMT_ISTAG != nDeep, bCheckForPseudo ) ) { if( bCharFormat ) - rHTMLWrt.m_aScriptTextStyles.insert( rFormat.GetName() ); + rWrt.m_aScriptTextStyles.insert( rFormat.GetName() ); else { if( nPoolFormatId==RES_POOLCOLL_TEXT ) - rHTMLWrt.m_aScriptParaStyles.insert( pDoc->GetTextCollFromPool( RES_POOLCOLL_STANDARD, false )->GetName() ); - rHTMLWrt.m_aScriptParaStyles.insert( rFormat.GetName() ); + rWrt.m_aScriptParaStyles.insert( pDoc->GetTextCollFromPool( RES_POOLCOLL_STANDARD, false )->GetName() ); + rWrt.m_aScriptParaStyles.insert( rFormat.GetName() ); } bHasScriptDependencies = true; } // export Drop-Caps - const SfxPoolItem *pItem; - if( SfxItemState::SET==aItemSet.GetItemState( RES_PARATR_DROP, false, &pItem )) + if( const SwFormatDrop *pDrop = aItemSet.GetItemIfSet( RES_PARATR_DROP, false ) ) { OUString sOut = aSelector + ":" + OStringToOUString( sCSS1_first_letter, RTL_TEXTENCODING_ASCII_US ); - const SwFormatDrop *pDrop = static_cast<const SwFormatDrop *>(pItem); - OutCSS1DropCapRule( rHTMLWrt, sOut, *pDrop, CSS1_FMT_ISTAG != nDeep, bHasScriptDependencies ); + OutCSS1DropCapRule( rWrt, sOut, *pDrop, CSS1_FMT_ISTAG != nDeep, bHasScriptDependencies ); } return rWrt; } -static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rPageDesc, +static SwHTMLWriter& OutCSS1_SwPageDesc( SwHTMLWriter& rWrt, const SwPageDesc& rPageDesc, IDocumentStylePoolAccess/*SwDoc*/ *pDoc, SwDoc *pTemplate, sal_uInt16 nRefPoolId, bool bExtRef, bool bPseudo ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - const SwPageDesc* pRefPageDesc = nullptr; if( !bExtRef ) pRefPageDesc = pDoc->GetPageDescFromPool( nRefPoolId, false ); @@ -1660,18 +1613,18 @@ static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rPageDesc, if( bPseudo ) { - const char *pPseudo = nullptr; + 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 ) + if( !pPseudo.empty() ) aSelector += ":" + OStringToOUString( pPseudo, RTL_TEXTENCODING_ASCII_US ); } - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_RULE_ON|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_RULE_ON|CSS1_OUTMODE_TEMPLATE, &aSelector ); // Size: If the only difference is the Landscape-Flag, @@ -1701,7 +1654,7 @@ static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rPageDesc, { if( bRefLandscape != rPageDesc.GetLandscape() ) { - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_size, + rWrt.OutCSS1_PropertyAscii( sCSS1_P_size, rPageDesc.GetLandscape() ? sCSS1_PV_landscape : sCSS1_PV_portrait ); } @@ -1709,16 +1662,15 @@ static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rPageDesc, else { OStringBuffer sVal; - AddUnitPropertyValue(sVal, rSz.Width(), rHTMLWrt.GetCSS1Unit()); + AddUnitPropertyValue(sVal, rSz.Width(), rWrt.GetCSS1Unit()); sVal.append(' '); - AddUnitPropertyValue(sVal, rSz.Height(), rHTMLWrt.GetCSS1Unit()); - rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_size, sVal.makeStringAndClear()); + AddUnitPropertyValue(sVal, rSz.Height(), rWrt.GetCSS1Unit()); + rWrt.OutCSS1_PropertyAscii(sCSS1_P_size, sVal); } // Export the distance-Attributes as normally const SwFrameFormat &rMaster = rPageDesc.GetMaster(); - SfxItemSet aItemSet( *rMaster.GetAttrSet().GetPool(), - svl::Items<RES_LR_SPACE, RES_UL_SPACE>{} ); + SfxItemSetFixed<RES_LR_SPACE, RES_UL_SPACE> aItemSet( *rMaster.GetAttrSet().GetPool() ); aItemSet.Set( rMaster.GetAttrSet() ); if( pRefPageDesc ) @@ -1733,25 +1685,23 @@ static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rPageDesc, // 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( rHTMLWrt.m_bFirstCSS1Property && bPseudo ) + if( rWrt.m_bFirstCSS1Property && bPseudo ) { - rHTMLWrt.OutNewLine(); - OString sTmp(OUStringToOString(aSelector, rHTMLWrt.m_eDestEnc)); - rWrt.Strm().WriteOString( sTmp ).WriteCharPtr( " {" ); - rHTMLWrt.m_bFirstCSS1Property = false; + rWrt.OutNewLine(); + OString sTmp(OUStringToOString(aSelector, RTL_TEXTENCODING_UTF8)); + rWrt.Strm().WriteOString( sTmp ).WriteOString( " {" ); + rWrt.m_bFirstCSS1Property = false; } - if( !rHTMLWrt.m_bFirstCSS1Property ) - rWrt.Strm().WriteCharPtr( sCSS1_rule_end ); + if( !rWrt.m_bFirstCSS1Property ) + rWrt.Strm().WriteOString( sCSS1_rule_end ); return rWrt; } -static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo, +static SwHTMLWriter& OutCSS1_SwFootnoteInfo( SwHTMLWriter& rWrt, const SwEndNoteInfo& rInfo, SwDoc *pDoc, bool bHasNotes, bool bEndNote ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - OUString aSelector; if( bHasNotes ) @@ -1759,11 +1709,11 @@ static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo, 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( rHTMLWrt, CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE, &aSelector ); - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_size, + rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_size, sHTML_FTN_fontheight ); - rHTMLWrt.Strm().WriteCharPtr( sCSS1_rule_end ); + rWrt.Strm().WriteOString( sCSS1_rule_end ); } const SwCharFormat *pSymCharFormat = rInfo.GetCharFormat( *pDoc ); @@ -1777,9 +1727,9 @@ static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo, // exported, so that Netscape displays the document correctly. // Otherwise it is sufficient, to export the differences to the // footnote and endnote template. - if( !bHasNotes && rHTMLWrt.m_xTemplate.is() ) + if( !bHasNotes && rWrt.m_xTemplate.is() ) { - SwFormat *pRefFormat = rHTMLWrt.m_xTemplate->getIDocumentStylePoolAccess().GetCharFormatFromPool( + 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(), @@ -1791,19 +1741,17 @@ static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo, ( bEndNote ? std::u16string_view(u"" OOO_STRING_SVTOOLS_HTML_sdendnote_sym) : std::u16string_view( u"" OOO_STRING_SVTOOLS_HTML_sdfootnote_sym)); - if( OutCSS1Rule( rHTMLWrt, aSelector, aItemSet, true, false )) - rHTMLWrt.m_aScriptTextStyles.insert( pSymCharFormat->GetName() ); + if( OutCSS1Rule( rWrt, aSelector, aItemSet, true, false )) + rWrt.m_aScriptTextStyles.insert( pSymCharFormat->GetName() ); } } return rWrt; } -Writer& OutCSS1_BodyTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet ) +SwHTMLWriter& OutCSS1_BodyTagStyleOpt( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON | + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_STYLE_OPT_ON | CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_BODY, nullptr ); // Only export the attributes of the page template. @@ -1815,7 +1763,7 @@ Writer& OutCSS1_BodyTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet ) &pItem ) ) { OUString rEmbeddedGraphicName; - OutCSS1_SvxBrush( rWrt, *pItem, Css1Background::Page, &rEmbeddedGraphicName ); + OutCSS1_SvxBrush( rWrt, *pItem, sw::Css1Background::Page, &rEmbeddedGraphicName ); } if( SfxItemState::SET == rItemSet.GetItemState( RES_BOX, false, @@ -1824,7 +1772,7 @@ Writer& OutCSS1_BodyTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet ) OutCSS1_SvxBox( rWrt, *pItem ); } - if( !rHTMLWrt.m_bFirstCSS1Property ) + if( !rWrt.m_bFirstCSS1Property ) { // if a Property was exported as part of a Style-Option, // the Option still needs to be finished @@ -1834,39 +1782,32 @@ Writer& OutCSS1_BodyTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet ) return rWrt; } -Writer& OutCSS1_ParaTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet ) +SwHTMLWriter& OutCSS1_ParaTagStyleOpt( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet, std::string_view rAdd ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - SwCSS1OutMode aMode( rHTMLWrt, rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_STYLE_OPT | + SwCSS1OutMode aMode( rWrt, rWrt.m_nCSS1Script|CSS1_OUTMODE_STYLE_OPT | CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_PARA, nullptr ); - rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false ); + rWrt.OutCSS1_SfxItemSet( rItemSet, false, rAdd ); return rWrt; } -// Wrapper for Table background -Writer& OutCSS1_TableBGStyleOpt( Writer& rWrt, const SfxPoolItem& rHt ) +SwHTMLWriter& OutCSS1_TableBGStyleOpt( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON | + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_STYLE_OPT_ON | CSS1_OUTMODE_ENCODE| CSS1_OUTMODE_TABLEBOX, nullptr ); - OutCSS1_SvxBrush( rWrt, rHt, Css1Background::Table, nullptr ); + OutCSS1_SvxBrush( rWrt, rHt, sw::Css1Background::TableRow, nullptr ); - if( !rHTMLWrt.m_bFirstCSS1Property ) - rWrt.Strm().WriteChar( '\"' ); + if (!rWrt.m_bFirstCSS1Property) + rWrt.Strm().WriteChar(cCSS1_style_opt_end); return rWrt; } -Writer& OutCSS1_NumberBulletListStyleOpt( Writer& rWrt, const SwNumRule& rNumRule, +SwHTMLWriter& OutCSS1_NumberBulletListStyleOpt( SwHTMLWriter& rWrt, const SwNumRule& rNumRule, sal_uInt8 nLevel ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT | + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_STYLE_OPT | CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_PARA, nullptr ); const SwNumFormat& rNumFormat = rNumRule.Get( nLevel ); @@ -1881,15 +1822,15 @@ Writer& OutCSS1_NumberBulletListStyleOpt( Writer& rWrt, const SwNumRule& rNumRul nDfltFirstLineOffset = rPrevNumFormat.GetFirstLineOffset(); } - if( rHTMLWrt.IsHTMLMode(HTMLMODE_LSPACE_IN_NUMBER_BULLET) && + if( rWrt.IsHTMLMode(HTMLMODE_LSPACE_IN_NUMBER_BULLET) && nLSpace != HTML_NUMBER_BULLET_MARGINLEFT ) - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLSpace ); + rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLSpace ); - if( rHTMLWrt.IsHTMLMode(HTMLMODE_FRSTLINE_IN_NUMBER_BULLET) && + if( rWrt.IsHTMLMode(HTMLMODE_FRSTLINE_IN_NUMBER_BULLET) && nFirstLineOffset != nDfltFirstLineOffset ) - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent, nFirstLineOffset ); + rWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent, nFirstLineOffset ); - if( !rHTMLWrt.m_bFirstCSS1Property ) + if( !rWrt.m_bFirstCSS1Property ) rWrt.Strm().WriteChar( '\"' ); return rWrt; @@ -1920,7 +1861,7 @@ void SwHTMLWriter::OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat if( !(nFrameOpts & HtmlFrmOpts::Align) ) { // float - const char *pStr = text::HoriOrientation::RIGHT==rHoriOri.GetHoriOrient() + std::string_view pStr = text::HoriOrientation::RIGHT==rHoriOri.GetHoriOrient() ? sCSS1_PV_right : sCSS1_PV_left; OutCSS1_PropertyAscii( sCSS1_P_float, pStr ); @@ -1977,7 +1918,7 @@ void SwHTMLWriter::OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat nYPos -= aULItem.GetUpper(); if( nYPos < 0 ) { - aULItem.SetUpper( static_cast<sal_uInt16>(aULItem.GetUpper() + nYPos) ); + aULItem.SetUpper( o3tl::narrowing<sal_uInt16>(aULItem.GetUpper() + nYPos) ); nYPos = 0; } } @@ -1993,7 +1934,7 @@ void SwHTMLWriter::OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat nXPos -= aLRItem.GetLeft(); if( nXPos < 0 ) { - aLRItem.SetLeft( static_cast<sal_uInt16>(aLRItem.GetLeft() + nXPos) ); + aLRItem.SetLeft( o3tl::narrowing<sal_uInt16>(aLRItem.GetLeft() + nXPos) ); nXPos = 0; } } @@ -2023,16 +1964,14 @@ void SwHTMLWriter::OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat if( nFrameOpts & HtmlFrmOpts::SWidth ) { if( nFrameOpts & HtmlFrmOpts::SPixSize ) - OutCSS1_PixelProperty( sCSS1_P_width, aTwipSz.Width(), - false ); + 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(), - true ); + OutCSS1_PixelProperty( sCSS1_P_height, aTwipSz.Height() ); else OutCSS1_UnitProperty( sCSS1_P_height, aTwipSz.Height() ); } @@ -2101,7 +2040,7 @@ void SwHTMLWriter::OutCSS1_TableFrameFormatOptions( const SwFrameFormat& rFrameF const SfxPoolItem *pItem; const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet(); if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) ) - OutCSS1_SvxBrush( *this, *pItem, Css1Background::Table, nullptr ); + OutCSS1_SvxBrush( *this, *pItem, sw::Css1Background::Table, nullptr ); if( IsHTMLMode( HTMLMODE_PRINT_EXT ) ) OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( *this, rItemSet, false ); @@ -2109,19 +2048,30 @@ void SwHTMLWriter::OutCSS1_TableFrameFormatOptions( const SwFrameFormat& rFrameF 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_TableCellBorderHack(SwFrameFormat const& rFrameFormat) +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 ); - } + Strm().WriteChar(cCSS1_style_opt_end); } void SwHTMLWriter::OutCSS1_SectionFormatOptions( const SwFrameFormat& rFrameFormat, const SwFormatCol *pCol ) @@ -2133,7 +2083,18 @@ void SwHTMLWriter::OutCSS1_SectionFormatOptions( const SwFrameFormat& rFrameForm const SfxPoolItem *pItem; const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet(); if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) ) - OutCSS1_SvxBrush( *this, *pItem, Css1Background::Section, nullptr ); + 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) { @@ -2155,7 +2116,7 @@ static bool OutCSS1_FrameFormatBrush( SwHTMLWriter& rWrt, !rBrushItem.GetGraphicLink().isEmpty() || 0 != rBrushItem.GetGraphicPos() ) { - OutCSS1_SvxBrush( rWrt, rBrushItem, Css1Background::Fly, nullptr ); + OutCSS1_SvxBrush( rWrt, rBrushItem, sw::Css1Background::Fly, nullptr ); bWritten = true; } return bWritten; @@ -2170,23 +2131,22 @@ void SwHTMLWriter::OutCSS1_FrameFormatBackground( const SwFrameFormat& rFrameFor // 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 SwPosition *pAnchorPos = rAnchor.GetContentAnchor(); - if (RndStdIds::FLY_AT_PAGE != eAnchorId && pAnchorPos) + const SwNode *pAnchorNode = rAnchor.GetAnchorNode(); + if (RndStdIds::FLY_AT_PAGE != eAnchorId && pAnchorNode) { - const SwNode& rNode = pAnchorPos->nNode.GetNode(); - if( rNode.IsContentNode() ) + 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, - rNode.GetContentNode()->GetSwAttrSet().GetBackground()) ) + pAnchorNode->GetContentNode()->GetSwAttrSet().GetBackground()) ) return; // Otherwise we also could be in a table - const SwTableNode *pTableNd = rNode.FindTableNode(); + const SwTableNode *pTableNd = pAnchorNode->FindTableNode(); if( pTableNd ) { - const SwStartNode *pBoxSttNd = rNode.FindTableBoxStartNode(); + const SwStartNode *pBoxSttNd = pAnchorNode->FindTableBoxStartNode(); const SwTableBox *pBox = pTableNd->GetTable().GetTableBox( pBoxSttNd->GetIndex() ); @@ -2215,7 +2175,7 @@ void SwHTMLWriter::OutCSS1_FrameFormatBackground( const SwFrameFormat& rFrameFor } // If the anchor is again in a Fly-Frame, use the background of the Fly-Frame. - const SwFrameFormat *pFrameFormat = rNode.GetFlyFormat(); + const SwFrameFormat *pFrameFormat = pAnchorNode->GetFlyFormat(); if( pFrameFormat ) { OutCSS1_FrameFormatBackground( *pFrameFormat ); @@ -2247,16 +2207,15 @@ void SwHTMLWriter::OutCSS1_FrameFormatBackground( const SwFrameFormat& rFrameFor OutCSS1_PropertyAscii(sCSS1_P_background, GetCSS1_Color(aColor)); } -static Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt, +static SwHTMLWriter& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( SwHTMLWriter& rWrt, const SvxUnderlineItem *pUItem, const SvxOverlineItem *pOItem, const SvxCrossedOutItem *pCOItem, const SvxBlinkItem *pBItem ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); bool bNone = false; + OStringBuffer sOut; - const char *pUStr = nullptr; if( pUItem ) { switch( pUItem->GetLineStyle() ) @@ -2267,19 +2226,18 @@ static Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt, case LINESTYLE_DONTKNOW: break; default: - if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + 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( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rHTMLWrt.mbReqIF, + OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rWrt.mbReqIF, "write underline as Hint?" ); - pUStr = sCSS1_PV_underline; + sOut.append(sCSS1_PV_underline); } break; } } - const char *pOStr = nullptr; if( pOItem ) { switch( pOItem->GetLineStyle() ) @@ -2290,19 +2248,20 @@ static Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt, case LINESTYLE_DONTKNOW: break; default: - if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + 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( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT), + OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT), "write overline as Hint?" ); - pOStr = sCSS1_PV_overline; + if (!sOut.isEmpty()) + sOut.append(' '); + sOut.append(sCSS1_PV_overline); } break; } } - const char *pCOStr = nullptr; if( pCOItem ) { switch( pCOItem->GetStrikeout() ) @@ -2313,88 +2272,64 @@ static Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt, case STRIKEOUT_DONTKNOW: break; default: - if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + 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( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rHTMLWrt.mbReqIF, + OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rWrt.mbReqIF, "write crossedOut as Hint?" ); - pCOStr = sCSS1_PV_line_through; + if (!sOut.isEmpty()) + sOut.append(' '); + sOut.append(sCSS1_PV_line_through); } break; } } - const char *pBStr = nullptr; if( pBItem ) { if( !pBItem->GetValue() ) { bNone = true; } - else if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + 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( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT), + OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT), "write blink as Hint?" ); - pBStr = sCSS1_PV_blink; + if (!sOut.isEmpty()) + sOut.append(' '); + sOut.append(sCSS1_PV_blink); } } - OStringBuffer sOut; - if( pUStr ) - sOut.append(pUStr); - - if( pOStr ) - { - if (!sOut.isEmpty()) - sOut.append(' '); - sOut.append(pOStr); - } - - if( pCOStr ) - { - if (!sOut.isEmpty()) - sOut.append(' '); - sOut.append(pCOStr); - } - - if( pBStr ) - { - if (!sOut.isEmpty()) - sOut.append(' '); - sOut.append(pBStr); - } - if (!sOut.isEmpty()) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sOut.makeStringAndClear() ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sOut ); else if( bNone ) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sCSS1_PV_none ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sCSS1_PV_none ); return rWrt; } -static Writer& OutCSS1_SvxCaseMap( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxCaseMap( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - switch( static_cast<const SvxCaseMapItem&>(rHt).GetCaseMap() ) { case SvxCaseMap::NotMapped: - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_normal ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_normal ); break; case SvxCaseMap::SmallCaps: - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_small_caps ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_small_caps ); break; case SvxCaseMap::Uppercase: - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_uppercase ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_uppercase ); break; case SvxCaseMap::Lowercase: - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_lowercase ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_lowercase ); break; case SvxCaseMap::Capitalize: - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_capitalize ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_capitalize ); break; default: ; @@ -2403,44 +2338,40 @@ static Writer& OutCSS1_SvxCaseMap( Writer& rWrt, const SfxPoolItem& rHt ) return rWrt; } -static Writer& OutCSS1_SvxColor( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxColor( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // Colors do not need to be exported for Style-Option. - if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) && - !rHTMLWrt.m_bCfgPreferStyles ) + if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) && + !rWrt.m_bCfgPreferStyles ) return rWrt; - OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT), + 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; - rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_color, GetCSS1_Color(aColor)); + rWrt.OutCSS1_PropertyAscii(sCSS1_P_color, GetCSS1_Color(aColor)); return rWrt; } -static Writer& OutCSS1_SvxCrossedOut( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxCrossedOut( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { // This function only exports Hints! // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly. - if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) ) + if( rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) ) OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt, nullptr, nullptr, static_cast<const SvxCrossedOutItem *>(&rHt), nullptr ); return rWrt; } -static Writer& OutCSS1_SvxFont( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxFont( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // No need to export Fonts for the Style-Option. - if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) return rWrt; sal_uInt16 nScript = CSS1_OUTMODE_WESTERN; @@ -2449,32 +2380,30 @@ static Writer& OutCSS1_SvxFont( Writer& rWrt, const SfxPoolItem& rHt ) case RES_CHRATR_CJK_FONT: nScript = CSS1_OUTMODE_CJK; break; case RES_CHRATR_CTL_FONT: nScript = CSS1_OUTMODE_CTL; break; } - if( !rHTMLWrt.IsCSS1Script( nScript ) ) + if( !rWrt.IsCSS1Script( nScript ) ) return rWrt; - OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT), + OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT), "write Font as Hint?" ); OUString sOut; // MS IE3b1 has problems with single quotes - sal_uInt16 nMode = rHTMLWrt.m_nCSS1OutMode & CSS1_OUTMODE_ANY_ON; + 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 ); - rHTMLWrt.OutCSS1_Property( sCSS1_P_font_family, sOut ); + rWrt.OutCSS1_Property( sCSS1_P_font_family, sOut ); return rWrt; } -static Writer& OutCSS1_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxFontHeight( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // Font-Height need not be exported in the Style-Option. // For Drop-Caps another Font-Size is exported. - if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) || - rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_DROPCAP ) ) + if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) || + rWrt.IsCSS1Source( CSS1_OUTMODE_DROPCAP ) ) return rWrt; sal_uInt16 nScript = CSS1_OUTMODE_WESTERN; @@ -2483,40 +2412,38 @@ static Writer& OutCSS1_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt ) case RES_CHRATR_CJK_FONTSIZE: nScript = CSS1_OUTMODE_CJK; break; case RES_CHRATR_CTL_FONTSIZE: nScript = CSS1_OUTMODE_CTL; break; } - if( !rHTMLWrt.IsCSS1Script( nScript ) ) + if( !rWrt.IsCSS1Script( nScript ) ) return rWrt; sal_uInt32 nHeight = static_cast<const SvxFontHeightItem&>(rHt).GetHeight(); OString sHeight(OString::number(nHeight/20) + sCSS1_UNIT_pt); - rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_font_size, sHeight); + rWrt.OutCSS1_PropertyAscii(sCSS1_P_font_size, sHeight); return rWrt; } -static Writer& OutCSS1_SvxPosture( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxPosture( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - 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( !rHTMLWrt.IsCSS1Script( nScript ) ) + if( !rWrt.IsCSS1Script( nScript ) ) return rWrt; - const char *pStr = nullptr; + 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( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + 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( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT), + OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT), "write italic as Hint?" ); pStr = sCSS1_PV_italic; } @@ -2525,16 +2452,14 @@ static Writer& OutCSS1_SvxPosture( Writer& rWrt, const SfxPoolItem& rHt ) ; } - if( pStr ) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_style, pStr ); + if( !pStr.empty() ) + rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_style, pStr ); return rWrt; } -static Writer& OutCSS1_SvxKerning( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxKerning( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - sal_Int16 nValue = static_cast<const SvxKerningItem&>(rHt).GetValue(); if( nValue ) { @@ -2550,24 +2475,22 @@ static Writer& OutCSS1_SvxKerning( Writer& rWrt, const SfxPoolItem& rHt ) sOut.append(OString::number(nValue / 10) + "." + OString::number(nValue % 10) + sCSS1_UNIT_pt); - rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_letter_spacing, - sOut.makeStringAndClear()); + rWrt.OutCSS1_PropertyAscii(sCSS1_P_letter_spacing, sOut); + sOut.setLength(0); } else { - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_letter_spacing, + rWrt.OutCSS1_PropertyAscii( sCSS1_P_letter_spacing, sCSS1_PV_normal ); } return rWrt; } -static Writer& OutCSS1_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxLanguage( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // Only export Language rules - if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) return rWrt; sal_uInt16 nScript = CSS1_OUTMODE_WESTERN; @@ -2576,10 +2499,10 @@ static Writer& OutCSS1_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt ) case RES_CHRATR_CJK_LANGUAGE: nScript = CSS1_OUTMODE_CJK; break; case RES_CHRATR_CTL_LANGUAGE: nScript = CSS1_OUTMODE_CTL; break; } - if( !rHTMLWrt.IsCSS1Script( nScript ) ) + if( !rWrt.IsCSS1Script( nScript ) ) return rWrt; - OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT), + OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT), "write Language as Hint?" ); LanguageType eLang = static_cast<const SvxLanguageItem &>(rHt).GetLanguage(); @@ -2588,59 +2511,55 @@ static Writer& OutCSS1_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt ) OUString sOut = LanguageTag::convertToBcp47( eLang ); - rHTMLWrt.OutCSS1_Property( sCSS1_P_so_language, sOut ); + rWrt.OutCSS1_Property( sCSS1_P_so_language, sOut ); return rWrt; } -static Writer& OutCSS1_SvxUnderline( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxUnderline( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { // This function only exports Hints! // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly. - if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) ) + if( rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) ) OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt, static_cast<const SvxUnderlineItem *>(&rHt), nullptr, nullptr, nullptr ); return rWrt; } -static Writer& OutCSS1_SvxOverline( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxOverline( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { // This function only exports Hints! // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly. - if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) ) + if( rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) ) OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt, nullptr, static_cast<const SvxOverlineItem *>(&rHt), nullptr, nullptr ); return rWrt; } -static Writer& OutCSS1_SvxHidden( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxHidden( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if ( static_cast<const SvxCharHiddenItem&>(rHt).GetValue() ) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_display, sCSS1_PV_none ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_display, sCSS1_PV_none ); return rWrt; } -static Writer& OutCSS1_SvxFontWeight( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxFontWeight( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - 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( !rHTMLWrt.IsCSS1Script( nScript ) ) + if( !rWrt.IsCSS1Script( nScript ) ) return rWrt; - const char *pStr = nullptr; + std::string_view pStr; switch( static_cast<const SvxWeightItem&>(rHt).GetWeight() ) { case WEIGHT_ULTRALIGHT: pStr = sCSS1_PV_extra_light; break; @@ -2649,11 +2568,11 @@ static Writer& OutCSS1_SvxFontWeight( Writer& rWrt, const SfxPoolItem& rHt ) case WEIGHT_NORMAL: pStr = sCSS1_PV_normal; break; case WEIGHT_SEMIBOLD: pStr = sCSS1_PV_demi_bold; break; case WEIGHT_BOLD: - if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + 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( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT), + OSL_ENSURE( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT), "write bold as Hint?" ); pStr = sCSS1_PV_bold; } @@ -2663,32 +2582,30 @@ static Writer& OutCSS1_SvxFontWeight( Writer& rWrt, const SfxPoolItem& rHt ) pStr = sCSS1_PV_normal; } - if( pStr ) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_weight, pStr ); + if( !pStr.empty() ) + rWrt.OutCSS1_PropertyAscii( sCSS1_P_font_weight, pStr ); return rWrt; } -static Writer& OutCSS1_SvxBlink( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxBlink( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { // This function only exports Hints! // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly. - if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) ) + if( rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) ) OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt, nullptr, nullptr, nullptr, static_cast<const SvxBlinkItem *>(&rHt) ); return rWrt; } -static Writer& OutCSS1_SvxLineSpacing( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxLineSpacing( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // 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( rHTMLWrt.m_bOutTable && rHTMLWrt.m_bCfgNetscape4 ) + if( rWrt.m_bOutTable && rWrt.m_bCfgNetscape4 ) return rWrt; const SvxLineSpacingItem& rLSItem = static_cast<const SvxLineSpacingItem&>(rHt); @@ -2724,27 +2641,25 @@ static Writer& OutCSS1_SvxLineSpacing( Writer& rWrt, const SfxPoolItem& rHt ) } if( nHeight ) - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_line_height, static_cast<tools::Long>(nHeight) ); + rWrt.OutCSS1_UnitProperty( sCSS1_P_line_height, static_cast<tools::Long>(nHeight) ); else if( nPercentHeight && - !(nPercentHeight < 115 && rHTMLWrt.m_bParaDotLeaders )) // avoid HTML scrollbars and missing descenders + !(nPercentHeight < 115 && rWrt.m_bParaDotLeaders )) // avoid HTML scrollbars and missing descenders { OString sHeight(OString::number(nPercentHeight) + "%"); - rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_line_height, sHeight); + rWrt.OutCSS1_PropertyAscii(sCSS1_P_line_height, sHeight); } return rWrt; } -static Writer& OutCSS1_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxAdjust( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // Export Alignment in Style-Option only if the Tag does not allow ALIGN=xxx - if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) && - !rHTMLWrt.m_bNoAlign) + if( rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) && + !rWrt.m_bNoAlign) return rWrt; - const char* pStr = nullptr; + std::string_view pStr; switch( static_cast<const SvxAdjustItem&>(rHt).GetAdjust() ) { case SvxAdjust::Left: pStr = sCSS1_PV_left; break; @@ -2755,52 +2670,44 @@ static Writer& OutCSS1_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt ) ; } - if( pStr ) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_align, pStr ); + if( !pStr.empty() ) + rWrt.OutCSS1_PropertyAscii( sCSS1_P_text_align, pStr ); return rWrt; } -static Writer& OutCSS1_SvxFormatSplit( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxFormatSplit( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - const char *pStr = static_cast<const SvxFormatSplitItem&>(rHt).GetValue() + std::string_view pStr = static_cast<const SvxFormatSplitItem&>(rHt).GetValue() ? sCSS1_PV_auto : sCSS1_PV_avoid; - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr ); return rWrt; } -static Writer& OutCSS1_SwFormatLayoutSplit( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SwFormatLayoutSplit( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - const char *pStr = static_cast<const SwFormatLayoutSplit&>(rHt).GetValue() + std::string_view pStr = static_cast<const SwFormatLayoutSplit&>(rHt).GetValue() ? sCSS1_PV_auto : sCSS1_PV_avoid; - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr ); return rWrt; } -static Writer& OutCSS1_SvxWidows( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxWidows( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - OString aStr(OString::number(static_cast<const SvxWidowsItem&>(rHt).GetValue())); - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_widows, aStr ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_widows, aStr ); return rWrt; } -static Writer& OutCSS1_SvxOrphans( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxOrphans( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - OString aStr(OString::number(static_cast<const SvxOrphansItem&>(rHt).GetValue())); - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_orphans, aStr ); + rWrt.OutCSS1_PropertyAscii( sCSS1_P_orphans, aStr ); return rWrt; } @@ -2827,40 +2734,36 @@ static void OutCSS1_SwFormatDropAttrs( SwHTMLWriter& rHWrt, else if( pDCCharFormat ) rHWrt.OutCSS1_SfxItemSet( pDCCharFormat->GetAttrSet() ); else if( (rHWrt.m_nCSS1OutMode & CSS1_OUTMODE_ANY_OFF) == CSS1_OUTMODE_RULE_OFF ) - rHWrt.Strm().WriteCharPtr( sCSS1_rule_end ); + rHWrt.Strm().WriteOString( sCSS1_rule_end ); } -static Writer& OutCSS1_SwFormatDrop( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SwFormatDrop( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // never export as an Option of a paragraph, but only as Hints - if( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) ) + if( !rWrt.IsCSS1Source(CSS1_OUTMODE_HINT) ) return rWrt; - if( rHTMLWrt.m_bTagOn ) + if( rWrt.m_bTagOn ) { - SwCSS1OutMode aMode( rHTMLWrt, - rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_SPAN_TAG1_ON|CSS1_OUTMODE_ENCODE| + SwCSS1OutMode aMode( rWrt, + rWrt.m_nCSS1Script|CSS1_OUTMODE_SPAN_TAG1_ON|CSS1_OUTMODE_ENCODE| CSS1_OUTMODE_DROPCAP, nullptr ); - OutCSS1_SwFormatDropAttrs( rHTMLWrt, static_cast<const SwFormatDrop&>(rHt) ); + OutCSS1_SwFormatDropAttrs( rWrt, static_cast<const SwFormatDrop&>(rHt) ); // A "> is already printed by the calling OutCSS1_HintAsSpanTag. } else { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false ); } return rWrt; } -static Writer& OutCSS1_SwFormatFrameSize( Writer& rWrt, const SfxPoolItem& rHt, +static SwHTMLWriter& OutCSS1_SwFormatFrameSize( SwHTMLWriter& rWrt, const SfxPoolItem& rHt, Css1FrameSize nMode ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - const SwFormatFrameSize& rFSItem = static_cast<const SwFormatFrameSize&>(rHt); if( nMode & Css1FrameSize::Width ) @@ -2869,16 +2772,16 @@ static Writer& OutCSS1_SwFormatFrameSize( Writer& rWrt, const SfxPoolItem& rHt, if( nPercentWidth ) { OString sOut(OString::number(nPercentWidth) + "%"); - rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_width, sOut); + rWrt.OutCSS1_PropertyAscii(sCSS1_P_width, sOut); } else if( nMode & Css1FrameSize::Pixel ) { - rHTMLWrt.OutCSS1_PixelProperty( sCSS1_P_width, - rFSItem.GetSize().Width(), false ); + rWrt.OutCSS1_PixelProperty( sCSS1_P_width, + rFSItem.GetSize().Width() ); } else { - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_width, + rWrt.OutCSS1_UnitProperty( sCSS1_P_width, rFSItem.GetSize().Width() ); } } @@ -2886,81 +2789,130 @@ static Writer& OutCSS1_SwFormatFrameSize( Writer& rWrt, const SfxPoolItem& rHt, return rWrt; } -static Writer& OutCSS1_SvxLRSpace( Writer& rWrt, const SfxPoolItem& rHt ) +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) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); + 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, o3tl::convert(DOT_LEADERS_MAX_WIDTH, o3tl::Length::cm, o3tl::Length::twip) - 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() - rHTMLWrt.m_nLeftMargin; - if( rHTMLWrt.m_nDfltLeftMargin != nLeftMargin ) + tools::Long nLeftMargin = rLRItem.GetTextLeft() - rWrt.m_nLeftMargin; + if( rWrt.m_nDfltLeftMargin != nLeftMargin ) { - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLeftMargin ); + rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLeftMargin ); // max-width = max-width - margin-left for TOC paragraphs with dot leaders - if( rHTMLWrt.m_bParaDotLeaders ) - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_max_width, tools::Long(DOT_LEADERS_MAX_WIDTH/2.54*72*20) - nLeftMargin ); + if( rWrt.m_bParaDotLeaders ) + rWrt.OutCSS1_UnitProperty( sCSS1_P_max_width, o3tl::convert(DOT_LEADERS_MAX_WIDTH, o3tl::Length::cm, o3tl::Length::twip) - nLeftMargin ); } - if( rHTMLWrt.m_nDfltRightMargin != rLRItem.GetRight() ) + if( rWrt.m_nDfltRightMargin != rLRItem.GetRight() ) { - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_right, 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()) - - rHTMLWrt.m_nFirstLineIndent; - if( rHTMLWrt.m_nDfltFirstLineIndent != nFirstLineIndent ) + rWrt.m_nFirstLineIndent; + if( rWrt.m_nDfltFirstLineIndent != nFirstLineIndent ) { - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent, + rWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent, nFirstLineIndent ); } return rWrt; } -static Writer& OutCSS1_SvxULSpace( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxULSpace( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - const SvxULSpaceItem& rULItem = static_cast<const SvxULSpaceItem&>(rHt); - if( rHTMLWrt.m_nDfltTopMargin != rULItem.GetUpper() ) + if( rWrt.m_nDfltTopMargin != rULItem.GetUpper() ) { - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_top, + rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_top, static_cast<tools::Long>(rULItem.GetUpper()) ); } - if( rHTMLWrt.m_nDfltBottomMargin != rULItem.GetLower() ) + if( rWrt.m_nDfltBottomMargin != rULItem.GetLower() ) { - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_bottom, + rWrt.OutCSS1_UnitProperty( sCSS1_P_margin_bottom, static_cast<tools::Long>(rULItem.GetLower()) ); } return rWrt; } -static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt, +static SwHTMLWriter& OutCSS1_SvxULSpace_SvxLRSpace( SwHTMLWriter& rWrt, const SvxULSpaceItem *pULItem, const SvxLRSpaceItem *pLRItem ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( pLRItem && pULItem && pLRItem->GetLeft() == pLRItem->GetRight() && pLRItem->GetLeft() == pULItem->GetUpper() && pLRItem->GetLeft() == pULItem->GetLower() && - pLRItem->GetLeft() != rHTMLWrt.m_nDfltLeftMargin && - pLRItem->GetRight() != rHTMLWrt.m_nDfltRightMargin && - pULItem->GetUpper() != rHTMLWrt.m_nDfltTopMargin && - pULItem->GetLower() != rHTMLWrt.m_nDfltBottomMargin ) + pLRItem->GetLeft() != rWrt.m_nDfltLeftMargin && + pLRItem->GetRight() != rWrt.m_nDfltRightMargin && + pULItem->GetUpper() != rWrt.m_nDfltTopMargin && + pULItem->GetLower() != rWrt.m_nDfltBottomMargin ) { - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin, pLRItem->GetLeft() ); + rWrt.OutCSS1_UnitProperty( sCSS1_P_margin, pLRItem->GetLeft() ); } else { @@ -2973,17 +2925,11 @@ static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt, return rWrt; } -static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt, +static SwHTMLWriter& OutCSS1_SvxULSpace_SvxLRSpace( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet ) { - const SvxULSpaceItem *pULSpace = nullptr; - const SvxLRSpaceItem *pLRSpace = nullptr; - const SfxPoolItem *pItem; - if( SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE, false/*bDeep*/, &pItem ) ) - pLRSpace = static_cast<const SvxLRSpaceItem *>(pItem); - - if( SfxItemState::SET == rItemSet.GetItemState( RES_UL_SPACE, false/*bDeep*/, &pItem ) ) - pULSpace = static_cast<const SvxULSpaceItem *>(pItem); + 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 ); @@ -2991,18 +2937,16 @@ static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt, return rWrt; } -static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt, +static SwHTMLWriter& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( SwHTMLWriter& rWrt, const SvxFormatBreakItem *pBreakItem, const SwFormatPageDesc *pPDescItem, const SvxFormatKeepItem *pKeepItem ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - if( !rHTMLWrt.IsHTMLMode(HTMLMODE_PRINT_EXT) ) + if( !rWrt.IsHTMLMode(HTMLMODE_PRINT_EXT) ) return rWrt; - const char *pBreakBefore = nullptr; - const char *pBreakAfter = nullptr; + std::string_view pBreakBefore; + std::string_view pBreakAfter; if( pKeepItem ) { @@ -3014,7 +2958,7 @@ static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt, { case SvxBreak::NONE: pBreakBefore = sCSS1_PV_auto; - if( !pBreakAfter ) + if( pBreakAfter.empty() ) pBreakAfter = sCSS1_PV_auto; break; @@ -3042,47 +2986,40 @@ static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt, default: pBreakBefore = sCSS1_PV_always; break; } } - else if( !pBreakBefore ) + else if( pBreakBefore.empty() ) { pBreakBefore = sCSS1_PV_auto; } } - if (rHTMLWrt.mbSkipHeaderFooter) + if (rWrt.mbSkipHeaderFooter) // No page break when writing only a fragment. return rWrt; - if( pBreakBefore ) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_before, + if( !pBreakBefore.empty() ) + rWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_before, pBreakBefore ); - if( pBreakAfter ) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_after, + if( !pBreakAfter.empty() ) + rWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_after, pBreakAfter ); return rWrt; } -static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt, +static SwHTMLWriter& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet, bool bDeep ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - const SfxPoolItem *pItem; - const SvxFormatBreakItem *pBreakItem = nullptr; - if( SfxItemState::SET==rItemSet.GetItemState( RES_BREAK, bDeep, &pItem )) - pBreakItem = static_cast<const SvxFormatBreakItem *>(pItem); + const SvxFormatBreakItem *pBreakItem = rItemSet.GetItemIfSet( RES_BREAK, bDeep ); const SwFormatPageDesc *pPDescItem = nullptr; - if( ( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) || - !rHTMLWrt.m_bCSS1IgnoreFirstPageDesc || - rHTMLWrt.m_pStartNdIdx->GetIndex() != - rHTMLWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() ) && - SfxItemState::SET==rItemSet.GetItemState( RES_PAGEDESC, bDeep, &pItem )) - pPDescItem = static_cast<const SwFormatPageDesc*>(pItem); + 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 = nullptr; - if( SfxItemState::SET==rItemSet.GetItemState( RES_KEEP, bDeep, &pItem )) - pKeepItem = static_cast<const SvxFormatKeepItem *>(pItem); + const SvxFormatKeepItem *pKeepItem = rItemSet.GetItemIfSet( RES_KEEP, bDeep ); if( pBreakItem || pPDescItem || pKeepItem ) OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( rWrt, pBreakItem, @@ -3092,22 +3029,20 @@ static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt, } // Wrapper for OutCSS1_SfxItemSet etc. -static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - OutCSS1_SvxBrush( rWrt, rHt, Css1Background::Attr, nullptr ); + OutCSS1_SvxBrush( rWrt, rHt, sw::Css1Background::Attr, nullptr ); return rWrt; } -static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt, - Css1Background nMode, +static SwHTMLWriter& OutCSS1_SvxBrush( SwHTMLWriter& rWrt, const SfxPoolItem& rHt, + sw::Css1Background nMode, const OUString* pGraphicName) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // The Character-Attribute is skipped, if we are about to // exporting options if( rHt.Which() < RES_CHRATR_END && - rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) return rWrt; // start getting a few values @@ -3116,7 +3051,7 @@ static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt, OUString aLink = pGraphicName ? *pGraphicName : static_cast<const SvxBrushItem &>(rHt).GetGraphicLink(); SvxGraphicPosition ePos = static_cast<const SvxBrushItem &>(rHt).GetGraphicPos(); - if( Css1Background::Page == nMode && !rHTMLWrt.mbEmbedImages ) + if( sw::Css1Background::Page == nMode && !rWrt.mbEmbedImages ) { // page style images are exported if not tiled if( aLink.isEmpty() || GPOS_TILED==ePos ) @@ -3139,30 +3074,30 @@ static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt, // Embedded Graphic -> export WriteEmbedded const Graphic* pGrf = nullptr; - if( rHTMLWrt.mbEmbedImages || aLink.isEmpty()) + if( rWrt.mbEmbedImages || aLink.isEmpty()) { pGrf = static_cast<const SvxBrushItem &>(rHt).GetGraphic(); if( pGrf ) { if( !XOutBitmap::GraphicToBase64(*pGrf, aGraphicInBase64) ) { - rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD; + rWrt.m_nWarn = WARN_SWG_POOR_LOAD; } } aLink.clear(); } - else if( !pGraphicName && rHTMLWrt.m_bCfgCpyLinkedGrfs ) + 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( Css1Background::Table==nMode && !pGrf && !aLink.isEmpty()) + if( (nMode == sw::Css1Background::Table || nMode == sw::Css1Background::TableRow) && !pGrf && !aLink.isEmpty()) return rWrt; // if necessary, add the orientation of the Graphic - const char *pRepeat = nullptr, *pHori = nullptr, *pVert = nullptr; + std::string_view pRepeat, pHori, pVert; if( pGrf || !aLink.isEmpty() ) { if( GPOS_TILED==ePos ) @@ -3219,7 +3154,7 @@ static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt, ; } - if( pHori || pVert ) + if( !pHori.empty() || !pVert.empty() ) pRepeat = sCSS1_PV_no_repeat; } } @@ -3229,7 +3164,7 @@ static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt, if( !pGrf && aLink.isEmpty() && !bColor ) { // no color and no Link, but a transparent Brush - if( bTransparent && Css1Background::Fly != nMode ) + if( bTransparent && sw::Css1Background::Fly != nMode ) sOut += OStringToOUString(sCSS1_PV_transparent, RTL_TEXTENCODING_ASCII_US); } else @@ -3257,16 +3192,16 @@ static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt, aLink) + ")"; } - if( pRepeat ) + if( !pRepeat.empty() ) { sOut += " " + OStringToOUString(pRepeat, RTL_TEXTENCODING_ASCII_US); } - if( pHori ) + if( !pHori.empty() ) { sOut += " " + OStringToOUString(pHori, RTL_TEXTENCODING_ASCII_US); } - if( pVert ) + if( !pVert.empty() ) { sOut += " " + OStringToOUString(pVert, RTL_TEXTENCODING_ASCII_US); } @@ -3276,27 +3211,28 @@ static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt, } if( !sOut.isEmpty() ) - rHTMLWrt.OutCSS1_Property( sCSS1_P_background, sOut ); + { + rWrt.OutCSS1_Property(sCSS1_P_background, std::string_view(), &sOut, + nMode); + } return rWrt; } -static void OutCSS1_SvxBorderLine( SwHTMLWriter& rHTMLWrt, - const char *pProperty, +static void OutCSS1_SvxBorderLine( SwHTMLWriter& rWrt, + std::string_view pProperty, const SvxBorderLine *pLine ) { if( !pLine || pLine->isEmpty() ) { - rHTMLWrt.OutCSS1_PropertyAscii( pProperty, sCSS1_PV_none ); + rWrt.OutCSS1_PropertyAscii( pProperty, sCSS1_PV_none ); return; } sal_Int32 nWidth = pLine->GetWidth(); OStringBuffer sOut; - if( Application::GetDefaultDevice() && - nWidth <= Application::GetDefaultDevice()->PixelToLogic( - Size( 1, 1 ), MapMode( MapUnit::MapTwip) ).Width() ) + 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. @@ -3353,28 +3289,28 @@ static void OutCSS1_SvxBorderLine( SwHTMLWriter& rHTMLWrt, // and also the color sOut.append(GetCSS1_Color(pLine->GetColor())); - rHTMLWrt.OutCSS1_PropertyAscii(pProperty, sOut.makeStringAndClear()); + rWrt.OutCSS1_PropertyAscii(pProperty, sOut); } -Writer& OutCSS1_SvxBox( Writer& rWrt, const SfxPoolItem& rHt ) +SwHTMLWriter& OutCSS1_SvxBox( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // Avoid interference between character and paragraph attributes if( rHt.Which() < RES_CHRATR_END && - rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) + rWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ) return rWrt; if( rHt.Which() == RES_CHRATR_BOX ) { - if( rHTMLWrt.m_bTagOn ) + constexpr std::string_view inline_block("inline-block"); + if( rWrt.m_bTagOn ) { // Inline-block to make the line height changing correspond to the character border - rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_display, "inline-block"); + rWrt.OutCSS1_PropertyAscii(sCSS1_P_display, inline_block); } else { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false ); + if (!IgnorePropertyForReqIF(rWrt.mbReqIF, sCSS1_P_display, inline_block)) + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false ); return rWrt; } } @@ -3391,15 +3327,15 @@ Writer& OutCSS1_SvxBox( Writer& rWrt, const SfxPoolItem& rHt ) { // all Lines are set and equal, or all Lines are not set // => border : ... - OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border, pTop ); + OutCSS1_SvxBorderLine( rWrt, sCSS1_P_border, pTop ); } else { // otherwise export all Lines separately - OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_top, pTop ); - OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_bottom, pBottom ); - OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_left, pLeft ); - OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_right, pRight ); + 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; @@ -3410,36 +3346,34 @@ Writer& OutCSS1_SvxBox( Writer& rWrt, const SfxPoolItem& rHt ) if( nTopDist == nBottomDist && nLeftDist == nRightDist ) { OStringBuffer sVal; - AddUnitPropertyValue(sVal, nTopDist, rHTMLWrt.GetCSS1Unit()); + AddUnitPropertyValue(sVal, nTopDist, rWrt.GetCSS1Unit()); if( nTopDist != nLeftDist ) { sVal.append(' '); - AddUnitPropertyValue(sVal, nLeftDist, rHTMLWrt.GetCSS1Unit()); + AddUnitPropertyValue(sVal, nLeftDist, rWrt.GetCSS1Unit()); } - rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_padding, sVal.makeStringAndClear()); + rWrt.OutCSS1_PropertyAscii(sCSS1_P_padding, sVal); } else { - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_top, nTopDist ); - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_bottom, nBottomDist ); - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_left, nLeftDist ); - rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_right, nRightDist ); + 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 Writer& OutCSS1_SvxFrameDirection( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutCSS1_SvxFrameDirection( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast< SwHTMLWriter& >( rWrt ); - // Language will be exported rules only - if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_TEMPLATE ) ) + if( !rWrt.IsCSS1Source( CSS1_OUTMODE_TEMPLATE ) ) return rWrt; SvxFrameDirection nDir = static_cast< const SvxFrameDirectionItem& >( rHt ).GetValue(); - const char* pStr = nullptr; + std::string_view pStr; switch( nDir ) { case SvxFrameDirection::Horizontal_LR_TB: @@ -3456,8 +3390,8 @@ static Writer& OutCSS1_SvxFrameDirection( Writer& rWrt, const SfxPoolItem& rHt ) default: break; } - if( pStr ) - rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_direction, pStr ); + if( !pStr.empty() ) + rWrt.OutCSS1_PropertyAscii( sCSS1_P_direction, pStr ); return rWrt; } @@ -3525,14 +3459,14 @@ SwAttrFnTab const aCSS1AttrFnTab = { /* 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_DUMMY3 */ nullptr, +/* RES_TXTATR_LINEBREAK */ nullptr, /* RES_TXTATR_DUMMY1 */ nullptr, // Dummy: -/* RES_TXTATR_DUMMY2 */ nullptr, // Dummy: /* RES_PARATR_LINESPACING */ OutCSS1_SvxLineSpacing, /* RES_PARATR_ADJUST */ OutCSS1_SvxAdjust, @@ -3564,6 +3498,12 @@ SwAttrFnTab const aCSS1AttrFnTab = { /* 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, @@ -3596,6 +3536,7 @@ SwAttrFnTab const aCSS1AttrFnTab = { /* 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, @@ -3604,6 +3545,9 @@ SwAttrFnTab const aCSS1AttrFnTab = { /* 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, @@ -3617,8 +3561,6 @@ SwAttrFnTab const aCSS1AttrFnTab = { /* RES_GRFATR_INVERT */ nullptr, /* RES_GRFATR_TRANSPARENCY */ nullptr, /* RES_GRFATR_DRWAMODE */ nullptr, -/* RES_GRFATR_DUMMY1 */ nullptr, -/* RES_GRFATR_DUMMY2 */ nullptr, /* RES_GRFATR_DUMMY3 */ nullptr, /* RES_GRFATR_DUMMY4 */ nullptr, /* RES_GRFATR_DUMMY5 */ nullptr, @@ -3631,33 +3573,28 @@ SwAttrFnTab const aCSS1AttrFnTab = { static_assert(SAL_N_ELEMENTS(aCSS1AttrFnTab) == RES_BOXATR_END); void SwHTMLWriter::OutCSS1_SfxItemSet( const SfxItemSet& rItemSet, - bool bDeep ) + bool bDeep, std::string_view rAdd ) { // print ItemSet, including all attributes Out_SfxItemSet( aCSS1AttrFnTab, *this, rItemSet, bDeep ); // some Attributes require special treatment - const SfxPoolItem *pItem = nullptr; // 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 = nullptr; - if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_UNDERLINE, bDeep, &pItem )) - pUnderlineItem = static_cast<const SvxUnderlineItem *>(pItem); + const SvxUnderlineItem *pUnderlineItem = + rItemSet.GetItemIfSet( RES_CHRATR_UNDERLINE, bDeep ); - const SvxOverlineItem *pOverlineItem = nullptr; - if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_OVERLINE, bDeep, &pItem )) - pOverlineItem = static_cast<const SvxOverlineItem *>(pItem); + const SvxOverlineItem *pOverlineItem = + rItemSet.GetItemIfSet( RES_CHRATR_OVERLINE, bDeep ); - const SvxCrossedOutItem *pCrossedOutItem = nullptr; - if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_CROSSEDOUT, bDeep, &pItem )) - pCrossedOutItem = static_cast<const SvxCrossedOutItem *>(pItem); + const SvxCrossedOutItem *pCrossedOutItem = + rItemSet.GetItemIfSet( RES_CHRATR_CROSSEDOUT, bDeep ); - const SvxBlinkItem *pBlinkItem = nullptr; - if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_BLINK, bDeep, &pItem )) - pBlinkItem = static_cast<const SvxBlinkItem *>(pItem); + const SvxBlinkItem *pBlinkItem = + rItemSet.GetItemIfSet( RES_CHRATR_BLINK, bDeep ); if( pUnderlineItem || pOverlineItem || pCrossedOutItem || pBlinkItem ) OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( *this, pUnderlineItem, @@ -3668,6 +3605,20 @@ void SwHTMLWriter::OutCSS1_SfxItemSet( const SfxItemSet& rItemSet, 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; @@ -3689,35 +3640,31 @@ void SwHTMLWriter::OutCSS1_SfxItemSet( const SfxItemSet& rItemSet, break; } if (!sOut.isEmpty()) - Strm().WriteOString( sOut.makeStringAndClear() ); + Strm().WriteOString( sOut ); } -Writer& OutCSS1_HintSpanTag( Writer& rWrt, const SfxPoolItem& rHt ) +SwHTMLWriter& OutCSS1_HintSpanTag( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_SPAN_TAG | + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_SPAN_TAG | CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_HINT, nullptr ); Out( aCSS1AttrFnTab, rHt, rWrt ); - if( !rHTMLWrt.m_bFirstCSS1Property && rHTMLWrt.m_bTagOn ) - rWrt.Strm().WriteCharPtr( sCSS1_span_tag_end ); + if( !rWrt.m_bFirstCSS1Property && rWrt.m_bTagOn ) + rWrt.Strm().WriteOString( sCSS1_span_tag_end ); return rWrt; } -Writer& OutCSS1_HintStyleOpt( Writer& rWrt, const SfxPoolItem& rHt ) +SwHTMLWriter& OutCSS1_HintStyleOpt( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON | + SwCSS1OutMode aMode( rWrt, CSS1_OUTMODE_STYLE_OPT_ON | CSS1_OUTMODE_ENCODE| CSS1_OUTMODE_HINT, nullptr ); Out( aCSS1AttrFnTab, rHt, rWrt ); - if( !rHTMLWrt.m_bFirstCSS1Property ) + if( !rWrt.m_bFirstCSS1Property ) rWrt.Strm().WriteChar( '\"' ); return rWrt; diff --git a/sw/source/filter/html/css1kywd.cxx b/sw/source/filter/html/css1kywd.cxx deleted file mode 100644 index af8c5392a765..000000000000 --- a/sw/source/filter/html/css1kywd.cxx +++ /dev/null @@ -1,214 +0,0 @@ -/* -*- 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 "css1kywd.hxx" - -const char* const sCSS_mimetype = "text/css"; - -const char* const sCSS1_page = "page"; -//const char* const sCSS1_media = "media"; - -const char* const sCSS1_link = "link"; -const char* const sCSS1_visited = "visited"; -const char* const sCSS1_first_letter = "first-letter"; - -const char* const sCSS1_left = "left"; -const char* const sCSS1_right = "right"; -const char* const sCSS1_first = "first"; - -const char* const sCSS1_url = "url"; - -const char* const sCSS1_UNIT_pt = "pt"; -const char* const sCSS1_UNIT_mm = "mm"; -const char* const sCSS1_UNIT_cm = "cm"; -const char* const sCSS1_UNIT_pc = "pc"; -const char* const sCSS1_UNIT_inch = "in"; -const char* const sCSS1_UNIT_px = "px"; - -// Strings for font properties - -const char* const sCSS1_P_font_family = "font-family"; - -const char* const sCSS1_PV_serif = "serif"; -const char* const sCSS1_PV_sans_serif = "sans-serif"; -const char* const sCSS1_PV_cursive = "cursive"; -const char* const sCSS1_PV_fantasy = "fantasy"; -const char* const sCSS1_PV_monospace = "monospace"; - -const char* const sCSS1_P_font_style = "font-style"; - -const char* const sCSS1_PV_normal = "normal"; -const char* const sCSS1_PV_italic = "italic"; -const char* const sCSS1_PV_oblique = "oblique"; - -const char* const sCSS1_P_font_variant = "font-variant"; - -//const char* const sCSS1_PV_normal = "normal"; -const char* const sCSS1_PV_small_caps = "small-caps"; - -const char* const sCSS1_P_font_weight = "font-weight"; - -const char* const sCSS1_PV_extra_light = "extra-light"; -const char* const sCSS1_PV_light = "light"; -const char* const sCSS1_PV_demi_light = "demi-light"; -//const char* const sCSS1_PV_medium = "medium"; -const char* const sCSS1_PV_demi_bold = "demi-bold"; -const char* const sCSS1_PV_bold = "bold"; -const char* const sCSS1_PV_extra_bold = "extra-bold"; - -const char* const sCSS1_P_text_transform = "text-transform"; - -const char* const sCSS1_PV_capitalize = "capitalize"; -const char* const sCSS1_PV_uppercase = "uppercase"; -const char* const sCSS1_PV_lowercase = "lowercase"; - -const char* const sCSS1_P_font_size = "font-size"; - -const char* const sCSS1_P_font = "font"; - -// Strings for color and background properties - -const char* const sCSS1_P_color = "color"; - -const char* const sCSS1_P_background = "background"; -const char* const sCSS1_P_background_color = "background-color"; - -const char* const sCSS1_PV_transparent = "transparent"; - -const char* const sCSS1_PV_repeat = "repeat"; -const char* const sCSS1_PV_no_repeat = "no-repeat"; - -const char* const sCSS1_PV_top = "top"; -const char* const sCSS1_PV_middle = "middle"; -const char* const sCSS1_PV_bottom = "bottom"; - -const char* const sCSS1_PV_scroll = "scroll"; - -// Strings for text properties - -const char* const sCSS1_P_letter_spacing = "letter-spacing"; - -const char* const sCSS1_P_text_decoration = "text-decoration"; - -const char* const sCSS1_PV_none = "none"; -const char* const sCSS1_PV_underline = "underline"; -const char* const sCSS1_PV_overline = "overline"; -const char* const sCSS1_PV_line_through = "line-through"; -const char* const sCSS1_PV_blink = "blink"; - -const char* const sCSS1_P_text_align = "text-align"; - -const char* const sCSS1_PV_left = "left"; -const char* const sCSS1_PV_center = "center"; -const char* const sCSS1_PV_right = "right"; -const char* const sCSS1_PV_justify = "justify"; - -const char* const sCSS1_P_text_indent = "text-indent"; - -const char* const sCSS1_P_line_height = "line-height"; -const char* const sCSS1_P_list_style_type = "list-style-type"; - -// Strings for box properties - -const char* const sCSS1_P_margin_left = "margin-left"; -const char* const sCSS1_P_margin_right = "margin-right"; -const char* const sCSS1_P_margin_top = "margin-top"; -const char* const sCSS1_P_margin_bottom = "margin-bottom"; -const char* const sCSS1_P_margin = "margin"; - -const char* const sCSS1_P_padding_top = "padding-top"; -const char* const sCSS1_P_padding_bottom = "padding-bottom"; -const char* const sCSS1_P_padding_left = "padding-left"; -const char* const sCSS1_P_padding_right = "padding-right"; -const char* const sCSS1_P_padding = "padding"; - -const char* const sCSS1_PV_auto = "auto"; - -const char* const sCSS1_P_border_left_width = "border-left-width"; -const char* const sCSS1_P_border_right_width = "border-right-width"; -const char* const sCSS1_P_border_top_width = "border-top-width"; -const char* const sCSS1_P_border_bottom_width = "border-bottom-width"; -const char* const sCSS1_P_border_width = "border-width"; -const char* const sCSS1_P_border_color = "border-color"; -const char* const sCSS1_P_border_style = "border-style"; -const char* const sCSS1_P_border_left = "border-left"; -const char* const sCSS1_P_border_right = "border-right"; -const char* const sCSS1_P_border_top = "border-top"; -const char* const sCSS1_P_border_bottom = "border-bottom"; -const char* const sCSS1_P_border = "border"; - -//const char* const sCSS1_PV_none = "none"; -const char* const sCSS1_PV_dotted = "dotted"; -const char* const sCSS1_PV_dashed = "dashed"; -const char* const sCSS1_PV_solid = "solid"; -const char* const sCSS1_PV_double = "double"; -const char* const sCSS1_PV_groove = "groove"; -const char* const sCSS1_PV_ridge = "ridge"; -const char* const sCSS1_PV_inset = "inset"; -const char* const sCSS1_PV_outset = "outset"; - -const char* const sCSS1_P_width = "width"; -const char* const sCSS1_P_max_width = "max-width"; - -const char* const sCSS1_P_height = "height"; - -const char* const sCSS1_P_float = "float"; - -const char* const sCSS1_P_column_count = "column-count"; - -// Strings for positioning - -const char* const sCSS1_P_position = "position"; - -const char* const sCSS1_PV_absolute = "absolute"; - -const char* const sCSS1_P_left = "left"; - -const char* const sCSS1_P_top = "top"; - -// Strings for printing extensions - -const char* const sCSS1_P_page_break_before = "page-break-before"; -const char* const sCSS1_P_page_break_after = "page-break-after"; -const char* const sCSS1_P_page_break_inside = "page-break-inside"; -const char* const sCSS1_P_size = "size"; -const char* const sCSS1_P_widows = "widows"; -const char* const sCSS1_P_visibility = "visibility"; -const char* const sCSS1_P_orphans = "orphans"; -//const char* const sCSS1_P_marks = "marks"; - -const char* const sCSS1_PV_always = "always"; -const char* const sCSS1_PV_avoid = "avoid"; - -const char* const sCSS1_PV_portrait = "portrait"; -const char* const sCSS1_PV_landscape = "landscape"; - -//const char* const sCSS1_PV_crop = "crop"; -//const char* const sCSS1_PV_cross = "cross"; - -const char* const sCSS1_P_so_language = "so-language"; - -const char* const sCSS1_P_direction = "direction"; -const char* const sCSS1_PV_ltr = "ltr"; -const char* const sCSS1_PV_rtl = "rtl"; -const char* const sCSS1_PV_inherit = "inherit"; - -const char* const sCSS1_P_display = "display"; - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/css1kywd.hxx b/sw/source/filter/html/css1kywd.hxx index 443af7e1ae91..42ad28da9259 100644 --- a/sw/source/filter/html/css1kywd.hxx +++ b/sw/source/filter/html/css1kywd.hxx @@ -20,196 +20,204 @@ #ifndef INCLUDED_SW_SOURCE_FILTER_HTML_CSS1KYWD_HXX #define INCLUDED_SW_SOURCE_FILTER_HTML_CSS1KYWD_HXX -extern const char* const sCSS_mimetype; +#include <sal/config.h> -extern const char* const sCSS1_page; +#include <string_view> -extern const char* const sCSS1_link; -extern const char* const sCSS1_visited; -extern const char* const sCSS1_first_letter; +constexpr inline std::string_view sCSS_mimetype = "text/css"; -extern const char* const sCSS1_left; -extern const char* const sCSS1_right; -extern const char* const sCSS1_first; +constexpr inline std::string_view sCSS1_page = "page"; +//constexpr inline std::string_view sCSS1_media = "media"; -extern const char* const sCSS1_url; +constexpr inline std::string_view sCSS1_link = "link"; +constexpr inline std::string_view sCSS1_visited = "visited"; +constexpr inline std::string_view sCSS1_first_letter = "first-letter"; -extern const char* const sCSS1_UNIT_pt; -extern const char* const sCSS1_UNIT_mm; -extern const char* const sCSS1_UNIT_cm; -extern const char* const sCSS1_UNIT_pc; -extern const char* const sCSS1_UNIT_inch; -extern const char* const sCSS1_UNIT_px; +constexpr inline std::string_view sCSS1_left = "left"; +constexpr inline std::string_view sCSS1_right = "right"; +constexpr inline std::string_view sCSS1_first = "first"; + +constexpr inline std::string_view sCSS1_url = "url"; + +constexpr inline std::string_view sCSS1_UNIT_pt = "pt"; +constexpr inline std::string_view sCSS1_UNIT_mm = "mm"; +constexpr inline std::string_view sCSS1_UNIT_cm = "cm"; +constexpr inline std::string_view sCSS1_UNIT_pc = "pc"; +constexpr inline std::string_view sCSS1_UNIT_inch = "in"; +constexpr inline std::string_view sCSS1_UNIT_px = "px"; // Strings for font properties -extern const char* const sCSS1_P_font_family; +constexpr inline std::string_view sCSS1_P_font_family = "font-family"; -extern const char* const sCSS1_PV_serif; -extern const char* const sCSS1_PV_sans_serif; -extern const char* const sCSS1_PV_cursive; -extern const char* const sCSS1_PV_fantasy; -extern const char* const sCSS1_PV_monospace; +constexpr inline std::string_view sCSS1_PV_serif = "serif"; +constexpr inline std::string_view sCSS1_PV_sans_serif = "sans-serif"; +constexpr inline std::string_view sCSS1_PV_cursive = "cursive"; +constexpr inline std::string_view sCSS1_PV_fantasy = "fantasy"; +constexpr inline std::string_view sCSS1_PV_monospace = "monospace"; -extern const char* const sCSS1_P_font_style; +constexpr inline std::string_view sCSS1_P_font_style = "font-style"; -extern const char* const sCSS1_PV_normal; -extern const char* const sCSS1_PV_italic; -extern const char* const sCSS1_PV_oblique; +constexpr inline std::string_view sCSS1_PV_normal = "normal"; +constexpr inline std::string_view sCSS1_PV_italic = "italic"; +constexpr inline std::string_view sCSS1_PV_oblique = "oblique"; -extern const char* const sCSS1_P_font_variant; +constexpr inline std::string_view sCSS1_P_font_variant = "font-variant"; -//extern const char* const sCSS1_PV_normal; -extern const char* const sCSS1_PV_small_caps; +//constexpr inline std::string_view sCSS1_PV_normal = "normal"; +constexpr inline std::string_view sCSS1_PV_small_caps = "small-caps"; -extern const char* const sCSS1_P_text_transform; +constexpr inline std::string_view sCSS1_P_text_transform = "text-transform"; -extern const char* const sCSS1_PV_capitalize; -extern const char* const sCSS1_PV_uppercase; -extern const char* const sCSS1_PV_lowercase; +constexpr inline std::string_view sCSS1_PV_capitalize = "capitalize"; +constexpr inline std::string_view sCSS1_PV_uppercase = "uppercase"; +constexpr inline std::string_view sCSS1_PV_lowercase = "lowercase"; -extern const char* const sCSS1_P_font_weight; +constexpr inline std::string_view sCSS1_P_font_weight = "font-weight"; -extern const char* const sCSS1_PV_extra_light; -extern const char* const sCSS1_PV_light; -extern const char* const sCSS1_PV_demi_light; -//extern const char* const sCSS1_PV_medium; -extern const char* const sCSS1_PV_demi_bold; -extern const char* const sCSS1_PV_bold; -extern const char* const sCSS1_PV_extra_bold; +constexpr inline std::string_view sCSS1_PV_extra_light = "extra-light"; +constexpr inline std::string_view sCSS1_PV_light = "light"; +constexpr inline std::string_view sCSS1_PV_demi_light = "demi-light"; +//constexpr inline std::string_view sCSS1_PV_medium = "medium"; +constexpr inline std::string_view sCSS1_PV_demi_bold = "demi-bold"; +constexpr inline std::string_view sCSS1_PV_bold = "bold"; +constexpr inline std::string_view sCSS1_PV_extra_bold = "extra-bold"; -extern const char* const sCSS1_P_font_size; +constexpr inline std::string_view sCSS1_P_font_size = "font-size"; -extern const char* const sCSS1_P_font; +constexpr inline std::string_view sCSS1_P_font = "font"; // Strings for color and background properties -extern const char* const sCSS1_P_color; +constexpr inline std::string_view sCSS1_P_color = "color"; -extern const char* const sCSS1_P_background; -extern const char* const sCSS1_P_background_color; +constexpr inline std::string_view sCSS1_P_background = "background"; +constexpr inline std::string_view sCSS1_P_background_color = "background-color"; -extern const char* const sCSS1_PV_transparent; +constexpr inline std::string_view sCSS1_PV_transparent = "transparent"; -extern const char* const sCSS1_PV_repeat; -extern const char* const sCSS1_PV_no_repeat; +constexpr inline std::string_view sCSS1_PV_repeat = "repeat"; +constexpr inline std::string_view sCSS1_PV_no_repeat = "no-repeat"; -extern const char* const sCSS1_PV_top; -extern const char* const sCSS1_PV_middle; -extern const char* const sCSS1_PV_bottom; +constexpr inline std::string_view sCSS1_PV_top = "top"; +constexpr inline std::string_view sCSS1_PV_middle = "middle"; +constexpr inline std::string_view sCSS1_PV_bottom = "bottom"; -extern const char* const sCSS1_PV_scroll; +constexpr inline std::string_view sCSS1_PV_scroll = "scroll"; // Strings for text properties -extern const char* const sCSS1_P_letter_spacing; +constexpr inline std::string_view sCSS1_P_letter_spacing = "letter-spacing"; -extern const char* const sCSS1_P_text_decoration; +constexpr inline std::string_view sCSS1_P_text_decoration = "text-decoration"; -extern const char* const sCSS1_PV_none; -extern const char* const sCSS1_PV_underline; -extern const char* const sCSS1_PV_overline; -extern const char* const sCSS1_PV_line_through; -extern const char* const sCSS1_PV_blink; +constexpr inline std::string_view sCSS1_PV_none = "none"; +constexpr inline std::string_view sCSS1_PV_underline = "underline"; +constexpr inline std::string_view sCSS1_PV_overline = "overline"; +constexpr inline std::string_view sCSS1_PV_line_through = "line-through"; +constexpr inline std::string_view sCSS1_PV_blink = "blink"; -extern const char* const sCSS1_P_text_align; +constexpr inline std::string_view sCSS1_P_text_align = "text-align"; -extern const char* const sCSS1_PV_left; -extern const char* const sCSS1_PV_center; -extern const char* const sCSS1_PV_right; -extern const char* const sCSS1_PV_justify; +constexpr inline std::string_view sCSS1_PV_left = "left"; +constexpr inline std::string_view sCSS1_PV_center = "center"; +constexpr inline std::string_view sCSS1_PV_right = "right"; +constexpr inline std::string_view sCSS1_PV_justify = "justify"; -extern const char* const sCSS1_P_text_indent; +constexpr inline std::string_view sCSS1_P_text_indent = "text-indent"; -extern const char* const sCSS1_P_line_height; +constexpr inline std::string_view sCSS1_P_line_height = "line-height"; -extern const char* const sCSS1_P_list_style_type; +constexpr inline std::string_view sCSS1_P_list_style_type = "list-style-type"; // Strings for box properties -extern const char* const sCSS1_P_margin_left; -extern const char* const sCSS1_P_margin_right; -extern const char* const sCSS1_P_margin_top; -extern const char* const sCSS1_P_margin_bottom; -extern const char* const sCSS1_P_margin; - -extern const char* const sCSS1_P_padding_top; -extern const char* const sCSS1_P_padding_bottom; -extern const char* const sCSS1_P_padding_left; -extern const char* const sCSS1_P_padding_right; -extern const char* const sCSS1_P_padding; - -extern const char* const sCSS1_PV_auto; - -extern const char* const sCSS1_P_border_left_width; -extern const char* const sCSS1_P_border_right_width; -extern const char* const sCSS1_P_border_top_width; -extern const char* const sCSS1_P_border_bottom_width; -extern const char* const sCSS1_P_border_width; -extern const char* const sCSS1_P_border_color; -extern const char* const sCSS1_P_border_style; -extern const char* const sCSS1_P_border_left; -extern const char* const sCSS1_P_border_right; -extern const char* const sCSS1_P_border_top; -extern const char* const sCSS1_P_border_bottom; -extern const char* const sCSS1_P_border; - -//extern const char* const sCSS1_PV_none; -extern const char* const sCSS1_PV_dotted; -extern const char* const sCSS1_PV_dashed; -extern const char* const sCSS1_PV_solid; -extern const char* const sCSS1_PV_double; -extern const char* const sCSS1_PV_groove; -extern const char* const sCSS1_PV_ridge; -extern const char* const sCSS1_PV_inset; -extern const char* const sCSS1_PV_outset; - -extern const char* const sCSS1_P_width; -extern const char* const sCSS1_P_max_width; - -extern const char* const sCSS1_P_height; - -extern const char* const sCSS1_P_float; - -extern const char* const sCSS1_P_column_count; +constexpr inline std::string_view sCSS1_P_margin_left = "margin-left"; +constexpr inline std::string_view sCSS1_P_margin_right = "margin-right"; +constexpr inline std::string_view sCSS1_P_margin_top = "margin-top"; +constexpr inline std::string_view sCSS1_P_margin_bottom = "margin-bottom"; +constexpr inline std::string_view sCSS1_P_margin = "margin"; + +constexpr inline std::string_view sCSS1_P_padding_top = "padding-top"; +constexpr inline std::string_view sCSS1_P_padding_bottom = "padding-bottom"; +constexpr inline std::string_view sCSS1_P_padding_left = "padding-left"; +constexpr inline std::string_view sCSS1_P_padding_right = "padding-right"; +constexpr inline std::string_view sCSS1_P_padding = "padding"; + +constexpr inline std::string_view sCSS1_PV_auto = "auto"; + +constexpr inline std::string_view sCSS1_P_border_left_width = "border-left-width"; +constexpr inline std::string_view sCSS1_P_border_right_width = "border-right-width"; +constexpr inline std::string_view sCSS1_P_border_top_width = "border-top-width"; +constexpr inline std::string_view sCSS1_P_border_bottom_width = "border-bottom-width"; +constexpr inline std::string_view sCSS1_P_border_width = "border-width"; +constexpr inline std::string_view sCSS1_P_border_color = "border-color"; +constexpr inline std::string_view sCSS1_P_border_style = "border-style"; +constexpr inline std::string_view sCSS1_P_border_left = "border-left"; +constexpr inline std::string_view sCSS1_P_border_right = "border-right"; +constexpr inline std::string_view sCSS1_P_border_top = "border-top"; +constexpr inline std::string_view sCSS1_P_border_bottom = "border-bottom"; +constexpr inline std::string_view sCSS1_P_border = "border"; + +//constexpr inline std::string_view sCSS1_PV_none = "none"; +constexpr inline std::string_view sCSS1_PV_dotted = "dotted"; +constexpr inline std::string_view sCSS1_PV_dashed = "dashed"; +constexpr inline std::string_view sCSS1_PV_solid = "solid"; +constexpr inline std::string_view sCSS1_PV_double = "double"; +constexpr inline std::string_view sCSS1_PV_groove = "groove"; +constexpr inline std::string_view sCSS1_PV_ridge = "ridge"; +constexpr inline std::string_view sCSS1_PV_inset = "inset"; +constexpr inline std::string_view sCSS1_PV_outset = "outset"; + +constexpr inline std::string_view sCSS1_P_width = "width"; +constexpr inline std::string_view sCSS1_P_max_width = "max-width"; + +constexpr inline std::string_view sCSS1_P_height = "height"; + +constexpr inline std::string_view sCSS1_P_float = "float"; + +constexpr inline std::string_view sCSS1_P_column_count = "column-count"; +constexpr inline std::string_view sCSS1_P_dir = "dir"; // Strings for positioning -extern const char* const sCSS1_P_position; +constexpr inline std::string_view sCSS1_P_position = "position"; -extern const char* const sCSS1_PV_absolute; +constexpr inline std::string_view sCSS1_PV_absolute = "absolute"; -extern const char* const sCSS1_P_left; +constexpr inline std::string_view sCSS1_P_left = "left"; -extern const char* const sCSS1_P_top; +constexpr inline std::string_view sCSS1_P_top = "top"; // Strings for printing extensions -extern const char* const sCSS1_P_page_break_before; -extern const char* const sCSS1_P_page_break_after; -extern const char* const sCSS1_P_page_break_inside; -extern const char* const sCSS1_P_size; -extern const char* const sCSS1_P_widows; -extern const char* const sCSS1_P_visibility; -extern const char* const sCSS1_P_orphans; -//extern const char* const sCSS1_P_marks; +constexpr inline std::string_view sCSS1_P_page_break_before = "page-break-before"; +constexpr inline std::string_view sCSS1_P_page_break_after = "page-break-after"; +constexpr inline std::string_view sCSS1_P_page_break_inside = "page-break-inside"; +constexpr inline std::string_view sCSS1_P_size = "size"; +constexpr inline std::string_view sCSS1_P_widows = "widows"; +constexpr inline std::string_view sCSS1_P_visibility = "visibility"; +constexpr inline std::string_view sCSS1_P_orphans = "orphans"; +//constexpr inline std::string_view sCSS1_P_marks = "marks"; + +constexpr inline std::string_view sCSS1_PV_always = "always"; +constexpr inline std::string_view sCSS1_PV_avoid = "avoid"; -extern const char* const sCSS1_PV_always; -extern const char* const sCSS1_PV_avoid; +constexpr inline std::string_view sCSS1_PV_portrait = "portrait"; +constexpr inline std::string_view sCSS1_PV_landscape = "landscape"; -extern const char* const sCSS1_PV_portrait; -extern const char* const sCSS1_PV_landscape; +//constexpr inline std::string_view sCSS1_PV_crop = "crop"; +//constexpr inline std::string_view sCSS1_PV_cross = "cross"; -//extern const char* const sCSS1_PV_crop; -//extern const char* const sCSS1_PV_cross; +constexpr inline std::string_view sCSS1_P_so_language = "so-language"; +constexpr inline std::string_view sCSS1_P_direction = "direction"; +constexpr inline std::string_view sCSS1_PV_ltr = "ltr"; +constexpr inline std::string_view sCSS1_PV_rtl = "rtl"; +constexpr inline std::string_view sCSS1_PV_inherit = "inherit"; -extern const char* const sCSS1_P_so_language; -extern const char* const sCSS1_P_direction; -extern const char* const sCSS1_PV_ltr; -extern const char* const sCSS1_PV_rtl; -extern const char* const sCSS1_PV_inherit; +constexpr inline std::string_view sCSS1_P_display = "display"; -extern const char* const sCSS1_P_display; +constexpr inline std::string_view sCSS1_white_space = "white-space"; #endif diff --git a/sw/source/filter/html/htmlatr.cxx b/sw/source/filter/html/htmlatr.cxx index cdbfae284ff8..f298f93dc5b2 100644 --- a/sw/source/filter/html/htmlatr.cxx +++ b/sw/source/filter/html/htmlatr.cxx @@ -76,6 +76,7 @@ #include <deque> #include <svtools/HtmlWriter.hxx> +#include <o3tl/string_view.hxx> #include <memory> #include <algorithm> @@ -90,9 +91,9 @@ HTMLOutEvent const aAnchorEventTable[] = { nullptr, nullptr, SvMacroItemId::NONE } }; -static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt ); +static SwHTMLWriter& OutHTML_SvxAdjust( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); -sal_uInt16 SwHTMLWriter::GetDefListLvl( const OUString& rNm, sal_uInt16 nPoolId ) +sal_uInt16 SwHTMLWriter::GetDefListLvl( std::u16string_view rNm, sal_uInt16 nPoolId ) { if( nPoolId == RES_POOLCOLL_HTML_DD ) { @@ -104,14 +105,14 @@ sal_uInt16 SwHTMLWriter::GetDefListLvl( const OUString& rNm, sal_uInt16 nPoolId } OUString sDTDD = OOO_STRING_SVTOOLS_HTML_dt " "; - if( rNm.startsWith(sDTDD) ) + if( o3tl::starts_with(rNm, sDTDD) ) // DefinitionList - term - return static_cast<sal_uInt16>(rNm.copy( sDTDD.getLength() ).toInt32()) | HTML_DLCOLL_DT; + return o3tl::narrowing<sal_uInt16>(o3tl::toInt32(rNm.substr( sDTDD.getLength() ))) | HTML_DLCOLL_DT; sDTDD = OOO_STRING_SVTOOLS_HTML_dd " "; - if( rNm.startsWith(sDTDD) ) + if( o3tl::starts_with(rNm, sDTDD) ) // DefinitionList - definition - return static_cast<sal_uInt16>(rNm.copy( sDTDD.getLength() ).toInt32()) | HTML_DLCOLL_DD; + return o3tl::narrowing<sal_uInt16>(o3tl::toInt32(rNm.substr( sDTDD.getLength() ))) | HTML_DLCOLL_DD; return 0; } @@ -132,11 +133,12 @@ void SwHTMLWriter::OutAndSetDefList( sal_uInt16 nNewLvl ) // write according to the level difference for( sal_uInt16 i=m_nDefListLvl; i<nNewLvl; i++ ) { - if( m_bLFPossible ) + if (IsLFPossible()) OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_deflist ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_deflist) ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_dd) ); IncIndentLevel(); - m_bLFPossible = true; + SetLFPossible(true); } } else if( m_nDefListLvl > nNewLvl ) @@ -144,10 +146,11 @@ void SwHTMLWriter::OutAndSetDefList( sal_uInt16 nNewLvl ) for( sal_uInt16 i=nNewLvl ; i < m_nDefListLvl; i++ ) { DecIndentLevel(); - if( m_bLFPossible ) + if (IsLFPossible()) OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_deflist, false ); - m_bLFPossible = true; + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_dd), false ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_deflist), false ); + SetLFPossible(true); } } @@ -158,8 +161,8 @@ void SwHTMLWriter::ChangeParaToken( HtmlTokenId nNew ) { if( nNew != m_nLastParaToken && HtmlTokenId::PREFORMTXT_ON == m_nLastParaToken ) { - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_preformtxt, false ); - m_bLFPossible = true; + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_preformtxt), false ); + SetLFPossible(true); } m_nLastParaToken = nNew; } @@ -201,7 +204,7 @@ namespace { struct SwHTMLTextCollOutputInfo { OString aToken; // End token to be output - std::unique_ptr<SfxItemSet> pItemSet; // hard attribute + std::optional<SfxItemSet> moItemSet; // hard attribute bool bInNumberBulletList; // in an enumerated list; bool bParaPossible; // a </P> may be output additionally @@ -291,22 +294,22 @@ SwHTMLFormatInfo::SwHTMLFormatInfo( const SwFormat *pF, SwDoc *pDoc, SwDoc *pTem if( pReferenceFormat || nDeep==0 ) { - pItemSet.reset( new SfxItemSet( *pFormat->GetAttrSet().GetPool(), - pFormat->GetAttrSet().GetRanges() ) ); + moItemSet.emplace( *pFormat->GetAttrSet().GetPool(), + pFormat->GetAttrSet().GetRanges() ); // if the differences to a different style are supposed to be // written, hard attribute is necessary. This is always true // for styles that are not derived from HTML-tag styles. - pItemSet->Set( pFormat->GetAttrSet() ); + moItemSet->Set( pFormat->GetAttrSet() ); if( pReferenceFormat ) - SwHTMLWriter::SubtractItemSet( *pItemSet, pReferenceFormat->GetAttrSet(), true ); + SwHTMLWriter::SubtractItemSet( *moItemSet, pReferenceFormat->GetAttrSet(), true ); // delete ItemSet that is empty straight away. This will save work // later on - if( !pItemSet->Count() ) + if( !moItemSet->Count() ) { - pItemSet.reset(); + moItemSet.reset(); } } @@ -355,10 +358,10 @@ SwHTMLFormatInfo::SwHTMLFormatInfo( const SwFormat *pF, SwDoc *pDoc, SwDoc *pTem const SfxPoolItem& rSet = pFormat->GetFormatAttr( aWhichIds[nSet][i] ); if( rSet != rRef ) { - if( !pItemSet ) - pItemSet.reset( new SfxItemSet( *pFormat->GetAttrSet().GetPool(), - pFormat->GetAttrSet().GetRanges() ) ); - pItemSet->Put( rSet ); + if( !moItemSet ) + moItemSet.emplace( *pFormat->GetAttrSet().GetPool(), + pFormat->GetAttrSet().GetRanges() ); + moItemSet->Put( rSet ); } } } @@ -366,11 +369,15 @@ SwHTMLFormatInfo::SwHTMLFormatInfo( const SwFormat *pF, SwDoc *pDoc, SwDoc *pTem // remember all the different default spacings from the style or // the comparison style. - const SvxLRSpaceItem &rLRSpace = - (pReferenceFormat ? pReferenceFormat : pFormat)->GetLRSpace(); - nLeftMargin = rLRSpace.GetTextLeft(); - nRightMargin = rLRSpace.GetRight(); - nFirstLineIndent = rLRSpace.GetTextFirstLineOffset(); + SvxFirstLineIndentItem const& rFirstLine( + (pReferenceFormat ? pReferenceFormat : pFormat)->GetFirstLineIndent()); + SvxTextLeftMarginItem const& rTextLeftMargin( + (pReferenceFormat ? pReferenceFormat : pFormat)->GetTextLeftMargin()); + SvxRightMarginItem const& rRightMargin( + (pReferenceFormat ? pReferenceFormat : pFormat)->GetRightMargin()); + nLeftMargin = rTextLeftMargin.GetTextLeft(); + nRightMargin = rRightMargin.GetRight(); + nFirstLineIndent = rFirstLine.GetTextFirstLineOffset(); const SvxULSpaceItem &rULSpace = (pReferenceFormat ? pReferenceFormat : pFormat)->GetULSpace(); @@ -378,34 +385,32 @@ SwHTMLFormatInfo::SwHTMLFormatInfo( const SwFormat *pF, SwDoc *pDoc, SwDoc *pTem nBottomMargin = rULSpace.GetLower(); // export language if it differs from the default language - sal_uInt16 nWhichId = + TypedWhichId<SvxLanguageItem> nWhichId = SwHTMLWriter::GetLangWhichIdFromScript( nCSS1Script ); - const SvxLanguageItem& rLang = - static_cast<const SvxLanguageItem&>(pFormat->GetFormatAttr( nWhichId )); + const SvxLanguageItem& rLang = pFormat->GetFormatAttr( nWhichId ); LanguageType eLang = rLang.GetLanguage(); if( eLang != eDfltLang ) { - if( !pItemSet ) - pItemSet.reset( new SfxItemSet( *pFormat->GetAttrSet().GetPool(), - pFormat->GetAttrSet().GetRanges() ) ); - pItemSet->Put( rLang ); + if( !moItemSet ) + moItemSet.emplace( *pFormat->GetAttrSet().GetPool(), + pFormat->GetAttrSet().GetRanges() ); + moItemSet->Put( rLang ); } - static const sal_uInt16 aWhichIds[3] = + static const TypedWhichId<SvxLanguageItem> aWhichIds[3] = { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE }; - for(sal_uInt16 i : aWhichIds) + for(const TypedWhichId<SvxLanguageItem>& i : aWhichIds) { if( i != nWhichId ) { - const SvxLanguageItem& rTmpLang = - static_cast<const SvxLanguageItem&>(pFormat->GetFormatAttr(i)); + const SvxLanguageItem& rTmpLang = pFormat->GetFormatAttr(i); if( rTmpLang.GetLanguage() != eLang ) { - if( !pItemSet ) - pItemSet.reset( new SfxItemSet( *pFormat->GetAttrSet().GetPool(), - pFormat->GetAttrSet().GetRanges() ) ); - pItemSet->Put( rTmpLang ); + if( !moItemSet ) + moItemSet.emplace( *pFormat->GetAttrSet().GetPool(), + pFormat->GetAttrSet().GetRanges() ); + moItemSet->Put( rTmpLang ); } } } @@ -416,15 +421,13 @@ SwHTMLFormatInfo::~SwHTMLFormatInfo() { } -static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, +static void OutHTML_SwFormat( SwHTMLWriter& rWrt, const SwFormat& rFormat, const SfxItemSet *pNodeItemSet, SwHTMLTextCollOutputInfo& rInfo ) { OSL_ENSURE( RES_CONDTXTFMTCOLL==rFormat.Which() || RES_TXTFMTCOLL==rFormat.Which(), "not a paragraph style" ); - SwHTMLWriter & rHWrt = static_cast<SwHTMLWriter&>(rWrt); - // First, some flags sal_uInt16 nNewDefListLvl = 0; sal_uInt16 nNumStart = USHRT_MAX; @@ -436,23 +439,23 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, rInfo.bParaPossible = false; // a <P> may be additionally output bool bNoEndTag = false; // don't output an end tag - rHWrt.m_bNoAlign = false; // no ALIGN=... possible + rWrt.m_bNoAlign = false; // no ALIGN=... possible - if (rHWrt.mbXHTML) + if (rWrt.mbXHTML) { - rHWrt.m_bNoAlign = true; + rWrt.m_bNoAlign = true; } sal_uInt8 nBulletGrfLvl = 255; // The bullet graphic we want to output // Are we in a bulleted or numbered list? - const SwTextNode* pTextNd = rWrt.m_pCurrentPam->GetNode().GetTextNode(); + const SwTextNode* pTextNd = rWrt.m_pCurrentPam->GetPointNode().GetTextNode(); SwHTMLNumRuleInfo aNumInfo; - if( rHWrt.GetNextNumInfo() ) + if( rWrt.GetNextNumInfo() ) { - aNumInfo = *rHWrt.GetNextNumInfo(); - rHWrt.ClearNextNumInfo(); + aNumInfo = *rWrt.GetNextNumInfo(); + rWrt.ClearNextNumInfo(); } else { @@ -485,7 +488,7 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, { nNumStart = static_cast< sal_uInt16 >(pTextNd->GetActualListStartValue()); } - OSL_ENSURE( rHWrt.m_nLastParaToken == HtmlTokenId::NONE, + OSL_ENSURE( rWrt.m_nLastParaToken == HtmlTokenId::NONE, "<PRE> was not closed before <LI>." ); } } @@ -493,18 +496,18 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, // Now, we're getting the token and, if necessary, the class std::unique_ptr<SwHTMLFormatInfo> pTmpInfo(new SwHTMLFormatInfo(&rFormat)); SwHTMLFormatInfo *pFormatInfo; - SwHTMLFormatInfos::iterator it = rHWrt.m_TextCollInfos.find( pTmpInfo ); - if (it != rHWrt.m_TextCollInfos.end()) + SwHTMLFormatInfos::iterator it = rWrt.m_TextCollInfos.find( pTmpInfo ); + if (it != rWrt.m_TextCollInfos.end()) { pFormatInfo = it->get(); } else { - pFormatInfo = new SwHTMLFormatInfo( &rFormat, rWrt.m_pDoc, rHWrt.m_xTemplate.get(), - rHWrt.m_bCfgOutStyles, rHWrt.m_eLang, - rHWrt.m_nCSS1Script ); - rHWrt.m_TextCollInfos.insert(std::unique_ptr<SwHTMLFormatInfo>(pFormatInfo)); - if( rHWrt.m_aScriptParaStyles.count( rFormat.GetName() ) ) + pFormatInfo = new SwHTMLFormatInfo( &rFormat, rWrt.m_pDoc, rWrt.m_xTemplate.get(), + rWrt.m_bCfgOutStyles, rWrt.m_eLang, + rWrt.m_nCSS1Script ); + rWrt.m_TextCollInfos.insert(std::unique_ptr<SwHTMLFormatInfo>(pFormatInfo)); + if( rWrt.m_aScriptParaStyles.count( rFormat.GetName() ) ) pFormatInfo->bScriptDependent = true; } @@ -520,12 +523,12 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, if (rInfo.aToken == OOO_STRING_SVTOOLS_HTML_address) { rInfo.bParaPossible = true; - rHWrt.m_bNoAlign = true; + rWrt.m_bNoAlign = true; } else if (rInfo.aToken == OOO_STRING_SVTOOLS_HTML_blockquote) { rInfo.bParaPossible = true; - rHWrt.m_bNoAlign = true; + rWrt.m_bNoAlign = true; } else if (rInfo.aToken == OOO_STRING_SVTOOLS_HTML_parabreak) { @@ -533,14 +536,14 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, } else if (rInfo.aToken == OOO_STRING_SVTOOLS_HTML_preformtxt) { - if (HtmlTokenId::PREFORMTXT_ON == rHWrt.m_nLastParaToken) + if (HtmlTokenId::PREFORMTXT_ON == rWrt.m_nLastParaToken) { bOutNewLine = true; } else { nToken = HtmlTokenId::PREFORMTXT_ON; - rHWrt.m_bNoAlign = true; + rWrt.m_bNoAlign = true; bNoEndTag = true; } } @@ -548,7 +551,7 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, { bDT = rInfo.aToken == OOO_STRING_SVTOOLS_HTML_dt; rInfo.bParaPossible = !bDT; - rHWrt.m_bNoAlign = true; + rWrt.m_bNoAlign = true; bForceDL = true; } } @@ -557,24 +560,24 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, // all styles that do not correspond to an HTML tag, or that are // not derived from it, are exported as <P> - rInfo.aToken = OOO_STRING_SVTOOLS_HTML_parabreak; + rInfo.aToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr; bPara = true; } // If necessary, take the hard attribute from the style - if( pFormatInfo->pItemSet ) + if( pFormatInfo->moItemSet ) { - OSL_ENSURE(!rInfo.pItemSet, "Where does this ItemSet come from?"); - rInfo.pItemSet.reset(new SfxItemSet( *pFormatInfo->pItemSet )); + OSL_ENSURE(!rInfo.moItemSet, "Where does this ItemSet come from?"); + rInfo.moItemSet.emplace( *pFormatInfo->moItemSet ); } // additionally, add the hard attribute from the paragraph if( pNodeItemSet ) { - if (rInfo.pItemSet) - rInfo.pItemSet->Put( *pNodeItemSet ); + if (rInfo.moItemSet) + rInfo.moItemSet->Put( *pNodeItemSet ); else - rInfo.pItemSet.reset(new SfxItemSet( *pNodeItemSet )); + rInfo.moItemSet.emplace( *pNodeItemSet ); } // we will need the lower spacing of the paragraph later on @@ -582,27 +585,27 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, pNodeItemSet ? pNodeItemSet->Get(RES_UL_SPACE) : rFormat.GetULSpace(); - if( (rHWrt.m_bOutHeader && - rWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() == - rWrt.m_pCurrentPam->GetMark()->nNode.GetIndex()) || - rHWrt.m_bOutFooter ) + if( (rWrt.m_bOutHeader && + rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex() == + rWrt.m_pCurrentPam->GetMark()->GetNodeIndex()) || + rWrt.m_bOutFooter ) { - if( rHWrt.m_bCfgOutStyles ) + if( rWrt.m_bCfgOutStyles ) { SvxULSpaceItem aULSpaceItem( rULSpace ); - if( rHWrt.m_bOutHeader ) - aULSpaceItem.SetLower( rHWrt.m_nHeaderFooterSpace ); + if( rWrt.m_bOutHeader ) + aULSpaceItem.SetLower( rWrt.m_nHeaderFooterSpace ); else - aULSpaceItem.SetUpper( rHWrt.m_nHeaderFooterSpace ); + aULSpaceItem.SetUpper( rWrt.m_nHeaderFooterSpace ); - if (!rInfo.pItemSet) + if (!rInfo.moItemSet) { - rInfo.pItemSet.reset(new SfxItemSet(*rFormat.GetAttrSet().GetPool(), svl::Items<RES_UL_SPACE, RES_UL_SPACE>{})); + rInfo.moItemSet.emplace(*rFormat.GetAttrSet().GetPool(), svl::Items<RES_UL_SPACE, RES_UL_SPACE>); } - rInfo.pItemSet->Put( aULSpaceItem ); + rInfo.moItemSet->Put( aULSpaceItem ); } - rHWrt.m_bOutHeader = false; - rHWrt.m_bOutFooter = false; + rWrt.m_bOutHeader = false; + rWrt.m_bOutFooter = false; } if( bOutNewLine ) @@ -610,45 +613,43 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, // output a line break (without indentation) at the beginning of the // paragraph, only rInfo.aToken.clear(); // don't output an end tag - rWrt.Strm().WriteCharPtr( SAL_NEWLINE_STRING ); + rWrt.Strm().WriteOString( SAL_NEWLINE_STRING ); return; } // should an ALIGN=... be written? - const SfxPoolItem* pAdjItem = nullptr; - const SfxPoolItem* pItem; + const SvxAdjustItem* pAdjItem = nullptr; - if( rInfo.pItemSet && - SfxItemState::SET == rInfo.pItemSet->GetItemState( RES_PARATR_ADJUST, - false, &pItem ) ) - { - pAdjItem = pItem; - } + if( rInfo.moItemSet ) + pAdjItem = rInfo.moItemSet->GetItemIfSet( RES_PARATR_ADJUST, false ); // Consider the lower spacing of the paragraph? (never in the last // paragraph of tables) - bool bUseParSpace = !rHWrt.m_bOutTable || - (rWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() != - rWrt.m_pCurrentPam->GetMark()->nNode.GetIndex()); + bool bUseParSpace = !rWrt.m_bOutTable || + (rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex() != + rWrt.m_pCurrentPam->GetMark()->GetNodeIndex()); // If styles are exported, indented paragraphs become definition lists - const SvxLRSpaceItem& rLRSpace = - pNodeItemSet ? pNodeItemSet->Get(RES_LR_SPACE) - : rFormat.GetLRSpace(); - if( (!rHWrt.m_bCfgOutStyles || bForceDL) && !rInfo.bInNumberBulletList ) + SvxFirstLineIndentItem const& rFirstLine( + pNodeItemSet ? pNodeItemSet->Get(RES_MARGIN_FIRSTLINE) + : rFormat.GetFirstLineIndent()); + SvxTextLeftMarginItem const& rTextLeftMargin( + pNodeItemSet ? pNodeItemSet->Get(RES_MARGIN_TEXTLEFT) + : rFormat.GetTextLeftMargin()); + if( (!rWrt.m_bCfgOutStyles || bForceDL) && !rInfo.bInNumberBulletList ) { sal_Int32 nLeftMargin; if( bForceDL ) - nLeftMargin = rLRSpace.GetTextLeft(); + nLeftMargin = rTextLeftMargin.GetTextLeft(); else - nLeftMargin = rLRSpace.GetTextLeft() > pFormatInfo->nLeftMargin - ? rLRSpace.GetTextLeft() - pFormatInfo->nLeftMargin + nLeftMargin = rTextLeftMargin.GetTextLeft() > pFormatInfo->nLeftMargin + ? rTextLeftMargin.GetTextLeft() - pFormatInfo->nLeftMargin : 0; - if( nLeftMargin > 0 && rHWrt.m_nDefListMargin > 0 ) + if( nLeftMargin > 0 && rWrt.m_nDefListMargin > 0 ) { - nNewDefListLvl = static_cast< sal_uInt16 >((nLeftMargin + (rHWrt.m_nDefListMargin/2)) / - rHWrt.m_nDefListMargin); + nNewDefListLvl = static_cast< sal_uInt16 >((nLeftMargin + (rWrt.m_nDefListMargin/2)) / + rWrt.m_nDefListMargin); if( nNewDefListLvl == 0 && bForceDL && !bDT ) nNewDefListLvl = 1; } @@ -661,7 +662,7 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, } bool bIsNextTextNode = - rWrt.m_pDoc->GetNodes()[rWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex()+1] + rWrt.m_pDoc->GetNodes()[rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex()+1] ->IsTextNode(); if( bForceDL && bDT ) @@ -669,32 +670,31 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, // Instead of a DD we must use a DT from the level above this one. nNewDefListLvl++; } - else if( !nNewDefListLvl && !rHWrt.m_bCfgOutStyles && bPara && + else if( !nNewDefListLvl && !rWrt.m_bCfgOutStyles && bPara && rULSpace.GetLower()==0 && - ((bUseParSpace && bIsNextTextNode) || rHWrt.m_nDefListLvl==1) && - (!pAdjItem || SvxAdjust::Left== - static_cast<const SvxAdjustItem *>(pAdjItem)->GetAdjust()) ) + ((bUseParSpace && bIsNextTextNode) || rWrt.m_nDefListLvl==1) && + (!pAdjItem || SvxAdjust::Left==pAdjItem->GetAdjust()) ) { // Export paragraphs without a lower spacing as DT nNewDefListLvl = 1; bDT = true; rInfo.bParaPossible = false; - rHWrt.m_bNoAlign = true; + rWrt.m_bNoAlign = true; } } - if( nNewDefListLvl != rHWrt.m_nDefListLvl ) - rHWrt.OutAndSetDefList( nNewDefListLvl ); + if( nNewDefListLvl != rWrt.m_nDefListLvl ) + rWrt.OutAndSetDefList( nNewDefListLvl ); // if necessary, start a bulleted or numbered list if( rInfo.bInNumberBulletList ) { - OSL_ENSURE( !rHWrt.m_nDefListLvl, "DL cannot be inside OL!" ); - OutHTML_NumberBulletListStart( rHWrt, aNumInfo ); + OSL_ENSURE( !rWrt.m_nDefListLvl, "DL cannot be inside OL!" ); + OutHTML_NumberBulletListStart( rWrt, aNumInfo ); if( bNumbered ) { - if( !rHWrt.m_aBulletGrfs[nBulletGrfLvl].isEmpty() ) + if( !rWrt.m_aBulletGrfs[nBulletGrfLvl].isEmpty() ) bNumbered = false; else nBulletGrfLvl = 255; @@ -703,96 +703,112 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, // Take the defaults of the style, because they don't need to be // exported - rHWrt.m_nDfltLeftMargin = pFormatInfo->nLeftMargin; - rHWrt.m_nDfltRightMargin = pFormatInfo->nRightMargin; - rHWrt.m_nDfltFirstLineIndent = pFormatInfo->nFirstLineIndent; + rWrt.m_nDfltLeftMargin = pFormatInfo->nLeftMargin; + rWrt.m_nDfltRightMargin = pFormatInfo->nRightMargin; + rWrt.m_nDfltFirstLineIndent = pFormatInfo->nFirstLineIndent; if( rInfo.bInNumberBulletList ) { - if( !rHWrt.IsHTMLMode( HTMLMODE_LSPACE_IN_NUMBER_BULLET ) ) - rHWrt.m_nDfltLeftMargin = rLRSpace.GetTextLeft(); + if( !rWrt.IsHTMLMode( HTMLMODE_LSPACE_IN_NUMBER_BULLET ) ) + rWrt.m_nDfltLeftMargin = rTextLeftMargin.GetTextLeft(); // In numbered lists, don't output a first line indent. - rHWrt.m_nFirstLineIndent = rLRSpace.GetTextFirstLineOffset(); + rWrt.m_nFirstLineIndent = rFirstLine.GetTextFirstLineOffset(); } - if( rInfo.bInNumberBulletList && bNumbered && bPara && !rHWrt.m_bCfgOutStyles ) + if( rInfo.bInNumberBulletList && bNumbered && bPara && !rWrt.m_bCfgOutStyles ) { // a single LI doesn't have spacing - rHWrt.m_nDfltTopMargin = 0; - rHWrt.m_nDfltBottomMargin = 0; + rWrt.m_nDfltTopMargin = 0; + rWrt.m_nDfltBottomMargin = 0; } - else if( rHWrt.m_nDefListLvl && bPara ) + else if( rWrt.m_nDefListLvl && bPara ) { // a single DD doesn't have spacing, as well - rHWrt.m_nDfltTopMargin = 0; - rHWrt.m_nDfltBottomMargin = 0; + rWrt.m_nDfltTopMargin = 0; + rWrt.m_nDfltBottomMargin = 0; } else { - rHWrt.m_nDfltTopMargin = pFormatInfo->nTopMargin; + rWrt.m_nDfltTopMargin = pFormatInfo->nTopMargin; // if in the last paragraph of a table the lower paragraph spacing // is changed, Netscape doesn't get it. That's why we don't // export anything here for now, by setting this spacing to the // default value. - if( rHWrt.m_bCfgNetscape4 && !bUseParSpace ) - rHWrt.m_nDfltBottomMargin = rULSpace.GetLower(); + if( rWrt.m_bCfgNetscape4 && !bUseParSpace ) + rWrt.m_nDfltBottomMargin = rULSpace.GetLower(); else - rHWrt.m_nDfltBottomMargin = pFormatInfo->nBottomMargin; + rWrt.m_nDfltBottomMargin = pFormatInfo->nBottomMargin; } - if( rHWrt.m_nDefListLvl ) + if( rWrt.m_nDefListLvl ) { - rHWrt.m_nLeftMargin = - (rHWrt.m_nDefListLvl-1) * rHWrt.m_nDefListMargin; + rWrt.m_nLeftMargin = + (rWrt.m_nDefListLvl-1) * rWrt.m_nDefListMargin; } - if( rHWrt.m_bLFPossible && !rHWrt.m_bFirstLine ) - rHWrt.OutNewLine(); // paragraph tag on a new line + if (rWrt.IsLFPossible() && !rWrt.m_bFirstLine) + rWrt.OutNewLine(); // paragraph tag on a new line rInfo.bOutPara = false; // this is now our new token - rHWrt.ChangeParaToken( nToken ); + rWrt.ChangeParaToken( nToken ); bool bHasParSpace = bUseParSpace && rULSpace.GetLower() > 0; + // XHTML doesn't allow character children for <blockquote>. + bool bXhtmlBlockQuote = rWrt.mbXHTML && rInfo.aToken == OOO_STRING_SVTOOLS_HTML_blockquote; // if necessary, start a new list item - if( rInfo.bInNumberBulletList && bNumbered ) + bool bNumberedForListItem = bNumbered; + if (!bNumberedForListItem) + { + // Open a list also for the leading unnumbered nodes (= list headers in ODF terminology); + // to do that, detect if this unnumbered node is the first in this list + const auto& rPrevListInfo = rWrt.GetNumInfo(); + if (rPrevListInfo.GetNumRule() != aNumInfo.GetNumRule() || aNumInfo.IsRestart(rPrevListInfo) + || rPrevListInfo.GetDepth() < aNumInfo.GetDepth()) + bNumberedForListItem = true; + } + if( rInfo.bInNumberBulletList && bNumberedForListItem ) { - HtmlWriter html(rWrt.Strm(), rHWrt.maNamespace); - html.start(OOO_STRING_SVTOOLS_HTML_li); - if( USHRT_MAX != nNumStart ) - html.attribute(OOO_STRING_SVTOOLS_HTML_O_value, OString::number(nNumStart)); - // Finish the opening element, but don't close it. - html.characters(OString()); + OStringBuffer sOut(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li); + if (!bNumbered) + { + // Handles list headers (<text:list-header> ODF element) + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_style "=\"display: block\""); + } + else if (USHRT_MAX != nNumStart) + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_value "=\"" + OString::number(nNumStart) + + "\""); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), sOut); } - if( rHWrt.m_nDefListLvl > 0 && !bForceDL ) + if( rWrt.m_nDefListLvl > 0 && !bForceDL ) { OString aTag = bDT ? OOO_STRING_SVTOOLS_HTML_dt : OOO_STRING_SVTOOLS_HTML_dd; - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHWrt.GetNamespace() + aTag ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag) ); } if( pAdjItem && - rHWrt.IsHTMLMode( HTMLMODE_NO_CONTROL_CENTERING ) && - rHWrt.HasControls() ) + rWrt.IsHTMLMode( HTMLMODE_NO_CONTROL_CENTERING ) && + rWrt.HasControls() ) { // The align=... attribute does behave strange in netscape // if there are controls in a paragraph, because the control and // all text behind the control does not recognize this attribute. - OString sOut = "<" + rHWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division; + OString sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division; rWrt.Strm().WriteOString( sOut ); - rHWrt.m_bTextAttr = false; - rHWrt.m_bOutOpts = true; + rWrt.m_bTextAttr = false; + rWrt.m_bOutOpts = true; OutHTML_SvxAdjust( rWrt, *pAdjItem ); rWrt.Strm().WriteChar( '>' ); pAdjItem = nullptr; - rHWrt.m_bNoAlign = false; + rWrt.m_bNoAlign = false; rInfo.bOutDiv = true; - rHWrt.IncIndentLevel(); - rHWrt.m_bLFPossible = true; - rHWrt.OutNewLine(); + rWrt.IncIndentLevel(); + rWrt.SetLFPossible(true); + rWrt.OutNewLine(); } // for BLOCKQUOTE, ADDRESS and DD we output another paragraph token, if @@ -800,38 +816,39 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, // - a lower spacing or a paragraph alignment exists // Also, XHTML does not allow character children in this context. OString aToken = rInfo.aToken; - if( (!rHWrt.m_bCfgOutStyles || rHWrt.mbXHTML) && rInfo.bParaPossible && !bPara && - (bHasParSpace || pAdjItem) ) + if( (!rWrt.m_bCfgOutStyles || rWrt.mbXHTML) && rInfo.bParaPossible && !bPara && + (bHasParSpace || bXhtmlBlockQuote || pAdjItem) ) { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHWrt.GetNamespace() + rInfo.aToken ); - aToken = OOO_STRING_SVTOOLS_HTML_parabreak; + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + rInfo.aToken) ); + aToken = OOO_STRING_SVTOOLS_HTML_parabreak ""_ostr; bPara = true; - rHWrt.m_bNoAlign = false; + rWrt.m_bNoAlign = false; } LanguageType eLang; - if (rInfo.pItemSet) - eLang = static_cast<const SvxLanguageItem&>(rInfo.pItemSet->Get(SwHTMLWriter::GetLangWhichIdFromScript(rHWrt.m_nCSS1Script))).GetLanguage(); + if (rInfo.moItemSet) + { + const SvxLanguageItem& rLangItem = rInfo.moItemSet->Get(SwHTMLWriter::GetLangWhichIdFromScript(rWrt.m_nCSS1Script)); + eLang = rLangItem.GetLanguage(); + } else - eLang = rHWrt.m_eLang; + eLang = rWrt.m_eLang; - if( rInfo.pItemSet ) + if( rInfo.moItemSet ) { - static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE }; + static const TypedWhichId<SvxLanguageItem> aWhichIds[3] = { RES_CHRATR_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CTL_LANGUAGE }; - for(sal_uInt16 i : aWhichIds) + for(auto const & i : aWhichIds) { // export language if it differs from the default language only. - const SfxPoolItem *pTmpItem; - if( SfxItemState::SET == rInfo.pItemSet->GetItemState( i, - true, &pTmpItem ) && - static_cast<const SvxLanguageItem *>(pTmpItem)->GetLanguage() == eLang ) - rInfo.pItemSet->ClearItem( i ); + const SvxLanguageItem* pTmpItem = rInfo.moItemSet->GetItemIfSet( i ); + if( pTmpItem && pTmpItem->GetLanguage() == eLang ) + rInfo.moItemSet->ClearItem( i ); } } // and the text direction - SvxFrameDirection nDir = rHWrt.GetHTMLDirection( + SvxFrameDirection nDir = rWrt.GetHTMLDirection( (pNodeItemSet ? pNodeItemSet->Get( RES_FRAMEDIR ) : rFormat.GetFrameDir() ).GetValue() ); @@ -846,49 +863,49 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, // - a user format is exported, or // - a paragraph attribute exists if( !bPara || - (!rInfo.bInNumberBulletList && !rHWrt.m_nDefListLvl) || + (!rInfo.bInNumberBulletList && !rWrt.m_nDefListLvl) || (rInfo.bInNumberBulletList && !bNumbered) || - (!rHWrt.m_bCfgOutStyles && - (bHasParSpace || pAdjItem || - (eLang != LANGUAGE_DONTKNOW && eLang != rHWrt.m_eLang))) || - nDir != rHWrt.m_nDirection || - rHWrt.m_bCfgOutStyles ) + (!rWrt.m_bCfgOutStyles && + (bHasParSpace || bXhtmlBlockQuote || pAdjItem || + (eLang != LANGUAGE_DONTKNOW && eLang != rWrt.m_eLang))) || + nDir != rWrt.m_nDirection || + rWrt.m_bCfgOutStyles ) { // now, options are output - rHWrt.m_bTextAttr = false; - rHWrt.m_bOutOpts = true; + rWrt.m_bTextAttr = false; + rWrt.m_bOutOpts = true; - OString sOut = "<" + rHWrt.GetNamespace() + aToken; + OString sOut = "<" + rWrt.GetNamespace() + aToken; - if( eLang != LANGUAGE_DONTKNOW && eLang != rHWrt.m_eLang ) + if( eLang != LANGUAGE_DONTKNOW && eLang != rWrt.m_eLang ) { rWrt.Strm().WriteOString( sOut ); - sOut = ""; - rHWrt.OutLanguage( eLang ); + sOut = ""_ostr; + rWrt.OutLanguage( eLang ); } - if( nDir != rHWrt.m_nDirection ) + if( nDir != rWrt.m_nDirection ) { if( !sOut.isEmpty() ) { rWrt.Strm().WriteOString( sOut ); - sOut = ""; + sOut = ""_ostr; } - rHWrt.OutDirection( nDir ); + rWrt.OutDirection( nDir ); } - if( rHWrt.m_bCfgOutStyles && + if( rWrt.m_bCfgOutStyles && (!pFormatInfo->aClass.isEmpty() || pFormatInfo->bScriptDependent) ) { sOut += " " OOO_STRING_SVTOOLS_HTML_O_class "=\""; rWrt.Strm().WriteOString( sOut ); - sOut = ""; + sOut = ""_ostr; OUString aClass( pFormatInfo->aClass ); if( pFormatInfo->bScriptDependent ) { if( !aClass.isEmpty() ) aClass += "-"; - switch( rHWrt.m_nCSS1Script ) + switch( rWrt.m_nCSS1Script ) { case CSS1_OUTMODE_WESTERN: aClass += "western"; @@ -901,32 +918,40 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, break; } } - HTMLOutFuncs::Out_String( rWrt.Strm(), aClass, - rHWrt.m_eDestEnc, &rHWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rWrt.Strm(), aClass ); sOut += "\""; } rWrt.Strm().WriteOString( sOut ); - sOut = ""; + sOut = ""_ostr; + + std::string_view sStyle; + if (rWrt.IsSpacePreserve()) + { + if (rWrt.mbXHTML) + rWrt.Strm().WriteOString(" xml:space=\"preserve\""); + else + sStyle = "white-space: pre-wrap"; + } // if necessary, output alignment - if( !rHWrt.m_bNoAlign && pAdjItem ) + if( !rWrt.m_bNoAlign && pAdjItem ) OutHTML_SvxAdjust( rWrt, *pAdjItem ); - rHWrt.m_bParaDotLeaders = bPara && rHWrt.m_bCfgPrintLayout && rHWrt.indexOfDotLeaders( + rWrt.m_bParaDotLeaders = bPara && rWrt.m_bCfgPrintLayout && rWrt.indexOfDotLeaders( pTextNd->GetAnyFormatColl().GetPoolFormatId(), pTextNd->GetText()) > -1; // and now, if necessary, the STYLE options - if (rHWrt.m_bCfgOutStyles && rInfo.pItemSet) + if (rWrt.m_bCfgOutStyles && rInfo.moItemSet) { - OutCSS1_ParaTagStyleOpt( rWrt, *rInfo.pItemSet ); + OutCSS1_ParaTagStyleOpt(rWrt, *rInfo.moItemSet, sStyle); } - if (rHWrt.m_bParaDotLeaders) { + if (rWrt.m_bParaDotLeaders) { sOut += " " OOO_STRING_SVTOOLS_HTML_O_class "=\"" sCSS2_P_CLASS_leaders "\"><" OOO_STRING_SVTOOLS_HTML_O_span; rWrt.Strm().WriteOString( sOut ); - sOut = ""; + sOut = ""_ostr; } rWrt.Strm().WriteChar( '>' ); @@ -934,7 +959,7 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, // is a </P> supposed to be written? rInfo.bOutPara = bPara && - ( rHWrt.m_bCfgOutStyles || bHasParSpace ); + ( rWrt.m_bCfgOutStyles || bHasParSpace ); // if no end tag is supposed to be written, delete it if( bNoEndTag ) @@ -947,79 +972,77 @@ static void OutHTML_SwFormat( Writer& rWrt, const SwFormat& rFormat, OSL_ENSURE( nBulletGrfLvl < MAXLEVEL, "There are not this many layers." ); const SwNumFormat& rNumFormat = aNumInfo.GetNumRule()->Get(nBulletGrfLvl); OutHTML_BulletImage( rWrt, OOO_STRING_SVTOOLS_HTML_image, rNumFormat.GetBrush(), - rHWrt.m_aBulletGrfs[nBulletGrfLvl]); + rWrt.m_aBulletGrfs[nBulletGrfLvl]); } - rHWrt.GetNumInfo() = aNumInfo; + rWrt.GetNumInfo() = aNumInfo; // reset the defaults - rHWrt.m_nDfltLeftMargin = 0; - rHWrt.m_nDfltRightMargin = 0; - rHWrt.m_nDfltFirstLineIndent = 0; - rHWrt.m_nDfltTopMargin = 0; - rHWrt.m_nDfltBottomMargin = 0; - rHWrt.m_nLeftMargin = 0; - rHWrt.m_nFirstLineIndent = 0; + rWrt.m_nDfltLeftMargin = 0; + rWrt.m_nDfltRightMargin = 0; + rWrt.m_nDfltFirstLineIndent = 0; + rWrt.m_nDfltTopMargin = 0; + rWrt.m_nDfltBottomMargin = 0; + rWrt.m_nLeftMargin = 0; + rWrt.m_nFirstLineIndent = 0; } -static void OutHTML_SwFormatOff( Writer& rWrt, const SwHTMLTextCollOutputInfo& rInfo ) +static void OutHTML_SwFormatOff( SwHTMLWriter& rWrt, const SwHTMLTextCollOutputInfo& rInfo ) { - SwHTMLWriter & rHWrt = static_cast<SwHTMLWriter&>(rWrt); - // if there is no token, we don't need to output anything if( rInfo.aToken.isEmpty() ) { - rHWrt.FillNextNumInfo(); - const SwHTMLNumRuleInfo& rNextInfo = *rHWrt.GetNextNumInfo(); + rWrt.FillNextNumInfo(); + const SwHTMLNumRuleInfo& rNextInfo = *rWrt.GetNextNumInfo(); // a bulleted list must be closed in PRE as well if( rInfo.bInNumberBulletList ) { - const SwHTMLNumRuleInfo& rNRInfo = rHWrt.GetNumInfo(); + const SwHTMLNumRuleInfo& rNRInfo = rWrt.GetNumInfo(); if( rNextInfo.GetNumRule() != rNRInfo.GetNumRule() || rNextInfo.GetDepth() != rNRInfo.GetDepth() || - rNextInfo.IsNumbered() || rNextInfo.IsRestart() ) - rHWrt.ChangeParaToken( HtmlTokenId::NONE ); - OutHTML_NumberBulletListEnd( rHWrt, rNextInfo ); + rNextInfo.IsNumbered() || rNextInfo.IsRestart(rNRInfo) ) + rWrt.ChangeParaToken( HtmlTokenId::NONE ); + OutHTML_NumberBulletListEnd( rWrt, rNextInfo ); } else if( rNextInfo.GetNumRule() != nullptr ) - rHWrt.ChangeParaToken( HtmlTokenId::NONE ); + rWrt.ChangeParaToken( HtmlTokenId::NONE ); return; } if( rInfo.ShouldOutputToken() ) { - if( rHWrt.m_bLFPossible ) - rHWrt.OutNewLine( true ); + if (rWrt.IsPrettyPrint() && rWrt.IsLFPossible()) + rWrt.OutNewLine( true ); // if necessary, for BLOCKQUOTE, ADDRESS and DD another paragraph token // is output, if // - no styles are written and // - a lower spacing exists if( rInfo.bParaPossible && rInfo.bOutPara ) - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_parabreak, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_parabreak), false ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHWrt.GetNamespace() + rInfo.aToken, false ); - rHWrt.m_bLFPossible = + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + rInfo.aToken), false ); + rWrt.SetLFPossible( rInfo.aToken != OOO_STRING_SVTOOLS_HTML_dt && rInfo.aToken != OOO_STRING_SVTOOLS_HTML_dd && - rInfo.aToken != OOO_STRING_SVTOOLS_HTML_li; + rInfo.aToken != OOO_STRING_SVTOOLS_HTML_li); } if( rInfo.bOutDiv ) { - rHWrt.DecIndentLevel(); - if( rHWrt.m_bLFPossible ) - rHWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division, false ); - rHWrt.m_bLFPossible = true; + rWrt.DecIndentLevel(); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false ); + rWrt.SetLFPossible(true); } // if necessary, close the list item, then close a bulleted or numbered list if( rInfo.bInNumberBulletList ) { - rHWrt.FillNextNumInfo(); - OutHTML_NumberBulletListEnd( rHWrt, *rHWrt.GetNextNumInfo() ); + rWrt.FillNextNumInfo(); + OutHTML_NumberBulletListEnd( rWrt, *rWrt.GetNextNumInfo() ); } } @@ -1027,33 +1050,32 @@ namespace { class HTMLStartEndPos { - sal_Int32 nStart; - sal_Int32 nEnd; - std::unique_ptr<SfxPoolItem> pItem; + sal_Int32 m_nStart; + sal_Int32 m_nEnd; + std::unique_ptr<SfxPoolItem> m_pItem; public: HTMLStartEndPos( const SfxPoolItem& rItem, sal_Int32 nStt, sal_Int32 nE ); - const SfxPoolItem *GetItem() const { return pItem.get(); } + const SfxPoolItem& GetItem() const { return *m_pItem; } - void SetStart( sal_Int32 nStt ) { nStart = nStt; } - sal_Int32 GetStart() const { return nStart; } + void SetStart(sal_Int32 nStt) { m_nStart = nStt; } + sal_Int32 GetStart() const { return m_nStart; } - sal_Int32 GetEnd() const { return nEnd; } - void SetEnd( sal_Int32 nE ) { nEnd = nE; } + sal_Int32 GetEnd() const { return m_nEnd; } + void SetEnd(sal_Int32 nE) { m_nEnd = nE; } }; } -HTMLStartEndPos::HTMLStartEndPos( const SfxPoolItem& rItem, sal_Int32 nStt, - sal_Int32 nE ) : - nStart( nStt ), - nEnd( nE ), - pItem( rItem.Clone() ) +HTMLStartEndPos::HTMLStartEndPos(const SfxPoolItem& rItem, sal_Int32 nStt, sal_Int32 nE) + : m_nStart(nStt) + , m_nEnd(nE) + , m_pItem(rItem.Clone()) {} -typedef std::vector<HTMLStartEndPos *> HTMLStartEndPositions; +typedef std::map<sal_Int32, std::vector<HTMLStartEndPos*>> HTMLStartEndPositions; namespace { @@ -1069,27 +1091,26 @@ enum HTMLOnOffState { HTML_NOT_SUPPORTED, // unsupported Attribute class HTMLEndPosLst { - HTMLStartEndPositions aStartLst; // list, sorted for start positions - HTMLStartEndPositions aEndLst; // list, sorted for end positions - std::deque<sal_Int32> aScriptChgLst; // positions where script changes - // 0 is not contained in this list, - // but the text length + HTMLStartEndPositions m_aStartLst; // list, each position's elements sorted by appearance order + HTMLStartEndPositions m_aEndLst; // list, no sort of elements in position + std::deque<sal_Int32> m_aScriptChgLst; // positions where script changes + // 0 is not contained in this list, + // but the text length // the script that is valid up to the position // contained in aScriptChgList at the same index - std::vector<sal_uInt16> aScriptLst; + std::vector<sal_uInt16> m_aScriptLst; - SwDoc *pDoc; // the current document - SwDoc* pTemplate; // the HTML template (or 0) - std::optional<Color> xDfltColor;// the default foreground colors - std::set<OUString>& rScriptTextStyles; + SwDoc* m_pDoc; // the current document + SwDoc* m_pTemplate; // the HTML template (or 0) + std::optional<Color> m_xDefaultColor; // the default foreground colors + std::set<OUString>& m_rScriptTextStyles; - sal_uLong nHTMLMode; - bool bOutStyles : 1; // are styles exported + sal_uLong m_nHTMLMode; + bool m_bOutStyles : 1; // are styles exported // Insert/remove a SttEndPos in/from the Start and End lists. // The end position is known. - void InsertItem_( HTMLStartEndPos *pPos, HTMLStartEndPositions::size_type nEndPos ); - void RemoveItem_( HTMLStartEndPositions::size_type nEndPos ); + void InsertItem_(HTMLStartEndPos* pPos); // determine the 'type' of the attribute HTMLOnOffState GetHTMLItemState( const SfxPoolItem& rItem ); @@ -1103,8 +1124,7 @@ class HTMLEndPosLst sal_Int32 nEndPos ); // adapt the end of a split item - void FixSplittedItem( HTMLStartEndPos *pPos, sal_Int32 nNewEnd, - HTMLStartEndPositions::size_type nStartPos ); + void FixSplittedItem(HTMLStartEndPos* pPos, sal_Int32 nNewEnd); // insert an attribute in the lists and, if necessary, split it void InsertItem( const SfxPoolItem& rItem, sal_Int32 nStart, @@ -1122,6 +1142,8 @@ class HTMLEndPosLst const SwHTMLFormatInfo *GetFormatInfo( const SwFormat& rFormat, SwHTMLFormatInfos& rFormatInfos ); + void OutEndAttrs(SwHTMLWriter& rWrt, std::vector<HTMLStartEndPos*>& posItems); + public: HTMLEndPosLst( SwDoc *pDoc, SwDoc* pTemplate, std::optional<Color> xDfltColor, @@ -1141,45 +1163,52 @@ public: sal_uInt16 GetScriptAtPos( sal_Int32 nPos, sal_uInt16 nWeak ); - void OutStartAttrs( SwHTMLWriter& rHWrt, sal_Int32 nPos, - HTMLOutContext *pContext = nullptr ); - void OutEndAttrs( SwHTMLWriter& rHWrt, sal_Int32 nPos, - HTMLOutContext *pContext ); + void OutStartAttrs( SwHTMLWriter& rWrt, sal_Int32 nPos ); + void OutEndAttrs( SwHTMLWriter& rWrt, sal_Int32 nPos ); - bool IsHTMLMode( sal_uLong nMode ) const { return (nHTMLMode & nMode) != 0; } + bool IsHTMLMode(sal_uLong nMode) const { return (m_nHTMLMode & nMode) != 0; } }; -} - -void HTMLEndPosLst::InsertItem_( HTMLStartEndPos *pPos, HTMLStartEndPositions::size_type nEndPos ) +struct SortEnds { - // Insert the attribute in the Start list behind all attributes that - // were started before, or at the same position. - sal_Int32 nStart = pPos->GetStart(); - HTMLStartEndPositions::size_type i {0}; + HTMLStartEndPositions& m_startList; + SortEnds(HTMLStartEndPositions& startList) : m_startList(startList) {} + bool operator()(const HTMLStartEndPos* p1, const HTMLStartEndPos* p2) + { + // if p1 start after p2, then it ends before + if (p1->GetStart() > p2->GetStart()) + return true; + if (p1->GetStart() < p2->GetStart()) + return false; + for (const auto p : m_startList[p1->GetStart()]) + { + if (p == p1) + return false; + if (p == p2) + return true; + } + assert(!"Neither p1 nor p2 found in their start list"); + return false; + } +}; - while( i < aStartLst.size() && aStartLst[i]->GetStart() <= nStart ) - ++i; - aStartLst.insert( aStartLst.begin() + i, pPos ); +#ifndef NDEBUG +bool IsEmpty(const HTMLStartEndPositions& l) +{ + return std::find_if(l.begin(), l.end(), [](auto& i) { return !i.second.empty(); }) == l.end(); +} +#endif - // the position in the End list was supplied - aEndLst.insert( aEndLst.begin() + nEndPos, pPos ); } -void HTMLEndPosLst::RemoveItem_( HTMLStartEndPositions::size_type nEndPos ) +void HTMLEndPosLst::InsertItem_(HTMLStartEndPos* pPos) { - HTMLStartEndPos *pPos = aEndLst[nEndPos]; + // Character border attribute must be the first which is written out because of border merge. + auto& posItems1 = m_aStartLst[pPos->GetStart()]; + auto it = pPos->GetItem().Which() == RES_CHRATR_BOX ? posItems1.begin() : posItems1.end(); + posItems1.insert(it, pPos); - // now, we are looking for it in the Start list - HTMLStartEndPositions::iterator it = - std::find(aStartLst.begin(), aStartLst.end(), pPos ); - OSL_ENSURE(it != aStartLst.end(), "Item not found in Start List!"); - if( it != aStartLst.end() ) - aStartLst.erase( it ); - - aEndLst.erase( aEndLst.begin() + nEndPos ); - - delete pPos; + m_aEndLst[pPos->GetEnd()].push_back(pPos); } HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem ) @@ -1206,7 +1235,7 @@ HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem ) break; case RES_CHRATR_CROSSEDOUT: - switch( static_cast<const SvxCrossedOutItem&>(rItem).GetStrikeout() ) + switch( rItem.StaticWhichCast(RES_CHRATR_CROSSEDOUT).GetStrikeout() ) { case STRIKEOUT_SINGLE: case STRIKEOUT_DOUBLE: @@ -1221,7 +1250,7 @@ HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem ) break; case RES_CHRATR_ESCAPEMENT: - switch( static_cast<SvxEscapement>(static_cast<const SvxEscapementItem&>(rItem).GetEnumValue()) ) + switch( static_cast<SvxEscapement>(rItem.StaticWhichCast(RES_CHRATR_ESCAPEMENT).GetEnumValue()) ) { case SvxEscapement::Superscript: case SvxEscapement::Subscript: @@ -1236,7 +1265,7 @@ HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem ) break; case RES_CHRATR_UNDERLINE: - switch( static_cast<const SvxUnderlineItem&>(rItem).GetLineStyle() ) + switch( rItem.StaticWhichCast(RES_CHRATR_UNDERLINE).GetLineStyle() ) { case LINESTYLE_SINGLE: eState = HTML_ON_VALUE; @@ -1276,7 +1305,7 @@ HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem ) break; case RES_CHRATR_BLINK: - eState = static_cast<const SvxBlinkItem&>(rItem).GetValue() ? HTML_ON_VALUE + eState = rItem.StaticWhichCast(RES_CHRATR_BLINK).GetValue() ? HTML_ON_VALUE : HTML_OFF_VALUE; break; @@ -1333,23 +1362,25 @@ HTMLOnOffState HTMLEndPosLst::GetHTMLItemState( const SfxPoolItem& rItem ) bool HTMLEndPosLst::ExistsOnTagItem( sal_uInt16 nWhich, sal_Int32 nPos ) { - for( auto pTest : aStartLst ) + for (const auto& [startPos, items] : m_aStartLst) { - if( pTest->GetStart() > nPos ) + if (startPos > nPos) { // this attribute, and all attributes that follow, start later break; } - else if( pTest->GetEnd() > nPos ) + + for (const auto* pTest : items) { - // the attribute starts before, or at, the current position and - // ends after it - const SfxPoolItem *pItem = pTest->GetItem(); - if( pItem->Which() == nWhich && - HTML_ON_VALUE == GetHTMLItemState(*pItem) ) + if (pTest->GetEnd() > nPos) { - // an OnTag attribute was found - return true; + // the attribute starts before, or at, the current position and ends after it + const SfxPoolItem& rItem = pTest->GetItem(); + if (rItem.Which() == nWhich && HTML_ON_VALUE == GetHTMLItemState(rItem)) + { + // an OnTag attribute was found + return true; + } } } } @@ -1367,24 +1398,17 @@ bool HTMLEndPosLst::ExistsOffTagItem( sal_uInt16 nWhich, sal_Int32 nStartPos, return false; } - for( auto pTest : aStartLst ) + for (const auto* pTest : m_aStartLst[nStartPos]) { - if( pTest->GetStart() > nStartPos ) - { - // this attribute, and all attributes that follow, start later - break; - } - else if( pTest->GetStart()==nStartPos && - pTest->GetEnd()==nEndPos ) + if (pTest->GetEnd() == nEndPos) { - // the attribute starts before or at the current position and - // ends after it - const SfxPoolItem *pItem = pTest->GetItem(); - sal_uInt16 nTstWhich = pItem->Which(); + // the attribute starts before or at the current position and ends after it + const SfxPoolItem& rItem = pTest->GetItem(); + sal_uInt16 nTstWhich = rItem.Which(); if( (nTstWhich == RES_CHRATR_CROSSEDOUT || nTstWhich == RES_CHRATR_UNDERLINE || nTstWhich == RES_CHRATR_BLINK) && - HTML_OFF_VALUE == GetHTMLItemState(*pItem) ) + HTML_OFF_VALUE == GetHTMLItemState(rItem) ) { // an OffTag attribute was found that is exported the same // way as the current item @@ -1396,56 +1420,51 @@ bool HTMLEndPosLst::ExistsOffTagItem( sal_uInt16 nWhich, sal_Int32 nStartPos, return false; } -void HTMLEndPosLst::FixSplittedItem( HTMLStartEndPos *pPos, sal_Int32 nNewEnd, - HTMLStartEndPositions::size_type nStartPos ) +void HTMLEndPosLst::FixSplittedItem(HTMLStartEndPos* pPos, sal_Int32 nNewEnd) { + // remove the item from the End list + std::erase(m_aEndLst[pPos->GetEnd()], pPos); // fix the end position accordingly pPos->SetEnd( nNewEnd ); - - // remove the item from the End list - HTMLStartEndPositions::iterator it = - std::find(aEndLst.begin(), aEndLst.end(), pPos ); - OSL_ENSURE(it != aEndLst.end(), "Item not found in End List!" ); - if( it != aEndLst.end() ) - aEndLst.erase( it ); - - // from now on, it is closed as the last one at the corresponding position - HTMLStartEndPositions::size_type nEndPos {0}; - while( nEndPos < aEndLst.size() && aEndLst[nEndPos]->GetEnd() <= nNewEnd ) - ++nEndPos; - aEndLst.insert( aEndLst.begin() + nEndPos, pPos ); + // from now on, it is closed at the corresponding position + m_aEndLst[nNewEnd].push_back(pPos); // now, adjust the attributes that got started afterwards - for( HTMLStartEndPositions::size_type i = nStartPos+1; i<aStartLst.size(); ++i ) + const sal_Int32 nPos = pPos->GetStart(); + for (const auto& [startPos, items] : m_aStartLst) { - HTMLStartEndPos *pTest = aStartLst[i]; - sal_Int32 nTestEnd = pTest->GetEnd(); - if( pTest->GetStart() >= nNewEnd ) - { - // the Test attribute and all the following ones start, after the - // split attribute ends + if (startPos < nPos) + continue; + + if (startPos >= nNewEnd) break; + + auto it = items.begin(); + if (startPos == nPos) + { + it = std::find(items.begin(), items.end(), pPos); + if (it != items.end()) + ++it; } - else if( nTestEnd > nNewEnd ) + for (; it != items.end(); ++it) { + HTMLStartEndPos* pTest = *it; + const sal_Int32 nTestEnd = pTest->GetEnd(); + if (nTestEnd <= nNewEnd) + continue; + // the Test attribute starts before the split attribute // ends, and ends afterwards, i.e., it must be split, as well + // remove the attribute from the End list + std::erase(m_aEndLst[pTest->GetEnd()], pTest); // set the new end pTest->SetEnd( nNewEnd ); - - // remove the attribute from the End list - it = std::find(aEndLst.begin(), aEndLst.end(), pTest ); - OSL_ENSURE(it != aEndLst.end(), "Item not found in End List!" ); - if( it != aEndLst.end() ) - aEndLst.erase( it ); - - // it now ends as the first attribute in the respective position. - // We already know this position in the End list. - aEndLst.insert( aEndLst.begin() + nEndPos, pTest ); + // it now ends in the respective position. + m_aEndLst[nNewEnd].push_back(pTest); // insert the 'rest' of the attribute - InsertItem( *pTest->GetItem(), nNewEnd, nTestEnd ); + InsertItem( pTest->GetItem(), nNewEnd, nTestEnd ); } } } @@ -1453,36 +1472,38 @@ void HTMLEndPosLst::FixSplittedItem( HTMLStartEndPos *pPos, sal_Int32 nNewEnd, void HTMLEndPosLst::InsertItem( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ) { - HTMLStartEndPositions::size_type i; - for( i = 0; i < aEndLst.size(); i++ ) + assert(nStart < nEnd); + + for (auto& [endPos, items] : m_aEndLst) { - HTMLStartEndPos *pTest = aEndLst[i]; - sal_Int32 nTestEnd = pTest->GetEnd(); - if( nTestEnd <= nStart ) + if (endPos <= nStart) { // the Test attribute ends, before the new one starts continue; } - else if( nTestEnd < nEnd ) + if (endPos >= nEnd) + { + // the Test attribute (and all that follow) ends, before the new + // one ends + break; + } + + std::sort(items.begin(), items.end(), SortEnds(m_aStartLst)); + + for (HTMLStartEndPos* pTest : items) { if( pTest->GetStart() < nStart ) { // the Test attribute ends, before the new one ends. Thus, the // new attribute must be split. - InsertItem_( new HTMLStartEndPos( rItem, nStart, nTestEnd ), i ); - nStart = nTestEnd; + InsertItem_(new HTMLStartEndPos(rItem, nStart, endPos)); + nStart = endPos; } } - else - { - // the Test attribute (and all that follow) ends, before the new - // one ends - break; - } } // one attribute must still be inserted - InsertItem_( new HTMLStartEndPos( rItem, nStart, nEnd ), i ); + InsertItem_(new HTMLStartEndPos(rItem, nStart, nEnd)); } void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, sal_Int32 nStart, @@ -1493,59 +1514,45 @@ void HTMLEndPosLst::SplitItem( const SfxPoolItem& rItem, sal_Int32 nStart, // first, we must search for the old items by using the start list and // determine the new item range - for( HTMLStartEndPositions::size_type i=0; i<aStartLst.size(); ++i ) + for (auto& [nTestStart, items] : m_aStartLst) { - HTMLStartEndPos *pTest = aStartLst[i]; - sal_Int32 nTestStart = pTest->GetStart(); - sal_Int32 nTestEnd = pTest->GetEnd(); - if( nTestStart >= nEnd ) { // this attribute, and all that follow, start later break; } - else if( nTestEnd > nStart ) + + for (auto it = items.begin(); it != items.end();) { + auto itTest = it++; // forward early, allow 'continue', and keep a copy for 'erase' + HTMLStartEndPos* pTest = *itTest; + const sal_Int32 nTestEnd = pTest->GetEnd(); + if (nTestEnd <= nStart) + continue; + // the Test attribute ends in the range that must be deleted - const SfxPoolItem *pItem = pTest->GetItem(); + const SfxPoolItem& rTestItem = pTest->GetItem(); // only the corresponding OnTag attributes have to be considered - if( pItem->Which() == nWhich && - HTML_ON_VALUE == GetHTMLItemState( *pItem ) ) - { - bool bDelete = true; - - if( nTestStart < nStart ) - { - // the start of the new attribute corresponds to the new - // end of the attribute - FixSplittedItem( pTest, nStart, i ); - bDelete = false; - } - else - { - // the Test item only starts after the new end of the - // attribute. Therefore, it can be completely erased. - aStartLst.erase( aStartLst.begin() + i ); - i--; - - HTMLStartEndPositions::iterator it = - std::find(aEndLst.begin(), aEndLst.end(), pTest ); - OSL_ENSURE(it != aEndLst.end(), "Item not found in End List!" ); - if( it != aEndLst.end() ) - aEndLst.erase( it ); - } + if (rTestItem.Which() != nWhich || HTML_ON_VALUE != GetHTMLItemState(rTestItem)) + continue; - // if necessary, insert the second part of the split - // attribute - if( nTestEnd > nEnd ) - { - InsertItem( *pTest->GetItem(), nEnd, nTestEnd ); - } + // if necessary, insert the second part of the split attribute + if (nTestEnd > nEnd) + InsertItem(rTestItem, nEnd, nTestEnd); - if( bDelete ) - delete pTest; + if (nTestStart >= nStart) + { + // the Test item only starts after the new end of the + // attribute. Therefore, it can be completely erased. + it = items.erase(itTest); + std::erase(m_aEndLst[nTestEnd], pTest); + delete pTest; + continue; } + + // the start of the new attribute corresponds to the new end of the attribute + FixSplittedItem(pTest, nStart); } } } @@ -1562,25 +1569,23 @@ const SwHTMLFormatInfo *HTMLEndPosLst::GetFormatInfo( const SwFormat& rFormat, } else { - pFormatInfo = new SwHTMLFormatInfo( &rFormat, pDoc, pTemplate, - bOutStyles ); + pFormatInfo = new SwHTMLFormatInfo(&rFormat, m_pDoc, m_pTemplate, m_bOutStyles); rFormatInfos.insert(std::unique_ptr<SwHTMLFormatInfo>(pFormatInfo)); - if ( rScriptTextStyles.count( rFormat.GetName() ) ) + if (m_rScriptTextStyles.count(rFormat.GetName())) pFormatInfo->bScriptDependent = true; } return pFormatInfo; } -HTMLEndPosLst::HTMLEndPosLst(SwDoc* pD, SwDoc* pTempl, std::optional<Color> xDfltCol, - bool bStyles, sal_uLong nMode, const OUString& rText, - std::set<OUString>& rStyles) - : pDoc(pD) - , pTemplate(pTempl) - , xDfltColor(std::move(xDfltCol)) - , rScriptTextStyles(rStyles) - , nHTMLMode(nMode) - , bOutStyles(bStyles) +HTMLEndPosLst::HTMLEndPosLst(SwDoc* pD, SwDoc* pTempl, std::optional<Color> xDfltCol, bool bStyles, + sal_uLong nMode, const OUString& rText, std::set<OUString>& rStyles) + : m_pDoc(pD) + , m_pTemplate(pTempl) + , m_xDefaultColor(std::move(xDfltCol)) + , m_rScriptTextStyles(rStyles) + , m_nHTMLMode(nMode) + , m_bOutStyles(bStyles) { sal_Int32 nEndPos = rText.getLength(); sal_Int32 nPos = 0; @@ -1588,15 +1593,15 @@ HTMLEndPosLst::HTMLEndPosLst(SwDoc* pD, SwDoc* pTempl, std::optional<Color> xDfl { sal_uInt16 nScript = g_pBreakIt->GetBreakIter()->getScriptType( rText, nPos ); nPos = g_pBreakIt->GetBreakIter()->endOfScript( rText, nPos, nScript ); - aScriptChgLst.push_back( nPos ); - aScriptLst.push_back( nScript ); + m_aScriptChgLst.push_back(nPos); + m_aScriptLst.push_back(nScript); } } HTMLEndPosLst::~HTMLEndPosLst() { - OSL_ENSURE(aStartLst.empty(), "Start List not empty in destructor"); - OSL_ENSURE(aEndLst.empty(), "End List not empty in destructor"); + assert(IsEmpty(m_aStartLst) && "Start List not empty in destructor"); + assert(IsEmpty(m_aEndLst) && "End List not empty in destructor"); } void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem, @@ -1623,8 +1628,7 @@ void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem, // together with the paragraph tag. if( ExistsOnTagItem( rItem.Which(), nStart ) ) bSplit = true; - bSet = bOutStyles && !bParaAttrs && - !ExistsOffTagItem( rItem.Which(), nStart, nEnd ); + bSet = m_bOutStyles && !bParaAttrs && !ExistsOffTagItem(rItem.Which(), nStart, nEnd); break; case HTML_REAL_VALUE: @@ -1637,18 +1641,16 @@ void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem, // the paragraph, it was already output with the paragraph tag. // The only exception is the character-background attribute. This // attribute must always be handled like a Hint. - bSet = bOutStyles && - (!bParaAttrs - || rItem.Which()==RES_CHRATR_BACKGROUND - || rItem.Which()==RES_CHRATR_BOX - || rItem.Which()==RES_CHRATR_OVERLINE); + bSet = m_bOutStyles + && (!bParaAttrs || rItem.Which() == RES_CHRATR_BACKGROUND + || rItem.Which() == RES_CHRATR_BOX || rItem.Which() == RES_CHRATR_OVERLINE); break; case HTML_CHRFMT_VALUE: { OSL_ENSURE( RES_TXTATR_CHARFMT == rItem.Which(), "Not a character style after all" ); - const SwFormatCharFormat& rChrFormat = static_cast<const SwFormatCharFormat&>(rItem); + const SwFormatCharFormat& rChrFormat = rItem.StaticWhichCast(RES_TXTATR_CHARFMT); const SwCharFormat* pFormat = rChrFormat.GetCharFormat(); const SwHTMLFormatInfo *pFormatInfo = GetFormatInfo( *pFormat, rFormatInfos ); @@ -1658,9 +1660,9 @@ void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem, // attributes InsertItem( rItem, nStart, nEnd ); } - if( pFormatInfo->pItemSet ) + if( pFormatInfo->moItemSet ) { - Insert( *pFormatInfo->pItemSet, nStart, nEnd, + Insert( *pFormatInfo->moItemSet, nStart, nEnd, rFormatInfos, true, bParaAttrs ); } } @@ -1668,7 +1670,9 @@ void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem, case HTML_AUTOFMT_VALUE: { - const SwFormatAutoFormat& rAutoFormat = static_cast<const SwFormatAutoFormat&>(rItem); + OSL_ENSURE( RES_TXTATR_AUTOFMT == rItem.Which(), + "Not an automatic style, after all" ); + const SwFormatAutoFormat& rAutoFormat = rItem.StaticWhichCast(RES_TXTATR_AUTOFMT); const std::shared_ptr<SfxItemSet>& pSet = rAutoFormat.GetStyleHandle(); if( pSet ) Insert( *pSet, nStart, nEnd, rFormatInfos, true, bParaAttrs ); @@ -1681,11 +1685,10 @@ void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem, { OSL_ENSURE( RES_CHRATR_COLOR == rItem.Which(), "Not a foreground color, after all" ); - Color aColor( static_cast<const SvxColorItem&>(rItem).GetValue() ); + Color aColor( rItem.StaticWhichCast(RES_CHRATR_COLOR).GetValue() ); if( COL_AUTO == aColor ) aColor = COL_BLACK; - bSet = !bParaAttrs || !xDfltColor || - !xDfltColor->IsRGBEqual( aColor ); + bSet = !bParaAttrs || !m_xDefaultColor || !m_xDefaultColor->IsRGBEqual(aColor); } break; @@ -1693,9 +1696,9 @@ void HTMLEndPosLst::InsertNoScript( const SfxPoolItem& rItem, { OSL_ENSURE( RES_PARATR_DROP == rItem.Which(), "Not a drop cap, after all" ); - const SwFormatDrop& rDrop = static_cast<const SwFormatDrop&>(rItem); + const SwFormatDrop& rDrop = rItem.StaticWhichCast(RES_PARATR_DROP); nEnd = nStart + rDrop.GetChars(); - if( !bOutStyles ) + if (!m_bOutStyles) { // At least use the attributes of the character style const SwCharFormat *pCharFormat = rDrop.GetCharFormat(); @@ -1757,7 +1760,7 @@ void HTMLEndPosLst::Insert( const SfxPoolItem& rItem, break; case RES_TXTATR_CHARFMT: { - const SwFormatCharFormat& rChrFormat = static_cast<const SwFormatCharFormat&>(rItem); + const SwFormatCharFormat& rChrFormat = rItem.StaticWhichCast(RES_TXTATR_CHARFMT); const SwCharFormat* pFormat = rChrFormat.GetCharFormat(); const SwHTMLFormatInfo *pFormatInfo = GetFormatInfo( *pFormat, rFormatInfos ); if( pFormatInfo->bScriptDependent ) @@ -1769,10 +1772,14 @@ void HTMLEndPosLst::Insert( const SfxPoolItem& rItem, break; case RES_TXTATR_INETFMT: { - if( GetFormatInfo( *pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( - RES_POOLCHR_INET_NORMAL), rFormatInfos )->bScriptDependent || - GetFormatInfo( *pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( - RES_POOLCHR_INET_VISIT), rFormatInfos )->bScriptDependent ) + if (GetFormatInfo(*m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( + RES_POOLCHR_INET_NORMAL), + rFormatInfos) + ->bScriptDependent + || GetFormatInfo(*m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( + RES_POOLCHR_INET_VISIT), + rFormatInfos) + ->bScriptDependent) { bDependsOnScript = true; bDependsOnAnyScript = true; @@ -1784,9 +1791,9 @@ void HTMLEndPosLst::Insert( const SfxPoolItem& rItem, if( bDependsOnScript ) { sal_Int32 nPos = nStart; - for( size_t i=0; i < aScriptChgLst.size(); i++ ) + for (size_t i = 0; i < m_aScriptChgLst.size(); i++) { - sal_Int32 nChgPos = aScriptChgLst[i]; + sal_Int32 nChgPos = m_aScriptChgLst[i]; if( nPos >= nChgPos ) { // the hint starts behind or at the next script change, @@ -1798,7 +1805,7 @@ void HTMLEndPosLst::Insert( const SfxPoolItem& rItem, // the (rest of) the hint ends before or at the next script // change, so we can insert it, but only if it belongs // to the current script. - if( bDependsOnAnyScript || nScript == aScriptLst[i] ) + if (bDependsOnAnyScript || nScript == m_aScriptLst[i]) InsertNoScript( rItem, nPos, nEnd, rFormatInfos, bParaAttrs ); break; @@ -1807,7 +1814,7 @@ void HTMLEndPosLst::Insert( const SfxPoolItem& rItem, // the hint starts before the next script change and ends behind // it, so we can insert a hint up to the next script change and // continue with the rest of the hint. - if( bDependsOnAnyScript || nScript == aScriptLst[i] ) + if (bDependsOnAnyScript || nScript == m_aScriptLst[i]) InsertNoScript( rItem, nPos, nChgPos, rFormatInfos, bParaAttrs ); nPos = nChgPos; } @@ -1829,7 +1836,7 @@ void HTMLEndPosLst::Insert( const SfxItemSet& rItemSet, while( nWhich ) { const SfxPoolItem *pItem; - if( SfxItemState::SET == rItemSet.GetItemState( nWhich, bDeep, &pItem ) ) + if( SfxItemState::SET == aIter.GetItemState( bDeep, &pItem ) ) { Insert( *pItem, nStart, nEnd, rFormatInfos, bParaAttrs ); } @@ -1850,164 +1857,188 @@ void HTMLEndPosLst::Insert( const SwDrawFrameFormat& rFormat, sal_Int32 nPos, // insert them as hints. Because of the amount of Hints the styles // are not considered! const SfxItemSet& rFormatItemSet = rFormat.GetAttrSet(); - SfxItemSet aItemSet( *rFormatItemSet.GetPool(), svl::Items<RES_CHRATR_BEGIN, - RES_CHRATR_END>{} ); + SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END> aItemSet( *rFormatItemSet.GetPool() ); SwHTMLWriter::GetEEAttrsFromDrwObj( aItemSet, pTextObj ); - bool bOutStylesOld = bOutStyles; - bOutStyles = false; + bool bOutStylesOld = m_bOutStyles; + m_bOutStyles = false; Insert( aItemSet, nPos, nPos+1, rFormatInfos, false ); - bOutStyles = bOutStylesOld; + m_bOutStyles = bOutStylesOld; } sal_uInt16 HTMLEndPosLst::GetScriptAtPos( sal_Int32 nPos, sal_uInt16 nWeak ) { sal_uInt16 nRet = CSS1_OUTMODE_ANY_SCRIPT; - size_t nScriptChgs = aScriptChgLst.size(); + size_t nScriptChgs = m_aScriptChgLst.size(); size_t i=0; - while( i < nScriptChgs && nPos >= aScriptChgLst[i] ) + while (i < nScriptChgs && nPos >= m_aScriptChgLst[i]) i++; OSL_ENSURE( i < nScriptChgs, "script list is too short" ); if( i < nScriptChgs ) { - if( i18n::ScriptType::WEAK == aScriptLst[i] ) + if (i18n::ScriptType::WEAK == m_aScriptLst[i]) nRet = nWeak; else - nRet = SwHTMLWriter::GetCSS1ScriptForScriptType( aScriptLst[i] ); + nRet = SwHTMLWriter::GetCSS1ScriptForScriptType(m_aScriptLst[i]); } return nRet; } -void HTMLEndPosLst::OutStartAttrs( SwHTMLWriter& rHWrt, sal_Int32 nPos, - HTMLOutContext *pContext ) +void HTMLEndPosLst::OutStartAttrs( SwHTMLWriter& rWrt, sal_Int32 nPos ) { - rHWrt.m_bTagOn = true; - - // Character border attribute must be the first which is written out - // because of border merge. - HTMLStartEndPositions::size_type nCharBoxIndex = 0; - while( nCharBoxIndex < aStartLst.size() && - aStartLst[nCharBoxIndex]->GetItem()->Which() != RES_CHRATR_BOX ) - { - ++nCharBoxIndex; - } + rWrt.m_bTagOn = true; + auto it = m_aStartLst.find(nPos); + if (it == m_aStartLst.end()) + return; // the attributes of the start list are sorted in ascending order - for( HTMLStartEndPositions::size_type i=0; i< aStartLst.size(); ++i ) + for (HTMLStartEndPos* pPos : it->second) { - HTMLStartEndPos *pPos = nullptr; - if( nCharBoxIndex < aStartLst.size() ) + // output the attribute + sal_uInt16 nCSS1Script = rWrt.m_nCSS1Script; + sal_uInt16 nWhich = pPos->GetItem().Which(); + if( RES_TXTATR_CHARFMT == nWhich || + RES_TXTATR_INETFMT == nWhich || + RES_PARATR_DROP == nWhich ) { - if( i == 0 ) - pPos = aStartLst[nCharBoxIndex]; - else if( i == nCharBoxIndex ) - pPos = aStartLst[0]; - else - pPos = aStartLst[i]; + rWrt.m_nCSS1Script = GetScriptAtPos( nPos, nCSS1Script ); } - else - pPos = aStartLst[i]; + HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); // was one time only - do we still need it? + Out( aHTMLAttrFnTab, pPos->GetItem(), rWrt ); + rWrt.maStartedAttributes[pPos->GetItem().Which()]++; + rWrt.m_nCSS1Script = nCSS1Script; + } +} - sal_Int32 nStart = pPos->GetStart(); - if( nStart > nPos ) - { - // this attribute, and all that follow, will be opened later on - break; - } - else if( nStart == nPos ) +void HTMLEndPosLst::OutEndAttrs( SwHTMLWriter& rWrt, sal_Int32 nPos ) +{ + rWrt.m_bTagOn = false; + + if (nPos == SAL_MAX_INT32) + { + for (auto& element : m_aEndLst) + OutEndAttrs(rWrt, element.second); + } + else + { + auto it = m_aEndLst.find(nPos); + if (it != m_aEndLst.end()) + OutEndAttrs(rWrt, it->second); + } +} + +void HTMLEndPosLst::OutEndAttrs(SwHTMLWriter& rWrt, std::vector<HTMLStartEndPos*>& posItems) +{ + std::sort(posItems.begin(), posItems.end(), SortEnds(m_aStartLst)); + for (auto it = posItems.begin(); it != posItems.end(); it = posItems.erase(it)) + { + HTMLStartEndPos* pPos = *it; + HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); // was one time only - do we still need it? + // Skip closing span if next character span has the same border (border merge) + bool bSkipOut = false; + if( pPos->GetItem().Which() == RES_CHRATR_BOX ) { - // output the attribute - sal_uInt16 nCSS1Script = rHWrt.m_nCSS1Script; - sal_uInt16 nWhich = pPos->GetItem()->Which(); - if( RES_TXTATR_CHARFMT == nWhich || - RES_TXTATR_INETFMT == nWhich || - RES_PARATR_DROP == nWhich ) + auto& startPosItems = m_aStartLst[pPos->GetEnd()]; + for (auto it2 = startPosItems.begin(); it2 != startPosItems.end(); ++it2) { - rHWrt.m_nCSS1Script = GetScriptAtPos( nPos, nCSS1Script ); - } - if( pContext ) - { - HTMLOutFuncs::FlushToAscii( rHWrt.Strm(), *pContext ); - pContext = nullptr; // one time only + HTMLStartEndPos* pEndPos = *it2; + if( pEndPos->GetItem().Which() == RES_CHRATR_BOX && + static_cast<const SvxBoxItem&>(pEndPos->GetItem()) == + static_cast<const SvxBoxItem&>(pPos->GetItem()) ) + { + startPosItems.erase(it2); + pEndPos->SetStart(pPos->GetStart()); + auto& oldStartPosItems = m_aStartLst[pEndPos->GetStart()]; + oldStartPosItems.insert(oldStartPosItems.begin(), pEndPos); + bSkipOut = true; + break; + } } - Out( aHTMLAttrFnTab, *pPos->GetItem(), rHWrt ); - rHWrt.maStartedAttributes[pPos->GetItem()->Which()]++; - rHWrt.m_nCSS1Script = nCSS1Script; } + if( !bSkipOut ) + { + Out( aHTMLAttrFnTab, pPos->GetItem(), rWrt ); + rWrt.maStartedAttributes[pPos->GetItem().Which()]--; + } + + std::erase(m_aStartLst[pPos->GetStart()], pPos); + delete pPos; } } -void HTMLEndPosLst::OutEndAttrs( SwHTMLWriter& rHWrt, sal_Int32 nPos, - HTMLOutContext *pContext = nullptr ) +static constexpr bool IsLF(sal_Unicode ch) { return ch == '\n'; } + +static constexpr bool IsWhitespaceExcludingLF(sal_Unicode ch) { - rHWrt.m_bTagOn = false; + return ch == ' ' || ch == '\t' || ch == '\r'; +} - // the attributes in the End list are sorted in ascending order - HTMLStartEndPositions::size_type i {0}; - while( i < aEndLst.size() ) - { - HTMLStartEndPos *pPos = aEndLst[i]; - sal_Int32 nEnd = pPos->GetEnd(); +static constexpr bool IsWhitespaceIncludingLF(sal_Unicode ch) +{ + return IsWhitespaceExcludingLF(ch) || IsLF(ch); +} - if( SAL_MAX_INT32 == nPos || nEnd == nPos ) +static bool NeedPreserveWhitespace(std::u16string_view str, bool xml) +{ + if (str.empty()) + return false; + // leading / trailing spaces + // A leading / trailing \n would turn into a leading / trailing <br/>, + // and will not disappear, even without space preserving option + if (IsWhitespaceExcludingLF(str.front()) || IsWhitespaceExcludingLF(str.back())) + return true; + for (size_t i = 0; i < str.size(); ++i) + { + if (xml) + { + // No need to consider \n, which convert to <br/>, when it's after a space + // (but handle it *before* a space) + if (IsWhitespaceIncludingLF(str[i])) + { + do + { + ++i; + if (i == str.size()) + return false; + } while (IsLF(str[i])); + if (IsWhitespaceExcludingLF(str[i])) + return true; // Second whitespace in a row + } + } + else // html { - if( pContext ) + // Only consider \n, when an adjacent space is not \n - which would be eaten + // without a space preserving option + if (IsWhitespaceExcludingLF(str[i])) { - HTMLOutFuncs::FlushToAscii( rHWrt.Strm(), *pContext ); - pContext = nullptr; // one time only + ++i; + if (i == str.size()) + return false; + if (IsWhitespaceIncludingLF(str[i])) + return true; // Any whitespace after a non-LF whitespace } - // Skip closing span if next character span has the same border (border merge) - bool bSkipOut = false; - if( pPos->GetItem()->Which() == RES_CHRATR_BOX ) + else if (IsLF(str[i])) { - HTMLStartEndPositions::iterator it = - std::find(aStartLst.begin(), aStartLst.end(), pPos ); - OSL_ENSURE(it != aStartLst.end(), "Item not found in Start List!" ); - if (it != aStartLst.end()) - ++it; - while(it != aStartLst.end() ) + do { - HTMLStartEndPos *pEndPos = *it; - if( pEndPos->GetItem()->Which() == RES_CHRATR_BOX && - *static_cast<const SvxBoxItem*>(pEndPos->GetItem()) == - *static_cast<const SvxBoxItem*>(pPos->GetItem()) ) - { - pEndPos->SetStart(pPos->GetStart()); - bSkipOut = true; - break; - } - ++it; + ++i; + if (i == str.size()) + return false; } + while (IsLF(str[i])); + if (IsWhitespaceExcludingLF(str[i])) + return true; // A non-LF whitespace after a LF } - if( !bSkipOut ) - { - Out( aHTMLAttrFnTab, *pPos->GetItem(), rHWrt ); - rHWrt.maStartedAttributes[pPos->GetItem()->Which()]--; - } - RemoveItem_( i ); - } - else if( nEnd > nPos ) - { - // this attribute, and all that follow, are closed later on - break; - } - else - { - // The attribute is closed before the current position. This - // is not allowed, but we can handle it anyway. - OSL_ENSURE( nEnd >= nPos, - "The attribute should've been closed a long time ago" ); - i++; } } + return false; } /* Output of the nodes*/ -Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) +SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter& rWrt, const SwContentNode& rNode ) { const SwTextNode * pNd = &static_cast<const SwTextNode&>(rNode); - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); const OUString& rStr = pNd->GetText(); sal_Int32 nEnd = rStr.getLength(); @@ -2024,34 +2055,39 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) // MIB 8.7.97: We enclose the line in a <PRE>. This means that the // spacings are wrong, but otherwise we get an empty paragraph // after the <HR> which is even uglier. - rHTMLWrt.ChangeParaToken( HtmlTokenId::NONE ); + rWrt.ChangeParaToken( HtmlTokenId::NONE ); // Output all the nodes that are anchored to a frame - rHTMLWrt.OutFlyFrame( rNode.GetIndex(), 0, HtmlPosition::Any ); + rWrt.OutFlyFrame( rNode.GetIndex(), 0, HtmlPosition::Any ); - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); // paragraph tag on a new line + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); // paragraph tag on a new line - rHTMLWrt.m_bLFPossible = true; + rWrt.SetLFPossible(true); - HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace); - aHtml.start(OOO_STRING_SVTOOLS_HTML_horzrule); + HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace); + aHtml.prettyPrint(rWrt.IsPrettyPrint()); + aHtml.start(OOO_STRING_SVTOOLS_HTML_horzrule ""_ostr); const SfxItemSet* pItemSet = pNd->GetpSwAttrSet(); if( !pItemSet ) { - aHtml.endAttribute(); - return rHTMLWrt; + aHtml.end(); + return rWrt; } - const SfxPoolItem* pItem; - if( SfxItemState::SET == pItemSet->GetItemState( RES_LR_SPACE, false, &pItem )) + if (pItemSet->GetItemIfSet(RES_MARGIN_FIRSTLINE, false) + || pItemSet->GetItemIfSet(RES_MARGIN_TEXTLEFT, false) + || pItemSet->GetItemIfSet(RES_MARGIN_RIGHT, false)) { - sal_Int32 nLeft = static_cast<const SvxLRSpaceItem*>(pItem)->GetLeft(); - sal_Int32 nRight = static_cast<const SvxLRSpaceItem*>(pItem)->GetRight(); + SvxFirstLineIndentItem const& rFirstLine(pItemSet->Get(RES_MARGIN_FIRSTLINE)); + SvxTextLeftMarginItem const& rTextLeftMargin(pItemSet->Get(RES_MARGIN_TEXTLEFT)); + SvxRightMarginItem const& rRightMargin(pItemSet->Get(RES_MARGIN_RIGHT)); + sal_Int32 const nLeft(rTextLeftMargin.GetLeft(rFirstLine)); + sal_Int32 const nRight(rRightMargin.GetRight()); if( nLeft || nRight ) { const SwFrameFormat& rPgFormat = - rHTMLWrt.m_pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool + rWrt.m_pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool ( RES_POOLPAGE_HTML, false )->GetMaster(); const SwFormatFrameSize& rSz = rPgFormat.GetFrameSize(); const SvxLRSpaceItem& rLR = rPgFormat.GetLRSpace(); @@ -2071,7 +2107,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) nPageWidth = pBox->GetFrameFormat()->GetFrameSize().GetWidth(); } - OString sWidth = OString::number(SwHTMLWriter::ToPixel(nPageWidth - nLeft - nRight, false)); + OString sWidth = OString::number(SwHTMLWriter::ToPixel(nPageWidth - nLeft - nRight)); aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_width, sWidth); if( !nLeft ) @@ -2083,14 +2119,13 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) } } - if( SfxItemState::SET == pItemSet->GetItemState( RES_BOX, false, &pItem )) + if( const SvxBoxItem* pBoxItem = pItemSet->GetItemIfSet( RES_BOX, false )) { - const SvxBoxItem* pBoxItem = static_cast<const SvxBoxItem*>(pItem); const editeng::SvxBorderLine* pBorderLine = pBoxItem->GetBottom(); if( pBorderLine ) { sal_uInt16 nWidth = pBorderLine->GetScaledWidth(); - OString sWidth = OString::number(SwHTMLWriter::ToPixel(nWidth, false)); + OString sWidth = OString::number(SwHTMLWriter::ToPixel(nWidth)); aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_size, sWidth); const Color& rBorderColor = pBorderLine->GetColor(); @@ -2106,7 +2141,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) } } aHtml.end(); - return rHTMLWrt; + return rWrt; } // Do not export the empty nodes with 2pt fonts and standard style that @@ -2117,14 +2152,14 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) nPoolId == RES_POOLCOLL_TABLE_HDLN) ) { // The current node is empty and contains the standard style ... - const SfxPoolItem* pItem; + const SvxFontHeightItem* pFontHeightItem; const SfxItemSet* pItemSet = pNd->GetpSwAttrSet(); if( pItemSet && pItemSet->Count() && - SfxItemState::SET == pItemSet->GetItemState( RES_CHRATR_FONTSIZE, false, &pItem ) && - 40 == static_cast<const SvxFontHeightItem *>(pItem)->GetHeight() ) + (pFontHeightItem = pItemSet->GetItemIfSet( RES_CHRATR_FONTSIZE, false )) && + 40 == pFontHeightItem->GetHeight() ) { // ... moreover, the 2pt font is set ... - sal_uLong nNdPos = rWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex(); + SwNodeOffset nNdPos = rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex(); const SwNode *pNextNd = rWrt.m_pDoc->GetNodes()[nNdPos+1]; const SwNode *pPrevNd = rWrt.m_pDoc->GetNodes()[nNdPos-1]; bool bStdColl = nPoolId == RES_POOLCOLL_STANDARD; @@ -2135,12 +2170,12 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) SwTableBoxStartNode == pPrevNd->GetStartNode()->GetStartNodeType() ) ) { // ... and it is located before a table or a section - rHTMLWrt.OutBookmarks(); - rHTMLWrt.m_bLFPossible = rHTMLWrt.m_nLastParaToken == HtmlTokenId::NONE; + rWrt.OutBookmarks(); + rWrt.SetLFPossible(rWrt.m_nLastParaToken == HtmlTokenId::NONE); // Output all frames that are anchored to this node - rHTMLWrt.OutFlyFrame( rNode.GetIndex(), 0, HtmlPosition::Any ); - rHTMLWrt.m_bLFPossible = false; + rWrt.OutFlyFrame( rNode.GetIndex(), 0, HtmlPosition::Any ); + rWrt.SetLFPossible(false); return rWrt; } @@ -2149,24 +2184,23 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) // catch PageBreaks and PageDescs bool bPageBreakBehind = false; - if( rHTMLWrt.m_bCfgFormFeed && - !(rHTMLWrt.m_bOutTable || rHTMLWrt.m_bOutFlyFrame) && - rHTMLWrt.m_pStartNdIdx->GetIndex() != rHTMLWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() ) + if( rWrt.m_bCfgFormFeed && + !(rWrt.m_bOutTable || rWrt.m_bOutFlyFrame) && + rWrt.m_pStartNdIdx->GetIndex() != rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex() ) { bool bPageBreakBefore = false; - const SfxPoolItem* pItem; const SfxItemSet* pItemSet = pNd->GetpSwAttrSet(); if( pItemSet ) { - if( SfxItemState::SET == pItemSet->GetItemState( RES_PAGEDESC, true, &pItem ) && - static_cast<const SwFormatPageDesc *>(pItem)->GetPageDesc() ) + const SwFormatPageDesc* pPageDescItem = pItemSet->GetItemIfSet( RES_PAGEDESC ); + if( pPageDescItem && pPageDescItem->GetPageDesc() ) { bPageBreakBefore = true; } - else if( SfxItemState::SET == pItemSet->GetItemState( RES_BREAK, true, &pItem ) ) + else if( const SvxFormatBreakItem* pItem = pItemSet->GetItemIfSet( RES_BREAK ) ) { - switch( static_cast<const SvxFormatBreakItem *>(pItem)->GetBreak() ) + switch( pItem->GetBreak() ) { case SvxBreak::PageBefore: bPageBreakBefore = true; @@ -2189,48 +2223,53 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) } // if necessary, open a form - rHTMLWrt.OutForm(); + rWrt.OutForm(); // Output the page-anchored frames that are 'anchored' to this node - bool bFlysLeft = rHTMLWrt.OutFlyFrame( rNode.GetIndex(), 0, HtmlPosition::Prefix ); + bool bFlysLeft = rWrt.OutFlyFrame( rNode.GetIndex(), 0, HtmlPosition::Prefix ); // Output all frames that are anchored to this node that are supposed to // be written before the paragraph tag. if( bFlysLeft ) { - bFlysLeft = rHTMLWrt.OutFlyFrame( rNode.GetIndex(), 0, HtmlPosition::Before ); + bFlysLeft = rWrt.OutFlyFrame( rNode.GetIndex(), 0, HtmlPosition::Before ); } - if( rHTMLWrt.m_pCurrentPam->GetPoint()->nNode == rHTMLWrt.m_pCurrentPam->GetMark()->nNode ) + if( rWrt.m_pCurrentPam->GetPoint()->GetNode() == rWrt.m_pCurrentPam->GetMark()->GetNode() ) { - nEnd = rHTMLWrt.m_pCurrentPam->GetMark()->nContent.GetIndex(); + nEnd = rWrt.m_pCurrentPam->GetMark()->GetContentIndex(); } // are there any hard attributes that must be written as options? - rHTMLWrt.m_bTagOn = true; + rWrt.m_bTagOn = true; // now, output the tag of the paragraph const SwFormat& rFormat = pNd->GetAnyFormatColl(); SwHTMLTextCollOutputInfo aFormatInfo; - bool bOldLFPossible = rHTMLWrt.m_bLFPossible; + bool bOldLFPossible = rWrt.IsLFPossible(); + bool bOldSpacePreserve = rWrt.IsSpacePreserve(); + if (rWrt.IsPreserveSpacesOnWritePrefSet()) + rWrt.SetSpacePreserve(NeedPreserveWhitespace(rStr, rWrt.mbReqIF)); OutHTML_SwFormat( rWrt, rFormat, pNd->GetpSwAttrSet(), aFormatInfo ); // If we didn't open a new line before the paragraph tag, we do that now - rHTMLWrt.m_bLFPossible = rHTMLWrt.m_nLastParaToken == HtmlTokenId::NONE; - if( !bOldLFPossible && rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); + rWrt.SetLFPossible(rWrt.m_nLastParaToken == HtmlTokenId::NONE); + if (!bOldLFPossible && rWrt.IsLFPossible()) + rWrt.OutNewLine(); // then, the bookmarks (including end tag) - rHTMLWrt.m_bOutOpts = false; - rHTMLWrt.OutBookmarks(); + rWrt.m_bOutOpts = false; + rWrt.OutBookmarks(); // now it's a good opportunity again for an LF - if it is still allowed - if( rHTMLWrt.m_bLFPossible && - rHTMLWrt.GetLineLen() >= rHTMLWrt.m_nWishLineLen ) + // FIXME: for LOK case we set rWrt.m_nWishLineLen as -1, for now keep old flow + // when LOK side will be fixed - don't insert new line at the beginning + if( rWrt.IsLFPossible() && rWrt.IsPrettyPrint() && rWrt.m_nWishLineLen >= 0 && + rWrt.GetLineLen() >= rWrt.m_nWishLineLen ) { - rHTMLWrt.OutNewLine(); + rWrt.OutNewLine(); } - rHTMLWrt.m_bLFPossible = false; + rWrt.SetLFPossible(false); // find text that originates from an outline numbering sal_Int32 nOffset = 0; @@ -2247,66 +2286,65 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) aFullText = aOutlineText; } OUString aFootEndNoteSym; - if( rHTMLWrt.m_pFormatFootnote ) + if( rWrt.m_pFormatFootnote ) { - aFootEndNoteSym = rHTMLWrt.GetFootEndNoteSym( *rHTMLWrt.m_pFormatFootnote ); + aFootEndNoteSym = rWrt.GetFootEndNoteSym( *rWrt.m_pFormatFootnote ); nOffset = nOffset + aFootEndNoteSym.getLength(); aFullText += aFootEndNoteSym; } // Table of Contents or other paragraph with dot leaders? - sal_Int32 nIndexTab = rHTMLWrt.indexOfDotLeaders( nPoolId, rStr ); + sal_Int32 nIndexTab = rWrt.indexOfDotLeaders( nPoolId, rStr ); if (nIndexTab > -1) // skip part after the tabulator (page number) nEnd = nIndexTab; // are there any hard attributes that must be written as tags? aFullText += rStr; - HTMLEndPosLst aEndPosLst( rWrt.m_pDoc, rHTMLWrt.m_xTemplate.get(), - rHTMLWrt.m_xDfltColor, rHTMLWrt.m_bCfgOutStyles, - rHTMLWrt.GetHTMLMode(), aFullText, - rHTMLWrt.m_aScriptTextStyles ); - if( aFormatInfo.pItemSet ) + HTMLEndPosLst aEndPosLst( rWrt.m_pDoc, rWrt.m_xTemplate.get(), + rWrt.m_xDfltColor, rWrt.m_bCfgOutStyles, + rWrt.GetHTMLMode(), aFullText, + rWrt.m_aScriptTextStyles ); + if( aFormatInfo.moItemSet ) { - aEndPosLst.Insert( *aFormatInfo.pItemSet, 0, nEnd + nOffset, - rHTMLWrt.m_CharFormatInfos, false, true ); + aEndPosLst.Insert( *aFormatInfo.moItemSet, 0, nEnd + nOffset, + rWrt.m_CharFormatInfos, false, true ); } - if( !aOutlineText.isEmpty() || rHTMLWrt.m_pFormatFootnote ) + if( !aOutlineText.isEmpty() || rWrt.m_pFormatFootnote ) { // output paragraph attributes, so that the text gets the attributes of // the paragraph. - aEndPosLst.OutStartAttrs( rHTMLWrt, 0 ); + aEndPosLst.OutStartAttrs( rWrt, 0 ); // Theoretically, we would have to consider the character style of // the numbering. Because it cannot be set via the UI, let's ignore // it for now. if( !aOutlineText.isEmpty() ) - HTMLOutFuncs::Out_String( rWrt.Strm(), aOutlineText, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters); + HTMLOutFuncs::Out_String( rWrt.Strm(), aOutlineText ); - if( rHTMLWrt.m_pFormatFootnote ) + if( rWrt.m_pFormatFootnote ) { - rHTMLWrt.OutFootEndNoteSym( *rHTMLWrt.m_pFormatFootnote, aFootEndNoteSym, - aEndPosLst.GetScriptAtPos( aOutlineText.getLength(), rHTMLWrt.m_nCSS1Script ) ); - rHTMLWrt.m_pFormatFootnote = nullptr; + rWrt.OutFootEndNoteSym( *rWrt.m_pFormatFootnote, aFootEndNoteSym, + aEndPosLst.GetScriptAtPos( aOutlineText.getLength(), rWrt.m_nCSS1Script ) ); + rWrt.m_pFormatFootnote = nullptr; } } // for now, correct the start. I.e., if we only output part of the sentence, // the attributes must be correct there, as well!! - rHTMLWrt.m_bTextAttr = true; + rWrt.m_bTextAttr = true; size_t nAttrPos = 0; - sal_Int32 nStrPos = rHTMLWrt.m_pCurrentPam->GetPoint()->nContent.GetIndex(); + sal_Int32 nStrPos = rWrt.m_pCurrentPam->GetPoint()->GetContentIndex(); const SwTextAttr * pHt = nullptr; const size_t nCntAttr = pNd->HasHints() ? pNd->GetSwpHints().Count() : 0; if( nCntAttr && nStrPos > ( pHt = pNd->GetSwpHints().Get(0) )->GetStart() ) { // Ok, there are earlier attributes that we must output do { - aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset ); + aEndPosLst.OutEndAttrs( rWrt, nStrPos + nOffset ); nAttrPos++; if( pHt->Which() == RES_TXTATR_FIELD @@ -2317,7 +2355,7 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) { const sal_Int32 nHtEnd = *pHt->End(), nHtStt = pHt->GetStart(); - if( !rHTMLWrt.m_bWriteAll && nHtEnd <= nStrPos ) + if( !rWrt.m_bWriteAll && nHtEnd <= nStrPos ) continue; // don't consider empty hints at the beginning - or should we ?? @@ -2325,17 +2363,17 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) continue; // add attribute to the list - if( rHTMLWrt.m_bWriteAll ) + if( rWrt.m_bWriteAll ) aEndPosLst.Insert( pHt->GetAttr(), nHtStt + nOffset, nHtEnd + nOffset, - rHTMLWrt.m_CharFormatInfos ); + rWrt.m_CharFormatInfos ); else { sal_Int32 nTmpStt = nHtStt < nStrPos ? nStrPos : nHtStt; sal_Int32 nTmpEnd = std::min(nHtEnd, nEnd); aEndPosLst.Insert( pHt->GetAttr(), nTmpStt + nOffset, nTmpEnd + nOffset, - rHTMLWrt.m_CharFormatInfos ); + rWrt.m_CharFormatInfos ); } continue; // but don't output it, that will be done later !! @@ -2345,26 +2383,28 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) ( pHt = pNd->GetSwpHints().Get( nAttrPos ) )->GetStart() ); // so, let's output all collected attributes from the string pos on - aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset ); - aEndPosLst.OutStartAttrs( rHTMLWrt, nStrPos + nOffset ); + aEndPosLst.OutEndAttrs( rWrt, nStrPos + nOffset ); + aEndPosLst.OutStartAttrs( rWrt, nStrPos + nOffset ); } - bool bWriteBreak = (HtmlTokenId::PREFORMTXT_ON != rHTMLWrt.m_nLastParaToken); - if( bWriteBreak && pNd->GetNumRule() ) + bool bWriteBreak = (HtmlTokenId::PREFORMTXT_ON != rWrt.m_nLastParaToken); + if (bWriteBreak && (pNd->GetNumRule() || rWrt.mbReqIF)) + { + // One line-break is exactly one <br> in the ReqIF case. bWriteBreak = false; + } { - HTMLOutContext aContext( rHTMLWrt.m_eDestEnc ); - + // Tabs are leading till there is a non-tab since the start of the paragraph. + bool bLeadingTab = true; for( ; nStrPos < nEnd; nStrPos++ ) { // output the frames that are anchored to the current position if( bFlysLeft ) { - aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset, &aContext ); - bFlysLeft = rHTMLWrt.OutFlyFrame( rNode.GetIndex(), - nStrPos, HtmlPosition::Inside, - &aContext ); + aEndPosLst.OutEndAttrs( rWrt, nStrPos + nOffset ); + bFlysLeft = rWrt.OutFlyFrame( rNode.GetIndex(), + nStrPos, HtmlPosition::Inside ); } bool bOutChar = true; @@ -2381,16 +2421,16 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) // are ignored) aEndPosLst.Insert( pHt->GetAttr(), nStrPos + nOffset, *pHt->End() + nOffset, - rHTMLWrt.m_CharFormatInfos ); + rWrt.m_CharFormatInfos ); } } else { // hints without an end are output last OSL_ENSURE( !pTextHt, "Why is there already an attribute without an end?" ); - if( rHTMLWrt.m_nTextAttrsToIgnore>0 ) + if( rWrt.m_nTextAttrsToIgnore>0 ) { - rHTMLWrt.m_nTextAttrsToIgnore--; + rWrt.m_nTextAttrsToIgnore--; } else { @@ -2413,29 +2453,29 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) if( pTextHt && RES_TXTATR_FLYCNT == pTextHt->Which() ) { const SwFrameFormat* pFrameFormat = - static_cast<const SwFormatFlyCnt &>(pTextHt->GetAttr()).GetFrameFormat(); + pTextHt->GetAttr().StaticWhichCast(RES_TXTATR_FLYCNT).GetFrameFormat(); if( RES_DRAWFRMFMT == pFrameFormat->Which() ) aEndPosLst.Insert( *static_cast<const SwDrawFrameFormat *>(pFrameFormat), nStrPos + nOffset, - rHTMLWrt.m_CharFormatInfos ); + rWrt.m_CharFormatInfos ); } - aEndPosLst.OutEndAttrs( rHTMLWrt, nStrPos + nOffset, &aContext ); - aEndPosLst.OutStartAttrs( rHTMLWrt, nStrPos + nOffset, &aContext ); + aEndPosLst.OutEndAttrs( rWrt, nStrPos + nOffset ); + aEndPosLst.OutStartAttrs( rWrt, nStrPos + nOffset ); if( pTextHt ) { - rHTMLWrt.m_bLFPossible = rHTMLWrt.m_nLastParaToken == HtmlTokenId::NONE && + rWrt.SetLFPossible(rWrt.m_nLastParaToken == HtmlTokenId::NONE && nStrPos > 0 && - rStr[nStrPos-1] == ' '; - sal_uInt16 nCSS1Script = rHTMLWrt.m_nCSS1Script; - rHTMLWrt.m_nCSS1Script = aEndPosLst.GetScriptAtPos( + rStr[nStrPos-1] == ' '); + sal_uInt16 nCSS1Script = rWrt.m_nCSS1Script; + rWrt.m_nCSS1Script = aEndPosLst.GetScriptAtPos( nStrPos + nOffset, nCSS1Script ); - HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); - Out( aHTMLAttrFnTab, pTextHt->GetAttr(), rHTMLWrt ); - rHTMLWrt.m_nCSS1Script = nCSS1Script; - rHTMLWrt.m_bLFPossible = false; + HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); + Out( aHTMLAttrFnTab, pTextHt->GetAttr(), rWrt ); + rWrt.m_nCSS1Script = nCSS1Script; + rWrt.SetLFPossible(false); } if( bOutChar ) @@ -2453,21 +2493,22 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) // try to split a line after about 255 characters // at a space character unless in a PRE-context - if( ' ' == c && rHTMLWrt.m_nLastParaToken == HtmlTokenId::NONE ) + if( ' ' == c && rWrt.m_nLastParaToken == HtmlTokenId::NONE && !rWrt.IsSpacePreserve() ) { sal_Int32 nLineLen; - nLineLen = rHTMLWrt.GetLineLen(); + nLineLen = rWrt.GetLineLen(); sal_Int32 nWordLen = rStr.indexOf( ' ', nStrPos+1 ); if( nWordLen == -1 ) nWordLen = nEnd; nWordLen -= nStrPos; - if( nLineLen >= rHTMLWrt.m_nWishLineLen || - (nLineLen+nWordLen) >= rHTMLWrt.m_nWishLineLen ) + if( rWrt.IsPrettyPrint() && rWrt.m_nWishLineLen >= 0 && + (nLineLen >= rWrt.m_nWishLineLen || + (nLineLen+nWordLen) >= rWrt.m_nWishLineLen ) ) { - HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); - rHTMLWrt.OutNewLine(); + HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); + rWrt.OutNewLine(); bOutChar = false; } } @@ -2476,74 +2517,104 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) { if( 0x0a == c ) { - HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); - HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace); - aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak); + HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); + HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace); + aHtml.prettyPrint(rWrt.IsPrettyPrint()); + aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr); } else if (c == CH_TXT_ATR_FORMELEMENT) { // Placeholder for a single-point fieldmark. SwPosition aMarkPos = *rWrt.m_pCurrentPam->GetPoint(); - aMarkPos.nContent += nStrPos - aMarkPos.nContent.GetIndex(); - rHTMLWrt.OutPointFieldmarks(aMarkPos); + aMarkPos.AdjustContent( nStrPos - aMarkPos.GetContentIndex() ); + rWrt.OutPointFieldmarks(aMarkPos); } else - HTMLOutFuncs::Out_Char( rWrt.Strm(), c, aContext, &rHTMLWrt.m_aNonConvertableCharacters ); + { + bool bConsumed = false; + if (c == '\t') + { + if (bLeadingTab && rWrt.m_nLeadingTabWidth.has_value()) + { + // Consume a tab if it's leading and we know the number of NBSPs to + // be used as a replacement. + for (sal_Int32 i = 0; i < *rWrt.m_nLeadingTabWidth; ++i) + { + rWrt.Strm().WriteOString(" "); + } + bConsumed = true; + } + } + else + { + // Not a tab -> later tabs are no longer leading. + bLeadingTab = false; + } + + if (!bConsumed) + { + HTMLOutFuncs::Out_Char(rWrt.Strm(), c); + } + } - // if a paragraph's last character is a hard line break - // then we need to add an extra <br> - // because browsers like Mozilla wouldn't add a line for the next paragraph - bWriteBreak = (0x0a == c) && - (HtmlTokenId::PREFORMTXT_ON != rHTMLWrt.m_nLastParaToken); + if (!rWrt.mbReqIF) + { + // if a paragraph's last character is a hard line break + // then we need to add an extra <br> + // because browsers like Mozilla wouldn't add a line for the next paragraph + bWriteBreak = (0x0a == c) && + (HtmlTokenId::PREFORMTXT_ON != rWrt.m_nLastParaToken); + } } } } - HTMLOutFuncs::FlushToAscii( rWrt.Strm(), aContext ); + HTMLOutFuncs::FlushToAscii( rWrt.Strm() ); } - aEndPosLst.OutEndAttrs( rHTMLWrt, SAL_MAX_INT32 ); + aEndPosLst.OutEndAttrs( rWrt, SAL_MAX_INT32 ); // Output the frames that are anchored to the last position if( bFlysLeft ) - bFlysLeft = rHTMLWrt.OutFlyFrame( rNode.GetIndex(), + bFlysLeft = rWrt.OutFlyFrame( rNode.GetIndex(), nEnd, HtmlPosition::Inside ); OSL_ENSURE( !bFlysLeft, "Not all frames were saved!" ); - rHTMLWrt.m_bTextAttr = false; + rWrt.m_bTextAttr = false; if( bWriteBreak ) { - bool bEndOfCell = rHTMLWrt.m_bOutTable && - rWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() == - rWrt.m_pCurrentPam->GetMark()->nNode.GetIndex(); + bool bEndOfCell = rWrt.m_bOutTable && + rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex() == + rWrt.m_pCurrentPam->GetMark()->GetNodeIndex(); if( bEndOfCell && !nEnd && - rHTMLWrt.IsHTMLMode(HTMLMODE_NBSP_IN_TABLES) ) + rWrt.IsHTMLMode(HTMLMODE_NBSP_IN_TABLES) ) { // If the last paragraph of a table cell is empty and we export // for the MS-IE, we write a instead of a <BR> - rWrt.Strm().WriteChar( '&' ).WriteCharPtr( OOO_STRING_SVTOOLS_HTML_S_nbsp ).WriteChar( ';' ); + rWrt.Strm().WriteChar( '&' ).WriteOString( OOO_STRING_SVTOOLS_HTML_S_nbsp ).WriteChar( ';' ); } else { - HtmlWriter aHtml(rHTMLWrt.Strm(), rHTMLWrt.maNamespace); - aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak); + HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace); + aHtml.prettyPrint(rWrt.IsPrettyPrint()); + aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr); const SvxULSpaceItem& rULSpace = pNd->GetSwAttrSet().Get(RES_UL_SPACE); if (rULSpace.GetLower() > 0 && !bEndOfCell) { - aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak); + aHtml.single(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr); } - rHTMLWrt.m_bLFPossible = true; + rWrt.SetLFPossible(true); } } - if( rHTMLWrt.m_bClearLeft || rHTMLWrt.m_bClearRight ) + if( rWrt.m_bClearLeft || rWrt.m_bClearRight ) { const char* pString; - if( rHTMLWrt.m_bClearLeft ) + if( rWrt.m_bClearLeft ) { - if( rHTMLWrt.m_bClearRight ) + if( rWrt.m_bClearRight ) pString = OOO_STRING_SVTOOLS_HTML_AL_all; else pString = OOO_STRING_SVTOOLS_HTML_AL_left; @@ -2553,61 +2624,64 @@ Writer& OutHTML_SwTextNode( Writer& rWrt, const SwContentNode& rNode ) pString = OOO_STRING_SVTOOLS_HTML_AL_right; } - HtmlWriter aHtml(rHTMLWrt.Strm(), rHTMLWrt.maNamespace); - aHtml.start(OOO_STRING_SVTOOLS_HTML_linebreak); + HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace); + aHtml.prettyPrint(rWrt.IsPrettyPrint()); + aHtml.start(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr); aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, pString); aHtml.end(); - rHTMLWrt.m_bClearLeft = false; - rHTMLWrt.m_bClearRight = false; + rWrt.m_bClearLeft = false; + rWrt.m_bClearRight = false; - rHTMLWrt.m_bLFPossible = true; + rWrt.SetLFPossible(true); } // if an LF is not allowed already, it is allowed once the paragraphs // ends with a ' ' - if( !rHTMLWrt.m_bLFPossible && - rHTMLWrt.m_nLastParaToken == HtmlTokenId::NONE && + if (!rWrt.IsLFPossible() && + rWrt.m_nLastParaToken == HtmlTokenId::NONE && nEnd > 0 && ' ' == rStr[nEnd-1] ) - rHTMLWrt.m_bLFPossible = true; + rWrt.SetLFPossible(true); // dot leaders: print the skipped page number in a different span element if (nIndexTab > -1) { OString sOut = OUStringToOString(rStr.subView(nIndexTab + 1), RTL_TEXTENCODING_ASCII_US); - rWrt.Strm().WriteOString( "</span><span>" + sOut + "</span>" ); + rWrt.Strm().WriteOString( Concat2View("</span><span>" + sOut + "</span>") ); } - rHTMLWrt.m_bTagOn = false; + rWrt.m_bTagOn = false; OutHTML_SwFormatOff( rWrt, aFormatInfo ); + rWrt.SetSpacePreserve(bOldSpacePreserve); // if necessary, close a form - rHTMLWrt.OutForm( false ); + rWrt.OutForm( false ); if( bPageBreakBehind ) rWrt.Strm().WriteChar( '\f' ); - return rHTMLWrt; + return rWrt; } -sal_uInt32 SwHTMLWriter::ToPixel( sal_uInt32 nVal, const bool bVert ) +// In CSS, "px" is 1/96 of inch: https://www.w3.org/TR/css3-values/#absolute-lengths +sal_uInt32 SwHTMLWriter::ToPixel(sal_uInt32 nTwips) { - if( Application::GetDefaultDevice() && nVal ) - { - Size aSz( bVert ? 0 : nVal, bVert ? nVal : 0 ); - aSz = Application::GetDefaultDevice()->LogicToPixel(aSz, MapMode( MapUnit::MapTwip )); - nVal = bVert ? aSz.Height() : aSz.Width(); - if( !nVal ) // if there is a Twip, there should be a pixel as well - nVal = 1; - } - return nVal; + // if there is a Twip, there should be a pixel as well + return nTwips + ? std::max(o3tl::convert(nTwips, o3tl::Length::twip, o3tl::Length::px), sal_Int64(1)) + : 0; +} + +Size SwHTMLWriter::ToPixel(Size aTwips) +{ + return Size(ToPixel(aTwips.Width()), ToPixel(aTwips.Height())); } -static Writer& OutHTML_CSS1Attr( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_CSS1Attr( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { // if hints are currently written, we try to write the hint as an // CSS1 attribute - if( static_cast<SwHTMLWriter&>(rWrt).m_bCfgOutStyles && static_cast<SwHTMLWriter&>(rWrt).m_bTextAttr ) + if( rWrt.m_bCfgOutStyles && rWrt.m_bTextAttr ) OutCSS1_HintSpanTag( rWrt, rHt ); return rWrt; @@ -2615,35 +2689,34 @@ static Writer& OutHTML_CSS1Attr( Writer& rWrt, const SfxPoolItem& rHt ) /* File CHRATR.HXX: */ -static Writer& OutHTML_SvxColor( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SvxColor( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; - if( !rHTMLWrt.m_bTextAttr && rHTMLWrt.m_bCfgOutStyles && rHTMLWrt.m_bCfgPreferStyles ) + if( !rWrt.m_bTextAttr && rWrt.m_bCfgOutStyles && rWrt.m_bCfgPreferStyles ) { // don't write the font color as a tag, if styles are preferred to // normal tags return rWrt; } - if( rHTMLWrt.m_bTagOn ) + if( rWrt.m_bTagOn ) { Color aColor( static_cast<const SvxColorItem&>(rHt).GetValue() ); if( COL_AUTO == aColor ) aColor = COL_BLACK; - if (rHTMLWrt.mbXHTML) + if (rWrt.mbXHTML) { - OString sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span + OString sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span " " OOO_STRING_SVTOOLS_HTML_O_style "="; rWrt.Strm().WriteOString(sOut); HTMLOutFuncs::Out_Color(rWrt.Strm(), aColor, /*bXHTML=*/true).WriteChar('>'); } else { - OString sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font " " + OString sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font " " OOO_STRING_SVTOOLS_HTML_O_color "="; rWrt.Strm().WriteOString( sOut ); HTMLOutFuncs::Out_Color( rWrt.Strm(), aColor ).WriteChar( '>' ); @@ -2651,28 +2724,27 @@ static Writer& OutHTML_SvxColor( Writer& rWrt, const SfxPoolItem& rHt ) } else { - if (rHTMLWrt.mbXHTML) + if (rWrt.mbXHTML) HTMLOutFuncs::Out_AsciiTag( - rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false); + rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false); else - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font), false ); } return rWrt; } -static Writer& OutHTML_SwPosture( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SwPosture( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; const FontItalic nPosture = static_cast<const SvxPostureItem&>(rHt).GetPosture(); if( ITALIC_NORMAL == nPosture ) { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_italic, rHTMLWrt.m_bTagOn ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_italic), rWrt.m_bTagOn ); } - else if( rHTMLWrt.m_bCfgOutStyles && rHTMLWrt.m_bTextAttr ) + else if( rWrt.m_bCfgOutStyles && rWrt.m_bTextAttr ) { // maybe as CSS1 attribute? OutCSS1_HintSpanTag( rWrt, rHt ); @@ -2681,68 +2753,65 @@ static Writer& OutHTML_SwPosture( Writer& rWrt, const SfxPoolItem& rHt ) return rWrt; } -static Writer& OutHTML_SvxFont( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SvxFont( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; - if (IgnorePropertyForReqIF(rHTMLWrt.mbReqIF, "font-family", "")) + if (IgnorePropertyForReqIF(rWrt.mbReqIF, "font-family", "")) { return rWrt; } - if( rHTMLWrt.m_bTagOn ) + if( rWrt.m_bTagOn ) { OUString aNames; SwHTMLWriter::PrepareFontList( static_cast<const SvxFontItem&>(rHt), aNames, 0, - rHTMLWrt.IsHTMLMode(HTMLMODE_FONT_GENERIC) ); - if (rHTMLWrt.mbXHTML) + rWrt.IsHTMLMode(HTMLMODE_FONT_GENERIC) ); + if (rWrt.mbXHTML) { - OString sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span + OString sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span " " OOO_STRING_SVTOOLS_HTML_O_style "=\"font-family: "; rWrt.Strm().WriteOString(sOut); - HTMLOutFuncs::Out_String(rWrt.Strm(), aNames, rHTMLWrt.m_eDestEnc, - &rHTMLWrt.m_aNonConvertableCharacters) - .WriteCharPtr("\">"); + HTMLOutFuncs::Out_String(rWrt.Strm(), aNames) + .WriteOString("\">"); } else { - OString sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font " " + OString sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font " " OOO_STRING_SVTOOLS_HTML_O_face "=\""; rWrt.Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aNames, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ) - .WriteCharPtr( "\">" ); + HTMLOutFuncs::Out_String( rWrt.Strm(), aNames ) + .WriteOString( "\">" ); } } else { - if (rHTMLWrt.mbXHTML) + if (rWrt.mbXHTML) HTMLOutFuncs::Out_AsciiTag( - rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false); + rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false); else - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font), false ); } return rWrt; } -static Writer& OutHTML_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SvxFontHeight( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; - if (IgnorePropertyForReqIF(rHTMLWrt.mbReqIF, "font-size", "")) + if (IgnorePropertyForReqIF(rWrt.mbReqIF, "font-size", "")) { return rWrt; } - if( rHTMLWrt.m_bTagOn ) + if( rWrt.m_bTagOn ) { - if (rHTMLWrt.mbXHTML) + if (rWrt.mbXHTML) { - OString sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span; + OString sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span; sal_uInt32 nHeight = static_cast<const SvxFontHeightItem&>(rHt).GetHeight(); // Twips -> points. @@ -2753,15 +2822,15 @@ static Writer& OutHTML_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt ) } else { - OString sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font; + OString sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font; sal_uInt32 nHeight = static_cast<const SvxFontHeightItem&>(rHt).GetHeight(); - sal_uInt16 nSize = rHTMLWrt.GetHTMLFontSize( nHeight ); + sal_uInt16 nSize = rWrt.GetHTMLFontSize( nHeight ); sOut += " " OOO_STRING_SVTOOLS_HTML_O_size "=\"" + OString::number(static_cast<sal_Int32>(nSize)) + "\""; rWrt.Strm().WriteOString( sOut ); - if( rHTMLWrt.m_bCfgOutStyles && rHTMLWrt.m_bTextAttr ) + if( rWrt.m_bCfgOutStyles && rWrt.m_bTextAttr ) { // always export font size as CSS option, too OutCSS1_HintStyleOpt( rWrt, rHt ); @@ -2771,52 +2840,50 @@ static Writer& OutHTML_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt ) } else { - if (rHTMLWrt.mbXHTML) + if (rWrt.mbXHTML) HTMLOutFuncs::Out_AsciiTag( - rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false); + rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false); else - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_font), false ); } return rWrt; } -static Writer& OutHTML_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SvxLanguage( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; LanguageType eLang = static_cast<const SvxLanguageItem &>(rHt).GetLanguage(); if( LANGUAGE_DONTKNOW == eLang ) return rWrt; - if( rHTMLWrt.m_bTagOn ) + if( rWrt.m_bTagOn ) { - OString sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span; + OString sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span; rWrt.Strm().WriteOString( sOut ); - rHTMLWrt.OutLanguage( static_cast<const SvxLanguageItem &>(rHt).GetLanguage() ); + rWrt.OutLanguage( static_cast<const SvxLanguageItem &>(rHt).GetLanguage() ); rWrt.Strm().WriteChar( '>' ); } else { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false ); } return rWrt; } -static Writer& OutHTML_SwWeight( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SwWeight( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; const FontWeight nBold = static_cast<const SvxWeightItem&>(rHt).GetWeight(); if( WEIGHT_BOLD == nBold ) { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_bold, rHTMLWrt.m_bTagOn ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_bold), rWrt.m_bTagOn ); } - else if( rHTMLWrt.m_bCfgOutStyles && rHTMLWrt.m_bTextAttr ) + else if( rWrt.m_bCfgOutStyles && rWrt.m_bTextAttr ) { // maybe as CSS1 attribute ? OutCSS1_HintSpanTag( rWrt, rHt ); @@ -2825,19 +2892,18 @@ static Writer& OutHTML_SwWeight( Writer& rWrt, const SfxPoolItem& rHt ) return rWrt; } -static Writer& OutHTML_SwCrossedOut( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SwCrossedOut( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; // Because of Netscape, we output STRIKE and not S! const FontStrikeout nStrike = static_cast<const SvxCrossedOutItem&>(rHt).GetStrikeout(); - if( STRIKEOUT_NONE != nStrike && !rHTMLWrt.mbReqIF ) + if( STRIKEOUT_NONE != nStrike && !rWrt.mbReqIF ) { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_strike, rHTMLWrt.m_bTagOn ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_strike), rWrt.m_bTagOn ); } - else if( rHTMLWrt.m_bCfgOutStyles && rHTMLWrt.m_bTextAttr ) + else if( rWrt.m_bCfgOutStyles && rWrt.m_bTextAttr ) { // maybe as CSS1 attribute? OutCSS1_HintSpanTag( rWrt, rHt ); @@ -2846,10 +2912,9 @@ static Writer& OutHTML_SwCrossedOut( Writer& rWrt, const SfxPoolItem& rHt ) return rWrt; } -static Writer& OutHTML_SvxEscapement( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SvxEscapement( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; const SvxEscapement eEscape = @@ -2857,17 +2922,17 @@ static Writer& OutHTML_SvxEscapement( Writer& rWrt, const SfxPoolItem& rHt ) OString aTag; switch( eEscape ) { - case SvxEscapement::Superscript: aTag = OOO_STRING_SVTOOLS_HTML_superscript; break; - case SvxEscapement::Subscript: aTag = OOO_STRING_SVTOOLS_HTML_subscript; break; + case SvxEscapement::Superscript: aTag = OOO_STRING_SVTOOLS_HTML_superscript ""_ostr; break; + case SvxEscapement::Subscript: aTag = OOO_STRING_SVTOOLS_HTML_subscript ""_ostr; break; default: ; } if( !aTag.isEmpty() ) { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + aTag, rHTMLWrt.m_bTagOn ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), rWrt.m_bTagOn ); } - else if( rHTMLWrt.m_bCfgOutStyles && rHTMLWrt.m_bTextAttr ) + else if( rWrt.m_bCfgOutStyles && rWrt.m_bTextAttr ) { // maybe as CSS1 attribute? OutCSS1_HintSpanTag( rWrt, rHt ); @@ -2876,18 +2941,17 @@ static Writer& OutHTML_SvxEscapement( Writer& rWrt, const SfxPoolItem& rHt ) return rWrt; } -static Writer& OutHTML_SwUnderline( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SwUnderline( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; const FontLineStyle eUnder = static_cast<const SvxUnderlineItem&>(rHt).GetLineStyle(); - if( LINESTYLE_NONE != eUnder && !rHTMLWrt.mbReqIF ) + if( LINESTYLE_NONE != eUnder && !rWrt.mbReqIF ) { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_underline, rHTMLWrt.m_bTagOn ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_underline), rWrt.m_bTagOn ); } - else if( rHTMLWrt.m_bCfgOutStyles && rHTMLWrt.m_bTextAttr ) + else if( rWrt.m_bCfgOutStyles && rWrt.m_bTextAttr ) { // maybe as CSS1 attribute? OutCSS1_HintSpanTag( rWrt, rHt ); @@ -2896,34 +2960,31 @@ static Writer& OutHTML_SwUnderline( Writer& rWrt, const SfxPoolItem& rHt ) return rWrt; } -static Writer& OutHTML_SwFlyCnt( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SwFlyCnt( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); const SwFormatFlyCnt& rFlyCnt = static_cast<const SwFormatFlyCnt&>(rHt); const SwFrameFormat& rFormat = *rFlyCnt.GetFrameFormat(); const SdrObject *pSdrObj = nullptr; - SwHTMLFrameType eType = - static_cast<SwHTMLFrameType>(rHTMLWrt.GuessFrameType( rFormat, pSdrObj )); - AllHtmlFlags nMode = aHTMLOutFrameAsCharTable[eType][rHTMLWrt.m_nExportMode]; - rHTMLWrt.OutFrameFormat( nMode, rFormat, pSdrObj ); + SwHTMLFrameType eType = rWrt.GuessFrameType( rFormat, pSdrObj ); + AllHtmlFlags nMode = getHTMLOutFrameAsCharTable(eType, rWrt.m_nExportMode); + rWrt.OutFrameFormat( nMode, rFormat, pSdrObj ); return rWrt; } // This is now our Blink item. Blinking is activated by setting the item to // true! -static Writer& OutHTML_SwBlink( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SwBlink( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; if( static_cast<const SvxBlinkItem&>(rHt).GetValue() ) { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_blink, rHTMLWrt.m_bTagOn ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_blink), rWrt.m_bTagOn ); } - else if( rHTMLWrt.m_bCfgOutStyles && rHTMLWrt.m_bTextAttr ) + else if( rWrt.m_bCfgOutStyles && rWrt.m_bTextAttr ) { // maybe as CSS1 attribute? OutCSS1_HintSpanTag( rWrt, rHt ); @@ -2932,10 +2993,8 @@ static Writer& OutHTML_SwBlink( Writer& rWrt, const SfxPoolItem& rHt ) return rWrt; } -Writer& OutHTML_INetFormat( Writer& rWrt, const SwFormatINetFormat& rINetFormat, bool bOn ) +SwHTMLWriter& OutHTML_INetFormat( SwHTMLWriter& rWrt, const SwFormatINetFormat& rINetFormat, bool bOn ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - OUString aURL( rINetFormat.GetValue() ); const SvxMacroTableDtor *pMacTable = rINetFormat.GetMacroTable(); bool bEvents = pMacTable != nullptr && !pMacTable->empty(); @@ -2947,19 +3006,19 @@ Writer& OutHTML_INetFormat( Writer& rWrt, const SwFormatINetFormat& rINetFormat, // bOn controls if we are writing the opening or closing tag if( !bOn ) { - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor), false ); return rWrt; } - OString sOut("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor); + OString sOut("<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor); bool bScriptDependent = false; { const SwCharFormat* pFormat = rWrt.m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_INET_NORMAL ); std::unique_ptr<SwHTMLFormatInfo> pFormatInfo(new SwHTMLFormatInfo(pFormat)); - auto const it = rHTMLWrt.m_CharFormatInfos.find( pFormatInfo ); - if (it != rHTMLWrt.m_CharFormatInfos.end()) + auto const it = rWrt.m_CharFormatInfos.find( pFormatInfo ); + if (it != rWrt.m_CharFormatInfos.end()) { bScriptDependent = (*it)->bScriptDependent; } @@ -2969,8 +3028,8 @@ Writer& OutHTML_INetFormat( Writer& rWrt, const SwFormatINetFormat& rINetFormat, const SwCharFormat* pFormat = rWrt.m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_INET_VISIT ); std::unique_ptr<SwHTMLFormatInfo> pFormatInfo(new SwHTMLFormatInfo(pFormat)); - auto const it = rHTMLWrt.m_CharFormatInfos.find( pFormatInfo ); - if (it != rHTMLWrt.m_CharFormatInfos.end()) + auto const it = rWrt.m_CharFormatInfos.find( pFormatInfo ); + if (it != rWrt.m_CharFormatInfos.end()) { bScriptDependent = (*it)->bScriptDependent; } @@ -2980,7 +3039,7 @@ Writer& OutHTML_INetFormat( Writer& rWrt, const SwFormatINetFormat& rINetFormat, { sOut += " " OOO_STRING_SVTOOLS_HTML_O_class "=\""; const char* pStr = nullptr; - switch( rHTMLWrt.m_nCSS1Script ) + switch( rWrt.m_nCSS1Script ) { case CSS1_OUTMODE_WESTERN: pStr = "western"; @@ -2992,11 +3051,11 @@ Writer& OutHTML_INetFormat( Writer& rWrt, const SwFormatINetFormat& rINetFormat, pStr = "ctl"; break; } - sOut += pStr + OStringLiteral("\""); + sOut += pStr + OString::Concat("\""); } rWrt.Strm().WriteOString( sOut ); - sOut = ""; + sOut = ""_ostr; OUString sRel; @@ -3013,17 +3072,16 @@ Writer& OutHTML_INetFormat( Writer& rWrt, const SwFormatINetFormat& rINetFormat, sOut += " " OOO_STRING_SVTOOLS_HTML_O_href "=\""; rWrt.Strm().WriteOString( sOut ); - rHTMLWrt.OutHyperlinkHRefValue( aURL ); - sOut = "\""; + rWrt.OutHyperlinkHRefValue( aURL ); + sOut = "\""_ostr; } if( !rINetFormat.GetName().isEmpty() ) { sOut += " " OOO_STRING_SVTOOLS_HTML_O_name "=\""; rWrt.Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( rWrt.Strm(), rINetFormat.GetName(), - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( rWrt.Strm(), rINetFormat.GetName() ); + sOut = "\""_ostr; } const OUString& rTarget = rINetFormat.GetTargetFrame(); @@ -3031,8 +3089,8 @@ Writer& OutHTML_INetFormat( Writer& rWrt, const SwFormatINetFormat& rINetFormat, { sOut += " " OOO_STRING_SVTOOLS_HTML_O_target "=\""; rWrt.Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( rWrt.Strm(), rTarget, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( rWrt.Strm(), rTarget ); + sOut = "\""_ostr; } if( !sRel.isEmpty() ) @@ -3043,29 +3101,26 @@ Writer& OutHTML_INetFormat( Writer& rWrt, const SwFormatINetFormat& rINetFormat, if( bEvents ) HTMLOutFuncs::Out_Events( rWrt.Strm(), *pMacTable, aAnchorEventTable, - rHTMLWrt.m_bCfgStarBasic, rHTMLWrt.m_eDestEnc, - &rHTMLWrt.m_aNonConvertableCharacters ); - rWrt.Strm().WriteCharPtr( ">" ); + rWrt.m_bCfgStarBasic ); + rWrt.Strm().WriteOString( ">" ); return rWrt; } -static Writer& OutHTML_SwFormatINetFormat( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SwFormatINetFormat( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; const SwFormatINetFormat& rINetFormat = static_cast<const SwFormatINetFormat&>(rHt); - if( rHTMLWrt.m_bTagOn ) + if( rWrt.m_bTagOn ) { // if necessary, temporarily close an attribute that is still open - if( !rHTMLWrt.m_aINetFormats.empty() ) + if( !rWrt.m_aINetFormats.empty() ) { SwFormatINetFormat *pINetFormat = - rHTMLWrt.m_aINetFormats.back(); + rWrt.m_aINetFormats.back(); OutHTML_INetFormat( rWrt, *pINetFormat, false ); } @@ -3074,25 +3129,25 @@ static Writer& OutHTML_SwFormatINetFormat( Writer& rWrt, const SfxPoolItem& rHt // and remember it SwFormatINetFormat *pINetFormat = new SwFormatINetFormat( rINetFormat ); - rHTMLWrt.m_aINetFormats.push_back( pINetFormat ); + rWrt.m_aINetFormats.push_back( pINetFormat ); } else { OutHTML_INetFormat( rWrt, rINetFormat, false ); - OSL_ENSURE( rHTMLWrt.m_aINetFormats.size(), "there must be a URL attribute missing" ); - if( !rHTMLWrt.m_aINetFormats.empty() ) + OSL_ENSURE( rWrt.m_aINetFormats.size(), "there must be a URL attribute missing" ); + if( !rWrt.m_aINetFormats.empty() ) { // get its own attribute from the stack - SwFormatINetFormat *pINetFormat = rHTMLWrt.m_aINetFormats.back(); - rHTMLWrt.m_aINetFormats.pop_back(); + SwFormatINetFormat *pINetFormat = rWrt.m_aINetFormats.back(); + rWrt.m_aINetFormats.pop_back(); delete pINetFormat; } - if( !rHTMLWrt.m_aINetFormats.empty() ) + if( !rWrt.m_aINetFormats.empty() ) { // there is still an attribute on the stack that must be reopened - SwFormatINetFormat *pINetFormat = rHTMLWrt.m_aINetFormats.back(); + SwFormatINetFormat *pINetFormat = rWrt.m_aINetFormats.back(); OutHTML_INetFormat( rWrt, *pINetFormat, true ); } } @@ -3100,10 +3155,9 @@ static Writer& OutHTML_SwFormatINetFormat( Writer& rWrt, const SfxPoolItem& rHt return rWrt; } -static Writer& OutHTML_SwTextCharFormat( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SwTextCharFormat( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( rHTMLWrt.m_bOutOpts ) + if( rWrt.m_bOutOpts ) return rWrt; const SwFormatCharFormat& rChrFormat = static_cast<const SwFormatCharFormat&>(rHt); @@ -3115,22 +3169,22 @@ static Writer& OutHTML_SwTextCharFormat( Writer& rWrt, const SfxPoolItem& rHt ) } std::unique_ptr<SwHTMLFormatInfo> pTmpInfo(new SwHTMLFormatInfo(pFormat)); - SwHTMLFormatInfos::const_iterator it = rHTMLWrt.m_CharFormatInfos.find(pTmpInfo); - if (it == rHTMLWrt.m_CharFormatInfos.end()) + SwHTMLFormatInfos::const_iterator it = rWrt.m_CharFormatInfos.find(pTmpInfo); + if (it == rWrt.m_CharFormatInfos.end()) return rWrt; const SwHTMLFormatInfo *pFormatInfo = it->get(); OSL_ENSURE( pFormatInfo, "Why is there no information about the character style?" ); - if( rHTMLWrt.m_bTagOn ) + if( rWrt.m_bTagOn ) { - OString sOut = "<" + rHTMLWrt.GetNamespace(); + OString sOut = "<" + rWrt.GetNamespace(); if( !pFormatInfo->aToken.isEmpty() ) sOut += pFormatInfo->aToken; else - sOut += OString(OOO_STRING_SVTOOLS_HTML_span); + sOut += OOO_STRING_SVTOOLS_HTML_span; - if( rHTMLWrt.m_bCfgOutStyles && + if( rWrt.m_bCfgOutStyles && (!pFormatInfo->aClass.isEmpty() || pFormatInfo->bScriptDependent) ) { sOut += " " OOO_STRING_SVTOOLS_HTML_O_class "=\""; @@ -3140,7 +3194,7 @@ static Writer& OutHTML_SwTextCharFormat( Writer& rWrt, const SfxPoolItem& rHt ) { if( !aClass.isEmpty() ) aClass += "-"; - switch( rHTMLWrt.m_nCSS1Script ) + switch( rWrt.m_nCSS1Script ) { case CSS1_OUTMODE_WESTERN: aClass += "western"; @@ -3153,9 +3207,8 @@ static Writer& OutHTML_SwTextCharFormat( Writer& rWrt, const SfxPoolItem& rHt ) break; } } - HTMLOutFuncs::Out_String( rWrt.Strm(), aClass, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( rWrt.Strm(), aClass ); + sOut = "\""_ostr; } sOut += ">"; rWrt.Strm().WriteOString( sOut ); @@ -3164,16 +3217,15 @@ static Writer& OutHTML_SwTextCharFormat( Writer& rWrt, const SfxPoolItem& rHt ) { OString aTag = !pFormatInfo->aToken.isEmpty() ? pFormatInfo->aToken.getStr() : OOO_STRING_SVTOOLS_HTML_span; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rHTMLWrt.GetNamespace() + aTag, false); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); } return rWrt; } -static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt ) +static SwHTMLWriter& OutHTML_SvxAdjust( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - if( !rHTMLWrt.m_bOutOpts || !rHTMLWrt.m_bTagOn ) + if( !rWrt.m_bOutOpts || !rWrt.m_bTagOn ) return rWrt; const SvxAdjustItem& rAdjust = static_cast<const SvxAdjustItem&>(rHt); @@ -3189,7 +3241,7 @@ static Writer& OutHTML_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt ) } if( pStr ) { - OString sOut = OStringLiteral(" " OOO_STRING_SVTOOLS_HTML_O_align "=\"") + + OString sOut = OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_align "=\"") + pStr + "\""; rWrt.Strm().WriteOString( sOut ); } @@ -3259,20 +3311,20 @@ SwAttrFnTab aHTMLAttrFnTab = { /* RES_TXTATR_CJK_RUBY */ nullptr, /* RES_TXTATR_UNKNOWN_CONTAINER */ nullptr, /* RES_TXTATR_INPUTFIELD */ OutHTML_SwFormatField, +/* RES_TXTATR_CONTENTCONTROL */ nullptr, /* RES_TXTATR_FIELD */ OutHTML_SwFormatField, /* RES_TXTATR_FLYCNT */ OutHTML_SwFlyCnt, /* RES_TXTATR_FTN */ OutHTML_SwFormatFootnote, /* RES_TXTATR_ANNOTATION */ OutHTML_SwFormatField, -/* RES_TXTATR_DUMMY3 */ nullptr, +/* RES_TXTATR_LINEBREAK */ OutHTML_SwFormatLineBreak, /* RES_TXTATR_DUMMY1 */ nullptr, // Dummy: -/* RES_TXTATR_DUMMY2 */ nullptr, // Dummy: /* RES_PARATR_LINESPACING */ nullptr, /* RES_PARATR_ADJUST */ OutHTML_SvxAdjust, /* RES_PARATR_SPLIT */ nullptr, -/* RES_PARATR_WIDOWS */ nullptr, /* RES_PARATR_ORPHANS */ nullptr, +/* RES_PARATR_WIDOWS */ nullptr, /* RES_PARATR_TABSTOP */ nullptr, /* RES_PARATR_HYPHENZONE*/ nullptr, /* RES_PARATR_DROP */ OutHTML_CSS1Attr, @@ -3297,6 +3349,12 @@ SwAttrFnTab aHTMLAttrFnTab = { /* RES_FILL_ORDER */ nullptr, /* RES_FRM_SIZE */ nullptr, /* RES_PAPER_BIN */ nullptr, +/* RES_MARGIN_FIRSTLINE */ nullptr, +/* RES_MARGIN_TEXTLEFT */ nullptr, +/* RES_MARGIN_RIGHT */ nullptr, +/* RES_MARGIN_LEFT */ nullptr, +/* RES_MARGIN_GUTTER */ nullptr, +/* RES_MARGIN_GUTTER_RIGHT */ nullptr, /* RES_LR_SPACE */ nullptr, /* RES_UL_SPACE */ nullptr, /* RES_PAGEDESC */ nullptr, @@ -3329,6 +3387,7 @@ SwAttrFnTab aHTMLAttrFnTab = { /* RES_FRAMEDIR */ nullptr, /* 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, @@ -3337,6 +3396,9 @@ SwAttrFnTab aHTMLAttrFnTab = { /* 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, @@ -3350,8 +3412,6 @@ SwAttrFnTab aHTMLAttrFnTab = { /* RES_GRFATR_INVERT */ nullptr, /* RES_GRFATR_TRANSPARENCY */ nullptr, /* RES_GRFATR_DRWAMODE */ nullptr, -/* RES_GRFATR_DUMMY1 */ nullptr, -/* RES_GRFATR_DUMMY2 */ nullptr, /* RES_GRFATR_DUMMY3 */ nullptr, /* RES_GRFATR_DUMMY4 */ nullptr, /* RES_GRFATR_DUMMY5 */ nullptr, diff --git a/sw/source/filter/html/htmlbas.cxx b/sw/source/filter/html/htmlbas.cxx index fecead1e542e..3500a631f108 100644 --- a/sw/source/filter/html/htmlbas.cxx +++ b/sw/source/filter/html/htmlbas.cxx @@ -189,7 +189,7 @@ void SwHTMLParser::AddScriptSource() if( nPos != -1 ) { m_aBasicLib = - aToken.copy( nPos + sizeof(OOO_STRING_SVTOOLS_HTML_SB_library) - 1 ); + aToken.subView( nPos + sizeof(OOO_STRING_SVTOOLS_HTML_SB_library) - 1 ); m_aBasicLib = comphelper::string::strip(m_aBasicLib, ' '); } } @@ -200,7 +200,7 @@ void SwHTMLParser::AddScriptSource() if( nPos != -1 ) { m_aBasicModule = - aToken.copy( nPos + sizeof(OOO_STRING_SVTOOLS_HTML_SB_module) - 1 ); + aToken.subView( nPos + sizeof(OOO_STRING_SVTOOLS_HTML_SB_module) - 1 ); m_aBasicModule = comphelper::string::strip(m_aBasicModule, ' '); } } @@ -284,16 +284,15 @@ void SwHTMLWriter::OutBasic(const SwHTMLWriter & rHTMLWrt) "=\"text/x-"; Strm().WriteOString( sOut ); // Entities aren't welcome here - Strm().WriteOString( OUStringToOString(sLang, m_eDestEnc) ) - .WriteCharPtr( "\">" ); + Strm().WriteOString( OUStringToOString(sLang, RTL_TEXTENCODING_UTF8) ) + .WriteOString( "\">" ); } const OUString& rModName = pModule->GetName(); - Strm().WriteCharPtr( SAL_NEWLINE_STRING ); // don't indent! + Strm().WriteOString( SAL_NEWLINE_STRING ); // don't indent! HTMLOutFuncs::OutScript( Strm(), GetBaseURL(), pModule->GetSource32(), sLang, STARBASIC, OUString(), - &rLibName, &rModName, - m_eDestEnc, &m_aNonConvertableCharacters ); + &rLibName, &rModName ); } } #endif @@ -325,7 +324,7 @@ void SwHTMLWriter::OutBasicBodyEvents() if( !aDocTable.empty() ) HTMLOutFuncs::Out_Events( Strm(), aDocTable, aBodyEventTable, - m_bCfgStarBasic, m_eDestEnc, &m_aNonConvertableCharacters ); + m_bCfgStarBasic ); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlcss1.cxx b/sw/source/filter/html/htmlcss1.cxx index 2560ef45bb8d..92e5d0d94d3a 100644 --- a/sw/source/filter/html/htmlcss1.cxx +++ b/sw/source/filter/html/htmlcss1.cxx @@ -34,6 +34,7 @@ #include <editeng/fontitem.hxx> #include <editeng/langitem.hxx> #include <editeng/frmdiritem.hxx> +#include <o3tl/string_view.hxx> #include <svtools/htmltokn.h> #include <svtools/htmlkywd.hxx> #include <fmtpdsc.hxx> @@ -178,14 +179,12 @@ bool SwCSS1Parser::SetFormatBreak( SfxItemSet& rItemSet, static void SetCharFormatAttrs( SwCharFormat *pCharFormat, SfxItemSet& rItemSet ) { - const SfxPoolItem *pItem; - static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONTSIZE,RES_CHRATR_CJK_FONTSIZE, + static const TypedWhichId<SvxFontHeightItem> aWhichIds[3] = { RES_CHRATR_FONTSIZE,RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CTL_FONTSIZE }; - for(sal_uInt16 i : aWhichIds) + for(auto const & i : aWhichIds) { - if( SfxItemState::SET == rItemSet.GetItemState( i, false, - &pItem ) && - static_cast<const SvxFontHeightItem *>(pItem)->GetProp() != 100) + const SvxFontHeightItem* pItem = rItemSet.GetItemIfSet( i, false ); + if( pItem && pItem->GetProp() != 100) { // percentage values at the FontHeight item aren't supported rItemSet.ClearItem( i ); @@ -194,19 +193,19 @@ static void SetCharFormatAttrs( SwCharFormat *pCharFormat, SfxItemSet& rItemSet pCharFormat->SetFormatAttr( rItemSet ); - if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) ) + if( const SvxBrushItem* pItem = rItemSet.GetItemIfSet( RES_BACKGROUND, false ) ) { // A Brush-Item with RES_BACKGROUND must be converted to one // with RES_CHRATR_BACKGROUND - SvxBrushItem aBrushItem( *static_cast<const SvxBrushItem *>(pItem) ); + SvxBrushItem aBrushItem( *pItem ); aBrushItem.SetWhich( RES_CHRATR_BACKGROUND ); pCharFormat->SetFormatAttr( aBrushItem ); } - if( SfxItemState::SET == rItemSet.GetItemState( RES_BOX, false, &pItem ) ) + if( const SvxBoxItem* pItem = rItemSet.GetItemIfSet( RES_BOX, false ) ) { - SvxBoxItem aBoxItem( *static_cast<const SvxBoxItem *>(pItem) ); + SvxBoxItem aBoxItem( *pItem ); aBoxItem.SetWhich( RES_CHRATR_BOX ); pCharFormat->SetFormatAttr( aBoxItem ); } @@ -269,39 +268,22 @@ static void SetTextCollAttrs( SwTextFormatColl *pColl, SfxItemSet& rItemSet, SwCSS1Parser *pCSS1Parser ) { const SfxItemSet& rCollItemSet = pColl->GetAttrSet(); - const SfxPoolItem *pCollItem, *pItem; - // left, right border and first line indentation - if( (rPropInfo.m_bLeftMargin || rPropInfo.m_bRightMargin || - rPropInfo.m_bTextIndent) && - (!rPropInfo.m_bLeftMargin || !rPropInfo.m_bRightMargin || - !rPropInfo.m_bTextIndent) && - SfxItemState::SET == rCollItemSet.GetItemState(RES_LR_SPACE,true,&pCollItem) && - SfxItemState::SET == rItemSet.GetItemState(RES_LR_SPACE,false,&pItem) ) - { - const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem); - - SvxLRSpaceItem aLRItem( *static_cast<const SvxLRSpaceItem *>(pCollItem) ); - if( rPropInfo.m_bLeftMargin ) - aLRItem.SetTextLeft( pLRItem->GetTextLeft() ); - if( rPropInfo.m_bRightMargin ) - aLRItem.SetRight( pLRItem->GetRight() ); - if( rPropInfo.m_bTextIndent ) - aLRItem.SetTextFirstLineOffset( pLRItem->GetTextFirstLineOffset() ); - - rItemSet.Put( aLRItem ); - } + // note: there was some SvxLRSpaceItem code here that was nonobvious + // but it looks like the only cases in which it would be required + // with split items are if some nProp != 100 or if SetAutoFirst() had + // been called (on the pColl items) but it looks like none of these are + // possible in HTML import. // top and bottom border + const SvxULSpaceItem* pCollULItem; + const SvxULSpaceItem* pULItem; if( (rPropInfo.m_bTopMargin || rPropInfo.m_bBottomMargin) && (!rPropInfo.m_bTopMargin || !rPropInfo.m_bBottomMargin) && - SfxItemState::SET == rCollItemSet.GetItemState(RES_UL_SPACE,true, - &pCollItem) && - SfxItemState::SET == rItemSet.GetItemState(RES_UL_SPACE,false,&pItem) ) + (pCollULItem = rCollItemSet.GetItemIfSet(RES_UL_SPACE)) && + (pULItem = rItemSet.GetItemIfSet(RES_UL_SPACE,false)) ) { - const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem); - - SvxULSpaceItem aULItem( *static_cast<const SvxULSpaceItem *>(pCollItem) ); + SvxULSpaceItem aULItem( *pCollULItem ); if( rPropInfo.m_bTopMargin ) aULItem.SetUpper( pULItem->GetUpper() ); if( rPropInfo.m_bBottomMargin ) @@ -310,13 +292,12 @@ static void SetTextCollAttrs( SwTextFormatColl *pColl, SfxItemSet& rItemSet, rItemSet.Put( aULItem ); } - static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONTSIZE,RES_CHRATR_CJK_FONTSIZE, + static const TypedWhichId<SvxFontHeightItem> aWhichIds[3] = { RES_CHRATR_FONTSIZE,RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CTL_FONTSIZE }; - for(sal_uInt16 i : aWhichIds) + for(auto const & i : aWhichIds) { - if( SfxItemState::SET == rItemSet.GetItemState( i, false, - &pItem ) && - static_cast<const SvxFontHeightItem *>(pItem)->GetProp() != 100) + const SvxFontHeightItem* pItem = rItemSet.GetItemIfSet( i, false ); + if( pItem && pItem->GetProp() != 100) { // percentage values at the FontHeight item aren't supported rItemSet.ClearItem( i ); @@ -385,28 +366,26 @@ void SwCSS1Parser::SetPageDescAttrs( const SvxBrushItem *pBrush, if( pItemSet2 ) { - const SfxPoolItem *pItem = nullptr; - if( SfxItemState::SET == pItemSet2->GetItemState( RES_BACKGROUND, false, - &pItem ) ) + if( const SvxBrushItem* pItem = pItemSet2->GetItemIfSet( RES_BACKGROUND, false ) ) { // set a background - aBrushItem.reset(static_cast<SvxBrushItem*>(pItem->Clone())); + aBrushItem.reset(pItem->Clone()); pItemSet2->ClearItem( RES_BACKGROUND ); bSetBrush = true; } - if( SfxItemState::SET == pItemSet2->GetItemState( RES_BOX, false, &pItem ) ) + if( const SvxBoxItem* pItem = pItemSet2->GetItemIfSet( RES_BOX, false ) ) { // set a border - aBoxItem.reset(static_cast<SvxBoxItem*>(pItem->Clone())); + aBoxItem.reset(pItem->Clone()); pItemSet2->ClearItem( RES_BOX ); bSetBox = true; } - if( SfxItemState::SET == pItemSet2->GetItemState( RES_FRAMEDIR, false, &pItem ) ) + if( const SvxFrameDirectionItem* pItem = pItemSet2->GetItemIfSet( RES_FRAMEDIR, false ) ) { // set a frame - aFrameDirItem.reset(static_cast<SvxFrameDirectionItem*>(pItem->Clone())); + aFrameDirItem.reset(pItem->Clone()); pItemSet2->ClearItem( RES_FRAMEDIR ); bSetFrameDir = true; } @@ -447,45 +426,65 @@ void SwCSS1Parser::SetPageDescAttrs( const SwPageDesc *pPageDesc, SwPageDesc aNewPageDesc( *pPageDesc ); SwFrameFormat &rMaster = aNewPageDesc.GetMaster(); const SfxItemSet& rPageItemSet = rMaster.GetAttrSet(); - const SfxPoolItem *pPageItem, *pItem; bool bChanged = false; // left, right border and first line indentation - if( (rPropInfo.m_bLeftMargin || rPropInfo.m_bRightMargin) && - SfxItemState::SET == rItemSet.GetItemState(RES_LR_SPACE,false,&pItem) ) + ::std::optional<SvxLRSpaceItem> oLRSpace; + assert(!rItemSet.GetItemIfSet(RES_LR_SPACE,false)); + if (rPropInfo.m_bLeftMargin) { - if( (!rPropInfo.m_bLeftMargin || !rPropInfo.m_bRightMargin) && - SfxItemState::SET == rPageItemSet.GetItemState(RES_LR_SPACE, - true,&pPageItem) ) + // note: parser never creates SvxLeftMarginItem! must be converted + if (SvxTextLeftMarginItem const*const pLeft = rItemSet.GetItemIfSet(RES_MARGIN_TEXTLEFT, false)) { - const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem); - - SvxLRSpaceItem aLRItem( *static_cast<const SvxLRSpaceItem *>(pPageItem) ); - if( rPropInfo.m_bLeftMargin ) - aLRItem.SetLeft( pLRItem->GetLeft() ); - if( rPropInfo.m_bRightMargin ) - aLRItem.SetRight( pLRItem->GetRight() ); - - rMaster.SetFormatAttr( aLRItem ); + if (!oLRSpace) + { + if (const SvxLRSpaceItem* pPageItem = rPageItemSet.GetItemIfSet(RES_LR_SPACE)) + { + oLRSpace.emplace(*pPageItem); + } + else + { + oLRSpace.emplace(RES_LR_SPACE); + } + } + oLRSpace->SetLeft(pLeft->GetTextLeft()); } - else + } + if (rPropInfo.m_bRightMargin) + { + // note: parser never creates SvxLeftMarginItem! must be converted + if (SvxRightMarginItem const*const pRight = rItemSet.GetItemIfSet(RES_MARGIN_RIGHT, false)) { - rMaster.SetFormatAttr( *pItem ); + if (!oLRSpace) + { + if (const SvxLRSpaceItem* pPageItem = rPageItemSet.GetItemIfSet(RES_LR_SPACE)) + { + oLRSpace.emplace(*pPageItem); + } + else + { + oLRSpace.emplace(RES_LR_SPACE); + } + } + oLRSpace->SetRight(pRight->GetRight()); } + } + if (oLRSpace) + { + rMaster.SetFormatAttr(*oLRSpace); bChanged = true; } // top and bottom border + const SvxULSpaceItem *pULItem; if( (rPropInfo.m_bTopMargin || rPropInfo.m_bBottomMargin) && - SfxItemState::SET == rItemSet.GetItemState(RES_UL_SPACE,false,&pItem) ) + (pULItem = rItemSet.GetItemIfSet(RES_UL_SPACE,false)) ) { + const SvxULSpaceItem* pPageItem; if( (!rPropInfo.m_bTopMargin || !rPropInfo.m_bBottomMargin) && - SfxItemState::SET == rPageItemSet.GetItemState(RES_UL_SPACE, - true,&pPageItem) ) + (pPageItem = rPageItemSet.GetItemIfSet(RES_UL_SPACE) ) ) { - const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem); - - SvxULSpaceItem aULItem( *static_cast<const SvxULSpaceItem *>(pPageItem) ); + SvxULSpaceItem aULItem( *pPageItem ); if( rPropInfo.m_bTopMargin ) aULItem.SetUpper( pULItem->GetUpper() ); if( rPropInfo.m_bBottomMargin ) @@ -495,7 +494,7 @@ void SwCSS1Parser::SetPageDescAttrs( const SwPageDesc *pPageDesc, } else { - rMaster.SetFormatAttr( *pItem ); + rMaster.SetFormatAttr( *pULItem ); } bChanged = true; } @@ -533,7 +532,7 @@ void SwCSS1Parser::SetPageDescAttrs( const SwPageDesc *pPageDesc, } // Is that possible? - if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) ) + if( const SvxBrushItem* pItem = rItemSet.GetItemIfSet( RES_BACKGROUND, false ) ) { // set a background rMaster.SetFormatAttr( *pItem ); @@ -800,12 +799,8 @@ void SwCSS1Parser::StyleParsed( const CSS1Selector *pSelector, // We must test the background before setting, because // in SetPageDescAttrs it will be deleted. - const SfxPoolItem *pItem; - if( SfxItemState::SET==rItemSet.GetItemState(RES_BACKGROUND,false,&pItem) ) + if( const SvxBrushItem *pBrushItem = rItemSet.GetItemIfSet(RES_BACKGROUND,false) ) { - const SvxBrushItem *pBrushItem = - static_cast<const SvxBrushItem *>(pItem); - /// Body has a background color, if it is not "no fill"/"auto fill" if( pBrushItem->GetColor() != COL_TRANSPARENT ) m_bBodyBGColorSet = true; @@ -992,11 +987,8 @@ void SwCSS1Parser::StyleParsed( const CSS1Selector *pSelector, if( !pNext ) { // set only the attributes at the style - const SfxPoolItem *pItem; - const SvxBoxItem *pBoxItem = nullptr; - if( SfxItemState::SET == - pColl->GetAttrSet().GetItemState(RES_BOX,true,&pItem) ) - pBoxItem = static_cast<const SvxBoxItem *>(pItem); + const SvxBoxItem *pBoxItem = + pColl->GetAttrSet().GetItemIfSet(RES_BOX); rPropInfo.SetBoxItem( rItemSet, MIN_BORDER_DIST, pBoxItem ); if( Css1ScriptFlags::AllMask == nScript && !pParentColl ) { @@ -1131,7 +1123,7 @@ SwCharFormat* SwCSS1Parser::GetChrFormat( HtmlTokenId nToken2, const OUString& r switch( nToken2 ) { case HtmlTokenId::EMPHASIS_ON: nPoolId = RES_POOLCHR_HTML_EMPHASIS; break; - case HtmlTokenId::CITIATION_ON: nPoolId = RES_POOLCHR_HTML_CITIATION; break; + case HtmlTokenId::CITATION_ON: nPoolId = RES_POOLCHR_HTML_CITATION; break; case HtmlTokenId::STRONG_ON: nPoolId = RES_POOLCHR_HTML_STRONG; break; case HtmlTokenId::CODE_ON: nPoolId = RES_POOLCHR_HTML_CODE; break; case HtmlTokenId::SAMPLE_ON: nPoolId = RES_POOLCHR_HTML_SAMPLE; break; @@ -1468,10 +1460,9 @@ void SwCSS1Parser::FillDropCap( SwFormatDrop& rDrop, // the number of lines matches somehow a percentage value // for the height (what happens with absolute heights???) sal_uInt8 nLines = rDrop.GetLines(); - const SfxPoolItem *pItem; - if( SfxItemState::SET == rItemSet.GetItemState( RES_CHRATR_FONTSIZE, false, &pItem ) ) + if( const SvxFontHeightItem* pFontHeightItem = rItemSet.GetItemIfSet( RES_CHRATR_FONTSIZE, false ) ) { - sal_uInt16 nProp = static_cast<const SvxFontHeightItem *>(pItem)->GetProp(); + sal_uInt16 nProp = pFontHeightItem->GetProp(); nLines = static_cast<sal_uInt8>((nProp + 50) / 100); if( nLines < 1 ) nLines = 1; @@ -1496,12 +1487,13 @@ void SwCSS1Parser::FillDropCap( SwFormatDrop& rDrop, rDrop.GetLines() = nLines; // a right border becomes the spacing to text! - if( SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE, false, &pItem ) ) + if (const SvxRightMarginItem *const pRightMargin = rItemSet.GetItemIfSet(RES_MARGIN_RIGHT, false)) { - rDrop.GetDistance() = static_cast< sal_uInt16 >( - static_cast<const SvxLRSpaceItem *>(pItem)->GetRight() ); - rItemSet.ClearItem( RES_LR_SPACE ); + rDrop.GetDistance() = static_cast<sal_uInt16>(pRightMargin->GetRight()); + rItemSet.ClearItem(RES_MARGIN_RIGHT); } + rItemSet.ClearItem(RES_MARGIN_FIRSTLINE); + rItemSet.ClearItem(RES_MARGIN_TEXTLEFT); // for every other attribute create a character style if( !rItemSet.Count() ) @@ -1615,8 +1607,14 @@ HTMLAttr **SwHTMLParser::GetAttrTabEntry( sal_uInt16 nWhich ) ppAttr = &m_xAttrTab->pAdjust; break; - case RES_LR_SPACE: - ppAttr = &m_xAttrTab->pLRSpace; + case RES_MARGIN_FIRSTLINE: + ppAttr = &m_xAttrTab->pFirstLineIndent; + break; + case RES_MARGIN_TEXTLEFT: + ppAttr = &m_xAttrTab->pTextLeftMargin; + break; + case RES_MARGIN_RIGHT: + ppAttr = &m_xAttrTab->pRightMargin; break; case RES_UL_SPACE: ppAttr = &m_xAttrTab->pULSpace; @@ -1677,7 +1675,7 @@ void SwHTMLParser::NewStyle() } m_bIgnoreRawData = sType.getLength() && - !sType.getToken(0,';').equalsAscii(sCSS_mimetype); + !o3tl::equalsAscii(o3tl::getToken(sType, 0,';'), sCSS_mimetype); } void SwHTMLParser::EndStyle() @@ -1763,7 +1761,7 @@ void SwHTMLParser::InsertLink() if( !sHRef.isEmpty() && sRel.equalsIgnoreAsciiCase( "STYLESHEET" ) && ( sType.isEmpty() || - sType.getToken(0,';').equalsAscii(sCSS_mimetype) ) ) + o3tl::equalsAscii(o3tl::getToken(sType, 0,';'), sCSS_mimetype) ) ) { if( GetMedium() ) { @@ -1951,7 +1949,7 @@ void SwHTMLParser::SetAnchorAndAdjustment( const SvxCSS1PropertyInfo &rPropInfo, // Absolute positioned objects are page-bound, when they // aren't in a frame and otherwise frame-bound. const SwStartNode *pFlySttNd = - m_pPam->GetPoint()->nNode.GetNode().FindFlyStartNode(); + m_pPam->GetPoint()->GetNode().FindFlyStartNode(); if( pFlySttNd ) { aAnchor.SetType( RndStdIds::FLY_AT_FLY ); @@ -1991,7 +1989,7 @@ void SwHTMLParser::SetAnchorAndAdjustment( const SvxCSS1PropertyInfo &rPropInfo, // still empty and otherwise auto-bound. // Auto-bound frames for the time being inserted at the previous position // and later moved. - const sal_Int32 nContent = m_pPam->GetPoint()->nContent.GetIndex(); + const sal_Int32 nContent = m_pPam->GetPoint()->GetContentIndex(); if( nContent ) { aAnchor.SetType( RndStdIds::FLY_AT_CHAR ); @@ -2079,35 +2077,37 @@ void SwHTMLParser::SetFrameFormatAttrs( SfxItemSet &rItemSet, HtmlFrameFormatFlags nFlags, SfxItemSet &rFrameItemSet ) { - const SfxPoolItem *pItem; + const SvxBoxItem *pBoxItem; if( (nFlags & HtmlFrameFormatFlags::Box) && - SfxItemState::SET==rItemSet.GetItemState( RES_BOX, true, &pItem ) ) + (pBoxItem = rItemSet.GetItemIfSet( RES_BOX )) ) { if( nFlags & HtmlFrameFormatFlags::Padding ) { - SvxBoxItem aBoxItem( *static_cast<const SvxBoxItem *>(pItem) ); + SvxBoxItem aBoxItem( *pBoxItem ); // reset all 4 sides to 0 aBoxItem.SetAllDistances(0); rFrameItemSet.Put( aBoxItem ); } else { - rFrameItemSet.Put( *pItem ); + rFrameItemSet.Put( *pBoxItem ); } rItemSet.ClearItem( RES_BOX ); } + const SvxBrushItem* pBrushItem; if( (nFlags & HtmlFrameFormatFlags::Background) && - SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, true, &pItem ) ) + (pBrushItem = rItemSet.GetItemIfSet( RES_BACKGROUND )) ) { - rFrameItemSet.Put( *pItem ); + rFrameItemSet.Put( *pBrushItem ); rItemSet.ClearItem( RES_BACKGROUND ); } + const SvxFrameDirectionItem* pFrameDirectionItem; if( (nFlags & HtmlFrameFormatFlags::Direction) && - SfxItemState::SET==rItemSet.GetItemState( RES_FRAMEDIR, true, &pItem ) ) + (pFrameDirectionItem = rItemSet.GetItemIfSet( RES_FRAMEDIR )) ) { - rFrameItemSet.Put( *pItem ); + rFrameItemSet.Put( *pFrameDirectionItem ); rItemSet.ClearItem( RES_FRAMEDIR ); } } @@ -2196,8 +2196,8 @@ void SwHTMLParser::GetMarginsFromContextWithNumberBullet( sal_uInt16& nLeft, void SwHTMLParser::GetULSpaceFromContext( sal_uInt16& nUpper, sal_uInt16& nLower ) const { - sal_uInt16 nDfltColl = 0; - OUString aDfltClass; + sal_uInt16 nDefaultColl = 0; + OUString aDefaultClass; HTMLAttrContexts::size_type nPos = m_aContexts.size(); while( nPos > m_nContextStAttrMin ) @@ -2208,19 +2208,19 @@ void SwHTMLParser::GetULSpaceFromContext( sal_uInt16& nUpper, pCntxt->GetULSpace( nUpper, nLower ); return; } - else if( !nDfltColl ) + else if (!nDefaultColl) { - nDfltColl = pCntxt->GetDfltTextFormatColl(); - if( nDfltColl ) - aDfltClass = pCntxt->GetClass(); + nDefaultColl = pCntxt->GetDefaultTextFormatColl(); + if (nDefaultColl) + aDefaultClass = pCntxt->GetClass(); } } - if( !nDfltColl ) - nDfltColl = RES_POOLCOLL_TEXT; + if (!nDefaultColl) + nDefaultColl = RES_POOLCOLL_TEXT; const SwTextFormatColl *pColl = - m_pCSS1Parser->GetTextFormatColl( nDfltColl, aDfltClass ); + m_pCSS1Parser->GetTextFormatColl(nDefaultColl, aDefaultClass); const SvxULSpaceItem& rULSpace = pColl->GetULSpace(); nUpper = rULSpace.GetUpper(); nLower = rULSpace.GetLower(); @@ -2235,7 +2235,7 @@ void SwHTMLParser::EndContextAttrs( HTMLAttrContext *pContext ) { // Set the number of characters for DropCaps. If it's zero at the // end, the attribute is set to invalid and then isn't set from SetAttr. - sal_Int32 nChars = m_pPam->GetPoint()->nContent.GetIndex(); + sal_Int32 nChars = m_pPam->GetPoint()->GetContentIndex(); if( nChars < 1 ) pAttr->Invalidate(); else if( nChars > MAX_DROPCAP_CHARS ) @@ -2276,22 +2276,21 @@ static void lcl_swcss1_setEncoding( SwFormat& rFormat, rtl_TextEncoding eEnc ) return; const SfxItemSet& rItemSet = rFormat.GetAttrSet(); - static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, - RES_CHRATR_CTL_FONT }; - const SfxPoolItem *pItem; - for(sal_uInt16 i : aWhichIds) - { - if( SfxItemState::SET == rItemSet.GetItemState( i, false,&pItem ) ) - { - const SvxFontItem& rFont = *static_cast<const SvxFontItem *>(pItem); - if( RTL_TEXTENCODING_SYMBOL != rFont.GetCharSet() ) - { - SvxFontItem aFont( rFont.GetFamily(), rFont.GetFamilyName(), - rFont.GetStyleName(), rFont.GetPitch(), - eEnc, i); - rFormat.SetFormatAttr( aFont ); - } - } + static const TypedWhichId<SvxFontItem> aWhichIds[3] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, + RES_CHRATR_CTL_FONT }; + for (auto const & i : aWhichIds) + { + const SvxFontItem *pFontItem = rItemSet.GetItemIfSet(i, false); + if (!pFontItem) + continue; + if (RTL_TEXTENCODING_SYMBOL == pFontItem->GetCharSet()) + continue; + if (eEnc == pFontItem->GetCharSet()) + continue; + SvxFontItem aFont(pFontItem->GetFamily(), pFontItem->GetFamilyName(), + pFontItem->GetStyleName(), pFontItem->GetPitch(), + eEnc, i); + rFormat.SetFormatAttr(aFont); } } diff --git a/sw/source/filter/html/htmlctxt.cxx b/sw/source/filter/html/htmlctxt.cxx index 6be3cab727d1..0e87b83644f8 100644 --- a/sw/source/filter/html/htmlctxt.cxx +++ b/sw/source/filter/html/htmlctxt.cxx @@ -29,6 +29,7 @@ #include <svtools/htmltokn.h> #include <editeng/boxitem.hxx> #include <osl/diagnose.h> +#include <o3tl/string_view.hxx> #include <doc.hxx> #include <pam.hxx> @@ -39,72 +40,73 @@ #include "swhtml.hxx" #include <memory> +#include <utility> using namespace ::com::sun::star; class HTMLAttrContext_SaveDoc { - SwHTMLNumRuleInfo aNumRuleInfo; // Numbering for this environment + SwHTMLNumRuleInfo m_aNumRuleInfo; // Numbering for this environment std::unique_ptr<SwPosition> - pPos; // Jump back to here when leaving context + m_pPos; // Jump back to here when leaving context std::shared_ptr<HTMLAttrTable> - xAttrTab; // Valid attributes for the environment, + m_xAttrTab; // Valid attributes for the environment, // if attributes shouldn't be preserved - size_t nContextStMin; // Stack lower bound for the environment + size_t m_nContextStMin; // Stack lower bound for the environment // if stack needs to be protected - size_t nContextStAttrMin; // Stack lower bound for the environment + size_t m_nContextStAttrMin; // Stack lower bound for the environment // if the attributes shouldn't be preserved - bool bStripTrailingPara : 1; - bool bKeepNumRules : 1; - bool bFixHeaderDist : 1; - bool bFixFooterDist : 1; + bool m_bStripTrailingPara : 1; + bool m_bKeepNumRules : 1; + bool m_bFixHeaderDist : 1; + bool m_bFixFooterDist : 1; public: HTMLAttrContext_SaveDoc() : - nContextStMin( SIZE_MAX ), nContextStAttrMin( SIZE_MAX ), - bStripTrailingPara( false ), bKeepNumRules( false ), - bFixHeaderDist( false ), bFixFooterDist( false ) + m_nContextStMin( SIZE_MAX ), m_nContextStAttrMin( SIZE_MAX ), + m_bStripTrailingPara( false ), m_bKeepNumRules( false ), + m_bFixHeaderDist( false ), m_bFixFooterDist( false ) {} // The position is ours, so we need to create and delete it - void SetPos( const SwPosition& rPos ) { pPos.reset( new SwPosition(rPos) ); } - const SwPosition *GetPos() const { return pPos.get(); } + void SetPos( const SwPosition& rPos ) { m_pPos.reset( new SwPosition(rPos) ); } + const SwPosition *GetPos() const { return m_pPos.get(); } // The index isn't ours. So no creation or deletion - void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { aNumRuleInfo.Set(rInf); } - const SwHTMLNumRuleInfo& GetNumInfo() const { return aNumRuleInfo; } + void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { m_aNumRuleInfo.Set(rInf); } + const SwHTMLNumRuleInfo& GetNumInfo() const { return m_aNumRuleInfo; } std::shared_ptr<HTMLAttrTable> const & GetAttrTab(bool bCreate = false); - void SetContextStMin( size_t nMin ) { nContextStMin = nMin; } - size_t GetContextStMin() const { return nContextStMin; } + void SetContextStMin( size_t nMin ) { m_nContextStMin = nMin; } + size_t GetContextStMin() const { return m_nContextStMin; } - void SetContextStAttrMin( size_t nMin ) { nContextStAttrMin = nMin; } - size_t GetContextStAttrMin() const { return nContextStAttrMin; } + void SetContextStAttrMin( size_t nMin ) { m_nContextStAttrMin = nMin; } + size_t GetContextStAttrMin() const { return m_nContextStAttrMin; } - void SetStripTrailingPara( bool bSet ) { bStripTrailingPara = bSet; } - bool GetStripTrailingPara() const { return bStripTrailingPara; } + void SetStripTrailingPara( bool bSet ) { m_bStripTrailingPara = bSet; } + bool GetStripTrailingPara() const { return m_bStripTrailingPara; } - void SetKeepNumRules( bool bSet ) { bKeepNumRules = bSet; } - bool GetKeepNumRules() const { return bKeepNumRules; } + void SetKeepNumRules( bool bSet ) { m_bKeepNumRules = bSet; } + bool GetKeepNumRules() const { return m_bKeepNumRules; } - void SetFixHeaderDist( bool bSet ) { bFixHeaderDist = bSet; } - bool GetFixHeaderDist() const { return bFixHeaderDist; } + void SetFixHeaderDist( bool bSet ) { m_bFixHeaderDist = bSet; } + bool GetFixHeaderDist() const { return m_bFixHeaderDist; } - void SetFixFooterDist( bool bSet ) { bFixFooterDist = bSet; } - bool GetFixFooterDist() const { return bFixFooterDist; } + void SetFixFooterDist( bool bSet ) { m_bFixFooterDist = bSet; } + bool GetFixFooterDist() const { return m_bFixFooterDist; } }; std::shared_ptr<HTMLAttrTable> const & HTMLAttrContext_SaveDoc::GetAttrTab( bool bCreate ) { - if (!xAttrTab && bCreate) + if (!m_xAttrTab && bCreate) { - xAttrTab = std::make_shared<HTMLAttrTable>(); - memset(xAttrTab.get(), 0, sizeof(HTMLAttrTable)); + m_xAttrTab = std::make_shared<HTMLAttrTable>(); + memset(m_xAttrTab.get(), 0, sizeof(HTMLAttrTable)); } - return xAttrTab; + return m_xAttrTab; } HTMLAttrContext_SaveDoc *HTMLAttrContext::GetSaveDocContext( bool bCreate ) @@ -115,9 +117,9 @@ HTMLAttrContext_SaveDoc *HTMLAttrContext::GetSaveDocContext( bool bCreate ) return m_pSaveDocContext.get(); } -HTMLAttrContext::HTMLAttrContext( HtmlTokenId nTokn, sal_uInt16 nPoolId, const OUString& rClass, +HTMLAttrContext::HTMLAttrContext( HtmlTokenId nTokn, sal_uInt16 nPoolId, OUString aClass, bool bDfltColl ) : - m_aClass( rClass ), + m_aClass(std::move( aClass )), m_nToken( nTokn ), m_nTextFormatColl( nPoolId ), m_nLeftMargin( 0 ), @@ -177,14 +179,14 @@ void SwHTMLParser::SplitAttrTab( const SwPosition& rNewPos ) "Danger: there are non-final paragraph attributes"); m_aParaAttrs.clear(); - const SwNodeIndex* pOldEndPara = &m_pPam->GetPoint()->nNode; + const SwPosition* pOldEndPara = m_pPam->GetPoint(); #ifndef NDEBUG - auto const nOld(pOldEndPara->GetIndex()); + auto const nOld(pOldEndPara->GetNodeIndex()); #endif - sal_Int32 nOldEndCnt = m_pPam->GetPoint()->nContent.GetIndex(); + sal_Int32 nOldEndCnt = m_pPam->GetPoint()->GetContentIndex(); - const SwNodeIndex& rNewSttPara = rNewPos.nNode; - sal_Int32 nNewSttCnt = rNewPos.nContent.GetIndex(); + const SwPosition& rNewSttPara = rNewPos; + sal_Int32 nNewSttCnt = rNewPos.GetContentIndex(); bool bMoveBack = false; @@ -200,31 +202,31 @@ void SwHTMLParser::SplitAttrTab( const SwPosition& rNewPos ) sal_uInt16 nWhich = pAttr->m_pItem->Which(); if( !nOldEndCnt && RES_PARATR_BEGIN <= nWhich && - pAttr->GetSttParaIdx() < pOldEndPara->GetIndex() ) + pAttr->GetStartParagraphIdx() < pOldEndPara->GetNodeIndex() ) { // The attribute needs to be closed one content position beforehand if( !bMoveBack ) { bMoveBack = m_pPam->Move( fnMoveBackward ); - nOldEndCnt = m_pPam->GetPoint()->nContent.GetIndex(); + nOldEndCnt = m_pPam->GetPoint()->GetContentIndex(); } } else if( bMoveBack ) { m_pPam->Move( fnMoveForward ); - nOldEndCnt = m_pPam->GetPoint()->nContent.GetIndex(); + nOldEndCnt = m_pPam->GetPoint()->GetContentIndex(); bMoveBack = false; } if( (RES_PARATR_BEGIN <= nWhich && bMoveBack) || - pAttr->GetSttParaIdx() < pOldEndPara->GetIndex() || - (pAttr->GetSttPara() == *pOldEndPara && - pAttr->GetSttCnt() != nOldEndCnt) ) + pAttr->GetStartParagraphIdx() < pOldEndPara->GetNodeIndex() || + (pAttr->GetStartParagraph() == pOldEndPara->GetNode() && + pAttr->GetStartContent() != nOldEndCnt) ) { // The attribute needs to be set. Because we still need the original, since // pointers to the attribute still exists in the contexts, we need to clone it. // The next-list gets lost but the previous-list is preserved - HTMLAttr *pSetAttr = pAttr->Clone( *pOldEndPara, nOldEndCnt ); + HTMLAttr *pSetAttr = pAttr->Clone( pOldEndPara->GetNode(), nOldEndCnt ); if( pNext ) pNext->InsertPrev( pSetAttr ); @@ -252,8 +254,8 @@ void SwHTMLParser::SplitAttrTab( const SwPosition& rNewPos ) } // Set the start of the attribute - pAttr->m_nStartPara = rNewSttPara; - pAttr->m_nEndPara = rNewSttPara; + pAttr->m_nStartPara = rNewSttPara.GetNode(); + pAttr->m_nEndPara = rNewSttPara.GetNode(); pAttr->m_nStartContent = nNewSttCnt; pAttr->m_nEndContent = nNewSttCnt; pAttr->m_pPrev = nullptr; @@ -265,7 +267,7 @@ void SwHTMLParser::SplitAttrTab( const SwPosition& rNewPos ) if( bMoveBack ) m_pPam->Move( fnMoveForward ); - assert(m_pPam->GetPoint()->nNode.GetIndex() == nOld); + assert(m_pPam->GetPoint()->GetNodeIndex() == nOld); } void SwHTMLParser::SaveDocContext( HTMLAttrContext *pCntxt, @@ -399,7 +401,7 @@ void SwHTMLParser::EndContext( HTMLAttrContext *pContext ) // Add a paragraph break if needed if( AM_NONE != pContext->GetAppendMode() && - m_pPam->GetPoint()->nContent.GetIndex() ) + m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( pContext->GetAppendMode() ); // Restart PRE, LISTING and XMP environments @@ -476,8 +478,7 @@ bool SwHTMLParser::DoPositioning( SfxItemSet &rItemSet, // - there's a given width if( SwCSS1Parser::MayBePositioned( rPropInfo ) ) { - SfxItemSet aFrameItemSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs(aFrameItemSet ); @@ -501,13 +502,13 @@ bool SwHTMLParser::DoPositioning( SfxItemSet &rItemSet, return bRet; } -bool SwHTMLParser::CreateContainer( const OUString& rClass, +bool SwHTMLParser::CreateContainer( std::u16string_view rClass, SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, HTMLAttrContext *pContext ) { bool bRet = false; - if( rClass.equalsIgnoreAsciiCase( "sd-abs-pos" ) && + if( o3tl::equalsIgnoreAsciiCase( rClass, u"sd-abs-pos" ) && SwCSS1Parser::MayBePositioned( rPropInfo ) ) { // Container class @@ -535,7 +536,7 @@ void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet, bool bCharLvl ) { // Put together a DropCap attribute, if a "float:left" is before the first character - if( bCharLvl && !m_pPam->GetPoint()->nContent.GetIndex() && + if( bCharLvl && !m_pPam->GetPoint()->GetContentIndex() && SvxAdjust::Left == rPropInfo.m_eFloat ) { SwFormatDrop aDrop; @@ -564,18 +565,36 @@ void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet, SfxItemIter aIter( rItemSet ); + const SvxFirstLineIndentItem * pFirstLineItem(nullptr); + const SvxTextLeftMarginItem * pTextLeftMargin(nullptr); + const SvxRightMarginItem * pRightMargin(nullptr); + for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem()) { - HTMLAttr **ppAttr = nullptr; - switch( pItem->Which() ) { - case RES_LR_SPACE: + case RES_MARGIN_FIRSTLINE: + { + pFirstLineItem = static_cast<const SvxFirstLineIndentItem*>(pItem); + } + break; + case RES_MARGIN_TEXTLEFT: + { + pTextLeftMargin = static_cast<const SvxTextLeftMarginItem*>(pItem); + } + break; + case RES_MARGIN_RIGHT: + { + pRightMargin = static_cast<const SvxRightMarginItem*>(pItem); + } + break; + } + } + +#if 1 { // Paragraph indents need to be added and are generated for each paragraphs // (here for the first paragraph only, all the following in SetTextCollAttrs) - const SvxLRSpaceItem *pLRItem = - static_cast<const SvxLRSpaceItem *>(pItem); // Get old paragraph indents without the top context (that's the one we're editing) sal_uInt16 nOldLeft = 0, nOldRight = 0; @@ -597,7 +616,8 @@ void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet, if( rPropInfo.m_bLeftMargin ) { OSL_ENSURE( rPropInfo.m_nLeftMargin < 0 || - rPropInfo.m_nLeftMargin == pLRItem->GetTextLeft(), + !pTextLeftMargin || + rPropInfo.m_nLeftMargin == pTextLeftMargin->GetTextLeft(), "left margin does not match with item" ); if( rPropInfo.m_nLeftMargin < 0 && -rPropInfo.m_nLeftMargin > nOldLeft ) @@ -608,7 +628,8 @@ void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet, if( rPropInfo.m_bRightMargin ) { OSL_ENSURE( rPropInfo.m_nRightMargin < 0 || - rPropInfo.m_nRightMargin == pLRItem->GetRight(), + !pRightMargin || + rPropInfo.m_nRightMargin == pRightMargin->GetRight(), "right margin does not match with item" ); if( rPropInfo.m_nRightMargin < 0 && -rPropInfo.m_nRightMargin > nOldRight ) @@ -616,21 +637,32 @@ void SwHTMLParser::InsertAttrs( SfxItemSet &rItemSet, else nRight = nOldRight + static_cast< sal_uInt16 >(rPropInfo.m_nRightMargin); } - if( rPropInfo.m_bTextIndent ) - nIndent = pLRItem->GetTextFirstLineOffset(); + if (rPropInfo.m_bTextIndent && pFirstLineItem) + nIndent = pFirstLineItem->GetTextFirstLineOffset(); // Remember the value for the following paragraphs pContext->SetMargins( nLeft, nRight, nIndent ); // Set the attribute on the current paragraph - SvxLRSpaceItem aLRItem( *pLRItem ); - aLRItem.SetTextFirstLineOffset( nIndent ); - aLRItem.SetTextLeft( nLeft ); - aLRItem.SetRight( nRight ); - NewAttr(m_xAttrTab, &m_xAttrTab->pLRSpace, aLRItem); - EndAttr( m_xAttrTab->pLRSpace, false ); + SvxFirstLineIndentItem const firstLine(nIndent, RES_MARGIN_FIRSTLINE); + NewAttr(m_xAttrTab, &m_xAttrTab->pFirstLineIndent, firstLine); + EndAttr(m_xAttrTab->pFirstLineIndent, false); + SvxTextLeftMarginItem const leftMargin(nLeft, RES_MARGIN_TEXTLEFT); + NewAttr(m_xAttrTab, &m_xAttrTab->pTextLeftMargin, leftMargin); + EndAttr(m_xAttrTab->pTextLeftMargin, false); + SvxRightMarginItem const rightMargin(nRight, RES_MARGIN_RIGHT); + NewAttr(m_xAttrTab, &m_xAttrTab->pRightMargin, rightMargin); + EndAttr(m_xAttrTab->pRightMargin, false); } - break; +#endif + + SfxItemIter aIter2(rItemSet); + for (const SfxPoolItem* pItem = aIter2.GetCurItem(); pItem; pItem = aIter2.NextItem()) + { + HTMLAttr **ppAttr = nullptr; + + switch( pItem->Which() ) + { case RES_UL_SPACE: if( !rPropInfo.m_bTopMargin || !rPropInfo.m_bBottomMargin ) @@ -767,8 +799,8 @@ void SwHTMLParser::SplitPREListingXMP( HTMLAttrContext *pCntxt ) SfxItemSet *HTMLAttrContext::GetFrameItemSet( SwDoc *pCreateDoc ) { if( !m_pFrameItemSet && pCreateDoc ) - m_pFrameItemSet = std::make_unique<SfxItemSet>( pCreateDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + m_pFrameItemSet = std::make_unique<SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1>> + ( pCreateDoc->GetAttrPool() ); return m_pFrameItemSet.get(); } diff --git a/sw/source/filter/html/htmldrawreader.cxx b/sw/source/filter/html/htmldrawreader.cxx index 1f09a40cf09b..fdbc187348e9 100644 --- a/sw/source/filter/html/htmldrawreader.cxx +++ b/sw/source/filter/html/htmldrawreader.cxx @@ -38,6 +38,7 @@ #include <svl/itemiter.hxx> #include <svtools/htmltokn.h> #include <svtools/htmlkywd.hxx> +#include <osl/diagnose.h> #include <charatr.hxx> #include <drawdoc.hxx> @@ -81,41 +82,37 @@ void SwHTMLParser::InsertDrawObject( SdrObject* pNewDrawObj, // to the visible layer. pNewDrawObj->SetLayer( m_xDoc->getIDocumentDrawModelAccess().GetInvisibleHeavenId() ); - SfxItemSet aFrameSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( aFrameSet ); sal_uInt16 nLeftSpace = 0, nRightSpace = 0, nUpperSpace = 0, nLowerSpace = 0; - if( (rPixSpace.Width() || rPixSpace.Height()) && Application::GetDefaultDevice() ) + if( rPixSpace.Width() || rPixSpace.Height() ) { - Size aTwipSpc( rPixSpace.Width(), rPixSpace.Height() ); - aTwipSpc = - Application::GetDefaultDevice()->PixelToLogic( aTwipSpc, - MapMode(MapUnit::MapTwip) ); - nLeftSpace = nRightSpace = static_cast<sal_uInt16>(aTwipSpc.Width()); - nUpperSpace = nLowerSpace = static_cast<sal_uInt16>(aTwipSpc.Height()); + nLeftSpace = nRightSpace = o3tl::convert(rPixSpace.Width(), o3tl::Length::px, o3tl::Length::twip); + nUpperSpace = nLowerSpace = o3tl::convert(rPixSpace.Height(), o3tl::Length::px, o3tl::Length::twip); } // set left/right border - const SfxPoolItem *pItem; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_LR_SPACE, true, &pItem ) ) + // note: parser never creates SvxLeftMarginItem! must be converted + if (const SvxTextLeftMarginItem *const pLeft = rCSS1ItemSet.GetItemIfSet(RES_MARGIN_TEXTLEFT)) { - // maybe flatten the first line indentation - const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem); - SvxLRSpaceItem aLRItem( *pLRItem ); - aLRItem.SetTextFirstLineOffset( 0 ); if( rCSS1PropInfo.m_bLeftMargin ) { - nLeftSpace = static_cast< sal_uInt16 >(aLRItem.GetLeft()); + // should be SvxLeftMarginItem... "cast" it + nLeftSpace = static_cast<sal_uInt16>(pLeft->GetTextLeft()); rCSS1PropInfo.m_bLeftMargin = false; } + rCSS1ItemSet.ClearItem(RES_MARGIN_TEXTLEFT); + } + if (const SvxRightMarginItem *const pRight = rCSS1ItemSet.GetItemIfSet(RES_MARGIN_RIGHT)) + { if( rCSS1PropInfo.m_bRightMargin ) { - nRightSpace = static_cast< sal_uInt16 >(aLRItem.GetRight()); + nRightSpace = static_cast< sal_uInt16 >(pRight->GetRight()); rCSS1PropInfo.m_bRightMargin = false; } - rCSS1ItemSet.ClearItem( RES_LR_SPACE ); + rCSS1ItemSet.ClearItem(RES_MARGIN_RIGHT); } if( nLeftSpace || nRightSpace ) { @@ -126,10 +123,9 @@ void SwHTMLParser::InsertDrawObject( SdrObject* pNewDrawObj, } // set top/bottom border - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_UL_SPACE, true, &pItem ) ) + if( const SvxULSpaceItem* pULItem = rCSS1ItemSet.GetItemIfSet( RES_UL_SPACE ) ) { // maybe flatten the first line indentation - const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem); if( rCSS1PropInfo.m_bTopMargin ) { nUpperSpace = pULItem->GetUpper(); @@ -157,7 +153,7 @@ void SwHTMLParser::InsertDrawObject( SdrObject* pNewDrawObj, SVX_CSS1_LTYPE_TWIP == rCSS1PropInfo.m_eTopType ) { const SwStartNode *pFlySttNd = - m_pPam->GetPoint()->nNode.GetNode().FindFlyStartNode(); + m_pPam->GetPoint()->GetNode().FindFlyStartNode(); if( pFlySttNd ) { @@ -306,7 +302,7 @@ void SwHTMLParser::NewMarquee( HTMLTable *pCurTable ) break; case HtmlOptionId::SCROLLDELAY: - nDelay = static_cast<sal_uInt16>(rOption.GetNumber()); + nDelay = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::WIDTH: @@ -349,15 +345,15 @@ void SwHTMLParser::NewMarquee( HTMLTable *pCurTable ) // #i52858# - method name changed SwDrawModel* pModel = m_xDoc->getIDocumentDrawModelAccess().GetOrCreateDrawModel(); SdrPage* pPg = pModel->GetPage( 0 ); - m_pMarquee = SdrObjFactory::MakeNewObject( + m_pMarquee = static_cast<SdrTextObj*>(SdrObjFactory::MakeNewObject( *pModel, SdrInventor::Default, - OBJ_TEXT); + SdrObjKind::Text).get()); if( !m_pMarquee ) return; - pPg->InsertObject( m_pMarquee ); + pPg->InsertObject( m_pMarquee.get() ); if( !aId.isEmpty() ) InsertBookmark( aId ); @@ -367,11 +363,11 @@ void SwHTMLParser::NewMarquee( HTMLTable *pCurTable ) eAniDir = SdrTextAniDirection::Right; // re set the attributes needed for scrolling - sal_uInt16 const aWhichMap[] { XATTR_FILL_FIRST, XATTR_FILL_LAST, - SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST, - EE_CHAR_START, EE_CHAR_END, - 0 }; - SfxItemSet aItemSet( pModel->GetItemPool(), aWhichMap ); + SfxItemSetFixed< + XATTR_FILL_FIRST, XATTR_FILL_LAST, + SDRATTR_MISC_FIRST, SDRATTR_MISC_LAST, + EE_CHAR_START, EE_CHAR_END> + aItemSet( pModel->GetItemPool() ); aItemSet.Put( makeSdrTextAutoGrowWidthItem( false ) ); aItemSet.Put( makeSdrTextAutoGrowHeightItem( true ) ); aItemSet.Put( SdrTextAniKindItem( eAniKind ) ); @@ -409,7 +405,7 @@ void SwHTMLParser::NewMarquee( HTMLTable *pCurTable ) 0 }; SwTextNode const*const pTextNd = - m_pPam->GetPoint()->nNode.GetNode().GetTextNode(); + m_pPam->GetPoint()->GetNode().GetTextNode(); if( pTextNd ) { const SfxItemSet& rItemSet = pTextNd->GetAnyFormatColl().GetAttrSet(); @@ -454,10 +450,9 @@ void SwHTMLParser::NewMarquee( HTMLTable *pCurTable ) // now set the size Size aTwipSz( bPercentWidth ? 0 : nWidth, nHeight ); - if( (aTwipSz.Width() || aTwipSz.Height()) && Application::GetDefaultDevice() ) + if( aTwipSz.Width() || aTwipSz.Height() ) { - aTwipSz = Application::GetDefaultDevice() - ->PixelToLogic( aTwipSz, MapMode( MapUnit::MapTwip ) ); + aTwipSz = o3tl::convert(aTwipSz, o3tl::Length::px, o3tl::Length::twip); } if( SVX_CSS1_LTYPE_TWIP== aPropInfo.m_eWidthType ) @@ -511,7 +506,7 @@ void SwHTMLParser::NewMarquee( HTMLTable *pCurTable ) m_pMarquee->SetLogicRect( tools::Rectangle( 0, 0, aTwipSz.Width(), aTwipSz.Height() ) ); // and insert the object into the document - InsertDrawObject( m_pMarquee, aSpace, eVertOri, eHoriOri, aStyleItemSet, + InsertDrawObject( m_pMarquee.get(), aSpace, eVertOri, eHoriOri, aStyleItemSet, aPropInfo ); // Register the drawing object at the table. Is a little bit complicated, @@ -520,12 +515,12 @@ void SwHTMLParser::NewMarquee( HTMLTable *pCurTable ) // The global pTable also can't be used, because the marquee can also be // in a sub-table. if( pCurTable && bPercentWidth) - RegisterDrawObjectToTable( pCurTable, m_pMarquee, static_cast<sal_uInt8>(nWidth) ); + RegisterDrawObjectToTable( pCurTable, m_pMarquee.get(), static_cast<sal_uInt8>(nWidth) ); } void SwHTMLParser::EndMarquee() { - OSL_ENSURE( m_pMarquee && OBJ_TEXT==m_pMarquee->GetObjIdentifier(), + OSL_ENSURE( m_pMarquee && SdrObjKind::Text==m_pMarquee->GetObjIdentifier(), "no marquee or wrong type" ); if( m_bFixMarqueeWidth ) @@ -538,13 +533,13 @@ void SwHTMLParser::EndMarquee() } // insert the collected text - static_cast<SdrTextObj*>(m_pMarquee)->SetText( m_aContents ); + m_pMarquee->SetText( m_aContents ); m_pMarquee->SetMergedItemSetAndBroadcast( m_pMarquee->GetMergedItemSet() ); - if( m_bFixMarqueeWidth ) + if (m_bFixMarqueeWidth && !bFuzzing) { // adjust the size to the text - static_cast<SdrTextObj*>(m_pMarquee)->FitFrameToTextSize(); + m_pMarquee->FitFrameToTextSize(); } m_aContents.clear(); @@ -553,7 +548,7 @@ void SwHTMLParser::EndMarquee() void SwHTMLParser::InsertMarqueeText() { - OSL_ENSURE( m_pMarquee && OBJ_TEXT==m_pMarquee->GetObjIdentifier(), + OSL_ENSURE( m_pMarquee && SdrObjKind::Text==m_pMarquee->GetObjIdentifier(), "no marquee or wrong type" ); // append the current text part to the text @@ -562,10 +557,10 @@ void SwHTMLParser::InsertMarqueeText() void SwHTMLParser::ResizeDrawObject( SdrObject* pObj, SwTwips nWidth ) { - OSL_ENSURE( OBJ_TEXT==pObj->GetObjIdentifier(), + OSL_ENSURE( SdrObjKind::Text==pObj->GetObjIdentifier(), "no marquee or wrong type" ); - if( OBJ_TEXT!=pObj->GetObjIdentifier() ) + if( SdrObjKind::Text!=pObj->GetObjIdentifier() ) return; // the old size diff --git a/sw/source/filter/html/htmldrawwriter.cxx b/sw/source/filter/html/htmldrawwriter.cxx index d9ff363bda18..0ef2d2514a22 100644 --- a/sw/source/filter/html/htmldrawwriter.cxx +++ b/sw/source/filter/html/htmldrawwriter.cxx @@ -31,6 +31,7 @@ #include <svl/whiter.hxx> #include <svtools/htmlout.hxx> #include <svtools/htmlkywd.hxx> +#include <osl/diagnose.h> #include <rtl/strbuf.hxx> @@ -71,8 +72,7 @@ void SwHTMLWriter::GetEEAttrsFromDrwObj( SfxItemSet& rItemSet, while( nEEWhich ) { const SfxPoolItem *pEEItem; - bool bSet = SfxItemState::SET == rObjItemSet.GetItemState( nEEWhich, false, - &pEEItem ); + bool bSet = SfxItemState::SET == aIter.GetItemState( false, &pEEItem ); sal_uInt16 nSwWhich = 0; switch( nEEWhich ) @@ -100,7 +100,7 @@ void SwHTMLWriter::GetEEAttrsFromDrwObj( SfxItemSet& rItemSet, { // if the item isn't set we maybe take the default item if( !bSet ) - pEEItem = &rObjItemSet.GetPool()->GetDefaultItem(nEEWhich); + pEEItem = &rObjItemSet.GetPool()->GetUserOrPoolDefaultItem(nEEWhich); // now we clone the item with the which id of the writer rItemSet.Put( pEEItem->CloneSetWhich(nSwWhich) ); @@ -110,12 +110,10 @@ void SwHTMLWriter::GetEEAttrsFromDrwObj( SfxItemSet& rItemSet, } } -Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, +SwHTMLWriter& OutHTML_DrawFrameFormatAsMarquee( SwHTMLWriter& rWrt, const SwDrawFrameFormat& rFormat, const SdrObject& rSdrObject ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - OSL_ENSURE( rWrt.m_pDoc->getIDocumentDrawModelAccess().GetDrawModel(), "There is a Draw-Obj with no Draw-Model?" ); const SdrTextObj *pTextObj = static_cast<const SdrTextObj *>(&rSdrObject); @@ -126,8 +124,7 @@ Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, if( !pOutlinerParaObj ) return rWrt; - OStringBuffer sOut; - sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_marquee); + OStringBuffer sOut("<" OOO_STRING_SVTOOLS_HTML_marquee); // get attributes of the object const SfxItemSet& rItemSet = pTextObj->GetMergedItemSet(); @@ -151,8 +148,8 @@ Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, if( pStr ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_behavior). - append("=\"").append(pStr).append("\""); + sOut.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_behavior "=\"") + + pStr + "\""); } // DIRECTION @@ -168,21 +165,21 @@ Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, if( pStr ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_direction). - append("=\"").append(pStr).append("\""); + sOut.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_direction + "=\"") + pStr + "\""); } // LOOP sal_Int32 nCount = rItemSet.Get( SDRATTR_TEXT_ANICOUNT ).GetValue(); if( 0==nCount ) nCount = SdrTextAniKind::Slide==eAniKind ? 1 : -1; - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_loop).append("=\""). - append(nCount).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_loop "=\"" + + OString::number(nCount) + "\""); // SCROLLDELAY sal_uInt16 nDelay = rItemSet.Get( SDRATTR_TEXT_ANIDELAY ).GetValue(); - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_scrolldelay). - append("=\"").append(static_cast<sal_Int32>(nDelay)).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_scrolldelay + "=\"" + OString::number(nDelay) + "\""); // SCROLLAMOUNT sal_Int16 nAmount = rItemSet.Get( SDRATTR_TEXT_ANIAMOUNT ).GetValue(); @@ -190,16 +187,14 @@ Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, { nAmount = -nAmount; } - else if( nAmount && Application::GetDefaultDevice() ) + else { - nAmount = Application::GetDefaultDevice() - ->LogicToPixel( Size(nAmount,0), - MapMode(MapUnit::MapTwip) ).Width(); + nAmount = SwHTMLWriter::ToPixel(nAmount); } if( nAmount ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_scrollamount). - append("=\"").append(static_cast<sal_Int32>(nAmount)).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_scrollamount + "=\"" + OString::number(nAmount) + "\""); } Size aTwipSz( pTextObj->GetLogicRect().GetSize() ); @@ -229,14 +224,14 @@ Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, if( aPixelSz.Width() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_width). - append("=\"").append(static_cast<sal_Int32>(aPixelSz.Width())).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width + "=\"" + OString::number(aPixelSz.Width()) + "\""); } if( aPixelSz.Height() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_height). - append("=\"").append(static_cast<sal_Int32>(aPixelSz.Height())).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_height + "=\"" + OString::number(aPixelSz.Height()) + "\""); } } @@ -248,34 +243,37 @@ Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, const Color& rFillColor = rItemSet.Get(XATTR_FILLCOLOR).GetColorValue(); - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_bgcolor).append("="); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_bgcolor "="); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); HTMLOutFuncs::Out_Color( rWrt.Strm(), rFillColor ); } if (!sOut.isEmpty()) - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + { + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + } // and now ALIGN, HSPACE and VSPACE HtmlFrmOpts nFrameFlags = HTML_FRMOPTS_MARQUEE; - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) ) + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) ) nFrameFlags |= HTML_FRMOPTS_MARQUEE_CSS1; - OString aEndTags = rHTMLWrt.OutFrameFormatOptions(rFormat, OUString(), nFrameFlags); - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) ) - rHTMLWrt.OutCSS1_FrameFormatOptions( rFormat, nFrameFlags, &rSdrObject ); + OString aEndTags = rWrt.OutFrameFormatOptions(rFormat, u"", nFrameFlags); + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) ) + rWrt.OutCSS1_FrameFormatOptions( rFormat, nFrameFlags, &rSdrObject ); rWrt.Strm().WriteChar( '>' ); // What follows now is the counterpart of SdrTextObject::SetText() Outliner aOutliner(nullptr, OutlinerMode::TextObject); - aOutliner.SetUpdateMode( false ); + aOutliner.SetUpdateLayout( false ); aOutliner.SetText( *pOutlinerParaObj ); OUString aText( aOutliner.GetText( aOutliner.GetParagraph(0), aOutliner.GetParagraphCount() ) ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aText, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rWrt.Strm(), aText ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_marquee, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_marquee), false ); if( !aEndTags.isEmpty() ) rWrt.Strm().WriteOString( aEndTags ); diff --git a/sw/source/filter/html/htmlfld.cxx b/sw/source/filter/html/htmlfld.cxx index 989457ef6244..c1eff7ef7cb7 100644 --- a/sw/source/filter/html/htmlfld.cxx +++ b/sw/source/filter/html/htmlfld.cxx @@ -20,10 +20,12 @@ #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> #include <com/sun/star/document/XDocumentProperties.hpp> #include <com/sun/star/frame/XModel.hpp> +#include <o3tl/string_view.hxx> #include <osl/diagnose.h> #include <docsh.hxx> #include <IDocumentFieldsAccess.hxx> #include <svtools/htmltokn.h> +#include <svl/numformat.hxx> #include <svl/zforlist.hxx> #include <unotools/useroptions.hxx> #include <fmtfld.hxx> @@ -42,7 +44,7 @@ namespace { struct HTMLNumFormatTableEntry { - const char *pName; + std::string_view pName; NfIndexTableOffset eFormat; }; @@ -81,7 +83,7 @@ HTMLNumFormatTableEntry const aHTMLDateFieldFormatTable[] = { "MD", NF_DATE_DIN_MMDD }, { "YMD", NF_DATE_DIN_YYMMDD }, { "YYMD", NF_DATE_DIN_YYYYMMDD }, - { nullptr, NF_NUMERIC_START } + { {}, NF_NUMERIC_START } }; HTMLNumFormatTableEntry const aHTMLTimeFieldFormatTable[] = @@ -89,7 +91,7 @@ HTMLNumFormatTableEntry const aHTMLTimeFieldFormatTable[] = { "SYS", NF_TIME_HHMMSS }, { "SSMM24", NF_TIME_HHMM }, { "SSMM12", NF_TIME_HHMMAMPM }, - { nullptr, NF_NUMERIC_START } + { {}, NF_NUMERIC_START } }; HTMLOptionEnum<SvxNumType> const aHTMLPageNumFieldFormatTable[] = @@ -195,12 +197,12 @@ HTMLOptionEnum<SwFileNameFormat> const aHTMLFileNameFieldFormatTable[] = { nullptr, SwFileNameFormat(0) } }; -SvxNumType SwHTMLParser::GetNumType( const OUString& rStr, SvxNumType nDfltType ) +SvxNumType SwHTMLParser::GetNumType( std::u16string_view rStr, SvxNumType nDfltType ) { const HTMLOptionEnum<SvxNumType> *pOptEnums = aHTMLPageNumFieldFormatTable; while( pOptEnums->pName ) { - if( rStr.equalsIgnoreAsciiCaseAscii( pOptEnums->pName ) ) + if( o3tl::equalsIgnoreAsciiCase( rStr, pOptEnums->pName ) ) return pOptEnums->nValue; pOptEnums++; } @@ -353,7 +355,7 @@ void SwHTMLParser::NewField() if( pFormatOption ) { const OUString& rFormat = pFormatOption->GetString(); - for( int k = 0; pFormatTable[k].pName; ++k ) + for( int k = 0; !pFormatTable[k].pName.empty(); ++k ) { if( rFormat.equalsIgnoreAsciiCaseAscii( pFormatTable[k].pName ) ) { @@ -583,23 +585,23 @@ void SwHTMLParser::InsertFieldText() } } -void SwHTMLParser::InsertCommentText( const char *pTag ) +void SwHTMLParser::InsertCommentText( std::string_view pTag ) { bool bEmpty = m_aContents.isEmpty(); if( !bEmpty ) m_aContents += "\n"; m_aContents += aToken; - if( bEmpty && pTag ) + if( bEmpty && !pTag.empty() ) { - m_aContents = OUStringLiteral(u"HTML: <") + OUStringChar(*pTag) + ">" + m_aContents; + m_aContents = OUString::Concat("HTML: <") + OUString::createFromAscii(pTag) + ">" + m_aContents; } } -void SwHTMLParser::InsertComment( const OUString& rComment, const char *pTag ) +void SwHTMLParser::InsertComment( const OUString& rComment, std::string_view pTag ) { OUString aComment( rComment ); - if( pTag ) + if( !pTag.empty() ) { aComment += "</" + OUString::createFromAscii(pTag) + @@ -609,20 +611,20 @@ void SwHTMLParser::InsertComment( const OUString& rComment, const char *pTag ) // MIB 24.06.97: If a PostIt should be insert after a space, we // will insert before the space. Then there are less problems // during formatting. (bug #40483#) - const sal_Int32 nPos = m_pPam->GetPoint()->nContent.GetIndex(); - SwTextNode *pTextNd = m_pPam->GetNode().GetTextNode(); + const sal_Int32 nPos = m_pPam->GetPoint()->GetContentIndex(); + SwTextNode *pTextNd = m_pPam->GetPointNode().GetTextNode(); bool bMoveFwd = false; if (nPos>0 && pTextNd && (' ' == pTextNd->GetText()[nPos-1])) { bMoveFwd = true; - sal_uLong nNodeIdx = m_pPam->GetPoint()->nNode.GetIndex(); - const sal_Int32 nIdx = m_pPam->GetPoint()->nContent.GetIndex(); + SwNodeOffset nNodeIdx = m_pPam->GetPoint()->GetNodeIndex(); + const sal_Int32 nIdx = m_pPam->GetPoint()->GetContentIndex(); for( auto i = m_aSetAttrTab.size(); i > 0; ) { HTMLAttr *pAttr = m_aSetAttrTab[--i]; - if( pAttr->GetSttParaIdx() != nNodeIdx || - pAttr->GetSttCnt() != nIdx ) + if( pAttr->GetStartParagraphIdx() != nNodeIdx || + pAttr->GetStartContent() != nIdx ) break; if( RES_TXTATR_FIELD == pAttr->m_pItem->Which() && diff --git a/sw/source/filter/html/htmlfldw.cxx b/sw/source/filter/html/htmlfldw.cxx index 825d563a9f39..65f0d7167d2a 100644 --- a/sw/source/filter/html/htmlfldw.cxx +++ b/sw/source/filter/html/htmlfldw.cxx @@ -19,11 +19,16 @@ #include <com/sun/star/i18n/XBreakIterator.hpp> #include <comphelper/string.hxx> +#include <comphelper/xmlencode.hxx> #include <svtools/htmlkywd.hxx> #include <svtools/htmlout.hxx> #include <osl/diagnose.h> +#include <o3tl/string_view.hxx> #include <fmtfld.hxx> #include <doc.hxx> +#include <docsh.hxx> +#include <view.hxx> +#include <wrtsh.hxx> #include <breakit.hxx> #include <ndtxt.hxx> #include <txtfld.hxx> @@ -62,11 +67,9 @@ const char *SwHTMLWriter::GetNumFormat( sal_uInt16 nFormat ) return pFormatStr; } -static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, +static SwHTMLWriter& OutHTML_SwField( SwHTMLWriter& rWrt, const SwField* pField, const SwTextNode& rTextNd, sal_Int32 nFieldPos ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - const SwFieldType* pFieldTyp = pField->GetTyp(); SwFieldIds nField = pFieldTyp->Which(); sal_uLong nFormat = pField->GetFormat(); @@ -258,7 +261,7 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, } // ReqIF-XHTML doesn't allow <sdfield>. - if (rHTMLWrt.mbReqIF && pTypeStr) + if (rWrt.mbReqIF && pTypeStr) { pTypeStr = nullptr; } @@ -266,36 +269,37 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, // Output the <sdfield> tag. if( pTypeStr ) { - OStringBuffer sOut; - sOut.append('<'); - sOut.append(rHTMLWrt.GetNamespace()); - sOut.append(OOO_STRING_SVTOOLS_HTML_sdfield).append(' '). - append(OOO_STRING_SVTOOLS_HTML_O_type).append('='). - append(pTypeStr); + OStringBuffer sOut("<" + + rWrt.GetNamespace() + + OOO_STRING_SVTOOLS_HTML_sdfield + " " + OOO_STRING_SVTOOLS_HTML_O_type + "=" + + pTypeStr); if( pSubStr ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_subtype). - append('=').append(pSubStr); + sOut.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_subtype "=") + + pSubStr); } if( pFormatStr ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_format). - append('=').append(pFormatStr); + sOut.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_format "=") + + pFormatStr); } if( !aName.isEmpty() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_name). - append("=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_name "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), aName ); sOut.append('\"'); } if( !aValue.isEmpty() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_value). - append("=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_value "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), aValue ); sOut.append('\"'); } if( bNumFormat ) @@ -303,15 +307,15 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, OSL_ENSURE( nFormat, "number format is 0" ); sOut.append(HTMLOutFuncs::CreateTableDataOptionsValNum( bNumValue, dNumValue, nFormat, - *rHTMLWrt.m_pDoc->GetNumberFormatter(), rHTMLWrt.m_eDestEnc, - &rHTMLWrt.m_aNonConvertableCharacters)); + *rWrt.m_pDoc->GetNumberFormatter())); } if( bFixed ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_sdfixed); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_sdfixed); } sOut.append('>'); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); } // output content of the field @@ -325,7 +329,7 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, sal_uInt16 nScript = SwHTMLWriter::GetCSS1ScriptForScriptType( nScriptType ); - if( (nPos < sExpand.getLength() && nPos >= 0) || nScript != rHTMLWrt.m_nCSS1Script ) + if( (nPos < sExpand.getLength() && nPos >= 0) || nScript != rWrt.m_nCSS1Script ) { bNeedsCJKProcessing = true; } @@ -335,11 +339,11 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, { //sequence of (start, end) property ranges we want to //query - SfxItemSet aScriptItemSet( rWrt.m_pDoc->GetAttrPool(), - svl::Items<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE, - RES_CHRATR_POSTURE, RES_CHRATR_POSTURE, - RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT, - RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT>{} ); + SfxItemSetFixed<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE, + RES_CHRATR_POSTURE, RES_CHRATR_POSTURE, + RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT, + RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT> + aScriptItemSet( rWrt.m_pDoc->GetAttrPool() ); rTextNd.GetParaAttr(aScriptItemSet, nFieldPos, nFieldPos+1); sal_uInt16 aWesternWhichIds[4] = @@ -353,7 +357,7 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT }; sal_uInt16 *pRefWhichIds = nullptr; - switch( rHTMLWrt.m_nCSS1Script ) + switch( rWrt.m_nCSS1Script ) { case CSS1_OUTMODE_WESTERN: pRefWhichIds = aWesternWhichIds; @@ -376,7 +380,7 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, sExpand, nPos, nScriptType ); sal_Int32 nChunkLen = nEndPos - nPos; if( nScript != CSS1_OUTMODE_ANY_SCRIPT && - /* #108791# */ nScript != rHTMLWrt.m_nCSS1Script ) + /* #108791# */ nScript != rWrt.m_nCSS1Script ) { sal_uInt16 *pWhichIds = nullptr; switch( nScript ) @@ -386,7 +390,7 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, case CSS1_OUTMODE_CTL: pWhichIds = aCTLWhichIds; break; } - rHTMLWrt.m_bTagOn = true; + rWrt.m_bTagOn = true; const SfxPoolItem *aItems[5]; int nItems = 0; @@ -404,24 +408,22 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, !(0==i ? swhtml_css1atr_equalFontItems( *pRefItem, *pItem ) : *pRefItem == *pItem) ) { - Out( aHTMLAttrFnTab, *pItem, rHTMLWrt ); + Out( aHTMLAttrFnTab, *pItem, rWrt ); aItems[nItems++] = pItem; } } } - HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand.copy( nPos, nChunkLen ), - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand.subView( nPos, nChunkLen ) ); - rHTMLWrt.m_bTagOn = false; + rWrt.m_bTagOn = false; while( nItems ) - Out( aHTMLAttrFnTab, *aItems[--nItems], rHTMLWrt ); + Out( aHTMLAttrFnTab, *aItems[--nItems], rWrt ); } else { - HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand.copy( nPos, nChunkLen ), - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand.subView( nPos, nChunkLen ) ); } nPos = nEndPos; } @@ -429,20 +431,18 @@ static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField, } else { - HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand ); } // Output the closing tag. if( pTypeStr ) - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_sdfield, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_sdfield), false ); return rWrt; } -Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) +SwHTMLWriter& OutHTML_SwFormatField( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); const SwFormatField & rField = static_cast<const SwFormatField&>(rHt); const SwField* pField = rField.GetField(); const SwFieldType* pFieldTyp = pField->GetTyp(); @@ -461,7 +461,7 @@ Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) // TODO: HTML-Tags are written without entities, that for, characters // not contained in the destination encoding are lost! OString sTmp(OUStringToOString(rText, - static_cast<SwHTMLWriter&>(rWrt).m_eDestEnc)); + RTL_TEXTENCODING_UTF8)); rWrt.Strm().WriteOString( sTmp ).WriteChar( '>' ); } else if( SwFieldIds::Postit == pFieldTyp->Which() ) @@ -472,7 +472,7 @@ Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) bool bWritten = false; if( (rComment.getLength() >= 6 && rComment.startsWith("<") && rComment.endsWith(">") && - rComment.copy( 1, 4 ).equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_meta) ) || + o3tl::equalsIgnoreAsciiCase(rComment.subView( 1, 4 ), u"" OOO_STRING_SVTOOLS_HTML_meta) ) || (rComment.getLength() >= 7 && rComment.startsWith( "<!--" ) && rComment.endsWith( "-->" )) ) @@ -482,7 +482,7 @@ Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) // TODO: HTML-Tags are written without entities, that for, // characters not contained in the destination encoding are lost! OString sTmp(OUStringToOString(sComment, - static_cast<SwHTMLWriter&>(rWrt).m_eDestEnc)); + RTL_TEXTENCODING_UTF8)); rWrt.Strm().WriteOString( sTmp ); bWritten = true; } @@ -490,7 +490,7 @@ Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) rComment.endsWith(">") && rComment.startsWithIgnoreAsciiCase( "HTML:" ) ) { - OUString sComment(comphelper::string::stripStart(rComment.copy(5), ' ')); + OUString sComment(comphelper::string::stripStart(rComment.subView(5), ' ')); if( '<' == sComment[0] ) { sComment = convertLineEnd(sComment, GetSystemLineEnd()); @@ -498,7 +498,7 @@ Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) // characters not contained in the destination encoding are // lost! OString sTmp(OUStringToOString(sComment, - static_cast<SwHTMLWriter&>(rWrt).m_eDestEnc)); + RTL_TEXTENCODING_UTF8)); rWrt.Strm().WriteOString( sTmp ); bWritten = true; } @@ -512,15 +512,15 @@ Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) OString sOut = "<" OOO_STRING_SVTOOLS_HTML_comment " " + - OUStringToOString(sComment, static_cast<SwHTMLWriter&>(rWrt).m_eDestEnc) + + OUStringToOString(comphelper::string::encodeForXml(sComment), RTL_TEXTENCODING_UTF8) + " -->"; rWrt.Strm().WriteOString( sOut ); } } else if( SwFieldIds::Script == pFieldTyp->Which() ) { - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine( true ); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine( true ); bool bURL = static_cast<const SwScriptField *>(pField)->IsCodeURL(); const OUString& rType = pField->GetPar1(); @@ -533,39 +533,39 @@ Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) // otherwise is the script content itself. Since only JavaScript // is in fields, it must be JavaScript ...:) HTMLOutFuncs::OutScript( rWrt.Strm(), rWrt.GetBaseURL(), aContents, rType, JAVASCRIPT, - aURL, nullptr, nullptr, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + aURL, nullptr, nullptr ); - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine( true ); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine( true ); } else { const SwTextField *pTextField = rField.GetTextField(); OSL_ENSURE( pTextField, "Where is the txt fld?" ); - if( pTextField ) + if (pTextField && rWrt.m_pDoc->GetDocShell() && rWrt.m_pDoc->GetDocShell()->GetView()) { // ReqIF-XHTML doesn't allow specifying a background color. - bool bFieldShadings = SwViewOption::IsFieldShadings() && !rHTMLWrt.mbReqIF; + const SwViewOption* pViewOptions = rWrt.m_pDoc->GetDocShell()->GetView()->GetWrtShell().GetViewOptions(); + bool bFieldShadings = pViewOptions->IsFieldShadings() && !rWrt.mbReqIF; if (bFieldShadings) { // If there is a text portion background started already, that should have priority. - auto it = rHTMLWrt.maStartedAttributes.find(RES_CHRATR_BACKGROUND); - if (it != rHTMLWrt.maStartedAttributes.end()) + auto it = rWrt.maStartedAttributes.find(RES_CHRATR_BACKGROUND); + if (it != rWrt.maStartedAttributes.end()) bFieldShadings = it->second <= 0; } if (bFieldShadings) { - OStringBuffer sOut; - sOut.append("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span); - sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_style "=\""); - sOut.append(sCSS1_P_background); - sOut.append(": "); - - Color& rColor = SwViewOption::GetFieldShadingsColor(); - sOut.append(GetCSS1_Color(rColor)); - sOut.append("\">"); - rWrt.Strm().WriteOString(sOut.makeStringAndClear()); + const Color& rColor = pViewOptions->GetFieldShadingsColor(); + OString sOut( + "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span + " " OOO_STRING_SVTOOLS_HTML_O_style "=\"" + + sCSS1_P_background + + ": " + + GetCSS1_Color(rColor) + + "\">"); + rWrt.Strm().WriteOString(sOut); } OutHTML_SwField( rWrt, pField, pTextField->GetTextNode(), @@ -573,7 +573,7 @@ Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ) if (bFieldShadings) HTMLOutFuncs::Out_AsciiTag( - rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false); + rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false); } } return rWrt; diff --git a/sw/source/filter/html/htmlfly.cxx b/sw/source/filter/html/htmlfly.cxx index 771a449ec90a..c4fe7dfa1006 100644 --- a/sw/source/filter/html/htmlfly.cxx +++ b/sw/source/filter/html/htmlfly.cxx @@ -33,12 +33,12 @@ using namespace css; SwHTMLPosFlyFrame::SwHTMLPosFlyFrame( const SwPosFlyFrame& rPosFly, const SdrObject *pSdrObj, AllHtmlFlags nFlags ) : - pFrameFormat( &rPosFly.GetFormat() ), - pSdrObject( pSdrObj ), - pNdIdx( new SwNodeIndex( rPosFly.GetNdIndex() ) ), - nOrdNum( rPosFly.GetOrdNum() ), - nContentIdx( 0 ), - nAllFlags( nFlags ) + m_pFrameFormat( &rPosFly.GetFormat() ), + m_pSdrObject( pSdrObj ), + m_aNodeIndex( rPosFly.GetNode() ), + m_nOrdNum( rPosFly.GetOrdNum() ), + m_nContentIndex( 0 ), + m_nAllFlags( nFlags ) { const SwFormatAnchor& rAnchor = rPosFly.GetFormat().GetAnchor(); if ((RndStdIds::FLY_AT_CHAR != rAnchor.GetAnchorId()) || @@ -47,38 +47,38 @@ SwHTMLPosFlyFrame::SwHTMLPosFlyFrame( const SwPosFlyFrame& rPosFly, // Output of auto-bound frames will be a character farther back, // because then the position aligns with Netscape. - OSL_ENSURE( rAnchor.GetContentAnchor(), "No anchor position?" ); - if( !rAnchor.GetContentAnchor() ) + OSL_ENSURE( rAnchor.GetAnchorNode(), "No anchor position?" ); + if( !rAnchor.GetAnchorNode() ) return; - nContentIdx = rAnchor.GetContentAnchor()->nContent.GetIndex(); + m_nContentIndex = rAnchor.GetAnchorContentOffset(); sal_Int16 eHoriRel = rPosFly.GetFormat().GetHoriOrient(). GetRelationOrient(); if( text::RelOrientation::FRAME == eHoriRel || text::RelOrientation::PRINT_AREA == eHoriRel ) { - const SwContentNode *pCNd = pNdIdx->GetNode().GetContentNode(); + const SwContentNode *pCNd = m_aNodeIndex.GetNode().GetContentNode(); OSL_ENSURE( pCNd, "No Content-Node at PaM position" ); - if( pCNd && nContentIdx < pCNd->Len() ) - nContentIdx++; + if( pCNd && m_nContentIndex < pCNd->Len() ) + m_nContentIndex++; } } bool SwHTMLPosFlyFrame::operator<( const SwHTMLPosFlyFrame& rFrame ) const { - if( pNdIdx->GetIndex() == rFrame.pNdIdx->GetIndex() ) + if( m_aNodeIndex.GetIndex() == rFrame.m_aNodeIndex.GetIndex() ) { - if( nContentIdx == rFrame.nContentIdx ) + if( m_nContentIndex == rFrame.m_nContentIndex ) { if( GetOutPos() == rFrame.GetOutPos() ) - return nOrdNum < rFrame.nOrdNum; + return m_nOrdNum < rFrame.m_nOrdNum; else return GetOutPos() < rFrame.GetOutPos(); } else - return nContentIdx < rFrame.nContentIdx; + return m_nContentIndex < rFrame.m_nContentIndex; } else - return pNdIdx->GetIndex() < rFrame.pNdIdx->GetIndex(); + return m_aNodeIndex.GetIndex() < rFrame.m_aNodeIndex.GetIndex(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlfly.hxx b/sw/source/filter/html/htmlfly.hxx index 32b9d80aa65d..4038ac2a2dcf 100644 --- a/sw/source/filter/html/htmlfly.hxx +++ b/sw/source/filter/html/htmlfly.hxx @@ -17,15 +17,16 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ -#ifndef INCLUDED_SW_SOURCE_FILTER_HTML_HTMLFLY_HXX -#define INCLUDED_SW_SOURCE_FILTER_HTML_HTMLFLY_HXX +#pragma once #include <o3tl/sorted_vector.hxx> #include <o3tl/typed_flags_set.hxx> +#include <sal/types.h> +#include <ndindex.hxx> +#include <memory> class SdrObject; class SwFrameFormat; -class SwNodeIndex; class SwPosFlyFrame; // ATTENTION: The values of this enum are used directly in the output table!!! @@ -78,28 +79,26 @@ namespace o3tl { template<> struct typed_flags<HtmlContainerFlags> : is_typed_flags<HtmlContainerFlags, 0x03> {}; } -const sal_uInt16 MAX_FRMTYPES = HTML_FRMTYPE_END; -const sal_uInt16 MAX_BROWSERS = 4; - struct AllHtmlFlags { HtmlOut nOut; HtmlPosition nPosition; HtmlContainerFlags nContainer; }; -extern AllHtmlFlags const aHTMLOutFramePageFlyTable[MAX_FRMTYPES][MAX_BROWSERS]; -extern AllHtmlFlags const aHTMLOutFrameParaFrameTable[MAX_FRMTYPES][MAX_BROWSERS]; -extern AllHtmlFlags const aHTMLOutFrameParaPrtAreaTable[MAX_FRMTYPES][MAX_BROWSERS]; -extern AllHtmlFlags const aHTMLOutFrameParaOtherTable[MAX_FRMTYPES][MAX_BROWSERS]; -extern AllHtmlFlags const aHTMLOutFrameAsCharTable[MAX_FRMTYPES][MAX_BROWSERS]; + +AllHtmlFlags getHTMLOutFramePageFlyTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode); +AllHtmlFlags getHTMLOutFrameParaFrameTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode); +AllHtmlFlags getHTMLOutFrameParaPrtAreaTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode); +AllHtmlFlags getHTMLOutFrameParaOtherTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode); +AllHtmlFlags getHTMLOutFrameAsCharTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode); class SwHTMLPosFlyFrame { - const SwFrameFormat *pFrameFormat; // the frame - const SdrObject *pSdrObject; // maybe Sdr-Object - SwNodeIndex *pNdIdx; // Node-Index - sal_uInt32 nOrdNum; // from SwPosFlyFrame - sal_Int32 nContentIdx; // its position in content - AllHtmlFlags nAllFlags; + const SwFrameFormat *m_pFrameFormat; // the frame + const SdrObject *m_pSdrObject; // maybe Sdr-Object + SwNodeIndex m_aNodeIndex; // Node-Index + sal_uInt32 m_nOrdNum; // from SwPosFlyFrame + sal_Int32 m_nContentIndex; // its position in content + AllHtmlFlags m_nAllFlags; SwHTMLPosFlyFrame(const SwHTMLPosFlyFrame&) = delete; SwHTMLPosFlyFrame& operator=(const SwHTMLPosFlyFrame&) = delete; @@ -111,21 +110,19 @@ public: bool operator<( const SwHTMLPosFlyFrame& ) const; - const SwFrameFormat& GetFormat() const { return *pFrameFormat; } - const SdrObject* GetSdrObject() const { return pSdrObject; } - const SwNodeIndex& GetNdIndex() const { return *pNdIdx; } - sal_Int32 GetContentIndex() const { return nContentIdx; } - AllHtmlFlags const & GetOutMode() const { return nAllFlags; } - HtmlOut GetOutFn() const { return nAllFlags.nOut; } - HtmlPosition GetOutPos() const { return nAllFlags.nPosition; } + const SwFrameFormat& GetFormat() const { return *m_pFrameFormat; } + const SdrObject* GetSdrObject() const { return m_pSdrObject; } + const SwNodeIndex& GetNdIndex() const { return m_aNodeIndex; } + sal_Int32 GetContentIndex() const { return m_nContentIndex; } + AllHtmlFlags const & GetOutMode() const { return m_nAllFlags; } + HtmlOut GetOutFn() const { return m_nAllFlags.nOut; } + HtmlPosition GetOutPos() const { return m_nAllFlags.nPosition; } }; class SwHTMLPosFlyFrames : public o3tl::sorted_vector<std::unique_ptr<SwHTMLPosFlyFrame>, - o3tl::less_uniqueptr_to<SwHTMLPosFlyFrame>, + o3tl::less_ptr_to, o3tl::find_partialorder_ptrequals> {}; -#endif - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlflyt.cxx b/sw/source/filter/html/htmlflyt.cxx index 9e4596ebc7bb..9653c0bb062e 100644 --- a/sw/source/filter/html/htmlflyt.cxx +++ b/sw/source/filter/html/htmlflyt.cxx @@ -18,488 +18,470 @@ */ #include "htmlfly.hxx" +#include <svtools/htmlcfg.hxx> -#define TE(t,p,c) { HtmlOut::t, HtmlPosition::p, HtmlContainerFlags::c } +constexpr sal_uInt16 MAX_FRMTYPES = HTML_FRMTYPE_END; +constexpr sal_uInt16 MAX_BROWSERS = HTML_CFG_MAX + 1; -AllHtmlFlags const aHTMLOutFramePageFlyTable[MAX_FRMTYPES][MAX_BROWSERS] = +constexpr AllHtmlFlags aHTMLOutFramePageFlyTable[][MAX_BROWSERS] = { { // text frame with table - TE(TableNode, Before, NONE), // HTML 3.2 - TE(Div, Prefix, NONE), // IE 4 - TE(Div, Prefix, NONE), // SW - TE(Div, Prefix, NONE) // Netscape 4! + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE } // Netscape 4! }, { // text frame with table and headline - TE(TableNode, Before, NONE), // HTML 3.2 - TE(Div, Prefix, NONE), // IE 4 - TE(Div, Prefix, NONE), // SW - TE(Div, Prefix, NONE) // Netscape 4 + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE } // Netscape 4 }, { // column frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Prefix, NONE), // IE 4 - TE(MultiCol, Prefix, NONE), // SW - TE(MultiCol, Prefix, Div) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::MultiCol, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::MultiCol, HtmlPosition::Prefix, HtmlContainerFlags::Div } // Netscape 4 }, { // empty text frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(Div, Prefix, NONE), // IE 4 - TE(Div, Prefix, NONE), // SW - TE(Div, Prefix, NONE) // Netscape 4 + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE } // Netscape 4 }, { // other text frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(Div, Prefix, NONE), // IE 4 - TE(Div, Prefix, NONE), // SW - TE(Div, Prefix, NONE) // Netscape 4 + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Div, HtmlPosition::Prefix, HtmlContainerFlags::NONE } // Netscape 4 }, { // graphic node - TE(GraphicNode, Inside, NONE), // HTML 3.2 - TE(GraphicNode, Prefix, NONE), // IE 4 - TE(GraphicNode, Prefix, NONE), // SW - TE(GraphicNode, Prefix, Span) // Netscape 4 + { HtmlOut::GraphicNode, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicNode, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicNode, HtmlPosition::Prefix, HtmlContainerFlags::Span } // Netscape 4 }, { // plug-in - TE(OleNode, Inside, NONE), // HTML 3.2 - TE(OleNode, Prefix, NONE), // IE 4 - TE(OleNode, Prefix, NONE), // SW - TE(OleNode, Prefix, Span) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Prefix, HtmlContainerFlags::Span } // Netscape 4 }, { // applet - TE(OleNode, Inside, NONE), // HTML 3.2 - TE(OleNode, Prefix, NONE), // IE 4 - TE(OleNode, Prefix, NONE), // SW - TE(OleNode, Prefix, Span) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Prefix, HtmlContainerFlags::Span } // Netscape 4 }, { // floating frame - TE(OleGraphic, Inside, NONE), // HTML 3.2 - TE(OleNode, Prefix, NONE), // IE 4 - TE(OleNode, Prefix, NONE), // SW - TE(OleGraphic, Prefix, Span) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Prefix, HtmlContainerFlags::Span } // Netscape 4 }, { // other OLE objects - TE(OleGraphic, Inside, NONE), // HTML 3.2 - TE(OleGraphic, Prefix, NONE), // IE 4 - TE(OleGraphic, Prefix, NONE), // SW - TE(OleGraphic, Prefix, Span) // Netscape 4 + { HtmlOut::OleGraphic, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleGraphic, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Prefix, HtmlContainerFlags::Span } // Netscape 4 }, { // marquee - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(AMarquee, Prefix, NONE), // IE 4 - TE(AMarquee, Prefix, NONE), // SW - TE(GraphicFrame, Prefix, Span) // Netscape 4 + { HtmlOut::AMarquee, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::AMarquee, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Prefix, HtmlContainerFlags::Span } // Netscape 4 }, { // controls - TE(Control, Inside, NONE), // HTML 3.2 - TE(Control, Prefix, NONE), // IE 4 - TE(Control, Prefix, NONE), // SW + { HtmlOut::Control, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Control, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW // Netscape disables FROM at controls in absolute position span. - TE(Control, Inside, NONE) // Netscape 4 + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other character objects - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Prefix, NONE), // IE 4 - TE(GraphicFrame, Prefix, NONE), // SW - TE(GraphicFrame, Prefix, Span) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicFrame, HtmlPosition::Prefix, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Prefix, HtmlContainerFlags::Span } // Netscape 4 } }; -AllHtmlFlags const aHTMLOutFrameParaFrameTable[MAX_FRMTYPES][MAX_BROWSERS] = +AllHtmlFlags getHTMLOutFramePageFlyTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode) +{ + static_assert(std::size(aHTMLOutFramePageFlyTable) == MAX_FRMTYPES); + assert(eFrameType < HTML_FRMTYPE_END); + assert(nExportMode <= HTML_CFG_MAX); + + return aHTMLOutFramePageFlyTable[eFrameType][nExportMode]; +} + +constexpr AllHtmlFlags aHTMLOutFrameParaFrameTable[][MAX_BROWSERS] = { { // text frame with table - TE(TableNode, Before, NONE), // HTML 3.2 - TE(TableNode, Before, NONE), // IE 4 - TE(TableNode, Before, NONE), // SW - TE(TableNode, Before, NONE) // Netscape 4 + { HtmlOut::TableNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::TableNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::TableNode, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // text frame with table and headline - TE(TableNode, Before, NONE), // HTML 3.2 - TE(Div, Before, NONE), // IE 4 - TE(Div, Before, NONE), // SW - TE(TableNode, Before, NONE) // Netscape 4 + { HtmlOut::Div, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Div, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::TableNode, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // column frame - TE(GraphicFrame, Before, NONE), // HTML 3.2 - TE(GraphicFrame, Before, NONE), // IE 4 - TE(MultiCol, Before, NONE), // SW - TE(MultiCol, Before, Div) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::MultiCol, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::MultiCol, HtmlPosition::Before, HtmlContainerFlags::Div } // Netscape 4 }, { // empty text frame - TE(GraphicFrame, Before, NONE), // HTML 3.2 - TE(Div, Before, NONE), // IE 4 - TE(Spacer, Before, NONE), // SW - TE(Spacer, Before, NONE) // Netscape 4 + { HtmlOut::Div, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Spacer, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Spacer, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // other text frame - TE(GraphicFrame, Before, NONE), // HTML 3.2 - TE(Div, Before, NONE), // IE 4 - TE(Div, Before, NONE), // SW - TE(Div, Before, NONE) // Netscape 4 + { HtmlOut::Div, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Div, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Div, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // graphic node - TE(GraphicNode, Before, NONE), // HTML 3.2 - TE(GraphicNode, Before, NONE), // IE 4 - TE(GraphicNode, Before, NONE), // SW - TE(GraphicNode, Before, NONE) // Netscape 4 + { HtmlOut::GraphicNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicNode, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // plug-in - TE(OleNode, Before, NONE), // HTML 3.2 - TE(OleNode, Before, NONE), // IE 4 - TE(OleNode, Before, NONE), // SW - TE(OleNode, Before, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // applet - TE(OleNode, Before, NONE), // HTML 3.2 - TE(OleNode, Before, NONE), // IE 4 - TE(OleNode, Before, NONE), // SW - TE(OleNode, Before, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // floating frame - TE(OleGraphic, Before, NONE), // HTML 3.2 - TE(OleNode, Before, NONE), // IE 4 - TE(OleNode, Before, NONE), // SW - TE(OleGraphic, Before, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // other OLE objects - TE(OleGraphic, Before, NONE), // HTML 3.2 - TE(OleGraphic, Before, NONE), // IE 4 - TE(OleGraphic, Before, NONE), // SW - TE(OleGraphic, Before, NONE) // Netscape 4 + { HtmlOut::OleGraphic, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleGraphic, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // marquee (for Netscape 4 in container, so that // the marquee appears at the right spot) - TE(GraphicFrame, Before, NONE), // HTML 3.2 - TE(AMarquee, Before, NONE), // IE 4 - TE(AMarquee, Before, NONE), // SW - TE(GraphicFrame, Before, NONE) // Netscape 4 + { HtmlOut::AMarquee, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::AMarquee, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // controls - TE(Control, Inside, NONE), // HTML 3.2 - TE(Control, Before, NONE), // IE 4 - TE(Control, Before, NONE), // SW + { HtmlOut::Control, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Control, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW // here you could make container out if it (import is missing) - TE(Control, Before, NONE) // Netscape 4 + { HtmlOut::Control, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 }, { // other character objects - TE(GraphicFrame, Before, NONE), // HTML 3.2 - TE(GraphicFrame, Before, NONE), // IE 4 - TE(GraphicFrame, Before, NONE), // SW - TE(GraphicFrame, Before, NONE) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Before, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicFrame, HtmlPosition::Before, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Before, HtmlContainerFlags::NONE } // Netscape 4 } }; -AllHtmlFlags const aHTMLOutFrameParaPrtAreaTable[MAX_FRMTYPES][MAX_BROWSERS] = +AllHtmlFlags getHTMLOutFrameParaFrameTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode) +{ + static_assert(std::size(aHTMLOutFrameParaFrameTable) == MAX_FRMTYPES); + assert(eFrameType < HTML_FRMTYPE_END); + assert(nExportMode <= HTML_CFG_MAX); + + return aHTMLOutFrameParaFrameTable[eFrameType][nExportMode]; +} + +constexpr AllHtmlFlags aHTMLOutFrameParaPrtAreaTable[][MAX_BROWSERS] = { { // text frame with table - TE(TableNode, Inside, NONE), // HTML 3.2 - TE(TableNode, Inside, NONE), // IE 4 - TE(TableNode, Inside, NONE), // SW - TE(TableNode, Inside, NONE) // Netscape 4 + { HtmlOut::TableNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::TableNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::TableNode, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // text frame with table and headline - TE(TableNode, Inside, NONE), // HTML 3.2 - TE(Span, Inside, NONE), // IE 4 - TE(Span, Inside, NONE), // SW - TE(Span, Inside, NONE) // Netscape 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // column frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(MultiCol, Inside, NONE), // SW - TE(MultiCol, Inside, Span) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::MultiCol, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::MultiCol, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 }, { // empty text frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(Span, Inside, NONE), // IE 4 - TE(Spacer, Inside, NONE), // SW - TE(Spacer, Inside, NONE) // Netscape 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Spacer, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Spacer, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other text frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(Span, Inside, NONE), // IE 4 - TE(Span, Inside, NONE), // SW - TE(Span, Inside, NONE) // Netscape 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // graphic node - TE(GraphicNode, Inside, NONE), // HTML 3.2 - TE(GraphicNode, Inside, NONE), // IE 4 - TE(GraphicNode, Inside, NONE), // SW - TE(GraphicNode, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // plug-in - TE(OleNode, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleNode, Inside, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // applet - TE(OleNode, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleNode, Inside, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // floating frame - TE(OleGraphic, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleGraphic, Inside, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other OLE objects - TE(OleGraphic, Inside, NONE), // HTML 3.2 - TE(OleGraphic, Inside, NONE), // IE 4 - TE(OleGraphic, Inside, NONE), // SW - TE(OleGraphic, Inside, NONE) // Netscape 4 + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // marquee - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(AMarquee, Inside, NONE), // IE 4 - TE(AMarquee, Inside, NONE), // SW - TE(GraphicFrame, Inside, NONE) // Netscape 4 + { HtmlOut::AMarquee, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::AMarquee, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // controls - TE(Control, Inside, NONE), // HTML 3.2 - TE(Control, Inside, NONE), // IE 4 - TE(Control, Inside, NONE), // SW + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW // here you could make container out if it (import is missing) - TE(Control, Inside, NONE) // Netscape 4 + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other character objects - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(GraphicFrame, Inside, NONE), // SW - TE(GraphicFrame, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 } }; -AllHtmlFlags const aHTMLOutFrameParaOtherTable[MAX_FRMTYPES][MAX_BROWSERS] = +AllHtmlFlags getHTMLOutFrameParaPrtAreaTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode) +{ + static_assert(std::size(aHTMLOutFrameParaPrtAreaTable) == MAX_FRMTYPES); + assert(eFrameType < HTML_FRMTYPE_END); + assert(nExportMode <= HTML_CFG_MAX); + + return aHTMLOutFrameParaPrtAreaTable[eFrameType][nExportMode]; +} + +constexpr AllHtmlFlags aHTMLOutFrameParaOtherTable[][MAX_BROWSERS] = { { // text frame with table - TE(TableNode, Before, NONE), // HTML 3.2 - TE(Span, Inside, NONE), // IE 4 - TE(Span, Inside, NONE), // SW - TE(Span, Inside, NONE) // Netscape 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // text frame with table and headline - TE(TableNode, Before, NONE), // HTML 3.2 - TE(Span, Inside, NONE), // IE 4 - TE(Span, Inside, NONE), // SW - TE(Span, Inside, NONE) // Netscape 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // column frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(MultiCol, Inside, NONE), // SW - TE(MultiCol, Inside, Span) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::MultiCol, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::MultiCol, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 }, { // empty text frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(Span, Inside, NONE), // IE 4 - TE(Span, Inside, NONE), // SW - TE(Span, Inside, NONE) // Netscape 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other text frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(Span, Inside, NONE), // IE 4 - TE(Span, Inside, NONE), // SW - TE(Span, Inside, NONE) // Netscape 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Span, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // graphic node - TE(GraphicNode, Inside, NONE), // HTML 3.2 - TE(GraphicNode, Inside, NONE), // IE 4 - TE(GraphicNode, Inside, NONE), // SW - TE(GraphicNode, Inside, Span) // Netscape 4 + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 }, { // plug-in - TE(OleNode, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleNode, Inside, Span) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 }, { // applet - TE(OleNode, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleNode, Inside, Span) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 }, { // floating frame - TE(OleGraphic, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleGraphic, Inside, Span) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 }, { // other OLE objects - TE(OleGraphic, Inside, NONE), // HTML 3.2 - TE(OleGraphic, Inside, NONE), // IE 4 - TE(OleGraphic, Inside, NONE), // SW - TE(OleGraphic, Inside, Span) // Netscape 4 + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 }, { // marquee - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(AMarquee, Inside, NONE), // IE 4 - TE(AMarquee, Inside, NONE), // SW - TE(GraphicFrame, Inside, Span) // Netscape 4 + { HtmlOut::AMarquee, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::AMarquee, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 }, { // controls - TE(Control, Inside, NONE), // HTML 3.2 - TE(Control, Inside, NONE), // IE 4 - TE(Control, Inside, NONE), // SW + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW // Netscape disables FROM at controls in absolute position span. - TE(Control, Inside, NONE) // Netscape 4 + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other character objects - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(GraphicFrame, Inside, NONE), // SW - TE(GraphicFrame, Inside, Span) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::Span } // Netscape 4 } }; -AllHtmlFlags const aHTMLOutFrameAsCharTable[MAX_FRMTYPES][MAX_BROWSERS] = +AllHtmlFlags getHTMLOutFrameParaOtherTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode) +{ + static_assert(std::size(aHTMLOutFrameParaOtherTable) == MAX_FRMTYPES); + assert(eFrameType < HTML_FRMTYPE_END); + assert(nExportMode <= HTML_CFG_MAX); + + return aHTMLOutFrameParaOtherTable[eFrameType][nExportMode]; +} + +constexpr AllHtmlFlags aHTMLOutFrameAsCharTable[][MAX_BROWSERS] = { { // text frame with table - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(GraphicFrame, Inside, NONE), // SW - TE(GraphicFrame, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // text frame with table and headline - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(GraphicFrame, Inside, NONE), // SW - TE(GraphicFrame, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // column frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(MultiCol, Inside, NONE), // SW - TE(MultiCol, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::MultiCol, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::MultiCol, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // empty text frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(Spacer, Inside, NONE), // SW - TE(Spacer, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Spacer, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Spacer, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other text frame - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(GraphicFrame, Inside, NONE), // SW - TE(GraphicFrame, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // graphic node - TE(GraphicNode, Inside, NONE), // HTML 3.2 - TE(GraphicNode, Inside, NONE), // IE 4 - TE(GraphicNode, Inside, NONE), // SW - TE(GraphicNode, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicNode, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // plug-in - TE(OleNode, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleNode, Inside, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // applet - TE(OleNode, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleNode, Inside, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // floating frame - TE(OleGraphic, Inside, NONE), // HTML 3.2 - TE(OleNode, Inside, NONE), // IE 4 - TE(OleNode, Inside, NONE), // SW - TE(OleGraphic, Inside, NONE) // Netscape 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleNode, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other OLE objects - TE(OleGraphic, Inside, NONE), // HTML 3.2 - TE(OleGraphic, Inside, NONE), // IE 4 - TE(OleGraphic, Inside, NONE), // SW - TE(OleGraphic, Inside, NONE) // Netscape 4 + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::OleGraphic, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // marquee (can always exported as marquee, because // the content shows up at the right spot - TE(Marquee, Inside, NONE), // HTML 3.2 - TE(Marquee, Inside, NONE), // IE 4 - TE(Marquee, Inside, NONE), // SW - TE(Marquee, Inside, NONE) // Netscape 4 + { HtmlOut::Marquee, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Marquee, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Marquee, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // controls - TE(Control, Inside, NONE), // HTML 3.2 - TE(Control, Inside, NONE), // IE 4 - TE(Control, Inside, NONE), // SW - TE(Control, Inside, NONE) // Netscape 4 + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::Control, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 }, { // other character objects - TE(GraphicFrame, Inside, NONE), // HTML 3.2 - TE(GraphicFrame, Inside, NONE), // IE 4 - TE(GraphicFrame, Inside, NONE), // SW - TE(GraphicFrame, Inside, NONE) // Netscape 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // IE 4 + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE }, // SW + { HtmlOut::GraphicFrame, HtmlPosition::Inside, HtmlContainerFlags::NONE } // Netscape 4 } }; +AllHtmlFlags getHTMLOutFrameAsCharTable(SwHTMLFrameType eFrameType, sal_uInt16 nExportMode) +{ + static_assert(std::size(aHTMLOutFrameAsCharTable) == MAX_FRMTYPES); + assert(eFrameType < HTML_FRMTYPE_END); + assert(nExportMode <= HTML_CFG_MAX); + + return aHTMLOutFrameAsCharTable[eFrameType][nExportMode]; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlflywriter.cxx b/sw/source/filter/html/htmlflywriter.cxx index e6cf6316474f..ea421f3cbc72 100644 --- a/sw/source/filter/html/htmlflywriter.cxx +++ b/sw/source/filter/html/htmlflywriter.cxx @@ -40,6 +40,9 @@ #include <editeng/ulspitem.hxx> #include <editeng/brushitem.hxx> #include <sal/log.hxx> +#include <osl/diagnose.h> +#include <svx/svdograf.hxx> +#include <comphelper/xmlencode.hxx> #include <fmtanchr.hxx> #include <fmtornt.hxx> @@ -127,18 +130,18 @@ const HtmlFrmOpts HTML_FRMOPTS_CNTNR = HtmlFrmOpts::AbsSize | HtmlFrmOpts::SPixSize; -static Writer& OutHTML_FrameFormatTableNode( Writer& rWrt, const SwFrameFormat& rFrameFormat ); -static Writer& OutHTML_FrameFormatAsMulticol( Writer& rWrt, const SwFrameFormat& rFormat, +static SwHTMLWriter& OutHTML_FrameFormatTableNode( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat ); +static SwHTMLWriter& OutHTML_FrameFormatAsMulticol( SwHTMLWriter& rWrt, const SwFrameFormat& rFormat, bool bInCntnr ); -static Writer& OutHTML_FrameFormatAsSpacer( Writer& rWrt, const SwFrameFormat& rFormat ); -static Writer& OutHTML_FrameFormatAsDivOrSpan( Writer& rWrt, +static SwHTMLWriter& OutHTML_FrameFormatAsSpacer( SwHTMLWriter& rWrt, const SwFrameFormat& rFormat ); +static SwHTMLWriter& OutHTML_FrameFormatAsDivOrSpan( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, bool bSpan ); -static Writer& OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& rFormat ); +static SwHTMLWriter& OutHTML_FrameFormatAsImage( SwHTMLWriter& rWrt, const SwFrameFormat& rFormat, bool bPNGFallback ); -static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rFormat, - bool bInCntnr ); +static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFrameFormat& rFormat, + bool bInCntnr, bool bPNGFallback ); -static Writer& OutHTML_FrameFormatAsMarquee( Writer& rWrt, const SwFrameFormat& rFrameFormat, +static SwHTMLWriter& OutHTML_FrameFormatAsMarquee( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, const SdrObject& rSdrObj ); HTMLOutEvent const aImageEventTable[] = @@ -156,7 +159,7 @@ HTMLOutEvent const aIMapEventTable[] = { nullptr, nullptr, SvMacroItemId::NONE } }; -sal_uInt16 SwHTMLWriter::GuessFrameType( const SwFrameFormat& rFrameFormat, +SwHTMLFrameType SwHTMLWriter::GuessFrameType( const SwFrameFormat& rFrameFormat, const SdrObject*& rpSdrObj ) { SwHTMLFrameType eType; @@ -192,7 +195,7 @@ sal_uInt16 SwHTMLWriter::GuessFrameType( const SwFrameFormat& rFrameFormat, eType = HTML_FRMTYPE_TEXT; const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); - sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1; + SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1; const SwNode* pNd = m_pDoc->GetNodes()[ nStt ]; if( pNd->IsGrfNode() ) @@ -203,17 +206,15 @@ sal_uInt16 SwHTMLWriter::GuessFrameType( const SwFrameFormat& rFrameFormat, else if( pNd->IsOLENode() ) { // applet, plugin, floating frame - eType = static_cast<SwHTMLFrameType>(GuessOLENodeFrameType( *pNd )); + eType = GuessOLENodeFrameType( *pNd ); } else { - sal_uLong nEnd = m_pDoc->GetNodes()[nStt-1]->EndOfSectionIndex(); + SwNodeOffset nEnd = m_pDoc->GetNodes()[nStt-1]->EndOfSectionIndex(); - const SfxPoolItem* pItem; const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet(); - if( SfxItemState::SET == rItemSet.GetItemState( RES_COL, - true, &pItem ) && - static_cast<const SwFormatCol *>(pItem)->GetNumCols() > 1 ) + const SwFormatCol* pFormatCol = rItemSet.GetItemIfSet( RES_COL ); + if( pFormatCol && pFormatCol->GetNumCols() > 1 ) { // frame with columns eType = HTML_FRMTYPE_MULTICOL; @@ -221,7 +222,7 @@ sal_uInt16 SwHTMLWriter::GuessFrameType( const SwFrameFormat& rFrameFormat, else if( pNd->IsTableNode() ) { const SwTableNode *pTableNd = pNd->GetTableNode(); - sal_uLong nTableEnd = pTableNd->EndOfSectionIndex(); + SwNodeOffset nTableEnd = pTableNd->EndOfSectionIndex(); if( nTableEnd+1 == nEnd ) { @@ -244,15 +245,12 @@ sal_uInt16 SwHTMLWriter::GuessFrameType( const SwFrameFormat& rFrameFormat, // empty frame? Only if no frame is // anchored to the text or start node. bEmpty = true; - if( m_pHTMLPosFlyFrames ) + for( auto & pHTMLPosFlyFrame : m_aHTMLPosFlyFrames ) { - for( auto & pHTMLPosFlyFrame : *m_pHTMLPosFlyFrames ) - { - sal_uLong nIdx = pHTMLPosFlyFrame->GetNdIndex().GetIndex(); - bEmpty = (nIdx != nStt) && (nIdx != nStt-1); - if( !bEmpty || nIdx > nStt ) - break; - } + SwNodeOffset nIdx = pHTMLPosFlyFrame->GetNdIndex().GetIndex(); + bEmpty = (nIdx != nStt) && (nIdx != nStt-1); + if( !bEmpty || nIdx > nStt ) + break; } } if( bEmpty ) @@ -260,9 +258,8 @@ sal_uInt16 SwHTMLWriter::GuessFrameType( const SwFrameFormat& rFrameFormat, std::unique_ptr<SvxBrushItem> aBrush = rFrameFormat.makeBackgroundBrushItem(); /// background is not empty, if it has a background graphic /// or its background color is not "no fill"/"auto fill". - if( aBrush && - (GPOS_NONE != aBrush->GetGraphicPos() || - aBrush->GetColor() != COL_TRANSPARENT )) + if( GPOS_NONE != aBrush->GetGraphicPos() || + aBrush->GetColor() != COL_TRANSPARENT ) { bEmpty = false; } @@ -286,24 +283,21 @@ sal_uInt16 SwHTMLWriter::GuessFrameType( const SwFrameFormat& rFrameFormat, } } - return static_cast< sal_uInt16 >(eType); + return eType; } void SwHTMLWriter::CollectFlyFrames() { - OSL_ENSURE( HTML_CFG_MAX+1 == MAX_BROWSERS, - "number of browser configurations has changed" ); - SwPosFlyFrames aFlyPos( m_pDoc->GetAllFlyFormats(m_bWriteAll ? nullptr : m_pCurrentPam.get(), true)); - for(const auto& rpItem : aFlyPos) + for(const SwPosFlyFrame& rItem : aFlyPos) { - const SwFrameFormat& rFrameFormat = rpItem->GetFormat(); + const SwFrameFormat& rFrameFormat = rItem.GetFormat(); const SdrObject *pSdrObj = nullptr; - const SwPosition *pAPos; + const SwNode *pAnchorNode; const SwContentNode *pACNd; - SwHTMLFrameType eType = static_cast<SwHTMLFrameType>(GuessFrameType( rFrameFormat, pSdrObj )); + SwHTMLFrameType eType = GuessFrameType( rFrameFormat, pSdrObj ); AllHtmlFlags nMode; const SwFormatAnchor& rAnchor = rFrameFormat.GetAnchor(); @@ -312,7 +306,7 @@ void SwHTMLWriter::CollectFlyFrames() { case RndStdIds::FLY_AT_PAGE: case RndStdIds::FLY_AT_FLY: - nMode = aHTMLOutFramePageFlyTable[eType][m_nExportMode]; + nMode = getHTMLOutFramePageFlyTable(eType, m_nExportMode); break; case RndStdIds::FLY_AT_PARA: @@ -320,61 +314,59 @@ void SwHTMLWriter::CollectFlyFrames() // before the paragraph, if the paragraph has a // spacing. if( text::RelOrientation::FRAME == eHoriRel && - (pAPos = rAnchor.GetContentAnchor()) != nullptr && - (pACNd = pAPos->nNode.GetNode().GetContentNode()) != nullptr ) + (pAnchorNode = rAnchor.GetAnchorNode()) != nullptr && + (pACNd = pAnchorNode->GetContentNode()) != nullptr ) { - const SvxLRSpaceItem& rLRItem = - static_cast<const SvxLRSpaceItem&>(pACNd->GetAttr(RES_LR_SPACE)); - if( rLRItem.GetTextLeft() || rLRItem.GetRight() ) + const SvxTextLeftMarginItem& rTextLeftMargin = + pACNd->GetAttr(RES_MARGIN_TEXTLEFT); + const SvxRightMarginItem& rRightMargin = + pACNd->GetAttr(RES_MARGIN_RIGHT); + if (rTextLeftMargin.GetTextLeft() || rRightMargin.GetRight()) { - nMode = aHTMLOutFrameParaFrameTable[eType][m_nExportMode]; + nMode = getHTMLOutFrameParaFrameTable(eType, m_nExportMode); break; } } - nMode = aHTMLOutFrameParaPrtAreaTable[eType][m_nExportMode]; + nMode = getHTMLOutFrameParaPrtAreaTable(eType, m_nExportMode); break; case RndStdIds::FLY_AT_CHAR: if( text::RelOrientation::FRAME == eHoriRel || text::RelOrientation::PRINT_AREA == eHoriRel ) - nMode = aHTMLOutFrameParaPrtAreaTable[eType][m_nExportMode]; + nMode = getHTMLOutFrameParaPrtAreaTable(eType, m_nExportMode); else - nMode = aHTMLOutFrameParaOtherTable[eType][m_nExportMode]; + nMode = getHTMLOutFrameParaOtherTable(eType, m_nExportMode); break; default: - nMode = aHTMLOutFrameParaPrtAreaTable[eType][m_nExportMode]; + nMode = getHTMLOutFrameParaPrtAreaTable(eType, m_nExportMode); break; } - if( !m_pHTMLPosFlyFrames ) - m_pHTMLPosFlyFrames.reset(new SwHTMLPosFlyFrames); - - m_pHTMLPosFlyFrames->insert( std::make_unique<SwHTMLPosFlyFrame>(*rpItem, pSdrObj, nMode) ); + m_aHTMLPosFlyFrames.insert( std::make_unique<SwHTMLPosFlyFrame>(rItem, pSdrObj, nMode) ); } } -bool SwHTMLWriter::OutFlyFrame( sal_uLong nNdIdx, sal_Int32 nContentIdx, HtmlPosition nPos, - HTMLOutContext *pContext ) +bool SwHTMLWriter::OutFlyFrame( SwNodeOffset nNdIdx, sal_Int32 nContentIdx, HtmlPosition nPos ) { bool bFlysLeft = false; // Are there still Flys left at the current node position? // OutFlyFrame can be called recursively. Thus, sometimes it is // necessary to start over after a Fly was returned. bool bRestart = true; - while( m_pHTMLPosFlyFrames && bRestart ) + while( !m_aHTMLPosFlyFrames.empty() && bRestart ) { bFlysLeft = bRestart = false; // search for the beginning of the FlyFrames size_t i {0}; - for( ; i < m_pHTMLPosFlyFrames->size() && - (*m_pHTMLPosFlyFrames)[i]->GetNdIndex().GetIndex() < nNdIdx; i++ ) + for( ; i < m_aHTMLPosFlyFrames.size() && + m_aHTMLPosFlyFrames[i]->GetNdIndex().GetIndex() < nNdIdx; i++ ) ; - for( ; !bRestart && i < m_pHTMLPosFlyFrames->size() && - (*m_pHTMLPosFlyFrames)[i]->GetNdIndex().GetIndex() == nNdIdx; i++ ) + for( ; !bRestart && i < m_aHTMLPosFlyFrames.size() && + m_aHTMLPosFlyFrames[i]->GetNdIndex().GetIndex() == nNdIdx; i++ ) { - SwHTMLPosFlyFrame *pPosFly = (*m_pHTMLPosFlyFrames)[i].get(); + SwHTMLPosFlyFrame *pPosFly = m_aHTMLPosFlyFrames[i].get(); if( ( HtmlPosition::Any == nPos || pPosFly->GetOutPos() == nPos ) && pPosFly->GetContentIndex() == nContentIdx ) @@ -382,19 +374,14 @@ bool SwHTMLWriter::OutFlyFrame( sal_uLong nNdIdx, sal_Int32 nContentIdx, HtmlPos // It is important to remove it first, because additional // elements or the whole array could be deleted on // deeper recursion levels. - std::unique_ptr<SwHTMLPosFlyFrame> flyHolder = m_pHTMLPosFlyFrames->erase_extract(i); + std::unique_ptr<SwHTMLPosFlyFrame> flyHolder = m_aHTMLPosFlyFrames.erase_extract(i); i--; - if( m_pHTMLPosFlyFrames->empty() ) + if( m_aHTMLPosFlyFrames.empty() ) { - m_pHTMLPosFlyFrames.reset(); bRestart = true; // not really, only exit the loop } - if( pContext ) - { - HTMLOutFuncs::FlushToAscii(Strm(), *pContext ); - pContext = nullptr; // one time only - } + HTMLOutFuncs::FlushToAscii(Strm()); // it was one time only; do we still need it? OutFrameFormat( pPosFly->GetOutMode(), pPosFly->GetFormat(), pPosFly->GetSdrObject() ); @@ -428,17 +415,18 @@ void SwHTMLWriter::OutFrameFormat( AllHtmlFlags nMode, const SwFrameFormat& rFra if( HtmlContainerFlags::NONE != nCntnrMode ) { - if( m_bLFPossible && HtmlContainerFlags::Div == nCntnrMode ) + if (IsLFPossible() && HtmlContainerFlags::Div == nCntnrMode) OutNewLine(); OStringBuffer sOut; aContainerStr = (HtmlContainerFlags::Div == nCntnrMode) ? OOO_STRING_SVTOOLS_HTML_division : OOO_STRING_SVTOOLS_HTML_span; - sOut.append('<').append(GetNamespace() + aContainerStr).append(' ') - .append(OOO_STRING_SVTOOLS_HTML_O_class).append("=\"") - .append("sd-abs-pos").append('\"'); - Strm().WriteOString( sOut.makeStringAndClear() ); + sOut.append("<" + GetNamespace() + aContainerStr + " " + OOO_STRING_SVTOOLS_HTML_O_class "=\"" + "sd-abs-pos\""); + Strm().WriteOString( sOut ); + sOut.setLength(0); // Output a width for non-draw objects HtmlFrmOpts nFrameFlags = HTML_FRMOPTS_CNTNR; @@ -455,7 +443,7 @@ void SwHTMLWriter::OutFrameFormat( AllHtmlFlags nMode, const SwFrameFormat& rFra if( HtmlContainerFlags::Div == nCntnrMode ) { IncIndentLevel(); - m_bLFPossible = true; + SetLFPossible(true); } } @@ -466,7 +454,7 @@ void SwHTMLWriter::OutFrameFormat( AllHtmlFlags nMode, const SwFrameFormat& rFra OutHTML_FrameFormatTableNode( *this, rFrameFormat ); break; case HtmlOut::GraphicNode: // OK - OutHTML_FrameFormatGrfNode( *this, rFrameFormat, !aContainerStr.isEmpty() ); + OutHTML_FrameFormatGrfNode( *this, rFrameFormat, !aContainerStr.isEmpty(), /*bPNGFallback=*/true ); break; case HtmlOut::OleNode: // OK OutHTML_FrameFormatOLENode( *this, rFrameFormat, !aContainerStr.isEmpty() ); @@ -500,29 +488,28 @@ void SwHTMLWriter::OutFrameFormat( AllHtmlFlags nMode, const SwFrameFormat& rFra static_cast<const SwDrawFrameFormat &>(rFrameFormat), *pSdrObject ); break; case HtmlOut::GraphicFrame: - OutHTML_FrameFormatAsImage( *this, rFrameFormat ); + OutHTML_FrameFormatAsImage( *this, rFrameFormat, /*bPNGFallback=*/true ); break; } if( HtmlContainerFlags::Div == nCntnrMode ) { DecIndentLevel(); - if( m_bLFPossible ) + if (IsLFPossible()) OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_division, false ); - m_bLFPossible = true; + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false ); + SetLFPossible(true); } else if( HtmlContainerFlags::Span == nCntnrMode ) - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false ); } OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, - const OUString& rAlternateText, + std::u16string_view rAlternateText, HtmlFrmOpts nFrameOpts ) { OString sRetEndTags; OStringBuffer sOut; - const SfxPoolItem* pItem; const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet(); // Name @@ -531,10 +518,10 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, { const char *pStr = (nFrameOpts & HtmlFrmOpts::Id) ? OOO_STRING_SVTOOLS_HTML_O_id : OOO_STRING_SVTOOLS_HTML_O_name; - sOut.append(' ').append(pStr). - append("=\""); - Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( Strm(), rFrameFormat.GetName(), m_eDestEnc, &m_aNonConvertableCharacters ); + sOut.append(OString::Concat(" ") + pStr + "=\""); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), rFrameFormat.GetName() ); sOut.append('\"'); } @@ -542,17 +529,18 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, if( nFrameOpts & HtmlFrmOpts::Dir ) { SvxFrameDirection nDir = GetHTMLDirection( rItemSet ); - Strm().WriteOString( sOut.makeStringAndClear() ); + Strm().WriteOString( sOut ); + sOut.setLength(0); OutDirection( nDir ); } // ALT - if( (nFrameOpts & HtmlFrmOpts::Alt) && !rAlternateText.isEmpty() ) + if( (nFrameOpts & HtmlFrmOpts::Alt) && !rAlternateText.empty() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_alt). - append("=\""); - Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( Strm(), rAlternateText, m_eDestEnc, &m_aNonConvertableCharacters ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_alt "=\""); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), rAlternateText ); sOut.append('\"'); } @@ -575,12 +563,13 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, : OOO_STRING_SVTOOLS_HTML_AL_left; } } + const SwFormatVertOrient* pVertOrient; if( (nFrameOpts & HtmlFrmOpts::Align) && !pStr && ( !(nFrameOpts & HtmlFrmOpts::SAlign) || (RndStdIds::FLY_AS_CHAR == eAnchorId) ) && - SfxItemState::SET == rItemSet.GetItemState( RES_VERT_ORIENT, true, &pItem )) + (pVertOrient = rItemSet.GetItemIfSet( RES_VERT_ORIENT )) ) { - switch( static_cast<const SwFormatVertOrient*>(pItem)->GetVertOrient() ) + switch( pVertOrient->GetVertOrient() ) { case text::VertOrientation::LINE_TOP: pStr = OOO_STRING_SVTOOLS_HTML_VA_top; break; case text::VertOrientation::CHAR_TOP: @@ -596,51 +585,45 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, } if( pStr ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align).append("=\""). - append(pStr).append("\""); + sOut.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_align "=\"") + + pStr + "\""); } // HSPACE and VSPACE Size aTwipSpc( 0, 0 ); + const SvxLRSpaceItem* pLRSpaceItem; if( (nFrameOpts & (HtmlFrmOpts::Space|HtmlFrmOpts::MarginSize)) && - SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE, true, &pItem )) + (pLRSpaceItem = rItemSet.GetItemIfSet( RES_LR_SPACE )) ) { aTwipSpc.setWidth( - ( static_cast<const SvxLRSpaceItem*>(pItem)->GetLeft() + - static_cast<const SvxLRSpaceItem*>(pItem)->GetRight() ) / 2 ); + ( pLRSpaceItem->GetLeft() + pLRSpaceItem->GetRight() ) / 2 ); m_nDfltLeftMargin = m_nDfltRightMargin = aTwipSpc.Width(); } + const SvxULSpaceItem* pULSpaceItem; if( (nFrameOpts & (HtmlFrmOpts::Space|HtmlFrmOpts::MarginSize)) && - SfxItemState::SET == rItemSet.GetItemState( RES_UL_SPACE, true, &pItem )) + (pULSpaceItem = rItemSet.GetItemIfSet( RES_UL_SPACE )) ) { aTwipSpc.setHeight( - ( static_cast<const SvxULSpaceItem*>(pItem)->GetUpper() + - static_cast<const SvxULSpaceItem*>(pItem)->GetLower() ) / 2 ); - m_nDfltTopMargin = m_nDfltBottomMargin = static_cast<sal_uInt16>(aTwipSpc.Height()); + ( pULSpaceItem->GetUpper() + pULSpaceItem->GetLower() ) / 2 ); + m_nDfltTopMargin = m_nDfltBottomMargin = o3tl::narrowing<sal_uInt16>(aTwipSpc.Height()); } if( (nFrameOpts & HtmlFrmOpts::Space) && (aTwipSpc.Width() || aTwipSpc.Height()) && - Application::GetDefaultDevice() ) + !mbReqIF ) { - Size aPixelSpc = - Application::GetDefaultDevice()->LogicToPixel( aTwipSpc, - MapMode(MapUnit::MapTwip) ); - if( !aPixelSpc.Width() && aTwipSpc.Width() ) - aPixelSpc.setWidth( 1 ); - if( !aPixelSpc.Height() && aTwipSpc.Height() ) - aPixelSpc.setHeight( 1 ); + Size aPixelSpc = SwHTMLWriter::ToPixel(aTwipSpc); if( aPixelSpc.Width() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_hspace). - append("=\"").append(static_cast<sal_Int32>(aPixelSpc.Width())).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_hspace + "=\"" + OString::number(aPixelSpc.Width()) + "\""); } if( aPixelSpc.Height() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_vspace). - append("=\"").append(static_cast<sal_Int32>(aPixelSpc.Height())).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_vspace + "=\"" + OString::number(aPixelSpc.Height()) + "\""); } } @@ -657,11 +640,10 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, aTwipSpc.setHeight( 0 ); } + const SvxBoxItem* pBoxItem; if( !(nFrameOpts & HtmlFrmOpts::AbsSize) && - SfxItemState::SET == rItemSet.GetItemState( RES_BOX, true, &pItem )) + (pBoxItem = rItemSet.GetItemIfSet( RES_BOX )) ) { - const SvxBoxItem* pBoxItem = static_cast<const SvxBoxItem*>(pItem); - aTwipSpc.AdjustWidth(pBoxItem->CalcLineSpace( SvxBoxItemLine::LEFT ) ); aTwipSpc.AdjustWidth(pBoxItem->CalcLineSpace( SvxBoxItemLine::RIGHT ) ); aTwipSpc.AdjustHeight(pBoxItem->CalcLineSpace( SvxBoxItemLine::TOP ) ); @@ -670,12 +652,12 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, // WIDTH and/or HEIGHT // Output SwFrameSize::Variable/SwFrameSize::Minimum only, if ANYSIZE is set + const SwFormatFrameSize *pFSItem; if( (nFrameOpts & HtmlFrmOpts::Size) && - SfxItemState::SET == rItemSet.GetItemState( RES_FRM_SIZE, true, &pItem ) && + (pFSItem = rItemSet.GetItemIfSet( RES_FRM_SIZE )) && ( (nFrameOpts & HtmlFrmOpts::AnySize) || - SwFrameSize::Fixed == static_cast<const SwFormatFrameSize *>(pItem)->GetHeightSizeType()) ) + SwFrameSize::Fixed == pFSItem->GetHeightSizeType()) ) { - const SwFormatFrameSize *pFSItem = static_cast<const SwFormatFrameSize *>(pItem); sal_uInt8 nPercentWidth = pFSItem->GetWidthPercent(); sal_uInt8 nPercentHeight = pFSItem->GetHeightPercent(); @@ -685,32 +667,20 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, (nPercentHeight ? 0 : pFSItem->GetHeight()-aTwipSpc.Height()) ); - OSL_ENSURE( !aTwipSz.IsEmpty(), "Frame size minus spacing < 0!!!???" ); + OSL_ENSURE( aTwipSz.Width() >= 0 && aTwipSz.Height() >= 0, "Frame size minus spacing < 0!!!???" ); if( aTwipSz.Width() < 0 ) aTwipSz.setWidth( 0 ); if( aTwipSz.Height() < 0 ) aTwipSz.setHeight( 0 ); - Size aPixelSz( 0, 0 ); - if( (aTwipSz.Width() || aTwipSz.Height()) && - Application::GetDefaultDevice() ) - { - aPixelSz = - Application::GetDefaultDevice()->LogicToPixel( aTwipSz, - MapMode(MapUnit::MapTwip) ); - if( !aPixelSz.Width() && aTwipSz.Width() ) - aPixelSz.setWidth( 1 ); - if( !aPixelSz.Height() && aTwipSz.Height() ) - aPixelSz.setHeight( 1 ); - } + Size aPixelSz(SwHTMLWriter::ToPixel(aTwipSz)); if( (nFrameOpts & HtmlFrmOpts::Width) && ((nPercentWidth && nPercentWidth!=255) || aPixelSz.Width()) ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_width). - append("=\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\""); if( nPercentWidth ) - sOut.append(static_cast<sal_Int32>(nPercentWidth)).append('%'); + sOut.append(OString::number(static_cast<sal_Int32>(nPercentWidth)) + "%"); else sOut.append(static_cast<sal_Int32>(aPixelSz.Width())); sOut.append("\""); @@ -719,10 +689,9 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, if( (nFrameOpts & HtmlFrmOpts::Height) && ((nPercentHeight && nPercentHeight!=255) || aPixelSz.Height()) ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_height). - append("=\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_height "=\""); if( nPercentHeight ) - sOut.append(static_cast<sal_Int32>(nPercentHeight)).append('%'); + sOut.append(OString::number(static_cast<sal_Int32>(nPercentHeight)) + "%"); else sOut.append(static_cast<sal_Int32>(aPixelSz.Height())); sOut.append("\""); @@ -730,79 +699,84 @@ OString SwHTMLWriter::OutFrameFormatOptions( const SwFrameFormat &rFrameFormat, } if (!sOut.isEmpty()) - Strm().WriteOString( sOut.makeStringAndClear() ); + { + Strm().WriteOString( sOut ); + sOut.setLength(0); + } - // Insert wrap for graphics that are anchored to a paragraph as - // <BR CLEAR=...> in the string - if( (nFrameOpts & HtmlFrmOpts::BrClear) && - ((RndStdIds::FLY_AT_PARA == rFrameFormat.GetAnchor().GetAnchorId()) || - (RndStdIds::FLY_AT_CHAR == rFrameFormat.GetAnchor().GetAnchorId())) && - SfxItemState::SET == rItemSet.GetItemState( RES_SURROUND, true, &pItem )) - { - const SwFormatSurround* pSurround = static_cast<const SwFormatSurround*>(pItem); - sal_Int16 eHoriOri = rFrameFormat.GetHoriOrient().GetHoriOrient(); - pStr = nullptr; - css::text::WrapTextMode eSurround = pSurround->GetSurround(); - bool bAnchorOnly = pSurround->IsAnchorOnly(); - switch( eHoriOri ) + if (!mbReqIF) + { + // Insert wrap for graphics that are anchored to a paragraph as + // <BR CLEAR=...> in the string + const SwFormatSurround* pSurround; + if( (nFrameOpts & HtmlFrmOpts::BrClear) && + ((RndStdIds::FLY_AT_PARA == rFrameFormat.GetAnchor().GetAnchorId()) || + (RndStdIds::FLY_AT_CHAR == rFrameFormat.GetAnchor().GetAnchorId())) && + (pSurround = rItemSet.GetItemIfSet( RES_SURROUND )) ) { - case text::HoriOrientation::RIGHT: + sal_Int16 eHoriOri = rFrameFormat.GetHoriOrient().GetHoriOrient(); + pStr = nullptr; + css::text::WrapTextMode eSurround = pSurround->GetSurround(); + bool bAnchorOnly = pSurround->IsAnchorOnly(); + switch( eHoriOri ) { - switch( eSurround ) + case text::HoriOrientation::RIGHT: { - case css::text::WrapTextMode_NONE: - case css::text::WrapTextMode_RIGHT: - pStr = OOO_STRING_SVTOOLS_HTML_AL_right; - break; - case css::text::WrapTextMode_LEFT: - case css::text::WrapTextMode_PARALLEL: - if( bAnchorOnly ) - m_bClearRight = true; - break; - default: - ; + switch( eSurround ) + { + case css::text::WrapTextMode_NONE: + case css::text::WrapTextMode_RIGHT: + pStr = OOO_STRING_SVTOOLS_HTML_AL_right; + break; + case css::text::WrapTextMode_LEFT: + case css::text::WrapTextMode_PARALLEL: + if( bAnchorOnly ) + m_bClearRight = true; + break; + default: + ; + } } - } - break; + break; - default: - // If a frame is centered, it gets left aligned. This - // should be taken into account here, too. - { - switch( eSurround ) + default: + // If a frame is centered, it gets left aligned. This + // should be taken into account here, too. { - case css::text::WrapTextMode_NONE: - case css::text::WrapTextMode_LEFT: - pStr = OOO_STRING_SVTOOLS_HTML_AL_left; - break; - case css::text::WrapTextMode_RIGHT: - case css::text::WrapTextMode_PARALLEL: - if( bAnchorOnly ) - m_bClearLeft = true; - break; - default: - ; + switch( eSurround ) + { + case css::text::WrapTextMode_NONE: + case css::text::WrapTextMode_LEFT: + pStr = OOO_STRING_SVTOOLS_HTML_AL_left; + break; + case css::text::WrapTextMode_RIGHT: + case css::text::WrapTextMode_PARALLEL: + if( bAnchorOnly ) + m_bClearLeft = true; + break; + default: + ; + } } - } - break; + break; - } + } - if( pStr ) - { - sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_linebreak). - append(' ').append(OOO_STRING_SVTOOLS_HTML_O_clear). - append("=\"").append(pStr).append("\">"); - sRetEndTags = sOut.makeStringAndClear(); + if( pStr ) + { + sOut.append("<" OOO_STRING_SVTOOLS_HTML_linebreak + " " OOO_STRING_SVTOOLS_HTML_O_clear + "=\"" + OString::Concat(pStr) + "\">"); + sRetEndTags = sOut.makeStringAndClear(); + } } } return sRetEndTags; } -void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameFormat& rFrameFormat, std::u16string_view rAlternateText, HtmlFrmOpts nFrameOptions) +void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameFormat& rFrameFormat, const OUString& rAlternateText, HtmlFrmOpts nFrameOptions) { bool bReplacement = (nFrameOptions & HtmlFrmOpts::Replacement) || mbReqIF; - const SfxPoolItem* pItem; const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet(); // Name @@ -822,13 +796,13 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameForma } // alt - if( (nFrameOptions & HtmlFrmOpts::Alt) && !rAlternateText.empty() && !bReplacement ) + if( (nFrameOptions & HtmlFrmOpts::Alt) && !rAlternateText.isEmpty() && !bReplacement ) { aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_alt, rAlternateText); } // align - const char* pAlignString = nullptr; + std::string_view pAlignString; RndStdIds eAnchorId = rFrameFormat.GetAnchor().GetAnchorId(); if( (nFrameOptions & HtmlFrmOpts::Align) && ((RndStdIds::FLY_AT_PARA == eAnchorId) || (RndStdIds::FLY_AT_CHAR == eAnchorId)) && !bReplacement) @@ -839,16 +813,17 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameForma text::RelOrientation::PRINT_AREA == rHoriOri.GetRelationOrient() ) { pAlignString = text::HoriOrientation::RIGHT == rHoriOri.GetHoriOrient() - ? OOO_STRING_SVTOOLS_HTML_AL_right - : OOO_STRING_SVTOOLS_HTML_AL_left; + ? std::string_view(OOO_STRING_SVTOOLS_HTML_AL_right) + : std::string_view(OOO_STRING_SVTOOLS_HTML_AL_left); } } - if( (nFrameOptions & HtmlFrmOpts::Align) && !pAlignString && + const SwFormatVertOrient* pVertOrient; + if( (nFrameOptions & HtmlFrmOpts::Align) && pAlignString.empty() && ( !(nFrameOptions & HtmlFrmOpts::SAlign) || (RndStdIds::FLY_AS_CHAR == eAnchorId) ) && - SfxItemState::SET == rItemSet.GetItemState( RES_VERT_ORIENT, true, &pItem )) + (pVertOrient = rItemSet.GetItemIfSet( RES_VERT_ORIENT )) ) { - switch( static_cast<const SwFormatVertOrient*>(pItem)->GetVertOrient() ) + switch( pVertOrient->GetVertOrient() ) { case text::VertOrientation::LINE_TOP: pAlignString = OOO_STRING_SVTOOLS_HTML_VA_top; break; case text::VertOrientation::CHAR_TOP: @@ -862,41 +837,35 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameForma case text::VertOrientation::NONE: break; } } - if (pAlignString && !bReplacement) + if (!pAlignString.empty() && !bReplacement) { aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_align, pAlignString); } // hspace and vspace Size aTwipSpc( 0, 0 ); + const SvxLRSpaceItem* pLRSpaceItem; if( (nFrameOptions & (HtmlFrmOpts::Space | HtmlFrmOpts::MarginSize)) && - SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE, true, &pItem )) + (pLRSpaceItem = rItemSet.GetItemIfSet( RES_LR_SPACE )) ) { aTwipSpc.setWidth( - ( static_cast<const SvxLRSpaceItem*>(pItem)->GetLeft() + - static_cast<const SvxLRSpaceItem*>(pItem)->GetRight() ) / 2 ); + ( pLRSpaceItem->GetLeft() + pLRSpaceItem->GetRight() ) / 2 ); m_nDfltLeftMargin = m_nDfltRightMargin = aTwipSpc.Width(); } + const SvxULSpaceItem* pULSpaceItem; if( (nFrameOptions & (HtmlFrmOpts::Space|HtmlFrmOpts::MarginSize)) && - SfxItemState::SET == rItemSet.GetItemState( RES_UL_SPACE, true, &pItem )) + (pULSpaceItem = rItemSet.GetItemIfSet( RES_UL_SPACE )) ) { aTwipSpc.setHeight( - ( static_cast<const SvxULSpaceItem*>(pItem)->GetUpper() + - static_cast<const SvxULSpaceItem*>(pItem)->GetLower() ) / 2 ); - m_nDfltTopMargin = m_nDfltBottomMargin = static_cast<sal_uInt16>(aTwipSpc.Height()); + ( pULSpaceItem->GetUpper() + pULSpaceItem->GetLower() ) / 2 ); + m_nDfltTopMargin = m_nDfltBottomMargin = o3tl::narrowing<sal_uInt16>(aTwipSpc.Height()); } if( (nFrameOptions & HtmlFrmOpts::Space) && (aTwipSpc.Width() || aTwipSpc.Height()) && - Application::GetDefaultDevice() ) + !mbReqIF ) { - Size aPixelSpc = - Application::GetDefaultDevice()->LogicToPixel( aTwipSpc, - MapMode(MapUnit::MapTwip) ); - if( !aPixelSpc.Width() && aTwipSpc.Width() ) - aPixelSpc.setWidth( 1 ); - if( !aPixelSpc.Height() && aTwipSpc.Height() ) - aPixelSpc.setHeight( 1 ); + Size aPixelSpc = SwHTMLWriter::ToPixel(aTwipSpc); if (aPixelSpc.Width()) { @@ -922,11 +891,10 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameForma aTwipSpc.setHeight( 0 ); } + const SvxBoxItem* pBoxItem; if( !(nFrameOptions & HtmlFrmOpts::AbsSize) && - SfxItemState::SET == rItemSet.GetItemState( RES_BOX, true, &pItem )) + (pBoxItem = rItemSet.GetItemIfSet( RES_BOX )) ) { - const SvxBoxItem* pBoxItem = static_cast<const SvxBoxItem*>(pItem); - aTwipSpc.AdjustWidth(pBoxItem->CalcLineSpace( SvxBoxItemLine::LEFT ) ); aTwipSpc.AdjustWidth(pBoxItem->CalcLineSpace( SvxBoxItemLine::RIGHT ) ); aTwipSpc.AdjustHeight(pBoxItem->CalcLineSpace( SvxBoxItemLine::TOP ) ); @@ -935,49 +903,70 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameForma // "width" and/or "height" // Only output SwFrameSize::Variable/SwFrameSize::Minimum if ANYSIZE is set + std::optional<SwFormatFrameSize> aFrameSize; + const SwFormatFrameSize* pFSItem = rItemSet.GetItemIfSet( RES_FRM_SIZE ); + const SdrObject* pObject; + if (!pFSItem && (pObject = rFrameFormat.FindSdrObject())) + { + // Write size for Draw shapes as well. + const tools::Rectangle& rSnapRect = pObject->GetSnapRect(); + aFrameSize.emplace(); + aFrameSize->SetWidthSizeType(SwFrameSize::Fixed); + aFrameSize->SetWidth(rSnapRect.getOpenWidth()); + aFrameSize->SetHeightSizeType(SwFrameSize::Fixed); + aFrameSize->SetHeight(rSnapRect.getOpenHeight()); + pFSItem = &*aFrameSize; + } if( (nFrameOptions & HtmlFrmOpts::Size) && - SfxItemState::SET == rItemSet.GetItemState( RES_FRM_SIZE, true, &pItem ) && + pFSItem && ( (nFrameOptions & HtmlFrmOpts::AnySize) || - SwFrameSize::Fixed == static_cast<const SwFormatFrameSize *>(pItem)->GetHeightSizeType()) ) + SwFrameSize::Fixed == pFSItem->GetHeightSizeType()) ) { - const SwFormatFrameSize *pFSItem = static_cast<const SwFormatFrameSize *>(pItem); sal_uInt8 nPercentWidth = pFSItem->GetWidthPercent(); sal_uInt8 nPercentHeight = pFSItem->GetHeightPercent(); // Size of the object in Twips without margins - Size aTwipSz( (nPercentWidth ? 0 + Size aTwipSz( (nPercentWidth && nPercentWidth != 255 ? 0 : pFSItem->GetWidth()-aTwipSpc.Width()), - (nPercentHeight ? 0 + (nPercentHeight && nPercentHeight != 255 ? 0 : pFSItem->GetHeight()-aTwipSpc.Height()) ); - OSL_ENSURE( !aTwipSz.IsEmpty(), "Frame size minus spacing < 0!!!???" ); + OSL_ENSURE( aTwipSz.Width() >= 0 && aTwipSz.Height() >= 0, "Frame size minus spacing < 0!!!???" ); if( aTwipSz.Width() < 0 ) aTwipSz.setWidth( 0 ); if( aTwipSz.Height() < 0 ) aTwipSz.setHeight( 0 ); - Size aPixelSz( 0, 0 ); - if( (aTwipSz.Width() || aTwipSz.Height()) && - Application::GetDefaultDevice() ) - { - aPixelSz = - Application::GetDefaultDevice()->LogicToPixel( aTwipSz, - MapMode(MapUnit::MapTwip) ); - if( !aPixelSz.Width() && aTwipSz.Width() ) - aPixelSz.setWidth( 1 ); - if( !aPixelSz.Height() && aTwipSz.Height() ) - aPixelSz.setHeight( 1 ); - } + Size aPixelSz(SwHTMLWriter::ToPixel(aTwipSz)); if( (nFrameOptions & HtmlFrmOpts::Width) && ((nPercentWidth && nPercentWidth!=255) || aPixelSz.Width()) ) { OString sWidth; if (nPercentWidth) - sWidth = OString::number(static_cast<sal_Int32>(nPercentWidth)) + "%"; + { + if (nPercentWidth == 255) + { + if (nPercentHeight) + { + sWidth = "auto"_ostr; + } + else + { + sWidth = OString::number(static_cast<sal_Int32>(aPixelSz.Width())); + } + } + else + { + sWidth = OString::number(static_cast<sal_Int32>(nPercentWidth)) + "%"; + } + } else sWidth = OString::number(static_cast<sal_Int32>(aPixelSz.Width())); - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_width, sWidth); + if (!mbXHTML || sWidth != "auto") + { + aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_width, sWidth); + } } if( (nFrameOptions & HtmlFrmOpts::Height) && @@ -985,25 +974,49 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameForma { OString sHeight; if (nPercentHeight) - sHeight = OString::number(static_cast<sal_Int32>(nPercentHeight)) + "%"; + { + if (nPercentHeight == 255) + { + if (nPercentWidth) + { + sHeight = "auto"_ostr; + } + else + { + sHeight = OString::number(static_cast<sal_Int32>(aPixelSz.Height())); + } + } + else + { + sHeight = OString::number(static_cast<sal_Int32>(nPercentHeight)) + "%"; + } + } else sHeight = OString::number(static_cast<sal_Int32>(aPixelSz.Height())); - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_height, sHeight); + if (!mbXHTML || sHeight != "auto") + { + aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_height, sHeight); + } } } + if (mbReqIF) + return; + // Insert wrap for graphics that are anchored to a paragraph as // <BR CLEAR=...> in the string - if( !((nFrameOptions & HtmlFrmOpts::BrClear) && - ((RndStdIds::FLY_AT_PARA == rFrameFormat.GetAnchor().GetAnchorId()) || - (RndStdIds::FLY_AT_CHAR == rFrameFormat.GetAnchor().GetAnchorId())) && - SfxItemState::SET == rItemSet.GetItemState( RES_SURROUND, true, &pItem ))) + if( !(nFrameOptions & HtmlFrmOpts::BrClear) ) + return; + RndStdIds nAnchorId = rFrameFormat.GetAnchor().GetAnchorId(); + if (RndStdIds::FLY_AT_PARA != nAnchorId && RndStdIds::FLY_AT_CHAR != nAnchorId) + return; + const SwFormatSurround* pSurround = rItemSet.GetItemIfSet( RES_SURROUND ); + if (!pSurround) return; - const char* pSurroundString = nullptr; + std::string_view pSurroundString; - const SwFormatSurround* pSurround = static_cast<const SwFormatSurround*>(pItem); sal_Int16 eHoriOri = rFrameFormat.GetHoriOrient().GetHoriOrient(); css::text::WrapTextMode eSurround = pSurround->GetSurround(); bool bAnchorOnly = pSurround->IsAnchorOnly(); @@ -1050,9 +1063,9 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameForma break; } - if (pSurroundString) + if (!pSurroundString.empty()) { - aHtml.start(OOO_STRING_SVTOOLS_HTML_linebreak); + aHtml.start(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr); aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, pSurroundString); aHtml.end(); } @@ -1061,18 +1074,14 @@ void SwHTMLWriter::writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameForma namespace { -OUString lclWriteOutImap(SwHTMLWriter& rHTMLWrt, const SfxItemSet& rItemSet, const SwFrameFormat& rFrameFormat, +OUString lclWriteOutImap(SwHTMLWriter& rWrt, const SfxItemSet& rItemSet, const SwFrameFormat& rFrameFormat, const Size& rRealSize, const ImageMap* pAltImgMap, const SwFormatURL*& pURLItem) { OUString aIMapName; - const SfxPoolItem* pItem; - // Only consider the URL attribute if no ImageMap was supplied - if (!pAltImgMap && SfxItemState::SET == rItemSet.GetItemState( RES_URL, true, &pItem)) - { - pURLItem = static_cast<const SwFormatURL*>( pItem); - } + if (!pAltImgMap) + pURLItem = rItemSet.GetItemIfSet( RES_URL ); // write ImageMap const ImageMap* pIMap = pAltImgMap; @@ -1092,13 +1101,13 @@ OUString lclWriteOutImap(SwHTMLWriter& rHTMLWrt, const SfxItemSet& rItemSet, con aNameBase = OOO_STRING_SVTOOLS_HTML_map; if (aIMapName.isEmpty()) - aIMapName = aNameBase + OUString::number(rHTMLWrt.m_nImgMapCnt); + aIMapName = aNameBase + OUString::number(rWrt.m_nImgMapCnt); bool bFound; do { bFound = false; - for (const OUString & rImgMapName : rHTMLWrt.m_aImgMapNames) + for (const OUString & rImgMapName : rWrt.m_aImgMapNames) { // TODO: Unicode: Comparison is case insensitive for ASCII // characters only now! @@ -1110,8 +1119,8 @@ OUString lclWriteOutImap(SwHTMLWriter& rHTMLWrt, const SfxItemSet& rItemSet, con } if (bFound) { - rHTMLWrt.m_nImgMapCnt++; - aIMapName = aNameBase + OUString::number( rHTMLWrt.m_nImgMapCnt ); + rWrt.m_nImgMapCnt++; + aIMapName = aNameBase + OUString::number( rWrt.m_nImgMapCnt ); } } while (bFound); @@ -1155,16 +1164,16 @@ OUString lclWriteOutImap(SwHTMLWriter& rHTMLWrt, const SfxItemSet& rItemSet, con } } - rHTMLWrt.m_aImgMapNames.push_back(aIMapName); + rWrt.m_aImgMapNames.push_back(aIMapName); OString aIndMap, aIndArea; const char *pIndArea = nullptr, *pIndMap = nullptr; - if (rHTMLWrt.m_bLFPossible) + if (rWrt.IsLFPossible()) { - rHTMLWrt.OutNewLine( true ); - aIndMap = rHTMLWrt.GetIndentString(); - aIndArea = rHTMLWrt.GetIndentString(1); + rWrt.OutNewLine( true ); + aIndMap = rWrt.GetIndentString(); + aIndArea = rWrt.GetIndentString(1); pIndArea = aIndArea.getStr(); pIndMap = aIndMap.getStr(); } @@ -1173,29 +1182,53 @@ OUString lclWriteOutImap(SwHTMLWriter& rHTMLWrt, const SfxItemSet& rItemSet, con { ImageMap aScaledIMap(*pIMap); aScaledIMap.Scale(aScaleX, aScaleY); - HTMLOutFuncs::Out_ImageMap( rHTMLWrt.Strm(), rHTMLWrt.GetBaseURL(), aScaledIMap, aIMapName, + HTMLOutFuncs::Out_ImageMap( rWrt.Strm(), rWrt.GetBaseURL(), aScaledIMap, aIMapName, aIMapEventTable, - rHTMLWrt.m_bCfgStarBasic, - SAL_NEWLINE_STRING, pIndArea, pIndMap, - rHTMLWrt.m_eDestEnc, - &rHTMLWrt.m_aNonConvertableCharacters ); + rWrt.m_bCfgStarBasic, + SAL_NEWLINE_STRING, pIndArea, pIndMap ); } else { - HTMLOutFuncs::Out_ImageMap( rHTMLWrt.Strm(), rHTMLWrt.GetBaseURL(), *pIMap, aIMapName, + HTMLOutFuncs::Out_ImageMap( rWrt.Strm(), rWrt.GetBaseURL(), *pIMap, aIMapName, aIMapEventTable, - rHTMLWrt.m_bCfgStarBasic, - SAL_NEWLINE_STRING, pIndArea, pIndMap, - rHTMLWrt.m_eDestEnc, - &rHTMLWrt.m_aNonConvertableCharacters ); + rWrt.m_bCfgStarBasic, + SAL_NEWLINE_STRING, pIndArea, pIndMap ); } } return aIMapName; } +OUString getFrameFormatText(const SwFrameFormat& rFrameFormat) +{ + const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); + const SwNodeIndex* pSttIx = rFlyContent.GetContentIdx(); + if (!pSttIx) + return {}; + + const SwNodeOffset nStt = pSttIx->GetIndex(); + const auto& nodes = rFrameFormat.GetDoc()->GetNodes(); + const SwNodeOffset nEnd = nodes[nStt]->EndOfSectionIndex(); + + OUStringBuffer result; + for (SwNodeOffset i = nStt + 1; i < nEnd; ++i) + { + if (const auto* pTextNd = nodes[i]->GetTextNode()) + { + if (!result.isEmpty()) + result.append("\n"); + result.append(comphelper::string::encodeForXml(pTextNd->GetExpandText( + nullptr, 0, -1, true, true, false, + ExpandMode::ExpandFields | ExpandMode::HideInvisible | ExpandMode::HideDeletions + | ExpandMode::HideFieldmarkCommands))); + } + } + + return result.makeStringAndClear(); +} + } -Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat, +SwHTMLWriter& OutHTML_ImageStart( HtmlWriter& rHtml, SwHTMLWriter& rWrt, const SwFrameFormat &rFrameFormat, const OUString& rGraphicURL, Graphic const & rGraphic, const OUString& rAlternateText, const Size &rRealSize, HtmlFrmOpts nFrameOpts, @@ -1203,48 +1236,40 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat, const ImageMap *pAltImgMap, const OUString& rMimeType ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); // <object data="..."> instead of <img src="..."> - bool bReplacement = (nFrameOpts & HtmlFrmOpts::Replacement) || rHTMLWrt.mbReqIF; + bool bReplacement = (nFrameOpts & HtmlFrmOpts::Replacement) || rWrt.mbReqIF; - if (rHTMLWrt.mbSkipImages) - return rHTMLWrt; + if (rWrt.mbSkipImages) + return rWrt; // if necessary, temporarily close an open attribute - if( !rHTMLWrt.m_aINetFormats.empty() ) + if( !rWrt.m_aINetFormats.empty() ) { - SwFormatINetFormat* pINetFormat = rHTMLWrt.m_aINetFormats.back(); + SwFormatINetFormat* pINetFormat = rWrt.m_aINetFormats.back(); OutHTML_INetFormat( rWrt, *pINetFormat, false ); } OUString aGraphicURL( rGraphicURL ); - if( !rHTMLWrt.mbEmbedImages && !HTMLOutFuncs::PrivateURLToInternalImg(aGraphicURL) && !rHTMLWrt.mpTempBaseURL ) + if( !rWrt.mbEmbedImages && !HTMLOutFuncs::PrivateURLToInternalImg(aGraphicURL) && !rWrt.mpTempBaseURL ) aGraphicURL = URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(), aGraphicURL); - const SfxPoolItem* pItem; const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet(); const SwFormatURL* pURLItem = nullptr; - OUString aIMapName = lclWriteOutImap(rHTMLWrt, rItemSet, rFrameFormat, rRealSize, pAltImgMap, pURLItem); + OUString aIMapName = lclWriteOutImap(rWrt, rItemSet, rFrameFormat, rRealSize, pAltImgMap, pURLItem); // put img into new line - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine( true ); - - HtmlWriter aHtml(rWrt.Strm(), rHTMLWrt.maNamespace); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine( true ); // <a name=...></a>...<img ...> if( pMarkType && !rFrameFormat.GetName().isEmpty() ) { - rHTMLWrt.OutImplicitMark( rFrameFormat.GetName(), pMarkType ); + rWrt.OutImplicitMark( rFrameFormat.GetName(), pMarkType ); } // URL -> <a>...<img ... >...</a> - const SvxMacroItem *pMacItem = nullptr; - if (SfxItemState::SET == rItemSet.GetItemState(RES_FRMMACRO, true, &pItem)) - { - pMacItem = static_cast<const SvxMacroItem *>(pItem); - } + const SvxMacroItem *pMacItem = rItemSet.GetItemIfSet(RES_FRMMACRO); if (pURLItem || pMacItem) { @@ -1263,22 +1288,22 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat, if( !aMapURL.isEmpty() || !aName.isEmpty() || !aTarget.isEmpty() || bEvents ) { - aHtml.start(OOO_STRING_SVTOOLS_HTML_anchor); + rHtml.start(OOO_STRING_SVTOOLS_HTML_anchor ""_ostr); // Output "href" element if a link or macro exists if( !aMapURL.isEmpty() || bEvents ) { - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_href, OUStringToOString(rHTMLWrt.convertHyperlinkHRefValue(aMapURL), RTL_TEXTENCODING_UTF8)); + rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_href, rWrt.convertHyperlinkHRefValue(aMapURL)); } if( !aName.isEmpty() ) { - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_name, OUStringToOString(aName, RTL_TEXTENCODING_UTF8)); + rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_name, aName); } if( !aTarget.isEmpty() ) { - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_target, OUStringToOString(aTarget, RTL_TEXTENCODING_UTF8)); + rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_target, aTarget); } if( pMacItem ) @@ -1286,7 +1311,7 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat, const SvxMacroTableDtor& rMacTable = pMacItem->GetMacroTable(); if (!rMacTable.empty()) { - HtmlWriterHelper::applyEvents(aHtml, rMacTable, aAnchorEventTable, rHTMLWrt.m_bCfgStarBasic); + HtmlWriterHelper::applyEvents(rHtml, rMacTable, aAnchorEventTable, rWrt.m_bCfgStarBasic); } } } @@ -1294,12 +1319,11 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat, // <font color = ...>...<img ... >...</font> sal_uInt16 nBorderWidth = 0; + const SvxBoxItem* pBoxItem; if( (nFrameOpts & HtmlFrmOpts::Border) && - SfxItemState::SET == rItemSet.GetItemState( RES_BOX, true, &pItem )) + (pBoxItem = rItemSet.GetItemIfSet( RES_BOX )) ) { Size aTwipBorder( 0, 0 ); - const SvxBoxItem* pBoxItem = static_cast<const SvxBoxItem*>(pItem); - const ::editeng::SvxBorderLine *pColBorderLine = nullptr; const ::editeng::SvxBorderLine *pBorderLine = pBoxItem->GetLeft(); if( pBorderLine ) @@ -1335,150 +1359,152 @@ Writer& OutHTML_Image( Writer& rWrt, const SwFrameFormat &rFrameFormat, if( (aTwipBorder.Width() || aTwipBorder.Height()) && Application::GetDefaultDevice() ) { - Size aPixelBorder = - Application::GetDefaultDevice()->LogicToPixel( aTwipBorder, - MapMode(MapUnit::MapTwip) ); - if( !aPixelBorder.Width() && aTwipBorder.Width() ) - aPixelBorder.setWidth( 1 ); - if( !aPixelBorder.Height() && aTwipBorder.Height() ) - aPixelBorder.setHeight( 1 ); + Size aPixelBorder = SwHTMLWriter::ToPixel(aTwipBorder); if( aPixelBorder.Width() ) aPixelBorder.setHeight( 0 ); nBorderWidth = - static_cast<sal_uInt16>(aPixelBorder.Width() + aPixelBorder.Height()); + o3tl::narrowing<sal_uInt16>(aPixelBorder.Width() + aPixelBorder.Height()); } if( pColBorderLine ) { - aHtml.start(OOO_STRING_SVTOOLS_HTML_font); - HtmlWriterHelper::applyColor(aHtml, OOO_STRING_SVTOOLS_HTML_O_color, pColBorderLine->GetColor()); + rHtml.start(OOO_STRING_SVTOOLS_HTML_font ""_ostr); + HtmlWriterHelper::applyColor(rHtml, OOO_STRING_SVTOOLS_HTML_O_color, pColBorderLine->GetColor()); } } - OString aTag(OOO_STRING_SVTOOLS_HTML_image); + OString aTag(OOO_STRING_SVTOOLS_HTML_image ""_ostr); if (bReplacement) // Write replacement graphic of OLE object as <object>. - aTag = OOO_STRING_SVTOOLS_HTML_object; - aHtml.start(aTag); + aTag = OOO_STRING_SVTOOLS_HTML_object ""_ostr; + rHtml.start(aTag); - OStringBuffer sBuffer; - if(rHTMLWrt.mbEmbedImages) + if(rWrt.mbEmbedImages) { OUString aGraphicInBase64; if (XOutBitmap::GraphicToBase64(rGraphic, aGraphicInBase64)) { - sBuffer.append(OOO_STRING_SVTOOLS_HTML_O_data); - sBuffer.append(":"); - sBuffer.append(OUStringToOString(aGraphicInBase64, RTL_TEXTENCODING_UTF8)); - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_src, sBuffer.makeStringAndClear().getStr()); + OString sBuffer(OString::Concat(OOO_STRING_SVTOOLS_HTML_O_data) + + ":" + + OUStringToOString(aGraphicInBase64, RTL_TEXTENCODING_UTF8)); + rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_src, sBuffer); } else - rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD; + rWrt.m_nWarn = WARN_SWG_POOR_LOAD; } else { - sBuffer.append(OUStringToOString(aGraphicURL, RTL_TEXTENCODING_UTF8)); - OString aAttribute(OOO_STRING_SVTOOLS_HTML_O_src); + OString sBuffer(OUStringToOString(aGraphicURL, RTL_TEXTENCODING_UTF8)); + OString aAttribute(OOO_STRING_SVTOOLS_HTML_O_src ""_ostr); if (bReplacement) - aAttribute = OOO_STRING_SVTOOLS_HTML_O_data; - aHtml.attribute(aAttribute, sBuffer.makeStringAndClear().getStr()); + aAttribute = OOO_STRING_SVTOOLS_HTML_O_data ""_ostr; + rHtml.attribute(aAttribute, sBuffer); } if (bReplacement) { // Handle XHTML type attribute for OLE replacement images. if (!rMimeType.isEmpty()) - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_type, rMimeType.toUtf8()); + rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_type, rMimeType); } // Events - if (SfxItemState::SET == rItemSet.GetItemState(RES_FRMMACRO, true, &pItem)) + if (const SvxMacroItem* pMacroItem = rItemSet.GetItemIfSet(RES_FRMMACRO)) { - const SvxMacroTableDtor& rMacTable = static_cast<const SvxMacroItem *>(pItem)->GetMacroTable(); + const SvxMacroTableDtor& rMacTable = pMacroItem->GetMacroTable(); if (!rMacTable.empty()) { - HtmlWriterHelper::applyEvents(aHtml, rMacTable, aImageEventTable, rHTMLWrt.m_bCfgStarBasic); + HtmlWriterHelper::applyEvents(rHtml, rMacTable, aImageEventTable, rWrt.m_bCfgStarBasic); } } // alt, align, width, height, hspace, vspace - rHTMLWrt.writeFrameFormatOptions(aHtml, rFrameFormat, rAlternateText, nFrameOpts); - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) ) - rHTMLWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts ); + rWrt.writeFrameFormatOptions(rHtml, rFrameFormat, rAlternateText, nFrameOpts); + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) ) + rWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts ); if ((nFrameOpts & HtmlFrmOpts::Border) && !bReplacement) { - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_border, nBorderWidth); + rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_border, nBorderWidth); } if( pURLItem && pURLItem->IsServerMap() ) { - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_ismap); + rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_ismap); } if( !aIMapName.isEmpty() ) { - aHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_usemap, OUString("#" + aIMapName)); + rHtml.attribute(OOO_STRING_SVTOOLS_HTML_O_usemap, "#" + aIMapName); } if (bReplacement) { + OUString aAltText = rAlternateText; + // In ReqIF mode, output text from the frame instead + if (rWrt.mbReqIF) + if (OUString aFrameText = getFrameFormatText(rFrameFormat); !aFrameText.isEmpty()) + aAltText = aFrameText; + // XHTML object replacement image's alternate text doesn't use the // "alt" attribute. - if (rAlternateText.isEmpty()) + if (aAltText.isEmpty()) // Empty alternate text is not valid. - aHtml.characters(" "); + rHtml.characters(" "); else - aHtml.characters(rAlternateText.toUtf8()); + rHtml.characters(aAltText.toUtf8()); } - aHtml.flushStack(); + return rWrt; +} + +SwHTMLWriter& OutHTML_ImageEnd( HtmlWriter& rHtml, SwHTMLWriter& rWrt ) +{ + rHtml.flushStack(); - if( !rHTMLWrt.m_aINetFormats.empty() ) + if( !rWrt.m_aINetFormats.empty() ) { // There is still an attribute on the stack that has to be reopened - SwFormatINetFormat *pINetFormat = rHTMLWrt.m_aINetFormats.back(); + SwFormatINetFormat *pINetFormat = rWrt.m_aINetFormats.back(); OutHTML_INetFormat( rWrt, *pINetFormat, true ); } - return rHTMLWrt; + return rWrt; } -Writer& OutHTML_BulletImage( Writer& rWrt, +SwHTMLWriter& OutHTML_BulletImage( SwHTMLWriter& rWrt, const char *pTag, const SvxBrushItem* pBrush, const OUString &rGraphicURL) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - OUString aGraphicInBase64; OUString aLink; if( pBrush ) { aLink = pBrush->GetGraphicLink(); - if(rHTMLWrt.mbEmbedImages || aLink.isEmpty()) + if(rWrt.mbEmbedImages || aLink.isEmpty()) { const Graphic* pGrf = pBrush->GetGraphic(); if( pGrf ) { if( !XOutBitmap::GraphicToBase64(*pGrf, aGraphicInBase64) ) { - rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD; + rWrt.m_nWarn = WARN_SWG_POOR_LOAD; } } } else if(!aLink.isEmpty()) { - if( rHTMLWrt.m_bCfgCpyLinkedGrfs ) + if( rWrt.m_bCfgCpyLinkedGrfs ) { - rHTMLWrt.CopyLocalFileToINet( aLink ); + rWrt.CopyLocalFileToINet( aLink ); } } } - else if(!rHTMLWrt.mbEmbedImages) + else if(!rWrt.mbEmbedImages) { aLink = rGraphicURL; } @@ -1490,98 +1516,94 @@ Writer& OutHTML_BulletImage( Writer& rWrt, OStringBuffer sOut; if( pTag ) - sOut.append('<').append(pTag); + sOut.append(OString::Concat("<") + pTag); - sOut.append(' '); - sOut.append(OOO_STRING_SVTOOLS_HTML_O_style).append("=\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_style "=\""); if(!aLink.isEmpty()) { - sOut.append(OOO_STRING_SVTOOLS_HTML_O_src).append("=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aLink, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append(OOO_STRING_SVTOOLS_HTML_O_src "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), aLink ); } else { - sOut.append("list-style-image: ").append("url("). - append(OOO_STRING_SVTOOLS_HTML_O_data).append(":"); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aGraphicInBase64, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append("list-style-image: url(" + OOO_STRING_SVTOOLS_HTML_O_data ":"); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), aGraphicInBase64 ); sOut.append(");"); } sOut.append('\"'); if (pTag) sOut.append('>'); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); return rWrt; } -static Writer& OutHTML_FrameFormatTableNode( Writer& rWrt, const SwFrameFormat& rFrameFormat ) +static SwHTMLWriter& OutHTML_FrameFormatTableNode( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); - sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1; - sal_uLong nEnd = rHTMLWrt.m_pDoc->GetNodes()[nStt-1]->EndOfSectionIndex(); + SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1; + SwNodeOffset nEnd = rWrt.m_pDoc->GetNodes()[nStt-1]->EndOfSectionIndex(); OUString aCaption; bool bTopCaption = false; // Not const, because GetTable won't be const sometime later - SwNode *pNd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]; + SwNode *pNd = rWrt.m_pDoc->GetNodes()[ nStt ]; SwTableNode *pTableNd = pNd->GetTableNode(); const SwTextNode *pTextNd = pNd->GetTextNode(); if( !pTableNd && pTextNd ) { // Table with heading bTopCaption = true; - pTableNd = rHTMLWrt.m_pDoc->GetNodes()[nStt+1]->GetTableNode(); + pTableNd = rWrt.m_pDoc->GetNodes()[nStt+1]->GetTableNode(); } OSL_ENSURE( pTableNd, "Frame does not contain a table" ); if( pTableNd ) { - sal_uLong nTableEnd = pTableNd->EndOfSectionIndex(); + SwNodeOffset nTableEnd = pTableNd->EndOfSectionIndex(); OSL_ENSURE( nTableEnd == nEnd - 1 || (nTableEnd == nEnd - 2 && !bTopCaption), "Invalid frame content for a table" ); if( nTableEnd == nEnd - 2 ) - pTextNd = rHTMLWrt.m_pDoc->GetNodes()[nTableEnd+1]->GetTextNode(); + pTextNd = rWrt.m_pDoc->GetNodes()[nTableEnd+1]->GetTextNode(); } if( pTextNd ) aCaption = pTextNd->GetText(); if( pTableNd ) { - HTMLSaveData aSaveData( rHTMLWrt, pTableNd->GetIndex()+1, + HTMLSaveData aSaveData( rWrt, pTableNd->GetIndex()+1, pTableNd->EndOfSectionIndex(), true, &rFrameFormat ); - rHTMLWrt.m_bOutFlyFrame = true; - OutHTML_SwTableNode( rHTMLWrt, *pTableNd, &rFrameFormat, &aCaption, + rWrt.m_bOutFlyFrame = true; + OutHTML_SwTableNode( rWrt, *pTableNd, &rFrameFormat, &aCaption, bTopCaption ); } return rWrt; } -static Writer & OutHTML_FrameFormatAsMulticol( Writer& rWrt, +static SwHTMLWriter & OutHTML_FrameFormatAsMulticol( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, bool bInCntnr ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - - rHTMLWrt.ChangeParaToken( HtmlTokenId::NONE ); + rWrt.ChangeParaToken( HtmlTokenId::NONE ); // Close the current <DL>! - rHTMLWrt.OutAndSetDefList( 0 ); + rWrt.OutAndSetDefList( 0 ); // output as Multicol - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); - OStringBuffer sOut; - sOut.append('<').append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_multicol); + OStringBuffer sOut("<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_multicol); const SwFormatCol& rFormatCol = rFrameFormat.GetCol(); @@ -1589,79 +1611,73 @@ static Writer & OutHTML_FrameFormatAsMulticol( Writer& rWrt, sal_uInt16 nCols = rFormatCol.GetNumCols(); if( nCols ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_cols). - append("=\"").append(static_cast<sal_Int32>(nCols)).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cols + "=\"" + OString::number(nCols) + "\""); } // the Gutter width (minimum value) as GUTTER sal_uInt16 nGutter = rFormatCol.GetGutterWidth( true ); if( nGutter!=USHRT_MAX ) { - if( nGutter && Application::GetDefaultDevice() ) - { - nGutter = static_cast<sal_uInt16>(Application::GetDefaultDevice() - ->LogicToPixel( Size(nGutter,0), - MapMode(MapUnit::MapTwip) ).Width()); - } - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_gutter). - append("=\"").append(static_cast<sal_Int32>(nGutter)).append("\""); + nGutter = SwHTMLWriter::ToPixel(nGutter); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_gutter + "=\"" + OString::number(nGutter) + "\""); } - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); // WIDTH HtmlFrmOpts nFrameFlags = HTML_FRMOPTS_MULTICOL; - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) nFrameFlags |= HTML_FRMOPTS_MULTICOL_CSS1; - rHTMLWrt.OutFrameFormatOptions(rFrameFormat, OUString(), nFrameFlags); - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) - rHTMLWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameFlags ); + rWrt.OutFrameFormatOptions(rFrameFormat, u"", nFrameFlags); + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) + rWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameFlags ); rWrt.Strm().WriteChar( '>' ); - rHTMLWrt.m_bLFPossible = true; - rHTMLWrt.IncIndentLevel(); // indent the content of Multicol + rWrt.SetLFPossible(true); + rWrt.IncIndentLevel(); // indent the content of Multicol const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); - sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex(); + SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex(); const SwStartNode* pSttNd = rWrt.m_pDoc->GetNodes()[nStt]->GetStartNode(); OSL_ENSURE( pSttNd, "Where is the start node" ); { // in a block, so that the old state can be restored in time // before the end - HTMLSaveData aSaveData( rHTMLWrt, nStt+1, + HTMLSaveData aSaveData( rWrt, nStt+1, pSttNd->EndOfSectionIndex(), true, &rFrameFormat ); - rHTMLWrt.m_bOutFlyFrame = true; - rHTMLWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() ); + rWrt.m_bOutFlyFrame = true; + rWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() ); } - rHTMLWrt.DecIndentLevel(); // indent the content of Multicol; - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_multicol, false ); - rHTMLWrt.m_bLFPossible = true; + rWrt.DecIndentLevel(); // indent the content of Multicol; + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_multicol), false ); + rWrt.SetLFPossible(true); return rWrt; } -static Writer& OutHTML_FrameFormatAsSpacer( Writer& rWrt, const SwFrameFormat& rFrameFormat ) +static SwHTMLWriter& OutHTML_FrameFormatAsSpacer( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // if possible, output a line break before the graphic - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine( true ); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine( true ); OString sOut = - "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_spacer " " + "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_spacer " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" OOO_STRING_SVTOOLS_HTML_SPTYPE_block "\""; rWrt.Strm().WriteOString( sOut ); // ALIGN, WIDTH, HEIGHT - OString aEndTags = rHTMLWrt.OutFrameFormatOptions(rFrameFormat, OUString(), HTML_FRMOPTS_SPACER); + OString aEndTags = rWrt.OutFrameFormatOptions(rFrameFormat, u"", HTML_FRMOPTS_SPACER); rWrt.Strm().WriteChar( '>' ); if( !aEndTags.isEmpty() ) @@ -1670,46 +1686,44 @@ static Writer& OutHTML_FrameFormatAsSpacer( Writer& rWrt, const SwFrameFormat& r return rWrt; } -static Writer& OutHTML_FrameFormatAsDivOrSpan( Writer& rWrt, +static SwHTMLWriter& OutHTML_FrameFormatAsDivOrSpan( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, bool bSpan) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - OString aTag; if( !bSpan ) { - rHTMLWrt.ChangeParaToken( HtmlTokenId::NONE ); + rWrt.ChangeParaToken( HtmlTokenId::NONE ); // Close the current <DL>! - rHTMLWrt.OutAndSetDefList( 0 ); - aTag = OOO_STRING_SVTOOLS_HTML_division; + rWrt.OutAndSetDefList( 0 ); + aTag = OOO_STRING_SVTOOLS_HTML_division ""_ostr; } else - aTag = OOO_STRING_SVTOOLS_HTML_span; + aTag = OOO_STRING_SVTOOLS_HTML_span ""_ostr; // output as DIV - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); - OStringBuffer sOut; - sOut.append('<').append(rHTMLWrt.GetNamespace() + aTag); + OStringBuffer sOut("<" + rWrt.GetNamespace() + aTag); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); HtmlFrmOpts nFrameFlags = HTML_FRMOPTS_DIV; - if( rHTMLWrt.IsHTMLMode( HTMLMODE_BORDER_NONE ) ) + if( rWrt.IsHTMLMode( HTMLMODE_BORDER_NONE ) ) nFrameFlags |= HtmlFrmOpts::SNoBorder; - OString aEndTags = rHTMLWrt.OutFrameFormatOptions(rFrameFormat, OUString(), nFrameFlags); - rHTMLWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameFlags ); + OString aEndTags = rWrt.OutFrameFormatOptions(rFrameFormat, u"", nFrameFlags); + rWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameFlags ); rWrt.Strm().WriteChar( '>' ); - rHTMLWrt.IncIndentLevel(); // indent the content - rHTMLWrt.m_bLFPossible = true; + rWrt.IncIndentLevel(); // indent the content + rWrt.SetLFPossible(true); const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); - sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex(); + SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex(); // Output frame-anchored frames that are anchored to the start node - rHTMLWrt.OutFlyFrame( nStt, 0, HtmlPosition::Any ); + rWrt.OutFlyFrame( nStt, 0, HtmlPosition::Any ); const SwStartNode* pSttNd = rWrt.m_pDoc->GetNodes()[nStt]->GetStartNode(); OSL_ENSURE( pSttNd, "Where is the start node" ); @@ -1717,17 +1731,17 @@ static Writer& OutHTML_FrameFormatAsDivOrSpan( Writer& rWrt, { // in a block, so that the old state can be restored in time // before the end - HTMLSaveData aSaveData( rHTMLWrt, nStt+1, + HTMLSaveData aSaveData( rWrt, nStt+1, pSttNd->EndOfSectionIndex(), true, &rFrameFormat ); - rHTMLWrt.m_bOutFlyFrame = true; - rHTMLWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() ); + rWrt.m_bOutFlyFrame = true; + rWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() ); } - rHTMLWrt.DecIndentLevel(); // indent the content of Multicol; - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + aTag, false ); + rWrt.DecIndentLevel(); // indent the content of Multicol; + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false ); if( !aEndTags.isEmpty() ) rWrt.Strm().WriteOString( aEndTags ); @@ -1735,29 +1749,109 @@ static Writer& OutHTML_FrameFormatAsDivOrSpan( Writer& rWrt, return rWrt; } -static Writer & OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& rFrameFormat ) +/// Starts the OLE version of an image in the ReqIF + OLE case. +static void OutHTML_ImageOLEStart(SwHTMLWriter& rWrt, const Graphic& rGraphic, + const SwFrameFormat& rFrameFormat) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); + if (!rWrt.mbReqIF || !rWrt.m_bExportImagesAsOLE) + return; - if (rHTMLWrt.mbSkipImages) + // Write the original image as an RTF fragment. + OUString aFileName; + if (rWrt.GetOrigFileName()) + aFileName = *rWrt.GetOrigFileName(); + INetURLObject aURL(aFileName); + OUString aName = aURL.getBase() + "_" + aURL.getExtension() + "_" + + OUString::number(rGraphic.GetChecksum(), 16); + aURL.setBase(aName); + aURL.setExtension(u"ole"); + aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); + + SvFileStream aOutStream(aFileName, StreamMode::WRITE); + if (!SwReqIfReader::WrapGraphicInRtf(rGraphic, rFrameFormat, aOutStream)) + SAL_WARN("sw.html", "SwReqIfReader::WrapGraphicInRtf() failed"); + + // Refer to this data. + aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName); + rWrt.Strm().WriteOString( + Concat2View("<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object)); + rWrt.Strm().WriteOString(Concat2View(" data=\"" + aFileName.toUtf8() + "\"")); + rWrt.Strm().WriteOString(" type=\"text/rtf\""); + rWrt.Strm().WriteOString(">"); + rWrt.OutNewLine(); +} + +/// Ends the OLE version of an image in the ReqIF + OLE case. +static void OutHTML_ImageOLEEnd(SwHTMLWriter& rWrt) +{ + if (rWrt.mbReqIF && rWrt.m_bExportImagesAsOLE) + { + rWrt.Strm().WriteOString( + Concat2View("</" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">")); + } +} + +static SwHTMLWriter & OutHTML_FrameFormatAsImage( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, bool bPNGFallback) +{ + bool bWritePNGFallback = rWrt.mbReqIF && !rWrt.m_bExportImagesAsOLE && bPNGFallback; + + if (rWrt.mbSkipImages) return rWrt; ImageMap aIMap; - Graphic aGraphic( const_cast<SwFrameFormat &>(rFrameFormat).MakeGraphic( &aIMap ) ); + std::optional<Size> aDPI; + if (rWrt.m_nShapeDPI.has_value()) + { + aDPI.emplace(*rWrt.m_nShapeDPI, *rWrt.m_nShapeDPI); + } + Graphic aGraphic( const_cast<SwFrameFormat &>(rFrameFormat).MakeGraphic( &aIMap, /*nMaximumQuadraticPixels=*/2100000, aDPI ) ); + + if (rWrt.mbReqIF) + { + // ImageMap doesn't seem to be allowed in reqif. + if (auto pGrafObj = dynamic_cast<const SdrGrafObj*>(rFrameFormat.FindSdrObject())) + { + aGraphic = pGrafObj->GetGraphic(); + } + else + { + // We only have a bitmap, write that as PNG without any fallback. + bWritePNGFallback = false; + } + } + Size aSz( 0, 0 ); OUString GraphicURL; - if(!rHTMLWrt.mbEmbedImages) + OUString aMimeType("image/jpeg"); + if(!rWrt.mbEmbedImages) { - if( rHTMLWrt.GetOrigFileName() ) - GraphicURL = *rHTMLWrt.GetOrigFileName(); + if( rWrt.GetOrigFileName() ) + GraphicURL = *rWrt.GetOrigFileName(); + + OUString aFilterName("JPG"); + XOutFlags nFlags = XOutFlags::UseGifIfPossible | XOutFlags::UseNativeIfPossible; + + if (rWrt.mbReqIF && !bWritePNGFallback) + { + // Writing image without fallback PNG in ReqIF mode: force PNG output. + aFilterName = "PNG"; + nFlags = XOutFlags::NONE; + aMimeType = "image/png"; + } + else if (rWrt.mbReqIF) + { + // Original format is wanted, don't force JPG. + aFilterName.clear(); + aMimeType.clear(); + } + if( aGraphic.GetType() == GraphicType::NONE || XOutBitmap::WriteGraphic( aGraphic, GraphicURL, - "JPG", - (XOutFlags::UseGifIfPossible| - XOutFlags::UseNativeIfPossible) ) != ERRCODE_NONE ) + aFilterName, + nFlags ) != ERRCODE_NONE ) { // empty or incorrect, because there is nothing to output - rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD; + rWrt.m_nWarn = WARN_SWG_POOR_LOAD; return rWrt; } @@ -1766,46 +1860,70 @@ static Writer & OutHTML_FrameFormatAsImage( Writer& rWrt, const SwFrameFormat& r URIHelper::GetMaybeFileHdl() ); } - OutHTML_Image( rWrt, rFrameFormat, GraphicURL, aGraphic, rFrameFormat.GetName(), aSz, + uno::Reference<beans::XPropertySet> xGraphic(aGraphic.GetXGraphic(), uno::UNO_QUERY); + if (xGraphic.is() && aMimeType.isEmpty()) + xGraphic->getPropertyValue("MimeType") >>= aMimeType; + + OutHTML_ImageOLEStart(rWrt, aGraphic, rFrameFormat); + + HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace); + OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, GraphicURL, aGraphic, rFrameFormat.GetName(), aSz, HtmlFrmOpts::GenImgMask, "frame", - aIMap.GetIMapObjectCount() ? &aIMap : nullptr ); + aIMap.GetIMapObjectCount() ? &aIMap : nullptr, aMimeType ); + + GfxLink aLink = aGraphic.GetGfxLink(); + if (bWritePNGFallback && aLink.GetType() != GfxLinkType::NativePng) + { + OutHTML_FrameFormatAsImage( rWrt, rFrameFormat, /*bPNGFallback=*/false); + } + + OutHTML_ImageEnd(aHtml, rWrt); + + OutHTML_ImageOLEEnd(rWrt); return rWrt; } -static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rFrameFormat, - bool bInCntnr ) +static SwHTMLWriter& OutHTML_FrameFormatGrfNode( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, + bool bInCntnr, bool bPNGFallback ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); + bool bWritePNGFallback = rWrt.mbReqIF && !rWrt.m_bExportImagesAsOLE && bPNGFallback; - if (rHTMLWrt.mbSkipImages) + if (rWrt.mbSkipImages) return rWrt; const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); - sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1; - SwGrfNode *pGrfNd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetGrfNode(); + SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1; + SwGrfNode *pGrfNd = rWrt.m_pDoc->GetNodes()[ nStt ]->GetGrfNode(); OSL_ENSURE( pGrfNd, "Grf node expected" ); if( !pGrfNd ) return rWrt; HtmlFrmOpts nFrameFlags = bInCntnr ? HTML_FRMOPTS_IMG_CNTNR : HTML_FRMOPTS_IMG; - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bInCntnr ) nFrameFlags |= HTML_FRMOPTS_IMG_CSS1; Graphic aGraphic = pGrfNd->GetGraphic(); + + if (aGraphic.GetType() == GraphicType::GdiMetafile) + { + // We only have a metafile, write that as PNG without any fallback. + bWritePNGFallback = false; + } + OUString aGraphicURL; OUString aMimeType; - if(!rHTMLWrt.mbEmbedImages) + if(!rWrt.mbEmbedImages) { const SwMirrorGrf& rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf(); if( !pGrfNd->IsLinkedFile() || MirrorGraph::Dont != rMirror.GetValue() ) { // create a (mirrored) jpeg file - if( rHTMLWrt.GetOrigFileName() ) - aGraphicURL = *rHTMLWrt.GetOrigFileName(); + if( rWrt.GetOrigFileName() ) + aGraphicURL = *rWrt.GetOrigFileName(); else - aGraphicURL = rHTMLWrt.GetBaseURL(); + aGraphicURL = rWrt.GetBaseURL(); pGrfNd->GetGrf( true ); XOutFlags nFlags = XOutFlags::UseGifIfSensible | @@ -1820,21 +1938,25 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF default: break; } - Size aMM100Size; const SwFormatFrameSize& rSize = rFrameFormat.GetFrameSize(); - aMM100Size = OutputDevice::LogicToLogic( rSize.GetSize(), - MapMode( MapUnit::MapTwip ), MapMode( MapUnit::Map100thMM )); + Size aMM100Size = o3tl::convert( rSize.GetSize(), + o3tl::Length::twip, o3tl::Length::mm100 ); - OUString aFilterName(""); + OUString aFilterName; - if (rHTMLWrt.mbReqIF) + if (rWrt.mbReqIF) { - // Writing image without fallback PNG in ReqIF mode: force PNG - // output. - aFilterName = "PNG"; - nFlags &= ~XOutFlags::UseNativeIfPossible; + // In ReqIF mode, do not try to write GIF for other image types nFlags &= ~XOutFlags::UseGifIfSensible; - aMimeType = "image/png"; + if (!bWritePNGFallback) + { + // Writing image without fallback PNG in ReqIF mode: force PNG + // output. + // But don't force it when writing the original format and we'll write PNG inside + // that. + aFilterName = "PNG"; + nFlags &= ~XOutFlags::UseNativeIfPossible; + } } const Graphic& rGraphic = pGrfNd->GetGrf(); @@ -1843,11 +1965,33 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF if (!rGraphic.isAvailable()) const_cast<Graphic&>(rGraphic).makeAvailable(); + if (rWrt.mbReqIF && bWritePNGFallback) + { + // ReqIF: force native data if possible. + const std::shared_ptr<VectorGraphicData>& pVectorGraphicData = rGraphic.getVectorGraphicData(); + if (pVectorGraphicData && pVectorGraphicData->getType() == VectorGraphicDataType::Svg) + { + aFilterName = "svg"; + } + else if (rGraphic.GetGfxLink().IsEMF()) + { + aFilterName = "emf"; + } + else if (pVectorGraphicData && pVectorGraphicData->getType() == VectorGraphicDataType::Wmf) + { + aFilterName = "wmf"; + } + else if (rGraphic.GetGfxLink().GetType() == GfxLinkType::NativeTif) + { + aFilterName = "tif"; + } + } + ErrCode nErr = XOutBitmap::WriteGraphic( rGraphic, aGraphicURL, - aFilterName, nFlags, &aMM100Size ); + aFilterName, nFlags, &aMM100Size, nullptr, &aMimeType ); if( nErr ) { - rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD; + rWrt.m_nWarn = WARN_SWG_POOR_LOAD; return rWrt; } aGraphicURL = URIHelper::SmartRel2Abs( @@ -1857,7 +2001,7 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF else { pGrfNd->GetFileFilterNms( &aGraphicURL, nullptr ); - if( rHTMLWrt.m_bCfgCpyLinkedGrfs ) + if( rWrt.m_bCfgCpyLinkedGrfs ) rWrt.CopyLocalFileToINet( aGraphicURL ); } @@ -1866,174 +2010,152 @@ static Writer& OutHTML_FrameFormatGrfNode( Writer& rWrt, const SwFrameFormat& rF if (xGraphic.is() && aMimeType.isEmpty()) xGraphic->getPropertyValue("MimeType") >>= aMimeType; - if (rHTMLWrt.mbReqIF) - { - // Write the original image as an RTF fragment. - OUString aFileName; - if (rHTMLWrt.GetOrigFileName()) - aFileName = *rHTMLWrt.GetOrigFileName(); - INetURLObject aURL(aFileName); - OUString aName = aURL.getBase() + "_" + - aURL.getExtension() + "_" + - OUString::number(aGraphic.GetChecksum(), 16); - aURL.setBase(aName); - aURL.setExtension("ole"); - aFileName = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); - - SvFileStream aOutStream(aFileName, StreamMode::WRITE); - if (!SwReqIfReader::WrapGraphicInRtf(aGraphic, pGrfNd->GetTwipSize(), aOutStream)) - SAL_WARN("sw.html", "SwReqIfReader::WrapGraphicInRtf() failed"); - - // Refer to this data. - aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName); - rWrt.Strm().WriteOString("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object); - rWrt.Strm().WriteOString(" data=\"" + aFileName.toUtf8() + "\""); - rWrt.Strm().WriteOString(" type=\"text/rtf\""); - rWrt.Strm().WriteOString(">"); - rHTMLWrt.OutNewLine(); - } - - OutHTML_Image( rWrt, rFrameFormat, aGraphicURL, aGraphic, pGrfNd->GetTitle(), + OutHTML_ImageOLEStart(rWrt, aGraphic, rFrameFormat); + + HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace); + OutHTML_ImageStart( aHtml, rWrt, rFrameFormat, aGraphicURL, aGraphic, pGrfNd->GetTitle(), pGrfNd->GetTwipSize(), nFrameFlags, "graphic", nullptr, aMimeType ); - if (rHTMLWrt.mbReqIF) - rWrt.Strm().WriteOString("</" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">"); + GfxLink aLink = aGraphic.GetGfxLink(); + if (bWritePNGFallback && aLink.GetType() != GfxLinkType::NativePng) + { + // Not OLE mode, outer format is not PNG: write inner PNG. + OutHTML_FrameFormatGrfNode( rWrt, rFrameFormat, + bInCntnr, /*bPNGFallback=*/false ); + } + + OutHTML_ImageEnd(aHtml, rWrt); + + OutHTML_ImageOLEEnd(rWrt); return rWrt; } -static Writer& OutHTML_FrameFormatAsMarquee( Writer& rWrt, const SwFrameFormat& rFrameFormat, +static SwHTMLWriter& OutHTML_FrameFormatAsMarquee( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, const SdrObject& rSdrObj ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // get the edit engine attributes of the object as SW attributes and // sort them as Hints const SfxItemSet& rFormatItemSet = rFrameFormat.GetAttrSet(); - SfxItemSet aItemSet( *rFormatItemSet.GetPool(), svl::Items<RES_CHRATR_BEGIN, - RES_CHRATR_END>{} ); + SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END> aItemSet( *rFormatItemSet.GetPool() ); SwHTMLWriter::GetEEAttrsFromDrwObj( aItemSet, &rSdrObj ); - bool bCfgOutStylesOld = rHTMLWrt.m_bCfgOutStyles; - rHTMLWrt.m_bCfgOutStyles = false; - rHTMLWrt.m_bTextAttr = true; - rHTMLWrt.m_bTagOn = true; + bool bCfgOutStylesOld = rWrt.m_bCfgOutStyles; + rWrt.m_bCfgOutStyles = false; + rWrt.m_bTextAttr = true; + rWrt.m_bTagOn = true; Out_SfxItemSet( aHTMLAttrFnTab, rWrt, aItemSet, false ); - rHTMLWrt.m_bTextAttr = false; + rWrt.m_bTextAttr = false; - OutHTML_DrawFrameFormatAsMarquee( rHTMLWrt, + OutHTML_DrawFrameFormatAsMarquee( rWrt, static_cast<const SwDrawFrameFormat &>(rFrameFormat), rSdrObj ); - rHTMLWrt.m_bTextAttr = true; - rHTMLWrt.m_bTagOn = false; + rWrt.m_bTextAttr = true; + rWrt.m_bTagOn = false; Out_SfxItemSet( aHTMLAttrFnTab, rWrt, aItemSet, false ); - rHTMLWrt.m_bTextAttr = false; - rHTMLWrt.m_bCfgOutStyles = bCfgOutStylesOld; + rWrt.m_bTextAttr = false; + rWrt.m_bCfgOutStyles = bCfgOutStylesOld; return rWrt; } -Writer& OutHTML_HeaderFooter( Writer& rWrt, const SwFrameFormat& rFrameFormat, +SwHTMLWriter& OutHTML_HeaderFooter( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, bool bHeader ) { - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // output as Multicol - rHTMLWrt.OutNewLine(); + rWrt.OutNewLine(); OStringBuffer sOut; - sOut.append(OOO_STRING_SVTOOLS_HTML_division).append(' ') - .append(OOO_STRING_SVTOOLS_HTML_O_title).append("=\"") + sOut.append(OOO_STRING_SVTOOLS_HTML_division " " + OOO_STRING_SVTOOLS_HTML_O_title "=\"") .append( bHeader ? "header" : "footer" ).append("\""); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + sOut.makeStringAndClear().getStr() ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOut) ); - rHTMLWrt.IncIndentLevel(); // indent the content of Multicol; + rWrt.IncIndentLevel(); // indent the content of Multicol; // Piece a spacer for the spacing together. Because the // <DL> or </DL> always produces a space between paragraphs, it is // subtracted if necessary. const SvxULSpaceItem& rULSpace = rFrameFormat.GetULSpace(); sal_uInt16 nSize = bHeader ? rULSpace.GetLower() : rULSpace.GetUpper(); - rHTMLWrt.m_nHeaderFooterSpace = nSize; + rWrt.m_nHeaderFooterSpace = nSize; OString aSpacer; - if( rHTMLWrt.IsHTMLMode(HTMLMODE_VERT_SPACER) && - nSize > HTML_PARSPACE && Application::GetDefaultDevice() ) + if( rWrt.IsHTMLMode(HTMLMODE_VERT_SPACER) && + nSize > HTML_PARSPACE ) { nSize -= HTML_PARSPACE; - nSize = static_cast<sal_Int16>(Application::GetDefaultDevice() - ->LogicToPixel( Size(nSize,0), MapMode(MapUnit::MapTwip) ).Width()); + nSize = SwHTMLWriter::ToPixel(nSize); - aSpacer = OStringBuffer(OOO_STRING_SVTOOLS_HTML_spacer). - append(' ').append(OOO_STRING_SVTOOLS_HTML_O_type). - append("=\"").append(OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical).append("\""). - append(' ').append(OOO_STRING_SVTOOLS_HTML_O_size). - append("=\"").append(static_cast<sal_Int32>(nSize)).append("\""). - makeStringAndClear(); + aSpacer = OOO_STRING_SVTOOLS_HTML_spacer + " " OOO_STRING_SVTOOLS_HTML_O_type + "=\"" OOO_STRING_SVTOOLS_HTML_SPTYPE_vertical "\"" + " " OOO_STRING_SVTOOLS_HTML_O_size + "=\"" + OString::number(nSize) + "\""; } const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); - sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex(); + SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex(); const SwStartNode* pSttNd = rWrt.m_pDoc->GetNodes()[nStt]->GetStartNode(); OSL_ENSURE( pSttNd, "Where is the start node" ); if( !bHeader && !aSpacer.isEmpty() ) { - rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + aSpacer.getStr() ); + rWrt.OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aSpacer) ); } { // in a block, so that the old state can be restored in time // before the end. pFlyFormat doesn't need to be set here, because // PageDesc attributes cannot occur here - HTMLSaveData aSaveData( rHTMLWrt, nStt+1, + HTMLSaveData aSaveData( rWrt, nStt+1, pSttNd->EndOfSectionIndex() ); if( bHeader ) - rHTMLWrt.m_bOutHeader = true; + rWrt.m_bOutHeader = true; else - rHTMLWrt.m_bOutFooter = true; + rWrt.m_bOutFooter = true; - rHTMLWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() ); + rWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() ); } if( bHeader && !aSpacer.isEmpty() ) { - rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + aSpacer.getStr() ); + rWrt.OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aSpacer) ); } - rHTMLWrt.DecIndentLevel(); // indent the content of Multicol; - rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division, false ); + rWrt.DecIndentLevel(); // indent the content of Multicol; + rWrt.OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false ); - rHTMLWrt.m_nHeaderFooterSpace = 0; + rWrt.m_nHeaderFooterSpace = 0; return rWrt; } -void SwHTMLWriter::AddLinkTarget( const OUString& rURL ) +void SwHTMLWriter::AddLinkTarget( std::u16string_view aURL ) { - if( rURL.isEmpty() || rURL[0] != '#' ) + if( aURL.empty() || aURL[0] != '#' ) return; // There might be a '|' as delimiter (if the link has been inserted // freshly) or a '%7c' or a '%7C' if the document has been saved and // loaded already. - sal_Int32 nPos = rURL.getLength(); + sal_Int32 nPos = aURL.size(); bool bFound = false, bEncoded = false; while( !bFound && nPos > 0 ) { - sal_Unicode c = rURL[ --nPos ]; + sal_Unicode c = aURL[ --nPos ]; switch( c ) { case cMarkSeparator: bFound = true; break; case '%': - bFound = (rURL.getLength() - nPos) >=3 && rURL[ nPos+1 ] == '7'; + bFound = (aURL.size() - nPos) >=3 && aURL[ nPos+1 ] == '7'; if(bFound) { - c = rURL[ nPos+2 ]; + c = aURL[ nPos+2 ]; bFound = (c == 'C' || c == 'c'); } if( bFound ) @@ -2043,10 +2165,10 @@ void SwHTMLWriter::AddLinkTarget( const OUString& rURL ) if( !bFound || nPos < 2 ) // at least "#a|..." return; - OUString aURL( rURL.copy( 1 ) ); + aURL = aURL.substr( 1 ); // nPos-1+1/3 (-1 because of Erase) - OUString sCmp = aURL.copy(bEncoded ? nPos+2 : nPos).replaceAll(" ",""); + OUString sCmp = OUString(aURL.substr(bEncoded ? nPos+2 : nPos)).replaceAll(" ",""); if( sCmp.isEmpty() ) return; @@ -2059,21 +2181,22 @@ void SwHTMLWriter::AddLinkTarget( const OUString& rURL ) sCmp == "table" ) { // Just remember it in a sorted array + OUString aURL2(aURL); if( bEncoded ) { - aURL = aURL.replaceAt( nPos - 1, 3, OUString(cMarkSeparator) ); + aURL2 = aURL2.replaceAt( nPos - 1, 3, rtl::OUStringChar(cMarkSeparator) ); } - m_aImplicitMarks.insert( aURL ); + m_aImplicitMarks.insert( aURL2 ); } else if( sCmp == "outline" ) { // Here, we need position and name. That's why we sort a // sal_uInt16 and a string array ourselves. - OUString aOutline( aURL.copy( 0, nPos-1 ) ); + OUString aOutline( aURL.substr( 0, nPos-1 ) ); SwPosition aPos( *m_pCurrentPam->GetPoint() ); if( m_pDoc->GotoOutline( aPos, aOutline ) ) { - sal_uInt32 nIdx = aPos.nNode.GetIndex(); + SwNodeOffset nIdx = aPos.GetNodeIndex(); decltype(m_aOutlineMarkPoss)::size_type nIns=0; while( nIns < m_aOutlineMarkPoss.size() && @@ -2081,11 +2204,12 @@ void SwHTMLWriter::AddLinkTarget( const OUString& rURL ) nIns++; m_aOutlineMarkPoss.insert( m_aOutlineMarkPoss.begin()+nIns, nIdx ); + OUString aURL2(aURL); if( bEncoded ) { - aURL = aURL.replaceAt( nPos - 1, 3, OUString(cMarkSeparator) ); + aURL2 = aURL2.replaceAt( nPos - 1, 3, rtl::OUStringChar(cMarkSeparator) ); } - m_aOutlineMarks.insert( m_aOutlineMarks.begin()+nIns, aURL ); + m_aOutlineMarks.insert( m_aOutlineMarks.begin()+nIns, aURL2 ); } } } @@ -2094,7 +2218,9 @@ void SwHTMLWriter::CollectLinkTargets() { const SwTextINetFormat* pTextAttr; - for (const SfxPoolItem* pItem : m_pDoc->GetAttrPool().GetItemSurrogates(RES_TXTATR_INETFMT)) + ItemSurrogates aSurrogates; + m_pDoc->GetAttrPool().GetItemSurrogates(aSurrogates, RES_TXTATR_INETFMT); + for (const SfxPoolItem* pItem : aSurrogates) { auto pINetFormat = dynamic_cast<const SwFormatINetFormat*>(pItem); const SwTextNode* pTextNd; @@ -2108,7 +2234,8 @@ void SwHTMLWriter::CollectLinkTargets() } } - for (const SfxPoolItem* pItem : m_pDoc->GetAttrPool().GetItemSurrogates(RES_URL)) + m_pDoc->GetAttrPool().GetItemSurrogates(aSurrogates, RES_URL); + for (const SfxPoolItem* pItem : aSurrogates) { auto pURL = dynamic_cast<const SwFormatURL*>(pItem); if( pURL ) diff --git a/sw/source/filter/html/htmlform.cxx b/sw/source/filter/html/htmlform.cxx index bb51694df012..d37abddc68d1 100644 --- a/sw/source/filter/html/htmlform.cxx +++ b/sw/source/filter/html/htmlform.cxx @@ -24,9 +24,12 @@ #include <hintids.hxx> #include <comphelper/documentinfo.hxx> #include <comphelper/string.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <tools/UnitConversion.hxx> +#include <o3tl/string_view.hxx> +#include <comphelper/diagnose_ex.hxx> #include <vcl/unohelp.hxx> #include <svtools/htmlkywd.hxx> #include <svtools/htmltokn.h> @@ -64,7 +67,6 @@ #include <com/sun/star/awt/XImageConsumer.hpp> #include <com/sun/star/awt/ImageStatus.hpp> #include <com/sun/star/form/XImageProducerSupplier.hpp> -#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> #include <com/sun/star/form/XForm.hpp> #include <doc.hxx> #include <IDocumentLayoutAccess.hxx> @@ -372,21 +374,21 @@ namespace { class SwHTMLImageWatcher : public cppu::WeakImplHelper< awt::XImageConsumer, XEventListener > { - uno::Reference< drawing::XShape > xShape; // the control - uno::Reference< XImageProducerSupplier > xSrc; - uno::Reference< awt::XImageConsumer > xThis; // reference to self - bool bSetWidth; - bool bSetHeight; + uno::Reference< drawing::XShape > m_xShape; // the control + uno::Reference< XImageProducerSupplier > m_xSrc; + uno::Reference< awt::XImageConsumer > m_xThis; // reference to self + bool m_bSetWidth; + bool m_bSetHeight; void clear(); public: - SwHTMLImageWatcher( const uno::Reference< drawing::XShape > & rShape, + SwHTMLImageWatcher( uno::Reference< drawing::XShape > xShape, bool bWidth, bool bHeight ); // startProduction can not be called in the constructor because it can // destruct itself, hence a separate method. - void start() { xSrc->getImageProducer()->startProduction(); } + void start() { m_xSrc->getImageProducer()->startProduction(); } // UNO binding @@ -415,47 +417,47 @@ public: } SwHTMLImageWatcher::SwHTMLImageWatcher( - const uno::Reference< drawing::XShape >& rShape, + uno::Reference< drawing::XShape > xShape, bool bWidth, bool bHeight ) : - xShape( rShape ), - bSetWidth( bWidth ), bSetHeight( bHeight ) + m_xShape(std::move( xShape )), + m_bSetWidth( bWidth ), m_bSetHeight( bHeight ) { // Remember the source of the image - uno::Reference< drawing::XControlShape > xControlShape( xShape, UNO_QUERY ); + uno::Reference< drawing::XControlShape > xControlShape( m_xShape, UNO_QUERY ); uno::Reference< awt::XControlModel > xControlModel( xControlShape->getControl() ); - xSrc.set( xControlModel, UNO_QUERY ); - OSL_ENSURE( xSrc.is(), "No XImageProducerSupplier" ); + m_xSrc.set( xControlModel, UNO_QUERY ); + OSL_ENSURE( m_xSrc.is(), "No XImageProducerSupplier" ); // Register as Event-Listener on the shape to be able to release it on dispose. uno::Reference< XEventListener > xEvtLstnr = static_cast<XEventListener *>(this); - uno::Reference< XComponent > xComp( xShape, UNO_QUERY ); + uno::Reference< XComponent > xComp( m_xShape, UNO_QUERY ); xComp->addEventListener( xEvtLstnr ); // Lastly we keep a reference to ourselves so we are not destroyed // (should not be necessary since we're still registered elsewhere) - xThis = static_cast<awt::XImageConsumer *>(this); + m_xThis = static_cast<awt::XImageConsumer *>(this); // Register at ImageProducer to retrieve the size... - xSrc->getImageProducer()->addConsumer( xThis ); + m_xSrc->getImageProducer()->addConsumer( m_xThis ); } void SwHTMLImageWatcher::clear() { // Unregister on Shape uno::Reference< XEventListener > xEvtLstnr = static_cast<XEventListener *>(this); - uno::Reference< XComponent > xComp( xShape, UNO_QUERY ); + uno::Reference< XComponent > xComp( m_xShape, UNO_QUERY ); xComp->removeEventListener( xEvtLstnr ); // Unregister on ImageProducer - uno::Reference<awt::XImageProducer> xProd = xSrc->getImageProducer(); + uno::Reference<awt::XImageProducer> xProd = m_xSrc->getImageProducer(); if( xProd.is() ) - xProd->removeConsumer( xThis ); + xProd->removeConsumer( m_xThis ); } void SwHTMLImageWatcher::init( sal_Int32 Width, sal_Int32 Height ) { - OSL_ENSURE( bSetWidth || bSetHeight, + OSL_ENSURE( m_bSetWidth || m_bSetHeight, "Width or height has to be adjusted" ); // If no width or height is given, it is initialized to those of @@ -465,27 +467,19 @@ void SwHTMLImageWatcher::init( sal_Int32 Width, sal_Int32 Height ) return; awt::Size aNewSz; - aNewSz.Width = Width; - aNewSz.Height = Height; - if( Application::GetDefaultDevice() ) - { - Size aTmp(aNewSz.Width, aNewSz.Height); - aTmp = Application::GetDefaultDevice() - ->PixelToLogic( aTmp, MapMode( MapUnit::Map100thMM ) ); - aNewSz.Width = aTmp.Width(); - aNewSz.Height = aTmp.Height(); - } + aNewSz.Width = o3tl::convert(Width, o3tl::Length::px, o3tl::Length::mm100); + aNewSz.Height = o3tl::convert(Height, o3tl::Length::px, o3tl::Length::mm100); - if( !bSetWidth || !bSetHeight ) + if( !m_bSetWidth || !m_bSetHeight ) { - awt::Size aSz( xShape->getSize() ); - if( bSetWidth && aNewSz.Height ) + awt::Size aSz( m_xShape->getSize() ); + if( m_bSetWidth && aNewSz.Height ) { aNewSz.Width *= aSz.Height; aNewSz.Width /= aNewSz.Height; aNewSz.Height = aSz.Height; } - if( bSetHeight && aNewSz.Width ) + if( m_bSetHeight && aNewSz.Width ) { aNewSz.Height *= aSz.Width; aNewSz.Height /= aNewSz.Width; @@ -497,15 +491,15 @@ void SwHTMLImageWatcher::init( sal_Int32 Width, sal_Int32 Height ) if( aNewSz.Height < MINFLY ) aNewSz.Height = MINFLY; - xShape->setSize( aNewSz ); - if( bSetWidth ) + m_xShape->setSize( aNewSz ); + if( m_bSetWidth ) { // If the control is anchored to a table, the column have to be recalculated // To get to the SwXShape* we need an interface that is implemented by SwXShape - uno::Reference< beans::XPropertySet > xPropSet( xShape, UNO_QUERY ); - SwXShape *pSwShape = comphelper::getUnoTunnelImplementation<SwXShape>(xPropSet); + uno::Reference< beans::XPropertySet > xPropSet( m_xShape, UNO_QUERY ); + SwXShape *pSwShape = comphelper::getFromUnoTunnel<SwXShape>(xPropSet); OSL_ENSURE( pSwShape, "Where is SW-Shape?" ); if( pSwShape ) @@ -513,9 +507,9 @@ void SwHTMLImageWatcher::init( sal_Int32 Width, sal_Int32 Height ) SwFrameFormat *pFrameFormat = pSwShape->GetFrameFormat(); const SwDoc *pDoc = pFrameFormat->GetDoc(); - const SwPosition* pAPos = pFrameFormat->GetAnchor().GetContentAnchor(); + SwNode* pAnchorNode = pFrameFormat->GetAnchor().GetAnchorNode(); SwTableNode *pTableNd; - if (pAPos && nullptr != (pTableNd = pAPos->nNode.GetNode().FindTableNode())) + if (pAnchorNode && nullptr != (pTableNd = pAnchorNode->FindTableNode())) { const bool bLastGrf = !pTableNd->GetTable().DecGrfsThatResize(); SwHTMLTableLayout *pLayout = @@ -538,7 +532,7 @@ void SwHTMLImageWatcher::init( sal_Int32 Width, sal_Int32 Height ) // unregister and delete self clear(); - xThis = nullptr; + m_xThis = nullptr; } void SwHTMLImageWatcher::setColorModel( @@ -566,7 +560,7 @@ void SwHTMLImageWatcher::complete( sal_Int32 Status, { // unregister and delete self clear(); - xThis = nullptr; + m_xThis = nullptr; } } @@ -575,11 +569,11 @@ void SwHTMLImageWatcher::disposing(const lang::EventObject& evt) uno::Reference< awt::XImageConsumer > xTmp; // We need to release the shape if it is disposed of - if( evt.Source == xShape ) + if( evt.Source == m_xShape ) { clear(); xTmp = static_cast<awt::XImageConsumer*>(this); - xThis = nullptr; + m_xThis = nullptr; } } @@ -641,7 +635,7 @@ void SwHTMLParser::SetControlSize( const uno::Reference< drawing::XShape >& rSha if ( pDocSh->GetMedium() ) { // if there is no hidden property in the MediaDescriptor it should be removed after loading - const SfxBoolItem* pHiddenItem = SfxItemSet::GetItem<SfxBoolItem>(pDocSh->GetMedium()->GetItemSet(), SID_HIDDEN, false); + const SfxBoolItem* pHiddenItem = pDocSh->GetMedium()->GetItemSet().GetItem(SID_HIDDEN, false); m_bRemoveHidden = ( pHiddenItem == nullptr || !pHiddenItem->GetValue() ); } @@ -653,7 +647,7 @@ void SwHTMLParser::SetControlSize( const uno::Reference< drawing::XShape >& rSha } } - SwXShape *pSwShape = comphelper::getUnoTunnelImplementation<SwXShape>(xPropSet); + SwXShape *pSwShape = comphelper::getFromUnoTunnel<SwXShape>(xPropSet); OSL_ENSURE( pSwShape, "Where is SW-Shape?" ); @@ -671,7 +665,7 @@ void SwHTMLParser::SetControlSize( const uno::Reference< drawing::XShape >& rSha const SdrUnoObj *pFormObj = dynamic_cast<const SdrUnoObj*>( pObj ); uno::Reference< awt::XControl > xControl; if ( pDrawView && pVSh->GetWin() && pFormObj ) - xControl = pFormObj->GetUnoControl( *pDrawView, *pVSh->GetWin() ); + xControl = pFormObj->GetUnoControl( *pDrawView, *pVSh->GetWin()->GetOutDev() ); awt::Size aSz( rShape->getSize() ); awt::Size aNewSz( 0, 0 ); @@ -709,14 +703,8 @@ void SwHTMLParser::SetControlSize( const uno::Reference< drawing::XShape >& rSha } } - if( Application::GetDefaultDevice() ) - { - Size aTmpSz( aNewSz.Width, aNewSz.Height ); - aTmpSz = Application::GetDefaultDevice() - ->PixelToLogic( aTmpSz, MapMode( MapUnit::Map100thMM ) ); - aNewSz.Width = aTmpSz.Width(); - aNewSz.Height = aTmpSz.Height(); - } + aNewSz.Width = o3tl::convert(aNewSz.Width, o3tl::Length::px, o3tl::Length::mm100); + aNewSz.Height = o3tl::convert(aNewSz.Height, o3tl::Length::px, o3tl::Length::mm100); if( aNewSz.Width ) { if( aNewSz.Width < MINLAY ) @@ -753,9 +741,9 @@ static bool lcl_html_setEvents( for( const auto &rStr : rUnoMacroTable ) { sal_Int32 nIndex = 0; - if( rStr.getToken( 0, '-', nIndex ).isEmpty() || -1 == nIndex ) + if( o3tl::getToken(rStr, 0, '-', nIndex ).empty() || -1 == nIndex ) continue; - if( rStr.getToken( 0, '-', nIndex ).isEmpty() || -1 == nIndex ) + if( o3tl::getToken(rStr, 0, '-', nIndex ).empty() || -1 == nIndex ) continue; if( nIndex < rStr.getLength() ) nEvents++; @@ -884,25 +872,25 @@ uno::Reference< drawing::XShape > SwHTMLParser::InsertControl( uno::Reference< beans::XPropertySet > xShapePropSet( xCreate, UNO_QUERY ); // set left/right border - const SfxPoolItem *pItem; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_LR_SPACE, true, - &pItem ) ) + // note: parser never creates SvxLeftMarginItem! must be converted + if (const SvxTextLeftMarginItem *const pLeft = rCSS1ItemSet.GetItemIfSet(RES_MARGIN_TEXTLEFT)) { - // Flatten first line indent - const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem); - SvxLRSpaceItem aLRItem( *pLRItem ); - aLRItem.SetTextFirstLineOffset( 0 ); if( rCSS1PropInfo.m_bLeftMargin ) { - nLeftSpace = convertTwipToMm100( aLRItem.GetLeft() ); + // should be SvxLeftMarginItem... "cast" it + nLeftSpace = convertTwipToMm100(pLeft->GetTextLeft()); rCSS1PropInfo.m_bLeftMargin = false; } + rCSS1ItemSet.ClearItem(RES_MARGIN_TEXTLEFT); + } + if (const SvxRightMarginItem *const pRight = rCSS1ItemSet.GetItemIfSet(RES_MARGIN_RIGHT)) + { if( rCSS1PropInfo.m_bRightMargin ) { - nRightSpace = convertTwipToMm100( aLRItem.GetRight() ); + nRightSpace = convertTwipToMm100(pRight->GetRight()); rCSS1PropInfo.m_bRightMargin = false; } - rCSS1ItemSet.ClearItem( RES_LR_SPACE ); + rCSS1ItemSet.ClearItem(RES_MARGIN_RIGHT); } if( nLeftSpace || nRightSpace ) { @@ -915,11 +903,9 @@ uno::Reference< drawing::XShape > SwHTMLParser::InsertControl( } // set upper/lower border - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_UL_SPACE, true, - &pItem ) ) + if( const SvxULSpaceItem *pULItem = rCSS1ItemSet.GetItemIfSet( RES_UL_SPACE ) ) { // Flatten first line indent - const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem); if( rCSS1PropInfo.m_bTopMargin ) { nUpperSpace = convertTwipToMm100( pULItem->GetUpper() ); @@ -946,11 +932,10 @@ uno::Reference< drawing::XShape > SwHTMLParser::InsertControl( uno::Reference< beans::XPropertySetInfo > xPropSetInfo = rFCompPropSet->getPropertySetInfo(); OUString sPropName = "BackgroundColor"; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_BACKGROUND, true, - &pItem ) && - xPropSetInfo->hasPropertyByName( sPropName ) ) + const SvxBrushItem* pBrushItem = rCSS1ItemSet.GetItemIfSet( RES_BACKGROUND ); + if( pBrushItem && xPropSetInfo->hasPropertyByName( sPropName ) ) { - const Color &rColor = static_cast<const SvxBrushItem *>(pItem)->GetColor(); + const Color &rColor = pBrushItem->GetColor(); /// copy color, if color is not "no fill"/"auto fill" if( rColor != COL_TRANSPARENT ) { @@ -962,30 +947,24 @@ uno::Reference< drawing::XShape > SwHTMLParser::InsertControl( } sPropName = "TextColor"; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_CHRATR_COLOR, true, - &pItem ) && - xPropSetInfo->hasPropertyByName( sPropName ) ) + const SvxColorItem* pColorItem = rCSS1ItemSet.GetItemIfSet( RES_CHRATR_COLOR ); + if( pColorItem && xPropSetInfo->hasPropertyByName( sPropName ) ) { - aTmp <<= static_cast<sal_Int32>(static_cast<const SvxColorItem *>(pItem)->GetValue() - .GetRGBColor()); + aTmp <<= static_cast<sal_Int32>(pColorItem->GetValue().GetRGBColor()); rFCompPropSet->setPropertyValue( sPropName, aTmp ); } sPropName = "FontHeight"; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_CHRATR_FONTSIZE, - true, &pItem ) && - xPropSetInfo->hasPropertyByName( sPropName ) ) + const SvxFontHeightItem* pFontHeightItem = rCSS1ItemSet.GetItemIfSet( RES_CHRATR_FONTSIZE ); + if( pFontHeightItem && xPropSetInfo->hasPropertyByName( sPropName ) ) { - float fVal = static_cast< float >( - (static_cast<const SvxFontHeightItem *>(pItem)->GetHeight()) / 20.0 ); + float fVal = static_cast< float >( pFontHeightItem->GetHeight() / 20.0 ); aTmp <<= fVal; rFCompPropSet->setPropertyValue( sPropName, aTmp ); } - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_CHRATR_FONT, true, - &pItem ) ) + if( const SvxFontItem* pFontItem = rCSS1ItemSet.GetItemIfSet( RES_CHRATR_FONT ) ) { - const SvxFontItem *pFontItem = static_cast<const SvxFontItem *>(pItem); sPropName = "FontName"; if( xPropSetInfo->hasPropertyByName( sPropName ) ) { @@ -1019,40 +998,36 @@ uno::Reference< drawing::XShape > SwHTMLParser::InsertControl( } sPropName = "FontWeight"; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_CHRATR_WEIGHT, - true, &pItem ) && - xPropSetInfo->hasPropertyByName( sPropName ) ) + const SvxWeightItem* pWeightItem = rCSS1ItemSet.GetItemIfSet( RES_CHRATR_WEIGHT ); + if( pWeightItem && xPropSetInfo->hasPropertyByName( sPropName ) ) { float fVal = vcl::unohelper::ConvertFontWeight( - static_cast<const SvxWeightItem *>(pItem)->GetWeight() ); + pWeightItem->GetWeight() ); aTmp <<= fVal; rFCompPropSet->setPropertyValue( sPropName, aTmp ); } sPropName = "FontSlant"; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_CHRATR_POSTURE, - true, &pItem ) && - xPropSetInfo->hasPropertyByName( sPropName ) ) + const SvxPostureItem* pPostureItem = rCSS1ItemSet.GetItemIfSet( RES_CHRATR_POSTURE ); + if( pPostureItem && xPropSetInfo->hasPropertyByName( sPropName ) ) { - aTmp <<= static_cast<sal_Int16>(static_cast<const SvxPostureItem *>(pItem)->GetPosture()); + aTmp <<= static_cast<sal_Int16>(pPostureItem->GetPosture()); rFCompPropSet->setPropertyValue( sPropName, aTmp ); } sPropName = "FontUnderline"; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_CHRATR_UNDERLINE, - true, &pItem ) && - xPropSetInfo->hasPropertyByName( sPropName ) ) + const SvxUnderlineItem* pUnderlineItem = rCSS1ItemSet.GetItemIfSet( RES_CHRATR_UNDERLINE ); + if( pUnderlineItem && xPropSetInfo->hasPropertyByName( sPropName ) ) { - aTmp <<= static_cast<sal_Int16>(static_cast<const SvxUnderlineItem *>(pItem)->GetLineStyle()); + aTmp <<= static_cast<sal_Int16>(pUnderlineItem->GetLineStyle()); rFCompPropSet->setPropertyValue( sPropName, aTmp ); } sPropName = "FontStrikeout"; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_CHRATR_CROSSEDOUT, - true, &pItem ) && - xPropSetInfo->hasPropertyByName( sPropName ) ) + const SvxCrossedOutItem* pCrossedOutItem = rCSS1ItemSet.GetItemIfSet( RES_CHRATR_CROSSEDOUT ); + if( pCrossedOutItem && xPropSetInfo->hasPropertyByName( sPropName ) ) { - aTmp <<= static_cast<sal_Int16>(static_cast<const SvxCrossedOutItem *>(pItem)->GetStrikeout()); + aTmp <<= static_cast<sal_Int16>(pCrossedOutItem->GetStrikeout()); rFCompPropSet->setPropertyValue( sPropName, aTmp ); } @@ -1066,7 +1041,7 @@ uno::Reference< drawing::XShape > SwHTMLParser::InsertControl( SVX_CSS1_LTYPE_TWIP == rCSS1PropInfo.m_eTopType ) { const SwStartNode *pFlySttNd = - m_pPam->GetPoint()->nNode.GetNode().FindFlyStartNode(); + m_pPam->GetPoint()->GetNode().FindFlyStartNode(); if( pFlySttNd ) { @@ -1212,7 +1187,7 @@ void SwHTMLParser::NewForm( bool bAppend ) if( bAppend ) { - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_SPACE ); else AddParSpace(); @@ -1301,18 +1276,22 @@ void SwHTMLParser::NewForm( bool bAppend ) return; uno::Reference< XInterface > xInt; + uno::Reference<XForm> xForm; try { xInt = rSrvcMgr->createInstance("com.sun.star.form.component.Form"); + if (!xInt.is()) + return; + xForm.set(xInt, UNO_QUERY); + SAL_WARN_IF(!xForm.is(), "sw", "no XForm for com.sun.star.form.component.Form?"); + if (!xForm.is()) + return; } - catch (const css::lang::ServiceNotRegisteredException&) + catch (...) { - } - if( !xInt.is() ) + TOOLS_WARN_EXCEPTION("sw", ""); return; - - uno::Reference< XForm > xForm( xInt, UNO_QUERY ); - OSL_ENSURE( xForm.is(), "no Form?" ); + } uno::Reference< container::XIndexContainer > xFormComps( xForm, UNO_QUERY ); m_pFormImpl->SetFormComps( xFormComps ); @@ -1371,7 +1350,7 @@ void SwHTMLParser::EndForm( bool bAppend ) { if( bAppend ) { - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_SPACE ); else AddParSpace(); @@ -1448,7 +1427,7 @@ void SwHTMLParser::InsertInput() nMaxLen = static_cast<sal_Int16>(rOption.GetNumber()); break; case HtmlOptionId::SIZE: - nSize = static_cast<sal_uInt16>(rOption.GetNumber()); + nSize = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::SRC: sImgSrc = rOption.GetString(); @@ -1628,7 +1607,7 @@ void SwHTMLParser::InsertInput() if( bDisabled ) { - xPropSet->setPropertyValue("Enabled", makeAny(false) ); + xPropSet->setPropertyValue("Enabled", Any(false) ); } } @@ -1673,14 +1652,8 @@ void SwHTMLParser::InsertInput() case HTMLInputType::Image: { // SIZE = WIDTH - aSz.setWidth( nSize ? nSize : nWidth ); - aSz.setWidth( nWidth ); - aSz.setHeight( nHeight ); - if( (aSz.Width() || aSz.Height()) && Application::GetDefaultDevice() ) - { - aSz = Application::GetDefaultDevice() - ->PixelToLogic( aSz, MapMode( MapUnit::Map100thMM ) ); - } + aSz.setWidth(o3tl::convert(nWidth, o3tl::Length::px, o3tl::Length::mm100)); + aSz.setHeight(o3tl::convert(nHeight, o3tl::Length::px, o3tl::Length::mm100)); aTmp <<= FormButtonType_SUBMIT; xPropSet->setPropertyValue("ButtonType", aTmp ); @@ -1763,15 +1736,9 @@ void SwHTMLParser::InsertInput() if( bUseSize && nSize>0 ) { - if( Application::GetDefaultDevice() ) - { - Size aNewSz( nSize, 0 ); - aNewSz = Application::GetDefaultDevice() - ->PixelToLogic( aNewSz, MapMode( MapUnit::Map100thMM ) ); - aSz.setWidth( aNewSz.Width() ); - OSL_ENSURE( !aTextSz.Width(), "text width is present" ); - bMinWidth = false; - } + aSz.setWidth(o3tl::convert(nSize, o3tl::Length::px, o3tl::Length::mm100)); + OSL_ENSURE( !aTextSz.Width(), "text width is present" ); + bMinWidth = false; } SfxItemSet aCSS1ItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() ); @@ -1907,10 +1874,10 @@ void SwHTMLParser::NewTextArea() bDisabled = true; break; case HtmlOptionId::ROWS: - nRows = static_cast<sal_uInt16>(rOption.GetNumber()); + nRows = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::COLS: - nCols = static_cast<sal_uInt16>(rOption.GetNumber()); + nCols = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::WRAP: nWrap = rOption.GetEnum( aHTMLTextAreaWrapTable, nWrap ); @@ -2022,7 +1989,7 @@ void SwHTMLParser::NewTextArea() if( bDisabled ) { - xPropSet->setPropertyValue("Enabled", makeAny(false) ); + xPropSet->setPropertyValue("Enabled", Any(false) ); } OSL_ENSURE( m_pFormImpl->GetText().isEmpty(), "Text is not empty!" ); @@ -2188,7 +2155,7 @@ void SwHTMLParser::NewSelect() bDisabled = true; break; case HtmlOptionId::SIZE: - m_nSelectEntryCnt = static_cast<sal_uInt16>(rOption.GetNumber()); + m_nSelectEntryCnt = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::TABINDEX: @@ -2279,14 +2246,14 @@ void SwHTMLParser::NewSelect() if( bDisabled ) { - xPropSet->setPropertyValue("Enabled", makeAny(false) ); + xPropSet->setPropertyValue("Enabled", Any(false) ); } Size aTextSz( 0, 0 ); bool bMinWidth = true, bMinHeight = true; if( !bMultiple && 1==m_nSelectEntryCnt ) { - xPropSet->setPropertyValue("Dropdown", makeAny(true) ); + xPropSet->setPropertyValue("Dropdown", Any(true) ); } else { @@ -2295,7 +2262,7 @@ void SwHTMLParser::NewSelect() if( bMultiple ) { - xPropSet->setPropertyValue("MultiSelection", makeAny(true) ); + xPropSet->setPropertyValue("MultiSelection", Any(true) ); } aTextSz.setHeight( m_nSelectEntryCnt ); bMinHeight = false; @@ -2479,7 +2446,7 @@ void SwHTMLParser::InsertSelectText() { sal_Int32 nLen = rText.getLength(); if( !nLen || ' '==rText[nLen-1]) - aToken = aToken.replaceAt( 0, 1, "" ); + aToken.remove( 0, 1 ); } if( !aToken.isEmpty() ) rText += aToken; diff --git a/sw/source/filter/html/htmlform.hxx b/sw/source/filter/html/htmlform.hxx index 0a3f02db47d1..d1acce1faf57 100644 --- a/sw/source/filter/html/htmlform.hxx +++ b/sw/source/filter/html/htmlform.hxx @@ -20,8 +20,6 @@ #ifndef INCLUDED_SW_SOURCE_FILTER_HTML_HTMLFORM_HXX #define INCLUDED_SW_SOURCE_FILTER_HTML_HTMLFORM_HXX -#include <sal/types.h> - extern const char* aEventListenerTable[]; extern const char* aEventMethodTable[]; extern const char* aEventSDOptionTable[]; diff --git a/sw/source/filter/html/htmlforw.cxx b/sw/source/filter/html/htmlforw.cxx index 91262fac3763..6416dfc93cd7 100644 --- a/sw/source/filter/html/htmlforw.cxx +++ b/sw/source/filter/html/htmlforw.cxx @@ -31,6 +31,7 @@ #include <hintids.hxx> #include <o3tl/any.hxx> #include <rtl/math.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <svl/macitem.hxx> #include <svtools/htmlout.hxx> @@ -46,6 +47,7 @@ #include <editeng/postitem.hxx> #include <editeng/udlnitem.hxx> #include <editeng/crossedoutitem.hxx> +#include <osl/diagnose.h> #include <docsh.hxx> #include <fmtanchr.hxx> #include <viewsh.hxx> @@ -78,9 +80,7 @@ const HtmlFrmOpts HTML_FRMOPTS_IMG_CONTROL_CSS1 = static void lcl_html_outEvents( SvStream& rStrm, const uno::Reference< form::XFormComponent >& rFormComp, - bool bCfgStarBasic, - rtl_TextEncoding eDestEnc, - OUString *pNonConvertableChars ) + bool bCfgStarBasic ) { uno::Reference< uno::XInterface > xParentIfc = rFormComp->getParent(); OSL_ENSURE( xParentIfc.is(), "lcl_html_outEvents: no parent interface" ); @@ -163,10 +163,10 @@ static void lcl_html_outEvents( SvStream& rStrm, } } - OString sOut = " "; + OString sOut = " "_ostr; if( pOpt && (EXTENDED_STYPE != eScriptType || rDesc.AddListenerParam.isEmpty()) ) - sOut += OString(pOpt); + sOut += pOpt; else { sOut += OOO_STRING_SVTOOLS_HTML_O_sdevent + @@ -175,7 +175,7 @@ static void lcl_html_outEvents( SvStream& rStrm, } sOut += "=\""; rStrm.WriteOString( sOut ); - HTMLOutFuncs::Out_String( rStrm, rDesc.ScriptCode, eDestEnc, pNonConvertableChars ); + HTMLOutFuncs::Out_String( rStrm, rDesc.ScriptCode ); rStrm.WriteChar( '\"' ); if( EXTENDED_STYPE == eScriptType && !rDesc.AddListenerParam.isEmpty() ) @@ -184,8 +184,7 @@ static void lcl_html_outEvents( SvStream& rStrm, OUStringToOString(sListener, RTL_TEXTENCODING_ASCII_US) + "-" + OUStringToOString(sMethod, RTL_TEXTENCODING_ASCII_US) + "=\""; rStrm.WriteOString( sOut ); - HTMLOutFuncs::Out_String( rStrm, rDesc.AddListenerParam, - eDestEnc, pNonConvertableChars ); + HTMLOutFuncs::Out_String( rStrm, rDesc.AddListenerParam ); rStrm.WriteChar( '\"' ); } } @@ -213,7 +212,7 @@ static bool lcl_html_isHTMLControl( sal_Int16 nClassId ) bool SwHTMLWriter::HasControls() const { - sal_uInt32 nStartIdx = m_pCurrentPam->GetPoint()->nNode.GetIndex(); + SwNodeOffset nStartIdx = m_pCurrentPam->GetPoint()->GetNodeIndex(); size_t i = 0; // Skip all controls in front of the current paragraph @@ -241,8 +240,8 @@ void SwHTMLWriter::OutForm( bool bTag_On, const SwStartNode *pStartNd ) } uno::Reference< container::XIndexContainer > xNewFormComps; - sal_uInt32 nStartIdx = pStartNd ? pStartNd->GetIndex() - : m_pCurrentPam->GetPoint()->nNode.GetIndex(); + SwNodeOffset nStartIdx = pStartNd ? pStartNd->GetIndex() + : m_pCurrentPam->GetPoint()->GetNodeIndex(); // skip controls before the interesting area size_t i = 0; @@ -266,7 +265,7 @@ void SwHTMLWriter::OutForm( bool bTag_On, const SwStartNode *pStartNd ) uno::Reference< container::XIndexContainer > xCurrentFormComps;// current form in table const SwStartNode *pCurrentStNd = nullptr; // and the start node of a Control sal_Int32 nCurrentCtrls = 0; // and the found controls in it - sal_uInt32 nEndIdx = pStartNd->EndOfSectionIndex(); + SwNodeOffset nEndIdx = pStartNd->EndOfSectionIndex(); for( ; i < m_aHTMLControls.size() && m_aHTMLControls[i]->nNdIdx <= nEndIdx; i++ ) { @@ -434,16 +433,16 @@ void SwHTMLWriter::OutForm( bool bOn, if( !bOn ) { DecIndentLevel(); // indent content of form - if( m_bLFPossible ) + if (IsLFPossible()) OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_form, false ); - m_bLFPossible = true; + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_form), false ); + SetLFPossible(true); return; } // the new form is opened - if( m_bLFPossible ) + if (IsLFPossible()) OutNewLine(); OString sOut = "<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_form; @@ -456,9 +455,8 @@ void SwHTMLWriter::OutForm( bool bOn, { sOut += " " OOO_STRING_SVTOOLS_HTML_O_name "=\""; Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( Strm(), *s, - m_eDestEnc, &m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( Strm(), *s ); + sOut = "\""_ostr; } } @@ -471,8 +469,8 @@ void SwHTMLWriter::OutForm( bool bOn, Strm().WriteOString( sOut ); OUString aURL = URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), *s); - HTMLOutFuncs::Out_String( Strm(), aURL, m_eDestEnc, &m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( Strm(), aURL ); + sOut = "\""_ostr; } } @@ -503,7 +501,7 @@ void SwHTMLWriter::OutForm( bool bOn, if( pStr ) { - sOut += OStringLiteral(" " OOO_STRING_SVTOOLS_HTML_O_enctype "=\"") + + sOut += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_enctype "=\"") + pStr + "\""; } } @@ -515,19 +513,18 @@ void SwHTMLWriter::OutForm( bool bOn, { sOut += " " OOO_STRING_SVTOOLS_HTML_O_target "=\""; Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( Strm(), *s, - m_eDestEnc, &m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( Strm(), *s ); + sOut = "\""_ostr; } } Strm().WriteOString( sOut ); uno::Reference< form::XFormComponent > xFormComp( rFormComps, uno::UNO_QUERY ); - lcl_html_outEvents( Strm(), xFormComp, m_bCfgStarBasic, m_eDestEnc, &m_aNonConvertableCharacters ); + lcl_html_outEvents( Strm(), xFormComp, m_bCfgStarBasic ); Strm().WriteChar( '>' ); IncIndentLevel(); // indent content of form - m_bLFPossible = true; + SetLFPossible(true); } void SwHTMLWriter::OutHiddenControls( @@ -572,7 +569,7 @@ void SwHTMLWriter::OutHiddenControls( if( form::FormComponentType::HIDDENCONTROL == *n ) { - if( m_bLFPossible ) + if (IsLFPossible()) OutNewLine( true ); OString sOut = "<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_input " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" @@ -585,9 +582,8 @@ void SwHTMLWriter::OutHiddenControls( { sOut += " " OOO_STRING_SVTOOLS_HTML_O_name "=\""; Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( Strm(), *s, - m_eDestEnc, &m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( Strm(), *s ); + sOut = "\""_ostr; } } aTmp = xPropSet->getPropertyValue( "HiddenValue" ); @@ -597,9 +593,8 @@ void SwHTMLWriter::OutHiddenControls( { sOut += " " OOO_STRING_SVTOOLS_HTML_O_value "=\""; Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( Strm(), *s, - m_eDestEnc, &m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( Strm(), *s ); + sOut = "\""_ostr; } } sOut += ">"; @@ -663,7 +658,7 @@ static void GetControlSize(const SdrUnoObj& rFormObj, Size& rSz, SwDoc *pDoc) SdrView* pDrawView = pVSh->GetDrawView(); OSL_ENSURE( pDrawView && pVSh->GetWin(), "no DrawView or window!" ); if ( pDrawView && pVSh->GetWin() ) - xControl = rFormObj.GetUnoControl( *pDrawView, *pVSh->GetWin() ); + xControl = rFormObj.GetUnoControl( *pDrawView, *pVSh->GetWin()->GetOutDev() ); uno::Reference< awt::XTextLayoutConstrains > xLC( xControl, uno::UNO_QUERY ); OSL_ENSURE( xLC.is(), "no XTextLayoutConstrains" ); if( !xLC.is() ) @@ -675,7 +670,7 @@ static void GetControlSize(const SdrUnoObj& rFormObj, Size& rSz, SwDoc *pDoc) rSz.setHeight( nLines ); } -Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, +SwHTMLWriter& OutHTML_DrawFrameFormatAsControl( SwHTMLWriter& rWrt, const SwDrawFrameFormat& rFormat, const SdrUnoObj& rFormObj, bool bInCntnr ) @@ -691,8 +686,7 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - rHTMLWrt.m_nFormCntrlCnt++; + rWrt.m_nFormCntrlCnt++; enum Tag { TAG_INPUT, TAG_SELECT, TAG_TEXTAREA, TAG_NONE }; static char const * const TagNames[] = { @@ -775,8 +769,8 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, break; case form::FormComponentType::LISTBOX: - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine( true ); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine( true ); eTag = TAG_SELECT; aTmp = xPropSet->getPropertyValue( "Dropdown" ); if( auto b1 = o3tl::tryAccess<bool>(aTmp) ) @@ -815,14 +809,14 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, if( xPropSetInfo->hasPropertyByName( sMultiLine ) ) { aTmp = xPropSet->getPropertyValue( sMultiLine ); - auto b = o3tl::tryAccess<bool>(aTmp); - bMultiLine = b && *b; + std::optional<const bool> b = o3tl::tryAccess<bool>(aTmp); + bMultiLine = b.has_value() && *b; } if( bMultiLine ) { - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine( true ); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine( true ); eTag = TAG_TEXTAREA; if( aSz.Height() ) @@ -843,10 +837,10 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, { const char *pWrapStr = nullptr; auto aTmp2 = xPropSet->getPropertyValue( "HardLineBreaks" ); - auto b = o3tl::tryAccess<bool>(aTmp2); - pWrapStr = (b && *b) ? OOO_STRING_SVTOOLS_HTML_WW_hard + std::optional<const bool> b = o3tl::tryAccess<bool>(aTmp2); + pWrapStr = (b.has_value() && *b) ? OOO_STRING_SVTOOLS_HTML_WW_hard : OOO_STRING_SVTOOLS_HTML_WW_soft; - sOptions += OStringLiteral(" " OOO_STRING_SVTOOLS_HTML_O_wrap "=\"") + + sOptions += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_wrap "=\"") + pWrapStr + "\""; } } @@ -924,10 +918,10 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, if( eTag == TAG_NONE ) return rWrt; - OString sOut = OStringLiteral("<") + TagNames[eTag]; + OString sOut = OString::Concat("<") + TagNames[eTag]; if( eType != TYPE_NONE ) { - sOut += OStringLiteral(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"") + + sOut += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"") + TypeNames[eType] + "\""; } @@ -938,9 +932,8 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, { sOut += " " OOO_STRING_SVTOOLS_HTML_O_name "=\""; rWrt.Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( rWrt.Strm(), *s, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( rWrt.Strm(), *s ); + sOut = "\""_ostr; } } @@ -957,8 +950,8 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, { sOut += " " OOO_STRING_SVTOOLS_HTML_O_value "=\""; rWrt.Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( rWrt.Strm(), sValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( rWrt.Strm(), sValue ); + sOut = "\""_ostr; } sOut += " " + sOptions; @@ -974,25 +967,12 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, rWrt.Strm().WriteOString( sOut ); HTMLOutFuncs::Out_String( rWrt.Strm(), - URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(), *s), - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - sOut = "\""; + URIHelper::simpleNormalizedMakeRelative( rWrt.GetBaseURL(), *s) ); + sOut = "\""_ostr; } } - Size aTwipSz( rFormObj.GetLogicRect().GetSize() ); - Size aPixelSz( 0, 0 ); - if( (aTwipSz.Width() || aTwipSz.Height()) && - Application::GetDefaultDevice() ) - { - aPixelSz = - Application::GetDefaultDevice()->LogicToPixel( aTwipSz, - MapMode(MapUnit::MapTwip) ); - if( !aPixelSz.Width() && aTwipSz.Width() ) - aPixelSz.setWidth( 1 ); - if( !aPixelSz.Height() && aTwipSz.Height() ) - aPixelSz.setHeight( 1 ); - } + Size aPixelSz(SwHTMLWriter::ToPixel(rFormObj.GetLogicRect().GetSize())); if( aPixelSz.Width() ) { @@ -1025,7 +1005,7 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, rWrt.Strm().WriteOString( sOut ); OSL_ENSURE( !bInCntnr, "Container is not supported for Controls" ); - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) && !bInCntnr ) + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_DRAW ) && !bInCntnr ) { // If Character-Objects can't be positioned absolutely, // then delete the corresponding flag. @@ -1035,15 +1015,14 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, } OString aEndTags; if( nFrameOpts != HtmlFrmOpts::NONE ) - aEndTags = rHTMLWrt.OutFrameFormatOptions(rFormat, OUString(), nFrameOpts); + aEndTags = rWrt.OutFrameFormatOptions(rFormat, u"", nFrameOpts); - if( rHTMLWrt.m_bCfgOutStyles ) + if( rWrt.m_bCfgOutStyles ) { bool bEdit = TAG_TEXTAREA == eTag || TYPE_FILE == eType || TYPE_TEXT == eType; - SfxItemSet aItemSet( rHTMLWrt.m_pDoc->GetAttrPool(), svl::Items<RES_CHRATR_BEGIN, - RES_CHRATR_END>{} ); + SfxItemSetFixed<RES_CHRATR_BEGIN, RES_CHRATR_END> aItemSet( rWrt.m_pDoc->GetAttrPool() ); if( xPropSetInfo->hasPropertyByName( "BackgroundColor" ) ) { aTmp = xPropSet->getPropertyValue( "BackgroundColor" ); @@ -1141,13 +1120,12 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, } } - rHTMLWrt.OutCSS1_FrameFormatOptions( rFormat, nFrameOpts, &rFormObj, + rWrt.OutCSS1_FrameFormatOptions( rFormat, nFrameOpts, &rFormObj, &aItemSet ); } uno::Reference< form::XFormComponent > xFormComp( xControlModel, uno::UNO_QUERY ); - lcl_html_outEvents( rWrt.Strm(), xFormComp, rHTMLWrt.m_bCfgStarBasic, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + lcl_html_outEvents( rWrt.Strm(), xFormComp, rWrt.m_bCfgStarBasic ); rWrt.Strm().WriteChar( '>' ); @@ -1156,7 +1134,7 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, aTmp = xPropSet->getPropertyValue( "StringItemList" ); if( auto aList = o3tl::tryAccess<uno::Sequence<OUString>>(aTmp) ) { - rHTMLWrt.IncIndentLevel(); // the content of Select can be indented + rWrt.IncIndentLevel(); // the content of Select can be indented sal_Int32 nCnt = aList->getLength(); const OUString *pStrings = aList->getConstArray(); @@ -1200,15 +1178,14 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, if( bSelected ) nSel++; - rHTMLWrt.OutNewLine(); // every Option gets its own line - sOut = "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_option; + rWrt.OutNewLine(); // every Option gets its own line + sOut = "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_option; if( !sVal.isEmpty() || bEmptyVal ) { sOut += " " OOO_STRING_SVTOOLS_HTML_O_value "=\""; rWrt.Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( rWrt.Strm(), sVal, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - sOut = "\""; + HTMLOutFuncs::Out_String( rWrt.Strm(), sVal ); + sOut = "\""_ostr; } if( bSelected ) sOut += " " OOO_STRING_SVTOOLS_HTML_O_selected; @@ -1216,15 +1193,14 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, sOut += ">"; rWrt.Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( rWrt.Strm(), pStrings[i], - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rWrt.Strm(), pStrings[i] ); } - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_option, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_option), false ); - rHTMLWrt.DecIndentLevel(); - rHTMLWrt.OutNewLine();// the </SELECT> gets its own line + rWrt.DecIndentLevel(); + rWrt.OutNewLine();// the </SELECT> gets its own line } - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_select, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_select), false ); } else if( TAG_TEXTAREA == eTag ) { @@ -1245,13 +1221,12 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, while ( nPos != -1 ) { if( nPos ) - rWrt.Strm().WriteCharPtr( SAL_NEWLINE_STRING ); + rWrt.Strm().WriteOString( SAL_NEWLINE_STRING ); OUString aLine = sVal.getToken( 0, 0x0A, nPos ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aLine, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rWrt.Strm(), aLine ); } } - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_textarea, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_textarea), false ); } else if( TYPE_CHECKBOX == eType || TYPE_RADIO == eType ) { @@ -1260,8 +1235,7 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, { if( !s->isEmpty() ) { - HTMLOutFuncs::Out_String( rWrt.Strm(), *s, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( ' ' ); + HTMLOutFuncs::Out_String( rWrt.Strm(), *s ).WriteChar( ' ' ); } } } @@ -1270,10 +1244,10 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, rWrt.Strm().WriteOString( aEndTags ); // Controls aren't bound to a paragraph, therefore don't output LF anymore! - rHTMLWrt.m_bLFPossible = false; + rWrt.SetLFPossible(false); - if( rHTMLWrt.mxFormComps.is() ) - rHTMLWrt.OutHiddenControls( rHTMLWrt.mxFormComps, xPropSet ); + if( rWrt.mxFormComps.is() ) + rWrt.OutHiddenControls( rWrt.mxFormComps, xPropSet ); return rWrt; } @@ -1282,7 +1256,7 @@ Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, */ static void AddControl( HTMLControls& rControls, const SdrUnoObj& rFormObj, - sal_uInt32 nNodeIdx ) + SwNodeOffset nNodeIdx ) { const uno::Reference< awt::XControlModel >& xControlModel = rFormObj.GetUnoControlModel(); @@ -1315,51 +1289,46 @@ void SwHTMLWriter::GetControls() // With that array it's possible to find out where form::Forms must be // opened and closed. - if( m_pHTMLPosFlyFrames ) + // collect the paragraph-bound controls + for( size_t i=0; i<m_aHTMLPosFlyFrames.size(); i++ ) { - // collect the paragraph-bound controls - for( size_t i=0; i<m_pHTMLPosFlyFrames->size(); i++ ) - { - const SwHTMLPosFlyFrame* pPosFlyFrame = (*m_pHTMLPosFlyFrames)[ i ].get(); - if( HtmlOut::Control != pPosFlyFrame->GetOutFn() ) - continue; + const SwHTMLPosFlyFrame* pPosFlyFrame = m_aHTMLPosFlyFrames[ i ].get(); + if( HtmlOut::Control != pPosFlyFrame->GetOutFn() ) + continue; - const SdrObject *pSdrObj = pPosFlyFrame->GetSdrObject(); - OSL_ENSURE( pSdrObj, "Where is the SdrObject?" ); - if( !pSdrObj ) - continue; + const SdrObject *pSdrObj = pPosFlyFrame->GetSdrObject(); + OSL_ENSURE( pSdrObj, "Where is the SdrObject?" ); + if( !pSdrObj ) + continue; - AddControl( m_aHTMLControls, dynamic_cast<const SdrUnoObj&>(*pSdrObj), - pPosFlyFrame->GetNdIndex().GetIndex() ); - } + AddControl( m_aHTMLControls, dynamic_cast<const SdrUnoObj&>(*pSdrObj), + pPosFlyFrame->GetNdIndex().GetIndex() ); } // and now the ones in a character-bound frame - const SwFrameFormats* pSpzFrameFormats = m_pDoc->GetSpzFrameFormats(); - for( size_t i=0; i<pSpzFrameFormats->size(); i++ ) + for(sw::SpzFrameFormat* pSpz: *m_pDoc->GetSpzFrameFormats()) { - const SwFrameFormat *pFrameFormat = (*pSpzFrameFormats)[i]; - if( RES_DRAWFRMFMT != pFrameFormat->Which() ) + if( RES_DRAWFRMFMT != pSpz->Which() ) continue; - const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor(); - const SwPosition *pPos = rAnchor.GetContentAnchor(); - if ((RndStdIds::FLY_AS_CHAR != rAnchor.GetAnchorId()) || !pPos) + const SwFormatAnchor& rAnchor = pSpz->GetAnchor(); + const SwNode *pAnchorNode = rAnchor.GetAnchorNode(); + if ((RndStdIds::FLY_AS_CHAR != rAnchor.GetAnchorId()) || !pAnchorNode) continue; const SdrObject *pSdrObj = - SwHTMLWriter::GetHTMLControl( *static_cast<const SwDrawFrameFormat*>(pFrameFormat) ); + SwHTMLWriter::GetHTMLControl(*static_cast<SwDrawFrameFormat*>(pSpz) ); if( !pSdrObj ) continue; - AddControl( m_aHTMLControls, dynamic_cast<const SdrUnoObj&>(*pSdrObj), pPos->nNode.GetIndex() ); + AddControl( m_aHTMLControls, dynamic_cast<const SdrUnoObj&>(*pSdrObj), pAnchorNode->GetIndex() ); } } HTMLControl::HTMLControl( - const uno::Reference< container::XIndexContainer > & rFormComps, - sal_uInt32 nIdx ) : - xFormComps( rFormComps ), nNdIdx( nIdx ), nCount( 1 ) + uno::Reference< container::XIndexContainer > _xFormComps, + SwNodeOffset nIdx ) : + xFormComps(std::move( _xFormComps )), nNdIdx( nIdx ), nCount( 1 ) {} HTMLControl::~HTMLControl() diff --git a/sw/source/filter/html/htmlftn.cxx b/sw/source/filter/html/htmlftn.cxx index cec1d3df6326..74916af9c705 100644 --- a/sw/source/filter/html/htmlftn.cxx +++ b/sw/source/filter/html/htmlftn.cxx @@ -17,9 +17,14 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <sal/config.h> + +#include <string_view> + #include <osl/diagnose.h> #include <svtools/htmlout.hxx> #include <svtools/htmlkywd.hxx> +#include <svtools/HtmlWriter.hxx> #include <rtl/strbuf.hxx> #include <ndindex.hxx> #include <fmtftn.hxx> @@ -32,11 +37,11 @@ #include "swhtml.hxx" #include "wrthtml.hxx" -static sal_Int32 lcl_html_getNextPart( OUString& rPart, const OUString& rContent, +static sal_Int32 lcl_html_getNextPart( OUString& rPart, std::u16string_view aContent, sal_Int32 nPos ) { rPart.clear(); - sal_Int32 nLen = rContent.getLength(); + sal_Int32 nLen = aContent.size(); if( nPos >= nLen ) { nPos = -1; @@ -46,7 +51,7 @@ static sal_Int32 lcl_html_getNextPart( OUString& rPart, const OUString& rContent bool bQuoted = false, bDone = false; for( ; nPos < nLen && !bDone; nPos++ ) { - sal_Unicode c = rContent[nPos]; + sal_Unicode c = aContent[nPos]; switch( c ) { case '\\': @@ -75,7 +80,7 @@ static sal_Int32 lcl_html_getNextPart( OUString& rPart, const OUString& rContent } static sal_Int32 lcl_html_getEndNoteInfo( SwEndNoteInfo& rInfo, - const OUString& rContent, + std::u16string_view aContent, bool bEndNote ) { sal_Int32 nStrPos = 0; @@ -83,7 +88,7 @@ static sal_Int32 lcl_html_getEndNoteInfo( SwEndNoteInfo& rInfo, { OUString aPart; if( -1 != nStrPos ) - nStrPos = lcl_html_getNextPart( aPart, rContent, nStrPos ); + nStrPos = lcl_html_getNextPart( aPart, aContent, nStrPos ); switch( nPart ) { @@ -95,7 +100,7 @@ static sal_Int32 lcl_html_getEndNoteInfo( SwEndNoteInfo& rInfo, break; case 1: - rInfo.m_nFootnoteOffset = aPart.isEmpty() ? 0 : static_cast<sal_uInt16>(aPart.toInt32()); + rInfo.m_nFootnoteOffset = aPart.isEmpty() ? 0 : o3tl::narrowing<sal_uInt16>(aPart.toInt32()); break; case 2: @@ -111,24 +116,24 @@ static sal_Int32 lcl_html_getEndNoteInfo( SwEndNoteInfo& rInfo, return nStrPos; } -void SwHTMLParser::FillEndNoteInfo( const OUString& rContent ) +void SwHTMLParser::FillEndNoteInfo( std::u16string_view aContent ) { SwEndNoteInfo aInfo( m_xDoc->GetEndNoteInfo() ); - lcl_html_getEndNoteInfo( aInfo, rContent, true ); + lcl_html_getEndNoteInfo( aInfo, aContent, true ); m_xDoc->SetEndNoteInfo( aInfo ); } -void SwHTMLParser::FillFootNoteInfo( const OUString& rContent ) +void SwHTMLParser::FillFootNoteInfo( std::u16string_view aContent ) { SwFootnoteInfo aInfo( m_xDoc->GetFootnoteInfo() ); - sal_Int32 nStrPos = lcl_html_getEndNoteInfo( aInfo, rContent, false ); + sal_Int32 nStrPos = lcl_html_getEndNoteInfo( aInfo, aContent, false ); for( int nPart = 4; nPart < 8; ++nPart ) { OUString aPart; if( -1 != nStrPos ) - nStrPos = lcl_html_getNextPart( aPart, rContent, nStrPos ); + nStrPos = lcl_html_getNextPart( aPart, aContent, nStrPos ); switch( nPart ) { @@ -196,11 +201,11 @@ void SwHTMLParser::FinishFootEndNote() m_xDoc->getIDocumentContentOperations().InsertPoolItem( *m_pPam, aFootnote ); SwTextFootnote * const pTextFootnote = static_cast<SwTextFootnote *>( - m_pPam->GetNode().GetTextNode()->GetTextAttrForCharAt( - m_pPam->GetPoint()->nContent.GetIndex() - 1, RES_TXTATR_FTN ) ); + m_pPam->GetPointNode().GetTextNode()->GetTextAttrForCharAt( + m_pPam->GetPoint()->GetContentIndex() - 1, RES_TXTATR_FTN ) ); // In header and footer no footnotes can be inserted. if (pTextFootnote) - m_pFootEndNoteImpl->aTextFootnotes.push_back(SwHTMLTextFootnote(m_pFootEndNoteImpl->sName,pTextFootnote)); + m_pFootEndNoteImpl->aTextFootnotes.emplace_back(m_pFootEndNoteImpl->sName,pTextFootnote); m_pFootEndNoteImpl->sName.clear(); m_pFootEndNoteImpl->sContent.clear(); m_pFootEndNoteImpl->bFixed = false; @@ -223,9 +228,9 @@ SwNodeIndex *SwHTMLParser::GetFootEndNoteSection( const OUString& rName ) size_t nCount = m_pFootEndNoteImpl->aTextFootnotes.size(); for(size_t i = 0; i < nCount; ++i) { - if (m_pFootEndNoteImpl->aTextFootnotes[i].sName == aName) + if (m_pFootEndNoteImpl->aTextFootnotes[i].GetName() == aName) { - pStartNodeIdx = m_pFootEndNoteImpl->aTextFootnotes[i].pTextFootnote->GetStartNode(); + pStartNodeIdx = const_cast<SwNodeIndex*>(m_pFootEndNoteImpl->aTextFootnotes[i].GetStartNode()); m_pFootEndNoteImpl->aTextFootnotes.erase( m_pFootEndNoteImpl->aTextFootnotes.begin() + i ); if (m_pFootEndNoteImpl->aTextFootnotes.empty()) { @@ -240,10 +245,33 @@ SwNodeIndex *SwHTMLParser::GetFootEndNoteSection( const OUString& rName ) return pStartNodeIdx; } -Writer& OutHTML_SwFormatFootnote( Writer& rWrt, const SfxPoolItem& rHt ) +SwHTMLWriter& OutHTML_SwFormatLineBreak(SwHTMLWriter& rWrt, const SfxPoolItem& rHt) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); + const auto& rLineBreak = static_cast<const SwFormatLineBreak&>(rHt); + HtmlWriter aWriter(rWrt.Strm(), rWrt.maNamespace); + aWriter.start(OOO_STRING_SVTOOLS_HTML_linebreak ""_ostr); + switch (rLineBreak.GetValue()) + { + case SwLineBreakClear::NONE: + aWriter.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, "none"); + break; + case SwLineBreakClear::LEFT: + aWriter.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, "left"); + break; + case SwLineBreakClear::RIGHT: + aWriter.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, "right"); + break; + case SwLineBreakClear::ALL: + aWriter.attribute(OOO_STRING_SVTOOLS_HTML_O_clear, "all"); + break; + } + aWriter.end(); + return rWrt; +} + +SwHTMLWriter& OutHTML_SwFormatFootnote( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ) +{ SwFormatFootnote& rFormatFootnote = const_cast<SwFormatFootnote&>(static_cast<const SwFormatFootnote&>(rHt)); SwTextFootnote *pTextFootnote = rFormatFootnote.GetTextFootnote(); if( !pTextFootnote ) @@ -253,55 +281,58 @@ Writer& OutHTML_SwFormatFootnote( Writer& rWrt, const SfxPoolItem& rHt ) size_t nPos; if( rFormatFootnote.IsEndNote() ) { - nPos = rHTMLWrt.m_pFootEndNotes ? rHTMLWrt.m_pFootEndNotes->size() : 0; - OSL_ENSURE( nPos == static_cast<size_t>(rHTMLWrt.m_nFootNote + rHTMLWrt.m_nEndNote), + nPos = rWrt.m_xFootEndNotes ? rWrt.m_xFootEndNotes->size() : 0; + OSL_ENSURE( nPos == static_cast<size_t>(rWrt.m_nFootNote + rWrt.m_nEndNote), "OutHTML_SwFormatFootnote: wrong position" ); sClass = OOO_STRING_SVTOOLS_HTML_sdendnote_anc; - sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdendnote + OUString::number( static_cast<sal_Int32>(++rHTMLWrt.m_nEndNote) ); + sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdendnote + OUString::number( static_cast<sal_Int32>(++rWrt.m_nEndNote) ); } else { - nPos = rHTMLWrt.m_nFootNote; + nPos = rWrt.m_nFootNote; sClass = OOO_STRING_SVTOOLS_HTML_sdfootnote_anc; - sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote + OUString::number( static_cast<sal_Int32>(++rHTMLWrt.m_nFootNote)); + sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote + OUString::number( static_cast<sal_Int32>(++rWrt.m_nFootNote)); } - if( !rHTMLWrt.m_pFootEndNotes ) - rHTMLWrt.m_pFootEndNotes.reset(new std::vector<SwTextFootnote*>); - rHTMLWrt.m_pFootEndNotes->insert( rHTMLWrt.m_pFootEndNotes->begin() + nPos, pTextFootnote ); + if( !rWrt.m_xFootEndNotes ) + rWrt.m_xFootEndNotes.emplace(); + rWrt.m_xFootEndNotes->insert( rWrt.m_xFootEndNotes->begin() + nPos, pTextFootnote ); OStringBuffer sOut; - OString aTag = rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor; + OString aTag = rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor; sOut.append("<" + aTag + " " OOO_STRING_SVTOOLS_HTML_O_class "=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), sClass, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), sClass ); sOut.append("\" " OOO_STRING_SVTOOLS_HTML_O_name "=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), sFootnoteName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), sFootnoteName ); sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_anchor "\" " OOO_STRING_SVTOOLS_HTML_O_href "=\"#"); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), sFootnoteName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), sFootnoteName ); sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_symbol "\""); if( !rFormatFootnote.GetNumStr().isEmpty() ) sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_sdfixed); sOut.append(">"); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_superscript ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_superscript )); - HTMLOutFuncs::Out_String( rWrt.Strm(), rFormatFootnote.GetViewNumStr(*rWrt.m_pDoc, nullptr), - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_superscript, false ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor, false ); + HTMLOutFuncs::Out_String( rWrt.Strm(), rFormatFootnote.GetViewNumStr(*rWrt.m_pDoc, nullptr) ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_superscript), false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor), false ); return rWrt; } void SwHTMLWriter::OutFootEndNotes() { - OSL_ENSURE( m_pFootEndNotes, + OSL_ENSURE( m_xFootEndNotes, "SwHTMLWriter::OutFootEndNotes(): unnecessary call" ); - if( !m_pFootEndNotes ) + if( !m_xFootEndNotes ) return; #if OSL_DEBUG_LEVEL > 0 @@ -310,7 +341,7 @@ void SwHTMLWriter::OutFootEndNotes() m_nFootNote = 0; m_nEndNote = 0; - for( auto *pTextFootnote : *m_pFootEndNotes ) + for( auto *pTextFootnote : *m_xFootEndNotes ) { m_pFormatFootnote = &pTextFootnote->GetFootnote(); @@ -324,20 +355,20 @@ void SwHTMLWriter::OutFootEndNotes() sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote + OUString::number(static_cast<sal_Int32>(++m_nFootNote)); } - if( m_bLFPossible ) + if (IsLFPossible()) OutNewLine(); OString sOut = "<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_division " " OOO_STRING_SVTOOLS_HTML_O_id "=\""; Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( Strm(), sFootnoteName, m_eDestEnc, &m_aNonConvertableCharacters ); - Strm().WriteCharPtr( "\">" ); + HTMLOutFuncs::Out_String( Strm(), sFootnoteName ); + Strm().WriteOString( "\">" ); - m_bLFPossible = true; + SetLFPossible(true); IncIndentLevel(); // indent content of <DIV> OSL_ENSURE( pTextFootnote, "SwHTMLWriter::OutFootEndNotes: SwTextFootnote is missing" ); - SwNodeIndex *pSttNdIdx = pTextFootnote->GetStartNode(); + const SwNodeIndex *pSttNdIdx = pTextFootnote->GetStartNode(); OSL_ENSURE( pSttNdIdx, "SwHTMLWriter::OutFootEndNotes: StartNode-Index is missing" ); if( pSttNdIdx ) @@ -348,10 +379,10 @@ void SwHTMLWriter::OutFootEndNotes() } DecIndentLevel(); // indent content of <DIV> - if( m_bLFPossible ) + if (IsLFPossible()) OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_division, false ); - m_bLFPossible = true; + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false ); + SetLFPossible(true); OSL_ENSURE( !m_pFormatFootnote, "SwHTMLWriter::OutFootEndNotes: Footnote was not output" ); @@ -373,7 +404,7 @@ void SwHTMLWriter::OutFootEndNotes() "SwHTMLWriter::OutFootEndNotes: Number of endnotes does not match" ); #endif - m_pFootEndNotes.reset(); + m_xFootEndNotes.reset(); m_nFootNote = m_nEndNote = 0; } @@ -395,7 +426,7 @@ OUString SwHTMLWriter::GetFootEndNoteSym( const SwFormatFootnote& rFormatFootnot } void SwHTMLWriter::OutFootEndNoteSym( const SwFormatFootnote& rFormatFootnote, - const OUString& rNum, + std::u16string_view rNum, sal_uInt16 nScript ) { const SwEndNoteInfo *pInfo; @@ -433,23 +464,27 @@ void SwHTMLWriter::OutFootEndNoteSym( const SwFormatFootnote& rFormatFootnote, } } - OStringBuffer sOut; - sOut.append('<').append(GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor).append(' ') - .append(OOO_STRING_SVTOOLS_HTML_O_class).append("=\""); - Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( Strm(), sClass, m_eDestEnc, &m_aNonConvertableCharacters ); - sOut.append("\" ").append(OOO_STRING_SVTOOLS_HTML_O_name).append("=\""); - Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( Strm(), sFootnoteName, m_eDestEnc, &m_aNonConvertableCharacters ); - sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_symbol).append("\" ") - .append(OOO_STRING_SVTOOLS_HTML_O_href).append("=\"#"); - Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( Strm(), sFootnoteName, m_eDestEnc, &m_aNonConvertableCharacters ); - sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_anchor).append("\">"); - Strm().WriteOString( sOut.makeStringAndClear() ); - - HTMLOutFuncs::Out_String( Strm(), rNum, m_eDestEnc, &m_aNonConvertableCharacters ); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor, false ); + OStringBuffer sOut("<" + + GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor " " + OOO_STRING_SVTOOLS_HTML_O_class "=\""); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), sClass ); + sOut.append("\" " OOO_STRING_SVTOOLS_HTML_O_name "=\""); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), sFootnoteName ); + sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_symbol "\" " + OOO_STRING_SVTOOLS_HTML_O_href "=\"#"); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), sFootnoteName ); + sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_anchor "\">"); + Strm().WriteOString( sOut ); + sOut.setLength(0); + + HTMLOutFuncs::Out_String( Strm(), rNum ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor), false ); } static int lcl_html_fillEndNoteInfo( const SwEndNoteInfo& rInfo, @@ -486,11 +521,9 @@ static int lcl_html_fillEndNoteInfo( const SwEndNoteInfo& rInfo, return nParts; } -static void lcl_html_outFootEndNoteInfo( Writer& rWrt, OUString const *pParts, +static void lcl_html_outFootEndNoteInfo( SwHTMLWriter& rWrt, OUString const *pParts, int nParts, const char *pName ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - OUStringBuffer aContent; for( int i=0; i<nParts; ++i ) { @@ -502,14 +535,14 @@ static void lcl_html_outFootEndNoteInfo( Writer& rWrt, OUString const *pParts, aContent.append(aTmp); } - rHTMLWrt.OutNewLine(); + rWrt.OutNewLine(); OString sOut = - "<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_meta " " + "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_meta " " OOO_STRING_SVTOOLS_HTML_O_name "=\"" + pName + "\" " OOO_STRING_SVTOOLS_HTML_O_content "=\""; rWrt.Strm().WriteOString( sOut ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aContent.makeStringAndClear(), rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - rWrt.Strm().WriteCharPtr( "\">" ); + HTMLOutFuncs::Out_String( rWrt.Strm(), aContent.makeStringAndClear() ); + rWrt.Strm().WriteOString( "\">" ); } void SwHTMLWriter::OutFootEndNoteInfo() @@ -529,7 +562,7 @@ void SwHTMLWriter::OutFootEndNoteInfo() int nParts = lcl_html_fillEndNoteInfo( rInfo, aParts, false ); if( rInfo.m_eNum != FTNNUM_DOC ) { - aParts[4] = rInfo.m_eNum == FTNNUM_CHAPTER ? OUStringLiteral( u"C" ) : OUStringLiteral( u"P" ); + aParts[4] = rInfo.m_eNum == FTNNUM_CHAPTER ? std::u16string_view( u"C" ) : std::u16string_view( u"P" ); nParts = 5; } if( rInfo.m_ePos != FTNPOS_PAGE) diff --git a/sw/source/filter/html/htmlgrin.cxx b/sw/source/filter/html/htmlgrin.cxx index 7b0c49cc3f3a..4b5a0d5e4bd5 100644 --- a/sw/source/filter/html/htmlgrin.cxx +++ b/sw/source/filter/html/htmlgrin.cxx @@ -19,6 +19,7 @@ #include <memory> #include <hintids.hxx> +#include <comphelper/lok.hxx> #include <comphelper/string.hxx> #include <comphelper/documentinfo.hxx> #include <vcl/svapp.hxx> @@ -34,12 +35,14 @@ #include <editeng/langitem.hxx> #include <sfx2/docfile.hxx> #include <sfx2/event.hxx> +#include <sfx2/lokhelper.hxx> #include <vcl/imap.hxx> #include <svtools/htmltokn.h> #include <svtools/htmlkywd.hxx> #include <unotools/eventcfg.hxx> #include <sal/log.hxx> #include <osl/diagnose.h> +#include <o3tl/string_view.hxx> #include <fmtornt.hxx> #include <fmturl.hxx> @@ -67,7 +70,10 @@ #include <frameformats.hxx> #include <vcl/graphicfilter.hxx> +#include <tools/UnitConversion.hxx> +#include <tools/hostfilter.hxx> #include <tools/urlobj.hxx> +#include <unotools/securityoptions.hxx> using namespace ::com::sun::star; @@ -91,7 +97,7 @@ HTMLOptionEnum<sal_Int16> const aHTMLImgVAlignTable[] = { nullptr, 0 } }; -ImageMap *SwHTMLParser::FindImageMap( const OUString& rName ) const +ImageMap *SwHTMLParser::FindImageMap( std::u16string_view rName ) const { OSL_ENSURE( rName[0] != '#', "FindImageMap: name begins with '#'!" ); @@ -99,7 +105,7 @@ ImageMap *SwHTMLParser::FindImageMap( const OUString& rName ) const { for (const auto &rpIMap : *m_pImageMaps) { - if (rName.equalsIgnoreAsciiCase(rpIMap->GetName())) + if (o3tl::equalsIgnoreAsciiCase(rName, rpIMap->GetName())) { return rpIMap.get(); } @@ -112,8 +118,8 @@ void SwHTMLParser::ConnectImageMaps() { SwNodes& rNds = m_xDoc->GetNodes(); // on the first node of section #1 - sal_uLong nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 1; - sal_uLong nEndIdx = rNds.GetEndOfAutotext().GetIndex(); + SwNodeOffset nIdx = rNds.GetEndOfAutotext().StartOfSectionIndex() + 1; + SwNodeOffset nEndIdx = rNds.GetEndOfAutotext().GetIndex(); SwGrfNode* pGrfNd; while( m_nMissingImgMaps > 0 && nIdx < nEndIdx ) @@ -235,7 +241,7 @@ void SwHTMLParser::SetAnchorAndAdjustment( sal_Int16 eVertOri, } // determine vertical alignment and anchoring - const sal_Int32 nContent = m_pPam->GetPoint()->nContent.GetIndex(); + const sal_Int32 nContent = m_pPam->GetPoint()->GetContentIndex(); if( nContent ) { aAnchor.SetType( RndStdIds::FLY_AT_CHAR ); @@ -259,7 +265,7 @@ void SwHTMLParser::SetAnchorAndAdjustment( sal_Int16 eVertOri, if( bMoveBackward ) m_pPam->Move( fnMoveBackward ); - if (aAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR && !m_pPam->GetNode().GetTextNode()) + if (aAnchor.GetAnchorId() == RndStdIds::FLY_AS_CHAR && !m_pPam->GetPointNode().GetTextNode()) { eState = SvParserState::Error; return; @@ -281,7 +287,7 @@ void SwHTMLParser::RegisterFlyFrame( SwFrameFormat *pFlyFormat ) css::text::WrapTextMode_THROUGH == pFlyFormat->GetSurround().GetSurround() ) { m_aMoveFlyFrames.emplace_back(std::make_unique<SwHTMLFrameFormatListener>(pFlyFormat)); - m_aMoveFlyCnts.push_back( m_pPam->GetPoint()->nContent.GetIndex() ); + m_aMoveFlyCnts.push_back( m_pPam->GetPoint()->GetContentIndex() ); } } @@ -307,7 +313,7 @@ namespace { sReferer = sh->GetMedium()->GetName(); } - return !SvtSecurityOptions().isUntrustedReferer(sReferer); + return !SvtSecurityOptions::isUntrustedReferer(sReferer); } } @@ -402,7 +408,7 @@ void SwHTMLParser::InsertImage() sAltNm = rOption.GetString(); break; case HtmlOptionId::BORDER: - nBorder = static_cast<sal_uInt16>(rOption.GetNumber()); + nBorder = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::ISMAP: bIsMap = true; @@ -460,12 +466,12 @@ IMAGE_SETEVENT: // When we are in an ordered list and the paragraph is still empty and not // numbered, it may be a graphic for a bullet list. - if( !m_pPam->GetPoint()->nContent.GetIndex() && + if( !m_pPam->GetPoint()->GetContentIndex() && GetNumInfo().GetDepth() > 0 && GetNumInfo().GetDepth() <= MAXLEVEL && !m_aBulletGrfs[GetNumInfo().GetDepth()-1].isEmpty() && m_aBulletGrfs[GetNumInfo().GetDepth()-1]==sGrfNm ) { - SwTextNode* pTextNode = m_pPam->GetNode().GetTextNode(); + SwTextNode* pTextNode = m_pPam->GetPointNode().GetTextNode(); if( pTextNode && ! pTextNode->IsCountedInList()) { @@ -477,7 +483,7 @@ IMAGE_SETEVENT: // It's necessary to invalidate the rule, because between the reading // of LI and the graphic an EndAction could be called. if( GetNumInfo().GetNumRule() ) - GetNumInfo().GetNumRule()->SetInvalidRule( true ); + GetNumInfo().GetNumRule()->Invalidate(); // Set the style again, so that indent of the first line is correct. SetTextCollAttrs(); @@ -499,13 +505,16 @@ IMAGE_SETEVENT: if (!sGrfNm.isEmpty()) { - if (ERRCODE_NONE == rFilter.ImportGraphic(aGraphic, "", *pStream)) + if (ERRCODE_NONE == rFilter.ImportGraphic(aGraphic, u"", *pStream)) sGrfNm.clear(); } } } else if (m_sBaseURL.isEmpty() || !aGraphicData.isEmpty()) { + if (comphelper::LibreOfficeKit::isActive() && HostFilter::isForbidden(aGraphicURL.GetHost())) + SfxLokHelper::sendNetworkAccessError("paste"); + // sBaseURL is empty if the source is clipboard // aGraphicData is non-empty for <object data="..."> -> not a linked graphic. if (ERRCODE_NONE == GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, aGraphicURL)) @@ -524,6 +533,31 @@ IMAGE_SETEVENT: nWidth = aPixelSize.Width(); if (!bHeightProvided) nHeight = aPixelSize.Height(); + // tdf#142781 - calculate the width/height keeping the aspect ratio + if (bWidthProvided && !bHeightProvided && aPixelSize.Width()) + { + if (bPercentWidth) + { + nHeight = SwFormatFrameSize::SYNCED; + bPercentHeight = true; + } + else + { + nHeight = nWidth * aPixelSize.Height() / aPixelSize.Width(); + } + } + else if (!bWidthProvided && bHeightProvided && aPixelSize.Height()) + { + if (bPercentHeight) + { + nWidth = SwFormatFrameSize::SYNCED; + bPercentWidth = true; + } + else + { + nWidth = nHeight * aPixelSize.Width() / aPixelSize.Height(); + } + } } SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() ); @@ -531,8 +565,7 @@ IMAGE_SETEVENT: if( HasStyleOptions( aStyle, aId, aClass ) ) ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ); - SfxItemSet aFrameSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( aFrameSet ); @@ -585,19 +618,19 @@ IMAGE_SETEVENT: SetFrameFormatAttrs( aItemSet, HtmlFrameFormatFlags::Box, aFrameSet ); Size aTwipSz( bPercentWidth ? 0 : nWidth, bPercentHeight ? 0 : nHeight ); - if( (aTwipSz.Width() || aTwipSz.Height()) && Application::GetDefaultDevice() ) + if( aTwipSz.Width() || aTwipSz.Height() ) { if (bWidthProvided || bHeightProvided || // attributes imply pixel! aGraphic.GetPrefMapMode().GetMapUnit() == MapUnit::MapPixel) { - aTwipSz = Application::GetDefaultDevice() - ->PixelToLogic( aTwipSz, MapMode( MapUnit::MapTwip ) ); + aTwipSz = o3tl::convert(aTwipSz, o3tl::Length::px, o3tl::Length::twip); } else { // some bitmaps may have a size in metric units (e.g. PNG); use that assert(aGraphic.GetPrefMapMode().GetMapUnit() < MapUnit::MapPixel); - aTwipSz = OutputDevice::LogicToLogic(aGraphic.GetPrefSize(), - aGraphic.GetPrefMapMode(), MapMode(MapUnit::MapTwip)); + aTwipSz = o3tl::convert(aGraphic.GetPrefSize(), + MapToO3tlLength(aGraphic.GetPrefMapMode().GetMapUnit()), + o3tl::Length::twip); } } @@ -642,21 +675,31 @@ IMAGE_SETEVENT: // bPercentWidth / bPercentHeight means we have a percent size. If that's not the case and we have no // size from nWidth / nHeight either, then inspect the image header. - if ((!bPercentWidth && !nWidth) && (!bPercentHeight && !nHeight) && allowAccessLink(*m_xDoc)) + bool bRelWidthScale = bPercentWidth && nWidth == SwFormatFrameSize::SYNCED; + bool bNeedWidth = (!bPercentWidth && !nWidth) || bRelWidthScale; + bool bRelHeightScale = bPercentHeight && nHeight == SwFormatFrameSize::SYNCED; + bool bNeedHeight = (!bPercentHeight && !nHeight) || bRelHeightScale; + if ((bNeedWidth || bNeedHeight) && !bFuzzing && allowAccessLink(*m_xDoc)) { GraphicDescriptor aDescriptor(aGraphicURL); if (aDescriptor.Detect(/*bExtendedInfo=*/true)) { // Try to use size info from the image header before defaulting to // HTML_DFLT_IMG_WIDTH/HEIGHT. - aTwipSz = Application::GetDefaultDevice()->PixelToLogic(aDescriptor.GetSizePixel(), - MapMode(MapUnit::MapTwip)); - nWidth = aTwipSz.getWidth(); - nHeight = aTwipSz.getHeight(); + aTwipSz + = o3tl::convert(aDescriptor.GetSizePixel(), o3tl::Length::px, o3tl::Length::twip); + if (!bPercentWidth && !nWidth) + { + nWidth = aTwipSz.getWidth(); + } + if (!bPercentHeight && !nHeight) + { + nHeight = aTwipSz.getHeight(); + } } } - if( !nWidth || !nHeight ) + if( !(nWidth && !bRelWidthScale) || !(nHeight && !bRelHeightScale) ) { // When the graphic is in a table, it will be requested immediately, // so that it is available before the table is layouted. @@ -747,9 +790,10 @@ IMAGE_SETEVENT: } // observe minimum values !! + bool bRelSizeScale = bRelWidthScale || bRelHeightScale; if( nPercentWidth ) { - OSL_ENSURE( !aTwipSz.Width(), + OSL_ENSURE( !aTwipSz.Width() || bRelSizeScale, "Why is a width set if we already have percentage value?" ); aTwipSz.setWidth( aGrfSz.Width() ? aGrfSz.Width() : HTML_DFLT_IMG_WIDTH ); @@ -762,7 +806,7 @@ IMAGE_SETEVENT: } if( nPercentHeight ) { - OSL_ENSURE( !aTwipSz.Height(), + OSL_ENSURE( !aTwipSz.Height() || bRelSizeScale, "Why is a height set if we already have percentage value?" ); aTwipSz.setHeight( aGrfSz.Height() ? aGrfSz.Height() : HTML_DFLT_IMG_HEIGHT ); @@ -779,7 +823,7 @@ IMAGE_SETEVENT: aFrameSize.SetHeightPercent( nPercentHeight ); aFrameSet.Put( aFrameSize ); - const SwNodeType eNodeType = m_pPam->GetNode().GetNodeType(); + const SwNodeType eNodeType = m_pPam->GetPointNode().GetNodeType(); if (eNodeType != SwNodeType::Text && eNodeType != SwNodeType::Table) return; @@ -793,7 +837,7 @@ IMAGE_SETEVENT: if( !sHTMLGrfName.isEmpty() ) { - pFlyFormat->SetName( sHTMLGrfName ); + pFlyFormat->SetFormatName( sHTMLGrfName ); // maybe jump to graphic if( JumpToMarks::Graphic == m_eJumpTo && sHTMLGrfName == m_sJmpMark ) @@ -844,10 +888,10 @@ IMAGE_SETEVENT: } if ((RndStdIds::FLY_AS_CHAR == pFlyFormat->GetAnchor().GetAnchorId()) && - m_xAttrTab->pINetFormat->GetSttPara() == - m_pPam->GetPoint()->nNode && - m_xAttrTab->pINetFormat->GetSttCnt() == - m_pPam->GetPoint()->nContent.GetIndex() - 1 ) + m_xAttrTab->pINetFormat->GetStartParagraph() == + m_pPam->GetPoint()->GetNode() && + m_xAttrTab->pINetFormat->GetStartContent() == + m_pPam->GetPoint()->GetContentIndex() - 1 ) { // the attribute was insert right before as-character anchored // graphic, therefore we move it @@ -865,6 +909,15 @@ IMAGE_SETEVENT: } } + else if (!m_aEmbedURL.isEmpty()) + { + // This is an inner <object> image and the outer <object> has a URL for us. Set that on the + // image. + SwFormatURL aURL(pFlyFormat->GetURL()); + aURL.SetURL(m_aEmbedURL, bIsMap); + m_aEmbedURL.clear(); + pFlyFormat->SetFormatAttr(aURL); + } if( !aMacroItem.GetMacroTable().empty() ) { @@ -1047,19 +1100,16 @@ void SwHTMLParser::InsertBodyOptions() m_pCSS1Parser->SetPageDescAttrs( bSetBrush ? aBrushItem.get() : nullptr, &aItemSet ); - const SfxPoolItem *pItem; - static const sal_uInt16 aWhichIds[3] = { RES_CHRATR_FONTSIZE, + static const TypedWhichId<SvxFontHeightItem> aWhichIds[3] = { RES_CHRATR_FONTSIZE, RES_CHRATR_CJK_FONTSIZE, RES_CHRATR_CTL_FONTSIZE }; - for(sal_uInt16 i : aWhichIds) + for(auto const & i : aWhichIds) { - if( SfxItemState::SET == aItemSet.GetItemState( i, false, - &pItem ) && - static_cast <const SvxFontHeightItem * >(pItem)->GetProp() != 100) + const SvxFontHeightItem *pItem = aItemSet.GetItemIfSet( i, false ); + if( pItem && pItem->GetProp() != 100) { sal_uInt32 nHeight = - ( m_aFontHeights[2] * - static_cast <const SvxFontHeightItem * >(pItem)->GetProp() ) / 100; + ( m_aFontHeights[2] * pItem->GetProp() ) / 100; SvxFontHeightItem aNewItem( nHeight, 100, i ); aItemSet.Put( aNewItem ); } @@ -1093,7 +1143,7 @@ void SwHTMLParser::InsertBodyOptions() LanguageType eLang = LanguageTag::convertToLanguageTypeWithFallback( aLang ); if( LANGUAGE_DONTKNOW != eLang ) { - sal_uInt16 nWhich = 0; + TypedWhichId<SvxLanguageItem> nWhich(0); switch( SvtLanguageOptions::GetScriptTypeOfLanguage( eLang ) ) { case SvtScriptType::LATIN: @@ -1357,7 +1407,7 @@ void SwHTMLParser::InsertBookmark( const OUString& rName ) bool SwHTMLParser::HasCurrentParaBookmarks( bool bIgnoreStack ) const { bool bHasMarks = false; - sal_uLong nNodeIdx = m_pPam->GetPoint()->nNode.GetIndex(); + SwNodeOffset nNodeIdx = m_pPam->GetPoint()->GetNodeIndex(); // first step: are there still bookmark in the attribute-stack? // bookmarks are added to the end of the stack - thus we only have @@ -1369,7 +1419,7 @@ bool SwHTMLParser::HasCurrentParaBookmarks( bool bIgnoreStack ) const HTMLAttr* pAttr = m_aSetAttrTab[ --i ]; if( RES_FLTR_BOOKMARK == pAttr->m_pItem->Which() ) { - if( pAttr->GetSttParaIdx() == nNodeIdx ) + if( pAttr->GetStartParagraphIdx() == nNodeIdx ) bHasMarks = true; break; } @@ -1386,7 +1436,7 @@ bool SwHTMLParser::HasCurrentParaBookmarks( bool bIgnoreStack ) const { const ::sw::mark::IMark* pBookmark = *ppMark; - const sal_uLong nBookNdIdx = pBookmark->GetMarkPos().nNode.GetIndex(); + const SwNodeOffset nBookNdIdx = pBookmark->GetMarkPos().GetNodeIndex(); if( nBookNdIdx==nNodeIdx ) { bHasMarks = true; @@ -1406,23 +1456,22 @@ void SwHTMLParser::StripTrailingPara() { bool bSetSmallFont = false; - SwContentNode* pCNd = m_pPam->GetContentNode(); - sal_uLong nNodeIdx = m_pPam->GetPoint()->nNode.GetIndex(); - if( !m_pPam->GetPoint()->nContent.GetIndex() ) + SwContentNode* pCNd = m_pPam->GetPointContentNode(); + SwNodeOffset nNodeIdx = m_pPam->GetPoint()->GetNodeIndex(); + if( !m_pPam->GetPoint()->GetContentIndex() ) { if( pCNd && pCNd->StartOfSectionIndex() + 2 < pCNd->EndOfSectionIndex() && CanRemoveNode(nNodeIdx)) { - const SwFrameFormats& rFrameFormatTable = *m_xDoc->GetSpzFrameFormats(); - for( auto pFormat : rFrameFormatTable ) + for(sw::SpzFrameFormat* pSpz: *m_xDoc->GetSpzFrameFormats()) { - SwFormatAnchor const*const pAnchor = &pFormat->GetAnchor(); - SwPosition const*const pAPos = pAnchor->GetContentAnchor(); - if (pAPos && + SwFormatAnchor const*const pAnchor = &pSpz->GetAnchor(); + SwNode const*const pAnchorNode = pAnchor->GetAnchorNode(); + if (pAnchorNode && ((RndStdIds::FLY_AT_PARA == pAnchor->GetAnchorId()) || (RndStdIds::FLY_AT_CHAR == pAnchor->GetAnchorId())) && - pAPos->nNode == nNodeIdx ) + pAnchorNode->GetIndex() == nNodeIdx ) return; // we can't delete the node } @@ -1438,7 +1487,7 @@ void SwHTMLParser::StripTrailingPara() SwTextNode *pPrvNd = m_xDoc->GetNodes()[nNodeIdx-1]->GetTextNode(); if( pPrvNd ) { - SwIndex aSrc( pCNd, 0 ); + SwContentIndex aSrc( pCNd, 0 ); pCNd->GetTextNode()->CutText( pPrvNd, aSrc, pCNd->Len() ); } } @@ -1451,10 +1500,10 @@ void SwHTMLParser::StripTrailingPara() { ::sw::mark::IMark* pMark = *ppMark; - sal_uLong nBookNdIdx = pMark->GetMarkPos().nNode.GetIndex(); + SwNodeOffset nBookNdIdx = pMark->GetMarkPos().GetNodeIndex(); if(nBookNdIdx==nNodeIdx) { - SwNodeIndex nNewNdIdx(m_pPam->GetPoint()->nNode); + SwNodeIndex nNewNdIdx(m_pPam->GetPoint()->GetNode()); SwContentNode* pNd = SwNodes::GoPrevious(&nNewNdIdx); if(!pNd) { @@ -1464,9 +1513,7 @@ void SwHTMLParser::StripTrailingPara() // #i81002# - refactoring // Do not directly manipulate member of <SwBookmark> { - SwPosition aNewPos(*pNd); - aNewPos.nContent.Assign(pNd, pNd->Len()); - const SwPaM aPaM(aNewPos); + const SwPaM aPaM(*pNd, pNd->Len()); pMarkAccess->repositionMark(*ppMark, aPaM); } } @@ -1474,11 +1521,11 @@ void SwHTMLParser::StripTrailingPara() break; } - m_pPam->GetPoint()->nContent.Assign( nullptr, 0 ); + SwNode& rDelNode = m_pPam->GetPoint()->GetNode(); + m_pPam->Move( fnMoveBackward, GoInNode ); m_pPam->SetMark(); m_pPam->DeleteMark(); - m_xDoc->GetNodes().Delete( m_pPam->GetPoint()->nNode ); - m_pPam->Move( fnMoveBackward, GoInNode ); + m_xDoc->GetNodes().Delete( rDelNode ); } else if (pCNd && pCNd->IsTextNode() && m_xTable) { @@ -1496,7 +1543,7 @@ void SwHTMLParser::StripTrailingPara() bSetSmallFont = true; SwTextNode* pTextNd = pCNd->GetTextNode(); - sal_Int32 nPos = m_pPam->GetPoint()->nContent.GetIndex(); + sal_Int32 nPos = m_pPam->GetPoint()->GetContentIndex(); while( bSetSmallFont && nPos>0 ) { --nPos; diff --git a/sw/source/filter/html/htmlnum.cxx b/sw/source/filter/html/htmlnum.cxx index 345645a240c8..8fa120a630cf 100644 --- a/sw/source/filter/html/htmlnum.cxx +++ b/sw/source/filter/html/htmlnum.cxx @@ -26,22 +26,68 @@ void SwHTMLNumRuleInfo::Set(const SwTextNode& rTextNd) const SwNumRule* pTextNdNumRule(rTextNd.GetNumRule()); if (pTextNdNumRule && pTextNdNumRule != rTextNd.GetDoc().GetOutlineNumRule()) { - pNumRule = const_cast<SwNumRule*>(pTextNdNumRule); - nDeep = static_cast<sal_uInt16>(pNumRule ? rTextNd.GetActualListLevel() + 1 : 0); - bNumbered = rTextNd.IsCountedInList(); + m_pNumRule = const_cast<SwNumRule*>(pTextNdNumRule); + m_nDeep = o3tl::narrowing<sal_uInt16>(m_pNumRule ? rTextNd.GetActualListLevel() + 1 : 0); + m_bNumbered = rTextNd.IsCountedInList(); // #i57919# - correction of refactoring done by cws swnumtree: // <bRestart> has to be set to <true>, if numbering is restarted at this // text node and the start value equals <USHRT_MAX>. // Start value <USHRT_MAX> indicates, that at this text node the numbering // is restarted with the value given at the corresponding level. - bRestart = rTextNd.IsListRestart() && !rTextNd.HasAttrListRestartValue(); + m_bRestart = rTextNd.IsListRestart() && !rTextNd.HasAttrListRestartValue(); } else { - pNumRule = nullptr; - nDeep = 0; - bNumbered = bRestart = false; + m_pNumRule = nullptr; + m_nDeep = 0; + m_bNumbered = m_bRestart = false; } } +// Restart flag is only effective when this level is not below the previous +bool SwHTMLNumRuleInfo::IsRestart(const SwHTMLNumRuleInfo& rPrev) const +{ + // calling this, when the rules are different, makes no sense + assert(rPrev.GetNumRule() == GetNumRule()); + + // An example ODF when the restart flag is set, but has no effect: + // <text:list text:style-name="L1"> + // <text:list-item> + // <text:p>l1</text:p> + // <text:list> + // <text:list-item> + // <text:p>l2</text:p> + // </text:list-item> + // <text:list-item> + // <text:p>l2</text:p> + // </text:list-item> + // </text:list> + // <text:list> + // <text:list-item> + // <text:list> + // <text:list-item> + // <text:p>l3</text:p> + // </text:list-item> + // </text:list> + // </text:list-item> + // </text:list> + // </text:list-item> + // </text:list> + // In this case, "l3" is in a separate sublist than "l2", and so the "l3" node gets the + // "list restart" property. But the document rendering would be + // 1. l1 + // 1.1. l2 + // 1.2. l2 + // 1.2.1. l3 + // and the second-level numbering will not actually restart at the "l3" node. + // + // TODO/LATER: note that restarting may happen at different levels. In the code using this + // function, the level is reset to 0 whenever a restart is detected. And also, there is no + // code to actually descend to that new level (close corresponding li/ul/ol elements). + + if (rPrev.GetDepth() < GetDepth()) + return false; // No matter if the restart flag is set, it is not effective for subitems + return m_bRestart; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlnum.hxx b/sw/source/filter/html/htmlnum.hxx index 917c0514a259..670f08229df2 100644 --- a/sw/source/filter/html/htmlnum.hxx +++ b/sw/source/filter/html/htmlnum.hxx @@ -22,8 +22,8 @@ #include <swtypes.hxx> #include <string.h> -#define HTML_NUMBER_BULLET_MARGINLEFT (MM50*2 + MM50/2) -#define HTML_NUMBER_BULLET_INDENT (-MM50) +#define HTML_NUMBER_BULLET_MARGINLEFT (o3tl::toTwips(125, o3tl::Length::mm10)) +#define HTML_NUMBER_BULLET_INDENT (-o3tl::toTwips(5, o3tl::Length::mm)) class SwTextNode; class SwNumRule; @@ -35,11 +35,11 @@ class SwNumRule; class SwHTMLNumRuleInfo { - sal_uInt16 aNumStarts[MAXLEVEL]; - SwNumRule * pNumRule; // current numbering - sal_uInt16 nDeep; // current numbering depth (1, 2, 3, ...) - bool bRestart : 1; // Export: restart numbering - bool bNumbered : 1; // Export: paragraph is numbered + sal_uInt16 m_aNumStarts[MAXLEVEL]; + SwNumRule * m_pNumRule; // current numbering + sal_uInt16 m_nDeep; // current numbering depth (1, 2, 3, ...) + bool m_bRestart; // Export: restart numbering + bool m_bNumbered; // Export: paragraph is numbered public: @@ -47,17 +47,17 @@ public: void Set( const SwTextNode& rTextNd ); SwHTMLNumRuleInfo() : - pNumRule( nullptr ), nDeep( 0 ), - bRestart( false ), bNumbered( false ) + m_pNumRule( nullptr ), m_nDeep( 0 ), + m_bRestart( false ), m_bNumbered( false ) { - memset( &aNumStarts, 0xff, sizeof( aNumStarts ) ); + memset( &m_aNumStarts, 0xff, sizeof( m_aNumStarts ) ); } SwHTMLNumRuleInfo( const SwHTMLNumRuleInfo& rInf ) : - pNumRule( rInf.pNumRule ), nDeep( rInf.nDeep ), - bRestart( rInf.bRestart ), bNumbered( rInf.bNumbered ) + m_pNumRule( rInf.m_pNumRule ), m_nDeep( rInf.m_nDeep ), + m_bRestart( rInf.m_bRestart ), m_bNumbered( rInf.m_bNumbered ) { - memcpy( &aNumStarts, &rInf.aNumStarts, sizeof( aNumStarts ) ); + memcpy( &m_aNumStarts, &rInf.m_aNumStarts, sizeof( m_aNumStarts ) ); } explicit SwHTMLNumRuleInfo( const SwTextNode& rTextNd ) { Set( rTextNd ); } @@ -65,22 +65,22 @@ public: inline void Clear(); - void SetNumRule( const SwNumRule *pRule ) { pNumRule = const_cast<SwNumRule *>(pRule); } - SwNumRule *GetNumRule() { return pNumRule; } - const SwNumRule *GetNumRule() const { return pNumRule; } + void SetNumRule( const SwNumRule *pRule ) { m_pNumRule = const_cast<SwNumRule *>(pRule); } + SwNumRule *GetNumRule() { return m_pNumRule; } + const SwNumRule *GetNumRule() const { return m_pNumRule; } - void SetDepth( sal_uInt16 nDepth ) { nDeep = nDepth; } - sal_uInt16 GetDepth() const { return nDeep; } - void IncDepth() { ++nDeep; } - void DecDepth() { if (nDeep!=0) --nDeep; } + void SetDepth( sal_uInt16 nDepth ) { m_nDeep = nDepth; } + sal_uInt16 GetDepth() const { return m_nDeep; } + void IncDepth() { ++m_nDeep; } + void DecDepth() { if (m_nDeep!=0) --m_nDeep; } inline sal_uInt8 GetLevel() const; - bool IsRestart() const { return bRestart; } + bool IsRestart(const SwHTMLNumRuleInfo& rPrev) const; - bool IsNumbered() const { return bNumbered; } + bool IsNumbered() const { return m_bNumbered; } inline void SetNodeStartValue( sal_uInt8 nLvl, sal_uInt16 nVal=USHRT_MAX ); - sal_uInt16 GetNodeStartValue( sal_uInt8 nLvl ) const { return aNumStarts[nLvl]; } + sal_uInt16 GetNodeStartValue( sal_uInt8 nLvl ) const { return m_aNumStarts[nLvl]; } }; inline SwHTMLNumRuleInfo& SwHTMLNumRuleInfo::operator=( @@ -92,32 +92,32 @@ inline SwHTMLNumRuleInfo& SwHTMLNumRuleInfo::operator=( inline void SwHTMLNumRuleInfo::Set( const SwHTMLNumRuleInfo& rInf ) { - pNumRule = rInf.pNumRule; - nDeep = rInf.nDeep; - bRestart = rInf.bRestart; - bNumbered = rInf.bNumbered; - memcpy( &aNumStarts, &rInf.aNumStarts, sizeof( aNumStarts ) ); + m_pNumRule = rInf.m_pNumRule; + m_nDeep = rInf.m_nDeep; + m_bRestart = rInf.m_bRestart; + m_bNumbered = rInf.m_bNumbered; + memcpy( &m_aNumStarts, &rInf.m_aNumStarts, sizeof( m_aNumStarts ) ); } inline void SwHTMLNumRuleInfo::Clear() { - pNumRule = nullptr; - nDeep = 0; - bRestart = bNumbered = false; - memset( &aNumStarts, 0xff, sizeof( aNumStarts ) ); + m_pNumRule = nullptr; + m_nDeep = 0; + m_bRestart = m_bNumbered = false; + memset( &m_aNumStarts, 0xff, sizeof( m_aNumStarts ) ); } inline sal_uInt8 SwHTMLNumRuleInfo::GetLevel() const { return - static_cast<sal_uInt8>( pNumRule!=nullptr && nDeep != 0 - ? ( nDeep<=MAXLEVEL ? nDeep-1 : MAXLEVEL - 1 ) + static_cast<sal_uInt8>( m_pNumRule!=nullptr && m_nDeep != 0 + ? ( m_nDeep<=MAXLEVEL ? m_nDeep-1 : MAXLEVEL - 1 ) : 0 ); } inline void SwHTMLNumRuleInfo::SetNodeStartValue( sal_uInt8 nLvl, sal_uInt16 nVal ) { - aNumStarts[nLvl] = nVal; + m_aNumStarts[nLvl] = nVal; } #endif diff --git a/sw/source/filter/html/htmlnumreader.cxx b/sw/source/filter/html/htmlnumreader.cxx index feaee46f4cb3..d9ecc21f3d3b 100644 --- a/sw/source/filter/html/htmlnumreader.cxx +++ b/sw/source/filter/html/htmlnumreader.cxx @@ -56,7 +56,7 @@ void SwHTMLParser::NewNumberBulletList( HtmlTokenId nToken ) // Create a new paragraph bool bSpace = (rInfo.GetDepth() + m_nDefListDeep) == 0; - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( bSpace ? AM_SPACE : AM_NOSPACE, false ); else if( bSpace ) AddParSpace(); @@ -165,7 +165,7 @@ void SwHTMLParser::NewNumberBulletList( HtmlTokenId nToken ) break; case HtmlOptionId::START: { - sal_uInt16 nStart = static_cast<sal_uInt16>(rOption.GetNumber()); + sal_uInt16 nStart = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); if( bNewNumFormat ) { aNumFormat.SetStart( nStart ); @@ -198,10 +198,10 @@ void SwHTMLParser::NewNumberBulletList( HtmlTokenId nToken ) } break; case HtmlOptionId::WIDTH: - nWidth = static_cast<sal_uInt16>(rOption.GetNumber()); + nWidth = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::HEIGHT: - nHeight = static_cast<sal_uInt16>(rOption.GetNumber()); + nHeight = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::ALIGN: eVertOri = rOption.GetEnum( aHTMLImgVAlignTable, eVertOri ); @@ -224,9 +224,7 @@ void SwHTMLParser::NewNumberBulletList( HtmlTokenId nToken ) Size aTwipSz( nWidth, nHeight), *pTwipSz=nullptr; if( nWidth!=USHRT_MAX && nHeight!=USHRT_MAX ) { - aTwipSz = - Application::GetDefaultDevice()->PixelToLogic( aTwipSz, - MapMode(MapUnit::MapTwip) ); + aTwipSz = o3tl::convert(aTwipSz, o3tl::Length::px, o3tl::Length::twip); pTwipSz = &aTwipSz; } @@ -280,7 +278,7 @@ void SwHTMLParser::NewNumberBulletList( HtmlTokenId nToken ) if( aPropInfo.m_bTextIndent ) { short nTextIndent = - aItemSet.Get( RES_LR_SPACE ).GetTextFirstLineOffset(); + aItemSet.Get(RES_MARGIN_FIRSTLINE).GetTextFirstLineOffset(); aNumFormat.SetFirstLineOffset( nTextIndent ); bChangeNumFormat = true; } @@ -297,7 +295,7 @@ void SwHTMLParser::NewNumberBulletList( HtmlTokenId nToken ) } aPropInfo.m_bLeftMargin = aPropInfo.m_bTextIndent = false; if( !aPropInfo.m_bRightMargin ) - aItemSet.ClearItem( RES_LR_SPACE ); + aItemSet.ClearItem(RES_MARGIN_RIGHT); // superfluous? // #i89812# - Perform change to list style before calling <DoPositioning(..)>, // because <DoPositioning(..)> may open a new context and thus may @@ -334,10 +332,10 @@ void SwHTMLParser::EndNumberBulletList( HtmlTokenId nToken ) // A new paragraph needs to be created, when // - the current one isn't empty (it contains text or paragraph-bound objects) // - the current one is numbered - bool bAppend = m_pPam->GetPoint()->nContent.GetIndex() > 0; + bool bAppend = m_pPam->GetPoint()->GetContentIndex() > 0; if( !bAppend ) { - SwTextNode* pTextNode = m_pPam->GetNode().GetTextNode(); + SwTextNode* pTextNode = m_pPam->GetPointNode().GetTextNode(); bAppend = (pTextNode && ! pTextNode->IsOutline() && pTextNode->IsCountedInList()) || @@ -395,7 +393,7 @@ void SwHTMLParser::EndNumberBulletList( HtmlTokenId nToken ) // On the last append, the NumRule item and NodeNum object were copied. // Now we need to delete them. ResetAttr deletes the NodeNum object as well - if (SwTextNode *pTextNode = m_pPam->GetNode().GetTextNode()) + if (SwTextNode *pTextNode = m_pPam->GetPointNode().GetTextNode()) pTextNode->ResetAttr(RES_PARATR_NUMRULE); rInfo.Clear(); @@ -441,7 +439,7 @@ void SwHTMLParser::NewNumberBulletListItem( HtmlTokenId nToken ) switch( rOption.GetToken() ) { case HtmlOptionId::VALUE: - nStart = static_cast<sal_uInt16>(rOption.GetNumber()); + nStart = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::ID: aId = rOption.GetString(); @@ -463,11 +461,11 @@ void SwHTMLParser::NewNumberBulletListItem( HtmlTokenId nToken ) } // create a new paragraph - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_NOSPACE, false ); m_bNoParSpace = false; // no space in <LI>! - SwTextNode* pTextNode = m_pPam->GetNode().GetTextNode(); + SwTextNode* pTextNode = m_pPam->GetPointNode().GetTextNode(); if (!pTextNode) { SAL_WARN("sw.html", "No Text-Node at PaM-Position"); @@ -528,7 +526,7 @@ void SwHTMLParser::NewNumberBulletListItem( HtmlTokenId nToken ) } if( GetNumInfo().GetNumRule() ) - GetNumInfo().GetNumRule()->SetInvalidRule( true ); + GetNumInfo().GetNumRule()->Invalidate(); // parse styles if( HasStyleOptions( aStyle, aId, aClass, &aLang, &aDir ) ) @@ -555,7 +553,7 @@ void SwHTMLParser::NewNumberBulletListItem( HtmlTokenId nToken ) void SwHTMLParser::EndNumberBulletListItem( HtmlTokenId nToken, bool bSetColl ) { // Create a new paragraph - if( nToken == HtmlTokenId::NONE && m_pPam->GetPoint()->nContent.GetIndex() ) + if( nToken == HtmlTokenId::NONE && m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_NOSPACE ); // Get context to that token and pop it from stack @@ -601,7 +599,7 @@ void SwHTMLParser::EndNumberBulletListItem( HtmlTokenId nToken, bool bSetColl ) void SwHTMLParser::SetNodeNum( sal_uInt8 nLevel ) { - SwTextNode* pTextNode = m_pPam->GetNode().GetTextNode(); + SwTextNode* pTextNode = m_pPam->GetPointNode().GetTextNode(); if (!pTextNode) { SAL_WARN("sw.html", "No Text-Node at PaM-Position"); @@ -616,7 +614,7 @@ void SwHTMLParser::SetNodeNum( sal_uInt8 nLevel ) pTextNode->SetCountedInList( false ); // Invalidate NumRule, it may have been set valid because of an EndAction - GetNumInfo().GetNumRule()->SetInvalidRule( false ); + GetNumInfo().GetNumRule()->Invalidate(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmlnumwriter.cxx b/sw/source/filter/html/htmlnumwriter.cxx index ea3c949c3801..046747754a38 100644 --- a/sw/source/filter/html/htmlnumwriter.cxx +++ b/sw/source/filter/html/htmlnumwriter.cxx @@ -37,7 +37,7 @@ void SwHTMLWriter::FillNextNumInfo() { m_pNextNumRuleInfo = nullptr; - sal_uLong nPos = m_pCurrentPam->GetPoint()->nNode.GetIndex() + 1; + SwNodeOffset nPos = m_pCurrentPam->GetPoint()->GetNodeIndex() + 1; bool bTable = false; do @@ -53,7 +53,7 @@ void SwHTMLWriter::FillNextNumInfo() // numbering level during import. if( bTable && m_pNextNumRuleInfo->GetNumRule()==GetNumInfo().GetNumRule() && - !m_pNextNumRuleInfo->IsRestart() ) + !m_pNextNumRuleInfo->IsRestart(GetNumInfo()) ) { m_pNextNumRuleInfo->SetDepth( GetNumInfo().GetDepth() ); } @@ -83,13 +83,13 @@ void SwHTMLWriter::SetNextNumInfo( std::unique_ptr<SwHTMLNumRuleInfo> pNxt ) m_pNextNumRuleInfo = std::move(pNxt); } -Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, +SwHTMLWriter& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, const SwHTMLNumRuleInfo& rInfo ) { SwHTMLNumRuleInfo& rPrevInfo = rWrt.GetNumInfo(); bool bSameRule = rPrevInfo.GetNumRule() == rInfo.GetNumRule(); if( bSameRule && rPrevInfo.GetDepth() >= rInfo.GetDepth() && - !rInfo.IsRestart() ) + !rInfo.IsRestart(rPrevInfo) ) { return rWrt; } @@ -111,8 +111,8 @@ Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, bStartValue = true; if( rInfo.GetDepth() > 1 ) { - sal_uLong nPos = - rWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() + 1; + SwNodeOffset nPos = + rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex() + 1; do { const SwNode* pNd = rWrt.m_pDoc->GetNodes()[nPos]; @@ -167,7 +167,7 @@ Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, OSL_ENSURE( rWrt.m_nLastParaToken == HtmlTokenId::NONE, "<PRE> was not closed before <OL>." ); sal_uInt16 nPrevDepth = - (bSameRule && !rInfo.IsRestart()) ? rPrevInfo.GetDepth() : 0; + (bSameRule && !rInfo.IsRestart(rPrevInfo)) ? rPrevInfo.GetDepth() : 0; for( sal_uInt16 i=nPrevDepth; i<rInfo.GetDepth(); i++ ) { @@ -175,12 +175,17 @@ Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, rWrt.m_aBulletGrfs[i].clear(); OString sOut = "<" + rWrt.GetNamespace(); + if (rWrt.mbXHTML && i != nPrevDepth) + { + // for all skipped sublevels, add a li + sOut += OOO_STRING_SVTOOLS_HTML_li "><" + rWrt.GetNamespace(); + } const SwNumFormat& rNumFormat = rInfo.GetNumRule()->Get( i ); sal_Int16 eType = rNumFormat.GetNumberingType(); if( SVX_NUM_CHAR_SPECIAL == eType ) { - // ordered list: <OL> - sOut += OString(OOO_STRING_SVTOOLS_HTML_unorderlist); + // unordered list: <UL> + sOut += OOO_STRING_SVTOOLS_HTML_unorderlist; // determine the type by the bullet character const char *pStr = nullptr; @@ -199,28 +204,25 @@ Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, if( pStr ) { - sOut += OStringLiteral(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"") + pStr + "\""; + sOut += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"") + pStr + "\""; } } else if( SVX_NUM_BITMAP == eType ) { // Unordered list: <UL> - sOut += OString(OOO_STRING_SVTOOLS_HTML_unorderlist); - rWrt.Strm().WriteOString( sOut ); - OutHTML_BulletImage( rWrt, - nullptr, - rNumFormat.GetBrush(), - rWrt.m_aBulletGrfs[i]); + sOut += OOO_STRING_SVTOOLS_HTML_unorderlist; } else { // Ordered list: <OL> - sOut += OString(OOO_STRING_SVTOOLS_HTML_orderlist); + sOut += OOO_STRING_SVTOOLS_HTML_orderlist; - // determine the type by the format - char cType = 0; - switch( eType ) + if (!rWrt.mbReqIF) // No 'type' nor 'start' attribute in ReqIF { + // determine the type by the format + char cType = 0; + switch (eType) + { case SVX_NUM_CHARS_UPPER_LETTER: case SVX_NUM_CHARS_UPPER_LETTER_N: cType = 'A'; @@ -235,33 +237,36 @@ Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, case SVX_NUM_ROMAN_LOWER: cType = 'i'; break; - } - if( cType ) - { - sOut += " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" + OStringChar(cType) + "\""; - } + } + if( cType ) + { + sOut += " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" + OStringChar(cType) + "\""; + } - sal_uInt16 nStartVal = rNumFormat.GetStart(); - if( bStartValue && 1 == nStartVal && i == rInfo.GetDepth()-1 ) - { - if ( rWrt.m_pCurrentPam->GetNode().GetTextNode()->GetNum() ) + sal_uInt16 nStartVal = rNumFormat.GetStart(); + if( bStartValue && 1 == nStartVal && i == rInfo.GetDepth()-1 ) { - nStartVal = static_cast< sal_uInt16 >( rWrt.m_pCurrentPam->GetNode() - .GetTextNode()->GetNumberVector()[i] ); + if ( rWrt.m_pCurrentPam->GetPointNode().GetTextNode()->GetNum() ) + { + nStartVal = static_cast< sal_uInt16 >( rWrt.m_pCurrentPam->GetPointNode() + .GetTextNode()->GetNumberVector()[i] ); + } + else + { + OSL_FAIL( "<OutHTML_NumberBulletListStart(..) - text node has no number." ); + } } - else + if( nStartVal != 1 ) { - OSL_FAIL( "<OutHTML_NumberBulletListStart(..) - text node has no number." ); + sOut += " " OOO_STRING_SVTOOLS_HTML_O_start "=\"" + OString::number(static_cast<sal_Int32>(nStartVal)) + "\""; } } - if( nStartVal != 1 ) - { - sOut += " " OOO_STRING_SVTOOLS_HTML_O_start "=\"" + OString::number(static_cast<sal_Int32>(nStartVal)) + "\""; - } } - if (!sOut.isEmpty() && SVX_NUM_BITMAP != eType) // second condition to avoid adding extra ul, already done before. - rWrt.Strm().WriteOString( sOut ); + rWrt.Strm().WriteOString(sOut); + + if (eType == SVX_NUM_BITMAP) + OutHTML_BulletImage(rWrt, nullptr, rNumFormat.GetBrush(), rWrt.m_aBulletGrfs[i]); if( rWrt.m_bCfgOutStyles ) OutCSS1_NumberBulletListStyleOpt( rWrt, *rInfo.GetNumRule(), static_cast<sal_uInt8>(i) ); @@ -274,20 +279,20 @@ Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, return rWrt; } -Writer& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt, +SwHTMLWriter& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt, const SwHTMLNumRuleInfo& rNextInfo ) { SwHTMLNumRuleInfo& rInfo = rWrt.GetNumInfo(); bool bSameRule = rNextInfo.GetNumRule() == rInfo.GetNumRule(); - bool bListEnd = !bSameRule || rNextInfo.GetDepth() < rInfo.GetDepth() || rNextInfo.IsRestart(); + bool bListEnd = !bSameRule || rNextInfo.GetDepth() < rInfo.GetDepth() || rNextInfo.IsRestart(rInfo); + bool bNextIsSubitem = !bListEnd && rNextInfo.GetDepth() > rInfo.GetDepth(); - if (rWrt.mbXHTML) + // XHTML </li> for the list item content, if there is an open <li>. + if (bListEnd || (!bNextIsSubitem && rNextInfo.IsNumbered())) { - if (bListEnd || (!bListEnd && rNextInfo.IsNumbered())) - { - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), - rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li, false); - } + HTMLOutFuncs::Out_AsciiTag( + rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li), + false); } if (!bListEnd) @@ -298,24 +303,31 @@ Writer& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt, OSL_ENSURE( rWrt.m_nLastParaToken == HtmlTokenId::NONE, "<PRE> was not closed before </OL>." ); sal_uInt16 nNextDepth = - (bSameRule && !rNextInfo.IsRestart()) ? rNextInfo.GetDepth() : 0; + (bSameRule && !rNextInfo.IsRestart(rInfo)) ? rNextInfo.GetDepth() : 0; // MIB 23.7.97: We must loop backwards, to get the right order of </OL>/</UL> for( sal_uInt16 i=rInfo.GetDepth(); i>nNextDepth; i-- ) { rWrt.DecIndentLevel(); // indent content of <OL> - if( rWrt.m_bLFPossible ) + if (rWrt.IsLFPossible()) rWrt.OutNewLine(); // </OL>/</UL> in a new line // a list is started or ended: sal_Int16 eType = rInfo.GetNumRule()->Get( i-1 ).GetNumberingType(); OString aTag; if( SVX_NUM_CHAR_SPECIAL == eType || SVX_NUM_BITMAP == eType) - aTag = OOO_STRING_SVTOOLS_HTML_unorderlist; + aTag = OOO_STRING_SVTOOLS_HTML_unorderlist ""_ostr; else - aTag = OOO_STRING_SVTOOLS_HTML_orderlist; - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + aTag, false ); - rWrt.m_bLFPossible = true; + aTag = OOO_STRING_SVTOOLS_HTML_orderlist ""_ostr; + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false ); + if (rWrt.mbXHTML && (i != nNextDepth + 1 || (i != 1 && rNextInfo.IsNumbered()))) + { + // for all skipped sublevels, close a li + HTMLOutFuncs::Out_AsciiTag( + rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li), + /*bOn=*/false); + } + rWrt.SetLFPossible(true); } return rWrt; diff --git a/sw/source/filter/html/htmlplug.cxx b/sw/source/filter/html/htmlplug.cxx index 65e0419f4ed9..d70634e2dddf 100644 --- a/sw/source/filter/html/htmlplug.cxx +++ b/sw/source/filter/html/htmlplug.cxx @@ -34,7 +34,7 @@ #include <svtools/htmlout.hxx> #include <svtools/htmlkywd.hxx> #include <svtools/htmltokn.h> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <IDocumentContentOperations.hxx> #include <SwAppletImpl.hxx> #include <fmtornt.hxx> @@ -79,14 +79,16 @@ #include <o3tl/safeint.hxx> #include <osl/file.hxx> #include <comphelper/propertyvalue.hxx> +#include <svtools/HtmlWriter.hxx> using namespace com::sun::star; -#define HTML_DFLT_EMBED_WIDTH ((MM50*5)/2) -#define HTML_DFLT_EMBED_HEIGHT ((MM50*5)/2) -#define HTML_DFLT_APPLET_WIDTH ((MM50*5)/2) -#define HTML_DFLT_APPLET_HEIGHT ((MM50*5)/2) +#define HTML_DFLT_EMBED_WIDTH (o3tl::toTwips(125, o3tl::Length::mm10)) +#define HTML_DFLT_EMBED_HEIGHT (o3tl::toTwips(125, o3tl::Length::mm10)) + +#define HTML_DFLT_APPLET_WIDTH (o3tl::toTwips(125, o3tl::Length::mm10)) +#define HTML_DFLT_APPLET_HEIGHT (o3tl::toTwips(125, o3tl::Length::mm10)) const HtmlFrmOpts HTML_FRMOPTS_EMBED_ALL = @@ -142,7 +144,7 @@ namespace * itself and a wanted extension. */ OUString lcl_CalculateFileName(const OUString* pOrigFileName, const Graphic& rGraphic, - const OUString& rExtension) + std::u16string_view rExtension) { OUString aFileName; @@ -170,11 +172,9 @@ void SwHTMLParser::SetFixSize( const Size& rPixSize, sal_uInt8 nPercentWidth = 0, nPercentHeight = 0; Size aTwipSz( bPercentWidth || USHRT_MAX==rPixSize.Width() ? 0 : rPixSize.Width(), bPercentHeight || USHRT_MAX==rPixSize.Height() ? 0 : rPixSize.Height() ); - if( (aTwipSz.Width() || aTwipSz.Height()) && Application::GetDefaultDevice() ) + if( aTwipSz.Width() || aTwipSz.Height() ) { - aTwipSz = - Application::GetDefaultDevice()->PixelToLogic( aTwipSz, - MapMode(MapUnit::MapTwip) ); + aTwipSz = o3tl::convert(aTwipSz, o3tl::Length::px, o3tl::Length::twip); } // process width @@ -190,7 +190,7 @@ void SwHTMLParser::SetFixSize( const Size& rPixSize, else if( bPercentWidth && rPixSize.Width() ) { nPercentWidth = static_cast<sal_uInt8>(rPixSize.Width()); - if( nPercentWidth > 100 ) + if (nPercentWidth > 100 && nPercentWidth != SwFormatFrameSize::SYNCED) nPercentWidth = 100; aTwipSz.setWidth( rTwipDfltSize.Width() ); @@ -217,7 +217,7 @@ void SwHTMLParser::SetFixSize( const Size& rPixSize, else if( bPercentHeight && rPixSize.Height() ) { nPercentHeight = static_cast<sal_uInt8>(rPixSize.Height()); - if( nPercentHeight > 100 ) + if (nPercentHeight > 100 && nPercentHeight != SwFormatFrameSize::SYNCED) nPercentHeight = 100; aTwipSz.setHeight( rTwipDfltSize.Height() ); @@ -245,35 +245,32 @@ void SwHTMLParser::SetSpace( const Size& rPixSpace, { sal_Int32 nLeftSpace = 0, nRightSpace = 0; sal_uInt16 nUpperSpace = 0, nLowerSpace = 0; - if( (rPixSpace.Width() || rPixSpace.Height()) && Application::GetDefaultDevice() ) + if( rPixSpace.Width() || rPixSpace.Height() ) { - Size aTwipSpc( rPixSpace.Width(), rPixSpace.Height() ); - aTwipSpc = - Application::GetDefaultDevice()->PixelToLogic( aTwipSpc, - MapMode(MapUnit::MapTwip) ); - nLeftSpace = nRightSpace = aTwipSpc.Width(); - nUpperSpace = nLowerSpace = static_cast<sal_uInt16>(aTwipSpc.Height()); + nLeftSpace = nRightSpace = o3tl::convert(rPixSpace.Width(), o3tl::Length::px, o3tl::Length::twip); + nUpperSpace = nLowerSpace = o3tl::convert(rPixSpace.Height(), o3tl::Length::px, o3tl::Length::twip); } // set left/right margin - const SfxPoolItem *pItem; - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_LR_SPACE, true, &pItem ) ) + // note: parser never creates SvxLeftMarginItem! must be converted + if (const SvxTextLeftMarginItem *const pLeft = rCSS1ItemSet.GetItemIfSet(RES_MARGIN_TEXTLEFT)) { - // if applicable remove the first line indent - const SvxLRSpaceItem *pLRItem = static_cast<const SvxLRSpaceItem *>(pItem); - SvxLRSpaceItem aLRItem( *pLRItem ); - aLRItem.SetTextFirstLineOffset( 0 ); if( rCSS1PropInfo.m_bLeftMargin ) { - nLeftSpace = aLRItem.GetLeft(); + // should be SvxLeftMarginItem... "cast" it + nLeftSpace = pLeft->GetTextLeft(); rCSS1PropInfo.m_bLeftMargin = false; } + rCSS1ItemSet.ClearItem(RES_MARGIN_TEXTLEFT); + } + if (const SvxRightMarginItem *const pRight = rCSS1ItemSet.GetItemIfSet(RES_MARGIN_RIGHT)) + { if( rCSS1PropInfo.m_bRightMargin ) { - nRightSpace = aLRItem.GetRight(); + nRightSpace = pRight->GetRight(); rCSS1PropInfo.m_bRightMargin = false; } - rCSS1ItemSet.ClearItem( RES_LR_SPACE ); + rCSS1ItemSet.ClearItem(RES_MARGIN_RIGHT); } if( nLeftSpace > 0 || nRightSpace > 0 ) { @@ -295,10 +292,9 @@ void SwHTMLParser::SetSpace( const Size& rPixSpace, } // set top/bottom margin - if( SfxItemState::SET==rCSS1ItemSet.GetItemState( RES_UL_SPACE, true, &pItem ) ) + if( const SvxULSpaceItem *pULItem = rCSS1ItemSet.GetItemIfSet( RES_UL_SPACE ) ) { // if applicable remove the first line indent - const SvxULSpaceItem *pULItem = static_cast<const SvxULSpaceItem *>(pItem); if( rCSS1PropInfo.m_bTopMargin ) { nUpperSpace = pULItem->GetUpper(); @@ -331,7 +327,7 @@ void SwHTMLParser::SetSpace( const Size& rPixSpace, } } -OUString SwHTMLParser::StripQueryFromPath(const OUString& rBase, const OUString& rPath) +OUString SwHTMLParser::StripQueryFromPath(std::u16string_view rBase, const OUString& rPath) { if (!comphelper::isFileUrl(rBase)) return rPath; @@ -433,9 +429,26 @@ bool SwHTMLParser::InsertEmbed() aCmdLst.Append( rOption.GetTokenString(), rOption.GetString() ); } - if (aType == "image/png" && m_aEmbeds.empty()) - // Toplevel <object> for PNG -> that's an image, not an OLE object. + static const std::set<std::u16string_view> vAllowlist = { + u"image/png", + u"image/gif", + u"image/x-MS-bmp", + u"image/jpeg", + u"image/x-wmf", + u"image/svg+xml", + u"image/tiff", + u"image/x-emf", + u"image/bmp", + u"image/tif", + u"image/wmf", + }; + + if (vAllowlist.find(aType) != vAllowlist.end() && m_aEmbeds.empty()) + { + // Toplevel <object> for an image format -> that's an image, not an OLE object. + m_aEmbeds.push(nullptr); return false; + } SfxItemSet aItemSet( m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap() ); SvxCSS1PropertyInfo aPropInfo; @@ -487,6 +500,12 @@ bool SwHTMLParser::InsertEmbed() { // Nested XHTML <object> element: points to replacement graphic. SwOLENode* pOLENode = m_aEmbeds.top(); + if (!pOLENode) + { + // <object> is mapped to an image -> ignore replacement graphic. + return true; + } + svt::EmbeddedObjectRef& rObj = pOLENode->GetOLEObj().GetObject(); Graphic aGraphic; if (GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, aURLObj) != ERRCODE_NONE) @@ -495,25 +514,27 @@ bool SwHTMLParser::InsertEmbed() rObj.SetGraphic(aGraphic, aType); // Set the size of the OLE frame to the size of the graphic. - OutputDevice* pDevice = Application::GetDefaultDevice(); - if (aSize.getHeight() == USHRT_MAX || aSize.getWidth() == USHRT_MAX) - { - Size aPixelSize = aGraphic.GetSizePixel(pDevice); - if (aSize.getWidth() == USHRT_MAX) - aSize.setWidth(aPixelSize.getWidth()); - if (aSize.getHeight() == USHRT_MAX) - aSize.setHeight(aPixelSize.getHeight()); - } - SwFrameFormat* pFormat = pOLENode->GetFlyFormat(); if (!pFormat) return true; - SwAttrSet aAttrSet(pFormat->GetAttrSet()); aAttrSet.ClearItem(RES_CNTNT); - Size aTwipSize(pDevice->PixelToLogic(aSize, MapMode(MapUnit::MapTwip))); - SwFormatFrameSize aFrameSize(SwFrameSize::Fixed, aTwipSize.Width(), aTwipSize.Height()); - aAttrSet.Put(aFrameSize); + Size aDefaultTwipSize(o3tl::convert(aGraphic.GetSizePixel(), o3tl::Length::px, o3tl::Length::twip)); + + if (aSize.Width() == USHRT_MAX && bPercentHeight) + { + // Height is relative, width is not set: keep aspect ratio. + aSize.setWidth(SwFormatFrameSize::SYNCED); + bPercentWidth = true; + } + if (aSize.Height() == USHRT_MAX && bPercentWidth) + { + // Width is relative, height is not set: keep aspect ratio. + aSize.setHeight(SwFormatFrameSize::SYNCED); + bPercentHeight = true; + } + + SetFixSize(aSize, aDefaultTwipSize, bPercentWidth, bPercentHeight, aPropInfo, aAttrSet); pOLENode->GetDoc().SetFlyFrameAttr(*pFormat, aAttrSet); return true; } @@ -531,13 +552,13 @@ bool SwHTMLParser::InsertEmbed() if ( xSet.is() ) { if( bHasURL ) - xSet->setPropertyValue("PluginURL", uno::makeAny( aURL ) ); + xSet->setPropertyValue("PluginURL", uno::Any( aURL ) ); if( bHasType ) - xSet->setPropertyValue("PluginMimeType", uno::makeAny( aType ) ); + xSet->setPropertyValue("PluginMimeType", uno::Any( aType ) ); uno::Sequence < beans::PropertyValue > aProps; aCmdLst.FillSequence( aProps ); - xSet->setPropertyValue("PluginCommands", uno::makeAny( aProps ) ); + xSet->setPropertyValue("PluginCommands", uno::Any( aProps ) ); } } @@ -549,8 +570,8 @@ bool SwHTMLParser::InsertEmbed() aCnt.SwitchPersistence(xStorage); aObjName = aCnt.CreateUniqueObjectName(); { - SvFileStream aFileStream(aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE), - StreamMode::READ); + OUString aEmbedURL = aURLObj.GetMainURL(INetURLObject::DecodeMechanism::NONE); + SvFileStream aFileStream(aEmbedURL, StreamMode::READ); uno::Reference<io::XInputStream> xInStream; SvMemoryStream aMemoryStream; @@ -559,7 +580,7 @@ bool SwHTMLParser::InsertEmbed() auto it = m_aAllowedRTFOLEMimeTypes.find(aType); if (m_aAllowedRTFOLEMimeTypes.empty() || it != m_aAllowedRTFOLEMimeTypes.end()) { - OString aMagic("{\\object"); + OString aMagic("{\\object"_ostr); OString aHeader(read_uInt8s_ToOString(aFileStream, aMagic.getLength())); aFileStream.Seek(0); if (aHeader == aMagic) @@ -574,9 +595,9 @@ bool SwHTMLParser::InsertEmbed() if (bOwnFormat) { uno::Sequence<beans::PropertyValue> aMedium = comphelper::InitPropertySequence( - { { "InputStream", uno::makeAny(xInStream) }, - { "URL", uno::makeAny(OUString("private:stream")) }, - { "DocumentBaseURL", uno::makeAny(m_sBaseURL) } }); + { { "InputStream", uno::Any(xInStream) }, + { "URL", uno::Any(OUString("private:stream")) }, + { "DocumentBaseURL", uno::Any(m_sBaseURL) } }); xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &m_sBaseURL); } else @@ -588,8 +609,13 @@ bool SwHTMLParser::InsertEmbed() } if (!xInStream.is()) - // Non-RTF case. - xInStream.set(new utl::OStreamWrapper(aFileStream)); + { + // Object data is neither OLE2 in RTF, nor an image. Then map this to an URL that + // will be set on the inner image. + m_aEmbedURL = aEmbedURL; + // Signal success, so the outer object won't fall back to the image handler. + return true; + } if (!xObj.is()) { @@ -604,15 +630,14 @@ bool SwHTMLParser::InsertEmbed() // Set media type of the native data. uno::Reference<beans::XPropertySet> xOutStreamProps(xOutStream, uno::UNO_QUERY); if (xOutStreamProps.is()) - xOutStreamProps->setPropertyValue("MediaType", uno::makeAny(aType)); + xOutStreamProps->setPropertyValue("MediaType", uno::Any(aType)); } } xObj = aCnt.GetEmbeddedObject(aObjName); } } - SfxItemSet aFrameSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( aFrameSet ); @@ -644,7 +669,7 @@ bool SwHTMLParser::InsertEmbed() // during parsing. uno::Sequence<beans::PropertyValue> aValues{ comphelper::makePropertyValue("StreamReadOnly", true) }; - uno::Sequence<uno::Any> aArguments{ uno::makeAny(aValues) }; + uno::Sequence<uno::Any> aArguments{ uno::Any(aValues) }; xObjInitialization->initialize(aArguments); } SwFrameFormat* pFlyFormat = @@ -655,13 +680,13 @@ bool SwHTMLParser::InsertEmbed() { uno::Sequence<beans::PropertyValue> aValues{ comphelper::makePropertyValue("StreamReadOnly", false) }; - uno::Sequence<uno::Any> aArguments{ uno::makeAny(aValues) }; + uno::Sequence<uno::Any> aArguments{ uno::Any(aValues) }; xObjInitialization->initialize(aArguments); } // set name at FrameFormat if( !aName.isEmpty() ) - pFlyFormat->SetName( aName ); + pFlyFormat->SetFormatName( aName ); // set the alternative text SwNoTextNode *pNoTextNd = @@ -1090,24 +1115,29 @@ void SwHTMLParser::InsertFloatingFrame() bool bHasBorder = aFrameDesc.HasFrameBorder(); Size aMargin = aFrameDesc.GetMargin(); - xSet->setPropertyValue("FrameURL", uno::makeAny( aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ) ) ); - xSet->setPropertyValue("FrameName", uno::makeAny( aName ) ); + OUString sHRef = aFrameDesc.GetURL().GetMainURL( INetURLObject::DecodeMechanism::NONE ); + + if (INetURLObject(sHRef).IsExoticProtocol()) + NotifyMacroEventRead(); + + xSet->setPropertyValue("FrameURL", uno::Any( sHRef ) ); + xSet->setPropertyValue("FrameName", uno::Any( aName ) ); if ( eScroll == ScrollingMode::Auto ) xSet->setPropertyValue("FrameIsAutoScroll", - uno::makeAny( true ) ); + uno::Any( true ) ); else xSet->setPropertyValue("FrameIsScrollingMode", - uno::makeAny( eScroll == ScrollingMode::Yes ) ); + uno::Any( eScroll == ScrollingMode::Yes ) ); xSet->setPropertyValue("FrameIsBorder", - uno::makeAny( bHasBorder ) ); + uno::Any( bHasBorder ) ); xSet->setPropertyValue("FrameMarginWidth", - uno::makeAny( sal_Int32( aMargin.Width() ) ) ); + uno::Any( sal_Int32( aMargin.Width() ) ) ); xSet->setPropertyValue("FrameMarginHeight", - uno::makeAny( sal_Int32( aMargin.Height() ) ) ); + uno::Any( sal_Int32( aMargin.Height() ) ) ); } } } @@ -1121,8 +1151,7 @@ void SwHTMLParser::InsertFloatingFrame() ParseStyleOptions( aStyle, aId, aClass, aItemSet, aPropInfo ); // fetch the ItemSet - SfxItemSet aFrameSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( aFrameSet ); @@ -1150,14 +1179,18 @@ void SwHTMLParser::InsertFloatingFrame() RegisterFlyFrame( pFlyFormat ); m_bInFloatingFrame = true; + + ++m_nFloatingFrames; } -sal_uInt16 SwHTMLWriter::GuessOLENodeFrameType( const SwNode& rNode ) +SwHTMLFrameType SwHTMLWriter::GuessOLENodeFrameType( const SwNode& rNode ) { - SwOLEObj& rObj = const_cast<SwOLENode*>(rNode.GetOLENode())->GetOLEObj(); - SwHTMLFrameType eType = HTML_FRMTYPE_OLE; + SwOLENode* pOLENode = const_cast<SwOLENode*>(rNode.GetOLENode()); + assert(pOLENode && "must exist"); + SwOLEObj& rObj = pOLENode->GetOLEObj(); + uno::Reference < embed::XClassifiedObject > xClass = rObj.GetOleRef(); SvGlobalName aClass( xClass->getClassID() ); if( aClass == SvGlobalName( SO3_PLUGIN_CLASSID ) ) @@ -1175,17 +1208,15 @@ sal_uInt16 SwHTMLWriter::GuessOLENodeFrameType( const SwNode& rNode ) } #endif - return static_cast< sal_uInt16 >(eType); + return eType; } -Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFormat, +SwHTMLWriter& OutHTML_FrameFormatOLENode( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, bool bInCntnr ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); - sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1; - SwOLENode *pOLENd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode(); + SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1; + SwOLENode *pOLENd = rWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode(); OSL_ENSURE( pOLENd, "OLE-Node expected" ); if( !pOLENd ) @@ -1209,20 +1240,19 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor HtmlFrmOpts nFrameOpts; // if possible output a line break before the "object" - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine( true ); + if (rWrt.IsLFPossible()) + rWrt.OutNewLine( true ); if( !rFrameFormat.GetName().isEmpty() ) - rHTMLWrt.OutImplicitMark( rFrameFormat.GetName(), + rWrt.OutImplicitMark( rFrameFormat.GetName(), "ole" ); uno::Any aAny; SvGlobalName aGlobName( xObj->getClassID() ); - OStringBuffer sOut; - sOut.append('<'); + OStringBuffer sOut("<"); if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) ) { // first the plug-in specifics - sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_embed); + sOut.append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_embed); OUString aStr; OUString aURL; @@ -1235,10 +1265,10 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor if( !aURL.isEmpty() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_src) - .append("=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aURL, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_src "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), aURL ); sOut.append('\"'); } @@ -1246,10 +1276,10 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor aAny = xSet->getPropertyValue("PluginMimeType"); if( (aAny >>= aType) && !aType.isEmpty() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_type) - .append("=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aType, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_type "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), aType ); sOut.append('\"'); } @@ -1257,7 +1287,7 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor css::text::WrapTextMode_THROUGH == rFrameFormat.GetSurround().GetSurround() ) { // A HIDDEN plug-in - sOut.append(' ').append(OOO_STRING_SW_HTML_O_Hidden); + sOut.append(" " OOO_STRING_SW_HTML_O_Hidden); nFrameOpts = HTML_FRMOPTS_HIDDEN_EMBED; bHiddenEmbed = true; } @@ -1271,7 +1301,7 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor { // or the applet specifics - sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet); + sOut.append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet); // CODEBASE OUString aCd; @@ -1281,10 +1311,10 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor OUString sCodeBase( URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aCd) ); if( !sCodeBase.isEmpty() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_codebase) - .append("=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), sCodeBase, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_codebase "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), sCodeBase ); sOut.append('\"'); } } @@ -1293,10 +1323,10 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor OUString aClass; aAny = xSet->getPropertyValue("AppletCode"); aAny >>= aClass; - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_code) - .append("=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aClass, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_code "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), aClass ); sOut.append('\"'); // NAME @@ -1305,10 +1335,10 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor aAny >>= aAppletName; if( !aAppletName.isEmpty() ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_name) - .append("=\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), aAppletName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_name "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), aAppletName ); sOut.append('\"'); } @@ -1316,7 +1346,7 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor aAny = xSet->getPropertyValue("AppletIsScript"); aAny >>= bScript; if( bScript ) - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_mayscript); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_mayscript); nFrameOpts = bInCntnr ? HTML_FRMOPTS_APPLET_CNTNR : HTML_FRMOPTS_APPLET; @@ -1325,26 +1355,26 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor { // or the Floating-Frame specifics - sOut.append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + sOut.append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); SfxFrameHTMLWriter::Out_FrameDescriptor( rWrt.Strm(), rWrt.GetBaseURL(), - xSet, - rHTMLWrt.m_eDestEnc, - &rHTMLWrt.m_aNonConvertableCharacters ); + xSet ); nFrameOpts = bInCntnr ? HTML_FRMOPTS_IFRAME_CNTNR : HTML_FRMOPTS_IFRAME; } - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); // ALT, WIDTH, HEIGHT, HSPACE, VSPACE, ALIGN - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed ) + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed ) nFrameOpts |= HTML_FRMOPTS_OLE_CSS1; - OString aEndTags = rHTMLWrt.OutFrameFormatOptions( rFrameFormat, pOLENd->GetTitle(), nFrameOpts ); - if( rHTMLWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed ) - rHTMLWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts ); + OString aEndTags = rWrt.OutFrameFormatOptions( rFrameFormat, pOLENd->GetTitle(), nFrameOpts ); + if( rWrt.IsHTMLMode( HTMLMODE_ABS_POS_FLY ) && !bHiddenEmbed ) + rWrt.OutCSS1_FrameFormatOptions( rFrameFormat, nFrameOpts ); if( aGlobName == SvGlobalName( SO3_APPLET_CLASSID ) ) { @@ -1368,9 +1398,9 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor { const OUString& rValue = rCommand.GetArgument(); rWrt.Strm().WriteChar( ' ' ); - HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - rWrt.Strm().WriteCharPtr( "=\"" ); - HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( '\"' ); + HTMLOutFuncs::Out_String( rWrt.Strm(), rName ); + rWrt.Strm().WriteOString( "=\"" ); + HTMLOutFuncs::Out_String( rWrt.Strm(), rValue ).WriteChar( '\"' ); } else if( SwHtmlOptType::PARAM == nType ) { @@ -1378,9 +1408,9 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor } } - rHTMLWrt.Strm().WriteChar( '>' ); + rWrt.Strm().WriteChar( '>' ); - rHTMLWrt.IncIndentLevel(); // indent the applet content + rWrt.IncIndentLevel(); // indent the applet content size_t ii = aParams.size(); while( ii > 0 ) @@ -1388,23 +1418,24 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor const SvCommand& rCommand = aCommands[ aParams[--ii] ]; const OUString& rName = rCommand.GetCommand(); const OUString& rValue = rCommand.GetArgument(); - rHTMLWrt.OutNewLine(); - OStringBuffer sBuf; - sBuf.append('<').append(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_param) - .append(' ').append(OOO_STRING_SVTOOLS_HTML_O_name) - .append("=\""); - rWrt.Strm().WriteOString( sBuf.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - sBuf.append("\" ").append(OOO_STRING_SVTOOLS_HTML_O_value) - .append("=\""); - rWrt.Strm().WriteOString( sBuf.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteCharPtr( "\">" ); + rWrt.OutNewLine(); + sOut.append( + "<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_param + " " OOO_STRING_SVTOOLS_HTML_O_name + "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), rName ); + sOut.append("\" " OOO_STRING_SVTOOLS_HTML_O_value "=\""); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rWrt.Strm(), rValue ).WriteOString( "\">" ); } - rHTMLWrt.DecIndentLevel(); // indent the applet content + rWrt.DecIndentLevel(); // indent the applet content if( aCommands.size() ) - rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet, false ); + rWrt.OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_applet), false ); } else if( aGlobName == SvGlobalName( SO3_PLUGIN_CLASSID ) ) { @@ -1425,19 +1456,19 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor { const OUString& rValue = rCommand.GetArgument(); rWrt.Strm().WriteChar( ' ' ); - HTMLOutFuncs::Out_String( rWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); - rWrt.Strm().WriteCharPtr( "=\"" ); - HTMLOutFuncs::Out_String( rWrt.Strm(), rValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ).WriteChar( '\"' ); + HTMLOutFuncs::Out_String( rWrt.Strm(), rName ); + rWrt.Strm().WriteOString( "=\"" ); + HTMLOutFuncs::Out_String( rWrt.Strm(), rValue ).WriteChar( '\"' ); } } - rHTMLWrt.Strm().WriteChar( '>' ); + rWrt.Strm().WriteChar( '>' ); } else { // and for Floating-Frames just output another </IFRAME> - rHTMLWrt.Strm().WriteChar( '>' ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe, false ); + rWrt.Strm().WriteChar( '>' ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_iframe), false ); } if( !aEndTags.isEmpty() ) @@ -1446,32 +1477,141 @@ Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFrameFor return rWrt; } -Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrameFormat, - bool bInCntnr ) +static void OutHTMLGraphic(SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, SwOLENode* pOLENd, + const Graphic& rGraphic, bool bObjectOpened, bool bInCntnr) +{ + OUString aGraphicURL; + OUString aMimeType; + if (!rWrt.mbEmbedImages) + { + const OUString* pTempFileName = rWrt.GetOrigFileName(); + if (pTempFileName) + aGraphicURL = *pTempFileName; + + OUString aFilterName(u"JPG"_ustr); + XOutFlags nFlags = XOutFlags::UseGifIfPossible | XOutFlags::UseNativeIfPossible; + + if (bObjectOpened) + { + aFilterName = u"PNG"_ustr; + nFlags = XOutFlags::NONE; + aMimeType = u"image/png"_ustr; + + if (rGraphic.GetType() == GraphicType::NONE) + { + // The OLE Object has no replacement image, write a stub. + aGraphicURL = lcl_CalculateFileName(rWrt.GetOrigFileName(), rGraphic, u"png"); + osl::File aFile(aGraphicURL); + aFile.open(osl_File_OpenFlag_Create); + aFile.close(); + } + } + + ErrCode nErr = XOutBitmap::WriteGraphic(rGraphic, aGraphicURL, aFilterName, nFlags); + if (nErr) // error, don't write anything + { + rWrt.m_nWarn = WARN_SWG_POOR_LOAD; + if (bObjectOpened) // Still at least close the tag. + rWrt.Strm().WriteOString( + Concat2View("</" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">")); + return; + } + aGraphicURL = URIHelper::SmartRel2Abs(INetURLObject(rWrt.GetBaseURL()), aGraphicURL, + URIHelper::GetMaybeFileHdl()); + } + HtmlFrmOpts nFlags = bInCntnr ? HtmlFrmOpts::GenImgAllMask : HtmlFrmOpts::GenImgMask; + if (bObjectOpened) + nFlags |= HtmlFrmOpts::Replacement; + HtmlWriter aHtml(rWrt.Strm(), rWrt.maNamespace); + OutHTML_ImageStart(aHtml, rWrt, rFrameFormat, aGraphicURL, rGraphic, pOLENd->GetTitle(), + pOLENd->GetTwipSize(), nFlags, "ole", nullptr, aMimeType); + OutHTML_ImageEnd(aHtml, rWrt); +} + +static void OutHTMLStartObject(SwHTMLWriter& rWrt, const OUString& rFileName, const OUString& rFileType) +{ + OUString aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), rFileName); + + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); + rWrt.Strm().WriteOString( + Concat2View("<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object)); + rWrt.Strm().WriteOString(Concat2View(" data=\"" + aFileName.toUtf8() + "\"")); + if (!rFileType.isEmpty()) + rWrt.Strm().WriteOString(Concat2View(" type=\"" + rFileType.toUtf8() + "\"")); + rWrt.Strm().WriteOString(">"); + rWrt.SetLFPossible(true); +} + +static void OutHTMLEndObject(SwHTMLWriter& rWrt) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); + rWrt.Strm().WriteOString( + Concat2View("</" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object ">")); +} + +static bool TrySaveFormulaAsPDF(SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, + SwOLENode* pOLENd, bool bWriteReplacementGraphic, bool bInCntnr) +{ + if (!rWrt.mbReqIF) + return false; + if (!rWrt.m_bExportFormulasAsPDF) + return false; + + auto xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject( + *rWrt.m_pDoc, const_cast<SwFrameFormat*>(&rFrameFormat)); + uno::Reference<frame::XStorable> xStorable(xTextContent->getEmbeddedObject(), uno::UNO_QUERY); + uno::Reference<lang::XServiceInfo> xServiceInfo(xStorable, uno::UNO_QUERY); + if (!xServiceInfo) + return false; + if (!xServiceInfo->supportsService(u"com.sun.star.formula.FormulaProperties"_ustr)) + return false; + + Graphic aGraphic(xTextContent->getReplacementGraphic()); + OUString aFileName = lcl_CalculateFileName(rWrt.GetOrigFileName(), aGraphic, u"pdf"); + + utl::MediaDescriptor aDescr; + aDescr[u"FilterName"_ustr] <<= u"math_pdf_Export"_ustr; + // Properties from starmath/inc/unomodel.hxx + aDescr[u"FilterData"_ustr] <<= comphelper::InitPropertySequence({ + { u"TitleRow"_ustr, css::uno::Any(false) }, + { u"FormulaText"_ustr, css::uno::Any(false) }, + { u"Border"_ustr, css::uno::Any(false) }, + { u"PrintFormat"_ustr, css::uno::Any(sal_Int32(1)) }, // PRINT_SIZE_SCALED + }); + xStorable->storeToURL(aFileName, aDescr.getAsConstPropertyValueList()); + + OutHTMLStartObject(rWrt, aFileName, u"application/pdf"_ustr); + + if (bWriteReplacementGraphic) + OutHTMLGraphic(rWrt, rFrameFormat, pOLENd, aGraphic, true, bInCntnr); + + OutHTMLEndObject(rWrt); + return true; +} + +SwHTMLWriter& OutHTML_FrameFormatOLENodeGrf( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, + bool bInCntnr, bool bWriteReplacementGraphic ) +{ const SwFormatContent& rFlyContent = rFrameFormat.GetContent(); - sal_uLong nStt = rFlyContent.GetContentIdx()->GetIndex()+1; - SwOLENode *pOLENd = rHTMLWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode(); + SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex()+1; + SwOLENode *pOLENd = rWrt.m_pDoc->GetNodes()[ nStt ]->GetOLENode(); OSL_ENSURE( pOLENd, "OLE-Node expected" ); if( !pOLENd ) return rWrt; - if (rHTMLWrt.mbSkipImages) + if (rWrt.mbSkipImages) { // If we skip images, embedded objects would be completely lost. // Instead, try to use the HTML export of the embedded object. - uno::Reference<text::XTextContent> xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(*rHTMLWrt.m_pDoc, const_cast<SwFrameFormat*>(&rFrameFormat)); - uno::Reference<document::XEmbeddedObjectSupplier2> xEmbeddedObjectSupplier(xTextContent, uno::UNO_QUERY); - uno::Reference<frame::XStorable> xStorable(xEmbeddedObjectSupplier->getEmbeddedObject(), uno::UNO_QUERY); + auto xTextContent = SwXTextEmbeddedObject::CreateXTextEmbeddedObject(*rWrt.m_pDoc, const_cast<SwFrameFormat*>(&rFrameFormat)); + uno::Reference<frame::XStorable> xStorable(xTextContent->getEmbeddedObject(), uno::UNO_QUERY); SAL_WARN_IF(!xStorable.is(), "sw.html", "OutHTML_FrameFormatOLENodeGrf: no embedded object"); // Figure out what is the filter name of the embedded object. - uno::Reference<lang::XServiceInfo> xServiceInfo(xStorable, uno::UNO_QUERY); OUString aFilter; - if (xServiceInfo.is()) + if (uno::Reference<lang::XServiceInfo> xServiceInfo{ xStorable, uno::UNO_QUERY }) { if (xServiceInfo->supportsService("com.sun.star.sheet.SpreadsheetDocument")) aFilter = "HTML (StarCalc)"; @@ -1479,7 +1619,7 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame aFilter = "HTML (StarWriter)"; } - if (xStorable.is() && !aFilter.isEmpty()) + if (!aFilter.isEmpty()) { try { @@ -1494,9 +1634,9 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame SAL_WARN_IF(aStream.GetSize()>=o3tl::make_unsigned(SAL_MAX_INT32), "sw.html", "Stream can't fit in OString"); OString aData(static_cast<const char*>(aStream.GetData()), static_cast<sal_Int32>(aStream.GetSize())); // Wrap output in a <span> tag to avoid 'HTML parser error: Unexpected end tag: p' - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span)); rWrt.Strm().WriteOString(aData); - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false); } catch ( uno::Exception& ) { @@ -1506,6 +1646,9 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame return rWrt; } + if (TrySaveFormulaAsPDF(rWrt, rFrameFormat, pOLENd, bWriteReplacementGraphic, bInCntnr)) + return rWrt; + if ( !pOLENd->GetGraphic() ) { SAL_WARN("sw.html", "Unexpected missing OLE fallback graphic"); @@ -1514,21 +1657,21 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame Graphic aGraphic( *pOLENd->GetGraphic() ); - SwDocShell* pDocSh = rHTMLWrt.m_pDoc->GetDocShell(); + SwDocShell* pDocSh = rWrt.m_pDoc->GetDocShell(); bool bObjectOpened = false; OUString aRTFType = "text/rtf"; - if (!rHTMLWrt.m_aRTFOLEMimeType.isEmpty()) + if (!rWrt.m_aRTFOLEMimeType.isEmpty()) { - aRTFType = rHTMLWrt.m_aRTFOLEMimeType; + aRTFType = rWrt.m_aRTFOLEMimeType; } - if (rHTMLWrt.mbXHTML && pDocSh) + if (rWrt.mbXHTML && pDocSh) { // Map native data to an outer <object> element. // Calculate the file name, which is meant to be the same as the // replacement image, just with a .ole extension. - OUString aFileName = lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, "ole"); + OUString aFileName = lcl_CalculateFileName(rWrt.GetOrigFileName(), aGraphic, u"ole"); // Write the data. SwOLEObj& rOLEObj = pOLENd->GetOLEObj(); @@ -1549,7 +1692,7 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame if (xStream.is()) { std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xStream)); - if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream, *pOLENd)) + if (SwReqIfReader::WrapOleInRtf(*pStream, aOutStream, *pOLENd, rFrameFormat)) { // Data always wrapped in RTF. aFileType = aRTFType; @@ -1564,11 +1707,11 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame // export it. pOLENd->GetTwipSize(); SvMemoryStream aMemory; - tools::SvRef<SotStorage> pStorage = new SotStorage(aMemory); + rtl::Reference<SotStorage> pStorage = new SotStorage(aMemory); aOLEExp.ExportOLEObject(rOLEObj.GetObject(), *pStorage); pStorage->Commit(); aMemory.Seek(0); - if (SwReqIfReader::WrapOleInRtf(aMemory, aOutStream, *pOLENd)) + if (SwReqIfReader::WrapOleInRtf(aMemory, aOutStream, *pOLENd, rFrameFormat)) { // Data always wrapped in RTF. aFileType = aRTFType; @@ -1603,72 +1746,18 @@ Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFrame aFileType = aRTFType; } } - aFileName = URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(), aFileName); // Refer to this data. - if (rHTMLWrt.m_bLFPossible) - rHTMLWrt.OutNewLine(); - rWrt.Strm().WriteOString("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object); - rWrt.Strm().WriteOString(" data=\"" + aFileName.toUtf8() + "\""); - if (!aFileType.isEmpty()) - rWrt.Strm().WriteOString(" type=\"" + aFileType.toUtf8() + "\""); - rWrt.Strm().WriteOString(">"); + OutHTMLStartObject(rWrt, aFileName, aFileType); bObjectOpened = true; - rHTMLWrt.m_bLFPossible = true; } - OUString aGraphicURL; - OUString aMimeType; - if(!rHTMLWrt.mbEmbedImages) - { - const OUString* pTempFileName = rHTMLWrt.GetOrigFileName(); - if(pTempFileName) - aGraphicURL = *pTempFileName; - - OUString aFilterName("JPG"); - XOutFlags nFlags = XOutFlags::UseGifIfPossible | XOutFlags::UseNativeIfPossible; - - if (bObjectOpened) - { - aFilterName = "PNG"; - nFlags = XOutFlags::NONE; - aMimeType = "image/png"; - - if (aGraphic.GetType() == GraphicType::NONE) - { - // The OLE Object has no replacement image, write a stub. - aGraphicURL = lcl_CalculateFileName(rHTMLWrt.GetOrigFileName(), aGraphic, "png"); - osl::File aFile(aGraphicURL); - aFile.open(osl_File_OpenFlag_Create); - aFile.close(); - } - } - - ErrCode nErr = XOutBitmap::WriteGraphic( aGraphic, aGraphicURL, - aFilterName, - nFlags ); - if( nErr ) // error, don't write anything - { - rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD; - return rWrt; - } - aGraphicURL = URIHelper::SmartRel2Abs( - INetURLObject(rWrt.GetBaseURL()), aGraphicURL, - URIHelper::GetMaybeFileHdl() ); - - } - HtmlFrmOpts nFlags = bInCntnr ? HtmlFrmOpts::GenImgAllMask - : HtmlFrmOpts::GenImgMask; - if (bObjectOpened) - nFlags |= HtmlFrmOpts::Replacement; - OutHTML_Image( rWrt, rFrameFormat, aGraphicURL, aGraphic, - pOLENd->GetTitle(), pOLENd->GetTwipSize(), - nFlags, "ole", nullptr, aMimeType ); + if (!bObjectOpened || bWriteReplacementGraphic) + OutHTMLGraphic(rWrt, rFrameFormat, pOLENd, aGraphic, bObjectOpened, bInCntnr); if (bObjectOpened) // Close native data. - rWrt.Strm().WriteOString("</" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_object - ">"); + OutHTMLEndObject(rWrt); return rWrt; } diff --git a/sw/source/filter/html/htmlreqifreader.cxx b/sw/source/filter/html/htmlreqifreader.cxx index d656f51bc0cb..d784312b6fd2 100644 --- a/sw/source/filter/html/htmlreqifreader.cxx +++ b/sw/source/filter/html/htmlreqifreader.cxx @@ -21,6 +21,13 @@ #include <vcl/cvtgrf.hxx> #include <ndole.hxx> #include <sal/log.hxx> +#include <vcl/FilterConfigItem.hxx> +#include <vcl/wmf.hxx> +#include <comphelper/propertyvalue.hxx> +#include <fmtfsize.hxx> +#include <frmfmt.hxx> + +using namespace com::sun::star; namespace { @@ -65,11 +72,11 @@ bool ReqIfRtfReader::WriteObjectData(SvStream& rOLE) } /// Looks up what OLE1 calls the ClassName, see [MS-OLEDS] 2.3.8 CompObjStream. -OString ExtractOLEClassName(const tools::SvRef<SotStorage>& xStorage) +OString ExtractOLEClassName(const rtl::Reference<SotStorage>& xStorage) { OString aRet; - tools::SvRef<SotStorageStream> pCompObj = xStorage->OpenSotStream("\1CompObj"); + rtl::Reference<SotStorageStream> pCompObj = xStorage->OpenSotStream("\1CompObj"); if (!pCompObj) return aRet; @@ -99,8 +106,8 @@ bool ParseOLE2Presentation(SvStream& rOle2, sal_uInt32& nWidth, sal_uInt32& nHei { // See [MS-OLEDS] 2.3.4, OLEPresentationStream rOle2.Seek(0); - tools::SvRef<SotStorage> pStorage = new SotStorage(rOle2); - tools::SvRef<SotStorageStream> xOle2Presentation + rtl::Reference<SotStorage> pStorage = new SotStorage(rOle2); + rtl::Reference<SotStorageStream> xOle2Presentation = pStorage->OpenSotStream("\002OlePres000", StreamMode::STD_READ); // Read AnsiClipboardFormat. @@ -137,6 +144,15 @@ bool ParseOLE2Presentation(SvStream& rOle2, sal_uInt32& nWidth, sal_uInt32& nHei // Read Data. if (nSize > xOle2Presentation->remainingSize()) return false; + + if (nSize <= 64) + { + SAL_WARN("sw.html", + "ParseOLE2Presentation: ignoring potentially broken small preview: size is " + << nSize); + return false; + } + std::vector<char> aBuffer(nSize); xOle2Presentation->ReadBytes(aBuffer.data(), aBuffer.size()); rPresentationData.WriteBytes(aBuffer.data(), aBuffer.size()); @@ -148,10 +164,10 @@ bool ParseOLE2Presentation(SvStream& rOle2, sal_uInt32& nWidth, sal_uInt32& nHei * Inserts an OLE1 header before an OLE2 storage, assuming that the storage has an Ole10Native * stream. */ -OString InsertOLE1HeaderFromOle10NativeStream(const tools::SvRef<SotStorage>& xStorage, +OString InsertOLE1HeaderFromOle10NativeStream(const rtl::Reference<SotStorage>& xStorage, SwOLENode& rOLENode, SvStream& rOle1) { - tools::SvRef<SotStorageStream> xOle1Stream + rtl::Reference<SotStorageStream> xOle1Stream = xStorage->OpenSotStream("\1Ole10Native", StreamMode::STD_READ); sal_uInt32 nOle1Size = 0; xOle1Stream->ReadUInt32(nOle1Size); @@ -159,7 +175,7 @@ OString InsertOLE1HeaderFromOle10NativeStream(const tools::SvRef<SotStorage>& xS OString aClassName; if (xStorage->GetClassName() == SvGlobalName(0x0003000A, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 0x46)) { - aClassName = "PBrush"; + aClassName = "PBrush"_ostr; } else { @@ -169,7 +185,7 @@ OString InsertOLE1HeaderFromOle10NativeStream(const tools::SvRef<SotStorage>& xS SAL_WARN("sw.html", "InsertOLE1HeaderFromOle10NativeStream: unexpected class id: " << xStorage->GetClassName().GetHexName()); } - aClassName = "Package"; + aClassName = "Package"_ostr; } // Write ObjectHeader, see [MS-OLEDS] 2.2.4. @@ -224,7 +240,7 @@ OString InsertOLE1HeaderFromOle10NativeStream(const tools::SvRef<SotStorage>& xS // FormatID: constant means the ClassName field is present. rOle1.WriteUInt32(0x00000005); // ClassName: null terminated pascal string. - OString aPresentationClassName("METAFILEPICT"); + OString aPresentationClassName("METAFILEPICT"_ostr); rOle1.WriteUInt32(aPresentationClassName.getLength() + 1); rOle1.WriteOString(aPresentationClassName); rOle1.WriteChar(0); @@ -255,9 +271,9 @@ OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1, sal_uInt32& nWidth, s sal_uInt64 nPresentationData) { rOle2.Seek(0); - tools::SvRef<SotStorage> xStorage(new SotStorage(rOle2)); + rtl::Reference<SotStorage> xStorage(new SotStorage(rOle2)); if (xStorage->GetError() != ERRCODE_NONE) - return OString(); + return {}; if (xStorage->IsStream("\1Ole10Native")) { @@ -303,7 +319,7 @@ OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1, sal_uInt32& nWidth, s // FormatID: constant means the ClassName field is present. rOle1.WriteUInt32(0x00000005); // ClassName: null terminated pascal string. - OString aPresentationClassName("METAFILEPICT"); + OString aPresentationClassName("METAFILEPICT"_ostr); rOle1.WriteUInt32(aPresentationClassName.getLength() + 1); rOle1.WriteOString(aPresentationClassName); rOle1.WriteChar(0); @@ -325,8 +341,8 @@ OString InsertOLE1Header(SvStream& rOle2, SvStream& rOle1, sal_uInt32& nWidth, s rOle1.WriteUInt32(nWidth); // Height. rOle1.WriteUInt32(nHeight * -1); - // PresentationDataSize - rOle1.WriteUInt32(8 + nPresentationData); + // PresentationDataSize: size of (reserved fields + pBytes). + rOle1.WriteUInt32(8 + nBytes); // Reserved1-4. rOle1.WriteUInt16(0x0008); rOle1.WriteUInt16(0x31b1); @@ -342,31 +358,31 @@ void WrapOleGraphicInRtf(SvStream& rRtf, sal_uInt32 nWidth, sal_uInt32 nHeight, const sal_uInt8* pPresentationData, sal_uInt64 nPresentationData) { // Start result. - rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_RESULT); + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_RESULT); // Start pict. - rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_PICT); + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_PICT); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_WMETAFILE "8"); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICW); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_WMETAFILE "8"); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_PICW); rRtf.WriteOString(OString::number(nWidth)); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICH); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_PICH); rRtf.WriteOString(OString::number(nHeight)); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICWGOAL); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_PICWGOAL); rRtf.WriteOString(OString::number(nWidth)); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICHGOAL); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_PICHGOAL); rRtf.WriteOString(OString::number(nHeight)); if (pPresentationData) { - rRtf.WriteCharPtr(SAL_NEWLINE_STRING); + rRtf.WriteOString(SAL_NEWLINE_STRING); msfilter::rtfutil::WriteHex(pPresentationData, nPresentationData, &rRtf); } // End pict. - rRtf.WriteCharPtr("}"); + rRtf.WriteOString("}"); // End result. - rRtf.WriteCharPtr("}"); + rRtf.WriteOString("}"); } } @@ -391,7 +407,7 @@ bool ExtractOleFromRtf(SvStream& rRtf, SvStream& rOle, bool& bOwnFormat) if (!xReader->WriteObjectData(rOle)) return false; - tools::SvRef<SotStorage> pStorage = new SotStorage(rOle); + rtl::Reference<SotStorage> pStorage = new SotStorage(rOle); OUString aFilterName = SvxMSDffManager::GetFilterNameFromClassID(pStorage->GetClassName()); bOwnFormat = !aFilterName.isEmpty(); if (!bOwnFormat) @@ -413,7 +429,8 @@ bool ExtractOleFromRtf(SvStream& rRtf, SvStream& rOle, bool& bOwnFormat) return true; } -bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode) +bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode, + const SwFrameFormat& rFormat) { sal_uInt64 nPos = rOle2.Tell(); comphelper::ScopeGuard g([&rOle2, nPos] { rOle2.Seek(nPos); }); @@ -422,7 +439,7 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode) SvMemoryStream aOLE1; // Prepare presentation data early, so it's available to both OLE1 and RTF. - Size aSize(rOLENode.GetTwipSize()); + Size aSize = rFormat.GetFrameSize().GetSize(); sal_uInt32 nWidth = aSize.getWidth(); sal_uInt32 nHeight = aSize.getHeight(); const Graphic* pGraphic = rOLENode.GetGraphic(); @@ -431,8 +448,10 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode) SvMemoryStream aGraphicStream; if (pGraphic) { - if (GraphicConverter::Export(aGraphicStream, *pGraphic, ConvertDataFormat::WMF) - == ERRCODE_NONE) + uno::Sequence<beans::PropertyValue> aFilterData + = { comphelper::makePropertyValue("EmbedEMF", false) }; + FilterConfigItem aConfigItem(&aFilterData); + if (ConvertGraphicToWMF(*pGraphic, aGraphicStream, &aConfigItem)) { pPresentationData = static_cast<const sal_uInt8*>(aGraphicStream.GetData()); nPresentationData = aGraphicStream.TellEnd(); @@ -443,28 +462,28 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode) pPresentationData, nPresentationData); // Start object. - rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_OBJECT); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_OBJEMB); + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_OBJECT); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_OBJEMB); // Start objclass. - rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJCLASS " "); + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJCLASS " "); rRtf.WriteOString(aClassName); // End objclass. - rRtf.WriteCharPtr("}"); + rRtf.WriteOString("}"); // Object size. - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_OBJW); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_OBJW); rRtf.WriteOString(OString::number(nWidth)); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_OBJH); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_OBJH); rRtf.WriteOString(OString::number(nHeight)); // Start objdata. - rRtf.WriteCharPtr( + rRtf.WriteOString( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA SAL_NEWLINE_STRING); msfilter::rtfutil::WriteHex(static_cast<const sal_uInt8*>(aOLE1.GetData()), aOLE1.GetSize(), &rRtf); // End objdata. - rRtf.WriteCharPtr("}"); + rRtf.WriteOString("}"); if (pPresentationData) { @@ -472,72 +491,160 @@ bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode) } // End object. - rRtf.WriteCharPtr("}"); + rRtf.WriteOString("}"); return true; } -bool WrapGraphicInRtf(const Graphic& rGraphic, const Size& rLogicSize, SvStream& rRtf) +bool WrapGraphicInRtf(const Graphic& rGraphic, const SwFrameFormat& rFormat, SvStream& rRtf) { - rRtf.WriteCharPtr("{" OOO_STRING_SVTOOLS_RTF_PICT); - - GfxLink aLink = rGraphic.GetGfxLink(); - const sal_uInt8* pGraphicAry = aLink.GetData(); - sal_uInt64 nSize = aLink.GetDataSize(); - OString aBlipType; - bool bIsWMF = false; - switch (aLink.GetType()) + // Start object. + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_OBJECT); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_OBJEMB); + + // Object size: as used in the document model (not pixel size) + Size aSize = rFormat.GetFrameSize().GetSize(); + sal_uInt32 nWidth = aSize.getWidth(); + sal_uInt32 nHeight = aSize.getHeight(); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_OBJW); + rRtf.WriteOString(OString::number(nWidth)); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_OBJH); + rRtf.WriteOString(OString::number(nHeight)); + rRtf.WriteOString(SAL_NEWLINE_STRING); + + // Start objclass. + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJCLASS " "); + OString aClassName("PBrush"_ostr); + rRtf.WriteOString(aClassName); + // End objclass. + rRtf.WriteOString("}"); + rRtf.WriteOString(SAL_NEWLINE_STRING); + + // Start objdata. + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA " "); + + SvMemoryStream aOle1; + // Write ObjectHeader, see [MS-OLEDS] 2.2.4. + // OLEVersion. + aOle1.WriteUInt32(0x00000501); + + // FormatID is EmbeddedObject. + aOle1.WriteUInt32(0x00000002); + + // ClassName + aOle1.WriteUInt32(aClassName.getLength() + 1); + aOle1.WriteOString(aClassName); + // Null terminated pascal string. + aOle1.WriteChar(0); + + // TopicName. + aOle1.WriteUInt32(0); + + // ItemName. + aOle1.WriteUInt32(0); + + // NativeDataSize + SvMemoryStream aNativeData; + + // Set white background for the semi-transparent pixels. + BitmapEx aBitmapEx = rGraphic.GetBitmapEx(); + Bitmap aBitmap = aBitmapEx.GetBitmap(/*aTransparentReplaceColor=*/COL_WHITE); + + if (aBitmap.getPixelFormat() != vcl::PixelFormat::N24_BPP) { - case GfxLinkType::NativeBmp: - aBlipType = OOO_STRING_SVTOOLS_RTF_WBITMAP; - break; - case GfxLinkType::NativeJpg: - aBlipType = OOO_STRING_SVTOOLS_RTF_JPEGBLIP; - break; - case GfxLinkType::NativePng: - aBlipType = OOO_STRING_SVTOOLS_RTF_PNGBLIP; - break; - case GfxLinkType::NativeWmf: - if (aLink.IsEMF()) - aBlipType = OOO_STRING_SVTOOLS_RTF_EMFBLIP; - else - { - aBlipType = OOO_STRING_SVTOOLS_RTF_WMETAFILE; - bIsWMF = true; - } - break; - default: - break; + // More exotic pixel formats cause trouble for ms paint. + aBitmap.Convert(BmpConversion::N24Bit); } - if (aBlipType.isEmpty()) - return false; + if (GraphicConverter::Export(aNativeData, BitmapEx(aBitmap), ConvertDataFormat::BMP) + != ERRCODE_NONE) + { + SAL_WARN("sw.html", "WrapGraphicInRtf: bmp conversion failed"); + } + aOle1.WriteUInt32(aNativeData.TellEnd()); - rRtf.WriteOString(aBlipType); + // Write the actual native data. + aNativeData.Seek(0); + aOle1.WriteStream(aNativeData); + + // Prepare presentation data. + const sal_uInt8* pPresentationData = nullptr; + sal_uInt64 nPresentationData = 0; + SvMemoryStream aGraphicStream; + uno::Sequence<beans::PropertyValue> aFilterData + = { comphelper::makePropertyValue("EmbedEMF", false) }; + FilterConfigItem aConfigItem(&aFilterData); + if (ConvertGraphicToWMF(rGraphic, aGraphicStream, &aConfigItem)) + { + pPresentationData = static_cast<const sal_uInt8*>(aGraphicStream.GetData()); + nPresentationData = aGraphicStream.TellEnd(); + msfilter::rtfutil::StripMetafileHeader(pPresentationData, nPresentationData); + } + + // Write Presentation. + // OLEVersion. + aOle1.WriteUInt32(0x00000501); + // FormatID: constant means the ClassName field is present. + aOle1.WriteUInt32(0x00000005); + // ClassName: null terminated pascal string. + OString aPresentationClassName("METAFILEPICT"_ostr); + aOle1.WriteUInt32(aPresentationClassName.getLength() + 1); + aOle1.WriteOString(aPresentationClassName); + aOle1.WriteChar(0); + const sal_uInt8* pBytes = nullptr; + sal_uInt64 nBytes = 0; + // Take presentation data for OLE1 from RTF. + pBytes = pPresentationData; + nBytes = nPresentationData; + // Width. + aOle1.WriteUInt32(nWidth); + // Height. + aOle1.WriteUInt32(nHeight * -1); + // PresentationDataSize: size of (reserved fields + pBytes). + aOle1.WriteUInt32(8 + nBytes); + // Reserved1-4. + aOle1.WriteUInt16(0x0008); + aOle1.WriteUInt16(0x31b1); + aOle1.WriteUInt16(0x1dd9); + aOle1.WriteUInt16(0x0000); + aOle1.WriteBytes(pBytes, nBytes); + + // End objdata. + msfilter::rtfutil::WriteHex(static_cast<const sal_uInt8*>(aOle1.GetData()), aOle1.GetSize(), + &rRtf); + rRtf.WriteOString("}"); + rRtf.WriteOString(SAL_NEWLINE_STRING); + + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_RESULT); + rRtf.WriteOString("{" OOO_STRING_SVTOOLS_RTF_PICT); Size aMapped(rGraphic.GetPrefSize()); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICW); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_PICW); rRtf.WriteOString(OString::number(aMapped.Width())); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICH); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_PICH); rRtf.WriteOString(OString::number(aMapped.Height())); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICWGOAL); - rRtf.WriteOString(OString::number(rLogicSize.Width())); - rRtf.WriteCharPtr(OOO_STRING_SVTOOLS_RTF_PICHGOAL); - rRtf.WriteOString(OString::number(rLogicSize.Height())); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_PICWGOAL); + rRtf.WriteOString(OString::number(nWidth)); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_PICHGOAL); + rRtf.WriteOString(OString::number(nHeight)); + rRtf.WriteOString(OOO_STRING_SVTOOLS_RTF_WMETAFILE "8"); + rRtf.WriteOString(SAL_NEWLINE_STRING); - if (bIsWMF) + if (pPresentationData) { - rRtf.WriteOString(OString::number(8)); - msfilter::rtfutil::StripMetafileHeader(pGraphicAry, nSize); + msfilter::rtfutil::WriteHex(pPresentationData, nPresentationData, &rRtf); + rRtf.WriteOString(SAL_NEWLINE_STRING); } - rRtf.WriteOString(SAL_NEWLINE_STRING); - - msfilter::rtfutil::WriteHex(pGraphicAry, nSize, &rRtf); - rRtf.WriteOString(SAL_NEWLINE_STRING); // End pict. - rRtf.WriteCharPtr("}"); + rRtf.WriteOString("}"); + + // End result. + rRtf.WriteOString("}"); + + // End object. + rRtf.WriteOString("}"); return true; } } diff --git a/sw/source/filter/html/htmlreqifreader.hxx b/sw/source/filter/html/htmlreqifreader.hxx index 3d0816739d6a..84169bb7c087 100644 --- a/sw/source/filter/html/htmlreqifreader.hxx +++ b/sw/source/filter/html/htmlreqifreader.hxx @@ -13,6 +13,7 @@ class Graphic; class Size; class SvStream; class SwOLENode; +class SwFrameFormat; namespace SwReqIfReader { @@ -24,14 +25,13 @@ namespace SwReqIfReader bool ExtractOleFromRtf(SvStream& rRtf, SvStream& rOle, bool& bOwnFormat); /// Wraps an OLE2 container binary in an RTF fragment. -bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode); +bool WrapOleInRtf(SvStream& rOle2, SvStream& rRtf, SwOLENode& rOLENode, + const SwFrameFormat& rFormat); /** * Wraps an image in an RTF fragment. - * - * @param rLogicSize the size used in the document model (not pixel size) */ -bool WrapGraphicInRtf(const Graphic& rGraphic, const Size& rLogicSize, SvStream& rRtf); +bool WrapGraphicInRtf(const Graphic& rGraphic, const SwFrameFormat& rFormat, SvStream& rRtf); } #endif // INCLUDED_SW_SOURCE_FILTER_HTML_HTMLREQIFREADER_HXX diff --git a/sw/source/filter/html/htmlsect.cxx b/sw/source/filter/html/htmlsect.cxx index d68a22e2e389..26a1ec8d0e19 100644 --- a/sw/source/filter/html/htmlsect.cxx +++ b/sw/source/filter/html/htmlsect.cxx @@ -103,7 +103,7 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) } bool bAppended = false; - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) { AppendTextNode( bHeader||bFooter||!aId.isEmpty()|| !aHRef.isEmpty() ? AM_NORMAL : AM_NOSPACE ); @@ -185,18 +185,16 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) const SwFormatContent& rFlyContent = pHdFtFormat->GetContent(); const SwNodeIndex& rContentStIdx = *rFlyContent.GetContentIdx(); - SwContentNode *pCNd; - if( bNew ) + if( !bNew ) { - pCNd = m_xDoc->GetNodes()[rContentStIdx.GetIndex()+1] - ->GetContentNode(); - } - else - { - // Create a new node at the beginning of the section + // Our own html export only exports one "header" at most (and one "footer") + + // Create a new node at the beginning of the section if a duplicate arises + // and hide the original header/footers content by putting it into a hidden + // document-level section SwNodeIndex aSttIdx( rContentStIdx, 1 ); - pCNd = m_xDoc->GetNodes().MakeTextNode( aSttIdx, + m_xDoc->GetNodes().MakeTextNode( aSttIdx.GetNode(), m_pCSS1Parser->GetTextCollFromPool(RES_POOLCOLL_TEXT)); // delete the current content of the section @@ -205,13 +203,11 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) const SwStartNode *pStNd = static_cast<const SwStartNode *>( &rContentStIdx.GetNode() ); - aDelPam.GetPoint()->nNode = pStNd->EndOfSectionIndex() - 1; + aDelPam.GetPoint()->Assign( pStNd->EndOfSectionIndex() ); - if (!PendingObjectsInPaM(aDelPam)) - { - ClearFootnotesMarksInRange(aDelPam.GetMark()->nNode, aDelPam.GetPoint()->nNode); - m_xDoc->getIDocumentContentOperations().DelFullPara(aDelPam); - } + SwSectionData aSection(SectionType::Content, m_xDoc->GetUniqueSectionName()); + if (SwSection* pOldContent = m_xDoc->InsertSwSection(aDelPam, aSection, nullptr, nullptr, false)) + pOldContent->SetHidden(true); // update page style for( size_t i=0; i < m_xDoc->GetPageDescCnt(); i++ ) @@ -224,7 +220,7 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) } } - SwPosition aNewPos( SwNodeIndex( rContentStIdx, 1 ), SwIndex( pCNd, 0 ) ); + SwPosition aNewPos( rContentStIdx, SwNodeOffset(1) ); SaveDocContext(xCntxt.get(), nFlags, &aNewPos); } else if( !bPositioned && aId.getLength() > 9 && @@ -244,7 +240,7 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) SwContentNode *pCNd = m_xDoc->GetNodes()[pStartNdIdx->GetIndex()+1]->GetContentNode(); SwNodeIndex aTmpSwNodeIndex(*pCNd); - SwPosition aNewPos( aTmpSwNodeIndex, SwIndex( pCNd, 0 ) ); + SwPosition aNewPos( aTmpSwNodeIndex, pCNd, 0 ); SaveDocContext(xCntxt.get(), HtmlContextFlags::MultiColMask, &aNewPos); aId.clear(); aPropInfo.m_aId.clear(); @@ -263,7 +259,7 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) // Therefore we have to add a node and delete it again! if( !bAppended ) { - SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->nNode, -1 ); + SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->GetNode(), -1 ); if (aPrvNdIdx.GetNode().IsSectionNode()) { AppendTextNode(); @@ -285,11 +281,7 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) { nPos2 = aHRef.lastIndexOf( cDelim, nPos ); if( nPos2 != -1 ) - { - sal_Int32 nTmp = nPos; - nPos = nPos2; - nPos2 = nTmp; - } + std::swap( nPos, nPos2 ); } OUString aURL; if( nPos == -1 ) @@ -324,20 +316,16 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) aSection.SetProtectFlag(true); } - SfxItemSet aFrameItemSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs(aFrameItemSet ); - const SfxPoolItem *pItem; - if( SfxItemState::SET == aItemSet.GetItemState( RES_BACKGROUND, false, - &pItem ) ) + if( const SvxBrushItem* pItem = aItemSet.GetItemIfSet( RES_BACKGROUND, false ) ) { aFrameItemSet.Put( *pItem ); aItemSet.ClearItem( RES_BACKGROUND ); } - if( SfxItemState::SET == aItemSet.GetItemState( RES_FRAMEDIR, false, - &pItem ) ) + if( const SvxFrameDirectionItem* pItem = aItemSet.GetItemIfSet( RES_FRAMEDIR, false ) ) { aFrameItemSet.Put( *pItem ); aItemSet.ClearItem( RES_FRAMEDIR ); @@ -353,14 +341,14 @@ void SwHTMLParser::NewDivision( HtmlTokenId nToken ) } SwTextNode* pOldTextNd = - bAppended ? nullptr : m_pPam->GetPoint()->nNode.GetNode().GetTextNode(); + bAppended ? nullptr : m_pPam->GetPoint()->GetNode().GetTextNode(); m_pPam->Move( fnMoveBackward ); // move PageDesc and SwFormatBreak attribute from current node into // (first) node of the section if( pOldTextNd ) - MovePageDescAttrs( pOldTextNd, m_pPam->GetPoint()->nNode.GetIndex(), + MovePageDescAttrs( pOldTextNd, m_pPam->GetPoint()->GetNodeIndex(), true ); if( pPostIts ) @@ -437,14 +425,14 @@ void SwHTMLParser::FixHeaderFooterDistance( bool bHeader, const SwFormatContent& rFlyContent = pHdFtFormat->GetContent(); const SwNodeIndex& rContentStIdx = *rFlyContent.GetContentIdx(); - sal_uLong nPrvNxtIdx; + SwNodeOffset nPrvNxtIdx; if( bHeader ) { nPrvNxtIdx = rContentStIdx.GetNode().EndOfSectionIndex()-1; } else { - nPrvNxtIdx = pOldPos->nNode.GetIndex() - 1; + nPrvNxtIdx = pOldPos->GetNodeIndex() - 1; } sal_uInt16 nSpace = 0; @@ -452,8 +440,7 @@ void SwHTMLParser::FixHeaderFooterDistance( bool bHeader, if( pTextNode ) { const SvxULSpaceItem& rULSpace = - static_cast<const SvxULSpaceItem&>(pTextNode - ->SwContentNode::GetAttr( RES_UL_SPACE )); + pTextNode->SwContentNode::GetAttr( RES_UL_SPACE ); // The bottom paragraph padding becomes the padding // to header or footer @@ -472,7 +459,7 @@ void SwHTMLParser::FixHeaderFooterDistance( bool bHeader, if( bHeader ) { - nPrvNxtIdx = pOldPos->nNode.GetIndex(); + nPrvNxtIdx = pOldPos->GetNodeIndex(); } else { @@ -484,8 +471,7 @@ void SwHTMLParser::FixHeaderFooterDistance( bool bHeader, if( pTextNode ) { const SvxULSpaceItem& rULSpace = - static_cast<const SvxULSpaceItem&>(pTextNode - ->SwContentNode::GetAttr( RES_UL_SPACE )); + pTextNode->SwContentNode::GetAttr( RES_UL_SPACE ); // The top paragraph padding becomes the padding // to headline or footer if it is greater than the @@ -515,7 +501,7 @@ void SwHTMLParser::FixHeaderFooterDistance( bool bHeader, bool SwHTMLParser::EndSection( bool bLFStripped ) { - SwEndNode *pEndNd = m_xDoc->GetNodes()[m_pPam->GetPoint()->nNode.GetIndex()+1] + SwEndNode *pEndNd = m_xDoc->GetNodes()[m_pPam->GetPoint()->GetNodeIndex()+1] ->GetEndNode(); if( pEndNd && pEndNd->StartOfSectionNode()->IsSectionNode() ) { @@ -579,7 +565,7 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) aDir = rOption.GetString(); break; case HtmlOptionId::COLS: - nCols = static_cast<sal_uInt16>(rOption.GetNumber()); + nCols = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::WIDTH: nWidth = rOption.GetNumber(); @@ -588,7 +574,7 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) nWidth = 100; break; case HtmlOptionId::GUTTER: - nGutter = static_cast<sal_uInt16>(rOption.GetNumber()); + nGutter = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; default: break; } @@ -614,11 +600,9 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) // Calculate width. sal_uInt8 nPercentWidth = bPercentWidth ? static_cast<sal_uInt8>(nWidth) : 0; SwTwips nTwipWidth = 0; - if( !bPercentWidth && nWidth && Application::GetDefaultDevice() ) + if( !bPercentWidth && nWidth ) { - nTwipWidth = Application::GetDefaultDevice() - ->PixelToLogic( Size(nWidth, 0), - MapMode(MapUnit::MapTwip) ).Width(); + nTwipWidth = o3tl::convert(nWidth, o3tl::Length::px, o3tl::Length::twip); } if( !nPercentWidth && nTwipWidth < MINFLY ) @@ -628,8 +612,7 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) bool bPositioned = false; if( bInCntnr || SwCSS1Parser::MayBePositioned( aPropInfo, true ) ) { - SfxItemSet aFrameItemSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs(aFrameItemSet ); @@ -667,7 +650,7 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) bool bAppended = false; if( !bPositioned ) { - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) { AppendTextNode( AM_SPACE ); bAppended = true; @@ -686,7 +669,7 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) // If the pam is at the start of a section, an additional text // node must be inserted. Otherwise, the new section will be // inserted in front of the old one. - SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->nNode, -1 ); + SwNodeIndex aPrvNdIdx( m_pPam->GetPoint()->GetNode(), -1 ); if (aPrvNdIdx.GetNode().IsSectionNode()) { AppendTextNode(); @@ -700,16 +683,13 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) OUString aName( m_xDoc->GetUniqueSectionName( !aId.isEmpty() ? &aId : nullptr ) ); SwSectionData aSection( SectionType::Content, aName ); - SfxItemSet aFrameItemSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameItemSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs(aFrameItemSet ); - if( nGutter && Application::GetDefaultDevice() ) + if( nGutter ) { - nGutter = static_cast<sal_uInt16>(Application::GetDefaultDevice() - ->PixelToLogic( Size(nGutter, 0), - MapMode(MapUnit::MapTwip) ).Width()); + nGutter = o3tl::convert(nGutter, o3tl::Length::px, o3tl::Length::twip); } SwFormatCol aFormatCol; @@ -717,15 +697,12 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) aFormatCol.Init( nCols, nGutter, USHRT_MAX ); aFrameItemSet.Put( aFormatCol ); - const SfxPoolItem *pItem; - if( SfxItemState::SET == aItemSet.GetItemState( RES_BACKGROUND, false, - &pItem ) ) + if( const SvxBrushItem* pItem = aItemSet.GetItemIfSet( RES_BACKGROUND, false) ) { aFrameItemSet.Put( *pItem ); aItemSet.ClearItem( RES_BACKGROUND ); } - if( SfxItemState::SET == aItemSet.GetItemState( RES_FRAMEDIR, false, - &pItem ) ) + if( const SvxFrameDirectionItem* pItem = aItemSet.GetItemIfSet( RES_FRAMEDIR, false ) ) { aFrameItemSet.Put( *pItem ); aItemSet.ClearItem( RES_FRAMEDIR ); @@ -740,14 +717,14 @@ void SwHTMLParser::NewMultiCol( sal_uInt16 columnsFromCss ) } SwTextNode* pOldTextNd = - bAppended ? nullptr : m_pPam->GetPoint()->nNode.GetNode().GetTextNode(); + bAppended ? nullptr : m_pPam->GetPoint()->GetNode().GetTextNode(); m_pPam->Move( fnMoveBackward ); // Move PageDesc and SwFormatBreak attributes of the current node // to the section's first node. if( pOldTextNd ) - MovePageDescAttrs( pOldTextNd, m_pPam->GetPoint()->nNode.GetIndex(), + MovePageDescAttrs( pOldTextNd, m_pPam->GetPoint()->GetNodeIndex(), true ); if( pPostIts ) @@ -782,22 +759,20 @@ void SwHTMLParser::InsertFlyFrame( const SfxItemSet& rItemSet, SwFlyFrameFormat* pFlyFormat = m_xDoc->MakeFlySection( eAnchorId, m_pPam->GetPoint(), &rItemSet ); if( !rName.isEmpty() ) - pFlyFormat->SetName( rName ); + pFlyFormat->SetFormatName( rName ); RegisterFlyFrame( pFlyFormat ); const SwFormatContent& rFlyContent = pFlyFormat->GetContent(); const SwNodeIndex& rFlyCntIdx = *rFlyContent.GetContentIdx(); - SwContentNode *pCNd = m_xDoc->GetNodes()[rFlyCntIdx.GetIndex()+1] - ->GetContentNode(); - SwPosition aNewPos( SwNodeIndex( rFlyCntIdx, 1 ), SwIndex( pCNd, 0 ) ); + SwPosition aNewPos( rFlyCntIdx, SwNodeOffset(1) ); const HtmlContextFlags nFlags = HtmlContextFlags::ProtectStack|HtmlContextFlags::StripPara; SaveDocContext( pCntxt, nFlags, &aNewPos ); } void SwHTMLParser::MovePageDescAttrs( SwNode *pSrcNd, - sal_uLong nDestIdx, + SwNodeOffset nDestIdx, bool bFormatBreak ) { SwContentNode* pDestContentNd = @@ -809,18 +784,17 @@ void SwHTMLParser::MovePageDescAttrs( SwNode *pSrcNd, { SwContentNode* pSrcContentNd = pSrcNd->GetContentNode(); - const SfxPoolItem* pItem; - if( SfxItemState::SET == pSrcContentNd->GetSwAttrSet() - .GetItemState( RES_PAGEDESC, false, &pItem ) && - static_cast<const SwFormatPageDesc *>(pItem)->GetPageDesc() ) + const SwFormatPageDesc* pFormatPageDesc = + pSrcContentNd->GetSwAttrSet().GetItemIfSet( RES_PAGEDESC, false ); + if( pFormatPageDesc && pFormatPageDesc->GetPageDesc() ) { - pDestContentNd->SetAttr( *pItem ); + pDestContentNd->SetAttr( *pFormatPageDesc ); pSrcContentNd->ResetAttr( RES_PAGEDESC ); } - if( SfxItemState::SET == pSrcContentNd->GetSwAttrSet() - .GetItemState( RES_BREAK, false, &pItem ) ) + if( const SvxFormatBreakItem* pItem = pSrcContentNd->GetSwAttrSet() + .GetItemIfSet( RES_BREAK, false ) ) { - switch( static_cast<const SvxFormatBreakItem *>(pItem)->GetBreak() ) + switch( pItem->GetBreak() ) { case SvxBreak::PageBefore: case SvxBreak::PageAfter: @@ -838,9 +812,8 @@ void SwHTMLParser::MovePageDescAttrs( SwNode *pSrcNd, { SwFrameFormat *pFrameFormat = pSrcNd->GetTableNode()->GetTable().GetFrameFormat(); - const SfxPoolItem* pItem; - if( SfxItemState::SET == pFrameFormat->GetAttrSet(). - GetItemState( RES_PAGEDESC, false, &pItem ) ) + if( const SwFormatPageDesc* pItem = pFrameFormat->GetAttrSet(). + GetItemIfSet( RES_PAGEDESC, false ) ) { if (pDestContentNd) pDestContentNd->SetAttr(*pItem); diff --git a/sw/source/filter/html/htmltab.cxx b/sw/source/filter/html/htmltab.cxx index c3c95cf7f788..1719347fe5dd 100644 --- a/sw/source/filter/html/htmltab.cxx +++ b/sw/source/filter/html/htmltab.cxx @@ -19,7 +19,9 @@ #include <memory> #include <hintids.hxx> +#include <comphelper/configuration.hxx> #include <comphelper/flagguard.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <editeng/boxitem.hxx> #include <editeng/brushitem.hxx> @@ -32,8 +34,12 @@ #include <unotools/configmgr.hxx> #include <svtools/htmltokn.h> #include <svtools/htmlkywd.hxx> +#include <svl/numformat.hxx> #include <svl/urihelper.hxx> +#include <svx/sdrobjectuser.hxx> +#include <svx/svdotext.hxx> #include <sal/log.hxx> +#include <osl/diagnose.h> #include <dcontact.hxx> #include <fmtornt.hxx> @@ -113,57 +119,57 @@ struct HTMLTableOptions class HTMLTableContext { - SwHTMLNumRuleInfo aNumRuleInfo; // Numbering valid before the table + SwHTMLNumRuleInfo m_aNumRuleInfo; // Numbering valid before the table - SwTableNode *pTableNd; // table node - SwFrameFormat *pFrameFormat; // the Fly frame::Frame, containing the table - std::unique_ptr<SwPosition> pPos; // position behind the table + SwTableNode *m_pTableNd; // table node + SwFrameFormat *m_pFrameFormat; // the Fly frame::Frame, containing the table + std::unique_ptr<SwPosition> m_pPos; // position behind the table - size_t nContextStAttrMin; - size_t nContextStMin; + size_t m_nContextStAttrMin; + size_t m_nContextStMin; - bool bRestartPRE : 1; - bool bRestartXMP : 1; - bool bRestartListing : 1; + bool m_bRestartPRE : 1; + bool m_bRestartXMP : 1; + bool m_bRestartListing : 1; HTMLTableContext(const HTMLTableContext&) = delete; HTMLTableContext& operator=(const HTMLTableContext&) = delete; public: - std::shared_ptr<HTMLAttrTable> xAttrTab; // attributes + std::shared_ptr<HTMLAttrTable> m_xAttrTab; // attributes HTMLTableContext( SwPosition *pPs, size_t nCntxtStMin, size_t nCntxtStAttrMin ) : - pTableNd( nullptr ), - pFrameFormat( nullptr ), - pPos( pPs ), - nContextStAttrMin( nCntxtStAttrMin ), - nContextStMin( nCntxtStMin ), - bRestartPRE( false ), - bRestartXMP( false ), - bRestartListing( false ), - xAttrTab(std::make_shared<HTMLAttrTable>()) + m_pTableNd( nullptr ), + m_pFrameFormat( nullptr ), + m_pPos( pPs ), + m_nContextStAttrMin( nCntxtStAttrMin ), + m_nContextStMin( nCntxtStMin ), + m_bRestartPRE( false ), + m_bRestartXMP( false ), + m_bRestartListing( false ), + m_xAttrTab(std::make_shared<HTMLAttrTable>()) { - memset(xAttrTab.get(), 0, sizeof(HTMLAttrTable)); + memset(m_xAttrTab.get(), 0, sizeof(HTMLAttrTable)); } - void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { aNumRuleInfo.Set(rInf); } - const SwHTMLNumRuleInfo& GetNumInfo() const { return aNumRuleInfo; }; + void SetNumInfo( const SwHTMLNumRuleInfo& rInf ) { m_aNumRuleInfo.Set(rInf); } + const SwHTMLNumRuleInfo& GetNumInfo() const { return m_aNumRuleInfo; }; void SavePREListingXMP( SwHTMLParser& rParser ); void RestorePREListingXMP( SwHTMLParser& rParser ); - SwPosition *GetPos() const { return pPos.get(); } + SwPosition *GetPos() const { return m_pPos.get(); } - void SetTableNode( SwTableNode *pNd ) { pTableNd = pNd; } - SwTableNode *GetTableNode() const { return pTableNd; } + void SetTableNode( SwTableNode *pNd ) { m_pTableNd = pNd; } + SwTableNode *GetTableNode() const { return m_pTableNd; } - void SetFrameFormat( SwFrameFormat *pFormat ) { pFrameFormat = pFormat; } - SwFrameFormat *GetFrameFormat() const { return pFrameFormat; } + void SetFrameFormat( SwFrameFormat *pFormat ) { m_pFrameFormat = pFormat; } + SwFrameFormat *GetFrameFormat() const { return m_pFrameFormat; } - size_t GetContextStMin() const { return nContextStMin; } - size_t GetContextStAttrMin() const { return nContextStAttrMin; } + size_t GetContextStMin() const { return m_nContextStMin; } + size_t GetContextStAttrMin() const { return m_nContextStAttrMin; } }; } @@ -188,7 +194,7 @@ class HTMLTableCnts public: explicit HTMLTableCnts(const SwStartNode* pStNd); - explicit HTMLTableCnts(const std::shared_ptr<HTMLTable>& rTab); + explicit HTMLTableCnts(std::shared_ptr<HTMLTable> xTab); ~HTMLTableCnts(); // only allowed in ~HTMLTableCell @@ -285,24 +291,24 @@ namespace { class HTMLTableRow { std::vector<HTMLTableCell> m_aCells; ///< cells of the row - std::unique_ptr<SvxBrushItem> xBGBrush; // background of cell from STYLE + std::unique_ptr<SvxBrushItem> m_xBGBrush; // background of cell from STYLE - SvxAdjust eAdjust; - sal_uInt16 nHeight; // options of <TR>/<TD> - sal_uInt16 nEmptyRows; // number of empty rows are following - sal_Int16 eVertOri; - bool bIsEndOfGroup : 1; - bool bBottomBorder : 1; // Is there a line after the row? + SvxAdjust m_eAdjust; + sal_uInt16 m_nHeight; // options of <TR>/<TD> + sal_uInt16 m_nEmptyRows; // number of empty rows are following + sal_Int16 m_eVertOri; + bool m_bIsEndOfGroup : 1; + bool m_bBottomBorder : 1; // Is there a line after the row? public: explicit HTMLTableRow( sal_uInt16 nCells ); // cells of the row are empty - void SetBottomBorder(bool bIn) { bBottomBorder = bIn; } - bool GetBottomBorder() const { return bBottomBorder; } + void SetBottomBorder(bool bIn) { m_bBottomBorder = bIn; } + bool GetBottomBorder() const { return m_bBottomBorder; } inline void SetHeight( sal_uInt16 nHeight ); - sal_uInt16 GetHeight() const { return nHeight; } + sal_uInt16 GetHeight() const { return m_nHeight; } const HTMLTableCell& GetCell(sal_uInt16 nCell) const; HTMLTableCell& GetCell(sal_uInt16 nCell) @@ -310,20 +316,20 @@ public: return const_cast<HTMLTableCell&>(const_cast<const HTMLTableRow&>(*this).GetCell(nCell)); } - void SetAdjust( SvxAdjust eAdj ) { eAdjust = eAdj; } - SvxAdjust GetAdjust() const { return eAdjust; } + void SetAdjust( SvxAdjust eAdj ) { m_eAdjust = eAdj; } + SvxAdjust GetAdjust() const { return m_eAdjust; } - void SetVertOri( sal_Int16 eV) { eVertOri = eV; } - sal_Int16 GetVertOri() const { return eVertOri; } + void SetVertOri( sal_Int16 eV) { m_eVertOri = eV; } + sal_Int16 GetVertOri() const { return m_eVertOri; } - void SetBGBrush(std::unique_ptr<SvxBrushItem>& rBrush ) { xBGBrush = std::move(rBrush); } - const std::unique_ptr<SvxBrushItem>& GetBGBrush() const { return xBGBrush; } + void SetBGBrush(std::unique_ptr<SvxBrushItem>& rBrush ) { m_xBGBrush = std::move(rBrush); } + const std::unique_ptr<SvxBrushItem>& GetBGBrush() const { return m_xBGBrush; } - void SetEndOfGroup() { bIsEndOfGroup = true; } - bool IsEndOfGroup() const { return bIsEndOfGroup; } + void SetEndOfGroup() { m_bIsEndOfGroup = true; } + bool IsEndOfGroup() const { return m_bIsEndOfGroup; } - void IncEmptyRows() { nEmptyRows++; } - sal_uInt16 GetEmptyRows() const { return nEmptyRows; } + void IncEmptyRows() { m_nEmptyRows++; } + sal_uInt16 GetEmptyRows() const { return m_nEmptyRows; } // Expand row by adding empty cells void Expand( sal_uInt16 nCells, bool bOneCell=false ); @@ -335,35 +341,35 @@ public: // Column of a HTML table class HTMLTableColumn { - bool bIsEndOfGroup; + bool m_bIsEndOfGroup; - sal_uInt16 nWidth; // options of <COL> - bool bRelWidth; + sal_uInt16 m_nWidth; // options of <COL> + bool m_bRelWidth; - SvxAdjust eAdjust; - sal_Int16 eVertOri; + SvxAdjust m_eAdjust; + sal_Int16 m_eVertOri; - SwFrameFormat *aFrameFormats[6]; + SwFrameFormat *m_aFrameFormats[6]; static inline sal_uInt16 GetFrameFormatIdx( bool bBorderLine, sal_Int16 eVertOri ); public: - bool bLeftBorder; // is there a line before the column + bool m_bLeftBorder; // is there a line before the column HTMLTableColumn(); inline void SetWidth( sal_uInt16 nWidth, bool bRelWidth); - void SetAdjust( SvxAdjust eAdj ) { eAdjust = eAdj; } - SvxAdjust GetAdjust() const { return eAdjust; } + void SetAdjust( SvxAdjust eAdj ) { m_eAdjust = eAdj; } + SvxAdjust GetAdjust() const { return m_eAdjust; } - void SetVertOri( sal_Int16 eV) { eVertOri = eV; } - sal_Int16 GetVertOri() const { return eVertOri; } + void SetVertOri( sal_Int16 eV) { m_eVertOri = eV; } + sal_Int16 GetVertOri() const { return m_eVertOri; } - void SetEndOfGroup() { bIsEndOfGroup = true; } - bool IsEndOfGroup() const { return bIsEndOfGroup; } + void SetEndOfGroup() { m_bIsEndOfGroup = true; } + bool IsEndOfGroup() const { return m_bIsEndOfGroup; } inline void SetFrameFormat( SwFrameFormat *pFormat, bool bBorderLine, sal_Int16 eVertOri ); @@ -378,15 +384,15 @@ public: // HTML table typedef std::vector<SdrObject *> SdrObjects; -class HTMLTable +class HTMLTable : public sdr::ObjectUser { OUString m_aId; OUString m_aStyle; OUString m_aClass; OUString m_aDir; - std::unique_ptr<SdrObjects> m_pResizeDrawObjects;// SDR objects - std::unique_ptr<std::vector<sal_uInt16>> m_pDrawObjectPercentWidths; // column of draw object and its rel. width + std::optional<SdrObjects> m_xResizeDrawObjects;// SDR objects + std::optional<std::vector<sal_uInt16>> m_xDrawObjectPercentWidths; // column of draw object and its rel. width std::vector<HTMLTableRow> m_aRows; ///< table rows std::vector<HTMLTableColumn> m_aColumns; ///< table columns @@ -526,6 +532,8 @@ private: sal_uInt16 GetBorderWidth( const SvxBorderLine& rBLine, bool bWithDistance=false ) const; + virtual void ObjectInDestruction(const SdrObject& rObject) override; + public: bool m_bFirstCell; // is there a cell created already? @@ -535,7 +543,7 @@ public: bool bHasToFly, const HTMLTableOptions& rOptions); - ~HTMLTable(); + virtual ~HTMLTable(); // Identifying of a cell const HTMLTableCell& GetCell(sal_uInt16 nRow, sal_uInt16 nCell) const; @@ -629,8 +637,6 @@ public: void IncBoxCount() { m_nBoxes++; } bool IsOverflowing() const { return m_nBoxes > 64000; } - - bool PendingDrawObjectsInPaM(SwPaM& rPam) const; }; void HTMLTableCnts::InitCtor() @@ -646,9 +652,9 @@ HTMLTableCnts::HTMLTableCnts(const SwStartNode* pStNd) InitCtor(); } -HTMLTableCnts::HTMLTableCnts(const std::shared_ptr<HTMLTable>& rTab) +HTMLTableCnts::HTMLTableCnts(std::shared_ptr<HTMLTable> xTab) : m_pStartNode(nullptr) - , m_xTable(rTab) + , m_xTable(std::move(xTab)) { InitCtor(); } @@ -775,12 +781,12 @@ std::unique_ptr<SwHTMLTableLayoutCell> HTMLTableCell::CreateLayoutInfo() HTMLTableRow::HTMLTableRow(sal_uInt16 const nCells) : m_aCells(nCells) - , eAdjust(SvxAdjust::End) - , nHeight(0) - , nEmptyRows(0) - , eVertOri(text::VertOrientation::TOP) - , bIsEndOfGroup(false) - , bBottomBorder(false) + , m_eAdjust(SvxAdjust::End) + , m_nHeight(0) + , m_nEmptyRows(0) + , m_eVertOri(text::VertOrientation::TOP) + , m_bIsEndOfGroup(false) + , m_bBottomBorder(false) { assert(nCells == m_aCells.size() && "wrong Cell count in new HTML table row"); @@ -788,8 +794,8 @@ HTMLTableRow::HTMLTableRow(sal_uInt16 const nCells) inline void HTMLTableRow::SetHeight( sal_uInt16 nHght ) { - if( nHght > nHeight ) - nHeight = nHght; + if( nHght > m_nHeight ) + m_nHeight = nHght; } const HTMLTableCell& HTMLTableRow::GetCell(sal_uInt16 nCell) const @@ -857,30 +863,30 @@ void HTMLTableRow::Shrink( sal_uInt16 nCells ) } HTMLTableColumn::HTMLTableColumn(): - bIsEndOfGroup(false), - nWidth(0), bRelWidth(false), - eAdjust(SvxAdjust::End), eVertOri(text::VertOrientation::TOP), - bLeftBorder(false) + m_bIsEndOfGroup(false), + m_nWidth(0), m_bRelWidth(false), + m_eAdjust(SvxAdjust::End), m_eVertOri(text::VertOrientation::TOP), + m_bLeftBorder(false) { - for(SwFrameFormat* & rp : aFrameFormats) + for(SwFrameFormat* & rp : m_aFrameFormats) rp = nullptr; } inline void HTMLTableColumn::SetWidth( sal_uInt16 nWdth, bool bRelWdth ) { - if( bRelWidth==bRelWdth ) + if( m_bRelWidth==bRelWdth ) { - if( nWdth > nWidth ) - nWidth = nWdth; + if( nWdth > m_nWidth ) + m_nWidth = nWdth; } else - nWidth = nWdth; - bRelWidth = bRelWdth; + m_nWidth = nWdth; + m_bRelWidth = bRelWdth; } inline std::unique_ptr<SwHTMLTableLayoutColumn> HTMLTableColumn::CreateLayoutInfo() { - return std::unique_ptr<SwHTMLTableLayoutColumn>(new SwHTMLTableLayoutColumn( nWidth, bRelWidth, bLeftBorder )); + return std::unique_ptr<SwHTMLTableLayoutColumn>(new SwHTMLTableLayoutColumn( m_nWidth, m_bRelWidth, m_bLeftBorder )); } inline sal_uInt16 HTMLTableColumn::GetFrameFormatIdx( bool bBorderLine, @@ -901,13 +907,13 @@ inline sal_uInt16 HTMLTableColumn::GetFrameFormatIdx( bool bBorderLine, inline void HTMLTableColumn::SetFrameFormat( SwFrameFormat *pFormat, bool bBorderLine, sal_Int16 eVertOrient ) { - aFrameFormats[GetFrameFormatIdx(bBorderLine,eVertOrient)] = pFormat; + m_aFrameFormats[GetFrameFormatIdx(bBorderLine,eVertOrient)] = pFormat; } inline SwFrameFormat *HTMLTableColumn::GetFrameFormat( bool bBorderLine, sal_Int16 eVertOrient ) const { - return aFrameFormats[GetFrameFormatIdx(bBorderLine,eVertOrient)]; + return m_aFrameFormats[GetFrameFormatIdx(bBorderLine,eVertOrient)]; } void HTMLTable::InitCtor(const HTMLTableOptions& rOptions) @@ -944,7 +950,7 @@ void HTMLTable::InitCtor(const HTMLTableOptions& rOptions) // nBorder tells the width of the border as it's used in the width calculation of NetScape // If pOption->nBorder == USHRT_MAX, there wasn't a BORDER option given // Nonetheless, a 1 pixel wide border will be used for width calculation - m_nBorder = static_cast<sal_uInt16>(nPWidth); + m_nBorder = o3tl::narrowing<sal_uInt16>(nPWidth); if( nBorderOpt==USHRT_MAX ) nPWidth = 0; @@ -972,14 +978,8 @@ void HTMLTable::InitCtor(const HTMLTableOptions& rOptions) m_aRightBorderLine = m_aLeftBorderLine; if( rOptions.nCellSpacing != 0 ) - { m_aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE); - m_aBorderLine.SetWidth( DEF_LINE_WIDTH_0 ); - } - else - { - m_aBorderLine.SetWidth( DEF_LINE_WIDTH_0 ); - } + m_aBorderLine.SetWidth(SvxBorderLineWidth::Hairline); m_aBorderLine.SetColor( rBorderColor ); if( m_nCellPadding ) @@ -1003,8 +1003,8 @@ void HTMLTable::InitCtor(const HTMLTableOptions& rOptions) nPWidth = rOptions.nHSpace; nPHeight = rOptions.nVSpace; SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight ); - m_nHSpace = static_cast<sal_uInt16>(nPWidth); - m_nVSpace = static_cast<sal_uInt16>(nPHeight); + m_nHSpace = o3tl::narrowing<sal_uInt16>(nPWidth); + m_nVSpace = o3tl::narrowing<sal_uInt16>(nPHeight); m_bColSpec = false; @@ -1056,7 +1056,7 @@ void SwHTMLParser::DeregisterHTMLTable(HTMLTable* pOld) { if (pOld->m_xBox1) m_aOrphanedTableBoxes.emplace_back(std::move(pOld->m_xBox1)); - m_aTables.erase(std::remove(m_aTables.begin(), m_aTables.end(), pOld)); + std::erase(m_aTables, pOld); } SwDoc* SwHTMLParser::GetDoc() const @@ -1069,12 +1069,34 @@ bool SwHTMLParser::IsReqIF() const return m_bReqIF; } +// if any m_xResizeDrawObjects members are deleted during parse, remove them +// from m_xResizeDrawObjects and m_xDrawObjectPercentWidths +void HTMLTable::ObjectInDestruction(const SdrObject& rObject) +{ + auto it = std::find(m_xResizeDrawObjects->begin(), m_xResizeDrawObjects->end(), &rObject); + assert(it != m_xResizeDrawObjects->end()); + auto nIndex = std::distance(m_xResizeDrawObjects->begin(), it); + m_xResizeDrawObjects->erase(it); + auto otherit = m_xDrawObjectPercentWidths->begin() + nIndex * 3; + m_xDrawObjectPercentWidths->erase(otherit, otherit + 3); +} + HTMLTable::~HTMLTable() { m_pParser->DeregisterHTMLTable(this); - m_pResizeDrawObjects.reset(); - m_pDrawObjectPercentWidths.reset(); + if (m_xResizeDrawObjects) + { + size_t nCount = m_xResizeDrawObjects->size(); + for (size_t i = 0; i < nCount; ++i) + { + SdrObject *pObj = (*m_xResizeDrawObjects)[i]; + pObj->RemoveObjectUser(*this); + } + m_xResizeDrawObjects.reset(); + } + + m_xDrawObjectPercentWidths.reset(); m_pContext.reset(); @@ -1087,7 +1109,7 @@ const std::shared_ptr<SwHTMLTableLayout>& HTMLTable::CreateLayoutInfo() sal_uInt16 nBorderWidth = GetBorderWidth( m_aBorderLine, true ); sal_uInt16 nLeftBorderWidth = - m_aColumns[0].bLeftBorder ? GetBorderWidth(m_aLeftBorderLine, true) : 0; + m_aColumns[0].m_bLeftBorder ? GetBorderWidth(m_aLeftBorderLine, true) : 0; sal_uInt16 nRightBorderWidth = m_bRightBorder ? GetBorderWidth( m_aRightBorderLine, true ) : 0; @@ -1225,21 +1247,6 @@ const SwStartNode* HTMLTable::GetPrevBoxStartNode( sal_uInt16 nRow, sal_uInt16 n return pTable->GetPrevBoxStartNode(USHRT_MAX, USHRT_MAX); } -static bool IsBoxEmpty( const SwTableBox *pBox ) -{ - const SwStartNode *pSttNd = pBox->GetSttNd(); - if( pSttNd && - pSttNd->GetIndex() + 2 == pSttNd->EndOfSectionIndex() ) - { - const SwContentNode *pCNd = - pSttNd->GetNodes()[pSttNd->GetIndex()+1]->GetContentNode(); - if( pCNd && !pCNd->Len() ) - return true; - } - - return false; -} - sal_uInt16 HTMLTable::GetTopCellSpace( sal_uInt16 nRow ) const { sal_uInt16 nSpace = m_nCellPadding; @@ -1371,7 +1378,7 @@ void HTMLTable::FixFrameFormat( SwTableBox *pBox, } bSet = true; } - if (m_aColumns[nCol].bLeftBorder) + if (m_aColumns[nCol].m_bLeftBorder) { const SvxBorderLine& rBorderLine = 0==nCol ? m_aLeftBorderLine : m_aBorderLine; @@ -1412,12 +1419,12 @@ void HTMLTable::FixFrameFormat( SwTableBox *pBox, pFrameFormat->ResetFormatAttr( RES_BACKGROUND ); // Only set format if there's a value or the box is empty - if( bHasNumFormat && (bHasValue || IsBoxEmpty(pBox)) ) + if( bHasNumFormat && (bHasValue || pBox->IsEmpty()) ) { bool bLock = pFrameFormat->GetDoc()->GetNumberFormatter() ->IsTextFormat( nNumFormat ); - SfxItemSet aItemSet( *pFrameFormat->GetAttrSet().GetPool(), - svl::Items<RES_BOXATR_FORMAT, RES_BOXATR_VALUE>{} ); + SfxItemSetFixed<RES_BOXATR_FORMAT, RES_BOXATR_VALUE> + aItemSet( *pFrameFormat->GetAttrSet().GetPool() ); SvxAdjust eAdjust = SvxAdjust::End; SwContentNode *pCNd = nullptr; if( !bLock ) @@ -1425,13 +1432,12 @@ void HTMLTable::FixFrameFormat( SwTableBox *pBox, const SwStartNode *pSttNd = pBox->GetSttNd(); pCNd = pSttNd->GetNodes()[pSttNd->GetIndex()+1] ->GetContentNode(); - const SfxPoolItem *pItem; + const SvxAdjustItem *pItem; if( pCNd && pCNd->HasSwAttrSet() && - SfxItemState::SET==pCNd->GetpSwAttrSet()->GetItemState( - RES_PARATR_ADJUST, false, &pItem ) ) + (pItem = pCNd->GetpSwAttrSet()->GetItemIfSet( + RES_PARATR_ADJUST, false )) ) { - eAdjust = static_cast<const SvxAdjustItem *>(pItem) - ->GetAdjust(); + eAdjust = pItem->GetAdjust(); } } aItemSet.Put( SwTableBoxNumFormat(nNumFormat) ); @@ -1482,11 +1488,34 @@ void HTMLTable::FixFrameFormat( SwTableBox *pBox, if (pTableFormat) { sal_uInt8 nPos = SwTableAutoFormat::CountPos(nCol, m_nCols, nRow, m_nRows); + const SfxItemSet& rAttrSet = pFrameFormat->GetAttrSet(); + std::unique_ptr<SvxBoxItem> pOldBoxItem; + if (const SvxBoxItem* pBoxItem2 = rAttrSet.GetItemIfSet(RES_BOX)) + pOldBoxItem.reset(pBoxItem2->Clone()); pTableFormat->UpdateToSet(nPos, m_nRows==1, m_nCols==1, - const_cast<SfxItemSet&>(static_cast<SfxItemSet const&>( - pFrameFormat->GetAttrSet())), + const_cast<SfxItemSet&>(rAttrSet), SwTableAutoFormatUpdateFlags::Box, pFrameFormat->GetDoc()->GetNumberFormatter()); + if (pOldBoxItem) + { + // There was an old item, so it's guaranteed that there's a new item + const SvxBoxItem* pBoxItem2(rAttrSet.GetItem(RES_BOX)); + if (*pBoxItem2 != *pOldBoxItem) + { + std::unique_ptr<SvxBoxItem> pNewBoxItem(pBoxItem2->Clone()); + // Restore the box elements that could have been already set + for (auto eLine : { SvxBoxItemLine::TOP, SvxBoxItemLine::BOTTOM, + SvxBoxItemLine::LEFT, SvxBoxItemLine::RIGHT }) + { + if (auto pLine = pOldBoxItem->GetLine(eLine)) + pNewBoxItem->SetLine(pLine, eLine); + if (auto nDistance = pOldBoxItem->GetDistance(eLine, true)) + pNewBoxItem->SetDistance(nDistance, eLine); + } + + pFrameFormat->SetFormatAttr(*pNewBoxItem); + } + } } } } @@ -1814,7 +1843,7 @@ void HTMLTable::InheritVertBorders( const HTMLTable *pParent, GetBorderWidth( m_aInheritedRightBorderLine, true ) + MIN_BORDER_DIST; } - if (pParent->m_aColumns[nCol].bLeftBorder) + if (pParent->m_aColumns[nCol].m_bLeftBorder) { m_bInheritedLeftBorder = true; // just remember for now m_aInheritedLeftBorderLine = 0==nCol ? pParent->m_aLeftBorderLine @@ -1832,7 +1861,7 @@ void HTMLTable::InheritVertBorders( const HTMLTable *pParent, m_bRightAllowed = ( pParent->m_bRightAllowed && (nCol+nColSpan==pParent->m_nCols || - !pParent->m_aColumns[nCol+nColSpan].bLeftBorder) ); + !pParent->m_aColumns[nCol+nColSpan].m_bLeftBorder) ); } void HTMLTable::SetBorders() @@ -1843,7 +1872,7 @@ void HTMLTable::SetBorders() ((HTMLTableRules::Rows==m_eRules || HTMLTableRules::Groups==m_eRules) && m_aColumns[i-1].IsEndOfGroup())) { - m_aColumns[i].bLeftBorder = true; + m_aColumns[i].m_bLeftBorder = true; } for( i=0; i<m_nRows-1; i++ ) @@ -1867,7 +1896,7 @@ void HTMLTable::SetBorders() m_bRightBorder = true; if( HTMLTableFrame::LHS==m_eFrame || HTMLTableFrame::VSides==m_eFrame || HTMLTableFrame::Box==m_eFrame ) { - m_aColumns[0].bLeftBorder = true; + m_aColumns[0].m_bLeftBorder = true; } for( i=0; i<m_nRows; i++ ) @@ -2027,23 +2056,22 @@ void HTMLTable::InsertCell( std::shared_ptr<HTMLTableCnts> const& rCnts, } Size aTwipSz( bRelWidth ? 0 : nCellWidth, nCellHeight ); - if( (aTwipSz.Width() || aTwipSz.Height()) && Application::GetDefaultDevice() ) + if( aTwipSz.Width() || aTwipSz.Height() ) { - aTwipSz = Application::GetDefaultDevice() - ->PixelToLogic( aTwipSz, MapMode( MapUnit::MapTwip ) ); + aTwipSz = o3tl::convert(aTwipSz, o3tl::Length::px, o3tl::Length::twip); } // Only set width on the first cell! if( nCellWidth ) { - sal_uInt16 nTmp = bRelWidth ? nCellWidth : static_cast<sal_uInt16>(aTwipSz.Width()); + sal_uInt16 nTmp = bRelWidth ? nCellWidth : o3tl::narrowing<sal_uInt16>(aTwipSz.Width()); GetCell( m_nCurrentRow, m_nCurrentColumn ).SetWidth( nTmp, bRelWidth ); } // Remember height if( nCellHeight && 1==nRowSpan ) { - m_aRows[m_nCurrentRow].SetHeight(static_cast<sal_uInt16>(aTwipSz.Height())); + m_aRows[m_nCurrentRow].SetHeight(o3tl::narrowing<sal_uInt16>(aTwipSz.Height())); } // Set the column counter behind the new cells @@ -2160,17 +2188,12 @@ void HTMLTable::InsertCol( sal_uInt16 nSpan, sal_uInt16 nColWidth, bool bRelWidt m_nCols = nColsReq; } - Size aTwipSz( bRelWidth ? 0 : nColWidth, 0 ); - if( aTwipSz.Width() && Application::GetDefaultDevice() ) - { - aTwipSz = Application::GetDefaultDevice() - ->PixelToLogic( aTwipSz, MapMode( MapUnit::MapTwip ) ); - } + sal_uInt16 nTwipWidth(bRelWidth ? 0 : o3tl::convert(nColWidth, o3tl::Length::px, o3tl::Length::twip)); for( i=m_nCurrentColumn; i<nColsReq; i++ ) { HTMLTableColumn& rCol = m_aColumns[i]; - sal_uInt16 nTmp = bRelWidth ? nColWidth : static_cast<sal_uInt16>(aTwipSz.Width()); + sal_uInt16 nTmp = bRelWidth ? nColWidth : o3tl::narrowing<sal_uInt16>(nTwipWidth); rCol.SetWidth( nTmp, bRelWidth ); rCol.SetAdjust( eAdjust ); rCol.SetVertOri( eVertOrient ); @@ -2290,16 +2313,19 @@ void HTMLTable::MakeTable( SwTableBox *pBox, sal_uInt16 nAbsAvail, // Step 1: needed layout structures are created (including tables in tables) CreateLayoutInfo(); - // Step 2: the minimal and maximal column width is calculated - // (including tables in tables). Since we don't have boxes yet, - // we'll work on the start nodes - m_xLayoutInfo->AutoLayoutPass1(); + if (!comphelper::IsFuzzing()) // skip slow path for fuzzing + { + // Step 2: the minimal and maximal column width is calculated + // (including tables in tables). Since we don't have boxes yet, + // we'll work on the start nodes + m_xLayoutInfo->AutoLayoutPass1(); - // Step 3: the actual column widths of this table are calculated (not tables in tables) - // We need this now to decide if we need filler cells - // (Pass1 was needed because of this as well) - m_xLayoutInfo->AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace, - nAbsRightSpace, nInhAbsSpace ); + // Step 3: the actual column widths of this table are calculated (not tables in tables) + // We need this now to decide if we need filler cells + // (Pass1 was needed because of this as well) + m_xLayoutInfo->AutoLayoutPass2( nAbsAvail, nRelAvail, nAbsLeftSpace, + nAbsRightSpace, nInhAbsSpace ); + } // Set adjustment for the top table sal_Int16 eHoriOri; @@ -2416,8 +2442,8 @@ void HTMLTable::MakeTable( SwTableBox *pBox, sal_uInt16 nAbsAvail, // left or right adjusted table without width mustn't be adjusted in width // as they would only shrink but never grow m_xLayoutInfo->SetMustNotRecalc( true ); - if( m_pContext->GetFrameFormat()->GetAnchor().GetContentAnchor() - ->nNode.GetNode().FindTableNode() ) + if( m_pContext->GetFrameFormat()->GetAnchor().GetAnchorNode() + ->FindTableNode() ) { sal_uInt32 nMax = m_xLayoutInfo->GetMax(); if( nMax > USHRT_MAX ) @@ -2444,16 +2470,16 @@ void HTMLTable::MakeTable( SwTableBox *pBox, sal_uInt16 nAbsAvail, const_cast<SwTable *>(m_pSwTable)->SetHTMLTableLayout(m_xLayoutInfo); - if( !m_pResizeDrawObjects ) + if( !m_xResizeDrawObjects ) return; - sal_uInt16 nCount = m_pResizeDrawObjects->size(); + sal_uInt16 nCount = m_xResizeDrawObjects->size(); for( sal_uInt16 i=0; i<nCount; i++ ) { - SdrObject *pObj = (*m_pResizeDrawObjects)[i]; - sal_uInt16 nRow = (*m_pDrawObjectPercentWidths)[3*i]; - sal_uInt16 nCol = (*m_pDrawObjectPercentWidths)[3*i+1]; - sal_uInt8 nPercentWidth = static_cast<sal_uInt8>((*m_pDrawObjectPercentWidths)[3*i+2]); + SdrObject *pObj = (*m_xResizeDrawObjects)[i]; + sal_uInt16 nRow = (*m_xDrawObjectPercentWidths)[3*i]; + sal_uInt16 nCol = (*m_xDrawObjectPercentWidths)[3*i+1]; + sal_uInt8 nPercentWidth = static_cast<sal_uInt8>((*m_xDrawObjectPercentWidths)[3*i+2]); SwHTMLTableLayoutCell *pLayoutCell = m_xLayoutInfo->GetCell( nRow, nCol ); @@ -2484,15 +2510,16 @@ void HTMLTable::SetTable( const SwStartNode *pStNd, std::unique_ptr<HTMLTableCon void HTMLTable::RegisterDrawObject( SdrObject *pObj, sal_uInt8 nPercentWidth ) { - if( !m_pResizeDrawObjects ) - m_pResizeDrawObjects.reset(new SdrObjects); - m_pResizeDrawObjects->push_back( pObj ); - - if( !m_pDrawObjectPercentWidths ) - m_pDrawObjectPercentWidths.reset(new std::vector<sal_uInt16>); - m_pDrawObjectPercentWidths->push_back( m_nCurrentRow ); - m_pDrawObjectPercentWidths->push_back( m_nCurrentColumn ); - m_pDrawObjectPercentWidths->push_back( static_cast<sal_uInt16>(nPercentWidth) ); + if( !m_xResizeDrawObjects ) + m_xResizeDrawObjects.emplace(); + m_xResizeDrawObjects->push_back( pObj ); + pObj->AddObjectUser(*this); + + if( !m_xDrawObjectPercentWidths ) + m_xDrawObjectPercentWidths.emplace(); + m_xDrawObjectPercentWidths->push_back( m_nCurrentRow ); + m_xDrawObjectPercentWidths->push_back( m_nCurrentColumn ); + m_xDrawObjectPercentWidths->push_back( o3tl::narrowing<sal_uInt16>(nPercentWidth) ); } void HTMLTable::MakeParentContents() @@ -2508,9 +2535,9 @@ void HTMLTable::MakeParentContents() void HTMLTableContext::SavePREListingXMP( SwHTMLParser& rParser ) { - bRestartPRE = rParser.IsReadPRE(); - bRestartXMP = rParser.IsReadXMP(); - bRestartListing = rParser.IsReadListing(); + m_bRestartPRE = rParser.IsReadPRE(); + m_bRestartXMP = rParser.IsReadXMP(); + m_bRestartListing = rParser.IsReadListing(); rParser.FinishPREListingXMP(); } @@ -2518,13 +2545,13 @@ void HTMLTableContext::RestorePREListingXMP( SwHTMLParser& rParser ) { rParser.FinishPREListingXMP(); - if( bRestartPRE ) + if( m_bRestartPRE ) rParser.StartPRE(); - if( bRestartXMP ) + if( m_bRestartXMP ) rParser.StartXMP(); - if( bRestartListing ) + if( m_bRestartListing ) rParser.StartListing(); } @@ -2539,7 +2566,7 @@ const SwStartNode *SwHTMLParser::InsertTableSection const SwStartNode *pStNd; if (m_xTable->m_bFirstCell ) { - SwNode *const pNd = & m_pPam->GetPoint()->nNode.GetNode(); + SwNode *const pNd = & m_pPam->GetPoint()->GetNode(); pNd->GetTextNode()->ChgFormatColl( pColl ); pStNd = pNd->FindTableBoxStartNode(); m_xTable->m_bFirstCell = false; @@ -2552,7 +2579,7 @@ const SwStartNode *SwHTMLParser::InsertTableSection else pNd = pPrevStNd->EndOfSectionNode(); SwNodeIndex nIdx( *pNd, 1 ); - pStNd = m_xDoc->GetNodes().MakeTextSection( nIdx, SwTableBoxStartNode, + pStNd = m_xDoc->GetNodes().MakeTextSection( nIdx.GetNode(), SwTableBoxStartNode, pColl ); m_xTable->IncBoxCount(); } @@ -2588,7 +2615,7 @@ const SwStartNode *SwHTMLParser::InsertTableSection( sal_uInt16 nPoolId ) SwTextFormatColl *pColl = m_pCSS1Parser->GetTextCollFromPool( nPoolId ); - SwNode *const pNd = & m_pPam->GetPoint()->nNode.GetNode(); + SwNode *const pNd = & m_pPam->GetPoint()->GetNode(); const SwStartNode *pStNd; if (m_xTable->m_bFirstCell) { @@ -2619,13 +2646,10 @@ const SwStartNode *SwHTMLParser::InsertTableSection( sal_uInt16 nPoolId ) pOutTable = pOutTable->StartOfSectionNode()->FindTableNode(); } while( pOutTable && pTableNd->GetTable().GetHTMLTableLayout() ); } - SwNodeIndex aIdx( *pTableNd->EndOfSectionNode() ); - pStNd = m_xDoc->GetNodes().MakeTextSection( aIdx, SwTableBoxStartNode, + pStNd = m_xDoc->GetNodes().MakeTextSection( *pTableNd->EndOfSectionNode(), SwTableBoxStartNode, pColl ); - m_pPam->GetPoint()->nNode = pStNd->GetIndex() + 1; - SwTextNode *pTextNd = m_pPam->GetPoint()->nNode.GetNode().GetTextNode(); - m_pPam->GetPoint()->nContent.Assign( pTextNd, 0 ); + m_pPam->GetPoint()->Assign( pStNd->GetIndex() + 1 ); m_xTable->IncBoxCount(); } @@ -2640,13 +2664,10 @@ const SwStartNode *SwHTMLParser::InsertTableSection( sal_uInt16 nPoolId ) SwStartNode *SwHTMLParser::InsertTempTableCaptionSection() { SwTextFormatColl *pColl = m_pCSS1Parser->GetTextCollFromPool( RES_POOLCOLL_TEXT ); - SwNodeIndex& rIdx = m_pPam->GetPoint()->nNode; - rIdx = m_xDoc->GetNodes().GetEndOfExtras(); - SwStartNode *pStNd = m_xDoc->GetNodes().MakeTextSection( rIdx, + SwStartNode *pStNd = m_xDoc->GetNodes().MakeTextSection( m_xDoc->GetNodes().GetEndOfExtras(), SwNormalStartNode, pColl ); - rIdx = pStNd->GetIndex() + 1; - m_pPam->GetPoint()->nContent.Assign( rIdx.GetNode().GetTextNode(), 0 ); + m_pPam->GetPoint()->Assign( pStNd->GetIndex() + 1); return pStNd; } @@ -2655,10 +2676,16 @@ sal_Int32 SwHTMLParser::StripTrailingLF() { sal_Int32 nStripped = 0; - const sal_Int32 nLen = m_pPam->GetPoint()->nContent.GetIndex(); + if (IsReqIF()) + { + // One <br> is exactly one line-break in the ReqIF case. + return nStripped; + } + + const sal_Int32 nLen = m_pPam->GetPoint()->GetContentIndex(); if( nLen ) { - SwTextNode* pTextNd = m_pPam->GetPoint()->nNode.GetNode().GetTextNode(); + SwTextNode* pTextNd = m_pPam->GetPoint()->GetNode().GetTextNode(); // careful, when comments aren't ignored!!! if( pTextNd ) { @@ -2681,7 +2708,7 @@ sal_Int32 SwHTMLParser::StripTrailingLF() } nPos = nLen - nLFCount; - SwIndex nIdx( pTextNd, nPos ); + SwContentIndex nIdx( pTextNd, nPos ); pTextNd->EraseText( nIdx, nLFCount ); nStripped = nLFCount; } @@ -2701,8 +2728,7 @@ SvxBrushItem* SwHTMLParser::CreateBrushItem( const Color *pColor, if( !rStyle.isEmpty() || !rId.isEmpty() || !rClass.isEmpty() ) { - SfxItemSet aItemSet( m_xDoc->GetAttrPool(), svl::Items<RES_BACKGROUND, - RES_BACKGROUND>{} ); + SfxItemSetFixed<RES_BACKGROUND, RES_BACKGROUND> aItemSet( m_xDoc->GetAttrPool() ); SvxCSS1PropertyInfo aPropInfo; if( !rClass.isEmpty() ) @@ -2722,11 +2748,9 @@ SvxBrushItem* SwHTMLParser::CreateBrushItem( const Color *pColor, } m_pCSS1Parser->ParseStyleOption( rStyle, aItemSet, aPropInfo ); - const SfxPoolItem *pItem = nullptr; - if( SfxItemState::SET == aItemSet.GetItemState( RES_BACKGROUND, false, - &pItem ) ) + if( const SvxBrushItem *pItem = aItemSet.GetItemIfSet( RES_BACKGROUND, false ) ) { - pBrushItem = new SvxBrushItem( *static_cast<const SvxBrushItem *>(pItem) ); + pBrushItem = new SvxBrushItem( *pItem ); } } @@ -2828,7 +2852,7 @@ class CellSaveStruct : public SectionSaveStruct std::shared_ptr<HTMLTableCnts> m_xCnts; // List of all contents HTMLTableCnts* m_pCurrCnts; // current content or 0 - std::unique_ptr<SwNodeIndex> m_pNoBreakEndNodeIndex; // Paragraph index of a <NOBR> + std::optional<SwNodeIndex> m_oNoBreakEndNodeIndex; // Paragraph index of a <NOBR> double m_nValue; @@ -2902,7 +2926,7 @@ CellSaveStruct::CellSaveStruct( SwHTMLParser& rParser, HTMLTable const *pCurTabl m_aId = rOption.GetString(); break; case HtmlOptionId::COLSPAN: - m_nColSpan = static_cast<sal_uInt16>(rOption.GetNumber()); + m_nColSpan = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); if (m_nColSpan > 256) { SAL_INFO("sw.html", "ignoring huge COLSPAN " << m_nColSpan); @@ -2910,8 +2934,8 @@ CellSaveStruct::CellSaveStruct( SwHTMLParser& rParser, HTMLTable const *pCurTabl } break; case HtmlOptionId::ROWSPAN: - m_nRowSpan = static_cast<sal_uInt16>(rOption.GetNumber()); - if (m_nRowSpan > 8192 || (m_nRowSpan > 256 && utl::ConfigManager::IsFuzzing())) + m_nRowSpan = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); + if (m_nRowSpan > 8192 || (m_nRowSpan > 256 && comphelper::IsFuzzing())) { SAL_INFO("sw.html", "ignoring huge ROWSPAN " << m_nRowSpan); m_nRowSpan = 1; @@ -2924,13 +2948,13 @@ CellSaveStruct::CellSaveStruct( SwHTMLParser& rParser, HTMLTable const *pCurTabl m_eVertOri = rOption.GetEnum( aHTMLTableVAlignTable, m_eVertOri ); break; case HtmlOptionId::WIDTH: - m_nWidth = static_cast<sal_uInt16>(rOption.GetNumber()); // Just for Netscape + m_nWidth = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); // Just for Netscape m_bPercentWidth = (rOption.GetString().indexOf('%') != -1); if( m_bPercentWidth && m_nWidth>100 ) m_nWidth = 100; break; case HtmlOptionId::HEIGHT: - m_nHeight = static_cast<sal_uInt16>(rOption.GetNumber()); // Just for Netscape + m_nHeight = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); // Just for Netscape if( rOption.GetString().indexOf('%') != -1) m_nHeight = 0; // don't consider % attributes break; @@ -3013,10 +3037,9 @@ CellSaveStruct::CellSaveStruct( SwHTMLParser& rParser, HTMLTable const *pCurTabl if( rParser.ParseStyleOptions( m_aStyle, m_aId, m_aClass, aItemSet, aPropInfo, &aLang, &aDir ) ) { - SfxPoolItem const* pItem; - if (SfxItemState::SET == aItemSet.GetItemState(RES_BOX, false, &pItem)) + if (SvxBoxItem const* pItem = aItemSet.GetItemIfSet(RES_BOX, false)) { // fdo#41796: steal box item to set it in FixFrameFormat later! - m_xBoxItem.reset(dynamic_cast<SvxBoxItem *>(pItem->Clone())); + m_xBoxItem.reset(pItem->Clone()); aItemSet.ClearItem(RES_BOX); } rParser.InsertAttrs(aItemSet, aPropInfo, xCntxt.get()); @@ -3081,10 +3104,10 @@ void CellSaveStruct::InsertCell( SwHTMLParser& rParser, void CellSaveStruct::StartNoBreak( const SwPosition& rPos ) { if( !m_xCnts || - (!rPos.nContent.GetIndex() && m_pCurrCnts == m_xCnts.get() && + (!rPos.GetContentIndex() && m_pCurrCnts == m_xCnts.get() && m_xCnts->GetStartNode() && m_xCnts->GetStartNode()->GetIndex() + 1 == - rPos.nNode.GetIndex()) ) + rPos.GetNodeIndex()) ) { m_bNoBreak = true; } @@ -3094,8 +3117,8 @@ void CellSaveStruct::EndNoBreak( const SwPosition& rPos ) { if( m_bNoBreak ) { - m_pNoBreakEndNodeIndex.reset( new SwNodeIndex( rPos.nNode ) ); - m_nNoBreakEndContentPos = rPos.nContent.GetIndex(); + m_oNoBreakEndNodeIndex.emplace( rPos.GetNode() ); + m_nNoBreakEndContentPos = rPos.GetContentIndex(); m_bNoBreak = false; } } @@ -3110,17 +3133,17 @@ void CellSaveStruct::CheckNoBreak( const SwPosition& rPos ) // <NOBR> wasn't closed m_xCnts->SetNoBreak(); } - else if( m_pNoBreakEndNodeIndex && - m_pNoBreakEndNodeIndex->GetIndex() == rPos.nNode.GetIndex() ) + else if( m_oNoBreakEndNodeIndex && + m_oNoBreakEndNodeIndex->GetIndex() == rPos.GetNodeIndex() ) { - if( m_nNoBreakEndContentPos == rPos.nContent.GetIndex() ) + if( m_nNoBreakEndContentPos == rPos.GetContentIndex() ) { // <NOBR> was closed immediately before the cell end m_xCnts->SetNoBreak(); } - else if( m_nNoBreakEndContentPos + 1 == rPos.nContent.GetIndex() ) + else if( m_nNoBreakEndContentPos + 1 == rPos.GetContentIndex() ) { - SwTextNode const*const pTextNd(rPos.nNode.GetNode().GetTextNode()); + SwTextNode const*const pTextNd(rPos.GetNode().GetTextNode()); if( pTextNd ) { sal_Unicode const cLast = @@ -3152,8 +3175,8 @@ std::unique_ptr<HTMLTableCnts> SwHTMLParser::InsertTableContents( } // Reset attributation start - const SwNodeIndex& rSttPara = m_pPam->GetPoint()->nNode; - sal_Int32 nSttCnt = m_pPam->GetPoint()->nContent.GetIndex(); + const SwNode& rSttPara = m_pPam->GetPoint()->GetNode(); + sal_Int32 nSttCnt = m_pPam->GetPoint()->GetContentIndex(); HTMLAttr** pHTMLAttributes = reinterpret_cast<HTMLAttr**>(m_xAttrTab.get()); for (sal_uInt16 nCnt = sizeof(HTMLAttrTable) / sizeof(HTMLAttr*); nCnt--; ++pHTMLAttributes) @@ -3222,19 +3245,15 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, // the table has no content yet, this means the actual table needs // to be created first - static sal_uInt16 aWhichIds[] = - { + SfxItemSetFixed< RES_PARATR_SPLIT, RES_PARATR_SPLIT, RES_PAGEDESC, RES_PAGEDESC, RES_BREAK, RES_BREAK, RES_BACKGROUND, RES_BACKGROUND, RES_KEEP, RES_KEEP, RES_LAYOUT_SPLIT, RES_LAYOUT_SPLIT, - RES_FRAMEDIR, RES_FRAMEDIR, - 0 - }; - - SfxItemSet aItemSet( m_xDoc->GetAttrPool(), aWhichIds ); + RES_FRAMEDIR, RES_FRAMEDIR + > aItemSet( m_xDoc->GetAttrPool() ); SvxCSS1PropertyInfo aPropInfo; bool bStyleParsed = ParseStyleOptions( pCurTable->GetStyle(), @@ -3242,21 +3261,19 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, pCurTable->GetClass(), aItemSet, aPropInfo, nullptr, &pCurTable->GetDirection() ); - const SfxPoolItem *pItem = nullptr; if( bStyleParsed ) { - if( SfxItemState::SET == aItemSet.GetItemState( - RES_BACKGROUND, false, &pItem ) ) + if( const SvxBrushItem* pItem = aItemSet.GetItemIfSet( + RES_BACKGROUND, false ) ) { - pCurTable->SetBGBrush( *static_cast<const SvxBrushItem *>(pItem) ); + pCurTable->SetBGBrush( *pItem ); aItemSet.ClearItem( RES_BACKGROUND ); } - if( SfxItemState::SET == aItemSet.GetItemState( - RES_PARATR_SPLIT, false, &pItem ) ) + if( const SvxFormatSplitItem* pSplitItem = aItemSet.GetItemIfSet( + RES_PARATR_SPLIT, false ) ) { aItemSet.Put( - SwFormatLayoutSplit( static_cast<const SvxFormatSplitItem *>(pItem) - ->GetValue() ) ); + SwFormatLayoutSplit( pSplitItem->GetValue() ) ); aItemSet.ClearItem( RES_PARATR_SPLIT ); } } @@ -3299,13 +3316,13 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, // Otherwise, we need to open a new paragraph if the paragraph // is empty or contains text frames or bookmarks bAppend = - m_pPam->GetPoint()->nContent.GetIndex() || + m_pPam->GetPoint()->GetContentIndex() || HasCurrentParaFlys() || HasCurrentParaBookmarks(); } if( bAppend ) { - if( !m_pPam->GetPoint()->nContent.GetIndex() ) + if( !m_pPam->GetPoint()->GetContentIndex() ) { //Set default to CJK and CTL m_xDoc->SetTextFormatColl( *m_pPam, @@ -3369,10 +3386,10 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, m_nContextStAttrMin ) ); // end all open attributes and open them again behind the table - std::unique_ptr<std::deque<std::unique_ptr<HTMLAttr>>> pPostIts; + std::optional<std::deque<std::unique_ptr<HTMLAttr>>> pPostIts; if( !bForceFrame && (bTopTable || pCurTable->HasParentSection()) ) { - SplitAttrTab(pTCntxt->xAttrTab, bTopTable); + SplitAttrTab(pTCntxt->m_xAttrTab, bTopTable); // If we reuse an already existing paragraph, we can't add // PostIts since the paragraph gets behind that table. // They're gonna be moved into the first paragraph of the table @@ -3380,17 +3397,17 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, // still empty paragraph, since it's not gonna be deleted that way if( (bTopTable && !bAppended) || (!bTopTable && !bParentLFStripped && - !m_pPam->GetPoint()->nContent.GetIndex()) ) - pPostIts.reset(new std::deque<std::unique_ptr<HTMLAttr>>); - SetAttr( bTopTable, bTopTable, pPostIts.get() ); + !m_pPam->GetPoint()->GetContentIndex()) ) + pPostIts.emplace(); + SetAttr( bTopTable, bTopTable, pPostIts ? &*pPostIts : nullptr ); } else { - SaveAttrTab(pTCntxt->xAttrTab); + SaveAttrTab(pTCntxt->m_xAttrTab); if( bTopTable && !bAppended ) { - pPostIts.reset(new std::deque<std::unique_ptr<HTMLAttr>>); - SetAttr( true, true, pPostIts.get() ); + pPostIts.emplace(); + SetAttr( true, true, &*pPostIts ); } } m_bNoParSpace = false; @@ -3406,8 +3423,8 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, { // the table should be put in a text frame - SfxItemSet aFrameSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> + aFrameSet( m_xDoc->GetAttrPool() ); if( !pCurTable->IsNewDoc() ) Reader::ResetFrameFormatAttrs( aFrameSet ); @@ -3434,13 +3451,15 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, true ); aFrameSet.Put( SwFormatSurround(eSurround) ); - SwFormatFrameSize aFrameSize( SwFrameSize::Variable, 20*MM50, MINLAY ); + constexpr tools::Long constTwips_100mm = o3tl::convert(tools::Long(100), o3tl::Length::mm, o3tl::Length::twip); + + SwFormatFrameSize aFrameSize( SwFrameSize::Variable, constTwips_100mm, MINLAY ); aFrameSize.SetWidthPercent( 100 ); aFrameSet.Put( aFrameSize ); sal_uInt16 nSpace = pCurTable->GetHSpace(); if( nSpace ) - aFrameSet.Put( SvxLRSpaceItem(nSpace,nSpace, 0, 0, RES_LR_SPACE) ); + aFrameSet.Put( SvxLRSpaceItem(nSpace, nSpace, 0, RES_LR_SPACE) ); nSpace = pCurTable->GetVSpace(); if( nSpace ) aFrameSet.Put( SvxULSpaceItem(nSpace,nSpace, RES_UL_SPACE) ); @@ -3453,17 +3472,14 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, pTCntxt->SetFrameFormat( pFrameFormat ); const SwFormatContent& rFlyContent = pFrameFormat->GetContent(); - m_pPam->GetPoint()->nNode = *rFlyContent.GetContentIdx(); - SwContentNode *pCNd = - m_xDoc->GetNodes().GoNext( &(m_pPam->GetPoint()->nNode) ); - m_pPam->GetPoint()->nContent.Assign( pCNd, 0 ); - + m_pPam->GetPoint()->Assign( *rFlyContent.GetContentIdx() ); + SwNodes::GoNext(m_pPam->GetPoint()); } // create a SwTable with a box and set the PaM to the content of // the box section (the adjustment parameter is a dummy for now // and will be corrected later) - OSL_ENSURE( !m_pPam->GetPoint()->nContent.GetIndex(), + OSL_ENSURE( !m_pPam->GetPoint()->GetContentIndex(), "The paragraph after the table is not empty!" ); const SwTable* pSwTable = m_xDoc->InsertTable( SwInsertTableOptions( SwInsertTableFlags::HeadlineNoBorder, 1 ), @@ -3472,7 +3488,7 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, if( bForceFrame ) { - SwNodeIndex aDstIdx( m_pPam->GetPoint()->nNode ); + SwNodeIndex aDstIdx( m_pPam->GetPoint()->GetNode() ); m_pPam->Move( fnMoveBackward ); m_xDoc->GetNodes().Delete( aDstIdx ); } @@ -3486,29 +3502,29 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, m_pPam->Move( fnMoveBackward ); } - SwNode const*const pNd = & m_pPam->GetPoint()->nNode.GetNode(); + SwNode const*const pNd = & m_pPam->GetPoint()->GetNode(); SwTextNode *const pOldTextNd = (!bAppended && !bForceFrame) ? - pSavePos->nNode.GetNode().GetTextNode() : nullptr; + pSavePos->GetNode().GetTextNode() : nullptr; if (pFrameFormat && pOldTextNd) { - const SfxPoolItem* pItem2; - if( SfxItemState::SET == pOldTextNd->GetSwAttrSet() - .GetItemState( RES_PAGEDESC, false, &pItem2 ) && - static_cast<const SwFormatPageDesc *>(pItem2)->GetPageDesc() ) + const SwFormatPageDesc* pPageDescItem = pOldTextNd->GetSwAttrSet() + .GetItemIfSet( RES_PAGEDESC, false ); + if( pPageDescItem && pPageDescItem->GetPageDesc() ) { - pFrameFormat->SetFormatAttr( *pItem2 ); + pFrameFormat->SetFormatAttr( *pPageDescItem ); pOldTextNd->ResetAttr( RES_PAGEDESC ); } - if( SfxItemState::SET == pOldTextNd->GetSwAttrSet() - .GetItemState( RES_BREAK, true, &pItem2 ) ) + + if( const SvxFormatBreakItem* pBreakItem = pOldTextNd->GetSwAttrSet() + .GetItemIfSet( RES_BREAK ) ) { - switch( static_cast<const SvxFormatBreakItem *>(pItem2)->GetBreak() ) + switch( pBreakItem->GetBreak() ) { case SvxBreak::PageBefore: case SvxBreak::PageAfter: case SvxBreak::PageBoth: - pFrameFormat->SetFormatAttr( *pItem2 ); + pFrameFormat->SetFormatAttr( *pBreakItem ); pOldTextNd->ResetAttr( RES_BREAK ); break; default: @@ -3554,7 +3570,7 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, } } - SwNode const*const pNd = & m_pPam->GetPoint()->nNode.GetNode(); + SwNode const*const pNd = & m_pPam->GetPoint()->GetNode(); const SwStartNode *pStNd = (m_xTable->m_bFirstCell ? pNd->FindTableNode() : pNd->FindTableBoxStartNode() ); @@ -3839,11 +3855,11 @@ void SwHTMLParser::BuildTableCell( HTMLTable *pCurTable, bool bReadOptions, } // Remove LFs at the paragraph end - if (StripTrailingLF() == 0 && !m_pPam->GetPoint()->nContent.GetIndex()) + if (StripTrailingLF() == 0 && !m_pPam->GetPoint()->GetContentIndex()) { HTMLTableContext* pTableContext = m_xTable ? m_xTable->GetContext() : nullptr; SwPosition* pSavedPos = pTableContext ? pTableContext->GetPos() : nullptr; - const bool bDeleteSafe = !pSavedPos || pSavedPos->nNode != m_pPam->GetPoint()->nNode; + const bool bDeleteSafe = !pSavedPos || pSavedPos->GetNode() != m_pPam->GetPoint()->GetNode(); if (bDeleteSafe) StripTrailingPara(); } @@ -4319,7 +4335,7 @@ void SwHTMLParser::BuildTableColGroup( HTMLTable *pCurTable, InsertBookmark( rOption.GetString() ); break; case HtmlOptionId::SPAN: - pSaveStruct->nColGrpSpan = static_cast<sal_uInt16>(rOption.GetNumber()); + pSaveStruct->nColGrpSpan = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); if (pSaveStruct->nColGrpSpan > 256) { SAL_INFO("sw.html", "ignoring huge SPAN " << pSaveStruct->nColGrpSpan); @@ -4327,7 +4343,7 @@ void SwHTMLParser::BuildTableColGroup( HTMLTable *pCurTable, } break; case HtmlOptionId::WIDTH: - pSaveStruct->nColGrpWidth = static_cast<sal_uInt16>(rOption.GetNumber()); + pSaveStruct->nColGrpWidth = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); pSaveStruct->bRelColGrpWidth = (rOption.GetString().indexOf('*') != -1); break; @@ -4406,7 +4422,7 @@ void SwHTMLParser::BuildTableColGroup( HTMLTable *pCurTable, InsertBookmark( rOption.GetString() ); break; case HtmlOptionId::SPAN: - nColSpan = static_cast<sal_uInt16>(rOption.GetNumber()); + nColSpan = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); if (nColSpan > 256) { SAL_INFO("sw.html", "ignoring huge SPAN " << nColSpan); @@ -4414,7 +4430,7 @@ void SwHTMLParser::BuildTableColGroup( HTMLTable *pCurTable, } break; case HtmlOptionId::WIDTH: - nColWidth = static_cast<sal_uInt16>(rOption.GetNumber()); + nColWidth = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); bRelColWidth = (rOption.GetString().indexOf('*') != -1); break; @@ -4474,25 +4490,25 @@ void SwHTMLParser::BuildTableColGroup( HTMLTable *pCurTable, class CaptionSaveStruct : public SectionSaveStruct { - SwPosition aSavePos; - SwHTMLNumRuleInfo aNumRuleInfo; // valid numbering + SwPosition m_aSavePos; + SwHTMLNumRuleInfo m_aNumRuleInfo; // valid numbering public: - std::shared_ptr<HTMLAttrTable> xAttrTab; // attributes + std::shared_ptr<HTMLAttrTable> m_xAttrTab; // attributes - CaptionSaveStruct( SwHTMLParser& rParser, const SwPosition& rPos ) : - SectionSaveStruct( rParser ), aSavePos( rPos ), - xAttrTab(std::make_shared<HTMLAttrTable>()) + CaptionSaveStruct( SwHTMLParser& rParser, SwPosition aPos ) : + SectionSaveStruct( rParser ), m_aSavePos(std::move( aPos )), + m_xAttrTab(std::make_shared<HTMLAttrTable>()) { - rParser.SaveAttrTab(xAttrTab); + rParser.SaveAttrTab(m_xAttrTab); // The current numbering was remembered and just needs to be closed - aNumRuleInfo.Set( rParser.GetNumInfo() ); + m_aNumRuleInfo.Set( rParser.GetNumInfo() ); rParser.GetNumInfo().Clear(); } - const SwPosition& GetPos() const { return aSavePos; } + const SwPosition& GetPos() const { return m_aSavePos; } void RestoreAll( SwHTMLParser& rParser ) { @@ -4500,10 +4516,10 @@ public: Restore( rParser ); // Recover the old attribute tables - rParser.RestoreAttrTab(xAttrTab); + rParser.RestoreAttrTab(m_xAttrTab); // Re-open the old numbering - rParser.GetNumInfo().Set( aNumRuleInfo ); + rParser.GetNumInfo().Set( m_aNumRuleInfo ); } }; @@ -4660,13 +4676,13 @@ void SwHTMLParser::BuildTableCaption( HTMLTable *pCurTable ) { // On moving the caption later, the last paragraph isn't moved as well. // That means, there has to be an empty paragraph at the end of the section - if( m_pPam->GetPoint()->nContent.GetIndex() || bLFStripped ) + if( m_pPam->GetPoint()->GetContentIndex() || bLFStripped ) AppendTextNode( AM_NOSPACE ); } else { // Strip LFs at the end of the paragraph - if( !m_pPam->GetPoint()->nContent.GetIndex() && !bLFStripped ) + if( !m_pPam->GetPoint()->GetContentIndex() && !bLFStripped ) StripTrailingPara(); } @@ -4694,8 +4710,8 @@ class TableSaveStruct : public SwPendingData public: std::shared_ptr<HTMLTable> m_xCurrentTable; - explicit TableSaveStruct(const std::shared_ptr<HTMLTable>& rCurTable) - : m_xCurrentTable(rCurTable) + explicit TableSaveStruct(std::shared_ptr<HTMLTable> xCurTable) + : m_xCurrentTable(std::move(xCurTable)) { } @@ -4730,9 +4746,9 @@ void TableSaveStruct::MakeTable( sal_uInt16 nWidth, SwPosition& rPos, SwDoc *pDo { pTableNd->DelFrames(); SwNodeIndex aIdx( *pTableNd->EndOfSectionNode(), 1 ); - OSL_ENSURE( aIdx.GetIndex() <= pTCntxt->GetPos()->nNode.GetIndex(), + OSL_ENSURE( aIdx.GetIndex() <= pTCntxt->GetPos()->GetNodeIndex(), "unexpected node for table layout" ); - pTableNd->MakeOwnFrames(&aIdx); + pTableNd->MakeOwnFrames(); } } @@ -4765,24 +4781,24 @@ HTMLTableOptions::HTMLTableOptions( const HTMLOptions& rOptions, aId = rOption.GetString(); break; case HtmlOptionId::COLS: - nCols = static_cast<sal_uInt16>(rOption.GetNumber()); + nCols = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::WIDTH: - nWidth = static_cast<sal_uInt16>(rOption.GetNumber()); + nWidth = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); bPercentWidth = (rOption.GetString().indexOf('%') != -1); if( bPercentWidth && nWidth>100 ) nWidth = 100; break; case HtmlOptionId::HEIGHT: - nHeight = static_cast<sal_uInt16>(rOption.GetNumber()); + nHeight = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); if( rOption.GetString().indexOf('%') != -1 ) nHeight = 0; // don't use % attributes break; case HtmlOptionId::CELLPADDING: - nCellPadding = static_cast<sal_uInt16>(rOption.GetNumber()); + nCellPadding = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::CELLSPACING: - nCellSpacing = static_cast<sal_uInt16>(rOption.GetNumber()); + nCellSpacing = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::ALIGN: { @@ -4801,7 +4817,7 @@ HTMLTableOptions::HTMLTableOptions( const HTMLOptions& rOptions, !rOption.GetString().equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_O_border)) { - nBorder = static_cast<sal_uInt16>(rOption.GetNumber()); + nBorder = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); } else nBorder = 1; @@ -4849,10 +4865,10 @@ HTMLTableOptions::HTMLTableOptions( const HTMLOptions& rOptions, aDir = rOption.GetString(); break; case HtmlOptionId::HSPACE: - nHSpace = static_cast<sal_uInt16>(rOption.GetNumber()); + nHSpace = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::VSPACE: - nVSpace = static_cast<sal_uInt16>(rOption.GetNumber()); + nVSpace = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; default: break; } @@ -4872,86 +4888,13 @@ HTMLTableOptions::HTMLTableOptions( const HTMLOptions& rOptions, } } -namespace -{ - class IndexInRange - { - private: - SwNodeIndex maStart; - SwNodeIndex maEnd; - public: - explicit IndexInRange(const SwNodeIndex& rStart, const SwNodeIndex& rEnd) - : maStart(rStart) - , maEnd(rEnd) - { - } - bool operator()(const SwHTMLTextFootnote& rTextFootnote) const - { - const SwNodeIndex aTextIdx(rTextFootnote.pTextFootnote->GetTextNode()); - return aTextIdx >= maStart && aTextIdx <= maEnd; - } - }; -} - -void SwHTMLParser::ClearFootnotesMarksInRange(const SwNodeIndex& rMkNdIdx, const SwNodeIndex& rPtNdIdx) -{ - //similarly for footnotes - if (m_pFootEndNoteImpl) - { - m_pFootEndNoteImpl->aTextFootnotes.erase(std::remove_if(m_pFootEndNoteImpl->aTextFootnotes.begin(), - m_pFootEndNoteImpl->aTextFootnotes.end(), IndexInRange(rMkNdIdx, rPtNdIdx)), m_pFootEndNoteImpl->aTextFootnotes.end()); - if (m_pFootEndNoteImpl->aTextFootnotes.empty()) - { - m_pFootEndNoteImpl.reset(); - } - } - - //follow DelFlyInRange pattern here - assert(rMkNdIdx.GetIndex() <= rPtNdIdx.GetIndex()); - - SwDoc& rDoc = rMkNdIdx.GetNode().GetDoc(); - - //ofz#9733 drop bookmarks in this range - IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess(); - pMarkAccess->deleteMarks(rMkNdIdx, SwNodeIndex(rPtNdIdx, 1), nullptr, nullptr, nullptr); - - SwFrameFormats& rTable = *rDoc.GetSpzFrameFormats(); - for ( auto i = rTable.size(); i; ) - { - SwFrameFormat *pFormat = rTable[--i]; - const SwFormatAnchor &rAnch = pFormat->GetAnchor(); - SwPosition const*const pAPos = rAnch.GetContentAnchor(); - if (pAPos && - ((rAnch.GetAnchorId() == RndStdIds::FLY_AT_PARA) || - (rAnch.GetAnchorId() == RndStdIds::FLY_AT_CHAR)) && - ( rMkNdIdx < pAPos->nNode && pAPos->nNode <= rPtNdIdx )) - { - if( rPtNdIdx != pAPos->nNode ) - { - // If the Fly is deleted, all Flys in its content have to be deleted too. - const SwFormatContent &rContent = pFormat->GetContent(); - // But only fly formats own their content, not draw formats. - if (rContent.GetContentIdx() && pFormat->Which() == RES_FLYFRMFMT) - { - ClearFootnotesMarksInRange(*rContent.GetContentIdx(), - SwNodeIndex(*rContent.GetContentIdx()->GetNode().EndOfSectionNode())); - } - } - } - } -} - void SwHTMLParser::DeleteSection(SwStartNode* pSttNd) { //if section to be deleted contains a pending m_pMarquee, it will be deleted //so clear m_pMarquee pointer if that's the case - SwFrameFormat* pObjectFormat = m_pMarquee ? ::FindFrameFormat(m_pMarquee) : nullptr; + SwFrameFormat* pObjectFormat = m_pMarquee ? ::FindFrameFormat(m_pMarquee.get()) : nullptr; FrameDeleteWatch aWatch(pObjectFormat); - //similarly for footnotes - SwNodeIndex aSttIdx(*pSttNd), aEndIdx(*pSttNd->EndOfSectionNode()); - ClearFootnotesMarksInRange(aSttIdx, aEndIdx); - m_xDoc->getIDocumentContentOperations().DeleteSection(pSttNd); if (pObjectFormat) @@ -4993,6 +4936,35 @@ std::shared_ptr<HTMLTable> SwHTMLParser::BuildTable(SvxAdjust eParentAdjust, else { m_xTable.reset(); + + // Parse CSS on the table. + OUString aStyle; + const HTMLOptions& rHTMLOptions = GetOptions(); + for (size_t i = rHTMLOptions.size(); i;) + { + const HTMLOption& rOption = rHTMLOptions[--i]; + if (rOption.GetToken() == HtmlOptionId::STYLE) + { + aStyle = rOption.GetString(); + } + } + if (!aStyle.isEmpty()) + { + // Have inline CSS. + SfxItemSet aItemSet(m_xDoc->GetAttrPool(), m_pCSS1Parser->GetWhichMap()); + SvxCSS1PropertyInfo aPropInfo; + if (ParseStyleOptions(aStyle, /*aId=*/OUString(), /*aClass=*/OUString(), aItemSet, + aPropInfo)) + { + if (aPropInfo.m_eLeftMarginType == SVX_CSS1_LTYPE_AUTO + && aPropInfo.m_eRightMarginType == SVX_CSS1_LTYPE_AUTO) + { + // Both left & right is set to auto: that's our center. + eParentAdjust = SvxAdjust::Center; + } + } + } + HTMLTableOptions aTableOptions(GetOptions(), eParentAdjust); if (!aTableOptions.aId.isEmpty()) @@ -5139,37 +5111,40 @@ std::shared_ptr<HTMLTable> SwHTMLParser::BuildTable(SvxAdjust eParentAdjust, // The last paragraph of the section is never part of the copy. // That's why the section needs to contain at least two paragraphs - if( pCapStNd->EndOfSectionIndex() - pCapStNd->GetIndex() > 2 ) + if( pCapStNd->EndOfSectionIndex() - pCapStNd->GetIndex() > SwNodeOffset(2) ) { // Don't copy start node and the last paragraph - SwNodeRange aSrcRg( *pCapStNd, 1, - *pCapStNd->EndOfSectionNode(), -1 ); + SwNodeRange aSrcRg( *pCapStNd, SwNodeOffset(1), + *pCapStNd->EndOfSectionNode(), SwNodeOffset(-1) ); bool bTop = m_xTable->IsTopCaption(); SwStartNode *pTableStNd = pTCntxt->GetTableNode(); OSL_ENSURE( pTableStNd, "Where is the table node" ); - OSL_ENSURE( pTableStNd==m_pPam->GetNode().FindTableNode(), + OSL_ENSURE( pTableStNd == m_pPam->GetPointNode().FindTableNode(), "Are we in the wrong table?" ); - SwNode* pNd; - if( bTop ) - pNd = pTableStNd; - else - pNd = pTableStNd->EndOfSectionNode(); - SwNodeIndex aDstIdx( *pNd, bTop ? 0 : 1 ); - - m_xDoc->getIDocumentContentOperations().MoveNodeRange( aSrcRg, aDstIdx, - SwMoveFlags::DEFAULT ); - - // If the caption was added before the table, a page style on that table - // needs to be moved to the first paragraph of the header. - // Additionally, all remembered indices that point to the table node - // need to be moved - if( bTop ) + if (pTableStNd) { - MovePageDescAttrs( pTableStNd, aSrcRg.aStart.GetIndex(), - false ); + SwNode* pNd; + if( bTop ) + pNd = pTableStNd; + else + pNd = pTableStNd->EndOfSectionNode(); + SwNodeIndex aDstIdx( *pNd, bTop ? 0 : 1 ); + + m_xDoc->getIDocumentContentOperations().MoveNodeRange( aSrcRg, aDstIdx.GetNode(), + SwMoveFlags::DEFAULT ); + + // If the caption was added before the table, a page style on that table + // needs to be moved to the first paragraph of the header. + // Additionally, all remembered indices that point to the table node + // need to be moved + if( bTop ) + { + MovePageDescAttrs( pTableStNd, aSrcRg.aStart.GetIndex(), + false ); + } } } @@ -5181,13 +5156,13 @@ std::shared_ptr<HTMLTable> SwHTMLParser::BuildTable(SvxAdjust eParentAdjust, } // Process SwTable - sal_uInt16 nBrowseWidth = static_cast<sal_uInt16>(GetCurrentBrowseWidth()); + sal_uInt16 nBrowseWidth = o3tl::narrowing<sal_uInt16>(GetCurrentBrowseWidth()); xSaveStruct->MakeTable(nBrowseWidth, *m_pPam->GetPoint(), m_xDoc.get()); } GetNumInfo().Set( pTCntxt->GetNumInfo() ); pTCntxt->RestorePREListingXMP( *this ); - RestoreAttrTab(pTCntxt->xAttrTab); + RestoreAttrTab(pTCntxt->m_xAttrTab); if (m_xTable == xCurTable) { @@ -5243,51 +5218,4 @@ std::shared_ptr<HTMLTable> SwHTMLParser::BuildTable(SvxAdjust eParentAdjust, return xRetTable; } -bool HTMLTable::PendingDrawObjectsInPaM(SwPaM& rPam) const -{ - if (!m_pResizeDrawObjects) - return false; - - bool bRet = false; - - sal_uInt16 nCount = m_pResizeDrawObjects->size(); - for (sal_uInt16 i = 0; i < nCount && !bRet; ++i) - { - SdrObject *pObj = (*m_pResizeDrawObjects)[i]; - SwFrameFormat* pObjectFormat = ::FindFrameFormat(pObj); - if (!pObjectFormat) - continue; - const SwFormatAnchor& rAnch = pObjectFormat->GetAnchor(); - if (const SwPosition* pPos = rAnch.GetContentAnchor()) - { - SwNodeIndex aObjNodeIndex(pPos->nNode); - bRet = (aObjNodeIndex >= rPam.Start()->nNode && aObjNodeIndex <= rPam.End()->nNode); - } - } - - return bRet; -} - -bool SwHTMLParser::PendingObjectsInPaM(SwPaM& rPam) const -{ - bool bRet = false; - for (const auto& a : m_aTables) - { - bRet = a->PendingDrawObjectsInPaM(rPam); - if (bRet) - break; - const SwTable *pTable = a->GetSwTable(); - if (!pTable) - continue; - const SwTableNode* pTableNode = pTable->GetTableNode(); - if (!pTableNode) - continue; - SwNodeIndex aTableNodeIndex(*pTableNode); - bRet = (aTableNodeIndex >= rPam.Start()->nNode && aTableNodeIndex <= rPam.End()->nNode); - if (bRet) - break; - } - return bRet; -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/filter/html/htmltabw.cxx b/sw/source/filter/html/htmltabw.cxx index 4c83319747b7..b1ef282396a0 100644 --- a/sw/source/filter/html/htmltabw.cxx +++ b/sw/source/filter/html/htmltabw.cxx @@ -63,12 +63,20 @@ class SwHTMLWrtTable : public SwWriteTable static void Pixelize( sal_uInt16& rValue ); void PixelizeBorders(); + /// Writes a single table cell. + /// + /// bCellRowSpan decides if the cell's row span should be written or not. void OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell, - bool bOutVAlign ) const; + bool bOutVAlign, + bool bCellRowSpan ) const; + /// Writes a single table row. + /// + /// rSkipRows decides if the next N rows should be skipped or written. void OutTableCells( SwHTMLWriter& rWrt, const SwWriteTableCells& rCells, - const SvxBrushItem *pBrushItem ) const; + const SvxBrushItem *pBrushItem, + sal_uInt16& rSkipRows ) const; virtual bool ShouldExpandSub( const SwTableBox *pBox, bool bExpandedBefore, sal_uInt16 nDepth ) const override; @@ -111,14 +119,9 @@ SwHTMLWrtTable::SwHTMLWrtTable( const SwHTMLTableLayout *pLayoutInfo ) void SwHTMLWrtTable::Pixelize( sal_uInt16& rValue ) { - if( rValue && Application::GetDefaultDevice() ) + if( rValue ) { - Size aSz( rValue, 0 ); - aSz = Application::GetDefaultDevice()->LogicToPixel( aSz, MapMode(MapUnit::MapTwip) ); - if( !aSz.Width() ) - aSz.setWidth( 1 ); - aSz = Application::GetDefaultDevice()->PixelToLogic( aSz, MapMode(MapUnit::MapTwip) ); - rValue = static_cast<sal_uInt16>(aSz.Width()); + rValue = o3tl::convert(SwHTMLWriter::ToPixel(rValue), o3tl::Length::px, o3tl::Length::twip); } } @@ -143,8 +146,8 @@ bool SwHTMLWrtTable::HasTabBackground( const SwTableBox& rBox, /// The table box has a background, if its background color is not "no fill"/ /// "auto fill" or it has a background graphic. - bRet = aBrushItem && (aBrushItem->GetColor() != COL_TRANSPARENT || - !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic()); + bRet = aBrushItem->GetColor() != COL_TRANSPARENT || + !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic(); } else { @@ -172,8 +175,8 @@ bool SwHTMLWrtTable::HasTabBackground( const SwTableLine& rLine, std::unique_ptr<SvxBrushItem> aBrushItem = rLine.GetFrameFormat()->makeBackgroundBrushItem(); /// The table line has a background, if its background color is not "no fill"/ /// "auto fill" or it has a background graphic. - bool bRet = aBrushItem && (aBrushItem->GetColor() != COL_TRANSPARENT || - !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic()); + bool bRet = aBrushItem->GetColor() != COL_TRANSPARENT || + !aBrushItem->GetGraphicLink().isEmpty() || aBrushItem->GetGraphic(); if( !bRet ) { @@ -254,7 +257,8 @@ bool SwHTMLWrtTable::ShouldExpandSub( const SwTableBox *pBox, // Write a box as single cell void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, const SwWriteTableCell *pCell, - bool bOutVAlign ) const + bool bOutVAlign, + bool bCellRowSpan ) const { const SwTableBox *pBox = pCell->GetBox(); sal_uInt16 nRow = pCell->GetRow(); @@ -269,7 +273,7 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, bool bHead = false; if( pSttNd ) { - sal_uLong nNdPos = pSttNd->GetIndex()+1; + SwNodeOffset nNdPos = pSttNd->GetIndex()+1; // determine the type of cell (TD/TH) SwNode* pNd; @@ -301,21 +305,20 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, } rWrt.OutNewLine(); // <TH>/<TD> in new line - OStringBuffer sOut; - sOut.append('<'); + OStringBuffer sOut("<"); OString aTag(bHead ? OOO_STRING_SVTOOLS_HTML_tableheader : OOO_STRING_SVTOOLS_HTML_tabledata); sOut.append(rWrt.GetNamespace() + aTag); // output ROW- and COLSPAN - if( nRowSpan>1 ) + if (nRowSpan > 1 && bCellRowSpan) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_rowspan). - append("=\"").append(static_cast<sal_Int32>(nRowSpan)).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_rowspan + "=\"" + OString::number(nRowSpan) + "\""); } if( nColSpan > 1 ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_colspan). - append("=\"").append(static_cast<sal_Int32>(nColSpan)).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_colspan + "=\"" + OString::number(nColSpan) + "\""); } tools::Long nWidth = 0; @@ -350,28 +353,15 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, tools::Long nHeight = pCell->GetHeight() > 0 ? GetAbsHeight( pCell->GetHeight(), nRow, nRowSpan ) : 0; - Size aPixelSz( nWidth, nHeight ); - - // output WIDTH (Argh: only for Netscape) - if( (aPixelSz.Width() || aPixelSz.Height()) && Application::GetDefaultDevice() ) - { - Size aOldSz( aPixelSz ); - aPixelSz = Application::GetDefaultDevice()->LogicToPixel( aPixelSz, - MapMode(MapUnit::MapTwip) ); - if( aOldSz.Width() && !aPixelSz.Width() ) - aPixelSz.setWidth( 1 ); - if( aOldSz.Height() && !aPixelSz.Height() ) - aPixelSz.setHeight( 1 ); - } + Size aPixelSz(SwHTMLWriter::ToPixel(nWidth), SwHTMLWriter::ToPixel(nHeight)); // output WIDTH: from layout or calculated if( bOutWidth ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_width). - append("=\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\""); if( nPercentWidth != SAL_MAX_UINT32 ) { - sOut.append(static_cast<sal_Int32>(nPercentWidth)).append('%'); + sOut.append(OString::number(static_cast<sal_Int32>(nPercentWidth)) + "%"); } else { @@ -380,14 +370,19 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, sOut.append("\""); } + if (rWrt.mbReqIF) + { + // ReqIF implies strict XHTML: no height for <td>. + nHeight = 0; + } + if( nHeight ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_height) - .append("=\"").append(static_cast<sal_Int32>(aPixelSz.Height())).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_height + "=\"" + OString::number(aPixelSz.Height()) + "\""); } const SfxItemSet& rItemSet = pBox->GetFrameFormat()->GetAttrSet(); - const SfxPoolItem *pItem; // ALIGN is only outputted at the paragraphs from now on @@ -397,23 +392,20 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, sal_Int16 eVertOri = pCell->GetVertOri(); if( text::VertOrientation::TOP==eVertOri || text::VertOrientation::BOTTOM==eVertOri ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_valign) - .append("=\"").append(text::VertOrientation::TOP==eVertOri ? + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_valign + "=\"").append(text::VertOrientation::TOP==eVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom) .append("\""); } } - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); rWrt.m_bTextAttr = false; rWrt.m_bOutOpts = true; - const SvxBrushItem *pBrushItem = nullptr; - if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) ) - { - pBrushItem = static_cast<const SvxBrushItem *>(pItem); - } + const SvxBrushItem *pBrushItem = rItemSet.GetItemIfSet( RES_BACKGROUND, false ); if( !pBrushItem ) pBrushItem = pCell->GetBackground(); @@ -424,37 +416,40 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, // Avoid non-CSS version in the ReqIF case. rWrt.OutBackground( pBrushItem, false ); - if( rWrt.m_bCfgOutStyles ) - OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem ); + if (!rWrt.m_bCfgOutStyles) + pBrushItem = nullptr; } - rWrt.OutCSS1_TableCellBorderHack(*pBox->GetFrameFormat()); + // tdf#132739 with rWrt.m_bCfgOutStyles of true bundle the brush item css + // properties into the same "style" tag as the borders so there is only one + // style tag + rWrt.OutCSS1_TableCellBordersAndBG(*pBox->GetFrameFormat(), pBrushItem); sal_uInt32 nNumFormat = 0; double nValue = 0.0; bool bNumFormat = false, bValue = false; - if( SfxItemState::SET==rItemSet.GetItemState( RES_BOXATR_FORMAT, false, &pItem ) ) + if( const SwTableBoxNumFormat* pItem = rItemSet.GetItemIfSet( RES_BOXATR_FORMAT, false ) ) { - nNumFormat = static_cast<const SwTableBoxNumFormat *>(pItem)->GetValue(); + nNumFormat = pItem->GetValue(); bNumFormat = true; } - if( SfxItemState::SET==rItemSet.GetItemState( RES_BOXATR_VALUE, false, &pItem ) ) + if( const SwTableBoxValue* pItem = rItemSet.GetItemIfSet( RES_BOXATR_VALUE, false ) ) { - nValue = static_cast<const SwTableBoxValue *>(pItem)->GetValue(); + nValue = pItem->GetValue(); bValue = true; if( !bNumFormat ) nNumFormat = pBox->GetFrameFormat()->GetTableBoxNumFormat().GetValue(); } - if( bNumFormat || bValue ) + if ((bNumFormat || bValue) && !rWrt.mbXHTML) { sOut.append(HTMLOutFuncs::CreateTableDataOptionsValNum(bValue, nValue, - nNumFormat, *rWrt.m_pDoc->GetNumberFormatter(), rWrt.m_eDestEnc, - &rWrt.m_aNonConvertableCharacters)); + nNumFormat, *rWrt.m_pDoc->GetNumberFormatter())); } sOut.append('>'); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - rWrt.m_bLFPossible = true; + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + rWrt.SetLFPossible(true); rWrt.IncIndentLevel(); // indent the content of <TD>...</TD> @@ -491,17 +486,18 @@ void SwHTMLWrtTable::OutTableCell( SwHTMLWriter& rWrt, rWrt.DecIndentLevel(); // indent the content of <TD>...</TD> - if( rWrt.m_bLFPossible ) + if (rWrt.IsLFPossible()) rWrt.OutNewLine(); aTag = bHead ? OOO_STRING_SVTOOLS_HTML_tableheader : OOO_STRING_SVTOOLS_HTML_tabledata; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rWrt.GetNamespace() + aTag, false); - rWrt.m_bLFPossible = true; + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); + rWrt.SetLFPossible(true); } // output a line as lines void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt, const SwWriteTableCells& rCells, - const SvxBrushItem *pBrushItem ) const + const SvxBrushItem *pBrushItem, + sal_uInt16& rSkipRows ) const { // If the line contains more the one cell and all cells have the same // alignment, then output the VALIGN at the line instead of the cell. @@ -524,39 +520,60 @@ void SwHTMLWrtTable::OutTableCells( SwHTMLWriter& rWrt, } rWrt.OutNewLine(); // <TR> in new line - rWrt.Strm().WriteChar( '<' ).WriteOString( rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow ); + rWrt.Strm().WriteChar( '<' ).WriteOString( Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow) ); if( pBrushItem ) { - rWrt.OutBackground( pBrushItem, false ); + if (!rWrt.mbXHTML) + { + rWrt.OutBackground(pBrushItem, false); + } rWrt.m_bTextAttr = false; rWrt.m_bOutOpts = true; - if( rWrt.m_bCfgOutStyles ) + if (rWrt.m_bCfgOutStyles || rWrt.mbXHTML) OutCSS1_TableBGStyleOpt( rWrt, *pBrushItem ); } if( text::VertOrientation::TOP==eRowVertOri || text::VertOrientation::BOTTOM==eRowVertOri ) { OStringBuffer sOut; - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_valign) - .append("=\"").append(text::VertOrientation::TOP==eRowVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom) + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_valign + "=\"").append(text::VertOrientation::TOP==eRowVertOri ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom) .append("\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); } rWrt.Strm().WriteChar( '>' ); rWrt.IncIndentLevel(); // indent content of <TR>...</TR> + bool bCellRowSpan = true; + if (!rCells.empty() && rCells[0]->GetRowSpan() > 1) + { + // Skip the rowspan attrs of <td> elements if they are the same for every cell of this row. + bCellRowSpan = std::adjacent_find(rCells.begin(), rCells.end(), + [](const std::unique_ptr<SwWriteTableCell>& pA, + const std::unique_ptr<SwWriteTableCell>& pB) + { return pA->GetRowSpan() != pB->GetRowSpan(); }) + != rCells.end(); + if (!bCellRowSpan) + { + // If no rowspan is written, then skip rows which would only contain covered cells, but + // not the current row. + rSkipRows = rCells[0]->GetRowSpan() - 1; + } + } + for (const auto &rpCell : rCells) { - OutTableCell(rWrt, rpCell.get(), text::VertOrientation::NONE == eRowVertOri); + OutTableCell(rWrt, rpCell.get(), text::VertOrientation::NONE == eRowVertOri, bCellRowSpan); } rWrt.DecIndentLevel(); // indent content of <TR>...</TR> rWrt.OutNewLine(); // </TR> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow), false ); } void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, @@ -567,143 +584,124 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, // determine value of RULES bool bRowsHaveBorder = false; bool bRowsHaveBorderOnly = true; - SwWriteTableRow *pRow = m_aRows[0].get(); - for( SwWriteTableRows::size_type nRow=1; nRow < m_aRows.size(); ++nRow ) + assert(m_aRows.begin() != m_aRows.end()); + for (auto row = m_aRows.begin(), next = std::next(row); next < m_aRows.end(); ++row, ++next) { - SwWriteTableRow *pNextRow = m_aRows[nRow].get(); - bool bBorder = ( pRow->bBottomBorder || pNextRow->bTopBorder ); + SwWriteTableRow* pRow = row->get(); + SwWriteTableRow* pNextRow = next->get(); + bool bBorder = ( pRow->HasBottomBorder() || pNextRow->HasTopBorder() ); bRowsHaveBorder |= bBorder; bRowsHaveBorderOnly &= bBorder; - sal_uInt16 nBorder2 = pRow->bBottomBorder ? pRow->nBottomBorder : USHRT_MAX; - if( pNextRow->bTopBorder && pNextRow->nTopBorder < nBorder2 ) - nBorder2 = pNextRow->nTopBorder; - - pRow->bBottomBorder = bBorder; - pRow->nBottomBorder = nBorder2; - - pNextRow->bTopBorder = bBorder; - pNextRow->nTopBorder = nBorder2; - - pRow = pNextRow; + pRow->SetBottomBorder(bBorder); + pNextRow->SetTopBorder(bBorder); } bool bColsHaveBorder = false; bool bColsHaveBorderOnly = true; - SwWriteTableCol *pCol = m_aCols[0].get(); - for( SwWriteTableCols::size_type nCol=1; nCol<m_aCols.size(); ++nCol ) + assert(m_aCols.begin() != m_aCols.end()); + for (auto col = m_aCols.begin(), next = std::next(col); next < m_aCols.end(); ++col, ++next) { - SwWriteTableCol *pNextCol = m_aCols[nCol].get(); - bool bBorder = ( pCol->bRightBorder || pNextCol->bLeftBorder ); + SwWriteTableCol* pCol = col->get(); + SwWriteTableCol* pNextCol = next->get(); + bool bBorder = ( pCol->m_bRightBorder || pNextCol->m_bLeftBorder ); bColsHaveBorder |= bBorder; bColsHaveBorderOnly &= bBorder; - pCol->bRightBorder = bBorder; - pNextCol->bLeftBorder = bBorder; - pCol = pNextCol; + pCol->m_bRightBorder = bBorder; + pNextCol->m_bLeftBorder = bBorder; } // close previous numbering, etc rWrt.ChangeParaToken( HtmlTokenId::NONE ); - if( rWrt.m_bLFPossible ) + if (rWrt.IsLFPossible()) rWrt.OutNewLine(); // <TABLE> in new line - OStringBuffer sOut; - sOut.append('<').append(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table); + OStringBuffer sOut("<" + rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table); const SvxFrameDirection nOldDirection = rWrt.m_nDirection; if( pFrameFormat ) rWrt.m_nDirection = rWrt.GetHTMLDirection( pFrameFormat->GetAttrSet() ); if( rWrt.m_bOutFlyFrame || nOldDirection != rWrt.m_nDirection ) { - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); rWrt.OutDirection( rWrt.m_nDirection ); } // output ALIGN= if( text::HoriOrientation::RIGHT == eAlign ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align). - append("=\"").append(OOO_STRING_SVTOOLS_HTML_AL_right).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align + "=\"" OOO_STRING_SVTOOLS_HTML_AL_right "\""); } else if( text::HoriOrientation::CENTER == eAlign ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align). - append("=\"").append(OOO_STRING_SVTOOLS_HTML_AL_center).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align + "=\"" OOO_STRING_SVTOOLS_HTML_AL_center "\""); } else if( text::HoriOrientation::LEFT == eAlign ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align). - append("=\"").append(OOO_STRING_SVTOOLS_HTML_AL_left).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_align + "=\"" OOO_STRING_SVTOOLS_HTML_AL_left "\""); } // output WIDTH: from layout or calculated if( m_nTabWidth ) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_width). - append("=\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_width "=\""); if( HasRelWidths() ) - sOut.append(static_cast<sal_Int32>(m_nTabWidth)).append('%'); - else if( Application::GetDefaultDevice() ) - { - sal_Int32 nPixWidth = Application::GetDefaultDevice()->LogicToPixel( - Size(m_nTabWidth,0), MapMode(MapUnit::MapTwip) ).Width(); - if( !nPixWidth ) - nPixWidth = 1; - - sOut.append(nPixWidth); - } + sOut.append(OString::number(static_cast<sal_Int32>(m_nTabWidth)) + "%"); else { - OSL_ENSURE( Application::GetDefaultDevice(), "no Application-Window!?" ); - sOut.append("100%"); + sal_Int32 nPixWidth = SwHTMLWriter::ToPixel(m_nTabWidth); + sOut.append(nPixWidth); } sOut.append("\""); } - if( (nHSpace || nVSpace) && Application::GetDefaultDevice()) + if( (nHSpace || nVSpace) && !rWrt.mbReqIF) { - Size aPixelSpc = - Application::GetDefaultDevice()->LogicToPixel( Size(nHSpace,nVSpace), - MapMode(MapUnit::MapTwip) ); - if( !aPixelSpc.Width() && nHSpace ) - aPixelSpc.setWidth( 1 ); - if( !aPixelSpc.Height() && nVSpace ) - aPixelSpc.setHeight( 1 ); - - if( aPixelSpc.Width() ) + if (auto nPixHSpace = SwHTMLWriter::ToPixel(nHSpace)) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_hspace). - append("=\"").append(static_cast<sal_Int32>(aPixelSpc.Width())).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_hspace + "=\"" + OString::number(nPixHSpace) + "\""); } - if( aPixelSpc.Height() ) + if (auto nPixVSpace = SwHTMLWriter::ToPixel(nVSpace)) { - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_vspace). - append("=\"").append(static_cast<sal_Int32>(aPixelSpc.Height())).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_vspace + "=\"" + OString::number(nPixVSpace) + "\""); } } // output CELLPADDING: from layout or calculated - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_cellpadding). - append("=\"").append(static_cast<sal_Int32>(SwHTMLWriter::ToPixel(m_nCellPadding,false))).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellpadding + "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellPadding)) + "\""); // output CELLSPACING: from layout or calculated - sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_cellspacing). - append("=\"").append(static_cast<sal_Int32>(SwHTMLWriter::ToPixel(m_nCellSpacing,false))).append("\""); + sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_cellspacing + "=\"" + OString::number(SwHTMLWriter::ToPixel(m_nCellSpacing)) + "\""); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); // output background if( pFrameFormat ) { - rWrt.OutBackground( pFrameFormat->GetAttrSet(), false ); + if (!rWrt.mbXHTML) + { + rWrt.OutBackground(pFrameFormat->GetAttrSet(), false); + } - if (rWrt.m_bCfgOutStyles) + if (rWrt.m_bCfgOutStyles || rWrt.mbXHTML) + { rWrt.OutCSS1_TableFrameFormatOptions( *pFrameFormat ); + } } sOut.append('>'); - rWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); rWrt.IncIndentLevel(); // indent content of table @@ -712,16 +710,14 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, { rWrt.OutNewLine(); // <CAPTION> in new line OStringBuffer sOutStr(OOO_STRING_SVTOOLS_HTML_caption); - sOutStr.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_align).append("=\"") + sOutStr.append(" " OOO_STRING_SVTOOLS_HTML_O_align "=\"") .append(bTopCaption ? OOO_STRING_SVTOOLS_HTML_VA_top : OOO_STRING_SVTOOLS_HTML_VA_bottom) .append("\""); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + sOutStr.getStr() ); - HTMLOutFuncs::Out_String( rWrt.Strm(), *pCaption, rWrt.m_eDestEnc, &rWrt.m_aNonConvertableCharacters ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_caption, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOutStr) ); + HTMLOutFuncs::Out_String( rWrt.Strm(), *pCaption ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_caption), false ); } - const SwWriteTableCols::size_type nCols = m_aCols.size(); - // output <COLGRP>/<COL>: If exporting via layout only when during import // some were there, otherwise always. bool bColGroups = (bColsHaveBorder && !bColsHaveBorderOnly); @@ -730,11 +726,12 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, if( bColGroups ) { rWrt.OutNewLine(); // <COLGRP> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) ); rWrt.IncIndentLevel(); // indent content of <COLGRP> } + const SwWriteTableCols::size_type nCols = m_aCols.size(); for( SwWriteTableCols::size_type nCol=0; nCol<nCols; ++nCol ) { rWrt.OutNewLine(); // </COL> in new line @@ -742,7 +739,8 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, const SwWriteTableCol *pColumn = m_aCols[nCol].get(); HtmlWriter html(rWrt.Strm(), rWrt.maNamespace); - html.start(OOO_STRING_SVTOOLS_HTML_col); + html.prettyPrint(false); // We add newlines ourself + html.start(OOO_STRING_SVTOOLS_HTML_col ""_ostr); sal_uInt32 nWidth; bool bRel; @@ -758,19 +756,19 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, } if( bRel ) - html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OString::number(nWidth) + "*"); + html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, Concat2View(OString::number(nWidth) + "*")); else - html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OString::number(SwHTMLWriter::ToPixel(nWidth,false))); + html.attribute(OOO_STRING_SVTOOLS_HTML_O_width, OString::number(SwHTMLWriter::ToPixel(nWidth))); html.end(); - if( bColGroups && pColumn->bRightBorder && nCol<nCols-1 ) + if( bColGroups && pColumn->m_bRightBorder && nCol<nCols-1 ) { rWrt.DecIndentLevel(); // indent content of <COLGRP> rWrt.OutNewLine(); // </COLGRP> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup, + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup), false ); rWrt.OutNewLine(); // <COLGRP> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup) ); rWrt.IncIndentLevel(); // indent content of <COLGRP> } } @@ -779,7 +777,7 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, rWrt.DecIndentLevel(); // indent content of <COLGRP> rWrt.OutNewLine(); // </COLGRP> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup, + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_colgroup), false ); } } @@ -794,7 +792,7 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, // can be outputted if there is a line below the cell. if( bTHead && (bTSections || bColGroups) && - m_nHeadEndRow<m_aRows.size()-1 && !m_aRows[m_nHeadEndRow]->bBottomBorder ) + m_nHeadEndRow<m_aRows.size()-1 && !m_aRows[m_nHeadEndRow]->HasBottomBorder() ) bTHead = false; // Output <TBODY> only if <THEAD> is outputted. @@ -804,42 +802,39 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, { rWrt.OutNewLine(); // <THEAD>/<TDATA> in new line OString aTag = bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rWrt.GetNamespace() + aTag); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag)); rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA> } + sal_uInt16 nSkipRows = 0; for( SwWriteTableRows::size_type nRow = 0; nRow < m_aRows.size(); ++nRow ) { - const SwWriteTableRow *pRow2 = m_aRows[nRow].get(); + const SwWriteTableRow *pRow = m_aRows[nRow].get(); - OutTableCells( rWrt, pRow2->GetCells(), pRow2->GetBackground() ); - if( !m_nCellSpacing && nRow < m_aRows.size()-1 && pRow2->bBottomBorder && - pRow2->nBottomBorder > DEF_LINE_WIDTH_1 ) + if (nSkipRows == 0) { - for( auto nCnt = (pRow2->nBottomBorder / DEF_LINE_WIDTH_1) - 1; nCnt; --nCnt ) - { - rWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow ); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_tablerow, - false ); - } + OutTableCells(rWrt, pRow->GetCells(), pRow->GetBackground(), nSkipRows); + } + else + { + --nSkipRows; } if( ( (bTHead && nRow==m_nHeadEndRow) || - (bTBody && pRow2->bBottomBorder) ) && + (bTBody && pRow->HasBottomBorder()) ) && nRow < m_aRows.size()-1 ) { rWrt.DecIndentLevel(); // indent content of <THEAD>/<TDATA> rWrt.OutNewLine(); // </THEAD>/</TDATA> in new line OString aTag = bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rWrt.GetNamespace() + aTag, false); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); rWrt.OutNewLine(); // <THEAD>/<TDATA> in new line if( bTHead && nRow==m_nHeadEndRow ) bTHead = false; aTag = bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rWrt.GetNamespace() + aTag); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag)); rWrt.IncIndentLevel(); // indent content of <THEAD>/<TDATA> } } @@ -850,26 +845,25 @@ void SwHTMLWrtTable::Write( SwHTMLWriter& rWrt, sal_Int16 eAlign, rWrt.OutNewLine(); // </THEAD>/</TDATA> in new line OString aTag = bTHead ? OOO_STRING_SVTOOLS_HTML_thead : OOO_STRING_SVTOOLS_HTML_tbody; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rWrt.GetNamespace() + aTag, false); + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); } rWrt.DecIndentLevel(); // indent content of <TABLE> rWrt.OutNewLine(); // </TABLE> in new line - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table, false ); + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_table), false ); rWrt.m_nDirection = nOldDirection; } -Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, +SwHTMLWriter& OutHTML_SwTableNode( SwHTMLWriter& rWrt, SwTableNode & rNode, const SwFrameFormat *pFlyFrameFormat, const OUString *pCaption, bool bTopCaption ) { SwTable& rTable = rNode.GetTable(); - SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - rHTMLWrt.m_bOutTable = true; + rWrt.m_bOutTable = true; // The horizontal alignment of the frame (if exists) has priority. // NONE means that no horizontal alignment was outputted. @@ -899,11 +893,11 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, // maybe open a FORM bool bPreserveForm = false; - if( !rHTMLWrt.m_bPreserveForm ) + if( !rWrt.m_bPreserveForm ) { - rHTMLWrt.OutForm( true, &rNode ); - bPreserveForm = rHTMLWrt.mxFormComps.is(); - rHTMLWrt.m_bPreserveForm = bPreserveForm; + rWrt.OutForm( true, &rNode ); + bPreserveForm = rWrt.mxFormComps.is(); + rWrt.m_bPreserveForm = bPreserveForm; } SwFrameFormat *pFormat = rTable.GetFrameFormat(); @@ -911,7 +905,7 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, const SwFormatFrameSize& rFrameSize = pFormat->GetFrameSize(); tools::Long nWidth = rFrameSize.GetSize().Width(); sal_uInt8 nPercentWidth = rFrameSize.GetWidthPercent(); - sal_uInt16 nBaseWidth = static_cast<sal_uInt16>(nWidth); + sal_uInt16 nBaseWidth = o3tl::narrowing<sal_uInt16>(nWidth); sal_Int16 eTabHoriOri = pFormat->GetHoriOrient().GetHoriOrient(); @@ -976,38 +970,31 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, break; } - if( bCheckDefList ) + // In ReqIF case, do not emulate indentation with fake description list + if( bCheckDefList && !rWrt.mbReqIF ) { - OSL_ENSURE( !rHTMLWrt.GetNumInfo().GetNumRule() || - rHTMLWrt.GetNextNumInfo(), + OSL_ENSURE( !rWrt.GetNumInfo().GetNumRule() || + rWrt.GetNextNumInfo(), "NumInfo for next paragraph is missing!" ); const SvxLRSpaceItem& aLRItem = pFormat->GetLRSpace(); - if( aLRItem.GetLeft() > 0 && rHTMLWrt.m_nDefListMargin > 0 && - ( !rHTMLWrt.GetNumInfo().GetNumRule() || - ( rHTMLWrt.GetNextNumInfo() && - (rHTMLWrt.GetNextNumInfo()->IsRestart() || - rHTMLWrt.GetNumInfo().GetNumRule() != - rHTMLWrt.GetNextNumInfo()->GetNumRule()) ) ) ) + if( aLRItem.GetLeft() > 0 && rWrt.m_nDefListMargin > 0 && + ( !rWrt.GetNumInfo().GetNumRule() || + ( rWrt.GetNextNumInfo() && + (rWrt.GetNumInfo().GetNumRule() != rWrt.GetNextNumInfo()->GetNumRule() || + rWrt.GetNextNumInfo()->IsRestart(rWrt.GetNumInfo())) ) ) ) { // If the paragraph before the table is not numbered or the // paragraph after the table starts with a new numbering or with // a different rule, we can maintain the indentation with a DL. // Otherwise we keep the indentation of the numbering. nNewDefListLvl = static_cast< sal_uInt16 >( - (aLRItem.GetLeft() + (rHTMLWrt.m_nDefListMargin/2)) / - rHTMLWrt.m_nDefListMargin ); + (aLRItem.GetLeft() + (rWrt.m_nDefListMargin/2)) / + rWrt.m_nDefListMargin ); } } - if( !pFlyFrameFormat && nNewDefListLvl != rHTMLWrt.m_nDefListLvl ) - rHTMLWrt.OutAndSetDefList( nNewDefListLvl ); - - if( nNewDefListLvl ) - { - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_dd ); - } + if( !pFlyFrameFormat && !rWrt.mbReqIF && nNewDefListLvl != rWrt.m_nDefListLvl ) + rWrt.OutAndSetDefList( nNewDefListLvl ); // eFlyHoriOri and eTabHoriOri now only contain the values of // LEFT/CENTER and RIGHT! @@ -1056,28 +1043,44 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, nFlyHSpace = nFlyVSpace = 0; if( !pFormat->GetName().isEmpty() ) - rHTMLWrt.OutImplicitMark( pFormat->GetName(), "table" ); + rWrt.OutImplicitMark( pFormat->GetName(), "table" ); if( text::HoriOrientation::NONE!=eDivHoriOri ) { - if( rHTMLWrt.m_bLFPossible ) - rHTMLWrt.OutNewLine(); // <CENTER> in new line + if (rWrt.IsLFPossible()) + rWrt.OutNewLine(); // <CENTER> in new line if( text::HoriOrientation::CENTER==eDivHoriOri ) - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_center ); + { + if (!rWrt.mbXHTML) + { + // Not XHTML's css center: start <center>. + HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_center) ); + } + } else { - OString sOut = OOO_STRING_SVTOOLS_HTML_division - " " OOO_STRING_SVTOOLS_HTML_O_align "=\"" - OOO_STRING_SVTOOLS_HTML_AL_right "\""; - HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + sOut.getStr() ); + if (rWrt.mbReqIF) + { + // In ReqIF, div cannot have an 'align' attribute. For now, use 'style' only + // for ReqIF; maybe it makes sense to use it in both cases? + static constexpr char sOut[] = OOO_STRING_SVTOOLS_HTML_division + " style=\"display: flex; flex-direction: column; align-items: flex-end\""; + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOut)); + } + else + { + static constexpr char sOut[] = OOO_STRING_SVTOOLS_HTML_division + " " OOO_STRING_SVTOOLS_HTML_O_align "=\"" OOO_STRING_SVTOOLS_HTML_AL_right "\""; + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + sOut)); + } } - rHTMLWrt.IncIndentLevel(); // indent content of <CENTER> - rHTMLWrt.m_bLFPossible = true; + rWrt.IncIndentLevel(); // indent content of <CENTER> + rWrt.SetLFPossible(true); } // If the table isn't in a frame, then you always can output a LF. if( text::HoriOrientation::NONE==eTabHoriOri ) - rHTMLWrt.m_bLFPossible = true; + rWrt.SetLFPossible(true); const SwHTMLTableLayout *pLayout = rTable.GetHTMLTableLayout(); @@ -1092,7 +1095,7 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, if( pLayout && pLayout->IsExportable() ) { SwHTMLWrtTable aTableWrt( pLayout ); - aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0, + aTableWrt.Write( rWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0, pFormat, pCaption, bTopCaption, nFlyHSpace, nFlyVSpace ); } @@ -1100,49 +1103,52 @@ Writer& OutHTML_SwTableNode( Writer& rWrt, SwTableNode & rNode, { SwHTMLWrtTable aTableWrt( rTable.GetTabLines(), nWidth, nBaseWidth, bRelWidths, 0, 0, rTable.GetRowsToRepeat() ); - aTableWrt.Write( rHTMLWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0, + aTableWrt.Write( rWrt, eTabHoriOri, rTable.GetRowsToRepeat() > 0, pFormat, pCaption, bTopCaption, nFlyHSpace, nFlyVSpace ); } // If the table wasn't in a frame, then you always can output a LF. if( text::HoriOrientation::NONE==eTabHoriOri ) - rHTMLWrt.m_bLFPossible = true; + rWrt.SetLFPossible(true); if( text::HoriOrientation::NONE!=eDivHoriOri ) { - rHTMLWrt.DecIndentLevel(); // indent content of <CENTER> - rHTMLWrt.OutNewLine(); // </CENTER> in new line + rWrt.DecIndentLevel(); // indent content of <CENTER> + rWrt.OutNewLine(); // </CENTER> in new line OString aTag = text::HoriOrientation::CENTER == eDivHoriOri ? OOO_STRING_SVTOOLS_HTML_center : OOO_STRING_SVTOOLS_HTML_division; - HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), rHTMLWrt.GetNamespace() + aTag, false); - rHTMLWrt.m_bLFPossible = true; + if (!rWrt.mbXHTML || eDivHoriOri != text::HoriOrientation::CENTER) + { + // Not XHTML's css center: end <center>. + HTMLOutFuncs::Out_AsciiTag(rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false); + } + rWrt.SetLFPossible(true); } // move Pam behind the table - rHTMLWrt.m_pCurrentPam->GetPoint()->nNode = *rNode.EndOfSectionNode(); + rWrt.m_pCurrentPam->GetPoint()->Assign( *rNode.EndOfSectionNode() ); if( bPreserveForm ) { - rHTMLWrt.m_bPreserveForm = false; - rHTMLWrt.OutForm( false ); + rWrt.m_bPreserveForm = false; + rWrt.OutForm( false ); } - rHTMLWrt.m_bOutTable = false; + rWrt.m_bOutTable = false; - if( rHTMLWrt.GetNextNumInfo() && - !rHTMLWrt.GetNextNumInfo()->IsRestart() && - rHTMLWrt.GetNextNumInfo()->GetNumRule() == - rHTMLWrt.GetNumInfo().GetNumRule() ) + if( rWrt.GetNextNumInfo() && + rWrt.GetNextNumInfo()->GetNumRule() == rWrt.GetNumInfo().GetNumRule() && + !rWrt.GetNextNumInfo()->IsRestart(rWrt.GetNumInfo()) ) { // If the paragraph after the table is numbered with the same rule as the // one before, then the NumInfo of the next paragraph holds the level of // paragraph before the table. Therefore NumInfo must be fetched again // to maybe close the Num list. - rHTMLWrt.ClearNextNumInfo(); - rHTMLWrt.FillNextNumInfo(); - OutHTML_NumberBulletListEnd( rHTMLWrt, *rHTMLWrt.GetNextNumInfo() ); + rWrt.ClearNextNumInfo(); + rWrt.FillNextNumInfo(); + OutHTML_NumberBulletListEnd( rWrt, *rWrt.GetNextNumInfo() ); } return rWrt; } diff --git a/sw/source/filter/html/parcss1.cxx b/sw/source/filter/html/parcss1.cxx index 39038ab8b91c..a32de72ab52f 100644 --- a/sw/source/filter/html/parcss1.cxx +++ b/sw/source/filter/html/parcss1.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <o3tl/string_view.hxx> +#include <o3tl/unit_conversion.hxx> #include <osl/diagnose.h> #include <rtl/character.hxx> #include <rtl/ustrbuf.hxx> @@ -373,92 +375,67 @@ CSS1Token CSS1Parser::GetNextToken() // save current position sal_Int32 nInPosOld = m_nInPos; sal_Unicode cNextChOld = m_cNextCh; - sal_uLong nlLineNrOld = m_nlLineNr; - sal_uLong nlLinePosOld = m_nlLinePos; + sal_uInt32 nlLineNrOld = m_nlLineNr; + sal_uInt32 nlLinePosOld = m_nlLinePos; bool bEOFOld = m_bEOF; // parse the next identifier - OUString aIdent; OUStringBuffer sTmpBuffer2(64); do { - sTmpBuffer2.append( m_cNextCh ); + sTmpBuffer2.append(static_cast<sal_Unicode>(rtl::toAsciiLowerCase(m_cNextCh))); m_cNextCh = GetNextChar(); } while( (rtl::isAsciiAlphanumeric(m_cNextCh) || '-' == m_cNextCh) && !IsEOF() ); - aIdent += sTmpBuffer2; + OUString aIdent = sTmpBuffer2.makeStringAndClear(); + nRet = CSS1_NUMBER; // Is it a unit? - const char *pCmp1 = nullptr, *pCmp2 = nullptr, *pCmp3 = nullptr; - double nScale1 = 1., nScale2 = 1.; - CSS1Token nToken1 = CSS1_LENGTH, - nToken2 = CSS1_LENGTH, - nToken3 = CSS1_LENGTH; switch( aIdent[0] ) { case 'c': - case 'C': - pCmp1 = "cm"; - nScale1 = (72.*20.)/2.54; // twip + if (aIdent == "cm") + { + m_nValue = o3tl::convert(m_nValue, o3tl::Length::cm, o3tl::Length::twip); + nRet = CSS1_LENGTH; + } break; case 'e': - case 'E': - pCmp1 = "em"; - nToken1 = CSS1_EMS; - - pCmp2 = "ex"; - nToken2 = CSS1_EMX; + if (aIdent == "em") + nRet = CSS1_EMS; + else if (aIdent == "ex") + nRet = CSS1_EMX; break; case 'i': - case 'I': - pCmp1 = "in"; - nScale1 = 72.*20.; // twip + if (aIdent == "in") + { + nRet = CSS1_LENGTH; + m_nValue = o3tl::convert(m_nValue, o3tl::Length::in, o3tl::Length::twip); + } break; case 'm': - case 'M': - pCmp1 = "mm"; - nScale1 = (72.*20.)/25.4; // twip + if (aIdent == "mm") + { + nRet = CSS1_LENGTH; + m_nValue = o3tl::convert(m_nValue, o3tl::Length::mm, o3tl::Length::twip); + } break; case 'p': - case 'P': - pCmp1 = "pt"; - nScale1 = 20.; // twip - - pCmp2 = "pc"; - nScale2 = 12.*20.; // twip - - pCmp3 = "px"; - nToken3 = CSS1_PIXLENGTH; + if (aIdent == "pt") + { + nRet = CSS1_LENGTH; + m_nValue = o3tl::convert(m_nValue, o3tl::Length::pt, o3tl::Length::twip); + } + else if (aIdent == "pc") + { + nRet = CSS1_LENGTH; + m_nValue = o3tl::convert(m_nValue, o3tl::Length::pc, o3tl::Length::twip); + } + else if (aIdent == "px") + nRet = CSS1_PIXLENGTH; break; } - double nScale = 0.0; - OSL_ENSURE( pCmp1, "Where does the first digit come from?" ); - if( aIdent.equalsIgnoreAsciiCaseAscii( pCmp1 ) ) - { - nScale = nScale1; - nRet = nToken1; - } - else if( pCmp2 && - aIdent.equalsIgnoreAsciiCaseAscii( pCmp2 ) ) - { - nScale = nScale2; - nRet = nToken2; - } - else if( pCmp3 && - aIdent.equalsIgnoreAsciiCaseAscii( pCmp3 ) ) - { - nScale = 1.; // nScale3 - nRet = nToken3; - } - else - { - nRet = CSS1_NUMBER; - } - - if( CSS1_LENGTH==nRet && nScale!=1.0 ) - m_nValue *= nScale; - if( nRet == CSS1_NUMBER ) { m_nInPos = nInPosOld; @@ -524,16 +501,16 @@ CSS1Token CSS1Parser::GetNextToken() // save current position sal_Int32 nInPosSave = m_nInPos; sal_Unicode cNextChSave = m_cNextCh; - sal_uLong nlLineNrSave = m_nlLineNr; - sal_uLong nlLinePosSave = m_nlLinePos; + sal_uInt32 nlLineNrSave = m_nlLineNr; + sal_uInt32 nlLinePosSave = m_nlLinePos; bool bEOFSave = m_bEOF; // first try to parse a hex digit - OUStringBuffer sTmpBuffer(6); + OUStringBuffer sTmpBuffer(8); do { sTmpBuffer.append( m_cNextCh ); m_cNextCh = GetNextChar(); - } while( sTmpBuffer.getLength() < 7 && + } while( sTmpBuffer.getLength() < 9 && ( ('0'<=m_cNextCh && '9'>=m_cNextCh) || ('A'<=m_cNextCh && 'F'>=m_cNextCh) || ('a'<=m_cNextCh && 'f'>=m_cNextCh) ) && @@ -541,7 +518,7 @@ CSS1Token CSS1Parser::GetNextToken() if( sTmpBuffer.getLength()==6 || sTmpBuffer.getLength()==3 ) { - // we found a color in hex + // we found a color in hex (RGB) m_aToken += sTmpBuffer; nRet = CSS1_HEXCOLOR; bNextCh = false; @@ -549,6 +526,26 @@ CSS1Token CSS1Parser::GetNextToken() break; } + if( sTmpBuffer.getLength()==8 ) + { + // we found a color in hex (RGBA) + // we convert it to RGB assuming white background + sal_uInt32 nColor = sTmpBuffer.makeStringAndClear().toUInt32(16); + sal_uInt32 nRed = (nColor & 0xff000000) >> 24; + sal_uInt32 nGreen = (nColor & 0xff0000) >> 16; + sal_uInt32 nBlue = (nColor & 0xff00) >> 8; + double nAlpha = (nColor & 0xff) / 255.0; + nRed = (1 - nAlpha) * 255 + nAlpha * nRed; + nGreen = (1 - nAlpha) * 255 + nAlpha * nGreen; + nBlue = (1 - nAlpha) * 255 + nAlpha * nBlue; + nColor = (nRed << 16) + (nGreen << 8) + nBlue; + m_aToken += OUString::number(nColor, 16); + nRet = CSS1_HEXCOLOR; + bNextCh = false; + + break; + } + // otherwise we try a number m_nInPos = nInPosSave; m_cNextCh = cNextChSave; @@ -612,7 +609,8 @@ CSS1Token CSS1Parser::GetNextToken() ( (('u'==m_aToken[0] || 'U'==m_aToken[0]) && m_aToken.equalsIgnoreAsciiCase( "url" )) || (('r'==m_aToken[0] || 'R'==m_aToken[0]) && - m_aToken.equalsIgnoreAsciiCase( "rgb" )) ) ) + (m_aToken.equalsIgnoreAsciiCase( "rgb" ) || m_aToken.equalsIgnoreAsciiCase( "rgba" ) ) + ) ) ) { int nNestCnt = 0; OUStringBuffer sTmpBuffer2(64); @@ -1200,7 +1198,7 @@ void CSS1Parser::DeclarationParsed( const OUString& /*rProperty*/, CSS1Selector::~CSS1Selector() { - delete pNext; + delete m_pNext; } CSS1Expression::~CSS1Expression() @@ -1247,25 +1245,31 @@ bool CSS1Expression::GetColor( Color &rColor ) const { case CSS1_RGB: { - sal_uInt8 aColors[3] = { 0, 0, 0 }; + // fourth value to 255 means no alpha transparency + // so the right by default value + sal_uInt8 aColors[4] = { 0, 0, 0, 255 }; + // it can be "rgb" or "rgba" if (!aValue.startsWithIgnoreAsciiCase( "rgb" ) || aValue.getLength() < 6 || - aValue[3] != '(' || aValue[aValue.getLength()-1] != ')') + (aValue[3] != '(' && aValue[4] != '(' ) || aValue[aValue.getLength()-1] != ')') { break; } - sal_Int32 nPos = 4; // start after "rgb(" - for ( int nCol = 0; nCol < 3 && nPos > 0; ++nCol ) + sal_Int32 nPos = aValue.startsWithIgnoreAsciiCase( "rgba" )?5:4; // start after "rgba(" or "rgb(" + char cSep = (aValue.indexOf(',') != -1)?',':' '; + // alpha value can be after a "/" or "," + bool bIsSepAlphaDiv = (aValue.indexOf('/') != -1)?true:false; + for ( int nCol = 0; nCol < 4 && nPos > 0; ++nCol ) { - const OUString aNumber = aValue.getToken(0, ',', nPos); + const std::u16string_view aNumber = o3tl::getToken(aValue, 0, cSep, nPos); - sal_Int32 nNumber = aNumber.toInt32(); + sal_Int32 nNumber = o3tl::toInt32(aNumber); if( nNumber<0 ) { nNumber = 0; } - else if( aNumber.indexOf('%') >= 0 ) + else if( aNumber.find('%') != std::u16string_view::npos ) { if( nNumber > 100 ) nNumber = 100; @@ -1274,13 +1278,25 @@ bool CSS1Expression::GetColor( Color &rColor ) const } else if( nNumber > 255 ) nNumber = 255; - + else if( aNumber.find('.') != std::u16string_view::npos ) + { + // in this case aNumber contains something like "0.3" so not an sal_Int32 + nNumber = static_cast<sal_Int32>(255.0*o3tl::toDouble(aNumber)); + } aColors[nCol] = static_cast<sal_uInt8>(nNumber); + // rgb with alpha and '/' has this form: rgb(255 0 0 / 50%) + if (bIsSepAlphaDiv && nCol == 2) + { + // but there can be some spaces or not before and after the "/", so skip them + while (aValue[nPos] == '/' || aValue[nPos] == ' ') + ++nPos; + } } rColor.SetRed( aColors[0] ); rColor.SetGreen( aColors[1] ); rColor.SetBlue( aColors[2] ); + rColor.SetAlpha( aColors[3] ); bRet = true; // something different than a colour isn't possible } diff --git a/sw/source/filter/html/parcss1.hxx b/sw/source/filter/html/parcss1.hxx index 6e2d50426d4c..99f46af8e830 100644 --- a/sw/source/filter/html/parcss1.hxx +++ b/sw/source/filter/html/parcss1.hxx @@ -24,6 +24,7 @@ #include <tools/color.hxx> #include <memory> +#include <utility> // tokens of the CSS1 parser enum CSS1Token @@ -90,22 +91,22 @@ enum CSS1SelectorType */ class CSS1Selector { - CSS1SelectorType eType; // the type - OUString aSelector; // the selector itself - CSS1Selector *pNext; // the following component + CSS1SelectorType m_eType; // the type + OUString m_aSelector; // the selector itself + CSS1Selector *m_pNext; // the following component public: - CSS1Selector( CSS1SelectorType eTyp, const OUString &rSel ) - : eType(eTyp), aSelector( rSel ), pNext( nullptr ) + CSS1Selector( CSS1SelectorType eTyp, OUString aSel ) + : m_eType(eTyp), m_aSelector(std::move( aSel )), m_pNext( nullptr ) {} ~CSS1Selector(); - CSS1SelectorType GetType() const { return eType; } - const OUString& GetString() const { return aSelector; } + CSS1SelectorType GetType() const { return m_eType; } + const OUString& GetString() const { return m_aSelector; } - void SetNext( CSS1Selector *pNxt ) { pNext = pNxt; } - const CSS1Selector *GetNext() const { return pNext; } + void SetNext( CSS1Selector *pNxt ) { m_pNext = pNxt; } + const CSS1Selector *GetNext() const { return m_pNext; } }; /** a subexpression of a CSS1 declaration @@ -117,6 +118,7 @@ public: */ struct CSS1Expression { +private: sal_Unicode cOp; // type of the link with its predecessor CSS1Token eType; // type of the expression OUString aValue; // value as string @@ -124,9 +126,9 @@ struct CSS1Expression CSS1Expression *pNext; // the following component public: - CSS1Expression( CSS1Token eTyp, const OUString &rVal, + CSS1Expression( CSS1Token eTyp, OUString aVal, double nVal, sal_Unicode cO = 0 ) - : cOp(cO), eType(eTyp), aValue(rVal), nValue(nVal), pNext(nullptr) + : cOp(cO), eType(eTyp), aValue(std::move(aVal)), nValue(nVal), pNext(nullptr) {} ~CSS1Expression(); diff --git a/sw/source/filter/html/svxcss1.cxx b/sw/source/filter/html/svxcss1.cxx index 9ff8244ca50b..d186fc295796 100644 --- a/sw/source/filter/html/svxcss1.cxx +++ b/sw/source/filter/html/svxcss1.cxx @@ -19,7 +19,9 @@ #include <sal/config.h> +#include <algorithm> #include <cmath> +#include <limits> #include <memory> #include <stdlib.h> @@ -50,17 +52,18 @@ #include <editeng/widwitem.hxx> #include <editeng/frmdiritem.hxx> #include <editeng/orphitem.hxx> -#include <svtools/svparser.hxx> +#include <utility> #include <vcl/svapp.hxx> #include <sal/log.hxx> #include <osl/diagnose.h> +#include <o3tl/string_view.hxx> + +#include <hintids.hxx> #include "css1kywd.hxx" #include "svxcss1.hxx" #include "htmlnum.hxx" -#include <utility> - using namespace ::com::sun::star; /// type of functions to parse CSS1 properties @@ -244,12 +247,11 @@ CSS1PropertyEnum const aBulletStyleTable[] = { nullptr, 0 } }; - sal_uInt16 const aBorderWidths[] = { - DEF_LINE_WIDTH_0, - DEF_LINE_WIDTH_5, - DEF_LINE_WIDTH_1 + SvxBorderLineWidth::Hairline, + SvxBorderLineWidth::VeryThin, + SvxBorderLineWidth::Thin }; #undef SBORDER_ENTRY @@ -285,8 +287,8 @@ struct SvxCSS1ItemIds sal_uInt16 nOrphans; sal_uInt16 nFormatSplit; - sal_uInt16 nLRSpace; - sal_uInt16 nULSpace; + // this looks a bit superfluous? TypedWhichId<SvxLRSpaceItem> nLRSpace{0}; + TypedWhichId<SvxULSpaceItem> nULSpace{0}; sal_uInt16 nBox; sal_uInt16 nBrush; @@ -400,6 +402,8 @@ SvxCSS1PropertyInfo::SvxCSS1PropertyInfo( const SvxCSS1PropertyInfo& rProp ) : m_eTopType( rProp.m_eTopType ), m_eWidthType( rProp.m_eWidthType ), m_eHeightType( rProp.m_eHeightType ), + m_eLeftMarginType( rProp.m_eLeftMarginType ), + m_eRightMarginType( rProp.m_eRightMarginType ), m_eSizeType( rProp.m_eSizeType ), m_ePageBreakBefore( rProp.m_ePageBreakBefore ), m_ePageBreakAfter( rProp.m_ePageBreakAfter ) @@ -439,6 +443,8 @@ void SvxCSS1PropertyInfo::Clear() m_nLeft = m_nTop = m_nWidth = m_nHeight = 0; m_eLeftType = m_eTopType = m_eWidthType = m_eHeightType = SVX_CSS1_LTYPE_NONE; + m_eLeftMarginType = SVX_CSS1_LTYPE_NONE; + m_eRightMarginType = SVX_CSS1_LTYPE_NONE; // Feature: PrintExt m_eSizeType = SVX_CSS1_STYPE_NONE; @@ -661,10 +667,10 @@ void SvxCSS1PropertyInfo::SetBoxItem( SfxItemSet& rItemSet, DestroyBorderInfos(); } -SvxCSS1MapEntry::SvxCSS1MapEntry( const SfxItemSet& rItemSet, +SvxCSS1MapEntry::SvxCSS1MapEntry( SfxItemSet aItemSet, const SvxCSS1PropertyInfo& rProp ) : - aItemSet( rItemSet ), - aPropInfo( rProp ) + m_aItemSet(std::move( aItemSet )), + m_aPropInfo( rProp ) {} void SvxCSS1Parser::StyleParsed( const CSS1Selector * /*pSelector*/, @@ -678,14 +684,14 @@ void SvxCSS1Parser::SelectorParsed( std::unique_ptr<CSS1Selector> pSelector, boo { if( bFirst ) { - OSL_ENSURE( pSheetItemSet, "Where is the Item-Set for Style-Sheets?" ); + OSL_ENSURE( m_pSheetItemSet, "Where is the Item-Set for Style-Sheets?" ); for (const std::unique_ptr<CSS1Selector> & rpSelection : m_Selectors) { - StyleParsed(rpSelection.get(), *pSheetItemSet, *pSheetPropInfo); + StyleParsed(rpSelection.get(), *m_pSheetItemSet, *m_pSheetPropInfo); } - pSheetItemSet->ClearItem(); - pSheetPropInfo->Clear(); + m_pSheetItemSet->ClearItem(); + m_pSheetPropInfo->Clear(); // prepare the next rule m_Selectors.clear(); @@ -694,66 +700,73 @@ void SvxCSS1Parser::SelectorParsed( std::unique_ptr<CSS1Selector> pSelector, boo m_Selectors.push_back(std::move(pSelector)); } -SvxCSS1Parser::SvxCSS1Parser( SfxItemPool& rPool, const OUString& rBaseURL, +SvxCSS1Parser::SvxCSS1Parser( SfxItemPool& rPool, OUString aBaseURL, sal_uInt16 const *pWhichIds, sal_uInt16 nWhichIds ) : - CSS1Parser(), - sBaseURL( rBaseURL ), - pItemSet(nullptr), - pPropInfo( nullptr ), - eDfltEnc( RTL_TEXTENCODING_DONTKNOW ), - bIgnoreFontFamily( false ) + m_sBaseURL(std::move( aBaseURL )), + m_pItemSet(nullptr), + m_pPropInfo( nullptr ), + m_eDefaultEnc( RTL_TEXTENCODING_DONTKNOW ), + m_bIgnoreFontFamily( false ) { // also initialize item IDs - aItemIds.nFont = rPool.GetTrueWhich( SID_ATTR_CHAR_FONT, false ); - aItemIds.nFontCJK = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_FONT, false ); - aItemIds.nFontCTL = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_FONT, false ); - aItemIds.nPosture = rPool.GetTrueWhich( SID_ATTR_CHAR_POSTURE, false ); - aItemIds.nPostureCJK = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_POSTURE, false ); - aItemIds.nPostureCTL = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_POSTURE, false ); - aItemIds.nWeight = rPool.GetTrueWhich( SID_ATTR_CHAR_WEIGHT, false ); - aItemIds.nWeightCJK = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_WEIGHT, false ); - aItemIds.nWeightCTL = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_WEIGHT, false ); - aItemIds.nFontHeight = rPool.GetTrueWhich( SID_ATTR_CHAR_FONTHEIGHT, false ); - aItemIds.nFontHeightCJK = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT, false ); - aItemIds.nFontHeightCTL = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT, false ); - aItemIds.nUnderline = rPool.GetTrueWhich( SID_ATTR_CHAR_UNDERLINE, false ); - aItemIds.nOverline = rPool.GetTrueWhich( SID_ATTR_CHAR_OVERLINE, false ); - aItemIds.nCrossedOut = rPool.GetTrueWhich( SID_ATTR_CHAR_STRIKEOUT, false ); - aItemIds.nColor = rPool.GetTrueWhich( SID_ATTR_CHAR_COLOR, false ); - aItemIds.nKerning = rPool.GetTrueWhich( SID_ATTR_CHAR_KERNING, false ); - aItemIds.nCaseMap = rPool.GetTrueWhich( SID_ATTR_CHAR_CASEMAP, false ); - aItemIds.nBlink = rPool.GetTrueWhich( SID_ATTR_FLASH, false ); - - aItemIds.nLineSpacing = rPool.GetTrueWhich( SID_ATTR_PARA_LINESPACE, false ); - aItemIds.nAdjust = rPool.GetTrueWhich( SID_ATTR_PARA_ADJUST, false ); - aItemIds.nWidows = rPool.GetTrueWhich( SID_ATTR_PARA_WIDOWS, false ); - aItemIds.nOrphans = rPool.GetTrueWhich( SID_ATTR_PARA_ORPHANS, false ); - aItemIds.nFormatSplit = rPool.GetTrueWhich( SID_ATTR_PARA_SPLIT, false ); - - aItemIds.nLRSpace = rPool.GetTrueWhich( SID_ATTR_LRSPACE, false ); - aItemIds.nULSpace = rPool.GetTrueWhich( SID_ATTR_ULSPACE, false ); - aItemIds.nBox = rPool.GetTrueWhich( SID_ATTR_BORDER_OUTER, false ); - aItemIds.nBrush = rPool.GetTrueWhich( SID_ATTR_BRUSH, false ); - - aItemIds.nLanguage = rPool.GetTrueWhich( SID_ATTR_CHAR_LANGUAGE, false ); - aItemIds.nLanguageCJK = rPool.GetTrueWhich( SID_ATTR_CHAR_CJK_LANGUAGE, false ); - aItemIds.nLanguageCTL = rPool.GetTrueWhich( SID_ATTR_CHAR_CTL_LANGUAGE, false ); - aItemIds.nDirection = rPool.GetTrueWhich( SID_ATTR_FRAMEDIRECTION, false ); - - aWhichMap.insert( aWhichMap.begin(), 0 ); - BuildWhichTable( aWhichMap, reinterpret_cast<sal_uInt16 *>(&aItemIds), - sizeof(aItemIds) / sizeof(sal_uInt16) ); + auto initTrueWhich = [&rPool, this](sal_uInt16 rWid) + { + rWid = rPool.GetTrueWhichIDFromSlotID(rWid, false); + m_aWhichMap = m_aWhichMap.MergeRange(rWid, rWid); + return rWid; + }; + + aItemIds.nFont = initTrueWhich( SID_ATTR_CHAR_FONT ); + aItemIds.nFontCJK = initTrueWhich( SID_ATTR_CHAR_CJK_FONT ); + aItemIds.nFontCTL = initTrueWhich( SID_ATTR_CHAR_CTL_FONT ); + aItemIds.nPosture = initTrueWhich( SID_ATTR_CHAR_POSTURE ); + aItemIds.nPostureCJK = initTrueWhich( SID_ATTR_CHAR_CJK_POSTURE ); + aItemIds.nPostureCTL = initTrueWhich( SID_ATTR_CHAR_CTL_POSTURE ); + aItemIds.nWeight = initTrueWhich( SID_ATTR_CHAR_WEIGHT ); + aItemIds.nWeightCJK = initTrueWhich( SID_ATTR_CHAR_CJK_WEIGHT ); + aItemIds.nWeightCTL = initTrueWhich( SID_ATTR_CHAR_CTL_WEIGHT ); + aItemIds.nFontHeight = initTrueWhich( SID_ATTR_CHAR_FONTHEIGHT ); + aItemIds.nFontHeightCJK = initTrueWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ); + aItemIds.nFontHeightCTL = initTrueWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ); + aItemIds.nUnderline = initTrueWhich( SID_ATTR_CHAR_UNDERLINE ); + aItemIds.nOverline = initTrueWhich( SID_ATTR_CHAR_OVERLINE ); + aItemIds.nCrossedOut = initTrueWhich( SID_ATTR_CHAR_STRIKEOUT ); + aItemIds.nColor = initTrueWhich( SID_ATTR_CHAR_COLOR ); + aItemIds.nKerning = initTrueWhich( SID_ATTR_CHAR_KERNING ); + aItemIds.nCaseMap = initTrueWhich( SID_ATTR_CHAR_CASEMAP ); + aItemIds.nBlink = initTrueWhich( SID_ATTR_FLASH ); + + aItemIds.nLineSpacing = initTrueWhich( SID_ATTR_PARA_LINESPACE ); + aItemIds.nAdjust = initTrueWhich( SID_ATTR_PARA_ADJUST ); + aItemIds.nWidows = initTrueWhich( SID_ATTR_PARA_WIDOWS ); + aItemIds.nOrphans = initTrueWhich( SID_ATTR_PARA_ORPHANS ); + aItemIds.nFormatSplit = initTrueWhich( SID_ATTR_PARA_SPLIT ); + + // every id that is used must be added + m_aWhichMap = m_aWhichMap.MergeRange(RES_MARGIN_FIRSTLINE, RES_MARGIN_FIRSTLINE); + m_aWhichMap = m_aWhichMap.MergeRange(RES_MARGIN_TEXTLEFT, RES_MARGIN_TEXTLEFT); + m_aWhichMap = m_aWhichMap.MergeRange(RES_MARGIN_RIGHT, RES_MARGIN_RIGHT); + aItemIds.nULSpace = TypedWhichId<SvxULSpaceItem>(initTrueWhich( SID_ATTR_ULSPACE )); + aItemIds.nBox = initTrueWhich( SID_ATTR_BORDER_OUTER ); + aItemIds.nBrush = initTrueWhich( SID_ATTR_BRUSH ); + + aItemIds.nLanguage = initTrueWhich( SID_ATTR_CHAR_LANGUAGE ); + aItemIds.nLanguageCJK = initTrueWhich( SID_ATTR_CHAR_CJK_LANGUAGE ); + aItemIds.nLanguageCTL = initTrueWhich( SID_ATTR_CHAR_CTL_LANGUAGE ); + aItemIds.nDirection = initTrueWhich( SID_ATTR_FRAMEDIRECTION ); + if( pWhichIds && nWhichIds ) - BuildWhichTable( aWhichMap, pWhichIds, nWhichIds ); + for (sal_uInt16 i = 0; i < nWhichIds; ++i) + m_aWhichMap = m_aWhichMap.MergeRange(pWhichIds[i], pWhichIds[i]); - pSheetItemSet.reset( new SfxItemSet( rPool, aWhichMap.data() ) ); - pSheetPropInfo.reset( new SvxCSS1PropertyInfo ); + m_pSheetItemSet.reset( new SfxItemSet( rPool, m_aWhichMap ) ); + m_pSheetPropInfo.reset( new SvxCSS1PropertyInfo ); } SvxCSS1Parser::~SvxCSS1Parser() { - pSheetItemSet.reset(); - pSheetPropInfo.reset(); + m_pSheetItemSet.reset(); + m_pSheetPropInfo.reset(); } void SvxCSS1Parser::InsertId( const OUString& rId, @@ -818,23 +831,23 @@ SvxCSS1MapEntry* SvxCSS1Parser::GetTag( const OUString& rTag ) bool SvxCSS1Parser::ParseStyleSheet( const OUString& rIn ) { - pItemSet = pSheetItemSet.get(); - pPropInfo = pSheetPropInfo.get(); + m_pItemSet = m_pSheetItemSet.get(); + m_pPropInfo = m_pSheetPropInfo.get(); CSS1Parser::ParseStyleSheet( rIn ); for (const std::unique_ptr<CSS1Selector> & rpSelector : m_Selectors) { - StyleParsed(rpSelector.get(), *pSheetItemSet, *pSheetPropInfo); + StyleParsed(rpSelector.get(), *m_pSheetItemSet, *m_pSheetPropInfo); } // and clean up a little bit m_Selectors.clear(); - pSheetItemSet->ClearItem(); - pSheetPropInfo->Clear(); + m_pSheetItemSet->ClearItem(); + m_pSheetPropInfo->Clear(); - pItemSet = nullptr; - pPropInfo = nullptr; + m_pItemSet = nullptr; + m_pPropInfo = nullptr; return true; } @@ -843,22 +856,22 @@ void SvxCSS1Parser::ParseStyleOption( const OUString& rIn, SfxItemSet& rItemSet, SvxCSS1PropertyInfo& rPropInfo ) { - pItemSet = &rItemSet; - pPropInfo = &rPropInfo; + m_pItemSet = &rItemSet; + m_pPropInfo = &rPropInfo; CSS1Parser::ParseStyleOption( rIn ); rItemSet.ClearItem( aItemIds.nDirection ); - pItemSet = nullptr; - pPropInfo = nullptr; + m_pItemSet = nullptr; + m_pPropInfo = nullptr; } bool SvxCSS1Parser::GetEnum( const CSS1PropertyEnum *pPropTable, - const OUString &rValue, sal_uInt16& rEnum ) + std::u16string_view rValue, sal_uInt16& rEnum ) { while( pPropTable->pName ) { - if( !rValue.equalsIgnoreAsciiCaseAscii( pPropTable->pName ) ) + if( !o3tl::equalsIgnoreAsciiCase( rValue, pPropTable->pName ) ) pPropTable++; else break; @@ -872,15 +885,8 @@ bool SvxCSS1Parser::GetEnum( const CSS1PropertyEnum *pPropTable, void SvxCSS1Parser::PixelToTwip( tools::Long &rWidth, tools::Long &rHeight ) { - if( Application::GetDefaultDevice() ) - { - Size aTwipSz( rWidth, rHeight ); - aTwipSz = Application::GetDefaultDevice()->PixelToLogic( aTwipSz, - MapMode(MapUnit::MapTwip) ); - - rWidth = aTwipSz.Width(); - rHeight = aTwipSz.Height(); - } + rWidth = o3tl::convert(rWidth, o3tl::Length::px, o3tl::Length::twip); + rHeight = o3tl::convert(rHeight, o3tl::Length::px, o3tl::Length::twip); } sal_uInt32 SvxCSS1Parser::GetFontHeight( sal_uInt16 nSize ) const @@ -912,11 +918,9 @@ void SvxCSS1Parser::InsertMapEntry( const OUString& rKey, const SvxCSS1PropertyInfo& rProp, CSS1Map& rMap ) { - CSS1Map::iterator itr = rMap.find(rKey); - if (itr == rMap.end()) - { - rMap.insert(std::make_pair(rKey, std::make_unique<SvxCSS1MapEntry>(rItemSet, rProp))); - } + auto [itr,inserted] = rMap.insert(std::make_pair(rKey, nullptr)); + if (inserted) + itr->second = std::make_unique<SvxCSS1MapEntry>(rItemSet, rProp); else { SvxCSS1MapEntry *const p = itr->second.get(); @@ -937,31 +941,28 @@ void SvxCSS1Parser::MergeStyles( const SfxItemSet& rSrcSet, } else { - SvxLRSpaceItem aLRSpace( static_cast<const SvxLRSpaceItem&>(rTargetSet.Get(aItemIds.nLRSpace)) ); - SvxULSpaceItem aULSpace( static_cast<const SvxULSpaceItem&>(rTargetSet.Get(aItemIds.nULSpace)) ); - - rTargetSet.Put( rSrcSet ); - - if( rSrcInfo.m_bLeftMargin || rSrcInfo.m_bRightMargin || - rSrcInfo.m_bTextIndent ) + // not sure if this is really necessary? + SfxItemSet copy(rSrcSet); + if (!rSrcInfo.m_bTextIndent) + { + copy.ClearItem(RES_MARGIN_FIRSTLINE); + } + if (!rSrcInfo.m_bLeftMargin) { - const SvxLRSpaceItem& rNewLRSpace = - static_cast<const SvxLRSpaceItem&>(rSrcSet.Get( aItemIds.nLRSpace )); + copy.ClearItem(RES_MARGIN_TEXTLEFT); + } + if (!rSrcInfo.m_bRightMargin) + { + copy.ClearItem(RES_MARGIN_RIGHT); + } - if( rSrcInfo.m_bLeftMargin ) - aLRSpace.SetLeft( rNewLRSpace.GetLeft() ); - if( rSrcInfo.m_bRightMargin ) - aLRSpace.SetRight( rNewLRSpace.GetRight() ); - if( rSrcInfo.m_bTextIndent ) - aLRSpace.SetTextFirstLineOffset( rNewLRSpace.GetTextFirstLineOffset() ); + SvxULSpaceItem aULSpace( rTargetSet.Get(aItemIds.nULSpace) ); - rTargetSet.Put( aLRSpace ); - } + rTargetSet.Put(copy); if( rSrcInfo.m_bTopMargin || rSrcInfo.m_bBottomMargin ) { - const SvxULSpaceItem& rNewULSpace = - static_cast<const SvxULSpaceItem&>(rSrcSet.Get( aItemIds.nULSpace )); + const SvxULSpaceItem& rNewULSpace = rSrcSet.Get( aItemIds.nULSpace ); if( rSrcInfo.m_bTopMargin ) aULSpace.SetUpper( rNewULSpace.GetUpper() ); @@ -977,7 +978,7 @@ void SvxCSS1Parser::MergeStyles( const SfxItemSet& rSrcSet, void SvxCSS1Parser::SetDfltEncoding( rtl_TextEncoding eEnc ) { - eDfltEnc = eEnc; + m_eDefaultEnc = eEnc; } static void ParseCSS1_font_size( const CSS1Expression *pExpr, @@ -1013,7 +1014,7 @@ static void ParseCSS1_font_size( const CSS1Expression *pExpr, break; case CSS1_PERCENTAGE: // only for drop caps! - nPropHeight = static_cast<sal_uInt16>(pExpr->GetNumber()); + nPropHeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber()); break; case CSS1_IDENT: { @@ -1139,7 +1140,7 @@ static void ParseCSS1_font_weight( const CSS1Expression *pExpr, break; case CSS1_NUMBER: { - sal_uInt16 nWeight = static_cast<sal_uInt16>(pExpr->GetNumber()); + sal_uInt16 nWeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber()); SvxWeightItem aWeight( nWeight>400 ? WEIGHT_BOLD : WEIGHT_NORMAL, aItemIds.nWeight ); rItemSet.Put( aWeight ); @@ -1448,7 +1449,7 @@ static void ParseCSS1_background( const CSS1Expression *pExpr, { // the percentage is converted to an enum - sal_uInt16 nPerc = static_cast<sal_uInt16>(pExpr->GetNumber()); + sal_uInt16 nPerc = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber()); if( !bHori ) { ePos = nPerc < 25 ? GPOS_LT @@ -1594,7 +1595,7 @@ static void ParseCSS1_line_height( const CSS1Expression *pExpr, switch( pExpr->GetType() ) { case CSS1_LENGTH: - nHeight = static_cast<sal_uInt16>(pExpr->GetULength()); + nHeight = o3tl::narrowing<sal_uInt16>(pExpr->GetULength()); break; case CSS1_PIXLENGTH: { @@ -1604,18 +1605,18 @@ static void ParseCSS1_line_height( const CSS1Expression *pExpr, tools::Long nPHeight = static_cast<tools::Long>(fHeight); tools::Long nPWidth = 0; SvxCSS1Parser::PixelToTwip(nPWidth, nPHeight); - nHeight = static_cast<sal_uInt16>(nPHeight); + nHeight = o3tl::narrowing<sal_uInt16>(nPHeight); } } break; case CSS1_PERCENTAGE: { - nPropHeight = static_cast<sal_uInt16>(pExpr->GetNumber()); + nPropHeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber()); } break; case CSS1_NUMBER: { - nPropHeight = static_cast<sal_uInt16>(pExpr->GetNumber() * 100); + nPropHeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber() * 100); } break; default: @@ -1711,7 +1712,7 @@ static void ParseCSS1_font( const CSS1Expression *pExpr, } else { - eWeight = static_cast<sal_uInt16>(pExpr->GetNumber()) > 400 ? WEIGHT_BOLD + eWeight = o3tl::narrowing<sal_uInt16>(pExpr->GetNumber()) > 400 ? WEIGHT_BOLD : WEIGHT_NORMAL; } @@ -1951,8 +1952,17 @@ static void ParseCSS1_text_indent( const CSS1Expression *pExpr, switch( pExpr->GetType() ) { case CSS1_LENGTH: - nIndent = static_cast<short>(pExpr->GetSLength()); - bSet = true; + { + double n = std::round(pExpr->GetNumber()); + SAL_WARN_IF( + n < std::numeric_limits<short>::min() || n > std::numeric_limits<short>::max(), + "sw.html", "clamping length " << n << " to short range"); + nIndent = static_cast<short>( + std::clamp( + n, double(std::numeric_limits<short>::min()), + double(std::numeric_limits<short>::max()))); + bSet = true; + } break; case CSS1_PIXLENGTH: { @@ -1977,20 +1987,8 @@ static void ParseCSS1_text_indent( const CSS1Expression *pExpr, if( !bSet ) return; - const SfxPoolItem* pItem; - if( SfxItemState::SET == rItemSet.GetItemState( aItemIds.nLRSpace, false, - &pItem ) ) - { - SvxLRSpaceItem aLRItem( *static_cast<const SvxLRSpaceItem*>(pItem) ); - aLRItem.SetTextFirstLineOffset( nIndent ); - rItemSet.Put( aLRItem ); - } - else - { - SvxLRSpaceItem aLRItem( aItemIds.nLRSpace ); - aLRItem.SetTextFirstLineOffset( nIndent ); - rItemSet.Put( aLRItem ); - } + SvxFirstLineIndentItem const firstLine(nIndent, RES_MARGIN_FIRSTLINE); + rItemSet.Put(firstLine); rPropInfo.m_bTextIndent = true; } @@ -2034,26 +2032,22 @@ static void ParseCSS1_margin_left( const CSS1Expression *pExpr, ; } + if (pExpr->GetString() == "auto") + { + rPropInfo.m_bLeftMargin = true; + rPropInfo.m_eLeftMarginType = SVX_CSS1_LTYPE_AUTO; + } + if( !bSet ) return; rPropInfo.m_nLeftMargin = nLeft; if( nLeft < 0 ) nLeft = 0; - const SfxPoolItem* pItem; - if( SfxItemState::SET == rItemSet.GetItemState( aItemIds.nLRSpace, false, - &pItem ) ) - { - SvxLRSpaceItem aLRItem( *static_cast<const SvxLRSpaceItem*>(pItem) ); - aLRItem.SetTextLeft( static_cast<sal_uInt16>(nLeft) ); - rItemSet.Put( aLRItem ); - } - else - { - SvxLRSpaceItem aLRItem( aItemIds.nLRSpace ); - aLRItem.SetTextLeft( static_cast<sal_uInt16>(nLeft) ); - rItemSet.Put( aLRItem ); - } + + // TODO: other things may need a SvxLeftMarginItem ? but they currently convert it anyway so they can convert that too. + SvxTextLeftMarginItem const leftMargin(o3tl::narrowing<sal_uInt16>(nLeft), RES_MARGIN_TEXTLEFT); + rItemSet.Put(leftMargin); rPropInfo.m_bLeftMargin = true; } @@ -2093,26 +2087,21 @@ static void ParseCSS1_margin_right( const CSS1Expression *pExpr, ; } + if (pExpr->GetString() == "auto") + { + rPropInfo.m_bRightMargin = true; + rPropInfo.m_eRightMarginType = SVX_CSS1_LTYPE_AUTO; + } + if( !bSet ) return; rPropInfo.m_nRightMargin = nRight; if( nRight < 0 ) nRight = 0; - const SfxPoolItem* pItem; - if( SfxItemState::SET == rItemSet.GetItemState( aItemIds.nLRSpace, false, - &pItem ) ) - { - SvxLRSpaceItem aLRItem( *static_cast<const SvxLRSpaceItem*>(pItem) ); - aLRItem.SetRight( static_cast<sal_uInt16>(nRight) ); - rItemSet.Put( aLRItem ); - } - else - { - SvxLRSpaceItem aLRItem( aItemIds.nLRSpace ); - aLRItem.SetRight( static_cast<sal_uInt16>(nRight) ); - rItemSet.Put( aLRItem ); - } + + SvxRightMarginItem rightMargin(o3tl::narrowing<sal_uInt16>(nRight), RES_MARGIN_RIGHT); + rItemSet.Put(rightMargin); rPropInfo.m_bRightMargin = true; } @@ -2132,7 +2121,7 @@ static void ParseCSS1_margin_top( const CSS1Expression *pExpr, tools::Long nTmp = pExpr->GetSLength(); if( nTmp < 0 ) nTmp = 0; - nUpper = static_cast<sal_uInt16>(nTmp); + nUpper = o3tl::narrowing<sal_uInt16>(nTmp); bSet = true; } break; @@ -2146,7 +2135,7 @@ static void ParseCSS1_margin_top( const CSS1Expression *pExpr, if( nPHeight < 0 ) nPHeight = 0; SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight ); - nUpper = static_cast<sal_uInt16>(nPHeight); + nUpper = o3tl::narrowing<sal_uInt16>(nPHeight); bSet = true; } } @@ -2161,11 +2150,9 @@ static void ParseCSS1_margin_top( const CSS1Expression *pExpr, if( !bSet ) return; - const SfxPoolItem* pItem; - if( SfxItemState::SET == rItemSet.GetItemState( aItemIds.nULSpace, false, - &pItem ) ) + if( const SvxULSpaceItem* pItem = rItemSet.GetItemIfSet( aItemIds.nULSpace, false ) ) { - SvxULSpaceItem aULItem( *static_cast<const SvxULSpaceItem*>(pItem) ); + SvxULSpaceItem aULItem( *pItem ); aULItem.SetUpper( nUpper ); rItemSet.Put( aULItem ); } @@ -2194,7 +2181,7 @@ static void ParseCSS1_margin_bottom( const CSS1Expression *pExpr, tools::Long nTmp = pExpr->GetSLength(); if( nTmp < 0 ) nTmp = 0; - nLower = static_cast<sal_uInt16>(nTmp); + nLower = o3tl::narrowing<sal_uInt16>(nTmp); bSet = true; } break; @@ -2208,7 +2195,7 @@ static void ParseCSS1_margin_bottom( const CSS1Expression *pExpr, if( nPHeight < 0 ) nPHeight = 0; SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight ); - nLower = static_cast<sal_uInt16>(nPHeight); + nLower = o3tl::narrowing<sal_uInt16>(nPHeight); bSet = true; } } @@ -2223,11 +2210,9 @@ static void ParseCSS1_margin_bottom( const CSS1Expression *pExpr, if( !bSet ) return; - const SfxPoolItem* pItem; - if( SfxItemState::SET == rItemSet.GetItemState( aItemIds.nULSpace, false, - &pItem ) ) + if( const SvxULSpaceItem* pItem = rItemSet.GetItemIfSet( aItemIds.nULSpace, false ) ) { - SvxULSpaceItem aULItem( *static_cast<const SvxULSpaceItem*>(pItem) ); + SvxULSpaceItem aULItem( *pItem ); aULItem.SetLower( nLower ); rItemSet.Put( aULItem ); } @@ -2333,25 +2318,15 @@ static void ParseCSS1_margin( const CSS1Expression *pExpr, nMargins[1] = 0; } - const SfxPoolItem* pItem; - if( SfxItemState::SET == rItemSet.GetItemState( aItemIds.nLRSpace, false, - &pItem ) ) + if (bSetMargins[3]) { - SvxLRSpaceItem aLRItem( *static_cast<const SvxLRSpaceItem*>(pItem) ); - if( bSetMargins[3] ) - aLRItem.SetLeft( static_cast<sal_uInt16>(nMargins[3]) ); - if( bSetMargins[1] ) - aLRItem.SetRight( static_cast<sal_uInt16>(nMargins[1]) ); - rItemSet.Put( aLRItem ); + SvxTextLeftMarginItem const leftMargin(o3tl::narrowing<sal_uInt16>(nMargins[3]), RES_MARGIN_TEXTLEFT); + rItemSet.Put(leftMargin); } - else + if (bSetMargins[1]) { - SvxLRSpaceItem aLRItem( aItemIds.nLRSpace ); - if( bSetMargins[3] ) - aLRItem.SetLeft( static_cast<sal_uInt16>(nMargins[3]) ); - if( bSetMargins[1] ) - aLRItem.SetRight( static_cast<sal_uInt16>(nMargins[1]) ); - rItemSet.Put( aLRItem ); + SvxRightMarginItem const rightMargin(o3tl::narrowing<sal_uInt16>(nMargins[1]), RES_MARGIN_RIGHT); + rItemSet.Put(rightMargin); } } @@ -2363,24 +2338,22 @@ static void ParseCSS1_margin( const CSS1Expression *pExpr, if( nMargins[2] < 0 ) nMargins[2] = 0; - const SfxPoolItem* pItem; - if( SfxItemState::SET == rItemSet.GetItemState( aItemIds.nULSpace, false, - &pItem ) ) + if( const SvxULSpaceItem* pItem = rItemSet.GetItemIfSet( aItemIds.nULSpace, false ) ) { - SvxULSpaceItem aULItem( *static_cast<const SvxULSpaceItem*>(pItem) ); + SvxULSpaceItem aULItem( *pItem ); if( bSetMargins[0] ) - aULItem.SetUpper( static_cast<sal_uInt16>(nMargins[0]) ); + aULItem.SetUpper( o3tl::narrowing<sal_uInt16>(nMargins[0]) ); if( bSetMargins[2] ) - aULItem.SetLower( static_cast<sal_uInt16>(nMargins[2]) ); + aULItem.SetLower( o3tl::narrowing<sal_uInt16>(nMargins[2]) ); rItemSet.Put( aULItem ); } else { SvxULSpaceItem aULItem( aItemIds.nULSpace ); if( bSetMargins[0] ) - aULItem.SetUpper( static_cast<sal_uInt16>(nMargins[0]) ); + aULItem.SetUpper( o3tl::narrowing<sal_uInt16>(nMargins[0]) ); if( bSetMargins[2] ) - aULItem.SetLower( static_cast<sal_uInt16>(nMargins[2]) ); + aULItem.SetLower( o3tl::narrowing<sal_uInt16>(nMargins[2]) ); rItemSet.Put( aULItem ); } @@ -2406,7 +2379,7 @@ static bool ParseCSS1_padding_xxx( const CSS1Expression *pExpr, nTmp = 0; else if( nTmp > SvxCSS1PropertyInfo::UNSET_BORDER_DISTANCE-1 ) nTmp = SvxCSS1PropertyInfo::UNSET_BORDER_DISTANCE-1; - nDist = static_cast<sal_uInt16>(nTmp); + nDist = o3tl::narrowing<sal_uInt16>(nTmp); bSet = true; } break; @@ -2422,7 +2395,7 @@ static bool ParseCSS1_padding_xxx( const CSS1Expression *pExpr, SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight ); if( nPWidth > SvxCSS1PropertyInfo::UNSET_BORDER_DISTANCE-1 ) nPWidth = SvxCSS1PropertyInfo::UNSET_BORDER_DISTANCE-1; - nDist = static_cast<sal_uInt16>(nPWidth); + nDist = o3tl::narrowing<sal_uInt16>(nPWidth); bSet = true; } } @@ -2549,7 +2522,7 @@ static void ParseCSS1_border_xxx( const CSS1Expression *pExpr, break; case CSS1_LENGTH: - nWidth = static_cast<sal_uInt16>(pExpr->GetULength()); + nWidth = o3tl::narrowing<sal_uInt16>(pExpr->GetULength()); break; case CSS1_PIXLENGTH: @@ -2564,7 +2537,7 @@ static void ParseCSS1_border_xxx( const CSS1Expression *pExpr, tools::Long nPWidth = bHori ? 0 : fWidth; tools::Long nPHeight = bHori ? fWidth : 0; SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight ); - nWidth = static_cast<sal_uInt16>(bHori ? nPHeight : nPWidth); + nWidth = o3tl::narrowing<sal_uInt16>(bHori ? nPHeight : nPWidth); } else nWidth = 1; @@ -2625,7 +2598,7 @@ static void ParseCSS1_border_xxx_width( const CSS1Expression *pExpr, break; case CSS1_LENGTH: - nWidth = static_cast<sal_uInt16>(pExpr->GetULength()); + nWidth = o3tl::narrowing<sal_uInt16>(pExpr->GetULength()); break; case CSS1_PIXLENGTH: @@ -2641,7 +2614,7 @@ static void ParseCSS1_border_xxx_width( const CSS1Expression *pExpr, tools::Long nPWidth = bHori ? 0 : nWidthL; tools::Long nPHeight = bHori ? nWidthL : 0; SvxCSS1Parser::PixelToTwip( nPWidth, nPHeight ); - nWidth = static_cast<sal_uInt16>(bHori ? nPHeight : nPWidth); + nWidth = o3tl::narrowing<sal_uInt16>(bHori ? nPHeight : nPWidth); } } break; @@ -2862,9 +2835,7 @@ static void ParseCSS1_length( const CSS1Expression *pExpr, break; case CSS1_PERCENTAGE: - rLength = static_cast<tools::Long>(pExpr->GetNumber()); - if( rLength > 100 ) - rLength = 100; + rLength = static_cast<tools::Long>(std::min(pExpr->GetNumber(), 100.0)); rLengthType = SVX_CSS1_LTYPE_PERCENTAGE; break; @@ -3073,85 +3044,94 @@ static void ParseCSS1_visibility(const CSS1Expression* pExpr, SfxItemSet& /*rIte rPropInfo.m_bVisible = pExpr->GetString() != "hidden"; } +static void ParseCSS1_white_space(const CSS1Expression* pExpr, SfxItemSet& /*rItemSet*/, + SvxCSS1PropertyInfo& rPropInfo, const SvxCSS1Parser& /*rParser*/) +{ + if (pExpr->GetType() == CSS1_IDENT) + { + if (pExpr->GetString().equalsIgnoreAsciiCase("pre") + || pExpr->GetString().equalsIgnoreAsciiCase("pre-wrap")) + { + rPropInfo.m_bPreserveSpace = true; + } + } +} + namespace { // the assignment of property to parsing function struct CSS1PropEntry { - const char * pName; + std::string_view pName; FnParseCSS1Prop pFunc; }; } -#define CSS1_PROP_ENTRY(p) \ - { sCSS1_P_##p, ParseCSS1_##p } - // the table with assignments -CSS1PropEntry const aCSS1PropFnTab[] = -{ - CSS1_PROP_ENTRY(background), - CSS1_PROP_ENTRY(background_color), - CSS1_PROP_ENTRY(border), - CSS1_PROP_ENTRY(border_bottom), - CSS1_PROP_ENTRY(border_bottom_width), - CSS1_PROP_ENTRY(border_color), - CSS1_PROP_ENTRY(border_left), - CSS1_PROP_ENTRY(border_left_width), - CSS1_PROP_ENTRY(border_right), - CSS1_PROP_ENTRY(border_right_width), - CSS1_PROP_ENTRY(border_style), - CSS1_PROP_ENTRY(border_top), - CSS1_PROP_ENTRY(border_top_width), - CSS1_PROP_ENTRY(border_width), - CSS1_PROP_ENTRY(color), - CSS1_PROP_ENTRY(column_count), - CSS1_PROP_ENTRY(direction), - CSS1_PROP_ENTRY(float), - CSS1_PROP_ENTRY(font), - CSS1_PROP_ENTRY(font_family), - CSS1_PROP_ENTRY(font_size), - CSS1_PROP_ENTRY(font_style), - CSS1_PROP_ENTRY(font_variant), - CSS1_PROP_ENTRY(font_weight), - CSS1_PROP_ENTRY(height), - CSS1_PROP_ENTRY(left), - CSS1_PROP_ENTRY(letter_spacing), - CSS1_PROP_ENTRY(line_height), - CSS1_PROP_ENTRY(list_style_type), - CSS1_PROP_ENTRY(margin), - CSS1_PROP_ENTRY(margin_bottom), - CSS1_PROP_ENTRY(margin_left), - CSS1_PROP_ENTRY(margin_right), - CSS1_PROP_ENTRY(margin_top), - CSS1_PROP_ENTRY(orphans), - CSS1_PROP_ENTRY(padding), - CSS1_PROP_ENTRY(padding_bottom), - CSS1_PROP_ENTRY(padding_left), - CSS1_PROP_ENTRY(padding_right), - CSS1_PROP_ENTRY(padding_top), - CSS1_PROP_ENTRY(page_break_after), - CSS1_PROP_ENTRY(page_break_before), - CSS1_PROP_ENTRY(page_break_inside), - CSS1_PROP_ENTRY(position), - CSS1_PROP_ENTRY(size), - CSS1_PROP_ENTRY(so_language), - CSS1_PROP_ENTRY(text_align), - CSS1_PROP_ENTRY(text_decoration), - CSS1_PROP_ENTRY(text_indent), - CSS1_PROP_ENTRY(text_transform), - CSS1_PROP_ENTRY(top), - CSS1_PROP_ENTRY(visibility), - CSS1_PROP_ENTRY(widows), - CSS1_PROP_ENTRY(width), +CSS1PropEntry constexpr aCSS1PropFnTab[] = +{ + { sCSS1_P_background, ParseCSS1_background }, + { sCSS1_P_background_color, ParseCSS1_background_color }, + { sCSS1_P_border, ParseCSS1_border }, + { sCSS1_P_border_bottom, ParseCSS1_border_bottom }, + { sCSS1_P_border_bottom_width, ParseCSS1_border_bottom_width }, + { sCSS1_P_border_color, ParseCSS1_border_color }, + { sCSS1_P_border_left, ParseCSS1_border_left }, + { sCSS1_P_border_left_width, ParseCSS1_border_left_width }, + { sCSS1_P_border_right, ParseCSS1_border_right }, + { sCSS1_P_border_right_width, ParseCSS1_border_right_width }, + { sCSS1_P_border_style, ParseCSS1_border_style }, + { sCSS1_P_border_top, ParseCSS1_border_top }, + { sCSS1_P_border_top_width, ParseCSS1_border_top_width }, + { sCSS1_P_border_width, ParseCSS1_border_width }, + { sCSS1_P_color, ParseCSS1_color }, + { sCSS1_P_column_count, ParseCSS1_column_count }, + { sCSS1_P_direction, ParseCSS1_direction }, + { sCSS1_P_float, ParseCSS1_float }, + { sCSS1_P_font, ParseCSS1_font }, + { sCSS1_P_font_family, ParseCSS1_font_family }, + { sCSS1_P_font_size, ParseCSS1_font_size }, + { sCSS1_P_font_style, ParseCSS1_font_style }, + { sCSS1_P_font_variant, ParseCSS1_font_variant }, + { sCSS1_P_font_weight, ParseCSS1_font_weight }, + { sCSS1_P_height, ParseCSS1_height }, + { sCSS1_P_left, ParseCSS1_left }, + { sCSS1_P_letter_spacing, ParseCSS1_letter_spacing }, + { sCSS1_P_line_height, ParseCSS1_line_height }, + { sCSS1_P_list_style_type, ParseCSS1_list_style_type }, + { sCSS1_P_margin, ParseCSS1_margin }, + { sCSS1_P_margin_bottom, ParseCSS1_margin_bottom }, + { sCSS1_P_margin_left, ParseCSS1_margin_left }, + { sCSS1_P_margin_right, ParseCSS1_margin_right }, + { sCSS1_P_margin_top, ParseCSS1_margin_top }, + { sCSS1_P_orphans, ParseCSS1_orphans }, + { sCSS1_P_padding, ParseCSS1_padding }, + { sCSS1_P_padding_bottom, ParseCSS1_padding_bottom }, + { sCSS1_P_padding_left, ParseCSS1_padding_left }, + { sCSS1_P_padding_right, ParseCSS1_padding_right }, + { sCSS1_P_padding_top, ParseCSS1_padding_top }, + { sCSS1_P_page_break_after, ParseCSS1_page_break_after }, + { sCSS1_P_page_break_before, ParseCSS1_page_break_before }, + { sCSS1_P_page_break_inside, ParseCSS1_page_break_inside }, + { sCSS1_P_position, ParseCSS1_position }, + { sCSS1_P_size, ParseCSS1_size }, + { sCSS1_P_so_language, ParseCSS1_so_language }, + { sCSS1_P_text_align, ParseCSS1_text_align }, + { sCSS1_P_text_decoration, ParseCSS1_text_decoration }, + { sCSS1_P_text_indent, ParseCSS1_text_indent }, + { sCSS1_P_text_transform, ParseCSS1_text_transform }, + { sCSS1_P_top, ParseCSS1_top }, + { sCSS1_P_visibility, ParseCSS1_visibility }, + { sCSS1_white_space, ParseCSS1_white_space }, + { sCSS1_P_widows, ParseCSS1_widows }, + { sCSS1_P_width, ParseCSS1_width }, }; -#if !defined NDEBUG -static bool CSS1PropEntryCompare( const CSS1PropEntry &lhs, const CSS1PropEntry &rhs) -{ - return strcmp(lhs.pName, rhs.pName) < 0; -} -#endif +static_assert(std::is_sorted(std::begin(aCSS1PropFnTab), std::end(aCSS1PropFnTab), + [](const auto& lhs, const auto& rhs) constexpr + { return lhs.pName < rhs.pName; })); + static bool CSS1PropEntryFindCompare(CSS1PropEntry const & lhs, OUString const & s) { return s.compareToIgnoreAsciiCaseAscii(lhs.pName) > 0; @@ -3160,22 +3140,13 @@ static bool CSS1PropEntryFindCompare(CSS1PropEntry const & lhs, OUString const & void SvxCSS1Parser::DeclarationParsed( const OUString& rProperty, std::unique_ptr<CSS1Expression> pExpr ) { - OSL_ENSURE( pItemSet, "DeclarationParsed() without ItemSet" ); - - static bool bSortedPropFns = false; - - if( !bSortedPropFns ) - { - assert( std::is_sorted( std::begin(aCSS1PropFnTab), std::end(aCSS1PropFnTab), - CSS1PropEntryCompare ) ); - bSortedPropFns = true; - } + OSL_ENSURE( m_pItemSet, "DeclarationParsed() without ItemSet" ); auto it = std::lower_bound( std::begin(aCSS1PropFnTab), std::end(aCSS1PropFnTab), rProperty, CSS1PropEntryFindCompare ); if( it != std::end(aCSS1PropFnTab) && !CSS1PropEntryFindCompare(*it,rProperty) ) { - it->pFunc( pExpr.get(), *pItemSet, *pPropInfo, *this ); + it->pFunc( pExpr.get(), *m_pItemSet, *m_pPropInfo, *this ); } } diff --git a/sw/source/filter/html/svxcss1.hxx b/sw/source/filter/html/svxcss1.hxx index e7888ff39813..669ed92a5b95 100644 --- a/sw/source/filter/html/svxcss1.hxx +++ b/sw/source/filter/html/svxcss1.hxx @@ -20,11 +20,11 @@ #define INCLUDED_SW_SOURCE_FILTER_HTML_SVXCSS1_HXX #include <svl/itemset.hxx> -#include <svx/flagsdef.hxx> #include <editeng/svxenum.hxx> #include <rtl/textenc.h> #include "parcss1.hxx" #include <o3tl/typed_flags_set.hxx> +#include <o3tl/unit_conversion.hxx> #include <array> #include <map> @@ -115,6 +115,7 @@ public: bool m_bTextIndent : 1; bool m_bNumbering : 1; bool m_bBullet : 1; + bool m_bPreserveSpace : 1 = false; SvxAdjust m_eFloat; @@ -136,6 +137,8 @@ public: SvxCSS1LengthType m_eLeftType, m_eTopType; SvxCSS1LengthType m_eWidthType, m_eHeightType; + SvxCSS1LengthType m_eLeftMarginType; + SvxCSS1LengthType m_eRightMarginType; SvxCSS1SizeType m_eSizeType; @@ -163,18 +166,18 @@ public: class SvxCSS1MapEntry { - SfxItemSet aItemSet; - SvxCSS1PropertyInfo aPropInfo; + SfxItemSet m_aItemSet; + SvxCSS1PropertyInfo m_aPropInfo; public: - SvxCSS1MapEntry( const SfxItemSet& rItemSet, + SvxCSS1MapEntry( SfxItemSet aItemSet, const SvxCSS1PropertyInfo& rProp ); - const SfxItemSet& GetItemSet() const { return aItemSet; } - SfxItemSet& GetItemSet() { return aItemSet; } + const SfxItemSet& GetItemSet() const { return m_aItemSet; } + SfxItemSet& GetItemSet() { return m_aItemSet; } - const SvxCSS1PropertyInfo& GetPropertyInfo() const { return aPropInfo; } - SvxCSS1PropertyInfo& GetPropertyInfo() { return aPropInfo; } + const SvxCSS1PropertyInfo& GetPropertyInfo() const { return m_aPropInfo; } + SvxCSS1PropertyInfo& GetPropertyInfo() { return m_aPropInfo; } }; // Class is processing the CSS1-Parser output by converting the CSS1 properties @@ -194,19 +197,20 @@ class SvxCSS1Parser : public CSS1Parser CSS1Map m_Pages; CSS1Map m_Tags; - OUString sBaseURL; + OUString m_sBaseURL; - std::unique_ptr<SfxItemSet> pSheetItemSet; // item set of Style-Sheet - SfxItemSet *pItemSet; // current item set + std::unique_ptr<SfxItemSet> m_pSheetItemSet; // item set of Style-Sheet + SfxItemSet *m_pItemSet; // current item set - std::unique_ptr<SvxCSS1PropertyInfo> pSheetPropInfo; - SvxCSS1PropertyInfo *pPropInfo; + std::unique_ptr<SvxCSS1PropertyInfo> m_pSheetPropInfo; + SvxCSS1PropertyInfo *m_pPropInfo; - static constexpr sal_uInt16 gnMinFixLineSpace = MM50/2; // minimum spacing for fixed line spacing + // minimum spacing for fixed line spacing + static constexpr sal_uInt16 gnMinFixLineSpace = o3tl::toTwips(25, o3tl::Length::mm10); - rtl_TextEncoding eDfltEnc; - bool bIgnoreFontFamily; - std::vector<sal_uInt16> aWhichMap; // Which-Map of Parser + rtl_TextEncoding m_eDefaultEnc; + bool m_bIgnoreFontFamily; + WhichRangesContainer m_aWhichMap; // Which-Map of Parser using CSS1Parser::ParseStyleOption; @@ -238,12 +242,12 @@ protected: public: SvxCSS1Parser( SfxItemPool& rPool, - const OUString& rBaseURL, + OUString aBaseURL, sal_uInt16 const *pWhichIds, sal_uInt16 nWhichIds ); virtual ~SvxCSS1Parser() override; - bool IsIgnoreFontFamily() const { return bIgnoreFontFamily; } - void SetIgnoreFontFamily( bool bSet ) { bIgnoreFontFamily = bSet; } + bool IsIgnoreFontFamily() const { return m_bIgnoreFontFamily; } + void SetIgnoreFontFamily( bool bSet ) { m_bIgnoreFontFamily = bSet; } // Parse a style sheet. For every found selector a StyleParsed with // according item set is called. @@ -255,7 +259,7 @@ public: // convert a string to enum value static bool GetEnum( const CSS1PropertyEnum *pPropTable, - const OUString& rValue, sal_uInt16 &rEnum ); + std::u16string_view rValue, sal_uInt16 &rEnum ); static void PixelToTwip( tools::Long &nWidth, tools::Long &nHeight ); @@ -264,7 +268,7 @@ public: virtual const FontList *GetFontList() const; - const sal_uInt16 *GetWhichMap() const { return aWhichMap.data(); } + const WhichRangesContainer& GetWhichMap() const { return m_aWhichMap; } static void InsertMapEntry( const OUString& rKey, const SfxItemSet& rItemSet, const SvxCSS1PropertyInfo& rProp, CSS1Map& rMap ); @@ -299,9 +303,9 @@ public: static sal_uInt16 GetMinFixLineSpace() { return gnMinFixLineSpace; } virtual void SetDfltEncoding( rtl_TextEncoding eEnc ); - rtl_TextEncoding GetDfltEncoding() const { return eDfltEnc; } + rtl_TextEncoding GetDfltEncoding() const { return m_eDefaultEnc; } - const OUString& GetBaseURL() const { return sBaseURL;} + const OUString& GetBaseURL() const { return m_sBaseURL;} }; diff --git a/sw/source/filter/html/swhtml.cxx b/sw/source/filter/html/swhtml.cxx index d0173d398fa9..dbbbc7cc0207 100644 --- a/sw/source/filter/html/swhtml.cxx +++ b/sw/source/filter/html/swhtml.cxx @@ -31,24 +31,24 @@ #include <o3tl/safeint.hxx> #include <rtl/ustrbuf.hxx> #include <svx/svxids.hrc> +#include <svx/svdotext.hxx> #if OSL_DEBUG_LEVEL > 0 #include <stdlib.h> #endif #include <hintids.hxx> +#include <utility> #include <vcl/errinf.hxx> #include <svl/stritem.hxx> #include <vcl/imap.hxx> #include <svtools/htmltokn.h> #include <svtools/htmlkywd.hxx> #include <svtools/ctrltool.hxx> -#include <unotools/configmgr.hxx> #include <unotools/pathoptions.hxx> #include <vcl/svapp.hxx> #include <sfx2/event.hxx> #include <sfx2/docfile.hxx> -#include <svtools/htmlcfg.hxx> #include <sfx2/linkmgr.hxx> #include <editeng/kernitem.hxx> #include <editeng/boxitem.hxx> @@ -117,6 +117,7 @@ #include <officecfg/Office/Writer.hxx> #include <comphelper/sequenceashashmap.hxx> #include <comphelper/sequence.hxx> +#include <officecfg/Office/Common.hxx> #include <swerror.h> #include <ndole.hxx> @@ -169,7 +170,7 @@ OUString HTMLReader::GetTemplateName(SwDoc& rDoc) const // HTML import into Writer, avoid loading the Writer/Web template. return OUString(); - const OUString sTemplateWithoutExt("internal/html"); + static constexpr OUString sTemplateWithoutExt(u"internal/html"_ustr); SvtPathOptions aPathOpt; // first search for OpenDocument Writer/Web template @@ -203,7 +204,7 @@ bool HTMLReader::SetStrmStgPtr() } // Call for the general Reader-Interface -ErrCode HTMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPam, const OUString & rName ) +ErrCodeMsg HTMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPam, const OUString & rName ) { SetupFilterOptions(); @@ -228,7 +229,7 @@ ErrCode HTMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPam, co // so nobody steals the document! rtl::Reference<SwDoc> xHoldAlive(&rDoc); - ErrCode nRet = ERRCODE_NONE; + ErrCodeMsg nRet = ERRCODE_NONE; tools::SvRef<SwHTMLParser> xParser = new SwHTMLParser( &rDoc, rPam, *m_pStream, rName, rBaseURL, !m_bInsertMode, m_pMedium, IsReadUTF8(), @@ -244,7 +245,7 @@ ErrCode HTMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPam, co + "," + OUString::number(static_cast<sal_Int32>(xParser->GetLinePos()))); // use the stream as transport for error number - nRet = *new StringErrorInfo( ERR_FORMAT_ROWCOL, sErr, + nRet = ErrCodeMsg( ERR_FORMAT_ROWCOL, sErr, DialogMask::ButtonsOk | DialogMask::MessageError ); } @@ -252,22 +253,21 @@ ErrCode HTMLReader::Read( SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPam, co } SwHTMLParser::SwHTMLParser( SwDoc* pD, SwPaM& rCursor, SvStream& rIn, - const OUString& rPath, - const OUString& rBaseURL, + OUString aPath, + OUString aBaseURL, bool bReadNewDoc, SfxMedium* pMed, bool bReadUTF8, bool bNoHTMLComments, const OUString& rNamespace ) : SfxHTMLParser( rIn, bReadNewDoc, pMed ), - m_aPathToFile( rPath ), - m_sBaseURL( rBaseURL ), + m_aPathToFile(std::move( aPath )), + m_sBaseURL(std::move( aBaseURL )), m_xAttrTab(std::make_shared<HTMLAttrTable>()), m_pNumRuleInfo( new SwHTMLNumRuleInfo ), m_xDoc( pD ), m_pActionViewShell( nullptr ), m_pSttNdIdx( nullptr ), m_pFormImpl( nullptr ), - m_pMarquee( nullptr ), m_pImageMap( nullptr ), m_nBaseFontStMin( 0 ), m_nFontStMin( 0 ), @@ -286,10 +286,11 @@ SwHTMLParser::SwHTMLParser( SwDoc* pD, SwPaM& rCursor, SvStream& rIn, m_nContinue( 0 ), #endif m_eParaAdjust( SvxAdjust::End ), - m_bDocInitalized( false ), + m_bDocInitialized( false ), m_bSetModEnabled( false ), m_bInFloatingFrame( false ), m_bInField( false ), + m_bKeepUnknown( false ), m_bCallNextToken( false ), m_bIgnoreRawData( false ), m_bLBEntrySelected ( false ), @@ -311,11 +312,17 @@ SwHTMLParser::SwHTMLParser( SwDoc* pD, SwPaM& rCursor, SvStream& rIn, m_bNotifyMacroEventRead( false ), m_isInTableStructure(false), m_nTableDepth( 0 ), + m_nFloatingFrames( 0 ), + m_nListItems( 0 ), m_pTempViewFrame(nullptr) { // If requested explicitly, then force ignoring of comments (don't create postits for them). - if (!utl::ConfigManager::IsFuzzing() && officecfg::Office::Writer::Filter::Import::HTML::IgnoreComments::get()) - m_bIgnoreHTMLComments = true; + if (!bFuzzing) + { + if (officecfg::Office::Writer::Filter::Import::HTML::IgnoreComments::get()) + m_bIgnoreHTMLComments = true; + m_bKeepUnknown = officecfg::Office::Common::Filter::HTML::Import::UnknownTag::get(); + } m_nEventId = nullptr; m_bUpperSpace = m_bViewCreated = m_bChkJumpMark = false; @@ -323,20 +330,25 @@ SwHTMLParser::SwHTMLParser( SwDoc* pD, SwPaM& rCursor, SvStream& rIn, m_eScriptLang = HTMLScriptLanguage::Unknown; rCursor.DeleteMark(); - m_pPam = &rCursor; // re-use existing cursor: avoids spurious ~SwIndexReg assert + m_pPam = &rCursor; // re-use existing cursor: avoids spurious ~SwContentIndexReg assert memset(m_xAttrTab.get(), 0, sizeof(HTMLAttrTable)); // Read the font sizes 1-7 from the INI file - SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get(); - m_aFontHeights[0] = rHtmlOptions.GetFontSize( 0 ) * 20; - m_aFontHeights[1] = rHtmlOptions.GetFontSize( 1 ) * 20; - m_aFontHeights[2] = rHtmlOptions.GetFontSize( 2 ) * 20; - m_aFontHeights[3] = rHtmlOptions.GetFontSize( 3 ) * 20; - m_aFontHeights[4] = rHtmlOptions.GetFontSize( 4 ) * 20; - m_aFontHeights[5] = rHtmlOptions.GetFontSize( 5 ) * 20; - m_aFontHeights[6] = rHtmlOptions.GetFontSize( 6 ) * 20; - - m_bKeepUnknown = rHtmlOptions.IsImportUnknown(); + if (!bFuzzing) + { + m_aFontHeights[0] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_1::get() * 20; + m_aFontHeights[1] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_2::get() * 20; + m_aFontHeights[2] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_3::get() * 20; + m_aFontHeights[3] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_4::get() * 20; + m_aFontHeights[4] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_5::get() * 20; + m_aFontHeights[5] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_6::get() * 20; + m_aFontHeights[6] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_7::get() * 20; + } + else + { + m_aFontHeights[0] = m_aFontHeights[1] = m_aFontHeights[2] = m_aFontHeights[3] = + m_aFontHeights[4] = m_aFontHeights[5] = m_aFontHeights[6] = 12 * 20; + } if(bReadNewDoc) { @@ -359,7 +371,8 @@ SwHTMLParser::SwHTMLParser( SwDoc* pD, SwPaM& rCursor, SvStream& rIn, m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, true); m_pCSS1Parser.reset(new SwCSS1Parser(m_xDoc.get(), *this, m_aFontHeights, m_sBaseURL, IsNewDoc())); - m_pCSS1Parser->SetIgnoreFontFamily( rHtmlOptions.IsIgnoreFontFamily() ); + if (!bFuzzing) + m_pCSS1Parser->SetIgnoreFontFamily( officecfg::Office::Common::Filter::HTML::Import::FontSetting::get() ); if( bReadUTF8 ) { @@ -519,7 +532,7 @@ SwHTMLParser::~SwHTMLParser() // the temporary view frame is hidden, so the hidden flag might need to be removed if ( m_bRemoveHidden && m_xDoc.is() && m_xDoc->GetDocShell() && m_xDoc->GetDocShell()->GetMedium() ) - m_xDoc->GetDocShell()->GetMedium()->GetItemSet()->ClearItem( SID_HIDDEN ); + m_xDoc->GetDocShell()->GetMedium()->GetItemSet().ClearItem( SID_HIDDEN ); } } @@ -549,7 +562,7 @@ SvParserState SwHTMLParser::CallParser() m_xDoc->getIDocumentContentOperations().SplitNode( *pPos, false ); - *m_pSttNdIdx = pPos->nNode.GetIndex()-1; + *m_pSttNdIdx = pPos->GetNodeIndex()-1; m_xDoc->getIDocumentContentOperations().SplitNode( *pPos, false ); SwPaM aInsertionRangePam( *pPos ); @@ -595,7 +608,7 @@ SvParserState SwHTMLParser::CallParser() return eRet; } -bool SwHTMLParser::CanRemoveNode(sal_uLong nNodeIdx) const +bool SwHTMLParser::CanRemoveNode(SwNodeOffset nNodeIdx) const { const SwNode *pPrev = m_xDoc->GetNodes()[nNodeIdx - 1]; return pPrev->IsContentNode() || (pPrev->IsEndNode() && pPrev->StartOfSectionNode()->IsSectionNode()); @@ -739,29 +752,28 @@ void SwHTMLParser::Continue( HtmlTokenId nToken ) { const sal_Int32 nStt = pTextNode->GetText().getLength(); // when the cursor is still in the node, then set him at the end - if( m_pPam->GetPoint()->nNode == aNxtIdx ) + if( m_pPam->GetPoint()->GetNode() == aNxtIdx.GetNode() ) { - m_pPam->GetPoint()->nNode = *m_pSttNdIdx; - m_pPam->GetPoint()->nContent.Assign( pTextNode, nStt ); + m_pPam->GetPoint()->Assign( *pTextNode, nStt ); } #if OSL_DEBUG_LEVEL > 0 // !!! shouldn't be possible, or ?? - OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 != m_pPam->GetBound().nNode.GetIndex(), + OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 != m_pPam->GetBound().GetNodeIndex(), "Pam.Bound1 is still in the node" ); - OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 != m_pPam->GetBound( false ).nNode.GetIndex(), + OSL_ENSURE( m_pSttNdIdx->GetIndex()+1 != m_pPam->GetBound( false ).GetNodeIndex(), "Pam.Bound2 is still in the node" ); - if( m_pSttNdIdx->GetIndex()+1 == m_pPam->GetBound().nNode.GetIndex() ) + if( m_pSttNdIdx->GetIndex()+1 == m_pPam->GetBound().GetNodeIndex() ) { - const sal_Int32 nCntPos = m_pPam->GetBound().nContent.GetIndex(); - m_pPam->GetBound().nContent.Assign( pTextNode, + const sal_Int32 nCntPos = m_pPam->GetBound().GetContentIndex(); + m_pPam->GetBound().SetContent( pTextNode->GetText().getLength() + nCntPos ); } - if( m_pSttNdIdx->GetIndex()+1 == m_pPam->GetBound( false ).nNode.GetIndex() ) + if( m_pSttNdIdx->GetIndex()+1 == m_pPam->GetBound( false ).GetNodeIndex() ) { - const sal_Int32 nCntPos = m_pPam->GetBound( false ).nContent.GetIndex(); - m_pPam->GetBound( false ).nContent.Assign( pTextNode, + const sal_Int32 nCntPos = m_pPam->GetBound( false ).GetContentIndex(); + m_pPam->GetBound( false ).SetContent( pTextNode->GetText().getLength() + nCntPos ); } #endif @@ -787,19 +799,19 @@ void SwHTMLParser::Continue( HtmlTokenId nToken ) // now remove the last useless paragraph SwPosition* pPos = m_pPam->GetPoint(); - if( !pPos->nContent.GetIndex() && !bLFStripped ) + if( !pPos->GetContentIndex() && !bLFStripped ) { SwTextNode* pCurrentNd; - sal_uLong nNodeIdx = pPos->nNode.GetIndex(); + SwNodeOffset nNodeIdx = pPos->GetNodeIndex(); bool bHasFlysOrMarks = HasCurrentParaFlys() || HasCurrentParaBookmarks( true ); if( IsNewDoc() ) { - if (!m_pPam->GetPoint()->nContent.GetIndex() && CanRemoveNode(nNodeIdx)) + if (!m_pPam->GetPoint()->GetContentIndex() && CanRemoveNode(nNodeIdx)) { - SwContentNode* pCNd = m_pPam->GetContentNode(); + SwContentNode* pCNd = m_pPam->GetPointContentNode(); if( pCNd && pCNd->StartOfSectionIndex()+2 < pCNd->EndOfSectionIndex() && !bHasFlysOrMarks ) { @@ -807,32 +819,36 @@ void SwHTMLParser::Continue( HtmlTokenId nToken ) SwCursorShell *pCursorSh = dynamic_cast<SwCursorShell *>( pVSh ); if( pCursorSh && pCursorSh->GetCursor()->GetPoint() - ->nNode.GetIndex() == nNodeIdx ) + ->GetNodeIndex() == nNodeIdx ) { pCursorSh->MovePara(GoPrevPara, fnParaEnd ); pCursorSh->SetMark(); pCursorSh->ClearMark(); } - m_pPam->GetBound().nContent.Assign( nullptr, 0 ); - m_pPam->GetBound(false).nContent.Assign( nullptr, 0 ); - m_xDoc->GetNodes().Delete( m_pPam->GetPoint()->nNode ); + SwNode& rDelNode = m_pPam->GetPoint()->GetNode(); + // move so we don't have a dangling SwContentIndex to the deleted node + m_pPam->GetPoint()->Adjust(SwNodeOffset(1)); + if (m_pPam->HasMark()) + m_pPam->GetMark()->Adjust(SwNodeOffset(1)); + m_xDoc->GetNodes().Delete( rDelNode ); } } } else if( nullptr != ( pCurrentNd = m_xDoc->GetNodes()[ nNodeIdx ]->GetTextNode()) && !bHasFlysOrMarks ) { - if( pCurrentNd->CanJoinNext( &pPos->nNode )) + if( pCurrentNd->CanJoinNext( pPos )) { - SwTextNode* pNextNd = pPos->nNode.GetNode().GetTextNode(); - pPos->nContent.Assign( pNextNd, 0 ); + SwTextNode* pNextNd = pPos->GetNode().GetTextNode(); m_pPam->SetMark(); m_pPam->DeleteMark(); pNextNd->JoinPrev(); } else if (pCurrentNd->GetText().isEmpty()) { - pPos->nContent.Assign( nullptr, 0 ); m_pPam->SetMark(); m_pPam->DeleteMark(); - m_xDoc->GetNodes().Delete( pPos->nNode ); + SwNode& rDelNode = pPos->GetNode(); + // move so we don't have a dangling SwContentIndex to the deleted node + m_pPam->GetPoint()->Adjust(SwNodeOffset(+1)); + m_xDoc->GetNodes().Delete( rDelNode ); m_pPam->Move( fnMoveBackward ); } } @@ -841,10 +857,10 @@ void SwHTMLParser::Continue( HtmlTokenId nToken ) // annul the SplitNode from the beginning else if( !IsNewDoc() ) { - if( pPos->nContent.GetIndex() ) // then there was no <p> at the end + if( pPos->GetContentIndex() ) // then there was no <p> at the end m_pPam->Move( fnMoveForward, GoInNode ); // therefore to the next - SwTextNode* pTextNode = pPos->nNode.GetNode().GetTextNode(); - SwNodeIndex aPrvIdx( pPos->nNode ); + SwTextNode* pTextNode = pPos->GetNode().GetTextNode(); + SwNodeIndex aPrvIdx( pPos->GetNode() ); if( pTextNode && pTextNode->CanJoinPrev( &aPrvIdx ) && *m_pSttNdIdx <= aPrvIdx ) { @@ -861,9 +877,9 @@ void SwHTMLParser::Continue( HtmlTokenId nToken ) if( pPrev->HasSwAttrSet() ) pTextNode->SetAttr( *pPrev->GetpSwAttrSet() ); - if( &m_pPam->GetBound().nNode.GetNode() == pPrev ) + if( &m_pPam->GetBound().GetNode() == pPrev ) m_pPam->GetBound().nContent.Assign( pTextNode, 0 ); - if( &m_pPam->GetBound(false).nNode.GetNode() == pPrev ) + if( &m_pPam->GetBound(false).GetNode() == pPrev ) m_pPam->GetBound(false).nContent.Assign( pTextNode, 0 ); pTextNode->JoinPrev(); @@ -871,7 +887,7 @@ void SwHTMLParser::Continue( HtmlTokenId nToken ) } // adjust AutoLoad in DocumentProperties - if (!utl::ConfigManager::IsFuzzing() && IsNewDoc()) + if (!bFuzzing && IsNewDoc()) { SwDocShell *pDocShell(m_xDoc->GetDocShell()); OSL_ENSURE(pDocShell, "no SwDocShell"); @@ -954,8 +970,8 @@ void SwHTMLParser::Notify(const SfxHint& rHint) void SwHTMLParser::DocumentDetected() { - OSL_ENSURE( !m_bDocInitalized, "DocumentDetected called multiple times" ); - m_bDocInitalized = true; + OSL_ENSURE( !m_bDocInitialized, "DocumentDetected called multiple times" ); + m_bDocInitialized = true; if( IsNewDoc() ) { if( IsInHeader() ) @@ -1073,7 +1089,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) // Find out what type of document it is if we don't know already. // For Controls this has to be finished before the control is inserted // because for inserting a View is needed. - if( !m_bDocInitalized ) + if( !m_bDocInitialized ) DocumentDetected(); bool bGetIDOption = false, bInsertUnknown = false; @@ -1253,9 +1269,9 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) // (but surely if we are not in the header section) fdo#36080 fdo#34666 if (!aToken.isEmpty() && !IsInHeader() ) { - if( !m_bDocInitalized ) + if( !m_bDocInitialized ) DocumentDetected(); - m_xDoc->getIDocumentContentOperations().InsertString( *m_pPam, aToken ); + m_xDoc->getIDocumentContentOperations().InsertString( *m_pPam, aToken.toString()); // if there are temporary paragraph attributes and the // paragraph isn't empty then the paragraph attributes @@ -1450,8 +1466,13 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) break; case HtmlTokenId::IFRAME_ON: - InsertFloatingFrame(); - m_bCallNextToken = m_bInFloatingFrame && m_xTable; + if (bFuzzing && m_nFloatingFrames > 64) + SAL_WARN("sw.html", "Not importing any more FloatingFrames for fuzzing performance"); + else + { + InsertFloatingFrame(); + m_bCallNextToken = m_bInFloatingFrame && m_xTable; + } break; case HtmlTokenId::LINEBREAK: @@ -1469,7 +1490,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) // CR in PRE/LISTING/XMP { if( HtmlTokenId::NEWPARA==nToken || - m_pPam->GetPoint()->nContent.GetIndex() ) + m_pPam->GetPoint()->GetContentIndex() ) { AppendTextNode(); // there is no LF at this place // therefore it will cause no problems @@ -1490,9 +1511,9 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) break; case HtmlTokenId::LINEFEEDCHAR: - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode(); - if (!m_xTable && !m_xDoc->IsInHeaderFooter(m_pPam->GetPoint()->nNode)) + if (!m_xTable && !m_xDoc->IsInHeaderFooter(m_pPam->GetPoint()->GetNode())) { NewAttr(m_xAttrTab, &m_xAttrTab->pBreak, SvxFormatBreakItem(SvxBreak::PageBefore, RES_BREAK)); EndAttr( m_xAttrTab->pBreak, false ); @@ -1500,20 +1521,21 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) break; case HtmlTokenId::TEXTTOKEN: + case HtmlTokenId::CDATA: // insert string without spanning attributes at the end. - if( !aToken.isEmpty() && ' '==aToken[0] && !IsReadPRE() ) + if (!aToken.isEmpty() && ' ' == aToken[0] && !IsReadPRE() && !GetPreserveSpaces()) { - sal_Int32 nPos = m_pPam->GetPoint()->nContent.GetIndex(); - const SwTextNode* pTextNode = nPos ? m_pPam->GetPoint()->nNode.GetNode().GetTextNode() : nullptr; + sal_Int32 nPos = m_pPam->GetPoint()->GetContentIndex(); + const SwTextNode* pTextNode = nPos ? m_pPam->GetPoint()->GetNode().GetTextNode() : nullptr; if (pTextNode) { const OUString& rText = pTextNode->GetText(); sal_Unicode cLast = rText[--nPos]; if( ' ' == cLast || '\x0a' == cLast) - aToken = aToken.copy(1); + aToken.remove(0, 1); } else - aToken = aToken.copy(1); + aToken.remove(0, 1); if( aToken.isEmpty() ) { @@ -1524,7 +1546,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) if( !aToken.isEmpty() ) { - if( !m_bDocInitalized ) + if( !m_bDocInitialized ) DocumentDetected(); if (!m_aEmbeds.empty()) @@ -1532,6 +1554,12 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) // The text token is inside an OLE object, which means // alternate text. SwOLENode* pOLENode = m_aEmbeds.top(); + if (!pOLENode) + { + // <object> is mapped to an image -> ignore. + break; + } + if (SwFlyFrameFormat* pFormat = dynamic_cast<SwFlyFrameFormat*>(pOLENode->GetFlyFormat())) { @@ -1543,7 +1571,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) } } - m_xDoc->getIDocumentContentOperations().InsertString( *m_pPam, aToken ); + m_xDoc->getIDocumentContentOperations().InsertString( *m_pPam, aToken.toString()); // if there are temporary paragraph attributes and the // paragraph isn't empty then the paragraph attributes @@ -1753,10 +1781,10 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) if( m_nOpenParaToken != HtmlTokenId::NONE ) EndPara(); OSL_ENSURE(!m_xTable, "table in table not allowed here"); - if( !m_xTable && (IsNewDoc() || !m_pPam->GetNode().FindTableNode()) && - (m_pPam->GetPoint()->nNode.GetIndex() > + if( !m_xTable && (IsNewDoc() || !m_pPam->GetPointNode().FindTableNode()) && + (m_pPam->GetPoint()->GetNodeIndex() > m_xDoc->GetNodes().GetEndOfExtras().GetIndex() || - !m_pPam->GetNode().FindFootnoteStartNode() ) ) + !m_pPam->GetPointNode().FindFootnoteStartNode() ) ) { if ( m_nParaCnt < 5 ) Show(); // show what we have up to here @@ -1795,17 +1823,26 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) case HtmlTokenId::LI_ON: case HtmlTokenId::LISTHEADER_ON: if( m_nOpenParaToken != HtmlTokenId::NONE && - (m_pPam->GetPoint()->nContent.GetIndex() + (m_pPam->GetPoint()->GetContentIndex() || HtmlTokenId::PARABREAK_ON==m_nOpenParaToken) ) { // only finish paragraph for <P><LI>, not for <DD><LI> EndPara(); } - EndNumberBulletListItem( HtmlTokenId::NONE, false );// close <LI>/<LH> and don't set a template - NewNumberBulletListItem( nToken ); - break; + if (bFuzzing && m_nListItems > 1024) + { + SAL_WARN("sw.html", "skipping remaining bullet import for performance during fuzzing"); + } + else + { + EndNumberBulletListItem( HtmlTokenId::NONE, false );// close <LI>/<LH> and don't set a template + NewNumberBulletListItem( nToken ); + } + ++m_nListItems; + + break; case HtmlTokenId::LI_OFF: case HtmlTokenId::LISTHEADER_OFF: EndNumberBulletListItem( nToken, false ); @@ -1909,7 +1946,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) break; case HtmlTokenId::EMPHASIS_ON: - case HtmlTokenId::CITIATION_ON: + case HtmlTokenId::CITATION_ON: case HtmlTokenId::STRONG_ON: case HtmlTokenId::CODE_ON: case HtmlTokenId::SAMPLE_ON: @@ -1935,7 +1972,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) break; case HtmlTokenId::EMPHASIS_OFF: - case HtmlTokenId::CITIATION_OFF: + case HtmlTokenId::CITATION_OFF: case HtmlTokenId::STRONG_OFF: case HtmlTokenId::CODE_OFF: case HtmlTokenId::SAMPLE_OFF: @@ -2023,8 +2060,8 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) if( ' ' == aToken[ 3 ] && ' ' == aToken[ aToken.getLength()-3 ] ) { - OUString aComment( aToken.copy( 3, aToken.getLength()-5 ) ); - InsertComment(comphelper::string::strip(aComment, ' ')); + std::u16string_view aComment( aToken.subView( 3, aToken.getLength()-5 ) ); + InsertComment(OUString(comphelper::string::strip(aComment, ' '))); } else { @@ -2103,7 +2140,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) if( !aToken.isEmpty() ) { UnescapeToken(); - aComment.append(" ").append(aToken); + aComment.append(" " + aToken); } aComment.append(">"); InsertComment( aComment.makeStringAndClear() ); @@ -2111,7 +2148,7 @@ void SwHTMLParser::NextToken( HtmlTokenId nToken ) // if there are temporary paragraph attributes and the // paragraph isn't empty then the paragraph attributes are final. - if( !m_aParaAttrs.empty() && m_pPam->GetPoint()->nContent.GetIndex() ) + if( !m_aParaAttrs.empty() && m_pPam->GetPoint()->GetContentIndex() ) m_aParaAttrs.clear(); } @@ -2163,12 +2200,12 @@ bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode, bool bUpdateNum ) m_aParaAttrs.clear(); SwTextNode *pTextNode = (AM_SPACE==eMode || AM_NOSPACE==eMode) ? - m_pPam->GetPoint()->nNode.GetNode().GetTextNode() : nullptr; + m_pPam->GetPoint()->GetNode().GetTextNode() : nullptr; if (pTextNode) { const SvxULSpaceItem& rULSpace = - static_cast<const SvxULSpaceItem&>(pTextNode->SwContentNode::GetAttr( RES_UL_SPACE )); + pTextNode->SwContentNode::GetAttr( RES_UL_SPACE ); bool bChange = AM_NOSPACE==eMode ? rULSpace.GetLower() > 0 : rULSpace.GetLower() == 0; @@ -2202,8 +2239,7 @@ bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode, bool bUpdateNum ) // split character attributes and maybe set none, // which are set for the whole paragraph - const SwNodeIndex& rEndIdx = aOldPos.nNode; - const sal_Int32 nEndCnt = aOldPos.nContent.GetIndex(); + const sal_Int32 nEndCnt = aOldPos.GetContentIndex(); const SwPosition& rPos = *m_pPam->GetPoint(); HTMLAttr** pHTMLAttributes = reinterpret_cast<HTMLAttr**>(m_xAttrTab.get()); @@ -2217,14 +2253,14 @@ bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode, bool bUpdateNum ) while( pAttr ) { HTMLAttr *pNext = pAttr->GetNext(); - if( pAttr->GetSttParaIdx() < rEndIdx.GetIndex() || + if( pAttr->GetStartParagraphIdx() < aOldPos.GetNodeIndex() || (!bWholePara && - pAttr->GetSttPara() == rEndIdx && - pAttr->GetSttCnt() != nEndCnt) ) + pAttr->GetStartParagraph() == aOldPos.GetNode() && + pAttr->GetStartContent() != nEndCnt) ) { bWholePara = - pAttr->GetSttPara() == rEndIdx && - pAttr->GetSttCnt() == 0; + pAttr->GetStartParagraph() == aOldPos.GetNode() && + pAttr->GetStartContent() == 0; sal_Int32 nStt = pAttr->m_nStartContent; bool bScript = false; @@ -2236,14 +2272,14 @@ bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode, bool bUpdateNum ) if( bScript ) { const SwTextNode *pTextNd = - pAttr->GetSttPara().GetNode().GetTextNode(); + pAttr->GetStartParagraph().GetNode().GetTextNode(); OSL_ENSURE( pTextNd, "No text node" ); if( pTextNd ) { const OUString& rText = pTextNd->GetText(); sal_uInt16 nScriptText = g_pBreakIt->GetBreakIter()->getScriptType( - rText, pAttr->GetSttCnt() ); + rText, pAttr->GetStartContent() ); sal_Int32 nScriptEnd = g_pBreakIt->GetBreakIter() ->endOfScript( rText, nStt, nScriptText ); while (nScriptEnd < nEndCnt && nScriptEnd != -1) @@ -2251,7 +2287,7 @@ bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode, bool bUpdateNum ) if( nScriptItem == nScriptText ) { HTMLAttr *pSetAttr = - pAttr->Clone( rEndIdx, nScriptEnd ); + pAttr->Clone( aOldPos.GetNode(), nScriptEnd ); pSetAttr->m_nStartContent = nStt; pSetAttr->ClearPrev(); if( !pNext || bWholePara ) @@ -2276,7 +2312,7 @@ bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode, bool bUpdateNum ) if( bInsert ) { HTMLAttr *pSetAttr = - pAttr->Clone( rEndIdx, nEndCnt ); + pAttr->Clone( aOldPos.GetNode(), nEndCnt ); pSetAttr->m_nStartContent = nStt; // When the attribute is for the whole paragraph, the outer @@ -2327,7 +2363,7 @@ bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode, bool bUpdateNum ) SetNodeNum( nLvl ); } else - m_pPam->GetNode().GetTextNode()->ResetAttr( RES_PARATR_NUMRULE ); + m_pPam->GetPointNode().GetTextNode()->ResetAttr( RES_PARATR_NUMRULE ); } // We must set the attribute of the paragraph before now (because of JavaScript) @@ -2335,7 +2371,7 @@ bool SwHTMLParser::AppendTextNode( SwHTMLAppendMode eMode, bool bUpdateNum ) // Now it is time to get rid of all script dependent hints that are // equal to the settings in the style - SwTextNode *pTextNd = rEndIdx.GetNode().GetTextNode(); + SwTextNode *pTextNd = aOldPos.GetNode().GetTextNode(); OSL_ENSURE( pTextNd, "There is the txt node" ); size_t nCntAttr = (pTextNd && pTextNd->GetpSwpHints()) ? pTextNd->GetSwpHints().Count() : 0; @@ -2462,14 +2498,14 @@ void SwHTMLParser::AddParSpace() m_bNoParSpace = false; - sal_uLong nNdIdx = m_pPam->GetPoint()->nNode.GetIndex() - 1; + SwNodeOffset nNdIdx = m_pPam->GetPoint()->GetNodeIndex() - 1; SwTextNode *pTextNode = m_xDoc->GetNodes()[nNdIdx]->GetTextNode(); if( !pTextNode ) return; SvxULSpaceItem rULSpace = - static_cast<const SvxULSpaceItem&>(pTextNode->SwContentNode::GetAttr( RES_UL_SPACE )); + pTextNode->SwContentNode::GetAttr( RES_UL_SPACE ); if( rULSpace.GetLower() ) return; @@ -2558,7 +2594,7 @@ void SwHTMLParser::Show() // is the current node not visible anymore, then we use a bigger increment if( pVSh ) { - m_nParaCnt = (m_pPam->GetPoint()->nNode.GetNode().IsInVisibleArea(pVSh)) + m_nParaCnt = (m_pPam->GetPoint()->GetNode().IsInVisibleArea(pVSh)) ? 5 : 50; } } @@ -2643,15 +2679,12 @@ SwViewShell *SwHTMLParser::CallEndAction( bool bChkAction, bool bChkPtr ) if( !m_pActionViewShell || (bChkAction && !m_pActionViewShell->ActionPend()) ) return m_pActionViewShell; - if( dynamic_cast< const SwEditShell *>( m_pActionViewShell ) != nullptr ) + if (SwEditShell* pEditShell = dynamic_cast<SwEditShell*>(m_pActionViewShell)) { // Already scrolled?, then make sure that the view doesn't move! const bool bOldLock = m_pActionViewShell->IsViewLocked(); m_pActionViewShell->LockView( true ); - const bool bOldEndActionByVirDev = m_pActionViewShell->IsEndActionByVirDev(); - m_pActionViewShell->SetEndActionByVirDev( true ); - static_cast<SwEditShell*>(m_pActionViewShell)->EndAction(); - m_pActionViewShell->SetEndActionByVirDev( bOldEndActionByVirDev ); + pEditShell->EndAction(); m_pActionViewShell->LockView( bOldLock ); // bChkJumpMark is only set when the object was also found @@ -2710,9 +2743,9 @@ void SwHTMLFrameFormatListener::Notify(const SfxHint& rHint) void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, std::deque<std::unique_ptr<HTMLAttr>> *pPostIts ) { - std::unique_ptr<SwPaM> pAttrPam( new SwPaM( *m_pPam->GetPoint() ) ); - const SwNodeIndex& rEndIdx = m_pPam->GetPoint()->nNode; - const sal_Int32 nEndCnt = m_pPam->GetPoint()->nContent.GetIndex(); + SwPaM aAttrPam( *m_pPam->GetPoint() ); + const SwPosition& rEndPos = *m_pPam->GetPoint(); + const sal_Int32 nEndCnt = m_pPam->GetPoint()->GetContentIndex(); HTMLAttr* pAttr; SwContentNode* pCNd; @@ -2723,7 +2756,7 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, pAttr = m_aSetAttrTab[ --n ]; sal_uInt16 nWhich = pAttr->m_pItem->Which(); - sal_uLong nEndParaIdx = pAttr->GetEndParaIdx(); + SwNodeOffset nEndParaIdx = pAttr->GetEndParagraphIdx(); bool bSetAttr; if( bChkEnd ) { @@ -2733,23 +2766,23 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, // the whole paragraph, because they could be from a paragraph style // which can't be set. Because the attributes are inserted with // SETATTR_DONTREPLACE, they should be able to be set later. - bSetAttr = ( nEndParaIdx < rEndIdx.GetIndex() && - (RES_LR_SPACE != nWhich || !GetNumInfo().GetNumRule()) ) || + bSetAttr = ( nEndParaIdx < rEndPos.GetNodeIndex() && + ((RES_MARGIN_FIRSTLINE != nWhich && RES_MARGIN_TEXTLEFT != nWhich) || !GetNumInfo().GetNumRule()) ) || ( !pAttr->IsLikePara() && - nEndParaIdx == rEndIdx.GetIndex() && - pAttr->GetEndCnt() < nEndCnt && + nEndParaIdx == rEndPos.GetNodeIndex() && + pAttr->GetEndContent() < nEndCnt && (isCHRATR(nWhich) || isTXTATR_WITHEND(nWhich)) ) || ( bBeforeTable && - nEndParaIdx == rEndIdx.GetIndex() && - !pAttr->GetEndCnt() ); + nEndParaIdx == rEndPos.GetNodeIndex() && + !pAttr->GetEndContent() ); } else { // Attributes in body nodes array section shouldn't be set if we are in a // special nodes array section, but vice versa it's possible. - sal_uLong nEndOfIcons = m_xDoc->GetNodes().GetEndOfExtras().GetIndex(); - bSetAttr = nEndParaIdx < rEndIdx.GetIndex() || - rEndIdx.GetIndex() > nEndOfIcons || + SwNodeOffset nEndOfIcons = m_xDoc->GetNodes().GetEndOfExtras().GetIndex(); + bSetAttr = nEndParaIdx < rEndPos.GetNodeIndex() || + rEndPos.GetNodeIndex() > nEndOfIcons || nEndParaIdx <= nEndOfIcons; } @@ -2783,7 +2816,7 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, { // because of the awful deleting of nodes an index can also // point to an end node :-( - if ( (pAttr->GetSttPara() == pAttr->GetEndPara()) && + if ( (pAttr->GetStartParagraph() == pAttr->GetEndParagraph()) && !isTXTATR_NOEND(nWhich) ) { // when the end index also points to the node, we don't @@ -2792,7 +2825,7 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, pAttr = pPrev; continue; } - pCNd = m_xDoc->GetNodes().GoNext( &(pAttr->m_nStartPara) ); + pCNd = SwNodes::GoNext(&(pAttr->m_nStartPara)); if( pCNd ) pAttr->m_nStartContent = 0; else @@ -2803,16 +2836,15 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, continue; } } - pAttrPam->GetPoint()->nNode = pAttr->m_nStartPara; // because of the deleting of BRs the start index can also // point behind the end the text if( pAttr->m_nStartContent > pCNd->Len() ) pAttr->m_nStartContent = pCNd->Len(); - pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->m_nStartContent ); + aAttrPam.GetPoint()->Assign( *pCNd, pAttr->m_nStartContent ); - pAttrPam->SetMark(); - if ( (pAttr->GetSttPara() != pAttr->GetEndPara()) && + aAttrPam.SetMark(); + if ( (pAttr->GetStartParagraph() != pAttr->GetEndParagraph()) && !isTXTATR_NOEND(nWhich) ) { pCNd = pAttr->m_nEndPara.GetNode().GetContentNode(); @@ -2824,14 +2856,12 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, else { OSL_ENSURE( false, "SetAttr: GoPrevious() failed!" ); - pAttrPam->DeleteMark(); + aAttrPam.DeleteMark(); delete pAttr; pAttr = pPrev; continue; } } - - pAttrPam->GetPoint()->nNode = pAttr->m_nEndPara; } else if( pAttr->IsLikePara() ) { @@ -2843,10 +2873,10 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, if( pAttr->m_nEndContent > pCNd->Len() ) pAttr->m_nEndContent = pCNd->Len(); - pAttrPam->GetPoint()->nContent.Assign( pCNd, pAttr->m_nEndContent ); + aAttrPam.GetPoint()->Assign( *pCNd, pAttr->m_nEndContent ); if( bBeforeTable && - pAttrPam->GetPoint()->nNode.GetIndex() == - rEndIdx.GetIndex() ) + aAttrPam.GetPoint()->GetNodeIndex() == + rEndPos.GetNodeIndex() ) { // If we're before inserting a table and the attribute ends // in the current node, then we must end it in the previous @@ -2854,16 +2884,16 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, if( nWhich != RES_BREAK && nWhich != RES_PAGEDESC && !isTXTATR_NOEND(nWhich) ) { - if( pAttrPam->GetMark()->nNode.GetIndex() != - rEndIdx.GetIndex() ) + if( aAttrPam.GetMark()->GetNodeIndex() != + rEndPos.GetNodeIndex() ) { - OSL_ENSURE( !pAttrPam->GetPoint()->nContent.GetIndex(), + OSL_ENSURE( !aAttrPam.GetPoint()->GetContentIndex(), "Content-Position before table not 0???" ); - pAttrPam->Move( fnMoveBackward ); + aAttrPam.Move( fnMoveBackward ); } else { - pAttrPam->DeleteMark(); + aAttrPam.DeleteMark(); delete pAttr; pAttr = pPrev; continue; @@ -2879,11 +2909,11 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, IDocumentMarkAccess* const pMarkAccess = m_xDoc->getIDocumentMarkAccess(); IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark( sName ); if( ppBkmk != pMarkAccess->getAllMarksEnd() && - (*ppBkmk)->GetMarkStart() == *pAttrPam->GetPoint() ) + (*ppBkmk)->GetMarkStart() == *aAttrPam.GetPoint() ) break; // do not generate duplicates on this position - pAttrPam->DeleteMark(); + aAttrPam.DeleteMark(); const ::sw::mark::IMark* const pNewMark = pMarkAccess->makeMark( - *pAttrPam, + aAttrPam, sName, IDocumentMarkAccess::MarkType::BOOKMARK, ::sw::mark::InsertMode::New); @@ -2914,22 +2944,10 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, aFields.emplace_back( pAttr); } } - pAttrPam->DeleteMark(); + aAttrPam.DeleteMark(); pAttr = pPrev; continue; - case RES_LR_SPACE: - if( pAttrPam->GetPoint()->nNode.GetIndex() == - pAttrPam->GetMark()->nNode.GetIndex()) - { - // because of numbering set this attribute directly at node - pCNd->SetAttr( *pAttr->m_pItem ); - break; - } - OSL_ENSURE( false, - "LRSpace set over multiple paragraphs!" ); - [[fallthrough]]; // (shouldn't reach this point anyway) - // tdf#94088 expand RES_BACKGROUND to the new fill attribute // definitions in the range [XATTR_FILL_FIRST .. XATTR_FILL_LAST]. // This is the right place in the future if the adapted fill attributes @@ -2937,12 +2955,30 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, case RES_BACKGROUND: { const SvxBrushItem& rBrush = static_cast< SvxBrushItem& >(*pAttr->m_pItem); - SfxItemSet aNewSet(m_xDoc->GetAttrPool(), svl::Items<XATTR_FILL_FIRST, XATTR_FILL_LAST>{}); + SfxItemSetFixed<XATTR_FILL_FIRST, XATTR_FILL_LAST> aNewSet(m_xDoc->GetAttrPool()); setSvxBrushItemAsFillAttributesToTargetSet(rBrush, aNewSet); - m_xDoc->getIDocumentContentOperations().InsertItemSet(*pAttrPam, aNewSet, SetAttrMode::DONTREPLACE); + m_xDoc->getIDocumentContentOperations().InsertItemSet(aAttrPam, aNewSet, SetAttrMode::DONTREPLACE); break; } + + case RES_LR_SPACE: + assert(false); + break; + + case RES_MARGIN_FIRSTLINE: + case RES_MARGIN_TEXTLEFT: + case RES_MARGIN_RIGHT: + if( aAttrPam.GetPoint()->GetNodeIndex() == + aAttrPam.GetMark()->GetNodeIndex()) + { + // because of numbering set this attribute directly at node + pCNd->SetAttr( *pAttr->m_pItem ); + break; + } + OSL_ENSURE( false, + "LRSpace set over multiple paragraphs!" ); + [[fallthrough]]; // (shouldn't reach this point anyway) default: // maybe jump to a bookmark @@ -2954,9 +2990,9 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, m_eJumpTo = JumpToMarks::NONE; } - m_xDoc->getIDocumentContentOperations().InsertPoolItem( *pAttrPam, *pAttr->m_pItem, SetAttrMode::DONTREPLACE ); + m_xDoc->getIDocumentContentOperations().InsertPoolItem( aAttrPam, *pAttr->m_pItem, SetAttrMode::DONTREPLACE ); } - pAttrPam->DeleteMark(); + aAttrPam.DeleteMark(); delete pAttr; pAttr = pPrev; @@ -2978,31 +3014,29 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, const SwFormatAnchor& rAnchor = pFrameFormat->GetAnchor(); OSL_ENSURE( RndStdIds::FLY_AT_PARA == rAnchor.GetAnchorId(), "Only At-Para flys need special handling" ); - const SwPosition *pFlyPos = rAnchor.GetContentAnchor(); - sal_uLong nFlyParaIdx = pFlyPos->nNode.GetIndex(); + SwNodeOffset nFlyParaIdx = rAnchor.GetAnchorNode()->GetIndex(); bool bMoveFly; if( bChkEnd ) { - bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() || - ( nFlyParaIdx == rEndIdx.GetIndex() && + bMoveFly = nFlyParaIdx < rEndPos.GetNodeIndex() || + ( nFlyParaIdx == rEndPos.GetNodeIndex() && m_aMoveFlyCnts[n] < nEndCnt ); } else { - sal_uLong nEndOfIcons = m_xDoc->GetNodes().GetEndOfExtras().GetIndex(); - bMoveFly = nFlyParaIdx < rEndIdx.GetIndex() || - rEndIdx.GetIndex() > nEndOfIcons || + SwNodeOffset nEndOfIcons = m_xDoc->GetNodes().GetEndOfExtras().GetIndex(); + bMoveFly = nFlyParaIdx < rEndPos.GetNodeIndex() || + rEndPos.GetNodeIndex() > nEndOfIcons || nFlyParaIdx <= nEndOfIcons; } if( bMoveFly ) { pFrameFormat->DelFrames(); - *pAttrPam->GetPoint() = *pFlyPos; - pAttrPam->GetPoint()->nContent.Assign( pAttrPam->GetContentNode(), - m_aMoveFlyCnts[n] ); + *aAttrPam.GetPoint() = *rAnchor.GetContentAnchor(); + aAttrPam.GetPoint()->SetContent( m_aMoveFlyCnts[n] ); SwFormatAnchor aAnchor( rAnchor ); aAnchor.SetType( RndStdIds::FLY_AT_CHAR ); - aAnchor.SetAnchor( pAttrPam->GetPoint() ); + aAnchor.SetAnchor( aAttrPam.GetPoint() ); pFrameFormat->SetFormatAttr( aAnchor ); const SwFormatHoriOrient& rHoriOri = pFrameFormat->GetHoriOrient(); @@ -3028,20 +3062,19 @@ void SwHTMLParser::SetAttr_( bool bChkEnd, bool bBeforeTable, for (auto & field : aFields) { pCNd = field->m_nStartPara.GetNode().GetContentNode(); - pAttrPam->GetPoint()->nNode = field->m_nStartPara; - pAttrPam->GetPoint()->nContent.Assign( pCNd, field->m_nStartContent ); + aAttrPam.GetPoint()->Assign( *pCNd, field->m_nStartContent ); if( bBeforeTable && - pAttrPam->GetPoint()->nNode.GetIndex() == rEndIdx.GetIndex() ) + aAttrPam.GetPoint()->GetNodeIndex() == rEndPos.GetNodeIndex() ) { OSL_ENSURE( !bBeforeTable, "Aha, the case does occur" ); - OSL_ENSURE( !pAttrPam->GetPoint()->nContent.GetIndex(), + OSL_ENSURE( !aAttrPam.GetPoint()->GetContentIndex(), "Content-Position before table not 0???" ); // !!! - pAttrPam->Move( fnMoveBackward ); + aAttrPam.Move( fnMoveBackward ); } - m_xDoc->getIDocumentContentOperations().InsertPoolItem( *pAttrPam, *field->m_pItem ); + m_xDoc->getIDocumentContentOperations().InsertPoolItem( aAttrPam, *field->m_pItem ); field.reset(); } @@ -3074,8 +3107,8 @@ bool SwHTMLParser::EndAttr( HTMLAttr* pAttr, bool bChkEmpty ) OSL_ENSURE( ppHead, "No list header attribute found!" ); // save the current position as end position - const SwNodeIndex* pEndIdx = &m_pPam->GetPoint()->nNode; - sal_Int32 nEndCnt = m_pPam->GetPoint()->nContent.GetIndex(); + const SwPosition* pEndPos = m_pPam->GetPoint(); + sal_Int32 nEndCnt = m_pPam->GetPoint()->GetContentIndex(); // Is the last started or an earlier started attribute being ended? HTMLAttr *pLast = nullptr; @@ -3096,11 +3129,11 @@ bool SwHTMLParser::EndAttr( HTMLAttr* pAttr, bool bChkEmpty ) bool bMoveBack = false; sal_uInt16 nWhich = pAttr->m_pItem->Which(); if( !nEndCnt && RES_PARATR_BEGIN <= nWhich && - *pEndIdx != pAttr->GetSttPara() ) + pEndPos->GetNodeIndex() != pAttr->GetStartParagraph().GetIndex() ) { // Then move back one position in the content! bMoveBack = m_pPam->Move( fnMoveBackward ); - nEndCnt = m_pPam->GetPoint()->nContent.GetIndex(); + nEndCnt = m_pPam->GetPoint()->GetContentIndex(); } // now end the attribute @@ -3112,12 +3145,12 @@ bool SwHTMLParser::EndAttr( HTMLAttr* pAttr, bool bChkEmpty ) // does it have a non-empty range? if( !bChkEmpty || (RES_PARATR_BEGIN <= nWhich && bMoveBack) || RES_PAGEDESC == nWhich || RES_BREAK == nWhich || - *pEndIdx != pAttr->GetSttPara() || - nEndCnt != pAttr->GetSttCnt() ) + pEndPos->GetNodeIndex() != pAttr->GetStartParagraph().GetIndex() || + nEndCnt != pAttr->GetStartContent() ) { bInsert = true; // We do some optimization for script dependent attributes here. - if( *pEndIdx == pAttr->GetSttPara() ) + if( pEndPos->GetNodeIndex() == pAttr->GetStartParagraph().GetIndex() ) { lcl_swhtml_getItemInfo( *pAttr, bScript, nScriptItem ); } @@ -3128,21 +3161,21 @@ bool SwHTMLParser::EndAttr( HTMLAttr* pAttr, bool bChkEmpty ) } const SwTextNode *pTextNd = (bInsert && bScript) ? - pAttr->GetSttPara().GetNode().GetTextNode() : + pAttr->GetStartParagraph().GetNode().GetTextNode() : nullptr; if (pTextNd) { const OUString& rText = pTextNd->GetText(); sal_uInt16 nScriptText = g_pBreakIt->GetBreakIter()->getScriptType( - rText, pAttr->GetSttCnt() ); + rText, pAttr->GetStartContent() ); sal_Int32 nScriptEnd = g_pBreakIt->GetBreakIter() - ->endOfScript( rText, pAttr->GetSttCnt(), nScriptText ); + ->endOfScript( rText, pAttr->GetStartContent(), nScriptText ); while (nScriptEnd < nEndCnt && nScriptEnd != -1) { if( nScriptItem == nScriptText ) { - HTMLAttr *pSetAttr = pAttr->Clone( *pEndIdx, nScriptEnd ); + HTMLAttr *pSetAttr = pAttr->Clone( pEndPos->GetNode(), nScriptEnd ); pSetAttr->ClearPrev(); if( pNext ) pNext->InsertPrev( pSetAttr ); @@ -3164,7 +3197,7 @@ bool SwHTMLParser::EndAttr( HTMLAttr* pAttr, bool bChkEmpty ) } if( bInsert ) { - pAttr->m_nEndPara = *pEndIdx; + pAttr->m_nEndPara = pEndPos->GetNode(); pAttr->m_nEndContent = nEndCnt; pAttr->m_bInsAtStart = RES_TXTATR_INETFMT != nWhich && RES_TXTATR_CHARFMT != nWhich; @@ -3319,20 +3352,19 @@ void SwHTMLParser::SplitAttrTab( std::shared_ptr<HTMLAttrTable> const & rNewAttr "Danger: there are non-final paragraph attributes"); m_aParaAttrs.clear(); - const SwNodeIndex& nSttIdx = m_pPam->GetPoint()->nNode; - SwNodeIndex nEndIdx( nSttIdx ); + SwNodeIndex nEndIdx( m_pPam->GetPoint()->GetNode() ); // close all still open attributes and re-open them after the table HTMLAttr** pHTMLAttributes = reinterpret_cast<HTMLAttr**>(m_xAttrTab.get()); HTMLAttr** pSaveAttributes = reinterpret_cast<HTMLAttr**>(rNewAttrTab.get()); bool bSetAttr = true; - const sal_Int32 nSttCnt = m_pPam->GetPoint()->nContent.GetIndex(); + const sal_Int32 nSttCnt = m_pPam->GetPoint()->GetContentIndex(); sal_Int32 nEndCnt = nSttCnt; if( bMoveEndBack ) { - sal_uLong nOldEnd = nEndIdx.GetIndex(); - sal_uLong nTmpIdx; + SwNodeOffset nOldEnd = nEndIdx.GetIndex(); + SwNodeOffset nTmpIdx; if( ( nTmpIdx = m_xDoc->GetNodes().GetEndOfExtras().GetIndex()) >= nOldEnd || ( nTmpIdx = m_xDoc->GetNodes().GetEndOfAutotext().GetIndex()) >= nOldEnd ) { @@ -3355,15 +3387,15 @@ void SwHTMLParser::SplitAttrTab( std::shared_ptr<HTMLAttrTable> const & rNewAttr HTMLAttr *pPrev = pAttr->GetPrev(); if( bSetAttr && - ( pAttr->GetSttParaIdx() < nEndIdx.GetIndex() || - (pAttr->GetSttPara() == nEndIdx && - pAttr->GetSttCnt() != nEndCnt) ) ) + ( pAttr->GetStartParagraphIdx() < nEndIdx.GetIndex() || + (pAttr->GetStartParagraph() == nEndIdx && + pAttr->GetStartContent() != nEndCnt) ) ) { // The attribute must be set before the list. We need the // original and therefore we clone it, because pointer to the // attribute exist in the other contexts. The Next-List is lost // in doing so, but the Previous-List is preserved. - HTMLAttr *pSetAttr = pAttr->Clone( nEndIdx, nEndCnt ); + HTMLAttr *pSetAttr = pAttr->Clone( nEndIdx.GetNode(), nEndCnt ); if( pNext ) pNext->InsertPrev( pSetAttr ); @@ -3391,7 +3423,7 @@ void SwHTMLParser::SplitAttrTab( std::shared_ptr<HTMLAttrTable> const & rNewAttr } // set the start of the attribute anew and break link - pAttr->Reset(nSttIdx, nSttCnt, pSaveAttributes, rNewAttrTab); + pAttr->Reset(m_pPam->GetPoint()->GetNode(), nSttCnt, pSaveAttributes, rNewAttrTab); if (*pSaveAttributes) { @@ -3605,7 +3637,7 @@ void SwHTMLParser::NewBasefontAttr() switch( rOption.GetToken() ) { case HtmlOptionId::SIZE: - nSize = static_cast<sal_uInt16>(rOption.GetNumber()); + nSize = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::ID: aId = rOption.GetString(); @@ -3721,7 +3753,7 @@ void SwHTMLParser::NewFontAttr( HtmlTokenId nToken ) else if( nSSize > 7 ) nSSize = 7; - nSize = static_cast<sal_uInt16>(nSSize); + nSize = o3tl::narrowing<sal_uInt16>(nSSize); nFontHeight = m_aFontHeights[nSize-1]; } break; @@ -3914,7 +3946,7 @@ void SwHTMLParser::EndFontAttr( HtmlTokenId nToken ) void SwHTMLParser::NewPara() { - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_SPACE ); else AddParSpace(); @@ -3946,6 +3978,11 @@ void SwHTMLParser::NewPara() case HtmlOptionId::DIR: aDir = rOption.GetString(); break; + case HtmlOptionId::XML_SPACE: + if (rOption.GetString() == "preserve") + SetPreserveSpaces(true); + break; + default: break; } } @@ -3969,6 +4006,9 @@ void SwHTMLParser::NewPara() "Class is not considered" ); DoPositioning( aItemSet, aPropInfo, xCntxt.get() ); InsertAttrs( aItemSet, aPropInfo, xCntxt.get() ); + + if (aPropInfo.m_bPreserveSpace) + SetPreserveSpaces(true); } } @@ -3993,15 +4033,16 @@ void SwHTMLParser::EndPara( bool bReal ) if (HtmlTokenId::LI_ON==m_nOpenParaToken && m_xTable) { #if OSL_DEBUG_LEVEL > 0 - const SwNumRule *pNumRule = m_pPam->GetNode().GetTextNode()->GetNumRule(); + const SwNumRule *pNumRule = m_pPam->GetPointNode().GetTextNode()->GetNumRule(); OSL_ENSURE( pNumRule, "Where is the NumRule" ); #endif } - // Netscape skips empty paragraphs, we do the same. + // Netscape skips empty paragraphs, we do the same; unless in XHTML mode, which prefers mapping + // the source document to the doc model 1:1 if possible. if( bReal ) { - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if (m_pPam->GetPoint()->GetContentIndex() || m_bXHTML) AppendTextNode( AM_SPACE ); else AddParSpace(); @@ -4033,6 +4074,7 @@ void SwHTMLParser::EndPara( bool bReal ) SetTextCollAttrs(); m_nOpenParaToken = HtmlTokenId::NONE; + SetPreserveSpaces(false); } void SwHTMLParser::NewHeading( HtmlTokenId nToken ) @@ -4070,7 +4112,7 @@ void SwHTMLParser::NewHeading( HtmlTokenId nToken ) } // open a new paragraph - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_SPACE ); else AddParSpace(); @@ -4124,7 +4166,7 @@ void SwHTMLParser::NewHeading( HtmlTokenId nToken ) void SwHTMLParser::EndHeading() { // open a new paragraph - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_SPACE ); else AddParSpace(); @@ -4219,7 +4261,7 @@ void SwHTMLParser::NewTextFormatColl( HtmlTokenId nToken, sal_uInt16 nColl ) OSL_ENSURE( false, "unknown style" ); break; } - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( eMode ); else if( AM_SPACE==eMode ) AddParSpace(); @@ -4272,7 +4314,7 @@ void SwHTMLParser::EndTextFormatColl( HtmlTokenId nToken ) OSL_ENSURE( false, "unknown style" ); break; } - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( eMode ); else if( AM_SPACE==eMode ) AddParSpace(); @@ -4323,7 +4365,7 @@ void SwHTMLParser::NewDefList() // open a new paragraph bool bSpace = (GetNumInfo().GetDepth() + m_nDefListDeep) == 0; - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE ); else if( bSpace ) AddParSpace(); @@ -4367,10 +4409,10 @@ void SwHTMLParser::NewDefList() { // and the one of the DT-style of the current level - SvxLRSpaceItem rLRSpace = + SvxTextLeftMarginItem const& rTextLeftMargin = m_pCSS1Parser->GetTextFormatColl(RES_POOLCOLL_HTML_DD, OUString()) - ->GetLRSpace(); - nLeft = nLeft + static_cast< sal_uInt16 >(rLRSpace.GetTextLeft()); + ->GetTextLeftMargin(); + nLeft = nLeft + static_cast<sal_uInt16>(rTextLeftMargin.GetTextLeft()); } xCntxt->SetMargins( nLeft, nRight, nIndent ); @@ -4398,7 +4440,7 @@ void SwHTMLParser::NewDefList() void SwHTMLParser::EndDefList() { bool bSpace = (GetNumInfo().GetDepth() + m_nDefListDeep) == 1; - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( bSpace ? AM_SPACE : AM_SOFTNOSPACE ); else if( bSpace ) AddParSpace(); @@ -4461,7 +4503,7 @@ void SwHTMLParser::NewDefListItem( HtmlTokenId nToken ) void SwHTMLParser::EndDefListItem( HtmlTokenId nToken ) { // open a new paragraph - if( nToken == HtmlTokenId::NONE && m_pPam->GetPoint()->nContent.GetIndex() ) + if( nToken == HtmlTokenId::NONE && m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_SOFTNOSPACE ); // search context matching the token and fetch it from stack @@ -4514,14 +4556,12 @@ void SwHTMLParser::EndDefListItem( HtmlTokenId nToken ) bool SwHTMLParser::HasCurrentParaFlys( bool bNoSurroundOnly, bool bSurroundOnly ) const { - SwNodeIndex& rNodeIdx = m_pPam->GetPoint()->nNode; + SwNode& rNode = m_pPam->GetPoint()->GetNode(); - const SwFrameFormats& rFrameFormatTable = *m_xDoc->GetSpzFrameFormats(); bool bFound = false; - for ( size_t i=0; i<rFrameFormatTable.size(); i++ ) + for(sw::SpzFrameFormat* pFormat: *m_xDoc->GetSpzFrameFormats()) { - const SwFrameFormat *const pFormat = rFrameFormatTable[i]; SwFormatAnchor const*const pAnchor = &pFormat->GetAnchor(); // A frame was found, when // - it is paragraph-bound, and @@ -4529,11 +4569,11 @@ bool SwHTMLParser::HasCurrentParaFlys( bool bNoSurroundOnly, // - every paragraph-bound frame counts, or // - (only frames without wrapping count and) the frame doesn't have // a wrapping - SwPosition const*const pAPos = pAnchor->GetContentAnchor(); - if (pAPos && + SwNode const*const pAnchorNode = pAnchor->GetAnchorNode(); + if (pAnchorNode && ((RndStdIds::FLY_AT_PARA == pAnchor->GetAnchorId()) || (RndStdIds::FLY_AT_CHAR == pAnchor->GetAnchorId())) && - pAPos->nNode == rNodeIdx ) + *pAnchorNode == rNode ) { if( !(bNoSurroundOnly || bSurroundOnly) ) { @@ -4579,7 +4619,7 @@ bool SwHTMLParser::HasCurrentParaFlys( bool bNoSurroundOnly, const SwFormatColl *SwHTMLParser::GetCurrFormatColl() const { - const SwContentNode* pCNd = m_pPam->GetContentNode(); + const SwContentNode* pCNd = m_pPam->GetPointContentNode(); return pCNd ? &pCNd->GetAnyFormatColl() : nullptr; } @@ -4596,7 +4636,14 @@ void SwHTMLParser::SetTextCollAttrs( HTMLAttrContext *pContext ) sal_uInt16 nLeftMargin = 0, nRightMargin = 0; // the margins and short nFirstLineIndent = 0; // indentations - for( auto i = m_nContextStAttrMin; i < m_aContexts.size(); ++i ) + auto nDepth = m_aContexts.size(); + if (bFuzzing && nDepth > 128) + { + SAL_WARN("sw.html", "Not applying any more text collection attributes to a deeply nested node for fuzzing performance"); + nDepth = 0; + } + + for (auto i = m_nContextStAttrMin; i < nDepth; ++i) { const HTMLAttrContext *pCntxt = m_aContexts[i].get(); @@ -4673,7 +4720,7 @@ void SwHTMLParser::SetTextCollAttrs( HTMLAttrContext *pContext ) else { // Maybe a default style exists? - nColl = pCntxt->GetDfltTextFormatColl(); + nColl = pCntxt->GetDefaultTextFormatColl(); if( nColl ) nDfltColl = nColl; } @@ -4702,24 +4749,20 @@ void SwHTMLParser::SetTextCollAttrs( HTMLAttrContext *pContext ) const SwTextFormatColl *pTopColl = m_pCSS1Parser->GetTextFormatColl( nTopColl, rTopClass ); const SfxItemSet& rItemSet = pTopColl->GetAttrSet(); - const SfxPoolItem *pItem; - if( SfxItemState::SET == rItemSet.GetItemState(RES_LR_SPACE,true, &pItem) ) + if (rItemSet.GetItemIfSet(RES_MARGIN_FIRSTLINE) + || rItemSet.GetItemIfSet(RES_MARGIN_TEXTLEFT) + || rItemSet.GetItemIfSet(RES_MARGIN_RIGHT)) { - const SvxLRSpaceItem *pLRItem = - static_cast<const SvxLRSpaceItem *>(pItem); - - sal_Int32 nLeft = pLRItem->GetTextLeft(); - sal_Int32 nRight = pLRItem->GetRight(); - nFirstLineIndent = pLRItem->GetTextFirstLineOffset(); + sal_Int32 nLeft = rItemSet.Get(RES_MARGIN_TEXTLEFT).GetTextLeft(); + sal_Int32 nRight = rItemSet.Get(RES_MARGIN_RIGHT).GetRight(); + nFirstLineIndent = rItemSet.Get(RES_MARGIN_FIRSTLINE).GetTextFirstLineOffset(); // In Definition lists the margins also contain the margins from the previous levels if( RES_POOLCOLL_HTML_DD == nTopColl ) { - const SvxLRSpaceItem& rDTLRSpace = m_pCSS1Parser - ->GetTextFormatColl(RES_POOLCOLL_HTML_DT, OUString()) - ->GetLRSpace(); - nLeft -= rDTLRSpace.GetTextLeft(); - nRight -= rDTLRSpace.GetRight(); + auto const*const pColl(m_pCSS1Parser->GetTextFormatColl(RES_POOLCOLL_HTML_DT, OUString())); + nLeft -= pColl->GetTextLeftMargin().GetTextLeft(); + nRight -= pColl->GetRightMargin().GetRight(); } else if( RES_POOLCOLL_HTML_DT == nTopColl ) { @@ -4734,10 +4777,8 @@ void SwHTMLParser::SetTextCollAttrs( HTMLAttrContext *pContext ) pContext->SetMargins( nLeftMargin, nRightMargin, nFirstLineIndent ); } - if( SfxItemState::SET == rItemSet.GetItemState(RES_UL_SPACE,true, &pItem) ) + if( const SvxULSpaceItem* pULItem = rItemSet.GetItemIfSet(RES_UL_SPACE) ) { - const SvxULSpaceItem *pULItem = - static_cast<const SvxULSpaceItem *>(pItem); pContext->SetULSpace( pULItem->GetUpper(), pULItem->GetLower() ); } } @@ -4746,13 +4787,18 @@ void SwHTMLParser::SetTextCollAttrs( HTMLAttrContext *pContext ) if( !pCollToSet ) { pCollToSet = m_pCSS1Parser->GetTextCollFromPool( nDfltColl ); - const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace(); if( !nLeftMargin ) - nLeftMargin = static_cast< sal_uInt16 >(rLRItem.GetTextLeft()); + { + nLeftMargin = static_cast<sal_uInt16>(pCollToSet->GetTextLeftMargin().GetTextLeft()); + } if( !nRightMargin ) - nRightMargin = static_cast< sal_uInt16 >(rLRItem.GetRight()); + { + nRightMargin = static_cast<sal_uInt16>(pCollToSet->GetRightMargin().GetRight()); + } if( !nFirstLineIndent ) - nFirstLineIndent = rLRItem.GetTextFirstLineOffset(); + { + nFirstLineIndent = pCollToSet->GetFirstLineIndent().GetTextFirstLineOffset(); + } } // remove previous hard attribution of paragraph @@ -4764,25 +4810,41 @@ void SwHTMLParser::SetTextCollAttrs( HTMLAttrContext *pContext ) m_xDoc->SetTextFormatColl( *m_pPam, pCollToSet ); // if applicable correct the paragraph indent - const SvxLRSpaceItem& rLRItem = pCollToSet->GetLRSpace(); - bool bSetLRSpace = nLeftMargin != rLRItem.GetTextLeft() || - nFirstLineIndent != rLRItem.GetTextFirstLineOffset() || - nRightMargin != rLRItem.GetRight(); + const SvxFirstLineIndentItem & rFirstLine = pCollToSet->GetFirstLineIndent(); + const SvxTextLeftMarginItem & rTextLeftMargin = pCollToSet->GetTextLeftMargin(); + const SvxRightMarginItem & rRightMargin = pCollToSet->GetRightMargin(); + bool bSetLRSpace = nLeftMargin != rTextLeftMargin.GetTextLeft() || + nFirstLineIndent != rFirstLine.GetTextFirstLineOffset() || + nRightMargin != rRightMargin.GetRight(); if( bSetLRSpace ) { - SvxLRSpaceItem aLRItem( rLRItem ); - aLRItem.SetTextLeft( nLeftMargin ); - aLRItem.SetRight( nRightMargin ); - aLRItem.SetTextFirstLineOffset( nFirstLineIndent ); + SvxFirstLineIndentItem firstLine(rFirstLine); + SvxTextLeftMarginItem leftMargin(rTextLeftMargin); + SvxRightMarginItem rightMargin(rRightMargin); + firstLine.SetTextFirstLineOffset(nFirstLineIndent); + leftMargin.SetTextLeft(nLeftMargin); + rightMargin.SetRight(nRightMargin); if( pItemSet ) - pItemSet->Put( aLRItem ); + { + pItemSet->Put(firstLine); + pItemSet->Put(leftMargin); + pItemSet->Put(rightMargin); + } else { - NewAttr(m_xAttrTab, &m_xAttrTab->pLRSpace, aLRItem); - m_xAttrTab->pLRSpace->SetLikePara(); - m_aParaAttrs.push_back( m_xAttrTab->pLRSpace ); - EndAttr( m_xAttrTab->pLRSpace, false ); + NewAttr(m_xAttrTab, &m_xAttrTab->pFirstLineIndent, firstLine); + m_xAttrTab->pFirstLineIndent->SetLikePara(); + m_aParaAttrs.push_back(m_xAttrTab->pFirstLineIndent); + EndAttr(m_xAttrTab->pFirstLineIndent, false); + NewAttr(m_xAttrTab, &m_xAttrTab->pTextLeftMargin, leftMargin); + m_xAttrTab->pTextLeftMargin->SetLikePara(); + m_aParaAttrs.push_back(m_xAttrTab->pTextLeftMargin); + EndAttr(m_xAttrTab->pTextLeftMargin, false); + NewAttr(m_xAttrTab, &m_xAttrTab->pRightMargin, rightMargin); + m_xAttrTab->pRightMargin->SetLikePara(); + m_aParaAttrs.push_back(m_xAttrTab->pRightMargin); + EndAttr(m_xAttrTab->pRightMargin, false); } } @@ -4908,8 +4970,7 @@ void SwHTMLParser::InsertSpacer() // create an empty text frame // fetch the ItemSet - SfxItemSet aFrameSet( m_xDoc->GetAttrPool(), - svl::Items<RES_FRMATR_BEGIN, RES_FRMATR_END-1>{} ); + SfxItemSetFixed<RES_FRMATR_BEGIN, RES_FRMATR_END-1> aFrameSet( m_xDoc->GetAttrPool() ); if( !IsNewDoc() ) Reader::ResetFrameFormatAttrs( aFrameSet ); @@ -4944,23 +5005,18 @@ void SwHTMLParser::InsertSpacer() case HTML_SPTYPE_VERT: if( nSize > 0 ) { - if (Application::GetDefaultDevice()) - { - nSize = Application::GetDefaultDevice() - ->PixelToLogic( Size(0,nSize), - MapMode(MapUnit::MapTwip) ).Height(); - } + nSize = o3tl::convert(nSize, o3tl::Length::px, o3tl::Length::twip); // set a paragraph margin SwTextNode *pTextNode = nullptr; - if( !m_pPam->GetPoint()->nContent.GetIndex() ) + if( !m_pPam->GetPoint()->GetContentIndex() ) { // if possible change the bottom paragraph margin // of previous node SetAttr(); // set still open paragraph attributes - pTextNode = m_xDoc->GetNodes()[m_pPam->GetPoint()->nNode.GetIndex()-1] + pTextNode = m_xDoc->GetNodes()[m_pPam->GetPoint()->GetNodeIndex()-1] ->GetTextNode(); // If the previous paragraph isn't a text node, then now an @@ -4972,14 +5028,13 @@ void SwHTMLParser::InsertSpacer() if( pTextNode ) { - SvxULSpaceItem aULSpace( static_cast<const SvxULSpaceItem&>(pTextNode - ->SwContentNode::GetAttr( RES_UL_SPACE )) ); - aULSpace.SetLower( aULSpace.GetLower() + static_cast<sal_uInt16>(nSize) ); + SvxULSpaceItem aULSpace( pTextNode->SwContentNode::GetAttr( RES_UL_SPACE ) ); + aULSpace.SetLower( aULSpace.GetLower() + o3tl::narrowing<sal_uInt16>(nSize) ); pTextNode->SetAttr( aULSpace ); } else { - NewAttr(m_xAttrTab, &m_xAttrTab->pULSpace, SvxULSpaceItem(0, static_cast<sal_uInt16>(nSize), RES_UL_SPACE)); + NewAttr(m_xAttrTab, &m_xAttrTab->pULSpace, SvxULSpaceItem(0, o3tl::narrowing<sal_uInt16>(nSize), RES_UL_SPACE)); EndAttr( m_xAttrTab->pULSpace, false ); AppendTextNode(); // Don't change spacing! @@ -4992,14 +5047,9 @@ void SwHTMLParser::InsertSpacer() // If the paragraph is still empty, set first line // indentation, otherwise apply letter spacing over a space. - if (Application::GetDefaultDevice()) - { - nSize = Application::GetDefaultDevice() - ->PixelToLogic( Size(nSize,0), - MapMode(MapUnit::MapTwip) ).Width(); - } + nSize = o3tl::convert(nSize, o3tl::Length::px, o3tl::Length::twip); - if( !m_pPam->GetPoint()->nContent.GetIndex() ) + if( !m_pPam->GetPoint()->GetContentIndex() ) { sal_uInt16 nLeft=0, nRight=0; short nIndent = 0; @@ -5007,13 +5057,16 @@ void SwHTMLParser::InsertSpacer() GetMarginsFromContextWithNumberBullet( nLeft, nRight, nIndent ); nIndent = nIndent + static_cast<short>(nSize); - SvxLRSpaceItem aLRItem( RES_LR_SPACE ); - aLRItem.SetTextLeft( nLeft ); - aLRItem.SetRight( nRight ); - aLRItem.SetTextFirstLineOffset( nIndent ); + SvxFirstLineIndentItem const firstLine(nIndent, RES_MARGIN_FIRSTLINE); + SvxTextLeftMarginItem const leftMargin(nLeft, RES_MARGIN_TEXTLEFT); + SvxRightMarginItem const rightMargin(nRight, RES_MARGIN_RIGHT); - NewAttr(m_xAttrTab, &m_xAttrTab->pLRSpace, aLRItem); - EndAttr( m_xAttrTab->pLRSpace, false ); + NewAttr(m_xAttrTab, &m_xAttrTab->pFirstLineIndent, firstLine); + EndAttr(m_xAttrTab->pFirstLineIndent, false); + NewAttr(m_xAttrTab, &m_xAttrTab->pTextLeftMargin, leftMargin); + EndAttr(m_xAttrTab->pTextLeftMargin, false); + NewAttr(m_xAttrTab, &m_xAttrTab->pRightMargin, rightMargin); + EndAttr(m_xAttrTab->pRightMargin, false); } else { @@ -5027,14 +5080,8 @@ void SwHTMLParser::InsertSpacer() sal_uInt16 SwHTMLParser::ToTwips( sal_uInt16 nPixel ) { - if( nPixel && Application::GetDefaultDevice() ) - { - SwTwips nTwips = Application::GetDefaultDevice()->PixelToLogic( - Size( nPixel, nPixel ), MapMode( MapUnit::MapTwip ) ).Width(); - return static_cast<sal_uInt16>(std::min(nTwips, SwTwips(SAL_MAX_UINT16))); - } - else - return nPixel; + return std::min(o3tl::convert(nPixel, o3tl::Length::px, o3tl::Length::twip), + sal_Int64(SAL_MAX_UINT16)); } SwTwips SwHTMLParser::GetCurrentBrowseWidth() @@ -5082,21 +5129,8 @@ void SwHTMLParser::InsertIDOption() void SwHTMLParser::InsertLineBreak() { - // <BR CLEAR=xxx> is handled as: - // 1.) Only regard the paragraph-bound frames anchored in current paragraph. - // 2.) For left-justified aligned frames, CLEAR=LEFT or ALL, and for right- - // justified aligned frames, CLEAR=RIGHT or ALL, the wrap-through is - // changed as following: - // 3.) If the paragraph contains no text, then the frames don't get a wrapping - // 4.) otherwise a left aligned frame gets a right "only anchor" wrapping - // and a right aligned frame gets a left "only anchor" wrapping. - // 5.) if in a non-empty paragraph the wrapping of a frame is changed, - // then a new paragraph is opened - // 6.) If no wrappings of frames are changed, a hard line break is inserted. - OUString aId, aStyle, aClass; // the id of bookmark - bool bClearLeft = false, bClearRight = false; - bool bCleared = false; // Was a CLEAR executed? + SwLineBreakClear eClear = SwLineBreakClear::NONE; // then we fetch the options const HTMLOptions& rHTMLOptions = GetOptions(); @@ -5110,13 +5144,16 @@ void SwHTMLParser::InsertLineBreak() const OUString &rClear = rOption.GetString(); if( rClear.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_all ) ) { - bClearLeft = true; - bClearRight = true; + eClear = SwLineBreakClear::ALL; } else if( rClear.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_left ) ) - bClearLeft = true; + { + eClear = SwLineBreakClear::LEFT; + } else if( rClear.equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_AL_right ) ) - bClearRight = true; + { + eClear = SwLineBreakClear::LEFT; + } } break; case HtmlOptionId::ID: @@ -5132,57 +5169,6 @@ void SwHTMLParser::InsertLineBreak() } } - // CLEAR is only supported for the current paragraph - if( bClearLeft || bClearRight ) - { - SwNodeIndex& rNodeIdx = m_pPam->GetPoint()->nNode; - SwTextNode* pTextNd = rNodeIdx.GetNode().GetTextNode(); - if( pTextNd ) - { - const SwFrameFormats& rFrameFormatTable = *m_xDoc->GetSpzFrameFormats(); - - for( size_t i=0; i<rFrameFormatTable.size(); i++ ) - { - SwFrameFormat *const pFormat = rFrameFormatTable[i]; - SwFormatAnchor const*const pAnchor = &pFormat->GetAnchor(); - SwPosition const*const pAPos = pAnchor->GetContentAnchor(); - if (pAPos && - ((RndStdIds::FLY_AT_PARA == pAnchor->GetAnchorId()) || - (RndStdIds::FLY_AT_CHAR == pAnchor->GetAnchorId())) && - pAPos->nNode == rNodeIdx && - pFormat->GetSurround().GetSurround() != css::text::WrapTextMode_NONE ) - { - sal_Int16 eHori = RES_DRAWFRMFMT == pFormat->Which() - ? text::HoriOrientation::LEFT - : pFormat->GetHoriOrient().GetHoriOrient(); - - css::text::WrapTextMode eSurround = css::text::WrapTextMode_PARALLEL; - if( m_pPam->GetPoint()->nContent.GetIndex() ) - { - if( bClearLeft && text::HoriOrientation::LEFT==eHori ) - eSurround = css::text::WrapTextMode_RIGHT; - else if( bClearRight && text::HoriOrientation::RIGHT==eHori ) - eSurround = css::text::WrapTextMode_LEFT; - } - else if( (bClearLeft && text::HoriOrientation::LEFT==eHori) || - (bClearRight && text::HoriOrientation::RIGHT==eHori) ) - { - eSurround = css::text::WrapTextMode_NONE; - } - - if( css::text::WrapTextMode_PARALLEL != eSurround ) - { - SwFormatSurround aSurround( eSurround ); - if( css::text::WrapTextMode_NONE != eSurround ) - aSurround.SetAnchorOnly( true ); - pFormat->SetFormatAttr( aSurround ); - bCleared = true; - } - } - } - } - } - // parse styles std::shared_ptr<SvxFormatBreakItem> aBreakItem(std::make_shared<SvxFormatBreakItem>(SvxBreak::NONE, RES_BREAK)); bool bBreakItem = false; @@ -5209,12 +5195,26 @@ void SwHTMLParser::InsertLineBreak() EndAttr( m_xAttrTab->pBreak, false ); } - if( !bCleared && !bBreakItem ) + if (!bBreakItem) { - // If no CLEAR could or should be executed, a line break will be inserted - m_xDoc->getIDocumentContentOperations().InsertString( *m_pPam, "\x0A" ); + if (eClear == SwLineBreakClear::NONE) + { + // If no CLEAR could or should be executed, a line break will be inserted + m_xDoc->getIDocumentContentOperations().InsertString(*m_pPam, "\x0A"); + } + else + { + // <BR CLEAR=xxx> is mapped an SwFormatLineBreak. + SwTextNode* pTextNode = m_pPam->GetPointNode().GetTextNode(); + if (pTextNode) + { + SwFormatLineBreak aLineBreak(eClear); + sal_Int32 nPos = m_pPam->GetPoint()->GetContentIndex(); + pTextNode->InsertItem(aLineBreak, nPos, nPos); + } + } } - else if( m_pPam->GetPoint()->nContent.GetIndex() ) + else if( m_pPam->GetPoint()->GetContentIndex() ) { // If a CLEAR is executed in a non-empty paragraph, then after it // a new paragraph has to be opened. @@ -5255,11 +5255,11 @@ void SwHTMLParser::InsertHorzRule() aId = rOption.GetString(); break; case HtmlOptionId::SIZE: - nSize = static_cast<sal_uInt16>(rOption.GetNumber()); + nSize = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); break; case HtmlOptionId::WIDTH: bPercentWidth = (rOption.GetString().indexOf('%') != -1); - nWidth = static_cast<sal_uInt16>(rOption.GetNumber()); + nWidth = o3tl::narrowing<sal_uInt16>(rOption.GetNumber()); if( bPercentWidth && nWidth>=100 ) { // the default case are 100% lines (no attributes necessary) @@ -5281,7 +5281,7 @@ void SwHTMLParser::InsertHorzRule() } } - if( m_pPam->GetPoint()->nContent.GetIndex() ) + if( m_pPam->GetPoint()->GetContentIndex() ) AppendTextNode( AM_NOSPACE ); if( m_nOpenParaToken != HtmlTokenId::NONE ) EndPara(); @@ -5320,12 +5320,12 @@ void SwHTMLParser::InsertHorzRule() } else if( bNoShade ) { - aBorderLine.SetWidth( DEF_LINE_WIDTH_2 ); + aBorderLine.SetWidth( SvxBorderLineWidth::Medium ); } else { aBorderLine.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE); - aBorderLine.SetWidth( DEF_LINE_WIDTH_0 ); + aBorderLine.SetWidth(SvxBorderLineWidth::Hairline); } SvxBoxItem aBoxItem(RES_BOX); @@ -5343,35 +5343,44 @@ void SwHTMLParser::InsertHorzRule() { // fake length and alignment of line above paragraph indents tools::Long nBrowseWidth = GetCurrentBrowseWidth(); - nWidth = bPercentWidth ? static_cast<sal_uInt16>((nWidth*nBrowseWidth) / 100) - : ToTwips( static_cast<sal_uInt16>(nBrowseWidth) ); + nWidth = bPercentWidth ? o3tl::narrowing<sal_uInt16>((nWidth*nBrowseWidth) / 100) + : ToTwips( o3tl::narrowing<sal_uInt16>(nBrowseWidth) ); if( nWidth < MINLAY ) nWidth = MINLAY; const SwFormatColl *pColl = (static_cast<tools::Long>(nWidth) < nBrowseWidth) ? GetCurrFormatColl() : nullptr; if (pColl) { - SvxLRSpaceItem aLRItem( pColl->GetLRSpace() ); tools::Long nDist = nBrowseWidth - nWidth; + ::std::optional<SvxTextLeftMarginItem> oLeft; + ::std::optional<SvxRightMarginItem> oRight; switch( eAdjust ) { case SvxAdjust::Right: - aLRItem.SetTextLeft( static_cast<sal_uInt16>(nDist) ); + oLeft.emplace(o3tl::narrowing<sal_uInt16>(nDist), RES_MARGIN_TEXTLEFT); break; case SvxAdjust::Left: - aLRItem.SetRight( static_cast<sal_uInt16>(nDist) ); + oRight.emplace(o3tl::narrowing<sal_uInt16>(nDist), RES_MARGIN_RIGHT); break; case SvxAdjust::Center: default: nDist /= 2; - aLRItem.SetTextLeft( static_cast<sal_uInt16>(nDist) ); - aLRItem.SetRight( static_cast<sal_uInt16>(nDist) ); + oLeft.emplace(o3tl::narrowing<sal_uInt16>(nDist), RES_MARGIN_TEXTLEFT); + oRight.emplace(o3tl::narrowing<sal_uInt16>(nDist), RES_MARGIN_RIGHT); break; } - HTMLAttr* pTmp = new HTMLAttr(*m_pPam->GetPoint(), aLRItem, nullptr, std::shared_ptr<HTMLAttrTable>()); - m_aSetAttrTab.push_back( pTmp ); + if (oLeft) + { + HTMLAttr* pTmp = new HTMLAttr(*m_pPam->GetPoint(), *oLeft, nullptr, std::shared_ptr<HTMLAttrTable>()); + m_aSetAttrTab.push_back( pTmp ); + } + if (oRight) + { + HTMLAttr* pTmp = new HTMLAttr(*m_pPam->GetPoint(), *oRight, nullptr, std::shared_ptr<HTMLAttrTable>()); + m_aSetAttrTab.push_back( pTmp ); + } } } } @@ -5440,21 +5449,21 @@ void SwHTMLParser::ParseMoreMetaOptions() return; } - OUStringBuffer sText; - sText.append("HTML: <"); - sText.append(OOO_STRING_SVTOOLS_HTML_meta); - sText.append(' '); + OUStringBuffer sText( + "HTML: <" + OOO_STRING_SVTOOLS_HTML_meta + " "); if( bHTTPEquiv ) sText.append(OOO_STRING_SVTOOLS_HTML_O_httpequiv); else sText.append(OOO_STRING_SVTOOLS_HTML_O_name); - sText.append("=\""); - sText.append(aName); - sText.append("\" "); - sText.append(OOO_STRING_SVTOOLS_HTML_O_content); - sText.append("=\""); - sText.append(aContent); - sText.append("\">"); + sText.append( + "=\"" + aName + + "\" " + OOO_STRING_SVTOOLS_HTML_O_content + "=\"" + + aContent + + "\">"); SwPostItField aPostItField( static_cast<SwPostItFieldType*>(m_xDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Postit )), @@ -5464,24 +5473,24 @@ void SwHTMLParser::ParseMoreMetaOptions() } HTMLAttr::HTMLAttr( const SwPosition& rPos, const SfxPoolItem& rItem, - HTMLAttr **ppHd, const std::shared_ptr<HTMLAttrTable>& rAttrTab ) : - m_nStartPara( rPos.nNode ), - m_nEndPara( rPos.nNode ), - m_nStartContent( rPos.nContent.GetIndex() ), - m_nEndContent(rPos.nContent.GetIndex() ), + HTMLAttr **ppHd, std::shared_ptr<HTMLAttrTable> xAttrTab ) : + m_nStartPara( rPos.GetNode() ), + m_nEndPara( rPos.GetNode() ), + m_nStartContent( rPos.GetContentIndex() ), + m_nEndContent(rPos.GetContentIndex() ), m_bInsAtStart( true ), m_bLikePara( false ), m_bValid( true ), m_pItem( rItem.Clone() ), - m_xAttrTab( rAttrTab ), + m_xAttrTab(std::move( xAttrTab )), m_pNext( nullptr ), m_pPrev( nullptr ), m_ppHead( ppHd ) { } -HTMLAttr::HTMLAttr( const HTMLAttr &rAttr, const SwNodeIndex &rEndPara, - sal_Int32 nEndCnt, HTMLAttr **ppHd, const std::shared_ptr<HTMLAttrTable>& rAttrTab ) : +HTMLAttr::HTMLAttr( const HTMLAttr &rAttr, const SwNode &rEndPara, + sal_Int32 nEndCnt, HTMLAttr **ppHd, std::shared_ptr<HTMLAttrTable> xAttrTab ) : m_nStartPara( rAttr.m_nStartPara ), m_nEndPara( rEndPara ), m_nStartContent( rAttr.m_nStartContent ), @@ -5490,7 +5499,7 @@ HTMLAttr::HTMLAttr( const HTMLAttr &rAttr, const SwNodeIndex &rEndPara, m_bLikePara( rAttr.m_bLikePara ), m_bValid( rAttr.m_bValid ), m_pItem( rAttr.m_pItem->Clone() ), - m_xAttrTab( rAttrTab ), + m_xAttrTab(std::move( xAttrTab )), m_pNext( nullptr ), m_pPrev( nullptr ), m_ppHead( ppHd ) @@ -5501,7 +5510,7 @@ HTMLAttr::~HTMLAttr() { } -HTMLAttr *HTMLAttr::Clone(const SwNodeIndex& rEndPara, sal_Int32 nEndCnt) const +HTMLAttr *HTMLAttr::Clone(const SwNode& rEndPara, sal_Int32 nEndCnt) const { // create the attribute anew with old start position HTMLAttr *pNew = new HTMLAttr( *this, rEndPara, nEndCnt, m_ppHead, m_xAttrTab ); @@ -5512,7 +5521,7 @@ HTMLAttr *HTMLAttr::Clone(const SwNodeIndex& rEndPara, sal_Int32 nEndCnt) const return pNew; } -void HTMLAttr::Reset(const SwNodeIndex& rSttPara, sal_Int32 nSttCnt, +void HTMLAttr::Reset(const SwNode& rSttPara, sal_Int32 nSttCnt, HTMLAttr **ppHd, const std::shared_ptr<HTMLAttrTable>& rAttrTab) { // reset the start (and the end) @@ -5581,16 +5590,12 @@ void HTMLReader::SetupFilterOptions() if (!m_pMedium) return; - const SfxItemSet* pItemSet = m_pMedium->GetItemSet(); - if (!pItemSet) - return; - - auto pItem = pItemSet->GetItem<SfxStringItem>(SID_FILE_FILTEROPTIONS); + auto pItem = m_pMedium->GetItemSet().GetItem(SID_FILE_FILTEROPTIONS); if (!pItem) return; OUString aFilterOptions = pItem->GetValue(); - const OUString aXhtmlNsKey("xhtmlns="); + static constexpr OUString aXhtmlNsKey(u"xhtmlns="_ustr); if (aFilterOptions.startsWith(aXhtmlNsKey)) { OUString aNamespace = aFilterOptions.copy(aXhtmlNsKey.getLength()); @@ -5613,8 +5618,8 @@ namespace bool TestImportHTML(SvStream &rStream) { FontCacheGuard aFontCacheGuard; - std::unique_ptr<Reader> xReader(new HTMLReader); - xReader->m_pStream = &rStream; + HTMLReader aReader; + aReader.m_pStream = &rStream; SwGlobals::ensure(); @@ -5622,13 +5627,12 @@ bool TestImportHTML(SvStream &rStream) xDocSh->DoInitNew(); SwDoc *pD = static_cast<SwDocShell*>((&xDocSh))->GetDoc(); - SwNodeIndex aIdx(pD->GetNodes().GetEndOfContent(), -1); - SwPaM aPaM(aIdx); + SwPaM aPaM(pD->GetNodes().GetEndOfContent(), SwNodeOffset(-1)); pD->SetInReading(true); bool bRet = false; try { - bRet = xReader->Read(*pD, OUString(), aPaM, OUString()) == ERRCODE_NONE; + bRet = aReader.Read(*pD, OUString(), aPaM, OUString()) == ERRCODE_NONE; } catch (const std::runtime_error&) { diff --git a/sw/source/filter/html/swhtml.hxx b/sw/source/filter/html/swhtml.hxx index 0f4809e23558..33f03ecf3fc3 100644 --- a/sw/source/filter/html/swhtml.hxx +++ b/sw/source/filter/html/swhtml.hxx @@ -28,13 +28,17 @@ #include <editeng/svxenum.hxx> #include <rtl/ref.hxx> #include <rtl/ustrbuf.hxx> +#include <deletelistener.hxx> +#include <fmtftn.hxx> #include <fltshell.hxx> #include <swtypes.hxx> +#include <txtftn.hxx> #include <com/sun/star/drawing/XShape.hpp> #include <com/sun/star/form/XFormComponent.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <memory> +#include <utility> #include <vector> #include <deque> #include <stack> @@ -58,11 +62,11 @@ struct SwPending; class SvxCSS1PropertyInfo; struct ImplSVEvent; -#define HTML_CJK_PARSPACE (MM50/2) -#define HTML_CTL_PARSPACE (MM50/2) +constexpr tools::Long HTML_CJK_PARSPACE = o3tl::toTwips(25, o3tl::Length::mm10); // 2.5mm +constexpr tools::Long HTML_CTL_PARSPACE = o3tl::toTwips(25, o3tl::Length::mm10); // 2.5mm -#define HTML_DFLT_IMG_WIDTH (MM50*4) -#define HTML_DFLT_IMG_HEIGHT (MM50*2) +constexpr tools::Long HTML_DFLT_IMG_WIDTH = o3tl::toTwips(2, o3tl::Length::cm); // 2cm +constexpr tools::Long HTML_DFLT_IMG_HEIGHT = o3tl::toTwips(1, o3tl::Length::cm); // 1cm // some things you often need extern HTMLOptionEnum<SvxAdjust> const aHTMLPAlignTable[]; @@ -78,51 +82,51 @@ typedef std::deque<HTMLAttr *> HTMLAttrs; // beginning of the table will set first in EndAllAttrs. struct HTMLAttrTable { - HTMLAttr - *pKeep, // frame attributes - *pBox, - *pBrush, - *pBreak, - *pPageDesc, - - *pLRSpace, // paragraph attributes - *pULSpace, - *pLineSpacing, - *pAdjust, - *pDropCap, - *pSplit, - *pWidows, - *pOrphans, - *pDirection, - - *pCharFormats, // text attributes - *pINetFormat, - - *pBold, // character attributes - *pBoldCJK, - *pBoldCTL, - *pItalic, - *pItalicCJK, - *pItalicCTL, - *pStrike, - *pUnderline, - *pBlink, - *pFont, - *pFontCJK, - *pFontCTL, - *pFontHeight, - *pFontHeightCJK, - *pFontHeightCTL, - *pFontColor, - *pEscapement, - *pCaseMap, - *pKerning, // (only for SPACER) - *pCharBrush, // character background - *pLanguage, - *pLanguageCJK, - *pLanguageCTL, - *pCharBox - ; + HTMLAttr* pKeep; // frame attributes + HTMLAttr* pBox; + HTMLAttr* pBrush; + HTMLAttr* pBreak; + HTMLAttr* pPageDesc; + + HTMLAttr* pFirstLineIndent; // paragraph attributes + HTMLAttr* pTextLeftMargin; + HTMLAttr* pRightMargin; + HTMLAttr* pULSpace; + HTMLAttr* pLineSpacing; + HTMLAttr* pAdjust; + HTMLAttr* pDropCap; + HTMLAttr* pSplit; + HTMLAttr* pWidows; + HTMLAttr* pOrphans; + HTMLAttr* pDirection; + + HTMLAttr* pCharFormats; // text attributes + HTMLAttr* pINetFormat; + + HTMLAttr* pBold; // character attributes + HTMLAttr* pBoldCJK; + HTMLAttr* pBoldCTL; + HTMLAttr* pItalic; + HTMLAttr* pItalicCJK; + HTMLAttr* pItalicCTL; + HTMLAttr* pStrike; + HTMLAttr* pUnderline; + HTMLAttr* pBlink; + HTMLAttr* pFont; + HTMLAttr* pFontCJK; + HTMLAttr* pFontCTL; + HTMLAttr* pFontHeight; + HTMLAttr* pFontHeightCJK; + HTMLAttr* pFontHeightCTL; + HTMLAttr* pFontColor; + HTMLAttr* pEscapement; + HTMLAttr* pCaseMap; + HTMLAttr* pKerning; // (only for SPACER) + HTMLAttr* pCharBrush; // character background + HTMLAttr* pLanguage; + HTMLAttr* pLanguageCJK; + HTMLAttr* pLanguageCTL; + HTMLAttr* pCharBox; }; class HTMLAttr @@ -130,8 +134,10 @@ class HTMLAttr friend class SwHTMLParser; friend class CellSaveStruct; - SwNodeIndex m_nStartPara, m_nEndPara; - sal_Int32 m_nStartContent, m_nEndContent; + SwNodeIndex m_nStartPara; + SwNodeIndex m_nEndPara; + sal_Int32 m_nStartContent; + sal_Int32 m_nEndContent; bool m_bInsAtStart : 1; bool m_bLikePara : 1; // set attribute above the whole paragraph bool m_bValid : 1; // is the attribute valid? @@ -143,28 +149,28 @@ class HTMLAttr HTMLAttr **m_ppHead; // list head HTMLAttr( const SwPosition& rPos, const SfxPoolItem& rItem, - HTMLAttr **pHd, const std::shared_ptr<HTMLAttrTable>& rAttrTab ); + HTMLAttr **pHd, std::shared_ptr<HTMLAttrTable> xAttrTab ); - HTMLAttr( const HTMLAttr &rAttr, const SwNodeIndex &rEndPara, - sal_Int32 nEndCnt, HTMLAttr **pHd, const std::shared_ptr<HTMLAttrTable>& rAttrTab ); + HTMLAttr( const HTMLAttr &rAttr, const SwNode &rEndPara, + sal_Int32 nEndCnt, HTMLAttr **pHd, std::shared_ptr<HTMLAttrTable> xAttrTab ); public: ~HTMLAttr(); - HTMLAttr *Clone( const SwNodeIndex& rEndPara, sal_Int32 nEndCnt ) const; - void Reset( const SwNodeIndex& rSttPara, sal_Int32 nSttCnt, + HTMLAttr *Clone( const SwNode& rEndPara, sal_Int32 nEndCnt ) const; + void Reset( const SwNode& rSttPara, sal_Int32 nSttCnt, HTMLAttr **pHd, const std::shared_ptr<HTMLAttrTable>& rAttrTab ); inline void SetStart( const SwPosition& rPos ); - sal_uInt32 GetSttParaIdx() const { return m_nStartPara.GetIndex(); } - sal_uInt32 GetEndParaIdx() const { return m_nEndPara.GetIndex(); } + SwNodeOffset GetStartParagraphIdx() const { return m_nStartPara.GetIndex(); } + SwNodeOffset GetEndParagraphIdx() const { return m_nEndPara.GetIndex(); } - const SwNodeIndex& GetSttPara() const { return m_nStartPara; } - const SwNodeIndex& GetEndPara() const { return m_nEndPara; } + const SwNodeIndex& GetStartParagraph() const { return m_nStartPara; } + const SwNodeIndex& GetEndParagraph() const { return m_nEndPara; } - sal_Int32 GetSttCnt() const { return m_nStartContent; } - sal_Int32 GetEndCnt() const { return m_nEndContent; } + sal_Int32 GetStartContent() const { return m_nStartContent; } + sal_Int32 GetEndContent() const { return m_nEndContent; } bool IsLikePara() const { return m_bLikePara; } void SetLikePara() { m_bLikePara = true; } @@ -211,9 +217,9 @@ class HTMLAttrContext std::unique_ptr<HTMLAttrContext_SaveDoc> m_pSaveDocContext; std::unique_ptr<SfxItemSet> m_pFrameItemSet; - HtmlTokenId m_nToken; // the token of the context + HtmlTokenId m_nToken; // the token of the context - sal_uInt16 m_nTextFormatColl; // a style created in the context or zero + sal_uInt16 m_nTextFormatColl; // a style created in the context or zero sal_uInt16 m_nLeftMargin; // a changed left border sal_uInt16 m_nRightMargin; // a changed right border @@ -240,7 +246,7 @@ class HTMLAttrContext public: void ClearSaveDocContext(); - HTMLAttrContext( HtmlTokenId nTokn, sal_uInt16 nPoolId, const OUString& rClass, + HTMLAttrContext( HtmlTokenId nTokn, sal_uInt16 nPoolId, OUString aClass, bool bDfltColl=false ); explicit HTMLAttrContext( HtmlTokenId nTokn ); ~HTMLAttrContext(); @@ -248,7 +254,7 @@ public: HtmlTokenId GetToken() const { return m_nToken; } sal_uInt16 GetTextFormatColl() const { return m_bDefaultTextFormatColl ? 0 : m_nTextFormatColl; } - sal_uInt16 GetDfltTextFormatColl() const { return m_bDefaultTextFormatColl ? m_nTextFormatColl : 0; } + sal_uInt16 GetDefaultTextFormatColl() const { return m_bDefaultTextFormatColl ? m_nTextFormatColl : 0; } const OUString& GetClass() const { return m_aClass; } @@ -397,7 +403,7 @@ class SwHTMLParser : public SfxHTMLParser, public SvtListener std::vector<HTMLTable*> m_aTables; std::shared_ptr<HTMLTable> m_xTable; // current "outermost" table SwHTMLForm_Impl* m_pFormImpl; // current form - SdrObject *m_pMarquee; // current marquee + rtl::Reference<SdrTextObj> m_pMarquee; // current marquee std::unique_ptr<SwField> m_xField; // current field ImageMap *m_pImageMap; // current image map std::unique_ptr<ImageMaps> m_pImageMaps; ///< all Image-Maps that have been read @@ -432,7 +438,7 @@ class SwHTMLParser : public SfxHTMLParser, public SvtListener bool m_bOldIsHTMLMode : 1; // Was it a HTML document? - bool m_bDocInitalized : 1; // document resp. shell was initialize + bool m_bDocInitialized : 1; // document resp. shell was initialize // flag to prevent double init via recursion bool m_bViewCreated : 1; // the view was already created (asynchronous) bool m_bSetModEnabled : 1; @@ -471,7 +477,9 @@ class SwHTMLParser : public SfxHTMLParser, public SvtListener bool m_bNotifyMacroEventRead : 1; bool m_isInTableStructure; - sal_Int32 m_nTableDepth; + int m_nTableDepth; + int m_nFloatingFrames; + int m_nListItems; /// the names corresponding to the DOCINFO field subtypes INFO[1-4] OUString m_InfoNames[4]; @@ -489,6 +497,9 @@ class SwHTMLParser : public SfxHTMLParser, public SvtListener std::set<OUString> m_aAllowedRTFOLEMimeTypes; + /// This is the URL of the outer <object> data if it's not OLE2 or an image. + OUString m_aEmbedURL; + void DeleteFormImpl(); void DocumentDetected(); @@ -533,7 +544,7 @@ class SwHTMLParser : public SfxHTMLParser, public SvtListener bool DoPositioning( SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, HTMLAttrContext *pContext ); - bool CreateContainer( const OUString& rClass, SfxItemSet &rItemSet, + bool CreateContainer( std::u16string_view rClass, SfxItemSet &rItemSet, SvxCSS1PropertyInfo &rPropInfo, HTMLAttrContext *pContext ); bool EndSection( bool bLFStripped=false ); @@ -581,7 +592,7 @@ class SwHTMLParser : public SfxHTMLParser, public SvtListener short& nIndent ) const; void GetULSpaceFromContext( sal_uInt16 &rUpper, sal_uInt16 &rLower ) const; - void MovePageDescAttrs( SwNode *pSrcNd, sal_uLong nDestIdx, bool bFormatBreak ); + void MovePageDescAttrs( SwNode *pSrcNd, SwNodeOffset nDestIdx, bool bFormatBreak ); // Handling of tags at paragraph level @@ -652,13 +663,11 @@ class SwHTMLParser : public SfxHTMLParser, public SvtListener // tags realized via character styles void NewCharFormat( HtmlTokenId nToken ); - void ClearFootnotesMarksInRange(const SwNodeIndex& rSttIdx, const SwNodeIndex& rEndIdx); - void DeleteSection(SwStartNode* pSttNd); // <SDFIELD> public: - static SvxNumType GetNumType( const OUString& rStr, SvxNumType eDfltType ); + static SvxNumType GetNumType( std::u16string_view rStr, SvxNumType eDfltType ); private: void NewField(); void EndField(); @@ -670,7 +679,7 @@ private: // Inserting graphics, plug-ins and applets // search image maps and link with graphic nodes - ImageMap *FindImageMap( const OUString& rURL ) const; + ImageMap *FindImageMap( std::u16string_view rURL ) const; void ConnectImageMaps(); // find anchor of Fly-Frames and set corresponding attributes @@ -737,8 +746,8 @@ private: // insert bookmark void InsertBookmark( const OUString& rName ); - void InsertCommentText( const char *pTag ); - void InsertComment( const OUString& rName, const char *pTag = nullptr ); + void InsertCommentText( std::string_view pTag ); + void InsertComment( const OUString& rName, std::string_view pTag = {} ); // Has the current paragraph bookmarks? bool HasCurrentParaBookmarks( bool bIgnoreStack=false ) const; @@ -853,8 +862,8 @@ private: void InsertLineBreak(); void InsertHorzRule(); - void FillEndNoteInfo( const OUString& rContent ); - void FillFootNoteInfo( const OUString& rContent ); + void FillEndNoteInfo( std::u16string_view aContent ); + void FillFootNoteInfo( std::u16string_view aContent ); void InsertFootEndNote( const OUString& rName, bool bEndNote, bool bFixed ); void FinishFootEndNote(); void InsertFootEndNoteText(); @@ -865,14 +874,12 @@ private: // Remove empty paragraph at the PaM position void StripTrailingPara(); // If removing an empty node would corrupt the document - bool CanRemoveNode(sal_uLong nNodeIdx) const; + bool CanRemoveNode(SwNodeOffset nNodeIdx) const; // Are there fly frames in the current paragraph? bool HasCurrentParaFlys( bool bNoSurroundOnly = false, bool bSurroundOnly = false ) const; - bool PendingObjectsInPaM(SwPaM& rPam) const; - class TableDepthGuard { private: @@ -912,8 +919,8 @@ protected: public: SwHTMLParser( SwDoc* pD, SwPaM & rCursor, SvStream& rIn, - const OUString& rFileName, - const OUString& rBaseURL, + OUString aFileName, + OUString aBaseURL, bool bReadNewDoc, SfxMedium* pMed, bool bReadUTF8, bool bIgnoreHTMLComments, @@ -946,7 +953,7 @@ public: void NotifyMacroEventRead(); /// Strips query and fragment from a URL path if base URL is a file:// one. - static OUString StripQueryFromPath(const OUString& rBase, const OUString& rPath); + static OUString StripQueryFromPath(std::u16string_view rBase, const OUString& rPath); }; struct SwPendingData @@ -966,8 +973,8 @@ struct SwPending inline void HTMLAttr::SetStart( const SwPosition& rPos ) { - m_nStartPara = rPos.nNode; - m_nStartContent = rPos.nContent.GetIndex(); + m_nStartPara = rPos.GetNode(); + m_nStartContent = rPos.GetContentIndex(); m_nEndPara = m_nStartPara; m_nEndContent = m_nStartContent; } @@ -1022,14 +1029,28 @@ inline bool SwHTMLParser::HasStyleOptions( std::u16string_view rStyle, class SwTextFootnote; -struct SwHTMLTextFootnote +class SwHTMLTextFootnote { - OUString sName; - SwTextFootnote* pTextFootnote; - SwHTMLTextFootnote(const OUString &rName, SwTextFootnote* pInTextFootnote) - : sName(rName) - , pTextFootnote(pInTextFootnote) +private: + OUString m_sName; + SwTextFootnote* m_pTextFootnote; + std::unique_ptr<SvtDeleteListener> m_xDeleteListener; +public: + SwHTMLTextFootnote(OUString rName, SwTextFootnote* pInTextFootnote) + : m_sName(std::move(rName)) + , m_pTextFootnote(pInTextFootnote) + , m_xDeleteListener(new SvtDeleteListener(static_cast<SwFormatFootnote&>(pInTextFootnote->GetAttr()).GetNotifier())) + { + } + const OUString& GetName() const + { + return m_sName; + } + const SwNodeIndex* GetStartNode() const { + if (m_xDeleteListener->WasDeleted()) + return nullptr; + return m_pTextFootnote->GetStartNode(); } }; diff --git a/sw/source/filter/html/wrthtml.cxx b/sw/source/filter/html/wrthtml.cxx index 741448d96f7f..093cef850614 100644 --- a/sw/source/filter/html/wrthtml.cxx +++ b/sw/source/filter/html/wrthtml.cxx @@ -82,6 +82,10 @@ #include <comphelper/scopeguard.hxx> #include <unotools/tempfile.hxx> #include <comphelper/sequenceashashmap.hxx> +#include <officecfg/Office/Common.hxx> +#include <officecfg/Office/Writer.hxx> +#include <comphelper/propertysequence.hxx> +#include <comphelper/sequence.hxx> #define MAX_INDENT_LEVEL 20 @@ -90,11 +94,10 @@ using namespace css; static char sIndentTabs[MAX_INDENT_LEVEL+2] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; -SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, const OUString& rFilterOptions ) +SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, std::u16string_view rFilterOptions ) : m_pNumRuleInfo(new SwHTMLNumRuleInfo) , m_nHTMLMode(0) , m_eCSS1Unit(FieldUnit::NONE) - , mxFormComps() , m_pStartNdIdx(nullptr) , m_pCurrPageDesc(nullptr) , m_pFormatFootnote(nullptr) @@ -114,7 +117,7 @@ SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, const OUString& rFilterOpt , m_nDfltTopMargin(0) , m_nDfltBottomMargin(0) , m_nIndentLvl(0) - , m_nWishLineLen(0) + , m_nWishLineLen(70) , m_nDefListLvl(0) , m_nDefListMargin(0) , m_nHeaderFooterSpace(0) @@ -123,7 +126,6 @@ SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, const OUString& rFilterOpt , m_nCSS1OutMode(0) , m_nCSS1Script(CSS1_OUTMODE_WESTERN) , m_nDirection(SvxFrameDirection::Horizontal_LR_TB) - , m_eDestEnc(RTL_TEXTENCODING_MS_1252) , m_eLang(LANGUAGE_DONTKNOW) , m_bCfgOutStyles( false ) , m_bCfgPreferStyles( false ) @@ -144,7 +146,6 @@ SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, const OUString& rFilterOpt , m_bNoAlign( false ) , m_bClearLeft( false ) , m_bClearRight( false ) - , m_bLFPossible( false ) , m_bPreserveForm( false ) , m_bCfgNetscape4( false ) , mbSkipImages(false) @@ -158,7 +159,7 @@ SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, const OUString& rFilterOpt if (rBaseURL.isEmpty()) { // Paste: set base URL to a tempfile, so images are not lost. - mpTempBaseURL.reset(new utl::TempFile()); + mpTempBaseURL.reset(new utl::TempFileNamed()); mpTempBaseURL->EnableKillingFile(); SetBaseURL(mpTempBaseURL->GetURL()); } @@ -182,66 +183,191 @@ std::unique_ptr<SwHTMLNumRuleInfo> SwHTMLWriter::ReleaseNextNumInfo() void SwHTMLWriter::SetupFilterOptions(SfxMedium& rMedium) { - const SfxItemSet* pSet = rMedium.GetItemSet(); - if (pSet == nullptr) - return; - - const SfxPoolItem* pItem; - if (pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) != SfxItemState::SET) - return; - + uno::Sequence<beans::PropertyValue> aArgs = rMedium.GetArgs(); + if (const SfxStringItem* pItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS )) + { + const OUString sFilterOptions = pItem->GetValue(); - const OUString sFilterOptions = static_cast<const SfxStringItem*>(pItem)->GetValue(); - SetupFilterOptions(sFilterOptions); + if (sFilterOptions.startsWith("{")) + { + std::vector<beans::PropertyValue> aArgsVec + = comphelper::JsonToPropertyValues(sFilterOptions.toUtf8()); + aArgs = comphelper::containerToSequence(aArgsVec); + } - comphelper::SequenceAsHashMap aStoreMap(rMedium.GetArgs()); - auto it = aStoreMap.find("RTFOLEMimeType"); - if (it == aStoreMap.end()) - { - return; + SetupFilterOptions(sFilterOptions); } - it->second >>= m_aRTFOLEMimeType; + SetupFilterFromPropertyValues(aArgs); } -void SwHTMLWriter::SetupFilterOptions(const OUString& rFilterOptions) +void SwHTMLWriter::SetupFilterOptions(std::u16string_view rFilterOptions) { - if (rFilterOptions == "SkipImages") + comphelper::SequenceAsHashMap aStoreMap; + if (rFilterOptions.find(u"SkipImages") != std::u16string_view::npos) + { + aStoreMap["SkipImages"] <<= true; + } + else if (rFilterOptions.find(u"SkipHeaderFooter") != std::u16string_view::npos) { - mbSkipImages = true; + aStoreMap["SkipHeaderFooter"] <<= true; } - else if (rFilterOptions == "SkipHeaderFooter") + else if (rFilterOptions.find(u"EmbedImages") != std::u16string_view::npos) { - mbSkipHeaderFooter = true; + aStoreMap["EmbedImages"] <<= true; } - else if (rFilterOptions == "EmbedImages") + + // this option can be "on" together with any of above + if (rFilterOptions.find(u"NoLineLimit") != std::u16string_view::npos) + { + aStoreMap["NoLineLimit"] <<= true; + } + + // this option can be "on" together with any of above + if (rFilterOptions.find(u"NoPrettyPrint") != std::u16string_view::npos) { - mbEmbedImages = true; + aStoreMap["NoPrettyPrint"] <<= true; } - const uno::Sequence<OUString> aOptionSeq = comphelper::string::convertCommaSeparated(rFilterOptions); - const OUString aXhtmlNsKey("xhtmlns="); + const uno::Sequence<OUString> aOptionSeq + = comphelper::string::convertCommaSeparated(rFilterOptions); + static constexpr OUString aXhtmlNsKey(u"xhtmlns="_ustr); for (const auto& rOption : aOptionSeq) { if (rOption == "XHTML") - mbXHTML = true; + { + aStoreMap["XHTML"] <<= true; + } else if (rOption.startsWith(aXhtmlNsKey)) { - maNamespace = rOption.copy(aXhtmlNsKey.getLength()).toUtf8(); - if (maNamespace == "reqif-xhtml") - { - mbReqIF = true; - // XHTML is always just a fragment inside ReqIF. - mbSkipHeaderFooter = true; - } - // XHTML namespace implies XHTML. - mbXHTML = true; + aStoreMap["XhtmlNs"] <<= rOption.copy(aXhtmlNsKey.getLength()); } } + + SetupFilterFromPropertyValues(aStoreMap.getAsConstPropertyValueList()); +} + +void SwHTMLWriter::SetupFilterFromPropertyValues( + const css::uno::Sequence<css::beans::PropertyValue>& rPropertyValues) +{ + comphelper::SequenceAsHashMap aStoreMap(rPropertyValues); + auto it = aStoreMap.find("RTFOLEMimeType"); + if (it != aStoreMap.end()) + { + it->second >>= m_aRTFOLEMimeType; + } + + it = aStoreMap.find("ExportImagesAsOLE"); + if (it != aStoreMap.end()) + { + it->second >>= m_bExportImagesAsOLE; + } + + it = aStoreMap.find("ExportFormulasAsPDF"); + if (it != aStoreMap.end()) + { + it->second >>= m_bExportFormulasAsPDF; + } + + it = aStoreMap.find("ShapeDPI"); + if (it != aStoreMap.end()) + { + sal_Int32 nVal{}; + it->second >>= nVal; + m_nShapeDPI.emplace(nVal); + } + + it = aStoreMap.find("SkipImages"); + if (it != aStoreMap.end()) + { + bool bVal{}; + it->second >>= bVal; + mbSkipImages = bVal; + } + + it = aStoreMap.find("SkipHeaderFooter"); + if (it != aStoreMap.end()) + { + bool bVal{}; + it->second >>= bVal; + mbSkipHeaderFooter = bVal; + } + + // this option can be "on" together with any of above + it = aStoreMap.find("NoPrettyPrint"); + if (it != aStoreMap.end()) + { + m_nWishLineLen = -1; + m_bPrettyPrint = false; + } + + it = aStoreMap.find("EmbedImages"); + if (it != aStoreMap.end()) + { + bool bVal{}; + it->second >>= bVal; + mbEmbedImages = bVal; + } + + it = aStoreMap.find("NoLineLimit"); + if (it != aStoreMap.end()) + { + bool bVal{}; + it->second >>= bVal; + if (bVal) + { + m_nWishLineLen = -1; + } + } + + it = aStoreMap.find("XHTML"); + if (it != aStoreMap.end()) + { + bool bVal{}; + it->second >>= bVal; + mbXHTML = bVal; + } + + it = aStoreMap.find("XhtmlNs"); + if (it != aStoreMap.end()) + { + OUString aVal; + it->second >>= aVal; + + maNamespace = aVal.toUtf8(); + if (maNamespace == "reqif-xhtml") + { + mbReqIF = true; + // XHTML is always just a fragment inside ReqIF. + mbSkipHeaderFooter = true; + } + // XHTML namespace implies XHTML. + mbXHTML = true; + } + + it = aStoreMap.find("LeadingTabWidth"); + if (it != aStoreMap.end()) + { + sal_Int32 nVal{}; + it->second >>= nVal; + m_nLeadingTabWidth.emplace(nVal); + } + + it = aStoreMap.find("PreserveSpaces"); + if (it != aStoreMap.end()) + { + // Paragraphs with leading/trailing/repeated whitespace will have "white-space: pre-wrap" + // style; whitespace in content will not be altered (except for "LeadingTabWidth" effects) + bool bVal = false; + it->second >>= bVal; + m_bPreserveSpacesOnWrite = bVal; + } } ErrCode SwHTMLWriter::WriteStream() { + if (!SW_MOD()) + return ERRCODE_ABORT; // Intercept paste output if requested. char* pPasteEnv = getenv("SW_DEBUG_HTML_PASTE_TO"); std::unique_ptr<SvStream> pPasteStream; @@ -259,20 +385,18 @@ ErrCode SwHTMLWriter::WriteStream() } comphelper::ScopeGuard g([this, pOldPasteStream] { this->SetStream(pOldPasteStream); }); - SvxHtmlOptions& rHtmlOptions = SvxHtmlOptions::Get(); - // font heights 1-7 - m_aFontHeights[0] = rHtmlOptions.GetFontSize( 0 ) * 20; - m_aFontHeights[1] = rHtmlOptions.GetFontSize( 1 ) * 20; - m_aFontHeights[2] = rHtmlOptions.GetFontSize( 2 ) * 20; - m_aFontHeights[3] = rHtmlOptions.GetFontSize( 3 ) * 20; - m_aFontHeights[4] = rHtmlOptions.GetFontSize( 4 ) * 20; - m_aFontHeights[5] = rHtmlOptions.GetFontSize( 5 ) * 20; - m_aFontHeights[6] = rHtmlOptions.GetFontSize( 6 ) * 20; + m_aFontHeights[0] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_1::get() * 20; + m_aFontHeights[1] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_2::get() * 20; + m_aFontHeights[2] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_3::get() * 20; + m_aFontHeights[3] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_4::get() * 20; + m_aFontHeights[4] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_5::get() * 20; + m_aFontHeights[5] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_6::get() * 20; + m_aFontHeights[6] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_7::get() * 20; // output styles anyway // (then also top and bottom paragraph spacing) - m_nExportMode = rHtmlOptions.GetExportMode(); + m_nExportMode = SvxHtmlOptions::GetExportMode(); m_nHTMLMode = GetHtmlMode(nullptr); if( HTML_CFG_WRITER == m_nExportMode || HTML_CFG_NS40 == m_nExportMode ) @@ -284,8 +408,8 @@ ErrCode SwHTMLWriter::WriteStream() if( HTML_CFG_MSIE == m_nExportMode ) m_nHTMLMode |= HTMLMODE_NBSP_IN_TABLES; - if( HTML_CFG_WRITER == m_nExportMode || HTML_CFG_NS40 == m_nExportMode || HTML_CFG_MSIE == m_nExportMode ) - m_nHTMLMode |= HTMLMODE_ABS_POS_FLY | HTMLMODE_ABS_POS_DRAW; + // For all three of HTML_CFG_WRITER, HTML_CFG_NS40, HTML_CFG_MSIE + m_nHTMLMode |= HTMLMODE_ABS_POS_FLY | HTMLMODE_ABS_POS_DRAW; if( HTML_CFG_WRITER == m_nExportMode ) m_nHTMLMode |= HTMLMODE_FLY_MARGINS; @@ -306,20 +430,15 @@ ErrCode SwHTMLWriter::WriteStream() m_eCSS1Unit = SW_MOD()->GetMetric( m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ); - bool bWriteUTF8 = m_bWriteClipboardDoc; - m_eDestEnc = bWriteUTF8 ? RTL_TEXTENCODING_UTF8 : rHtmlOptions.GetTextEncoding(); - const char *pCharSet = rtl_getBestMimeCharsetFromTextEncoding( m_eDestEnc ); - m_eDestEnc = rtl_getTextEncodingFromMimeCharset( pCharSet ); - // Only for the MS-IE we favour the export of styles. m_bCfgPreferStyles = HTML_CFG_MSIE == m_nExportMode; - m_bCfgStarBasic = rHtmlOptions.IsStarBasic(); + m_bCfgStarBasic = officecfg::Office::Common::Filter::HTML::Export::Basic::get(); m_bCfgFormFeed = !IsHTMLMode(HTMLMODE_PRINT_EXT); - m_bCfgCpyLinkedGrfs = rHtmlOptions.IsSaveGraphicsLocal(); + m_bCfgCpyLinkedGrfs = officecfg::Office::Common::Filter::HTML::Export::LocalGraphic::get(); - m_bCfgPrintLayout = rHtmlOptions.IsPrintLayoutExtension(); + m_bCfgPrintLayout = officecfg::Office::Common::Filter::HTML::Export::PrintLayout::get(); // get HTML template bool bOldHTMLMode = false; @@ -338,11 +457,11 @@ ErrCode SwHTMLWriter::WriteStream() } if( m_bShowProgress ) - ::StartProgress( STR_STATSTR_W4WWRITE, 0, m_pDoc->GetNodes().Count(), + ::StartProgress( STR_STATSTR_W4WWRITE, 0, sal_Int32(m_pDoc->GetNodes().Count()), m_pDoc->GetDocShell()); m_xDfltColor.reset(); - m_pFootEndNotes = nullptr; + m_xFootEndNotes.reset(); m_pFormatFootnote = nullptr; m_bOutTable = m_bOutHeader = m_bOutFooter = m_bOutFlyFrame = false; mxFormComps.clear(); @@ -350,6 +469,7 @@ ErrCode SwHTMLWriter::WriteStream() m_bPreserveForm = false; m_bClearLeft = m_bClearRight = false; m_bLFPossible = false; + m_bSpacePreserve = false; m_nLeftMargin = m_nDfltLeftMargin = m_nDfltRightMargin = 0; m_nDfltTopMargin = m_nDfltBottomMargin = 0; @@ -357,12 +477,11 @@ ErrCode SwHTMLWriter::WriteStream() m_bFirstCSS1Property = m_bFirstCSS1Rule = false; m_bCSS1IgnoreFirstPageDesc = false; m_nIndentLvl = 0; - m_nWishLineLen = 70; m_nLastLFPos = 0; m_nDefListLvl = 0; m_nDefListMargin = ((m_xTemplate.is() && !m_bCfgOutStyles) ? m_xTemplate.get() : m_pDoc) ->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_HTML_DD, false ) - ->GetLRSpace().GetTextLeft(); + ->GetTextLeftMargin().GetTextLeft(); m_nHeaderFooterSpace = 0; m_nTextAttrsToIgnore = 0; m_nCSS1OutMode = 0; @@ -379,8 +498,8 @@ ErrCode SwHTMLWriter::WriteStream() m_nCSS1Script = CSS1_OUTMODE_WESTERN; break; } - m_eLang = static_cast<const SvxLanguageItem&>(m_pDoc - ->GetDefault(GetLangWhichIdFromScript(m_nCSS1Script))).GetLanguage(); + const SvxLanguageItem& rLangitem = m_pDoc->GetDefault(GetLangWhichIdFromScript(m_nCSS1Script)); + m_eLang = rLangitem.GetLanguage(); m_nFootNote = m_nEndNote = 0; @@ -392,26 +511,29 @@ ErrCode SwHTMLWriter::WriteStream() // respect table and section at document beginning { - SwTableNode * pTNd = m_pCurrentPam->GetNode().FindTableNode(); - if( pTNd && m_bWriteAll ) + if (m_bWriteAll) { - // start with table node !! - m_pCurrentPam->GetPoint()->nNode = *pTNd; + while (const SwStartNode* pTNd = m_pCurrentPam->GetPointNode().FindTableBoxStartNode()) + { + // start with table node !! + m_pCurrentPam->GetPoint()->Assign(*pTNd->FindTableNode()); - if( m_bWriteOnlyFirstTable ) - m_pCurrentPam->GetMark()->nNode = *pTNd->EndOfSectionNode(); + if (m_bWriteOnlyFirstTable) + m_pCurrentPam->GetMark()->Assign( + *m_pCurrentPam->GetPointNode().EndOfSectionNode()); + } } - // first node (with can contain a page break) - m_pStartNdIdx = new SwNodeIndex( m_pCurrentPam->GetPoint()->nNode ); + // first node (which can contain a page break) + m_pStartNdIdx = new SwNodeIndex( m_pCurrentPam->GetPoint()->GetNode() ); - SwSectionNode * pSNd = m_pCurrentPam->GetNode().FindSectionNode(); + SwSectionNode * pSNd = m_pCurrentPam->GetPointNode().FindSectionNode(); while( pSNd ) { if( m_bWriteAll ) { // start with section node !! - m_pCurrentPam->GetPoint()->nNode = *pSNd; + m_pCurrentPam->GetPoint()->Assign(*pSNd); } else { @@ -420,8 +542,7 @@ ErrCode SwHTMLWriter::WriteStream() // save only the tag of section OString aName = HTMLOutFuncs::ConvertStringToHTML( - pSNd->GetSection().GetSectionName(), m_eDestEnc, - &m_aNonConvertableCharacters ); + pSNd->GetSection().GetSectionName() ); aStartTags = "<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_division @@ -436,71 +557,80 @@ ErrCode SwHTMLWriter::WriteStream() // create table of the floating frames, but only when the whole // document is saved - m_pHTMLPosFlyFrames = nullptr; + m_aHTMLPosFlyFrames.clear(); CollectFlyFrames(); m_nLastParaToken = HtmlTokenId::NONE; - GetControls(); - CollectLinkTargets(); - sal_uInt16 nHeaderAttrs = 0; - m_pCurrPageDesc = MakeHeader( nHeaderAttrs ); + if (mbReqIF && !m_bWriteAll + && *m_pCurrentPam->GetPoint() == *m_pCurrentPam->GetMark() + && m_pCurrentPam->GetPoint()->GetNode().IsOLENode() && m_aHTMLPosFlyFrames.size() == 1) + { + // A single OLE object selection must be output: do it directly (without replacement) + OutHTML_FrameFormatOLENodeGrf(*this, m_aHTMLPosFlyFrames[0]->GetFormat(), true, false); + } + else + { + GetControls(); + CollectLinkTargets(); - m_bLFPossible = true; + sal_uInt16 nHeaderAttrs = 0; + m_pCurrPageDesc = MakeHeader( nHeaderAttrs ); - // output forms which contain only HiddenControls - OutHiddenForms(); + SetLFPossible(true); - if( !aStartTags.isEmpty() ) - Strm().WriteOString( aStartTags ); + // output forms which contain only HiddenControls + OutHiddenForms(); - const SfxPoolItem *pItem; - const SfxItemSet& rPageItemSet = m_pCurrPageDesc->GetMaster().GetAttrSet(); - if( !m_bWriteClipboardDoc && m_pDoc->GetDocShell() && - (!m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && - !m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE)) && - SfxItemState::SET == rPageItemSet.GetItemState( RES_HEADER, true, &pItem) ) - { - const SwFrameFormat *pHeaderFormat = - static_cast<const SwFormatHeader *>(pItem)->GetHeaderFormat(); - if( pHeaderFormat ) - OutHTML_HeaderFooter( *this, *pHeaderFormat, true ); - } + if( !aStartTags.isEmpty() ) + Strm().WriteOString( aStartTags ); - m_nTextAttrsToIgnore = nHeaderAttrs; - Out_SwDoc( m_pOrigPam ); - m_nTextAttrsToIgnore = 0; + const SwFormatHeader *pFormatHeader; + const SfxItemSet& rPageItemSet = m_pCurrPageDesc->GetMaster().GetAttrSet(); + if( !m_bWriteClipboardDoc && m_pDoc->GetDocShell() && + (!m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && + !m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE)) && + (pFormatHeader = rPageItemSet.GetItemIfSet( RES_HEADER )) ) + { + const SwFrameFormat *pHeaderFormat = pFormatHeader->GetHeaderFormat(); + if( pHeaderFormat ) + OutHTML_HeaderFooter( *this, *pHeaderFormat, true ); + } - if( mxFormComps.is() ) - OutForm( false, mxFormComps ); + m_nTextAttrsToIgnore = nHeaderAttrs; + Out_SwDoc( m_pOrigPam ); + m_nTextAttrsToIgnore = 0; - if( m_pFootEndNotes ) - OutFootEndNotes(); + if( mxFormComps.is() ) + OutForm( false, mxFormComps ); - if( !m_bWriteClipboardDoc && m_pDoc->GetDocShell() && - (!m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && !m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE)) && - SfxItemState::SET == rPageItemSet.GetItemState( RES_FOOTER, true, &pItem) ) - { - const SwFrameFormat *pFooterFormat = - static_cast<const SwFormatFooter *>(pItem)->GetFooterFormat(); - if( pFooterFormat ) - OutHTML_HeaderFooter( *this, *pFooterFormat, false ); - } + if( m_xFootEndNotes ) + OutFootEndNotes(); - if( m_bLFPossible ) - OutNewLine(); - if (!mbSkipHeaderFooter) - { - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_body, false ); - OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_html, false ); - } - else if (mbReqIF) - // ReqIF: end xhtml.BlkStruct.class. - HTMLOutFuncs::Out_AsciiTag(Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_division, false); + const SwFormatFooter* pFormatFooter; + if( !m_bWriteClipboardDoc && m_pDoc->GetDocShell() && + (!m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && !m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE)) && + (pFormatFooter = rPageItemSet.GetItemIfSet( RES_FOOTER )) ) + { + const SwFrameFormat *pFooterFormat = pFormatFooter->GetFooterFormat(); + if( pFooterFormat ) + OutHTML_HeaderFooter( *this, *pFooterFormat, false ); + } + if (IsLFPossible()) + OutNewLine(); + if (!mbSkipHeaderFooter) + { + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_body), false ); + OutNewLine(); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_html), false ); + } + else if (mbReqIF) + // ReqIF: end xhtml.BlkStruct.class. + HTMLOutFuncs::Out_AsciiTag(Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false); + } // delete the table with floating frames - OSL_ENSURE( !m_pHTMLPosFlyFrames, "Were not all frames output?" ); - m_pHTMLPosFlyFrames.reset(); + OSL_ENSURE( m_aHTMLPosFlyFrames.empty(), "Were not all frames output?" ); + m_aHTMLPosFlyFrames.clear(); m_aHTMLControls.clear(); @@ -521,7 +651,7 @@ ErrCode SwHTMLWriter::WriteStream() mxFormComps.clear(); - OSL_ENSURE( !m_pFootEndNotes, + OSL_ENSURE( !m_xFootEndNotes, "SwHTMLWriter::Write: Footnotes not deleted by OutFootEndNotes" ); m_pCurrPageDesc = nullptr; @@ -531,8 +661,6 @@ ErrCode SwHTMLWriter::WriteStream() for(OUString & s : m_aBulletGrfs) s.clear(); - m_aNonConvertableCharacters.clear(); - if( m_bShowProgress ) ::EndProgress( m_pDoc->GetDocShell() ); @@ -563,20 +691,17 @@ ErrCode SwHTMLWriter::WriteStream() static const SwFormatCol *lcl_html_GetFormatCol( const SwSection& rSection, const SwSectionFormat& rFormat ) { - const SwFormatCol *pCol = nullptr; + if( SectionType::FileLink == rSection.GetType() ) + return nullptr; - const SfxPoolItem* pItem; - if( SectionType::FileLink != rSection.GetType() && - SfxItemState::SET == rFormat.GetAttrSet().GetItemState(RES_COL,false,&pItem) && - static_cast<const SwFormatCol *>(pItem)->GetNumCols() > 1 ) - { - pCol = static_cast<const SwFormatCol *>(pItem); - } + const SwFormatCol *pCol = rFormat.GetAttrSet().GetItemIfSet(RES_COL,false); + if (pCol->GetNumCols() > 1 ) + return pCol; - return pCol; + return nullptr; } -static bool lcl_html_IsMultiColStart( const SwHTMLWriter& rHTMLWrt, sal_uLong nIndex ) +static bool lcl_html_IsMultiColStart( const SwHTMLWriter& rHTMLWrt, SwNodeOffset nIndex ) { bool bRet = false; const SwSectionNode *pSectNd = @@ -592,7 +717,7 @@ static bool lcl_html_IsMultiColStart( const SwHTMLWriter& rHTMLWrt, sal_uLong nI return bRet; } -static bool lcl_html_IsMultiColEnd( const SwHTMLWriter& rHTMLWrt, sal_uLong nIndex ) +static bool lcl_html_IsMultiColEnd( const SwHTMLWriter& rHTMLWrt, SwNodeOffset nIndex ) { bool bRet = false; const SwEndNode *pEndNd = rHTMLWrt.m_pDoc->GetNodes()[nIndex]->GetEndNode(); @@ -611,29 +736,33 @@ static void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt, { OSL_ENSURE( pCol || !bContinued, "Continuation of DIV" ); - if( rHTMLWrt.m_bLFPossible ) + if (rHTMLWrt.IsLFPossible()) rHTMLWrt.OutNewLine(); - OStringBuffer sOut; - sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_division); + OStringBuffer sOut("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division); const OUString& rName = rSection.GetSectionName(); if( !rName.isEmpty() && !bContinued ) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_id "=\""); - rHTMLWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), rName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + rHTMLWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), rName ); sOut.append('\"'); } - SvxFrameDirection nDir = rHTMLWrt.GetHTMLDirection( rFormat.GetAttrSet() ); rHTMLWrt.Strm().WriteOString( sOut.makeStringAndClear() ); - rHTMLWrt.OutDirection( nDir ); + if (!rHTMLWrt.mbXHTML) + { + SvxFrameDirection nDir = rHTMLWrt.GetHTMLDirection(rFormat.GetAttrSet()); + rHTMLWrt.OutDirection(nDir); + } if( SectionType::FileLink == rSection.GetType() ) { sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_href "=\""); - rHTMLWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rHTMLWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); const OUString& aFName = rSection.GetLinkFileName(); sal_Int32 nIdx{ 0 }; @@ -645,32 +774,19 @@ static void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt, sal_Unicode cDelim = 255U; bool bURLContainsDelim = (-1 != aEncURL.indexOf( cDelim ) ); - HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aEncURL, - rHTMLWrt.m_eDestEnc, - &rHTMLWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aEncURL ); const char* const pDelim = "ÿ"; if( !aFilter.isEmpty() || !aSection.isEmpty() || bURLContainsDelim ) - rHTMLWrt.Strm().WriteCharPtr( pDelim ); + rHTMLWrt.Strm().WriteOString( pDelim ); if( !aFilter.isEmpty() ) - HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aFilter, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aFilter ); if( !aSection.isEmpty() || bURLContainsDelim ) - rHTMLWrt.Strm().WriteCharPtr( pDelim ); + rHTMLWrt.Strm().WriteOString( pDelim ); if( !aSection.isEmpty() ) { - sal_Int32 nPos = aSection.indexOf( '%' ); - while( nPos != -1 ) - { - aSection = aSection.replaceAt(nPos, 1, "%25"); - nPos = aSection.indexOf( '%', nPos+3 ); - } - nPos = aSection.indexOf( cDelim ); - while( nPos != -1 ) - { - aSection = aSection.replaceAt(nPos, 1, "%FF" ); - nPos = aSection.indexOf( cDelim, nPos+3 ); - } - HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aSection, - rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters ); + aSection = aSection.replaceAll(u"%", u"%25"); + aSection = aSection.replaceAll(OUStringChar(cDelim), u"%FF"); + HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aSection ); } sOut.append('\"'); } @@ -680,22 +796,19 @@ static void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt, sal_uInt16 nGutter = pCol->GetGutterWidth( true ); if( nGutter!=USHRT_MAX ) { - if( nGutter && Application::GetDefaultDevice() ) - { - nGutter = static_cast<sal_uInt16>(Application::GetDefaultDevice() - ->LogicToPixel( Size(nGutter, 0), MapMode(MapUnit::MapTwip) ).Width()); - } + nGutter = SwHTMLWriter::ToPixel(nGutter); sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_gutter "=\"" + OString::number(nGutter) + "\""); } } - rHTMLWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + rHTMLWrt.Strm().WriteOString( sOut ); + sOut.setLength(0); if( rHTMLWrt.IsHTMLMode( rHTMLWrt.m_bCfgOutStyles ? HTMLMODE_ON : 0 ) ) rHTMLWrt.OutCSS1_SectionFormatOptions( rFormat, pCol ); rHTMLWrt.Strm().WriteChar( '>' ); - rHTMLWrt.m_bLFPossible = true; + rHTMLWrt.SetLFPossible(true); if( !rName.isEmpty() && !bContinued ) rHTMLWrt.OutImplicitMark( rName, "region" ); @@ -705,20 +818,18 @@ static void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt, static void lcl_html_OutSectionEndTag( SwHTMLWriter& rHTMLWrt ) { rHTMLWrt.DecIndentLevel(); - if( rHTMLWrt.m_bLFPossible ) + if (rHTMLWrt.IsLFPossible()) rHTMLWrt.OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division, false ); - rHTMLWrt.m_bLFPossible = true; + HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), Concat2View(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false ); + rHTMLWrt.SetLFPossible(true); } -static Writer& OutHTML_Section( Writer& rWrt, const SwSectionNode& rSectNd ) +static SwHTMLWriter& OutHTML_Section( SwHTMLWriter& rWrt, const SwSectionNode& rSectNd ) { - SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt); - // End <PRE> and any <DL>, because a definition list's level may // change inside the section. - rHTMLWrt.ChangeParaToken( HtmlTokenId::NONE ); - rHTMLWrt.OutAndSetDefList( 0 ); + rWrt.ChangeParaToken( HtmlTokenId::NONE ); + rWrt.OutAndSetDefList( 0 ); const SwSection& rSection = rSectNd.GetSection(); const SwSectionFormat *pFormat = rSection.GetFormat(); @@ -731,18 +842,18 @@ static Writer& OutHTML_Section( Writer& rWrt, const SwSectionNode& rSectNd ) const SwSection *pSurrSection = nullptr; const SwFormatCol *pSurrCol = nullptr; - sal_uInt32 nSectSttIdx = rSectNd.GetIndex(); - sal_uInt32 nSectEndIdx = rSectNd.EndOfSectionIndex(); + SwNodeOffset nSectSttIdx = rSectNd.GetIndex(); + SwNodeOffset nSectEndIdx = rSectNd.EndOfSectionIndex(); const SwFormatCol *pCol = lcl_html_GetFormatCol( rSection, *pFormat ); if( pCol ) { // If the next node is a columned section node, too, don't export // an empty section. - if( lcl_html_IsMultiColStart( rHTMLWrt, nSectSttIdx+1 ) ) + if( lcl_html_IsMultiColStart( rWrt, nSectSttIdx+1 ) ) bStartTag = false; // The same applies if the section end with another columned section. - if( lcl_html_IsMultiColEnd( rHTMLWrt, nSectEndIdx-1 ) ) + if( lcl_html_IsMultiColEnd( rWrt, nSectEndIdx-1 ) ) bEndTag = false; // is there a columned section around this one? @@ -769,32 +880,32 @@ static Writer& OutHTML_Section( Writer& rWrt, const SwSectionNode& rSectNd ) // The surrounding section must be closed before the current one is // opened, except that it start immediately before the current one or // another end immediately before the current one - if( pSurrCol && nSectSttIdx - pSurrSectNd->GetIndex() > 1 && - !lcl_html_IsMultiColEnd( rHTMLWrt, nSectSttIdx-1 ) ) - lcl_html_OutSectionEndTag( rHTMLWrt ); + if( pSurrCol && nSectSttIdx - pSurrSectNd->GetIndex() > SwNodeOffset(1) && + !lcl_html_IsMultiColEnd( rWrt, nSectSttIdx-1 ) ) + lcl_html_OutSectionEndTag( rWrt ); if( bStartTag ) - lcl_html_OutSectionStartTag( rHTMLWrt, rSection, *pFormat, pCol ); + lcl_html_OutSectionStartTag( rWrt, rSection, *pFormat, pCol ); { - HTMLSaveData aSaveData( rHTMLWrt, - rHTMLWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex()+1, + HTMLSaveData aSaveData( rWrt, + rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex()+1, rSectNd.EndOfSectionIndex(), false, pFormat ); - rHTMLWrt.Out_SwDoc( rHTMLWrt.m_pCurrentPam.get() ); + rWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() ); } - rHTMLWrt.m_pCurrentPam->GetPoint()->nNode = *rSectNd.EndOfSectionNode(); + rWrt.m_pCurrentPam->GetPoint()->Assign(*rSectNd.EndOfSectionNode()); if( bEndTag ) - lcl_html_OutSectionEndTag( rHTMLWrt ); + lcl_html_OutSectionEndTag( rWrt ); // The surrounding section must be started again, except that it ends // immediately behind the current one. if( pSurrCol && - pSurrSectNd->EndOfSectionIndex() - nSectEndIdx > 1 && - !lcl_html_IsMultiColStart( rHTMLWrt, nSectEndIdx+1 ) ) - lcl_html_OutSectionStartTag( rHTMLWrt, *pSurrSection, *pSurrFormat, + pSurrSectNd->EndOfSectionIndex() - nSectEndIdx > SwNodeOffset(1) && + !lcl_html_IsMultiColStart( rWrt, nSectEndIdx+1 ) ) + lcl_html_OutSectionStartTag( rWrt, *pSurrSection, *pSurrFormat, pSurrCol, true ); return rWrt; @@ -803,6 +914,7 @@ static Writer& OutHTML_Section( Writer& rWrt, const SwSectionNode& rSectNd ) void SwHTMLWriter::Out_SwDoc( SwPaM* pPam ) { bool bSaveWriteAll = m_bWriteAll; // save + bool bIncludeHidden = officecfg::Office::Writer::FilterFlags::HTML::IncludeHiddenText::get(); // search next text::Bookmark position from text::Bookmark table m_nBkmkTabPos = m_bWriteAll ? FindPos_Bkmk( *m_pCurrentPam->GetPoint() ) : -1; @@ -815,22 +927,25 @@ void SwHTMLWriter::Out_SwDoc( SwPaM* pPam ) // search for first on PaM created FlyFrame // still missing: - while( m_pCurrentPam->GetPoint()->nNode.GetIndex() < m_pCurrentPam->GetMark()->nNode.GetIndex() || - (m_pCurrentPam->GetPoint()->nNode.GetIndex() == m_pCurrentPam->GetMark()->nNode.GetIndex() && - m_pCurrentPam->GetPoint()->nContent.GetIndex() <= m_pCurrentPam->GetMark()->nContent.GetIndex()) ) + while( m_pCurrentPam->GetPoint()->GetNodeIndex() < m_pCurrentPam->GetMark()->GetNodeIndex() || + (m_pCurrentPam->GetPoint()->GetNodeIndex() == m_pCurrentPam->GetMark()->GetNodeIndex() && + m_pCurrentPam->GetPoint()->GetContentIndex() <= m_pCurrentPam->GetMark()->GetContentIndex()) ) { - SwNode& rNd = m_pCurrentPam->GetNode(); + SwNode& rNd = m_pCurrentPam->GetPointNode(); OSL_ENSURE( !(rNd.IsGrfNode() || rNd.IsOLENode()), "Unexpected Grf- or OLE-Node here" ); + if( rNd.IsTextNode() ) { SwTextNode* pTextNd = rNd.GetTextNode(); + if (!pTextNd->IsHidden() || bIncludeHidden) + { + if (!m_bFirstLine) + m_pCurrentPam->GetPoint()->Assign(*pTextNd, 0); - if( !m_bFirstLine ) - m_pCurrentPam->GetPoint()->nContent.Assign( pTextNd, 0 ); - - OutHTML_SwTextNode( *this, *pTextNd ); + OutHTML_SwTextNode(*this, *pTextNd); + } } else if( rNd.IsTableNode() ) { @@ -839,17 +954,21 @@ void SwHTMLWriter::Out_SwDoc( SwPaM* pPam ) } else if( rNd.IsSectionNode() ) { - OutHTML_Section( *this, *rNd.GetSectionNode() ); - m_nBkmkTabPos = m_bWriteAll ? FindPos_Bkmk( *m_pCurrentPam->GetPoint() ) : -1; + SwSectionNode* pSectionNode = rNd.GetSectionNode(); + if (!pSectionNode->GetSection().IsHiddenFlag() || bIncludeHidden) + { + OutHTML_Section( *this, *pSectionNode ); + m_nBkmkTabPos = m_bWriteAll ? FindPos_Bkmk( *m_pCurrentPam->GetPoint() ) : -1; + } } else if( &rNd == &m_pDoc->GetNodes().GetEndOfContent() ) break; - ++m_pCurrentPam->GetPoint()->nNode; // move - sal_uInt32 nPos = m_pCurrentPam->GetPoint()->nNode.GetIndex(); + m_pCurrentPam->GetPoint()->Adjust(SwNodeOffset(+1)); // move + SwNodeOffset nPos = m_pCurrentPam->GetPoint()->GetNodeIndex(); if( m_bShowProgress ) - ::SetProgressState( nPos, m_pDoc->GetDocShell() ); // How far ? + ::SetProgressState( sal_Int32(nPos), m_pDoc->GetDocShell() ); // How far ? /* If only the selected area should be saved, so only the complete * nodes should be saved, this means the first and n-th node @@ -857,7 +976,7 @@ void SwHTMLWriter::Out_SwDoc( SwPaM* pPam ) * all formats!) */ m_bWriteAll = bSaveWriteAll || - nPos != m_pCurrentPam->GetMark()->nNode.GetIndex(); + nPos != m_pCurrentPam->GetMark()->GetNodeIndex(); m_bFirstLine = false; m_bOutFooter = false; // after one node no footer anymore } @@ -883,19 +1002,16 @@ static void OutBodyColor( const char* pTag, const SwFormat *pFormat, const SvxColorItem *pColorItem = nullptr; const SfxItemSet& rItemSet = pFormat->GetAttrSet(); - const SfxPoolItem *pRefItem = nullptr, *pItem = nullptr; - bool bItemSet = SfxItemState::SET == rItemSet.GetItemState( RES_CHRATR_COLOR, - true, &pItem); - bool bRefItemSet = pRefFormat && - SfxItemState::SET == pRefFormat->GetAttrSet().GetItemState( RES_CHRATR_COLOR, - true, &pRefItem); - if( bItemSet ) + const SvxColorItem *pCItem = rItemSet.GetItemIfSet( RES_CHRATR_COLOR ); + const SvxColorItem *pRefItem = nullptr; + if (pRefFormat) + pRefItem = pRefFormat->GetAttrSet().GetItemIfSet( RES_CHRATR_COLOR ); + if( pCItem ) { // only when the item is set in the template of the current document // or has a different value as the in HTML template, it will be set - const SvxColorItem *pCItem = static_cast<const SvxColorItem*>(pItem); - if( !bRefItemSet ) + if( !pRefItem ) { pColorItem = pCItem; } @@ -905,7 +1021,7 @@ static void OutBodyColor( const char* pTag, const SwFormat *pFormat, if( COL_AUTO == aColor ) aColor = COL_BLACK; - Color aRefColor( static_cast<const SvxColorItem*>(pRefItem)->GetValue() ); + Color aRefColor( pRefItem->GetValue() ); if( COL_AUTO == aRefColor ) aRefColor = COL_BLACK; @@ -913,17 +1029,16 @@ static void OutBodyColor( const char* pTag, const SwFormat *pFormat, pColorItem = pCItem; } } - else if( bRefItemSet ) + else if( pRefItem ) { // The item was still set in the HTML template so we output the default - pColorItem = &rItemSet.GetPool()->GetDefaultItem( RES_CHRATR_COLOR ); + pColorItem = &rItemSet.GetPool()->GetUserOrPoolDefaultItem( RES_CHRATR_COLOR ); } if( pColorItem ) { - OStringBuffer sOut; - sOut.append(OStringLiteral(" ") + pTag + "="); - rHWrt.Strm().WriteOString( sOut.makeStringAndClear() ); + OString sOut = OString::Concat(" ") + pTag + "="; + rHWrt.Strm().WriteOString( sOut ); Color aColor( pColorItem->GetValue() ); if( COL_AUTO == aColor ) aColor = COL_BLACK; @@ -935,8 +1050,8 @@ static void OutBodyColor( const char* pTag, const SwFormat *pFormat, sal_uInt16 SwHTMLWriter::OutHeaderAttrs() { - sal_uLong nIdx = m_pCurrentPam->GetPoint()->nNode.GetIndex(); - sal_uLong nEndIdx = m_pCurrentPam->GetMark()->nNode.GetIndex(); + SwNodeOffset nIdx = m_pCurrentPam->GetPoint()->GetNodeIndex(); + SwNodeOffset nEndIdx = m_pCurrentPam->GetMark()->GetNodeIndex(); SwTextNode *pTextNd = nullptr; while( nIdx<=nEndIdx && @@ -986,15 +1101,15 @@ const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs ) if (mbXHTML) sOut.append(OOO_STRING_SVTOOLS_HTML_doctype " " OOO_STRING_SVTOOLS_XHTML_doctype11); else - sOut.append(OOO_STRING_SVTOOLS_HTML_doctype " " OOO_STRING_SVTOOLS_HTML_doctype40); - HTMLOutFuncs::Out_AsciiTag( Strm(), sOut.makeStringAndClear().getStr() ); // No GetNamespace() here. + sOut.append(OOO_STRING_SVTOOLS_HTML_doctype " " OOO_STRING_SVTOOLS_HTML_doctype5); + HTMLOutFuncs::Out_AsciiTag( Strm(), sOut.makeStringAndClear() ); // No GetNamespace() here. // build prelude OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_html ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_html) ); OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_head ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_head) ); IncIndentLevel(); // indent content of <HEAD> @@ -1012,8 +1127,7 @@ const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs ) // xDocProps may be null here (when copying) SfxFrameHTMLWriter::Out_DocInfo( Strm(), GetBaseURL(), xDocProps, - sIndent.getStr(), m_eDestEnc, - &m_aNonConvertableCharacters ); + sIndent.getStr() ); // comments and meta-tags of first paragraph rHeaderAttrs = OutHeaderAttrs(); @@ -1025,15 +1139,14 @@ const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs ) // In none HTML documents the first set template will be exported // and if none is set the default template - sal_uLong nNodeIdx = m_pCurrentPam->GetPoint()->nNode.GetIndex(); + SwNodeOffset nNodeIdx = m_pCurrentPam->GetPoint()->GetNodeIndex(); while( nNodeIdx < m_pDoc->GetNodes().Count() ) { SwNode *pNd = m_pDoc->GetNodes()[ nNodeIdx ]; if( pNd->IsContentNode() ) { - pPageDesc = static_cast<const SwFormatPageDesc &>(pNd->GetContentNode() - ->GetAttr(RES_PAGEDESC)).GetPageDesc(); + pPageDesc = pNd->GetContentNode()->GetAttr(RES_PAGEDESC).GetPageDesc(); break; } else if( pNd->IsTableNode() ) @@ -1063,12 +1176,13 @@ const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs ) DecIndentLevel(); // indent content of <HEAD> OutNewLine(); - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_head, false ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_head), false ); // the body won't be indented, because then everything would be indented! OutNewLine(); sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_body); - Strm().WriteOString( sOut.makeStringAndClear() ); + Strm().WriteOString( sOut ); + sOut.setLength(0); // language OutLanguage( m_eLang ); @@ -1107,30 +1221,39 @@ const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs ) } else if (mbReqIF) // ReqIF: start xhtml.BlkStruct.class. - HTMLOutFuncs::Out_AsciiTag(Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_division); + HTMLOutFuncs::Out_AsciiTag(Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_division)); return pPageDesc; } void SwHTMLWriter::OutAnchor( const OUString& rName ) { - OStringBuffer sOut; - sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor " "); + if (mbReqIF) + { + // <a id=".."> has to be unique inside the whole document, but + // we only write a fragment, so we can't ensure the ID is indeed + // unique. Just don't write anchors in the ReqIF case. + return; + } + + OStringBuffer sOut("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor " "); if (!mbXHTML) { sOut.append(OOO_STRING_SVTOOLS_HTML_O_name "=\""); - Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( Strm(), rName, m_eDestEnc, &m_aNonConvertableCharacters ).WriteCharPtr( "\">" ); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), rName ).WriteOString( "\">" ); } else { // XHTML wants 'id' instead of 'name', also the value can't contain // spaces. sOut.append(OOO_STRING_SVTOOLS_HTML_O_id "=\""); - Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( Strm(), rName.replace(' ', '_'), m_eDestEnc, &m_aNonConvertableCharacters ).WriteCharPtr( "\">" ); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), rName.replace(' ', '_') ).WriteOString( "\">" ); } - HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor, false ); + HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor), false ); } void SwHTMLWriter::OutBookmarks() @@ -1142,9 +1265,9 @@ void SwHTMLWriter::OutBookmarks() pBookmark = pMarkAccess->getAllMarksBegin()[m_nBkmkTabPos]; // Output all bookmarks in this paragraph. The content position // for the moment isn't considered! - sal_uInt32 nNode = m_pCurrentPam->GetPoint()->nNode.GetIndex(); + SwNodeOffset nNode = m_pCurrentPam->GetPoint()->GetNodeIndex(); while( m_nBkmkTabPos != -1 - && pBookmark->GetMarkPos().nNode.GetIndex() == nNode ) + && pBookmark->GetMarkPos().GetNodeIndex() == nNode ) { // The area of bookmarks is first ignored, because it's not read. @@ -1202,7 +1325,7 @@ void SwHTMLWriter::OutPointFieldmarks( const SwPosition& rPos ) OOO_STRING_SVTOOLS_HTML_O_type "=\"" OOO_STRING_SVTOOLS_HTML_IT_checkbox - "\""); + "\""_ostr); if (pCheckBox->IsChecked()) { @@ -1255,7 +1378,8 @@ OUString SwHTMLWriter::convertHyperlinkHRefValue(const OUString& rURL) { // Link is not started from "#", so looks like external link. Encode this URL. INetURLObject aURL(sURL); - sURL = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); + if (!aURL.HasError()) + sURL = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE); } return URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), sURL ); } @@ -1263,7 +1387,7 @@ OUString SwHTMLWriter::convertHyperlinkHRefValue(const OUString& rURL) void SwHTMLWriter::OutHyperlinkHRefValue( const OUString& rURL ) { OUString sURL = convertHyperlinkHRefValue(rURL); - HTMLOutFuncs::Out_String( Strm(), sURL, m_eDestEnc, &m_aNonConvertableCharacters ); + HTMLOutFuncs::Out_String( Strm(), sURL ); } void SwHTMLWriter::OutBackground( const SvxBrushItem *pBrushItem, bool bGraphic ) @@ -1291,9 +1415,9 @@ void SwHTMLWriter::OutBackground( const SvxBrushItem *pBrushItem, bool bGraphic { m_nWarn = WARN_SWG_POOR_LOAD; } - Strm().WriteCharPtr( " " OOO_STRING_SVTOOLS_HTML_O_background "=\"" ); - Strm().WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_data ":" ); - HTMLOutFuncs::Out_String( Strm(), aGraphicInBase64, m_eDestEnc, &m_aNonConvertableCharacters ).WriteChar( '\"' ); + Strm().WriteOString( " " OOO_STRING_SVTOOLS_HTML_O_background "=\"" ); + Strm().WriteOString( OOO_STRING_SVTOOLS_HTML_O_data ":" ); + HTMLOutFuncs::Out_String( Strm(), aGraphicInBase64 ).WriteChar( '\"' ); } } else @@ -1303,26 +1427,24 @@ void SwHTMLWriter::OutBackground( const SvxBrushItem *pBrushItem, bool bGraphic CopyLocalFileToINet( GraphicURL ); } OUString s( URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), GraphicURL)); - Strm().WriteCharPtr(" " OOO_STRING_SVTOOLS_HTML_O_background "=\"" ); - HTMLOutFuncs::Out_String( Strm(), s, m_eDestEnc, &m_aNonConvertableCharacters ); - Strm().WriteCharPtr("\""); + Strm().WriteOString(" " OOO_STRING_SVTOOLS_HTML_O_background "=\"" ); + HTMLOutFuncs::Out_String( Strm(), s ); + Strm().WriteOString("\""); } } void SwHTMLWriter::OutBackground( const SfxItemSet& rItemSet, bool bGraphic ) { - const SfxPoolItem* pItem; - if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false, - &pItem )) + if( const SvxBrushItem* pItem = rItemSet.GetItemIfSet( RES_BACKGROUND, false ) ) { - OutBackground( static_cast<const SvxBrushItem*>(pItem), bGraphic ); + OutBackground( pItem, bGraphic ); } } -sal_uInt16 SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript ) +TypedWhichId<SvxLanguageItem> SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript ) { - sal_uInt16 nWhichId; + TypedWhichId<SvxLanguageItem> nWhichId(0); switch( nScript ) { case CSS1_OUTMODE_CJK: @@ -1344,16 +1466,15 @@ void SwHTMLWriter::OutLanguage( LanguageType nLang ) if (!(LANGUAGE_DONTKNOW != nLang && !mbReqIF)) return; - OStringBuffer sOut; - sOut.append(' '); + OStringBuffer sOut(" "); if (mbXHTML) sOut.append(OOO_STRING_SVTOOLS_XHTML_O_lang); else sOut.append(OOO_STRING_SVTOOLS_HTML_O_lang); sOut.append("=\""); - Strm().WriteOString( sOut.makeStringAndClear() ); - HTMLOutFuncs::Out_String( Strm(), LanguageTag::convertToBcp47(nLang), - m_eDestEnc, &m_aNonConvertableCharacters ).WriteChar( '"' ); + Strm().WriteOString( sOut ); + sOut.setLength(0); + HTMLOutFuncs::Out_String( Strm(), LanguageTag::convertToBcp47(nLang) ).WriteChar( '"' ); } SvxFrameDirection SwHTMLWriter::GetHTMLDirection( const SfxItemSet& rItemSet ) const @@ -1399,11 +1520,11 @@ OString SwHTMLWriter::convertDirection(SvxFrameDirection nDir) { case SvxFrameDirection::Horizontal_LR_TB: case SvxFrameDirection::Vertical_LR_TB: - sConverted = "ltr"; + sConverted = "ltr"_ostr; break; case SvxFrameDirection::Horizontal_RL_TB: case SvxFrameDirection::Vertical_RL_TB: - sConverted = "rtl"; + sConverted = "rtl"_ostr; break; default: break; } @@ -1431,14 +1552,14 @@ void SwHTMLWriter::OutNewLine( bool bCheck ) { if( !bCheck || (Strm().Tell()-m_nLastLFPos) > m_nIndentLvl ) { - Strm().WriteCharPtr( SAL_NEWLINE_STRING ); + Strm().WriteOString( SAL_NEWLINE_STRING ); m_nLastLFPos = Strm().Tell(); } if( m_nIndentLvl && m_nIndentLvl <= MAX_INDENT_LEVEL) { sIndentTabs[m_nIndentLvl] = 0; - Strm().WriteCharPtr( sIndentTabs ); + Strm().WriteOString( sIndentTabs ); sIndentTabs[m_nIndentLvl] = '\t'; } } @@ -1460,7 +1581,7 @@ sal_uInt16 SwHTMLWriter::GetHTMLFontSize( sal_uInt32 nHeight ) const // Paragraphs with Table of Contents and other index styles will be typeset with // dot leaders at the position of the last tabulator in PrintLayout (CSS2) mode -sal_Int32 SwHTMLWriter::indexOfDotLeaders( sal_uInt16 nPoolId, const OUString& rStr ) +sal_Int32 SwHTMLWriter::indexOfDotLeaders( sal_uInt16 nPoolId, std::u16string_view rStr ) { if (m_bCfgPrintLayout && ((nPoolId >= RES_POOLCOLL_TOX_CNTNT1 && nPoolId <= RES_POOLCOLL_TOX_CNTNT5) || (nPoolId >= RES_POOLCOLL_TOX_IDX1 && nPoolId <= RES_POOLCOLL_TOX_IDX3) || @@ -1468,9 +1589,9 @@ sal_Int32 SwHTMLWriter::indexOfDotLeaders( sal_uInt16 nPoolId, const OUString& r nPoolId == RES_POOLCOLL_TOX_ILLUS1 || nPoolId == RES_POOLCOLL_TOX_TABLES1 || nPoolId == RES_POOLCOLL_TOX_OBJECT1 || (nPoolId >= RES_POOLCOLL_TOX_AUTHORITIES1 && nPoolId <= RES_POOLCOLL_TOX_USER10))) { - sal_Int32 i = rStr.lastIndexOf('\t'); + size_t i = rStr.rfind('\t'); // there are only ASCII (Latin-1) characters after the tabulator - if (i > -1 && OUStringToOString(rStr.subView(i + 1), RTL_TEXTENCODING_ASCII_US).indexOf('?') == -1) + if (i != std::u16string_view::npos && OUStringToOString(rStr.substr(i + 1), RTL_TEXTENCODING_ASCII_US).indexOf('?') == -1) return i; } return -1; @@ -1486,8 +1607,8 @@ OString SwHTMLWriter::GetNamespace() const // Structure caches the current data of the writer to output a // other part of the document, like e.g. header/footer -HTMLSaveData::HTMLSaveData(SwHTMLWriter& rWriter, sal_uLong nStt, - sal_uLong nEnd, bool bSaveNum, +HTMLSaveData::HTMLSaveData(SwHTMLWriter& rWriter, SwNodeOffset nStt, + SwNodeOffset nEnd, bool bSaveNum, const SwFrameFormat *pFrameFormat) : rWrt(rWriter) , pOldPam(rWrt.m_pCurrentPam) @@ -1503,11 +1624,11 @@ HTMLSaveData::HTMLSaveData(SwHTMLWriter& rWriter, sal_uLong nStt, rWrt.m_pCurrentPam = Writer::NewUnoCursor(*rWrt.m_pDoc, nStt, nEnd); // recognize table in special areas - if( nStt != rWrt.m_pCurrentPam->GetMark()->nNode.GetIndex() ) + if( nStt != rWrt.m_pCurrentPam->GetMark()->GetNodeIndex() ) { const SwNode *pNd = rWrt.m_pDoc->GetNodes()[ nStt ]; if( pNd->IsTableNode() || pNd->IsSectionNode() ) - rWrt.m_pCurrentPam->GetMark()->nNode = nStt; + rWrt.m_pCurrentPam->GetMark()->Assign(*pNd); } rWrt.SetEndPaM( rWrt.m_pCurrentPam.get() ); @@ -1565,7 +1686,7 @@ HTMLSaveData::~HTMLSaveData() } } -void GetHTMLWriter( const OUString& rFilterOptions, const OUString& rBaseURL, WriterRef& xRet ) +void GetHTMLWriter( std::u16string_view rFilterOptions, const OUString& rBaseURL, WriterRef& xRet ) { xRet = new SwHTMLWriter( rBaseURL, rFilterOptions ); } diff --git a/sw/source/filter/html/wrthtml.hxx b/sw/source/filter/html/wrthtml.hxx index cef3eb788167..aac06fbf8868 100644 --- a/sw/source/filter/html/wrthtml.hxx +++ b/sw/source/filter/html/wrthtml.hxx @@ -24,6 +24,7 @@ #include <set> #include <string_view> #include <map> +#include <optional> #include <com/sun/star/container/XIndexContainer.hpp> #include <com/sun/star/form/XForm.hpp> @@ -62,11 +63,11 @@ class SwHTMLPosFlyFrames; class SwTextFootnote; enum class HtmlPosition; enum class HtmlTokenId : sal_Int16; -namespace utl { class TempFile; } +namespace utl { class TempFileNamed; } extern SwAttrFnTab aHTMLAttrFnTab; -#define HTML_PARSPACE (MM50) +#define HTML_PARSPACE (o3tl::toTwips(5, o3tl::Length::mm)) // flags for the output of any kind of frames // BORDER only possible if OutHTML_Image @@ -190,10 +191,10 @@ struct HTMLControl { // the form to which the control belongs css::uno::Reference<css::container::XIndexContainer> xFormComps; - sal_uLong nNdIdx; // the node in which it's anchored + SwNodeOffset nNdIdx; // the node in which it's anchored sal_Int32 nCount; // how many controls are on the node - HTMLControl( const css::uno::Reference<css::container::XIndexContainer>& rForm, sal_uInt32 nIdx ); + HTMLControl( css::uno::Reference<css::container::XIndexContainer> xForm, SwNodeOffset nIdx ); ~HTMLControl(); // operators for the sort array @@ -203,7 +204,7 @@ struct HTMLControl } }; -class HTMLControls : public o3tl::sorted_vector<std::unique_ptr<HTMLControl>, o3tl::less_uniqueptr_to<HTMLControl> > { +class HTMLControls : public o3tl::sorted_vector<std::unique_ptr<HTMLControl>, o3tl::less_ptr_to > { }; struct SwHTMLFormatInfo @@ -213,7 +214,7 @@ struct SwHTMLFormatInfo OString aToken; // the token to output OUString aClass; // the class to output - std::unique_ptr<SfxItemSet> pItemSet; // the attribute set to output + std::optional<SfxItemSet> moItemSet; // the attribute set to output sal_Int32 nLeftMargin; // some default values for sal_Int32 nRightMargin; // paragraph styles @@ -254,27 +255,48 @@ typedef std::set<std::unique_ptr<SwHTMLFormatInfo>, class IDocumentStylePoolAccess; -class SW_DLLPUBLIC SwHTMLWriter : public Writer +namespace sw { - std::unique_ptr<SwHTMLPosFlyFrames> m_pHTMLPosFlyFrames; +enum class Css1Background +{ + Attr = 1, + Page = 2, + Table = 3, + Fly = 4, + Section = 5, + TableRow = 6, + TableCell = 7, +}; +} + +class SwHTMLWriter : public Writer +{ + SwHTMLPosFlyFrames m_aHTMLPosFlyFrames; std::unique_ptr<SwHTMLNumRuleInfo> m_pNumRuleInfo;// current numbering std::unique_ptr<SwHTMLNumRuleInfo> m_pNextNumRuleInfo; sal_uInt32 m_nHTMLMode; // description of export configuration FieldUnit m_eCSS1Unit; + bool m_bPrettyPrint = true; // Allows to add new lines to make it more readable + bool m_bLFPossible = false; // a line break can be inserted + bool m_bSpacePreserve = false; // Using xml::space="preserve", or "white-space: pre-wrap" style + bool m_bPreserveSpacesOnWrite = false; // If export should use m_bSpacePreserve + sal_uInt16 OutHeaderAttrs(); const SwPageDesc *MakeHeader( sal_uInt16& rHeaderAtrs ); void GetControls(); - void AddLinkTarget( const OUString& rURL ); + void AddLinkTarget( std::u16string_view aURL ); void CollectLinkTargets(); - void SetupFilterOptions(const OUString& rFilterOptions); + void SetupFilterOptions(std::u16string_view rFilterOptions); protected: ErrCode WriteStream() override; void SetupFilterOptions(SfxMedium& rMedium) override; + void SetupFilterFromPropertyValues( + const css::uno::Sequence<css::beans::PropertyValue>& rPropertyValues); public: std::vector<OUString> m_aImgMapNames; // written image maps @@ -283,15 +305,14 @@ public: std::set<OUString> m_aScriptParaStyles; // script dependent para styles std::set<OUString> m_aScriptTextStyles; // script dependent text styles std::vector<OUString> m_aOutlineMarks; - std::vector<sal_uInt32> m_aOutlineMarkPoss; + std::vector<SwNodeOffset> m_aOutlineMarkPoss; HTMLControls m_aHTMLControls; // the forms to be written SwHTMLFormatInfos m_CharFormatInfos; SwHTMLFormatInfos m_TextCollInfos; std::vector<SwFormatINetFormat*> m_aINetFormats; // the "open" INet attributes - std::unique_ptr<std::vector<SwTextFootnote*>> m_pFootEndNotes; + std::optional<std::vector<SwTextFootnote*>> m_xFootEndNotes; OUString m_aCSS1Selector; // style selector - OUString m_aNonConvertableCharacters; OUString m_aBulletGrfs[MAXLEVEL]; // list graphics css::uno::Reference<css::container::XIndexContainer> mxFormComps; // current form @@ -305,7 +326,7 @@ public: sal_uInt32 m_aFontHeights[7]; // font heights 1-7 ErrCode m_nWarn; // warning code - sal_uInt32 m_nLastLFPos; // last position of LF + sal_uInt64 m_nLastLFPos; // last position of LF HtmlTokenId m_nLastParaToken; // to hold paragraphs together sal_Int32 m_nBkmkTabPos; // current position in bookmark table @@ -332,7 +353,6 @@ public: // that is not contained in class names) SvxFrameDirection m_nDirection; // the current direction - rtl_TextEncoding m_eDestEnc; LanguageType m_eLang; // description of the export configuration @@ -377,7 +397,6 @@ public: bool m_bNoAlign : 1; // HTML tag doesn't allow ALIGN=... bool m_bClearLeft : 1; // <BR CLEAR=LEFT> write at end of paragraph bool m_bClearRight : 1; // <BR CLEAR=RIGHT> write at end of paragraph - bool m_bLFPossible : 1; // a line break can be inserted // others @@ -390,7 +409,7 @@ public: bool mbSkipHeaderFooter : 1; bool mbEmbedImages : 1; /// Temporary base URL for paste of images. - std::unique_ptr<utl::TempFile> mpTempBaseURL; + std::unique_ptr<utl::TempFileNamed> mpTempBaseURL; /// If XHTML markup should be written instead of HTML. bool mbXHTML = false; /// XML namespace, in case of XHTML. @@ -401,16 +420,28 @@ public: #define sCSS2_P_CLASS_leaders "leaders" bool m_bCfgPrintLayout : 1; // PrintLayout option for TOC dot leaders bool m_bParaDotLeaders : 1; // for TOC dot leaders - // 25 + // 26 /// Tracks which text portion attributes are currently open: a which id -> open count map. std::map<sal_uInt16, int> maStartedAttributes; OUString m_aRTFOLEMimeType; + /// ReqIF mode: export images as OLE objects. + bool m_bExportImagesAsOLE = false; + + /// ReqIF mode: export formulas as PDFs. + bool m_bExportFormulasAsPDF = false; + + /// DPI used when exporting a vector shape as a bitmap. + std::optional<sal_Int32> m_nShapeDPI; + + /// If set, replace leading tabs with this many non-breaking spaces. + std::optional<sal_Int32> m_nLeadingTabWidth; + /// Construct an instance of SwHTMLWriter and optionally give it /// the filter options directly, which can also be set via SetupFilterOptions(). - explicit SwHTMLWriter( const OUString& rBaseURL, const OUString& rFilterOptions = "" ); + SW_DLLPUBLIC explicit SwHTMLWriter( const OUString& rBaseURL, std::u16string_view rFilterOptions = std::u16string_view() ); virtual ~SwHTMLWriter() override; void Out_SwDoc( SwPaM* ); // write the marked range @@ -426,8 +457,8 @@ public: void OutHyperlinkHRefValue( const OUString& rURL ); // output the FlyFrame anchored at current position - bool OutFlyFrame( sal_uLong nNdIdx, sal_Int32 nContentIdx, - HtmlPosition nPos, HTMLOutContext *pContext = nullptr ); + bool OutFlyFrame( SwNodeOffset nNdIdx, sal_Int32 nContentIdx, + HtmlPosition nPos ); void OutFrameFormat( AllHtmlFlags nType, const SwFrameFormat& rFormat, const SdrObject *pSdrObj ); @@ -443,25 +474,24 @@ public: void OutFootEndNoteInfo(); void OutFootEndNotes(); OUString GetFootEndNoteSym( const SwFormatFootnote& rFormatFootnote ); - void OutFootEndNoteSym( const SwFormatFootnote& rFormatFootnote, const OUString& rNum, + void OutFootEndNoteSym( const SwFormatFootnote& rFormatFootnote, std::u16string_view rNum, sal_uInt16 nScript ); void OutBasic(const SwHTMLWriter& rHTMLWrt); + // Used to indent inner blocks using dl/dd tags void OutAndSetDefList( sal_uInt16 nNewLvl ); void OutStyleSheet( const SwPageDesc& rPageDesc ); - inline void OutCSS1_PropertyAscii( const char *pProp, - const char *pVal ); - inline void OutCSS1_PropertyAscii( const char *pProp, + inline void OutCSS1_PropertyAscii( std::string_view pProp, std::string_view rVal ); - inline void OutCSS1_Property( const char *pProp, const OUString& rVal ); - void OutCSS1_Property( const char *pProp, std::string_view pVal, - const OUString *pSVal ); - void OutCSS1_UnitProperty( const char *pProp, tools::Long nVal ); - void OutCSS1_PixelProperty( const char *pProp, tools::Long nVal, bool bVert ); - void OutCSS1_SfxItemSet( const SfxItemSet& rItemSet, bool bDeep=true ); + inline void OutCSS1_Property( std::string_view pProp, const OUString& rVal ); + void OutCSS1_Property( std::string_view pProp, std::string_view pVal, + const OUString *pSVal, std::optional<sw::Css1Background> oBackground = std::nullopt ); + void OutCSS1_UnitProperty( std::string_view pProp, tools::Long nVal ); + void OutCSS1_PixelProperty( std::string_view pProp, tools::Long nTwips ); + void OutCSS1_SfxItemSet( const SfxItemSet& rItemSet, bool bDeep=true, std::string_view rAdd = {} ); // events of BODY tag from SFX configuration void OutBasicBodyEvents(); @@ -479,13 +509,17 @@ public: // ALT/ALIGN/WIDTH/HEIGHT/HSPACE/VSPACE option of current // frame format output and maybe add a <BR CLEAR=...> at the // beginning of rEndTags - OString OutFrameFormatOptions( const SwFrameFormat& rFrameFormat, const OUString& rAltText, + OString OutFrameFormatOptions( const SwFrameFormat& rFrameFormat, std::u16string_view rAltText, HtmlFrmOpts nFrameOpts ); - void writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameFormat& rFrameFormat, std::u16string_view rAltText, HtmlFrmOpts nFrameOpts); + void writeFrameFormatOptions(HtmlWriter& aHtml, const SwFrameFormat& rFrameFormat, const OUString& rAltText, HtmlFrmOpts nFrameOpts); + /// Writes the formatting for tables. void OutCSS1_TableFrameFormatOptions( const SwFrameFormat& rFrameFormat ); - void OutCSS1_TableCellBorderHack(const SwFrameFormat& rFrameFormat); + + /// Writes the borders and background for table cells. + void OutCSS1_TableCellBordersAndBG(const SwFrameFormat& rFrameFormat, const SvxBrushItem *pBrushItem); + void OutCSS1_SectionFormatOptions( const SwFrameFormat& rFrameFormat, const SwFormatCol *pCol ); void OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat, HtmlFrmOpts nFrameOpts, const SdrObject *pSdrObj=nullptr, @@ -514,11 +548,12 @@ public: SwPaM* GetEndPaM() { return m_pOrigPam; } void SetEndPaM( SwPaM* pPam ) { m_pOrigPam = pPam; } - static sal_uInt32 ToPixel( sal_uInt32 nVal, const bool bVert ); + static sal_uInt32 ToPixel(sal_uInt32 nTwips); + static Size ToPixel(Size aTwips); - sal_uInt16 GuessFrameType( const SwFrameFormat& rFrameFormat, + SwHTMLFrameType GuessFrameType( const SwFrameFormat& rFrameFormat, const SdrObject*& rpStrObj ); - static sal_uInt16 GuessOLENodeFrameType( const SwNode& rNd ); + static SwHTMLFrameType GuessOLENodeFrameType( const SwNode& rNd ); void CollectFlyFrames(); @@ -561,7 +596,7 @@ public: static void GetEEAttrsFromDrwObj( SfxItemSet& rItemSet, const SdrObject *pObj ); - static sal_uInt16 GetDefListLvl( const OUString& rNm, sal_uInt16 nPoolId ); + static sal_uInt16 GetDefListLvl( std::u16string_view rNm, sal_uInt16 nPoolId ); sal_uInt32 GetHTMLMode() const { @@ -579,14 +614,21 @@ public: static void PrepareFontList( const SvxFontItem& rFontItem, OUString& rNames, sal_Unicode cQuote, bool bGeneric ); static sal_uInt16 GetCSS1ScriptForScriptType( sal_uInt16 nScriptType ); - static sal_uInt16 GetLangWhichIdFromScript( sal_uInt16 nScript ); + static TypedWhichId<SvxLanguageItem> GetLangWhichIdFromScript( sal_uInt16 nScript ); FieldUnit GetCSS1Unit() const { return m_eCSS1Unit; } - sal_Int32 indexOfDotLeaders( sal_uInt16 nPoolId, const OUString& rText ); + sal_Int32 indexOfDotLeaders( sal_uInt16 nPoolId, std::u16string_view rText ); /// Determines the prefix string needed to respect the requested namespace alias. OString GetNamespace() const; + + bool IsPrettyPrint() const { return !m_bSpacePreserve && m_bPrettyPrint; } + bool IsLFPossible() const { return !m_bSpacePreserve && m_bLFPossible; } + void SetLFPossible(bool val) { m_bLFPossible = val; } + bool IsSpacePreserve() const { return m_bSpacePreserve; } + void SetSpacePreserve(bool val) { m_bSpacePreserve = val; } + bool IsPreserveSpacesOnWritePrefSet() const { return m_bPreserveSpacesOnWrite; } }; inline bool SwHTMLWriter::IsCSS1Source( sal_uInt16 n ) const @@ -600,19 +642,13 @@ inline bool SwHTMLWriter::IsCSS1Script( sal_uInt16 n ) const return CSS1_OUTMODE_ANY_SCRIPT == nScript || n == nScript; } -inline void SwHTMLWriter::OutCSS1_PropertyAscii( const char *pProp, - const char *pVal ) -{ - OutCSS1_Property( pProp, pVal, nullptr ); -} - -inline void SwHTMLWriter::OutCSS1_PropertyAscii( const char *pProp, +inline void SwHTMLWriter::OutCSS1_PropertyAscii( std::string_view pProp, std::string_view rVal ) { OutCSS1_Property( pProp, rVal, nullptr ); } -inline void SwHTMLWriter::OutCSS1_Property( const char *pProp, +inline void SwHTMLWriter::OutCSS1_Property( std::string_view pProp, const OUString& rVal ) { OutCSS1_Property( pProp, std::string_view(), &rVal ); @@ -625,7 +661,7 @@ inline void SwHTMLWriter::OutCSS1_Property( const char *pProp, // positions in the document. // In dtor all data is restored and the created PaM is deleted again. -struct HTMLSaveData +class HTMLSaveData { SwHTMLWriter& rWrt; std::shared_ptr<SwUnoCursor> pOldPam; @@ -639,67 +675,73 @@ struct HTMLSaveData bool bOldOutFooter : 1; bool bOldOutFlyFrame : 1; - HTMLSaveData( SwHTMLWriter&, sal_uLong nStt, sal_uLong nEnd, +public: + HTMLSaveData( SwHTMLWriter&, SwNodeOffset nStt, SwNodeOffset nEnd, bool bSaveNum=true, const SwFrameFormat *pFrameFormat=nullptr ); ~HTMLSaveData(); }; // some function prototypes -Writer& OutHTML_FrameFormatOLENode( Writer& rWrt, const SwFrameFormat& rFormat, +SwHTMLWriter& OutHTML_FrameFormatOLENode( SwHTMLWriter& rWrt, const SwFrameFormat& rFormat, bool bInCntnr ); -Writer& OutHTML_FrameFormatOLENodeGrf( Writer& rWrt, const SwFrameFormat& rFormat, - bool bInCntnr ); +SwHTMLWriter& OutHTML_FrameFormatOLENodeGrf( SwHTMLWriter& rWrt, const SwFrameFormat& rFormat, + bool bInCntnr, bool bWriteReplacementGraphic = true ); -Writer& OutHTML_SwTextNode( Writer&, const SwContentNode& ); -Writer& OutHTML_SwTableNode( Writer& , SwTableNode &, const SwFrameFormat *, +SwHTMLWriter& OutHTML_SwTextNode( SwHTMLWriter&, const SwContentNode& ); +SwHTMLWriter& OutHTML_SwTableNode( SwHTMLWriter& , SwTableNode &, const SwFrameFormat *, const OUString* pCaption=nullptr, bool bTopCaption=false ); -Writer& OutHTML_DrawFrameFormatAsControl( Writer& rWrt, const SwDrawFrameFormat& rFormat, +SwHTMLWriter& OutHTML_DrawFrameFormatAsControl( SwHTMLWriter& rWrt, const SwDrawFrameFormat& rFormat, const SdrUnoObj& rSdrObj, bool bInCntnr ); -Writer& OutHTML_DrawFrameFormatAsMarquee( Writer& rWrt, const SwDrawFrameFormat& rFormat, +SwHTMLWriter& OutHTML_DrawFrameFormatAsMarquee( SwHTMLWriter& rWrt, const SwDrawFrameFormat& rFormat, const SdrObject& rSdrObj ); -Writer& OutHTML_HeaderFooter( Writer& rWrt, const SwFrameFormat& rFrameFormat, +SwHTMLWriter& OutHTML_HeaderFooter( SwHTMLWriter& rWrt, const SwFrameFormat& rFrameFormat, bool bHeader ); -Writer& OutHTML_Image( Writer&, const SwFrameFormat& rFormat, +SwHTMLWriter& OutHTML_ImageStart( HtmlWriter& rHtml, SwHTMLWriter&, const SwFrameFormat& rFormat, const OUString& rGraphicURL, Graphic const & rGraphic, const OUString& rAlternateText, const Size& rRealSize, HtmlFrmOpts nFrameOpts, const char *pMarkType, const ImageMap *pGenImgMap, - const OUString& rMimeType = OUString() ); + const OUString& rMimeType = {} ); +SwHTMLWriter& OutHTML_ImageEnd( HtmlWriter& rHtml, SwHTMLWriter& ); -Writer& OutHTML_BulletImage( Writer& rWrt, const char *pTag, +SwHTMLWriter& OutHTML_BulletImage( SwHTMLWriter& rWrt, const char *pTag, const SvxBrushItem* pBrush, const OUString& rGraphicURL); -Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt ); -Writer& OutHTML_SwFormatFootnote( Writer& rWrt, const SfxPoolItem& rHt ); -Writer& OutHTML_INetFormat( Writer&, const SwFormatINetFormat& rINetFormat, bool bOn ); +SwHTMLWriter& OutHTML_SwFormatField( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); +SwHTMLWriter& OutHTML_SwFormatFootnote( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); +SwHTMLWriter& OutHTML_SwFormatLineBreak(SwHTMLWriter& rWrt, const SfxPoolItem& rHt); +SwHTMLWriter& OutHTML_INetFormat( SwHTMLWriter&, const SwFormatINetFormat& rINetFormat, bool bOn ); + +SwHTMLWriter& OutCSS1_BodyTagStyleOpt( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet ); +SwHTMLWriter& OutCSS1_ParaTagStyleOpt( SwHTMLWriter& rWrt, const SfxItemSet& rItemSet, std::string_view rAdd = {} ); -Writer& OutCSS1_BodyTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet ); -Writer& OutCSS1_ParaTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet ); +SwHTMLWriter& OutCSS1_HintSpanTag( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); +SwHTMLWriter& OutCSS1_HintStyleOpt( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); -Writer& OutCSS1_HintSpanTag( Writer& rWrt, const SfxPoolItem& rHt ); -Writer& OutCSS1_HintStyleOpt( Writer& rWrt, const SfxPoolItem& rHt ); +/// Writes the background of table rows. +SwHTMLWriter& OutCSS1_TableBGStyleOpt( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); -Writer& OutCSS1_TableBGStyleOpt( Writer& rWrt, const SfxPoolItem& rHt ); -Writer& OutCSS1_NumberBulletListStyleOpt( Writer& rWrt, const SwNumRule& rNumRule, +SwHTMLWriter& OutCSS1_NumberBulletListStyleOpt( SwHTMLWriter& rWrt, const SwNumRule& rNumRule, sal_uInt8 nLevel ); -Writer& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, +SwHTMLWriter& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt, const SwHTMLNumRuleInfo& rInfo ); -Writer& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt, +SwHTMLWriter& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt, const SwHTMLNumRuleInfo& rNextInfo ); -Writer& OutCSS1_SvxBox( Writer& rWrt, const SfxPoolItem& rHt ); +SwHTMLWriter& OutCSS1_SvxBox( SwHTMLWriter& rWrt, const SfxPoolItem& rHt ); OString GetCSS1_Color(const Color& rColor); /// Determines if rProperty with a given rValue has to be suppressed due to ReqIF mode. -bool IgnorePropertyForReqIF(bool bReqIF, std::string_view rProperty, std::string_view rValue); +bool IgnorePropertyForReqIF(bool bReqIF, std::string_view rProperty, std::string_view rValue, + std::optional<sw::Css1Background> oBackground = std::nullopt); #endif // INCLUDED_SW_SOURCE_FILTER_HTML_WRTHTML_HXX |