Files
core/HtmlFile2/Table.cpp
2026-04-16 17:15:01 +03:00

384 lines
7.7 KiB
C++

#include "Table.h"
#include "Common.h"
#include "src/CCompiledStyle.h"
namespace HTML
{
ITableElementCell::ITableElementCell(size_t unColspan)
: m_unColspan(unColspan)
{}
void ITableElementCell::SetColspan(size_t unColspan)
{
if (0 < unColspan)
m_unColspan = unColspan;
}
size_t ITableElementCell::GetColspan() const
{
return m_unColspan;
}
CTableElementCell::CTableElementCell(bool bIsFilling, size_t unColspan)
: ITableElementCell(unColspan), m_eType{(bIsFilling) ? ETableElement::FillingCell : ETableElement::Cell}
{}
CTableElementCell::~CTableElementCell()
{}
ETableElement CTableElementCell::GetType() const
{
return m_eType;
}
void CTableElementCell::IsFlatTable()
{
m_eType = ETableElement::FlatTable;
}
CTableElementCell* CTableElementCell::CreateCell(const size_t& unColspan)
{
return new CTableElementCell(false, unColspan);
}
CTableElementCell* CTableElementCell::CreateFillingCell(const size_t& unColspan)
{
return new CTableElementCell(true, unColspan);
}
CTableMatrix::CTableMatrix()
{}
CTableMatrix::~CTableMatrix()
{
for (Row& oRow : m_arCells)
{
for (ITableElementCell* pCell : oRow)
{
if (nullptr != pCell)
delete pCell;
}
}
}
bool CTableMatrix::Empty() const
{
return m_arCells.empty();
}
void CTableMatrix::Clear()
{
m_arCells.clear();
}
bool CTableMatrix::SetCell(size_t unRowIndex, size_t unColumnIndex, ITableElementCell* pCell, bool bAutoClean)
{
if (nullptr == pCell)
return false;
if (m_arCells.size() <= unRowIndex)
{
if (!m_arCells.empty())
{
const size_t unMaxColumn{m_arCells.back().size()};
const size_t unOldSize{m_arCells.size()};
m_arCells.resize(unRowIndex + 1);
for (size_t unIndex = unOldSize; unIndex < m_arCells.size(); ++unIndex)
m_arCells[unIndex].resize(unMaxColumn);
}
else
m_arCells.resize(unRowIndex + 1);
}
if (m_arCells[unRowIndex].size() <= unColumnIndex)
{
m_arCells[unRowIndex].resize(unColumnIndex + 1);
m_arCells[unRowIndex][unColumnIndex] = pCell;
return true;
}
if (nullptr != m_arCells[unRowIndex][unColumnIndex])
{
pCell->SetColspan(m_arCells[unRowIndex][unColumnIndex]->GetColspan());
if (bAutoClean)
delete m_arCells[unRowIndex][unColumnIndex];
}
m_arCells[unRowIndex][unColumnIndex] = pCell;
return true;
}
void CTableMatrix::NormalizeNumberColumns(size_t unNumberColumns)
{
if (m_arCells.empty())
return;
for (Row& oRow : m_arCells)
if (unNumberColumns > oRow.size())
oRow.resize(unNumberColumns);
}
bool CTableMatrix::IsFillingCell(size_t unRowIndex, size_t unColumnIndex) const
{
if (unRowIndex >= m_arCells.size())
return false;
if (unColumnIndex >= m_arCells[unRowIndex].size())
return false;
return (nullptr != m_arCells[unRowIndex][unColumnIndex]) ? ETableElement::FillingCell == m_arCells[unRowIndex][unColumnIndex]->GetType() : false;
}
bool CTableMatrix::IsNotNullCell(size_t unRowIndex, size_t unColumnIndex) const
{
if (unRowIndex >= m_arCells.size())
return false;
if (unColumnIndex >= m_arCells[unRowIndex].size())
return false;
return nullptr != m_arCells[unRowIndex][unColumnIndex];
}
size_t CTableMatrix::GetRowSize() const
{
return m_arCells.size();
}
size_t CTableMatrix::GetColumnSize() const
{
return (m_arCells.empty()) ? 0 : m_arCells.front().size();
}
Table& CTableMatrix::GetMatrixCells()
{
return m_arCells;
}
const Table& CTableMatrix::GetMatrixCells() const
{
return m_arCells;
}
const ITableElementCell* CTableMatrix::GetCell(size_t unRowIndex, size_t unColumnIndex) const
{
if (unRowIndex >= m_arCells.size())
return nullptr;
if (unColumnIndex >= m_arCells[unRowIndex].size())
return nullptr;
return m_arCells[unRowIndex][unColumnIndex];
}
ITableElementCell* CTableMatrix::GetCell(size_t unRowIndex, size_t unColumnIndex)
{
if (unRowIndex >= m_arCells.size())
return nullptr;
if (unColumnIndex >= m_arCells[unRowIndex].size())
return nullptr;
return m_arCells[unRowIndex][unColumnIndex];
}
CTableElement::CTableElement(TExternalTableData &oExternalData)
: m_pCaption(nullptr), m_oExternalData(oExternalData)
{}
CTableElement::~CTableElement()
{
Clear();
}
void CTableElement::Clear()
{
if (nullptr != m_pCaption)
{
delete m_pCaption;
m_pCaption = nullptr;
}
for (CTableColgroup* pColgroup : m_arColgroups)
if (nullptr != pColgroup)
delete pColgroup;
m_arColgroups.clear();
m_oHeader.Clear();
m_oBody.Clear();
m_oFoother.Clear();
}
bool CTableElement::Empty() const
{
return m_oHeader.Empty() && m_oBody.Empty() && m_oFoother.Empty();
}
bool CTableElement::HaveCaption() const
{
return nullptr != m_pCaption && 0 != m_pCaption->GetCurSize();
}
const NSCSS::CCompiledStyle* CTableElement::GetColStyle(size_t unColIndex) const
{
if (m_arColgroups.empty())
return nullptr;
const NSCSS::CCompiledStyle* pColStyle{nullptr};
size_t unSkipSpans{0};
for (const CTableColgroup* pColgroup : m_arColgroups)
{
pColStyle = pColgroup->GetColStyle(unColIndex - unSkipSpans);
if (nullptr != pColStyle)
return pColStyle;
unSkipSpans += pColgroup->GetTotalSpans();
}
return nullptr;
}
bool MoveToNextTableCell(XmlUtils::CXmlLiteReader& oReader, std::vector<NSCSS::CNode>& arSelectors, std::stack<int>& arDepths, TExternalTableData::FuncGetSubClass& GetSubClass)
{
while (!arDepths.empty() && !oReader.ReadNextSiblingNode2(arDepths.top()))
{
arDepths.pop();
arSelectors.pop_back();
}
if (arDepths.empty())
return false;
do
{
const std::wstring wsName = oReader.GetName();
if (L"#text" == wsName || L"colgroup" == wsName || L"caption" == wsName)
return MoveToNextTableCell(oReader, arSelectors, arDepths, GetSubClass);
GetSubClass(oReader, arSelectors);
if (L"td" == wsName || L"th" == wsName)
return true;
else if (L"table" == wsName)
return false;
arDepths.push(oReader.GetDepth());
return MoveToNextTableCell(oReader, arSelectors, arDepths, GetSubClass);
}while(oReader.ReadNextSiblingNode2(arDepths.top()));
return false;
}
CTableContainer::CTableContainer()
: ITableElementCell(1)
{}
CTableContainer::~CTableContainer()
{
for (const CTableElement* pTable : m_arTables)
if (nullptr != pTable)
delete pTable;
}
ETableElement CTableContainer::GetType() const
{
return ETableElement::TableContainer;
}
void CTableContainer::AddTable(CTableElement* pTable)
{
if (nullptr != pTable)
m_arTables.push_back(pTable);
}
const std::vector<CTableElement*>& CTableContainer::GetTables() const
{
return m_arTables;
}
CTableCol::CTableCol(NSCSS::CNode& oTableColNode)
: m_pStyle(oTableColNode.m_pCompiledStyle)
{
oTableColNode.m_pCompiledStyle = nullptr;
m_unSpan = NSStringFinder::ToInt(oTableColNode.GetAttributeValue(L"span"), 1);
}
CTableCol::~CTableCol()
{
if (nullptr != m_pStyle)
delete m_pStyle;
}
UINT CTableCol::GetSpan() const
{
return m_unSpan;
}
const NSCSS::CCompiledStyle* CTableCol::GetStyle() const
{
return m_pStyle;
}
CTableColgroup::CTableColgroup(const NSCSS::CNode& oTableColgroupNode)
: m_unTotalSpans(0)
{
m_unWidth = NSStringFinder::ToInt(oTableColgroupNode.GetAttributeValue(L"width"), 0);
}
CTableColgroup::~CTableColgroup()
{
for (CTableCol* pCol : m_arCols)
if (nullptr != pCol)
delete pCol;
}
bool CTableColgroup::Empty() const
{
return m_arCols.empty();
}
void CTableColgroup::AddCol(CTableCol* pCol)
{
if (nullptr == pCol)
return;
m_arCols.push_back(pCol);
m_unTotalSpans += pCol->GetSpan();
}
UINT CTableColgroup::GetTotalSpans() const
{
return m_unTotalSpans;
}
const std::vector<CTableCol*>& CTableColgroup::GetCols() const
{
return m_arCols;
}
const NSCSS::CCompiledStyle* CTableColgroup::GetColStyle(size_t unIndex) const
{
if (m_arCols.empty())
return nullptr;
size_t unCurrentIndex{0};
for (const CTableCol* pCol : m_arCols)
{
if (unCurrentIndex <= unIndex && (unCurrentIndex + pCol->GetSpan()) > unIndex)
return pCol->GetStyle();
unCurrentIndex += pCol->GetSpan();
}
return nullptr;
}
}