summaryrefslogtreecommitdiff
path: root/content/handlers/html/box_normalise.c
diff options
context:
space:
mode:
Diffstat (limited to 'content/handlers/html/box_normalise.c')
-rw-r--r--content/handlers/html/box_normalise.c874
1 files changed, 412 insertions, 462 deletions
diff --git a/content/handlers/html/box_normalise.c b/content/handlers/html/box_normalise.c
index 7155cb722..03fe731b2 100644
--- a/content/handlers/html/box_normalise.c
+++ b/content/handlers/html/box_normalise.c
@@ -21,7 +21,7 @@
/**
* \file
- * Box tree normalisation (implementation).
+ * Box tree normalisation implementation.
*/
#include <assert.h>
@@ -33,6 +33,7 @@
#include "css/select.h"
#include "html/box.h"
+#include "html/box_normalise.h"
#include "html/html_internal.h"
#include "html/table.h"
@@ -66,279 +67,310 @@ struct columns {
};
-static bool box_normalise_table(
- struct box *table,
- const struct box *root,
- html_content *c);
-static bool box_normalise_table_spans(
- struct box *table,
- const struct box *root,
- struct span_info *spans,
- html_content *c);
-static bool box_normalise_table_row_group(
- struct box *row_group,
- const struct box *root,
- struct columns *col_info,
- html_content *c);
-static bool box_normalise_table_row(
- struct box *row,
- const struct box *root,
- struct columns *col_info,
- html_content *c);
-static bool calculate_table_row(struct columns *col_info,
- unsigned int col_span, unsigned int row_span,
- unsigned int *start_column, struct box *cell);
-static bool box_normalise_inline_container(
- struct box *cont,
- const struct box *root,
- html_content *c);
-
/**
- * Ensure the box tree is correctly nested by adding and removing nodes.
- *
- * \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL
- * \param root root box of document
- * \param c content of boxes
- * \return true on success, false on memory exhaustion
+ * Compute the column index at which the current cell begins.
+ * Additionally, update the column record to reflect row spanning.
*
- * The tree is modified to satisfy the following:
- * \code
- * parent permitted child nodes
- * BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE
- * INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, TEXT
- * INLINE, TEXT none
- * TABLE at least 1 TABLE_ROW_GROUP
- * TABLE_ROW_GROUP at least 1 TABLE_ROW
- * TABLE_ROW at least 1 TABLE_CELL
- * TABLE_CELL BLOCK, INLINE_CONTAINER, TABLE (same as BLOCK)
- * FLOAT_(LEFT|RIGHT) exactly 1 BLOCK or TABLE
- * \endcode
+ * \param col_info Column record
+ * \param col_span Number of columns that current cell spans
+ * \param row_span Number of rows that current cell spans
+ * \param start_column Pointer to location to receive column index
+ * \param cell Box for current table cell
+ * \return true on success, false on memory exhaustion
*/
+static bool
+calculate_table_row(struct columns *col_info,
+ unsigned int col_span,
+ unsigned int row_span,
+ unsigned int *start_column,
+ struct box *cell)
+{
+ unsigned int cell_start_col = col_info->current_column;
+ unsigned int cell_end_col;
+ unsigned int i;
+ struct span_info *spans;
+ struct box *rg = cell->parent->parent; /* Cell's row group */
+
+ /* Skip columns with cells spanning from above */
+ /* TODO: Need to ignore cells spanning from above that belong to
+ * different row group. We don't have that info here. */
+ while (col_info->spans[cell_start_col].row_span != 0 &&
+ col_info->spans[cell_start_col].rg == rg) {
+ cell_start_col++;
+ }
-bool box_normalise_block(
- struct box *block,
- const struct box *root,
- html_content *c)
+ /* Update current column with calculated start */
+ col_info->current_column = cell_start_col;
+
+ /* If this cell has a colspan of 0, then assume 1.
+ * No other browser supports colspan=0, anyway. */
+ if (col_span == 0)
+ col_span = 1;
+
+ cell_end_col = cell_start_col + col_span;
+
+ if (col_info->num_columns < cell_end_col) {
+ /* It appears that this row has more columns than
+ * the maximum recorded for the table so far.
+ * Allocate more span records. */
+ spans = realloc(col_info->spans,
+ sizeof *spans * (cell_end_col + 1));
+ if (spans == NULL)
+ return false;
+
+ col_info->spans = spans;
+ col_info->num_columns = cell_end_col;
+
+ /* Mark new final column as sentinel */
+ col_info->spans[cell_end_col].row_span = 0;
+ col_info->spans[cell_end_col].auto_row = false;
+ }
+
+ /* This cell may span multiple columns. If it also wants to span
+ * multiple rows, temporarily assume it spans 1 row only. This will
+ * be fixed up in box_normalise_table_spans() */
+ for (i = cell_start_col; i < cell_end_col; i++) {
+ col_info->spans[i].row_span = (row_span == 0) ? 1 : row_span;
+ col_info->spans[i].auto_row = (row_span == 0);
+ col_info->spans[i].rg = rg;
+ }
+
+ /* Update current column with calculated end. */
+ col_info->current_column = cell_end_col;
+
+ *start_column = cell_start_col;
+
+ return true;
+}
+
+
+static bool
+box_normalise_table_row(struct box *row,
+ const struct box *root,
+ struct columns *col_info,
+ html_content * c)
{
struct box *child;
struct box *next_child;
- struct box *table;
+ struct box *cell = NULL;
css_computed_style *style;
+ unsigned int i;
nscss_select_ctx ctx;
- assert(block != NULL);
- assert(root != NULL);
+ assert(row != NULL);
+ assert(row->type == BOX_TABLE_ROW);
ctx.root_style = root->style;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "block %p, block->type %u", block, block->type);
-#endif
-
- assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK ||
- block->type == BOX_TABLE_CELL);
-
- for (child = block->children; child != NULL; child = next_child) {
-#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "child %p, child->type = %d", child,
- child->type);
+ NSLOG(netsurf, INFO, "row %p", row);
#endif
- next_child = child->next; /* child may be destroyed */
+ for (child = row->children; child != NULL; child = next_child) {
+ next_child = child->next;
switch (child->type) {
- case BOX_BLOCK:
+ case BOX_TABLE_CELL:
/* ok */
if (box_normalise_block(child, root, c) == false)
return false;
+ cell = child;
break;
+ case BOX_BLOCK:
case BOX_INLINE_CONTAINER:
- if (box_normalise_inline_container(child, root, c) == false)
- return false;
- break;
case BOX_TABLE:
- if (box_normalise_table(child, root, c) == false)
- return false;
- break;
- case BOX_INLINE:
- case BOX_INLINE_END:
- case BOX_INLINE_BLOCK:
- case BOX_FLOAT_LEFT:
- case BOX_FLOAT_RIGHT:
- case BOX_BR:
- case BOX_TEXT:
- /* should have been wrapped in inline
- container by convert_xml_to_box() */
- assert(0);
- break;
case BOX_TABLE_ROW_GROUP:
case BOX_TABLE_ROW:
- case BOX_TABLE_CELL:
- /* insert implied table */
- assert(block->style != NULL);
+ /* insert implied table cell */
+ assert(row->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, block->style);
+ style = nscss_get_blank_style(&ctx, row->style);
if (style == NULL)
return false;
- table = box_create(NULL, style, true, block->href,
- block->target, NULL, NULL, c->bctx);
- if (table == NULL) {
+ cell = box_create(NULL, style, true, row->href,
+ row->target, NULL, NULL, c->bctx);
+ if (cell == NULL) {
css_computed_style_destroy(style);
return false;
}
- table->type = BOX_TABLE;
+ cell->type = BOX_TABLE_CELL;
if (child->prev == NULL)
- block->children = table;
+ row->children = cell;
else
- child->prev->next = table;
+ child->prev->next = cell;
- table->prev = child->prev;
+ cell->prev = child->prev;
while (child != NULL && (
+ child->type == BOX_BLOCK ||
+ child->type == BOX_INLINE_CONTAINER ||
+ child->type == BOX_TABLE ||
child->type == BOX_TABLE_ROW_GROUP ||
- child->type == BOX_TABLE_ROW ||
- child->type == BOX_TABLE_CELL)) {
- box_add_child(table, child);
+ child->type == BOX_TABLE_ROW)) {
+ box_add_child(cell, child);
next_child = child->next;
child->next = NULL;
child = next_child;
}
- table->last->next = NULL;
- table->next = next_child = child;
- if (table->next != NULL)
- table->next->prev = table;
+ assert(cell->last != NULL);
+
+ cell->last->next = NULL;
+ cell->next = next_child = child;
+ if (cell->next != NULL)
+ cell->next->prev = cell;
else
- block->last = table;
- table->parent = block;
+ row->last = cell;
+ cell->parent = row;
- if (box_normalise_table(table, root, c) == false)
+ if (box_normalise_block(cell, root, c) == false)
return false;
break;
+ case BOX_INLINE:
+ case BOX_INLINE_END:
+ case BOX_INLINE_BLOCK:
+ case BOX_FLOAT_LEFT:
+ case BOX_FLOAT_RIGHT:
+ case BOX_BR:
+ case BOX_TEXT:
+ /* should have been wrapped in inline
+ container by convert_xml_to_box() */
+ assert(0);
+ break;
default:
assert(0);
}
+
+ if (calculate_table_row(col_info, cell->columns, cell->rows,
+ &cell->start_column, cell) == false)
+ return false;
+ }
+
+
+ /* Update row spanning details for all columns */
+ for (i = 0; i < col_info->num_columns; i++) {
+ if (col_info->spans[i].row_span != 0 &&
+ col_info->spans[i].auto_row == false) {
+ /* This cell spans rows, and is not an auto row.
+ * Reduce number of rows left to span */
+ col_info->spans[i].row_span--;
+ }
}
+ /* Reset current column for next row */
+ col_info->current_column = 0;
+
+ /* Increment row counter */
+ col_info->num_rows++;
+
+#ifdef BOX_NORMALISE_DEBUG
+ NSLOG(netsurf, INFO, "row %p done", row);
+#endif
+
return true;
}
-bool box_normalise_table(
- struct box *table,
- const struct box *root,
- html_content * c)
+static bool
+box_normalise_table_row_group(struct box *row_group,
+ const struct box *root,
+ struct columns *col_info,
+ html_content * c)
{
struct box *child;
struct box *next_child;
- struct box *row_group;
+ struct box *row;
css_computed_style *style;
- struct columns col_info;
nscss_select_ctx ctx;
+ unsigned int group_row_count = 0;
- assert(table != NULL);
- assert(table->type == BOX_TABLE);
+ assert(row_group != 0);
+ assert(row_group->type == BOX_TABLE_ROW_GROUP);
ctx.root_style = root->style;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "table %p", table);
+ NSLOG(netsurf, INFO, "row_group %p", row_group);
#endif
- col_info.num_columns = 1;
- col_info.current_column = 0;
- col_info.spans = malloc(2 * sizeof *col_info.spans);
- if (col_info.spans == NULL)
- return false;
-
- col_info.spans[0].row_span = col_info.spans[1].row_span = 0;
- col_info.spans[0].auto_row = false;
- col_info.spans[1].auto_row = false;
- col_info.num_rows = 0;
-
- for (child = table->children; child != NULL; child = next_child) {
+ for (child = row_group->children; child != NULL; child = next_child) {
next_child = child->next;
+
switch (child->type) {
- case BOX_TABLE_ROW_GROUP:
+ case BOX_TABLE_ROW:
/* ok */
- if (box_normalise_table_row_group(child, root,
- &col_info, c) == false) {
- free(col_info.spans);
+ group_row_count++;
+ if (box_normalise_table_row(child, root, col_info,
+ c) == false)
return false;
- }
break;
case BOX_BLOCK:
case BOX_INLINE_CONTAINER:
case BOX_TABLE:
- case BOX_TABLE_ROW:
+ case BOX_TABLE_ROW_GROUP:
case BOX_TABLE_CELL:
- /* insert implied table row group */
- assert(table->style != NULL);
+ /* insert implied table row */
+ assert(row_group->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, table->style);
- if (style == NULL) {
- free(col_info.spans);
+ style = nscss_get_blank_style(&ctx, row_group->style);
+ if (style == NULL)
return false;
- }
- row_group = box_create(NULL, style, true, table->href,
- table->target, NULL, NULL, c->bctx);
- if (row_group == NULL) {
+ row = box_create(NULL, style, true, row_group->href,
+ row_group->target, NULL, NULL, c->bctx);
+ if (row == NULL) {
css_computed_style_destroy(style);
- free(col_info.spans);
return false;
}
-
- row_group->type = BOX_TABLE_ROW_GROUP;
+ row->type = BOX_TABLE_ROW;
if (child->prev == NULL)
- table->children = row_group;
+ row_group->children = row;
else
- child->prev->next = row_group;
+ child->prev->next = row;
- row_group->prev = child->prev;
+ row->prev = child->prev;
while (child != NULL && (
child->type == BOX_BLOCK ||
child->type == BOX_INLINE_CONTAINER ||
child->type == BOX_TABLE ||
- child->type == BOX_TABLE_ROW ||
+ child->type == BOX_TABLE_ROW_GROUP ||
child->type == BOX_TABLE_CELL)) {
- box_add_child(row_group, child);
+ box_add_child(row, child);
next_child = child->next;
child->next = NULL;
child = next_child;
}
- assert(row_group->last != NULL);
+ assert(row->last != NULL);
- row_group->last->next = NULL;
- row_group->next = next_child = child;
- if (row_group->next != NULL)
- row_group->next->prev = row_group;
+ row->last->next = NULL;
+ row->next = next_child = child;
+ if (row->next != NULL)
+ row->next->prev = row;
else
- table->last = row_group;
- row_group->parent = table;
+ row_group->last = row;
+ row->parent = row_group;
- if (box_normalise_table_row_group(row_group, root,
- &col_info, c) == false) {
- free(col_info.spans);
+ group_row_count++;
+ if (box_normalise_table_row(row, root, col_info,
+ c) == false)
return false;
- }
break;
case BOX_INLINE:
case BOX_INLINE_END:
@@ -352,48 +384,25 @@ bool box_normalise_table(
assert(0);
break;
default:
- fprintf(stderr, "%i\n", child->type);
assert(0);
}
}
- table->columns = col_info.num_columns;
- table->rows = col_info.num_rows;
-
- if (table->children == NULL) {
- struct box *row;
-
+ if (row_group->children == NULL) {
#ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO,
- "table->children == 0, creating implied row");
+ "row_group->children == 0, inserting implied row");
#endif
- assert(table->style != NULL);
+ assert(row_group->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, table->style);
- if (style == NULL) {
- free(col_info.spans);
- return false;
- }
-
- row_group = box_create(NULL, style, true, table->href,
- table->target, NULL, NULL, c->bctx);
- if (row_group == NULL) {
- css_computed_style_destroy(style);
- free(col_info.spans);
- return false;
- }
- row_group->type = BOX_TABLE_ROW_GROUP;
-
style = nscss_get_blank_style(&ctx, row_group->style);
if (style == NULL) {
- box_free(row_group);
- free(col_info.spans);
return false;
}
@@ -401,8 +410,6 @@ bool box_normalise_table(
row_group->target, NULL, NULL, c->bctx);
if (row == NULL) {
css_computed_style_destroy(style);
- box_free(row_group);
- free(col_info.spans);
return false;
}
row->type = BOX_TABLE_ROW;
@@ -410,21 +417,16 @@ bool box_normalise_table(
row->parent = row_group;
row_group->children = row_group->last = row;
- row_group->parent = table;
- table->children = table->last = row_group;
-
- table->rows = 1;
- }
+ group_row_count = 1;
- if (box_normalise_table_spans(table, root, col_info.spans, c) == false) {
- free(col_info.spans);
- return false;
+ /* Keep table's row count in sync */
+ col_info->num_rows++;
}
- free(col_info.spans);
+ row_group->rows = group_row_count;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "table %p done", table);
+ NSLOG(netsurf, INFO, "row_group %p done", row_group);
#endif
return true;
@@ -441,12 +443,11 @@ bool box_normalise_table(
* \param c Content containing table
* \return True on success, false on memory exhaustion.
*/
-
-bool box_normalise_table_spans(
- struct box *table,
- const struct box *root,
- struct span_info *spans,
- html_content *c)
+static bool
+box_normalise_table_spans(struct box *table,
+ const struct box *root,
+ struct span_info *spans,
+ html_content *c)
{
struct box *table_row_group;
struct box *table_row;
@@ -601,98 +602,111 @@ bool box_normalise_table_spans(
}
-bool box_normalise_table_row_group(
- struct box *row_group,
- const struct box *root,
- struct columns *col_info,
- html_content * c)
+static bool
+box_normalise_table(struct box *table, const struct box *root, html_content * c)
{
struct box *child;
struct box *next_child;
- struct box *row;
+ struct box *row_group;
css_computed_style *style;
+ struct columns col_info;
nscss_select_ctx ctx;
- unsigned int group_row_count = 0;
- assert(row_group != 0);
- assert(row_group->type == BOX_TABLE_ROW_GROUP);
+ assert(table != NULL);
+ assert(table->type == BOX_TABLE);
ctx.root_style = root->style;
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "row_group %p", row_group);
+ NSLOG(netsurf, INFO, "table %p", table);
#endif
- for (child = row_group->children; child != NULL; child = next_child) {
- next_child = child->next;
+ col_info.num_columns = 1;
+ col_info.current_column = 0;
+ col_info.spans = malloc(2 * sizeof *col_info.spans);
+ if (col_info.spans == NULL)
+ return false;
+ col_info.spans[0].row_span = col_info.spans[1].row_span = 0;
+ col_info.spans[0].auto_row = false;
+ col_info.spans[1].auto_row = false;
+ col_info.num_rows = 0;
+
+ for (child = table->children; child != NULL; child = next_child) {
+ next_child = child->next;
switch (child->type) {
- case BOX_TABLE_ROW:
+ case BOX_TABLE_ROW_GROUP:
/* ok */
- group_row_count++;
- if (box_normalise_table_row(child, root, col_info,
- c) == false)
+ if (box_normalise_table_row_group(child, root,
+ &col_info, c) == false) {
+ free(col_info.spans);
return false;
+ }
break;
case BOX_BLOCK:
case BOX_INLINE_CONTAINER:
case BOX_TABLE:
- case BOX_TABLE_ROW_GROUP:
+ case BOX_TABLE_ROW:
case BOX_TABLE_CELL:
- /* insert implied table row */
- assert(row_group->style != NULL);
+ /* insert implied table row group */
+ assert(table->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
- style = nscss_get_blank_style(&ctx, row_group->style);
- if (style == NULL)
+ style = nscss_get_blank_style(&ctx, table->style);
+ if (style == NULL) {
+ free(col_info.spans);
return false;
+ }
- row = box_create(NULL, style, true, row_group->href,
- row_group->target, NULL, NULL, c->bctx);
- if (row == NULL) {
+ row_group = box_create(NULL, style, true, table->href,
+ table->target, NULL, NULL, c->bctx);
+ if (row_group == NULL) {
css_computed_style_destroy(style);
+ free(col_info.spans);
return false;
}
- row->type = BOX_TABLE_ROW;
+
+ row_group->type = BOX_TABLE_ROW_GROUP;
if (child->prev == NULL)
- row_group->children = row;
+ table->children = row_group;
else
- child->prev->next = row;
+ child->prev->next = row_group;
- row->prev = child->prev;
+ row_group->prev = child->prev;
while (child != NULL && (
child->type == BOX_BLOCK ||
child->type == BOX_INLINE_CONTAINER ||
child->type == BOX_TABLE ||
- child->type == BOX_TABLE_ROW_GROUP ||
+ child->type == BOX_TABLE_ROW ||
child->type == BOX_TABLE_CELL)) {
- box_add_child(row, child);
+ box_add_child(row_group, child);
next_child = child->next;
child->next = NULL;
child = next_child;
}
- assert(row->last != NULL);
+ assert(row_group->last != NULL);
- row->last->next = NULL;
- row->next = next_child = child;
- if (row->next != NULL)
- row->next->prev = row;
+ row_group->last->next = NULL;
+ row_group->next = next_child = child;
+ if (row_group->next != NULL)
+ row_group->next->prev = row_group;
else
- row_group->last = row;
- row->parent = row_group;
+ table->last = row_group;
+ row_group->parent = table;
- group_row_count++;
- if (box_normalise_table_row(row, root, col_info,
- c) == false)
+ if (box_normalise_table_row_group(row_group, root,
+ &col_info, c) == false) {
+ free(col_info.spans);
return false;
+ }
break;
case BOX_INLINE:
case BOX_INLINE_END:
@@ -706,25 +720,48 @@ bool box_normalise_table_row_group(
assert(0);
break;
default:
+ fprintf(stderr, "%i\n", child->type);
assert(0);
}
}
- if (row_group->children == NULL) {
+ table->columns = col_info.num_columns;
+ table->rows = col_info.num_rows;
+
+ if (table->children == NULL) {
+ struct box *row;
+
#ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO,
- "row_group->children == 0, inserting implied row");
+ "table->children == 0, creating implied row");
#endif
- assert(row_group->style != NULL);
+ assert(table->style != NULL);
ctx.ctx = c->select_ctx;
ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
ctx.base_url = c->base_url;
ctx.universal = c->universal;
+ style = nscss_get_blank_style(&ctx, table->style);
+ if (style == NULL) {
+ free(col_info.spans);
+ return false;
+ }
+
+ row_group = box_create(NULL, style, true, table->href,
+ table->target, NULL, NULL, c->bctx);
+ if (row_group == NULL) {
+ css_computed_style_destroy(style);
+ free(col_info.spans);
+ return false;
+ }
+ row_group->type = BOX_TABLE_ROW_GROUP;
+
style = nscss_get_blank_style(&ctx, row_group->style);
if (style == NULL) {
+ box_free(row_group);
+ free(col_info.spans);
return false;
}
@@ -732,6 +769,8 @@ bool box_normalise_table_row_group(
row_group->target, NULL, NULL, c->bctx);
if (row == NULL) {
css_computed_style_destroy(style);
+ box_free(row_group);
+ free(col_info.spans);
return false;
}
row->type = BOX_TABLE_ROW;
@@ -739,236 +778,31 @@ bool box_normalise_table_row_group(
row->parent = row_group;
row_group->children = row_group->last = row;
- group_row_count = 1;
-
- /* Keep table's row count in sync */
- col_info->num_rows++;
- }
-
- row_group->rows = group_row_count;
-
-#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "row_group %p done", row_group);
-#endif
-
- return true;
-}
-
-
-bool box_normalise_table_row(
- struct box *row,
- const struct box *root,
- struct columns *col_info,
- html_content * c)
-{
- struct box *child;
- struct box *next_child;
- struct box *cell = NULL;
- css_computed_style *style;
- unsigned int i;
- nscss_select_ctx ctx;
-
- assert(row != NULL);
- assert(row->type == BOX_TABLE_ROW);
-
- ctx.root_style = root->style;
-
-#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "row %p", row);
-#endif
-
- for (child = row->children; child != NULL; child = next_child) {
- next_child = child->next;
-
- switch (child->type) {
- case BOX_TABLE_CELL:
- /* ok */
- if (box_normalise_block(child, root, c) == false)
- return false;
- cell = child;
- break;
- case BOX_BLOCK:
- case BOX_INLINE_CONTAINER:
- case BOX_TABLE:
- case BOX_TABLE_ROW_GROUP:
- case BOX_TABLE_ROW:
- /* insert implied table cell */
- assert(row->style != NULL);
-
- ctx.ctx = c->select_ctx;
- ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
- ctx.base_url = c->base_url;
- ctx.universal = c->universal;
-
- style = nscss_get_blank_style(&ctx, row->style);
- if (style == NULL)
- return false;
-
- cell = box_create(NULL, style, true, row->href,
- row->target, NULL, NULL, c->bctx);
- if (cell == NULL) {
- css_computed_style_destroy(style);
- return false;
- }
- cell->type = BOX_TABLE_CELL;
-
- if (child->prev == NULL)
- row->children = cell;
- else
- child->prev->next = cell;
-
- cell->prev = child->prev;
-
- while (child != NULL && (
- child->type == BOX_BLOCK ||
- child->type == BOX_INLINE_CONTAINER ||
- child->type == BOX_TABLE ||
- child->type == BOX_TABLE_ROW_GROUP ||
- child->type == BOX_TABLE_ROW)) {
- box_add_child(cell, child);
-
- next_child = child->next;
- child->next = NULL;
- child = next_child;
- }
-
- assert(cell->last != NULL);
-
- cell->last->next = NULL;
- cell->next = next_child = child;
- if (cell->next != NULL)
- cell->next->prev = cell;
- else
- row->last = cell;
- cell->parent = row;
-
- if (box_normalise_block(cell, root, c) == false)
- return false;
- break;
- case BOX_INLINE:
- case BOX_INLINE_END:
- case BOX_INLINE_BLOCK:
- case BOX_FLOAT_LEFT:
- case BOX_FLOAT_RIGHT:
- case BOX_BR:
- case BOX_TEXT:
- /* should have been wrapped in inline
- container by convert_xml_to_box() */
- assert(0);
- break;
- default:
- assert(0);
- }
+ row_group->parent = table;
+ table->children = table->last = row_group;
- if (calculate_table_row(col_info, cell->columns, cell->rows,
- &cell->start_column, cell) == false)
- return false;
+ table->rows = 1;
}
-
- /* Update row spanning details for all columns */
- for (i = 0; i < col_info->num_columns; i++) {
- if (col_info->spans[i].row_span != 0 &&
- col_info->spans[i].auto_row == false) {
- /* This cell spans rows, and is not an auto row.
- * Reduce number of rows left to span */
- col_info->spans[i].row_span--;
- }
+ if (box_normalise_table_spans(table, root, col_info.spans, c) == false) {
+ free(col_info.spans);
+ return false;
}
- /* Reset current column for next row */
- col_info->current_column = 0;
-
- /* Increment row counter */
- col_info->num_rows++;
+ free(col_info.spans);
#ifdef BOX_NORMALISE_DEBUG
- NSLOG(netsurf, INFO, "row %p done", row);
+ NSLOG(netsurf, INFO, "table %p done", table);
#endif
return true;
}
-/**
- * Compute the column index at which the current cell begins.
- * Additionally, update the column record to reflect row spanning.
- *
- * \param col_info Column record
- * \param col_span Number of columns that current cell spans
- * \param row_span Number of rows that current cell spans
- * \param start_column Pointer to location to receive column index
- * \param cell Box for current table cell
- * \return true on success, false on memory exhaustion
- */
-
-bool calculate_table_row(struct columns *col_info,
- unsigned int col_span, unsigned int row_span,
- unsigned int *start_column, struct box *cell)
-{
- unsigned int cell_start_col = col_info->current_column;
- unsigned int cell_end_col;
- unsigned int i;
- struct span_info *spans;
- struct box *rg = cell->parent->parent; /* Cell's row group */
-
- /* Skip columns with cells spanning from above */
- /* TODO: Need to ignore cells spanning from above that belong to
- * different row group. We don't have that info here. */
- while (col_info->spans[cell_start_col].row_span != 0 &&
- col_info->spans[cell_start_col].rg == rg) {
- cell_start_col++;
- }
-
- /* Update current column with calculated start */
- col_info->current_column = cell_start_col;
-
- /* If this cell has a colspan of 0, then assume 1.
- * No other browser supports colspan=0, anyway. */
- if (col_span == 0)
- col_span = 1;
-
- cell_end_col = cell_start_col + col_span;
-
- if (col_info->num_columns < cell_end_col) {
- /* It appears that this row has more columns than
- * the maximum recorded for the table so far.
- * Allocate more span records. */
- spans = realloc(col_info->spans,
- sizeof *spans * (cell_end_col + 1));
- if (spans == NULL)
- return false;
-
- col_info->spans = spans;
- col_info->num_columns = cell_end_col;
-
- /* Mark new final column as sentinel */
- col_info->spans[cell_end_col].row_span = 0;
- col_info->spans[cell_end_col].auto_row = false;
- }
-
- /* This cell may span multiple columns. If it also wants to span
- * multiple rows, temporarily assume it spans 1 row only. This will
- * be fixed up in box_normalise_table_spans() */
- for (i = cell_start_col; i < cell_end_col; i++) {
- col_info->spans[i].row_span = (row_span == 0) ? 1 : row_span;
- col_info->spans[i].auto_row = (row_span == 0);
- col_info->spans[i].rg = rg;
- }
-
- /* Update current column with calculated end. */
- col_info->current_column = cell_end_col;
-
- *start_column = cell_start_col;
-
- return true;
-}
-
-
-bool box_normalise_inline_container(
- struct box *cont,
- const struct box *root,
- html_content * c)
+static bool
+box_normalise_inline_container(struct box *cont,
+ const struct box *root,
+ html_content * c)
{
struct box *child;
struct box *next_child;
@@ -1045,3 +879,119 @@ bool box_normalise_inline_container(
return true;
}
+
+
+/* Exported function documented in html/box_normalise.h */
+bool
+box_normalise_block(struct box *block, const struct box *root, html_content *c)
+{
+ struct box *child;
+ struct box *next_child;
+ struct box *table;
+ css_computed_style *style;
+ nscss_select_ctx ctx;
+
+ assert(block != NULL);
+ assert(root != NULL);
+
+ ctx.root_style = root->style;
+
+#ifdef BOX_NORMALISE_DEBUG
+ NSLOG(netsurf, INFO, "block %p, block->type %u", block, block->type);
+#endif
+
+ assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK ||
+ block->type == BOX_TABLE_CELL);
+
+ for (child = block->children; child != NULL; child = next_child) {
+#ifdef BOX_NORMALISE_DEBUG
+ NSLOG(netsurf, INFO, "child %p, child->type = %d", child,
+ child->type);
+#endif
+
+ next_child = child->next; /* child may be destroyed */
+
+ switch (child->type) {
+ case BOX_BLOCK:
+ /* ok */
+ if (box_normalise_block(child, root, c) == false)
+ return false;
+ break;
+ case BOX_INLINE_CONTAINER:
+ if (box_normalise_inline_container(child, root, c) == false)
+ return false;
+ break;
+ case BOX_TABLE:
+ if (box_normalise_table(child, root, c) == false)
+ return false;
+ break;
+ case BOX_INLINE:
+ case BOX_INLINE_END:
+ case BOX_INLINE_BLOCK:
+ case BOX_FLOAT_LEFT:
+ case BOX_FLOAT_RIGHT:
+ case BOX_BR:
+ case BOX_TEXT:
+ /* should have been wrapped in inline
+ container by convert_xml_to_box() */
+ assert(0);
+ break;
+ case BOX_TABLE_ROW_GROUP:
+ case BOX_TABLE_ROW:
+ case BOX_TABLE_CELL:
+ /* insert implied table */
+ assert(block->style != NULL);
+
+ ctx.ctx = c->select_ctx;
+ ctx.quirks = (c->quirks == DOM_DOCUMENT_QUIRKS_MODE_FULL);
+ ctx.base_url = c->base_url;
+ ctx.universal = c->universal;
+
+ style = nscss_get_blank_style(&ctx, block->style);
+ if (style == NULL)
+ return false;
+
+ table = box_create(NULL, style, true, block->href,
+ block->target, NULL, NULL, c->bctx);
+ if (table == NULL) {
+ css_computed_style_destroy(style);
+ return false;
+ }
+ table->type = BOX_TABLE;
+
+ if (child->prev == NULL)
+ block->children = table;
+ else
+ child->prev->next = table;
+
+ table->prev = child->prev;
+
+ while (child != NULL && (
+ child->type == BOX_TABLE_ROW_GROUP ||
+ child->type == BOX_TABLE_ROW ||
+ child->type == BOX_TABLE_CELL)) {
+ box_add_child(table, child);
+
+ next_child = child->next;
+ child->next = NULL;
+ child = next_child;
+ }
+
+ table->last->next = NULL;
+ table->next = next_child = child;
+ if (table->next != NULL)
+ table->next->prev = table;
+ else
+ block->last = table;
+ table->parent = block;
+
+ if (box_normalise_table(table, root, c) == false)
+ return false;
+ break;
+ default:
+ assert(0);
+ }
+ }
+
+ return true;
+}