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/htmltokn.h>
21 #include <svtools/htmlkywd.hxx>
22 #include <svtools/htmlout.hxx>
23 #include <numrule.hxx>
28 #include "htmlnum.hxx"
29 #include "wrthtml.hxx"
31 #include <osl/diagnose.h>
36 void SwHTMLWriter::FillNextNumInfo()
38 m_pNextNumRuleInfo
= nullptr;
40 SwNodeOffset nPos
= m_pCurrentPam
->GetPoint()->GetNodeIndex() + 1;
45 const SwNode
* pNd
= m_pDoc
->GetNodes()[nPos
];
46 if( pNd
->IsTextNode() )
48 m_pNextNumRuleInfo
.reset( new SwHTMLNumRuleInfo( *pNd
->GetTextNode() ) );
50 // Before a table we keep the old level if the same numbering is
51 // continued after the table and no new numbering is started.
52 // The table will get the indentation that corresponds to its
53 // numbering level during import.
55 m_pNextNumRuleInfo
->GetNumRule()==GetNumInfo().GetNumRule() &&
56 !m_pNextNumRuleInfo
->IsRestart(GetNumInfo()) )
58 m_pNextNumRuleInfo
->SetDepth( GetNumInfo().GetDepth() );
61 else if( pNd
->IsTableNode() )
63 // A table is skipped so the node after table is viewed.
64 nPos
= pNd
->EndOfSectionIndex() + 1;
69 // In all other case the numbering is over.
70 m_pNextNumRuleInfo
.reset(new SwHTMLNumRuleInfo
);
73 while( !m_pNextNumRuleInfo
);
76 void SwHTMLWriter::ClearNextNumInfo()
78 m_pNextNumRuleInfo
.reset();
81 void SwHTMLWriter::SetNextNumInfo( std::unique_ptr
<SwHTMLNumRuleInfo
> pNxt
)
83 m_pNextNumRuleInfo
= std::move(pNxt
);
86 SwHTMLWriter
& OutHTML_NumberBulletListStart( SwHTMLWriter
& rWrt
,
87 const SwHTMLNumRuleInfo
& rInfo
)
89 SwHTMLNumRuleInfo
& rPrevInfo
= rWrt
.GetNumInfo();
90 bool bSameRule
= rPrevInfo
.GetNumRule() == rInfo
.GetNumRule();
91 if( bSameRule
&& rPrevInfo
.GetDepth() >= rInfo
.GetDepth() &&
92 !rInfo
.IsRestart(rPrevInfo
) )
97 bool bStartValue
= false;
98 if( !bSameRule
&& rInfo
.GetDepth() )
100 OUString
aName( rInfo
.GetNumRule()->GetName() );
101 if( 0 != rWrt
.m_aNumRuleNames
.count( aName
) )
103 // The rule has been applied before
104 sal_Int16 eType
= rInfo
.GetNumRule()
105 ->Get( rInfo
.GetDepth()-1 ).GetNumberingType();
106 if( SVX_NUM_CHAR_SPECIAL
!= eType
&& SVX_NUM_BITMAP
!= eType
)
108 // If it's a numbering rule, the current number should be
109 // exported as start value, but only if there are no nodes
110 // within the numbering that have a lower level
112 if( rInfo
.GetDepth() > 1 )
115 rWrt
.m_pCurrentPam
->GetPoint()->GetNodeIndex() + 1;
118 const SwNode
* pNd
= rWrt
.m_pDoc
->GetNodes()[nPos
];
119 if( pNd
->IsTextNode() )
121 const SwTextNode
*pTextNd
= pNd
->GetTextNode();
122 if( !pTextNd
->GetNumRule() )
124 // node isn't numbered => check completed
128 OSL_ENSURE(! pTextNd
->IsOutline(),
129 "outline not expected");
131 if( pTextNd
->GetActualListLevel() + 1 <
134 if (rPrevInfo
.GetDepth() == 0)
135 // previous node had no numbering => write start value
138 // node is numbered, but level is lower
140 // => check completed
145 else if( pNd
->IsTableNode() )
148 nPos
= pNd
->EndOfSectionIndex() + 1;
152 // end node or sections start node -> check
163 rWrt
.m_aNumRuleNames
.insert( aName
);
167 OSL_ENSURE( rWrt
.m_nLastParaToken
== HtmlTokenId::NONE
,
168 "<PRE> was not closed before <OL>." );
169 sal_uInt16 nPrevDepth
=
170 (bSameRule
&& !rInfo
.IsRestart(rPrevInfo
)) ? rPrevInfo
.GetDepth() : 0;
172 for( sal_uInt16 i
=nPrevDepth
; i
<rInfo
.GetDepth(); i
++ )
174 rWrt
.OutNewLine(); // <OL>/<UL> in a new row
176 rWrt
.m_aBulletGrfs
[i
].clear();
177 OString sOut
= "<" + rWrt
.GetNamespace();
178 if (rWrt
.mbXHTML
&& i
!= nPrevDepth
)
180 // for all skipped sublevels, add a li
181 sOut
+= OOO_STRING_SVTOOLS_HTML_li
"><" + rWrt
.GetNamespace();
183 const SwNumFormat
& rNumFormat
= rInfo
.GetNumRule()->Get( i
);
184 sal_Int16 eType
= rNumFormat
.GetNumberingType();
185 if( SVX_NUM_CHAR_SPECIAL
== eType
)
187 // unordered list: <UL>
188 sOut
+= OOO_STRING_SVTOOLS_HTML_unorderlist
;
190 // determine the type by the bullet character
191 const char *pStr
= nullptr;
192 switch( rNumFormat
.GetBulletChar() )
194 case HTML_BULLETCHAR_DISC
:
195 pStr
= OOO_STRING_SVTOOLS_HTML_ULTYPE_disc
;
197 case HTML_BULLETCHAR_CIRCLE
:
198 pStr
= OOO_STRING_SVTOOLS_HTML_ULTYPE_circle
;
200 case HTML_BULLETCHAR_SQUARE
:
201 pStr
= OOO_STRING_SVTOOLS_HTML_ULTYPE_square
;
207 sOut
+= OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_type
"=\"") + pStr
+ "\"";
210 else if( SVX_NUM_BITMAP
== eType
)
212 // Unordered list: <UL>
213 sOut
+= OOO_STRING_SVTOOLS_HTML_unorderlist
;
217 // Ordered list: <OL>
218 sOut
+= OOO_STRING_SVTOOLS_HTML_orderlist
;
220 if (!rWrt
.mbReqIF
) // No 'type' nor 'start' attribute in ReqIF
222 // determine the type by the format
226 case SVX_NUM_CHARS_UPPER_LETTER
:
227 case SVX_NUM_CHARS_UPPER_LETTER_N
:
230 case SVX_NUM_CHARS_LOWER_LETTER
:
231 case SVX_NUM_CHARS_LOWER_LETTER_N
:
234 case SVX_NUM_ROMAN_UPPER
:
237 case SVX_NUM_ROMAN_LOWER
:
243 sOut
+= " " OOO_STRING_SVTOOLS_HTML_O_type
"=\"" + OStringChar(cType
) + "\"";
246 sal_uInt16 nStartVal
= rNumFormat
.GetStart();
247 if( bStartValue
&& 1 == nStartVal
&& i
== rInfo
.GetDepth()-1 )
249 if ( rWrt
.m_pCurrentPam
->GetPointNode().GetTextNode()->GetNum() )
251 nStartVal
= static_cast< sal_uInt16
>( rWrt
.m_pCurrentPam
->GetPointNode()
252 .GetTextNode()->GetNumberVector()[i
] );
256 OSL_FAIL( "<OutHTML_NumberBulletListStart(..) - text node has no number." );
261 sOut
+= " " OOO_STRING_SVTOOLS_HTML_O_start
"=\"" + OString::number(static_cast<sal_Int32
>(nStartVal
)) + "\"";
266 rWrt
.Strm().WriteOString(sOut
);
268 if (eType
== SVX_NUM_BITMAP
)
269 OutHTML_BulletImage(rWrt
, nullptr, rNumFormat
.GetBrush(), rWrt
.m_aBulletGrfs
[i
]);
271 if( rWrt
.m_bCfgOutStyles
)
272 OutCSS1_NumberBulletListStyleOpt( rWrt
, *rInfo
.GetNumRule(), static_cast<sal_uInt8
>(i
) );
274 rWrt
.Strm().WriteChar( '>' );
276 rWrt
.IncIndentLevel(); // indent content of <OL>
282 SwHTMLWriter
& OutHTML_NumberBulletListEnd( SwHTMLWriter
& rWrt
,
283 const SwHTMLNumRuleInfo
& rNextInfo
)
285 SwHTMLNumRuleInfo
& rInfo
= rWrt
.GetNumInfo();
286 bool bSameRule
= rNextInfo
.GetNumRule() == rInfo
.GetNumRule();
287 bool bListEnd
= !bSameRule
|| rNextInfo
.GetDepth() < rInfo
.GetDepth() || rNextInfo
.IsRestart(rInfo
);
288 bool bNextIsSubitem
= !bListEnd
&& rNextInfo
.GetDepth() > rInfo
.GetDepth();
290 // XHTML </li> for the list item content, if there is an open <li>.
291 if (bListEnd
|| (!bNextIsSubitem
&& rNextInfo
.IsNumbered()))
293 HTMLOutFuncs::Out_AsciiTag(
294 rWrt
.Strm(), Concat2View(rWrt
.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li
),
303 OSL_ENSURE( rWrt
.m_nLastParaToken
== HtmlTokenId::NONE
,
304 "<PRE> was not closed before </OL>." );
305 sal_uInt16 nNextDepth
=
306 (bSameRule
&& !rNextInfo
.IsRestart(rInfo
)) ? rNextInfo
.GetDepth() : 0;
308 // MIB 23.7.97: We must loop backwards, to get the right order of </OL>/</UL>
309 for( sal_uInt16 i
=rInfo
.GetDepth(); i
>nNextDepth
; i
-- )
311 rWrt
.DecIndentLevel(); // indent content of <OL>
312 if( rWrt
.m_bLFPossible
)
313 rWrt
.OutNewLine(); // </OL>/</UL> in a new line
315 // a list is started or ended:
316 sal_Int16 eType
= rInfo
.GetNumRule()->Get( i
-1 ).GetNumberingType();
318 if( SVX_NUM_CHAR_SPECIAL
== eType
|| SVX_NUM_BITMAP
== eType
)
319 aTag
= OOO_STRING_SVTOOLS_HTML_unorderlist
;
321 aTag
= OOO_STRING_SVTOOLS_HTML_orderlist
;
322 HTMLOutFuncs::Out_AsciiTag( rWrt
.Strm(), Concat2View(rWrt
.GetNamespace() + aTag
), false );
323 if (rWrt
.mbXHTML
&& (i
!= nNextDepth
+ 1 || (i
!= 1 && rNextInfo
.IsNumbered())))
325 // for all skipped sublevels, close a li
326 HTMLOutFuncs::Out_AsciiTag(
327 rWrt
.Strm(), Concat2View(rWrt
.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li
),
330 rWrt
.m_bLFPossible
= true;
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */