1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <com/sun/star/i18n/XBreakIterator.hpp>
21 #include <comphelper/string.hxx>
22 #include <comphelper/xmlencode.hxx>
23 #include <svtools/htmlkywd.hxx>
24 #include <svtools/htmlout.hxx>
25 #include <osl/diagnose.h>
26 #include <o3tl/string_view.hxx>
32 #include <breakit.hxx>
36 #include <docufld.hxx>
38 #include <viewopt.hxx>
39 #include "htmlfld.hxx"
40 #include "wrthtml.hxx"
41 #include <rtl/strbuf.hxx>
42 #include "css1atr.hxx"
43 #include "css1kywd.hxx"
45 using namespace nsSwDocInfoSubType
;
47 const char *SwHTMLWriter::GetNumFormat( sal_uInt16 nFormat
)
49 const char *pFormatStr
= nullptr;
51 switch( static_cast<SvxNumType
>(nFormat
) )
53 case SVX_NUM_CHARS_UPPER_LETTER
: pFormatStr
= OOO_STRING_SW_HTML_FF_uletter
; break;
54 case SVX_NUM_CHARS_LOWER_LETTER
: pFormatStr
= OOO_STRING_SW_HTML_FF_lletter
; break;
55 case SVX_NUM_ROMAN_UPPER
: pFormatStr
= OOO_STRING_SW_HTML_FF_uroman
; break;
56 case SVX_NUM_ROMAN_LOWER
: pFormatStr
= OOO_STRING_SW_HTML_FF_lroman
; break;
57 case SVX_NUM_ARABIC
: pFormatStr
= OOO_STRING_SW_HTML_FF_arabic
; break;
58 case SVX_NUM_NUMBER_NONE
: pFormatStr
= OOO_STRING_SW_HTML_FF_none
; break;
59 case SVX_NUM_CHAR_SPECIAL
: pFormatStr
= OOO_STRING_SW_HTML_FF_char
; break;
60 case SVX_NUM_PAGEDESC
: pFormatStr
= OOO_STRING_SW_HTML_FF_page
; break;
61 case SVX_NUM_CHARS_UPPER_LETTER_N
: pFormatStr
= OOO_STRING_SW_HTML_FF_ulettern
; break;
62 case SVX_NUM_CHARS_LOWER_LETTER_N
: pFormatStr
= OOO_STRING_SW_HTML_FF_llettern
; break;
70 static SwHTMLWriter
& OutHTML_SwField( SwHTMLWriter
& rWrt
, const SwField
* pField
,
71 const SwTextNode
& rTextNd
, sal_Int32 nFieldPos
)
73 const SwFieldType
* pFieldTyp
= pField
->GetTyp();
74 SwFieldIds nField
= pFieldTyp
->Which();
75 sal_uLong nFormat
= pField
->GetFormat();
77 const char *pTypeStr
=nullptr, // TYPE
78 *pSubStr
=nullptr, // SUBTYPE
79 *pFormatStr
=nullptr; // FORMAT (SW)
80 OUString aValue
; // VALUE (SW)
81 bool bNumFormat
=false; // SDNUM (Number-Formatter-Format)
82 bool bNumValue
=false; // SDVAL (Number-Formatter-Value)
83 double dNumValue
= 0.0; // SDVAL (Number-Formatter-Value)
84 bool bFixed
=false; // SDFIXED
85 OUString aName
; // NAME (CUSTOM)
89 case SwFieldIds::ExtUser
:
90 pTypeStr
= OOO_STRING_SW_HTML_FT_sender
;
91 switch( static_cast<SwExtUserSubType
>(pField
->GetSubType()) )
93 case EU_COMPANY
: pSubStr
= OOO_STRING_SW_HTML_FS_company
; break;
94 case EU_FIRSTNAME
: pSubStr
= OOO_STRING_SW_HTML_FS_firstname
; break;
95 case EU_NAME
: pSubStr
= OOO_STRING_SW_HTML_FS_name
; break;
96 case EU_SHORTCUT
: pSubStr
= OOO_STRING_SW_HTML_FS_shortcut
; break;
97 case EU_STREET
: pSubStr
= OOO_STRING_SW_HTML_FS_street
; break;
98 case EU_COUNTRY
: pSubStr
= OOO_STRING_SW_HTML_FS_country
; break;
99 case EU_ZIP
: pSubStr
= OOO_STRING_SW_HTML_FS_zip
; break;
100 case EU_CITY
: pSubStr
= OOO_STRING_SW_HTML_FS_city
; break;
101 case EU_TITLE
: pSubStr
= OOO_STRING_SW_HTML_FS_title
; break;
102 case EU_POSITION
: pSubStr
= OOO_STRING_SW_HTML_FS_position
; break;
103 case EU_PHONE_PRIVATE
: pSubStr
= OOO_STRING_SW_HTML_FS_pphone
; break;
104 case EU_PHONE_COMPANY
: pSubStr
= OOO_STRING_SW_HTML_FS_cphone
; break;
105 case EU_FAX
: pSubStr
= OOO_STRING_SW_HTML_FS_fax
; break;
106 case EU_EMAIL
: pSubStr
= OOO_STRING_SW_HTML_FS_email
; break;
107 case EU_STATE
: pSubStr
= OOO_STRING_SW_HTML_FS_state
; break;
111 OSL_ENSURE( pSubStr
, "unknown sub type for SwExtUserField" );
112 bFixed
= static_cast<const SwExtUserField
*>(pField
)->IsFixed();
115 case SwFieldIds::Author
:
116 pTypeStr
= OOO_STRING_SW_HTML_FT_author
;
117 switch( static_cast<SwAuthorFormat
>(nFormat
) & 0xff)
119 case AF_NAME
: pFormatStr
= OOO_STRING_SW_HTML_FF_name
; break;
120 case AF_SHORTCUT
: pFormatStr
= OOO_STRING_SW_HTML_FF_shortcut
; break;
122 OSL_ENSURE( pFormatStr
, "unknown format for SwAuthorField" );
123 bFixed
= static_cast<const SwAuthorField
*>(pField
)->IsFixed();
126 case SwFieldIds::DateTime
:
127 pTypeStr
= OOO_STRING_SW_HTML_FT_datetime
;
129 if( static_cast<const SwDateTimeField
*>(pField
)->IsFixed() )
132 dNumValue
= static_cast<const SwDateTimeField
*>(pField
)->GetValue();
136 case SwFieldIds::PageNumber
:
138 pTypeStr
= OOO_STRING_SW_HTML_FT_page
;
139 SwPageNumSubType eSubType
= static_cast<SwPageNumSubType
>(pField
->GetSubType());
142 case PG_RANDOM
: pSubStr
= OOO_STRING_SW_HTML_FS_random
; break;
143 case PG_NEXT
: pSubStr
= OOO_STRING_SW_HTML_FS_next
; break;
144 case PG_PREV
: pSubStr
= OOO_STRING_SW_HTML_FS_prev
; break;
146 OSL_ENSURE( pSubStr
, "unknown sub type for SwPageNumberField" );
147 pFormatStr
= SwHTMLWriter::GetNumFormat( static_cast< sal_uInt16
>(nFormat
) );
149 if( static_cast<SvxNumType
>(nFormat
)==SVX_NUM_CHAR_SPECIAL
)
151 aValue
= static_cast<const SwPageNumberField
*>(pField
)->GetUserString();
155 const OUString aPar2Value
= pField
->GetPar2();
156 short nValue
= static_cast<short>(aPar2Value
.toInt32());
157 if( (eSubType
== PG_NEXT
&& nValue
!=1) ||
158 (eSubType
== PG_PREV
&& nValue
!=-1) ||
159 (eSubType
== PG_RANDOM
&& nValue
!=0) )
166 case SwFieldIds::DocInfo
:
168 sal_uInt16 nSubType
= pField
->GetSubType();
169 pTypeStr
= OOO_STRING_SW_HTML_FT_docinfo
;
170 sal_uInt16 nExtSubType
= nSubType
& 0x0f00;
175 case DI_TITLE
: pSubStr
= OOO_STRING_SW_HTML_FS_title
; break;
176 case DI_SUBJECT
: pSubStr
= OOO_STRING_SW_HTML_FS_theme
; break;
177 case DI_KEYS
: pSubStr
= OOO_STRING_SW_HTML_FS_keys
; break;
178 case DI_COMMENT
: pSubStr
= OOO_STRING_SW_HTML_FS_comment
; break;
179 case DI_CREATE
: pSubStr
= OOO_STRING_SW_HTML_FS_create
; break;
180 case DI_CHANGE
: pSubStr
= OOO_STRING_SW_HTML_FS_change
; break;
181 case DI_CUSTOM
: pSubStr
= OOO_STRING_SW_HTML_FS_custom
; break;
182 default: pTypeStr
= nullptr; break;
185 if( DI_CUSTOM
== nSubType
) {
186 aName
= static_cast<const SwDocInfoField
*>(pField
)->GetName();
189 if( DI_CREATE
== nSubType
|| DI_CHANGE
== nSubType
)
191 switch( nExtSubType
)
194 pFormatStr
= OOO_STRING_SW_HTML_FF_author
;
197 pFormatStr
= OOO_STRING_SW_HTML_FF_time
;
201 pFormatStr
= OOO_STRING_SW_HTML_FF_date
;
206 bFixed
= static_cast<const SwDocInfoField
*>(pField
)->IsFixed();
211 // For a fixed field output the num value too.
212 // Fixed fields without number format shouldn't
213 // exist. See below for OSL_ENSURE().
214 dNumValue
= static_cast<const SwDocInfoField
*>(pField
)->GetValue();
219 // Non-fixed fields may not have a number format, when
220 // they come from a 4.0-document.
227 case SwFieldIds::DocStat
:
229 pTypeStr
= OOO_STRING_SW_HTML_FT_docstat
;
230 sal_uInt16 nSubType
= pField
->GetSubType();
233 case DS_PAGE
: pSubStr
= OOO_STRING_SW_HTML_FS_page
; break;
234 case DS_PARA
: pSubStr
= OOO_STRING_SW_HTML_FS_para
; break;
235 case DS_WORD
: pSubStr
= OOO_STRING_SW_HTML_FS_word
; break;
236 case DS_CHAR
: pSubStr
= OOO_STRING_SW_HTML_FS_char
; break;
237 case DS_TBL
: pSubStr
= OOO_STRING_SW_HTML_FS_tbl
; break;
238 case DS_GRF
: pSubStr
= OOO_STRING_SW_HTML_FS_grf
; break;
239 case DS_OLE
: pSubStr
= OOO_STRING_SW_HTML_FS_ole
; break;
240 default: pTypeStr
= nullptr; break;
242 pFormatStr
= SwHTMLWriter::GetNumFormat( static_cast< sal_uInt16
>(nFormat
) );
246 case SwFieldIds::Filename
:
247 pTypeStr
= OOO_STRING_SW_HTML_FT_filename
;
248 switch( static_cast<SwFileNameFormat
>(nFormat
& ~FF_FIXED
) )
250 case FF_NAME
: pFormatStr
= OOO_STRING_SW_HTML_FF_name
; break;
251 case FF_PATHNAME
: pFormatStr
= OOO_STRING_SW_HTML_FF_pathname
; break;
252 case FF_PATH
: pFormatStr
= OOO_STRING_SW_HTML_FF_path
; break;
253 case FF_NAME_NOEXT
: pFormatStr
= OOO_STRING_SW_HTML_FF_name_noext
; break;
257 bFixed
= static_cast<const SwFileNameField
*>(pField
)->IsFixed();
258 OSL_ENSURE( pFormatStr
, "unknown format for SwFileNameField" );
263 // ReqIF-XHTML doesn't allow <sdfield>.
264 if (rWrt
.mbReqIF
&& pTypeStr
)
269 // Output the <sdfield> tag.
272 OStringBuffer
sOut("<"
273 + rWrt
.GetNamespace()
274 + OOO_STRING_SVTOOLS_HTML_sdfield
276 OOO_STRING_SVTOOLS_HTML_O_type
281 sOut
.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_subtype
"=")
286 sOut
.append(OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_format
"=")
289 if( !aName
.isEmpty() )
291 sOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_name
"=\"");
292 rWrt
.Strm().WriteOString( sOut
);
294 HTMLOutFuncs::Out_String( rWrt
.Strm(), aName
);
297 if( !aValue
.isEmpty() )
299 sOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_value
"=\"");
300 rWrt
.Strm().WriteOString( sOut
);
302 HTMLOutFuncs::Out_String( rWrt
.Strm(), aValue
);
307 OSL_ENSURE( nFormat
, "number format is 0" );
308 sOut
.append(HTMLOutFuncs::CreateTableDataOptionsValNum(
309 bNumValue
, dNumValue
, nFormat
,
310 *rWrt
.m_pDoc
->GetNumberFormatter()));
314 sOut
.append(" " OOO_STRING_SVTOOLS_HTML_O_sdfixed
);
317 rWrt
.Strm().WriteOString( sOut
);
321 // output content of the field
322 OUString
const sExpand( pField
->ExpandField(true, nullptr) );
323 bool bNeedsCJKProcessing
= false;
324 if( !sExpand
.isEmpty() )
326 sal_uInt16 nScriptType
= g_pBreakIt
->GetBreakIter()->getScriptType( sExpand
, 0 );
327 sal_Int32 nPos
= g_pBreakIt
->GetBreakIter()->endOfScript( sExpand
, 0,
331 SwHTMLWriter::GetCSS1ScriptForScriptType( nScriptType
);
332 if( (nPos
< sExpand
.getLength() && nPos
>= 0) || nScript
!= rWrt
.m_nCSS1Script
)
334 bNeedsCJKProcessing
= true;
338 if( bNeedsCJKProcessing
)
340 //sequence of (start, end) property ranges we want to
342 SfxItemSetFixed
<RES_CHRATR_FONT
, RES_CHRATR_FONTSIZE
,
343 RES_CHRATR_POSTURE
, RES_CHRATR_POSTURE
,
344 RES_CHRATR_WEIGHT
, RES_CHRATR_WEIGHT
,
345 RES_CHRATR_CJK_FONT
, RES_CHRATR_CTL_WEIGHT
>
346 aScriptItemSet( rWrt
.m_pDoc
->GetAttrPool() );
347 rTextNd
.GetParaAttr(aScriptItemSet
, nFieldPos
, nFieldPos
+1);
349 sal_uInt16 aWesternWhichIds
[4] =
350 { RES_CHRATR_FONT
, RES_CHRATR_FONTSIZE
,
351 RES_CHRATR_POSTURE
, RES_CHRATR_WEIGHT
};
352 sal_uInt16 aCJKWhichIds
[4] =
353 { RES_CHRATR_CJK_FONT
, RES_CHRATR_CJK_FONTSIZE
,
354 RES_CHRATR_CJK_POSTURE
, RES_CHRATR_CJK_WEIGHT
};
355 sal_uInt16 aCTLWhichIds
[4] =
356 { RES_CHRATR_CTL_FONT
, RES_CHRATR_CTL_FONTSIZE
,
357 RES_CHRATR_CTL_POSTURE
, RES_CHRATR_CTL_WEIGHT
};
359 sal_uInt16
*pRefWhichIds
= nullptr;
360 switch( rWrt
.m_nCSS1Script
)
362 case CSS1_OUTMODE_WESTERN
:
363 pRefWhichIds
= aWesternWhichIds
;
365 case CSS1_OUTMODE_CJK
:
366 pRefWhichIds
= aCJKWhichIds
;
368 case CSS1_OUTMODE_CTL
:
369 pRefWhichIds
= aCTLWhichIds
;
376 sal_uInt16 nScriptType
= g_pBreakIt
->GetBreakIter()->getScriptType( sExpand
, nPos
);
378 SwHTMLWriter::GetCSS1ScriptForScriptType( nScriptType
);
379 sal_Int32 nEndPos
= g_pBreakIt
->GetBreakIter()->endOfScript(
380 sExpand
, nPos
, nScriptType
);
381 sal_Int32 nChunkLen
= nEndPos
- nPos
;
382 if( nScript
!= CSS1_OUTMODE_ANY_SCRIPT
&&
383 /* #108791# */ nScript
!= rWrt
.m_nCSS1Script
)
385 sal_uInt16
*pWhichIds
= nullptr;
388 case CSS1_OUTMODE_WESTERN
: pWhichIds
= aWesternWhichIds
; break;
389 case CSS1_OUTMODE_CJK
: pWhichIds
= aCJKWhichIds
; break;
390 case CSS1_OUTMODE_CTL
: pWhichIds
= aCTLWhichIds
; break;
393 rWrt
.m_bTagOn
= true;
395 const SfxPoolItem
*aItems
[5];
398 assert(pWhichIds
&& pRefWhichIds
);
399 if (pWhichIds
&& pRefWhichIds
)
401 for( int i
=0; i
<4; i
++ )
403 const SfxPoolItem
*pRefItem
=
404 aScriptItemSet
.GetItem( pRefWhichIds
[i
] );
405 const SfxPoolItem
*pItem
=
406 aScriptItemSet
.GetItem( pWhichIds
[i
] );
407 if( pRefItem
&& pItem
&&
408 !(0==i
? swhtml_css1atr_equalFontItems( *pRefItem
, *pItem
)
409 : *pRefItem
== *pItem
) )
411 Out( aHTMLAttrFnTab
, *pItem
, rWrt
);
412 aItems
[nItems
++] = pItem
;
417 HTMLOutFuncs::Out_String( rWrt
.Strm(), sExpand
.subView( nPos
, nChunkLen
) );
419 rWrt
.m_bTagOn
= false;
421 Out( aHTMLAttrFnTab
, *aItems
[--nItems
], rWrt
);
426 HTMLOutFuncs::Out_String( rWrt
.Strm(), sExpand
.subView( nPos
, nChunkLen
) );
430 while( nPos
< sExpand
.getLength() );
434 HTMLOutFuncs::Out_String( rWrt
.Strm(), sExpand
);
437 // Output the closing tag.
439 HTMLOutFuncs::Out_AsciiTag( rWrt
.Strm(), Concat2View(rWrt
.GetNamespace() + OOO_STRING_SVTOOLS_HTML_sdfield
), false );
446 const SwViewOption
* GetViewOptionFromDoc(SwDoc
* pDoc
)
448 SwDocShell
* pDocShell
= pDoc
->GetDocShell();
454 SwWrtShell
* pWrtShell
= pDocShell
->GetWrtShell();
460 return pWrtShell
->GetViewOptions();
464 SwHTMLWriter
& OutHTML_SwFormatField( SwHTMLWriter
& rWrt
, const SfxPoolItem
& rHt
)
466 const SwFormatField
& rField
= static_cast<const SwFormatField
&>(rHt
);
467 const SwField
* pField
= rField
.GetField();
468 const SwFieldType
* pFieldTyp
= pField
->GetTyp();
470 if( SwFieldIds::SetExp
== pFieldTyp
->Which() &&
471 (nsSwGetSetExpType::GSE_STRING
& pField
->GetSubType()) )
473 const bool bOn
= pFieldTyp
->GetName() == "HTML_ON";
474 if (!bOn
&& pFieldTyp
->GetName() != "HTML_OFF")
477 OUString
rText(comphelper::string::strip(pField
->GetPar2(), ' '));
478 rWrt
.Strm().WriteChar( '<' );
480 rWrt
.Strm().WriteChar( '/' );
481 // TODO: HTML-Tags are written without entities, that for, characters
482 // not contained in the destination encoding are lost!
483 OString
sTmp(OUStringToOString(rText
,
484 RTL_TEXTENCODING_UTF8
));
485 rWrt
.Strm().WriteOString( sTmp
).WriteChar( '>' );
487 else if( SwFieldIds::Postit
== pFieldTyp
->Which() )
489 // Comments will be written in ANSI character set, but with system
491 const OUString aComment
= pField
->GetPar2();
492 bool bWritten
= false;
494 if( (aComment
.getLength() >= 6 && aComment
.startsWith("<") && aComment
.endsWith(">") &&
495 o3tl::equalsIgnoreAsciiCase(aComment
.subView( 1, 4 ), u
"" OOO_STRING_SVTOOLS_HTML_meta
) ) ||
496 (aComment
.getLength() >= 7 &&
497 aComment
.startsWith( "<!--" ) &&
498 aComment
.endsWith( "-->" )) )
500 // directly output META tags
501 OUString
sComment(convertLineEnd(aComment
, GetSystemLineEnd()));
502 // TODO: HTML-Tags are written without entities, that for,
503 // characters not contained in the destination encoding are lost!
504 OString
sTmp(OUStringToOString(sComment
,
505 RTL_TEXTENCODING_UTF8
));
506 rWrt
.Strm().WriteOString( sTmp
);
509 else if( aComment
.getLength() >= 7 &&
510 aComment
.endsWith(">") &&
511 aComment
.startsWithIgnoreAsciiCase( "HTML:" ) )
513 OUString
sComment(comphelper::string::stripStart(aComment
.subView(5), ' '));
514 if( '<' == sComment
[0] )
516 sComment
= convertLineEnd(sComment
, GetSystemLineEnd());
517 // TODO: HTML-Tags are written without entities, that for,
518 // characters not contained in the destination encoding are
520 OString
sTmp(OUStringToOString(sComment
,
521 RTL_TEXTENCODING_UTF8
));
522 rWrt
.Strm().WriteOString( sTmp
);
530 OUString
sComment(convertLineEnd(aComment
, GetSystemLineEnd()));
533 "<" OOO_STRING_SVTOOLS_HTML_comment
535 OUStringToOString(comphelper::string::encodeForXml(sComment
), RTL_TEXTENCODING_UTF8
) +
537 rWrt
.Strm().WriteOString( sOut
);
540 else if( SwFieldIds::Script
== pFieldTyp
->Which() )
542 if (rWrt
.IsLFPossible())
543 rWrt
.OutNewLine( true );
545 bool bURL
= static_cast<const SwScriptField
*>(pField
)->IsCodeURL();
546 const OUString aType
= pField
->GetPar1();
547 OUString aContents
, aURL
;
549 aURL
= pField
->GetPar2();
551 aContents
= pField
->GetPar2();
553 // otherwise is the script content itself. Since only JavaScript
554 // is in fields, it must be JavaScript ...:)
555 HTMLOutFuncs::OutScript( rWrt
.Strm(), rWrt
.GetBaseURL(), aContents
, aType
, JAVASCRIPT
,
556 aURL
, nullptr, nullptr );
558 if (rWrt
.IsLFPossible())
559 rWrt
.OutNewLine( true );
563 const SwTextField
*pTextField
= rField
.GetTextField();
564 OSL_ENSURE( pTextField
, "Where is the txt fld?" );
567 const SwViewOption
* pViewOptions
= GetViewOptionFromDoc(rWrt
.m_pDoc
);
568 // ReqIF-XHTML doesn't allow specifying a background color.
569 bool bFieldShadings
= pViewOptions
&& pViewOptions
->IsFieldShadings() && !rWrt
.mbReqIF
;
572 // If there is a text portion background started already, that should have priority.
573 auto it
= rWrt
.maStartedAttributes
.find(RES_CHRATR_BACKGROUND
);
574 if (it
!= rWrt
.maStartedAttributes
.end())
575 bFieldShadings
= it
->second
<= 0;
580 const Color
& rColor
= pViewOptions
->GetFieldShadingsColor();
582 "<" + rWrt
.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span
583 " " OOO_STRING_SVTOOLS_HTML_O_style
"=\""
586 + GetCSS1_Color(rColor
)
588 rWrt
.Strm().WriteOString(sOut
);
591 OutHTML_SwField( rWrt
, pField
, pTextField
->GetTextNode(),
592 pTextField
->GetStart() );
595 HTMLOutFuncs::Out_AsciiTag(
596 rWrt
.Strm(), Concat2View(rWrt
.GetNamespace() + OOO_STRING_SVTOOLS_HTML_span
), false);
602 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */