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 <com/sun/star/style/NumberingType.hpp>
21 #include <hintids.hxx>
22 #include <svtools/htmltokn.h>
23 #include <svtools/htmlkywd.hxx>
24 #include <svtools/htmlout.hxx>
25 #include <svl/urihelper.hxx>
26 #include <editeng/brushitem.hxx>
27 #include <editeng/lrspitem.hxx>
28 #include <vcl/svapp.hxx>
29 #include <vcl/wrkwin.hxx>
30 #include <numrule.hxx>
31 #include <doc.hxx>
32 #include <docary.hxx>
33 #include <poolfmt.hxx>
34 #include <ndtxt.hxx>
35 #include <paratr.hxx>
36 #include <pam.hxx>
37 
38 #include "htmlnum.hxx"
39 #include "wrthtml.hxx"
40 
41 #include <SwNodeNum.hxx>
42 #include <rtl/strbuf.hxx>
43 #include <osl/diagnose.h>
44 
45 using namespace css;
46 
47 
49 {
50  m_pNextNumRuleInfo = nullptr;
51 
52  sal_uLong nPos = m_pCurrentPam->GetPoint()->nNode.GetIndex() + 1;
53 
54  bool bTable = false;
55  do
56  {
57  const SwNode* pNd = m_pDoc->GetNodes()[nPos];
58  if( pNd->IsTextNode() )
59  {
60  m_pNextNumRuleInfo.reset( new SwHTMLNumRuleInfo( *pNd->GetTextNode() ) );
61 
62  // Before a table we keep the old level if the same numbering is
63  // continued after the table and no new numbering is started.
64  // The table will get the indentation that corresponds to its
65  // numbering level during import.
66  if( bTable &&
67  m_pNextNumRuleInfo->GetNumRule()==GetNumInfo().GetNumRule() &&
68  !m_pNextNumRuleInfo->IsRestart() )
69  {
70  m_pNextNumRuleInfo->SetDepth( GetNumInfo().GetDepth() );
71  }
72  }
73  else if( pNd->IsTableNode() )
74  {
75  // A table is skipped so the node after table is viewed.
76  nPos = pNd->EndOfSectionIndex() + 1;
77  bTable = true;
78  }
79  else
80  {
81  // In all other case the numbering is over.
82  m_pNextNumRuleInfo.reset(new SwHTMLNumRuleInfo);
83  }
84  }
85  while( !m_pNextNumRuleInfo );
86 }
87 
89 {
90  m_pNextNumRuleInfo.reset();
91 }
92 
93 void SwHTMLWriter::SetNextNumInfo( std::unique_ptr<SwHTMLNumRuleInfo> pNxt )
94 {
95  m_pNextNumRuleInfo = std::move(pNxt);
96 }
97 
99  const SwHTMLNumRuleInfo& rInfo )
100 {
101  SwHTMLNumRuleInfo& rPrevInfo = rWrt.GetNumInfo();
102  bool bSameRule = rPrevInfo.GetNumRule() == rInfo.GetNumRule();
103  if( bSameRule && rPrevInfo.GetDepth() >= rInfo.GetDepth() &&
104  !rInfo.IsRestart() )
105  {
106  return rWrt;
107  }
108 
109  bool bStartValue = false;
110  if( !bSameRule && rInfo.GetDepth() )
111  {
112  OUString aName( rInfo.GetNumRule()->GetName() );
113  if( 0 != rWrt.m_aNumRuleNames.count( aName ) )
114  {
115  // The rule has been applied before
116  sal_Int16 eType = rInfo.GetNumRule()
117  ->Get( rInfo.GetDepth()-1 ).GetNumberingType();
118  if( SVX_NUM_CHAR_SPECIAL != eType && SVX_NUM_BITMAP != eType )
119  {
120  // If it's a numbering rule, the current number should be
121  // exported as start value, but only if there are no nodes
122  // within the numbering that have a lower level
123  bStartValue = true;
124  if( rInfo.GetDepth() > 1 )
125  {
126  sal_uLong nPos =
127  rWrt.m_pCurrentPam->GetPoint()->nNode.GetIndex() + 1;
128  do
129  {
130  const SwNode* pNd = rWrt.m_pDoc->GetNodes()[nPos];
131  if( pNd->IsTextNode() )
132  {
133  const SwTextNode *pTextNd = pNd->GetTextNode();
134  if( !pTextNd->GetNumRule() )
135  {
136  // node isn't numbered => check completed
137  break;
138  }
139 
140  OSL_ENSURE(! pTextNd->IsOutline(),
141  "outline not expected");
142 
143  if( pTextNd->GetActualListLevel() + 1 <
144  rInfo.GetDepth() )
145  {
146  if (rPrevInfo.GetDepth() == 0)
147  // previous node had no numbering => write start value
148  bStartValue = true;
149  else
150  // node is numbered, but level is lower
151  bStartValue = false;
152  // => check completed
153  break;
154  }
155  nPos++;
156  }
157  else if( pNd->IsTableNode() )
158  {
159  // skip table
160  nPos = pNd->EndOfSectionIndex() + 1;
161  }
162  else
163  {
164  // end node or sections start node -> check
165  // completed
166  break;
167  }
168  }
169  while( true );
170  }
171  }
172  }
173  else
174  {
175  rWrt.m_aNumRuleNames.insert( aName );
176  }
177  }
178 
179  OSL_ENSURE( rWrt.m_nLastParaToken == HtmlTokenId::NONE,
180  "<PRE> was not closed before <OL>." );
181  sal_uInt16 nPrevDepth =
182  (bSameRule && !rInfo.IsRestart()) ? rPrevInfo.GetDepth() : 0;
183 
184  for( sal_uInt16 i=nPrevDepth; i<rInfo.GetDepth(); i++ )
185  {
186  rWrt.OutNewLine(); // <OL>/<UL> in a new row
187 
188  rWrt.m_aBulletGrfs[i].clear();
189  OString sOut = "<";
190  sOut += rWrt.GetNamespace();
191  const SwNumFormat& rNumFormat = rInfo.GetNumRule()->Get( i );
192  sal_Int16 eType = rNumFormat.GetNumberingType();
193  if( SVX_NUM_CHAR_SPECIAL == eType )
194  {
195  // ordered list: <OL>
196  sOut += OString(OOO_STRING_SVTOOLS_HTML_unorderlist);
197 
198  // determine the type by the bullet character
199  const sal_Char *pStr = nullptr;
200  switch( rNumFormat.GetBulletChar() )
201  {
204  break;
207  break;
210  break;
211  }
212 
213  if( pStr )
214  {
215  sOut += " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" + OString(pStr) + "\"";
216  }
217  }
218  else if( SVX_NUM_BITMAP == eType )
219  {
220  // Unordered list: <UL>
221  sOut += OString(OOO_STRING_SVTOOLS_HTML_unorderlist);
222  rWrt.Strm().WriteOString( sOut );
223  OutHTML_BulletImage( rWrt,
224  nullptr,
225  rNumFormat.GetBrush(),
226  rWrt.m_aBulletGrfs[i]);
227  }
228  else
229  {
230  // Ordered list: <OL>
231  sOut += OString(OOO_STRING_SVTOOLS_HTML_orderlist);
232 
233  // determine the type by the format
234  sal_Char cType = 0;
235  switch( eType )
236  {
239  cType = 'A';
240  break;
243  cType = 'a';
244  break;
245  case SVX_NUM_ROMAN_UPPER:
246  cType = 'I';
247  break;
248  case SVX_NUM_ROMAN_LOWER:
249  cType = 'i';
250  break;
251  }
252  if( cType )
253  {
254  sOut += " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" + OString(cType) + "\"";
255  }
256 
257  sal_uInt16 nStartVal = rNumFormat.GetStart();
258  if( bStartValue && 1 == nStartVal && i == rInfo.GetDepth()-1 )
259  {
260  if ( rWrt.m_pCurrentPam->GetNode().GetTextNode()->GetNum() )
261  {
262  nStartVal = static_cast< sal_uInt16 >( rWrt.m_pCurrentPam->GetNode()
263  .GetTextNode()->GetNumberVector()[i] );
264  }
265  else
266  {
267  OSL_FAIL( "<OutHTML_NumBulListStart(..) - text node has no number." );
268  }
269  }
270  if( nStartVal != 1 )
271  {
272  sOut += " " OOO_STRING_SVTOOLS_HTML_O_start "=\"" + OString::number(static_cast<sal_Int32>(nStartVal)) + "\"";
273  }
274  }
275 
276  if (!sOut.isEmpty() && SVX_NUM_BITMAP != eType) // second condition to avoid adding extra ul, already done before.
277  rWrt.Strm().WriteOString( sOut );
278 
279  if( rWrt.m_bCfgOutStyles )
280  OutCSS1_NumBulListStyleOpt( rWrt, *rInfo.GetNumRule(), static_cast<sal_uInt8>(i) );
281 
282  rWrt.Strm().WriteChar( '>' );
283 
284  rWrt.IncIndentLevel(); // indent content of <OL>
285  }
286 
287  return rWrt;
288 }
289 
291  const SwHTMLNumRuleInfo& rNextInfo )
292 {
293  SwHTMLNumRuleInfo& rInfo = rWrt.GetNumInfo();
294  bool bSameRule = rNextInfo.GetNumRule() == rInfo.GetNumRule();
295  if( bSameRule && rNextInfo.GetDepth() >= rInfo.GetDepth() &&
296  !rNextInfo.IsRestart() )
297  {
298  return rWrt;
299  }
300 
301  OSL_ENSURE( rWrt.m_nLastParaToken == HtmlTokenId::NONE,
302  "<PRE> was not closed before </OL>." );
303  sal_uInt16 nNextDepth =
304  (bSameRule && !rNextInfo.IsRestart()) ? rNextInfo.GetDepth() : 0;
305 
306  // MIB 23.7.97: We must loop backwards, to get the right order of </OL>/</UL>
307  for( sal_uInt16 i=rInfo.GetDepth(); i>nNextDepth; i-- )
308  {
309  rWrt.DecIndentLevel(); // indent content of <OL>
310  if( rWrt.m_bLFPossible )
311  rWrt.OutNewLine(); // </OL>/</UL> in a new line
312 
313  // a list is started or ended:
314  sal_Int16 eType = rInfo.GetNumRule()->Get( i-1 ).GetNumberingType();
315  OString aTag;
316  if( SVX_NUM_CHAR_SPECIAL == eType || SVX_NUM_BITMAP == eType)
318  else
320  HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), rWrt.GetNamespace() + aTag, false );
321  rWrt.m_bLFPossible = true;
322  }
323 
324  return rWrt;
325 }
326 
327 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SvxNumType GetNumberingType() const
SVX_NUM_CHARS_UPPER_LETTER_N
SwHTMLNumRuleInfo & GetNumInfo()
Definition: wrthtml.hxx:525
void FillNextNumInfo()
bool IsOutline() const
Returns if this text node is an outline.
Definition: ndtxt.cxx:4001
#define OOO_STRING_SVTOOLS_HTML_O_start
const SvxBrushItem * GetBrush() const
sal_uIntPtr sal_uLong
SVX_NUM_CHARS_UPPER_LETTER
bool IsRestart() const
Definition: htmlnum.hxx:78
#define OOO_STRING_SVTOOLS_HTML_unorderlist
void DecIndentLevel()
Definition: wrthtml.hxx:498
const OUString & GetName() const
Definition: numrule.hxx:222
SvStream & WriteOString(const OString &rStr)
int GetActualListLevel() const
Returns the actual list level of this text node, when it is a list item.
Definition: ndtxt.cxx:4096
Writer & OutHTML_NumBulListStart(SwHTMLWriter &rWrt, const SwHTMLNumRuleInfo &rInfo)
void OutNewLine(bool bCheck=false)
Definition: wrthtml.cxx:1420
bool m_bLFPossible
Definition: wrthtml.hxx:379
static SVT_DLLPUBLIC SvStream & Out_AsciiTag(SvStream &, const OString &rStr, bool bOn=true)
Writer & OutHTML_NumBulListEnd(SwHTMLWriter &rWrt, const SwHTMLNumRuleInfo &rNextInfo)
std::set< OUString > m_aNumRuleNames
Definition: wrthtml.hxx:281
char sal_Char
SVX_NUM_ROMAN_UPPER
SVX_NUM_ROMAN_LOWER
#define HTML_BULLETCHAR_DISC
Definition: htmlnum.hxx:32
SVX_NUM_BITMAP
SVX_NUM_CHAR_SPECIAL
SVX_NUM_CHARS_LOWER_LETTER
sal_uInt16 GetDepth() const
Definition: htmlnum.hxx:73
#define OOO_STRING_SVTOOLS_HTML_ULTYPE_disc
int i
void SetNextNumInfo(std::unique_ptr< SwHTMLNumRuleInfo > pNxt)
#define OOO_STRING_SVTOOLS_HTML_ULTYPE_square
SwNumRule * GetNumRule(bool bInParent=true) const
Returns numbering rule of this text node.
Definition: ndtxt.cxx:2813
OUString m_aBulletGrfs[MAXLEVEL]
Definition: wrthtml.hxx:294
SwNodes & GetNodes()
Node is in which nodes-array/doc?
Definition: node.hxx:693
#define HTML_BULLETCHAR_CIRCLE
Definition: htmlnum.hxx:33
sal_uInt16 GetStart() const
DocumentType const eType
SVX_NUM_CHARS_LOWER_LETTER_N
void ClearNextNumInfo()
const SwNumFormat & Get(sal_uInt16 i) const
Definition: number.cxx:83
sal_uLong EndOfSectionIndex() const
Definition: node.hxx:677
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
unsigned char sal_uInt8
void IncIndentLevel()
Definition: wrthtml.hxx:494
SwNodes & GetNodes()
Definition: doc.hxx:402
Writer & OutCSS1_NumBulListStyleOpt(Writer &rWrt, const SwNumRule &rNumRule, sal_uInt8 nLevel)
Definition: css1atr.cxx:1853
Writer & OutHTML_BulletImage(Writer &rWrt, const sal_Char *pTag, const SvxBrushItem *pBrush, const OUString &rGraphicURL)
OString GetNamespace() const
Determines the prefix string needed to respect the requested namespace alias.
Definition: wrthtml.cxx:1469
SvStream & WriteChar(char nChar)
sal_Unicode GetBulletChar() const
#define OOO_STRING_SVTOOLS_HTML_orderlist
std::shared_ptr< SwUnoCursor > m_pCurrentPam
Definition: shellio.hxx:405
OString const aName
SvStream & Strm()
Definition: writer.cxx:218
#define OOO_STRING_SVTOOLS_HTML_O_type
bool IsTableNode() const
Definition: node.hxx:640
bool m_bCfgOutStyles
Definition: wrthtml.hxx:339
#define OOO_STRING_SVTOOLS_HTML_ULTYPE_circle
sal_Int32 nPos
#define HTML_BULLETCHAR_SQUARE
Definition: htmlnum.hxx:34
bool IsTextNode() const
Definition: node.hxx:636
SwNumRule * GetNumRule()
Definition: htmlnum.hxx:69
SwDoc * m_pDoc
Definition: shellio.hxx:403
HtmlTokenId m_nLastParaToken
Definition: wrthtml.hxx:309
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:843
Base class of the Writer document model elements.
Definition: node.hxx:79