summaryrefslogtreecommitdiff
path: root/render/html.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/html.c')
-rw-r--r--render/html.c99
1 files changed, 97 insertions, 2 deletions
diff --git a/render/html.c b/render/html.c
index 506904f6f..39d4541fe 100644
--- a/render/html.c
+++ b/render/html.c
@@ -45,6 +45,8 @@ static void html_object_callback(content_msg msg, struct content *object,
void *p1, void *p2, union content_msg_data data);
static void html_object_done(struct box *box, struct content *object,
bool background);
+static void html_object_failed(struct box *box, struct content *content,
+ bool background);
static bool html_object_type_permitted(const content_type type,
const content_type *permitted_types);
@@ -799,7 +801,10 @@ void html_object_callback(content_msg msg, struct content *object,
content_add_error(c, "?", 0);
content_set_status(c, messages_get("BadObject"));
content_broadcast(c, CONTENT_MSG_STATUS, data);
- content_remove_user(object, html_object_callback, c, (void*)i);
+ content_remove_user(object, html_object_callback, c,
+ (void *) i);
+ html_object_failed(box, c,
+ c->data.html.object[i].background);
break;
case CONTENT_MSG_READY:
@@ -815,7 +820,8 @@ void html_object_callback(content_msg msg, struct content *object,
break;
case CONTENT_MSG_DONE:
- html_object_done(box, object, c->data.html.object[i].background);
+ html_object_done(box, object,
+ c->data.html.object[i].background);
c->active--;
break;
@@ -826,6 +832,8 @@ void html_object_callback(content_msg msg, struct content *object,
content_set_status(c, messages_get("ObjError"),
data.error);
content_broadcast(c, CONTENT_MSG_STATUS, data);
+ html_object_failed(box, c,
+ c->data.html.object[i].background);
break;
case CONTENT_MSG_STATUS:
@@ -952,6 +960,93 @@ void html_object_done(struct box *box, struct content *object,
/**
+ * Handle object fetching or loading failure.
+ *
+ * \param box box containing object which failed to load
+ * \param content document of type CONTENT_HTML
+ * \param background the object was the background image for the box
+ *
+ * Any fallback content for the object is made visible.
+ */
+
+void html_object_failed(struct box *box, struct content *content,
+ bool background)
+{
+ struct box *b, *ic;
+
+ if (background)
+ return;
+ if (!box->fallback)
+ return;
+
+ /* make fallback boxes into children or siblings, as appropriate */
+ if (box->type != BOX_INLINE) {
+ /* easy case: fallbacks become children */
+ assert(box->type == BOX_BLOCK ||
+ box->type == BOX_TABLE_CELL ||
+ box->type == BOX_INLINE_BLOCK);
+ box->children = box->fallback;
+ box->last = box->children;
+ while (box->last->next)
+ box->last = box->last->next;
+ box->fallback = 0;
+ box_normalise_block(box, content);
+ } else {
+ assert(box->parent->type == BOX_INLINE_CONTAINER);
+ if (box->fallback->type == BOX_INLINE_CONTAINER &&
+ !box->fallback->next) {
+ /* the fallback is a single inline container: splice
+ * it into this inline container */
+ for (b = box->fallback->children; b; b = b->next)
+ b->parent = box->parent;
+ box->fallback->last->next = box->next;
+ if (!box->next)
+ box->parent->last = box->fallback->last;
+ box->next = box->fallback->children;
+ box->next->prev = box;
+ box->fallback = 0;
+ } else {
+ if (box->next) {
+ /* split this inline container into two inline
+ * containers */
+ ic = box_create(0, 0, 0, 0, content);
+ if (!ic) {
+ warn_user("NoMemory", 0);
+ return;
+ }
+ ic->type = BOX_INLINE_CONTAINER;
+ box_insert_sibling(box->parent, ic);
+ ic->children = box->next;
+ ic->last = box->parent->last;
+ ic->children->prev = 0;
+ box->next = 0;
+ box->parent->last = box;
+ for (b = ic->children; b; b = b->next)
+ b->parent = ic;
+ }
+ /* insert the fallback after the parent */
+ for (b = box->fallback; b->next; b = b->next)
+ b->parent = box->parent->parent;
+ b->parent = box->parent->parent;
+ /* [b is the last fallback box] */
+ b->next = box->parent->next;
+ if (b->next)
+ b->next->prev = b;
+ box->parent->next = box->fallback;
+ box->fallback->prev = box->parent;
+ box->fallback = 0;
+ box_normalise_block(box->parent->parent, content);
+ }
+ }
+
+ /* invalidate parent min, max widths */
+ for (b = box->parent; b; b = b->parent)
+ b->max_width = UNKNOWN_MAX_WIDTH;
+ box->width = UNKNOWN_WIDTH;
+}
+
+
+/**
* Check if a type is in a list.
*
* \param type the content_type to search for