[project @ 2005-04-13 21:58:28 by bursa]

Add fallback field to struct box for object fallback content. Add some checks for tree consistency to box_dump(). Rename struct plugin_params to object_param. Clean up box_object(), box_embed(), box_iframe(), and box_image(). Implement object fallback to contents if the fetch or conversion fails.

svn path=/import/netsurf/; revision=1627
This commit is contained in:
James Bursa 2005-04-13 21:58:28 +00:00
parent 4ebe390f8d
commit 11bc5345c5
5 changed files with 318 additions and 384 deletions

View File

@ -75,6 +75,7 @@ struct box * box_create(struct css_style *style,
box->children = NULL; box->children = NULL;
box->last = NULL; box->last = NULL;
box->parent = NULL; box->parent = NULL;
box->fallback = NULL;
box->float_children = NULL; box->float_children = NULL;
box->next_float = NULL; box->next_float = NULL;
box->col = NULL; box->col = NULL;
@ -167,45 +168,10 @@ void box_free_box(struct box *box)
form_free_control(box->gadget); form_free_control(box->gadget);
} }
box_free_object_params(box->object_params);
talloc_free(box); talloc_free(box);
} }
/**
* Free an object parameter structure.
*
* \param op object parameter structure to free
*/
void box_free_object_params(struct object_params *op)
{
struct plugin_params *a, *b;
if (!op)
return;
free(op->data);
free(op->type);
free(op->codetype);
free(op->codebase);
free(op->classid);
free(op->basehref);
for (a = op->params; a; a = b) {
b = a->next;
free(a->name);
free(a->value);
free(a->type);
free(a->valuetype);
free(a);
}
free(op);
}
/** /**
* Find the absolute coordinates of a box. * Find the absolute coordinates of a box.
* *
@ -434,7 +400,7 @@ struct box *box_find_by_id(struct box *box, const char *id)
void box_dump(struct box *box, unsigned int depth) void box_dump(struct box *box, unsigned int depth)
{ {
unsigned int i; unsigned int i;
struct box * c; struct box *c, *prev;
for (i = 0; i != depth; i++) for (i = 0; i != depth; i++)
fprintf(stderr, " "); fprintf(stderr, " ");
@ -486,6 +452,27 @@ void box_dump(struct box *box, unsigned int depth)
fprintf(stderr, " next_float %p", box->next_float); fprintf(stderr, " next_float %p", box->next_float);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
for (c = box->children; c; c = c->next) for (c = box->children; c->next; c = c->next)
;
if (box->last != c)
fprintf(stderr, "warning: box->last %p (should be %p) "
"(box %p)\n", box->last, c, box);
for (prev = 0, c = box->children; c; prev = c, c = c->next) {
if (c->parent != box)
fprintf(stderr, "warning: box->parent %p (should be "
"%p) (box on next line)\n",
c->parent, box);
if (c->prev != prev)
fprintf(stderr, "warning: box->prev %p (should be "
"%p) (box on next line)\n",
c->prev, prev);
box_dump(c, depth + 1); box_dump(c, depth + 1);
}
if (box->fallback) {
for (i = 0; i != depth; i++)
fprintf(stderr, " ");
fprintf(stderr, "fallback:\n");
for (c = box->fallback; c; c = c->next)
box_dump(c, depth + 1);
}
} }

View File

@ -81,6 +81,8 @@
struct box; struct box;
struct column; struct column;
struct css_style; struct css_style;
struct object_params;
struct object_param;
/** Type of a struct box. */ /** Type of a struct box. */
@ -92,27 +94,6 @@ typedef enum {
BOX_INLINE_BLOCK, BOX_BR, BOX_TEXT BOX_INLINE_BLOCK, BOX_BR, BOX_TEXT
} box_type; } box_type;
/* parameters for <object> and related elements */
struct object_params {
char* data;
char* type;
char* codetype;
char* codebase;
char* classid;
struct plugin_params* params;
/* not a parameter but stored here for convenience */
char* basehref;
};
struct plugin_params {
char* name;
char* value;
char* type;
char* valuetype;
struct plugin_params* next;
};
/** Node in box tree. All dimensions are in pixels. */ /** Node in box tree. All dimensions are in pixels. */
struct box { struct box {
/** Type of box. */ /** Type of box. */
@ -181,6 +162,7 @@ struct box {
struct box *children; /**< First child box, or 0. */ struct box *children; /**< First child box, or 0. */
struct box *last; /**< Last child box, or 0. */ struct box *last; /**< Last child box, or 0. */
struct box *parent; /**< Parent box, or 0. */ struct box *parent; /**< Parent box, or 0. */
struct box *fallback; /**< Fallback children for object, or 0. */
/** First float child box, or 0. Float boxes are in the tree twice, in /** First float child box, or 0. Float boxes are in the tree twice, in
* this list for the block box which defines the area for floats, and * this list for the block box which defines the area for floats, and
@ -221,6 +203,25 @@ struct column {
int max; int max;
}; };
/** Parameters for <object> and similar elements. */
struct object_params {
char *data;
char *type;
char *codetype;
char *codebase;
char *classid;
struct object_param *params;
};
/** Linked list of <object> parameters. */
struct object_param {
char *name;
char *value;
char *type;
char *valuetype;
struct object_param *next;
};
#define UNKNOWN_WIDTH INT_MAX #define UNKNOWN_WIDTH INT_MAX
#define UNKNOWN_MAX_WIDTH INT_MAX #define UNKNOWN_MAX_WIDTH INT_MAX

View File

@ -105,7 +105,6 @@ static bool box_object(BOX_SPECIAL_PARAMS);
static bool box_embed(BOX_SPECIAL_PARAMS); static bool box_embed(BOX_SPECIAL_PARAMS);
/*static bool box_applet(BOX_SPECIAL_PARAMS);*/ /*static bool box_applet(BOX_SPECIAL_PARAMS);*/
static bool box_iframe(BOX_SPECIAL_PARAMS); static bool box_iframe(BOX_SPECIAL_PARAMS);
static bool plugin_decode(struct content* content, struct box* box);
static bool box_get_attribute(xmlNode *n, const char *attribute, static bool box_get_attribute(xmlNode *n, const char *attribute,
void *context, char **value); void *context, char **value);
static bool box_extract_link(const char *rel, const char *base, char **result); static bool box_extract_link(const char *rel, const char *base, char **result);
@ -957,6 +956,7 @@ bool box_a(BOX_SPECIAL_PARAMS)
box->href = talloc_strdup(content, url); box->href = talloc_strdup(content, url);
if (!box->href) if (!box->href)
return false; return false;
free(url);
} }
} }
@ -974,14 +974,14 @@ bool box_a(BOX_SPECIAL_PARAMS)
bool box_image(BOX_SPECIAL_PARAMS) bool box_image(BOX_SPECIAL_PARAMS)
{ {
char *s, *url, *s1; bool ok;
xmlChar *s2; char *s, *url;
url_func_result res; xmlChar *alt, *src;
/* handle alt text */ /* handle alt text */
if ((s2 = xmlGetProp(n, (const xmlChar *) "alt"))) { if ((alt = xmlGetProp(n, (const xmlChar *) "alt"))) {
s = squash_whitespace(s2); s = squash_whitespace(alt);
xmlFree(s2); xmlFree(alt);
if (!s) if (!s)
return false; return false;
box->text = talloc_strdup(content, s); box->text = talloc_strdup(content, s);
@ -997,33 +997,20 @@ bool box_image(BOX_SPECIAL_PARAMS)
if (box->usemap && box->usemap[0] == '#') if (box->usemap && box->usemap[0] == '#')
box->usemap++; box->usemap++;
/* img without src is an error */ /* get image URL */
if (!(s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) if (!(src = xmlGetProp(n, (const xmlChar *) "src")))
return true; return true;
if (!box_extract_link((char *) src, content->data.html.base_url, &url))
/* remove leading and trailing whitespace */
s1 = strip(s);
res = url_join(s1, content->data.html.base_url, &url);
xmlFree(s);
if (res == URL_FUNC_NOMEM)
return false; return false;
else if (res == URL_FUNC_FAILED) xmlFree(src);
return true; if (!url)
if (strcmp(url, content->data.html.base_url) == 0)
/* if url is equivalent to the parent's url,
* we've got infinite inclusion: ignore */
return true; return true;
/* start fetch */ /* start fetch */
if (!html_fetch_object(content, url, box, image_types, ok = html_fetch_object(content, url, box, image_types,
content->available_width, 1000, false)) { content->available_width, 1000, false);
free(url); free(url);
return false; return ok;
}
free(url);
return true;
} }
@ -1033,93 +1020,120 @@ bool box_image(BOX_SPECIAL_PARAMS)
bool box_object(BOX_SPECIAL_PARAMS) bool box_object(BOX_SPECIAL_PARAMS)
{ {
struct object_params *po; struct object_params *params;
struct plugin_params *pp = NULL; struct object_param *param;
xmlChar *codebase, *classid, *data;
xmlNode *c; xmlNode *c;
struct box *inline_container = 0;
po = talloc(content, struct object_params);
if (!po)
return false;
po->data = 0;
po->type = 0;
po->codetype = 0;
po->codebase = 0;
po->classid = 0;
po->params = 0;
po->basehref = 0;
if (!box_get_attribute(n, "data", content, &po->data))
return false;
if (!box_get_attribute(n, "usemap", content, &box->usemap)) if (!box_get_attribute(n, "usemap", content, &box->usemap))
return false; return false;
if (box->usemap && box->usemap[0] == '#') if (box->usemap && box->usemap[0] == '#')
box->usemap++; box->usemap++;
if (!box_get_attribute(n, "type", content, &po->type)) params = talloc(content, struct object_params);
return false; if (!params)
if (!box_get_attribute(n, "codetype", content, &po->codetype))
return false;
if (!box_get_attribute(n, "codebase", content, &po->codebase))
return false;
if (!box_get_attribute(n, "classid", content, &po->classid))
return false; return false;
params->data = 0;
params->type = 0;
params->codetype = 0;
params->codebase = 0;
params->classid = 0;
params->params = 0;
/* parameters /* codebase, classid, and data are URLs (codebase is the base for the
* parameter data is stored in a singly linked list. * other two) */
* po->params points to the head of the list. if ((codebase = xmlGetProp(n, (const xmlChar *) "codebase"))) {
* new parameters are added to the head of the list. if (!box_extract_link((char *) codebase,
*/ content->data.html.base_url, &params->codebase))
return false;
xmlFree(codebase);
}
if (!params->codebase)
params->codebase = content->data.html.base_url;
if ((classid = xmlGetProp(n, (const xmlChar *) "codebase"))) {
if (!box_extract_link((char *) classid, params->codebase,
&params->classid))
return false;
xmlFree(classid);
}
if ((data = xmlGetProp(n, (const xmlChar *) "data"))) {
if (!box_extract_link((char *) data, params->codebase,
&params->data))
return false;
xmlFree(data);
}
if (!params->data)
/* objects without data are ignored */
return true;
/* codetype and type are MIME types */
if (!box_get_attribute(n, "codetype", params, &params->codetype))
return false;
if (!box_get_attribute(n, "type", params, &params->type))
return false;
if (params->type && content_lookup(params->type) == CONTENT_OTHER)
/* can't handle this MIME type */
return true;
/* add parameters to linked list */
for (c = n->children; c; c = c->next) { for (c = n->children; c; c = c->next) {
if (c->type != XML_ELEMENT_NODE) if (c->type != XML_ELEMENT_NODE)
continue; continue;
if (strcmp((const char *) c->name, "param") != 0) if (strcmp((const char *) c->name, "param") != 0)
/* The first non-param child is the start /* The first non-param child is the start of the alt
* of the alt html. Therefore, we should * html. Therefore, we should break out of this loop. */
* break out of this loop.
*/
break; break;
pp = talloc(content, struct plugin_params); param = talloc(params, struct object_param);
if (!pp) if (!param)
return false; return false;
pp->name = 0; param->name = 0;
pp->value = 0; param->value = 0;
pp->type = 0; param->type = 0;
pp->valuetype = 0; param->valuetype = 0;
pp->next = 0; param->next = 0;
if (!box_get_attribute(c, "name", content, &pp->name)) if (!box_get_attribute(c, "name", param, &param->name))
return false; return false;
if (!box_get_attribute(c, "value", content, &pp->value)) if (!box_get_attribute(c, "value", param, &param->value))
return false; return false;
if (!box_get_attribute(c, "type", content, &pp->type)) if (!box_get_attribute(c, "type", param, &param->type))
return false; return false;
if (!box_get_attribute(c, "valuetype", content, &pp->valuetype)) if (!box_get_attribute(c, "valuetype", param,
return false; &param->valuetype))
if (!pp->valuetype) {
pp->valuetype = talloc_strdup(content, "data");
if (!pp->valuetype)
return false; return false;
if (!param->valuetype)
param->valuetype = "data";
param->next = params->params;
params->params = param;
} }
pp->next = po->params; box->object_params = params;
po->params = pp;
/* start fetch (MIME type is ok or not specified) */
if (!html_fetch_object(content, params->data, box, 0,
content->available_width, 1000, false))
return false;
/* convert children and place into fallback */
for (c = n->children; c; c = c->next) {
if (!convert_xml_to_box(c, content, box->style, box,
&inline_container, 0, 0))
return false;
} }
box->fallback = box->children;
box->children = box->last = 0;
box->object_params = po; *convert_children = false;
/* start fetch */
if (!plugin_decode(content, box))
*convert_children = true;
return true; return true;
} }
#if 0 #if 0 /**
/**
* "Java applet" [13.4]. * "Java applet" [13.4].
* *
* \todo This needs reworking to be compliant to the spec * \todo This needs reworking to be compliant to the spec
@ -1131,7 +1145,7 @@ struct box_result box_applet(xmlNode *n, struct box_status *status,
{ {
struct box *box; struct box *box;
struct object_params *po; struct object_params *po;
struct plugin_params *pp = NULL; struct object_param *pp = NULL;
char *s; char *s;
xmlNode *c; xmlNode *c;
@ -1183,7 +1197,7 @@ struct box_result box_applet(xmlNode *n, struct box_status *status,
continue; continue;
if (strcmp((const char *) c->name, "param") == 0) { if (strcmp((const char *) c->name, "param") == 0) {
pp = calloc(1, sizeof(struct plugin_params)); pp = calloc(1, sizeof(struct object_param));
if (!pp) if (!pp)
goto no_memory; goto no_memory;
@ -1459,34 +1473,23 @@ bool box_frameset(BOX_SPECIAL_PARAMS)
bool box_iframe(BOX_SPECIAL_PARAMS) bool box_iframe(BOX_SPECIAL_PARAMS)
{ {
struct object_params *po; bool ok;
char *s; char *url;
xmlChar *src;
po = talloc(content, struct object_params); /* get frame URL */
if (!po) if (!(src = xmlGetProp(n, (const xmlChar *) "src")))
return true;
if (!box_extract_link((char *) src, content->data.html.base_url, &url))
return false; return false;
po->data = 0; if (!url)
po->type = 0; return true;
po->codetype = 0;
po->codebase = 0;
po->classid = 0;
po->params = 0;
po->basehref = 0;
/* iframe src */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src"))) {
po->data = talloc_strdup(content, s);
xmlFree(s);
if (!po->data)
return false;
}
box->object_params = po;
/* start fetch */ /* start fetch */
plugin_decode(content, box); ok = html_fetch_object(content, url, box, 0,
content->available_width, 1000, false);
return true; free(url);
return ok;
} }
@ -2054,66 +2057,60 @@ bool box_textarea(BOX_SPECIAL_PARAMS)
bool box_embed(BOX_SPECIAL_PARAMS) bool box_embed(BOX_SPECIAL_PARAMS)
{ {
struct object_params *po; struct object_params *params;
struct plugin_params *pp = NULL; struct object_param *param;
char *s; xmlChar *src;
xmlAttr *a; xmlAttr *a;
po = talloc(content, struct object_params); params = talloc(content, struct object_params);
if (!po) if (!params)
return false; return false;
po->data = 0; params->data = 0;
po->type = 0; params->type = 0;
po->codetype = 0; params->codetype = 0;
po->codebase = 0; params->codebase = 0;
po->classid = 0; params->classid = 0;
po->params = 0; params->params = 0;
po->basehref = 0;
/* embed src */ /* src is a URL */
if ((s = (char *) xmlGetProp(n, (const xmlChar *) "src")) != NULL) { if (!(src = xmlGetProp(n, (const xmlChar *) "src")))
LOG(("embed '%s'", s)); return true;
po->data = talloc_strdup(content, s); if (!box_extract_link((char *) src, content->data.html.base_url,
xmlFree(s); &params->data))
if (!po->data)
return false; return false;
} xmlFree(src);
if (!params->data)
return true;
/** /* add attributes as parameters to linked list */
* we munge all other attributes into a plugin_parameter structure
*/
for (a = n->properties; a; a = a->next) { for (a = n->properties; a; a = a->next) {
pp = talloc(content, struct plugin_params); if (strcasecmp((const char *) a->name, "src") == 0)
if (!pp) continue;
return false; if (!a->children || !a->children->content)
pp->name = 0; continue;
pp->value = 0;
pp->type = 0;
pp->valuetype = 0;
pp->next = 0;
if (strcasecmp((const char *) a->name, "src") != 0 && param = talloc(content, struct object_param);
a->children && a->children->content) { if (!param)
pp->name = talloc_strdup(content, return false;
(const char *) a->name); param->name = talloc_strdup(content, (const char *) a->name);
pp->value = talloc_strdup(content, param->value = talloc_strdup(content,
(char *) a->children->content); (char *) a->children->content);
pp->valuetype = talloc_strdup(content, "data"); param->type = 0;
if (!pp->name || !pp->value || !pp->valuetype) param->valuetype = "data";
param->next = 0;
if (!param->name || !param->value)
return false; return false;
pp->next = po->params; param->next = params->params;
po->params = pp; params->params = param;
}
} }
box->object_params = po; box->object_params = params;
/* start fetch */ /* start fetch */
/* embeds have no content, so we don't care if this returns false */ return html_fetch_object(content, params->data, box, 0,
plugin_decode(content, box); content->available_width, 1000, false);
return true;
} }
/** /**
@ -2121,153 +2118,6 @@ bool box_embed(BOX_SPECIAL_PARAMS)
*/ */
/**
* plugin_decode
* This function checks that the contents of the plugin_object struct
* are valid. If they are, it initiates the fetch process. If they are
* not, it exits, leaving the box structure as it was on entry. This is
* necessary as there are multiple ways of declaring an object's attributes.
*
* Returns false if the object could not be handled.
*/
bool plugin_decode(struct content *content, struct box *box)
{
char *codebase, *url = NULL;
struct object_params *po;
struct plugin_params *pp;
url_func_result res;
assert(content && box);
po = box->object_params;
/* Check if the codebase attribute is defined.
* If it is not, set it to the codebase of the current document.
*/
if (po->codebase == 0)
res = url_join("./", content->data.html.base_url,
&codebase);
else
res = url_join(po->codebase, content->data.html.base_url,
&codebase);
if (res != URL_FUNC_OK)
return false;
/* free pre-existing codebase */
if (po->codebase)
talloc_free(po->codebase);
po->codebase = talloc_strdup(content, codebase);
if (!po->codebase) {
free(codebase);
return false;
}
/* no longer need this */
free(codebase);
/* Set basehref */
po->basehref = talloc_strdup(content, content->data.html.base_url);
if (!po->basehref)
return false;
if (po->data == 0 && po->classid == 0)
/* no data => ignore this object */
return false;
if (po->data == 0 && po->classid != 0) {
/* just classid specified */
if (strncasecmp(po->classid, "clsid:", 6) == 0) {
if (strcasecmp(po->classid, "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000") == 0) {
/* Flash */
for (pp = po->params;
pp != 0 &&
strcasecmp(pp->name, "movie") != 0;
pp = pp->next)
/* no body */;
if (pp == 0)
return false;
res = url_join(pp->value, po->basehref, &url);
if (res != URL_FUNC_OK)
return false;
/* munge the codebase */
res = url_join("./",
content->data.html.base_url,
&codebase);
if (res != URL_FUNC_OK) {
free(url);
return false;
}
if (po->codebase)
talloc_free(po->codebase);
po->codebase = talloc_strdup(content,
codebase);
free(codebase);
if (!po->codebase) {
free(url);
return false;
}
}
else {
LOG(("ActiveX object"));
return false;
}
} else {
res = url_join(po->classid, po->codebase, &url);
if (res != URL_FUNC_OK)
return false;
#if 0
/* jmb - I'm not convinced by this */
/* The java plugin doesn't need the .class extension
* so we strip it.
*/
if (strcasecmp(&po->classid[strlen(po->classid)-6],
".class") == 0)
po->classid[strlen(po->classid)-6] = 0;
#endif
}
} else {
/* just data (or both) specified - data takes precedence */
res = url_join(po->data, po->codebase, &url);
if (res != URL_FUNC_OK)
return false;
}
/* Check if the declared mime type is understandable.
* Checks type and codetype attributes.
*/
if (po->type != 0 && content_lookup(po->type) == CONTENT_OTHER)
goto no_handler;
if (po->codetype != 0 &&
content_lookup(po->codetype) == CONTENT_OTHER)
goto no_handler;
/* Ensure that the object to be included isn't this document */
if (strcasecmp(url, content->data.html.base_url) == 0)
goto no_handler;
/* If we've got to here, the object declaration has provided us with
* enough data to enable us to have a go at downloading and
* displaying it.
*
* We may still find that the object has a MIME type that we can't
* handle when we fetch it (if the type was not specified or is
* different to that given in the attributes).
*/
if (!html_fetch_object(content, url, box, 0, 1000, 1000, false))
goto no_handler;
free(url);
return true;
no_handler:
free(url);
return false;
}
/** /**
* Get the value of an XML element's attribute. * Get the value of an XML element's attribute.
* *

View File

@ -45,6 +45,8 @@ static void html_object_callback(content_msg msg, struct content *object,
void *p1, void *p2, union content_msg_data data); void *p1, void *p2, union content_msg_data data);
static void html_object_done(struct box *box, struct content *object, static void html_object_done(struct box *box, struct content *object,
bool background); 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, static bool html_object_type_permitted(const content_type type,
const content_type *permitted_types); 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_add_error(c, "?", 0);
content_set_status(c, messages_get("BadObject")); content_set_status(c, messages_get("BadObject"));
content_broadcast(c, CONTENT_MSG_STATUS, data); 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; break;
case CONTENT_MSG_READY: case CONTENT_MSG_READY:
@ -815,7 +820,8 @@ void html_object_callback(content_msg msg, struct content *object,
break; break;
case CONTENT_MSG_DONE: 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--; c->active--;
break; break;
@ -826,6 +832,8 @@ void html_object_callback(content_msg msg, struct content *object,
content_set_status(c, messages_get("ObjError"), content_set_status(c, messages_get("ObjError"),
data.error); data.error);
content_broadcast(c, CONTENT_MSG_STATUS, data); content_broadcast(c, CONTENT_MSG_STATUS, data);
html_object_failed(box, c,
c->data.html.object[i].background);
break; break;
case CONTENT_MSG_STATUS: case CONTENT_MSG_STATUS:
@ -951,6 +959,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. * Check if a type is in a list.
* *

View File

@ -90,7 +90,7 @@ static void plugin_stream_write_callback(void *p);
static void plugin_write_stream_as_file(struct content *c); static void plugin_write_stream_as_file(struct content *c);
static void plugin_destroy_stream(struct content *c); static void plugin_destroy_stream(struct content *c);
static bool plugin_write_parameters_file(struct content *c, static bool plugin_write_parameters_file(struct content *c,
struct object_params *params); struct object_params *params, const char *base);
static int plugin_calculate_rsize(const char* name, const char* data, static int plugin_calculate_rsize(const char* name, const char* data,
const char* mime); const char* mime);
static bool plugin_add_item_to_pilist(struct plugin_param_item **pilist, static bool plugin_add_item_to_pilist(struct plugin_param_item **pilist,
@ -207,13 +207,13 @@ void plugin_open(struct content *c, struct browser_window *bw,
struct object_params *params) struct object_params *params)
{ {
bool standalone = false; bool standalone = false;
const char *base;
char sysvar[25]; char sysvar[25];
char *varval; char *varval;
plugin_full_message_open pmo; plugin_full_message_open pmo;
wimp_window_state state; wimp_window_state state;
os_error *error; os_error *error;
if (option_no_plugins) if (option_no_plugins)
return; return;
@ -235,11 +235,6 @@ void plugin_open(struct content *c, struct browser_window *bw,
warn_user("NoMemory", 0); warn_user("NoMemory", 0);
goto error; goto error;
} }
params->basehref = strdup(c->url);
if (!params->basehref) {
warn_user("NoMemory", 0);
goto error;
}
standalone = true; standalone = true;
} }
@ -249,8 +244,15 @@ void plugin_open(struct content *c, struct browser_window *bw,
*/ */
c->data.plugin.box = box; c->data.plugin.box = box;
if (params->codebase)
base = params->codebase;
else if (page)
base = page->data.html.base_url;
else
base = c->url;
LOG(("writing parameters file")); LOG(("writing parameters file"));
if (!plugin_write_parameters_file(c, params)) if (!plugin_write_parameters_file(c, params, base))
goto error; goto error;
LOG(("creating sysvar")); LOG(("creating sysvar"));
@ -325,7 +327,6 @@ error:
if (standalone) { if (standalone) {
free(params->type); free(params->type);
free(params->data); free(params->data);
free(params->basehref);
free(params); free(params);
} }
@ -1071,12 +1072,13 @@ void plugin_destroy_stream(struct content *c)
* *
* \param c Content to write parameters for * \param c Content to write parameters for
* \param params Plugin parameters struct * \param params Plugin parameters struct
* \param base base URL for object
* \return true on success, false otherwise * \return true on success, false otherwise
*/ */
bool plugin_write_parameters_file(struct content *c, bool plugin_write_parameters_file(struct content *c,
struct object_params *params) struct object_params *params, const char *base)
{ {
struct plugin_params *p; struct object_param *p;
struct plugin_param_item *ppi; struct plugin_param_item *ppi;
struct plugin_param_item *pilist = 0; struct plugin_param_item *pilist = 0;
char bgcolor[10] = {0}; char bgcolor[10] = {0};
@ -1163,8 +1165,7 @@ bool plugin_write_parameters_file(struct content *c,
/* BASEHREF */ /* BASEHREF */
if (!plugin_add_item_to_pilist(&pilist, PLUGIN_PARAMETER_SPECIAL, if (!plugin_add_item_to_pilist(&pilist, PLUGIN_PARAMETER_SPECIAL,
"BASEHREF", "BASEHREF", base,
(const char *)params->basehref,
NULL)) NULL))
goto error; goto error;