More work on lists. Simplify the implementation to a BLOCK for display: list-item, with a marker box on box->list_marker.

svn path=/trunk/netsurf/; revision=3031
This commit is contained in:
James Bursa 2006-11-05 12:58:24 +00:00
parent 8043344eb8
commit f4f17f905b
6 changed files with 124 additions and 424 deletions

View File

@ -84,6 +84,7 @@ struct box * box_create(struct css_style *style,
box->inline_end = NULL;
box->float_children = NULL;
box->next_float = NULL;
box->list_marker = NULL;
box->col = NULL;
box->gadget = NULL;
box->usemap = NULL;
@ -495,10 +496,6 @@ void box_dump(struct box *box, unsigned int depth)
case BOX_FLOAT_RIGHT: fprintf(stderr, "FLOAT_RIGHT "); break;
case BOX_BR: fprintf(stderr, "BR "); break;
case BOX_TEXT: fprintf(stderr, "TEXT "); break;
case BOX_LIST: fprintf(stderr, "LIST "); break;
case BOX_LIST_ITEM: fprintf(stderr, "LIST_ITEM "); break;
case BOX_LIST_MARKER: fprintf(stderr, "LIST_MARKER "); break;
case BOX_LIST_PRINCIPAL: fprintf(stderr, "LIST_PRINCIPAL "); break;
default: fprintf(stderr, "Unknown box type ");
}
@ -538,6 +535,13 @@ void box_dump(struct box *box, unsigned int depth)
}
fprintf(stderr, "\n");
if (box->list_marker) {
for (i = 0; i != depth; i++)
fprintf(stderr, " ");
fprintf(stderr, "list_marker:\n");
box_dump(box->list_marker, depth + 1);
}
for (c = box->children; c && c->next; c = c->next)
;
if (box->last != c)

View File

