1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <hintids.hxx>
22 #include <comphelper/string.hxx>
23 #include <svl/urihelper.hxx>
24 #include <rtl/tencinfo.h>
25 #include <vcl/wrkwin.hxx>
26 #include <sfx2/linkmgr.hxx>
28 #include <svtools/htmlcfg.hxx>
29 #include <vcl/svapp.hxx>
30 #include <i18nlangtag/languagetag.hxx>
31 #include <sfx2/frmhtmlw.hxx>
32 #include <svx/xoutbmp.hxx>
33 #include <svx/unobrushitemhelper.hxx>
34 #include <sfx2/htmlmode.hxx>
35 #include <editeng/lrspitem.hxx>
36 #include <editeng/colritem.hxx>
37 #include <editeng/brushitem.hxx>
38 #include <editeng/fontitem.hxx>
39 #include <editeng/scripttypeitem.hxx>
40 #include <editeng/langitem.hxx>
41 #include <svl/stritem.hxx>
42 #include <editeng/frmdiritem.hxx>
44 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
45 #include <com/sun/star/document/XDocumentProperties.hpp>
46 #include <com/sun/star/form/XFormsSupplier.hpp>
47 #include <com/sun/star/form/XForm.hpp>
48 #include <com/sun/star/form/XImageProducerSupplier.hpp>
49 #include <com/sun/star/form/XFormController.hpp>
50 #include <com/sun/star/container/XContainer.hpp>
51 #include <com/sun/star/container/XIndexContainer.hpp>
52 #include <com/sun/star/container/XSet.hpp>
53 #include <fmthdft.hxx>
55 #include <fmtpdsc.hxx>
56 #include <txatbase.hxx>
58 #include <charfmt.hxx>
65 #include <viewopt.hxx>
67 #include <poolfmt.hxx>
68 #include <pagedesc.hxx>
69 #include <section.hxx>
70 #include <swtable.hxx>
72 #include <fmtclds.hxx>
74 #include <wrthtml.hxx>
75 #include <htmlnum.hxx>
76 #include <htmlfly.hxx>
77 #include <swmodule.hxx>
78 #include <statstr.hrc>
80 #include <rtl/strbuf.hxx>
81 #include <IDocumentSettingAccess.hxx>
82 #include <IDocumentStylePoolAccess.hxx>
83 #include <xmloff/odffields.hxx>
84 #include <tools/urlobj.hxx>
86 #define MAX_INDENT_LEVEL 20
90 static sal_Char sIndentTabs
[MAX_INDENT_LEVEL
+2] =
91 "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
93 SwHTMLWriter::SwHTMLWriter( const OUString
& rBaseURL
)
94 : m_pHTMLPosFlyFrames(nullptr)
95 , m_pNumRuleInfo(new SwHTMLNumRuleInfo
)
96 , m_pNextNumRuleInfo(nullptr)
98 , m_eCSS1Unit(FUNIT_NONE
)
99 , m_pFootEndNotes(nullptr)
101 , m_pTemplate(nullptr)
102 , m_pDfltColor(nullptr)
103 , m_pStartNdIdx(nullptr)
104 , m_pCurrPageDesc(nullptr)
105 , m_pFormatFootnote(nullptr)
108 , m_nLastParaToken(0)
115 , m_nDfltLeftMargin(0)
116 , m_nDfltRightMargin(0)
117 , m_nFirstLineIndent(0)
118 , m_nDfltFirstLineIndent(0)
119 , m_nDfltTopMargin(0)
120 , m_nDfltBottomMargin(0)
124 , m_nDefListMargin(0)
125 , m_nHeaderFooterSpace(0)
126 , m_nTextAttrsToIgnore(0)
129 , m_nCSS1Script(CSS1_OUTMODE_WESTERN
)
130 , m_nDirection(FRMDIR_HORI_LEFT_TOP
)
131 , m_eDestEnc(RTL_TEXTENCODING_MS_1252
)
132 , m_eLang(LANGUAGE_DONTKNOW
)
133 , m_bCfgOutStyles( false )
134 , m_bCfgPreferStyles( false )
135 , m_bCfgFormFeed( false )
136 , m_bCfgStarBasic( false )
137 , m_bCfgCpyLinkedGrfs( false )
140 , m_bTextAttr( false )
141 , m_bOutOpts( false )
142 , m_bOutTable( false )
143 , m_bOutHeader( false )
144 , m_bOutFooter( false )
145 , m_bOutFlyFrame( false )
146 , m_bFirstCSS1Rule( false )
147 , m_bFirstCSS1Property( false )
148 , m_bPoolCollTextModified( false )
149 , m_bCSS1IgnoreFirstPageDesc( false )
150 , m_bNoAlign( false )
151 , m_bClearLeft( false )
152 , m_bClearRight( false )
153 , m_bLFPossible( false )
154 , m_bPreserveForm( false )
155 , m_bCfgNetscape4( false )
156 , mbSkipImages(false)
157 , mbSkipHeaderFooter(false)
158 , mbEmbedImages(false)
159 , m_bCfgPrintLayout( false )
160 , m_bParaDotLeaders( false )
162 SetBaseURL(rBaseURL
);
165 SwHTMLWriter::~SwHTMLWriter()
167 delete m_pNumRuleInfo
;
170 void SwHTMLWriter::SetupFilterOptions(SfxMedium
& rMedium
)
172 const SfxItemSet
* pSet
= rMedium
.GetItemSet();
176 const SfxPoolItem
* pItem
;
177 if (pSet
->GetItemState( SID_FILE_FILTEROPTIONS
, true, &pItem
) != SfxItemState::SET
)
181 OUString sFilterOptions
= static_cast<const SfxStringItem
*>(pItem
)->GetValue();
182 if (sFilterOptions
== "SkipImages")
186 else if (sFilterOptions
== "SkipHeaderFooter")
188 mbSkipHeaderFooter
= true;
190 else if (sFilterOptions
== "EmbedImages" )
192 mbEmbedImages
= true;
196 sal_uLong
SwHTMLWriter::WriteStream()
198 SvxHtmlOptions
& rHtmlOptions
= SvxHtmlOptions::Get();
201 m_aFontHeights
[0] = rHtmlOptions
.GetFontSize( 0 ) * 20;
202 m_aFontHeights
[1] = rHtmlOptions
.GetFontSize( 1 ) * 20;
203 m_aFontHeights
[2] = rHtmlOptions
.GetFontSize( 2 ) * 20;
204 m_aFontHeights
[3] = rHtmlOptions
.GetFontSize( 3 ) * 20;
205 m_aFontHeights
[4] = rHtmlOptions
.GetFontSize( 4 ) * 20;
206 m_aFontHeights
[5] = rHtmlOptions
.GetFontSize( 5 ) * 20;
207 m_aFontHeights
[6] = rHtmlOptions
.GetFontSize( 6 ) * 20;
209 // ueberhaupt Styles ausgeben
210 // (dann auch obere und untere Absatz-Abstaende)
211 m_nExportMode
= rHtmlOptions
.GetExportMode();
212 m_nHTMLMode
= GetHtmlMode(nullptr);
214 if( HTML_CFG_WRITER
== m_nExportMode
|| HTML_CFG_NS40
== m_nExportMode
)
215 m_nHTMLMode
|= HTMLMODE_BLOCK_SPACER
;
217 if( HTML_CFG_WRITER
== m_nExportMode
|| HTML_CFG_MSIE
== m_nExportMode
)
218 m_nHTMLMode
|= (HTMLMODE_FLOAT_FRAME
| HTMLMODE_LSPACE_IN_NUMBUL
);
220 if( HTML_CFG_MSIE
== m_nExportMode
)
221 m_nHTMLMode
|= HTMLMODE_NBSP_IN_TABLES
;
223 if( HTML_CFG_WRITER
== m_nExportMode
|| HTML_CFG_NS40
== m_nExportMode
|| HTML_CFG_MSIE
== m_nExportMode
)
224 m_nHTMLMode
|= HTMLMODE_ABS_POS_FLY
| HTMLMODE_ABS_POS_DRAW
;
226 if( HTML_CFG_WRITER
== m_nExportMode
)
227 m_nHTMLMode
|= HTMLMODE_FLY_MARGINS
;
229 if( HTML_CFG_NS40
== m_nExportMode
)
230 m_nHTMLMode
|= HTMLMODE_BORDER_NONE
;
232 m_nHTMLMode
|= HTMLMODE_FONT_GENERIC
;
234 if( HTML_CFG_NS40
==m_nExportMode
)
235 m_nHTMLMode
|= HTMLMODE_NO_CONTROL_CENTERING
;
237 m_bCfgOutStyles
= IsHTMLMode(HTMLMODE_SOME_STYLES
| HTMLMODE_FULL_STYLES
);
238 m_bCfgNetscape4
= (HTML_CFG_NS40
== m_nExportMode
);
240 if( IsHTMLMode(HTMLMODE_SOME_STYLES
| HTMLMODE_FULL_STYLES
) )
241 m_nHTMLMode
|= HTMLMODE_PRINT_EXT
;
243 const sal_Char
*pHelpHack
= getenv( "HelpEx" );
246 OString
aTmp(pHelpHack
);
247 if (aTmp
.equalsIgnoreAsciiCase("Hilfe"))
248 m_nHTMLMode
|= HTMLMODE_NO_BR_AT_PAREND
;
251 m_eCSS1Unit
= (FieldUnit
)SW_MOD()->GetMetric( pDoc
->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE
) );
253 bool bWriteUTF8
= bWriteClipboardDoc
;
254 m_eDestEnc
= bWriteUTF8
? RTL_TEXTENCODING_UTF8
: rHtmlOptions
.GetTextEncoding();
255 const sal_Char
*pCharSet
= rtl_getBestMimeCharsetFromTextEncoding( m_eDestEnc
);
256 m_eDestEnc
= rtl_getTextEncodingFromMimeCharset( pCharSet
);
258 // Nur noch fuer den MS-IE ziehen wir den Export von Styles vor.
259 m_bCfgPreferStyles
= HTML_CFG_MSIE
== m_nExportMode
;
261 m_bCfgStarBasic
= rHtmlOptions
.IsStarBasic();
263 m_bCfgFormFeed
= !IsHTMLMode(HTMLMODE_PRINT_EXT
);
264 m_bCfgCpyLinkedGrfs
= rHtmlOptions
.IsSaveGraphicsLocal();
266 m_bCfgPrintLayout
= rHtmlOptions
.IsPrintLayoutExtension();
268 // die HTML-Vorlage holen
269 bool bOldHTMLMode
= false;
270 SwTextFormatColls::size_type nOldTextFormatCollCnt
= 0;
271 SwCharFormats::size_type nOldCharFormatCnt
= 0;
273 OSL_ENSURE( !m_pTemplate
, "Wo kommt denn die HTML-Vorlage hier her?" );
274 m_pTemplate
= static_cast<HTMLReader
*>(ReadHTML
)->GetTemplateDoc();
277 m_pTemplate
->acquire();
278 bOldHTMLMode
= m_pTemplate
->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE
);
279 m_pTemplate
->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE
, true);
281 nOldTextFormatCollCnt
= m_pTemplate
->GetTextFormatColls()->size();
282 nOldCharFormatCnt
= m_pTemplate
->GetCharFormats()->size();
286 ::StartProgress( STR_STATSTR_W4WWRITE
, 0, pDoc
->GetNodes().Count(),
287 pDoc
->GetDocShell());
289 m_pDfltColor
= nullptr;
290 m_pFootEndNotes
= nullptr;
291 m_pFormatFootnote
= nullptr;
292 m_bOutTable
= m_bOutHeader
= m_bOutFooter
= m_bOutFlyFrame
= false;
295 m_bPreserveForm
= false;
296 m_bClearLeft
= m_bClearRight
= false;
297 m_bLFPossible
= false;
299 m_nLeftMargin
= m_nDfltLeftMargin
= m_nDfltRightMargin
= 0;
300 m_nDfltTopMargin
= m_nDfltBottomMargin
= 0;
301 m_nFirstLineIndent
= m_nDfltFirstLineIndent
= 0;
302 m_bPoolCollTextModified
= false;
303 m_bFirstCSS1Property
= m_bFirstCSS1Rule
= false;
304 m_bCSS1IgnoreFirstPageDesc
= false;
306 m_nWhishLineLen
= 70;
309 m_nDefListMargin
= ((m_pTemplate
&& !m_bCfgOutStyles
) ? m_pTemplate
: pDoc
)
310 ->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_HTML_DD
, false )
311 ->GetLRSpace().GetTextLeft();
312 m_nHeaderFooterSpace
= 0;
313 m_nTextAttrsToIgnore
= 0;
315 SvtScriptType nScript
= SvtLanguageOptions::GetScriptTypeOfLanguage( GetAppLanguage() );
318 case SvtScriptType::ASIAN
:
319 m_nCSS1Script
= CSS1_OUTMODE_CJK
;
321 case SvtScriptType::COMPLEX
:
322 m_nCSS1Script
= CSS1_OUTMODE_CTL
;
325 m_nCSS1Script
= CSS1_OUTMODE_WESTERN
;
328 m_eLang
= static_cast<const SvxLanguageItem
&>(pDoc
329 ->GetDefault(GetLangWhichIdFromScript(m_nCSS1Script
))).GetLanguage();
331 m_nFootNote
= m_nEndNote
= 0;
334 GetNumInfo().Clear();
335 m_pNextNumRuleInfo
= nullptr;
339 // respect table and section at document beginning
341 SwTableNode
* pTNd
= pCurPam
->GetNode().FindTableNode();
342 if( pTNd
&& bWriteAll
)
344 // mit dem Tabellen-Node anfangen !!
345 pCurPam
->GetPoint()->nNode
= *pTNd
;
347 if( bWriteOnlyFirstTable
)
348 pCurPam
->GetMark()->nNode
= *pTNd
->EndOfSectionNode();
351 // erster Node (der einen Seitenumbruch enthalten darf)
352 m_pStartNdIdx
= new SwNodeIndex( pCurPam
->GetPoint()->nNode
);
354 SwSectionNode
* pSNd
= pCurPam
->GetNode().FindSectionNode();
359 // mit dem Section-Node anfangen !!
360 pCurPam
->GetPoint()->nNode
= *pSNd
;
364 OSL_ENSURE( FILE_LINK_SECTION
!= pSNd
->GetSection().GetType(),
365 "Export gelinkter Bereiche am Dok-Anfang ist nicht implemntiert" );
367 // nur das Tag fuer die Section merken
368 OString aName
= HTMLOutFuncs::ConvertStringToHTML(
369 pSNd
->GetSection().GetSectionName(), m_eDestEnc
,
370 &m_aNonConvertableCharacters
);
373 sOut
.append('<').append(OOO_STRING_SVTOOLS_HTML_division
)
374 .append(' ').append(OOO_STRING_SVTOOLS_HTML_O_id
)
375 .append("=\"").append(aName
).append('\"').append('>')
377 aStartTags
= sOut
.makeStringAndClear();
379 // FindSectionNode() an einem SectionNode liefert den selben!
380 pSNd
= pSNd
->StartOfSectionNode()->FindSectionNode();
384 // Tabelle fuer die freifliegenden Rahmen erzeugen, aber nur wenn
385 // das gesamte Dokument geschrieben wird
386 m_pHTMLPosFlyFrames
= nullptr;
388 m_nLastParaToken
= 0;
390 CollectLinkTargets();
392 sal_uInt16 nHeaderAttrs
= 0;
393 m_pCurrPageDesc
= MakeHeader( nHeaderAttrs
);
395 m_bLFPossible
= true;
397 // Formulare, die nur HiddenControls enthalten ausgeben.
400 if( !aStartTags
.isEmpty() )
401 Strm().WriteCharPtr( aStartTags
.getStr() );
403 const SfxPoolItem
*pItem
;
404 const SfxItemSet
& rPageItemSet
= m_pCurrPageDesc
->GetMaster().GetAttrSet();
405 if( !bWriteClipboardDoc
&& pDoc
->GetDocShell() &&
406 (!pDoc
->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE
) &&
407 !pDoc
->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE
)) &&
408 SfxItemState::SET
== rPageItemSet
.GetItemState( RES_HEADER
, true, &pItem
) )
410 const SwFrameFormat
*pHeaderFormat
=
411 static_cast<const SwFormatHeader
*>(pItem
)->GetHeaderFormat();
413 OutHTML_HeaderFooter( *this, *pHeaderFormat
, true );
416 m_nTextAttrsToIgnore
= nHeaderAttrs
;
417 Out_SwDoc( pOrigPam
);
418 m_nTextAttrsToIgnore
= 0;
420 if( mxFormComps
.is() )
421 OutForm( false, mxFormComps
);
423 if( m_pFootEndNotes
)
426 if( !bWriteClipboardDoc
&& pDoc
->GetDocShell() &&
427 (!pDoc
->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE
) && !pDoc
->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE
)) &&
428 SfxItemState::SET
== rPageItemSet
.GetItemState( RES_FOOTER
, true, &pItem
) )
430 const SwFrameFormat
*pFooterFormat
=
431 static_cast<const SwFormatFooter
*>(pItem
)->GetFooterFormat();
433 OutHTML_HeaderFooter( *this, *pFooterFormat
, false );
438 if (!mbSkipHeaderFooter
)
440 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_body
, false );
442 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html
, false );
445 // loesche die Tabelle mit den freifliegenden Rahmen
446 OSL_ENSURE( !m_pHTMLPosFlyFrames
, "Wurden nicht alle Rahmen ausgegeben" );
447 if( m_pHTMLPosFlyFrames
)
449 m_pHTMLPosFlyFrames
->DeleteAndDestroyAll();
450 delete m_pHTMLPosFlyFrames
;
451 m_pHTMLPosFlyFrames
= nullptr;
454 m_aHTMLControls
.DeleteAndDestroyAll();
456 if (!m_CharFormatInfos
.empty())
457 m_CharFormatInfos
.clear();
459 if (!m_TextCollInfos
.empty())
460 m_TextCollInfos
.clear();
462 if(!m_aImgMapNames
.empty())
463 m_aImgMapNames
.clear();
465 m_aImplicitMarks
.clear();
467 m_aOutlineMarks
.clear();
469 m_aOutlineMarkPoss
.clear();
471 m_aNumRuleNames
.clear();
473 m_aScriptParaStyles
.clear();
474 m_aScriptTextStyles
.clear();
477 m_pDfltColor
= nullptr;
479 delete m_pStartNdIdx
;
480 m_pStartNdIdx
= nullptr;
484 OSL_ENSURE( !m_pFootEndNotes
,
485 "SwHTMLWriter::Write: Footnotes nicht durch OutFootEndNotes geloescht" );
487 m_pCurrPageDesc
= nullptr;
491 for(OUString
& s
: m_aBulletGrfs
)
494 m_aNonConvertableCharacters
.clear();
497 ::EndProgress( pDoc
->GetDocShell() );
501 // Waehrend des Exports angelegte Zeichen- und Abastzvorlagen
503 auto nTextFormatCollCnt
= m_pTemplate
->GetTextFormatColls()->size();
504 while( nTextFormatCollCnt
> nOldTextFormatCollCnt
)
505 m_pTemplate
->DelTextFormatColl( --nTextFormatCollCnt
);
506 OSL_ENSURE( m_pTemplate
->GetTextFormatColls()->size() == nOldTextFormatCollCnt
,
507 "falsche Anzahl TextFormatColls geloescht" );
509 auto nCharFormatCnt
= m_pTemplate
->GetCharFormats()->size();
510 while( nCharFormatCnt
> nOldCharFormatCnt
)
511 m_pTemplate
->DelCharFormat( --nCharFormatCnt
);
512 OSL_ENSURE( m_pTemplate
->GetCharFormats()->size() == nOldCharFormatCnt
,
513 "falsche Anzahl CharFormats geloescht" );
515 // HTML-Modus wieder restaurieren
516 m_pTemplate
->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE
, bOldHTMLMode
);
518 if( 0 == m_pTemplate
->release() )
521 m_pTemplate
= nullptr;
527 static const SwFormatCol
*lcl_html_GetFormatCol( const SwSection
& rSection
,
528 const SwSectionFormat
& rFormat
)
530 const SwFormatCol
*pCol
= nullptr;
532 const SfxPoolItem
* pItem
;
533 if( FILE_LINK_SECTION
!= rSection
.GetType() &&
534 SfxItemState::SET
== rFormat
.GetAttrSet().GetItemState(RES_COL
,false,&pItem
) &&
535 static_cast<const SwFormatCol
*>(pItem
)->GetNumCols() > 1 )
537 pCol
= static_cast<const SwFormatCol
*>(pItem
);
543 static bool lcl_html_IsMultiColStart( const SwHTMLWriter
& rHTMLWrt
, sal_uLong nIndex
)
546 const SwSectionNode
*pSectNd
=
547 rHTMLWrt
.pDoc
->GetNodes()[nIndex
]->GetSectionNode();
550 const SwSection
& rSection
= pSectNd
->GetSection();
551 const SwSectionFormat
*pFormat
= rSection
.GetFormat();
552 if( pFormat
&& lcl_html_GetFormatCol( rSection
, *pFormat
) )
559 static bool lcl_html_IsMultiColEnd( const SwHTMLWriter
& rHTMLWrt
, sal_uLong nIndex
)
562 const SwEndNode
*pEndNd
= rHTMLWrt
.pDoc
->GetNodes()[nIndex
]->GetEndNode();
564 bRet
= lcl_html_IsMultiColStart( rHTMLWrt
,
565 pEndNd
->StartOfSectionIndex() );
570 static void lcl_html_OutSectionStartTag( SwHTMLWriter
& rHTMLWrt
,
571 const SwSection
& rSection
,
572 const SwSectionFormat
& rFormat
,
573 const SwFormatCol
*pCol
,
574 bool bContinued
=false )
576 OSL_ENSURE( pCol
|| !bContinued
, "Continuation of DIV" );
578 if( rHTMLWrt
.m_bLFPossible
)
579 rHTMLWrt
.OutNewLine();
582 sOut
.append('<').append(OOO_STRING_SVTOOLS_HTML_division
);
584 const OUString
& rName
= rSection
.GetSectionName();
585 if( !rName
.isEmpty() && !bContinued
)
587 sOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_id
"=\"");
588 rHTMLWrt
.Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
589 HTMLOutFuncs::Out_String( rHTMLWrt
.Strm(), rName
, rHTMLWrt
.m_eDestEnc
, &rHTMLWrt
.m_aNonConvertableCharacters
);
593 sal_uInt16 nDir
= rHTMLWrt
.GetHTMLDirection( rFormat
.GetAttrSet() );
594 rHTMLWrt
.Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
595 rHTMLWrt
.OutDirection( nDir
);
597 if( FILE_LINK_SECTION
== rSection
.GetType() )
599 sOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_href
"=\"");
600 rHTMLWrt
.Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
602 const OUString
& aFName
= rSection
.GetLinkFileName();
603 OUString
aURL( aFName
.getToken(0,sfx2::cTokenSeparator
) );
604 OUString
aFilter( aFName
.getToken(1,sfx2::cTokenSeparator
) );
605 OUString
aSection( aFName
.getToken(2,sfx2::cTokenSeparator
) );
607 OUString
aEncURL( URIHelper::simpleNormalizedMakeRelative(rHTMLWrt
.GetBaseURL(), aURL
) );
608 sal_Unicode cDelim
= 255U;
609 bool bURLContainsDelim
= (-1 != aEncURL
.indexOf( cDelim
) );
611 HTMLOutFuncs::Out_String( rHTMLWrt
.Strm(), aEncURL
,
613 &rHTMLWrt
.m_aNonConvertableCharacters
);
614 const sal_Char
* pDelim
= "ÿ";
615 if( !aFilter
.isEmpty() || !aSection
.isEmpty() || bURLContainsDelim
)
616 rHTMLWrt
.Strm().WriteCharPtr( pDelim
);
617 if( !aFilter
.isEmpty() )
618 HTMLOutFuncs::Out_String( rHTMLWrt
.Strm(), aFilter
, rHTMLWrt
.m_eDestEnc
, &rHTMLWrt
.m_aNonConvertableCharacters
);
619 if( !aSection
.isEmpty() || bURLContainsDelim
)
620 rHTMLWrt
.Strm().WriteCharPtr( pDelim
);
621 if( !aSection
.isEmpty() )
623 sal_Int32 nPos
= aSection
.indexOf( '%' );
626 aSection
= aSection
.replaceAt(nPos
, 1, "%25");
627 nPos
= aSection
.indexOf( '%', nPos
+3 );
629 nPos
= aSection
.indexOf( cDelim
);
632 aSection
= aSection
.replaceAt(nPos
, 1, "%FF" );
633 nPos
= aSection
.indexOf( cDelim
, nPos
+3 );
635 HTMLOutFuncs::Out_String( rHTMLWrt
.Strm(), aSection
,
636 rHTMLWrt
.m_eDestEnc
, &rHTMLWrt
.m_aNonConvertableCharacters
);
642 // minimum gutter width
643 sal_uInt16 nGutter
= pCol
->GetGutterWidth( true );
644 if( nGutter
!=USHRT_MAX
)
646 if( nGutter
&& Application::GetDefaultDevice() )
648 nGutter
= (sal_uInt16
)Application::GetDefaultDevice()
649 ->LogicToPixel( Size(nGutter
, 0), MapMode(MapUnit::MapTwip
) ).Width();
651 sOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_gutter
"=\"" + OString::number(nGutter
) + "\"");
655 rHTMLWrt
.Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
656 if( rHTMLWrt
.IsHTMLMode( rHTMLWrt
.m_bCfgOutStyles
? HTMLMODE_ON
: 0 ) )
657 rHTMLWrt
.OutCSS1_SectionFormatOptions( rFormat
, pCol
);
659 rHTMLWrt
.Strm().WriteChar( '>' );
661 rHTMLWrt
.m_bLFPossible
= true;
662 if( !rName
.isEmpty() && !bContinued
)
663 rHTMLWrt
.OutImplicitMark( rName
, "region" );
665 rHTMLWrt
.IncIndentLevel();
668 static void lcl_html_OutSectionEndTag( SwHTMLWriter
& rHTMLWrt
)
670 rHTMLWrt
.DecIndentLevel();
671 if( rHTMLWrt
.m_bLFPossible
)
672 rHTMLWrt
.OutNewLine();
673 HTMLOutFuncs::Out_AsciiTag( rHTMLWrt
.Strm(), OOO_STRING_SVTOOLS_HTML_division
, false );
674 rHTMLWrt
.m_bLFPossible
= true;
677 static Writer
& OutHTML_Section( Writer
& rWrt
, const SwSectionNode
& rSectNd
)
679 SwHTMLWriter
& rHTMLWrt
= static_cast<SwHTMLWriter
&>(rWrt
);
681 // End <PRE> and any <DL>, because a definition list's level may
682 // change inside the section.
683 rHTMLWrt
.ChangeParaToken( 0 );
684 rHTMLWrt
.OutAndSetDefList( 0 );
686 const SwSection
& rSection
= rSectNd
.GetSection();
687 const SwSectionFormat
*pFormat
= rSection
.GetFormat();
688 OSL_ENSURE( pFormat
, "Section without a format?" );
690 bool bStartTag
= true;
692 const SwSectionFormat
*pSurrFormat
= nullptr;
693 const SwSectionNode
*pSurrSectNd
= nullptr;
694 const SwSection
*pSurrSection
= nullptr;
695 const SwFormatCol
*pSurrCol
= nullptr;
697 sal_uInt32 nSectSttIdx
= rSectNd
.GetIndex();
698 sal_uInt32 nSectEndIdx
= rSectNd
.EndOfSectionIndex();
699 const SwFormatCol
*pCol
= lcl_html_GetFormatCol( rSection
, *pFormat
);
702 // If the next node is a columned section node, too, don't export
704 if( lcl_html_IsMultiColStart( rHTMLWrt
, nSectSttIdx
+1 ) )
707 // The same applies if the section end with another columned section.
708 if( lcl_html_IsMultiColEnd( rHTMLWrt
, nSectEndIdx
-1 ) )
711 //.is there a columned section around this one?
712 const SwStartNode
*pSttNd
= rSectNd
.StartOfSectionNode();
715 pSurrSectNd
= pSttNd
->FindSectionNode();
718 const SwStartNode
*pBoxSttNd
= pSttNd
->FindTableBoxStartNode();
720 pBoxSttNd
->GetIndex() < pSurrSectNd
->GetIndex() )
722 pSurrSection
= &pSurrSectNd
->GetSection();
723 pSurrFormat
= pSurrSection
->GetFormat();
725 pSurrCol
= lcl_html_GetFormatCol( *pSurrSection
,
732 // The surrounding section must be closed before the current one is
733 // opended, except that it start immediately before the current one or
734 // another end immediately before the current one
735 if( pSurrCol
&& nSectSttIdx
- pSurrSectNd
->GetIndex() > 1 &&
736 !lcl_html_IsMultiColEnd( rHTMLWrt
, nSectSttIdx
-1 ) )
737 lcl_html_OutSectionEndTag( rHTMLWrt
);
740 lcl_html_OutSectionStartTag( rHTMLWrt
, rSection
, *pFormat
, pCol
);
743 HTMLSaveData
aSaveData( rHTMLWrt
,
744 rHTMLWrt
.pCurPam
->GetPoint()->nNode
.GetIndex()+1,
745 rSectNd
.EndOfSectionIndex(),
747 rHTMLWrt
.Out_SwDoc( rHTMLWrt
.pCurPam
);
750 rHTMLWrt
.pCurPam
->GetPoint()->nNode
= *rSectNd
.EndOfSectionNode();
753 lcl_html_OutSectionEndTag( rHTMLWrt
);
755 // The surrounding section must be started again, except that it ends
756 // immeditaly behind the current one.
758 pSurrSectNd
->EndOfSectionIndex() - nSectEndIdx
> 1 &&
759 !lcl_html_IsMultiColStart( rHTMLWrt
, nSectEndIdx
+1 ) )
760 lcl_html_OutSectionStartTag( rHTMLWrt
, *pSurrSection
, *pSurrFormat
,
766 void SwHTMLWriter::Out_SwDoc( SwPaM
* pPam
)
768 bool bSaveWriteAll
= bWriteAll
; // sichern
770 // suche die naechste text::Bookmark-Position aus der text::Bookmark-Tabelle
771 m_nBkmkTabPos
= bWriteAll
? FindPos_Bkmk( *pCurPam
->GetPoint() ) : -1;
773 // gebe alle Bereiche des Pams in das HTML-File aus.
775 bWriteAll
= bSaveWriteAll
;
778 // suche den ersten am Pam-auszugebenen FlyFrame
781 while( pCurPam
->GetPoint()->nNode
.GetIndex() < pCurPam
->GetMark()->nNode
.GetIndex() ||
782 (pCurPam
->GetPoint()->nNode
.GetIndex() == pCurPam
->GetMark()->nNode
.GetIndex() &&
783 pCurPam
->GetPoint()->nContent
.GetIndex() <= pCurPam
->GetMark()->nContent
.GetIndex()) )
785 SwNode
& rNd
= pCurPam
->GetNode();
787 OSL_ENSURE( !(rNd
.IsGrfNode() || rNd
.IsOLENode()),
788 "Grf- oder OLE-Node hier unerwartet" );
789 if( rNd
.IsTextNode() )
791 SwTextNode
* pTextNd
= rNd
.GetTextNode();
794 pCurPam
->GetPoint()->nContent
.Assign( pTextNd
, 0 );
796 OutHTML_SwTextNode( *this, *pTextNd
);
798 else if( rNd
.IsTableNode() )
800 OutHTML_SwTableNode( *this, *rNd
.GetTableNode(), nullptr );
801 m_nBkmkTabPos
= bWriteAll
? FindPos_Bkmk( *pCurPam
->GetPoint() ) : -1;
803 else if( rNd
.IsSectionNode() )
805 OutHTML_Section( *this, *rNd
.GetSectionNode() );
806 m_nBkmkTabPos
= bWriteAll
? FindPos_Bkmk( *pCurPam
->GetPoint() ) : -1;
808 else if( &rNd
== &pDoc
->GetNodes().GetEndOfContent() )
811 ++pCurPam
->GetPoint()->nNode
; // Bewegen
812 sal_uInt32 nPos
= pCurPam
->GetPoint()->nNode
.GetIndex();
815 ::SetProgressState( nPos
, pDoc
->GetDocShell() ); // Wie weit ?
817 /* sollen nur die Selectierten Bereiche gesichert werden, so
818 * duerfen nur die vollstaendigen Nodes gespeichert werde,
819 * d.H. der 1. und n. Node teilweise, der 2. bis n-1. Node
820 * vollstaendig. (vollstaendig heisst mit allen Formaten! )
822 bWriteAll
= bSaveWriteAll
||
823 nPos
!= pCurPam
->GetMark()->nNode
.GetIndex();
824 m_bFirstLine
= false;
825 m_bOutFooter
= false; // Nach einem Node keine Fusszeile mehr
828 ChangeParaToken( 0 ); // MIB 8.7.97: Machen wir jetzt hier und nicht
830 OutAndSetDefList( 0 );
832 } while( CopyNextPam( &pPam
) ); // bis alle PaM's bearbeitet
834 bWriteAll
= bSaveWriteAll
; // wieder auf alten Wert zurueck
837 // schreibe die StyleTabelle, algemeine Angaben,Header/Footer/Footnotes
838 static void OutBodyColor( const sal_Char
* pTag
, const SwFormat
*pFormat
,
839 SwHTMLWriter
& rHWrt
)
841 const SwFormat
*pRefFormat
= nullptr;
843 if( rHWrt
.m_pTemplate
)
844 pRefFormat
= SwHTMLWriter::GetTemplateFormat( pFormat
->GetPoolFormatId(),
845 &rHWrt
.m_pTemplate
->getIDocumentStylePoolAccess() );
847 const SvxColorItem
*pColorItem
= nullptr;
849 const SfxItemSet
& rItemSet
= pFormat
->GetAttrSet();
850 const SfxPoolItem
*pRefItem
= nullptr, *pItem
= nullptr;
851 bool bItemSet
= SfxItemState::SET
== rItemSet
.GetItemState( RES_CHRATR_COLOR
,
853 bool bRefItemSet
= pRefFormat
&&
854 SfxItemState::SET
== pRefFormat
->GetAttrSet().GetItemState( RES_CHRATR_COLOR
,
858 // wenn das Item nur in der Vorlage des aktuellen Doks gesetzt
859 // ist oder einen anderen Wert hat, als in der HTML-Vorlage,
861 const SvxColorItem
*pCItem
= static_cast<const SvxColorItem
*>(pItem
);
869 Color
aColor( pCItem
->GetValue() );
870 if( COL_AUTO
== aColor
.GetColor() )
871 aColor
.SetColor( COL_BLACK
);
873 Color
aRefColor( static_cast<const SvxColorItem
*>(pRefItem
)->GetValue() );
874 if( COL_AUTO
== aRefColor
.GetColor() )
875 aRefColor
.SetColor( COL_BLACK
);
877 if( !aColor
.IsRGBEqual( aRefColor
) )
881 else if( bRefItemSet
)
883 // Das Item war in der HTML-Vorlage noch gesetzt, also geben wir
885 pColorItem
= static_cast<const SvxColorItem
*>(&rItemSet
.GetPool()
886 ->GetDefaultItem( RES_CHRATR_COLOR
));
892 sOut
.append(" " + OString(pTag
) + "=");
893 rHWrt
.Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
894 Color
aColor( pColorItem
->GetValue() );
895 if( COL_AUTO
== aColor
.GetColor() )
896 aColor
.SetColor( COL_BLACK
);
897 HTMLOutFuncs::Out_Color( rHWrt
.Strm(), aColor
, rHWrt
.m_eDestEnc
);
898 if( RES_POOLCOLL_STANDARD
==pFormat
->GetPoolFormatId() )
899 rHWrt
.m_pDfltColor
= new Color( aColor
);
903 sal_uInt16
SwHTMLWriter::OutHeaderAttrs()
905 sal_uLong nIdx
= pCurPam
->GetPoint()->nNode
.GetIndex();
906 sal_uLong nEndIdx
= pCurPam
->GetMark()->nNode
.GetIndex();
908 SwTextNode
*pTextNd
= nullptr;
909 while( nIdx
<=nEndIdx
&&
910 nullptr==(pTextNd
=pDoc
->GetNodes()[nIdx
]->GetTextNode()) )
913 OSL_ENSURE( pTextNd
, "Kein Text-Node gefunden" );
914 if( !pTextNd
|| !pTextNd
->HasHints() )
917 sal_uInt16 nAttrs
= 0;
918 const size_t nCntAttr
= pTextNd
->GetSwpHints().Count();
919 sal_Int32 nOldPos
= 0;
920 for( size_t i
=0; i
<nCntAttr
; ++i
)
922 const SwTextAttr
*pHt
= pTextNd
->GetSwpHints().Get(i
);
925 sal_Int32 nPos
= pHt
->GetStart();
927 || ( pHt
->Which() != RES_TXTATR_FIELD
928 && pHt
->Which() != RES_TXTATR_ANNOTATION
) )
931 const sal_uInt16 nFieldWhich
=
932 static_cast<const SwFormatField
&>(pHt
->GetAttr()).GetField()->GetTyp()->Which();
933 if( RES_POSTITFLD
!=nFieldWhich
&&
934 RES_SCRIPTFLD
!=nFieldWhich
)
938 OutHTML_SwFormatField( *this, pHt
->GetAttr() );
940 OSL_ENSURE( nAttrs
<SAL_MAX_UINT16
, "Too many attributes" );
948 const SwPageDesc
*SwHTMLWriter::MakeHeader( sal_uInt16
&rHeaderAttrs
)
951 if (!mbSkipHeaderFooter
)
953 sOut
.append(OOO_STRING_SVTOOLS_HTML_doctype
" " OOO_STRING_SVTOOLS_HTML_doctype40
);
954 HTMLOutFuncs::Out_AsciiTag( Strm(), sOut
.makeStringAndClear().getStr() );
958 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_html
);
961 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head
);
963 IncIndentLevel(); // Inhalt von <HEAD> einruecken
966 OString sIndent
= GetIndentString();
968 uno::Reference
<document::XDocumentProperties
> xDocProps
;
969 SwDocShell
*pDocShell(pDoc
->GetDocShell());
972 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
973 pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
974 xDocProps
.set(xDPS
->getDocumentProperties());
977 // xDocProps may be null here (when copying)
978 SfxFrameHTMLWriter::Out_DocInfo( Strm(), GetBaseURL(), xDocProps
,
979 sIndent
.getStr(), m_eDestEnc
,
980 &m_aNonConvertableCharacters
);
982 // Kommentare und Meta-Tags des ersten Absatzes
983 rHeaderAttrs
= OutHeaderAttrs();
985 OutFootEndNoteInfo();
988 const SwPageDesc
*pPageDesc
= nullptr;
990 // In Nicht-HTML-Dokumenten wird die erste gesetzte Seitenvorlage
991 // exportiert und wenn keine gesetzt ist die Standard-Vorlage
992 sal_uLong nNodeIdx
= pCurPam
->GetPoint()->nNode
.GetIndex();
994 while( nNodeIdx
< pDoc
->GetNodes().Count() )
996 SwNode
*pNd
= pDoc
->GetNodes()[ nNodeIdx
];
997 if( pNd
->IsContentNode() )
999 pPageDesc
= static_cast<const SwFormatPageDesc
&>(pNd
->GetContentNode()
1000 ->GetAttr(RES_PAGEDESC
)).GetPageDesc();
1003 else if( pNd
->IsTableNode() )
1005 pPageDesc
= pNd
->GetTableNode()->GetTable().GetFrameFormat()
1006 ->GetPageDesc().GetPageDesc();
1014 pPageDesc
= &pDoc
->GetPageDesc( 0 );
1016 if (!mbSkipHeaderFooter
)
1018 // und nun ... das Style-Sheet!!!
1019 if( m_bCfgOutStyles
)
1021 OutStyleSheet( *pPageDesc
);
1024 // und nun ... das BASIC und JavaScript!
1025 if( pDoc
->GetDocShell() ) // nur mit DocShell ist Basic moeglich
1028 DecIndentLevel(); // Inhalt von <HEAD> einruecken
1030 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_head
, false );
1032 // der Body wird nicht eingerueckt, weil sonst alles eingerueckt waere!
1034 sOut
.append("<" OOO_STRING_SVTOOLS_HTML_body
);
1035 Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
1038 OutLanguage( m_eLang
);
1040 // Textfarbe ausgeben, wenn sie an der Standard-Vorlage gesetzt ist
1041 // und sich geaendert hat.
1042 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_text
,
1043 pDoc
->getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_STANDARD
, false ),
1046 // Farben fuer (un)besuchte Links
1047 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_link
,
1048 pDoc
->getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_INET_NORMAL
),
1050 OutBodyColor( OOO_STRING_SVTOOLS_HTML_O_vlink
,
1051 pDoc
->getIDocumentStylePoolAccess().GetCharFormatFromPool( RES_POOLCHR_INET_VISIT
),
1054 const SfxItemSet
& rItemSet
= pPageDesc
->GetMaster().GetAttrSet();
1056 // fdo#86857 page styles now contain the XATTR_*, not RES_BACKGROUND
1057 SvxBrushItem
const aBrushItem(
1058 getSvxBrushItemFromSourceSet(rItemSet
, RES_BACKGROUND
));
1059 OutBackground(&aBrushItem
, true);
1061 m_nDirection
= GetHTMLDirection( rItemSet
);
1062 OutDirection( m_nDirection
);
1064 if( m_bCfgOutStyles
)
1067 OutCSS1_BodyTagStyleOpt( *this, rItemSet
, dummy
);
1070 if( pDoc
->GetDocShell() ) // nur mit DocShell ist Basic moeglich
1071 OutBasicBodyEvents();
1073 Strm().WriteChar( '>' );
1079 void SwHTMLWriter::OutAnchor( const OUString
& rName
)
1082 sOut
.append("<" OOO_STRING_SVTOOLS_HTML_anchor
" " OOO_STRING_SVTOOLS_HTML_O_name
"=\"");
1083 Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
1084 HTMLOutFuncs::Out_String( Strm(), rName
, m_eDestEnc
, &m_aNonConvertableCharacters
).WriteCharPtr( "\">" );
1085 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_anchor
, false );
1088 void SwHTMLWriter::OutBookmarks()
1090 // hole das aktuelle Bookmark
1091 const ::sw::mark::IMark
* pBookmark
= nullptr;
1092 IDocumentMarkAccess
* const pMarkAccess
= pDoc
->getIDocumentMarkAccess();
1093 if(m_nBkmkTabPos
!= -1)
1094 pBookmark
= (pMarkAccess
->getAllMarksBegin() + m_nBkmkTabPos
)->get();
1095 // Ausgabe aller Bookmarks in diesem Absatz. Die Content-Position
1096 // wird vorerst nicht beruecksichtigt!
1097 sal_uInt32 nNode
= pCurPam
->GetPoint()->nNode
.GetIndex();
1098 while( m_nBkmkTabPos
!= -1
1099 && pBookmark
->GetMarkPos().nNode
.GetIndex() == nNode
)
1101 // Der Bereich derBookmark wird erstam ignoriert, da er von uns
1102 // auch nicht eingelesen wird.
1104 // erst die SWG spezifischen Daten:
1105 if ( dynamic_cast< const ::sw::mark::IBookmark
* >(pBookmark
) && !pBookmark
->GetName().isEmpty() )
1107 OutAnchor( pBookmark
->GetName() );
1110 if( ++m_nBkmkTabPos
>= pMarkAccess
->getAllMarksCount() )
1113 pBookmark
= (pMarkAccess
->getAllMarksBegin() + m_nBkmkTabPos
)->get();
1117 for( nPos
= 0; nPos
< m_aOutlineMarkPoss
.size() &&
1118 m_aOutlineMarkPoss
[nPos
] < nNode
; nPos
++ )
1121 while( nPos
< m_aOutlineMarkPoss
.size() && m_aOutlineMarkPoss
[nPos
] == nNode
)
1123 OUString
sMark( m_aOutlineMarks
[nPos
] );
1124 OutAnchor( sMark
.replace('?', '_') ); // '?' causes problems in IE/Netscape 5
1125 m_aOutlineMarkPoss
.erase( m_aOutlineMarkPoss
.begin()+nPos
);
1126 m_aOutlineMarks
.erase( m_aOutlineMarks
.begin() + nPos
);
1130 void SwHTMLWriter::OutPointFieldmarks( const SwPosition
& rPos
)
1132 // "point" fieldmarks that occupy single character space, as opposed to
1133 // range fieldmarks that are associated with start and end points.
1135 const IDocumentMarkAccess
* pMarkAccess
= pDoc
->getIDocumentMarkAccess();
1139 const sw::mark::IFieldmark
* pMark
= pMarkAccess
->getFieldmarkFor(rPos
);
1143 if (pMark
->GetFieldname() == ODF_FORMCHECKBOX
)
1145 const sw::mark::ICheckboxFieldmark
* pCheckBox
=
1146 dynamic_cast<const sw::mark::ICheckboxFieldmark
*>(pMark
);
1151 aOut
+= OOO_STRING_SVTOOLS_HTML_input
;
1153 aOut
+= OOO_STRING_SVTOOLS_HTML_O_type
;
1155 aOut
+= OOO_STRING_SVTOOLS_HTML_IT_checkbox
;
1158 if (pCheckBox
->IsChecked())
1161 aOut
+= OOO_STRING_SVTOOLS_HTML_O_checked
;
1163 aOut
+= OOO_STRING_SVTOOLS_HTML_O_checked
;
1168 Strm().WriteCharPtr(aOut
.getStr());
1172 // TODO : Handle other single-point fieldmark types here (if any).
1175 void SwHTMLWriter::OutImplicitMark( const OUString
& rMark
,
1176 const sal_Char
*pMarkType
)
1178 if( !rMark
.isEmpty() && !m_aImplicitMarks
.empty() )
1180 OUString
sMark(rMark
+ OUStringLiteral1(cMarkSeparator
) + OUString::createFromAscii(pMarkType
));
1181 if( 0 != m_aImplicitMarks
.erase( sMark
) )
1183 OutAnchor(sMark
.replace('?', '_')); // '?' causes problems in IE/Netscape 5
1188 OUString
SwHTMLWriter::convertHyperlinkHRefValue(const OUString
& rURL
)
1190 OUString
sURL(rURL
);
1191 sal_Int32 nPos
= sURL
.lastIndexOf(cMarkSeparator
);
1194 OUString sCompare
= sURL
.copy(nPos
+ 1).replaceAll(" ", "");
1195 if (!sCompare
.isEmpty())
1197 sCompare
= sCompare
.toAsciiLowerCase();
1198 if( sCompare
== "region" || sCompare
== "frame" ||
1199 sCompare
== "graphic" || sCompare
== "ole" ||
1200 sCompare
== "table" || sCompare
== "outline" ||
1201 sCompare
== "text" )
1203 sURL
= sURL
.replace( '?', '_' ); // '?' causes problems in IE/Netscape 5
1207 else if (!sURL
.isEmpty() && sURL
[0] != '#')
1209 // Link is not started from "#", so looks like external link. Encode this URL.
1210 INetURLObject
aURL(sURL
);
1211 sURL
= aURL
.GetMainURL(INetURLObject::DecodeMechanism::NONE
);
1213 return URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), sURL
);
1216 void SwHTMLWriter::OutHyperlinkHRefValue( const OUString
& rURL
)
1218 OUString sURL
= convertHyperlinkHRefValue(rURL
);
1219 HTMLOutFuncs::Out_String( Strm(), sURL
, m_eDestEnc
, &m_aNonConvertableCharacters
);
1222 void SwHTMLWriter::OutBackground( const SvxBrushItem
*pBrushItem
, bool bGraphic
)
1224 const Color
&rBackColor
= pBrushItem
->GetColor();
1225 /// check, if background color is not "no fill"/"auto fill", instead of
1226 /// only checking, if transparency is not set.
1227 if( rBackColor
.GetColor() != COL_TRANSPARENT
)
1230 sOut
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_bgcolor
).append('=');
1231 Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
1232 HTMLOutFuncs::Out_Color( Strm(), rBackColor
, m_eDestEnc
);
1238 OUString aGraphicInBase64
;
1239 const Graphic
* pGrf
= pBrushItem
->GetGraphic();
1240 OUString GraphicURL
= pBrushItem
->GetGraphicLink();
1241 if( mbEmbedImages
|| GraphicURL
.isEmpty())
1245 if( !XOutBitmap::GraphicToBase64(*pGrf
, aGraphicInBase64
) )
1247 m_nWarn
= WARN_SWG_POOR_LOAD
| WARN_SW_WRITE_BASE
;
1249 Strm().WriteCharPtr( " " OOO_STRING_SVTOOLS_HTML_O_background
"=\"" );
1250 Strm().WriteCharPtr( OOO_STRING_SVTOOLS_HTML_O_data
":" );
1251 HTMLOutFuncs::Out_String( Strm(), aGraphicInBase64
, m_eDestEnc
, &m_aNonConvertableCharacters
).WriteChar( '\"' );
1256 if( m_bCfgCpyLinkedGrfs
)
1258 CopyLocalFileToINet( GraphicURL
);
1260 OUString
s( URIHelper::simpleNormalizedMakeRelative( GetBaseURL(), GraphicURL
));
1261 Strm().WriteCharPtr(" " OOO_STRING_SVTOOLS_HTML_O_background
"=\"" );
1262 HTMLOutFuncs::Out_String( Strm(), s
, m_eDestEnc
, &m_aNonConvertableCharacters
);
1263 Strm().WriteCharPtr("\"");
1268 void SwHTMLWriter::OutBackground( const SfxItemSet
& rItemSet
, bool bGraphic
)
1270 const SfxPoolItem
* pItem
;
1271 if( SfxItemState::SET
== rItemSet
.GetItemState( RES_BACKGROUND
, false,
1274 OutBackground( static_cast<const SvxBrushItem
*>(pItem
), bGraphic
);
1278 sal_uInt16
SwHTMLWriter::GetLangWhichIdFromScript( sal_uInt16 nScript
)
1280 sal_uInt16 nWhichId
;
1283 case CSS1_OUTMODE_CJK
:
1284 nWhichId
= RES_CHRATR_CJK_LANGUAGE
;
1286 case CSS1_OUTMODE_CTL
:
1287 nWhichId
= RES_CHRATR_CJK_LANGUAGE
;
1290 nWhichId
= RES_CHRATR_LANGUAGE
;
1296 void SwHTMLWriter::OutLanguage( LanguageType nLang
)
1298 if( LANGUAGE_DONTKNOW
!= nLang
)
1301 sOut
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_lang
)
1303 Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
1304 HTMLOutFuncs::Out_String( Strm(), LanguageTag::convertToBcp47(nLang
),
1305 m_eDestEnc
, &m_aNonConvertableCharacters
).WriteChar( '"' );
1309 sal_uInt16
SwHTMLWriter::GetHTMLDirection( const SfxItemSet
& rItemSet
) const
1311 return GetHTMLDirection(
1312 static_cast < const SvxFrameDirectionItem
& >( rItemSet
.Get( RES_FRAMEDIR
) )
1316 sal_uInt16
SwHTMLWriter::GetHTMLDirection( sal_uInt16 nDir
) const
1320 case FRMDIR_VERT_TOP_LEFT
:
1321 nDir
= FRMDIR_HORI_LEFT_TOP
;
1323 case FRMDIR_VERT_TOP_RIGHT
:
1324 nDir
= FRMDIR_HORI_RIGHT_TOP
;
1326 case FRMDIR_ENVIRONMENT
:
1327 nDir
= m_nDirection
;
1333 void SwHTMLWriter::OutDirection( sal_uInt16 nDir
)
1335 OString sConverted
= convertDirection(nDir
);
1336 if (!sConverted
.isEmpty())
1339 sOut
.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_dir
)
1340 .append("=\"").append(sConverted
).append('\"');
1341 Strm().WriteCharPtr( sOut
.makeStringAndClear().getStr() );
1345 OString
SwHTMLWriter::convertDirection(sal_uInt16 nDir
)
1350 case FRMDIR_HORI_LEFT_TOP
:
1351 case FRMDIR_VERT_TOP_LEFT
:
1354 case FRMDIR_HORI_RIGHT_TOP
:
1355 case FRMDIR_VERT_TOP_RIGHT
:
1362 OString
SwHTMLWriter::GetIndentString(sal_uInt16 nIncLvl
)
1366 // etwas umstaendlich, aber wir haben nur einen Indent-String!
1367 sal_uInt16 nLevel
= m_nIndentLvl
+ nIncLvl
;
1369 if( nLevel
&& nLevel
<= MAX_INDENT_LEVEL
)
1371 sIndentTabs
[nLevel
] = 0;
1373 sIndentTabs
[nLevel
] = '\t';
1379 void SwHTMLWriter::OutNewLine( bool bCheck
)
1381 if( !bCheck
|| (Strm().Tell()-m_nLastLFPos
) > m_nIndentLvl
)
1383 Strm().WriteCharPtr( SAL_NEWLINE_STRING
);
1384 m_nLastLFPos
= Strm().Tell();
1387 if( m_nIndentLvl
&& m_nIndentLvl
<= MAX_INDENT_LEVEL
)
1389 sIndentTabs
[m_nIndentLvl
] = 0;
1390 Strm().WriteCharPtr( sIndentTabs
);
1391 sIndentTabs
[m_nIndentLvl
] = '\t';
1395 sal_uInt16
SwHTMLWriter::GetHTMLFontSize( sal_uInt32 nHeight
) const
1397 sal_uInt16 nSize
= 1;
1398 for( sal_uInt16 i
=6; i
>0; i
-- )
1400 if( nHeight
> (m_aFontHeights
[i
] + m_aFontHeights
[i
-1])/2 )
1410 // Paragraphs with Table of Contents and other index styles will be typeset with
1411 // dot leaders at the position of the last tabulator in PrintLayout (CSS2) mode
1412 sal_Int32
SwHTMLWriter::indexOfDotLeaders( sal_uInt16 nPoolId
, const OUString
& rStr
)
1414 if (m_bCfgPrintLayout
&& ((nPoolId
>= RES_POOLCOLL_TOX_CNTNT1
&& nPoolId
<= RES_POOLCOLL_TOX_CNTNT5
) ||
1415 (nPoolId
>= RES_POOLCOLL_TOX_IDX1
&& nPoolId
<= RES_POOLCOLL_TOX_IDX3
) ||
1416 (nPoolId
>= RES_POOLCOLL_TOX_USER1
&& nPoolId
<= RES_POOLCOLL_TOX_CNTNT10
) ||
1417 nPoolId
== RES_POOLCOLL_TOX_ILLUS1
|| nPoolId
== RES_POOLCOLL_TOX_TABLES1
||
1418 nPoolId
== RES_POOLCOLL_TOX_OBJECT1
||
1419 (nPoolId
>= RES_POOLCOLL_TOX_AUTHORITIES1
&& nPoolId
<= RES_POOLCOLL_TOX_USER10
))) {
1420 sal_Int32 i
= rStr
.lastIndexOf('\t');
1421 // there are only ASCII (Latin-1) characters after the tabulator
1422 if (i
> -1 && OUStringToOString(rStr
.copy(i
+ 1), RTL_TEXTENCODING_ASCII_US
).indexOf('?') == -1)
1428 // Struktur speichert die aktuellen Daten des Writers zwischen, um
1429 // einen anderen Dokument-Teil auszugeben, wie z.B. Header/Footer
1430 HTMLSaveData::HTMLSaveData(SwHTMLWriter
& rWriter
, sal_uLong nStt
,
1431 sal_uLong nEnd
, bool bSaveNum
,
1432 const SwFrameFormat
*pFrameFormat
)
1434 , pOldPam(rWrt
.pCurPam
)
1435 , pOldEnd(rWrt
.GetEndPaM())
1436 , pOldNumRuleInfo(nullptr)
1437 , pOldNextNumRuleInfo(nullptr)
1438 , nOldDefListLvl(rWrt
.m_nDefListLvl
)
1439 , nOldDirection(rWrt
.m_nDirection
)
1440 , bOldOutHeader(rWrt
.m_bOutHeader
)
1441 , bOldOutFooter(rWrt
.m_bOutFooter
)
1442 , bOldOutFlyFrame(rWrt
.m_bOutFlyFrame
)
1444 bOldWriteAll
= rWrt
.bWriteAll
;
1446 rWrt
.pCurPam
= Writer::NewSwPaM( *rWrt
.pDoc
, nStt
, nEnd
);
1448 // Tabelle in Sonderbereichen erkennen
1449 if( nStt
!= rWrt
.pCurPam
->GetMark()->nNode
.GetIndex() )
1451 const SwNode
*pNd
= rWrt
.pDoc
->GetNodes()[ nStt
];
1452 if( pNd
->IsTableNode() || pNd
->IsSectionNode() )
1453 rWrt
.pCurPam
->GetMark()->nNode
= nStt
;
1456 rWrt
.SetEndPaM( rWrt
.pCurPam
);
1457 rWrt
.pCurPam
->Exchange( );
1458 rWrt
.bWriteAll
= true;
1459 rWrt
.m_nDefListLvl
= 0;
1460 rWrt
.m_bOutHeader
= rWrt
.m_bOutFooter
= false;
1462 // Ggf. die aktuelle Numerierungs-Info merken, damit sie wieder
1463 // neu aufgenommen werden kann. Nur dann belibt auch die Numerierungs-
1464 // Info des nachsten Absatz gueltig.
1467 pOldNumRuleInfo
= new SwHTMLNumRuleInfo( rWrt
.GetNumInfo() );
1468 pOldNextNumRuleInfo
= rWrt
.GetNextNumInfo();
1469 rWrt
.SetNextNumInfo( nullptr );
1473 rWrt
.ClearNextNumInfo();
1476 // Die Numerierung wird in jedem Fall unterbrochen.
1477 rWrt
.GetNumInfo().Clear();
1480 rWrt
.m_nDirection
= rWrt
.GetHTMLDirection( pFrameFormat
->GetAttrSet() );
1483 HTMLSaveData::~HTMLSaveData()
1485 delete rWrt
.pCurPam
; // Pam wieder loeschen
1487 rWrt
.pCurPam
= pOldPam
;
1488 rWrt
.SetEndPaM( pOldEnd
);
1489 rWrt
.bWriteAll
= bOldWriteAll
;
1490 rWrt
.m_nBkmkTabPos
= bOldWriteAll
? rWrt
.FindPos_Bkmk( *pOldPam
->GetPoint() ) : -1;
1491 rWrt
.m_nLastParaToken
= 0;
1492 rWrt
.m_nDefListLvl
= nOldDefListLvl
;
1493 rWrt
.m_nDirection
= nOldDirection
;
1494 rWrt
.m_bOutHeader
= bOldOutHeader
;
1495 rWrt
.m_bOutFooter
= bOldOutFooter
;
1496 rWrt
.m_bOutFlyFrame
= bOldOutFlyFrame
;
1498 // Ggf. die Numerierung von vor der Section fortsetzen. Die Numerierung
1499 // des naecshten Absatz wird in jedem Fall ungueltig.
1500 if( pOldNumRuleInfo
)
1502 rWrt
.GetNumInfo().Set( *pOldNumRuleInfo
);
1503 delete pOldNumRuleInfo
;
1504 rWrt
.SetNextNumInfo( pOldNextNumRuleInfo
);
1508 rWrt
.GetNumInfo().Clear();
1509 rWrt
.ClearNextNumInfo();
1513 void GetHTMLWriter( const OUString
&, const OUString
& rBaseURL
, WriterRef
& xRet
)
1515 xRet
= new SwHTMLWriter( rBaseURL
);
1518 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */