summaryrefslogtreecommitdiff
path: root/render/box_normalise.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/box_normalise.c')
-rw-r--r--render/box_normalise.c637
1 files changed, 386 insertions, 251 deletions
diff --git a/render/box_normalise.c b/render/box_normalise.c
index 865433e26..fc563e743 100644
--- a/render/box_normalise.c
+++ b/render/box_normalise.c
@@ -26,6 +26,7 @@
#include <assert.h>
#include <stdbool.h>
#include "css/css.h"
+#include "css/select.h"
#include "render/box.h"
#include "render/table.h"
#include "desktop/gui.h"
@@ -35,29 +36,34 @@
#include "utils/talloc.h"
+/**
+ * Row spanning information for a cell
+ */
struct span_info {
+ /** Number of rows this cell spans */
unsigned int row_span;
+ /** The cell in this column spans all rows until the end of the table */
bool auto_row;
- bool auto_column;
};
+/**
+ * Column record for a table
+ */
struct columns {
+ /** Current column index */
unsigned int current_column;
- bool extra;
- /* Number of columns in main part of table 1..max columns */
+ /** Number of columns in main part of table 1..max columns */
unsigned int num_columns;
- /* Information about columns in main table,
- array 0 to num_columns - 1 */
+ /** Information about columns in main table, array [0, num_columns) */
struct span_info *spans;
- /* Number of columns that have cells after a colspan 0 */
- unsigned int extra_columns;
- /* Number of rows in table */
+ /** Number of rows in table */
unsigned int num_rows;
};
static bool box_normalise_table(struct box *table, struct content *c);
-static void box_normalise_table_spans(struct box *table);
+static bool box_normalise_table_spans(struct box *table,
+ struct span_info *spans, struct content *c);
static bool box_normalise_table_row_group(struct box *row_group,
struct columns *col_info,
struct content *c);
@@ -69,6 +75,18 @@ static bool calculate_table_row(struct columns *col_info,
unsigned int *start_column);
static bool box_normalise_inline_container(struct box *cont, struct content *c);
+/**
+ * Allocator
+ *
+ * \param ptr Pointer to reallocate, or NULL for new allocation
+ * \param size Number of bytes requires
+ * \param pw Allocation context
+ * \return Pointer to allocated block, or NULL on failure
+ */
+static void *myrealloc(void *ptr, size_t len, void *pw)
+{
+ return talloc_realloc_size(pw, ptr, len);
+}
/**
* Ensure the box tree is correctly nested by adding and removing nodes.
@@ -96,30 +114,34 @@ bool box_normalise_block(struct box *block, struct content *c)
struct box *child;
struct box *next_child;
struct box *table;
- struct css_style *style;
+ css_computed_style *style;
+
+ assert(block != NULL);
- assert(block != 0);
LOG(("block %p, block->type %u", block, block->type));
+
assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK ||
block->type == BOX_TABLE_CELL);
+
gui_multitask();
- for (child = block->children; child != 0; child = next_child) {
+ for (child = block->children; child != NULL; child = next_child) {
LOG(("child %p, child->type = %d", child, child->type));
+
next_child = child->next; /* child may be destroyed */
+
switch (child->type) {
case BOX_BLOCK:
/* ok */
- if (!box_normalise_block(child, c))
+ if (box_normalise_block(child, c) == false)
return false;
break;
case BOX_INLINE_CONTAINER:
- if (!box_normalise_inline_container(child,
- c))
+ if (box_normalise_inline_container(child, c) == false)
return false;
break;
case BOX_TABLE:
- if (!box_normalise_table(child, c))
+ if (box_normalise_table(child, c) == false)
return false;
break;
case BOX_INLINE:
@@ -137,37 +159,48 @@ bool box_normalise_block(struct box *block, struct content *c)
case BOX_TABLE_ROW:
case BOX_TABLE_CELL:
/* insert implied table */
- style = talloc_memdup(c, block->style, sizeof *style);
- if (!style)
+ assert(block->style != NULL);
+
+ style = nscss_get_blank_style(c, block->style,
+ myrealloc, c);
+ if (style == NULL)
return false;
- css_cascade(style, &css_blank_style, NULL);
+
table = box_create(style, block->href, block->target,
- 0, 0, c);
- if (!table) {
- talloc_free(style);
+ NULL, NULL, c);
+ if (table == NULL) {
+ css_computed_style_destroy(style);
return false;
}
table->type = BOX_TABLE;
- if (child->prev == 0)
+
+ if (child->prev == NULL)
block->children = table;
else
child->prev->next = table;
+
table->prev = child->prev;
- while (child != 0 && (
+
+ 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 = 0;
+ child->next = NULL;
child = next_child;
}
- table->last->next = 0;
+
+ table->last->next = NULL;
table->next = next_child = child;
- if (table->next)
+ if (table->next != NULL)
table->next->prev = table;
+ else
+ block->last = table;
table->parent = block;
- if (!box_normalise_table(table, c))
+
+ if (box_normalise_table(table, c) == false)
return false;
break;
default:
@@ -184,30 +217,32 @@ bool box_normalise_table(struct box *table, struct content * c)
struct box *child;
struct box *next_child;
struct box *row_group;
- struct css_style *style;
+ css_computed_style *style;
struct columns col_info;
- assert(table != 0);
+ assert(table != NULL);
assert(table->type == BOX_TABLE);
+
LOG(("table %p", table));
+
col_info.num_columns = 1;
col_info.current_column = 0;
col_info.spans = malloc(2 * sizeof *col_info.spans);
- if (!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 = col_info.spans[0].auto_column =
- col_info.spans[1].auto_row = col_info.spans[1].auto_column = false;
- col_info.num_rows = col_info.extra_columns = 0;
- col_info.extra = false;
+ col_info.spans[0].auto_row = false;
+ col_info.spans[1].auto_row = false;
+ col_info.num_rows = 0;
- for (child = table->children; child != 0; child = next_child) {
+ for (child = table->children; child != NULL; child = next_child) {
next_child = child->next;
switch (child->type) {
case BOX_TABLE_ROW_GROUP:
/* ok */
- if (!box_normalise_table_row_group(child,
- &col_info, c)) {
+ if (box_normalise_table_row_group(child,
+ &col_info, c) == false) {
free(col_info.spans);
return false;
}
@@ -219,46 +254,56 @@ bool box_normalise_table(struct box *table, struct content * c)
case BOX_TABLE_CELL:
/* insert implied table row group */
assert(table->style != NULL);
- style = talloc_memdup(c, table->style, sizeof *style);
- if (!style) {
+
+ style = nscss_get_blank_style(c, table->style,
+ myrealloc, c);
+ if (style == NULL) {
free(col_info.spans);
return false;
}
- css_cascade(style, &css_blank_style, NULL);
+
row_group = box_create(style, table->href,
- table->target, 0, 0, c);
- if (!row_group) {
+ table->target, NULL, NULL, c);
+ if (row_group == NULL) {
+ css_computed_style_destroy(style);
free(col_info.spans);
- talloc_free(style);
return false;
}
+
row_group->type = BOX_TABLE_ROW_GROUP;
- if (child->prev == 0)
+
+ if (child->prev == NULL)
table->children = row_group;
else
child->prev->next = row_group;
+
row_group->prev = child->prev;
- while (child != 0 && (
+
+ 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_CELL)) {
box_add_child(row_group, child);
+
next_child = child->next;
- child->next = 0;
+ child->next = NULL;
child = next_child;
}
+
assert(row_group->last != NULL);
- row_group->last->next = 0;
+
+ row_group->last->next = NULL;
row_group->next = next_child = child;
- if (row_group->next)
+ if (row_group->next != NULL)
row_group->next->prev = row_group;
else
table->last = row_group;
row_group->parent = table;
- if (!box_normalise_table_row_group(row_group,
- &col_info, c)) {
+
+ if (box_normalise_table_row_group(row_group,
+ &col_info, c) == false) {
free(col_info.spans);
return false;
}
@@ -282,38 +327,43 @@ bool box_normalise_table(struct box *table, struct content * c)
table->columns = col_info.num_columns;
table->rows = col_info.num_rows;
- free(col_info.spans);
- if (table->children == 0) {
+ if (table->children == NULL) {
struct box *row;
LOG(("table->children == 0, creating implied row"));
assert(table->style != NULL);
- style = talloc_memdup(c, table->style, sizeof *style);
- if (!style) {
+
+ style = nscss_get_blank_style(c, table->style, myrealloc, c);
+ if (style == NULL) {
+ free(col_info.spans);
return false;
}
- css_cascade(style, &css_blank_style, NULL);
+
row_group = box_create(style, table->href,
- table->target, 0, 0, c);
- if (!row_group) {
- talloc_free(style);
+ table->target, NULL, NULL, c);
+ if (row_group == NULL) {
+ css_computed_style_destroy(style);
+ free(col_info.spans);
return false;
}
row_group->type = BOX_TABLE_ROW_GROUP;
- style = talloc_memdup(c, row_group->style, sizeof *style);
- if (!style) {
+ style = nscss_get_blank_style(c, row_group->style,
+ myrealloc, c);
+ if (style == NULL) {
box_free(row_group);
+ free(col_info.spans);
return false;
}
- css_cascade(style, &css_blank_style, NULL);
+
row = box_create(style, row_group->href,
- row_group->target, 0, 0, c);
- if (!row) {
- talloc_free(style);
+ row_group->target, NULL, NULL, c);
+ if (row == NULL) {
+ css_computed_style_destroy(style);
box_free(row_group);
+ free(col_info.spans);
return false;
}
row->type = BOX_TABLE_ROW;
@@ -327,11 +377,15 @@ bool box_normalise_table(struct box *table, struct content * c)
table->rows = 1;
}
- box_normalise_table_spans(table);
- if (!table_calculate_column_types(table))
+ if (box_normalise_table_spans(table, col_info.spans, c) == false) {
+ free(col_info.spans);
+ return false;
+ }
+
+ free(col_info.spans);
+
+ if (table_calculate_column_types(table) == false)
return false;
- if (table->style->border_collapse == CSS_BORDER_COLLAPSE_COLLAPSE)
- table_collapse_borders(table);
LOG(("table %p done", table));
@@ -339,62 +393,141 @@ bool box_normalise_table(struct box *table, struct content * c)
}
-void box_normalise_table_spans(struct box *table)
+/**
+ * Normalise table cell column/row counts for colspan/rowspan = 0.
+ * Additionally, generate empty cells.
+ *
+ * \param table Table to process
+ * \param spans Array of length table->columns for use in empty cell detection
+ * \param c Content containing table
+ * \return True on success, false on memory exhaustion.
+ */
+
+bool box_normalise_table_spans(struct box *table, struct span_info *spans,
+ struct content *c)
{
struct box *table_row_group;
struct box *table_row;
struct box *table_cell;
- unsigned int last_column;
- unsigned int max_extra = 0;
- bool extra;
- bool force = false;
unsigned int rows_left = table->rows;
+ unsigned int col;
+
+ /* Clear span data */
+ memset(spans, 0, table->columns * sizeof(struct span_info));
- /* Scan table filling in table the width and height of table cells for
- cells with colspan = 0 or rowspan = 0. Ignore the colspan and
- rowspan of any cells that that follow an colspan = 0 */
+ /* Scan table, filling in width and height of table cells with
+ * colspan = 0 and rowspan = 0. Also generate empty cells */
for (table_row_group = table->children; table_row_group != NULL;
- table_row_group = table_row_group->next) {
- for (table_row = table_row_group->children; NULL != table_row;
+ table_row_group = table_row_group->next) {
+ for (table_row = table_row_group->children; table_row != NULL;
table_row = table_row->next){
- last_column = 0;
- extra = false;
- for (table_cell = table_row->children; NULL != table_cell;
+ for (table_cell = table_row->children;
+ table_cell != NULL;
table_cell = table_cell->next) {
- /* We hae reached the end of the row, and have passed
- a cell with colspan = 0 so ignore col and row spans */
- if (force || extra || (table_cell->start_column + 1 <=
- last_column)) {
- extra = true;
+ /* colspan = 0 -> colspan = 1 */
+ if (table_cell->columns == 0)
table_cell->columns = 1;
- table_cell->rows = 1;
- if (table_cell->start_column <= max_extra) {
- max_extra = table_cell->start_column + 1;
+
+ /* rowspan = 0 -> rowspan = rows_left */
+ if (table_cell->rows == 0)
+ table_cell->rows = rows_left;
+
+ /* Record span information */
+ for (col = table_cell->start_column;
+ col < table_cell->start_column +
+ table_cell->columns; col++) {
+ spans[col].row_span = table_cell->rows;
+ }
+ }
+
+ /* Reduce span count of each column */
+ for (col = 0; col < table->columns; col++) {
+ if (spans[col].row_span == 0) {
+ unsigned int start = col;
+ css_computed_style *style;
+ struct box *cell, *prev;
+
+ /* If it's already zero, then we need
+ * to generate an empty cell for the
+ * gap in the row that spans as many
+ * columns as remain blank.
+ */
+ assert(table_row->style != NULL);
+
+ /* Find width of gap */
+ while (col < table->columns &&
+ spans[col].row_span ==
+ 0) {
+ col++;
}
- table_cell->start_column += table->columns;
- } else {
- /* Fill out the number of columns or the number of rows
- if necessary */
- if (0 == table_cell->columns) {
- table_cell->columns = table->columns -
- table_cell->start_column;
- if ((0 == table_cell->start_column) &&
- (0 == table_cell->rows)) {
- force = true;
- }
+
+ style = nscss_get_blank_style(c,
+ table_row->style,
+ myrealloc, c);
+ if (style == NULL)
+ return false;
+
+ cell = box_create(style,
+ table_row->href,
+ table_row->target,
+ NULL, NULL, c);
+ if (cell == NULL) {
+ css_computed_style_destroy(
+ style);
+ return false;
}
- assert(0 != table_cell->columns);
- if (0 == table_cell->rows) {
- table_cell->rows = rows_left;
+ cell->type = BOX_TABLE_CELL;
+
+ cell->rows = 1;
+ cell->columns = col - start;
+ cell->start_column = start;
+
+ /* Find place to insert cell */
+ for (prev = table_row->children;
+ prev != NULL;
+ prev = prev->next) {
+ if (prev->start_column +
+ prev->columns ==
+ start)
+ break;
+ if (prev->next == NULL)
+ break;
}
- assert(0 != table_cell->rows);
- last_column = table_cell->start_column + 1;
+
+ /* Insert it */
+ if (prev == NULL) {
+ if (table_row->children != NULL)
+ table_row->children->
+ prev = cell;
+ else
+ table_row->last = cell;
+
+ cell->next =
+ table_row->children;
+ table_row->children = cell;
+ } else {
+ if (prev->next != NULL)
+ prev->next->prev = cell;
+ else
+ table_row->last = cell;
+
+ cell->next = prev->next;
+ prev->next = cell;
+ cell->prev = prev;
+ }
+ cell->parent = table_row;
+ } else {
+ spans[col].row_span--;
}
}
+
+ assert(rows_left > 0);
+
rows_left--;
}
}
- table->columns += max_extra;
+
+ return true;
}
@@ -405,19 +538,21 @@ bool box_normalise_table_row_group(struct box *row_group,
struct box *child;
struct box *next_child;
struct box *row;
- struct css_style *style;
+ css_computed_style *style;
assert(row_group != 0);
assert(row_group->type == BOX_TABLE_ROW_GROUP);
+
LOG(("row_group %p", row_group));
- for (child = row_group->children; child != 0; child = next_child) {
+ for (child = row_group->children; child != NULL; child = next_child) {
next_child = child->next;
+
switch (child->type) {
case BOX_TABLE_ROW:
/* ok */
- if (!box_normalise_table_row(child, col_info,
- c))
+ if (box_normalise_table_row(child, col_info,
+ c) == false)
return false;
break;
case BOX_BLOCK:
@@ -427,44 +562,52 @@ bool box_normalise_table_row_group(struct box *row_group,
case BOX_TABLE_CELL:
/* insert implied table row */
assert(row_group->style != NULL);
- style = talloc_memdup(c, row_group->style,
- sizeof *style);
- if (!style)
+
+ style = nscss_get_blank_style(c, row_group->style,
+ myrealloc, c);
+ if (style == NULL)
return false;
- css_cascade(style, &css_blank_style, NULL);
+
row = box_create(style, row_group->href,
- row_group->target, 0, 0, c);
- if (!row) {
- talloc_free(style);
+ row_group->target, NULL, NULL, c);
+ if (row == NULL) {
+ css_computed_style_destroy(style);
return false;
}
row->type = BOX_TABLE_ROW;
- if (child->prev == 0)
+
+ if (child->prev == NULL)
row_group->children = row;
else
child->prev->next = row;
+
row->prev = child->prev;
- while (child != 0 && (
+
+ 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_CELL)) {
box_add_child(row, child);
+
next_child = child->next;
- child->next = 0;
+ child->next = NULL;
child = next_child;
}
+
assert(row->last != NULL);
- row->last->next = 0;
+
+ row->last->next = NULL;
row->next = next_child = child;
- if (row->next)
+ if (row->next != NULL)
row->next->prev = row;
else
row_group->last = row;
row->parent = row_group;
- if (!box_normalise_table_row(row, col_info,
- c))
+
+ if (box_normalise_table_row(row, col_info,
+ c) == false)
return false;
break;
case BOX_INLINE:
@@ -483,24 +626,30 @@ bool box_normalise_table_row_group(struct box *row_group,
}
}
- if (row_group->children == 0) {
+ if (row_group->children == NULL) {
LOG(("row_group->children == 0, inserting implied row"));
+
assert(row_group->style != NULL);
- style = talloc_memdup(c, row_group->style, sizeof *style);
- if (!style) {
+
+ style = nscss_get_blank_style(c, row_group->style,
+ myrealloc, c);
+ if (style == NULL) {
return false;
}
- css_cascade(style, &css_blank_style, NULL);
+
row = box_create(style, row_group->href,
- row_group->target, 0, 0, c);
- if (!row) {
- talloc_free(style);
+ row_group->target, NULL, NULL, c);
+ if (row == NULL) {
+ css_computed_style_destroy(style);
return false;
}
row->type = BOX_TABLE_ROW;
row->parent = row_group;
row_group->children = row_group->last = row;
+
+ /* Keep table's row count in sync */
+ col_info->num_rows++;
}
LOG(("row_group %p done", row_group));
@@ -516,19 +665,20 @@ bool box_normalise_table_row(struct box *row,
struct box *child;
struct box *next_child;
struct box *cell = NULL;
- struct css_style *style;
+ css_computed_style *style;
unsigned int i;
- assert(row != 0);
+ assert(row != NULL);
assert(row->type == BOX_TABLE_ROW);
LOG(("row %p", row));
- for (child = row->children; child != 0; child = next_child) {
+ 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, c))
+ if (box_normalise_block(child, c) == false)
return false;
cell = child;
break;
@@ -539,46 +689,51 @@ bool box_normalise_table_row(struct box *row,
case BOX_TABLE_ROW:
/* insert implied table cell */
assert(row->style != NULL);
- style = talloc_memdup(c, row->style, sizeof *style);
- if (!style)
+
+ style = nscss_get_blank_style(c, row->style,
+ myrealloc, c);
+ if (style == NULL)
return false;
- css_cascade(style, &css_blank_style, NULL);
- if (child->style && (child->style->position ==
- CSS_POSITION_ABSOLUTE ||
- child->style->position ==
- CSS_POSITION_FIXED)) {
- style->position = child->style->position;
- }
- cell = box_create(style, row->href, row->target, 0, 0,
- c);
- if (!cell) {
- talloc_free(style);
+
+ cell = box_create(style, row->href, row->target,
+ NULL, NULL, c);
+ if (cell == NULL) {
+ css_computed_style_destroy(style);
return false;
}
cell->type = BOX_TABLE_CELL;
- if (child->prev == 0)
+
+ if (child->prev == NULL)
row->children = cell;
else
child->prev->next = cell;
+
cell->prev = child->prev;
- while (child != 0 && (
+
+ 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 = 0;
+ child->next = NULL;
child = next_child;
}
+
assert(cell->last != NULL);
- cell->last->next = 0;
+
+ cell->last->next = NULL;
cell->next = next_child = child;
- if (cell->next)
+ if (cell->next != NULL)
cell->next->prev = cell;
+ else
+ row->last = cell;
cell->parent = row;
- if (!box_normalise_block(cell, c))
+
+ if (box_normalise_block(cell, c) == false)
return false;
break;
case BOX_INLINE:
@@ -596,42 +751,27 @@ bool box_normalise_table_row(struct box *row,
assert(0);
}
- if (!calculate_table_row(col_info, cell->columns, cell->rows,
- &cell->start_column))
+ if (calculate_table_row(col_info, cell->columns, cell->rows,
+ &cell->start_column) == 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)) {
+ 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 ((col_info->spans[i].auto_column) && (0 == col_info->spans[i].row_span)) {
- col_info->spans[i].auto_column = false;
- }
}
}
+
+ /* Reset current column for next row */
col_info->current_column = 0;
- col_info->extra = false;
-
- /* Removing empty rows causes ill effects for HTML such as:
- *
- * <tr><td colspan="2">1</td></tr><tr></tr><tr><td>2</td></tr>
- *
- * as it breaks the colspan value. Additionally, both MSIE and FF
- * render in the same manner as NetSurf does with the empty row
- * culling commented out.
- */
-// if (row->children == 0) {
-// LOG(("row->children == 0, removing"));
-// if (row->prev == 0)
-// row->parent->children = row->next;
-// else
-// row->prev->next = row->next;
-// if (row->next != 0)
-// row->next->prev = row->prev;
-// box_free(row);
-// } else {
- col_info->num_rows++;
-// }
+
+ /* Increment row counter */
+ col_info->num_rows++;
LOG(("row %p done", row));
@@ -640,6 +780,13 @@ bool box_normalise_table_row(struct box *row,
/**
+ * 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
* \return true on success, false on memory exhaustion
*/
@@ -647,70 +794,55 @@ bool calculate_table_row(struct columns *col_info,
unsigned int col_span, unsigned int row_span,
unsigned int *start_column)
{
- unsigned int cell_start_col;
+ unsigned int cell_start_col = col_info->current_column;
unsigned int cell_end_col;
unsigned int i;
struct span_info *spans;
- if (!col_info->extra) {
- /* skip columns with cells spanning from above */
- while ((col_info->spans[col_info->current_column].row_span != 0) &&
- (!col_info->spans[col_info->current_column].auto_column)) {
- col_info->current_column++;
- }
- if (col_info->spans[col_info->current_column].auto_column) {
- col_info->extra = true;
- col_info->current_column = 0;
- }
- }
+ /* Skip columns with cells spanning from above */
+ while (col_info->spans[cell_start_col].row_span != 0)
+ 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;
- cell_start_col = col_info->current_column;
-
- /* If the current table cell follows a cell with colspan=0,
- ignore both colspan and rowspan just assume it is a standard
- size cell */
- if (col_info->extra) {
- col_info->current_column++;
- col_info->extra_columns = col_info->current_column;
- } else {
- /* If span to end of table, assume spaning single column
- at the moment */
- cell_end_col = cell_start_col + ((0 == col_span) ? 1 : col_span);
-
- if (col_info->num_columns < cell_end_col) {
- spans = realloc(col_info->spans,
- sizeof *spans * (cell_end_col + 1));
- if (!spans)
- return false;
- col_info->spans = spans;
- col_info->num_columns = cell_end_col;
-
- /* Mark new final column as sentinal */
- col_info->spans[cell_end_col].row_span = 0;
- col_info->spans[cell_end_col].auto_row =
- col_info->spans[cell_end_col].auto_column =
- false;
- }
+ col_info->spans = spans;
+ col_info->num_columns = cell_end_col;
- if (0 == col_span) {
- col_info->spans[cell_start_col].auto_column = true;
- col_info->spans[cell_start_col].row_span = row_span;
- col_info->spans[cell_start_col].auto_row = (0 == row_span);
- } else {
- for (i = cell_start_col; i < cell_end_col; i++) {
- col_info->spans[i].row_span = (0 == row_span) ?
- 1 : row_span;
- col_info->spans[i].auto_row = (0 == row_span);
- col_info->spans[i].auto_column = false;
- }
- }
- if (0 == col_span) {
- col_info->spans[cell_end_col].auto_column = true;
- }
- col_info->current_column = 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);
}
+ /* Update current column with calculated end. */
+ col_info->current_column = cell_end_col;
+
*start_column = cell_start_col;
+
return true;
}
@@ -720,11 +852,11 @@ bool box_normalise_inline_container(struct box *cont, struct content * c)
struct box *child;
struct box *next_child;
- assert(cont != 0);
+ assert(cont != NULL);
assert(cont->type == BOX_INLINE_CONTAINER);
LOG(("cont %p", cont));
- for (child = cont->children; child != 0; child = next_child) {
+ for (child = cont->children; child != NULL; child = next_child) {
next_child = child->next;
switch (child->type) {
case BOX_INLINE:
@@ -735,37 +867,40 @@ bool box_normalise_inline_container(struct box *cont, struct content * c)
break;
case BOX_INLINE_BLOCK:
/* ok */
- if (!box_normalise_block(child, c))
+ if (box_normalise_block(child, c) == false)
return false;
break;
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
/* ok */
- assert(child->children != 0);
+ assert(child->children != NULL);
+
switch (child->children->type) {
case BOX_BLOCK:
- if (!box_normalise_block(
- child->children,
- c))
+ if (box_normalise_block(child->children,
+ c) == false)
return false;
break;
case BOX_TABLE:
- if (!box_normalise_table(
- child->children,
- c))
+ if (box_normalise_table(child->children,
+ c) == false)
return false;
break;
default:
assert(0);
}
- if (child->children == 0) {
+
+ if (child->children == NULL) {
/* the child has destroyed itself: remove float */
- if (child->prev == 0)
+ if (child->prev == NULL)
child->parent->children = child->next;
else
child->prev->next = child->next;
- if (child->next != 0)
+ if (child->next != NULL)
child->next->prev = child->prev;
+ else
+ child->parent->last = child->prev;
+
box_free(child);
}
break;