xref: /core/sw/source/filter/html/wrthtml.cxx (revision edaa5c608548ec2878abc5a9dc88f7867a1429a9)
161355e51SSebastian Spaeth /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2caaeb0a0SMichael Meeks /*
3caaeb0a0SMichael Meeks  * This file is part of the LibreOffice project.
47b0b5cdfSJens-Heiner Rechtien  *
5caaeb0a0SMichael Meeks  * This Source Code Form is subject to the terms of the Mozilla Public
6caaeb0a0SMichael Meeks  * License, v. 2.0. If a copy of the MPL was not distributed with this
7caaeb0a0SMichael Meeks  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8a817f983SRüdiger Timm  *
9caaeb0a0SMichael Meeks  * This file incorporates work covered by the following license notice:
10a817f983SRüdiger Timm  *
11caaeb0a0SMichael Meeks  *   Licensed to the Apache Software Foundation (ASF) under one or more
12caaeb0a0SMichael Meeks  *   contributor license agreements. See the NOTICE file distributed
13caaeb0a0SMichael Meeks  *   with this work for additional information regarding copyright
14caaeb0a0SMichael Meeks  *   ownership. The ASF licenses this file to you under the Apache
15caaeb0a0SMichael Meeks  *   License, Version 2.0 (the "License"); you may not use this file
16caaeb0a0SMichael Meeks  *   except in compliance with the License. You may obtain a copy of
17caaeb0a0SMichael Meeks  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18caaeb0a0SMichael Meeks  */
197b0b5cdfSJens-Heiner Rechtien 
207b0b5cdfSJens-Heiner Rechtien #include <stdlib.h>
217b0b5cdfSJens-Heiner Rechtien #include <hintids.hxx>
22ca02d728SCaolán McNamara #include <comphelper/string.hxx>
23ed87eb8fSMathias Bauer #include <svl/urihelper.hxx>
24a361f46bSGabor Kelemen #include <svl/languageoptions.hxx>
257b0b5cdfSJens-Heiner Rechtien #include <rtl/tencinfo.h>
268ba10f80SKurt Zenker #include <sfx2/linkmgr.hxx>
27b810c84cSMiklos Vajna #include <sfx2/docfile.hxx>
28683e0f74SJens-Heiner Rechtien 
29a3dad64dSMathias Bauer #include <svtools/htmlcfg.hxx>
3057f1934bSNoel Grandin #include <svtools/htmltokn.h>
311d39c5aaSGabor Kelemen #include <svtools/htmlkywd.hxx>
32683e0f74SJens-Heiner Rechtien #include <vcl/svapp.hxx>
33876c619bSEike Rathke #include <i18nlangtag/languagetag.hxx>
347b0b5cdfSJens-Heiner Rechtien #include <sfx2/frmhtmlw.hxx>
357b0b5cdfSJens-Heiner Rechtien #include <svx/xoutbmp.hxx>
36298e144fSMichael Stahl #include <svx/unobrushitemhelper.hxx>
3713dcaae5SMichael Dunphy #include <sfx2/htmlmode.hxx>
3855f1f483SMathias Bauer #include <editeng/lrspitem.hxx>
3955f1f483SMathias Bauer #include <editeng/colritem.hxx>
401aaf9a9bSKohei Yoshida #include <editeng/brushitem.hxx>
4155f1f483SMathias Bauer #include <editeng/langitem.hxx>
42ed87eb8fSMathias Bauer #include <svl/stritem.hxx>
4355f1f483SMathias Bauer #include <editeng/frmdiritem.hxx>
44b13f6ea1SMichael Brauer 
456f28e672SOliver Bolte #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
466f28e672SOliver Bolte #include <com/sun/star/document/XDocumentProperties.hpp>
47b512ce25SStephan Bergmann #include <com/sun/star/frame/XModel.hpp>
487b0b5cdfSJens-Heiner Rechtien #include <fmthdft.hxx>
497b0b5cdfSJens-Heiner Rechtien #include <fmtfld.hxx>
507b0b5cdfSJens-Heiner Rechtien #include <fmtpdsc.hxx>
517b0b5cdfSJens-Heiner Rechtien #include <txatbase.hxx>
522ae65086Sjp #include <frmatr.hxx>
537b0b5cdfSJens-Heiner Rechtien #include <charfmt.hxx>
547b0b5cdfSJens-Heiner Rechtien #include <docary.hxx>
557b0b5cdfSJens-Heiner Rechtien #include <pam.hxx>
567b0b5cdfSJens-Heiner Rechtien #include <doc.hxx>
577b0b5cdfSJens-Heiner Rechtien #include <ndtxt.hxx>
58a7724966STor Lillqvist #include <mdiexp.hxx>
597b0b5cdfSJens-Heiner Rechtien #include <fltini.hxx>
607b0b5cdfSJens-Heiner Rechtien #include <viewopt.hxx>
61a7724966STor Lillqvist #include <IMark.hxx>
627b0b5cdfSJens-Heiner Rechtien #include <poolfmt.hxx>
637b0b5cdfSJens-Heiner Rechtien #include <pagedesc.hxx>
647b0b5cdfSJens-Heiner Rechtien #include <section.hxx>
657b0b5cdfSJens-Heiner Rechtien #include <swtable.hxx>
667b0b5cdfSJens-Heiner Rechtien #include <fldbas.hxx>
677b0b5cdfSJens-Heiner Rechtien #include <fmtclds.hxx>
687b0b5cdfSJens-Heiner Rechtien #include <docsh.hxx>
69b567cfb9SMike Kaganski #include "wrthtml.hxx"
70b567cfb9SMike Kaganski #include "htmlnum.hxx"
71b567cfb9SMike Kaganski #include "htmlfly.hxx"
727b0b5cdfSJens-Heiner Rechtien #include <swmodule.hxx>
7300657aefSCaolán McNamara #include <strings.hrc>
747b0b5cdfSJens-Heiner Rechtien #include <swerror.h>
7568a832c7SCaolán McNamara #include <rtl/strbuf.hxx>
764269e3a7SValentin Kettner #include <IDocumentSettingAccess.hxx>
77535971f3SValentin Kettner #include <IDocumentStylePoolAccess.hxx>
78fc2d155fSMiklos Vajna #include <IDocumentMarkAccess.hxx>
7937be7a3fSKohei Yoshida #include <xmloff/odffields.hxx>
800706b575SVasily Melenchuk #include <tools/urlobj.hxx>
81af69f27eSMiklos Vajna #include <osl/file.hxx>
82af69f27eSMiklos Vajna #include <comphelper/scopeguard.hxx>
836a189b2aSMiklos Vajna #include <unotools/tempfile.hxx>
84037cd13aSMiklos Vajna #include <comphelper/sequenceashashmap.hxx>
85da9bba7cSNoel Grandin #include <officecfg/Office/Common.hxx>
86c3549e78SSamuel Mehrbrodt #include <officecfg/Office/Writer.hxx>
87c2cf1b01SMiklos Vajna #include <comphelper/propertysequence.hxx>
88c2cf1b01SMiklos Vajna #include <comphelper/sequence.hxx>
897b0b5cdfSJens-Heiner Rechtien 
907b0b5cdfSJens-Heiner Rechtien #define MAX_INDENT_LEVEL 20
917b0b5cdfSJens-Heiner Rechtien 
924aec6c9eSTomaž Vajngerl using namespace css;
934aec6c9eSTomaž Vajngerl 
9440a7abaaSNoel Grandin static char sIndentTabs[MAX_INDENT_LEVEL+2] =
957b0b5cdfSJens-Heiner Rechtien     "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
967b0b5cdfSJens-Heiner Rechtien 
SwHTMLWriter(const OUString & rBaseURL,std::u16string_view rFilterOptions)975de24375SNoel Grandin SwHTMLWriter::SwHTMLWriter( const OUString& rBaseURL, std::u16string_view rFilterOptions )
983af36642SNoel Grandin     : m_pNumRuleInfo(new SwHTMLNumRuleInfo)
99b46496c4SMiklos Vajna     , m_nHTMLMode(0)
1009e0770eaSMike Kaganski     , m_eCSS1Unit(FieldUnit::NONE)
10101b49802SStephan Bergmann     , m_pStartNdIdx(nullptr)
10201b49802SStephan Bergmann     , m_pCurrPageDesc(nullptr)
10301b49802SStephan Bergmann     , m_pFormatFootnote(nullptr)
104b46496c4SMiklos Vajna     , m_nWarn(0)
105b46496c4SMiklos Vajna     , m_nLastLFPos(0)
10657f1934bSNoel Grandin     , m_nLastParaToken(HtmlTokenId::NONE)
107b46496c4SMiklos Vajna     , m_nBkmkTabPos(-1)
108b46496c4SMiklos Vajna     , m_nImgMapCnt(1)
109b46496c4SMiklos Vajna     , m_nFormCntrlCnt(0)
110b46496c4SMiklos Vajna     , m_nEndNote(0)
111b46496c4SMiklos Vajna     , m_nFootNote(0)
112b46496c4SMiklos Vajna     , m_nLeftMargin(0)
113b46496c4SMiklos Vajna     , m_nDfltLeftMargin(0)
114b46496c4SMiklos Vajna     , m_nDfltRightMargin(0)
115b46496c4SMiklos Vajna     , m_nFirstLineIndent(0)
116b46496c4SMiklos Vajna     , m_nDfltFirstLineIndent(0)
117b46496c4SMiklos Vajna     , m_nDfltTopMargin(0)
118b46496c4SMiklos Vajna     , m_nDfltBottomMargin(0)
119b46496c4SMiklos Vajna     , m_nIndentLvl(0)
1204dab08d7SSzymon Kłos     , m_nWishLineLen(70)
121b46496c4SMiklos Vajna     , m_nDefListLvl(0)
122b46496c4SMiklos Vajna     , m_nDefListMargin(0)
123b46496c4SMiklos Vajna     , m_nHeaderFooterSpace(0)
124b46496c4SMiklos Vajna     , m_nTextAttrsToIgnore(0)
125b46496c4SMiklos Vajna     , m_nExportMode(0)
126b46496c4SMiklos Vajna     , m_nCSS1OutMode(0)
127b46496c4SMiklos Vajna     , m_nCSS1Script(CSS1_OUTMODE_WESTERN)
1288ccbc16bSNoel Grandin     , m_nDirection(SvxFrameDirection::Horizontal_LR_TB)
129b46496c4SMiklos Vajna     , m_eLang(LANGUAGE_DONTKNOW)
130b46496c4SMiklos Vajna     , m_bCfgOutStyles( false )
131b46496c4SMiklos Vajna     , m_bCfgPreferStyles( false )
132b46496c4SMiklos Vajna     , m_bCfgFormFeed( false )
133b46496c4SMiklos Vajna     , m_bCfgStarBasic( false )
134b46496c4SMiklos Vajna     , m_bCfgCpyLinkedGrfs( false )
135b46496c4SMiklos Vajna     , m_bFirstLine(true)
136b46496c4SMiklos Vajna     , m_bTagOn( false )
137b46496c4SMiklos Vajna     , m_bTextAttr( false )
138b46496c4SMiklos Vajna     , m_bOutOpts( false )
139b46496c4SMiklos Vajna     , m_bOutTable( false )
140b46496c4SMiklos Vajna     , m_bOutHeader( false )
141b46496c4SMiklos Vajna     , m_bOutFooter( false )
142b46496c4SMiklos Vajna     , m_bOutFlyFrame( false )
143b46496c4SMiklos Vajna     , m_bFirstCSS1Rule( false )
144b46496c4SMiklos Vajna     , m_bFirstCSS1Property( false )
145b46496c4SMiklos Vajna     , m_bCSS1IgnoreFirstPageDesc( false )
146b46496c4SMiklos Vajna     , m_bNoAlign( false )
147b46496c4SMiklos Vajna     , m_bClearLeft( false )
148b46496c4SMiklos Vajna     , m_bClearRight( false )
149b46496c4SMiklos Vajna     , m_bPreserveForm( false )
150b46496c4SMiklos Vajna     , m_bCfgNetscape4( false )
1512387805fSTomaž Vajngerl     , mbSkipImages(false)
1528760b2b0SMiklos Vajna     , mbSkipHeaderFooter(false)
15346fa816aSOliver Specht     , mbEmbedImages(false)
154b46496c4SMiklos Vajna     , m_bCfgPrintLayout( false )
155b46496c4SMiklos Vajna     , m_bParaDotLeaders( false )
1567b0b5cdfSJens-Heiner Rechtien {
157ae87272cSRüdiger Timm     SetBaseURL(rBaseURL);
1586a189b2aSMiklos Vajna 
1596a189b2aSMiklos Vajna     if (rBaseURL.isEmpty())
1606a189b2aSMiklos Vajna     {
1616a189b2aSMiklos Vajna         // Paste: set base URL to a tempfile, so images are not lost.
1624b95451fSNoel Grandin         mpTempBaseURL.reset(new utl::TempFileNamed());
1636a189b2aSMiklos Vajna         mpTempBaseURL->EnableKillingFile();
1646a189b2aSMiklos Vajna         SetBaseURL(mpTempBaseURL->GetURL());
1656a189b2aSMiklos Vajna     }
166ff90a487SAshod Nakashian 
167ff90a487SAshod Nakashian     SetupFilterOptions(rFilterOptions);
1689d38360eSMiklos Vajna 
1699d38360eSMiklos Vajna     if (mbXHTML)
1709d38360eSMiklos Vajna     {
1719d38360eSMiklos Vajna         m_bNoAlign = true;
1729d38360eSMiklos Vajna     }
1737b0b5cdfSJens-Heiner Rechtien }
1747b0b5cdfSJens-Heiner Rechtien 
~SwHTMLWriter()17529f5b4f7SGert Faller SwHTMLWriter::~SwHTMLWriter()
1767b0b5cdfSJens-Heiner Rechtien {
1777b0b5cdfSJens-Heiner Rechtien }
1787b0b5cdfSJens-Heiner Rechtien 
ReleaseNextNumInfo()179011c6c71SNoel Grandin std::unique_ptr<SwHTMLNumRuleInfo> SwHTMLWriter::ReleaseNextNumInfo()
180011c6c71SNoel Grandin {
181011c6c71SNoel Grandin     return std::move(m_pNextNumRuleInfo);
182011c6c71SNoel Grandin }
183011c6c71SNoel Grandin 
SetupFilterOptions(SfxMedium & rMedium)1844aec6c9eSTomaž Vajngerl void SwHTMLWriter::SetupFilterOptions(SfxMedium& rMedium)
1854aec6c9eSTomaž Vajngerl {
186c2cf1b01SMiklos Vajna     uno::Sequence<beans::PropertyValue> aArgs = rMedium.GetArgs();
187f5dd4faeSMike Kaganski     if (const SfxStringItem* pItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ))
18889667371SMiklos Vajna     {
18904e32513SNoel Grandin         const OUString sFilterOptions = pItem->GetValue();
190c2cf1b01SMiklos Vajna 
191c2cf1b01SMiklos Vajna         if (sFilterOptions.startsWith("{"))
192c2cf1b01SMiklos Vajna         {
193c2cf1b01SMiklos Vajna             std::vector<beans::PropertyValue> aArgsVec
194c2cf1b01SMiklos Vajna                 = comphelper::JsonToPropertyValues(sFilterOptions.toUtf8());
195c2cf1b01SMiklos Vajna             aArgs = comphelper::containerToSequence(aArgsVec);
196c2cf1b01SMiklos Vajna         }
197c2cf1b01SMiklos Vajna 
198ff90a487SAshod Nakashian         SetupFilterOptions(sFilterOptions);
19989667371SMiklos Vajna     }
200037cd13aSMiklos Vajna 
201c2cf1b01SMiklos Vajna     SetupFilterFromPropertyValues(aArgs);
20222d09d65SMiklos Vajna }
20322d09d65SMiklos Vajna 
SetupFilterOptions(std::u16string_view rFilterOptions)2045de24375SNoel Grandin void SwHTMLWriter::SetupFilterOptions(std::u16string_view rFilterOptions)
20522d09d65SMiklos Vajna {
20622d09d65SMiklos Vajna     comphelper::SequenceAsHashMap aStoreMap;
2075de24375SNoel Grandin     if (rFilterOptions.find(u"SkipImages") != std::u16string_view::npos)
20822d09d65SMiklos Vajna     {
20963025350SNoel Grandin         aStoreMap[u"SkipImages"_ustr] <<= true;
21022d09d65SMiklos Vajna     }
2115de24375SNoel Grandin     else if (rFilterOptions.find(u"SkipHeaderFooter") != std::u16string_view::npos)
21222d09d65SMiklos Vajna     {
21363025350SNoel Grandin         aStoreMap[u"SkipHeaderFooter"_ustr] <<= true;
21422d09d65SMiklos Vajna     }
2155de24375SNoel Grandin     else if (rFilterOptions.find(u"EmbedImages") != std::u16string_view::npos)
21622d09d65SMiklos Vajna     {
21763025350SNoel Grandin         aStoreMap[u"EmbedImages"_ustr] <<= true;
21822d09d65SMiklos Vajna     }
21922d09d65SMiklos Vajna 
22022d09d65SMiklos Vajna     // this option can be "on" together with any of above
2215de24375SNoel Grandin     if (rFilterOptions.find(u"NoLineLimit") != std::u16string_view::npos)
22222d09d65SMiklos Vajna     {
22363025350SNoel Grandin         aStoreMap[u"NoLineLimit"_ustr] <<= true;
22422d09d65SMiklos Vajna     }
22522d09d65SMiklos Vajna 
2263f794ed0SSzymon Kłos     // this option can be "on" together with any of above
2273f794ed0SSzymon Kłos     if (rFilterOptions.find(u"NoPrettyPrint") != std::u16string_view::npos)
2283f794ed0SSzymon Kłos     {
22963025350SNoel Grandin         aStoreMap[u"NoPrettyPrint"_ustr] <<= true;
2303f794ed0SSzymon Kłos     }
2313f794ed0SSzymon Kłos 
23222d09d65SMiklos Vajna     const uno::Sequence<OUString> aOptionSeq
23322d09d65SMiklos Vajna         = comphelper::string::convertCommaSeparated(rFilterOptions);
23422d09d65SMiklos Vajna     for (const auto& rOption : aOptionSeq)
23522d09d65SMiklos Vajna     {
23622d09d65SMiklos Vajna         if (rOption == "XHTML")
23722d09d65SMiklos Vajna         {
23863025350SNoel Grandin             aStoreMap[u"XHTML"_ustr] <<= true;
23922d09d65SMiklos Vajna         }
24014ece9f5SMike Kaganski         else if (OUString aNamespace; rOption.startsWith("xhtmlns=", &aNamespace))
24122d09d65SMiklos Vajna         {
24214ece9f5SMike Kaganski             aStoreMap[u"XhtmlNs"_ustr] <<= aNamespace;
24322d09d65SMiklos Vajna         }
24422d09d65SMiklos Vajna     }
24522d09d65SMiklos Vajna 
24622d09d65SMiklos Vajna     SetupFilterFromPropertyValues(aStoreMap.getAsConstPropertyValueList());
24722d09d65SMiklos Vajna }
24822d09d65SMiklos Vajna 
SetupFilterFromPropertyValues(const css::uno::Sequence<css::beans::PropertyValue> & rPropertyValues)24922d09d65SMiklos Vajna void SwHTMLWriter::SetupFilterFromPropertyValues(
25022d09d65SMiklos Vajna     const css::uno::Sequence<css::beans::PropertyValue>& rPropertyValues)
25122d09d65SMiklos Vajna {
25222d09d65SMiklos Vajna     comphelper::SequenceAsHashMap aStoreMap(rPropertyValues);
25363025350SNoel Grandin     auto it = aStoreMap.find(u"RTFOLEMimeType"_ustr);
254e1546b79SMiklos Vajna     if (it != aStoreMap.end())
255037cd13aSMiklos Vajna     {
256e1546b79SMiklos Vajna         it->second >>= m_aRTFOLEMimeType;
257037cd13aSMiklos Vajna     }
258037cd13aSMiklos Vajna 
25963025350SNoel Grandin     it = aStoreMap.find(u"ExportImagesAsOLE"_ustr);
260e1546b79SMiklos Vajna     if (it != aStoreMap.end())
261e1546b79SMiklos Vajna     {
262e1546b79SMiklos Vajna         it->second >>= m_bExportImagesAsOLE;
263e1546b79SMiklos Vajna     }
26404716690SMiklos Vajna 
26563025350SNoel Grandin     it = aStoreMap.find(u"ExportFormulasAsPDF"_ustr);
2662ecd5da5SMike Kaganski     if (it != aStoreMap.end())
2672ecd5da5SMike Kaganski     {
2682ecd5da5SMike Kaganski         it->second >>= m_bExportFormulasAsPDF;
2692ecd5da5SMike Kaganski     }
2702ecd5da5SMike Kaganski 
27163025350SNoel Grandin     it = aStoreMap.find(u"ShapeDPI"_ustr);
27204716690SMiklos Vajna     if (it != aStoreMap.end())
27304716690SMiklos Vajna     {
27404716690SMiklos Vajna         sal_Int32 nVal{};
27504716690SMiklos Vajna         it->second >>= nVal;
27604716690SMiklos Vajna         m_nShapeDPI.emplace(nVal);
27704716690SMiklos Vajna     }
27822d09d65SMiklos Vajna 
27963025350SNoel Grandin     it = aStoreMap.find(u"SkipImages"_ustr);
28022d09d65SMiklos Vajna     if (it != aStoreMap.end())
28122d09d65SMiklos Vajna     {
28222d09d65SMiklos Vajna         bool bVal{};
28322d09d65SMiklos Vajna         it->second >>= bVal;
28422d09d65SMiklos Vajna         mbSkipImages = bVal;
285ff90a487SAshod Nakashian     }
286ff90a487SAshod Nakashian 
28763025350SNoel Grandin     it = aStoreMap.find(u"SkipHeaderFooter"_ustr);
28822d09d65SMiklos Vajna     if (it != aStoreMap.end())
289ff90a487SAshod Nakashian     {
29022d09d65SMiklos Vajna         bool bVal{};
29122d09d65SMiklos Vajna         it->second >>= bVal;
29222d09d65SMiklos Vajna         mbSkipHeaderFooter = bVal;
29346fa816aSOliver Specht     }
2949df0ce08SMiklos Vajna 
2953f794ed0SSzymon Kłos     // this option can be "on" together with any of above
29663025350SNoel Grandin     it = aStoreMap.find(u"NoPrettyPrint"_ustr);
2973f794ed0SSzymon Kłos     if (it != aStoreMap.end())
2983f794ed0SSzymon Kłos     {
2993f794ed0SSzymon Kłos         m_nWishLineLen = -1;
3003f794ed0SSzymon Kłos         m_bPrettyPrint = false;
3013f794ed0SSzymon Kłos     }
3023f794ed0SSzymon Kłos 
30363025350SNoel Grandin     it = aStoreMap.find(u"EmbedImages"_ustr);
30422d09d65SMiklos Vajna     if (it != aStoreMap.end())
30522d09d65SMiklos Vajna     {
30622d09d65SMiklos Vajna         bool bVal{};
30722d09d65SMiklos Vajna         it->second >>= bVal;
30822d09d65SMiklos Vajna         mbEmbedImages = bVal;
30922d09d65SMiklos Vajna     }
31022d09d65SMiklos Vajna 
31163025350SNoel Grandin     it = aStoreMap.find(u"NoLineLimit"_ustr);
31222d09d65SMiklos Vajna     if (it != aStoreMap.end())
31322d09d65SMiklos Vajna     {
31422d09d65SMiklos Vajna         bool bVal{};
31522d09d65SMiklos Vajna         it->second >>= bVal;
31622d09d65SMiklos Vajna         if (bVal)
3174dab08d7SSzymon Kłos         {
3184dab08d7SSzymon Kłos             m_nWishLineLen = -1;
3194dab08d7SSzymon Kłos         }
32022d09d65SMiklos Vajna     }
3214dab08d7SSzymon Kłos 
32263025350SNoel Grandin     it = aStoreMap.find(u"XHTML"_ustr);
32322d09d65SMiklos Vajna     if (it != aStoreMap.end())
3249df0ce08SMiklos Vajna     {
32522d09d65SMiklos Vajna         bool bVal{};
32622d09d65SMiklos Vajna         it->second >>= bVal;
32722d09d65SMiklos Vajna         mbXHTML = bVal;
32822d09d65SMiklos Vajna     }
32922d09d65SMiklos Vajna 
33063025350SNoel Grandin     it = aStoreMap.find(u"XhtmlNs"_ustr);
33122d09d65SMiklos Vajna     if (it != aStoreMap.end())
332eb104959SMiklos Vajna     {
33322d09d65SMiklos Vajna         OUString aVal;
33422d09d65SMiklos Vajna         it->second >>= aVal;
33522d09d65SMiklos Vajna 
33622d09d65SMiklos Vajna         maNamespace = aVal.toUtf8();
337eb104959SMiklos Vajna         if (maNamespace == "reqif-xhtml")
3387a644e36SMiklos Vajna         {
3397a644e36SMiklos Vajna             mbReqIF = true;
340eb104959SMiklos Vajna             // XHTML is always just a fragment inside ReqIF.
341eb104959SMiklos Vajna             mbSkipHeaderFooter = true;
3427a644e36SMiklos Vajna         }
343*edaa5c60SMike Kaganski         if (!maNamespace.isEmpty())
344*edaa5c60SMike Kaganski             maNamespace += ":";
345a1aa7cfeSMiklos Vajna         // XHTML namespace implies XHTML.
346a1aa7cfeSMiklos Vajna         mbXHTML = true;
347eb104959SMiklos Vajna     }
348505f5db5SMiklos Vajna 
34963025350SNoel Grandin     it = aStoreMap.find(u"LeadingTabWidth"_ustr);
350505f5db5SMiklos Vajna     if (it != aStoreMap.end())
351505f5db5SMiklos Vajna     {
352505f5db5SMiklos Vajna         sal_Int32 nVal{};
353505f5db5SMiklos Vajna         it->second >>= nVal;
354505f5db5SMiklos Vajna         m_nLeadingTabWidth.emplace(nVal);
355505f5db5SMiklos Vajna     }
356926826e4SMike Kaganski 
35763025350SNoel Grandin     it = aStoreMap.find(u"PreserveSpaces"_ustr);
358926826e4SMike Kaganski     if (it != aStoreMap.end())
359926826e4SMike Kaganski     {
360926826e4SMike Kaganski         // Paragraphs with leading/trailing/repeated whitespace will have "white-space: pre-wrap"
361926826e4SMike Kaganski         // style; whitespace in content will not be altered (except for "LeadingTabWidth" effects)
362926826e4SMike Kaganski         bool bVal = false;
363926826e4SMike Kaganski         it->second >>= bVal;
364926826e4SMike Kaganski         m_bPreserveSpacesOnWrite = bVal;
365926826e4SMike Kaganski     }
3664be345abSMike Kaganski 
3674be345abSMike Kaganski     it = aStoreMap.find(u"RelativeOwnObjectURL"_ustr);
3684be345abSMike Kaganski     if (it != aStoreMap.end())
3694be345abSMike Kaganski     {
3704be345abSMike Kaganski         // URLs for images / objects created by export (from the document information) will be
3714be345abSMike Kaganski         // relative, regardless of org.openoffice.Office.Common/Save/URL/Internet and
3724be345abSMike Kaganski         // org.openoffice.Office.Common/Save/URL/FileSystem settings
3734be345abSMike Kaganski         bool bVal = false;
3744be345abSMike Kaganski         it->second >>= bVal;
3754be345abSMike Kaganski         m_bRelativeURLsForOwnObjects = bVal;
3764be345abSMike Kaganski     }
3779df0ce08SMiklos Vajna }
3784aec6c9eSTomaž Vajngerl 
WriteStream()37952863266SNoel Grandin ErrCode SwHTMLWriter::WriteStream()
3807b0b5cdfSJens-Heiner Rechtien {
3812ca32d29SMike Kaganski     SwModule* mod = SwModule::get();
3822ca32d29SMike Kaganski     if (!mod)
383415e250eSMike Kaganski         return ERRCODE_ABORT;
384af69f27eSMiklos Vajna     // Intercept paste output if requested.
385af69f27eSMiklos Vajna     char* pPasteEnv = getenv("SW_DEBUG_HTML_PASTE_TO");
386af69f27eSMiklos Vajna     std::unique_ptr<SvStream> pPasteStream;
387af69f27eSMiklos Vajna     SvStream* pOldPasteStream = nullptr;
388af69f27eSMiklos Vajna     if (pPasteEnv)
389af69f27eSMiklos Vajna     {
390af69f27eSMiklos Vajna         OUString aPasteStr;
39130c0134cSMike Kaganski         if (osl::FileBase::getFileURLFromSystemPath(OUString::fromUtf8(pPasteEnv), aPasteStr)
392af69f27eSMiklos Vajna                    == osl::FileBase::E_None)
393af69f27eSMiklos Vajna         {
394af69f27eSMiklos Vajna             pPasteStream.reset(new SvFileStream(aPasteStr, StreamMode::WRITE));
395af69f27eSMiklos Vajna             pOldPasteStream = &Strm();
396af69f27eSMiklos Vajna             SetStream(pPasteStream.get());
397af69f27eSMiklos Vajna         }
398af69f27eSMiklos Vajna     }
399af69f27eSMiklos Vajna     comphelper::ScopeGuard g([this, pOldPasteStream] { this->SetStream(pOldPasteStream); });
400af69f27eSMiklos Vajna 
401af04f766STomaž Vajngerl     // font heights 1-7
402da9bba7cSNoel Grandin     m_aFontHeights[0] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_1::get() * 20;
403da9bba7cSNoel Grandin     m_aFontHeights[1] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_2::get() * 20;
404da9bba7cSNoel Grandin     m_aFontHeights[2] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_3::get() * 20;
405da9bba7cSNoel Grandin     m_aFontHeights[3] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_4::get() * 20;
406da9bba7cSNoel Grandin     m_aFontHeights[4] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_5::get() * 20;
407da9bba7cSNoel Grandin     m_aFontHeights[5] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_6::get() * 20;
408da9bba7cSNoel Grandin     m_aFontHeights[6] = officecfg::Office::Common::Filter::HTML::Import::FontSize::Size_7::get() * 20;
4097b0b5cdfSJens-Heiner Rechtien 
410c2511f27SJens Carl     // output styles anyway
411d05b2b91SAndrea Gelmini     // (then also top and bottom paragraph spacing)
412da9bba7cSNoel Grandin     m_nExportMode = SvxHtmlOptions::GetExportMode();
41301b49802SStephan Bergmann     m_nHTMLMode = GetHtmlMode(nullptr);
414af04f766STomaž Vajngerl 
415b46496c4SMiklos Vajna     if( HTML_CFG_WRITER == m_nExportMode || HTML_CFG_NS40 == m_nExportMode )
416b46496c4SMiklos Vajna         m_nHTMLMode |= HTMLMODE_BLOCK_SPACER;
4177b0b5cdfSJens-Heiner Rechtien 
418b46496c4SMiklos Vajna     if( HTML_CFG_WRITER == m_nExportMode || HTML_CFG_MSIE == m_nExportMode )
419696689c1SNoel Grandin         m_nHTMLMode |= (HTMLMODE_FLOAT_FRAME | HTMLMODE_LSPACE_IN_NUMBER_BULLET);
4207b0b5cdfSJens-Heiner Rechtien 
421b46496c4SMiklos Vajna     if( HTML_CFG_MSIE == m_nExportMode )
422b46496c4SMiklos Vajna         m_nHTMLMode |= HTMLMODE_NBSP_IN_TABLES;
4237b0b5cdfSJens-Heiner Rechtien 
424622e49a2SMike Kaganski     // For all three of HTML_CFG_WRITER, HTML_CFG_NS40, HTML_CFG_MSIE
425b46496c4SMiklos Vajna     m_nHTMLMode |= HTMLMODE_ABS_POS_FLY | HTMLMODE_ABS_POS_DRAW;
4267b0b5cdfSJens-Heiner Rechtien 
427b46496c4SMiklos Vajna     if( HTML_CFG_WRITER == m_nExportMode )
428b46496c4SMiklos Vajna         m_nHTMLMode |= HTMLMODE_FLY_MARGINS;
4297b0b5cdfSJens-Heiner Rechtien 
430b46496c4SMiklos Vajna     if( HTML_CFG_NS40 == m_nExportMode )
431b46496c4SMiklos Vajna         m_nHTMLMode |= HTMLMODE_BORDER_NONE;
4327b0b5cdfSJens-Heiner Rechtien 
433b46496c4SMiklos Vajna     m_nHTMLMode |= HTMLMODE_FONT_GENERIC;
4347b0b5cdfSJens-Heiner Rechtien 
435b46496c4SMiklos Vajna     if( HTML_CFG_NS40==m_nExportMode )
436b46496c4SMiklos Vajna         m_nHTMLMode |= HTMLMODE_NO_CONTROL_CENTERING;
4377b0b5cdfSJens-Heiner Rechtien 
438b46496c4SMiklos Vajna     m_bCfgOutStyles = IsHTMLMode(HTMLMODE_SOME_STYLES | HTMLMODE_FULL_STYLES);
439b46496c4SMiklos Vajna     m_bCfgNetscape4 = (HTML_CFG_NS40 == m_nExportMode);
4407b0b5cdfSJens-Heiner Rechtien 
4417b0b5cdfSJens-Heiner Rechtien     if( IsHTMLMode(HTMLMODE_SOME_STYLES | HTMLMODE_FULL_STYLES) )
442b46496c4SMiklos Vajna         m_nHTMLMode |= HTMLMODE_PRINT_EXT;
4437b0b5cdfSJens-Heiner Rechtien 
4442ca32d29SMike Kaganski     m_eCSS1Unit = mod->GetMetric( m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) );
4457b0b5cdfSJens-Heiner Rechtien 
446c2511f27SJens Carl     // Only for the MS-IE we favour the export of styles.
447b46496c4SMiklos Vajna     m_bCfgPreferStyles = HTML_CFG_MSIE == m_nExportMode;
4487b0b5cdfSJens-Heiner Rechtien 
449da9bba7cSNoel Grandin     m_bCfgStarBasic = officecfg::Office::Common::Filter::HTML::Export::Basic::get();
4507b0b5cdfSJens-Heiner Rechtien 
451b46496c4SMiklos Vajna     m_bCfgFormFeed = !IsHTMLMode(HTMLMODE_PRINT_EXT);
452da9bba7cSNoel Grandin     m_bCfgCpyLinkedGrfs = officecfg::Office::Common::Filter::HTML::Export::LocalGraphic::get();
4537b0b5cdfSJens-Heiner Rechtien 
45408d74d89SGabor Kelemen     m_bCfgPrintLayout = officecfg::Office::Common::Filter::HTML::Export::PrintLayout::get();
4553e17677fSLászló Németh 
456c2511f27SJens Carl     // get HTML template
4576aa35db3SNoel Grandin     bool bOldHTMLMode = false;
458f26097c0SMatteo Casalin     SwTextFormatColls::size_type nOldTextFormatCollCnt = 0;
459f26097c0SMatteo Casalin     SwCharFormats::size_type nOldCharFormatCnt = 0;
4607b0b5cdfSJens-Heiner Rechtien 
461c2511f27SJens Carl     OSL_ENSURE( !m_xTemplate.is(), "Where is the HTML template coming from?" );
462266e58d2SMiklos Vajna     m_xTemplate = static_cast<HTMLReader*>(ReadHTML)->GetTemplateDoc(*m_pDoc);
46382f9573bSNoel Grandin     if( m_xTemplate.is() )
4647b0b5cdfSJens-Heiner Rechtien     {
46582f9573bSNoel Grandin         bOldHTMLMode = m_xTemplate->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE);
46682f9573bSNoel Grandin         m_xTemplate->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, true);
4677b0b5cdfSJens-Heiner Rechtien 
46882f9573bSNoel Grandin         nOldTextFormatCollCnt = m_xTemplate->GetTextFormatColls()->size();
46982f9573bSNoel Grandin         nOldCharFormatCnt = m_xTemplate->GetCharFormats()->size();
4707b0b5cdfSJens-Heiner Rechtien     }
4717b0b5cdfSJens-Heiner Rechtien 
472266e58d2SMiklos Vajna     if( m_bShowProgress )
4735f9ffc31SNoel Grandin         ::StartProgress( STR_STATSTR_W4WWRITE, 0, sal_Int32(m_pDoc->GetNodes().Count()),
474266e58d2SMiklos Vajna                          m_pDoc->GetDocShell());
4757b0b5cdfSJens-Heiner Rechtien 
476dba5dccfSNoel Grandin     m_xDfltColor.reset();
47766438a0aSNoel Grandin     m_xFootEndNotes.reset();
47801b49802SStephan Bergmann     m_pFormatFootnote = nullptr;
479b46496c4SMiklos Vajna     m_bOutTable = m_bOutHeader = m_bOutFooter = m_bOutFlyFrame = false;
480e25669fcSNoel Grandin     mxFormComps.clear();
481b46496c4SMiklos Vajna     m_nFormCntrlCnt = 0;
482b46496c4SMiklos Vajna     m_bPreserveForm = false;
483b46496c4SMiklos Vajna     m_bClearLeft = m_bClearRight = false;
484b46496c4SMiklos Vajna     m_bLFPossible = false;
485926826e4SMike Kaganski     m_bSpacePreserve = false;
4867b0b5cdfSJens-Heiner Rechtien 
487b46496c4SMiklos Vajna     m_nLeftMargin = m_nDfltLeftMargin = m_nDfltRightMargin = 0;
488b46496c4SMiklos Vajna     m_nDfltTopMargin = m_nDfltBottomMargin = 0;
489b46496c4SMiklos Vajna     m_nFirstLineIndent = m_nDfltFirstLineIndent = 0;
490b46496c4SMiklos Vajna     m_bFirstCSS1Property = m_bFirstCSS1Rule = false;
491b46496c4SMiklos Vajna     m_bCSS1IgnoreFirstPageDesc = false;
492b46496c4SMiklos Vajna     m_nIndentLvl = 0;
493b46496c4SMiklos Vajna     m_nLastLFPos = 0;
494b46496c4SMiklos Vajna     m_nDefListLvl = 0;
495266e58d2SMiklos Vajna     m_nDefListMargin = ((m_xTemplate.is() && !m_bCfgOutStyles) ? m_xTemplate.get() : m_pDoc)
4967e4f4a0cSJonathan Clark                            ->getIDocumentStylePoolAccess()
4977e4f4a0cSJonathan Clark                            .GetTextCollFromPool(RES_POOLCOLL_HTML_DD, false)
4987e4f4a0cSJonathan Clark                            ->GetTextLeftMargin()
4997e4f4a0cSJonathan Clark                            .ResolveTextLeft({});
500b46496c4SMiklos Vajna     m_nHeaderFooterSpace = 0;
501b46496c4SMiklos Vajna     m_nTextAttrsToIgnore = 0;
502b46496c4SMiklos Vajna     m_nCSS1OutMode = 0;
503a7b7c64aSNoel Grandin     SvtScriptType nScript = SvtLanguageOptions::GetScriptTypeOfLanguage( GetAppLanguage() );
504b786f456SMichael Brauer     switch( nScript )
505b786f456SMichael Brauer     {
506a7b7c64aSNoel Grandin     case SvtScriptType::ASIAN:
507b46496c4SMiklos Vajna         m_nCSS1Script = CSS1_OUTMODE_CJK;
508b786f456SMichael Brauer         break;
509a7b7c64aSNoel Grandin     case SvtScriptType::COMPLEX:
510b46496c4SMiklos Vajna         m_nCSS1Script = CSS1_OUTMODE_CTL;
511b786f456SMichael Brauer         break;
512b786f456SMichael Brauer     default:
513b46496c4SMiklos Vajna         m_nCSS1Script = CSS1_OUTMODE_WESTERN;
514b786f456SMichael Brauer         break;
515b786f456SMichael Brauer     }
516ae095608SNoel Grandin     const SvxLanguageItem& rLangitem = m_pDoc->GetDefault(GetLangWhichIdFromScript(m_nCSS1Script));
517ae095608SNoel Grandin     m_eLang = rLangitem.GetLanguage();
51897075a38SMichael Brauer 
519b46496c4SMiklos Vajna     m_nFootNote = m_nEndNote = 0;
5207b0b5cdfSJens-Heiner Rechtien 
521a6aa57ffSNoel Grandin     m_nWarn = ERRCODE_NONE;
5227b0b5cdfSJens-Heiner Rechtien     GetNumInfo().Clear();
52301b49802SStephan Bergmann     m_pNextNumRuleInfo = nullptr;
5247b0b5cdfSJens-Heiner Rechtien 
5251946794aSLuboš Luňák     OString aStartTags;
5267b0b5cdfSJens-Heiner Rechtien 
527c24aa380SMarc Bessières     // respect table and section at document beginning
5287b0b5cdfSJens-Heiner Rechtien     {
529094fc93dSMike Kaganski         if (m_bWriteAll)
530094fc93dSMike Kaganski         {
531094fc93dSMike Kaganski             while (const SwStartNode* pTNd = m_pCurrentPam->GetPointNode().FindTableBoxStartNode())
5327b0b5cdfSJens-Heiner Rechtien             {
533c2511f27SJens Carl                 // start with table node !!
534094fc93dSMike Kaganski                 m_pCurrentPam->GetPoint()->Assign(*pTNd->FindTableNode());
5357b0b5cdfSJens-Heiner Rechtien 
536266e58d2SMiklos Vajna                 if (m_bWriteOnlyFirstTable)
537094fc93dSMike Kaganski                     m_pCurrentPam->GetMark()->Assign(
538094fc93dSMike Kaganski                         *m_pCurrentPam->GetPointNode().EndOfSectionNode());
539094fc93dSMike Kaganski             }
5407b0b5cdfSJens-Heiner Rechtien         }
5417b0b5cdfSJens-Heiner Rechtien 
542094fc93dSMike Kaganski         // first node (which can contain a page break)
54325a299a8SNoel Grandin         m_pStartNdIdx = new SwNodeIndex( m_pCurrentPam->GetPoint()->GetNode() );
5447b0b5cdfSJens-Heiner Rechtien 
545ab0d9af9SNoel Grandin         SwSectionNode * pSNd = m_pCurrentPam->GetPointNode().FindSectionNode();
5467b0b5cdfSJens-Heiner Rechtien         while( pSNd )
5477b0b5cdfSJens-Heiner Rechtien         {
548266e58d2SMiklos Vajna             if( m_bWriteAll )
5497b0b5cdfSJens-Heiner Rechtien             {
550c2511f27SJens Carl                 // start with section node !!
5510df94183SNoel Grandin                 m_pCurrentPam->GetPoint()->Assign(*pSNd);
5527b0b5cdfSJens-Heiner Rechtien             }
5537b0b5cdfSJens-Heiner Rechtien             else
5547b0b5cdfSJens-Heiner Rechtien             {
555f26621d4SNoel Grandin                 OSL_ENSURE( SectionType::FileLink != pSNd->GetSection().GetType(),
556c2511f27SJens Carl                         "Export linked areas at document beginning is not implemented" );
5577b0b5cdfSJens-Heiner Rechtien 
558c2511f27SJens Carl                 // save only the tag of section
5591946794aSLuboš Luňák                 OString aName = HTMLOutFuncs::ConvertStringToHTML(
560ac3b217aSNoel Grandin                     pSNd->GetSection().GetSectionName().toString() );
5617b0b5cdfSJens-Heiner Rechtien 
5624a96fb8eSNoel Grandin                 aStartTags =
563186ef501SMiklos Vajna                     "<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_division
5644a96fb8eSNoel Grandin                     " " OOO_STRING_SVTOOLS_HTML_O_id
5654a96fb8eSNoel Grandin                     "=\"" + aName + "\">" +
5664a96fb8eSNoel Grandin                     aStartTags;
5677b0b5cdfSJens-Heiner Rechtien             }
568c2511f27SJens Carl             // FindSectionNode() on a SectionNode return the same!
56977fb2279SJens-Heiner Rechtien             pSNd = pSNd->StartOfSectionNode()->FindSectionNode();
5707b0b5cdfSJens-Heiner Rechtien         }
5717b0b5cdfSJens-Heiner Rechtien     }
5727b0b5cdfSJens-Heiner Rechtien 
573c2511f27SJens Carl     // create table of the floating frames, but only when the whole
574c2511f27SJens Carl     // document is saved
575eaf0b96eSNoel Grandin     m_aHTMLPosFlyFrames.clear();
57649c2b980SRobinson Tryon     CollectFlyFrames();
57757f1934bSNoel Grandin     m_nLastParaToken = HtmlTokenId::NONE;
5782f9c1990SMike Kaganski 
5795b250edaSCaolán McNamara     if (mbReqIF && !m_bWriteAll
5802f9c1990SMike Kaganski         && *m_pCurrentPam->GetPoint() == *m_pCurrentPam->GetMark()
5812f9c1990SMike Kaganski         && m_pCurrentPam->GetPoint()->GetNode().IsOLENode() && m_aHTMLPosFlyFrames.size() == 1)
5822f9c1990SMike Kaganski     {
5832f9c1990SMike Kaganski         // A single OLE object selection must be output: do it directly (without replacement)
5842f9c1990SMike Kaganski         OutHTML_FrameFormatOLENodeGrf(*this, m_aHTMLPosFlyFrames[0]->GetFormat(), true, false);
5852f9c1990SMike Kaganski     }
5862f9c1990SMike Kaganski     else
5872f9c1990SMike Kaganski     {
5887b0b5cdfSJens-Heiner Rechtien         GetControls();
5897b0b5cdfSJens-Heiner Rechtien         CollectLinkTargets();
5907b0b5cdfSJens-Heiner Rechtien 
5917b0b5cdfSJens-Heiner Rechtien         sal_uInt16 nHeaderAttrs = 0;
5921da7d73eSTomaž Vajngerl         m_pCurrPageDesc = MakeHeader( nHeaderAttrs );
5937b0b5cdfSJens-Heiner Rechtien 
594926826e4SMike Kaganski         SetLFPossible(true);
5957b0b5cdfSJens-Heiner Rechtien 
596c2511f27SJens Carl         // output forms which contain only HiddenControls
5977b0b5cdfSJens-Heiner Rechtien         OutHiddenForms();
5987b0b5cdfSJens-Heiner Rechtien 
59979dc19fcSCaolán McNamara         if( !aStartTags.isEmpty() )
600241bee7eSNoel Grandin             Strm().WriteOString( aStartTags );
6017b0b5cdfSJens-Heiner Rechtien 
60204e32513SNoel Grandin         const SwFormatHeader *pFormatHeader;
603b46496c4SMiklos Vajna         const SfxItemSet& rPageItemSet = m_pCurrPageDesc->GetMaster().GetAttrSet();
604266e58d2SMiklos Vajna         if( !m_bWriteClipboardDoc && m_pDoc->GetDocShell() &&
605266e58d2SMiklos Vajna              (!m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) &&
606266e58d2SMiklos Vajna               !m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE)) &&
60704e32513SNoel Grandin             (pFormatHeader = rPageItemSet.GetItemIfSet( RES_HEADER )) )
6087b0b5cdfSJens-Heiner Rechtien         {
60904e32513SNoel Grandin             const SwFrameFormat *pHeaderFormat = pFormatHeader->GetHeaderFormat();
610ab465b90SChristian Lohmaier             if( pHeaderFormat )
611ab465b90SChristian Lohmaier                 OutHTML_HeaderFooter( *this, *pHeaderFormat, true );
6127b0b5cdfSJens-Heiner Rechtien         }
6137b0b5cdfSJens-Heiner Rechtien 
614b46496c4SMiklos Vajna         m_nTextAttrsToIgnore = nHeaderAttrs;
615266e58d2SMiklos Vajna         Out_SwDoc( m_pOrigPam );
616b46496c4SMiklos Vajna         m_nTextAttrsToIgnore = 0;
6177b0b5cdfSJens-Heiner Rechtien 
618e25669fcSNoel Grandin         if( mxFormComps.is() )
619e25669fcSNoel Grandin             OutForm( false, mxFormComps );
6207b0b5cdfSJens-Heiner Rechtien 
62166438a0aSNoel Grandin         if( m_xFootEndNotes )
6227b0b5cdfSJens-Heiner Rechtien             OutFootEndNotes();
6237b0b5cdfSJens-Heiner Rechtien 
62404e32513SNoel Grandin         const SwFormatFooter* pFormatFooter;
625266e58d2SMiklos Vajna         if( !m_bWriteClipboardDoc && m_pDoc->GetDocShell() &&
626266e58d2SMiklos Vajna             (!m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && !m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE))  &&
62704e32513SNoel Grandin             (pFormatFooter = rPageItemSet.GetItemIfSet( RES_FOOTER )) )
6287b0b5cdfSJens-Heiner Rechtien         {
62904e32513SNoel Grandin             const SwFrameFormat *pFooterFormat = pFormatFooter->GetFooterFormat();
630ab465b90SChristian Lohmaier             if( pFooterFormat )
631ab465b90SChristian Lohmaier                 OutHTML_HeaderFooter( *this, *pFooterFormat, false );
6327b0b5cdfSJens-Heiner Rechtien         }
6337b0b5cdfSJens-Heiner Rechtien 
634926826e4SMike Kaganski         if (IsLFPossible())
6357b0b5cdfSJens-Heiner Rechtien             OutNewLine();
6368760b2b0SMiklos Vajna         if (!mbSkipHeaderFooter)
6378760b2b0SMiklos Vajna         {
6383d236177SMike Kaganski             HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_body), false );
6397b0b5cdfSJens-Heiner Rechtien             OutNewLine();
6403d236177SMike Kaganski             HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_html), false );
6418760b2b0SMiklos Vajna         }
642f74d9ba2SMiklos Vajna         else if (mbReqIF)
643f74d9ba2SMiklos Vajna             // ReqIF: end xhtml.BlkStruct.class.
6443d236177SMike Kaganski             HTMLOutFuncs::Out_AsciiTag(Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false);
6452f9c1990SMike Kaganski     }
646c2511f27SJens Carl     // delete the table with floating frames
647eaf0b96eSNoel Grandin     OSL_ENSURE( m_aHTMLPosFlyFrames.empty(), "Were not all frames output?" );
648eaf0b96eSNoel Grandin     m_aHTMLPosFlyFrames.clear();
6497b0b5cdfSJens-Heiner Rechtien 
65070b125c6SNoel Grandin     m_aHTMLControls.clear();
6517b0b5cdfSJens-Heiner Rechtien 
65227825a35SMichael Stahl     m_CharFormatInfos.clear();
65327825a35SMichael Stahl     m_TextCollInfos.clear();
654b46496c4SMiklos Vajna     m_aImgMapNames.clear();
655b46496c4SMiklos Vajna     m_aImplicitMarks.clear();
656b46496c4SMiklos Vajna     m_aOutlineMarks.clear();
657b46496c4SMiklos Vajna     m_aOutlineMarkPoss.clear();
658b46496c4SMiklos Vajna     m_aNumRuleNames.clear();
659b46496c4SMiklos Vajna     m_aScriptParaStyles.clear();
660b46496c4SMiklos Vajna     m_aScriptTextStyles.clear();
661b786f456SMichael Brauer 
662dba5dccfSNoel Grandin     m_xDfltColor.reset();
6637b0b5cdfSJens-Heiner Rechtien 
664b46496c4SMiklos Vajna     delete m_pStartNdIdx;
66501b49802SStephan Bergmann     m_pStartNdIdx = nullptr;
6667b0b5cdfSJens-Heiner Rechtien 
667e25669fcSNoel Grandin     mxFormComps.clear();
6687b0b5cdfSJens-Heiner Rechtien 
66966438a0aSNoel Grandin     OSL_ENSURE( !m_xFootEndNotes,
670c2511f27SJens Carl             "SwHTMLWriter::Write: Footnotes not deleted by OutFootEndNotes" );
6717b0b5cdfSJens-Heiner Rechtien 
67201b49802SStephan Bergmann     m_pCurrPageDesc = nullptr;
6737b0b5cdfSJens-Heiner Rechtien 
6747b0b5cdfSJens-Heiner Rechtien     ClearNextNumInfo();
6757b0b5cdfSJens-Heiner Rechtien 
676b415494bSNoel Grandin     for(OUString & s : m_aBulletGrfs)
677b415494bSNoel Grandin         s.clear();
6787b0b5cdfSJens-Heiner Rechtien 
679266e58d2SMiklos Vajna     if( m_bShowProgress )
680266e58d2SMiklos Vajna         ::EndProgress( m_pDoc->GetDocShell() );
6817b0b5cdfSJens-Heiner Rechtien 
68282f9573bSNoel Grandin     if( m_xTemplate.is() )
6837b0b5cdfSJens-Heiner Rechtien     {
684c2511f27SJens Carl         // delete character and paragraph templates created during export
68582f9573bSNoel Grandin         auto nTextFormatCollCnt = m_xTemplate->GetTextFormatColls()->size();
686ab465b90SChristian Lohmaier         while( nTextFormatCollCnt > nOldTextFormatCollCnt )
68782f9573bSNoel Grandin             m_xTemplate->DelTextFormatColl( --nTextFormatCollCnt );
68882f9573bSNoel Grandin         OSL_ENSURE( m_xTemplate->GetTextFormatColls()->size() == nOldTextFormatCollCnt,
689c2511f27SJens Carl                 "wrong number of TextFormatColls deleted" );
6907b0b5cdfSJens-Heiner Rechtien 
69182f9573bSNoel Grandin         auto nCharFormatCnt = m_xTemplate->GetCharFormats()->size();
692ab465b90SChristian Lohmaier         while( nCharFormatCnt > nOldCharFormatCnt )
69382f9573bSNoel Grandin             m_xTemplate->DelCharFormat( --nCharFormatCnt );
69482f9573bSNoel Grandin         OSL_ENSURE( m_xTemplate->GetCharFormats()->size() == nOldCharFormatCnt,
695c2511f27SJens Carl                 "wrong number of CharFormats deleted" );
6967b0b5cdfSJens-Heiner Rechtien 
697c2511f27SJens Carl         // restore HTML mode
69882f9573bSNoel Grandin         m_xTemplate->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, bOldHTMLMode);
6997b0b5cdfSJens-Heiner Rechtien 
70082f9573bSNoel Grandin         m_xTemplate.clear();
7017b0b5cdfSJens-Heiner Rechtien     }
7027b0b5cdfSJens-Heiner Rechtien 
703b46496c4SMiklos Vajna     return m_nWarn;
7047b0b5cdfSJens-Heiner Rechtien }
7057b0b5cdfSJens-Heiner Rechtien 
lcl_html_GetFormatCol(const SwSection & rSection,const SwSectionFormat & rFormat)706ab465b90SChristian Lohmaier static const SwFormatCol *lcl_html_GetFormatCol( const SwSection& rSection,
707ab465b90SChristian Lohmaier                                        const SwSectionFormat& rFormat )
7087b0b5cdfSJens-Heiner Rechtien {
70904e32513SNoel Grandin     if( SectionType::FileLink == rSection.GetType() )
71004e32513SNoel Grandin         return nullptr;
7117b0b5cdfSJens-Heiner Rechtien 
71204e32513SNoel Grandin     const SwFormatCol *pCol = rFormat.GetAttrSet().GetItemIfSet(RES_COL,false);
71304e32513SNoel Grandin     if (pCol->GetNumCols() > 1 )
7147b0b5cdfSJens-Heiner Rechtien         return pCol;
71504e32513SNoel Grandin 
71604e32513SNoel Grandin     return nullptr;
7177b0b5cdfSJens-Heiner Rechtien }
7187b0b5cdfSJens-Heiner Rechtien 
lcl_html_IsMultiColStart(const SwHTMLWriter & rHTMLWrt,SwNodeOffset nIndex)7195f9ffc31SNoel Grandin static bool lcl_html_IsMultiColStart( const SwHTMLWriter& rHTMLWrt, SwNodeOffset nIndex )
7207b0b5cdfSJens-Heiner Rechtien {
721ac0f9d32STakeshi Abe     bool bRet = false;
7227b0b5cdfSJens-Heiner Rechtien     const SwSectionNode *pSectNd =
723266e58d2SMiklos Vajna         rHTMLWrt.m_pDoc->GetNodes()[nIndex]->GetSectionNode();
7247b0b5cdfSJens-Heiner Rechtien     if( pSectNd )
7257b0b5cdfSJens-Heiner Rechtien     {
7267b0b5cdfSJens-Heiner Rechtien         const SwSection& rSection = pSectNd->GetSection();
727ab465b90SChristian Lohmaier         const SwSectionFormat *pFormat = rSection.GetFormat();
728ab465b90SChristian Lohmaier         if( pFormat && lcl_html_GetFormatCol( rSection, *pFormat ) )
729ac0f9d32STakeshi Abe             bRet = true;
7307b0b5cdfSJens-Heiner Rechtien     }
7317b0b5cdfSJens-Heiner Rechtien 
7327b0b5cdfSJens-Heiner Rechtien     return bRet;
7337b0b5cdfSJens-Heiner Rechtien }
7347b0b5cdfSJens-Heiner Rechtien 
lcl_html_IsMultiColEnd(const SwHTMLWriter & rHTMLWrt,SwNodeOffset nIndex)7355f9ffc31SNoel Grandin static bool lcl_html_IsMultiColEnd( const SwHTMLWriter& rHTMLWrt, SwNodeOffset nIndex )
7367b0b5cdfSJens-Heiner Rechtien {
737ac0f9d32STakeshi Abe     bool bRet = false;
738266e58d2SMiklos Vajna     const SwEndNode *pEndNd = rHTMLWrt.m_pDoc->GetNodes()[nIndex]->GetEndNode();
7397b0b5cdfSJens-Heiner Rechtien     if( pEndNd )
7407b0b5cdfSJens-Heiner Rechtien         bRet = lcl_html_IsMultiColStart( rHTMLWrt,
7417b0b5cdfSJens-Heiner Rechtien                                          pEndNd->StartOfSectionIndex() );
7427b0b5cdfSJens-Heiner Rechtien 
7437b0b5cdfSJens-Heiner Rechtien     return bRet;
7447b0b5cdfSJens-Heiner Rechtien }
7457b0b5cdfSJens-Heiner Rechtien 
lcl_html_OutSectionStartTag(SwHTMLWriter & rHTMLWrt,const SwSection & rSection,const SwSectionFormat & rFormat,const SwFormatCol * pCol,bool bContinued=false)74621d10c6fSLuboš Luňák static void lcl_html_OutSectionStartTag( SwHTMLWriter& rHTMLWrt,
7477b0b5cdfSJens-Heiner Rechtien                                      const SwSection& rSection,
748ab465b90SChristian Lohmaier                                      const SwSectionFormat& rFormat,
749ab465b90SChristian Lohmaier                                   const SwFormatCol *pCol,
750ac0f9d32STakeshi Abe                                   bool bContinued=false )
7517b0b5cdfSJens-Heiner Rechtien {
752c16ba8a0SCédric Bosdonnat     OSL_ENSURE( pCol || !bContinued, "Continuation of DIV" );
7537b0b5cdfSJens-Heiner Rechtien 
754926826e4SMike Kaganski     if (rHTMLWrt.IsLFPossible())
7557b0b5cdfSJens-Heiner Rechtien         rHTMLWrt.OutNewLine();
7567b0b5cdfSJens-Heiner Rechtien 
7571f93816dSNoel Grandin     OStringBuffer sOut("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division);
7587b0b5cdfSJens-Heiner Rechtien 
759ac3b217aSNoel Grandin     const UIName& rName = rSection.GetSectionName();
760111c843cSNoel Grandin     if( !rName.isEmpty() && !bContinued )
7617b0b5cdfSJens-Heiner Rechtien     {
7620e54605eSStephan Bergmann         sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_id "=\"");
763c0fec001SNoel Grandin         rHTMLWrt.Strm().WriteOString( sOut );
764c0fec001SNoel Grandin         sOut.setLength(0);
765ac3b217aSNoel Grandin         HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), rName.toString() );
76668a832c7SCaolán McNamara         sOut.append('\"');
7677b0b5cdfSJens-Heiner Rechtien     }
7687b0b5cdfSJens-Heiner Rechtien 
769241bee7eSNoel Grandin     rHTMLWrt.Strm().WriteOString( sOut.makeStringAndClear() );
7703b7c18a5SMiklos Vajna     if (!rHTMLWrt.mbXHTML)
7713b7c18a5SMiklos Vajna     {
7723b7c18a5SMiklos Vajna         SvxFrameDirection nDir = rHTMLWrt.GetHTMLDirection(rFormat.GetAttrSet());
773b13f6ea1SMichael Brauer         rHTMLWrt.OutDirection(nDir);
7743b7c18a5SMiklos Vajna     }
775b13f6ea1SMichael Brauer 
776f26621d4SNoel Grandin     if( SectionType::FileLink == rSection.GetType() )
7777b0b5cdfSJens-Heiner Rechtien     {
7780e54605eSStephan Bergmann         sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_href "=\"");
779c0fec001SNoel Grandin         rHTMLWrt.Strm().WriteOString( sOut );
780c0fec001SNoel Grandin         sOut.setLength(0);
7817b0b5cdfSJens-Heiner Rechtien 
782111c843cSNoel Grandin         const OUString& aFName = rSection.GetLinkFileName();
78325a05cf2SMatteo Casalin         sal_Int32 nIdx{ 0 };
78425a05cf2SMatteo Casalin         OUString aURL( aFName.getToken(0, sfx2::cTokenSeparator, nIdx) );
78525a05cf2SMatteo Casalin         OUString aFilter( aFName.getToken(0, sfx2::cTokenSeparator, nIdx) );
78625a05cf2SMatteo Casalin         OUString aSection( aFName.getToken(0, sfx2::cTokenSeparator, nIdx) );
7877b0b5cdfSJens-Heiner Rechtien 
7884be345abSMike Kaganski         OUString aEncURL(rHTMLWrt.normalizeURL(aURL, false));
789ae0988f8SMichael Brauer         sal_Unicode cDelim = 255U;
790111c843cSNoel Grandin         bool bURLContainsDelim = (-1 != aEncURL.indexOf( cDelim ) );
791ae0988f8SMichael Brauer 
792aeeacd28SMike Kaganski         HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aEncURL );
79340a7abaaSNoel Grandin         const char* const pDelim = "&#255;";
794111c843cSNoel Grandin         if( !aFilter.isEmpty() || !aSection.isEmpty() || bURLContainsDelim )
7955fe96b6dSMike Kaganski             rHTMLWrt.Strm().WriteOString( pDelim );
796111c843cSNoel Grandin         if( !aFilter.isEmpty() )
797aeeacd28SMike Kaganski             HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aFilter );
79828c9207dSCaolán McNamara         if( !aSection.isEmpty() || bURLContainsDelim  )
7995fe96b6dSMike Kaganski                 rHTMLWrt.Strm().WriteOString( pDelim );
80028c9207dSCaolán McNamara         if( !aSection.isEmpty() )
8017b0b5cdfSJens-Heiner Rechtien         {
802de7fced0SJulien Nabet             aSection = aSection.replaceAll(u"%", u"%25");
803de7fced0SJulien Nabet             aSection = aSection.replaceAll(OUStringChar(cDelim), u"%FF");
804aeeacd28SMike Kaganski             HTMLOutFuncs::Out_String( rHTMLWrt.Strm(), aSection );
8057b0b5cdfSJens-Heiner Rechtien         }
80668a832c7SCaolán McNamara         sOut.append('\"');
8077b0b5cdfSJens-Heiner Rechtien     }
8087b0b5cdfSJens-Heiner Rechtien     else if( pCol )
8097b0b5cdfSJens-Heiner Rechtien     {
810da40cac5SAndrea Gelmini         // minimum gutter width
8116aa35db3SNoel Grandin         sal_uInt16 nGutter = pCol->GetGutterWidth( true );
8127b0b5cdfSJens-Heiner Rechtien         if( nGutter!=USHRT_MAX )
8137b0b5cdfSJens-Heiner Rechtien         {
8146d5848ecSMike Kaganski             nGutter = SwHTMLWriter::ToPixel(nGutter);
8150e54605eSStephan Bergmann             sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_gutter "=\"" + OString::number(nGutter) + "\"");
8167b0b5cdfSJens-Heiner Rechtien         }
8177b0b5cdfSJens-Heiner Rechtien     }
8187b0b5cdfSJens-Heiner Rechtien 
819c0fec001SNoel Grandin     rHTMLWrt.Strm().WriteOString( sOut );
820c0fec001SNoel Grandin     sOut.setLength(0);
821b46496c4SMiklos Vajna     if( rHTMLWrt.IsHTMLMode( rHTMLWrt.m_bCfgOutStyles ? HTMLMODE_ON : 0 ) )
822ab465b90SChristian Lohmaier         rHTMLWrt.OutCSS1_SectionFormatOptions( rFormat, pCol );
8237b0b5cdfSJens-Heiner Rechtien 
824d803483fSNoel Grandin     rHTMLWrt.Strm().WriteChar( '>' );
8257b0b5cdfSJens-Heiner Rechtien 
826926826e4SMike Kaganski     rHTMLWrt.SetLFPossible(true);
827111c843cSNoel Grandin     if( !rName.isEmpty() && !bContinued )
828ac3b217aSNoel Grandin         rHTMLWrt.OutImplicitMark( rName.toString(), "region" );
8297b0b5cdfSJens-Heiner Rechtien 
8307b0b5cdfSJens-Heiner Rechtien     rHTMLWrt.IncIndentLevel();
8317b0b5cdfSJens-Heiner Rechtien }
8327b0b5cdfSJens-Heiner Rechtien 
lcl_html_OutSectionEndTag(SwHTMLWriter & rHTMLWrt)83315f8a130SHarri Pitkänen static void lcl_html_OutSectionEndTag( SwHTMLWriter& rHTMLWrt )
8347b0b5cdfSJens-Heiner Rechtien {
8357b0b5cdfSJens-Heiner Rechtien     rHTMLWrt.DecIndentLevel();
836926826e4SMike Kaganski     if (rHTMLWrt.IsLFPossible())
8377b0b5cdfSJens-Heiner Rechtien         rHTMLWrt.OutNewLine();
8383d236177SMike Kaganski     HTMLOutFuncs::Out_AsciiTag( rHTMLWrt.Strm(), Concat2View(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_division), false );
839926826e4SMike Kaganski     rHTMLWrt.SetLFPossible(true);
8407b0b5cdfSJens-Heiner Rechtien }
8417b0b5cdfSJens-Heiner Rechtien 
OutHTML_Section(SwHTMLWriter & rWrt,const SwSectionNode & rSectNd)84260d9e89fSNoel Grandin static SwHTMLWriter& OutHTML_Section( SwHTMLWriter& rWrt, const SwSectionNode& rSectNd )
8437b0b5cdfSJens-Heiner Rechtien {
8447b0b5cdfSJens-Heiner Rechtien     // End <PRE> and any <DL>, because a definition list's level may
8457b0b5cdfSJens-Heiner Rechtien     // change inside the section.
84660d9e89fSNoel Grandin     rWrt.ChangeParaToken( HtmlTokenId::NONE );
84760d9e89fSNoel Grandin     rWrt.OutAndSetDefList( 0 );
8487b0b5cdfSJens-Heiner Rechtien 
8497b0b5cdfSJens-Heiner Rechtien     const SwSection& rSection = rSectNd.GetSection();
850ab465b90SChristian Lohmaier     const SwSectionFormat *pFormat = rSection.GetFormat();
851d884c4beSCaolán McNamara     assert(pFormat && "Section without a format?");
8527b0b5cdfSJens-Heiner Rechtien 
853ac0f9d32STakeshi Abe     bool bStartTag = true;
854ac0f9d32STakeshi Abe     bool bEndTag = true;
85501b49802SStephan Bergmann     const SwSectionFormat *pSurrFormat = nullptr;
85601b49802SStephan Bergmann     const SwSectionNode *pSurrSectNd = nullptr;
85701b49802SStephan Bergmann     const SwSection *pSurrSection = nullptr;
85801b49802SStephan Bergmann     const SwFormatCol *pSurrCol = nullptr;
8597b0b5cdfSJens-Heiner Rechtien 
8605f9ffc31SNoel Grandin     SwNodeOffset nSectSttIdx = rSectNd.GetIndex();
8615f9ffc31SNoel Grandin     SwNodeOffset nSectEndIdx = rSectNd.EndOfSectionIndex();
862ab465b90SChristian Lohmaier     const SwFormatCol *pCol = lcl_html_GetFormatCol( rSection, *pFormat );
8637b0b5cdfSJens-Heiner Rechtien     if( pCol )
8647b0b5cdfSJens-Heiner Rechtien     {
8657b0b5cdfSJens-Heiner Rechtien         // If the next node is a columned section node, too, don't export
8667b0b5cdfSJens-Heiner Rechtien         // an empty section.
86760d9e89fSNoel Grandin         if( lcl_html_IsMultiColStart( rWrt, nSectSttIdx+1 ) )
868ac0f9d32STakeshi Abe             bStartTag = false;
8697b0b5cdfSJens-Heiner Rechtien 
8707b0b5cdfSJens-Heiner Rechtien         // The same applies if the section end with another columned section.
87160d9e89fSNoel Grandin         if( lcl_html_IsMultiColEnd( rWrt, nSectEndIdx-1 ) )
872ac0f9d32STakeshi Abe             bEndTag = false;
8737b0b5cdfSJens-Heiner Rechtien 
874c2511f27SJens Carl         // is there a columned section around this one?
87577fb2279SJens-Heiner Rechtien         const SwStartNode *pSttNd = rSectNd.StartOfSectionNode();
8767b0b5cdfSJens-Heiner Rechtien         if( pSttNd )
8777b0b5cdfSJens-Heiner Rechtien         {
8787b0b5cdfSJens-Heiner Rechtien             pSurrSectNd = pSttNd->FindSectionNode();
8797b0b5cdfSJens-Heiner Rechtien             if( pSurrSectNd )
8807b0b5cdfSJens-Heiner Rechtien             {
8817b0b5cdfSJens-Heiner Rechtien                 const SwStartNode *pBoxSttNd = pSttNd->FindTableBoxStartNode();
8827b0b5cdfSJens-Heiner Rechtien                 if( !pBoxSttNd ||
8837b0b5cdfSJens-Heiner Rechtien                     pBoxSttNd->GetIndex() < pSurrSectNd->GetIndex() )
8847b0b5cdfSJens-Heiner Rechtien                 {
8857b0b5cdfSJens-Heiner Rechtien                     pSurrSection = &pSurrSectNd->GetSection();
886ab465b90SChristian Lohmaier                     pSurrFormat = pSurrSection->GetFormat();
887ab465b90SChristian Lohmaier                     if( pSurrFormat )
888ab465b90SChristian Lohmaier                         pSurrCol = lcl_html_GetFormatCol( *pSurrSection,
889ab465b90SChristian Lohmaier                                                        *pSurrFormat );
8907b0b5cdfSJens-Heiner Rechtien                 }
8917b0b5cdfSJens-Heiner Rechtien             }
8927b0b5cdfSJens-Heiner Rechtien         }
8937b0b5cdfSJens-Heiner Rechtien     }
8947b0b5cdfSJens-Heiner Rechtien 
8957b0b5cdfSJens-Heiner Rechtien     // The surrounding section must be closed before the current one is
896c2511f27SJens Carl     // opened, except that it start immediately before the current one or
8977b0b5cdfSJens-Heiner Rechtien     // another end immediately before the current one
8985f9ffc31SNoel Grandin     if( pSurrCol && nSectSttIdx - pSurrSectNd->GetIndex() > SwNodeOffset(1) &&
89960d9e89fSNoel Grandin         !lcl_html_IsMultiColEnd( rWrt, nSectSttIdx-1 ) )
90060d9e89fSNoel Grandin         lcl_html_OutSectionEndTag( rWrt );
9017b0b5cdfSJens-Heiner Rechtien 
9027b0b5cdfSJens-Heiner Rechtien     if( bStartTag )
90360d9e89fSNoel Grandin         lcl_html_OutSectionStartTag( rWrt, rSection, *pFormat, pCol );
9047b0b5cdfSJens-Heiner Rechtien 
9057b0b5cdfSJens-Heiner Rechtien     {
90660d9e89fSNoel Grandin         HTMLSaveData aSaveData( rWrt,
90760d9e89fSNoel Grandin             rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex()+1,
9087b0b5cdfSJens-Heiner Rechtien             rSectNd.EndOfSectionIndex(),
909ab465b90SChristian Lohmaier             false, pFormat );
91060d9e89fSNoel Grandin         rWrt.Out_SwDoc( rWrt.m_pCurrentPam.get() );
9117b0b5cdfSJens-Heiner Rechtien     }
9127b0b5cdfSJens-Heiner Rechtien 
91360d9e89fSNoel Grandin     rWrt.m_pCurrentPam->GetPoint()->Assign(*rSectNd.EndOfSectionNode());
9147b0b5cdfSJens-Heiner Rechtien 
9157b0b5cdfSJens-Heiner Rechtien     if( bEndTag )
91660d9e89fSNoel Grandin         lcl_html_OutSectionEndTag( rWrt );
9177b0b5cdfSJens-Heiner Rechtien 
9187b0b5cdfSJens-Heiner Rechtien     // The surrounding section must be started again, except that it ends
919c2511f27SJens Carl     // immediately behind the current one.
9207b0b5cdfSJens-Heiner Rechtien     if( pSurrCol &&
9215f9ffc31SNoel Grandin         pSurrSectNd->EndOfSectionIndex() - nSectEndIdx > SwNodeOffset(1) &&
92260d9e89fSNoel Grandin         !lcl_html_IsMultiColStart( rWrt, nSectEndIdx+1 ) )
92360d9e89fSNoel Grandin         lcl_html_OutSectionStartTag( rWrt, *pSurrSection, *pSurrFormat,
924ac0f9d32STakeshi Abe                                      pSurrCol, true );
9257b0b5cdfSJens-Heiner Rechtien 
9267b0b5cdfSJens-Heiner Rechtien     return rWrt;
9277b0b5cdfSJens-Heiner Rechtien }
9287b0b5cdfSJens-Heiner Rechtien 
Out_SwDoc(SwPaM * pPam)9297b0b5cdfSJens-Heiner Rechtien void SwHTMLWriter::Out_SwDoc( SwPaM* pPam )
9307b0b5cdfSJens-Heiner Rechtien {
931266e58d2SMiklos Vajna     bool bSaveWriteAll = m_bWriteAll;     // save
932c3549e78SSamuel Mehrbrodt     bool bIncludeHidden = officecfg::Office::Writer::FilterFlags::HTML::IncludeHiddenText::get();
9337b0b5cdfSJens-Heiner Rechtien 
934c2511f27SJens Carl     // search next text::Bookmark position from text::Bookmark table
935266e58d2SMiklos Vajna     m_nBkmkTabPos = m_bWriteAll ? FindPos_Bkmk( *m_pCurrentPam->GetPoint() ) : -1;
9367b0b5cdfSJens-Heiner Rechtien 
937c2511f27SJens Carl     // output all areas of PaM's in the HTML file
9387b0b5cdfSJens-Heiner Rechtien     do {
939266e58d2SMiklos Vajna         m_bWriteAll = bSaveWriteAll;
940b46496c4SMiklos Vajna         m_bFirstLine = true;
9417b0b5cdfSJens-Heiner Rechtien 
942c2511f27SJens Carl         // search for first on PaM created FlyFrame
943c2511f27SJens Carl         // still missing:
9447b0b5cdfSJens-Heiner Rechtien 
945fc227d83SMike Kaganski         while (*m_pCurrentPam->GetPoint() <= *m_pCurrentPam->GetMark())
9467b0b5cdfSJens-Heiner Rechtien         {
947ab0d9af9SNoel Grandin             SwNode&  rNd = m_pCurrentPam->GetPointNode();
9487b0b5cdfSJens-Heiner Rechtien 
949e2080e70SNoel Grandin             OSL_ENSURE( !(rNd.IsGrfNode() || rNd.IsOLENode()),
950c2511f27SJens Carl                     "Unexpected Grf- or OLE-Node here" );
951c3549e78SSamuel Mehrbrodt 
952ab465b90SChristian Lohmaier             if( rNd.IsTextNode() )
9537b0b5cdfSJens-Heiner Rechtien             {
954ab465b90SChristian Lohmaier                 SwTextNode* pTextNd = rNd.GetTextNode();
955c3549e78SSamuel Mehrbrodt                 if (!pTextNd->IsHidden() || bIncludeHidden)
956c3549e78SSamuel Mehrbrodt                 {
957b46496c4SMiklos Vajna                     if (!m_bFirstLine)
958c98388dbSNoel Grandin                         m_pCurrentPam->GetPoint()->Assign(*pTextNd, 0);
9597b0b5cdfSJens-Heiner Rechtien 
960ab465b90SChristian Lohmaier                     OutHTML_SwTextNode(*this, *pTextNd);
9617b0b5cdfSJens-Heiner Rechtien                 }
962c3549e78SSamuel Mehrbrodt             }
963e2080e70SNoel Grandin             else if( rNd.IsTableNode() )
9647b0b5cdfSJens-Heiner Rechtien             {
96501b49802SStephan Bergmann                 OutHTML_SwTableNode( *this, *rNd.GetTableNode(), nullptr );
966266e58d2SMiklos Vajna                 m_nBkmkTabPos = m_bWriteAll ? FindPos_Bkmk( *m_pCurrentPam->GetPoint() ) : -1;
9677b0b5cdfSJens-Heiner Rechtien             }
968e2080e70SNoel Grandin             else if( rNd.IsSectionNode() )
9697b0b5cdfSJens-Heiner Rechtien             {
970c3549e78SSamuel Mehrbrodt                 SwSectionNode* pSectionNode = rNd.GetSectionNode();
971c3549e78SSamuel Mehrbrodt                 if (!pSectionNode->GetSection().IsHiddenFlag() || bIncludeHidden)
972c3549e78SSamuel Mehrbrodt                 {
973c3549e78SSamuel Mehrbrodt                     OutHTML_Section( *this, *pSectionNode );
974266e58d2SMiklos Vajna                     m_nBkmkTabPos = m_bWriteAll ? FindPos_Bkmk( *m_pCurrentPam->GetPoint() ) : -1;
9757b0b5cdfSJens-Heiner Rechtien                 }
976c3549e78SSamuel Mehrbrodt             }
977266e58d2SMiklos Vajna             else if( &rNd == &m_pDoc->GetNodes().GetEndOfContent() )
9787b0b5cdfSJens-Heiner Rechtien                 break;
9797b0b5cdfSJens-Heiner Rechtien 
9800df94183SNoel Grandin             m_pCurrentPam->GetPoint()->Adjust(SwNodeOffset(+1));   // move
981961d42e1SNoel Grandin             SwNodeOffset nPos = m_pCurrentPam->GetPoint()->GetNodeIndex();
9827b0b5cdfSJens-Heiner Rechtien 
983266e58d2SMiklos Vajna             if( m_bShowProgress )
9845f9ffc31SNoel Grandin                 ::SetProgressState( sal_Int32(nPos), m_pDoc->GetDocShell() );   // How far ?
9857b0b5cdfSJens-Heiner Rechtien 
986c2511f27SJens Carl             /* If only the selected area should be saved, so only the complete
987c2511f27SJens Carl              * nodes should be saved, this means the first and n-th node
988c2511f27SJens Carl              * partly, the 2nd till n-1 node complete. (complete means with
989c2511f27SJens Carl              * all formats!)
9907b0b5cdfSJens-Heiner Rechtien              */
991266e58d2SMiklos Vajna             m_bWriteAll = bSaveWriteAll ||
992961d42e1SNoel Grandin                         nPos != m_pCurrentPam->GetMark()->GetNodeIndex();
993b46496c4SMiklos Vajna             m_bFirstLine = false;
994c2511f27SJens Carl             m_bOutFooter = false; // after one node no footer anymore
9957b0b5cdfSJens-Heiner Rechtien         }
9967b0b5cdfSJens-Heiner Rechtien 
99757f1934bSNoel Grandin         ChangeParaToken( HtmlTokenId::NONE ); // MIB 8.7.97: We're doing it here and not at the caller
9987b0b5cdfSJens-Heiner Rechtien         OutAndSetDefList( 0 );
9997b0b5cdfSJens-Heiner Rechtien 
1000c2511f27SJens Carl     } while( CopyNextPam( &pPam ) );        // until all PaM's processed
10017b0b5cdfSJens-Heiner Rechtien 
1002266e58d2SMiklos Vajna     m_bWriteAll = bSaveWriteAll;          // reset to old values
10037b0b5cdfSJens-Heiner Rechtien }
10047b0b5cdfSJens-Heiner Rechtien 
1005c2511f27SJens Carl // write the StyleTable, general data, header/footer/footnotes
OutBodyColor(const char * pTag,const SwFormat * pFormat,SwHTMLWriter & rHWrt)100640a7abaaSNoel Grandin static void OutBodyColor( const char* pTag, const SwFormat *pFormat,
10077b0b5cdfSJens-Heiner Rechtien                           SwHTMLWriter& rHWrt )
10087b0b5cdfSJens-Heiner Rechtien {
100901b49802SStephan Bergmann     const SwFormat *pRefFormat = nullptr;
10107b0b5cdfSJens-Heiner Rechtien 
101182f9573bSNoel Grandin     if( rHWrt.m_xTemplate.is() )
1012ab465b90SChristian Lohmaier         pRefFormat = SwHTMLWriter::GetTemplateFormat( pFormat->GetPoolFormatId(),
101382f9573bSNoel Grandin                                                 &rHWrt.m_xTemplate->getIDocumentStylePoolAccess() );
10147b0b5cdfSJens-Heiner Rechtien 
101501b49802SStephan Bergmann     const SvxColorItem *pColorItem = nullptr;
10167b0b5cdfSJens-Heiner Rechtien 
1017ab465b90SChristian Lohmaier     const SfxItemSet& rItemSet = pFormat->GetAttrSet();
101804e32513SNoel Grandin     const SvxColorItem *pCItem = rItemSet.GetItemIfSet( RES_CHRATR_COLOR );
101904e32513SNoel Grandin     const SvxColorItem *pRefItem = nullptr;
102004e32513SNoel Grandin     if (pRefFormat)
102104e32513SNoel Grandin         pRefItem = pRefFormat->GetAttrSet().GetItemIfSet( RES_CHRATR_COLOR );
102204e32513SNoel Grandin     if( pCItem )
10237b0b5cdfSJens-Heiner Rechtien     {
1024c2511f27SJens Carl         // only when the item is set in the template of the current document
1025c2511f27SJens Carl         // or has a different value as the in HTML template, it will be set
10267a35d80aSMichael Brauer 
102704e32513SNoel Grandin         if( !pRefItem )
10287a35d80aSMichael Brauer         {
10297b0b5cdfSJens-Heiner Rechtien             pColorItem = pCItem;
10307b0b5cdfSJens-Heiner Rechtien         }
10317a35d80aSMichael Brauer         else
10327a35d80aSMichael Brauer         {
10337a35d80aSMichael Brauer             Color aColor( pCItem->GetValue() );
10349a97b9c0SNoel Grandin             if( COL_AUTO == aColor )
103519a906f0SNoel Grandin                 aColor = COL_BLACK;
10367a35d80aSMichael Brauer 
103704e32513SNoel Grandin             Color aRefColor( pRefItem->GetValue() );
10389a97b9c0SNoel Grandin             if( COL_AUTO == aRefColor )
103919a906f0SNoel Grandin                 aRefColor = COL_BLACK;
10407a35d80aSMichael Brauer 
10417a35d80aSMichael Brauer             if( !aColor.IsRGBEqual( aRefColor ) )
10427a35d80aSMichael Brauer                 pColorItem = pCItem;
10437a35d80aSMichael Brauer         }
10447a35d80aSMichael Brauer     }
104504e32513SNoel Grandin     else if( pRefItem )
10467b0b5cdfSJens-Heiner Rechtien     {
1047c2511f27SJens Carl         // The item was still set in the HTML template so we output the default
10484790ef5cSArmin Le Grand (allotropia)         pColorItem = &rItemSet.GetPool()->GetUserOrPoolDefaultItem( RES_CHRATR_COLOR );
10497b0b5cdfSJens-Heiner Rechtien     }
10507b0b5cdfSJens-Heiner Rechtien 
10517b0b5cdfSJens-Heiner Rechtien     if( pColorItem )
10527b0b5cdfSJens-Heiner Rechtien     {
10537049328fSNoel Grandin         OString sOut = OString::Concat(" ") + pTag + "=";
10547049328fSNoel Grandin         rHWrt.Strm().WriteOString( sOut );
10557a35d80aSMichael Brauer         Color aColor( pColorItem->GetValue() );
10569a97b9c0SNoel Grandin         if( COL_AUTO == aColor )
105719a906f0SNoel Grandin             aColor = COL_BLACK;
105893a9b70cSNoel Grandin         HTMLOutFuncs::Out_Color( rHWrt.Strm(), aColor );
1059ab465b90SChristian Lohmaier         if( RES_POOLCOLL_STANDARD==pFormat->GetPoolFormatId() )
1060dba5dccfSNoel Grandin             rHWrt.m_xDfltColor = aColor;
10617b0b5cdfSJens-Heiner Rechtien     }
10627b0b5cdfSJens-Heiner Rechtien }
10637b0b5cdfSJens-Heiner Rechtien 
OutHeaderAttrs()10647b0b5cdfSJens-Heiner Rechtien sal_uInt16 SwHTMLWriter::OutHeaderAttrs()
10657b0b5cdfSJens-Heiner Rechtien {
1066961d42e1SNoel Grandin     SwNodeOffset nIdx = m_pCurrentPam->GetPoint()->GetNodeIndex();
1067961d42e1SNoel Grandin     SwNodeOffset nEndIdx = m_pCurrentPam->GetMark()->GetNodeIndex();
10687b0b5cdfSJens-Heiner Rechtien 
106901b49802SStephan Bergmann     SwTextNode *pTextNd = nullptr;
10707b0b5cdfSJens-Heiner Rechtien     while( nIdx<=nEndIdx &&
1071266e58d2SMiklos Vajna         nullptr==(pTextNd=m_pDoc->GetNodes()[nIdx]->GetTextNode()) )
10727b0b5cdfSJens-Heiner Rechtien         nIdx++;
10737b0b5cdfSJens-Heiner Rechtien 
1074c2511f27SJens Carl     OSL_ENSURE( pTextNd, "No Text-Node found" );
1075ab465b90SChristian Lohmaier     if( !pTextNd || !pTextNd->HasHints() )
10767b0b5cdfSJens-Heiner Rechtien         return 0;
10777b0b5cdfSJens-Heiner Rechtien 
10787b0b5cdfSJens-Heiner Rechtien     sal_uInt16 nAttrs = 0;
1079ab465b90SChristian Lohmaier     const size_t nCntAttr = pTextNd->GetSwpHints().Count();
10802e5ec4f5SCaolán McNamara     sal_Int32 nOldPos = 0;
108105dda9a9SMatteo Casalin     for( size_t i=0; i<nCntAttr; ++i )
10827b0b5cdfSJens-Heiner Rechtien     {
108342b0440dSNoel Grandin         const SwTextAttr *pHt = pTextNd->GetSwpHints().Get(i);
1084c2b55219SOliver-Rainer Wittmann         if( !pHt->End() )
10857b0b5cdfSJens-Heiner Rechtien         {
1086e2080e70SNoel Grandin             sal_Int32 nPos = pHt->GetStart();
10870761f816SOliver-Rainer Wittmann             if( nPos-nOldPos > 1
10880761f816SOliver-Rainer Wittmann                 || ( pHt->Which() != RES_TXTATR_FIELD
10890761f816SOliver-Rainer Wittmann                      && pHt->Which() != RES_TXTATR_ANNOTATION ) )
10907b0b5cdfSJens-Heiner Rechtien                 break;
10917b0b5cdfSJens-Heiner Rechtien 
109208f5355dSNoel Grandin             const SwFieldIds nFieldWhich =
1093ab465b90SChristian Lohmaier                 static_cast<const SwFormatField&>(pHt->GetAttr()).GetField()->GetTyp()->Which();
109408f5355dSNoel Grandin             if( SwFieldIds::Postit!=nFieldWhich &&
109508f5355dSNoel Grandin                 SwFieldIds::Script!=nFieldWhich )
10967b0b5cdfSJens-Heiner Rechtien                 break;
10977b0b5cdfSJens-Heiner Rechtien 
10987b0b5cdfSJens-Heiner Rechtien             OutNewLine();
1099ab465b90SChristian Lohmaier             OutHTML_SwFormatField( *this, pHt->GetAttr() );
11007b0b5cdfSJens-Heiner Rechtien             nOldPos = nPos;
110105dda9a9SMatteo Casalin             OSL_ENSURE( nAttrs<SAL_MAX_UINT16, "Too many attributes" );
11027b0b5cdfSJens-Heiner Rechtien             nAttrs++;
11037b0b5cdfSJens-Heiner Rechtien         }
11047b0b5cdfSJens-Heiner Rechtien     }
11057b0b5cdfSJens-Heiner Rechtien 
11067b0b5cdfSJens-Heiner Rechtien     return nAttrs;
11077b0b5cdfSJens-Heiner Rechtien }
11087b0b5cdfSJens-Heiner Rechtien 
MakeHeader(sal_uInt16 & rHeaderAttrs)11091da7d73eSTomaž Vajngerl const SwPageDesc *SwHTMLWriter::MakeHeader( sal_uInt16 &rHeaderAttrs )
11107b0b5cdfSJens-Heiner Rechtien {
11111946794aSLuboš Luňák     OStringBuffer sOut;
11128760b2b0SMiklos Vajna     if (!mbSkipHeaderFooter)
11138760b2b0SMiklos Vajna     {
1114aad9c6daSMiklos Vajna         if (mbXHTML)
1115aad9c6daSMiklos Vajna             sOut.append(OOO_STRING_SVTOOLS_HTML_doctype " " OOO_STRING_SVTOOLS_XHTML_doctype11);
1116aad9c6daSMiklos Vajna         else
1117821d2f8cSAndreas Heinisch             sOut.append(OOO_STRING_SVTOOLS_HTML_doctype " " OOO_STRING_SVTOOLS_HTML_doctype5);
1118eaf07139SNoel Grandin         HTMLOutFuncs::Out_AsciiTag( Strm(), sOut.makeStringAndClear() ); // No GetNamespace() here.
11197b0b5cdfSJens-Heiner Rechtien 
1120c2511f27SJens Carl         // build prelude
11217b0b5cdfSJens-Heiner Rechtien         OutNewLine();
11223d236177SMike Kaganski         HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_html) );
11237b0b5cdfSJens-Heiner Rechtien 
11247b0b5cdfSJens-Heiner Rechtien         OutNewLine();
11253d236177SMike Kaganski         HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_head) );
11267b0b5cdfSJens-Heiner Rechtien 
1127c2511f27SJens Carl         IncIndentLevel();   // indent content of <HEAD>
11287b0b5cdfSJens-Heiner Rechtien 
1129c2511f27SJens Carl         // DocumentInfo
11301946794aSLuboš Luňák         OString sIndent = GetIndentString();
11314aec6c9eSTomaž Vajngerl 
11326f28e672SOliver Bolte         uno::Reference<document::XDocumentProperties> xDocProps;
1133266e58d2SMiklos Vajna         SwDocShell *pDocShell(m_pDoc->GetDocShell());
113479dc19fcSCaolán McNamara         if (pDocShell)
113579dc19fcSCaolán McNamara         {
11366f28e672SOliver Bolte             uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
11376f28e672SOliver Bolte                                                                        pDocShell->GetModel(), uno::UNO_QUERY_THROW);
11386f28e672SOliver Bolte             xDocProps.set(xDPS->getDocumentProperties());
11396f28e672SOliver Bolte         }
11406f28e672SOliver Bolte 
11416f28e672SOliver Bolte         // xDocProps may be null here (when copying)
11426f28e672SOliver Bolte         SfxFrameHTMLWriter::Out_DocInfo( Strm(), GetBaseURL(), xDocProps,
1143aeeacd28SMike Kaganski                                          sIndent.getStr() );
11447b0b5cdfSJens-Heiner Rechtien 
1145c2511f27SJens Carl         // comments and meta-tags of first paragraph
11467b0b5cdfSJens-Heiner Rechtien         rHeaderAttrs = OutHeaderAttrs();
11477b0b5cdfSJens-Heiner Rechtien 
11487b0b5cdfSJens-Heiner Rechtien         OutFootEndNoteInfo();
11498760b2b0SMiklos Vajna     }
11507b0b5cdfSJens-Heiner Rechtien 
115101b49802SStephan Bergmann     const SwPageDesc *pPageDesc = nullptr;
115294ae5e18SKayo Hamid 
1153c2511f27SJens Carl     // In none HTML documents the first set template will be exported
1154c2511f27SJens Carl     // and if none is set the default template
1155961d42e1SNoel Grandin     SwNodeOffset nNodeIdx = m_pCurrentPam->GetPoint()->GetNodeIndex();
11567b0b5cdfSJens-Heiner Rechtien 
1157266e58d2SMiklos Vajna     while( nNodeIdx < m_pDoc->GetNodes().Count() )
11587b0b5cdfSJens-Heiner Rechtien     {
1159266e58d2SMiklos Vajna         SwNode *pNd = m_pDoc->GetNodes()[ nNodeIdx ];
1160ab465b90SChristian Lohmaier         if( pNd->IsContentNode() )
11617b0b5cdfSJens-Heiner Rechtien         {
11628d762c14SNoel Grandin             pPageDesc = pNd->GetContentNode()->GetAttr(RES_PAGEDESC).GetPageDesc();
11637b0b5cdfSJens-Heiner Rechtien             break;
11647b0b5cdfSJens-Heiner Rechtien         }
11657b0b5cdfSJens-Heiner Rechtien         else if( pNd->IsTableNode() )
11667b0b5cdfSJens-Heiner Rechtien         {
1167ab465b90SChristian Lohmaier             pPageDesc = pNd->GetTableNode()->GetTable().GetFrameFormat()
11687b0b5cdfSJens-Heiner Rechtien                            ->GetPageDesc().GetPageDesc();
11697b0b5cdfSJens-Heiner Rechtien             break;
11707b0b5cdfSJens-Heiner Rechtien         }
11717b0b5cdfSJens-Heiner Rechtien 
11727b0b5cdfSJens-Heiner Rechtien         nNodeIdx++;
11737b0b5cdfSJens-Heiner Rechtien     }
11747b0b5cdfSJens-Heiner Rechtien 
11757b0b5cdfSJens-Heiner Rechtien     if( !pPageDesc )
1176266e58d2SMiklos Vajna         pPageDesc = &m_pDoc->GetPageDesc( 0 );
11777b0b5cdfSJens-Heiner Rechtien 
11788760b2b0SMiklos Vajna     if (!mbSkipHeaderFooter)
11798760b2b0SMiklos Vajna     {
1180c2511f27SJens Carl         // and now ... the style sheet!!!
1181b46496c4SMiklos Vajna         if( m_bCfgOutStyles )
11827b0b5cdfSJens-Heiner Rechtien         {
11837b0b5cdfSJens-Heiner Rechtien             OutStyleSheet( *pPageDesc );
11847b0b5cdfSJens-Heiner Rechtien         }
11857b0b5cdfSJens-Heiner Rechtien 
1186c2511f27SJens Carl         // and now ... the BASIC and JavaScript!
118703fd45dcSMiklos Vajna         if( m_pDoc->GetDocShell() )   // BASIC is possible only in case we have a DocShell
1188186ef501SMiklos Vajna             OutBasic(*this);
11897b0b5cdfSJens-Heiner Rechtien 
1190c2511f27SJens Carl         DecIndentLevel();   // indent content of <HEAD>
11917b0b5cdfSJens-Heiner Rechtien         OutNewLine();
11923d236177SMike Kaganski         HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_head), false );
11937b0b5cdfSJens-Heiner Rechtien 
1194c2511f27SJens Carl         // the body won't be indented, because then everything would be indented!
11957b0b5cdfSJens-Heiner Rechtien         OutNewLine();
1196b4f3af91SMiklos Vajna         sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_body);
1197c0fec001SNoel Grandin         Strm().WriteOString( sOut );
1198c0fec001SNoel Grandin         sOut.setLength(0);
11997b0b5cdfSJens-Heiner Rechtien 
120097075a38SMichael Brauer         // language
1201b46496c4SMiklos Vajna         OutLanguage( m_eLang );
120297075a38SMichael Brauer 
1203c2511f27SJens Carl         // output text colour, when it was set in the default template or was changed
1204f83ef386SIvo Hinkelmann         OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_text,
1205266e58d2SMiklos Vajna                       m_pDoc->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD, false ),
12067b0b5cdfSJens-Heiner Rechtien                       *this );
12077b0b5cdfSJens-Heiner Rechtien 
1208c2511f27SJens Carl         // colour of (un)visited links
1209f83ef386SIvo Hinkelmann         OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_link,
1210266e58d2SMiklos Vajna                       m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_INET_NORMAL ),
12117b0b5cdfSJens-Heiner Rechtien                       *this );
1212f83ef386SIvo Hinkelmann         OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_vlink,
1213266e58d2SMiklos Vajna                       m_pDoc->getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_INET_VISIT ),
12147b0b5cdfSJens-Heiner Rechtien                       *this );
12157b0b5cdfSJens-Heiner Rechtien 
12167b0b5cdfSJens-Heiner Rechtien         const SfxItemSet& rItemSet = pPageDesc->GetMaster().GetAttrSet();
12177b0b5cdfSJens-Heiner Rechtien 
1218298e144fSMichael Stahl         // fdo#86857 page styles now contain the XATTR_*, not RES_BACKGROUND
1219d4248915SNoel Grandin         std::unique_ptr<SvxBrushItem> const aBrushItem(getSvxBrushItemFromSourceSet(rItemSet, RES_BACKGROUND));
12201e268223SArmin Le Grand         OutBackground(aBrushItem.get(), true);
12217b0b5cdfSJens-Heiner Rechtien 
1222b46496c4SMiklos Vajna         m_nDirection = GetHTMLDirection( rItemSet );
1223b46496c4SMiklos Vajna         OutDirection( m_nDirection );
1224b13f6ea1SMichael Brauer 
1225b46496c4SMiklos Vajna         if( m_bCfgOutStyles )
122646fa816aSOliver Specht         {
12271c3ffcddSNoel Grandin             OutCSS1_BodyTagStyleOpt( *this, rItemSet );
122846fa816aSOliver Specht         }
1229c2511f27SJens Carl         // append events
123003fd45dcSMiklos Vajna         if( m_pDoc->GetDocShell() )   // BASIC is possible only in case we have a DocShell
12317b0b5cdfSJens-Heiner Rechtien             OutBasicBodyEvents();
12327b0b5cdfSJens-Heiner Rechtien 
1233d803483fSNoel Grandin         Strm().WriteChar( '>' );
12348760b2b0SMiklos Vajna     }
1235f74d9ba2SMiklos Vajna     else if (mbReqIF)
1236f74d9ba2SMiklos Vajna         // ReqIF: start xhtml.BlkStruct.class.
12373d236177SMike Kaganski         HTMLOutFuncs::Out_AsciiTag(Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_division));
12387b0b5cdfSJens-Heiner Rechtien 
12397b0b5cdfSJens-Heiner Rechtien     return pPageDesc;
12407b0b5cdfSJens-Heiner Rechtien }
12417b0b5cdfSJens-Heiner Rechtien 
OutAnchor(const OUString & rName)1242e1cebdd8SNoel Grandin void SwHTMLWriter::OutAnchor( const OUString& rName )
12437b0b5cdfSJens-Heiner Rechtien {
12444e6327c6SMiklos Vajna     if (mbReqIF)
12454e6327c6SMiklos Vajna     {
12464e6327c6SMiklos Vajna         // <a id=".."> has to be unique inside the whole document, but
12474e6327c6SMiklos Vajna         // we only write a fragment, so we can't ensure the ID is indeed
12484e6327c6SMiklos Vajna         // unique. Just don't write anchors in the ReqIF case.
12494e6327c6SMiklos Vajna         return;
12504e6327c6SMiklos Vajna     }
12514e6327c6SMiklos Vajna 
12521f93816dSNoel Grandin     OStringBuffer sOut("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor " ");
1253967eb080SMiklos Vajna     if (!mbXHTML)
1254967eb080SMiklos Vajna     {
1255967eb080SMiklos Vajna         sOut.append(OOO_STRING_SVTOOLS_HTML_O_name "=\"");
1256c0fec001SNoel Grandin         Strm().WriteOString( sOut );
1257c0fec001SNoel Grandin         sOut.setLength(0);
12585fe96b6dSMike Kaganski         HTMLOutFuncs::Out_String( Strm(), rName ).WriteOString( "\">" );
1259967eb080SMiklos Vajna     }
1260967eb080SMiklos Vajna     else
1261967eb080SMiklos Vajna     {
1262967eb080SMiklos Vajna         // XHTML wants 'id' instead of 'name', also the value can't contain
1263967eb080SMiklos Vajna         // spaces.
1264967eb080SMiklos Vajna         sOut.append(OOO_STRING_SVTOOLS_HTML_O_id "=\"");
1265c0fec001SNoel Grandin         Strm().WriteOString( sOut );
1266c0fec001SNoel Grandin         sOut.setLength(0);
12675fe96b6dSMike Kaganski         HTMLOutFuncs::Out_String( Strm(), rName.replace(' ', '_') ).WriteOString( "\">" );
1268967eb080SMiklos Vajna     }
12693d236177SMike Kaganski     HTMLOutFuncs::Out_AsciiTag( Strm(), Concat2View(GetNamespace() + OOO_STRING_SVTOOLS_HTML_anchor), false );
12707b0b5cdfSJens-Heiner Rechtien }
12717b0b5cdfSJens-Heiner Rechtien 
OutBookmarks()12727b0b5cdfSJens-Heiner Rechtien void SwHTMLWriter::OutBookmarks()
12737b0b5cdfSJens-Heiner Rechtien {
1274c2511f27SJens Carl     // fetch current bookmark
1275266e58d2SMiklos Vajna     IDocumentMarkAccess* const pMarkAccess = m_pDoc->getIDocumentMarkAccess();
1276d884c4beSCaolán McNamara 
1277c2511f27SJens Carl     // Output all bookmarks in this paragraph. The content position
1278c2511f27SJens Carl     // for the moment isn't considered!
1279961d42e1SNoel Grandin     SwNodeOffset nNode = m_pCurrentPam->GetPoint()->GetNodeIndex();
1280d884c4beSCaolán McNamara     while (m_nBkmkTabPos != -1)
12817b0b5cdfSJens-Heiner Rechtien     {
1282ed172f76SNoel Grandin         const ::sw::mark::Bookmark* pBookmark = pMarkAccess->getBookmarksBegin()[m_nBkmkTabPos];
1283d884c4beSCaolán McNamara         assert(pBookmark);
1284d884c4beSCaolán McNamara         if (pBookmark->GetMarkPos().GetNodeIndex() != nNode)
1285d884c4beSCaolán McNamara             break;
1286c2511f27SJens Carl         // The area of bookmarks is first ignored, because it's not read.
12877b0b5cdfSJens-Heiner Rechtien 
1288c2511f27SJens Carl         // first the SWG specific data:
1289ed172f76SNoel Grandin         if ( !pBookmark->GetName().isEmpty() )
1290ac0a285fSNoel Grandin             OutAnchor( pBookmark->GetName().toString() );
12917b0b5cdfSJens-Heiner Rechtien 
1292ed172f76SNoel Grandin         if( ++m_nBkmkTabPos >= pMarkAccess->getBookmarksCount() )
1293b46496c4SMiklos Vajna             m_nBkmkTabPos = -1;
12947b0b5cdfSJens-Heiner Rechtien         else
1295ed172f76SNoel Grandin             pBookmark = pMarkAccess->getBookmarksBegin()[m_nBkmkTabPos];
12967b0b5cdfSJens-Heiner Rechtien     }
12977b0b5cdfSJens-Heiner Rechtien 
1298c1723a3bSStephan Bergmann     decltype(m_aOutlineMarkPoss)::size_type nPos;
1299b46496c4SMiklos Vajna     for( nPos = 0; nPos < m_aOutlineMarkPoss.size() &&
1300b46496c4SMiklos Vajna                    m_aOutlineMarkPoss[nPos] < nNode; nPos++ )
13017b0b5cdfSJens-Heiner Rechtien         ;
13027b0b5cdfSJens-Heiner Rechtien 
1303b46496c4SMiklos Vajna     while( nPos < m_aOutlineMarkPoss.size() && m_aOutlineMarkPoss[nPos] == nNode )
13047b0b5cdfSJens-Heiner Rechtien     {
1305b46496c4SMiklos Vajna         OUString sMark( m_aOutlineMarks[nPos] );
1306832e5aadSCaolán McNamara         OutAnchor( sMark.replace('?', '_') ); // '?' causes problems in IE/Netscape 5
1307b46496c4SMiklos Vajna         m_aOutlineMarkPoss.erase( m_aOutlineMarkPoss.begin()+nPos );
1308b46496c4SMiklos Vajna         m_aOutlineMarks.erase( m_aOutlineMarks.begin() + nPos );
13097b0b5cdfSJens-Heiner Rechtien     }
13107b0b5cdfSJens-Heiner Rechtien }
13117b0b5cdfSJens-Heiner Rechtien 
OutPointFieldmarks(const SwPosition & rPos)131237be7a3fSKohei Yoshida void SwHTMLWriter::OutPointFieldmarks( const SwPosition& rPos )
131337be7a3fSKohei Yoshida {
131437be7a3fSKohei Yoshida     // "point" fieldmarks that occupy single character space, as opposed to
131537be7a3fSKohei Yoshida     // range fieldmarks that are associated with start and end points.
131637be7a3fSKohei Yoshida 
1317266e58d2SMiklos Vajna     const IDocumentMarkAccess* pMarkAccess = m_pDoc->getIDocumentMarkAccess();
131837be7a3fSKohei Yoshida     if (!pMarkAccess)
131937be7a3fSKohei Yoshida         return;
132037be7a3fSKohei Yoshida 
1321f9c4fd0bSNoel Grandin     const sw::mark::Fieldmark* pMark = pMarkAccess->getFieldmarkAt(rPos);
132237be7a3fSKohei Yoshida     if (!pMark)
132337be7a3fSKohei Yoshida         return;
132437be7a3fSKohei Yoshida 
1325639206f3SNoel Grandin     if (pMark->GetFieldname() != ODF_FORMCHECKBOX)
1326639206f3SNoel Grandin         return;
1327639206f3SNoel Grandin 
132861a63b97SNoel Grandin     const sw::mark::CheckboxFieldmark* pCheckBox =
132961a63b97SNoel Grandin         dynamic_cast<const sw::mark::CheckboxFieldmark*>(pMark);
133037be7a3fSKohei Yoshida 
1331639206f3SNoel Grandin     if (!pCheckBox)
1332639206f3SNoel Grandin         return;
1333639206f3SNoel Grandin 
133491c836acSNoel Grandin     OString aOut("<"
133591c836acSNoel Grandin         OOO_STRING_SVTOOLS_HTML_input
133691c836acSNoel Grandin         " "
133791c836acSNoel Grandin         OOO_STRING_SVTOOLS_HTML_O_type
133891c836acSNoel Grandin         "=\""
133991c836acSNoel Grandin         OOO_STRING_SVTOOLS_HTML_IT_checkbox
13407724e504SStephan Bergmann         "\""_ostr);
134137be7a3fSKohei Yoshida 
134237be7a3fSKohei Yoshida     if (pCheckBox->IsChecked())
134337be7a3fSKohei Yoshida     {
134491c836acSNoel Grandin         aOut += " "
134591c836acSNoel Grandin             OOO_STRING_SVTOOLS_HTML_O_checked
134691c836acSNoel Grandin             "=\""
134791c836acSNoel Grandin             OOO_STRING_SVTOOLS_HTML_O_checked
134891c836acSNoel Grandin             "\"";
134937be7a3fSKohei Yoshida     }
135037be7a3fSKohei Yoshida 
135137be7a3fSKohei Yoshida     aOut += "/>";
1352241bee7eSNoel Grandin     Strm().WriteOString(aOut);
135337be7a3fSKohei Yoshida 
135437be7a3fSKohei Yoshida     // TODO : Handle other single-point fieldmark types here (if any).
135537be7a3fSKohei Yoshida }
135637be7a3fSKohei Yoshida 
OutImplicitMark(std::u16string_view rMark,const char * pMarkType)1357042033f1SStephan Bergmann void SwHTMLWriter::OutImplicitMark( std::u16string_view rMark,
135840a7abaaSNoel Grandin                                     const char *pMarkType )
13597b0b5cdfSJens-Heiner Rechtien {
1360042033f1SStephan Bergmann     if( !rMark.empty() && !m_aImplicitMarks.empty() )
13617b0b5cdfSJens-Heiner Rechtien     {
13628b4719c2SStephan Bergmann         OUString sMark(rMark + OUStringChar(cMarkSeparator) + OUString::createFromAscii(pMarkType));
1363b46496c4SMiklos Vajna         if( 0 != m_aImplicitMarks.erase( sMark ) )
13647b0b5cdfSJens-Heiner Rechtien         {
1365832e5aadSCaolán McNamara             OutAnchor(sMark.replace('?', '_')); // '?' causes problems in IE/Netscape 5
13667b0b5cdfSJens-Heiner Rechtien         }
13677b0b5cdfSJens-Heiner Rechtien     }
13687b0b5cdfSJens-Heiner Rechtien }
13697b0b5cdfSJens-Heiner Rechtien 
convertHyperlinkHRefValue(const OUString & rURL)137003fe839dSTomaž Vajngerl OUString SwHTMLWriter::convertHyperlinkHRefValue(const OUString& rURL)
137191feb6d5SVladimir Glazounov {
1372b3a8056aSCaolán McNamara     OUString sURL(rURL);
1373b3a8056aSCaolán McNamara     sal_Int32 nPos = sURL.lastIndexOf(cMarkSeparator);
1374b3a8056aSCaolán McNamara     if (nPos != -1)
137591feb6d5SVladimir Glazounov     {
13767855ea48SNoel Grandin         OUString sCompare = sURL.copy(nPos + 1).replaceAll(" ", "");
137703fe839dSTomaž Vajngerl         if (!sCompare.isEmpty())
137891feb6d5SVladimir Glazounov         {
137903fe839dSTomaž Vajngerl             sCompare = sCompare.toAsciiLowerCase();
138003fe839dSTomaž Vajngerl             if( sCompare == "region"  || sCompare == "frame"   ||
138103fe839dSTomaž Vajngerl                 sCompare == "graphic" || sCompare == "ole"     ||
138203fe839dSTomaž Vajngerl                 sCompare == "table"   || sCompare == "outline" ||
138303fe839dSTomaž Vajngerl                 sCompare == "text" )
138491feb6d5SVladimir Glazounov             {
1385b3a8056aSCaolán McNamara                 sURL = sURL.replace( '?', '_' );   // '?' causes problems in IE/Netscape 5
138691feb6d5SVladimir Glazounov             }
138791feb6d5SVladimir Glazounov         }
138891feb6d5SVladimir Glazounov     }
1389fd346802SVasily Melenchuk     else if (!sURL.isEmpty() && sURL[0] != '#')
1390d82c0359SVasily Melenchuk     {
1391fd346802SVasily Melenchuk         // Link is not started from "#", so looks like external link. Encode this URL.
13920706b575SVasily Melenchuk         INetURLObject aURL(sURL);
1393599da3faSVasily Melenchuk         if (!aURL.HasError())
1394bfde4866SNoel Grandin             sURL = aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE);
1395d82c0359SVasily Melenchuk     }
13964be345abSMike Kaganski     return normalizeURL(sURL, false);
139703fe839dSTomaž Vajngerl }
139891feb6d5SVladimir Glazounov 
OutHyperlinkHRefValue(const OUString & rURL)139903fe839dSTomaž Vajngerl void SwHTMLWriter::OutHyperlinkHRefValue( const OUString& rURL )
140003fe839dSTomaž Vajngerl {
140103fe839dSTomaž Vajngerl     OUString sURL = convertHyperlinkHRefValue(rURL);
1402aeeacd28SMike Kaganski     HTMLOutFuncs::Out_String( Strm(), sURL );
140391feb6d5SVladimir Glazounov }
140491feb6d5SVladimir Glazounov 
OutBackground(const SvxBrushItem * pBrushItem,bool bGraphic)14056aa35db3SNoel Grandin void SwHTMLWriter::OutBackground( const SvxBrushItem *pBrushItem, bool bGraphic )
14067b0b5cdfSJens-Heiner Rechtien {
14077b0b5cdfSJens-Heiner Rechtien     const Color &rBackColor = pBrushItem->GetColor();
1408c02f4b9bSOliver Düsterhoff     /// check, if background color is not "no fill"/"auto fill", instead of
1409c02f4b9bSOliver Düsterhoff     /// only checking, if transparency is not set.
1410e2cb1541SNoel Grandin     if( rBackColor != COL_TRANSPARENT )
14117b0b5cdfSJens-Heiner Rechtien     {
141240fa3a61SStephan Bergmann         Strm().WriteOString( " " OOO_STRING_SVTOOLS_HTML_O_bgcolor "=" );
141393a9b70cSNoel Grandin         HTMLOutFuncs::Out_Color( Strm(), rBackColor);
14147b0b5cdfSJens-Heiner Rechtien     }
14157b0b5cdfSJens-Heiner Rechtien 
14167b0b5cdfSJens-Heiner Rechtien     if( !bGraphic )
14177b0b5cdfSJens-Heiner Rechtien         return;
14187b0b5cdfSJens-Heiner Rechtien 
14197b0b5cdfSJens-Heiner Rechtien     const Graphic* pGrf = pBrushItem->GetGraphic();
142046fa816aSOliver Specht     OUString GraphicURL = pBrushItem->GetGraphicLink();
142146fa816aSOliver Specht     if( mbEmbedImages || GraphicURL.isEmpty())
142246fa816aSOliver Specht     {
14237b0b5cdfSJens-Heiner Rechtien         if( pGrf )
14247b0b5cdfSJens-Heiner Rechtien         {
14259373320fSNoel             OUString aGraphicInBase64;
1426d00ca13fSMatteo Casalin             if( !XOutBitmap::GraphicToBase64(*pGrf, aGraphicInBase64) )
14277b0b5cdfSJens-Heiner Rechtien             {
142825f65b23SNoel Grandin                 m_nWarn = WARN_SWG_POOR_LOAD;
14297b0b5cdfSJens-Heiner Rechtien             }
14305fe96b6dSMike Kaganski             Strm().WriteOString( " " OOO_STRING_SVTOOLS_HTML_O_background "=\"" );
14315fe96b6dSMike Kaganski             Strm().WriteOString( OOO_STRING_SVTOOLS_HTML_O_data ":" );
1432aeeacd28SMike Kaganski             HTMLOutFuncs::Out_String( Strm(), aGraphicInBase64 ).WriteChar( '\"' );
14337b0b5cdfSJens-Heiner Rechtien         }
14347b0b5cdfSJens-Heiner Rechtien     }
143546fa816aSOliver Specht     else
143646fa816aSOliver Specht     {
14374be345abSMike Kaganski         bool bOwn = false;
143846fa816aSOliver Specht         if( m_bCfgCpyLinkedGrfs )
143946fa816aSOliver Specht         {
14404be345abSMike Kaganski             bOwn = CopyLocalFileToINet(GraphicURL);
144146fa816aSOliver Specht         }
14424be345abSMike Kaganski         OUString s(normalizeURL(GraphicURL, bOwn));
14435fe96b6dSMike Kaganski         Strm().WriteOString(" " OOO_STRING_SVTOOLS_HTML_O_background "=\"" );
1444aeeacd28SMike Kaganski         HTMLOutFuncs::Out_String( Strm(), s );
14455fe96b6dSMike Kaganski         Strm().WriteOString("\"");
144646fa816aSOliver Specht 
144746fa816aSOliver Specht     }
144846fa816aSOliver Specht }
14497b0b5cdfSJens-Heiner Rechtien 
OutBackground(const SfxItemSet & rItemSet,bool bGraphic)14506aa35db3SNoel Grandin void SwHTMLWriter::OutBackground( const SfxItemSet& rItemSet, bool bGraphic )
14517b0b5cdfSJens-Heiner Rechtien {
145204e32513SNoel Grandin     if( const SvxBrushItem* pItem = rItemSet.GetItemIfSet( RES_BACKGROUND, false ) )
14537b0b5cdfSJens-Heiner Rechtien     {
145404e32513SNoel Grandin         OutBackground( pItem, bGraphic );
14557b0b5cdfSJens-Heiner Rechtien     }
14567b0b5cdfSJens-Heiner Rechtien }
14577b0b5cdfSJens-Heiner Rechtien 
GetLangWhichIdFromScript(sal_uInt16 nScript)1458ae095608SNoel Grandin TypedWhichId<SvxLanguageItem> SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript )
145997075a38SMichael Brauer {
1460ae095608SNoel Grandin     TypedWhichId<SvxLanguageItem> nWhichId(0);
146197075a38SMichael Brauer     switch( nScript )
146297075a38SMichael Brauer     {
146397075a38SMichael Brauer     case CSS1_OUTMODE_CJK:
146497075a38SMichael Brauer         nWhichId = RES_CHRATR_CJK_LANGUAGE;
146597075a38SMichael Brauer         break;
146697075a38SMichael Brauer     case CSS1_OUTMODE_CTL:
1467f85366c4SBogdan Buzea         nWhichId = RES_CHRATR_CTL_LANGUAGE;
146897075a38SMichael Brauer         break;
146997075a38SMichael Brauer     default:
147097075a38SMichael Brauer         nWhichId = RES_CHRATR_LANGUAGE;
147197075a38SMichael Brauer         break;
147297075a38SMichael Brauer     }
147397075a38SMichael Brauer     return nWhichId;
147497075a38SMichael Brauer }
147597075a38SMichael Brauer 
OutLanguage(LanguageType nLang)14760159a13bSJens-Heiner Rechtien void SwHTMLWriter::OutLanguage( LanguageType nLang )
147797075a38SMichael Brauer {
147881fac013SMiklos Vajna     // ReqIF mode: consumers would ignore language anyway.
1479639206f3SNoel Grandin     if (!(LANGUAGE_DONTKNOW != nLang && !mbReqIF))
1480639206f3SNoel Grandin         return;
1481639206f3SNoel Grandin 
14821f93816dSNoel Grandin     OStringBuffer sOut(" ");
1483aad9c6daSMiklos Vajna     if (mbXHTML)
1484aad9c6daSMiklos Vajna         sOut.append(OOO_STRING_SVTOOLS_XHTML_O_lang);
1485aad9c6daSMiklos Vajna     else
1486aad9c6daSMiklos Vajna         sOut.append(OOO_STRING_SVTOOLS_HTML_O_lang);
1487aad9c6daSMiklos Vajna     sOut.append("=\"");
1488c0fec001SNoel Grandin     Strm().WriteOString( sOut );
1489c0fec001SNoel Grandin     sOut.setLength(0);
1490aeeacd28SMike Kaganski     HTMLOutFuncs::Out_String( Strm(), LanguageTag::convertToBcp47(nLang) ).WriteChar( '"' );
149197075a38SMichael Brauer }
149297075a38SMichael Brauer 
GetHTMLDirection(const SfxItemSet & rItemSet) const14938ccbc16bSNoel Grandin SvxFrameDirection SwHTMLWriter::GetHTMLDirection( const SfxItemSet& rItemSet ) const
1494b13f6ea1SMichael Brauer {
1495617a2fefSNoel Grandin     return GetHTMLDirection( rItemSet.Get( RES_FRAMEDIR ).GetValue() );
1496b13f6ea1SMichael Brauer }
1497b13f6ea1SMichael Brauer 
GetHTMLDirection(SvxFrameDirection nDir) const14988ccbc16bSNoel Grandin SvxFrameDirection SwHTMLWriter::GetHTMLDirection( SvxFrameDirection nDir ) const
1499b13f6ea1SMichael Brauer {
1500b13f6ea1SMichael Brauer     switch( nDir )
1501b13f6ea1SMichael Brauer     {
15028ccbc16bSNoel Grandin     case SvxFrameDirection::Vertical_LR_TB:
15038ccbc16bSNoel Grandin         nDir = SvxFrameDirection::Horizontal_LR_TB;
1504b13f6ea1SMichael Brauer         break;
15058ccbc16bSNoel Grandin     case SvxFrameDirection::Vertical_RL_TB:
15068ccbc16bSNoel Grandin         nDir = SvxFrameDirection::Horizontal_RL_TB;
1507b13f6ea1SMichael Brauer         break;
15088ccbc16bSNoel Grandin     case SvxFrameDirection::Environment:
1509b46496c4SMiklos Vajna         nDir = m_nDirection;
15108ccbc16bSNoel Grandin         break;
15118ccbc16bSNoel Grandin     default: break;
1512b13f6ea1SMichael Brauer     }
1513b13f6ea1SMichael Brauer 
1514b13f6ea1SMichael Brauer     return nDir;
1515b13f6ea1SMichael Brauer }
1516b13f6ea1SMichael Brauer 
OutDirection(SvxFrameDirection nDir)15178ccbc16bSNoel Grandin void SwHTMLWriter::OutDirection( SvxFrameDirection nDir )
1518b13f6ea1SMichael Brauer {
151903fe839dSTomaž Vajngerl     OString sConverted = convertDirection(nDir);
152003fe839dSTomaž Vajngerl     if (!sConverted.isEmpty())
1521b13f6ea1SMichael Brauer     {
15224a96fb8eSNoel Grandin         OString sOut =
15234a96fb8eSNoel Grandin             " " OOO_STRING_SVTOOLS_HTML_O_dir
15244a96fb8eSNoel Grandin             "=\"" + sConverted + "\"";
15254a96fb8eSNoel Grandin         Strm().WriteOString( sOut );
1526b13f6ea1SMichael Brauer     }
1527b13f6ea1SMichael Brauer }
1528b13f6ea1SMichael Brauer 
convertDirection(SvxFrameDirection nDir)15298ccbc16bSNoel Grandin OString SwHTMLWriter::convertDirection(SvxFrameDirection nDir)
153003fe839dSTomaž Vajngerl {
153103fe839dSTomaž Vajngerl     OString sConverted;
1532935e8fc9STomaž Vajngerl     switch (nDir)
153303fe839dSTomaž Vajngerl     {
15348ccbc16bSNoel Grandin     case SvxFrameDirection::Horizontal_LR_TB:
15358ccbc16bSNoel Grandin     case SvxFrameDirection::Vertical_LR_TB:
15362c1e01b2SStephan Bergmann         sConverted = "ltr"_ostr;
153703fe839dSTomaž Vajngerl         break;
15388ccbc16bSNoel Grandin     case SvxFrameDirection::Horizontal_RL_TB:
15398ccbc16bSNoel Grandin     case SvxFrameDirection::Vertical_RL_TB:
15402c1e01b2SStephan Bergmann         sConverted = "rtl"_ostr;
154103fe839dSTomaž Vajngerl         break;
15428ccbc16bSNoel Grandin     default: break;
154303fe839dSTomaž Vajngerl     }
154403fe839dSTomaž Vajngerl     return sConverted;
154503fe839dSTomaž Vajngerl }
154603fe839dSTomaž Vajngerl 
GetIndentString(sal_uInt16 nIncLvl)15471946794aSLuboš Luňák OString SwHTMLWriter::GetIndentString(sal_uInt16 nIncLvl)
15487b0b5cdfSJens-Heiner Rechtien {
15491946794aSLuboš Luňák     OString sRet;
155079dc19fcSCaolán McNamara 
1551c2511f27SJens Carl     // somewhat cumbersome, but we have only one indent string!
1552b46496c4SMiklos Vajna     sal_uInt16 nLevel = m_nIndentLvl + nIncLvl;
15537b0b5cdfSJens-Heiner Rechtien 
15547b0b5cdfSJens-Heiner Rechtien     if( nLevel && nLevel <= MAX_INDENT_LEVEL)
15557b0b5cdfSJens-Heiner Rechtien     {
15567b0b5cdfSJens-Heiner Rechtien         sIndentTabs[nLevel] = 0;
155779dc19fcSCaolán McNamara         sRet = sIndentTabs;
15587b0b5cdfSJens-Heiner Rechtien         sIndentTabs[nLevel] = '\t';
15597b0b5cdfSJens-Heiner Rechtien     }
156079dc19fcSCaolán McNamara 
156179dc19fcSCaolán McNamara     return sRet;
15627b0b5cdfSJens-Heiner Rechtien }
15637b0b5cdfSJens-Heiner Rechtien 
OutNewLine(bool bCheck)15646aa35db3SNoel Grandin void SwHTMLWriter::OutNewLine( bool bCheck )
15657b0b5cdfSJens-Heiner Rechtien {
1566b46496c4SMiklos Vajna     if( !bCheck || (Strm().Tell()-m_nLastLFPos) > m_nIndentLvl )
15677b0b5cdfSJens-Heiner Rechtien     {
15685fe96b6dSMike Kaganski         Strm().WriteOString( SAL_NEWLINE_STRING );
1569b46496c4SMiklos Vajna         m_nLastLFPos = Strm().Tell();
15707b0b5cdfSJens-Heiner Rechtien     }
15717b0b5cdfSJens-Heiner Rechtien 
1572b46496c4SMiklos Vajna     if( m_nIndentLvl && m_nIndentLvl <= MAX_INDENT_LEVEL)
15737b0b5cdfSJens-Heiner Rechtien     {
1574b46496c4SMiklos Vajna         sIndentTabs[m_nIndentLvl] = 0;
15755fe96b6dSMike Kaganski         Strm().WriteOString( sIndentTabs );
1576b46496c4SMiklos Vajna         sIndentTabs[m_nIndentLvl] = '\t';
15777b0b5cdfSJens-Heiner Rechtien     }
15787b0b5cdfSJens-Heiner Rechtien }
15797b0b5cdfSJens-Heiner Rechtien 
GetHTMLFontSize(sal_uInt32 nHeight) const15807b0b5cdfSJens-Heiner Rechtien sal_uInt16 SwHTMLWriter::GetHTMLFontSize( sal_uInt32 nHeight ) const
15817b0b5cdfSJens-Heiner Rechtien {
15827b0b5cdfSJens-Heiner Rechtien     sal_uInt16 nSize = 1;
15837b0b5cdfSJens-Heiner Rechtien     for( sal_uInt16 i=6; i>0; i-- )
15847b0b5cdfSJens-Heiner Rechtien     {
1585b46496c4SMiklos Vajna         if( nHeight > (m_aFontHeights[i] + m_aFontHeights[i-1])/2 )
15867b0b5cdfSJens-Heiner Rechtien         {
15877b0b5cdfSJens-Heiner Rechtien             nSize = i+1;
15887b0b5cdfSJens-Heiner Rechtien             break;
15897b0b5cdfSJens-Heiner Rechtien         }
15907b0b5cdfSJens-Heiner Rechtien     }
15917b0b5cdfSJens-Heiner Rechtien 
15927b0b5cdfSJens-Heiner Rechtien     return nSize;
15937b0b5cdfSJens-Heiner Rechtien }
15947b0b5cdfSJens-Heiner Rechtien 
15953e17677fSLászló Németh // Paragraphs with Table of Contents and other index styles will be typeset with
15963e17677fSLászló Németh // dot leaders at the position of the last tabulator in PrintLayout (CSS2) mode
indexOfDotLeaders(sal_uInt16 nPoolId,std::u16string_view rStr)15971927b519SNoel Grandin sal_Int32 SwHTMLWriter::indexOfDotLeaders( sal_uInt16 nPoolId, std::u16string_view rStr )
15983e17677fSLászló Németh {
1599b46496c4SMiklos Vajna     if (m_bCfgPrintLayout && ((nPoolId >= RES_POOLCOLL_TOX_CNTNT1 && nPoolId <= RES_POOLCOLL_TOX_CNTNT5) ||
16003e17677fSLászló Németh         (nPoolId >= RES_POOLCOLL_TOX_IDX1 && nPoolId <= RES_POOLCOLL_TOX_IDX3) ||
16013e17677fSLászló Németh         (nPoolId >= RES_POOLCOLL_TOX_USER1 && nPoolId <= RES_POOLCOLL_TOX_CNTNT10) ||
16023e17677fSLászló Németh         nPoolId == RES_POOLCOLL_TOX_ILLUS1 || nPoolId == RES_POOLCOLL_TOX_TABLES1 ||
16033e17677fSLászló Németh         nPoolId == RES_POOLCOLL_TOX_OBJECT1 ||
16043e17677fSLászló Németh         (nPoolId >= RES_POOLCOLL_TOX_AUTHORITIES1 && nPoolId <= RES_POOLCOLL_TOX_USER10))) {
16051927b519SNoel Grandin              size_t i = rStr.rfind('\t');
16063e17677fSLászló Németh              // there are only ASCII (Latin-1) characters after the tabulator
16071927b519SNoel Grandin              if (i != std::u16string_view::npos && OUStringToOString(rStr.substr(i + 1), RTL_TEXTENCODING_ASCII_US).indexOf('?') == -1)
16083e17677fSLászló Németh                  return i;
16093e17677fSLászló Németh     }
16103e17677fSLászló Németh     return -1;
16113e17677fSLászló Németh }
16123e17677fSLászló Németh 
normalizeURL(const OUString & url,bool own) const16134be345abSMike Kaganski OUString SwHTMLWriter::normalizeURL(const OUString& url, bool own) const
16144be345abSMike Kaganski {
16154be345abSMike Kaganski     OUString ret(url);
16164be345abSMike Kaganski     if (HTMLOutFuncs::PrivateURLToInternalImg(ret))
16174be345abSMike Kaganski         return ret;
16184be345abSMike Kaganski     OUString base;
16194be345abSMike Kaganski     if (!mpTempBaseURL)
16204be345abSMike Kaganski         base = GetBaseURL();
16214be345abSMike Kaganski     else if (own && m_bRelativeURLsForOwnObjects && GetOrigFileName())
16224be345abSMike Kaganski         base = *GetOrigFileName();
16234be345abSMike Kaganski     if (!base.isEmpty())
16244be345abSMike Kaganski         ret = URIHelper::simpleNormalizedMakeRelative(base, ret);
16254be345abSMike Kaganski     return ret;
16264be345abSMike Kaganski }
16274be345abSMike Kaganski 
1628c2511f27SJens Carl // Structure caches the current data of the writer to output a
1629c2511f27SJens Carl // other part of the document, like e.g. header/footer
HTMLSaveData(SwHTMLWriter & rWriter,SwNodeOffset nStt,SwNodeOffset nEnd,bool bSaveNum,const SwFrameFormat * pFrameFormat)16305f9ffc31SNoel Grandin HTMLSaveData::HTMLSaveData(SwHTMLWriter& rWriter, SwNodeOffset nStt,
16315f9ffc31SNoel Grandin                            SwNodeOffset nEnd, bool bSaveNum,
1632ab465b90SChristian Lohmaier                            const SwFrameFormat *pFrameFormat)
16336dbe8335SCaolán McNamara     : rWrt(rWriter)
1634266e58d2SMiklos Vajna     , pOldPam(rWrt.m_pCurrentPam)
16356dbe8335SCaolán McNamara     , pOldEnd(rWrt.GetEndPaM())
1636b46496c4SMiklos Vajna     , nOldDefListLvl(rWrt.m_nDefListLvl)
1637b46496c4SMiklos Vajna     , nOldDirection(rWrt.m_nDirection)
1638b46496c4SMiklos Vajna     , bOldOutHeader(rWrt.m_bOutHeader)
1639b46496c4SMiklos Vajna     , bOldOutFooter(rWrt.m_bOutFooter)
1640b46496c4SMiklos Vajna     , bOldOutFlyFrame(rWrt.m_bOutFlyFrame)
16417b0b5cdfSJens-Heiner Rechtien {
1642266e58d2SMiklos Vajna     bOldWriteAll = rWrt.m_bWriteAll;
16437b0b5cdfSJens-Heiner Rechtien 
16443c367de9SMichael Stahl     rWrt.m_pCurrentPam = Writer::NewUnoCursor(*rWrt.m_pDoc, nStt, nEnd);
16457b0b5cdfSJens-Heiner Rechtien 
1646c2511f27SJens Carl     // recognize table in special areas
1647961d42e1SNoel Grandin     if( nStt != rWrt.m_pCurrentPam->GetMark()->GetNodeIndex() )
16487b0b5cdfSJens-Heiner Rechtien     {
1649266e58d2SMiklos Vajna         const SwNode *pNd = rWrt.m_pDoc->GetNodes()[ nStt ];
16507b0b5cdfSJens-Heiner Rechtien         if( pNd->IsTableNode() || pNd->IsSectionNode() )
16510df94183SNoel Grandin             rWrt.m_pCurrentPam->GetMark()->Assign(*pNd);
16527b0b5cdfSJens-Heiner Rechtien     }
16537b0b5cdfSJens-Heiner Rechtien 
16543c367de9SMichael Stahl     rWrt.SetEndPaM( rWrt.m_pCurrentPam.get() );
1655266e58d2SMiklos Vajna     rWrt.m_pCurrentPam->Exchange( );
1656266e58d2SMiklos Vajna     rWrt.m_bWriteAll = true;
1657b46496c4SMiklos Vajna     rWrt.m_nDefListLvl = 0;
1658b46496c4SMiklos Vajna     rWrt.m_bOutHeader = rWrt.m_bOutFooter = false;
16597b0b5cdfSJens-Heiner Rechtien 
1660c2511f27SJens Carl     // Maybe save the current numbering information, so that it can be started again.
1661c2511f27SJens Carl     // Only then also the numbering information of the next paragraph will be valid.
16627b0b5cdfSJens-Heiner Rechtien     if( bSaveNum )
16637b0b5cdfSJens-Heiner Rechtien     {
1664dba5dccfSNoel Grandin         pOldNumRuleInfo.reset( new SwHTMLNumRuleInfo( rWrt.GetNumInfo() ) );
1665011c6c71SNoel Grandin         pOldNextNumRuleInfo = rWrt.ReleaseNextNumInfo();
16667b0b5cdfSJens-Heiner Rechtien     }
16677b0b5cdfSJens-Heiner Rechtien     else
16687b0b5cdfSJens-Heiner Rechtien     {
16697b0b5cdfSJens-Heiner Rechtien         rWrt.ClearNextNumInfo();
16707b0b5cdfSJens-Heiner Rechtien     }
16717b0b5cdfSJens-Heiner Rechtien 
1672c2511f27SJens Carl     // The numbering will be in any case interrupted.
16737b0b5cdfSJens-Heiner Rechtien     rWrt.GetNumInfo().Clear();
1674b13f6ea1SMichael Brauer 
1675ab465b90SChristian Lohmaier     if( pFrameFormat )
1676b46496c4SMiklos Vajna         rWrt.m_nDirection = rWrt.GetHTMLDirection( pFrameFormat->GetAttrSet() );
16777b0b5cdfSJens-Heiner Rechtien }
16787b0b5cdfSJens-Heiner Rechtien 
~HTMLSaveData()16797b0b5cdfSJens-Heiner Rechtien HTMLSaveData::~HTMLSaveData()
16807b0b5cdfSJens-Heiner Rechtien {
16813c367de9SMichael Stahl     rWrt.m_pCurrentPam.reset(); // delete PaM again
16827b0b5cdfSJens-Heiner Rechtien 
1683266e58d2SMiklos Vajna     rWrt.m_pCurrentPam = pOldPam;
16847b0b5cdfSJens-Heiner Rechtien     rWrt.SetEndPaM( pOldEnd );
1685266e58d2SMiklos Vajna     rWrt.m_bWriteAll = bOldWriteAll;
1686b46496c4SMiklos Vajna     rWrt.m_nBkmkTabPos = bOldWriteAll ? rWrt.FindPos_Bkmk( *pOldPam->GetPoint() ) : -1;
168757f1934bSNoel Grandin     rWrt.m_nLastParaToken = HtmlTokenId::NONE;
1688b46496c4SMiklos Vajna     rWrt.m_nDefListLvl = nOldDefListLvl;
1689b46496c4SMiklos Vajna     rWrt.m_nDirection = nOldDirection;
1690b46496c4SMiklos Vajna     rWrt.m_bOutHeader = bOldOutHeader;
1691b46496c4SMiklos Vajna     rWrt.m_bOutFooter = bOldOutFooter;
1692b46496c4SMiklos Vajna     rWrt.m_bOutFlyFrame = bOldOutFlyFrame;
16937b0b5cdfSJens-Heiner Rechtien 
1694c2511f27SJens Carl     // Maybe continue the numbering from before section. The numbering
1695c2511f27SJens Carl     // of the next paragraph will be invalid in any case.
16967b0b5cdfSJens-Heiner Rechtien     if( pOldNumRuleInfo )
16977b0b5cdfSJens-Heiner Rechtien     {
16987b0b5cdfSJens-Heiner Rechtien         rWrt.GetNumInfo().Set( *pOldNumRuleInfo );
1699dba5dccfSNoel Grandin         pOldNumRuleInfo.reset();
1700011c6c71SNoel Grandin         rWrt.SetNextNumInfo( std::move(pOldNextNumRuleInfo) );
17017b0b5cdfSJens-Heiner Rechtien     }
17027b0b5cdfSJens-Heiner Rechtien     else
17037b0b5cdfSJens-Heiner Rechtien     {
17047b0b5cdfSJens-Heiner Rechtien         rWrt.GetNumInfo().Clear();
17057b0b5cdfSJens-Heiner Rechtien         rWrt.ClearNextNumInfo();
17067b0b5cdfSJens-Heiner Rechtien     }
17077b0b5cdfSJens-Heiner Rechtien }
17087b0b5cdfSJens-Heiner Rechtien 
GetHTMLWriter(std::u16string_view rFilterOptions,const OUString & rBaseURL,WriterRef & xRet)17095de24375SNoel Grandin void GetHTMLWriter( std::u16string_view rFilterOptions, const OUString& rBaseURL, WriterRef& xRet )
17107b0b5cdfSJens-Heiner Rechtien {
1711ff90a487SAshod Nakashian     xRet = new SwHTMLWriter( rBaseURL, rFilterOptions );
17127b0b5cdfSJens-Heiner Rechtien }
17137b0b5cdfSJens-Heiner Rechtien 
171461355e51SSebastian Spaeth /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1715