xref: /core/sw/source/filter/html/css1atr.cxx (revision 507ac9b8)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <hintids.hxx>
21 #include <comphelper/string.hxx>
22 #include <vcl/svapp.hxx>
23 #include <vcl/wrkwin.hxx>
24 #include <svl/whiter.hxx>
25 #include <editeng/boxitem.hxx>
26 #include <editeng/ulspitem.hxx>
27 #include <editeng/udlnitem.hxx>
28 #include <editeng/crossedoutitem.hxx>
29 #include <editeng/blinkitem.hxx>
30 #include <editeng/cmapitem.hxx>
31 #include <editeng/colritem.hxx>
32 #include <editeng/fontitem.hxx>
33 #include <editeng/fhgtitem.hxx>
34 #include <editeng/postitem.hxx>
35 #include <editeng/kernitem.hxx>
36 #include <editeng/wghtitem.hxx>
37 #include <editeng/lspcitem.hxx>
38 #include <editeng/adjustitem.hxx>
39 #include <editeng/lrspitem.hxx>
40 #include <editeng/brushitem.hxx>
41 #include <editeng/formatbreakitem.hxx>
42 #include <editeng/keepitem.hxx>
43 #include <editeng/widwitem.hxx>
44 #include <editeng/spltitem.hxx>
45 #include <editeng/orphitem.hxx>
46 #include <editeng/charhiddenitem.hxx>
47 #include <svx/xoutbmp.hxx>
48 #include <svx/svdobj.hxx>
49 #include <editeng/langitem.hxx>
50 #include <editeng/frmdiritem.hxx>
51 #include <svtools/htmlout.hxx>
52 #include <svtools/htmlkywd.hxx>
53 #include <sfx2/htmlmode.hxx>
54 #include <svl/urihelper.hxx>
55 #include <tools/urlobj.hxx>
56 #include <unotools/charclass.hxx>
57 #include <i18nlangtag/languagetag.hxx>
58 #include <charfmt.hxx>
59 #include <fmtclds.hxx>
60 #include <fmtcol.hxx>
61 #include <fmtfsize.hxx>
62 #include <fmtornt.hxx>
63 #include <fmtpdsc.hxx>
64 #include <fmtlsplt.hxx>
65 #include <pagedesc.hxx>
66 #include <fmtanchr.hxx>
67 #include <docary.hxx>
68 #include <pam.hxx>
69 #include <viewsh.hxx>
70 #include <viewopt.hxx>
71 #include <swtable.hxx>
72 // NOTES
73 #include <ftninfo.hxx>
74 #include <ftnidx.hxx>
75 #include <txtftn.hxx>
76 #include <fmtftn.hxx>
77 // FOOTNOTES
78 #include <doc.hxx>
79 #include <IDocumentSettingAccess.hxx>
80 #include <IDocumentLayoutAccess.hxx>
81 #include <swerror.h>
82 #include <charatr.hxx>
83 #include <paratr.hxx>
84 #include <frmatr.hxx>
85 #include <poolfmt.hxx>
86 #include <fltini.hxx>
87 #include "css1kywd.hxx"
88 #include "wrthtml.hxx"
89 #include "htmlnum.hxx"
90 #include "css1atr.hxx"
91 
92 #include <IDocumentStylePoolAccess.hxx>
93 #include <numrule.hxx>
94 #include <o3tl/typed_flags_set.hxx>
95 
96 #include <rtl/strbuf.hxx>
97 
98 using namespace css;
99 using editeng::SvxBorderLine;
100 
101 #define HTML_HEADSPACE (12*20)
102 
103 enum class Css1Background {
104     Attr    = 1,
105     Page    = 2,
106     Table   = 3,
107     Fly     = 4,
108     Section = 5
109 };
110 
111 enum class Css1FrameSize {
112     NONE       = 0x00,
113     Width      = 0x01,
114     MinHeight  = 0x02,
115     FixHeight  = 0x04,
116     AnyHeight  = 0x06,
117     Pixel      = 0x10,
118 };
119 namespace o3tl {
120     template<> struct typed_flags<Css1FrameSize> : is_typed_flags<Css1FrameSize, 0x17> {};
121 }
122 
123 #define DOT_LEADERS_MAX_WIDTH   18
124 
125 static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat,
126                               IDocumentStylePoolAccess /*SwDoc*/ *pDoc, SwDoc *pTemplate );
127 static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rFormat,
128                                    IDocumentStylePoolAccess /*SwDoc*/ *pDoc, SwDoc *pTemplate,
129                                    sal_uInt16 nRefPoolId, bool bExtRef,
130                                    bool bPseudo=true );
131 static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo,
132                                   SwDoc *pDoc, bool bHasNotes, bool bEndNote );
133 static void OutCSS1_SwFormatDropAttrs( SwHTMLWriter& rHWrt,
134                                     const SwFormatDrop& rDrop,
135                                      const SfxItemSet *pCharFormatItemSet=nullptr );
136 static Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt,
137                     const SvxUnderlineItem *pUItem,
138                     const SvxOverlineItem *pOItem,
139                     const SvxCrossedOutItem *pCOItem,
140                     const SvxBlinkItem *pBItem );
141 static Writer& OutCSS1_SvxFontWeight( Writer& rWrt, const SfxPoolItem& rHt );
142 static Writer& OutCSS1_SvxPosture( Writer& rWrt, const SfxPoolItem& rHt );
143 static Writer& OutCSS1_SvxULSpace( Writer& rWrt, const SfxPoolItem& rHt );
144 static Writer& OutCSS1_SvxLRSpace( Writer& rWrt, const SfxPoolItem& rHt );
145 static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt,
146                                         const SvxULSpaceItem *pULSpace,
147                                         const SvxLRSpaceItem *pLRSpace );
148 static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt,
149                                         const SfxItemSet& rItemSet );
150 static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt,
151                                  Css1Background nMode,
152                                  const OUString *pGraphicName );
153 static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt );
154 static Writer& OutCSS1_SwFormatFrameSize( Writer& rWrt, const SfxPoolItem& rHt,
155                                      Css1FrameSize nMode );
156 static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt,
157                                         const SfxItemSet& rItemSet,
158                                         bool bDeep );
159 static Writer& OutCSS1_SwFormatLayoutSplit( Writer& rWrt, const SfxPoolItem& rHt );
160 
161 namespace
162 {
163 
164 const sal_Char sCSS1_rule_end[] = " }";
165 const sal_Char sCSS1_span_tag_end[] = "\">";
166 const sal_Char cCSS1_style_opt_end  = '\"';
167 
168 const sal_Char* const sHTML_FTN_fontheight = "57%";
169 
170 OString lclConvToHex(sal_uInt16 nHex)
171 {
172     sal_Char aNToABuf[] = "00";
173 
174     // set pointer to end of buffer
175     sal_Char *pStr = aNToABuf + (sizeof(aNToABuf)-1);
176     for( sal_uInt8 n = 0; n < 2; ++n )
177     {
178         *(--pStr) = static_cast<sal_Char>(nHex & 0xf ) + 48;
179         if( *pStr > '9' )
180             *pStr += 39;
181         nHex >>= 4;
182     }
183 
184     return OString(aNToABuf, 2);
185 }
186 
187 /// Determines if rProperty has to be suppressed due to ReqIF mode.
188 bool IgnorePropertyForReqIF(bool bReqIF, const OString& rProperty)
189 {
190     if (!bReqIF)
191         return false;
192 
193     // Only allow these two keys, nothing else in ReqIF mode.
194     if (rProperty == sCSS1_P_text_decoration)
195         return false;
196 
197     if (rProperty == sCSS1_P_color)
198         return false;
199 
200     return true;
201 }
202 }
203 
204 OString GetCSS1_Color(const Color& rColor)
205 {
206     return "#" + lclConvToHex(rColor.GetRed()) + lclConvToHex(rColor.GetGreen()) + lclConvToHex(rColor.GetBlue());
207 }
208 
209 class SwCSS1OutMode
210 {
211     SwHTMLWriter& rWrt;
212     sal_uInt16 const nOldMode;
213 
214 public:
215 
216     SwCSS1OutMode( SwHTMLWriter& rHWrt, sal_uInt16 nMode,
217                    const OUString *pSelector ) :
218         rWrt( rHWrt ),
219         nOldMode( rHWrt.m_nCSS1OutMode )
220     {
221         rWrt.m_nCSS1OutMode = nMode;
222         rWrt.m_bFirstCSS1Property = true;
223         if( pSelector )
224             rWrt.m_aCSS1Selector = *pSelector;
225     }
226 
227     ~SwCSS1OutMode()
228     {
229         rWrt.m_nCSS1OutMode = nOldMode;
230     }
231 };
232 
233 void SwHTMLWriter::OutCSS1_Property( const sal_Char *pProp,
234                                      const sal_Char *pVal,
235                                      const OUString *pSVal )
236 {
237     if (IgnorePropertyForReqIF(mbReqIF, pProp))
238         return;
239 
240     OStringBuffer sOut;
241 
242     if( m_bFirstCSS1Rule && (m_nCSS1OutMode & CSS1_OUTMODE_RULE_ON)!=0 )
243     {
244         m_bFirstCSS1Rule = false;
245         OutNewLine();
246         sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_style " "
247                     OOO_STRING_SVTOOLS_HTML_O_type "=\"text/css\">");
248     //  Optional CSS2 code for dot leaders (dotted line between the Table of Contents titles and page numbers):
249     //  (More information: http://www.w3.org/Style/Examples/007/leaders.en.html)
250     //
251     //  p.leaders {
252     //      /* FIXME:
253     //         (1) dots line up vertically only in the paragraphs with the same alignment/level
254     //         (2) max-width = 18 cm instead of 80em; possible improvement with the new CSS3 calc() */
255     //      max-width: 18cm; /* note: need to overwrite max-width with max-width - border-left_of_the_actual_paragraph */
256     //      padding: 0;
257     //      overflow-x: hidden;
258     //      line-height: 120%; /* note: avoid HTML scrollbars and missing descenders of the letters */
259     //  }
260     //  p.leaders:after {
261     //      float: left;
262     //      width: 0;
263     //      white-space: nowrap;
264     //      content: ". . . . . . . . . . . . . . . . . . ...";
265     //  }
266     //  p.leaders span:first-child {
267     //      padding-right: 0.33em;
268     //      background: white;
269     //  }
270     //  p.leaders span + span {
271     //      float: right;
272     //      padding-left: 0.33em;
273     //      background: white;
274     //      position: relative;
275     //      z-index: 1
276     //  }
277 
278         if (m_bCfgPrintLayout) {
279             sOut.append(
280                 "p." sCSS2_P_CLASS_leaders "{max-width:" + OString::number(DOT_LEADERS_MAX_WIDTH) +
281                     "cm;padding:0;overflow-x:hidden;line-height:120%}"
282                 "p." sCSS2_P_CLASS_leaders ":after{float:left;width:0;white-space:nowrap;content:\"");
283             for (int i = 0; i < 100; i++ )
284                 sOut.append(". ");
285             sOut.append(
286                     "\"}p." sCSS2_P_CLASS_leaders " span:first-child{padding-right:0.33em;background:white}"
287                     "p." sCSS2_P_CLASS_leaders " span+span{float:right;padding-left:0.33em;"
288                     "background:white;position:relative;z-index:1}");
289         }
290         Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
291 
292         IncIndentLevel();
293     }
294 
295     if( m_bFirstCSS1Property )
296     {
297         switch( m_nCSS1OutMode & CSS1_OUTMODE_ANY_ON )
298         {
299         case CSS1_OUTMODE_SPAN_TAG_ON:
300         case CSS1_OUTMODE_SPAN_TAG1_ON:
301             if( m_bTagOn )
302             {
303                 sOut.append("<" + GetNamespace() + OOO_STRING_SVTOOLS_HTML_span
304                             " " OOO_STRING_SVTOOLS_HTML_O_style "=\"");
305             }
306             else
307             {
308                 HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false );
309                 return;
310             }
311             break;
312 
313         case CSS1_OUTMODE_RULE_ON:
314             {
315                 OutNewLine();
316                 sOut.append(OUStringToOString(m_aCSS1Selector, m_eDestEnc) + " { ");
317             }
318             break;
319 
320         case CSS1_OUTMODE_STYLE_OPT_ON:
321             sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_style "=\"");
322             break;
323         }
324         m_bFirstCSS1Property = false;
325     }
326     else
327     {
328         sOut.append("; ");
329     }
330 
331     sOut.append(OString(pProp) + ": ");
332     if( m_nCSS1OutMode & CSS1_OUTMODE_ENCODE )
333     {
334         // for STYLE-Option encode string
335         Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
336         if( pVal )
337             HTMLOutFuncs::Out_String( Strm(), OUString::createFromAscii(pVal),
338                                       m_eDestEnc, &m_aNonConvertableCharacters );
339         else if( pSVal )
340             HTMLOutFuncs::Out_String( Strm(), *pSVal, m_eDestEnc, &m_aNonConvertableCharacters );
341     }
342     else
343     {
344         // for STYLE-Tag print string directly
345         if( pVal )
346             sOut.append(pVal);
347         else if( pSVal )
348             sOut.append(OUStringToOString(*pSVal, m_eDestEnc));
349     }
350 
351     if (!sOut.isEmpty())
352         Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
353 }
354 
355 static void AddUnitPropertyValue(OStringBuffer &rOut, long nVal,
356     FieldUnit eUnit)
357 {
358     if( nVal < 0 )
359     {
360         // special-case sign symbol
361         nVal = -nVal;
362         rOut.append('-');
363     }
364 
365     // the recalculated unit results from (x * nMul)/(nDiv*nFac*10)
366     long nMul = 1000;
367     long nDiv = 1;
368     long nFac = 100;
369     const sal_Char *pUnit;
370     switch( eUnit )
371     {
372     case FieldUnit::MM_100TH:
373         OSL_ENSURE( FieldUnit::MM == eUnit, "Measuring unit not supported" );
374         [[fallthrough]];
375     case FieldUnit::MM:
376         // 0.01mm = 0.57twip
377         nMul = 25400;   // 25.4 * 1000
378         nDiv = 1440;    // 72 * 20;
379         nFac = 100;
380         pUnit = sCSS1_UNIT_mm;
381         break;
382 
383     case FieldUnit::M:
384     case FieldUnit::KM:
385         OSL_ENSURE( FieldUnit::CM == eUnit, "Measuring unit not supported" );
386         [[fallthrough]];
387     case FieldUnit::CM:
388         // 0.01cm = 5.7twip (not exact, but the UI is also not exact)
389         nMul = 2540;    // 2.54 * 1000
390         nDiv = 1440;    // 72 * 20;
391         nFac = 100;
392         pUnit = sCSS1_UNIT_cm;
393         break;
394 
395     case FieldUnit::TWIP:
396         OSL_ENSURE( FieldUnit::POINT == eUnit, "Measuring unit not supported" );
397         [[fallthrough]];
398     case FieldUnit::POINT:
399         // 0.1pt = 2.0twip (not exact, but the UI is also not exact)
400         nMul = 100;
401         nDiv = 20;
402         nFac = 10;
403         pUnit = sCSS1_UNIT_pt;
404         break;
405 
406     case FieldUnit::PICA:
407         // 0.01pc = 2.40twip (not exact, but the UI is also not exact)
408         nMul = 1000;
409         nDiv = 240;     // 12 * 20;
410         nFac = 100;
411         pUnit = sCSS1_UNIT_pc;
412         break;
413 
414     case FieldUnit::NONE:
415     case FieldUnit::FOOT:
416     case FieldUnit::MILE:
417     case FieldUnit::CUSTOM:
418     case FieldUnit::PERCENT:
419     case FieldUnit::INCH:
420     default:
421         OSL_ENSURE( FieldUnit::INCH == eUnit, "Measuring unit not supported" );
422         // 0.01in = 14.4twip (not exact, but the UI is also not exact)
423         nMul = 1000;
424         nDiv = 1440;    // 72 * 20;
425         nFac = 100;
426         pUnit = sCSS1_UNIT_inch;
427         break;
428     }
429 
430     long nLongVal = 0;
431     bool bOutLongVal = true;
432     if( nVal > LONG_MAX / nMul )
433     {
434         sal_Int64 nBigVal( nVal );
435         nBigVal *= nMul;
436         nBigVal /= nDiv;
437         nBigVal += 5;
438         nBigVal /= 10;
439 
440         if( nBigVal <= LONG_MAX )
441         {
442             // a long is sufficient
443             nLongVal = static_cast<long>(nBigVal);
444         }
445         else
446         {
447             rOut.append(nBigVal / static_cast<sal_Int64>(nFac));
448             if( (nBigVal % static_cast<sal_Int64>(nFac)) != 0 )
449             {
450                 rOut.append('.');
451                 while( nFac > 1 && (nBigVal % static_cast<sal_Int64>(nFac)) != 0 )
452                 {
453                     nFac /= 10;
454                     rOut.append((nBigVal / static_cast<sal_Int64>(nFac)) % sal_Int64(10));
455                 }
456             }
457             bOutLongVal = false;
458         }
459     }
460     else
461     {
462         nLongVal = nVal * nMul;
463         nLongVal /= nDiv;
464         nLongVal += 5;
465         nLongVal /= 10;
466     }
467 
468     if( bOutLongVal )
469     {
470         rOut.append(OString::number(nLongVal/nFac));
471         if( (nLongVal % nFac) != 0 )
472         {
473             rOut.append('.');
474             while( nFac > 1 && (nLongVal % nFac) != 0 )
475             {
476                 nFac /= 10;
477                 rOut.append(OString::number((nLongVal / nFac) % 10));
478             }
479         }
480     }
481 
482     rOut.append(pUnit);
483 }
484 
485 void SwHTMLWriter::OutCSS1_UnitProperty( const sal_Char *pProp, long nVal )
486 {
487     OStringBuffer sOut;
488     AddUnitPropertyValue(sOut, nVal, m_eCSS1Unit);
489     OutCSS1_PropertyAscii(pProp, sOut.makeStringAndClear());
490 }
491 
492 void SwHTMLWriter::OutCSS1_PixelProperty( const sal_Char *pProp, long nVal,
493                                           bool bVert )
494 {
495     OString sOut(OString::number(ToPixel(nVal,bVert)) + sCSS1_UNIT_px);
496     OutCSS1_PropertyAscii(pProp, sOut);
497 }
498 
499 void SwHTMLWriter::OutStyleSheet( const SwPageDesc& rPageDesc )
500 {
501     m_bFirstCSS1Rule = true;
502 
503 // Feature: PrintExt
504     if( IsHTMLMode(HTMLMODE_PRINT_EXT) )
505     {
506         const SwPageDesc *pFirstPageDesc = nullptr;
507         sal_uInt16 nFirstRefPoolId = RES_POOLPAGE_HTML;
508         m_bCSS1IgnoreFirstPageDesc = true;
509 
510         // First we try to guess how the document is constructed.
511         // Allowed are only the templates: HTML, 1st page, left page, and right page.
512         // A first page is only exported, if it matches the template "1st page".
513         // Left and right pages are only exported, if their templates are linked.
514         // If other templates are used, only very simple cases are exported.
515         const SwPageDesc *pPageDesc = &rPageDesc;
516         const SwPageDesc *pFollow = rPageDesc.GetFollow();
517         if( RES_POOLPAGE_FIRST == pPageDesc->GetPoolFormatId() &&
518             pFollow != pPageDesc &&
519             !IsPoolUserFormat( pFollow->GetPoolFormatId() ) )
520         {
521             // the document has a first page
522             pFirstPageDesc = pPageDesc;
523             pPageDesc = pFollow;
524             pFollow = pPageDesc->GetFollow();
525         }
526 
527         IDocumentStylePoolAccess* pStylePoolAccess = &getIDocumentStylePoolAccess();
528         if( pPageDesc == pFollow )
529         {
530             // The document is one-sided; no matter what page, we do not create a 2-sided doc.
531             // The attribute is exported relative to the HTML page template.
532             OutCSS1_SwPageDesc( *this, *pPageDesc, pStylePoolAccess, m_xTemplate.get(),
533                                 RES_POOLPAGE_HTML, true, false );
534             nFirstRefPoolId = pFollow->GetPoolFormatId();
535         }
536         else if( (RES_POOLPAGE_LEFT == pPageDesc->GetPoolFormatId() &&
537                   RES_POOLPAGE_RIGHT == pFollow->GetPoolFormatId()) ||
538                  (RES_POOLPAGE_RIGHT == pPageDesc->GetPoolFormatId() &&
539                   RES_POOLPAGE_LEFT == pFollow->GetPoolFormatId()) )
540         {
541             // the document is double-sided
542             OutCSS1_SwPageDesc( *this, *pPageDesc, pStylePoolAccess, m_xTemplate.get(),
543                                 RES_POOLPAGE_HTML, true );
544             OutCSS1_SwPageDesc( *this, *pFollow, pStylePoolAccess, m_xTemplate.get(),
545                                 RES_POOLPAGE_HTML, true );
546             nFirstRefPoolId = RES_POOLPAGE_RIGHT;
547             m_bCSS1IgnoreFirstPageDesc = false;
548         }
549         // other cases we miss
550 
551         if( pFirstPageDesc )
552           OutCSS1_SwPageDesc( *this, *pFirstPageDesc, pStylePoolAccess, m_xTemplate.get(),
553                                 nFirstRefPoolId, false );
554     }
555 
556     // The text body style has to be exported always (if it is changed compared
557     // to the template), because it is used as reference for any style
558     // that maps to <P>, and that's especially the standard style
559     getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT, false );
560 
561     // the Default-TextStyle is not also exported !!
562     // 0-Style is the Default; is never exported !!
563     const size_t nTextFormats = m_pDoc->GetTextFormatColls()->size();
564     for( size_t i = 1; i < nTextFormats; ++i )
565     {
566         const SwTextFormatColl* pColl = (*m_pDoc->GetTextFormatColls())[i];
567         sal_uInt16 nPoolId = pColl->GetPoolFormatId();
568         if( nPoolId == RES_POOLCOLL_TEXT || m_pDoc->IsUsed( *pColl ) )
569             OutCSS1_SwFormat( *this, *pColl, &m_pDoc->getIDocumentStylePoolAccess(), m_xTemplate.get() );
570     }
571 
572     // the Default-TextStyle is not also exported !!
573     const size_t nCharFormats = m_pDoc->GetCharFormats()->size();
574     for( size_t i = 1; i < nCharFormats; ++i )
575     {
576         const SwCharFormat *pCFormat = (*m_pDoc->GetCharFormats())[i];
577         sal_uInt16 nPoolId = pCFormat->GetPoolFormatId();
578         if( nPoolId == RES_POOLCHR_INET_NORMAL ||
579             nPoolId == RES_POOLCHR_INET_VISIT ||
580             m_pDoc->IsUsed( *pCFormat ) )
581             OutCSS1_SwFormat( *this, *pCFormat, &m_pDoc->getIDocumentStylePoolAccess(), m_xTemplate.get() );
582     }
583 
584     bool bHasEndNotes {false};
585     bool bHasFootNotes {false};
586     const SwFootnoteIdxs& rIdxs = m_pDoc->GetFootnoteIdxs();
587     for( auto pIdx : rIdxs )
588     {
589         if( pIdx->GetFootnote().IsEndNote() )
590         {
591             bHasEndNotes = true;
592             if (bHasFootNotes)
593                 break;
594         }
595         else
596         {
597             bHasFootNotes = true;
598             if (bHasEndNotes)
599                 break;
600         }
601     }
602     OutCSS1_SwFootnoteInfo( *this, m_pDoc->GetFootnoteInfo(), m_pDoc, bHasFootNotes, false );
603     OutCSS1_SwFootnoteInfo( *this, m_pDoc->GetEndNoteInfo(), m_pDoc, bHasEndNotes, true );
604 
605     if( !m_bFirstCSS1Rule )
606     {
607         DecIndentLevel();
608 
609         OutNewLine();
610         HTMLOutFuncs::Out_AsciiTag( Strm(), GetNamespace() + OOO_STRING_SVTOOLS_HTML_style, false );
611     }
612     else
613     {
614         m_bFirstCSS1Rule = false;
615     }
616 
617     m_nDfltTopMargin = 0;
618     m_nDfltBottomMargin = 0;
619 }
620 
621 // if pPseudo is set, Styles-Sheets will be exported;
622 // otherwise we only search for Token and Class for a Format
623 sal_uInt16 SwHTMLWriter::GetCSS1Selector( const SwFormat *pFormat, OString& rToken,
624                                       OUString& rClass, sal_uInt16& rRefPoolId,
625                                       OUString *pPseudo )
626 {
627     sal_uInt16 nDeep = 0;
628     rToken.clear();
629     rClass.clear();
630     rRefPoolId = 0;
631     if( pPseudo )
632         pPseudo->clear();
633 
634     bool bChrFormat = RES_CHRFMT==pFormat->Which();
635 
636     // search formats above for the nearest standard or HTML-Tag template
637     const SwFormat *pPFormat = pFormat;
638     while( pPFormat && !pPFormat->IsDefault() )
639     {
640         bool bStop = false;
641         sal_uInt16 nPoolId = pPFormat->GetPoolFormatId();
642         if( USER_FMT & nPoolId )
643         {
644             // user templates
645             const OUString& aNm(pPFormat->GetName());
646 
647             if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_blockquote)
648             {
649                 rRefPoolId = RES_POOLCOLL_HTML_BLOCKQUOTE;
650                 rToken = OString(OOO_STRING_SVTOOLS_HTML_blockquote);
651             }
652             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_citiation)
653             {
654                 rRefPoolId = RES_POOLCHR_HTML_CITIATION;
655                 rToken = OString(OOO_STRING_SVTOOLS_HTML_citiation);
656             }
657             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_code)
658             {
659                 rRefPoolId = RES_POOLCHR_HTML_CODE;
660                 rToken = OString(OOO_STRING_SVTOOLS_HTML_code);
661             }
662             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_definstance)
663             {
664                 rRefPoolId = RES_POOLCHR_HTML_DEFINSTANCE;
665                 rToken = OString(OOO_STRING_SVTOOLS_HTML_definstance);
666             }
667             else if (!bChrFormat && (aNm == OOO_STRING_SVTOOLS_HTML_dd ||
668                                   aNm == OOO_STRING_SVTOOLS_HTML_dt))
669             {
670                 sal_uInt16 nDefListLvl = GetDefListLvl(aNm, nPoolId);
671                 // Export the templates DD 1/DT 1,
672                 // but none of their derived templates,
673                 // also not DD 2/DT 2 etc.
674                 if (nDefListLvl)
675                 {
676                     if (pPseudo && (nDeep || (nDefListLvl & 0x0fff) > 1))
677                     {
678                         bStop = true;
679                     }
680                     else if (nDefListLvl & HTML_DLCOLL_DD)
681                     {
682                         rRefPoolId = RES_POOLCOLL_HTML_DD;
683                         rToken = OString(OOO_STRING_SVTOOLS_HTML_dd);
684                     }
685                     else
686                     {
687                         rRefPoolId = RES_POOLCOLL_HTML_DT;
688                         rToken = OString(OOO_STRING_SVTOOLS_HTML_dt);
689                     }
690                 }
691             }
692             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_emphasis)
693             {
694                 rRefPoolId = RES_POOLCHR_HTML_EMPHASIS;
695                 rToken = OString(OOO_STRING_SVTOOLS_HTML_emphasis);
696             }
697             else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_horzrule)
698             {
699                 // do not export HR !
700                 bStop = (nDeep==0);
701             }
702             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_keyboard)
703             {
704                 rRefPoolId = RES_POOLCHR_HTML_KEYBOARD;
705                 rToken = OString(OOO_STRING_SVTOOLS_HTML_keyboard);
706             }
707             else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_listing)
708             {
709                 // Export Listings as PRE or PRE-derived template
710                 rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt);
711                 rRefPoolId = RES_POOLCOLL_HTML_PRE;
712                 nDeep = CSS1_FMT_CMPREF;
713             }
714             else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_preformtxt)
715             {
716                 rRefPoolId = RES_POOLCOLL_HTML_PRE;
717                 rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt);
718             }
719             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_sample)
720             {
721                 rRefPoolId = RES_POOLCHR_HTML_SAMPLE;
722                 rToken = OString(OOO_STRING_SVTOOLS_HTML_sample);
723             }
724             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_strong)
725             {
726                 rRefPoolId = RES_POOLCHR_HTML_STRONG;
727                 rToken = OString(OOO_STRING_SVTOOLS_HTML_strong);
728             }
729             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_teletype)
730             {
731                 rRefPoolId = RES_POOLCHR_HTML_TELETYPE;
732                 rToken = OString(OOO_STRING_SVTOOLS_HTML_teletype);
733             }
734             else if (bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_variable)
735             {
736                 rRefPoolId = RES_POOLCHR_HTML_VARIABLE;
737                 rToken = OString(OOO_STRING_SVTOOLS_HTML_variable);
738             }
739             else if (!bChrFormat && aNm == OOO_STRING_SVTOOLS_HTML_xmp)
740             {
741                 // export XMP as PRE (but not the template as Style)
742                 rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt);
743                 rRefPoolId = RES_POOLCOLL_HTML_PRE;
744                 nDeep = CSS1_FMT_CMPREF;
745             }
746 
747             // if a PoolId is set, the Name of the template is that of the related Token
748             OSL_ENSURE( (rRefPoolId != 0) == (!rToken.isEmpty()),
749                     "Token missing" );
750         }
751         else
752         {
753             // Pool templates
754             switch( nPoolId )
755             {
756             // paragraph templates
757             case RES_POOLCOLL_HEADLINE_BASE:
758             case RES_POOLCOLL_STANDARD:
759                 // do not export this template
760                 bStop = (nDeep==0);
761                 break;
762             case RES_POOLCOLL_TEXT:
763                 rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak);
764                 break;
765             case RES_POOLCOLL_HEADLINE1:
766                 rToken = OString(OOO_STRING_SVTOOLS_HTML_head1);
767                 break;
768             case RES_POOLCOLL_HEADLINE2:
769                 rToken = OString(OOO_STRING_SVTOOLS_HTML_head2);
770                 break;
771             case RES_POOLCOLL_HEADLINE3:
772                 rToken = OString(OOO_STRING_SVTOOLS_HTML_head3);
773                 break;
774             case RES_POOLCOLL_HEADLINE4:
775                 rToken = OString(OOO_STRING_SVTOOLS_HTML_head4);
776                 break;
777             case RES_POOLCOLL_HEADLINE5:
778                 rToken = OString(OOO_STRING_SVTOOLS_HTML_head5);
779                 break;
780             case RES_POOLCOLL_HEADLINE6:
781                 rToken = OString(OOO_STRING_SVTOOLS_HTML_head6);
782                 break;
783             case RES_POOLCOLL_SENDADRESS:
784                 rToken = OString(OOO_STRING_SVTOOLS_HTML_address);
785                 break;
786             case RES_POOLCOLL_HTML_BLOCKQUOTE:
787                 rToken = OString(OOO_STRING_SVTOOLS_HTML_blockquote);
788                 break;
789             case RES_POOLCOLL_HTML_PRE:
790                 rToken = OString(OOO_STRING_SVTOOLS_HTML_preformtxt);
791                 break;
792 
793             case RES_POOLCOLL_HTML_DD:
794                 rToken = OString(OOO_STRING_SVTOOLS_HTML_dd);
795                 break;
796             case RES_POOLCOLL_HTML_DT:
797                 rToken = OString(OOO_STRING_SVTOOLS_HTML_dt);
798                 break;
799 
800             case RES_POOLCOLL_TABLE:
801                 if( pPseudo )
802                 {
803                     rToken = OOO_STRING_SVTOOLS_HTML_tabledata " "
804                              OOO_STRING_SVTOOLS_HTML_parabreak;
805                 }
806                 else
807                     rToken = OOO_STRING_SVTOOLS_HTML_parabreak;
808                 break;
809             case RES_POOLCOLL_TABLE_HDLN:
810                 if( pPseudo )
811                 {
812                     rToken = OOO_STRING_SVTOOLS_HTML_tableheader " "
813                              OOO_STRING_SVTOOLS_HTML_parabreak;
814                 }
815                 else
816                     rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak);
817                 break;
818             case RES_POOLCOLL_HTML_HR:
819                 // do not export HR !
820                 bStop = (nDeep==0);
821                 break;
822             case RES_POOLCOLL_FOOTNOTE:
823                 if( !nDeep )
824                 {
825                     rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak);
826                     rClass = OOO_STRING_SVTOOLS_HTML_sdfootnote;
827                     rRefPoolId = RES_POOLCOLL_TEXT;
828                     nDeep = CSS1_FMT_CMPREF;
829                 }
830                 break;
831             case RES_POOLCOLL_ENDNOTE:
832                 if( !nDeep )
833                 {
834                     rToken = OString(OOO_STRING_SVTOOLS_HTML_parabreak);
835                     rClass = OOO_STRING_SVTOOLS_HTML_sdendnote;
836                     rRefPoolId = RES_POOLCOLL_TEXT;
837                     nDeep = CSS1_FMT_CMPREF;
838                 }
839                 break;
840 
841             // character templates
842             case RES_POOLCHR_HTML_EMPHASIS:
843                 rToken = OString(OOO_STRING_SVTOOLS_HTML_emphasis);
844                 break;
845             case RES_POOLCHR_HTML_CITIATION:
846                 rToken = OString(OOO_STRING_SVTOOLS_HTML_citiation);
847                 break;
848             case RES_POOLCHR_HTML_STRONG:
849                 rToken = OString(OOO_STRING_SVTOOLS_HTML_strong);
850                 break;
851             case RES_POOLCHR_HTML_CODE:
852                 rToken = OString(OOO_STRING_SVTOOLS_HTML_code);
853                 break;
854             case RES_POOLCHR_HTML_SAMPLE:
855                 rToken = OString(OOO_STRING_SVTOOLS_HTML_sample);
856                 break;
857             case RES_POOLCHR_HTML_KEYBOARD:
858                 rToken = OString(OOO_STRING_SVTOOLS_HTML_keyboard);
859                 break;
860             case RES_POOLCHR_HTML_VARIABLE:
861                 rToken = OString(OOO_STRING_SVTOOLS_HTML_variable);
862                 break;
863             case RES_POOLCHR_HTML_DEFINSTANCE:
864                 rToken = OString(OOO_STRING_SVTOOLS_HTML_definstance);
865                 break;
866             case RES_POOLCHR_HTML_TELETYPE:
867                 rToken = OString(OOO_STRING_SVTOOLS_HTML_teletype);
868                 break;
869 
870             case RES_POOLCHR_INET_NORMAL:
871                 if( pPseudo )
872                 {
873                     rToken = OString(OOO_STRING_SVTOOLS_HTML_anchor);
874                     *pPseudo = OStringToOUString( sCSS1_link, RTL_TEXTENCODING_ASCII_US );
875                 }
876                 break;
877             case RES_POOLCHR_INET_VISIT:
878                 if( pPseudo )
879                 {
880                     rToken = OString(OOO_STRING_SVTOOLS_HTML_anchor);
881                     *pPseudo = OStringToOUString( sCSS1_visited, RTL_TEXTENCODING_ASCII_US );
882                 }
883                 break;
884             }
885 
886             // if a token is set, PoolId contains the related template
887             if( !rToken.isEmpty() && !rRefPoolId )
888                 rRefPoolId = nPoolId;
889         }
890 
891         if( !rToken.isEmpty() || bStop )
892         {
893             // stop if a HTML-Tag template was found
894             break;
895         }
896         else
897         {
898             // continue otherwise
899             nDeep++;
900             pPFormat = pPFormat->DerivedFrom();
901         }
902     }
903 
904     if( !rToken.isEmpty() )
905     {
906         // this is a HTML-Tag template
907         if( !nDeep )
908             nDeep = CSS1_FMT_ISTAG;
909     }
910     else
911     {
912         // this is not a HTML-Tag template nor derived from one
913         nDeep = 0;
914     }
915     if( nDeep > 0 && nDeep < CSS1_FMT_SPECIAL )
916     {
917         // If the template is derived from a HTML template,
918         // we export it as <TOKEN>.<CLASS>, otherwise as .<CLASS>.
919         // <CLASS> is the name of the template after removing all characters
920         // before and including the first '.'
921         rClass = pFormat->GetName();
922         sal_Int32 nPos = rClass.indexOf( '.' );
923         if( nPos >= 0 && rClass.getLength() > nPos+1 )
924         {
925             rClass = rClass.replaceAt( 0, nPos+1, "" );
926         }
927 
928         rClass = GetAppCharClass().lowercase( rClass );
929         rClass = rClass.replaceAll( ".", "-" );
930         rClass = rClass.replaceAll( " ", "-" );
931         rClass = rClass.replaceAll( "_", "-" );
932     }
933 
934     return nDeep;
935 }
936 
937 static sal_uInt16 GetCSS1Selector( const SwFormat *pFormat, OUString& rSelector,
938                                sal_uInt16& rRefPoolId )
939 {
940     OString aToken;
941     OUString aClass;
942     OUString aPseudo;
943 
944     sal_uInt16 nDeep = SwHTMLWriter::GetCSS1Selector( pFormat, aToken, aClass,
945                                                   rRefPoolId, &aPseudo );
946     if( nDeep )
947     {
948         if( !aToken.isEmpty() )
949             rSelector = OStringToOUString(aToken, RTL_TEXTENCODING_ASCII_US);
950         else
951             rSelector.clear();
952 
953         if( !aClass.isEmpty() )
954             rSelector += "." + aClass;
955         if( !aPseudo.isEmpty() )
956             rSelector += ":" + aPseudo;
957     }
958 
959     return nDeep;
960 }
961 
962 const SwFormat *SwHTMLWriter::GetTemplateFormat( sal_uInt16 nPoolFormatId,
963                                            IDocumentStylePoolAccess* pTemplate /*SwDoc *pTemplate*/)
964 {
965     const SwFormat *pRefFormat = nullptr;
966 
967     if( pTemplate )
968     {
969         OSL_ENSURE( !(USER_FMT & nPoolFormatId),
970                 "No user templates found" );
971         if( POOLGRP_NOCOLLID & nPoolFormatId )
972             pRefFormat = pTemplate->GetCharFormatFromPool( nPoolFormatId );
973         else
974             pRefFormat = pTemplate->GetTextCollFromPool( nPoolFormatId, false );
975     }
976 
977     return pRefFormat;
978 }
979 
980 const SwFormat *SwHTMLWriter::GetParentFormat( const SwFormat& rFormat, sal_uInt16 nDeep )
981 {
982     OSL_ENSURE( nDeep != USHRT_MAX, "Called GetParent for HTML-template!" );
983     const SwFormat *pRefFormat = nullptr;
984 
985     if( nDeep > 0 )
986     {
987         // get the pointer for the HTML-Tag template, from which the template is derived
988         pRefFormat = &rFormat;
989         for( sal_uInt16 i=nDeep; i>0; i-- )
990             pRefFormat = pRefFormat->DerivedFrom();
991 
992         if( pRefFormat && pRefFormat->IsDefault() )
993             pRefFormat = nullptr;
994     }
995 
996     return pRefFormat;
997 }
998 
999 bool swhtml_css1atr_equalFontItems( const SfxPoolItem& r1, const SfxPoolItem& r2 )
1000 {
1001     return  static_cast<const SvxFontItem &>(r1).GetFamilyName() ==
1002                     static_cast<const SvxFontItem &>(r2).GetFamilyName() &&
1003             static_cast<const SvxFontItem &>(r1).GetFamily() ==
1004                     static_cast<const SvxFontItem &>(r2).GetFamily();
1005 }
1006 
1007 void SwHTMLWriter::SubtractItemSet( SfxItemSet& rItemSet,
1008                                     const SfxItemSet& rRefItemSet,
1009                                     bool bSetDefaults,
1010                                     bool bClearSame,
1011                                      const SfxItemSet *pRefScriptItemSet )
1012 {
1013     OSL_ENSURE( bSetDefaults || bClearSame,
1014             "SwHTMLWriter::SubtractItemSet: No action for this Flag" );
1015     SfxItemSet aRefItemSet( *rRefItemSet.GetPool(), rRefItemSet.GetRanges() );
1016     aRefItemSet.Set( rRefItemSet );
1017 
1018     // compare with the Attr-Set of the template
1019     SfxWhichIter aIter( rItemSet );
1020     sal_uInt16 nWhich = aIter.FirstWhich();
1021     while( nWhich )
1022     {
1023         const SfxPoolItem *pRefItem, *pItem;
1024         bool bItemSet = ( SfxItemState::SET ==
1025                 rItemSet.GetItemState( nWhich, false, &pItem) );
1026         bool bRefItemSet;
1027 
1028         if( pRefScriptItemSet )
1029         {
1030             switch( nWhich )
1031             {
1032             case RES_CHRATR_FONT:
1033             case RES_CHRATR_FONTSIZE:
1034             case RES_CHRATR_LANGUAGE:
1035             case RES_CHRATR_POSTURE:
1036             case RES_CHRATR_WEIGHT:
1037             case RES_CHRATR_CJK_FONT:
1038             case RES_CHRATR_CJK_FONTSIZE:
1039             case RES_CHRATR_CJK_LANGUAGE:
1040             case RES_CHRATR_CJK_POSTURE:
1041             case RES_CHRATR_CJK_WEIGHT:
1042             case RES_CHRATR_CTL_FONT:
1043             case RES_CHRATR_CTL_FONTSIZE:
1044             case RES_CHRATR_CTL_LANGUAGE:
1045             case RES_CHRATR_CTL_POSTURE:
1046             case RES_CHRATR_CTL_WEIGHT:
1047                 bRefItemSet = ( SfxItemState::SET ==
1048                     pRefScriptItemSet->GetItemState( nWhich, true, &pRefItem) );
1049                 break;
1050             default:
1051                 bRefItemSet = ( SfxItemState::SET ==
1052                     aRefItemSet.GetItemState( nWhich, false, &pRefItem) );
1053                 break;
1054             }
1055         }
1056         else
1057         {
1058             bRefItemSet = ( SfxItemState::SET ==
1059                 aRefItemSet.GetItemState( nWhich, false, &pRefItem) );
1060         }
1061 
1062         if( bItemSet )
1063         {
1064             if( (bClearSame || pRefScriptItemSet) && bRefItemSet &&
1065                 ( *pItem == *pRefItem ||
1066                   ((RES_CHRATR_FONT == nWhich ||
1067                     RES_CHRATR_CJK_FONT == nWhich ||
1068                     RES_CHRATR_CTL_FONT == nWhich)  &&
1069                    swhtml_css1atr_equalFontItems( *pItem, *pRefItem )) ) )
1070             {
1071                 // the Attribute is in both templates with the same value
1072                 // and does not need to be exported
1073                 rItemSet.ClearItem( nWhich );
1074             }
1075         }
1076         else
1077         {
1078             if( (bSetDefaults || pRefScriptItemSet) && bRefItemSet )
1079             {
1080                 // the Attribute exists only in the reference; the default
1081                 // might have to be exported
1082                 rItemSet.Put( rItemSet.GetPool()->GetDefaultItem(nWhich) );
1083             }
1084         }
1085 
1086         nWhich = aIter.NextWhich();
1087     }
1088 }
1089 
1090 void SwHTMLWriter::PrepareFontList( const SvxFontItem& rFontItem,
1091                                     OUString& rNames,
1092                                     sal_Unicode cQuote, bool bGeneric )
1093 {
1094     rNames.clear();
1095     const OUString& rName = rFontItem.GetFamilyName();
1096     bool bContainsKeyword = false;
1097     if( !rName.isEmpty() )
1098     {
1099         sal_Int32 nStrPos = 0;
1100         while( nStrPos != -1 )
1101         {
1102             OUString aName = rName.getToken( 0, ';', nStrPos );
1103             aName = comphelper::string::strip(aName, ' ');
1104             if( aName.isEmpty() )
1105                 continue;
1106 
1107             bool bIsKeyword = false;
1108             switch( aName[0] )
1109             {
1110             case 'c':
1111             case 'C':
1112                 bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_cursive );
1113                 break;
1114 
1115             case 'f':
1116             case 'F':
1117                 bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_fantasy );
1118                 break;
1119 
1120             case 'm':
1121             case 'M':
1122                 bIsKeyword = aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_monospace );
1123                 break;
1124 
1125             case 's':
1126             case 'S':
1127                 bIsKeyword =
1128                     aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_serif ) ||
1129                     aName.equalsIgnoreAsciiCaseAscii( sCSS1_PV_sans_serif );
1130                 break;
1131             }
1132 
1133             bContainsKeyword |= bIsKeyword;
1134 
1135             if( !rNames.isEmpty() )
1136                 rNames += ", ";
1137             if( cQuote && !bIsKeyword )
1138                 rNames += OUStringLiteral1( cQuote );
1139             rNames += aName;
1140             if( cQuote && !bIsKeyword )
1141                 rNames += OUStringLiteral1( cQuote );
1142         }
1143     }
1144 
1145     if( !bContainsKeyword && bGeneric )
1146     {
1147         const sal_Char *pStr = nullptr;
1148         switch( rFontItem.GetFamily() )
1149         {
1150         case FAMILY_ROMAN:      pStr = sCSS1_PV_serif;      break;
1151         case FAMILY_SWISS:      pStr = sCSS1_PV_sans_serif; break;
1152         case FAMILY_SCRIPT:     pStr = sCSS1_PV_cursive;    break;
1153         case FAMILY_DECORATIVE: pStr = sCSS1_PV_fantasy;    break;
1154         case FAMILY_MODERN:     pStr = sCSS1_PV_monospace;  break;
1155         default:
1156             ;
1157         }
1158 
1159         if( pStr )
1160         {
1161             if( !rNames.isEmpty() )
1162                 rNames += ", ";
1163             rNames += OStringToOUString( pStr, RTL_TEXTENCODING_ASCII_US );
1164         }
1165     }
1166 }
1167 
1168 bool SwHTMLWriter::HasScriptDependentItems( const SfxItemSet& rItemSet,
1169                                                  bool bCheckDropCap )
1170 {
1171     static const sal_uInt16 aWhichIds[] =
1172     {
1173         RES_CHRATR_FONT,        RES_CHRATR_CJK_FONT,        RES_CHRATR_CTL_FONT,
1174         RES_CHRATR_FONTSIZE,    RES_CHRATR_CJK_FONTSIZE,    RES_CHRATR_CTL_FONTSIZE,
1175         RES_CHRATR_LANGUAGE,    RES_CHRATR_CJK_LANGUAGE,    RES_CHRATR_CTL_LANGUAGE,
1176         RES_CHRATR_POSTURE,     RES_CHRATR_CJK_POSTURE,     RES_CHRATR_CTL_POSTURE,
1177         RES_CHRATR_WEIGHT,      RES_CHRATR_CJK_WEIGHT,      RES_CHRATR_CTL_WEIGHT,
1178         0,                      0,                          0
1179     };
1180 
1181     for( int i=0; aWhichIds[i]; i += 3 )
1182     {
1183         const SfxPoolItem *pItem = nullptr, *pItemCJK = nullptr, *pItemCTL = nullptr, *pTmp;
1184         int nItemCount = 0;
1185         if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i], false,
1186                                                    &pTmp ) )
1187         {
1188             pItem = pTmp;
1189             nItemCount++;
1190         }
1191         if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i+1], false,
1192                                                    &pTmp ) )
1193         {
1194             pItemCJK = pTmp;
1195             nItemCount++;
1196         }
1197         if( SfxItemState::SET == rItemSet.GetItemState( aWhichIds[i+2], false,
1198                                                    &pTmp ) )
1199         {
1200             pItemCTL = pTmp;
1201             nItemCount++;
1202         }
1203 
1204         // If some of the items are set, but not all, we need script dependent
1205         // styles
1206         if( nItemCount > 0 && nItemCount < 3 )
1207             return true;
1208 
1209         if( 3 == nItemCount )
1210         {
1211             // If all items are set, but some of them have different values,
1212             // we need script dependent styles, too. For font items, we have
1213             // to take care about their special HTML/CSS1 representation.
1214             if( RES_CHRATR_FONT == aWhichIds[i] )
1215             {
1216                 if( !swhtml_css1atr_equalFontItems( *pItem, *pItemCJK ) ||
1217                     !swhtml_css1atr_equalFontItems( *pItem, *pItemCTL ) ||
1218                     !swhtml_css1atr_equalFontItems( *pItemCJK, *pItemCTL ) )
1219                     return true;
1220             }
1221             else
1222             {
1223                 if( *pItem != *pItemCJK ||
1224                     *pItem != *pItemCTL ||
1225                     *pItemCJK != *pItemCTL )
1226                     return true;
1227             }
1228         }
1229     }
1230 
1231     const SfxPoolItem *pItem;
1232     if( bCheckDropCap &&
1233         SfxItemState::SET == rItemSet.GetItemState( RES_PARATR_DROP, true,
1234                 &pItem ) )
1235     {
1236         const SwFormatDrop *pDrop = static_cast<const SwFormatDrop *>(pItem);
1237         const SwCharFormat *pDCCharFormat = pDrop->GetCharFormat();
1238         if( pDCCharFormat )
1239         {
1240             //sequence of (start, end) property ranges we want to
1241             //query
1242             SfxItemSet aTstItemSet(
1243                 *pDCCharFormat->GetAttrSet().GetPool(),
1244                 svl::Items<
1245                     RES_CHRATR_FONT, RES_CHRATR_FONT,
1246                     RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
1247                     RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
1248                     RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONT,
1249                     RES_CHRATR_CJK_POSTURE, RES_CHRATR_CTL_FONT,
1250                     RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT>{});
1251             aTstItemSet.Set( pDCCharFormat->GetAttrSet() );
1252             return HasScriptDependentItems( aTstItemSet, false );
1253         }
1254     }
1255 
1256     return false;
1257 }
1258 
1259 static bool OutCSS1Rule( SwHTMLWriter& rHTMLWrt, const OUString& rSelector,
1260                     const SfxItemSet& rItemSet, bool bHasClass,
1261                      bool bCheckForPseudo  )
1262 {
1263     bool bScriptDependent = false;
1264     if( SwHTMLWriter::HasScriptDependentItems( rItemSet, bHasClass ) )
1265     {
1266         bScriptDependent = true;
1267         OUString aSelector( rSelector );
1268 
1269         OUString aPseudo;
1270         if( bCheckForPseudo )
1271         {
1272             sal_Int32 nPos = aSelector.lastIndexOf( ':' );
1273             if( nPos >= 0 )
1274             {
1275                 aPseudo = aSelector.copy( nPos );
1276                 aSelector =aSelector.copy( 0, nPos );
1277             }
1278         }
1279 
1280         if( !bHasClass )
1281         {
1282             // If we are exporting styles for a tag we have to export a tag
1283             // rule for all properties that aren't style dependent and
1284             // some class rule for the additional style dependen properties
1285             {
1286                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1287                                      &rSelector );
1288                 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1289             }
1290 
1291             //sequence of (start, end) property ranges we want to
1292             //query
1293             SfxItemSet aScriptItemSet( *rItemSet.GetPool(),
1294                                        svl::Items<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
1295                                        RES_CHRATR_LANGUAGE, RES_CHRATR_POSTURE,
1296                                        RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
1297                                        RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT>{} );
1298             aScriptItemSet.Put( rItemSet );
1299 
1300             OUString aNewSelector( aSelector );
1301             aNewSelector += ".western" + aPseudo;
1302             {
1303                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1304                                      &aNewSelector );
1305                 rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
1306             }
1307 
1308             aNewSelector = aSelector + ".cjk" + aPseudo;
1309             {
1310                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1311                                      &aNewSelector );
1312                 rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
1313             }
1314 
1315             aNewSelector = aSelector + ".ctl" + aPseudo;
1316             {
1317                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1318                                      &aNewSelector );
1319                 rHTMLWrt.OutCSS1_SfxItemSet( aScriptItemSet, false );
1320             }
1321         }
1322         else
1323         {
1324             // If there are script dependencies and we are derived from a tag,
1325             // when we have to export a style dependent class for all
1326             // scripts
1327             OUString aNewSelector( aSelector );
1328             aNewSelector += "-western" + aPseudo;
1329             {
1330                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1331                                      &aNewSelector );
1332                 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1333             }
1334 
1335             aNewSelector = aSelector + "-cjk" + aPseudo;
1336             {
1337                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1338                                      &aNewSelector );
1339                 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1340             }
1341 
1342             aNewSelector = aSelector + "-ctl" + aPseudo;
1343             {
1344                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1345                                      &aNewSelector );
1346                 rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1347             }
1348         }
1349     }
1350     else
1351     {
1352         // If there are no script dependencies, when all items are
1353         // exported in one step. For hyperlinks only, a script information
1354         // must be there, because these two chr formats don't support
1355         // script dependencies by now.
1356         SwCSS1OutMode aMode( rHTMLWrt,
1357                 rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1358                              &rSelector );
1359         rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1360     }
1361 
1362     return bScriptDependent;
1363 }
1364 
1365 static void OutCSS1DropCapRule(
1366                     SwHTMLWriter& rHTMLWrt, const OUString& rSelector,
1367                     const SwFormatDrop& rDrop, bool bHasClass,
1368                      bool bHasScriptDependencies  )
1369 {
1370     const SwCharFormat *pDCCharFormat = rDrop.GetCharFormat();
1371     if( (bHasScriptDependencies && bHasClass) ||
1372          (pDCCharFormat && SwHTMLWriter::HasScriptDependentItems( pDCCharFormat->GetAttrSet(), false ) ) )
1373     {
1374         OUString aSelector( rSelector );
1375 
1376         OUString aPseudo;
1377         sal_Int32 nPos = aSelector.lastIndexOf( ':' );
1378         if( nPos >= 0 )
1379         {
1380             aPseudo = aSelector.copy( nPos );
1381             aSelector = aSelector.copy( 0, nPos );
1382         }
1383 
1384         if( !bHasClass )
1385         {
1386             // If we are exporting styles for a tag we have to export a tag
1387             // rule for all properties that aren't style dependent and
1388             // some class rule for the additional style dependen properties
1389             {
1390                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_NO_SCRIPT|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1391                                      &rSelector );
1392                 OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop );
1393             }
1394 
1395             SfxItemSet aScriptItemSet( rHTMLWrt.m_pDoc->GetAttrPool(),
1396                                        svl::Items<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
1397                                        RES_CHRATR_LANGUAGE, RES_CHRATR_POSTURE,
1398                                        RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
1399                                        RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT>{} );
1400             if( pDCCharFormat )
1401                 aScriptItemSet.Set( pDCCharFormat->GetAttrSet() );
1402 
1403             OUString aNewSelector( aSelector );
1404             aNewSelector += ".western" + aPseudo;
1405             {
1406                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1407                                      &aNewSelector );
1408                 OutCSS1_SwFormatDropAttrs(  rHTMLWrt, rDrop, &aScriptItemSet );
1409             }
1410 
1411             aNewSelector = aSelector + ".cjk" + aPseudo;
1412             {
1413                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1414                                      &aNewSelector );
1415                 OutCSS1_SwFormatDropAttrs(  rHTMLWrt, rDrop, &aScriptItemSet );
1416             }
1417 
1418             aNewSelector = aSelector + ".ctl" + aPseudo;
1419             {
1420                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1421                                      &aNewSelector );
1422                 OutCSS1_SwFormatDropAttrs(  rHTMLWrt, rDrop, &aScriptItemSet );
1423             }
1424         }
1425         else
1426         {
1427             // If there are script dependencies and we are derived from a tag,
1428             // when we have to export a style dependent class for all
1429             // scripts
1430             OUString aNewSelector( aSelector );
1431             aNewSelector += "-western" + aPseudo;
1432             {
1433                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_WESTERN|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1434                                      &aNewSelector );
1435                 OutCSS1_SwFormatDropAttrs(  rHTMLWrt, rDrop );
1436             }
1437 
1438             aNewSelector = aSelector + "-cjk" + aPseudo;
1439             {
1440                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CJK|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1441                                      &aNewSelector );
1442                 OutCSS1_SwFormatDropAttrs(  rHTMLWrt, rDrop );
1443             }
1444 
1445             aNewSelector = aSelector + "-ctl" + aPseudo;
1446             {
1447                 SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_CTL|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1448                                      &aNewSelector );
1449                 OutCSS1_SwFormatDropAttrs(  rHTMLWrt, rDrop );
1450             }
1451         }
1452     }
1453     else
1454     {
1455         // If there are no script dependencies, when all items are
1456         // exported in one step. For hyperlinks only, a script information
1457         // must be there, because these two chr formats don't support
1458         // script dependencies by now.
1459         SwCSS1OutMode aMode( rHTMLWrt,
1460                 rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_RULE|CSS1_OUTMODE_DROPCAP,
1461                              &rSelector );
1462         OutCSS1_SwFormatDropAttrs( rHTMLWrt, rDrop );
1463     }
1464 }
1465 
1466 static Writer& OutCSS1_SwFormat( Writer& rWrt, const SwFormat& rFormat,
1467                               IDocumentStylePoolAccess/*SwDoc*/ *pDoc, SwDoc *pTemplate )
1468 {
1469     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1470 
1471     bool bCharFormat = false;
1472     switch( rFormat.Which() )
1473     {
1474     case RES_CHRFMT:
1475         bCharFormat = true;
1476         break;
1477 
1478     case RES_TXTFMTCOLL:
1479     case RES_CONDTXTFMTCOLL:
1480         // these template-types can be exported
1481         break;
1482 
1483     default:
1484         // but not these
1485         return rWrt;
1486     }
1487 
1488     // determine Selector and the to-be-exported Attr-Set-depth
1489     OUString aSelector;
1490     sal_uInt16 nRefPoolId = 0;
1491     sal_uInt16 nDeep = GetCSS1Selector( &rFormat, aSelector, nRefPoolId );
1492     if( !nDeep )
1493         return rWrt;    // not derived from a HTML-template
1494 
1495     sal_uInt16 nPoolFormatId = rFormat.GetPoolFormatId();
1496 
1497     // Determine the to-be-exported Attr-Set. We have to distinguish 3 cases:
1498     // - HTML-Tag templates (nDeep==USHRT_MAX):
1499     //   Export Attrs...
1500     //     - that are set in the template, but not in the original of the HTML template
1501     //     - the Default-Attrs for the Attrs, that are set in the Original of the
1502     //       HTML template, but not in the current template.
1503     // - templates directly derived from HTML templates (nDeep==1):
1504     //   Export only Attributes of the template Item-Set w/o its parents.
1505     // - templates in-directly derived from HTML templates (nDeep>1):
1506     //   Export Attributes of the template Item-Set incl. its Parents,
1507     //   but w/o Attributes that are set in the HTML-Tag template.
1508 
1509     // create Item-Set with all Attributes from the template
1510     // (all but for nDeep==1)
1511     const SfxItemSet& rFormatItemSet = rFormat.GetAttrSet();
1512     SfxItemSet aItemSet( *rFormatItemSet.GetPool(), rFormatItemSet.GetRanges() );
1513     aItemSet.Set( rFormatItemSet ); // Was nDeep!=1 that is not working
1514                                     // for script dependent items buts should
1515                                     // not make a difference for any other
1516 
1517     bool bSetDefaults = true, bClearSame = true;
1518     const SwFormat *pRefFormat = nullptr;
1519     const SwFormat *pRefFormatScript = nullptr;
1520     switch( nDeep )
1521     {
1522     case CSS1_FMT_ISTAG:
1523         pRefFormat = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
1524         break;
1525     case CSS1_FMT_CMPREF:
1526         pRefFormat = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pDoc );
1527         pRefFormatScript = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
1528         bClearSame = false;
1529         break;
1530     default:
1531         pRefFormat = SwHTMLWriter::GetParentFormat( rFormat, nDeep );
1532         pRefFormatScript = SwHTMLWriter::GetTemplateFormat( nRefPoolId, pTemplate == nullptr ? nullptr : &pTemplate->getIDocumentStylePoolAccess() );
1533         bSetDefaults = false;
1534         break;
1535     }
1536 
1537     if( pRefFormat )
1538     {
1539         // subtract Item-Set of the Reference template (incl. its Parents)
1540         SwHTMLWriter::SubtractItemSet( aItemSet, pRefFormat->GetAttrSet(),
1541                                        bSetDefaults, bClearSame,
1542                                        pRefFormatScript
1543                                                ? &pRefFormatScript->GetAttrSet()
1544                                             : nullptr  );
1545 
1546         if( !bCharFormat )
1547         {
1548             const SvxULSpaceItem& rULItem = pRefFormat->GetULSpace();
1549             rHTMLWrt.m_nDfltTopMargin = rULItem.GetUpper();
1550             rHTMLWrt.m_nDfltBottomMargin = rULItem.GetLower();
1551         }
1552     }
1553     else if( CSS1_FMT_ISTAG==nDeep && !bCharFormat )
1554     {
1555         // set Default-distance above and below (for the
1556         // case that there is no reference template)
1557         rHTMLWrt.m_nDfltTopMargin = 0;
1558         rHTMLWrt.m_nDfltBottomMargin = HTML_PARSPACE;
1559         if( USER_FMT & nPoolFormatId )
1560         {
1561             // user templates
1562             const OUString& aNm(rFormat.GetName());
1563 
1564             if (aNm == "DD 1" || aNm == "DT 1")
1565                 rHTMLWrt.m_nDfltBottomMargin = 0;
1566             else if (aNm == OOO_STRING_SVTOOLS_HTML_listing)
1567                 rHTMLWrt.m_nDfltBottomMargin = 0;
1568             else if (aNm == OOO_STRING_SVTOOLS_HTML_preformtxt)
1569                 rHTMLWrt.m_nDfltBottomMargin = 0;
1570             else if (aNm == OOO_STRING_SVTOOLS_HTML_xmp)
1571                 rHTMLWrt.m_nDfltBottomMargin = 0;
1572         }
1573         else
1574         {
1575             // Pool templates
1576             switch( nPoolFormatId )
1577             {
1578             case RES_POOLCOLL_HEADLINE1:
1579             case RES_POOLCOLL_HEADLINE2:
1580             case RES_POOLCOLL_HEADLINE3:
1581             case RES_POOLCOLL_HEADLINE4:
1582             case RES_POOLCOLL_HEADLINE5:
1583             case RES_POOLCOLL_HEADLINE6:
1584                 rHTMLWrt.m_nDfltTopMargin = HTML_HEADSPACE;
1585                 break;
1586             case RES_POOLCOLL_SENDADRESS:
1587             case RES_POOLCOLL_HTML_DT:
1588             case RES_POOLCOLL_HTML_DD:
1589             case RES_POOLCOLL_HTML_PRE:
1590                 rHTMLWrt.m_nDfltBottomMargin = 0;
1591                 break;
1592             }
1593         }
1594     }
1595 
1596     // if nothing is to be exported ...
1597     if( !aItemSet.Count() )
1598         return rWrt;
1599 
1600     // There is no support for script dependent hyperlinks by now.
1601     bool bCheckForPseudo = false;
1602     if( bCharFormat &&
1603         (RES_POOLCHR_INET_NORMAL==nRefPoolId ||
1604          RES_POOLCHR_INET_VISIT==nRefPoolId) )
1605         bCheckForPseudo = true;
1606 
1607     // export now the Attributes (incl. selector)
1608     bool bHasScriptDependencies = false;
1609     if( OutCSS1Rule( rHTMLWrt, aSelector, aItemSet, CSS1_FMT_ISTAG != nDeep,
1610                       bCheckForPseudo ) )
1611     {
1612         if( bCharFormat )
1613             rHTMLWrt.m_aScriptTextStyles.insert( rFormat.GetName() );
1614         else
1615         {
1616             if( nPoolFormatId==RES_POOLCOLL_TEXT )
1617                 rHTMLWrt.m_aScriptParaStyles.insert( pDoc->GetTextCollFromPool( RES_POOLCOLL_STANDARD, false )->GetName() );
1618             rHTMLWrt.m_aScriptParaStyles.insert( rFormat.GetName() );
1619         }
1620         bHasScriptDependencies = true;
1621     }
1622 
1623     // export Drop-Caps
1624     const SfxPoolItem *pItem;
1625     if( SfxItemState::SET==aItemSet.GetItemState( RES_PARATR_DROP, false, &pItem ))
1626     {
1627         OUString sOut( aSelector );
1628         sOut += ":" + OStringToOUString( sCSS1_first_letter, RTL_TEXTENCODING_ASCII_US );
1629         const SwFormatDrop *pDrop = static_cast<const SwFormatDrop *>(pItem);
1630         OutCSS1DropCapRule( rHTMLWrt, sOut, *pDrop, CSS1_FMT_ISTAG != nDeep, bHasScriptDependencies );
1631     }
1632 
1633     return rWrt;
1634 }
1635 
1636 static Writer& OutCSS1_SwPageDesc( Writer& rWrt, const SwPageDesc& rPageDesc,
1637                                    IDocumentStylePoolAccess/*SwDoc*/ *pDoc, SwDoc *pTemplate,
1638                                    sal_uInt16 nRefPoolId, bool bExtRef,
1639                                    bool bPseudo )
1640 {
1641     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1642 
1643     const SwPageDesc* pRefPageDesc = nullptr;
1644     if( !bExtRef )
1645         pRefPageDesc = pDoc->GetPageDescFromPool( nRefPoolId, false );
1646     else if( pTemplate )
1647         pRefPageDesc = pTemplate->getIDocumentStylePoolAccess().GetPageDescFromPool( nRefPoolId, false );
1648 
1649     OUString aSelector = "@" + OStringToOUString( sCSS1_page, RTL_TEXTENCODING_ASCII_US );
1650 
1651     if( bPseudo )
1652     {
1653         const sal_Char *pPseudo = nullptr;
1654         switch( rPageDesc.GetPoolFormatId() )
1655         {
1656         case RES_POOLPAGE_FIRST:    pPseudo = sCSS1_first;  break;
1657         case RES_POOLPAGE_LEFT:     pPseudo = sCSS1_left;   break;
1658         case RES_POOLPAGE_RIGHT:    pPseudo = sCSS1_right;  break;
1659         }
1660         if( pPseudo )
1661             aSelector += ":" + OStringToOUString( pPseudo, RTL_TEXTENCODING_ASCII_US );
1662     }
1663 
1664     SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_RULE_ON|CSS1_OUTMODE_TEMPLATE,
1665                          &aSelector );
1666 
1667     // Size: If the only difference is the Landscape-Flag,
1668     // only export Portrait or Landscape. Otherwise export size.
1669     bool bRefLandscape = pRefPageDesc && pRefPageDesc->GetLandscape();
1670     Size aRefSz;
1671     const Size& rSz = rPageDesc.GetMaster().GetFrameSize().GetSize();
1672     if( pRefPageDesc )
1673     {
1674         aRefSz = pRefPageDesc->GetMaster().GetFrameSize().GetSize();
1675         if( bRefLandscape != rPageDesc.GetLandscape() )
1676         {
1677             long nTmp = aRefSz.Height();
1678             aRefSz.setHeight( aRefSz.Width() );
1679             aRefSz.setWidth( nTmp );
1680         }
1681     }
1682 
1683     // TODO: Bad Hack: On the Page-Tabpage there are small rounding errors
1684     // for the page size. Partially because of bug 25535, we stupidly still
1685     // use the Size-Item from Dialog, even if nothing changed.
1686     // Thus: once one visited the Page-Dialog and left it with OK, we get a
1687     // new page size that then gets exported here. To avoid that, we allow
1688     // here small deviations.
1689     if( std::abs( rSz.Width() - aRefSz.Width() ) <= 2 &&
1690         std::abs( rSz.Height() - aRefSz.Height() ) <= 2 )
1691     {
1692         if( bRefLandscape != rPageDesc.GetLandscape() )
1693         {
1694             rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_size,
1695                 rPageDesc.GetLandscape() ? sCSS1_PV_landscape
1696                                          : sCSS1_PV_portrait );
1697         }
1698     }
1699     else
1700     {
1701         OStringBuffer sVal;
1702         AddUnitPropertyValue(sVal, rSz.Width(), rHTMLWrt.GetCSS1Unit());
1703         sVal.append(' ');
1704         AddUnitPropertyValue(sVal, rSz.Height(), rHTMLWrt.GetCSS1Unit());
1705         rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_size, sVal.makeStringAndClear());
1706     }
1707 
1708     // Export the distance-Attributes as normally
1709     const SwFrameFormat &rMaster = rPageDesc.GetMaster();
1710     SfxItemSet aItemSet( *rMaster.GetAttrSet().GetPool(),
1711                          svl::Items<RES_LR_SPACE, RES_UL_SPACE>{} );
1712     aItemSet.Set( rMaster.GetAttrSet() );
1713 
1714     if( pRefPageDesc )
1715     {
1716         SwHTMLWriter::SubtractItemSet( aItemSet,
1717                                        pRefPageDesc->GetMaster().GetAttrSet(),
1718                                        true );
1719     }
1720 
1721     OutCSS1_SvxULSpace_SvxLRSpace( rWrt, aItemSet );
1722 
1723     // If for a Pseudo-Selector no Property had been set, we still
1724     // have to export something, so that the corresponding template is
1725     // created on the next import.
1726     if( rHTMLWrt.m_bFirstCSS1Property && bPseudo )
1727     {
1728         rHTMLWrt.OutNewLine();
1729         OString sTmp(OUStringToOString(aSelector, rHTMLWrt.m_eDestEnc));
1730         rWrt.Strm().WriteCharPtr( sTmp.getStr() ).WriteCharPtr( " {" );
1731         rHTMLWrt.m_bFirstCSS1Property = false;
1732     }
1733 
1734     if( !rHTMLWrt.m_bFirstCSS1Property )
1735         rWrt.Strm().WriteCharPtr( sCSS1_rule_end );
1736 
1737     return rWrt;
1738 }
1739 
1740 static Writer& OutCSS1_SwFootnoteInfo( Writer& rWrt, const SwEndNoteInfo& rInfo,
1741                                   SwDoc *pDoc, bool bHasNotes, bool bEndNote )
1742 {
1743     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1744 
1745     OUString aSelector;
1746 
1747     if( bHasNotes )
1748     {
1749         aSelector = OOO_STRING_SVTOOLS_HTML_anchor "." +
1750                     ( bEndNote ? OUString(OOO_STRING_SVTOOLS_HTML_sdendnote_anc)
1751                                : OUString(OOO_STRING_SVTOOLS_HTML_sdfootnote_anc) );
1752         SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_RULE|CSS1_OUTMODE_TEMPLATE,
1753                              &aSelector );
1754         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_size,
1755                                         sHTML_FTN_fontheight );
1756         rHTMLWrt.Strm().WriteCharPtr( sCSS1_rule_end );
1757     }
1758 
1759     const SwCharFormat *pSymCharFormat = rInfo.GetCharFormat( *pDoc );
1760     if( pSymCharFormat )
1761     {
1762         const SfxItemSet& rFormatItemSet = pSymCharFormat->GetAttrSet();
1763         SfxItemSet aItemSet( *rFormatItemSet.GetPool(), rFormatItemSet.GetRanges() );
1764         aItemSet.Set( rFormatItemSet );
1765 
1766         // If there are footnotes or endnotes, then all Attributes have to be
1767         // exported, so that Netscape displays the document correctly.
1768         // Otherwise it is sufficient, to export the differences to the
1769         // footnote and endnote template.
1770         if( !bHasNotes && rHTMLWrt.m_xTemplate.is() )
1771         {
1772             SwFormat *pRefFormat = rHTMLWrt.m_xTemplate->getIDocumentStylePoolAccess().GetCharFormatFromPool(
1773                         static_cast< sal_uInt16 >(bEndNote ? RES_POOLCHR_ENDNOTE : RES_POOLCHR_FOOTNOTE) );
1774             if( pRefFormat )
1775                 SwHTMLWriter::SubtractItemSet( aItemSet, pRefFormat->GetAttrSet(),
1776                                                true );
1777         }
1778         if( aItemSet.Count() )
1779         {
1780             aSelector = OOO_STRING_SVTOOLS_HTML_anchor "." +
1781                         ( bEndNote ? OUString(OOO_STRING_SVTOOLS_HTML_sdendnote_sym)
1782                                    : OUString(OOO_STRING_SVTOOLS_HTML_sdfootnote_sym));
1783             if( OutCSS1Rule( rHTMLWrt, aSelector, aItemSet, true, false ))
1784                 rHTMLWrt.m_aScriptTextStyles.insert( pSymCharFormat->GetName() );
1785         }
1786     }
1787 
1788     return rWrt;
1789 }
1790 
1791 Writer& OutCSS1_BodyTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet )
1792 {
1793     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1794 
1795     SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON |
1796                                    CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_BODY, nullptr );
1797 
1798     // Only export the attributes of the page template.
1799     // The attributes of the default paragraph template were
1800     // considered already when exporting the paragraph template.
1801 
1802     const SfxPoolItem *pItem;
1803     if( SfxItemState::SET == rItemSet.GetItemState( RES_BACKGROUND, false,
1804                                                &pItem ) )
1805     {
1806         OUString rEmbeddedGraphicName;
1807         OutCSS1_SvxBrush( rWrt, *pItem, Css1Background::Page, &rEmbeddedGraphicName );
1808     }
1809 
1810     if( SfxItemState::SET == rItemSet.GetItemState( RES_BOX, false,
1811                                                &pItem ))
1812     {
1813         OutCSS1_SvxBox( rWrt, *pItem );
1814     }
1815 
1816     if( !rHTMLWrt.m_bFirstCSS1Property )
1817     {
1818         // if a Property was exported as part of a Style-Option,
1819         // the Option still needs to be finished
1820         rWrt.Strm().WriteChar( '\"' );
1821     }
1822 
1823     return rWrt;
1824 }
1825 
1826 Writer& OutCSS1_ParaTagStyleOpt( Writer& rWrt, const SfxItemSet& rItemSet )
1827 {
1828     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1829 
1830     SwCSS1OutMode aMode( rHTMLWrt, rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_STYLE_OPT |
1831                                    CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_PARA, nullptr );
1832     rHTMLWrt.OutCSS1_SfxItemSet( rItemSet, false );
1833 
1834     return rWrt;
1835 }
1836 
1837 // Wrapper for Table background
1838 Writer& OutCSS1_TableBGStyleOpt( Writer& rWrt, const SfxPoolItem& rHt )
1839 {
1840     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1841 
1842     SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON |
1843                                    CSS1_OUTMODE_ENCODE|
1844                                    CSS1_OUTMODE_TABLEBOX, nullptr );
1845     OutCSS1_SvxBrush( rWrt, rHt, Css1Background::Table, nullptr );
1846 
1847     if( !rHTMLWrt.m_bFirstCSS1Property )
1848         rWrt.Strm().WriteChar( '\"' );
1849 
1850     return rWrt;
1851 }
1852 
1853 Writer& OutCSS1_NumBulListStyleOpt( Writer& rWrt, const SwNumRule& rNumRule,
1854                                     sal_uInt8 nLevel )
1855 {
1856     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
1857 
1858     SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT |
1859                                    CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_PARA, nullptr );
1860 
1861     const SwNumFormat& rNumFormat = rNumRule.Get( nLevel );
1862 
1863     long nLSpace = rNumFormat.GetAbsLSpace();
1864     long nFirstLineOffset = rNumFormat.GetFirstLineOffset();
1865     long nDfltFirstLineOffset = HTML_NUMBUL_INDENT;
1866     if( nLevel > 0 )
1867     {
1868         const SwNumFormat& rPrevNumFormat = rNumRule.Get( nLevel-1 );
1869         nLSpace -= rPrevNumFormat.GetAbsLSpace();
1870         nDfltFirstLineOffset = rPrevNumFormat.GetFirstLineOffset();
1871     }
1872 
1873     if( rHTMLWrt.IsHTMLMode(HTMLMODE_LSPACE_IN_NUMBUL) &&
1874         nLSpace != HTML_NUMBUL_MARGINLEFT )
1875         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLSpace );
1876 
1877     if( rHTMLWrt.IsHTMLMode(HTMLMODE_FRSTLINE_IN_NUMBUL) &&
1878         nFirstLineOffset != nDfltFirstLineOffset )
1879         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent, nFirstLineOffset );
1880 
1881     if( !rHTMLWrt.m_bFirstCSS1Property )
1882         rWrt.Strm().WriteChar( '\"' );
1883 
1884     return rWrt;
1885 }
1886 
1887 void SwHTMLWriter::OutCSS1_FrameFormatOptions( const SwFrameFormat& rFrameFormat,
1888                                           HtmlFrmOpts nFrameOpts,
1889                                           const SdrObject *pSdrObj,
1890                                           const SfxItemSet *pItemSet )
1891 {
1892     SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
1893                                 CSS1_OUTMODE_ENCODE|
1894                                 CSS1_OUTMODE_FRAME, nullptr );
1895 
1896     const SwFormatHoriOrient& rHoriOri = rFrameFormat.GetHoriOrient();
1897     SvxLRSpaceItem aLRItem( rFrameFormat.GetLRSpace() );
1898     SvxULSpaceItem aULItem( rFrameFormat.GetULSpace() );
1899     if( nFrameOpts & HtmlFrmOpts::SAlign )
1900     {
1901         const SwFormatAnchor& rAnchor = rFrameFormat.GetAnchor();
1902         switch( rAnchor.GetAnchorId() )
1903         {
1904         case RndStdIds::FLY_AT_PARA:
1905         case RndStdIds::FLY_AT_CHAR:
1906             if( text::RelOrientation::FRAME == rHoriOri.GetRelationOrient() ||
1907                 text::RelOrientation::PRINT_AREA == rHoriOri.GetRelationOrient() )
1908             {
1909                 if( !(nFrameOpts & HtmlFrmOpts::Align) )
1910                 {
1911                     // float
1912                     const sal_Char *pStr = text::HoriOrientation::RIGHT==rHoriOri.GetHoriOrient()
1913                             ? sCSS1_PV_right
1914                             : sCSS1_PV_left;
1915                     OutCSS1_PropertyAscii( sCSS1_P_float, pStr );
1916                 }
1917                 break;
1918             }
1919             [[fallthrough]];
1920 
1921         case RndStdIds::FLY_AT_PAGE:
1922         case RndStdIds::FLY_AT_FLY:
1923             {
1924                 // position
1925                 OutCSS1_PropertyAscii( sCSS1_P_position, sCSS1_PV_absolute );
1926 
1927                 // For top/left we need to subtract the distance to the frame
1928                 // from the position, as in CSS1 it is added to the position.
1929                 // This works also for automatically aligned frames, even that
1930                 // in this case Writer also adds the distance; because in this
1931                 // case the Orient-Attribute contains the correct position.
1932 
1933                 // top
1934                 long nXPos=0, nYPos=0;
1935                 bool bOutXPos = false, bOutYPos = false;
1936                 if( RES_DRAWFRMFMT == rFrameFormat.Which() )
1937                 {
1938                     OSL_ENSURE( pSdrObj, "Do not pass a SdrObject. Inefficient" );
1939                     if( !pSdrObj )
1940                         pSdrObj = rFrameFormat.FindSdrObject();
1941                     OSL_ENSURE( pSdrObj, "Where is the SdrObject" );
1942                     if( pSdrObj )
1943                     {
1944                         Point aPos( pSdrObj->GetRelativePos() );
1945                         nXPos = aPos.X();
1946                         nYPos = aPos.Y();
1947                     }
1948                     bOutXPos = bOutYPos = true;
1949                 }
1950                 else
1951                 {
1952                     bOutXPos = text::RelOrientation::CHAR != rHoriOri.GetRelationOrient();
1953                     nXPos = text::HoriOrientation::NONE == rHoriOri.GetHoriOrient()
1954                                 ? rHoriOri.GetPos() : 0;
1955 
1956                     const SwFormatVertOrient& rVertOri = rFrameFormat.GetVertOrient();
1957                     bOutYPos = text::RelOrientation::CHAR != rVertOri.GetRelationOrient();
1958                     nYPos = text::VertOrientation::NONE == rVertOri.GetVertOrient()
1959                                  ? rVertOri.GetPos() : 0;
1960                 }
1961 
1962                 if( bOutYPos )
1963                 {
1964                     if( IsHTMLMode( HTMLMODE_FLY_MARGINS) )
1965                     {
1966                         nYPos -= aULItem.GetUpper();
1967                         if( nYPos < 0 )
1968                         {
1969                             aULItem.SetUpper( static_cast<sal_uInt16>(aULItem.GetUpper() + nYPos) );
1970                             nYPos = 0;
1971                         }
1972                     }
1973 
1974                     OutCSS1_UnitProperty( sCSS1_P_top, nYPos );
1975                 }
1976 
1977                 if( bOutXPos )
1978                 {
1979                     // left
1980                     if( IsHTMLMode( HTMLMODE_FLY_MARGINS) )
1981                     {
1982                         nXPos -= aLRItem.GetLeft();
1983                         if( nXPos < 0 )
1984                         {
1985                             aLRItem.SetLeft( static_cast<sal_uInt16>(aLRItem.GetLeft() + nXPos) );
1986                             nXPos = 0;
1987                         }
1988                     }
1989 
1990                     OutCSS1_UnitProperty( sCSS1_P_left, nXPos );
1991                 }
1992             }
1993             break;
1994 
1995         default:
1996             ;
1997         }
1998     }
1999 
2000     // width/height
2001     if( nFrameOpts & HtmlFrmOpts::SSize )
2002     {
2003         if( RES_DRAWFRMFMT == rFrameFormat.Which() )
2004         {
2005             OSL_ENSURE( pSdrObj, "Do not pass a SdrObject. Inefficient" );
2006             if( !pSdrObj )
2007                 pSdrObj = rFrameFormat.FindSdrObject();
2008             OSL_ENSURE( pSdrObj, "Where is the SdrObject" );
2009             if( pSdrObj )
2010             {
2011                 Size aTwipSz( pSdrObj->GetLogicRect().GetSize() );
2012                 if( nFrameOpts & HtmlFrmOpts::SWidth )
2013                 {
2014                     if( nFrameOpts & HtmlFrmOpts::SPixSize )
2015                         OutCSS1_PixelProperty( sCSS1_P_width, aTwipSz.Width(),
2016                                                false );
2017                     else
2018                         OutCSS1_UnitProperty( sCSS1_P_width, aTwipSz.Width() );
2019                 }
2020                 if( nFrameOpts & HtmlFrmOpts::SHeight )
2021                 {
2022                     if( nFrameOpts & HtmlFrmOpts::SPixSize )
2023                         OutCSS1_PixelProperty( sCSS1_P_height, aTwipSz.Height(),
2024                                                true );
2025                     else
2026                         OutCSS1_UnitProperty( sCSS1_P_height, aTwipSz.Height() );
2027                 }
2028             }
2029         }
2030         else
2031         {
2032             OSL_ENSURE( HtmlFrmOpts::AbsSize & nFrameOpts,
2033                     "Export absolute size" );
2034             OSL_ENSURE( HtmlFrmOpts::AnySize & nFrameOpts,
2035                     "Export every size" );
2036             Css1FrameSize nMode = Css1FrameSize::NONE;
2037             if( nFrameOpts & HtmlFrmOpts::SWidth )
2038                 nMode |= Css1FrameSize::Width;
2039             if( nFrameOpts & HtmlFrmOpts::SHeight )
2040                 nMode |= Css1FrameSize::MinHeight|Css1FrameSize::FixHeight;
2041             if( nFrameOpts & HtmlFrmOpts::SPixSize )
2042                 nMode |= Css1FrameSize::Pixel;
2043 
2044             OutCSS1_SwFormatFrameSize( *this, rFrameFormat.GetFrameSize(), nMode );
2045         }
2046     }
2047 
2048     const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
2049     // margin-*
2050     if( (nFrameOpts & HtmlFrmOpts::SSpace) &&
2051         IsHTMLMode( HTMLMODE_FLY_MARGINS) )
2052     {
2053         const SvxLRSpaceItem *pLRItem = nullptr;
2054         const SvxULSpaceItem *pULItem = nullptr;
2055         if( SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE ) )
2056             pLRItem = &aLRItem;
2057         if( SfxItemState::SET == rItemSet.GetItemState( RES_UL_SPACE ) )
2058             pULItem = &aULItem;
2059         if( pLRItem || pULItem )
2060             OutCSS1_SvxULSpace_SvxLRSpace( *this, pULItem, pLRItem );
2061     }
2062 
2063     // border
2064     if( nFrameOpts & HtmlFrmOpts::SBorder )
2065     {
2066         const SfxPoolItem* pItem;
2067         if( nFrameOpts & HtmlFrmOpts::SNoBorder )
2068             OutCSS1_SvxBox( *this, rFrameFormat.GetBox() );
2069         else if( SfxItemState::SET==rItemSet.GetItemState( RES_BOX, true, &pItem ) )
2070             OutCSS1_SvxBox( *this, *pItem );
2071     }
2072 
2073     // background (if, then the color must be set also)
2074     if( nFrameOpts & HtmlFrmOpts::SBackground )
2075         OutCSS1_FrameFormatBackground( rFrameFormat );
2076 
2077     if( pItemSet )
2078         OutCSS1_SfxItemSet( *pItemSet, false );
2079 
2080     if( !m_bFirstCSS1Property )
2081         Strm().WriteChar( '\"' );
2082 }
2083 
2084 void SwHTMLWriter::OutCSS1_TableFrameFormatOptions( const SwFrameFormat& rFrameFormat )
2085 {
2086     SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
2087                                 CSS1_OUTMODE_ENCODE|
2088                                 CSS1_OUTMODE_TABLE, nullptr );
2089 
2090     const SfxPoolItem *pItem;
2091     const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
2092     if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) )
2093         OutCSS1_SvxBrush( *this, *pItem, Css1Background::Table, nullptr );
2094 
2095     if( IsHTMLMode( HTMLMODE_PRINT_EXT ) )
2096         OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( *this, rItemSet, false );
2097 
2098     if( SfxItemState::SET==rItemSet.GetItemState( RES_LAYOUT_SPLIT, false, &pItem ) )
2099         OutCSS1_SwFormatLayoutSplit( *this, *pItem );
2100 
2101     if( !m_bFirstCSS1Property )
2102         Strm().WriteChar( '\"' );
2103 }
2104 
2105 void SwHTMLWriter::OutCSS1_TableCellBorderHack(SwFrameFormat const& rFrameFormat)
2106 {
2107     SwCSS1OutMode const aMode( *this,
2108         CSS1_OUTMODE_STYLE_OPT_ON|CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_TABLEBOX, nullptr );
2109     OutCSS1_SvxBox(*this, rFrameFormat.GetBox());
2110     if (!m_bFirstCSS1Property)
2111     {
2112         Strm().WriteChar( cCSS1_style_opt_end );
2113     }
2114 }
2115 
2116 void SwHTMLWriter::OutCSS1_SectionFormatOptions( const SwFrameFormat& rFrameFormat, const SwFormatCol *pCol )
2117 {
2118     SwCSS1OutMode aMode( *this, CSS1_OUTMODE_STYLE_OPT_ON |
2119                                 CSS1_OUTMODE_ENCODE|
2120                                 CSS1_OUTMODE_SECTION, nullptr );
2121 
2122     const SfxPoolItem *pItem;
2123     const SfxItemSet& rItemSet = rFrameFormat.GetAttrSet();
2124     if( SfxItemState::SET==rItemSet.GetItemState( RES_BACKGROUND, false, &pItem ) )
2125         OutCSS1_SvxBrush( *this, *pItem, Css1Background::Section, nullptr );
2126 
2127     if (pCol)
2128     {
2129         OString sColumnCount(OString::number(static_cast<sal_Int32>(pCol->GetNumCols())));
2130         OutCSS1_PropertyAscii(sCSS1_P_column_count, sColumnCount);
2131     }
2132 
2133     if( !m_bFirstCSS1Property )
2134         Strm().WriteChar( '\"' );
2135 }
2136 
2137 static bool OutCSS1_FrameFormatBrush( SwHTMLWriter& rWrt,
2138                                  const SvxBrushItem& rBrushItem )
2139 {
2140     bool bWritten = false;
2141     /// output brush of frame format, if its background color is not "no fill"/"auto fill"
2142     /// or it has a background graphic.
2143     if( rBrushItem.GetColor() != COL_TRANSPARENT ||
2144         !rBrushItem.GetGraphicLink().isEmpty() ||
2145         0 != rBrushItem.GetGraphicPos() )
2146     {
2147         OutCSS1_SvxBrush( rWrt, rBrushItem, Css1Background::Fly, nullptr );
2148         bWritten = true;
2149     }
2150     return bWritten;
2151 }
2152 
2153 void SwHTMLWriter::OutCSS1_FrameFormatBackground( const SwFrameFormat& rFrameFormat )
2154 {
2155     // If the frame itself has a background, then export.
2156     if( OutCSS1_FrameFormatBrush( *this, rFrameFormat.makeBackgroundBrushItem() ) )
2157         return;
2158 
2159     // If the frame is not linked to a page, we use the background of the anchor.
2160     const SwFormatAnchor& rAnchor = rFrameFormat.GetAnchor();
2161     RndStdIds eAnchorId = rAnchor.GetAnchorId();
2162     const SwPosition *pAnchorPos = rAnchor.GetContentAnchor();
2163     if (RndStdIds::FLY_AT_PAGE != eAnchorId && pAnchorPos)
2164     {
2165         const SwNode& rNode = pAnchorPos->nNode.GetNode();
2166         if( rNode.IsContentNode() )
2167         {
2168             // If the frame is linked to a content-node,
2169             // we take the background of the content-node, if it has one.
2170             if( OutCSS1_FrameFormatBrush( *this,
2171                     rNode.GetContentNode()->GetSwAttrSet().GetBackground()) )
2172                 return;
2173 
2174             // Otherwise we also could be in a table
2175             const SwTableNode *pTableNd = rNode.FindTableNode();
2176             if( pTableNd )
2177             {
2178                 const SwStartNode *pBoxSttNd = rNode.FindTableBoxStartNode();
2179                 const SwTableBox *pBox =
2180                     pTableNd->GetTable().GetTableBox( pBoxSttNd->GetIndex() );
2181 
2182                 // If the box has a background, we take it.
2183                 if( OutCSS1_FrameFormatBrush( *this,
2184                         pBox->GetFrameFormat()->makeBackgroundBrushItem() ) )
2185                     return;
2186 
2187                 // Otherwise we use that of the lines
2188                 const SwTableLine *pLine = pBox->GetUpper();
2189                 while( pLine )
2190                 {
2191                     if( OutCSS1_FrameFormatBrush( *this,
2192                             pLine->GetFrameFormat()->makeBackgroundBrushItem() ) )
2193                         return;
2194                     pBox = pLine->GetUpper();
2195                     pLine = pBox ? pBox->GetUpper() : nullptr;
2196                 }
2197 
2198                 // If there was none either, we use the background of the table.
2199                 if( OutCSS1_FrameFormatBrush( *this,
2200                         pTableNd->GetTable().GetFrameFormat()->makeBackgroundBrushItem() ) )
2201                     return;
2202             }
2203 
2204         }
2205 
2206         // If the anchor is again in a Fly-Frame, use the background of the Fly-Frame.
2207         const SwFrameFormat *pFrameFormat = rNode.GetFlyFormat();
2208         if( pFrameFormat )
2209         {
2210             OutCSS1_FrameFormatBackground( *pFrameFormat );
2211             return;
2212         }
2213     }
2214 
2215     // At last there is the background of the page, and as the final rescue
2216     // the value of the Config.
2217     OSL_ENSURE( m_pCurrPageDesc, "no page template found" );
2218     if( !OutCSS1_FrameFormatBrush( *this,
2219                               m_pCurrPageDesc->GetMaster().makeBackgroundBrushItem() ) )
2220     {
2221         Color aColor( COL_WHITE );
2222 
2223         // The background color is normally only used in Browse-Mode.
2224         // We always use it for a HTML document, but for a text document
2225         // only if viewed in Browse-Mode.
2226         if( m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ||
2227             m_pDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE))
2228         {
2229             SwViewShell *pVSh = m_pDoc->getIDocumentLayoutAccess().GetCurrentViewShell();
2230             if ( pVSh &&
2231                  COL_TRANSPARENT != pVSh->GetViewOptions()->GetRetoucheColor())
2232                 aColor = pVSh->GetViewOptions()->GetRetoucheColor();
2233         }
2234 
2235         OutCSS1_PropertyAscii(sCSS1_P_background, GetCSS1_Color(aColor));
2236     }
2237 }
2238 
2239 static Writer& OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( Writer& rWrt,
2240                     const SvxUnderlineItem *pUItem,
2241                     const SvxOverlineItem *pOItem,
2242                     const SvxCrossedOutItem *pCOItem,
2243                     const SvxBlinkItem *pBItem )
2244 {
2245     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2246     bool bNone = false;
2247 
2248     const sal_Char *pUStr = nullptr;
2249     if( pUItem )
2250     {
2251         switch( pUItem->GetLineStyle() )
2252         {
2253         case LINESTYLE_NONE:
2254             bNone = true;
2255             break;
2256         case LINESTYLE_DONTKNOW:
2257             break;
2258         default:
2259             if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2260             {
2261                 // this also works in HTML does not need to be written as
2262                 // a STYLE-Options, and must not be written as Hint
2263                 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rHTMLWrt.mbReqIF,
2264                         "write underline as Hint?" );
2265                 pUStr = sCSS1_PV_underline;
2266             }
2267             break;
2268         }
2269     }
2270 
2271     const sal_Char *pOStr = nullptr;
2272     if( pOItem )
2273     {
2274         switch( pOItem->GetLineStyle() )
2275         {
2276         case LINESTYLE_NONE:
2277             bNone = true;
2278             break;
2279         case LINESTYLE_DONTKNOW:
2280             break;
2281         default:
2282             if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2283             {
2284                 // this also works in HTML does not need to be written as
2285                 // a STYLE-Options, and must not be written as Hint
2286                 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2287                         "write overline as Hint?" );
2288                 pOStr = sCSS1_PV_overline;
2289             }
2290             break;
2291         }
2292     }
2293 
2294     const sal_Char *pCOStr = nullptr;
2295     if( pCOItem )
2296     {
2297         switch( pCOItem->GetStrikeout() )
2298         {
2299         case STRIKEOUT_NONE:
2300             bNone = true;
2301             break;
2302         case STRIKEOUT_DONTKNOW:
2303             break;
2304         default:
2305             if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2306             {
2307                 // this also works in HTML does not need to be written as
2308                 // a STYLE-Options, and must not be written as Hint
2309                 OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) || rHTMLWrt.mbReqIF,
2310                         "write crossedOut as Hint?" );
2311                 pCOStr = sCSS1_PV_line_through;
2312             }
2313             break;
2314         }
2315     }
2316 
2317     const sal_Char *pBStr = nullptr;
2318     if( pBItem )
2319     {
2320         if( !pBItem->GetValue() )
2321         {
2322             bNone = true;
2323         }
2324         else if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2325         {
2326             // this also works in HTML does not need to be written as
2327             // a STYLE-Options, and must not be written as Hint
2328             OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2329                     "write blink as Hint?" );
2330             pBStr = sCSS1_PV_blink;
2331         }
2332     }
2333 
2334     OStringBuffer sOut;
2335     if( pUStr )
2336         sOut.append(pUStr);
2337 
2338     if( pOStr )
2339     {
2340         if (!sOut.isEmpty())
2341             sOut.append(' ');
2342         sOut.append(pOStr);
2343     }
2344 
2345     if( pCOStr )
2346     {
2347         if (!sOut.isEmpty())
2348             sOut.append(' ');
2349         sOut.append(pCOStr);
2350     }
2351 
2352     if( pBStr )
2353     {
2354         if (!sOut.isEmpty())
2355             sOut.append(' ');
2356         sOut.append(pBStr);
2357     }
2358 
2359     if (!sOut.isEmpty())
2360         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sOut.makeStringAndClear() );
2361     else if( bNone )
2362         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_decoration, sCSS1_PV_none );
2363 
2364     return rWrt;
2365 }
2366 
2367 static Writer& OutCSS1_SvxCaseMap( Writer& rWrt, const SfxPoolItem& rHt )
2368 {
2369     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2370 
2371     switch( static_cast<const SvxCaseMapItem&>(rHt).GetCaseMap() )
2372     {
2373     case SvxCaseMap::NotMapped:
2374         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_normal );
2375         break;
2376     case SvxCaseMap::SmallCaps:
2377         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_variant, sCSS1_PV_small_caps );
2378         break;
2379     case SvxCaseMap::Uppercase:
2380         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_uppercase );
2381         break;
2382     case SvxCaseMap::Lowercase:
2383         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_lowercase );
2384         break;
2385     case SvxCaseMap::Capitalize:
2386         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_transform, sCSS1_PV_capitalize );
2387         break;
2388     default:
2389         ;
2390     }
2391 
2392     return rWrt;
2393 }
2394 
2395 static Writer& OutCSS1_SvxColor( Writer& rWrt, const SfxPoolItem& rHt )
2396 {
2397     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2398 
2399     // Colors do not need to be exported for Style-Option.
2400     if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) &&
2401         !rHTMLWrt.m_bCfgPreferStyles )
2402         return rWrt;
2403     OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2404             "write color as Hint?" );
2405 
2406     Color aColor( static_cast<const SvxColorItem&>(rHt).GetValue() );
2407     if( COL_AUTO == aColor )
2408         aColor = COL_BLACK;
2409 
2410     rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_color, GetCSS1_Color(aColor));
2411 
2412     return rWrt;
2413 }
2414 
2415 static Writer& OutCSS1_SvxCrossedOut( Writer& rWrt, const SfxPoolItem& rHt )
2416 {
2417     // This function only exports Hints!
2418     // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
2419 
2420     if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) )
2421         OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
2422                 nullptr, nullptr, static_cast<const SvxCrossedOutItem *>(&rHt), nullptr );
2423 
2424     return rWrt;
2425 }
2426 
2427 static Writer& OutCSS1_SvxFont( Writer& rWrt, const SfxPoolItem& rHt )
2428 {
2429     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2430 
2431     // No need to export Fonts for the Style-Option.
2432     if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2433         return rWrt;
2434 
2435     sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2436     switch( rHt.Which() )
2437     {
2438     case RES_CHRATR_CJK_FONT:   nScript = CSS1_OUTMODE_CJK; break;
2439     case RES_CHRATR_CTL_FONT:   nScript = CSS1_OUTMODE_CTL; break;
2440     }
2441     if( !rHTMLWrt.IsCSS1Script( nScript ) )
2442         return rWrt;
2443 
2444     OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2445             "write Font as Hint?" );
2446 
2447     OUString sOut;
2448     // MS IE3b1 has problems with single quotes
2449     sal_uInt16 nMode = rHTMLWrt.m_nCSS1OutMode & CSS1_OUTMODE_ANY_ON;
2450     sal_Unicode cQuote = nMode == CSS1_OUTMODE_RULE_ON ? '\"' : '\'';
2451     SwHTMLWriter::PrepareFontList( static_cast<const SvxFontItem&>(rHt), sOut, cQuote,
2452                                    true );
2453 
2454     rHTMLWrt.OutCSS1_Property( sCSS1_P_font_family, sOut );
2455 
2456     return rWrt;
2457 }
2458 
2459 static Writer& OutCSS1_SvxFontHeight( Writer& rWrt, const SfxPoolItem& rHt )
2460 {
2461     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2462 
2463     // Font-Height need not be exported in the Style-Option.
2464     // For Drop-Caps another Font-Size is exported.
2465     if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ||
2466         rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_DROPCAP ) )
2467         return rWrt;
2468 
2469     sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2470     switch( rHt.Which() )
2471     {
2472     case RES_CHRATR_CJK_FONTSIZE:   nScript = CSS1_OUTMODE_CJK; break;
2473     case RES_CHRATR_CTL_FONTSIZE:   nScript = CSS1_OUTMODE_CTL; break;
2474     }
2475     if( !rHTMLWrt.IsCSS1Script( nScript ) )
2476         return rWrt;
2477 
2478     sal_uInt32 nHeight = static_cast<const SvxFontHeightItem&>(rHt).GetHeight();
2479     OString sHeight(OString::number(nHeight/20) + OString(sCSS1_UNIT_pt));
2480     rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_font_size, sHeight);
2481 
2482     return rWrt;
2483 }
2484 
2485 static Writer& OutCSS1_SvxPosture( Writer& rWrt, const SfxPoolItem& rHt )
2486 {
2487     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2488 
2489     sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2490     switch( rHt.Which() )
2491     {
2492     case RES_CHRATR_CJK_POSTURE:    nScript = CSS1_OUTMODE_CJK; break;
2493     case RES_CHRATR_CTL_POSTURE:    nScript = CSS1_OUTMODE_CTL; break;
2494     }
2495     if( !rHTMLWrt.IsCSS1Script( nScript ) )
2496         return rWrt;
2497 
2498     const sal_Char *pStr = nullptr;
2499     switch( static_cast<const SvxPostureItem&>(rHt).GetPosture() )
2500     {
2501     case ITALIC_NONE:       pStr = sCSS1_PV_normal;     break;
2502     case ITALIC_OBLIQUE:    pStr = sCSS1_PV_oblique;    break;
2503     case ITALIC_NORMAL:
2504         if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2505         {
2506             // this also works in HTML does not need to be written as
2507             // a STYLE-Options, and must not be written as Hint
2508             OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2509                     "write italic as Hint?" );
2510             pStr = sCSS1_PV_italic;
2511         }
2512         break;
2513     default:
2514         ;
2515     }
2516 
2517     if( pStr )
2518         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_style, pStr );
2519 
2520     return rWrt;
2521 }
2522 
2523 static Writer& OutCSS1_SvxKerning( Writer& rWrt, const SfxPoolItem& rHt )
2524 {
2525     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2526 
2527     sal_Int16 nValue = static_cast<const SvxKerningItem&>(rHt).GetValue();
2528     if( nValue )
2529     {
2530         OStringBuffer sOut;
2531         if( nValue < 0 )
2532         {
2533             sOut.append('-');
2534             nValue = -nValue;
2535         }
2536 
2537         // Width as n.n pt
2538         nValue = (nValue + 1) / 2;  // 1/10pt
2539         sOut.append(OString::number(nValue  / 10) + "." + OString::number(nValue % 10) +
2540                     OString(sCSS1_UNIT_pt));
2541 
2542         rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_letter_spacing,
2543             sOut.makeStringAndClear());
2544     }
2545     else
2546     {
2547         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_letter_spacing,
2548                                         sCSS1_PV_normal );
2549     }
2550 
2551     return rWrt;
2552 }
2553 
2554 static Writer& OutCSS1_SvxLanguage( Writer& rWrt, const SfxPoolItem& rHt )
2555 {
2556     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2557 
2558     // Only export Language rules
2559     if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2560         return rWrt;
2561 
2562     sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2563     switch( rHt.Which() )
2564     {
2565     case RES_CHRATR_CJK_LANGUAGE:   nScript = CSS1_OUTMODE_CJK; break;
2566     case RES_CHRATR_CTL_LANGUAGE:   nScript = CSS1_OUTMODE_CTL; break;
2567     }
2568     if( !rHTMLWrt.IsCSS1Script( nScript ) )
2569         return rWrt;
2570 
2571     OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2572             "write Language as Hint?" );
2573 
2574     LanguageType eLang = static_cast<const SvxLanguageItem &>(rHt).GetLanguage();
2575     if( LANGUAGE_DONTKNOW == eLang )
2576         return rWrt;
2577 
2578     OUString sOut = LanguageTag::convertToBcp47( eLang );
2579 
2580     rHTMLWrt.OutCSS1_Property( sCSS1_P_so_language, sOut );
2581 
2582     return rWrt;
2583 }
2584 
2585 static Writer& OutCSS1_SvxUnderline( Writer& rWrt, const SfxPoolItem& rHt )
2586 {
2587     // This function only exports Hints!
2588     // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
2589 
2590     if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) )
2591         OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
2592                 static_cast<const SvxUnderlineItem *>(&rHt), nullptr, nullptr, nullptr );
2593 
2594     return rWrt;
2595 }
2596 
2597 static Writer& OutCSS1_SvxOverline( Writer& rWrt, const SfxPoolItem& rHt )
2598 {
2599     // This function only exports Hints!
2600     // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
2601 
2602     if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) )
2603         OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
2604                 nullptr, static_cast<const SvxOverlineItem *>(&rHt), nullptr, nullptr );
2605 
2606     return rWrt;
2607 }
2608 
2609 static Writer& OutCSS1_SvxHidden( Writer& rWrt, const SfxPoolItem& rHt )
2610 {
2611     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2612 
2613     if ( static_cast<const SvxCharHiddenItem&>(rHt).GetValue() )
2614         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_display, sCSS1_PV_none );
2615 
2616     return rWrt;
2617 }
2618 
2619 static Writer& OutCSS1_SvxFontWeight( Writer& rWrt, const SfxPoolItem& rHt )
2620 {
2621     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2622 
2623     sal_uInt16 nScript = CSS1_OUTMODE_WESTERN;
2624     switch( rHt.Which() )
2625     {
2626     case RES_CHRATR_CJK_WEIGHT: nScript = CSS1_OUTMODE_CJK; break;
2627     case RES_CHRATR_CTL_WEIGHT: nScript = CSS1_OUTMODE_CTL; break;
2628     }
2629     if( !rHTMLWrt.IsCSS1Script( nScript ) )
2630         return rWrt;
2631 
2632     const sal_Char *pStr = nullptr;
2633     switch( static_cast<const SvxWeightItem&>(rHt).GetWeight() )
2634     {
2635     case WEIGHT_ULTRALIGHT: pStr = sCSS1_PV_extra_light;    break;
2636     case WEIGHT_LIGHT:      pStr = sCSS1_PV_light;          break;
2637     case WEIGHT_SEMILIGHT:  pStr = sCSS1_PV_demi_light;     break;
2638     case WEIGHT_NORMAL:     pStr = sCSS1_PV_normal;         break;
2639     case WEIGHT_SEMIBOLD:   pStr = sCSS1_PV_demi_bold;      break;
2640     case WEIGHT_BOLD:
2641         if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
2642         {
2643             // this also works in HTML does not need to be written as
2644             // a STYLE-Options, and must not be written as Hint
2645             OSL_ENSURE( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT),
2646                     "write bold as Hint?" );
2647             pStr = sCSS1_PV_bold;
2648         }
2649         break;
2650     case WEIGHT_ULTRABOLD:  pStr = sCSS1_PV_extra_bold;     break;
2651     default:
2652         pStr = sCSS1_PV_normal;
2653     }
2654 
2655     if( pStr )
2656         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_font_weight, pStr );
2657 
2658     return rWrt;
2659 }
2660 
2661 static Writer& OutCSS1_SvxBlink( Writer& rWrt, const SfxPoolItem& rHt )
2662 {
2663     // This function only exports Hints!
2664     // Otherwise OutCSS1_SvxTextLn_SvxCrOut_SvxBlink() is called directly.
2665 
2666     if( static_cast<SwHTMLWriter&>(rWrt).IsCSS1Source(CSS1_OUTMODE_HINT) )
2667         OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( rWrt,
2668                 nullptr, nullptr, nullptr, static_cast<const SvxBlinkItem *>(&rHt) );
2669 
2670     return rWrt;
2671 }
2672 
2673 static Writer& OutCSS1_SvxLineSpacing( Writer& rWrt, const SfxPoolItem& rHt )
2674 {
2675     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2676 
2677     // Netscape4 has big problems with cell heights if the line spacing is
2678     // changed within a table and the width of the table is not calculated
2679     // automatically (== if there is a WIDTH-Option)
2680     if( rHTMLWrt.m_bOutTable && rHTMLWrt.m_bCfgNetscape4 )
2681         return rWrt;
2682 
2683     const SvxLineSpacingItem& rLSItem = static_cast<const SvxLineSpacingItem&>(rHt);
2684 
2685     sal_uInt16 nHeight = 0;
2686     sal_uInt16 nPrcHeight = 0;
2687     SvxLineSpaceRule eLineSpace = rLSItem.GetLineSpaceRule();
2688     switch( rLSItem.GetInterLineSpaceRule() )
2689     {
2690     case SvxInterLineSpaceRule::Off:
2691     case SvxInterLineSpaceRule::Fix:
2692         {
2693             switch( eLineSpace )
2694             {
2695             case SvxLineSpaceRule::Min:
2696             case SvxLineSpaceRule::Fix:
2697                 nHeight = rLSItem.GetLineHeight();
2698                 break;
2699             case SvxLineSpaceRule::Auto:
2700                 nPrcHeight = 100;
2701                 break;
2702             default:
2703                 ;
2704             }
2705         }
2706         break;
2707     case SvxInterLineSpaceRule::Prop:
2708         nPrcHeight = rLSItem.GetPropLineSpace();
2709         break;
2710 
2711     default:
2712         ;
2713     }
2714 
2715     if( nHeight )
2716         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_line_height, static_cast<long>(nHeight) );
2717     else if( nPrcHeight &&
2718         !(nPrcHeight < 115 && rHTMLWrt.m_bParaDotLeaders )) // avoid HTML scrollbars and missing descenders
2719     {
2720         OString sHeight(OString::number(nPrcHeight) + "%");
2721         rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_line_height, sHeight);
2722     }
2723 
2724     return rWrt;
2725 }
2726 
2727 static Writer& OutCSS1_SvxAdjust( Writer& rWrt, const SfxPoolItem& rHt )
2728 {
2729     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2730 
2731     // Export Alignment in Style-Option only if the Tag does not allow ALIGN=xxx
2732     if( rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) &&
2733         !rHTMLWrt.m_bNoAlign)
2734         return rWrt;
2735 
2736     const sal_Char* pStr = nullptr;
2737     switch( static_cast<const SvxAdjustItem&>(rHt).GetAdjust() )
2738     {
2739     case SvxAdjust::Left:   pStr = sCSS1_PV_left;       break;
2740     case SvxAdjust::Right:  pStr = sCSS1_PV_right;      break;
2741     case SvxAdjust::Block:  pStr = sCSS1_PV_justify;    break;
2742     case SvxAdjust::Center: pStr = sCSS1_PV_center;     break;
2743     default:
2744         ;
2745     }
2746 
2747     if( pStr )
2748         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_text_align, pStr );
2749 
2750     return rWrt;
2751 }
2752 
2753 static Writer& OutCSS1_SvxFormatSplit( Writer& rWrt, const SfxPoolItem& rHt )
2754 {
2755     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2756 
2757     const sal_Char *pStr = static_cast<const SvxFormatSplitItem&>(rHt).GetValue()
2758                             ? sCSS1_PV_auto
2759                             : sCSS1_PV_avoid;
2760     rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr );
2761 
2762     return rWrt;
2763 }
2764 
2765 static Writer& OutCSS1_SwFormatLayoutSplit( Writer& rWrt, const SfxPoolItem& rHt )
2766 {
2767     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2768 
2769     const sal_Char *pStr = static_cast<const SwFormatLayoutSplit&>(rHt).GetValue()
2770                             ? sCSS1_PV_auto
2771                             : sCSS1_PV_avoid;
2772     rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_inside, pStr );
2773 
2774     return rWrt;
2775 }
2776 
2777 static Writer& OutCSS1_SvxWidows( Writer& rWrt, const SfxPoolItem& rHt )
2778 {
2779     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2780 
2781     OString aStr(OString::number(static_cast<const SvxWidowsItem&>(rHt).GetValue()));
2782     rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_widows, aStr );
2783 
2784     return rWrt;
2785 }
2786 
2787 static Writer& OutCSS1_SvxOrphans( Writer& rWrt, const SfxPoolItem& rHt )
2788 {
2789     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2790 
2791     OString aStr(OString::number(static_cast<const SvxOrphansItem&>(rHt).GetValue()));
2792     rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_orphans, aStr );
2793 
2794     return rWrt;
2795 }
2796 
2797 static void OutCSS1_SwFormatDropAttrs( SwHTMLWriter& rHWrt,
2798                                     const SwFormatDrop& rDrop,
2799                                      const SfxItemSet *pCharFormatItemSet )
2800 {
2801     // Text flows around on right side
2802     rHWrt.OutCSS1_PropertyAscii( sCSS1_P_float, sCSS1_PV_left );
2803 
2804     // number of lines -> use % for Font-Height!
2805     OString sOut(OString::number(rDrop.GetLines()*100) + "%");
2806     rHWrt.OutCSS1_PropertyAscii(sCSS1_P_font_size, sOut);
2807 
2808     // distance to Text = right margin
2809     sal_uInt16 nDistance = rDrop.GetDistance();
2810     if( nDistance > 0 )
2811         rHWrt.OutCSS1_UnitProperty( sCSS1_P_margin_right, nDistance );
2812 
2813     const SwCharFormat *pDCCharFormat = rDrop.GetCharFormat();
2814     if( pCharFormatItemSet )
2815         rHWrt.OutCSS1_SfxItemSet( *pCharFormatItemSet );
2816     else if( pDCCharFormat )
2817         rHWrt.OutCSS1_SfxItemSet( pDCCharFormat->GetAttrSet() );
2818     else if( (rHWrt.m_nCSS1OutMode & CSS1_OUTMODE_ANY_OFF) == CSS1_OUTMODE_RULE_OFF )
2819         rHWrt.Strm().WriteCharPtr( sCSS1_rule_end );
2820 
2821 }
2822 
2823 static Writer& OutCSS1_SwFormatDrop( Writer& rWrt, const SfxPoolItem& rHt )
2824 {
2825     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2826 
2827     // never export as an Option of a paragraph, but only as Hints
2828     if( !rHTMLWrt.IsCSS1Source(CSS1_OUTMODE_HINT) )
2829         return rWrt;
2830 
2831     if( rHTMLWrt.m_bTagOn )
2832     {
2833         SwCSS1OutMode aMode( rHTMLWrt,
2834                              rHTMLWrt.m_nCSS1Script|CSS1_OUTMODE_SPAN_TAG1_ON|CSS1_OUTMODE_ENCODE|
2835                              CSS1_OUTMODE_DROPCAP, nullptr );
2836 
2837         OutCSS1_SwFormatDropAttrs( rHTMLWrt, static_cast<const SwFormatDrop&>(rHt) );
2838         // A "> is already printed by the calling OutCSS1_HintAsSpanTag.
2839     }
2840     else
2841     {
2842         HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false );
2843     }
2844 
2845     return rWrt;
2846 }
2847 
2848 static Writer& OutCSS1_SwFormatFrameSize( Writer& rWrt, const SfxPoolItem& rHt,
2849                                      Css1FrameSize nMode )
2850 {
2851     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2852 
2853     const SwFormatFrameSize& rFSItem = static_cast<const SwFormatFrameSize&>(rHt);
2854 
2855     if( nMode & Css1FrameSize::Width )
2856     {
2857         sal_uInt8 nPrcWidth = rFSItem.GetWidthPercent();
2858         if( nPrcWidth )
2859         {
2860             OString sOut(OString::number(nPrcWidth) + "%");
2861             rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_width, sOut);
2862         }
2863         else if( nMode & Css1FrameSize::Pixel )
2864         {
2865             rHTMLWrt.OutCSS1_PixelProperty( sCSS1_P_width,
2866                                             rFSItem.GetSize().Width(), false );
2867         }
2868         else
2869         {
2870             rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_width,
2871                                            rFSItem.GetSize().Width() );
2872         }
2873     }
2874 
2875     if( nMode & Css1FrameSize::AnyHeight )
2876     {
2877         bool bOutHeight = false;
2878         switch( rFSItem.GetHeightSizeType() )
2879         {
2880         case ATT_FIX_SIZE:
2881             bOutHeight = bool(nMode & Css1FrameSize::FixHeight);
2882             break;
2883         case ATT_MIN_SIZE:
2884             bOutHeight = bool(nMode & Css1FrameSize::MinHeight);
2885             break;
2886         default:
2887             OSL_ENSURE( bOutHeight, "Height will not be exported" );
2888             break;
2889         }
2890 
2891         if( bOutHeight )
2892         {
2893             sal_uInt8 nPrcHeight = rFSItem.GetHeightPercent();
2894             if( nPrcHeight )
2895             {
2896                 OString sOut(OString::number(nPrcHeight) + "%");
2897                 rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_height, sOut);
2898             }
2899             else if( nMode & Css1FrameSize::Pixel )
2900             {
2901                 rHTMLWrt.OutCSS1_PixelProperty( sCSS1_P_height,
2902                                                 rFSItem.GetSize().Height(),
2903                                                 true );
2904             }
2905             else
2906             {
2907                 rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_height,
2908                                                rFSItem.GetSize().Height() );
2909             }
2910         }
2911     }
2912 
2913     return rWrt;
2914 }
2915 
2916 static Writer& OutCSS1_SvxLRSpace( Writer& rWrt, const SfxPoolItem& rHt )
2917 {
2918     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2919 
2920     const SvxLRSpaceItem& rLRItem = static_cast<const SvxLRSpaceItem&>(rHt);
2921 
2922     // No Export of a firm attribute is needed if the new values
2923     // match that of the current template
2924 
2925     // A left margin can exist because of a list nearby
2926     long nLeftMargin = rLRItem.GetTextLeft() - rHTMLWrt.m_nLeftMargin;
2927     if( rHTMLWrt.m_nDfltLeftMargin != nLeftMargin )
2928     {
2929         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_left, nLeftMargin );
2930 
2931         // max-width = max-width - margin-left for TOC paragraphs with dot leaders
2932         if( rHTMLWrt.m_bParaDotLeaders )
2933             rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_max_width, long(DOT_LEADERS_MAX_WIDTH/2.54*72*20) - nLeftMargin );
2934 
2935     }
2936 
2937     if( rHTMLWrt.m_nDfltRightMargin != rLRItem.GetRight() )
2938     {
2939         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_right, rLRItem.GetRight() );
2940     }
2941 
2942     // The LineIndent of the first line might contain the room for numbering
2943     long nFirstLineIndent = static_cast<long>(rLRItem.GetTextFirstLineOfst()) -
2944         rHTMLWrt.m_nFirstLineIndent;
2945     if( rHTMLWrt.m_nDfltFirstLineIndent != nFirstLineIndent )
2946     {
2947         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_text_indent,
2948                                      nFirstLineIndent );
2949     }
2950 
2951     return rWrt;
2952 }
2953 
2954 static Writer& OutCSS1_SvxULSpace( Writer& rWrt, const SfxPoolItem& rHt )
2955 {
2956     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2957 
2958     const SvxULSpaceItem& rULItem = static_cast<const SvxULSpaceItem&>(rHt);
2959 
2960     if( rHTMLWrt.m_nDfltTopMargin != rULItem.GetUpper() )
2961     {
2962         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_top,
2963                                      static_cast<long>(rULItem.GetUpper()) );
2964     }
2965 
2966     if( rHTMLWrt.m_nDfltBottomMargin != rULItem.GetLower() )
2967     {
2968         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin_bottom,
2969                                      static_cast<long>(rULItem.GetLower()) );
2970     }
2971 
2972     return rWrt;
2973 }
2974 
2975 static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt,
2976                                         const SvxULSpaceItem *pULItem,
2977                                         const SvxLRSpaceItem *pLRItem )
2978 {
2979     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
2980 
2981     if( pLRItem && pULItem &&
2982         pLRItem->GetLeft() == pLRItem->GetRight() &&
2983         pLRItem->GetLeft() == pULItem->GetUpper() &&
2984         pLRItem->GetLeft() == pULItem->GetLower() &&
2985         pLRItem->GetLeft() != rHTMLWrt.m_nDfltLeftMargin &&
2986         pLRItem->GetRight() != rHTMLWrt.m_nDfltRightMargin &&
2987         pULItem->GetUpper() != rHTMLWrt.m_nDfltTopMargin &&
2988         pULItem->GetLower() != rHTMLWrt.m_nDfltBottomMargin )
2989     {
2990         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_margin, pLRItem->GetLeft() );
2991     }
2992     else
2993     {
2994         if( pLRItem )
2995             OutCSS1_SvxLRSpace( rWrt, *pLRItem );
2996         if( pULItem )
2997             OutCSS1_SvxULSpace( rWrt, *pULItem );
2998     }
2999 
3000     return rWrt;
3001 }
3002 
3003 static Writer& OutCSS1_SvxULSpace_SvxLRSpace( Writer& rWrt,
3004                                         const SfxItemSet& rItemSet )
3005 {
3006     const SvxULSpaceItem *pULSpace = nullptr;
3007     const SvxLRSpaceItem *pLRSpace = nullptr;
3008     const SfxPoolItem *pItem;
3009     if( SfxItemState::SET == rItemSet.GetItemState( RES_LR_SPACE, false/*bDeep*/, &pItem ) )
3010         pLRSpace = static_cast<const SvxLRSpaceItem *>(pItem);
3011 
3012     if( SfxItemState::SET == rItemSet.GetItemState( RES_UL_SPACE, false/*bDeep*/, &pItem ) )
3013         pULSpace = static_cast<const SvxULSpaceItem *>(pItem);
3014 
3015     if( pLRSpace || pULSpace )
3016         OutCSS1_SvxULSpace_SvxLRSpace( rWrt, pULSpace, pLRSpace );
3017 
3018     return rWrt;
3019 }
3020 
3021 static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt,
3022                                         const SvxFormatBreakItem *pBreakItem,
3023                                         const SwFormatPageDesc *pPDescItem,
3024                                         const SvxFormatKeepItem *pKeepItem )
3025 {
3026     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3027 
3028     if( !rHTMLWrt.IsHTMLMode(HTMLMODE_PRINT_EXT) )
3029         return rWrt;
3030 
3031     const sal_Char *pBreakBefore = nullptr;
3032     const sal_Char *pBreakAfter = nullptr;
3033 
3034     if( pKeepItem )
3035     {
3036         pBreakAfter = pKeepItem->GetValue() ? sCSS1_PV_avoid : sCSS1_PV_auto;
3037     }
3038     if( pBreakItem )
3039     {
3040         switch( pBreakItem->GetBreak() )
3041         {
3042         case SvxBreak::NONE:
3043             pBreakBefore = sCSS1_PV_auto;
3044             if( !pBreakAfter )
3045                 pBreakAfter = sCSS1_PV_auto;
3046             break;
3047 
3048         case SvxBreak::PageBefore:
3049             pBreakBefore = sCSS1_PV_always;
3050             break;
3051 
3052         case SvxBreak::PageAfter:
3053             pBreakAfter= sCSS1_PV_always;
3054             break;
3055 
3056         default:
3057             ;
3058         }
3059     }
3060     if( pPDescItem )
3061     {
3062         const SwPageDesc *pPDesc = pPDescItem->GetPageDesc();
3063         if( pPDesc )
3064         {
3065             switch( pPDesc->GetPoolFormatId() )
3066             {
3067             case RES_POOLPAGE_LEFT:     pBreakBefore = sCSS1_PV_left;   break;
3068             case RES_POOLPAGE_RIGHT:    pBreakBefore = sCSS1_PV_right;  break;
3069             default:                    pBreakBefore = sCSS1_PV_always; break;
3070             }
3071         }
3072         else if( !pBreakBefore )
3073         {
3074             pBreakBefore = sCSS1_PV_auto;
3075         }
3076     }
3077 
3078     if (rHTMLWrt.mbSkipHeaderFooter)
3079         // No page break when writing only a fragment.
3080         return rWrt;
3081 
3082     if( pBreakBefore )
3083         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_before,
3084                                         pBreakBefore );
3085     if( pBreakAfter )
3086         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_page_break_after,
3087                                         pBreakAfter );
3088 
3089     return rWrt;
3090 }
3091 
3092 static Writer& OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( Writer& rWrt,
3093                                         const SfxItemSet& rItemSet,
3094                                         bool bDeep )
3095 {
3096     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3097     const SfxPoolItem *pItem;
3098     const SvxFormatBreakItem *pBreakItem = nullptr;
3099     if( SfxItemState::SET==rItemSet.GetItemState( RES_BREAK, bDeep, &pItem ))
3100         pBreakItem = static_cast<const SvxFormatBreakItem *>(pItem);
3101 
3102     const SwFormatPageDesc *pPDescItem = nullptr;
3103     if( ( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) ||
3104           !rHTMLWrt.m_bCSS1IgnoreFirstPageDesc ||
3105           rHTMLWrt.m_pStartNdIdx->GetIndex() !=
3106                       rHTMLWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() ) &&
3107         SfxItemState::SET==rItemSet.GetItemState( RES_PAGEDESC, bDeep, &pItem ))
3108         pPDescItem = static_cast<const SwFormatPageDesc*>(pItem);
3109 
3110     const SvxFormatKeepItem *pKeepItem = nullptr;
3111     if( SfxItemState::SET==rItemSet.GetItemState( RES_KEEP, bDeep, &pItem ))
3112         pKeepItem = static_cast<const SvxFormatKeepItem *>(pItem);
3113 
3114     if( pBreakItem || pPDescItem || pKeepItem )
3115         OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( rWrt, pBreakItem,
3116                                                    pPDescItem, pKeepItem );
3117 
3118     return rWrt;
3119 }
3120 
3121 // Wrapper for OutCSS1_SfxItemSet etc.
3122 static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt )
3123 {
3124     OutCSS1_SvxBrush( rWrt, rHt, Css1Background::Attr, nullptr );
3125     return rWrt;
3126 }
3127 
3128 static Writer& OutCSS1_SvxBrush( Writer& rWrt, const SfxPoolItem& rHt,
3129                                  Css1Background nMode,
3130                                  const OUString* pGraphicName)
3131 {
3132     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3133 
3134     // The Character-Attribute is skipped, if we are about to
3135     // exporting options
3136     if( rHt.Which() < RES_CHRATR_END &&
3137         rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
3138         return rWrt;
3139 
3140     // start getting a few values
3141 //  const Brush &rBrush = static_cast<const SvxBrushItem &>(rHt).GetBrush();
3142     const Color & rColor = static_cast<const SvxBrushItem &>(rHt).GetColor();
3143     OUString aLink = pGraphicName ? *pGraphicName
3144                             : static_cast<const SvxBrushItem &>(rHt).GetGraphicLink();
3145     SvxGraphicPosition ePos = static_cast<const SvxBrushItem &>(rHt).GetGraphicPos();
3146     if( Css1Background::Page == nMode && !rHTMLWrt.mbEmbedImages )
3147     {
3148         // page style images are exported if not tiled
3149         if( aLink.isEmpty() || GPOS_TILED==ePos )
3150             return rWrt;
3151     }
3152 
3153     // get the color
3154     bool bColor = false;
3155     /// set <bTransparent> to true, if color is "no fill"/"auto fill"
3156     bool bTransparent = (rColor == COL_TRANSPARENT);
3157     Color aColor;
3158     if( !bTransparent )
3159     {
3160         aColor = rColor;
3161         bColor = true;
3162     }
3163 
3164     // and now the Graphic
3165     OUString aGraphicInBase64;
3166     OUString aGraphicAsLink;
3167 
3168     // Embedded Graphic -> export WriteEmbedded
3169     const Graphic* pGrf = nullptr;
3170     if( rHTMLWrt.mbEmbedImages || aLink.isEmpty())
3171     {
3172         pGrf = static_cast<const SvxBrushItem &>(rHt).GetGraphic();
3173         if( pGrf )
3174         {
3175             if( !XOutBitmap::GraphicToBase64(*pGrf, aGraphicInBase64) )
3176             {
3177                 rHTMLWrt.m_nWarn = WARN_SWG_POOR_LOAD;
3178             }
3179         }
3180         aLink.clear();
3181     }
3182     else if( !pGraphicName && rHTMLWrt.m_bCfgCpyLinkedGrfs )
3183     {
3184         aGraphicAsLink = aLink;
3185         rWrt.CopyLocalFileToINet( aGraphicAsLink );
3186         aLink = aGraphicAsLink;
3187     }
3188     // In tables we only export something if there is a Graphic
3189     if( Css1Background::Table==nMode && !pGrf && !aLink.isEmpty())
3190         return rWrt;
3191 
3192     // if necessary, add the orientation of the Graphic
3193     const sal_Char *pRepeat = nullptr, *pHori = nullptr, *pVert = nullptr;
3194     if( pGrf || !aLink.isEmpty() )
3195     {
3196         if( GPOS_TILED==ePos )
3197         {
3198             pRepeat = sCSS1_PV_repeat;
3199         }
3200         else
3201         {
3202             switch( ePos )
3203             {
3204             case GPOS_LT:
3205             case GPOS_MT:
3206             case GPOS_RT:
3207                 pHori = sCSS1_PV_top;
3208                 break;
3209 
3210             case GPOS_LM:
3211             case GPOS_MM:
3212             case GPOS_RM:
3213                 pHori = sCSS1_PV_middle;
3214                 break;
3215 
3216             case GPOS_LB:
3217             case GPOS_MB:
3218             case GPOS_RB:
3219                 pHori = sCSS1_PV_bottom;
3220                 break;
3221 
3222             default:
3223                 ;
3224             }
3225 
3226             switch( ePos )
3227             {
3228             case GPOS_LT:
3229             case GPOS_LM:
3230             case GPOS_LB:
3231                 pVert = sCSS1_PV_left;
3232                 break;
3233 
3234             case GPOS_MT:
3235             case GPOS_MM:
3236             case GPOS_MB:
3237                 pVert = sCSS1_PV_center;
3238                 break;
3239 
3240             case GPOS_RT:
3241             case GPOS_RM:
3242             case GPOS_RB:
3243                 pVert = sCSS1_PV_right;
3244                 break;
3245 
3246             default:
3247                 ;
3248             }
3249 
3250             if( pHori || pVert )
3251                 pRepeat = sCSS1_PV_no_repeat;
3252         }
3253     }
3254 
3255     // now build the string
3256     OUString sOut;
3257     if( !pGrf && aLink.isEmpty() && !bColor )
3258     {
3259         // no color and no Link, but a transparent Brush
3260         if( bTransparent && Css1Background::Fly != nMode )
3261             sOut += OStringToOUString(sCSS1_PV_transparent, RTL_TEXTENCODING_ASCII_US);
3262     }
3263     else
3264     {
3265         if( bColor )
3266         {
3267             OString sTmp(GetCSS1_Color(aColor));
3268             sOut += OStringToOUString(sTmp, RTL_TEXTENCODING_ASCII_US);
3269         }
3270 
3271         if( pGrf || !aLink.isEmpty() )
3272         {
3273             if( bColor )
3274                 sOut += " ";
3275 
3276             if(pGrf)
3277             {
3278                 sOut += OStringToOUString(sCSS1_url, RTL_TEXTENCODING_ASCII_US) +
3279                     "(\'" OOO_STRING_SVTOOLS_HTML_O_data ":" + aGraphicInBase64 + "\')";
3280             }
3281             else
3282             {
3283                 sOut += OStringToOUString(sCSS1_url, RTL_TEXTENCODING_ASCII_US)+
3284                      "(" +  URIHelper::simpleNormalizedMakeRelative(rWrt.GetBaseURL(),
3285                              aLink) + ")";
3286             }
3287 
3288             if( pRepeat )
3289             {
3290                 sOut += " " + OStringToOUString(pRepeat, RTL_TEXTENCODING_ASCII_US);
3291             }
3292 
3293             if( pHori )
3294             {
3295                 sOut += " " + OStringToOUString(pHori, RTL_TEXTENCODING_ASCII_US);
3296             }
3297             if( pVert )
3298             {
3299                 sOut += " " + OStringToOUString(pVert, RTL_TEXTENCODING_ASCII_US);
3300             }
3301 
3302             sOut += " " + OStringToOUString(sCSS1_PV_scroll, RTL_TEXTENCODING_ASCII_US) + " ";
3303         }
3304     }
3305 
3306     if( !sOut.isEmpty() )
3307         rHTMLWrt.OutCSS1_Property( sCSS1_P_background, sOut );
3308 
3309     return rWrt;
3310 }
3311 
3312 static void OutCSS1_SvxBorderLine( SwHTMLWriter& rHTMLWrt,
3313                                    const sal_Char *pProperty,
3314                                    const SvxBorderLine *pLine )
3315 {
3316     if( !pLine || pLine->isEmpty() )
3317     {
3318         rHTMLWrt.OutCSS1_PropertyAscii( pProperty, sCSS1_PV_none );
3319         return;
3320     }
3321 
3322     sal_Int32 nWidth = pLine->GetWidth();
3323 
3324     OStringBuffer sOut;
3325     if( Application::GetDefaultDevice() &&
3326         nWidth <= Application::GetDefaultDevice()->PixelToLogic(
3327                     Size( 1, 1 ), MapMode( MapUnit::MapTwip) ).Width() )
3328     {
3329         // If the width is smaller than one pixel, then export as 1px
3330         // so that Netscape and IE show the line.
3331         sOut.append("1px");
3332     }
3333     else
3334     {
3335         nWidth *= 5;    // 1/100pt
3336 
3337         // width in n.nn pt
3338         sOut.append(OString::number(nWidth / 100) + "." + OString::number((nWidth/10) % 10) +
3339                     OString::number(nWidth % 10) + OString(sCSS1_UNIT_pt));
3340     }
3341 
3342     // Line-Style: solid or double
3343     sOut.append(' ');
3344     switch (pLine->GetBorderLineStyle())
3345     {
3346         case SvxBorderLineStyle::SOLID:
3347             sOut.append(sCSS1_PV_solid);
3348             break;
3349         case SvxBorderLineStyle::DOTTED:
3350             sOut.append(sCSS1_PV_dotted);
3351             break;
3352         case SvxBorderLineStyle::DASHED:
3353             sOut.append(sCSS1_PV_dashed);
3354             break;
3355         case SvxBorderLineStyle::DOUBLE:
3356         case SvxBorderLineStyle::THINTHICK_SMALLGAP:
3357         case SvxBorderLineStyle::THINTHICK_MEDIUMGAP:
3358         case SvxBorderLineStyle::THINTHICK_LARGEGAP:
3359         case SvxBorderLineStyle::THICKTHIN_SMALLGAP:
3360         case SvxBorderLineStyle::THICKTHIN_MEDIUMGAP:
3361         case SvxBorderLineStyle::THICKTHIN_LARGEGAP:
3362             sOut.append(sCSS1_PV_double);
3363             break;
3364         case SvxBorderLineStyle::EMBOSSED:
3365             sOut.append(sCSS1_PV_ridge);
3366             break;
3367         case SvxBorderLineStyle::ENGRAVED:
3368             sOut.append(sCSS1_PV_groove);
3369             break;
3370         case SvxBorderLineStyle::INSET:
3371             sOut.append(sCSS1_PV_inset);
3372             break;
3373         case SvxBorderLineStyle::OUTSET:
3374             sOut.append(sCSS1_PV_outset);
3375             break;
3376         default:
3377             sOut.append(sCSS1_PV_none);
3378     }
3379     sOut.append(' ');
3380 
3381     // and also the color
3382     sOut.append(GetCSS1_Color(pLine->GetColor()));
3383 
3384     rHTMLWrt.OutCSS1_PropertyAscii(pProperty, sOut.makeStringAndClear());
3385 }
3386 
3387 Writer& OutCSS1_SvxBox( Writer& rWrt, const SfxPoolItem& rHt )
3388 {
3389     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3390 
3391     // Avoid interference between character and paragraph attributes
3392     if( rHt.Which() < RES_CHRATR_END &&
3393         rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_PARA ) )
3394         return rWrt;
3395 
3396     if( rHt.Which() == RES_CHRATR_BOX )
3397     {
3398         if( rHTMLWrt.m_bTagOn )
3399         {
3400             // Inline-block to make the line height changing correspond to the character border
3401             rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_display, "inline-block");
3402         }
3403         else
3404         {
3405             HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span, false );
3406             return rWrt;
3407         }
3408     }
3409 
3410     const SvxBoxItem& rBoxItem = static_cast<const SvxBoxItem&>(rHt);
3411     const SvxBorderLine *pTop = rBoxItem.GetTop();
3412     const SvxBorderLine *pBottom = rBoxItem.GetBottom();
3413     const SvxBorderLine *pLeft = rBoxItem.GetLeft();
3414     const SvxBorderLine *pRight = rBoxItem.GetRight();
3415 
3416     if( (pTop && pBottom && pLeft && pRight &&
3417          *pTop == *pBottom && *pTop == *pLeft && *pTop == *pRight) ||
3418          (!pTop && !pBottom && !pLeft && !pRight) )
3419     {
3420         // all Lines are set and equal, or all Lines are not set
3421         // => border : ...
3422         OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border, pTop );
3423     }
3424     else
3425     {
3426         // otherwise export all Lines separately
3427         OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_top, pTop );
3428         OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_bottom, pBottom );
3429         OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_left, pLeft );
3430         OutCSS1_SvxBorderLine( rHTMLWrt, sCSS1_P_border_right, pRight );
3431     }
3432 
3433     long nTopDist = pTop ? rBoxItem.GetDistance( SvxBoxItemLine::TOP ) : 0;
3434     long nBottomDist = pBottom ? rBoxItem.GetDistance( SvxBoxItemLine::BOTTOM ) : 0;
3435     long nLeftDist = pLeft ? rBoxItem.GetDistance( SvxBoxItemLine::LEFT ) : 0;
3436     long nRightDist = pRight ? rBoxItem.GetDistance( SvxBoxItemLine::RIGHT ) : 0;
3437 
3438     if( nTopDist == nBottomDist && nLeftDist == nRightDist )
3439     {
3440         OStringBuffer sVal;
3441         AddUnitPropertyValue(sVal, nTopDist, rHTMLWrt.GetCSS1Unit());
3442         if( nTopDist != nLeftDist )
3443         {
3444             sVal.append(' ');
3445             AddUnitPropertyValue(sVal, nLeftDist, rHTMLWrt.GetCSS1Unit());
3446         }
3447         rHTMLWrt.OutCSS1_PropertyAscii(sCSS1_P_padding, sVal.makeStringAndClear());
3448     }
3449     else
3450     {
3451         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_top, nTopDist );
3452         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_bottom, nBottomDist );
3453         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_left, nLeftDist );
3454         rHTMLWrt.OutCSS1_UnitProperty( sCSS1_P_padding_right, nRightDist );
3455     }
3456 
3457     return rWrt;
3458 }
3459 
3460 static Writer& OutCSS1_SvxFrameDirection( Writer& rWrt, const SfxPoolItem& rHt )
3461 {
3462     SwHTMLWriter& rHTMLWrt = static_cast< SwHTMLWriter& >( rWrt  );
3463 
3464     // Language will be exported rules only
3465     if( !rHTMLWrt.IsCSS1Source( CSS1_OUTMODE_TEMPLATE ) )
3466         return rWrt;
3467 
3468     SvxFrameDirection nDir =
3469         static_cast< const SvxFrameDirectionItem& >( rHt ).GetValue();
3470     const sal_Char* pStr = nullptr;
3471     switch( nDir )
3472     {
3473     case SvxFrameDirection::Horizontal_LR_TB:
3474     case SvxFrameDirection::Vertical_LR_TB:
3475         pStr = sCSS1_PV_ltr;
3476         break;
3477     case SvxFrameDirection::Horizontal_RL_TB:
3478     case SvxFrameDirection::Vertical_RL_TB:
3479         pStr = sCSS1_PV_rtl;
3480         break;
3481     case SvxFrameDirection::Environment:
3482         pStr = sCSS1_PV_inherit;
3483         break;
3484     default: break;
3485     }
3486 
3487     if( pStr )
3488         rHTMLWrt.OutCSS1_PropertyAscii( sCSS1_P_direction, pStr );
3489 
3490     return rWrt;
3491 }
3492 
3493 /*
3494  * Place here the table for the HTML-Function-Pointer to the
3495  * Export-Functions.
3496  * They are local structures, only needed within the HTML-DLL.
3497  */
3498 
3499 static SwAttrFnTab const aCSS1AttrFnTab = {
3500 /* RES_CHRATR_CASEMAP   */          OutCSS1_SvxCaseMap,
3501 /* RES_CHRATR_CHARSETCOLOR  */      nullptr,
3502 /* RES_CHRATR_COLOR */              OutCSS1_SvxColor,
3503 /* RES_CHRATR_CONTOUR   */          nullptr,
3504 /* RES_CHRATR_CROSSEDOUT    */      OutCSS1_SvxCrossedOut,
3505 /* RES_CHRATR_ESCAPEMENT    */      nullptr,
3506 /* RES_CHRATR_FONT  */              OutCSS1_SvxFont,
3507 /* RES_CHRATR_FONTSIZE  */          OutCSS1_SvxFontHeight,
3508 /* RES_CHRATR_KERNING   */          OutCSS1_SvxKerning,
3509 /* RES_CHRATR_LANGUAGE  */          OutCSS1_SvxLanguage,
3510 /* RES_CHRATR_POSTURE   */          OutCSS1_SvxPosture,
3511 /* RES_CHRATR_UNUSED1*/             nullptr,
3512 /* RES_CHRATR_SHADOWED  */          nullptr,
3513 /* RES_CHRATR_UNDERLINE */          OutCSS1_SvxUnderline,
3514 /* RES_CHRATR_WEIGHT    */          OutCSS1_SvxFontWeight,
3515 /* RES_CHRATR_WORDLINEMODE  */      nullptr,
3516 /* RES_CHRATR_AUTOKERN  */          nullptr,
3517 /* RES_CHRATR_BLINK */              OutCSS1_SvxBlink,
3518 /* RES_CHRATR_NOHYPHEN  */          nullptr, // new: don't separate
3519 /* RES_CHRATR_UNUSED2 */            nullptr,
3520 /* RES_CHRATR_BACKGROUND */         OutCSS1_SvxBrush, // new: character background
3521 /* RES_CHRATR_CJK_FONT */           OutCSS1_SvxFont,
3522 /* RES_CHRATR_CJK_FONTSIZE */       OutCSS1_SvxFontHeight,
3523 /* RES_CHRATR_CJK_LANGUAGE */       OutCSS1_SvxLanguage,
3524 /* RES_CHRATR_CJK_POSTURE */        OutCSS1_SvxPosture,
3525 /* RES_CHRATR_CJK_WEIGHT */         OutCSS1_SvxFontWeight,
3526 /* RES_CHRATR_CTL_FONT */           OutCSS1_SvxFont,
3527 /* RES_CHRATR_CTL_FONTSIZE */       OutCSS1_SvxFontHeight,
3528 /* RES_CHRATR_CTL_LANGUAGE */       OutCSS1_SvxLanguage,
3529 /* RES_CHRATR_CTL_POSTURE */        OutCSS1_SvxPosture,
3530 /* RES_CHRATR_CTL_WEIGHT */         OutCSS1_SvxFontWeight,
3531 /* RES_CHRATR_ROTATE */             nullptr,
3532 /* RES_CHRATR_EMPHASIS_MARK */      nullptr,
3533 /* RES_CHRATR_TWO_LINES */          nullptr,
3534 /* RES_CHRATR_SCALEW */             nullptr,
3535 /* RES_CHRATR_RELIEF */             nullptr,
3536 /* RES_CHRATR_HIDDEN */             OutCSS1_SvxHidden,
3537 /* RES_CHRATR_OVERLINE */           OutCSS1_SvxOverline,
3538 /* RES_CHRATR_RSID */               nullptr,
3539 /* RES_CHRATR_BOX */                OutCSS1_SvxBox,
3540 /* RES_CHRATR_SHADOW */             nullptr,
3541 /* RES_CHRATR_HIGHLIGHT */          nullptr,
3542 /* RES_CHRATR_GRABBAG */            nullptr,
3543 /* RES_CHRATR_BIDIRTL */            nullptr,
3544 /* RES_CHRATR_IDCTHINT */           nullptr,
3545 
3546 /* RES_TXTATR_REFMARK */            nullptr,
3547 /* RES_TXTATR_TOXMARK */            nullptr,
3548 /* RES_TXTATR_META */               nullptr,
3549 /* RES_TXTATR_METAFIELD */          nullptr,
3550 /* RES_TXTATR_AUTOFMT */            nullptr,
3551 /* RES_TXTATR_INETFMT */            nullptr,
3552 /* RES_TXTATR_CHARFMT */            nullptr,
3553 /* RES_TXTATR_CJK_RUBY */           nullptr,
3554 /* RES_TXTATR_UNKNOWN_CONTAINER */  nullptr,
3555 /* RES_TXTATR_INPUTFIELD */         nullptr,
3556 
3557 /* RES_TXTATR_FIELD */              nullptr,
3558 /* RES_TXTATR_FLYCNT */             nullptr,
3559 /* RES_TXTATR_FTN */                nullptr,
3560 /* RES_TXTATR_ANNOTATION */         nullptr,
3561 /* RES_TXTATR_DUMMY3 */             nullptr,
3562 /* RES_TXTATR_DUMMY1 */             nullptr, // Dummy:
3563 /* RES_TXTATR_DUMMY2 */             nullptr, // Dummy:
3564 
3565 /* RES_PARATR_LINESPACING   */      OutCSS1_SvxLineSpacing,
3566 /* RES_PARATR_ADJUST    */          OutCSS1_SvxAdjust,
3567 /* RES_PARATR_SPLIT */              OutCSS1_SvxFormatSplit,
3568 /* RES_PARATR_ORPHANS   */          OutCSS1_SvxOrphans,
3569 /* RES_PARATR_WIDOWS    */          OutCSS1_SvxWidows,
3570 /* RES_PARATR_TABSTOP   */          nullptr,
3571 /* RES_PARATR_HYPHENZONE*/          nullptr,
3572 /* RES_PARATR_DROP */               OutCSS1_SwFormatDrop,
3573 /* RES_PARATR_REGISTER */           nullptr, // new: register-true
3574 /* RES_PARATR_NUMRULE */            nullptr,
3575 /* RES_PARATR_SCRIPTSPACE */        nullptr,
3576 /* RES_PARATR_HANGINGPUNCTUATION */ nullptr,
3577 /* RES_PARATR_FORBIDDEN_RULES */    nullptr, // new
3578 /* RES_PARATR_VERTALIGN */          nullptr, // new
3579 /* RES_PARATR_SNAPTOGRID*/          nullptr, // new
3580 /* RES_PARATR_CONNECT_TO_BORDER */  nullptr, // new
3581 /* RES_PARATR_OUTLINELEVEL */       nullptr, // new since cws outlinelevel
3582 /* RES_PARATR_RSID */               nullptr, // new
3583 /* RES_PARATR_GRABBAG */            nullptr,
3584 
3585 /* RES_PARATR_LIST_ID */            nullptr, // new
3586 /* RES_PARATR_LIST_LEVEL */         nullptr, // new
3587 /* RES_PARATR_LIST_ISRESTART */     nullptr, // new
3588 /* RES_PARATR_LIST_RESTARTVALUE */  nullptr, // new
3589 /* RES_PARATR_LIST_ISCOUNTED */     nullptr, // new
3590 
3591 /* RES_FILL_ORDER   */              nullptr,
3592 /* RES_FRM_SIZE */                  nullptr,
3593 /* RES_PAPER_BIN    */              nullptr,
3594 /* RES_LR_SPACE */                  OutCSS1_SvxLRSpace,
3595 /* RES_UL_SPACE */                  OutCSS1_SvxULSpace,
3596 /* RES_PAGEDESC */                  nullptr,
3597 /* RES_BREAK */                     nullptr,
3598 /* RES_CNTNT */                     nullptr,
3599 /* RES_HEADER */                    nullptr,
3600 /* RES_FOOTER */                    nullptr,
3601 /* RES_PRINT */                     nullptr,
3602 /* RES_OPAQUE */                    nullptr,
3603 /* RES_PROTECT */                   nullptr,
3604 /* RES_SURROUND */                  nullptr,
3605 /* RES_VERT_ORIENT */               nullptr,
3606 /* RES_HORI_ORIENT */               nullptr,
3607 /* RES_ANCHOR */                    nullptr,
3608 /* RES_BACKGROUND */                OutCSS1_SvxBrush,
3609 /* RES_BOX  */                      OutCSS1_SvxBox,
3610 /* RES_SHADOW */                    nullptr,
3611 /* RES_FRMMACRO */                  nullptr,
3612 /* RES_COL */                       nullptr,
3613 /* RES_KEEP */                      nullptr,
3614 /* RES_URL */                       nullptr,
3615 /* RES_EDIT_IN_READONLY */          nullptr,
3616 /* RES_LAYOUT_SPLIT */              nullptr,
3617 /* RES_CHAIN */                     nullptr,
3618 /* RES_TEXTGRID */                  nullptr,
3619 /* RES_LINENUMBER */                nullptr,
3620 /* RES_FTN_AT_TXTEND */             nullptr,
3621 /* RES_END_AT_TXTEND */             nullptr,
3622 /* RES_COLUMNBALANCE */             nullptr,
3623 /* RES_FRAMEDIR */                  OutCSS1_SvxFrameDirection,
3624 /* RES_HEADER_FOOTER_EAT_SPACING */ nullptr,
3625 /* RES_ROW_SPLIT */                 nullptr,
3626 /* RES_FOLLOW_TEXT_FLOW */          nullptr,
3627 /* RES_COLLAPSING_BORDERS */        nullptr,
3628 /* RES_WRAP_INFLUENCE_ON_OBJPOS */  nullptr,
3629 /* RES_AUTO_STYLE */                nullptr,
3630 /* RES_FRMATR_STYLE_NAME */         nullptr,
3631 /* RES_FRMATR_CONDITIONAL_STYLE_NAME */ nullptr,
3632 /* RES_FRMATR_GRABBAG */            nullptr,
3633 /* RES_TEXT_VERT_ADJUST */          nullptr,
3634 
3635 /* RES_GRFATR_MIRRORGRF */          nullptr,
3636 /* RES_GRFATR_CROPGRF   */          nullptr,
3637 /* RES_GRFATR_ROTATION */           nullptr,
3638 /* RES_GRFATR_LUMINANCE */          nullptr,
3639 /* RES_GRFATR_CONTRAST */           nullptr,
3640 /* RES_GRFATR_CHANNELR */           nullptr,
3641 /* RES_GRFATR_CHANNELG */           nullptr,
3642 /* RES_GRFATR_CHANNELB */           nullptr,
3643 /* RES_GRFATR_GAMMA */              nullptr,
3644 /* RES_GRFATR_INVERT */             nullptr,
3645 /* RES_GRFATR_TRANSPARENCY */       nullptr,
3646 /* RES_GRFATR_DRWAMODE */           nullptr,
3647 /* RES_GRFATR_DUMMY1 */             nullptr,
3648 /* RES_GRFATR_DUMMY2 */             nullptr,
3649 /* RES_GRFATR_DUMMY3 */             nullptr,
3650 /* RES_GRFATR_DUMMY4 */             nullptr,
3651 /* RES_GRFATR_DUMMY5 */             nullptr,
3652 
3653 /* RES_BOXATR_FORMAT */             nullptr,
3654 /* RES_BOXATR_FORMULA */            nullptr,
3655 /* RES_BOXATR_VALUE */              nullptr
3656 };
3657 
3658 void SwHTMLWriter::OutCSS1_SfxItemSet( const SfxItemSet& rItemSet,
3659                                        bool bDeep )
3660 {
3661     // print ItemSet, including all attributes
3662     Out_SfxItemSet( aCSS1AttrFnTab, *this, rItemSet, bDeep );
3663 
3664     // some Attributes require special treatment
3665     const SfxPoolItem *pItem = nullptr;
3666 
3667     // Underline, Overline, CrossedOut and Blink form together a CSS1-Property
3668     // (doesn't work of course for Hints)
3669     if( !IsCSS1Source(CSS1_OUTMODE_HINT) )
3670     {
3671         const SvxUnderlineItem *pUnderlineItem = nullptr;
3672         if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_UNDERLINE, bDeep, &pItem ))
3673             pUnderlineItem = static_cast<const SvxUnderlineItem *>(pItem);
3674 
3675         const SvxOverlineItem *pOverlineItem = nullptr;
3676         if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_OVERLINE, bDeep, &pItem ))
3677             pOverlineItem = static_cast<const SvxOverlineItem *>(pItem);
3678 
3679         const SvxCrossedOutItem *pCrossedOutItem = nullptr;
3680         if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_CROSSEDOUT, bDeep, &pItem ))
3681             pCrossedOutItem = static_cast<const SvxCrossedOutItem *>(pItem);
3682 
3683         const SvxBlinkItem *pBlinkItem = nullptr;
3684         if( SfxItemState::SET==rItemSet.GetItemState( RES_CHRATR_BLINK, bDeep, &pItem ))
3685             pBlinkItem = static_cast<const SvxBlinkItem *>(pItem);
3686 
3687         if( pUnderlineItem || pOverlineItem || pCrossedOutItem || pBlinkItem )
3688             OutCSS1_SvxTextLn_SvxCrOut_SvxBlink( *this, pUnderlineItem,
3689                                                  pOverlineItem,
3690                                                  pCrossedOutItem,
3691                                                  pBlinkItem );
3692 
3693         OutCSS1_SvxFormatBreak_SwFormatPDesc_SvxFormatKeep( *this, rItemSet, bDeep );
3694     }
3695 
3696     if( !m_bFirstCSS1Property )
3697     {
3698         // if a Property was exported as part of a Style-Option,
3699         // the Option still needs to be finished
3700         OStringBuffer sOut;
3701         switch( m_nCSS1OutMode & CSS1_OUTMODE_ANY_OFF )
3702         {
3703         case CSS1_OUTMODE_SPAN_TAG_OFF:
3704             sOut.append(sCSS1_span_tag_end);
3705             break;
3706 
3707         case CSS1_OUTMODE_STYLE_OPT_OFF:
3708             sOut.append(cCSS1_style_opt_end);
3709             break;
3710 
3711         case CSS1_OUTMODE_RULE_OFF:
3712             sOut.append(sCSS1_rule_end);
3713             break;
3714         }
3715         if (!sOut.isEmpty())
3716             Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
3717     }
3718 }
3719 
3720 Writer& OutCSS1_HintSpanTag( Writer& rWrt, const SfxPoolItem& rHt )
3721 {
3722     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3723 
3724     SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_SPAN_TAG |
3725                                    CSS1_OUTMODE_ENCODE|CSS1_OUTMODE_HINT, nullptr );
3726 
3727     Out( aCSS1AttrFnTab, rHt, rWrt );
3728 
3729     if( !rHTMLWrt.m_bFirstCSS1Property  && rHTMLWrt.m_bTagOn )
3730         rWrt.Strm().WriteCharPtr( sCSS1_span_tag_end );
3731 
3732     return rWrt;
3733 }
3734 
3735 Writer& OutCSS1_HintStyleOpt( Writer& rWrt, const SfxPoolItem& rHt )
3736 {
3737     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
3738 
3739     SwCSS1OutMode aMode( rHTMLWrt, CSS1_OUTMODE_STYLE_OPT_ON |
3740                                    CSS1_OUTMODE_ENCODE|
3741                                    CSS1_OUTMODE_HINT, nullptr );
3742 
3743     Out( aCSS1AttrFnTab, rHt, rWrt );
3744 
3745     if( !rHTMLWrt.m_bFirstCSS1Property )
3746         rWrt.Strm().WriteChar( '\"' );
3747 
3748     return rWrt;
3749 }
3750 
3751 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3752