summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2004-05-27 22:13:20 +0000
committerJames Bursa <james@netsurf-browser.org>2004-05-27 22:13:20 +0000
commit4f31db54f76fa046675954581d9a908a7d6f5382 (patch)
tree5fd45d8803db51f1c180e9f81271b9d56a8e06db
parent2af77b03e50b5fc70c7df56fda6c4a54ec04453d (diff)
downloadnetsurf-4f31db54f76fa046675954581d9a908a7d6f5382.tar.gz
netsurf-4f31db54f76fa046675954581d9a908a7d6f5382.tar.bz2
[project @ 2004-05-27 22:13:20 by bursa]
Fix some table layout bugs related to the recent changes to calculate_table_widths(). svn path=/import/netsurf/; revision=898
-rw-r--r--render/box.h31
-rw-r--r--render/layout.c140
2 files changed, 94 insertions, 77 deletions
diff --git a/render/box.h b/render/box.h
index 6e94247c4..b4ecfa631 100644
--- a/render/box.h
+++ b/render/box.h
@@ -82,6 +82,11 @@
#include "netsurf/utils/pool.h"
+struct box;
+struct column;
+
+
+/** Type of a struct box. */
typedef enum {
BOX_BLOCK, BOX_INLINE_CONTAINER, BOX_INLINE,
BOX_TABLE, BOX_TABLE_ROW, BOX_TABLE_CELL,
@@ -90,15 +95,6 @@ typedef enum {
BOX_INLINE_BLOCK, BOX_BR
} box_type;
-struct column {
- enum { COLUMN_WIDTH_UNKNOWN = 0, COLUMN_WIDTH_FIXED,
- COLUMN_WIDTH_AUTO, COLUMN_WIDTH_PERCENT,
- COLUMN_WIDTH_RELATIVE } type;
- int min, max, width;
-};
-
-struct box;
-
/* parameters for <object> and related elements */
struct object_params {
char* data;
@@ -184,7 +180,7 @@ struct box {
/** Next sibling float box. */
struct box *next_float;
- struct column *col; /**< Table column data for TABLE only. */
+ struct column *col; /**< Array of table column data for TABLE only. */
struct font_data *font; /**< Font, or 0 if no text. */
@@ -201,6 +197,21 @@ struct box {
void *object_state;
};
+/** Table column data. */
+struct column {
+ /** Type of column. */
+ enum { COLUMN_WIDTH_UNKNOWN, COLUMN_WIDTH_FIXED,
+ COLUMN_WIDTH_AUTO, COLUMN_WIDTH_PERCENT,
+ COLUMN_WIDTH_RELATIVE } type;
+ /** Preferred width of column. Pixels for FIXED, percentage for PERCENT,
+ * relative units for RELATIVE, unused for AUTO. */
+ int width;
+ /** Minimum width of content. */
+ int min;
+ /** Maximum width of content. */
+ int max;
+};
+
#define UNKNOWN_WIDTH INT_MAX
#define UNKNOWN_MAX_WIDTH INT_MAX
diff --git a/render/layout.c b/render/layout.c
index 1979b2a0f..16f59fc12 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -1149,9 +1149,13 @@ void layout_table(struct box *table, int available_width)
}
for (i = 0; i != columns; i++) {
- if (col[i].type == COLUMN_WIDTH_FIXED)
+ if (col[i].type == COLUMN_WIDTH_FIXED) {
+ if (col[i].width < col[i].min)
+ col[i].width = col[i].max = col[i].min;
+ else
+ col[i].min = col[i].max = col[i].width;
required_width += col[i].width;
- else if (col[i].type == COLUMN_WIDTH_PERCENT) {
+ } else if (col[i].type == COLUMN_WIDTH_PERCENT) {
int width = col[i].width * auto_width / 100;
required_width += col[i].min < width ? width : col[i].min;
} else
@@ -1574,6 +1578,17 @@ void calculate_inline_widths(struct box *box, int *min, int *line_max)
/**
* Find min, max widths for a table and determine column width types.
+ *
+ * \param table table box to calculate widths
+ *
+ * If table->max_width is not UNKNOWN_MAX_WIDTH, returns with no change to table.
+ *
+ * If table->col is 0, it is created and filled in completely.
+ *
+ * If table->col exists, the type and width fields are left unchanged, and the min
+ * and max fields are updated.
+ *
+ * table->min_width and table->max_width are set.
*/
void calculate_table_widths(struct box *table)
@@ -1589,20 +1604,27 @@ void calculate_table_widths(struct box *table)
if (table->max_width != UNKNOWN_MAX_WIDTH)
return;
- if (!table->col)
- table->col = xcalloc(table->columns, sizeof(*col));
+ if (!table->col) {
+ col = table->col = malloc(table->columns * sizeof *col);
+ assert(col);
+ for (i = 0; i != table->columns; i++)
+ col[i].type = COLUMN_WIDTH_UNKNOWN;
+ }
col = table->col;
+ for (i = 0; i != table->columns; i++)
+ col[i].min = col[i].max = 0;
- assert(table->children != 0 && table->children->children != 0);
+ assert(table->children && table->children->children);
/* 1st pass: consider cells with colspan 1 only */
- for (row_group = table->children; row_group != 0; row_group = row_group->next) {
+ for (row_group = table->children; row_group;
+ row_group = row_group->next) {
assert(row_group->type == BOX_TABLE_ROW_GROUP);
- for (row = row_group->children; row != 0; row = row->next) {
+ for (row = row_group->children; row; row = row->next) {
assert(row->type == BOX_TABLE_ROW);
- for (cell = row->children; cell != 0; cell = cell->next) {
+ for (cell = row->children; cell; cell = cell->next) {
assert(cell->type == BOX_TABLE_CELL);
- assert(cell->style != 0);
+ assert(cell->style);
if (cell->columns != 1)
continue;
@@ -1610,48 +1632,48 @@ void calculate_table_widths(struct box *table)
calculate_widths(cell);
i = cell->start_column;
- if (col[i].type == COLUMN_WIDTH_FIXED) {
- if (col[i].width < cell->min_width)
- col[i].min = col[i].width = col[i].max = cell->min_width;
- continue;
- }
-
- /* update column min, max widths using cell widths */
+ /* update column min, max widths
+ * using cell widths */
if (col[i].min < cell->min_width)
col[i].min = cell->min_width;
if (col[i].max < cell->max_width)
col[i].max = cell->max_width;
+ /* fixed width takes priority over any
+ * other width type */
if (col[i].type != COLUMN_WIDTH_FIXED &&
- cell->style->width.width == CSS_WIDTH_LENGTH) {
- /* fixed width cell => fixed width column */
+ cell->style->width.width ==
+ CSS_WIDTH_LENGTH) {
col[i].type = COLUMN_WIDTH_FIXED;
- width = len(&cell->style->width.value.length,
+ col[i].width = len(&cell->style->
+ width.value.length,
cell->style);
- if (width < col[i].min)
- /* if the given width is too small, give
- * the column its minimum width */
- width = col[i].min;
- col[i].min = col[i].width = col[i].max = width;
-
- } else if (col[i].type == COLUMN_WIDTH_UNKNOWN) {
- if (cell->style->width.width == CSS_WIDTH_PERCENT) {
- col[i].type = COLUMN_WIDTH_PERCENT;
- col[i].width = cell->style->width.value.percent;
- } else if (cell->style->width.width == CSS_WIDTH_AUTO) {
- col[i].type = COLUMN_WIDTH_AUTO;
- }
+ continue;
+ }
+
+ if (col[i].type != COLUMN_WIDTH_UNKNOWN)
+ continue;
+
+ if (cell->style->width.width ==
+ CSS_WIDTH_PERCENT) {
+ col[i].type = COLUMN_WIDTH_PERCENT;
+ col[i].width = cell->style->
+ width.value.percent;
+ } else if (cell->style->width.width ==
+ CSS_WIDTH_AUTO) {
+ col[i].type = COLUMN_WIDTH_AUTO;
}
}
}
}
/* 2nd pass: cells which span multiple columns */
- for (row_group = table->children; row_group != 0; row_group = row_group->next) {
- for (row = row_group->children; row != 0; row = row->next) {
- for (cell = row->children; cell != 0; cell = cell->next) {
+ for (row_group = table->children; row_group;
+ row_group = row_group->next) {
+ for (row = row_group->children; row; row = row->next) {
+ for (cell = row->children; cell; cell = cell->next) {
unsigned int flexible_columns = 0;
- int min = 0, max = 0, fixed_width = 0;
+ int min = 0, max = 0, fixed_width = 0, cell_min;
signed long extra;
if (cell->columns == 1)
@@ -1659,8 +1681,10 @@ void calculate_table_widths(struct box *table)
calculate_widths(cell);
i = cell->start_column;
+ cell_min = cell->min_width;
- /* find min, max width so far of spanned columns */
+ /* find min, max width so far of
+ * spanned columns */
for (j = 0; j != cell->columns; j++) {
min += col[i + j].min;
max += col[i + j].max;
@@ -1670,43 +1694,25 @@ void calculate_table_widths(struct box *table)
flexible_columns++;
}
- if (cell->style->width.width == CSS_WIDTH_LENGTH &&
- flexible_columns) {
- /* cell is fixed width, and not all the spanned columns
- * are fixed width, so split difference between spanned
- * columns which aren't fixed width yet */
+ if (cell->style->width.width == CSS_WIDTH_LENGTH) {
width = len(&cell->style->width.value.length,
cell->style);
- if (width < cell->min_width)
- width = cell->min_width;
- extra = width - fixed_width;
- for (j = 0; j != cell->columns; j++)
- if (col[i + j].type != COLUMN_WIDTH_FIXED)
- extra -= col[i + j].min;
- if (0 < extra)
- extra = 1 + extra / flexible_columns;
- else
- extra = 0;
- for (j = 0; j != cell->columns; j++) {
- if (col[i + j].type != COLUMN_WIDTH_FIXED) {
- col[i + j].width = col[i + j].max =
- col[i + j].min += extra;
- col[i + j].type = COLUMN_WIDTH_FIXED;
- }
- }
- continue;
+ if (cell_min < width)
+ cell_min = width;
}
/* distribute extra min, max to spanned columns */
- if (min < cell->min_width) {
+ if (min < cell_min) {
if (flexible_columns == 0) {
- extra = 1 + (cell->min_width - min)
+ extra = 1 + (cell_min - min)
/ cell->columns;
- for (j = 0; j != cell->columns; j++)
- col[i + j].min = col[i + j].width =
- col[i + j].max += extra;
+ for (j = 0; j != cell->columns; j++) {
+ col[i + j].min += extra;
+ if (col[i + j].max < col[i + j].min)
+ col[i + j].max = col[i + j].min;
+ }
} else {
- extra = 1 + (cell->min_width - min)
+ extra = 1 + (cell_min - min)
/ flexible_columns;
max = 0;
for (j = 0; j != cell->columns; j++) {
@@ -1714,8 +1720,8 @@ void calculate_table_widths(struct box *table)
col[i + j].min += extra;
if (col[i + j].max < col[i + j].min)
col[i + j].max = col[i + j].min;
- max += col[i + j].max;
}
+ max += col[i + j].max;
}
}
}