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