@ -60,18 +60,15 @@
* A box tree is "normalized" if the following is satisfied:
* \code
* parent permitted child nodes
* BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE, LIST
* BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE
* INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, TEXT,
* INLINE_END
* INLINE 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, LIST (same as BLOCK)
* TABLE_CELL BLOCK, INLINE_CONTAINER, TABLE (same as BLOCK)
* FLOAT_(LEFT|RIGHT) exactly 1 BLOCK or TABLE
* LIST at least 1 LIST_ITEM
* LIST_ITEM exactly 1 LIST_MARKER and exactly 1 LIST_PRINCIPAL
* LIST_PRINCIPAL BLOCK, INLINE_CONTAINER, TABLE, LIST (same as BLOCK)
* \endcode
*/
@ -97,8 +94,7 @@ typedef enum {
BOX_TABLE_ROW_GROUP,
BOX_FLOAT_LEFT, BOX_FLOAT_RIGHT,
BOX_INLINE_BLOCK, BOX_BR, BOX_TEXT,
BOX_INLINE_END,
BOX_LIST, BOX_LIST_ITEM, BOX_LIST_MARKER, BOX_LIST_PRINCIPAL
BOX_INLINE_END
} box_type;
struct rect {
@ -198,6 +194,9 @@ struct box {
/** Next sibling float box. */
struct box *next_float;
/** List marker box if this is a list-item, or 0. */
struct box *list_marker;
struct column *col; /**< Array of table column data for TABLE only. */
/** Form control data, or 0 if not a form control. */

View File

@ -205,7 +205,7 @@ static const box_type box_map[] = {
0, /*CSS_DISPLAY_INHERIT,*/
BOX_INLINE, /*CSS_DISPLAY_INLINE,*/
BOX_BLOCK, /*CSS_DISPLAY_BLOCK,*/
BOX_LIST_ITEM, /*CSS_DISPLAY_LIST_ITEM,*/
BOX_BLOCK, /*CSS_DISPLAY_LIST_ITEM,*/
BOX_INLINE, /*CSS_DISPLAY_RUN_IN,*/
BOX_INLINE_BLOCK, /*CSS_DISPLAY_INLINE_BLOCK,*/
BOX_TABLE, /*CSS_DISPLAY_TABLE,*/
@ -350,10 +350,6 @@ bool box_construct_element(xmlNode *n, struct content *content,
return true;
}
/* if this is a list item, then reset the box type */
if (style->display == CSS_DISPLAY_LIST_ITEM)
box->type = BOX_LIST_ITEM;
if (!*inline_container &&
(box->type == BOX_INLINE ||
box->type == BOX_BR ||
@ -398,59 +394,6 @@ bool box_construct_element(xmlNode *n, struct content *content,
&inline_container_c,
href, target, title))
return false;
} else if (box->type == BOX_LIST_ITEM) {
/* list item: create marker box and recurse */
struct box *list_item;
struct box *marker;
/* create container box */
list_item = box_create(0, href, target, title, 0, content);
if (!list_item)
return false;
list_item->type = BOX_LIST_ITEM;
/* create marker - effectively a single INLINE */
/* marker style information is contained in PRINCIPAL box */
marker = box_create(box->style, href, target, title, 0,
content);
if (!marker)
return false;
marker->type = BOX_LIST_MARKER;
marker->clone = 1;
/** \todo marker content (list-style-type)
* need to traverse up the tree to find containing BOX_LIST,
* which contains the counter information */
marker->text = talloc_strdup(content, "1.");
if (!marker->text)
return false;
marker->space = 1;
marker->length = 2;
if (style->list_style_image.type ==
CSS_LIST_STYLE_IMAGE_URI) {
if (!html_fetch_object(content,
style->list_style_image.uri, marker,
0, content->available_width, 1000,
false))
return false;
}
/* make box into principal block for list */
box->type = BOX_LIST_PRINCIPAL;
box_add_child(parent, list_item);
box_add_child(list_item, marker);
box_add_child(list_item, box);
/* and recurse */
inline_container_c = 0;
for (c = n->children; convert_children && c; c = c->next) {
if (!convert_xml_to_box(c, content, style,
box, &inline_container_c,
href, target, title))
return false;
}
} else {
if (style->float_ == CSS_FLOAT_LEFT ||
style->float_ == CSS_FLOAT_RIGHT) {
@ -466,6 +409,28 @@ bool box_construct_element(xmlNode *n, struct content *content,
box_add_child(*inline_container, parent);
}
if (style->display == CSS_DISPLAY_LIST_ITEM) {
struct box *marker;
marker = box_create(style, 0, 0, title, 0, content);
if (!marker)
return false;
marker->type = BOX_BLOCK;
/** \todo marker content (list-style-type) */
marker->text = "\342\200\242";
marker->length = 3;
if (style->list_style_image.type ==
CSS_LIST_STYLE_IMAGE_URI) {
if (!html_fetch_object(content,
style->list_style_image.uri,
marker,
0, content->available_width,
1000, false))
return false;
}
box->list_marker = marker;
marker->parent = box;
}
/* non-inline box: add to tree and recurse */
box_add_child(parent, box);
inline_container_c = 0;
@ -610,6 +575,14 @@ bool box_construct_text(xmlNode *n, struct content *content,
* text node, if any */
if (text[0] == ' ' && text[1] == 0) {
if (*inline_container) {
if ((*inline_container)->last == 0) {
LOG(("empty inline_container %p",
*inline_container));
while (parent->parent &&
parent->parent->parent)
parent = parent->parent;
box_dump(parent, 0);
}
assert((*inline_container)->last != 0);
(*inline_container)->last->space = 1;
}

View File

@ -57,21 +57,19 @@ static bool calculate_table_row(struct columns *col_info,
unsigned int col_span, unsigned int row_span,
unsigned int *start_column);
static bool box_normalise_inline_container(struct box *cont, struct content *c);
static bool box_normalise_list(struct box *cont, struct content *c);
static bool box_normalise_list_item(struct box *cont, struct content *c);
/**
* Ensure the box tree is correctly nested by adding and removing nodes.
*
* \param block box of type BLOCK, INLINE_BLOCK, TABLE_CELL or LIST_PRINCIPAL
* \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL
* \param box_pool pool to allocate new boxes in
* \return true on success, false on memory exhaustion
*
* The tree is modified to satisfy the following:
* \code
* parent permitted child nodes
* BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE, LIST
* 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
@ -79,9 +77,6 @@ static bool box_normalise_list_item(struct box *cont, struct content *c);
* TABLE_ROW at least 1 TABLE_CELL
* TABLE_CELL BLOCK, INLINE_CONTAINER, TABLE (same as BLOCK)
* FLOAT_(LEFT|RIGHT) exactly 1 BLOCK or TABLE
* LIST at least 1 LIST_ITEM
* LIST_ITEM exactly 1 LIST_MARKER and exactly 1 LIST_PRINCIPAL
* LIST_PRINCIPAL BLOCK, INLINE_CONTAINER, TABLE, LIST (same as BLOCK)
* \endcode
*/
@ -90,14 +85,12 @@ bool box_normalise_block(struct box *block, struct content *c)
struct box *child;
struct box *next_child;
struct box *table;
struct box *list;
struct css_style *style;
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 ||
block->type == BOX_LIST_PRINCIPAL);
block->type == BOX_TABLE_CELL);
gui_multitask();
for (child = block->children; child != 0; child = next_child) {
@ -166,48 +159,6 @@ bool box_normalise_block(struct box *block, struct content *c)
if (!box_normalise_table(table, c))
return false;
break;
case BOX_LIST:
if (!box_normalise_list(child, c))
return false;
break;
case BOX_LIST_ITEM:
/* Insert implied BOX_LIST */
style = css_duplicate_style(block->style);
if (!style)
return false;
css_cascade(style, &css_blank_style);
list = box_create(style, 0, 0, 0, 0, c);
if (!list) {
css_free_style(style);
return false;
}
list->type = BOX_LIST;
if (child->prev == 0)
block->children = list;
else
child->prev->next = list;
list->prev = child->prev;
while (child != 0 && child->type == BOX_LIST_ITEM) {
box_add_child(list, child);
next_child = child->next;
child->next = 0;
child = next_child;
}
list->last->next = 0;
list->next = next_child = child;
if (list->next)
list->next->prev = list;
else
block->last = list;
list->parent = block;
if (!box_normalise_list(list, c))
return false;
break;
case BOX_LIST_MARKER:
case BOX_LIST_PRINCIPAL:
/* Should be wrapped in BOX_LIST_ITEM */
assert(0);
break;
default:
assert(0);
}
@ -255,8 +206,6 @@ bool box_normalise_table(struct box *table, struct content * c)
case BOX_TABLE:
case BOX_TABLE_ROW:
case BOX_TABLE_CELL:
case BOX_LIST:
case BOX_LIST_ITEM:
/* insert implied table row group */
assert(table->style != NULL);
style = css_duplicate_style(table->style);
@ -285,9 +234,7 @@ bool box_normalise_table(struct box *table, struct content * c)
child->type == BOX_INLINE_CONTAINER ||
child->type == BOX_TABLE ||
child->type == BOX_TABLE_ROW ||
child->type == BOX_TABLE_CELL ||
child->type == BOX_LIST ||
child->type == BOX_LIST_ITEM)) {
child->type == BOX_TABLE_CELL)) {
box_add_child(row_group, child);
next_child = child->next;
child->next = 0;
@ -316,11 +263,6 @@ bool box_normalise_table(struct box *table, struct content * c)
container by convert_xml_to_box() */
assert(0);
break;
case BOX_LIST_MARKER:
case BOX_LIST_PRINCIPAL:
/* Should have been wrapped in BOX_LIST_ITEM */
assert(0);
break;
default:
fprintf(stderr, "%i\n", child->type);
assert(0);
@ -441,8 +383,6 @@ bool box_normalise_table_row_group(struct box *row_group,
case BOX_TABLE:
case BOX_TABLE_ROW_GROUP:
case BOX_TABLE_CELL:
case BOX_LIST:
case BOX_LIST_ITEM:
/* insert implied table row */
assert(row_group->style != NULL);
style = css_duplicate_style(row_group->style);
@ -466,9 +406,7 @@ bool box_normalise_table_row_group(struct box *row_group,
child->type == BOX_INLINE_CONTAINER ||
child->type == BOX_TABLE ||
child->type == BOX_TABLE_ROW_GROUP ||
child->type == BOX_TABLE_CELL ||
child->type == BOX_LIST ||
child->type == BOX_LIST_ITEM)) {
child->type == BOX_TABLE_CELL)) {
box_add_child(row, child);
next_child = child->next;
child->next = 0;
@ -495,11 +433,6 @@ bool box_normalise_table_row_group(struct box *row_group,
container by convert_xml_to_box() */
assert(0);
break;
case BOX_LIST_MARKER:
case BOX_LIST_PRINCIPAL:
/* should have been wrapped in LIST_ITEM */
assert(0);
break;
default:
assert(0);
}
@ -550,8 +483,6 @@ bool box_normalise_table_row(struct box *row,
case BOX_TABLE:
case BOX_TABLE_ROW_GROUP:
case BOX_TABLE_ROW:
case BOX_LIST:
case BOX_LIST_ITEM:
/* insert implied table cell */
assert(row->style != NULL);
style = css_duplicate_style(row->style);
@ -575,9 +506,7 @@ bool box_normalise_table_row(struct box *row,
child->type == BOX_INLINE_CONTAINER ||
child->type == BOX_TABLE ||
child->type == BOX_TABLE_ROW_GROUP ||
child->type == BOX_TABLE_ROW ||
child->type == BOX_LIST ||
child->type == BOX_LIST_ITEM)) {
child->type == BOX_TABLE_ROW)) {
box_add_child(cell, child);
next_child = child->next;
child->next = 0;
@ -603,11 +532,6 @@ bool box_normalise_table_row(struct box *row,
container by convert_xml_to_box() */
assert(0);
break;
case BOX_LIST_MARKER:
case BOX_LIST_PRINCIPAL:
/* should have been wrapped in a BOX_LIST_ITEM */
assert(0);
break;
default:
assert(0);
}
@ -751,20 +675,20 @@ bool box_normalise_inline_container(struct box *cont, struct content * c)
/* ok */
assert(child->children != 0);
switch (child->children->type) {
case BOX_BLOCK:
if (!box_normalise_block(
child->children,
c))
return false;
break;
case BOX_TABLE:
if (!box_normalise_table(
child->children,
c))
return false;
break;
default:
assert(0);
case BOX_BLOCK:
if (!box_normalise_block(
child->children,
c))
return false;
break;
case BOX_TABLE:
if (!box_normalise_table(
child->children,
c))
return false;
break;
default:
assert(0);
}
if (child->children == 0) {
/* the child has destroyed itself: remove float */
@ -783,10 +707,6 @@ bool box_normalise_inline_container(struct box *cont, struct content * c)
case BOX_TABLE_ROW_GROUP:
case BOX_TABLE_ROW:
case BOX_TABLE_CELL:
case BOX_LIST:
case BOX_LIST_ITEM:
case BOX_LIST_MARKER:
case BOX_LIST_PRINCIPAL:
default:
assert(0);
}
@ -795,59 +715,3 @@ bool box_normalise_inline_container(struct box *cont, struct content * c)
return true;
}
bool box_normalise_list(struct box *cont, struct content *c)
{
struct box *child;
struct box *next_child;
assert(cont != 0);
assert(cont->type == BOX_LIST);
for (child = cont->children; child; child = next_child) {
next_child = child->next;
switch (child->type) {
case BOX_LIST_ITEM:
/* ok */
if (!box_normalise_list_item(child, c))
return false;
break;
case BOX_LIST_MARKER:
case BOX_LIST_PRINCIPAL:
/** \todo imply LIST_ITEM here? */
default:
assert(0);
}
}
return true;
}
bool box_normalise_list_item(struct box *cont, struct content *c)
{
struct box *child;
struct box *next_child;
assert(cont != 0);
assert(cont->type == BOX_LIST_ITEM);
for (child = cont->children; child; child = next_child) {
next_child = child->next;
switch (child->type) {
case BOX_LIST_MARKER:
/* ok */
break;
case BOX_LIST_PRINCIPAL:
/* ok */
if (!box_normalise_block(child, c))
return false;
break;
default:
assert(0);
}
}
return true;
}

View File

@ -333,6 +333,15 @@ bool html_redraw_box(struct box *box,
return false;
}
/* list marker */
if (box->list_marker)
if (!html_redraw_box(box->list_marker,
x_parent + box->x - box->scroll_x,
y_parent + box->y - box->scroll_y,
clip_x0, clip_y0, clip_x1, clip_y1,
scale, current_background_color))
return false;
/* scrollbars */
if (box->style && box->type != BOX_BR && box->type != BOX_INLINE &&
(box->style->overflow == CSS_OVERFLOW_SCROLL ||

View File

@ -48,7 +48,6 @@
static void layout_minmax_block(struct box *block);
static bool layout_block_object(struct box *block);
static void layout_block_find_dimensions(int available_width, struct box *box);
static void layout_list_find_dimensions(int available_width, struct box *box);
static int layout_solve_width(int available_width, int width,
int margin[4], int padding[4], int border[4]);
static void layout_float_find_dimensions(int available_width,
@ -60,9 +59,6 @@ static void layout_find_dimensions(int available_width,
static int layout_clear(struct box *fl, css_clear clear);
static void find_sides(struct box *fl, int y0, int y1,
int *x0, int *x1, struct box **left, struct box **right);
static void layout_minmax_list(struct box *box);
static void layout_minmax_list_item(struct box *box);
static bool layout_list(struct box *box, struct content *content);
static void layout_minmax_inline_container(struct box *inline_container);
static int line_height(struct css_style *style);
static bool layout_line(struct box *first, int *width, int *y,
@ -80,6 +76,7 @@ static void layout_minmax_table(struct box *table);
static void layout_move_children(struct box *box, int x, int y);
static void calculate_mbp_width(struct css_style *style, unsigned int side,
int *fixed, float *frac);
static void layout_lists(struct box *box);
static void layout_position_relative(struct box *root);
static void layout_compute_relative_offset(struct box *box, int *x, int *y);
static bool layout_position_absolute(struct box *box,
@ -141,6 +138,7 @@ bool layout_document(struct content *content, int width, int height)
doc->children->margin[BOTTOM]);
}
layout_lists(doc);
layout_position_absolute(doc, doc, 0, 0, content);
layout_position_relative(doc);
@ -153,7 +151,7 @@ bool layout_document(struct content *content, int width, int height)
/**
* Layout a block formatting context.
*
* \param block BLOCK, INLINE_BLOCK, TABLE_CELL or LIST_PRINCIPAL to layout
* \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
* \param content memory pool for any new boxes
* \return true on success, false on memory exhaustion
*
@ -172,8 +170,9 @@ bool layout_block_context(struct box *block, struct content *content)
assert(block->type == BOX_BLOCK ||
block->type == BOX_INLINE_BLOCK ||
block->type == BOX_TABLE_CELL ||
block->type == BOX_LIST_PRINCIPAL);
block->type == BOX_TABLE_CELL);
assert(block->width != UNKNOWN_WIDTH);
assert(block->width != AUTO);
gui_multitask();
@ -215,8 +214,7 @@ bool layout_block_context(struct box *block, struct content *content)
* to each in the order shown. */
while (box) {
assert(box->type == BOX_BLOCK || box->type == BOX_TABLE ||
box->type == BOX_INLINE_CONTAINER ||
box->type == BOX_LIST);
box->type == BOX_INLINE_CONTAINER);
assert(margin_box);
/* Tables are laid out before being positioned, because the
@ -241,8 +239,7 @@ bool layout_block_context(struct box *block, struct content *content)
return false;
layout_solve_width(box->parent->width, box->width,
box->margin, box->padding, box->border);
} else if (box->type == BOX_LIST)
layout_list_find_dimensions(box->parent->width, box);
}
/* Position box: horizontal. */
box->x = box->parent->padding[LEFT] + box->margin[LEFT] +
@ -315,9 +312,6 @@ bool layout_block_context(struct box *block, struct content *content)
cx = x0;
box->y += y - cy;
cy = y;
} else if (box->type == BOX_LIST) {
if (!layout_list(box, content))
return false;
}
/* Advance to next box. */
@ -396,7 +390,7 @@ bool layout_block_context(struct box *block, struct content *content)
/**
* Calculate minimum and maximum width of a block.
*
* \param block box of type BLOCK, INLINE_BLOCK, TABLE_CELL, or LIST_PRINCIPAL
* \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL
* \post block->min_width and block->max_width filled in,
* 0 <= block->min_width <= block->max_width
*/
@ -410,8 +404,7 @@ void layout_minmax_block(struct box *block)
assert(block->type == BOX_BLOCK ||
block->type == BOX_INLINE_BLOCK ||
block->type == BOX_TABLE_CELL ||
block->type == BOX_LIST_PRINCIPAL);
block->type == BOX_TABLE_CELL);
/* check if the widths have already been calculated */
if (block->max_width != UNKNOWN_MAX_WIDTH)
@ -438,9 +431,6 @@ void layout_minmax_block(struct box *block)
case BOX_TABLE:
layout_minmax_table(child);
break;
case BOX_LIST:
layout_minmax_list(child);
break;
default:
assert(0);
}
@ -576,64 +566,6 @@ void layout_block_find_dimensions(int available_width, struct box *box)
}
/**
* Compute dimensions of box, margins, paddings, and borders for a list.
*
* Similar to layout_block_find_dimensions()
*/
void layout_list_find_dimensions(int available_width, struct box *box)
{
int width, height;
int *margin = box->margin;
int *padding = box->padding;
int *border = box->border;
struct css_style *style = box->style;
struct box *c;
layout_find_dimensions(available_width, style,
&width, &height, margin, padding, border);
for (c = box->children; c; c = c->next) {
struct box *marker, *principal;
marker = c->children;
principal = marker->next;
/** \todo handle marker */
marker->width = marker->height = 0;
layout_block_find_dimensions(available_width, principal);
if (width < principal->x + principal->width +
principal->padding[RIGHT] +
principal->border[RIGHT] +
principal->margin[RIGHT])
width = principal->x + principal->width +
principal->padding[RIGHT] +
principal->border[RIGHT] +
principal->margin[RIGHT];
if (height < principal->y + principal->height +
principal->padding[BOTTOM] +
principal->border[BOTTOM] +
principal->margin[BOTTOM])
height = principal->y + principal->height +
principal->padding[BOTTOM] +
principal->border[BOTTOM] +
principal->margin[BOTTOM];
}
box->width = layout_solve_width(available_width, width, margin,
padding, border);
box->height = height;
if (margin[TOP] == AUTO)
margin[TOP] = 0;
if (margin[BOTTOM] == AUTO)
margin[BOTTOM] = 0;
}
/**
* Solve the width constraint as given in CSS 2.1 section 10.3.3.
*/
@ -889,127 +821,6 @@ void find_sides(struct box *fl, int y0, int y1,
}
/**
* Calculate minimum and maximum widths of a list
*/
void layout_minmax_list(struct box *box)
{
int min = 0, max = 0;
struct box *c;
assert(box->type == BOX_LIST);
/* check if we've already calculated the width */
if (box->max_width != UNKNOWN_MAX_WIDTH)
return;
for (c = box->children; c; c = c->next) {
layout_minmax_list_item(c);
if (min < c->min_width)
min = c->min_width;
if (max < c->max_width)
max = c->max_width;
}
box->min_width = min;
box->max_width = max;
}
/**
* Calculate minimum and maximum widths of a list item
*/
void layout_minmax_list_item(struct box *box)
{
struct box *marker, *principal;
assert(box->type == BOX_LIST_ITEM);
/* check if we've already calculated the width */
if (box->max_width != UNKNOWN_MAX_WIDTH)
return;
marker = box->children;
principal = marker->next;
layout_minmax_block(principal);
/** \todo what on earth are we expected to do with the marker?
* AFAICS, none of Opera, Firefox nor Konqueror support
* display: list-item with list-style-position: outside
* In Opera/Firefox's case, they don't appear to bother to
* generate the marker box (probably following the "optional"
* wording of the spec - 12.5). Konqueror turns it into
* list-style-position: inside. */
marker->min_width = marker->max_width = 0;
box->min_width = principal->min_width + marker->min_width;
box->max_width = principal->max_width + marker->max_width;
}
/**
* Layout a list
*
* \param box list box
* \param content memory pool for any new boxes
* \return true on success, false on memory exhaustion
*/
bool layout_list(struct box *box, struct content *content)
{
struct box *c;
int cy = 0;
assert(box->type == BOX_LIST);
for (c = box->children; c; c = c->next) {
struct box *marker, *principal;
assert(c->type == BOX_LIST_ITEM);
marker = c->children;
principal = marker->next;
c->x = 0;
c->y = cy;
/** \todo handle marker */
marker->x = marker->y = 0;
principal->x = 0;
principal->y = 0;
/* manipulate principal box's parent pointer so
* layout_block_context has a parent style to play with */
/** \todo is this sane? */
principal->parent = box;
layout_block_context(principal, content);
principal->parent = c;
if (c->width == UNKNOWN_WIDTH)
c->width = principal->x + principal->width +
principal->padding[RIGHT] +
principal->border[RIGHT] +
principal->margin[RIGHT];
// if (c->height == AUTO)
c->height = principal->y + principal->height +
principal->padding[BOTTOM] +
principal->border[BOTTOM] +
principal->margin[BOTTOM];
cy += c->height;
}
// if (box->height == AUTO)
box->height = cy - box->padding[TOP];
return true;
}
/**
* Layout lines of text or inline boxes with floats.
*
@ -1885,6 +1696,8 @@ int layout_text_indent(struct css_style *style, int width)
bool layout_float(struct box *b, int width, struct content *content)
{
assert(b->type == BOX_TABLE || b->type == BOX_BLOCK ||
b->type == BOX_INLINE_BLOCK);
layout_float_find_dimensions(width, b->style, b);
if (b->type == BOX_TABLE) {
if (!layout_table(b, width, content))
@ -2569,6 +2382,30 @@ void calculate_mbp_width(struct css_style *style, unsigned int side,
}
/**
* Layout list markers.
*/
void layout_lists(struct box *box)
{
struct box *child;
struct box *marker;
for (child = box->children; child; child = child->next) {
if (child->list_marker) {
marker = child->list_marker;
if (marker->width == UNKNOWN_WIDTH)
nsfont_width(marker->style, marker->text,
marker->length, &marker->width);
marker->x = -marker->width;
marker->y = 0;
marker->height = line_height(marker->style);
}
layout_lists(child);
}
}
/**
* Adjust positions of relatively positioned boxes.
*/
@ -3199,4 +3036,18 @@ void layout_calculate_descendant_bboxes(struct box *box)
if (box->descendant_y1 < child->y + child->descendant_y1)
box->descendant_y1 = child->y + child->descendant_y1;
}
if (box->list_marker) {
child = box->list_marker;
layout_calculate_descendant_bboxes(child);
if (child->x + child->descendant_x0 < box->descendant_x0)
box->descendant_x0 = child->x + child->descendant_x0;
if (box->descendant_x1 < child->x + child->descendant_x1)
box->descendant_x1 = child->x + child->descendant_x1;
if (child->y + child->descendant_y0 < box->descendant_y0)
box->descendant_y0 = child->y + child->descendant_y0;
if (box->descendant_y1 < child->y + child->descendant_y1)
box->descendant_y1 = child->y + child->descendant_y1;
}
}