HTML: Honor TABLE ALIGN as table placement

Apply TABLE ALIGN to the wrapper that positions the table instead of
using it as the default alignment for TD/TH content. Leave cell text
alignment controlled by row/cell alignment, with the existing TH default.

Add a parser layout regression test and sample markup for the centered
table case.

Fixes #21853.

Closes #26672.
This commit is contained in:
Richard
2026-07-20 20:23:34 +02:00
committed by Vadim Zeitlin
parent 34191600f2
commit 4e9b924ec6
3 changed files with 101 additions and 6 deletions
+9
View File
@@ -34,6 +34,15 @@ tests page...</H3>
</TR>
</TABLE></CENTER>
<P>TABLE ALIGN moves the table, not the cell text:
<BR>&nbsp;
<TABLE BORDER ALIGN=CENTER WIDTH="40%">
<TR>
<TD>Left-aligned cell text</TD>
<TD>More text</TD>
</TR>
</TABLE>
<P>Subsampling is shown there:
<BR>&nbsp;
<TABLE BORDER COLS=2 WIDTH="100%" NOSAVE >
+23 -6
View File
@@ -3,6 +3,7 @@
// Purpose: wxHtml module for tables
// Author: Vaclav Slavik
// Copyright: (c) 1999 Vaclav Slavik
// (c) 2026 wxWidgets development team
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
@@ -683,9 +684,25 @@ TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")
TAG_HANDLER_VARS
wxHtmlTableCell* m_Table;
wxString m_tAlign, m_rAlign;
wxString m_rAlign;
wxHtmlContainerCell *m_enclosingContainer;
void SetTableAlignment(wxHtmlContainerCell *c, const wxHtmlTag& tag)
{
wxString align;
if ( !tag.GetParamAsString("ALIGN", &align) )
return;
align.MakeUpper();
if ( align == "RIGHT" )
c->SetAlignHor(wxHTML_ALIGN_RIGHT);
else if ( align == "LEFT" )
c->SetAlignHor(wxHTML_ALIGN_LEFT);
else if ( align == "CENTER" )
c->SetAlignHor(wxHTML_ALIGN_CENTER);
}
// Call ParseInner() preserving background colour and mode after any
// changes done by it.
void CallParseInnerWithBg(const wxHtmlTag& tag, const wxColour& colBg)
@@ -721,7 +738,6 @@ TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")
{
m_Table = nullptr;
m_enclosingContainer = nullptr;
m_tAlign.clear();
m_rAlign.clear();
}
@@ -734,9 +750,11 @@ TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")
if (tag.GetName() == wxT("TABLE"))
{
wxHtmlTableCell *oldt = m_Table;
const wxString oldRowAlign = m_rAlign;
wxHtmlContainerCell *oldEnclosing = m_enclosingContainer;
m_enclosingContainer = c = m_WParser->OpenContainer();
SetTableAlignment(c, tag);
m_Table = new wxHtmlTableCell(c, tag, m_WParser->GetPixelScale());
@@ -759,8 +777,6 @@ TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")
m_Table->SetWidthFloat(0, wxHTML_UNITS_PIXELS);
}
int oldAlign = m_WParser->GetAlign();
if (!tag.GetParamAsString(wxT("ALIGN"), &m_tAlign))
m_tAlign.clear();
CallParseInnerWithBg(tag, m_Table->GetBackgroundColour());
@@ -769,6 +785,7 @@ TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")
m_WParser->CloseContainer();
m_Table = oldt;
m_rAlign = oldRowAlign;
m_enclosingContainer = oldEnclosing;
return true; // ParseInner() called
@@ -781,8 +798,8 @@ TAG_HANDLER_BEGIN(TABLE, "TABLE,TR,TD,TH")
if (tag.GetName() == wxT("TR"))
{
m_Table->AddRow(tag);
if (!tag.GetParamAsString(wxT("ALIGN"), &m_rAlign))
m_rAlign = m_tAlign;
if ( !tag.GetParamAsString("ALIGN", &m_rAlign) )
m_rAlign.clear();
}
// new cell
+69
View File
@@ -17,6 +17,7 @@
#ifndef WX_PRECOMP
#include "wx/bitmap.h"
#include "wx/dcmemory.h"
#include "wx/log.h"
#endif // WX_PRECOMP
@@ -25,6 +26,20 @@
#include <memory>
namespace
{
const wxHtmlCell *GetFirstNonFormattingChild(const wxHtmlContainerCell *cell)
{
const wxHtmlCell *child = cell->GetFirstChild();
while ( child && child->IsFormattingCell() )
child = child->GetNext();
return child;
}
} // anonymous namespace
// Test that parsing invalid HTML simply fails but doesn't crash for example.
TEST_CASE("wxHtmlParser::ParseInvalid", "[html][parser][error]")
{
@@ -134,4 +149,58 @@ TEST_CASE("wxHtmlCell::Detach", "[html][cell]")
}
}
TEST_CASE("wxHtmlParser::TableAlign", "[html][parser][table]")
{
wxBitmap bmp(400, 400);
wxMemoryDC dc(bmp);
wxHtmlWinParser parser;
parser.SetDC(&dc);
std::unique_ptr<wxHtmlContainerCell> const root(
static_cast<wxHtmlContainerCell*>(
parser.Parse(
"<table align=\"center\"><tr><td>test</td><td>ok</td></tr></table>"
)
)
);
REQUIRE( root );
root->Layout(200);
const wxHtmlCell *cell = GetFirstNonFormattingChild(root.get());
REQUIRE( cell );
const wxHtmlContainerCell *body =
static_cast<const wxHtmlContainerCell*>(cell);
cell = GetFirstNonFormattingChild(body);
REQUIRE( cell );
const wxHtmlContainerCell *tableWrapper =
static_cast<const wxHtmlContainerCell*>(cell);
cell = GetFirstNonFormattingChild(tableWrapper);
REQUIRE( cell );
const wxHtmlContainerCell *table =
static_cast<const wxHtmlContainerCell*>(cell);
CHECK( table->GetPosX() > 0 );
cell = GetFirstNonFormattingChild(table);
REQUIRE( cell );
const wxHtmlContainerCell *td =
static_cast<const wxHtmlContainerCell*>(cell);
cell = GetFirstNonFormattingChild(td);
REQUIRE( cell );
const wxHtmlContainerCell *tdContent =
static_cast<const wxHtmlContainerCell*>(cell);
CHECK( tdContent->GetAlignHor() == wxHTML_ALIGN_LEFT );
}
#endif //wxUSE_HTML