diff --git a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
index a1e048a816..5462e9085f 100644
--- a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
+++ b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
@@ -1,6 +1,5 @@
#include "CDocumentStyle.h"
-#include
#include
#include
#include
diff --git a/HtmlFile2/HTMLReader.cpp b/HtmlFile2/HTMLReader.cpp
index 53d09c9dd4..eea0e0f94e 100644
--- a/HtmlFile2/HTMLReader.cpp
+++ b/HtmlFile2/HTMLReader.cpp
@@ -29,8 +29,6 @@ namespace HTML
#define UNKNOWN_TAG GumboTag::GUMBO_TAG_UNKNOWN
#define HtmlTag GumboTag
-#define TAGS_COUNT 32
-
const static std::map m_HTML_TAGS
{
ADD_TAG(L"a", A),
@@ -344,6 +342,8 @@ void CHTMLReader::Clear()
if (nullptr != m_pTableElement)
delete m_pTableElement;
+
+ ClearStopTags();
}
bool CHTMLReader::InitOOXMLTags(THTMLParameters* pParametrs)
@@ -382,6 +382,13 @@ bool CHTMLReader::InitOOXMLTags(THTMLParameters* pParametrs)
std::vector& arSelectors)
{ GetSubClass(oReader, arSelectors, m_oCSSCalculator); };
+ oExternalData.ReadInside = [this](XmlUtils::CXmlLiteReader& oReader,
+ std::vector& arSelectors)
+ { return ReadInside(oReader, arSelectors); };
+
+ oExternalData.AddStopTag = [this](const std::wstring& wsTag){ AddStopTag(wsTag); };
+ oExternalData.ClearStopTags = [this]{ ClearStopTags(); };
+
oExternalData.m_pWriter = pWriter;
m_pTableElement = new COOXMLTable(oExternalData);
@@ -418,11 +425,18 @@ bool CHTMLReader::InitMDTags(TMarkdownParameters* pParametrs)
oExternalData.ReadStream = [this](XmlUtils::CXmlLiteReader& oReader,
std::vector& arSelectors)
- { return ReadStream(oReader, arSelectors, true); };
+ { return ReadStream(oReader, arSelectors, true); };
oExternalData.GetSubClass = [this](XmlUtils::CXmlLiteReader& oReader,
std::vector& arSelectors)
- { GetSubClass(oReader, arSelectors, m_oCSSCalculator); };
+ { GetSubClass(oReader, arSelectors, m_oCSSCalculator); };
+
+ oExternalData.ReadInside = [this](XmlUtils::CXmlLiteReader& oReader,
+ std::vector& arSelectors)
+ { return ReadInside(oReader, arSelectors); };
+
+ oExternalData.AddStopTag = [this](const std::wstring& wsTag){ AddStopTag(wsTag); };
+ oExternalData.ClearStopTags = [this]{ ClearStopTags(); };
oExternalData.m_pWriter = pWriter;
@@ -665,6 +679,9 @@ bool CHTMLReader::ReadStream(XmlUtils::CXmlLiteReader& oReader, std::vector
-#include
-
#include "../Common/3dParty/html/css/src/CCssCalculator.h"
#include "../DesktopEditor/xml/include/xmlutils.h"
@@ -14,6 +11,8 @@
#include "Tags/HTMLTags.h"
#include "Table.h"
+#include
+
namespace HTML
{
class CHTMLReader
@@ -32,6 +31,8 @@ class CHTMLReader
CTableElement* m_pTableElement; // Table Converter
+ std::set m_arStopTags;
+
THTMLTags m_oTags;
public:
CHTMLReader();
@@ -81,6 +82,9 @@ private:
bool ReadText(XmlUtils::CXmlLiteReader& oReader, std::vector& arSelectors);
bool ReadTable(XmlUtils::CXmlLiteReader& oReader, std::vector& arSelectors);
+
+ void AddStopTag(const std::wstring& wsTag);
+ void ClearStopTags();
};
}
diff --git a/HtmlFile2/Table.cpp b/HtmlFile2/Table.cpp
index 0c0d7df8fa..0cd64f2380 100644
--- a/HtmlFile2/Table.cpp
+++ b/HtmlFile2/Table.cpp
@@ -114,9 +114,23 @@ namespace HTML
// }
// }
+ITableElementCell::ITableElementCell(size_t unColspan)
+ : m_unColspan(unColspan)
+{}
-CTableElementCell::CTableElementCell(bool bIsFilling)
- : m_eType{(bIsFilling) ? ETableElement::FillingCell : ETableElement::Cell}
+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()
@@ -132,6 +146,16 @@ 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()
{}
@@ -157,7 +181,7 @@ void CTableMatrix::Clear()
m_arCells.clear();
}
-bool CTableMatrix::SetCell(size_t unRowIndex, size_t unColumnIndex, ITableElementCell* pCell)
+bool CTableMatrix::SetCell(size_t unRowIndex, size_t unColumnIndex, ITableElementCell* pCell, bool bAutoClean)
{
if (nullptr == pCell)
return false;
@@ -185,7 +209,12 @@ bool CTableMatrix::SetCell(size_t unRowIndex, size_t unColumnIndex, ITableElemen
}
if (nullptr != m_arCells[unRowIndex][unColumnIndex])
- delete m_arCells[unRowIndex][unColumnIndex];
+ {
+ pCell->SetColspan(m_arCells[unRowIndex][unColumnIndex]->GetColspan());
+
+ if (bAutoClean)
+ delete m_arCells[unRowIndex][unColumnIndex];
+ }
m_arCells[unRowIndex][unColumnIndex] = pCell;
@@ -255,6 +284,17 @@ const ITableElementCell* CTableMatrix::GetCell(size_t unRowIndex, size_t unColum
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)
{}
@@ -282,11 +322,6 @@ void CTableElement::Clear()
m_oFoother.Clear();
}
-ETableElement CTableElement::GetType() const
-{
- return ETableElement::Table;
-}
-
bool CTableElement::Empty() const
{
return m_oHeader.Empty() && m_oBody.Empty() && m_oFoother.Empty();
@@ -351,6 +386,33 @@ bool MoveToNextTableCell(XmlUtils::CXmlLiteReader& oReader, std::vector& CTableContainer::GetTables() const
+{
+ return m_arTables;
+}
+
CTableCol::CTableCol(NSCSS::CNode& oTableColNode)
: m_pStyle(oTableColNode.m_pCompiledStyle)
{
diff --git a/HtmlFile2/Table.h b/HtmlFile2/Table.h
index 96c7b9d80b..41d2908415 100644
--- a/HtmlFile2/Table.h
+++ b/HtmlFile2/Table.h
@@ -29,28 +29,46 @@ enum class ETableElement
FillingCell,
Cell,
FlatTable,
- Table
+ TableContainer
};
+// !TODO!:: At the moment, I don't really like the implementation where there is a table inside a cell,
+// or when there are multiple nested tables inside a cell
+
+// Perhaps it's worth doing it as follows:
+// ITableCell -> CTableCell (A regular cell that does not contain nested tables)
+// -> CTableCellContainer (Stores anything (like default, but has a container for storing nested tables))
+
class ITableElementCell
{
+ size_t m_unColspan;
+protected:
+ ITableElementCell(size_t unColspan);
public:
- ITableElementCell() = default;
virtual ~ITableElementCell() = default;
virtual ETableElement GetType() const = 0;
+
+ void SetColspan(size_t unColspan);
+
+ size_t GetColspan() const;
};
class CTableElementCell : public ITableElementCell
{
ETableElement m_eType;
+
+protected:
+ CTableElementCell(bool bIsFilling, size_t unColspan);
public:
- CTableElementCell(bool bIsFilling = false);
virtual ~CTableElementCell();
ETableElement GetType() const override;
void IsFlatTable();
+
+ static CTableElementCell* CreateCell(const size_t& unColspan = 1);
+ static CTableElementCell* CreateFillingCell(const size_t& unColspan = 1);
};
class ITag;
@@ -60,9 +78,15 @@ struct TExternalTableData
{
typedef std::function& arSelectors)> FuncReadStream;
typedef std::function& arSelectors)> FuncGetSubClass;
+ typedef std::function& arSelectors)> FuncReadInside;
+ typedef std::function FuncAddStopTag;
+ typedef std::function FuncClearStopTags;
- FuncReadStream ReadStream;
- FuncGetSubClass GetSubClass;
+ FuncReadStream ReadStream;
+ FuncGetSubClass GetSubClass;
+ FuncReadInside ReadInside;
+ FuncAddStopTag AddStopTag;
+ FuncClearStopTags ClearStopTags;
IWriter* m_pWriter{nullptr};
};
@@ -82,7 +106,7 @@ public:
void Clear();
- bool SetCell(size_t unRowIndex, size_t unColumnIndex, ITableElementCell* pCell);
+ bool SetCell(size_t unRowIndex, size_t unColumnIndex, ITableElementCell* pCell, bool bAutoClean = true);
void NormalizeNumberColumns(size_t unNumberColumns);
@@ -94,7 +118,9 @@ public:
const Table& GetMatrixCells() const;
Table& GetMatrixCells();
+
const ITableElementCell* GetCell(size_t unRowIndex, size_t unColumnIndex) const;
+ ITableElementCell* GetCell(size_t unRowIndex, size_t unColumnIndex);
protected:
Table m_arCells;
};
@@ -131,7 +157,7 @@ private:
UINT m_unTotalSpans;
};
-class CTableElement : public ITableElementCell
+class CTableElement
{
protected:
CTableElement(TExternalTableData &oExternalData);
@@ -140,8 +166,6 @@ public:
void Clear();
- ETableElement GetType() const override;
-
bool Empty() const;
bool HaveCaption() const;
@@ -169,6 +193,31 @@ protected:
inline bool ParseMatrix(XmlUtils::CXmlLiteReader& oReader, CTableMatrix* pMatrix, size_t& unRowIndex, size_t& unColumnIndex);
};
+class CTableContainer : public ITableElementCell
+{
+public:
+ CTableContainer();
+ virtual ~CTableContainer();
+
+ ETableElement GetType() const override;
+
+ void AddTable(CTableElement* pTable);
+ const std::vector& GetTables() const;
+private:
+ std::vector m_arTables;
+};
+
+struct TTableData
+{
+ CTableMatrix m_oHeader;
+ CTableMatrix m_oBody;
+ CTableMatrix m_oFoother;
+
+ XmlString *m_pCaption;
+
+ std::vector m_arColgroups;
+};
+
template
inline bool CTableElement::ParseTable(XmlUtils::CXmlLiteReader& oReader, T* pTable)
{
@@ -208,7 +257,21 @@ inline bool CTableElement::ParseMatrix(XmlUtils::CXmlLiteReader& oReader, CTable
if (nullptr == pNewTable)
return false;
- pMatrix->SetCell(unRowIndex - 1, unColumnIndex - 1, pNewTable);
+ ITableElementCell* pTableElement{pMatrix->GetCell(unRowIndex - 1, unColumnIndex - 1)};
+ CTableContainer *pContainer{nullptr};
+
+ if (nullptr != pTableElement && ETableElement::TableContainer == pTableElement->GetType())
+ pContainer = dynamic_cast(pTableElement);
+ else
+ {
+ pContainer = new CTableContainer();
+ pMatrix->SetCell(unRowIndex - 1, unColumnIndex - 1, pContainer);
+ }
+
+ if (nullptr == pContainer)
+ return false;
+
+ pContainer->AddTable(pNewTable);
ParseTable(oReader, pNewTable);
}
@@ -233,26 +296,26 @@ inline bool CTableElement::ParseMatrix(XmlUtils::CXmlLiteReader& oReader, CTable
while (pMatrix->IsFillingCell(unRowIndex - 1, unColumnIndex - 1))
++unColumnIndex;
- if (!pMatrix->SetCell(unRowIndex - 1, unColumnIndex - 1, new CTableElementCell()))
- return false;
+ size_t unRowspan{1}, unColspan{1};
if (oReader.MoveToFirstAttribute())
{
do
{
if (L"rowspan" == oReader.GetName())
- {
- const int nRowSpan{NSStringFinder::ToInt(oReader.GetText(), 1)};
-
- for (int nRow = 1; nRow < nRowSpan; ++nRow)
- pMatrix->SetCell(unRowIndex + nRow - 1, unColumnIndex - 1, new CTableElementCell(true));
- }
+ unRowspan = NSStringFinder::ToInt(oReader.GetText(), 1);
else if (L"colspan" == oReader.GetName())
- unColumnIndex += NSStringFinder::ToInt(oReader.GetText(), 1) - 1;
+ unColspan = NSStringFinder::ToInt(oReader.GetText(), 1);
}while (oReader.MoveToNextAttribute());
oReader.MoveToElement();
}
+ if (!pMatrix->SetCell(unRowIndex - 1, unColumnIndex - 1, CTableElementCell::CreateCell(unColspan)))
+ return false;
+
+ for (size_t unRow = 1; unRow < unRowspan; ++unRow)
+ pMatrix->SetCell(unRowIndex + unRow - 1, unColumnIndex - 1, CTableElementCell::CreateFillingCell(unColspan));
+
const int nDepth{oReader.GetDepth()};
while (oReader.ReadNextSiblingNode(nDepth))
ParseMatrix(oReader, pMatrix, unRowIndex, unColumnIndex);
diff --git a/HtmlFile2/Tags/MDTags.cpp b/HtmlFile2/Tags/MDTags.cpp
index 145b52fcb0..e6780a764d 100644
--- a/HtmlFile2/Tags/MDTags.cpp
+++ b/HtmlFile2/Tags/MDTags.cpp
@@ -15,8 +15,6 @@
#include "../../DesktopEditor/graphics/pro/Graphics.h"
#include "../../DesktopEditor/raster/BgraFrame.h"
-#include
-
namespace HTML
{
template<>
@@ -637,9 +635,9 @@ void CCodeTag::Close()
m_pWriter->OutCode();
}
-bool IsTable(const ITableElementCell* pCell)
+bool IsTableContainer(const ITableElementCell* pCell)
{
- return nullptr != pCell && ETableElement::Table == pCell->GetType();
+ return nullptr != pCell && ETableElement::TableContainer == pCell->GetType();
}
CMarkdownTable::CMarkdownTable(TExternalTableData &oExternalData)
@@ -665,10 +663,10 @@ void CMarkdownTable::Normalize()
size_t unMaxColumns{m_oBody.GetColumnSize()};
if (!m_oHeader.Empty())
- unMaxColumns = std::max(unMaxColumns, m_oHeader.GetColumnSize());
+ unMaxColumns = (std::max)(unMaxColumns, m_oHeader.GetColumnSize());
if (!m_oFoother.Empty())
- unMaxColumns = std::max(unMaxColumns, m_oFoother.GetColumnSize());
+ unMaxColumns = (std::max)(unMaxColumns, m_oFoother.GetColumnSize());
#define NORMALIZE_NUMBER_COLUMN(table_variable)\
if (!table_variable.Empty() && unMaxColumns != table_variable.GetColumnSize())\
@@ -679,7 +677,8 @@ void CMarkdownTable::Normalize()
NORMALIZE_NUMBER_COLUMN(m_oFoother);
}
-typedef std::queue, NSStringUtils::CStringBuilder*>> NestedCells;
+
+typedef std::map, NSStringUtils::CStringBuilder*> NestedCells;
inline void WriteRowStart(CMDWriter& oWriter)
{
@@ -697,21 +696,47 @@ inline void WriteCellSeparator(CMDWriter& oWriter)
oWriter.WriteOpenSpecialString(L" | ");
}
-void ReadNestedCells(XmlUtils::CXmlLiteReader& oReader, std::vector& arSelectors, TCurentTablePosition& oPosition, NestedCells& arNestedCells, const Table& oCells, CMDWriter* pWriter, const TExternalTableData& oExternalTableData)
+// TODO: Instead of handling the different parsing behavior for nested tables
+// (when a cell contains both a table and data),
+// you can set a specific parsing method in HTMLReader and replace
+// it with the desired one. As a result,
+// everything except the table will be parsed using HTMLReader,
+// while reading the nested table will be done using the newly set method.
+
+void ReadNestedCells(XmlUtils::CXmlLiteReader& oReader, std::vector& arSelectors, TCurentTablePosition& oPosition, NestedCells& arNestedCells, const Table& oCells, CMDWriter* pWriter, const TExternalTableData& oExternalTableData, NSStringUtils::CStringBuilder& oIntermediateData);
+
+void ReadNestedTable(XmlUtils::CXmlLiteReader& oReader, std::vector& arSelectors, TCurentTablePosition& oPosition, NestedCells& arNestedCells, const Table& oCells, CMDWriter* pWriter, const TExternalTableData& oExternalTableData, NSStringUtils::CStringBuilder& oIntermediateData)
+{
+ TCurentTablePosition oNestedPosition{oPosition};
+
+ oNestedPosition.m_unStartRowIndex = oPosition.m_unRowIndex;
+ oNestedPosition.m_unStartColumnIndex = oPosition.m_unColumnIndex;
+
+ std::vector arNestedSelectors{arSelectors.back()};
+
+ ReadNestedCells(oReader, arNestedSelectors, oNestedPosition, arNestedCells, oCells, pWriter, oExternalTableData, oIntermediateData);
+
+ oPosition.m_unRowIndex = oNestedPosition.m_unRowIndex;
+}
+
+void ReadNestedCells(XmlUtils::CXmlLiteReader& oReader, std::vector& arSelectors, TCurentTablePosition& oPosition, NestedCells& arNestedCells, const Table& oCells, CMDWriter* pWriter, const TExternalTableData& oExternalTableData, NSStringUtils::CStringBuilder& oIntermediateData)
{
const int nDepth{oReader.GetDepth()};
- while(oReader.ReadNextSiblingNode(nDepth))
+ while(oReader.ReadNextSiblingNode2(nDepth))
{
const std::wstring wsName = oReader.GetName();
+
oExternalTableData.GetSubClass(oReader, arSelectors);
if (L"td" == wsName || L"th" == wsName)
{
+ const ITableElementCell* pCell{oCells[oPosition.m_unRowIndex][oPosition.m_unColumnIndex]};
+
if ((oPosition.m_unRowIndex != oPosition.m_unStartRowIndex || oPosition.m_unColumnIndex != oPosition.m_unStartColumnIndex) &&
- ETableElement::FlatTable == oCells[oPosition.m_unRowIndex][oPosition.m_unColumnIndex]->GetType())
+ (nullptr != pCell && ETableElement::FlatTable == pCell->GetType()))
{
- ReadNestedCells(oReader, arSelectors, oPosition, arNestedCells, oCells, pWriter, oExternalTableData);
+ ReadNestedCells(oReader, arSelectors, oPosition, arNestedCells, oCells, pWriter, oExternalTableData, oIntermediateData);
continue;
}
@@ -719,14 +744,33 @@ void ReadNestedCells(XmlUtils::CXmlLiteReader& oReader, std::vectorWrite(oIntermediateData);
+ oIntermediateData.Clear();
+
pWriter->SetDataOutput(pCellData);
oExternalTableData.ReadStream(oReader, arSelectors);
- if (oPosition.m_unColumnIndex != oCells[oPosition.m_unRowIndex].size() - 1)
- WriteCellSeparator(*pWriter);
pWriter->RevertDataOutput();
}
- arNestedCells.push(std::make_pair(std::make_pair(oPosition.m_unRowIndex, oPosition.m_unColumnIndex), pCellData));
+ while (nullptr != oCells[oPosition.m_unRowIndex][oPosition.m_unColumnIndex])
+ {
+ if (ETableElement::FillingCell == oCells[oPosition.m_unRowIndex][oPosition.m_unColumnIndex]->GetType())
+ oPosition.m_unColumnIndex += oCells[oPosition.m_unRowIndex][oPosition.m_unColumnIndex]->GetColspan();
+ else
+ break;
+ }
+
+ arNestedCells[{oPosition.m_unRowIndex, oPosition.m_unColumnIndex}] = pCellData;
+
+ if (oReader.MoveToFirstAttribute())
+ {
+ do
+ {
+ if (L"colspan" == oReader.GetName())
+ oPosition.m_unColumnIndex += NSStringFinder::ToInt(oReader.GetText(), 1) - 1;
+ }while (oReader.MoveToNextAttribute());
+ oReader.MoveToElement();
+ }
//READ and add to nested cells
++oPosition.m_unColumnIndex;
@@ -735,25 +779,47 @@ void ReadNestedCells(XmlUtils::CXmlLiteReader& oReader, std::vector arNestedSelectors{arSelectors.back()};
-
- ReadNestedCells(oReader, arNestedSelectors, oNestedPosition, arNestedCells, oCells, pWriter, oExternalTableData);
-
- oPosition.m_unRowIndex = oNestedPosition.m_unRowIndex;
- }
+ ReadNestedTable(oReader, arSelectors, oPosition, arNestedCells, oCells, pWriter, oExternalTableData, oIntermediateData);
+ else if (L"caption" == wsName)
+ continue;
+ else if (L"tbody" == wsName || L"thead" == wsName || L"tfoot" == wsName)
+ ReadNestedCells(oReader, arSelectors, oPosition, arNestedCells, oCells, pWriter, oExternalTableData, oIntermediateData);
else
- ReadNestedCells(oReader, arSelectors, oPosition, arNestedCells, oCells, pWriter, oExternalTableData);
+ {
+ const size_t unCurrentIntermediateDataSize{oIntermediateData.GetCurSize()};
+
+ pWriter->SetDataOutput(&oIntermediateData);
+ oExternalTableData.ReadInside(oReader, arSelectors);
+ pWriter->RevertDataOutput();
+
+ if (unCurrentIntermediateDataSize != oIntermediateData.GetCurSize())
+ oIntermediateData.WriteString(L" ");
+
+ if (L"table" != oReader.GetName())
+ continue;
+
+ ReadNestedTable(oReader, arSelectors, oPosition, arNestedCells, oCells, pWriter, oExternalTableData, oIntermediateData);
+
+ pWriter->SetDataOutput(&oIntermediateData);
+
+ const int nNewDepth{oReader.GetDepth()};
+ while (oReader.ReadNextSiblingNode2(nNewDepth - 1))
+ oExternalTableData.ReadInside(oReader, arSelectors);
+
+ pWriter->RevertDataOutput();
+
+ if (0 != oIntermediateData.GetCurSize())
+ {
+ arNestedCells.rbegin()->second->WriteString(L" ");
+ arNestedCells.rbegin()->second->Write(oIntermediateData);
+ oIntermediateData.Clear();
+ }
+ }
arSelectors.pop_back();
}
@@ -771,7 +837,7 @@ bool CMarkdownTable::Convert(XmlUtils::CXmlLiteReader& oReader, const NSCSS::CNo
std::vector arTableSelectors{oTableNode};
- pWriter->WriteBreakLine();
+ pWriter->WriteBreakLine(false);
if (HaveCaption())
WriteToStringBuilder(*m_pCaption, *pWriter->GetCurrentDocument());
@@ -806,6 +872,18 @@ bool CMarkdownTable::Convert(XmlUtils::CXmlLiteReader& oReader, const NSCSS::CNo
WriteCellSeparator(*pWriter);
WriteRowEnd(*pWriter);
+
+ WriteRowStart(*pWriter);
+
+ for (size_t unColumnIndex = 0; unColumnIndex < m_oBody.GetColumnSize(); ++unColumnIndex)
+ {
+ pWriter->WriteString(L"-", true);
+
+ if (unColumnIndex != m_oBody.GetColumnSize() - 1)
+ WriteCellSeparator(*pWriter);
+ }
+
+ WriteRowEnd(*pWriter);
}
//Convert body
ConvertMatrix(oReader, arTableSelectors, m_oBody.GetMatrixCells(), pWriter);
@@ -861,46 +939,137 @@ bool CMarkdownTable::ConvertMatrix(XmlUtils::CXmlLiteReader& oReader, std::vecto
{
WriteRowStart(*pWriter);
- for (size_t unColumnIndex = 0; unColumnIndex < oMatrix[unRowIndex].size(); ++unColumnIndex)
+ for (size_t unColumnIndex = 0; unColumnIndex < oMatrix[unRowIndex].size();)
{
pTableCell = oMatrix[unRowIndex][unColumnIndex];
if (nullptr != pTableCell && ETableElement::FillingCell != pTableCell->GetType())
{
- if (!arNestedCells.empty() && arNestedCells.front().first == std::make_pair(unRowIndex, unColumnIndex))
+ if (!arNestedCells.empty())
{
- if (nullptr != arNestedCells.front().second)
+ NestedCells::const_iterator itElement{arNestedCells.find({unRowIndex, unColumnIndex})};
+
+ if (arNestedCells.end() != itElement)
{
- m_oExternalData.m_pWriter->GetCurrentDocument()->Write(*arNestedCells.front().second);
- delete arNestedCells.front().second;
+ if (nullptr != itElement->second)
+ {
+ m_oExternalData.m_pWriter->GetCurrentDocument()->Write(*itElement->second);
+ delete itElement->second;
+
+ if (oMatrix[unRowIndex].size() - 1 != unColumnIndex)
+ WriteCellSeparator(*pWriter);
+ }
+ arNestedCells.erase(itElement);
+
+ ++unColumnIndex;
+ continue;
+ }
+ }
+
+ MoveToNextTableCell(oReader, arSelectors, arDepths, m_oExternalData.GetSubClass);
+
+ if (ETableElement::FlatTable == pTableCell->GetType())
+ {
+ TCurentTablePosition oPosition{unRowIndex, unColumnIndex, unRowIndex, unColumnIndex};
+ std::vector arNestedSelectors;
+
+ const int nDepth{oReader.GetDepth()};
+
+ NSStringUtils::CStringBuilder oTempData(100);
+ bool bSetedDataOutput{false};
+
+ const size_t unDepthSize{arDepths.size()};
+
+ arDepths.push(oReader.GetDepth());
+
+ m_oExternalData.AddStopTag(L"table");
+
+ NSStringUtils::CStringBuilder oIntermediateData(100);
+
+ while(oReader.ReadNextSiblingNode2(nDepth))
+ {
+ if (L"table" == oReader.GetName())
+ {
+ if (bSetedDataOutput)
+ {
+ if (!arNestedCells.empty() && 0 != oTempData.GetCurSize())
+ {
+ arNestedCells.rbegin()->second->WriteString(L" ");
+ arNestedCells.rbegin()->second->Write(oTempData);
+ oTempData.Clear();
+ }
+
+ pWriter->RevertDataOutput();
+ bSetedDataOutput = false;
+ }
+
+ m_oExternalData.GetSubClass(oReader, arNestedSelectors);
+ ReadNestedCells(oReader, arNestedSelectors, oPosition, arNestedCells, oMatrix, pWriter, m_oExternalData, oIntermediateData);
+
+ oPosition.m_unColumnIndex = oPosition.m_unStartColumnIndex;
+ oPosition.m_unStartRowIndex = oPosition.m_unRowIndex;
+
+ if (0 != oTempData.GetCurSize() && !arNestedCells.empty())
+ {
+ oTempData.WriteString(L" ");
+ arNestedCells.begin()->second->WriteBefore(oTempData);
+ oTempData.Clear();
+ }
+
+ if (0 != oIntermediateData.GetCurSize() && !arNestedCells.empty())
+ {
+ arNestedCells.rbegin()->second->WriteString(L" ");
+ arNestedCells.rbegin()->second->Write(oIntermediateData);
+ oIntermediateData.Clear();
+ }
+ }
+ else
+ {
+ if (!bSetedDataOutput)
+ {
+ pWriter->SetDataOutput(&oTempData);
+ bSetedDataOutput = true;
+ }
+
+ m_oExternalData.ReadInside(oReader, arSelectors);
+ }
+ }
+
+ while (arDepths.size() > unDepthSize)
+ {
+ arDepths.pop();
+ arSelectors.pop_back();
+ }
+
+ m_oExternalData.ClearStopTags();
+
+ if (bSetedDataOutput)
+ {
+ if (!arNestedCells.empty())
+ {
+ arNestedCells.rbegin()->second->WriteString(L" ");
+ arNestedCells.rbegin()->second->Write(oTempData);
+ }
+
+ pWriter->RevertDataOutput();
}
- arNestedCells.pop();
}
else
{
- MoveToNextTableCell(oReader, arSelectors, arDepths, m_oExternalData.GetSubClass);
+ m_oExternalData.ReadStream(oReader, arSelectors);
+ if (oMatrix[unRowIndex].size() - 1 != unColumnIndex)
+ WriteCellSeparator(*pWriter);
- if (ETableElement::FlatTable == pTableCell->GetType())
- {
- TCurentTablePosition oPosition{unRowIndex, unColumnIndex, unRowIndex, unColumnIndex};
- std::vector arNestedSelectors;
-
- ReadNestedCells(oReader, arNestedSelectors, oPosition, arNestedCells, oMatrix, pWriter, m_oExternalData);
- --unColumnIndex;
- }
- else
- {
- m_oExternalData.ReadStream(oReader, arSelectors);
- if (oMatrix[unRowIndex].size() - 1 != unColumnIndex)
- WriteCellSeparator(*pWriter);
- }
- arSelectors.pop_back();
+ ++unColumnIndex;
}
+ arSelectors.pop_back();
}
else
{
if (oMatrix[unRowIndex].size() - 1 != unColumnIndex)
WriteCellSeparator(*pWriter);
+
+ ++unColumnIndex;
}
}
@@ -910,8 +1079,13 @@ bool CMarkdownTable::ConvertMatrix(XmlUtils::CXmlLiteReader& oReader, std::vecto
{
WriteRowStart(*pWriter);
- for (size_t unColumnIndex = 0; unColumnIndex < oMatrix[unRowIndex].size() - 1; ++unColumnIndex)
- pWriter->WriteString(L"-|-", true);
+ for (size_t unColumnIndex = 0; unColumnIndex < m_oBody.GetColumnSize(); ++unColumnIndex)
+ {
+ pWriter->WriteString(L"-", true);
+
+ if (unColumnIndex != m_oBody.GetColumnSize() - 1)
+ WriteCellSeparator(*pWriter);
+ }
WriteRowEnd(*pWriter);
}
@@ -926,7 +1100,39 @@ Table CMarkdownTable::Flatten(Table&& srcTable)
return {};
const size_t unRows{srcTable.size()};
- const size_t unColumns{srcTable[0].size()};
+
+ size_t unColumns{0}, unRowColumns{0};
+
+ for (const Row& oRow : srcTable)
+ {
+ for (ITableElementCell* pCell : oRow)
+ unRowColumns += (nullptr != pCell) ? ((CTableElementCell*)pCell)->GetColspan() : 1;
+
+ unColumns = (std::max)(unColumns, unRowColumns);
+
+ unRowColumns = 0;
+ }
+
+ size_t unColspan{1};
+
+ for (Row& oRow : srcTable)
+ {
+ for (size_t unColumnIndex = 0; unColumnIndex < oRow.size(); ++ unColumnIndex)
+ {
+ if (nullptr == oRow[unColumnIndex])
+ continue;
+
+ unColspan = oRow[unColumnIndex]->GetColspan();
+
+ if (1 != unColspan)
+ oRow.insert(oRow.begin() + unColumnIndex + 1, unColspan - 1, nullptr);
+
+ unColumnIndex += unColspan - 1;
+ }
+
+ if (oRow.size() != unColumns)
+ oRow.resize(unColumns);
+ }
std::vector> oInfos{unRows, std::vector{unColumns}};
@@ -941,8 +1147,8 @@ Table CMarkdownTable::Flatten(Table&& srcTable)
{
for (size_t unColumnIndex = 0; unColumnIndex < unColumns; ++unColumnIndex)
{
- arRowHeights[unRowIndex] = (std::max)(arRowHeights[unRowIndex], oInfos[unRowIndex][unColumnIndex].unRows);
- arColumnWidths[unColumnIndex] = (std::max)(arColumnWidths[unColumnIndex], oInfos[unRowIndex][unColumnIndex].unColumns);
+ arRowHeights[unRowIndex] = (std::max)(arRowHeights[unRowIndex], oInfos[unRowIndex][unColumnIndex].m_unRows);
+ arColumnWidths[unColumnIndex] = (std::max)(arColumnWidths[unColumnIndex], oInfos[unRowIndex][unColumnIndex].m_unColumns);
}
}
@@ -971,68 +1177,229 @@ Table CMarkdownTable::Flatten(Table&& srcTable)
if (nullptr == pCell)
continue;
- const TElementInfo oInfo{oInfos[unRowIndex][unColumnIndex]};
-
unBaseRow = arRowStart[unRowIndex];
unBaseColumn = arColumnStart[unColumnIndex];
- if (!IsTable(pCell))
+ if (!IsTableContainer(pCell))
{
oResult[unBaseRow][unBaseColumn] = pCell;
pCell = nullptr;
continue;
}
- CMarkdownTable *pTable{dynamic_cast(pCell)};
+
+ CTableContainer* pContainer{dynamic_cast(pCell)};
+ std::vector arTables{pContainer->GetTables()};
+ size_t unCurrentRowOffset{0};
+
pCell = nullptr;
- Table& oChild{pTable->m_oBody.GetMatrixCells()};
- Table oFlatChild{Flatten(std::move(oChild))};
+ for (CTableElement* pTable : arTables)
+ {
+ TElementInfo oSubInfo{ComputeInfo(pTable)};
- for (size_t unChildRowIndex = 0; unChildRowIndex < oInfo.unRows; ++unChildRowIndex)
- for (size_t unChildColumnIndex = 0; unChildColumnIndex < oInfo.unColumns; ++unChildColumnIndex)
- oResult[unBaseRow + unChildRowIndex][unBaseColumn + unChildColumnIndex] = oFlatChild[unChildRowIndex][unChildColumnIndex];
+ Table& oChild{dynamic_cast(pTable)->m_oBody.GetMatrixCells()};
+ Table oFlatChild{Flatten(std::move(oChild))};
- CTableElementCell* pFlatCell{dynamic_cast(oResult[unBaseRow][unBaseColumn])};
+ for (size_t unChildRowIndex = 0; unChildRowIndex < oSubInfo.m_unRows; ++unChildRowIndex)
+ for (size_t unChildColumnIndex = 0; unChildColumnIndex < oSubInfo.m_unColumns; ++unChildColumnIndex)
+ oResult[unBaseRow + unCurrentRowOffset + unChildRowIndex][unBaseColumn + unChildColumnIndex] = oFlatChild[unChildRowIndex][unChildColumnIndex];
- if(nullptr != pFlatCell)
- pFlatCell->IsFlatTable();
+ CTableElementCell* pFlatCell{dynamic_cast(oResult[unBaseRow + unCurrentRowOffset][unBaseColumn])};
- delete pTable;
+ if(nullptr != pFlatCell)
+ pFlatCell->IsFlatTable();
+
+ unCurrentRowOffset += oSubInfo.m_unRows;
+ }
+
+ delete pContainer;
}
}
return oResult;
}
+// Table CMarkdownTable::Flatten(Table&& srcTable)
+// {
+// if (srcTable.empty())
+// return {};
+
+// const size_t unRows = srcTable.size();
+
+// // ---------- 1. Разворачиваем строки с учётом colspan ----------
+// std::vector> expandedRows;
+// expandedRows.reserve(unRows);
+// size_t unColumns = 0;
+
+// for (Row& oRow : srcTable)
+// {
+// std::vector expandedRow;
+// for (ITableElementCell* pCell : oRow)
+// {
+// if (pCell != nullptr)
+// {
+// expandedRow.push_back(pCell);
+// size_t colspan = pCell->GetColspan();
+// // Добавляем (colspan - 1) пустых ячеек справа
+// for (size_t i = 1; i < colspan; ++i)
+// expandedRow.push_back(nullptr);
+// }
+// else
+// {
+// expandedRow.push_back(nullptr);
+// }
+// }
+// unColumns = std::max(unColumns, expandedRow.size());
+// expandedRows.push_back(std::move(expandedRow));
+// }
+
+// // Приводим все строки к одинаковой длине
+// for (auto& row : expandedRows)
+// row.resize(unColumns, nullptr);
+
+// // ---------- 2. Вычисляем информацию о размерах каждой ячейки ----------
+// std::vector> oInfos(unRows, std::vector(unColumns));
+// for (size_t r = 0; r < unRows; ++r)
+// for (size_t c = 0; c < unColumns; ++c)
+// oInfos[r][c] = ComputeInfo(expandedRows[r][c]);
+
+// // ---------- 3. Вычисляем высоты строк и ширины столбцов ----------
+// std::vector arRowHeights(unRows, 1);
+// std::vector arColumnWidths(unColumns, 1);
+
+// for (size_t r = 0; r < unRows; ++r)
+// {
+// for (size_t c = 0; c < unColumns; ++c)
+// {
+// arRowHeights[r] = std::max(arRowHeights[r], oInfos[r][c].m_unRows);
+// arColumnWidths[c] = std::max(arColumnWidths[c], oInfos[r][c].m_unColumns);
+// }
+// }
+
+// // ---------- 4. Вычисляем смещения строк и столбцов в результирующей сетке ----------
+// std::vector arRowStart(unRows + 1, 0);
+// std::vector arColumnStart(unColumns + 1, 0);
+
+// for (size_t r = 0; r < unRows; ++r)
+// arRowStart[r + 1] = arRowStart[r] + arRowHeights[r];
+
+// for (size_t c = 0; c < unColumns; ++c)
+// arColumnStart[c + 1] = arColumnStart[c] + arColumnWidths[c];
+
+// const size_t unTotalRows = arRowStart[unRows];
+// const size_t unTotalColumns = arColumnStart[unColumns];
+
+// Table oResult(unTotalRows, Row(unTotalColumns, nullptr));
+
+// // ---------- 5. Заполняем результат ----------
+// for (size_t r = 0; r < unRows; ++r)
+// {
+// for (size_t c = 0; c < unColumns; ++c)
+// {
+// ITableElementCell*& pCell = expandedRows[r][c];
+// if (pCell == nullptr)
+// continue;
+
+// const size_t unBaseRow = arRowStart[r];
+// const size_t unBaseColumn = arColumnStart[c];
+
+// // Обычная ячейка (не контейнер)
+// if (!IsTableContainer(pCell))
+// {
+// oResult[unBaseRow][unBaseColumn] = pCell;
+// pCell = nullptr;
+// continue;
+// }
+
+// // Контейнер таблиц
+// CTableContainer* pContainer = dynamic_cast(pCell);
+// std::vector arTables = pContainer->GetTables();
+// pCell = nullptr; // владение передано
+
+// size_t unCurrentRowOffset = 0;
+// for (CTableElement* pTableElem : arTables)
+// {
+// // Предполагаем, что в контейнере лежат только CMarkdownTable
+// CMarkdownTable* pMarkdownTable = dynamic_cast(pTableElem);
+// if (pMarkdownTable == nullptr)
+// continue;
+
+// TElementInfo oSubInfo = ComputeInfo(pMarkdownTable);
+// Table& oChild = pMarkdownTable->m_oBody.GetMatrixCells();
+// Table oFlatChild = Flatten(std::move(oChild));
+
+// for (size_t cr = 0; cr < oSubInfo.m_unRows; ++cr)
+// for (size_t cc = 0; cc < oSubInfo.m_unColumns; ++cc)
+// oResult[unBaseRow + unCurrentRowOffset + cr][unBaseColumn + cc] = oFlatChild[cr][cc];
+
+// // Если первая ячейка сплющенной таблицы является CTableElementCell, помечаем её
+// if (auto* pFlatCell = dynamic_cast(oResult[unBaseRow + unCurrentRowOffset][unBaseColumn]))
+// pFlatCell->IsFlatTable();
+
+// unCurrentRowOffset += oSubInfo.m_unRows;
+// }
+
+// delete pContainer;
+// }
+// }
+
+// return oResult;
+// }
+
TElementInfo CMarkdownTable::ComputeInfo(const ITableElementCell* pCell)
{
- if (!IsTable(pCell))
+ if (IsTableContainer(pCell))
+ {
+ const std::vector arTables{((CTableContainer*)pCell)->GetTables()};
+
+ TElementInfo oElementInfo, oTempInfo;
+
+ for (CTableElement* pTable : arTables)
+ {
+ oTempInfo = ComputeInfo(pTable);
+
+ oElementInfo.m_unColumns = std::max(oElementInfo.m_unColumns, oTempInfo.m_unColumns);
+ oElementInfo.m_unRows += oTempInfo.m_unRows;
+ }
+
+ return oElementInfo;
+ }
+
+ return {1, 1};
+}
+
+TElementInfo CMarkdownTable::ComputeInfo(const CTableElement* pTable)
+{
+ if (nullptr == pTable)
return {1, 1};
- const CMarkdownTable *pMarkdownTable{dynamic_cast(pCell)};
+ const CMarkdownTable *pMarkdownTable{dynamic_cast(pTable)};
if (nullptr == pMarkdownTable)
return {1, 1};
- const CTableMatrix *pTable{&pMarkdownTable->m_oBody};
+ const CTableMatrix *pTableMaxtix{&pMarkdownTable->m_oBody};
- const size_t unRows{pTable->GetRowSize()};
- const size_t unColumns{pTable->GetColumnSize()};
+ const size_t unRows{pTableMaxtix->GetRowSize()};
+ const size_t unColumns{pTableMaxtix->GetColumnSize()};
std::vector arRowHeights(unRows, 1);
std::vector arColumnWidths(unColumns, 1);
- const Table& arCells{pTable->GetMatrixCells()};
+ const Table& arCells{pTableMaxtix->GetMatrixCells()};
for (size_t unRowIndex = 0; unRowIndex < unRows; ++unRowIndex)
{
for (size_t unColumnIndex = 0; unColumnIndex < unColumns; ++unColumnIndex)
{
- TElementInfo oInfo{ComputeInfo(arCells[unRowIndex][unColumnIndex])};
+ TElementInfo oInfo{1, arCells[unRowIndex][unColumnIndex]->GetColspan()};
- arRowHeights[unRowIndex] = (std::max)(arRowHeights[unRowIndex], oInfo.unRows);
- arColumnWidths[unColumnIndex] = (std::max)(arColumnWidths[unColumnIndex], oInfo.unColumns);
+ if (IsTableContainer(arCells[unRowIndex][unColumnIndex]))
+ oInfo = ComputeInfo(arCells[unRowIndex][unColumnIndex]);
+
+ arRowHeights[unRowIndex] = (std::max)(arRowHeights[unRowIndex], oInfo.m_unRows);
+ arColumnWidths[unColumnIndex] = (std::max)(arColumnWidths[unColumnIndex], oInfo.m_unColumns);
}
}
diff --git a/HtmlFile2/Tags/MDTags.h b/HtmlFile2/Tags/MDTags.h
index d78eaa7918..bb9eb31189 100644
--- a/HtmlFile2/Tags/MDTags.h
+++ b/HtmlFile2/Tags/MDTags.h
@@ -55,8 +55,16 @@ void CCodeTag::Close();
struct TElementInfo
{
- size_t unRows;
- size_t unColumns;
+ size_t m_unRows;
+ size_t m_unColumns;
+
+ TElementInfo()
+ : m_unRows{0}, m_unColumns{0}
+ {}
+
+ TElementInfo(const size_t& unRows, const size_t& m_unColumns)
+ : m_unRows{unRows}, m_unColumns{m_unColumns}
+ {}
};
class CMarkdownTable : public CTableElement
@@ -76,6 +84,7 @@ private:
static Table Flatten(Table&& srcTable);
static TElementInfo ComputeInfo(const ITableElementCell* pCell);
+ static TElementInfo ComputeInfo(const CTableElement* pTable);
};
}
diff --git a/HtmlFile2/Tags/OOXMLTags.cpp b/HtmlFile2/Tags/OOXMLTags.cpp
index e0f2bf4c1f..6109bf368a 100644
--- a/HtmlFile2/Tags/OOXMLTags.cpp
+++ b/HtmlFile2/Tags/OOXMLTags.cpp
@@ -1403,14 +1403,14 @@ void COOXMLTable::CloseRow(XmlString& oXmlString)
oXmlString.WriteNodeEnd(L"w:tr");
}
-void COOXMLTable::OpenCell(XmlString& oXmlString, size_t unColumnIndex)
+void COOXMLTable::OpenCell(XmlString& oXmlString)
{
oXmlString.WriteNodeBegin(L"w:tc");
}
-void COOXMLTable::OpenCell(XmlString& oXmlString, const NSCSS::CNode& oCellNode, CTableElementCell* pCell, size_t unColumnIndex, ERowParseMode eRowParseMode, ERowPosition eRowPosition, size_t& unHeight, const TTableStyles& oTableStyles)
+void COOXMLTable::OpenCell(XmlString& oXmlString, const NSCSS::CNode& oCellNode, ITableElementCell* pCell, size_t unColumnIndex, ERowParseMode eRowParseMode, ERowPosition eRowPosition, size_t& unHeight, const TTableStyles& oTableStyles, std::unordered_map& mFillingColumn)
{
- OpenCell(oXmlString, unColumnIndex);
+ OpenCell(oXmlString);
if (nullptr == pCell)
return;
@@ -1450,25 +1450,8 @@ void COOXMLTable::OpenCell(XmlString& oXmlString, const NSCSS::CNode& oCellNode,
else
oXmlString += L"";
- std::wstring wsValue;
-
- if (oCellNode.GetAttributeValue(L"colspan", wsValue))
- {
- const int nColspan{NSStringFinder::ToInt(wsValue, 1)};
-
- if (1 < nColspan)
- oXmlString += L"";
- }
-
- if (ETableElement::FillingCell == pCell->GetType())
- oXmlString += L"";
- else if (oCellNode.GetAttributeValue(L"rowspan", wsValue))
- {
- const int nRowspan{NSStringFinder::ToInt(wsValue, 1)};
-
- if (1 < nRowspan)
- oXmlString += L"";
- }
+ if (1 != pCell->GetColspan())
+ oXmlString += L"GetColspan()) + L"\"/>";
const NSCSS::NSProperties::CBorder* pBorder{&oCellNode.m_pCompiledStyle->m_oBorder};
@@ -1493,6 +1476,22 @@ void COOXMLTable::OpenCell(XmlString& oXmlString, const NSCSS::CNode& oCellNode,
oXmlString += L"" + wsBorders + L"";
}
+ std::wstring wsValue;
+
+ if (ETableElement::FillingCell == pCell->GetType())
+ oXmlString += L"";
+ else if (oCellNode.GetAttributeValue(L"rowspan", wsValue))
+ {
+ const int nRowspan{NSStringFinder::ToInt(wsValue, 1)};
+
+ if (1 < nRowspan)
+ {
+ oXmlString += L"";
+ mFillingColumn[unColumnIndex] = oCellNode;
+ mFillingColumn[unColumnIndex].m_pCompiledStyle = new NSCSS::CCompiledStyle(*oCellNode.m_pCompiledStyle);
+ }
+ }
+
const NSCSS::NSProperties::CColor* pBackground{&oCellNode.m_pCompiledStyle->m_oBackground.GetColor()};
if (nullptr != pColStyle && pBackground->LessSignificantThen(pColStyle->m_oBackground.GetColor()))
@@ -1594,65 +1593,122 @@ void COOXMLTable::ConvertMatrix(XmlUtils::CXmlLiteReader& oReader, COOXMLWriter&
ITableElementCell* pTableCell{nullptr};
size_t unCellHeight{0}, unMaxCellHeight{0};
+ std::unordered_map mFillingColumn;
for (size_t unRowIndex = 0; unRowIndex < oMatrix.size(); ++unRowIndex)
{
XmlString oCellsData;
oWriter.SetDataOutput(&oCellsData);
+ bool bEmptyRow{true};
for (size_t unColumnIndex = 0; unColumnIndex < oMatrix[unRowIndex].size(); ++unColumnIndex)
{
pTableCell = oMatrix[unRowIndex][unColumnIndex];
- if (nullptr != pTableCell)
- {
- MoveToNextTableCell(oReader, arSelectors, arDepths, m_oExternalData.GetSubClass);
-
- if (ETableElement::Table == pTableCell->GetType())
- {
- if (unColumnIndex < MAX_COLUMNS_IN_TABLE)
- OpenCell(oCellsData, unColumnIndex);
-
- const COOXMLTable* pTable{dynamic_cast(pTableCell)};
-
- if (nullptr == pTableCell)
- oWriter.WriteEmptyParagraph();
- else
- {
- arDepths.push(oReader.GetDepth());
- MoveToNextTableCell(oReader, arSelectors, arDepths, m_oExternalData.GetSubClass);
- ConvertTable(oReader, oWriter, *pTable, arSelectors.back());
- }
- }
- else
- {
- if (unColumnIndex < MAX_COLUMNS_IN_TABLE)
- OpenCell(oCellsData, arSelectors.back(), (CTableElementCell*)pTableCell, unColumnIndex, eRowParseMode,
- ((0 == unRowIndex) ? ERowPosition::First : ((oMatrix.size() - 1 == unRowIndex) ? ERowPosition::Last : ERowPosition::Middle)),
- unCellHeight, oTableStyles);
-
- unMaxCellHeight = (std::max)(unMaxCellHeight, unCellHeight);
-
- m_oExternalData.ReadStream(oReader, arSelectors);
- }
-
- oWriter.CloseP();
-
- if (unColumnIndex < MAX_COLUMNS_IN_TABLE - 1)
- CloseCell(oCellsData);
-
- arSelectors.pop_back();
- }
- else
+ if (nullptr == pTableCell)
{
if (unColumnIndex < MAX_COLUMNS_IN_TABLE)
- OpenCell(oCellsData, unColumnIndex);
+ OpenCell(oCellsData);
oWriter.WriteEmptyParagraph();
if (unColumnIndex < MAX_COLUMNS_IN_TABLE - 1)
CloseCell(oCellsData);
+
+ continue;
}
+
+ if (ETableElement::FillingCell == pTableCell->GetType())
+ {
+ if (unColumnIndex < MAX_COLUMNS_IN_TABLE)
+ {
+ OpenCell(oCellsData, mFillingColumn.at(unColumnIndex), (CTableElementCell*)pTableCell, unColumnIndex, eRowParseMode,
+ ((0 == unRowIndex) ? ERowPosition::First : ((oMatrix.size() - 1 == unRowIndex) ? ERowPosition::Last : ERowPosition::Middle)),
+ unCellHeight, oTableStyles, mFillingColumn);
+ }
+
+ oWriter.WriteEmptyParagraph();
+
+ if (unColumnIndex < MAX_COLUMNS_IN_TABLE - 1)
+ CloseCell(oCellsData);
+
+ continue;
+ }
+
+ MoveToNextTableCell(oReader, arSelectors, arDepths, m_oExternalData.GetSubClass);
+
+ bEmptyRow = false;
+
+ if (ETableElement::TableContainer == pTableCell->GetType())
+ {
+ if (unColumnIndex < MAX_COLUMNS_IN_TABLE)
+ OpenCell(oCellsData, arSelectors.back(), (CTableElementCell*)pTableCell, unColumnIndex, eRowParseMode,
+ ((0 == unRowIndex) ? ERowPosition::First : ((oMatrix.size() - 1 == unRowIndex) ? ERowPosition::Last : ERowPosition::Middle)),
+ unCellHeight, oTableStyles, mFillingColumn);
+
+ std::vector arTables{((CTableContainer*)pTableCell)->GetTables()};
+ std::vector::const_iterator itTable = arTables.cbegin();
+
+ const size_t unDepthSize{arDepths.size()};
+
+ arDepths.push(oReader.GetDepth());
+
+ m_oExternalData.AddStopTag(L"table");
+
+ #define READ_TABLE()\
+ m_oExternalData.GetSubClass(oReader, arSelectors);\
+ oWriter.CloseP();\
+ ConvertTable(oReader, oWriter, *(COOXMLTable*)*itTable++, arSelectors.back());\
+ oWriter.WriteEmptyParagraph(true);\
+ arSelectors.pop_back()
+
+ while (oReader.ReadNextSiblingNode2(arDepths.top()))
+ {
+ if (L"table" == oReader.GetName())
+ {
+ READ_TABLE();
+ }
+ else
+ {
+ m_oExternalData.ReadInside(oReader, arSelectors);
+
+ if (L"table" == oReader.GetName())
+ {
+ READ_TABLE();
+ }
+ }
+ }
+
+ while (arDepths.size() > unDepthSize)
+ {
+ arDepths.pop();
+ arSelectors.pop_back();
+ }
+
+ m_oExternalData.ClearStopTags();
+ }
+ else
+ {
+ if (unColumnIndex < MAX_COLUMNS_IN_TABLE)
+ OpenCell(oCellsData, arSelectors.back(), (CTableElementCell*)pTableCell, unColumnIndex, eRowParseMode,
+ ((0 == unRowIndex) ? ERowPosition::First : ((oMatrix.size() - 1 == unRowIndex) ? ERowPosition::Last : ERowPosition::Middle)),
+ unCellHeight, oTableStyles, mFillingColumn);
+
+ unMaxCellHeight = (std::max)(unMaxCellHeight, unCellHeight);
+
+ const size_t unSelectorsSize{arSelectors.size()};
+
+ m_oExternalData.ReadStream(oReader, arSelectors);
+
+ arSelectors.resize(unSelectorsSize);
+
+ arSelectors.pop_back();
+ }
+
+ oWriter.CloseP();
+
+ if (unColumnIndex < MAX_COLUMNS_IN_TABLE - 1)
+ CloseCell(oCellsData);
}
if (oMatrix[unRowIndex].size() >= MAX_COLUMNS_IN_TABLE)
@@ -1664,34 +1720,68 @@ void COOXMLTable::ConvertMatrix(XmlUtils::CXmlLiteReader& oReader, COOXMLWriter&
WriteToStringBuilder(oCellsData, *oWriter.GetCurrentDocument());
CloseRow(*oWriter.GetCurrentDocument());
- arSelectors.pop_back();
- arDepths.pop();
+ if (!bEmptyRow)
+ {
+ arSelectors.pop_back();
+ arDepths.pop();
+ }
}
arSelectors.pop_back();
arDepths.pop();
}
+inline void CalculateMaxRowSize(const Table& oMatrix, size_t& unMaxRowSize)
+{
+ for (const Row& oRow : oMatrix)
+ {
+ size_t unCurrentSize{0};
+ for (ITableElementCell* pCell : oRow)
+ {
+ if (nullptr == pCell || ETableElement::TableContainer == pCell->GetType())
+ unCurrentSize += 1;
+ else
+ unCurrentSize += ((CTableElementCell*)pCell)->GetColspan();
+ }
+ unMaxRowSize = (std::max)(unMaxRowSize, unCurrentSize);
+ }
+}
+
+inline void NormalizeMatrix(Table& oMatrix, const size_t& unMaxMatrixColumns, const size_t& unMaxColumns)
+{
+ for (Row& oRow : oMatrix)
+ {
+ for (ITableElementCell* pCell : oRow)
+ {
+ if (nullptr == pCell)
+ continue;
+
+ if (ETableElement::TableContainer == pCell->GetType())
+ {
+ for (CTableElement* pTable : ((CTableContainer*)pCell)->GetTables())
+ if (nullptr != pTable)
+ pTable->Normalize();
+ }
+ }
+
+ if (unMaxMatrixColumns != unMaxColumns)
+ oRow.resize(oRow.size() + (unMaxColumns - unMaxMatrixColumns));
+ }
+}
+
void COOXMLTable::Normalize()
{
- size_t unMaxColumn{0};
+ size_t unMaxColumns{0}, unHeaderRowSize{0}, unBodyRowSize{0}, unFootherRowSize{0};
- #define CHECK_TABLE(table_variable)\
- for (const Row& oRow : table_variable.GetMatrixCells())\
- unMaxColumn = (std::max)(unMaxColumn, oRow.size())
+ CalculateMaxRowSize(m_oHeader.GetMatrixCells(), unHeaderRowSize);
+ CalculateMaxRowSize(m_oBody.GetMatrixCells(), unBodyRowSize);
+ CalculateMaxRowSize(m_oFoother.GetMatrixCells(), unFootherRowSize);
- CHECK_TABLE(m_oHeader);
- CHECK_TABLE(m_oBody);
- CHECK_TABLE(m_oFoother);
+ unMaxColumns = (std::max)((std::max)(unHeaderRowSize, unBodyRowSize), unFootherRowSize);
- #define NORMALIZE_TABLE(table_variable)\
- for (Row& oRow : table_variable.GetMatrixCells())\
- if (oRow.size() != unMaxColumn)\
- oRow.resize(unMaxColumn)
-
- NORMALIZE_TABLE(m_oHeader);
- NORMALIZE_TABLE(m_oBody);
- NORMALIZE_TABLE(m_oFoother);
+ NormalizeMatrix(m_oHeader.GetMatrixCells(), unHeaderRowSize, unMaxColumns);
+ NormalizeMatrix(m_oBody.GetMatrixCells(), unBodyRowSize, unMaxColumns);
+ NormalizeMatrix(m_oFoother.GetMatrixCells(), unFootherRowSize, unMaxColumns);
}
bool COOXMLTable::Convert(XmlUtils::CXmlLiteReader& oReader, const NSCSS::CNode& oTableNode)
diff --git a/HtmlFile2/Tags/OOXMLTags.h b/HtmlFile2/Tags/OOXMLTags.h
index 9f93c57fa9..faddf02aa3 100644
--- a/HtmlFile2/Tags/OOXMLTags.h
+++ b/HtmlFile2/Tags/OOXMLTags.h
@@ -117,7 +117,7 @@ private:
NSCSS::NSProperties::CIndent m_oPadding;
TTableStyles()
- : m_unCellSpacing{0}, m_enRules{ETableRules::All}, m_pTable{nullptr}
+ : m_unCellSpacing{0}, m_enRules{ETableRules::All}, m_pTable{nullptr}
{}
};
@@ -141,8 +141,8 @@ private:
void OpenRow(XmlString& oXmlString, bool bIsHeader, size_t unMaxHeight, size_t unCellSpacing);
void CloseRow(XmlString& oXmlString);
- void OpenCell(XmlString& oXmlString, size_t unColumnIndex);
- void OpenCell(XmlString& oXmlString, const NSCSS::CNode& oCellNode, CTableElementCell* pCell, size_t unColumnIndex, ERowParseMode eRowParseMode, ERowPosition eRowPosition, size_t& unHeight, const TTableStyles& oTableStyles);
+ void OpenCell(XmlString& oXmlString);
+ void OpenCell(XmlString& oXmlString, const NSCSS::CNode& oCellNode, ITableElementCell* pCell, size_t unColumnIndex, ERowParseMode eRowParseMode, ERowPosition eRowPosition, size_t& unHeight, const TTableStyles& oTableStyles, std::unordered_map& mFillingColumn);
void CloseCell(XmlString& oXmlString);
void ConvertTable(XmlUtils::CXmlLiteReader& oReader, COOXMLWriter& oWriter, const COOXMLTable& oTable, const NSCSS::CNode& oTableNode);