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 <com/sun/star/i18n/XBreakIterator.hpp>
21 #include <comphelper/string.hxx>
22 #include <svtools/htmlkywd.hxx>
23 #include <svtools/htmlout.hxx>
24 #include <osl/diagnose.h>
25 #include <fmtfld.hxx>
26 #include <doc.hxx>
27 #include <breakit.hxx>
28 #include <ndtxt.hxx>
29 #include <txtfld.hxx>
30 #include <fldbas.hxx>
31 #include <docufld.hxx>
32 #include <flddat.hxx>
33 #include <viewopt.hxx>
34 #include "htmlfld.hxx"
35 #include "wrthtml.hxx"
36 #include <rtl/strbuf.hxx>
37 #include "css1atr.hxx"
38 #include "css1kywd.hxx"
39 
40 using namespace nsSwDocInfoSubType;
41 
GetNumFormat(sal_uInt16 nFormat)42 const char *SwHTMLWriter::GetNumFormat( sal_uInt16 nFormat )
43 {
44     const char *pFormatStr = nullptr;
45 
46     switch( static_cast<SvxNumType>(nFormat) )
47     {
48     case SVX_NUM_CHARS_UPPER_LETTER:    pFormatStr = OOO_STRING_SW_HTML_FF_uletter;    break;
49     case SVX_NUM_CHARS_LOWER_LETTER:    pFormatStr = OOO_STRING_SW_HTML_FF_lletter;    break;
50     case SVX_NUM_ROMAN_UPPER:           pFormatStr = OOO_STRING_SW_HTML_FF_uroman;         break;
51     case SVX_NUM_ROMAN_LOWER:           pFormatStr = OOO_STRING_SW_HTML_FF_lroman;         break;
52     case SVX_NUM_ARABIC:                pFormatStr = OOO_STRING_SW_HTML_FF_arabic;     break;
53     case SVX_NUM_NUMBER_NONE:           pFormatStr = OOO_STRING_SW_HTML_FF_none;       break;
54     case SVX_NUM_CHAR_SPECIAL:          pFormatStr = OOO_STRING_SW_HTML_FF_char;       break;
55     case SVX_NUM_PAGEDESC:              pFormatStr = OOO_STRING_SW_HTML_FF_page;       break;
56     case SVX_NUM_CHARS_UPPER_LETTER_N:  pFormatStr = OOO_STRING_SW_HTML_FF_ulettern;   break;
57     case SVX_NUM_CHARS_LOWER_LETTER_N:  pFormatStr = OOO_STRING_SW_HTML_FF_llettern;   break;
58     default:
59         ;
60     }
61 
62     return pFormatStr;
63 }
64 
OutHTML_SwField(Writer & rWrt,const SwField * pField,const SwTextNode & rTextNd,sal_Int32 nFieldPos)65 static Writer& OutHTML_SwField( Writer& rWrt, const SwField* pField,
66                                  const SwTextNode& rTextNd, sal_Int32 nFieldPos )
67 {
68     SwHTMLWriter & rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
69 
70     const SwFieldType* pFieldTyp = pField->GetTyp();
71     SwFieldIds nField = pFieldTyp->Which();
72     sal_uLong nFormat = pField->GetFormat();
73 
74     const char *pTypeStr=nullptr, // TYPE
75                       *pSubStr=nullptr,   // SUBTYPE
76                    *pFormatStr=nullptr;  // FORMAT (SW)
77     OUString aValue;              // VALUE (SW)
78     bool bNumFormat=false;         // SDNUM (Number-Formatter-Format)
79     bool bNumValue=false;       // SDVAL (Number-Formatter-Value)
80     double dNumValue = 0.0;     // SDVAL (Number-Formatter-Value)
81     bool bFixed=false;          // SDFIXED
82     OUString aName;               // NAME (CUSTOM)
83 
84     switch( nField )
85     {
86         case SwFieldIds::ExtUser:
87             pTypeStr = OOO_STRING_SW_HTML_FT_sender;
88             switch( static_cast<SwExtUserSubType>(pField->GetSubType()) )
89             {
90                 case EU_COMPANY:    pSubStr = OOO_STRING_SW_HTML_FS_company;        break;
91                 case EU_FIRSTNAME:  pSubStr = OOO_STRING_SW_HTML_FS_firstname;  break;
92                 case EU_NAME:       pSubStr = OOO_STRING_SW_HTML_FS_name;       break;
93                 case EU_SHORTCUT:   pSubStr = OOO_STRING_SW_HTML_FS_shortcut;   break;
94                 case EU_STREET:     pSubStr = OOO_STRING_SW_HTML_FS_street;     break;
95                 case EU_COUNTRY:    pSubStr = OOO_STRING_SW_HTML_FS_country;     break;
96                 case EU_ZIP:        pSubStr = OOO_STRING_SW_HTML_FS_zip;         break;
97                 case EU_CITY:       pSubStr = OOO_STRING_SW_HTML_FS_city;        break;
98                 case EU_TITLE:      pSubStr = OOO_STRING_SW_HTML_FS_title;       break;
99                 case EU_POSITION:   pSubStr = OOO_STRING_SW_HTML_FS_position;    break;
100                 case EU_PHONE_PRIVATE:  pSubStr = OOO_STRING_SW_HTML_FS_pphone;      break;
101                 case EU_PHONE_COMPANY:  pSubStr = OOO_STRING_SW_HTML_FS_cphone;      break;
102                 case EU_FAX:        pSubStr = OOO_STRING_SW_HTML_FS_fax;         break;
103                 case EU_EMAIL:      pSubStr = OOO_STRING_SW_HTML_FS_email;       break;
104                 case EU_STATE:      pSubStr = OOO_STRING_SW_HTML_FS_state;       break;
105                 default:
106                     ;
107             }
108             OSL_ENSURE( pSubStr, "unknown sub type for SwExtUserField" );
109             bFixed = static_cast<const SwExtUserField*>(pField)->IsFixed();
110             break;
111 
112         case SwFieldIds::Author:
113             pTypeStr = OOO_STRING_SW_HTML_FT_author;
114             switch( static_cast<SwAuthorFormat>(nFormat) & 0xff)
115             {
116                 case AF_NAME:     pFormatStr = OOO_STRING_SW_HTML_FF_name;     break;
117                 case AF_SHORTCUT:  pFormatStr = OOO_STRING_SW_HTML_FF_shortcut;    break;
118             }
119             OSL_ENSURE( pFormatStr, "unknown format for SwAuthorField" );
120             bFixed = static_cast<const SwAuthorField*>(pField)->IsFixed();
121             break;
122 
123         case SwFieldIds::DateTime:
124             pTypeStr = OOO_STRING_SW_HTML_FT_datetime;
125             bNumFormat = true;
126             if( static_cast<const SwDateTimeField*>(pField)->IsFixed() )
127             {
128                 bNumValue = true;
129                 dNumValue = static_cast<const SwDateTimeField*>(pField)->GetValue();
130             }
131             break;
132 
133         case SwFieldIds::PageNumber:
134             {
135                 pTypeStr = OOO_STRING_SW_HTML_FT_page;
136                 SwPageNumSubType eSubType = static_cast<SwPageNumSubType>(pField->GetSubType());
137                 switch( eSubType )
138                 {
139                     case PG_RANDOM:     pSubStr = OOO_STRING_SW_HTML_FS_random;     break;
140                     case PG_NEXT:       pSubStr = OOO_STRING_SW_HTML_FS_next;       break;
141                     case PG_PREV:       pSubStr = OOO_STRING_SW_HTML_FS_prev;       break;
142                 }
143                 OSL_ENSURE( pSubStr, "unknown sub type for SwPageNumberField" );
144                 pFormatStr = SwHTMLWriter::GetNumFormat( static_cast< sal_uInt16 >(nFormat) );
145 
146                 if( static_cast<SvxNumType>(nFormat)==SVX_NUM_CHAR_SPECIAL )
147                 {
148                     aValue = static_cast<const SwPageNumberField *>(pField)->GetUserString();
149                 }
150                 else
151                 {
152                     const OUString& rValue = pField->GetPar2();
153                     short nValue = static_cast<short>(rValue.toInt32());
154                     if( (eSubType == PG_NEXT && nValue!=1) ||
155                         (eSubType == PG_PREV && nValue!=-1) ||
156                         (eSubType == PG_RANDOM && nValue!=0) )
157                     {
158                         aValue = rValue;
159                     }
160                 }
161             }
162             break;
163         case SwFieldIds::DocInfo:
164             {
165                 sal_uInt16 nSubType = pField->GetSubType();
166                 pTypeStr = OOO_STRING_SW_HTML_FT_docinfo;
167                 sal_uInt16 nExtSubType = nSubType & 0x0f00;
168                 nSubType &= 0x00ff;
169 
170                 switch( nSubType )
171                 {
172                     case DI_TITLE:      pSubStr = OOO_STRING_SW_HTML_FS_title;  break;
173                     case DI_SUBJECT:    pSubStr = OOO_STRING_SW_HTML_FS_theme;  break;
174                     case DI_KEYS:       pSubStr = OOO_STRING_SW_HTML_FS_keys;   break;
175                     case DI_COMMENT:    pSubStr = OOO_STRING_SW_HTML_FS_comment; break;
176                     case DI_CREATE:     pSubStr = OOO_STRING_SW_HTML_FS_create;     break;
177                     case DI_CHANGE:     pSubStr = OOO_STRING_SW_HTML_FS_change;     break;
178                     case DI_CUSTOM:     pSubStr = OOO_STRING_SW_HTML_FS_custom;     break;
179                     default:            pTypeStr = nullptr;               break;
180                 }
181 
182                 if( DI_CUSTOM == nSubType ) {
183                     aName = static_cast<const SwDocInfoField*>(pField)->GetName();
184                 }
185 
186                 if( DI_CREATE == nSubType || DI_CHANGE == nSubType )
187                 {
188                     switch( nExtSubType )
189                     {
190                         case DI_SUB_AUTHOR:
191                             pFormatStr = OOO_STRING_SW_HTML_FF_author;
192                             break;
193                         case DI_SUB_TIME:
194                             pFormatStr = OOO_STRING_SW_HTML_FF_time;
195                             bNumFormat = true;
196                             break;
197                         case DI_SUB_DATE:
198                             pFormatStr = OOO_STRING_SW_HTML_FF_date;
199                             bNumFormat = true;
200                             break;
201                     }
202                 }
203                 bFixed = static_cast<const SwDocInfoField*>(pField)->IsFixed();
204                 if( bNumFormat )
205                 {
206                     if( bFixed )
207                     {
208                         // For a fixed field output the num value too.
209                         // Fixed fields without number format shouldn't
210                         // exist. See below for OSL_ENSURE().
211                         dNumValue = static_cast<const SwDocInfoField*>(pField)->GetValue();
212                         bNumValue = true;
213                     }
214                     else if( !nFormat  )
215                     {
216                         // Non-fixed fields may not have a number format, when
217                         // they come from a 4.0-document.
218                         bNumFormat = false;
219                     }
220                 }
221             }
222             break;
223 
224         case SwFieldIds::DocStat:
225             {
226                 pTypeStr = OOO_STRING_SW_HTML_FT_docstat;
227                 sal_uInt16 nSubType = pField->GetSubType();
228                 switch( nSubType )
229                 {
230                     case DS_PAGE:       pSubStr = OOO_STRING_SW_HTML_FS_page;   break;
231                     case DS_PARA:       pSubStr = OOO_STRING_SW_HTML_FS_para;   break;
232                     case DS_WORD:       pSubStr = OOO_STRING_SW_HTML_FS_word;   break;
233                     case DS_CHAR:       pSubStr = OOO_STRING_SW_HTML_FS_char;   break;
234                     case DS_TBL:        pSubStr = OOO_STRING_SW_HTML_FS_tbl;    break;
235                     case DS_GRF:        pSubStr = OOO_STRING_SW_HTML_FS_grf;    break;
236                     case DS_OLE:        pSubStr = OOO_STRING_SW_HTML_FS_ole;    break;
237                     default:            pTypeStr = nullptr;               break;
238                 }
239                 pFormatStr = SwHTMLWriter::GetNumFormat( static_cast< sal_uInt16 >(nFormat) );
240             }
241             break;
242 
243         case SwFieldIds::Filename:
244             pTypeStr = OOO_STRING_SW_HTML_FT_filename;
245             switch( static_cast<SwFileNameFormat>(nFormat & ~FF_FIXED) )
246             {
247                 case FF_NAME:       pFormatStr = OOO_STRING_SW_HTML_FF_name;       break;
248                 case FF_PATHNAME:   pFormatStr = OOO_STRING_SW_HTML_FF_pathname;   break;
249                 case FF_PATH:       pFormatStr = OOO_STRING_SW_HTML_FF_path;       break;
250                 case FF_NAME_NOEXT: pFormatStr = OOO_STRING_SW_HTML_FF_name_noext; break;
251                 default:
252                     ;
253             }
254             bFixed = static_cast<const SwFileNameField*>(pField)->IsFixed();
255             OSL_ENSURE( pFormatStr, "unknown format for SwFileNameField" );
256             break;
257         default: break;
258     }
259 
260     // ReqIF-XHTML doesn't allow <sdfield>.
261     if (rHTMLWrt.mbReqIF && pTypeStr)
262     {
263         pTypeStr = nullptr;
264     }
265 
266     // Output the <sdfield> tag.
267     if( pTypeStr )
268     {
269         OStringBuffer sOut;
270         sOut.append('<');
271         sOut.append(rHTMLWrt.GetNamespace());
272         sOut.append(OOO_STRING_SVTOOLS_HTML_sdfield).append(' ').
273             append(OOO_STRING_SVTOOLS_HTML_O_type).append('=').
274             append(pTypeStr);
275         if( pSubStr )
276         {
277             sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_subtype).
278                 append('=').append(pSubStr);
279         }
280         if( pFormatStr )
281         {
282             sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_format).
283                 append('=').append(pFormatStr);
284         }
285         if( !aName.isEmpty() )
286         {
287             sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_name "=\"");
288             rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
289             HTMLOutFuncs::Out_String( rWrt.Strm(), aName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
290             sOut.append('\"');
291         }
292         if( !aValue.isEmpty() )
293         {
294             sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_value "=\"");
295             rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
296             HTMLOutFuncs::Out_String( rWrt.Strm(), aValue, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
297             sOut.append('\"');
298         }
299         if( bNumFormat )
300         {
301             OSL_ENSURE( nFormat, "number format is 0" );
302             sOut.append(HTMLOutFuncs::CreateTableDataOptionsValNum(
303                 bNumValue, dNumValue, nFormat,
304                 *rHTMLWrt.m_pDoc->GetNumberFormatter(), rHTMLWrt.m_eDestEnc,
305                 &rHTMLWrt.m_aNonConvertableCharacters));
306         }
307         if( bFixed )
308         {
309             sOut.append(' ').append(OOO_STRING_SVTOOLS_HTML_O_sdfixed);
310         }
311         sOut.append('>');
312         rWrt.Strm().WriteOString( sOut.makeStringAndClear() );
313     }
314 
315     // output content of the field
316     OUString const sExpand( pField->ExpandField(true, nullptr) );
317     bool bNeedsCJKProcessing = false;
318     if( !sExpand.isEmpty() )
319     {
320         sal_uInt16 nScriptType = g_pBreakIt->GetBreakIter()->getScriptType( sExpand, 0 );
321         sal_Int32 nPos = g_pBreakIt->GetBreakIter()->endOfScript( sExpand, 0,
322                                                           nScriptType );
323 
324         sal_uInt16 nScript =
325             SwHTMLWriter::GetCSS1ScriptForScriptType( nScriptType );
326         if( (nPos < sExpand.getLength() && nPos >= 0) || nScript != rHTMLWrt.m_nCSS1Script )
327         {
328             bNeedsCJKProcessing = true;
329         }
330     }
331 
332     if( bNeedsCJKProcessing )
333     {
334         //sequence of (start, end) property ranges we want to
335         //query
336         SfxItemSet aScriptItemSet( rWrt.m_pDoc->GetAttrPool(),
337                                    svl::Items<RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
338                                    RES_CHRATR_POSTURE, RES_CHRATR_POSTURE,
339                                    RES_CHRATR_WEIGHT, RES_CHRATR_WEIGHT,
340                                    RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_WEIGHT>{} );
341         rTextNd.GetParaAttr(aScriptItemSet, nFieldPos, nFieldPos+1);
342 
343         sal_uInt16 aWesternWhichIds[4] =
344             { RES_CHRATR_FONT, RES_CHRATR_FONTSIZE,
345               RES_CHRATR_POSTURE, RES_CHRATR_WEIGHT };
346         sal_uInt16 aCJKWhichIds[4] =
347             { RES_CHRATR_CJK_FONT, RES_CHRATR_CJK_FONTSIZE,
348               RES_CHRATR_CJK_POSTURE, RES_CHRATR_CJK_WEIGHT };
349         sal_uInt16 aCTLWhichIds[4] =
350             { RES_CHRATR_CTL_FONT, RES_CHRATR_CTL_FONTSIZE,
351               RES_CHRATR_CTL_POSTURE, RES_CHRATR_CTL_WEIGHT };
352 
353         sal_uInt16 *pRefWhichIds = nullptr;
354         switch( rHTMLWrt.m_nCSS1Script )
355         {
356         case CSS1_OUTMODE_WESTERN:
357             pRefWhichIds = aWesternWhichIds;
358             break;
359         case CSS1_OUTMODE_CJK:
360             pRefWhichIds = aCJKWhichIds;
361             break;
362         case CSS1_OUTMODE_CTL:
363             pRefWhichIds = aCTLWhichIds;
364             break;
365         }
366 
367         sal_Int32 nPos = 0;
368         do
369         {
370             sal_uInt16 nScriptType = g_pBreakIt->GetBreakIter()->getScriptType( sExpand, nPos );
371             sal_uInt16 nScript =
372                 SwHTMLWriter::GetCSS1ScriptForScriptType( nScriptType );
373             sal_Int32 nEndPos = g_pBreakIt->GetBreakIter()->endOfScript(
374                                     sExpand, nPos, nScriptType );
375             sal_Int32 nChunkLen = nEndPos - nPos;
376             if( nScript != CSS1_OUTMODE_ANY_SCRIPT &&
377                 /* #108791# */ nScript != rHTMLWrt.m_nCSS1Script )
378             {
379                 sal_uInt16 *pWhichIds = nullptr;
380                 switch( nScript )
381                 {
382                 case CSS1_OUTMODE_WESTERN:  pWhichIds = aWesternWhichIds; break;
383                 case CSS1_OUTMODE_CJK:      pWhichIds = aCJKWhichIds; break;
384                 case CSS1_OUTMODE_CTL:      pWhichIds = aCTLWhichIds; break;
385                 }
386 
387                 rHTMLWrt.m_bTagOn = true;
388 
389                 const SfxPoolItem *aItems[5];
390                 int nItems = 0;
391 
392                 assert(pWhichIds && pRefWhichIds);
393                 if (pWhichIds && pRefWhichIds)
394                 {
395                     for( int i=0; i<4; i++ )
396                     {
397                         const SfxPoolItem *pRefItem =
398                             aScriptItemSet.GetItem( pRefWhichIds[i] );
399                         const SfxPoolItem *pItem =
400                             aScriptItemSet.GetItem( pWhichIds[i] );
401                         if( pRefItem && pItem &&
402                             !(0==i ? swhtml_css1atr_equalFontItems( *pRefItem, *pItem )
403                                    : *pRefItem == *pItem) )
404                         {
405                             Out( aHTMLAttrFnTab, *pItem, rHTMLWrt );
406                             aItems[nItems++] = pItem;
407                         }
408                     }
409                 }
410 
411                 HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand.copy( nPos, nChunkLen ),
412                     rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
413 
414                 rHTMLWrt.m_bTagOn = false;
415                 while( nItems )
416                     Out( aHTMLAttrFnTab, *aItems[--nItems], rHTMLWrt );
417 
418             }
419             else
420             {
421                 HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand.copy( nPos, nChunkLen ),
422                     rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
423             }
424             nPos = nEndPos;
425         }
426         while( nPos < sExpand.getLength() );
427     }
428     else
429     {
430         HTMLOutFuncs::Out_String( rWrt.Strm(), sExpand,
431               rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
432     }
433 
434     // Output the closing tag.
435     if( pTypeStr )
436         HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_sdfield), false );
437 
438     return rWrt;
439 }
440 
OutHTML_SwFormatField(Writer & rWrt,const SfxPoolItem & rHt)441 Writer& OutHTML_SwFormatField( Writer& rWrt, const SfxPoolItem& rHt )
442 {
443     SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
444     const SwFormatField & rField = static_cast<const SwFormatField&>(rHt);
445     const SwField* pField = rField.GetField();
446     const SwFieldType* pFieldTyp = pField->GetTyp();
447 
448     if( SwFieldIds::SetExp == pFieldTyp->Which() &&
449         (nsSwGetSetExpType::GSE_STRING & pField->GetSubType()) )
450     {
451         const bool bOn = pFieldTyp->GetName() == "HTML_ON";
452         if (!bOn && pFieldTyp->GetName() != "HTML_OFF")
453             return rWrt;
454 
455         OUString rText(comphelper::string::strip(pField->GetPar2(), ' '));
456         rWrt.Strm().WriteChar( '<' );
457         if( !bOn )
458             rWrt.Strm().WriteChar( '/' );
459         // TODO: HTML-Tags are written without entities, that for, characters
460         // not contained in the destination encoding are lost!
461         OString sTmp(OUStringToOString(rText,
462             static_cast<SwHTMLWriter&>(rWrt).m_eDestEnc));
463         rWrt.Strm().WriteOString( sTmp ).WriteChar( '>' );
464     }
465     else if( SwFieldIds::Postit == pFieldTyp->Which() )
466     {
467         // Comments will be written in ANSI character set, but with system
468         // line breaks.
469         const OUString& rComment = pField->GetPar2();
470         bool bWritten = false;
471 
472         if( (rComment.getLength() >= 6 && rComment.startsWith("<") && rComment.endsWith(">") &&
473              rComment.copy( 1, 4 ).equalsIgnoreAsciiCase( OOO_STRING_SVTOOLS_HTML_meta) ) ||
474             (rComment.getLength() >= 7 &&
475              rComment.startsWith( "<!--" ) &&
476              rComment.endsWith( "-->" )) )
477         {
478             // directly output META tags
479             OUString sComment(convertLineEnd(rComment, GetSystemLineEnd()));
480             // TODO: HTML-Tags are written without entities, that for,
481             // characters not contained in the destination encoding are lost!
482             OString sTmp(OUStringToOString(sComment,
483                 static_cast<SwHTMLWriter&>(rWrt).m_eDestEnc));
484             rWrt.Strm().WriteOString( sTmp );
485             bWritten = true;
486         }
487         else if( rComment.getLength() >= 7 &&
488                  rComment.endsWith(">") &&
489                  rComment.startsWithIgnoreAsciiCase( "HTML:" ) )
490         {
491             OUString sComment(comphelper::string::stripStart(rComment.subView(5), ' '));
492             if( '<' == sComment[0] )
493             {
494                 sComment = convertLineEnd(sComment, GetSystemLineEnd());
495                 // TODO: HTML-Tags are written without entities, that for,
496                 // characters not contained in the destination encoding are
497                 // lost!
498                 OString sTmp(OUStringToOString(sComment,
499                     static_cast<SwHTMLWriter&>(rWrt).m_eDestEnc));
500                 rWrt.Strm().WriteOString( sTmp );
501                 bWritten = true;
502             }
503 
504         }
505 
506         if( !bWritten )
507         {
508             OUString sComment(convertLineEnd(rComment, GetSystemLineEnd()));
509             // TODO: ???
510             OString sOut =
511                 "<" OOO_STRING_SVTOOLS_HTML_comment
512                 " " +
513                 OUStringToOString(sComment, static_cast<SwHTMLWriter&>(rWrt).m_eDestEnc) +
514                 " -->";
515             rWrt.Strm().WriteOString( sOut );
516         }
517     }
518     else if( SwFieldIds::Script == pFieldTyp->Which() )
519     {
520         if( rHTMLWrt.m_bLFPossible )
521             rHTMLWrt.OutNewLine( true );
522 
523         bool bURL = static_cast<const SwScriptField *>(pField)->IsCodeURL();
524         const OUString& rType = pField->GetPar1();
525         OUString aContents, aURL;
526         if(bURL)
527             aURL = pField->GetPar2();
528         else
529             aContents = pField->GetPar2();
530 
531         // otherwise is the script content itself. Since only JavaScript
532         // is in fields, it must be JavaScript ...:)
533         HTMLOutFuncs::OutScript( rWrt.Strm(), rWrt.GetBaseURL(), aContents, rType, JAVASCRIPT,
534                                  aURL, nullptr, nullptr, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
535 
536         if( rHTMLWrt.m_bLFPossible )
537             rHTMLWrt.OutNewLine( true );
538     }
539     else
540     {
541         const SwTextField *pTextField = rField.GetTextField();
542         OSL_ENSURE( pTextField, "Where is the txt fld?" );
543         if( pTextField )
544         {
545             // ReqIF-XHTML doesn't allow specifying a background color.
546             bool bFieldShadings = SwViewOption::IsFieldShadings() && !rHTMLWrt.mbReqIF;
547             if (bFieldShadings)
548             {
549                 // If there is a text portion background started already, that should have priority.
550                 auto it = rHTMLWrt.maStartedAttributes.find(RES_CHRATR_BACKGROUND);
551                 if (it != rHTMLWrt.maStartedAttributes.end())
552                     bFieldShadings = it->second <= 0;
553             }
554 
555             if (bFieldShadings)
556             {
557                 OStringBuffer sOut;
558                 sOut.append("<" + rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span);
559                 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_style "=\"");
560                 sOut.append(sCSS1_P_background);
561                 sOut.append(": ");
562 
563                 Color& rColor = SwViewOption::GetFieldShadingsColor();
564                 sOut.append(GetCSS1_Color(rColor));
565                 sOut.append("\">");
566                 rWrt.Strm().WriteOString(sOut.makeStringAndClear());
567             }
568 
569             OutHTML_SwField( rWrt, pField, pTextField->GetTextNode(),
570                              pTextField->GetStart()  );
571 
572             if (bFieldShadings)
573                 HTMLOutFuncs::Out_AsciiTag(
574                     rWrt.Strm(), OString(rHTMLWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span), false);
575         }
576     }
577     return rWrt;
578 }
579 
580 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
581