From f4f17f905b1f7d1c12baebca6f4c18362d71d80c Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sun, 5 Nov 2006 12:58:24 +0000 Subject: 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 --- render/box.c | 12 ++- render/box.h | 13 ++- render/box_construct.c | 89 ++++++------------ render/box_normalise.c | 176 ++++------------------------------ render/html_redraw.c | 9 ++ render/layout.c | 249 ++++++++++--------------------------------------- 6 files changed, 124 insertions(+), 424 deletions(-) diff --git a/render/box.c b/render/box.c index 4113120de..590b673a8 100644 --- a/render/box.c +++ b/render/box.c @@ -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) diff --git a/render/box.h b/render/box.h index 369956f76..adefcdc1e 100644 --- a/render/box.h +++ b/render/box.h @@ -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. */ diff --git a/render/box_construct.c b/render/box_construct.c index 4c847289a..1245ed800 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -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; } diff --git a/render/box_normalise.c b/render/box_normalise.c index 703622bb9..9cc49bdce 100644 --- a/render/box_normalise.c +++ b/render/box_normalise.c @@ -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; -} diff --git a/render/html_redraw.c b/render/html_redraw.c index 9cf8a2927..bc57d3cba 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -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 || diff --git a/render/layout.c b/render/layout.c index 2822c5239..af1904a66 100644 --- a/render/layout.c +++ b/render/layout.c @@ -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; + } } -- cgit v1.2.3