/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <svtools/htmltokn.h>
#include <svtools/htmlkywd.hxx>
#include <svtools/htmlout.hxx>
#include <numrule.hxx>
#include <doc.hxx>
#include <ndtxt.hxx>
#include <pam.hxx>
#include "htmlnum.hxx"
#include "wrthtml.hxx"
#include <osl/diagnose.h>
using namespace css;
void SwHTMLWriter::FillNextNumInfo()
{
m_pNextNumRuleInfo = nullptr;
SwNodeOffset nPos = m_pCurrentPam->GetPoint()->GetNodeIndex() + 1;
bool bTable = false;
do
{
const SwNode* pNd = m_pDoc->GetNodes()[nPos];
if( pNd->IsTextNode() )
{
m_pNextNumRuleInfo.reset( new SwHTMLNumRuleInfo( *pNd->GetTextNode() ) );
// Before a table we keep the old level if the same numbering is
// continued after the table and no new numbering is started.
// The table will get the indentation that corresponds to its
// numbering level during import.
if( bTable &&
m_pNextNumRuleInfo->GetNumRule()==GetNumInfo().GetNumRule() &&
!m_pNextNumRuleInfo->IsRestart(GetNumInfo()) )
{
m_pNextNumRuleInfo->SetDepth( GetNumInfo().GetDepth() );
}
}
else if( pNd->IsTableNode() )
{
// A table is skipped so the node after table is viewed.
nPos = pNd->EndOfSectionIndex() + 1;
bTable = true;
}
else
{
// In all other case the numbering is over.
m_pNextNumRuleInfo.reset(new SwHTMLNumRuleInfo);
}
}
while( !m_pNextNumRuleInfo );
}
void SwHTMLWriter::ClearNextNumInfo()
{
m_pNextNumRuleInfo.reset();
}
void SwHTMLWriter::SetNextNumInfo( std::unique_ptr<SwHTMLNumRuleInfo> pNxt )
{
m_pNextNumRuleInfo = std::move(pNxt);
}
SwHTMLWriter& OutHTML_NumberBulletListStart( SwHTMLWriter& rWrt,
const SwHTMLNumRuleInfo& rInfo )
{
SwHTMLNumRuleInfo& rPrevInfo = rWrt.GetNumInfo();
bool bSameRule = rPrevInfo.GetNumRule() == rInfo.GetNumRule();
if( bSameRule && rPrevInfo.GetDepth() >= rInfo.GetDepth() &&
!rInfo.IsRestart(rPrevInfo) )
{
return rWrt;
}
bool bStartValue = false;
if( !bSameRule && rInfo.GetDepth() )
{
OUString aName( rInfo.GetNumRule()->GetName() );
if( 0 != rWrt.m_aNumRuleNames.count( aName ) )
{
// The rule has been applied before
sal_Int16 eType = rInfo.GetNumRule()
->Get( rInfo.GetDepth()-1 ).GetNumberingType();
if( SVX_NUM_CHAR_SPECIAL != eType && SVX_NUM_BITMAP != eType )
{
// If it's a numbering rule, the current number should be
// exported as start value, but only if there are no nodes
// within the numbering that have a lower level
bStartValue = true;
if( rInfo.GetDepth() > 1 )
{
SwNodeOffset nPos =
rWrt.m_pCurrentPam->GetPoint()->GetNodeIndex() + 1;
do
{
const SwNode* pNd = rWrt.m_pDoc->GetNodes()[nPos];
if( pNd->IsTextNode() )
{
const SwTextNode *pTextNd = pNd->GetTextNode();
if( !pTextNd->GetNumRule() )
{
// node isn't numbered => check completed
break;
}
OSL_ENSURE(! pTextNd->IsOutline(),
"outline not expected");
if( pTextNd->GetActualListLevel() + 1 <
rInfo.GetDepth() )
{
if (rPrevInfo.GetDepth() == 0)
// previous node had no numbering => write start value
bStartValue = true;
else
// node is numbered, but level is lower
bStartValue = false;
// => check completed
break;
}
nPos++;
}
else if( pNd->IsTableNode() )
{
// skip table
nPos = pNd->EndOfSectionIndex() + 1;
}
else
{
// end node or sections start node -> check
// completed
break;
}
}
while( true );
}
}
}
else
{
rWrt.m_aNumRuleNames.insert( aName );
}
}
OSL_ENSURE( rWrt.m_nLastParaToken == HtmlTokenId::NONE,
"<PRE> was not closed before <OL>." );
sal_uInt16 nPrevDepth =
(bSameRule && !rInfo.IsRestart(rPrevInfo)) ? rPrevInfo.GetDepth() : 0;
for( sal_uInt16 i=nPrevDepth; i<rInfo.GetDepth(); i++ )
{
rWrt.OutNewLine(); // <OL>/<UL> in a new row
rWrt.m_aBulletGrfs[i].clear();
OString sOut = "<" + rWrt.GetNamespace();
if (rWrt.mbXHTML && i != nPrevDepth)
{
// for all skipped sublevels, add a li
sOut += OOO_STRING_SVTOOLS_HTML_li "><" + rWrt.GetNamespace();
}
const SwNumFormat& rNumFormat = rInfo.GetNumRule()->Get( i );
sal_Int16 eType = rNumFormat.GetNumberingType();
if( SVX_NUM_CHAR_SPECIAL == eType )
{
// unordered list: <UL>
sOut += OOO_STRING_SVTOOLS_HTML_unorderlist;
// determine the type by the bullet character
const char *pStr = nullptr;
switch( rNumFormat.GetBulletChar() )
{
case HTML_BULLETCHAR_DISC:
pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_disc;
break;
case HTML_BULLETCHAR_CIRCLE:
pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_circle;
break;
case HTML_BULLETCHAR_SQUARE:
pStr = OOO_STRING_SVTOOLS_HTML_ULTYPE_square;
break;
}
if( pStr )
{
sOut += OString::Concat(" " OOO_STRING_SVTOOLS_HTML_O_type "=\"") + pStr + "\"";
}
}
else if( SVX_NUM_BITMAP == eType )
{
// Unordered list: <UL>
sOut += OOO_STRING_SVTOOLS_HTML_unorderlist;
}
else
{
// Ordered list: <OL>
sOut += OOO_STRING_SVTOOLS_HTML_orderlist;
if (!rWrt.mbReqIF) // No 'type' nor 'start' attribute in ReqIF
{
// determine the type by the format
char cType = 0;
switch (eType)
{
case SVX_NUM_CHARS_UPPER_LETTER:
case SVX_NUM_CHARS_UPPER_LETTER_N:
cType = 'A';
break;
case SVX_NUM_CHARS_LOWER_LETTER:
case SVX_NUM_CHARS_LOWER_LETTER_N:
cType = 'a';
break;
case SVX_NUM_ROMAN_UPPER:
cType = 'I';
break;
case SVX_NUM_ROMAN_LOWER:
cType = 'i';
break;
}
if( cType )
{
sOut += " " OOO_STRING_SVTOOLS_HTML_O_type "=\"" + OStringChar(cType) + "\"";
}
sal_uInt16 nStartVal = rNumFormat.GetStart();
if( bStartValue && 1 == nStartVal && i == rInfo.GetDepth()-1 )
{
if ( rWrt.m_pCurrentPam->GetPointNode().GetTextNode()->GetNum() )
{
nStartVal = static_cast< sal_uInt16 >( rWrt.m_pCurrentPam->GetPointNode()
.GetTextNode()->GetNumberVector()[i] );
}
else
{
OSL_FAIL( "<OutHTML_NumberBulletListStart(..) - text node has no number." );
}
}
if( nStartVal != 1 )
{
sOut += " " OOO_STRING_SVTOOLS_HTML_O_start "=\"" + OString::number(static_cast<sal_Int32>(nStartVal)) + "\"";
}
}
}
rWrt.Strm().WriteOString(sOut);
if (eType == SVX_NUM_BITMAP)
OutHTML_BulletImage(rWrt, nullptr, rNumFormat.GetBrush(), rWrt.m_aBulletGrfs[i]);
if( rWrt.m_bCfgOutStyles )
OutCSS1_NumberBulletListStyleOpt( rWrt, *rInfo.GetNumRule(), static_cast<sal_uInt8>(i) );
rWrt.Strm().WriteChar( '>' );
rWrt.IncIndentLevel(); // indent content of <OL>
}
return rWrt;
}
SwHTMLWriter& OutHTML_NumberBulletListEnd( SwHTMLWriter& rWrt,
const SwHTMLNumRuleInfo& rNextInfo )
{
SwHTMLNumRuleInfo& rInfo = rWrt.GetNumInfo();
bool bSameRule = rNextInfo.GetNumRule() == rInfo.GetNumRule();
bool bListEnd = !bSameRule || rNextInfo.GetDepth() < rInfo.GetDepth() || rNextInfo.IsRestart(rInfo);
bool bNextIsSubitem = !bListEnd && rNextInfo.GetDepth() > rInfo.GetDepth();
// XHTML </li> for the list item content, if there is an open <li>.
if (bListEnd || (!bNextIsSubitem && rNextInfo.IsNumbered()))
{
HTMLOutFuncs::Out_AsciiTag(
rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li),
false);
}
if (!bListEnd)
{
return rWrt;
}
OSL_ENSURE( rWrt.m_nLastParaToken == HtmlTokenId::NONE,
"<PRE> was not closed before </OL>." );
sal_uInt16 nNextDepth =
(bSameRule && !rNextInfo.IsRestart(rInfo)) ? rNextInfo.GetDepth() : 0;
// MIB 23.7.97: We must loop backwards, to get the right order of </OL>/</UL>
for( sal_uInt16 i=rInfo.GetDepth(); i>nNextDepth; i-- )
{
rWrt.DecIndentLevel(); // indent content of <OL>
if (rWrt.IsLFPossible())
rWrt.OutNewLine(); // </OL>/</UL> in a new line
// a list is started or ended:
sal_Int16 eType = rInfo.GetNumRule()->Get( i-1 ).GetNumberingType();
OString aTag;
if( SVX_NUM_CHAR_SPECIAL == eType || SVX_NUM_BITMAP == eType)
aTag = OOO_STRING_SVTOOLS_HTML_unorderlist ""_ostr;
else
aTag = OOO_STRING_SVTOOLS_HTML_orderlist ""_ostr;
HTMLOutFuncs::Out_AsciiTag( rWrt.Strm(), Concat2View(rWrt.GetNamespace() + aTag), false );
if (rWrt.mbXHTML && (i != nNextDepth + 1 || (i != 1 && rNextInfo.IsNumbered())))
{
// for all skipped sublevels, close a li
HTMLOutFuncs::Out_AsciiTag(
rWrt.Strm(), Concat2View(rWrt.GetNamespace() + OOO_STRING_SVTOOLS_HTML_li),
/*bOn=*/false);
}
rWrt.SetLFPossible(true);
}
return rWrt;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
↑ V735 Possibly an incorrect HTML. The "</ol>" closing tag was encountered, while the "</pre>" tag was expected.
↑ V1048 The 'bStartValue' variable was assigned the same value.