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 <svtools/htmlout.hxx>
21 #include <svtools/htmlkywd.hxx>
22 #include <rtl/strbuf.hxx>
23 #include <ndindex.hxx>
26 #include <ftninfo.hxx>
29 #include <charfmt.hxx>
32 #include "wrthtml.hxx"
34 struct SwHTMLFootEndNote_Impl
36 SwHTMLTextFootnotes aTextFootnotes
;
37 std::vector
<OUString
> aNames
;
40 OUString sContent
; // Infos fuer die letzte Fussnote
45 sal_Int32
lcl_html_getNextPart( OUString
& rPart
, const OUString
& rContent
,
49 sal_Int32 nLen
= rContent
.getLength();
56 bool bQuoted
= false, bDone
= false;
57 for( ; nPos
< nLen
&& !bDone
; nPos
++ )
59 sal_Unicode c
= rContent
[nPos
];
64 rPart
+= OUStringLiteral1( c
);
70 rPart
+= OUStringLiteral1( c
);
77 rPart
+= OUStringLiteral1( c
);
87 sal_Int32
lcl_html_getEndNoteInfo( SwEndNoteInfo
& rInfo
,
88 const OUString
& rContent
,
91 sal_Int32 nStrPos
= 0;
92 for( int nPart
= 0; nPart
< 4; ++nPart
)
96 nStrPos
= lcl_html_getNextPart( aPart
, rContent
, nStrPos
);
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() ));
108 rInfo
.nFootnoteOffset
= aPart
.isEmpty() ? 0 : (sal_uInt16
)aPart
.toInt32();
112 rInfo
.SetPrefix( aPart
);
116 rInfo
.SetSuffix( aPart
);
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
)
141 nStrPos
= lcl_html_getNextPart( aPart
, rContent
, nStrPos
);
146 aInfo
.eNum
= FTNNUM_DOC
;
147 if( !aPart
.isEmpty() )
151 case 'D': aInfo
.eNum
= FTNNUM_DOC
; break;
152 case 'C': aInfo
.eNum
= FTNNUM_CHAPTER
; break;
153 case 'P': aInfo
.eNum
= FTNNUM_PAGE
; break;
159 aInfo
.ePos
= FTNPOS_PAGE
;
160 if( !aPart
.isEmpty() )
164 case 'C': aInfo
.ePos
= FTNPOS_CHAPTER
; break;
165 case 'P': aInfo
.ePos
= FTNPOS_PAGE
; break;
171 aInfo
.aQuoVadis
= aPart
;
175 aInfo
.aErgoSum
= aPart
;
180 m_pDoc
->SetFootnoteInfo( aInfo
);
183 void SwHTMLParser::InsertFootEndNote( const OUString
& rName
, bool bEndNote
,
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
)
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.
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;
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();
273 OUString sFootnoteName
, sClass
;
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
) );
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
);
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
);
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 );
321 void SwHTMLWriter::OutFootEndNotes()
323 OSL_ENSURE( m_pFootEndNotes
,
324 "SwHTMLWriter::OutFootEndNotes(): unnoetiger Aufruf" );
325 if( !m_pFootEndNotes
)
328 #if OSL_DEBUG_LEVEL > 0
329 sal_uInt16 nFootnote
= m_nFootNote
, nEn
= m_nEndNote
;
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
));
347 sClass
= OOO_STRING_SVTOOLS_HTML_sdfootnote
;
348 sFootnoteName
= OOO_STRING_SVTOOLS_HTML_sdfootnote
;
349 sFootnoteName
+= OUString::number((sal_Int32
)(++m_nFootNote
));
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" );
370 HTMLSaveData
aSaveData( *this, pSttNdIdx
->GetIndex()+1,
371 pSttNdIdx
->GetNode().EndOfSectionIndex(), false );
372 Out_SwDoc( pCurPam
);
375 DecIndentLevel(); // Inhalt von <DIV> einruecken
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() )
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" );
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();
415 sRet
= pInfo
->GetPrefix();
416 sRet
+= rFormatFootnote
.GetViewNumStr( *pDoc
);
418 sRet
+= pInfo
->GetSuffix();
423 void SwHTMLWriter::OutFootEndNoteSym( const SwFormatFootnote
& rFormatFootnote
,
424 const OUString
& rNum
,
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();
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() ) )
450 case CSS1_OUTMODE_WESTERN
:
451 sClass
+= "-western";
453 case CSS1_OUTMODE_CJK
:
456 case CSS1_OUTMODE_CTL
:
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
,
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
);
492 pParts
[0] = OUString::createFromAscii( pStr
);
496 if( rInfo
.nFootnoteOffset
> 0 )
498 pParts
[1] = OUString::number(rInfo
.nFootnoteOffset
);
501 if( !rInfo
.GetPrefix().isEmpty() )
503 pParts
[2] = rInfo
.GetPrefix();
506 if( !rInfo
.GetSuffix().isEmpty() )
508 pParts
[3] = rInfo
.GetSuffix();
515 static void lcl_html_outFootEndNoteInfo( Writer
& rWrt
, OUString
*pParts
,
516 int nParts
, const sal_Char
*pName
)
518 SwHTMLWriter
& rHTMLWrt
= static_cast<SwHTMLWriter
&>(rWrt
);
521 for( int i
=0; i
<nParts
; ++i
)
523 OUString
aTmp( pParts
[i
] );
524 aTmp
= aTmp
.replaceAll( "\\", "\\\\" );
525 aTmp
= aTmp
.replaceAll( ";", "\\;" );
531 rHTMLWrt
.OutNewLine();
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)
553 const SwFootnoteInfo
& rInfo
= pDoc
->GetFootnoteInfo();
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" );
561 if( rInfo
.ePos
!= FTNPOS_PAGE
)
566 if( !rInfo
.aQuoVadis
.isEmpty() )
568 aParts
[6] = rInfo
.aQuoVadis
;
571 if( !rInfo
.aErgoSum
.isEmpty() )
573 aParts
[7] = rInfo
.aErgoSum
;
577 lcl_html_outFootEndNoteInfo( *this, aParts
, nParts
,
578 OOO_STRING_SVTOOLS_HTML_META_sdfootnote
);
582 const SwEndNoteInfo
& rInfo
= pDoc
->GetEndNoteInfo();
584 const int nParts
= lcl_html_fillEndNoteInfo( rInfo
, aParts
, true );
586 lcl_html_outFootEndNoteInfo( *this, aParts
, nParts
,
587 OOO_STRING_SVTOOLS_HTML_META_sdendnote
);
591 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */