docthemes: Save themes def. to a file when added to ColorSets
[LibreOffice.git] / sw / source / filter / html / htmlnumwriter.cxx
blob7f09fd8ce8ccdf2ec90365fc723bf9b36dfb7e51
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/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>
28 #include "htmlnum.hxx"
29 #include "wrthtml.hxx"
31 #include <osl/diagnose.h>
33 using namespace css;
36 void SwHTMLWriter::FillNextNumInfo()
38 m_pNextNumRuleInfo = nullptr;
40 SwNodeOffset nPos = m_pCurrentPam->GetPoint()->GetNodeIndex() + 1;
42 bool bTable = false;
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.
54 if( bTable &&
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;
65 bTable = true;
67 else
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) )
94 return rWrt;
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
111 bStartValue = true;
112 if( rInfo.GetDepth() > 1 )
114 SwNodeOffset nPos =
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
125 break;
128 OSL_ENSURE(! pTextNd->IsOutline(),
129 "outline not expected");
131 if( pTextNd->GetActualListLevel() + 1 <
132 rInfo.GetDepth() )
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;
143 nPos++;
145 else if( pNd->IsTableNode() )
147 // skip table
148 nPos = pNd->EndOfSectionIndex() + 1;
150 else
152 // end node or sections start node -> check
153 // completed
154 break;
157 while( true );
161 else
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 if (!rWrt.mbReqIF) // No 'type' attribute in ReqIF
192 // determine the type by the bullet character
193 const char* pStr = nullptr;
194 switch (rNumFormat.GetBulletChar())
196 case HTML_BULLETCHAR_DISC:
197 pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_disc;
198 break;
199 case HTML_BULLETCHAR_CIRCLE:
200 pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_circle;
201 break;
202 case HTML_BULLETCHAR_SQUARE:
203 pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_square;
204 break;
207 if (pStr)
209 sOut += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"") + pStr + "\"";
213 else if( SVX_NUM_BITMAP == eType )
215 // Unordered list: <UL>
216 sOut += OOO_STRING_SVTOOLS_HTML_unorderlist;
218 else
220 // Ordered list: <OL>
221 sOut += OOO_STRING_SVTOOLS_HTML_orderlist;
223 if (!rWrt.mbReqIF) // No 'type' nor 'start' attribute in ReqIF
225 // determine the type by the format
226 char cType = 0;
227 switch (eType)
229 case SVX_NUM_CHARS_UPPER_LETTER:
230 case SVX_NUM_CHARS_UPPER_LETTER_N:
231 cType = 'A';
232 break;
233 case SVX_NUM_CHARS_LOWER_LETTER:
234 case SVX_NUM_CHARS_LOWER_LETTER_N:
235 cType = 'a';
236 break;
237 case SVX_NUM_ROMAN_UPPER:
238 cType = 'I';
239 break;
240 case SVX_NUM_ROMAN_LOWER:
241 cType = 'i';
242 break;
244 if( cType )
246 sOut += " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" + OStringChar(cType) + "\"";
249 sal_uInt16 nStartVal = rNumFormat.GetStart();
250 if( bStartValue && 1 == nStartVal && i == rInfo.GetDepth()-1 )
252 if ( rWrt.m_pCurrentPam->GetPointNode().GetTextNode()->GetNum() )
254 nStartVal = static_cast< sal_uInt16 >( rWrt.m_pCurrentPam->GetPointNode()
255 .GetTextNode()->GetNumberVector()[i] );
257 else
259 OSL_FAIL( "<OutHTML_NumberBulletListStart(..) - text node has no number." );
262 if( nStartVal != 1 )
264 sOut += " " OOO_STRING_SVTOOLS_HTML_O_start "=\"" + OString::number(static_cast<sal_Int32>(nStartVal)) + "\"";
269 rWrt.Strm().WriteOString(sOut);
271 if (eType == SVX_NUM_BITMAP)
272 OutHTML_BulletImage(rWrt, nullptr, rNumFormat.GetBrush(), rWrt.m_aBulletGrfs[i]);
274 if( rWrt.m_bCfgOutStyles )
275 OutCSS1_NumberBulletListStyleOpt( rWrt, *rInfo.GetNumRule(), static_cast<sal_uInt8>(i) );
277 rWrt.Strm().WriteChar( '>' );
279 rWrt.IncIndentLevel(); // indent content of <OL>
282 return rWrt;
285 SwHTMLWriter& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt,
286 const SwHTMLNumRuleInfo& rNextInfo )
288 SwHTMLNumRuleInfo& rInfo = rWrt.GetNumInfo();
289 bool bSameRule = rNextInfo.GetNumRule() == rInfo.GetNumRule();
290 bool bListEnd = !bSameRule || rNextInfo.GetDepth() < rInfo.GetDepth() || rNextInfo.IsRestart(rInfo);
291 bool bNextIsSubitem = !bListEnd && rNextInfo.GetDepth() > rInfo.GetDepth();
293 // XHTML </li> for the list item content, if there is an open <li>.
294 if (bListEnd || (!bNextIsSubitem && rNextInfo.IsNumbered()))
296 HTMLOutFuncs::Out_AsciiTag(
297 rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li),
298 false);
301 if (!bListEnd)
303 return rWrt;
306 OSL_ENSURE( rWrt.m_nLastParaToken == HtmlTokenId::NONE,
307 "<PRE> was not closed before </OL>." );
308 sal_uInt16 nNextDepth =
309 (bSameRule && !rNextInfo.IsRestart(rInfo)) ? rNextInfo.GetDepth() : 0;
311 // MIB 23.7.97: We must loop backwards, to get the right order of </OL>/</UL>
312 for( sal_uInt16 i=rInfo.GetDepth(); i>nNextDepth; i-- )
314 rWrt.DecIndentLevel(); // indent content of <OL>
315 if (rWrt.IsLFPossible())
316 rWrt.OutNewLine(); // </OL>/</UL> in a new line
318 // a list is started or ended:
319 sal_Int16 eType = rInfo.GetNumRule()->Get( i-1 ).GetNumberingType();
320 OString aTag;
321 if( SVX_NUM_CHAR_SPECIAL == eType || SVX_NUM_BITMAP == eType)
322 aTag = OOO_STRING_SVTOOLS_HTML_unorderlist ""_ostr;
323 else
324 aTag = OOO_STRING_SVTOOLS_HTML_orderlist ""_ostr;
325 HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false );
326 if (rWrt.mbXHTML && (i != nNextDepth + 1 || (i != 1 && rNextInfo.IsNumbered())))
328 // for all skipped sublevels, close a li
329 HTMLOutFuncs::Out_AsciiTag(
330 rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li),
331 /*bOn=*/false);
333 rWrt.SetLFPossible(true);
336 return rWrt;
339 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */