LibreOffice Module sw (master) 1
htmlnumwriter.cxx
Go to the documentation of this file.
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 <svtools/htmltokn.h>
21#include <svtools/htmlkywd.hxx>
22#include <svtools/htmlout.hxx>
23#include <numrule.hxx>
24#include <doc.hxx>
25#include <ndtxt.hxx>
26#include <pam.hxx>
27
28#include "htmlnum.hxx"
29#include "wrthtml.hxx"
30
31#include <osl/diagnose.h>
32
33using namespace css;
34
35
37{
38 m_pNextNumRuleInfo = nullptr;
39
40 SwNodeOffset nPos = m_pCurrentPam->GetPoint()->GetNodeIndex() + 1;
41
42 bool bTable = false;
43 do
44 {
45 const SwNode* pNd = m_pDoc->GetNodes()[nPos];
46 if( pNd->IsTextNode() )
47 {
48 m_pNextNumRuleInfo.reset( new SwHTMLNumRuleInfo( *pNd->GetTextNode() ) );
49
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.
54 if( bTable &&
55 m_pNextNumRuleInfo->GetNumRule()==GetNumInfo().GetNumRule() &&
56 !m_pNextNumRuleInfo->IsRestart(GetNumInfo()) )
57 {
58 m_pNextNumRuleInfo->SetDepth( GetNumInfo().GetDepth() );
59 }
60 }
61 else if( pNd->IsTableNode() )
62 {
63 // A table is skipped so the node after table is viewed.
64 nPos = pNd->EndOfSectionIndex() + 1;
65 bTable = true;
66 }
67 else
68 {
69 // In all other case the numbering is over.
71 }
72 }
73 while( !m_pNextNumRuleInfo );
74}
75
77{
78 m_pNextNumRuleInfo.reset();
79}
80
81void SwHTMLWriter::SetNextNumInfo( std::unique_ptr<SwHTMLNumRuleInfo> pNxt )
82{
83 m_pNextNumRuleInfo = std::move(pNxt);
84}
85
87 const SwHTMLNumRuleInfo& rInfo )
88{
89 SwHTMLNumRuleInfo& rPrevInfo = rWrt.GetNumInfo();
90 bool bSameRule = rPrevInfo.GetNumRule() == rInfo.GetNumRule();
91 if( bSameRule && rPrevInfo.GetDepth() >= rInfo.GetDepth() &&
92 !rInfo.IsRestart(rPrevInfo) )
93 {
94 return rWrt;
95 }
96
97 bool bStartValue = false;
98 if( !bSameRule && rInfo.GetDepth() )
99 {
100 OUString aName( rInfo.GetNumRule()->GetName() );
101 if( 0 != rWrt.m_aNumRuleNames.count( aName ) )
102 {
103 // The rule has been applied before
104 sal_Int16 eType = rInfo.GetNumRule()
105 ->Get( rInfo.GetDepth()-1 ).GetNumberingType();
107 {
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
111 bStartValue = true;
112 if( rInfo.GetDepth() > 1 )
113 {
115 rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex() + 1;
116 do
117 {
118 const SwNode* pNd = rWrt.m_pDoc->GetNodes()[nPos];
119 if( pNd->IsTextNode() )
120 {
121 const SwTextNode *pTextNd = pNd->GetTextNode();
122 if( !pTextNd->GetNumRule() )
123 {
124 // node isn't numbered => check completed
125 break;
126 }
127
128 OSL_ENSURE(! pTextNd->IsOutline(),
129 "outline not expected");
130
131 if( pTextNd->GetActualListLevel() + 1 <
132 rInfo.GetDepth() )
133 {
134 if (rPrevInfo.GetDepth() == 0)
135 // previous node had no numbering => write start value
136 bStartValue = true;
137 else
138 // node is numbered, but level is lower
139 bStartValue = false;
140 // => check completed
141 break;
142 }
143 nPos++;
144 }
145 else if( pNd->IsTableNode() )
146 {
147 // skip table
148 nPos = pNd->EndOfSectionIndex() + 1;
149 }
150 else
151 {
152 // end node or sections start node -> check
153 // completed
154 break;
155 }
156 }
157 while( true );
158 }
159 }
160 }
161 else
162 {
163 rWrt.m_aNumRuleNames.insert( aName );
164 }
165 }
166
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;
171
172 for( sal_uInt16 i=nPrevDepth; i<rInfo.GetDepth(); i++ )
173 {
174 rWrt.OutNewLine(); // <OL>/<UL> in a new row
175
176 rWrt.m_aBulletGrfs[i].clear();
177 OString sOut = "<" + rWrt.GetNamespace();
178 if (rWrt.mbXHTML && i != nPrevDepth)
179 {
180 // for all skipped sublevels, add a li
181 sOut += OOO_STRING_SVTOOLS_HTML_li "><" + rWrt.GetNamespace();
182 }
183 const SwNumFormat& rNumFormat = rInfo.GetNumRule()->Get( i );
184 sal_Int16 eType = rNumFormat.GetNumberingType();
186 {
187 // unordered list: <UL>
189
190 // determine the type by the bullet character
191 const char *pStr = nullptr;
192 switch( rNumFormat.GetBulletChar() )
193 {
196 break;
199 break;
202 break;
203 }
204
205 if( pStr )
206 {
207 sOut += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"") + pStr + "\"";
208 }
209 }
210 else if( SVX_NUM_BITMAP == eType )
211 {
212 // Unordered list: <UL>
214 }
215 else
216 {
217 // Ordered list: <OL>
219
220 if (!rWrt.mbReqIF) // No 'type' nor 'start' attribute in ReqIF
221 {
222 // determine the type by the format
223 char cType = 0;
224 switch (eType)
225 {
228 cType = 'A';
229 break;
232 cType = 'a';
233 break;
235 cType = 'I';
236 break;
238 cType = 'i';
239 break;
240 }
241 if( cType )
242 {
243 sOut += " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" + OStringChar(cType) + "\"";
244 }
245
246 sal_uInt16 nStartVal = rNumFormat.GetStart();
247 if( bStartValue && 1 == nStartVal && i == rInfo.GetDepth()-1 )
248 {
249 if ( rWrt.m_pCurrentPam->GetPointNode().GetTextNode()->GetNum() )
250 {
251 nStartVal = static_cast< sal_uInt16 >( rWrt.m_pCurrentPam->GetPointNode()
252 .GetTextNode()->GetNumberVector()[i] );
253 }
254 else
255 {
256 OSL_FAIL( "<OutHTML_NumberBulletListStart(..) - text node has no number." );
257 }
258 }
259 if( nStartVal != 1 )
260 {
261 sOut += " " OOO_STRING_SVTOOLS_HTML_O_start "=\"" + OString::number(static_cast<sal_Int32>(nStartVal)) + "\"";
262 }
263 }
264 }
265
266 rWrt.Strm().WriteOString(sOut);
267
268 if (eType == SVX_NUM_BITMAP)
269 OutHTML_BulletImage(rWrt, nullptr, rNumFormat.GetBrush(), rWrt.m_aBulletGrfs[i]);
270
271 if( rWrt.m_bCfgOutStyles )
272 OutCSS1_NumberBulletListStyleOpt( rWrt, *rInfo.GetNumRule(), static_cast<sal_uInt8>(i) );
273
274 rWrt.Strm().WriteChar( '>' );
275
276 rWrt.IncIndentLevel(); // indent content of <OL>
277 }
278
279 return rWrt;
280}
281
283 const SwHTMLNumRuleInfo& rNextInfo )
284{
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();
289
290 // XHTML </li> for the list item content, if there is an open <li>.
291 if (bListEnd || (!bNextIsSubitem && rNextInfo.IsNumbered()))
292 {
294 rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li),
295 false);
296 }
297
298 if (!bListEnd)
299 {
300 return rWrt;
301 }
302
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;
307
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-- )
310 {
311 rWrt.DecIndentLevel(); // indent content of <OL>
312 if( rWrt.m_bLFPossible )
313 rWrt.OutNewLine(); // </OL>/</UL> in a new line
314
315 // a list is started or ended:
316 sal_Int16 eType = rInfo.GetNumRule()->Get( i-1 ).GetNumberingType();
317 OString aTag;
320 else
322 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false );
323 if (rWrt.mbXHTML && (i != nNextDepth + 1 || (i != 1 && rNextInfo.IsNumbered())))
324 {
325 // for all skipped sublevels, close a li
327 rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li),
328 /*bOn=*/false);
329 }
330 rWrt.m_bLFPossible = true;
331 }
332
333 return rWrt;
334}
335
336/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvStream & WriteOString(std::string_view rStr)
SvStream & WriteChar(char nChar)
const SvxBrushItem * GetBrush() const
sal_UCS4 GetBulletChar() const
sal_uInt16 GetStart() const
SvxNumType GetNumberingType() const
SwNodes & GetNodes()
Definition: doc.hxx:422
bool IsNumbered() const
Definition: htmlnum.hxx:80
sal_uInt16 GetDepth() const
Definition: htmlnum.hxx:73
bool IsRestart(const SwHTMLNumRuleInfo &rPrev) const
Definition: htmlnum.cxx:48
SwNumRule * GetNumRule()
Definition: htmlnum.hxx:69
bool mbXHTML
If XHTML markup should be written instead of HTML.
Definition: wrthtml.hxx:410
OUString m_aBulletGrfs[MAXLEVEL]
Definition: wrthtml.hxx:311
void IncIndentLevel()
Definition: wrthtml.hxx:525
bool m_bLFPossible
Definition: wrthtml.hxx:395
bool m_bCfgOutStyles
Definition: wrthtml.hxx:355
void DecIndentLevel()
Definition: wrthtml.hxx:529
OString GetNamespace() const
Determines the prefix string needed to respect the requested namespace alias.
Definition: wrthtml.cxx:1586
void FillNextNumInfo()
bool mbReqIF
If the ReqIF subset of XHTML should be written.
Definition: wrthtml.hxx:414
SwHTMLNumRuleInfo & GetNumInfo()
Definition: wrthtml.hxx:556
void OutNewLine(bool bCheck=false)
Definition: wrthtml.cxx:1537
std::set< OUString > m_aNumRuleNames
Definition: wrthtml.hxx:299
HtmlTokenId m_nLastParaToken
Definition: wrthtml.hxx:326
void ClearNextNumInfo()
std::unique_ptr< SwHTMLNumRuleInfo > m_pNextNumRuleInfo
Definition: wrthtml.hxx:276
void SetNextNumInfo(std::unique_ptr< SwHTMLNumRuleInfo > pNxt)
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
bool IsTableNode() const
Definition: node.hxx:191
bool IsTextNode() const
Definition: node.hxx:190
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:87
const OUString & GetName() const
Definition: numrule.hxx:224
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
bool IsOutline() const
Returns if this text node is an outline.
Definition: ndtxt.cxx:4138
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2921
int GetActualListLevel(SwListRedlineType eRedline=SwListRedlineType::SHOW) const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4248
SvStream & Strm()
Definition: writer.cxx:193
SwDoc * m_pDoc
Definition: shellio.hxx:407
std::shared_ptr< SwUnoCursor > m_pCurrentPam
Definition: shellio.hxx:409
SwHTMLWriter & OutCSS1_NumberBulletListStyleOpt(SwHTMLWriter &rWrt, const SwNumRule &rNumRule, sal_uInt8 nLevel)
Definition: css1atr.cxx:1808
DocumentType eType
SwHTMLWriter & OutHTML_BulletImage(SwHTMLWriter &rWrt, const char *pTag, const SvxBrushItem *pBrush, const OUString &rGraphicURL)
#define OOO_STRING_SVTOOLS_HTML_orderlist
#define OOO_STRING_SVTOOLS_HTML_ULTYPE_disc
#define OOO_STRING_SVTOOLS_HTML_ULTYPE_square
#define OOO_STRING_SVTOOLS_HTML_O_type
#define OOO_STRING_SVTOOLS_HTML_ULTYPE_circle
#define OOO_STRING_SVTOOLS_HTML_O_start
#define OOO_STRING_SVTOOLS_HTML_unorderlist
#define OOO_STRING_SVTOOLS_HTML_li
#define HTML_BULLETCHAR_SQUARE
Definition: htmlnum.hxx:34
#define HTML_BULLETCHAR_CIRCLE
Definition: htmlnum.hxx:33
#define HTML_BULLETCHAR_DISC
Definition: htmlnum.hxx:32
SwHTMLWriter & OutHTML_NumberBulletListEnd(SwHTMLWriter &rWrt, const SwHTMLNumRuleInfo &rNextInfo)
SwHTMLWriter & OutHTML_NumberBulletListStart(SwHTMLWriter &rWrt, const SwHTMLNumRuleInfo &rInfo)
OUString aName
sal_uInt16 nPos
SwNumRule * GetNumRule(SwTextFormatColl &rTextFormatColl)
determines the list style, which directly set at the given paragraph style
Definition: fmtcol.cxx:74
int i
static SVT_DLLPUBLIC SvStream & Out_AsciiTag(SvStream &, std::string_view rStr, bool bOn=true)
SVX_NUM_CHARS_LOWER_LETTER_N
SVX_NUM_CHARS_LOWER_LETTER
SVX_NUM_CHARS_UPPER_LETTER
SVX_NUM_ROMAN_UPPER
SVX_NUM_ROMAN_LOWER
SVX_NUM_CHARS_UPPER_LETTER_N
SVX_NUM_BITMAP
SVX_NUM_CHAR_SPECIAL
unsigned char sal_uInt8