build fix
[LibreOffice.git] / sw / source / filter / html / htmlftn.cxx
blobf6a8d02510507de949e4e5a7df321cd20e98c3d8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <svtools/htmlout.hxx>
21 #include <svtools/htmlkywd.hxx>
22 #include <rtl/strbuf.hxx>
23 #include <ndindex.hxx>
24 #include <fmtftn.hxx>
25 #include <txtftn.hxx>
26 #include <ftninfo.hxx>
27 #include <doc.hxx>
28 #include <ndtxt.hxx>
29 #include <charfmt.hxx>
31 #include "swhtml.hxx"
32 #include "wrthtml.hxx"
34 struct SwHTMLFootEndNote_Impl
36 SwHTMLTextFootnotes aTextFootnotes;
37 std::vector<OUString> aNames;
39 OUString sName;
40 OUString sContent; // Infos fuer die letzte Fussnote
41 bool bEndNote;
42 bool bFixed;
45 sal_Int32 lcl_html_getNextPart( OUString& rPart, const OUString& rContent,
46 sal_Int32 nPos )
48 rPart = aEmptyOUStr;
49 sal_Int32 nLen = rContent.getLength();
50 if( nPos >= nLen )
52 nPos = -1;
54 else
56 bool bQuoted = false, bDone = false;
57 for( ; nPos < nLen && !bDone; nPos++ )
59 sal_Unicode c = rContent[nPos];
60 switch( c )
62 case '\\':
63 if( bQuoted )
64 rPart += OUStringLiteral1( c );
65 bQuoted = !bQuoted;
66 break;
68 case ';':
69 if( bQuoted )
70 rPart += OUStringLiteral1( c );
71 else
72 bDone = true;
73 bQuoted = false;
74 break;
76 default:
77 rPart += OUStringLiteral1( c );
78 bQuoted = false;
79 break;
84 return nPos;
87 sal_Int32 lcl_html_getEndNoteInfo( SwEndNoteInfo& rInfo,
88 const OUString& rContent,
89 bool bEndNote )
91 sal_Int32 nStrPos = 0;
92 for( int nPart = 0; nPart < 4; ++nPart )
94 OUString aPart;
95 if( -1 != nStrPos )
96 nStrPos = lcl_html_getNextPart( aPart, rContent, nStrPos );
98 switch( nPart )
100 case 0:
101 rInfo.aFormat.SetNumberingType( static_cast< sal_Int16 >(bEndNote ? SVX_NUM_ROMAN_LOWER : SVX_NUM_ARABIC));
102 if( !aPart.isEmpty() )
103 rInfo.aFormat.SetNumberingType(SwHTMLParser::GetNumType( aPart,
104 rInfo.aFormat.GetNumberingType() ));
105 break;
107 case 1:
108 rInfo.nFootnoteOffset = aPart.isEmpty() ? 0 : (sal_uInt16)aPart.toInt32();
109 break;
111 case 2:
112 rInfo.SetPrefix( aPart );
113 break;
115 case 3:
116 rInfo.SetSuffix( aPart );
117 break;
121 return nStrPos;
124 void SwHTMLParser::FillEndNoteInfo( const OUString& rContent )
126 SwEndNoteInfo aInfo( m_pDoc->GetEndNoteInfo() );
127 lcl_html_getEndNoteInfo( aInfo, rContent, true );
128 m_pDoc->SetEndNoteInfo( aInfo );
131 void SwHTMLParser::FillFootNoteInfo( const OUString& rContent )
133 SwFootnoteInfo aInfo( m_pDoc->GetFootnoteInfo() );
135 sal_Int32 nStrPos = lcl_html_getEndNoteInfo( aInfo, rContent, false );
137 for( int nPart = 4; nPart < 8; ++nPart )
139 OUString aPart;
140 if( -1 != nStrPos )
141 nStrPos = lcl_html_getNextPart( aPart, rContent, nStrPos );
143 switch( nPart )
145 case 4:
146 aInfo.eNum = FTNNUM_DOC;
147 if( !aPart.isEmpty() )
149 switch( aPart[0] )
151 case 'D': aInfo.eNum = FTNNUM_DOC; break;
152 case 'C': aInfo.eNum = FTNNUM_CHAPTER; break;
153 case 'P': aInfo.eNum = FTNNUM_PAGE; break;
156 break;
158 case 5:
159 aInfo.ePos = FTNPOS_PAGE;
160 if( !aPart.isEmpty() )
162 switch( aPart[0] )
164 case 'C': aInfo.ePos = FTNPOS_CHAPTER; break;
165 case 'P': aInfo.ePos = FTNPOS_PAGE; break;
168 break;
170 case 6:
171 aInfo.aQuoVadis = aPart;
172 break;
174 case 7:
175 aInfo.aErgoSum = aPart;
176 break;
180 m_pDoc->SetFootnoteInfo( aInfo );
183 void SwHTMLParser::InsertFootEndNote( const OUString& rName, bool bEndNote,
184 bool bFixed )
186 if( !m_pFootEndNoteImpl )
187 m_pFootEndNoteImpl = new SwHTMLFootEndNote_Impl;
189 m_pFootEndNoteImpl->sName = rName;
190 if( m_pFootEndNoteImpl->sName.getLength() > 3 )
191 m_pFootEndNoteImpl->sName = m_pFootEndNoteImpl->sName.copy( 0, m_pFootEndNoteImpl->sName.getLength() - 3 );
192 m_pFootEndNoteImpl->sName = m_pFootEndNoteImpl->sName.toAsciiUpperCase();
193 m_pFootEndNoteImpl->bEndNote = bEndNote;
194 m_pFootEndNoteImpl->bFixed = bFixed;
195 m_pFootEndNoteImpl->sContent = aEmptyOUStr;
198 void SwHTMLParser::FinishFootEndNote()
200 if( !m_pFootEndNoteImpl )
201 return;
203 SwFormatFootnote aFootnote( m_pFootEndNoteImpl->bEndNote );
204 if( m_pFootEndNoteImpl->bFixed )
205 aFootnote.SetNumStr( m_pFootEndNoteImpl->sContent );
207 m_pDoc->getIDocumentContentOperations().InsertPoolItem( *m_pPam, aFootnote );
208 SwTextFootnote * const pTextFootnote = static_cast<SwTextFootnote *>(
209 m_pPam->GetNode().GetTextNode()->GetTextAttrForCharAt(
210 m_pPam->GetPoint()->nContent.GetIndex() - 1, RES_TXTATR_FTN ) );
211 // In Kopf- und Fusszeilen duerfen keine Fussnoten eingefuegt werden.
212 if( pTextFootnote )
214 m_pFootEndNoteImpl->aTextFootnotes.push_back( pTextFootnote );
215 m_pFootEndNoteImpl->aNames.push_back(m_pFootEndNoteImpl->sName);
217 m_pFootEndNoteImpl->sName = aEmptyOUStr;
218 m_pFootEndNoteImpl->sContent = aEmptyOUStr;
219 m_pFootEndNoteImpl->bFixed = false;
222 void SwHTMLParser::InsertFootEndNoteText()
224 if( m_pFootEndNoteImpl && m_pFootEndNoteImpl->bFixed )
225 m_pFootEndNoteImpl->sContent += aToken;
228 void SwHTMLParser::DeleteFootEndNoteImpl()
230 delete m_pFootEndNoteImpl;
231 m_pFootEndNoteImpl = nullptr;
234 SwNodeIndex *SwHTMLParser::GetFootEndNoteSection( const OUString& rName )
236 SwNodeIndex *pStartNodeIdx = nullptr;
238 if( m_pFootEndNoteImpl )
240 OUString aName(rName.toAsciiUpperCase());
242 size_t nCount = m_pFootEndNoteImpl->aNames.size();
243 for(size_t i = 0; i < nCount; ++i)
245 if(m_pFootEndNoteImpl->aNames[i] == aName)
247 pStartNodeIdx = m_pFootEndNoteImpl->aTextFootnotes[i]->GetStartNode();
248 m_pFootEndNoteImpl->aNames.erase(m_pFootEndNoteImpl->aNames.begin() + i);
249 m_pFootEndNoteImpl->aTextFootnotes.erase( m_pFootEndNoteImpl->aTextFootnotes.begin() + i );
250 if(m_pFootEndNoteImpl->aNames.empty())
252 delete m_pFootEndNoteImpl;
253 m_pFootEndNoteImpl = nullptr;
256 break;
261 return pStartNodeIdx;
264 Writer& OutHTML_SwFormatFootnote( Writer& rWrt, const SfxPoolItem& rHt )
266 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
268 SwFormatFootnote& rFormatFootnote = const_cast<SwFormatFootnote&>(static_cast<const SwFormatFootnote&>(rHt));
269 SwTextFootnote *pTextFootnote = rFormatFootnote.GetTextFootnote();
270 if( !pTextFootnote )
271 return rWrt;
273 OUString sFootnoteName, sClass;
274 size_t nPos;
275 if( rFormatFootnote.IsEndNote() )
277 nPos = rHTMLWrt.m_pFootEndNotes ? rHTMLWrt.m_pFootEndNotes->size() : 0;
278 OSL_ENSURE( nPos == static_cast<size_t>(rHTMLWrt.m_nFootNote + rHTMLWrt.m_nEndNote),
279 "OutHTML_SwFormatFootnote: wrong position" );
280 sClass = OOO_STRING_SVTOOLS_HTML_sdendnote_anc;
281 sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdendnote + OUString::number( (sal_Int32)(++rHTMLWrt.m_nEndNote) );
283 else
285 nPos = rHTMLWrt.m_nFootNote;
286 sClass = OOO_STRING_SVTOOLS_HTML_sdfootnote_anc;
287 sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote + OUString::number( (sal_Int32)(++rHTMLWrt.m_nFootNote));
290 if( !rHTMLWrt.m_pFootEndNotes )
291 rHTMLWrt.m_pFootEndNotes = new SwHTMLTextFootnotes;
292 rHTMLWrt.m_pFootEndNotes->insert( rHTMLWrt.m_pFootEndNotes->begin() + nPos, pTextFootnote );
294 OStringBuffer sOut;
295 sOut.append("<" OOO_STRING_SVTOOLS_HTML_anchor " "
296 OOO_STRING_SVTOOLS_HTML_O_class "=\"");
297 rWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
298 HTMLOutFuncs::Out_String( rWrt.Strm(), sClass, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
299 sOut.append("\" " OOO_STRING_SVTOOLS_HTML_O_name "=\"");
300 rWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
301 HTMLOutFuncs::Out_String( rWrt.Strm(), sFootnoteName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
302 sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_anchor "\" "
303 OOO_STRING_SVTOOLS_HTML_O_href "=\"#");
304 rWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
305 HTMLOutFuncs::Out_String( rWrt.Strm(), sFootnoteName, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
306 sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_symbol "\"");
307 if( !rFormatFootnote.GetNumStr().isEmpty() )
308 sOut.append(" " OOO_STRING_SVTOOLS_HTML_O_sdfixed);
309 sOut.append(">");
310 rWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
311 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_superscript );
313 HTMLOutFuncs::Out_String( rWrt.Strm(), rFormatFootnote.GetViewNumStr(*rWrt.pDoc),
314 rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
315 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_superscript, false );
316 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), OOO_STRING_SVTOOLS_HTML_anchor, false );
318 return rWrt;
321 void SwHTMLWriter::OutFootEndNotes()
323 OSL_ENSURE( m_pFootEndNotes,
324 "SwHTMLWriter::OutFootEndNotes(): unnoetiger Aufruf" );
325 if( !m_pFootEndNotes )
326 return;
328 #if OSL_DEBUG_LEVEL > 0
329 sal_uInt16 nFootnote = m_nFootNote, nEn = m_nEndNote;
330 #endif
331 m_nFootNote = 0;
332 m_nEndNote = 0;
334 for( auto *pTextFootnote : *m_pFootEndNotes )
336 m_pFormatFootnote = &pTextFootnote->GetFootnote();
338 OUString sFootnoteName, sClass;
339 if( m_pFormatFootnote->IsEndNote() )
341 sClass = OOO_STRING_SVTOOLS_HTML_sdendnote;
342 sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdendnote;
343 sFootnoteName += OUString::number((sal_Int32)(++m_nEndNote));
345 else
347 sClass = OOO_STRING_SVTOOLS_HTML_sdfootnote;
348 sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote;
349 sFootnoteName += OUString::number((sal_Int32)(++m_nFootNote));
352 if( m_bLFPossible )
353 OutNewLine();
354 OStringBuffer sOut;
355 sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_division)
356 .append(' ').append(OOO_STRING_SVTOOLS_HTML_O_id).append("=\"");
357 Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
358 HTMLOutFuncs::Out_String( Strm(), sFootnoteName, m_eDestEnc, &m_aNonConvertableCharacters );
359 Strm().WriteCharPtr( "\">" );
361 m_bLFPossible = true;
362 IncIndentLevel(); // Inhalt von <DIV> einruecken
364 OSL_ENSURE( pTextFootnote, "SwHTMLWriter::OutFootEndNotes: SwTextFootnote fehlt" );
365 SwNodeIndex *pSttNdIdx = pTextFootnote->GetStartNode();
366 OSL_ENSURE( pSttNdIdx,
367 "SwHTMLWriter::OutFootEndNotes: StartNode-Index fehlt" );
368 if( pSttNdIdx )
370 HTMLSaveData aSaveData( *this, pSttNdIdx->GetIndex()+1,
371 pSttNdIdx->GetNode().EndOfSectionIndex(), false );
372 Out_SwDoc( pCurPam );
375 DecIndentLevel(); // Inhalt von <DIV> einruecken
376 if( m_bLFPossible )
377 OutNewLine();
378 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_division, false );
379 m_bLFPossible = true;
381 OSL_ENSURE( !m_pFormatFootnote,
382 "SwHTMLWriter::OutFootEndNotes: Footnote wurde nicht ausgegeben" );
383 if( m_pFormatFootnote )
385 if( m_pFormatFootnote->IsEndNote() )
386 m_nEndNote++;
387 else
388 m_nFootNote++;
390 m_pFormatFootnote = nullptr;
394 #if OSL_DEBUG_LEVEL > 0
395 OSL_ENSURE( nFootnote == m_nFootNote,
396 "SwHTMLWriter::OutFootEndNotes: Anzahl Fussnoten stimmt nicht" );
397 OSL_ENSURE( nEn == m_nEndNote,
398 "SwHTMLWriter::OutFootEndNotes: Anzahl Endnoten stimmt nicht" );
399 #endif
401 delete m_pFootEndNotes;
402 m_pFootEndNotes = nullptr;
403 m_nFootNote = m_nEndNote = 0;
406 OUString SwHTMLWriter::GetFootEndNoteSym( const SwFormatFootnote& rFormatFootnote )
408 const SwEndNoteInfo * pInfo = nullptr;
409 if( rFormatFootnote.GetNumStr().isEmpty() )
410 pInfo = rFormatFootnote.IsEndNote() ? &pDoc->GetEndNoteInfo()
411 : &pDoc->GetFootnoteInfo();
413 OUString sRet;
414 if( pInfo )
415 sRet = pInfo->GetPrefix();
416 sRet += rFormatFootnote.GetViewNumStr( *pDoc );
417 if( pInfo )
418 sRet += pInfo->GetSuffix();
420 return sRet;
423 void SwHTMLWriter::OutFootEndNoteSym( const SwFormatFootnote& rFormatFootnote,
424 const OUString& rNum,
425 sal_uInt16 nScript )
427 const SwEndNoteInfo *pInfo;
429 OUString sFootnoteName, sClass;
430 if( rFormatFootnote.IsEndNote() )
432 sClass = OOO_STRING_SVTOOLS_HTML_sdendnote_sym;
433 sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdendnote;
434 sFootnoteName += OUString::number((sal_Int32)m_nEndNote);
435 pInfo = &pDoc->GetEndNoteInfo();
437 else
439 sClass = OOO_STRING_SVTOOLS_HTML_sdfootnote_sym;
440 sFootnoteName = OOO_STRING_SVTOOLS_HTML_sdfootnote;
441 sFootnoteName += OUString::number((sal_Int32)m_nFootNote);
442 pInfo = &pDoc->GetFootnoteInfo();
445 const SwCharFormat *pSymCharFormat = pInfo->GetCharFormat( *pDoc );
446 if( pSymCharFormat && 0 != m_aScriptTextStyles.count( pSymCharFormat->GetName() ) )
448 switch( nScript )
450 case CSS1_OUTMODE_WESTERN:
451 sClass += "-western";
452 break;
453 case CSS1_OUTMODE_CJK:
454 sClass += "-cjk";
455 break;
456 case CSS1_OUTMODE_CTL:
457 sClass += "-ctl";
458 break;
462 OStringBuffer sOut;
463 sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_anchor).append(' ')
464 .append(OOO_STRING_SVTOOLS_HTML_O_class).append("=\"");
465 Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
466 HTMLOutFuncs::Out_String( Strm(), sClass, m_eDestEnc, &m_aNonConvertableCharacters );
467 sOut.append("\" ").append(OOO_STRING_SVTOOLS_HTML_O_name).append("=\"");
468 Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
469 HTMLOutFuncs::Out_String( Strm(), sFootnoteName, m_eDestEnc, &m_aNonConvertableCharacters );
470 sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_symbol).append("\" ")
471 .append(OOO_STRING_SVTOOLS_HTML_O_href).append("=\"#");
472 Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
473 HTMLOutFuncs::Out_String( Strm(), sFootnoteName, m_eDestEnc, &m_aNonConvertableCharacters );
474 sOut.append(OOO_STRING_SVTOOLS_HTML_FTN_anchor).append("\">");
475 Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
477 HTMLOutFuncs::Out_String( Strm(), rNum, m_eDestEnc, &m_aNonConvertableCharacters );
478 HTMLOutFuncs::Out_AsciiTag( Strm(), OOO_STRING_SVTOOLS_HTML_anchor, false );
481 static int lcl_html_fillEndNoteInfo( const SwEndNoteInfo& rInfo,
482 OUString *pParts,
483 bool bEndNote )
485 int nParts = 0;
486 sal_Int16 eFormat = rInfo.aFormat.GetNumberingType();
487 if( (bEndNote ? SVX_NUM_ROMAN_LOWER : SVX_NUM_ARABIC) != eFormat )
489 const sal_Char *pStr = SwHTMLWriter::GetNumFormat( eFormat );
490 if( pStr )
492 pParts[0] = OUString::createFromAscii( pStr );
493 nParts = 1;
496 if( rInfo.nFootnoteOffset > 0 )
498 pParts[1] = OUString::number(rInfo.nFootnoteOffset);
499 nParts = 2;
501 if( !rInfo.GetPrefix().isEmpty() )
503 pParts[2] = rInfo.GetPrefix();
504 nParts = 3;
506 if( !rInfo.GetSuffix().isEmpty() )
508 pParts[3] = rInfo.GetSuffix();
509 nParts = 4;
512 return nParts;
515 static void lcl_html_outFootEndNoteInfo( Writer& rWrt, OUString *pParts,
516 int nParts, const sal_Char *pName )
518 SwHTMLWriter& rHTMLWrt = static_cast<SwHTMLWriter&>(rWrt);
520 OUString aContent;
521 for( int i=0; i<nParts; ++i )
523 OUString aTmp( pParts[i] );
524 aTmp = aTmp.replaceAll( "\\", "\\\\" );
525 aTmp = aTmp.replaceAll( ";", "\\;" );
526 if( i > 0 )
527 aContent += ";";
528 aContent += aTmp;
531 rHTMLWrt.OutNewLine();
532 OStringBuffer sOut;
533 sOut.append('<').append(OOO_STRING_SVTOOLS_HTML_meta).append(' ')
534 .append(OOO_STRING_SVTOOLS_HTML_O_name).append("=\"").append(pName)
535 .append("\" ").append(OOO_STRING_SVTOOLS_HTML_O_content).append("=\"");
536 rWrt.Strm().WriteCharPtr( sOut.makeStringAndClear().getStr() );
537 HTMLOutFuncs::Out_String( rWrt.Strm(), aContent, rHTMLWrt.m_eDestEnc, &rHTMLWrt.m_aNonConvertableCharacters );
538 rWrt.Strm().WriteCharPtr( "\">" );
541 void SwHTMLWriter::OutFootEndNoteInfo()
543 // Nummerntyp (1 bzw. i)
544 // Offset (0)
545 // Davor
546 // Dahinter
547 // Dok/Seite/Kap (D)
548 // Position (S)
549 // Folgeseite
550 // Beginn
553 const SwFootnoteInfo& rInfo = pDoc->GetFootnoteInfo();
554 OUString aParts[8];
555 int nParts = lcl_html_fillEndNoteInfo( rInfo, aParts, false );
556 if( rInfo.eNum != FTNNUM_DOC )
558 aParts[4] = rInfo.eNum == FTNNUM_CHAPTER ? OUString( "C" ) : OUString( "P" );
559 nParts = 5;
561 if( rInfo.ePos != FTNPOS_PAGE)
563 aParts[5] = "C";
564 nParts = 6;
566 if( !rInfo.aQuoVadis.isEmpty() )
568 aParts[6] = rInfo.aQuoVadis;
569 nParts = 7;
571 if( !rInfo.aErgoSum.isEmpty() )
573 aParts[7] = rInfo.aErgoSum;
574 nParts = 8;
576 if( nParts > 0 )
577 lcl_html_outFootEndNoteInfo( *this, aParts, nParts,
578 OOO_STRING_SVTOOLS_HTML_META_sdfootnote );
582 const SwEndNoteInfo& rInfo = pDoc->GetEndNoteInfo();
583 OUString aParts[4];
584 const int nParts = lcl_html_fillEndNoteInfo( rInfo, aParts, true );
585 if( nParts > 0 )
586 lcl_html_outFootEndNoteInfo( *this, aParts, nParts,
587 OOO_STRING_SVTOOLS_HTML_META_sdendnote );
591 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */