diff --git a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
index 816ca43c35..9948bb9e72 100644
--- a/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
+++ b/Common/3dParty/html/css/src/xhtml/CDocumentStyle.cpp
@@ -317,7 +317,7 @@ namespace NSCSS
oXmlElement.AddPropertiesInP(PProperties::P_ContextualSpacing, L"true");
}
- if (!oStyle.m_oBackground.Empty() && oStyle.HaveThisParent(L"table"))
+ if (!oStyle.m_oBackground.Empty() && !oStyle.HaveThisParent(L"table"))
oXmlElement.AddPropertiesInP(PProperties::P_Shd, oStyle.m_oBackground.IsNone() ? L"auto" : oStyle.m_oBackground.GetColor().ToWString());
if (!oStyle.m_oBorder.Empty() && !oStyle.HaveThisParent(L"table"))
diff --git a/HtmlFile2/htmlfile2.cpp b/HtmlFile2/htmlfile2.cpp
index bdbfcad343..ee91b818e4 100644
--- a/HtmlFile2/htmlfile2.cpp
+++ b/HtmlFile2/htmlfile2.cpp
@@ -41,6 +41,8 @@
#define DEFAULT_PAGE_WIDTH 12240 // Значение в Twips
#define DEFAULT_PAGE_HEIGHT 15840 // Значение в Twips
+#define SAVE_NORMALIZED_HTML 0
+
std::wstring rStyle = L" a area b strong bdo bdi big br center cite dfn em i var code kbd samp tt del s font img ins u mark q rt sup small sub svg input basefont button label data object noscript output abbr time ruby progress hgroup meter span acronym ";
//struct CTree
@@ -273,6 +275,11 @@ public:
m_oStyles.m_wsAlign = wsAlign;
}
+ void SetBackground(const NSCSS::NSProperties::CColor& oColor)
+ {
+ m_oStyles.m_oBackground = oColor;
+ }
+
std::wstring ConvertToOOXML(const TTableStyles& oTableStyles)
{
NSStringUtils::CStringBuilder oCell;
@@ -285,12 +292,25 @@ public:
if (NSCSS::UnitMeasure::Percent == m_oStyles.m_oWidth.GetUnitMeasure())
oCell += L"";
else
- oCell += L"";
+ {
+ if (!m_oStyles.m_oWidth.Zero())
+ {
+ int nWidth;
+ if (NSCSS::UnitMeasure::None != m_oStyles.m_oWidth.GetUnitMeasure())
+ nWidth = m_oStyles.m_oWidth.ToInt(NSCSS::UnitMeasure::Twips);
+ else
+ nWidth = static_cast(NSCSS::CUnitMeasureConverter::ConvertPx(m_oStyles.m_oWidth.ToDouble(), NSCSS::UnitMeasure::Twips, 96) + 0.5);
+
+ oCell += L"";
+ }
+ else
+ oCell += L"";
+ }
}
else
oCell += L"";
- if (1 < m_unColspan)
+ if (1 != m_unColspan)
oCell += L"";
if (m_bIsMerged)
@@ -465,6 +485,29 @@ public:
RELEASEOBJECT(pRow);
}
+ CTableRow* operator[](UINT unIndex)
+ {
+ if (unIndex < m_arRows.size())
+ return m_arRows[unIndex];
+
+ return NULL;
+ }
+
+ bool Empty() const
+ {
+ return m_arRows.empty();
+ }
+
+ bool HaveCaption()
+ {
+ return 0 != m_oCaption.GetCurSize();
+ }
+
+ UINT GetRowCount() const
+ {
+ return m_arRows.size();
+ }
+
void AddRow(CTableRow* pRow)
{
if (NULL == pRow)
@@ -481,6 +524,11 @@ public:
m_arRows.push_back(pRow);
}
+ void SetCaption(const NSStringUtils::CStringBuilder& oCaption)
+ {
+ m_oCaption = oCaption;
+ }
+
void SetPadding(const NSCSS::NSProperties::CIndent& oPadding)
{
m_oStyles.m_oPadding = oPadding;
@@ -521,6 +569,16 @@ public:
return m_oStyles.m_bHaveBorderAttribute;
}
+ UINT GetMaxColumns()
+ {
+ UINT unMaxColumns = 0;
+
+ for (const CTableRow* pRow : m_arRows)
+ unMaxColumns = std::max(unMaxColumns, pRow->GetIndex());
+
+ return unMaxColumns;
+ }
+
void ApplyRowspan()
{
CTableCell* pCell = NULL;
@@ -553,6 +611,12 @@ public:
if (NULL == pCell)
continue;
+ if (1 != pCell->GetColspan() && unIndex + pCell->GetColspan() > m_arMinColspan[unIndex])
+ {
+ pCell->SetColspan(m_arMinColspan[unIndex] - unIndex, MAXCOLUMNSINTABLE);
+ continue;
+ }
+
if ((*pRow)[unIndex]->GetColspan() == m_arMinColspan[unIndex] + 1)
(*pRow)[unIndex]->SetColspan(2, MAXCOLUMNSINTABLE);
else if ((*pRow)[unIndex]->GetColspan() > m_arMinColspan[unIndex])
@@ -596,12 +660,23 @@ public:
if (NSCSS::UnitMeasure::Percent == m_oStyles.m_oWidth.GetUnitMeasure())
oTable += L"";
else
- oTable += L"";
+ {
+ int nWidth;
+ if (NSCSS::UnitMeasure::None != m_oStyles.m_oWidth.GetUnitMeasure())
+ nWidth = m_oStyles.m_oWidth.ToInt(NSCSS::UnitMeasure::Twips);
+ else
+ nWidth = static_cast(NSCSS::CUnitMeasureConverter::ConvertPx(m_oStyles.m_oWidth.ToDouble(), NSCSS::UnitMeasure::Twips, 96) + 0.5);
+
+ oTable += L"";
+ }
}
else
oTable += L"";
- if (0 < m_oStyles.m_nCellSpacing)
+ if (!m_oStyles.m_wsAlign.empty())
+ oTable += L"";
+
+ if (0 <= m_oStyles.m_nCellSpacing)
oTable += L"";
if (!m_oStyles.m_oBorder.Empty() && !m_oStyles.m_oBorder.Zero())
@@ -624,12 +699,28 @@ public:
else
oTable += L"";
- if (!m_oStyles.m_wsAlign.empty())
- oTable += L"";
-
oTable += L"";
oTable.WriteNodeEnd(L"w:tblPr");
+ if (HaveCaption())
+ {
+ oTable.WriteNodeBegin(L"w:tr");
+ oTable.WriteNodeBegin(L"w:trPr");
+ oTable += L"";
+ oTable.WriteNodeEnd(L"w:trPr");
+ oTable.WriteNodeBegin(L"w:tc");
+ oTable.WriteNodeBegin(L"w:tcPr");
+ oTable += L"";
+ oTable += L"";
+ oTable += L"";
+ oTable += L"";
+ oTable += L"";
+ oTable.WriteNodeEnd(L"w:tcPr");
+ oTable.WriteString(m_oCaption.GetData());
+ oTable.WriteNodeEnd(L"w:tc");
+ oTable.WriteNodeEnd(L"w:tr");
+ }
+
for (CTableRow* pRow : m_arRows)
oTable += pRow->ConvertToOOXML(m_oStyles);
@@ -641,6 +732,8 @@ private:
std::vector m_arRows;
std::vector m_arMinColspan;
+ NSStringUtils::CStringBuilder m_oCaption;
+
TTableStyles m_oStyles;
};
@@ -1074,13 +1167,16 @@ public:
std::wstring sRes = htmlToXhtml(sFileContent);
-// NSFile::CFileBinary oWriter;
-// if (oWriter.CreateFileW(m_sTmp + L"/res.html"))
-// {
-// oWriter.WriteStringUTF8(sRes);
-// oWriter.CloseFile();
-// }
-
+ #ifdef SAVE_NORMALIZED_HTML
+ #if 1 == SAVE_NORMALIZED_HTML
+ NSFile::CFileBinary oWriter;
+ if (oWriter.CreateFileW(m_sTmp + L"/res.html"))
+ {
+ oWriter.WriteStringUTF8(sRes);
+ oWriter.CloseFile();
+ }
+ #endif
+ #endif
return m_oLightReader.FromString(sRes);
}
@@ -1892,7 +1988,7 @@ private:
// Таблицы
else if(sName == L"table")
readTable(oXml, sSelectors, oTS);
- // Текст с границами
+ // Текст с границами
else if(sName == L"textarea" || sName == L"fieldset")
{
CTextSettings oTSP(oTS);
@@ -2197,6 +2293,51 @@ private:
}
}
+ void CalculateCellStyles(CTableCell* pCell, const std::vector& arSelectors)
+ {
+ if (NULL == pCell)
+ return;
+
+ std::vector arNewSelectors{(std::vector::const_iterator)std::find_if(arSelectors.begin(), arSelectors.end(), [](const NSCSS::CNode& oNode){ return L"table" == oNode.m_wsName; }), arSelectors.cend()};
+
+ NSCSS::CCompiledStyle oStyle;
+ m_oStylesCalculator.GetCompiledStyle(oStyle, arNewSelectors);
+
+ pCell->SetAlign(oStyle.m_oDisplay.GetHAlign().ToWString());
+ pCell->SetBackground(oStyle.m_oBackground.GetColor());
+ pCell->SetHeight(oStyle.m_oDisplay.GetHeight());
+ pCell->SetWidth(oStyle.m_oDisplay.GetWidth());
+ pCell->SetPadding(oStyle.m_oPadding);
+ pCell->SetBorder(oStyle.m_oBorder);
+ }
+
+ struct TTableCaption
+ {
+ UINT m_unPrevRows;
+ NSStringUtils::CStringBuilder m_oData;
+
+ TTableCaption(UINT unPrevRows = 0) : m_unPrevRows(unPrevRows)
+ {}
+ };
+
+ void ParseTableCaption(CTable& oTable, std::vector& sSelectors, const CTextSettings& oTS, std::vector& arCaptions)
+ {
+ GetSubClass(NULL, sSelectors);
+
+ TTableCaption *pData = new TTableCaption(oTable.GetRowCount());
+
+ CTextSettings oTSCaption{oTS};
+ oTSCaption.sPStyle += L"";
+
+ wrP(&(pData->m_oData), sSelectors, oTSCaption);
+ readStream(&(pData->m_oData), sSelectors, oTSCaption);
+ CloseP(&(pData->m_oData), sSelectors);
+
+ arCaptions.push_back(pData);
+ sSelectors.pop_back();
+ return;
+ }
+
void ParseTableRows(CTable& oTable, std::vector& sSelectors, const CTextSettings& oTS)
{
int nDeath = m_oLightReader.GetDepth();
@@ -2215,17 +2356,7 @@ private:
CTableCell *pCell = new CTableCell();
GetSubClass(pCell->GetData(), sSelectors);
-
- std::vector arNewSelectors{(std::vector::const_iterator)std::find_if(sSelectors.begin(), sSelectors.end(), [](const NSCSS::CNode& oNode){ return L"table" == oNode.m_wsName; }), sSelectors.cend()};
-
- NSCSS::CCompiledStyle oStyle;
- m_oStylesCalculator.GetCompiledStyle(oStyle, arNewSelectors);
-
- pCell->SetAlign(oStyle.m_oDisplay.GetHAlign().ToWString());
- pCell->SetHeight(oStyle.m_oDisplay.GetHeight());
- pCell->SetWidth(oStyle.m_oDisplay.GetWidth());
- pCell->SetPadding(oStyle.m_oPadding);
- pCell->SetBorder(oStyle.m_oBorder);
+ CalculateCellStyles(pCell, sSelectors);
while(m_oLightReader.MoveToNextAttribute())
{
@@ -2242,8 +2373,11 @@ private:
if(m_oLightReader.GetName() == L"th")
{
CTextSettings oTSR(oTS);
+ oTSR.sPStyle += L"";
oTSR.sRStyle += L"";
+ wrP(pCell->GetData(), sSelectors, oTS);
readStream(pCell->GetData(), sSelectors, oTSR);
+ CloseP(pCell->GetData(), sSelectors);
}
// Читаем td. Ячейка таблицы. Выравнивание вправо
else if(m_oLightReader.GetName() == L"td")
@@ -2291,7 +2425,7 @@ private:
{
if(m_oLightReader.IsEmptyNode())
return;
-
+
CTable oTable;
//Table styles
@@ -2327,6 +2461,8 @@ private:
oTable.SetAlign(oStyle.m_oDisplay.GetHAlign().ToWString());
//------
+ std::vector arCaptions;
+
int nDeath = m_oLightReader.GetDepth();
while(m_oLightReader.ReadNextSiblingNode(nDeath))
{
@@ -2334,35 +2470,79 @@ private:
GetSubClass(oXml, sSelectors);
// Заголовок таблицы
if(sName == L"caption")
- {
- if (!m_bInP)
- {
- oXml->WriteString(L"");
- for (const NSCSS::CNode& item : sSelectors)
- {
- if (item.m_wsName == L"a")
- oXml->WriteString(L"");
- }
- m_bInP = true;
- m_bWasPStyle = false;
- }
- // Заголовок таблицы выравнивание посередине
- CTextSettings oTSP(oTS);
- oTSP.sPStyle += L"";
- readStream(oXml, sSelectors, oTSP);
- if (m_bInP)
- m_bWasPStyle = false;
- CloseP(oXml, sSelectors);
- }
+ ParseTableCaption(oTable, sSelectors, oTS, arCaptions);
// if(sName == L"thead")
// readTr(&oHead, sSelectors, oTS, oTableStyles);
- else if(sName == L"tbody")
+ if(sName == L"tbody")
ParseTableRows(oTable, sSelectors, oTS);
// else if(sName == L"tfoot")
// readTr(&oFoot, sSelectors, oTS, oTableStyles);
sSelectors.pop_back();
}
+ if (!arCaptions.empty() && !oTable.Empty())
+ {
+ std::vector arUnnecessaryCaptions;
+
+ for (TTableCaption* pCaption : arCaptions)
+ {
+ if (0 == pCaption->m_unPrevRows || oTable.GetRowCount() == pCaption->m_unPrevRows)
+ {
+ arUnnecessaryCaptions.push_back(&pCaption->m_oData);
+ continue;
+ }
+
+ if (arUnnecessaryCaptions.empty() && !oTable.HaveCaption())
+ {
+ oTable.SetCaption(pCaption->m_oData);
+ continue;
+ }
+
+ CTableRow* pRow = oTable[pCaption->m_unPrevRows - 1];
+
+ if (NULL == pRow)
+ continue;
+
+ CTableCell *pCell = new CTableCell;
+
+ if (NULL == pCell)
+ continue;
+
+ pCell->GetData()->SetText(pCaption->m_oData.GetData());
+ pRow->AddCell(pCell);
+ }
+
+ if (!arUnnecessaryCaptions.empty())
+ {
+ oTable.SetCaption(*arUnnecessaryCaptions.back());
+ arUnnecessaryCaptions.pop_back();
+ }
+
+ if (!oTable.Empty())
+ {
+ CTableRow* pRow = oTable[0];
+ if (NULL != pRow)
+ {
+ CTableCell *pCell = (*pRow)[0];
+ if (NULL != pCell)
+ {
+ NSStringUtils::CStringBuilder oData;
+
+ for (NSStringUtils::CStringBuilder* pData : arUnnecessaryCaptions)
+ oData += pData->GetData();
+
+ arCaptions.clear();
+
+ oData += pCell->GetData()->GetData();
+ pCell->GetData()->SetText(oData.GetData());
+ }
+ }
+ }
+ }
+
+ for (TTableCaption* pCaption : arCaptions)
+ delete pCaption;
+
oTable.ApplyRowspan();
oTable.Shorten();
oTable.CompleteTable();
@@ -2958,12 +3138,12 @@ private:
NSCSS::CCompiledStyle oStyle = m_oStylesCalculator.GetCompiledStyle(sSelectors);
NSCSS::CCompiledStyle::StyleEquation(oStyle, oStyleSetting);
-
+
std::wstring sPStyle = GetStyle(oStyle, true);
- if (sPStyle.empty())
+ if (sPStyle.empty() && oTS.sPStyle.empty())
return L"";
-
+
m_oXmlStyle.WriteLitePStyle(oStyleSetting);
std::wstring sPSettings = m_oXmlStyle.GetStyle();
m_oXmlStyle.Clear();
@@ -2987,11 +3167,17 @@ private:
}
}
- oXml->WriteString(L"WriteString(sPStyle);
- oXml->WriteString(L"\"/>");
+ oXml->WriteNodeBegin(L"w:pPr");
+
+ if (!sPStyle.empty())
+ {
+ oXml->WriteString(L"WriteString(sPStyle);
+ oXml->WriteString(L"\"/>");
+ }
+
oXml->WriteString(oTS.sPStyle + L' ' + sPSettings);
- oXml->WriteString(L"");
+ oXml->WriteNodeEnd(L"w:pPr");
m_bWasPStyle = true;
return sPStyle;
}